@oh-my-pi/pi-coding-agent 8.0.20 → 8.2.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/CHANGELOG.md +125 -0
- package/docs/session.md +111 -46
- package/examples/custom-tools/hello/index.ts +1 -1
- package/examples/custom-tools/todo/index.ts +3 -4
- package/examples/extensions/api-demo.ts +0 -1
- package/examples/extensions/chalk-logger.ts +2 -3
- package/examples/extensions/hello.ts +0 -1
- package/examples/extensions/pirate.ts +0 -1
- package/examples/extensions/plan-mode.ts +15 -16
- package/examples/extensions/todo.ts +3 -4
- package/examples/extensions/tools.ts +1 -2
- package/examples/extensions/with-deps/index.ts +0 -1
- package/examples/hooks/auto-commit-on-exit.ts +1 -2
- package/examples/hooks/confirm-destructive.ts +0 -1
- package/examples/hooks/custom-compaction.ts +1 -2
- package/examples/hooks/dirty-repo-guard.ts +0 -1
- package/examples/hooks/file-trigger.ts +3 -4
- package/examples/hooks/git-checkpoint.ts +0 -1
- package/examples/hooks/handoff.ts +3 -4
- package/examples/hooks/permission-gate.ts +1 -2
- package/examples/hooks/protected-paths.ts +1 -2
- package/examples/hooks/qna.ts +2 -3
- package/examples/hooks/snake.ts +4 -5
- package/examples/hooks/status-line.ts +0 -1
- package/examples/sdk/01-minimal.ts +2 -3
- package/examples/sdk/02-custom-model.ts +2 -3
- package/examples/sdk/03-custom-prompt.ts +3 -4
- package/examples/sdk/04-skills.ts +2 -3
- package/examples/sdk/06-extensions.ts +1 -2
- package/examples/sdk/06-hooks.ts +6 -7
- package/examples/sdk/07-context-files.ts +0 -1
- package/examples/sdk/08-prompt-templates.ts +0 -1
- package/examples/sdk/08-slash-commands.ts +0 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +0 -1
- package/examples/sdk/10-settings.ts +0 -1
- package/examples/sdk/11-sessions.ts +0 -1
- package/package.json +54 -23
- package/scripts/format-prompts.ts +0 -1
- package/src/capability/context-file.ts +3 -4
- package/src/capability/extension-module.ts +3 -4
- package/src/capability/extension.ts +3 -4
- package/src/capability/fs.ts +20 -21
- package/src/capability/hook.ts +3 -4
- package/src/capability/index.ts +15 -16
- package/src/capability/instruction.ts +3 -4
- package/src/capability/mcp.ts +3 -4
- package/src/capability/prompt.ts +3 -4
- package/src/capability/rule.ts +3 -4
- package/src/capability/settings.ts +2 -3
- package/src/capability/skill.ts +3 -4
- package/src/capability/slash-command.ts +3 -4
- package/src/capability/ssh.ts +3 -4
- package/src/capability/system-prompt.ts +3 -4
- package/src/capability/tool.ts +3 -4
- package/src/cli/args.ts +5 -6
- package/src/cli/config-cli.ts +6 -7
- package/src/cli/file-processor.ts +19 -17
- package/src/cli/jupyter-cli.ts +105 -0
- package/src/cli/list-models.ts +10 -11
- package/src/cli/plugin-cli.ts +20 -25
- package/src/cli/session-picker.ts +2 -3
- package/src/cli/setup-cli.ts +2 -3
- package/src/cli/stats-cli.ts +2 -3
- package/src/cli/update-cli.ts +25 -22
- package/src/commit/agentic/agent.ts +307 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +351 -0
- package/src/commit/agentic/prompts/analyze-file.md +22 -0
- package/src/commit/agentic/prompts/session-user.md +26 -0
- package/src/commit/agentic/prompts/split-confirm.md +1 -0
- package/src/commit/agentic/prompts/system.md +40 -0
- package/src/commit/agentic/state.ts +69 -0
- package/src/commit/agentic/tools/analyze-file.ts +131 -0
- package/src/commit/agentic/tools/git-file-diff.ts +194 -0
- package/src/commit/agentic/tools/git-hunk.ts +50 -0
- package/src/commit/agentic/tools/git-overview.ts +84 -0
- package/src/commit/agentic/tools/index.ts +56 -0
- package/src/commit/agentic/tools/propose-changelog.ts +128 -0
- package/src/commit/agentic/tools/propose-commit.ts +154 -0
- package/src/commit/agentic/tools/recent-commits.ts +81 -0
- package/src/commit/agentic/tools/split-commit.ts +280 -0
- package/src/commit/agentic/topo-sort.ts +44 -0
- package/src/commit/agentic/trivial.ts +51 -0
- package/src/commit/agentic/validation.ts +200 -0
- package/src/commit/analysis/conventional.ts +165 -0
- package/src/commit/analysis/index.ts +4 -0
- package/src/commit/analysis/scope.ts +242 -0
- package/src/commit/analysis/summary.ts +112 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +36 -0
- package/src/commit/changelog/generate.ts +110 -0
- package/src/commit/changelog/index.ts +233 -0
- package/src/commit/changelog/parse.ts +44 -0
- package/src/commit/cli.ts +93 -0
- package/src/commit/git/diff.ts +148 -0
- package/src/commit/git/errors.ts +11 -0
- package/src/commit/git/index.ts +212 -0
- package/src/commit/git/operations.ts +53 -0
- package/src/commit/index.ts +5 -0
- package/src/commit/map-reduce/index.ts +63 -0
- package/src/commit/map-reduce/map-phase.ts +178 -0
- package/src/commit/map-reduce/reduce-phase.ts +145 -0
- package/src/commit/map-reduce/utils.ts +9 -0
- package/src/commit/message.ts +11 -0
- package/src/commit/model-selection.ts +80 -0
- package/src/commit/pipeline.ts +240 -0
- package/src/commit/prompts/analysis-system.md +155 -0
- package/src/commit/prompts/analysis-user.md +41 -0
- package/src/commit/prompts/changelog-system.md +56 -0
- package/src/commit/prompts/changelog-user.md +19 -0
- package/src/commit/prompts/file-observer-system.md +26 -0
- package/src/commit/prompts/file-observer-user.md +9 -0
- package/src/commit/prompts/reduce-system.md +60 -0
- package/src/commit/prompts/reduce-user.md +17 -0
- package/src/commit/prompts/summary-retry.md +4 -0
- package/src/commit/prompts/summary-system.md +52 -0
- package/src/commit/prompts/summary-user.md +13 -0
- package/src/commit/prompts/types-description.md +2 -0
- package/src/commit/types.ts +109 -0
- package/src/commit/utils/exclusions.ts +42 -0
- package/src/config/file-lock.ts +121 -0
- package/src/config/keybindings.ts +6 -8
- package/src/config/model-registry.ts +65 -38
- package/src/config/model-resolver.ts +18 -19
- package/src/config/prompt-templates.ts +11 -11
- package/src/config/settings-manager.ts +141 -50
- package/src/config.ts +64 -66
- package/src/cursor.ts +11 -9
- package/src/discovery/agents-md.ts +11 -12
- package/src/discovery/builtin.ts +68 -73
- package/src/discovery/claude.ts +41 -42
- package/src/discovery/cline.ts +11 -12
- package/src/discovery/codex.ts +52 -53
- package/src/discovery/cursor.ts +9 -10
- package/src/discovery/gemini.ts +17 -22
- package/src/discovery/github.ts +13 -14
- package/src/discovery/helpers.ts +35 -34
- package/src/discovery/index.ts +22 -24
- package/src/discovery/mcp-json.ts +8 -9
- package/src/discovery/ssh.ts +8 -9
- package/src/discovery/vscode.ts +4 -5
- package/src/discovery/windsurf.ts +6 -7
- package/src/exa/company.ts +1 -2
- package/src/exa/index.ts +2 -3
- package/src/exa/linkedin.ts +1 -2
- package/src/exa/mcp-client.ts +14 -16
- package/src/exa/render.ts +10 -11
- package/src/exa/researcher.ts +1 -2
- package/src/exa/search.ts +1 -2
- package/src/exa/types.ts +0 -1
- package/src/exa/websets.ts +1 -2
- package/src/exec/bash-executor.ts +3 -4
- package/src/exec/exec.ts +0 -1
- package/src/export/custom-share.ts +5 -6
- package/src/export/html/index.ts +24 -21
- package/src/export/ttsr.ts +2 -3
- package/src/extensibility/custom-commands/bundled/review/index.ts +7 -8
- package/src/extensibility/custom-commands/loader.ts +18 -15
- package/src/extensibility/custom-commands/types.ts +2 -3
- package/src/extensibility/custom-tools/loader.ts +11 -12
- package/src/extensibility/custom-tools/types.ts +7 -8
- package/src/extensibility/custom-tools/wrapper.ts +2 -3
- package/src/extensibility/extensions/loader.ts +76 -54
- package/src/extensibility/extensions/runner.ts +11 -12
- package/src/extensibility/extensions/types.ts +20 -27
- package/src/extensibility/extensions/wrapper.ts +3 -4
- package/src/extensibility/hooks/index.ts +1 -1
- package/src/extensibility/hooks/loader.ts +9 -10
- package/src/extensibility/hooks/runner.ts +7 -8
- package/src/extensibility/hooks/tool-wrapper.ts +0 -1
- package/src/extensibility/hooks/types.ts +11 -18
- package/src/extensibility/plugins/doctor.ts +3 -3
- package/src/extensibility/plugins/installer.ts +27 -27
- package/src/extensibility/plugins/loader.ts +59 -56
- package/src/extensibility/plugins/manager.ts +211 -171
- package/src/extensibility/plugins/parser.ts +1 -1
- package/src/extensibility/plugins/paths.ts +8 -8
- package/src/extensibility/skills.ts +63 -60
- package/src/extensibility/slash-commands.ts +10 -10
- package/src/index.ts +54 -54
- package/src/internal-urls/agent-protocol.ts +21 -11
- package/src/internal-urls/artifact-protocol.ts +17 -13
- package/src/internal-urls/router.ts +1 -2
- package/src/internal-urls/rule-protocol.ts +3 -4
- package/src/internal-urls/skill-protocol.ts +3 -4
- package/src/ipy/executor.ts +109 -9
- package/src/ipy/gateway-coordinator.ts +79 -90
- package/src/ipy/kernel.ts +32 -30
- package/src/ipy/modules.ts +13 -13
- package/src/lsp/client.ts +21 -10
- package/src/lsp/clients/biome-client.ts +1 -2
- package/src/lsp/clients/index.ts +3 -3
- package/src/lsp/clients/lsp-linter-client.ts +4 -5
- package/src/lsp/config.ts +15 -15
- package/src/lsp/edits.ts +4 -5
- package/src/lsp/index.ts +43 -44
- package/src/lsp/lspmux.ts +8 -8
- package/src/lsp/render.ts +99 -61
- package/src/lsp/utils.ts +3 -3
- package/src/main.ts +71 -37
- package/src/mcp/client.ts +2 -3
- package/src/mcp/config.ts +5 -6
- package/src/mcp/json-rpc.ts +0 -1
- package/src/mcp/loader.ts +6 -7
- package/src/mcp/manager.ts +17 -18
- package/src/mcp/tool-bridge.ts +4 -9
- package/src/mcp/tool-cache.ts +2 -3
- package/src/mcp/transports/http.ts +2 -4
- package/src/mcp/transports/stdio.ts +1 -2
- package/src/migrations.ts +63 -52
- package/src/modes/components/armin.ts +4 -5
- package/src/modes/components/assistant-message.ts +33 -5
- package/src/modes/components/bash-execution.ts +7 -8
- package/src/modes/components/bordered-loader.ts +3 -3
- package/src/modes/components/branch-summary-message.ts +3 -3
- package/src/modes/components/compaction-summary-message.ts +3 -3
- package/src/modes/components/countdown-timer.ts +0 -1
- package/src/modes/components/custom-message.ts +5 -5
- package/src/modes/components/diff.ts +1 -1
- package/src/modes/components/dynamic-border.ts +2 -2
- package/src/modes/components/extensions/extension-dashboard.ts +6 -7
- package/src/modes/components/extensions/extension-list.ts +2 -3
- package/src/modes/components/extensions/inspector-panel.ts +3 -4
- package/src/modes/components/extensions/state-manager.ts +25 -26
- package/src/modes/components/extensions/types.ts +1 -2
- package/src/modes/components/footer.ts +47 -43
- package/src/modes/components/history-search.ts +2 -2
- package/src/modes/components/hook-editor.ts +3 -4
- package/src/modes/components/hook-input.ts +2 -3
- package/src/modes/components/hook-message.ts +5 -5
- package/src/modes/components/hook-selector.ts +2 -3
- package/src/modes/components/keybinding-hints.ts +2 -3
- package/src/modes/components/login-dialog.ts +2 -2
- package/src/modes/components/model-selector.ts +12 -12
- package/src/modes/components/oauth-selector.ts +2 -2
- package/src/modes/components/plugin-settings.ts +20 -20
- package/src/modes/components/python-execution.ts +7 -8
- package/src/modes/components/queue-mode-selector.ts +3 -3
- package/src/modes/components/read-tool-group.ts +2 -2
- package/src/modes/components/session-selector.ts +4 -4
- package/src/modes/components/settings-defs.ts +77 -69
- package/src/modes/components/settings-selector.ts +16 -16
- package/src/modes/components/show-images-selector.ts +2 -2
- package/src/modes/components/status-line/segments.ts +4 -4
- package/src/modes/components/status-line/separators.ts +1 -1
- package/src/modes/components/status-line/types.ts +2 -2
- package/src/modes/components/status-line-segment-editor.ts +7 -8
- package/src/modes/components/status-line.ts +12 -12
- package/src/modes/components/theme-selector.ts +8 -7
- package/src/modes/components/thinking-selector.ts +4 -4
- package/src/modes/components/todo-display.ts +2 -2
- package/src/modes/components/todo-reminder.ts +4 -4
- package/src/modes/components/tool-execution.ts +16 -19
- package/src/modes/components/tree-selector.ts +12 -12
- package/src/modes/components/ttsr-notification.ts +5 -5
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +1 -1
- package/src/modes/components/visual-truncate.ts +0 -1
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +46 -47
- package/src/modes/controllers/event-controller.ts +16 -20
- package/src/modes/controllers/extension-ui-controller.ts +40 -46
- package/src/modes/controllers/input-controller.ts +17 -18
- package/src/modes/controllers/selector-controller.ts +103 -91
- package/src/modes/index.ts +3 -3
- package/src/modes/interactive-mode.ts +31 -31
- package/src/modes/print-mode.ts +12 -13
- package/src/modes/rpc/rpc-client.ts +7 -8
- package/src/modes/rpc/rpc-mode.ts +24 -28
- package/src/modes/rpc/rpc-types.ts +3 -4
- package/src/modes/theme/mermaid-cache.ts +89 -0
- package/src/modes/theme/theme.ts +130 -53
- package/src/modes/types.ts +10 -10
- package/src/modes/utils/ui-helpers.ts +17 -17
- package/src/patch/applicator.ts +18 -19
- package/src/patch/diff.ts +1 -2
- package/src/patch/fuzzy.ts +1 -2
- package/src/patch/index.ts +11 -18
- package/src/patch/normalize.ts +4 -4
- package/src/patch/normative.ts +1 -2
- package/src/patch/parser.ts +8 -9
- package/src/patch/shared.ts +43 -16
- package/src/prompts/tools/task.md +2 -0
- package/src/sdk.ts +100 -65
- package/src/session/agent-session.ts +84 -85
- package/src/session/agent-storage.ts +43 -39
- package/src/session/artifacts.ts +32 -10
- package/src/session/auth-storage.ts +50 -39
- package/src/session/compaction/branch-summarization.ts +7 -10
- package/src/session/compaction/compaction.ts +8 -19
- package/src/session/compaction/utils.ts +6 -9
- package/src/session/history-storage.ts +10 -10
- package/src/session/messages.ts +4 -5
- package/src/session/session-manager.ts +76 -65
- package/src/session/session-storage.ts +57 -69
- package/src/session/storage-migration.ts +14 -56
- package/src/session/streaming-output.ts +2 -2
- package/src/ssh/connection-manager.ts +43 -50
- package/src/ssh/ssh-executor.ts +2 -2
- package/src/ssh/sshfs-mount.ts +11 -18
- package/src/system-prompt.ts +28 -35
- package/src/task/agents.ts +45 -30
- package/src/task/commands.ts +6 -7
- package/src/task/discovery.ts +39 -76
- package/src/task/executor.ts +14 -15
- package/src/task/index.ts +40 -34
- package/src/task/output-manager.ts +93 -0
- package/src/task/parallel.ts +0 -1
- package/src/task/render.ts +24 -30
- package/src/task/subprocess-tool-registry.ts +1 -2
- package/src/task/worker-protocol.ts +3 -3
- package/src/task/worker.ts +33 -39
- package/src/task/worktree.ts +19 -19
- package/src/tools/ask.ts +41 -20
- package/src/tools/bash-interceptor.ts +1 -5
- package/src/tools/bash.ts +91 -97
- package/src/tools/calculator.ts +49 -47
- package/src/tools/complete.ts +4 -5
- package/src/tools/context.ts +2 -2
- package/src/tools/fetch.ts +84 -124
- package/src/tools/find.ts +94 -98
- package/src/tools/gemini-image.ts +14 -14
- package/src/tools/grep.ts +100 -116
- package/src/tools/index.ts +80 -55
- package/src/tools/list-limit.ts +1 -1
- package/src/tools/ls.ts +44 -70
- package/src/tools/notebook.ts +51 -67
- package/src/tools/output-meta.ts +3 -4
- package/src/tools/output-utils.ts +2 -2
- package/src/tools/path-utils.ts +5 -5
- package/src/tools/python.ts +104 -217
- package/src/tools/read.ts +92 -33
- package/src/tools/render-utils.ts +8 -23
- package/src/tools/renderers.ts +6 -7
- package/src/tools/review.ts +8 -11
- package/src/tools/ssh.ts +69 -49
- package/src/tools/todo-write.ts +37 -25
- package/src/tools/tool-errors.ts +3 -3
- package/src/tools/tool-result.ts +3 -8
- package/src/tools/write.ts +99 -75
- package/src/tui/code-cell.ts +109 -0
- package/src/tui/file-list.ts +47 -0
- package/src/tui/index.ts +11 -0
- package/src/tui/output-block.ts +72 -0
- package/src/tui/status-line.ts +39 -0
- package/src/tui/tree-list.ts +55 -0
- package/src/tui/types.ts +16 -0
- package/src/tui/utils.ts +48 -0
- package/src/utils/changelog.ts +9 -10
- package/src/utils/clipboard.ts +11 -11
- package/src/utils/file-mentions.ts +4 -10
- package/src/utils/frontmatter.ts +6 -3
- package/src/utils/fuzzy.ts +2 -2
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +1 -1
- package/src/utils/mime.ts +2 -2
- package/src/utils/shell-snapshot.ts +11 -13
- package/src/utils/shell.ts +4 -5
- package/src/utils/title-generator.ts +8 -9
- package/src/utils/tools-manager.ts +23 -23
- package/src/vendor/photon/index.js +1099 -1059
- package/src/vendor/photon/photon_rs_bg.wasm +0 -0
- package/src/web/scrapers/artifacthub.ts +1 -1
- package/src/web/scrapers/arxiv.ts +2 -2
- package/src/web/scrapers/bluesky.ts +2 -2
- package/src/web/scrapers/cheatsh.ts +1 -1
- package/src/web/scrapers/chocolatey.ts +2 -2
- package/src/web/scrapers/choosealicense.ts +5 -5
- package/src/web/scrapers/cisa-kev.ts +1 -1
- package/src/web/scrapers/crossref.ts +2 -2
- package/src/web/scrapers/devto.ts +3 -3
- package/src/web/scrapers/discogs.ts +3 -4
- package/src/web/scrapers/discourse.ts +1 -1
- package/src/web/scrapers/dockerhub.ts +1 -1
- package/src/web/scrapers/fdroid.ts +2 -2
- package/src/web/scrapers/firefox-addons.ts +3 -3
- package/src/web/scrapers/flathub.ts +1 -1
- package/src/web/scrapers/github.ts +3 -3
- package/src/web/scrapers/gitlab.ts +4 -4
- package/src/web/scrapers/hackernews.ts +2 -2
- package/src/web/scrapers/huggingface.ts +1 -1
- package/src/web/scrapers/iacr.ts +2 -2
- package/src/web/scrapers/index.ts +0 -1
- package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
- package/src/web/scrapers/lemmy.ts +2 -2
- package/src/web/scrapers/maven.ts +2 -2
- package/src/web/scrapers/mdn.ts +2 -4
- package/src/web/scrapers/metacpan.ts +2 -2
- package/src/web/scrapers/musicbrainz.ts +1 -2
- package/src/web/scrapers/npm.ts +1 -1
- package/src/web/scrapers/nuget.ts +2 -2
- package/src/web/scrapers/nvd.ts +3 -3
- package/src/web/scrapers/ollama.ts +7 -9
- package/src/web/scrapers/opencorporates.ts +2 -2
- package/src/web/scrapers/openlibrary.ts +6 -6
- package/src/web/scrapers/orcid.ts +0 -1
- package/src/web/scrapers/osv.ts +2 -2
- package/src/web/scrapers/packagist.ts +1 -1
- package/src/web/scrapers/pubmed.ts +1 -2
- package/src/web/scrapers/rawg.ts +2 -2
- package/src/web/scrapers/readthedocs.ts +1 -2
- package/src/web/scrapers/repology.ts +2 -2
- package/src/web/scrapers/rfc.ts +1 -1
- package/src/web/scrapers/searchcode.ts +2 -2
- package/src/web/scrapers/semantic-scholar.ts +1 -1
- package/src/web/scrapers/snapcraft.ts +2 -2
- package/src/web/scrapers/sourcegraph.ts +1 -1
- package/src/web/scrapers/spdx.ts +3 -3
- package/src/web/scrapers/spotify.ts +0 -1
- package/src/web/scrapers/twitter.ts +1 -1
- package/src/web/scrapers/types.ts +1 -2
- package/src/web/scrapers/utils.ts +5 -5
- package/src/web/scrapers/wikidata.ts +3 -3
- package/src/web/scrapers/youtube.ts +9 -14
- package/src/web/search/auth.ts +5 -10
- package/src/web/search/index.ts +11 -21
- package/src/web/search/providers/anthropic.ts +3 -9
- package/src/web/search/providers/exa.ts +6 -10
- package/src/web/search/providers/perplexity.ts +5 -5
- package/src/web/search/render.ts +129 -175
- package/tsconfig.json +0 -42
package/src/task/agents.ts
CHANGED
|
@@ -3,16 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Agents are embedded at build time via Bun's import with { type: "text" }.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import exploreMd from "@oh-my-pi/pi-coding-agent/prompts/agents/explore.md" with { type: "text" };
|
|
6
|
+
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
7
|
+
import { parseAgentFields } from "../discovery/helpers";
|
|
8
|
+
import exploreMd from "../prompts/agents/explore.md" with { type: "text" };
|
|
10
9
|
// Embed agent markdown files at build time
|
|
11
|
-
import agentFrontmatterTemplate from "
|
|
12
|
-
import planMd from "
|
|
13
|
-
import reviewerMd from "
|
|
14
|
-
import taskMd from "
|
|
15
|
-
import { parseFrontmatter } from "
|
|
10
|
+
import agentFrontmatterTemplate from "../prompts/agents/frontmatter.md" with { type: "text" };
|
|
11
|
+
import planMd from "../prompts/agents/plan.md" with { type: "text" };
|
|
12
|
+
import reviewerMd from "../prompts/agents/reviewer.md" with { type: "text" };
|
|
13
|
+
import taskMd from "../prompts/agents/task.md" with { type: "text" };
|
|
14
|
+
import { parseFrontmatter } from "../utils/frontmatter";
|
|
16
15
|
import type { AgentDefinition, AgentSource } from "./types";
|
|
17
16
|
|
|
18
17
|
interface AgentFrontmatter {
|
|
@@ -69,30 +68,56 @@ const EMBEDDED_AGENT_DEFS: EmbeddedAgentDef[] = [
|
|
|
69
68
|
},
|
|
70
69
|
];
|
|
71
70
|
|
|
72
|
-
const EMBEDDED_AGENTS: { name: string; content: string }[] = EMBEDDED_AGENT_DEFS.map(
|
|
71
|
+
const EMBEDDED_AGENTS: { name: string; content: string }[] = EMBEDDED_AGENT_DEFS.map(def => ({
|
|
73
72
|
name: def.fileName,
|
|
74
73
|
content: buildAgentContent(def),
|
|
75
74
|
}));
|
|
76
75
|
|
|
76
|
+
export class AgentParsingError extends Error {
|
|
77
|
+
constructor(
|
|
78
|
+
error: Error,
|
|
79
|
+
public readonly source?: unknown,
|
|
80
|
+
) {
|
|
81
|
+
super(`Failed to parse agent: ${error.message}`, { cause: error });
|
|
82
|
+
this.name = "AgentParsingError";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
toString(): string {
|
|
86
|
+
const details: string[] = [this.message];
|
|
87
|
+
if (this.source !== undefined) {
|
|
88
|
+
details.push(`Source: ${JSON.stringify(this.source)}`);
|
|
89
|
+
}
|
|
90
|
+
if (this.cause && typeof this.cause === "object" && "stack" in this.cause && this.cause.stack) {
|
|
91
|
+
details.push(`Stack:\n${this.cause.stack}`);
|
|
92
|
+
} else if (this.stack) {
|
|
93
|
+
details.push(`Stack:\n${this.stack}`);
|
|
94
|
+
}
|
|
95
|
+
return details.join("\n\n");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
77
99
|
/**
|
|
78
100
|
* Parse an agent from embedded content.
|
|
79
101
|
*/
|
|
80
|
-
function parseAgent(
|
|
102
|
+
export function parseAgent(
|
|
103
|
+
filePath: string,
|
|
104
|
+
content: string,
|
|
105
|
+
source: AgentSource,
|
|
106
|
+
level: "fatal" | "warn" | "off" = "fatal",
|
|
107
|
+
): AgentDefinition {
|
|
81
108
|
const { frontmatter, body } = parseFrontmatter(content, {
|
|
82
|
-
|
|
83
|
-
level
|
|
109
|
+
location: filePath,
|
|
110
|
+
level,
|
|
84
111
|
});
|
|
85
112
|
const fields = parseAgentFields(frontmatter);
|
|
86
|
-
|
|
87
113
|
if (!fields) {
|
|
88
|
-
|
|
114
|
+
throw new AgentParsingError(new Error("Invalid agent fields"), filePath);
|
|
89
115
|
}
|
|
90
|
-
|
|
91
116
|
return {
|
|
92
117
|
...fields,
|
|
93
118
|
systemPrompt: body,
|
|
94
119
|
source,
|
|
95
|
-
filePath
|
|
120
|
+
filePath,
|
|
96
121
|
};
|
|
97
122
|
}
|
|
98
123
|
|
|
@@ -107,25 +132,15 @@ export function loadBundledAgents(): AgentDefinition[] {
|
|
|
107
132
|
if (bundledAgentsCache !== null) {
|
|
108
133
|
return bundledAgentsCache;
|
|
109
134
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
for (const { name, content } of EMBEDDED_AGENTS) {
|
|
114
|
-
const agent = parseAgent(name, content, "bundled");
|
|
115
|
-
if (agent) {
|
|
116
|
-
agents.push(agent);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
bundledAgentsCache = agents;
|
|
121
|
-
return agents;
|
|
135
|
+
bundledAgentsCache = EMBEDDED_AGENTS.map(({ name, content }) => parseAgent(`embedded:${name}`, content, "bundled"));
|
|
136
|
+
return bundledAgentsCache;
|
|
122
137
|
}
|
|
123
138
|
|
|
124
139
|
/**
|
|
125
140
|
* Get a bundled agent by name.
|
|
126
141
|
*/
|
|
127
142
|
export function getBundledAgent(name: string): AgentDefinition | undefined {
|
|
128
|
-
return loadBundledAgents().find(
|
|
143
|
+
return loadBundledAgents().find(a => a.name === name);
|
|
129
144
|
}
|
|
130
145
|
|
|
131
146
|
/**
|
package/src/task/commands.ts
CHANGED
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Commands are embedded at build time via Bun's import with { type: "text" }.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
6
|
import * as path from "node:path";
|
|
8
|
-
import { type SlashCommand, slashCommandCapability } from "
|
|
9
|
-
import { renderPromptTemplate } from "
|
|
10
|
-
import { loadCapability } from "
|
|
7
|
+
import { type SlashCommand, slashCommandCapability } from "../capability/slash-command";
|
|
8
|
+
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
9
|
+
import { loadCapability } from "../discovery";
|
|
11
10
|
// Embed command markdown files at build time
|
|
12
|
-
import initMd from "
|
|
13
|
-
import { parseFrontmatter } from "
|
|
11
|
+
import initMd from "../prompts/agents/init.md" with { type: "text" };
|
|
12
|
+
import { parseFrontmatter } from "../utils/frontmatter";
|
|
14
13
|
|
|
15
14
|
const EMBEDDED_COMMANDS: { name: string; content: string }[] = [
|
|
16
15
|
{ name: "init.md", content: renderPromptTemplate(initMd) },
|
|
@@ -116,7 +115,7 @@ export async function discoverCommands(cwd: string): Promise<WorkflowCommand[]>
|
|
|
116
115
|
* Get a command by name.
|
|
117
116
|
*/
|
|
118
117
|
export function getCommand(commands: WorkflowCommand[], name: string): WorkflowCommand | undefined {
|
|
119
|
-
return commands.find(
|
|
118
|
+
return commands.find(c => c.name === name);
|
|
120
119
|
}
|
|
121
120
|
|
|
122
121
|
/**
|
package/src/task/discovery.ts
CHANGED
|
@@ -11,13 +11,11 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Agent files use markdown with YAML frontmatter.
|
|
13
13
|
*/
|
|
14
|
-
|
|
15
|
-
import * as fs from "node:fs";
|
|
14
|
+
import * as fs from "node:fs/promises";
|
|
16
15
|
import * as path from "node:path";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { loadBundledAgents } from "./agents";
|
|
16
|
+
import { logger } from "@oh-my-pi/pi-utils";
|
|
17
|
+
import { findAllNearestProjectConfigDirs, getConfigDirs } from "../config";
|
|
18
|
+
import { loadBundledAgents, parseAgent } from "./agents";
|
|
21
19
|
import type { AgentDefinition, AgentSource } from "./types";
|
|
22
20
|
|
|
23
21
|
/** Result of agent discovery */
|
|
@@ -29,55 +27,23 @@ export interface DiscoveryResult {
|
|
|
29
27
|
/**
|
|
30
28
|
* Load agents from a directory.
|
|
31
29
|
*/
|
|
32
|
-
function loadAgentsFromDir(dir: string, source: AgentSource): AgentDefinition[] {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
for (const entry of entries) {
|
|
47
|
-
if (!entry.name.endsWith(".md")) continue;
|
|
48
|
-
|
|
49
|
-
const filePath = path.resolve(dir, entry.name);
|
|
50
|
-
|
|
51
|
-
// Handle both regular files and symlinks
|
|
52
|
-
try {
|
|
53
|
-
if (!fs.statSync(filePath).isFile()) continue;
|
|
54
|
-
} catch {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
let content: string;
|
|
59
|
-
try {
|
|
60
|
-
content = fs.readFileSync(filePath, "utf-8");
|
|
61
|
-
} catch {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const { frontmatter, body } = parseFrontmatter(content, { source: filePath });
|
|
66
|
-
const fields = parseAgentFields(frontmatter);
|
|
67
|
-
|
|
68
|
-
if (!fields) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
agents.push({
|
|
73
|
-
...fields,
|
|
74
|
-
systemPrompt: body,
|
|
75
|
-
source,
|
|
76
|
-
filePath,
|
|
30
|
+
async function loadAgentsFromDir(dir: string, source: AgentSource): Promise<AgentDefinition[]> {
|
|
31
|
+
const entries = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
32
|
+
const files = entries
|
|
33
|
+
.filter(entry => (entry.isFile() || entry.isSymbolicLink()) && entry.name.endsWith(".md"))
|
|
34
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
35
|
+
.map(file => {
|
|
36
|
+
const filePath = path.join(dir, file.name);
|
|
37
|
+
return fs
|
|
38
|
+
.readFile(filePath, "utf-8")
|
|
39
|
+
.then(content => parseAgent(filePath, content, source, "warn"))
|
|
40
|
+
.catch(error => {
|
|
41
|
+
logger.warn("Failed to read agent file", { filePath, error });
|
|
42
|
+
return null;
|
|
43
|
+
});
|
|
77
44
|
});
|
|
78
|
-
}
|
|
79
45
|
|
|
80
|
-
return
|
|
46
|
+
return (await Promise.all(files)).filter(Boolean) as AgentDefinition[];
|
|
81
47
|
}
|
|
82
48
|
|
|
83
49
|
/**
|
|
@@ -89,62 +55,59 @@ function loadAgentsFromDir(dir: string, source: AgentSource): AgentDefinition[]
|
|
|
89
55
|
*/
|
|
90
56
|
export async function discoverAgents(cwd: string): Promise<DiscoveryResult> {
|
|
91
57
|
const resolvedCwd = path.resolve(cwd);
|
|
92
|
-
const agentSources = Array.from(new Set(getConfigDirs("", { project: false }).map(
|
|
58
|
+
const agentSources = Array.from(new Set(getConfigDirs("", { project: false }).map(entry => entry.source)));
|
|
93
59
|
|
|
94
60
|
// Get user directories (priority order: .omp, .pi, .claude, ...)
|
|
95
61
|
const userDirs = getConfigDirs("agents", { project: false })
|
|
96
|
-
.filter(
|
|
97
|
-
.map(
|
|
62
|
+
.filter(entry => agentSources.includes(entry.source))
|
|
63
|
+
.map(entry => ({
|
|
98
64
|
...entry,
|
|
99
65
|
path: path.resolve(entry.path),
|
|
100
66
|
}));
|
|
101
67
|
|
|
102
68
|
// Get project directories by walking up from cwd (priority order)
|
|
103
69
|
const projectDirs = (await findAllNearestProjectConfigDirs("agents", resolvedCwd))
|
|
104
|
-
.filter(
|
|
105
|
-
.map(
|
|
70
|
+
.filter(entry => agentSources.includes(entry.source))
|
|
71
|
+
.map(entry => ({
|
|
106
72
|
...entry,
|
|
107
73
|
path: path.resolve(entry.path),
|
|
108
74
|
}));
|
|
109
75
|
|
|
110
76
|
const orderedSources = agentSources.filter(
|
|
111
|
-
(source) =>
|
|
112
|
-
userDirs.some((entry) => entry.source === source) || projectDirs.some((entry) => entry.source === source),
|
|
77
|
+
source => userDirs.some(entry => entry.source === source) || projectDirs.some(entry => entry.source === source),
|
|
113
78
|
);
|
|
114
79
|
|
|
115
80
|
const orderedDirs: Array<{ dir: string; source: AgentSource }> = [];
|
|
116
81
|
for (const source of orderedSources) {
|
|
117
|
-
const project = projectDirs.find(
|
|
82
|
+
const project = projectDirs.find(entry => entry.source === source);
|
|
118
83
|
if (project) orderedDirs.push({ dir: project.path, source: "project" });
|
|
119
|
-
const user = userDirs.find(
|
|
84
|
+
const user = userDirs.find(entry => entry.source === source);
|
|
120
85
|
if (user) orderedDirs.push({ dir: user.path, source: "user" });
|
|
121
86
|
}
|
|
122
87
|
|
|
123
|
-
const agents: AgentDefinition[] = [];
|
|
124
88
|
const seen = new Set<string>();
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (seen.has(agent.name))
|
|
129
|
-
agents.push(agent);
|
|
89
|
+
const loadedAgents = (await Promise.all(orderedDirs.map(({ dir, source }) => loadAgentsFromDir(dir, source))))
|
|
90
|
+
.flat()
|
|
91
|
+
.filter(agent => {
|
|
92
|
+
if (seen.has(agent.name)) return false;
|
|
130
93
|
seen.add(agent.name);
|
|
131
|
-
|
|
132
|
-
|
|
94
|
+
return true;
|
|
95
|
+
});
|
|
133
96
|
|
|
134
|
-
|
|
135
|
-
if (seen.has(agent.name))
|
|
136
|
-
agents.push(agent);
|
|
97
|
+
const bundledAgents = loadBundledAgents().filter(agent => {
|
|
98
|
+
if (seen.has(agent.name)) return false;
|
|
137
99
|
seen.add(agent.name);
|
|
138
|
-
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
139
102
|
|
|
140
103
|
const projectAgentsDir = projectDirs.length > 0 ? projectDirs[0].path : null;
|
|
141
104
|
|
|
142
|
-
return { agents, projectAgentsDir };
|
|
105
|
+
return { agents: [...loadedAgents, ...bundledAgents], projectAgentsDir };
|
|
143
106
|
}
|
|
144
107
|
|
|
145
108
|
/**
|
|
146
109
|
* Get an agent by name from discovered agents.
|
|
147
110
|
*/
|
|
148
111
|
export function getAgent(agents: AgentDefinition[], name: string): AgentDefinition | undefined {
|
|
149
|
-
return agents.find(
|
|
112
|
+
return agents.find(a => a.name === name);
|
|
150
113
|
}
|
package/src/task/executor.ts
CHANGED
|
@@ -3,20 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Runs each subagent in a Bun Worker and forwards AgentEvents for progress tracking.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
6
|
import path from "node:path";
|
|
8
7
|
import type { AgentEvent, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
9
|
-
import type { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
|
|
10
|
-
import { formatModelString, parseModelPattern } from "@oh-my-pi/pi-coding-agent/config/model-resolver";
|
|
11
|
-
import { checkPythonKernelAvailability } from "@oh-my-pi/pi-coding-agent/ipy/kernel";
|
|
12
|
-
import { LspTool } from "@oh-my-pi/pi-coding-agent/lsp/index";
|
|
13
|
-
import type { LspParams } from "@oh-my-pi/pi-coding-agent/lsp/types";
|
|
14
|
-
import { callTool } from "@oh-my-pi/pi-coding-agent/mcp/client";
|
|
15
|
-
import type { MCPManager } from "@oh-my-pi/pi-coding-agent/mcp/manager";
|
|
16
|
-
import type { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
|
|
17
|
-
import { PythonTool, type PythonToolParams } from "@oh-my-pi/pi-coding-agent/tools/python";
|
|
18
|
-
import type { EventBus } from "@oh-my-pi/pi-coding-agent/utils/event-bus";
|
|
19
8
|
import type { ToolSession } from "..";
|
|
9
|
+
import type { ModelRegistry } from "../config/model-registry";
|
|
10
|
+
import { formatModelString, parseModelPattern } from "../config/model-resolver";
|
|
11
|
+
import { checkPythonKernelAvailability } from "../ipy/kernel";
|
|
12
|
+
import { LspTool } from "../lsp";
|
|
13
|
+
import type { LspParams } from "../lsp/types";
|
|
14
|
+
import { callTool } from "../mcp/client";
|
|
15
|
+
import type { MCPManager } from "../mcp/manager";
|
|
16
|
+
import type { AuthStorage } from "../session/auth-storage";
|
|
17
|
+
import { PythonTool, type PythonToolParams } from "../tools/python";
|
|
18
|
+
import type { EventBus } from "../utils/event-bus";
|
|
20
19
|
import { subprocessToolRegistry } from "./subprocess-tool-registry";
|
|
21
20
|
import {
|
|
22
21
|
type AgentDefinition,
|
|
@@ -171,7 +170,7 @@ function getUsageTokens(usage: unknown): number {
|
|
|
171
170
|
* falling back to empty strings if not.
|
|
172
171
|
*/
|
|
173
172
|
function extractMCPToolMetadata(mcpManager: MCPManager): MCPToolMetadata[] {
|
|
174
|
-
return mcpManager.getTools().map(
|
|
173
|
+
return mcpManager.getTools().map(tool => {
|
|
175
174
|
// MCPTool and DeferredMCPTool have these properties
|
|
176
175
|
const mcpTool = tool as { mcpToolName?: string; mcpServerName?: string };
|
|
177
176
|
return {
|
|
@@ -264,7 +263,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
264
263
|
|
|
265
264
|
const pythonToolMode = options.settingsManager?.getPythonToolMode?.() ?? "ipy-only";
|
|
266
265
|
if (toolNames?.includes("exec")) {
|
|
267
|
-
const expanded = toolNames.filter(
|
|
266
|
+
const expanded = toolNames.filter(name => name !== "exec");
|
|
268
267
|
if (pythonToolMode === "bash-only") {
|
|
269
268
|
expanded.push("bash");
|
|
270
269
|
} else if (pythonToolMode === "ipy-only") {
|
|
@@ -706,11 +705,11 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
706
705
|
message: string;
|
|
707
706
|
}
|
|
708
707
|
|
|
709
|
-
const done = await new Promise<Extract<SubagentWorkerResponse, { type: "done" }>>(
|
|
708
|
+
const done = await new Promise<Extract<SubagentWorkerResponse, { type: "done" }>>(resolve => {
|
|
710
709
|
const cleanup = () => {
|
|
711
710
|
listenerController.abort();
|
|
712
711
|
};
|
|
713
|
-
finalize =
|
|
712
|
+
finalize = message => {
|
|
714
713
|
if (resolved) return;
|
|
715
714
|
resolved = true;
|
|
716
715
|
cleanup();
|
package/src/task/index.ts
CHANGED
|
@@ -12,21 +12,23 @@
|
|
|
12
12
|
* - Progress tracking via JSON events
|
|
13
13
|
* - Session artifacts for debugging
|
|
14
14
|
*/
|
|
15
|
-
|
|
16
|
-
import
|
|
17
|
-
import { tmpdir } from "node:os";
|
|
15
|
+
import * as fs from "node:fs/promises";
|
|
16
|
+
import * as os from "node:os";
|
|
18
17
|
import path from "node:path";
|
|
19
18
|
import type { AgentTool, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
20
19
|
import type { Usage } from "@oh-my-pi/pi-ai";
|
|
21
|
-
import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
|
|
22
|
-
import type { Theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
|
23
|
-
import taskDescriptionTemplate from "@oh-my-pi/pi-coding-agent/prompts/tools/task.md" with { type: "text" };
|
|
24
|
-
import { formatDuration } from "@oh-my-pi/pi-coding-agent/tools/render-utils";
|
|
25
20
|
import { $ } from "bun";
|
|
26
21
|
import { nanoid } from "nanoid";
|
|
27
22
|
import type { ToolSession } from "..";
|
|
23
|
+
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
24
|
+
import type { Theme } from "../modes/theme/theme";
|
|
25
|
+
import taskDescriptionTemplate from "../prompts/tools/task.md" with { type: "text" };
|
|
26
|
+
import { formatDuration } from "../tools/render-utils";
|
|
27
|
+
// Import review tools for side effects (registers subagent tool handlers)
|
|
28
|
+
import "../tools/review";
|
|
28
29
|
import { discoverAgents, getAgent } from "./discovery";
|
|
29
30
|
import { runSubprocess } from "./executor";
|
|
31
|
+
import { AgentOutputManager } from "./output-manager";
|
|
30
32
|
import { mapWithConcurrencyLimit } from "./parallel";
|
|
31
33
|
import { renderCall, renderResult } from "./render";
|
|
32
34
|
import { renderTemplate } from "./template";
|
|
@@ -48,9 +50,6 @@ import {
|
|
|
48
50
|
getRepoRoot,
|
|
49
51
|
} from "./worktree";
|
|
50
52
|
|
|
51
|
-
// Import review tools for side effects (registers subagent tool handlers)
|
|
52
|
-
import "../tools/review";
|
|
53
|
-
|
|
54
53
|
/** Format byte count for display */
|
|
55
54
|
function formatBytes(bytes: number): string {
|
|
56
55
|
if (bytes < 1024) return `${bytes}B`;
|
|
@@ -101,6 +100,7 @@ function addUsageTotals(target: Usage, usage: Partial<Usage>): void {
|
|
|
101
100
|
export { loadBundledAgents as BUNDLED_AGENTS } from "./agents";
|
|
102
101
|
export { discoverCommands, expandCommand, getCommand } from "./commands";
|
|
103
102
|
export { discoverAgents, getAgent } from "./discovery";
|
|
103
|
+
export { AgentOutputManager } from "./output-manager";
|
|
104
104
|
export type { AgentDefinition, AgentProgress, SingleResult, TaskParams, TaskToolDetails } from "./types";
|
|
105
105
|
export { taskSchema } from "./types";
|
|
106
106
|
|
|
@@ -172,7 +172,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
172
172
|
// Validate agent exists
|
|
173
173
|
const agent = getAgent(agents, agentName);
|
|
174
174
|
if (!agent) {
|
|
175
|
-
const available = agents.map(
|
|
175
|
+
const available = agents.map(a => a.name).join(", ") || "none";
|
|
176
176
|
return {
|
|
177
177
|
content: [
|
|
178
178
|
{
|
|
@@ -266,7 +266,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
266
266
|
problems.push(`Missing task ids at indexes: ${missingTaskIndexes.join(", ")}`);
|
|
267
267
|
}
|
|
268
268
|
if (duplicateIds.length > 0) {
|
|
269
|
-
const details = duplicateIds.map(
|
|
269
|
+
const details = duplicateIds.map(entry => `${entry.id} (indexes ${entry.indexes.join(", ")})`).join("; ");
|
|
270
270
|
problems.push(`Duplicate task ids detected (case-insensitive): ${details}`);
|
|
271
271
|
}
|
|
272
272
|
return {
|
|
@@ -306,9 +306,8 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
306
306
|
// Derive artifacts directory
|
|
307
307
|
const sessionFile = this.session.getSessionFile();
|
|
308
308
|
const artifactsDir = sessionFile ? sessionFile.slice(0, -6) : null;
|
|
309
|
-
const tempArtifactsDir = artifactsDir ? null : path.join(tmpdir(), `omp-task-${nanoid()}`);
|
|
309
|
+
const tempArtifactsDir = artifactsDir ? null : path.join(os.tmpdir(), `omp-task-${nanoid()}`);
|
|
310
310
|
const effectiveArtifactsDir = artifactsDir || tempArtifactsDir!;
|
|
311
|
-
await mkdir(effectiveArtifactsDir, { recursive: true });
|
|
312
311
|
|
|
313
312
|
// Initialize progress tracking
|
|
314
313
|
const progressMap = new Map<number, AgentProgress>();
|
|
@@ -347,7 +346,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
347
346
|
|
|
348
347
|
// Check spawn restrictions from parent
|
|
349
348
|
const parentSpawns = this.session.getSessionSpawns() ?? "*";
|
|
350
|
-
const allowedSpawns = parentSpawns.split(",").map(
|
|
349
|
+
const allowedSpawns = parentSpawns.split(",").map(s => s.trim());
|
|
351
350
|
const isSpawnAllowed = (): boolean => {
|
|
352
351
|
if (parentSpawns === "") return false; // Empty = deny all
|
|
353
352
|
if (parentSpawns === "*") return true; // Wildcard = allow all
|
|
@@ -367,7 +366,14 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
367
366
|
}
|
|
368
367
|
|
|
369
368
|
// Build full prompts with context prepended
|
|
370
|
-
|
|
369
|
+
// Allocate unique IDs across the session to prevent artifact collisions
|
|
370
|
+
const outputManager =
|
|
371
|
+
this.session.agentOutputManager ?? new AgentOutputManager(this.session.getArtifactsDir ?? (() => null));
|
|
372
|
+
const uniqueIds = await outputManager.allocateBatch(tasks.map(t => t.id));
|
|
373
|
+
const tasksWithUniqueIds = tasks.map((t, i) => ({ ...t, id: uniqueIds[i] }));
|
|
374
|
+
|
|
375
|
+
// Build full prompts with context prepended
|
|
376
|
+
const tasksWithContext = tasksWithUniqueIds.map(t => renderTemplate(context, t));
|
|
371
377
|
|
|
372
378
|
// Initialize progress for all tasks
|
|
373
379
|
for (let i = 0; i < tasksWithContext.length; i++) {
|
|
@@ -410,7 +416,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
410
416
|
enableLsp: false,
|
|
411
417
|
signal,
|
|
412
418
|
eventBus: undefined,
|
|
413
|
-
onProgress:
|
|
419
|
+
onProgress: progress => {
|
|
414
420
|
progressMap.set(index, {
|
|
415
421
|
...structuredClone(progress),
|
|
416
422
|
args: tasksWithContext[index]?.args,
|
|
@@ -450,7 +456,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
450
456
|
enableLsp: false,
|
|
451
457
|
signal,
|
|
452
458
|
eventBus: undefined,
|
|
453
|
-
onProgress:
|
|
459
|
+
onProgress: progress => {
|
|
454
460
|
progressMap.set(index, {
|
|
455
461
|
...structuredClone(progress),
|
|
456
462
|
args: tasksWithContext[index]?.args,
|
|
@@ -556,29 +562,29 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
556
562
|
let patchApplySummary = "";
|
|
557
563
|
let patchesApplied: boolean | null = null;
|
|
558
564
|
if (isIsolated) {
|
|
559
|
-
const patchesInOrder = results.map(
|
|
560
|
-
const missingPatch = results.some(
|
|
565
|
+
const patchesInOrder = results.map(result => result.patchPath).filter(Boolean) as string[];
|
|
566
|
+
const missingPatch = results.some(result => !result.patchPath);
|
|
561
567
|
if (!repoRoot || missingPatch) {
|
|
562
568
|
patchesApplied = false;
|
|
563
569
|
} else {
|
|
564
570
|
const patchStats = await Promise.all(
|
|
565
|
-
patchesInOrder.map(async
|
|
571
|
+
patchesInOrder.map(async patchPath => ({
|
|
566
572
|
patchPath,
|
|
567
|
-
size: (await stat(patchPath)).size,
|
|
573
|
+
size: (await fs.stat(patchPath)).size,
|
|
568
574
|
})),
|
|
569
575
|
);
|
|
570
|
-
const nonEmptyPatches = patchStats.filter(
|
|
576
|
+
const nonEmptyPatches = patchStats.filter(patch => patch.size > 0).map(patch => patch.patchPath);
|
|
571
577
|
if (nonEmptyPatches.length === 0) {
|
|
572
578
|
patchesApplied = true;
|
|
573
579
|
} else {
|
|
574
580
|
const patchTexts = await Promise.all(
|
|
575
|
-
nonEmptyPatches.map(async
|
|
581
|
+
nonEmptyPatches.map(async patchPath => Bun.file(patchPath).text()),
|
|
576
582
|
);
|
|
577
|
-
const combinedPatch = patchTexts.map(
|
|
583
|
+
const combinedPatch = patchTexts.map(text => (text.endsWith("\n") ? text : `${text}\n`)).join("");
|
|
578
584
|
if (!combinedPatch.trim()) {
|
|
579
585
|
patchesApplied = true;
|
|
580
586
|
} else {
|
|
581
|
-
const combinedPatchPath = path.join(tmpdir(), `omp-task-combined-${nanoid()}.patch`);
|
|
587
|
+
const combinedPatchPath = path.join(os.tmpdir(), `omp-task-combined-${nanoid()}.patch`);
|
|
582
588
|
try {
|
|
583
589
|
await Bun.write(combinedPatchPath, combinedPatch);
|
|
584
590
|
const checkResult = await $`git apply --check --binary ${combinedPatchPath}`
|
|
@@ -595,7 +601,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
595
601
|
patchesApplied = applyResult.exitCode === 0;
|
|
596
602
|
}
|
|
597
603
|
} finally {
|
|
598
|
-
await rm(combinedPatchPath, { force: true });
|
|
604
|
+
await fs.rm(combinedPatchPath, { force: true });
|
|
599
605
|
}
|
|
600
606
|
}
|
|
601
607
|
}
|
|
@@ -608,18 +614,18 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
608
614
|
"<system-notification>Patches were not applied and must be handled manually.</system-notification>";
|
|
609
615
|
const patchList =
|
|
610
616
|
patchPaths.length > 0
|
|
611
|
-
? `\n\nPatch artifacts:\n${patchPaths.map(
|
|
617
|
+
? `\n\nPatch artifacts:\n${patchPaths.map(patch => `- ${patch}`).join("\n")}`
|
|
612
618
|
: "";
|
|
613
619
|
patchApplySummary = `\n\n${notification}${patchList}`;
|
|
614
620
|
}
|
|
615
621
|
}
|
|
616
622
|
|
|
617
623
|
// Build final output - match plugin format
|
|
618
|
-
const successCount = results.filter(
|
|
619
|
-
const cancelledCount = results.filter(
|
|
624
|
+
const successCount = results.filter(r => r.exitCode === 0).length;
|
|
625
|
+
const cancelledCount = results.filter(r => r.aborted).length;
|
|
620
626
|
const totalDuration = Date.now() - startTime;
|
|
621
627
|
|
|
622
|
-
const summaries = results.map(
|
|
628
|
+
const summaries = results.map(r => {
|
|
623
629
|
const status = r.aborted ? "cancelled" : r.exitCode === 0 ? "completed" : `failed (exit ${r.exitCode})`;
|
|
624
630
|
const output = r.output.trim() || r.stderr.trim() || "(no output)";
|
|
625
631
|
const preview = output.split("\n").slice(0, 5).join("\n");
|
|
@@ -629,10 +635,10 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
629
635
|
return `[${r.agent}] ${status}${meta} ${r.id}\n${preview}`;
|
|
630
636
|
});
|
|
631
637
|
|
|
632
|
-
const outputIds = results.filter(
|
|
638
|
+
const outputIds = results.filter(r => !r.aborted || r.output.trim()).map(r => r.id);
|
|
633
639
|
const outputHint =
|
|
634
640
|
outputIds.length > 0
|
|
635
|
-
? `\n\nUse read with agent:// for full logs: ${outputIds.map(
|
|
641
|
+
? `\n\nUse read with agent:// for full logs: ${outputIds.map(id => `agent://${id}`).join(", ")}`
|
|
636
642
|
: "";
|
|
637
643
|
const schemaNote = schemaOverridden
|
|
638
644
|
? `\n\nNote: Agent '${agentName}' has a fixed output schema; your 'output' parameter was ignored.\nRequired schema: ${JSON.stringify(agent.output)}`
|
|
@@ -646,7 +652,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
|
|
|
646
652
|
const shouldCleanupTempArtifacts =
|
|
647
653
|
tempArtifactsDir && (!isIsolated || patchesApplied === true || patchesApplied === null);
|
|
648
654
|
if (shouldCleanupTempArtifacts) {
|
|
649
|
-
await rm(tempArtifactsDir, { recursive: true, force: true });
|
|
655
|
+
await fs.rm(tempArtifactsDir, { recursive: true, force: true });
|
|
650
656
|
}
|
|
651
657
|
|
|
652
658
|
return {
|