@oh-my-pi/pi-coding-agent 15.0.1 → 15.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -1
- package/examples/custom-tools/README.md +11 -7
- package/examples/custom-tools/hello/index.ts +2 -2
- package/examples/extensions/README.md +19 -8
- package/examples/extensions/api-demo.ts +15 -19
- package/examples/extensions/hello.ts +5 -6
- package/examples/extensions/plan-mode.ts +1 -1
- package/examples/extensions/reload-runtime.ts +4 -3
- package/examples/extensions/with-deps/index.ts +4 -3
- package/examples/sdk/06-extensions.ts +4 -2
- package/package.json +8 -18
- package/src/autoresearch/tools/init-experiment.ts +38 -41
- package/src/autoresearch/tools/log-experiment.ts +32 -41
- package/src/autoresearch/tools/run-experiment.ts +3 -3
- package/src/autoresearch/tools/update-notes.ts +11 -11
- package/src/commands/commit.ts +10 -0
- package/src/commit/agentic/tools/analyze-file.ts +4 -4
- package/src/commit/agentic/tools/git-file-diff.ts +4 -4
- package/src/commit/agentic/tools/git-hunk.ts +5 -5
- package/src/commit/agentic/tools/git-overview.ts +4 -4
- package/src/commit/agentic/tools/propose-changelog.ts +13 -13
- package/src/commit/agentic/tools/propose-commit.ts +6 -6
- package/src/commit/agentic/tools/recent-commits.ts +3 -3
- package/src/commit/agentic/tools/schemas.ts +28 -28
- package/src/commit/agentic/tools/split-commit.ts +22 -21
- package/src/commit/analysis/summary.ts +4 -4
- package/src/commit/changelog/generate.ts +7 -11
- package/src/commit/shared-llm.ts +22 -34
- package/src/config/config-file.ts +35 -13
- package/src/config/model-registry.ts +40 -191
- package/src/config/models-config-schema.ts +166 -0
- package/src/config/settings-schema.ts +29 -0
- package/src/discovery/claude-plugins.ts +19 -7
- package/src/edit/index.ts +2 -2
- package/src/edit/modes/apply-patch.ts +7 -6
- package/src/edit/modes/patch.ts +18 -25
- package/src/edit/modes/replace.ts +18 -20
- package/src/eval/js/shared/rewrite-imports.ts +131 -10
- package/src/eval/py/executor.ts +233 -623
- package/src/eval/py/kernel.ts +27 -2
- package/src/eval/py/runner.py +42 -11
- package/src/eval/py/runtime.ts +1 -0
- package/src/exa/factory.ts +5 -4
- package/src/exa/mcp-client.ts +1 -1
- package/src/exa/researcher.ts +9 -20
- package/src/exa/search.ts +26 -52
- package/src/exa/types.ts +1 -1
- package/src/exa/websets.ts +54 -53
- package/src/exec/bash-executor.ts +2 -1
- package/src/extensibility/custom-commands/loader.ts +5 -3
- package/src/extensibility/custom-commands/types.ts +4 -2
- package/src/extensibility/custom-tools/loader.ts +5 -3
- package/src/extensibility/custom-tools/types.ts +7 -6
- package/src/extensibility/custom-tools/wrapper.ts +1 -1
- package/src/extensibility/extensions/get-commands-handler.ts +77 -0
- package/src/extensibility/extensions/loader.ts +7 -3
- package/src/extensibility/extensions/types.ts +9 -5
- package/src/extensibility/extensions/wrapper.ts +1 -2
- package/src/extensibility/hooks/loader.ts +3 -1
- package/src/extensibility/hooks/tool-wrapper.ts +1 -1
- package/src/extensibility/hooks/types.ts +4 -2
- package/src/extensibility/plugins/legacy-pi-compat.ts +78 -31
- package/src/extensibility/shared-events.ts +1 -1
- package/src/extensibility/typebox.ts +391 -0
- package/src/goals/tools/goal-tool.ts +6 -12
- package/src/hashline/input.ts +2 -1
- package/src/hashline/parser.ts +27 -3
- package/src/hashline/types.ts +4 -4
- package/src/hindsight/state.ts +2 -2
- package/src/index.ts +0 -2
- package/src/internal-urls/docs-index.generated.ts +15 -15
- package/src/internal-urls/router.ts +8 -0
- package/src/internal-urls/types.ts +21 -0
- package/src/lsp/config.ts +15 -6
- package/src/lsp/defaults.json +6 -2
- package/src/lsp/types.ts +30 -38
- package/src/mcp/manager.ts +1 -1
- package/src/mcp/tool-bridge.ts +1 -1
- package/src/modes/acp/acp-agent.ts +248 -50
- package/src/modes/components/session-observer-overlay.ts +12 -1
- package/src/modes/components/status-line/segments.ts +39 -4
- package/src/modes/controllers/command-controller.ts +27 -2
- package/src/modes/controllers/event-controller.ts +3 -4
- package/src/modes/controllers/extension-ui-controller.ts +3 -2
- package/src/modes/interactive-mode.ts +1 -1
- package/src/modes/rpc/host-tools.ts +1 -1
- package/src/modes/rpc/host-uris.ts +235 -0
- package/src/modes/rpc/rpc-client.ts +1 -1
- package/src/modes/rpc/rpc-mode.ts +27 -1
- package/src/modes/rpc/rpc-types.ts +58 -1
- package/src/modes/runtime-init.ts +2 -1
- package/src/modes/theme/defaults/dark-poimandres.json +1 -0
- package/src/modes/theme/defaults/light-poimandres.json +1 -0
- package/src/modes/theme/theme.ts +117 -117
- package/src/modes/types.ts +1 -1
- package/src/modes/utils/context-usage.ts +2 -2
- package/src/prompts/tools/github.md +4 -4
- package/src/prompts/tools/hashline.md +22 -26
- package/src/prompts/tools/read.md +55 -37
- package/src/sdk.ts +31 -8
- package/src/session/agent-session.ts +74 -104
- package/src/session/messages.ts +16 -51
- package/src/session/session-manager.ts +22 -2
- package/src/session/streaming-output.ts +16 -6
- package/src/task/discovery.ts +5 -2
- package/src/task/executor.ts +210 -87
- package/src/task/index.ts +15 -11
- package/src/task/render.ts +32 -5
- package/src/task/types.ts +54 -39
- package/src/tools/ask.ts +12 -12
- package/src/tools/ast-edit.ts +11 -15
- package/src/tools/ast-grep.ts +9 -10
- package/src/tools/bash-command-fixup.ts +47 -0
- package/src/tools/bash.ts +48 -38
- package/src/tools/browser/render.ts +2 -2
- package/src/tools/browser.ts +39 -53
- package/src/tools/calculator.ts +12 -11
- package/src/tools/checkpoint.ts +7 -7
- package/src/tools/debug.ts +40 -43
- package/src/tools/eval.ts +16 -10
- package/src/tools/find.ts +10 -13
- package/src/tools/gh.ts +108 -132
- package/src/tools/hindsight-recall.ts +4 -6
- package/src/tools/hindsight-reflect.ts +5 -5
- package/src/tools/hindsight-retain.ts +15 -17
- package/src/tools/image-gen.ts +31 -81
- package/src/tools/index.ts +4 -1
- package/src/tools/inspect-image.ts +8 -9
- package/src/tools/irc.ts +15 -27
- package/src/tools/job.ts +30 -28
- package/src/tools/output-meta.ts +26 -0
- package/src/tools/read.ts +39 -12
- package/src/tools/recipe/index.ts +7 -9
- package/src/tools/render-mermaid.ts +12 -12
- package/src/tools/report-tool-issue.ts +4 -4
- package/src/tools/resolve.ts +11 -11
- package/src/tools/review.ts +14 -26
- package/src/tools/search-tool-bm25.ts +7 -9
- package/src/tools/search.ts +19 -22
- package/src/tools/ssh.ts +10 -9
- package/src/tools/todo-write.ts +26 -34
- package/src/tools/vim.ts +10 -26
- package/src/tools/write.ts +25 -5
- package/src/tools/yield.ts +100 -54
- package/src/web/search/index.ts +9 -24
- package/src/web/search/providers/anthropic.ts +5 -0
- package/src/web/search/providers/exa.ts +3 -0
- package/src/web/search/providers/gemini.ts +5 -0
- package/src/web/search/providers/jina.ts +5 -2
- package/src/web/search/providers/zai.ts +5 -2
- package/src/prompts/compaction/branch-summary-context.md +0 -5
- package/src/prompts/compaction/branch-summary-preamble.md +0 -2
- package/src/prompts/compaction/branch-summary.md +0 -30
- package/src/prompts/compaction/compaction-short-summary.md +0 -9
- package/src/prompts/compaction/compaction-summary-context.md +0 -5
- package/src/prompts/compaction/compaction-summary.md +0 -38
- package/src/prompts/compaction/compaction-turn-prefix.md +0 -17
- package/src/prompts/compaction/compaction-update-summary.md +0 -45
- package/src/prompts/system/auto-handoff-threshold-focus.md +0 -1
- package/src/prompts/system/file-operations.md +0 -10
- package/src/prompts/system/handoff-document.md +0 -49
- package/src/prompts/system/summarization-system.md +0 -3
- package/src/session/compaction/branch-summarization.ts +0 -324
- package/src/session/compaction/compaction.ts +0 -1420
- package/src/session/compaction/errors.ts +0 -31
- package/src/session/compaction/index.ts +0 -8
- package/src/session/compaction/pruning.ts +0 -91
- package/src/session/compaction/utils.ts +0 -184
|
@@ -8,19 +8,20 @@
|
|
|
8
8
|
* the `patch` mode.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import * as z from "zod/v4";
|
|
12
12
|
import { parseApplyPatch, parseApplyPatchStreaming } from "../apply-patch/parser";
|
|
13
13
|
import { ApplyPatchError } from "../diff";
|
|
14
14
|
import type { PatchEditEntry } from "./patch";
|
|
15
15
|
|
|
16
|
-
export const applyPatchSchema =
|
|
17
|
-
input:
|
|
18
|
-
|
|
16
|
+
export const applyPatchSchema = z.object({
|
|
17
|
+
input: z
|
|
18
|
+
.string()
|
|
19
|
+
.describe(
|
|
19
20
|
"Full Codex apply_patch envelope, including '*** Begin Patch' and '*** End Patch'. Contains any mix of Add/Delete/Update (with optional Move to) file operations.",
|
|
20
|
-
|
|
21
|
+
),
|
|
21
22
|
});
|
|
22
23
|
|
|
23
|
-
export type ApplyPatchParams =
|
|
24
|
+
export type ApplyPatchParams = z.infer<typeof applyPatchSchema>;
|
|
24
25
|
|
|
25
26
|
export type ApplyPatchEntry = PatchEditEntry & { path: string };
|
|
26
27
|
|
package/src/edit/modes/patch.ts
CHANGED
|
@@ -8,9 +8,8 @@
|
|
|
8
8
|
import * as fs from "node:fs";
|
|
9
9
|
import * as path from "node:path";
|
|
10
10
|
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
11
|
-
import { StringEnum } from "@oh-my-pi/pi-ai";
|
|
12
11
|
import { isEnoent } from "@oh-my-pi/pi-utils";
|
|
13
|
-
import
|
|
12
|
+
import * as z from "zod/v4";
|
|
14
13
|
import {
|
|
15
14
|
type FileDiagnosticsResult,
|
|
16
15
|
flushLspWritethroughBatch,
|
|
@@ -1577,29 +1576,23 @@ export async function computePatchDiff(
|
|
|
1577
1576
|
}
|
|
1578
1577
|
}
|
|
1579
1578
|
|
|
1580
|
-
export const patchEditEntrySchema =
|
|
1581
|
-
{
|
|
1582
|
-
op:
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
)
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
},
|
|
1598
|
-
{ additionalProperties: false },
|
|
1599
|
-
);
|
|
1600
|
-
|
|
1601
|
-
export type PatchEditEntry = Static<typeof patchEditEntrySchema>;
|
|
1602
|
-
export type PatchParams = Static<typeof patchEditSchema>;
|
|
1579
|
+
export const patchEditEntrySchema = z
|
|
1580
|
+
.object({
|
|
1581
|
+
op: z.enum(["create", "delete", "update"]).optional().describe("Operation (default: update)"),
|
|
1582
|
+
rename: z.string().describe("New path for move").optional(),
|
|
1583
|
+
diff: z.string().describe("Diff hunks (update) or full content (create)").optional(),
|
|
1584
|
+
})
|
|
1585
|
+
.strict();
|
|
1586
|
+
|
|
1587
|
+
export const patchEditSchema = z
|
|
1588
|
+
.object({
|
|
1589
|
+
path: z.string().describe("file path for edits"),
|
|
1590
|
+
edits: z.array(patchEditEntrySchema).min(1).describe("Patch operations"),
|
|
1591
|
+
})
|
|
1592
|
+
.strict();
|
|
1593
|
+
|
|
1594
|
+
export type PatchEditEntry = z.infer<typeof patchEditEntrySchema>;
|
|
1595
|
+
export type PatchParams = z.infer<typeof patchEditSchema>;
|
|
1603
1596
|
|
|
1604
1597
|
export interface ExecutePatchSingleOptions {
|
|
1605
1598
|
session: ToolSession;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* fallback strategies for finding text in files.
|
|
6
6
|
*/
|
|
7
7
|
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
8
|
-
import
|
|
8
|
+
import * as z from "zod/v4";
|
|
9
9
|
import type { WritethroughCallback, WritethroughDeferredHandle } from "../../lsp";
|
|
10
10
|
import type { ToolSession } from "../../tools";
|
|
11
11
|
import { invalidateFsScanAfterWrite } from "../../tools/fs-cache-invalidation";
|
|
@@ -976,25 +976,23 @@ export function findContextLine(
|
|
|
976
976
|
return { index: undefined, confidence: bestScore };
|
|
977
977
|
}
|
|
978
978
|
|
|
979
|
-
export const replaceEditEntrySchema =
|
|
980
|
-
{
|
|
981
|
-
old_text:
|
|
982
|
-
new_text:
|
|
983
|
-
all:
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
export type ReplaceEditEntry = Static<typeof replaceEditEntrySchema>;
|
|
997
|
-
export type ReplaceParams = Static<typeof replaceEditSchema>;
|
|
979
|
+
export const replaceEditEntrySchema = z
|
|
980
|
+
.object({
|
|
981
|
+
old_text: z.string().describe("Text to find (fuzzy whitespace matching enabled)"),
|
|
982
|
+
new_text: z.string().describe("Replacement text"),
|
|
983
|
+
all: z.boolean().describe("Replace all occurrences (default: unique match required)").optional(),
|
|
984
|
+
})
|
|
985
|
+
.strict();
|
|
986
|
+
|
|
987
|
+
export const replaceEditSchema = z
|
|
988
|
+
.object({
|
|
989
|
+
path: z.string().describe("file path for edits"),
|
|
990
|
+
edits: z.array(replaceEditEntrySchema).min(1).describe("Replacements"),
|
|
991
|
+
})
|
|
992
|
+
.strict();
|
|
993
|
+
|
|
994
|
+
export type ReplaceEditEntry = z.infer<typeof replaceEditEntrySchema>;
|
|
995
|
+
export type ReplaceParams = z.infer<typeof replaceEditSchema>;
|
|
998
996
|
|
|
999
997
|
export interface ExecuteReplaceSingleOptions {
|
|
1000
998
|
session: ToolSession;
|
|
@@ -22,9 +22,32 @@ type BabelImportDeclaration = {
|
|
|
22
22
|
}>;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
type
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
type BabelBindingPattern = {
|
|
26
|
+
type: string;
|
|
27
|
+
name?: string;
|
|
28
|
+
properties?: ReadonlyArray<unknown>;
|
|
29
|
+
elements?: ReadonlyArray<unknown | null>;
|
|
30
|
+
argument?: unknown;
|
|
31
|
+
left?: unknown;
|
|
32
|
+
value?: unknown;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type BabelVariableDeclaration = {
|
|
36
|
+
type: "VariableDeclaration";
|
|
37
|
+
kind: "const" | "let" | "var";
|
|
38
|
+
start: number;
|
|
39
|
+
end: number;
|
|
40
|
+
declarations?: ReadonlyArray<{ id: BabelBindingPattern }>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type BabelClassDeclaration = {
|
|
44
|
+
type: "ClassDeclaration";
|
|
45
|
+
start: number;
|
|
46
|
+
end: number;
|
|
47
|
+
id: { start: number; end: number; name: string } | null;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
type BabelLexicalDecl = BabelVariableDeclaration | BabelClassDeclaration;
|
|
28
51
|
|
|
29
52
|
type BabelExpressionStatement = {
|
|
30
53
|
type: "ExpressionStatement";
|
|
@@ -167,6 +190,53 @@ export function rewriteImports(code: string): string {
|
|
|
167
190
|
return result;
|
|
168
191
|
}
|
|
169
192
|
|
|
193
|
+
function collectBindingNames(pattern: unknown, names: string[]): void {
|
|
194
|
+
if (!pattern || typeof pattern !== "object") return;
|
|
195
|
+
const node = pattern as BabelBindingPattern & { parameter?: unknown };
|
|
196
|
+
switch (node.type) {
|
|
197
|
+
case "Identifier":
|
|
198
|
+
if (typeof node.name === "string") names.push(node.name);
|
|
199
|
+
return;
|
|
200
|
+
case "ObjectPattern":
|
|
201
|
+
for (const property of node.properties ?? []) collectBindingNames(property, names);
|
|
202
|
+
return;
|
|
203
|
+
case "ObjectProperty":
|
|
204
|
+
case "Property":
|
|
205
|
+
collectBindingNames(node.value, names);
|
|
206
|
+
return;
|
|
207
|
+
case "ArrayPattern":
|
|
208
|
+
for (const element of node.elements ?? []) collectBindingNames(element, names);
|
|
209
|
+
return;
|
|
210
|
+
case "AssignmentPattern":
|
|
211
|
+
collectBindingNames(node.left, names);
|
|
212
|
+
return;
|
|
213
|
+
case "RestElement":
|
|
214
|
+
collectBindingNames(node.argument, names);
|
|
215
|
+
return;
|
|
216
|
+
case "TSParameterProperty":
|
|
217
|
+
collectBindingNames(node.parameter, names);
|
|
218
|
+
return;
|
|
219
|
+
default:
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function getLexicalBindingNames(node: BabelLexicalDecl): string[] {
|
|
225
|
+
const names: string[] = [];
|
|
226
|
+
if (node.type === "VariableDeclaration") {
|
|
227
|
+
for (const declaration of node.declarations ?? []) collectBindingNames(declaration.id, names);
|
|
228
|
+
} else if (node.id) {
|
|
229
|
+
names.push(node.id.name);
|
|
230
|
+
}
|
|
231
|
+
return names;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function appendGlobalBindingPublish(source: string, names: readonly string[]): string {
|
|
235
|
+
if (names.length === 0) return source;
|
|
236
|
+
const assignments = names.map(name => `this[${JSON.stringify(name)}] = ${name};`).join("\n");
|
|
237
|
+
return `${source};\n${assignments}`;
|
|
238
|
+
}
|
|
239
|
+
|
|
170
240
|
/**
|
|
171
241
|
* Demote top-level `const`/`let`/`class` declarations to `var` so they persist on the
|
|
172
242
|
* worker's globalThis across indirect `eval` calls. Indirect eval gives each call its own
|
|
@@ -177,10 +247,14 @@ export function rewriteImports(code: string): string {
|
|
|
177
247
|
* let { a, b } = obj; -> var { a, b } = obj;
|
|
178
248
|
* class Foo extends Bar {} -> var Foo = class extends Bar {};
|
|
179
249
|
*
|
|
250
|
+
* When the source must run inside the async wrapper, demoted `var`s would normally become
|
|
251
|
+
* function-scoped. In that mode we publish each top-level binding back to the wrapper's
|
|
252
|
+
* lexical `this`, which is the worker global object.
|
|
253
|
+
*
|
|
180
254
|
* Nested declarations (inside functions, blocks, classes) are left alone \u2014 they're
|
|
181
255
|
* scoped to their enclosing function/block regardless of `var` vs `let`/`const`.
|
|
182
256
|
*/
|
|
183
|
-
function demoteTopLevelLexicals(code: string): string {
|
|
257
|
+
function demoteTopLevelLexicals(code: string, options: { publishGlobals?: boolean } = {}): string {
|
|
184
258
|
if (!/\b(?:const|let|class)\b/.test(code)) return code;
|
|
185
259
|
|
|
186
260
|
const ast = parseProgram(code);
|
|
@@ -191,10 +265,10 @@ function demoteTopLevelLexicals(code: string): string {
|
|
|
191
265
|
const targets: BabelLexicalDecl[] = [];
|
|
192
266
|
for (const node of ast.program.body) {
|
|
193
267
|
if (node.type === "VariableDeclaration") {
|
|
194
|
-
const decl = node as unknown as
|
|
195
|
-
if (decl.kind === "const" || decl.kind === "let") targets.push(decl
|
|
268
|
+
const decl = node as unknown as BabelVariableDeclaration;
|
|
269
|
+
if (decl.kind === "const" || decl.kind === "let") targets.push(decl);
|
|
196
270
|
} else if (node.type === "ClassDeclaration") {
|
|
197
|
-
const decl = node as unknown as
|
|
271
|
+
const decl = node as unknown as BabelClassDeclaration;
|
|
198
272
|
if (decl.id) targets.push(decl);
|
|
199
273
|
}
|
|
200
274
|
}
|
|
@@ -204,6 +278,7 @@ function demoteTopLevelLexicals(code: string): string {
|
|
|
204
278
|
let result = code;
|
|
205
279
|
for (const node of targets) {
|
|
206
280
|
const segment = result.slice(node.start, node.end);
|
|
281
|
+
const bindingNames = options.publishGlobals ? getLexicalBindingNames(node) : [];
|
|
207
282
|
let replacement: string;
|
|
208
283
|
if (node.type === "VariableDeclaration") {
|
|
209
284
|
replacement = `var${segment.slice(node.kind.length)}`;
|
|
@@ -215,7 +290,8 @@ function demoteTopLevelLexicals(code: string): string {
|
|
|
215
290
|
const hasTrailingSemi = segment.endsWith(";");
|
|
216
291
|
replacement = `var ${id.name} = class${tail}${hasTrailingSemi ? "" : ";"}`;
|
|
217
292
|
}
|
|
218
|
-
result =
|
|
293
|
+
result =
|
|
294
|
+
result.slice(0, node.start) + appendGlobalBindingPublish(replacement, bindingNames) + result.slice(node.end);
|
|
219
295
|
}
|
|
220
296
|
return result;
|
|
221
297
|
}
|
|
@@ -238,6 +314,50 @@ function returnFinalExpression(code: string): { source: string; returned: boolea
|
|
|
238
314
|
return { source: `${prefix}__omp_set_final_expr__((${trimmedStatement}));${suffix}`, returned: true };
|
|
239
315
|
}
|
|
240
316
|
|
|
317
|
+
function isExecutionBoundary(type: string): boolean {
|
|
318
|
+
return (
|
|
319
|
+
type === "FunctionDeclaration" ||
|
|
320
|
+
type === "FunctionExpression" ||
|
|
321
|
+
type === "ArrowFunctionExpression" ||
|
|
322
|
+
type === "ObjectMethod" ||
|
|
323
|
+
type === "ClassMethod" ||
|
|
324
|
+
type === "ClassPrivateMethod" ||
|
|
325
|
+
type === "PrivateMethod"
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function containsAsyncWrapperSyntax(value: unknown): boolean {
|
|
330
|
+
if (!value || typeof value !== "object") return false;
|
|
331
|
+
if (Array.isArray(value)) {
|
|
332
|
+
for (const item of value) {
|
|
333
|
+
if (containsAsyncWrapperSyntax(item)) return true;
|
|
334
|
+
}
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const node = value as Record<string, unknown>;
|
|
339
|
+
const type = node.type;
|
|
340
|
+
if (type === "ReturnStatement" || type === "AwaitExpression") return true;
|
|
341
|
+
if (type === "ForOfStatement" && node.await === true) return true;
|
|
342
|
+
if (typeof type === "string" && isExecutionBoundary(type)) return false;
|
|
343
|
+
|
|
344
|
+
for (const key in node) {
|
|
345
|
+
if (key === "loc" || key === "extra" || key === "range") continue;
|
|
346
|
+
if (key === "leadingComments" || key === "trailingComments" || key === "innerComments") continue;
|
|
347
|
+
if (containsAsyncWrapperSyntax(node[key])) return true;
|
|
348
|
+
}
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function requiresAsyncWrapper(code: string): boolean {
|
|
353
|
+
const ast = parseProgram(code);
|
|
354
|
+
if (!ast) return false;
|
|
355
|
+
for (const node of ast.program.body) {
|
|
356
|
+
if (containsAsyncWrapperSyntax(node)) return true;
|
|
357
|
+
}
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
241
361
|
/**
|
|
242
362
|
* Strip TypeScript syntax (type annotations, `interface`, `as`, `satisfies`, generics in
|
|
243
363
|
* call expressions, etc.) before the import/lexical rewriters parse the code. We use Bun's
|
|
@@ -267,11 +387,12 @@ const LOOKS_LIKE_TS =
|
|
|
267
387
|
export function wrapCode(code: string): { source: string; asyncWrapped: boolean; finalExpressionReturned: boolean } {
|
|
268
388
|
const stripped = stripTypeScript(code);
|
|
269
389
|
const finalExpression = returnFinalExpression(stripped);
|
|
390
|
+
const importsRewritten = rewriteImports(finalExpression.source);
|
|
391
|
+
const needsAsyncWrapper = requiresAsyncWrapper(importsRewritten);
|
|
270
392
|
const rewritten = {
|
|
271
|
-
source: demoteTopLevelLexicals(
|
|
393
|
+
source: demoteTopLevelLexicals(importsRewritten, { publishGlobals: needsAsyncWrapper }),
|
|
272
394
|
returned: finalExpression.returned,
|
|
273
395
|
};
|
|
274
|
-
const needsAsyncWrapper = /\bawait\b|\breturn\b/.test(rewritten.source);
|
|
275
396
|
if (!needsAsyncWrapper) {
|
|
276
397
|
return { source: rewritten.source, asyncWrapped: false, finalExpressionReturned: rewritten.returned };
|
|
277
398
|
}
|