@ai-workbench/remote-agent 0.8.19 → 0.8.23
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 +27 -134
- package/dist/acp.d.ts +23 -16
- package/dist/acp.js +209 -226
- package/dist/agents.d.ts +0 -1
- package/dist/agents.js +2 -2
- package/dist/broker-runtime.d.ts +3 -5
- package/dist/broker-runtime.js +45 -342
- package/dist/broker.d.ts +6 -31
- package/dist/broker.js +42 -113
- package/dist/catalog-ssh.d.ts +2 -31
- package/dist/catalog-ssh.js +9 -39
- package/dist/claude-local.d.ts +1 -1
- package/dist/claude-local.js +41 -105
- package/dist/client.js +34 -126
- package/dist/close-diagnostics.d.ts +6 -20
- package/dist/close-diagnostics.js +13 -57
- package/dist/connect-contract.d.ts +4 -8
- package/dist/conversation-details.d.ts +0 -29
- package/dist/conversation-details.js +8 -99
- package/dist/employee-endpoint.d.ts +1 -1
- package/dist/employee-endpoint.js +21 -19
- package/dist/employee-exec.d.ts +4 -3
- package/dist/employee-exec.js +25 -13
- package/dist/employee-info.d.ts +7 -1
- package/dist/employee-info.js +24 -3
- package/dist/employee-location.js +3 -4
- package/dist/employee-mcp.js +44 -69
- package/dist/employee-native.d.ts +1 -3
- package/dist/employee-native.js +6 -27
- package/dist/employee-presentation.d.ts +0 -5
- package/dist/employee-presentation.js +0 -15
- package/dist/employee-provider.d.ts +3 -11
- package/dist/employee-provider.js +69 -205
- package/dist/employee-reasons.js +1 -5
- package/dist/employee-shell.d.ts +2 -1
- package/dist/employee-shell.js +10 -13
- package/dist/employee-ssh.d.ts +1 -3
- package/dist/employee-ssh.js +13 -16
- package/dist/employee-tools.d.ts +5 -5
- package/dist/failure-evidence.d.ts +2 -10
- package/dist/failure-evidence.js +12 -61
- package/dist/host-workspace.d.ts +4 -2
- package/dist/host-workspace.js +6 -2
- package/dist/index.d.ts +13 -43
- package/dist/index.js +192 -484
- package/dist/input.js +2 -3
- package/dist/local-user-turn.js +5 -6
- package/dist/mapping.d.ts +5 -3
- package/dist/mapping.js +31 -36
- package/dist/model-catalog.d.ts +2 -41
- package/dist/model-catalog.js +24 -282
- package/dist/model-configuration.d.ts +0 -3
- package/dist/model-configuration.js +8 -47
- package/dist/model-presentation.d.ts +1 -0
- package/dist/model-presentation.js +2 -2
- package/dist/permissions.d.ts +15 -0
- package/dist/permissions.js +30 -0
- package/dist/preflight-diagnostic.js +11 -22
- package/dist/preflight-payload.d.ts +1 -1
- package/dist/preflight-payload.js +2 -2
- package/dist/presentation.js +21 -41
- package/dist/provider.d.ts +12 -34
- package/dist/provider.js +17 -92
- package/dist/readiness.js +1 -7
- package/dist/remote-details.d.ts +41 -17
- package/dist/remote-details.js +84 -381
- package/dist/workspace-source.d.ts +1 -25
- package/dist/workspace-source.js +1 -138
- package/package.json +11 -12
- package/dist/catalog-diagnostics.d.ts +0 -16
- package/dist/catalog-diagnostics.js +0 -108
- package/dist/host-layout.d.ts +0 -8
- package/dist/host-layout.js +0 -9
- package/dist/job.d.ts +0 -17
- package/dist/job.js +0 -57
- package/dist/model-defaults.d.ts +0 -29
- package/dist/model-defaults.js +0 -62
- package/dist/oneshot.d.ts +0 -13
- package/dist/oneshot.js +0 -78
- package/dist/protocol-boundary.d.ts +0 -13
- package/dist/protocol-boundary.js +0 -49
- package/dist/provider-locale.d.ts +0 -19
- package/dist/provider-locale.js +0 -73
- package/dist/recovery-checkpoint.d.ts +0 -6
- package/dist/recovery-checkpoint.js +0 -71
- package/dist/recovery.d.ts +0 -51
- package/dist/recovery.js +0 -61
- package/dist/sdk-ssh-wrapper.d.ts +0 -2
- package/dist/sdk-ssh-wrapper.js +0 -34
- package/dist/stage-timing.d.ts +0 -31
- package/dist/stage-timing.js +0 -61
- package/dist/workspace-notice.d.ts +0 -47
- package/dist/workspace-notice.js +0 -273
- package/dist/workspace-source-confirmation.d.ts +0 -4
- package/dist/workspace-source-confirmation.js +0 -12
package/dist/workspace-notice.js
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
-
import type { WorkspaceSourceOptions } from './workspace-source.ts';
|
|
3
|
-
/** Official same-turn one-shot question; never changes policy or fabricates a tool call. */
|
|
4
|
-
export declare function nativeWorkspaceSourceConfirmation(ctx: Context): WorkspaceSourceOptions['confirm'];
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
2
|
-
/** Official same-turn one-shot question; never changes policy or fabricates a tool call. */
|
|
3
|
-
export function nativeWorkspaceSourceConfirmation(ctx) {
|
|
4
|
-
return async (question, request) => {
|
|
5
|
-
const agent = request.sessionId ? ctx.get('agents')?.get(SessionId(request.sessionId)) : undefined;
|
|
6
|
-
const approval = ctx.get('approval');
|
|
7
|
-
const session = request.sessionId ? ctx.get('sessions')?.get(SessionId(request.sessionId)) : undefined;
|
|
8
|
-
if (!agent || !approval || !session || agent.session !== session)
|
|
9
|
-
return 'unavailable';
|
|
10
|
-
return approval.request({ agent, toolName: question.action, reason: question.question, signal: request.signal });
|
|
11
|
-
};
|
|
12
|
-
}
|