@ai-workbench/remote-agent 0.0.0-stage → 0.8.1
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 +58 -2
- package/cordis.patch.yml +3 -0
- package/dist/acp.d.ts +54 -0
- package/dist/acp.js +341 -0
- package/dist/agents.d.ts +15 -0
- package/dist/agents.js +4 -0
- package/dist/broker.d.ts +67 -0
- package/dist/broker.js +397 -0
- package/dist/client.js +36 -0
- package/dist/connect-contract.d.ts +26 -0
- package/dist/connect-contract.js +1 -0
- package/dist/conversation-details.d.ts +47 -0
- package/dist/conversation-details.js +319 -0
- package/dist/host-layout.d.ts +8 -0
- package/dist/host-layout.js +9 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.js +360 -0
- package/dist/input.d.ts +12 -0
- package/dist/input.js +49 -0
- package/dist/interaction.d.ts +19 -0
- package/dist/interaction.js +1 -0
- package/dist/job.d.ts +17 -0
- package/dist/job.js +57 -0
- package/dist/mapping.d.ts +46 -0
- package/dist/mapping.js +230 -0
- package/dist/oneshot.d.ts +13 -0
- package/dist/oneshot.js +78 -0
- package/dist/presentation.d.ts +6 -0
- package/dist/presentation.js +45 -0
- package/dist/provider-locale.d.ts +19 -0
- package/dist/provider-locale.js +73 -0
- package/dist/provider.d.ts +144 -0
- package/dist/provider.js +164 -0
- package/dist/readiness.d.ts +28 -0
- package/dist/readiness.js +192 -0
- package/dist/remote-details.d.ts +26 -0
- package/dist/remote-details.js +250 -0
- package/dist/remote.d.ts +34 -0
- package/dist/remote.js +51 -0
- package/dist/sdk-ssh-wrapper.d.ts +2 -0
- package/dist/sdk-ssh-wrapper.js +34 -0
- package/dist/workspace-notice.d.ts +47 -0
- package/dist/workspace-notice.js +273 -0
- package/locale/en.json +10 -0
- package/locale/zh.json +10 -0
- package/package.json +97 -4
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
2
|
+
import { BlockAssembler, expandAssistantStream } from '@deepseek-ai/dsh-llm';
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
4
|
+
import { AGENTS } from "./agents.js";
|
|
5
|
+
import { NeedError } from "./remote.js";
|
|
6
|
+
const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
7
|
+
const string = (value) => typeof value === 'string' && value.length > 0;
|
|
8
|
+
const workspaceName = (value) => string(value) && value !== '.' && value !== '..' && !/[\u0000-\u001f\u007f/\\]/u.test(value);
|
|
9
|
+
function noticeText(name) {
|
|
10
|
+
// The native reply renderer accepts Markdown; escape the precise verified name as ordinary text.
|
|
11
|
+
return `此工作区对应远程主机上的 ${name.replace(/[\\`*_{}\[\]()<>#+.!|~-]/gu, '\\$&')};本地文件不会自动上传。`;
|
|
12
|
+
}
|
|
13
|
+
function rawMarker(message) {
|
|
14
|
+
if (!object(message) || !object(message.source) || !object(message.source.replayState) || !object(message.source.replayState.response))
|
|
15
|
+
return;
|
|
16
|
+
return message.source.replayState.response;
|
|
17
|
+
}
|
|
18
|
+
export function parseWorkspaceNoticeMarker(message) {
|
|
19
|
+
if (!object(message) || message.role !== 'assistant' || !string(message.id) || !object(message.source))
|
|
20
|
+
return;
|
|
21
|
+
const source = message.source, marker = rawMarker(message), definition = AGENTS.find(item => item.id === source.provider);
|
|
22
|
+
if (!object(source.replayState) || Object.keys(source.replayState).some(key => key !== 'response'))
|
|
23
|
+
return;
|
|
24
|
+
if (!marker || !definition || source.kind !== 'model' || !string(source.model) || marker.kind !== 'workspace-notice' || marker.version !== 1
|
|
25
|
+
|| marker.provider !== definition.id || marker.loginProvider !== definition.loginProvider
|
|
26
|
+
|| !['sessionId', 'noticeId', 'claimId', 'deliveryId', 'messageId', 'bindingId', 'workspaceId'].every(key => string(marker[key]))
|
|
27
|
+
|| marker.messageId !== message.id || marker.deliveryId !== message.id || !workspaceName(marker.workspaceName)
|
|
28
|
+
|| !Array.isArray(message.content) || message.content.length !== 1 || !object(message.content[0])
|
|
29
|
+
|| message.content[0].type !== 'text' || message.content[0].text !== noticeText(marker.workspaceName))
|
|
30
|
+
return;
|
|
31
|
+
return marker;
|
|
32
|
+
}
|
|
33
|
+
/** Only this plugin's complete, source-bound notice may be excluded from remote model history. */
|
|
34
|
+
export function isWorkspaceNoticeMessage(message) { return parseWorkspaceNoticeMarker(message) !== undefined; }
|
|
35
|
+
function rawPresentation(message) {
|
|
36
|
+
const response = rawMarker(message), presentation = response && object(response.presentation) ? response.presentation : undefined;
|
|
37
|
+
return presentation && object(presentation.workspaceNotice) ? presentation.workspaceNotice : undefined;
|
|
38
|
+
}
|
|
39
|
+
function shape(value) {
|
|
40
|
+
if (!object(value))
|
|
41
|
+
return false;
|
|
42
|
+
const agent = AGENTS.find(a => a.id === value.provider);
|
|
43
|
+
return !!agent && value.kind === 'workspace-notice' && value.version === 2 && value.loginProvider === agent.loginProvider
|
|
44
|
+
&& ['sessionId', 'noticeId', 'claimId', 'bindingId', 'workspaceId'].every(k => string(value[k])) && workspaceName(value.workspaceName)
|
|
45
|
+
&& Number.isSafeInteger(value.turn) && value.turn > 0 && Number.isSafeInteger(value.step) && value.step > 0
|
|
46
|
+
&& value.blockIndex === 0 && value.text === noticeText(value.workspaceName) + '\n\n';
|
|
47
|
+
}
|
|
48
|
+
export function workspaceNoticeFromMessage(message) {
|
|
49
|
+
if (!object(message) || message.role !== 'assistant' || !object(message.source) || message.source.kind !== 'model')
|
|
50
|
+
return;
|
|
51
|
+
const marker = rawPresentation(message), pointer = rawMarker(message);
|
|
52
|
+
if (!shape(marker) || message.source.provider !== marker.provider || pointer?.agent !== marker.provider || pointer.dshSessionId !== marker.sessionId
|
|
53
|
+
|| pointer.bindingId !== marker.bindingId || pointer.workspaceId !== marker.workspaceId || !Array.isArray(message.content))
|
|
54
|
+
return;
|
|
55
|
+
const block = message.content[marker.blockIndex];
|
|
56
|
+
if (!object(block) || block.type !== 'text' || block.text !== marker.text)
|
|
57
|
+
return;
|
|
58
|
+
return marker;
|
|
59
|
+
}
|
|
60
|
+
/** Preserve the model answer and exact remote replay pointer; ordinary text is never searched. */
|
|
61
|
+
export function withoutWorkspaceNotice(message) {
|
|
62
|
+
const marker = workspaceNoticeFromMessage(message);
|
|
63
|
+
if (!marker)
|
|
64
|
+
return message;
|
|
65
|
+
return { ...message, content: message.content.filter((_block, index) => index !== marker.blockIndex) };
|
|
66
|
+
}
|
|
67
|
+
function unknown(cause) {
|
|
68
|
+
return Object.assign(new NeedError('PROJECT_NOTICE_DELIVERY_UNKNOWN', '工作区说明的最终回复持久回执无法核对;请联系管理员核对,本次未继续派发远端请求。', '完整的官方最终会话记录和L工作区说明回执'), cause === undefined ? {} : { cause });
|
|
69
|
+
}
|
|
70
|
+
function requireServices(ctx, request) {
|
|
71
|
+
const id = string(request.sessionId) ? SessionId(request.sessionId) : undefined;
|
|
72
|
+
const registry = ctx.get('agents'), store = ctx.get('sessions'), persistence = ctx.get('sessionPersistence');
|
|
73
|
+
const live = id && typeof registry?.get === 'function' ? registry.get(id) : undefined, session = live?.session;
|
|
74
|
+
if (!id || !live || live.id !== id || !session || session.id !== id || typeof store?.get !== 'function' || store.get(id) !== session
|
|
75
|
+
|| typeof session.snapshotEvents !== 'function' || typeof session.append !== 'function' || typeof store.flush !== 'function' || typeof persistence?.open !== 'function') {
|
|
76
|
+
throw new NeedError('DEPENDENCY_REQUIRED', '我需要当前真实会话及官方持久化读取能力,才能确认工作区说明;本次未启动远端。', 'DSH agents、sessions、sessionPersistence公共能力');
|
|
77
|
+
}
|
|
78
|
+
return { session, flush: () => store.flush(session), persistence };
|
|
79
|
+
}
|
|
80
|
+
function requireAcknowledge(api) {
|
|
81
|
+
const method = api.acknowledgeWorkspaceNotice;
|
|
82
|
+
if (typeof method !== 'function')
|
|
83
|
+
throw new NeedError('DEPENDENCY_REQUIRED', '我需要工作区说明回执能力;本次未启动远端。', 'L acknowledgeWorkspaceNotice公共接口');
|
|
84
|
+
return method.bind(api);
|
|
85
|
+
}
|
|
86
|
+
function receipt(marker, outcome, deliveryId) {
|
|
87
|
+
const base = { noticeId: marker.noticeId, surface: 'provider', claimId: marker.claimId, sessionId: marker.sessionId, provider: marker.loginProvider };
|
|
88
|
+
if (outcome === 'delivered' && string(deliveryId))
|
|
89
|
+
return { ...base, outcome, deliveryId };
|
|
90
|
+
return { ...base, outcome: 'unknown' };
|
|
91
|
+
}
|
|
92
|
+
async function acknowledge(method, value) {
|
|
93
|
+
const result = await method(value);
|
|
94
|
+
if (!object(result) || result.ok !== true)
|
|
95
|
+
throw unknown(result);
|
|
96
|
+
}
|
|
97
|
+
async function reportUnknown(api, marker, cause) {
|
|
98
|
+
let failure = cause;
|
|
99
|
+
try {
|
|
100
|
+
await acknowledge(requireAcknowledge(api), receipt(marker, 'unknown'));
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
failure = new AggregateError([cause, error], '说明核对和未知状态记录均未完成');
|
|
104
|
+
}
|
|
105
|
+
throw unknown(failure);
|
|
106
|
+
}
|
|
107
|
+
async function readDurable(services) {
|
|
108
|
+
if (!await services.flush())
|
|
109
|
+
throw unknown();
|
|
110
|
+
const handle = await services.persistence.open(services.session.id, 'read');
|
|
111
|
+
try {
|
|
112
|
+
if (!handle || handle.id !== services.session.id || handle.header?.id !== services.session.id || handle.access !== 'read' || typeof handle.read !== 'function' || typeof handle.close !== 'function')
|
|
113
|
+
throw unknown();
|
|
114
|
+
const result = await handle.read();
|
|
115
|
+
if (!result || !Array.isArray(result.events))
|
|
116
|
+
throw unknown();
|
|
117
|
+
return result.events;
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
if (typeof handle?.close === 'function')
|
|
121
|
+
await handle.close();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function validateFinal(event, marker, events) {
|
|
125
|
+
if (event.surfaceOp !== 'append' || event.data.interrupted === true || !Array.isArray(event.data.stream)
|
|
126
|
+
|| event.data.turn !== marker.turn || event.data.step !== marker.step || !isDeepStrictEqual(workspaceNoticeFromMessage(event.data.message), marker))
|
|
127
|
+
throw unknown();
|
|
128
|
+
// Chat renders the last final for a step. An earlier append is not enough.
|
|
129
|
+
if (events.some(e => e.type === 'assistant/message' && e.surfaceOp === 'append' && e.seq > event.seq && e.data.turn === marker.turn && e.data.step === marker.step))
|
|
130
|
+
throw unknown();
|
|
131
|
+
const assembler = new BlockAssembler();
|
|
132
|
+
for (const member of expandAssistantStream(event.data.stream))
|
|
133
|
+
assembler.push(member.chunk);
|
|
134
|
+
if (!['stop', 'max-tokens'].includes(assembler.finish.kind) || !isDeepStrictEqual(assembler.blocks(), event.data.message.content)
|
|
135
|
+
|| !isDeepStrictEqual(assembler.replayState, event.data.message.source.replayState))
|
|
136
|
+
throw unknown();
|
|
137
|
+
}
|
|
138
|
+
function activeRequest(session, agent) {
|
|
139
|
+
let turn, step, provider;
|
|
140
|
+
for (const event of session.snapshotEvents())
|
|
141
|
+
switch (event.type) {
|
|
142
|
+
case 'turn/start':
|
|
143
|
+
turn = event.data.turn;
|
|
144
|
+
step = undefined;
|
|
145
|
+
break;
|
|
146
|
+
case 'turn/end':
|
|
147
|
+
turn = undefined;
|
|
148
|
+
step = undefined;
|
|
149
|
+
break;
|
|
150
|
+
case 'step/start':
|
|
151
|
+
if (event.data.turn !== turn)
|
|
152
|
+
throw unknown();
|
|
153
|
+
step = event.data.step;
|
|
154
|
+
break;
|
|
155
|
+
case 'step/end':
|
|
156
|
+
step = undefined;
|
|
157
|
+
break;
|
|
158
|
+
case 'request/header':
|
|
159
|
+
provider = event.data.header.config.provider;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
if (!Number.isSafeInteger(turn) || turn < 1 || !Number.isSafeInteger(step) || step < 1 || provider !== agent.id)
|
|
163
|
+
throw unknown();
|
|
164
|
+
return { turn: turn, step: step };
|
|
165
|
+
}
|
|
166
|
+
export function createWorkspaceNoticeConsumer(ctx, agent) {
|
|
167
|
+
const pending = new Map();
|
|
168
|
+
const flights = new Map();
|
|
169
|
+
const failures = new Map();
|
|
170
|
+
const verify = async (sessionId, api, marker, event) => {
|
|
171
|
+
try {
|
|
172
|
+
const services = requireServices(ctx, { mode: 'session', sessionId }), events = await readDurable(services);
|
|
173
|
+
const current = event ? events.find(e => e.seq === event.seq) : undefined;
|
|
174
|
+
if (!event || current?.type !== 'assistant/message' || !isDeepStrictEqual(current, event))
|
|
175
|
+
throw unknown();
|
|
176
|
+
validateFinal(current, marker, events);
|
|
177
|
+
await acknowledge(requireAcknowledge(api), receipt(marker, 'delivered', current.data.message.id));
|
|
178
|
+
pending.delete(sessionId);
|
|
179
|
+
failures.delete(sessionId);
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
return reportUnknown(api, marker, error);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
ctx.on('session/event', (session, event) => {
|
|
186
|
+
const preparation = pending.get(session.id);
|
|
187
|
+
if (!preparation)
|
|
188
|
+
return;
|
|
189
|
+
const { marker, api } = preparation;
|
|
190
|
+
let relevant;
|
|
191
|
+
if (event.type === 'assistant/message' && event.data.turn === marker.turn && event.data.step === marker.step && event.data.message.source.provider === agent.id)
|
|
192
|
+
relevant = event;
|
|
193
|
+
else if (event.type === 'turn/end' && event.data.turn === marker.turn && !session.snapshotEvents().some(e => e.type === 'assistant/message' && e.data.turn === marker.turn && e.data.step === marker.step && e.data.message.source.provider === agent.id))
|
|
194
|
+
relevant = undefined;
|
|
195
|
+
else
|
|
196
|
+
return;
|
|
197
|
+
if (flights.has(session.id))
|
|
198
|
+
return;
|
|
199
|
+
// Wait for the synchronous event dispatch to enqueue the writer, then flush.
|
|
200
|
+
const operation = Promise.resolve().then(() => verify(session.id, api, marker, relevant));
|
|
201
|
+
flights.set(session.id, operation);
|
|
202
|
+
void operation.catch(error => { failures.set(session.id, error); });
|
|
203
|
+
});
|
|
204
|
+
const reconcile = async (request, api) => {
|
|
205
|
+
request.signal?.throwIfAborted();
|
|
206
|
+
const services = requireServices(ctx, request);
|
|
207
|
+
requireAcknowledge(api);
|
|
208
|
+
const flight = flights.get(services.session.id);
|
|
209
|
+
if (flight) {
|
|
210
|
+
try {
|
|
211
|
+
await flight;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
if (flights.get(services.session.id) === flight)
|
|
216
|
+
flights.delete(services.session.id);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const events = await readDurable(services), seen = new Set();
|
|
220
|
+
let found = false;
|
|
221
|
+
for (const event of services.session.snapshotEvents()) {
|
|
222
|
+
if (event.type !== 'assistant/message')
|
|
223
|
+
continue;
|
|
224
|
+
const raw = rawPresentation(event.data.message);
|
|
225
|
+
if (!shape(raw) || raw.provider !== agent.id || raw.sessionId !== services.session.id)
|
|
226
|
+
continue;
|
|
227
|
+
if (seen.has(raw.noticeId))
|
|
228
|
+
return reportUnknown(api, raw, unknown());
|
|
229
|
+
seen.add(raw.noticeId);
|
|
230
|
+
found = true;
|
|
231
|
+
const durable = events.find(e => e.seq === event.seq);
|
|
232
|
+
if (durable?.type !== 'assistant/message' || !isDeepStrictEqual(durable, event))
|
|
233
|
+
return reportUnknown(api, raw, unknown());
|
|
234
|
+
try {
|
|
235
|
+
validateFinal(durable, raw, events);
|
|
236
|
+
await acknowledge(requireAcknowledge(api), receipt(raw, 'delivered', durable.data.message.id));
|
|
237
|
+
failures.delete(services.session.id);
|
|
238
|
+
pending.delete(services.session.id);
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
return reportUnknown(api, raw, error);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (!found && failures.has(services.session.id))
|
|
245
|
+
throw unknown(failures.get(services.session.id));
|
|
246
|
+
request.signal?.throwIfAborted();
|
|
247
|
+
};
|
|
248
|
+
const deliver = async (notice, resolved, request, api) => {
|
|
249
|
+
request.signal?.throwIfAborted();
|
|
250
|
+
const services = requireServices(ctx, request);
|
|
251
|
+
requireAcknowledge(api);
|
|
252
|
+
if (!notice || !string(notice.noticeId) || !string(notice.claimId) || notice.messageKey !== 'remote-workspace-binding' || !workspaceName(notice.workspaceName)
|
|
253
|
+
|| resolved.sessionId !== services.session.id || !string(resolved.bindingId) || !string(resolved.workspaceId) || resolved.project?.name !== notice.workspaceName)
|
|
254
|
+
throw unknown();
|
|
255
|
+
const { turn, step } = activeRequest(services.session, agent);
|
|
256
|
+
const marker = { kind: 'workspace-notice', version: 2, provider: agent.id, loginProvider: agent.loginProvider, sessionId: services.session.id,
|
|
257
|
+
noticeId: notice.noticeId, claimId: notice.claimId, workspaceName: notice.workspaceName, bindingId: resolved.bindingId, workspaceId: resolved.workspaceId, turn, step, blockIndex: 0, text: noticeText(notice.workspaceName) + '\n\n' };
|
|
258
|
+
const prior = pending.get(services.session.id);
|
|
259
|
+
if (prior) {
|
|
260
|
+
if (!isDeepStrictEqual(prior.marker, marker))
|
|
261
|
+
throw unknown();
|
|
262
|
+
return prior.marker;
|
|
263
|
+
}
|
|
264
|
+
const recorded = services.session.snapshotEvents().filter((e) => e.type === 'assistant/message').find(e => workspaceNoticeFromMessage(e.data.message)?.noticeId === notice.noticeId);
|
|
265
|
+
if (recorded) {
|
|
266
|
+
await reconcile(request, api);
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
pending.set(services.session.id, { marker, api });
|
|
270
|
+
return marker;
|
|
271
|
+
};
|
|
272
|
+
return { reconcile, deliver };
|
|
273
|
+
}
|
package/locale/en.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "Codex (Remote Host)",
|
|
4
|
+
"description": "Run Codex sessions through a remote host. Administrators: use Settings → Open configuration file to edit the existing plugin entry. See README for the six fields and approved defaults."
|
|
5
|
+
},
|
|
6
|
+
"configuration": {
|
|
7
|
+
"administratorNote": "Administrators: use Settings → Open configuration file to edit the existing plugin entry. See README for the six fields and approved defaults.",
|
|
8
|
+
"providerName": "Codex (Remote Host)"
|
|
9
|
+
}
|
|
10
|
+
}
|
package/locale/zh.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"title": "远程主机ACP",
|
|
4
|
+
"description": "通过远程主机运行Claude与Codex。首版不支持总是允许和歧义审批选项、已有Claude会话中立即生效的系统上下文变更;完整说明见README。管理员从官方设置打开配置文件修改已有条目。"
|
|
5
|
+
},
|
|
6
|
+
"configuration": {
|
|
7
|
+
"administratorNote": "管理员:从设置使用“打开配置文件”,修改已有插件条目;六个字段和已批准默认值见 README。",
|
|
8
|
+
"providerName": "Codex(远程主机)"
|
|
9
|
+
}
|
|
10
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,99 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-workbench/remote-agent",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.8.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./client": "./dist/client.js",
|
|
13
|
+
"./package.json": "./package.json",
|
|
14
|
+
"./locale/*.json": "./locale/*.json"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"locale",
|
|
19
|
+
"cordis.patch.yml"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "npm run build && node --test lib/test/*.test.js",
|
|
23
|
+
"typecheck": "node node_modules/typescript/bin/tsc --noEmit",
|
|
24
|
+
"build": "node node_modules/typescript/bin/tsc && node node_modules/typescript/bin/tsc -p tsconfig.build.json && chmod 755 lib/src/sdk-ssh-wrapper.js dist/sdk-ssh-wrapper.js && node tools/build-client.mjs",
|
|
25
|
+
"probe:host": "node tools/probe-host.ts",
|
|
26
|
+
"probe:broker": "node tools/probe-broker.ts",
|
|
27
|
+
"pack:artifact": "node tools/pack-artifact.mjs",
|
|
28
|
+
"probe:formal": "node tools/probe-formal.mjs"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=24.13.1"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@agentclientprotocol/sdk": "2.0.0",
|
|
35
|
+
"@openai/codex-sdk": "0.163.0",
|
|
36
|
+
"zod": "4.6.7"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@ai-workbench/connect": "file:test/fixtures/ai-workbench-connect-0.7.9.tgz",
|
|
40
|
+
"@deepseek-ai/cordis": "4.0.4",
|
|
41
|
+
"@deepseek-ai/cordis-plugin-group": "1.0.4",
|
|
42
|
+
"@deepseek-ai/cordis-plugin-include": "1.0.9",
|
|
43
|
+
"@deepseek-ai/cordis-plugin-loader": "1.0.5",
|
|
44
|
+
"@deepseek-ai/cordis-plugin-timer": "1.1.6",
|
|
45
|
+
"@deepseek-ai/dsh-agent": "0.2.0-rc.2",
|
|
46
|
+
"@deepseek-ai/dsh-api-gateway": "0.2.0-rc.2",
|
|
47
|
+
"@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
|
|
48
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-typert-registry": "0.2.0-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-user-approval": "0.2.0-rc.2",
|
|
52
|
+
"@deepseek-ai/schemastery": "3.18.4",
|
|
53
|
+
"@types/node": "24.10.0",
|
|
54
|
+
"typescript": "5.9.3",
|
|
55
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
|
|
56
|
+
"@deepseek-ai/dsh-attachment": "0.2.0-rc.2"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@ai-workbench/connect": "~0.7.9",
|
|
60
|
+
"@deepseek-ai/cordis": "4.0.4",
|
|
61
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.2",
|
|
63
|
+
"@deepseek-ai/schemastery": "3.18.4",
|
|
64
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
|
|
65
|
+
"@deepseek-ai/dsh-agent": "0.2.0-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-user-approval": "0.2.0-rc.2",
|
|
67
|
+
"@deepseek-ai/dsh-attachment": "0.2.0-rc.2"
|
|
68
|
+
},
|
|
69
|
+
"dsh": {
|
|
70
|
+
"bundle": {
|
|
71
|
+
"patch": "./cordis.patch.yml"
|
|
72
|
+
},
|
|
73
|
+
"client": {
|
|
74
|
+
"inject": [
|
|
75
|
+
"@deepseek-ai/dsh-client-locale",
|
|
76
|
+
"@deepseek-ai/dsh-client-connection"
|
|
77
|
+
],
|
|
78
|
+
"platform": "web"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"peerDependenciesMeta": {
|
|
82
|
+
"@ai-workbench/connect": {
|
|
83
|
+
"optional": true
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"description": "通过远程主机运行Claude与Codex会话。",
|
|
87
|
+
"publishConfig": {
|
|
88
|
+
"access": "public",
|
|
89
|
+
"registry": "https://registry.npmjs.org/"
|
|
90
|
+
},
|
|
91
|
+
"keywords": [
|
|
92
|
+
"dsh",
|
|
93
|
+
"dsh-plugin",
|
|
94
|
+
"deepseek-harness",
|
|
95
|
+
"acp",
|
|
96
|
+
"claude",
|
|
97
|
+
"codex"
|
|
98
|
+
]
|
|
99
|
+
}
|