berry-agent 0.1.0-alpha.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 (401) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/dist/.api-emit.stamp +1 -0
  4. package/dist/.build-meta.json +6 -0
  5. package/dist/agent/events.js +1 -0
  6. package/dist/agent/index.js +2 -0
  7. package/dist/agent/loop.js +139 -0
  8. package/dist/agent/queue.js +119 -0
  9. package/dist/agent/stream.js +62 -0
  10. package/dist/agent/tools-batch.js +221 -0
  11. package/dist/agent/types.js +8 -0
  12. package/dist/api/berry-agent-llm.d.ts +18 -0
  13. package/dist/api/berry-agent.d.ts +9 -0
  14. package/dist/api/surface.json +1632 -0
  15. package/dist/api/tsconfig.paths.json +12 -0
  16. package/dist/api/typebox-compile.d.ts +2 -0
  17. package/dist/api/typebox-value.d.ts +2 -0
  18. package/dist/api/typebox.d.ts +2 -0
  19. package/dist/browser/cdp.js +256 -0
  20. package/dist/browser/codes.js +31 -0
  21. package/dist/browser/discover.js +107 -0
  22. package/dist/browser/engine.js +169 -0
  23. package/dist/browser/index.js +17 -0
  24. package/dist/browser/install.js +342 -0
  25. package/dist/browser/page.js +321 -0
  26. package/dist/browser/service.js +158 -0
  27. package/dist/browser/tools.js +198 -0
  28. package/dist/browser/types.js +81 -0
  29. package/dist/channels/ask-queue.js +82 -0
  30. package/dist/channels/commands.js +129 -0
  31. package/dist/channels/engine/cell.js +143 -0
  32. package/dist/channels/engine/diff.js +143 -0
  33. package/dist/channels/engine/engine.js +416 -0
  34. package/dist/channels/engine/index.js +8 -0
  35. package/dist/channels/engine/input-keys.js +86 -0
  36. package/dist/channels/engine/input.js +596 -0
  37. package/dist/channels/engine/memory-io.js +71 -0
  38. package/dist/channels/engine/process-io.js +38 -0
  39. package/dist/channels/engine/types.js +17 -0
  40. package/dist/channels/engine/width.js +122 -0
  41. package/dist/channels/index.js +15 -0
  42. package/dist/channels/registry.js +56 -0
  43. package/dist/channels/sdk/admit.js +29 -0
  44. package/dist/channels/sdk/backend.js +102 -0
  45. package/dist/channels/sdk/cursor.js +56 -0
  46. package/dist/channels/sdk/index.js +20 -0
  47. package/dist/channels/sdk/jsonl.js +208 -0
  48. package/dist/channels/sdk/protocol.js +24 -0
  49. package/dist/channels/sdk/schema.js +91 -0
  50. package/dist/channels/sdk/wire-core.js +446 -0
  51. package/dist/channels/service.js +169 -0
  52. package/dist/channels/tui/autocomplete/autocomplete.js +42 -0
  53. package/dist/channels/tui/autocomplete/file-mentions.js +106 -0
  54. package/dist/channels/tui/autocomplete/popup.js +148 -0
  55. package/dist/channels/tui/autocomplete/provider.js +7 -0
  56. package/dist/channels/tui/autocomplete/token.js +68 -0
  57. package/dist/channels/tui/backend/ansi-rows.js +211 -0
  58. package/dist/channels/tui/backend/main-screen.js +207 -0
  59. package/dist/channels/tui/backend/osc.js +91 -0
  60. package/dist/channels/tui/backend/transcript.js +230 -0
  61. package/dist/channels/tui/backend/tui-backend.js +915 -0
  62. package/dist/channels/tui/editor/editor-model.js +543 -0
  63. package/dist/channels/tui/editor/editor-view.js +140 -0
  64. package/dist/channels/tui/editor/editor.js +275 -0
  65. package/dist/channels/tui/editor/undo-stack.js +35 -0
  66. package/dist/channels/tui/editor/visual-lines.js +126 -0
  67. package/dist/channels/tui/editor/word-nav.js +106 -0
  68. package/dist/channels/tui/history/history-viewer.js +403 -0
  69. package/dist/channels/tui/index.js +3 -0
  70. package/dist/channels/tui/layout.js +167 -0
  71. package/dist/channels/tui/markdown/blocks.js +111 -0
  72. package/dist/channels/tui/markdown/inline.js +75 -0
  73. package/dist/channels/tui/markdown/markdown.js +182 -0
  74. package/dist/channels/tui/memory/memory-viewer.js +540 -0
  75. package/dist/channels/tui/overlay/alt-screen.js +105 -0
  76. package/dist/channels/tui/overlay/overlay.js +57 -0
  77. package/dist/channels/tui/overlay/select-confirm.js +156 -0
  78. package/dist/channels/tui/panels/todo-panel.js +54 -0
  79. package/dist/channels/tui/panels/tool-progress-panel.js +93 -0
  80. package/dist/channels/tui/scroll/scroll-view.js +254 -0
  81. package/dist/channels/tui/status/status-line.js +76 -0
  82. package/dist/channels/tui/text.js +38 -0
  83. package/dist/channels/tui/theme.js +41 -0
  84. package/dist/channels/types.js +11 -0
  85. package/dist/channels/ui-core.js +209 -0
  86. package/dist/checkpoint/capture.js +45 -0
  87. package/dist/checkpoint/codes.js +33 -0
  88. package/dist/checkpoint/command.js +82 -0
  89. package/dist/checkpoint/gate.js +48 -0
  90. package/dist/checkpoint/index.js +20 -0
  91. package/dist/checkpoint/restore.js +172 -0
  92. package/dist/checkpoint/store.js +247 -0
  93. package/dist/checkpoint/types.js +4 -0
  94. package/dist/checkpoint/walk.js +146 -0
  95. package/dist/compaction/ccr-tools.js +112 -0
  96. package/dist/compaction/ccr.js +84 -0
  97. package/dist/compaction/codes.js +21 -0
  98. package/dist/compaction/index.js +18 -0
  99. package/dist/compaction/policy.js +200 -0
  100. package/dist/compaction/service.js +422 -0
  101. package/dist/compaction/slots.js +121 -0
  102. package/dist/compaction/types.js +10 -0
  103. package/dist/context/codes.js +40 -0
  104. package/dist/context/events.js +160 -0
  105. package/dist/context/index.js +13 -0
  106. package/dist/context/logger.js +136 -0
  107. package/dist/context/scope.js +182 -0
  108. package/dist/context/workspace.js +104 -0
  109. package/dist/contracts/agent-events.d.ts +73 -0
  110. package/dist/contracts/agent-events.js +16 -0
  111. package/dist/contracts/api.d.ts +249 -0
  112. package/dist/contracts/api.js +299 -0
  113. package/dist/contracts/approval.d.ts +37 -0
  114. package/dist/contracts/approval.js +9 -0
  115. package/dist/contracts/env-ref.d.ts +41 -0
  116. package/dist/contracts/env-ref.js +32 -0
  117. package/dist/contracts/errors.d.ts +56 -0
  118. package/dist/contracts/errors.js +266 -0
  119. package/dist/contracts/events.d.ts +70 -0
  120. package/dist/contracts/events.js +329 -0
  121. package/dist/contracts/index.d.ts +32 -0
  122. package/dist/contracts/index.js +26 -0
  123. package/dist/contracts/llm.d.ts +275 -0
  124. package/dist/contracts/llm.js +12 -0
  125. package/dist/contracts/messages.d.ts +63 -0
  126. package/dist/contracts/messages.js +65 -0
  127. package/dist/contracts/redact.d.ts +46 -0
  128. package/dist/contracts/redact.js +223 -0
  129. package/dist/contracts/tools.d.ts +197 -0
  130. package/dist/contracts/tools.js +33 -0
  131. package/dist/contracts/types.d.ts +302 -0
  132. package/dist/contracts/types.js +50 -0
  133. package/dist/contracts/ui.d.ts +122 -0
  134. package/dist/contracts/ui.js +15 -0
  135. package/dist/conversation/agent-service.js +61 -0
  136. package/dist/conversation/approval-wiring.js +82 -0
  137. package/dist/conversation/backoff.js +38 -0
  138. package/dist/conversation/codes.js +47 -0
  139. package/dist/conversation/control-tools.js +102 -0
  140. package/dist/conversation/control.js +210 -0
  141. package/dist/conversation/driver.js +922 -0
  142. package/dist/conversation/index.js +12 -0
  143. package/dist/conversation/model-visible.js +169 -0
  144. package/dist/conversation/open-tools.js +126 -0
  145. package/dist/conversation/reseed.js +132 -0
  146. package/dist/conversation/sessions.js +215 -0
  147. package/dist/conversation/todo.js +203 -0
  148. package/dist/conversation/types.js +35 -0
  149. package/dist/conversation/wiring.js +204 -0
  150. package/dist/credentials/codes.js +59 -0
  151. package/dist/credentials/commands.js +186 -0
  152. package/dist/credentials/env-ref.js +34 -0
  153. package/dist/credentials/index.js +28 -0
  154. package/dist/credentials/migration.js +18 -0
  155. package/dist/credentials/oauth.js +266 -0
  156. package/dist/credentials/refresh.js +152 -0
  157. package/dist/credentials/secrets.js +118 -0
  158. package/dist/credentials/types.js +30 -0
  159. package/dist/exec/bash.js +279 -0
  160. package/dist/exec/codes.js +37 -0
  161. package/dist/exec/env.js +99 -0
  162. package/dist/exec/environment.js +39 -0
  163. package/dist/exec/git-guard.js +623 -0
  164. package/dist/exec/index.js +24 -0
  165. package/dist/exec/registry.js +120 -0
  166. package/dist/exec/spawn.js +281 -0
  167. package/dist/exec/tail.js +77 -0
  168. package/dist/exec/types.js +5 -0
  169. package/dist/goal/codes.js +33 -0
  170. package/dist/goal/command.js +175 -0
  171. package/dist/goal/fold.js +121 -0
  172. package/dist/goal/gates.js +122 -0
  173. package/dist/goal/index.js +22 -0
  174. package/dist/goal/migration.js +48 -0
  175. package/dist/goal/service.js +501 -0
  176. package/dist/goal/todo-tool.js +174 -0
  177. package/dist/goal/types.js +1 -0
  178. package/dist/goal/update-tool.js +46 -0
  179. package/dist/host/approval-cmd.js +276 -0
  180. package/dist/host/assembly.js +1146 -0
  181. package/dist/host/boot-failures.js +104 -0
  182. package/dist/host/budget-advisory.js +74 -0
  183. package/dist/host/budget-broadcast.js +50 -0
  184. package/dist/host/builtins.js +54 -0
  185. package/dist/host/cli.js +544 -0
  186. package/dist/host/codes.js +120 -0
  187. package/dist/host/config-schema.js +195 -0
  188. package/dist/host/conversation-stack.js +654 -0
  189. package/dist/host/core-plugins.js +1685 -0
  190. package/dist/host/credentials-cmd.js +42 -0
  191. package/dist/host/disclosure.js +30 -0
  192. package/dist/host/dispatch.js +105 -0
  193. package/dist/host/doors-cmd.js +154 -0
  194. package/dist/host/dump-config.js +44 -0
  195. package/dist/host/hook-dispatch-guard.js +27 -0
  196. package/dist/host/import-gate.js +153 -0
  197. package/dist/host/index.js +54 -0
  198. package/dist/host/issue-session.js +241 -0
  199. package/dist/host/loader.js +372 -0
  200. package/dist/host/main.js +161 -0
  201. package/dist/host/manifest.js +381 -0
  202. package/dist/host/mcp-entry.js +53 -0
  203. package/dist/host/plugin-boot.js +952 -0
  204. package/dist/host/plugin-context.js +672 -0
  205. package/dist/host/plugin-install.js +480 -0
  206. package/dist/host/plugin-reload.js +124 -0
  207. package/dist/host/plugin-store.js +462 -0
  208. package/dist/host/plugin-tools.js +359 -0
  209. package/dist/host/plugin-uninstall.js +257 -0
  210. package/dist/host/plugins-cmd.js +302 -0
  211. package/dist/host/plugins-command.js +130 -0
  212. package/dist/host/plugins-config.js +195 -0
  213. package/dist/host/prompt-sections.js +133 -0
  214. package/dist/host/run-entry.js +544 -0
  215. package/dist/host/runtime.js +209 -0
  216. package/dist/host/scheduler-tick.js +294 -0
  217. package/dist/host/serve-daemon.js +501 -0
  218. package/dist/host/serve-entry.js +279 -0
  219. package/dist/host/session-anchor.js +41 -0
  220. package/dist/host/sessions-cmd.js +219 -0
  221. package/dist/host/sessions-face.js +47 -0
  222. package/dist/host/settings-store.js +112 -0
  223. package/dist/host/signals.js +69 -0
  224. package/dist/host/single-instance.js +105 -0
  225. package/dist/host/subagent-factory.js +291 -0
  226. package/dist/host/testkit/harness.js +283 -0
  227. package/dist/host/testkit/index.js +14 -0
  228. package/dist/host/testkit/matrix.js +302 -0
  229. package/dist/host/tool-policy-store.js +177 -0
  230. package/dist/host/triggers.js +212 -0
  231. package/dist/host/tui-entry.js +216 -0
  232. package/dist/host/webui-bridge.js +165 -0
  233. package/dist/issue/codes.js +38 -0
  234. package/dist/issue/filter.js +146 -0
  235. package/dist/issue/github.js +116 -0
  236. package/dist/issue/index.js +17 -0
  237. package/dist/issue/mount.js +70 -0
  238. package/dist/issue/poll.js +58 -0
  239. package/dist/issue/service.js +341 -0
  240. package/dist/issue/tools.js +70 -0
  241. package/dist/issue/types.js +34 -0
  242. package/dist/issue/webhook.js +126 -0
  243. package/dist/llm/codes.js +77 -0
  244. package/dist/llm/complete.js +196 -0
  245. package/dist/llm/events.js +15 -0
  246. package/dist/llm/index.js +24 -0
  247. package/dist/llm/inflight.js +65 -0
  248. package/dist/llm/model-id.js +58 -0
  249. package/dist/llm/provider-face.d.ts +32 -0
  250. package/dist/llm/provider-face.js +34 -0
  251. package/dist/llm/recovery.js +146 -0
  252. package/dist/llm/runtime.js +46 -0
  253. package/dist/llm/stream-fn.js +147 -0
  254. package/dist/lsp/codes.js +31 -0
  255. package/dist/lsp/connection.js +147 -0
  256. package/dist/lsp/frame.js +110 -0
  257. package/dist/lsp/index.js +16 -0
  258. package/dist/lsp/inject.js +58 -0
  259. package/dist/lsp/instance.js +264 -0
  260. package/dist/lsp/service.js +522 -0
  261. package/dist/lsp/tools.js +53 -0
  262. package/dist/lsp/types.js +201 -0
  263. package/dist/mcp/bridge.js +222 -0
  264. package/dist/mcp/codes.js +21 -0
  265. package/dist/mcp/index.js +19 -0
  266. package/dist/mcp/jsonrpc.js +230 -0
  267. package/dist/mcp/service.js +125 -0
  268. package/dist/mcp/tools.js +145 -0
  269. package/dist/mcp/types.js +108 -0
  270. package/dist/memory/cite.js +131 -0
  271. package/dist/memory/codes.js +50 -0
  272. package/dist/memory/command.js +71 -0
  273. package/dist/memory/consolidate.js +219 -0
  274. package/dist/memory/cycle.js +109 -0
  275. package/dist/memory/dao.js +878 -0
  276. package/dist/memory/diff.js +238 -0
  277. package/dist/memory/extract.js +181 -0
  278. package/dist/memory/fts.js +58 -0
  279. package/dist/memory/index.js +42 -0
  280. package/dist/memory/inject.js +354 -0
  281. package/dist/memory/merge.js +178 -0
  282. package/dist/memory/migration.js +132 -0
  283. package/dist/memory/pollution.js +59 -0
  284. package/dist/memory/port.js +385 -0
  285. package/dist/memory/review.js +201 -0
  286. package/dist/memory/scan.js +89 -0
  287. package/dist/memory/tools.js +508 -0
  288. package/dist/memory/types.js +140 -0
  289. package/dist/obs/codes.js +38 -0
  290. package/dist/obs/db.js +115 -0
  291. package/dist/obs/index.js +20 -0
  292. package/dist/obs/rollup.js +61 -0
  293. package/dist/obs/service.js +363 -0
  294. package/dist/obs/session-tools.js +282 -0
  295. package/dist/obs/session-view.js +225 -0
  296. package/dist/obs/tool.js +97 -0
  297. package/dist/obs/types.js +1 -0
  298. package/dist/persist/audit.js +63 -0
  299. package/dist/persist/aux.js +39 -0
  300. package/dist/persist/codes.js +35 -0
  301. package/dist/persist/index.js +30 -0
  302. package/dist/persist/load-history.js +50 -0
  303. package/dist/persist/migrations.js +37 -0
  304. package/dist/persist/paths.js +108 -0
  305. package/dist/persist/persistence.js +229 -0
  306. package/dist/persist/schema.js +99 -0
  307. package/dist/persist/secret-box.js +95 -0
  308. package/dist/persist/store.js +706 -0
  309. package/dist/persist/write-behind.js +238 -0
  310. package/dist/safety/approval.js +171 -0
  311. package/dist/safety/bwrap.js +123 -0
  312. package/dist/safety/codes.js +57 -0
  313. package/dist/safety/danger.js +505 -0
  314. package/dist/safety/gate.js +226 -0
  315. package/dist/safety/index.js +24 -0
  316. package/dist/safety/presets.js +73 -0
  317. package/dist/safety/roots.js +139 -0
  318. package/dist/safety/sandbox.js +214 -0
  319. package/dist/safety/seatbelt.js +88 -0
  320. package/dist/safety/sensitive.js +34 -0
  321. package/dist/safety/tool-policy.js +203 -0
  322. package/dist/safety/types.js +13 -0
  323. package/dist/scheduler/codes.js +54 -0
  324. package/dist/scheduler/cron-backend.js +135 -0
  325. package/dist/scheduler/engine.js +280 -0
  326. package/dist/scheduler/gates.js +60 -0
  327. package/dist/scheduler/index.js +25 -0
  328. package/dist/scheduler/migration.js +22 -0
  329. package/dist/scheduler/runner.js +171 -0
  330. package/dist/scheduler/schedule.js +193 -0
  331. package/dist/scheduler/service.js +283 -0
  332. package/dist/scheduler/tick.js +139 -0
  333. package/dist/scheduler/types.js +1 -0
  334. package/dist/sdk/http.js +865 -0
  335. package/dist/sdk/index.js +22 -0
  336. package/dist/sdk/mcp.js +289 -0
  337. package/dist/sdk/plugin-route-registry.js +126 -0
  338. package/dist/sdk/plugin-routes.js +149 -0
  339. package/dist/sdk/security.js +116 -0
  340. package/dist/sdk/types.js +32 -0
  341. package/dist/session/budget.js +159 -0
  342. package/dist/session/codes.js +40 -0
  343. package/dist/session/derive.js +180 -0
  344. package/dist/session/event-data.js +1 -0
  345. package/dist/session/fork.js +72 -0
  346. package/dist/session/import-gates.js +148 -0
  347. package/dist/session/index.js +18 -0
  348. package/dist/session/recover.js +103 -0
  349. package/dist/session/session.js +279 -0
  350. package/dist/session/snapshot.js +107 -0
  351. package/dist/skills/agents.js +242 -0
  352. package/dist/skills/codes.js +51 -0
  353. package/dist/skills/discovery.js +266 -0
  354. package/dist/skills/frontmatter.js +215 -0
  355. package/dist/skills/index.js +28 -0
  356. package/dist/skills/load.js +118 -0
  357. package/dist/skills/manage.js +201 -0
  358. package/dist/skills/registry.js +138 -0
  359. package/dist/skills/render.js +124 -0
  360. package/dist/skills/sections.js +171 -0
  361. package/dist/skills/types.js +21 -0
  362. package/dist/subagent/codes.js +50 -0
  363. package/dist/subagent/declarative.js +55 -0
  364. package/dist/subagent/index.js +19 -0
  365. package/dist/subagent/notify.js +51 -0
  366. package/dist/subagent/provide.js +7 -0
  367. package/dist/subagent/registry.js +149 -0
  368. package/dist/subagent/service.js +338 -0
  369. package/dist/subagent/surface.js +44 -0
  370. package/dist/subagent/tool.js +153 -0
  371. package/dist/subagent/types.js +25 -0
  372. package/dist/tools/apply-patch.js +164 -0
  373. package/dist/tools/codes.js +109 -0
  374. package/dist/tools/fs.js +501 -0
  375. package/dist/tools/index.js +17 -0
  376. package/dist/tools/observed.js +99 -0
  377. package/dist/tools/pipeline.js +176 -0
  378. package/dist/tools/protected-read.js +54 -0
  379. package/dist/tools/registry.js +250 -0
  380. package/dist/tools/search.js +451 -0
  381. package/dist/tools/worktree.js +327 -0
  382. package/dist/web/codes.js +37 -0
  383. package/dist/web/gate.js +43 -0
  384. package/dist/web/hygiene.js +195 -0
  385. package/dist/web/index.js +16 -0
  386. package/dist/web/service.js +207 -0
  387. package/dist/web/ssrf-guard.js +44 -0
  388. package/dist/web/tool.js +76 -0
  389. package/dist/web/types.js +10 -0
  390. package/dist/webui/assets/index-B-t2O8gh.js +22 -0
  391. package/dist/webui/assets/index-DOlgSZ9Q.css +2 -0
  392. package/dist/webui/index.html +14 -0
  393. package/dist/webui/index.js +14 -0
  394. package/dist/webui/server.js +549 -0
  395. package/dist/webui/types.js +38 -0
  396. package/examples/README.md +26 -0
  397. package/examples/minimal-code-plugin/entry.js +43 -0
  398. package/examples/minimal-code-plugin/package.json +12 -0
  399. package/examples/pure-skill-pack/package.json +14 -0
  400. package/examples/pure-skill-pack/skills/markdown-table/SKILL.md +32 -0
  401. package/package.json +86 -0
