@lemoncat7/dsh-partner 1.13.0 → 1.14.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.
Files changed (103) hide show
  1. package/README.md +10 -2
  2. package/docs/architecture.md +3 -0
  3. package/docs/releases/1.14.0.md +24 -0
  4. package/docs/releases/1.14.1.md +11 -0
  5. package/lib/agent-runtime.d.ts +23 -2
  6. package/lib/agent-runtime.d.ts.map +1 -1
  7. package/lib/agent-runtime.js +45 -282
  8. package/lib/agent-runtime.js.map +1 -1
  9. package/lib/api.js +34 -2
  10. package/lib/api.js.map +1 -1
  11. package/lib/autonomy.d.ts.map +1 -1
  12. package/lib/autonomy.js +13 -5
  13. package/lib/autonomy.js.map +1 -1
  14. package/lib/client-api.d.ts +8 -1
  15. package/lib/client-api.d.ts.map +1 -1
  16. package/lib/client-api.js.map +1 -1
  17. package/lib/client.js +1790 -1402
  18. package/lib/client.js.map +4 -4
  19. package/lib/companions/session-recovery.d.ts +7 -0
  20. package/lib/companions/session-recovery.d.ts.map +1 -0
  21. package/lib/companions/session-recovery.js +22 -0
  22. package/lib/companions/session-recovery.js.map +1 -0
  23. package/lib/concern-domain.d.ts +9 -0
  24. package/lib/concern-domain.d.ts.map +1 -1
  25. package/lib/concern-domain.js.map +1 -1
  26. package/lib/concern-recording.d.ts +20 -0
  27. package/lib/concern-recording.d.ts.map +1 -0
  28. package/lib/concern-recording.js +37 -0
  29. package/lib/concern-recording.js.map +1 -0
  30. package/lib/concern-store.d.ts +20 -1
  31. package/lib/concern-store.d.ts.map +1 -1
  32. package/lib/concern-store.js +170 -1
  33. package/lib/concern-store.js.map +1 -1
  34. package/lib/heartbeat.d.ts +16 -0
  35. package/lib/heartbeat.d.ts.map +1 -1
  36. package/lib/heartbeat.js +97 -9
  37. package/lib/heartbeat.js.map +1 -1
  38. package/lib/memory-errors.d.ts +6 -0
  39. package/lib/memory-errors.d.ts.map +1 -0
  40. package/lib/memory-errors.js +12 -0
  41. package/lib/memory-errors.js.map +1 -0
  42. package/lib/memory-journal.js +4 -4
  43. package/lib/memory-journal.js.map +1 -1
  44. package/lib/memory-reflection.d.ts.map +1 -1
  45. package/lib/memory-reflection.js +11 -3
  46. package/lib/memory-reflection.js.map +1 -1
  47. package/lib/memory-store.d.ts +4 -0
  48. package/lib/memory-store.d.ts.map +1 -1
  49. package/lib/memory-store.js +11 -3
  50. package/lib/memory-store.js.map +1 -1
  51. package/lib/observation-budget.d.ts +9 -0
  52. package/lib/observation-budget.d.ts.map +1 -0
  53. package/lib/observation-budget.js +9 -0
  54. package/lib/observation-budget.js.map +1 -0
  55. package/lib/observation-errors.d.ts +21 -0
  56. package/lib/observation-errors.d.ts.map +1 -0
  57. package/lib/observation-errors.js +36 -0
  58. package/lib/observation-errors.js.map +1 -0
  59. package/lib/observation-executor.d.ts +7 -0
  60. package/lib/observation-executor.d.ts.map +1 -0
  61. package/lib/observation-executor.js +23 -0
  62. package/lib/observation-executor.js.map +1 -0
  63. package/lib/observation-loop.d.ts +17 -0
  64. package/lib/observation-loop.d.ts.map +1 -0
  65. package/lib/observation-loop.js +180 -0
  66. package/lib/observation-loop.js.map +1 -0
  67. package/lib/recording-snapshot.d.ts +11 -0
  68. package/lib/recording-snapshot.d.ts.map +1 -0
  69. package/lib/recording-snapshot.js +19 -0
  70. package/lib/recording-snapshot.js.map +1 -0
  71. package/lib/ui/memory/concern-board.d.ts +4 -2
  72. package/lib/ui/memory/concern-board.d.ts.map +1 -1
  73. package/lib/ui/memory/concern-board.js +17 -6
  74. package/lib/ui/memory/concern-board.js.map +1 -1
  75. package/lib/ui/memory/concern-deletion.d.ts +12 -0
  76. package/lib/ui/memory/concern-deletion.d.ts.map +1 -0
  77. package/lib/ui/memory/concern-deletion.js +43 -0
  78. package/lib/ui/memory/concern-deletion.js.map +1 -0
  79. package/lib/ui/memory/concern-editor.d.ts +8 -0
  80. package/lib/ui/memory/concern-editor.d.ts.map +1 -0
  81. package/lib/ui/memory/concern-editor.js +37 -0
  82. package/lib/ui/memory/concern-editor.js.map +1 -0
  83. package/lib/ui/memory/concern-panel.d.ts.map +1 -1
  84. package/lib/ui/memory/concern-panel.js +51 -12
  85. package/lib/ui/memory/concern-panel.js.map +1 -1
  86. package/lib/ui/memory/concern-record-fields.d.ts +10 -0
  87. package/lib/ui/memory/concern-record-fields.d.ts.map +1 -0
  88. package/lib/ui/memory/concern-record-fields.js +7 -0
  89. package/lib/ui/memory/concern-record-fields.js.map +1 -0
  90. package/lib/ui/memory/job-feedback.d.ts +5 -0
  91. package/lib/ui/memory/job-feedback.d.ts.map +1 -0
  92. package/lib/ui/memory/job-feedback.js +7 -0
  93. package/lib/ui/memory/job-feedback.js.map +1 -0
  94. package/lib/ui/memory/memory-panel.d.ts.map +1 -1
  95. package/lib/ui/memory/memory-panel.js +4 -2
  96. package/lib/ui/memory/memory-panel.js.map +1 -1
  97. package/lib/ui/memory/record-target-picker.d.ts +7 -0
  98. package/lib/ui/memory/record-target-picker.d.ts.map +1 -0
  99. package/lib/ui/memory/record-target-picker.js +33 -0
  100. package/lib/ui/memory/record-target-picker.js.map +1 -0
  101. package/lib/ui/memory/types.d.ts +4 -0
  102. package/lib/ui/memory/types.d.ts.map +1 -1
  103. package/package.json +3 -1
