@selesai/code 0.13.16 → 0.13.18
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 +30 -0
- package/README.md +2 -14
- package/dist/bun/cli.d.ts +3 -1
- package/dist/bun/cli.js +3 -9
- package/dist/bun/{register-bedrock.js → runtime-setup.js} +5 -0
- package/dist/bun/sandbox-env-setup.d.ts +1 -0
- package/dist/bun/sandbox-env-setup.js +3 -0
- package/dist/cli/auth-command.d.ts +23 -0
- package/dist/cli/auth-command.js +102 -0
- package/dist/cli/config-selector.js +2 -1
- package/dist/cli/setup.d.ts +1 -0
- package/dist/cli/setup.js +11 -0
- package/dist/cli.js +2 -14
- package/dist/config.d.ts +3 -2
- package/dist/config.js +9 -4
- package/dist/core/agent-session-runtime.js +15 -7
- package/dist/core/agent-session.d.ts +2 -6
- package/dist/core/agent-session.js +15 -4
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.js +2 -1
- package/dist/core/extensions/loader.js +3 -0
- package/dist/core/extensions/types.d.ts +16 -2
- package/dist/core/http-dispatcher.js +2 -0
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.js +4 -0
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/model-config.d.ts +15 -0
- package/dist/core/model-config.js +3 -0
- package/dist/core/model-runtime.d.ts +1 -0
- package/dist/core/model-runtime.js +5 -2
- package/dist/core/provider-composer.js +8 -2
- package/dist/core/session-export.d.ts +3 -0
- package/dist/core/session-export.js +31 -0
- package/dist/core/session-manager.d.ts +3 -2
- package/dist/core/session-manager.js +40 -13
- package/dist/core/skills.d.ts +1 -1
- package/dist/core/skills.js +4 -2
- package/dist/core/system-prompt.js +10 -10
- package/dist/core/tools/bash.js +3 -117
- package/dist/core/tools/edit.d.ts +1 -12
- package/dist/core/tools/edit.js +5 -163
- package/dist/core/tools/find.js +4 -55
- package/dist/core/tools/grep.js +4 -60
- package/dist/core/tools/ls.js +4 -49
- package/dist/core/tools/read.d.ts +4 -0
- package/dist/core/tools/read.js +10 -122
- package/dist/core/tools/renderers/bash.d.ts +11 -0
- package/dist/core/tools/renderers/bash.js +129 -0
- package/dist/core/tools/renderers/edit.d.ts +22 -0
- package/dist/core/tools/renderers/edit.js +166 -0
- package/dist/core/tools/renderers/find.d.ts +9 -0
- package/dist/core/tools/renderers/find.js +63 -0
- package/dist/core/tools/renderers/grep.d.ts +9 -0
- package/dist/core/tools/renderers/grep.js +68 -0
- package/dist/core/tools/renderers/index.d.ts +27 -0
- package/dist/core/tools/renderers/index.js +46 -0
- package/dist/core/tools/renderers/ls.d.ts +9 -0
- package/dist/core/tools/renderers/ls.js +57 -0
- package/dist/core/tools/renderers/read.d.ts +10 -0
- package/dist/core/tools/renderers/read.js +128 -0
- package/dist/core/tools/renderers/write.d.ts +9 -0
- package/dist/core/tools/renderers/write.js +152 -0
- package/dist/core/tools/write.js +5 -146
- package/dist/extensions/pi-hermes-memory/CHANGELOG.md +18 -0
- package/dist/extensions/pi-hermes-memory/README.md +16 -12
- package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +1 -1
- package/dist/extensions/pi-hermes-memory/package-lock.json +587 -62
- package/dist/extensions/pi-hermes-memory/package.json +4 -4
- package/dist/extensions/pi-hermes-memory/src/config.ts +32 -0
- package/dist/extensions/pi-hermes-memory/src/constants.ts +12 -2
- package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +109 -51
- package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +9 -3
- package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +257 -98
- package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +9 -2
- package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +5 -0
- package/dist/extensions/pi-hermes-memory/src/index.ts +22 -2
- package/dist/extensions/pi-hermes-memory/src/paths.ts +1 -1
- package/dist/extensions/pi-hermes-memory/src/store/db.ts +6 -0
- package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +58 -1
- package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +60 -8
- package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +169 -7
- package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +7 -21
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +134 -15
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +4 -2
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +24 -9
- package/dist/extensions/pi-hermes-memory/src/types.ts +11 -0
- package/dist/extensions/pi-hermes-memory/tests/config.test.ts +42 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +159 -3
- package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +452 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +39 -0
- package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +91 -0
- package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +29 -0
- package/dist/extensions/pi-hermes-memory/tests/store/fts-query.test.ts +116 -0
- package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +163 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +233 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +12 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +175 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +2 -2
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +22 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +37 -1
- package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
- package/dist/extensions/pi-intercom/README.md +16 -2
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +19 -2
- package/dist/extensions/pi-intercom/broker/spawn.ts +4 -4
- package/dist/extensions/pi-intercom/index.ts +1 -1
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +121 -2
- package/dist/extensions/pi-intercom/package.json +1 -1
- package/dist/extensions/pi-intercom/project-agent.test.ts +1 -1
- package/dist/extensions/pi-intercom/project-agent.ts +1 -6
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +7 -6
- package/dist/extensions/pi-rewind-hook/index.test.ts +7 -0
- package/dist/extensions/pi-subagents/.github/workflows/test.yml +36 -4
- package/dist/extensions/pi-subagents/CHANGELOG.md +120 -0
- package/dist/extensions/pi-subagents/README.md +3 -3
- package/dist/extensions/pi-subagents/agents/researcher.md +23 -13
- package/dist/extensions/pi-subagents/agents/reviewer.md +1 -1
- package/dist/extensions/pi-subagents/agents/scout.md +1 -1
- package/dist/extensions/pi-subagents/docs/agents.md +32 -16
- package/dist/extensions/pi-subagents/docs/configuration.md +41 -15
- package/dist/extensions/pi-subagents/docs/extension-api.md +109 -6
- package/dist/extensions/pi-subagents/docs/missions.md +2 -0
- package/dist/extensions/pi-subagents/docs/models.md +58 -1
- package/dist/extensions/pi-subagents/docs/observability.md +50 -12
- package/dist/extensions/pi-subagents/docs/tool-reference.md +17 -10
- package/dist/extensions/pi-subagents/docs/watchdog.md +1 -1
- package/dist/extensions/pi-subagents/docs/workflows.md +26 -9
- package/dist/extensions/pi-subagents/package-lock.json +747 -177
- package/dist/extensions/pi-subagents/package.json +6 -4
- package/dist/extensions/pi-subagents/runner-server-preload.mjs +13 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +21 -4
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
- package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +63 -0
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +61 -16
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +8 -0
- package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +0 -1
- package/dist/extensions/pi-subagents/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
- package/dist/extensions/pi-subagents/src/api/preflight.ts +7 -4
- package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -2
- package/dist/extensions/pi-subagents/src/api/workflow-resources.ts +6 -0
- package/dist/extensions/pi-subagents/src/extension/config.ts +4 -2
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +2 -10
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +9 -11
- package/dist/extensions/pi-subagents/src/extension/index.ts +99 -10
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +13 -0
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +7 -23
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +11 -8
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +25 -7
- package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +73 -0
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +228 -136
- package/dist/extensions/pi-subagents/src/intercom/supervisor-ui.ts +244 -0
- package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +37 -16
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +18 -18
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +51 -25
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +46 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +9 -0
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +10 -12
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -15
- package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +40 -29
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +8 -0
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +79 -247
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +88 -12
- package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +6 -6
- package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +24 -24
- package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +96 -0
- package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +642 -0
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +75 -6
- package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +163 -0
- package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +86 -0
- package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +31 -0
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +18 -4
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +597 -1092
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +3 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +20 -17
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +296 -394
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +9 -5
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +630 -283
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +78 -98
- package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +16 -3
- package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +47 -47
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -2
- package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +174 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +14 -3
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +319 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +25 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +126 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +373 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +530 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +11 -11
- package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +30 -20
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +84 -15
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +88 -12
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +37 -53
- package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +18 -7
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +57 -12
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +3 -4
- package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +0 -11
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +4 -1
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-drain-observation.ts +42 -0
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +69 -0
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +307 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +8 -21
- package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +3 -30
- package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +17 -4
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +99 -386
- package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +18 -62
- package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +0 -14
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +31 -9
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +190 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +506 -226
- package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +1 -1
- package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +11 -0
- package/dist/extensions/pi-subagents/src/shared/model-response-aliases.ts +13 -0
- package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +0 -6
- package/dist/extensions/pi-subagents/src/shared/types.ts +145 -89
- package/dist/extensions/pi-subagents/src/shared/utils.ts +13 -6
- package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +2 -0
- package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +18 -13
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +0 -6
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +1 -1
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +11 -6
- package/dist/extensions/pi-subagents/src/tui/render.ts +277 -46
- package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +0 -1
- package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +12 -12
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +116 -15
- package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +15 -18
- package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +57 -8
- package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +19 -19
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +3 -3
- package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +97 -22
- package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +3 -0
- package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +336 -21
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +1181 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +2240 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +2268 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +1512 -0
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +231 -16
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +4 -18
- package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +95 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +9 -15
- package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +374 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -10
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +18 -6
- package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +151 -0
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +42 -1
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +150 -25
- package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +354 -0
- package/dist/extensions/pi-subagents/test/integration/shared-cwd-terminal-evidence.test.ts +117 -0
- package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +3678 -0
- package/dist/extensions/pi-subagents/test/integration/{single-execution.test.ts → single-execution.part-2.test.ts} +500 -4207
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -2
- package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +127 -0
- package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +365 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +31 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +74 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-extension.ts +16 -0
- package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +699 -0
- package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +418 -0
- package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +13 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +30 -76
- package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +84 -0
- package/dist/extensions/pi-subagents/test/support/result-publication-capacity-preload.mjs +70 -0
- package/dist/extensions/pi-subagents/test/support/runner-child-session-factory.ts +17 -0
- package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +390 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +120 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +24 -3
- package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +87 -0
- package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +163 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -31
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +78 -3
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +2 -8
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +73 -66
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +51 -1
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +49 -1
- package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +9 -8
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +10 -7
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +48 -6
- package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +90 -0
- package/dist/extensions/pi-subagents/test/unit/{pi-args-permission-system.test.ts → child-tool-plan-permission-system.test.ts} +48 -86
- package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +18 -18
- package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +9 -9
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +8 -7
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +225 -65
- package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +17 -22
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +11 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +47 -3
- package/dist/extensions/pi-subagents/test/unit/foreign-workflow-steering.test.ts +74 -0
- package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +23 -29
- package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +96 -4
- package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +4 -4
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +116 -55
- package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +58 -1
- package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +104 -3
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
- package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +31 -1
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +102 -51
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +196 -6
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +181 -38
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +62 -70
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +58 -53
- package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +42 -0
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +13 -5
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +21 -5
- package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +5 -4
- package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +2 -6
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +28 -2
- package/dist/extensions/pi-subagents/test/unit/pi-web-session-liveness.test.ts +209 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +38 -1
- package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +43 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +24 -2
- package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +174 -0
- package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +1329 -0
- package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +29 -80
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +11 -8
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/retained-nested-route-tracker.test.ts +175 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +38 -12
- package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +2 -5
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +89 -1
- package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +2 -16
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +27 -3
- package/dist/extensions/pi-subagents/test/unit/scheduled-supervisor-demand.test.ts +215 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +15 -11
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +237 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -5
- package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +14 -1
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +130 -739
- package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +682 -0
- package/dist/extensions/pi-subagents/test/unit/supervisor-ui.test.ts +137 -0
- package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +1 -11
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +23 -3
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +8 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +19 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +72 -4
- package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +17 -3
- package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +12 -2
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +46 -6
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +133 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +53 -2
- package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +222 -14
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +526 -85
- package/dist/extensions/pi-zentui/README.md +17 -0
- package/dist/extensions/pi-zentui/assets/screenshots/footer-status-hyperlink.png +0 -0
- package/dist/extensions/pi-zentui/docs/configuration.md +71 -2
- package/dist/extensions/pi-zentui/extensions/zentui/config.ts +11 -0
- package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +14 -0
- package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +29 -13
- package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +5 -4
- package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +11 -0
- package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +11 -10
- package/dist/extensions/pi-zentui/extensions/zentui/index.ts +77 -3
- package/dist/extensions/pi-zentui/extensions/zentui/presets.ts +77 -0
- package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +103 -2
- package/dist/extensions/pi-zentui/extensions/zentui/working-line-extension-segments.ts +115 -0
- package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +87 -5
- package/dist/extensions/pi-zentui/package-lock.json +277 -517
- package/dist/extensions/pi-zentui/package.json +7 -4
- package/dist/extensions/pi-zentui/test/config-presets.test.ts +238 -0
- package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +24 -1
- package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +570 -2
- package/dist/extensions/pi-zentui/test/extension-status.test.ts +90 -0
- package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +243 -0
- package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
- package/dist/extensions/pi-zentui/test/presets.test.ts +121 -0
- package/dist/extensions/pi-zentui/test/settings-command.test.ts +205 -1
- package/dist/extensions/pi-zentui/test/working-line-extension-segments.test.ts +139 -0
- package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +237 -3
- package/dist/extensions/pi-zentui/test/working-line.test.ts +94 -2
- package/dist/index.d.ts +1 -1
- package/dist/main.js +4 -1
- package/dist/modes/interactive/chat-viewport.d.ts +19 -0
- package/dist/modes/interactive/chat-viewport.js +27 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
- package/dist/modes/interactive/components/assistant-message.js +30 -13
- package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
- package/dist/modes/interactive/components/custom-editor.js +39 -1
- package/dist/modes/interactive/components/first-time-setup.js +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts +2 -0
- package/dist/modes/interactive/components/markdown-transform.js +18 -0
- package/dist/modes/interactive/components/model-selector.js +19 -17
- package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
- package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
- package/dist/modes/interactive/components/settings-selector.js +128 -20
- package/dist/modes/interactive/components/settings-submenu.d.ts +71 -0
- package/dist/modes/interactive/components/settings-submenu.js +164 -0
- package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
- package/dist/modes/interactive/components/status-indicator.js +10 -3
- package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
- package/dist/modes/interactive/components/thinking-selector.js +75 -18
- package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
- package/dist/modes/interactive/components/tool-execution.js +35 -33
- package/dist/modes/interactive/components/trust-selector.js +2 -2
- package/dist/modes/interactive/interactive-mode.d.ts +13 -15
- package/dist/modes/interactive/interactive-mode.js +144 -80
- package/dist/modes/interactive/session-share.d.ts +15 -0
- package/dist/modes/interactive/session-share.js +183 -0
- package/dist/modes/interactive/theme/dark.json +2 -1
- package/dist/modes/interactive/theme/light.json +2 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
- package/dist/modes/interactive/theme/theme-controller.js +5 -0
- package/dist/modes/interactive/theme/theme-json.d.ts +83 -0
- package/dist/modes/interactive/theme/theme-json.js +129 -0
- package/dist/modes/interactive/theme/theme-schema.json +9 -1
- package/dist/modes/interactive/theme/theme.d.ts +14 -5
- package/dist/modes/interactive/theme/theme.js +18 -119
- package/dist/modes/interactive/tui-renderer.d.ts +20 -0
- package/dist/modes/interactive/tui-renderer.js +65 -0
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/management-http.d.ts +24 -0
- package/dist/utils/management-http.js +53 -0
- package/dist/utils/text.d.ts +7 -0
- package/dist/utils/text.js +8 -0
- package/dist/utils/tools-manager.d.ts +1 -0
- package/dist/utils/tools-manager.js +43 -21
- package/docs/docs.json +0 -4
- package/package.json +4 -4
- package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +0 -415
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +0 -1059
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +0 -116
- package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +0 -224
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +0 -6986
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +0 -447
- package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +0 -185
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +0 -311
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +0 -84
- package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +0 -202
- package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +0 -101
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +0 -2347
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +0 -104
- package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +0 -49
- package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -1465
- package/dist/skills/imagegen-frontend-web/SKILL.md +0 -987
- package/dist/skills/implanger/SKILL.md +0 -70
- package/dist/skills/output/SKILL.md +0 -49
- package/dist/skills/planger/SKILL.md +0 -167
- package/dist/skills/workflow/SKILL.md +0 -95
- package/docs/workflows.md +0 -18
- /package/dist/bun/{register-bedrock.d.ts → runtime-setup.d.ts} +0 -0
package/dist/core/tools/read.js
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import { basename, dirname, isAbsolute, relative, resolve as resolvePath, sep } from "node:path";
|
|
2
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
3
1
|
import { constants } from "fs";
|
|
4
2
|
import { access as fsAccess, readFile as fsReadFile } from "fs/promises";
|
|
5
3
|
import { Type } from "typebox";
|
|
6
|
-
import { getReadmePath } from "../../config.js";
|
|
7
|
-
import { keyHint, keyText } from "../../modes/interactive/components/keybinding-hints.js";
|
|
8
|
-
import { getLanguageFromPath, highlightCode } from "../../modes/interactive/theme/theme.js";
|
|
9
4
|
import { processImage } from "../../utils/image-process.js";
|
|
10
5
|
import { detectSupportedImageMimeTypeFromFile } from "../../utils/mime.js";
|
|
11
|
-
import { formatPathRelativeToCwdOrAbsolute } from "../../utils/paths.js";
|
|
12
6
|
import { getExperimentalToolSampling } from "../experimental.js";
|
|
13
7
|
import { captionImageWithModel } from "../vision-caption.js";
|
|
14
|
-
import { resolveReadPathAsync
|
|
15
|
-
import {
|
|
8
|
+
import { resolveReadPathAsync } from "./path-utils.js";
|
|
9
|
+
import { readRenderers } from "./renderers/read.js";
|
|
16
10
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
17
11
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead } from "./truncate.js";
|
|
18
12
|
const readSchema = Type.Object({
|
|
@@ -20,30 +14,15 @@ const readSchema = Type.Object({
|
|
|
20
14
|
offset: Type.Optional(Type.Number({ description: "Line number to start reading from (1-indexed)" })),
|
|
21
15
|
limit: Type.Optional(Type.Number({ description: "Maximum number of lines to read" })),
|
|
22
16
|
});
|
|
23
|
-
const
|
|
17
|
+
export const readToolSystemPromptContribution = {
|
|
18
|
+
snippet: "Read file contents",
|
|
19
|
+
guidelines: ["Use read to examine files instead of cat or sed."],
|
|
20
|
+
};
|
|
24
21
|
const defaultReadOperations = {
|
|
25
22
|
readFile: (path) => fsReadFile(path),
|
|
26
23
|
access: (path) => fsAccess(path, constants.R_OK),
|
|
27
24
|
detectImageMimeType: detectSupportedImageMimeTypeFromFile,
|
|
28
25
|
};
|
|
29
|
-
function formatReadLineRange(args, theme) {
|
|
30
|
-
if (args?.offset === undefined && args?.limit === undefined)
|
|
31
|
-
return "";
|
|
32
|
-
const startLine = args.offset ?? 1;
|
|
33
|
-
const endLine = args.limit !== undefined ? startLine + args.limit - 1 : "";
|
|
34
|
-
return theme.fg("warning", `:${startLine}${endLine ? `-${endLine}` : ""}`);
|
|
35
|
-
}
|
|
36
|
-
function formatReadCall(args, theme, cwd) {
|
|
37
|
-
const pathDisplay = renderToolPath(str(args?.file_path ?? args?.path), theme, cwd);
|
|
38
|
-
return `${theme.fg("toolTitle", theme.bold("read"))} ${pathDisplay}${formatReadLineRange(args, theme)}`;
|
|
39
|
-
}
|
|
40
|
-
function trimTrailingEmptyLines(lines) {
|
|
41
|
-
let end = lines.length;
|
|
42
|
-
while (end > 0 && lines[end - 1] === "") {
|
|
43
|
-
end--;
|
|
44
|
-
}
|
|
45
|
-
return lines.slice(0, end);
|
|
46
|
-
}
|
|
47
26
|
function getNonVisionImageNote(model) {
|
|
48
27
|
if (!model || model.input.includes("image")) {
|
|
49
28
|
return undefined;
|
|
@@ -80,85 +59,6 @@ export async function captionImage(image, captionModelId, ctx, signal) {
|
|
|
80
59
|
signal,
|
|
81
60
|
});
|
|
82
61
|
}
|
|
83
|
-
function toPosixPath(filePath) {
|
|
84
|
-
return filePath.split(sep).join("/");
|
|
85
|
-
}
|
|
86
|
-
function getPiDocsClassification(absolutePath) {
|
|
87
|
-
const packageRoot = dirname(getReadmePath());
|
|
88
|
-
const relativePath = relative(resolvePath(packageRoot), resolvePath(absolutePath));
|
|
89
|
-
if (relativePath === "" ||
|
|
90
|
-
relativePath === ".." ||
|
|
91
|
-
relativePath.startsWith(`..${sep}`) ||
|
|
92
|
-
isAbsolute(relativePath)) {
|
|
93
|
-
return undefined;
|
|
94
|
-
}
|
|
95
|
-
const label = toPosixPath(relativePath);
|
|
96
|
-
if (label === "README.md" || label.startsWith("docs/") || label.startsWith("examples/")) {
|
|
97
|
-
return { kind: "docs", label };
|
|
98
|
-
}
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
function getCompactReadClassification(args, cwd) {
|
|
102
|
-
const rawPath = str(args?.file_path ?? args?.path);
|
|
103
|
-
if (!rawPath)
|
|
104
|
-
return undefined;
|
|
105
|
-
const absolutePath = resolveToCwd(rawPath, cwd);
|
|
106
|
-
const fileName = basename(absolutePath);
|
|
107
|
-
if (fileName === "SKILL.md") {
|
|
108
|
-
return { kind: "skill", label: basename(dirname(absolutePath)) || fileName };
|
|
109
|
-
}
|
|
110
|
-
const docsClassification = getPiDocsClassification(absolutePath);
|
|
111
|
-
if (docsClassification)
|
|
112
|
-
return docsClassification;
|
|
113
|
-
if (COMPACT_RESOURCE_FILE_NAMES.has(fileName)) {
|
|
114
|
-
return { kind: "resource", label: formatPathRelativeToCwdOrAbsolute(absolutePath, cwd) };
|
|
115
|
-
}
|
|
116
|
-
return undefined;
|
|
117
|
-
}
|
|
118
|
-
function formatCompactReadCall(classification, args, theme) {
|
|
119
|
-
const expandHint = theme.fg("dim", ` (${keyText("app.tools.expand")} to expand)`);
|
|
120
|
-
if (classification.kind === "skill") {
|
|
121
|
-
return (theme.fg("customMessageLabel", `\x1b[1m[skill]\x1b[22m `) +
|
|
122
|
-
theme.fg("customMessageText", classification.label) +
|
|
123
|
-
formatReadLineRange(args, theme) +
|
|
124
|
-
expandHint);
|
|
125
|
-
}
|
|
126
|
-
return (theme.fg("toolTitle", theme.bold(`read ${classification.kind}`)) +
|
|
127
|
-
" " +
|
|
128
|
-
theme.fg("accent", classification.label) +
|
|
129
|
-
formatReadLineRange(args, theme) +
|
|
130
|
-
expandHint);
|
|
131
|
-
}
|
|
132
|
-
function formatReadResult(args, result, options, theme, showImages, _cwd, isError) {
|
|
133
|
-
if (!options.expanded && !isError) {
|
|
134
|
-
return "";
|
|
135
|
-
}
|
|
136
|
-
const rawPath = str(args?.file_path ?? args?.path);
|
|
137
|
-
const output = getTextOutput(result, showImages);
|
|
138
|
-
const lang = !isError && rawPath ? getLanguageFromPath(rawPath) : undefined;
|
|
139
|
-
const renderedLines = lang ? highlightCode(replaceTabs(output), lang) : output.split("\n");
|
|
140
|
-
const lines = trimTrailingEmptyLines(renderedLines);
|
|
141
|
-
const maxLines = options.expanded ? lines.length : 10;
|
|
142
|
-
const displayLines = lines.slice(0, maxLines);
|
|
143
|
-
const remaining = lines.length - maxLines;
|
|
144
|
-
let text = `\n${displayLines.map((line) => (lang ? replaceTabs(line) : theme.fg("toolOutput", replaceTabs(line)))).join("\n")}`;
|
|
145
|
-
if (remaining > 0) {
|
|
146
|
-
text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
|
|
147
|
-
}
|
|
148
|
-
const truncation = result.details?.truncation;
|
|
149
|
-
if (truncation?.truncated) {
|
|
150
|
-
if (truncation.firstLineExceedsLimit) {
|
|
151
|
-
text += `\n${theme.fg("warning", `[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`)}`;
|
|
152
|
-
}
|
|
153
|
-
else if (truncation.truncatedBy === "lines") {
|
|
154
|
-
text += `\n${theme.fg("warning", `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines ?? DEFAULT_MAX_LINES} line limit)]`)}`;
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
text += `\n${theme.fg("warning", `[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`)}`;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return text;
|
|
161
|
-
}
|
|
162
62
|
export function createReadToolDefinition(cwd, options) {
|
|
163
63
|
const autoResizeImages = options?.autoResizeImages ?? true;
|
|
164
64
|
const imageCaptionModel = options?.imageCaptionModel;
|
|
@@ -167,8 +67,8 @@ export function createReadToolDefinition(cwd, options) {
|
|
|
167
67
|
name: "read",
|
|
168
68
|
label: "read",
|
|
169
69
|
description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,
|
|
170
|
-
promptSnippet:
|
|
171
|
-
promptGuidelines: [
|
|
70
|
+
promptSnippet: readToolSystemPromptContribution.snippet,
|
|
71
|
+
promptGuidelines: [...readToolSystemPromptContribution.guidelines],
|
|
172
72
|
parameters: readSchema,
|
|
173
73
|
constrainedSampling: getExperimentalToolSampling(),
|
|
174
74
|
async execute(_toolCallId, { path, offset, limit }, signal, _onUpdate, ctx) {
|
|
@@ -185,7 +85,7 @@ export function createReadToolDefinition(cwd, options) {
|
|
|
185
85
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
186
86
|
(async () => {
|
|
187
87
|
try {
|
|
188
|
-
const absolutePath = await resolveReadPathAsync(path, cwd);
|
|
88
|
+
const absolutePath = await resolveReadPathAsync(path, ctx?.cwd || cwd);
|
|
189
89
|
if (aborted)
|
|
190
90
|
return;
|
|
191
91
|
// Check if file exists and is readable.
|
|
@@ -307,19 +207,7 @@ export function createReadToolDefinition(cwd, options) {
|
|
|
307
207
|
})();
|
|
308
208
|
});
|
|
309
209
|
},
|
|
310
|
-
|
|
311
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
312
|
-
const classification = !context.expanded ? getCompactReadClassification(args, context.cwd) : undefined;
|
|
313
|
-
text.setText(classification
|
|
314
|
-
? formatCompactReadCall(classification, args, theme)
|
|
315
|
-
: formatReadCall(args, theme, context.cwd));
|
|
316
|
-
return text;
|
|
317
|
-
},
|
|
318
|
-
renderResult(result, options, theme, context) {
|
|
319
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
320
|
-
text.setText(formatReadResult(context.args, result, options, theme, context.showImages, context.cwd, context.isError));
|
|
321
|
-
return text;
|
|
322
|
-
},
|
|
210
|
+
...readRenderers,
|
|
323
211
|
};
|
|
324
212
|
}
|
|
325
213
|
export function createReadTool(cwd, options) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation for the shell tools.
|
|
3
|
+
*
|
|
4
|
+
* Renderers live apart from the implementation so a process that only displays tool output does not
|
|
5
|
+
* load the execution path or its typebox parameter schema. `bash.ts` spreads these into the shell
|
|
6
|
+
* tool definition, so the tool's public shape is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import type { ToolDefinition } from "../../extensions/types.ts";
|
|
9
|
+
export declare const BASH_UPDATE_THROTTLE_MS = 100;
|
|
10
|
+
/** Shell renderers are shared by bash and powershell, which differ only in the prompt they display. */
|
|
11
|
+
export declare function createShellRenderers(prompt: string): Pick<ToolDefinition<any, any>, "renderCall" | "renderResult">;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation for the shell tools.
|
|
3
|
+
*
|
|
4
|
+
* Renderers live apart from the implementation so a process that only displays tool output does not
|
|
5
|
+
* load the execution path or its typebox parameter schema. `bash.ts` spreads these into the shell
|
|
6
|
+
* tool definition, so the tool's public shape is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import { Container, Text, truncateToWidth } from "@earendil-works/pi-tui";
|
|
9
|
+
import { keyHint } from "../../../modes/interactive/components/keybinding-hints.js";
|
|
10
|
+
import { truncateToVisualLines } from "../../../modes/interactive/components/visual-truncate.js";
|
|
11
|
+
import { theme } from "../../../modes/interactive/theme/theme.js";
|
|
12
|
+
import { getTextOutput, invalidArgText, str } from "../render-utils.js";
|
|
13
|
+
import { DEFAULT_MAX_BYTES, formatSize } from "../truncate.js";
|
|
14
|
+
const BASH_PREVIEW_LINES = 5;
|
|
15
|
+
export const BASH_UPDATE_THROTTLE_MS = 100;
|
|
16
|
+
class BashResultRenderComponent extends Container {
|
|
17
|
+
state = {
|
|
18
|
+
cachedWidth: undefined,
|
|
19
|
+
cachedLines: undefined,
|
|
20
|
+
cachedSkipped: undefined,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function formatDuration(ms) {
|
|
24
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
25
|
+
}
|
|
26
|
+
function formatShellCall(args, prompt) {
|
|
27
|
+
const command = str(args?.command);
|
|
28
|
+
const timeout = args?.timeout;
|
|
29
|
+
const timeoutSuffix = timeout ? theme.fg("muted", ` (timeout ${timeout}s)`) : "";
|
|
30
|
+
const commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg("toolOutput", "...");
|
|
31
|
+
return theme.fg("toolTitle", theme.bold(`${prompt} ${commandDisplay}`)) + timeoutSuffix;
|
|
32
|
+
}
|
|
33
|
+
function rebuildBashResultRenderComponent(component, result, options, showImages, startedAt, endedAt) {
|
|
34
|
+
const state = component.state;
|
|
35
|
+
component.clear();
|
|
36
|
+
let output = getTextOutput(result, showImages).trim();
|
|
37
|
+
const truncation = result.details?.truncation;
|
|
38
|
+
const fullOutputPath = result.details?.fullOutputPath;
|
|
39
|
+
if (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith("]")) {
|
|
40
|
+
const footerStart = output.lastIndexOf("\n\n[");
|
|
41
|
+
if (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {
|
|
42
|
+
output = output.slice(0, footerStart).trimEnd();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (output) {
|
|
46
|
+
const styledOutput = output
|
|
47
|
+
.split("\n")
|
|
48
|
+
.map((line) => theme.fg("toolOutput", line))
|
|
49
|
+
.join("\n");
|
|
50
|
+
if (options.expanded) {
|
|
51
|
+
component.addChild(new Text(`\n${styledOutput}`, 0, 0));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
component.addChild({
|
|
55
|
+
render: (width) => {
|
|
56
|
+
if (state.cachedLines === undefined || state.cachedWidth !== width) {
|
|
57
|
+
const preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);
|
|
58
|
+
state.cachedLines = preview.visualLines;
|
|
59
|
+
state.cachedSkipped = preview.skippedCount;
|
|
60
|
+
state.cachedWidth = width;
|
|
61
|
+
}
|
|
62
|
+
if (state.cachedSkipped && state.cachedSkipped > 0) {
|
|
63
|
+
const hint = theme.fg("muted", `... (${state.cachedSkipped} earlier lines,`) +
|
|
64
|
+
` ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
|
|
65
|
+
return ["", truncateToWidth(hint, width, "..."), ...(state.cachedLines ?? [])];
|
|
66
|
+
}
|
|
67
|
+
return ["", ...(state.cachedLines ?? [])];
|
|
68
|
+
},
|
|
69
|
+
invalidate: () => {
|
|
70
|
+
state.cachedWidth = undefined;
|
|
71
|
+
state.cachedLines = undefined;
|
|
72
|
+
state.cachedSkipped = undefined;
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (truncation?.truncated || fullOutputPath) {
|
|
78
|
+
const warnings = [];
|
|
79
|
+
if (fullOutputPath) {
|
|
80
|
+
warnings.push(`Full output: ${fullOutputPath}`);
|
|
81
|
+
}
|
|
82
|
+
if (truncation?.truncated) {
|
|
83
|
+
if (truncation.truncatedBy === "lines") {
|
|
84
|
+
warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
warnings.push(`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
component.addChild(new Text(`\n${theme.fg("warning", `[${warnings.join(". ")}]`)}`, 0, 0));
|
|
91
|
+
}
|
|
92
|
+
if (startedAt !== undefined) {
|
|
93
|
+
const label = options.isPartial ? "Elapsed" : "Took";
|
|
94
|
+
const endTime = endedAt ?? Date.now();
|
|
95
|
+
component.addChild(new Text(`\n${theme.fg("muted", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Shell renderers are shared by bash and powershell, which differ only in the prompt they display. */
|
|
99
|
+
export function createShellRenderers(prompt) {
|
|
100
|
+
return {
|
|
101
|
+
renderCall(args, _theme, context) {
|
|
102
|
+
const state = context.state;
|
|
103
|
+
if (context.executionStarted && state.startedAt === undefined) {
|
|
104
|
+
state.startedAt = Date.now();
|
|
105
|
+
state.endedAt = undefined;
|
|
106
|
+
}
|
|
107
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
108
|
+
text.setText(formatShellCall(args, prompt));
|
|
109
|
+
return text;
|
|
110
|
+
},
|
|
111
|
+
renderResult(result, options, _theme, context) {
|
|
112
|
+
const state = context.state;
|
|
113
|
+
if (state.startedAt !== undefined && options.isPartial && !state.interval) {
|
|
114
|
+
state.interval = setInterval(() => context.invalidate(), 1000);
|
|
115
|
+
}
|
|
116
|
+
if (!options.isPartial || context.isError) {
|
|
117
|
+
state.endedAt ??= Date.now();
|
|
118
|
+
if (state.interval) {
|
|
119
|
+
clearInterval(state.interval);
|
|
120
|
+
state.interval = undefined;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const component = context.lastComponent ?? new BashResultRenderComponent();
|
|
124
|
+
rebuildBashResultRenderComponent(component, result, options, context.showImages, state.startedAt, state.endedAt);
|
|
125
|
+
component.invalidate();
|
|
126
|
+
return component;
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation for the edit tool.
|
|
3
|
+
*
|
|
4
|
+
* Renderers live apart from the implementation so a process that only displays tool output does not
|
|
5
|
+
* load the execution path or its typebox parameter schema. `edit.ts` spreads these into its
|
|
6
|
+
* definition, so the tool's public shape is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import { Box } from "@earendil-works/pi-tui";
|
|
9
|
+
import type { ToolDefinition } from "../../extensions/types.ts";
|
|
10
|
+
import { type EditDiffError, type EditDiffResult } from "../edit-diff.ts";
|
|
11
|
+
type EditPreview = EditDiffResult | EditDiffError;
|
|
12
|
+
export type EditRenderState = {
|
|
13
|
+
callComponent?: EditCallRenderComponent;
|
|
14
|
+
};
|
|
15
|
+
type EditCallRenderComponent = Box & {
|
|
16
|
+
preview?: EditPreview;
|
|
17
|
+
previewArgsKey?: string;
|
|
18
|
+
previewPending?: boolean;
|
|
19
|
+
settledError?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export declare const editRenderers: Pick<ToolDefinition<any, any>, "renderCall" | "renderResult">;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation for the edit tool.
|
|
3
|
+
*
|
|
4
|
+
* Renderers live apart from the implementation so a process that only displays tool output does not
|
|
5
|
+
* load the execution path or its typebox parameter schema. `edit.ts` spreads these into its
|
|
6
|
+
* definition, so the tool's public shape is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import { Box, Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
9
|
+
import { renderDiff } from "../../../modes/interactive/components/diff.js";
|
|
10
|
+
import { computeEditsDiff } from "../edit-diff.js";
|
|
11
|
+
import { renderToolPath, str } from "../render-utils.js";
|
|
12
|
+
function createEditCallRenderComponent() {
|
|
13
|
+
return Object.assign(new Box(1, 1, (text) => text), {
|
|
14
|
+
preview: undefined,
|
|
15
|
+
previewArgsKey: undefined,
|
|
16
|
+
previewPending: false,
|
|
17
|
+
settledError: false,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function getEditCallRenderComponent(state, lastComponent) {
|
|
21
|
+
if (lastComponent instanceof Box) {
|
|
22
|
+
const component = lastComponent;
|
|
23
|
+
state.callComponent = component;
|
|
24
|
+
return component;
|
|
25
|
+
}
|
|
26
|
+
if (state.callComponent) {
|
|
27
|
+
return state.callComponent;
|
|
28
|
+
}
|
|
29
|
+
const component = createEditCallRenderComponent();
|
|
30
|
+
state.callComponent = component;
|
|
31
|
+
return component;
|
|
32
|
+
}
|
|
33
|
+
function getRenderablePreviewInput(args) {
|
|
34
|
+
if (!args) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const path = typeof args.path === "string" ? args.path : typeof args.file_path === "string" ? args.file_path : null;
|
|
38
|
+
if (!path) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (Array.isArray(args.edits) &&
|
|
42
|
+
args.edits.length > 0 &&
|
|
43
|
+
args.edits.every((edit) => typeof edit?.oldText === "string" && typeof edit?.newText === "string")) {
|
|
44
|
+
return { path, edits: args.edits };
|
|
45
|
+
}
|
|
46
|
+
if (typeof args.oldText === "string" && typeof args.newText === "string") {
|
|
47
|
+
return { path, edits: [{ oldText: args.oldText, newText: args.newText }] };
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function formatEditCall(args, theme, cwd) {
|
|
52
|
+
const pathDisplay = renderToolPath(str(args?.file_path ?? args?.path), theme, cwd);
|
|
53
|
+
return `${theme.fg("toolTitle", theme.bold("edit"))} ${pathDisplay}`;
|
|
54
|
+
}
|
|
55
|
+
function formatEditResult(args, preview, result, theme, isError) {
|
|
56
|
+
const rawPath = str(args?.file_path ?? args?.path);
|
|
57
|
+
const previewDiff = preview && !("error" in preview) ? preview.diff : undefined;
|
|
58
|
+
const previewError = preview && "error" in preview ? preview.error : undefined;
|
|
59
|
+
if (isError) {
|
|
60
|
+
const errorText = result.content
|
|
61
|
+
.filter((c) => c.type === "text")
|
|
62
|
+
.map((c) => c.text || "")
|
|
63
|
+
.join("\n");
|
|
64
|
+
if (!errorText || errorText === previewError) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
return theme.fg("error", errorText);
|
|
68
|
+
}
|
|
69
|
+
const resultDiff = result.details?.diff;
|
|
70
|
+
if (resultDiff && resultDiff !== previewDiff) {
|
|
71
|
+
return renderDiff(resultDiff, { filePath: rawPath ?? undefined });
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
function getEditHeaderBg(preview, settledError, theme) {
|
|
76
|
+
if (preview) {
|
|
77
|
+
if ("error" in preview) {
|
|
78
|
+
return (text) => theme.bg("toolErrorBg", text);
|
|
79
|
+
}
|
|
80
|
+
return (text) => theme.bg("toolSuccessBg", text);
|
|
81
|
+
}
|
|
82
|
+
if (settledError) {
|
|
83
|
+
return (text) => theme.bg("toolErrorBg", text);
|
|
84
|
+
}
|
|
85
|
+
return (text) => theme.bg("toolPendingBg", text);
|
|
86
|
+
}
|
|
87
|
+
function buildEditCallComponent(component, args, theme, cwd) {
|
|
88
|
+
component.setBgFn(getEditHeaderBg(component.preview, component.settledError, theme));
|
|
89
|
+
component.clear();
|
|
90
|
+
component.addChild(new Text(formatEditCall(args, theme, cwd), 0, 0));
|
|
91
|
+
if (!component.preview) {
|
|
92
|
+
return component;
|
|
93
|
+
}
|
|
94
|
+
const body = "error" in component.preview ? theme.fg("error", component.preview.error) : renderDiff(component.preview.diff);
|
|
95
|
+
component.addChild(new Spacer(1));
|
|
96
|
+
component.addChild(new Text(body, 0, 0));
|
|
97
|
+
return component;
|
|
98
|
+
}
|
|
99
|
+
function setEditPreview(component, preview, argsKey) {
|
|
100
|
+
const current = component.preview;
|
|
101
|
+
const changed = current === undefined ||
|
|
102
|
+
("error" in current && "error" in preview
|
|
103
|
+
? current.error !== preview.error
|
|
104
|
+
: "error" in current !== "error" in preview) ||
|
|
105
|
+
(!("error" in current) &&
|
|
106
|
+
!("error" in preview) &&
|
|
107
|
+
(current.diff !== preview.diff || current.firstChangedLine !== preview.firstChangedLine));
|
|
108
|
+
component.preview = preview;
|
|
109
|
+
component.previewArgsKey = argsKey;
|
|
110
|
+
component.previewPending = false;
|
|
111
|
+
return changed;
|
|
112
|
+
}
|
|
113
|
+
export const editRenderers = {
|
|
114
|
+
renderCall(args, theme, context) {
|
|
115
|
+
const component = getEditCallRenderComponent(context.state, context.lastComponent);
|
|
116
|
+
const previewInput = getRenderablePreviewInput(args);
|
|
117
|
+
const argsKey = previewInput ? JSON.stringify({ path: previewInput.path, edits: previewInput.edits }) : undefined;
|
|
118
|
+
if (component.previewArgsKey !== argsKey) {
|
|
119
|
+
component.preview = undefined;
|
|
120
|
+
component.previewArgsKey = argsKey;
|
|
121
|
+
component.previewPending = false;
|
|
122
|
+
component.settledError = false;
|
|
123
|
+
}
|
|
124
|
+
if (context.argsComplete && previewInput && !component.preview && !component.previewPending) {
|
|
125
|
+
component.previewPending = true;
|
|
126
|
+
const requestKey = argsKey;
|
|
127
|
+
void computeEditsDiff(previewInput.path, previewInput.edits, context.cwd).then((preview) => {
|
|
128
|
+
if (component.previewArgsKey === requestKey) {
|
|
129
|
+
setEditPreview(component, preview, requestKey);
|
|
130
|
+
context.invalidate();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return buildEditCallComponent(component, args, theme, context.cwd);
|
|
135
|
+
},
|
|
136
|
+
renderResult(result, _options, theme, context) {
|
|
137
|
+
const callComponent = context.state.callComponent;
|
|
138
|
+
const previewInput = getRenderablePreviewInput(context.args);
|
|
139
|
+
const argsKey = previewInput ? JSON.stringify({ path: previewInput.path, edits: previewInput.edits }) : undefined;
|
|
140
|
+
const typedResult = result;
|
|
141
|
+
const resultDiff = !context.isError ? typedResult.details?.diff : undefined;
|
|
142
|
+
let changed = false;
|
|
143
|
+
if (callComponent) {
|
|
144
|
+
if (typeof resultDiff === "string") {
|
|
145
|
+
changed =
|
|
146
|
+
setEditPreview(callComponent, { diff: resultDiff, firstChangedLine: typedResult.details?.firstChangedLine }, argsKey) || changed;
|
|
147
|
+
}
|
|
148
|
+
if (callComponent.settledError !== context.isError) {
|
|
149
|
+
callComponent.settledError = context.isError;
|
|
150
|
+
changed = true;
|
|
151
|
+
}
|
|
152
|
+
if (changed) {
|
|
153
|
+
buildEditCallComponent(callComponent, context.args, theme, context.cwd);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const output = formatEditResult(context.args, callComponent?.preview, typedResult, theme, context.isError);
|
|
157
|
+
const component = context.lastComponent ?? new Container();
|
|
158
|
+
component.clear();
|
|
159
|
+
if (!output) {
|
|
160
|
+
return component;
|
|
161
|
+
}
|
|
162
|
+
component.addChild(new Spacer(1));
|
|
163
|
+
component.addChild(new Text(output, 1, 0));
|
|
164
|
+
return component;
|
|
165
|
+
},
|
|
166
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation for the find tool.
|
|
3
|
+
*
|
|
4
|
+
* Renderers live apart from the implementation so a process that only displays tool output does not
|
|
5
|
+
* load the execution path or its typebox parameter schema. `find.ts` spreads these into its
|
|
6
|
+
* definition, so the tool's public shape is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import type { ToolDefinition } from "../../extensions/types.ts";
|
|
9
|
+
export declare const findRenderers: Pick<ToolDefinition<any, any>, "renderCall" | "renderResult">;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation for the find tool.
|
|
3
|
+
*
|
|
4
|
+
* Renderers live apart from the implementation so a process that only displays tool output does not
|
|
5
|
+
* load the execution path or its typebox parameter schema. `find.ts` spreads these into its
|
|
6
|
+
* definition, so the tool's public shape is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
9
|
+
import { keyHint } from "../../../modes/interactive/components/keybinding-hints.js";
|
|
10
|
+
import { getTextOutput, invalidArgText, shortenPath, str } from "../render-utils.js";
|
|
11
|
+
import { DEFAULT_MAX_BYTES, formatSize } from "../truncate.js";
|
|
12
|
+
function formatFindCall(args, theme) {
|
|
13
|
+
const pattern = str(args?.pattern);
|
|
14
|
+
const rawPath = str(args?.path);
|
|
15
|
+
const path = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
16
|
+
const limit = args?.limit;
|
|
17
|
+
const invalidArg = invalidArgText(theme);
|
|
18
|
+
let text = theme.fg("toolTitle", theme.bold("find")) +
|
|
19
|
+
" " +
|
|
20
|
+
(pattern === null ? invalidArg : theme.fg("accent", pattern || "")) +
|
|
21
|
+
theme.fg("toolOutput", ` in ${path === null ? invalidArg : path}`);
|
|
22
|
+
if (limit !== undefined) {
|
|
23
|
+
text += theme.fg("toolOutput", ` (limit ${limit})`);
|
|
24
|
+
}
|
|
25
|
+
return text;
|
|
26
|
+
}
|
|
27
|
+
function formatFindResult(result, options, theme, showImages) {
|
|
28
|
+
const output = getTextOutput(result, showImages).trim();
|
|
29
|
+
let text = "";
|
|
30
|
+
if (output) {
|
|
31
|
+
const lines = output.split("\n");
|
|
32
|
+
const maxLines = options.expanded ? lines.length : 20;
|
|
33
|
+
const displayLines = lines.slice(0, maxLines);
|
|
34
|
+
const remaining = lines.length - maxLines;
|
|
35
|
+
text += `\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
36
|
+
if (remaining > 0) {
|
|
37
|
+
text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const resultLimit = result.details?.resultLimitReached;
|
|
41
|
+
const truncation = result.details?.truncation;
|
|
42
|
+
if (resultLimit || truncation?.truncated) {
|
|
43
|
+
const warnings = [];
|
|
44
|
+
if (resultLimit)
|
|
45
|
+
warnings.push(`${resultLimit} results limit`);
|
|
46
|
+
if (truncation?.truncated)
|
|
47
|
+
warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
|
|
48
|
+
text += `\n${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
|
|
49
|
+
}
|
|
50
|
+
return text;
|
|
51
|
+
}
|
|
52
|
+
export const findRenderers = {
|
|
53
|
+
renderCall(args, theme, context) {
|
|
54
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
55
|
+
text.setText(formatFindCall(args, theme));
|
|
56
|
+
return text;
|
|
57
|
+
},
|
|
58
|
+
renderResult(result, options, theme, context) {
|
|
59
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
60
|
+
text.setText(formatFindResult(result, options, theme, context.showImages));
|
|
61
|
+
return text;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation for the grep tool.
|
|
3
|
+
*
|
|
4
|
+
* Renderers live apart from the implementation so a process that only displays tool output does not
|
|
5
|
+
* load the execution path or its typebox parameter schema. `grep.ts` spreads these into its
|
|
6
|
+
* definition, so the tool's public shape is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import type { ToolDefinition } from "../../extensions/types.ts";
|
|
9
|
+
export declare const grepRenderers: Pick<ToolDefinition<any, any>, "renderCall" | "renderResult">;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presentation for the grep tool.
|
|
3
|
+
*
|
|
4
|
+
* Renderers live apart from the implementation so a process that only displays tool output does not
|
|
5
|
+
* load the execution path or its typebox parameter schema. `grep.ts` spreads these into its
|
|
6
|
+
* definition, so the tool's public shape is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
9
|
+
import { keyHint } from "../../../modes/interactive/components/keybinding-hints.js";
|
|
10
|
+
import { getTextOutput, invalidArgText, shortenPath, str } from "../render-utils.js";
|
|
11
|
+
import { DEFAULT_MAX_BYTES, formatSize } from "../truncate.js";
|
|
12
|
+
function formatGrepCall(args, theme) {
|
|
13
|
+
const pattern = str(args?.pattern);
|
|
14
|
+
const rawPath = str(args?.path);
|
|
15
|
+
const path = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
16
|
+
const glob = str(args?.glob);
|
|
17
|
+
const limit = args?.limit;
|
|
18
|
+
const invalidArg = invalidArgText(theme);
|
|
19
|
+
let text = theme.fg("toolTitle", theme.bold("grep")) +
|
|
20
|
+
" " +
|
|
21
|
+
(pattern === null ? invalidArg : theme.fg("accent", `/${pattern || ""}/`)) +
|
|
22
|
+
theme.fg("toolOutput", ` in ${path === null ? invalidArg : path}`);
|
|
23
|
+
if (glob)
|
|
24
|
+
text += theme.fg("toolOutput", ` (${glob})`);
|
|
25
|
+
if (limit !== undefined)
|
|
26
|
+
text += theme.fg("toolOutput", ` limit ${limit}`);
|
|
27
|
+
return text;
|
|
28
|
+
}
|
|
29
|
+
function formatGrepResult(result, options, theme, showImages) {
|
|
30
|
+
const output = getTextOutput(result, showImages).trim();
|
|
31
|
+
let text = "";
|
|
32
|
+
if (output) {
|
|
33
|
+
const lines = output.split("\n");
|
|
34
|
+
const maxLines = options.expanded ? lines.length : 15;
|
|
35
|
+
const displayLines = lines.slice(0, maxLines);
|
|
36
|
+
const remaining = lines.length - maxLines;
|
|
37
|
+
text += `\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
38
|
+
if (remaining > 0) {
|
|
39
|
+
text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const matchLimit = result.details?.matchLimitReached;
|
|
43
|
+
const truncation = result.details?.truncation;
|
|
44
|
+
const linesTruncated = result.details?.linesTruncated;
|
|
45
|
+
if (matchLimit || truncation?.truncated || linesTruncated) {
|
|
46
|
+
const warnings = [];
|
|
47
|
+
if (matchLimit)
|
|
48
|
+
warnings.push(`${matchLimit} matches limit`);
|
|
49
|
+
if (truncation?.truncated)
|
|
50
|
+
warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);
|
|
51
|
+
if (linesTruncated)
|
|
52
|
+
warnings.push("some lines truncated");
|
|
53
|
+
text += `\n${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
|
|
54
|
+
}
|
|
55
|
+
return text;
|
|
56
|
+
}
|
|
57
|
+
export const grepRenderers = {
|
|
58
|
+
renderCall(args, theme, context) {
|
|
59
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
60
|
+
text.setText(formatGrepCall(args, theme));
|
|
61
|
+
return text;
|
|
62
|
+
},
|
|
63
|
+
renderResult(result, options, theme, context) {
|
|
64
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
65
|
+
text.setText(formatGrepResult(result, options, theme, context.showImages));
|
|
66
|
+
return text;
|
|
67
|
+
},
|
|
68
|
+
};
|