@oh-my-pi/pi-coding-agent 17.2.3 → 17.2.5
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 +92 -0
- package/dist/{CHANGELOG-c5hpqt9r.md → CHANGELOG-q2w43aw3.md} +92 -0
- package/dist/cli.js +3979 -3548
- package/dist/{template-8vdv6xb4.js → template-c2hyaytt.js} +8 -26
- package/dist/types/advisor/advise-tool.d.ts +6 -0
- package/dist/types/advisor/runtime.d.ts +4 -4
- package/dist/types/capability/mcp.d.ts +9 -0
- package/dist/types/cli/args.d.ts +4 -1
- package/dist/types/cli/browser-relay-cli.d.ts +15 -0
- package/dist/types/cli/command-help.d.ts +99 -0
- package/dist/types/cli/help-extra.d.ts +2 -0
- package/dist/types/cli/models-cli.d.ts +1 -1
- package/dist/types/cli/thinking-levels.d.ts +5 -0
- package/dist/types/cli/update-cli.d.ts +13 -0
- package/dist/types/commands/browser-relay.d.ts +38 -0
- package/dist/types/commands/commit.d.ts +3 -0
- package/dist/types/commands/complete.d.ts +1 -1
- package/dist/types/commands/completions.d.ts +6 -0
- package/dist/types/commands/grep.d.ts +3 -0
- package/dist/types/commands/join.d.ts +4 -0
- package/dist/types/commands/launch-help.d.ts +171 -0
- package/dist/types/commands/launch.d.ts +5 -1
- package/dist/types/commands/models.d.ts +3 -0
- package/dist/types/commands/say.d.ts +10 -0
- package/dist/types/commands/worktree.d.ts +3 -0
- package/dist/types/config/keybindings.d.ts +6 -1
- package/dist/types/config/model-discovery.d.ts +2 -2
- package/dist/types/config/models-config-schema-bundle.d.ts +3 -0
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/config/models-config.d.ts +1 -0
- package/dist/types/config/service-tier.d.ts +2 -0
- package/dist/types/config/settings-schema.d.ts +70 -22
- package/dist/types/cursor-bridge-tools.d.ts +1 -1
- package/dist/types/cursor.d.ts +7 -4
- package/dist/types/discovery/helpers.d.ts +6 -0
- package/dist/types/discovery/omp-extension-roots.d.ts +21 -2
- package/dist/types/edit/index.d.ts +3 -3
- package/dist/types/edit/modes/replace.d.ts +22 -15
- package/dist/types/edit/renderer.d.ts +1 -1
- package/dist/types/eval/py/kernel.d.ts +3 -1
- package/dist/types/eval/py/spawn-options.d.ts +12 -16
- package/dist/types/extensibility/extensions/loader.d.ts +6 -2
- package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +8 -1
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +1 -1
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +2 -0
- package/dist/types/extensibility/plugins/marketplace/registry.d.ts +2 -2
- package/dist/types/launch/broker.d.ts +1 -1
- package/dist/types/launch/client.d.ts +6 -3
- package/dist/types/launch/ensure.d.ts +8 -0
- package/dist/types/launch/paths.d.ts +3 -2
- package/dist/types/launch/protocol.d.ts +2 -2
- package/dist/types/lsp/client.d.ts +2 -0
- package/dist/types/lsp/mux/daemon.d.ts +15 -0
- package/dist/types/lsp/mux/protocol.d.ts +57 -0
- package/dist/types/lsp/mux/server.d.ts +18 -0
- package/dist/types/lsp/types.d.ts +22 -2
- package/dist/types/main.d.ts +2 -0
- package/dist/types/mcp/request-id.d.ts +19 -0
- package/dist/types/mcp/types.d.ts +14 -0
- package/dist/types/memory-backend/index.d.ts +1 -0
- package/dist/types/memory-backend/messages.d.ts +15 -0
- package/dist/types/mnemopi/embed-client.d.ts +1 -1
- package/dist/types/mnemopi/state.d.ts +0 -23
- package/dist/types/modes/components/assistant-message.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +2 -1
- package/dist/types/modes/components/model-browser.d.ts +7 -5
- package/dist/types/modes/components/model-picker.d.ts +9 -3
- package/dist/types/modes/components/read-tool-group.d.ts +11 -0
- package/dist/types/modes/components/stripped-tool-calls-placeholder.d.ts +12 -0
- package/dist/types/modes/components/tool-execution.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/types.d.ts +2 -1
- package/dist/types/modes/workflow.d.ts +2 -1
- package/dist/types/registry/agent-lifecycle.d.ts +14 -5
- package/dist/types/registry/agent-registry.d.ts +4 -3
- package/dist/types/sdk.d.ts +4 -2
- package/dist/types/secrets/index.d.ts +7 -9
- package/dist/types/session/agent-session-types.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +6 -1
- package/dist/types/session/indexed-session-storage.d.ts +1 -0
- package/dist/types/session/model-controls.d.ts +0 -1
- package/dist/types/session/session-advisors.d.ts +8 -1
- package/dist/types/session/session-context.d.ts +2 -1
- package/dist/types/session/session-maintenance.d.ts +2 -0
- package/dist/types/session/session-manager.d.ts +16 -5
- package/dist/types/session/session-stats.d.ts +10 -0
- package/dist/types/session/session-storage.d.ts +15 -3
- package/dist/types/system-prompt.d.ts +6 -1
- package/dist/types/task/index.d.ts +2 -1
- package/dist/types/task/spawn-policy.d.ts +5 -0
- package/dist/types/thinking.d.ts +1 -7
- package/dist/types/tools/ast-grep.d.ts +1 -1
- package/dist/types/tools/browser/registry.d.ts +2 -1
- package/dist/types/tools/browser/relay/bridge.d.ts +35 -0
- package/dist/types/tools/browser/relay/daemon.d.ts +16 -0
- package/dist/types/tools/browser/relay/kind.d.ts +19 -0
- package/dist/types/tools/browser/relay/protocol.d.ts +97 -0
- package/dist/types/tools/browser/relay/server.d.ts +35 -0
- package/dist/types/tools/browser/render.d.ts +1 -0
- package/dist/types/tools/browser.d.ts +3 -0
- package/dist/types/tools/computer/exposure.d.ts +9 -7
- package/dist/types/tools/computer/protocol.d.ts +70 -17
- package/dist/types/tools/computer/supervisor.d.ts +23 -10
- package/dist/types/tools/computer/worker-entry.d.ts +1 -0
- package/dist/types/tools/computer/worker.d.ts +42 -7
- package/dist/types/tools/computer-renderer.d.ts +7 -5
- package/dist/types/tools/computer.d.ts +25 -44
- package/dist/types/tools/context.d.ts +3 -0
- package/dist/types/tools/default-renderer.d.ts +3 -0
- package/dist/types/tools/glob.d.ts +1 -1
- package/dist/types/tools/grep.d.ts +1 -1
- package/dist/types/tools/render-utils.d.ts +2 -0
- package/dist/types/tools/{browser/run-cancellation.d.ts → run-scope.d.ts} +8 -8
- package/dist/types/tools/tool-timeouts.d.ts +5 -0
- package/dist/types/tools/xdev.d.ts +8 -0
- package/dist/types/utils/clipboard.d.ts +2 -2
- package/dist/types/web/kagi.d.ts +1 -0
- package/dist/types/web/search/index.d.ts +1 -1
- package/dist/types/web/search/providers/anthropic.d.ts +1 -0
- package/dist/types/web/search/providers/base.d.ts +2 -0
- package/dist/types/web/search/providers/brave.d.ts +1 -0
- package/dist/types/web/search/providers/browser-page.d.ts +1 -0
- package/dist/types/web/search/providers/codex.d.ts +1 -0
- package/dist/types/web/search/providers/exa.d.ts +1 -0
- package/dist/types/web/search/providers/firecrawl.d.ts +1 -0
- package/dist/types/web/search/providers/gemini.d.ts +1 -0
- package/dist/types/web/search/providers/jina.d.ts +1 -0
- package/dist/types/web/search/providers/kagi.d.ts +1 -0
- package/dist/types/web/search/providers/kimi.d.ts +1 -0
- package/dist/types/web/search/providers/parallel.d.ts +1 -0
- package/dist/types/web/search/providers/perplexity.d.ts +1 -0
- package/dist/types/web/search/providers/searxng.d.ts +1 -0
- package/dist/types/web/search/providers/tavily.d.ts +1 -0
- package/dist/types/web/search/providers/tinyfish.d.ts +1 -0
- package/dist/types/web/search/providers/utils.d.ts +6 -9
- package/dist/types/web/search/providers/zai.d.ts +1 -0
- package/dist/types/web/search/types.d.ts +4 -0
- package/package.json +12 -12
- package/scripts/legacy-pi-virtual-module.ts +12 -2
- package/src/advisor/advise-tool.ts +18 -0
- package/src/advisor/runtime.ts +6 -6
- package/src/capability/mcp.ts +7 -0
- package/src/cli/args.ts +7 -87
- package/src/cli/browser-relay-cli.ts +119 -0
- package/src/cli/command-help.ts +103 -0
- package/src/cli/completion-gen.ts +5 -5
- package/src/cli/flag-tables.ts +9 -0
- package/src/cli/help-extra.ts +89 -0
- package/src/cli/models-cli.ts +13 -16
- package/src/cli/setup-cli.ts +13 -21
- package/src/cli/thinking-levels.ts +7 -0
- package/src/cli/update-cli.ts +26 -7
- package/src/cli-commands.ts +170 -33
- package/src/cli.ts +17 -5
- package/src/collab/host.ts +1 -1
- package/src/commands/acp.ts +3 -1
- package/src/commands/agents.ts +3 -2
- package/src/commands/auth-broker.ts +3 -2
- package/src/commands/auth-gateway.ts +3 -2
- package/src/commands/bench.ts +2 -3
- package/src/commands/browser-relay.ts +53 -0
- package/src/commands/cleanse.ts +2 -2
- package/src/commands/commit.ts +3 -2
- package/src/commands/complete.ts +2 -1
- package/src/commands/completions.ts +3 -2
- package/src/commands/config.ts +3 -2
- package/src/commands/dry-balance.ts +2 -2
- package/src/commands/gallery.ts +3 -2
- package/src/commands/gc.ts +3 -2
- package/src/commands/grep.ts +3 -2
- package/src/commands/grievances.ts +3 -2
- package/src/commands/install.ts +2 -2
- package/src/commands/join.ts +3 -2
- package/src/commands/launch-help.ts +116 -0
- package/src/commands/launch.ts +7 -191
- package/src/commands/models.ts +3 -2
- package/src/commands/plugin.ts +3 -2
- package/src/commands/read.ts +3 -2
- package/src/commands/say.ts +3 -2
- package/src/commands/setup.ts +3 -2
- package/src/commands/shell.ts +3 -2
- package/src/commands/ssh.ts +3 -2
- package/src/commands/stats.ts +3 -2
- package/src/commands/tiny-models.ts +2 -2
- package/src/commands/token.ts +2 -2
- package/src/commands/ttsr.ts +2 -2
- package/src/commands/update.ts +3 -2
- package/src/commands/usage.ts +3 -2
- package/src/commands/web-search.ts +3 -2
- package/src/commands/worktree.ts +3 -2
- package/src/config/keybindings.ts +19 -9
- package/src/config/mcp-schema.json +5 -0
- package/src/config/model-discovery.ts +30 -13
- package/src/config/model-registry.ts +16 -6
- package/src/config/models-config-schema-bundle.ts +9 -0
- package/src/config/resolve-config-value.ts +2 -1
- package/src/config/service-tier.ts +5 -0
- package/src/config/settings-schema.ts +73 -21
- package/src/cursor-bridge-tools.ts +1 -1
- package/src/cursor.ts +10 -14
- package/src/discovery/builtin.ts +10 -0
- package/src/discovery/helpers.ts +10 -0
- package/src/discovery/mcp-json.ts +11 -1
- package/src/discovery/omp-extension-roots.ts +79 -20
- package/src/discovery/omp-plugins.ts +10 -1
- package/src/edit/diff.ts +17 -8
- package/src/edit/index.ts +20 -7
- package/src/edit/modes/replace.ts +93 -40
- package/src/edit/renderer.ts +1 -1
- package/src/edit/streaming.ts +14 -17
- package/src/eval/py/kernel.ts +2 -1
- package/src/eval/py/spawn-options.ts +24 -29
- package/src/export/html/template.js +8 -26
- package/src/extensibility/extensions/loader.ts +66 -28
- package/src/extensibility/extensions/wrapper.ts +1 -0
- package/src/extensibility/legacy-pi-ai-shim.ts +22 -1
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +7 -6
- package/src/extensibility/plugins/legacy-pi-compat.ts +124 -57
- package/src/extensibility/plugins/marketplace/registry.ts +4 -8
- package/src/extensibility/skills.ts +11 -0
- package/src/extensibility/utils.ts +10 -2
- package/src/launch/broker.ts +1 -1
- package/src/launch/client.ts +32 -13
- package/src/launch/ensure.ts +73 -0
- package/src/launch/paths.ts +3 -6
- package/src/launch/protocol.ts +2 -2
- package/src/lsp/client.ts +23 -2
- package/src/lsp/index.ts +8 -0
- package/src/lsp/mux/daemon.ts +348 -0
- package/src/lsp/mux/protocol.ts +96 -0
- package/src/lsp/mux/server.ts +797 -0
- package/src/lsp/types.ts +28 -2
- package/src/main.ts +31 -24
- package/src/mcp/config.ts +1 -0
- package/src/mcp/oauth-flow.ts +11 -1
- package/src/mcp/request-id.ts +24 -0
- package/src/mcp/transports/http.ts +4 -2
- package/src/mcp/transports/sse.ts +4 -2
- package/src/mcp/transports/stdio.ts +4 -2
- package/src/mcp/types.ts +15 -0
- package/src/memory-backend/index.ts +1 -0
- package/src/memory-backend/messages.ts +19 -0
- package/src/mnemopi/embed-client.ts +49 -2
- package/src/mnemopi/state.ts +57 -23
- package/src/modes/components/agent-hub.ts +1 -1
- package/src/modes/components/assistant-message.ts +11 -0
- package/src/modes/components/chat-transcript-builder.ts +4 -0
- package/src/modes/components/custom-editor.ts +10 -1
- package/src/modes/components/model-browser.ts +25 -17
- package/src/modes/components/model-picker.ts +10 -6
- package/src/modes/components/read-tool-group.ts +36 -0
- package/src/modes/components/status-line/component.ts +1 -1
- package/src/modes/components/stripped-tool-calls-placeholder.ts +35 -0
- package/src/modes/components/tool-execution.ts +85 -20
- package/src/modes/components/tree-selector.ts +46 -48
- package/src/modes/controllers/command-controller.ts +2 -2
- package/src/modes/controllers/event-controller.ts +199 -10
- package/src/modes/controllers/input-controller.ts +39 -1
- package/src/modes/controllers/mcp-command-controller.ts +11 -5
- package/src/modes/controllers/selector-controller.ts +47 -6
- package/src/modes/interactive-mode.ts +2 -0
- package/src/modes/types.ts +6 -1
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/interactive-context-helpers.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +6 -10
- package/src/modes/workflow.ts +8 -2
- package/src/prompts/agents/init.md +1 -1
- package/src/prompts/system/plan-mode-active.md +2 -2
- package/src/prompts/system/system-prompt.md +26 -52
- package/src/prompts/system/workflow-notice.md +3 -3
- package/src/prompts/tools/ast-grep.md +1 -1
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/browser.md +1 -0
- package/src/prompts/tools/computer.md +21 -21
- package/src/prompts/tools/glob.md +1 -1
- package/src/prompts/tools/grep.md +1 -1
- package/src/prompts/tools/replace.md +5 -4
- package/src/prompts/tools/task.md +4 -4
- package/src/registry/agent-lifecycle.ts +36 -11
- package/src/registry/agent-registry.ts +12 -5
- package/src/sdk.ts +102 -35
- package/src/secrets/index.ts +16 -18
- package/src/session/agent-session-types.ts +3 -1
- package/src/session/agent-session.ts +23 -2
- package/src/session/agent-storage.ts +6 -4
- package/src/session/history-storage.ts +4 -2
- package/src/session/indexed-session-storage.ts +9 -0
- package/src/session/messages.ts +31 -7
- package/src/session/model-controls.ts +0 -1
- package/src/session/prewalk.ts +24 -2
- package/src/session/session-advisors.ts +21 -3
- package/src/session/session-context.ts +16 -12
- package/src/session/session-dump-format.ts +1 -1
- package/src/session/session-maintenance.ts +41 -4
- package/src/session/session-manager.ts +181 -94
- package/src/session/session-paths.ts +118 -55
- package/src/session/session-stats.ts +48 -3
- package/src/session/session-storage.ts +30 -22
- package/src/session/session-tools.ts +25 -23
- package/src/session/stream-guards.ts +1 -1
- package/src/slash-commands/builtin-registry.ts +29 -26
- package/src/system-prompt.ts +14 -4
- package/src/task/executor.ts +8 -1
- package/src/task/index.ts +23 -8
- package/src/task/spawn-policy.ts +14 -0
- package/src/thinking.ts +2 -8
- package/src/tiny/text.ts +12 -0
- package/src/tools/ast-grep.ts +10 -4
- package/src/tools/browser/cmux/cmux-tab.ts +5 -10
- package/src/tools/browser/cmux/rpc.ts +2 -8
- package/src/tools/browser/registry.ts +53 -2
- package/src/tools/browser/relay/bridge.ts +945 -0
- package/src/tools/browser/relay/daemon.ts +117 -0
- package/src/tools/browser/relay/extension-assets/background.js.txt +242 -0
- package/src/tools/browser/relay/extension-assets/manifest.json.txt +14 -0
- package/src/tools/browser/relay/extension-assets/options.html.txt +53 -0
- package/src/tools/browser/relay/extension-assets/options.js.txt +23 -0
- package/src/tools/browser/relay/kind.ts +41 -0
- package/src/tools/browser/relay/protocol.ts +54 -0
- package/src/tools/browser/relay/server.ts +141 -0
- package/src/tools/browser/render.ts +4 -1
- package/src/tools/browser/shared-daemon.ts +7 -58
- package/src/tools/browser/tab-supervisor.ts +5 -4
- package/src/tools/browser/tab-worker.ts +33 -12
- package/src/tools/browser.ts +26 -1
- package/src/tools/computer/exposure.ts +11 -35
- package/src/tools/computer/protocol.ts +51 -10
- package/src/tools/computer/supervisor.ts +227 -124
- package/src/tools/computer/worker-entry.ts +11 -6
- package/src/tools/computer/worker.ts +695 -81
- package/src/tools/computer-renderer.ts +104 -65
- package/src/tools/computer.ts +134 -428
- package/src/tools/context.ts +3 -0
- package/src/tools/default-renderer.ts +19 -4
- package/src/tools/glob.ts +9 -2
- package/src/tools/grep.ts +12 -6
- package/src/tools/index.ts +10 -6
- package/src/tools/inspect-image.ts +32 -6
- package/src/tools/render-utils.ts +2 -0
- package/src/tools/{browser/run-cancellation.ts → run-scope.ts} +11 -11
- package/src/tools/tool-timeouts.ts +1 -0
- package/src/tools/xdev.ts +29 -2
- package/src/utils/clipboard.ts +40 -14
- package/src/utils/command-args.ts +26 -28
- package/src/utils/tool-choice.ts +0 -13
- package/src/web/kagi.ts +2 -1
- package/src/web/search/index.ts +18 -2
- package/src/web/search/providers/anthropic.ts +7 -2
- package/src/web/search/providers/base.ts +2 -0
- package/src/web/search/providers/brave.ts +3 -1
- package/src/web/search/providers/browser-page.ts +6 -4
- package/src/web/search/providers/codex.ts +4 -1
- package/src/web/search/providers/duckduckgo.ts +2 -1
- package/src/web/search/providers/ecosia.ts +2 -1
- package/src/web/search/providers/exa.ts +4 -2
- package/src/web/search/providers/firecrawl.ts +3 -1
- package/src/web/search/providers/gemini.ts +8 -2
- package/src/web/search/providers/google.ts +2 -1
- package/src/web/search/providers/jina.ts +12 -2
- package/src/web/search/providers/kagi.ts +3 -0
- package/src/web/search/providers/kimi.ts +5 -1
- package/src/web/search/providers/mojeek.ts +2 -1
- package/src/web/search/providers/parallel.ts +5 -1
- package/src/web/search/providers/perplexity.ts +6 -3
- package/src/web/search/providers/public.ts +1 -1
- package/src/web/search/providers/searxng.ts +11 -5
- package/src/web/search/providers/startpage.ts +10 -4
- package/src/web/search/providers/synthetic.ts +11 -5
- package/src/web/search/providers/tavily.ts +3 -1
- package/src/web/search/providers/tinyfish.ts +3 -1
- package/src/web/search/providers/utils.ts +12 -10
- package/src/web/search/providers/xai.ts +2 -2
- package/src/web/search/providers/zai.ts +18 -3
- package/src/web/search/types.ts +6 -0
package/src/tools/glob.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { splitMemoryGlobPattern } from "../internal-urls/memory-protocol";
|
|
|
13
13
|
import type { Theme } from "../modes/theme/theme";
|
|
14
14
|
import globDescription from "../prompts/tools/glob.md" with { type: "text" };
|
|
15
15
|
import { type TruncationResult, truncateHead } from "../session/streaming-output";
|
|
16
|
+
import { isScoutSpawnable } from "../task/spawn-policy";
|
|
16
17
|
import { Ellipsis, fileHyperlink, renderFileList, renderStatusLine, renderTreeList, truncateToWidth } from "../tui";
|
|
17
18
|
import type { ToolSession } from ".";
|
|
18
19
|
import { applyListLimit } from "./list-limit";
|
|
@@ -106,7 +107,14 @@ export class GlobTool implements AgentTool<typeof findSchema, GlobToolDetails> {
|
|
|
106
107
|
readonly approval = "read" as const;
|
|
107
108
|
readonly loadMode = "essential";
|
|
108
109
|
readonly label = "Glob";
|
|
109
|
-
|
|
110
|
+
get description(): string {
|
|
111
|
+
return prompt.render(globDescription, {
|
|
112
|
+
scoutAvailable: isScoutSpawnable(
|
|
113
|
+
this.session.settings.get("task.disabledAgents") as string[] | undefined,
|
|
114
|
+
this.session.getSessionSpawns?.() ?? "*",
|
|
115
|
+
),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
110
118
|
readonly parameters = findSchema;
|
|
111
119
|
|
|
112
120
|
readonly examples: readonly ToolExample<typeof findSchema.infer>[] = [
|
|
@@ -138,7 +146,6 @@ export class GlobTool implements AgentTool<typeof findSchema, GlobToolDetails> {
|
|
|
138
146
|
) {
|
|
139
147
|
this.#customOps = options?.operations;
|
|
140
148
|
this.#rootPathAlias = options?.rootPathAlias === true;
|
|
141
|
-
this.description = prompt.render(globDescription);
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
async execute(
|
package/src/tools/grep.ts
CHANGED
|
@@ -22,6 +22,7 @@ import type { InternalResource, ResolveContext } from "../internal-urls/types";
|
|
|
22
22
|
import type { Theme } from "../modes/theme/theme";
|
|
23
23
|
import grepDescription from "../prompts/tools/grep.md" with { type: "text" };
|
|
24
24
|
import { DEFAULT_MAX_COLUMN, type TruncationResult, truncateHead, truncateLine } from "../session/streaming-output";
|
|
25
|
+
import { isScoutSpawnable } from "../task/spawn-policy";
|
|
25
26
|
import {
|
|
26
27
|
Ellipsis,
|
|
27
28
|
fileHyperlink,
|
|
@@ -909,7 +910,17 @@ export class GrepTool implements AgentTool<typeof searchSchema, GrepToolDetails>
|
|
|
909
910
|
readonly label = "Grep";
|
|
910
911
|
readonly loadMode = "discoverable";
|
|
911
912
|
readonly summary = "Grep file contents using ripgrep (fast regex search)";
|
|
912
|
-
|
|
913
|
+
get description(): string {
|
|
914
|
+
const displayMode = resolveFileDisplayMode(this.session);
|
|
915
|
+
return prompt.render(grepDescription, {
|
|
916
|
+
IS_HL_MODE: displayMode.hashLines,
|
|
917
|
+
IS_LINE_NUMBER_MODE: !displayMode.hashLines && displayMode.lineNumbers,
|
|
918
|
+
scoutAvailable: isScoutSpawnable(
|
|
919
|
+
this.session.settings.get("task.disabledAgents") as string[] | undefined,
|
|
920
|
+
this.session.getSessionSpawns?.() ?? "*",
|
|
921
|
+
),
|
|
922
|
+
});
|
|
923
|
+
}
|
|
913
924
|
readonly parameters = searchSchema;
|
|
914
925
|
readonly strict = true;
|
|
915
926
|
|
|
@@ -924,11 +935,6 @@ export class GrepTool implements AgentTool<typeof searchSchema, GrepToolDetails>
|
|
|
924
935
|
this.#contextOverride = context !== undefined ? Math.max(0, Math.floor(context)) : undefined;
|
|
925
936
|
const total = options?.totalMatchLimit;
|
|
926
937
|
this.#totalMatchLimit = total !== undefined ? Math.max(1, Math.floor(total)) : undefined;
|
|
927
|
-
const displayMode = resolveFileDisplayMode(session);
|
|
928
|
-
this.description = prompt.render(grepDescription, {
|
|
929
|
-
IS_HL_MODE: displayMode.hashLines,
|
|
930
|
-
IS_LINE_NUMBER_MODE: !displayMode.hashLines && displayMode.lineNumbers,
|
|
931
|
-
});
|
|
932
938
|
}
|
|
933
939
|
|
|
934
940
|
async execute(
|
package/src/tools/index.ts
CHANGED
|
@@ -667,8 +667,12 @@ export async function createTools(session: ToolSession, toolNames?: string[]): P
|
|
|
667
667
|
// Ordinary sessions use xd:// for discoverable built-ins, custom tools, and
|
|
668
668
|
// MCP tools. Structured children must expose only their host-provided names,
|
|
669
669
|
// so never allocate a registry that later SDK assembly could populate.
|
|
670
|
+
// The transport rides read/write, so a session granted no write tool never
|
|
671
|
+
// allocates xd:// state — its tools are exposed top-level directly instead
|
|
672
|
+
// of auto-granting a write transport the session was denied.
|
|
670
673
|
// Explicitly requested built-ins retain their top-level presentation.
|
|
671
|
-
const xdevEnabled =
|
|
674
|
+
const xdevEnabled =
|
|
675
|
+
!restrictToolNames && session.settings.get("tools.xdev") && tools.some(tool => tool.name === "write");
|
|
672
676
|
const mountBuiltinTools = requestedTools === undefined;
|
|
673
677
|
if (xdevEnabled) {
|
|
674
678
|
const mountedNames = new Set<string>();
|
|
@@ -686,14 +690,14 @@ export async function createTools(session: ToolSession, toolNames?: string[]): P
|
|
|
686
690
|
};
|
|
687
691
|
tools = kept;
|
|
688
692
|
}
|
|
689
|
-
//
|
|
690
|
-
// `write xd
|
|
691
|
-
//
|
|
692
|
-
//
|
|
693
|
+
// Staged previews from deferrable tools (e.g. ast_edit) resolve through a
|
|
694
|
+
// `write` to xd://resolve/reject, so retain write whenever one can stage.
|
|
695
|
+
// xd:// mounting itself never registers write: sessions without a granted
|
|
696
|
+
// write tool skip mounting entirely (see xdevEnabled above).
|
|
693
697
|
const xdevMounted = (session.xdev?.mountedNames.size ?? 0) > 0;
|
|
694
698
|
if (
|
|
695
699
|
!restrictToolNames &&
|
|
696
|
-
|
|
700
|
+
tools.some(tool => tool.deferrable === true) &&
|
|
697
701
|
!tools.some(tool => tool.name === "write")
|
|
698
702
|
) {
|
|
699
703
|
const writeTool = await logger.time("createTools:write", BUILTIN_TOOLS.write, session);
|
|
@@ -12,9 +12,15 @@ import { prompt } from "@oh-my-pi/pi-utils";
|
|
|
12
12
|
import { type } from "arktype";
|
|
13
13
|
import { extractTextContent } from "../commit/utils";
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
expandRoleAlias,
|
|
17
|
+
extractExplicitThinkingSelector,
|
|
18
|
+
getModelMatchPreferences,
|
|
19
|
+
resolveModelFromString,
|
|
20
|
+
} from "../config/model-resolver";
|
|
16
21
|
import inspectImageDescription from "../prompts/tools/inspect-image.md" with { type: "text" };
|
|
17
22
|
import inspectImageSystemPromptTemplate from "../prompts/tools/inspect-image-system.md" with { type: "text" };
|
|
23
|
+
import { concreteThinkingLevel, resolveThinkingLevelForModel, toReasoningEffort } from "../thinking";
|
|
18
24
|
import {
|
|
19
25
|
ImageInputTooLargeError,
|
|
20
26
|
type LoadedImageInput,
|
|
@@ -163,11 +169,17 @@ export class InspectImageTool implements AgentTool<typeof inspectImageSchema, In
|
|
|
163
169
|
};
|
|
164
170
|
|
|
165
171
|
const activeModelPattern = this.session.getActiveModelString?.() ?? this.session.getModelString?.();
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
resolvePattern(
|
|
170
|
-
|
|
172
|
+
let model: Model<Api> | undefined;
|
|
173
|
+
let selectedPattern: string | undefined;
|
|
174
|
+
for (const pattern of ["@vision", "@default", activeModelPattern]) {
|
|
175
|
+
const resolved = resolvePattern(pattern);
|
|
176
|
+
if (resolved) {
|
|
177
|
+
model = resolved;
|
|
178
|
+
selectedPattern = pattern;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
model ??= availableModels[0];
|
|
171
183
|
if (!model) {
|
|
172
184
|
throw new ToolError("Unable to resolve a model for inspect_image.");
|
|
173
185
|
}
|
|
@@ -233,6 +245,19 @@ export class InspectImageTool implements AgentTool<typeof inspectImageSchema, In
|
|
|
233
245
|
return `inspect_image request timed out after ${seconds}s. Increase inspect_image.timeoutMs (currently ${timeoutMs}ms; 0 disables) or check the vision model provider.`;
|
|
234
246
|
};
|
|
235
247
|
|
|
248
|
+
// Honor the thinking effort configured on the resolved model role
|
|
249
|
+
// (e.g. `modelRoles.vision: <model>:high`). Without it the oneshot sent a
|
|
250
|
+
// suppressed/zero thinking budget, which thinking-only models (Gemini 3.x)
|
|
251
|
+
// reject with HTTP 400 ("Budget 0 is invalid. This model only works in
|
|
252
|
+
// thinking mode.").
|
|
253
|
+
const configuredThinking = concreteThinkingLevel(
|
|
254
|
+
extractExplicitThinkingSelector(selectedPattern, this.session.settings, {
|
|
255
|
+
isLiteralModelId: (provider, id) =>
|
|
256
|
+
availableModels.some(candidate => candidate.provider === provider && candidate.id === id),
|
|
257
|
+
}),
|
|
258
|
+
);
|
|
259
|
+
const reasoning = toReasoningEffort(resolveThinkingLevelForModel(model, configuredThinking));
|
|
260
|
+
|
|
236
261
|
let response: AssistantMessage;
|
|
237
262
|
try {
|
|
238
263
|
response = await instrumentedCompleteSimple(
|
|
@@ -253,6 +278,7 @@ export class InspectImageTool implements AgentTool<typeof inspectImageSchema, In
|
|
|
253
278
|
{
|
|
254
279
|
apiKey: modelRegistry.resolver(model, this.session.getSessionId?.() ?? undefined),
|
|
255
280
|
signal: effectiveSignal,
|
|
281
|
+
reasoning,
|
|
256
282
|
},
|
|
257
283
|
{ telemetry, oneshotKind: "inspect_image", completeImpl: this.completeImageRequest },
|
|
258
284
|
);
|
|
@@ -61,6 +61,8 @@ export const PREVIEW_LIMITS = {
|
|
|
61
61
|
OUTPUT_COLLAPSED: 3,
|
|
62
62
|
/** Output preview lines in expanded view */
|
|
63
63
|
OUTPUT_EXPANDED: 10,
|
|
64
|
+
/** Computer script lines shown in collapsed view */
|
|
65
|
+
COMPUTER_CODE_COLLAPSED: 10,
|
|
64
66
|
/** Max hunks shown when collapsed (edit tool) */
|
|
65
67
|
DIFF_COLLAPSED_HUNKS: 8,
|
|
66
68
|
/** Max diff lines shown when collapsed (edit tool) */
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { untilAborted } from "@oh-my-pi/pi-utils";
|
|
2
|
-
import { ToolError, throwIfAborted } from "
|
|
1
|
+
import { untilAborted } from "@oh-my-pi/pi-utils/abortable";
|
|
2
|
+
import { ToolError, throwIfAborted } from "./tool-errors";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Marks a run-scoped promise as observed without changing its behavior for awaited callers.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Run teardown aborts can reject promises created for evaluated code after user code
|
|
8
8
|
* has stopped observing them (for example fire-and-forget `wait()`/facade calls). In 16.3.0
|
|
9
9
|
* those zero-consumer rejections reached the process-level `unhandledRejection` handler and
|
|
10
10
|
* killed every subagent sharing the process (issues #4499/#4672). Attaching a no-op rejection
|
|
@@ -33,8 +33,8 @@ export interface WaitPredicateOptions {
|
|
|
33
33
|
/**
|
|
34
34
|
* Effective `wait(predicate)` deadline for a given cell budget. Always strictly below
|
|
35
35
|
* the cell budget so the named `wait(predicate) timed out` error wins the race against
|
|
36
|
-
* the opaque whole-cell
|
|
37
|
-
*
|
|
36
|
+
* the opaque whole-cell execution timeout. `0`/`Infinity` ("disable") map to the largest
|
|
37
|
+
* bounded deadline; negative/NaN garbage falls back to the default.
|
|
38
38
|
*/
|
|
39
39
|
export function resolvePredicateTimeout(cellTimeoutMs: number, explicit?: number): number {
|
|
40
40
|
const budgetBound = Math.max(1, cellTimeoutMs - CELL_BUDGET_SLACK_MS);
|
|
@@ -44,15 +44,15 @@ export function resolvePredicateTimeout(cellTimeoutMs: number, explicit?: number
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* Run-scoped `wait()` helper for evaluated browser
|
|
48
|
-
* cancellation signal.
|
|
47
|
+
* Run-scoped `wait()` helper for evaluated code (browser and computer workers), honoring
|
|
48
|
+
* the owning run's cancellation signal.
|
|
49
49
|
*
|
|
50
50
|
* - `wait(ms)` sleeps for `ms` milliseconds.
|
|
51
51
|
* - `wait(fn, { timeout?, interval? })` polls `fn` (sync or async) until it returns a
|
|
52
52
|
* truthy value and resolves with that value; throws a named `ToolError` on timeout
|
|
53
53
|
* instead of stalling into the whole-cell deadline. Predicate errors propagate.
|
|
54
54
|
*/
|
|
55
|
-
export function
|
|
55
|
+
export function waitForRun(
|
|
56
56
|
msOrPredicate: number | (() => unknown),
|
|
57
57
|
signal: AbortSignal,
|
|
58
58
|
opts?: WaitPredicateOptions,
|
|
@@ -86,8 +86,8 @@ export function waitForBrowserRun(
|
|
|
86
86
|
return markHandled(promise);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/** Binds a long-lived
|
|
90
|
-
export function
|
|
89
|
+
/** Binds a long-lived scope facade (page/tab/desktop objects) to one evaluated run's abort signal. */
|
|
90
|
+
export function bindRunFacade<T extends object>(target: T, signal: AbortSignal): T {
|
|
91
91
|
const cache = new Map<PropertyKey, unknown>();
|
|
92
92
|
return new Proxy(target, {
|
|
93
93
|
get(current, prop) {
|
|
@@ -121,7 +121,7 @@ export function bindBrowserRunFacade<T extends object>(target: T, signal: AbortS
|
|
|
121
121
|
// brand-check internal slots that a Proxy cannot forward, and reading a
|
|
122
122
|
// signal needs no abort gating anyway.
|
|
123
123
|
if (value instanceof AbortSignal) return value;
|
|
124
|
-
const wrapped =
|
|
124
|
+
const wrapped = bindRunFacade(value, signal);
|
|
125
125
|
cache.set(prop, wrapped);
|
|
126
126
|
return wrapped;
|
|
127
127
|
}
|
|
@@ -11,6 +11,7 @@ export const TOOL_TIMEOUTS = {
|
|
|
11
11
|
bash: { default: 300, min: 1, max: 3600 },
|
|
12
12
|
eval: { default: 30, min: 1, max: 3600 },
|
|
13
13
|
browser: { default: 30, min: 1, max: 300 },
|
|
14
|
+
computer: { default: 120, min: 1, max: 300 },
|
|
14
15
|
ssh: { default: 60, min: 1, max: 3600 },
|
|
15
16
|
fetch: { default: 20, min: 1, max: 45 },
|
|
16
17
|
lsp: { default: 20, min: 5, max: 300 },
|
package/src/tools/xdev.ts
CHANGED
|
@@ -36,6 +36,7 @@ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
|
36
36
|
import { XD_URL_PREFIX } from "../internal-urls/xd-protocol";
|
|
37
37
|
import type { Theme } from "../modes/theme/theme";
|
|
38
38
|
import { truncateHeadBytes } from "../session/streaming-output";
|
|
39
|
+
import { resolveToolTier, type ToolTier } from "./approval";
|
|
39
40
|
import { renderDefaultToolExecution } from "./default-renderer";
|
|
40
41
|
import type { Tool } from "./index";
|
|
41
42
|
import { replaceTabs } from "./render-utils";
|
|
@@ -88,6 +89,13 @@ export interface XdevDispatch {
|
|
|
88
89
|
mode: "help" | "execute";
|
|
89
90
|
/** Validated inner args, kept for renderer delegation on result rebuilds. */
|
|
90
91
|
args?: Record<string, unknown>;
|
|
92
|
+
/**
|
|
93
|
+
* Approval tier of the wrapped tool for {@link args} (`read` = no workspace
|
|
94
|
+
* mutation). Absent for `help` dispatches and calls whose tier could not be
|
|
95
|
+
* resolved. Consumed by the prewalk coordinator to skip read-only device
|
|
96
|
+
* calls when deciding the model hand-off (issue #7312).
|
|
97
|
+
*/
|
|
98
|
+
tier?: ToolTier;
|
|
91
99
|
/** Details object returned by the wrapped tool, when executed. */
|
|
92
100
|
inner?: unknown;
|
|
93
101
|
}
|
|
@@ -415,7 +423,18 @@ export async function dispatchXdevTool(
|
|
|
415
423
|
}
|
|
416
424
|
|
|
417
425
|
const validated = parseDeviceArgs(canonical as AiTool, content, toolCallId, () => renderDocs(canonical));
|
|
418
|
-
|
|
426
|
+
// Record the wrapped tool's approval tier so the prewalk coordinator can
|
|
427
|
+
// tell a read-only device call (e.g. `lsp` navigation) from a real
|
|
428
|
+
// workspace mutation without re-decoding the payload. Best-effort: a
|
|
429
|
+
// throwing approval leaves the tier absent (prewalk then declines to
|
|
430
|
+
// switch), unlike the write gate which fails closed to `exec`.
|
|
431
|
+
let tier: ToolTier | undefined;
|
|
432
|
+
try {
|
|
433
|
+
tier = resolveToolTier(canonical, validated);
|
|
434
|
+
} catch {
|
|
435
|
+
tier = undefined;
|
|
436
|
+
}
|
|
437
|
+
xdev = { ...xdev, args: validated, tier };
|
|
419
438
|
const innerOnUpdate: AgentToolUpdateCallback | undefined = onUpdate
|
|
420
439
|
? partial =>
|
|
421
440
|
onUpdate({
|
|
@@ -425,7 +444,15 @@ export async function dispatchXdevTool(
|
|
|
425
444
|
})
|
|
426
445
|
: undefined;
|
|
427
446
|
const executable = state.decorateExecution?.(canonical) ?? canonical;
|
|
428
|
-
const
|
|
447
|
+
const executionContext = context
|
|
448
|
+
? {
|
|
449
|
+
...context,
|
|
450
|
+
xdevTierResolved: (effectiveTier: ToolTier) => {
|
|
451
|
+
xdev = { ...xdev, tier: effectiveTier };
|
|
452
|
+
},
|
|
453
|
+
}
|
|
454
|
+
: undefined;
|
|
455
|
+
const result = await executable.execute(toolCallId, validated as never, signal, innerOnUpdate, executionContext);
|
|
429
456
|
return { result, xdev: { ...xdev, inner: result.details } };
|
|
430
457
|
} catch (error) {
|
|
431
458
|
if (
|
package/src/utils/clipboard.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
type ClipboardImage,
|
|
3
|
+
copyToClipboard as nativeCopyToClipboard,
|
|
4
|
+
readImageFromClipboard as nativeReadImageFromClipboard,
|
|
5
|
+
} from "@oh-my-pi/pi-natives/clipboard";
|
|
6
|
+
import * as logger from "@oh-my-pi/pi-utils/logger";
|
|
7
|
+
import { SUPPORTED_IMAGE_MIME_TYPES } from "@oh-my-pi/pi-utils/mime";
|
|
4
8
|
import MAC_FILE_URL_SCRIPT from "./mac-file-urls.applescript" with { type: "text" };
|
|
5
9
|
|
|
10
|
+
type SpawnCaptureOptions = { input?: string; timeoutMs?: number };
|
|
11
|
+
|
|
6
12
|
/**
|
|
7
13
|
* Run a subprocess and capture its stdout without blocking the event loop.
|
|
8
14
|
*
|
|
@@ -10,15 +16,20 @@ import MAC_FILE_URL_SCRIPT from "./mac-file-urls.applescript" with { type: "text
|
|
|
10
16
|
* path all shell out to CLI clipboard tools. The synchronous `execSync` API
|
|
11
17
|
* parks the render loop until the child exits or the timeout fires, so a hung
|
|
12
18
|
* clipboard daemon freezes the TUI for the full 2000ms budget (#4235). This
|
|
13
|
-
* helper mirrors the previous semantics —
|
|
14
|
-
*
|
|
15
|
-
*
|
|
19
|
+
* helper mirrors the previous semantics — capture stdout, throw on non-zero
|
|
20
|
+
* exit or timeout, forward optional stdin — but yields to the event loop while
|
|
21
|
+
* the child runs.
|
|
16
22
|
*
|
|
17
23
|
* @throws Error when the child fails to spawn, is killed by the timeout, or
|
|
18
|
-
* exits with a non-zero status. Callers rely on this to
|
|
19
|
-
*
|
|
24
|
+
* exits with a non-zero status. Callers rely on this to use platform
|
|
25
|
+
* fallbacks or report an empty clipboard.
|
|
20
26
|
*/
|
|
21
|
-
async function spawnCapture(cmd: string[], options:
|
|
27
|
+
async function spawnCapture(cmd: string[], options: SpawnCaptureOptions & { encoding: "bytes" }): Promise<Uint8Array>;
|
|
28
|
+
async function spawnCapture(cmd: string[], options?: SpawnCaptureOptions): Promise<string>;
|
|
29
|
+
async function spawnCapture(
|
|
30
|
+
cmd: string[],
|
|
31
|
+
options: SpawnCaptureOptions & { encoding?: "bytes" } = {},
|
|
32
|
+
): Promise<string | Uint8Array> {
|
|
22
33
|
const timeoutMs = options.timeoutMs ?? 2000;
|
|
23
34
|
const proc = Bun.spawn(cmd, {
|
|
24
35
|
stdout: "pipe",
|
|
@@ -31,7 +42,9 @@ async function spawnCapture(cmd: string[], options: { input?: string; timeoutMs?
|
|
|
31
42
|
proc.kill();
|
|
32
43
|
}, timeoutMs);
|
|
33
44
|
try {
|
|
34
|
-
const
|
|
45
|
+
const response = new Response(proc.stdout);
|
|
46
|
+
const stdout =
|
|
47
|
+
options.encoding === "bytes" ? new Uint8Array(await response.arrayBuffer()) : await response.text();
|
|
35
48
|
await proc.exited;
|
|
36
49
|
if (timedOut) {
|
|
37
50
|
throw new Error(`${cmd[0]} timed out after ${timeoutMs}ms`);
|
|
@@ -125,7 +138,7 @@ export async function copyToClipboard(text: string): Promise<void> {
|
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
140
|
|
|
128
|
-
await
|
|
141
|
+
await nativeCopyToClipboard(text);
|
|
129
142
|
} catch {
|
|
130
143
|
// Ignore — clipboard copy is best-effort
|
|
131
144
|
}
|
|
@@ -255,7 +268,7 @@ async function readTextViaPowerShell(): Promise<string | null> {
|
|
|
255
268
|
* because terminal clipboard paths can leave image payloads invisible to the
|
|
256
269
|
* native bridge.
|
|
257
270
|
*
|
|
258
|
-
* @returns
|
|
271
|
+
* @returns A supported image payload or null when no image is available.
|
|
259
272
|
*/
|
|
260
273
|
export async function readImageFromClipboard(): Promise<ClipboardImage | null> {
|
|
261
274
|
if (process.env.TERMUX_VERSION) {
|
|
@@ -272,7 +285,7 @@ export async function readImageFromClipboard(): Promise<ClipboardImage | null> {
|
|
|
272
285
|
|
|
273
286
|
if (process.platform === "win32") {
|
|
274
287
|
try {
|
|
275
|
-
const image = await
|
|
288
|
+
const image = await nativeReadImageFromClipboard();
|
|
276
289
|
if (image) return image;
|
|
277
290
|
} catch (err) {
|
|
278
291
|
logger.warn("clipboard: native Windows image read failed", { error: String(err) });
|
|
@@ -280,11 +293,24 @@ export async function readImageFromClipboard(): Promise<ClipboardImage | null> {
|
|
|
280
293
|
return await readImageViaPowerShell();
|
|
281
294
|
}
|
|
282
295
|
|
|
296
|
+
if (process.platform === "linux" && process.env.WAYLAND_DISPLAY) {
|
|
297
|
+
try {
|
|
298
|
+
const offeredMimeTypes = new Set((await spawnCapture(["wl-paste", "--list-types"])).split(/\r?\n/));
|
|
299
|
+
for (const mimeType of SUPPORTED_IMAGE_MIME_TYPES) {
|
|
300
|
+
if (!offeredMimeTypes.has(mimeType)) continue;
|
|
301
|
+
const data = await spawnCapture(["wl-paste", "--type", mimeType], { encoding: "bytes" });
|
|
302
|
+
if (data.byteLength > 0) return { data, mimeType };
|
|
303
|
+
}
|
|
304
|
+
} catch {
|
|
305
|
+
// Fall through when wl-clipboard is absent or no advertised image payload can be read.
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
283
309
|
if (!hasDisplay()) {
|
|
284
310
|
return null;
|
|
285
311
|
}
|
|
286
312
|
|
|
287
|
-
return (await
|
|
313
|
+
return (await nativeReadImageFromClipboard()) ?? null;
|
|
288
314
|
}
|
|
289
315
|
|
|
290
316
|
/**
|
|
@@ -39,38 +39,36 @@ export function parseCommandArgs(argsString: string): string[] {
|
|
|
39
39
|
* containing patterns like $1, $@, or $ARGUMENTS are NOT recursively substituted.
|
|
40
40
|
*/
|
|
41
41
|
export function substituteArgs(content: string, args: string[]): string {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// Replace $1, $2, etc. with positional args FIRST (before wildcards)
|
|
45
|
-
// This prevents wildcard replacement values containing $<digit> patterns from being re-substituted
|
|
46
|
-
result = result.replace(/\$(\d+)/g, (_, num) => {
|
|
47
|
-
const index = parseInt(num, 10) - 1;
|
|
48
|
-
return args[index] ?? "";
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
result = result.replace(/\$@\[(\d+)(?::(\d*)?)?\]/g, (_, startRaw: string, lengthRaw?: string) => {
|
|
52
|
-
const start = Number.parseInt(startRaw, 10);
|
|
53
|
-
if (!Number.isFinite(start) || start < 1) return "";
|
|
54
|
-
const startIndex = start - 1;
|
|
55
|
-
if (startIndex >= args.length) return "";
|
|
42
|
+
const allArgs = args.join(" ");
|
|
56
43
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
44
|
+
return content.replace(
|
|
45
|
+
/\$@\[(\d+)(?::(\d*)?)?\]|\$ARGUMENTS|\$@|\$(\d+)/g,
|
|
46
|
+
(match, startRaw?: string, lengthRaw?: string, positionalNum?: string) => {
|
|
47
|
+
if (positionalNum !== undefined) {
|
|
48
|
+
const index = Number.parseInt(positionalNum, 10) - 1;
|
|
49
|
+
return args[index] ?? "";
|
|
50
|
+
}
|
|
60
51
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
if (startRaw !== undefined) {
|
|
53
|
+
const start = Number.parseInt(startRaw, 10);
|
|
54
|
+
if (!Number.isFinite(start) || start < 1) return "";
|
|
55
|
+
const startIndex = start - 1;
|
|
56
|
+
if (startIndex >= args.length) return "";
|
|
65
57
|
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
if (lengthRaw === undefined || lengthRaw === "") {
|
|
59
|
+
return args.slice(startIndex).join(" ");
|
|
60
|
+
}
|
|
68
61
|
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
const length = Number.parseInt(lengthRaw, 10);
|
|
63
|
+
if (!Number.isFinite(length) || length <= 0) return "";
|
|
64
|
+
return args.slice(startIndex, startIndex + length).join(" ");
|
|
65
|
+
}
|
|
71
66
|
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
if (match === "$ARGUMENTS" || match === "$@") {
|
|
68
|
+
return allArgs;
|
|
69
|
+
}
|
|
74
70
|
|
|
75
|
-
|
|
71
|
+
return match;
|
|
72
|
+
},
|
|
73
|
+
);
|
|
76
74
|
}
|
package/src/utils/tool-choice.ts
CHANGED
|
@@ -12,19 +12,6 @@ export function buildNamedToolChoice(toolName: string, model?: Model<Api>): Tool
|
|
|
12
12
|
return { type: "tool", name: toolName };
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
if (toolName === "computer" && model.supportsComputerUse === true) {
|
|
16
|
-
if (
|
|
17
|
-
model.api === "openai-codex-responses" ||
|
|
18
|
-
model.api === "openai-responses" ||
|
|
19
|
-
model.api === "azure-openai-responses"
|
|
20
|
-
) {
|
|
21
|
-
return { type: "computer" };
|
|
22
|
-
}
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
// Models without native computer support receive the tool as a regular
|
|
26
|
-
// function tool, so the generic named-function forcing below applies.
|
|
27
|
-
|
|
28
15
|
if (
|
|
29
16
|
model.api === "openai-codex-responses" ||
|
|
30
17
|
model.api === "openai-responses" ||
|
package/src/web/kagi.ts
CHANGED
|
@@ -156,6 +156,7 @@ export interface KagiSearchOptions {
|
|
|
156
156
|
recency?: "day" | "week" | "month" | "year";
|
|
157
157
|
sessionId?: string;
|
|
158
158
|
signal?: AbortSignal;
|
|
159
|
+
timeoutMs?: number;
|
|
159
160
|
fetch?: FetchImpl;
|
|
160
161
|
}
|
|
161
162
|
|
|
@@ -253,7 +254,7 @@ export async function searchWithKagi(
|
|
|
253
254
|
Accept: "application/json",
|
|
254
255
|
},
|
|
255
256
|
body,
|
|
256
|
-
signal: withHardTimeout(options.signal),
|
|
257
|
+
signal: withHardTimeout(options.signal, options.timeoutMs),
|
|
257
258
|
});
|
|
258
259
|
|
|
259
260
|
if (!res.ok) {
|
package/src/web/search/index.ts
CHANGED
|
@@ -29,8 +29,13 @@ import {
|
|
|
29
29
|
} from "./provider";
|
|
30
30
|
import { applyQueryConstraints, parseSearchQuery } from "./query";
|
|
31
31
|
import { renderSearchCall, renderSearchResult, type SearchRenderDetails } from "./render";
|
|
32
|
-
import
|
|
33
|
-
|
|
32
|
+
import {
|
|
33
|
+
DEFAULT_WEB_SEARCH_TIMEOUT_SECONDS,
|
|
34
|
+
MAX_WEB_SEARCH_TIMEOUT_SECONDS,
|
|
35
|
+
SearchProviderError,
|
|
36
|
+
type SearchProviderId,
|
|
37
|
+
type SearchResponse,
|
|
38
|
+
} from "./types";
|
|
34
39
|
|
|
35
40
|
/** Web search tool parameters schema */
|
|
36
41
|
export const webSearchSchema = type({
|
|
@@ -164,6 +169,16 @@ async function executeSearch(
|
|
|
164
169
|
geminiModel = undefined;
|
|
165
170
|
}
|
|
166
171
|
|
|
172
|
+
let timeoutMs = DEFAULT_WEB_SEARCH_TIMEOUT_SECONDS * 1_000;
|
|
173
|
+
try {
|
|
174
|
+
const configuredSeconds = settings.get("providers.webSearchTimeoutSeconds");
|
|
175
|
+
if (Number.isFinite(configuredSeconds) && configuredSeconds > 0) {
|
|
176
|
+
timeoutMs = Math.ceil(Math.min(configuredSeconds, MAX_WEB_SEARCH_TIMEOUT_SECONDS) * 1_000);
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
// Preserve the default for one-shot callers that do not initialize Settings.
|
|
180
|
+
}
|
|
181
|
+
|
|
167
182
|
const failures: Array<{ provider: Pick<SearchProvider, "id" | "label">; error: unknown }> = [];
|
|
168
183
|
let availableProviderCount = 0;
|
|
169
184
|
let lastProvider: Pick<SearchProvider, "id" | "label"> | undefined;
|
|
@@ -196,6 +211,7 @@ async function executeSearch(
|
|
|
196
211
|
numSearchResults: params.num_search_results,
|
|
197
212
|
temperature: params.temperature,
|
|
198
213
|
signal,
|
|
214
|
+
timeoutMs,
|
|
199
215
|
authStorage,
|
|
200
216
|
modelRegistry,
|
|
201
217
|
sessionId,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
withAuth,
|
|
20
20
|
wrapFetchForCch,
|
|
21
21
|
} from "@oh-my-pi/pi-ai";
|
|
22
|
+
import { hasOpus47ApiRestrictions } from "@oh-my-pi/pi-catalog/identity/family";
|
|
22
23
|
import { $env } from "@oh-my-pi/pi-utils";
|
|
23
24
|
import type {
|
|
24
25
|
AnthropicApiResponse,
|
|
@@ -97,6 +98,7 @@ export interface AnthropicSearchParams {
|
|
|
97
98
|
max_tokens?: number;
|
|
98
99
|
temperature?: number;
|
|
99
100
|
signal?: AbortSignal;
|
|
101
|
+
timeoutMs?: number;
|
|
100
102
|
fetch?: FetchImpl;
|
|
101
103
|
}
|
|
102
104
|
|
|
@@ -152,6 +154,7 @@ async function callSearch(
|
|
|
152
154
|
temperature?: number,
|
|
153
155
|
signal?: AbortSignal,
|
|
154
156
|
fetchImpl: FetchImpl = fetch,
|
|
157
|
+
timeoutMs?: number,
|
|
155
158
|
): Promise<AnthropicApiResponse> {
|
|
156
159
|
const url = buildAnthropicUrl(auth);
|
|
157
160
|
const headers = buildAnthropicSearchHeaders(auth);
|
|
@@ -176,7 +179,8 @@ async function callSearch(
|
|
|
176
179
|
body.metadata = { user_id: metadataUserId };
|
|
177
180
|
}
|
|
178
181
|
|
|
179
|
-
|
|
182
|
+
// Opus 4.7+, Sonnet 5+, and Fable/Mythos 5 reject sampling parameters with a 400.
|
|
183
|
+
if (temperature !== undefined && !hasOpus47ApiRestrictions(model)) {
|
|
180
184
|
body.temperature = temperature;
|
|
181
185
|
}
|
|
182
186
|
|
|
@@ -191,7 +195,7 @@ async function callSearch(
|
|
|
191
195
|
method: "POST",
|
|
192
196
|
headers,
|
|
193
197
|
body: JSON.stringify(body),
|
|
194
|
-
signal: withHardTimeout(signal),
|
|
198
|
+
signal: withHardTimeout(signal, timeoutMs),
|
|
195
199
|
});
|
|
196
200
|
|
|
197
201
|
if (!response.ok) {
|
|
@@ -367,6 +371,7 @@ export async function searchAnthropic(
|
|
|
367
371
|
params.temperature,
|
|
368
372
|
params.signal,
|
|
369
373
|
params.fetch,
|
|
374
|
+
params.timeoutMs,
|
|
370
375
|
);
|
|
371
376
|
},
|
|
372
377
|
{
|
|
@@ -47,6 +47,8 @@ export interface SearchParams {
|
|
|
47
47
|
recency?: "day" | "week" | "month" | "year";
|
|
48
48
|
systemPrompt: string;
|
|
49
49
|
signal?: AbortSignal;
|
|
50
|
+
/** Hard timeout for this provider's search transport, in milliseconds. */
|
|
51
|
+
timeoutMs?: number;
|
|
50
52
|
fetch?: FetchImpl;
|
|
51
53
|
maxOutputTokens?: number;
|
|
52
54
|
numSearchResults?: number;
|
|
@@ -52,6 +52,7 @@ export interface BraveSearchParams {
|
|
|
52
52
|
recency?: "day" | "week" | "month" | "year";
|
|
53
53
|
parsedQuery?: StructuredQuery;
|
|
54
54
|
signal?: AbortSignal;
|
|
55
|
+
timeoutMs?: number;
|
|
55
56
|
fetch?: FetchImpl;
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -113,7 +114,7 @@ async function callBraveSearch(
|
|
|
113
114
|
Accept: "application/json",
|
|
114
115
|
"X-Subscription-Token": apiKey,
|
|
115
116
|
},
|
|
116
|
-
signal: withHardTimeout(params.signal),
|
|
117
|
+
signal: withHardTimeout(params.signal, params.timeoutMs),
|
|
117
118
|
});
|
|
118
119
|
|
|
119
120
|
if (!response.ok) {
|
|
@@ -173,6 +174,7 @@ export class BraveProvider extends SearchProvider {
|
|
|
173
174
|
recency: params.recency,
|
|
174
175
|
parsedQuery: params.parsedQuery,
|
|
175
176
|
signal: params.signal,
|
|
177
|
+
timeoutMs: params.timeoutMs,
|
|
176
178
|
fetch: params.fetch,
|
|
177
179
|
});
|
|
178
180
|
}
|