feat(ai-tools): install/update AI CLIs, remote catalog sync, cached favicons (#40 A2)

This commit is contained in:
2026-09-29 08:25:37 +07:00
parent fcfebe44f1
commit 7ec5a7cd85
40 changed files with 3145 additions and 92 deletions
+251
View File
@@ -4114,6 +4114,7 @@ components:
type: string
enum:
- builtin
- remote
- custom
launcher:
type: string
@@ -4141,6 +4142,69 @@ components:
routerCapable:
type: boolean
description: Can use an AI Router profile
install:
type: object
nullable: true
description: 'How Install runs: npm install -g <package>@latest, or a vendor script'
properties:
kind:
type: string
enum:
- npm
- script
package:
type: string
example: '@openai/codex'
url:
type: string
example: https://cursor.com/install
update:
type: object
nullable: true
properties:
kind:
type: string
enum:
- npm
- script
- self
args:
type: array
items:
type: string
description: self only
AiToolsJob:
type: object
properties:
id:
type: integer
tool:
type: string
nullable: true
description: null for update-all
action:
type: string
enum:
- install
- update
- update-all
status:
type: string
enum:
- running
- ok
- failed
startedAt:
type: string
endedAt:
type: string
nullable: true
exitCode:
type: integer
nullable: true
log:
type: string
description: stdout+stderr, last 256 KB
AiToolsView:
type: object
required:
@@ -4155,6 +4219,20 @@ components:
type: string
nullable: true
description: Effective default tool id
catalog:
type: object
properties:
source:
type: string
enum:
- builtin
- remote
tag:
type: string
nullable: true
fetchedAt:
type: string
nullable: true
AiToolsError:
type: object
properties:
@@ -11602,6 +11680,179 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
/api/ai-tools/{id}/install:
post:
tags:
- AI Tools
summary: Install a tool
description: Runs the catalog's install (npm install -g <package>@latest with the login shell's npm, or the vendor script downloaded by the server and run with bash). One job at a time. Same-origin only.
operationId: aiToolsInstall
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'202':
description: The job started; poll GET /api/ai-tools/job
content:
application/json:
schema:
type: object
properties:
job:
$ref: '#/components/schemas/AiToolsJob'
'400':
description: ENOINSTALL
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
'404':
description: ENOTOOL
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
'409':
description: EINSTALLED, ENONPM or EBUSY
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
/api/ai-tools/{id}/update:
post:
tags:
- AI Tools
summary: Update a tool
description: npm update only for a tool whose binary lives under npm's global prefix (else ENOTNPM); a self updater runs the tool's own command. Same-origin only.
operationId: aiToolsUpdateTool
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'202':
description: The job started; poll GET /api/ai-tools/job
content:
application/json:
schema:
type: object
properties:
job:
$ref: '#/components/schemas/AiToolsJob'
'400':
description: ENOUPDATE
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
'404':
description: ENOTOOL
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
'409':
description: ENOTINSTALLED, ENOTNPM, ENONPM or EBUSY
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
/api/ai-tools/update-all:
post:
tags:
- AI Tools
summary: Update every tool with an update
description: 'One job: every npm-managed tool with a newer version, then every installed self updater. Same-origin only.'
operationId: aiToolsUpdateAll
responses:
'202':
description: The job started; poll GET /api/ai-tools/job
content:
application/json:
schema:
type: object
properties:
job:
$ref: '#/components/schemas/AiToolsJob'
'400':
description: ENOTHING
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
'409':
description: EBUSY
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsError'
/api/ai-tools/job:
get:
tags:
- AI Tools
summary: The current or last install/update job
operationId: aiToolsJob
responses:
'200':
description: The job, or null
content:
application/json:
schema:
$ref: '#/components/schemas/AiToolsJob'
/api/ai-tools/versions:
get:
tags:
- AI Tools
summary: npm version badges
description: 'For installed tools with an npm update: whether npm manages them, the installed and latest version, and updateAvailable. Cached 24 h.'
operationId: aiToolsVersions
responses:
'200':
description: Map of tool id to its versions
content:
application/json:
schema:
type: object
additionalProperties:
type: object
properties:
npmManaged:
type: boolean
installed:
type: string
nullable: true
latest:
type: string
nullable: true
updateAvailable:
type: boolean
/api/ai-tools/{id}/icon:
get:
tags:
- AI Tools
summary: A tool's icon
description: The favicon of the tool's faviconDomain (or homepage host), fetched once by the server and cached. Raster only, never SVG; served with nosniff and CSP sandbox.
operationId: aiToolsIcon
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: The image
content:
image/*: {}
'204':
description: No icon (the client shows a letter avatar)
'404':
description: Unknown tool id
/api/sessions/facets:
get:
tags: