zooid 0.11.2 → 0.13.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/README.md +8 -3
- package/dist/bin.js +503 -124
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-KGYQ5YNP.js → chunk-YZ4IO5MR.js} +78 -11
- package/dist/chunk-YZ4IO5MR.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +11 -9
- package/src/bin.test.ts +63 -0
- package/src/bin.ts +55 -6
- package/src/bootstrap/configs.test.ts +7 -0
- package/src/bootstrap/configs.ts +14 -0
- package/src/build-registry.ts +1 -1
- package/src/build-registry.zod044.test.ts +23 -0
- package/src/commands/dev.ts +37 -7
- package/src/commands/init/generators.test.ts +43 -0
- package/src/commands/init/generators.ts +24 -5
- package/src/commands/init/pi-scaffold.test.ts +151 -0
- package/src/commands/init/prompts.ts +53 -2
- package/src/commands/init/registry.test.ts +60 -0
- package/src/commands/init/registry.ts +58 -0
- package/src/commands/init/sniff.test.ts +61 -2
- package/src/commands/init/sniff.ts +43 -12
- package/src/commands/init.ts +91 -5
- package/src/commands/status.test.ts +15 -0
- package/src/commands/status.ts +27 -2
- package/src/daemon/start-daemon.ts +15 -1
- package/src/push-gateway/gateway.test.ts +150 -0
- package/src/push-gateway/gateway.ts +78 -0
- package/src/push-gateway/index.ts +17 -0
- package/src/push-gateway/payload.test.ts +88 -0
- package/src/push-gateway/payload.ts +39 -0
- package/src/push-gateway/types.ts +37 -0
- package/src/push-gateway/vapid.test.ts +45 -0
- package/src/push-gateway/vapid.ts +34 -0
- package/src/services/tuwunel.ts +21 -2
- package/src/version.test.ts +67 -0
- package/src/version.ts +30 -0
- package/src/web/static.test.ts +22 -0
- package/src/web/static.ts +9 -1
- package/dist/chunk-KGYQ5YNP.js.map +0 -1
|
@@ -24056,6 +24056,27 @@ var PRESETS_INTERNAL = {
|
|
|
24056
24056
|
create: false
|
|
24057
24057
|
}
|
|
24058
24058
|
]
|
|
24059
|
+
},
|
|
24060
|
+
// pi (ZOD073). Vendored-shim category: `pi-acp` is an adapter that speaks ACP
|
|
24061
|
+
// on pi's behalf and spawns `pi --mode rpc` as a child. No flags — its
|
|
24062
|
+
// published Zed config is `args: []`, and the only documented flag
|
|
24063
|
+
// (--terminal-login) is an interactive auth path with no place in a daemon.
|
|
24064
|
+
pi: {
|
|
24065
|
+
command: "npx",
|
|
24066
|
+
args: ["-y", "pi-acp"],
|
|
24067
|
+
image: "ghcr.io/zooid-ai/agent-pi:latest",
|
|
24068
|
+
mounts: (ctx) => [
|
|
24069
|
+
{
|
|
24070
|
+
// Single tree: agent/sessions, agent/prompts, and the adapter's
|
|
24071
|
+
// pi-acp/session-map.json. Project config lives in <cwd>/.pi, which is
|
|
24072
|
+
// already inside the workspace mount.
|
|
24073
|
+
id: "home",
|
|
24074
|
+
host: `${ctx.daemonHome}/.pi`,
|
|
24075
|
+
target: "/root/.pi",
|
|
24076
|
+
mode: "rw",
|
|
24077
|
+
create: false
|
|
24078
|
+
}
|
|
24079
|
+
]
|
|
24059
24080
|
}
|
|
24060
24081
|
};
|
|
24061
24082
|
var PRESETS = Object.freeze(
|
|
@@ -25914,7 +25935,8 @@ var MatrixContextProvider = class {
|
|
|
25914
25935
|
const threads = [];
|
|
25915
25936
|
for (const ev of chunk) {
|
|
25916
25937
|
if (ev.type !== "m.room.message") continue;
|
|
25917
|
-
if (ev.content?.msgtype !== "m.text" || typeof ev.content.body !== "string")
|
|
25938
|
+
if (ev.content?.msgtype !== "m.text" && ev.content?.msgtype !== "m.notice" || typeof ev.content.body !== "string")
|
|
25939
|
+
continue;
|
|
25918
25940
|
const relatesTo = ev.content["m.relates_to"];
|
|
25919
25941
|
if (relatesTo?.rel_type === "m.thread") continue;
|
|
25920
25942
|
const agent = this.opts.agentBots.get(ev.sender);
|
|
@@ -25988,7 +26010,7 @@ var MatrixContextProvider = class {
|
|
|
25988
26010
|
...threadId !== void 0 ? { thread_id: threadId } : {}
|
|
25989
26011
|
};
|
|
25990
26012
|
}
|
|
25991
|
-
if (msgtype !== "m.text" || typeof body !== "string") return null;
|
|
26013
|
+
if (msgtype !== "m.text" && msgtype !== "m.notice" || typeof body !== "string") return null;
|
|
25992
26014
|
return {
|
|
25993
26015
|
id: ev.event_id,
|
|
25994
26016
|
sender: ev.sender,
|
|
@@ -26381,7 +26403,11 @@ var RECOVERY_URLS = {
|
|
|
26381
26403
|
function toErrorBody(evt, threadRoot) {
|
|
26382
26404
|
const msg = evt.message.slice(0, 250);
|
|
26383
26405
|
const out = {
|
|
26384
|
-
msgtype:
|
|
26406
|
+
// No msgtype: dev.zooid.error is not m.room.message, so the field is
|
|
26407
|
+
// meaningless here — it was a vestige of copying the message-body shape.
|
|
26408
|
+
// Its presence used to force careful push-rule `before` positioning
|
|
26409
|
+
// (ZNC025 §10); that positioning is kept regardless, since it also
|
|
26410
|
+
// protects rules for event types that never carried the field.
|
|
26385
26411
|
body: `\u26A0 [${evt.code}] ${msg}`,
|
|
26386
26412
|
code: evt.code,
|
|
26387
26413
|
message: msg,
|
|
@@ -26396,6 +26422,25 @@ function toErrorBody(evt, threadRoot) {
|
|
|
26396
26422
|
if (recovery) out.recovery = recovery;
|
|
26397
26423
|
return out;
|
|
26398
26424
|
}
|
|
26425
|
+
var PREVIEW_MAX = 140;
|
|
26426
|
+
function toTurnEndBody(evt, threadRoot) {
|
|
26427
|
+
const preview = evt.lastMessage?.trim().replace(/\s+/g, " ");
|
|
26428
|
+
return {
|
|
26429
|
+
// `body` stays the turn-boundary summary: it is what a generic Matrix
|
|
26430
|
+
// client renders for this event, and the prose is already its own message
|
|
26431
|
+
// in the timeline. The preview below exists only for the push, which
|
|
26432
|
+
// cannot see that message — agent prose is `m.notice`, deliberately
|
|
26433
|
+
// silenced by `.m.rule.suppress_notices` so a chatty turn doesn't fire one
|
|
26434
|
+
// push per chunk ([[ZNC025]] §10). Without it the only notification the
|
|
26435
|
+
// user gets says an agent finished and nothing about what it said.
|
|
26436
|
+
body: evt.producedOutput ? `${evt.agentId} finished` : `${evt.agentId} finished without output`,
|
|
26437
|
+
...preview ? { last_message: preview.slice(0, PREVIEW_MAX) } : {},
|
|
26438
|
+
agent_id: evt.agentId,
|
|
26439
|
+
session_id: evt.sessionId,
|
|
26440
|
+
produced_output: evt.producedOutput,
|
|
26441
|
+
"m.relates_to": { rel_type: "m.thread", event_id: threadRoot }
|
|
26442
|
+
};
|
|
26443
|
+
}
|
|
26399
26444
|
|
|
26400
26445
|
// ../transport-matrix/src/markdown-to-matrix-html.ts
|
|
26401
26446
|
import { marked } from "marked";
|
|
@@ -26710,7 +26755,11 @@ function createMatrixTransport(opts) {
|
|
|
26710
26755
|
const pendingCommands = /* @__PURE__ */ new Map();
|
|
26711
26756
|
const buildTextContent = (text) => {
|
|
26712
26757
|
const content = {
|
|
26713
|
-
|
|
26758
|
+
// m.notice, not m.text: .m.rule.suppress_notices silences the
|
|
26759
|
+
// chunk-storm of agent prose server-side (ZNC025 §10) instead of every
|
|
26760
|
+
// client having to filter it. dev.zooid.error carries the same tweak
|
|
26761
|
+
// for the same reason.
|
|
26762
|
+
msgtype: "m.notice",
|
|
26714
26763
|
body: text
|
|
26715
26764
|
};
|
|
26716
26765
|
const html = toMatrixHtml(text);
|
|
@@ -26724,11 +26773,13 @@ function createMatrixTransport(opts) {
|
|
|
26724
26773
|
}
|
|
26725
26774
|
return content;
|
|
26726
26775
|
};
|
|
26776
|
+
const lastFlushed = /* @__PURE__ */ new Map();
|
|
26727
26777
|
const flushBuffer = (sessionId) => {
|
|
26728
26778
|
const ctx = sessions.get(sessionId);
|
|
26729
26779
|
const text = buffers.get(sessionId) ?? "";
|
|
26730
26780
|
if (!ctx || text.length === 0) return false;
|
|
26731
26781
|
buffers.set(sessionId, "");
|
|
26782
|
+
lastFlushed.set(sessionId, text);
|
|
26732
26783
|
flushedCounts.set(sessionId, (flushedCounts.get(sessionId) ?? 0) + 1);
|
|
26733
26784
|
const content = buildTextContent(text);
|
|
26734
26785
|
const tail = (sendQueue.get(sessionId) ?? Promise.resolve()).then(async () => {
|
|
@@ -27141,19 +27192,30 @@ function createMatrixTransport(opts) {
|
|
|
27141
27192
|
drained = next;
|
|
27142
27193
|
}
|
|
27143
27194
|
flushBuffer(sessionId);
|
|
27195
|
+
} finally {
|
|
27196
|
+
clearInterval(refresh);
|
|
27197
|
+
await safeTyping(false);
|
|
27198
|
+
await safePresence("online");
|
|
27144
27199
|
await (sendQueue.get(sessionId) ?? Promise.resolve());
|
|
27145
|
-
|
|
27200
|
+
const producedOutput = (flushedCounts.get(sessionId) ?? 0) > 0;
|
|
27201
|
+
if (!producedOutput) {
|
|
27146
27202
|
console.warn(
|
|
27147
27203
|
`[matrix:${agent.name}] turn finished with empty buffer (session=${sessionId}); nothing sent to ${evt.room_id}`
|
|
27148
27204
|
);
|
|
27149
27205
|
}
|
|
27150
|
-
|
|
27151
|
-
|
|
27152
|
-
|
|
27153
|
-
|
|
27206
|
+
await client.sendCustomEvent({
|
|
27207
|
+
roomId: evt.room_id,
|
|
27208
|
+
asUserId: agent.userId,
|
|
27209
|
+
eventType: "dev.zooid.turn.end",
|
|
27210
|
+
content: toTurnEndBody(
|
|
27211
|
+
{ agentId: agent.name, sessionId, producedOutput, lastMessage: lastFlushed.get(sessionId) },
|
|
27212
|
+
threadRoot
|
|
27213
|
+
)
|
|
27214
|
+
}).catch((e) => console.warn(`[matrix:${agent.name}] turn.end send failed:`, e));
|
|
27154
27215
|
buffers.delete(sessionId);
|
|
27155
27216
|
bufferMessageIds.delete(sessionId);
|
|
27156
27217
|
flushedCounts.delete(sessionId);
|
|
27218
|
+
lastFlushed.delete(sessionId);
|
|
27157
27219
|
sendQueue.delete(sessionId);
|
|
27158
27220
|
}
|
|
27159
27221
|
}
|
|
@@ -27303,7 +27365,10 @@ import { unlink } from "fs/promises";
|
|
|
27303
27365
|
async function startDaemonSocketServer(opts) {
|
|
27304
27366
|
await unlink(opts.sockPath).catch(() => {
|
|
27305
27367
|
});
|
|
27368
|
+
const open = /* @__PURE__ */ new Set();
|
|
27306
27369
|
const server = createServer((socket) => {
|
|
27370
|
+
open.add(socket);
|
|
27371
|
+
socket.on("close", () => open.delete(socket));
|
|
27307
27372
|
let buf = "";
|
|
27308
27373
|
socket.setEncoding("utf8");
|
|
27309
27374
|
socket.on("data", async (chunk) => {
|
|
@@ -27329,6 +27394,8 @@ async function startDaemonSocketServer(opts) {
|
|
|
27329
27394
|
return {
|
|
27330
27395
|
close: () => new Promise((resolve) => {
|
|
27331
27396
|
server.close(() => resolve());
|
|
27397
|
+
for (const socket of open) socket.destroy();
|
|
27398
|
+
open.clear();
|
|
27332
27399
|
})
|
|
27333
27400
|
};
|
|
27334
27401
|
}
|
|
@@ -32764,7 +32831,7 @@ function buildAcpRegistry(cfg, opts = {}) {
|
|
|
32764
32831
|
throw new Error(
|
|
32765
32832
|
`runtime: ${cfg.runtime} requires a container image for each agent. Unresolved:
|
|
32766
32833
|
` + lines.join("\n") + `
|
|
32767
|
-
Set agents.<name>.container.image, top-level container.image, or use a preset that ships a default image (claude, codex, opencode).`
|
|
32834
|
+
Set agents.<name>.container.image, top-level container.image, or use a preset that ships a default image (claude, codex, opencode, pi).`
|
|
32768
32835
|
);
|
|
32769
32836
|
}
|
|
32770
32837
|
}
|
|
@@ -32890,4 +32957,4 @@ export {
|
|
|
32890
32957
|
startDaemonSocketServer,
|
|
32891
32958
|
buildAcpRegistry
|
|
32892
32959
|
};
|
|
32893
|
-
//# sourceMappingURL=chunk-
|
|
32960
|
+
//# sourceMappingURL=chunk-YZ4IO5MR.js.map
|