package/README.md CHANGED
@@ -197,8 +197,8 @@
197
197
  - 伙伴从记忆提炼或每日终审中自动新建关注后,会在当前伙伴会话中发出一次创建通知,并同步到对应的微信渠道,方便及时检查或移除
198
198
  - 心跳只查询到期挂念,使用独立内存推理作用域观察上次检查后的变化;无到期事项时不会调用模型
199
199
  - 心跳根据挂念选择当前可用的安全来源,并在来源内部逐层缩小范围:知识库按“找库→库内搜索→读取条目”,本地按“确定范围→定位文件/内容→读取证据”;发现阶段有独立软截止、单工具超时和整轮安全上限
200
- - 知识文档明确指定本地核验命令时,心跳可使用作用域内临时注册的受控只读命令工具;它不经过 shell,只接受版本、npm 包版本和少量 Git 状态查询,禁止管道、重定向、脚本、任意程序与任意参数,并记录命令结果或拒绝原因
201
- - 挂念明确关联 `@文件` 时,伙伴可先读取再以最小修改持续维护该文件;写权限精确限定到已关联的现存文件,不能创建其他文件或触碰伙伴私有存储
200
+ - 关注可使用来源会话已有的 bash 工具完成文档要求的多步检查,保留 DSH 原有审批,不另行实现命令执行或自动授权。
201
+ - `@文件` 仅作为只读依据;记录写权限只覆盖用户在“需要记录的地方”手动选择的现存文件或笔记,不能创建其他文件或触碰伙伴私有存储
202
202
  - 发现结果先保存为 Observation,经过去重、相关性、新鲜度、可行动性和近期打扰历史的确定性评分,再决定静默记下、下次顺手一提、进入伙伴动态或主动通知
203
203
  - 心跳硬性排除伙伴记忆、挂念数据库、会话归档及其备份,不向无关主题扩散
204
204
  - 未送达的重要提醒会保留并安全补发;普通对话开始时只召回与当前消息相关的延迟提及
@@ -324,3 +324,11 @@ ClawHub、LoopHub、SkillHub 是内置公共来源,默认启用且不能删除
324
324
  `skillUrl` 可相对索引 URL。市场索引上限 1 MiB、单个 `SKILL.md` 上限 512 KiB;未标记为可信的市场即使声明 `context: inline`,安装后也会强制改为 `fork`。
325
325
 
326
326
  市场页面的“代理设置”接受不含账号、密码和路径的 `http://host:port`。配置仅保存在当前客户端的伙伴状态中,同时作用于市场索引、Markdown Skill 和 ZIP 安装包下载;测试连接不会先写入配置。需要鉴权的代理应在本地网关侧处理,不要把凭据写进代理 URL。
327
+
328
+ ## 关注依据与记录位置
329
+
330
+ 关注使用后台轻量模型循环,不创建临时 Agent 或向聊天写入过程消息。每条关注独立执行,最多 12 轮工具交互和一轮无工具收尾,不再共用整批总时限或工具调用次数。单次模型请求最多 180 秒,单次工具最多 60 秒(工具自身可有更短限制),收尾有独立请求时间。每条完成立即保存;失败只保留未完成关注等待重试。只提供关联依据与记录目标,按文档完成代理、登录和查询;工具走来源作用域的 DSH 执行和审批,不自动批准。输出截断需按需分页。依据只读,结果仅写指定目标;检查受阻不能当作无变化。工具审计不复制参数正文。任意命令的文件隔离仍依赖 DSH 沙箱,工具名限制不等同文件系统隔离。
331
+
332
+ “交代一件事”中的 @文件或 @知识文档是只读检查依据;“需要记录的地方”另选现存本地文件或可编辑笔记。没有记录位置时不写文档,旧关注不自动把依据迁移成输出位置。有依据按依据整理,没有依据自主记录核实的现状和进展;笔记使用稳定 ID 绑定,知识库插件需提供 `dshKnowledgeNoteRecording` 宿主接口。心跳的笔记工具只接收 concernId,不允许模型选择其他笔记 ID;本地文件写权限只覆盖用户选择的现存文件。该入口不包含创建、删除、移动或重命名记录目标。首次可初始化已核实现状,后续避免重复追加,写入与通知判断相互独立。
333
+
334
+ 完整核验结果通过 `heartbeat_record_checkpoint` 持久暂存,后台独立同步到记录目标。失败15分钟后仅重试同步,不重新抓取或提醒;实际写入成功才清除任务。详见 [1.14.0 发布说明](docs/releases/1.14.0.md)。
@@ -295,3 +295,6 @@ form and save feedback, using the shared companion draft and existing UI tokens.
295
295
  - `api/features/pendant-api.ts` 沿用原有 API 同源和写操作校验,只提供固定渲染资源、消息查询和批量已读。前端可见时每 4 秒条件查询(ETag);无变化不传正文,失败退避至 30 秒,隐藏或卸载时取消请求。
296
296
  - 验证:`test/pendant-inbox.test.mjs`、`test/pendant-physics.test.mjs`;构建后设置 `PARTNER_PLAYWRIGHT_MODULE` 并运行 `node scripts/verify-pendant.mjs`,使用隔离假数据检查 WebGL、真实拖拽、拉住停顿后的回弹与反向振荡、休眠、键盘、通知导航、移动端和清理。可设置 `PARTNER_PENDANT_VIDEO_DIR` 保存连续交互录像。
