@oh-my-pi/pi-coding-agent 15.10.10 → 15.10.11
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 +95 -4
- package/dist/cli.js +23087 -0
- package/dist/tokenizers.linux-x64-gnu-xcjh3jwk.node +0 -0
- package/dist/types/async/job-manager.d.ts +18 -0
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/cli/dry-balance-cli.d.ts +1 -1
- package/dist/types/cli/gallery-cli.d.ts +1 -1
- package/dist/types/cli/gallery-fixtures/types.d.ts +1 -1
- package/dist/types/cli/usage-cli.d.ts +72 -0
- package/dist/types/commands/launch.d.ts +1 -1
- package/dist/types/commands/read.d.ts +1 -1
- package/dist/types/commands/usage.d.ts +25 -0
- package/dist/types/config/append-only-context-mode.d.ts +2 -1
- package/dist/types/config/model-discovery.d.ts +55 -0
- package/dist/types/config/model-registry.d.ts +7 -219
- package/dist/types/config/model-resolver.d.ts +16 -10
- package/dist/types/config/model-roles.d.ts +28 -0
- package/dist/types/config/models-config-schema.d.ts +523 -42
- package/dist/types/config/models-config.d.ts +385 -0
- package/dist/types/config/settings-schema.d.ts +12 -7
- package/dist/types/config/settings.d.ts +1 -1
- package/dist/types/debug/log-viewer.d.ts +1 -1
- package/dist/types/debug/raw-sse.d.ts +1 -1
- package/dist/types/eval/backend.d.ts +0 -2
- package/dist/types/eval/idle-timeout.d.ts +0 -4
- package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/extensions/types.d.ts +3 -3
- package/dist/types/hindsight/mental-models.d.ts +17 -8
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/lsp/edits.d.ts +9 -0
- package/dist/types/lsp/index.d.ts +2 -2
- package/dist/types/lsp/types.d.ts +2 -0
- package/dist/types/lsp/utils.d.ts +3 -0
- package/dist/types/mcp/json-rpc.d.ts +5 -0
- package/dist/types/mnemopi/state.d.ts +11 -1
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/bash-execution.d.ts +1 -1
- package/dist/types/modes/components/copy-selector.d.ts +1 -1
- package/dist/types/modes/components/dynamic-border.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
- package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
- package/dist/types/modes/components/footer.d.ts +1 -1
- package/dist/types/modes/components/hook-editor.d.ts +5 -0
- package/dist/types/modes/components/hook-input.d.ts +4 -0
- package/dist/types/modes/components/hook-selector.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +1 -1
- package/dist/types/modes/components/plan-review-overlay.d.ts +1 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +1 -1
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/component.d.ts +1 -1
- package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
- package/dist/types/modes/components/transcript-container.d.ts +25 -6
- package/dist/types/modes/components/tree-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message.d.ts +2 -1
- package/dist/types/modes/components/visual-truncate.d.ts +1 -1
- package/dist/types/modes/components/welcome.d.ts +19 -3
- package/dist/types/modes/controllers/mcp-command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/streaming-reveal.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/types.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
- package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
- package/dist/types/modes/types.d.ts +2 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/auth-broker-config.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +1 -1
- package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
- package/dist/types/ssh/connection-manager.d.ts +8 -0
- package/dist/types/task/parallel.d.ts +2 -2
- package/dist/types/task/worktree.d.ts +2 -0
- package/dist/types/tools/ask.d.ts +4 -0
- package/dist/types/tools/conflict-detect.d.ts +16 -0
- package/dist/types/tools/github-cache.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +3 -0
- package/dist/types/tui/output-block.d.ts +3 -3
- package/dist/types/utils/changelog.d.ts +8 -0
- package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
- package/dist/types/web/scrapers/types.d.ts +12 -0
- package/dist/types/web/search/providers/codex.d.ts +1 -1
- package/dist/types/web/search/providers/gemini.d.ts +1 -1
- package/examples/extensions/tools.ts +5 -4
- package/package.json +14 -11
- package/scripts/build-binary.ts +18 -23
- package/scripts/bundle-dist.ts +81 -0
- package/scripts/{dev-launch → omp} +1 -1
- package/scripts/{dev-launch-preload.ts → omp.ts} +1 -1
- package/src/async/job-manager.ts +57 -3
- package/src/autoresearch/dashboard.ts +1 -1
- package/src/autoresearch/prompt-setup.md +6 -6
- package/src/autoresearch/prompt.md +6 -6
- package/src/capability/fs.ts +10 -0
- package/src/cli/args.ts +1 -1
- package/src/cli/auth-gateway-cli.ts +1 -3
- package/src/cli/dry-balance-cli.ts +1 -1
- package/src/cli/gallery-cli.ts +1 -1
- package/src/cli/gallery-fixtures/fs.ts +1 -1
- package/src/cli/gallery-fixtures/types.ts +5 -1
- package/src/cli/list-models.ts +2 -1
- package/src/cli/usage-cli.ts +603 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +69 -5
- package/src/commands/complete.ts +1 -1
- package/src/commands/launch.ts +1 -1
- package/src/commands/read.ts +6 -3
- package/src/commands/usage.ts +35 -0
- package/src/commit/agentic/agent.ts +1 -1
- package/src/commit/model-selection.ts +1 -1
- package/src/config/append-only-context-mode.ts +6 -12
- package/src/config/model-discovery.ts +554 -0
- package/src/config/model-registry.ts +231 -1019
- package/src/config/model-resolver.ts +113 -156
- package/src/config/model-roles.ts +74 -0
- package/src/config/models-config-schema.ts +57 -8
- package/src/config/models-config.ts +129 -0
- package/src/config/settings-schema.ts +18 -4
- package/src/config/settings.ts +37 -1
- package/src/dap/client.ts +124 -37
- package/src/dap/session.ts +259 -158
- package/src/debug/log-viewer.ts +1 -1
- package/src/debug/raw-sse.ts +1 -1
- package/src/edit/diff.ts +47 -3
- package/src/edit/hashline/block-resolver.ts +20 -1
- package/src/edit/hashline/diff.ts +36 -1
- package/src/edit/hashline/execute.ts +8 -2
- package/src/edit/index.ts +16 -1
- package/src/edit/modes/patch.ts +52 -0
- package/src/edit/modes/replace.ts +56 -22
- package/src/edit/notebook.ts +22 -2
- package/src/edit/renderer.ts +36 -10
- package/src/eval/__tests__/completion-bridge.test.ts +1 -1
- package/src/eval/backend.ts +0 -2
- package/src/eval/completion-bridge.ts +2 -1
- package/src/eval/idle-timeout.ts +2 -9
- package/src/eval/js/context-manager.ts +6 -8
- package/src/eval/js/executor.ts +6 -2
- package/src/eval/js/index.ts +0 -2
- package/src/eval/js/shared/helpers.ts +5 -6
- package/src/eval/js/shared/local-module-loader.ts +1 -1
- package/src/eval/js/shared/prelude.txt +62 -1
- package/src/eval/js/shared/rewrite-imports.ts +40 -22
- package/src/eval/js/shared/runtime.ts +1 -1
- package/src/eval/py/index.ts +0 -2
- package/src/eval/py/kernel.ts +19 -0
- package/src/eval/py/runner.py +107 -3
- package/src/exec/bash-executor.ts +3 -1
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +3 -1
- package/src/extensibility/extensions/types.ts +3 -2
- package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
- package/src/hindsight/mental-models.ts +59 -12
- package/src/hindsight/state.ts +6 -1
- package/src/internal-urls/artifact-protocol.ts +11 -2
- package/src/internal-urls/docs-index.generated.ts +8 -8
- package/src/internal-urls/issue-pr-protocol.ts +12 -5
- package/src/internal-urls/router.ts +1 -1
- package/src/internal-urls/types.ts +1 -1
- package/src/lib/xai-http.ts +1 -1
- package/src/lsp/client.ts +118 -38
- package/src/lsp/clients/biome-client.ts +101 -39
- package/src/lsp/edits.ts +143 -95
- package/src/lsp/index.ts +31 -22
- package/src/lsp/render.ts +1 -1
- package/src/lsp/types.ts +2 -0
- package/src/lsp/utils.ts +28 -10
- package/src/main.ts +165 -17
- package/src/mcp/json-rpc.ts +35 -5
- package/src/mcp/transports/stdio.ts +7 -1
- package/src/memories/index.ts +2 -1
- package/src/mnemopi/backend.ts +25 -3
- package/src/mnemopi/state.ts +38 -2
- package/src/modes/components/agent-dashboard.ts +10 -7
- package/src/modes/components/assistant-message.ts +19 -13
- package/src/modes/components/bash-execution.ts +1 -1
- package/src/modes/components/copy-selector.ts +1 -1
- package/src/modes/components/diff.ts +13 -2
- package/src/modes/components/dynamic-border.ts +12 -3
- package/src/modes/components/extensions/extension-dashboard.ts +8 -5
- package/src/modes/components/extensions/extension-list.ts +1 -1
- package/src/modes/components/extensions/inspector-panel.ts +1 -1
- package/src/modes/components/footer.ts +1 -1
- package/src/modes/components/history-search.ts +1 -1
- package/src/modes/components/hook-editor.ts +8 -0
- package/src/modes/components/hook-input.ts +8 -0
- package/src/modes/components/hook-selector.ts +2 -2
- package/src/modes/components/model-selector.ts +4 -2
- package/src/modes/components/plan-review-overlay.ts +1 -1
- package/src/modes/components/session-observer-overlay.ts +2 -2
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-selector.ts +5 -1
- package/src/modes/components/status-line/component.ts +1 -1
- package/src/modes/components/tiny-title-download-progress.ts +1 -1
- package/src/modes/components/transcript-container.ts +258 -53
- package/src/modes/components/tree-selector.ts +3 -3
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +17 -5
- package/src/modes/components/visual-truncate.ts +1 -1
- package/src/modes/components/welcome.ts +108 -26
- package/src/modes/controllers/command-controller.ts +10 -3
- package/src/modes/controllers/event-controller.ts +73 -4
- package/src/modes/controllers/input-controller.ts +1 -1
- package/src/modes/controllers/mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/controllers/streaming-reveal.ts +85 -18
- package/src/modes/interactive-mode.ts +3 -9
- package/src/modes/setup-wizard/scenes/glyph.ts +1 -1
- package/src/modes/setup-wizard/scenes/providers.ts +1 -1
- package/src/modes/setup-wizard/scenes/sign-in.ts +1 -1
- package/src/modes/setup-wizard/scenes/theme.ts +1 -1
- package/src/modes/setup-wizard/scenes/types.ts +1 -1
- package/src/modes/setup-wizard/scenes/web-search.ts +1 -1
- package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/types.ts +2 -1
- package/src/prompts/agents/explore.md +2 -2
- package/src/prompts/agents/librarian.md +1 -2
- package/src/prompts/agents/oracle.md +1 -1
- package/src/prompts/agents/plan.md +5 -5
- package/src/prompts/agents/task.md +5 -5
- package/src/prompts/ci-green-request.md +5 -7
- package/src/prompts/goals/goal-budget-limit.md +2 -2
- package/src/prompts/goals/goal-continuation.md +4 -4
- package/src/prompts/goals/goal-mode-active.md +1 -1
- package/src/prompts/memories/read-path.md +1 -1
- package/src/prompts/memories/stage_one_system.md +2 -2
- package/src/prompts/review-custom-request.md +1 -1
- package/src/prompts/system/agent-creation-architect.md +2 -2
- package/src/prompts/system/auto-continue.md +1 -1
- package/src/prompts/system/background-tan-dispatch.md +1 -1
- package/src/prompts/system/btw-user.md +2 -2
- package/src/prompts/system/commit-message-system.md +13 -1
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/eager-todo.md +2 -2
- package/src/prompts/system/irc-incoming.md +1 -1
- package/src/prompts/system/manual-continue.md +1 -1
- package/src/prompts/system/omfg-user.md +3 -4
- package/src/prompts/system/orchestrate-notice.md +9 -9
- package/src/prompts/system/plan-mode-active.md +4 -4
- package/src/prompts/system/plan-mode-subagent.md +4 -5
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
- package/src/prompts/system/project-prompt.md +2 -2
- package/src/prompts/system/subagent-system-prompt.md +4 -4
- package/src/prompts/system/system-prompt.md +13 -24
- package/src/prompts/system/title-system.md +2 -2
- package/src/prompts/system/ttsr-tool-reminder.md +1 -1
- package/src/prompts/system/workflow-notice.md +1 -1
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/prompts/tools/ast-grep.md +2 -2
- package/src/prompts/tools/bash.md +5 -7
- package/src/prompts/tools/browser.md +7 -7
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/eval.md +3 -3
- package/src/prompts/tools/find.md +0 -1
- package/src/prompts/tools/github.md +8 -7
- package/src/prompts/tools/goal.md +1 -1
- package/src/prompts/tools/image-gen.md +1 -1
- package/src/prompts/tools/inspect-image-system.md +1 -1
- package/src/prompts/tools/irc.md +15 -15
- package/src/prompts/tools/lsp.md +2 -2
- package/src/prompts/tools/patch.md +2 -2
- package/src/prompts/tools/read.md +3 -4
- package/src/prompts/tools/recall.md +1 -1
- package/src/prompts/tools/reflect.md +1 -1
- package/src/prompts/tools/render-mermaid.md +2 -2
- package/src/prompts/tools/replace.md +4 -10
- package/src/prompts/tools/rewind.md +2 -2
- package/src/prompts/tools/search-tool-bm25.md +1 -9
- package/src/prompts/tools/search.md +0 -1
- package/src/prompts/tools/ssh.md +0 -4
- package/src/prompts/tools/task.md +2 -3
- package/src/prompts/tools/todo.md +1 -1
- package/src/sdk.ts +23 -10
- package/src/session/agent-session.ts +44 -10
- package/src/session/auth-broker-config.ts +30 -1
- package/src/session/session-manager.ts +2 -2
- package/src/session/streaming-output.ts +23 -2
- package/src/slash-commands/builtin-registry.ts +20 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/ssh/connection-manager.ts +27 -0
- package/src/task/commands.ts +2 -1
- package/src/task/executor.ts +61 -53
- package/src/task/index.ts +137 -60
- package/src/task/parallel.ts +3 -3
- package/src/task/render.ts +2 -2
- package/src/task/worktree.ts +64 -56
- package/src/thinking.ts +2 -1
- package/src/tiny/title-client.ts +26 -11
- package/src/tools/archive-reader.ts +30 -2
- package/src/tools/ask.ts +104 -21
- package/src/tools/ast-edit.ts +25 -5
- package/src/tools/auto-generated-guard.ts +20 -3
- package/src/tools/bash-interactive.ts +27 -7
- package/src/tools/bash.ts +54 -13
- package/src/tools/browser/launch.ts +11 -2
- package/src/tools/browser/readable.ts +19 -2
- package/src/tools/browser/registry.ts +4 -1
- package/src/tools/browser/render.ts +2 -2
- package/src/tools/browser/tab-supervisor.ts +55 -16
- package/src/tools/conflict-detect.ts +50 -4
- package/src/tools/debug.ts +1 -1
- package/src/tools/eval-render.ts +5 -5
- package/src/tools/eval.ts +0 -2
- package/src/tools/fetch.ts +33 -10
- package/src/tools/gh-cache-invalidation.ts +63 -8
- package/src/tools/gh-renderer.ts +1 -1
- package/src/tools/gh.ts +172 -29
- package/src/tools/github-cache.ts +70 -6
- package/src/tools/image-gen.ts +3 -9
- package/src/tools/irc.ts +5 -1
- package/src/tools/job.ts +1 -1
- package/src/tools/read.ts +202 -61
- package/src/tools/render-utils.ts +3 -3
- package/src/tools/resolve.ts +1 -1
- package/src/tools/search.ts +92 -29
- package/src/tools/sqlite-reader.ts +17 -5
- package/src/tools/ssh.ts +8 -8
- package/src/tools/todo.ts +38 -8
- package/src/tools/write.ts +118 -18
- package/src/tui/output-block.ts +4 -4
- package/src/utils/changelog.ts +27 -1
- package/src/utils/file-mentions.ts +2 -1
- package/src/web/scrapers/arxiv.ts +1 -1
- package/src/web/scrapers/go-pkg.ts +1 -1
- package/src/web/scrapers/iacr.ts +1 -1
- package/src/web/scrapers/readthedocs.ts +1 -1
- package/src/web/scrapers/twitter.ts +2 -1
- package/src/web/scrapers/types.ts +87 -8
- package/src/web/scrapers/wikipedia.ts +1 -1
- package/src/web/scrapers/youtube.ts +6 -1
- package/src/web/search/index.ts +1 -1
- package/src/web/search/providers/codex.ts +2 -1
- package/src/web/search/providers/gemini.ts +2 -3
- package/src/web/search/render.ts +8 -6
- package/dist/types/config/model-equivalence.d.ts +0 -24
- package/dist/types/config/model-id-affixes.d.ts +0 -12
- package/dist/types/config/model-provider-priority.d.ts +0 -1
- package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
- package/src/config/model-equivalence.ts +0 -875
- package/src/config/model-id-affixes.ts +0 -81
- package/src/config/model-provider-priority.ts +0 -56
- package/src/exec/idle-timeout-watchdog.ts +0 -126
|
@@ -90,15 +90,25 @@ if (!globalThis.__omp_js_prelude_loaded__) {
|
|
|
90
90
|
const limit = await __concurrencyLimit();
|
|
91
91
|
const concurrency = limit > 0 ? Math.min(limit, list.length) : list.length;
|
|
92
92
|
const results = new Array(list.length);
|
|
93
|
+
// Barrier semantics (mirrors the Python _pool_map): every item settles
|
|
94
|
+
// before we return or throw, then the lowest-index error propagates.
|
|
95
|
+
// Early-rejecting would orphan in-flight thunks (e.g. live agent()
|
|
96
|
+
// subagents) whose worker-side promises would never be observed.
|
|
97
|
+
const errors = new Map();
|
|
93
98
|
let next = 0;
|
|
94
99
|
const worker = async () => {
|
|
95
100
|
while (true) {
|
|
96
101
|
const index = next++;
|
|
97
102
|
if (index >= list.length) return;
|
|
98
|
-
|
|
103
|
+
try {
|
|
104
|
+
results[index] = await fn(list[index], index);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
errors.set(index, error);
|
|
107
|
+
}
|
|
99
108
|
}
|
|
100
109
|
};
|
|
101
110
|
await Promise.all(Array.from({ length: concurrency }, () => worker()));
|
|
111
|
+
if (errors.size > 0) throw errors.get(Math.min(...errors.keys()));
|
|
102
112
|
return results;
|
|
103
113
|
};
|
|
104
114
|
|
|
@@ -148,6 +158,8 @@ if (!globalThis.__omp_js_prelude_loaded__) {
|
|
|
148
158
|
|
|
149
159
|
const formatArgs = args => args.map(arg => (typeof arg === "string" ? arg : arg));
|
|
150
160
|
|
|
161
|
+
const consoleTimers = new Map();
|
|
162
|
+
const consoleCounts = new Map();
|
|
151
163
|
const consoleBridge = {
|
|
152
164
|
log: (...args) => globalThis.__omp_log__("log", ...formatArgs(args)),
|
|
153
165
|
info: (...args) => globalThis.__omp_log__("info", ...formatArgs(args)),
|
|
@@ -158,6 +170,55 @@ if (!globalThis.__omp_js_prelude_loaded__) {
|
|
|
158
170
|
columns === undefined
|
|
159
171
|
? globalThis.__omp_table__(data)
|
|
160
172
|
: globalThis.__omp_table__(data, columns),
|
|
173
|
+
dir: (value, _options) => globalThis.__omp_log__("log", value),
|
|
174
|
+
dirxml: (...args) => globalThis.__omp_log__("log", ...formatArgs(args)),
|
|
175
|
+
trace: (...args) => {
|
|
176
|
+
const stack = (new Error().stack ?? "").split("\n").slice(2).join("\n");
|
|
177
|
+
globalThis.__omp_log__("log", args.length > 0 ? `Trace: ${formatArgs(args).join(" ")}` : "Trace", `\n${stack}`);
|
|
178
|
+
},
|
|
179
|
+
assert: (condition, ...args) => {
|
|
180
|
+
if (condition) return;
|
|
181
|
+
if (args.length > 0) globalThis.__omp_log__("error", "Assertion failed:", ...formatArgs(args));
|
|
182
|
+
else globalThis.__omp_log__("error", "Assertion failed");
|
|
183
|
+
},
|
|
184
|
+
group: (...args) => {
|
|
185
|
+
if (args.length > 0) globalThis.__omp_log__("log", ...formatArgs(args));
|
|
186
|
+
},
|
|
187
|
+
groupCollapsed: (...args) => {
|
|
188
|
+
if (args.length > 0) globalThis.__omp_log__("log", ...formatArgs(args));
|
|
189
|
+
},
|
|
190
|
+
groupEnd: () => {},
|
|
191
|
+
time: label => {
|
|
192
|
+
consoleTimers.set(String(label ?? "default"), Date.now());
|
|
193
|
+
},
|
|
194
|
+
timeLog: (label, ...args) => {
|
|
195
|
+
const key = String(label ?? "default");
|
|
196
|
+
const start = consoleTimers.get(key);
|
|
197
|
+
if (start === undefined) {
|
|
198
|
+
globalThis.__omp_log__("warn", `Timer '${key}' does not exist`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
globalThis.__omp_log__("log", `${key}: ${Date.now() - start}ms`, ...formatArgs(args));
|
|
202
|
+
},
|
|
203
|
+
timeEnd: label => {
|
|
204
|
+
const key = String(label ?? "default");
|
|
205
|
+
const start = consoleTimers.get(key);
|
|
206
|
+
if (start === undefined) {
|
|
207
|
+
globalThis.__omp_log__("warn", `Timer '${key}' does not exist`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
consoleTimers.delete(key);
|
|
211
|
+
globalThis.__omp_log__("log", `${key}: ${Date.now() - start}ms`);
|
|
212
|
+
},
|
|
213
|
+
count: label => {
|
|
214
|
+
const key = String(label ?? "default");
|
|
215
|
+
const next = (consoleCounts.get(key) ?? 0) + 1;
|
|
216
|
+
consoleCounts.set(key, next);
|
|
217
|
+
globalThis.__omp_log__("log", `${key}: ${next}`);
|
|
218
|
+
},
|
|
219
|
+
countReset: label => {
|
|
220
|
+
consoleCounts.delete(String(label ?? "default"));
|
|
221
|
+
},
|
|
161
222
|
};
|
|
162
223
|
|
|
163
224
|
globalThis.console = consoleBridge;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type * as BabelParser from "@babel/parser";
|
|
2
2
|
|
|
3
3
|
// Static ESM `import` declarations are not valid inside vm.runInContext (script-mode parsing),
|
|
4
4
|
// and dynamic `import(...)` would otherwise resolve specifiers against the worker module's URL
|
|
@@ -64,9 +64,22 @@ type BabelModuleSourceDeclaration = {
|
|
|
64
64
|
|
|
65
65
|
type BabelNode = { type: string; start: number; end: number; [key: string]: unknown };
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
// @babel/parser sits on the CLI launch graph (tools → eval backend → worker-core →
|
|
68
|
+
// runtime → this module) but only runs when an eval cell executes, so it is loaded
|
|
69
|
+
// lazily and memoized.
|
|
70
|
+
let babelParser: typeof BabelParser | undefined;
|
|
71
|
+
|
|
72
|
+
async function loadBabelParser(): Promise<typeof BabelParser> {
|
|
73
|
+
if (!babelParser) {
|
|
74
|
+
babelParser = await import("@babel/parser");
|
|
75
|
+
}
|
|
76
|
+
return babelParser;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function parseProgram(code: string): Promise<{ program: { body: ReadonlyArray<BabelProgramNode> } } | null> {
|
|
80
|
+
const { parse } = await loadBabelParser();
|
|
68
81
|
try {
|
|
69
|
-
return
|
|
82
|
+
return parse(code, {
|
|
70
83
|
sourceType: "module",
|
|
71
84
|
allowAwaitOutsideFunction: true,
|
|
72
85
|
allowReturnOutsideFunction: true,
|
|
@@ -162,10 +175,10 @@ function rewriteImportNode(node: BabelImportDeclaration): string {
|
|
|
162
175
|
return `await ${importCall};`;
|
|
163
176
|
}
|
|
164
177
|
|
|
165
|
-
export function rewriteImports(code: string): string {
|
|
178
|
+
export async function rewriteImports(code: string): Promise<string> {
|
|
166
179
|
if (!code.includes("import")) return code;
|
|
167
180
|
|
|
168
|
-
const ast = parseProgram(code);
|
|
181
|
+
const ast = await parseProgram(code);
|
|
169
182
|
if (!ast) {
|
|
170
183
|
// Parser bailed entirely — let the VM surface the real syntax error.
|
|
171
184
|
return code;
|
|
@@ -201,8 +214,8 @@ export function rewriteImports(code: string): string {
|
|
|
201
214
|
}
|
|
202
215
|
return result;
|
|
203
216
|
}
|
|
204
|
-
export function collectModuleSourceSpecifiers(code: string): string[] {
|
|
205
|
-
const ast = parseProgram(code);
|
|
217
|
+
export async function collectModuleSourceSpecifiers(code: string): Promise<string[]> {
|
|
218
|
+
const ast = await parseProgram(code);
|
|
206
219
|
if (!ast) return [];
|
|
207
220
|
const sources: string[] = [];
|
|
208
221
|
for (const node of ast.program.body) {
|
|
@@ -218,8 +231,11 @@ export function collectModuleSourceSpecifiers(code: string): string[] {
|
|
|
218
231
|
return sources;
|
|
219
232
|
}
|
|
220
233
|
|
|
221
|
-
export function rewriteModuleSourceSpecifiers(
|
|
222
|
-
|
|
234
|
+
export async function rewriteModuleSourceSpecifiers(
|
|
235
|
+
code: string,
|
|
236
|
+
replacer: (source: string) => string,
|
|
237
|
+
): Promise<string> {
|
|
238
|
+
const ast = await parseProgram(code);
|
|
223
239
|
if (!ast) return code;
|
|
224
240
|
|
|
225
241
|
type Edit = { start: number; end: number; text: string };
|
|
@@ -249,9 +265,9 @@ export function rewriteModuleSourceSpecifiers(code: string, replacer: (source: s
|
|
|
249
265
|
return result;
|
|
250
266
|
}
|
|
251
267
|
|
|
252
|
-
export function rewriteDynamicImports(code: string, callee = "__omp_import__"): string {
|
|
268
|
+
export async function rewriteDynamicImports(code: string, callee = "__omp_import__"): Promise<string> {
|
|
253
269
|
if (!code.includes("import")) return code;
|
|
254
|
-
const ast = parseProgram(code);
|
|
270
|
+
const ast = await parseProgram(code);
|
|
255
271
|
if (!ast) return code;
|
|
256
272
|
|
|
257
273
|
type Edit = { start: number; end: number; text: string };
|
|
@@ -339,10 +355,10 @@ function appendGlobalBindingPublish(source: string, names: readonly string[]): s
|
|
|
339
355
|
* Nested declarations (inside functions, blocks, classes) are left alone \u2014 they're
|
|
340
356
|
* scoped to their enclosing function/block regardless of `var` vs `let`/`const`.
|
|
341
357
|
*/
|
|
342
|
-
function demoteTopLevelLexicals(code: string, options: { publishGlobals?: boolean } = {}): string {
|
|
358
|
+
async function demoteTopLevelLexicals(code: string, options: { publishGlobals?: boolean } = {}): Promise<string> {
|
|
343
359
|
if (!/\b(?:const|let|class)\b/.test(code)) return code;
|
|
344
360
|
|
|
345
|
-
const ast = parseProgram(code);
|
|
361
|
+
const ast = await parseProgram(code);
|
|
346
362
|
if (!ast) {
|
|
347
363
|
return code;
|
|
348
364
|
}
|
|
@@ -381,8 +397,8 @@ function demoteTopLevelLexicals(code: string, options: { publishGlobals?: boolea
|
|
|
381
397
|
return result;
|
|
382
398
|
}
|
|
383
399
|
|
|
384
|
-
function returnFinalExpression(code: string): { source: string; returned: boolean } {
|
|
385
|
-
const ast = parseProgram(code);
|
|
400
|
+
async function returnFinalExpression(code: string): Promise<{ source: string; returned: boolean }> {
|
|
401
|
+
const ast = await parseProgram(code);
|
|
386
402
|
const body = ast?.program.body;
|
|
387
403
|
if (!body) return { source: code, returned: false };
|
|
388
404
|
let lastIndex = body.length - 1;
|
|
@@ -446,8 +462,8 @@ function containsAsyncWrapperSyntax(value: unknown): boolean {
|
|
|
446
462
|
return false;
|
|
447
463
|
}
|
|
448
464
|
|
|
449
|
-
function requiresAsyncWrapper(code: string): boolean {
|
|
450
|
-
const ast = parseProgram(code);
|
|
465
|
+
async function requiresAsyncWrapper(code: string): Promise<boolean> {
|
|
466
|
+
const ast = await parseProgram(code);
|
|
451
467
|
if (!ast) return false;
|
|
452
468
|
for (const node of ast.program.body) {
|
|
453
469
|
if (containsAsyncWrapperSyntax(node)) return true;
|
|
@@ -494,13 +510,15 @@ export function stripTypeScriptSyntax(
|
|
|
494
510
|
const LOOKS_LIKE_TS =
|
|
495
511
|
/(?:\bimport\s+type\b|\bexport\s+type\b|\b(?:import|export)\s*\{[^}\n]*\btype\s+\w|\binterface\s+\w|\btype\s+\w+\s*=|\b(?:as|satisfies)\s+(?:[A-Z]|\bconst\b)|:\s*(?:string|number|boolean|any|unknown|void|never|object|[A-Z]\w*)\b|<\s*[A-Z]\w*\s*[,>])/;
|
|
496
512
|
|
|
497
|
-
export function wrapCode(
|
|
498
|
-
|
|
513
|
+
export async function wrapCode(
|
|
514
|
+
code: string,
|
|
515
|
+
): Promise<{ source: string; asyncWrapped: boolean; finalExpressionReturned: boolean }> {
|
|
516
|
+
const finalExpression = await returnFinalExpression(code);
|
|
499
517
|
const stripped = stripTypeScript(finalExpression.source);
|
|
500
|
-
const importsRewritten = rewriteImports(stripped);
|
|
501
|
-
const needsAsyncWrapper = requiresAsyncWrapper(importsRewritten);
|
|
518
|
+
const importsRewritten = await rewriteImports(stripped);
|
|
519
|
+
const needsAsyncWrapper = await requiresAsyncWrapper(importsRewritten);
|
|
502
520
|
const rewritten = {
|
|
503
|
-
source: demoteTopLevelLexicals(importsRewritten, { publishGlobals: needsAsyncWrapper }),
|
|
521
|
+
source: await demoteTopLevelLexicals(importsRewritten, { publishGlobals: needsAsyncWrapper }),
|
|
504
522
|
returned: finalExpression.returned,
|
|
505
523
|
};
|
|
506
524
|
if (!needsAsyncWrapper) {
|
|
@@ -181,7 +181,7 @@ export class JsRuntime {
|
|
|
181
181
|
finalExpressionValue: undefined,
|
|
182
182
|
};
|
|
183
183
|
return await this.#als.run(context, async () => {
|
|
184
|
-
const wrapped = wrapCode(code);
|
|
184
|
+
const wrapped = await wrapCode(code);
|
|
185
185
|
const value = indirectEval(wrapped.source, filename);
|
|
186
186
|
if (wrapped.finalExpressionReturned) {
|
|
187
187
|
const awaited = await awaitMaybePromise(value);
|
package/src/eval/py/index.ts
CHANGED
|
@@ -42,8 +42,6 @@ export default {
|
|
|
42
42
|
localRoots: resolveEvalUrlRoots(opts.session),
|
|
43
43
|
kernelOwnerId: opts.kernelOwnerId,
|
|
44
44
|
reset: opts.reset,
|
|
45
|
-
artifactPath: opts.artifactPath,
|
|
46
|
-
artifactId: opts.artifactId,
|
|
47
45
|
onChunk: opts.onChunk,
|
|
48
46
|
onStatus: opts.onStatus,
|
|
49
47
|
toolSession: opts.session,
|
package/src/eval/py/kernel.ts
CHANGED
|
@@ -129,10 +129,29 @@ function throwIfAborted(signal: AbortSignal | undefined, fallbackReason: string)
|
|
|
129
129
|
throw createAbortError("AbortError", typeof reason === "string" ? reason : fallbackReason);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
// Cache successful probes per resolved cwd: every cell otherwise pays one (or
|
|
133
|
+
// two — backend.isAvailable + ensureKernelAvailable) interpreter spawns even
|
|
134
|
+
// when the kernel is already hot. Failures are not cached so installing a
|
|
135
|
+
// Python mid-session is picked up on the next attempt.
|
|
136
|
+
const availabilityCache = new Map<string, Promise<PythonKernelAvailability>>();
|
|
137
|
+
|
|
132
138
|
export async function checkPythonKernelAvailability(cwd: string): Promise<PythonKernelAvailability> {
|
|
133
139
|
if (isBunTestRuntime() || $flag("PI_PYTHON_SKIP_CHECK")) {
|
|
134
140
|
return { ok: true };
|
|
135
141
|
}
|
|
142
|
+
const key = path.resolve(cwd);
|
|
143
|
+
const cached = availabilityCache.get(key);
|
|
144
|
+
if (cached) return await cached;
|
|
145
|
+
const probe = probePythonKernelAvailability(key);
|
|
146
|
+
availabilityCache.set(key, probe);
|
|
147
|
+
const result = await probe;
|
|
148
|
+
if (!result.ok && availabilityCache.get(key) === probe) {
|
|
149
|
+
availabilityCache.delete(key);
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function probePythonKernelAvailability(cwd: string): Promise<PythonKernelAvailability> {
|
|
136
155
|
try {
|
|
137
156
|
const settings = await Settings.init();
|
|
138
157
|
const { env } = settings.getShellConfig();
|
package/src/eval/py/runner.py
CHANGED
|
@@ -51,8 +51,23 @@ from typing import Any
|
|
|
51
51
|
# Frame writer
|
|
52
52
|
# ---------------------------------------------------------------------------
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
# Frames travel on a private dup of the original stdout. fd 1 itself is then
|
|
55
|
+
# repointed at a capture pipe: child processes spawned by user code without
|
|
56
|
+
# stdout=PIPE inherit fd 1, and their output is forwarded to the host as
|
|
57
|
+
# regular stdout frames by a drain thread instead of being written raw into
|
|
58
|
+
# the NDJSON channel (where it would be dropped as invalid JSON — or worse,
|
|
59
|
+
# spoof a frame). The wire protocol is unchanged: the host still reads NDJSON
|
|
60
|
+
# frames from the subprocess stdout.
|
|
55
61
|
_RAW_STDERR = sys.__stderr__
|
|
62
|
+
try:
|
|
63
|
+
_FRAME_FD = os.dup(sys.__stdout__.fileno())
|
|
64
|
+
_RAW_STDOUT = os.fdopen(_FRAME_FD, "w", encoding="utf-8", errors="backslashreplace")
|
|
65
|
+
_CAPTURE_READ_FD, _capture_write_fd = os.pipe()
|
|
66
|
+
os.dup2(_capture_write_fd, sys.__stdout__.fileno())
|
|
67
|
+
os.close(_capture_write_fd)
|
|
68
|
+
except (AttributeError, OSError, ValueError, io.UnsupportedOperation):
|
|
69
|
+
_RAW_STDOUT = sys.__stdout__
|
|
70
|
+
_CAPTURE_READ_FD = None
|
|
56
71
|
_OUT_LOCK = threading.Lock()
|
|
57
72
|
|
|
58
73
|
|
|
@@ -78,11 +93,22 @@ def _emit(frame: dict) -> None:
|
|
|
78
93
|
|
|
79
94
|
|
|
80
95
|
class _StreamProxy(io.TextIOBase):
|
|
81
|
-
"""Emit
|
|
96
|
+
"""Emit ``write()`` data as typed frames tied to the current request.
|
|
97
|
+
|
|
98
|
+
Writes are coalesced per request: a frame is emitted once the buffer holds
|
|
99
|
+
a complete line (everything up to the last newline goes out together) or
|
|
100
|
+
grows past ``_MAX_BUFFER`` bytes, so the common ``print()`` pair of
|
|
101
|
+
``write(text)`` + ``write("\\n")`` costs one frame instead of two. Partial
|
|
102
|
+
lines are bounded by ``flush()`` and the end-of-request flush.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
_MAX_BUFFER = 8192
|
|
82
106
|
|
|
83
107
|
def __init__(self, kind: str) -> None:
|
|
84
108
|
super().__init__()
|
|
85
109
|
self._kind = kind
|
|
110
|
+
self._lock = threading.Lock()
|
|
111
|
+
self._buffers: dict[str, str] = {}
|
|
86
112
|
|
|
87
113
|
def writable(self) -> bool: # noqa: D401 - protocol method
|
|
88
114
|
return True
|
|
@@ -100,12 +126,44 @@ class _StreamProxy(io.TextIOBase):
|
|
|
100
126
|
_RAW_STDERR.write(data)
|
|
101
127
|
_RAW_STDERR.flush()
|
|
102
128
|
return len(data)
|
|
103
|
-
|
|
129
|
+
emit_text = None
|
|
130
|
+
with self._lock:
|
|
131
|
+
buf = self._buffers.pop(rid, "") + data
|
|
132
|
+
if len(buf) >= self._MAX_BUFFER:
|
|
133
|
+
emit_text = buf
|
|
134
|
+
else:
|
|
135
|
+
nl = buf.rfind("\n")
|
|
136
|
+
if nl >= 0:
|
|
137
|
+
emit_text = buf[: nl + 1]
|
|
138
|
+
rest = buf[nl + 1 :]
|
|
139
|
+
if rest:
|
|
140
|
+
self._buffers[rid] = rest
|
|
141
|
+
else:
|
|
142
|
+
self._buffers[rid] = buf
|
|
143
|
+
if emit_text:
|
|
144
|
+
_emit({"type": self._kind, "id": rid, "data": emit_text})
|
|
104
145
|
return len(data)
|
|
105
146
|
|
|
106
147
|
def flush(self) -> None: # noqa: D401 - protocol method
|
|
148
|
+
rid = _CURRENT_RID.get()
|
|
149
|
+
if rid is not None:
|
|
150
|
+
self.flush_rid(rid)
|
|
107
151
|
return None
|
|
108
152
|
|
|
153
|
+
def flush_rid(self, rid: str) -> None:
|
|
154
|
+
"""Flush any buffered partial line for ``rid`` as its own frame."""
|
|
155
|
+
with self._lock:
|
|
156
|
+
buf = self._buffers.pop(rid, None)
|
|
157
|
+
if buf:
|
|
158
|
+
_emit({"type": self._kind, "id": rid, "data": buf})
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _flush_stream_proxies(rid: str) -> None:
|
|
162
|
+
"""Drain buffered proxy output for ``rid`` (called before its done frame)."""
|
|
163
|
+
for stream in (sys.stdout, sys.stderr):
|
|
164
|
+
if isinstance(stream, _StreamProxy):
|
|
165
|
+
stream.flush_rid(rid)
|
|
166
|
+
|
|
109
167
|
|
|
110
168
|
# ---------------------------------------------------------------------------
|
|
111
169
|
# Runner state
|
|
@@ -125,6 +183,10 @@ class _RunnerState:
|
|
|
125
183
|
self.last_install_marker: int = 0
|
|
126
184
|
self.loop: asyncio.AbstractEventLoop | None = None
|
|
127
185
|
self.active_executions: int = 0
|
|
186
|
+
# Best-effort attribution target for captured fd-1 bytes (child
|
|
187
|
+
# processes inheriting stdout). With overlapping requests the most
|
|
188
|
+
# recently started one wins — strictly better than dropping the bytes.
|
|
189
|
+
self.capture_rid: str | None = None
|
|
128
190
|
|
|
129
191
|
|
|
130
192
|
_CURRENT_RID: contextvars.ContextVar[str | None] = contextvars.ContextVar("omp_current_rid", default=None)
|
|
@@ -132,6 +194,42 @@ _CURRENT_RID: contextvars.ContextVar[str | None] = contextvars.ContextVar("omp_c
|
|
|
132
194
|
_STATE = _RunnerState()
|
|
133
195
|
|
|
134
196
|
|
|
197
|
+
def _drain_captured_stdout() -> None:
|
|
198
|
+
"""Forward bytes written to the captured fd 1 as stdout frames.
|
|
199
|
+
|
|
200
|
+
Runs on a daemon thread for the life of the process. Child processes that
|
|
201
|
+
inherit fd 1 (any ``subprocess`` call without ``stdout=PIPE``) land here.
|
|
202
|
+
"""
|
|
203
|
+
if _CAPTURE_READ_FD is None:
|
|
204
|
+
return
|
|
205
|
+
import codecs
|
|
206
|
+
|
|
207
|
+
decoder = codecs.getincrementaldecoder("utf-8")("replace")
|
|
208
|
+
while True:
|
|
209
|
+
try:
|
|
210
|
+
chunk = os.read(_CAPTURE_READ_FD, 65536)
|
|
211
|
+
except OSError:
|
|
212
|
+
return
|
|
213
|
+
if not chunk:
|
|
214
|
+
return
|
|
215
|
+
text = decoder.decode(chunk)
|
|
216
|
+
if not text:
|
|
217
|
+
continue
|
|
218
|
+
rid = _STATE.capture_rid
|
|
219
|
+
if rid is None:
|
|
220
|
+
_RAW_STDERR.write(text)
|
|
221
|
+
_RAW_STDERR.flush()
|
|
222
|
+
else:
|
|
223
|
+
_emit({"type": "stdout", "id": rid, "data": text})
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _start_capture_drain() -> None:
|
|
227
|
+
if _CAPTURE_READ_FD is None:
|
|
228
|
+
return
|
|
229
|
+
thread = threading.Thread(target=_drain_captured_stdout, name="omp-fd1-capture", daemon=True)
|
|
230
|
+
thread.start()
|
|
231
|
+
|
|
232
|
+
|
|
135
233
|
# ---------------------------------------------------------------------------
|
|
136
234
|
# Magic source transformer
|
|
137
235
|
# ---------------------------------------------------------------------------
|
|
@@ -880,6 +978,7 @@ def _start_parent_watchdog() -> None:
|
|
|
880
978
|
async def _handle_request_async(req: dict) -> None:
|
|
881
979
|
rid = str(req.get("id"))
|
|
882
980
|
token = _CURRENT_RID.set(rid)
|
|
981
|
+
_STATE.capture_rid = rid
|
|
883
982
|
_STATE.user_ns["__omp_run_id__"] = rid
|
|
884
983
|
_STATE.cancel_requested = False
|
|
885
984
|
_STATE.execution_count += 1
|
|
@@ -934,6 +1033,7 @@ async def _handle_request_async(req: dict) -> None:
|
|
|
934
1033
|
except Exception:
|
|
935
1034
|
pass
|
|
936
1035
|
|
|
1036
|
+
_flush_stream_proxies(rid)
|
|
937
1037
|
_emit({
|
|
938
1038
|
"type": "done",
|
|
939
1039
|
"id": rid,
|
|
@@ -942,6 +1042,9 @@ async def _handle_request_async(req: dict) -> None:
|
|
|
942
1042
|
"cancelled": cancelled,
|
|
943
1043
|
})
|
|
944
1044
|
finally:
|
|
1045
|
+
if _STATE.capture_rid == rid:
|
|
1046
|
+
_STATE.capture_rid = None
|
|
1047
|
+
_flush_stream_proxies(rid)
|
|
945
1048
|
_CURRENT_RID.reset(token)
|
|
946
1049
|
|
|
947
1050
|
|
|
@@ -986,6 +1089,7 @@ async def _main_async() -> None:
|
|
|
986
1089
|
sys.stderr = _StreamProxy("stderr")
|
|
987
1090
|
_install_idle_sigint()
|
|
988
1091
|
_start_parent_watchdog()
|
|
1092
|
+
_start_capture_drain()
|
|
989
1093
|
|
|
990
1094
|
stdin = sys.__stdin__
|
|
991
1095
|
if stdin is None:
|
|
@@ -314,7 +314,9 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
314
314
|
if (userSignal) {
|
|
315
315
|
userSignal.removeEventListener("abort", abortHandler);
|
|
316
316
|
}
|
|
317
|
-
if (resetSession) {
|
|
317
|
+
if (resetSession || options?.sessionKey?.includes(":async:")) {
|
|
318
|
+
// `:async:` keys are per-job (jobId is unique), so the Shell would
|
|
319
|
+
// otherwise stay in the process-global map forever after completion.
|
|
318
320
|
shellSessions.delete(sessionKey);
|
|
319
321
|
}
|
|
320
322
|
}
|