agent-theatre 1.1.4 → 1.2.1
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.js +49 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +50 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/web/assets/browserAll-DHOoTekQ.js +2 -0
- package/web/assets/{browserAll-oXCedPBk.js.map → browserAll-DHOoTekQ.js.map} +1 -1
- package/web/assets/index-CO8a_HgY.js +958 -0
- package/web/assets/index-CO8a_HgY.js.map +1 -0
- package/web/assets/{index-BcMndIlk.css → index-DLvIe75m.css} +1 -1
- package/web/assets/webworkerAll-CwKw12By.js +2 -0
- package/web/assets/{webworkerAll-BG4khe1M.js.map → webworkerAll-CwKw12By.js.map} +1 -1
- package/web/index.html +2 -2
- package/web/assets/browserAll-oXCedPBk.js +0 -2
- package/web/assets/index-CZ8tuB9J.js +0 -956
- package/web/assets/index-CZ8tuB9J.js.map +0 -1
- package/web/assets/webworkerAll-BG4khe1M.js +0 -2
package/dist/cli.js
CHANGED
|
@@ -9,9 +9,10 @@ import pc from "picocolors";
|
|
|
9
9
|
|
|
10
10
|
// src/server.ts
|
|
11
11
|
import { createServer } from "http";
|
|
12
|
-
import { existsSync, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync, realpathSync } from "fs";
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync as readFileSync2, readdirSync as readdirSync2, rmSync, writeFileSync, realpathSync } from "fs";
|
|
13
13
|
import { homedir as homedir2 } from "os";
|
|
14
14
|
import { join as join2, basename as basename2, resolve, sep } from "path";
|
|
15
|
+
import { spawn, spawnSync } from "child_process";
|
|
15
16
|
import { Hono } from "hono";
|
|
16
17
|
import { getRequestListener } from "@hono/node-server";
|
|
17
18
|
import { WebSocketServer } from "ws";
|
|
@@ -1195,6 +1196,8 @@ var Theatre = class {
|
|
|
1195
1196
|
wss = null;
|
|
1196
1197
|
live;
|
|
1197
1198
|
signal = "ok";
|
|
1199
|
+
/** The most recent Claude Code session that spoke to this stage; what a prompt from the stage resumes. */
|
|
1200
|
+
lastSessionId = null;
|
|
1198
1201
|
timer = null;
|
|
1199
1202
|
port = 0;
|
|
1200
1203
|
routes() {
|
|
@@ -1208,6 +1211,8 @@ var Theatre = class {
|
|
|
1208
1211
|
}
|
|
1209
1212
|
const cwd = typeof payload?.cwd === "string" ? payload.cwd : "";
|
|
1210
1213
|
if (cwd && !isWithin(cwd, this.opts.cwd)) return c.body(null, 204);
|
|
1214
|
+
const sid = payload.session_id;
|
|
1215
|
+
if (typeof sid === "string" && sid) this.lastSessionId = sid;
|
|
1211
1216
|
const { events } = hookPayloadToEvents(payload, { home: homedir2() });
|
|
1212
1217
|
if (events.length) this.ingest(events);
|
|
1213
1218
|
return c.body(null, 204);
|
|
@@ -1232,6 +1237,18 @@ var Theatre = class {
|
|
|
1232
1237
|
const beats = direct(events, world);
|
|
1233
1238
|
return c.json({ mode: "replay", repoId: this.opts.repoId, title: s.title, world, events, beats, warnings: warnings.length });
|
|
1234
1239
|
});
|
|
1240
|
+
a.get("/api/prompt", (c) => c.json({ available: !!claudeBinary() && !!this.lastSessionId, session: this.lastSessionId }));
|
|
1241
|
+
a.post("/api/prompt", async (c) => {
|
|
1242
|
+
const body = await c.req.json().catch(() => ({}));
|
|
1243
|
+
const text = typeof body.text === "string" ? body.text.trim() : "";
|
|
1244
|
+
const bin = claudeBinary();
|
|
1245
|
+
if (!text) return c.json({ ok: false, error: "empty prompt" }, 400);
|
|
1246
|
+
if (!bin) return c.json({ ok: false, error: "Claude Code 2.x not found on PATH" }, 503);
|
|
1247
|
+
if (!this.lastSessionId) return c.json({ ok: false, error: "no session to resume yet" }, 409);
|
|
1248
|
+
const child = spawn(bin, ["-p", "--resume", this.lastSessionId, text], { cwd: this.opts.cwd, stdio: "ignore", detached: true, env: process.env });
|
|
1249
|
+
child.unref();
|
|
1250
|
+
return c.json({ ok: true, session: this.lastSessionId });
|
|
1251
|
+
});
|
|
1235
1252
|
a.get("/healthz", (c) => c.json({ ok: true, port: this.port, events: this.live.events.length }));
|
|
1236
1253
|
if (this.opts.webDir) {
|
|
1237
1254
|
const dir = this.opts.webDir;
|
|
@@ -1264,7 +1281,15 @@ var Theatre = class {
|
|
|
1264
1281
|
this.broadcast({ type: "beats", beats: out, events });
|
|
1265
1282
|
return out;
|
|
1266
1283
|
}
|
|
1284
|
+
/** In-process subscribers (the VS Code extension relays these to its webview). */
|
|
1285
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1267
1286
|
broadcast(msg) {
|
|
1287
|
+
for (const l of this.listeners) {
|
|
1288
|
+
try {
|
|
1289
|
+
l(msg);
|
|
1290
|
+
} catch {
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1268
1293
|
const data = JSON.stringify(msg);
|
|
1269
1294
|
for (const ws of this.wss?.clients ?? []) if (ws.readyState === 1) ws.send(data);
|
|
1270
1295
|
}
|
|
@@ -1307,6 +1332,10 @@ var Theatre = class {
|
|
|
1307
1332
|
this.wss?.close();
|
|
1308
1333
|
await new Promise((res) => this.server ? this.server.close(() => res()) : res());
|
|
1309
1334
|
}
|
|
1335
|
+
/** The live scene as /api/scene returns it. */
|
|
1336
|
+
scene() {
|
|
1337
|
+
return { mode: "live", repoId: this.opts.repoId, world: this.live.world, events: this.live.events, beats: this.live.beats, signal: this.signal };
|
|
1338
|
+
}
|
|
1310
1339
|
get url() {
|
|
1311
1340
|
return `http://127.0.0.1:${this.port}/`;
|
|
1312
1341
|
}
|
|
@@ -1325,9 +1354,26 @@ function isWithin(dir, root) {
|
|
|
1325
1354
|
const d = norm3(dir), r = norm3(root);
|
|
1326
1355
|
return d === r || d.startsWith(r.endsWith(sep) ? r : r + sep);
|
|
1327
1356
|
}
|
|
1357
|
+
function claudeBinary() {
|
|
1358
|
+
const cands = [process.env.AGENT_THEATRE_CLAUDE, "claude"].filter((x) => !!x);
|
|
1359
|
+
try {
|
|
1360
|
+
const ext = join2(homedir2(), ".vscode", "extensions");
|
|
1361
|
+
for (const d of (existsSync(ext) ? readdirSync2(ext) : []).filter((n) => n.startsWith("anthropic.claude-code-")).sort().reverse()) cands.push(join2(ext, d, "resources", "native-binary", "claude"));
|
|
1362
|
+
} catch {
|
|
1363
|
+
}
|
|
1364
|
+
for (const c of cands) {
|
|
1365
|
+
try {
|
|
1366
|
+
const r = spawnSync(c, ["--version"], { encoding: "utf8", timeout: 4e3 });
|
|
1367
|
+
const m = /^(\d+)\./.exec(r.stdout.trim());
|
|
1368
|
+
if (r.status === 0 && m && Number(m[1]) >= 2) return c;
|
|
1369
|
+
} catch {
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
return null;
|
|
1373
|
+
}
|
|
1328
1374
|
|
|
1329
1375
|
// src/scan.ts
|
|
1330
|
-
import { readdirSync as
|
|
1376
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
1331
1377
|
import { join as join3, relative } from "path";
|
|
1332
1378
|
function scanRepo(root, opts = {}) {
|
|
1333
1379
|
const maxFiles = opts.maxFiles ?? 2e4, maxBytes = opts.maxBytesForLoc ?? 512e3;
|
|
@@ -1336,7 +1382,7 @@ function scanRepo(root, opts = {}) {
|
|
|
1336
1382
|
if (files.length >= maxFiles) return;
|
|
1337
1383
|
let ents;
|
|
1338
1384
|
try {
|
|
1339
|
-
ents =
|
|
1385
|
+
ents = readdirSync3(dir, { withFileTypes: true });
|
|
1340
1386
|
} catch {
|
|
1341
1387
|
return;
|
|
1342
1388
|
}
|