297
297
  - 卡面验证:`test/pendant-motion-glare.test.mjs` 覆盖角度往返、固定姿态十秒不漂移、四元数等价、强度边界、减少动态效果和背面关闭;`test/pendant-surface.test.mjs` 覆盖共享 uniform 与背面不变。`scripts/verify-pendant-gloss.mjs` 检查 162 组原色误差、渐变参考对照、不同倾角的光带位移与对比度保护及无额外绘制。浏览器测试覆盖 hover 不改变反光、拖拽改变角度时更新、握持静止高光不循环并正常休眠。
298
+ ## 轻量关注执行
299
+
300
+ `observation-loop.ts` 维护私有消息缓冲,继承来源工具作用域,不启动 Agent turn 或新会话。按需暴露检查工具和指定记录工具,保留 DSH guard/审批。`heartbeat.ts` 逐条调用并立即持久化结果,单条失败不终止后续关注。每条独享 12 轮检查和一轮无工具收尾;模型请求 180 秒、工具执行 60 秒分别计时,无整批总时限和共享调用次数限制。重试退避从执行结束计算,已完成关注按自身 nextCheckAt 调度。结束必须给出 completed/blocked,失败不写成无变化。来源知识挂载沿用原 session,无需临时知识映射。记录内容不回写依据。
@@ -0,0 +1,24 @@
1
+ # 1.14.0
2
+
3
+ ## 持续关注与记录
4
+
5
+ - 轻量后台检查继承来源会话权限,不创建临时 Agent 对话;检查与无工具收尾分阶段计时,保留逐轮耗时及脱敏诊断。
6
+ - 核验结果可通过检查点持久保存,记录同步单独执行。同步失败15分钟后重试,不重新调查来源或发送变化通知。
7
+ - 只写用户手动指定的现存笔记或文件,不通过知识文档引用推导写入目标。同步先读再合并,笔记使用版本校验;更换目标取消旧目标的待同步数据。
8
+ - 支持编辑关注说明、依据和记录位置,查看归档配置及确认删除。删除关注不删除关联文档。
9
+ - 手动检查异步返回,界面查询执行状态,避免长请求等待。
10
+
11
+ ## 记忆与稳定性
12
+
13
+ - 同一联系人任务连续失败3次后,退避期间允许后续任务整理;失败任务仍保留并重试。
14
+ - 旧轮次补处理不覆盖较新的同主题记忆或日摘要。
15
+ - 展示完整积压数量、上次失败原因;模型错误保留脱敏错误码与HTTP状态。
16
+ - 会话恢复仅在确认持久化会话不存在时回退创建,避免重复会话错误。
17
+
18
+ ## 升级说明
19
+
20
+ 保留现有配置和数据,SQLite字段增量迁移。升级前建议备份伙伴数据。
21
+ 旧轮次若没有完整结果快照,不能仅凭变化摘要补建文档,需重新核验。
22
+ 同步写入仍需要有效权限和模型正常返回;外部写入与本地队列不是跨系统原子事务,不承诺严格一次执行。
23
+
24
+ 验证:341项自动化测试通过;部署已确认独立笔记同步成功。
@@ -0,0 +1,11 @@
1
+ # 1.14.1
2
+
3
+ 正式版,适配 DSH **0.1.2-rc.1**;需要 Node.js 22.19+ 或 24+。
4
+
5
+ - 心跳逐条执行关注,每条独享 12 轮检查与一轮无工具收尾,移除整批 180 秒总时限和共享 24 次工具调用额度。
6
+ - 单次模型请求限时 180 秒,单次工具限时 60 秒;工具自身可设置更短时限,原有权限与审批保留。
7
+ - 每条完成立即保存,单条失败不阻止后续关注;重试仅检查仍到期的关注,已保存通知支持补发。
8
+ - 重试退避从执行结束计算,避免长检查结束后立即再次触发。
9
+ - 更新诊断与架构说明;不修改界面、用户配置或知识内容。
10
+
11
+ 验证:342 项自动化测试通过。保留现有数据,无新增迁移。
@@ -40,6 +40,18 @@ export interface HeartbeatToolTrace {
40
40
  status: 'completed' | 'failed';
41
41
  }
