feat(ai-tools): install/update AI CLIs, remote catalog sync, cached favicons (#40 A2)
This commit is contained in:
+51
-1
@@ -1950,6 +1950,28 @@ export const api = {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
/** POST /api/ai-tools/:id/install - start the catalog's install job. */
|
||||
install: (id: string) =>
|
||||
request<{ job: AiToolJob }>(`/ai-tools/${encodeURIComponent(id)}/install`, {
|
||||
method: "POST",
|
||||
}),
|
||||
/** POST /api/ai-tools/:id/update - start the catalog's update job. */
|
||||
updateTool: (id: string) =>
|
||||
request<{ job: AiToolJob }>(`/ai-tools/${encodeURIComponent(id)}/update`, {
|
||||
method: "POST",
|
||||
}),
|
||||
/** POST /api/ai-tools/update-all - one job updating every tool with an update. */
|
||||
updateAll: () => request<{ job: AiToolJob }>("/ai-tools/update-all", { method: "POST" }),
|
||||
/** GET /api/ai-tools/job - the current or last job, or null. */
|
||||
job: () => request<AiToolJob | null>("/ai-tools/job"),
|
||||
/** GET /api/ai-tools/versions - npm version badges, cached a day server-side. */
|
||||
versions: () => request<Record<string, AiToolVersion>>("/ai-tools/versions"),
|
||||
/** The server-cached icon; an <img> cannot send the bearer header, so the token rides the query. */
|
||||
iconUrl: (id: string) => {
|
||||
const token = dashboardToken();
|
||||
const q = token ? `?token=${encodeURIComponent(token)}` : "";
|
||||
return `${BASE}/ai-tools/${encodeURIComponent(id)}/icon${q}`;
|
||||
},
|
||||
},
|
||||
aiRouters: {
|
||||
/** GET /api/ai-routers - every profile, the built-in `native` one first. */
|
||||
@@ -2985,7 +3007,7 @@ export interface AiTool {
|
||||
installed: boolean;
|
||||
path: string | null;
|
||||
enabled: boolean;
|
||||
source: "builtin" | "custom";
|
||||
source: "builtin" | "remote" | "custom";
|
||||
/** `claude` / `codex` keep their own run form; null for every other tool. */
|
||||
launcher: "claude" | "codex" | null;
|
||||
prompt: { mode: "argv" | "flag" | "after-start" } | null;
|
||||
@@ -2995,12 +3017,40 @@ export interface AiTool {
|
||||
bypass: boolean;
|
||||
/** Can use an AI Router profile (Claude, Codex); others are native only. */
|
||||
routerCapable: boolean;
|
||||
/** What Install runs; null when the catalog names no install. */
|
||||
install: { kind: "npm"; package: string } | { kind: "script"; url: string } | null;
|
||||
/** What Update runs; `self` is the tool's own updater with these args. */
|
||||
update: { kind: "npm" } | { kind: "script" } | { kind: "self"; args: string[] } | null;
|
||||
}
|
||||
|
||||
export interface AiToolsView {
|
||||
tools: AiTool[];
|
||||
/** The effective default tool id, or null when nothing is installed and enabled. */
|
||||
default: string | null;
|
||||
/** Where the catalog came from: this build, or the newer release synced daily. */
|
||||
catalog?: { source: "builtin" | "remote"; tag: string | null; fetchedAt: string | null };
|
||||
}
|
||||
|
||||
/** An install/update job (GET /api/ai-tools/job). */
|
||||
export interface AiToolJob {
|
||||
id: number;
|
||||
/** null for update-all. */
|
||||
tool: string | null;
|
||||
action: "install" | "update" | "update-all";
|
||||
status: "running" | "ok" | "failed";
|
||||
startedAt: string;
|
||||
endedAt: string | null;
|
||||
exitCode: number | null;
|
||||
log: string;
|
||||
}
|
||||
|
||||
/** One row of GET /api/ai-tools/versions. */
|
||||
export interface AiToolVersion {
|
||||
/** Its binary lives under npm's global prefix, so an npm update replaces it. */
|
||||
npmManaged: boolean;
|
||||
installed: string | null;
|
||||
latest: string | null;
|
||||
updateAvailable: boolean;
|
||||
}
|
||||
|
||||
export interface AiRouter {
|
||||
|
||||
Reference in New Issue
Block a user