@selesai/code 0.13.16 → 0.13.19
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 +41 -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/agent-browser.ts +1 -2
- package/dist/extensions/package.json +0 -1
- 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-web-agent/README.md +6 -5
- package/dist/extensions/pi-web-agent/src/backends/config.ts +12 -6
- package/dist/extensions/pi-web-agent/src/backends/factory.ts +2 -2
- package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +4 -5
- package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +8 -8
- package/dist/extensions/pi-web-agent/src/extension.ts +3 -3
- package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +2 -2
- package/dist/extensions/pi-web-agent/src/search/tokenin.ts +14 -3
- 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 +6 -6
- 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/extensions/web-agent-onboarding.test.ts +0 -415
- package/dist/extensions/web-agent-onboarding.ts +0 -222
- 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
|
@@ -16,18 +16,18 @@ One public tool, `web_explore`, that does bounded web research for Pi: search, f
|
|
|
16
16
|
|
|
17
17
|
- **One tool.** `web_explore` handles direct links, discovery, HTTP reads, targeted headless rendering, source ranking, source-quality checks, and caveats internally.
|
|
18
18
|
- **Reads the real content behind links.** Paste a GitHub, PDF, or YouTube URL and it pulls the actual thing (GitHub files/issues/PRs from the API, PDF text, YouTube transcripts), keyless. So "summarize this PDF" or "what does this repo do" works off the source, not the page shell.
|
|
19
|
-
- **
|
|
19
|
+
- **Seven search backends.** TokenIn (default with an active account), DuckDuckGo (keyless otherwise), SearXNG, Brave, You.com, Exa, Tavily.
|
|
20
20
|
- **Optional search fanout.** Query several backends at once, dedupe, and rank pages that more than one provider agreed on to the top. Off by default; flip it to `on` or `auto`.
|
|
21
21
|
- **Honest by default.** Weak, narrow, blocked, or cautionary evidence gets flagged instead of dressed up as confidence.
|
|
22
22
|
- **Bounded output.** `compact` / `preview` / `verbose` transcript modes.
|
|
23
|
-
- **Zero-config to start.**
|
|
23
|
+
- **Zero-config to start.** Without an active TokenIn account, runs keyless out of the box (DuckDuckGo search, local browser, the built-in readers). Opt into hosted backends, fallback, search fanout, and per-tool output modes through config when you want more control.
|
|
24
24
|
|
|
25
25
|
## Why pi-web-agent
|
|
26
26
|
|
|
27
27
|
Compared to other web tooling for agents:
|
|
28
28
|
|
|
29
29
|
- **Hands-off.** No curator, no browser windows to approve, no step that pops you out of your session. Ask `web_explore` once and the answer comes back with caveats. Nothing to babysit.
|
|
30
|
-
- **Keyless
|
|
30
|
+
- **Keyless without TokenIn.** Search, page reads, and the GitHub/PDF/YouTube readers all work with no API keys when TokenIn is not configured. Add hosted providers only when you want them.
|
|
31
31
|
- **Bounded and honest.** Compact output by default, and it says when a read was not good enough instead of returning fake confidence.
|
|
32
32
|
|
|
33
33
|
## Install
|
|
@@ -63,11 +63,12 @@ If a pass comes back thin, call `web_explore` again with a narrower query.
|
|
|
63
63
|
|
|
64
64
|
## Backends
|
|
65
65
|
|
|
66
|
-
Defaults are
|
|
66
|
+
Defaults are TokenIn search when an active TokenIn account exists, otherwise DuckDuckGo search; fetch remains plain HTTP and headless remains local-browser. Switch providers from `/web-agent settings → Backends`. API keys stay in environment variables, never in config files.
|
|
67
67
|
|
|
68
68
|
| Backend | Role | Enable with |
|
|
69
69
|
| --- | --- | --- |
|
|
70
|
-
|
|
|
70
|
+
| TokenIn | search (default with an active account) | `/tokenin add` |
|
|
71
|
+
| DuckDuckGo | search (default without TokenIn) | nothing, keyless |
|
|
71
72
|
| SearXNG | search (self-hosted) | base URL |
|
|
72
73
|
| Brave | search (hosted) | `PI_WEB_AGENT_BRAVE_API_KEY` |
|
|
73
74
|
| You.com | search (hosted) | `YDC_API_KEY` |
|
|
@@ -54,11 +54,17 @@ export type BackendConfigFile = {
|
|
|
54
54
|
};
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
export
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
export function getDefaultBackendConfig(
|
|
58
|
+
hasActiveAccount: () => boolean = hasActiveTokenInAccount
|
|
59
|
+
): BackendConfig {
|
|
60
|
+
return {
|
|
61
|
+
search: hasActiveAccount()
|
|
62
|
+
? { provider: 'tokenin', fallback: 'duckduckgo' }
|
|
63
|
+
: { provider: 'duckduckgo' },
|
|
64
|
+
fetch: { provider: 'http' },
|
|
65
|
+
headless: { provider: 'local-browser' }
|
|
66
|
+
};
|
|
67
|
+
}
|
|
62
68
|
|
|
63
69
|
function extractStringArray(value: unknown): string[] | undefined {
|
|
64
70
|
if (!Array.isArray(value)) return undefined;
|
|
@@ -260,6 +266,6 @@ export function mergeBackendConfigLayers(
|
|
|
260
266
|
fetch: mergeFetchConfig(merged.fetch, layer?.fetch),
|
|
261
267
|
headless: { ...merged.headless, ...layer?.headless }
|
|
262
268
|
}),
|
|
263
|
-
|
|
269
|
+
getDefaultBackendConfig()
|
|
264
270
|
);
|
|
265
271
|
}
|
|
@@ -13,7 +13,7 @@ import { createWebFetchTool } from '../tools/web-fetch.js';
|
|
|
13
13
|
import { createWebSearchTool } from '../tools/web-search.js';
|
|
14
14
|
import { readBraveKeyFromSettings } from './settings-reader.js';
|
|
15
15
|
import type { SearchProviderName, WebFetchHeadlessResponse, WebFetchResponse, WebSearchResponse } from '../types.js';
|
|
16
|
-
import {
|
|
16
|
+
import { getDefaultBackendConfig, type BackendConfig, usableSearchProviders } from './config.js';
|
|
17
17
|
import { createSpecialContentResolver } from '../readers/resolver.js';
|
|
18
18
|
import { createGithubReader } from '../readers/github-reader.js';
|
|
19
19
|
import { createPdfReader } from '../readers/pdf-reader.js';
|
|
@@ -117,7 +117,7 @@ function withFetchFallback(
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
export function createBackendSet(
|
|
120
|
-
config: BackendConfig =
|
|
120
|
+
config: BackendConfig = getDefaultBackendConfig(),
|
|
121
121
|
deps: BackendFactoryDeps = {}
|
|
122
122
|
): BackendSet {
|
|
123
123
|
const createDuckDuckGoSearch = deps.createDuckDuckGoSearch ?? createWebSearchTool;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
// ponytail:
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// helper needs updating; upgrade path = upstream pi-web-agent adopting a settings hook.
|
|
1
|
+
// ponytail: preserve existing manually configured Brave keys in settings.json
|
|
2
|
+
// (webAgent.braveApiKey). Upstream pi-web-agent reads only PI_WEB_AGENT_BRAVE_API_KEY.
|
|
3
|
+
// Ceiling: if selesai moves web search config elsewhere, update this helper; upgrade path =
|
|
4
|
+
// upstream pi-web-agent adopting a settings hook.
|
|
6
5
|
import { existsSync, readFileSync } from 'node:fs';
|
|
7
6
|
import { join } from 'node:path';
|
|
8
7
|
import { getAgentDir, getSettingsPath } from '@selesai/code';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
getDefaultBackendConfig,
|
|
3
3
|
mergeBackendConfigLayers,
|
|
4
4
|
validateBackendConfig,
|
|
5
5
|
usableSearchProviders,
|
|
@@ -150,7 +150,7 @@ function formatFetchOptions(config: BackendConfig['fetch']) {
|
|
|
150
150
|
].filter(Boolean).join(' ');
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
function formatBackendSummary(config: BackendConfig =
|
|
153
|
+
function formatBackendSummary(config: BackendConfig = getDefaultBackendConfig()) {
|
|
154
154
|
const searchSuffix = formatSearchOptions(config.search);
|
|
155
155
|
const fetchSuffix = formatFetchOptions(config.fetch);
|
|
156
156
|
const searchBase = config.search.baseUrl
|
|
@@ -394,10 +394,10 @@ export function getInheritedBackendsForScope(
|
|
|
394
394
|
scope: PresentationScope
|
|
395
395
|
): BackendConfig {
|
|
396
396
|
if (scope === 'global') {
|
|
397
|
-
return
|
|
397
|
+
return getDefaultBackendConfig();
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
return mergeBackendConfigLayers(
|
|
400
|
+
return mergeBackendConfigLayers(getDefaultBackendConfig(), loaded.global.rawBackends);
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
export function getScopeDisplayBackends(
|
|
@@ -405,11 +405,11 @@ export function getScopeDisplayBackends(
|
|
|
405
405
|
scope: PresentationScope
|
|
406
406
|
): BackendConfig {
|
|
407
407
|
if (scope === 'global') {
|
|
408
|
-
return mergeBackendConfigLayers(
|
|
408
|
+
return mergeBackendConfigLayers(getDefaultBackendConfig(), loaded.global.rawBackends);
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
return mergeBackendConfigLayers(
|
|
412
|
-
|
|
412
|
+
getDefaultBackendConfig(),
|
|
413
413
|
loaded.global.rawBackends,
|
|
414
414
|
loaded.project.rawBackends
|
|
415
415
|
);
|
|
@@ -942,7 +942,7 @@ export function registerWebAgentConfigCommands(pi: ExtensionAPI, deps: CommandDe
|
|
|
942
942
|
|
|
943
943
|
if (action === 'doctor') {
|
|
944
944
|
const [typeboxOk, browser, loaded] = await Promise.all([checkTypebox(), resolveBrowser(), load()]);
|
|
945
|
-
const backendConfig = loaded.effectiveBackends ??
|
|
945
|
+
const backendConfig = loaded.effectiveBackends ?? getDefaultBackendConfig();
|
|
946
946
|
const backendIssues = validateBackendConfig(backendConfig);
|
|
947
947
|
const backendHealth = await checkBackends(backendConfig);
|
|
948
948
|
const lines = [
|
|
@@ -971,7 +971,7 @@ export function registerWebAgentConfigCommands(pi: ExtensionAPI, deps: CommandDe
|
|
|
971
971
|
ctx.ui.notify(
|
|
972
972
|
[
|
|
973
973
|
formatConfigSummary(loaded.effectiveConfig),
|
|
974
|
-
formatBackendSummary(loaded.effectiveBackends ??
|
|
974
|
+
formatBackendSummary(loaded.effectiveBackends ?? getDefaultBackendConfig()),
|
|
975
975
|
`global: ${loaded.global.path}${loaded.global.exists ? '' : ' (missing)'}`,
|
|
976
976
|
`project: ${loaded.project.path}${loaded.project.exists ? '' : ' (missing)'}`
|
|
977
977
|
].join('\n'),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from '@selesai/code';
|
|
2
|
-
import {
|
|
2
|
+
import { getDefaultBackendConfig, type BackendConfig } from './backends/config.js';
|
|
3
3
|
import { Type } from 'typebox';
|
|
4
4
|
import { registerWebAgentConfigCommands } from './commands/web-agent-config.js';
|
|
5
5
|
import { DEFAULT_PRESENTATION_CONFIG, resolvePresentationMode } from './presentation/config.js';
|
|
@@ -60,9 +60,9 @@ async function getEffectivePresentationConfig(pi: ExtensionAPI): Promise<Present
|
|
|
60
60
|
async function getEffectiveBackendConfig(pi: ExtensionAPI): Promise<BackendConfig> {
|
|
61
61
|
try {
|
|
62
62
|
const loaded = await loadWebAgentConfig(pi);
|
|
63
|
-
return loaded.effectiveBackends ??
|
|
63
|
+
return loaded.effectiveBackends ?? getDefaultBackendConfig();
|
|
64
64
|
} catch {
|
|
65
|
-
return
|
|
65
|
+
return getDefaultBackendConfig();
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -2,7 +2,7 @@ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { CONFIG_DIR_NAME, getAgentDir } from '@selesai/code';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
getDefaultBackendConfig,
|
|
6
6
|
extractBackendConfigOverride,
|
|
7
7
|
mergeBackendConfigLayers,
|
|
8
8
|
type BackendConfig,
|
|
@@ -162,7 +162,7 @@ export async function loadPresentationConfigLayers(
|
|
|
162
162
|
project.rawConfig
|
|
163
163
|
),
|
|
164
164
|
effectiveBackends: mergeBackendConfigLayers(
|
|
165
|
-
|
|
165
|
+
getDefaultBackendConfig(),
|
|
166
166
|
global.rawBackends,
|
|
167
167
|
project.rawBackends
|
|
168
168
|
)
|
|
@@ -6,6 +6,7 @@ import type { SearchResult, WebSearchResponse } from '../types.js';
|
|
|
6
6
|
|
|
7
7
|
export const TOKENIN_SEARCH_TOOL_NAME = 'firecrawl';
|
|
8
8
|
export const TOKENIN_DEFAULT_BASE_URL = 'https://lite.andlet.me/v1';
|
|
9
|
+
const TOKENIN_SEARCH_TIMEOUT_MS = 10_000;
|
|
9
10
|
|
|
10
11
|
type TokenInAccount = { id: string; label: string; apiKey: string; baseUrl?: string };
|
|
11
12
|
type TokenInAuth = { accounts: TokenInAccount[]; activeId: string | null };
|
|
@@ -54,10 +55,12 @@ function normalizeResults(response: LiteLLMSearchResponse): SearchResult[] {
|
|
|
54
55
|
|
|
55
56
|
export function createTokenInSearchTool({
|
|
56
57
|
readAccount = readActiveTokenInAccount,
|
|
57
|
-
fetchImpl = fetch
|
|
58
|
+
fetchImpl = fetch,
|
|
59
|
+
timeoutMs = TOKENIN_SEARCH_TIMEOUT_MS
|
|
58
60
|
}: {
|
|
59
61
|
readAccount?: () => TokenInAccount | undefined;
|
|
60
62
|
fetchImpl?: typeof fetch;
|
|
63
|
+
timeoutMs?: number;
|
|
61
64
|
} = {}) {
|
|
62
65
|
return async function tokenInSearch({ query }: { query: string }): Promise<WebSearchResponse> {
|
|
63
66
|
const normalizedQuery = query.trim();
|
|
@@ -89,6 +92,9 @@ export function createTokenInSearchTool({
|
|
|
89
92
|
.replace(/\/v1$/, '');
|
|
90
93
|
const url = `${rootUrl}/v1/search/${TOKENIN_SEARCH_TOOL_NAME}`;
|
|
91
94
|
|
|
95
|
+
const controller = new AbortController();
|
|
96
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
97
|
+
|
|
92
98
|
try {
|
|
93
99
|
const response = await fetchImpl(url, {
|
|
94
100
|
method: 'POST',
|
|
@@ -97,7 +103,8 @@ export function createTokenInSearchTool({
|
|
|
97
103
|
'Content-Type': 'application/json',
|
|
98
104
|
Authorization: `Bearer ${account.apiKey}`
|
|
99
105
|
},
|
|
100
|
-
body: JSON.stringify({ query: normalizedQuery, max_results: 10 })
|
|
106
|
+
body: JSON.stringify({ query: normalizedQuery, max_results: 10 }),
|
|
107
|
+
signal: controller.signal
|
|
101
108
|
});
|
|
102
109
|
|
|
103
110
|
if (!response.ok) {
|
|
@@ -122,13 +129,17 @@ export function createTokenInSearchTool({
|
|
|
122
129
|
metadata: { backend: 'tokenin', cacheHit: false }
|
|
123
130
|
});
|
|
124
131
|
} catch (error) {
|
|
125
|
-
const rawMessage =
|
|
132
|
+
const rawMessage = controller.signal.aborted
|
|
133
|
+
? `Token-In search timed out after ${timeoutMs}ms.`
|
|
134
|
+
: error instanceof Error ? error.message : String(error);
|
|
126
135
|
return resultWithPresentation({
|
|
127
136
|
status: 'error',
|
|
128
137
|
results: [],
|
|
129
138
|
metadata: { backend: 'tokenin', cacheHit: false },
|
|
130
139
|
error: { code: 'FETCH_FAILED', message: `Token-In search request failed: ${rawMessage}` }
|
|
131
140
|
});
|
|
141
|
+
} finally {
|
|
142
|
+
clearTimeout(timeout);
|
|
132
143
|
}
|
|
133
144
|
};
|
|
134
145
|
}
|
|
@@ -37,6 +37,8 @@ Editor, User messages, Thinking (Experimental), Working line, and selector borde
|
|
|
37
37
|
|
|
38
38
|
The Starship Footer shows directory, Git, runtime, context, tokens, and cost. Optional segments include model/provider, package version, session duration, `user@host`, time, OS, Git commit, Git metrics, and third-party extension statuses. The layout is segment-driven by default and supports a complete Starship-style format template.
|
|
39
39
|
|
|
40
|
+
When the Working line is enabled, third-party extensions can publish keyed text segments through Pi's shared event bus. Zentui composes those segments into the owned row so Classic and KITT animate across them with the built-in content. See the [Working-line extension integration](https://github.com/lmilojevicc/pi-zentui/blob/main/docs/configuration.md#working-line-extension-integration) reference.
|
|
41
|
+
|
|
40
42
|
Zentui detects a broad set of runtime and language modules, preserves Nerd Font icons with an ASCII mode, and can source colors from the active Pi theme or directly from the terminal palette.
|
|
41
43
|
|
|
42
44
|
## Screenshots
|
|
@@ -95,6 +97,21 @@ Run `/zentui` inside Pi to configure Appearance, Editor, User messages, Thinking
|
|
|
95
97
|
~/.pi/agent/zentui.json
|
|
96
98
|
```
|
|
97
99
|
|
|
100
|
+
### Component presets
|
|
101
|
+
|
|
102
|
+
Choose **Appearance → Preset** in `/zentui`, or run `/zentui preset <id>`:
|
|
103
|
+
|
|
104
|
+
| ID | Editor (enabled) | Footer | User messages |
|
|
105
|
+
| --- | --- | --- | --- |
|
|
106
|
+
| `opencode` | Opencode | Starship | Framed |
|
|
107
|
+
| `opencode-copy-friendly` | Opencode (copy-friendly) | Starship | Framed (copy-friendly) |
|
|
108
|
+
| `rail` | Accent Rail | Starship | Compact (accent rail) |
|
|
109
|
+
| `minimalist` | Minimalist | Hidden (zero rows) | Zentui styling disabled |
|
|
110
|
+
|
|
111
|
+
Presets apply once, saving only these component selections. Colors, color sources, style options, icons, Footer segments/formats, selector borders, Working line, and Thinking remain unchanged. Minimalist preserves the dormant message style and leaves Pi's native message presentation alone. Hidden suppresses the Footer; it is not Native.
|
|
112
|
+
|
|
113
|
+
The displayed preset is derived from your current selections: individual changes may show **Custom**, and returning to a matching combination restores its name. No `preset` config key is saved or reapplied at startup. Defaults are unchanged and match Opencode. Selecting a preset keeps settings open for further adjustments. Editor installation waits until the panel closes; if editor ownership prevents application, the saved choice may require reloading Pi.
|
|
114
|
+
|
|
98
115
|
A small starter config:
|
|
99
116
|
|
|
100
117
|
```json
|
|
@@ -8,7 +8,7 @@ Zentui reads optional user configuration from `~/.pi/agent/zentui.json`. Missing
|
|
|
8
8
|
|
|
9
9
|
The interactive `/zentui` menu is split into nine component-oriented sections. Use `Tab` and `Shift+Tab` to switch sections:
|
|
10
10
|
|
|
11
|
-
1. **Appearance** — selector-border enablement, style, and colors; icon mode.
|
|
11
|
+
1. **Appearance** — component Preset; selector-border enablement, style, and colors; icon mode.
|
|
12
12
|
2. **Editor** — enablement, style, colors, model label, border behavior, viewport indicators, settings for the selected editor style, and a static synthetic preview.
|
|
13
13
|
3. **User messages** — enablement, style, colors, and a static synthetic Markdown preview.
|
|
14
14
|
4. **Thinking (Experimental)** — private Rail, Tree, or Streaming rendering; active Streaming can switch live to Rail or Tree, Rail and Tree can switch live between each other, and the private renderer may break after Pi updates.
|
|
@@ -45,6 +45,44 @@ Useful slash-command shortcuts:
|
|
|
45
45
|
|
|
46
46
|
`footer`, `statusline`, `status`, and `status line` are aliases. Enable selects Starship, disable selects Native, and toggle selects Native only from Starship; Native or Hidden toggle to Starship.
|
|
47
47
|
|
|
48
|
+
### Component presets
|
|
49
|
+
|
|
50
|
+
Use the first **Appearance → Preset** row, or one of these exact commands:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
/zentui preset opencode
|
|
54
|
+
/zentui preset opencode-copy-friendly
|
|
55
|
+
/zentui preset rail
|
|
56
|
+
/zentui preset minimalist
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Preset ID | `components.editor` | `components.footer.style` | `components.userMessages` |
|
|
60
|
+
| --- | --- | --- | --- |
|
|
61
|
+
| `opencode` | `enabled: true`, `style: "opencode"` | `"starship"` | `enabled: true`, `style: "framed"` |
|
|
62
|
+
| `opencode-copy-friendly` | `enabled: true`, `style: "opencode-copy-friendly"` | `"starship"` | `enabled: true`, `style: "framed-copy-friendly"` |
|
|
63
|
+
| `rail` | `enabled: true`, `style: "accent-rail"` | `"starship"` | `enabled: true`, `style: "compact"` |
|
|
64
|
+
| `minimalist` | `enabled: true`, `style: "minimalist"` | `"hidden"` | `enabled: false` (style preserved) |
|
|
65
|
+
|
|
66
|
+
These are one-time, atomic selection patches, not ongoing profiles. Only the listed leaves are written, with the existing obsolete copy-friendly/Footer-enabled migration flags removed when their styles are explicitly selected. Colors and color sources, per-style options, icons, Footer segments/templates/path settings, all other components, and unknown fields remain untouched. Unsupported future style IDs are preserved unless the preset explicitly replaces that style; Minimalist even preserves an unsupported dormant message style. Existing legacy option resolution continues to work.
|
|
67
|
+
|
|
68
|
+
**Custom** is a derived display state, not a selectable preset or a saved key. Matching checks only the listed selection leaves, not colors/options or current runtime ownership; Minimalist ignores dormant message style. Unsupported active selected styles do not match. Hand-editing or individually changing a selection can show Custom; returning to a matching combination restores the preset label. No `preset` config key is used, and nothing is automatically reapplied on startup. New-install defaults remain unchanged and match Opencode.
|
|
69
|
+
|
|
70
|
+
The existing Minimalist editor stays enabled with its saved metadata/options. Disabled User messages releases only Zentui styling, leaving native or predecessor rendering intact. Hidden installs an owned zero-row Footer, whereas Native releases Zentui's Footer to Pi or a predecessor; `/zentui statusline disable` still selects Native, not Hidden.
|
|
71
|
+
|
|
72
|
+
Selecting presets keeps the settings panel open and preserves its focus. Config, Footer, and User messages update immediately; editor installation waits until the panel closes and Pi restores the draft. Only the latest editor settings are reconciled on exit, and shutdown cancels pending installation. With public editor-text APIs available, opening settings expands nonempty drafts before Pi snapshots them, preserving collapsed paste contents; this can move the cursor to the end and add an undo step. Empty drafts are untouched. Older hosts without these APIs retain Pi's existing draft-restoration behavior. Saves fail without changing active settings or overwriting corrupt/unreadable JSON. Live application reconciles only Editor, User messages, Footer, and dependent timers. Editor ownership restrictions are reported as saved-but-not-applied/reload-required; Footer host failures retain existing fail-open behavior. Direct preset commands also save in non-TUI modes without installing TUI components. Unknown IDs, missing IDs, and extra arguments do not change settings.
|
|
73
|
+
|
|
74
|
+
### Extension-status hyperlinks
|
|
75
|
+
|
|
76
|
+
An extension's **Original** color mode preserves SGR styling and HTTP/HTTPS
|
|
77
|
+
OSC 8 hyperlinks supplied by that extension. For example, set
|
|
78
|
+
`components.footer.styles.starship.extensionStatuses.colorModes.github-pr` to
|
|
79
|
+
`"original"` to retain a PR link from a GitHub status extension. Open it with
|
|
80
|
+
your terminal's link-opening gesture. Other URL schemes and unrelated terminal
|
|
81
|
+
controls (including clipboard, title, and cursor commands) are removed.
|
|
82
|
+
|
|
83
|
+
Zentui color mode continues to show plain status text. Zentui does not infer a
|
|
84
|
+
URL when an extension supplies only a label.
|
|
85
|
+
|
|
48
86
|
## Complete default configuration
|
|
49
87
|
|
|
50
88
|
Copy this example and change only the values you need. Optional editor source-aware overrides such as `editorRail`, `editorGitBranch`, and `editorThinkingMax` are intentionally omitted.
|
|
@@ -428,7 +466,38 @@ Classic and KITT move color across message and segments. **Animate spinner color
|
|
|
428
466
|
|
|
429
467
|
Both speeds accept `30..1000` ms. Classic/KITT combine both cadences through one Pi Loader interval; exact cycles are used within 1024-frame/512-KiB limits. Pathological custom pairs use a bounded evenly distributed schedule with at most half a spinner-cycle and half a text-step rounding. Legacy `intervalMs` is accepted only as migration input for `spinnerIntervalMs` when the canonical field is absent.
|
|
430
468
|
|
|
431
|
-
Content reserves the complete Tokens label first, then Message, Thought, Elapsed, and Tool allocation, while preserving visual order **Message · Tool · Elapsed · Thought · Tokens** within the 80-column Loader-row contract. Active thought starts as `thinking 0s`; completed positive thought becomes `thought for Ns`. Rebuilds preserve spinner and visible color phase. Pi's working-row APIs are global and unkeyed, so another extension may win by writing last.
|
|
469
|
+
Content reserves the complete Tokens label and active extension segments first, then Message, Thought, Elapsed, and Tool allocation, while preserving visual order **Message · Tool · Elapsed · Thought · Tokens · Extensions** within the 80-column Loader-row contract. Active thought starts as `thinking 0s`; completed positive thought becomes `thought for Ns`. Rebuilds preserve spinner and visible color phase. Pi's working-row APIs are global and unkeyed, so another extension may win by writing last.
|
|
470
|
+
|
|
471
|
+
### Working-line extension integration
|
|
472
|
+
|
|
473
|
+
Third-party extensions can add dynamic text to Zentui's owned Working line through Pi's shared event bus. Protocol version 1 uses keyed segments that are sanitized, ordered by key, width-bounded, and included in the same Classic/KITT animation frames as Zentui's built-in content.
|
|
474
|
+
|
|
475
|
+
Probe the capability when an interaction starts so an extension can fall back to Pi's public `setWorkingMessage()` slot when Zentui's Working line is unavailable:
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
const capability = { supported: false, active: false };
|
|
479
|
+
pi.events.emit("zentui:working-line-segment-capability", capability);
|
|
480
|
+
|
|
481
|
+
if (capability.active) {
|
|
482
|
+
pi.events.emit("zentui:working-line-segment", {
|
|
483
|
+
key: "@scope/my-extension:throughput",
|
|
484
|
+
text: "24.3 tok/s · TTFT 820ms",
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Update a segment by emitting the same key with new text. Remove it when the interaction settles or the publishing extension shuts down:
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
pi.events.emit("zentui:working-line-segment", {
|
|
493
|
+
key: "@scope/my-extension:throughput",
|
|
494
|
+
text: undefined,
|
|
495
|
+
});
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
All publishers share one global key namespace. Collisions are last-update-wins, and removal by either publisher removes the value for that key. Publishers must therefore use stable, package-qualified keys such as `@scope/package:segment`; each publisher owns removal and lifecycle cleanup for its keys. `text: ""` also removes a segment. Published state is scoped to the current session and Working-row ownership: Zentui discards it on a new session, disable, shutdown, or ownership release. Positive updates while capability is inactive are ignored rather than retained, so publishers must probe again and republish their current value after capability becomes active.
|
|
499
|
+
|
|
500
|
+
Zentui accepts at most 16 unique keys, keys up to 64 code units, and values up to 256 code units. Extra segments are omitted or truncated when the complete row reaches its fixed width. `supported` reports whether this Zentui version understands the protocol. Zentui also adds `version: 1` to the mutable capability response; probes that initialize only `supported` and `active`, as above, remain compatible. `active` additionally requires an enabled Working line in an active TUI session where Zentui successfully installed and still claims both required Pi working-row surfaces. Pi's unkeyed, last-writer-wins APIs provide no way to prove that another extension has not overwritten a surface after installation, so publishers should probe at each interaction and retain their normal fallback.
|
|
432
501
|
|
|
433
502
|
## Git status icons
|
|
434
503
|
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type ResolvedIcons,
|
|
25
25
|
resolveConfiguredIcons,
|
|
26
26
|
} from "./icons";
|
|
27
|
+
import type { ComponentPreset } from "./presets";
|
|
27
28
|
import { isSupportedColorSpec } from "./style";
|
|
28
29
|
import { normalizeWorkingLineMessages } from "./working-line";
|
|
29
30
|
import { PI_WORKING_LINE_MESSAGES } from "./working-line-messages";
|
|
@@ -1651,6 +1652,16 @@ function deleteLegacyMessageCopyFriendly(record: ConfigRecord): void {
|
|
|
1651
1652
|
if (isRecord(framed)) delete framed.copyFriendly;
|
|
1652
1653
|
}
|
|
1653
1654
|
|
|
1655
|
+
/** A preset is a one-time, selection-only transaction; do not normalize unrelated leaves. */
|
|
1656
|
+
export function saveComponentPreset(preset: ComponentPreset, path = configPath): PolishedTuiConfig {
|
|
1657
|
+
return mutateConfig(path, (record) => {
|
|
1658
|
+
record.components = overlayKnown(record.components, preset.components);
|
|
1659
|
+
deleteLegacyEditorCopyFriendly(record);
|
|
1660
|
+
deleteLegacyFooterEnabled(record);
|
|
1661
|
+
if (preset.components.userMessages.style !== undefined) deleteLegacyMessageCopyFriendly(record);
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1654
1665
|
function applyEditorComponentPatch(
|
|
1655
1666
|
component: EditorComponentConfig,
|
|
1656
1667
|
patch: Partial<
|
|
@@ -19,6 +19,20 @@ export type EditorTransferResult =
|
|
|
19
19
|
| { ok: true }
|
|
20
20
|
| { ok: false; reason: EditorTransferFailureReason };
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Pi custom UI saves raw editor text and restores it with setText(), which clears
|
|
24
|
+
* collapsed paste storage. Expand nonempty drafts before that snapshot is taken.
|
|
25
|
+
* Hosts without public text APIs retain their existing custom-UI behavior.
|
|
26
|
+
*/
|
|
27
|
+
export function prepareEditorTextForCustomUi(
|
|
28
|
+
ui: Pick<EditorTransferUi, "getEditorText" | "setEditorText">,
|
|
29
|
+
): void {
|
|
30
|
+
if (typeof ui.getEditorText !== "function" || typeof ui.setEditorText !== "function") return;
|
|
31
|
+
const text = ui.getEditorText();
|
|
32
|
+
if (typeof text !== "string") throw new Error("expanded editor text could not be read safely");
|
|
33
|
+
if (text) ui.setEditorText(text);
|
|
34
|
+
}
|
|
35
|
+
|
|
22
36
|
/**
|
|
23
37
|
* Prepare the active editor's public expanded text before Pi replaces its factory.
|
|
24
38
|
* This intentionally transfers prompt contents only; editor-private state is never inspected.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { stripVTControlCharacters } from "node:util";
|
|
2
3
|
import type { ExtensionStatusColorMode, ExtensionStatusPlacement, ZentuiConfig } from "./config";
|
|
3
4
|
import {
|
|
@@ -19,9 +20,6 @@ export type ExtensionStatusSegmentsByPlacement = {
|
|
|
19
20
|
right: ExtensionStatusSegment[];
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
const safeSgrPattern = /\x1b\[[0-9;:]*m/g;
|
|
23
|
-
const sgrPlaceholderPattern = /__ZENTUI_SGR_(\d+)__/g;
|
|
24
|
-
|
|
25
23
|
function compareKeys(a: ExtensionStatusSegment, b: ExtensionStatusSegment): number {
|
|
26
24
|
return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
|
|
27
25
|
}
|
|
@@ -43,18 +41,36 @@ function hasVisibleStatusText(value: string): boolean {
|
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
export function sanitizeExtensionStatusOriginalText(value: string): string {
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
// Preserve only SGR and HTTP(S) OSC 8 links. Never pass title/clipboard/cursor controls.
|
|
45
|
+
const marker = `__ZENTUI_${randomUUID()}_`;
|
|
46
|
+
const sequences: Array<{ sequence: string; url: string | undefined }> = [];
|
|
47
|
+
const protectedValue = value.replace(
|
|
48
|
+
/\x1b\[[0-9;:]*m|\x1b\]8;[^;\x07\x1b]*;([^\x07\x1b]*)(?:\x07|\x1b\\)/g,
|
|
49
|
+
(sequence, url: string | undefined) => `${marker}${sequences.push({ sequence, url }) - 1}__`,
|
|
50
|
+
);
|
|
51
51
|
const cleaned = normalizeStatusWhitespace(stripVTControlCharacters(protectedValue));
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
// Other controls can swallow placeholders. Track only sequences that survive
|
|
53
|
+
// stripping, including invalid targets that must end any surviving link.
|
|
54
|
+
let activeLink = false;
|
|
55
|
+
const restored = cleaned.replace(new RegExp(`${marker}(\\d+)__`, "g"), (_match, index) => {
|
|
56
|
+
const entry = sequences[Number(index)];
|
|
57
|
+
if (!entry) return "";
|
|
58
|
+
const { sequence, url } = entry;
|
|
59
|
+
if (url === undefined) return sequence;
|
|
60
|
+
const close = activeLink ? "\x1b]8;;\x07" : "";
|
|
61
|
+
activeLink = false;
|
|
62
|
+
if (!url || /[\s\x00-\x1f\x7f-\x9f]/.test(url)) return close;
|
|
63
|
+
try {
|
|
64
|
+
const parsed = new URL(url);
|
|
65
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return close;
|
|
66
|
+
activeLink = true;
|
|
67
|
+
return `${close}\x1b]8;;${parsed.href}\x07`;
|
|
68
|
+
} catch {
|
|
69
|
+
return close;
|
|
70
|
+
}
|
|
55
71
|
});
|
|
56
|
-
|
|
57
|
-
return hasVisibleStatusText(
|
|
72
|
+
const result = restored + (activeLink ? "\x1b]8;;\x07" : "");
|
|
73
|
+
return hasVisibleStatusText(result) ? result : "";
|
|
58
74
|
}
|
|
59
75
|
|
|
60
76
|
export function collectExtensionStatusSegments(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
2
2
|
import type { CompactFooterMaxLines } from "./config";
|
|
3
3
|
import type { CompactBoundaryKind } from "./footer-format";
|
|
4
|
+
import { truncateFooterText } from "./footer-text";
|
|
4
5
|
|
|
5
6
|
export type FooterZones = {
|
|
6
7
|
left: string;
|
|
@@ -59,7 +60,7 @@ function fitChunk(chunk: string, innerWidth: number): PackedRow {
|
|
|
59
60
|
return { text: chunk, endsWithRendererEllipsis: false };
|
|
60
61
|
}
|
|
61
62
|
return {
|
|
62
|
-
text:
|
|
63
|
+
text: truncateFooterText(chunk, innerWidth, "…"),
|
|
63
64
|
endsWithRendererEllipsis: true,
|
|
64
65
|
};
|
|
65
66
|
}
|
|
@@ -68,7 +69,7 @@ function appendOmissionMarker(row: PackedRow, innerWidth: number): PackedRow {
|
|
|
68
69
|
if (row.endsWithRendererEllipsis) return row;
|
|
69
70
|
if (innerWidth <= 1) return { text: "…", endsWithRendererEllipsis: true };
|
|
70
71
|
return {
|
|
71
|
-
text: `${
|
|
72
|
+
text: `${truncateFooterText(row.text, innerWidth - 1, "")}…`,
|
|
72
73
|
endsWithRendererEllipsis: true,
|
|
73
74
|
};
|
|
74
75
|
}
|
|
@@ -118,5 +119,5 @@ export function packCompactChunks(
|
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
if (current) rows.push(omitted ? appendOmissionMarker(current, innerWidth) : current);
|
|
121
|
-
return rows.map((row) =>
|
|
122
|
+
return rows.map((row) => truncateFooterText(row.text, innerWidth, ""));
|
|
122
123
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
|
|
3
|
+
/** Close retained links before joining/padding footer fragments, even on Pi < 0.84.0. */
|
|
4
|
+
export function truncateFooterText(text: string, width: number, ellipsis: string): string {
|
|
5
|
+
const truncated = truncateToWidth(text, width, ellipsis);
|
|
6
|
+
let activeLink = false;
|
|
7
|
+
for (const match of truncated.matchAll(/\x1b\]8;[^;\x07\x1b]*;([^\x07\x1b]*)(?:\x07|\x1b\\)/g)) {
|
|
8
|
+
activeLink = Boolean(match[1]);
|
|
9
|
+
}
|
|
10
|
+
return truncated + (activeLink ? "\x1b]8;;\x07" : "");
|
|
11
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import {
|
|
2
|
+
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
3
3
|
import type { SeparatorStyle, ZentuiConfig } from "./config";
|
|
4
4
|
import { FOOTER_FORMAT_ALIASES } from "./config";
|
|
5
5
|
import { sanitizeEditorMetadataText } from "./editor-metadata-format";
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
packCompactChunks,
|
|
23
23
|
reflowFullFooter,
|
|
24
24
|
} from "./footer-layout";
|
|
25
|
+
import { truncateFooterText } from "./footer-text";
|
|
25
26
|
import {
|
|
26
27
|
buildContextDisplayLabel,
|
|
27
28
|
buildSessionDurationLabel,
|
|
@@ -77,7 +78,7 @@ function fitStatusTexts(statusTexts: string[], maxWidth: number, separator: stri
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
if (fitted.length === 0) {
|
|
80
|
-
return maxWidth > 1 ?
|
|
81
|
+
return maxWidth > 1 ? truncateFooterText(text, maxWidth, "…") : "";
|
|
81
82
|
}
|
|
82
83
|
break;
|
|
83
84
|
}
|
|
@@ -101,10 +102,10 @@ function composeBuiltInFooterContent(left: string, right: string, innerWidth: nu
|
|
|
101
102
|
const leftWidth = visibleWidth(left);
|
|
102
103
|
const rightWidth = visibleWidth(right);
|
|
103
104
|
return leftWidth >= innerWidth
|
|
104
|
-
?
|
|
105
|
+
? truncateFooterText(left, innerWidth, "")
|
|
105
106
|
: leftWidth + 1 + rightWidth <= innerWidth
|
|
106
107
|
? `${left}${" ".repeat(innerWidth - leftWidth - rightWidth)}${right}`
|
|
107
|
-
:
|
|
108
|
+
: truncateFooterText(left, innerWidth, "");
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
function composeFooterContent(
|
|
@@ -700,8 +701,8 @@ export function installFooter(
|
|
|
700
701
|
);
|
|
701
702
|
const frameRows = (rows: string[]) =>
|
|
702
703
|
rows.map((row) => {
|
|
703
|
-
const framed = width > 2 ? ` ${
|
|
704
|
-
return
|
|
704
|
+
const framed = width > 2 ? ` ${truncateFooterText(row, width - 2, "")} ` : row;
|
|
705
|
+
return truncateFooterText(framed, width, "");
|
|
705
706
|
});
|
|
706
707
|
|
|
707
708
|
if (!config.components.footer.styles.starship.responsive)
|
|
@@ -732,8 +733,8 @@ export function installFooter(
|
|
|
732
733
|
if (reflowed) return frameRows(reflowed);
|
|
733
734
|
|
|
734
735
|
const chunkBudget = compactChunkBudget(innerWidth);
|
|
735
|
-
const compactCwdLabel =
|
|
736
|
-
const compactSessionNameLabel =
|
|
736
|
+
const compactCwdLabel = truncateFooterText(cwdLabel, chunkBudget, "…");
|
|
737
|
+
const compactSessionNameLabel = truncateFooterText(
|
|
737
738
|
sessionNameLabel,
|
|
738
739
|
Math.max(1, chunkBudget - visibleWidth("in ")),
|
|
739
740
|
"…",
|
|
@@ -742,7 +743,7 @@ export function installFooter(
|
|
|
742
743
|
1,
|
|
743
744
|
chunkBudget - visibleWidth("on ") - (statusBlock ? visibleWidth(statusBlock) + 1 : 0),
|
|
744
745
|
);
|
|
745
|
-
const compactBranchLabel =
|
|
746
|
+
const compactBranchLabel = truncateFooterText(
|
|
746
747
|
renderVariable("git_branch"),
|
|
747
748
|
compactBranchBudget,
|
|
748
749
|
"…",
|
|
@@ -784,7 +785,7 @@ export function installFooter(
|
|
|
784
785
|
);
|
|
785
786
|
const references = collectFooterFormatReferences(chunk.tokens, FOOTER_FORMAT_ALIASES);
|
|
786
787
|
if (["cwd", "session_name", "git_branch"].some((name) => references.has(name))) {
|
|
787
|
-
rendered =
|
|
788
|
+
rendered = truncateFooterText(rendered, chunkBudget, "…");
|
|
788
789
|
}
|
|
789
790
|
if (rendered) compactChunks.push({ text: rendered, boundary: chunk.boundary });
|
|
790
791
|
}
|