pi-usereq 0.6.0 → 0.10.0
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/.gitignore +2 -0
- package/CHANGELOG.md +44 -0
- package/README.md +1 -1
- package/docs/pi.dev/coding-agent-docs/custom-provider.md +42 -1
- package/docs/pi.dev/coding-agent-docs/extensions.md +302 -28
- package/docs/pi.dev/coding-agent-docs/keybindings.md +23 -1
- package/docs/pi.dev/coding-agent-docs/models.md +3 -0
- package/docs/pi.dev/coding-agent-docs/packages.md +2 -2
- package/docs/pi.dev/coding-agent-docs/prompt-templates.md +21 -0
- package/docs/pi.dev/coding-agent-docs/providers.md +1 -0
- package/docs/pi.dev/coding-agent-docs/rpc.md +36 -6
- package/docs/pi.dev/coding-agent-docs/sdk.md +30 -5
- package/docs/pi.dev/coding-agent-docs/session.md +1 -1
- package/docs/pi.dev/coding-agent-docs/settings.md +2 -1
- package/docs/pi.dev/coding-agent-docs/skills.md +12 -12
- package/docs/pi.dev/coding-agent-docs/tree.md +2 -0
- package/docs/pi.dev/coding-agent-docs/tui.md +31 -0
- package/docs/pi.dev/mom-docs/new.md +4 -4
- package/package.json +1 -1
- package/pi-usereq/docs/REFERENCES.md +2658 -2035
- package/pi-usereq/docs/REQUIREMENTS.md +345 -191
- package/pi-usereq/docs/WORKFLOW.md +387 -363
- package/pi.dev-src/pi-mono/agent/src/agent-loop.ts +683 -0
- package/pi.dev-src/pi-mono/agent/src/agent.ts +543 -0
- package/pi.dev-src/pi-mono/agent/src/index.ts +8 -0
- package/pi.dev-src/pi-mono/agent/src/proxy.ts +367 -0
- package/pi.dev-src/pi-mono/agent/src/types.ts +364 -0
- package/pi.dev-src/pi-mono/agent/test/agent-loop.test.ts +1181 -0
- package/pi.dev-src/pi-mono/agent/test/agent.test.ts +463 -0
- package/pi.dev-src/pi-mono/agent/test/e2e.test.ts +404 -0
- package/pi.dev-src/pi-mono/agent/test/utils/calculate.ts +32 -0
- package/pi.dev-src/pi-mono/agent/test/utils/get-current-time.ts +46 -0
- package/pi.dev-src/pi-mono/agent/vitest.config.ts +9 -0
- package/pi.dev-src/pi-mono/ai/bedrock-provider.d.ts +1 -0
- package/pi.dev-src/pi-mono/ai/bedrock-provider.js +1 -0
- package/pi.dev-src/pi-mono/ai/scripts/generate-models.ts +1635 -0
- package/pi.dev-src/pi-mono/ai/scripts/generate-test-image.ts +34 -0
- package/pi.dev-src/pi-mono/ai/src/api-registry.ts +98 -0
- package/pi.dev-src/pi-mono/ai/src/bedrock-provider.ts +6 -0
- package/pi.dev-src/pi-mono/ai/src/cli.ts +133 -0
- package/pi.dev-src/pi-mono/ai/src/env-api-keys.ts +134 -0
- package/pi.dev-src/pi-mono/ai/src/index.ts +35 -0
- package/pi.dev-src/pi-mono/ai/src/models.generated.ts +14928 -0
- package/pi.dev-src/pi-mono/ai/src/models.ts +82 -0
- package/pi.dev-src/pi-mono/ai/src/oauth.ts +1 -0
- package/pi.dev-src/pi-mono/ai/src/providers/amazon-bedrock.ts +929 -0
- package/pi.dev-src/pi-mono/ai/src/providers/anthropic.ts +1125 -0
- package/pi.dev-src/pi-mono/ai/src/providers/azure-openai-responses.ts +253 -0
- package/pi.dev-src/pi-mono/ai/src/providers/faux.ts +499 -0
- package/pi.dev-src/pi-mono/ai/src/providers/github-copilot-headers.ts +37 -0
- package/pi.dev-src/pi-mono/ai/src/providers/google-gemini-cli.ts +996 -0
- package/pi.dev-src/pi-mono/ai/src/providers/google-shared.ts +354 -0
- package/pi.dev-src/pi-mono/ai/src/providers/google-vertex.ts +543 -0
- package/pi.dev-src/pi-mono/ai/src/providers/google.ts +500 -0
- package/pi.dev-src/pi-mono/ai/src/providers/mistral.ts +629 -0
- package/pi.dev-src/pi-mono/ai/src/providers/openai-codex-responses.ts +984 -0
- package/pi.dev-src/pi-mono/ai/src/providers/openai-completions.ts +1063 -0
- package/pi.dev-src/pi-mono/ai/src/providers/openai-responses-shared.ts +539 -0
- package/pi.dev-src/pi-mono/ai/src/providers/openai-responses.ts +264 -0
- package/pi.dev-src/pi-mono/ai/src/providers/register-builtins.ts +433 -0
- package/pi.dev-src/pi-mono/ai/src/providers/simple-options.ts +47 -0
- package/pi.dev-src/pi-mono/ai/src/providers/transform-messages.ts +220 -0
- package/pi.dev-src/pi-mono/ai/src/stream.ts +59 -0
- package/pi.dev-src/pi-mono/ai/src/types.ts +417 -0
- package/pi.dev-src/pi-mono/ai/src/utils/event-stream.ts +87 -0
- package/pi.dev-src/pi-mono/ai/src/utils/hash.ts +13 -0
- package/pi.dev-src/pi-mono/ai/src/utils/headers.ts +7 -0
- package/pi.dev-src/pi-mono/ai/src/utils/json-parse.ts +124 -0
- package/pi.dev-src/pi-mono/ai/src/utils/overflow.ts +138 -0
- package/pi.dev-src/pi-mono/ai/src/utils/sanitize-unicode.ts +25 -0
- package/pi.dev-src/pi-mono/ai/src/utils/typebox-helpers.ts +24 -0
- package/pi.dev-src/pi-mono/ai/src/utils/validation.ts +324 -0
- package/pi.dev-src/pi-mono/ai/test/abort.test.ts +260 -0
- package/pi.dev-src/pi-mono/ai/test/anthropic-oauth.test.ts +99 -0
- package/pi.dev-src/pi-mono/ai/test/anthropic-opus-4-7-smoke.test.ts +72 -0
- package/pi.dev-src/pi-mono/ai/test/anthropic-sse-parsing.test.ts +113 -0
- package/pi.dev-src/pi-mono/ai/test/anthropic-thinking-disable.test.ts +152 -0
- package/pi.dev-src/pi-mono/ai/test/anthropic-tool-name-normalization.test.ts +205 -0
- package/pi.dev-src/pi-mono/ai/test/azure-utils.ts +28 -0
- package/pi.dev-src/pi-mono/ai/test/bedrock-endpoint-resolution.test.ts +131 -0
- package/pi.dev-src/pi-mono/ai/test/bedrock-models.test.ts +66 -0
- package/pi.dev-src/pi-mono/ai/test/bedrock-thinking-payload.test.ts +107 -0
- package/pi.dev-src/pi-mono/ai/test/bedrock-utils.ts +18 -0
- package/pi.dev-src/pi-mono/ai/test/cache-retention.test.ts +335 -0
- package/pi.dev-src/pi-mono/ai/test/context-overflow.test.ts +714 -0
- package/pi.dev-src/pi-mono/ai/test/cross-provider-handoff.test.ts +458 -0
- package/pi.dev-src/pi-mono/ai/test/data/red-circle.png +0 -0
- package/pi.dev-src/pi-mono/ai/test/empty.test.ts +742 -0
- package/pi.dev-src/pi-mono/ai/test/faux-provider.test.ts +597 -0
- package/pi.dev-src/pi-mono/ai/test/fireworks-models.test.ts +49 -0
- package/pi.dev-src/pi-mono/ai/test/github-copilot-anthropic.test.ts +108 -0
- package/pi.dev-src/pi-mono/ai/test/github-copilot-oauth.test.ts +196 -0
- package/pi.dev-src/pi-mono/ai/test/google-gemini-cli-claude-thinking-header.test.ts +103 -0
- package/pi.dev-src/pi-mono/ai/test/google-gemini-cli-empty-stream.test.ts +108 -0
- package/pi.dev-src/pi-mono/ai/test/google-gemini-cli-retry-delay.test.ts +53 -0
- package/pi.dev-src/pi-mono/ai/test/google-shared-convert-tools.test.ts +187 -0
- package/pi.dev-src/pi-mono/ai/test/google-shared-gemini3-unsigned-tool-call.test.ts +172 -0
- package/pi.dev-src/pi-mono/ai/test/google-shared-image-tool-result-routing.test.ts +124 -0
- package/pi.dev-src/pi-mono/ai/test/google-thinking-disable.test.ts +183 -0
- package/pi.dev-src/pi-mono/ai/test/google-thinking-signature.test.ts +38 -0
- package/pi.dev-src/pi-mono/ai/test/google-tool-call-missing-args.test.ts +105 -0
- package/pi.dev-src/pi-mono/ai/test/google-vertex-api-key-resolution.test.ts +144 -0
- package/pi.dev-src/pi-mono/ai/test/image-tool-result.test.ts +481 -0
- package/pi.dev-src/pi-mono/ai/test/interleaved-thinking.test.ts +145 -0
- package/pi.dev-src/pi-mono/ai/test/lazy-module-load.test.ts +102 -0
- package/pi.dev-src/pi-mono/ai/test/mistral-reasoning-mode.test.ts +66 -0
- package/pi.dev-src/pi-mono/ai/test/mistral-tool-schema.test.ts +61 -0
- package/pi.dev-src/pi-mono/ai/test/oauth.ts +89 -0
- package/pi.dev-src/pi-mono/ai/test/openai-codex-cache-affinity-e2e.test.ts +36 -0
- package/pi.dev-src/pi-mono/ai/test/openai-codex-stream.test.ts +686 -0
- package/pi.dev-src/pi-mono/ai/test/openai-completions-cache-control-format.test.ts +189 -0
- package/pi.dev-src/pi-mono/ai/test/openai-completions-prompt-cache.test.ts +198 -0
- package/pi.dev-src/pi-mono/ai/test/openai-completions-thinking-as-text.test.ts +214 -0
- package/pi.dev-src/pi-mono/ai/test/openai-completions-tool-choice.test.ts +560 -0
- package/pi.dev-src/pi-mono/ai/test/openai-completions-tool-result-images.test.ts +101 -0
- package/pi.dev-src/pi-mono/ai/test/openai-responses-cache-affinity-e2e.test.ts +32 -0
- package/pi.dev-src/pi-mono/ai/test/openai-responses-copilot-provider.test.ts +128 -0
- package/pi.dev-src/pi-mono/ai/test/openai-responses-foreign-toolcall-id.test.ts +66 -0
- package/pi.dev-src/pi-mono/ai/test/openai-responses-partial-json-cleanup.test.ts +101 -0
- package/pi.dev-src/pi-mono/ai/test/openai-responses-reasoning-replay-e2e.test.ts +292 -0
- package/pi.dev-src/pi-mono/ai/test/openai-responses-tool-result-images.test.ts +200 -0
- package/pi.dev-src/pi-mono/ai/test/openrouter-cache-write-repro.test.ts +78 -0
- package/pi.dev-src/pi-mono/ai/test/overflow.test.ts +64 -0
- package/pi.dev-src/pi-mono/ai/test/responseid.test.ts +145 -0
- package/pi.dev-src/pi-mono/ai/test/stream.test.ts +1405 -0
- package/pi.dev-src/pi-mono/ai/test/supports-xhigh.test.ts +34 -0
- package/pi.dev-src/pi-mono/ai/test/tokens.test.ts +304 -0
- package/pi.dev-src/pi-mono/ai/test/tool-call-id-normalization.test.ts +291 -0
- package/pi.dev-src/pi-mono/ai/test/tool-call-without-result.test.ts +313 -0
- package/pi.dev-src/pi-mono/ai/test/total-tokens.test.ts +695 -0
- package/pi.dev-src/pi-mono/ai/test/transform-messages-copilot-openai-to-anthropic.test.ts +191 -0
- package/pi.dev-src/pi-mono/ai/test/unicode-surrogate.test.ts +754 -0
- package/pi.dev-src/pi-mono/ai/test/validation.test.ts +116 -0
- package/pi.dev-src/pi-mono/ai/test/xhigh.test.ts +71 -0
- package/pi.dev-src/pi-mono/ai/test/zen.test.ts +25 -0
- package/pi.dev-src/pi-mono/ai/vitest.config.ts +9 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/antigravity-image-gen.ts +418 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/bash-spawn-hook.ts +30 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/bookmark.ts +50 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/built-in-tool-renderer.ts +249 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/claude-rules.ts +86 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/commands.ts +72 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/confirm-destructive.ts +59 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/custom-compaction.ts +127 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/custom-footer.ts +64 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/custom-header.ts +73 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/custom-provider-qwen-cli/index.ts +345 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/dirty-repo-guard.ts +56 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/doom-overlay/index.ts +74 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/doom-overlay/wad-finder.ts +51 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/dynamic-resources/dynamic.json +79 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/dynamic-resources/index.ts +15 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/dynamic-tools.ts +74 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/event-bus.ts +43 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/file-trigger.ts +41 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/git-checkpoint.ts +53 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/github-issue-autocomplete.ts +185 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/handoff.ts +153 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/hello.ts +26 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/hidden-thinking-label.ts +53 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/inline-bash.ts +94 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/input-transform.ts +43 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/interactive-shell.ts +196 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/mac-system-theme.ts +47 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/message-renderer.ts +59 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/minimal-mode.ts +426 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/modal-editor.ts +85 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/model-status.ts +31 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/notify.ts +55 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/overlay-qa-tests.ts +1348 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/overlay-test.ts +150 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/permission-gate.ts +34 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/pirate.ts +47 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/plan-mode/index.ts +340 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/plan-mode/utils.ts +168 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/preset.ts +430 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/prompt-customizer.ts +97 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/protected-paths.ts +30 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/provider-payload.ts +18 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/qna.ts +122 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/question.ts +264 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/questionnaire.ts +427 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/rainbow-editor.ts +88 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/reload-runtime.ts +37 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/rpc-demo.ts +118 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/sandbox/index.ts +321 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/sandbox/package-lock.json +92 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/send-user-message.ts +97 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/session-name.ts +27 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/shutdown-command.ts +63 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/snake.ts +343 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/space-invaders.ts +560 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/ssh.ts +220 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/status-line.ts +32 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/structured-output.ts +65 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/agents/planner.md +37 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/agents/scout.md +50 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/agents/worker.md +24 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/agents.ts +126 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/index.ts +987 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/prompts/implement.md +10 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/summarize.ts +206 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/system-prompt-header.ts +17 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/tic-tac-toe.ts +1008 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/timed-confirm.ts +70 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/titlebar-spinner.ts +58 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/todo.ts +297 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/tool-override.ts +144 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/tools.ts +141 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/trigger-compact.ts +50 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/truncated-tool.ts +195 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/widget-placement.ts +9 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/with-deps/index.ts +32 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/with-deps/package-lock.json +31 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/working-indicator.ts +123 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/extensions/working-message-test.ts +25 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/rpc-extension-ui.ts +632 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/01-minimal.ts +22 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/02-custom-model.ts +49 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/03-custom-prompt.ts +62 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/04-skills.ts +55 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/05-tools.ts +44 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/06-extensions.ts +90 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/07-context-files.ts +42 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/08-prompt-templates.ts +51 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/09-api-keys-and-oauth.ts +48 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/10-settings.ts +53 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/11-sessions.ts +48 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/12-full-control.ts +73 -0
- package/pi.dev-src/pi-mono/coding-agent/examples/sdk/13-session-runtime.ts +67 -0
- package/pi.dev-src/pi-mono/coding-agent/scripts/migrate-sessions.sh +93 -0
- package/pi.dev-src/pi-mono/coding-agent/src/bun/cli.ts +6 -0
- package/pi.dev-src/pi-mono/coding-agent/src/bun/register-bedrock.ts +4 -0
- package/pi.dev-src/pi-mono/coding-agent/src/cli/args.ts +335 -0
- package/pi.dev-src/pi-mono/coding-agent/src/cli/config-selector.ts +52 -0
- package/pi.dev-src/pi-mono/coding-agent/src/cli/file-processor.ts +100 -0
- package/pi.dev-src/pi-mono/coding-agent/src/cli/initial-message.ts +43 -0
- package/pi.dev-src/pi-mono/coding-agent/src/cli/list-models.ts +110 -0
- package/pi.dev-src/pi-mono/coding-agent/src/cli/session-picker.ts +52 -0
- package/pi.dev-src/pi-mono/coding-agent/src/cli.ts +17 -0
- package/pi.dev-src/pi-mono/coding-agent/src/config.ts +261 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/agent-session-runtime.ts +394 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/agent-session-services.ts +196 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/agent-session.ts +3096 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/auth-storage.ts +493 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/bash-executor.ts +154 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/compaction/branch-summarization.ts +355 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/compaction/compaction.ts +839 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/compaction/index.ts +7 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/compaction/utils.ts +170 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/defaults.ts +3 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/diagnostics.ts +15 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/event-bus.ts +33 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/exec.ts +107 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/export-html/ansi-to-html.ts +258 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/export-html/index.ts +314 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/export-html/template.css +1017 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/export-html/template.html +55 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/export-html/template.js +1770 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/export-html/tool-renderer.ts +158 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/export-html/vendor/highlight.min.js +1213 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/export-html/vendor/marked.min.js +6 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/extensions/index.ts +171 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/extensions/loader.ts +606 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/extensions/runner.ts +1019 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/extensions/types.ts +1542 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/extensions/wrapper.ts +30 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/footer-data-provider.ts +354 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/index.ts +77 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/keybindings.ts +370 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/messages.ts +195 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/model-registry.ts +858 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/model-resolver.ts +629 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/output-guard.ts +74 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/package-manager.ts +2408 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/prompt-templates.ts +296 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/resolve-config-value.ts +142 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/resource-loader.ts +917 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/sdk.ts +380 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/session-cwd.ts +59 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/session-manager.ts +1425 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/settings-manager.ts +999 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/skills.ts +508 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/slash-commands.ts +39 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/source-info.ts +40 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/system-prompt.ts +172 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/telemetry.ts +13 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/timings.ts +31 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/bash.ts +448 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/edit-diff.ts +445 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/edit.ts +487 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/file-mutation-queue.ts +39 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/find.ts +370 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/grep.ts +384 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/index.ts +196 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/ls.ts +229 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/path-utils.ts +94 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/read.ts +273 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/render-utils.ts +64 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/tool-definition-wrapper.ts +45 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/truncate.ts +265 -0
- package/pi.dev-src/pi-mono/coding-agent/src/core/tools/write.ts +281 -0
- package/pi.dev-src/pi-mono/coding-agent/src/index.ts +352 -0
- package/pi.dev-src/pi-mono/coding-agent/src/main.ts +731 -0
- package/pi.dev-src/pi-mono/coding-agent/src/migrations.ts +314 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/index.ts +9 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/assets/clankolas.png +0 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/armin.ts +382 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/assistant-message.ts +147 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/bash-execution.ts +218 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/bordered-loader.ts +68 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/branch-summary-message.ts +58 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/compaction-summary-message.ts +59 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/config-selector.ts +592 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/countdown-timer.ts +38 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/custom-editor.ts +80 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/custom-message.ts +99 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/daxnuts.ts +164 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/diff.ts +147 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/dynamic-border.ts +25 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/earendil-announcement.ts +53 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/extension-editor.ts +147 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/extension-input.ts +87 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/extension-selector.ts +107 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/footer.ts +220 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/index.ts +32 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/keybinding-hints.ts +24 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/login-dialog.ts +178 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/model-selector.ts +338 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/oauth-selector.ts +121 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/scoped-models-selector.ts +355 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/session-selector-search.ts +194 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/session-selector.ts +1026 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/settings-selector.ts +456 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/show-images-selector.ts +50 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/skill-invocation-message.ts +55 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/theme-selector.ts +67 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/thinking-selector.ts +74 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/tool-execution.ts +352 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/tree-selector.ts +1246 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/user-message-selector.ts +155 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/user-message.ts +35 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/components/visual-truncate.ts +50 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/interactive-mode.ts +5155 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/theme/dark.json +85 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/theme/light.json +84 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/theme/theme-schema.json +335 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/interactive/theme/theme.ts +1141 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/print-mode.ts +158 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/rpc/jsonl.ts +58 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/rpc/rpc-client.ts +515 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/rpc/rpc-mode.ts +745 -0
- package/pi.dev-src/pi-mono/coding-agent/src/modes/rpc/rpc-types.ts +264 -0
- package/pi.dev-src/pi-mono/coding-agent/src/package-manager-cli.ts +270 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/changelog.ts +99 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/child-process.ts +86 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/clipboard-image.ts +300 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/clipboard-native.ts +22 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/clipboard.ts +81 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/exif-orientation.ts +183 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/frontmatter.ts +39 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/fs-watch.ts +30 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/git.ts +192 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/image-convert.ts +41 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/image-resize.ts +176 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/mime.ts +30 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/paths.ts +20 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/photon.ts +139 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/shell.ts +210 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/sleep.ts +18 -0
- package/pi.dev-src/pi-mono/coding-agent/src/utils/tools-manager.ts +287 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-auto-compaction-queue.test.ts +437 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-branching.test.ts +156 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-compaction.test.ts +208 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-concurrent.test.ts +618 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-dynamic-provider.test.ts +117 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-dynamic-tools.test.ts +182 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-retry.test.ts +318 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-runtime-events.test.ts +208 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-stats.test.ts +143 -0
- package/pi.dev-src/pi-mono/coding-agent/test/agent-session-tree-navigation.test.ts +323 -0
- package/pi.dev-src/pi-mono/coding-agent/test/args.test.ts +328 -0
- package/pi.dev-src/pi-mono/coding-agent/test/assistant-message.test.ts +57 -0
- package/pi.dev-src/pi-mono/coding-agent/test/auth-storage.test.ts +462 -0
- package/pi.dev-src/pi-mono/coding-agent/test/bash-close-hang-windows.test.ts +126 -0
- package/pi.dev-src/pi-mono/coding-agent/test/bash-execution-width.test.ts +80 -0
- package/pi.dev-src/pi-mono/coding-agent/test/block-images.test.ts +120 -0
- package/pi.dev-src/pi-mono/coding-agent/test/clipboard-image-bmp-conversion.test.ts +88 -0
- package/pi.dev-src/pi-mono/coding-agent/test/clipboard-image.test.ts +136 -0
- package/pi.dev-src/pi-mono/coding-agent/test/compaction-extensions-example.test.ts +66 -0
- package/pi.dev-src/pi-mono/coding-agent/test/compaction-extensions.test.ts +415 -0
- package/pi.dev-src/pi-mono/coding-agent/test/compaction-serialization.test.ts +79 -0
- package/pi.dev-src/pi-mono/coding-agent/test/compaction-summary-reasoning.test.ts +118 -0
- package/pi.dev-src/pi-mono/coding-agent/test/compaction-thinking-model.test.ts +223 -0
- package/pi.dev-src/pi-mono/coding-agent/test/compaction.test.ts +550 -0
- package/pi.dev-src/pi-mono/coding-agent/test/config.test.ts +30 -0
- package/pi.dev-src/pi-mono/coding-agent/test/edit-tool-legacy-input.test.ts +116 -0
- package/pi.dev-src/pi-mono/coding-agent/test/edit-tool-no-full-redraw.test.ts +235 -0
- package/pi.dev-src/pi-mono/coding-agent/test/export-html-whitespace.test.ts +12 -0
- package/pi.dev-src/pi-mono/coding-agent/test/export-html-xss.test.ts +28 -0
- package/pi.dev-src/pi-mono/coding-agent/test/extensions-discovery.test.ts +463 -0
- package/pi.dev-src/pi-mono/coding-agent/test/extensions-input-event.test.ts +112 -0
- package/pi.dev-src/pi-mono/coding-agent/test/extensions-runner.test.ts +805 -0
- package/pi.dev-src/pi-mono/coding-agent/test/file-mutation-queue.test.ts +163 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/assistant-message-with-thinking-code.json +33 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/before-compaction.jsonl +1003 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/empty-agent/.gitkeep +0 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/empty-cwd/.gitkeep +0 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/large-session.jsonl +1019 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/consecutive-hyphens/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/disable-model-invocation/SKILL.md +9 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/invalid-name-chars/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/invalid-yaml/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/long-name/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/missing-description/SKILL.md +7 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/multiline-description/SKILL.md +11 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/name-mismatch/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/nested/child-skill/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/no-frontmatter/SKILL.md +3 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/root-skill-preferred/SKILL.md +3 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/root-skill-preferred/nested-child/SKILL.md +3 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/unknown-field/SKILL.md +10 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills/valid-skill/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills-collision/first/calendar/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/fixtures/skills-collision/second/calendar/SKILL.md +8 -0
- package/pi.dev-src/pi-mono/coding-agent/test/footer-data-provider.test.ts +265 -0
- package/pi.dev-src/pi-mono/coding-agent/test/footer-width.test.ts +115 -0
- package/pi.dev-src/pi-mono/coding-agent/test/frontmatter.test.ts +60 -0
- package/pi.dev-src/pi-mono/coding-agent/test/git-ssh-url.test.ts +78 -0
- package/pi.dev-src/pi-mono/coding-agent/test/git-update.test.ts +411 -0
- package/pi.dev-src/pi-mono/coding-agent/test/image-processing.test.ts +145 -0
- package/pi.dev-src/pi-mono/coding-agent/test/image-resize-callers.test.ts +53 -0
- package/pi.dev-src/pi-mono/coding-agent/test/initial-message.test.ts +48 -0
- package/pi.dev-src/pi-mono/coding-agent/test/interactive-mode-anthropic-warning.test.ts +73 -0
- package/pi.dev-src/pi-mono/coding-agent/test/interactive-mode-clone-command.test.ts +77 -0
- package/pi.dev-src/pi-mono/coding-agent/test/interactive-mode-compaction.test.ts +57 -0
- package/pi.dev-src/pi-mono/coding-agent/test/interactive-mode-import-command.test.ts +144 -0
- package/pi.dev-src/pi-mono/coding-agent/test/interactive-mode-status.test.ts +635 -0
- package/pi.dev-src/pi-mono/coding-agent/test/interactive-mode-suspend.test.ts +149 -0
- package/pi.dev-src/pi-mono/coding-agent/test/keybindings-migration.test.ts +88 -0
- package/pi.dev-src/pi-mono/coding-agent/test/model-registry.test.ts +1209 -0
- package/pi.dev-src/pi-mono/coding-agent/test/model-resolver.test.ts +436 -0
- package/pi.dev-src/pi-mono/coding-agent/test/package-command-paths.test.ts +144 -0
- package/pi.dev-src/pi-mono/coding-agent/test/package-manager-ssh.test.ts +97 -0
- package/pi.dev-src/pi-mono/coding-agent/test/package-manager.test.ts +1795 -0
- package/pi.dev-src/pi-mono/coding-agent/test/path-utils.test.ts +162 -0
- package/pi.dev-src/pi-mono/coding-agent/test/plan-mode-utils.test.ts +261 -0
- package/pi.dev-src/pi-mono/coding-agent/test/print-mode.test.ts +140 -0
- package/pi.dev-src/pi-mono/coding-agent/test/prompt-templates.test.ts +515 -0
- package/pi.dev-src/pi-mono/coding-agent/test/resource-loader.test.ts +576 -0
- package/pi.dev-src/pi-mono/coding-agent/test/rpc-client-clone.test.ts +29 -0
- package/pi.dev-src/pi-mono/coding-agent/test/rpc-example.ts +86 -0
- package/pi.dev-src/pi-mono/coding-agent/test/rpc-jsonl.test.ts +65 -0
- package/pi.dev-src/pi-mono/coding-agent/test/rpc-prompt-response-semantics.test.ts +285 -0
- package/pi.dev-src/pi-mono/coding-agent/test/rpc.test.ts +321 -0
- package/pi.dev-src/pi-mono/coding-agent/test/sdk-codex-cache-probe-tool-loop.ts +364 -0
- package/pi.dev-src/pi-mono/coding-agent/test/sdk-openrouter-attribution.test.ts +181 -0
- package/pi.dev-src/pi-mono/coding-agent/test/sdk-session-manager.test.ts +95 -0
- package/pi.dev-src/pi-mono/coding-agent/test/sdk-skills.test.ts +109 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-cwd.test.ts +91 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-info-modified-timestamp.test.ts +83 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-manager/build-context.test.ts +268 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-manager/custom-session-id.test.ts +109 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-manager/file-operations.test.ts +208 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-manager/labels.test.ts +198 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-manager/migration.test.ts +78 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-manager/save-entry.test.ts +55 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-manager/tree-traversal.test.ts +533 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-selector-path-delete.test.ts +315 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-selector-rename.test.ts +111 -0
- package/pi.dev-src/pi-mono/coding-agent/test/session-selector-search.test.ts +195 -0
- package/pi.dev-src/pi-mono/coding-agent/test/settings-manager-bug.test.ts +147 -0
- package/pi.dev-src/pi-mono/coding-agent/test/settings-manager.test.ts +319 -0
- package/pi.dev-src/pi-mono/coding-agent/test/skills.test.ts +432 -0
- package/pi.dev-src/pi-mono/coding-agent/test/stdout-cleanliness.test.ts +103 -0
- package/pi.dev-src/pi-mono/coding-agent/test/streaming-render-debug.ts +97 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/agent-session-bash-persistence.test.ts +242 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/agent-session-compaction.test.ts +343 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/agent-session-model-extension.test.ts +325 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/agent-session-prompt.test.ts +323 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/agent-session-queue.test.ts +422 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/agent-session-retry-events.test.ts +358 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/agent-session-runtime.test.ts +553 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/harness.ts +208 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/2023-queued-slash-command-followup.test.ts +80 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/2753-reload-stale-resource-settings.test.ts +100 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/2781-skill-collision-precedence.test.ts +120 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/2791-fswatch-error-crash.test.ts +106 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/2835-tools-allowlist-filters-extension-tools.test.ts +94 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/2860-replaced-session-context.test.ts +274 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/3217-scoped-model-order.test.ts +104 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/3302-find-path-glob.test.ts +72 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/3303-find-nested-gitignore.test.ts +83 -0
- package/pi.dev-src/pi-mono/coding-agent/test/suite/regressions/3317-network-connection-lost-retry.test.ts +33 -0
- package/pi.dev-src/pi-mono/coding-agent/test/system-prompt.test.ts +102 -0
- package/pi.dev-src/pi-mono/coding-agent/test/test-harness.test.ts +321 -0
- package/pi.dev-src/pi-mono/coding-agent/test/test-harness.ts +446 -0
- package/pi.dev-src/pi-mono/coding-agent/test/test-theme-colors.ts +246 -0
- package/pi.dev-src/pi-mono/coding-agent/test/theme-export.test.ts +104 -0
- package/pi.dev-src/pi-mono/coding-agent/test/tool-execution-component.test.ts +331 -0
- package/pi.dev-src/pi-mono/coding-agent/test/tools.test.ts +889 -0
- package/pi.dev-src/pi-mono/coding-agent/test/tree-selector.test.ts +655 -0
- package/pi.dev-src/pi-mono/coding-agent/test/trigger-compact-extension.test.ts +57 -0
- package/pi.dev-src/pi-mono/coding-agent/test/truncate-to-width.test.ts +81 -0
- package/pi.dev-src/pi-mono/coding-agent/test/user-message.test.ts +25 -0
- package/pi.dev-src/pi-mono/coding-agent/test/utilities.ts +316 -0
- package/pi.dev-src/pi-mono/coding-agent/tsconfig.examples.json +16 -0
- package/pi.dev-src/pi-mono/coding-agent/vitest.config.ts +26 -0
- package/pi.dev-src/pi-mono/mom/dev.sh +30 -0
- package/pi.dev-src/pi-mono/mom/docker.sh +95 -0
- package/pi.dev-src/pi-mono/mom/scripts/migrate-timestamps.ts +121 -0
- package/pi.dev-src/pi-mono/mom/src/agent.ts +882 -0
- package/pi.dev-src/pi-mono/mom/src/context.ts +180 -0
- package/pi.dev-src/pi-mono/mom/src/download.ts +117 -0
- package/pi.dev-src/pi-mono/mom/src/events.ts +442 -0
- package/pi.dev-src/pi-mono/mom/src/fs-watch.ts +30 -0
- package/pi.dev-src/pi-mono/mom/src/log.ts +271 -0
- package/pi.dev-src/pi-mono/mom/src/main.ts +367 -0
- package/pi.dev-src/pi-mono/mom/src/sandbox.ts +221 -0
- package/pi.dev-src/pi-mono/mom/src/slack.ts +623 -0
- package/pi.dev-src/pi-mono/mom/src/store.ts +234 -0
- package/pi.dev-src/pi-mono/mom/src/tools/attach.ts +47 -0
- package/pi.dev-src/pi-mono/mom/src/tools/bash.ts +97 -0
- package/pi.dev-src/pi-mono/mom/src/tools/edit.ts +165 -0
- package/pi.dev-src/pi-mono/mom/src/tools/index.ts +19 -0
- package/pi.dev-src/pi-mono/mom/src/tools/read.ts +159 -0
- package/pi.dev-src/pi-mono/mom/src/tools/truncate.ts +236 -0
- package/pi.dev-src/pi-mono/mom/src/tools/write.ts +45 -0
- package/pi.dev-src/pi-mono/mom/test/events.test.ts +50 -0
- package/pi.dev-src/pi-mono/pods/scripts/model_run.sh +83 -0
- package/pi.dev-src/pi-mono/pods/scripts/pod_setup.sh +336 -0
- package/pi.dev-src/pi-mono/pods/src/cli.ts +360 -0
- package/pi.dev-src/pi-mono/pods/src/commands/models.ts +753 -0
- package/pi.dev-src/pi-mono/pods/src/commands/pods.ts +205 -0
- package/pi.dev-src/pi-mono/pods/src/commands/prompt.ts +84 -0
- package/pi.dev-src/pi-mono/pods/src/config.ts +80 -0
- package/pi.dev-src/pi-mono/pods/src/index.ts +2 -0
- package/pi.dev-src/pi-mono/pods/src/model-configs.ts +111 -0
- package/pi.dev-src/pi-mono/pods/src/models.json +295 -0
- package/pi.dev-src/pi-mono/pods/src/ssh.ts +151 -0
- package/pi.dev-src/pi-mono/pods/src/types.ts +27 -0
- package/pi.dev-src/pi-mono/tui/src/autocomplete.ts +783 -0
- package/pi.dev-src/pi-mono/tui/src/components/box.ts +137 -0
- package/pi.dev-src/pi-mono/tui/src/components/cancellable-loader.ts +40 -0
- package/pi.dev-src/pi-mono/tui/src/components/editor.ts +2280 -0
- package/pi.dev-src/pi-mono/tui/src/components/image.ts +104 -0
- package/pi.dev-src/pi-mono/tui/src/components/input.ts +503 -0
- package/pi.dev-src/pi-mono/tui/src/components/loader.ts +86 -0
- package/pi.dev-src/pi-mono/tui/src/components/markdown.ts +852 -0
- package/pi.dev-src/pi-mono/tui/src/components/select-list.ts +229 -0
- package/pi.dev-src/pi-mono/tui/src/components/settings-list.ts +250 -0
- package/pi.dev-src/pi-mono/tui/src/components/spacer.ts +28 -0
- package/pi.dev-src/pi-mono/tui/src/components/text.ts +106 -0
- package/pi.dev-src/pi-mono/tui/src/components/truncated-text.ts +65 -0
- package/pi.dev-src/pi-mono/tui/src/editor-component.ts +74 -0
- package/pi.dev-src/pi-mono/tui/src/fuzzy.ts +133 -0
- package/pi.dev-src/pi-mono/tui/src/index.ts +106 -0
- package/pi.dev-src/pi-mono/tui/src/keybindings.ts +244 -0
- package/pi.dev-src/pi-mono/tui/src/keys.ts +1400 -0
- package/pi.dev-src/pi-mono/tui/src/kill-ring.ts +46 -0
- package/pi.dev-src/pi-mono/tui/src/stdin-buffer.ts +386 -0
- package/pi.dev-src/pi-mono/tui/src/terminal-image.ts +414 -0
- package/pi.dev-src/pi-mono/tui/src/terminal.ts +373 -0
- package/pi.dev-src/pi-mono/tui/src/tui.ts +1243 -0
- package/pi.dev-src/pi-mono/tui/src/undo-stack.ts +28 -0
- package/pi.dev-src/pi-mono/tui/src/utils.ts +1085 -0
- package/pi.dev-src/pi-mono/tui/test/autocomplete.test.ts +542 -0
- package/pi.dev-src/pi-mono/tui/test/bug-regression-isimageline-startswith-bug.test.ts +237 -0
- package/pi.dev-src/pi-mono/tui/test/chat-simple.ts +129 -0
- package/pi.dev-src/pi-mono/tui/test/editor.test.ts +3812 -0
- package/pi.dev-src/pi-mono/tui/test/fuzzy.test.ts +98 -0
- package/pi.dev-src/pi-mono/tui/test/image-test.ts +56 -0
- package/pi.dev-src/pi-mono/tui/test/input.test.ts +580 -0
- package/pi.dev-src/pi-mono/tui/test/key-tester.ts +105 -0
- package/pi.dev-src/pi-mono/tui/test/keybindings.test.ts +38 -0
- package/pi.dev-src/pi-mono/tui/test/keys.test.ts +614 -0
- package/pi.dev-src/pi-mono/tui/test/markdown.test.ts +1236 -0
- package/pi.dev-src/pi-mono/tui/test/overlay-non-capturing.test.ts +609 -0
- package/pi.dev-src/pi-mono/tui/test/overlay-options.test.ts +538 -0
- package/pi.dev-src/pi-mono/tui/test/overlay-short-content.test.ts +56 -0
- package/pi.dev-src/pi-mono/tui/test/regression-regional-indicator-width.test.ts +52 -0
- package/pi.dev-src/pi-mono/tui/test/select-list.test.ts +116 -0
- package/pi.dev-src/pi-mono/tui/test/stdin-buffer.test.ts +422 -0
- package/pi.dev-src/pi-mono/tui/test/terminal-image.test.ts +279 -0
- package/pi.dev-src/pi-mono/tui/test/test-themes.ts +38 -0
- package/pi.dev-src/pi-mono/tui/test/truncate-to-width.test.ts +62 -0
- package/pi.dev-src/pi-mono/tui/test/truncated-text.test.ts +129 -0
- package/pi.dev-src/pi-mono/tui/test/tui-cell-size-input.test.ts +81 -0
- package/pi.dev-src/pi-mono/tui/test/tui-overlay-style-leak.test.ts +72 -0
- package/pi.dev-src/pi-mono/tui/test/tui-render.test.ts +509 -0
- package/pi.dev-src/pi-mono/tui/test/viewport-overwrite-repro.ts +106 -0
- package/pi.dev-src/pi-mono/tui/test/virtual-terminal.ts +218 -0
- package/pi.dev-src/pi-mono/tui/test/wrap-ansi.test.ts +207 -0
- package/pi.dev-src/pi-mono/tui/vitest.config.ts +7 -0
- package/pi.dev-src/pi-mono/web-ui/example/index.html +13 -0
- package/pi.dev-src/pi-mono/web-ui/example/src/app.css +1 -0
- package/pi.dev-src/pi-mono/web-ui/example/src/custom-messages.ts +99 -0
- package/pi.dev-src/pi-mono/web-ui/example/src/main.ts +421 -0
- package/pi.dev-src/pi-mono/web-ui/example/tsconfig.json +23 -0
- package/pi.dev-src/pi-mono/web-ui/example/vite.config.ts +6 -0
- package/pi.dev-src/pi-mono/web-ui/scripts/count-prompt-tokens.ts +88 -0
- package/pi.dev-src/pi-mono/web-ui/src/ChatPanel.ts +209 -0
- package/pi.dev-src/pi-mono/web-ui/src/app.css +68 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/AgentInterface.ts +403 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/AttachmentTile.ts +107 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/ConsoleBlock.ts +72 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/CustomProviderCard.ts +100 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/ExpandableSection.ts +46 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/Input.ts +113 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/MessageEditor.ts +405 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/MessageList.ts +98 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/Messages.ts +383 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/ProviderKeyInput.ts +153 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/SandboxedIframe.ts +626 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/StreamingMessageContainer.ts +103 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/ThinkingBlock.ts +43 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/message-renderer-registry.ts +28 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/sandbox/ArtifactsRuntimeProvider.ts +220 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/sandbox/AttachmentsRuntimeProvider.ts +66 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/sandbox/ConsoleRuntimeProvider.ts +186 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/sandbox/FileDownloadRuntimeProvider.ts +110 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/sandbox/RuntimeMessageBridge.ts +82 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/sandbox/RuntimeMessageRouter.ts +216 -0
- package/pi.dev-src/pi-mono/web-ui/src/components/sandbox/SandboxRuntimeProvider.ts +52 -0
- package/pi.dev-src/pi-mono/web-ui/src/dialogs/ApiKeyPromptDialog.ts +75 -0
- package/pi.dev-src/pi-mono/web-ui/src/dialogs/AttachmentOverlay.ts +636 -0
- package/pi.dev-src/pi-mono/web-ui/src/dialogs/CustomProviderDialog.ts +274 -0
- package/pi.dev-src/pi-mono/web-ui/src/dialogs/ModelSelector.ts +370 -0
- package/pi.dev-src/pi-mono/web-ui/src/dialogs/PersistentStorageDialog.ts +144 -0
- package/pi.dev-src/pi-mono/web-ui/src/dialogs/ProvidersModelsTab.ts +212 -0
- package/pi.dev-src/pi-mono/web-ui/src/dialogs/SessionListDialog.ts +150 -0
- package/pi.dev-src/pi-mono/web-ui/src/dialogs/SettingsDialog.ts +218 -0
- package/pi.dev-src/pi-mono/web-ui/src/index.ts +120 -0
- package/pi.dev-src/pi-mono/web-ui/src/prompts/prompts.ts +282 -0
- package/pi.dev-src/pi-mono/web-ui/src/storage/app-storage.ts +60 -0
- package/pi.dev-src/pi-mono/web-ui/src/storage/backends/indexeddb-storage-backend.ts +193 -0
- package/pi.dev-src/pi-mono/web-ui/src/storage/store.ts +33 -0
- package/pi.dev-src/pi-mono/web-ui/src/storage/stores/custom-providers-store.ts +62 -0
- package/pi.dev-src/pi-mono/web-ui/src/storage/stores/provider-keys-store.ts +33 -0
- package/pi.dev-src/pi-mono/web-ui/src/storage/stores/sessions-store.ts +136 -0
- package/pi.dev-src/pi-mono/web-ui/src/storage/stores/settings-store.ts +34 -0
- package/pi.dev-src/pi-mono/web-ui/src/storage/types.ts +206 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/ArtifactElement.ts +14 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/ArtifactPill.ts +26 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/Console.ts +93 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/DocxArtifact.ts +213 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/ExcelArtifact.ts +231 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/GenericArtifact.ts +117 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/HtmlArtifact.ts +195 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/ImageArtifact.ts +116 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/MarkdownArtifact.ts +82 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/PdfArtifact.ts +201 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/SvgArtifact.ts +119 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/TextArtifact.ts +148 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/artifacts-tool-renderer.ts +310 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/artifacts.ts +713 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/artifacts/index.ts +7 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/extract-document.ts +275 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/index.ts +46 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/javascript-repl.ts +293 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/renderer-registry.ts +130 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/renderers/BashRenderer.ts +52 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/renderers/CalculateRenderer.ts +58 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/renderers/DefaultRenderer.ts +103 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/renderers/GetCurrentTimeRenderer.ts +92 -0
- package/pi.dev-src/pi-mono/web-ui/src/tools/types.ts +15 -0
- package/pi.dev-src/pi-mono/web-ui/src/utils/attachment-utils.ts +472 -0
- package/pi.dev-src/pi-mono/web-ui/src/utils/auth-token.ts +22 -0
- package/pi.dev-src/pi-mono/web-ui/src/utils/format.ts +42 -0
- package/pi.dev-src/pi-mono/web-ui/src/utils/i18n.ts +653 -0
- package/pi.dev-src/pi-mono/web-ui/src/utils/model-discovery.ts +277 -0
- package/pi.dev-src/pi-mono/web-ui/src/utils/proxy-utils.ts +139 -0
- package/pi.dev-src/pi-mono/web-ui/src/utils/test-sessions.ts +2357 -0
- package/pi.dev-src/pi-mono/web-ui/tsconfig.json +7 -0
- package/scripts/lib/extension-debug-harness.ts +3 -10
- package/scripts/lib/recording-extension-api.ts +71 -2
- package/scripts/pi-usereq-debug.sh +1 -1
- package/scripts/tool-args-to-params.ts +4 -15
- package/src/cli.ts +24 -68
- package/src/core/agent-tool-json.ts +53 -239
- package/src/core/compress-payload.ts +4 -74
- package/src/core/compress.ts +26 -15
- package/src/core/config.ts +546 -65
- package/src/core/debug-runtime.ts +542 -0
- package/src/core/extension-status.ts +324 -202
- package/src/core/find-constructs.ts +3 -3
- package/src/core/find-payload.ts +26 -132
- package/src/core/path-context.ts +346 -81
- package/src/core/pi-notify.ts +585 -315
- package/src/core/pi-usereq-tools.ts +57 -19
- package/src/core/prompt-command-catalog.ts +46 -0
- package/src/core/prompt-command-runtime.ts +1650 -0
- package/src/core/prompt-command-state.ts +211 -0
- package/src/core/prompts.ts +173 -41
- package/src/core/reference-payload.ts +5 -63
- package/src/core/resources.ts +61 -5
- package/src/core/settings-menu.ts +33 -7
- package/src/core/source-analyzer.ts +27 -7
- package/src/core/token-counter.ts +61 -79
- package/src/core/tool-runner.ts +38 -317
- package/src/index.ts +2629 -1220
- package/src/resources/images/favicon.svg +21 -0
- package/src/resources/images/pi.dev.png +0 -0
- package/src/resources/instructions/git_commit.md +16 -0
- package/src/resources/instructions/git_read-only.md +2 -0
- package/src/resources/prompts/analyze.md +12 -13
- package/src/resources/prompts/change.md +21 -59
- package/src/resources/prompts/check.md +14 -16
- package/src/resources/prompts/cover.md +21 -59
- package/src/resources/prompts/create.md +5 -4
- package/src/resources/prompts/fix.md +20 -58
- package/src/resources/prompts/flowchart.md +14 -49
- package/src/resources/prompts/implement.md +14 -50
- package/src/resources/prompts/new.md +20 -58
- package/src/resources/prompts/readme.md +14 -50
- package/src/resources/prompts/recreate.md +14 -45
- package/src/resources/prompts/refactor.md +20 -58
- package/src/resources/prompts/references.md +7 -43
- package/src/resources/prompts/renumber.md +8 -39
- package/src/resources/prompts/workflow.md +14 -50
- package/src/resources/prompts/write.md +5 -4
- package/tests/attended-results-scenarios.ts +30 -136
- package/tests/cli-command-option-parity.test.ts +148 -192
- package/tests/debug-extension-harness.test.ts +74 -73
- package/tests/extension-registration.test.ts +3626 -685
- package/tests/fixtures_attended_results/project/compress-line-numbers.json +1 -1
- package/tests/fixtures_attended_results/project/compress.json +1 -1
- package/tests/fixtures_attended_results/project/find-line-numbers.json +1 -1
- package/tests/fixtures_attended_results/project/find.json +1 -1
- package/tests/fixtures_attended_results/project/references.json +2 -2
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_go.go.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_go.go.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-find/fixture_go.go.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_go.go.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_c.c.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_cpp.cpp.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_csharp.cs.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_elixir.ex.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_go.go.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_haskell.hs.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_java.java.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_javascript.js.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_kotlin.kt.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_lua.lua.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_perl.pl.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_php.php.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_python.py.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_ruby.rb.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_rust.rs.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_scala.scala.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_shell.sh.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_swift.swift.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_typescript.ts.json +1 -1
- package/tests/fixtures_attended_results/standalone/files-references/fixture_zig.zig.json +1 -1
- package/tests/helpers.ts +24 -15
- package/tests/oracle-project.test.ts +29 -30
- package/tests/oracle-standalone.test.ts +27 -1
- package/tests/prompt-rendering.test.ts +40 -9
- package/tests/python_oracle_stubs/tiktoken.py +76 -0
package/src/core/pi-notify.ts
CHANGED
|
@@ -1,70 +1,93 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file
|
|
3
|
-
* @brief Implements pi-usereq
|
|
4
|
-
* @details Centralizes configuration defaults, status serialization,
|
|
3
|
+
* @brief Implements pi-usereq command-notify, sound, and Pushover prompt-end helpers.
|
|
4
|
+
* @details Centralizes configuration defaults, status serialization, prompt-end outcome classification, placeholder substitution, detached shell-command execution, and native Pushover delivery. Runtime is O(m + c + b) in `agent_end` message count plus command length and Pushover payload size. Side effects include detached child-process spawning and outbound HTTPS requests.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
8
10
|
import * as https from "node:https";
|
|
9
11
|
import type { AgentEndEvent } from "@mariozechner/pi-coding-agent";
|
|
10
|
-
import { getInstallationPath } from "./path-context.js";
|
|
12
|
+
import { getInstallationPath, normalizePathSlashes } from "./path-context.js";
|
|
11
13
|
import type { UseReqConfig } from "./config.js";
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
|
-
* @brief Enumerates supported
|
|
15
|
-
* @details Defines the canonical persisted order used by config normalization, shortcut cycling, status rendering, and
|
|
16
|
+
* @brief Enumerates supported sound levels.
|
|
17
|
+
* @details Defines the canonical persisted order used by config normalization, shortcut cycling, status rendering, and sound-command selection. Access complexity is O(1).
|
|
16
18
|
*/
|
|
17
19
|
export const PI_NOTIFY_SOUND_LEVELS = ["none", "low", "mid", "high"] as const;
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
|
-
* @brief Represents one supported
|
|
21
|
-
* @details Narrows configuration parsing and runtime command dispatch to the canonical four-state
|
|
22
|
+
* @brief Represents one supported sound level.
|
|
23
|
+
* @details Narrows configuration parsing and runtime sound-command dispatch to the canonical four-state domain. Compile-time only and introduces no runtime cost.
|
|
22
24
|
*/
|
|
23
25
|
export type PiNotifySoundLevel = (typeof PI_NOTIFY_SOUND_LEVELS)[number];
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
|
-
* @brief Enumerates supported prompt-end
|
|
27
|
-
* @details Distinguishes
|
|
28
|
+
* @brief Enumerates supported prompt-end outcomes.
|
|
29
|
+
* @details Distinguishes completed, interrupted, and failed prompt termination states for cross-channel notification routing. Access complexity is O(1).
|
|
28
30
|
*/
|
|
29
|
-
export const PI_NOTIFY_OUTCOMES = ["
|
|
31
|
+
export const PI_NOTIFY_OUTCOMES = ["completed", "interrupted", "failed"] as const;
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
|
-
* @brief Represents one supported prompt-end
|
|
33
|
-
* @details Narrows prompt-end event classification and
|
|
34
|
+
* @brief Represents one supported prompt-end outcome.
|
|
35
|
+
* @details Narrows prompt-end event classification and per-feature toggle routing to the canonical completed/interrupted/failed domain. Compile-time only and introduces no runtime cost.
|
|
34
36
|
*/
|
|
35
37
|
export type PiNotifyOutcome = (typeof PI_NOTIFY_OUTCOMES)[number];
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
|
-
* @brief Defines the default
|
|
40
|
+
* @brief Defines the default sound toggle shortcut.
|
|
39
41
|
* @details Seeds persisted configuration when no project-specific shortcut exists. Access complexity is O(1).
|
|
40
42
|
* @satisfies REQ-134
|
|
41
43
|
*/
|
|
42
44
|
export const DEFAULT_PI_NOTIFY_SOUND_TOGGLE_SHORTCUT = "alt+s";
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
|
-
* @brief Defines the default
|
|
46
|
-
* @details Uses the bundled
|
|
47
|
-
* @satisfies REQ-
|
|
47
|
+
* @brief Defines the default command-notify shell command.
|
|
48
|
+
* @details Uses `notify-send`, the bundled icon, the fixed `PI-useReq` application name, and runtime placeholder substitution for prompt name, base path, elapsed time, and terminal outcome text. Access complexity is O(1).
|
|
49
|
+
* @satisfies REQ-175
|
|
50
|
+
*/
|
|
51
|
+
export const DEFAULT_PI_NOTIFY_CMD = "notify-send -i %%INSTALLATION_PATH%%/resources/images/pi.dev.png -a \"PI-useReq\" \"%%PROMT%% @ %%BASE%% [%%TIME%%]\" \"%%RESULT%%\"";
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @brief Defines the default low-volume sound command.
|
|
55
|
+
* @details Uses the bundled notification asset with a low playback volume and defers `%%INSTALLATION_PATH%%` substitution until runtime execution. Access complexity is O(1).
|
|
56
|
+
* @satisfies REQ-133
|
|
48
57
|
*/
|
|
49
58
|
export const DEFAULT_PI_NOTIFY_SOUND_LOW_CMD = "paplay --volume=21845 %%INSTALLATION_PATH%%/resources/sounds/Soft-high-tech-notification-sound-effect.mp3";
|
|
50
59
|
|
|
51
60
|
/**
|
|
52
|
-
* @brief Defines the default mid-
|
|
53
|
-
* @details Uses the bundled
|
|
54
|
-
* @satisfies REQ-133
|
|
61
|
+
* @brief Defines the default mid-volume sound command.
|
|
62
|
+
* @details Uses the bundled notification asset with a mid playback volume and defers `%%INSTALLATION_PATH%%` substitution until runtime execution. Access complexity is O(1).
|
|
63
|
+
* @satisfies REQ-133
|
|
55
64
|
*/
|
|
56
65
|
export const DEFAULT_PI_NOTIFY_SOUND_MID_CMD = "paplay --volume=43690 %%INSTALLATION_PATH%%/resources/sounds/Soft-high-tech-notification-sound-effect.mp3";
|
|
57
66
|
|
|
58
67
|
/**
|
|
59
|
-
* @brief Defines the default high-
|
|
60
|
-
* @details Uses the bundled
|
|
61
|
-
* @satisfies REQ-133
|
|
68
|
+
* @brief Defines the default high-volume sound command.
|
|
69
|
+
* @details Uses the bundled notification asset with a high playback volume and defers `%%INSTALLATION_PATH%%` substitution until runtime execution. Access complexity is O(1).
|
|
70
|
+
* @satisfies REQ-133
|
|
62
71
|
*/
|
|
63
72
|
export const DEFAULT_PI_NOTIFY_SOUND_HIGH_CMD = "paplay --volume=65535 %%INSTALLATION_PATH%%/resources/sounds/Soft-high-tech-notification-sound-effect.mp3";
|
|
64
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @brief Defines the default Pushover title template.
|
|
76
|
+
* @details Reuses the same runtime placeholder contract required by `PI_NOTIFY_CMD` except for `%%INSTALLATION_PATH%%`. Access complexity is O(1).
|
|
77
|
+
* @satisfies REQ-185
|
|
78
|
+
*/
|
|
79
|
+
export const DEFAULT_PI_NOTIFY_PUSHOVER_TITLE = "%%PROMT%% @ %%BASE%% [%%TIME%%]";
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @brief Defines the default Pushover text template.
|
|
83
|
+
* @details Prefixes outbound Pushover messages with the terminal outcome token and preserves the raw prompt arguments on the following line so notifications remain traceable to the invoked prompt command. Access complexity is O(1).
|
|
84
|
+
* @satisfies REQ-185
|
|
85
|
+
*/
|
|
86
|
+
export const DEFAULT_PI_NOTIFY_PUSHOVER_TEXT = "%%RESULT%%\n%%ARGS%%";
|
|
87
|
+
|
|
65
88
|
/**
|
|
66
89
|
* @brief Enumerates supported Pushover priorities.
|
|
67
|
-
* @details Restricts persisted Pushover delivery to the canonical normal and high-priority values accepted by the
|
|
90
|
+
* @details Restricts persisted Pushover delivery to the canonical normal and high-priority values accepted by the configuration menu. Access complexity is O(1).
|
|
68
91
|
*/
|
|
69
92
|
export const PI_NOTIFY_PUSHOVER_PRIORITIES = [0, 1] as const;
|
|
70
93
|
|
|
@@ -75,10 +98,10 @@ export const PI_NOTIFY_PUSHOVER_PRIORITIES = [0, 1] as const;
|
|
|
75
98
|
export type PiNotifyPushoverPriority = (typeof PI_NOTIFY_PUSHOVER_PRIORITIES)[number];
|
|
76
99
|
|
|
77
100
|
/**
|
|
78
|
-
* @brief Describes one
|
|
79
|
-
* @details Stores the prompt command name,
|
|
101
|
+
* @brief Describes one prompt-end request used for command-notify and Pushover substitution.
|
|
102
|
+
* @details Stores the prompt command name, raw prompt arguments, runtime base path, and final prompt duration required to resolve runtime placeholders. The interface is compile-time only and introduces no runtime cost.
|
|
80
103
|
*/
|
|
81
|
-
export interface
|
|
104
|
+
export interface PiNotifyEventRequest {
|
|
82
105
|
promptName: string;
|
|
83
106
|
promptArgs: string;
|
|
84
107
|
basePath: string;
|
|
@@ -87,31 +110,52 @@ export interface PiNotifyPushoverRequest {
|
|
|
87
110
|
|
|
88
111
|
/**
|
|
89
112
|
* @brief Describes the configuration fields consumed by pi-notify helpers.
|
|
90
|
-
* @details Narrows the full project config to the persisted
|
|
113
|
+
* @details Narrows the full project config to the persisted notify, sound, and Pushover fields used by status rendering, prompt-end routing, and shortcut toggles. Compile-time only and introduces no runtime cost.
|
|
91
114
|
*/
|
|
92
115
|
export type PiNotifyConfigFields = Pick<
|
|
93
116
|
UseReqConfig,
|
|
94
|
-
| "notify-
|
|
95
|
-
| "notify-
|
|
96
|
-
| "notify-
|
|
117
|
+
| "notify-enabled"
|
|
118
|
+
| "notify-on-completed"
|
|
119
|
+
| "notify-on-interrupted"
|
|
120
|
+
| "notify-on-failed"
|
|
97
121
|
| "notify-sound"
|
|
122
|
+
| "notify-sound-on-completed"
|
|
123
|
+
| "notify-sound-on-interrupted"
|
|
124
|
+
| "notify-sound-on-failed"
|
|
98
125
|
| "notify-sound-toggle-shortcut"
|
|
99
|
-
| "notify-pushover-
|
|
100
|
-
| "notify-pushover-on-
|
|
126
|
+
| "notify-pushover-enabled"
|
|
127
|
+
| "notify-pushover-on-completed"
|
|
128
|
+
| "notify-pushover-on-interrupted"
|
|
129
|
+
| "notify-pushover-on-failed"
|
|
101
130
|
| "notify-pushover-user-key"
|
|
102
131
|
| "notify-pushover-api-token"
|
|
103
132
|
| "notify-pushover-priority"
|
|
133
|
+
| "notify-pushover-title"
|
|
134
|
+
| "notify-pushover-text"
|
|
135
|
+
| "PI_NOTIFY_CMD"
|
|
104
136
|
| "PI_NOTIFY_SOUND_LOW_CMD"
|
|
105
137
|
| "PI_NOTIFY_SOUND_MID_CMD"
|
|
106
138
|
| "PI_NOTIFY_SOUND_HIGH_CMD"
|
|
107
139
|
>;
|
|
108
140
|
|
|
141
|
+
/**
|
|
142
|
+
* @brief Describes the shell-spawn callback used by prompt-end command dispatch.
|
|
143
|
+
* @details Narrows the injected spawn surface so deterministic tests can capture detached shell invocations without patching global module state externally. Compile-time only and introduces no runtime cost.
|
|
144
|
+
*/
|
|
145
|
+
type PiNotifySpawn = typeof spawn;
|
|
146
|
+
|
|
109
147
|
/**
|
|
110
148
|
* @brief Stores the currently configured native HTTPS request function used for Pushover delivery.
|
|
111
149
|
* @details Defaults to `node:https.request` and can be replaced by deterministic tests so Pushover dispatch remains observable without real network I/O. Access complexity is O(1). Side effect: mutated only through the dedicated test hook.
|
|
112
150
|
*/
|
|
113
151
|
let piNotifyHttpsRequest: typeof https.request = https.request;
|
|
114
152
|
|
|
153
|
+
/**
|
|
154
|
+
* @brief Stores the currently configured shell-spawn function used for notify and sound commands.
|
|
155
|
+
* @details Defaults to `node:child_process.spawn` and can be replaced by deterministic tests so detached shell-command execution remains observable without launching real child processes. Access complexity is O(1). Side effect: mutated only through the dedicated test hook.
|
|
156
|
+
*/
|
|
157
|
+
let piNotifySpawn: PiNotifySpawn = spawn;
|
|
158
|
+
|
|
115
159
|
/**
|
|
116
160
|
* @brief Normalizes one persisted sound level.
|
|
117
161
|
* @details Accepts only canonical `none|low|mid|high` values and falls back to `none` for missing or invalid payloads. Runtime is O(1). No external state is mutated.
|
|
@@ -139,17 +183,140 @@ export function normalizePiNotifyShortcut(value: unknown): string {
|
|
|
139
183
|
}
|
|
140
184
|
|
|
141
185
|
/**
|
|
142
|
-
* @brief Normalizes one persisted
|
|
143
|
-
* @details Accepts any non-empty string so project config can override bundled
|
|
186
|
+
* @brief Normalizes one persisted shell-command string.
|
|
187
|
+
* @details Accepts any non-empty string so project config can override bundled command templates verbatim and falls back to the supplied default when the payload is empty or invalid. Runtime is O(n) in command length. No external state is mutated.
|
|
144
188
|
* @param[in] value {unknown} Raw persisted command payload.
|
|
145
189
|
* @param[in] fallback {string} Canonical fallback command.
|
|
146
190
|
* @return {string} Canonical non-empty command string.
|
|
147
|
-
* @satisfies REQ-133
|
|
191
|
+
* @satisfies REQ-133, REQ-175
|
|
148
192
|
*/
|
|
149
193
|
export function normalizePiNotifyCommand(value: unknown, fallback: string): string {
|
|
150
194
|
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
151
195
|
}
|
|
152
196
|
|
|
197
|
+
/**
|
|
198
|
+
* @brief Normalizes one persisted template string.
|
|
199
|
+
* @details Accepts any non-empty string so Pushover title and text templates can be user-configured verbatim, preserves internal and edge control characters, and falls back to the supplied default when the payload is empty or invalid. Runtime is O(n) in template length. No external state is mutated.
|
|
200
|
+
* @param[in] value {unknown} Raw persisted template payload.
|
|
201
|
+
* @param[in] fallback {string} Canonical fallback template.
|
|
202
|
+
* @return {string} Canonical non-empty template string.
|
|
203
|
+
* @satisfies REQ-185, REQ-235
|
|
204
|
+
*/
|
|
205
|
+
export function normalizePiNotifyTemplateValue(value: unknown, fallback: string): string {
|
|
206
|
+
return typeof value === "string" && value.trim() ? value : fallback;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @brief Formats control characters for single-line menu rendering.
|
|
211
|
+
* @details Rewrites supported control bytes into escaped display sequences so configuration rows can render `Pushover text` inside a one-line settings list without executing the embedded control effects. Runtime is O(n) in text length. No external state is mutated.
|
|
212
|
+
* @param[in] value {string} Raw template text.
|
|
213
|
+
* @return {string} Escaped single-line display text.
|
|
214
|
+
* @satisfies REQ-235
|
|
215
|
+
*/
|
|
216
|
+
export function formatPiNotifyControlSequenceText(value: string): string {
|
|
217
|
+
let result = "";
|
|
218
|
+
for (const character of value) {
|
|
219
|
+
switch (character) {
|
|
220
|
+
case "\\":
|
|
221
|
+
result += "\\\\";
|
|
222
|
+
break;
|
|
223
|
+
case "\n":
|
|
224
|
+
result += "\\n";
|
|
225
|
+
break;
|
|
226
|
+
case "\r":
|
|
227
|
+
result += "\\r";
|
|
228
|
+
break;
|
|
229
|
+
case "\t":
|
|
230
|
+
result += "\\t";
|
|
231
|
+
break;
|
|
232
|
+
case "\0":
|
|
233
|
+
result += "\\0";
|
|
234
|
+
break;
|
|
235
|
+
case "\b":
|
|
236
|
+
result += "\\b";
|
|
237
|
+
break;
|
|
238
|
+
case "\f":
|
|
239
|
+
result += "\\f";
|
|
240
|
+
break;
|
|
241
|
+
case "\v":
|
|
242
|
+
result += "\\v";
|
|
243
|
+
break;
|
|
244
|
+
default:
|
|
245
|
+
result += character;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @brief Decodes supported escaped control sequences from one menu input string.
|
|
254
|
+
* @details Converts the documented `\n`, `\r`, `\t`, `\\`, `\0`, `\b`, `\f`, and `\v` escape sequences into their raw byte forms while preserving unknown escapes verbatim so user-entered text is not lossy. Runtime is O(n) in text length. No external state is mutated.
|
|
255
|
+
* @param[in] value {string} Escaped menu input text.
|
|
256
|
+
* @return {string} Decoded raw template text.
|
|
257
|
+
* @satisfies REQ-235
|
|
258
|
+
*/
|
|
259
|
+
export function parsePiNotifyControlSequenceText(value: string): string {
|
|
260
|
+
let result = "";
|
|
261
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
262
|
+
const character = value[index];
|
|
263
|
+
if (character !== "\\") {
|
|
264
|
+
result += character;
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const nextCharacter = value[index + 1];
|
|
268
|
+
if (nextCharacter === undefined) {
|
|
269
|
+
result += "\\";
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
switch (nextCharacter) {
|
|
273
|
+
case "\\":
|
|
274
|
+
result += "\\";
|
|
275
|
+
break;
|
|
276
|
+
case "n":
|
|
277
|
+
result += "\n";
|
|
278
|
+
break;
|
|
279
|
+
case "r":
|
|
280
|
+
result += "\r";
|
|
281
|
+
break;
|
|
282
|
+
case "t":
|
|
283
|
+
result += "\t";
|
|
284
|
+
break;
|
|
285
|
+
case "0":
|
|
286
|
+
result += "\0";
|
|
287
|
+
break;
|
|
288
|
+
case "b":
|
|
289
|
+
result += "\b";
|
|
290
|
+
break;
|
|
291
|
+
case "f":
|
|
292
|
+
result += "\f";
|
|
293
|
+
break;
|
|
294
|
+
case "v":
|
|
295
|
+
result += "\v";
|
|
296
|
+
break;
|
|
297
|
+
default:
|
|
298
|
+
result += `\\${nextCharacter}`;
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
index += 1;
|
|
302
|
+
}
|
|
303
|
+
return result;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* @brief Tests whether both persisted Pushover credentials are non-empty.
|
|
308
|
+
* @details Performs exact empty-string checks against the normalized user and token fields so UI locking, config persistence, and prompt-end delivery can share one readiness rule. Runtime is O(1). No external state is mutated.
|
|
309
|
+
* @param[in] config {Pick<UseReqConfig, "notify-pushover-user-key" | "notify-pushover-api-token">} Effective Pushover credential subset.
|
|
310
|
+
* @return {boolean} `true` when both Pushover credential fields are non-empty.
|
|
311
|
+
* @satisfies REQ-168, REQ-234
|
|
312
|
+
*/
|
|
313
|
+
export function hasPiNotifyPushoverCredentials(
|
|
314
|
+
config: Pick<UseReqConfig, "notify-pushover-user-key" | "notify-pushover-api-token">,
|
|
315
|
+
): boolean {
|
|
316
|
+
return config["notify-pushover-user-key"] !== ""
|
|
317
|
+
&& config["notify-pushover-api-token"] !== "";
|
|
318
|
+
}
|
|
319
|
+
|
|
153
320
|
/**
|
|
154
321
|
* @brief Normalizes one persisted Pushover credential string.
|
|
155
322
|
* @details Accepts any trimmed string so the project config can store raw Pushover user and token values verbatim and falls back to the empty string for missing or invalid payloads. Runtime is O(n) in credential length. No external state is mutated.
|
|
@@ -166,42 +333,32 @@ export function normalizePiNotifyPushoverCredential(value: unknown): string {
|
|
|
166
333
|
* @details Accepts only canonical `0` and `1` values, treating numeric-string `"1"` as high priority and every other payload as normal priority. Runtime is O(1). No external state is mutated.
|
|
167
334
|
* @param[in] value {unknown} Raw persisted priority payload.
|
|
168
335
|
* @return {PiNotifyPushoverPriority} Canonical priority value.
|
|
169
|
-
* @satisfies REQ-
|
|
336
|
+
* @satisfies REQ-172
|
|
170
337
|
*/
|
|
171
338
|
export function normalizePiNotifyPushoverPriority(value: unknown): PiNotifyPushoverPriority {
|
|
172
339
|
return value === 1 || value === "1" ? 1 : 0;
|
|
173
340
|
}
|
|
174
341
|
|
|
175
342
|
/**
|
|
176
|
-
* @brief Formats
|
|
177
|
-
* @details
|
|
178
|
-
* @param[in] config {
|
|
179
|
-
* @return {string}
|
|
180
|
-
* @satisfies REQ-
|
|
343
|
+
* @brief Formats the global command-notify flag for UI value rendering.
|
|
344
|
+
* @details Serializes only the persisted global command-notify enable state so configuration menus and summaries can report `on|off` independently from per-event toggles. Runtime is O(1). No external state is mutated.
|
|
345
|
+
* @param[in] config {Pick<UseReqConfig, "notify-enabled">} Effective command-notify configuration subset.
|
|
346
|
+
* @return {string} `on` when command-notify is globally enabled; otherwise `off`.
|
|
347
|
+
* @satisfies REQ-196
|
|
181
348
|
*/
|
|
182
|
-
export function
|
|
183
|
-
|
|
184
|
-
if (config["notify-beep-on-end"]) {
|
|
185
|
-
enabledOutcomes.push("end");
|
|
186
|
-
}
|
|
187
|
-
if (config["notify-beep-on-esc"]) {
|
|
188
|
-
enabledOutcomes.push("esc");
|
|
189
|
-
}
|
|
190
|
-
if (config["notify-beep-on-error"]) {
|
|
191
|
-
enabledOutcomes.push("err");
|
|
192
|
-
}
|
|
193
|
-
return enabledOutcomes.length > 0 ? enabledOutcomes.join(",") : "none";
|
|
349
|
+
export function formatPiNotifyStatus(config: Pick<UseReqConfig, "notify-enabled">): string {
|
|
350
|
+
return config["notify-enabled"] ? "on" : "off";
|
|
194
351
|
}
|
|
195
352
|
|
|
196
353
|
/**
|
|
197
|
-
* @brief Formats the Pushover
|
|
198
|
-
* @details Serializes only the persisted
|
|
199
|
-
* @param[in] config {Pick<UseReqConfig, "notify-pushover-
|
|
200
|
-
* @return {string} `on` when
|
|
201
|
-
* @satisfies REQ-
|
|
354
|
+
* @brief Formats the global Pushover flag for UI value rendering.
|
|
355
|
+
* @details Serializes only the persisted global Pushover enable state so configuration menus and summaries can report `on|off` independently from per-event toggles. Runtime is O(1). No external state is mutated.
|
|
356
|
+
* @param[in] config {Pick<UseReqConfig, "notify-pushover-enabled">} Effective Pushover configuration subset.
|
|
357
|
+
* @return {string} `on` when Pushover is globally enabled; otherwise `off`.
|
|
358
|
+
* @satisfies REQ-163
|
|
202
359
|
*/
|
|
203
|
-
export function formatPiNotifyPushoverStatus(config: Pick<UseReqConfig, "notify-pushover-
|
|
204
|
-
return config["notify-pushover-
|
|
360
|
+
export function formatPiNotifyPushoverStatus(config: Pick<UseReqConfig, "notify-pushover-enabled">): string {
|
|
361
|
+
return config["notify-pushover-enabled"] ? "on" : "off";
|
|
205
362
|
}
|
|
206
363
|
|
|
207
364
|
/**
|
|
@@ -220,114 +377,28 @@ export function cyclePiNotifySoundLevel(currentLevel: PiNotifySoundLevel): PiNot
|
|
|
220
377
|
}
|
|
221
378
|
|
|
222
379
|
/**
|
|
223
|
-
* @brief
|
|
224
|
-
* @details
|
|
225
|
-
* @param[in]
|
|
226
|
-
* @
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* @brief Builds the PowerShell script used for Windows toast notifications.
|
|
234
|
-
* @details Reuses the pi notify example contract, escapes title and body literals, and emits a one-shot script that shows a toast notification through the Windows Runtime API. Runtime is O(n) in payload length. No external state is mutated.
|
|
235
|
-
* @param[in] title {string} Notification title.
|
|
236
|
-
* @param[in] body {string} Notification body.
|
|
237
|
-
* @return {string} PowerShell script passed to `powershell.exe`.
|
|
238
|
-
*/
|
|
239
|
-
function windowsToastScript(title: string, body: string): string {
|
|
240
|
-
const type = "Windows.UI.Notifications";
|
|
241
|
-
const manager = `[${type}.ToastNotificationManager, ${type}, ContentType = WindowsRuntime]`;
|
|
242
|
-
const template = `[${type}.ToastTemplateType]::ToastText02`;
|
|
243
|
-
const escapedTitle = escapePowerShellLiteral(title);
|
|
244
|
-
const escapedBody = escapePowerShellLiteral(body);
|
|
245
|
-
return [
|
|
246
|
-
`${manager} > $null`,
|
|
247
|
-
`$xml = [${type}.ToastNotificationManager]::GetTemplateContent(${template})`,
|
|
248
|
-
`$texts = $xml.GetElementsByTagName('text')`,
|
|
249
|
-
`$texts[0].AppendChild($xml.CreateTextNode('${escapedTitle}')) > $null`,
|
|
250
|
-
`$texts[1].AppendChild($xml.CreateTextNode('${escapedBody}')) > $null`,
|
|
251
|
-
`$toast = [${type}.ToastNotification]::new($xml)`,
|
|
252
|
-
`[${type}.ToastNotificationManager]::CreateToastNotifier('pi-usereq').Show($toast)`,
|
|
253
|
-
].join("; ");
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* @brief Emits one OSC 777 terminal notification.
|
|
258
|
-
* @details Writes the Ghostty/iTerm2/WezTerm-compatible OSC 777 escape sequence directly to stdout using the supplied title and body payloads. Runtime is O(n) in payload length. Side effect: writes to stdout.
|
|
259
|
-
* @param[in] title {string} Notification title.
|
|
260
|
-
* @param[in] body {string} Notification body.
|
|
261
|
-
* @return {void} No return value.
|
|
262
|
-
* @satisfies REQ-130
|
|
380
|
+
* @brief Tests whether one outcome-specific toggle is enabled.
|
|
381
|
+
* @details Reuses the canonical completed/interrupted/failed routing order shared by notify, sound, and Pushover event toggles. Runtime is O(1). No external state is mutated.
|
|
382
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
383
|
+
* @param[in] completedEnabled {boolean} Enabled state for completed prompt termination.
|
|
384
|
+
* @param[in] interruptedEnabled {boolean} Enabled state for interrupted prompt termination.
|
|
385
|
+
* @param[in] failedEnabled {boolean} Enabled state for failed prompt termination.
|
|
386
|
+
* @return {boolean} `true` when the selected outcome flag is enabled.
|
|
263
387
|
*/
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
process.stdout.write(`\u001b]99;i=1:d=0;${title}\u001b\\`);
|
|
278
|
-
process.stdout.write(`\u001b]99;i=1:p=body;${body}\u001b\\`);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* @brief Emits one OSC 9 terminal notification.
|
|
283
|
-
* @details Writes the single-part OSC 9 sequence commonly used by terminals that accept message-only desktop notifications. Runtime is O(n) in payload length. Side effect: writes to stdout.
|
|
284
|
-
* @param[in] title {string} Notification title.
|
|
285
|
-
* @param[in] body {string} Notification body.
|
|
286
|
-
* @return {void} No return value.
|
|
287
|
-
* @satisfies REQ-130
|
|
288
|
-
*/
|
|
289
|
-
export function notifyOSC9(title: string, body: string): void {
|
|
290
|
-
process.stdout.write(`\u001b]9;${title}: ${body}\u0007`);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* @brief Emits one Windows toast notification.
|
|
295
|
-
* @details Spawns `powershell.exe` without waiting, delegates payload rendering to `windowsToastScript(...)`, and ignores transport failures so prompt-end handling remains non-blocking. Runtime is dominated by process spawn. Side effects include child-process execution.
|
|
296
|
-
* @param[in] title {string} Notification title.
|
|
297
|
-
* @param[in] body {string} Notification body.
|
|
298
|
-
* @return {void} No return value.
|
|
299
|
-
* @satisfies REQ-130
|
|
300
|
-
*/
|
|
301
|
-
export function notifyWindows(title: string, body: string): void {
|
|
302
|
-
void execFile(
|
|
303
|
-
"powershell.exe",
|
|
304
|
-
["-NoProfile", "-Command", windowsToastScript(title, body)],
|
|
305
|
-
() => undefined,
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* @brief Routes one prompt-end terminal notification through the detected terminal protocol.
|
|
311
|
-
* @details Prefers Windows toast delivery inside Windows Terminal, Kitty OSC 99 inside Kitty, OSC 9 inside iTerm-like terminals, and OSC 777 as the fallback path. Runtime is O(n) in payload length plus optional process spawn cost. Side effects include stdout writes or child-process execution.
|
|
312
|
-
* @param[in] title {string} Notification title.
|
|
313
|
-
* @param[in] body {string} Notification body.
|
|
314
|
-
* @return {void} No return value.
|
|
315
|
-
* @satisfies REQ-130
|
|
316
|
-
*/
|
|
317
|
-
export function notifyPiTerminal(title: string, body: string): void {
|
|
318
|
-
if (process.env.WT_SESSION) {
|
|
319
|
-
notifyWindows(title, body);
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
if (process.env.KITTY_WINDOW_ID) {
|
|
323
|
-
notifyOSC99(title, body);
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
if (process.env.TERM_PROGRAM === "iTerm.app" || process.env.TERM_PROGRAM === "Apple_Terminal") {
|
|
327
|
-
notifyOSC9(title, body);
|
|
328
|
-
return;
|
|
388
|
+
function isPiNotifyOutcomeEnabled(
|
|
389
|
+
outcome: PiNotifyOutcome,
|
|
390
|
+
completedEnabled: boolean,
|
|
391
|
+
interruptedEnabled: boolean,
|
|
392
|
+
failedEnabled: boolean,
|
|
393
|
+
): boolean {
|
|
394
|
+
switch (outcome) {
|
|
395
|
+
case "interrupted":
|
|
396
|
+
return interruptedEnabled;
|
|
397
|
+
case "failed":
|
|
398
|
+
return failedEnabled;
|
|
399
|
+
default:
|
|
400
|
+
return completedEnabled;
|
|
329
401
|
}
|
|
330
|
-
notifyOSC777(title, body);
|
|
331
402
|
}
|
|
332
403
|
|
|
333
404
|
/**
|
|
@@ -351,120 +422,387 @@ function hasAgentEndStopReason(
|
|
|
351
422
|
|
|
352
423
|
/**
|
|
353
424
|
* @brief Classifies one agent-end payload into the canonical pi-notify outcome.
|
|
354
|
-
* @details Treats assistant `stopReason=error` as `
|
|
425
|
+
* @details Treats assistant `stopReason=error` as `failed`, `stopReason=aborted` as `interrupted`, and every remaining terminal state as `completed`. Runtime is O(m) in message count. No external state is mutated.
|
|
355
426
|
* @param[in] event {Pick<AgentEndEvent, "messages">} Agent-end payload subset.
|
|
356
427
|
* @return {PiNotifyOutcome} Canonical prompt-end outcome.
|
|
357
|
-
* @satisfies REQ-129
|
|
358
428
|
*/
|
|
359
429
|
export function classifyPiNotifyOutcome(event: Pick<AgentEndEvent, "messages">): PiNotifyOutcome {
|
|
360
430
|
if (hasAgentEndStopReason(event.messages, "error")) {
|
|
361
|
-
return "
|
|
431
|
+
return "failed";
|
|
362
432
|
}
|
|
363
433
|
if (hasAgentEndStopReason(event.messages, "aborted")) {
|
|
364
|
-
return "
|
|
434
|
+
return "interrupted";
|
|
365
435
|
}
|
|
366
|
-
return "
|
|
436
|
+
return "completed";
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* @brief Formats one prompt-end duration for runtime placeholders.
|
|
441
|
+
* @details Floors the supplied duration to whole seconds, keeps minutes unbounded above 59, and zero-pads seconds to two digits so `%%TIME%%` aligns with status-bar elapsed formatting. Runtime is O(1). No external state is mutated.
|
|
442
|
+
* @param[in] durationMs {number} Prompt-end duration in milliseconds.
|
|
443
|
+
* @return {string} Duration rendered as `M:SS`.
|
|
444
|
+
* @satisfies REQ-187
|
|
445
|
+
*/
|
|
446
|
+
function formatPiNotifyDuration(durationMs: number): string {
|
|
447
|
+
const totalSeconds = Math.max(0, Math.floor(durationMs / 1000));
|
|
448
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
449
|
+
const seconds = totalSeconds % 60;
|
|
450
|
+
return `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
367
451
|
}
|
|
368
452
|
|
|
369
453
|
/**
|
|
370
|
-
* @brief
|
|
371
|
-
* @details
|
|
372
|
-
* @
|
|
454
|
+
* @brief Formats one runtime base path for placeholder substitution.
|
|
455
|
+
* @details Emits `~` or `~/...` when the supplied path equals or descends from the current user home directory; otherwise emits the slash-normalized absolute path. Runtime is O(p) in path length. No external state is mutated.
|
|
456
|
+
* @param[in] basePath {string} Runtime base path.
|
|
457
|
+
* @return {string} Placeholder-ready base path string.
|
|
458
|
+
* @satisfies REQ-187
|
|
373
459
|
*/
|
|
374
|
-
function
|
|
375
|
-
|
|
460
|
+
function formatPiNotifyBasePath(basePath: string): string {
|
|
461
|
+
const normalizedBasePath = path.resolve(basePath);
|
|
462
|
+
const homePath = path.resolve(os.homedir());
|
|
463
|
+
if (normalizedBasePath === homePath) {
|
|
464
|
+
return "~";
|
|
465
|
+
}
|
|
466
|
+
const relativePath = path.relative(homePath, normalizedBasePath);
|
|
467
|
+
if (relativePath !== "" && !relativePath.startsWith("..") && !path.isAbsolute(relativePath)) {
|
|
468
|
+
return `~/${normalizePathSlashes(relativePath)}`;
|
|
469
|
+
}
|
|
470
|
+
return normalizePathSlashes(normalizedBasePath);
|
|
376
471
|
}
|
|
377
472
|
|
|
378
473
|
/**
|
|
379
|
-
* @brief
|
|
380
|
-
* @details Maps
|
|
381
|
-
* @param[in] outcome {PiNotifyOutcome}
|
|
382
|
-
* @return {string}
|
|
474
|
+
* @brief Formats one prompt-end outcome for `%%RESULT%%` substitution.
|
|
475
|
+
* @details Maps canonical prompt-end outcomes to the persisted human-readable result tokens reused by default notify-command and Pushover templates. Runtime is O(1). No external state is mutated.
|
|
476
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
477
|
+
* @return {string} `successed`, `aborted`, or `failed`.
|
|
478
|
+
* @satisfies REQ-169, REQ-186, REQ-199
|
|
383
479
|
*/
|
|
384
|
-
function
|
|
480
|
+
function formatPiNotifyResult(outcome: PiNotifyOutcome): string {
|
|
385
481
|
switch (outcome) {
|
|
386
|
-
case "
|
|
387
|
-
return "
|
|
388
|
-
case "
|
|
389
|
-
return "
|
|
482
|
+
case "interrupted":
|
|
483
|
+
return "aborted";
|
|
484
|
+
case "failed":
|
|
485
|
+
return "failed";
|
|
390
486
|
default:
|
|
391
|
-
return "
|
|
487
|
+
return "successed";
|
|
392
488
|
}
|
|
393
489
|
}
|
|
394
490
|
|
|
395
491
|
/**
|
|
396
|
-
* @brief
|
|
397
|
-
* @details
|
|
398
|
-
* @param[in]
|
|
399
|
-
* @
|
|
400
|
-
* @
|
|
492
|
+
* @brief Builds the raw runtime placeholder map for one prompt-end request.
|
|
493
|
+
* @details Resolves every placeholder value exactly once so notify-command and Pushover template substitution reuse the same prompt name, base path, elapsed time, argument string, and terminal outcome token. Runtime is O(p) in path length. No external state is mutated.
|
|
494
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
495
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
496
|
+
* @return {{ "%%PROMT%%": string; "%%BASE%%": string; "%%TIME%%": string; "%%ARGS%%": string; "%%RESULT%%": string }} Raw placeholder-value map.
|
|
401
497
|
*/
|
|
402
|
-
function
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
return
|
|
498
|
+
function buildPiNotifyRuntimeTemplateValues(
|
|
499
|
+
request: PiNotifyEventRequest,
|
|
500
|
+
outcome: PiNotifyOutcome,
|
|
501
|
+
): Record<string, string> {
|
|
502
|
+
return {
|
|
503
|
+
"%%PROMT%%": request.promptName,
|
|
504
|
+
"%%BASE%%": formatPiNotifyBasePath(request.basePath),
|
|
505
|
+
"%%TIME%%": formatPiNotifyDuration(request.completionTimeMs),
|
|
506
|
+
"%%ARGS%%": request.promptArgs,
|
|
507
|
+
"%%RESULT%%": formatPiNotifyResult(outcome),
|
|
508
|
+
};
|
|
407
509
|
}
|
|
408
510
|
|
|
409
511
|
/**
|
|
410
|
-
* @brief
|
|
411
|
-
* @details
|
|
412
|
-
* @param[in]
|
|
413
|
-
* @return {string}
|
|
414
|
-
* @satisfies REQ-169
|
|
512
|
+
* @brief Quotes one installation path for shell substitution.
|
|
513
|
+
* @details Emits POSIX single-quoted literals for `sh -lc` execution and CMD double-quoted literals for `cmd.exe /c` execution so `%%INSTALLATION_PATH%%` substitutions preserve whitespace safely. Runtime is O(n) in path length. No external state is mutated.
|
|
514
|
+
* @param[in] installationPath {string} Absolute extension installation path.
|
|
515
|
+
* @return {string} Shell-quoted installation path fragment.
|
|
415
516
|
*/
|
|
416
|
-
function
|
|
417
|
-
|
|
517
|
+
function quotePiNotifyInstallPath(installationPath: string): string {
|
|
518
|
+
if (process.platform === "win32") {
|
|
519
|
+
return `"${installationPath.replace(/"/g, '""')}"`;
|
|
520
|
+
}
|
|
521
|
+
return `'${installationPath.replace(/'/g, `'\\''`)}'`;
|
|
418
522
|
}
|
|
419
523
|
|
|
420
524
|
/**
|
|
421
|
-
* @brief
|
|
422
|
-
* @details
|
|
423
|
-
* @param[in]
|
|
424
|
-
* @return {string}
|
|
525
|
+
* @brief Escapes one placeholder value for double-quoted shell insertion.
|
|
526
|
+
* @details Escapes the characters interpreted specially by POSIX or CMD double-quoted strings so default notify-command templates remain safe when placeholders are embedded inside double quotes. Runtime is O(n) in value length. No external state is mutated.
|
|
527
|
+
* @param[in] value {string} Raw placeholder value.
|
|
528
|
+
* @return {string} Shell-escaped placeholder fragment without surrounding quotes.
|
|
529
|
+
*/
|
|
530
|
+
function escapePiNotifyShellTemplateValue(value: string): string {
|
|
531
|
+
if (process.platform === "win32") {
|
|
532
|
+
return value.replace(/%/g, "%%").replace(/"/g, '""');
|
|
533
|
+
}
|
|
534
|
+
return value
|
|
535
|
+
.replace(/\\/g, "\\\\")
|
|
536
|
+
.replace(/\$/g, "\\$")
|
|
537
|
+
.replace(/`/g, "\\`")
|
|
538
|
+
.replace(/"/g, '\\"');
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* @brief Substitutes `%%INSTALLATION_PATH%%` inside one shell command.
|
|
543
|
+
* @details Replaces every `%%INSTALLATION_PATH%%` token with a shell-quoted runtime installation path so bundled assets can be addressed safely from external commands. Runtime is O(n) in command length. No external state is mutated.
|
|
544
|
+
* @param[in] command {string} Raw configured shell command.
|
|
545
|
+
* @param[in] installationPath {string} Absolute extension installation path.
|
|
546
|
+
* @return {string} Runtime-ready command string.
|
|
425
547
|
* @satisfies REQ-169
|
|
426
548
|
*/
|
|
427
|
-
function
|
|
428
|
-
return
|
|
549
|
+
export function substitutePiNotifyInstallPath(command: string, installationPath: string): string {
|
|
550
|
+
return command.replaceAll(
|
|
551
|
+
"%%INSTALLATION_PATH%%",
|
|
552
|
+
quotePiNotifyInstallPath(installationPath),
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* @brief Substitutes runtime placeholders inside one shell-command template.
|
|
558
|
+
* @details Applies shell-quoted installation-path substitution plus shell-escaped prompt, base-path, elapsed-time, raw-argument, and outcome-result substitution expected by `PI_NOTIFY_CMD`. Runtime is O(n) in template length. No external state is mutated.
|
|
559
|
+
* @param[in] template {string} Raw shell-command template.
|
|
560
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
561
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
562
|
+
* @param[in] installationPath {string} Absolute extension installation path.
|
|
563
|
+
* @return {string} Runtime-ready shell command.
|
|
564
|
+
* @satisfies REQ-169, REQ-199
|
|
565
|
+
*/
|
|
566
|
+
function substitutePiNotifyShellTemplate(
|
|
567
|
+
template: string,
|
|
568
|
+
request: PiNotifyEventRequest,
|
|
569
|
+
outcome: PiNotifyOutcome,
|
|
570
|
+
installationPath: string,
|
|
571
|
+
): string {
|
|
572
|
+
const runtimeValues = buildPiNotifyRuntimeTemplateValues(request, outcome);
|
|
573
|
+
let result = substitutePiNotifyInstallPath(template, installationPath);
|
|
574
|
+
for (const [token, value] of Object.entries(runtimeValues)) {
|
|
575
|
+
result = result.replaceAll(token, escapePiNotifyShellTemplateValue(value));
|
|
576
|
+
}
|
|
577
|
+
return result;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* @brief Substitutes runtime placeholders inside one text template.
|
|
582
|
+
* @details Applies raw prompt name, home-relative base path, elapsed time, raw prompt arguments, and terminal outcome text without shell escaping so Pushover payloads preserve literal text. Runtime is O(n) in template length. No external state is mutated.
|
|
583
|
+
* @param[in] template {string} Raw text template.
|
|
584
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
585
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
586
|
+
* @return {string} Placeholder-resolved text string.
|
|
587
|
+
* @satisfies REQ-186, REQ-187, REQ-199
|
|
588
|
+
*/
|
|
589
|
+
function substitutePiNotifyTextTemplate(
|
|
590
|
+
template: string,
|
|
591
|
+
request: PiNotifyEventRequest,
|
|
592
|
+
outcome: PiNotifyOutcome,
|
|
593
|
+
): string {
|
|
594
|
+
let result = template;
|
|
595
|
+
for (const [token, value] of Object.entries(buildPiNotifyRuntimeTemplateValues(request, outcome))) {
|
|
596
|
+
result = result.replaceAll(token, value);
|
|
597
|
+
}
|
|
598
|
+
return result;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* @brief Executes one detached shell command without waiting for completion.
|
|
603
|
+
* @details Uses the platform-default shell contract already employed by sound-command execution and ignores transport failures so prompt-end handling remains non-blocking. Runtime is dominated by process spawn. Side effects include detached child-process execution.
|
|
604
|
+
* @param[in] command {string} Runtime-ready shell command.
|
|
605
|
+
* @return {void} No return value.
|
|
606
|
+
*/
|
|
607
|
+
function runPiNotifyShellCommand(command: string): void {
|
|
608
|
+
const shell = process.platform === "win32" ? "cmd.exe" : (process.env.SHELL ?? "sh");
|
|
609
|
+
const shellArgs = process.platform === "win32"
|
|
610
|
+
? ["/d", "/s", "/c", command]
|
|
611
|
+
: ["-lc", command];
|
|
612
|
+
const child = piNotifySpawn(shell, shellArgs, {
|
|
613
|
+
detached: true,
|
|
614
|
+
stdio: "ignore",
|
|
615
|
+
});
|
|
616
|
+
child.once("error", () => undefined);
|
|
617
|
+
child.unref();
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* @brief Determines whether one prompt-end outcome should trigger command-notify.
|
|
622
|
+
* @details Requires a prompt-end request, the global command-notify enable flag, and the corresponding per-event notify toggle. Runtime is O(1). No external state is mutated.
|
|
623
|
+
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
624
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
625
|
+
* @param[in] request {PiNotifyEventRequest | undefined} Prompt-end request metadata.
|
|
626
|
+
* @return {boolean} `true` when command-notify prerequisites are satisfied.
|
|
627
|
+
* @satisfies REQ-174, REQ-176
|
|
628
|
+
*/
|
|
629
|
+
function shouldRunPiNotifyCommand(
|
|
630
|
+
config: PiNotifyConfigFields,
|
|
631
|
+
outcome: PiNotifyOutcome,
|
|
632
|
+
request: PiNotifyEventRequest | undefined,
|
|
633
|
+
): boolean {
|
|
634
|
+
return request !== undefined
|
|
635
|
+
&& config["notify-enabled"]
|
|
636
|
+
&& isPiNotifyOutcomeEnabled(
|
|
637
|
+
outcome,
|
|
638
|
+
config["notify-on-completed"],
|
|
639
|
+
config["notify-on-interrupted"],
|
|
640
|
+
config["notify-on-failed"],
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* @brief Executes the configured command-notify shell command.
|
|
646
|
+
* @details Resolves the runtime installation path, substitutes runtime placeholders into `PI_NOTIFY_CMD`, and spawns the resulting command without waiting for completion. Runtime is dominated by process spawn. Side effects include detached child-process execution.
|
|
647
|
+
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
648
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
649
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
650
|
+
* @return {void} No return value.
|
|
651
|
+
* @satisfies REQ-169, REQ-175, REQ-176, REQ-199
|
|
652
|
+
*/
|
|
653
|
+
function runPiNotifyCommand(
|
|
654
|
+
config: PiNotifyConfigFields,
|
|
655
|
+
outcome: PiNotifyOutcome,
|
|
656
|
+
request: PiNotifyEventRequest,
|
|
657
|
+
): void {
|
|
658
|
+
const installationPath = getInstallationPath();
|
|
659
|
+
const command = substitutePiNotifyShellTemplate(
|
|
660
|
+
config.PI_NOTIFY_CMD,
|
|
661
|
+
request,
|
|
662
|
+
outcome,
|
|
663
|
+
installationPath,
|
|
664
|
+
);
|
|
665
|
+
runPiNotifyShellCommand(command);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* @brief Resolves the configured command for one non-`none` sound level.
|
|
670
|
+
* @details Selects the matching persisted command string from config without performing runtime substitution or shell execution. Runtime is O(1). No external state is mutated.
|
|
671
|
+
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
672
|
+
* @param[in] soundLevel {Exclude<PiNotifySoundLevel, "none">} Non-disabled sound level.
|
|
673
|
+
* @return {string} Configured command string for the requested level.
|
|
674
|
+
*/
|
|
675
|
+
function resolvePiNotifySoundCommand(
|
|
676
|
+
config: PiNotifyConfigFields,
|
|
677
|
+
soundLevel: Exclude<PiNotifySoundLevel, "none">,
|
|
678
|
+
): string {
|
|
679
|
+
switch (soundLevel) {
|
|
680
|
+
case "low":
|
|
681
|
+
return config.PI_NOTIFY_SOUND_LOW_CMD;
|
|
682
|
+
case "mid":
|
|
683
|
+
return config.PI_NOTIFY_SOUND_MID_CMD;
|
|
684
|
+
case "high":
|
|
685
|
+
return config.PI_NOTIFY_SOUND_HIGH_CMD;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* @brief Determines whether one prompt-end outcome should trigger sound-command execution.
|
|
691
|
+
* @details Requires a non-`none` sound level and the corresponding per-event sound toggle. Runtime is O(1). No external state is mutated.
|
|
692
|
+
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
693
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
694
|
+
* @return {boolean} `true` when sound-command prerequisites are satisfied.
|
|
695
|
+
* @satisfies REQ-178
|
|
696
|
+
*/
|
|
697
|
+
function shouldRunPiNotifySound(
|
|
698
|
+
config: PiNotifyConfigFields,
|
|
699
|
+
outcome: PiNotifyOutcome,
|
|
700
|
+
): boolean {
|
|
701
|
+
return config["notify-sound"] !== "none"
|
|
702
|
+
&& isPiNotifyOutcomeEnabled(
|
|
703
|
+
outcome,
|
|
704
|
+
config["notify-sound-on-completed"],
|
|
705
|
+
config["notify-sound-on-interrupted"],
|
|
706
|
+
config["notify-sound-on-failed"],
|
|
707
|
+
);
|
|
429
708
|
}
|
|
430
709
|
|
|
431
710
|
/**
|
|
432
|
-
* @brief
|
|
433
|
-
* @details
|
|
711
|
+
* @brief Executes the configured sound command on an external shell.
|
|
712
|
+
* @details Resolves the runtime installation path, substitutes `%%INSTALLATION_PATH%%`, and spawns the configured command without waiting for completion. Runtime is dominated by process spawn. Side effects include detached child-process execution.
|
|
434
713
|
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
435
|
-
* @param[in]
|
|
714
|
+
* @param[in] soundLevel {Exclude<PiNotifySoundLevel, "none">} Requested non-disabled sound level.
|
|
715
|
+
* @return {void} No return value.
|
|
716
|
+
* @satisfies REQ-132, REQ-133
|
|
717
|
+
*/
|
|
718
|
+
export function runPiNotifySoundCommand(
|
|
719
|
+
config: PiNotifyConfigFields,
|
|
720
|
+
soundLevel: Exclude<PiNotifySoundLevel, "none">,
|
|
721
|
+
): void {
|
|
722
|
+
const rawCommand = resolvePiNotifySoundCommand(config, soundLevel);
|
|
723
|
+
const command = substitutePiNotifyInstallPath(rawCommand, getInstallationPath());
|
|
724
|
+
runPiNotifyShellCommand(command);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* @brief Determines whether one prompt-end outcome should trigger Pushover delivery.
|
|
729
|
+
* @details Requires a prompt-end request, the global Pushover enable flag, the corresponding per-event Pushover toggle, and non-empty user plus token credentials. Runtime is O(1). No external state is mutated.
|
|
730
|
+
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
731
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
732
|
+
* @param[in] request {PiNotifyEventRequest | undefined} Prompt-end request metadata.
|
|
436
733
|
* @return {boolean} `true` when Pushover delivery prerequisites are satisfied.
|
|
437
|
-
* @satisfies REQ-166, REQ-168, REQ-
|
|
734
|
+
* @satisfies REQ-166, REQ-168, REQ-184
|
|
438
735
|
*/
|
|
439
736
|
function shouldRunPiNotifyPushover(
|
|
440
737
|
config: PiNotifyConfigFields,
|
|
441
|
-
|
|
738
|
+
outcome: PiNotifyOutcome,
|
|
739
|
+
request: PiNotifyEventRequest | undefined,
|
|
442
740
|
): boolean {
|
|
443
741
|
return request !== undefined
|
|
444
|
-
&& config["notify-pushover-
|
|
445
|
-
&&
|
|
446
|
-
|
|
447
|
-
|
|
742
|
+
&& config["notify-pushover-enabled"]
|
|
743
|
+
&& isPiNotifyOutcomeEnabled(
|
|
744
|
+
outcome,
|
|
745
|
+
config["notify-pushover-on-completed"],
|
|
746
|
+
config["notify-pushover-on-interrupted"],
|
|
747
|
+
config["notify-pushover-on-failed"],
|
|
748
|
+
)
|
|
749
|
+
&& hasPiNotifyPushoverCredentials(config);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* @brief Builds the Pushover notification title for one prompt-end request.
|
|
754
|
+
* @details Resolves the configured `notify-pushover-title` template with raw runtime placeholder substitution so the pushed title remains configurable and deterministic. Runtime is O(n) in template length. No external state is mutated.
|
|
755
|
+
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
756
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
757
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
758
|
+
* @return {string} Pushover title string.
|
|
759
|
+
* @satisfies REQ-185, REQ-186, REQ-187, REQ-199
|
|
760
|
+
*/
|
|
761
|
+
function buildPiNotifyPushoverTitle(
|
|
762
|
+
config: PiNotifyConfigFields,
|
|
763
|
+
outcome: PiNotifyOutcome,
|
|
764
|
+
request: PiNotifyEventRequest,
|
|
765
|
+
): string {
|
|
766
|
+
return substitutePiNotifyTextTemplate(config["notify-pushover-title"], request, outcome);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* @brief Builds the Pushover message body for one prompt-end request.
|
|
771
|
+
* @details Resolves the configured `notify-pushover-text` template with raw runtime placeholder substitution so the pushed text remains configurable and deterministic. Runtime is O(n) in template length. No external state is mutated.
|
|
772
|
+
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
773
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
774
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
775
|
+
* @return {string} Pushover message body.
|
|
776
|
+
* @satisfies REQ-185, REQ-186, REQ-187, REQ-199
|
|
777
|
+
*/
|
|
778
|
+
function buildPiNotifyPushoverBody(
|
|
779
|
+
config: PiNotifyConfigFields,
|
|
780
|
+
outcome: PiNotifyOutcome,
|
|
781
|
+
request: PiNotifyEventRequest,
|
|
782
|
+
): string {
|
|
783
|
+
return substitutePiNotifyTextTemplate(config["notify-pushover-text"], request, outcome);
|
|
448
784
|
}
|
|
449
785
|
|
|
450
786
|
/**
|
|
451
|
-
* @brief Builds the Pushover API payload for one
|
|
452
|
-
* @details Encodes the configured token, user key,
|
|
787
|
+
* @brief Builds the Pushover API payload for one prompt-end request.
|
|
788
|
+
* @details Encodes the configured token, user key, substituted title, priority, and substituted text as `application/x-www-form-urlencoded` fields accepted by the Pushover Message API. Runtime is O(n) in payload size. No external state is mutated.
|
|
453
789
|
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
454
|
-
* @param[in]
|
|
790
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
791
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
455
792
|
* @return {URLSearchParams} Encoded Pushover request payload.
|
|
456
|
-
* @satisfies REQ-167, REQ-
|
|
793
|
+
* @satisfies REQ-167, REQ-172, REQ-185, REQ-186, REQ-199
|
|
457
794
|
*/
|
|
458
795
|
function buildPiNotifyPushoverPayload(
|
|
459
796
|
config: PiNotifyConfigFields,
|
|
460
|
-
|
|
797
|
+
outcome: PiNotifyOutcome,
|
|
798
|
+
request: PiNotifyEventRequest,
|
|
461
799
|
): URLSearchParams {
|
|
462
800
|
return new URLSearchParams({
|
|
463
801
|
token: config["notify-pushover-api-token"],
|
|
464
802
|
user: config["notify-pushover-user-key"],
|
|
465
|
-
title: buildPiNotifyPushoverTitle(request),
|
|
803
|
+
title: buildPiNotifyPushoverTitle(config, outcome, request),
|
|
466
804
|
priority: String(config["notify-pushover-priority"]),
|
|
467
|
-
message: buildPiNotifyPushoverBody(request),
|
|
805
|
+
message: buildPiNotifyPushoverBody(config, outcome, request),
|
|
468
806
|
});
|
|
469
807
|
}
|
|
470
808
|
|
|
@@ -472,16 +810,18 @@ function buildPiNotifyPushoverPayload(
|
|
|
472
810
|
* @brief Dispatches one native HTTPS request to the Pushover Message API.
|
|
473
811
|
* @details Serializes the request body as URL-encoded form data, posts it to `https://api.pushover.net/1/messages.json`, drains the response, and ignores transport failures so prompt-end handling remains non-blocking. Runtime is dominated by outbound I/O. Side effects include one HTTPS request.
|
|
474
812
|
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
475
|
-
* @param[in]
|
|
813
|
+
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
814
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
476
815
|
* @return {void} No return value.
|
|
477
|
-
* @satisfies REQ-167, REQ-
|
|
816
|
+
* @satisfies REQ-167, REQ-199
|
|
478
817
|
*/
|
|
479
818
|
function runPiNotifyPushoverRequest(
|
|
480
819
|
config: PiNotifyConfigFields,
|
|
481
|
-
|
|
820
|
+
outcome: PiNotifyOutcome,
|
|
821
|
+
request: PiNotifyEventRequest,
|
|
482
822
|
): void {
|
|
483
823
|
const url = new URL("https://api.pushover.net/1/messages.json");
|
|
484
|
-
const body = buildPiNotifyPushoverPayload(config, request).toString();
|
|
824
|
+
const body = buildPiNotifyPushoverPayload(config, outcome, request).toString();
|
|
485
825
|
const httpRequest = piNotifyHttpsRequest(url, {
|
|
486
826
|
method: "POST",
|
|
487
827
|
headers: {
|
|
@@ -507,111 +847,41 @@ export function setPiNotifyHttpsRequestForTests(requestImpl: typeof https.reques
|
|
|
507
847
|
}
|
|
508
848
|
|
|
509
849
|
/**
|
|
510
|
-
* @brief
|
|
511
|
-
* @details
|
|
512
|
-
* @param[in]
|
|
513
|
-
* @return {string} Shell-quoted installation path fragment.
|
|
514
|
-
*/
|
|
515
|
-
function quotePiNotifyInstallPath(installationPath: string): string {
|
|
516
|
-
if (process.platform === "win32") {
|
|
517
|
-
return `"${installationPath.replace(/"/g, '""')}"`;
|
|
518
|
-
}
|
|
519
|
-
return `'${installationPath.replace(/'/g, `'\\''`)}'`;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* @brief Substitutes `%%INSTALLATION_PATH%%` inside one sound command.
|
|
524
|
-
* @details Replaces every `%%INSTALLATION_PATH%%` token with a shell-quoted runtime installation path so bundled sound assets can be addressed safely from external commands. Runtime is O(n) in command length. No external state is mutated.
|
|
525
|
-
* @param[in] command {string} Raw configured sound command.
|
|
526
|
-
* @param[in] installationPath {string} Absolute extension installation path.
|
|
527
|
-
* @return {string} Runtime-ready command string.
|
|
528
|
-
* @satisfies REQ-133
|
|
529
|
-
*/
|
|
530
|
-
export function substitutePiNotifyInstallPath(command: string, installationPath: string): string {
|
|
531
|
-
return command.replaceAll("%%INSTALLATION_PATH%%", quotePiNotifyInstallPath(installationPath));
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* @brief Resolves the configured command for one non-`none` sound level.
|
|
536
|
-
* @details Selects the matching persisted command string from config without performing runtime substitution or shell execution. Runtime is O(1). No external state is mutated.
|
|
537
|
-
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
538
|
-
* @param[in] soundLevel {Exclude<PiNotifySoundLevel, "none">} Non-disabled sound level.
|
|
539
|
-
* @return {string} Configured command string for the requested level.
|
|
540
|
-
*/
|
|
541
|
-
function resolvePiNotifySoundCommand(
|
|
542
|
-
config: PiNotifyConfigFields,
|
|
543
|
-
soundLevel: Exclude<PiNotifySoundLevel, "none">,
|
|
544
|
-
): string {
|
|
545
|
-
switch (soundLevel) {
|
|
546
|
-
case "low":
|
|
547
|
-
return config.PI_NOTIFY_SOUND_LOW_CMD;
|
|
548
|
-
case "mid":
|
|
549
|
-
return config.PI_NOTIFY_SOUND_MID_CMD;
|
|
550
|
-
case "high":
|
|
551
|
-
return config.PI_NOTIFY_SOUND_HIGH_CMD;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
/**
|
|
556
|
-
* @brief Executes the configured successful-run sound command on an external shell.
|
|
557
|
-
* @details Resolves the runtime installation path, substitutes `%%INSTALLATION_PATH%%`, spawns the configured shell command without waiting, and ignores transport failures so prompt-end handling remains non-blocking. Runtime is dominated by process spawn. Side effects include detached child-process execution.
|
|
558
|
-
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
559
|
-
* @param[in] soundLevel {Exclude<PiNotifySoundLevel, "none">} Requested non-disabled sound level.
|
|
850
|
+
* @brief Replaces the shell-spawn function used for notify and sound commands in deterministic tests.
|
|
851
|
+
* @details Accepts a drop-in `node:child_process.spawn` replacement and restores the native implementation when `undefined` is supplied. Runtime is O(1). Side effect: mutates the module-local shell transport hook.
|
|
852
|
+
* @param[in] spawnImpl {PiNotifySpawn | undefined} Replacement shell-spawn function.
|
|
560
853
|
* @return {void} No return value.
|
|
561
|
-
* @satisfies REQ-132, REQ-133
|
|
562
854
|
*/
|
|
563
|
-
export function
|
|
564
|
-
|
|
565
|
-
soundLevel: Exclude<PiNotifySoundLevel, "none">,
|
|
566
|
-
): void {
|
|
567
|
-
const rawCommand = resolvePiNotifySoundCommand(config, soundLevel);
|
|
568
|
-
const command = substitutePiNotifyInstallPath(rawCommand, getInstallationPath());
|
|
569
|
-
const shell = process.platform === "win32" ? "cmd.exe" : (process.env.SHELL ?? "sh");
|
|
570
|
-
const shellArgs = process.platform === "win32"
|
|
571
|
-
? ["/d", "/s", "/c", command]
|
|
572
|
-
: ["-lc", command];
|
|
573
|
-
const child = spawn(shell, shellArgs, {
|
|
574
|
-
detached: true,
|
|
575
|
-
stdio: "ignore",
|
|
576
|
-
});
|
|
577
|
-
child.once("error", () => undefined);
|
|
578
|
-
child.unref();
|
|
855
|
+
export function setPiNotifySpawnForTests(spawnImpl: PiNotifySpawn | undefined): void {
|
|
856
|
+
piNotifySpawn = spawnImpl ?? spawn;
|
|
579
857
|
}
|
|
580
858
|
|
|
581
859
|
/**
|
|
582
|
-
* @brief Dispatches prompt-end
|
|
583
|
-
* @details Classifies the terminal outcome,
|
|
860
|
+
* @brief Dispatches prompt-end notify, sound, and Pushover effects for one agent-end payload.
|
|
861
|
+
* @details Classifies the terminal outcome, executes `PI_NOTIFY_CMD` when command-notify prerequisites are satisfied, executes the configured sound command when sound prerequisites are satisfied, and dispatches the native Pushover request when Pushover prerequisites are satisfied. Runtime is O(m + c + b) in message count, command length, and Pushover payload size. Side effects include child-process spawning and outbound HTTPS requests.
|
|
584
862
|
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
585
863
|
* @param[in] event {Pick<AgentEndEvent, "messages">} Agent-end payload subset.
|
|
586
|
-
* @param[in]
|
|
864
|
+
* @param[in] request {PiNotifyEventRequest | undefined} Optional prompt-end request metadata used for command-notify and Pushover substitution.
|
|
587
865
|
* @return {void} No return value.
|
|
588
|
-
* @satisfies REQ-
|
|
866
|
+
* @satisfies REQ-131, REQ-132, REQ-133, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-176, REQ-178, REQ-184, REQ-185, REQ-186, REQ-187, REQ-199
|
|
589
867
|
*/
|
|
590
868
|
export function runPiNotifyEffects(
|
|
591
869
|
config: PiNotifyConfigFields,
|
|
592
870
|
event: Pick<AgentEndEvent, "messages">,
|
|
593
|
-
|
|
871
|
+
request?: PiNotifyEventRequest,
|
|
594
872
|
): void {
|
|
595
873
|
const outcome = classifyPiNotifyOutcome(event);
|
|
596
|
-
|
|
597
|
-
(outcome
|
|
598
|
-
|| (outcome === "esc" && config["notify-beep-on-esc"])
|
|
599
|
-
|| (outcome === "err" && config["notify-beep-on-error"])
|
|
600
|
-
);
|
|
601
|
-
if (shouldNotify) {
|
|
602
|
-
notifyPiTerminal(buildPiNotifyTitle(), buildPiNotifyBody(outcome));
|
|
603
|
-
}
|
|
604
|
-
if (outcome !== "end") {
|
|
605
|
-
return;
|
|
874
|
+
if (shouldRunPiNotifyCommand(config, outcome, request)) {
|
|
875
|
+
runPiNotifyCommand(config, outcome, request as PiNotifyEventRequest);
|
|
606
876
|
}
|
|
607
|
-
if (config
|
|
877
|
+
if (shouldRunPiNotifySound(config, outcome)) {
|
|
608
878
|
runPiNotifySoundCommand(
|
|
609
879
|
config,
|
|
610
880
|
config["notify-sound"] as Exclude<PiNotifySoundLevel, "none">,
|
|
611
881
|
);
|
|
612
882
|
}
|
|
613
|
-
if (!shouldRunPiNotifyPushover(config,
|
|
883
|
+
if (!shouldRunPiNotifyPushover(config, outcome, request)) {
|
|
614
884
|
return;
|
|
615
885
|
}
|
|
616
|
-
runPiNotifyPushoverRequest(config,
|
|
886
|
+
runPiNotifyPushoverRequest(config, outcome, request as PiNotifyEventRequest);
|
|
617
887
|
}
|