@@ -0,0 +1,203 @@
1
+ /**
2
+ * todo 机器(04 §8 todo 工具件 / 05 §1.1 todo/write 词行)——跨轮任务清单的
3
+ * durable 事实 + fold 推导 + 模型回看注入 + 工具件四件套。
4
+ *
5
+ * 语义单源 = 05 §1.1 词行:
6
+ * - durable 词 `todo/write`(类别 surface,items 全量快照、last-write-wins);
7
+ * - **fold = 日志倒扫「最后一条可见 user/message 之后的最后一条本事件」**
8
+ * (run 重置语义由推导规则承载、无显式 reset 词;遮蔽区间内的事件不参与
9
+ * fold——occluded 的 user/message 不重置、occluded 的 todo/write 不成表,
10
+ * 两向同律:对模型不可见即从未发生);
11
+ * - 跨 turn 每轮注入当前全表(CC 式回看),走 context_transform 瀑布最后
12
+ * 关口的瞬态层——角色 `conversation/todo`(hidden 瞬态,不进 timeline 不落
13
+ * durable,llmContext 每请求新建故零累积);冷启动 resume 首请求同样覆盖
14
+ * (fold 在请求时点对 durable 日志重放);
15
+ * - 工具形态 = 全量快照式提交(模型每次提交完整清单覆盖旧表)+ 一行计数
16
+ * 回执。
17
+ *
18
+ * 呈现投影(channels TodoItem 四态记号面板)与 durable 形有意分立:conversation
19
+ * 不得 import channels(DAG 边表),字段形状以注释互镜;status 四值两处同词表。
20
+ */
21
+ import { Type } from 'typebox';
22
+ import { getMessageRoleDefinition, registerMessageRole, } from '../contracts/index.js';
23
+ import { occludedSeqs } from '../session/index.js';
24
+ /** todo 回看注入角色名(域名前缀两段式——conversation 域) */
25
+ export const TODO_ROLE = 'conversation/todo';
26
+ /** status 四值词表(schema 与 fold 校验共用单源) */
27
+ const TODO_STATUSES = ['pending', 'in-progress', 'completed', 'deferred'];
28
+ /**
29
+ * 角色定义(模块级单例——身份同一性判据):toLlm 全表渲染为一条 UserMessage
30
+ * 尾注(清空表返回 null 剥离);render hidden(瞬态注入,呈现面不可见——
31
+ * UI 投影走 durable todo/write 事件,不经此角色)。
32
+ */
33
+ const TODO_ROLE_DEFINITION = {
34
+ toLlm: (message) => {
35
+ const items = validateTodoItems(message.content);
36
+ if (items.length === 0)
37
+ return null;
38
+ return {
39
+ role: 'user',
40
+ content: renderTodoTable(items),
41
+ timestamp: message.timestamp,
42
+ };
43
+ },
44
+ render: { intent: 'hidden', label: '任务清单' },
45
+ };
46
+ /**
47
+ * 注册 todo 角色(幂等 + 身份守卫):进程级注册表 + per-session 驱动 ⇒ 多次
48
+ * 调用常态。在册定义恰为本模块单例 → 幂等通过;在册定义另有其身 → 域名
49
+ * 被窃据,fail-loud(不静默借用他者转写——消息转写分叉比崩溃更难查)。
50
+ */
51
+ export function ensureTodoRole() {
52
+ const existing = getMessageRoleDefinition(TODO_ROLE);
53
+ if (existing !== undefined) {
54
+ if (existing !== TODO_ROLE_DEFINITION) {
55
+ throw new Error(`消息角色 ${TODO_ROLE} 已被其他定义占用(conversation 域名窃据——todo 回看注入拒绝分叉转写)`);
56
+ }
57
+ return;
58
+ }
59
+ registerMessageRole(TODO_ROLE, TODO_ROLE_DEFINITION);
60
+ }
61
+ /**
62
+ * fold 当前任务清单(05 §1.1 倒扫规则,遮蔽感知):
63
+ * 从日志尾向头扫**可见**事件——
64
+ * - 先遇 `todo/write` → 其 items 即当前表(last-write-wins);
65
+ * - 先遇可见 `user/message` → 空表(用户出手即重置——重置语义由推导承载);
66
+ * - 扫到头 → 空表(从未建表)。
67
+ * assistant 消息与工具事件不参与判据(清单跨 assistant 轮持续——CC 语义)。
68
+ *
69
+ * goal 段升格(03 §10.5 计划态跨轮条):scope 在场(goal active——组合根
70
+ * `goalScopeFor(sessionId)` 闭包注入)时 fold 边界从「用户输入段」升格
71
+ * 「goal 生命周期段」——倒扫只取激活锚 `activatedSeq` 之后的最后一条
72
+ * `todo/write`,**续跑轮 user/message 不再重置表**(计划状态结构性跨轮
73
+ * 存活);goal 段载荷扩展字段(resumeWhen/role/taskClass/followUp/gate 等)
74
+ * 由 validateTodoItems 剥离(本 fold 只投影核心四字段——扩展语义归 goal 件
75
+ * fold 读侧,词面独立零 import)。
76
+ */
77
+ export function foldTodoTable(events, scope) {
78
+ const occluded = occludedSeqs(events);
79
+ for (let seq = events.length - 1; seq >= 0; seq -= 1) {
80
+ if (occluded.has(seq))
81
+ continue;
82
+ const event = events[seq];
83
+ // goal 段边界:越激活锚即出段(锚前历史不成表——goal 生命周期段语义;
84
+ // 下标即 seq——「seq = 写入时 log.length」不变式下单源)
85
+ if (scope !== undefined && seq < scope.activatedSeq)
86
+ return [];
87
+ if (event.type === 'todo/write')
88
+ return validateTodoItems(event.data.items);
89
+ // goal 段内 user/message 不重置(跨轮存活);无 scope 保持 run-scoped 重置
90
+ if (scope === undefined && event.type === 'user/message')
91
+ return [];
92
+ }
93
+ return [];
94
+ }
95
+ /** 四态中文计数(回执与渲染表头共用词面) */
96
+ function countByStatus(items) {
97
+ const counts = { pending: 0, 'in-progress': 0, completed: 0, deferred: 0 };
98
+ for (const item of items)
99
+ counts[item.status] += 1;
100
+ return counts;
101
+ }
102
+ /**
103
+ * 渲染清单为模型可见文本(快照注入体 + 工具回执共用单源):
104
+ * 表头一行计数总览 + 每条目一行(status 标签稳定英文词——模型可编程依赖;
105
+ * 进行中态 activeForm 优先于 content 呈现,与呈现投影同律)。
106
+ */
107
+ export function renderTodoTable(items) {
108
+ if (items.length === 0)
109
+ return '';
110
+ const counts = countByStatus(items);
111
+ const header = `当前任务清单(共 ${items.length} 项:` +
112
+ `进行中 ${counts['in-progress']} · 待办 ${counts.pending} · ` +
113
+ `已完成 ${counts.completed} · 缓办 ${counts.deferred}):`;
114
+ const lines = items.map((item, index) => {
115
+ const body = item.status === 'in-progress' && item.activeForm !== undefined ? item.activeForm : item.content;
116
+ return `${index + 1}. [${item.status}] ${body}`;
117
+ });
118
+ return [header, ...lines].join('\n');
119
+ }
120
+ /**
121
+ * 构建跨 turn 注入快照消息:空表返回 null(不注入——从未建表/已重置语义下
122
+ * 不打扰上下文);非空走角色的 toLlm 转写(ensureTodoRole 自足——快照构建
123
+ * 不依赖驱动侧先行注册)。timestamp 取请求时点(注入体的时间面)。
124
+ * scope 在场 = goal 段 fold(升格语义见 foldTodoTable 头注)。
125
+ */
126
+ export function todoSnapshotMessage(events, timestamp, scope) {
127
+ const items = foldTodoTable(events, scope);
128
+ if (items.length === 0)
129
+ return null;
130
+ ensureTodoRole();
131
+ const converted = TODO_ROLE_DEFINITION.toLlm?.({ role: TODO_ROLE, content: items, timestamp });
132
+ // 定义体在本模块单源——非空表必产单条 user;运行时窄化防御仅挡未来改动
133
+ if (converted === undefined || converted === null || Array.isArray(converted) || converted.role !== 'user') {
134
+ return null;
135
+ }
136
+ return converted;
137
+ }
138
+ /**
139
+ * todo 工具件(04 §8):全量快照式提交——每次调用提交完整清单覆盖旧表
140
+ * (增删改全走同一路径,无局部更新动词面)。effect 'read':写的是 surface
141
+ * 状态(todo/write 词)非文件系统,不触发审批对与守门拦截面。
142
+ *
143
+ * append 回调 = durable 写入面(装配层注入 session.append 闭包——本件不
144
+ * 直接依赖 SessionLog,纯函数件可独立测试)。
145
+ */
146
+ export function createTodoTool(append) {
147
+ return {
148
+ name: 'todo',
149
+ description: '维护当前任务清单(全量快照式:每次调用提交完整清单覆盖旧表,含增删改与' +
150
+ '清空)。清单跨对话轮持续可见(每轮自动回看注入),用户出手后重置为空。' +
151
+ '适合多步骤任务的进度自查——一次只专注一件事,进行中的条目置 in-progress。',
152
+ parameters: Type.Object({
153
+ items: Type.Array(Type.Object({
154
+ status: Type.Union(TODO_STATUSES.map((status) => Type.Literal(status))),
155
+ content: Type.String(),
156
+ activeForm: Type.Optional(Type.String()),
157
+ },
158
+ // 条目面收紧:多余字段整体拒收(goal 段扩展字段不在此消化——
159
+ // GOAL_TODO_SCOPE 执法归 goal 件批,本件 schema 即第一道闸)
160
+ { additionalProperties: false })),
161
+ }, { additionalProperties: false }),
162
+ effect: 'read',
163
+ execute: async (args) => {
164
+ // 管道已按 schema 校验过参数;validate 再产新拷贝(append 快照拷贝前的
165
+ // 干净形——不带 undefined 可选腿)并防御读侧漂移
166
+ const items = validateTodoItems(args.items);
167
+ append({ items: items.map((item) => ({ ...item })) });
168
+ const counts = countByStatus(items);
169
+ const receipt = `已更新任务清单:${items.length} 项` +
170
+ `(进行中 ${counts['in-progress']} · 待办 ${counts.pending} · ` +
171
+ `已完成 ${counts.completed} · 缓办 ${counts.deferred})`;
172
+ return { content: [{ type: 'text', text: receipt }] };
173
+ },
174
+ };
175
+ }
176
+ /**
177
+ * 未知载荷 → 条目形列表(fold 读侧与工具写侧共用的收窄面):非对象元素 /
178
+ * status 出词表 / content 非串 → 整条丢弃(保守降级不 fail-loud——durable
179
+ * 日志受信但 owner 形演进不得崩读侧);activeForm 仅收 string 型缺席剔除。
180
+ */
181
+ function validateTodoItems(value) {
182
+ if (!Array.isArray(value))
183
+ return [];
184
+ const items = [];
185
+ for (const entry of value) {
186
+ if (typeof entry !== 'object' || entry === null)
187
+ continue;
188
+ const candidate = entry;
189
+ if (typeof candidate.status !== 'string' ||
190
+ !TODO_STATUSES.includes(candidate.status) ||
191
+ typeof candidate.content !== 'string') {
192
+ continue;
193
+ }
194
+ items.push(typeof candidate.activeForm === 'string'
195
+ ? {
196
+ status: candidate.status,
197
+ content: candidate.content,
198
+ activeForm: candidate.activeForm,
199
+ }
200
+ : { status: candidate.status, content: candidate.content });
201
+ }
202
+ return items;
203
+ }
@@ -0,0 +1,35 @@
1
+ /** RetryPolicy 缺省(04 §3.3 条 6 定值:enabled / 3 次 / 1000ms 基值) */
2
+ export const DEFAULT_RETRY_POLICY = {
3
+ enabled: true,
4
+ maxRetries: 3,
5
+ baseDelayMs: 1000,
6
+ };
7
+ /** 唤醒预算帽(04 §4 定值:连续后台唤醒计数上限——批消费位记账) */
8
+ export const MAX_CONSECUTIVE_WAKES = 3;
9
+ /**
10
+ * context_transform 钩子事件词(03 §2.4 主表 message 层行——mode waterfall)。
11
+ * LLM 请求组装最后关口:驱动发射、插件经 ctx.on 挂管线监听器(不调 next 即
12
+ * 短路——管线语义)。词汇注册双源幂等:bootPlugins 预注册 41 词在前,驱动
13
+ * 构造器自举在后(已注册词跳过——一词两册不撞名,open-tools 同律)。
14
+ */
15
+ export const CONTEXT_TRANSFORM_EVENT = 'context_transform';
16
+ /**
17
+ * agent_pre_step 钩子事件词(03 §2.4 主表 message 层行——mode waterfall)。
18
+ * 每次模型请求前发射(loop while 体顶、steering 消费与 turn_start 之前——
19
+ * 预算刹停不产生 dangling turn):驱动发射、插件经 ctx.on 挂瀑布监听器。
20
+ * 消费例:goal 预算复验(04 §5 双轨第二腿——budgetExceeded 步间复查防
21
+ * 记账腿与执行腿竞速漏刹)、压缩压力挂点。词汇注册双源幂等:
22
+ * bootPlugins 预注册在前,驱动构造器自举在后(CONTEXT_TRANSFORM_EVENT
23
+ * 同律)。
24
+ */
25
+ export const AGENT_PRE_STEP_EVENT = 'agent_pre_step';
26
+ /**
27
+ * session/lifecycle 活体事件词(04 §6 在飞状态活体词——e-2 观测腿)。
28
+ * run 起/终态广播:驱动 kick 起拍 + runTurns finally 终态拍两发、宿主包装层
29
+ * 按订阅作用域(self|tree|all)过滤派发。**活体不落日志**(dispatch 内存
30
+ * 直推——job_settled 同律;durable 真源 = 事件流尾条推导〔03 §10.8〕——推送
31
+ * 是推导的投影非第二真相源)。词汇注册双源幂等:装配根预注册(插件装载期
32
+ * 订阅可达——boot 先于首会话起跑)在前、驱动构造器自举在后(已注册词跳过
33
+ * ——CONTEXT_TRANSFORM_EVENT 同律)。
34
+ */
35
+ export const SESSION_LIFECYCLE_EVENT = 'session/lifecycle';
@@ -0,0 +1,204 @@
1
+ /**
2
+ * durable 接线器(驱动私有件——活体事件翻译 + 请求信封快照 + 锚 seq 记账)。
3
+ *
4
+ * 构造时从既有日志初始化三态(turn 开合 / header 在否 / 冷启动续接位)——
5
+ * 会话恢复与新建同路(05 §1.3 恢复 = 重放:接线器状态就是日志状态的折叠)。
6
+ */
7
+ export class DurableWiring {
8
+ session;
9
+ /** durable turn 开合态(agent_end 安全网与 turn_start 判据共用) */
10
+ turnOpen;
11
+ /** 日志是否已有 request/header(initial 判据) */
12
+ hasHeader;
13
+ /** timeline 重建后的首请求标记(resume 判据——遮蔽重播种/冷启动置位) */
14
+ rebuildPending;
15
+ /** 上一信封快照的比对键(change 判据——JSON 序列化同构比对) */
16
+ lastEnvelopeKey;
17
+ /** 最后一条 assistant/message 的 seq(runTurns 遮蔽区间的起点锚) */
18
+ lastAssistantSeqValue;
19
+ /** 工具归因取值器(tool/call 载荷 owner 位——缺席 = 载荷不带 owner) */
20
+ resolveToolOwner;
21
+ constructor(session, options = {}) {
22
+ this.session = session;
23
+ this.resolveToolOwner = options.resolveToolOwner;
24
+ let depth = 0;
25
+ let header = false;
26
+ for (const event of session.events()) {
27
+ if (event.type === 'turn/start')
28
+ depth += 1;
29
+ else if (event.type === 'turn/end' && depth > 0)
30
+ depth -= 1;
31
+ else if (event.type === 'request/header')
32
+ header = true;
33
+ }
34
+ this.turnOpen = depth > 0;
35
+ this.hasHeader = header;
36
+ // 冷启动续接(日志已有 header):首请求 resume 形——11d resume 续接的先手位
37
+ this.rebuildPending = header;
38
+ }
39
+ /** 最后一条 assistant/message 的锚 seq(重试遮蔽区间起点——驱动消费) */
40
+ get lastAssistantSeq() {
41
+ return this.lastAssistantSeqValue;
42
+ }
43
+ /** timeline 重建标记(重播种/压缩后置位——下一请求 header 落 resume) */
44
+ markRebuildPending() {
45
+ this.rebuildPending = true;
46
+ }
47
+ /**
48
+ * inject 通道直落账(04 §4 inject 行 / berry 停摆语义:只追加会话日志/
49
+ * 投影、不触发任何模型调用——「随下次启动带入」的 durable 承载)。durable
50
+ * 写点单归本件(驱动不绕过接线器直写 session)。
51
+ * @returns 落账 seq(inject 收执面)
52
+ */
53
+ appendInjectedUser(message) {
54
+ const event = this.session.append('user/message', {
55
+ content: message.content,
56
+ ...(message.source !== undefined ? { source: message.source } : {}),
57
+ ...(message.dedupeKey !== undefined ? { dedupeKey: message.dedupeKey } : {}),
58
+ });
59
+ return event.seq;
60
+ }
61
+ /**
62
+ * 请求信封快照(边界制——transformContext 关口调用,请求发出前落账)。
63
+ * initial / resume / change 三边界各落一条;稳态不落。
64
+ */
65
+ noteRequest(envelope) {
66
+ const key = JSON.stringify({
67
+ config: envelope.config,
68
+ systemPrompt: envelope.systemPrompt,
69
+ tools: envelope.toolSchemas,
70
+ });
71
+ let reason;
72
+ if (!this.hasHeader)
73
+ reason = 'initial';
74
+ else if (this.rebuildPending)
75
+ reason = 'resume';
76
+ else if (key !== this.lastEnvelopeKey)
77
+ reason = 'change';
78
+ else
79
+ return; // 稳态——最后一条基准仍真,不重复快照
80
+ this.session.append('request/header', {
81
+ config: envelope.config,
82
+ systemPrompt: envelope.systemPrompt,
83
+ toolSchemas: envelope.toolSchemas,
84
+ reason,
85
+ });
86
+ this.hasHeader = true;
87
+ this.rebuildPending = false;
88
+ this.lastEnvelopeKey = key;
89
+ }
90
+ /**
91
+ * 活体事件翻译(onEvent 汇的第一腿——外部汇是第二腿,两腿同源同序)。
92
+ * 只认消息级终值与轮边界;其余事件型零翻译(流式细节属活体层)。
93
+ */
94
+ onEvent(event) {
95
+ switch (event.type) {
96
+ case 'turn_start': {
97
+ // 无打开 durable turn 才开(工具批延续轮/重试续入轮同判据)
98
+ if (!this.turnOpen) {
99
+ this.session.append('turn/start', {});
100
+ this.turnOpen = true;
101
+ }
102
+ return;
103
+ }
104
+ case 'turn_end': {
105
+ if (!this.turnOpen)
106
+ return; // 防御:配对外的 turn_end(不应出现)
107
+ // toolUse 不闭(轮内继续);length 延到 agent_end(截断配对结果先落)
108
+ if (event.stopReason === 'toolUse' || event.stopReason === 'length')
109
+ return;
110
+ this.closeTurn(turnEndReasonOf(event.stopReason));
111
+ return;
112
+ }
113
+ case 'agent_end': {
114
+ // 安全网:turn 仍开(工具批后打断/length 配对后)→ 按终态补收口
115
+ if (!this.turnOpen)
116
+ return;
117
+ const reason = event.stopReason === 'length'
118
+ ? 'max-tokens'
119
+ : event.status === 'completed'
120
+ ? 'completed'
121
+ : event.status === 'aborted'
122
+ ? 'aborted'
123
+ : 'error';
124
+ this.closeTurn(reason);
125
+ return;
126
+ }
127
+ case 'message_end': {
128
+ this.appendMessage(event.message);
129
+ return;
130
+ }
131
+ default:
132
+ // message_start/update、tool_execution_*、agent_start——活体层专属
133
+ return;
134
+ }
135
+ }
136
+ /** 落 turn/end 并闭 turn(turn_end 与 agent_end 安全网共用) */
137
+ closeTurn(reason) {
138
+ this.session.append('turn/end', { reason });
139
+ this.turnOpen = false;
140
+ }
141
+ /** 消息级终值翻译(标准三角色各走各的 durable 词;自定义角色暂无 durable 写点) */
142
+ appendMessage(message) {
143
+ const role = message.role;
144
+ if (role === 'user') {
145
+ const user = message;
146
+ this.session.append('user/message', {
147
+ content: user.content,
148
+ ...(user.source !== undefined ? { source: user.source } : {}),
149
+ ...(user.dedupeKey !== undefined ? { dedupeKey: user.dedupeKey } : {}),
150
+ });
151
+ return;
152
+ }
153
+ if (role === 'assistant') {
154
+ const assistant = message;
155
+ // toolCall 块不内联(05 §1.1——内联+事件双载会在投影回读拼出重复块);
156
+ // text/thinking 块原样透传(签名位随行——pi-ai 投影形状)
157
+ const content = assistant.content.filter((block) => block.type !== 'toolCall');
158
+ const event = this.session.append('assistant/message', {
159
+ content,
160
+ usage: assistant.usage,
161
+ stopReason: assistant.stopReason,
162
+ ...(assistant.errorMessage !== undefined ? { errorMessage: assistant.errorMessage } : {}),
163
+ });
164
+ this.lastAssistantSeqValue = event.seq;
165
+ // 工具调用分立落账:arguments 回写原始串(审计保真——读侧解析失败兜底 {});
166
+ // owner 归因位写时带出(05 §1.1——T9 案一批 R2 案 A:调用流直读「这次
167
+ // 调用是谁的」读侧零 join)。可选带出形(dedupeKey 同律):resolver
168
+ // 缺席或未命中(装配残缺——模型调用的名必然在当次请求面内,未命中即
169
+ // 装配缺陷)不带 owner,不虚构归因
170
+ for (const block of assistant.content) {
171
+ if (block.type !== 'toolCall')
172
+ continue;
173
+ const owner = this.resolveToolOwner?.(block.name);
174
+ this.session.append('tool/call', {
175
+ toolCallId: block.id,
176
+ name: block.name,
177
+ arguments: JSON.stringify(block.arguments),
178
+ ...(owner !== undefined ? { owner } : {}),
179
+ });
180
+ }
181
+ return;
182
+ }
183
+ if (role === 'toolResult') {
184
+ const result = message;
185
+ this.session.append('tool/result', {
186
+ toolCallId: result.toolCallId,
187
+ content: result.content,
188
+ ...(result.isError ? { error: true } : {}),
189
+ });
190
+ return;
191
+ }
192
+ // 自定义角色(memory/recall 等):瞬态注入纪律不落 durable;非瞬态自定义
193
+ // 角色的落账词随 11f/记忆批纵切裁决——当前零写点,静默跳过即唯一诚实行为
194
+ }
195
+ }
196
+ /** loop 终态值 → durable turn/end reason(TurnEndReason 闭集内归位) */
197
+ function turnEndReasonOf(stopReason) {
198
+ if (stopReason === 'aborted')
199
+ return 'aborted';
200
+ if (stopReason === 'error')
201
+ return 'error';
202
+ // stop / deferred——自然收尾(deferred 是延迟装载透传值,v1 不产生但词汇保留)
203
+ return 'completed';
204
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * credentials 域错误码注册(02 §5.3 族前缀 `CREDENTIALS_`——c-1 规范先行批
3
+ * 明列三码;03 §10.9 错误码族 bullet 真源)。
4
+ *
5
+ * 码语义分层:一码守 get 作用名缺席(NOT_FOUND——GOAL_NOT_FOUND 同构
6
+ * 守卫);一码管 namespace 隔离与跨域门检(NAMESPACE_DENIED——同码分流:
7
+ * 未开门越域拒 / namespace 坏形拒,两档共用 message 底稿指路开门位写法);
8
+ * 一码管受理窗外写拒(WRITE_WINDOW_CLOSED——宿主回调窗执法,12f-2a
9
+ * PLUGIN_WINDOW_CLOSED 唯一例外位的凭证面同律);一码管注入腿引用形坏形
10
+ * (ENV_REF_INVALID——c-4:前缀命中而名空,exec env.ts 抛出)。
11
+ *
12
+ * oauth 流内码三枚(c-6 扩族——03 §10.9 错误码族 bullet 兑现):用户拒授
13
+ * (DENIED——token 端点 access_denied,授权页明确拒绝)/ 态坏过期
14
+ * (EXPIRED——设备码轮询窗超窗 + expired_token + refresh 凭据失效 invalid_grant
15
+ * 三形同码:共同语义 = 授权态已坏、重试无益、须重新发起授权流)/ 协议传输
16
+ * 兜底(FLOW_FAILED——端点非预期应答/载荷坏形/网络错,重试可期)。
17
+ *
18
+ * 密钥物理面既有码 PERSIST_SECRET_UNREADABLE(05 §9)复用不重立。
19
+ *
20
+ * 本文件由模块公开面 index.ts 引入(注册纪律:import 发生才注册)。
21
+ */
22
+ import { registerErrorCodes } from '../contracts/index.js';
23
+ registerErrorCodes([
24
+ {
25
+ code: 'CREDENTIALS_NOT_FOUND',
26
+ module: 'credentials',
27
+ description: 'get 作用名缺席守卫——自域/越域读命中不存在的凭证名响亮拒(GOAL_NOT_FOUND 同构)',
28
+ },
29
+ {
30
+ code: 'CREDENTIALS_NAMESPACE_DENIED',
31
+ module: 'credentials',
32
+ description: 'namespace 隔离执法——同码分流两档:未开门越域读拒(credentials.read-cross 高危面默认关,开门位 = 启用清单 opens)/ namespace 坏形拒(非 host 且非 plugin:<id> 值域)',
33
+ },
34
+ {
35
+ code: 'CREDENTIALS_WRITE_WINDOW_CLOSED',
36
+ module: 'credentials',
37
+ description: '受理窗外写拒——ctx.secrets.set 只在宿主回调窗内可达(用户发起 oauth 授权流 → 宿主回调插件 handler → 窗内写;03 §10.9 写入面复合案)',
38
+ },
39
+ {
40
+ code: 'CREDENTIALS_ENV_REF_INVALID',
41
+ module: 'credentials',
42
+ description: 'env 引用形坏形(c-4 注入腿)——set 值前缀 @credentials: 命中而名空,响亮拒字面注入;词面单源 contracts/env-ref.ts',
43
+ },
44
+ {
45
+ code: 'CREDENTIALS_OAUTH_DENIED',
46
+ module: 'credentials',
47
+ description: 'oauth 授权流用户拒授——token 端点 error=access_denied(授权页明确拒绝;重发流可再试)',
48
+ },
49
+ {
50
+ code: 'CREDENTIALS_OAUTH_EXPIRED',
51
+ module: 'credentials',
52
+ description: 'oauth 授权态坏过期(三形同码:设备码轮询窗超窗 / token 端点 error=expired_token / refresh 凭据失效 error=invalid_grant——重试无益,须重新发起 /credentials oauth)',
53
+ },
54
+ {
55
+ code: 'CREDENTIALS_OAUTH_FLOW_FAILED',
56
+ module: 'credentials',
57
+ description: 'oauth 流协议/传输面失败兜底——端点非预期应答、载荷坏形(缺 device_code/access_token 等)、网络传输错;重试可期',
58
+ },
59
+ ]);