@armadra/agent 0.0.0-stage → 0.2.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/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +426 -2
- package/dist/agent/agent.d.ts +56 -0
- package/dist/agent/agent.js +129 -0
- package/dist/agent/loop.d.ts +51 -0
- package/dist/agent/loop.js +158 -0
- package/dist/agent/queue.d.ts +25 -0
- package/dist/agent/queue.js +55 -0
- package/dist/agent/retry.d.ts +22 -0
- package/dist/agent/retry.js +92 -0
- package/dist/agent/schema.d.ts +27 -0
- package/dist/agent/schema.js +186 -0
- package/dist/agent/session-cache.d.ts +100 -0
- package/dist/agent/session-cache.js +511 -0
- package/dist/agent/session-compaction.d.ts +49 -0
- package/dist/agent/session-compaction.js +251 -0
- package/dist/agent/session-core.d.ts +103 -0
- package/dist/agent/session-core.js +7 -0
- package/dist/agent/session-run.d.ts +55 -0
- package/dist/agent/session-run.js +246 -0
- package/dist/agent/session-state.d.ts +39 -0
- package/dist/agent/session-state.js +118 -0
- package/dist/agent/session-subagent.d.ts +54 -0
- package/dist/agent/session-subagent.js +157 -0
- package/dist/agent/session-sync.d.ts +20 -0
- package/dist/agent/session-sync.js +104 -0
- package/dist/agent/session-tools.d.ts +24 -0
- package/dist/agent/session-tools.js +277 -0
- package/dist/agent/session.d.ts +117 -0
- package/dist/agent/session.js +484 -0
- package/dist/agent/system-prompt.d.ts +49 -0
- package/dist/agent/system-prompt.js +121 -0
- package/dist/agent/tool-runner.d.ts +64 -0
- package/dist/agent/tool-runner.js +309 -0
- package/dist/agent/transform.d.ts +26 -0
- package/dist/agent/transform.js +171 -0
- package/dist/agent/types.d.ts +378 -0
- package/dist/agent/types.js +21 -0
- package/dist/ai/apis/anthropic-messages.d.ts +26 -0
- package/dist/ai/apis/anthropic-messages.js +214 -0
- package/dist/ai/apis/anthropic-request.d.ts +42 -0
- package/dist/ai/apis/anthropic-request.js +282 -0
- package/dist/ai/apis/api.d.ts +28 -0
- package/dist/ai/apis/api.js +102 -0
- package/dist/ai/apis/cache-params.d.ts +48 -0
- package/dist/ai/apis/cache-params.js +163 -0
- package/dist/ai/apis/google-generative-ai.d.ts +32 -0
- package/dist/ai/apis/google-generative-ai.js +249 -0
- package/dist/ai/apis/google-request.d.ts +40 -0
- package/dist/ai/apis/google-request.js +255 -0
- package/dist/ai/apis/openai-compat.d.ts +35 -0
- package/dist/ai/apis/openai-compat.js +142 -0
- package/dist/ai/apis/openai-completions.d.ts +28 -0
- package/dist/ai/apis/openai-completions.js +246 -0
- package/dist/ai/apis/openai-request.d.ts +35 -0
- package/dist/ai/apis/openai-request.js +303 -0
- package/dist/ai/apis/openai-responses-request.d.ts +52 -0
- package/dist/ai/apis/openai-responses-request.js +266 -0
- package/dist/ai/apis/openai-responses.d.ts +28 -0
- package/dist/ai/apis/openai-responses.js +303 -0
- package/dist/ai/apis/shared.d.ts +56 -0
- package/dist/ai/apis/shared.js +179 -0
- package/dist/ai/cache/economics.d.ts +24 -0
- package/dist/ai/cache/economics.js +69 -0
- package/dist/ai/cache/fingerprint.d.ts +17 -0
- package/dist/ai/cache/fingerprint.js +39 -0
- package/dist/ai/cache/miss.d.ts +49 -0
- package/dist/ai/cache/miss.js +96 -0
- package/dist/ai/cache/reporting.d.ts +39 -0
- package/dist/ai/cache/reporting.js +102 -0
- package/dist/ai/cache/types.d.ts +94 -0
- package/dist/ai/cache/types.js +19 -0
- package/dist/ai/cache/warmer.d.ts +94 -0
- package/dist/ai/cache/warmer.js +224 -0
- package/dist/ai/context.d.ts +35 -0
- package/dist/ai/context.js +114 -0
- package/dist/ai/cost.d.ts +21 -0
- package/dist/ai/cost.js +60 -0
- package/dist/ai/event-stream.d.ts +33 -0
- package/dist/ai/event-stream.js +101 -0
- package/dist/ai/fake/fake-provider.d.ts +68 -0
- package/dist/ai/fake/fake-provider.js +278 -0
- package/dist/ai/fake/fake-script.d.ts +69 -0
- package/dist/ai/fake/fake-script.js +142 -0
- package/dist/ai/http.d.ts +54 -0
- package/dist/ai/http.js +212 -0
- package/dist/ai/json-partial.d.ts +17 -0
- package/dist/ai/json-partial.js +243 -0
- package/dist/ai/overflow.d.ts +22 -0
- package/dist/ai/overflow.js +61 -0
- package/dist/ai/providers/auth.d.ts +71 -0
- package/dist/ai/providers/auth.js +202 -0
- package/dist/ai/providers/builtin.d.ts +23 -0
- package/dist/ai/providers/builtin.js +148 -0
- package/dist/ai/providers/catalog-data.d.ts +5 -0
- package/dist/ai/providers/catalog-data.js +19 -0
- package/dist/ai/providers/catalog.d.ts +28 -0
- package/dist/ai/providers/catalog.js +166 -0
- package/dist/ai/providers/registry.d.ts +83 -0
- package/dist/ai/providers/registry.js +305 -0
- package/dist/ai/sse.d.ts +32 -0
- package/dist/ai/sse.js +140 -0
- package/dist/ai/thinking.d.ts +42 -0
- package/dist/ai/thinking.js +101 -0
- package/dist/ai/types.d.ts +428 -0
- package/dist/ai/types.js +19 -0
- package/dist/bundle/ama-sandbox.cjs +324 -0
- package/dist/bundle/ama.cjs +25770 -0
- package/dist/bundle.d.ts +9 -0
- package/dist/bundle.js +15 -0
- package/dist/cli/args.d.ts +82 -0
- package/dist/cli/args.js +381 -0
- package/dist/cli/bootstrap.d.ts +18 -0
- package/dist/cli/bootstrap.js +398 -0
- package/dist/cli/compose-providers.d.ts +37 -0
- package/dist/cli/compose-providers.js +104 -0
- package/dist/cli/compose-session.d.ts +69 -0
- package/dist/cli/compose-session.js +370 -0
- package/dist/cli/compose-store.d.ts +24 -0
- package/dist/cli/compose-store.js +125 -0
- package/dist/cli/compose.d.ts +106 -0
- package/dist/cli/compose.js +206 -0
- package/dist/cli/default-model.d.ts +16 -0
- package/dist/cli/default-model.js +24 -0
- package/dist/cli/deps.d.ts +205 -0
- package/dist/cli/deps.js +12 -0
- package/dist/cli/exit-codes.d.ts +29 -0
- package/dist/cli/exit-codes.js +40 -0
- package/dist/cli/main.d.ts +26 -0
- package/dist/cli/main.js +165 -0
- package/dist/cli/runtime.d.ts +90 -0
- package/dist/cli/runtime.js +8 -0
- package/dist/cli/startup-screen.d.ts +15 -0
- package/dist/cli/startup-screen.js +56 -0
- package/dist/cli/startup-steps.d.ts +35 -0
- package/dist/cli/startup-steps.js +197 -0
- package/dist/cli/subcommands/auth.d.ts +12 -0
- package/dist/cli/subcommands/auth.js +91 -0
- package/dist/cli/subcommands/config.d.ts +44 -0
- package/dist/cli/subcommands/config.js +201 -0
- package/dist/cli/subcommands/context.d.ts +21 -0
- package/dist/cli/subcommands/context.js +41 -0
- package/dist/cli/subcommands/doctor.d.ts +11 -0
- package/dist/cli/subcommands/doctor.js +246 -0
- package/dist/cli/subcommands/models-cache-probe.d.ts +34 -0
- package/dist/cli/subcommands/models-cache-probe.js +190 -0
- package/dist/cli/subcommands/models-discover.d.ts +40 -0
- package/dist/cli/subcommands/models-discover.js +204 -0
- package/dist/cli/subcommands/models.d.ts +40 -0
- package/dist/cli/subcommands/models.js +144 -0
- package/dist/cli/subcommands/sessions.d.ts +11 -0
- package/dist/cli/subcommands/sessions.js +100 -0
- package/dist/codemode/capability.d.ts +37 -0
- package/dist/codemode/capability.js +55 -0
- package/dist/codemode/declarations.d.ts +44 -0
- package/dist/codemode/declarations.js +111 -0
- package/dist/codemode/host-side.d.ts +59 -0
- package/dist/codemode/host-side.js +253 -0
- package/dist/codemode/modes.d.ts +23 -0
- package/dist/codemode/modes.js +40 -0
- package/dist/codemode/protocol.d.ts +91 -0
- package/dist/codemode/protocol.js +114 -0
- package/dist/codemode/sandbox-entry.d.ts +25 -0
- package/dist/codemode/sandbox-entry.js +323 -0
- package/dist/codemode/store.d.ts +26 -0
- package/dist/codemode/store.js +53 -0
- package/dist/codemode/tool.d.ts +105 -0
- package/dist/codemode/tool.js +283 -0
- package/dist/compaction/branch-summary.d.ts +30 -0
- package/dist/compaction/branch-summary.js +79 -0
- package/dist/compaction/breaker.d.ts +32 -0
- package/dist/compaction/breaker.js +65 -0
- package/dist/compaction/cut-point.d.ts +23 -0
- package/dist/compaction/cut-point.js +70 -0
- package/dist/compaction/estimate.d.ts +30 -0
- package/dist/compaction/estimate.js +114 -0
- package/dist/compaction/prune-tier.d.ts +31 -0
- package/dist/compaction/prune-tier.js +83 -0
- package/dist/compaction/serialize.d.ts +20 -0
- package/dist/compaction/serialize.js +115 -0
- package/dist/compaction/summarize-tier.d.ts +111 -0
- package/dist/compaction/summarize-tier.js +305 -0
- package/dist/config/auth-file.d.ts +39 -0
- package/dist/config/auth-file.js +92 -0
- package/dist/config/context-files.d.ts +30 -0
- package/dist/config/context-files.js +77 -0
- package/dist/config/load.d.ts +45 -0
- package/dist/config/load.js +97 -0
- package/dist/config/merge.d.ts +73 -0
- package/dist/config/merge.js +248 -0
- package/dist/config/paths.d.ts +38 -0
- package/dist/config/paths.js +108 -0
- package/dist/config/profile.d.ts +27 -0
- package/dist/config/profile.js +65 -0
- package/dist/config/schema.d.ts +34 -0
- package/dist/config/schema.js +413 -0
- package/dist/config/trust.d.ts +42 -0
- package/dist/config/trust.js +122 -0
- package/dist/config/types.d.ts +172 -0
- package/dist/config/types.js +27 -0
- package/dist/config/write.d.ts +10 -0
- package/dist/config/write.js +25 -0
- package/dist/errors.d.ts +28 -0
- package/dist/errors.js +30 -0
- package/dist/hooks/config.d.ts +49 -0
- package/dist/hooks/config.js +102 -0
- package/dist/hooks/dispatcher.d.ts +41 -0
- package/dist/hooks/dispatcher.js +104 -0
- package/dist/hooks/matcher.d.ts +22 -0
- package/dist/hooks/matcher.js +108 -0
- package/dist/hooks/protocol.d.ts +33 -0
- package/dist/hooks/protocol.js +240 -0
- package/dist/hooks/runner.d.ts +30 -0
- package/dist/hooks/runner.js +143 -0
- package/dist/hooks/types.d.ts +147 -0
- package/dist/hooks/types.js +20 -0
- package/dist/host/api-impl.d.ts +75 -0
- package/dist/host/api-impl.js +173 -0
- package/dist/host/loader.d.ts +31 -0
- package/dist/host/loader.js +147 -0
- package/dist/host/types.d.ts +169 -0
- package/dist/host/types.js +14 -0
- package/dist/host.d.ts +5 -0
- package/dist/host.js +4 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +28 -0
- package/dist/modes/commands-core.d.ts +44 -0
- package/dist/modes/commands-core.js +171 -0
- package/dist/modes/interactive/approval-dialog.d.ts +48 -0
- package/dist/modes/interactive/approval-dialog.js +202 -0
- package/dist/modes/interactive/commands.d.ts +41 -0
- package/dist/modes/interactive/commands.js +202 -0
- package/dist/modes/interactive/completion.d.ts +53 -0
- package/dist/modes/interactive/completion.js +157 -0
- package/dist/modes/interactive/interactive-mode.d.ts +46 -0
- package/dist/modes/interactive/interactive-mode.js +487 -0
- package/dist/modes/interactive/key-dispatch.d.ts +29 -0
- package/dist/modes/interactive/key-dispatch.js +107 -0
- package/dist/modes/interactive/line/line-editor.d.ts +50 -0
- package/dist/modes/interactive/line/line-editor.js +232 -0
- package/dist/modes/interactive/line/line-mode.d.ts +20 -0
- package/dist/modes/interactive/line/line-mode.js +216 -0
- package/dist/modes/interactive/line/line-render.d.ts +35 -0
- package/dist/modes/interactive/line/line-render.js +171 -0
- package/dist/modes/interactive/line/paste-state.d.ts +26 -0
- package/dist/modes/interactive/line/paste-state.js +72 -0
- package/dist/modes/interactive/message-view.d.ts +77 -0
- package/dist/modes/interactive/message-view.js +269 -0
- package/dist/modes/interactive/pickers.d.ts +42 -0
- package/dist/modes/interactive/pickers.js +115 -0
- package/dist/modes/interactive/startup-ui.d.ts +28 -0
- package/dist/modes/interactive/startup-ui.js +238 -0
- package/dist/modes/interactive/status-bar.d.ts +48 -0
- package/dist/modes/interactive/status-bar.js +139 -0
- package/dist/modes/interactive/tool-view.d.ts +95 -0
- package/dist/modes/interactive/tool-view.js +344 -0
- package/dist/modes/print/json-event.d.ts +15 -0
- package/dist/modes/print/json-event.js +39 -0
- package/dist/modes/print/print-mode.d.ts +15 -0
- package/dist/modes/print/print-mode.js +96 -0
- package/dist/modes/rpc/commands.d.ts +40 -0
- package/dist/modes/rpc/commands.js +258 -0
- package/dist/modes/rpc/jsonl.d.ts +16 -0
- package/dist/modes/rpc/jsonl.js +55 -0
- package/dist/modes/rpc/rpc-mode.d.ts +22 -0
- package/dist/modes/rpc/rpc-mode.js +153 -0
- package/dist/modes/session-report.d.ts +55 -0
- package/dist/modes/session-report.js +278 -0
- package/dist/modes/shared.d.ts +13 -0
- package/dist/modes/shared.js +52 -0
- package/dist/modes/startup-ui-text.d.ts +16 -0
- package/dist/modes/startup-ui-text.js +103 -0
- package/dist/permissions/broker.d.ts +47 -0
- package/dist/permissions/broker.js +107 -0
- package/dist/permissions/dangerous.d.ts +47 -0
- package/dist/permissions/dangerous.js +370 -0
- package/dist/permissions/pipeline.d.ts +51 -0
- package/dist/permissions/pipeline.js +181 -0
- package/dist/permissions/preview.d.ts +43 -0
- package/dist/permissions/preview.js +463 -0
- package/dist/permissions/rules.d.ts +58 -0
- package/dist/permissions/rules.js +249 -0
- package/dist/permissions/types.d.ts +100 -0
- package/dist/permissions/types.js +18 -0
- package/dist/rpc.d.ts +171 -0
- package/dist/rpc.js +13 -0
- package/dist/sdk.d.ts +98 -0
- package/dist/sdk.js +195 -0
- package/dist/session/manager.d.ts +70 -0
- package/dist/session/manager.js +278 -0
- package/dist/session/migrate.d.ts +19 -0
- package/dist/session/migrate.js +53 -0
- package/dist/session/projection.d.ts +50 -0
- package/dist/session/projection.js +180 -0
- package/dist/session/store.d.ts +47 -0
- package/dist/session/store.js +210 -0
- package/dist/session/tree.d.ts +21 -0
- package/dist/session/tree.js +88 -0
- package/dist/session/types.d.ts +199 -0
- package/dist/session/types.js +18 -0
- package/dist/skills/discover.d.ts +60 -0
- package/dist/skills/discover.js +160 -0
- package/dist/skills/expand.d.ts +35 -0
- package/dist/skills/expand.js +46 -0
- package/dist/skills/frontmatter.d.ts +27 -0
- package/dist/skills/frontmatter.js +157 -0
- package/dist/skills/index-prompt.d.ts +13 -0
- package/dist/skills/index-prompt.js +42 -0
- package/dist/skills/templates.d.ts +52 -0
- package/dist/skills/templates.js +177 -0
- package/dist/tools/bash.d.ts +49 -0
- package/dist/tools/bash.js +222 -0
- package/dist/tools/edit-fuzzy.d.ts +36 -0
- package/dist/tools/edit-fuzzy.js +129 -0
- package/dist/tools/edit.d.ts +38 -0
- package/dist/tools/edit.js +241 -0
- package/dist/tools/file-mutex.d.ts +8 -0
- package/dist/tools/file-mutex.js +29 -0
- package/dist/tools/glob.d.ts +44 -0
- package/dist/tools/glob.js +217 -0
- package/dist/tools/grep.d.ts +39 -0
- package/dist/tools/grep.js +179 -0
- package/dist/tools/ignore.d.ts +40 -0
- package/dist/tools/ignore.js +174 -0
- package/dist/tools/ls.d.ts +21 -0
- package/dist/tools/ls.js +96 -0
- package/dist/tools/output-accumulator.d.ts +48 -0
- package/dist/tools/output-accumulator.js +106 -0
- package/dist/tools/paths.d.ts +20 -0
- package/dist/tools/paths.js +58 -0
- package/dist/tools/presets.d.ts +71 -0
- package/dist/tools/presets.js +128 -0
- package/dist/tools/process-tree.d.ts +35 -0
- package/dist/tools/process-tree.js +125 -0
- package/dist/tools/read.d.ts +28 -0
- package/dist/tools/read.js +181 -0
- package/dist/tools/registry.d.ts +43 -0
- package/dist/tools/registry.js +106 -0
- package/dist/tools/shell.d.ts +38 -0
- package/dist/tools/shell.js +91 -0
- package/dist/tools/task.d.ts +29 -0
- package/dist/tools/task.js +107 -0
- package/dist/tools/todo.d.ts +28 -0
- package/dist/tools/todo.js +107 -0
- package/dist/tools/truncate.d.ts +44 -0
- package/dist/tools/truncate.js +175 -0
- package/dist/tools/types.d.ts +135 -0
- package/dist/tools/types.js +19 -0
- package/dist/tools/write.d.ts +20 -0
- package/dist/tools/write.js +84 -0
- package/dist/tui/ansi.d.ts +29 -0
- package/dist/tui/ansi.js +420 -0
- package/dist/tui/component.d.ts +38 -0
- package/dist/tui/component.js +13 -0
- package/dist/tui/components/box.d.ts +26 -0
- package/dist/tui/components/box.js +65 -0
- package/dist/tui/components/container.d.ts +14 -0
- package/dist/tui/components/container.js +39 -0
- package/dist/tui/components/editor-buffer.d.ts +67 -0
- package/dist/tui/components/editor-buffer.js +300 -0
- package/dist/tui/components/editor-paste.d.ts +29 -0
- package/dist/tui/components/editor-paste.js +64 -0
- package/dist/tui/components/editor.d.ts +114 -0
- package/dist/tui/components/editor.js +530 -0
- package/dist/tui/components/key-value.d.ts +29 -0
- package/dist/tui/components/key-value.js +48 -0
- package/dist/tui/components/loader.d.ts +35 -0
- package/dist/tui/components/loader.js +71 -0
- package/dist/tui/components/markdown.d.ts +90 -0
- package/dist/tui/components/markdown.js +462 -0
- package/dist/tui/components/meter.d.ts +29 -0
- package/dist/tui/components/meter.js +47 -0
- package/dist/tui/components/overlay.d.ts +24 -0
- package/dist/tui/components/overlay.js +52 -0
- package/dist/tui/components/select-list.d.ts +57 -0
- package/dist/tui/components/select-list.js +179 -0
- package/dist/tui/components/spacer.d.ts +11 -0
- package/dist/tui/components/spacer.js +16 -0
- package/dist/tui/components/text.d.ts +30 -0
- package/dist/tui/components/text.js +65 -0
- package/dist/tui/keybindings.d.ts +66 -0
- package/dist/tui/keybindings.js +120 -0
- package/dist/tui/keys.d.ts +38 -0
- package/dist/tui/keys.js +275 -0
- package/dist/tui/stdin-buffer.d.ts +41 -0
- package/dist/tui/stdin-buffer.js +206 -0
- package/dist/tui/terminal.d.ts +79 -0
- package/dist/tui/terminal.js +153 -0
- package/dist/tui/theme.d.ts +31 -0
- package/dist/tui/theme.js +199 -0
- package/dist/tui/tui.d.ts +103 -0
- package/dist/tui/tui.js +363 -0
- package/dist/tui/vt-screen.d.ts +46 -0
- package/dist/tui/vt-screen.js +251 -0
- package/dist/tui.d.ts +30 -0
- package/dist/tui.js +31 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.js +24 -0
- package/docs/codemode.md +102 -0
- package/docs/hooks.md +196 -0
- package/docs/host-api.md +161 -0
- package/docs/providers.md +316 -0
- package/docs/rpc.md +253 -0
- package/docs/session-format.md +119 -0
- package/docs/tui.md +168 -0
- package/package.json +101 -4
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工具调用显示(设计 §12.5)。[B7]
|
|
3
|
+
*
|
|
4
|
+
* - 一行标题 `● bash git status`:圆点运行中为强调色,成功绿、失败红;摘要取最能代表这次调用的参数
|
|
5
|
+
* (bash 命令、文件路径、搜索模式、task 描述……),路径相对会话 cwd。
|
|
6
|
+
* - 折叠(缺省):结果前 3 行 + 剩余行数;`edit` 显示 `details.diff`(+/− 着色,前 12 行);
|
|
7
|
+
* `bash` 运行中流式显示尾部 8 行;错误红色。`Ctrl+O` 展开全部(上限 400 行)。
|
|
8
|
+
* - 嵌套:带 `parentToolCallId` 的调用(codemode 脚本里的 `tools.*`,B10)挂在外层调用下;折叠时只列
|
|
9
|
+
* 内层调用的标题(最近 5 个),展开时完整显示。
|
|
10
|
+
* - 工具输出先去掉 ANSI 与控制字符、Tab 换成空格,避免打乱布局。
|
|
11
|
+
* - 自定义渲染(W3-B9a-2,`ToolDefinition.renderCall / renderResult`):`getTool` 能取到定义时,标题摘要
|
|
12
|
+
* 优先取 `renderCall(input, width)` 的第一行(codemode 显示脚本首行);成功的结果优先用
|
|
13
|
+
* `renderResult(result, width, expanded)`(去控制字符、按宽截断、上限 400 行);自定义渲染抛错或返回
|
|
14
|
+
* 空时回到缺省显示;错误结果始终用缺省的红色显示。
|
|
15
|
+
*/
|
|
16
|
+
import { isAbsolute, relative } from "node:path";
|
|
17
|
+
import { stripAnsi, truncateToWidth, wrapTextWithAnsi, } from "../../tui.js";
|
|
18
|
+
import { contentText } from "./message-view.js";
|
|
19
|
+
export const COLLAPSED_RESULT_LINES = 3;
|
|
20
|
+
export const COLLAPSED_DIFF_LINES = 12;
|
|
21
|
+
export const BASH_TAIL_LINES = 8;
|
|
22
|
+
export const EXPANDED_MAX_LINES = 400;
|
|
23
|
+
export const COLLAPSED_CHILDREN = 5;
|
|
24
|
+
/** 工具输出 → 可安全显示的行。 */
|
|
25
|
+
export function cleanLines(text) {
|
|
26
|
+
const clean = stripAnsi(text)
|
|
27
|
+
.replace(/\r\n?/g, "\n")
|
|
28
|
+
.replace(/\t/g, " ")
|
|
29
|
+
.replace(/[\x00-\x08\x0b-\x1f\x7f]/g, "");
|
|
30
|
+
const lines = clean.split("\n");
|
|
31
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "")
|
|
32
|
+
lines.pop();
|
|
33
|
+
return lines;
|
|
34
|
+
}
|
|
35
|
+
function flat(text, max = 120) {
|
|
36
|
+
const one = text.replace(/\s*\n\s*/g, " ⏎ ").trim();
|
|
37
|
+
return one.length > max ? `${one.slice(0, max - 1)}…` : one;
|
|
38
|
+
}
|
|
39
|
+
function displayPath(path, cwd) {
|
|
40
|
+
if (cwd === undefined || !isAbsolute(path))
|
|
41
|
+
return path;
|
|
42
|
+
const rel = relative(cwd, path);
|
|
43
|
+
return rel === "" ? "." : rel.startsWith("..") || isAbsolute(rel) ? path : rel;
|
|
44
|
+
}
|
|
45
|
+
/** 标题行里的参数摘要。 */
|
|
46
|
+
export function toolSummary(name, args, cwd) {
|
|
47
|
+
if (typeof args !== "object" || args === null)
|
|
48
|
+
return "";
|
|
49
|
+
const a = args;
|
|
50
|
+
const str = (key) => typeof a[key] === "string" && a[key] !== "" ? a[key] : undefined;
|
|
51
|
+
const path = str("path") ?? str("file_path");
|
|
52
|
+
switch (name) {
|
|
53
|
+
case "bash":
|
|
54
|
+
return flat(str("command") ?? "");
|
|
55
|
+
case "read": {
|
|
56
|
+
if (path === undefined)
|
|
57
|
+
return "";
|
|
58
|
+
const offset = typeof a["offset"] === "number" ? a["offset"] : undefined;
|
|
59
|
+
const limit = typeof a["limit"] === "number" ? a["limit"] : undefined;
|
|
60
|
+
const range = offset !== undefined || limit !== undefined
|
|
61
|
+
? `:${offset ?? 1}${limit !== undefined ? `+${limit}` : ""}`
|
|
62
|
+
: "";
|
|
63
|
+
return displayPath(path, cwd) + range;
|
|
64
|
+
}
|
|
65
|
+
case "grep":
|
|
66
|
+
case "glob": {
|
|
67
|
+
const pattern = str("pattern") ?? "";
|
|
68
|
+
return path !== undefined ? `${flat(pattern)} in ${displayPath(path, cwd)}` : flat(pattern);
|
|
69
|
+
}
|
|
70
|
+
case "task":
|
|
71
|
+
return flat(str("description") ?? str("prompt") ?? "");
|
|
72
|
+
default:
|
|
73
|
+
if (path !== undefined)
|
|
74
|
+
return displayPath(path, cwd);
|
|
75
|
+
for (const key of [
|
|
76
|
+
"command",
|
|
77
|
+
"pattern",
|
|
78
|
+
"description",
|
|
79
|
+
"query",
|
|
80
|
+
"url",
|
|
81
|
+
"name",
|
|
82
|
+
"code",
|
|
83
|
+
"script",
|
|
84
|
+
]) {
|
|
85
|
+
const value = str(key);
|
|
86
|
+
if (value !== undefined)
|
|
87
|
+
return flat(value);
|
|
88
|
+
}
|
|
89
|
+
return "";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function diffOf(result) {
|
|
93
|
+
const details = result?.details;
|
|
94
|
+
if (typeof details !== "object" || details === null)
|
|
95
|
+
return undefined;
|
|
96
|
+
const diff = details.diff;
|
|
97
|
+
return typeof diff === "string" && diff !== "" ? diff : undefined;
|
|
98
|
+
}
|
|
99
|
+
export class ToolView {
|
|
100
|
+
toolCallId;
|
|
101
|
+
toolName;
|
|
102
|
+
args;
|
|
103
|
+
options;
|
|
104
|
+
state = "running";
|
|
105
|
+
partial = "";
|
|
106
|
+
result;
|
|
107
|
+
expanded = false;
|
|
108
|
+
nested = [];
|
|
109
|
+
cache = null;
|
|
110
|
+
version = 0;
|
|
111
|
+
/** 外层调用(嵌套时):子视图变化要让外层缓存失效。 */
|
|
112
|
+
parent;
|
|
113
|
+
constructor(toolCallId, toolName, args, options) {
|
|
114
|
+
this.toolCallId = toolCallId;
|
|
115
|
+
this.toolName = toolName;
|
|
116
|
+
this.args = args;
|
|
117
|
+
this.options = options;
|
|
118
|
+
}
|
|
119
|
+
get isRunning() {
|
|
120
|
+
return this.state === "running";
|
|
121
|
+
}
|
|
122
|
+
get isExpanded() {
|
|
123
|
+
return this.expanded;
|
|
124
|
+
}
|
|
125
|
+
get children() {
|
|
126
|
+
return this.nested;
|
|
127
|
+
}
|
|
128
|
+
setExpanded(expanded) {
|
|
129
|
+
if (this.expanded === expanded)
|
|
130
|
+
return;
|
|
131
|
+
this.expanded = expanded;
|
|
132
|
+
for (const child of this.nested)
|
|
133
|
+
child.setExpanded(expanded);
|
|
134
|
+
this.touch();
|
|
135
|
+
}
|
|
136
|
+
/** 运行中的输出(滚动尾部,整体替换)。 */
|
|
137
|
+
update(partial) {
|
|
138
|
+
this.partial = partial;
|
|
139
|
+
this.touch();
|
|
140
|
+
}
|
|
141
|
+
finish(result, isError) {
|
|
142
|
+
this.result = result;
|
|
143
|
+
this.state = isError || result.isError === true ? "error" : "done";
|
|
144
|
+
this.touch();
|
|
145
|
+
}
|
|
146
|
+
addNested(child) {
|
|
147
|
+
child.setExpanded(this.expanded);
|
|
148
|
+
child.parent = this;
|
|
149
|
+
this.nested.push(child);
|
|
150
|
+
this.touch();
|
|
151
|
+
}
|
|
152
|
+
touch() {
|
|
153
|
+
this.version++;
|
|
154
|
+
this.parent?.touch();
|
|
155
|
+
}
|
|
156
|
+
invalidate() {
|
|
157
|
+
this.cache = null;
|
|
158
|
+
for (const child of this.nested)
|
|
159
|
+
child.invalidate();
|
|
160
|
+
}
|
|
161
|
+
render(width) {
|
|
162
|
+
if (this.cache && this.cache.width === width && this.cache.version === this.version) {
|
|
163
|
+
return this.cache.lines;
|
|
164
|
+
}
|
|
165
|
+
const lines = [this.header(width), ...this.body(width)];
|
|
166
|
+
this.cache = { width, version: this.version, lines };
|
|
167
|
+
return lines;
|
|
168
|
+
}
|
|
169
|
+
header(width) {
|
|
170
|
+
const { theme } = this.options;
|
|
171
|
+
const dot = this.state === "running"
|
|
172
|
+
? theme.fg("accent", "●")
|
|
173
|
+
: this.state === "error"
|
|
174
|
+
? theme.fg("error", "●")
|
|
175
|
+
: theme.fg("success", "●");
|
|
176
|
+
const summary = this.customCall(width) ?? toolSummary(this.toolName, this.args, this.options.cwd);
|
|
177
|
+
const title = `${dot} ${theme.bold(theme.fg("tool", this.toolName))}`;
|
|
178
|
+
return truncateToWidth(summary === "" ? title : `${title} ${summary}`, width);
|
|
179
|
+
}
|
|
180
|
+
custom(render) {
|
|
181
|
+
const tool = this.options.getTool?.(this.toolName);
|
|
182
|
+
if (tool === undefined)
|
|
183
|
+
return undefined;
|
|
184
|
+
try {
|
|
185
|
+
return render(tool);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** `renderCall` 的第一行(去控制字符、折叠空白);没有或为空时 undefined。 */
|
|
192
|
+
customCall(width) {
|
|
193
|
+
const first = this.custom((tool) => tool.renderCall?.(this.args, width)?.[0]);
|
|
194
|
+
if (typeof first !== "string")
|
|
195
|
+
return undefined;
|
|
196
|
+
const line = flat(cleanLines(first).join(" "));
|
|
197
|
+
return line === "" ? undefined : line;
|
|
198
|
+
}
|
|
199
|
+
/** 成功结果的 `renderResult` 行;没有或为空时 undefined。 */
|
|
200
|
+
customResult(width) {
|
|
201
|
+
const result = this.result;
|
|
202
|
+
if (result === undefined || this.state !== "done")
|
|
203
|
+
return undefined;
|
|
204
|
+
const inner = Math.max(1, width - 2);
|
|
205
|
+
const rendered = this.custom((tool) => tool.renderResult?.(result, inner, this.expanded));
|
|
206
|
+
if (!Array.isArray(rendered) || rendered.length === 0)
|
|
207
|
+
return undefined;
|
|
208
|
+
return rendered
|
|
209
|
+
.slice(0, EXPANDED_MAX_LINES)
|
|
210
|
+
.map((line) => " " + truncateToWidth(cleanLines(String(line)).join(" "), inner));
|
|
211
|
+
}
|
|
212
|
+
indent(lines, width, color) {
|
|
213
|
+
const { theme } = this.options;
|
|
214
|
+
const inner = Math.max(1, width - 2);
|
|
215
|
+
const out = [];
|
|
216
|
+
for (const line of lines) {
|
|
217
|
+
const pieces = this.expanded ? wrapTextWithAnsi(line, inner) : [truncateToWidth(line, inner)];
|
|
218
|
+
for (const piece of pieces)
|
|
219
|
+
out.push(" " + (color ? theme.fg(color, piece) : piece));
|
|
220
|
+
}
|
|
221
|
+
return out;
|
|
222
|
+
}
|
|
223
|
+
more(hidden) {
|
|
224
|
+
return " " + this.options.theme.fg("dim", `… 另 ${hidden} 行(Ctrl+O 展开)`);
|
|
225
|
+
}
|
|
226
|
+
body(width) {
|
|
227
|
+
const { theme } = this.options;
|
|
228
|
+
const out = [];
|
|
229
|
+
// 嵌套调用
|
|
230
|
+
if (this.nested.length > 0) {
|
|
231
|
+
if (this.expanded) {
|
|
232
|
+
for (const child of this.nested) {
|
|
233
|
+
for (const line of child.render(Math.max(1, width - 2)))
|
|
234
|
+
out.push(" " + line);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
const shown = this.nested.slice(-COLLAPSED_CHILDREN);
|
|
239
|
+
if (this.nested.length > shown.length) {
|
|
240
|
+
out.push(" " + theme.fg("dim", `… 前 ${this.nested.length - shown.length} 个调用`));
|
|
241
|
+
}
|
|
242
|
+
for (const child of shown)
|
|
243
|
+
out.push(" " + child.header(Math.max(1, width - 2)));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (this.state === "running") {
|
|
247
|
+
if (this.partial !== "") {
|
|
248
|
+
const all = cleanLines(this.partial);
|
|
249
|
+
const tail = this.expanded ? all.slice(-EXPANDED_MAX_LINES) : all.slice(-BASH_TAIL_LINES);
|
|
250
|
+
out.push(...this.indent(tail, width, "dim"));
|
|
251
|
+
}
|
|
252
|
+
return out;
|
|
253
|
+
}
|
|
254
|
+
const custom = this.customResult(width);
|
|
255
|
+
if (custom !== undefined) {
|
|
256
|
+
out.push(...custom);
|
|
257
|
+
return out;
|
|
258
|
+
}
|
|
259
|
+
const diff = this.state === "done" ? diffOf(this.result) : undefined;
|
|
260
|
+
if (diff !== undefined) {
|
|
261
|
+
const all = cleanLines(diff).filter((l) => !l.startsWith("---") && !l.startsWith("+++"));
|
|
262
|
+
const limit = this.expanded ? EXPANDED_MAX_LINES : COLLAPSED_DIFF_LINES;
|
|
263
|
+
const shown = all.slice(0, limit);
|
|
264
|
+
const inner = Math.max(1, width - 2);
|
|
265
|
+
for (const line of shown) {
|
|
266
|
+
const text = truncateToWidth(line, inner);
|
|
267
|
+
const colored = line.startsWith("+")
|
|
268
|
+
? theme.fg("success", text)
|
|
269
|
+
: line.startsWith("-")
|
|
270
|
+
? theme.fg("error", text)
|
|
271
|
+
: line.startsWith("@@")
|
|
272
|
+
? theme.fg("accent", text)
|
|
273
|
+
: theme.fg("dim", text);
|
|
274
|
+
out.push(" " + colored);
|
|
275
|
+
}
|
|
276
|
+
if (all.length > shown.length)
|
|
277
|
+
out.push(this.more(all.length - shown.length));
|
|
278
|
+
return out;
|
|
279
|
+
}
|
|
280
|
+
const text = this.result === undefined ? "" : contentText(this.result.content);
|
|
281
|
+
const all = cleanLines(text);
|
|
282
|
+
if (all.length === 0)
|
|
283
|
+
return out;
|
|
284
|
+
const limit = this.expanded ? EXPANDED_MAX_LINES : COLLAPSED_RESULT_LINES;
|
|
285
|
+
const shown = all.slice(0, limit);
|
|
286
|
+
out.push(...this.indent(shown, width, this.state === "error" ? "error" : "dim"));
|
|
287
|
+
if (all.length > shown.length)
|
|
288
|
+
out.push(this.more(all.length - shown.length));
|
|
289
|
+
return out;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/** 按 toolCallId 管理视图与嵌套;`Ctrl+O` 的全局展开状态也在这里。 */
|
|
293
|
+
export class ToolTracker {
|
|
294
|
+
options;
|
|
295
|
+
views = new Map();
|
|
296
|
+
expanded = false;
|
|
297
|
+
constructor(options) {
|
|
298
|
+
this.options = options;
|
|
299
|
+
}
|
|
300
|
+
get isExpanded() {
|
|
301
|
+
return this.expanded;
|
|
302
|
+
}
|
|
303
|
+
get(toolCallId) {
|
|
304
|
+
return this.views.get(toolCallId);
|
|
305
|
+
}
|
|
306
|
+
/** 新调用;返回视图与它是否是顶层(顶层由调用方加进消息区)。 */
|
|
307
|
+
start(event) {
|
|
308
|
+
const existing = this.views.get(event.toolCallId);
|
|
309
|
+
if (existing !== undefined)
|
|
310
|
+
return { view: existing, topLevel: false };
|
|
311
|
+
const view = new ToolView(event.toolCallId, event.toolName, event.args, this.options);
|
|
312
|
+
view.setExpanded(this.expanded);
|
|
313
|
+
this.views.set(event.toolCallId, view);
|
|
314
|
+
const parent = event.parentToolCallId !== undefined ? this.views.get(event.parentToolCallId) : undefined;
|
|
315
|
+
if (parent !== undefined) {
|
|
316
|
+
parent.addNested(view);
|
|
317
|
+
return { view, topLevel: false };
|
|
318
|
+
}
|
|
319
|
+
return { view, topLevel: true };
|
|
320
|
+
}
|
|
321
|
+
update(toolCallId, partial) {
|
|
322
|
+
this.views.get(toolCallId)?.update(partial);
|
|
323
|
+
}
|
|
324
|
+
end(toolCallId, result, isError) {
|
|
325
|
+
this.views.get(toolCallId)?.finish(result, isError);
|
|
326
|
+
}
|
|
327
|
+
/** 已完成的调用(重放历史)。 */
|
|
328
|
+
completed(toolCallId, toolName, args, result, isError) {
|
|
329
|
+
const { view } = this.start({ toolCallId, toolName, args });
|
|
330
|
+
if (result !== undefined)
|
|
331
|
+
view.finish(result, isError);
|
|
332
|
+
return view;
|
|
333
|
+
}
|
|
334
|
+
/** Ctrl+O:切换全部调用的展开状态。 */
|
|
335
|
+
toggleExpanded() {
|
|
336
|
+
this.expanded = !this.expanded;
|
|
337
|
+
for (const view of this.views.values())
|
|
338
|
+
view.setExpanded(this.expanded);
|
|
339
|
+
return this.expanded;
|
|
340
|
+
}
|
|
341
|
+
clear() {
|
|
342
|
+
this.views.clear();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 线上事件形状(设计 §13.2、src/rpc.ts):RPC 与 `--output-format stream-json` 共用。[B6]
|
|
3
|
+
*
|
|
4
|
+
* - `message_update` 变成纯增量:去掉累计消息与 `partial`,附最新 `usage`;`done / error`
|
|
5
|
+
* 保留最终 `message`。其余 `SessionEvent` 原样。
|
|
6
|
+
* - `toJsonLine()`:一行 JSON;Error 序列化为 `{ name, message }`,bigint 转字符串,
|
|
7
|
+
* U+2028 / U+2029 转义(部分 JSONL 客户端会把它们当换行);图片 base64 不截断。
|
|
8
|
+
*/
|
|
9
|
+
import type { SessionEvent } from "../../agent/types.js";
|
|
10
|
+
import type { AssistantEvent } from "../../ai/types.js";
|
|
11
|
+
import type { RpcEvent, WireAssistantEvent } from "../../rpc.js";
|
|
12
|
+
export declare function toWireAssistantEvent(event: AssistantEvent): WireAssistantEvent;
|
|
13
|
+
export declare function toWireEvent(event: SessionEvent): RpcEvent;
|
|
14
|
+
/** 一行 JSON(不含换行符)。 */
|
|
15
|
+
export declare function toJsonLine(value: unknown): string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 线上事件形状(设计 §13.2、src/rpc.ts):RPC 与 `--output-format stream-json` 共用。[B6]
|
|
3
|
+
*
|
|
4
|
+
* - `message_update` 变成纯增量:去掉累计消息与 `partial`,附最新 `usage`;`done / error`
|
|
5
|
+
* 保留最终 `message`。其余 `SessionEvent` 原样。
|
|
6
|
+
* - `toJsonLine()`:一行 JSON;Error 序列化为 `{ name, message }`,bigint 转字符串,
|
|
7
|
+
* U+2028 / U+2029 转义(部分 JSONL 客户端会把它们当换行);图片 base64 不截断。
|
|
8
|
+
*/
|
|
9
|
+
export function toWireAssistantEvent(event) {
|
|
10
|
+
if (!("partial" in event))
|
|
11
|
+
return event;
|
|
12
|
+
const { partial: _partial, ...rest } = event;
|
|
13
|
+
return rest;
|
|
14
|
+
}
|
|
15
|
+
export function toWireEvent(event) {
|
|
16
|
+
if (event.type !== "message_update")
|
|
17
|
+
return event;
|
|
18
|
+
const wire = {
|
|
19
|
+
type: "message_update",
|
|
20
|
+
assistantMessageEvent: toWireAssistantEvent(event.assistantMessageEvent),
|
|
21
|
+
};
|
|
22
|
+
const usage = event.message.usage;
|
|
23
|
+
if (usage !== undefined)
|
|
24
|
+
wire.usage = usage;
|
|
25
|
+
return wire;
|
|
26
|
+
}
|
|
27
|
+
function replacer(_key, value) {
|
|
28
|
+
if (typeof value === "bigint")
|
|
29
|
+
return value.toString();
|
|
30
|
+
if (value instanceof Error)
|
|
31
|
+
return { name: value.name, message: value.message };
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
/** 一行 JSON(不含换行符)。 */
|
|
35
|
+
export function toJsonLine(value) {
|
|
36
|
+
return JSON.stringify(value, replacer)
|
|
37
|
+
.replace(/\u2028/g, "\\u2028")
|
|
38
|
+
.replace(/\u2029/g, "\\u2029");
|
|
39
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* print 模式(`ama -p`,设计 §11.1 第 15–16 步)。[B6]
|
|
3
|
+
*
|
|
4
|
+
* - 提示 = 位置参数 + stdin 管道(stdin 非 TTY 时读到 EOF),两者都有时空一行拼接;都没有 → 用法错误 2。
|
|
5
|
+
* - `--output-format text`(缺省):运行结束后输出最后一条助手文本;`json`:一个结果对象(文本、
|
|
6
|
+
* 停止原因、用量、缓存命中率、[W3-C2] `cache` 统计(同 `get_session_stats.cache`)、全部条目);
|
|
7
|
+
* `stream-json`:每个会话事件一行(线上形状同 RPC,含 `cache_miss` / `cache_warm` /
|
|
8
|
+
* `context_pressure`)。
|
|
9
|
+
* - 无人值守:ask → deny(bootstrap 已按 print 设 unattended)。
|
|
10
|
+
* - 退出码:最终助手消息 `error / aborted` 或提示被拒 → 1;SIGINT 130、SIGTERM 143(先 abort)。
|
|
11
|
+
*/
|
|
12
|
+
import type { ModeContext } from "../../cli/deps.js";
|
|
13
|
+
import type { Runtime } from "../../cli/runtime.js";
|
|
14
|
+
export declare function joinPrompt(argument: string | undefined, piped: string): string;
|
|
15
|
+
export declare function runPrintMode(runtime: Runtime, context: ModeContext): Promise<number>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* print 模式(`ama -p`,设计 §11.1 第 15–16 步)。[B6]
|
|
3
|
+
*
|
|
4
|
+
* - 提示 = 位置参数 + stdin 管道(stdin 非 TTY 时读到 EOF),两者都有时空一行拼接;都没有 → 用法错误 2。
|
|
5
|
+
* - `--output-format text`(缺省):运行结束后输出最后一条助手文本;`json`:一个结果对象(文本、
|
|
6
|
+
* 停止原因、用量、缓存命中率、[W3-C2] `cache` 统计(同 `get_session_stats.cache`)、全部条目);
|
|
7
|
+
* `stream-json`:每个会话事件一行(线上形状同 RPC,含 `cache_miss` / `cache_warm` /
|
|
8
|
+
* `context_pressure`)。
|
|
9
|
+
* - 无人值守:ask → deny(bootstrap 已按 print 设 unattended)。
|
|
10
|
+
* - 退出码:最终助手消息 `error / aborted` 或提示被拒 → 1;SIGINT 130、SIGTERM 143(先 abort)。
|
|
11
|
+
*/
|
|
12
|
+
import { currentSession } from "../../cli/compose-session.js";
|
|
13
|
+
import { ExitCode } from "../../cli/exit-codes.js";
|
|
14
|
+
import { errorText, lastAssistant, onStdoutClosed, onTerminationSignals } from "../shared.js";
|
|
15
|
+
import { toJsonLine, toWireEvent } from "./json-event.js";
|
|
16
|
+
export function joinPrompt(argument, piped) {
|
|
17
|
+
const parts = [argument ?? "", piped.replace(/\s+$/, "")].filter((p) => p.trim() !== "");
|
|
18
|
+
return parts.join("\n\n");
|
|
19
|
+
}
|
|
20
|
+
export async function runPrintMode(runtime, context) {
|
|
21
|
+
const { io } = context;
|
|
22
|
+
const format = context.args.outputFormat ?? "text";
|
|
23
|
+
const piped = io.stdinIsTTY ? "" : await io.readStdin();
|
|
24
|
+
const prompt = joinPrompt(context.prompt, piped);
|
|
25
|
+
if (prompt === "") {
|
|
26
|
+
io.stderr("ama: -p 需要提示(位置参数或 stdin 管道)\n");
|
|
27
|
+
return ExitCode.Usage;
|
|
28
|
+
}
|
|
29
|
+
const session = currentSession(runtime);
|
|
30
|
+
const unsubscribe = format === "stream-json"
|
|
31
|
+
? session.subscribe((event) => io.stdout(`${toJsonLine(toWireEvent(event))}\n`))
|
|
32
|
+
: () => undefined;
|
|
33
|
+
let signalled;
|
|
34
|
+
const offSignals = onTerminationSignals((code) => {
|
|
35
|
+
signalled ??= code;
|
|
36
|
+
void session.abort();
|
|
37
|
+
});
|
|
38
|
+
let stdoutClosed = false;
|
|
39
|
+
const offEpipe = onStdoutClosed(() => {
|
|
40
|
+
stdoutClosed = true;
|
|
41
|
+
void session.abort();
|
|
42
|
+
});
|
|
43
|
+
let failure;
|
|
44
|
+
try {
|
|
45
|
+
await session.prompt(prompt);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
failure = errorText(error);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
offSignals();
|
|
52
|
+
offEpipe();
|
|
53
|
+
unsubscribe();
|
|
54
|
+
}
|
|
55
|
+
const last = lastAssistant(session);
|
|
56
|
+
const text = session.getLastAssistantText() ?? "";
|
|
57
|
+
const stopReason = failure !== undefined ? "error" : (last?.stopReason ?? "stop");
|
|
58
|
+
if (format === "text") {
|
|
59
|
+
// 部分模型在正文前多发空行:只去前导空行,保留首行缩进;json / stream-json 原样。
|
|
60
|
+
const shown = text.replace(/^\s*\n/, "");
|
|
61
|
+
if (shown !== "" && last?.stopReason !== "error")
|
|
62
|
+
io.stdout(shown.endsWith("\n") ? shown : `${shown}\n`);
|
|
63
|
+
}
|
|
64
|
+
else if (format === "json") {
|
|
65
|
+
const stats = session.getStats();
|
|
66
|
+
io.stdout(`${toJsonLine({
|
|
67
|
+
type: "result",
|
|
68
|
+
sessionId: session.state.sessionId,
|
|
69
|
+
sessionFile: session.state.sessionFile,
|
|
70
|
+
model: session.state.model,
|
|
71
|
+
stopReason,
|
|
72
|
+
text,
|
|
73
|
+
...(failure !== undefined || last?.errorMessage !== undefined
|
|
74
|
+
? { error: failure ?? last?.errorMessage }
|
|
75
|
+
: {}),
|
|
76
|
+
usage: stats.tokens,
|
|
77
|
+
cost: stats.cost,
|
|
78
|
+
cacheHitRate: stats.cacheHitRate,
|
|
79
|
+
...(stats.cache !== undefined ? { cache: stats.cache } : {}),
|
|
80
|
+
entries: session.entries,
|
|
81
|
+
})}\n`);
|
|
82
|
+
}
|
|
83
|
+
if (signalled !== undefined)
|
|
84
|
+
return signalled;
|
|
85
|
+
if (stdoutClosed)
|
|
86
|
+
return ExitCode.Ok; // 下游(如 `| head`)已拿够输出
|
|
87
|
+
if (failure !== undefined) {
|
|
88
|
+
io.stderr(`ama: ${failure}\n`);
|
|
89
|
+
return ExitCode.RuntimeError;
|
|
90
|
+
}
|
|
91
|
+
if (last?.stopReason === "error" || last?.stopReason === "aborted") {
|
|
92
|
+
io.stderr(`ama: ${last.errorMessage ?? "模型调用失败"}\n`);
|
|
93
|
+
return ExitCode.RuntimeError;
|
|
94
|
+
}
|
|
95
|
+
return ExitCode.Ok;
|
|
96
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RPC 命令分派表(设计 §13.2、src/rpc.ts 的 33 条命令)。[B6]
|
|
3
|
+
*
|
|
4
|
+
* - 提示类(prompt / steer / follow_up)不等运行结束:会话开始运行(`before_agent_start` /
|
|
5
|
+
* `agent_start`)、入队或被处理后立刻应答 `{ disposition }`;运行中的进展走事件。
|
|
6
|
+
* - 会话类(new_session / switch_session / fork)经组装根 `switchSession`,`ctx.onSessionChanged`
|
|
7
|
+
* 让模式重新订阅事件。
|
|
8
|
+
* - 审批:`RpcApprovals` 是 UI broker(`set_client_capabilities` 声明 approvals 后挂上),
|
|
9
|
+
* `permission_response` 按 requestId 作答;先到的回答暂存,等 broker 被问到时取用。
|
|
10
|
+
* - 密钥不离开进程:`get_available_models` 只回 `hasKey` 与 `keySource`。
|
|
11
|
+
*/
|
|
12
|
+
import type { AgentSession } from "../../agent/types.js";
|
|
13
|
+
import type { Runtime } from "../../cli/runtime.js";
|
|
14
|
+
import type { ApprovalBroker, ApprovalDecision, ApprovalRequest } from "../../permissions/types.js";
|
|
15
|
+
import type { RpcCapability, RpcCommandMap, RpcCommandType } from "../../rpc.js";
|
|
16
|
+
/** 审批 broker:等客户端 `permission_response`。 */
|
|
17
|
+
export declare class RpcApprovals implements ApprovalBroker {
|
|
18
|
+
private readonly pending;
|
|
19
|
+
private readonly early;
|
|
20
|
+
ask(request: ApprovalRequest, signal: AbortSignal): Promise<ApprovalDecision | undefined>;
|
|
21
|
+
/** 返回 false = 当前没有在等这个 requestId(已暂存,稍后被问到时生效)。 */
|
|
22
|
+
respond(requestId: string, decision: ApprovalDecision): boolean;
|
|
23
|
+
/** 关 stdin / 撤下时:全部弃权(会话按无人作答 deny)。 */
|
|
24
|
+
cancelAll(): void;
|
|
25
|
+
}
|
|
26
|
+
export interface RpcContext {
|
|
27
|
+
readonly runtime: Runtime;
|
|
28
|
+
session(): AgentSession;
|
|
29
|
+
capabilities: Set<RpcCapability>;
|
|
30
|
+
readonly approvals: RpcApprovals;
|
|
31
|
+
/** 会话被换掉后调用(模式据此重新订阅)。 */
|
|
32
|
+
onSessionChanged(next: AgentSession): void;
|
|
33
|
+
/** 运行开始后提示命令自身的失败(应答已发出)。 */
|
|
34
|
+
onBackgroundError(error: unknown): void;
|
|
35
|
+
}
|
|
36
|
+
export type RpcHandlers = {
|
|
37
|
+
[K in RpcCommandType]: (params: RpcCommandMap[K], ctx: RpcContext) => Promise<unknown>;
|
|
38
|
+
};
|
|
39
|
+
export declare const handlers: RpcHandlers;
|
|
40
|
+
export declare const RPC_COMMAND_TYPES: RpcCommandType[];
|