@selesai/code 0.13.15 → 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 +37 -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/capability-gateway/index.ts +12 -1
- package/dist/extensions/capability-gateway/integration.test.ts +23 -0
- 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/src/backends/config.ts +1 -0
- package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +5 -3
- package/dist/extensions/pi-web-agent/src/search/tokenin.ts +7 -3
- package/dist/extensions/pi-web-agent/src/types.ts +1 -1
- 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
|
@@ -179,6 +179,89 @@ describe('sqlite-memory-store', () => {
|
|
|
179
179
|
assert.deepStrictEqual(getMemories(dbManager, { project: 'spoofed-project' }), []);
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
+
it('reports a degraded result (not a swallowed success) on FTS5 index errors', () => {
|
|
183
|
+
// A genuine FTS5 search-index error must not look like a successful
|
|
184
|
+
// zero-row sync: the result carries degraded + reason so the caller can
|
|
185
|
+
// surface /memory-sync-markdown repair guidance.
|
|
186
|
+
const failingDb = {
|
|
187
|
+
prepare: (sql: string) => ({
|
|
188
|
+
get: () => undefined,
|
|
189
|
+
all: () => [],
|
|
190
|
+
run: () => {
|
|
191
|
+
throw new Error('fts5: table memory_fts is corrupted');
|
|
192
|
+
},
|
|
193
|
+
}),
|
|
194
|
+
} as never;
|
|
195
|
+
const stubDbManager = {
|
|
196
|
+
getDb: () => failingDb,
|
|
197
|
+
withCorruptionRecovery: <T>(operation: () => T): T => operation(),
|
|
198
|
+
} as unknown as DatabaseManager;
|
|
199
|
+
|
|
200
|
+
const result = reconcileMarkdownMemoryScope(
|
|
201
|
+
stubDbManager,
|
|
202
|
+
['degraded reconcile test entry'],
|
|
203
|
+
'memory',
|
|
204
|
+
null,
|
|
205
|
+
);
|
|
206
|
+
assert.equal(result.degraded, true);
|
|
207
|
+
assert.match(result.degradedReason ?? '', /fts5/);
|
|
208
|
+
assert.equal(result.inserted, 0);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('propagates degraded from failure scopes (first reason wins)', () => {
|
|
212
|
+
// When multiple failure scopes are degraded, the aggregate result must
|
|
213
|
+
// be degraded with the first reason (not the last) so the user sees the
|
|
214
|
+
// original failure, not a later duplicate.
|
|
215
|
+
let callCount = 0;
|
|
216
|
+
const failingDb = {
|
|
217
|
+
prepare: (sql: string) => ({
|
|
218
|
+
get: () => undefined,
|
|
219
|
+
all: () => [],
|
|
220
|
+
run: () => {
|
|
221
|
+
callCount++;
|
|
222
|
+
throw new Error(`fts5: error #${callCount}`);
|
|
223
|
+
},
|
|
224
|
+
}),
|
|
225
|
+
} as never;
|
|
226
|
+
const stubDbManager = {
|
|
227
|
+
getDb: () => failingDb,
|
|
228
|
+
withCorruptionRecovery: <T>(operation: () => T): T => operation(),
|
|
229
|
+
} as unknown as DatabaseManager;
|
|
230
|
+
|
|
231
|
+
const result = reconcileMarkdownFailureScopes(
|
|
232
|
+
stubDbManager,
|
|
233
|
+
[
|
|
234
|
+
'failure entry one — Project: project-a <!-- created=2026-01-01 -->',
|
|
235
|
+
'failure entry two — Project: project-b <!-- created=2026-01-01 -->',
|
|
236
|
+
],
|
|
237
|
+
);
|
|
238
|
+
assert.equal(result.degraded, true);
|
|
239
|
+
assert.match(result.degradedReason ?? '', /fts5: error #1/);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('still propagates corruption errors instead of degrading (recovery must run)', () => {
|
|
243
|
+
// Corruption signals are NOT FTS5 errors: they must escape so
|
|
244
|
+
// DatabaseManager quarantines + rebuilds, never a degraded zero-result.
|
|
245
|
+
const failingDb = {
|
|
246
|
+
prepare: () => ({
|
|
247
|
+
get: () => undefined,
|
|
248
|
+
all: () => [],
|
|
249
|
+
run: () => {
|
|
250
|
+
throw new Error('database disk image is malformed');
|
|
251
|
+
},
|
|
252
|
+
}),
|
|
253
|
+
} as never;
|
|
254
|
+
const stubDbManager = {
|
|
255
|
+
getDb: () => failingDb,
|
|
256
|
+
withCorruptionRecovery: <T>(operation: () => T): T => operation(),
|
|
257
|
+
} as unknown as DatabaseManager;
|
|
258
|
+
|
|
259
|
+
assert.throws(
|
|
260
|
+
() => reconcileMarkdownMemoryScope(stubDbManager, ['corruption test entry'], 'memory', null),
|
|
261
|
+
/malformed/,
|
|
262
|
+
);
|
|
263
|
+
});
|
|
264
|
+
|
|
182
265
|
it('prunes only absent rows in the exact target and project scope', () => {
|
|
183
266
|
addMemory(dbManager, 'kept global memory', 'memory', null);
|
|
184
267
|
addMemory(dbManager, 'orphaned global memory', 'memory', null);
|
|
@@ -333,6 +416,18 @@ describe('sqlite-memory-store', () => {
|
|
|
333
416
|
addMemory(dbManager, 'timezone: AEST', 'user');
|
|
334
417
|
});
|
|
335
418
|
|
|
419
|
+
it('degrades an all-stop-word query to the LIKE fallback instead of []', () => {
|
|
420
|
+
// "the" is a stop word and "and"/"or" connectors, so FTS5 normalization
|
|
421
|
+
// leaves nothing to match. The query must fall through to the scoped
|
|
422
|
+
// literal fallback (which still searches the raw terms) rather than
|
|
423
|
+
// hard-return an empty result set.
|
|
424
|
+
addMemory(dbManager, 'the build passes after restart');
|
|
425
|
+
|
|
426
|
+
const results = searchMemories(dbManager, 'the and or');
|
|
427
|
+
assert.ok(results.length > 0, 'all-stop-word query must reach the LIKE fallback, not []');
|
|
428
|
+
assert.ok(results.some(r => r.content.includes('the')));
|
|
429
|
+
});
|
|
430
|
+
|
|
336
431
|
it('should find memories by keyword', () => {
|
|
337
432
|
const results = searchMemories(dbManager, 'pnpm');
|
|
338
433
|
assert.ok(results.length > 0);
|
|
@@ -344,6 +439,36 @@ describe('sqlite-memory-store', () => {
|
|
|
344
439
|
assert.ok(results.length > 0);
|
|
345
440
|
assert.ok(results.some(r => r.content.includes('Prisma')));
|
|
346
441
|
});
|
|
442
|
+
|
|
443
|
+
it('returns only project-attributed memories for target "project"', () => {
|
|
444
|
+
const results = searchMemories(dbManager, 'Prisma', { target: 'project' });
|
|
445
|
+
|
|
446
|
+
assert.ok(results.length > 0);
|
|
447
|
+
assert.ok(results.every((r) => r.project === 'project-a'));
|
|
448
|
+
assert.ok(results.every((r) => r.target === 'memory'));
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('keeps target "memory" matching both global and project-attributed memories', () => {
|
|
452
|
+
const global = searchMemories(dbManager, 'pnpm', { target: 'memory' });
|
|
453
|
+
const project = searchMemories(dbManager, 'Prisma', { target: 'memory' });
|
|
454
|
+
|
|
455
|
+
assert.ok(global.some((r) => r.project === null));
|
|
456
|
+
assert.ok(project.length > 0);
|
|
457
|
+
assert.ok(project.every((r) => r.project === 'project-a'));
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it('combines target "project" with an explicit project filter', () => {
|
|
461
|
+
addMemory(dbManager, 'uses Bun with PostgreSQL', 'memory', 'project-b');
|
|
462
|
+
|
|
463
|
+
const named = searchMemories(dbManager, 'PostgreSQL', { target: 'project', project: 'project-b' });
|
|
464
|
+
const anyProject = searchMemories(dbManager, 'PostgreSQL', { target: 'project' });
|
|
465
|
+
const globalOnly = searchMemories(dbManager, 'PostgreSQL', { target: 'project', project: null });
|
|
466
|
+
|
|
467
|
+
assert.ok(named.length > 0);
|
|
468
|
+
assert.ok(named.every((r) => r.project === 'project-b'));
|
|
469
|
+
assert.ok(anyProject.some((r) => r.project === 'project-a'));
|
|
470
|
+
assert.strictEqual(globalOnly.length, 0);
|
|
471
|
+
});
|
|
347
472
|
it('finds pure CJK substrings with the trigram tokenizer', () => {
|
|
348
473
|
addMemory(dbManager, '设备清单包含 NAS 和备份策略');
|
|
349
474
|
|
|
@@ -370,6 +495,17 @@ describe('sqlite-memory-store', () => {
|
|
|
370
495
|
assert.ok(results.some((result) => result.content.includes('设备清单')));
|
|
371
496
|
});
|
|
372
497
|
|
|
498
|
+
it('applies target "project" in the CJK literal fallback path', () => {
|
|
499
|
+
addMemory(dbManager, '项目约定使用 pnpm', 'memory', 'project-a');
|
|
500
|
+
addMemory(dbManager, '项目全局笔记');
|
|
501
|
+
|
|
502
|
+
const results = searchMemories(dbManager, '项目', { target: 'project' });
|
|
503
|
+
|
|
504
|
+
assert.ok(results.length > 0);
|
|
505
|
+
assert.ok(results.every((r) => r.project === 'project-a'));
|
|
506
|
+
assert.ok(results.every((r) => r.target === 'memory'));
|
|
507
|
+
});
|
|
508
|
+
|
|
373
509
|
|
|
374
510
|
it('should match multi-word queries without requiring an exact phrase', () => {
|
|
375
511
|
const results = searchMemories(dbManager, 'gpu issue');
|
|
@@ -456,6 +592,45 @@ describe('sqlite-memory-store', () => {
|
|
|
456
592
|
const results = searchMemories(dbManager, 'AND OR NOT');
|
|
457
593
|
assert.strictEqual(results.length, 0);
|
|
458
594
|
});
|
|
595
|
+
|
|
596
|
+
it('ranks a dense old match above a fresher, more diluted one (BM25 before recency)', () => {
|
|
597
|
+
addMemory(dbManager, 'deploy target is the staging cluster');
|
|
598
|
+
addMemory(
|
|
599
|
+
dbManager,
|
|
600
|
+
'unrelated retrospective notes that mention deploy once among a great many other words about hiring, budgets, roadmaps, vendor calls, office moves and quarterly planning for the staging of a conference'
|
|
601
|
+
);
|
|
602
|
+
const db = dbManager.getDb();
|
|
603
|
+
db.prepare("UPDATE memories SET last_referenced = '2025-01-01' WHERE content LIKE 'deploy target%'").run();
|
|
604
|
+
db.prepare("UPDATE memories SET last_referenced = '2026-08-30' WHERE content LIKE 'unrelated retrospective%'").run();
|
|
605
|
+
|
|
606
|
+
const results = searchMemories(dbManager, 'deploy staging');
|
|
607
|
+
|
|
608
|
+
// Both rows match; recency ordering would put the long fresh note first.
|
|
609
|
+
assert.strictEqual(results.length, 2);
|
|
610
|
+
assert.ok(results[0].content.startsWith('deploy target is the staging cluster'));
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it('still broadens a two-term natural-language query through the OR fallback', () => {
|
|
614
|
+
// Neither "dark" nor "chocolate" co-occur, so the implicit-AND query
|
|
615
|
+
// misses and only the OR fallback can recover this row. The existing
|
|
616
|
+
// fallback test uses three terms; this pins the two-term case.
|
|
617
|
+
addMemory(dbManager, 'user prefers dark mode UI theme', 'user');
|
|
618
|
+
|
|
619
|
+
const results = searchMemories(dbManager, 'dark chocolate', { target: 'user' });
|
|
620
|
+
|
|
621
|
+
assert.ok(results.some((r) => r.content.includes('dark mode')));
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('recovers a natural-language query whose raw FTS5 form fails to parse', () => {
|
|
625
|
+
// "DO NOT USE FIND /" passes through as raw FTS5 syntax and throws;
|
|
626
|
+
// runSearch must catch that and let the natural-language retry run.
|
|
627
|
+
addMemory(dbManager, 'Never search whole filesystem from root. Do not run find /.', 'user');
|
|
628
|
+
|
|
629
|
+
assert.doesNotThrow(() => searchMemories(dbManager, 'DO NOT USE FIND /', { target: 'user' }));
|
|
630
|
+
const results = searchMemories(dbManager, 'DO NOT USE FIND /', { target: 'user' });
|
|
631
|
+
|
|
632
|
+
assert.ok(results.some((r) => r.content.includes('find /')));
|
|
633
|
+
});
|
|
459
634
|
});
|
|
460
635
|
|
|
461
636
|
describe('getMemories', () => {
|
|
@@ -127,12 +127,12 @@ describe("sqlite-native loader", () => {
|
|
|
127
127
|
it("formats actionable ABI recovery text", () => {
|
|
128
128
|
const message = formatBetterSqlite3AbiError({
|
|
129
129
|
originalError: new Error("NODE_MODULE_VERSION 115"),
|
|
130
|
-
packageRoot: "/Users/me/.
|
|
130
|
+
packageRoot: "/Users/me/.selesai/agent/npm/node_modules/better-sqlite3",
|
|
131
131
|
rebuildAttempted: true,
|
|
132
132
|
rebuildDetail: "exit 1",
|
|
133
133
|
});
|
|
134
134
|
assert.match(message, /NODE_MODULE_VERSION/);
|
|
135
|
-
assert.match(message, /\/Users\/me\/\.
|
|
135
|
+
assert.match(message, /\/Users\/me\/\.selesai\/agent\/npm\/node_modules\/better-sqlite3/);
|
|
136
136
|
assert.match(message, /npm rebuild better-sqlite3/);
|
|
137
137
|
assert.match(message, /Homebrew/);
|
|
138
138
|
});
|
|
@@ -66,6 +66,28 @@ describe('registerMemorySearchTool', () => {
|
|
|
66
66
|
dbManager.close();
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
+
it('accepts target "project" as a filter and shows the schema value', async () => {
|
|
70
|
+
const dbManager = makeDbManager();
|
|
71
|
+
addMemory(dbManager, 'project deployment convention', 'memory', 'project-a');
|
|
72
|
+
addMemory(dbManager, 'global deployment convention');
|
|
73
|
+
addMemory(dbManager, 'project failure deployment lesson', 'failure', 'project-a');
|
|
74
|
+
|
|
75
|
+
let captured: any;
|
|
76
|
+
registerMemorySearchTool({ registerTool: (def: any) => { captured = def; } } as any, dbManager);
|
|
77
|
+
|
|
78
|
+
assert.ok(captured.parameters.properties.target.enum.includes('project'));
|
|
79
|
+
|
|
80
|
+
const result = await captured.execute('tc-1', { query: 'deployment', target: 'project' });
|
|
81
|
+
const text = result.content[0].text;
|
|
82
|
+
|
|
83
|
+
assert.strictEqual(result.details.success, true);
|
|
84
|
+
assert.strictEqual(result.details.count, 1);
|
|
85
|
+
assert.match(text, /scope=project:project-a \[target=project\]/);
|
|
86
|
+
assert.doesNotMatch(text, /scope=global/);
|
|
87
|
+
|
|
88
|
+
dbManager.close();
|
|
89
|
+
});
|
|
90
|
+
|
|
69
91
|
it('keeps copied results reversible when a project name contains brackets', async () => {
|
|
70
92
|
const dbManager = makeDbManager();
|
|
71
93
|
addMemory(dbManager, 'literal project entry', 'memory', 'foo] bar');
|
|
@@ -9,7 +9,7 @@ import path from "node:path";
|
|
|
9
9
|
import { registerMemoryTool } from "../../src/tools/memory-tool.js";
|
|
10
10
|
import { MemoryStore } from "../../src/store/memory-store.js";
|
|
11
11
|
import { DatabaseManager } from "../../src/store/db.js";
|
|
12
|
-
import { getMemories, syncMemoryEntry } from "../../src/store/sqlite-memory-store.js";
|
|
12
|
+
import { getMemories, searchMemories, syncMemoryEntry } from "../../src/store/sqlite-memory-store.js";
|
|
13
13
|
import { ENTRY_DELIMITER, MEMORY_FILE } from "../../src/constants.js";
|
|
14
14
|
import { Value } from "typebox/value";
|
|
15
15
|
|
|
@@ -147,6 +147,42 @@ describe("registerMemoryTool", () => {
|
|
|
147
147
|
assert.strictEqual(results[0].content, 'Entry one');
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
+
it("lands over-cap policy-only adds in searchable SQLite", async () => {
|
|
151
|
+
let capturedResult: any;
|
|
152
|
+
const mockPi = {
|
|
153
|
+
registerTool: (def: any) => {
|
|
154
|
+
if (!capturedResult || def.name === "memory_add") capturedResult = def;
|
|
155
|
+
},
|
|
156
|
+
} as unknown as ExtensionAPI;
|
|
157
|
+
const store = new MemoryStore({
|
|
158
|
+
memoryMode: "policy-only",
|
|
159
|
+
memoryCharLimit: 40,
|
|
160
|
+
userCharLimit: 5000,
|
|
161
|
+
projectCharLimit: 5000,
|
|
162
|
+
nudgeInterval: 10,
|
|
163
|
+
reviewEnabled: false,
|
|
164
|
+
flushOnCompact: false,
|
|
165
|
+
flushOnShutdown: false,
|
|
166
|
+
flushMinTurns: 6,
|
|
167
|
+
autoConsolidate: false,
|
|
168
|
+
correctionDetection: false,
|
|
169
|
+
failureInjectionEnabled: true,
|
|
170
|
+
failureInjectionMaxAgeDays: 7,
|
|
171
|
+
failureInjectionMaxEntries: 5,
|
|
172
|
+
nudgeToolCalls: 15,
|
|
173
|
+
consolidationTimeoutMs: 60000,
|
|
174
|
+
memoryDir: tmpDir,
|
|
175
|
+
});
|
|
176
|
+
await store.loadFromDisk();
|
|
177
|
+
registerMemoryTool(mockPi, store, null, dbManager);
|
|
178
|
+
const first = await capturedResult.execute("tc-1", { action: "add", target: "memory", content: "alpha entry" }, undefined as any, undefined as any, undefined as any);
|
|
179
|
+
assert.strictEqual(first.details.success, true);
|
|
180
|
+
const second = await capturedResult.execute("tc-2", { action: "add", target: "memory", content: "beta entry past the tiny cap" }, undefined as any, undefined as any, undefined as any);
|
|
181
|
+
assert.strictEqual(second.details.success, true);
|
|
182
|
+
const results = searchMemories(dbManager, "beta entry past the tiny cap", { target: "memory" });
|
|
183
|
+
assert.ok(results.some((r) => r.content.includes("beta entry past the tiny cap")));
|
|
184
|
+
});
|
|
185
|
+
|
|
150
186
|
it("reports the matching target when replace is sent to the wrong target", async () => {
|
|
151
187
|
let removeTool: any;
|
|
152
188
|
const mockPi = {
|
|
@@ -4,6 +4,19 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.13.0] - 2026-09-02
|
|
8
|
+
|
|
9
|
+
### Highlights
|
|
10
|
+
- You can now give the current session a friendly alias from pi-intercom.
|
|
11
|
+
- Aliases show up right away in the session list, messages, replies, overlays, and incoming-message displays.
|
|
12
|
+
- Windows broker startup is more reliable with non-ASCII profile paths and stricter Windows Script Host setups.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- Added `/alias <name>` plus the interactive `/alias` and `/alias menu` forms for naming the current session. Thanks to [@yceachan](https://github.com/yceachan) for issue #122.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Fixed hidden Windows broker startup when the user profile path contains non-ASCII characters or Windows Script Host cannot infer the VBScript engine. Thanks to [@maelo1028](https://github.com/maelo1028) for issue #121 and [@Agustin-Prieto](https://github.com/Agustin-Prieto) for issue #123.
|
|
19
|
+
|
|
7
20
|
## [0.12.1] - 2026-08-29
|
|
8
21
|
|
|
9
22
|
### Highlights
|
|
@@ -58,6 +58,20 @@ The session list only shows intercom-connected sessions, not every open Selesai
|
|
|
58
58
|
|
|
59
59
|
If a session is unnamed, pi-intercom exposes a collision-resistant runtime-only fallback alias like `subagent-chat-1a2b3c4d-5e6f-7a8b` so other connected sessions can target it. That alias is not persisted as the Selesai session title or treated as a reconnect identity, so `selesai --resume` can keep showing the transcript snippet without allowing a different unnamed process to inherit queued mail.
|
|
60
60
|
|
|
61
|
+
### Name your current session
|
|
62
|
+
|
|
63
|
+
Use `/alias <name>` as a pi-intercom-friendly way to name the current session:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
/alias api-worker
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The alias is Selesai's session name, so it is persisted in the session and immediately
|
|
70
|
+
published to pi-intercom peers. Session lists, send/reply results, overlays, and
|
|
71
|
+
incoming message headers use it when available. In an interactive UI, `/alias`
|
|
72
|
+
or `/alias menu` opens an input for the current session's alias; it does not
|
|
73
|
+
rename other sessions. Use `/alias <name>` in non-UI modes.
|
|
74
|
+
|
|
61
75
|
## Quick Start
|
|
62
76
|
|
|
63
77
|
### From the Keyboard
|
|
@@ -135,11 +149,11 @@ The most natural use of pi-intercom is splitting a task between two sessions —
|
|
|
135
149
|
|
|
136
150
|
### Setup
|
|
137
151
|
|
|
138
|
-
Open two terminals and start
|
|
152
|
+
Open two terminals and start Selesai in each. Name them so they can find each other:
|
|
139
153
|
|
|
140
154
|
```
|
|
141
155
|
# Terminal 1 # Terminal 2
|
|
142
|
-
/
|
|
156
|
+
/alias planner /alias worker
|
|
143
157
|
```
|
|
144
158
|
|
|
145
159
|
Verify they see each other from either session:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { cpSync, existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
7
|
import {
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
getWindowsBrokerCommandLine,
|
|
13
13
|
getWindowsHiddenLauncherPath,
|
|
14
14
|
isBrokerHealthOkMessage,
|
|
15
|
+
writeWindowsHiddenLauncher,
|
|
15
16
|
} from "./spawn.ts";
|
|
16
17
|
|
|
17
18
|
test("getTsxCliPath resolves tsx cli via module resolution", () => {
|
|
@@ -80,6 +81,21 @@ test("getWindowsHiddenLauncherScript runs the broker command without showing a c
|
|
|
80
81
|
assert.match(script, /, 0, False/);
|
|
81
82
|
});
|
|
82
83
|
|
|
84
|
+
test("writeWindowsHiddenLauncher writes a UTF-16LE script with a BOM", () => {
|
|
85
|
+
const intercomDir = mkdtempSync(path.join(tmpdir(), "pi-intercom-用户-"));
|
|
86
|
+
const launcherPath = path.join(intercomDir, "broker-launch.vbs");
|
|
87
|
+
const commandLine = '"C:/Users/用户/node.exe" "C:/repo/用户/broker.ts"';
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
writeWindowsHiddenLauncher(commandLine, launcherPath);
|
|
91
|
+
const contents = readFileSync(launcherPath);
|
|
92
|
+
assert.deepEqual([...contents.subarray(0, 2)], [0xff, 0xfe]);
|
|
93
|
+
assert.equal(contents.toString("utf16le"), `\uFEFF${getWindowsHiddenLauncherScript(commandLine)}`);
|
|
94
|
+
} finally {
|
|
95
|
+
rmSync(intercomDir, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
83
99
|
test("getBrokerLaunchSpec uses wscript launcher on Windows without writing files", () => {
|
|
84
100
|
const intercomDir = mkdtempSync(path.join(tmpdir(), "pi-intercom-"));
|
|
85
101
|
|
|
@@ -94,7 +110,7 @@ test("getBrokerLaunchSpec uses wscript launcher on Windows without writing files
|
|
|
94
110
|
"C:/Program Files/nodejs/node.exe",
|
|
95
111
|
);
|
|
96
112
|
assert.equal(spec.command, "wscript.exe");
|
|
97
|
-
assert.deepEqual(spec.args, [path.join(intercomDir, "broker-launch.vbs")]);
|
|
113
|
+
assert.deepEqual(spec.args, ["//E:VBScript", path.join(intercomDir, "broker-launch.vbs")]);
|
|
98
114
|
assert.equal(spec.kind, "windows-launcher");
|
|
99
115
|
const expectedTsxPath = getTsxCliPath("C:/repo");
|
|
100
116
|
assert.equal(spec.launcherCommandLine, `"C:/Program Files/nodejs/node.exe" "${expectedTsxPath}" "C:/repo/broker.ts"`);
|
|
@@ -131,6 +147,7 @@ test("getBrokerLaunchSpec uses custom broker command on Windows", () => {
|
|
|
131
147
|
try {
|
|
132
148
|
const spec = getBrokerLaunchSpec("C:/repo/broker.ts", "bun", ["--smol"], "C:/repo", "win32", intercomDir, "C:/Program Files/nodejs/node.exe");
|
|
133
149
|
assert.equal(spec.command, "wscript.exe");
|
|
150
|
+
assert.deepEqual(spec.args, ["//E:VBScript", path.join(intercomDir, "broker-launch.vbs")]);
|
|
134
151
|
assert.equal(spec.kind, "windows-launcher");
|
|
135
152
|
assert.equal(spec.launcherCommandLine, `"bun" "--smol" "C:/repo/broker.ts"`);
|
|
136
153
|
} finally {
|
|
@@ -120,13 +120,13 @@ export function isBrokerHealthOkMessage(message: unknown, requestId: string): bo
|
|
|
120
120
|
&& response.version === INTERCOM_PROTOCOL_VERSION;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
function writeWindowsHiddenLauncher(
|
|
123
|
+
export function writeWindowsHiddenLauncher(
|
|
124
124
|
commandLine: string,
|
|
125
125
|
launcherPath: string = getWindowsHiddenLauncherPath(),
|
|
126
126
|
): string {
|
|
127
127
|
ensureIntercomRuntimeDir(dirname(launcherPath));
|
|
128
|
-
writeFileSync(launcherPath, getWindowsHiddenLauncherScript(commandLine)
|
|
129
|
-
encoding: "
|
|
128
|
+
writeFileSync(launcherPath, `\uFEFF${getWindowsHiddenLauncherScript(commandLine)}`, {
|
|
129
|
+
encoding: "utf16le",
|
|
130
130
|
mode: INTERCOM_RUNTIME_FILE_MODE,
|
|
131
131
|
});
|
|
132
132
|
restrictIntercomRuntimeFile(launcherPath);
|
|
@@ -147,7 +147,7 @@ export function getBrokerLaunchSpec(
|
|
|
147
147
|
return {
|
|
148
148
|
kind: "windows-launcher",
|
|
149
149
|
command: "wscript.exe",
|
|
150
|
-
args: [launcherPath],
|
|
150
|
+
args: ["//E:VBScript", launcherPath],
|
|
151
151
|
launcherPath,
|
|
152
152
|
launcherCommandLine: getWindowsBrokerCommandLine(brokerPath, extensionDir, nodePath, brokerCommand, brokerArgs),
|
|
153
153
|
captureStartupStderr: false,
|
|
@@ -761,7 +761,7 @@ export default function piIntercomExtension(pi: ExtensionAPI) {
|
|
|
761
761
|
if (!liveContext) return;
|
|
762
762
|
if (!liveContext.hasUI) {
|
|
763
763
|
// Command handlers return void and print mode supplies a no-op UI. Keep
|
|
764
|
-
// alias guidance visible without injecting a synthetic
|
|
764
|
+
// alias guidance visible without injecting a synthetic Selesai message.
|
|
765
765
|
console.error(message);
|
|
766
766
|
return;
|
|
767
767
|
}
|
|
@@ -183,11 +183,13 @@ function createExtensionHarness(sessionName: string | (() => string) = "child-wo
|
|
|
183
183
|
const lifecycleHandlers = new Map<string, Array<(event: unknown, ctx: unknown) => unknown>>();
|
|
184
184
|
const commands = new Map<string, (args: string, ctx: unknown) => unknown>();
|
|
185
185
|
const tools: CapturedTool[] = [];
|
|
186
|
+
let currentSessionName = typeof sessionName === "function" ? sessionName() : sessionName;
|
|
186
187
|
let activeToolNames = [...(options.activeTools ?? [])];
|
|
187
188
|
const entries: Array<{ type: string; data: unknown }> = [];
|
|
188
189
|
const sentMessages: Array<{ message: { customType?: string; content?: string; details?: unknown }; options?: { triggerTurn?: boolean; deliverAs?: string }; activeTools: string[] }> = [];
|
|
189
190
|
const pi = {
|
|
190
|
-
getSessionName: () => typeof sessionName === "function" ? sessionName() :
|
|
191
|
+
getSessionName: () => typeof sessionName === "function" ? sessionName() : currentSessionName,
|
|
192
|
+
setSessionName: (name: string) => { currentSessionName = name; },
|
|
191
193
|
events: {
|
|
192
194
|
on: (channel: string, handler: (payload: unknown) => void) => {
|
|
193
195
|
events.on(channel, handler);
|
|
@@ -1330,7 +1332,7 @@ test("intercom-id inserts a stable handoff snippet into the editor", { concurren
|
|
|
1330
1332
|
piIntercomExtension(harness.pi as never);
|
|
1331
1333
|
await harness.emitLifecycle("session_start");
|
|
1332
1334
|
await harness.commands.get("intercom-id")!("", harness.ctx);
|
|
1333
|
-
assert.match(editorText, /Existing note\n\nUse
|
|
1335
|
+
assert.match(editorText, /Existing note\n\nUse pi-intercom: intercom\(\{ action: "send", to: "session-child-test", message: "\.\.\." \}\)/);
|
|
1334
1336
|
assert.match(notifications.at(-1) ?? "", /Inserted intercom contact target: session-child-test/);
|
|
1335
1337
|
await harness.emitLifecycle("session_shutdown");
|
|
1336
1338
|
} finally {
|
|
@@ -1338,6 +1340,123 @@ test("intercom-id inserts a stable handoff snippet into the editor", { concurren
|
|
|
1338
1340
|
}
|
|
1339
1341
|
});
|
|
1340
1342
|
|
|
1343
|
+
test("alias names the current session, opens the local input menu, and appears in intercom displays", { concurrency: false }, async () => {
|
|
1344
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
1345
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1346
|
+
const inputCalls: Array<[string, string | undefined]> = [];
|
|
1347
|
+
const inputValues = ["menu-worker", "no-arg-worker"];
|
|
1348
|
+
const harness = createExtensionHarness("alias-worker", {
|
|
1349
|
+
hasUI: true,
|
|
1350
|
+
ui: {
|
|
1351
|
+
input: async (title: string, placeholder?: string) => {
|
|
1352
|
+
inputCalls.push([title, placeholder]);
|
|
1353
|
+
return inputValues.shift();
|
|
1354
|
+
},
|
|
1355
|
+
notify: () => undefined,
|
|
1356
|
+
},
|
|
1357
|
+
});
|
|
1358
|
+
|
|
1359
|
+
try {
|
|
1360
|
+
// Disable the background name poll for this test so the broker update
|
|
1361
|
+
// proves that /alias synchronizes presence directly.
|
|
1362
|
+
await withChildOrchestratorEnv({ namePollMs: "60000" }, async () => {
|
|
1363
|
+
piIntercomExtension(harness.pi as never);
|
|
1364
|
+
await harness.emitLifecycle("session_start");
|
|
1365
|
+
const initial = await waitForSessionByName(planner, "alias-worker");
|
|
1366
|
+
const aliasCommand = harness.commands.get("alias")!;
|
|
1367
|
+
|
|
1368
|
+
await aliasCommand("direct-worker", harness.ctx);
|
|
1369
|
+
const direct = await waitForSessionByName(planner, "direct-worker");
|
|
1370
|
+
assert.equal(direct.id, initial.id);
|
|
1371
|
+
assert.equal(harness.pi.getSessionName(), "direct-worker");
|
|
1372
|
+
assert.equal(inputCalls.length, 0);
|
|
1373
|
+
|
|
1374
|
+
await aliasCommand("menu", harness.ctx);
|
|
1375
|
+
await waitForSessionByName(planner, "menu-worker");
|
|
1376
|
+
await aliasCommand("", harness.ctx);
|
|
1377
|
+
const current = await waitForSessionByName(planner, "no-arg-worker");
|
|
1378
|
+
assert.equal(current.id, initial.id);
|
|
1379
|
+
assert.deepEqual(inputCalls, [
|
|
1380
|
+
["Set session alias", "Current alias: direct-worker"],
|
|
1381
|
+
["Set session alias", "Current alias: menu-worker"],
|
|
1382
|
+
]);
|
|
1383
|
+
|
|
1384
|
+
const intercomTool = harness.tools.find((tool) => tool.name === "intercom")!;
|
|
1385
|
+
const listed = await intercomTool.execute("alias-list", { action: "list" }, new AbortController().signal, undefined, harness.ctx);
|
|
1386
|
+
assert.match(listed.content[0]?.text ?? "", /no-arg-worker/);
|
|
1387
|
+
|
|
1388
|
+
orchestrator.updatePresence({ name: "alias-orchestrator" });
|
|
1389
|
+
await waitForSessionByName(planner, "alias-orchestrator");
|
|
1390
|
+
const outgoing = once(orchestrator, "message") as Promise<[SessionInfo, Message]>;
|
|
1391
|
+
const sendResult = await intercomTool.execute("alias-send", {
|
|
1392
|
+
action: "send",
|
|
1393
|
+
to: "alias-orchestrator",
|
|
1394
|
+
message: "Alias display check.",
|
|
1395
|
+
}, new AbortController().signal, undefined, harness.ctx);
|
|
1396
|
+
assert.equal(sendResult.content[0]?.text, "Message sent to alias-orchestrator");
|
|
1397
|
+
assert.equal((await outgoing)[1].content.text, "Alias display check.");
|
|
1398
|
+
|
|
1399
|
+
const askId = "alias-reply-ask";
|
|
1400
|
+
assert.equal((await orchestrator.send(initial.id, {
|
|
1401
|
+
messageId: askId,
|
|
1402
|
+
text: "Reply using the alias.",
|
|
1403
|
+
expectsReply: true,
|
|
1404
|
+
})).delivered, true);
|
|
1405
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
1406
|
+
const replyReceived = waitForReply(orchestrator, askId);
|
|
1407
|
+
const replyResult = await intercomTool.execute("alias-reply", {
|
|
1408
|
+
action: "reply",
|
|
1409
|
+
replyTo: askId,
|
|
1410
|
+
message: "Alias reply display check.",
|
|
1411
|
+
}, new AbortController().signal, undefined, harness.ctx);
|
|
1412
|
+
assert.equal(replyResult.content[0]?.text, "Reply sent to alias-orchestrator");
|
|
1413
|
+
assert.equal((await replyReceived).message.content.text, "Alias reply display check.");
|
|
1414
|
+
});
|
|
1415
|
+
} finally {
|
|
1416
|
+
await harness.emitLifecycle("session_shutdown");
|
|
1417
|
+
await cleanup();
|
|
1418
|
+
}
|
|
1419
|
+
});
|
|
1420
|
+
|
|
1421
|
+
test("alias reports no-UI usage and current alias without hanging", { concurrency: false }, async () => {
|
|
1422
|
+
const { planner, cleanup } = await setupClients();
|
|
1423
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1424
|
+
const output: string[] = [];
|
|
1425
|
+
const previousConsoleError = console.error;
|
|
1426
|
+
console.error = (...args: unknown[]) => {
|
|
1427
|
+
output.push(args.map((value) => String(value)).join(" "));
|
|
1428
|
+
};
|
|
1429
|
+
const harness = createExtensionHarness("no-ui-worker");
|
|
1430
|
+
|
|
1431
|
+
try {
|
|
1432
|
+
await withChildOrchestratorEnv({ namePollMs: "60000" }, async () => {
|
|
1433
|
+
piIntercomExtension(harness.pi as never);
|
|
1434
|
+
await harness.emitLifecycle("session_start");
|
|
1435
|
+
const initial = await waitForSessionByName(planner, "no-ui-worker");
|
|
1436
|
+
const aliasCommand = harness.commands.get("alias")!;
|
|
1437
|
+
|
|
1438
|
+
await aliasCommand("no-ui-renamed", harness.ctx);
|
|
1439
|
+
const renamed = await waitForSessionByName(planner, "no-ui-renamed");
|
|
1440
|
+
assert.equal(renamed.id, initial.id);
|
|
1441
|
+
assert.equal(harness.pi.getSessionName(), "no-ui-renamed");
|
|
1442
|
+
assert.deepEqual(output, ["Session alias set: no-ui-renamed"]);
|
|
1443
|
+
|
|
1444
|
+
output.length = 0;
|
|
1445
|
+
await aliasCommand("", harness.ctx);
|
|
1446
|
+
assert.deepEqual(output, ["Session alias: no-ui-renamed"]);
|
|
1447
|
+
|
|
1448
|
+
output.length = 0;
|
|
1449
|
+
await aliasCommand("menu", harness.ctx);
|
|
1450
|
+
assert.deepEqual(output, ["The alias menu requires an interactive UI; use /alias <name>."]);
|
|
1451
|
+
assert.equal(harness.pi.getSessionName(), "no-ui-renamed");
|
|
1452
|
+
});
|
|
1453
|
+
} finally {
|
|
1454
|
+
console.error = previousConsoleError;
|
|
1455
|
+
await harness.emitLifecycle("session_shutdown");
|
|
1456
|
+
await cleanup();
|
|
1457
|
+
}
|
|
1458
|
+
});
|
|
1459
|
+
|
|
1341
1460
|
test("intercom tool shows unique ID prefixes when names collide", { concurrency: false }, async () => {
|
|
1342
1461
|
const { cleanup } = await setupClients();
|
|
1343
1462
|
const { default: piIntercomExtension } = await import("./index.ts");
|
|
@@ -90,7 +90,7 @@ test("openProjectPane opens a Herdr pane and runs pi in the project", async () =
|
|
|
90
90
|
assert.equal(launched.paneId, "pane-1");
|
|
91
91
|
assert.equal(launched.herdrVersion, "herdr 0.7.5");
|
|
92
92
|
assert.deepEqual(calls[1], ["pane", "split", "--current", "--direction", "right", "--cwd", launched.projectRoot]);
|
|
93
|
-
assert.deepEqual(calls[2], ["pane", "run", "pane-1", "
|
|
93
|
+
assert.deepEqual(calls[2], ["pane", "run", "pane-1", "selesai"]);
|
|
94
94
|
} finally {
|
|
95
95
|
rmSync(root, { recursive: true, force: true });
|
|
96
96
|
}
|
|
@@ -171,11 +171,6 @@ function extractPaneId(value: unknown): string | undefined {
|
|
|
171
171
|
return undefined;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
function shellQuote(value: string): string {
|
|
175
|
-
if (process.platform === "win32") return `"${value.replaceAll('"', '\\"')}"`;
|
|
176
|
-
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
174
|
function resolveProjectRoot(cwd: string): string {
|
|
180
175
|
const resolved = resolve(cwd);
|
|
181
176
|
const stat = statSync(resolved);
|
|
@@ -242,7 +237,7 @@ export async function openProjectPane(input: {
|
|
|
242
237
|
const paneId = extractPaneId(split.data);
|
|
243
238
|
if (!paneId) throw new Error("Herdr project pane error (PANE_GONE): pane split returned no pane id.");
|
|
244
239
|
|
|
245
|
-
const command =
|
|
240
|
+
const command = process.env.SELESAI_INTERCOM_BINARY?.trim() || process.env.SELESAI_BIN?.trim() || "selesai";
|
|
246
241
|
const started = await client.run(["pane", "run", paneId, command], { timeoutMs: 15_000, signal: input.signal });
|
|
247
242
|
if (started.ok === false) {
|
|
248
243
|
await client.run(["pane", "close", paneId], { timeoutMs: 5_000 });
|