@lemoncat7/dsh-partner 2.4.2 → 2.5.0
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 +4 -0
- package/docs/long-task-continuation.md +51 -0
- package/docs/releases/2.5.0.md +13 -0
- package/lib/agent-runtime.d.ts +6 -0
- package/lib/agent-runtime.d.ts.map +1 -1
- package/lib/agent-runtime.js +84 -8
- package/lib/agent-runtime.js.map +1 -1
- package/lib/channels/delivery-policy.d.ts.map +1 -1
- package/lib/channels/delivery-policy.js +1 -0
- package/lib/channels/delivery-policy.js.map +1 -1
- package/lib/channels/manager.d.ts +1 -0
- package/lib/channels/manager.d.ts.map +1 -1
- package/lib/channels/manager.js +15 -0
- package/lib/channels/manager.js.map +1 -1
- package/lib/client-api.d.ts +1 -23
- package/lib/client-api.d.ts.map +1 -1
- package/lib/client-api.js.map +1 -1
- package/lib/client.js +84 -36
- package/lib/client.js.map +3 -3
- package/lib/collaboration/composition.d.ts.map +1 -1
- package/lib/collaboration/composition.js +18 -4
- package/lib/collaboration/composition.js.map +1 -1
- package/lib/collaboration/domain.d.ts +2 -0
- package/lib/collaboration/domain.d.ts.map +1 -1
- package/lib/collaboration/domain.js.map +1 -1
- package/lib/collaboration/service.d.ts.map +1 -1
- package/lib/collaboration/service.js +5 -2
- package/lib/collaboration/service.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -1
- package/lib/scheduler/continuations.d.ts +29 -0
- package/lib/scheduler/continuations.d.ts.map +1 -0
- package/lib/scheduler/continuations.js +266 -0
- package/lib/scheduler/continuations.js.map +1 -0
- package/lib/scheduler/domain.d.ts +27 -0
- package/lib/scheduler/domain.d.ts.map +1 -1
- package/lib/scheduler/service.d.ts +2 -0
- package/lib/scheduler/service.d.ts.map +1 -1
- package/lib/scheduler/service.js +30 -1
- package/lib/scheduler/service.js.map +1 -1
- package/lib/scheduler/wakeup-context.d.ts +7 -0
- package/lib/scheduler/wakeup-context.d.ts.map +1 -0
- package/lib/scheduler/wakeup-context.js +14 -0
- package/lib/scheduler/wakeup-context.js.map +1 -0
- package/lib/scheduler/wakeup.d.ts +11 -0
- package/lib/scheduler/wakeup.d.ts.map +1 -0
- package/lib/scheduler/wakeup.js +52 -0
- package/lib/scheduler/wakeup.js.map +1 -0
- package/lib/skills/builtin.d.ts.map +1 -1
- package/lib/skills/builtin.js +5 -0
- package/lib/skills/builtin.js.map +1 -1
- package/lib/skills/long-task-continuation.d.ts +4 -0
- package/lib/skills/long-task-continuation.d.ts.map +1 -0
- package/lib/skills/long-task-continuation.js +43 -0
- package/lib/skills/long-task-continuation.js.map +1 -0
- package/lib/store.d.ts.map +1 -1
- package/lib/store.js +2 -0
- package/lib/store.js.map +1 -1
- package/lib/tasks/continuation-yield.d.ts +4 -0
- package/lib/tasks/continuation-yield.d.ts.map +1 -0
- package/lib/tasks/continuation-yield.js +27 -0
- package/lib/tasks/continuation-yield.js.map +1 -0
- package/lib/tasks/continuation.d.ts +13 -0
- package/lib/tasks/continuation.d.ts.map +1 -0
- package/lib/tasks/continuation.js +103 -0
- package/lib/tasks/continuation.js.map +1 -0
- package/lib/tasks/scheduling.d.ts.map +1 -1
- package/lib/tasks/scheduling.js +7 -0
- package/lib/tasks/scheduling.js.map +1 -1
- package/lib/tasks/service.d.ts.map +1 -1
- package/lib/tasks/service.js +4 -0
- package/lib/tasks/service.js.map +1 -1
- package/lib/ui/schedule-panel.d.ts.map +1 -1
- package/lib/ui/schedule-panel.js +19 -3
- package/lib/ui/schedule-panel.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
Matrix / Mattermost 私聊支持图片、文件、音频和视频收发;单条入站消息最多 8 个附件、合计 64 MB。音视频先作为文件保存或交付,不自动转写;Matrix 加密房间仍不支持。详见 [渠道说明](docs/direct-channels.md)。
|
|
12
12
|
|
|
13
|
+
## 2.5.0:长任务续接与看板等待协调
|
|
14
|
+
|
|
15
|
+
正式版,已验证宿主 **DSH 0.1.5-rc.1**,Node.js **^22.19.0 或 >=24.0.0**。长时间外部任务支持持久化一次性预约;绑定看板后等待期间不重复派发、不提前送验收,到期只检查外部结果,由看板恢复后续步骤。修复恢复会话首次工具装配时序,内置可选续接技能。详见 [2.5.0 发布说明](docs/releases/2.5.0.md)。
|
|
16
|
+
|
|
13
17
|
## 2.4.0:伙伴 MCP、能力管理与验收恢复
|
|
14
18
|
|
|
15
19
|
正式版,已验证宿主 **DSH 0.1.5-rc.1**。新增 MCP 服务与伙伴授权,能力修改自动保存,资源管理改为自适应弹窗;修复验收分配、自动验收恢复及凭据键随机保存失败。详见 [2.4.0 发布说明](docs/releases/2.4.0.md)。
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# 长任务一次性续接
|
|
2
|
+
|
|
3
|
+
## 看板等待协调
|
|
4
|
+
|
|
5
|
+
看板执行内的 `defer` 支持 `boardTaskId`,服务端还会按正在执行的委派及实际会话自动匹配唯一任务。
|
|
6
|
+
预约持久化时将该委派挂起,任务保留进行中,但调度信息显示“等待外部任务结果”和下次检查时间;不占用看板执行位、不触发恢复重试、不进入验收,也不触发需求阶段完成通知。
|
|
7
|
+
|
|
8
|
+
关联看板的唤醒只检查外部状态:pending 延期原预约,completed 唤醒原委派继续 nextStep,而不是定时会话再做一次 nextStep;真实交付仍须通过原看板验收流程。取消、删除、检查失败、权限撤回将任务置为受阻,不自动重新提交外部任务;暂停预约保留等待。修改工作版本、改派、删除任务会使旧预约及迟到回执失效。
|
|
9
|
+
|
|
10
|
+
绑定信息及工作版本随原状态持久化,重启不会把等待委派当作新工作派发。续接结果通知统一归需求处理,不逐条通知定时检查。普通未关联看板的续接保持原有行为。旧的一次性预约可以在同一会话、同一外部 ID、同一 taskKey 再次 defer 时安全关联当前执行任务;无法确认归属的旧周期计划不会按标题或文本猜测并自动迁移。
|
|
11
|
+
|
|
12
|
+
职责:`tasks/continuation` 维护绑定和跨域事务约束,`tasks/continuation-yield` 释放会话执行等待,调度服务只推进预约状态,看板继续持有交付和验收的责任。状态存储在持久化前统一检查约束,避免删除或编辑入口遗漏导致失效预约继续运行。
|
|
13
|
+
|
|
14
|
+
## 能力与技能
|
|
15
|
+
|
|
16
|
+
伙伴必须启用 `schedules`(定时任务)能力。工具注册、每次执行、服务层创建和调度执行均校验;停用后不会唤醒或发送后续通知。已运行的续接请求中断,外部已提交任务不会自动撤销。
|
|
17
|
+
|
|
18
|
+
内置市场提供可选的“长任务等待与续接”inline 技能。需要时安装并绑定,不自动启用。基础参数协议直接在工具和能力提示中提供,未启用 skills 或未绑定技能不影响基础调用。
|
|
19
|
+
|
|
20
|
+
## 工具协议
|
|
21
|
+
|
|
22
|
+
复用 `partner_schedule`:
|
|
23
|
+
|
|
24
|
+
- `defer`:必须传 `taskKey / externalTaskId / title / check / nextStep`,当前正式伙伴会话由服务端确认。可传 `delayMinutes`(1–1440,默认2)、`deadlineMinutes`(不早于首次预约,最多43200,默认1440)、`maxAttempts`(1–100,默认12)。同伙伴同 taskKey 幂等,终态不重置预算。
|
|
25
|
+
- `resolve`:当前唤醒轮次传 `scheduleId / runToken / outcome / summary`;`pending` 保存原条目延期,`completed` / `blocked` 停止执行。检查完成不等于外部任务完成。
|
|
26
|
+
- `cancel / delete`:停止续接,中断正在执行的轮次;不代表已取消外部任务。
|
|
27
|
+
- `list`:查看自己的计划、检查次数、截止时间及最近结果。已有 update 支持暂停等待中的续接,不能改成周期或绕过终态重新执行。
|
|
28
|
+
|
|
29
|
+
## 架构
|
|
30
|
+
|
|
31
|
+
- `scheduler/service` 保持统一入口和已有周期调度。
|
|
32
|
+
- `scheduler/continuations` 负责持久化续接状态、幂等、预算、轮次 token、撤权取消、执行记录和终态通知重试。
|
|
33
|
+
- `PartnerAgentRuntime.wakeSchedule` 复用原会话的工具与审批;空闲时 followup,运行时 steer 到下一处理点。`scheduler/wakeup` 只等待本计划持久化回执,不等待会话 idle 或 Goal 完成。超时暂停预约但不取消共享会话;原会话删除/归档不换会话。
|
|
34
|
+
- `ChannelManager.notifyContinuation` 复用现有通知目标选择与分片收据。等待不通知,完成/受阻才通知;本地无通知目标时保留会话和计划记录。
|
|
35
|
+
- 内置技能只提供策略,不获得权限,不把所有工具加入白名单。
|
|
36
|
+
|
|
37
|
+
数据复用已有 `schedules` 和 `executionRuns` 持久化/分区存储,不创建散落文件、不更改旧数据布局。新增 `schedule.kind=once` 和可选 continuation 字段;正常周期计划不转换。
|
|
38
|
+
|
|
39
|
+
## 恢复与安全边界
|
|
40
|
+
|
|
41
|
+
恢复时在 system-prompt/assemble 检查伙伴装配版本,若本次新装配则重建这次快照,让首次请求就携带身份与工具;不能只在 agent/pre-step 注册,因为当前宿主在该事件前已经采集了工具。并发装配合并等待,失败阻止模型请求,重建保留宿主的工具过滤与权限。唤醒投递前检查最终可见的 partner_schedule 与 check 明确命名的 MCP 工具,缺失时记录受阻,不发出缺工具的唤醒。旧预约未填 completion 时只核实当前外部任务成功,不把旧 check 的整条后续流程当作完成条件。
|
|
42
|
+
|
|
43
|
+
等待中的计划重启后仍按时间执行;运行中断的计划以新 token 重新进入核验,先查询已有任务/已有产出,禁止再次提交。外部副作用无法在通用适配器层保证 exactly-once,技能明确要求幂等检查;执行异常或未提交 resolve 默认受阻,而非无条件自动重跑后续步骤。
|
|
44
|
+
|
|
45
|
+
检查采用原会话和工具审批,不能绕过未授权的 SSH/MCP/文件操作。计划字段不应写凭据或签名下载地址,只保存引用。相同伙伴同时投递一个续接,收到该预约结果即释放,不被整个对话阻塞。
|
|
46
|
+
|
|
47
|
+
可选 completion 明确本预约的完成条件(默认仅核实本外部任务成功且产出可回查,不复用旧 check 中混入的后续动作);一旦核实先 resolve completed,再做 nextStep。后续新长任务单独预约,与 Goal 无依赖。原会话可携带精确 externalTaskId 提前关闭 waiting 预约,不传 token;running 状态必须使用当前 token。pending 保存延期。timeoutMinutes 默认 10(1–120),超过后暂停并保留原因。过期唤醒在执行前必须 list 核对 token;不保证撤销已提交的外部副作用。
|
|
48
|
+
|
|
49
|
+
首次实现不解析任意用户文本自动撤销外部服务任务;伙伴收到用户取消指令应调用 cancel,管理台可直接删除预约。截止/次数是持久预算,不因重复 defer 或重启重置。
|
|
50
|
+
|
|
51
|
+
验证覆盖能力开关、幂等、迟到 token、取消/撤权、期限/次数、重启恢复、可选技能与通知抑制;浏览器用隔离 API fixture,不向用户渠道发送测试消息。
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# 2.5.0 · 长任务续接与看板等待协调
|
|
2
|
+
|
|
3
|
+
正式版。已验证 DSH **0.1.5-rc.1**,Node.js **^22.19.0 或 >=24.0.0**;保留已有 DSH 0.1.2-rc.1 兼容声明,该旧宿主不作为本次部署验证基线。
|
|
4
|
+
|
|
5
|
+
- 新增 `partner_schedule defer/resolve/cancel` 一次性长任务续接:保存外部任务身份、截止时间、次数预算及轮次 token,重启后核验已有任务,不重新提交外部工作。
|
|
6
|
+
- 看板续接支持 `boardTaskId`,按实际执行会话自动匹配唯一委派。等待释放执行位、保留独占资源,不反复派发、不提前送验收、不发送中间渠道通知。
|
|
7
|
+
- 定时检查只核验外部状态,pending 延期原预约,completed 由看板恢复原任务并继续后续步骤;不会两边同时执行 nextStep。
|
|
8
|
+
- 修改需求、改派或删除任务使旧预约失效;取消、删除预约或撤权安全阻塞等待任务,不自动重提交。普通独立预约保持原有行为。
|
|
9
|
+
- 恢复会话在模型请求装配前准备身份与工具,避免首次唤醒时工具缺失;缺少核验工具时明确记录受阻。
|
|
10
|
+
- 增加可选的“长任务等待与续接”内置技能和预约状态展示,不自动开启能力或扩大工具权限。
|
|
11
|
+
- 旧的一次性预约可在原会话、相同外部 ID 与 taskKey 下重新关联当前任务;不猜测迁移或删除旧周期计划,不自动取消外部服务任务。
|
|
12
|
+
|
|
13
|
+
验证:全量 573 项自动化测试通过,最终构建和 26 项续接定向测试通过。详见 [续接协议与恢复边界](../long-task-continuation.md)。
|
package/lib/agent-runtime.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ScheduledPartnerTask } from './scheduler/domain.js';
|
|
1
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
3
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
3
4
|
import type { AgentDefaultModelConfig } from '@deepseek-ai/dsh-agent-default-model';
|
|
@@ -82,6 +83,8 @@ export declare class PartnerAgentRuntime {
|
|
|
82
83
|
private readonly restoredCompositionJobs;
|
|
83
84
|
private readonly disposeAgentListener;
|
|
84
85
|
private readonly disposeConfigurationListener;
|
|
86
|
+
private readonly disposeAssemblyListener;
|
|
87
|
+
private readonly rebuildingAssemblies;
|
|
85
88
|
private readonly configurations;
|
|
86
89
|
private readonly preparedTurns;
|
|
87
90
|
private readonly observationJobs;
|
|
@@ -98,6 +101,7 @@ export declare class PartnerAgentRuntime {
|
|
|
98
101
|
ensureLocalSessionRecord(companionId: string): Promise<ChannelSession>;
|
|
99
102
|
createLocalSession(companionId: string): Promise<ChannelSession>;
|
|
100
103
|
notifyTaskProgress(task: BoardTask, previousStatus: BoardTask['status']): Promise<void>;
|
|
104
|
+
wakeSchedule(entry: ScheduledPartnerTask, signal: AbortSignal): Promise<void>;
|
|
101
105
|
executeTask(input: {
|
|
102
106
|
sourceId: string;
|
|
103
107
|
companion: Companion;
|
|
@@ -138,6 +142,8 @@ export declare class PartnerAgentRuntime {
|
|
|
138
142
|
reloadCompanion(companionId: string): Promise<void>;
|
|
139
143
|
/** Awaited by the host before prompt/tool assembly, never from a running tool. */
|
|
140
144
|
prepareAgentTurn(agent: Agent, turn: number, signal: AbortSignal): Promise<void>;
|
|
145
|
+
/** Also used by assembly: never return a model-facing snapshot before setup. */
|
|
146
|
+
prepareAgentAssembly(agent: Agent, signal: AbortSignal): Promise<boolean>;
|
|
141
147
|
isCompanionBusy(companionId: string): boolean;
|
|
142
148
|
private releaseCompanion;
|
|
143
149
|
resetChannel(channelId: string): Promise<void>;
|
|
@@ -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,4 +1,8 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { deliverScheduledWake } from './scheduler/wakeup.js';
|
|
3
|
+
import { continuationPrompt } from './scheduler/continuations.js';
|
|
4
|
+
import { assertWakeTools } from './scheduler/wakeup-context.js';
|
|
5
|
+
import { assembleContextFor } from '@deepseek-ai/dsh-agent';
|
|
2
6
|
import { conversationMemoryScope } from './memory-scope.js';
|
|
3
7
|
import { mkdir, realpath, stat, writeFile } from 'node:fs/promises';
|
|
4
8
|
import { isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
@@ -14,6 +18,7 @@ import { PARTNER_MEDIA_MAX_BYTES, safeMediaName } from './channel-message.js';
|
|
|
14
18
|
import { listConcernFileSources } from './concern-sources.js';
|
|
15
19
|
import { CONCERN_CREATED_NOTICE, renderConcernCreatedNotice } from './concern-notification.js';
|
|
16
20
|
import { executeObservationLoop } from './observation-loop.js';
|
|
21
|
+
import { waitForBoardTurn } from './tasks/continuation-yield.js';
|
|
17
22
|
import { assistantTextAfter, renderPartnerPersona, renderToolProtocol, resolvePartnerAgentOptions as resolveAgentOptions } from './execution/agent-support.js';
|
|
18
23
|
import { channelReplyPartsAfter, isInternalTaskNotice } from './channels/delivery-policy.js';
|
|
19
24
|
import { prepareChannelReply } from './channels/outbound-media.js';
|
|
@@ -52,6 +57,8 @@ export class PartnerAgentRuntime {
|
|
|
52
57
|
restoredCompositionJobs = new Map();
|
|
53
58
|
disposeAgentListener;
|
|
54
59
|
disposeConfigurationListener;
|
|
60
|
+
disposeAssemblyListener;
|
|
61
|
+
rebuildingAssemblies = new WeakSet();
|
|
55
62
|
configurations;
|
|
56
63
|
preparedTurns = new WeakMap();
|
|
57
64
|
observationJobs = new Map();
|
|
@@ -68,6 +75,24 @@ export class PartnerAgentRuntime {
|
|
|
68
75
|
this.concerns = concerns;
|
|
69
76
|
this.composer = composer;
|
|
70
77
|
this.configurations = new SessionConfigurationIndex(store);
|
|
78
|
+
// Current hosts snapshot providers BEFORE agent/pre-step. Rebuild the first
|
|
79
|
+
// assembly after installing scoped contributions; returning the old snapshot
|
|
80
|
+
// would still omit tools for one request even though registration succeeded.
|
|
81
|
+
this.disposeAssemblyListener = typeof this.ctx.on === 'function'
|
|
82
|
+
? this.ctx.on('system-prompt/assemble', async (_assembly, context, next) => {
|
|
83
|
+
if (!context.agent || !context.signal || this.rebuildingAssemblies.has(context))
|
|
84
|
+
return next();
|
|
85
|
+
const changed = await this.prepareAgentAssembly(context.agent, context.signal);
|
|
86
|
+
if (!changed)
|
|
87
|
+
return next();
|
|
88
|
+
this.rebuildingAssemblies.add(context);
|
|
89
|
+
try {
|
|
90
|
+
return await this.ctx.systemPrompt.assemble(context);
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
this.rebuildingAssemblies.delete(context);
|
|
94
|
+
}
|
|
95
|
+
}) : () => { };
|
|
71
96
|
this.disposeConfigurationListener = typeof this.ctx.on === 'function'
|
|
72
97
|
? this.ctx.on('agent/pre-step', async ({ agent, turn, signal }, next) => {
|
|
73
98
|
await this.prepareAgentTurn(agent, turn, signal);
|
|
@@ -256,6 +281,31 @@ export class PartnerAgentRuntime {
|
|
|
256
281
|
source: { kind: 'plugin', plugin: '@lemoncat7/dsh-partner', form: 'notice', summary: taskProgressNoticeSummary(task.status) },
|
|
257
282
|
}));
|
|
258
283
|
}
|
|
284
|
+
async wakeSchedule(entry, signal) {
|
|
285
|
+
signal.throwIfAborted();
|
|
286
|
+
const wake = entry.continuation;
|
|
287
|
+
const state = this.store.snapshot();
|
|
288
|
+
const companion = state.companions.find(c => c.id === entry.companionId);
|
|
289
|
+
const route = state.sessions.find(s => s.companionId === entry.companionId && s.sessionId === wake.originSessionId);
|
|
290
|
+
if (!companion || !route || this.isArchived(route))
|
|
291
|
+
throw new Error('原续接会话不存在或已归档');
|
|
292
|
+
const agent = await this.ensureAgent(companion, route);
|
|
293
|
+
if (!this.store.snapshot().sessions.some(s => s.id === route.id && s.sessionId === wake.originSessionId) || this.isArchived(route))
|
|
294
|
+
throw new Error('原续接会话已变更');
|
|
295
|
+
const assembly = await agent.ctx.systemPrompt.assemble(assembleContextFor(agent, signal));
|
|
296
|
+
signal.throwIfAborted();
|
|
297
|
+
assertWakeTools(entry, assembly.tools.map(tool => tool.name));
|
|
298
|
+
await deliverScheduledWake({ store: this.store, id: entry.id, token: wake.runToken, signal,
|
|
299
|
+
timeoutMs: entry.timeoutMinutes * 60_000,
|
|
300
|
+
deliver: () => {
|
|
301
|
+
const message = createUserMessage({ content: [{ type: 'text', text: continuationPrompt(entry) }],
|
|
302
|
+
source: { kind: 'plugin', plugin: '@lemoncat7/dsh-partner', form: 'notice', summary: '伙伴长任务续接' } });
|
|
303
|
+
if (agent.status === 'idle')
|
|
304
|
+
agent.followup(message);
|
|
305
|
+
else
|
|
306
|
+
agent.steer(message);
|
|
307
|
+
}, });
|
|
308
|
+
}
|
|
259
309
|
async executeTask(input) {
|
|
260
310
|
input.signal?.throwIfAborted();
|
|
261
311
|
const route = await this.createLocalSession(input.companion.id);
|
|
@@ -269,6 +319,12 @@ export class PartnerAgentRuntime {
|
|
|
269
319
|
await agent.whenIdle();
|
|
270
320
|
input.signal?.throwIfAborted();
|
|
271
321
|
const startSeq = agent.session.seq;
|
|
322
|
+
await this.store.update(state => {
|
|
323
|
+
const delegation = state.delegations.find(d => d.id === input.sourceId && d.status === 'running');
|
|
324
|
+
if (delegation)
|
|
325
|
+
delegation.executionSessionId = route.sessionId;
|
|
326
|
+
});
|
|
327
|
+
input.signal?.throwIfAborted();
|
|
272
328
|
agent.followup(createUserMessage({
|
|
273
329
|
content: [{ type: 'text', text: input.prompt }],
|
|
274
330
|
source: { kind: 'plugin', plugin: '@lemoncat7/dsh-partner', form: 'notice', summary: input.sourceId.startsWith('requirement:') ? '伙伴汇总需求' : input.sourceId.startsWith('review:') ? '伙伴核验看板任务' : '伙伴执行看板任务' },
|
|
@@ -283,14 +339,17 @@ export class PartnerAgentRuntime {
|
|
|
283
339
|
input.signal?.addEventListener('abort', cancel, { once: true });
|
|
284
340
|
if (input.signal?.aborted)
|
|
285
341
|
cancel();
|
|
342
|
+
let deferred = false;
|
|
286
343
|
try {
|
|
287
|
-
await agent.whenIdle();
|
|
344
|
+
deferred = await waitForBoardTurn(this.store, input.sourceId, agent.whenIdle(), input.signal);
|
|
288
345
|
input.signal?.throwIfAborted();
|
|
289
346
|
}
|
|
290
347
|
finally {
|
|
291
348
|
clearTimeout(timer);
|
|
292
349
|
input.signal?.removeEventListener('abort', cancel);
|
|
293
350
|
}
|
|
351
|
+
if (deferred)
|
|
352
|
+
return;
|
|
294
353
|
if (timedOut)
|
|
295
354
|
throw new Error('伙伴看板任务执行超时');
|
|
296
355
|
output = assistantTextAfter(agent, startSeq).trim();
|
|
@@ -534,19 +593,34 @@ export class PartnerAgentRuntime {
|
|
|
534
593
|
throw new Error('伙伴运行时已关闭');
|
|
535
594
|
if (this.preparedTurns.get(agent) === turn)
|
|
536
595
|
return;
|
|
596
|
+
await this.prepareAgentAssembly(agent, signal);
|
|
597
|
+
this.preparedTurns.set(agent, turn);
|
|
598
|
+
}
|
|
599
|
+
/** Also used by assembly: never return a model-facing snapshot before setup. */
|
|
600
|
+
async prepareAgentAssembly(agent, signal) {
|
|
601
|
+
if (this.closed)
|
|
602
|
+
throw new Error('伙伴运行时已关闭');
|
|
603
|
+
const pending = this.restoredCompositionJobs.get(agent.session.id);
|
|
604
|
+
if (pending) {
|
|
605
|
+
await pending;
|
|
606
|
+
signal.throwIfAborted();
|
|
607
|
+
return true;
|
|
608
|
+
}
|
|
537
609
|
const configuration = this.configurations.forSession(agent.session.id);
|
|
538
610
|
if (!configuration)
|
|
539
|
-
return;
|
|
611
|
+
return false;
|
|
540
612
|
if (this.store.isCompanionRemoving(configuration.companion.id))
|
|
541
613
|
throw new Error('伙伴正在删除,不能启动新轮次');
|
|
542
614
|
signal.throwIfAborted();
|
|
543
615
|
const installed = this.restoredCompositions.get(agent.session.id);
|
|
544
616
|
if (installed?.agent !== agent || installed.revision !== configuration.revision) {
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
617
|
+
const job = (async () => {
|
|
618
|
+
const profile = await this.memory?.profileSnapshot(configuration.companion.id, conversationMemoryScope(configuration.route, this.store.snapshot().sessions)).catch(() => undefined);
|
|
619
|
+
signal.throwIfAborted();
|
|
620
|
+
if (this.closed)
|
|
621
|
+
throw new Error('伙伴运行时已关闭');
|
|
622
|
+
await this.composeRestoredAgent(agent, configuration.companion, configuration.route, configuration.revision, profile, signal);
|
|
623
|
+
})();
|
|
550
624
|
this.restoredCompositionJobs.set(agent.session.id, job);
|
|
551
625
|
try {
|
|
552
626
|
await job;
|
|
@@ -555,8 +629,9 @@ export class PartnerAgentRuntime {
|
|
|
555
629
|
if (this.restoredCompositionJobs.get(agent.session.id) === job)
|
|
556
630
|
this.restoredCompositionJobs.delete(agent.session.id);
|
|
557
631
|
}
|
|
632
|
+
return true;
|
|
558
633
|
}
|
|
559
|
-
|
|
634
|
+
return false;
|
|
560
635
|
}
|
|
561
636
|
isCompanionBusy(companionId) {
|
|
562
637
|
return this.reflection?.isRunning(companionId) === true || this.observationJobs.has(companionId) || this.agentSetupJobs.has(companionId) || this.store.snapshot().sessions.some(route => route.companionId === companionId
|
|
@@ -588,6 +663,7 @@ export class PartnerAgentRuntime {
|
|
|
588
663
|
async close() {
|
|
589
664
|
this.closed = true;
|
|
590
665
|
this.disposeConfigurationListener();
|
|
666
|
+
this.disposeAssemblyListener();
|
|
591
667
|
this.disposeAgentListener();
|
|
592
668
|
this.configurations.close();
|
|
593
669
|
await Promise.allSettled(this.restoredCompositionJobs.values());
|