@lemoncat7/dsh-partner 1.8.0 → 1.8.3

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.
Files changed (65) hide show
  1. package/README.md +17 -2
  2. package/docs/architecture.md +18 -4
  3. package/lib/agent-runtime.d.ts +7 -2
  4. package/lib/agent-runtime.d.ts.map +1 -1
  5. package/lib/agent-runtime.js +93 -87
  6. package/lib/agent-runtime.js.map +1 -1
  7. package/lib/api/features/workspace-api.d.ts.map +1 -1
  8. package/lib/api/features/workspace-api.js +1 -10
  9. package/lib/api/features/workspace-api.js.map +1 -1
  10. package/lib/api.js +8 -11
  11. package/lib/api.js.map +1 -1
  12. package/lib/client.d.ts.map +1 -1
  13. package/lib/client.js +780 -733
  14. package/lib/client.js.map +4 -4
  15. package/lib/collaboration/composition.d.ts.map +1 -1
  16. package/lib/collaboration/composition.js +13 -5
  17. package/lib/collaboration/composition.js.map +1 -1
  18. package/lib/companions/management-tool.d.ts +1 -1
  19. package/lib/companions/management-tool.d.ts.map +1 -1
  20. package/lib/companions/management-tool.js +1 -1
  21. package/lib/companions/management-tool.js.map +1 -1
  22. package/lib/companions/management.d.ts +4 -2
  23. package/lib/companions/management.d.ts.map +1 -1
  24. package/lib/companions/management.js +2 -2
  25. package/lib/companions/management.js.map +1 -1
  26. package/lib/companions/session-configuration.d.ts +19 -0
  27. package/lib/companions/session-configuration.d.ts.map +1 -0
  28. package/lib/companions/session-configuration.js +38 -0
  29. package/lib/companions/session-configuration.js.map +1 -0
  30. package/lib/index.d.ts.map +1 -1
  31. package/lib/index.js +1 -3
  32. package/lib/index.js.map +1 -1
  33. package/lib/pendant/coordinates.d.ts +9 -0
  34. package/lib/pendant/coordinates.d.ts.map +1 -0
  35. package/lib/pendant/coordinates.js +20 -0
  36. package/lib/pendant/coordinates.js.map +1 -0
  37. package/lib/pendant/notice-motion.d.ts.map +1 -1
  38. package/lib/pendant/notice-motion.js +12 -6
  39. package/lib/pendant/notice-motion.js.map +1 -1
  40. package/lib/pendant/renderer.d.ts.map +1 -1
  41. package/lib/pendant/renderer.js +8 -3
  42. package/lib/pendant/renderer.js.map +1 -1
  43. package/lib/pendant/sheen.d.ts +1 -1
  44. package/lib/pendant/sheen.d.ts.map +1 -1
  45. package/lib/pendant/sheen.js +9 -8
  46. package/lib/pendant/sheen.js.map +1 -1
  47. package/lib/pendant/use-placement.d.ts.map +1 -1
  48. package/lib/pendant/use-placement.js +3 -4
  49. package/lib/pendant/use-placement.js.map +1 -1
  50. package/lib/pendant/widget.js +1 -1
  51. package/lib/pendant/widget.js.map +1 -1
  52. package/lib/pendant-renderer.js +168 -168
  53. package/lib/store.d.ts +3 -0
  54. package/lib/store.d.ts.map +1 -1
  55. package/lib/store.js +4 -0
  56. package/lib/store.js.map +1 -1
  57. package/lib/ui/capability-editor.d.ts +7 -0
  58. package/lib/ui/capability-editor.d.ts.map +1 -0
  59. package/lib/ui/capability-editor.js +85 -0
  60. package/lib/ui/capability-editor.js.map +1 -0
  61. package/lib/ui/companion-draft.d.ts +12 -0
  62. package/lib/ui/companion-draft.d.ts.map +1 -0
  63. package/lib/ui/companion-draft.js +2 -0
  64. package/lib/ui/companion-draft.js.map +1 -0
  65. package/package.json +1 -1
package/README.md CHANGED
@@ -6,7 +6,22 @@
6
6
 
7
7
  ## 兼容性
8
8
 
