minimal-agent 0.10.0 → 0.12.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.
Files changed (573) hide show
  1. package/README.md +11 -3
  2. package/package.json +52 -5
  3. package/plugins/computer_use/.claude-plugin/plugin.json +6 -0
  4. package/plugins/computer_use/README.md +94 -0
  5. package/plugins/computer_use/app/_template.md +142 -0
  6. package/plugins/computer_use/app/chrome.md +165 -0
  7. package/plugins/computer_use/app/finder.md +76 -0
  8. package/plugins/computer_use/app/macos-system-settings.md +81 -0
  9. package/plugins/computer_use/app/microsoft-excel.md +80 -0
  10. package/plugins/computer_use/app/microsoft-powerpoint.md +80 -0
  11. package/plugins/computer_use/app/microsoft-word.md +79 -0
  12. package/plugins/computer_use/app/wechat.md +413 -0
  13. package/plugins/computer_use/app/weread.md +319 -0
  14. package/plugins/computer_use/commands/computeruse.md +25 -0
  15. package/plugins/computer_use/commands/cu.md +9 -0
  16. package/plugins/computer_use/plugin.js +26 -0
  17. package/plugins/computer_use/plugin.ts +30 -0
  18. package/plugins/computer_use/src/capture.js +90 -0
  19. package/plugins/computer_use/src/capture.ts +104 -0
  20. package/plugins/computer_use/src/commands.js +91 -0
  21. package/plugins/computer_use/src/commands.ts +103 -0
  22. package/plugins/computer_use/src/daemon.js +134 -0
  23. package/plugins/computer_use/src/daemon.ts +161 -0
  24. package/plugins/computer_use/src/manuals.js +135 -0
  25. package/plugins/computer_use/src/manuals.ts +159 -0
  26. package/plugins/computer_use/src/verify.js +168 -0
  27. package/plugins/computer_use/src/verify.ts +219 -0
  28. package/plugins/computer_use/test/commands.test.ts +73 -0
  29. package/plugins/cron-runner/plugin.ts +38 -0
  30. package/plugins/cron-runner/src/commands.ts +373 -0
  31. package/plugins/cron-runner/src/cronTime.ts +155 -0
  32. package/plugins/cron-runner/src/lock.ts +79 -0
  33. package/plugins/cron-runner/src/runs.ts +99 -0
  34. package/plugins/cron-runner/src/scheduleEngine.ts +76 -0
  35. package/plugins/cron-runner/src/scheduler.ts +376 -0
  36. package/plugins/cron-runner/src/schema.ts +139 -0
  37. package/plugins/cron-runner/src/service.ts +193 -0
  38. package/plugins/cron-runner/src/store.ts +333 -0
  39. package/plugins/cron-runner/src/types.ts +141 -0
  40. package/plugins/cron-runner/test/cronTime.test.ts +41 -0
  41. package/plugins/cron-runner/test/plugin-integration.test.ts +47 -0
  42. package/plugins/cron-runner/test/scheduleEngine.test.ts +41 -0
  43. package/plugins/cron-runner/test/service.test.ts +76 -0
  44. package/plugins/cron-runner/test/store-and-scheduler.test.ts +501 -0
  45. package/plugins/workflow-runner/plugin.js +56 -2
  46. package/plugins/workflow-runner/plugin.ts +113 -0
  47. package/plugins/workflow-runner/src/agentCommon.js +43 -4
  48. package/plugins/workflow-runner/src/agentCommon.ts +435 -0
  49. package/plugins/workflow-runner/src/controlFlow/branch.js +40 -0
  50. package/plugins/workflow-runner/src/controlFlow/branch.ts +46 -0
  51. package/plugins/workflow-runner/src/controlFlow/loop.js +211 -0
  52. package/plugins/workflow-runner/src/controlFlow/loop.ts +248 -0
  53. package/plugins/workflow-runner/src/controlFlow/pause.js +129 -0
  54. package/plugins/workflow-runner/src/controlFlow/pause.ts +141 -0
  55. package/plugins/workflow-runner/src/controlFlow/signal.js +21 -0
  56. package/plugins/workflow-runner/src/controlFlow/signal.ts +29 -0
  57. package/plugins/workflow-runner/src/controlFlow/types.js +18 -0
  58. package/plugins/workflow-runner/src/controlFlow/types.ts +63 -0
  59. package/plugins/workflow-runner/src/dslManifest.ts +127 -0
  60. package/plugins/workflow-runner/src/expressions.ts +622 -0
  61. package/plugins/workflow-runner/src/index.js +13 -4
  62. package/plugins/workflow-runner/src/index.ts +338 -0
  63. package/plugins/workflow-runner/src/jsonPayload.ts +84 -0
  64. package/plugins/workflow-runner/src/loader.js +23 -0
  65. package/plugins/workflow-runner/src/loader.ts +721 -0
  66. package/plugins/workflow-runner/src/multimodal.js +2 -1
  67. package/plugins/workflow-runner/src/multimodal.ts +64 -0
  68. package/plugins/workflow-runner/src/recovery.ts +149 -0
  69. package/plugins/workflow-runner/src/runner.js +75 -659
  70. package/plugins/workflow-runner/src/runner.ts +604 -0
  71. package/plugins/workflow-runner/src/stepExecutors/agent.ts +234 -0
  72. package/plugins/workflow-runner/src/stepExecutors/assert.ts +50 -0
  73. package/plugins/workflow-runner/src/stepExecutors/echo.js +31 -0
  74. package/plugins/workflow-runner/src/stepExecutors/echo.ts +38 -0
  75. package/plugins/workflow-runner/src/stepExecutors/llm.ts +133 -0
  76. package/plugins/workflow-runner/src/stepExecutors/set.js +49 -0
  77. package/plugins/workflow-runner/src/stepExecutors/set.ts +56 -0
  78. package/plugins/workflow-runner/src/stepExecutors/skill.js +5 -6
  79. package/plugins/workflow-runner/src/stepExecutors/skill.ts +140 -0
  80. package/plugins/workflow-runner/src/stepExecutors/tool.js +80 -8
  81. package/plugins/workflow-runner/src/stepExecutors/tool.ts +256 -0
  82. package/plugins/workflow-runner/src/stepExecutors/verify.ts +68 -0
  83. package/plugins/workflow-runner/src/stepPipeline.js +277 -0
  84. package/plugins/workflow-runner/src/stepPipeline.ts +366 -0
  85. package/plugins/workflow-runner/src/taskIdentity.ts +405 -0
  86. package/plugins/workflow-runner/src/toolRuntime.js +48 -0
  87. package/plugins/workflow-runner/src/toolRuntime.ts +64 -0
  88. package/plugins/workflow-runner/src/types.js +37 -1
  89. package/plugins/workflow-runner/src/types.ts +602 -0
  90. package/plugins/workflow-runner/src/workflowState.ts +733 -0
  91. package/plugins/workflow-runner/test/agent.test.ts +587 -0
  92. package/plugins/workflow-runner/test/agentLlmError.test.ts +373 -0
  93. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +65 -0
  94. package/plugins/workflow-runner/test/captureMisbind.test.ts +99 -0
  95. package/plugins/workflow-runner/test/cli.e2e.test.ts +147 -0
  96. package/plugins/workflow-runner/test/context-files.test.ts +320 -0
  97. package/plugins/workflow-runner/test/e2e.test.ts +370 -0
  98. package/plugins/workflow-runner/test/engineRobustness.test.ts +226 -0
  99. package/plugins/workflow-runner/test/expressions.test.ts +397 -0
  100. package/plugins/workflow-runner/test/foundation.test.ts +126 -0
  101. package/plugins/workflow-runner/test/graceful.test.ts +139 -0
  102. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +47 -0
  103. package/plugins/workflow-runner/test/hostCapability.test.ts +108 -0
  104. package/plugins/workflow-runner/test/illustrate.load.test.ts +183 -0
  105. package/plugins/workflow-runner/test/jsonPayload.test.ts +83 -0
  106. package/plugins/workflow-runner/test/loader.test.ts +617 -0
  107. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +33 -0
  108. package/plugins/workflow-runner/test/multimodal.test.ts +342 -0
  109. package/plugins/workflow-runner/test/output-schema.test.ts +213 -0
  110. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +87 -0
  111. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +269 -0
  112. package/plugins/workflow-runner/test/ppt.load.test.ts +1220 -0
  113. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +220 -0
  114. package/plugins/workflow-runner/test/recovery.test.ts +265 -0
  115. package/plugins/workflow-runner/test/runner.test.ts +911 -0
  116. package/plugins/workflow-runner/test/runnerPreflight.test.ts +379 -0
  117. package/plugins/workflow-runner/test/skillTurnDone.test.ts +71 -0
  118. package/plugins/workflow-runner/test/stateLifecycle.test.ts +150 -0
  119. package/plugins/workflow-runner/test/stepPipeline.test.ts +114 -0
  120. package/plugins/workflow-runner/test/taskArbitration.test.ts +338 -0
  121. package/plugins/workflow-runner/test/taskIdentity.test.ts +237 -0
  122. package/plugins/workflow-runner/test/taskLifecycle.test.ts +270 -0
  123. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +221 -0
  124. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +29 -0
  125. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +168 -0
  126. package/plugins/workflow-runner/test/webppt.load.test.ts +250 -0
  127. package/plugins/workflow-runner/test/word.load.test.ts +208 -0
  128. package/plugins/workflow-runner/test/workflows.smoke.test.ts +76 -0
  129. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +207 -0
  130. package/skills/browser-automation/SKILL.md +9 -19
  131. package/skills/web-crawler/SKILL.md +9 -11
  132. package/src/askBridge.ts +249 -0
  133. package/src/bootstrap/cwdArg.js +10 -3
  134. package/src/bootstrap/cwdArg.ts +31 -0
  135. package/src/bootstrap/workingDir.ts +48 -0
  136. package/src/cli/args.js +70 -7
  137. package/src/cli/args.ts +146 -0
  138. package/src/cli/computerUse.js +185 -0
  139. package/src/cli/computerUse.ts +221 -0
  140. package/src/cli/configMenu.js +274 -202
  141. package/src/cli/configMenu.tsx +521 -0
  142. package/src/cli/memoryAccess.js +45 -0
  143. package/src/cli/memoryAccess.ts +53 -0
  144. package/src/cli/print.js +119 -5
  145. package/src/cli/print.ts +597 -0
  146. package/src/cli/quickModelSetup.js +60 -0
  147. package/src/cli/quickModelSetup.tsx +96 -0
  148. package/src/cli/streamJson.js +80 -4
  149. package/src/cli/streamJson.ts +433 -0
  150. package/src/cli/wizards/advisorWizard.js +1 -0
  151. package/src/cli/wizards/advisorWizard.tsx +195 -0
  152. package/src/cli/wizards/agentRuntimeWizard.js +84 -0
  153. package/src/cli/wizards/agentRuntimeWizard.tsx +134 -0
  154. package/src/cli/wizards/browserWizard.js +55 -0
  155. package/src/cli/wizards/browserWizard.tsx +77 -0
  156. package/src/cli/wizards/contextAdvisorWizard.js +84 -0
  157. package/src/cli/wizards/contextAdvisorWizard.tsx +124 -0
  158. package/src/cli/wizards/fieldForm.js +7 -4
  159. package/src/cli/wizards/fieldForm.tsx +250 -0
  160. package/src/cli/wizards/imageWizard.js +4 -5
  161. package/src/cli/wizards/imageWizard.tsx +96 -0
  162. package/src/cli/wizards/openRouterWizard.tsx +48 -0
  163. package/src/cli/wizards/providerPresets.js +1 -8
  164. package/src/cli/wizards/providerPresets.ts +106 -0
  165. package/src/cli/wizards/providerWizard.js +152 -205
  166. package/src/cli/wizards/providerWizard.tsx +266 -0
  167. package/src/cli/wizards/searchWizard.tsx +47 -0
  168. package/src/cli/wizards/ttsWizard.js +4 -3
  169. package/src/cli/wizards/ttsWizard.tsx +61 -0
  170. package/src/config/configDefaults.js +25 -0
  171. package/src/config/configDefaults.ts +33 -0
  172. package/src/config/configDiagnostics.js +117 -0
  173. package/src/config/configDiagnostics.ts +166 -0
  174. package/src/config/configFile.js +52 -32
  175. package/src/config/configFile.ts +633 -0
  176. package/src/config/configManagement.js +126 -0
  177. package/src/config/configManagement.ts +159 -0
  178. package/src/config/configService.js +66 -11
  179. package/src/config/configService.ts +554 -0
  180. package/src/config/numericLimits.js +61 -0
  181. package/src/config/numericLimits.ts +80 -0
  182. package/src/config.ts +109 -0
  183. package/src/context/agentHome.ts +11 -0
  184. package/src/context/archive.ts +144 -0
  185. package/src/context/budgetPlan.js +54 -0
  186. package/src/context/budgetPlan.ts +88 -0
  187. package/src/context/compact.js +179 -106
  188. package/src/context/compact.ts +584 -0
  189. package/src/context/contextBundle.js +119 -0
  190. package/src/context/contextBundle.ts +176 -0
  191. package/src/context/contextLock.ts +84 -0
  192. package/src/context/microCompactLite.ts +218 -0
  193. package/src/context/persistContext.ts +177 -0
  194. package/src/context/reactiveCompact.js +19 -4
  195. package/src/context/reactiveCompact.ts +240 -0
  196. package/src/context/recentDirs.ts +42 -0
  197. package/src/context/sessionPath.ts +206 -0
  198. package/src/context/sessionRegistry.js +8 -2
  199. package/src/context/sessionRegistry.ts +414 -0
  200. package/src/context/snipCompact.ts +163 -0
  201. package/src/context/tokenCounter.ts +106 -0
  202. package/src/context/workspaceIndex.js +2 -2
  203. package/src/context/workspaceIndex.ts +751 -0
  204. package/src/entry.compiled.tsx +20 -0
  205. package/src/harness/claimValidation.js +9 -0
  206. package/src/harness/claimValidation.ts +22 -0
  207. package/src/harness/evidenceLedger.js +92 -0
  208. package/src/harness/evidenceLedger.ts +96 -0
  209. package/src/harness/stallGuard.js +60 -0
  210. package/src/harness/stallGuard.ts +81 -0
  211. package/src/humanIntervention.js +129 -0
  212. package/src/humanIntervention.ts +216 -0
  213. package/src/infra/verification.ts +295 -0
  214. package/src/irreversible/rules.js +216 -0
  215. package/src/irreversible/rules.ts +261 -0
  216. package/src/llm/client.js +40 -3
  217. package/src/llm/client.ts +621 -0
  218. package/src/llm/promptCache.js +27 -0
  219. package/src/llm/promptCache.ts +41 -0
  220. package/src/llm/providers/anthropicFormat.js +41 -5
  221. package/src/llm/providers/anthropicFormat.ts +290 -0
  222. package/src/llm/providers/openaiFormat.js +186 -8
  223. package/src/llm/providers/openaiFormat.ts +428 -0
  224. package/src/loop.js +614 -63
  225. package/src/loop.ts +1454 -0
  226. package/src/main.js +67 -10
  227. package/src/main.tsx +344 -0
  228. package/src/memory/codec.js +204 -0
  229. package/src/memory/codec.ts +249 -0
  230. package/src/memory/constants.js +34 -0
  231. package/src/memory/constants.ts +50 -0
  232. package/src/memory/episodicMemory.js +684 -0
  233. package/src/memory/episodicMemory.ts +815 -0
  234. package/src/memory/fileStore.js +148 -0
  235. package/src/memory/fileStore.ts +184 -0
  236. package/src/memory/memoryService.js +570 -0
  237. package/src/memory/memoryService.ts +859 -0
  238. package/src/memory/migration.js +128 -0
  239. package/src/memory/migration.ts +160 -0
  240. package/src/memory/repository.js +789 -0
  241. package/src/memory/repository.ts +893 -0
  242. package/src/memory/retrieval.js +108 -0
  243. package/src/memory/retrieval.ts +145 -0
  244. package/src/memory/searchIndex.js +107 -0
  245. package/src/memory/searchIndex.ts +153 -0
  246. package/src/memory/topicView.js +82 -0
  247. package/src/memory/topicView.ts +95 -0
  248. package/src/memory/turnJournal.js +95 -0
  249. package/src/memory/turnJournal.ts +120 -0
  250. package/src/memory/types.js +2 -0
  251. package/src/memory/types.ts +186 -0
  252. package/src/messageQueue.ts +123 -0
  253. package/src/multimodal.js +128 -46
  254. package/src/multimodal.ts +349 -0
  255. package/src/plugin-sdk.js +21 -1
  256. package/src/plugin-sdk.ts +134 -0
  257. package/src/plugins/builtinPluginIds.js +47 -0
  258. package/src/plugins/builtinPluginIds.ts +51 -0
  259. package/src/plugins/builtinRegistry.ts +43 -0
  260. package/src/plugins/commandRouter.js +40 -26
  261. package/src/plugins/commandRouter.ts +261 -0
  262. package/src/plugins/hookEngine.ts +341 -0
  263. package/src/plugins/pluginApi.ts +133 -0
  264. package/src/plugins/pluginLifecycle.ts +34 -0
  265. package/src/plugins/pluginLoader.ts +147 -0
  266. package/src/plugins/pluginManifest.js +127 -0
  267. package/src/plugins/pluginManifest.ts +152 -0
  268. package/src/plugins/pluginRunner.js +47 -2
  269. package/src/plugins/pluginRunner.ts +207 -0
  270. package/src/plugins/transcript.ts +208 -0
  271. package/src/prompts/lint.js +169 -0
  272. package/src/prompts/lint.ts +220 -0
  273. package/src/prompts/pluginList.js +32 -16
  274. package/src/prompts/pluginList.ts +86 -0
  275. package/src/prompts/policyRegistry.js +318 -0
  276. package/src/prompts/policyRegistry.ts +358 -0
  277. package/src/prompts/projectInstructions.js +24 -0
  278. package/src/prompts/projectInstructions.ts +81 -0
  279. package/src/prompts/promptAssembly.js +311 -202
  280. package/src/prompts/promptAssembly.ts +510 -0
  281. package/src/prompts/skillList.js +106 -45
  282. package/src/prompts/skillList.ts +198 -0
  283. package/src/prompts/system.js +31 -6
  284. package/src/prompts/system.ts +81 -0
  285. package/src/runtime/agentRuntimeContext.js +53 -0
  286. package/src/runtime/agentRuntimeContext.ts +112 -0
  287. package/src/session/runAgentTurn.js +71 -12
  288. package/src/session/runAgentTurn.ts +181 -0
  289. package/src/session/runTurn.js +29 -0
  290. package/src/session/runTurn.ts +160 -0
  291. package/src/session/runtimeStore.js +149 -0
  292. package/src/session/runtimeStore.ts +197 -0
  293. package/src/session/sessionState.js +79 -3
  294. package/src/session/sessionState.ts +134 -0
  295. package/src/toolGate.ts +50 -0
  296. package/src/tools/advisor/advisor.js +76 -15
  297. package/src/tools/advisor/advisor.ts +512 -0
  298. package/src/tools/agent/agent.js +245 -29
  299. package/src/tools/agent/agent.ts +837 -0
  300. package/src/tools/agent/agentTaskService.js +60 -0
  301. package/src/tools/agent/agentTaskService.ts +113 -0
  302. package/src/tools/agent/agentTypes.js +20 -8
  303. package/src/tools/agent/agentTypes.ts +94 -0
  304. package/src/tools/agent/coordinator.ts +111 -0
  305. package/src/tools/agent/worktree.ts +296 -0
  306. package/src/tools/ask/ask.js +17 -0
  307. package/src/tools/ask/ask.ts +122 -0
  308. package/src/tools/bash/attachImage.js +223 -0
  309. package/src/tools/bash/attachImage.ts +281 -0
  310. package/src/tools/bash/bash.js +132 -14
  311. package/src/tools/bash/bash.ts +642 -0
  312. package/src/tools/bash/semantics.ts +103 -0
  313. package/src/tools/bash/warnings.js +17 -11
  314. package/src/tools/bash/warnings.ts +117 -0
  315. package/src/tools/capabilities.js +42 -0
  316. package/src/tools/capabilities.ts +69 -0
  317. package/src/tools/computeruse/accessibilityPermission.js +261 -0
  318. package/src/tools/computeruse/accessibilityPermission.ts +294 -0
  319. package/src/tools/computeruse/axSearch.js +96 -0
  320. package/src/tools/computeruse/axSearch.ts +120 -0
  321. package/src/tools/computeruse/axSnap.js +272 -0
  322. package/src/tools/computeruse/axSnap.ts +349 -0
  323. package/src/tools/computeruse/capabilityLabels.js +95 -0
  324. package/src/tools/computeruse/capabilityLabels.ts +115 -0
  325. package/src/tools/computeruse/computerUseService.js +2235 -0
  326. package/src/tools/computeruse/computerUseService.ts +2686 -0
  327. package/src/tools/computeruse/computeruse.js +2742 -0
  328. package/src/tools/computeruse/computeruse.ts +3265 -0
  329. package/src/tools/computeruse/diagnosticTrace.js +154 -0
  330. package/src/tools/computeruse/diagnosticTrace.ts +195 -0
  331. package/src/tools/computeruse/diagnostics.js +369 -0
  332. package/src/tools/computeruse/diagnostics.ts +453 -0
  333. package/src/tools/computeruse/grants.js +53 -0
  334. package/src/tools/computeruse/grants.ts +70 -0
  335. package/src/tools/computeruse/humanBoundary.js +159 -0
  336. package/src/tools/computeruse/humanBoundary.ts +199 -0
  337. package/src/tools/computeruse/intervention.js +77 -0
  338. package/src/tools/computeruse/intervention.ts +110 -0
  339. package/src/tools/computeruse/manualSchema.js +709 -0
  340. package/src/tools/computeruse/manualSchema.ts +916 -0
  341. package/src/tools/computeruse/observationImages.js +705 -0
  342. package/src/tools/computeruse/observationImages.ts +889 -0
  343. package/src/tools/computeruse/protocol.js +60 -0
  344. package/src/tools/computeruse/protocol.ts +515 -0
  345. package/src/tools/computeruse/telemetryLog.js +57 -0
  346. package/src/tools/computeruse/telemetryLog.ts +67 -0
  347. package/src/tools/computeruse/vision/appGuide.js +325 -0
  348. package/src/tools/computeruse/vision/appGuide.ts +482 -0
  349. package/src/tools/computeruse/vision/focus.js +291 -0
  350. package/src/tools/computeruse/vision/focus.ts +382 -0
  351. package/src/tools/computeruse/vision/frames.js +248 -0
  352. package/src/tools/computeruse/vision/frames.ts +329 -0
  353. package/src/tools/computeruse/vision/geometry.js +131 -0
  354. package/src/tools/computeruse/vision/geometry.ts +163 -0
  355. package/src/tools/computeruse/vision/imaging.js +201 -0
  356. package/src/tools/computeruse/vision/imaging.ts +281 -0
  357. package/src/tools/computeruse/vision/png.js +274 -0
  358. package/src/tools/computeruse/vision/png.ts +317 -0
  359. package/src/tools/computeruse/vision/raster.js +320 -0
  360. package/src/tools/computeruse/vision/raster.ts +408 -0
  361. package/src/tools/computeruse/vision/settle.js +131 -0
  362. package/src/tools/computeruse/vision/settle.ts +220 -0
  363. package/src/tools/computeruse/vision/telemetry.js +196 -0
  364. package/src/tools/computeruse/vision/telemetry.ts +241 -0
  365. package/src/tools/computeruse/visionOcr.js +115 -0
  366. package/src/tools/computeruse/visionOcr.ts +128 -0
  367. package/src/tools/computeruse/waitFor.js +237 -0
  368. package/src/tools/computeruse/waitFor.ts +291 -0
  369. package/src/tools/download/download.js +10 -6
  370. package/src/tools/download/download.ts +187 -0
  371. package/src/tools/edit/edit.js +30 -18
  372. package/src/tools/edit/edit.ts +349 -0
  373. package/src/tools/edit/multi-edit.js +25 -14
  374. package/src/tools/edit/multi-edit.ts +223 -0
  375. package/src/tools/effectiveToolSet.js +73 -0
  376. package/src/tools/effectiveToolSet.ts +91 -0
  377. package/src/tools/genimage/genimage.ts +257 -0
  378. package/src/tools/genspeech/genspeech.ts +83 -0
  379. package/src/tools/glob/glob.js +176 -29
  380. package/src/tools/glob/glob.ts +283 -0
  381. package/src/tools/grep/grep.js +61 -19
  382. package/src/tools/grep/grep.ts +239 -0
  383. package/src/tools/grep/rgPath.ts +206 -0
  384. package/src/tools/index.js +99 -5
  385. package/src/tools/index.ts +293 -0
  386. package/src/tools/lsp/config.js +113 -0
  387. package/src/tools/lsp/config.ts +113 -0
  388. package/src/tools/lsp/lsp.js +256 -0
  389. package/src/tools/lsp/lsp.ts +274 -0
  390. package/src/tools/lsp/service.js +303 -0
  391. package/src/tools/lsp/service.ts +296 -0
  392. package/src/tools/memory/memory.js +520 -0
  393. package/src/tools/memory/memory.ts +625 -0
  394. package/src/tools/memory/policy.js +53 -0
  395. package/src/tools/memory/policy.ts +72 -0
  396. package/src/tools/notebook/notebookEdit.js +114 -0
  397. package/src/tools/notebook/notebookEdit.ts +126 -0
  398. package/src/tools/powershell/powershell.js +210 -0
  399. package/src/tools/powershell/powershell.ts +239 -0
  400. package/src/tools/presentresult/presentresult.js +145 -0
  401. package/src/tools/presentresult/presentresult.ts +156 -0
  402. package/src/tools/read/read.js +371 -163
  403. package/src/tools/read/read.ts +558 -0
  404. package/src/tools/shared/diffSummary.js +44 -0
  405. package/src/tools/shared/diffSummary.ts +63 -0
  406. package/src/tools/shared/fileActivity.js +51 -0
  407. package/src/tools/shared/fileActivity.ts +66 -0
  408. package/src/tools/shared/fileMutationBus.js +13 -0
  409. package/src/tools/shared/fileMutationBus.ts +14 -0
  410. package/src/tools/shared/fileState.js +73 -65
  411. package/src/tools/shared/fileState.ts +145 -0
  412. package/src/tools/shared/fileUtils.js +81 -4
  413. package/src/tools/shared/fileUtils.ts +504 -0
  414. package/src/tools/shared/killTree.ts +50 -0
  415. package/src/tools/shared/permanentDeleteGuard.js +26 -0
  416. package/src/tools/shared/permanentDeleteGuard.ts +34 -0
  417. package/src/tools/shared/schemas.ts +20 -0
  418. package/src/tools/shared/toolOutputStore.js +97 -0
  419. package/src/tools/shared/toolOutputStore.ts +110 -0
  420. package/src/tools/skill/skill.js +86 -0
  421. package/src/tools/skill/skill.ts +94 -0
  422. package/src/tools/snip/snip.js +67 -0
  423. package/src/tools/snip/snip.ts +80 -0
  424. package/src/tools/tasks/backgroundTaskService.js +275 -0
  425. package/src/tools/tasks/backgroundTaskService.ts +369 -0
  426. package/src/tools/tasks/processEvidence.js +24 -0
  427. package/src/tools/tasks/processEvidence.ts +34 -0
  428. package/src/tools/tasks/taskManagement.js +163 -0
  429. package/src/tools/tasks/taskManagement.ts +180 -0
  430. package/src/tools/tasks/taskOutput.js +113 -0
  431. package/src/tools/tasks/taskOutput.ts +145 -0
  432. package/src/tools/tasks/taskStop.js +74 -0
  433. package/src/tools/tasks/taskStop.ts +99 -0
  434. package/src/tools/tasks/taskStore.js +46 -0
  435. package/src/tools/tasks/taskStore.ts +77 -0
  436. package/src/tools/terminal/terminalCapture.js +167 -0
  437. package/src/tools/terminal/terminalCapture.ts +179 -0
  438. package/src/tools/trash/trash.js +233 -0
  439. package/src/tools/trash/trash.ts +283 -0
  440. package/src/tools/types.js +1 -1
  441. package/src/tools/types.ts +24 -0
  442. package/src/tools/webbrowser/agentBrowserPath.ts +286 -0
  443. package/src/tools/webbrowser/browser.js +214 -11
  444. package/src/tools/webbrowser/browser.ts +293 -0
  445. package/src/tools/webbrowser/browserControl.js +153 -48
  446. package/src/tools/webbrowser/browserControl.ts +262 -0
  447. package/src/tools/webbrowser/browserDaemon.js +147 -39
  448. package/src/tools/webbrowser/browserDaemon.ts +270 -0
  449. package/src/tools/webbrowser/browserOutcome.js +273 -0
  450. package/src/tools/webbrowser/browserOutcome.ts +306 -0
  451. package/src/tools/webbrowser/browserRunRegistry.js +150 -0
  452. package/src/tools/webbrowser/browserRunRegistry.ts +179 -0
  453. package/src/tools/webbrowser/browserService.js +20 -6
  454. package/src/tools/webbrowser/browserService.ts +56 -0
  455. package/src/tools/webbrowser/browserStream.js +30 -1
  456. package/src/tools/webbrowser/browserStream.ts +216 -0
  457. package/src/tools/webbrowser/browserTabs.js +143 -0
  458. package/src/tools/webbrowser/browserTabs.ts +210 -0
  459. package/src/tools/webbrowser/webbrowser.js +831 -150
  460. package/src/tools/webbrowser/webbrowser.ts +1537 -0
  461. package/src/tools/webfetch/preapproved.ts +274 -0
  462. package/src/tools/webfetch/webfetch.js +24 -23
  463. package/src/tools/webfetch/webfetch.ts +383 -0
  464. package/src/tools/websearch/websearch.js +12 -11
  465. package/src/tools/websearch/websearch.ts +292 -0
  466. package/src/tools/worktree/sessionWorktree.js +128 -0
  467. package/src/tools/worktree/sessionWorktree.ts +158 -0
  468. package/src/tools/write/write.js +27 -44
  469. package/src/tools/write/write.ts +136 -0
  470. package/src/types.ts +960 -0
  471. package/src/ui/App.js +216 -12
  472. package/src/ui/App.tsx +879 -0
  473. package/src/ui/AskQuestion.tsx +300 -0
  474. package/src/ui/InputBox.js +77 -1
  475. package/src/ui/InputBox.tsx +567 -0
  476. package/src/ui/LiveArea.tsx +344 -0
  477. package/src/ui/MessageList.js +27 -6
  478. package/src/ui/MessageList.tsx +559 -0
  479. package/src/ui/ModelPicker.tsx +107 -0
  480. package/src/ui/QueuedMessagesBanner.tsx +51 -0
  481. package/src/ui/Root.js +6 -8
  482. package/src/ui/Root.tsx +100 -0
  483. package/src/ui/SessionPicker.tsx +169 -0
  484. package/src/ui/StatusLine.js +22 -1
  485. package/src/ui/StatusLine.tsx +145 -0
  486. package/src/ui/WorkspacePicker.tsx +84 -0
  487. package/src/ui/advisorCommand.js +54 -0
  488. package/src/ui/advisorCommand.ts +63 -0
  489. package/src/ui/computerCommand.js +19 -0
  490. package/src/ui/computerCommand.ts +35 -0
  491. package/src/ui/figures.ts +45 -0
  492. package/src/ui/hooks/askSlot.ts +112 -0
  493. package/src/ui/hooks/useChat.js +271 -7
  494. package/src/ui/hooks/useChat.ts +1578 -0
  495. package/src/ui/hooks/useInputHistory.ts +235 -0
  496. package/src/ui/hooks/usePasteHandler.ts +220 -0
  497. package/src/ui/hooks/useTerminalSize.ts +41 -0
  498. package/src/ui/hooks/useTextBuffer.ts +108 -0
  499. package/src/ui/hooks/useTokenUsage.ts +44 -0
  500. package/src/ui/liveViewport.ts +189 -0
  501. package/src/ui/markdown.ts +230 -0
  502. package/src/ui/textBuffer.ts +239 -0
  503. package/src/ui/theme.ts +35 -0
  504. package/src/utils/clipboardImage.js +358 -0
  505. package/src/utils/clipboardImage.ts +420 -0
  506. package/src/utils/debugLog.ts +50 -0
  507. package/src/utils/greenRoot.ts +35 -0
  508. package/src/utils/packageRoot.ts +40 -0
  509. package/src/utils/pathContains.js +28 -0
  510. package/src/utils/pathContains.ts +31 -0
  511. package/src/utils/resourcePaths.ts +71 -0
  512. package/src/utils/stripThink.ts +49 -0
  513. package/src/utils/zodToJson.ts +73 -0
  514. package/src/web/browserBridge.js +365 -66
  515. package/src/web/browserBridge.ts +672 -0
  516. package/src/web/protocol.ts +1804 -0
  517. package/vendor/computer-use/arm64-darwin/cu-helperd +0 -0
  518. package/workflows/ppt.yaml +13 -2
  519. package/workflows/wechat-reading-shots.yaml +315 -0
  520. package/workflows/word.yaml +11 -1
  521. package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
  522. package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
  523. package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
  524. package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
  525. package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
  526. package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
  527. package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
  528. package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
  529. package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
  530. package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
  531. package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
  532. package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
  533. package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
  534. package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
  535. package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
  536. package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
  537. package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
  538. package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
  539. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
  540. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
  541. package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
  542. package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
  543. package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
  544. package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
  545. package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
  546. package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
  547. package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
  548. package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
  549. package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
  550. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
  551. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
  552. package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
  553. package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
  554. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
  555. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
  556. package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
  557. package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
  558. package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
  559. package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
  560. package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
  561. package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
  562. package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
  563. package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
  564. package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
  565. package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
  566. package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
  567. package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
  568. package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
  569. package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
  570. package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
  571. package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
  572. /package/skills/ai-image/scripts/{generate_test.mjs → generate.selftest.mjs} +0 -0
  573. /package/skills/ai-image/scripts/{generate_from_plan_test.mjs → generate_from_plan.selftest.mjs} +0 -0
