@oh-my-pi/pi-coding-agent 17.2.4 → 17.2.6
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 +69 -0
- package/dist/{CHANGELOG-bpmhv26t.md → CHANGELOG-gs76k6wc.md} +69 -0
- package/dist/cli.js +4438 -3962
- package/dist/{template-8vdv6xb4.js → template-c2hyaytt.js} +8 -26
- 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/gc-cli.d.ts +1 -0
- package/dist/types/cli/help-extra.d.ts +2 -0
- 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 +5 -0
- 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 +69 -21
- package/dist/types/cursor-bridge-tools.d.ts +1 -1
- package/dist/types/cursor.d.ts +7 -4
- 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/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/launch/broker.d.ts +1 -1
- package/dist/types/launch/client.d.ts +15 -4
- package/dist/types/launch/ensure.d.ts +8 -0
- package/dist/types/launch/paths.d.ts +1 -1
- package/dist/types/launch/protocol.d.ts +19 -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/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/btw-panel.d.ts +3 -0
- package/dist/types/modes/components/custom-editor.d.ts +2 -1
- package/dist/types/modes/components/read-tool-group.d.ts +2 -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/btw-controller.d.ts +2 -0
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +5 -1
- package/dist/types/modes/types.d.ts +4 -1
- package/dist/types/modes/workflow.d.ts +2 -1
- package/dist/types/sdk.d.ts +3 -1
- package/dist/types/secrets/index.d.ts +1 -1
- package/dist/types/security/contracts/schemas.d.ts +405 -403
- package/dist/types/session/agent-session-types.d.ts +8 -1
- package/dist/types/session/agent-session.d.ts +26 -2
- package/dist/types/session/indexed-session-storage.d.ts +1 -0
- package/dist/types/session/launch-completion.d.ts +10 -0
- package/dist/types/session/session-advisors.d.ts +1 -1
- package/dist/types/session/session-context.d.ts +2 -1
- package/dist/types/session/session-entries.d.ts +15 -1
- package/dist/types/session/session-maintenance.d.ts +1 -0
- package/dist/types/session/session-manager.d.ts +23 -11
- package/dist/types/session/session-stats.d.ts +10 -0
- package/dist/types/session/session-storage.d.ts +15 -3
- package/dist/types/session/yield-queue.d.ts +6 -1
- package/dist/types/system-prompt.d.ts +4 -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/glob.d.ts +1 -1
- package/dist/types/tools/grep.d.ts +1 -1
- package/dist/types/tools/index.d.ts +9 -0
- 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/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/gc-cli.ts +641 -21
- package/src/cli/help-extra.ts +89 -0
- 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/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 +5 -0
- package/src/config/model-discovery.ts +44 -27
- package/src/config/model-registry.ts +19 -13
- 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 +72 -20
- package/src/config/settings.ts +1 -1
- package/src/cursor-bridge-tools.ts +1 -1
- package/src/cursor.ts +10 -14
- 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/index.ts +10 -3
- package/src/export/html/template.js +8 -26
- package/src/export/share.ts +4 -0
- 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/skills.ts +11 -0
- package/src/extensibility/utils.ts +10 -2
- package/src/launch/broker.ts +223 -7
- package/src/launch/client.ts +192 -21
- package/src/launch/ensure.ts +73 -0
- package/src/launch/paths.ts +1 -1
- package/src/launch/protocol.ts +54 -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 +20 -8
- package/src/mcp/config-writer.ts +1 -1
- package/src/mcp/oauth-flow.ts +11 -1
- package/src/mnemopi/embed-client.ts +49 -2
- package/src/mnemopi/state.ts +57 -23
- package/src/modes/components/assistant-message.ts +11 -0
- package/src/modes/components/btw-panel.ts +41 -4
- package/src/modes/components/chat-transcript-builder.ts +4 -0
- package/src/modes/components/custom-editor.ts +9 -0
- package/src/modes/components/read-tool-group.ts +10 -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 +8 -0
- package/src/modes/components/tree-selector.ts +46 -48
- package/src/modes/controllers/btw-controller.ts +55 -7
- package/src/modes/controllers/command-controller.ts +31 -0
- package/src/modes/controllers/event-controller.ts +17 -0
- package/src/modes/controllers/input-controller.ts +63 -8
- package/src/modes/controllers/mcp-command-controller.ts +11 -5
- package/src/modes/controllers/selector-controller.ts +20 -0
- package/src/modes/interactive-mode.ts +18 -2
- package/src/modes/types.ts +9 -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/session/launch-completion.md +1 -0
- 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/sdk.ts +49 -6
- package/src/secrets/index.ts +1 -1
- package/src/security/contracts/schemas.ts +205 -183
- package/src/security/contracts/validation.ts +5 -1
- package/src/security/store.ts +2 -2
- package/src/session/agent-session-types.ts +9 -1
- package/src/session/agent-session.ts +204 -15
- package/src/session/indexed-session-storage.ts +9 -0
- package/src/session/launch-completion.ts +37 -0
- package/src/session/prewalk.ts +24 -2
- package/src/session/session-advisors.ts +2 -2
- package/src/session/session-context.ts +42 -12
- package/src/session/session-dump-format.ts +1 -1
- package/src/session/session-entries.ts +17 -1
- package/src/session/session-maintenance.ts +38 -4
- package/src/session/session-manager.ts +123 -67
- 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/stream-guards.ts +1 -1
- package/src/session/yield-queue.ts +121 -16
- package/src/slash-commands/builtin-registry.ts +37 -24
- package/src/system-prompt.ts +8 -3
- package/src/task/index.ts +23 -8
- package/src/task/spawn-policy.ts +14 -0
- package/src/thinking.ts +2 -8
- package/src/tools/ast-grep.ts +10 -4
- package/src/tools/browser/cmux/cmux-tab.ts +97 -14
- 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/glob.ts +9 -2
- package/src/tools/grep.ts +12 -6
- package/src/tools/hub/launch.ts +122 -6
- package/src/tools/index.ts +9 -0
- 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 +4 -1
- 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/dist/types/config/file-lock.d.ts +0 -29
- package/src/config/file-lock.ts +0 -164
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
containsActive.set(node, has);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
// Stack: [node, indent,
|
|
207
|
+
// Stack: [node, indent, showConnector, isLast, gutters, isVirtualRootChild]
|
|
208
208
|
const stack = [];
|
|
209
209
|
|
|
210
210
|
// Add roots (prioritize branch containing active leaf)
|
|
@@ -213,11 +213,11 @@
|
|
|
213
213
|
);
|
|
214
214
|
for (let i = orderedRoots.length - 1; i >= 0; i--) {
|
|
215
215
|
const isLast = i === orderedRoots.length - 1;
|
|
216
|
-
stack.push([orderedRoots[i], multipleRoots ? 1 : 0, multipleRoots,
|
|
216
|
+
stack.push([orderedRoots[i], multipleRoots ? 1 : 0, multipleRoots, isLast, [], multipleRoots]);
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
while (stack.length > 0) {
|
|
220
|
-
const [node, indent,
|
|
220
|
+
const [node, indent, showConnector, isLast, gutters, isVirtualRootChild] = stack.pop();
|
|
221
221
|
|
|
222
222
|
result.push({ node, indent, showConnector, isLast, gutters, isVirtualRootChild, multipleRoots });
|
|
223
223
|
|
|
@@ -229,18 +229,10 @@
|
|
|
229
229
|
Number(containsActive.get(b)) - Number(containsActive.get(a))
|
|
230
230
|
);
|
|
231
231
|
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
childIndent = indent + 1;
|
|
237
|
-
} else if (justBranched && indent > 0) {
|
|
238
|
-
// First generation after a branch: +1 for visual grouping
|
|
239
|
-
childIndent = indent + 1;
|
|
240
|
-
} else {
|
|
241
|
-
// Single-child chain: stay flat
|
|
242
|
-
childIndent = indent;
|
|
243
|
-
}
|
|
232
|
+
// Real branch points add visual depth, and a virtual root's direct
|
|
233
|
+
// children (the session roots) nest one level under the shared
|
|
234
|
+
// column-0 root. Linear continuations otherwise stay aligned.
|
|
235
|
+
const childIndent = multipleChildren || isVirtualRootChild ? indent + 1 : indent;
|
|
244
236
|
|
|
245
237
|
// Build gutters for children
|
|
246
238
|
const connectorDisplayed = showConnector && !isVirtualRootChild;
|
|
@@ -253,7 +245,7 @@
|
|
|
253
245
|
// Add children in reverse order for stack
|
|
254
246
|
for (let i = orderedChildren.length - 1; i >= 0; i--) {
|
|
255
247
|
const childIsLast = i === orderedChildren.length - 1;
|
|
256
|
-
stack.push([orderedChildren[i], childIndent, multipleChildren,
|
|
248
|
+
stack.push([orderedChildren[i], childIndent, multipleChildren, childIsLast, childGutters, false]);
|
|
257
249
|
}
|
|
258
250
|
}
|
|
259
251
|
|
|
@@ -268,13 +260,6 @@
|
|
|
268
260
|
const displayIndent = multipleRoots ? Math.max(0, indent - 1) : indent;
|
|
269
261
|
const connector = showConnector && !isVirtualRootChild ? (isLast ? '└─ ' : '├─ ') : '';
|
|
270
262
|
const connectorPosition = connector ? displayIndent - 1 : -1;
|
|
271
|
-
// Chain rows (no connector of their own) under a last-sibling (`└─`)
|
|
272
|
-
// branch stay anchored by a vertical drawn one level right of the
|
|
273
|
-
// suppressed gutter — below the branch head's content — never in the
|
|
274
|
-
// `└─` corner column itself (#2298, #2325). Chains under `├─` heads
|
|
275
|
-
// are already anchored by the sibling line (`show: true` gutter).
|
|
276
|
-
const nearestGutter = !connector ? gutters[gutters.length - 1] : undefined;
|
|
277
|
-
const chainAnchorLevel = nearestGutter && !nearestGutter.show ? nearestGutter.position + 1 : -1;
|
|
278
263
|
|
|
279
264
|
const totalChars = displayIndent * 3;
|
|
280
265
|
const prefixChars = [];
|
|
@@ -287,9 +272,6 @@
|
|
|
287
272
|
// Standard tree semantics: `│` only while more siblings continue
|
|
288
273
|
// below (`show`), space below a `└─`.
|
|
289
274
|
prefixChars.push(posInLevel === 0 && gutter.show ? '│' : ' ');
|
|
290
|
-
} else if (level === chainAnchorLevel) {
|
|
291
|
-
// Chain anchor for rows under a `└─` branch head.
|
|
292
|
-
prefixChars.push(posInLevel === 0 ? '│' : ' ');
|
|
293
275
|
} else if (connector && level === connectorPosition) {
|
|
294
276
|
if (posInLevel === 0) {
|
|
295
277
|
prefixChars.push(isLast ? '└' : '├');
|
package/src/export/share.ts
CHANGED
|
@@ -223,6 +223,7 @@ function collectShareRegexSecretValues(o: SecretObfuscator, data: SessionData):
|
|
|
223
223
|
if (!header) return;
|
|
224
224
|
add(header.title);
|
|
225
225
|
add(header.cwd);
|
|
226
|
+
for (const previousSessionFile of header.previousSessionFiles ?? []) add(previousSessionFile);
|
|
226
227
|
};
|
|
227
228
|
|
|
228
229
|
addHeader(data.header);
|
|
@@ -246,6 +247,9 @@ function redactShareHeader(
|
|
|
246
247
|
...header,
|
|
247
248
|
title: header.title === undefined ? undefined : o.obfuscate(header.title, sharedRegexSecretValues),
|
|
248
249
|
cwd: o.obfuscate(header.cwd, sharedRegexSecretValues),
|
|
250
|
+
previousSessionFiles: header.previousSessionFiles?.map(previousSessionFile =>
|
|
251
|
+
o.obfuscate(previousSessionFile, sharedRegexSecretValues),
|
|
252
|
+
),
|
|
249
253
|
};
|
|
250
254
|
}
|
|
251
255
|
|
|
@@ -239,6 +239,7 @@ export class ExtensionToolWrapper<TParameters extends TSchema = TSchema, TDetail
|
|
|
239
239
|
// short-circuit above.
|
|
240
240
|
const resolvedArgs = approvalArgs(effectiveParams, context);
|
|
241
241
|
const resolved = resolveApproval(this.tool, resolvedArgs, approvalMode, userPolicies);
|
|
242
|
+
context?.xdevTierResolved?.(resolved.tier);
|
|
242
243
|
if (resolved.policy === "deny") {
|
|
243
244
|
throw new Error(
|
|
244
245
|
`Tool "${this.tool.name}" is blocked by user policy.\n` +
|
|
@@ -19,7 +19,15 @@
|
|
|
19
19
|
* `types.ts` via the `export *` below — pi-ai still exports both as types,
|
|
20
20
|
* only the runtime `Type` builder and `StringEnum()` helper were removed.
|
|
21
21
|
*/
|
|
22
|
-
import
|
|
22
|
+
import {
|
|
23
|
+
type Api,
|
|
24
|
+
type AssistantMessage,
|
|
25
|
+
type AssistantMessageEventStream,
|
|
26
|
+
type Context,
|
|
27
|
+
type Model,
|
|
28
|
+
type SimpleStreamOptions,
|
|
29
|
+
streamSimple,
|
|
30
|
+
} from "@oh-my-pi/pi-ai";
|
|
23
31
|
import type { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
24
32
|
import { clampThinkingLevelForModel } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
25
33
|
import {
|
|
@@ -121,6 +129,19 @@ export { calculateCost, getBundledModel, getBundledModels, getBundledProviders,
|
|
|
121
129
|
export const getModel = getBundledModel;
|
|
122
130
|
export const getModels = getBundledModels;
|
|
123
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Stream OpenAI Responses through the historical simple-options contract.
|
|
134
|
+
*
|
|
135
|
+
* Legacy `/compat` callers pass {@link SimpleStreamOptions}; routing through
|
|
136
|
+
* `streamSimple` preserves option normalization before provider dispatch.
|
|
137
|
+
*/
|
|
138
|
+
export function streamSimpleOpenAIResponses(
|
|
139
|
+
model: Model<"openai-responses">,
|
|
140
|
+
context: Context,
|
|
141
|
+
options?: SimpleStreamOptions,
|
|
142
|
+
): AssistantMessageEventStream {
|
|
143
|
+
return streamSimple(model, context, options);
|
|
144
|
+
}
|
|
124
145
|
/**
|
|
125
146
|
* Compatibility re-exports for runtime helpers that upstream
|
|
126
147
|
* `@earendil-works/pi-ai` exposed from its package root but omp's
|
|
@@ -1415,12 +1415,13 @@ export function getPackageDir(): string {
|
|
|
1415
1415
|
return getOmpPackageDir() ?? (isCompiledBinary() ? path.dirname(process.execPath) : process.cwd());
|
|
1416
1416
|
}
|
|
1417
1417
|
|
|
1418
|
-
// Legacy pi's `@earendil-works/pi-coding-agent` re-exported `estimateTokens
|
|
1419
|
-
// and `
|
|
1420
|
-
// omp
|
|
1421
|
-
//
|
|
1422
|
-
//
|
|
1423
|
-
export
|
|
1418
|
+
// Legacy pi's `@earendil-works/pi-coding-agent` re-exported `estimateTokens`,
|
|
1419
|
+
// `compact`, and `serializeConversation` from its package root (via
|
|
1420
|
+
// `./core/compaction/index.ts`). In omp they live in
|
|
1421
|
+
// `@oh-my-pi/pi-agent-core/compaction`, and the coding-agent barrel below does
|
|
1422
|
+
// not forward them, so legacy extensions importing them fail Bun's static
|
|
1423
|
+
// export check during validation (issues #6583, #7174, #7403).
|
|
1424
|
+
export { compact, estimateTokens, serializeConversation } from "@oh-my-pi/pi-agent-core/compaction";
|
|
1424
1425
|
|
|
1425
1426
|
// Same barrel gap for two more legacy package-root exports: pi re-exported the
|
|
1426
1427
|
// `CONFIG_DIR_NAME` constant and the CLI parser `parseArgs`. In omp
|
|
@@ -665,7 +665,6 @@ const bareRequireResolutionCache = new Map<string, Promise<string | null>>();
|
|
|
665
665
|
const realpathCache = new Map<string, Promise<string>>();
|
|
666
666
|
const nativeAddonResolutionCache = new Map<string, Promise<string | null>>();
|
|
667
667
|
const nativeAddonRequireScanCache = new Map<string, Promise<boolean>>();
|
|
668
|
-
const nativeAddonLoaderModulePaths = new Set<string>();
|
|
669
668
|
|
|
670
669
|
function clearLegacyPiResolutionCaches(): void {
|
|
671
670
|
resolvedSpecifierFallbacks.clear();
|
|
@@ -677,7 +676,6 @@ function clearLegacyPiResolutionCaches(): void {
|
|
|
677
676
|
bareRequireResolutionCache.clear();
|
|
678
677
|
nativeAddonResolutionCache.clear();
|
|
679
678
|
nativeAddonRequireScanCache.clear();
|
|
680
|
-
nativeAddonLoaderModulePaths.clear();
|
|
681
679
|
realpathCache.clear();
|
|
682
680
|
}
|
|
683
681
|
|
|
@@ -1076,6 +1074,23 @@ async function resolveSourceModuleFile(basePath: string): Promise<string | null>
|
|
|
1076
1074
|
return null;
|
|
1077
1075
|
}
|
|
1078
1076
|
|
|
1077
|
+
async function resolveRelativeCommonJsRequire(specifier: string, importerPath: string): Promise<string | null> {
|
|
1078
|
+
const candidate = path.resolve(path.dirname(importerPath), specifier);
|
|
1079
|
+
try {
|
|
1080
|
+
const stats = await fs.promises.stat(candidate);
|
|
1081
|
+
if (stats.isDirectory()) {
|
|
1082
|
+
const manifest = await readPackageManifest(candidate);
|
|
1083
|
+
if (typeof manifest?.main === "string") {
|
|
1084
|
+
const main = await resolveSourceModuleFile(path.resolve(candidate, manifest.main));
|
|
1085
|
+
if (main) return main;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
} catch {
|
|
1089
|
+
// Missing candidates fall through to extension and index resolution.
|
|
1090
|
+
}
|
|
1091
|
+
return resolveSourceModuleFile(candidate);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1079
1094
|
function isPathInsideRoot(rootPath: string, candidatePath: string): boolean {
|
|
1080
1095
|
const relative = path.relative(rootPath, candidatePath);
|
|
1081
1096
|
return relative === "" || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
|
|
@@ -1255,7 +1270,7 @@ function isBareExtensionDependencySpecifier(specifier: string): boolean {
|
|
|
1255
1270
|
return false;
|
|
1256
1271
|
}
|
|
1257
1272
|
const packageName = specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0];
|
|
1258
|
-
return Boolean(packageName && !isBuiltin(
|
|
1273
|
+
return Boolean(packageName && !isBuiltin(specifier));
|
|
1259
1274
|
}
|
|
1260
1275
|
|
|
1261
1276
|
interface BarePackageSpecifier {
|
|
@@ -1319,7 +1334,6 @@ async function readPackageManifestUncached(packageRoot: string): Promise<Record<
|
|
|
1319
1334
|
}
|
|
1320
1335
|
|
|
1321
1336
|
type ExtensionModuleKind = "commonjs" | "esm";
|
|
1322
|
-
class ExtensionModuleKindConflictError extends Error {}
|
|
1323
1337
|
|
|
1324
1338
|
async function isCommonJsModulePath(
|
|
1325
1339
|
modulePath: string,
|
|
@@ -1440,7 +1454,7 @@ async function resolveNodePackageFallback(
|
|
|
1440
1454
|
subpath: string | null,
|
|
1441
1455
|
manifest: Record<string, unknown>,
|
|
1442
1456
|
): Promise<string | null> {
|
|
1443
|
-
if (subpath
|
|
1457
|
+
if (subpath) {
|
|
1444
1458
|
return resolvePackageSourceTarget(packageRoot, path.join(packageRoot, subpath));
|
|
1445
1459
|
}
|
|
1446
1460
|
for (const field of ["module", "main"]) {
|
|
@@ -1476,7 +1490,7 @@ async function resolveNodePackageRequire(specifier: string, importerPath: string
|
|
|
1476
1490
|
if (Object.hasOwn(manifest, "exports")) {
|
|
1477
1491
|
return resolveNodePackageExport(packageRoot, parsed.subpath, manifest, SUPPORTED_PACKAGE_REQUIRE_CONDITIONS);
|
|
1478
1492
|
}
|
|
1479
|
-
if (parsed.subpath
|
|
1493
|
+
if (parsed.subpath) {
|
|
1480
1494
|
return resolvePackageSourceTarget(packageRoot, path.join(packageRoot, parsed.subpath));
|
|
1481
1495
|
}
|
|
1482
1496
|
const main = manifest.main;
|
|
@@ -1638,6 +1652,9 @@ async function resolveExtensionBareRequire(specifier: string, importerPath: stri
|
|
|
1638
1652
|
}
|
|
1639
1653
|
|
|
1640
1654
|
async function resolveExtensionCommonJsRequire(specifier: string, importerPath: string): Promise<string | null> {
|
|
1655
|
+
if (specifier.startsWith(".")) {
|
|
1656
|
+
return resolveRelativeCommonJsRequire(specifier, importerPath);
|
|
1657
|
+
}
|
|
1641
1658
|
const remappedSpecifier = remapLegacyPiSpecifier(specifier);
|
|
1642
1659
|
if (remappedSpecifier) {
|
|
1643
1660
|
try {
|
|
@@ -1757,6 +1774,7 @@ const extensionGraphCacheBustResolvedImportModules = new Map<string, Set<string>
|
|
|
1757
1774
|
const commonJsModuleSources = new Map<string, string>();
|
|
1758
1775
|
const commonJsFallbackModulePaths = new Map<string, string>();
|
|
1759
1776
|
const extensionSynchronousSpecifierTargets = new Map<string, Map<string, string>>();
|
|
1777
|
+
const synchronousModuleSources = new Map<string, string>();
|
|
1760
1778
|
const commonJsGraphModulePaths = new Set<string>();
|
|
1761
1779
|
const COMMONJS_REQUIRE_GLOBAL = "__ompLegacyPiRequireGraphModule";
|
|
1762
1780
|
const commonJsModuleDefinitions = new Map<string, { source: string; filename: string; dirname: string }>();
|
|
@@ -1886,6 +1904,7 @@ interface ExtensionModuleGraph {
|
|
|
1886
1904
|
readonly modules: Map<string, string>;
|
|
1887
1905
|
readonly cacheBustResolvedImportModules: Set<string>;
|
|
1888
1906
|
readonly commonJsPaths: Set<string>;
|
|
1907
|
+
readonly synchronousSourcePaths: Set<string>;
|
|
1889
1908
|
}
|
|
1890
1909
|
|
|
1891
1910
|
/**
|
|
@@ -1901,6 +1920,7 @@ interface ExtensionModuleGraph {
|
|
|
1901
1920
|
async function collectExtensionModules(entryRealPath: string): Promise<ExtensionModuleGraph> {
|
|
1902
1921
|
const modules = new Map<string, string>();
|
|
1903
1922
|
const commonJsPaths = new Set<string>();
|
|
1923
|
+
const synchronousSourcePaths = new Set<string>();
|
|
1904
1924
|
const queuedCacheBustResolvedImports = new Map<string, boolean>([[entryRealPath, true]]);
|
|
1905
1925
|
const queuedModuleKinds = new Map<string, ExtensionModuleKind>([[entryRealPath, "esm"]]);
|
|
1906
1926
|
const queuedEsmBranchPaths = new Set<string>();
|
|
@@ -1949,10 +1969,14 @@ async function collectExtensionModules(entryRealPath: string): Promise<Extension
|
|
|
1949
1969
|
let resolvedModuleKind: ExtensionModuleKind | undefined;
|
|
1950
1970
|
let resolvedEsmBranch = false;
|
|
1951
1971
|
let requiresNativeAddonRewrite = false;
|
|
1972
|
+
let requiresSynchronousSourceHook = false;
|
|
1973
|
+
let synchronousSourceUpgraded = false;
|
|
1952
1974
|
const isRequired = reference.kind === "require";
|
|
1953
1975
|
if (specifier.startsWith(".")) {
|
|
1954
|
-
const candidate =
|
|
1955
|
-
|
|
1976
|
+
const candidate = isRequired
|
|
1977
|
+
? await resolveRelativeCommonJsRequire(specifier, file)
|
|
1978
|
+
: Bun.resolveSync(specifier, dir);
|
|
1979
|
+
if (candidate && hasSourceModuleExtension(candidate)) {
|
|
1956
1980
|
const inheritedTargetKind = isRequired
|
|
1957
1981
|
? sourceIsCommonJs
|
|
1958
1982
|
? "commonjs"
|
|
@@ -1966,10 +1990,11 @@ async function collectExtensionModules(entryRealPath: string): Promise<Extension
|
|
|
1966
1990
|
const isCommonJsDescendant = isRequired && sourceIsCommonJs && targetIsCommonJs;
|
|
1967
1991
|
requiresNativeAddonRewrite =
|
|
1968
1992
|
isRequired && !isCommonJsDescendant && (await moduleRequiresNativeAddon(candidate));
|
|
1969
|
-
if (!isRequired || isCommonJsDescendant || requiresNativeAddonRewrite) {
|
|
1993
|
+
if (!isRequired || isCommonJsDescendant || requiresNativeAddonRewrite || !targetIsCommonJs) {
|
|
1970
1994
|
resolved = await realpathOrSelf(candidate);
|
|
1971
1995
|
resolvedModuleKind = targetIsCommonJs ? "commonjs" : "esm";
|
|
1972
1996
|
resolvedEsmBranch = !targetIsCommonJs && esmBranch;
|
|
1997
|
+
requiresSynchronousSourceHook = isRequired && !targetIsCommonJs;
|
|
1973
1998
|
}
|
|
1974
1999
|
}
|
|
1975
2000
|
} else if (specifier.startsWith("#")) {
|
|
@@ -1988,10 +2013,11 @@ async function collectExtensionModules(entryRealPath: string): Promise<Extension
|
|
|
1988
2013
|
const isCommonJsDescendant = isRequired && sourceIsCommonJs && targetIsCommonJs;
|
|
1989
2014
|
requiresNativeAddonRewrite =
|
|
1990
2015
|
isRequired && !isCommonJsDescendant && (await moduleRequiresNativeAddon(candidate));
|
|
1991
|
-
if (!isRequired || isCommonJsDescendant || requiresNativeAddonRewrite) {
|
|
2016
|
+
if (!isRequired || isCommonJsDescendant || requiresNativeAddonRewrite || !targetIsCommonJs) {
|
|
1992
2017
|
resolved = candidate;
|
|
1993
2018
|
resolvedModuleKind = targetIsCommonJs ? "commonjs" : "esm";
|
|
1994
2019
|
resolvedEsmBranch = !targetIsCommonJs && esmBranch;
|
|
2020
|
+
requiresSynchronousSourceHook = isRequired && !targetIsCommonJs;
|
|
1995
2021
|
}
|
|
1996
2022
|
}
|
|
1997
2023
|
} else if (
|
|
@@ -2022,6 +2048,9 @@ async function collectExtensionModules(entryRealPath: string): Promise<Extension
|
|
|
2022
2048
|
: false;
|
|
2023
2049
|
if (isHookableEntry && dependencyEntry && (!isRequired || (sourceIsCommonJs && isCommonJsEntry))) {
|
|
2024
2050
|
resolved = await realpathOrSelf(dependencyEntry);
|
|
2051
|
+
} else if (isHookableEntry && dependencyEntry && isRequired && !isCommonJsEntry) {
|
|
2052
|
+
resolved = await realpathOrSelf(dependencyEntry);
|
|
2053
|
+
requiresSynchronousSourceHook = true;
|
|
2025
2054
|
} else if (isHookableEntry && dependencyEntry && isRequired) {
|
|
2026
2055
|
requiresNativeAddonRewrite = await moduleRequiresNativeAddon(dependencyEntry);
|
|
2027
2056
|
if (requiresNativeAddonRewrite) {
|
|
@@ -2034,26 +2063,37 @@ async function collectExtensionModules(entryRealPath: string): Promise<Extension
|
|
|
2034
2063
|
}
|
|
2035
2064
|
nextCacheBustResolvedImports = false;
|
|
2036
2065
|
}
|
|
2037
|
-
if (
|
|
2038
|
-
|
|
2066
|
+
if (
|
|
2067
|
+
resolved &&
|
|
2068
|
+
(requiresNativeAddonRewrite ||
|
|
2069
|
+
requiresSynchronousSourceHook ||
|
|
2070
|
+
(synchronousSourcePaths.has(file) && resolvedModuleKind === "esm"))
|
|
2071
|
+
) {
|
|
2072
|
+
synchronousSourceUpgraded = !synchronousSourcePaths.has(resolved);
|
|
2073
|
+
synchronousSourcePaths.add(resolved);
|
|
2039
2074
|
}
|
|
2040
2075
|
if (resolved) {
|
|
2041
2076
|
const queuedCacheBust = queuedCacheBustResolvedImports.get(resolved) ?? false;
|
|
2042
2077
|
const mergedCacheBust = queuedCacheBust || nextCacheBustResolvedImports;
|
|
2043
2078
|
queuedCacheBustResolvedImports.set(resolved, mergedCacheBust);
|
|
2044
2079
|
const queuedModuleKind = queuedModuleKinds.get(resolved);
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2080
|
+
const mergedEsmBranch = queuedEsmBranchPaths.has(resolved) || resolvedEsmBranch;
|
|
2081
|
+
const mergedModuleKind =
|
|
2082
|
+
queuedModuleKind && resolvedModuleKind && queuedModuleKind !== resolvedModuleKind
|
|
2083
|
+
? mergedEsmBranch
|
|
2084
|
+
? "esm"
|
|
2085
|
+
: "commonjs"
|
|
2086
|
+
: (queuedModuleKind ?? resolvedModuleKind);
|
|
2051
2087
|
if (mergedModuleKind) {
|
|
2052
2088
|
queuedModuleKinds.set(resolved, mergedModuleKind);
|
|
2053
2089
|
}
|
|
2054
|
-
if (
|
|
2090
|
+
if (mergedEsmBranch) {
|
|
2055
2091
|
queuedEsmBranchPaths.add(resolved);
|
|
2056
2092
|
}
|
|
2093
|
+
if (modules.has(resolved) && (queuedModuleKind !== mergedModuleKind || synchronousSourceUpgraded)) {
|
|
2094
|
+
modules.delete(resolved);
|
|
2095
|
+
commonJsPaths.delete(resolved);
|
|
2096
|
+
}
|
|
2057
2097
|
if (!modules.has(resolved)) {
|
|
2058
2098
|
queue.push({
|
|
2059
2099
|
file: resolved,
|
|
@@ -2063,22 +2103,22 @@ async function collectExtensionModules(entryRealPath: string): Promise<Extension
|
|
|
2063
2103
|
});
|
|
2064
2104
|
}
|
|
2065
2105
|
}
|
|
2066
|
-
} catch
|
|
2067
|
-
if (error instanceof ExtensionModuleKindConflictError) {
|
|
2068
|
-
throw error;
|
|
2069
|
-
}
|
|
2106
|
+
} catch {
|
|
2070
2107
|
// Unresolvable import (e.g. a type-only path); skip it.
|
|
2071
2108
|
}
|
|
2072
2109
|
}
|
|
2073
2110
|
}
|
|
2074
2111
|
for (const [modulePath, source] of modules) {
|
|
2075
|
-
if (commonJsPaths.has(modulePath)
|
|
2076
|
-
modules.set(modulePath, await rewriteExtensionSpecifiers(source, modulePath,
|
|
2112
|
+
if (commonJsPaths.has(modulePath)) {
|
|
2113
|
+
modules.set(modulePath, await rewriteExtensionSpecifiers(source, modulePath, true));
|
|
2114
|
+
} else if (synchronousSourcePaths.has(modulePath)) {
|
|
2115
|
+
modules.set(modulePath, await rewriteLegacyExtensionSource(source, modulePath));
|
|
2077
2116
|
}
|
|
2078
2117
|
}
|
|
2079
2118
|
return {
|
|
2080
2119
|
modules,
|
|
2081
2120
|
commonJsPaths,
|
|
2121
|
+
synchronousSourcePaths,
|
|
2082
2122
|
cacheBustResolvedImportModules: new Set(
|
|
2083
2123
|
[...queuedCacheBustResolvedImports]
|
|
2084
2124
|
.filter(([modulePath, enabled]) => enabled && modules.has(modulePath))
|
|
@@ -2087,6 +2127,15 @@ async function collectExtensionModules(entryRealPath: string): Promise<Extension
|
|
|
2087
2127
|
};
|
|
2088
2128
|
}
|
|
2089
2129
|
|
|
2130
|
+
/** Test seam for compiled-binary dependency graph discovery and rewriting. */
|
|
2131
|
+
export async function __collectLegacyPiExtensionSourcesForTests(
|
|
2132
|
+
entryPath: string,
|
|
2133
|
+
): Promise<ReadonlyMap<string, string>> {
|
|
2134
|
+
const entryRealPath = await realpathOrSelf(path.resolve(entryPath));
|
|
2135
|
+
const graph = await collectExtensionModules(entryRealPath);
|
|
2136
|
+
return graph.modules;
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2090
2139
|
/**
|
|
2091
2140
|
* Discovers CommonJS export names Bun normally exposes to ESM importers. The
|
|
2092
2141
|
* bridge must declare them statically because its default export is synthetic.
|
|
@@ -2252,19 +2301,15 @@ async function installExtensionGraphHook(
|
|
|
2252
2301
|
entryRealPath: string,
|
|
2253
2302
|
modules: Map<string, string>,
|
|
2254
2303
|
commonJsPaths: Set<string>,
|
|
2304
|
+
synchronousSourcePaths: ReadonlySet<string>,
|
|
2255
2305
|
cacheBustResolvedImportModules: ReadonlySet<string>,
|
|
2256
|
-
): Promise<{ asyncModules: Map<string, string
|
|
2306
|
+
): Promise<{ asyncModules: Map<string, string> }> {
|
|
2257
2307
|
const asyncModules = new Map<string, string>();
|
|
2258
|
-
const syncSourceModules = new Map<string, string>();
|
|
2259
2308
|
for (const [modulePath, source] of modules) {
|
|
2260
|
-
if (commonJsPaths.has(modulePath)) {
|
|
2309
|
+
if (commonJsPaths.has(modulePath) || synchronousSourcePaths.has(modulePath)) {
|
|
2261
2310
|
continue;
|
|
2262
2311
|
}
|
|
2263
|
-
|
|
2264
|
-
syncSourceModules.set(modulePath, source);
|
|
2265
|
-
} else {
|
|
2266
|
-
asyncModules.set(modulePath, source);
|
|
2267
|
-
}
|
|
2312
|
+
asyncModules.set(modulePath, source);
|
|
2268
2313
|
}
|
|
2269
2314
|
|
|
2270
2315
|
if (asyncModules.size > 0) {
|
|
@@ -2274,24 +2319,35 @@ async function installExtensionGraphHook(
|
|
|
2274
2319
|
Bun.plugin({
|
|
2275
2320
|
name: `omp:legacy-pi-ext:${hookId}`,
|
|
2276
2321
|
setup(build) {
|
|
2277
|
-
build.onLoad({ filter, namespace: "file" },
|
|
2322
|
+
build.onLoad({ filter, namespace: "file" }, args => {
|
|
2278
2323
|
const queryIndex = args.path.indexOf("?mtime=");
|
|
2279
2324
|
const sourcePath = queryIndex >= 0 ? args.path.slice(0, queryIndex) : args.path;
|
|
2280
2325
|
const mtimeTag = queryIndex >= 0 ? args.path.slice(queryIndex + "?mtime=".length) : null;
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2326
|
+
// A later reload can upgrade this module to synchronous loading (a
|
|
2327
|
+
// new `require()` edge reaches it) without re-registering hooks:
|
|
2328
|
+
// this filter keeps matching and `require()` rejects async onLoad
|
|
2329
|
+
// results, so serve the pre-rewritten synchronous source inline.
|
|
2330
|
+
// `ensureExtensionGraphHook` refreshes it on every (re)load.
|
|
2331
|
+
const synchronousSource = synchronousModuleSources.get(sourcePath);
|
|
2332
|
+
if (synchronousSource !== undefined) {
|
|
2333
|
+
return { contents: synchronousSource, loader: getLoader(sourcePath) };
|
|
2289
2334
|
}
|
|
2335
|
+
const cached = asyncModules.get(sourcePath);
|
|
2290
2336
|
const resolvedImportMtimeTag = cacheBustResolvedImportModules.has(sourcePath) ? mtimeTag : null;
|
|
2291
|
-
return {
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2337
|
+
return (async () => {
|
|
2338
|
+
let raw: string;
|
|
2339
|
+
if (cached !== undefined) {
|
|
2340
|
+
// consume-once: preserves ?mtime edit-pickup for re-imports
|
|
2341
|
+
asyncModules.delete(sourcePath);
|
|
2342
|
+
raw = cached;
|
|
2343
|
+
} else {
|
|
2344
|
+
raw = await Bun.file(sourcePath).text();
|
|
2345
|
+
}
|
|
2346
|
+
return {
|
|
2347
|
+
contents: await rewriteLegacyExtensionSource(raw, sourcePath, mtimeTag, resolvedImportMtimeTag),
|
|
2348
|
+
loader: getLoader(sourcePath),
|
|
2349
|
+
};
|
|
2350
|
+
})();
|
|
2295
2351
|
});
|
|
2296
2352
|
},
|
|
2297
2353
|
});
|
|
@@ -2319,28 +2375,26 @@ async function installExtensionGraphHook(
|
|
|
2319
2375
|
});
|
|
2320
2376
|
}
|
|
2321
2377
|
|
|
2322
|
-
if (
|
|
2323
|
-
const alternation = [...
|
|
2378
|
+
if (synchronousSourcePaths.size > 0) {
|
|
2379
|
+
const alternation = [...synchronousSourcePaths].map(escapeRegExp).join("|");
|
|
2324
2380
|
const filter = new RegExp(`^(?:${alternation})(?:\\?mtime=\\d+)?$`);
|
|
2325
|
-
const hookId = Bun.hash(`${entryRealPath}\0sync-source\0${[...
|
|
2326
|
-
36,
|
|
2327
|
-
);
|
|
2381
|
+
const hookId = Bun.hash(`${entryRealPath}\0sync-source\0${[...synchronousSourcePaths].join("\0")}`).toString(36);
|
|
2328
2382
|
Bun.plugin({
|
|
2329
2383
|
name: `omp:legacy-pi-ext:${hookId}`,
|
|
2330
2384
|
setup(build) {
|
|
2331
2385
|
build.onLoad({ filter, namespace: "file" }, args => {
|
|
2332
2386
|
const queryIndex = args.path.indexOf("?mtime=");
|
|
2333
2387
|
const sourcePath = queryIndex >= 0 ? args.path.slice(0, queryIndex) : args.path;
|
|
2334
|
-
const source =
|
|
2388
|
+
const source = synchronousModuleSources.get(sourcePath);
|
|
2335
2389
|
if (source === undefined) {
|
|
2336
|
-
throw new Error(`Missing pre-rewritten
|
|
2390
|
+
throw new Error(`Missing pre-rewritten synchronous extension source: ${sourcePath}`);
|
|
2337
2391
|
}
|
|
2338
2392
|
return { contents: source, loader: getLoader(sourcePath) };
|
|
2339
2393
|
});
|
|
2340
2394
|
},
|
|
2341
2395
|
});
|
|
2342
2396
|
}
|
|
2343
|
-
return { asyncModules
|
|
2397
|
+
return { asyncModules };
|
|
2344
2398
|
}
|
|
2345
2399
|
|
|
2346
2400
|
/**
|
|
@@ -2356,6 +2410,7 @@ async function ensureExtensionGraphHook(entryRealPath: string): Promise<{ clear(
|
|
|
2356
2410
|
modules: currentModules,
|
|
2357
2411
|
commonJsPaths,
|
|
2358
2412
|
cacheBustResolvedImportModules: discoveredCacheBustModules,
|
|
2413
|
+
synchronousSourcePaths,
|
|
2359
2414
|
} = await collectExtensionModules(entryRealPath);
|
|
2360
2415
|
let cacheBustResolvedImportModules = extensionGraphCacheBustResolvedImportModules.get(entryRealPath);
|
|
2361
2416
|
if (!cacheBustResolvedImportModules) {
|
|
@@ -2370,6 +2425,15 @@ async function ensureExtensionGraphHook(entryRealPath: string): Promise<{ clear(
|
|
|
2370
2425
|
commonJsModuleSources.set(modulePath, await prepareCommonJsDefaultModule(modulePath, source));
|
|
2371
2426
|
commonJsGraphModulePaths.add(modulePath);
|
|
2372
2427
|
}
|
|
2428
|
+
if (synchronousSourcePaths.has(modulePath)) {
|
|
2429
|
+
synchronousModuleSources.set(modulePath, source);
|
|
2430
|
+
} else if (synchronousModuleSources.has(modulePath)) {
|
|
2431
|
+
// The path lost its require() edges on this walk, but the permanent
|
|
2432
|
+
// hooks installed while it was synchronous still serve it from this
|
|
2433
|
+
// map — keep the pre-rewritten bytes fresh instead of serving the
|
|
2434
|
+
// stale snapshot from the walk that flagged it.
|
|
2435
|
+
synchronousModuleSources.set(modulePath, await rewriteLegacyExtensionSource(source, modulePath));
|
|
2436
|
+
}
|
|
2373
2437
|
}
|
|
2374
2438
|
let hookedModules = extensionGraphHookModules.get(entryRealPath);
|
|
2375
2439
|
if (!hookedModules) {
|
|
@@ -2379,12 +2443,16 @@ async function ensureExtensionGraphHook(entryRealPath: string): Promise<{ clear(
|
|
|
2379
2443
|
|
|
2380
2444
|
const pendingModules = new Map<string, string>();
|
|
2381
2445
|
const pendingCommonJsPaths = new Set<string>();
|
|
2446
|
+
const pendingSynchronousSourcePaths = new Set<string>();
|
|
2382
2447
|
for (const [modulePath, source] of currentModules) {
|
|
2383
2448
|
if (!hookedModules.has(modulePath)) {
|
|
2384
2449
|
pendingModules.set(modulePath, source);
|
|
2385
2450
|
if (commonJsPaths.has(modulePath)) {
|
|
2386
2451
|
pendingCommonJsPaths.add(modulePath);
|
|
2387
2452
|
}
|
|
2453
|
+
if (synchronousSourcePaths.has(modulePath)) {
|
|
2454
|
+
pendingSynchronousSourcePaths.add(modulePath);
|
|
2455
|
+
}
|
|
2388
2456
|
}
|
|
2389
2457
|
}
|
|
2390
2458
|
if (pendingModules.size === 0 && commonJsPaths.size === 0) {
|
|
@@ -2392,12 +2460,12 @@ async function ensureExtensionGraphHook(entryRealPath: string): Promise<{ clear(
|
|
|
2392
2460
|
}
|
|
2393
2461
|
|
|
2394
2462
|
let asyncModules = new Map<string, string>();
|
|
2395
|
-
let syncSourceModules = new Map<string, string>();
|
|
2396
2463
|
if (pendingModules.size > 0) {
|
|
2397
|
-
({ asyncModules
|
|
2464
|
+
({ asyncModules } = await installExtensionGraphHook(
|
|
2398
2465
|
entryRealPath,
|
|
2399
2466
|
pendingModules,
|
|
2400
2467
|
pendingCommonJsPaths,
|
|
2468
|
+
pendingSynchronousSourcePaths,
|
|
2401
2469
|
cacheBustResolvedImportModules,
|
|
2402
2470
|
));
|
|
2403
2471
|
for (const modulePath of pendingModules.keys()) {
|
|
@@ -2407,7 +2475,6 @@ async function ensureExtensionGraphHook(entryRealPath: string): Promise<{ clear(
|
|
|
2407
2475
|
return {
|
|
2408
2476
|
clear() {
|
|
2409
2477
|
asyncModules.clear();
|
|
2410
|
-
syncSourceModules.clear();
|
|
2411
2478
|
for (const modulePath of commonJsPaths) {
|
|
2412
2479
|
commonJsModuleSources.delete(modulePath);
|
|
2413
2480
|
commonJsModuleDefinitions.delete(modulePath);
|
|
@@ -302,6 +302,17 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
|
|
|
302
302
|
|
|
303
303
|
const existing = skillMap.get(skill.name);
|
|
304
304
|
if (existing) {
|
|
305
|
+
// A skill name claimed by a DEFAULT-path provider (e.g.
|
|
306
|
+
// ~/.claude/skills/<name>) yields to the explicitly configured
|
|
307
|
+
// skills.customDirectories entry — the user's custom dir is the
|
|
308
|
+
// higher-priority source (issue #7190). Only same-source custom
|
|
309
|
+
// duplicates keep first-wins.
|
|
310
|
+
const isCustomExisting = existing.source.startsWith("custom:");
|
|
311
|
+
if (!isCustomExisting) {
|
|
312
|
+
skillMap.set(skill.name, skill);
|
|
313
|
+
realPathSet.add(resolvedPath);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
305
316
|
collisionWarnings.push({
|
|
306
317
|
skillPath: skill.filePath,
|
|
307
318
|
message: `name collision: "${skill.name}" already loaded from ${existing.filePath}, skipping this one`,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
+
import { postmortem } from "@oh-my-pi/pi-utils";
|
|
2
3
|
import { theme } from "../modes/theme/theme";
|
|
3
4
|
import { expandPath, normalizeLocalScheme } from "../tools/path-utils";
|
|
4
5
|
import type { HookUIContext } from "./hooks/types";
|
|
@@ -115,12 +116,19 @@ function guardedExit(alias: ExitAliasName): (code?: number | string) => never {
|
|
|
115
116
|
|
|
116
117
|
export async function withHostGuard<T>(fn: () => Promise<T>): Promise<T> {
|
|
117
118
|
if (hostGuardDepth === 0) {
|
|
119
|
+
// Stamp each throwing replacement with the native primitive it shadows so
|
|
120
|
+
// host-owned shutdown (postmortem's signal/fatal handlers) can still exit
|
|
121
|
+
// through the real exit even while this guard window is open (#6488).
|
|
118
122
|
hostGuardOriginalProcessExit = process.exit;
|
|
119
|
-
|
|
123
|
+
const processExitGuard = guardedExit("process.exit") as typeof process.exit;
|
|
124
|
+
Reflect.set(processExitGuard, postmortem.NATIVE_PROCESS_EXIT, hostGuardOriginalProcessExit);
|
|
125
|
+
process.exit = processExitGuard;
|
|
120
126
|
|
|
121
127
|
if (typeof process.reallyExit === "function") {
|
|
122
128
|
hostGuardOriginalReallyExit = process.reallyExit;
|
|
123
|
-
|
|
129
|
+
const reallyExitGuard = guardedExit("process.reallyExit") as typeof process.reallyExit;
|
|
130
|
+
Reflect.set(reallyExitGuard, postmortem.NATIVE_PROCESS_EXIT, hostGuardOriginalReallyExit);
|
|
131
|
+
process.reallyExit = reallyExitGuard;
|
|
124
132
|
}
|
|
125
133
|
|
|
126
134
|
const stdin = process.stdin;
|