9
- 正式版 `1.7.1` 适配 DeepSeek Harness `0.1.2-rc.1`,需要 Node.js `22.19+` 或 `24+`。DSH 官方 Agent、Session、Settings、Tools 与客户端 UI 依赖均锁定到 `0.1.2-rc.1` 接口族。
9
+ 正式版 `1.8.3` 适配 DeepSeek Harness `0.1.2-rc.1`,需要 Node.js `22.19+` 或 `24+`。DSH 官方 Agent、Session、Settings、Tools 与客户端 UI 依赖均锁定到 `0.1.2-rc.1` 接口族。
10
+
11
+ ### 1.8.3 更新
12
+
13
+ - 伙伴身份、能力、Skill 和协作配置保存后,在下一轮执行前统一注册到会话;覆盖已有浏览器会话和历史会话恢复,不在正在执行的轮次中重组工具,也不唤醒闲置会话。高权限管理工具继续在调用时检查当前授权。
14
+ - 「应用能力组合」增加保存中、成功和失败反馈,成功显示「已保存,下一轮生效」;防止重复提交,失败保留草稿,区分保存失败与保存后刷新失败。
15
+ - 新消息轻摆转向文字面,仅在文字面扫光两次;结束及阅读后不自动恢复图案面,不锁定用户手动翻面。
16
+ - 挂点旁增加小数字未读标记,超过 99 显示 99+,全部已读后隐藏;支持深浅色与减少动态效果,不增加常驻动画或渲染循环。
17
+ - 保留自定义图案、现有卡片材质、24/30/60 FPS 与休眠策略,不改 DSH 源码或伙伴数据。162 项自动化测试及隔离浏览器交互回归通过。
18
+
19
+ ### 1.8.2 更新
20
+
21
+ - 修复保存伙伴权限后,已有会话未立即刷新管理工具的问题;仅重组已活动的空闲会话,执行中拒绝修改,不唤醒其他历史会话。
22
+ - 修复桌面覆盖层有偏移时挂点、SVG 绳子和 WebGL 卡片脱节:重新布局时测量固定定位层原点,统一坐标换算;挂点拖动和键盘移动使用容器本地坐标。
23
+ - 不改变绳子物理、卡片材质和帧率设置,不在逐帧渲染中测量布局。已覆盖偏移容器、拖拽、窗口尺寸变化、移动端与完整挂饰回归。
24
+ - 伙伴管理(高权限)仍默认关闭,仅用户可授予或撤回;知识库挂载管理需配合 `dsh-knowledge 2.4.0+`。
10
25
 
11
26
  ### 1.7.1 更新
12
27
 
@@ -90,7 +105,7 @@
90
105
 
91
106
  知识库挂载要求同时安装包含 `dshKnowledgeMountManagement` 接口的知识库插件;旧版或未安装时会明确提示,身份、能力等管理仍可用。挂载通过知识库当前选中的本地或远程后端执行,远程只读令牌不能修改挂载,不会绕过认证或退回本地写入。
92
107
 
93
- 目标伙伴执行中拒绝修改,配置过期须重新读取。配置已保存但会话未能刷新时,工具会返回 `applied: true` 和 `runtime: reopen-required`,应重新打开目标伙伴会话后使用新配置,不要重复提交。此权限不自动开启任何伙伴的记忆、心跳或渠道。
108
+ 目标伙伴执行中拒绝管理工具修改,配置过期须重新读取。配置保存成功后,身份、能力、Skill 与协作关系在下一轮执行前注册,无需为了注入工具重开会话;Preset 和模型作为会话默认配置,不覆盖已有会话的选择。此权限不自动开启任何伙伴的记忆、心跳或渠道。
94
109
 
95
110
  ## 安装
96
111
 
@@ -12,6 +12,20 @@ client -> HTTP feature routers -> application services -> repositories/store
12
12
 
13
13
  ## Module boundaries
14
14
 
