@oh-my-pi/pi-coding-agent 7.0.0 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/README.md +1 -1
- package/docs/hooks.md +2 -2
- package/docs/sdk.md +1 -1
- package/package.json +12 -11
- package/scripts/format-prompts.ts +143 -0
- package/scripts/generate-template.ts +1 -1
- package/src/cli/args.ts +3 -3
- package/src/cli/config-cli.ts +4 -4
- package/src/cli/file-processor.ts +3 -3
- package/src/cli/list-models.ts +2 -2
- package/src/cli/plugin-cli.ts +3 -3
- package/src/cli/session-picker.ts +2 -2
- package/src/cli/setup-cli.ts +2 -2
- package/src/cli/stats-cli.ts +1 -1
- package/src/cli/update-cli.ts +2 -2
- package/src/{core → config}/keybindings.ts +1 -1
- package/src/{core → config}/model-registry.ts +1 -1
- package/src/{core → config}/model-resolver.ts +3 -3
- package/src/{core → config}/prompt-templates.ts +2 -2
- package/src/{core → config}/settings-manager.ts +6 -6
- package/src/{core/cursor/exec-bridge.ts → cursor.ts} +4 -4
- package/src/discovery/agents-md.ts +4 -4
- package/src/discovery/builtin.ts +17 -17
- package/src/discovery/claude.ts +12 -12
- package/src/discovery/cline.ts +6 -6
- package/src/discovery/codex.ts +21 -21
- package/src/discovery/cursor.ts +9 -9
- package/src/discovery/gemini.ts +9 -9
- package/src/discovery/github.ts +6 -6
- package/src/discovery/helpers.ts +4 -4
- package/src/discovery/index.ts +16 -16
- package/src/discovery/mcp-json.ts +4 -4
- package/src/discovery/ssh.ts +4 -4
- package/src/discovery/vscode.ts +4 -4
- package/src/discovery/windsurf.ts +6 -6
- package/src/{core/tools/exa → exa}/company.ts +2 -3
- package/src/{core/tools/exa → exa}/index.ts +2 -2
- package/src/{core/tools/exa → exa}/linkedin.ts +2 -3
- package/src/{core/tools/exa → exa}/mcp-client.ts +2 -2
- package/src/{core/tools/exa → exa}/render.ts +3 -3
- package/src/{core/tools/exa → exa}/researcher.ts +1 -1
- package/src/{core/tools/exa → exa}/search.ts +2 -10
- package/src/{core/tools/exa → exa}/websets.ts +1 -1
- package/src/{core → exec}/bash-executor.ts +22 -6
- package/src/{core → export}/custom-share.ts +1 -1
- package/src/{core/export-html → export/html}/index.ts +3 -3
- package/src/{core → export}/ttsr.ts +2 -2
- package/src/{core → extensibility}/custom-commands/bundled/review/index.ts +4 -4
- package/src/{core → extensibility}/custom-commands/loader.ts +3 -3
- package/src/{core → extensibility}/custom-commands/types.ts +1 -1
- package/src/{core → extensibility}/custom-tools/loader.ts +9 -9
- package/src/{core → extensibility}/custom-tools/types.ts +6 -6
- package/src/{core → extensibility}/custom-tools/wrapper.ts +1 -1
- package/src/{core → extensibility}/extensions/loader.ts +8 -8
- package/src/{core → extensibility}/extensions/runner.ts +3 -3
- package/src/{core → extensibility}/extensions/types.ts +15 -15
- package/src/{core → extensibility}/extensions/wrapper.ts +1 -1
- package/src/{core → extensibility}/hooks/index.ts +1 -1
- package/src/{core → extensibility}/hooks/loader.ts +7 -7
- package/src/{core → extensibility}/hooks/runner.ts +4 -4
- package/src/{core → extensibility}/hooks/types.ts +9 -9
- package/src/{core → extensibility}/plugins/doctor.ts +1 -1
- package/src/{core → extensibility}/plugins/installer.ts +2 -3
- package/src/{core → extensibility}/plugins/paths.ts +1 -1
- package/src/{core → extensibility}/skills.ts +8 -48
- package/src/{core → extensibility}/slash-commands.ts +6 -6
- package/src/index.ts +127 -128
- package/src/internal-urls/agent-protocol.ts +126 -0
- package/src/internal-urls/artifact-protocol.ts +93 -0
- package/src/internal-urls/index.ts +28 -0
- package/src/internal-urls/json-query.ts +126 -0
- package/src/internal-urls/router.ts +69 -0
- package/src/internal-urls/rule-protocol.ts +56 -0
- package/src/internal-urls/skill-protocol.ts +112 -0
- package/src/internal-urls/types.ts +48 -0
- package/src/{core/python-executor.ts → ipy/executor.ts} +51 -11
- package/src/{core/python-gateway-coordinator.ts → ipy/gateway-coordinator.ts} +41 -325
- package/src/{core/python-kernel.ts → ipy/kernel.ts} +38 -10
- package/src/ipy/prelude.ts +3 -0
- package/src/{core/tools/lsp → lsp}/client.ts +7 -6
- package/src/{core/tools/lsp → lsp}/clients/biome-client.ts +1 -1
- package/src/{core/tools/lsp → lsp}/clients/index.ts +1 -1
- package/src/{core/tools/lsp → lsp}/clients/lsp-linter-client.ts +4 -4
- package/src/{core/tools/lsp → lsp}/config.ts +1 -1
- package/src/{core/tools/lsp → lsp}/index.ts +16 -15
- package/src/{core/tools/lsp → lsp}/render.ts +2 -2
- package/src/{core/tools/lsp → lsp}/types.ts +14 -16
- package/src/{core/tools/lsp → lsp}/utils.ts +1 -1
- package/src/main.ts +12 -12
- package/src/{core/mcp → mcp}/config.ts +8 -8
- package/src/{core/mcp → mcp}/loader.ts +5 -6
- package/src/{core/mcp → mcp}/manager.ts +2 -2
- package/src/{core/mcp → mcp}/tool-bridge.ts +35 -6
- package/src/{core/mcp → mcp}/tool-cache.ts +1 -1
- package/src/{core/mcp → mcp}/transports/http.ts +7 -1
- package/src/{core/mcp → mcp}/transports/stdio.ts +1 -1
- package/src/{core/mcp → mcp}/types.ts +1 -1
- package/src/migrations.ts +2 -2
- package/src/modes/{interactive/components → components}/armin.ts +1 -1
- package/src/modes/{interactive/components → components}/assistant-message.ts +1 -1
- package/src/modes/{interactive/components → components}/bash-execution.ts +37 -29
- package/src/modes/{interactive/components → components}/bordered-loader.ts +1 -1
- package/src/modes/{interactive/components → components}/branch-summary-message.ts +2 -2
- package/src/modes/{interactive/components → components}/compaction-summary-message.ts +2 -2
- package/src/modes/{interactive/components → components}/custom-message.ts +3 -3
- package/src/modes/{interactive/components → components}/diff.ts +1 -1
- package/src/modes/{interactive/components → components}/dynamic-border.ts +1 -1
- package/src/modes/{interactive/components → components}/extensions/extension-dashboard.ts +3 -3
- package/src/modes/{interactive/components → components}/extensions/extension-list.ts +2 -2
- package/src/modes/{interactive/components → components}/extensions/inspector-panel.ts +1 -1
- package/src/modes/{interactive/components → components}/extensions/state-manager.ts +11 -17
- package/src/modes/{interactive/components → components}/extensions/types.ts +1 -1
- package/src/modes/{interactive/components → components}/footer.ts +3 -3
- package/src/modes/{interactive/components → components}/history-search.ts +2 -2
- package/src/modes/{interactive/components → components}/hook-editor.ts +1 -1
- package/src/modes/{interactive/components → components}/hook-input.ts +1 -1
- package/src/modes/{interactive/components → components}/hook-message.ts +3 -3
- package/src/modes/{interactive/components → components}/hook-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/keybinding-hints.ts +2 -2
- package/src/modes/{interactive/components → components}/login-dialog.ts +1 -1
- package/src/modes/{interactive/components → components}/model-selector.ts +5 -5
- package/src/modes/{interactive/components → components}/oauth-selector.ts +2 -2
- package/src/modes/{interactive/components → components}/plugin-settings.ts +3 -3
- package/src/modes/{interactive/components → components}/python-execution.ts +35 -24
- package/src/modes/{interactive/components → components}/queue-mode-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/read-tool-group.ts +2 -2
- package/src/modes/{interactive/components → components}/session-selector.ts +3 -3
- package/src/modes/{interactive/components → components}/settings-defs.ts +2 -2
- package/src/modes/{interactive/components → components}/settings-selector.ts +2 -2
- package/src/modes/{interactive/components → components}/show-images-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/status-line/segments.ts +2 -2
- package/src/modes/{interactive/components → components}/status-line/separators.ts +1 -1
- package/src/modes/{interactive/components → components}/status-line/types.ts +2 -2
- package/src/modes/{interactive/components → components}/status-line-segment-editor.ts +2 -2
- package/src/modes/{interactive/components → components}/status-line.ts +3 -3
- package/src/modes/{interactive/components → components}/theme-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/thinking-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/todo-display.ts +3 -4
- package/src/modes/{interactive/components → components}/todo-reminder.ts +2 -2
- package/src/modes/{interactive/components → components}/tool-execution.ts +8 -8
- package/src/modes/{interactive/components → components}/tree-selector.ts +3 -3
- package/src/modes/{interactive/components → components}/ttsr-notification.ts +2 -2
- package/src/modes/{interactive/components → components}/user-message-selector.ts +1 -1
- package/src/modes/{interactive/components → components}/user-message.ts +1 -1
- package/src/modes/{interactive/components → components}/welcome.ts +2 -2
- package/src/modes/{interactive/controllers → controllers}/command-controller.ts +32 -30
- package/src/modes/{interactive/controllers → controllers}/event-controller.ts +9 -9
- package/src/modes/{interactive/controllers → controllers}/extension-ui-controller.ts +8 -8
- package/src/modes/{interactive/controllers → controllers}/input-controller.ts +6 -6
- package/src/modes/{interactive/controllers → controllers}/selector-controller.ts +16 -16
- package/src/modes/index.ts +1 -1
- package/src/modes/{interactive/interactive-mode.ts → interactive-mode.ts} +14 -14
- package/src/modes/print-mode.ts +1 -1
- package/src/modes/rpc/rpc-client.ts +3 -3
- package/src/modes/rpc/rpc-mode.ts +3 -3
- package/src/modes/rpc/rpc-types.ts +3 -3
- package/src/modes/{interactive/theme → theme}/theme.ts +1 -1
- package/src/modes/{interactive/types.ts → types.ts} +8 -9
- package/src/modes/{interactive/utils → utils}/ui-helpers.ts +20 -27
- package/src/{core/tools/patch → patch}/applicator.ts +1 -1
- package/src/{core/tools/patch → patch}/diff.ts +1 -1
- package/src/{core/tools/patch → patch}/index.ts +31 -36
- package/src/{core/tools/patch → patch}/shared.ts +9 -6
- package/src/prompts/agents/explore.md +83 -46
- package/src/prompts/agents/init.md +9 -4
- package/src/prompts/agents/plan.md +8 -7
- package/src/prompts/agents/reviewer.md +36 -18
- package/src/prompts/agents/task.md +4 -4
- package/src/prompts/compaction/branch-summary-preamble.md +0 -1
- package/src/prompts/review-request.md +0 -1
- package/src/prompts/system/custom-system-prompt.md +2 -14
- package/src/prompts/system/file-operations.md +0 -2
- package/src/prompts/system/system-prompt.md +147 -138
- package/src/prompts/system/web-search.md +26 -0
- package/src/prompts/tools/ask.md +31 -24
- package/src/prompts/tools/bash.md +20 -17
- package/src/prompts/tools/calculator.md +9 -5
- package/src/prompts/tools/fetch.md +16 -0
- package/src/prompts/tools/find.md +15 -5
- package/src/prompts/tools/gemini-image.md +21 -6
- package/src/prompts/tools/grep.md +28 -12
- package/src/prompts/tools/lsp.md +35 -14
- package/src/prompts/tools/patch.md +39 -41
- package/src/prompts/tools/python.md +59 -76
- package/src/prompts/tools/read.md +23 -22
- package/src/prompts/tools/replace.md +19 -12
- package/src/prompts/tools/ssh.md +21 -28
- package/src/prompts/tools/task.md +54 -44
- package/src/prompts/tools/todo-write.md +52 -163
- package/src/prompts/tools/web-search.md +16 -9
- package/src/prompts/tools/write.md +13 -2
- package/src/{core/sdk.ts → sdk.ts} +65 -34
- package/src/{core → session}/agent-session.ts +45 -37
- package/src/{core → session}/agent-storage.ts +2 -2
- package/src/session/artifacts.ts +110 -0
- package/src/{core → session}/auth-storage.ts +1 -1
- package/src/{core → session}/compaction/branch-summarization.ts +5 -5
- package/src/{core → session}/compaction/compaction.ts +6 -6
- package/src/{core → session}/compaction/utils.ts +3 -3
- package/src/{core → session}/history-storage.ts +1 -1
- package/src/{core → session}/messages.ts +6 -8
- package/src/{core → session}/session-manager.ts +2 -2
- package/src/{core → session}/storage-migration.ts +2 -2
- package/src/session/streaming-output.ts +177 -0
- package/src/{core/ssh → ssh}/connection-manager.ts +1 -1
- package/src/{core/ssh → ssh}/ssh-executor.ts +19 -4
- package/src/{core/ssh → ssh}/sshfs-mount.ts +1 -1
- package/src/{core/system-prompt.ts → system-prompt.ts} +8 -37
- package/src/{core/tools/task → task}/agents.ts +8 -8
- package/src/{core/tools/task → task}/commands.ts +5 -6
- package/src/{core/tools/task → task}/discovery.ts +3 -3
- package/src/{core/tools/task → task}/executor.ts +34 -44
- package/src/{core/tools/task → task}/index.ts +206 -50
- package/src/{core/tools/task → task}/render.ts +80 -23
- package/src/{core/tools/task → task}/subprocess-tool-registry.ts +1 -1
- package/src/task/template.ts +47 -0
- package/src/{core/tools/task → task}/types.ts +19 -27
- package/src/{core/tools/task → task}/worker-protocol.ts +8 -4
- package/src/{core/tools/task → task}/worker.ts +34 -29
- package/src/task/worktree.ts +166 -0
- package/src/{core/tools → tools}/ask.ts +13 -21
- package/src/{core/tools → tools}/bash-interceptor.ts +1 -1
- package/src/{core/tools → tools}/bash.ts +61 -63
- package/src/{core/tools → tools}/calculator.ts +4 -4
- package/src/{core/tools → tools}/complete.ts +1 -1
- package/src/{core/tools → tools}/context.ts +2 -2
- package/src/{core/tools/web-fetch.ts → tools/fetch.ts} +97 -76
- package/src/{core/tools → tools}/find.ts +80 -104
- package/src/{core/tools → tools}/gemini-image.ts +420 -29
- package/src/{core/tools → tools}/grep.ts +155 -164
- package/src/{core/tools → tools}/index.ts +63 -56
- package/src/tools/list-limit.ts +40 -0
- package/src/{core/tools → tools}/ls.ts +44 -35
- package/src/{core/tools → tools}/notebook.ts +3 -3
- package/src/tools/output-meta.ts +443 -0
- package/src/tools/output-utils.ts +63 -0
- package/src/{core/tools → tools}/python.ts +105 -89
- package/src/tools/read.ts +882 -0
- package/src/{core/tools → tools}/render-utils.ts +1 -1
- package/src/{core/tools → tools}/renderers.ts +8 -10
- package/src/{core/tools → tools}/review.ts +2 -2
- package/src/{core/tools → tools}/ssh.ts +56 -59
- package/src/{core/tools → tools}/todo-write.ts +12 -23
- package/src/tools/tool-errors.ts +95 -0
- package/src/tools/tool-result.ts +92 -0
- package/src/{core/tools → tools}/truncate.ts +2 -2
- package/src/{core/tools → tools}/write.ts +15 -13
- package/src/utils/changelog.ts +1 -1
- package/src/{core → utils}/file-mentions.ts +4 -4
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +1 -1
- package/src/utils/shell.ts +1 -1
- package/src/{core → utils}/title-generator.ts +4 -4
- package/src/utils/tools-manager.ts +1 -1
- package/src/{core/tools/web-scrapers → web/scrapers}/choosealicense.ts +1 -1
- package/src/{core/tools/web-scrapers → web/scrapers}/twitter.ts +3 -2
- package/src/{core/tools/web-scrapers → web/scrapers}/types.ts +4 -2
- package/src/{core/tools/web-scrapers → web/scrapers}/utils.ts +1 -1
- package/src/{core/tools/web-scrapers → web/scrapers}/youtube.ts +14 -13
- package/src/{core/tools/web-search → web/search}/auth.ts +4 -4
- package/src/{core/tools/web-search → web/search}/index.ts +22 -71
- package/src/{core/tools/web-search → web/search}/providers/anthropic.ts +7 -10
- package/src/{core/tools/web-search → web/search}/providers/exa.ts +2 -2
- package/src/{core/tools/web-search → web/search}/providers/perplexity.ts +4 -16
- package/src/{core/tools/web-search → web/search}/render.ts +3 -3
- package/tsconfig.json +25 -0
- package/scripts/migrate-sessions.sh +0 -93
- package/src/core/index.ts +0 -56
- package/src/core/python-prelude.ts +0 -3
- package/src/core/ssh-executor.ts +0 -5
- package/src/core/streaming-output.ts +0 -115
- package/src/core/tools/output.ts +0 -519
- package/src/core/tools/read.ts +0 -717
- package/src/core/tools/task/template.ts +0 -37
- package/src/prompts/tools/output.md +0 -47
- package/src/prompts/tools/web-fetch.md +0 -9
- package/src/vendor/photon/photon_rs_bg.wasm.b64.js +0 -1
- /package/src/{core/tools/exa → exa}/types.ts +0 -0
- /package/src/{core → exec}/exec.ts +0 -0
- /package/src/{core/export-html → export/html}/template.css +0 -0
- /package/src/{core/export-html → export/html}/template.generated.ts +0 -0
- /package/src/{core/export-html → export/html}/template.html +0 -0
- /package/src/{core/export-html → export/html}/template.js +0 -0
- /package/src/{core/export-html → export/html}/template.macro.ts +0 -0
- /package/src/{core/export-html → export/html}/vendor/highlight.min.js +0 -0
- /package/src/{core/export-html → export/html}/vendor/marked.min.js +0 -0
- /package/src/{core → extensibility}/custom-commands/index.ts +0 -0
- /package/src/{core → extensibility}/custom-tools/index.ts +0 -0
- /package/src/{core → extensibility}/extensions/index.ts +0 -0
- /package/src/{core → extensibility}/hooks/tool-wrapper.ts +0 -0
- /package/src/{core → extensibility}/plugins/index.ts +0 -0
- /package/src/{core → extensibility}/plugins/loader.ts +0 -0
- /package/src/{core → extensibility}/plugins/manager.ts +0 -0
- /package/src/{core → extensibility}/plugins/parser.ts +0 -0
- /package/src/{core → extensibility}/plugins/types.ts +0 -0
- /package/src/{core/python-modules.ts → ipy/modules.ts} +0 -0
- /package/src/{core/python-prelude.py → ipy/prelude.py} +0 -0
- /package/src/{core/tools/lsp → lsp}/defaults.json +0 -0
- /package/src/{core/tools/lsp → lsp}/edits.ts +0 -0
- /package/src/{core/tools/lsp → lsp}/lspmux.ts +0 -0
- /package/src/{core/tools/lsp → lsp}/rust-analyzer.ts +0 -0
- /package/src/{core/mcp → mcp}/client.ts +0 -0
- /package/src/{core/mcp → mcp}/index.ts +0 -0
- /package/src/{core/mcp → mcp}/json-rpc.ts +0 -0
- /package/src/{core/mcp → mcp}/transports/index.ts +0 -0
- /package/src/modes/{interactive/components → components}/countdown-timer.ts +0 -0
- /package/src/modes/{interactive/components → components}/custom-editor.ts +0 -0
- /package/src/modes/{interactive/components → components}/extensions/index.ts +0 -0
- /package/src/modes/{interactive/components → components}/index.ts +0 -0
- /package/src/modes/{interactive/components → components}/status-line/index.ts +0 -0
- /package/src/modes/{interactive/components → components}/status-line/presets.ts +0 -0
- /package/src/modes/{interactive/components → components}/visual-truncate.ts +0 -0
- /package/src/modes/{interactive/theme → theme}/dark.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/alabaster.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/amethyst.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/anthracite.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/basalt.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/birch.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-abyss.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-arctic.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-aurora.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-catppuccin.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-cavern.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-copper.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-cosmos.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-cyberpunk.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-dracula.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-eclipse.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-ember.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-equinox.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-forest.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-github.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-gruvbox.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-lavender.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-lunar.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-midnight.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-monochrome.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-monokai.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-nebula.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-nord.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-ocean.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-one.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-rainforest.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-reef.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-retro.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-rose-pine.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-sakura.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-slate.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-solarized.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-solstice.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-starfall.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-sunset.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-swamp.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-synthwave.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-taiga.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-terminal.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-tokyo-night.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-tundra.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-twilight.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/dark-volcanic.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/graphite.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/index.ts +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-arctic.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-aurora-day.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-canyon.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-catppuccin.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-cirrus.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-coral.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-cyberpunk.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-dawn.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-dunes.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-eucalyptus.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-forest.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-frost.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-github.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-glacier.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-gruvbox.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-haze.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-honeycomb.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-lagoon.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-lavender.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-meadow.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-mint.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-monochrome.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-ocean.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-one.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-opal.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-orchard.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-paper.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-prism.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-retro.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-sand.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-savanna.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-solarized.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-soleil.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-sunset.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-synthwave.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-tokyo-night.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-wetland.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/light-zenith.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/limestone.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/mahogany.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/marble.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/obsidian.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/onyx.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/pearl.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/porcelain.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/quartz.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/sandstone.json +0 -0
- /package/src/modes/{interactive/theme → theme}/defaults/titanium.json +0 -0
- /package/src/modes/{interactive/theme → theme}/light.json +0 -0
- /package/src/modes/{interactive/theme → theme}/theme-schema.json +0 -0
- /package/src/{core/tools/patch → patch}/fuzzy.ts +0 -0
- /package/src/{core/tools/patch → patch}/normalize.ts +0 -0
- /package/src/{core/tools/patch → patch}/normative.ts +0 -0
- /package/src/{core/tools/patch → patch}/parser.ts +0 -0
- /package/src/{core/tools/patch → patch}/types.ts +0 -0
- /package/src/{core → session}/compaction/index.ts +0 -0
- /package/src/{core → session}/session-storage.ts +0 -0
- /package/src/{core/tools/task → task}/name-generator.ts +0 -0
- /package/src/{core/tools/task → task}/omp-command.ts +0 -0
- /package/src/{core/tools/task → task}/parallel.ts +0 -0
- /package/src/{core/tools → tools}/jtd-to-json-schema.ts +0 -0
- /package/src/{core/tools → tools}/path-utils.ts +0 -0
- /package/src/{core → utils}/event-bus.ts +0 -0
- /package/src/{core → utils}/frontmatter.ts +0 -0
- /package/src/{core → utils}/terminal-notify.ts +0 -0
- /package/src/{core → utils}/timings.ts +0 -0
- /package/src/{core → utils}/utils.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/artifacthub.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/arxiv.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/aur.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/biorxiv.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/bluesky.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/brew.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/cheatsh.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/chocolatey.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/cisa-kev.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/clojars.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/coingecko.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/crates-io.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/crossref.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/devto.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/discogs.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/discourse.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/dockerhub.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/fdroid.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/firefox-addons.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/flathub.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/github-gist.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/github.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/gitlab.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/go-pkg.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/hackage.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/hackernews.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/hex.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/huggingface.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/iacr.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/index.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/jetbrains-marketplace.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/lemmy.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/lobsters.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/mastodon.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/maven.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/mdn.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/metacpan.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/musicbrainz.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/npm.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/nuget.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/nvd.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/ollama.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/open-vsx.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/opencorporates.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/openlibrary.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/orcid.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/osv.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/packagist.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/pub-dev.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/pubmed.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/pypi.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/rawg.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/readthedocs.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/reddit.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/repology.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/rfc.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/rubygems.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/searchcode.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/sec-edgar.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/semantic-scholar.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/snapcraft.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/sourcegraph.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/spdx.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/spotify.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/stackoverflow.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/terraform.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/tldr.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/vimeo.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/vscode-marketplace.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/w3c.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/wikidata.ts +0 -0
- /package/src/{core/tools/web-scrapers → web/scrapers}/wikipedia.ts +0 -0
- /package/src/{core/tools/web-search → web/search}/types.ts +0 -0
|
@@ -13,25 +13,25 @@
|
|
|
13
13
|
* - Session artifacts for debugging
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { mkdir, rm } from "node:fs/promises";
|
|
16
|
+
import { mkdir, rm, stat } from "node:fs/promises";
|
|
17
17
|
import { tmpdir } from "node:os";
|
|
18
18
|
import path from "node:path";
|
|
19
19
|
import type { AgentTool, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
20
20
|
import type { Usage } from "@oh-my-pi/pi-ai";
|
|
21
|
+
import { $ } from "bun";
|
|
21
22
|
import { nanoid } from "nanoid";
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
23
|
+
import { renderPromptTemplate } from "$c/config/prompt-templates";
|
|
24
|
+
import type { Theme } from "$c/modes/theme/theme";
|
|
25
|
+
import taskDescriptionTemplate from "$c/prompts/tools/task.md" with { type: "text" };
|
|
26
|
+
import { formatDuration } from "$c/tools/render-utils";
|
|
25
27
|
import type { ToolSession } from "..";
|
|
26
|
-
import { formatDuration } from "../render-utils";
|
|
27
28
|
import { discoverAgents, getAgent } from "./discovery";
|
|
28
29
|
import { runSubprocess } from "./executor";
|
|
29
30
|
import { mapWithConcurrencyLimit } from "./parallel";
|
|
30
31
|
import { renderCall, renderResult } from "./render";
|
|
31
|
-
import { renderTemplate
|
|
32
|
+
import { renderTemplate } from "./template";
|
|
32
33
|
import {
|
|
33
34
|
type AgentProgress,
|
|
34
|
-
MAX_AGENTS_IN_DESCRIPTION,
|
|
35
35
|
MAX_CONCURRENCY,
|
|
36
36
|
MAX_PARALLEL_TASKS,
|
|
37
37
|
type SingleResult,
|
|
@@ -39,9 +39,17 @@ import {
|
|
|
39
39
|
type TaskToolDetails,
|
|
40
40
|
taskSchema,
|
|
41
41
|
} from "./types";
|
|
42
|
+
import {
|
|
43
|
+
applyBaseline,
|
|
44
|
+
captureBaseline,
|
|
45
|
+
captureDeltaPatch,
|
|
46
|
+
cleanupWorktree,
|
|
47
|
+
ensureWorktree,
|
|
48
|
+
getRepoRoot,
|
|
49
|
+
} from "./worktree";
|
|
42
50
|
|
|
43
51
|
// Import review tools for side effects (registers subagent tool handlers)
|
|
44
|
-
import "../review";
|
|
52
|
+
import "../tools/review";
|
|
45
53
|
|
|
46
54
|
/** Format byte count for display */
|
|
47
55
|
function formatBytes(bytes: number): string {
|
|
@@ -103,8 +111,7 @@ async function buildDescription(cwd: string): Promise<string> {
|
|
|
103
111
|
const { agents } = await discoverAgents(cwd);
|
|
104
112
|
|
|
105
113
|
return renderPromptTemplate(taskDescriptionTemplate, {
|
|
106
|
-
agents
|
|
107
|
-
moreAgents: agents.length > MAX_AGENTS_IN_DESCRIPTION ? agents.length - MAX_AGENTS_IN_DESCRIPTION : 0,
|
|
114
|
+
agents,
|
|
108
115
|
MAX_PARALLEL_TASKS,
|
|
109
116
|
MAX_CONCURRENCY,
|
|
110
117
|
});
|
|
@@ -153,7 +160,8 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
153
160
|
): Promise<AgentToolResult<TaskToolDetails>> {
|
|
154
161
|
const startTime = Date.now();
|
|
155
162
|
const { agents, projectAgentsDir } = await discoverAgents(this.session.cwd);
|
|
156
|
-
const { agent: agentName, context,
|
|
163
|
+
const { agent: agentName, context, output: outputSchema, isolated } = params;
|
|
164
|
+
const isIsolated = isolated === true;
|
|
157
165
|
|
|
158
166
|
const isDefaultModelAlias = (value: string | undefined): boolean => {
|
|
159
167
|
if (!value) return true;
|
|
@@ -180,9 +188,9 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
180
188
|
};
|
|
181
189
|
}
|
|
182
190
|
|
|
183
|
-
const
|
|
184
|
-
const
|
|
185
|
-
|
|
191
|
+
const effectiveAgentModel = isDefaultModelAlias(agent.model) ? undefined : agent.model;
|
|
192
|
+
const modelOverride =
|
|
193
|
+
effectiveAgentModel ?? this.session.getActiveModelString?.() ?? this.session.getModelString?.();
|
|
186
194
|
const thinkingLevelOverride = agent.thinkingLevel;
|
|
187
195
|
|
|
188
196
|
// Output schema priority: agent frontmatter > params > inherited from parent session
|
|
@@ -195,7 +203,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
195
203
|
content: [
|
|
196
204
|
{
|
|
197
205
|
type: "text",
|
|
198
|
-
text: `No tasks provided. Use: { agent, context, tasks: [{id, description,
|
|
206
|
+
text: `No tasks provided. Use: { agent, context, tasks: [{id, description, args}, ...] }`,
|
|
199
207
|
},
|
|
200
208
|
],
|
|
201
209
|
details: {
|
|
@@ -271,16 +279,28 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
271
279
|
};
|
|
272
280
|
}
|
|
273
281
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
282
|
+
let repoRoot: string | null = null;
|
|
283
|
+
let baseline = null as Awaited<ReturnType<typeof captureBaseline>> | null;
|
|
284
|
+
if (isIsolated) {
|
|
285
|
+
try {
|
|
286
|
+
repoRoot = await getRepoRoot(this.session.cwd);
|
|
287
|
+
baseline = await captureBaseline(repoRoot);
|
|
288
|
+
} catch (err) {
|
|
289
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
290
|
+
return {
|
|
291
|
+
content: [
|
|
292
|
+
{
|
|
293
|
+
type: "text",
|
|
294
|
+
text: `Isolated task execution requires a git repository. ${message}`,
|
|
295
|
+
},
|
|
296
|
+
],
|
|
297
|
+
details: {
|
|
298
|
+
projectAgentsDir,
|
|
299
|
+
results: [],
|
|
300
|
+
totalDurationMs: Date.now() - startTime,
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
}
|
|
284
304
|
}
|
|
285
305
|
|
|
286
306
|
// Derive artifacts directory
|
|
@@ -347,25 +367,19 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
347
367
|
}
|
|
348
368
|
|
|
349
369
|
// Build full prompts with context prepended
|
|
350
|
-
const
|
|
351
|
-
const tasksWithContext = tasks.map((t) => ({
|
|
352
|
-
task: renderTemplate(contextTemplate, t.vars),
|
|
353
|
-
description: t.description,
|
|
354
|
-
taskId: t.id,
|
|
355
|
-
vars: t.vars,
|
|
356
|
-
}));
|
|
370
|
+
const tasksWithContext = tasks.map((t) => renderTemplate(context, t));
|
|
357
371
|
|
|
358
372
|
// Initialize progress for all tasks
|
|
359
373
|
for (let i = 0; i < tasksWithContext.length; i++) {
|
|
360
374
|
const t = tasksWithContext[i];
|
|
361
375
|
progressMap.set(i, {
|
|
362
376
|
index: i,
|
|
363
|
-
|
|
377
|
+
id: t.id,
|
|
364
378
|
agent: agentName,
|
|
365
379
|
agentSource: agent.source,
|
|
366
380
|
status: "pending",
|
|
367
381
|
task: t.task,
|
|
368
|
-
|
|
382
|
+
args: t.args,
|
|
369
383
|
recentTools: [],
|
|
370
384
|
recentOutput: [],
|
|
371
385
|
toolCount: 0,
|
|
@@ -377,18 +391,15 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
377
391
|
}
|
|
378
392
|
emitProgress();
|
|
379
393
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
tasksWithContext,
|
|
383
|
-
MAX_CONCURRENCY,
|
|
384
|
-
async (task, index) => {
|
|
394
|
+
const runTask = async (task: (typeof tasksWithContext)[number], index: number) => {
|
|
395
|
+
if (!isIsolated) {
|
|
385
396
|
return runSubprocess({
|
|
386
397
|
cwd: this.session.cwd,
|
|
387
398
|
agent,
|
|
388
399
|
task: task.task,
|
|
389
400
|
description: task.description,
|
|
390
401
|
index,
|
|
391
|
-
|
|
402
|
+
id: task.id,
|
|
392
403
|
context: undefined, // Already prepended above
|
|
393
404
|
modelOverride,
|
|
394
405
|
thinkingLevel: thinkingLevelOverride,
|
|
@@ -402,7 +413,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
402
413
|
onProgress: (progress) => {
|
|
403
414
|
progressMap.set(index, {
|
|
404
415
|
...structuredClone(progress),
|
|
405
|
-
|
|
416
|
+
args: tasksWithContext[index]?.args,
|
|
406
417
|
});
|
|
407
418
|
emitProgress();
|
|
408
419
|
},
|
|
@@ -411,7 +422,83 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
411
422
|
settingsManager: this.session.settingsManager,
|
|
412
423
|
mcpManager: this.session.mcpManager,
|
|
413
424
|
});
|
|
414
|
-
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const taskStart = Date.now();
|
|
428
|
+
let worktreeDir: string | undefined;
|
|
429
|
+
try {
|
|
430
|
+
if (!repoRoot || !baseline) {
|
|
431
|
+
throw new Error("Isolated task execution not initialized.");
|
|
432
|
+
}
|
|
433
|
+
worktreeDir = await ensureWorktree(repoRoot, task.id);
|
|
434
|
+
await applyBaseline(worktreeDir, baseline);
|
|
435
|
+
const result = await runSubprocess({
|
|
436
|
+
cwd: this.session.cwd,
|
|
437
|
+
worktree: worktreeDir,
|
|
438
|
+
agent,
|
|
439
|
+
task: task.task,
|
|
440
|
+
description: task.description,
|
|
441
|
+
index,
|
|
442
|
+
id: task.id,
|
|
443
|
+
context: undefined, // Already prepended above
|
|
444
|
+
modelOverride,
|
|
445
|
+
thinkingLevel: thinkingLevelOverride,
|
|
446
|
+
outputSchema: effectiveOutputSchema,
|
|
447
|
+
sessionFile,
|
|
448
|
+
persistArtifacts: !!artifactsDir,
|
|
449
|
+
artifactsDir: effectiveArtifactsDir,
|
|
450
|
+
enableLsp: false,
|
|
451
|
+
signal,
|
|
452
|
+
eventBus: undefined,
|
|
453
|
+
onProgress: (progress) => {
|
|
454
|
+
progressMap.set(index, {
|
|
455
|
+
...structuredClone(progress),
|
|
456
|
+
args: tasksWithContext[index]?.args,
|
|
457
|
+
});
|
|
458
|
+
emitProgress();
|
|
459
|
+
},
|
|
460
|
+
authStorage: this.session.authStorage,
|
|
461
|
+
modelRegistry: this.session.modelRegistry,
|
|
462
|
+
settingsManager: this.session.settingsManager,
|
|
463
|
+
mcpManager: this.session.mcpManager,
|
|
464
|
+
});
|
|
465
|
+
const patch = await captureDeltaPatch(worktreeDir, baseline);
|
|
466
|
+
const patchPath = path.join(effectiveArtifactsDir, `${task.id}.patch`);
|
|
467
|
+
await Bun.write(patchPath, patch);
|
|
468
|
+
return {
|
|
469
|
+
...result,
|
|
470
|
+
patchPath,
|
|
471
|
+
};
|
|
472
|
+
} catch (err) {
|
|
473
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
474
|
+
return {
|
|
475
|
+
index,
|
|
476
|
+
id: task.id,
|
|
477
|
+
agent: agent.name,
|
|
478
|
+
agentSource: agent.source,
|
|
479
|
+
task: task.task,
|
|
480
|
+
description: task.description,
|
|
481
|
+
exitCode: 1,
|
|
482
|
+
output: "",
|
|
483
|
+
stderr: message,
|
|
484
|
+
truncated: false,
|
|
485
|
+
durationMs: Date.now() - taskStart,
|
|
486
|
+
tokens: 0,
|
|
487
|
+
modelOverride,
|
|
488
|
+
error: message,
|
|
489
|
+
};
|
|
490
|
+
} finally {
|
|
491
|
+
if (worktreeDir) {
|
|
492
|
+
await cleanupWorktree(worktreeDir);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
// Execute in parallel with concurrency limit
|
|
498
|
+
const { results: partialResults, aborted } = await mapWithConcurrencyLimit(
|
|
499
|
+
tasksWithContext,
|
|
500
|
+
MAX_CONCURRENCY,
|
|
501
|
+
runTask,
|
|
415
502
|
signal,
|
|
416
503
|
);
|
|
417
504
|
|
|
@@ -420,17 +507,17 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
420
507
|
if (result !== undefined) {
|
|
421
508
|
return {
|
|
422
509
|
...result,
|
|
423
|
-
|
|
510
|
+
args: tasksWithContext[index]?.args,
|
|
424
511
|
};
|
|
425
512
|
}
|
|
426
513
|
const task = tasksWithContext[index];
|
|
427
514
|
return {
|
|
428
515
|
index,
|
|
429
|
-
|
|
516
|
+
id: task.id,
|
|
430
517
|
agent: agentName,
|
|
431
518
|
agentSource: agent.source,
|
|
432
519
|
task: task.task,
|
|
433
|
-
|
|
520
|
+
args: task.args,
|
|
434
521
|
description: task.description,
|
|
435
522
|
exitCode: 1,
|
|
436
523
|
output: "",
|
|
@@ -456,10 +543,75 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
456
543
|
|
|
457
544
|
// Collect output paths (artifacts already written by executor in real-time)
|
|
458
545
|
const outputPaths: string[] = [];
|
|
546
|
+
const patchPaths: string[] = [];
|
|
459
547
|
for (const result of results) {
|
|
460
548
|
if (result.outputPath) {
|
|
461
549
|
outputPaths.push(result.outputPath);
|
|
462
550
|
}
|
|
551
|
+
if (result.patchPath) {
|
|
552
|
+
patchPaths.push(result.patchPath);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
let patchApplySummary = "";
|
|
557
|
+
let patchesApplied: boolean | null = null;
|
|
558
|
+
if (isIsolated) {
|
|
559
|
+
const patchesInOrder = results.map((result) => result.patchPath).filter(Boolean) as string[];
|
|
560
|
+
const missingPatch = results.some((result) => !result.patchPath);
|
|
561
|
+
if (!repoRoot || missingPatch) {
|
|
562
|
+
patchesApplied = false;
|
|
563
|
+
} else {
|
|
564
|
+
const patchStats = await Promise.all(
|
|
565
|
+
patchesInOrder.map(async (patchPath) => ({
|
|
566
|
+
patchPath,
|
|
567
|
+
size: (await stat(patchPath)).size,
|
|
568
|
+
})),
|
|
569
|
+
);
|
|
570
|
+
const nonEmptyPatches = patchStats.filter((patch) => patch.size > 0).map((patch) => patch.patchPath);
|
|
571
|
+
if (nonEmptyPatches.length === 0) {
|
|
572
|
+
patchesApplied = true;
|
|
573
|
+
} else {
|
|
574
|
+
const patchTexts = await Promise.all(
|
|
575
|
+
nonEmptyPatches.map(async (patchPath) => Bun.file(patchPath).text()),
|
|
576
|
+
);
|
|
577
|
+
const combinedPatch = patchTexts.map((text) => (text.endsWith("\n") ? text : `${text}\n`)).join("");
|
|
578
|
+
if (!combinedPatch.trim()) {
|
|
579
|
+
patchesApplied = true;
|
|
580
|
+
} else {
|
|
581
|
+
const combinedPatchPath = path.join(tmpdir(), `omp-task-combined-${nanoid()}.patch`);
|
|
582
|
+
try {
|
|
583
|
+
await Bun.write(combinedPatchPath, combinedPatch);
|
|
584
|
+
const checkResult = await $`git apply --check --binary ${combinedPatchPath}`
|
|
585
|
+
.cwd(repoRoot)
|
|
586
|
+
.quiet()
|
|
587
|
+
.nothrow();
|
|
588
|
+
if (checkResult.exitCode !== 0) {
|
|
589
|
+
patchesApplied = false;
|
|
590
|
+
} else {
|
|
591
|
+
const applyResult = await $`git apply --binary ${combinedPatchPath}`
|
|
592
|
+
.cwd(repoRoot)
|
|
593
|
+
.quiet()
|
|
594
|
+
.nothrow();
|
|
595
|
+
patchesApplied = applyResult.exitCode === 0;
|
|
596
|
+
}
|
|
597
|
+
} finally {
|
|
598
|
+
await rm(combinedPatchPath, { force: true });
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (patchesApplied) {
|
|
605
|
+
patchApplySummary = "\n\nApplied patches: yes";
|
|
606
|
+
} else {
|
|
607
|
+
const notification =
|
|
608
|
+
"<system-notification>Patches were not applied and must be handled manually.</system-notification>";
|
|
609
|
+
const patchList =
|
|
610
|
+
patchPaths.length > 0
|
|
611
|
+
? `\n\nPatch artifacts:\n${patchPaths.map((patch) => `- ${patch}`).join("\n")}`
|
|
612
|
+
: "";
|
|
613
|
+
patchApplySummary = `\n\n${notification}${patchList}`;
|
|
614
|
+
}
|
|
463
615
|
}
|
|
464
616
|
|
|
465
617
|
// Build final output - match plugin format
|
|
@@ -474,22 +626,26 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
474
626
|
const meta = r.outputMeta
|
|
475
627
|
? ` [${r.outputMeta.lineCount} lines, ${formatBytes(r.outputMeta.charCount)}]`
|
|
476
628
|
: "";
|
|
477
|
-
return `[${r.agent}] ${status}${meta} ${r.
|
|
629
|
+
return `[${r.agent}] ${status}${meta} ${r.id}\n${preview}`;
|
|
478
630
|
});
|
|
479
631
|
|
|
480
|
-
const outputIds = results.filter((r) => !r.aborted || r.output.trim()).map((r) => r.
|
|
632
|
+
const outputIds = results.filter((r) => !r.aborted || r.output.trim()).map((r) => r.id);
|
|
481
633
|
const outputHint =
|
|
482
|
-
outputIds.length > 0
|
|
634
|
+
outputIds.length > 0
|
|
635
|
+
? `\n\nUse read with agent:// for full logs: ${outputIds.map((id) => `agent://${id}`).join(", ")}`
|
|
636
|
+
: "";
|
|
483
637
|
const schemaNote = schemaOverridden
|
|
484
638
|
? `\n\nNote: Agent '${agentName}' has a fixed output schema; your 'output' parameter was ignored.\nRequired schema: ${JSON.stringify(agent.output)}`
|
|
485
639
|
: "";
|
|
486
640
|
const cancelledNote = aborted && cancelledCount > 0 ? ` (${cancelledCount} cancelled)` : "";
|
|
487
641
|
const summary = `${successCount}/${results.length} succeeded${cancelledNote} [${formatDuration(
|
|
488
642
|
totalDuration,
|
|
489
|
-
)}]\n\n${summaries.join("\n\n---\n\n")}${outputHint}${schemaNote}`;
|
|
643
|
+
)}]\n\n${summaries.join("\n\n---\n\n")}${outputHint}${schemaNote}${patchApplySummary}`;
|
|
490
644
|
|
|
491
645
|
// Cleanup temp directory if used
|
|
492
|
-
|
|
646
|
+
const shouldCleanupTempArtifacts =
|
|
647
|
+
tempArtifactsDir && (!isIsolated || patchesApplied === true || patchesApplied === null);
|
|
648
|
+
if (shouldCleanupTempArtifacts) {
|
|
493
649
|
await rm(tempArtifactsDir, { recursive: true, force: true });
|
|
494
650
|
}
|
|
495
651
|
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
10
10
|
import { Container, Text } from "@oh-my-pi/pi-tui";
|
|
11
|
-
import type {
|
|
12
|
-
import type {
|
|
11
|
+
import type { RenderResultOptions } from "$c/extensibility/custom-tools/types";
|
|
12
|
+
import type { Theme } from "$c/modes/theme/theme";
|
|
13
13
|
import {
|
|
14
14
|
formatBadge,
|
|
15
15
|
formatDuration,
|
|
@@ -17,14 +17,14 @@ import {
|
|
|
17
17
|
formatStatusIcon,
|
|
18
18
|
formatTokens,
|
|
19
19
|
truncate,
|
|
20
|
-
} from "
|
|
20
|
+
} from "$c/tools/render-utils";
|
|
21
21
|
import {
|
|
22
22
|
type FindingPriority,
|
|
23
23
|
getPriorityInfo,
|
|
24
24
|
PRIORITY_LABELS,
|
|
25
25
|
type ReportFindingDetails,
|
|
26
26
|
type SubmitReviewDetails,
|
|
27
|
-
} from "
|
|
27
|
+
} from "$c/tools/review";
|
|
28
28
|
import { subprocessToolRegistry } from "./subprocess-tool-registry";
|
|
29
29
|
import type { AgentProgress, SingleResult, TaskParams, TaskToolDetails } from "./types";
|
|
30
30
|
|
|
@@ -236,7 +236,7 @@ function renderOutputSection(
|
|
|
236
236
|
try {
|
|
237
237
|
const parsed = JSON.parse(trimmedOutput);
|
|
238
238
|
|
|
239
|
-
// Collapsed: inline format like
|
|
239
|
+
// Collapsed: inline format like Args
|
|
240
240
|
if (!expanded) {
|
|
241
241
|
lines.push(`${continuePrefix}${theme.fg("dim", formatOutputInline(parsed, theme))}`);
|
|
242
242
|
return lines;
|
|
@@ -276,11 +276,25 @@ function renderOutputSection(
|
|
|
276
276
|
return lines;
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
function
|
|
280
|
-
const entries = Object.entries(
|
|
281
|
-
if (entries.length === 0) return "
|
|
279
|
+
function formatArgsInline(args: Record<string, string>, theme: Theme): string {
|
|
280
|
+
const entries = Object.entries(args);
|
|
281
|
+
if (entries.length === 0) return "No arguments";
|
|
282
|
+
|
|
283
|
+
// Single variable: show inline as "Key: value" without tree structure
|
|
284
|
+
if (entries.length === 1) {
|
|
285
|
+
const [key, value] = entries[0];
|
|
286
|
+
const humanKey = humanizeKey(key);
|
|
287
|
+
const displayValue = `"${truncate(value, 32, theme.format.ellipsis)}"`;
|
|
288
|
+
return `${humanKey}: ${displayValue}`;
|
|
289
|
+
}
|
|
290
|
+
|
|
282
291
|
const pairs = entries.map(([key, value]) => `${key}=${truncate(value, 24, theme.format.ellipsis)}`);
|
|
283
|
-
return `
|
|
292
|
+
return `Args: ${pairs.join(", ")}`;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** Convert snake_case or kebab-case to Title Case */
|
|
296
|
+
function humanizeKey(key: string): string {
|
|
297
|
+
return key.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
284
298
|
}
|
|
285
299
|
|
|
286
300
|
function formatScalarInline(value: unknown, maxLen: number, theme: Theme): string {
|
|
@@ -336,22 +350,37 @@ function formatOutputInline(data: unknown, theme: Theme, maxWidth = 80): string
|
|
|
336
350
|
return `Output: ${pairs.join(", ")}`;
|
|
337
351
|
}
|
|
338
352
|
|
|
339
|
-
function
|
|
340
|
-
|
|
353
|
+
function renderArgsSection(
|
|
354
|
+
args: Record<string, string> | undefined,
|
|
341
355
|
continuePrefix: string,
|
|
342
356
|
expanded: boolean,
|
|
343
357
|
theme: Theme,
|
|
344
358
|
): string[] {
|
|
345
|
-
if (!
|
|
359
|
+
if (!args) return [];
|
|
360
|
+
// Filter out auto-injected id and description
|
|
361
|
+
const filteredArgs = Object.fromEntries(
|
|
362
|
+
Object.entries(args).filter(([key]) => key !== "id" && key !== "description"),
|
|
363
|
+
);
|
|
364
|
+
if (Object.keys(filteredArgs).length === 0) return [];
|
|
346
365
|
const lines: string[] = [];
|
|
366
|
+
const entries = Object.entries(filteredArgs);
|
|
347
367
|
|
|
348
368
|
if (!expanded) {
|
|
349
|
-
lines.push(`${continuePrefix}${theme.fg("dim",
|
|
369
|
+
lines.push(`${continuePrefix}${theme.fg("dim", formatArgsInline(filteredArgs, theme))}`);
|
|
370
|
+
return lines;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Single variable: show inline as "Key: value" without tree structure
|
|
374
|
+
if (entries.length === 1) {
|
|
375
|
+
const [key, value] = entries[0];
|
|
376
|
+
const humanKey = humanizeKey(key);
|
|
377
|
+
const displayValue = `"${truncate(value, 60, theme.format.ellipsis)}"`;
|
|
378
|
+
lines.push(`${continuePrefix}${theme.fg("dim", `${humanKey}: ${displayValue}`)}`);
|
|
350
379
|
return lines;
|
|
351
380
|
}
|
|
352
381
|
|
|
353
|
-
lines.push(`${continuePrefix}${theme.fg("dim", "
|
|
354
|
-
const tree = renderJsonTreeLines(
|
|
382
|
+
lines.push(`${continuePrefix}${theme.fg("dim", "Args")}`);
|
|
383
|
+
const tree = renderJsonTreeLines(filteredArgs, theme, 4, 16);
|
|
355
384
|
for (const line of tree.lines) {
|
|
356
385
|
lines.push(`${continuePrefix} ${line}`);
|
|
357
386
|
}
|
|
@@ -380,6 +409,7 @@ export function renderCall(args: TaskParams, theme: Theme): Component {
|
|
|
380
409
|
const branch = theme.fg("dim", theme.tree.branch);
|
|
381
410
|
const last = theme.fg("dim", theme.tree.last);
|
|
382
411
|
const vertical = theme.fg("dim", theme.tree.vertical);
|
|
412
|
+
const showIsolated = args.isolated === true;
|
|
383
413
|
|
|
384
414
|
if (hasContext) {
|
|
385
415
|
lines.push(` ${branch} ${theme.fg("dim", "Context")}`);
|
|
@@ -387,11 +417,18 @@ export function renderCall(args: TaskParams, theme: Theme): Component {
|
|
|
387
417
|
const content = line ? theme.fg("muted", line) : "";
|
|
388
418
|
lines.push(` ${vertical} ${content}`);
|
|
389
419
|
}
|
|
390
|
-
|
|
420
|
+
const taskPrefix = showIsolated ? branch : last;
|
|
421
|
+
lines.push(` ${taskPrefix} ${theme.fg("dim", "Tasks")}: ${theme.fg("muted", `${args.tasks.length} agents`)}`);
|
|
422
|
+
if (showIsolated) {
|
|
423
|
+
lines.push(` ${last} ${theme.fg("dim", "Isolated")}: ${theme.fg("muted", "true")}`);
|
|
424
|
+
}
|
|
391
425
|
return new Text(lines.join("\n"), 0, 0);
|
|
392
426
|
}
|
|
393
427
|
|
|
394
428
|
lines.push(`${theme.fg("dim", "Tasks")}: ${theme.fg("muted", `${args.tasks.length} agents`)}`);
|
|
429
|
+
if (showIsolated) {
|
|
430
|
+
lines.push(`${theme.fg("dim", "Isolated")}: ${theme.fg("muted", "true")}`);
|
|
431
|
+
}
|
|
395
432
|
|
|
396
433
|
return new Text(lines.join("\n"), 0, 0);
|
|
397
434
|
}
|
|
@@ -418,9 +455,9 @@ function renderAgentProgress(
|
|
|
418
455
|
? "error"
|
|
419
456
|
: "accent";
|
|
420
457
|
|
|
421
|
-
// Main status line:
|
|
458
|
+
// Main status line: id: description [status] · stats · ⟨agent⟩
|
|
422
459
|
const description = progress.description?.trim();
|
|
423
|
-
const titlePart = description ? `${theme.bold(progress.
|
|
460
|
+
const titlePart = description ? `${theme.bold(progress.id)}: ${description}` : progress.id;
|
|
424
461
|
let statusLine = `${prefix} ${theme.fg(iconColor, icon)} ${theme.fg("accent", titlePart)}`;
|
|
425
462
|
|
|
426
463
|
// Only show badge for non-running states (spinner already indicates running)
|
|
@@ -445,7 +482,7 @@ function renderAgentProgress(
|
|
|
445
482
|
|
|
446
483
|
lines.push(statusLine);
|
|
447
484
|
|
|
448
|
-
lines.push(...
|
|
485
|
+
lines.push(...renderArgsSection(progress.args, continuePrefix, expanded, theme));
|
|
449
486
|
|
|
450
487
|
// Current tool (if running) or most recent completed tool
|
|
451
488
|
if (progress.status === "running") {
|
|
@@ -638,9 +675,9 @@ function renderAgentResult(result: SingleResult, isLast: boolean, expanded: bool
|
|
|
638
675
|
const iconColor = success ? "success" : "error";
|
|
639
676
|
const statusText = aborted ? "aborted" : success ? "done" : "failed";
|
|
640
677
|
|
|
641
|
-
// Main status line:
|
|
678
|
+
// Main status line: id: description [status] · stats · ⟨agent⟩
|
|
642
679
|
const description = result.description?.trim();
|
|
643
|
-
const titlePart = description ? `${theme.bold(result.
|
|
680
|
+
const titlePart = description ? `${theme.bold(result.id)}: ${description}` : result.id;
|
|
644
681
|
let statusLine = `${prefix} ${theme.fg(iconColor, icon)} ${theme.fg("accent", titlePart)} ${formatBadge(
|
|
645
682
|
statusText,
|
|
646
683
|
iconColor,
|
|
@@ -656,7 +693,7 @@ function renderAgentResult(result: SingleResult, isLast: boolean, expanded: bool
|
|
|
656
693
|
}
|
|
657
694
|
|
|
658
695
|
lines.push(statusLine);
|
|
659
|
-
lines.push(...
|
|
696
|
+
lines.push(...renderArgsSection(result.args, continuePrefix, expanded, theme));
|
|
660
697
|
|
|
661
698
|
// Check for review result (complete with review schema + report_finding)
|
|
662
699
|
const completeData = result.extractedToolData?.complete as Array<{ data: unknown }> | undefined;
|
|
@@ -722,6 +759,10 @@ function renderAgentResult(result: SingleResult, isLast: boolean, expanded: bool
|
|
|
722
759
|
lines.push(...renderOutputSection(result.output, continuePrefix, expanded, theme, 3, 12));
|
|
723
760
|
}
|
|
724
761
|
|
|
762
|
+
if (result.patchPath && !aborted && result.exitCode === 0) {
|
|
763
|
+
lines.push(`${continuePrefix}${theme.fg("dim", `Patch: ${result.patchPath}`)}`);
|
|
764
|
+
}
|
|
765
|
+
|
|
725
766
|
// Error message
|
|
726
767
|
if (result.error && !success) {
|
|
727
768
|
lines.push(`${continuePrefix}${theme.fg("error", truncate(result.error, 70, theme.format.ellipsis))}`);
|
|
@@ -739,6 +780,7 @@ export function renderResult(
|
|
|
739
780
|
theme: Theme,
|
|
740
781
|
): Component {
|
|
741
782
|
const { expanded, isPartial, spinnerFrame } = options;
|
|
783
|
+
const fallbackText = result.content.find((c) => c.type === "text")?.text ?? "";
|
|
742
784
|
const details = result.details;
|
|
743
785
|
|
|
744
786
|
if (!details) {
|
|
@@ -785,7 +827,22 @@ export function renderResult(
|
|
|
785
827
|
}
|
|
786
828
|
|
|
787
829
|
if (lines.length === 0) {
|
|
788
|
-
|
|
830
|
+
const text = fallbackText.trim() ? fallbackText : "No results";
|
|
831
|
+
return new Text(theme.fg("dim", truncate(text, 140, theme.format.ellipsis)), 0, 0);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
if (fallbackText.trim()) {
|
|
835
|
+
const summaryLines = fallbackText.split("\n");
|
|
836
|
+
const markerIndex = summaryLines.findIndex(
|
|
837
|
+
(line) => line.includes("<system-notification>") || line.startsWith("Applied patches:"),
|
|
838
|
+
);
|
|
839
|
+
if (markerIndex >= 0) {
|
|
840
|
+
const extra = summaryLines.slice(markerIndex);
|
|
841
|
+
for (const line of extra) {
|
|
842
|
+
if (!line.trim()) continue;
|
|
843
|
+
lines.push(theme.fg("dim", line));
|
|
844
|
+
}
|
|
845
|
+
}
|
|
789
846
|
}
|
|
790
847
|
|
|
791
848
|
const indented = lines.map((line) => (line.trim() ? ` ${line}` : ""));
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
11
|
-
import type { Theme } from "
|
|
11
|
+
import type { Theme } from "$c/modes/theme/theme";
|
|
12
12
|
|
|
13
13
|
/** Event from subprocess tool execution (parsed from JSONL) */
|
|
14
14
|
export interface SubprocessToolEvent {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { TaskItem } from "./types";
|
|
2
|
+
|
|
3
|
+
type RenderResult = {
|
|
4
|
+
task: string;
|
|
5
|
+
args: Record<string, string>;
|
|
6
|
+
id: string;
|
|
7
|
+
description: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function renderTemplate(template: string, task: TaskItem): RenderResult {
|
|
11
|
+
const { id, description, args } = task;
|
|
12
|
+
|
|
13
|
+
let usedPlaceholder = false;
|
|
14
|
+
const unknownArguments: string[] = [];
|
|
15
|
+
let renderedTask = template.replace(/\{\{(\w+)\}\}/g, (_match, key: string) => {
|
|
16
|
+
const value = args?.[key];
|
|
17
|
+
if (value) {
|
|
18
|
+
usedPlaceholder = true;
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
switch (key) {
|
|
22
|
+
case "id":
|
|
23
|
+
usedPlaceholder = true;
|
|
24
|
+
return id;
|
|
25
|
+
case "description":
|
|
26
|
+
usedPlaceholder = true;
|
|
27
|
+
return description;
|
|
28
|
+
default:
|
|
29
|
+
unknownArguments.push(key);
|
|
30
|
+
return `{{${key}}}`;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (unknownArguments.length > 0) {
|
|
35
|
+
throw new Error(`Task "${id}" has unknown arguments: ${unknownArguments.join(", ")}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!usedPlaceholder) {
|
|
39
|
+
renderedTask += `\n----------------------\n# ${id}\n${description}`;
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
task: renderedTask,
|
|
43
|
+
args: { id, description, ...args },
|
|
44
|
+
id,
|
|
45
|
+
description,
|
|
46
|
+
};
|
|
47
|
+
}
|