zooid 0.7.0 → 0.7.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/bin.js +106 -12
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-N5POSZX5.js → chunk-SUPTPSN3.js} +629 -195
- package/dist/chunk-SUPTPSN3.js.map +1 -0
- package/dist/index.d.ts +27 -3
- package/dist/index.js +1 -1
- package/dist/web/assets/index-C2MAIew3.css +1 -0
- package/dist/web/assets/{index-JZMMlqDP.js → index-CqfWXqvO.js} +1 -1
- package/dist/web/assets/{index-BT_v3DKu.js → index-Cz5fEZBc.js} +51 -51
- package/dist/web/assets/{reaction-picker-emoji-Kh7emgFa.js → reaction-picker-emoji-cME0vOsX.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +8 -7
- package/src/bin.ts +5 -2
- package/src/build-registry.ts +211 -10
- package/src/build-registry.zod044.test.ts +261 -0
- package/src/commands/dev.ts +15 -7
- package/src/commands/init/generators.ts +5 -0
- package/src/commands/status.ts +7 -2
- package/src/daemon/start-daemon.ts +28 -1
- package/src/prepull-images.test.ts +149 -0
- package/src/prepull-images.ts +100 -0
- package/dist/chunk-N5POSZX5.js.map +0 -1
- package/dist/web/assets/index-DJTghnF-.css +0 -1
package/dist/bin.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
renderRegistration,
|
|
15
15
|
startDaemonSocketServer,
|
|
16
16
|
startWorkforcePublisher
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-SUPTPSN3.js";
|
|
18
18
|
|
|
19
19
|
// src/bin.ts
|
|
20
20
|
import { resolve as resolve5 } from "path";
|
|
@@ -401,6 +401,68 @@ function createApp({
|
|
|
401
401
|
return app;
|
|
402
402
|
}
|
|
403
403
|
|
|
404
|
+
// src/prepull-images.ts
|
|
405
|
+
import { execFile } from "child_process";
|
|
406
|
+
import { promisify } from "util";
|
|
407
|
+
var pExecFile = promisify(execFile);
|
|
408
|
+
async function prepullImages(registry, opts) {
|
|
409
|
+
if (opts.skip || opts.runtime === "local") return;
|
|
410
|
+
const exec = opts.exec ?? defaultExec;
|
|
411
|
+
const log = opts.log ?? ((l) => console.log(l));
|
|
412
|
+
const images = /* @__PURE__ */ new Set();
|
|
413
|
+
for (const name of registry.agentNames()) {
|
|
414
|
+
const img = registry.resolveSpawnImage(name);
|
|
415
|
+
if (img) images.add(img);
|
|
416
|
+
}
|
|
417
|
+
const toPull = [];
|
|
418
|
+
let cached = 0;
|
|
419
|
+
if (opts.refresh) {
|
|
420
|
+
toPull.push(...images);
|
|
421
|
+
} else {
|
|
422
|
+
await Promise.all(
|
|
423
|
+
[...images].map(async (img) => {
|
|
424
|
+
const r = await exec(opts.engine, ["image", "inspect", img]);
|
|
425
|
+
if (r.code === 0) cached++;
|
|
426
|
+
else toPull.push(img);
|
|
427
|
+
})
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
log(
|
|
431
|
+
`[zooid] image prepull: ${images.size} unique images (${cached} cached, ${toPull.length} to pull)`
|
|
432
|
+
);
|
|
433
|
+
if (toPull.length === 0) return;
|
|
434
|
+
await Promise.all(
|
|
435
|
+
toPull.map(async (img) => {
|
|
436
|
+
log(`[zooid] ${img} pulling\u2026`);
|
|
437
|
+
const start = Date.now();
|
|
438
|
+
const r = await exec(opts.engine, ["pull", img]);
|
|
439
|
+
const secs = ((Date.now() - start) / 1e3).toFixed(1);
|
|
440
|
+
if (r.code !== 0) {
|
|
441
|
+
throw new Error(
|
|
442
|
+
`image prepull failed for ${img}:
|
|
443
|
+
${r.stderr.trim() || "(no stderr)"}`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
log(`[zooid] ${img} \u2713 ${secs}s`);
|
|
447
|
+
})
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
var defaultExec = async (cmd, args) => {
|
|
451
|
+
try {
|
|
452
|
+
const { stdout, stderr } = await pExecFile(cmd, args, {
|
|
453
|
+
maxBuffer: 16 * 1024 * 1024
|
|
454
|
+
});
|
|
455
|
+
return { code: 0, stdout, stderr };
|
|
456
|
+
} catch (err) {
|
|
457
|
+
const e = err;
|
|
458
|
+
return {
|
|
459
|
+
code: typeof e.code === "number" ? e.code : 1,
|
|
460
|
+
stdout: e.stdout ?? "",
|
|
461
|
+
stderr: e.stderr ?? String(e)
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
|
|
404
466
|
// src/daemon/start-daemon.ts
|
|
405
467
|
function listenAsync(server) {
|
|
406
468
|
return new Promise((resolve6) => {
|
|
@@ -421,7 +483,8 @@ async function startDaemon(opts = {}) {
|
|
|
421
483
|
const cwd = opts.cwd ?? process.cwd();
|
|
422
484
|
const found = opts.configPath ? { path: opts.configPath } : findConfigFile(cwd);
|
|
423
485
|
if (!found) throw new Error("zooid.yaml is required");
|
|
424
|
-
const
|
|
486
|
+
const configDir = dirname2(found.path);
|
|
487
|
+
const base = loadZooidConfig(readFileSync2(found.path, "utf8"), { configDir });
|
|
425
488
|
const config = mergeCliFlags(base, opts.cliFlags ?? {});
|
|
426
489
|
const approvals = new ApprovalCorrelator();
|
|
427
490
|
const daemonSockPath = opts.agentsDir ? join3(opts.agentsDir, "..", "run", "context.sock") : join3(tmpdir(), `zooid-context-${process.pid}.sock`);
|
|
@@ -437,14 +500,27 @@ async function startDaemon(opts = {}) {
|
|
|
437
500
|
} catch (err) {
|
|
438
501
|
console.warn("[context] daemon socket startup failed; zooid-context MCP disabled:", err);
|
|
439
502
|
}
|
|
503
|
+
const dataDir = opts.agentsDir ? dirname2(opts.agentsDir) : void 0;
|
|
440
504
|
const registry = buildAcpRegistry(config, {
|
|
441
505
|
approvals,
|
|
442
506
|
onTap: opts.onTap,
|
|
443
507
|
agentsDir: opts.agentsDir,
|
|
444
508
|
contextSpawnRegistry: contextSocket ? contextSpawnRegistry : void 0,
|
|
445
|
-
daemonSockPath: contextSocket ? daemonSockPath : void 0
|
|
509
|
+
daemonSockPath: contextSocket ? daemonSockPath : void 0,
|
|
510
|
+
configDir,
|
|
511
|
+
dataDir,
|
|
512
|
+
daemonHome: process.env.HOME
|
|
446
513
|
});
|
|
447
514
|
const agentNames = Object.keys(config.agents);
|
|
515
|
+
if (config.runtime !== "local") {
|
|
516
|
+
await prepullImages(registry, {
|
|
517
|
+
engine: config.runtime === "podman" ? "podman" : "docker",
|
|
518
|
+
runtime: config.runtime,
|
|
519
|
+
skip: opts.noPrepull ?? process.env.ZOOID_NO_PREPULL === "1",
|
|
520
|
+
refresh: opts.refreshImages ?? process.env.ZOOID_REFRESH_IMAGES === "1",
|
|
521
|
+
log: opts.prepullLog
|
|
522
|
+
});
|
|
523
|
+
}
|
|
448
524
|
console.log(
|
|
449
525
|
`[context] socket=${daemonSockPath} status=${contextSocket ? "listening" : "disabled"} agents={${agentNames.map((n) => `${n}:${registry.hasContextSpawn(n) ? "yes" : "no"}`).join(", ")}}`
|
|
450
526
|
);
|
|
@@ -1011,7 +1087,7 @@ async function runDev(flags) {
|
|
|
1011
1087
|
process.env.MATRIX_AS_TOKEN = tokens.asToken;
|
|
1012
1088
|
process.env.MATRIX_HS_TOKEN = tokens.hsToken;
|
|
1013
1089
|
const rawYaml = readFileSync4(found.path, "utf8");
|
|
1014
|
-
const preview = loadZooidConfig(rawYaml);
|
|
1090
|
+
const preview = loadZooidConfig(rawYaml, { configDir: dirname6(found.path) });
|
|
1015
1091
|
const matrix = findMatrixTransport(preview);
|
|
1016
1092
|
if (!matrix) {
|
|
1017
1093
|
throw new Error("zooid.yaml: zooid dev requires at least one matrix transport");
|
|
@@ -1072,7 +1148,7 @@ async function runDev(flags) {
|
|
|
1072
1148
|
},
|
|
1073
1149
|
{
|
|
1074
1150
|
title: "Start daemon",
|
|
1075
|
-
task: async () => {
|
|
1151
|
+
task: async (_ctx, t) => {
|
|
1076
1152
|
const captures = {};
|
|
1077
1153
|
for (const name of Object.keys(preview.agents)) {
|
|
1078
1154
|
captures[name] = wireAgentCapture({
|
|
@@ -1091,7 +1167,10 @@ async function runDev(flags) {
|
|
|
1091
1167
|
installSignalHandlers: false,
|
|
1092
1168
|
adminUserId: `@${flags.adminUser}:${shape.serverName}`,
|
|
1093
1169
|
agentsDir: layout.agentsDir,
|
|
1094
|
-
onTap: (agentName, event) => captures[agentName]?.onTap(event)
|
|
1170
|
+
onTap: (agentName, event) => captures[agentName]?.onTap(event),
|
|
1171
|
+
prepullLog: (line) => {
|
|
1172
|
+
t.output = line.replace(/^\[zooid\]\s+/, "").trim();
|
|
1173
|
+
}
|
|
1095
1174
|
});
|
|
1096
1175
|
}
|
|
1097
1176
|
},
|
|
@@ -1099,10 +1178,12 @@ async function runDev(flags) {
|
|
|
1099
1178
|
{
|
|
1100
1179
|
title: "Start @zoon/web watcher (vite build --watch)",
|
|
1101
1180
|
task: async () => {
|
|
1102
|
-
const pkgDir = webSourcePackage(CLI_ROOT);
|
|
1181
|
+
const pkgDir = typeof flags.watchWeb === "string" ? resolve2(flags.watchWeb) : webSourcePackage(CLI_ROOT);
|
|
1103
1182
|
if (!pkgDir) {
|
|
1183
|
+
const defaultPath = dirname6(dirname6(dirname6(CLI_ROOT))) + "/zoon/packages/web";
|
|
1104
1184
|
throw new Error(
|
|
1105
|
-
|
|
1185
|
+
`--watch-web: @zoon/web not found at ${defaultPath}.
|
|
1186
|
+
Pass an explicit path: --watch-web=/path/to/zoon/packages/web`
|
|
1106
1187
|
);
|
|
1107
1188
|
}
|
|
1108
1189
|
ctx.webWatch = await startWebWatch({ webPackageDir: pkgDir });
|
|
@@ -1218,6 +1299,11 @@ You are the zooid setup assistant. Your job is to help the operator get a workfo
|
|
|
1218
1299
|
- Zooid documentation: https://zooid.dev/docs/
|
|
1219
1300
|
- Use your web fetch tool to read documentation pages when answering questions.
|
|
1220
1301
|
|
|
1302
|
+
## Stack facts
|
|
1303
|
+
|
|
1304
|
+
- **Tuwunel** is a lightweight Rust Matrix homeserver (Conduit fork) backed by RocksDB. Single binary, low resource floor \u2014 not "heavy" for typical workforces.
|
|
1305
|
+
- **Logs land on disk** in \`./data/\` inside this zooid home dir: tuwunel logs, the daemon, and each agent's ACP stream. Use \`zooid logs <source>\` to tail them (sources: \`tuwunel\`, \`daemon\`, \`dev\`, \`agent-<name>\`, \`agent-<name>.acp\`). Debugging is mostly "read the log file" \u2014 don't tell the operator it's opaque.
|
|
1306
|
+
|
|
1221
1307
|
## Behavior
|
|
1222
1308
|
|
|
1223
1309
|
- Be terse. Give the answer; link to the doc page; stop.
|
|
@@ -1656,6 +1742,7 @@ async function runStart(flags) {
|
|
|
1656
1742
|
|
|
1657
1743
|
// src/commands/status.ts
|
|
1658
1744
|
import { readFileSync as readFileSync5 } from "fs";
|
|
1745
|
+
import { dirname as dirname8 } from "path";
|
|
1659
1746
|
import chalk2 from "chalk";
|
|
1660
1747
|
async function probe(url, timeoutMs = 2e3) {
|
|
1661
1748
|
try {
|
|
@@ -1679,7 +1766,9 @@ async function collectStatus(opts) {
|
|
|
1679
1766
|
agents: []
|
|
1680
1767
|
};
|
|
1681
1768
|
}
|
|
1682
|
-
const cfg = loadZooidConfig(readFileSync5(found.path, "utf8")
|
|
1769
|
+
const cfg = loadZooidConfig(readFileSync5(found.path, "utf8"), {
|
|
1770
|
+
configDir: dirname8(found.path)
|
|
1771
|
+
});
|
|
1683
1772
|
const matrixEntry = Object.entries(cfg.transports).find(
|
|
1684
1773
|
([, t]) => t.type === "matrix"
|
|
1685
1774
|
);
|
|
@@ -1708,7 +1797,9 @@ async function runStatus(flags) {
|
|
|
1708
1797
|
if (port === void 0) {
|
|
1709
1798
|
const found = findConfigFile(cwd);
|
|
1710
1799
|
if (found) {
|
|
1711
|
-
const cfg = loadZooidConfig(readFileSync5(found.path, "utf8")
|
|
1800
|
+
const cfg = loadZooidConfig(readFileSync5(found.path, "utf8"), {
|
|
1801
|
+
configDir: dirname8(found.path)
|
|
1802
|
+
});
|
|
1712
1803
|
const matrix = findMatrixTransport(cfg);
|
|
1713
1804
|
if (matrix) {
|
|
1714
1805
|
const userIds = Object.values(cfg.agents).filter((a) => a.matrix?.transport === matrix.name).map((a) => a.matrix.user_id);
|
|
@@ -1741,14 +1832,17 @@ cli.command("start", "Run the daemon (production entry-point)").option("--data <
|
|
|
1741
1832
|
printToken: flags.printToken
|
|
1742
1833
|
});
|
|
1743
1834
|
});
|
|
1744
|
-
cli.command("dev", "Tuwunel + daemon + UI for local development").option("--data <dir>", "Persistent data root dir", { default: "./data" }).option("--engine <docker|podman>", "Container engine", { default: "docker" }).option("--ui-port <n>", "UI HTTP port", { default: 5173 }).option("--admin-user <name>", "Admin username", { default: "admin" }).option("--admin-password <pw>", "Admin password", { default: "admin" }).option(
|
|
1835
|
+
cli.command("dev", "Tuwunel + daemon + UI for local development").option("--data <dir>", "Persistent data root dir", { default: "./data" }).option("--engine <docker|podman>", "Container engine", { default: "docker" }).option("--ui-port <n>", "UI HTTP port", { default: 5173 }).option("--admin-user <name>", "Admin username", { default: "admin" }).option("--admin-password <pw>", "Admin password", { default: "admin" }).option(
|
|
1836
|
+
"--watch-web [path]",
|
|
1837
|
+
"Run vite build --watch on @zoon/web. Path defaults to sibling ../zoon/packages/web."
|
|
1838
|
+
).action(async (flags) => {
|
|
1745
1839
|
await runDev({
|
|
1746
1840
|
dataDir: flags.data,
|
|
1747
1841
|
engine: flags.engine,
|
|
1748
1842
|
uiPort: Number(flags.uiPort),
|
|
1749
1843
|
adminUser: flags.adminUser,
|
|
1750
1844
|
adminPassword: flags.adminPassword,
|
|
1751
|
-
watchWeb:
|
|
1845
|
+
watchWeb: flags.watchWeb
|
|
1752
1846
|
});
|
|
1753
1847
|
});
|
|
1754
1848
|
cli.command(
|