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.
- package/LICENSE +21 -0
- package/README.md +96 -0
- package/dist/.api-emit.stamp +1 -0
- package/dist/.build-meta.json +6 -0
- package/dist/agent/events.js +1 -0
- package/dist/agent/index.js +2 -0
- package/dist/agent/loop.js +139 -0
- package/dist/agent/queue.js +119 -0
- package/dist/agent/stream.js +62 -0
- package/dist/agent/tools-batch.js +221 -0
- package/dist/agent/types.js +8 -0
- package/dist/api/berry-agent-llm.d.ts +18 -0
- package/dist/api/berry-agent.d.ts +9 -0
- package/dist/api/surface.json +1632 -0
- package/dist/api/tsconfig.paths.json +12 -0
- package/dist/api/typebox-compile.d.ts +2 -0
- package/dist/api/typebox-value.d.ts +2 -0
- package/dist/api/typebox.d.ts +2 -0
- package/dist/browser/cdp.js +256 -0
- package/dist/browser/codes.js +31 -0
- package/dist/browser/discover.js +107 -0
- package/dist/browser/engine.js +169 -0
- package/dist/browser/index.js +17 -0
- package/dist/browser/install.js +342 -0
- package/dist/browser/page.js +321 -0
- package/dist/browser/service.js +158 -0
- package/dist/browser/tools.js +198 -0
- package/dist/browser/types.js +81 -0
- package/dist/channels/ask-queue.js +82 -0
- package/dist/channels/commands.js +129 -0
- package/dist/channels/engine/cell.js +143 -0
- package/dist/channels/engine/diff.js +143 -0
- package/dist/channels/engine/engine.js +416 -0
- package/dist/channels/engine/index.js +8 -0
- package/dist/channels/engine/input-keys.js +86 -0
- package/dist/channels/engine/input.js +596 -0
- package/dist/channels/engine/memory-io.js +71 -0
- package/dist/channels/engine/process-io.js +38 -0
- package/dist/channels/engine/types.js +17 -0
- package/dist/channels/engine/width.js +122 -0
- package/dist/channels/index.js +15 -0
- package/dist/channels/registry.js +56 -0
- package/dist/channels/sdk/admit.js +29 -0
- package/dist/channels/sdk/backend.js +102 -0
- package/dist/channels/sdk/cursor.js +56 -0
- package/dist/channels/sdk/index.js +20 -0
- package/dist/channels/sdk/jsonl.js +208 -0
- package/dist/channels/sdk/protocol.js +24 -0
- package/dist/channels/sdk/schema.js +91 -0
- package/dist/channels/sdk/wire-core.js +446 -0
- package/dist/channels/service.js +169 -0
- package/dist/channels/tui/autocomplete/autocomplete.js +42 -0
- package/dist/channels/tui/autocomplete/file-mentions.js +106 -0
- package/dist/channels/tui/autocomplete/popup.js +148 -0
- package/dist/channels/tui/autocomplete/provider.js +7 -0
- package/dist/channels/tui/autocomplete/token.js +68 -0
- package/dist/channels/tui/backend/ansi-rows.js +211 -0
- package/dist/channels/tui/backend/main-screen.js +207 -0
- package/dist/channels/tui/backend/osc.js +91 -0
- package/dist/channels/tui/backend/transcript.js +230 -0
- package/dist/channels/tui/backend/tui-backend.js +915 -0
- package/dist/channels/tui/editor/editor-model.js +543 -0
- package/dist/channels/tui/editor/editor-view.js +140 -0
- package/dist/channels/tui/editor/editor.js +275 -0
- package/dist/channels/tui/editor/undo-stack.js +35 -0
- package/dist/channels/tui/editor/visual-lines.js +126 -0
- package/dist/channels/tui/editor/word-nav.js +106 -0
- package/dist/channels/tui/history/history-viewer.js +403 -0
- package/dist/channels/tui/index.js +3 -0
- package/dist/channels/tui/layout.js +167 -0
- package/dist/channels/tui/markdown/blocks.js +111 -0
- package/dist/channels/tui/markdown/inline.js +75 -0
- package/dist/channels/tui/markdown/markdown.js +182 -0
- package/dist/channels/tui/memory/memory-viewer.js +540 -0
- package/dist/channels/tui/overlay/alt-screen.js +105 -0
- package/dist/channels/tui/overlay/overlay.js +57 -0
- package/dist/channels/tui/overlay/select-confirm.js +156 -0
- package/dist/channels/tui/panels/todo-panel.js +54 -0
- package/dist/channels/tui/panels/tool-progress-panel.js +93 -0
- package/dist/channels/tui/scroll/scroll-view.js +254 -0
- package/dist/channels/tui/status/status-line.js +76 -0
- package/dist/channels/tui/text.js +38 -0
- package/dist/channels/tui/theme.js +41 -0
- package/dist/channels/types.js +11 -0
- package/dist/channels/ui-core.js +209 -0
- package/dist/checkpoint/capture.js +45 -0
- package/dist/checkpoint/codes.js +33 -0
- package/dist/checkpoint/command.js +82 -0
- package/dist/checkpoint/gate.js +48 -0
- package/dist/checkpoint/index.js +20 -0
- package/dist/checkpoint/restore.js +172 -0
- package/dist/checkpoint/store.js +247 -0
- package/dist/checkpoint/types.js +4 -0
- package/dist/checkpoint/walk.js +146 -0
- package/dist/compaction/ccr-tools.js +112 -0
- package/dist/compaction/ccr.js +84 -0
- package/dist/compaction/codes.js +21 -0
- package/dist/compaction/index.js +18 -0
- package/dist/compaction/policy.js +200 -0
- package/dist/compaction/service.js +422 -0
- package/dist/compaction/slots.js +121 -0
- package/dist/compaction/types.js +10 -0
- package/dist/context/codes.js +40 -0
- package/dist/context/events.js +160 -0
- package/dist/context/index.js +13 -0
- package/dist/context/logger.js +136 -0
- package/dist/context/scope.js +182 -0
- package/dist/context/workspace.js +104 -0
- package/dist/contracts/agent-events.d.ts +73 -0
- package/dist/contracts/agent-events.js +16 -0
- package/dist/contracts/api.d.ts +249 -0
- package/dist/contracts/api.js +299 -0
- package/dist/contracts/approval.d.ts +37 -0
- package/dist/contracts/approval.js +9 -0
- package/dist/contracts/env-ref.d.ts +41 -0
- package/dist/contracts/env-ref.js +32 -0
- package/dist/contracts/errors.d.ts +56 -0
- package/dist/contracts/errors.js +266 -0
- package/dist/contracts/events.d.ts +70 -0
- package/dist/contracts/events.js +329 -0
- package/dist/contracts/index.d.ts +32 -0
- package/dist/contracts/index.js +26 -0
- package/dist/contracts/llm.d.ts +275 -0
- package/dist/contracts/llm.js +12 -0
- package/dist/contracts/messages.d.ts +63 -0
- package/dist/contracts/messages.js +65 -0
- package/dist/contracts/redact.d.ts +46 -0
- package/dist/contracts/redact.js +223 -0
- package/dist/contracts/tools.d.ts +197 -0
- package/dist/contracts/tools.js +33 -0
- package/dist/contracts/types.d.ts +302 -0
- package/dist/contracts/types.js +50 -0
- package/dist/contracts/ui.d.ts +122 -0
- package/dist/contracts/ui.js +15 -0
- package/dist/conversation/agent-service.js +61 -0
- package/dist/conversation/approval-wiring.js +82 -0
- package/dist/conversation/backoff.js +38 -0
- package/dist/conversation/codes.js +47 -0
- package/dist/conversation/control-tools.js +102 -0
- package/dist/conversation/control.js +210 -0
- package/dist/conversation/driver.js +922 -0
- package/dist/conversation/index.js +12 -0
- package/dist/conversation/model-visible.js +169 -0
- package/dist/conversation/open-tools.js +126 -0
- package/dist/conversation/reseed.js +132 -0
- package/dist/conversation/sessions.js +215 -0
- package/dist/conversation/todo.js +203 -0
- package/dist/conversation/types.js +35 -0
- package/dist/conversation/wiring.js +204 -0
- package/dist/credentials/codes.js +59 -0
- package/dist/credentials/commands.js +186 -0
- package/dist/credentials/env-ref.js +34 -0
- package/dist/credentials/index.js +28 -0
- package/dist/credentials/migration.js +18 -0
- package/dist/credentials/oauth.js +266 -0
- package/dist/credentials/refresh.js +152 -0
- package/dist/credentials/secrets.js +118 -0
- package/dist/credentials/types.js +30 -0
- package/dist/exec/bash.js +279 -0
- package/dist/exec/codes.js +37 -0
- package/dist/exec/env.js +99 -0
- package/dist/exec/environment.js +39 -0
- package/dist/exec/git-guard.js +623 -0
- package/dist/exec/index.js +24 -0
- package/dist/exec/registry.js +120 -0
- package/dist/exec/spawn.js +281 -0
- package/dist/exec/tail.js +77 -0
- package/dist/exec/types.js +5 -0
- package/dist/goal/codes.js +33 -0
- package/dist/goal/command.js +175 -0
- package/dist/goal/fold.js +121 -0
- package/dist/goal/gates.js +122 -0
- package/dist/goal/index.js +22 -0
- package/dist/goal/migration.js +48 -0
- package/dist/goal/service.js +501 -0
- package/dist/goal/todo-tool.js +174 -0
- package/dist/goal/types.js +1 -0
- package/dist/goal/update-tool.js +46 -0
- package/dist/host/approval-cmd.js +276 -0
- package/dist/host/assembly.js +1146 -0
- package/dist/host/boot-failures.js +104 -0
- package/dist/host/budget-advisory.js +74 -0
- package/dist/host/budget-broadcast.js +50 -0
- package/dist/host/builtins.js +54 -0
- package/dist/host/cli.js +544 -0
- package/dist/host/codes.js +120 -0
- package/dist/host/config-schema.js +195 -0
- package/dist/host/conversation-stack.js +654 -0
- package/dist/host/core-plugins.js +1685 -0
- package/dist/host/credentials-cmd.js +42 -0
- package/dist/host/disclosure.js +30 -0
- package/dist/host/dispatch.js +105 -0
- package/dist/host/doors-cmd.js +154 -0
- package/dist/host/dump-config.js +44 -0
- package/dist/host/hook-dispatch-guard.js +27 -0
- package/dist/host/import-gate.js +153 -0
- package/dist/host/index.js +54 -0
- package/dist/host/issue-session.js +241 -0
- package/dist/host/loader.js +372 -0
- package/dist/host/main.js +161 -0
- package/dist/host/manifest.js +381 -0
- package/dist/host/mcp-entry.js +53 -0
- package/dist/host/plugin-boot.js +952 -0
- package/dist/host/plugin-context.js +672 -0
- package/dist/host/plugin-install.js +480 -0
- package/dist/host/plugin-reload.js +124 -0
- package/dist/host/plugin-store.js +462 -0
- package/dist/host/plugin-tools.js +359 -0
- package/dist/host/plugin-uninstall.js +257 -0
- package/dist/host/plugins-cmd.js +302 -0
- package/dist/host/plugins-command.js +130 -0
- package/dist/host/plugins-config.js +195 -0
- package/dist/host/prompt-sections.js +133 -0
- package/dist/host/run-entry.js +544 -0
- package/dist/host/runtime.js +209 -0
- package/dist/host/scheduler-tick.js +294 -0
- package/dist/host/serve-daemon.js +501 -0
- package/dist/host/serve-entry.js +279 -0
- package/dist/host/session-anchor.js +41 -0
- package/dist/host/sessions-cmd.js +219 -0
- package/dist/host/sessions-face.js +47 -0
- package/dist/host/settings-store.js +112 -0
- package/dist/host/signals.js +69 -0
- package/dist/host/single-instance.js +105 -0
- package/dist/host/subagent-factory.js +291 -0
- package/dist/host/testkit/harness.js +283 -0
- package/dist/host/testkit/index.js +14 -0
- package/dist/host/testkit/matrix.js +302 -0
- package/dist/host/tool-policy-store.js +177 -0
- package/dist/host/triggers.js +212 -0
- package/dist/host/tui-entry.js +216 -0
- package/dist/host/webui-bridge.js +165 -0
- package/dist/issue/codes.js +38 -0
- package/dist/issue/filter.js +146 -0
- package/dist/issue/github.js +116 -0
- package/dist/issue/index.js +17 -0
- package/dist/issue/mount.js +70 -0
- package/dist/issue/poll.js +58 -0
- package/dist/issue/service.js +341 -0
- package/dist/issue/tools.js +70 -0
- package/dist/issue/types.js +34 -0
- package/dist/issue/webhook.js +126 -0
- package/dist/llm/codes.js +77 -0
- package/dist/llm/complete.js +196 -0
- package/dist/llm/events.js +15 -0
- package/dist/llm/index.js +24 -0
- package/dist/llm/inflight.js +65 -0
- package/dist/llm/model-id.js +58 -0
- package/dist/llm/provider-face.d.ts +32 -0
- package/dist/llm/provider-face.js +34 -0
- package/dist/llm/recovery.js +146 -0
- package/dist/llm/runtime.js +46 -0
- package/dist/llm/stream-fn.js +147 -0
- package/dist/lsp/codes.js +31 -0
- package/dist/lsp/connection.js +147 -0
- package/dist/lsp/frame.js +110 -0
- package/dist/lsp/index.js +16 -0
- package/dist/lsp/inject.js +58 -0
- package/dist/lsp/instance.js +264 -0
- package/dist/lsp/service.js +522 -0
- package/dist/lsp/tools.js +53 -0
- package/dist/lsp/types.js +201 -0
- package/dist/mcp/bridge.js +222 -0
- package/dist/mcp/codes.js +21 -0
- package/dist/mcp/index.js +19 -0
- package/dist/mcp/jsonrpc.js +230 -0
- package/dist/mcp/service.js +125 -0
- package/dist/mcp/tools.js +145 -0
- package/dist/mcp/types.js +108 -0
- package/dist/memory/cite.js +131 -0
- package/dist/memory/codes.js +50 -0
- package/dist/memory/command.js +71 -0
- package/dist/memory/consolidate.js +219 -0
- package/dist/memory/cycle.js +109 -0
- package/dist/memory/dao.js +878 -0
- package/dist/memory/diff.js +238 -0
- package/dist/memory/extract.js +181 -0
- package/dist/memory/fts.js +58 -0
- package/dist/memory/index.js +42 -0
- package/dist/memory/inject.js +354 -0
- package/dist/memory/merge.js +178 -0
- package/dist/memory/migration.js +132 -0
- package/dist/memory/pollution.js +59 -0
- package/dist/memory/port.js +385 -0
- package/dist/memory/review.js +201 -0
- package/dist/memory/scan.js +89 -0
- package/dist/memory/tools.js +508 -0
- package/dist/memory/types.js +140 -0
- package/dist/obs/codes.js +38 -0
- package/dist/obs/db.js +115 -0
- package/dist/obs/index.js +20 -0
- package/dist/obs/rollup.js +61 -0
- package/dist/obs/service.js +363 -0
- package/dist/obs/session-tools.js +282 -0
- package/dist/obs/session-view.js +225 -0
- package/dist/obs/tool.js +97 -0
- package/dist/obs/types.js +1 -0
- package/dist/persist/audit.js +63 -0
- package/dist/persist/aux.js +39 -0
- package/dist/persist/codes.js +35 -0
- package/dist/persist/index.js +30 -0
- package/dist/persist/load-history.js +50 -0
- package/dist/persist/migrations.js +37 -0
- package/dist/persist/paths.js +108 -0
- package/dist/persist/persistence.js +229 -0
- package/dist/persist/schema.js +99 -0
- package/dist/persist/secret-box.js +95 -0
- package/dist/persist/store.js +706 -0
- package/dist/persist/write-behind.js +238 -0
- package/dist/safety/approval.js +171 -0
- package/dist/safety/bwrap.js +123 -0
- package/dist/safety/codes.js +57 -0
- package/dist/safety/danger.js +505 -0
- package/dist/safety/gate.js +226 -0
- package/dist/safety/index.js +24 -0
- package/dist/safety/presets.js +73 -0
- package/dist/safety/roots.js +139 -0
- package/dist/safety/sandbox.js +214 -0
- package/dist/safety/seatbelt.js +88 -0
- package/dist/safety/sensitive.js +34 -0
- package/dist/safety/tool-policy.js +203 -0
- package/dist/safety/types.js +13 -0
- package/dist/scheduler/codes.js +54 -0
- package/dist/scheduler/cron-backend.js +135 -0
- package/dist/scheduler/engine.js +280 -0
- package/dist/scheduler/gates.js +60 -0
- package/dist/scheduler/index.js +25 -0
- package/dist/scheduler/migration.js +22 -0
- package/dist/scheduler/runner.js +171 -0
- package/dist/scheduler/schedule.js +193 -0
- package/dist/scheduler/service.js +283 -0
- package/dist/scheduler/tick.js +139 -0
- package/dist/scheduler/types.js +1 -0
- package/dist/sdk/http.js +865 -0
- package/dist/sdk/index.js +22 -0
- package/dist/sdk/mcp.js +289 -0
- package/dist/sdk/plugin-route-registry.js +126 -0
- package/dist/sdk/plugin-routes.js +149 -0
- package/dist/sdk/security.js +116 -0
- package/dist/sdk/types.js +32 -0
- package/dist/session/budget.js +159 -0
- package/dist/session/codes.js +40 -0
- package/dist/session/derive.js +180 -0
- package/dist/session/event-data.js +1 -0
- package/dist/session/fork.js +72 -0
- package/dist/session/import-gates.js +148 -0
- package/dist/session/index.js +18 -0
- package/dist/session/recover.js +103 -0
- package/dist/session/session.js +279 -0
- package/dist/session/snapshot.js +107 -0
- package/dist/skills/agents.js +242 -0
- package/dist/skills/codes.js +51 -0
- package/dist/skills/discovery.js +266 -0
- package/dist/skills/frontmatter.js +215 -0
- package/dist/skills/index.js +28 -0
- package/dist/skills/load.js +118 -0
- package/dist/skills/manage.js +201 -0
- package/dist/skills/registry.js +138 -0
- package/dist/skills/render.js +124 -0
- package/dist/skills/sections.js +171 -0
- package/dist/skills/types.js +21 -0
- package/dist/subagent/codes.js +50 -0
- package/dist/subagent/declarative.js +55 -0
- package/dist/subagent/index.js +19 -0
- package/dist/subagent/notify.js +51 -0
- package/dist/subagent/provide.js +7 -0
- package/dist/subagent/registry.js +149 -0
- package/dist/subagent/service.js +338 -0
- package/dist/subagent/surface.js +44 -0
- package/dist/subagent/tool.js +153 -0
- package/dist/subagent/types.js +25 -0
- package/dist/tools/apply-patch.js +164 -0
- package/dist/tools/codes.js +109 -0
- package/dist/tools/fs.js +501 -0
- package/dist/tools/index.js +17 -0
- package/dist/tools/observed.js +99 -0
- package/dist/tools/pipeline.js +176 -0
- package/dist/tools/protected-read.js +54 -0
- package/dist/tools/registry.js +250 -0
- package/dist/tools/search.js +451 -0
- package/dist/tools/worktree.js +327 -0
- package/dist/web/codes.js +37 -0
- package/dist/web/gate.js +43 -0
- package/dist/web/hygiene.js +195 -0
- package/dist/web/index.js +16 -0
- package/dist/web/service.js +207 -0
- package/dist/web/ssrf-guard.js +44 -0
- package/dist/web/tool.js +76 -0
- package/dist/web/types.js +10 -0
- package/dist/webui/assets/index-B-t2O8gh.js +22 -0
- package/dist/webui/assets/index-DOlgSZ9Q.css +2 -0
- package/dist/webui/index.html +14 -0
- package/dist/webui/index.js +14 -0
- package/dist/webui/server.js +549 -0
- package/dist/webui/types.js +38 -0
- package/examples/README.md +26 -0
- package/examples/minimal-code-plugin/entry.js +43 -0
- package/examples/minimal-code-plugin/package.json +12 -0
- package/examples/pure-skill-pack/package.json +14 -0
- package/examples/pure-skill-pack/skills/markdown-table/SKILL.md +32 -0
- package/package.json +86 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* host/credentials-cmd — `credentials` 子命令族 CLI 入口(03 §10.9 人面命令
|
|
3
|
+
* CLI 半边;c-5 落码批)。
|
|
4
|
+
*
|
|
5
|
+
* 零装配直开库(sessions 读腿同形):不开运行时、不占单活跃机标记、不装载
|
|
6
|
+
* 插件——短命凭证管理动词不是第二宿主实例。开库走 Persistence 直开 + 宿主
|
|
7
|
+
* 迁移链尾单源(HOST_MIGRATION_TAIL——链必须与运行时全同,短链开真库会被
|
|
8
|
+
* 同库拒降级运行)。动词语义/值域执法/结算文本单源在 credentials/commands
|
|
9
|
+
* (TUI /credentials 同源——双面一底座)。
|
|
10
|
+
*
|
|
11
|
+
* 退出码:0 成功(含空清单——诚实空非失败)/ 1 执行失败(名缺席、namespace
|
|
12
|
+
* 坏形——结算文本已含原因,不另打行)。用法错归解析层(exit 2)。
|
|
13
|
+
*
|
|
14
|
+
* 审计注记:CLI 短命进程不接 credentials/changed seam(宿主运行时形态的
|
|
15
|
+
* 发射位在 assembly deps——U3 批 U3-5 已接线 audit_events)。
|
|
16
|
+
*/
|
|
17
|
+
import { stdout as processStdout, stderr as processStderr } from 'node:process';
|
|
18
|
+
import { Persistence } from '../persist/index.js';
|
|
19
|
+
import { runCredentialsCommand } from '../credentials/index.js';
|
|
20
|
+
import { HOST_MIGRATION_TAIL } from './runtime.js';
|
|
21
|
+
/** credentials 子命令族主入口。返回进程退出码(0/1;用法错归解析层退 2) */
|
|
22
|
+
export async function runCredentialsEntry(sub, options) {
|
|
23
|
+
const out = options.writeOut ?? ((text) => processStdout.write(`${text}\n`));
|
|
24
|
+
const err = options.writeErr ?? ((text) => processStderr.write(`${text}\n`));
|
|
25
|
+
// 开库(迁移链尾单源;warn 走错误面——毒丸/撕裂尾告警直达人面)
|
|
26
|
+
const persistence = Persistence.open({
|
|
27
|
+
...(options.dbPath !== undefined ? { dbPath: options.dbPath } : {}),
|
|
28
|
+
...(options.dataDir !== undefined ? { dataDir: options.dataDir } : {}),
|
|
29
|
+
migrations: HOST_MIGRATION_TAIL,
|
|
30
|
+
warn: (message) => err(`warn:${message}`),
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
// persist Store 结构可赋 CredentialsCommandStore 四法投影(词面独立律
|
|
34
|
+
// compat 面——commands.test.ts 对拍互证;直传真身零适配层)
|
|
35
|
+
const result = runCredentialsCommand(sub, { store: persistence.store });
|
|
36
|
+
out(result.text);
|
|
37
|
+
return result.ok ? 0 : 1;
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
await persistence.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** 五件全缺席 → null(无披露段——注入面零强求) */
|
|
2
|
+
export function renderEnvironmentDisclosure(inputs) {
|
|
3
|
+
const lines = [];
|
|
4
|
+
if (inputs.platform !== undefined)
|
|
5
|
+
lines.push(`- 平台: ${inputs.platform}`);
|
|
6
|
+
if (inputs.cwd !== undefined)
|
|
7
|
+
lines.push(`- 工作目录: ${inputs.cwd}`);
|
|
8
|
+
if (inputs.date !== undefined)
|
|
9
|
+
lines.push(`- 日期: ${inputs.date}`);
|
|
10
|
+
if (inputs.gitSummary != null && inputs.gitSummary.length > 0)
|
|
11
|
+
lines.push(`- git: ${inputs.gitSummary}`);
|
|
12
|
+
if (inputs.plugins != null) {
|
|
13
|
+
// 插件计数行——04 §environment 披露段钉形「插件 N 个(启用 M · 失败 F)」
|
|
14
|
+
lines.push(`- 插件: ${inputs.plugins.total} 个(启用 ${inputs.plugins.enabled} · 失败 ${inputs.plugins.failed})`);
|
|
15
|
+
}
|
|
16
|
+
if (lines.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
return ['<environment>', ...lines, '</environment>'].join('\n');
|
|
19
|
+
}
|
|
20
|
+
/** 平台/OS 行采集(darwin 27.0.0 形——process.platform + os.release) */
|
|
21
|
+
export function collectPlatform(osRelease, platform) {
|
|
22
|
+
return `${platform} ${osRelease()}`;
|
|
23
|
+
}
|
|
24
|
+
/** 日期行采集(本地时区 YYYY-MM-DD——每请求重算自然跨日刷新) */
|
|
25
|
+
export function collectDate(now) {
|
|
26
|
+
const d = now();
|
|
27
|
+
const month = `${d.getMonth() + 1}`.padStart(2, '0');
|
|
28
|
+
const day = `${d.getDate()}`.padStart(2, '0');
|
|
29
|
+
return `${d.getFullYear()}-${month}-${day}`;
|
|
30
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/** 帮助文案(07 §5 命令族定名块单源摘编——自包含不外指) */
|
|
2
|
+
export const HELP_TEXT = `berry-agent — 单一可扩展的个人 Agent
|
|
3
|
+
|
|
4
|
+
用法:berry-agent [命令] [旗标]
|
|
5
|
+
|
|
6
|
+
命令:
|
|
7
|
+
(无参) TUI 主入口:直进对话
|
|
8
|
+
run "<message>" 单次执行:一轮对话 → stdout 输出结果
|
|
9
|
+
serve 常驻宿主(stdio JSONL;serve status / serve stop 管理动词)
|
|
10
|
+
mcp MCP server 包装形态
|
|
11
|
+
dump-config 打印实际生效装配
|
|
12
|
+
plugins <sub> 插件生命周期(list/install/uninstall/mount/unmount/toggle/update/check)
|
|
13
|
+
sessions <sub> 会话管理(list/resume <id>/fork <id>/search <query>/reindex)
|
|
14
|
+
credentials <sub> 凭证人面管理(add <name> <value>/list/rm <name>;--namespace <ns> 指定域)
|
|
15
|
+
doors <sub> 开门制人面(list 只读——六枚高危面清单与开态双源呈现;写动词 TUI /doors 专属)
|
|
16
|
+
upgrade 升级维护动词
|
|
17
|
+
|
|
18
|
+
常用旗标:
|
|
19
|
+
--help / --version / --debug / --port <n> / --no-plugins
|
|
20
|
+
run 限定:--output-format <text|json|stream> --output-last-message <file> --ephemeral
|
|
21
|
+
--max-turns <n> --session <id> --continue --fork [id] --read-only --preset <名> --tick <名> --background
|
|
22
|
+
serve 限定:--daemon --no-delta --sdk-port <n> --sdk-host <host>(后两旗标 daemon 形专属)
|
|
23
|
+
|
|
24
|
+
裸 -- 之后的 argv 全字面;未识别 -- 词一律用法错退 2。`;
|
|
25
|
+
/**
|
|
26
|
+
* 分派解析产物到执行器(返回退出码——不 exit)。
|
|
27
|
+
*
|
|
28
|
+
* 分派序:用法错 → help/version 短路 → TUI 非 TTY 卫兵 → 执行器派发
|
|
29
|
+
* (缺席退 1 fail-loud;抛错退 1 + stderr 码与报文——BaseError 呈码身份,
|
|
30
|
+
* 裸 Error 呈 message)。
|
|
31
|
+
*/
|
|
32
|
+
export async function dispatchCli(parsed, handlers, env) {
|
|
33
|
+
// 用法错(解析面执法律①③⑤同源)——stderr 一行 + 退 2
|
|
34
|
+
if (!parsed.ok) {
|
|
35
|
+
env.writeErr(parsed.message);
|
|
36
|
+
return 2;
|
|
37
|
+
}
|
|
38
|
+
const { command } = parsed;
|
|
39
|
+
// help/version 统一短路(执法位在未识别旗标闸之后——此处到达的必是干净解析)
|
|
40
|
+
if (command.kind === 'help') {
|
|
41
|
+
if (command.overreach !== undefined) {
|
|
42
|
+
env.writeErr(`注记:${command.overreach} 之后的词不再落位置参数(分派层短路)`);
|
|
43
|
+
}
|
|
44
|
+
env.writeOut(HELP_TEXT);
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
if (command.kind === 'version') {
|
|
48
|
+
env.writeOut(env.version);
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
// TUI 入口非 TTY 卫兵(07 §5 单源:stdin 或 stdout 非 TTY 即触发)
|
|
52
|
+
if (command.kind === 'tui' && (!env.stdinIsTTY || !env.stdoutIsTTY)) {
|
|
53
|
+
env.writeErr('非交互环境(stdin/stdout 非 TTY)——无参 TUI 主入口不适用于管道/CI;改用 `berry-agent run "<message>"` 单发或 `berry-agent serve` 常驻。');
|
|
54
|
+
return 2;
|
|
55
|
+
}
|
|
56
|
+
// 执行器派发:缺席 = 尚未装配(fail-loud 退 1);在席 = 交执(抛错退 1)
|
|
57
|
+
const invoke = async () => {
|
|
58
|
+
switch (command.kind) {
|
|
59
|
+
case 'tui':
|
|
60
|
+
return requireHandler(handlers.tui, 'TUI 主入口')(command.flags);
|
|
61
|
+
case 'run':
|
|
62
|
+
return requireHandler(handlers.run, 'run')(command.message, command.flags);
|
|
63
|
+
case 'serve':
|
|
64
|
+
return requireHandler(handlers.serve, 'serve')(command.flags);
|
|
65
|
+
case 'serve-status':
|
|
66
|
+
return requireHandler(handlers.serveStatus, 'serve status')();
|
|
67
|
+
case 'serve-stop':
|
|
68
|
+
return requireHandler(handlers.serveStop, 'serve stop')();
|
|
69
|
+
case 'mcp':
|
|
70
|
+
return requireHandler(handlers.mcp, 'mcp')();
|
|
71
|
+
case 'dump-config':
|
|
72
|
+
return requireHandler(handlers.dumpConfig, 'dump-config')(command.flags);
|
|
73
|
+
case 'plugins':
|
|
74
|
+
return requireHandler(handlers.plugins, 'plugins')(command.sub);
|
|
75
|
+
case 'sessions':
|
|
76
|
+
return requireHandler(handlers.sessions, 'sessions')(command.sub);
|
|
77
|
+
case 'credentials':
|
|
78
|
+
return requireHandler(handlers.credentials, 'credentials')(command.sub);
|
|
79
|
+
case 'doors':
|
|
80
|
+
return requireHandler(handlers.doors, 'doors')(command.sub);
|
|
81
|
+
case 'upgrade':
|
|
82
|
+
return requireHandler(handlers.upgrade, 'upgrade')();
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
try {
|
|
86
|
+
return await invoke();
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
// 执行失败档(退 1)——stderr 码身份 + 报文(调用方可判别)
|
|
90
|
+
const line = err instanceof Error
|
|
91
|
+
? 'code' in err && typeof err.code === 'string'
|
|
92
|
+
? `${err.code}: ${err.message}`
|
|
93
|
+
: err.message
|
|
94
|
+
: String(err);
|
|
95
|
+
env.writeErr(`执行失败(退出码 1):${line}`);
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** 执行器缺席面(统一文案——「命令面已解析、执行面随后续批装配」诚实告知) */
|
|
100
|
+
function requireHandler(handler, label) {
|
|
101
|
+
if (handler === undefined) {
|
|
102
|
+
throw new Error(`${label} 执行面尚未装配(随后续批次接线)——本命令解析与旗标面已就绪`);
|
|
103
|
+
}
|
|
104
|
+
return handler;
|
|
105
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* host/doors-cmd — 开门制人面命令件(03 §4.6 `/doors` 人面命令 =
|
|
3
|
+
* enabled.yaml doors 段的编辑腿;07 §5 定名行——开门制扩展批 g-2 落码)。
|
|
4
|
+
*
|
|
5
|
+
* 双面分立(有意偏离 /credentials 双面族形——07 §5 定名:**写动词 TUI
|
|
6
|
+
* 单面**,headless 场景经文件直编 doors 段、boot diff 记账覆盖〔origin
|
|
7
|
+
* 'boot-diff'〕):
|
|
8
|
+
* - **TUI 面**(assembly 直挂——与 /reload、/plugins 同位,机制宿主有、
|
|
9
|
+
* 不随插件换代卸除):三动词全量——list 只读 + open/close 写动词(写回
|
|
10
|
+
* 段 + 落 `doors/updated` origin 'tui-cmd' + 生效时点诚实回执);
|
|
11
|
+
* - **CLI 面**(`berry-agent doors <sub>`——runDoorsEntry):list 只读
|
|
12
|
+
* 受理;open/close **语义拒退 1**(合法解析形非用法错——解析层照常受理,
|
|
13
|
+
* 执行层诚实指路文件直编)。零装配零库纯文件读(不 boot 插件面、不开
|
|
14
|
+
* Persistence——段在文件不在库)。
|
|
15
|
+
*
|
|
16
|
+
* list 呈现 = 六枚高危面全清单(USER_GRANTABLE_CAPABILITIES 单源)+ 当前
|
|
17
|
+
* 开态**双源呈现**:行 opens 按插件分组 + doors 段进程级一行;闭门 reason
|
|
18
|
+
* = adjudicateCapabilityDoor 单源 message(与 session_status 门态段、执行
|
|
19
|
+
* 时拒绝同源——先查后用)。
|
|
20
|
+
*
|
|
21
|
+
* 生效时点诚实律:g-1 门检输入 = 活体源(受理时点现读现判——open/close 写
|
|
22
|
+
* 回即门立即生效、撤位即收回);装载面(boot 快照/审计基线)下次 /reload
|
|
23
|
+
* 或启动刷新。回执两时点都陈述。
|
|
24
|
+
*/
|
|
25
|
+
import { stdout as processStdout, stderr as processStderr } from 'node:process';
|
|
26
|
+
import { resolveDataDir } from '../persist/index.js';
|
|
27
|
+
import { adjudicateCapabilityDoor, DOORS_SEGMENT_V1_DOMAIN, USER_GRANTABLE_CAPABILITIES } from '../contracts/api.js';
|
|
28
|
+
import { createPluginStoreFs, editDoorsSegment, readEnabledRowsForEdit } from './plugin-store.js';
|
|
29
|
+
/** 用法说明(TUI 命令描述位 + 解析错回执共用单源) */
|
|
30
|
+
export const DOORS_USAGE = `/doors list | open <capability> | close <capability>
|
|
31
|
+
list 六枚高危面全清单 + 当前开态双源呈现(行 opens 按插件分组 + doors 段进程级一行)
|
|
32
|
+
open <capability> 开门(写回 enabled.yaml doors 段 + 落 doors/updated——门检即时生效)
|
|
33
|
+
close <capability> 关门(撤位即收回;doors 段收口为显式空段)
|
|
34
|
+
(CLI 面只读 list——写动词 TUI 专属;headless 经文件直编 doors 段 + boot diff 记账)`;
|
|
35
|
+
/**
|
|
36
|
+
* TUI 面 argv 解析(CLI 面由 cli.ts 解析律执法——未知旗标退 2 等;本函数
|
|
37
|
+
* 只服务 TUI 通道的裸 argv:动词识别 + 位置参数,零旗标面)。
|
|
38
|
+
*/
|
|
39
|
+
export function parseDoorsArgv(argv) {
|
|
40
|
+
const [verb, ...rest] = argv;
|
|
41
|
+
if (verb === undefined || verb.startsWith('--')) {
|
|
42
|
+
return { ok: false, message: `缺子命令。\n${DOORS_USAGE}` };
|
|
43
|
+
}
|
|
44
|
+
if (rest.some((tok) => tok.startsWith('--'))) {
|
|
45
|
+
return { ok: false, message: `本命令族无旗标。\n${DOORS_USAGE}` };
|
|
46
|
+
}
|
|
47
|
+
if (verb === 'list') {
|
|
48
|
+
if (rest.length > 0)
|
|
49
|
+
return { ok: false, message: `list 不收位置参数。\n${DOORS_USAGE}` };
|
|
50
|
+
return { ok: true, sub: { sub: 'list' } };
|
|
51
|
+
}
|
|
52
|
+
if (verb === 'open' || verb === 'close') {
|
|
53
|
+
if (rest.length !== 1 || rest[0] === '') {
|
|
54
|
+
return { ok: false, message: `${verb} 须带 <capability> 一参数。\n${DOORS_USAGE}` };
|
|
55
|
+
}
|
|
56
|
+
return { ok: true, sub: { sub: verb, door: rest[0] } };
|
|
57
|
+
}
|
|
58
|
+
return { ok: false, message: `未知子命令:${verb}(合法:list/open/close)。\n${DOORS_USAGE}` };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* list 渲染(六枚全清单 + 双源呈现——纯读零副作用):
|
|
62
|
+
* - 清单段:每枚高危面标注开态——doors 段含(进程级)/ 启用行 opens 含
|
|
63
|
+
* (插件道:插件 id 清单)/ 闭门附 adjudicateCapabilityDoor 单源 reason
|
|
64
|
+
* (与 session_status 门态段、执行时拒绝 message 同源);
|
|
65
|
+
* - 双源段:行 opens 按插件分组(disabled 行标注——授予面在场但实效收回)
|
|
66
|
+
* + doors 段进程级一行(缺席 = 空集诚实呈现)。
|
|
67
|
+
*/
|
|
68
|
+
function renderDoorsList(dataDir, fs) {
|
|
69
|
+
const read = readEnabledRowsForEdit(dataDir ?? '', fs);
|
|
70
|
+
if (!read.ok)
|
|
71
|
+
return { ok: false, text: read.message };
|
|
72
|
+
const doors = new Set(read.doors ?? []);
|
|
73
|
+
// 行 opens 分组(带 opens 的行全列——disabled 行授予面在场但装载侧实效
|
|
74
|
+
// 收回〔readTriggerOpensLive 判 disabled → 空集〕,标注呈现不隐藏)
|
|
75
|
+
const rowLines = [];
|
|
76
|
+
for (const row of read.rows) {
|
|
77
|
+
if (row.opens === undefined || row.opens.length === 0)
|
|
78
|
+
continue;
|
|
79
|
+
rowLines.push(` ${row.id}: ${[...row.opens].join('、')}${row.disabled === true ? '(已禁用——授予实效收回)' : ''}`);
|
|
80
|
+
}
|
|
81
|
+
const lines = [];
|
|
82
|
+
lines.push(`高危面清单(${USER_GRANTABLE_CAPABILITIES.length} 枚——闭门附 adjudicateCapabilityDoor 同源 reason):`);
|
|
83
|
+
for (const capability of USER_GRANTABLE_CAPABILITIES) {
|
|
84
|
+
const openers = read.rows
|
|
85
|
+
.filter((row) => row.disabled !== true && (row.opens ?? []).includes(capability))
|
|
86
|
+
.map((r) => r.id);
|
|
87
|
+
// 闭门 reason = 单源 verdict.message(六枚皆高危面,空集判恒 door-closed
|
|
88
|
+
// 非 not-a-door——窄化兜底只为类型面,语义上不可达)
|
|
89
|
+
const closed = adjudicateCapabilityDoor(new Set(), capability);
|
|
90
|
+
const state = doors.has(capability)
|
|
91
|
+
? `open(doors 段——进程级)`
|
|
92
|
+
: openers.length > 0
|
|
93
|
+
? `open(行 opens:${openers.join('、')})`
|
|
94
|
+
: `closed——${closed.ok ? '未开门' : closed.message}`;
|
|
95
|
+
lines.push(` ${capability}=${state}`);
|
|
96
|
+
}
|
|
97
|
+
lines.push('授予双源(03 §4.6——两源任一含即门开;受理时点现读现判,撤位即收回):');
|
|
98
|
+
lines.push(' 行 opens(插件道——授予跟插件 id 走,换装零继承):');
|
|
99
|
+
lines.push(...(rowLines.length > 0 ? rowLines : [' (无——未有任何插件行开位)']));
|
|
100
|
+
lines.push(' doors 段(进程级——模型道两门值域,/doors open|close 编辑对象):');
|
|
101
|
+
lines.push(doors.size > 0
|
|
102
|
+
? ` ${[...doors].sort().join('、')}`
|
|
103
|
+
: read.doors === undefined
|
|
104
|
+
? ' (段缺席 = 空集)'
|
|
105
|
+
: ' (显式空段 = 空集)');
|
|
106
|
+
return { ok: true, text: lines.join('\n') };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* `/doors` 命令面主入口(sub → 结算形)。写动词失败零副作用(值域拒/文件
|
|
110
|
+
* 面 refusal 不落账);成功尾序 = 段写回 → doors/updated 落账 → 生效时点
|
|
111
|
+
* 诚实回执(门检即时生效——g-1 活体源;装载面 /reload 或下次启动刷新)。
|
|
112
|
+
*/
|
|
113
|
+
export function runDoorsCommand(sub, deps) {
|
|
114
|
+
if (sub.sub === 'list') {
|
|
115
|
+
return renderDoorsList(deps.dataDir, deps.fs);
|
|
116
|
+
}
|
|
117
|
+
if (deps.dataDir === null) {
|
|
118
|
+
return { ok: false, text: '纯 memory 诊断形无数据目录——写动词不可用(doors 段编辑无落点)' };
|
|
119
|
+
}
|
|
120
|
+
const result = editDoorsSegment(deps.dataDir, { verb: sub.sub, door: sub.door }, deps.fs, deps.onDoorsUpdated);
|
|
121
|
+
if (!result.ok)
|
|
122
|
+
return { ok: false, text: result.message };
|
|
123
|
+
const tail = '门检即时生效(受理时点现读现判);装载面(boot 快照/审计基线)下次 /reload 或启动刷新';
|
|
124
|
+
return {
|
|
125
|
+
ok: true,
|
|
126
|
+
text: sub.sub === 'open'
|
|
127
|
+
? `已开门:${sub.door}——写回 enabled.yaml doors 段。${tail}`
|
|
128
|
+
: `已关门:${sub.door}——doors 段撤位(收口为空时写回显式空段)。${tail}`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* `berry-agent doors <sub>` CLI 入口(07 §5 定名——list 只读 v1 进、写动词
|
|
133
|
+
* 语义拒)。零装配零库纯文件读:不开运行时、不占单活跃机标记、不 boot
|
|
134
|
+
* 插件面、不开 Persistence(与 credentials-cmd 直开库分立点——doors 真源
|
|
135
|
+
* 恒文件)。退出码:0 成功(含空集诚实呈现)/ 1 执行失败或写动词语义拒 /
|
|
136
|
+
* 用法错归解析层退 2。
|
|
137
|
+
*/
|
|
138
|
+
export async function runDoorsEntry(sub, options) {
|
|
139
|
+
const out = options.writeOut ?? ((text) => processStdout.write(`${text}\n`));
|
|
140
|
+
const err = options.writeErr ?? ((text) => processStderr.write(`${text}\n`));
|
|
141
|
+
if (sub.sub !== 'list') {
|
|
142
|
+
// 写动词 TUI 专属(07 §5 定名——有意偏离双面族形):合法解析形非用法
|
|
143
|
+
// 错,执行层诚实指路(headless 正路 = 文件直编 + boot diff 记账覆盖)
|
|
144
|
+
out(`doors ${sub.sub} 为 TUI /doors 专属动词——CLI 面只读 list。\n` +
|
|
145
|
+
`headless 场景经文件直编 enabled.yaml 顶层 doors 段(值域 v1:${DOORS_SEGMENT_V1_DOMAIN.join('、')}),boot diff 记账覆盖(origin 'boot-diff')。`);
|
|
146
|
+
return 1;
|
|
147
|
+
}
|
|
148
|
+
const result = runDoorsCommand(sub, { dataDir: options.dataDir ?? resolveDataDir(), fs: createPluginStoreFs() });
|
|
149
|
+
if (result.ok)
|
|
150
|
+
out(result.text);
|
|
151
|
+
else
|
|
152
|
+
err(result.text);
|
|
153
|
+
return result.ok ? 0 : 1;
|
|
154
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { assembleHostStack } from './assembly.js';
|
|
2
|
+
/** dump-config 主入口:同构装配 → 打印 JSON → 收口。返回进程退出码。 */
|
|
3
|
+
export async function runDumpConfigEntry(options) {
|
|
4
|
+
const writeOut = options.writeOut ?? ((text) => process.stdout.write(`${text}\n`));
|
|
5
|
+
const writeErr = options.writeErr ?? ((text) => process.stderr.write(`${text}\n`));
|
|
6
|
+
// dataDir 缺省 resolveDataDir()——同构诊断形(memory + 真数据目录读侧)
|
|
7
|
+
const assembly = await assembleHostStack({
|
|
8
|
+
runtime: {
|
|
9
|
+
...(options.dataDir !== undefined ? { dataDir: options.dataDir } : {}),
|
|
10
|
+
memory: true,
|
|
11
|
+
},
|
|
12
|
+
noPlugins: options.flags.noPlugins === true,
|
|
13
|
+
debug: options.flags.debug === true,
|
|
14
|
+
version: options.version,
|
|
15
|
+
...(options.env !== undefined ? { env: options.env } : {}),
|
|
16
|
+
...(options.onRuntime !== undefined ? { onRuntime: options.onRuntime } : {}),
|
|
17
|
+
...(options.corePlugins !== undefined ? { corePlugins: options.corePlugins } : {}),
|
|
18
|
+
});
|
|
19
|
+
if (!assembly.ok) {
|
|
20
|
+
writeErr(assembly.message); // 干净退出档语义(message 已含前缀与修复指引)
|
|
21
|
+
return assembly.exitCode;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
writeOut(JSON.stringify({
|
|
25
|
+
version: options.version,
|
|
26
|
+
dataDir: assembly.runtime.dataDir,
|
|
27
|
+
database: ':memory:', // 同构诊断形注记——主库零落盘(07 §5)
|
|
28
|
+
model: assembly.stack.model,
|
|
29
|
+
// --port 收下不起监听(07 §5 旗标块「dump-config 忽略不起监听」);
|
|
30
|
+
// 布尔归一(缺省 false)——诊断 JSON 键形稳定(undefined 会被 stringify 丢键)
|
|
31
|
+
flags: { noPlugins: options.flags.noPlugins === true, port: options.flags.port ?? null },
|
|
32
|
+
plugins: {
|
|
33
|
+
activated: assembly.boot.report.activated,
|
|
34
|
+
failed: assembly.boot.report.failed,
|
|
35
|
+
skipped: assembly.boot.report.skipped,
|
|
36
|
+
},
|
|
37
|
+
counts: assembly.boot.counts,
|
|
38
|
+
}, null, 2));
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
await assembly.runtime.shutdown(); // 幂等六步(closer 含插件卸载回卷)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* host/hook-dispatch-guard — 钩子派发段深度计数 guard(03 §3.4 执法形定形注;
|
|
3
|
+
* cache 经济批 ca-3)。
|
|
4
|
+
*
|
|
5
|
+
* 语义:包裹**插件钩子派发**前后自增自减——await 跨度天然覆盖 handler 全执行
|
|
6
|
+
* 段,派发收口即闭窗(「起异步任务不等结果合法、await 耦合违法」的条款语义
|
|
7
|
+
* 精确对齐:fire-and-forget 尾链在派发收口后窗外合法跑);**只包钩子派发不包
|
|
8
|
+
* 工具执行体**(03 §3.4 只禁钩子段——工具执行期模型调用不受限)。
|
|
9
|
+
*
|
|
10
|
+
* 旗标住 host 装配根(全局单实例——全部插件 ctx 共享同一深度计数,跨插件
|
|
11
|
+
* 嵌套钩子叠加正确);只读面经装配注入 llm 双入口(complete 单发 + StreamFn)
|
|
12
|
+
* 前置查——命中拒发 `LLM_CALL_IN_HOOK`(02 §4.1 llm 无 host 逆边——窗态必经
|
|
13
|
+
* 装配注入,llm 侧收结构窄面 { inHookDispatch() },llm 域自持本类型副本)。
|
|
14
|
+
*/
|
|
15
|
+
/** 深度计数 guard 工厂(单实例随装配根创建——多实例各计各深度即漏跨插件嵌套) */
|
|
16
|
+
export function createHookDispatchGuard() {
|
|
17
|
+
let depth = 0;
|
|
18
|
+
return {
|
|
19
|
+
enter: () => {
|
|
20
|
+
depth += 1;
|
|
21
|
+
},
|
|
22
|
+
exit: () => {
|
|
23
|
+
depth -= 1;
|
|
24
|
+
},
|
|
25
|
+
inHookDispatch: () => depth > 0,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* host/import-gate — 插件 import 门禁三道白名单执法件(03 §3.3;批 12d)。
|
|
3
|
+
*
|
|
4
|
+
* 三道白名单:① 虚拟面六键(§3.2 表——闭集,越出键表的 `berry-agent/*` 子径
|
|
5
|
+
* 同拒);② `node:` 内建(裸内建名〔无前缀〕不在道内——白名单字面只收
|
|
6
|
+
* `node:` 形);③ 插件目录树内(相对导入 + 自带 node_modules——裸第三方
|
|
7
|
+
* 说明符由「能否在插件树内解析」判,解析不可达即拒)。
|
|
8
|
+
*
|
|
9
|
+
* 执法 = **字面量腿**(单腿——03 §3.3 批 12d 勘正):装载期 jiti transform
|
|
10
|
+
* 钩子拦截说明符(静态 import/export-from/require + 动态字面量
|
|
11
|
+
* `import('…')`/`require('…')` 全扫),越界即**抛** `PLUGIN_IMPORT_FORBIDDEN`
|
|
12
|
+
* ——jiti 主求值径只消费 transform 产码、error 通道仅 debug 日志(2026-09-07
|
|
13
|
+
* 探针实证),故 throw 直抛是唯一拒载通道;配套 jiti `fsCache:false`(缓存
|
|
14
|
+
* 键不含门禁身份——命中即跳过 transform 穿门,装载器件负责关)。原设计
|
|
15
|
+
* 运行期兜底腿(前置守卫注入/裸内建 alias 毒丸)经 jiti v2 公开面核实无
|
|
16
|
+
* 注入位(裸内建名 builtin 短路判在 alias/resolve 之前)——结构性不可实现,
|
|
17
|
+
* 残差(动态拼接裸内建名/绝对径逃逸)随沙箱立题裁,详 03 §3.3 勘正段。
|
|
18
|
+
*
|
|
19
|
+
* 辖域 = 插件自有码:入口与相对导入的自有模块全扫;插件树 `node_modules/`
|
|
20
|
+
* 子树内第三方码豁免(npm 生态惯例裸内建与 `node:` 形语义等价——豁免只
|
|
21
|
+
* 跳过裁决、babel 链转照常)。辖域判定 = 两侧 realpath 归一后路径前缀比对
|
|
22
|
+
* (macOS `/var` ↔ `/private/var` 符号链径差异防假阴性);符号链接形态的
|
|
23
|
+
* 深层对齐(install 期记 realpath)归装机腿落码批收口。
|
|
24
|
+
*/
|
|
25
|
+
import { realpathSync } from 'node:fs';
|
|
26
|
+
import { fileURLToPath } from 'node:url';
|
|
27
|
+
import { createJiti } from 'jiti';
|
|
28
|
+
import { BaseError } from '../contracts/index.js';
|
|
29
|
+
import { BARE_BUILTINS } from './builtins.js';
|
|
30
|
+
/** 虚拟面六键闭集(03 §3.2 定名表——同实例注入的真源清单) */
|
|
31
|
+
export const VIRTUAL_KEYS = [
|
|
32
|
+
'berry-agent',
|
|
33
|
+
'berry-agent/llm',
|
|
34
|
+
'berry-agent/sqlite',
|
|
35
|
+
'typebox',
|
|
36
|
+
'typebox/value',
|
|
37
|
+
'typebox/compile',
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* 单说明符白名单裁决(纯谓词——字面量腿的裁决核)。
|
|
41
|
+
*
|
|
42
|
+
* 判序:node: 前缀 → 虚拟键闭集(`berry-agent`/`typebox` 前缀但越出键表 =
|
|
43
|
+
* 越界拒)→ 相对导入(./ ../——树内 containment 由解析保证)→ 绝对路径
|
|
44
|
+
* (file: / 盘符——直拒:插件面无绝对径合法位)→ 裸说明符(resolveBare
|
|
45
|
+
* 判,缺席即拒 fail-closed)。
|
|
46
|
+
*/
|
|
47
|
+
export function checkImportSpecifier(specifier, ctx = {}) {
|
|
48
|
+
if (specifier.startsWith('node:'))
|
|
49
|
+
return true; // 道②:node: 内建
|
|
50
|
+
if (VIRTUAL_KEYS.includes(specifier))
|
|
51
|
+
return true; // 道①:虚拟键闭集
|
|
52
|
+
if ((specifier.startsWith('berry-agent') || specifier.startsWith('typebox')) && !specifier.startsWith('./')) {
|
|
53
|
+
// 虚拟键域内越出键表(berry-agent/unknown、typebox/extra)——闭集外即拒
|
|
54
|
+
return forbidden(specifier, '虚拟键域内未知子径(键表闭集外)');
|
|
55
|
+
}
|
|
56
|
+
if (specifier.startsWith('./') || specifier.startsWith('../'))
|
|
57
|
+
return true; // 道③:相对导入
|
|
58
|
+
if (/^(\/|[a-zA-Z]:[\\/]|file:)/.test(specifier)) {
|
|
59
|
+
return forbidden(specifier, '绝对路径不在白名单(插件面合法径只有三道)');
|
|
60
|
+
}
|
|
61
|
+
if (specifier.length === 0)
|
|
62
|
+
return forbidden(specifier, '空说明符');
|
|
63
|
+
// 裸说明符(内建裸名 / 第三方包名)——树内解析可达才放行
|
|
64
|
+
if (ctx.resolveBare?.(specifier) === true)
|
|
65
|
+
return true;
|
|
66
|
+
if (BARE_BUILTINS.has(specifier)) {
|
|
67
|
+
return forbidden(specifier, '裸内建名被拒——用 node: 前缀(白名单道②字面只收 node: 形)');
|
|
68
|
+
}
|
|
69
|
+
return forbidden(specifier, '裸说明符在插件目录树内不可解析(依赖自捆——03 §9.3)');
|
|
70
|
+
}
|
|
71
|
+
/** 越界裁决产物(携带码与因由——统一抛形) */
|
|
72
|
+
function forbidden(specifier, reason) {
|
|
73
|
+
return new BaseError('PLUGIN_IMPORT_FORBIDDEN', `import 越界拒载:${specifier}(${reason}——三道白名单见 03 §3.3)`);
|
|
74
|
+
}
|
|
75
|
+
/** 说明符字面量抽取正则族(静态 + 动态字面量——注释/字符串内误伤由「越界即拒」的保守面消化) */
|
|
76
|
+
const SPECIFIER_PATTERNS = [
|
|
77
|
+
/(?:^|[\s;}])(?:import|export)\s+(?:type\s+)?[\s\S]*?from\s*['"]([^'"]+)['"]/g, // import/export … from '…'
|
|
78
|
+
/(?:^|[\s;}])import\s*['"]([^'"]+)['"]/g, // 副作用 import '…'
|
|
79
|
+
/(?:^|[\s;[(!,:=])require\s*\(\s*['"]([^'"]+)['"]\s*\)/g, // require('…')(含动态字面量)
|
|
80
|
+
/(?:^|[\s;[(!,:=])import\s*\(\s*['"]([^'"]+)['"]\s*\)/g, // import('…')(动态字面量)
|
|
81
|
+
];
|
|
82
|
+
/**
|
|
83
|
+
* 抽取源文本中的全部说明符字面量(字面量腿的扫描核——纯函数可单测)。
|
|
84
|
+
*/
|
|
85
|
+
export function extractImportSpecifiers(source) {
|
|
86
|
+
const found = [];
|
|
87
|
+
for (const pattern of SPECIFIER_PATTERNS) {
|
|
88
|
+
const re = new RegExp(pattern.source, pattern.flags);
|
|
89
|
+
let match;
|
|
90
|
+
while ((match = re.exec(source)) !== null) {
|
|
91
|
+
const spec = match[1];
|
|
92
|
+
if (spec !== undefined)
|
|
93
|
+
found.push(spec);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return found;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 字面量腿 transform:辖域内文件扫描说明符字面量 → 白名单裁决 → 越界即
|
|
100
|
+
* **抛** `PLUGIN_IMPORT_FORBIDDEN`(jiti 把 transform 抛错直接传导给装载方
|
|
101
|
+
* ——error 通道不抛已实证);在道内则链委托 babel transform 产码(第二
|
|
102
|
+
* jiti 实例的公开 `.transform()` 法,fsCache 关闭——委托自身缓存不受门禁
|
|
103
|
+
* 影响但求确定性关闭)。
|
|
104
|
+
*/
|
|
105
|
+
export function createGateTransform(options) {
|
|
106
|
+
let delegate = options.delegate;
|
|
107
|
+
if (delegate === undefined) {
|
|
108
|
+
const util = createJiti(import.meta.url, { fsCache: false });
|
|
109
|
+
delegate = (opts) => util.transform(opts);
|
|
110
|
+
}
|
|
111
|
+
const pluginRoot = normalizePath(options.pluginDir); // 辖域基归一(realpath——与 filename 同尺比对)
|
|
112
|
+
return (opts) => {
|
|
113
|
+
if (!isPluginOwnCode(opts.filename, pluginRoot)) {
|
|
114
|
+
return { code: delegate(opts) }; // node_modules 子树豁免——第三方码按生态惯例
|
|
115
|
+
}
|
|
116
|
+
for (const spec of extractImportSpecifiers(opts.source)) {
|
|
117
|
+
const verdict = checkImportSpecifier(spec, { resolveBare: options.resolveBare });
|
|
118
|
+
if (verdict !== true) {
|
|
119
|
+
// 越界即拒——throw 直抛(唯一拒载通道;error 通道仅 debug 日志不抛)
|
|
120
|
+
throw new BaseError(verdict.code, `[${options.pluginId}] ${verdict.message}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return { code: delegate(opts) };
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 辖域判定:文件在 pluginDir 之下且不含 node_modules 段 = 插件自有码。
|
|
128
|
+
*
|
|
129
|
+
* 两侧 realpath 归一后前缀比对(macOS 临时目录 `/var` ↔ `/private/var` 符号
|
|
130
|
+
* 链径差异会使裸前缀比对假阴性 → 好依赖被当树外保守全扫);file: URL 形
|
|
131
|
+
* 防御性归一(jiti 版本间 filename 形态差异)。符号链接形态的深层正规化
|
|
132
|
+
* 归装机腿落码批对齐(install 期记录 realpath 后此处自然收口)。
|
|
133
|
+
*/
|
|
134
|
+
function isPluginOwnCode(filename, pluginRoot) {
|
|
135
|
+
if (filename === undefined)
|
|
136
|
+
return true; // 无文件名(eval 串)——保守全扫
|
|
137
|
+
const normalized = normalizePath(filename);
|
|
138
|
+
const prefix = pluginRoot.endsWith('/') ? pluginRoot : `${pluginRoot}/`;
|
|
139
|
+
if (!normalized.startsWith(prefix) && !filename.startsWith(prefix))
|
|
140
|
+
return true; // 树外文件(理论不达)——保守全扫
|
|
141
|
+
const effective = normalized.startsWith(prefix) ? normalized : filename;
|
|
142
|
+
return !effective.slice(prefix.length).includes('node_modules/');
|
|
143
|
+
}
|
|
144
|
+
/** 路径归一:file: URL → 路径 + realpath(不可达原样返回——保守) */
|
|
145
|
+
function normalizePath(filename) {
|
|
146
|
+
const plain = filename.startsWith('file:') ? fileURLToPath(filename) : filename;
|
|
147
|
+
try {
|
|
148
|
+
return realpathSync(plain);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return plain;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* host 域公开面——装配根契约件收口(批 12a 契约先行笔)。
|
|
3
|
+
*
|
|
4
|
+
* host 是唯一可 import 全部宿主模块的横切装配层(02 §4.1 host 席;07 §1.1
|
|
5
|
+
* 表 #10:装配序 + CLI 入口 + 插件装载器 + 生命周期工具族落位本域)。
|
|
6
|
+
* 本笔序:12a 契约面三件(PLUGIN_ 码族补落〔codes〕+ 插件清单/启用行拒绝式
|
|
7
|
+
* 校验〔manifest〕+ CLI 解析面〔cli——手写 argv 解析器,执法律五条〕)→
|
|
8
|
+
* 12b 装配序实装(运行时生命周期 + dataDir 接线 + 单活跃机 +
|
|
9
|
+
* environmentDisclosure)→ 12c CLI 分派面(dispatch/signals/main bin)→
|
|
10
|
+
* 12d 装载器 jiti 实装(import 门禁字面量腿〔03 §3.3 批 12d 勘正〕+ 虚拟
|
|
11
|
+
* 面直注防双实例 + Kahn 轮次 + 失败三档 + boot-failures 记账;库句柄门禁
|
|
12
|
+
* 码名已补落 codes——执法位随 SqliteFace 件消费)→ 12e TUI 入口装配。
|
|
13
|
+
*
|
|
14
|
+
* 单向 DAG:host → 全宿主模块(边表已预登记 24 deps;本笔实际触达
|
|
15
|
+
* contracts 单边——契约笔不解包重件)。
|
|
16
|
+
*/
|
|
17
|
+
import './codes.js';
|
|
18
|
+
export { HOST_PLUGIN_ERROR_CODES } from './codes.js';
|
|
19
|
+
export { checkPluginId, parseManifest, parseEnabledRows, MANIFEST_KEY_CATALOG } from './manifest.js';
|
|
20
|
+
export { parseCli } from './cli.js';
|
|
21
|
+
// 批 12b 装配序生命周期(单活跃机 + 开库 + 退出序六步编舞 + 披露段组装)
|
|
22
|
+
export { acquireActiveMarker, ACTIVE_MARKER_BASENAME } from './single-instance.js';
|
|
23
|
+
export { renderEnvironmentDisclosure, collectPlatform, collectDate } from './disclosure.js';
|
|
24
|
+
export { createHostRuntime, appendCrashLog } from './runtime.js';
|
|
25
|
+
// 批 12c CLI 分派面(退出码三态 + 非 TTY 卫兵 + help/version 短路)与进程编舞
|
|
26
|
+
export { dispatchCli, HELP_TEXT } from './dispatch.js';
|
|
27
|
+
export { installSignalChoreography, installCrashChoreography } from './signals.js';
|
|
28
|
+
// 批 12d 装载器 jiti 实装(import 门禁字面量腿 + 虚拟面直注 + Kahn 轮次 + 失败三档)
|
|
29
|
+
export { VIRTUAL_KEYS, checkImportSpecifier, extractImportSpecifiers, createGateTransform } from './import-gate.js';
|
|
30
|
+
export { loadPlugins, CorePluginBootError } from './loader.js';
|
|
31
|
+
// core: 官方件注册表单源(批 19a 起——assembly 缺省注入源/测试注入面;批
|
|
32
|
+
// 19b-1 工厂形升级:宿主真身〔dataDir 等〕经 CorePluginHostDeps 入件)
|
|
33
|
+
export { createCorePlugins } from './core-plugins.js';
|
|
34
|
+
export { readBootFailures, recordBootFailure, clearBootFailure } from './boot-failures.js';
|
|
35
|
+
// 批 12e TUI 入口装配(对话栈组合根——五层一次成型 + 启动会话策略)
|
|
36
|
+
export { createConversationStack } from './conversation-stack.js';
|
|
37
|
+
export { runTuiEntry } from './tui-entry.js';
|
|
38
|
+
// 批 12f-2a ctx 面件(提示词段注册表 + 插件上下文装配件——窗口律/频率护栏/钩子路由)
|
|
39
|
+
export { PromptSectionRegistry } from './prompt-sections.js';
|
|
40
|
+
export { createPluginContext, PLUGIN_HOOK_VOCABULARY } from './plugin-context.js';
|
|
41
|
+
// 批 12f-2b 插件装载装配序(enabled.yaml 读侧两律 + core overlay + 装机账本
|
|
42
|
+
// installPath 解析 + --no-plugins 短路 + 生命周期事件批量补发 + closer 回卷)
|
|
43
|
+
export { bootPlugins } from './plugin-boot.js';
|
|
44
|
+
// 批 12f-2c webui 开面装配桥 + 批 18a-3' 三入口咬合共用挂载段(--port 旗标
|
|
45
|
+
// 消费 + 三窄面映射 + token 披露 + daemon face 挂载位)
|
|
46
|
+
export { openWebuiFace, mountWebuiOnFace } from './webui-bridge.js';
|
|
47
|
+
// 批 12f-3 装配序公共段(:memory: 同构纪律防侧门件——TUI 与诊断命令唯一装配序真源)
|
|
48
|
+
export { assembleHostStack } from './assembly.js';
|
|
49
|
+
// 批 12f-4 跨会话工具策略表文件读写件(04 §9 粘性第 3 款定形块装配侧执法;
|
|
50
|
+
// 2026-09-11 审批分档批更名 tool-policy.json + 旧文件升格读入)
|
|
51
|
+
export { readToolPolicy, appendToolPolicyEntry, TOOL_POLICY_BASENAME, LEGACY_ALLOWLIST_BASENAME, } from './tool-policy-store.js';
|
|
52
|
+
// 批 12f-3 dump-config / plugins 子命令族(同构诊断命令 + 装载态清单 + 纯只读体检骨架)
|
|
53
|
+
export { runDumpConfigEntry } from './dump-config.js';
|
|
54
|
+
export { runPluginsEntry } from './plugins-cmd.js';
|