@dsh-enhanced/assistant-delivery 0.1.30 → 0.1.32
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 -0
- package/lib/agent-runtime.d.ts.map +1 -1
- package/lib/agent-runtime.js +120 -30
- package/lib/agent-runtime.js.map +1 -1
- package/lib/native-web-owner.d.ts.map +1 -1
- package/lib/native-web-owner.js +3 -3
- package/lib/native-web-owner.js.map +1 -1
- package/lib/service.d.ts +3 -0
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +56 -32
- package/lib/service.js.map +1 -1
- package/lib/session-lease-runtime.d.ts +2 -1
- package/lib/session-lease-runtime.d.ts.map +1 -1
- package/lib/session-lease-runtime.js +3 -3
- package/lib/session-lease-runtime.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -354,6 +354,8 @@ Automation incident 使用 `automation-incident:<incidentId>:g<generation>` 同
|
|
|
354
354
|
|
|
355
355
|
Delivery 只向 Goals 的已注册 Host capability 提供一次受限恢复:它重读当前 owner route、binding、原 Session、GoalId、revision 和 deadline,在重新加载原 Session 后重查状态,仅在 Goals 的 dispatch CAS 成功后恢复原生目标。它不把历史 Session snapshot、runtime context 或任意 `user/message` 当作新的 owner 输入;DSH 会把 runtime context snapshot 持久化为 user-role message,它不能替代人类回合证明。
|
|
356
356
|
|
|
357
|
+
Web 事件唤醒若仅调用工具、没有最终回复正文,但准确原目标已结算且取得新鲜的独立成功验收,Delivery 会在复核 Goals capability、owner、原会话和发送权限后显示“目标已通过独立验收并完成。”。这是有期限、按验收证明去重的原会话通知,不伪造模型回复,也不授予执行权限;发送前继续检查 owner、binding、route、Policy 和期限。已有正文沿用原生回复;无正文的非 Web 唤醒仍不能生成外部结果消息。
|
|
358
|
+
|
|
357
359
|
Cordis 按上下文读取 service 时可能产生不同 proxy 对象,Host 不能用对象 `===` 判断同一 Delivery service 或 capability 所属。恢复、撤权、lease 到期、取消和 teardown 只能阻止新的边界动作;它们不证明已有模型、工具、子进程或外部动作已经停止。无法确认终态时返回 unknown,Goals 不自动重放。
|
|
358
360
|
|
|
359
361
|
## 权限与数据边界
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-runtime.d.ts","sourceRoot":"","sources":["../src/agent-runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-runtime.d.ts","sourceRoot":"","sources":["../src/agent-runtime.ts"],"names":[],"mappings":"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"}
|
package/lib/agent-runtime.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { mkdir, stat } from 'node:fs/promises';
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
3
4
|
import { installModelSelection, } from '@deepseek-ai/dsh-agent';
|
|
4
5
|
import { contentHasImage, createUserMessage, ReasoningEffortId, } from '@deepseek-ai/dsh-llm';
|
|
5
6
|
import { setSandboxMode } from '@deepseek-ai/dsh-sandbox-policy';
|
|
@@ -864,6 +865,12 @@ function sessionResumeFailureCode(error) {
|
|
|
864
865
|
return 'session-persistence-corrupt';
|
|
865
866
|
return 'session-resume-unavailable';
|
|
866
867
|
}
|
|
868
|
+
function sessionFormatUnsupportedReply() {
|
|
869
|
+
return {
|
|
870
|
+
text: '旧会话格式无法由当前 Host 恢复,记录已保留。请使用 /new 开启会话。',
|
|
871
|
+
format: 'plain',
|
|
872
|
+
};
|
|
873
|
+
}
|
|
867
874
|
function sessionFingerprint(value) {
|
|
868
875
|
return createHash('sha256').update(value).digest('hex').slice(0, 8);
|
|
869
876
|
}
|
|
@@ -1658,8 +1665,8 @@ export class DshDeliveryRuntime {
|
|
|
1658
1665
|
releaseToolBarriers();
|
|
1659
1666
|
}
|
|
1660
1667
|
}
|
|
1661
|
-
async setupAgent(agentCtx, workspace, presetId, principal, selected, agentPresets, initiator = 'external') {
|
|
1662
|
-
const agent = agentCtx.agent;
|
|
1668
|
+
async setupAgent(agentCtx, preparedAgent, workspace, presetId, principal, selected, agentPresets, initiator = 'external') {
|
|
1669
|
+
const agent = preparedAgent ?? agentCtx.agent;
|
|
1663
1670
|
if (agent === undefined)
|
|
1664
1671
|
throw new Error('assistant-delivery: unpublished Agent identity is missing');
|
|
1665
1672
|
if (agent.session.header.cwd !== workspace || agent.session.header.agentPreset !== presetId) {
|
|
@@ -1858,8 +1865,8 @@ export class DshDeliveryRuntime {
|
|
|
1858
1865
|
model: selected.model,
|
|
1859
1866
|
maxTokens: this.options.maxOutputTokens,
|
|
1860
1867
|
},
|
|
1861
|
-
setup: async (agentCtx) => {
|
|
1862
|
-
await this.setupAgent(agentCtx, binding.workspace, presetId, externalPrincipalId(binding.principal), selected, agentPresets);
|
|
1868
|
+
setup: async (agentCtx, preparedAgent) => {
|
|
1869
|
+
await this.setupAgent(agentCtx, preparedAgent, binding.workspace, presetId, externalPrincipalId(binding.principal), selected, agentPresets);
|
|
1863
1870
|
},
|
|
1864
1871
|
});
|
|
1865
1872
|
signal.throwIfAborted();
|
|
@@ -2177,8 +2184,8 @@ export class DshDeliveryRuntime {
|
|
|
2177
2184
|
await ensureWorkspace(workspace);
|
|
2178
2185
|
const selected = agentSelection(toModelRoute(this.options.getModelSelection(input.envelope.conversation)
|
|
2179
2186
|
?? { provider: this.options.provider, model: this.options.model }));
|
|
2180
|
-
const setup = async (agentCtx) => {
|
|
2181
|
-
await this.setupAgent(agentCtx, workspace, presetId, externalPrincipalId(input.envelope.principal), selected, agentPresets);
|
|
2187
|
+
const setup = async (agentCtx, preparedAgent) => {
|
|
2188
|
+
await this.setupAgent(agentCtx, preparedAgent, workspace, presetId, externalPrincipalId(input.envelope.principal), selected, agentPresets);
|
|
2182
2189
|
};
|
|
2183
2190
|
const lease = this.sessionLeases.open({ kind: 'construction', sessionId: String(id),
|
|
2184
2191
|
conversation: input.envelope.conversation, principal: input.envelope.principal,
|
|
@@ -2292,17 +2299,18 @@ export class DshDeliveryRuntime {
|
|
|
2292
2299
|
resumeSessionId: SessionId(binding.sessionId),
|
|
2293
2300
|
signal: control.controller.signal,
|
|
2294
2301
|
agentOptions: { provider: selected.provider, model: selected.model, maxTokens: this.options.maxOutputTokens },
|
|
2295
|
-
setup: async (agentCtx) => {
|
|
2302
|
+
setup: async (agentCtx, preparedAgent) => {
|
|
2296
2303
|
// Restored inbox entries may wake immediately on Session publication.
|
|
2297
2304
|
// Install the background-only gate before that publication boundary.
|
|
2298
|
-
|
|
2305
|
+
const agent = preparedAgent ?? agentCtx.agent;
|
|
2306
|
+
if (agent === undefined)
|
|
2299
2307
|
throw new Error('assistant-delivery: wake Agent missing');
|
|
2300
|
-
releaseFences = this.installScheduledGoalFences(
|
|
2301
|
-
await this.setupAgent(agentCtx, binding.workspace, presetId, input.attestation.principalId, selected, presets, 'background');
|
|
2308
|
+
releaseFences = this.installScheduledGoalFences(agent, input);
|
|
2309
|
+
await this.setupAgent(agentCtx, agent, binding.workspace, presetId, input.attestation.principalId, selected, presets, 'background');
|
|
2302
2310
|
const llm = this.ctx.get('llm');
|
|
2303
2311
|
if (llm === undefined)
|
|
2304
2312
|
throw new Error('assistant-delivery: llm service is required');
|
|
2305
|
-
requireAdapterToolCallProtocol(llm, selected.provider, selected.model, presetId, agentCtx.tools.schemas(agentCtx.agent).length);
|
|
2313
|
+
requireAdapterToolCallProtocol(llm, selected.provider, selected.model, presetId, agentCtx.tools.schemas(preparedAgent ?? agentCtx.agent).length);
|
|
2306
2314
|
},
|
|
2307
2315
|
});
|
|
2308
2316
|
const agent = handle.agent;
|
|
@@ -2414,6 +2422,39 @@ export class DshDeliveryRuntime {
|
|
|
2414
2422
|
input.assertCurrent(agent, phase);
|
|
2415
2423
|
}
|
|
2416
2424
|
installScheduledGoalFences(agent, input) {
|
|
2425
|
+
let pendingGoalStep;
|
|
2426
|
+
const nativeGoalStep = (source) => {
|
|
2427
|
+
const native = this.ctx.get('goals')?.get(agent);
|
|
2428
|
+
const round = source.round;
|
|
2429
|
+
if (source.kind !== 'goal' || String(source.goalId) !== input.native.goalId
|
|
2430
|
+
|| source.revision !== input.native.revision + 1 || typeof round !== 'number' || !Number.isSafeInteger(round) || round < 1
|
|
2431
|
+
|| native === undefined || native.phase !== 'active' || String(native.id) !== input.native.goalId
|
|
2432
|
+
|| native.revision !== source.revision || round !== native.roundsStarted + 1)
|
|
2433
|
+
return undefined;
|
|
2434
|
+
return { turn: 0, step: 0, goalId: String(source.goalId), revision: source.revision, round };
|
|
2435
|
+
};
|
|
2436
|
+
const durableTurnMessages = (turn) => {
|
|
2437
|
+
const events = agent.session.snapshotEvents();
|
|
2438
|
+
const start = events.findLast(event => event.type === 'turn/start');
|
|
2439
|
+
if (start?.type !== 'turn/start' || start.data.turn !== turn
|
|
2440
|
+
|| events.some(event => event.seq > start.seq && event.type === 'turn/end')) {
|
|
2441
|
+
throw new Error('assistant-delivery: exact native goal turn required');
|
|
2442
|
+
}
|
|
2443
|
+
return events.filter(event => event.seq > start.seq && event.type === 'user/message'
|
|
2444
|
+
&& !isScheduledGoalRuntimeContext(event.data.source));
|
|
2445
|
+
};
|
|
2446
|
+
const pendingCurrent = (turn, step) => {
|
|
2447
|
+
const pending = pendingGoalStep;
|
|
2448
|
+
if (pending === undefined || pending.turn !== turn || pending.step !== step)
|
|
2449
|
+
return undefined;
|
|
2450
|
+
const native = this.ctx.get('goals')?.get(agent);
|
|
2451
|
+
// Only bridge the gap before the accepted goal input is durably folded.
|
|
2452
|
+
// Once any input appears, the ordinary snapshot fence must verify it.
|
|
2453
|
+
if (native === undefined || native.phase !== 'active' || String(native.id) !== pending.goalId
|
|
2454
|
+
|| native.revision !== pending.revision || native.roundsStarted !== pending.round - 1)
|
|
2455
|
+
return undefined;
|
|
2456
|
+
return pending;
|
|
2457
|
+
};
|
|
2417
2458
|
const goalTurn = () => {
|
|
2418
2459
|
const events = agent.session.snapshotEvents();
|
|
2419
2460
|
const start = events.findLast(event => event.type === 'turn/start');
|
|
@@ -2439,23 +2480,57 @@ export class DshDeliveryRuntime {
|
|
|
2439
2480
|
catch { }
|
|
2440
2481
|
throw new Error('assistant-delivery: scheduled goal wake authorization changed');
|
|
2441
2482
|
};
|
|
2442
|
-
const
|
|
2443
|
-
|
|
2444
|
-
|
|
2483
|
+
const clearPending = () => { pendingGoalStep = undefined; };
|
|
2484
|
+
input.signal.addEventListener('abort', clearPending, { once: true });
|
|
2485
|
+
const preStep = agent.ctx.on('agent/pre-step', async (payload, next) => {
|
|
2486
|
+
// A pre-step decision is the sole new-Host bridge between the claimed
|
|
2487
|
+
// inbox item and its later durable append. Never carry it into another
|
|
2488
|
+
// boundary, rejection, replacement, or retry.
|
|
2489
|
+
clearPending();
|
|
2490
|
+
const offered = payload.messages.filter(message => !isScheduledGoalRuntimeContext(message.source));
|
|
2491
|
+
const offeredMessage = offered.length === 1 ? structuredClone(offered[0]) : undefined;
|
|
2492
|
+
const decision = await next();
|
|
2493
|
+
if (payload.signal.aborted || input.signal.aborted || decision.kind !== 'enter')
|
|
2494
|
+
return decision;
|
|
2495
|
+
const entered = decision.messages.filter(message => !isScheduledGoalRuntimeContext(message.source));
|
|
2496
|
+
if (offeredMessage === undefined || entered.length !== 1
|
|
2497
|
+
|| typeof offeredMessage.id !== 'string' || offeredMessage.id.length === 0
|
|
2498
|
+
|| !isDeepStrictEqual(entered[0], offeredMessage))
|
|
2499
|
+
return decision;
|
|
2500
|
+
const candidate = nativeGoalStep(entered[0].source);
|
|
2501
|
+
if (candidate === undefined)
|
|
2502
|
+
return decision;
|
|
2503
|
+
pendingGoalStep = { ...candidate, turn: payload.turn, step: payload.step };
|
|
2504
|
+
return decision;
|
|
2505
|
+
}, { prepend: true });
|
|
2506
|
+
const request = agent.ctx.on('agent/request', async (payload, next) => {
|
|
2507
|
+
const assertRequest = () => {
|
|
2508
|
+
payload.signal.throwIfAborted();
|
|
2509
|
+
if (durableTurnMessages(payload.turn).length > 0)
|
|
2510
|
+
goalTurn();
|
|
2511
|
+
else if (pendingCurrent(payload.turn, payload.step) === undefined)
|
|
2512
|
+
throw new Error('assistant-delivery: native goal step not admitted');
|
|
2445
2513
|
this.assertScheduledGoal(input, agent, 'running');
|
|
2446
|
-
}
|
|
2447
|
-
catch {
|
|
2448
|
-
return reject();
|
|
2449
|
-
}
|
|
2450
|
-
const result = await next();
|
|
2514
|
+
};
|
|
2451
2515
|
try {
|
|
2452
|
-
|
|
2453
|
-
|
|
2516
|
+
try {
|
|
2517
|
+
assertRequest();
|
|
2518
|
+
}
|
|
2519
|
+
catch {
|
|
2520
|
+
return reject();
|
|
2521
|
+
}
|
|
2522
|
+
const result = await next();
|
|
2523
|
+
try {
|
|
2524
|
+
assertRequest();
|
|
2525
|
+
}
|
|
2526
|
+
catch {
|
|
2527
|
+
return reject();
|
|
2528
|
+
}
|
|
2529
|
+
return result;
|
|
2454
2530
|
}
|
|
2455
|
-
|
|
2456
|
-
|
|
2531
|
+
finally {
|
|
2532
|
+
clearPending();
|
|
2457
2533
|
}
|
|
2458
|
-
return result;
|
|
2459
2534
|
}, { prepend: true });
|
|
2460
2535
|
const preExecute = agent.ctx.on('tools/pre-execute', async (_payload, next) => {
|
|
2461
2536
|
try {
|
|
@@ -2485,7 +2560,7 @@ export class DshDeliveryRuntime {
|
|
|
2485
2560
|
return 'assistant-delivery: scheduled goal wake authorization changed';
|
|
2486
2561
|
}
|
|
2487
2562
|
});
|
|
2488
|
-
return () => { request(); preExecute(); guard(); };
|
|
2563
|
+
return () => { input.signal.removeEventListener('abort', clearPending); clearPending(); preStep(); request(); preExecute(); guard(); };
|
|
2489
2564
|
}
|
|
2490
2565
|
waitForScheduledGoalTerminal(agent, input, signal) {
|
|
2491
2566
|
return new Promise(resolve => {
|
|
@@ -2988,8 +3063,8 @@ export class DshDeliveryRuntime {
|
|
|
2988
3063
|
model: selected.model,
|
|
2989
3064
|
maxTokens: this.options.maxOutputTokens,
|
|
2990
3065
|
},
|
|
2991
|
-
setup: async (agentCtx) => {
|
|
2992
|
-
await this.setupAgent(agentCtx, binding.workspace, presetId, externalPrincipalId(binding.principal), selected, agentPresets);
|
|
3066
|
+
setup: async (agentCtx, preparedAgent) => {
|
|
3067
|
+
await this.setupAgent(agentCtx, preparedAgent, binding.workspace, presetId, externalPrincipalId(binding.principal), selected, agentPresets);
|
|
2993
3068
|
},
|
|
2994
3069
|
});
|
|
2995
3070
|
resumed = true;
|
|
@@ -3329,12 +3404,12 @@ export class DshDeliveryRuntime {
|
|
|
3329
3404
|
handle = await this.resumeAgent({ resumeSessionId: SessionId(binding.sessionId), signal,
|
|
3330
3405
|
agentOptions: { provider: selected.provider, model: selected.model,
|
|
3331
3406
|
maxTokens: this.options.maxOutputTokens },
|
|
3332
|
-
setup: async (agentCtx) => {
|
|
3333
|
-
await this.setupAgent(agentCtx, binding.workspace, presetId, externalPrincipalId(binding.principal), selected, agentPresets);
|
|
3407
|
+
setup: async (agentCtx, preparedAgent) => {
|
|
3408
|
+
await this.setupAgent(agentCtx, preparedAgent, binding.workspace, presetId, externalPrincipalId(binding.principal), selected, agentPresets);
|
|
3334
3409
|
const llm = this.ctx.get('llm');
|
|
3335
3410
|
if (llm === undefined)
|
|
3336
3411
|
throw new Error('assistant-delivery: llm service is required');
|
|
3337
|
-
requireAdapterToolCallProtocol(llm, selected.provider, selected.model, presetId, agentCtx.tools.schemas(agentCtx.agent).length);
|
|
3412
|
+
requireAdapterToolCallProtocol(llm, selected.provider, selected.model, presetId, agentCtx.tools.schemas(preparedAgent ?? agentCtx.agent).length);
|
|
3338
3413
|
} });
|
|
3339
3414
|
const agent = handle.agent;
|
|
3340
3415
|
await this.reconcileNativeFullPermissionReviewer(agent.session);
|
|
@@ -3609,6 +3684,21 @@ export class DshDeliveryRuntime {
|
|
|
3609
3684
|
if (causedByDurableIdentity(error)) {
|
|
3610
3685
|
return { outcome: 'not-processed', failureCode: 'agent-identity-mismatch', retryable: false };
|
|
3611
3686
|
}
|
|
3687
|
+
if (errorChainHasName(error, 'SessionFormatUnsupportedError')) {
|
|
3688
|
+
this.ctx.logger.warn(`assistant-delivery: session-format-unsupported for session ${sessionFingerprint(binding.sessionId)}`);
|
|
3689
|
+
try {
|
|
3690
|
+
this.options.replyCommand(binding, envelope.eventId, sessionFormatUnsupportedReply());
|
|
3691
|
+
// The durable reply is the only user effect. Dead-letter the original
|
|
3692
|
+
// inbound event so a legacy format cannot consume the normal retry
|
|
3693
|
+
// budget or produce a second notification.
|
|
3694
|
+
return { outcome: 'not-processed', failureCode: 'session-format-unsupported', retryable: false };
|
|
3695
|
+
}
|
|
3696
|
+
catch {
|
|
3697
|
+
// Do not mark a terminal diagnosis without its owner-authorized,
|
|
3698
|
+
// durable reply; Coordinator may retry this pre-dispatch failure.
|
|
3699
|
+
return { outcome: 'not-processed', failureCode: 'session-format-unsupported-notice-failed', retryable: true };
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3612
3702
|
if (error instanceof ImageCapabilityAdmissionError) {
|
|
3613
3703
|
try {
|
|
3614
3704
|
this.options.replyCommand(binding, envelope.eventId, imageCapabilityReply(error));
|