coding-tool-x 3.8.7 → 3.8.9
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.md +2 -2
- package/dist/web/assets/{AgentsDrawer-C7ePByZx.js → AgentsDrawer-Cj5CJ4d9.js} +1 -1
- package/dist/web/assets/Analytics-1doS-8uC.js +1 -0
- package/dist/web/assets/AssetPathField-C9TOPl7o.js +1 -0
- package/dist/web/assets/{ChatHistoryDrawer-Ccl4rhdz.js → ChatHistoryDrawer-BTmQ1aQr.js} +1 -1
- package/dist/web/assets/{CollapseItem-MxG_UD4o.js → CollapseItem-CwqJk3bE.js} +1 -1
- package/dist/web/assets/{CommandsDrawer-DWbaxHRZ.js → CommandsDrawer-CaZWDI_G.js} +1 -1
- package/dist/web/assets/ConfigExportDrawer-C3vSZEsS.js +1 -0
- package/dist/web/assets/{ConfigTemplates-AiRPv2cd.js → ConfigTemplates-gyERg9iC.js} +1 -1
- package/dist/web/assets/{ConfigTemplatesDrawer-CKMFsfEF.js → ConfigTemplatesDrawer-B17RqFi4.js} +1 -1
- package/dist/web/assets/{ConfigTemplatesPanel-Cvbnkvpt.js → ConfigTemplatesPanel-DKIC_FqG.js} +1 -1
- package/dist/web/assets/{Divider-D28g1gwj.js → Divider-DsdbkHrG.js} +1 -1
- package/dist/web/assets/{FavoritesDrawer-DA-dR_vP.js → FavoritesDrawer-DaziQmBp.js} +1 -1
- package/dist/web/assets/Forward-DLCL7aMY.js +1 -0
- package/dist/web/assets/{GatewayConvertDrawer-402_raGb.js → GatewayConvertDrawer-OMgWUUSc.js} +1 -1
- package/dist/web/assets/Home-DOSUTfrE.js +1 -0
- package/dist/web/assets/{MarkdownEditor-BvkDECwH.js → MarkdownEditor-9TTwTS-U.js} +1 -1
- package/dist/web/assets/McpDrawer-I8rl8lGH.js +1 -0
- package/dist/web/assets/{McpFormDrawer-DPMnyt5L.js → McpFormDrawer-DEP3C7ut.js} +1 -1
- package/dist/web/assets/{PluginManager-FKVeugr4.js → PluginManager-BuRcWuBj.js} +1 -1
- package/dist/web/assets/{PluginsDrawer-MvM1R55d.js → PluginsDrawer-_zZENaQn.js} +1 -1
- package/dist/web/assets/PluginsPanel-Bs5qZ-TK.js +1 -0
- package/dist/web/assets/PluginsPanel-CzGMK-Ap.css +1 -0
- package/dist/web/assets/ProjectList-BSxuL2td.js +1 -0
- package/dist/web/assets/{ProjectList-677RLZ8O.css → ProjectList-VbIYSHbH.css} +1 -1
- package/dist/web/assets/PromptsDrawer-CoZ-ZtsY.js +1 -0
- package/dist/web/assets/RecentSessionsDrawer-B_17aJBG.js +1 -0
- package/dist/web/assets/RecentSessionsDrawer-yrAD4p1A.css +1 -0
- package/dist/web/assets/SessionCard-BL_x0d3t.js +1 -0
- package/dist/web/assets/SessionList-DhRYZ6vl.js +1 -0
- package/dist/web/assets/SessionList-qG_XpPBJ.css +1 -0
- package/dist/web/assets/{SettingsDrawer-lMjttbkD.js → SettingsDrawer-fYb0DU7X.js} +1 -1
- package/dist/web/assets/SkillManager-S698Hns8.js +1 -0
- package/dist/web/assets/{SkillsDrawer-DF6JsSyj.js → SkillsDrawer-Ms4lPCow.js} +1 -1
- package/dist/web/assets/{SkillsPanel-B3Nm5j32.css → SkillsPanel-C4ke56nF.css} +1 -1
- package/dist/web/assets/SkillsPanel-rqnqAOGL.js +1 -0
- package/dist/web/assets/{SpeedTestDrawer-BaZkZqPP.js → SpeedTestDrawer-Bbn38SfV.js} +1 -1
- package/dist/web/assets/Upload-CdyVHxCI.js +1 -0
- package/dist/web/assets/{WorkspaceDrawer-BFSwZ5yU.js → WorkspaceDrawer-L7HJRc6u.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-BHL1uYct.js → WorkspaceManager-DsoNg2z8.js} +1 -1
- package/dist/web/assets/{WorkspacePanel-B5PooBtg.js → WorkspacePanel-Be8PVZah.js} +1 -1
- package/dist/web/assets/{headers-cf-QapUq.js → headers-B5JWGn3v.js} +1 -1
- package/dist/web/assets/{icons-B2Vg-IOC.js → icons-DmFe4b5j.js} +1 -1
- package/dist/web/assets/{index-BohDDAy_.css → index-3Lp6z8TQ.css} +1 -1
- package/dist/web/assets/index-BKlAWTH-.js +2 -0
- package/dist/web/assets/{light-Cp0t7v32.js → light-0eavxNvt.js} +1 -1
- package/dist/web/assets/platforms-BmzzwnSw.js +1 -0
- package/dist/web/assets/platforms-DWXgmy2w.js +1 -0
- package/dist/web/assets/session-visibility-BAmxh3cK.js +1 -0
- package/dist/web/assets/sessions-CC0j-KH_.js +1 -0
- package/dist/web/assets/sessions-D4yQtfKb.js +1 -0
- package/dist/web/assets/use-message-DqCwefG6.js +1 -0
- package/dist/web/assets/{useResponsiveDrawer-D-DDpbnI.js → useResponsiveDrawer-V_onl9NV.js} +1 -1
- package/dist/web/index.html +7 -7
- package/package.json +1 -1
- package/src/commands/daemon.js +27 -4
- package/src/commands/search.js +17 -2
- package/src/config/paths.js +2 -0
- package/src/platforms/channel-auth-registry.js +36 -6
- package/src/platforms/channel-auth-service.js +12 -2
- package/src/platforms/driver-registry.js +9 -1
- package/src/platforms/drivers/claude/session-history-adapter.js +72 -1
- package/src/platforms/drivers/claude/sessions-implementation.js +49 -7
- package/src/platforms/drivers/claude/sessions.js +30 -6
- package/src/platforms/drivers/codex/parser.js +57 -1
- package/src/platforms/drivers/codex/session-history-adapter.js +8 -2
- package/src/platforms/drivers/codex/sessions-implementation.js +25 -3
- package/src/platforms/drivers/codex/sessions.js +18 -1
- package/src/platforms/drivers/dsh/api-operations.js +396 -0
- package/src/platforms/drivers/dsh/channels-implementation.js +458 -0
- package/src/platforms/drivers/dsh/channels.js +191 -0
- package/src/platforms/drivers/dsh/common.js +571 -0
- package/src/platforms/drivers/dsh/native-config.js +93 -0
- package/src/platforms/drivers/dsh/native-logs.js +116 -0
- package/src/platforms/drivers/dsh/plugin-manager.js +117 -0
- package/src/platforms/drivers/dsh/projects.js +23 -0
- package/src/platforms/drivers/dsh/proxy-implementation.js +260 -0
- package/src/platforms/drivers/dsh/proxy.js +23 -0
- package/src/platforms/drivers/dsh/resources.js +346 -0
- package/src/platforms/drivers/dsh/sessions.js +587 -0
- package/src/platforms/drivers/dsh/statistics-implementation.js +238 -0
- package/src/platforms/drivers/dsh/statistics.js +24 -0
- package/src/platforms/drivers/gemini/session-history-adapter.js +49 -1
- package/src/platforms/drivers/gemini/sessions-implementation.js +46 -1
- package/src/platforms/drivers/gemini/sessions.js +2 -1
- package/src/platforms/drivers/omp/prompts.js +58 -2
- package/src/platforms/drivers/omp/proxy-implementation.js +25 -1
- package/src/platforms/drivers/omp/session-history-adapter.js +42 -1
- package/src/platforms/drivers/omp/sessions-implementation.js +51 -3
- package/src/platforms/drivers/omp/sessions.js +33 -2
- package/src/platforms/drivers/opencode/channels-implementation.js +25 -22
- package/src/platforms/drivers/opencode/channels.js +6 -1
- package/src/platforms/drivers/opencode/sessions-implementation.js +89 -9
- package/src/platforms/drivers/opencode/sessions.js +37 -1
- package/src/platforms/manifest-schema.js +43 -3
- package/src/platforms/manifests/dsh.json +542 -0
- package/src/platforms/manifests/omp.json +2 -1
- package/src/platforms/manifests/opencode.json +28 -0
- package/src/platforms/native-oauth-adapters.js +318 -18
- package/src/platforms/oauth-credentials-service.js +344 -13
- package/src/platforms/path-resolver.js +2 -0
- package/src/platforms/platform-path-context.js +12 -2
- package/src/platforms/registry.js +16 -1
- package/src/platforms/runtime.js +5 -0
- package/src/platforms/session-history-adapters.js +1 -0
- package/src/server/api/platform-api-config.js +23 -2
- package/src/server/api/platform-route-factory.js +9 -2
- package/src/server/api/platforms.js +19 -1
- package/src/server/api/plugins.js +108 -13
- package/src/server/index.js +35 -1
- package/src/server/services/config-registry-service.js +10 -1
- package/src/server/services/config-templates-service.js +1 -0
- package/src/server/services/plugins-service.js +474 -103
- package/src/server/services/session-history-index.js +900 -140
- package/src/server/services/session-history-worker.js +3 -1
- package/src/server/services/skill-service.js +214 -7
- package/src/server/services/usage-log-utils.js +1 -0
- package/src/server/services/workspace-service.js +39 -10
- package/src/shared/driver-factories/api.js +22 -6
- package/src/shared/driver-factories/projects.js +8 -0
- package/dist/web/assets/Analytics-BVG6ehFv.js +0 -1
- package/dist/web/assets/AssetPathField-BZI9NvEr.js +0 -1
- package/dist/web/assets/ConfigExportDrawer-DrawKwxE.js +0 -1
- package/dist/web/assets/Home-CTF8ZWKW.js +0 -1
- package/dist/web/assets/McpDrawer-DZGHkuDm.js +0 -1
- package/dist/web/assets/PluginsPanel-CKuBs38B.js +0 -1
- package/dist/web/assets/PluginsPanel-D6ZqITcR.css +0 -1
- package/dist/web/assets/ProjectList-tsjwjXV1.js +0 -1
- package/dist/web/assets/PromptsDrawer-B-X9ci8n.js +0 -1
- package/dist/web/assets/RecentSessionsDrawer-CKFsOYDM.css +0 -1
- package/dist/web/assets/RecentSessionsDrawer-wLktMF_c.js +0 -1
- package/dist/web/assets/SessionCard-DkJPy0TY.js +0 -1
- package/dist/web/assets/SessionList-BpYRz1cX.css +0 -1
- package/dist/web/assets/SessionList-Gzhh4FOZ.js +0 -1
- package/dist/web/assets/SkillManager-CzFxWxx-.js +0 -1
- package/dist/web/assets/SkillsPanel--lLEts9y.js +0 -1
- package/dist/web/assets/Upload-BEQ-3Kqq.js +0 -1
- package/dist/web/assets/index-BFInlZGI.js +0 -2
- package/dist/web/assets/platforms-CBkB45JP.js +0 -1
- package/dist/web/assets/platforms-FTpjxAT6.js +0 -1
- package/dist/web/assets/sessions-Cmy31slD.js +0 -1
- package/dist/web/assets/sessions-yC_oVVh8.js +0 -1
- package/dist/web/assets/use-message-DoLM8C1C.js +0 -1
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { createDriver: createNativeConfigDriver } = require('./native-config');
|
|
4
|
+
const { createDriver: createProjectsDriver } = require('./projects');
|
|
5
|
+
const { createDriver: createSessionsDriver } = require('./sessions');
|
|
6
|
+
const { listProfiles, listProfilePlugins, listProfileCapabilities, listProfileMcp, listProfilePrompts, listPlugins, upsertProfilePatchRow, deleteProfilePatchRow } = require('./common');
|
|
7
|
+
const { listSkills, getSkill, createSkill, updateSkill, deleteSkill } = require('./resources');
|
|
8
|
+
const { installPlugin, uninstallPlugin, updatePlugin } = require('./plugin-manager');
|
|
9
|
+
const { createDriver: createChannelsDriver } = require('./channels');
|
|
10
|
+
const { createDriver: createProxyDriver } = require('./proxy');
|
|
11
|
+
const { createDriver: createStatisticsDriver } = require('./statistics');
|
|
12
|
+
|
|
13
|
+
function requiredId(value, label) {
|
|
14
|
+
const id = String(value || '').trim();
|
|
15
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(id)) throw new Error(`${label} must be a safe identifier`);
|
|
16
|
+
return id;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function profilePatchOptions(request = {}) {
|
|
20
|
+
const body = request.body || {};
|
|
21
|
+
return { expectedRevision: body.expectedRevision };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function mcpConfigFromRequest(request = {}) {
|
|
25
|
+
const body = request.body || {};
|
|
26
|
+
const source = body.config && typeof body.config === 'object' && !Array.isArray(body.config) ? body.config : body;
|
|
27
|
+
const config = { ...source };
|
|
28
|
+
delete config.id;
|
|
29
|
+
delete config.name;
|
|
30
|
+
delete config.profile;
|
|
31
|
+
delete config.expectedRevision;
|
|
32
|
+
delete config.enabled;
|
|
33
|
+
delete config.disabled;
|
|
34
|
+
delete config.scope;
|
|
35
|
+
delete config.cwd;
|
|
36
|
+
if (!['stdio', 'streamable-http'].includes(config.transport)) throw new Error('MCP transport must be stdio or streamable-http');
|
|
37
|
+
if (!/^[A-Za-z0-9_-]{1,32}$/.test(String(config.serverName || '').trim())) throw new Error('MCP serverName must be 1-32 ASCII letters, digits, underscores, or hyphens');
|
|
38
|
+
return config;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function promptConfigFromRequest(request = {}) {
|
|
42
|
+
const body = request.body || {};
|
|
43
|
+
const source = body.config && typeof body.config === 'object' && !Array.isArray(body.config) ? body.config : body;
|
|
44
|
+
const config = { ...source };
|
|
45
|
+
delete config.id;
|
|
46
|
+
delete config.name;
|
|
47
|
+
delete config.profile;
|
|
48
|
+
delete config.expectedRevision;
|
|
49
|
+
delete config.enabled;
|
|
50
|
+
delete config.disabled;
|
|
51
|
+
delete config.scope;
|
|
52
|
+
delete config.cwd;
|
|
53
|
+
return config;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function patchResult(context, request, profileName, operation, patch) {
|
|
57
|
+
return {
|
|
58
|
+
profile: profileName,
|
|
59
|
+
operation,
|
|
60
|
+
patch,
|
|
61
|
+
mcp: listProfileMcp(context, profileName),
|
|
62
|
+
prompts: listProfilePrompts(context, profileName)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function requirePatchResult(patch, profileName) {
|
|
67
|
+
if (patch) return patch;
|
|
68
|
+
const error = new Error(`DSH profile not found: ${profileName}`);
|
|
69
|
+
error.statusCode = 404;
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function resultFor(context = {}, status, data, error, cause) {
|
|
74
|
+
const route = context.route || {};
|
|
75
|
+
const result = {
|
|
76
|
+
status,
|
|
77
|
+
platform: context.platform || 'dsh',
|
|
78
|
+
capability: route.capability || context.capability || 'api',
|
|
79
|
+
operation: route.operation || context.operation
|
|
80
|
+
};
|
|
81
|
+
if (status === 'ok') result.data = data;
|
|
82
|
+
if (error) result.error = error instanceof Error ? error.message : String(error);
|
|
83
|
+
if (cause) Object.defineProperty(result, 'cause', { value: cause, enumerable: false });
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function resolveProfileName(context = {}, requested = '') {
|
|
88
|
+
const profiles = listProfiles(context);
|
|
89
|
+
const requestedName = String(requested || '').trim();
|
|
90
|
+
if (requestedName) return requestedName;
|
|
91
|
+
const envProfile = String(process.env.DSH_PROFILE || '').trim();
|
|
92
|
+
if (envProfile && profiles.some(profile => profile.name === envProfile)) return envProfile;
|
|
93
|
+
return profiles.find(profile => profile.name === 'default')?.name || profiles[0]?.name || null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function profileNameForRequest(context = {}, request = {}) {
|
|
97
|
+
return resolveProfileName(
|
|
98
|
+
context,
|
|
99
|
+
request.profile
|
|
100
|
+
|| request.query?.profile
|
|
101
|
+
|| request.body?.profile
|
|
102
|
+
|| request.params?.profileName
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function dshMcpConfigToSpec(config = {}) {
|
|
107
|
+
const transport = config.transport === 'streamable-http' ? 'streamable_http' : config.transport || 'stdio';
|
|
108
|
+
const spec = { type: transport };
|
|
109
|
+
if (transport === 'stdio') {
|
|
110
|
+
if (config.command) spec.command = config.command;
|
|
111
|
+
if (Array.isArray(config.args)) spec.args = [...config.args];
|
|
112
|
+
if (config.env && typeof config.env === 'object') spec.env = { ...config.env };
|
|
113
|
+
} else {
|
|
114
|
+
if (config.url) spec.url = config.url;
|
|
115
|
+
if (config.headers && typeof config.headers === 'object') spec.headers = { ...config.headers };
|
|
116
|
+
}
|
|
117
|
+
return spec;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function dshMcpSpecToConfig(spec = {}, serverName) {
|
|
121
|
+
const type = spec.type === 'streamable_http' ? 'streamable-http' : spec.type || 'stdio';
|
|
122
|
+
if (!['stdio', 'streamable-http'].includes(type)) {
|
|
123
|
+
throw new Error(`DSH MCP does not support transport: ${spec.type || type}`);
|
|
124
|
+
}
|
|
125
|
+
const config = { serverName, transport: type };
|
|
126
|
+
if (type === 'stdio') {
|
|
127
|
+
if (spec.command) config.command = spec.command;
|
|
128
|
+
if (Array.isArray(spec.args)) config.args = [...spec.args];
|
|
129
|
+
if (spec.env && typeof spec.env === 'object') config.env = { ...spec.env };
|
|
130
|
+
} else {
|
|
131
|
+
if (spec.url) config.url = spec.url;
|
|
132
|
+
if (spec.headers && typeof spec.headers === 'object') config.headers = { ...spec.headers };
|
|
133
|
+
}
|
|
134
|
+
return config;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function readDshMcpEntries(context = {}) {
|
|
138
|
+
const profile = resolveProfileName(context);
|
|
139
|
+
if (!profile) return {};
|
|
140
|
+
const result = listProfileMcp(context, profile);
|
|
141
|
+
const entries = {};
|
|
142
|
+
for (const server of result?.servers || []) {
|
|
143
|
+
if (!server?.id || server.disabled) continue;
|
|
144
|
+
entries[server.id] = dshMcpConfigToSpec(server.config || {});
|
|
145
|
+
}
|
|
146
|
+
return entries;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function promptContentFromDshConfig(config = {}) {
|
|
150
|
+
for (const key of ['content', 'prompt', 'text']) {
|
|
151
|
+
if (typeof config[key] === 'string') return config[key];
|
|
152
|
+
}
|
|
153
|
+
return [config.personaPrefix, config.personaSuffix]
|
|
154
|
+
.filter(value => typeof value === 'string' && value.trim())
|
|
155
|
+
.join('\n')
|
|
156
|
+
.trim();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function readDshPrompt(context = {}) {
|
|
160
|
+
const profile = resolveProfileName(context);
|
|
161
|
+
if (!profile) return '';
|
|
162
|
+
const result = listProfilePrompts(context, profile);
|
|
163
|
+
const prompt = [...(result?.prompts || [])]
|
|
164
|
+
.filter(entry => entry && entry.disabled !== true)
|
|
165
|
+
.pop();
|
|
166
|
+
return promptContentFromDshConfig(prompt?.config || {});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function dshCapabilityContext(context, capability, operation) {
|
|
170
|
+
return { ...context, capability, operation };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function createDriver(context = {}) {
|
|
174
|
+
const native = createNativeConfigDriver(context);
|
|
175
|
+
const projects = createProjectsDriver(context);
|
|
176
|
+
const sessions = createSessionsDriver(context);
|
|
177
|
+
const channels = createChannelsDriver(context);
|
|
178
|
+
const proxy = createProxyDriver(context);
|
|
179
|
+
const statistics = createStatisticsDriver(context);
|
|
180
|
+
const driver = {
|
|
181
|
+
...projects,
|
|
182
|
+
...sessions,
|
|
183
|
+
platform: 'dsh',
|
|
184
|
+
capability: context.capability || 'api'
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// Keep the aggregate DSH API driver compatible with the manifest consistency
|
|
188
|
+
// contract. Actual descriptor requests are still dispatched by capability.
|
|
189
|
+
for (const operation of ['list', 'current', 'enabled', 'create', 'update', 'remove', 'applyToSettings', 'sync', 'order', 'models', 'probeModels', 'speedTest', 'speedTestAll']) {
|
|
190
|
+
driver[operation] = (...args) => channels[operation](...args);
|
|
191
|
+
}
|
|
192
|
+
for (const operation of ['status', 'start', 'stop']) {
|
|
193
|
+
driver[operation] = (...args) => proxy[operation](...args);
|
|
194
|
+
}
|
|
195
|
+
for (const operation of ['summary', 'today', 'daily']) {
|
|
196
|
+
driver[operation] = (...args) => statistics[operation](...args);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
driver.getConfig = async request => resultFor(request, 'ok', native.getConfig());
|
|
200
|
+
driver.updateConfig = async request => {
|
|
201
|
+
try {
|
|
202
|
+
return resultFor(request, 'ok', native.updateConfig(request));
|
|
203
|
+
} catch (error) {
|
|
204
|
+
return resultFor(request, error.statusCode === 409 ? 'conflict' : 'failed', undefined, error, error);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
driver.getConfigCapabilities = async request => resultFor(request, 'ok', native.getConfigCapabilities());
|
|
208
|
+
driver.getConfigAuthProviders = async request => resultFor(request, 'ok', native.getConfigAuthProviders());
|
|
209
|
+
driver.getConfigResources = async request => resultFor(request, 'ok', native.getConfigResources(request));
|
|
210
|
+
driver.listProfiles = async request => resultFor(request, 'ok', { profiles: listProfiles(context) });
|
|
211
|
+
driver.listPlugins = request => resultFor(request, 'ok', listPlugins(context));
|
|
212
|
+
driver.listProfilePlugins = async (request = {}) => {
|
|
213
|
+
const profile = request.params?.profileName;
|
|
214
|
+
const result = listProfilePlugins(context, profile);
|
|
215
|
+
return result ? resultFor(request, 'ok', result) : resultFor(request, 'unsupported');
|
|
216
|
+
};
|
|
217
|
+
driver.listProfileCapabilities = async (request = {}) => {
|
|
218
|
+
const profile = request.params?.profileName;
|
|
219
|
+
const result = listProfileCapabilities(context, profile);
|
|
220
|
+
return result ? resultFor(request, 'ok', result) : resultFor(request, 'unsupported');
|
|
221
|
+
};
|
|
222
|
+
driver.listProfileMcp = async (request = {}) => {
|
|
223
|
+
const profile = request.params?.profileName;
|
|
224
|
+
const result = listProfileMcp(context, profile);
|
|
225
|
+
return result ? resultFor(request, 'ok', result) : resultFor(request, 'unsupported');
|
|
226
|
+
};
|
|
227
|
+
driver.listProfilePrompts = async (request = {}) => {
|
|
228
|
+
const profile = request.params?.profileName;
|
|
229
|
+
const result = listProfilePrompts(context, profile);
|
|
230
|
+
return result ? resultFor(request, 'ok', result) : resultFor(request, 'unsupported');
|
|
231
|
+
};
|
|
232
|
+
driver.installPlugin = async (request = {}) => {
|
|
233
|
+
const result = await installPlugin(context, request);
|
|
234
|
+
return resultFor(request, 'ok', result);
|
|
235
|
+
};
|
|
236
|
+
driver.uninstallPlugin = async (request = {}) => {
|
|
237
|
+
const result = await uninstallPlugin(context, request);
|
|
238
|
+
return resultFor(request, 'ok', result);
|
|
239
|
+
};
|
|
240
|
+
driver.updatePlugin = async (request = {}) => {
|
|
241
|
+
const result = await updatePlugin(context, request);
|
|
242
|
+
return resultFor(request, 'ok', result);
|
|
243
|
+
};
|
|
244
|
+
driver.upsertMcp = async (request = {}) => {
|
|
245
|
+
const profileName = request.params?.profileName;
|
|
246
|
+
const body = request.body || {};
|
|
247
|
+
const config = mcpConfigFromRequest(request);
|
|
248
|
+
const serverName = String(config.serverName).trim();
|
|
249
|
+
const id = requiredId(request.params?.serverId || body.id || `mcp-${serverName}`, 'MCP id');
|
|
250
|
+
const entry = {
|
|
251
|
+
id,
|
|
252
|
+
name: '@deepseek-ai/dsh-mcp-client',
|
|
253
|
+
...(body.disabled === true || body.enabled === false ? { disabled: true } : {}),
|
|
254
|
+
config
|
|
255
|
+
};
|
|
256
|
+
const patch = requirePatchResult(
|
|
257
|
+
upsertProfilePatchRow(context, profileName, entry, profilePatchOptions(request)),
|
|
258
|
+
profileName
|
|
259
|
+
);
|
|
260
|
+
return resultFor(request, 'ok', patchResult(context, request, profileName, 'upsertMcp', patch));
|
|
261
|
+
};
|
|
262
|
+
driver.deleteMcp = async (request = {}) => {
|
|
263
|
+
const profileName = request.params?.profileName;
|
|
264
|
+
const body = request.body || {};
|
|
265
|
+
const id = requiredId(request.params?.serverId || body.id, 'MCP id');
|
|
266
|
+
const patch = requirePatchResult(
|
|
267
|
+
deleteProfilePatchRow(context, profileName, id, profilePatchOptions(request)),
|
|
268
|
+
profileName
|
|
269
|
+
);
|
|
270
|
+
return resultFor(request, 'ok', patchResult(context, request, profileName, 'deleteMcp', patch));
|
|
271
|
+
};
|
|
272
|
+
driver.upsertPrompt = async (request = {}) => {
|
|
273
|
+
const profileName = request.params?.profileName;
|
|
274
|
+
const body = request.body || {};
|
|
275
|
+
const id = requiredId(request.params?.promptId || body.id, 'prompt id');
|
|
276
|
+
const patch = requirePatchResult(
|
|
277
|
+
upsertProfilePatchRow(context, profileName, {
|
|
278
|
+
id,
|
|
279
|
+
name: '@deepseek-ai/dsh-system-prompt',
|
|
280
|
+
...(body.disabled === true || body.enabled === false ? { disabled: true } : {}),
|
|
281
|
+
config: promptConfigFromRequest(request)
|
|
282
|
+
}, profilePatchOptions(request)),
|
|
283
|
+
profileName
|
|
284
|
+
);
|
|
285
|
+
return resultFor(request, 'ok', patchResult(context, request, profileName, 'upsertPrompt', patch));
|
|
286
|
+
};
|
|
287
|
+
driver.deletePrompt = async (request = {}) => {
|
|
288
|
+
const profileName = request.params?.profileName;
|
|
289
|
+
const body = request.body || {};
|
|
290
|
+
const id = requiredId(request.params?.promptId || body.id, 'prompt id');
|
|
291
|
+
const patch = requirePatchResult(
|
|
292
|
+
deleteProfilePatchRow(context, profileName, id, profilePatchOptions(request)),
|
|
293
|
+
profileName
|
|
294
|
+
);
|
|
295
|
+
return resultFor(request, 'ok', patchResult(context, request, profileName, 'deletePrompt', patch));
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
if (context.capability === 'mcp') {
|
|
299
|
+
const mcpContext = operation => dshCapabilityContext(context, 'mcp', operation);
|
|
300
|
+
driver.entries = () => resultFor(mcpContext('entries'), 'ok', readDshMcpEntries(context));
|
|
301
|
+
driver.read = () => resultFor(mcpContext('read'), 'ok', { mcpServers: readDshMcpEntries(context) });
|
|
302
|
+
driver.normalize = spec => resultFor(mcpContext('normalize'), 'ok', spec);
|
|
303
|
+
driver.sync = async server => {
|
|
304
|
+
const profileName = profileNameForRequest(context, server);
|
|
305
|
+
const id = String(server?.id || '').trim();
|
|
306
|
+
if (!id) throw new Error('MCP server id is required');
|
|
307
|
+
const patch = requirePatchResult(
|
|
308
|
+
upsertProfilePatchRow(context, profileName, {
|
|
309
|
+
id,
|
|
310
|
+
name: '@deepseek-ai/dsh-mcp-client',
|
|
311
|
+
config: dshMcpSpecToConfig(server.server || {}, id)
|
|
312
|
+
}),
|
|
313
|
+
profileName
|
|
314
|
+
);
|
|
315
|
+
return resultFor(mcpContext('sync'), 'ok', patch);
|
|
316
|
+
};
|
|
317
|
+
driver.remove = async serverId => {
|
|
318
|
+
const profileName = profileNameForRequest(context);
|
|
319
|
+
const id = String(serverId || '').trim();
|
|
320
|
+
if (!id) throw new Error('MCP server id is required');
|
|
321
|
+
if (!profileName) return resultFor(mcpContext('remove'), 'ok', true);
|
|
322
|
+
const patch = requirePatchResult(deleteProfilePatchRow(context, profileName, id), profileName);
|
|
323
|
+
return resultFor(mcpContext('remove'), 'ok', patch);
|
|
324
|
+
};
|
|
325
|
+
driver.import = async servers => {
|
|
326
|
+
const entries = readDshMcpEntries(context);
|
|
327
|
+
let count = 0;
|
|
328
|
+
for (const [id, spec] of Object.entries(entries)) {
|
|
329
|
+
if (servers[id]) {
|
|
330
|
+
servers[id].apps = { ...(servers[id].apps || {}), dsh: true };
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
const now = Date.now();
|
|
334
|
+
servers[id] = {
|
|
335
|
+
id,
|
|
336
|
+
name: id,
|
|
337
|
+
server: spec,
|
|
338
|
+
apps: { dsh: true },
|
|
339
|
+
createdAt: now,
|
|
340
|
+
updatedAt: now
|
|
341
|
+
};
|
|
342
|
+
count++;
|
|
343
|
+
}
|
|
344
|
+
return resultFor(mcpContext('import'), 'ok', count);
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (context.capability === 'prompts') {
|
|
349
|
+
const promptContext = operation => dshCapabilityContext(context, 'prompts', operation);
|
|
350
|
+
driver.read = () => resultFor(promptContext('read'), 'ok', readDshPrompt(context));
|
|
351
|
+
driver.write = async content => {
|
|
352
|
+
const profileName = profileNameForRequest(context);
|
|
353
|
+
if (!profileName) throw new Error('No DSH profile is available');
|
|
354
|
+
if (typeof content !== 'string') throw new Error('Prompt text must be a string');
|
|
355
|
+
const patch = requirePatchResult(
|
|
356
|
+
upsertProfilePatchRow(context, profileName, {
|
|
357
|
+
id: 'system-prompt',
|
|
358
|
+
name: '@deepseek-ai/dsh-system-prompt',
|
|
359
|
+
config: { personaPrefix: content }
|
|
360
|
+
}),
|
|
361
|
+
profileName
|
|
362
|
+
);
|
|
363
|
+
return resultFor(promptContext('write'), 'ok', patch);
|
|
364
|
+
};
|
|
365
|
+
driver.remove = async () => {
|
|
366
|
+
const profileName = profileNameForRequest(context);
|
|
367
|
+
if (!profileName) return resultFor(promptContext('remove'), 'ok', true);
|
|
368
|
+
const patch = requirePatchResult(
|
|
369
|
+
deleteProfilePatchRow(context, profileName, 'system-prompt'),
|
|
370
|
+
profileName
|
|
371
|
+
);
|
|
372
|
+
return resultFor(promptContext('remove'), 'ok', patch);
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
driver.listSkills = async (request = {}) => resultFor(request, 'ok', listSkills(context, {
|
|
377
|
+
profile: request.query?.profile,
|
|
378
|
+
cwd: request.query?.cwd,
|
|
379
|
+
scope: request.query?.scope,
|
|
380
|
+
includeContent: request.query?.includeContent === '1'
|
|
381
|
+
}));
|
|
382
|
+
driver.getSkill = async (request = {}) => {
|
|
383
|
+
const result = getSkill(context, request.query?.profile, request.params?.skillName, {
|
|
384
|
+
cwd: request.query?.cwd,
|
|
385
|
+
scope: request.query?.scope
|
|
386
|
+
});
|
|
387
|
+
return result ? resultFor(request, 'ok', result) : resultFor(request, 'unsupported');
|
|
388
|
+
};
|
|
389
|
+
driver.createSkill = async (request = {}) => resultFor(request, 'ok', createSkill(context, request));
|
|
390
|
+
driver.updateSkill = async (request = {}) => resultFor(request, 'ok', updateSkill(context, request));
|
|
391
|
+
driver.deleteSkill = async (request = {}) => resultFor(request, 'ok', deleteSkill(context, request));
|
|
392
|
+
|
|
393
|
+
return driver;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
module.exports = { createDriver };
|