15
+ Configuration saves only commit state. The awaited `agent/pre-step` hook compares
16
+ the saved configuration with the installed revision before each new turn, covering
17
+ native history resume as well as local, channel and task-board conversations.
18
+ Unchanged configurations do not re-register tools or read Skill bodies again;
19
+ mid-turn saves never dismantle a running composition. No polling or eager wakeup
20
+ of inactive sessions is needed. Plugin-owned tools recheck capability revocations
21
+ at execution even when an old schema remains in the current turn.
22
+ The UI reports saved/next-turn, separately from request failures and refresh
23
+ failures. Preset and model defaults remain subject to DSH session-selection rules;
24
+ the plugin does not bypass restrictions on changing an existing session's preset.
25
+ `companions/session-configuration.ts` indexes persisted routes and configuration
26
+ revisions without transcript copies. `ui/capability-editor.tsx` owns the capability
27
+ form and save feedback, using the shared companion draft and existing UI tokens.
28
+
15
29
  - `core/`: shared validation, identifiers and bounded collections. It contains
16
30
  no partner feature policy.
17
31
  - `execution/`: the only owner of short-lived DSH agent sessions. Skill forks,
@@ -101,9 +115,9 @@ client -> HTTP feature routers -> application services -> repositories/store
101
115
  Identity, enabled Skill IDs and outgoing grants commit together. Unknown
102
116
  fields, stale revisions, cancellation, missing resources and busy targets
103
117
  fail closed. Authority is checked again inside the serialized store write.
104
- A reload error after commit is reported as saved/reopen-required, not a failed
105
- write; browser-owned Agent handles are not forcibly destroyed or reported as
106
- hot-reloaded. Unspecified settings, including automation, remain unchanged.
118
+ A runtime confirmation error after commit is reported as saved/next-turn with
119
+ a warning, not a failed write. Browser-owned Agent handles are not destroyed.
120
+ Unspecified settings, including automation, remain unchanged.
107
121
  - Knowledge mount management is a separate provider-backed operation. The
108
122
  adapter derives the target's default project and existing session scopes on
109
123
  the server, never from model-supplied paths. It calls the optional
@@ -140,7 +154,7 @@ client -> HTTP feature routers -> application services -> repositories/store
140
154
  - 点击层不绘制材质或装饰边框,鼠标拖动不触发键盘聚焦,键盘操作保留可见焦点。卸载时一并清理小画布、绳带节点和物理资源。
141
155
  - `pendant/use-placement.ts` 只负责挂点位置:拖动顶部挂点或用方向键移动整件挂饰,与卡牌拉伸手势分离。位置按可用视口比例保存在本地浏览器,刷新恢复,窄屏及旋转时约束到可见范围;逐帧移动不触发 React 状态更新,完成时才写存储,不查询宿主私有 DOM。
142
156
  - 卡牌正面只负责图案,消息更新不会重绘或覆盖正面纹理;内侧单独绘制未读数量、伙伴名和简短状态。图案与消息使用独立纹理,不自动弹出消息或额外角标。
143
- - `pendant/notice-motion.ts` 统一处理新消息提醒:等待被握持或快速甩动的卡牌空闲,轻摆并以短暂的物理角速度辅助转回正面,再由 `pendant/sheen.ts` 在正面轻扫光两次。提醒不修改卡牌的自由拖拽物理结构,多条到达合并一次动作,抓取可中断;后台、全部已读及减少动态效果时取消。效果共用卡面圆角几何,不使用全屏后处理、独立计时器或逐帧纹理重绘。
157
+ - `pendant/notice-motion.ts` 统一处理新消息提醒:等待被握持或快速甩动的卡牌空闲,轻摆并以短暂的物理角速度辅助转向文字面(背面,Y 轴半周),再由 `pendant/sheen.ts` 仅在文字面轻扫光两次。结束或阅读后不自动恢复图案面,也不持续锁定朝向;抓取可中断,用户仍能自由翻面。多条到达合并一次动作;后台、全部已读及减少动态效果时取消。效果共用卡面圆角几何,不使用全屏后处理、独立计时器或逐帧纹理重绘。挂点旁保留静态小数字未读标记(超过 99 显示 99+,全部已读后隐藏),翻面及减少动态效果时仍可见,不拦截拖动、不唤醒渲染循环;读屏复用消息按钮和现有单一播报区。
144
158
  - `pendant/reader.tsx` 点击打开最新未读正文(无未读时展示列表),保留可见、可玩的挂饰;桌面优先放在卡牌旁边,窄屏选择卡牌上方或下方的可用空间。正文独立滚动,来源操作留在底部;使用独立冷灰纸面材质,支持 Escape 关闭、键盘焦点返回、卡牌再次点击关闭和来源导航。静止挂卡即使在阅读时也会自然休眠。
