Spaces:
Sleeping
Sleeping
File size: 8,529 Bytes
fd0a8b6 5b5da0e cae0460 5017021 744d9e5 5017021 fd0a8b6 cae0460 fd0a8b6 5b5da0e bd25310 5b5da0e 94ef8c1 40f8c9b ad23973 b60e122 585ab8a b60e122 e9256c1 5b5da0e 6d51a81 5b5da0e e34ce4a 5b5da0e 7d9aec4 8e5d9a0 7d9aec4 a3d2eef a9cda9b 7d9aec4 7c91582 8e5d9a0 7d9aec4 e34ce4a 7d9aec4 9c5792a 604c3c1 37775da 604c3c1 5b5da0e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | import type { Cli, Group, MoveTarget, Session, Tree } from './types';
const HEADERS = { 'content-type': 'application/json' };
const json = (r: Response) => {
if (!r.ok) throw new Error(`${r.status}`);
return r.json();
};
export const getClis = (): Promise<Cli[]> => fetch('/api/clis').then(json);
export const getTree = (): Promise<Tree> => fetch('/api/tree').then(json);
// path: '.' = the workspaces root; anything else is a workspace-relative dir.
const normalizePath = (path?: string) => (path && path.trim() ? path : '.');
// Quickstart: create at the workspaces root, boot the CLI, and type the prompt
// as soon as it's up — all server-side, no waiting in the UI.
export const quickStart = (cli: string, prompt: string, name = '', path = '.'): Promise<Session> =>
fetch('/api/sessions', { method: 'POST', headers: HEADERS, body: JSON.stringify({ cli, name: name || undefined, path: path || '.', prompt: prompt || undefined }) }).then(json);
export const createSession = (name: string, cli: string, groupId?: string, path?: string): Promise<Session> =>
fetch('/api/sessions', { method: 'POST', headers: HEADERS, body: JSON.stringify({ name, cli, groupId, path: normalizePath(path) }) }).then(json);
export const listFolders = (p = ''): Promise<{ path: string; folders: string[] }> =>
fetch(`/api/folders?path=${encodeURIComponent(p)}`).then(json);
export const stopSession = (id: string) =>
fetch(`/api/sessions/${id}/stop`, { method: 'POST' }).then(json);
export const deleteSession = (id: string) =>
fetch(`/api/sessions/${id}`, { method: 'DELETE' }).then(json);
export const renameSession = (id: string, name: string) =>
fetch(`/api/sessions/${id}`, { method: 'PUT', headers: HEADERS, body: JSON.stringify({ name }) }).then(json);
export const createGroup = (name: string): Promise<Group> =>
fetch('/api/groups', { method: 'POST', headers: HEADERS, body: JSON.stringify({ name }) }).then(json);
export const renameGroup = (id: string, name: string) =>
fetch(`/api/groups/${id}`, { method: 'PUT', headers: HEADERS, body: JSON.stringify({ name }) }).then(json);
// Generic group patch: pane order (sessionIds) and/or tile layout (null = auto).
export const updateGroup = (id: string, patch: { sessionIds?: string[]; layout?: { cols: number; rows: number } | null }) =>
fetch(`/api/groups/${id}`, { method: 'PUT', headers: HEADERS, body: JSON.stringify(patch) }).then(json);
export const deleteGroup = (id: string) =>
fetch(`/api/groups/${id}`, { method: 'DELETE' }).then(json);
export const move = (ref: string, to: MoveTarget) =>
fetch('/api/move', { method: 'POST', headers: HEADERS, body: JSON.stringify({ ref, to }) }).then(json);
export const getInfo = () => fetch('/api/info').then(json);
export const dismissWelcome = () => fetch('/api/welcome/seen', { method: 'POST' }).then(json);
export const setDemo = (active: boolean): Promise<{ ok: boolean; active: boolean }> =>
fetch('/api/demo', { method: 'POST', headers: HEADERS, body: JSON.stringify({ active }) }).then(json);
export const relaunchSpace = (): Promise<{ ok: boolean; reason?: string }> =>
fetch('/api/relaunch', { method: 'POST' }).then(json);
export interface AmConfig {
artifacts: { enabled: boolean; space: string; visibility: 'public' | 'private' };
jobs: { askAboveUsd: number };
archive: { after: 'week' | 'month' | 'never' };
defaultArtifactsSpace?: string;
}
export const getConfig = (): Promise<AmConfig> => fetch('/api/config').then(json);
export const saveConfig = (c: AmConfig) =>
fetch('/api/config', { method: 'PUT', headers: HEADERS, body: JSON.stringify(c) }).then(json);
export interface SecretsData { detected: string[]; notes: Record<string, string>; }
export const getSecrets = (): Promise<SecretsData> => fetch('/api/secrets').then(json);
export const saveSecrets = (notes: Record<string, string>) =>
fetch('/api/secrets', { method: 'PUT', headers: HEADERS, body: JSON.stringify({ notes }) }).then(json);
export interface QuotaWindow { usedPercent?: number; resetsAt?: number; windowMinutes?: number; }
export interface ProviderUsage {
tokensToday?: number; costToday?: number; tokensWeek?: number; costWeek?: number; totalCost?: number;
quota?: { fiveHour?: QuotaWindow; weekly?: QuotaWindow; opus?: QuotaWindow; updatedAt?: number; source?: 'live' | 'snapshot' } | null;
}
export interface Usage { providers: Record<string, ProviderUsage>; generatedAt: string; }
export const getUsage = (provider?: string): Promise<Usage> => fetch(provider ? `/api/usage?provider=${provider}` : '/api/usage').then(json);
// ---- overview (meta) ----
export interface TurnEntry { answer: string; answerMd: string; ts: number; }
export interface MetaDigest {
lastPromptText: string; lastPromptRaw?: string; lastPromptTs: number;
lastAssistantText: string; lastAssistantMd: string; lastAssistantTs: number;
sinceTurns: number; sinceToolCalls: number; sinceTools: Record<string, number>; sinceFiles: string[];
sinceTokens: number;
running?: boolean; // task in flight (codex task_started/task_complete)
turnsLog?: TurnEntry[]; // newest-first history of completed exchanges
}
export interface MetaSession extends Session { digest: MetaDigest | null }
export const getMeta = (): Promise<{ sessions: MetaSession[]; generatedAt: string }> =>
fetch('/api/meta').then(json);
// Targeted digest for one session (progressive tile fill); digest is null when
// this CLI only resolves through the bulk pass.
export const getMetaOne = (id: string): Promise<{ id: string; digest: MetaDigest | null }> =>
fetch(`/api/meta/${id}`).then(json);
export const sendInput = (id: string, text: string): Promise<{ ok: boolean; started?: boolean }> =>
fetch(`/api/sessions/${id}/input`, { method: 'POST', headers: HEADERS, body: JSON.stringify({ text }) }).then(json);
// ---- push notifications ----
export const getPushKey = (): Promise<{ publicKey: string; devices: number }> =>
fetch('/api/push/key').then(json);
export const subscribePush = (subscription: PushSubscription) =>
fetch('/api/push/subscribe', { method: 'POST', headers: HEADERS, body: JSON.stringify({ subscription }) }).then(json);
export const unsubscribePush = (endpoint: string) =>
fetch('/api/push/unsubscribe', { method: 'POST', headers: HEADERS, body: JSON.stringify({ endpoint }) }).then(json);
export const sendTestNotification = (): Promise<{ ok: boolean; sent: number; devices: number }> =>
fetch('/api/notify', { method: 'POST', headers: HEADERS, body: JSON.stringify({ title: 'Agent Manager', body: 'Test notification — agents can reach this device.' }) }).then(json);
// ---- trace analytics ----
export interface TraceStats {
turns: number; prompts: number; toolCalls: number; tools: Record<string, number>;
web: number; tokensIn: number; tokensOut: number; cacheRead: number;
firstTs: number; lastTs: number; files: number;
}
export interface SessionTraces extends TraceStats { id: string; name: string; cli: string; path: string | null; }
export interface Traces { sessions: SessionTraces[]; totals: TraceStats; generatedAt: string; }
export const getTraces = (): Promise<Traces> => fetch('/api/traces').then(json);
// ---- files ----
export interface FileEntry { name: string; dir: boolean; size: number; }
export interface FileListing { path: string; root: string; entries: FileEntry[]; }
export const listFiles = (id: string, p = ''): Promise<FileListing> =>
fetch(`/api/files/${id}?path=${encodeURIComponent(p)}`).then(json);
export const uploadFile = (id: string, p: string, file: File) =>
fetch(`/api/files/${id}/upload?path=${encodeURIComponent(p)}&name=${encodeURIComponent(file.name)}`, {
method: 'POST', headers: { 'content-type': 'application/octet-stream' }, body: file,
}).then(json);
export const downloadUrl = (id: string, p: string) =>
`/api/files/${id}/download?path=${encodeURIComponent(p)}`;
// ---- skills ----
export interface SkillFile { name: string; size: number; }
export const listSkills = (): Promise<SkillFile[]> => fetch('/api/skills').then(json);
export const getSkill = (name: string): Promise<{ name: string; content: string }> =>
fetch(`/api/skills/${encodeURIComponent(name)}`).then(json);
export const saveSkill = (name: string, content: string) =>
fetch(`/api/skills/${encodeURIComponent(name)}`, { method: 'PUT', headers: { 'content-type': 'text/plain' }, body: content }).then(json);
export const deleteSkill = (name: string) =>
fetch(`/api/skills/${encodeURIComponent(name)}`, { method: 'DELETE' }).then(json);
|