@oh-my-pi/pi-coding-agent 7.0.0 → 8.0.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 +87 -0
- package/README.md +1 -1
- package/docs/hooks.md +2 -2
- package/docs/sdk.md +1 -1
- package/package.json +10 -10
- 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/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/{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
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal URL router for resolving agent:// and skill:// URLs.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Router for internal URL schemes.
|
|
9
|
+
*
|
|
10
|
+
* Dispatches URLs like `agent://output_id` or `skill://skill-name` to
|
|
11
|
+
* registered protocol handlers.
|
|
12
|
+
*/
|
|
13
|
+
export class InternalUrlRouter {
|
|
14
|
+
private handlers = new Map<string, ProtocolHandler>();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Register a protocol handler.
|
|
18
|
+
* @param handler Handler to register (uses handler.scheme as key)
|
|
19
|
+
*/
|
|
20
|
+
register(handler: ProtocolHandler): void {
|
|
21
|
+
this.handlers.set(handler.scheme, handler);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Check if the router can handle a URL.
|
|
26
|
+
* @param input URL string to check
|
|
27
|
+
*/
|
|
28
|
+
canHandle(input: string): boolean {
|
|
29
|
+
const match = input.match(/^([a-z][a-z0-9+.-]*):\/\//i);
|
|
30
|
+
if (!match) return false;
|
|
31
|
+
const scheme = match[1].toLowerCase();
|
|
32
|
+
return this.handlers.has(scheme);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Resolve an internal URL to its content.
|
|
37
|
+
* @param input URL string (e.g., "agent://reviewer_0", "skill://notion-pages")
|
|
38
|
+
* @throws Error if scheme is not registered or resolution fails
|
|
39
|
+
*/
|
|
40
|
+
async resolve(input: string): Promise<InternalResource> {
|
|
41
|
+
let parsed: URL;
|
|
42
|
+
try {
|
|
43
|
+
parsed = new URL(input);
|
|
44
|
+
} catch {
|
|
45
|
+
throw new Error(`Invalid URL: ${input}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const hostMatch = input.match(/^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i);
|
|
49
|
+
let rawHost = hostMatch ? hostMatch[2] : parsed.hostname;
|
|
50
|
+
try {
|
|
51
|
+
rawHost = decodeURIComponent(rawHost);
|
|
52
|
+
} catch {
|
|
53
|
+
// Leave rawHost as-is if decoding fails.
|
|
54
|
+
}
|
|
55
|
+
(parsed as InternalUrl).rawHost = rawHost;
|
|
56
|
+
|
|
57
|
+
const scheme = parsed.protocol.replace(/:$/, "").toLowerCase();
|
|
58
|
+
const handler = this.handlers.get(scheme);
|
|
59
|
+
|
|
60
|
+
if (!handler) {
|
|
61
|
+
const available = Array.from(this.handlers.keys())
|
|
62
|
+
.map((s) => `${s}://`)
|
|
63
|
+
.join(", ");
|
|
64
|
+
throw new Error(`Unknown protocol: ${scheme}://\nSupported: ${available || "none"}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return handler.resolve(parsed as InternalUrl);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol handler for rule:// URLs.
|
|
3
|
+
*
|
|
4
|
+
* Resolves rule names to their content files.
|
|
5
|
+
*
|
|
6
|
+
* URL forms:
|
|
7
|
+
* - rule://<name> - Reads rule content
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Rule } from "$c/capability/rule";
|
|
11
|
+
import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
|
|
12
|
+
|
|
13
|
+
export interface RuleProtocolOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Returns the currently loaded rules.
|
|
16
|
+
*/
|
|
17
|
+
getRules: () => readonly Rule[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Handler for rule:// URLs.
|
|
22
|
+
*
|
|
23
|
+
* Resolves rule names to their content.
|
|
24
|
+
*/
|
|
25
|
+
export class RuleProtocolHandler implements ProtocolHandler {
|
|
26
|
+
readonly scheme = "rule";
|
|
27
|
+
|
|
28
|
+
constructor(private readonly options: RuleProtocolOptions) {}
|
|
29
|
+
|
|
30
|
+
async resolve(url: InternalUrl): Promise<InternalResource> {
|
|
31
|
+
const rules = this.options.getRules();
|
|
32
|
+
|
|
33
|
+
// Extract rule name from host
|
|
34
|
+
const ruleName = url.rawHost || url.hostname;
|
|
35
|
+
if (!ruleName) {
|
|
36
|
+
throw new Error("rule:// URL requires a rule name: rule://<name>");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Find the rule
|
|
40
|
+
const rule = rules.find((r) => r.name === ruleName);
|
|
41
|
+
if (!rule) {
|
|
42
|
+
const available = rules.map((r) => r.name);
|
|
43
|
+
const availableStr = available.length > 0 ? available.join(", ") : "none";
|
|
44
|
+
throw new Error(`Unknown rule: ${ruleName}\nAvailable: ${availableStr}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
url: url.href,
|
|
49
|
+
content: rule.content,
|
|
50
|
+
contentType: "text/markdown",
|
|
51
|
+
size: Buffer.byteLength(rule.content, "utf-8"),
|
|
52
|
+
sourcePath: rule.path,
|
|
53
|
+
notes: [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol handler for skill:// URLs.
|
|
3
|
+
*
|
|
4
|
+
* Resolves skill names to their SKILL.md files or relative paths within skill directories.
|
|
5
|
+
*
|
|
6
|
+
* URL forms:
|
|
7
|
+
* - skill://<name> - Reads SKILL.md
|
|
8
|
+
* - skill://<name>/<path> - Reads relative path within skill's baseDir
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
import type { Skill } from "$c/extensibility/skills";
|
|
13
|
+
import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
|
|
14
|
+
|
|
15
|
+
export interface SkillProtocolOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Returns the currently loaded skills.
|
|
18
|
+
*/
|
|
19
|
+
getSkills: () => readonly Skill[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get content type based on file extension.
|
|
24
|
+
*/
|
|
25
|
+
function getContentType(filePath: string): InternalResource["contentType"] {
|
|
26
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
27
|
+
if (ext === ".md") return "text/markdown";
|
|
28
|
+
return "text/plain";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validate that a path is safe (no traversal, no absolute paths).
|
|
33
|
+
*/
|
|
34
|
+
function validateRelativePath(relativePath: string): void {
|
|
35
|
+
if (path.isAbsolute(relativePath)) {
|
|
36
|
+
throw new Error("Absolute paths are not allowed in skill:// URLs");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const normalized = path.normalize(relativePath);
|
|
40
|
+
if (normalized.startsWith("..") || normalized.includes("/../") || normalized.includes("/..")) {
|
|
41
|
+
throw new Error("Path traversal (..) is not allowed in skill:// URLs");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Handler for skill:// URLs.
|
|
47
|
+
*
|
|
48
|
+
* Resolves skill names to their content files.
|
|
49
|
+
*/
|
|
50
|
+
export class SkillProtocolHandler implements ProtocolHandler {
|
|
51
|
+
readonly scheme = "skill";
|
|
52
|
+
|
|
53
|
+
constructor(private readonly options: SkillProtocolOptions) {}
|
|
54
|
+
|
|
55
|
+
async resolve(url: InternalUrl): Promise<InternalResource> {
|
|
56
|
+
const skills = this.options.getSkills();
|
|
57
|
+
|
|
58
|
+
// Extract skill name from host
|
|
59
|
+
const skillName = url.rawHost || url.hostname;
|
|
60
|
+
if (!skillName) {
|
|
61
|
+
throw new Error("skill:// URL requires a skill name: skill://<name>");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Find the skill
|
|
65
|
+
const skill = skills.find((s) => s.name === skillName);
|
|
66
|
+
if (!skill) {
|
|
67
|
+
const available = skills.map((s) => s.name);
|
|
68
|
+
const availableStr = available.length > 0 ? available.join(", ") : "none";
|
|
69
|
+
throw new Error(`Unknown skill: ${skillName}\nAvailable: ${availableStr}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Determine the file to read
|
|
73
|
+
let targetPath: string;
|
|
74
|
+
const urlPath = url.pathname;
|
|
75
|
+
const hasRelativePath = urlPath && urlPath !== "/" && urlPath !== "";
|
|
76
|
+
|
|
77
|
+
if (hasRelativePath) {
|
|
78
|
+
// Read relative path within skill's baseDir
|
|
79
|
+
const relativePath = decodeURIComponent(urlPath.slice(1)); // Remove leading /
|
|
80
|
+
validateRelativePath(relativePath);
|
|
81
|
+
targetPath = path.join(skill.baseDir, relativePath);
|
|
82
|
+
|
|
83
|
+
// Verify the resolved path is still within baseDir
|
|
84
|
+
const resolvedPath = path.resolve(targetPath);
|
|
85
|
+
const resolvedBaseDir = path.resolve(skill.baseDir);
|
|
86
|
+
if (!resolvedPath.startsWith(resolvedBaseDir + path.sep) && resolvedPath !== resolvedBaseDir) {
|
|
87
|
+
throw new Error("Path traversal is not allowed");
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
// Read SKILL.md
|
|
91
|
+
targetPath = skill.filePath;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Read the file
|
|
95
|
+
const file = Bun.file(targetPath);
|
|
96
|
+
if (!(await file.exists())) {
|
|
97
|
+
throw new Error(`File not found: ${targetPath}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const content = await file.text();
|
|
101
|
+
const contentType = getContentType(targetPath);
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
url: url.href,
|
|
105
|
+
content,
|
|
106
|
+
contentType,
|
|
107
|
+
size: Buffer.byteLength(content, "utf-8"),
|
|
108
|
+
sourcePath: targetPath,
|
|
109
|
+
notes: [],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the internal URL routing system.
|
|
3
|
+
*
|
|
4
|
+
* Internal URLs (agent://, skill://) are resolved by tools like fetch and read,
|
|
5
|
+
* providing access to agent outputs and skill files without exposing filesystem paths.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Resolved internal resource returned by protocol handlers.
|
|
10
|
+
*/
|
|
11
|
+
export interface InternalResource {
|
|
12
|
+
/** Canonical URL that was resolved */
|
|
13
|
+
url: string;
|
|
14
|
+
/** Resolved text content */
|
|
15
|
+
content: string;
|
|
16
|
+
/** MIME type: text/markdown, application/json, or text/plain */
|
|
17
|
+
contentType: "text/markdown" | "application/json" | "text/plain";
|
|
18
|
+
/** Content size in bytes */
|
|
19
|
+
size?: number;
|
|
20
|
+
/** Underlying filesystem path (for debugging, not exposed to agent) */
|
|
21
|
+
sourcePath?: string;
|
|
22
|
+
/** Additional notes about resolution */
|
|
23
|
+
notes?: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Parsed internal URL with preserved host casing.
|
|
28
|
+
*/
|
|
29
|
+
export interface InternalUrl extends URL {
|
|
30
|
+
/**
|
|
31
|
+
* Raw host segment extracted from input, preserving case.
|
|
32
|
+
*/
|
|
33
|
+
rawHost: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Handler for a specific internal URL scheme (e.g., agent://, skill://).
|
|
38
|
+
*/
|
|
39
|
+
export interface ProtocolHandler {
|
|
40
|
+
/** The scheme this handler processes (without trailing ://) */
|
|
41
|
+
readonly scheme: string;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve an internal URL to its content.
|
|
44
|
+
* @param url Parsed URL object
|
|
45
|
+
* @throws Error with user-friendly message if resolution fails
|
|
46
|
+
*/
|
|
47
|
+
resolve(url: InternalUrl): Promise<InternalResource>;
|
|
48
|
+
}
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
type KernelExecuteResult,
|
|
7
7
|
type PreludeHelper,
|
|
8
8
|
PythonKernel,
|
|
9
|
-
} from "
|
|
10
|
-
import { OutputSink } from "
|
|
9
|
+
} from "$c/ipy/kernel";
|
|
10
|
+
import { OutputSink } from "$c/session/streaming-output";
|
|
11
11
|
export type PythonKernelMode = "session" | "per-call";
|
|
12
12
|
|
|
13
13
|
export interface PythonExecutorOptions {
|
|
@@ -29,6 +29,11 @@ export interface PythonExecutorOptions {
|
|
|
29
29
|
useSharedGateway?: boolean;
|
|
30
30
|
/** Session file path for accessing task outputs */
|
|
31
31
|
sessionFile?: string;
|
|
32
|
+
/** Artifacts directory for $ARTIFACTS env var and artifact storage */
|
|
33
|
+
artifactsDir?: string;
|
|
34
|
+
/** Artifact path/id for full output storage */
|
|
35
|
+
artifactPath?: string;
|
|
36
|
+
artifactId?: string;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
export interface PythonKernelExecutor {
|
|
@@ -44,8 +49,16 @@ export interface PythonResult {
|
|
|
44
49
|
cancelled: boolean;
|
|
45
50
|
/** Whether the output was truncated */
|
|
46
51
|
truncated: boolean;
|
|
47
|
-
/**
|
|
48
|
-
|
|
52
|
+
/** Artifact ID if full output was saved to artifact storage */
|
|
53
|
+
artifactId?: string;
|
|
54
|
+
/** Total number of lines in the output stream */
|
|
55
|
+
totalLines: number;
|
|
56
|
+
/** Total number of bytes in the output stream */
|
|
57
|
+
totalBytes: number;
|
|
58
|
+
/** Number of lines included in the output text */
|
|
59
|
+
outputLines: number;
|
|
60
|
+
/** Number of bytes included in the output text */
|
|
61
|
+
outputBytes: number;
|
|
49
62
|
/** Rich display outputs captured from display_data/execute_result */
|
|
50
63
|
displayOutputs: KernelDisplayOutput[];
|
|
51
64
|
/** Whether stdin was requested */
|
|
@@ -124,8 +137,15 @@ async function createKernelSession(
|
|
|
124
137
|
cwd: string,
|
|
125
138
|
useSharedGateway?: boolean,
|
|
126
139
|
sessionFile?: string,
|
|
140
|
+
artifactsDir?: string,
|
|
127
141
|
): Promise<KernelSession> {
|
|
128
|
-
const env
|
|
142
|
+
const env: Record<string, string> | undefined =
|
|
143
|
+
sessionFile || artifactsDir
|
|
144
|
+
? {
|
|
145
|
+
...(sessionFile ? { OMP_SESSION_FILE: sessionFile } : {}),
|
|
146
|
+
...(artifactsDir ? { ARTIFACTS: artifactsDir } : {}),
|
|
147
|
+
}
|
|
148
|
+
: undefined;
|
|
129
149
|
const kernel = await PythonKernel.start({ cwd, useSharedGateway, env });
|
|
130
150
|
const session: KernelSession = {
|
|
131
151
|
id: sessionId,
|
|
@@ -152,6 +172,7 @@ async function restartKernelSession(
|
|
|
152
172
|
cwd: string,
|
|
153
173
|
useSharedGateway?: boolean,
|
|
154
174
|
sessionFile?: string,
|
|
175
|
+
artifactsDir?: string,
|
|
155
176
|
): Promise<void> {
|
|
156
177
|
session.restartCount += 1;
|
|
157
178
|
if (session.restartCount > 1) {
|
|
@@ -162,7 +183,13 @@ async function restartKernelSession(
|
|
|
162
183
|
} catch (err) {
|
|
163
184
|
logger.warn("Failed to shutdown crashed kernel", { error: err instanceof Error ? err.message : String(err) });
|
|
164
185
|
}
|
|
165
|
-
const env
|
|
186
|
+
const env: Record<string, string> | undefined =
|
|
187
|
+
sessionFile || artifactsDir
|
|
188
|
+
? {
|
|
189
|
+
...(sessionFile ? { OMP_SESSION_FILE: sessionFile } : {}),
|
|
190
|
+
...(artifactsDir ? { ARTIFACTS: artifactsDir } : {}),
|
|
191
|
+
}
|
|
192
|
+
: undefined;
|
|
166
193
|
const kernel = await PythonKernel.start({ cwd, useSharedGateway, env });
|
|
167
194
|
session.kernel = kernel;
|
|
168
195
|
session.dead = false;
|
|
@@ -187,17 +214,18 @@ async function withKernelSession<T>(
|
|
|
187
214
|
handler: (kernel: PythonKernel) => Promise<T>,
|
|
188
215
|
useSharedGateway?: boolean,
|
|
189
216
|
sessionFile?: string,
|
|
217
|
+
artifactsDir?: string,
|
|
190
218
|
): Promise<T> {
|
|
191
219
|
let session = kernelSessions.get(sessionId);
|
|
192
220
|
if (!session) {
|
|
193
|
-
session = await createKernelSession(sessionId, cwd, useSharedGateway, sessionFile);
|
|
221
|
+
session = await createKernelSession(sessionId, cwd, useSharedGateway, sessionFile, artifactsDir);
|
|
194
222
|
kernelSessions.set(sessionId, session);
|
|
195
223
|
}
|
|
196
224
|
|
|
197
225
|
const run = async (): Promise<T> => {
|
|
198
226
|
session!.lastUsedAt = Date.now();
|
|
199
227
|
if (session!.dead || !session!.kernel.isAlive()) {
|
|
200
|
-
await restartKernelSession(session!, cwd, useSharedGateway, sessionFile);
|
|
228
|
+
await restartKernelSession(session!, cwd, useSharedGateway, sessionFile, artifactsDir);
|
|
201
229
|
}
|
|
202
230
|
try {
|
|
203
231
|
const result = await handler(session!.kernel);
|
|
@@ -207,7 +235,7 @@ async function withKernelSession<T>(
|
|
|
207
235
|
if (!session!.dead && session!.kernel.isAlive()) {
|
|
208
236
|
throw err;
|
|
209
237
|
}
|
|
210
|
-
await restartKernelSession(session!, cwd, useSharedGateway, sessionFile);
|
|
238
|
+
await restartKernelSession(session!, cwd, useSharedGateway, sessionFile, artifactsDir);
|
|
211
239
|
const result = await handler(session!.kernel);
|
|
212
240
|
session!.restartCount = 0;
|
|
213
241
|
return result;
|
|
@@ -227,7 +255,11 @@ async function executeWithKernel(
|
|
|
227
255
|
code: string,
|
|
228
256
|
options: PythonExecutorOptions | undefined,
|
|
229
257
|
): Promise<PythonResult> {
|
|
230
|
-
const sink = new OutputSink({
|
|
258
|
+
const sink = new OutputSink({
|
|
259
|
+
onChunk: options?.onChunk,
|
|
260
|
+
artifactPath: options?.artifactPath,
|
|
261
|
+
artifactId: options?.artifactId,
|
|
262
|
+
});
|
|
231
263
|
const displayOutputs: KernelDisplayOutput[] = [];
|
|
232
264
|
|
|
233
265
|
try {
|
|
@@ -291,9 +323,16 @@ export async function executePython(code: string, options?: PythonExecutorOption
|
|
|
291
323
|
const kernelMode = options?.kernelMode ?? "session";
|
|
292
324
|
const useSharedGateway = options?.useSharedGateway;
|
|
293
325
|
const sessionFile = options?.sessionFile;
|
|
326
|
+
const artifactsDir = options?.artifactsDir;
|
|
294
327
|
|
|
295
328
|
if (kernelMode === "per-call") {
|
|
296
|
-
const env
|
|
329
|
+
const env: Record<string, string> | undefined =
|
|
330
|
+
sessionFile || artifactsDir
|
|
331
|
+
? {
|
|
332
|
+
...(sessionFile ? { OMP_SESSION_FILE: sessionFile } : {}),
|
|
333
|
+
...(artifactsDir ? { ARTIFACTS: artifactsDir } : {}),
|
|
334
|
+
}
|
|
335
|
+
: undefined;
|
|
297
336
|
const kernel = await PythonKernel.start({ cwd, useSharedGateway, env });
|
|
298
337
|
try {
|
|
299
338
|
return await executeWithKernel(kernel, code, options);
|
|
@@ -315,5 +354,6 @@ export async function executePython(code: string, options?: PythonExecutorOption
|
|
|
315
354
|
async (kernel) => executeWithKernel(kernel, code, options),
|
|
316
355
|
useSharedGateway,
|
|
317
356
|
sessionFile,
|
|
357
|
+
artifactsDir,
|
|
318
358
|
);
|
|
319
359
|
}
|