145
159
  - `notifications/service.ts` 从已提交的任务/定时执行变化和完整伙伴回复生成终态通知;不改变任务执行,不暴露内部验收交接。普通回复按会话和轮次去重,任务按 ID/修订/终态去重。
146
160
  - `notifications/store.ts` 在主状态文件同目录保存 `partner-inbox.sqlite`,权限 0600,最多 200 条摘要(每条最多 2000 字符)及已读状态。它不是新的会话历史;完整内容仍在原任务/会话中。
@@ -1,4 +1,5 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
+ import type { Agent } from '@deepseek-ai/dsh-agent';
2
3
  import type { AgentDefaultModelConfig } from '@deepseek-ai/dsh-agent-default-model';
3
4
  import type { AgentPresets } from '@deepseek-ai/dsh-agent-presets';
4
5
  import type { SessionId } from '@deepseek-ai/dsh-session';
@@ -66,6 +67,10 @@ export declare class PartnerAgentRuntime {
66
67
  private readonly restoredCompositions;
67
68
  private readonly restoredCompositionJobs;
68
69
  private readonly disposeAgentListener;
70
+ private readonly disposeConfigurationListener;
71
+ private readonly configurations;
72
+ private readonly preparedTurns;
73
+ private closed;
69
74
  private questionAnswerer;
70
75
  constructor(ctx: RuntimeContext, store: PartnerStore, defaultCwd: string, memory?: PartnerMemoryStore | undefined, reflection?: MemoryReflectionService | undefined, concerns?: PartnerConcernStore | undefined, composer?: PartnerAgentComposer | undefined);
71
76
  setQuestionAnswerer(answerer: PartnerQuestionAnswerer): void;
@@ -100,7 +105,8 @@ export declare class PartnerAgentRuntime {
100
105
  recordHeartbeatActivity(companion: Companion, route: ChannelSession, execution: HeartbeatExecution, outcome: HeartbeatOutcome, deliveryError?: string): Promise<void>;
101
106
  resetCompanion(companionId: string): Promise<void>;
102
107
  reloadCompanion(companionId: string): Promise<void>;
103
- reloadManagedCompanion(companionId: string): Promise<void>;
108
+ /** Awaited by the host before prompt/tool assembly, never from a running tool. */
109
+ prepareAgentTurn(agent: Agent, turn: number, signal: AbortSignal): Promise<void>;
104
110
  isCompanionBusy(companionId: string): boolean;
105
111
  private releaseCompanion;
106
112
  resetChannel(channelId: string): Promise<void>;
@@ -110,7 +116,6 @@ export declare class PartnerAgentRuntime {
110
116
  private persistInbound;
111
117
  private ensureSession;
112
118
  private ensureAgent;
113
- private ensureRestoredComposition;
114
119
  private composeRestoredAgent;
115
120
  private injectProfileUpdate;
116
121
  private attachSession;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-runtime.d.ts","sourceRoot":"","sources":["../src/agent-runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-runtime.d.ts","sourceRoot":"","sources":["../src/agent-runtime.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { mkdir, realpath, stat, writeFile } from 'node:fs/promises';
3
3
  import { basename, extname, isAbsolute, join, relative, resolve, sep } from 'node:path';
4
4
  import { BlockAssembler, createToolResultMessage, createUserMessage } from '@deepseek-ai/dsh-llm';
5
5
  import { createScope, scopeOf, scopeParentOf } from '@deepseek-ai/dsh-scope';
6
+ import { SessionConfigurationIndex } from './companions/session-configuration.js';
6
7
  import { concernObservationPrompt } from './autonomy.js';
7
8
  import { boundedConcernCheckMinutes } from './concern-domain.js';
8
9
  import { PARTNER_MEDIA_MAX_BYTES, safeMediaName } from './channel-message.js';
@@ -54,6 +55,10 @@ export class PartnerAgentRuntime {
54
55
  restoredCompositions = new Map();
55
56
  restoredCompositionJobs = new Map();
56
57
  disposeAgentListener;
58
+ disposeConfigurationListener;
59
+ configurations;
60
+ preparedTurns = new WeakMap();
61
+ closed = false;
57
62
  questionAnswerer;
58
63
  constructor(ctx, store, defaultCwd, memory, reflection, concerns, composer) {
59
64
  this.ctx = ctx;
@@ -63,8 +68,15 @@ export class PartnerAgentRuntime {
63
68
  this.reflection = reflection;
64
69
  this.concerns = concerns;
65
70
  this.composer = composer;
71
+ this.configurations = new SessionConfigurationIndex(store);
72
+ this.disposeConfigurationListener = typeof this.ctx.on === 'function'
73
+ ? this.ctx.on('agent/pre-step', async ({ agent, turn, signal }, next) => {
74
+ await this.prepareAgentTurn(agent, turn, signal);
75
+ return next();
76
+ }) : () => { };
66
77
  this.disposeAgentListener = typeof this.ctx.on === 'function'
67
78
  ? this.ctx.on('agent/disposed', ({ agent }) => {
79
+ this.preparedTurns.delete(agent);
68
80
  const restored = this.restoredCompositions.get(agent.session.id);
69
81
  if (restored?.agent !== agent)
70
82
  return;
@@ -477,16 +489,38 @@ export class PartnerAgentRuntime {
477
489
  await this.store.update(state => { state.sessions = state.sessions.filter(item => item.companionId !== companionId); });
478
490
  }
479
491
  async reloadCompanion(companionId) {
480
- await this.releaseCompanion(companionId);
492
+ // Compatibility for callers that saved a configuration. The index already
493
+ // observes committed writes; do not tear down or wake any Agent here.
494
+ if (!this.configurations.companion(companionId))
495
+ throw new Error('伙伴不存在');
481
496
  }
482
- async reloadManagedCompanion(companionId) {
483
- await this.reloadCompanion(companionId);
484
- // Browser-owned handles cannot be disposed by this plugin. In particular,
485
- // their preset/model must not be reported as hot-reloaded successfully.
486
- if (this.store.snapshot().sessions.some(route => route.companionId === companionId
487
- && this.ctx.agents.get(route.sessionId) !== undefined)) {
488
- throw new Error('目标伙伴还有由 DSH 管理的活动会话,请重新打开会话使配置生效');
497
+ /** Awaited by the host before prompt/tool assembly, never from a running tool. */
498
+ async prepareAgentTurn(agent, turn, signal) {
499
+ if (this.closed)
500
+ throw new Error('伙伴运行时已关闭');
501
+ if (this.preparedTurns.get(agent) === turn)
502
+ return;
503
+ const configuration = this.configurations.forSession(agent.session.id);
504
+ if (!configuration)
505
+ return;
506
+ signal.throwIfAborted();
507
+ const installed = this.restoredCompositions.get(agent.session.id);
508
+ if (installed?.agent !== agent || installed.revision !== configuration.revision) {
509
+ const profile = await this.memory?.profileSnapshot(configuration.companion.id, memoryScope(configuration.route.channelId, configuration.route.userId)).catch(() => undefined);
510
+ signal.throwIfAborted();
511
+ if (this.closed)
512
+ throw new Error('伙伴运行时已关闭');
513
+ const job = this.composeRestoredAgent(agent, configuration.companion, configuration.route, configuration.revision, profile, signal);
514
+ this.restoredCompositionJobs.set(agent.session.id, job);
515
+ try {
516
+ await job;
517
+ }
518
+ finally {
519
+ if (this.restoredCompositionJobs.get(agent.session.id) === job)
520
+ this.restoredCompositionJobs.delete(agent.session.id);
521
+ }
489
522
  }
523
+ this.preparedTurns.set(agent, turn);
490
524
  }
491
525
  isCompanionBusy(companionId) {
492
526
  return this.store.snapshot().sessions.some(route => route.companionId === companionId
@@ -514,7 +548,10 @@ export class PartnerAgentRuntime {
514
548
  await this.store.update(state => { state.sessions = state.sessions.filter(item => item.channelId !== channelId); });
515
549
  }
516
550
  async close() {
551
+ this.closed = true;
552
+ this.disposeConfigurationListener();
517
553
  this.disposeAgentListener();
554
+ this.configurations.close();
518
555
  await Promise.allSettled(this.restoredCompositionJobs.values());
519
556
  for (const restored of this.restoredCompositions.values())
520
557
  restored.dispose();
@@ -530,6 +567,8 @@ export class PartnerAgentRuntime {
530
567
  async releaseRestoredComposition(sessionId) {
531
568
  await this.restoredCompositionJobs.get(sessionId)?.catch(() => { });
532
569
  const restored = this.restoredCompositions.get(sessionId);
570
+ if (restored)
571
+ this.preparedTurns.delete(restored.agent);
533
572
  restored?.dispose();
534
573
  this.restoredCompositions.delete(sessionId);
535
574
  }
@@ -632,7 +671,6 @@ export class PartnerAgentRuntime {
632
671
  }
633
672
  const live = this.ctx.agents.get(route.sessionId);
634
673
  if (live !== undefined) {
635
- await this.ensureRestoredComposition(live, companion, route, profile);
636
674
  await this.attachSession(companion, route);
637
675
  if (profile)
638
676
  this.injectProfileUpdate(live, route.sessionId, profile);
@@ -644,24 +682,8 @@ export class PartnerAgentRuntime {
644
682
  if (presets === undefined)
645
683
  throw new Error('伙伴会话缺少 Agent Presets 服务');
646
684
  await presets.mount(agentCtx, companion.presetId);
647
- agentCtx.systemPrompt.section({
648
- name: 'partner-identity',
649
- order: -10,
650
- text: renderPartnerPersona(companion, route.kind === 'local' ? 'local' : 'conversation'),
651
- });
652
- agentCtx.systemPrompt.section({
653
- name: 'partner-tool-routing',
654
- order: -9,
655
- text: renderToolProtocol(),
656
- });
657
- if (profile && profile.entries.length > 0)
658
- agentCtx.systemPrompt.section({
659
- name: 'partner-user-profile',
660
- order: -8,
661
- text: renderProfile(profile),
662
- });
663
- this.questionAnswerer?.(agentCtx, route);
664
- await this.composer?.compose(agentCtx, companion);
685
+ // Partner composition is installed at the same awaited pre-step boundary
686
+ // for factory-created and native browser-resumed Agents alike.
665
687
  };
666
688
  let handle;
667
689
  try {
@@ -688,69 +710,53 @@ export class PartnerAgentRuntime {
688
710
  await this.attachSession(companion, route);
689
711
  return handle.agent;
690
712
  }
691
- async ensureRestoredComposition(agent, companion, route, profile) {
692
- const installed = this.restoredCompositions.get(route.sessionId);
693
- if (installed?.agent === agent)
694
- return;
695
- const pending = this.restoredCompositionJobs.get(route.sessionId);
696
- if (pending !== undefined)
697
- return pending;
698
- const job = this.composeRestoredAgent(agent, companion, route, profile);
699
- this.restoredCompositionJobs.set(route.sessionId, job);
700
- try {
701
- await job;
702
- }
703
- finally {
704
- if (this.restoredCompositionJobs.get(route.sessionId) === job)
705
- this.restoredCompositionJobs.delete(route.sessionId);
713
+ async composeRestoredAgent(agent, companion, route, revision, profile, signal) {
714
+ // Already inside the driver's awaited pre-step hook. Waiting for idle or
715
+ // runMaintenance here would deadlock the very turn we are preparing.
716
+ signal.throwIfAborted();
717
+ const agentCtx = agent.ctx;
718
+ const key = scopeOf(agentCtx);
719
+ if (key === undefined)
720
+ throw new Error('伙伴会话缺少 Agent 作用域');
721
+ if (scopeParentOf(key) === undefined) {
722
+ const presets = agentCtx.get('agentPresets');
723
+ if (presets === undefined)
724
+ throw new Error('伙伴会话缺少 Agent Presets 服务');
725
+ await presets.mount(agentCtx, companion.presetId);
706
726
  }
707
- }
708
- async composeRestoredAgent(agent, companion, route, profile) {
709
- await agent.whenIdle();
710
- let dispose;
711
- await agent.runMaintenance(async (signal) => {
712
- if (signal.aborted)
713
- throw signal.reason;
714
- const agentCtx = agent.ctx;
715
- const key = scopeOf(agentCtx);
716
- if (key === undefined)
717
- throw new Error('伙伴会话缺少 Agent 作用域');
718
- if (scopeParentOf(key) === undefined) {
719
- const presets = agentCtx.get('agentPresets');
720
- if (presets === undefined)
721
- throw new Error('伙伴会话缺少 Agent Presets 服务');
722
- await presets.mount(agentCtx, companion.presetId);
723
- }
724
- const disposers = [];
725
- try {
726
- disposers.push(agentCtx.systemPrompt.section({ name: 'partner-identity', order: -10, text: renderPartnerPersona(companion, route.kind === 'local' ? 'local' : 'conversation') }));
727
- disposers.push(agentCtx.systemPrompt.section({ name: 'partner-tool-routing', order: -9, text: renderToolProtocol() }));
728
- if (profile && profile.entries.length > 0)
729
- disposers.push(agentCtx.systemPrompt.section({ name: 'partner-user-profile', order: -8, text: renderProfile(profile) }));
730
- if (this.questionAnswerer)
731
- disposers.push(this.questionAnswerer(agentCtx, route));
732
- if (this.composer)
733
- disposers.push(await this.composer.compose(agentCtx, companion));
734
- }
735
- catch (error) {
736
- for (let index = disposers.length - 1; index >= 0; index -= 1)
737
- disposers[index]?.();
738
- throw error;
739
- }
740
- let disposed = false;
741
- dispose = () => {
742
- if (disposed)
743
- return;
744
- disposed = true;
745
- for (let index = disposers.length - 1; index >= 0; index -= 1)
746
- disposers[index]?.();
747
- };
748
- });
749
- if (dispose === undefined)
750
- throw new Error('伙伴会话恢复组合未完成');
751
727
  const previous = this.restoredCompositions.get(route.sessionId);
752
728
  previous?.dispose();
753
- this.restoredCompositions.set(route.sessionId, { agent, dispose });
729
+ this.restoredCompositions.delete(route.sessionId);
730
+ const disposers = [];
731
+ try {
732
+ disposers.push(agentCtx.systemPrompt.section({ name: 'partner-identity', order: -10, text: renderPartnerPersona(companion, route.kind === 'local' ? 'local' : 'conversation') }));
733
+ disposers.push(agentCtx.systemPrompt.section({ name: 'partner-tool-routing', order: -9, text: renderToolProtocol() }));
734
+ if (profile && profile.entries.length > 0)
735
+ disposers.push(agentCtx.systemPrompt.section({ name: 'partner-user-profile', order: -8, text: renderProfile(profile) }));
736
+ if (this.questionAnswerer)
737
+ disposers.push(this.questionAnswerer(agentCtx, route));
738
+ if (this.composer)
739
+ disposers.push(await this.composer.compose(agentCtx, companion));
740
+ signal.throwIfAborted();
741
+ if (this.closed)
742
+ throw new Error('伙伴运行时已关闭');
743
+ }
744
+ catch (error) {
745
+ for (let index = disposers.length - 1; index >= 0; index -= 1)
746
+ disposers[index]?.();
747
+ throw error;
748
+ }
749
+ let disposed = false;
750
+ const dispose = () => {
751
+ if (disposed)
752
+ return;
753
+ disposed = true;
754
+ for (let index = disposers.length - 1; index >= 0; index -= 1)
755
+ disposers[index]?.();
756
+ };
757
+ // Keep the captured revision: a concurrent save must be applied next turn,
758
+ // never incorrectly recorded as already installed by this composition.
759
+ this.restoredCompositions.set(route.sessionId, { agent, dispose, revision });
754
760
  }
755
761
  injectProfileUpdate(agent, sessionId, profile) {
756
762
  const previous = this.profileVersions.get(sessionId);