@fitchmultz/pi-subagents 0.50.0 → 0.51.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 +51 -2
- package/README.md +36 -5
- package/dist/agent/contracts.js +6 -24
- package/dist/agent/host.js +3 -16
- package/dist/agent/index.js +207 -173
- package/dist/agent/journal-tail.js +115 -156
- package/dist/agent/launch.js +20 -8
- package/dist/agent/legacy.js +65 -23
- package/dist/agent/notifications.js +138 -47
- package/dist/agent/observation-state.js +246 -0
- package/dist/agent/observation-view.js +258 -0
- package/dist/agent/observation.js +346 -0
- package/dist/agent/observe-card.js +243 -0
- package/dist/agent/observe-chrome.js +85 -0
- package/dist/agent/observe-client.js +285 -0
- package/dist/agent/observe-layout.js +65 -0
- package/dist/agent/observe-reading.js +84 -0
- package/dist/agent/observe-screen.js +400 -96
- package/dist/agent/observe-transcript.js +382 -0
- package/dist/agent/observe.js +250 -43
- package/dist/agent/process.js +198 -25
- package/dist/agent/receipts.js +92 -20
- package/dist/agent/runner.js +125 -20
- package/dist/agent/shell.js +2 -1
- package/dist/agent/storage.js +29 -12
- package/dist/agent/tool-schemas.js +20 -0
- package/dist/agent/typebox.js +10 -5
- package/dist/agent/usage.js +0 -115
- package/dist/agent/view.js +46 -16
- package/dist/agent/wake.js +99 -0
- package/dist/build-info.js +1 -1
- package/dist/intercom-client.d.ts +26 -0
- package/dist/intercom-client.js +45 -0
- package/dist/pi-intercom/agent-dir.d.ts +1 -0
- package/dist/pi-intercom/bridge-session.js +2 -1
- package/dist/pi-intercom/broker/broker.js +27 -21
- package/dist/pi-intercom/broker/client-last.d.ts +13 -0
- package/dist/pi-intercom/broker/client-last.js +17 -5
- package/dist/pi-intercom/broker/client.d.ts +60 -0
- package/dist/pi-intercom/broker/client.js +47 -16
- package/dist/pi-intercom/broker/connection.d.ts +29 -0
- package/dist/pi-intercom/broker/framing.d.ts +17 -0
- package/dist/pi-intercom/broker/framing.js +10 -7
- package/dist/pi-intercom/broker/guard.js +23 -0
- package/dist/pi-intercom/broker/last.d.ts +26 -0
- package/dist/pi-intercom/broker/last.js +57 -32
- package/dist/pi-intercom/broker/paths.d.ts +13 -0
- package/dist/pi-intercom/broker/paths.js +35 -12
- package/dist/pi-intercom/broker/pid.js +5 -1
- package/dist/pi-intercom/broker/server-connection.js +19 -0
- package/dist/pi-intercom/broker/snapshot-reader.d.ts +9 -0
- package/dist/pi-intercom/broker/snapshots.d.ts +29 -0
- package/dist/pi-intercom/broker/targets.d.ts +9 -0
- package/dist/pi-intercom/connection.js +10 -2
- package/dist/pi-intercom/identity.js +6 -5
- package/dist/pi-intercom/inbound-delivery.js +16 -60
- package/dist/pi-intercom/inbound-journal.js +83 -6
- package/dist/pi-intercom/inbound-record.js +18 -1
- package/dist/pi-intercom/inbound.js +12 -38
- package/dist/pi-intercom/index.js +3 -0
- package/dist/pi-intercom/last-message.js +4 -16
- package/dist/pi-intercom/lifecycle.js +88 -3
- package/dist/pi-intercom/outbound.js +5 -15
- package/dist/pi-intercom/reply-tracker.js +7 -6
- package/dist/pi-intercom/reply-wait.js +2 -2
- package/dist/pi-intercom/session-targets.d.ts +24 -0
- package/dist/pi-intercom/tool-registration.js +4 -1
- package/dist/pi-intercom/tool-results.js +5 -7
- package/dist/pi-intercom/tool-schemas.js +12 -26
- package/dist/pi-intercom/types.d.ts +212 -0
- package/dist/pi-intercom/types.js +54 -3
- package/dist/pi-intercom/validation.d.ts +12 -0
- package/dist/pi-intercom/validation.js +3 -0
- package/dist/shared/bounded-json.js +151 -0
- package/dist/shared/compact-cards.js +66 -0
- package/dist/shared/journal-frames.js +3 -6
- package/dist/shared/json-projection.js +267 -129
- package/dist/shared/native-journal.js +123 -56
- package/dist/shared/post-exit-stdio-guard.js +120 -7
- package/dist/shared/tui-action.js +29 -0
- package/dist/shared/unknown.d.ts +9 -0
- package/docs/code-quality.md +2 -0
- package/docs/development.md +40 -1
- package/docs/intercom-bridge.md +9 -4
- package/docs/intercom.md +226 -6
- package/docs/performance.md +87 -11
- package/docs/reference.md +157 -20
- package/docs/retired-history-maintenance.md +252 -0
- package/package.json +28 -15
- package/scripts/archive-retired-history.mjs +464 -0
- package/scripts/build.mjs +48 -28
- package/scripts/measure-size.mjs +1 -1
- package/scripts/native-package-smoke.mjs +153 -12
- package/scripts/package-smoke.mjs +80 -11
- package/scripts/prepare.mjs +2 -2
- package/scripts/real-pi-live.mjs +377 -0
- package/scripts/real-pi-processes.mjs +6 -1
- package/scripts/real-pi-smoke.mjs +6 -282
- package/scripts/run-tests.mjs +4 -2
- package/scripts/typescript.mjs +35 -0
- package/skills/pi-intercom/SKILL.md +2 -1
- package/skills/pi-subagents/SKILL.md +23 -5
- package/src/agent/contracts.ts +8 -34
- package/src/agent/host.ts +19 -20
- package/src/agent/index.ts +224 -190
- package/src/agent/journal-tail.ts +141 -153
- package/src/agent/launch.ts +33 -9
- package/src/agent/legacy.ts +85 -31
- package/src/agent/notifications.ts +192 -67
- package/src/agent/observation-state.ts +277 -0
- package/src/agent/observation-view.ts +267 -0
- package/src/agent/observation.ts +405 -0
- package/src/agent/observe-card.ts +304 -0
- package/src/agent/observe-chrome.ts +170 -0
- package/src/agent/observe-client.ts +318 -0
- package/src/agent/observe-layout.ts +79 -0
- package/src/agent/observe-reading.ts +97 -0
- package/src/agent/observe-screen.ts +443 -129
- package/src/agent/observe-transcript.ts +434 -0
- package/src/agent/observe.ts +304 -71
- package/src/agent/process.ts +240 -34
- package/src/agent/receipts.ts +114 -24
- package/src/agent/runner.ts +125 -27
- package/src/agent/shell.ts +2 -1
- package/src/agent/storage.ts +27 -11
- package/src/agent/tool-schemas.ts +33 -0
- package/src/agent/typebox.ts +12 -7
- package/src/agent/usage.ts +0 -130
- package/src/agent/view.ts +70 -20
- package/src/agent/wake.ts +107 -0
- package/src/intercom-client.ts +108 -0
- package/src/pi-intercom/bridge-session.ts +2 -2
- package/src/pi-intercom/broker/broker.ts +27 -23
- package/src/pi-intercom/broker/client-last.ts +25 -12
- package/src/pi-intercom/broker/client.ts +55 -33
- package/src/pi-intercom/broker/framing.ts +11 -8
- package/src/pi-intercom/broker/guard.ts +33 -0
- package/src/pi-intercom/broker/last.ts +86 -33
- package/src/pi-intercom/broker/paths.ts +39 -12
- package/src/pi-intercom/broker/pid.ts +6 -1
- package/src/pi-intercom/broker/server-connection.ts +25 -0
- package/src/pi-intercom/connection.ts +21 -10
- package/src/pi-intercom/identity.ts +8 -5
- package/src/pi-intercom/inbound-delivery.ts +20 -66
- package/src/pi-intercom/inbound-journal.ts +103 -7
- package/src/pi-intercom/inbound-record.ts +21 -4
- package/src/pi-intercom/inbound.ts +18 -49
- package/src/pi-intercom/index.ts +3 -0
- package/src/pi-intercom/last-message.ts +10 -19
- package/src/pi-intercom/lifecycle.ts +117 -14
- package/src/pi-intercom/outbound.ts +7 -16
- package/src/pi-intercom/reply-tracker.ts +8 -6
- package/src/pi-intercom/reply-wait.ts +3 -2
- package/src/pi-intercom/runtime-types.ts +0 -1
- package/src/pi-intercom/tool-registration.ts +4 -1
- package/src/pi-intercom/tool-results.ts +10 -9
- package/src/pi-intercom/tool-schemas.ts +12 -44
- package/src/pi-intercom/types.ts +115 -4
- package/src/pi-intercom/validation.ts +4 -0
- package/src/shared/bounded-json.ts +162 -0
- package/src/shared/compact-cards.ts +118 -0
- package/src/shared/journal-frames.ts +3 -19
- package/src/shared/json-projection.ts +267 -147
- package/src/shared/native-journal.ts +157 -75
- package/src/shared/post-exit-stdio-guard.ts +165 -7
- package/src/shared/tui-action.ts +39 -0
- package/tsconfig.client.json +8 -0
- package/tsconfig.json +1 -0
- package/src/shared/stream-json.d.ts +0 -10
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Runtime-only package probe: selected native SDK/CLI, real packed actor and private broker.
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
+
import { execFile as execFileCallback } from "node:child_process";
|
|
4
|
+
import { promisify } from "node:util";
|
|
3
5
|
import {
|
|
4
6
|
mkdtempSync,
|
|
5
7
|
mkdirSync,
|
|
@@ -10,13 +12,15 @@ import {
|
|
|
10
12
|
existsSync,
|
|
11
13
|
} from "node:fs";
|
|
12
14
|
import { tmpdir } from "node:os";
|
|
13
|
-
import { join, resolve } from "node:path";
|
|
15
|
+
import { dirname, join, resolve } from "node:path";
|
|
14
16
|
import { setTimeout as delay } from "node:timers/promises";
|
|
15
17
|
import { pathToFileURL } from "node:url";
|
|
16
18
|
import { createRequire } from "node:module";
|
|
17
19
|
import { hostCli, hostIndex, hostRoot } from "./compat-host.mjs";
|
|
18
20
|
import { SmokeProcesses } from "./real-pi-processes.mjs";
|
|
19
21
|
|
|
22
|
+
const execFile = promisify(execFileCallback);
|
|
23
|
+
|
|
20
24
|
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
21
25
|
console.log(
|
|
22
26
|
"Usage: node scripts/native-package-smoke.mjs [package-root]\n\nLoad the single compiled entry using the selected native host. Exercise all three eager package tools and a real actor prompt/toolResult/completion with a credential-free provider, then verify bundled CLI startup and shutdown. No paid model calls.\nExit codes: 0 passed; 1 native execution or cleanup failed.",
|
|
@@ -25,6 +29,8 @@ if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
const packageRoot = realpathSync(resolve(process.argv[2] ?? "."));
|
|
32
|
+
const consumerDir = process.argv[3];
|
|
33
|
+
const consumerScript = process.argv[4];
|
|
28
34
|
const root = mkdtempSync(join(tmpdir(), "ps-native-"));
|
|
29
35
|
const agentDir = join(root, "agent");
|
|
30
36
|
mkdirSync(join(agentDir, "extensions"), { recursive: true });
|
|
@@ -105,16 +111,24 @@ export default function(pi) {
|
|
|
105
111
|
assert.deepEqual([...tools].sort(), ${JSON.stringify(expectedTools)});
|
|
106
112
|
}
|
|
107
113
|
observe({ tools, requested: true });
|
|
108
|
-
return fauxAssistantMessage(fauxToolCall(child ? "packed_probe" : "delegate", child ? { value: "native-tool-input" } : { prompt: ${JSON.stringify(prompt)}, name: "packed-native"
|
|
114
|
+
return fauxAssistantMessage(fauxToolCall(child ? "packed_probe" : "delegate", child ? { value: "native-tool-input" } : { prompt: ${JSON.stringify(prompt)}, name: "packed-native" }), { stopReason: "toolUse" });
|
|
109
115
|
},
|
|
110
116
|
(context) => {
|
|
111
117
|
const result = context.messages.findLast(message => message.role === "toolResult");
|
|
112
118
|
assert.equal(result?.isError ?? false, false);
|
|
113
119
|
assert.equal(result?.toolName, child ? "packed_probe" : "delegate");
|
|
114
|
-
|
|
120
|
+
// The parent gets only an honest launch receipt; the child's outcome arrives later.
|
|
121
|
+
assert.ok(result.content.some(part => part.type === "text" && (child ? part.text.includes("PACKED_TOOL_RESULT") : part.text.includes("Launch accepted") && !part.text.includes("PACKED_NATIVE_COMPLETE"))));
|
|
115
122
|
observe({ consumedResult: true, calls: faux.state.callCount });
|
|
116
|
-
return fauxAssistantMessage(child ? "PACKED_NATIVE_COMPLETE" : "
|
|
117
|
-
}
|
|
123
|
+
return fauxAssistantMessage(child ? "PACKED_NATIVE_COMPLETE" : "PACKED_LAUNCH_RECEIPT_SEEN");
|
|
124
|
+
},
|
|
125
|
+
...(child ? [] : [(context) => {
|
|
126
|
+
const notice = context.messages.at(-1);
|
|
127
|
+
const text = typeof notice.content === "string" ? notice.content : notice.content.map(part => part.text ?? "").join("");
|
|
128
|
+
assert.ok(text.includes(": completed. \\nPACKED_NATIVE_COMPLETE\\n"), text);
|
|
129
|
+
observe({ consumedCompletion: true, calls: faux.state.callCount });
|
|
130
|
+
return fauxAssistantMessage("PACKED_PARENT_COMPLETE");
|
|
131
|
+
}])
|
|
118
132
|
]);
|
|
119
133
|
pi.registerProvider(faux.provider);
|
|
120
134
|
}
|
|
@@ -141,6 +155,7 @@ const processes = new SmokeProcesses({
|
|
|
141
155
|
let session;
|
|
142
156
|
let watchdog;
|
|
143
157
|
let brokerError;
|
|
158
|
+
let intercomEvents;
|
|
144
159
|
const brokerRun = processes
|
|
145
160
|
.run("private broker", process.execPath, [join(packageRoot, "dist/pi-intercom/broker/broker.js")])
|
|
146
161
|
.catch((error) => {
|
|
@@ -166,14 +181,21 @@ try {
|
|
|
166
181
|
noContextFiles: true,
|
|
167
182
|
noPromptTemplates: true,
|
|
168
183
|
noThemes: true,
|
|
184
|
+
extensionFactories: consumerScript
|
|
185
|
+
? [
|
|
186
|
+
(pi) => {
|
|
187
|
+
intercomEvents = pi.events;
|
|
188
|
+
},
|
|
189
|
+
]
|
|
190
|
+
: [],
|
|
169
191
|
});
|
|
170
192
|
await loader.reload();
|
|
171
193
|
assert.deepEqual(loader.getExtensions().errors, []);
|
|
172
194
|
assert.deepEqual(loader.getExtensions().warnings ?? [], []);
|
|
173
195
|
assert.equal(
|
|
174
196
|
loader.getExtensions().extensions.length,
|
|
175
|
-
2,
|
|
176
|
-
"one package entry plus credential-free provider
|
|
197
|
+
consumerScript ? 3 : 2,
|
|
198
|
+
"one package entry plus credential-free provider and optional client observer fixtures",
|
|
177
199
|
);
|
|
178
200
|
const modelRuntime = await sdk.ModelRuntime.create({
|
|
179
201
|
credentials: new ai.InMemoryCredentialStore(),
|
|
@@ -218,6 +240,29 @@ try {
|
|
|
218
240
|
}, 30_000);
|
|
219
241
|
await session.prompt("Exercise the packed native delegate.", { expandPromptTemplates: false });
|
|
220
242
|
await session.waitForIdle();
|
|
243
|
+
assert.equal(
|
|
244
|
+
session.getLastAssistantText(),
|
|
245
|
+
"PACKED_LAUNCH_RECEIPT_SEEN",
|
|
246
|
+
JSON.stringify({
|
|
247
|
+
errors,
|
|
248
|
+
messages: events.filter(
|
|
249
|
+
(event) =>
|
|
250
|
+
(event.type === "message_end" && event.message?.role === "assistant") ||
|
|
251
|
+
event.type === "tool_execution_end",
|
|
252
|
+
),
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
const completionDeadline = Date.now() + 30_000;
|
|
256
|
+
while (session.getLastAssistantText() !== "PACKED_PARENT_COMPLETE") {
|
|
257
|
+
// Observe the native completion notification turn, not a fixed delay.
|
|
258
|
+
assert.ok(
|
|
259
|
+
Date.now() < completionDeadline,
|
|
260
|
+
`native completion notification resumes the parent: ${JSON.stringify(session.messages.slice(-3))}`,
|
|
261
|
+
);
|
|
262
|
+
// oxlint-disable-next-line no-await-in-loop
|
|
263
|
+
await delay(25);
|
|
264
|
+
}
|
|
265
|
+
await session.waitForIdle();
|
|
221
266
|
clearTimeout(watchdog);
|
|
222
267
|
assert.equal(
|
|
223
268
|
session.getLastAssistantText(),
|
|
@@ -235,11 +280,13 @@ try {
|
|
|
235
280
|
(event) => event.type === "tool_execution_start" && event.toolName === "delegate",
|
|
236
281
|
);
|
|
237
282
|
assert.equal(starts.length, 1, "one real native delegate call, no fabricated wire events");
|
|
238
|
-
const
|
|
283
|
+
const receipt = events.find(
|
|
239
284
|
(event) => event.type === "tool_execution_end" && event.toolName === "delegate",
|
|
240
285
|
);
|
|
241
|
-
assert.ok(
|
|
242
|
-
|
|
286
|
+
assert.ok(receipt && !receipt.isError, JSON.stringify(receipt));
|
|
287
|
+
assert.equal(receipt.result.details.receipt, "launch");
|
|
288
|
+
const run = (await execute("agent_runs", { action: "inspect", id: receipt.result.details.id }))
|
|
289
|
+
.details;
|
|
243
290
|
assert.equal(run.status, "completed");
|
|
244
291
|
assert.equal(run.output.text, "PACKED_NATIVE_COMPLETE");
|
|
245
292
|
const childEntries = readFileSync(run.sessionFile, "utf8")
|
|
@@ -280,6 +327,11 @@ try {
|
|
|
280
327
|
observed.filter((item) => !item.child && item.consumedResult && item.calls === 2).length,
|
|
281
328
|
1,
|
|
282
329
|
);
|
|
330
|
+
assert.equal(
|
|
331
|
+
observed.filter((item) => !item.child && item.consumedCompletion && item.calls === 3).length,
|
|
332
|
+
1,
|
|
333
|
+
"the parent is resumed exactly once by the native completion notification",
|
|
334
|
+
);
|
|
283
335
|
assert.equal(networkAttempts, 0);
|
|
284
336
|
assert.equal(
|
|
285
337
|
observed.some((item) => item.networkAttempt),
|
|
@@ -287,13 +339,102 @@ try {
|
|
|
287
339
|
);
|
|
288
340
|
assert.deepEqual(errors, []);
|
|
289
341
|
|
|
342
|
+
if (consumerScript) {
|
|
343
|
+
let target;
|
|
344
|
+
intercomEvents.emit("pi-intercom:context-query", {
|
|
345
|
+
version: 1,
|
|
346
|
+
respond: (snapshot) => {
|
|
347
|
+
target = snapshot;
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
assert.ok(target?.connected && target.peerId && target.rootSessionId && target.incarnation);
|
|
351
|
+
const guard = {
|
|
352
|
+
rootSessionId: target.rootSessionId,
|
|
353
|
+
peerId: target.peerId,
|
|
354
|
+
incarnation: target.incarnation,
|
|
355
|
+
applicationGuard: "package-consent-1",
|
|
356
|
+
};
|
|
357
|
+
let consent;
|
|
358
|
+
intercomEvents.emit("pi-intercom:application-guard", {
|
|
359
|
+
version: 1,
|
|
360
|
+
target: guard,
|
|
361
|
+
revision: guard.applicationGuard,
|
|
362
|
+
respond: (result) => {
|
|
363
|
+
consent = result;
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
assert.equal(consent.applicationGuard, guard.applicationGuard);
|
|
367
|
+
const consumerHome = join(root, "consumer-home");
|
|
368
|
+
mkdirSync(consumerHome);
|
|
369
|
+
const brokerPid = Number(
|
|
370
|
+
readFileSync(join(process.env.PI_INTERCOM_RUNTIME_DIR, "broker.pid"), "utf8").split("\n")[0],
|
|
371
|
+
);
|
|
372
|
+
const consumerOptions = {
|
|
373
|
+
cwd: consumerDir,
|
|
374
|
+
env: {
|
|
375
|
+
HOME: consumerHome,
|
|
376
|
+
PATH: process.env.PATH,
|
|
377
|
+
PI_CODING_AGENT_DIR: join(consumerHome, "agent"),
|
|
378
|
+
PI_INTERCOM_RUNTIME_DIR: process.env.PI_INTERCOM_RUNTIME_DIR,
|
|
379
|
+
S3_ROOT: guard.rootSessionId,
|
|
380
|
+
S3_PEER: guard.peerId,
|
|
381
|
+
S3_INCARNATION: guard.incarnation,
|
|
382
|
+
S3_GUARD: guard.applicationGuard,
|
|
383
|
+
S3_BROKER_PID: String(brokerPid),
|
|
384
|
+
},
|
|
385
|
+
timeout: 30_000,
|
|
386
|
+
maxBuffer: 1024 * 1024,
|
|
387
|
+
};
|
|
388
|
+
const turns = events.filter((event) => event.type === "turn_start").length;
|
|
389
|
+
try {
|
|
390
|
+
const { stdout, stderr } = await execFile(
|
|
391
|
+
process.execPath,
|
|
392
|
+
[
|
|
393
|
+
"--permission",
|
|
394
|
+
"--allow-fs-read=*",
|
|
395
|
+
"--allow-fs-write=*",
|
|
396
|
+
"--input-type=module",
|
|
397
|
+
"-e",
|
|
398
|
+
readFileSync(consumerScript, "utf8"),
|
|
399
|
+
],
|
|
400
|
+
consumerOptions,
|
|
401
|
+
);
|
|
402
|
+
process.stdout.write(stdout);
|
|
403
|
+
process.stderr.write(stderr);
|
|
404
|
+
assert.equal(events.filter((event) => event.type === "turn_start").length, turns);
|
|
405
|
+
} finally {
|
|
406
|
+
// The consumer's failure/timeout must never leave this fixture's broker stopped.
|
|
407
|
+
process.kill(brokerPid, "SIGCONT");
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
290
411
|
const marker = join(root, "cli.json");
|
|
291
412
|
const observer = join(root, "observer.mjs");
|
|
292
413
|
writeFileSync(
|
|
293
414
|
observer,
|
|
294
|
-
`import
|
|
415
|
+
`import assert from "node:assert/strict";
|
|
416
|
+
import { writeFileSync } from "node:fs";
|
|
417
|
+
import { Type } from "typebox";
|
|
418
|
+
import { Assert } from "typebox/value";
|
|
419
|
+
import { Type as AgentType, Assert as AgentAssert } from ${JSON.stringify(pathToFileURL(join(packageRoot, "dist/agent/typebox.js")).href)};
|
|
420
|
+
export default function(pi) {
|
|
421
|
+
// Native development graphs can resolve local peers before Jiti runs.
|
|
422
|
+
// Production-only installs must instead reuse the bundled host's virtual modules.
|
|
423
|
+
if (${!existsSync(join(packageRoot, "node_modules/typebox"))}) {
|
|
424
|
+
assert.equal(AgentType, Type, "extension schemas reuse Pi's TypeBox instance");
|
|
425
|
+
assert.equal(AgentAssert, Assert, "extension validation reuses Pi's TypeBox instance");
|
|
426
|
+
}
|
|
427
|
+
pi.on("session_start", (_event, ctx) => {
|
|
428
|
+
writeFileSync(${JSON.stringify(marker)}, JSON.stringify(pi.getActiveTools()));
|
|
429
|
+
ctx.shutdown();
|
|
430
|
+
});
|
|
431
|
+
}`,
|
|
295
432
|
);
|
|
296
|
-
const cliEnv = {
|
|
433
|
+
const cliEnv = {
|
|
434
|
+
...process.env,
|
|
435
|
+
PATH:
|
|
436
|
+
process.platform === "android" ? `${dirname(process.execPath)}:/system/bin` : "/usr/bin:/bin",
|
|
437
|
+
};
|
|
297
438
|
delete cliEnv.PI_PACKAGE_DIR;
|
|
298
439
|
const cliProcesses = new SmokeProcesses({
|
|
299
440
|
cwd: root,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { createRequire } from "node:module";
|
|
5
4
|
import {
|
|
6
5
|
cpSync,
|
|
7
6
|
existsSync,
|
|
@@ -13,9 +12,10 @@ import {
|
|
|
13
12
|
writeFileSync,
|
|
14
13
|
} from "node:fs";
|
|
15
14
|
import { tmpdir } from "node:os";
|
|
16
|
-
import { join } from "node:path";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
17
16
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
17
|
import { hostRoot } from "./compat-host.mjs";
|
|
18
|
+
import { compilerInvocation } from "./typescript.mjs";
|
|
19
19
|
|
|
20
20
|
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
21
21
|
console.log(
|
|
@@ -95,12 +95,42 @@ function installProduction(pack) {
|
|
|
95
95
|
);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
-
return [
|
|
98
|
+
return [
|
|
99
|
+
{ packageRoot: installed, consumerDir: installDir },
|
|
100
|
+
{ packageRoot: standalone, consumerDir: standalone },
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function verifyDeclarations(consumerDir) {
|
|
105
|
+
const contract = join(consumerDir, "public-client.test-d.ts");
|
|
106
|
+
cpSync(new URL("../test/fixtures/intercom-client-contract.test-d.ts", import.meta.url), contract);
|
|
107
|
+
const compiler = compilerInvocation();
|
|
108
|
+
run(
|
|
109
|
+
compiler.command,
|
|
110
|
+
[
|
|
111
|
+
...compiler.args,
|
|
112
|
+
"--ignoreConfig",
|
|
113
|
+
"--noEmit",
|
|
114
|
+
"--strict",
|
|
115
|
+
"--target",
|
|
116
|
+
"ES2025",
|
|
117
|
+
"--module",
|
|
118
|
+
"NodeNext",
|
|
119
|
+
"--moduleResolution",
|
|
120
|
+
"NodeNext",
|
|
121
|
+
"--types",
|
|
122
|
+
"node",
|
|
123
|
+
"--typeRoots",
|
|
124
|
+
fileURLToPath(new URL("../node_modules/@types", import.meta.url)),
|
|
125
|
+
contract,
|
|
126
|
+
],
|
|
127
|
+
consumerDir,
|
|
128
|
+
);
|
|
99
129
|
}
|
|
100
130
|
|
|
101
|
-
async function verifyRuntime(packageRoot) {
|
|
131
|
+
async function verifyRuntime({ packageRoot, consumerDir }) {
|
|
102
132
|
verifyManifest(JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8")));
|
|
103
|
-
|
|
133
|
+
verifyDeclarations(consumerDir);
|
|
104
134
|
const sdk = await import(pathToFileURL(join(hostRoot, "dist/index.js")).href);
|
|
105
135
|
const nativeHost = await import(pathToFileURL(join(packageRoot, "dist/agent/host.js")).href);
|
|
106
136
|
assert.equal(
|
|
@@ -108,11 +138,28 @@ async function verifyRuntime(packageRoot) {
|
|
|
108
138
|
sdk,
|
|
109
139
|
"actor must use the exact selected host SDK",
|
|
110
140
|
);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
141
|
+
run(
|
|
142
|
+
process.execPath,
|
|
143
|
+
[
|
|
144
|
+
"--input-type=module",
|
|
145
|
+
"-e",
|
|
146
|
+
`import assert from "node:assert/strict";
|
|
147
|
+
import { createRequire } from "node:module";
|
|
148
|
+
import { pathToFileURL } from "node:url";
|
|
149
|
+
const require = createRequire(${JSON.stringify(join(hostRoot, "dist/index.js"))});
|
|
150
|
+
const hostTypebox = await import(pathToFileURL(require.resolve("typebox")).href);
|
|
151
|
+
const hostValue = await import(pathToFileURL(require.resolve("typebox/value")).href);
|
|
152
|
+
const native = await import(${JSON.stringify(pathToFileURL(join(packageRoot, "dist/agent/typebox.js")).href)});
|
|
153
|
+
assert.equal(native.Type, hostTypebox.Type, "detached schemas use the selected host");
|
|
154
|
+
assert.equal(native.Assert, hostValue.Assert, "detached validation uses the selected host");`,
|
|
155
|
+
],
|
|
156
|
+
root,
|
|
157
|
+
{
|
|
158
|
+
...process.env,
|
|
159
|
+
PI_INTERCOM_ROOT_SESSION_ID: "package-smoke",
|
|
160
|
+
PI_INTERCOM_PARENT_SESSION_ID: "package-smoke",
|
|
161
|
+
},
|
|
114
162
|
);
|
|
115
|
-
assert.equal(nativeTypebox.Type, hostTypebox.Type, "shared schemas use the selected host");
|
|
116
163
|
const broker = await import(
|
|
117
164
|
pathToFileURL(join(packageRoot, "dist/pi-intercom/broker/spawn.js")).href
|
|
118
165
|
);
|
|
@@ -123,12 +170,30 @@ async function verifyRuntime(packageRoot) {
|
|
|
123
170
|
root,
|
|
124
171
|
);
|
|
125
172
|
assert.match(help, /Usage: node scripts\/intercom-bridge-credentials.mjs/);
|
|
173
|
+
const maintenanceHelp = run(
|
|
174
|
+
process.execPath,
|
|
175
|
+
[join(packageRoot, "scripts/archive-retired-history.mjs"), "--help"],
|
|
176
|
+
root,
|
|
177
|
+
);
|
|
178
|
+
assert.match(maintenanceHelp, /Offline-only opt-in maintenance/);
|
|
126
179
|
process.stdout.write(
|
|
127
180
|
run(
|
|
128
181
|
process.execPath,
|
|
129
|
-
[
|
|
182
|
+
[
|
|
183
|
+
fileURLToPath(new URL("./native-package-smoke.mjs", import.meta.url)),
|
|
184
|
+
packageRoot,
|
|
185
|
+
consumerDir,
|
|
186
|
+
fileURLToPath(new URL("../test/fixtures/intercom-client-consumer.mjs", import.meta.url)),
|
|
187
|
+
],
|
|
130
188
|
root,
|
|
131
|
-
{
|
|
189
|
+
{
|
|
190
|
+
...process.env,
|
|
191
|
+
PI_PACKAGE_DIR: hostRoot,
|
|
192
|
+
PATH:
|
|
193
|
+
process.platform === "android"
|
|
194
|
+
? `${dirname(process.execPath)}:/system/bin`
|
|
195
|
+
: "/usr/bin:/bin",
|
|
196
|
+
},
|
|
132
197
|
),
|
|
133
198
|
);
|
|
134
199
|
}
|
|
@@ -146,6 +211,8 @@ try {
|
|
|
146
211
|
"LICENSE",
|
|
147
212
|
"README.md",
|
|
148
213
|
"dist/index.js",
|
|
214
|
+
"dist/intercom-client.js",
|
|
215
|
+
"dist/intercom-client.d.ts",
|
|
149
216
|
"dist/build-info.js",
|
|
150
217
|
"dist/agent/runner.js",
|
|
151
218
|
"dist/pi-intercom/broker/broker.js",
|
|
@@ -156,6 +223,8 @@ try {
|
|
|
156
223
|
"scripts/build.mjs",
|
|
157
224
|
"scripts/real-pi-smoke.mjs",
|
|
158
225
|
"scripts/intercom-remote.mjs",
|
|
226
|
+
"scripts/archive-retired-history.mjs",
|
|
227
|
+
"docs/retired-history-maintenance.md",
|
|
159
228
|
"skills/pi-subagents/SKILL.md",
|
|
160
229
|
"skills/pi-intercom/SKILL.md",
|
|
161
230
|
]) {
|
package/scripts/prepare.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Purpose: Build generated dist output for GitHub/source installs even when Pi invokes npm install --omit=dev.
|
|
4
|
-
* Responsibilities: Build with the local compiler
|
|
4
|
+
* Responsibilities: Build with native Android tsgo or the local compiler; otherwise install only the pinned
|
|
5
5
|
* `typescript` into a throwaway prefix, build with it, and delete the prefix. Emit needs no type
|
|
6
6
|
* information (tsconfig.build.json sets noCheck), so the Pi host graph is never installed here.
|
|
7
7
|
* Scope: Package install lifecycle only; runtime behavior remains owned by scripts/build.mjs.
|
|
@@ -46,7 +46,7 @@ async function runNode(args) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
async function main() {
|
|
49
|
-
if (existsSync(tscBin(cwd))) {
|
|
49
|
+
if (process.platform === "android" || existsSync(tscBin(cwd))) {
|
|
50
50
|
await runNode([buildScript]);
|
|
51
51
|
return;
|
|
52
52
|
}
|