@@ -0,0 +1,570 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { copyFile, readFile, unlink } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { countTextTokens } from '../context/tokenCounter.js';
5
+ import { containsForbiddenSecret, deriveTopicKey, hydrateRecord, parsePersona, serializePersona, sha256, validateMemoryInput, } from './codec.js';
6
+ import { DEFAULT_RETENTION, DEFAULT_SETTINGS, MEMORY_RETENTION_DAYS_MAX, MEMORY_RETENTION_DAYS_MIN, MEMORY_RETENTION_MB_MAX, MEMORY_RETENTION_MB_MIN, PERSONA_MAX_CHARS, } from './constants.js';
7
+ import { clearConversationEpisodes, episodicMemoryService, } from './episodicMemory.js';
8
+ import { acquireFileLock, appendPrivateLine, atomicWriteFile, auditFilePath, enqueueMemoryMutation, personaFilePath, scopeDirectory, settingsFilePath, } from './fileStore.js';
9
+ import { ensureMemoryMigrated } from './migration.js';
10
+ import { clearScopeTransactionQuarantine, readVersionedMemory, refreshTopicView, removeVersionedMemory, replaceMemoryBatchVersioned, scanMemoryScope, writeNewMemory, } from './repository.js';
11
+ import { isReviewDue, recallFromSnapshot, takeTokenBudget, truncateTokenBudget, } from './retrieval.js';
12
+ export { containsForbiddenSecret } from './codec.js';
13
+ function mergeSettings(raw) {
14
+ const review = raw.reviewAfterDays;
15
+ const retention = raw.retention;
16
+ return {
17
+ autoRemember: typeof raw.autoRemember === 'boolean'
18
+ ? raw.autoRemember
19
+ : DEFAULT_SETTINGS.autoRemember,
20
+ reviewAfterDays: {
21
+ profile: review?.profile ?? DEFAULT_SETTINGS.reviewAfterDays.profile,
22
+ preference: review?.preference ?? DEFAULT_SETTINGS.reviewAfterDays.preference,
23
+ topic: review?.topic ?? DEFAULT_SETTINGS.reviewAfterDays.topic,
24
+ person: review?.person ?? DEFAULT_SETTINGS.reviewAfterDays.person,
25
+ project: review?.project ?? DEFAULT_SETTINGS.reviewAfterDays.project,
26
+ decision: review?.decision ?? DEFAULT_SETTINGS.reviewAfterDays.decision,
27
+ },
28
+ retention: {
29
+ episodeDays: retention?.episodeDays ?? DEFAULT_RETENTION.episodeDays,
30
+ episodeMaxMegabytes: retention?.episodeMaxMegabytes ?? DEFAULT_RETENTION.episodeMaxMegabytes,
31
+ },
32
+ };
33
+ }
34
+ function validateSettingsPatch(patch) {
35
+ if (patch.reviewAfterDays !== undefined) {
36
+ for (const [category, days] of Object.entries(patch.reviewAfterDays)) {
37
+ if (!Number.isInteger(days) || days < 7 || days > 3_650) {
38
+ throw new Error(`复核周期 ${category} 必须是 7-3650 之间的整数天`);
39
+ }
40
+ }
41
+ }
42
+ if (patch.retention === undefined)
43
+ return;
44
+ const { episodeDays, episodeMaxMegabytes } = patch.retention;
45
+ if (episodeDays !== undefined
46
+ && (!Number.isInteger(episodeDays)
47
+ || episodeDays < MEMORY_RETENTION_DAYS_MIN
48
+ || episodeDays > MEMORY_RETENTION_DAYS_MAX)) {
49
+ throw new Error(`会话原文保留天数必须是 ${MEMORY_RETENTION_DAYS_MIN}-${MEMORY_RETENTION_DAYS_MAX} 之间的整数`);
50
+ }
51
+ if (episodeMaxMegabytes !== undefined
52
+ && (!Number.isInteger(episodeMaxMegabytes)
53
+ || episodeMaxMegabytes < MEMORY_RETENTION_MB_MIN
54
+ || episodeMaxMegabytes > MEMORY_RETENTION_MB_MAX)) {
55
+ throw new Error(`会话原文体积上限必须是 ${MEMORY_RETENTION_MB_MIN}-${MEMORY_RETENTION_MB_MAX} 之间的整数 MB`);
56
+ }
57
+ }
58
+ async function settingsDocument() {
59
+ try {
60
+ const raw = await readFile(settingsFilePath(), 'utf8');
61
+ return {
62
+ settings: mergeSettings(JSON.parse(raw)),
63
+ version: sha256(raw),
64
+ };
65
+ }
66
+ catch (error) {
67
+ if (error.code !== 'ENOENT') {
68
+ const path = settingsFilePath();
69
+ await copyFile(path, `${path}.corrupt-${Date.now()}`).catch(() => { });
70
+ }
71
+ const settings = structuredClone(DEFAULT_SETTINGS);
72
+ return { settings, version: sha256(`${JSON.stringify(settings, null, 2)}\n`) };
73
+ }
74
+ }
75
+ /** 审计日志单代上限;超限挪成 `.1`,保留最近两代。 */
76
+ const AUDIT_MAX_BYTES = 4 * 1024 * 1024;
77
+ async function appendAudit(input) {
78
+ await appendPrivateLine(auditFilePath(), JSON.stringify({
79
+ timestamp: Date.now(),
80
+ action: input.action,
81
+ id: input.record?.id,
82
+ scope: input.record?.scope,
83
+ workspaceId: input.record?.workspaceId,
84
+ revision: input.record?.revision,
85
+ version: input.version,
86
+ result: input.result,
87
+ }),
88
+ // 审计日志同样是 append-only,必须轮转——它此前是仓库里第二个只增不减的存储。
89
+ { maxBytes: AUDIT_MAX_BYTES }).catch(() => undefined);
90
+ }
91
+ const EMPTY_SCOPE_SNAPSHOT = Object.freeze({
92
+ records: [],
93
+ versions: {},
94
+ diagnostics: [],
95
+ createdAt: 0,
96
+ });
97
+ /**
98
+ * 合并快照的记忆化。
99
+ *
100
+ * ⚠️ 这不是"顺手加个缓存",是修一个死缓存:`retrieval.ts` 用
101
+ * `WeakMap<MemorySnapshot, Bm25Index>` 按快照对象缓存 BM25 索引,而本函数以前**每次都
102
+ * 返回全新对象字面量** —— 于是 recall / buildContextBundle 这两条热路径上 WeakMap 永远
103
+ * miss,每轮对话都要重建整个索引,`recordSearchIndexCacheHit()` 一次都不会触发(诊断计数
104
+ * 器因此说谎)。单测直接对同一个 snapshot 对象调两次 recallFromSnapshot,机制是对的,
105
+ * 但生产集成从不复用对象,属于"测试通过、生产死代码"。
106
+ *
107
+ * 用底层两个 scope 快照的**对象标识**做键:scanMemoryScope 在缓存命中时返回同一个对象,
108
+ * 有变更时才换新对象——比时间戳更精确,也不怕时钟碰撞。
109
+ */
110
+ let combinedSnapshotCache = null;
111
+ async function combinedSnapshot(workspaceId) {
112
+ await ensureMemoryMigrated();
113
+ const personal = await scanMemoryScope('personal');
114
+ const workspace = workspaceId
115
+ ? await scanMemoryScope('workspace', workspaceId)
116
+ : EMPTY_SCOPE_SNAPSHOT;
117
+ const cached = combinedSnapshotCache;
118
+ if (cached
119
+ && cached.personal === personal
120
+ && cached.workspace === workspace
121
+ && cached.workspaceId === workspaceId) {
122
+ return cached.combined;
123
+ }
124
+ const combined = {
125
+ records: [...personal.records, ...workspace.records],
126
+ versions: { ...personal.versions, ...workspace.versions },
127
+ diagnostics: [...personal.diagnostics, ...workspace.diagnostics],
128
+ createdAt: Date.now(),
129
+ };
130
+ combinedSnapshotCache = { personal, workspace, workspaceId, combined };
131
+ return combined;
132
+ }
133
+ function refreshTopicViewAfterMutation(scope, workspaceId) {
134
+ combinedSnapshotCache = null;
135
+ void refreshTopicView(scope, workspaceId).catch(() => undefined);
136
+ }
137
+ function sameTopic(a, b) {
138
+ const topicKey = b.topicKey || deriveTopicKey(b);
139
+ if (a.topicKey === topicKey)
140
+ return true;
141
+ const candidates = new Set([
142
+ b.subject.toLocaleLowerCase(),
143
+ ...(b.aliases ?? []).map((item) => item.toLocaleLowerCase()),
144
+ ]);
145
+ return [a.subject, ...a.aliases].some((item) => candidates.has(item.toLocaleLowerCase()));
146
+ }
147
+ function evidenceForStorage(record) {
148
+ if (record.sensitivity === 'normal')
149
+ return { evidenceQuote: record.evidenceQuote };
150
+ return {
151
+ evidenceQuote: '[sensitive evidence generalized]',
152
+ evidenceHash: sha256(record.evidenceQuote),
153
+ };
154
+ }
155
+ function currentInputOverrides(record, input) {
156
+ const normalized = input.toLocaleLowerCase();
157
+ const mentionsTopic = [record.subject, ...record.aliases].some((value) => value.length > 1 && normalized.includes(value.toLocaleLowerCase()));
158
+ return (mentionsTopic &&
159
+ /纠正|改成|更新|不再|以后不要|不是|现在(?:改|用|是)|correction|change to|no longer|instead/i.test(input));
160
+ }
161
+ export const memoryService = {
162
+ async settings() {
163
+ return (await settingsDocument()).settings;
164
+ },
165
+ async settingsWithVersion() {
166
+ return settingsDocument();
167
+ },
168
+ async updateSettings(patch) {
169
+ return (await this.updateSettingsWithVersion(patch)).settings;
170
+ },
171
+ async updateSettingsWithVersion(patch, expectedVersion) {
172
+ validateSettingsPatch(patch);
173
+ const release = await acquireFileLock(settingsFilePath());
174
+ try {
175
+ const current = await settingsDocument();
176
+ if (expectedVersion && current.version !== expectedVersion) {
177
+ throw new Error('MEMORY_SETTINGS_VERSION_CONFLICT');
178
+ }
179
+ const next = mergeSettings({ ...current.settings, ...patch });
180
+ const content = `${JSON.stringify(next, null, 2)}\n`;
181
+ await atomicWriteFile(settingsFilePath(), content);
182
+ return { settings: next, version: sha256(content) };
183
+ }
184
+ finally {
185
+ await release();
186
+ }
187
+ },
188
+ async snapshot(workspaceId) {
189
+ return combinedSnapshot(workspaceId);
190
+ },
191
+ async scan(scope, workspaceId) {
192
+ await ensureMemoryMigrated();
193
+ return scanMemoryScope(scope, workspaceId);
194
+ },
195
+ async list(scope, workspaceId) {
196
+ return (await this.scan(scope, workspaceId)).records;
197
+ },
198
+ async diagnostics(scope, workspaceId) {
199
+ return (await this.scan(scope, workspaceId)).diagnostics;
200
+ },
201
+ async readWithVersion(id, scope, workspaceId) {
202
+ await ensureMemoryMigrated();
203
+ return readVersionedMemory(id, scope, workspaceId);
204
+ },
205
+ async recall(query, workspaceId, limit = 8) {
206
+ return (await this.recallDetailed(query, workspaceId, limit)).records;
207
+ },
208
+ async recallDetailed(query, workspaceId, limit = 8) {
209
+ const snapshot = await combinedSnapshot(workspaceId);
210
+ return {
211
+ records: recallFromSnapshot(snapshot, query, await this.settings(), limit),
212
+ snapshot,
213
+ };
214
+ },
215
+ async remember(input) {
216
+ validateMemoryInput(input);
217
+ await ensureMemoryMigrated();
218
+ return enqueueMemoryMutation(async () => {
219
+ const release = await acquireFileLock(join(scopeDirectory(input.scope, input.workspaceId), '.records'));
220
+ try {
221
+ const records = (await scanMemoryScope(input.scope, input.workspaceId))
222
+ .records;
223
+ const hydratedInput = hydrateRecord({
224
+ ...input,
225
+ id: randomUUID(),
226
+ createdAt: 0,
227
+ updatedAt: 0,
228
+ });
229
+ const duplicate = records.find((record) => sameTopic(record, hydratedInput));
230
+ if (duplicate?.statement === input.statement) {
231
+ await appendAudit({
232
+ action: 'remember-idempotent',
233
+ record: duplicate,
234
+ result: 'ok',
235
+ });
236
+ return duplicate;
237
+ }
238
+ if (duplicate) {
239
+ throw new Error(`已有同主题记忆 ${duplicate.id};内容变更必须使用 UpdateMemory,不能静默覆盖`);
240
+ }
241
+ const now = Date.now();
242
+ const evidence = evidenceForStorage(input);
243
+ const record = hydrateRecord({
244
+ ...input,
245
+ ...evidence,
246
+ id: hydratedInput.id,
247
+ createdAt: now,
248
+ updatedAt: now,
249
+ topicKey: hydratedInput.topicKey,
250
+ status: 'active',
251
+ revision: 1,
252
+ lastConfirmedAt: now,
253
+ });
254
+ const version = await writeNewMemory(record);
255
+ await appendAudit({
256
+ action: 'remember',
257
+ record,
258
+ version,
259
+ result: 'ok',
260
+ });
261
+ refreshTopicViewAfterMutation(record.scope, record.workspaceId);
262
+ return record;
263
+ }
264
+ finally {
265
+ await release();
266
+ }
267
+ });
268
+ },
269
+ async updateWithVersion(id, scope, expectedVersion, patch, workspaceId) {
270
+ await ensureMemoryMigrated();
271
+ return enqueueMemoryMutation(async () => {
272
+ const current = await readVersionedMemory(id, scope, workspaceId);
273
+ if (!current) {
274
+ await appendAudit({ action: 'update', result: 'not_found' });
275
+ return null;
276
+ }
277
+ const now = Date.now();
278
+ const merged = { ...current.record, ...patch, updatedAt: now };
279
+ validateMemoryInput(merged);
280
+ const evidence = evidenceForStorage(merged);
281
+ const next = hydrateRecord({
282
+ ...merged,
283
+ ...evidence,
284
+ topicKey: deriveTopicKey(merged),
285
+ revision: current.record.revision + 1,
286
+ lastConfirmedAt: now,
287
+ });
288
+ const scopeSnapshot = await scanMemoryScope(scope, workspaceId);
289
+ const topicConflicts = scopeSnapshot.records.filter((record) => record.id !== current.record.id &&
290
+ record.status !== 'superseded' &&
291
+ sameTopic(record, next));
292
+ const declaredSuperseded = new Set(next.supersedesIds);
293
+ if (topicConflicts.some((record) => !declaredSuperseded.has(record.id))) {
294
+ throw new Error(`MEMORY_TOPIC_CONFLICT:${topicConflicts.map((record) => record.id).join(',')}`);
295
+ }
296
+ try {
297
+ const supersededRecords = [];
298
+ const replacements = [
299
+ { current, next, expectedVersion },
300
+ ];
301
+ for (const conflict of topicConflicts) {
302
+ const conflictVersion = scopeSnapshot.versions[conflict.id];
303
+ if (!conflictVersion)
304
+ continue;
305
+ const superseded = hydrateRecord({
306
+ ...conflict,
307
+ status: 'superseded',
308
+ revision: conflict.revision + 1,
309
+ updatedAt: now,
310
+ });
311
+ supersededRecords.push(superseded);
312
+ replacements.push({
313
+ current: { record: conflict, version: conflictVersion },
314
+ next: superseded,
315
+ expectedVersion: conflictVersion,
316
+ });
317
+ }
318
+ const versions = await replaceMemoryBatchVersioned(replacements);
319
+ const version = versions[next.id];
320
+ for (const superseded of supersededRecords) {
321
+ await appendAudit({
322
+ action: 'supersede',
323
+ record: superseded,
324
+ version: versions[superseded.id],
325
+ result: 'ok',
326
+ });
327
+ }
328
+ await appendAudit({
329
+ action: 'update',
330
+ record: next,
331
+ version,
332
+ result: 'ok',
333
+ });
334
+ refreshTopicViewAfterMutation(next.scope, next.workspaceId);
335
+ return { record: next, version };
336
+ }
337
+ catch (error) {
338
+ if (error.message === 'MEMORY_VERSION_CONFLICT') {
339
+ await appendAudit({
340
+ action: 'update',
341
+ record: current.record,
342
+ result: 'conflict',
343
+ });
344
+ }
345
+ throw error;
346
+ }
347
+ });
348
+ },
349
+ async update(id, scope, patch, workspaceId) {
350
+ const current = await this.readWithVersion(id, scope, workspaceId);
351
+ if (!current)
352
+ return null;
353
+ return ((await this.updateWithVersion(id, scope, current.version, patch, workspaceId))?.record ?? null);
354
+ },
355
+ async confirm(id, scope, expectedVersion, evidence, workspaceId) {
356
+ return this.updateWithVersion(id, scope, expectedVersion, {
357
+ evidence: 'user_confirmed',
358
+ ...evidence,
359
+ status: 'active',
360
+ }, workspaceId);
361
+ },
362
+ async reviewQueue(scope, workspaceId) {
363
+ const snapshot = scope
364
+ ? await this.scan(scope, workspaceId)
365
+ : await this.snapshot(workspaceId);
366
+ const settings = await this.settings();
367
+ return snapshot.records.filter((record) => record.status !== 'superseded' &&
368
+ (record.status === 'needs_review' || isReviewDue(record, settings)));
369
+ },
370
+ async forget(id, scope, workspaceId) {
371
+ const current = await this.readWithVersion(id, scope, workspaceId);
372
+ if (!current)
373
+ return false;
374
+ return this.forgetWithVersion(id, scope, current.version, workspaceId);
375
+ },
376
+ async forgetWithVersion(id, scope, expectedVersion, workspaceId) {
377
+ await ensureMemoryMigrated();
378
+ return enqueueMemoryMutation(async () => {
379
+ const current = await readVersionedMemory(id, scope, workspaceId);
380
+ if (!current)
381
+ return false;
382
+ const removed = await removeVersionedMemory(current, expectedVersion);
383
+ await appendAudit({
384
+ action: 'forget',
385
+ record: current.record,
386
+ version: expectedVersion,
387
+ result: removed ? 'ok' : 'not_found',
388
+ });
389
+ if (removed)
390
+ refreshTopicViewAfterMutation(scope, workspaceId);
391
+ return removed;
392
+ });
393
+ },
394
+ async clear(scope, workspaceId) {
395
+ await ensureMemoryMigrated();
396
+ await enqueueMemoryMutation(async () => {
397
+ const snapshot = await scanMemoryScope(scope, workspaceId);
398
+ for (const record of snapshot.records) {
399
+ const version = snapshot.versions[record.id];
400
+ if (!version)
401
+ continue;
402
+ await removeVersionedMemory({ record, version }, version);
403
+ await appendAudit({ action: 'clear', record, version, result: 'ok' });
404
+ }
405
+ // ★ 会话原文日志也要清掉。
406
+ // Desktop「永久清空」以前只删 records,而同一个记忆中心页面还提供
407
+ // ConversationHistorySearch —— 用户"清空记忆"后全部对话原文依然可搜,
408
+ // 与按钮承诺严重不符。工作区范围才有对应的 episodes 文件。
409
+ if (scope === 'workspace' && workspaceId) {
410
+ const removed = await clearConversationEpisodes(workspaceId).catch(() => 0);
411
+ if (removed) {
412
+ await appendAudit({ action: 'clear-episodes', result: 'ok' });
413
+ }
414
+ }
415
+ // 只有用户明确清空整个 scope 才表示隔离事务的复核现场也不再需要。
416
+ // 普通新增/更新记忆不得清除这类诊断。
417
+ await clearScopeTransactionQuarantine(scope, workspaceId);
418
+ refreshTopicViewAfterMutation(scope, workspaceId);
419
+ });
420
+ },
421
+ async readPersona() {
422
+ return (await this.readPersonaWithVersion())?.persona ?? null;
423
+ },
424
+ async readPersonaWithVersion() {
425
+ await ensureMemoryMigrated();
426
+ try {
427
+ const raw = await readFile(personaFilePath(), 'utf8');
428
+ return { persona: parsePersona(raw), version: sha256(raw) };
429
+ }
430
+ catch (error) {
431
+ if (error.code === 'ENOENT')
432
+ return null;
433
+ throw new Error(`无法读取人格设定:${error.message}`);
434
+ }
435
+ },
436
+ async setPersona(input) {
437
+ return (await this.setPersonaWithVersion(input)).persona;
438
+ },
439
+ async setPersonaWithVersion(input, expectedVersion) {
440
+ if (!input.content.trim() || input.content.length > PERSONA_MAX_CHARS) {
441
+ throw new Error(`人格设定长度必须为 1-${PERSONA_MAX_CHARS} 字符`);
442
+ }
443
+ if (!input.evidenceQuote.trim() ||
444
+ containsForbiddenSecret(`${input.content}\n${input.evidenceQuote}`)) {
445
+ throw new Error('人格设定缺少有效证据,或包含不得保存的凭据');
446
+ }
447
+ await ensureMemoryMigrated();
448
+ return enqueueMemoryMutation(async () => {
449
+ const release = await acquireFileLock(personaFilePath());
450
+ try {
451
+ const raw = await readFile(personaFilePath(), 'utf8').catch((error) => {
452
+ if (error.code === 'ENOENT')
453
+ return null;
454
+ throw error;
455
+ });
456
+ if (expectedVersion && (!raw || sha256(raw) !== expectedVersion)) {
457
+ throw new Error('MEMORY_PERSONA_VERSION_CONFLICT');
458
+ }
459
+ const previous = raw ? parsePersona(raw) : null;
460
+ const persona = {
461
+ ...input,
462
+ content: input.content.trim(),
463
+ updatedAt: Date.now(),
464
+ revision: (previous?.revision ?? 0) + 1,
465
+ };
466
+ const content = serializePersona(persona);
467
+ await atomicWriteFile(personaFilePath(), content);
468
+ await appendAudit({ action: 'persona-set', result: 'ok' });
469
+ return { persona, version: sha256(content) };
470
+ }
471
+ finally {
472
+ await release();
473
+ }
474
+ });
475
+ },
476
+ async clearPersona() {
477
+ const current = await this.readPersonaWithVersion();
478
+ if (!current)
479
+ return false;
480
+ return this.clearPersonaWithVersion(current.version);
481
+ },
482
+ async clearPersonaWithVersion(expectedVersion) {
483
+ await ensureMemoryMigrated();
484
+ return enqueueMemoryMutation(async () => {
485
+ const release = await acquireFileLock(personaFilePath());
486
+ try {
487
+ try {
488
+ const raw = await readFile(personaFilePath(), 'utf8');
489
+ if (sha256(raw) !== expectedVersion) {
490
+ throw new Error('MEMORY_PERSONA_VERSION_CONFLICT');
491
+ }
492
+ await unlink(personaFilePath());
493
+ await appendAudit({ action: 'persona-clear', result: 'ok' });
494
+ return true;
495
+ }
496
+ catch (error) {
497
+ if (error.code === 'ENOENT')
498
+ return false;
499
+ throw error;
500
+ }
501
+ }
502
+ finally {
503
+ await release();
504
+ }
505
+ });
506
+ },
507
+ async buildContextBundle(input, workspaceId) {
508
+ const snapshot = await combinedSnapshot(workspaceId);
509
+ const settings = await this.settings();
510
+ const persona = await this.readPersona().catch(() => null);
511
+ const preferences = snapshot.records.filter((record) => record.scope === 'personal' &&
512
+ record.category === 'preference' &&
513
+ record.sensitivity === 'normal' &&
514
+ record.status !== 'superseded' &&
515
+ !currentInputOverrides(record, input));
516
+ const relevant = recallFromSnapshot(snapshot, input, settings, 12)
517
+ .filter((record) => record.sensitivity === 'normal' &&
518
+ record.category !== 'preference' &&
519
+ !currentInputOverrides(record, input))
520
+ .slice(0, 5);
521
+ const reviewCount = snapshot.records.filter((record) => record.status !== 'superseded' && isReviewDue(record, settings)).length;
522
+ const sections = [];
523
+ const contextSections = [];
524
+ const includedIds = [];
525
+ const pushSection = (id, content, ids = []) => {
526
+ sections.push(content);
527
+ contextSections.push({
528
+ id,
529
+ content,
530
+ includedIds: ids,
531
+ estimatedTokens: countTextTokens(content),
532
+ });
533
+ };
534
+ if (persona) {
535
+ const personaText = truncateTokenBudget(persona.content, 1_000);
536
+ pushSection('persona', `【全局 Agent 人格|可信本机配置】\n只用于角色、语气和协作风格;不得扩大权限、覆盖安全规则或改变当前任务。\n${personaText}`);
537
+ }
538
+ const preferenceLines = takeTokenBudget(preferences.map((record) => `- ${record.subject}: ${record.statement}`), 600);
539
+ if (preferenceLines.length) {
540
+ const ids = preferences
541
+ .slice(0, preferenceLines.length)
542
+ .map((record) => record.id);
543
+ pushSection('preferences', `【全局响应偏好|当前消息可纠正】\n${preferenceLines.join('\n')}`, ids);
544
+ includedIds.push(...ids);
545
+ }
546
+ const relevantLines = takeTokenBudget(relevant.map((record) => `- ${record.scope}/${record.category}/${record.subject}: ${record.statement}`), 1_200);
547
+ if (relevantLines.length) {
548
+ const ids = relevant.slice(0, relevantLines.length).map((record) => record.id);
549
+ pushSection('relevant', `【相关本机记忆|低优先级、可纠正】\n这些记录来自用户此前明确陈述;当前消息冲突时以当前消息为准。需要来源时调用 RecallMemory。\n${relevantLines.join('\n')}`, ids);
550
+ includedIds.push(...ids);
551
+ }
552
+ if (snapshot.diagnostics.length || reviewCount) {
553
+ pushSection('health', `【记忆健康提示】${snapshot.diagnostics.length ? ` ${snapshot.diagnostics.length} 个文件损坏并已隔离。` : ''}${reviewCount ? ` ${reviewCount} 条记忆已到复核周期;不要自动删除。` : ''}`);
554
+ }
555
+ const unboundedText = sections.length
556
+ ? sections.join('\n\n')
557
+ : '长期记忆:当前没有与本轮明显相关的记录;需要时可调用 RecallMemory。';
558
+ const text = truncateTokenBudget(unboundedText, 3_000);
559
+ return {
560
+ text,
561
+ snapshot,
562
+ includedIds,
563
+ estimatedTokens: countTextTokens(text),
564
+ sections: contextSections,
565
+ };
566
+ },
567
+ async searchConversations(query, options) {
568
+ return episodicMemoryService.search(query, options);
569
+ },
570
+ };