@goodandready/dsh-remote-workspace 0.3.4 → 0.3.6
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/docs/design/DESIGN.md +6 -0
- package/lib/client.js +19 -1
- package/lib/tools.js +21 -19
- package/package.json +1 -1
package/docs/design/DESIGN.md
CHANGED
|
@@ -83,3 +83,9 @@ emote_tunnel: создание/остановка/листинг туннеле
|
|
|
83
83
|
- `src/client/plugin-card.js` — Plugin card and status chip components
|
|
84
84
|
- `src/client/entry.js` — Cordis client plugin apply and slot registration
|
|
85
85
|
- Added native builder `scripts/build-client.mjs` hooked into `prepack` and `npm test`.
|
|
86
|
+
|
|
87
|
+
### v0.3.6 Model Tools JSON Schema Standardization (Refs: #33)
|
|
88
|
+
- Все 9 инструментов (`remote_exec`, `remote_fs`, `remote_sync`, `remote_tunnel`, `remote_docker`, `remote_service`, `remote_transfer`, `remote_diagnose`, `remote_env`) переведены на компиляцию через `defineTool()` из `@deepseek-ai/dsh-tools`.
|
|
89
|
+
- Параметры инструментов компилируются в строгий JSON Schema с корнем `{ type: 'object', properties: ..., required: [...] }`.
|
|
90
|
+
- Предотвращены ошибки валидации схем в OpenAI-совместимых провайдерах (`Invalid schema: schema must be a JSON Schema of 'type: "object"', got 'type: null'`).
|
|
91
|
+
- Схема вывода стандартизирована с явным `{ type: 'object', additionalProperties: true }`.
|
package/lib/client.js
CHANGED
|
@@ -2300,7 +2300,25 @@ window.__ModuleLoader__.load({
|
|
|
2300
2300
|
}
|
|
2301
2301
|
|
|
2302
2302
|
if (ctx.slots && typeof ctx.slots.inject === 'function') {
|
|
2303
|
-
//
|
|
2303
|
+
// Plugin-list seat (plugins.item) first: the seat the current core
|
|
2304
|
+
// (0.1.6-alpha.2) renders as the plugin's own page with its configuration. The
|
|
2305
|
+
// label is a static string on purpose — it is resolved while the page renders,
|
|
2306
|
+
// and a locale lookup there would take the whole client batch down with it.
|
|
2307
|
+
ctx.slots.inject('plugins.item', () =>
|
|
2308
|
+
ctx.slots.register(
|
|
2309
|
+
{
|
|
2310
|
+
name: 'plugins.item',
|
|
2311
|
+
id: ROW_ID,
|
|
2312
|
+
order: 60,
|
|
2313
|
+
label: () => 'Remote Workspace',
|
|
2314
|
+
locale: NS,
|
|
2315
|
+
inject: () => ({ ctx })
|
|
2316
|
+
},
|
|
2317
|
+
(props) => React.createElement(PluginCard, Object.assign({}, props, { ctx }))
|
|
2318
|
+
)
|
|
2319
|
+
)
|
|
2320
|
+
|
|
2321
|
+
// Row seat and the legacy seat stay as fallbacks.
|
|
2304
2322
|
ctx.slots.inject('plugins.row.config', () =>
|
|
2305
2323
|
ctx.slots.register(
|
|
2306
2324
|
{
|
package/lib/tools.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
2
|
+
|
|
1
3
|
export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunnelService, getActiveProfile, getProfileById, dockerService, diagnoseService, envService, tarSyncService) {
|
|
2
4
|
if (!ctx.tools || typeof ctx.tools.register !== 'function') {
|
|
3
5
|
return;
|
|
4
6
|
}
|
|
5
7
|
|
|
6
8
|
const genericOutput = {
|
|
7
|
-
schema: { type: 'object' },
|
|
9
|
+
schema: { type: 'object', additionalProperties: true },
|
|
8
10
|
render: (_args, value) => ({ type: 'text', content: typeof value === 'string' ? value : JSON.stringify(value, null, 2) })
|
|
9
11
|
};
|
|
10
12
|
|
|
11
13
|
// 1. remote_exec
|
|
12
|
-
ctx.tools.register({
|
|
14
|
+
ctx.tools.register(defineTool({
|
|
13
15
|
name: 'remote_exec',
|
|
14
16
|
description: 'Execute bash/shell command on the active remote workspace host with timeout and ANSI cleaning',
|
|
15
17
|
parameters: {
|
|
@@ -41,10 +43,10 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
41
43
|
signal: res.signal
|
|
42
44
|
};
|
|
43
45
|
}
|
|
44
|
-
});
|
|
46
|
+
}));
|
|
45
47
|
|
|
46
48
|
// 2. remote_fs
|
|
47
|
-
ctx.tools.register({
|
|
49
|
+
ctx.tools.register(defineTool({
|
|
48
50
|
name: 'remote_fs',
|
|
49
51
|
description: 'Perform file operations (read, write, stat, list, mkdir, remove) on remote workspace with caching',
|
|
50
52
|
parameters: {
|
|
@@ -91,10 +93,10 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
91
93
|
throw new Error(`Unknown action: ${action}`);
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
|
-
});
|
|
96
|
+
}));
|
|
95
97
|
|
|
96
98
|
// 3. remote_sync
|
|
97
|
-
ctx.tools.register({
|
|
99
|
+
ctx.tools.register(defineTool({
|
|
98
100
|
name: 'remote_sync',
|
|
99
101
|
description: 'Perform 3-way delta or streaming tarball synchronization between local mirror and remote server',
|
|
100
102
|
parameters: {
|
|
@@ -125,10 +127,10 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
125
127
|
return await mirrorSync.push(profile, profile.localMirrorPath, profile.remoteWorkspace, args.force, args.dryRun);
|
|
126
128
|
}
|
|
127
129
|
}
|
|
128
|
-
});
|
|
130
|
+
}));
|
|
129
131
|
|
|
130
132
|
// 4. remote_tunnel
|
|
131
|
-
ctx.tools.register({
|
|
133
|
+
ctx.tools.register(defineTool({
|
|
132
134
|
name: 'remote_tunnel',
|
|
133
135
|
description: 'Manage SSH port forwarding tunnels (start, stop, list) with telemetry metrics',
|
|
134
136
|
parameters: {
|
|
@@ -157,11 +159,11 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
157
159
|
return { success: ok };
|
|
158
160
|
}
|
|
159
161
|
}
|
|
160
|
-
});
|
|
162
|
+
}));
|
|
161
163
|
|
|
162
164
|
// 5. remote_docker
|
|
163
165
|
if (dockerService) {
|
|
164
|
-
ctx.tools.register({
|
|
166
|
+
ctx.tools.register(defineTool({
|
|
165
167
|
name: 'remote_docker',
|
|
166
168
|
description: 'Manage Docker/Podman containers and Docker Compose on remote host',
|
|
167
169
|
parameters: {
|
|
@@ -194,11 +196,11 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
194
196
|
throw new Error(`Unknown docker action: ${args.action}`);
|
|
195
197
|
}
|
|
196
198
|
}
|
|
197
|
-
});
|
|
199
|
+
}));
|
|
198
200
|
}
|
|
199
201
|
|
|
200
202
|
// 6. remote_service
|
|
201
|
-
ctx.tools.register({
|
|
203
|
+
ctx.tools.register(defineTool({
|
|
202
204
|
name: 'remote_service',
|
|
203
205
|
description: 'Inspect and manage Linux systemd or PM2 services on the remote machine',
|
|
204
206
|
parameters: {
|
|
@@ -232,10 +234,10 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
232
234
|
output: res.stdout || res.stderr
|
|
233
235
|
};
|
|
234
236
|
}
|
|
235
|
-
});
|
|
237
|
+
}));
|
|
236
238
|
|
|
237
239
|
// 7. remote_transfer
|
|
238
|
-
ctx.tools.register({
|
|
240
|
+
ctx.tools.register(defineTool({
|
|
239
241
|
name: 'remote_transfer',
|
|
240
242
|
description: 'Transfer a file directly between two configured remote servers via in-memory SFTP streams',
|
|
241
243
|
parameters: {
|
|
@@ -254,11 +256,11 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
254
256
|
|
|
255
257
|
return await sshService.transferFileBetweenHosts(srcProfile, args.sourcePath, destProfile, args.destPath);
|
|
256
258
|
}
|
|
257
|
-
});
|
|
259
|
+
}));
|
|
258
260
|
|
|
259
261
|
// 8. remote_diagnose (New in v0.3.1)
|
|
260
262
|
if (diagnoseService) {
|
|
261
|
-
ctx.tools.register({
|
|
263
|
+
ctx.tools.register(defineTool({
|
|
262
264
|
name: 'remote_diagnose',
|
|
263
265
|
description: 'Run targeted system health diagnostics on remote host (ports, disk, memory, oom_killer, service_logs)',
|
|
264
266
|
parameters: {
|
|
@@ -278,12 +280,12 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
278
280
|
if (!profile) throw new Error('No active remote workspace profile selected');
|
|
279
281
|
return await diagnoseService.diagnose(profile, args.category, args.target);
|
|
280
282
|
}
|
|
281
|
-
});
|
|
283
|
+
}));
|
|
282
284
|
}
|
|
283
285
|
|
|
284
286
|
// 9. remote_env (New in v0.3.1)
|
|
285
287
|
if (envService) {
|
|
286
|
-
ctx.tools.register({
|
|
288
|
+
ctx.tools.register(defineTool({
|
|
287
289
|
name: 'remote_env',
|
|
288
290
|
description: 'Inspect and atomically update remote .env files preserving comments and structure',
|
|
289
291
|
parameters: {
|
|
@@ -320,6 +322,6 @@ export function registerRemoteTools(ctx, sshService, remoteFs, mirrorSync, tunne
|
|
|
320
322
|
throw new Error(`Unknown env action: ${args.action}`);
|
|
321
323
|
}
|
|
322
324
|
}
|
|
323
|
-
});
|
|
325
|
+
}));
|
|
324
326
|
}
|
|
325
327
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-remote-workspace",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Enterprise Remote Workspace Plugin for DeepSeek Harness: SSH2 connection pool, SFTP operations, 3-way conflict-aware mirror sync, port forwarding, and native DSH UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|