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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 berry-agent contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # berry-agent
2
+
3
+ 单一、可扩展的个人 Agent——对话与编码即本体,一切能力以**插件**装载。
4
+ TypeScript + SQLite + [pi-ai](https://github.com/earendil-works/pi-ai)。
5
+
6
+ > 状态:`0.1.0-alpha.1`,开发中——契约先行、逐批纵切落地;官方插件 16 件已随包出厂。包尚未在 npm 首发——下方两路安装待首发后可用,源码构建即时可用(见[使用指南](./docs/usage.md#安装))。
7
+
8
+ 核心理念:**基座强在接口,能力长在插件**——扩展点/钩子/事件/服务面做满做稳,任何能力(shell 执行、技能、浏览器、定时任务、记忆、Web 界面……)都以插件装载表达;官方件与社区件走同一装载面,第一方无私有车道。
9
+
10
+ ## 安装
11
+
12
+ 要求 Node.js ≥ 24。两路任选:
13
+
14
+ ```bash
15
+ # 路一:安装脚本(两段式——先落盘再执行;不要用管道直灌,断流会让 shell 执行半截脚本)
16
+ curl -fsSL -o install.sh https://raw.githubusercontent.com/miuiadmin/berry-agent/main/scripts/install.sh
17
+ sh install.sh
18
+
19
+ # 路二:npm
20
+ npm install -g berry-agent
21
+ ```
22
+
23
+ 从源码构建见[使用指南](./docs/usage.md#安装);卸载见[使用指南](./docs/usage.md#卸载)。
24
+
25
+ ## 快速开始
26
+
27
+ ```bash
28
+ berry-agent # TUI:直进对话(按当前目录续接最新会话)
29
+ berry-agent run "一句话单发" # 单次执行 → stdout
30
+ berry-agent sessions list # 会话管理:list / resume / fork / search / reindex
31
+ berry-agent plugins list # 插件装机管理:list / check / install / uninstall / mount / unmount / toggle / update
32
+ berry-agent credentials list # 凭证管理:add / list / rm(TUI 另有 oauth 授权流)
33
+ berry-agent doors list # 开门制门态只读(开/关走 TUI /doors open|close)
34
+ berry-agent serve --port 7860 # 常驻宿主(Web 界面 + /v1/* 程序调用面)
35
+ ```
36
+
37
+ 首启自动创建 `~/.berry-agent/`。模型缺省 `anthropic/claude-sonnet-5`,凭证按 provider 生态变量供给(如 `ANTHROPIC_API_KEY`),`BERRY_AGENT_MODEL` 可覆盖。
38
+
39
+ 完整命令族、旗标、环境变量与 TUI 键位见[使用指南](./docs/usage.md)。
40
+
41
+ ## 官方插件 16 件(默认启用,可禁用)
42
+
43
+ `core:exec`(shell 执行)· `core:skills`(技能)· `core:web`(网络取数)· `core:scheduler`(定时任务)· `core:goal`(目标续跑)· `core:subagent`(子代理)· `core:checkpoint`(边界快照/rewind)· `core:memory`(记忆)· `core:mcp`(MCP 客户端)· `core:lsp`(LSP 客户端)· `core:browser`(浏览器)· `core:webui`(Web 界面)· `core:sdk`(自动化通道)· `core:obs`(观测)· `core:issue`(issue 模式)· `core:credentials`(凭证代管)
44
+
45
+ ## 自动化通道
46
+
47
+ - **npm SDK**:`npm install berry-agent-sdk`——类型化客户端(spawn stdio / 直连 HTTP 两传输);
48
+ - **MCP**:`berry-agent mcp` 以 MCP server 形态暴露两工具,任意 MCP 客户端可接入;
49
+ - **守护**:`serve --daemon` + `serve status` / `serve stop`。
50
+
51
+ ## 环境变量
52
+
53
+ 前缀一律 `BERRY_AGENT_*`:
54
+
55
+ | 变量 | 作用 | 缺省 |
56
+ | ------------------------------------ | ------------------------------------------------------- | --------------------------- |
57
+ | `BERRY_AGENT_MODEL` | 覆盖缺省模型 | `anthropic/claude-sonnet-5` |
58
+ | `BERRY_AGENT_DATA_DIR` | 数据目录 | `~/.berry-agent` |
59
+ | `BERRY_AGENT_DB_PATH` | 库文件路径(独立梯子) | `<数据目录>/sessions.db` |
60
+ | `BERRY_AGENT_LOG_LEVEL` | error / warn / info / debug / silent | `info` |
61
+ | `BERRY_AGENT_BASH_PATH` | bash 可执行路径 | PATH 发现序 |
62
+ | `BERRY_AGENT_FD_PATH` | `@` 补全的 fd 路径(保留位——fd 批未触,当前仅内置遍历) | — |
63
+ | `BERRY_AGENT_BROWSER_PATH` | 浏览器引擎路径 | 引擎发现序 |
64
+ | `BERRY_AGENT_PLUGIN_MIN_RELEASE_AGE` | 插件装机供应链护栏:npm 源最小发布龄分钟数(0 = 关窗) | 1440 |
65
+ | `BERRY_AGENT_MAX_CONCURRENT_RUNS` | 宿主级 run 并发帽(lane 帽——正整数必需,坏值 fail-loud 拒启;steer/inject 不经闸) | 16 |
66
+
67
+ ## 遥测
68
+
69
+ **默认不发任何网络包**——无使用统计、无崩溃上报、无版本检查。出厂网络面 = 凭证供给的模型调用 + 用户显式动作(fetch 工具 / `--port` 开面 / 插件装机与更新 / upgrade 维护动词),此外零。详见[运维手册](./docs/operations.md#遥测立场)。
70
+
71
+ ## 文档
72
+
73
+ | 册 | 内容 |
74
+ | -------------------------------------------- | ------------------------------------ |
75
+ | [架构总览](./docs/architecture.md) | 分层、模块拓扑、运行时骨架、安全模型 |
76
+ | [使用指南](./docs/usage.md) | 安装、命令族、TUI、环境变量 |
77
+ | [插件开发指南](./docs/plugin-development.md) | manifest、ctx 能力面、扩展点、发布 |
78
+ | [开发指南](./docs/development.md) | 门禁、拓扑律、测试纪律、贡献流程 |
79
+ | [运维手册](./docs/operations.md) | 数据目录、备份恢复、故障排查 |
80
+
81
+ ## 开发
82
+
83
+ ```bash
84
+ npm install
85
+ npm run typecheck # 门禁一:tsc --noEmit
86
+ npm test # 门禁二:vitest run
87
+ npm run lint:topology # 门禁三:模块 DAG 边表 + API 治理面门禁
88
+ npm run format:check # 门禁四:prettier 检查
89
+ npm run build # 构建链(webui → tsc → API 声明快照)
90
+ ```
91
+
92
+ 四门禁提交前全绿。贡献流程见[开发指南](./docs/development.md)与 [CONTRIBUTING](./CONTRIBUTING.md)。
93
+
94
+ ## License
95
+
96
+ [MIT](./LICENSE)
@@ -0,0 +1 @@
1
+ 2026-09-13T16:30:46.861Z
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": "0.1.0-alpha.1",
3
+ "commit": "6e0508e",
4
+ "builtAt": "2026-09-13T16:30:47.027Z",
5
+ "node": "24.18.0"
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export { PendingMessageQueue, DEFAULT_QUEUE_CAPACITY } from './queue.js';
2
+ export { startRun, continueRun } from './loop.js';
@@ -0,0 +1,139 @@
1
+ /**
2
+ * agent 件 — loop 骨架(04 §2 形态铁律:双 while、≤150 行、零 try/catch、零存储感知)。
3
+ * 外层 turn 循环:steering 注入 → 流消费 → 终态判定 → 工具批 → followUp 续跑裁决。
4
+ * 内层流消费与工具批执行分别住在 stream.ts / tools-batch.ts(骨架只留控制流)。
5
+ * 全部策略经注入回调(AgentLoopConfig 12 项)、全部状态经活体事件回流——
6
+ * loop 不知道 conversation 存在;错误不就地 try/catch(StreamFn 永不抛契约),失败由 run 终态承载(04 §2/§3)。
7
+ */
8
+ import { BaseError } from '../contracts/index.js';
9
+ import { streamAssistantResponse } from './stream.js';
10
+ import { executeToolBatch } from './tools-batch.js';
11
+ /** 种子/续跑消息入列(steering 顶注与 followUp 续跑共用——channel 随事件披露) */
12
+ function pushAll(context, messages, emit, channel) {
13
+ for (const message of messages) {
14
+ context.messages.push(message);
15
+ emit({ type: 'message_start', role: message.role, ...(channel ? { channel } : {}) });
16
+ emit({ type: 'message_end', message, ...(channel ? { channel } : {}) });
17
+ }
18
+ }
19
+ /** assistant 内联 toolCall 块直取(工具批与截断配对的公共提取面) */
20
+ function toolCallsOf(message) {
21
+ return message.content.filter((block) => block.type === 'toolCall');
22
+ }
23
+ /**
24
+ * 种子起跑:seeds 逐条入列(用户直发——channel 缺省)后进主循环。
25
+ * @param context 运行上下文(messages 活数组) @param config 回调面 @param seeds 种子消息(缺省空)
26
+ */
27
+ export function startRun(context, config, seeds = []) {
28
+ const emit = (event) => void config.onEvent?.(event);
29
+ pushAll(context, seeds, emit);
30
+ return runLoop(context, config, emit);
31
+ }
32
+ /**
33
+ * 续入起跑:末角色校验(经 convertToLlm 转换后须 user/toolResult——违者
34
+ * AGENT_CONTINUE_INVALID fail-loud,防把 assistant 尾直接重发 provider)。
35
+ */
36
+ export function continueRun(context, config) {
37
+ const last = context.messages[context.messages.length - 1];
38
+ const converted = last === undefined ? null : config.convertToLlm(last);
39
+ const role = Array.isArray(converted) ? converted[converted.length - 1]?.role : converted?.role;
40
+ if (role !== 'user' && role !== 'toolResult') {
41
+ throw new BaseError('AGENT_CONTINUE_INVALID', `continueRun 末角色校验红:转换后末角色为 ${String(role ?? '空')}(须 user/toolResult——恢复续入的上下文形状前提)`);
42
+ }
43
+ return runLoop(context, config, (event) => void config.onEvent?.(event));
44
+ }
45
+ /** 主循环(双 while 的外层本体——内层流消费在 streamAssistantResponse 内) */
46
+ async function runLoop(context, config, emit) {
47
+ emit({ type: 'agent_start' });
48
+ let turn = 0;
49
+ let stopReason;
50
+ let errorMessage;
51
+ while (true) {
52
+ // turn 顶:steering 注入(busy 中插入的消息进本轮上下文)——消费点在
53
+ // preModelRequest 之前(同步零让出):await 窗若先于消费点,busy 期
54
+ // submit 会漂移进 steer 通道(本应 followUp 尾声消费——通道语义时序
55
+ // 回归锁见 driver.test 队列通道族)
56
+ pushAll(context, config.getSteeringMessages?.() ?? [], emit, 'steer');
57
+ // 模型请求前检查(03 §2.4 agent_pre_step 窗——'stop' 刹停零 dangling turn):
58
+ // 位置 = steering 消费后、turn_start 前(steering 注入属上下文组装非模型
59
+ // 请求;刹停时 steer 件已落 durable 由下次 run 重播种承载)
60
+ if ((await config.preModelRequest?.(context)) === 'stop') {
61
+ stopReason = 'stop';
62
+ break;
63
+ }
64
+ turn += 1;
65
+ emit({ type: 'turn_start', turn });
66
+ const assistant = await streamAssistantResponse(config, context, emit);
67
+ stopReason = assistant.stopReason;
68
+ errorMessage = assistant.errorMessage;
69
+ // 中止竞速败者形重归因:pi-ai 层 response promise 与 abort 信号竞速——败者形 =
70
+ // stopReason 'error' + errorMessage 系 AbortError 文案('This operation was aborted'
71
+ // 等)。signal 已 aborted 即实证善意中止在途(issue watchdog 预算帽 / TUI Esc /
72
+ // webui stop),重归因 aborted——消费面善意词面(『每 issue 预算帽耗尽』等)全靠
73
+ // aborted 分支承载。窄判据三合一(缺一不触发):error + signal.aborted + abort 文案
74
+ // ——真 error(网络断等)不受泛化误伤。
75
+ if (stopReason === 'error' &&
76
+ config.signal?.aborted === true &&
77
+ errorMessage !== undefined &&
78
+ /abort/i.test(errorMessage)) {
79
+ stopReason = 'aborted';
80
+ }
81
+ emit({ type: 'turn_end', turn, stopReason });
82
+ // 终态短路:error/aborted → run 收场(status 映射见函数尾)
83
+ if (assistant.stopReason === 'error' || assistant.stopReason === 'aborted')
84
+ break;
85
+ // 截断防御:length → 整批配对 isError 后收 failed(残缺批不进下一轮)
86
+ if (assistant.stopReason === 'length') {
87
+ errorMessage = assistant.errorMessage ?? '输出被上下文窗口截断(stopReason=length)';
88
+ pushAll(context, toolCallsOf(assistant).map((call) => ({
89
+ role: 'toolResult',
90
+ toolCallId: call.id,
91
+ toolName: call.name,
92
+ content: [{ type: 'text', text: '输出被上下文窗口截断——整批配对收口,不进下一轮' }],
93
+ isError: true,
94
+ timestamp: Date.now(),
95
+ })), emit);
96
+ break;
97
+ }
98
+ if (assistant.stopReason === 'toolUse') {
99
+ const outcome = await executeToolBatch(config, context, toolCallsOf(assistant), emit);
100
+ pushAll(context, outcome.results, emit);
101
+ if (outcome.terminate)
102
+ break; // 批内一致 terminate → 优雅停
103
+ }
104
+ // turn 终止裁决(停止词/预算尽/打断)——先于 followUp 消费:停则留在驱动侧队列不入列
105
+ if (await config.shouldStopAfterTurn?.(context, assistant))
106
+ break;
107
+ if (assistant.stopReason !== 'toolUse') {
108
+ // stop/deferred:followUp 是 idle 起跑通道——空即自然停 completed
109
+ const followUps = config.getFollowUpMessages?.() ?? [];
110
+ if (followUps.length === 0)
111
+ break;
112
+ pushAll(context, followUps, emit, 'followUp');
113
+ }
114
+ // turn 间准备窗:换 model/thinkingLevel 唯一时机(todo/goal 注入同窗)。
115
+ // 实况注记(2026-09-11 定形):换档只改内存 config 不落 session/thinking-level
116
+ // durable 事件——该词 v1 词先锚定(05 §1.1 在册、写点随会话档位切换面立题;
117
+ // 冷启动恢复走栈级静态 options.thinkingLevel)
118
+ const adjustment = await config.prepareNextTurn?.(context);
119
+ if (adjustment) {
120
+ if (adjustment.model !== undefined)
121
+ config.model = adjustment.model;
122
+ if (adjustment.thinkingLevel !== undefined)
123
+ config.thinkingLevel = adjustment.thinkingLevel;
124
+ }
125
+ }
126
+ // 终态映射:error/length → failed;aborted → aborted;其余(stop/toolUse/deferred)→ completed
127
+ const status = stopReason === 'error' || stopReason === 'length' ? 'failed' : stopReason === 'aborted' ? 'aborted' : 'completed';
128
+ emit({
129
+ type: 'agent_end',
130
+ status,
131
+ ...(stopReason !== undefined ? { stopReason } : {}),
132
+ ...(errorMessage !== undefined ? { errorMessage } : {}),
133
+ });
134
+ return {
135
+ status,
136
+ ...(stopReason !== undefined ? { stopReason } : {}),
137
+ ...(errorMessage !== undefined ? { errorMessage } : {}),
138
+ };
139
+ }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * agent 件 — PendingMessageQueue 待发队列(04 篇 §4:三通道的暂存与合批机制)。
3
+ *
4
+ * 两轴分立(本仓 vs berry 蓝本差异④——蓝本只有取件单轴):
5
+ * - QueueMode 取件策略轴:one-at-a-time(缺省,一次取一件)/ all(合批——后台
6
+ * 唤醒合批收窄工具面即此);
7
+ * - overflowPolicy 容量溢出策略轴:drop-oldest(缺省,丢弃即回执可见不静默
8
+ * 堆积)/ bounded(排到帽拒新并回执拒收)。
9
+ * 队列是内存态:崩溃即丢——durable 真相只有已进 timeline 的消息(05 篇)。
10
+ */
11
+ /** 队列缺省容量帽(04 §4 定值——码面缺省参数非契约常数,channels 件可再裁) */
12
+ export const DEFAULT_QUEUE_CAPACITY = 100;
13
+ /**
14
+ * 待发队列(机制件——通道判定在驱动侧 conversation,本件只司暂存与取件)。
15
+ * mode 可运行期调整(合批窗口的开关);capacity/overflowPolicy 构造期钉死
16
+ * (溢出语义漂移属配置面变更,不开放热改)。
17
+ */
18
+ export class PendingMessageQueue {
19
+ /** 待发条目(FIFO;队首最旧) */
20
+ items = [];
21
+ /** 取件策略(可运行期调整) */
22
+ modeValue;
23
+ /** 容量帽(构造期钉死) */
24
+ capacityValue;
25
+ /** 溢出策略(构造期钉死) */
26
+ overflowValue;
27
+ /**
28
+ * @param options.mode 取件策略(缺省 one-at-a-time)
29
+ * @param options.capacity 容量帽(缺省 100;<1 拒构造——空队列是死配置)
30
+ * @param options.overflowPolicy 溢出策略(缺省 drop-oldest)
31
+ */
32
+ constructor(options) {
33
+ this.modeValue = options?.mode ?? 'one-at-a-time';
34
+ this.capacityValue = options?.capacity ?? DEFAULT_QUEUE_CAPACITY;
35
+ this.overflowValue = options?.overflowPolicy ?? 'drop-oldest';
36
+ if (!Number.isInteger(this.capacityValue) || this.capacityValue < 1) {
37
+ throw new RangeError(`capacity 须为正整数,收到 ${this.capacityValue}——空队列是死配置`);
38
+ }
39
+ }
40
+ /** 取件策略(读) */
41
+ get mode() {
42
+ return this.modeValue;
43
+ }
44
+ /** 取件策略(写——运行期调整面:合批窗口开关) */
45
+ set mode(mode) {
46
+ this.modeValue = mode;
47
+ }
48
+ /** 当前条目数 */
49
+ get size() {
50
+ return this.items.length;
51
+ }
52
+ /** 是否有待发条目 */
53
+ hasItems() {
54
+ return this.items.length > 0;
55
+ }
56
+ /**
57
+ * 入列(溢出按策略执法、回执不静默)。
58
+ * @param message 待发消息 @param channel 通道判定结果(驱动侧已裁)
59
+ * @param options.backgroundWake 后台唤醒标记位(随条目透传——消费侧合批/预算面)
60
+ * @param options.id 撤回关联键(随条目透传——withdraw 消费面;e-4)
61
+ * @returns 回执:accepted=true 正常入列;false 时 dropped 载被丢/被拒项
62
+ */
63
+ enqueue(message, channel, options) {
64
+ const item = {
65
+ message,
66
+ channel,
67
+ enqueuedAt: Date.now(),
68
+ ...(options?.backgroundWake !== undefined ? { backgroundWake: options.backgroundWake } : {}),
69
+ ...(options?.id !== undefined ? { id: options.id } : {}),
70
+ };
71
+ if (this.items.length < this.capacityValue) {
72
+ this.items.push(item);
73
+ return { accepted: true };
74
+ }
75
+ if (this.overflowValue === 'bounded') {
76
+ // 有界排队腿:排到帽拒新——拒收项原样回执(调用方告知用户)
77
+ return { accepted: false, dropped: item };
78
+ }
79
+ // drop-oldest 腿:丢队首腾位(丢弃可见——被丢项回执给调用方)
80
+ const dropped = this.items.shift();
81
+ this.items.push(item);
82
+ return { accepted: true, dropped };
83
+ }
84
+ /**
85
+ * 取件(按 mode:one-at-a-time 取队首一件;all 全取清空)。
86
+ * @returns 取出的条目(空队列返回空数组)
87
+ */
88
+ drain() {
89
+ if (this.items.length === 0)
90
+ return [];
91
+ if (this.modeValue === 'all') {
92
+ return this.items.splice(0, this.items.length);
93
+ }
94
+ return [this.items.shift()];
95
+ }
96
+ /** 清空(run 收场/会话拆解用;返回被清条目供回执) */
97
+ clear() {
98
+ return this.items.splice(0, this.items.length);
99
+ }
100
+ /**
101
+ * 在队快照(e-5 操控收口——interrupt 回执 still_queued 数据源):只读呈报
102
+ * 不取件不 mutate(与 drain/clear 分立——快照零副作用)。返回浅拷贝数组,
103
+ * 调用方改写不影响队内真身。
104
+ */
105
+ snapshot() {
106
+ return [...this.items];
107
+ }
108
+ /**
109
+ * 在队撤回(e-4 withdraw——03 §2.2 第十一面):按撤回关联键移除在队件。
110
+ * @returns 命中返回被移除条目;不在队(已出队被消费/从未入列/已被溢出
111
+ * 丢弃)返回 undefined——调用方以「已投递」语义诚实呈报。
112
+ */
113
+ withdraw(id) {
114
+ const index = this.items.findIndex((item) => item.id === id);
115
+ if (index === -1)
116
+ return undefined;
117
+ return this.items.splice(index, 1)[0];
118
+ }
119
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * agent 件 — 流消费辅助(loop 骨架的内层腿;04 §2 双 while 的内层本体)。
3
+ *
4
+ * 组装序(承蓝本):convertToLlm 全量转写 → transformContext 最后关口 →
5
+ * getApiKey → streamFn(永不抛——错误编码为流终值)→ 迭代(start 占位入列、
6
+ * delta 就地替换、终值 result() 落位)。partial 就地替换:流中每事件的
7
+ * partial 即累计快照,尾元素直接替换即活体更新——不重建数组。
8
+ */
9
+ /**
10
+ * 单轮流式请求:从 context 组装 LlmContext、消费流、终值落位并回推。
11
+ *
12
+ * @param config loop 配置(convertToLlm/transformContext/getApiKey/streamFn 消费面)
13
+ * @param context 运行上下文(messages 活数组——assistant 占位与终值都入列)
14
+ * @param emit 活体事件发射器
15
+ * @returns 终值消息(stopReason=error/aborted 时错误即数据——loop 按终态短路)
16
+ */
17
+ export async function streamAssistantResponse(config, context, emit) {
18
+ // ① convertToLlm 全量转写(null = 剥离不进上下文;数组 = 一拆多)
19
+ const messages = [];
20
+ for (const message of context.messages) {
21
+ const converted = config.convertToLlm(message);
22
+ if (converted === null)
23
+ continue;
24
+ if (Array.isArray(converted))
25
+ messages.push(...converted);
26
+ else
27
+ messages.push(converted);
28
+ }
29
+ let llmContext = {
30
+ systemPrompt: context.systemPrompt,
31
+ messages,
32
+ tools: context.tools?.map((tool) => ({
33
+ name: tool.name,
34
+ description: tool.description,
35
+ parameters: tool.parameters,
36
+ })),
37
+ };
38
+ // ② transformContext 最后关口(记忆检索瞬态注入位)
39
+ if (config.transformContext)
40
+ llmContext = await config.transformContext(llmContext);
41
+ // ③ 凭证取用 + ④ 流式调用(永不抛契约——一切失败在流终值里)
42
+ const stream = await config.streamFn(llmContext, { model: config.model, thinkingLevel: config.thinkingLevel, apiKey: config.getApiKey?.(config.model) }, config.signal);
43
+ // ⑤ 消费流:start 占位入列 → 带 partial 事件就地替换尾 → 终值 result() 落位
44
+ for await (const event of stream) {
45
+ if (event.type === 'start') {
46
+ context.messages.push(event.partial);
47
+ emit({ type: 'message_start', role: 'assistant' });
48
+ }
49
+ else if (event.type === 'done' || event.type === 'error') {
50
+ break; // 终值统一走 result()(流协议:done/error 后迭代自然收尾)
51
+ }
52
+ else {
53
+ // 各内容块事件的 partial 均为累计快照——就地替换尾元素即活体更新
54
+ context.messages[context.messages.length - 1] = event.partial;
55
+ emit({ type: 'message_update', role: 'assistant', partial: event.partial });
56
+ }
57
+ }
58
+ const final = await stream.result();
59
+ context.messages[context.messages.length - 1] = final;
60
+ emit({ type: 'message_end', message: final });
61
+ return final;
62
+ }