@armadra/agent 0.5.1 → 0.6.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 +203 -304
- package/CHANGELOG.zh-CN.md +462 -0
- package/README.md +408 -364
- package/README.zh-CN.md +705 -0
- package/dist/agent/session-plan.js +2 -2
- package/dist/agent/session-state.d.ts +3 -0
- package/dist/agent/session-state.js +20 -0
- package/dist/agent/session-subagent.d.ts +15 -1
- package/dist/agent/session-subagent.js +26 -3
- package/dist/agent/session-telemetry.d.ts +16 -2
- package/dist/agent/session-telemetry.js +29 -7
- package/dist/agent/session-tools.js +5 -2
- package/dist/agent/session-trace-writer.d.ts +27 -0
- package/dist/agent/session-trace-writer.js +253 -0
- package/dist/agent/session.d.ts +2 -0
- package/dist/agent/session.js +12 -0
- package/dist/agent/subagent-direct.d.ts +20 -0
- package/dist/agent/subagent-direct.js +76 -0
- package/dist/agent/subagent-registry.d.ts +8 -1
- package/dist/agent/subagent-registry.js +28 -1
- package/dist/agent/system-prompt.d.ts +3 -1
- package/dist/agent/system-prompt.js +3 -0
- package/dist/agent/tool-runner.d.ts +2 -1
- package/dist/agent/tool-runner.js +5 -4
- package/dist/agent/types-w6.d.ts +39 -0
- package/dist/agent/types-w6.js +4 -0
- package/dist/agent/types.d.ts +5 -2
- package/dist/agents/external.js +1 -1
- package/dist/agents/task-record.d.ts +74 -1
- package/dist/agents/task-record.js +100 -0
- package/dist/ai/apis/cache-params.js +2 -1
- package/dist/ai/apis/chatgpt-backend.d.ts +52 -0
- package/dist/ai/apis/chatgpt-backend.js +224 -0
- package/dist/ai/apis/chatgpt-rate-limits.d.ts +26 -0
- package/dist/ai/apis/chatgpt-rate-limits.js +91 -0
- package/dist/ai/apis/openai-responses-request.d.ts +2 -1
- package/dist/ai/apis/openai-responses-request.js +8 -2
- package/dist/ai/apis/openai-responses.d.ts +2 -0
- package/dist/ai/apis/openai-responses.js +51 -16
- package/dist/ai/overflow.d.ts +1 -1
- package/dist/ai/overflow.js +10 -7
- package/dist/ai/providers/auth.d.ts +15 -2
- package/dist/ai/providers/auth.js +69 -2
- package/dist/ai/providers/builtin.js +27 -0
- package/dist/ai/providers/catalog-data.js +1 -0
- package/dist/ai/providers/discovered-cache.d.ts +48 -0
- package/dist/ai/providers/discovered-cache.js +102 -0
- package/dist/ai/providers/enrich.js +2 -7
- package/dist/ai/providers/model-visibility.d.ts +33 -0
- package/dist/ai/providers/model-visibility.js +70 -0
- package/dist/ai/providers/models-dev-cache.js +15 -19
- package/dist/ai/providers/models-dev-snapshot.js +8 -7
- package/dist/ai/providers/models-dev.js +5 -15
- package/dist/ai/providers/registry.d.ts +2 -0
- package/dist/ai/providers/registry.js +6 -1
- package/dist/ai/providers/suggest.js +2 -16
- package/dist/ai/types.d.ts +27 -1
- package/dist/auth/chatgpt/backend-client.d.ts +26 -0
- package/dist/auth/chatgpt/backend-client.js +74 -0
- package/dist/auth/chatgpt/claims.d.ts +17 -0
- package/dist/auth/chatgpt/claims.js +46 -0
- package/dist/auth/chatgpt/cli.d.ts +35 -0
- package/dist/auth/chatgpt/cli.js +279 -0
- package/dist/auth/chatgpt/doctor.d.ts +17 -0
- package/dist/auth/chatgpt/doctor.js +36 -0
- package/dist/auth/chatgpt/host-id.d.ts +7 -0
- package/dist/auth/chatgpt/host-id.js +26 -0
- package/dist/auth/chatgpt/login.d.ts +30 -0
- package/dist/auth/chatgpt/login.js +130 -0
- package/dist/auth/chatgpt/presets.d.ts +66 -0
- package/dist/auth/chatgpt/presets.js +120 -0
- package/dist/auth/chatgpt/quota-text.d.ts +13 -0
- package/dist/auth/chatgpt/quota-text.js +36 -0
- package/dist/auth/oauth/browser.d.ts +12 -0
- package/dist/auth/oauth/browser.js +27 -0
- package/dist/auth/oauth/callback-server.d.ts +47 -0
- package/dist/auth/oauth/callback-server.js +147 -0
- package/dist/auth/oauth/flows.d.ts +62 -0
- package/dist/auth/oauth/flows.js +113 -0
- package/dist/auth/oauth/jwt.d.ts +24 -0
- package/dist/auth/oauth/jwt.js +81 -0
- package/dist/auth/oauth/live.d.ts +21 -0
- package/dist/auth/oauth/live.js +25 -0
- package/dist/auth/oauth/oidc.d.ts +26 -0
- package/dist/auth/oauth/oidc.js +72 -0
- package/dist/auth/oauth/pkce.d.ts +15 -0
- package/dist/auth/oauth/pkce.js +20 -0
- package/dist/auth/oauth/refresh.d.ts +35 -0
- package/dist/auth/oauth/refresh.js +129 -0
- package/dist/auth/oauth/token-client.d.ts +33 -0
- package/dist/auth/oauth/token-client.js +121 -0
- package/dist/auth/oauth/token-store.d.ts +23 -0
- package/dist/auth/oauth/token-store.js +125 -0
- package/dist/auth/testing/fake-oauth.d.ts +73 -0
- package/dist/auth/testing/fake-oauth.js +271 -0
- package/dist/auth/testing/refresh-child.d.ts +5 -0
- package/dist/auth/testing/refresh-child.js +16 -0
- package/dist/bundle/ama.cjs +26532 -11045
- package/dist/checkpoints/backend.js +6 -5
- package/dist/checkpoints/restore.js +3 -2
- package/dist/checkpoints/settings.js +2 -1
- package/dist/checkpoints/shadow-git.js +7 -6
- package/dist/checkpoints/shadow-restore.js +3 -2
- package/dist/checkpoints/tracker.js +4 -3
- package/dist/cli/args.d.ts +9 -2
- package/dist/cli/args.js +74 -27
- package/dist/cli/bootstrap.js +53 -31
- package/dist/cli/choice-prompt.js +8 -6
- package/dist/cli/codemode-notice.js +2 -2
- package/dist/cli/compose-agents.js +2 -1
- package/dist/cli/compose-extensions.js +2 -0
- package/dist/cli/compose-memory.d.ts +53 -0
- package/dist/cli/compose-memory.js +127 -0
- package/dist/cli/compose-providers.d.ts +6 -0
- package/dist/cli/compose-providers.js +38 -2
- package/dist/cli/compose-session.d.ts +5 -0
- package/dist/cli/compose-session.js +27 -13
- package/dist/cli/compose-store.d.ts +2 -0
- package/dist/cli/compose-store.js +9 -5
- package/dist/cli/compose.d.ts +2 -0
- package/dist/cli/compose.js +13 -5
- package/dist/cli/default-model.d.ts +0 -2
- package/dist/cli/default-model.js +5 -8
- package/dist/cli/deps.d.ts +5 -1
- package/dist/cli/exit-codes.d.ts +1 -1
- package/dist/cli/exit-codes.js +7 -16
- package/dist/cli/from-prompt.js +3 -2
- package/dist/cli/help-text.d.ts +2 -1
- package/dist/cli/help-text.js +5 -99
- package/dist/cli/main.d.ts +5 -0
- package/dist/cli/main.js +21 -2
- package/dist/cli/proxy.js +14 -9
- package/dist/cli/runtime.d.ts +5 -0
- package/dist/cli/startup-screen.js +20 -27
- package/dist/cli/startup-steps.js +6 -8
- package/dist/cli/subcommands/auth.d.ts +6 -3
- package/dist/cli/subcommands/auth.js +52 -22
- package/dist/cli/subcommands/config-set.d.ts +21 -0
- package/dist/cli/subcommands/config-set.js +145 -0
- package/dist/cli/subcommands/config.d.ts +2 -1
- package/dist/cli/subcommands/config.js +51 -37
- package/dist/cli/subcommands/doctor.d.ts +2 -1
- package/dist/cli/subcommands/doctor.js +97 -58
- package/dist/cli/subcommands/init.d.ts +1 -1
- package/dist/cli/subcommands/init.js +8 -7
- package/dist/cli/subcommands/memory.d.ts +18 -0
- package/dist/cli/subcommands/memory.js +189 -0
- package/dist/cli/subcommands/model-meta.js +11 -9
- package/dist/cli/subcommands/models-cache-probe.js +23 -20
- package/dist/cli/subcommands/models-discover.d.ts +4 -0
- package/dist/cli/subcommands/models-discover.js +60 -21
- package/dist/cli/subcommands/models-enable.d.ts +13 -0
- package/dist/cli/subcommands/models-enable.js +145 -0
- package/dist/cli/subcommands/models.d.ts +3 -1
- package/dist/cli/subcommands/models.js +39 -24
- package/dist/cli/subcommands/probe-runner.js +8 -7
- package/dist/cli/subcommands/providers-list.js +32 -21
- package/dist/cli/subcommands/providers-plan.js +24 -25
- package/dist/cli/subcommands/providers-probe.js +5 -6
- package/dist/cli/subcommands/providers.d.ts +1 -1
- package/dist/cli/subcommands/providers.js +45 -50
- package/dist/cli/subcommands/sessions-export.d.ts +1 -1
- package/dist/cli/subcommands/sessions-export.js +10 -9
- package/dist/cli/subcommands/sessions-search.d.ts +1 -1
- package/dist/cli/subcommands/sessions-search.js +11 -10
- package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
- package/dist/cli/subcommands/sessions-trace.js +156 -0
- package/dist/cli/subcommands/sessions.d.ts +4 -3
- package/dist/cli/subcommands/sessions.js +40 -37
- package/dist/cli/subcommands/stats.d.ts +1 -1
- package/dist/cli/subcommands/stats.js +49 -30
- package/dist/cli/system-prompt-arg.js +3 -2
- package/dist/codemode/capability.js +3 -2
- package/dist/compaction/post-compact.d.ts +1 -0
- package/dist/compaction/post-compact.js +15 -1
- package/dist/compaction/prune-tier.d.ts +1 -1
- package/dist/compaction/prune-tier.js +3 -3
- package/dist/compaction/serialize.js +2 -1
- package/dist/config/auth-file.d.ts +12 -2
- package/dist/config/auth-file.js +32 -10
- package/dist/config/checker.js +12 -11
- package/dist/config/context-files.js +3 -2
- package/dist/config/edit.d.ts +106 -0
- package/dist/config/edit.js +350 -0
- package/dist/config/init.d.ts +4 -3
- package/dist/config/init.js +10 -18
- package/dist/config/json-schema.d.ts +2 -1
- package/dist/config/json-schema.js +102 -69
- package/dist/config/key-docs.d.ts +18 -7
- package/dist/config/key-docs.js +43 -128
- package/dist/config/load.js +7 -6
- package/dist/config/merge.d.ts +4 -1
- package/dist/config/merge.js +42 -22
- package/dist/config/paths.js +6 -5
- package/dist/config/profile.d.ts +5 -1
- package/dist/config/profile.js +7 -2
- package/dist/config/schema-w5.js +12 -4
- package/dist/config/schema-w6.d.ts +19 -0
- package/dist/config/schema-w6.js +115 -0
- package/dist/config/schema.js +34 -20
- package/dist/config/settings-registry.d.ts +81 -0
- package/dist/config/settings-registry.js +185 -0
- package/dist/config/types-w5.d.ts +7 -0
- package/dist/config/types-w5.js +2 -0
- package/dist/config/types-w6.d.ts +109 -0
- package/dist/config/types-w6.js +19 -0
- package/dist/config/types.d.ts +11 -8
- package/dist/config/types.js +1 -0
- package/dist/drivers/acp/client.js +1 -1
- package/dist/drivers/acp/driver.js +13 -8
- package/dist/drivers/agents.js +4 -3
- package/dist/drivers/base.js +3 -2
- package/dist/drivers/host-runners.js +2 -1
- package/dist/drivers/native/claude-stream.js +12 -11
- package/dist/drivers/native/codex-app-server.js +17 -12
- package/dist/drivers/native/oneshot.js +8 -7
- package/dist/drivers/pool.js +1 -1
- package/dist/drivers/runner.d.ts +3 -1
- package/dist/drivers/runner.js +68 -20
- package/dist/drivers/turn.js +1 -1
- package/dist/hooks/config.js +3 -2
- package/dist/hooks/protocol.js +18 -12
- package/dist/host/api-impl.js +11 -10
- package/dist/host/loader.js +9 -8
- package/dist/host/types.d.ts +3 -0
- package/dist/i18n/catalog.d.ts +2209 -0
- package/dist/i18n/catalog.js +72 -0
- package/dist/i18n/format.d.ts +21 -0
- package/dist/i18n/format.js +58 -0
- package/dist/i18n/index.d.ts +58 -0
- package/dist/i18n/index.js +72 -0
- package/dist/i18n/messages/agents.d.ts +84 -0
- package/dist/i18n/messages/agents.js +85 -0
- package/dist/i18n/messages/approval.d.ts +99 -0
- package/dist/i18n/messages/approval.js +100 -0
- package/dist/i18n/messages/auth.d.ts +189 -0
- package/dist/i18n/messages/auth.js +201 -0
- package/dist/i18n/messages/cli-args.d.ts +46 -0
- package/dist/i18n/messages/cli-args.js +46 -0
- package/dist/i18n/messages/cli-help.d.ts +12 -0
- package/dist/i18n/messages/cli-help.js +248 -0
- package/dist/i18n/messages/cli.d.ts +336 -0
- package/dist/i18n/messages/cli.js +311 -0
- package/dist/i18n/messages/config-keys.d.ts +293 -0
- package/dist/i18n/messages/config-keys.js +296 -0
- package/dist/i18n/messages/config.d.ts +508 -0
- package/dist/i18n/messages/config.js +241 -0
- package/dist/i18n/messages/drivers.d.ts +123 -0
- package/dist/i18n/messages/drivers.js +124 -0
- package/dist/i18n/messages/errors.d.ts +83 -0
- package/dist/i18n/messages/errors.js +171 -0
- package/dist/i18n/messages/interactive-line.d.ts +61 -0
- package/dist/i18n/messages/interactive-line.js +69 -0
- package/dist/i18n/messages/interactive-startup.d.ts +99 -0
- package/dist/i18n/messages/interactive-startup.js +100 -0
- package/dist/i18n/messages/interactive-view.d.ts +140 -0
- package/dist/i18n/messages/interactive-view.js +141 -0
- package/dist/i18n/messages/interactive.d.ts +489 -0
- package/dist/i18n/messages/interactive.js +248 -0
- package/dist/i18n/messages/memory.d.ts +123 -0
- package/dist/i18n/messages/memory.js +128 -0
- package/dist/i18n/messages/panels.d.ts +233 -0
- package/dist/i18n/messages/panels.js +232 -0
- package/dist/i18n/messages/permissions.d.ts +126 -0
- package/dist/i18n/messages/permissions.js +151 -0
- package/dist/i18n/messages/plan.d.ts +123 -0
- package/dist/i18n/messages/plan.js +124 -0
- package/dist/i18n/messages/print.d.ts +86 -0
- package/dist/i18n/messages/print.js +91 -0
- package/dist/i18n/messages/report.d.ts +391 -0
- package/dist/i18n/messages/report.js +490 -0
- package/dist/i18n/messages/rewind.d.ts +198 -0
- package/dist/i18n/messages/rewind.js +217 -0
- package/dist/i18n/messages/session.d.ts +230 -0
- package/dist/i18n/messages/session.js +258 -0
- package/dist/i18n/messages/settings.d.ts +355 -0
- package/dist/i18n/messages/settings.js +343 -0
- package/dist/i18n/messages/subcommands-config.d.ts +113 -0
- package/dist/i18n/messages/subcommands-config.js +129 -0
- package/dist/i18n/messages/subcommands-models.d.ts +34 -0
- package/dist/i18n/messages/subcommands-models.js +34 -0
- package/dist/i18n/messages/subcommands.d.ts +576 -0
- package/dist/i18n/messages/subcommands.js +477 -0
- package/dist/i18n/messages/trace.d.ts +243 -0
- package/dist/i18n/messages/trace.js +238 -0
- package/dist/i18n/types.d.ts +15 -0
- package/dist/i18n/types.js +7 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -0
- package/dist/memory/edit.d.ts +24 -0
- package/dist/memory/edit.js +63 -0
- package/dist/memory/frontmatter.d.ts +37 -0
- package/dist/memory/frontmatter.js +79 -0
- package/dist/memory/index.d.ts +28 -0
- package/dist/memory/index.js +126 -0
- package/dist/memory/lock.d.ts +17 -0
- package/dist/memory/lock.js +62 -0
- package/dist/memory/paths.d.ts +57 -0
- package/dist/memory/paths.js +175 -0
- package/dist/memory/report.d.ts +36 -0
- package/dist/memory/report.js +86 -0
- package/dist/memory/runtime.d.ts +42 -0
- package/dist/memory/runtime.js +36 -0
- package/dist/memory/secrets.d.ts +8 -0
- package/dist/memory/secrets.js +27 -0
- package/dist/memory/section.d.ts +28 -0
- package/dist/memory/section.js +59 -0
- package/dist/memory/store.d.ts +70 -0
- package/dist/memory/store.js +284 -0
- package/dist/memory/tool.d.ts +31 -0
- package/dist/memory/tool.js +94 -0
- package/dist/modes/acp/acp-events.js +2 -1
- package/dist/modes/acp/acp-server.js +13 -12
- package/dist/modes/commands-core.d.ts +11 -0
- package/dist/modes/commands-core.js +93 -62
- package/dist/modes/image-input.js +20 -6
- package/dist/modes/interactive/agent-bar.d.ts +95 -0
- package/dist/modes/interactive/agent-bar.js +248 -0
- package/dist/modes/interactive/agent-panels.js +27 -26
- package/dist/modes/interactive/agent-transcript.d.ts +47 -0
- package/dist/modes/interactive/agent-transcript.js +191 -0
- package/dist/modes/interactive/agent-ui.d.ts +36 -1
- package/dist/modes/interactive/agent-ui.js +180 -14
- package/dist/modes/interactive/agent-view.d.ts +72 -0
- package/dist/modes/interactive/agent-view.js +281 -0
- package/dist/modes/interactive/approval-dialog.js +46 -34
- package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
- package/dist/modes/interactive/clipboard-paste.js +9 -4
- package/dist/modes/interactive/commands.d.ts +22 -1
- package/dist/modes/interactive/commands.js +100 -49
- package/dist/modes/interactive/completion.js +2 -1
- package/dist/modes/interactive/config-panel.d.ts +70 -0
- package/dist/modes/interactive/config-panel.js +319 -0
- package/dist/modes/interactive/config-ui.d.ts +96 -0
- package/dist/modes/interactive/config-ui.js +397 -0
- package/dist/modes/interactive/confirm-dialog.js +6 -7
- package/dist/modes/interactive/event-notices.js +11 -9
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.js +21 -22
- package/dist/modes/interactive/key-dispatch.d.ts +12 -0
- package/dist/modes/interactive/key-dispatch.js +24 -9
- package/dist/modes/interactive/line/line-editor.js +2 -1
- package/dist/modes/interactive/line/line-mode.js +18 -7
- package/dist/modes/interactive/line/line-render.js +25 -24
- package/dist/modes/interactive/memory-panel.d.ts +64 -0
- package/dist/modes/interactive/memory-panel.js +221 -0
- package/dist/modes/interactive/message-view.d.ts +4 -2
- package/dist/modes/interactive/message-view.js +42 -33
- package/dist/modes/interactive/model-items.d.ts +45 -0
- package/dist/modes/interactive/model-items.js +134 -0
- package/dist/modes/interactive/model-picker.d.ts +57 -0
- package/dist/modes/interactive/model-picker.js +191 -0
- package/dist/modes/interactive/panels.js +39 -31
- package/dist/modes/interactive/pickers.d.ts +2 -1
- package/dist/modes/interactive/pickers.js +10 -6
- package/dist/modes/interactive/plan-command.d.ts +1 -1
- package/dist/modes/interactive/plan-command.js +24 -27
- package/dist/modes/interactive/plan-dialog.js +18 -17
- package/dist/modes/interactive/plan-flow.js +6 -5
- package/dist/modes/interactive/rewind-command.d.ts +1 -1
- package/dist/modes/interactive/rewind-command.js +18 -16
- package/dist/modes/interactive/rewind-flow.d.ts +0 -1
- package/dist/modes/interactive/rewind-flow.js +13 -14
- package/dist/modes/interactive/rewind-list.js +7 -6
- package/dist/modes/interactive/rewind-panel.js +40 -40
- package/dist/modes/interactive/rewind-text.d.ts +5 -3
- package/dist/modes/interactive/rewind-text.js +48 -38
- package/dist/modes/interactive/run-indicator.js +15 -12
- package/dist/modes/interactive/session-events.js +3 -2
- package/dist/modes/interactive/startup-header.js +22 -23
- package/dist/modes/interactive/startup-ui.d.ts +3 -9
- package/dist/modes/interactive/startup-ui.js +44 -88
- package/dist/modes/interactive/status-area.d.ts +2 -0
- package/dist/modes/interactive/status-area.js +8 -2
- package/dist/modes/interactive/status-bar.js +4 -3
- package/dist/modes/interactive/subagent-view.js +9 -7
- package/dist/modes/interactive/tasks-report.d.ts +6 -0
- package/dist/modes/interactive/tasks-report.js +28 -31
- package/dist/modes/interactive/terminal-setup.d.ts +9 -0
- package/dist/modes/interactive/terminal-setup.js +23 -0
- package/dist/modes/interactive/tool-summary.js +19 -17
- package/dist/modes/interactive/tool-view.js +7 -4
- package/dist/modes/interactive/trace-view.d.ts +89 -0
- package/dist/modes/interactive/trace-view.js +332 -0
- package/dist/modes/print/print-mode.js +14 -15
- package/dist/modes/rpc/commands.js +7 -3
- package/dist/modes/rpc/rpc-mode.js +9 -3
- package/dist/modes/session-report.d.ts +2 -0
- package/dist/modes/session-report.js +101 -105
- package/dist/modes/startup-ui-text.js +11 -6
- package/dist/permissions/bypass.d.ts +8 -10
- package/dist/permissions/bypass.js +19 -10
- package/dist/permissions/memory-class.d.ts +23 -0
- package/dist/permissions/memory-class.js +54 -0
- package/dist/permissions/modes.d.ts +3 -3
- package/dist/permissions/modes.js +21 -16
- package/dist/permissions/pipeline.d.ts +1 -1
- package/dist/permissions/pipeline.js +9 -2
- package/dist/permissions/preview.js +49 -42
- package/dist/permissions/rules.js +5 -2
- package/dist/permissions/types.d.ts +4 -0
- package/dist/plan/store.js +2 -1
- package/dist/rpc.d.ts +39 -1
- package/dist/rpc.js +3 -0
- package/dist/sandbox/bash.js +11 -8
- package/dist/sandbox/detect.js +14 -11
- package/dist/sdk.d.ts +17 -1
- package/dist/sdk.js +29 -7
- package/dist/session/export.js +31 -30
- package/dist/session/manager.d.ts +1 -1
- package/dist/session/manager.js +5 -3
- package/dist/session/reuse.js +5 -4
- package/dist/session/scan.js +3 -2
- package/dist/session/stats-aggregate.d.ts +3 -1
- package/dist/session/stats-aggregate.js +5 -1
- package/dist/session/stats-index.js +2 -1
- package/dist/session/stats-scan.d.ts +4 -1
- package/dist/session/stats-scan.js +6 -2
- package/dist/session/store.d.ts +11 -0
- package/dist/session/store.js +48 -1
- package/dist/session/types.d.ts +2 -0
- package/dist/skills/builtin.js +2 -1
- package/dist/tools/image-file.d.ts +26 -1
- package/dist/tools/image-file.js +55 -13
- package/dist/tools/presets.d.ts +14 -1
- package/dist/tools/presets.js +3 -3
- package/dist/tools/registry.js +1 -1
- package/dist/tools/truncate.d.ts +1 -1
- package/dist/tools/truncate.js +2 -2
- package/dist/tools/types.d.ts +17 -1
- package/dist/trace/build-index.d.ts +91 -0
- package/dist/trace/build-index.js +127 -0
- package/dist/trace/build-nodes.d.ts +24 -0
- package/dist/trace/build-nodes.js +279 -0
- package/dist/trace/build-util.d.ts +43 -0
- package/dist/trace/build-util.js +120 -0
- package/dist/trace/build.d.ts +82 -0
- package/dist/trace/build.js +382 -0
- package/dist/trace/detail.d.ts +35 -0
- package/dist/trace/detail.js +205 -0
- package/dist/trace/flatten.d.ts +69 -0
- package/dist/trace/flatten.js +173 -0
- package/dist/trace/format.d.ts +47 -0
- package/dist/trace/format.js +329 -0
- package/dist/trace/html-template.d.ts +19 -0
- package/dist/trace/html-template.js +150 -0
- package/dist/trace/html.d.ts +104 -0
- package/dist/trace/html.js +292 -0
- package/dist/trace/preview.d.ts +29 -0
- package/dist/trace/preview.js +59 -0
- package/dist/trace/query-session.d.ts +14 -0
- package/dist/trace/query-session.js +38 -0
- package/dist/trace/query.d.ts +55 -0
- package/dist/trace/query.js +188 -0
- package/dist/trace/session.d.ts +40 -0
- package/dist/trace/session.js +168 -0
- package/dist/trace/types.d.ts +243 -0
- package/dist/trace/types.js +13 -0
- package/dist/tui/components/editor-paste.d.ts +2 -0
- package/dist/tui/components/editor-paste.js +6 -3
- package/dist/tui/components/editor.js +2 -2
- package/dist/tui/components/loader.d.ts +3 -0
- package/dist/tui/components/loader.js +14 -0
- package/dist/tui/components/select-list.d.ts +2 -0
- package/dist/tui/components/select-list.js +7 -0
- package/dist/tui/components/settings-list.d.ts +61 -0
- package/dist/tui/components/settings-list.js +135 -0
- package/dist/tui/keybindings.d.ts +5 -0
- package/dist/tui/keybindings.js +17 -5
- package/dist/tui.d.ts +1 -0
- package/dist/tui.js +2 -0
- package/docs/en/host-api.md +167 -0
- package/docs/en/permissions.md +214 -0
- package/docs/en/providers.md +627 -0
- package/docs/en/rpc.md +361 -0
- package/docs/en/sessions.md +219 -0
- package/docs/en/tui.md +534 -0
- package/docs/host-api.md +18 -17
- package/docs/memory.md +172 -0
- package/docs/permissions.md +2 -2
- package/docs/providers.md +73 -1
- package/docs/rpc.md +31 -3
- package/docs/session-format.md +8 -2
- package/docs/sessions.md +29 -1
- package/docs/tui.md +140 -4
- package/package.json +8 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互模式装配用到的两个小工具(从 interactive-mode.ts 拆出,控制单文件行数):真实终端与 keybindings.json。
|
|
3
|
+
*/
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { KEYBINDINGS_FILE } from "../../config/paths.js";
|
|
6
|
+
import { AmaError } from "../../errors.js";
|
|
7
|
+
import { msg } from "../../i18n/index.js";
|
|
8
|
+
import { Keybindings, ProcessTerminal, loadKeybindingsFile } from "../../tui.js";
|
|
9
|
+
/** stdin / stdout 都是 TTY 才用真实终端;否则抛 `terminal_init_failed`(调用方降级到行式界面)。 */
|
|
10
|
+
export function processTerminal() {
|
|
11
|
+
const stdin = process.stdin;
|
|
12
|
+
if (stdin.isTTY !== true || typeof stdin.setRawMode !== "function" || !process.stdout.isTTY) {
|
|
13
|
+
throw new AmaError("terminal_init_failed", msg().interactive.app.notTty);
|
|
14
|
+
}
|
|
15
|
+
return new ProcessTerminal();
|
|
16
|
+
}
|
|
17
|
+
/** 读 `<configDir>/keybindings.json`;问题逐条交给 `warn`。 */
|
|
18
|
+
export function loadKeys(runtime, warn) {
|
|
19
|
+
const parsed = loadKeybindingsFile(join(runtime.paths.configDir, KEYBINDINGS_FILE));
|
|
20
|
+
for (const w of parsed.warnings)
|
|
21
|
+
warn(msg().interactive.app.keybindingsWarning(w));
|
|
22
|
+
return new Keybindings(parsed.overrides);
|
|
23
|
+
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* - grep `N 处匹配 · M 个文件`;glob `N 个文件`;codemode `N 个内层调用 · 脚本输出 M 行`;
|
|
9
9
|
* - task `完成 · 耗时 · ↑in ↓out`;其它 `N 行输出`;失败(非 bash)取错误首行。
|
|
10
10
|
*/
|
|
11
|
+
import { msg } from "../../i18n/index.js";
|
|
11
12
|
import { isAbsolute, relative } from "node:path";
|
|
12
13
|
import { stripAnsi } from "../../tui.js";
|
|
13
14
|
import { formatTokens } from "./status-bar.js";
|
|
@@ -135,6 +136,7 @@ export function bashOutput(result) {
|
|
|
135
136
|
/** 完成后的一行结果摘要(已着色,不含 `⎿`)。 */
|
|
136
137
|
export function resultSummary(input, theme) {
|
|
137
138
|
const { name, result, isError, lines } = input;
|
|
139
|
+
const m = msg().interactive.view.tool;
|
|
138
140
|
const details = record(result.details);
|
|
139
141
|
const muted = (s) => theme.fg("muted", s);
|
|
140
142
|
const sep = theme.fg("dim", " · ");
|
|
@@ -146,27 +148,27 @@ export function resultSummary(input, theme) {
|
|
|
146
148
|
const code = num(details["exit_code"]) ?? (isError ? 1 : 0);
|
|
147
149
|
const total = num(details["totalLines"]) ?? count;
|
|
148
150
|
const head = details["aborted"] === true
|
|
149
|
-
?
|
|
151
|
+
? m.interrupted
|
|
150
152
|
: details["timedOut"] === true
|
|
151
|
-
?
|
|
152
|
-
:
|
|
153
|
-
const parts = [head, duration, ...(total > 0 ? [
|
|
153
|
+
? m.timedOut
|
|
154
|
+
: m.exit(code);
|
|
155
|
+
const parts = [head, duration, ...(total > 0 ? [m.lines(total)] : [])];
|
|
154
156
|
const text = parts.join(" · ");
|
|
155
157
|
return isError || code !== 0 ? theme.fg("error", text) : parts.map(muted).join(sep);
|
|
156
158
|
}
|
|
157
159
|
if (isError)
|
|
158
|
-
return theme.fg("error", `${theme.glyphs.fail} ${lines[0] ??
|
|
160
|
+
return theme.fg("error", `${theme.glyphs.fail} ${lines[0] ?? m.failed}`);
|
|
159
161
|
switch (name) {
|
|
160
162
|
case "read": {
|
|
161
163
|
const mime = details["mimeType"];
|
|
162
164
|
if (typeof mime === "string")
|
|
163
|
-
return muted(
|
|
165
|
+
return muted(m.image(mime));
|
|
164
166
|
const first = num(details["firstLine"]);
|
|
165
167
|
const last = num(details["lastLine"]);
|
|
166
168
|
if (num(details["totalLines"]) === 0)
|
|
167
|
-
return muted(
|
|
169
|
+
return muted(m.emptyFile);
|
|
168
170
|
const n = first !== undefined && last !== undefined ? last - first + 1 : count;
|
|
169
|
-
return muted(
|
|
171
|
+
return muted(m.read(n));
|
|
170
172
|
}
|
|
171
173
|
case "edit": {
|
|
172
174
|
const rows = parseDiff(diffOf(result) ?? "");
|
|
@@ -174,7 +176,7 @@ export function resultSummary(input, theme) {
|
|
|
174
176
|
const del = rows.filter((r) => r.kind === "del").length;
|
|
175
177
|
const edits = record(input.args)["edits"];
|
|
176
178
|
const n = num(details["replacements"]) ?? (Array.isArray(edits) ? edits.length : 1);
|
|
177
|
-
return (muted(
|
|
179
|
+
return (muted(m.edits(n)) +
|
|
178
180
|
sep +
|
|
179
181
|
theme.fg("success", `+${add}`) +
|
|
180
182
|
" " +
|
|
@@ -183,23 +185,23 @@ export function resultSummary(input, theme) {
|
|
|
183
185
|
case "write": {
|
|
184
186
|
const content = record(input.args)["content"];
|
|
185
187
|
const n = typeof content === "string" ? cleanLines(content).length : 0;
|
|
186
|
-
return muted(
|
|
188
|
+
return muted(m.write(details["created"] === true, n));
|
|
187
189
|
}
|
|
188
190
|
case "grep": {
|
|
189
191
|
const matches = num(details["matches"]);
|
|
190
192
|
if (matches === 0)
|
|
191
|
-
return muted(
|
|
193
|
+
return muted(m.noMatch);
|
|
192
194
|
if (matches === undefined)
|
|
193
|
-
return muted(
|
|
194
|
-
return muted(
|
|
195
|
+
return muted(m.lines(count));
|
|
196
|
+
return muted(m.matches(matches, num(details["files"])));
|
|
195
197
|
}
|
|
196
198
|
case "glob": {
|
|
197
199
|
const n = num(details["count"]);
|
|
198
|
-
return muted(n === 0 ?
|
|
200
|
+
return muted(n === 0 ? m.noMatch : m.files(n ?? count));
|
|
199
201
|
}
|
|
200
202
|
case "codemode": {
|
|
201
203
|
const calls = num(details["toolCalls"]) ?? input.nestedCount ?? 0;
|
|
202
|
-
return muted(
|
|
204
|
+
return muted(m.codemode(calls, count));
|
|
203
205
|
}
|
|
204
206
|
case "task": {
|
|
205
207
|
const usage = record(details["usage"]);
|
|
@@ -210,9 +212,9 @@ export function resultSummary(input, theme) {
|
|
|
210
212
|
`${theme.glyphs.arrowUp}${formatTokens(input_)} ${theme.glyphs.arrowDown}${formatTokens(output)}`,
|
|
211
213
|
]
|
|
212
214
|
: [];
|
|
213
|
-
return muted([
|
|
215
|
+
return muted([m.done, duration, ...tokens].join(" · "));
|
|
214
216
|
}
|
|
215
217
|
default:
|
|
216
|
-
return muted(count === 0 ?
|
|
218
|
+
return muted(count === 0 ? m.done : m.outputLines(count));
|
|
217
219
|
}
|
|
218
220
|
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* - 自定义渲染(`ToolDefinition.renderCall / renderResult`):标题摘要优先取 `renderCall` 第一行;成功的结果
|
|
21
21
|
* 正文优先用 `renderResult`;抛错或返回空时回到缺省显示;错误结果始终用缺省显示。
|
|
22
22
|
*/
|
|
23
|
+
import { msg } from "../../i18n/index.js";
|
|
23
24
|
import { formatElapsed, truncateToWidth, wrapTextWithAnsi, } from "../../tui.js";
|
|
24
25
|
import { contentText } from "./message-view.js";
|
|
25
26
|
import { subagentLine } from "./subagent-view.js";
|
|
@@ -159,7 +160,7 @@ export class ToolView {
|
|
|
159
160
|
const g = theme.glyphs;
|
|
160
161
|
const lead = " " + theme.fg("border", g.result) + " ";
|
|
161
162
|
if (this.state === "running" && this.awaiting) {
|
|
162
|
-
return truncateToWidth(lead + theme.fg("dim",
|
|
163
|
+
return truncateToWidth(lead + theme.fg("dim", msg().interactive.view.tool.awaiting(g.spinnerStatic)), width);
|
|
163
164
|
}
|
|
164
165
|
const sub = this.subagentState();
|
|
165
166
|
if (this.state === "running" && sub !== undefined) {
|
|
@@ -170,7 +171,8 @@ export class ToolView {
|
|
|
170
171
|
if (this.state === "running") {
|
|
171
172
|
const frame = this.options.spinner?.() ?? g.spinnerStatic;
|
|
172
173
|
const elapsed = formatElapsed(this.now() - this.startedAt);
|
|
173
|
-
const
|
|
174
|
+
const m = msg().interactive.view.tool;
|
|
175
|
+
const what = this.toolName === "task" ? m.subagentRunning(elapsed) : m.running(elapsed);
|
|
174
176
|
return truncateToWidth(lead + theme.fg("accent", frame) + " " + theme.fg("muted", what), width);
|
|
175
177
|
}
|
|
176
178
|
const result = this.result;
|
|
@@ -251,7 +253,7 @@ export class ToolView {
|
|
|
251
253
|
}
|
|
252
254
|
more(hidden) {
|
|
253
255
|
const { theme } = this.options;
|
|
254
|
-
return BODY + theme.fg("dim",
|
|
256
|
+
return (BODY + theme.fg("dim", msg().interactive.view.tool.moreLines(theme.glyphs.ellipsis, hidden)));
|
|
255
257
|
}
|
|
256
258
|
nestedLines(width) {
|
|
257
259
|
const { theme } = this.options;
|
|
@@ -269,7 +271,8 @@ export class ToolView {
|
|
|
269
271
|
const shown = this.nested.slice(-COLLAPSED_CHILDREN);
|
|
270
272
|
if (this.nested.length > shown.length) {
|
|
271
273
|
const hidden = this.nested.length - shown.length;
|
|
272
|
-
out.push(BODY +
|
|
274
|
+
out.push(BODY +
|
|
275
|
+
theme.fg("dim", msg().interactive.view.tool.earlierCalls(theme.glyphs.ellipsis, hidden)));
|
|
273
276
|
}
|
|
274
277
|
for (const child of shown) {
|
|
275
278
|
out.push(BODY + child.header(inner));
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/trace` 覆盖层(docs/wave6-plan.md §2.4)。[W6-T1]
|
|
3
|
+
*
|
|
4
|
+
* - `/trace`(当前会话)、`/trace t2`(以任务 t2 为根:ama 子会话的子轨迹,或外部 Agent 骨架)。
|
|
5
|
+
* - 主屏约束下的覆盖层:`anchor: "bottom"`、高度 `rows − 1`(同 rewind 面板);退出撤掉覆盖层,消息区不变。
|
|
6
|
+
* - 布局:标题汇总一行 + 列表窗口 + 按键提示一行;只格式化可见窗口里的行(10k 节点也只算可见行)。
|
|
7
|
+
* - 键:↑↓ / PgUp PgDn / Home End 移动;→ 展开(子 Agent 展开即懒加载子轨迹)或进第一个子行;← 折叠或回父行;
|
|
8
|
+
* Enter 详情卡片(再按或 Esc 返回);「更早的 N 个回合」行上 Enter / ↑ 加载前一页;f 跟随开关(进行中自动开,
|
|
9
|
+
* 手动上移暂停,End 恢复);Esc 先关详情再关视图。
|
|
10
|
+
* - 刷新:会话事件(`entry_appended` / `telemetry_tick` / 工具起止 / 请求起止)触发,节流 ≤ 2 Hz;每次整棵
|
|
11
|
+
* 重建(构建器是 O(条目) 的纯函数,10k 节点实测见 trace-view.test.ts),展开状态与光标按行 key 保留。
|
|
12
|
+
*/
|
|
13
|
+
import type { AgentSession } from "../../agent/types.js";
|
|
14
|
+
import { type Component, type Focusable, type Keybindings, type OverlayHandle, type Theme } from "../../tui.js";
|
|
15
|
+
import { type TraceRow } from "../../trace/flatten.js";
|
|
16
|
+
import { LiveTracker, type ChildLoader } from "../../trace/session.js";
|
|
17
|
+
import type { NoticeLevel } from "./message-view.js";
|
|
18
|
+
/** 尾部优先:首屏与每次向前翻页的回合数。 */
|
|
19
|
+
export declare const TRACE_PAGE_TURNS = 50;
|
|
20
|
+
/** 刷新节流(≤ 2 Hz)。 */
|
|
21
|
+
export declare const TRACE_REFRESH_MS = 500;
|
|
22
|
+
export interface TraceViewHost {
|
|
23
|
+
theme: Theme;
|
|
24
|
+
keybindings?: Keybindings;
|
|
25
|
+
showOverlay(component: Component, options: {
|
|
26
|
+
anchor: "bottom";
|
|
27
|
+
}): OverlayHandle;
|
|
28
|
+
rows(): number;
|
|
29
|
+
session(): AgentSession;
|
|
30
|
+
now(): number;
|
|
31
|
+
notice(level: NoticeLevel, text: string): void;
|
|
32
|
+
/** 请求重画(异步刷新后)。 */
|
|
33
|
+
render?(): void;
|
|
34
|
+
/** 子会话读取(测试注入);缺省只读读文件、按 mtime 缓存。 */
|
|
35
|
+
loadChild?: ChildLoader;
|
|
36
|
+
/** 刷新节流(测试用 0)。 */
|
|
37
|
+
refreshMs?: number;
|
|
38
|
+
}
|
|
39
|
+
export declare class TraceView implements Component, Focusable {
|
|
40
|
+
private readonly host;
|
|
41
|
+
private readonly taskId;
|
|
42
|
+
private readonly close;
|
|
43
|
+
focused: boolean;
|
|
44
|
+
private trace;
|
|
45
|
+
private root;
|
|
46
|
+
private rows;
|
|
47
|
+
private lookup;
|
|
48
|
+
private readonly expanded;
|
|
49
|
+
/** 已展开过的 ama 子 Agent(重建后重新挂子轨迹)。 */
|
|
50
|
+
private readonly loaded;
|
|
51
|
+
private fromTurn;
|
|
52
|
+
private cursor;
|
|
53
|
+
private top;
|
|
54
|
+
private follow;
|
|
55
|
+
private detail;
|
|
56
|
+
readonly live: LiveTracker;
|
|
57
|
+
private readonly loadChild;
|
|
58
|
+
constructor(host: TraceViewHost, taskId: string | undefined, close: () => void);
|
|
59
|
+
/** 任务存在(`/trace <id>`)或看主会话。 */
|
|
60
|
+
get found(): boolean;
|
|
61
|
+
private rowsKeyOfRoot;
|
|
62
|
+
/** 重建轨迹(会话条目 + live 叠加 + 已展开的子轨迹)。 */
|
|
63
|
+
rebuild(): void;
|
|
64
|
+
/** 重新摊平,光标按 key 保持;跟随时贴底。 */
|
|
65
|
+
private reflow;
|
|
66
|
+
/** 会话有变化:重建并重排。 */
|
|
67
|
+
refresh(): void;
|
|
68
|
+
/** 当前行数(测试用)。 */
|
|
69
|
+
get rowCount(): number;
|
|
70
|
+
get cursorIndex(): number;
|
|
71
|
+
get selected(): TraceRow | undefined;
|
|
72
|
+
get following(): boolean;
|
|
73
|
+
get detailOpen(): boolean;
|
|
74
|
+
private bodyHeight;
|
|
75
|
+
private move;
|
|
76
|
+
private loadEarlier;
|
|
77
|
+
private expand;
|
|
78
|
+
private collapse;
|
|
79
|
+
handleInput(data: string): void;
|
|
80
|
+
private detailInput;
|
|
81
|
+
private ctx;
|
|
82
|
+
private headerLine;
|
|
83
|
+
render(width: number): string[];
|
|
84
|
+
invalidate(): void;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 打开 `/trace` 覆盖层;关闭时 resolve。任务不存在时提示一行、不打开。
|
|
88
|
+
*/
|
|
89
|
+
export declare function openTraceView(host: TraceViewHost, taskId?: string): Promise<void>;
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/trace` 覆盖层(docs/wave6-plan.md §2.4)。[W6-T1]
|
|
3
|
+
*
|
|
4
|
+
* - `/trace`(当前会话)、`/trace t2`(以任务 t2 为根:ama 子会话的子轨迹,或外部 Agent 骨架)。
|
|
5
|
+
* - 主屏约束下的覆盖层:`anchor: "bottom"`、高度 `rows − 1`(同 rewind 面板);退出撤掉覆盖层,消息区不变。
|
|
6
|
+
* - 布局:标题汇总一行 + 列表窗口 + 按键提示一行;只格式化可见窗口里的行(10k 节点也只算可见行)。
|
|
7
|
+
* - 键:↑↓ / PgUp PgDn / Home End 移动;→ 展开(子 Agent 展开即懒加载子轨迹)或进第一个子行;← 折叠或回父行;
|
|
8
|
+
* Enter 详情卡片(再按或 Esc 返回);「更早的 N 个回合」行上 Enter / ↑ 加载前一页;f 跟随开关(进行中自动开,
|
|
9
|
+
* 手动上移暂停,End 恢复);Esc 先关详情再关视图。
|
|
10
|
+
* - 刷新:会话事件(`entry_appended` / `telemetry_tick` / 工具起止 / 请求起止)触发,节流 ≤ 2 Hz;每次整棵
|
|
11
|
+
* 重建(构建器是 O(条目) 的纯函数,10k 节点实测见 trace-view.test.ts),展开状态与光标按行 key 保留。
|
|
12
|
+
*/
|
|
13
|
+
import { msg } from "../../i18n/index.js";
|
|
14
|
+
import { defaultKeybindings, matchesKey, padToWidth, truncateToWidth, visibleWidth, } from "../../tui.js";
|
|
15
|
+
import { buildTrace, findSubagent, loadSubagentTrace } from "../../trace/build.js";
|
|
16
|
+
import { describeNode, detailLines, entryLookup, } from "../../trace/detail.js";
|
|
17
|
+
import { flattenNode, flattenTrace, needsChild, rowIndex, tailStart, } from "../../trace/flatten.js";
|
|
18
|
+
import { formatRow, rowLabel, summaryText } from "../../trace/format.js";
|
|
19
|
+
import { childLoader, LiveTracker, traceInputOf } from "../../trace/session.js";
|
|
20
|
+
/** 尾部优先:首屏与每次向前翻页的回合数。 */
|
|
21
|
+
export const TRACE_PAGE_TURNS = 50;
|
|
22
|
+
/** 刷新节流(≤ 2 Hz)。 */
|
|
23
|
+
export const TRACE_REFRESH_MS = 500;
|
|
24
|
+
export class TraceView {
|
|
25
|
+
host;
|
|
26
|
+
taskId;
|
|
27
|
+
close;
|
|
28
|
+
focused = false;
|
|
29
|
+
trace;
|
|
30
|
+
root;
|
|
31
|
+
rows = [];
|
|
32
|
+
lookup;
|
|
33
|
+
expanded = new Map();
|
|
34
|
+
/** 已展开过的 ama 子 Agent(重建后重新挂子轨迹)。 */
|
|
35
|
+
loaded = new Set();
|
|
36
|
+
fromTurn = 0;
|
|
37
|
+
cursor = 0;
|
|
38
|
+
top = 0;
|
|
39
|
+
follow = false;
|
|
40
|
+
detail;
|
|
41
|
+
live;
|
|
42
|
+
loadChild;
|
|
43
|
+
constructor(host, taskId, close) {
|
|
44
|
+
this.host = host;
|
|
45
|
+
this.taskId = taskId;
|
|
46
|
+
this.close = close;
|
|
47
|
+
this.live = new LiveTracker(host.session, host.now);
|
|
48
|
+
this.loadChild = host.loadChild ?? childLoader();
|
|
49
|
+
this.rebuild();
|
|
50
|
+
this.follow = this.trace.partial;
|
|
51
|
+
if (taskId === undefined)
|
|
52
|
+
this.fromTurn = tailStart(this.trace, TRACE_PAGE_TURNS);
|
|
53
|
+
if (this.root !== undefined)
|
|
54
|
+
this.expanded.set(this.rowsKeyOfRoot(), true);
|
|
55
|
+
this.reflow();
|
|
56
|
+
this.cursor = Math.max(0, this.rows.length - 1);
|
|
57
|
+
}
|
|
58
|
+
/** 任务存在(`/trace <id>`)或看主会话。 */
|
|
59
|
+
get found() {
|
|
60
|
+
return this.taskId === undefined || this.root !== undefined;
|
|
61
|
+
}
|
|
62
|
+
rowsKeyOfRoot() {
|
|
63
|
+
return `a:${this.taskId}`;
|
|
64
|
+
}
|
|
65
|
+
/** 重建轨迹(会话条目 + live 叠加 + 已展开的子轨迹)。 */
|
|
66
|
+
rebuild() {
|
|
67
|
+
const session = this.host.session();
|
|
68
|
+
const input = traceInputOf(session);
|
|
69
|
+
this.trace = buildTrace(input, { live: this.live.overlay() });
|
|
70
|
+
for (const taskId of this.loaded) {
|
|
71
|
+
const node = findSubagent(this.trace, taskId);
|
|
72
|
+
if (node !== undefined)
|
|
73
|
+
loadSubagentTrace(node, this.loadChild);
|
|
74
|
+
}
|
|
75
|
+
if (this.taskId !== undefined) {
|
|
76
|
+
this.root = findSubagent(this.trace, this.taskId);
|
|
77
|
+
if (this.root !== undefined)
|
|
78
|
+
loadSubagentTrace(this.root, this.loadChild);
|
|
79
|
+
}
|
|
80
|
+
const children = this.loadChild.inputs().flatMap((i) => i.entries);
|
|
81
|
+
this.lookup = entryLookup([...input.entries, ...children], session.state.cwd);
|
|
82
|
+
}
|
|
83
|
+
/** 重新摊平,光标按 key 保持;跟随时贴底。 */
|
|
84
|
+
reflow() {
|
|
85
|
+
const key = this.rows[this.cursor]?.key;
|
|
86
|
+
const opts = { expanded: this.expanded, fromTurn: this.fromTurn };
|
|
87
|
+
this.rows =
|
|
88
|
+
this.root !== undefined ? flattenNode(this.root, opts) : flattenTrace(this.trace, opts);
|
|
89
|
+
const at = key === undefined ? -1 : rowIndex(this.rows, key);
|
|
90
|
+
this.cursor = this.follow
|
|
91
|
+
? Math.max(0, this.rows.length - 1)
|
|
92
|
+
: at >= 0
|
|
93
|
+
? at
|
|
94
|
+
: Math.min(this.cursor, Math.max(0, this.rows.length - 1));
|
|
95
|
+
if (this.detail !== undefined) {
|
|
96
|
+
const fresh = this.rows[rowIndex(this.rows, this.detail.row.key)];
|
|
97
|
+
if (fresh !== undefined)
|
|
98
|
+
this.detail.row = fresh;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** 会话有变化:重建并重排。 */
|
|
102
|
+
refresh() {
|
|
103
|
+
this.rebuild();
|
|
104
|
+
this.reflow();
|
|
105
|
+
}
|
|
106
|
+
/** 当前行数(测试用)。 */
|
|
107
|
+
get rowCount() {
|
|
108
|
+
return this.rows.length;
|
|
109
|
+
}
|
|
110
|
+
get cursorIndex() {
|
|
111
|
+
return this.cursor;
|
|
112
|
+
}
|
|
113
|
+
get selected() {
|
|
114
|
+
return this.rows[this.cursor];
|
|
115
|
+
}
|
|
116
|
+
get following() {
|
|
117
|
+
return this.follow;
|
|
118
|
+
}
|
|
119
|
+
get detailOpen() {
|
|
120
|
+
return this.detail !== undefined;
|
|
121
|
+
}
|
|
122
|
+
bodyHeight() {
|
|
123
|
+
return Math.max(1, this.host.rows() - 1 - 2);
|
|
124
|
+
}
|
|
125
|
+
move(delta) {
|
|
126
|
+
if (this.rows.length === 0)
|
|
127
|
+
return;
|
|
128
|
+
if (delta < 0)
|
|
129
|
+
this.follow = false;
|
|
130
|
+
// 第一行是「更早的回合」时继续上移 = 加载前一页
|
|
131
|
+
if (delta < 0 && this.cursor === 0 && this.rows[0]?.node.kind === "more")
|
|
132
|
+
return this.loadEarlier();
|
|
133
|
+
this.cursor = Math.max(0, Math.min(this.rows.length - 1, this.cursor + delta));
|
|
134
|
+
if (delta > 0 && this.cursor === this.rows.length - 1 && this.trace.partial)
|
|
135
|
+
this.follow = true;
|
|
136
|
+
}
|
|
137
|
+
loadEarlier() {
|
|
138
|
+
const key = this.rows[1]?.key;
|
|
139
|
+
this.fromTurn = Math.max(0, this.fromTurn - TRACE_PAGE_TURNS);
|
|
140
|
+
this.reflow();
|
|
141
|
+
const at = key === undefined ? -1 : rowIndex(this.rows, key);
|
|
142
|
+
this.cursor = Math.max(0, at - 1);
|
|
143
|
+
}
|
|
144
|
+
expand() {
|
|
145
|
+
const row = this.selected;
|
|
146
|
+
if (row === undefined)
|
|
147
|
+
return;
|
|
148
|
+
if (!row.expandable)
|
|
149
|
+
return;
|
|
150
|
+
if (!row.expanded) {
|
|
151
|
+
if (needsChild(row.node)) {
|
|
152
|
+
this.loaded.add(row.node.taskId);
|
|
153
|
+
loadSubagentTrace(row.node, this.loadChild);
|
|
154
|
+
this.rebuild();
|
|
155
|
+
}
|
|
156
|
+
this.expanded.set(row.key, true);
|
|
157
|
+
this.reflow();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (this.rows[this.cursor + 1]?.depth === row.depth + 1)
|
|
161
|
+
this.cursor++;
|
|
162
|
+
}
|
|
163
|
+
collapse() {
|
|
164
|
+
const row = this.selected;
|
|
165
|
+
if (row === undefined)
|
|
166
|
+
return;
|
|
167
|
+
this.follow = false;
|
|
168
|
+
if (row.expanded) {
|
|
169
|
+
this.expanded.set(row.key, false);
|
|
170
|
+
this.reflow();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const slash = row.key.lastIndexOf("/");
|
|
174
|
+
if (slash < 0)
|
|
175
|
+
return;
|
|
176
|
+
const parent = rowIndex(this.rows, row.key.slice(0, slash));
|
|
177
|
+
if (parent >= 0)
|
|
178
|
+
this.cursor = parent;
|
|
179
|
+
}
|
|
180
|
+
handleInput(data) {
|
|
181
|
+
const keys = this.host.keybindings ?? defaultKeybindings;
|
|
182
|
+
if (this.detail !== undefined)
|
|
183
|
+
return this.detailInput(data, keys);
|
|
184
|
+
const page = this.bodyHeight();
|
|
185
|
+
if (keys.matches(data, "tui.select.up"))
|
|
186
|
+
this.move(-1);
|
|
187
|
+
else if (keys.matches(data, "tui.select.down"))
|
|
188
|
+
this.move(1);
|
|
189
|
+
else if (keys.matches(data, "tui.select.pageUp"))
|
|
190
|
+
this.move(-page);
|
|
191
|
+
else if (keys.matches(data, "tui.select.pageDown"))
|
|
192
|
+
this.move(page);
|
|
193
|
+
else if (matchesKey(data, "home")) {
|
|
194
|
+
this.follow = false;
|
|
195
|
+
this.cursor = 0;
|
|
196
|
+
}
|
|
197
|
+
else if (matchesKey(data, "end")) {
|
|
198
|
+
this.cursor = Math.max(0, this.rows.length - 1);
|
|
199
|
+
this.follow = this.trace.partial;
|
|
200
|
+
}
|
|
201
|
+
else if (matchesKey(data, "right"))
|
|
202
|
+
this.expand();
|
|
203
|
+
else if (matchesKey(data, "left"))
|
|
204
|
+
this.collapse();
|
|
205
|
+
else if (matchesKey(data, "enter")) {
|
|
206
|
+
const row = this.selected;
|
|
207
|
+
if (row?.node.kind === "more")
|
|
208
|
+
this.loadEarlier();
|
|
209
|
+
else if (row !== undefined && row.node.kind !== "aux_group")
|
|
210
|
+
this.detail = { row, scroll: 0 };
|
|
211
|
+
}
|
|
212
|
+
else if (data === "f") {
|
|
213
|
+
this.follow = !this.follow;
|
|
214
|
+
if (this.follow)
|
|
215
|
+
this.cursor = Math.max(0, this.rows.length - 1);
|
|
216
|
+
}
|
|
217
|
+
else if (matchesKey(data, "escape") || keys.matches(data, "tui.select.cancel"))
|
|
218
|
+
this.close();
|
|
219
|
+
}
|
|
220
|
+
detailInput(data, keys) {
|
|
221
|
+
const detail = this.detail;
|
|
222
|
+
const page = this.bodyHeight();
|
|
223
|
+
if (keys.matches(data, "tui.select.up"))
|
|
224
|
+
detail.scroll = Math.max(0, detail.scroll - 1);
|
|
225
|
+
else if (keys.matches(data, "tui.select.down"))
|
|
226
|
+
detail.scroll++;
|
|
227
|
+
else if (keys.matches(data, "tui.select.pageUp"))
|
|
228
|
+
detail.scroll = Math.max(0, detail.scroll - page);
|
|
229
|
+
else if (keys.matches(data, "tui.select.pageDown"))
|
|
230
|
+
detail.scroll += page;
|
|
231
|
+
else if (matchesKey(data, "escape") || matchesKey(data, "enter") || matchesKey(data, "left"))
|
|
232
|
+
this.detail = undefined;
|
|
233
|
+
}
|
|
234
|
+
ctx() {
|
|
235
|
+
return {
|
|
236
|
+
theme: this.host.theme,
|
|
237
|
+
describe: (n) => describeNode(n, this.lookup),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
headerLine(width) {
|
|
241
|
+
const theme = this.host.theme;
|
|
242
|
+
const m = msg().trace;
|
|
243
|
+
const root = this.root;
|
|
244
|
+
const title = root !== undefined ? m.taskTitle(root.taskId, root.agent) : m.title;
|
|
245
|
+
const source = root !== undefined ? root.child : this.trace;
|
|
246
|
+
const summary = source !== undefined ? ` · ${summaryText(source, theme)}` : "";
|
|
247
|
+
const state = this.trace.partial ? (this.follow ? m.follow.on : m.follow.off) : "";
|
|
248
|
+
const right = state === "" ? "" : ` ${theme.fg(this.follow ? "accent" : "muted", state)}`;
|
|
249
|
+
const left = truncateToWidth(`${theme.bold(title)}${theme.fg("muted", summary)}`, Math.max(1, width - visibleWidth(right)), theme.glyphs.ellipsis);
|
|
250
|
+
return padToWidth(`${left}${right}`, width);
|
|
251
|
+
}
|
|
252
|
+
render(width) {
|
|
253
|
+
const theme = this.host.theme;
|
|
254
|
+
const height = this.bodyHeight();
|
|
255
|
+
const lines = [this.headerLine(width)];
|
|
256
|
+
if (this.detail !== undefined) {
|
|
257
|
+
const { row } = this.detail;
|
|
258
|
+
const body = [
|
|
259
|
+
theme.bold(rowLabel(row, this.ctx())),
|
|
260
|
+
...detailLines(row.node, this.lookup, Math.max(8, width - 2), theme, this.trace.startedAt),
|
|
261
|
+
].map((l) => ` ${l}`);
|
|
262
|
+
const max = Math.max(0, body.length - height);
|
|
263
|
+
this.detail.scroll = Math.min(this.detail.scroll, max);
|
|
264
|
+
for (const line of body.slice(this.detail.scroll, this.detail.scroll + height))
|
|
265
|
+
lines.push(padToWidth(truncateToWidth(line, width, theme.glyphs.ellipsis), width));
|
|
266
|
+
}
|
|
267
|
+
else if (this.rows.length === 0)
|
|
268
|
+
lines.push(padToWidth(theme.dim(` ${msg().trace.empty}`), width));
|
|
269
|
+
else {
|
|
270
|
+
// 窗口:光标始终可见;跟随时贴底
|
|
271
|
+
if (this.cursor < this.top)
|
|
272
|
+
this.top = this.cursor;
|
|
273
|
+
if (this.cursor >= this.top + height)
|
|
274
|
+
this.top = this.cursor - height + 1;
|
|
275
|
+
this.top = Math.max(0, Math.min(this.top, Math.max(0, this.rows.length - height)));
|
|
276
|
+
const ctx = this.ctx();
|
|
277
|
+
for (let i = this.top; i < Math.min(this.rows.length, this.top + height); i++)
|
|
278
|
+
lines.push(formatRow(this.rows[i], width, ctx, i === this.cursor));
|
|
279
|
+
}
|
|
280
|
+
while (lines.length < height + 1)
|
|
281
|
+
lines.push(" ".repeat(width));
|
|
282
|
+
const hints = msg().trace.hints;
|
|
283
|
+
const hint = this.detail !== undefined ? hints.detail : width < 60 ? hints.listNarrow : hints.list;
|
|
284
|
+
lines.push(padToWidth(truncateToWidth(theme.dim(hint), width, theme.glyphs.ellipsis), width));
|
|
285
|
+
return lines;
|
|
286
|
+
}
|
|
287
|
+
invalidate() { }
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* 打开 `/trace` 覆盖层;关闭时 resolve。任务不存在时提示一行、不打开。
|
|
291
|
+
*/
|
|
292
|
+
export function openTraceView(host, taskId) {
|
|
293
|
+
return new Promise((resolve) => {
|
|
294
|
+
let handle;
|
|
295
|
+
let timer;
|
|
296
|
+
let unsubscribe;
|
|
297
|
+
let last = 0;
|
|
298
|
+
const finish = () => {
|
|
299
|
+
if (timer !== undefined)
|
|
300
|
+
clearTimeout(timer);
|
|
301
|
+
unsubscribe?.();
|
|
302
|
+
handle?.hide();
|
|
303
|
+
host.render?.();
|
|
304
|
+
resolve();
|
|
305
|
+
};
|
|
306
|
+
const view = new TraceView(host, taskId, finish);
|
|
307
|
+
if (!view.found) {
|
|
308
|
+
host.notice("warn", msg().trace.taskNotFound(taskId));
|
|
309
|
+
resolve();
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
const throttle = host.refreshMs ?? TRACE_REFRESH_MS;
|
|
313
|
+
const flush = () => {
|
|
314
|
+
timer = undefined;
|
|
315
|
+
last = host.now();
|
|
316
|
+
view.refresh();
|
|
317
|
+
host.render?.();
|
|
318
|
+
};
|
|
319
|
+
unsubscribe = host.session().subscribe((event) => {
|
|
320
|
+
if (!view.live.onEvent(event) || timer !== undefined)
|
|
321
|
+
return;
|
|
322
|
+
const wait = Math.max(0, throttle - (host.now() - last));
|
|
323
|
+
if (wait === 0)
|
|
324
|
+
flush();
|
|
325
|
+
else {
|
|
326
|
+
timer = setTimeout(flush, wait);
|
|
327
|
+
timer.unref?.();
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
handle = host.showOverlay(view, { anchor: "bottom" });
|
|
331
|
+
});
|
|
332
|
+
}
|