gsd-pi 2.45.0-dev.6b9da3e → 2.45.0-dev.fdcf73c
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 +15 -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/prompts/complete-milestone.md +20 -7
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -0
- 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 +17 -17
- 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 +17 -17
- 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 +2 -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 +15 -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/prompts/complete-milestone.md +20 -7
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +96 -0
- 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/tools/complete-milestone.ts +6 -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 → zWYDSwB-terOjfhmWzqk1}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{rzO54ZboyINyEt7cVM_uS → zWYDSwB-terOjfhmWzqk1}/_ssgManifest.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { Writable } from "node:stream";
|
|
@@ -22,204 +22,215 @@ function writePackage(root, files) {
|
|
|
22
22
|
writeFileSync(abs, content, "utf-8");
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
function createTestDirs(prefix, t) {
|
|
26
|
+
const root = mkdtempSync(join(tmpdir(), `pi-lifecycle-${prefix}-`));
|
|
27
|
+
t.after(() => rmSync(root, { recursive: true, force: true }));
|
|
28
|
+
const cwd = join(root, "cwd");
|
|
29
|
+
const agentDir = join(root, "agent");
|
|
30
|
+
const extensionDir = join(root, `ext-${prefix}`);
|
|
31
|
+
mkdirSync(cwd, { recursive: true });
|
|
32
|
+
mkdirSync(agentDir, { recursive: true });
|
|
33
|
+
mkdirSync(extensionDir, { recursive: true });
|
|
34
|
+
return { root, cwd, agentDir, extensionDir };
|
|
35
|
+
}
|
|
25
36
|
describe("runPackageCommand lifecycle hooks", () => {
|
|
26
|
-
it("executes registered beforeInstall and afterInstall handlers for local packages", async () => {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}),
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
37
|
+
it("executes registered beforeInstall and afterInstall handlers for local packages", async (t) => {
|
|
38
|
+
const { cwd, agentDir, extensionDir } = createTestDirs("install", t);
|
|
39
|
+
writePackage(extensionDir, {
|
|
40
|
+
"package.json": JSON.stringify({
|
|
41
|
+
name: "ext-registered",
|
|
42
|
+
type: "module",
|
|
43
|
+
pi: { extensions: ["./index.js"] },
|
|
44
|
+
}),
|
|
45
|
+
"index.js": [
|
|
46
|
+
'import { writeFileSync } from "node:fs";',
|
|
47
|
+
'import { join } from "node:path";',
|
|
48
|
+
"export default function (pi) {",
|
|
49
|
+
" pi.registerBeforeInstall((ctx) => {",
|
|
50
|
+
' writeFileSync(join(ctx.installedPath, "before-install-ran.txt"), "ok", "utf-8");',
|
|
51
|
+
" });",
|
|
52
|
+
" pi.registerAfterInstall((ctx) => {",
|
|
53
|
+
' writeFileSync(join(ctx.installedPath, "after-install-ran.txt"), "ok", "utf-8");',
|
|
54
|
+
" });",
|
|
55
|
+
"}",
|
|
56
|
+
].join("\n"),
|
|
57
|
+
});
|
|
58
|
+
const stdout = createCaptureStream();
|
|
59
|
+
const stderr = createCaptureStream();
|
|
60
|
+
const result = await runPackageCommand({
|
|
61
|
+
appName: "pi",
|
|
62
|
+
args: ["install", extensionDir],
|
|
63
|
+
cwd,
|
|
64
|
+
agentDir,
|
|
65
|
+
stdout: stdout.stream,
|
|
66
|
+
stderr: stderr.stream,
|
|
67
|
+
});
|
|
68
|
+
assert.equal(result.handled, true);
|
|
69
|
+
assert.equal(result.exitCode, 0);
|
|
70
|
+
assert.equal(readFileSync(join(extensionDir, "before-install-ran.txt"), "utf-8"), "ok");
|
|
71
|
+
assert.equal(readFileSync(join(extensionDir, "after-install-ran.txt"), "utf-8"), "ok");
|
|
72
|
+
assert.ok(stdout.getOutput().includes(`Installed ${extensionDir}`));
|
|
73
|
+
});
|
|
74
|
+
it("runs legacy named lifecycle hooks when no registered hooks exist", async (t) => {
|
|
75
|
+
const { cwd, agentDir, extensionDir } = createTestDirs("legacy", t);
|
|
76
|
+
writePackage(extensionDir, {
|
|
77
|
+
"package.json": JSON.stringify({
|
|
78
|
+
name: "ext-legacy",
|
|
79
|
+
type: "module",
|
|
80
|
+
pi: { extensions: ["./index.js"] },
|
|
81
|
+
}),
|
|
82
|
+
"index.js": [
|
|
83
|
+
'import { writeFileSync } from "node:fs";',
|
|
84
|
+
'import { join } from "node:path";',
|
|
85
|
+
"export default function () {}",
|
|
86
|
+
"export async function beforeInstall(ctx) {",
|
|
87
|
+
' writeFileSync(join(ctx.installedPath, "legacy-before-install.txt"), "ok", "utf-8");',
|
|
88
|
+
"}",
|
|
89
|
+
"export async function afterInstall(ctx) {",
|
|
90
|
+
' writeFileSync(join(ctx.installedPath, "legacy-after-install.txt"), "ok", "utf-8");',
|
|
91
|
+
"}",
|
|
92
|
+
"export async function beforeRemove(ctx) {",
|
|
93
|
+
' writeFileSync(join(ctx.installedPath, "legacy-before-remove.txt"), "ok", "utf-8");',
|
|
94
|
+
"}",
|
|
95
|
+
"export async function afterRemove(ctx) {",
|
|
96
|
+
' writeFileSync(join(ctx.installedPath, "legacy-after-remove.txt"), "ok", "utf-8");',
|
|
97
|
+
"}",
|
|
98
|
+
].join("\n"),
|
|
99
|
+
});
|
|
100
|
+
const stdout = createCaptureStream();
|
|
101
|
+
const stderr = createCaptureStream();
|
|
102
|
+
const installResult = await runPackageCommand({
|
|
103
|
+
appName: "pi",
|
|
104
|
+
args: ["install", extensionDir],
|
|
105
|
+
cwd,
|
|
106
|
+
agentDir,
|
|
107
|
+
stdout: stdout.stream,
|
|
108
|
+
stderr: stderr.stream,
|
|
109
|
+
});
|
|
110
|
+
assert.equal(installResult.handled, true);
|
|
111
|
+
assert.equal(installResult.exitCode, 0);
|
|
112
|
+
assert.equal(readFileSync(join(extensionDir, "legacy-before-install.txt"), "utf-8"), "ok");
|
|
113
|
+
assert.equal(readFileSync(join(extensionDir, "legacy-after-install.txt"), "utf-8"), "ok");
|
|
114
|
+
const removeResult = await runPackageCommand({
|
|
115
|
+
appName: "pi",
|
|
116
|
+
args: ["remove", extensionDir],
|
|
117
|
+
cwd,
|
|
118
|
+
agentDir,
|
|
119
|
+
stdout: stdout.stream,
|
|
120
|
+
stderr: stderr.stream,
|
|
121
|
+
});
|
|
122
|
+
assert.equal(removeResult.handled, true);
|
|
123
|
+
assert.equal(removeResult.exitCode, 0);
|
|
124
|
+
assert.equal(readFileSync(join(extensionDir, "legacy-before-remove.txt"), "utf-8"), "ok");
|
|
125
|
+
assert.equal(readFileSync(join(extensionDir, "legacy-after-remove.txt"), "utf-8"), "ok");
|
|
73
126
|
});
|
|
74
|
-
it("
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const stdout = createCaptureStream();
|
|
108
|
-
const stderr = createCaptureStream();
|
|
109
|
-
const installResult = await runPackageCommand({
|
|
110
|
-
appName: "pi",
|
|
111
|
-
args: ["install", extensionDir],
|
|
112
|
-
cwd,
|
|
113
|
-
agentDir,
|
|
114
|
-
stdout: stdout.stream,
|
|
115
|
-
stderr: stderr.stream,
|
|
116
|
-
});
|
|
117
|
-
assert.equal(installResult.handled, true);
|
|
118
|
-
assert.equal(installResult.exitCode, 0);
|
|
119
|
-
assert.equal(readFileSync(join(extensionDir, "legacy-before-install.txt"), "utf-8"), "ok");
|
|
120
|
-
assert.equal(readFileSync(join(extensionDir, "legacy-after-install.txt"), "utf-8"), "ok");
|
|
121
|
-
const removeResult = await runPackageCommand({
|
|
122
|
-
appName: "pi",
|
|
123
|
-
args: ["remove", extensionDir],
|
|
124
|
-
cwd,
|
|
125
|
-
agentDir,
|
|
126
|
-
stdout: stdout.stream,
|
|
127
|
-
stderr: stderr.stream,
|
|
128
|
-
});
|
|
129
|
-
assert.equal(removeResult.handled, true);
|
|
130
|
-
assert.equal(removeResult.exitCode, 0);
|
|
131
|
-
assert.equal(readFileSync(join(extensionDir, "legacy-before-remove.txt"), "utf-8"), "ok");
|
|
132
|
-
assert.equal(readFileSync(join(extensionDir, "legacy-after-remove.txt"), "utf-8"), "ok");
|
|
133
|
-
}
|
|
134
|
-
finally {
|
|
135
|
-
rmSync(root, { recursive: true, force: true });
|
|
136
|
-
}
|
|
127
|
+
it("skips lifecycle phases with no hooks declared", async (t) => {
|
|
128
|
+
const { cwd, agentDir, extensionDir } = createTestDirs("skip", t);
|
|
129
|
+
writePackage(extensionDir, {
|
|
130
|
+
"package.json": JSON.stringify({
|
|
131
|
+
name: "ext-empty",
|
|
132
|
+
type: "module",
|
|
133
|
+
pi: { extensions: ["./index.js"] },
|
|
134
|
+
}),
|
|
135
|
+
"index.js": "export default function () {}",
|
|
136
|
+
});
|
|
137
|
+
const stdout = createCaptureStream();
|
|
138
|
+
const stderr = createCaptureStream();
|
|
139
|
+
const installResult = await runPackageCommand({
|
|
140
|
+
appName: "pi",
|
|
141
|
+
args: ["install", extensionDir],
|
|
142
|
+
cwd,
|
|
143
|
+
agentDir,
|
|
144
|
+
stdout: stdout.stream,
|
|
145
|
+
stderr: stderr.stream,
|
|
146
|
+
});
|
|
147
|
+
assert.equal(installResult.handled, true);
|
|
148
|
+
assert.equal(installResult.exitCode, 0);
|
|
149
|
+
const removeResult = await runPackageCommand({
|
|
150
|
+
appName: "pi",
|
|
151
|
+
args: ["remove", extensionDir],
|
|
152
|
+
cwd,
|
|
153
|
+
agentDir,
|
|
154
|
+
stdout: stdout.stream,
|
|
155
|
+
stderr: stderr.stream,
|
|
156
|
+
});
|
|
157
|
+
assert.equal(removeResult.handled, true);
|
|
158
|
+
assert.equal(removeResult.exitCode, 0);
|
|
159
|
+
assert.equal(stderr.getOutput().includes("Hook failed"), false);
|
|
137
160
|
});
|
|
138
|
-
it("
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
"
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const removeResult = await runPackageCommand({
|
|
168
|
-
appName: "pi",
|
|
169
|
-
args: ["remove", extensionDir],
|
|
170
|
-
cwd,
|
|
171
|
-
agentDir,
|
|
172
|
-
stdout: stdout.stream,
|
|
173
|
-
stderr: stderr.stream,
|
|
174
|
-
});
|
|
175
|
-
assert.equal(removeResult.handled, true);
|
|
176
|
-
assert.equal(removeResult.exitCode, 0);
|
|
177
|
-
assert.equal(stderr.getOutput().includes("Hook failed"), false);
|
|
178
|
-
}
|
|
179
|
-
finally {
|
|
180
|
-
rmSync(root, { recursive: true, force: true });
|
|
181
|
-
}
|
|
161
|
+
it("fails install when manifest runtime dependency is missing", async (t) => {
|
|
162
|
+
const { cwd, agentDir, extensionDir } = createTestDirs("deps", t);
|
|
163
|
+
writePackage(extensionDir, {
|
|
164
|
+
"package.json": JSON.stringify({
|
|
165
|
+
name: "ext-runtime-deps",
|
|
166
|
+
type: "module",
|
|
167
|
+
pi: { extensions: ["./index.js"] },
|
|
168
|
+
}),
|
|
169
|
+
"index.js": "export default function () {}",
|
|
170
|
+
"extension-manifest.json": JSON.stringify({
|
|
171
|
+
id: "ext-runtime-deps",
|
|
172
|
+
name: "Runtime Dep Test",
|
|
173
|
+
version: "1.0.0",
|
|
174
|
+
dependencies: { runtime: ["__definitely_missing_command_for_test__"] },
|
|
175
|
+
}),
|
|
176
|
+
});
|
|
177
|
+
const stdout = createCaptureStream();
|
|
178
|
+
const stderr = createCaptureStream();
|
|
179
|
+
const result = await runPackageCommand({
|
|
180
|
+
appName: "pi",
|
|
181
|
+
args: ["install", extensionDir],
|
|
182
|
+
cwd,
|
|
183
|
+
agentDir,
|
|
184
|
+
stdout: stdout.stream,
|
|
185
|
+
stderr: stderr.stream,
|
|
186
|
+
});
|
|
187
|
+
assert.equal(result.handled, true);
|
|
188
|
+
assert.equal(result.exitCode, 1);
|
|
189
|
+
assert.ok(stderr.getOutput().includes("Missing runtime dependencies"));
|
|
182
190
|
});
|
|
183
|
-
it("
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
"
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
"
|
|
199
|
-
"
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
191
|
+
it("afterRemove hook receives installedPath even when directory is deleted", async (t) => {
|
|
192
|
+
const { cwd, agentDir, extensionDir } = createTestDirs("after-remove", t);
|
|
193
|
+
writePackage(extensionDir, {
|
|
194
|
+
"package.json": JSON.stringify({
|
|
195
|
+
name: "ext-after-remove",
|
|
196
|
+
type: "module",
|
|
197
|
+
pi: { extensions: ["./index.js"] },
|
|
198
|
+
}),
|
|
199
|
+
"index.js": [
|
|
200
|
+
'import { writeFileSync, existsSync } from "node:fs";',
|
|
201
|
+
'import { join } from "node:path";',
|
|
202
|
+
"export default function () {}",
|
|
203
|
+
"export async function afterRemove(ctx) {",
|
|
204
|
+
' const marker = join(ctx.cwd, "after-remove-marker.json");',
|
|
205
|
+
" writeFileSync(marker, JSON.stringify({",
|
|
206
|
+
" receivedPath: ctx.installedPath,",
|
|
207
|
+
" pathExisted: existsSync(ctx.installedPath),",
|
|
208
|
+
' }), "utf-8");',
|
|
209
|
+
"}",
|
|
210
|
+
].join("\n"),
|
|
211
|
+
});
|
|
212
|
+
const stdout = createCaptureStream();
|
|
213
|
+
const stderr = createCaptureStream();
|
|
214
|
+
await runPackageCommand({
|
|
215
|
+
appName: "pi",
|
|
216
|
+
args: ["install", extensionDir],
|
|
217
|
+
cwd,
|
|
218
|
+
agentDir,
|
|
219
|
+
stdout: stdout.stream,
|
|
220
|
+
stderr: stderr.stream,
|
|
221
|
+
});
|
|
222
|
+
await runPackageCommand({
|
|
223
|
+
appName: "pi",
|
|
224
|
+
args: ["remove", extensionDir],
|
|
225
|
+
cwd,
|
|
226
|
+
agentDir,
|
|
227
|
+
stdout: stdout.stream,
|
|
228
|
+
stderr: stderr.stream,
|
|
229
|
+
});
|
|
230
|
+
const markerPath = join(cwd, "after-remove-marker.json");
|
|
231
|
+
assert.ok(existsSync(markerPath), "afterRemove hook must have executed and written marker");
|
|
232
|
+
const marker = JSON.parse(readFileSync(markerPath, "utf-8"));
|
|
233
|
+
assert.equal(typeof marker.receivedPath, "string", "hook must receive installedPath as string");
|
|
223
234
|
});
|
|
224
235
|
});
|
|
225
236
|
//# sourceMappingURL=package-commands.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-commands.test.js","sourceRoot":"","sources":["../../src/core/package-commands.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { Writable } from \"node:stream\";\nimport { describe, it } from \"node:test\";\nimport { runPackageCommand } from \"./package-commands.js\";\n\nfunction createCaptureStream() {\n\tlet output = \"\";\n\tconst stream = new Writable({\n\t\twrite(chunk, _encoding, callback) {\n\t\t\toutput += chunk.toString();\n\t\t\tcallback();\n\t\t},\n\t}) as unknown as NodeJS.WriteStream;\n\treturn { stream, getOutput: () => output };\n}\n\nfunction writePackage(root: string, files: Record<string, string>): void {\n\tfor (const [relPath, content] of Object.entries(files)) {\n\t\tconst abs = join(root, relPath);\n\t\tmkdirSync(join(abs, \"..\"), { recursive: true });\n\t\twriteFileSync(abs, content, \"utf-8\");\n\t}\n}\n\ndescribe(\"runPackageCommand lifecycle hooks\", () => {\n\tit(\"executes registered beforeInstall and afterInstall handlers for local packages\", async () => {\n\t\tconst root = mkdtempSync(join(tmpdir(), \"pi-lifecycle-install-\"));\n\t\tconst cwd = join(root, \"cwd\");\n\t\tconst agentDir = join(root, \"agent\");\n\t\tconst extensionDir = join(root, \"ext-registered\");\n\t\tmkdirSync(cwd, { recursive: true });\n\t\tmkdirSync(agentDir, { recursive: true });\n\t\tmkdirSync(extensionDir, { recursive: true });\n\n\t\ttry {\n\t\t\twritePackage(extensionDir, {\n\t\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\t\tname: \"ext-registered\",\n\t\t\t\t\ttype: \"module\",\n\t\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t\t}),\n\t\t\t\t\"index.js\": `\n\t\t\t\t\timport { writeFileSync } from \"node:fs\";\n\t\t\t\t\timport { join } from \"node:path\";\n\t\t\t\t\texport default function (pi) {\n\t\t\t\t\t\tpi.registerBeforeInstall((ctx) => {\n\t\t\t\t\t\t\twriteFileSync(join(ctx.installedPath, \"before-install-ran.txt\"), \"ok\", \"utf-8\");\n\t\t\t\t\t\t});\n\t\t\t\t\t\tpi.registerAfterInstall((ctx) => {\n\t\t\t\t\t\t\twriteFileSync(join(ctx.installedPath, \"after-install-ran.txt\"), \"ok\", \"utf-8\");\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t`,\n\t\t\t});\n\n\t\t\tconst stdout = createCaptureStream();\n\t\t\tconst stderr = createCaptureStream();\n\t\t\tconst result = await runPackageCommand({\n\t\t\t\tappName: \"pi\",\n\t\t\t\targs: [\"install\", extensionDir],\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tstdout: stdout.stream,\n\t\t\t\tstderr: stderr.stream,\n\t\t\t});\n\n\t\t\tassert.equal(result.handled, true);\n\t\t\tassert.equal(result.exitCode, 0);\n\t\t\tassert.equal(readFileSync(join(extensionDir, \"before-install-ran.txt\"), \"utf-8\"), \"ok\");\n\t\t\tassert.equal(readFileSync(join(extensionDir, \"after-install-ran.txt\"), \"utf-8\"), \"ok\");\n\t\t\tassert.ok(stdout.getOutput().includes(`Installed ${extensionDir}`));\n\t\t} finally {\n\t\t\trmSync(root, { recursive: true, force: true });\n\t\t}\n\t});\n\n\tit(\"runs legacy named lifecycle hooks when no registered hooks exist\", async () => {\n\t\tconst root = mkdtempSync(join(tmpdir(), \"pi-lifecycle-legacy-\"));\n\t\tconst cwd = join(root, \"cwd\");\n\t\tconst agentDir = join(root, \"agent\");\n\t\tconst extensionDir = join(root, \"ext-legacy\");\n\t\tmkdirSync(cwd, { recursive: true });\n\t\tmkdirSync(agentDir, { recursive: true });\n\t\tmkdirSync(extensionDir, { recursive: true });\n\n\t\ttry {\n\t\t\twritePackage(extensionDir, {\n\t\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\t\tname: \"ext-legacy\",\n\t\t\t\t\ttype: \"module\",\n\t\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t\t}),\n\t\t\t\t\"index.js\": `\n\t\t\t\t\timport { writeFileSync } from \"node:fs\";\n\t\t\t\t\timport { join } from \"node:path\";\n\t\t\t\t\texport default function () {}\n\t\t\t\t\texport async function beforeInstall(ctx) {\n\t\t\t\t\t\twriteFileSync(join(ctx.installedPath, \"legacy-before-install.txt\"), \"ok\", \"utf-8\");\n\t\t\t\t\t}\n\t\t\t\t\texport async function afterInstall(ctx) {\n\t\t\t\t\t\twriteFileSync(join(ctx.installedPath, \"legacy-after-install.txt\"), \"ok\", \"utf-8\");\n\t\t\t\t\t}\n\t\t\t\t\texport async function beforeRemove(ctx) {\n\t\t\t\t\t\twriteFileSync(join(ctx.installedPath, \"legacy-before-remove.txt\"), \"ok\", \"utf-8\");\n\t\t\t\t\t}\n\t\t\t\t\texport async function afterRemove(ctx) {\n\t\t\t\t\t\twriteFileSync(join(ctx.installedPath, \"legacy-after-remove.txt\"), \"ok\", \"utf-8\");\n\t\t\t\t\t}\n\t\t\t\t`,\n\t\t\t});\n\n\t\t\tconst stdout = createCaptureStream();\n\t\t\tconst stderr = createCaptureStream();\n\t\t\tconst installResult = await runPackageCommand({\n\t\t\t\tappName: \"pi\",\n\t\t\t\targs: [\"install\", extensionDir],\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tstdout: stdout.stream,\n\t\t\t\tstderr: stderr.stream,\n\t\t\t});\n\n\t\t\tassert.equal(installResult.handled, true);\n\t\t\tassert.equal(installResult.exitCode, 0);\n\t\t\tassert.equal(readFileSync(join(extensionDir, \"legacy-before-install.txt\"), \"utf-8\"), \"ok\");\n\t\t\tassert.equal(readFileSync(join(extensionDir, \"legacy-after-install.txt\"), \"utf-8\"), \"ok\");\n\n\t\t\tconst removeResult = await runPackageCommand({\n\t\t\t\tappName: \"pi\",\n\t\t\t\targs: [\"remove\", extensionDir],\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tstdout: stdout.stream,\n\t\t\t\tstderr: stderr.stream,\n\t\t\t});\n\n\t\t\tassert.equal(removeResult.handled, true);\n\t\t\tassert.equal(removeResult.exitCode, 0);\n\t\t\tassert.equal(readFileSync(join(extensionDir, \"legacy-before-remove.txt\"), \"utf-8\"), \"ok\");\n\t\t\tassert.equal(readFileSync(join(extensionDir, \"legacy-after-remove.txt\"), \"utf-8\"), \"ok\");\n\t\t} finally {\n\t\t\trmSync(root, { recursive: true, force: true });\n\t\t}\n\t});\n\n\tit(\"skips lifecycle phases with no hooks declared\", async () => {\n\t\tconst root = mkdtempSync(join(tmpdir(), \"pi-lifecycle-skip-\"));\n\t\tconst cwd = join(root, \"cwd\");\n\t\tconst agentDir = join(root, \"agent\");\n\t\tconst extensionDir = join(root, \"ext-empty\");\n\t\tmkdirSync(cwd, { recursive: true });\n\t\tmkdirSync(agentDir, { recursive: true });\n\t\tmkdirSync(extensionDir, { recursive: true });\n\n\t\ttry {\n\t\t\twritePackage(extensionDir, {\n\t\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\t\tname: \"ext-empty\",\n\t\t\t\t\ttype: \"module\",\n\t\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t\t}),\n\t\t\t\t\"index.js\": `export default function () {}`,\n\t\t\t});\n\n\t\t\tconst stdout = createCaptureStream();\n\t\t\tconst stderr = createCaptureStream();\n\t\t\tconst installResult = await runPackageCommand({\n\t\t\t\tappName: \"pi\",\n\t\t\t\targs: [\"install\", extensionDir],\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tstdout: stdout.stream,\n\t\t\t\tstderr: stderr.stream,\n\t\t\t});\n\t\t\tassert.equal(installResult.handled, true);\n\t\t\tassert.equal(installResult.exitCode, 0);\n\n\t\t\tconst removeResult = await runPackageCommand({\n\t\t\t\tappName: \"pi\",\n\t\t\t\targs: [\"remove\", extensionDir],\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tstdout: stdout.stream,\n\t\t\t\tstderr: stderr.stream,\n\t\t\t});\n\t\t\tassert.equal(removeResult.handled, true);\n\t\t\tassert.equal(removeResult.exitCode, 0);\n\t\t\tassert.equal(stderr.getOutput().includes(\"Hook failed\"), false);\n\t\t} finally {\n\t\t\trmSync(root, { recursive: true, force: true });\n\t\t}\n\t});\n\n\tit(\"fails install when manifest runtime dependency is missing\", async () => {\n\t\tconst root = mkdtempSync(join(tmpdir(), \"pi-lifecycle-deps-\"));\n\t\tconst cwd = join(root, \"cwd\");\n\t\tconst agentDir = join(root, \"agent\");\n\t\tconst extensionDir = join(root, \"ext-runtime-deps\");\n\t\tmkdirSync(cwd, { recursive: true });\n\t\tmkdirSync(agentDir, { recursive: true });\n\t\tmkdirSync(extensionDir, { recursive: true });\n\n\t\ttry {\n\t\t\twritePackage(extensionDir, {\n\t\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\t\tname: \"ext-runtime-deps\",\n\t\t\t\t\ttype: \"module\",\n\t\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t\t}),\n\t\t\t\t\"index.js\": `export default function () {}`,\n\t\t\t\t\"extension-manifest.json\": JSON.stringify({\n\t\t\t\t\tid: \"ext-runtime-deps\",\n\t\t\t\t\tname: \"Runtime Dep Test\",\n\t\t\t\t\tversion: \"1.0.0\",\n\t\t\t\t\tdependencies: { runtime: [\"__definitely_missing_command_for_test__\"] },\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tconst stdout = createCaptureStream();\n\t\t\tconst stderr = createCaptureStream();\n\t\t\tconst result = await runPackageCommand({\n\t\t\t\tappName: \"pi\",\n\t\t\t\targs: [\"install\", extensionDir],\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tstdout: stdout.stream,\n\t\t\t\tstderr: stderr.stream,\n\t\t\t});\n\n\t\t\tassert.equal(result.handled, true);\n\t\t\tassert.equal(result.exitCode, 1);\n\t\t\tassert.ok(stderr.getOutput().includes(\"Missing runtime dependencies\"));\n\t\t} finally {\n\t\t\trmSync(root, { recursive: true, force: true });\n\t\t}\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"package-commands.test.js","sourceRoot":"","sources":["../../src/core/package-commands.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { Writable } from \"node:stream\";\nimport { describe, it } from \"node:test\";\nimport { runPackageCommand } from \"./package-commands.js\";\n\nfunction createCaptureStream() {\n\tlet output = \"\";\n\tconst stream = new Writable({\n\t\twrite(chunk, _encoding, callback) {\n\t\t\toutput += chunk.toString();\n\t\t\tcallback();\n\t\t},\n\t}) as unknown as NodeJS.WriteStream;\n\treturn { stream, getOutput: () => output };\n}\n\nfunction writePackage(root: string, files: Record<string, string>): void {\n\tfor (const [relPath, content] of Object.entries(files)) {\n\t\tconst abs = join(root, relPath);\n\t\tmkdirSync(join(abs, \"..\"), { recursive: true });\n\t\twriteFileSync(abs, content, \"utf-8\");\n\t}\n}\n\nfunction createTestDirs(prefix: string, t: { after: (fn: () => void) => void }) {\n\tconst root = mkdtempSync(join(tmpdir(), `pi-lifecycle-${prefix}-`));\n\tt.after(() => rmSync(root, { recursive: true, force: true }));\n\tconst cwd = join(root, \"cwd\");\n\tconst agentDir = join(root, \"agent\");\n\tconst extensionDir = join(root, `ext-${prefix}`);\n\tmkdirSync(cwd, { recursive: true });\n\tmkdirSync(agentDir, { recursive: true });\n\tmkdirSync(extensionDir, { recursive: true });\n\treturn { root, cwd, agentDir, extensionDir };\n}\n\ndescribe(\"runPackageCommand lifecycle hooks\", () => {\n\tit(\"executes registered beforeInstall and afterInstall handlers for local packages\", async (t) => {\n\t\tconst { cwd, agentDir, extensionDir } = createTestDirs(\"install\", t);\n\n\t\twritePackage(extensionDir, {\n\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\tname: \"ext-registered\",\n\t\t\t\ttype: \"module\",\n\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t}),\n\t\t\t\"index.js\": [\n\t\t\t\t'import { writeFileSync } from \"node:fs\";',\n\t\t\t\t'import { join } from \"node:path\";',\n\t\t\t\t\"export default function (pi) {\",\n\t\t\t\t\" pi.registerBeforeInstall((ctx) => {\",\n\t\t\t\t' writeFileSync(join(ctx.installedPath, \"before-install-ran.txt\"), \"ok\", \"utf-8\");',\n\t\t\t\t\" });\",\n\t\t\t\t\" pi.registerAfterInstall((ctx) => {\",\n\t\t\t\t' writeFileSync(join(ctx.installedPath, \"after-install-ran.txt\"), \"ok\", \"utf-8\");',\n\t\t\t\t\" });\",\n\t\t\t\t\"}\",\n\t\t\t].join(\"\\n\"),\n\t\t});\n\n\t\tconst stdout = createCaptureStream();\n\t\tconst stderr = createCaptureStream();\n\t\tconst result = await runPackageCommand({\n\t\t\tappName: \"pi\",\n\t\t\targs: [\"install\", extensionDir],\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tstdout: stdout.stream,\n\t\t\tstderr: stderr.stream,\n\t\t});\n\n\t\tassert.equal(result.handled, true);\n\t\tassert.equal(result.exitCode, 0);\n\t\tassert.equal(readFileSync(join(extensionDir, \"before-install-ran.txt\"), \"utf-8\"), \"ok\");\n\t\tassert.equal(readFileSync(join(extensionDir, \"after-install-ran.txt\"), \"utf-8\"), \"ok\");\n\t\tassert.ok(stdout.getOutput().includes(`Installed ${extensionDir}`));\n\t});\n\n\tit(\"runs legacy named lifecycle hooks when no registered hooks exist\", async (t) => {\n\t\tconst { cwd, agentDir, extensionDir } = createTestDirs(\"legacy\", t);\n\n\t\twritePackage(extensionDir, {\n\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\tname: \"ext-legacy\",\n\t\t\t\ttype: \"module\",\n\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t}),\n\t\t\t\"index.js\": [\n\t\t\t\t'import { writeFileSync } from \"node:fs\";',\n\t\t\t\t'import { join } from \"node:path\";',\n\t\t\t\t\"export default function () {}\",\n\t\t\t\t\"export async function beforeInstall(ctx) {\",\n\t\t\t\t' writeFileSync(join(ctx.installedPath, \"legacy-before-install.txt\"), \"ok\", \"utf-8\");',\n\t\t\t\t\"}\",\n\t\t\t\t\"export async function afterInstall(ctx) {\",\n\t\t\t\t' writeFileSync(join(ctx.installedPath, \"legacy-after-install.txt\"), \"ok\", \"utf-8\");',\n\t\t\t\t\"}\",\n\t\t\t\t\"export async function beforeRemove(ctx) {\",\n\t\t\t\t' writeFileSync(join(ctx.installedPath, \"legacy-before-remove.txt\"), \"ok\", \"utf-8\");',\n\t\t\t\t\"}\",\n\t\t\t\t\"export async function afterRemove(ctx) {\",\n\t\t\t\t' writeFileSync(join(ctx.installedPath, \"legacy-after-remove.txt\"), \"ok\", \"utf-8\");',\n\t\t\t\t\"}\",\n\t\t\t].join(\"\\n\"),\n\t\t});\n\n\t\tconst stdout = createCaptureStream();\n\t\tconst stderr = createCaptureStream();\n\t\tconst installResult = await runPackageCommand({\n\t\t\tappName: \"pi\",\n\t\t\targs: [\"install\", extensionDir],\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tstdout: stdout.stream,\n\t\t\tstderr: stderr.stream,\n\t\t});\n\n\t\tassert.equal(installResult.handled, true);\n\t\tassert.equal(installResult.exitCode, 0);\n\t\tassert.equal(readFileSync(join(extensionDir, \"legacy-before-install.txt\"), \"utf-8\"), \"ok\");\n\t\tassert.equal(readFileSync(join(extensionDir, \"legacy-after-install.txt\"), \"utf-8\"), \"ok\");\n\n\t\tconst removeResult = await runPackageCommand({\n\t\t\tappName: \"pi\",\n\t\t\targs: [\"remove\", extensionDir],\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tstdout: stdout.stream,\n\t\t\tstderr: stderr.stream,\n\t\t});\n\n\t\tassert.equal(removeResult.handled, true);\n\t\tassert.equal(removeResult.exitCode, 0);\n\t\tassert.equal(readFileSync(join(extensionDir, \"legacy-before-remove.txt\"), \"utf-8\"), \"ok\");\n\t\tassert.equal(readFileSync(join(extensionDir, \"legacy-after-remove.txt\"), \"utf-8\"), \"ok\");\n\t});\n\n\tit(\"skips lifecycle phases with no hooks declared\", async (t) => {\n\t\tconst { cwd, agentDir, extensionDir } = createTestDirs(\"skip\", t);\n\n\t\twritePackage(extensionDir, {\n\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\tname: \"ext-empty\",\n\t\t\t\ttype: \"module\",\n\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t}),\n\t\t\t\"index.js\": \"export default function () {}\",\n\t\t});\n\n\t\tconst stdout = createCaptureStream();\n\t\tconst stderr = createCaptureStream();\n\t\tconst installResult = await runPackageCommand({\n\t\t\tappName: \"pi\",\n\t\t\targs: [\"install\", extensionDir],\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tstdout: stdout.stream,\n\t\t\tstderr: stderr.stream,\n\t\t});\n\t\tassert.equal(installResult.handled, true);\n\t\tassert.equal(installResult.exitCode, 0);\n\n\t\tconst removeResult = await runPackageCommand({\n\t\t\tappName: \"pi\",\n\t\t\targs: [\"remove\", extensionDir],\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tstdout: stdout.stream,\n\t\t\tstderr: stderr.stream,\n\t\t});\n\t\tassert.equal(removeResult.handled, true);\n\t\tassert.equal(removeResult.exitCode, 0);\n\t\tassert.equal(stderr.getOutput().includes(\"Hook failed\"), false);\n\t});\n\n\tit(\"fails install when manifest runtime dependency is missing\", async (t) => {\n\t\tconst { cwd, agentDir, extensionDir } = createTestDirs(\"deps\", t);\n\n\t\twritePackage(extensionDir, {\n\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\tname: \"ext-runtime-deps\",\n\t\t\t\ttype: \"module\",\n\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t}),\n\t\t\t\"index.js\": \"export default function () {}\",\n\t\t\t\"extension-manifest.json\": JSON.stringify({\n\t\t\t\tid: \"ext-runtime-deps\",\n\t\t\t\tname: \"Runtime Dep Test\",\n\t\t\t\tversion: \"1.0.0\",\n\t\t\t\tdependencies: { runtime: [\"__definitely_missing_command_for_test__\"] },\n\t\t\t}),\n\t\t});\n\n\t\tconst stdout = createCaptureStream();\n\t\tconst stderr = createCaptureStream();\n\t\tconst result = await runPackageCommand({\n\t\t\tappName: \"pi\",\n\t\t\targs: [\"install\", extensionDir],\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tstdout: stdout.stream,\n\t\t\tstderr: stderr.stream,\n\t\t});\n\n\t\tassert.equal(result.handled, true);\n\t\tassert.equal(result.exitCode, 1);\n\t\tassert.ok(stderr.getOutput().includes(\"Missing runtime dependencies\"));\n\t});\n\n\tit(\"afterRemove hook receives installedPath even when directory is deleted\", async (t) => {\n\t\tconst { cwd, agentDir, extensionDir } = createTestDirs(\"after-remove\", t);\n\n\t\twritePackage(extensionDir, {\n\t\t\t\"package.json\": JSON.stringify({\n\t\t\t\tname: \"ext-after-remove\",\n\t\t\t\ttype: \"module\",\n\t\t\t\tpi: { extensions: [\"./index.js\"] },\n\t\t\t}),\n\t\t\t\"index.js\": [\n\t\t\t\t'import { writeFileSync, existsSync } from \"node:fs\";',\n\t\t\t\t'import { join } from \"node:path\";',\n\t\t\t\t\"export default function () {}\",\n\t\t\t\t\"export async function afterRemove(ctx) {\",\n\t\t\t\t' const marker = join(ctx.cwd, \"after-remove-marker.json\");',\n\t\t\t\t\" writeFileSync(marker, JSON.stringify({\",\n\t\t\t\t\" receivedPath: ctx.installedPath,\",\n\t\t\t\t\" pathExisted: existsSync(ctx.installedPath),\",\n\t\t\t\t' }), \"utf-8\");',\n\t\t\t\t\"}\",\n\t\t\t].join(\"\\n\"),\n\t\t});\n\n\t\tconst stdout = createCaptureStream();\n\t\tconst stderr = createCaptureStream();\n\n\t\tawait runPackageCommand({\n\t\t\tappName: \"pi\",\n\t\t\targs: [\"install\", extensionDir],\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tstdout: stdout.stream,\n\t\t\tstderr: stderr.stream,\n\t\t});\n\n\t\tawait runPackageCommand({\n\t\t\tappName: \"pi\",\n\t\t\targs: [\"remove\", extensionDir],\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tstdout: stdout.stream,\n\t\t\tstderr: stderr.stream,\n\t\t});\n\n\t\tconst markerPath = join(cwd, \"after-remove-marker.json\");\n\t\tassert.ok(existsSync(markerPath), \"afterRemove hook must have executed and written marker\");\n\t\tconst marker = JSON.parse(readFileSync(markerPath, \"utf-8\"));\n\t\tassert.equal(typeof marker.receivedPath, \"string\", \"hook must receive installedPath as string\");\n\t});\n});\n"]}
|
|
@@ -97,6 +97,7 @@ export class CompactionOrchestrator {
|
|
|
97
97
|
if (!this._deps.modelRegistry.isProviderRequestReady(model.provider)) {
|
|
98
98
|
throw new Error(`No API key for ${model.provider}`);
|
|
99
99
|
}
|
|
100
|
+
// undefined for externalCli/none providers — stripped at the streamSimple boundary (model-registry.ts)
|
|
100
101
|
const apiKey = await this._deps.modelRegistry.getApiKey(model, this._deps.getSessionId());
|
|
101
102
|
|
|
102
103
|
const pathEntries = this._deps.sessionManager.getBranch();
|
|
@@ -303,6 +304,7 @@ export class CompactionOrchestrator {
|
|
|
303
304
|
this._deps.emit({ type: "auto_compaction_end", result: undefined, aborted: false, willRetry: false });
|
|
304
305
|
return;
|
|
305
306
|
}
|
|
307
|
+
// undefined for externalCli/none providers — stripped at the streamSimple boundary (model-registry.ts)
|
|
306
308
|
const apiKey = await this._deps.modelRegistry.getApiKey(model, this._deps.getSessionId());
|
|
307
309
|
|
|
308
310
|
const pathEntries = this._deps.sessionManager.getBranch();
|
|
@@ -1242,7 +1242,8 @@ export interface ExtensionAPI {
|
|
|
1242
1242
|
export interface ProviderConfig {
|
|
1243
1243
|
/** Auth behavior for provider availability and request key handling. Defaults to "apiKey". */
|
|
1244
1244
|
authMode?: "apiKey" | "oauth" | "externalCli" | "none";
|
|
1245
|
-
/** Optional readiness check. Return false if the provider cannot accept requests (e.g., CLI not authenticated, API key invalid).
|
|
1245
|
+
/** Optional readiness check. Return false if the provider cannot accept requests (e.g., CLI not authenticated, API key invalid).
|
|
1246
|
+
* Called before default auth checks. Trusted at the same level as extension code — extensions already have arbitrary code execution. */
|
|
1246
1247
|
isReady?: () => boolean;
|
|
1247
1248
|
/** Base URL for the API endpoint. Required when defining models. */
|
|
1248
1249
|
baseUrl?: string;
|