picopilot 0.1.4 → 0.2.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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +111 -16
- package/dist/cli.js.map +1 -1
- package/dist/commands/audio.d.ts +3 -3
- package/dist/commands/audio.d.ts.map +1 -1
- package/dist/commands/audio.js +61 -44
- package/dist/commands/audio.js.map +1 -1
- package/dist/commands/cart-includes.d.ts +11 -0
- package/dist/commands/cart-includes.d.ts.map +1 -0
- package/dist/commands/cart-includes.js +26 -0
- package/dist/commands/cart-includes.js.map +1 -0
- package/dist/commands/doctor.d.ts +22 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +222 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/export.d.ts +3 -4
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +66 -86
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/gfx.d.ts +2 -2
- package/dist/commands/gfx.d.ts.map +1 -1
- package/dist/commands/gfx.js +3 -2
- package/dist/commands/gfx.js.map +1 -1
- package/dist/commands/label-cart.d.ts +72 -0
- package/dist/commands/label-cart.d.ts.map +1 -0
- package/dist/commands/label-cart.js +228 -0
- package/dist/commands/label-cart.js.map +1 -0
- package/dist/commands/lint.d.ts +2 -2
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +3 -2
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/minify.d.ts +2 -2
- package/dist/commands/minify.d.ts.map +1 -1
- package/dist/commands/minify.js +3 -2
- package/dist/commands/minify.js.map +1 -1
- package/dist/commands/pico8-env.d.ts +76 -0
- package/dist/commands/pico8-env.d.ts.map +1 -0
- package/dist/commands/pico8-env.js +71 -0
- package/dist/commands/pico8-env.js.map +1 -0
- package/dist/commands/playtest.d.ts +2 -2
- package/dist/commands/playtest.d.ts.map +1 -1
- package/dist/commands/playtest.js +6 -32
- package/dist/commands/playtest.js.map +1 -1
- package/dist/commands/run.d.ts +3 -4
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +46 -19
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/serve.d.ts +2 -2
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +65 -19
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/shrinko-env.d.ts +22 -0
- package/dist/commands/shrinko-env.d.ts.map +1 -0
- package/dist/commands/shrinko-env.js +15 -0
- package/dist/commands/shrinko-env.js.map +1 -0
- package/dist/commands/tokens.d.ts +4 -4
- package/dist/commands/tokens.d.ts.map +1 -1
- package/dist/commands/tokens.js +3 -2
- package/dist/commands/tokens.js.map +1 -1
- package/dist/commands/verify.d.ts +2 -2
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +3 -2
- package/dist/commands/verify.js.map +1 -1
- package/dist/engine/child-env.d.ts +14 -0
- package/dist/engine/child-env.d.ts.map +1 -0
- package/dist/engine/child-env.js +21 -0
- package/dist/engine/child-env.js.map +1 -0
- package/dist/engine/gfx/label.d.ts +15 -9
- package/dist/engine/gfx/label.d.ts.map +1 -1
- package/dist/engine/gfx/label.js +130 -38
- package/dist/engine/gfx/label.js.map +1 -1
- package/dist/engine/pico8/adapter.d.ts +23 -3
- package/dist/engine/pico8/adapter.d.ts.map +1 -1
- package/dist/engine/pico8/adapter.js.map +1 -1
- package/dist/engine/pico8/cleanup.d.ts +16 -0
- package/dist/engine/pico8/cleanup.d.ts.map +1 -0
- package/dist/engine/pico8/cleanup.js +74 -0
- package/dist/engine/pico8/cleanup.js.map +1 -0
- package/dist/engine/pico8/display.d.ts +149 -0
- package/dist/engine/pico8/display.d.ts.map +1 -0
- package/dist/engine/pico8/display.js +311 -0
- package/dist/engine/pico8/display.js.map +1 -0
- package/dist/engine/pico8/drive.d.ts.map +1 -1
- package/dist/engine/pico8/drive.js +28 -2
- package/dist/engine/pico8/drive.js.map +1 -1
- package/dist/engine/pico8/harness.d.ts +8 -0
- package/dist/engine/pico8/harness.d.ts.map +1 -1
- package/dist/engine/pico8/harness.js +9 -1
- package/dist/engine/pico8/harness.js.map +1 -1
- package/dist/engine/pico8/index.d.ts +3 -0
- package/dist/engine/pico8/index.d.ts.map +1 -1
- package/dist/engine/pico8/index.js +3 -0
- package/dist/engine/pico8/index.js.map +1 -1
- package/dist/engine/pico8/session-daemon-entry.d.ts +1 -1
- package/dist/engine/pico8/session-daemon-entry.js +1 -1
- package/dist/engine/pico8/session-daemon-main.d.ts +1 -1
- package/dist/engine/pico8/session-daemon-main.js +1 -1
- package/dist/engine/pico8/session-daemon.d.ts +1 -1
- package/dist/engine/pico8/session-daemon.d.ts.map +1 -1
- package/dist/engine/pico8/session-daemon.js +19 -19
- package/dist/engine/pico8/session-daemon.js.map +1 -1
- package/dist/engine/pico8/session.d.ts +1 -1
- package/dist/engine/pico8/session.js +1 -1
- package/dist/engine/pico8/shell.d.ts +56 -3
- package/dist/engine/pico8/shell.d.ts.map +1 -1
- package/dist/engine/pico8/shell.js +188 -24
- package/dist/engine/pico8/shell.js.map +1 -1
- package/dist/engine/pico8/supervisor.d.ts +1 -1
- package/dist/engine/pico8/supervisor.js +1 -1
- package/dist/engine/shrinko/adapter.d.ts +1 -1
- package/dist/engine/shrinko/shell.d.ts +3 -3
- package/dist/engine/shrinko/shell.js +3 -3
- package/package.json +2 -1
- package/src/cli.test.ts +188 -0
- package/src/cli.ts +122 -16
- package/src/commands/audio.test.ts +76 -1
- package/src/commands/audio.ts +79 -57
- package/src/commands/cart-includes.ts +27 -0
- package/src/commands/doctor.test.ts +149 -0
- package/src/commands/doctor.ts +280 -0
- package/src/commands/export.test.ts +327 -3
- package/src/commands/export.ts +81 -99
- package/src/commands/gfx.ts +7 -6
- package/src/commands/label-cart.ts +304 -0
- package/src/commands/lint.test.ts +6 -0
- package/src/commands/lint.ts +7 -6
- package/src/commands/minify.test.ts +6 -0
- package/src/commands/minify.ts +7 -6
- package/src/commands/pico8-env.ts +124 -0
- package/src/commands/playtest.test.ts +3 -0
- package/src/commands/playtest.ts +10 -34
- package/src/commands/run.test.ts +116 -2
- package/src/commands/run.ts +62 -24
- package/src/commands/serve.test.ts +138 -2
- package/src/commands/serve.ts +80 -21
- package/src/commands/shrinko-env.test.ts +68 -0
- package/src/commands/shrinko-env.ts +40 -0
- package/src/commands/tokens.test.ts +19 -0
- package/src/commands/tokens.ts +9 -6
- package/src/commands/verify.test.ts +12 -0
- package/src/commands/verify.ts +7 -4
- package/src/engine/child-env.ts +22 -0
- package/src/engine/gfx/fixtures/pico8-screenshot-384.png +0 -0
- package/src/engine/gfx/label.test.ts +467 -1
- package/src/engine/gfx/label.ts +147 -41
- package/src/engine/pico8/adapter.ts +25 -3
- package/src/engine/pico8/cleanup.test.ts +28 -0
- package/src/engine/pico8/cleanup.ts +76 -0
- package/src/engine/pico8/display.test.ts +210 -0
- package/src/engine/pico8/display.ts +429 -0
- package/src/engine/pico8/drive.test.ts +20 -0
- package/src/engine/pico8/drive.ts +25 -2
- package/src/engine/pico8/fake-xvfb.test-support.ts +55 -0
- package/src/engine/pico8/harness.test.ts +26 -0
- package/src/engine/pico8/harness.ts +18 -2
- package/src/engine/pico8/index.ts +3 -0
- package/src/engine/pico8/session-daemon-entry.ts +1 -1
- package/src/engine/pico8/session-daemon-main.ts +1 -1
- package/src/engine/pico8/session-daemon.test.ts +32 -1
- package/src/engine/pico8/session-daemon.ts +25 -17
- package/src/engine/pico8/session.test.ts +1 -1
- package/src/engine/pico8/session.ts +1 -1
- package/src/engine/pico8/shell.test.ts +449 -10
- package/src/engine/pico8/shell.ts +255 -26
- package/src/engine/pico8/supervisor.ts +1 -1
- package/src/engine/pico8/virtual-display.process.test.ts +206 -0
- package/src/engine/shrinko/adapter.ts +1 -1
- package/src/engine/shrinko/shell.ts +3 -3
- package/src/engine/skills/skills.test.ts +10 -0
- package/src/skills/picopilot-audio/SKILL.md +4 -8
- package/src/skills/picopilot-debug/SKILL.md +18 -1
- package/src/skills/picopilot-overview/SKILL.md +9 -1
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
-
import { existsSync, mkdirSync, mkdtempSync, readdirSync, statSync, } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, } from 'node:fs';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { EXPORT_HTML_NAME, pico8NotFound, RECORD_WAV_BASENAME, } from './adapter.js';
|
|
6
|
+
import { DEFAULT_DISPLAY_MODE, findExecutable, needsVirtualDisplay, startVirtualDisplay, } from './display.js';
|
|
7
|
+
import { overlayEnv } from '../child-env.js';
|
|
8
|
+
import { killOnAbort } from './cleanup.js';
|
|
6
9
|
import { SentinelWatcher } from './sentinel.js';
|
|
7
10
|
/**
|
|
8
11
|
* The default {@link SpawnRunner}: `spawn` with stdin detached (`ignore`) so the
|
|
@@ -39,6 +42,63 @@ export function withPico8Home(args) {
|
|
|
39
42
|
mkdirSync(home, { recursive: true });
|
|
40
43
|
return ['-home', home, ...args];
|
|
41
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* The environment PICO-8 is spawned with: the parent env overlaid with the
|
|
47
|
+
* picopilot-resolved values ({@link overlayEnv}). A `-run` session cannot open a
|
|
48
|
+
* window or an audio device without DISPLAY, HOME, XDG_RUNTIME_DIR, SDL_*, ...
|
|
49
|
+
*/
|
|
50
|
+
export function pico8ChildEnv(resolved, parent) {
|
|
51
|
+
return overlayEnv(resolved, parent);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A private `XDG_RUNTIME_DIR` (mode 0700, one per picopilot process) for a
|
|
55
|
+
* PICO-8 launched without one. SDL logs "XDG_RUNTIME_DIR is invalid or not set"
|
|
56
|
+
* otherwise, which is noise in every headless report.
|
|
57
|
+
*/
|
|
58
|
+
let cachedRuntimeDir;
|
|
59
|
+
export function pico8RuntimeDir() {
|
|
60
|
+
if (cachedRuntimeDir !== undefined && existsSync(cachedRuntimeDir)) {
|
|
61
|
+
return cachedRuntimeDir;
|
|
62
|
+
}
|
|
63
|
+
cachedRuntimeDir = mkdtempSync(join(tmpdir(), 'picopilot-xdg-runtime-'));
|
|
64
|
+
return cachedRuntimeDir;
|
|
65
|
+
}
|
|
66
|
+
/** `env` with a private {@link pico8RuntimeDir} filled in when XDG_RUNTIME_DIR is absent. */
|
|
67
|
+
export function withRuntimeDir(env) {
|
|
68
|
+
const current = env.XDG_RUNTIME_DIR;
|
|
69
|
+
if (current !== undefined && current.trim() !== '')
|
|
70
|
+
return env;
|
|
71
|
+
return { ...env, XDG_RUNTIME_DIR: pico8RuntimeDir() };
|
|
72
|
+
}
|
|
73
|
+
/** How many lines of PICO-8's `log.txt` a failed record reports. */
|
|
74
|
+
const LOG_TAIL_LINES = 25;
|
|
75
|
+
/** The last lines of PICO-8's `log.txt` in the isolated `-home`, or undefined if absent. */
|
|
76
|
+
export function readPico8LogTail(home = pico8HomeDir(), lines = LOG_TAIL_LINES) {
|
|
77
|
+
try {
|
|
78
|
+
const text = readFileSync(join(home, 'log.txt'), 'utf8');
|
|
79
|
+
const all = text.trimEnd().split('\n');
|
|
80
|
+
return all.slice(-lines).join('\n');
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Says WHY a record run produced no WAV, from how it ended. The sentinel is the
|
|
88
|
+
* harness's last act (after `audio_end`), so anything other than a sentinel
|
|
89
|
+
* means the harness never finished; a sentinel with no WAV means `audio_end`
|
|
90
|
+
* saved nothing usable.
|
|
91
|
+
*/
|
|
92
|
+
export function explainNoWav(exitReason, ctx) {
|
|
93
|
+
switch (exitReason) {
|
|
94
|
+
case 'timeout':
|
|
95
|
+
return `the backstop fired after ${ctx.backstopMs}ms before the record harness printed its done-sentinel: the cart never reached audio_end (it failed to load, errored at runtime, or its game loop never ran). See pico8LogTail and printh.`;
|
|
96
|
+
case 'exit':
|
|
97
|
+
return 'PICO-8 exited before the record harness printed its done-sentinel: the cart failed to load or crashed, or PICO-8 itself could not start (e.g. no display or audio device). See pico8LogTail and printh.';
|
|
98
|
+
case 'sentinel':
|
|
99
|
+
return `the record harness reached its done-sentinel but no non-empty ${ctx.basename}.wav was written to ${ctx.wavDir}: audio_end saved nothing usable (an empty 0-frame capture).`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
42
102
|
export const spawnRunner = (file, args, env, options) => {
|
|
43
103
|
// `drive` pipes fixed-size command blocks to stdin; `run`/`record` detach it so
|
|
44
104
|
// the cart never blocks on console input.
|
|
@@ -69,14 +129,14 @@ export const spawnRunner = (file, args, env, options) => {
|
|
|
69
129
|
// A closed stdin (the cart exited) is not fatal to the run.
|
|
70
130
|
}
|
|
71
131
|
},
|
|
72
|
-
kill() {
|
|
132
|
+
kill(signal = 'SIGKILL') {
|
|
73
133
|
try {
|
|
74
134
|
// Negative pid kills the process GROUP (detached), so any child dies too.
|
|
75
135
|
if (child.pid !== undefined)
|
|
76
|
-
process.kill(-child.pid,
|
|
136
|
+
process.kill(-child.pid, signal);
|
|
77
137
|
}
|
|
78
138
|
catch {
|
|
79
|
-
child.kill(
|
|
139
|
+
child.kill(signal); // fall back to killing just the process
|
|
80
140
|
}
|
|
81
141
|
},
|
|
82
142
|
};
|
|
@@ -143,6 +203,8 @@ function collectWav(wavDir, basename) {
|
|
|
143
203
|
}
|
|
144
204
|
return path;
|
|
145
205
|
}
|
|
206
|
+
/** The default SIGTERM-to-SIGKILL grace for a gracefully-ended run. */
|
|
207
|
+
export const DEFAULT_KILL_GRACE_MS = 2_000;
|
|
146
208
|
/**
|
|
147
209
|
* The v1 {@link Pico8Adapter}: shells out to the user's native `pico8 -x`
|
|
148
210
|
* (ADR-0006, native path first). It owns the ORCHESTRATION the command should
|
|
@@ -156,9 +218,15 @@ function collectWav(wavDir, basename) {
|
|
|
156
218
|
export class ShellPico8Adapter {
|
|
157
219
|
env;
|
|
158
220
|
spawnRun;
|
|
221
|
+
display;
|
|
222
|
+
virtualDisplay;
|
|
223
|
+
killGraceMs;
|
|
159
224
|
constructor(options) {
|
|
225
|
+
this.killGraceMs = options.killGraceMs ?? DEFAULT_KILL_GRACE_MS;
|
|
160
226
|
this.env = options.env;
|
|
161
227
|
this.spawnRun = options.spawn ?? spawnRunner;
|
|
228
|
+
this.display = options.display ?? DEFAULT_DISPLAY_MODE;
|
|
229
|
+
this.virtualDisplay = options.virtualDisplay ?? {};
|
|
162
230
|
}
|
|
163
231
|
run(options) {
|
|
164
232
|
const [file] = pico8Candidates(this.env);
|
|
@@ -246,20 +314,80 @@ export class ShellPico8Adapter {
|
|
|
246
314
|
});
|
|
247
315
|
}
|
|
248
316
|
record(options) {
|
|
317
|
+
if (needsVirtualDisplay(this.display, this.env)) {
|
|
318
|
+
return this.recordOnVirtualDisplay(options);
|
|
319
|
+
}
|
|
320
|
+
return this.recordWith(options, 'native');
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* The record session on a private virtual display (ADR-0017): start Xvfb
|
|
324
|
+
* (or fall back to `xvfb-run`), run PICO-8 on it with a dummy SDL audio
|
|
325
|
+
* driver (unless the caller chose one; `audio_rec` captures PICO-8's own
|
|
326
|
+
* mixer, not the device), and ALWAYS stop the display afterwards, however
|
|
327
|
+
* the run ended (sentinel, backstop, crash, spawn failure).
|
|
328
|
+
*/
|
|
329
|
+
async recordOnVirtualDisplay(options) {
|
|
330
|
+
const [file] = pico8Candidates(this.env);
|
|
331
|
+
// Absent PICO-8 is reported as such BEFORE paying for (or failing on) a
|
|
332
|
+
// display, and wrapped in xvfb-run a missing binary would not ENOENT.
|
|
333
|
+
const find = this.virtualDisplay.find ?? findExecutable;
|
|
334
|
+
if (find(file, this.env) === undefined)
|
|
335
|
+
return pico8NotFound();
|
|
336
|
+
const started = await startVirtualDisplay(this.env, this.virtualDisplay);
|
|
337
|
+
if (!started.ok)
|
|
338
|
+
return started;
|
|
339
|
+
const vd = started.display;
|
|
340
|
+
try {
|
|
341
|
+
const env = { ...this.env, ...vd.env };
|
|
342
|
+
const audioDriver = env.SDL_AUDIODRIVER;
|
|
343
|
+
if (audioDriver === undefined || audioDriver.trim() === '') {
|
|
344
|
+
env.SDL_AUDIODRIVER = 'dummy';
|
|
345
|
+
}
|
|
346
|
+
return await this.recordWith(options, vd.backend, {
|
|
347
|
+
env,
|
|
348
|
+
wrap: (f, a) => vd.wrap(f, a),
|
|
349
|
+
// xvfb-run's Xvfb lives in PICO-8's process group: SIGTERM first so it
|
|
350
|
+
// removes its /tmp/.X<n>-lock and socket (a SIGKILL leaves them behind).
|
|
351
|
+
endGracefully: vd.backend === 'xvfb-run',
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
finally {
|
|
355
|
+
await vd.stop();
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/** The record launch itself, natively or under a virtual display's env/wrapper. */
|
|
359
|
+
recordWith(options, display, launch) {
|
|
249
360
|
const [file] = pico8Candidates(this.env);
|
|
250
361
|
const basename = options.wavBasename ?? RECORD_WAV_BASENAME;
|
|
251
362
|
// `-root_path <wavDir>` steers the `audio_end(1)`-to-current-folder WAV into
|
|
252
363
|
// the isolated temp dir (never ~/Desktop or the carts root). `-run` is a real
|
|
253
364
|
// A/V session (recording needs audio to capture; `-x` yields an empty WAV).
|
|
254
365
|
const args = ['-root_path', options.wavDir, '-run', options.cartPath];
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
366
|
+
// The `-home` is shared by every launch in this process: drop the previous
|
|
367
|
+
// log.txt so a failed record never reports another run's log as its own.
|
|
368
|
+
rmSync(join(pico8HomeDir(), 'log.txt'), { force: true });
|
|
369
|
+
return this.orchestrate(file, args, { sentinel: options.sentinel, backstopMs: options.backstopMs }, (exitReason, printh) => {
|
|
370
|
+
const wavPath = collectWav(options.wavDir, basename);
|
|
371
|
+
if (wavPath !== undefined) {
|
|
372
|
+
return { ok: true, value: { wavPath, printh, exitReason, display } };
|
|
373
|
+
}
|
|
374
|
+
const pico8LogTail = readPico8LogTail();
|
|
375
|
+
return {
|
|
376
|
+
ok: true,
|
|
377
|
+
value: {
|
|
378
|
+
wavPath,
|
|
379
|
+
printh,
|
|
380
|
+
exitReason,
|
|
381
|
+
display,
|
|
382
|
+
noWavReason: explainNoWav(exitReason, {
|
|
383
|
+
backstopMs: options.backstopMs,
|
|
384
|
+
wavDir: options.wavDir,
|
|
385
|
+
basename,
|
|
386
|
+
}),
|
|
387
|
+
...(pico8LogTail !== undefined ? { pico8LogTail } : {}),
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
}, launch);
|
|
263
391
|
}
|
|
264
392
|
/**
|
|
265
393
|
* The shared launch/sentinel-watch/backstop/collect loop behind both
|
|
@@ -274,16 +402,49 @@ export class ShellPico8Adapter {
|
|
|
274
402
|
return new Promise((resolve) => {
|
|
275
403
|
let settled = false;
|
|
276
404
|
let backstop;
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
405
|
+
const homeArgs = withPico8Home(args);
|
|
406
|
+
const launch = spawnOpts?.wrap !== undefined
|
|
407
|
+
? spawnOpts.wrap(file, homeArgs)
|
|
408
|
+
: { file, args: homeArgs };
|
|
409
|
+
const proc = this.spawnRun(launch.file, launch.args, withRuntimeDir(spawnOpts?.env ?? this.env), { stdin: spawnOpts?.stdin });
|
|
410
|
+
// If picopilot itself is stopped mid-run, take PICO-8 down with it.
|
|
411
|
+
const disposeAbort = killOnAbort(() => proc.kill());
|
|
412
|
+
let onClosed;
|
|
413
|
+
/**
|
|
414
|
+
* Ends the run once. `kill` = PICO-8 is still running (sentinel/backstop):
|
|
415
|
+
* SIGKILL its group, or for a graceful end SIGTERM it and resolve when it
|
|
416
|
+
* has closed (SIGKILL after the grace period).
|
|
417
|
+
*/
|
|
418
|
+
const finish = (exitReason, kill = false) => {
|
|
281
419
|
if (settled)
|
|
282
420
|
return;
|
|
283
421
|
settled = true;
|
|
284
422
|
if (backstop !== undefined)
|
|
285
423
|
clearTimeout(backstop);
|
|
286
|
-
|
|
424
|
+
let resolved = false;
|
|
425
|
+
const done = () => {
|
|
426
|
+
if (resolved)
|
|
427
|
+
return;
|
|
428
|
+
resolved = true;
|
|
429
|
+
// Only now: a signal during the graceful wait must still kill PICO-8.
|
|
430
|
+
disposeAbort();
|
|
431
|
+
resolve(buildOk(exitReason, watcher.text));
|
|
432
|
+
};
|
|
433
|
+
if (!kill)
|
|
434
|
+
return done();
|
|
435
|
+
if (spawnOpts?.endGracefully !== true) {
|
|
436
|
+
proc.kill();
|
|
437
|
+
return done();
|
|
438
|
+
}
|
|
439
|
+
proc.kill('SIGTERM');
|
|
440
|
+
const hard = setTimeout(() => {
|
|
441
|
+
proc.kill();
|
|
442
|
+
done();
|
|
443
|
+
}, this.killGraceMs);
|
|
444
|
+
onClosed = () => {
|
|
445
|
+
clearTimeout(hard);
|
|
446
|
+
done();
|
|
447
|
+
};
|
|
287
448
|
};
|
|
288
449
|
proc.onError((err) => {
|
|
289
450
|
// A spawn ENOENT ⇒ PICO-8 is absent (a bad PICO8_PATH surfaces as absence
|
|
@@ -293,6 +454,7 @@ export class ShellPico8Adapter {
|
|
|
293
454
|
return;
|
|
294
455
|
if (err.code === 'ENOENT') {
|
|
295
456
|
settled = true;
|
|
457
|
+
disposeAbort();
|
|
296
458
|
if (backstop !== undefined)
|
|
297
459
|
clearTimeout(backstop);
|
|
298
460
|
resolve(pico8NotFound());
|
|
@@ -302,12 +464,15 @@ export class ShellPico8Adapter {
|
|
|
302
464
|
}
|
|
303
465
|
});
|
|
304
466
|
proc.onStdout((chunk) => {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
finish('sentinel');
|
|
308
|
-
|
|
467
|
+
// sentinel matched: end the run promptly
|
|
468
|
+
if (watcher.push(chunk) && !settled)
|
|
469
|
+
finish('sentinel', true);
|
|
470
|
+
});
|
|
471
|
+
proc.onClose(() => {
|
|
472
|
+
if (onClosed !== undefined)
|
|
473
|
+
return onClosed();
|
|
474
|
+
finish('exit'); // PICO-8 exited on its own
|
|
309
475
|
});
|
|
310
|
-
proc.onClose(() => finish('exit')); // PICO-8 exited on its own
|
|
311
476
|
// For `drive`: write the command blocks to the live stdin now that it is
|
|
312
477
|
// spawned. A spawn ENOENT resolves via onError before this matters.
|
|
313
478
|
spawnOpts?.onSpawn?.(proc);
|
|
@@ -315,8 +480,7 @@ export class ShellPico8Adapter {
|
|
|
315
480
|
backstop = setTimeout(() => {
|
|
316
481
|
if (settled)
|
|
317
482
|
return;
|
|
318
|
-
|
|
319
|
-
finish('timeout');
|
|
483
|
+
finish('timeout', true);
|
|
320
484
|
}, opts.backstopMs);
|
|
321
485
|
});
|
|
322
486
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/engine/pico8/shell.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/engine/pico8/shell.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The playtest SESSION SUPERVISOR (ADR-0011,
|
|
2
|
+
* The playtest SESSION SUPERVISOR (ADR-0011, spec US #6): the daemon that keeps a
|
|
3
3
|
* driven PICO-8 process ALIVE + PAUSED across the agent's separate CLI turns, and
|
|
4
4
|
* the client the per-verb sub-invocations use to address it BY ID.
|
|
5
5
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The playtest SESSION SUPERVISOR (ADR-0011,
|
|
2
|
+
* The playtest SESSION SUPERVISOR (ADR-0011, spec US #6): the daemon that keeps a
|
|
3
3
|
* driven PICO-8 process ALIVE + PAUSED across the agent's separate CLI turns, and
|
|
4
4
|
* the client the per-verb sub-invocations use to address it BY ID.
|
|
5
5
|
*
|
|
@@ -23,7 +23,7 @@ export declare const SHRINKO_REMEDY: "uv pip install shrinko";
|
|
|
23
23
|
export declare const SHRINKO_NEEDS: readonly ["python>=3.8"];
|
|
24
24
|
/**
|
|
25
25
|
* The structured "shrinko is not installed" failure (ADR-0002). Its shape is
|
|
26
|
-
* fixed by the
|
|
26
|
+
* fixed by the spec's two-tier contract (US #17): `ok:false`, a machine-readable
|
|
27
27
|
* `reason`, the EXACT `remedy` string, and the `needs` list. A command turns
|
|
28
28
|
* this into an incur `error({ code: reason, ... })` with a nonzero exit.
|
|
29
29
|
*/
|
|
@@ -23,9 +23,9 @@ export type ChildRunner = (file: string, args: string[], env: NodeJS.ProcessEnv)
|
|
|
23
23
|
* The default {@link ChildRunner}: an `execFile` that captures stdout/stderr and
|
|
24
24
|
* NEVER rejects. A failed spawn (ENOENT) becomes `spawnError`; a nonzero exit
|
|
25
25
|
* becomes a `code`, so both outcomes are data the adapter maps to a structured
|
|
26
|
-
* result. The child
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* result. The child gets exactly the `env` it is handed and reads nothing
|
|
27
|
+
* ambiently; the command layer builds that env as the parent env overlaid with
|
|
28
|
+
* the resolved `PATH` (`commands/shrinko-env.ts`), and a test injects its own.
|
|
29
29
|
*/
|
|
30
30
|
export declare const execFileRunner: ChildRunner;
|
|
31
31
|
/** Options for {@link ShellShrinkoAdapter}. */
|
|
@@ -4,9 +4,9 @@ import { parseCount, parseLint, shrinkoNotFound, } from './adapter.js';
|
|
|
4
4
|
* The default {@link ChildRunner}: an `execFile` that captures stdout/stderr and
|
|
5
5
|
* NEVER rejects. A failed spawn (ENOENT) becomes `spawnError`; a nonzero exit
|
|
6
6
|
* becomes a `code`, so both outcomes are data the adapter maps to a structured
|
|
7
|
-
* result. The child
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* result. The child gets exactly the `env` it is handed and reads nothing
|
|
8
|
+
* ambiently; the command layer builds that env as the parent env overlaid with
|
|
9
|
+
* the resolved `PATH` (`commands/shrinko-env.ts`), and a test injects its own.
|
|
10
10
|
*/
|
|
11
11
|
export const execFileRunner = (file, args, env) => new Promise((resolve) => {
|
|
12
12
|
execFile(file, args, { env, encoding: 'utf8' }, (error, stdout, stderr) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "picopilot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "An agent-first toolchain for PICO-8 game development, built on the incur CLI framework.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsc -p tsconfig.build.json",
|
|
45
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
45
46
|
"dev": "as-soon -w src pnpm build",
|
|
46
47
|
"test": "vitest run",
|
|
47
48
|
"test:watch": "vitest",
|
package/src/cli.test.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import {mkdtempSync, rmSync, writeFileSync} from 'node:fs';
|
|
2
|
+
import {tmpdir} from 'node:os';
|
|
3
|
+
import {join} from 'node:path';
|
|
4
|
+
import {z} from 'incur';
|
|
5
|
+
import {afterEach, beforeEach, describe, expect, it} from 'vitest';
|
|
6
|
+
import {createCli} from './cli.js';
|
|
7
|
+
import {displayModeOf} from './commands/pico8-env.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The display mode (ADR-0017) is resolved ONCE, globally, by the root CLI:
|
|
11
|
+
* `--display` > `PICOPILOT_DISPLAY` > picopilot.json `display` > `auto`. A probe
|
|
12
|
+
* command mounted on the real CLI reports what a command handler sees.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
let dir: string;
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
dir = mkdtempSync(join(tmpdir(), 'picopilot-cli-'));
|
|
18
|
+
});
|
|
19
|
+
afterEach(() => rmSync(dir, {recursive: true, force: true}));
|
|
20
|
+
|
|
21
|
+
async function probe(
|
|
22
|
+
argv: string[],
|
|
23
|
+
env: Record<string, string | undefined> = {},
|
|
24
|
+
config?: unknown,
|
|
25
|
+
) {
|
|
26
|
+
const cli = createCli();
|
|
27
|
+
cli.command('probe-display', {
|
|
28
|
+
run: (c) => ({display: displayModeOf(c.var)}),
|
|
29
|
+
});
|
|
30
|
+
const args = [...argv];
|
|
31
|
+
if (config !== undefined) {
|
|
32
|
+
const path = join(dir, 'picopilot.json');
|
|
33
|
+
writeFileSync(path, JSON.stringify(config));
|
|
34
|
+
args.push('--config', path);
|
|
35
|
+
}
|
|
36
|
+
let stdout = '';
|
|
37
|
+
let exitCode = 0;
|
|
38
|
+
await cli.serve([...args, '--json'], {
|
|
39
|
+
stdout(s) {
|
|
40
|
+
stdout += s;
|
|
41
|
+
},
|
|
42
|
+
exit(code) {
|
|
43
|
+
exitCode = code;
|
|
44
|
+
},
|
|
45
|
+
env,
|
|
46
|
+
});
|
|
47
|
+
return {out: JSON.parse(stdout), exitCode};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
describe('display mode resolution through the CLI', () => {
|
|
51
|
+
it('defaults to auto', async () => {
|
|
52
|
+
expect((await probe(['probe-display'])).out.display).toBe('auto');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('reads picopilot.json "display"', async () => {
|
|
56
|
+
const {out} = await probe(['probe-display'], {}, {display: 'native'});
|
|
57
|
+
expect(out.display).toBe('native');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('PICOPILOT_DISPLAY beats picopilot.json', async () => {
|
|
61
|
+
const {out} = await probe(
|
|
62
|
+
['probe-display'],
|
|
63
|
+
{PICOPILOT_DISPLAY: 'xvfb'},
|
|
64
|
+
{display: 'native'},
|
|
65
|
+
);
|
|
66
|
+
expect(out.display).toBe('xvfb');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('--display beats both, before or after the command', async () => {
|
|
70
|
+
for (const argv of [
|
|
71
|
+
['--display', 'native', 'probe-display'],
|
|
72
|
+
['probe-display', '--display', 'native'],
|
|
73
|
+
]) {
|
|
74
|
+
const {out} = await probe(
|
|
75
|
+
argv,
|
|
76
|
+
{PICOPILOT_DISPLAY: 'xvfb'},
|
|
77
|
+
{display: 'xvfb'},
|
|
78
|
+
);
|
|
79
|
+
expect(out.display).toBe('native');
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('an invalid PICOPILOT_DISPLAY is an error for a display command, not a silent auto', async () => {
|
|
84
|
+
const cli = createCli();
|
|
85
|
+
let stdout = '';
|
|
86
|
+
let exitCode = 0;
|
|
87
|
+
await cli.serve(['run', join(dir, 'none.p8'), '--json'], {
|
|
88
|
+
stdout(s) {
|
|
89
|
+
stdout += s;
|
|
90
|
+
},
|
|
91
|
+
exit(code) {
|
|
92
|
+
exitCode = code;
|
|
93
|
+
},
|
|
94
|
+
env: {PICOPILOT_DISPLAY: 'xfvb'},
|
|
95
|
+
});
|
|
96
|
+
expect(exitCode).not.toBe(0);
|
|
97
|
+
const out = JSON.parse(stdout);
|
|
98
|
+
expect(out.code).toBe('invalid-display-mode');
|
|
99
|
+
expect(out.message).toContain('PICOPILOT_DISPLAY');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('an invalid value does not break commands that never use the display', async () => {
|
|
103
|
+
const cli = createCli();
|
|
104
|
+
let stdout = '';
|
|
105
|
+
let exitCode = 0;
|
|
106
|
+
await cli.serve(['version', '--json'], {
|
|
107
|
+
stdout(s) {
|
|
108
|
+
stdout += s;
|
|
109
|
+
},
|
|
110
|
+
exit(code) {
|
|
111
|
+
exitCode = code;
|
|
112
|
+
},
|
|
113
|
+
env: {PICOPILOT_DISPLAY: 'xfvb'},
|
|
114
|
+
});
|
|
115
|
+
expect(exitCode).toBe(0);
|
|
116
|
+
expect(JSON.parse(stdout).name).toBe('picopilot');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('--no-config ignores the picopilot.json display key', async () => {
|
|
120
|
+
const path = join(dir, 'picopilot.json');
|
|
121
|
+
writeFileSync(path, JSON.stringify({display: 'native'}));
|
|
122
|
+
// First load it (so a stale value could leak), then disable config.
|
|
123
|
+
const cli = createCli();
|
|
124
|
+
cli.command('probe-display', {
|
|
125
|
+
run: (c) => ({display: displayModeOf(c.var)}),
|
|
126
|
+
});
|
|
127
|
+
const outs: string[] = [];
|
|
128
|
+
for (const argv of [
|
|
129
|
+
['probe-display', '--config', path, '--json'],
|
|
130
|
+
['probe-display', '--no-config', '--json'],
|
|
131
|
+
]) {
|
|
132
|
+
let stdout = '';
|
|
133
|
+
await cli.serve(argv, {
|
|
134
|
+
stdout(s) {
|
|
135
|
+
stdout += s;
|
|
136
|
+
},
|
|
137
|
+
exit() {},
|
|
138
|
+
env: {},
|
|
139
|
+
});
|
|
140
|
+
outs.push(JSON.parse(stdout).display);
|
|
141
|
+
}
|
|
142
|
+
expect(outs).toEqual(['native', 'auto']);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('--config naming a missing file is an error', async () => {
|
|
146
|
+
const cli = createCli();
|
|
147
|
+
let stdout = '';
|
|
148
|
+
let exitCode = 0;
|
|
149
|
+
await cli.serve(['version', '--config', join(dir, 'nope.json'), '--json'], {
|
|
150
|
+
stdout(s) {
|
|
151
|
+
stdout += s;
|
|
152
|
+
},
|
|
153
|
+
exit(code) {
|
|
154
|
+
exitCode = code;
|
|
155
|
+
},
|
|
156
|
+
env: {},
|
|
157
|
+
});
|
|
158
|
+
expect(exitCode).not.toBe(0);
|
|
159
|
+
expect(stdout).toContain('not found');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('a per-command config option still loads next to the display key', async () => {
|
|
163
|
+
// The custom config loader must keep incur's per-command option defaults.
|
|
164
|
+
const cli = createCli();
|
|
165
|
+
let seen: unknown;
|
|
166
|
+
cli.command('probe-opt', {
|
|
167
|
+
options: z.object({flag: z.boolean().default(false)}),
|
|
168
|
+
run: (c) => {
|
|
169
|
+
seen = c.options.flag;
|
|
170
|
+
return {};
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
const path = join(dir, 'picopilot.json');
|
|
174
|
+
writeFileSync(
|
|
175
|
+
path,
|
|
176
|
+
JSON.stringify({
|
|
177
|
+
display: 'native',
|
|
178
|
+
commands: {'probe-opt': {options: {flag: true}}},
|
|
179
|
+
}),
|
|
180
|
+
);
|
|
181
|
+
await cli.serve(['probe-opt', '--config', path, '--json'], {
|
|
182
|
+
stdout() {},
|
|
183
|
+
exit() {},
|
|
184
|
+
env: {},
|
|
185
|
+
});
|
|
186
|
+
expect(seen).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
});
|