gsd-pi 2.45.0-dev.6b9da3e → 2.45.0-dev.e0ee972
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/dist/help-text.js +1 -1
- package/dist/loader.js +34 -0
- package/dist/resources/extensions/gsd/auto/phases.js +16 -10
- package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
- package/dist/resources/extensions/gsd/auto-worktree.js +5 -4
- package/dist/resources/extensions/gsd/auto.js +4 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +13 -12
- package/dist/resources/extensions/gsd/db-writer.js +9 -9
- package/dist/resources/extensions/gsd/doctor-checks.js +1 -1
- package/dist/resources/extensions/gsd/doctor.js +2 -2
- package/dist/resources/extensions/gsd/gsd-db.js +5 -1
- package/dist/resources/extensions/gsd/preferences-types.js +2 -2
- package/dist/resources/extensions/gsd/preferences.js +8 -4
- package/dist/resources/extensions/gsd/workflow-logger.js +138 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +4 -3
- package/dist/resources/extensions/gsd/worktree-resolver.js +37 -0
- package/dist/resources/extensions/voice/index.js +11 -16
- package/dist/resources/extensions/voice/linux-ready.js +67 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +19 -19
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +19 -19
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +20 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
- package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
- package/packages/pi-coding-agent/src/core/model-registry.ts +30 -3
- package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
- package/src/resources/extensions/gsd/auto/phases.ts +16 -12
- package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +8 -5
- package/src/resources/extensions/gsd/auto.ts +3 -3
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -12
- package/src/resources/extensions/gsd/db-writer.ts +9 -17
- package/src/resources/extensions/gsd/doctor-checks.ts +1 -1
- package/src/resources/extensions/gsd/doctor.ts +2 -2
- package/src/resources/extensions/gsd/gsd-db.ts +5 -1
- package/src/resources/extensions/gsd/journal.ts +6 -1
- package/src/resources/extensions/gsd/preferences-types.ts +2 -2
- package/src/resources/extensions/gsd/preferences.ts +7 -3
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +42 -3
- package/src/resources/extensions/gsd/tests/preferences.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +193 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +4 -9
- package/src/resources/extensions/gsd/worktree-resolver.ts +37 -0
- package/src/resources/extensions/voice/index.ts +11 -21
- package/src/resources/extensions/voice/linux-ready.ts +87 -0
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
- /package/dist/web/standalone/.next/static/{rzO54ZboyINyEt7cVM_uS → dFMji9G1LZ-Tv36el9pRT}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{rzO54ZboyINyEt7cVM_uS → dFMji9G1LZ-Tv36el9pRT}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { homedir, tmpdir } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { describe, it } from "node:test";
|
|
6
|
+
import {
|
|
7
|
+
readManifestRuntimeDeps,
|
|
8
|
+
collectRuntimeDependencies,
|
|
9
|
+
verifyRuntimeDependencies,
|
|
10
|
+
resolveLocalSourcePath,
|
|
11
|
+
} from "./lifecycle-hooks.js";
|
|
12
|
+
|
|
13
|
+
function tmpDir(prefix: string, t: { after: (fn: () => void) => void }): string {
|
|
14
|
+
const dir = mkdtempSync(join(tmpdir(), `pi-lh-${prefix}-`));
|
|
15
|
+
t.after(() => rmSync(dir, { recursive: true, force: true }));
|
|
16
|
+
return dir;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ─── readManifestRuntimeDeps ──────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
describe("readManifestRuntimeDeps", () => {
|
|
22
|
+
it("returns empty array when manifest file is missing", (t) => {
|
|
23
|
+
const dir = tmpDir("no-manifest", t);
|
|
24
|
+
assert.deepEqual(readManifestRuntimeDeps(dir), []);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("returns empty array for malformed JSON", (t) => {
|
|
28
|
+
const dir = tmpDir("bad-json", t);
|
|
29
|
+
writeFileSync(join(dir, "extension-manifest.json"), "not json{{{", "utf-8");
|
|
30
|
+
assert.deepEqual(readManifestRuntimeDeps(dir), []);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("returns runtime deps from valid manifest", (t) => {
|
|
34
|
+
const dir = tmpDir("valid", t);
|
|
35
|
+
writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
|
|
36
|
+
dependencies: { runtime: ["claude", "node"] },
|
|
37
|
+
}), "utf-8");
|
|
38
|
+
assert.deepEqual(readManifestRuntimeDeps(dir), ["claude", "node"]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("returns empty array when dependencies exists but runtime is missing", (t) => {
|
|
42
|
+
const dir = tmpDir("no-runtime", t);
|
|
43
|
+
writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
|
|
44
|
+
dependencies: {},
|
|
45
|
+
}), "utf-8");
|
|
46
|
+
assert.deepEqual(readManifestRuntimeDeps(dir), []);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("returns empty array when runtime is empty", (t) => {
|
|
50
|
+
const dir = tmpDir("empty-runtime", t);
|
|
51
|
+
writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
|
|
52
|
+
dependencies: { runtime: [] },
|
|
53
|
+
}), "utf-8");
|
|
54
|
+
assert.deepEqual(readManifestRuntimeDeps(dir), []);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("filters out non-string entries in runtime array", (t) => {
|
|
58
|
+
const dir = tmpDir("mixed-types", t);
|
|
59
|
+
writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
|
|
60
|
+
dependencies: { runtime: [123, null, "node", false, "python"] },
|
|
61
|
+
}), "utf-8");
|
|
62
|
+
assert.deepEqual(readManifestRuntimeDeps(dir), ["node", "python"]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("returns empty array when no dependencies field at all", (t) => {
|
|
66
|
+
const dir = tmpDir("no-deps-field", t);
|
|
67
|
+
writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
|
|
68
|
+
id: "test",
|
|
69
|
+
name: "Test",
|
|
70
|
+
}), "utf-8");
|
|
71
|
+
assert.deepEqual(readManifestRuntimeDeps(dir), []);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// ─── collectRuntimeDependencies ───────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
describe("collectRuntimeDependencies", () => {
|
|
78
|
+
it("aggregates deps from installedPath manifest", (t) => {
|
|
79
|
+
const dir = tmpDir("collect-installed", t);
|
|
80
|
+
writeFileSync(join(dir, "extension-manifest.json"), JSON.stringify({
|
|
81
|
+
dependencies: { runtime: ["claude"] },
|
|
82
|
+
}), "utf-8");
|
|
83
|
+
assert.deepEqual(collectRuntimeDependencies(dir, []), ["claude"]);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("aggregates deps from entry path directory manifests", (t) => {
|
|
87
|
+
const root = tmpDir("collect-entry", t);
|
|
88
|
+
const installedDir = join(root, "installed");
|
|
89
|
+
const entryDir = join(root, "entry");
|
|
90
|
+
mkdirSync(installedDir, { recursive: true });
|
|
91
|
+
mkdirSync(entryDir, { recursive: true });
|
|
92
|
+
writeFileSync(join(entryDir, "extension-manifest.json"), JSON.stringify({
|
|
93
|
+
dependencies: { runtime: ["python"] },
|
|
94
|
+
}), "utf-8");
|
|
95
|
+
const deps = collectRuntimeDependencies(installedDir, [join(entryDir, "index.ts")]);
|
|
96
|
+
assert.deepEqual(deps, ["python"]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("deduplicates across multiple directories", (t) => {
|
|
100
|
+
const root = tmpDir("collect-dedup", t);
|
|
101
|
+
const dir1 = join(root, "dir1");
|
|
102
|
+
const dir2 = join(root, "dir2");
|
|
103
|
+
mkdirSync(dir1, { recursive: true });
|
|
104
|
+
mkdirSync(dir2, { recursive: true });
|
|
105
|
+
writeFileSync(join(dir1, "extension-manifest.json"), JSON.stringify({
|
|
106
|
+
dependencies: { runtime: ["node", "python"] },
|
|
107
|
+
}), "utf-8");
|
|
108
|
+
writeFileSync(join(dir2, "extension-manifest.json"), JSON.stringify({
|
|
109
|
+
dependencies: { runtime: ["python", "claude"] },
|
|
110
|
+
}), "utf-8");
|
|
111
|
+
const deps = collectRuntimeDependencies(dir1, [join(dir2, "index.ts")]);
|
|
112
|
+
assert.equal(deps.length, 3);
|
|
113
|
+
assert.ok(deps.includes("node"));
|
|
114
|
+
assert.ok(deps.includes("python"));
|
|
115
|
+
assert.ok(deps.includes("claude"));
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("returns empty when no directories have manifests", (t) => {
|
|
119
|
+
const dir = tmpDir("collect-empty", t);
|
|
120
|
+
assert.deepEqual(collectRuntimeDependencies(dir, []), []);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// ─── verifyRuntimeDependencies ────────────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
describe("verifyRuntimeDependencies", () => {
|
|
127
|
+
it("does not throw for empty deps array", () => {
|
|
128
|
+
assert.doesNotThrow(() => verifyRuntimeDependencies([], "test-source", "pi"));
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("does not throw when all deps are present", () => {
|
|
132
|
+
assert.doesNotThrow(() => verifyRuntimeDependencies(["node"], "test-source", "pi"));
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("throws for missing dep with 'Missing runtime dependencies' message", () => {
|
|
136
|
+
assert.throws(
|
|
137
|
+
() => verifyRuntimeDependencies(["__nonexistent_dep_for_test__"], "test-source", "pi"),
|
|
138
|
+
(err: Error) => {
|
|
139
|
+
assert.ok(err.message.includes("Missing runtime dependencies"));
|
|
140
|
+
assert.ok(err.message.includes("__nonexistent_dep_for_test__"));
|
|
141
|
+
return true;
|
|
142
|
+
},
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("lists all missing deps in error message", () => {
|
|
147
|
+
assert.throws(
|
|
148
|
+
() => verifyRuntimeDependencies(["__missing_1__", "__missing_2__"], "test-source", "pi"),
|
|
149
|
+
(err: Error) => {
|
|
150
|
+
assert.ok(err.message.includes("__missing_1__"));
|
|
151
|
+
assert.ok(err.message.includes("__missing_2__"));
|
|
152
|
+
return true;
|
|
153
|
+
},
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("includes appName and source in error for retry hint", () => {
|
|
158
|
+
assert.throws(
|
|
159
|
+
() => verifyRuntimeDependencies(["__missing__"], "github:user/repo", "gsd"),
|
|
160
|
+
(err: Error) => {
|
|
161
|
+
assert.ok(err.message.includes("gsd"));
|
|
162
|
+
assert.ok(err.message.includes("github:user/repo"));
|
|
163
|
+
return true;
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// ─── resolveLocalSourcePath ───────────────────────────────────────────────────
|
|
170
|
+
|
|
171
|
+
describe("resolveLocalSourcePath", () => {
|
|
172
|
+
it("returns undefined for empty string", () => {
|
|
173
|
+
assert.equal(resolveLocalSourcePath("", "/tmp"), undefined);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("returns undefined for npm: source", () => {
|
|
177
|
+
assert.equal(resolveLocalSourcePath("npm:@foo/bar", "/tmp"), undefined);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("returns undefined for git URL", () => {
|
|
181
|
+
assert.equal(resolveLocalSourcePath("git:github.com/user/repo", "/tmp"), undefined);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("returns undefined for https git URL", () => {
|
|
185
|
+
assert.equal(resolveLocalSourcePath("https://github.com/user/repo", "/tmp"), undefined);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("resolves ~ to homedir", () => {
|
|
189
|
+
const result = resolveLocalSourcePath("~", "/tmp");
|
|
190
|
+
if (existsSync(homedir())) {
|
|
191
|
+
assert.equal(result, homedir());
|
|
192
|
+
} else {
|
|
193
|
+
assert.equal(result, undefined);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("resolves ~/path relative to homedir", () => {
|
|
198
|
+
const result = resolveLocalSourcePath("~/", "/tmp");
|
|
199
|
+
if (existsSync(homedir())) {
|
|
200
|
+
assert.equal(result, homedir());
|
|
201
|
+
} else {
|
|
202
|
+
assert.equal(result, undefined);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("resolves relative path that exists", (t) => {
|
|
207
|
+
const dir = tmpDir("resolve-rel", t);
|
|
208
|
+
const sub = join(dir, "myext");
|
|
209
|
+
mkdirSync(sub, { recursive: true });
|
|
210
|
+
const result = resolveLocalSourcePath("myext", dir);
|
|
211
|
+
assert.equal(result, resolve(dir, "myext"));
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("returns undefined for relative path that does not exist", (t) => {
|
|
215
|
+
const dir = tmpDir("resolve-noexist", t);
|
|
216
|
+
assert.equal(resolveLocalSourcePath("nonexistent", dir), undefined);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("resolves absolute path that exists", (t) => {
|
|
220
|
+
const dir = tmpDir("resolve-abs", t);
|
|
221
|
+
assert.equal(resolveLocalSourcePath(dir, "/irrelevant"), dir);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("returns undefined for absolute path that does not exist", () => {
|
|
225
|
+
assert.equal(resolveLocalSourcePath("/tmp/__nonexistent_path_for_test__", "/tmp"), undefined);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
@@ -62,7 +62,7 @@ function toScope(local: boolean): LifecycleHookScope {
|
|
|
62
62
|
return local ? "project" : "user";
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
function readManifestRuntimeDeps(dir: string): string[] {
|
|
65
|
+
export function readManifestRuntimeDeps(dir: string): string[] {
|
|
66
66
|
const manifestPath = join(dir, "extension-manifest.json");
|
|
67
67
|
if (!existsSync(manifestPath)) return [];
|
|
68
68
|
try {
|
|
@@ -73,7 +73,7 @@ function readManifestRuntimeDeps(dir: string): string[] {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
function collectRuntimeDependencies(installedPath: string, entryPaths: string[]): string[] {
|
|
76
|
+
export function collectRuntimeDependencies(installedPath: string, entryPaths: string[]): string[] {
|
|
77
77
|
const deps = new Set<string>();
|
|
78
78
|
const candidateDirs = new Set<string>([installedPath, ...entryPaths.map((entryPath) => dirname(entryPath))]);
|
|
79
79
|
for (const dir of candidateDirs) {
|
|
@@ -84,7 +84,7 @@ function collectRuntimeDependencies(installedPath: string, entryPaths: string[])
|
|
|
84
84
|
return Array.from(deps);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
function verifyRuntimeDependencies(runtimeDeps: string[], source: string, appName: string): void {
|
|
87
|
+
export function verifyRuntimeDependencies(runtimeDeps: string[], source: string, appName: string): void {
|
|
88
88
|
const missing: string[] = [];
|
|
89
89
|
for (const dep of runtimeDeps) {
|
|
90
90
|
const result = spawnSync(dep, ["--version"], { encoding: "utf-8", timeout: 5000 });
|
|
@@ -99,7 +99,7 @@ function verifyRuntimeDependencies(runtimeDeps: string[], source: string, appNam
|
|
|
99
99
|
);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
function resolveLocalSourcePath(source: string, cwd: string): string | undefined {
|
|
102
|
+
export function resolveLocalSourcePath(source: string, cwd: string): string | undefined {
|
|
103
103
|
const trimmed = source.trim();
|
|
104
104
|
if (!trimmed) return undefined;
|
|
105
105
|
if (trimmed.startsWith("npm:")) return undefined;
|
|
@@ -193,13 +193,19 @@ function getLegacyExportCandidates(phase: LifecycleHookPhase): string[] {
|
|
|
193
193
|
return [phase];
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
const _legacyModuleCache = new Map<string, Record<string, unknown>>();
|
|
197
|
+
|
|
196
198
|
async function runLegacyExportHook(
|
|
197
199
|
entryPath: string,
|
|
198
200
|
phase: LifecycleHookPhase,
|
|
199
201
|
context: LifecycleHookContext,
|
|
200
202
|
): Promise<LifecycleHookHandler | null> {
|
|
201
203
|
try {
|
|
202
|
-
|
|
204
|
+
let module = _legacyModuleCache.get(entryPath);
|
|
205
|
+
if (!module) {
|
|
206
|
+
module = await importExtensionModule<Record<string, unknown>>(import.meta.url, pathToFileURL(entryPath).href);
|
|
207
|
+
_legacyModuleCache.set(entryPath, module);
|
|
208
|
+
}
|
|
203
209
|
for (const exportName of getLegacyExportCandidates(phase)) {
|
|
204
210
|
const candidate = module[exportName];
|
|
205
211
|
if (typeof candidate === "function") {
|