@cloudcli-ai/cloudcli 1.31.5 → 1.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.ru.md +1 -1
- package/README.tr.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/api-docs.html +6 -7
- package/dist/assets/index-MOIvpy53.css +32 -0
- package/dist/assets/{index-DqMVUeZS.js → index-skXSjBje.js} +290 -270
- package/dist/index.html +2 -2
- package/dist/modelConstants.js +841 -0
- package/dist-server/server/claude-sdk.js +67 -39
- package/dist-server/server/claude-sdk.js.map +1 -1
- package/dist-server/server/cursor-cli.js +6 -9
- package/dist-server/server/cursor-cli.js.map +1 -1
- package/dist-server/server/gemini-cli.js +163 -35
- package/dist-server/server/gemini-cli.js.map +1 -1
- package/dist-server/server/gemini-response-handler.js +34 -0
- package/dist-server/server/gemini-response-handler.js.map +1 -1
- package/dist-server/server/index.js +131 -19
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/database/index.js +1 -0
- package/dist-server/server/modules/database/index.js.map +1 -1
- package/dist-server/server/modules/database/migrations.js +11 -0
- package/dist-server/server/modules/database/migrations.js.map +1 -1
- package/dist-server/server/modules/database/repositories/projects.db.js +12 -0
- package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -1
- package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js +61 -0
- package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js.map +1 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js +49 -8
- package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
- package/dist-server/server/modules/database/schema.js +1 -0
- package/dist-server/server/modules/database/schema.js.map +1 -1
- package/dist-server/server/modules/projects/projects.routes.js +12 -3
- package/dist-server/server/modules/projects/projects.routes.js.map +1 -1
- package/dist-server/server/modules/projects/services/project-delete.service.js +14 -1
- package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -1
- package/dist-server/server/modules/projects/services/project-management.service.js +1 -0
- package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -1
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +47 -0
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -1
- package/dist-server/server/modules/providers/index.js +1 -0
- package/dist-server/server/modules/providers/index.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +27 -7
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +141 -0
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +55 -2
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +153 -14
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +198 -0
- package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js +4 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +84 -0
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +54 -2
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +21 -6
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +50 -0
- package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex.provider.js +4 -0
- package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +754 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +8 -30
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +187 -24
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js +28 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +4 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js +125 -2
- package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js +27 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js +24 -8
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +10 -10
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js +33 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +4 -0
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js +92 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-mcp.provider.js +181 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-mcp.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +267 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +115 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +410 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-skills.provider.js +62 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode.provider.js +19 -0
- package/dist-server/server/modules/providers/list/opencode/opencode.provider.js.map +1 -0
- package/dist-server/server/modules/providers/provider.registry.js +2 -0
- package/dist-server/server/modules/providers/provider.registry.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +65 -3
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/modules/providers/services/mcp.service.js +1 -9
- package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-models.service.js +199 -0
- package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js +129 -13
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js +1 -0
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js +13 -4
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions.service.js +81 -7
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/skills.service.js +11 -0
- package/dist-server/server/modules/providers/services/skills.service.js.map +1 -0
- package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -1
- package/dist-server/server/modules/providers/shared/skills/skills.provider.js +45 -0
- package/dist-server/server/modules/providers/shared/skills/skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/tests/mcp.test.js +73 -6
- package/dist-server/server/modules/providers/tests/mcp.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-models.test.js +66 -0
- package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +262 -0
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js +270 -0
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/skills.test.js +259 -0
- package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -0
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +12 -1
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js +4 -4
- package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js +9 -1
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
- package/dist-server/server/openai-codex.js +87 -29
- package/dist-server/server/openai-codex.js.map +1 -1
- package/dist-server/server/opencode-cli.js +287 -0
- package/dist-server/server/opencode-cli.js.map +1 -0
- package/dist-server/server/opencode-cli.test.js +84 -0
- package/dist-server/server/opencode-cli.test.js.map +1 -0
- package/dist-server/server/routes/agent.js +21 -8
- package/dist-server/server/routes/agent.js.map +1 -1
- package/dist-server/server/routes/commands.js +204 -211
- package/dist-server/server/routes/commands.js.map +1 -1
- package/dist-server/server/routes/cursor.js +2 -2
- package/dist-server/server/routes/cursor.js.map +1 -1
- package/dist-server/server/routes/settings.js +0 -10
- package/dist-server/server/routes/settings.js.map +1 -1
- package/dist-server/server/routes/tests/commands.test.js +76 -0
- package/dist-server/server/routes/tests/commands.test.js.map +1 -0
- package/dist-server/server/shared/claude-cli-path.js +103 -0
- package/dist-server/server/shared/claude-cli-path.js.map +1 -0
- package/dist-server/server/shared/claude-cli-path.test.js +45 -0
- package/dist-server/server/shared/claude-cli-path.test.js.map +1 -0
- package/dist-server/server/{utils → shared}/frontmatter.js +3 -3
- package/dist-server/server/shared/frontmatter.js.map +1 -0
- package/dist-server/server/shared/utils.js +368 -0
- package/dist-server/server/shared/utils.js.map +1 -1
- package/dist-server/server/utils/commandParser.js +3 -3
- package/dist-server/server/utils/commandParser.js.map +1 -1
- package/package.json +3 -1
- package/public/api-docs.html +878 -0
- package/public/modelConstants.js +841 -0
- package/server/claude-sdk.js +74 -40
- package/server/cursor-cli.js +6 -11
- package/server/gemini-cli.js +197 -43
- package/server/gemini-response-handler.js +38 -0
- package/server/index.js +144 -19
- package/server/modules/database/index.ts +1 -0
- package/server/modules/database/migrations.ts +12 -0
- package/server/modules/database/repositories/projects.db.ts +13 -0
- package/server/modules/database/repositories/sessions.db.integration.test.ts +72 -0
- package/server/modules/database/repositories/sessions.db.ts +60 -9
- package/server/modules/database/schema.ts +1 -0
- package/server/modules/projects/projects.routes.ts +20 -3
- package/server/modules/projects/services/project-delete.service.ts +16 -1
- package/server/modules/projects/services/project-management.service.ts +2 -0
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +71 -1
- package/server/modules/providers/README.md +354 -0
- package/server/modules/providers/index.ts +2 -1
- package/server/modules/providers/list/claude/claude-auth.provider.ts +38 -13
- package/server/modules/providers/list/claude/claude-models.provider.ts +191 -0
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +68 -2
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +175 -14
- package/server/modules/providers/list/claude/claude-skills.provider.ts +257 -0
- package/server/modules/providers/list/claude/claude.provider.ts +11 -1
- package/server/modules/providers/list/codex/codex-models.provider.ts +125 -0
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +62 -2
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +25 -6
- package/server/modules/providers/list/codex/codex-skills.provider.ts +60 -0
- package/server/modules/providers/list/codex/codex.provider.ts +11 -1
- package/server/modules/providers/list/cursor/cursor-models.provider.ts +820 -0
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +17 -40
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +216 -26
- package/server/modules/providers/list/cursor/cursor-skills.provider.ts +31 -0
- package/server/modules/providers/list/cursor/cursor.provider.ts +11 -1
- package/server/modules/providers/list/gemini/gemini-auth.provider.ts +158 -2
- package/server/modules/providers/list/gemini/gemini-models.provider.ts +42 -0
- package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +24 -20
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +10 -11
- package/server/modules/providers/list/gemini/gemini-skills.provider.ts +36 -0
- package/server/modules/providers/list/gemini/gemini.provider.ts +11 -1
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +111 -0
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +228 -0
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +339 -0
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +157 -0
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +506 -0
- package/server/modules/providers/list/opencode/opencode-skills.provider.ts +78 -0
- package/server/modules/providers/list/opencode/opencode.provider.ts +27 -0
- package/server/modules/providers/provider.registry.ts +2 -0
- package/server/modules/providers/provider.routes.ts +97 -4
- package/server/modules/providers/services/mcp.service.ts +1 -12
- package/server/modules/providers/services/provider-models.service.ts +325 -0
- package/server/modules/providers/services/session-conversations-search.service.ts +162 -13
- package/server/modules/providers/services/session-synchronizer.service.ts +1 -0
- package/server/modules/providers/services/sessions-watcher.service.ts +14 -4
- package/server/modules/providers/services/sessions.service.ts +112 -9
- package/server/modules/providers/services/skills.service.ts +15 -0
- package/server/modules/providers/shared/base/abstract.provider.ts +4 -0
- package/server/modules/providers/shared/skills/skills.provider.ts +64 -0
- package/server/modules/providers/tests/mcp.test.ts +93 -6
- package/server/modules/providers/tests/opencode-models.test.ts +73 -0
- package/server/modules/providers/tests/opencode-sessions.test.ts +334 -0
- package/server/modules/providers/tests/provider-models.service.test.ts +318 -0
- package/server/modules/providers/tests/skills.test.ts +512 -0
- package/server/modules/websocket/services/chat-websocket.service.ts +15 -1
- package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +4 -4
- package/server/modules/websocket/services/shell-websocket.service.ts +9 -0
- package/server/openai-codex.js +99 -30
- package/server/opencode-cli.js +336 -0
- package/server/opencode-cli.test.js +95 -0
- package/server/routes/agent.js +22 -8
- package/server/routes/commands.js +256 -233
- package/server/routes/cursor.js +2 -2
- package/server/routes/settings.js +1 -10
- package/server/routes/tests/commands.test.js +82 -0
- package/server/shared/claude-cli-path.test.ts +61 -0
- package/server/shared/claude-cli-path.ts +139 -0
- package/server/{utils/frontmatter.js → shared/frontmatter.ts} +3 -3
- package/server/shared/interfaces.ts +64 -0
- package/server/shared/types.ts +166 -1
- package/server/shared/utils.ts +478 -0
- package/server/utils/commandParser.js +5 -3
- package/dist/assets/index-6rYG_mRo.css +0 -32
- package/dist-server/server/utils/frontmatter.js.map +0 -1
- package/dist-server/shared/modelConstants.js +0 -98
- package/dist-server/shared/modelConstants.js.map +0 -1
- package/shared/modelConstants.js +0 -106
package/server/routes/cursor.js
CHANGED
|
@@ -2,7 +2,7 @@ import express from 'express';
|
|
|
2
2
|
import { promises as fs } from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import os from 'os';
|
|
5
|
-
import {
|
|
5
|
+
import { CURSOR_FALLBACK_MODELS } from '../modules/providers/list/cursor/cursor-models.provider.js';
|
|
6
6
|
|
|
7
7
|
const router = express.Router();
|
|
8
8
|
|
|
@@ -29,7 +29,7 @@ router.get('/config', async (req, res) => {
|
|
|
29
29
|
config: {
|
|
30
30
|
version: 1,
|
|
31
31
|
model: {
|
|
32
|
-
modelId:
|
|
32
|
+
modelId: CURSOR_FALLBACK_MODELS.DEFAULT,
|
|
33
33
|
displayName: 'GPT-5',
|
|
34
34
|
},
|
|
35
35
|
permissions: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
+
|
|
2
3
|
import { apiKeysDb, credentialsDb, notificationPreferencesDb, pushSubscriptionsDb } from '../modules/database/index.js';
|
|
3
4
|
import { getPublicKey } from '../services/vapid-keys.js';
|
|
4
5
|
import { createNotificationEvent, notifyUserIfEnabled } from '../services/notification-orchestrator.js';
|
|
@@ -273,14 +274,4 @@ router.post('/push/unsubscribe', async (req, res) => {
|
|
|
273
274
|
}
|
|
274
275
|
});
|
|
275
276
|
|
|
276
|
-
// Host OS for UI (e.g. hide Cursor agent when the backend runs on Windows).
|
|
277
|
-
router.get('/server-env', async (req, res) => {
|
|
278
|
-
try {
|
|
279
|
-
res.json({ platform: process.platform });
|
|
280
|
-
} catch (error) {
|
|
281
|
-
console.error('Error reading server environment:', error);
|
|
282
|
-
res.status(500).json({ error: 'Failed to read server environment' });
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
|
|
286
277
|
export default router;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import { executeModelsCommand } from '../commands.js';
|
|
5
|
+
import { providerModelsService } from '../../modules/providers/services/provider-models.service.js';
|
|
6
|
+
|
|
7
|
+
test('models command returns available models only for the active provider', async () => {
|
|
8
|
+
const originalGetProviderModels = providerModelsService.getProviderModels;
|
|
9
|
+
const originalGetCurrentActiveModel = providerModelsService.getCurrentActiveModel;
|
|
10
|
+
let getCurrentActiveModelCalls = 0;
|
|
11
|
+
|
|
12
|
+
providerModelsService.getProviderModels = async () => ({
|
|
13
|
+
models: {
|
|
14
|
+
OPTIONS: [{ value: 'gpt-5.4', label: 'gpt-5.4' }],
|
|
15
|
+
DEFAULT: 'gpt-5.4',
|
|
16
|
+
},
|
|
17
|
+
cache: {
|
|
18
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
19
|
+
expiresAt: '2026-01-04T00:00:00.000Z',
|
|
20
|
+
source: 'fresh',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
providerModelsService.getCurrentActiveModel = async () => {
|
|
24
|
+
getCurrentActiveModelCalls += 1;
|
|
25
|
+
return {
|
|
26
|
+
model: 'gpt-5.3-codex',
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const result = await executeModelsCommand([], {
|
|
32
|
+
provider: 'codex',
|
|
33
|
+
model: 'gpt-5.4',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
assert.equal(result.type, 'builtin');
|
|
37
|
+
assert.equal(result.action, 'models');
|
|
38
|
+
assert.equal(result.data.current.provider, 'codex');
|
|
39
|
+
assert.equal(result.data.current.model, 'gpt-5.4');
|
|
40
|
+
assert.deepEqual(Object.keys(result.data.available), ['codex']);
|
|
41
|
+
assert.deepEqual(result.data.available.codex, result.data.availableModels);
|
|
42
|
+
assert.ok(result.data.availableModels.includes('gpt-5.4'));
|
|
43
|
+
assert.equal(result.data.available.claude, undefined);
|
|
44
|
+
assert.equal(result.data.available.cursor, undefined);
|
|
45
|
+
assert.equal(getCurrentActiveModelCalls, 0);
|
|
46
|
+
} finally {
|
|
47
|
+
providerModelsService.getProviderModels = originalGetProviderModels;
|
|
48
|
+
providerModelsService.getCurrentActiveModel = originalGetCurrentActiveModel;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('models command falls back to claude for unsupported providers', async () => {
|
|
53
|
+
const originalGetProviderModels = providerModelsService.getProviderModels;
|
|
54
|
+
const originalGetCurrentActiveModel = providerModelsService.getCurrentActiveModel;
|
|
55
|
+
|
|
56
|
+
providerModelsService.getProviderModels = async () => ({
|
|
57
|
+
models: {
|
|
58
|
+
OPTIONS: [{ value: 'default', label: 'Default (recommended)' }],
|
|
59
|
+
DEFAULT: 'default',
|
|
60
|
+
},
|
|
61
|
+
cache: {
|
|
62
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
63
|
+
expiresAt: '2026-01-04T00:00:00.000Z',
|
|
64
|
+
source: 'fresh',
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
providerModelsService.getCurrentActiveModel = async () => ({
|
|
68
|
+
model: 'default',
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const result = await executeModelsCommand([], {
|
|
73
|
+
provider: 'unknown-provider',
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
assert.equal(result.data.current.provider, 'claude');
|
|
77
|
+
assert.deepEqual(Object.keys(result.data.available), ['claude']);
|
|
78
|
+
} finally {
|
|
79
|
+
providerModelsService.getProviderModels = originalGetProviderModels;
|
|
80
|
+
providerModelsService.getCurrentActiveModel = originalGetCurrentActiveModel;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
resolveClaudeCodeExecutablePath,
|
|
6
|
+
type ResolveClaudeCodeExecutablePathDependencies,
|
|
7
|
+
} from '@/shared/claude-cli-path.js';
|
|
8
|
+
|
|
9
|
+
test('resolveClaudeCodeExecutablePath resolves the npm Claude wrapper to its native exe on Windows', () => {
|
|
10
|
+
const wrapperDir = 'C:\\nvm4w\\nodejs';
|
|
11
|
+
const nativePath = `${wrapperDir}\\node_modules\\@anthropic-ai\\claude-code\\bin\\claude.exe`;
|
|
12
|
+
const execFileSync =
|
|
13
|
+
(() => `${wrapperDir}\\claude\r\n${wrapperDir}\\claude.cmd\r\n`) as unknown as ResolveClaudeCodeExecutablePathDependencies['execFileSync'];
|
|
14
|
+
const readFileSync = (() => '') as unknown as ResolveClaudeCodeExecutablePathDependencies['readFileSync'];
|
|
15
|
+
|
|
16
|
+
const resolved = resolveClaudeCodeExecutablePath('claude', {
|
|
17
|
+
platform: 'win32',
|
|
18
|
+
execFileSync,
|
|
19
|
+
existsSync: (candidate) => candidate === nativePath,
|
|
20
|
+
readFileSync,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
assert.equal(resolved, nativePath);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('resolveClaudeCodeExecutablePath keeps an explicit JavaScript launcher path unchanged', () => {
|
|
27
|
+
const scriptPath = 'C:\\tools\\claude.js';
|
|
28
|
+
|
|
29
|
+
const resolved = resolveClaudeCodeExecutablePath(scriptPath, {
|
|
30
|
+
platform: 'win32',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
assert.equal(resolved, scriptPath);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('resolveClaudeCodeExecutablePath can parse a wrapper file path containing letters r and n before claude.exe', () => {
|
|
37
|
+
const wrapperPath = 'C:\\tools\\claude';
|
|
38
|
+
const nativePath = 'C:\\tools\\custom\\bin\\node_modules\\@anthropic-ai\\claude-code\\bin\\claude.exe';
|
|
39
|
+
const readFileSync = (() => `exec "$basedir/custom/bin/node_modules/@anthropic-ai/claude-code/bin/claude.exe" "$@"`) as unknown as ResolveClaudeCodeExecutablePathDependencies['readFileSync'];
|
|
40
|
+
|
|
41
|
+
const resolved = resolveClaudeCodeExecutablePath(wrapperPath, {
|
|
42
|
+
platform: 'win32',
|
|
43
|
+
existsSync: (candidate) => candidate === nativePath,
|
|
44
|
+
readFileSync,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
assert.equal(resolved, nativePath);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('resolveClaudeCodeExecutablePath falls back to the configured command when PATH lookup fails', () => {
|
|
51
|
+
const execFileSync = (() => {
|
|
52
|
+
throw new Error('not found');
|
|
53
|
+
}) as unknown as ResolveClaudeCodeExecutablePathDependencies['execFileSync'];
|
|
54
|
+
|
|
55
|
+
const resolved = resolveClaudeCodeExecutablePath('claude', {
|
|
56
|
+
platform: 'win32',
|
|
57
|
+
execFileSync,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
assert.equal(resolved, 'claude');
|
|
61
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_CLAUDE_COMMAND = 'claude';
|
|
6
|
+
const CLAUDE_SCRIPT_EXTENSIONS = new Set(['.cjs', '.js', '.jsx', '.mjs', '.ts', '.tsx']);
|
|
7
|
+
const CLAUDE_WRAPPER_SEGMENTS = ['node_modules', '@anthropic-ai', 'claude-code', 'bin', 'claude.exe'] as const;
|
|
8
|
+
|
|
9
|
+
export type ResolveClaudeCodeExecutablePathDependencies = {
|
|
10
|
+
execFileSync?: typeof execFileSync;
|
|
11
|
+
existsSync?: typeof fs.existsSync;
|
|
12
|
+
platform?: NodeJS.Platform;
|
|
13
|
+
readFileSync?: typeof fs.readFileSync;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function getPathApi(platform: NodeJS.Platform) {
|
|
17
|
+
return platform === 'win32' ? path.win32 : path;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function stripWrappingQuotes(value: string): string {
|
|
21
|
+
const trimmed = value.trim();
|
|
22
|
+
if (
|
|
23
|
+
(trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
24
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"))
|
|
25
|
+
) {
|
|
26
|
+
return trimmed.slice(1, -1);
|
|
27
|
+
}
|
|
28
|
+
return trimmed;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isPathLike(value: string): boolean {
|
|
32
|
+
return value.includes('/') || value.includes('\\');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function resolveClaudeWrapperBinary(
|
|
36
|
+
wrapperPath: string,
|
|
37
|
+
deps: Required<ResolveClaudeCodeExecutablePathDependencies>,
|
|
38
|
+
): string | null {
|
|
39
|
+
const pathApi = getPathApi(deps.platform);
|
|
40
|
+
const directCandidate = pathApi.resolve(pathApi.dirname(wrapperPath), ...CLAUDE_WRAPPER_SEGMENTS);
|
|
41
|
+
|
|
42
|
+
if (deps.existsSync(directCandidate)) {
|
|
43
|
+
return directCandidate;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let content: string;
|
|
47
|
+
try {
|
|
48
|
+
content = deps.readFileSync(wrapperPath, 'utf8');
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const matches = content.matchAll(/["']([^"'\\\r\n]*claude\.exe)["']/gi);
|
|
54
|
+
for (const match of matches) {
|
|
55
|
+
const rawTarget = match[1]
|
|
56
|
+
.replace(/^\$basedir[\\/]/i, '')
|
|
57
|
+
.replace(/^%dp0%[\\/]/i, '')
|
|
58
|
+
.replace(/^%~dp0[\\/]/i, '');
|
|
59
|
+
const normalizedTarget = rawTarget.replace(/[\\/]/g, pathApi.sep);
|
|
60
|
+
const candidate = pathApi.isAbsolute(normalizedTarget)
|
|
61
|
+
? normalizedTarget
|
|
62
|
+
: pathApi.resolve(pathApi.dirname(wrapperPath), normalizedTarget);
|
|
63
|
+
|
|
64
|
+
if (deps.existsSync(candidate)) {
|
|
65
|
+
return candidate;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function resolveWindowsClaudeExecutablePath(
|
|
73
|
+
configuredPath: string,
|
|
74
|
+
deps: Required<ResolveClaudeCodeExecutablePathDependencies>,
|
|
75
|
+
): string {
|
|
76
|
+
const pathApi = getPathApi(deps.platform);
|
|
77
|
+
const extension = pathApi.extname(configuredPath).toLowerCase();
|
|
78
|
+
const explicitPath = isPathLike(configuredPath) || pathApi.isAbsolute(configuredPath);
|
|
79
|
+
|
|
80
|
+
if (CLAUDE_SCRIPT_EXTENSIONS.has(extension)) {
|
|
81
|
+
return configuredPath;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (explicitPath && extension === '.exe') {
|
|
85
|
+
return configuredPath;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (explicitPath) {
|
|
89
|
+
return resolveClaudeWrapperBinary(configuredPath, deps) ?? configuredPath;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const stdout = deps.execFileSync('where.exe', [configuredPath], {
|
|
94
|
+
encoding: 'utf8',
|
|
95
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
96
|
+
windowsHide: true,
|
|
97
|
+
});
|
|
98
|
+
const candidates = stdout
|
|
99
|
+
.split(/\r?\n/)
|
|
100
|
+
.map((entry) => entry.trim())
|
|
101
|
+
.filter(Boolean);
|
|
102
|
+
|
|
103
|
+
for (const candidate of candidates) {
|
|
104
|
+
if (pathApi.extname(candidate).toLowerCase() === '.exe') {
|
|
105
|
+
return candidate;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const candidate of candidates) {
|
|
110
|
+
const resolved = resolveClaudeWrapperBinary(candidate, deps);
|
|
111
|
+
if (resolved) {
|
|
112
|
+
return resolved;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
return configuredPath;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return configuredPath;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function resolveClaudeCodeExecutablePath(
|
|
123
|
+
configuredPath: string | undefined = process.env.CLAUDE_CLI_PATH,
|
|
124
|
+
dependencies: ResolveClaudeCodeExecutablePathDependencies = {},
|
|
125
|
+
): string {
|
|
126
|
+
const deps: Required<ResolveClaudeCodeExecutablePathDependencies> = {
|
|
127
|
+
execFileSync: dependencies.execFileSync ?? execFileSync,
|
|
128
|
+
existsSync: dependencies.existsSync ?? fs.existsSync,
|
|
129
|
+
platform: dependencies.platform ?? process.platform,
|
|
130
|
+
readFileSync: dependencies.readFileSync ?? fs.readFileSync,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const normalizedPath = stripWrappingQuotes(configuredPath || DEFAULT_CLAUDE_COMMAND);
|
|
134
|
+
if (deps.platform !== 'win32') {
|
|
135
|
+
return normalizedPath;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return resolveWindowsClaudeExecutablePath(normalizedPath, deps);
|
|
139
|
+
}
|
|
@@ -9,10 +9,10 @@ const frontmatterOptions = {
|
|
|
9
9
|
engines: {
|
|
10
10
|
js: disabledFrontmatterEngine,
|
|
11
11
|
javascript: disabledFrontmatterEngine,
|
|
12
|
-
json: disabledFrontmatterEngine
|
|
13
|
-
}
|
|
12
|
+
json: disabledFrontmatterEngine,
|
|
13
|
+
},
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
export function
|
|
16
|
+
export function parseFrontMatter(content: string) {
|
|
17
17
|
return matter(content, frontmatterOptions);
|
|
18
18
|
}
|
|
@@ -4,8 +4,14 @@ import type {
|
|
|
4
4
|
LLMProvider,
|
|
5
5
|
McpScope,
|
|
6
6
|
NormalizedMessage,
|
|
7
|
+
ProviderSkill,
|
|
8
|
+
ProviderSkillListOptions,
|
|
7
9
|
ProviderAuthStatus,
|
|
10
|
+
ProviderChangeActiveModelInput,
|
|
11
|
+
ProviderCurrentActiveModel,
|
|
12
|
+
ProviderModelsDefinition,
|
|
8
13
|
ProviderMcpServer,
|
|
14
|
+
ProviderSessionActiveModelChange,
|
|
9
15
|
UpsertProviderMcpServerInput,
|
|
10
16
|
} from '@/shared/types.js';
|
|
11
17
|
|
|
@@ -18,12 +24,54 @@ import type {
|
|
|
18
24
|
*/
|
|
19
25
|
export interface IProvider {
|
|
20
26
|
readonly id: LLMProvider;
|
|
27
|
+
readonly models: IProviderModels;
|
|
21
28
|
readonly mcp: IProviderMcp;
|
|
22
29
|
readonly auth: IProviderAuth;
|
|
30
|
+
readonly skills: IProviderSkills;
|
|
23
31
|
readonly sessions: IProviderSessions;
|
|
24
32
|
readonly sessionSynchronizer: IProviderSessionSynchronizer;
|
|
25
33
|
}
|
|
26
34
|
|
|
35
|
+
// ---------------------------
|
|
36
|
+
//----------------- PROVIDER MODEL INTERFACE ------------
|
|
37
|
+
/**
|
|
38
|
+
* Model catalog contract for one provider.
|
|
39
|
+
*
|
|
40
|
+
* Implementations are responsible for resolving the provider's currently
|
|
41
|
+
* supported models and converting them into the shared
|
|
42
|
+
* `ProviderModelsDefinition` shape used by backend routes and frontend model
|
|
43
|
+
* pickers. The `DEFAULT` field should be the most appropriate default selection
|
|
44
|
+
* for that provider at the time the catalog is read.
|
|
45
|
+
*/
|
|
46
|
+
export interface IProviderModels {
|
|
47
|
+
/**
|
|
48
|
+
* Returns the provider's currently supported model catalog.
|
|
49
|
+
*/
|
|
50
|
+
getSupportedModels(): Promise<ProviderModelsDefinition>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Returns the currently active model for one session or provider runtime.
|
|
54
|
+
*
|
|
55
|
+
* Implementations must use the provider-specific lookup mechanism approved
|
|
56
|
+
* for that provider and fall back only to the provider catalog default when
|
|
57
|
+
* no active model can be resolved.
|
|
58
|
+
*/
|
|
59
|
+
getCurrentActiveModel(sessionId?: string): Promise<ProviderCurrentActiveModel>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Persists a session-scoped model override that the next resumed turn should
|
|
63
|
+
* honor for this provider.
|
|
64
|
+
*
|
|
65
|
+
* This does not require the provider to mutate an already running remote
|
|
66
|
+
* session in-place. Instead, adapters store the user's explicit model choice
|
|
67
|
+
* so the backend resume path can add the correct provider-native model option
|
|
68
|
+
* on the next CLI/SDK invocation for the same session.
|
|
69
|
+
*/
|
|
70
|
+
changeActiveModel(
|
|
71
|
+
input: ProviderChangeActiveModelInput,
|
|
72
|
+
): Promise<ProviderSessionActiveModelChange>;
|
|
73
|
+
}
|
|
74
|
+
|
|
27
75
|
// ---------------------------
|
|
28
76
|
//----------------- PROVIDER AUTH INTERFACE ------------
|
|
29
77
|
/**
|
|
@@ -39,6 +87,22 @@ export interface IProviderAuth {
|
|
|
39
87
|
getStatus(): Promise<ProviderAuthStatus>;
|
|
40
88
|
}
|
|
41
89
|
|
|
90
|
+
// ---------------------------
|
|
91
|
+
//----------------- PROVIDER SKILLS INTERFACE ------------
|
|
92
|
+
/**
|
|
93
|
+
* Skills contract for one provider.
|
|
94
|
+
*
|
|
95
|
+
* Implementations discover provider-native skill markdown locations and return
|
|
96
|
+
* normalized skill records with the exact command syntax expected by that
|
|
97
|
+
* provider. Each skill is read from a `SKILL.md` file under its skill directory.
|
|
98
|
+
*/
|
|
99
|
+
export interface IProviderSkills {
|
|
100
|
+
/**
|
|
101
|
+
* Lists all skills visible to this provider for the optional workspace.
|
|
102
|
+
*/
|
|
103
|
+
listSkills(options?: ProviderSkillListOptions): Promise<ProviderSkill[]>;
|
|
104
|
+
}
|
|
105
|
+
|
|
42
106
|
// ---------------------------
|
|
43
107
|
//----------------- PROVIDER MCP INTERFACE ------------
|
|
44
108
|
/**
|
package/server/shared/types.ts
CHANGED
|
@@ -65,7 +65,94 @@ export type AuthenticatedWebSocketRequest = IncomingMessage & {
|
|
|
65
65
|
* Use this as the source of truth whenever a function or payload needs to identify
|
|
66
66
|
* a specific LLM integration.
|
|
67
67
|
*/
|
|
68
|
-
export type LLMProvider = 'claude' | 'codex' | 'gemini' | 'cursor';
|
|
68
|
+
export type LLMProvider = 'claude' | 'codex' | 'gemini' | 'cursor' | 'opencode';
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* One selectable model row (matches the documentation `public/modelConstants.js` option shape).
|
|
72
|
+
*/
|
|
73
|
+
export type ProviderModelOption = {
|
|
74
|
+
value: string;
|
|
75
|
+
label: string;
|
|
76
|
+
description?: string;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Provider model catalog returned by `GET /api/providers/:provider/models`.
|
|
81
|
+
*/
|
|
82
|
+
export type ProviderModelsDefinition = {
|
|
83
|
+
OPTIONS: ProviderModelOption[];
|
|
84
|
+
DEFAULT: string;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Cache metadata returned alongside one provider model catalog.
|
|
89
|
+
*
|
|
90
|
+
* `updatedAt` is when the current cached snapshot was last refreshed from the
|
|
91
|
+
* provider itself. `expiresAt` is the backend cache expiry timestamp, and
|
|
92
|
+
* `source` tells callers whether the current response came from in-memory cache,
|
|
93
|
+
* persisted disk cache, or a fresh provider fetch.
|
|
94
|
+
*/
|
|
95
|
+
export type ProviderModelsCacheInfo = {
|
|
96
|
+
updatedAt: string;
|
|
97
|
+
expiresAt: string;
|
|
98
|
+
source: 'memory' | 'disk' | 'fresh';
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Full provider model lookup result returned by the backend service layer.
|
|
103
|
+
*
|
|
104
|
+
* Use this shape when a caller needs both the selectable model catalog and the
|
|
105
|
+
* cache metadata that explains how current the catalog is.
|
|
106
|
+
*/
|
|
107
|
+
export type ProviderModelsResult = {
|
|
108
|
+
models: ProviderModelsDefinition;
|
|
109
|
+
cache: ProviderModelsCacheInfo;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// ---------------------------
|
|
113
|
+
//----------------- PROVIDER ACTIVE MODEL TYPES ------------
|
|
114
|
+
/**
|
|
115
|
+
* Provider-neutral result for the model that is actively driving a session or
|
|
116
|
+
* provider runtime at the time of lookup.
|
|
117
|
+
*
|
|
118
|
+
* `model` must always be populated. Provider adapters should use the
|
|
119
|
+
* provider-specific lookup method requested by the caller, and only fall back
|
|
120
|
+
* to the provider catalog `DEFAULT` value when the active model cannot be read.
|
|
121
|
+
*/
|
|
122
|
+
export type ProviderCurrentActiveModel = {
|
|
123
|
+
model: string;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Input payload used when one session needs to use a different model on its
|
|
128
|
+
* next resumed turn.
|
|
129
|
+
*
|
|
130
|
+
* This is a backend-owned session override, not a claim that the provider has
|
|
131
|
+
* already switched the currently running session in-place. Provider adapters
|
|
132
|
+
* persist this request so the next CLI/SDK resume can inject the chosen model
|
|
133
|
+
* using the provider-specific mechanism supported by that runtime.
|
|
134
|
+
*/
|
|
135
|
+
export type ProviderChangeActiveModelInput = {
|
|
136
|
+
sessionId: string;
|
|
137
|
+
model: string;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Provider-neutral session model-change state.
|
|
142
|
+
*
|
|
143
|
+
* `supported` indicates whether the provider adapter supports the app's
|
|
144
|
+
* session-scoped resume override flow. `changed` is the persisted boolean the
|
|
145
|
+
* resume layer checks before forcing a model on the next resumed turn. When
|
|
146
|
+
* `changed` is `false`, `model` is `null` and the runtime should use the
|
|
147
|
+
* normal request/default model selection path.
|
|
148
|
+
*/
|
|
149
|
+
export type ProviderSessionActiveModelChange = {
|
|
150
|
+
provider: LLMProvider;
|
|
151
|
+
sessionId: string;
|
|
152
|
+
supported: boolean;
|
|
153
|
+
changed: boolean;
|
|
154
|
+
model: string | null;
|
|
155
|
+
};
|
|
69
156
|
|
|
70
157
|
/**
|
|
71
158
|
* Message/event variants emitted by provider adapters and normalized transports.
|
|
@@ -102,6 +189,21 @@ export type NormalizedMessage = {
|
|
|
102
189
|
kind: MessageKind;
|
|
103
190
|
role?: 'user' | 'assistant';
|
|
104
191
|
content?: string;
|
|
192
|
+
/**
|
|
193
|
+
* Optional display-oriented metadata used by providers that need to expose
|
|
194
|
+
* richer transcript artifacts without introducing a brand-new message kind.
|
|
195
|
+
*
|
|
196
|
+
* Current Claude usage:
|
|
197
|
+
* - local slash commands expose parsed command fields
|
|
198
|
+
* - compact summaries are flagged so the UI can treat them differently later
|
|
199
|
+
*/
|
|
200
|
+
displayText?: string;
|
|
201
|
+
commandName?: string;
|
|
202
|
+
commandMessage?: string;
|
|
203
|
+
commandArgs?: string;
|
|
204
|
+
isLocalCommand?: boolean;
|
|
205
|
+
isLocalCommandStdout?: boolean;
|
|
206
|
+
isCompactSummary?: boolean;
|
|
105
207
|
images?: unknown;
|
|
106
208
|
toolName?: string;
|
|
107
209
|
toolInput?: unknown;
|
|
@@ -156,6 +258,69 @@ export type FetchHistoryResult = {
|
|
|
156
258
|
tokenUsage?: unknown;
|
|
157
259
|
};
|
|
158
260
|
|
|
261
|
+
// ---------------------------
|
|
262
|
+
//----------------- PROVIDER SKILL TYPES ------------
|
|
263
|
+
/**
|
|
264
|
+
* Scope where a provider skill definition was discovered.
|
|
265
|
+
*
|
|
266
|
+
* Provider skill adapters should use this to describe the origin of each
|
|
267
|
+
* skill markdown file without leaking provider-specific folder names into route
|
|
268
|
+
* contracts. `repo` is used for Codex repository lookup locations, while
|
|
269
|
+
* `project` is used for providers that treat workspace-local skills as project
|
|
270
|
+
* scoped.
|
|
271
|
+
*/
|
|
272
|
+
export type ProviderSkillScope = 'user' | 'project' | 'plugin' | 'repo' | 'admin' | 'system';
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Shared input accepted by provider skill listing operations.
|
|
276
|
+
*
|
|
277
|
+
* Routes pass `workspacePath` when a caller wants project/repository skills for
|
|
278
|
+
* a specific folder. Providers should fall back to the backend process cwd when
|
|
279
|
+
* this option is omitted.
|
|
280
|
+
*/
|
|
281
|
+
export type ProviderSkillListOptions = {
|
|
282
|
+
workspacePath?: string;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Normalized skill record returned by provider skill adapters.
|
|
287
|
+
*
|
|
288
|
+
* The `command` value is the exact invocation text the selected provider expects
|
|
289
|
+
* for this skill. Claude plugin skills use a namespaced command such as
|
|
290
|
+
* `/plugin-name:skill-name`, while Codex skills use the `$skill-name` form.
|
|
291
|
+
* `sourcePath` points to the skill markdown file that produced the record so
|
|
292
|
+
* callers can distinguish duplicate skill names across scopes.
|
|
293
|
+
*/
|
|
294
|
+
export type ProviderSkill = {
|
|
295
|
+
provider: LLMProvider;
|
|
296
|
+
name: string;
|
|
297
|
+
description: string;
|
|
298
|
+
command: string;
|
|
299
|
+
scope: ProviderSkillScope;
|
|
300
|
+
sourcePath: string;
|
|
301
|
+
pluginName?: string;
|
|
302
|
+
pluginId?: string;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Internal source descriptor consumed by shared provider skill discovery logic.
|
|
307
|
+
*
|
|
308
|
+
* Concrete provider adapters build these records from their native lookup rules.
|
|
309
|
+
* The shared skills provider then scans `rootDir` for child skill markdown files
|
|
310
|
+
* and uses `commandForSkill` or `commandPrefix` to produce the provider-specific
|
|
311
|
+
* invocation command. Set `recursive` only when a provider stores skills under
|
|
312
|
+
* arbitrary nested folders below the source root.
|
|
313
|
+
*/
|
|
314
|
+
export type ProviderSkillSource = {
|
|
315
|
+
scope: ProviderSkillScope;
|
|
316
|
+
rootDir: string;
|
|
317
|
+
recursive?: boolean;
|
|
318
|
+
commandPrefix?: '/' | '$';
|
|
319
|
+
commandForSkill?: (skillName: string) => string;
|
|
320
|
+
pluginName?: string;
|
|
321
|
+
pluginId?: string;
|
|
322
|
+
};
|
|
323
|
+
|
|
159
324
|
// ---------------------------
|
|
160
325
|
//----------------- SHARED ERROR TYPES ------------
|
|
161
326
|
/**
|