42
42
  export interface HeartbeatExecution {
43
+ recording?: Array<{
44
+ concernId: string;
45
+ state: 'synced' | 'pending';
46
+ }>;
47
+ rounds?: Array<{
48
+ round: number;
49
+ phase: 'check' | 'final';
50
+ modelMs: number;
51
+ outputChars: number;
52
+ }>;
53
+ blocked?: string[];
54
+ blockedReasons?: Record<string, string>;
43
55
  concerns: PartnerConcern[];
44
56
  candidates: ConcernObservationCandidate[];
45
57
  observations?: ConcernObservation[];
@@ -73,6 +85,7 @@ export declare class PartnerAgentRuntime {
73
85
  private readonly preparedTurns;
74
86
  private readonly observationJobs;
75
87
  private readonly agentSetupJobs;
88
+ private readonly sessionRecoveryJobs;
76
89
  private closed;
77
90
  private questionAnswerer;
78
91
  constructor(ctx: RuntimeContext, store: PartnerStore, defaultCwd: string, memory?: PartnerMemoryStore | undefined, reflection?: MemoryReflectionService | undefined, concerns?: PartnerConcernStore | undefined, composer?: PartnerAgentComposer | undefined);
@@ -99,14 +112,22 @@ export declare class PartnerAgentRuntime {
99
112
  isArchived(route: ChannelSession): boolean;
100
113
  renewSession(routeId: string): Promise<ChannelSession>;
101
114
  heartbeat(companion: Companion, route: ChannelSession, concerns: PartnerConcern[]): Promise<HeartbeatExecution>;
102
- persistKnowledgeObservations(companion: Companion, route: ChannelSession, concerns: PartnerConcern[], observations: ConcernObservation[]): Promise<void>;
103
115
  concernSources(companion: Companion, query?: string): Promise<ConcernSource[]>;
116
+ recordingSources(companion: Companion, query?: string): Promise<({
117
+ kind: "file";
118
+ locator: string;
119
+ label: string;
120
+ } | {
121
+ kind: "note";
122
+ locator: string;
123
+ label: string;
124
+ })[]>;
125
+ validateRecordingTarget(companion: Companion, raw: unknown): Promise<PartnerConcern['recordTarget']>;
104
126
  private runHeartbeatWhenIdle;
105
127
  observeSessionEvent(session: Session, event: SessionEvent): Promise<void>;
106
128
  private processSessionEvent;
107
129
  recordConcernCreatedNotice(companion: Companion, scopeId: string, concerns: PartnerConcern[]): Promise<boolean>;
108
130
  private driveScopedHeartbeat;
109
- private driveEphemeralHeartbeat;
110
131
  recordHeartbeatActivity(companion: Companion, route: ChannelSession, execution: HeartbeatExecution, outcome: HeartbeatOutcome, deliveryError?: string): Promise<void>;
111
132
  resetCompanion(companionId: string): Promise<void>;
112
133
  removeCompanionWorkspace(companionId: string): Promise<void>;
@@ -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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"}
@@ -1,33 +1,23 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
2
  import { mkdir, realpath, stat, writeFile } from 'node:fs/promises';
3
3
  import { isAbsolute, join, relative, resolve, sep } from 'node:path';
4
- import { BlockAssembler, createToolResultMessage, createUserMessage } from '@deepseek-ai/dsh-llm';
5
- import { createScope, scopeOf, scopeParentOf } from '@deepseek-ai/dsh-scope';
4
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
5
+ import { scopeOf, scopeParentOf } from '@deepseek-ai/dsh-scope';
6
6
  import { SessionConfigurationIndex } from './companions/session-configuration.js';
7
+ import { isMissingSession, SessionRecoveryJobs } from './companions/session-recovery.js';
7
8
  import { removeOwnedWorkspace } from './companions/workspace-cleanup.js';
8
9
  import { assertOwnedDirectory, removeOwnedDirectory } from './companions/directory-cleanup.js';
9
- import { concernObservationPrompt } from './autonomy.js';
10
10
  import { boundedConcernCheckMinutes } from './concern-domain.js';
11
11
  import { taskWorkContext } from './tasks/context.js';
12
12
  import { PARTNER_MEDIA_MAX_BYTES, safeMediaName } from './channel-message.js';
13
13
  import { listConcernFileSources } from './concern-sources.js';
14
14
  import { CONCERN_CREATED_NOTICE, renderConcernCreatedNotice } from './concern-notification.js';
15
- import { HEARTBEAT_LOCAL_COMMAND, heartbeatLocalCommandTool } from './heartbeat-command.js';
15
+ import { executeObservationLoop } from './observation-loop.js';
16
16
  import { assistantTextAfter, renderPartnerPersona, renderToolProtocol, resolvePartnerAgentOptions as resolveAgentOptions } from './execution/agent-support.js';
17
17
  import { channelReplyPartsAfter } from './channels/delivery-policy.js';
18
18
  import { prepareChannelReply } from './channels/outbound-media.js';
19
19
  export { extractOutboundAttachments } from './channels/outbound-media.js';
20
20
  export { renderToolProtocol, resolvePartnerAgentOptions as resolveAgentOptions } from './execution/agent-support.js';
21
- const HEARTBEAT_TIMEOUT_MS = 115_000;
22
- const HEARTBEAT_DISCOVERY_BUDGET_MS = 72_000;
23
- const HEARTBEAT_TOOL_TIMEOUT_MS = 18_000;
24
- const HEARTBEAT_WEB_TOOL_TIMEOUT_MS = 30_000;
25
- const HEARTBEAT_TOOL_RESULT_LIMIT = 5_000;
26
- const HEARTBEAT_KNOWLEDGE_RESULT_LIMIT = 8_000;
27
- const HEARTBEAT_WEB_FETCH_RESULT_LIMIT = 40_000;
28
- const HEARTBEAT_WEB_SOURCE_RESULT_LIMIT = 125_000;
29
- const HEARTBEAT_AUDIT_INPUT_LIMIT = 320;
30
- const HEARTBEAT_AUDIT_OUTPUT_LIMIT = 520;
31
21
  const PARTNER_TASK_TIMEOUT_MS = 30 * 60_000;
32
22
  const HEARTBEAT_READ_ONLY_TOOLS = new Set([
33
23
  'knowledge_base_search',
@@ -41,8 +31,6 @@ const HEARTBEAT_READ_ONLY_TOOLS = new Set([
41
31
  'read',
42
32
  ]);
43
33
  const HEARTBEAT_FILE_UPDATE_TOOLS = new Set(['write', 'edit', 'str_replace_editor']);
44
- const HEARTBEAT_TOOLS = new Set([...HEARTBEAT_READ_ONLY_TOOLS, ...HEARTBEAT_FILE_UPDATE_TOOLS]);
45
- HEARTBEAT_TOOLS.add(HEARTBEAT_LOCAL_COMMAND);
46
34
  export class PartnerAgentRuntime {
47
35
  ctx;
48
36
  store;
@@ -66,6 +54,7 @@ export class PartnerAgentRuntime {
66
54
  preparedTurns = new WeakMap();
67
55
  observationJobs = new Map();
68
56
  agentSetupJobs = new Map();
57
+ sessionRecoveryJobs = new SessionRecoveryJobs();
69
58
  closed = false;
70
59
  questionAnswerer;
71
60
  constructor(ctx, store, defaultCwd, memory, reflection, concerns, composer) {
@@ -328,44 +317,6 @@ export class PartnerAgentRuntime {
328
317
  this.heartbeatQueues.delete(key);
329
318
  }
330
319
  }
331
- async persistKnowledgeObservations(companion, route, concerns, observations) {
332
- const service = this.ctx.get('dshKnowledgeTracking');
333
- if (service === undefined || observations.length === 0)
334
- return;
335
- const agent = await this.ensureAgent(companion, route);
336
- const byId = new Map(concerns.map(item => [item.id, item]));
337
- const controller = new AbortController();
338
- const timeout = setTimeout(() => controller.abort(new Error('知识库观察记录超时')), 30_000);
339
- timeout.unref?.();
340
- try {
341
- for (const observation of observations) {
342
- if (observation.decision === 'drop')
343
- continue;
344
- const concern = byId.get(observation.concernId);
345
- if (concern === undefined)
346
- continue;
347
- const references = concern.resources.filter(item => item.kind === 'knowledge').map(item => item.locator).slice(0, 4);
348
- if (references.length === 0 && concern.watchKind !== 'knowledge')
349
- continue;
350
- for (const reference of references.length > 0 ? references : [undefined]) {
351
- await service.record(agent, {
352
- id: observation.id,
353
- subject: concern.subject,
354
- event: observation.event,
355
- evidence: observation.evidence,
356
- source: observation.source,
357
- ...(reference === undefined ? {} : { reference }),
358
- at: observation.createdAt,
359
- }, controller.signal).catch(error => {
360
- this.ctx.logger.warn(`dsh-partner: knowledge observation fell back to local storage: ${errorMessage(error)}`);
361
- });
362
- }
363
- }
364
- }
365
- finally {
366
- clearTimeout(timeout);
367
- }
368
- }
369
320
  async concernSources(companion, query = '') {
370
321
  const routes = this.store.snapshot().sessions
371
322
  .filter(item => item.companionId === companion.id)
@@ -390,6 +341,24 @@ export class PartnerAgentRuntime {
390
341
  clearTimeout(timeout);
391
342
  }
392
343
  }
344
+ async recordingSources(companion, query = '') {
345
+ const route = this.store.snapshot().sessions.filter(item => item.companionId === companion.id).sort((a, b) => b.lastMessageAt - a.lastMessageAt)[0];
346
+ const files = await listConcernFileSources(route?.cwd ?? partnerCwd(this.defaultCwd, companion.id), query, 24);
347
+ const bridge = this.ctx.get('dshKnowledgeNoteRecording');
348
+ const notes = bridge?.version === 1 ? await bridge.list(query, AbortSignal.timeout(8000)) : [];
349
+ return [...files.map(file => ({ kind: 'file', locator: file.label, label: file.label })), ...notes.map(note => ({ kind: 'note', locator: note.id, label: note.name }))];
350
+ }
351
+ async validateRecordingTarget(companion, raw) {
352
+ if (raw === undefined || raw === null)
353
+ return undefined;
354
+ if (!isRecord(raw) || typeof raw.locator !== 'string' || typeof raw.label !== 'string')
355
+ throw new Error('记录位置无效,请重新选择');
356
+ const choices = await this.recordingSources(companion, raw.kind === 'file' ? raw.locator : raw.label);
357
+ const selected = choices.find(item => item.kind === raw.kind && item.locator === raw.locator);
358
+ if (!selected)
359
+ throw new Error('记录位置已不存在或不可写,请重新选择');
360
+ return selected;
361
+ }
393
362
  async runHeartbeatWhenIdle(key, companion, route, concerns) {
394
363
  for (;;) {
395
364
  await this.queues.get(key)?.catch(() => { });
@@ -486,38 +455,9 @@ export class PartnerAgentRuntime {
486
455
  return true;
487
456
  }
488
457
  async driveScopedHeartbeat(conversation, companion, concerns) {
489
- const scope = await createHeartbeatScope(this.ctx, conversation, concerns);
490
- try {
491
- return await this.driveEphemeralHeartbeat(scope.agent, companion, concerns);
492
- }
493
- finally {
494
- await scope.dispose();
495
- }
496
- }
497
- async driveEphemeralHeartbeat(agent, companion, concerns) {
498
- const controller = new AbortController();
499
- const timeout = setTimeout(() => controller.abort(new Error('伙伴心跳超过安全时限')), HEARTBEAT_TIMEOUT_MS);
500
- timeout.unref?.();
501
- try {
502
- const execution = await runHeartbeatInference(this.ctx, agent, companion, concerns, controller.signal);
503
- return controller.signal.aborted
504
- ? { ...execution, error: '伙伴心跳超过安全时限,已收束并终止' }
505
- : execution;
506
- }
507
- catch (error) {
508
- const now = Date.now();
509
- return {
510
- concerns,
511
- candidates: [],
512
- startedAt: now,
513
- completedAt: now,
514
- tools: [],
515
- error: controller.signal.aborted ? '伙伴心跳超过安全时限,已收束并终止' : errorMessage(error),
516
- };
517
- }
518
- finally {
519
- clearTimeout(timeout);
520
- }
458
+ const access = await resolveHeartbeatFileAccess(conversation.session.header.cwd, concerns);
459
+ return executeObservationLoop({ ctx: this.ctx, conversation, companion, concerns, guard: (name, args) => heartbeatToolDenial(name, args, access), parse: parseConcernObservations, checkpoint: async (item, snapshot) => { if (!this.concerns)
460
+ throw new Error('关注存储不可用'); await this.concerns.checkpointRecording(item, snapshot); } });
521
461
  }
522
462
  async recordHeartbeatActivity(companion, route, execution, outcome, deliveryError) {
523
463
  const conversation = await this.ensureAgent(companion, route);
@@ -734,7 +674,7 @@ export class PartnerAgentRuntime {
734
674
  const id = companion.id;
735
675
  this.agentSetupJobs.set(id, (this.agentSetupJobs.get(id) ?? 0) + 1);
736
676
  try {
737
- return await this.ensureAgentReady(companion, route);
677
+ return await this.sessionRecoveryJobs.run(route.sessionId, () => this.ensureAgentReady(companion, route));
738
678
  }
739
679
  finally {
740
680
  const left = (this.agentSetupJobs.get(id) ?? 1) - 1;
@@ -779,7 +719,10 @@ export class PartnerAgentRuntime {
779
719
  setup,
780
720
  });
781
721
  }
782
- catch {
722
+ catch (error) {
723
+ // Never turn a preset/loading/permission failure into a duplicate create.
724
+ if (!isMissingSession(error, route.sessionId))
725
+ throw error;
783
726
  handle = await this.ctx.agents.create({
784
727
  sessionId: route.sessionId,
785
728
  meta: {
@@ -960,123 +903,13 @@ export function renewedSession(previous, now = Date.now()) {
960
903
  export function partnerCwd(root, companionId) {
961
904
  return join(root, 'partners', companionId);
962
905
  }
963
- async function createHeartbeatScope(ctx, conversation, concerns) {
964
- const parent = scopeOf(conversation.ctx);
965
- if (parent === undefined)
966
- throw new Error('伙伴心跳无法解析当前 Agent 作用域');
967
- const availableTools = [...HEARTBEAT_TOOLS].filter(name => ctx.tools.get(name, conversation) !== undefined);
968
- const policy = heartbeatToolPolicy(concerns, availableTools);
969
- const allowedTools = [...policy.allowed];
970
- const cwd = conversation.session.header.cwd;
971
- if (!cwd)
972
- throw new Error('伙伴心跳缺少当前伙伴工作目录');
973
- const fileAccess = await resolveHeartbeatFileAccess(cwd, concerns);
974
- const agent = {};
975
- const scope = createScope(ctx, agent, { parent });
976
- const agentCtx = scope.ctx.extend({ agent });
977
- Object.assign(agent, {
978
- id: conversation.id,
979
- options: conversation.options,
980
- session: conversation.session,
981
- inbox: conversation.inbox,
982
- status: 'idle',
983
- ctx: agentCtx,
984
- cancel: () => { },
985
- whenIdle: async () => { },
986
- runMaintenance: async (job) => job(new AbortController().signal),
987
- send: () => { throw new Error('心跳作用域不接受会话消息'); },
988
- followup: () => { throw new Error('心跳作用域不接受会话消息'); },
989
- steer: () => { throw new Error('心跳作用域不接受会话消息'); },
990
- inject: () => { throw new Error('心跳作用域不接受会话消息'); },
991
- });
992
- agentCtx.tools.presentAs('native');
993
- agentCtx.tools.register(heartbeatLocalCommandTool(cwd));
994
- if (allowedTools.length > 0)
995
- agentCtx.tools.restrict({ allow: allowedTools });
996
- agentCtx.tools.guard(exec => {
997
- if (exec.name !== HEARTBEAT_LOCAL_COMMAND && !policy.allowed.has(exec.name))
998
- return `当前挂念的来源策略不允许调用 ${exec.name}`;
999
- return heartbeatToolDenial(exec.name, exec.arguments, fileAccess);
1000
- });
1001
- return { agent, dispose: () => scope.dispose() };
1002
- }
1003
906
  export function heartbeatToolPolicy(concerns, available) {
1004
907
  const installed = new Set(available);
1005
- const hasLinkedFile = concerns.some(item => item.resources?.some(resource => resource.kind === 'file') === true);
908
+ const hasLinkedFile = concerns.some(item => item.recordTarget?.kind === 'file');
1006
909
  return {
1007
910
  allowed: new Set([...installed].filter(name => HEARTBEAT_READ_ONLY_TOOLS.has(name) || (hasLinkedFile && HEARTBEAT_FILE_UPDATE_TOOLS.has(name)))),
1008
911
  };
1009
912
  }
1010
- async function runHeartbeatInference(ctx, agent, companion, concerns, signal) {
1011
- const startedAt = Date.now();
1012
- const traces = [];
1013
- const discoveryDeadline = startedAt + HEARTBEAT_DISCOVERY_BUDGET_MS;
1014
- try {
1015
- const selection = resolveAgentOptions(ctx.agentDefaultModel, companion);
1016
- if (!selection.provider || !selection.model)
1017
- throw new Error('伙伴心跳没有可用的模型路由');
1018
- const tools = ctx.tools.schemas(agent).filter(tool => HEARTBEAT_TOOLS.has(tool.name));
1019
- if (tools.length === 0)
1020
- throw new Error('伙伴心跳没有可用的只读发现工具');
1021
- const messages = [createUserMessage({
1022
- content: [{ type: 'text', text: concernObservationPrompt(concerns, agent.session.header.cwd) }],
1023
- source: { kind: 'plugin', plugin: '@lemoncat7/dsh-partner', form: 'notice', summary: '伙伴观察挂念变化' },
1024
- })];
1025
- for (;;) {
1026
- const discoveryOpen = Date.now() < discoveryDeadline;
1027
- const prepared = await ctx.llm.prepareCall(selection, signal);
1028
- const assembler = new BlockAssembler();
1029
- for await (const chunk of prepared.stream({
1030
- ...prepared.config,
1031
- messages,
1032
- system: renderPartnerPersona(companion, 'heartbeat'),
1033
- tools: discoveryOpen ? tools : [],
1034
- signal,
1035
- }))
1036
- assembler.push(chunk);
1037
- const finish = assembler.finish;
1038
- if (finish.kind === 'error' || finish.kind === 'aborted') {
1039
- throw new Error(`伙伴心跳模型调用失败:${finish.failure.message}`);
1040
- }
1041
- const response = assembler.message({ kind: 'model', provider: prepared.config.provider, model: prepared.config.model });
1042
- messages.push(response);
1043
- const pending = response.content.filter((block) => block.type === 'tool-call');
1044
- if (pending.length === 0) {
1045
- const output = textContent(response.content);
1046
- return {
1047
- concerns,
1048
- candidates: parseConcernObservations(output, new Set(concerns.map(item => item.id))),
1049
- startedAt,
1050
- completedAt: Date.now(),
1051
- output,
1052
- tools: traces,
1053
- };
1054
- }
1055
- for (const call of pending) {
1056
- const argumentsValue = boundHeartbeatToolArguments(call.name, parseHeartbeatToolArguments(call));
1057
- const toolStartedAt = Date.now();
1058
- const remainingDiscoveryMs = discoveryDeadline - toolStartedAt;
1059
- const result = remainingDiscoveryMs <= 0
1060
- ? { isError: true, content: [{ type: 'text', text: '本轮发现阶段的时间预算已用完,请根据已有结果立即输出最终 Observation JSON。' }] }
1061
- : await executeHeartbeatTool(ctx, agent, call, argumentsValue, signal, remainingDiscoveryMs);
1062
- const toolCompletedAt = Date.now();
1063
- const visibleContent = heartbeatToolContent(call.name, result.content);
1064
- traces.push({
1065
- name: call.name,
1066
- input: auditValue(argumentsValue, HEARTBEAT_AUDIT_INPUT_LIMIT),
1067
- output: auditText(textContent(visibleContent) || '工具返回了非文本结果', HEARTBEAT_AUDIT_OUTPUT_LIMIT),
1068
- startedAt: toolStartedAt,
1069
- completedAt: toolCompletedAt,
1070
- status: result.isError ? 'failed' : 'completed',
1071
- });
1072
- messages.push(createToolResultMessage({ callId: call.id, content: visibleContent, isError: result.isError }));
1073
- }
1074
- }
1075
- }
1076
- catch (error) {
1077
- return { concerns, candidates: [], startedAt, completedAt: Date.now(), tools: traces, error: errorMessage(error) };
1078
- }
1079
- }
1080
913
  export function parseConcernObservations(raw, allowedIds) {
1081
914
  const match = raw.trim().match(/\{[\s\S]*\}/);
1082
915
  if (!match)
@@ -1115,18 +948,10 @@ export function parseConcernObservations(raw, allowedIds) {
1115
948
  function boundedScore(value) {
1116
949
  return typeof value === 'number' && Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : .5;
1117
950
  }
1118
- function parseHeartbeatToolArguments(call) {
1119
- try {
1120
- return JSON.parse(call.arguments);
1121
- }
1122
- catch {
1123
- return { __invalidArguments: call.arguments };
1124
- }
1125
- }
1126
951
  async function resolveHeartbeatFileAccess(cwd, concerns) {
1127
952
  const root = await realpath(cwd);
1128
953
  const writable = new Set();
1129
- const locators = concerns.flatMap(item => item.resources ?? []).filter(item => item.kind === 'file').map(item => item.locator);
954
+ const locators = concerns.flatMap(item => item.recordTarget?.kind === 'file' ? [item.recordTarget.locator] : []);
1130
955
  for (const locator of new Set(locators)) {
1131
956
  const lexical = resolve(root, locator);
1132
957
  if (!pathInside(root, lexical) || isPartnerMemoryPath(relative(root, lexical)))
@@ -1144,6 +969,8 @@ async function resolveHeartbeatFileAccess(cwd, concerns) {
1144
969
  return { root, writable };
1145
970
  }
1146
971
  export function heartbeatToolDenial(name, argumentsValue, access) {
972
+ if (['knowledge_note_references', 'knowledge_note_read', 'knowledge_note_update'].includes(name))
973
+ return '关注不处理依据中的笔记引用;记录仅使用手动配置的 recordTarget 和专用记录工具。';
1147
974
  if (!isRecord(argumentsValue))
1148
975
  return undefined;
1149
976
  const isRead = ['glob', 'grep', 'read'].includes(name);
@@ -1165,70 +992,10 @@ export function heartbeatToolDenial(name, argumentsValue, access) {
1165
992
  }
1166
993
  return undefined;
1167
994
  }
1168
- async function executeHeartbeatTool(ctx, agent, call, argumentsValue, signal, remainingDiscoveryMs) {
1169
- const configuredTimeoutMs = call.name === 'web_fetch' || call.name === 'web_source' ? HEARTBEAT_WEB_TOOL_TIMEOUT_MS : HEARTBEAT_TOOL_TIMEOUT_MS;
1170
- const timeoutMs = Math.max(1, Math.min(configuredTimeoutMs, remainingDiscoveryMs));
1171
- const timeoutSignal = AbortSignal.timeout(timeoutMs);
1172
- const toolSignal = AbortSignal.any([signal, timeoutSignal]);
1173
- try {
1174
- return await ctx.tools.execute({ callId: call.id, name: call.name, arguments: argumentsValue, agent, signal: toolSignal });
1175
- }
1176
- catch (error) {
1177
- const message = timeoutSignal.aborted && !signal.aborted
1178
- ? `工具 ${call.name} 超过 ${timeoutMs / 1_000} 秒,已跳过;请按既有规则判断来源不可用,或根据已有结果收束。`
1179
- : `工具 ${call.name} 调用失败:${errorMessage(error)}`;
1180
- return { isError: true, content: [{ type: 'text', text: message }] };
1181
- }
1182
- }
1183
995
  function pathInside(root, target) {
1184
996
  const value = relative(root, target);
1185
997
  return value === '' || (value !== '..' && !value.startsWith(`..${sep}`) && !isAbsolute(value));
1186
998
  }
1187
- function boundHeartbeatToolArguments(name, value) {
1188
- if (!isRecord(value))
1189
- return value;
1190
- const bounded = { ...value };
1191
- if (name === 'knowledge_base_search' || name === 'knowledge_search')
1192
- bounded.limit = boundedInteger(value.limit, 4);
1193
- if (name === 'knowledge_read')
1194
- bounded.maxChars = boundedInteger(value.maxChars, HEARTBEAT_KNOWLEDGE_RESULT_LIMIT);
1195
- if (name === 'web_source')
1196
- bounded.max_chars = boundedInteger(value.max_chars, 120_000);
1197
- if (name === 'read')
1198
- bounded.limit = boundedInteger(value.limit, 80);
1199
- return bounded;
1200
- }
1201
- function heartbeatToolContent(name, content) {
1202
- let remaining = heartbeatToolResultLimit(name);
1203
- const bounded = [];
1204
- for (const block of content) {
1205
- if (remaining <= 0)
1206
- break;
1207
- if (block.type !== 'text') {
1208
- bounded.push(block);
1209
- continue;
1210
- }
1211
- const sanitized = name === 'glob'
1212
- ? block.text.split('\n').filter(line => !isPartnerMemoryPath(line.trim())).join('\n')
1213
- : block.text;
1214
- const text = sanitized.length <= remaining ? sanitized : `${sanitized.slice(0, Math.max(0, remaining - 1))}…`;
1215
- if (text)
1216
- bounded.push({ ...block, text });
1217
- remaining -= text.length;
1218
- }
1219
- if (bounded.length === 0 && name === 'glob')
1220
- return [{ type: 'text', text: '未发现可供心跳检查的普通工作文件;伙伴记忆与会话归档已从结果中排除。' }];
1221
- return bounded;
1222
- }
1223
- function heartbeatToolResultLimit(name) {
1224
- if (name === 'knowledge_read')
1225
- return HEARTBEAT_KNOWLEDGE_RESULT_LIMIT;
1226
- if (name === 'web_fetch')
1227
- return HEARTBEAT_WEB_FETCH_RESULT_LIMIT;
1228
- if (name === 'web_source')
1229
- return HEARTBEAT_WEB_SOURCE_RESULT_LIMIT;
1230
- return HEARTBEAT_TOOL_RESULT_LIMIT;
1231
- }
1232
999
  function isPartnerMemoryPath(value) {
1233
1000
  const normalized = value.replaceAll('\\', '/').replace(/^\.\//, '/');
1234
1001
  return /(?:^|\/)(?:memory(?:\/|-backup(?:-|\/)|$)|concerns(?:\/|$))/i.test(normalized);
@@ -1240,45 +1007,41 @@ function isRecord(value) {
1240
1007
  return typeof value === 'object' && value !== null && !Array.isArray(value);
1241
1008
  }
1242
1009
  export function renderHeartbeatActivity(execution, outcome, deliveryError) {
1243
- const status = outcome === 'notified' ? '已通过微信提醒' : outcome === 'quiet' ? '无需主动提醒' : '执行失败';
1010
+ const status = execution.blocked?.length ? '检查受阻' : outcome === 'notified' ? '已通过微信提醒' : outcome === 'quiet' ? '检查完成,无需主动提醒' : '执行失败';
1244
1011
  const lines = [
1245
1012
  `状态:${status}`,
1246
1013
  `本轮挂念:${execution.concerns.map(item => item.subject).join(';')}`,
1247
1014
  `用时:${formatDuration(execution.completedAt - execution.startedAt)}`,
1248
1015
  `工具:${execution.tools.length > 0 ? `${execution.tools.length} 次调用` : '未调用'}`,
1016
+ ...(execution.recording ?? []).map(item => `记录同步:${execution.concerns.find(concern => concern.id === item.concernId)?.subject ?? item.concernId} · ${item.state === 'synced' ? '已写入手动指定位置' : '待同步(本轮未完成写入,下轮继续处理)'}`),
1017
+ ...(execution.rounds?.length ? [`模型轮次:${execution.rounds.map(item => `${item.round}${item.phase === 'final' ? '(收尾)' : ''} / ${(item.modelMs / 1000).toFixed(1)}秒 / ${item.outputChars}字`).join(';')}`] : []),
1249
1018
  ];
1250
1019
  execution.tools.forEach((trace, index) => {
1251
1020
  lines.push('', `${index + 1}. ${trace.name} · ${trace.status === 'completed' ? '完成' : '失败'} · ${formatDuration(trace.completedAt - trace.startedAt)}`, `输入:${trace.input}`, `结果:${trace.output}`);
1252
1021
  });
1022
+ for (const id of execution.blocked ?? [])
1023
+ lines.push(`受阻事项:${execution.concerns.find(item => item.id === id)?.subject ?? id};${execution.blockedReasons?.[id] ?? '目标数据尚未核实'}`);
1253
1024
  const changed = execution.observations ?? [];
1254
1025
  const conclusion = execution.error || deliveryError
1255
1026
  ? `失败原因:${deliveryError ?? execution.error}`
1256
1027
  : changed.length > 0
1257
1028
  ? `新变化:\n${changed.map(item => `- ${item.event}(${decisionLabel(item.decision)} · ${Math.round(item.interruptScore * 100)})`).join('\n')}`
1258
- : '最终结论:本轮没有发现经过校验的新变化。';
1029
+ : execution.concerns.some(item => item.recordingSnapshot) ? '最终结论:本轮仅执行记录同步,未抓取来源或发送变化提醒。' : '最终结论:本轮没有发现经过校验的新变化。';
1259
1030
  lines.push('', conclusion);
1260
1031
  return lines.join('\n');
1261
1032
  }
1262
1033
  function decisionLabel(value) {
1263
1034
  return value === 'notify' ? '已提醒' : value === 'feed' ? '伙伴动态' : value === 'defer' ? '顺手一提' : value === 'remember' ? '静默记下' : '忽略';
1264
1035
  }
1265
- function auditValue(value, limit) {
1266
- try {
1267
- return auditText(JSON.stringify(value), limit);
1268
- }
1269
- catch {
1270
- return auditText(String(value), limit);
1271
- }
1272
- }
1273
- function auditText(value, limit) {
1274
- const text = value.trim().replace(/\n{3,}/g, '\n\n');
1275
- return text.length <= limit ? text : `${text.slice(0, limit - 1)}…`;
1276
- }
1277
1036
  function formatDuration(milliseconds) {
1278
1037
  if (milliseconds < 1_000)
1279
1038
  return `${Math.max(0, milliseconds)} ms`;
1280
1039
  return `${(milliseconds / 1_000).toFixed(milliseconds < 10_000 ? 1 : 0)} 秒`;
1281
1040
  }
1041
+ function auditText(value, limit) {
1042
+ const text = value.trim().replace(/\n{3,}/g, '\n\n');
1043
+ return text.length <= limit ? text : `${text.slice(0, limit - 1)}…`;
1044
+ }
1282
1045
  function errorMessage(error) { return error instanceof Error ? error.message : String(error); }
1283
1046
  function textContent(content) {
1284
1047
  return content.filter((block) => block.type === 'text' && typeof block.text === 'string')