agents
Version:
A home for your AI agents
481 lines (480 loc) • 18.1 kB
JavaScript
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
import { f as parseHostMessage, l as chunkEntries, t as CLOSE_REPLACED, u as inputText } from "./protocol-cOklVBBD.js";
//#region src/harness/container/daemon-core.ts
/**
* The harness daemon's core: everything about running an agent inside a
* container that does not depend on which agent it is.
*
* A daemon serves any number of sessions. For each one it keeps a queue of
* operations, runs them one at a time through an adapter, numbers every
* frame it produces, and keeps frames until the Durable Object acknowledges
* them, so a reconnecting object replays exactly what it missed. The
* adapter is the only agent-specific part: it opens a session (resuming it
* from state it persisted earlier, possibly in another container), runs one
* turn at a time, and reports what happens as `ContainerEvent`s.
*
* Nothing here touches Node, a socket library or a model SDK. The transport
* hands the daemon a `DaemonSocket` per connection and feeds it messages;
* `./runtime` does that over HTTP in a container, and the tests do it over
* a `WebSocketPair` in Workers.
*
* Modelled on the AI SDK's harness bridge (`runBridge`): the runtime owns
* the transport, sequencing and replay, and an adapter owns only the agent.
*
* @experimental The API may change before it stabilizes.
*/
/** Settled operations remembered per session, for `hello`. */
const SETTLED_KEPT = 1e3;
var _adapter = /* @__PURE__ */ new WeakMap();
var _runtimeId = /* @__PURE__ */ new WeakMap();
var _maxKeptFrames = /* @__PURE__ */ new WeakMap();
var _sessions = /* @__PURE__ */ new WeakMap();
/**
* The daemon core. One per container process.
*
* @experimental The API may change before it stabilizes.
*/
var ContainerDaemon = class {
/**
* @param options - The adapter and this container's id.
*/
constructor(options) {
_classPrivateFieldInitSpec(this, _adapter, void 0);
_classPrivateFieldInitSpec(this, _runtimeId, void 0);
_classPrivateFieldInitSpec(this, _maxKeptFrames, void 0);
_classPrivateFieldInitSpec(this, _sessions, /* @__PURE__ */ new Map());
_classPrivateFieldSet2(_adapter, this, options.adapter);
_classPrivateFieldSet2(_runtimeId, this, options.runtimeId);
_classPrivateFieldSet2(_maxKeptFrames, this, options.maxKeptFrames ?? 1e4);
}
/**
* Attach a connection for a session. A newer connection replaces an older
* one, which is closed with `CLOSE_REPLACED`. The daemon sends `hello`
* at once.
*
* @param session - The harness session id.
* @param socket - The send side.
* @returns The receive side, for the transport to drive.
*/
connect(session, socket) {
let state = _classPrivateFieldGet2(_sessions, this).get(session);
if (!state) {
state = new DaemonSession(session, _classPrivateFieldGet2(_adapter, this), _classPrivateFieldGet2(_runtimeId, this), _classPrivateFieldGet2(_maxKeptFrames, this));
_classPrivateFieldGet2(_sessions, this).set(session, state);
}
return state.attach(socket);
}
/** Close every adapter session, as the container shuts down. */
async close() {
await Promise.all([..._classPrivateFieldGet2(_sessions, this).values()].map((s) => s.shutdown()));
}
};
var _id = /* @__PURE__ */ new WeakMap();
var _adapter2 = /* @__PURE__ */ new WeakMap();
var _runtimeId2 = /* @__PURE__ */ new WeakMap();
var _maxKeptFrames2 = /* @__PURE__ */ new WeakMap();
var _seq = /* @__PURE__ */ new WeakMap();
var _kept = /* @__PURE__ */ new WeakMap();
var _operations = /* @__PURE__ */ new WeakMap();
var _queue = /* @__PURE__ */ new WeakMap();
var _running = /* @__PURE__ */ new WeakMap();
var _opened = /* @__PURE__ */ new WeakMap();
var _restoring = /* @__PURE__ */ new WeakMap();
var _socket = /* @__PURE__ */ new WeakMap();
var _live = /* @__PURE__ */ new WeakMap();
var _inbox = /* @__PURE__ */ new WeakMap();
var _DaemonSession_brand = /* @__PURE__ */ new WeakSet();
var DaemonSession = class {
constructor(id, adapter, runtimeId, maxKeptFrames) {
_classPrivateMethodInitSpec(this, _DaemonSession_brand);
_classPrivateFieldInitSpec(this, _id, void 0);
_classPrivateFieldInitSpec(this, _adapter2, void 0);
_classPrivateFieldInitSpec(this, _runtimeId2, void 0);
_classPrivateFieldInitSpec(this, _maxKeptFrames2, void 0);
_classPrivateFieldInitSpec(this, _seq, 0);
_classPrivateFieldInitSpec(this, _kept, []);
_classPrivateFieldInitSpec(this, _operations, /* @__PURE__ */ new Map());
_classPrivateFieldInitSpec(this, _queue, []);
_classPrivateFieldInitSpec(this, _running, void 0);
_classPrivateFieldInitSpec(this, _opened, void 0);
_classPrivateFieldInitSpec(this, _restoring, void 0);
_classPrivateFieldInitSpec(this, _socket, void 0);
_classPrivateFieldInitSpec(this, _live, false);
_classPrivateFieldInitSpec(this, _inbox, Promise.resolve());
_classPrivateFieldSet2(_id, this, id);
_classPrivateFieldSet2(_adapter2, this, adapter);
_classPrivateFieldSet2(_runtimeId2, this, runtimeId);
_classPrivateFieldSet2(_maxKeptFrames2, this, maxKeptFrames);
}
attach(socket) {
const previous = _classPrivateFieldGet2(_socket, this);
_classPrivateFieldSet2(_socket, this, socket);
_classPrivateFieldSet2(_live, this, false);
previous?.close(CLOSE_REPLACED, "replaced by a newer connection");
_assertClassBrand(_DaemonSession_brand, this, _send).call(this, socket, _assertClassBrand(_DaemonSession_brand, this, _hello).call(this));
return {
receive: (text) => {
if (_classPrivateFieldGet2(_socket, this) !== socket) return;
const message = parseHostMessage(text);
if (!message) {
_assertClassBrand(_DaemonSession_brand, this, _send).call(this, socket, {
type: "error",
message: "unparseable message"
});
return;
}
_classPrivateFieldSet2(_inbox, this, _classPrivateFieldGet2(_inbox, this).then(() => _assertClassBrand(_DaemonSession_brand, this, _handle).call(this, message)).catch((error) => {
_assertClassBrand(_DaemonSession_brand, this, _send).call(this, socket, {
type: "error",
message: errorText(error)
});
}));
},
closed: () => {
if (_classPrivateFieldGet2(_socket, this) !== socket) return;
_classPrivateFieldSet2(_socket, this, void 0);
_classPrivateFieldSet2(_live, this, false);
}
};
}
async shutdown() {
_classPrivateFieldGet2(_running, this)?.controller.abort();
const opened = _classPrivateFieldGet2(_opened, this);
_classPrivateFieldSet2(_opened, this, void 0);
await opened?.session.close().catch(() => void 0);
}
};
function _hello() {
const operations = [];
for (const operation of _classPrivateFieldGet2(_operations, this).values()) {
const state = operation.state;
operations.push(state.tag === "settled" ? {
operationId: operation.id,
status: "settled",
outcome: state.outcome
} : {
operationId: operation.id,
status: state.tag
});
}
return {
type: "hello",
protocol: 1,
runtimeId: _classPrivateFieldGet2(_runtimeId2, this),
session: _classPrivateFieldGet2(_id, this),
adapter: {
id: _classPrivateFieldGet2(_adapter2, this).id,
version: _classPrivateFieldGet2(_adapter2, this).version,
capabilities: [..._classPrivateFieldGet2(_adapter2, this).capabilities ?? []]
},
open: _classPrivateFieldGet2(_opened, this)?.generation ?? null,
lastSeq: _classPrivateFieldGet2(_seq, this),
operations
};
}
async function _handle(message) {
switch (message.type) {
case "restore":
if (_classPrivateFieldGet2(_restoring, this)?.generation !== message.generation) _classPrivateFieldSet2(_restoring, this, {
generation: message.generation,
entries: []
});
_classPrivateFieldGet2(_restoring, this).entries.push(...message.entries);
return;
case "open":
await _assertClassBrand(_DaemonSession_brand, this, _open).call(this, message);
return;
case "replay":
_assertClassBrand(_DaemonSession_brand, this, _replay).call(this, message.after);
return;
case "prompt":
await _assertClassBrand(_DaemonSession_brand, this, _prompt).call(this, message.operationId, message.input, message.whenBusy);
return;
case "abort":
_assertClassBrand(_DaemonSession_brand, this, _abort).call(this, message.operationId);
return;
case "configure":
await _classPrivateFieldGet2(_opened, this)?.session.configure?.(message.settings);
return;
case "ack":
_classPrivateFieldSet2(_kept, this, _classPrivateFieldGet2(_kept, this).filter((kept) => kept.seq > message.seq));
return;
}
}
async function _open(message) {
const restoring = _classPrivateFieldGet2(_restoring, this);
_classPrivateFieldSet2(_restoring, this, void 0);
if (_classPrivateFieldGet2(_opened, this)?.generation === message.generation) return;
const restore = restoring?.generation === message.generation ? [...restoring.entries, ...message.restore] : message.restore;
if (_classPrivateFieldGet2(_opened, this)) {
_classPrivateFieldGet2(_running, this)?.controller.abort();
await _classPrivateFieldGet2(_opened, this).session.close().catch(() => void 0);
_classPrivateFieldSet2(_opened, this, void 0);
}
const session = await _classPrivateFieldGet2(_adapter2, this).open({
session: _classPrivateFieldGet2(_id, this),
settings: message.settings,
restore,
emit: (event) => _assertClassBrand(_DaemonSession_brand, this, _emit).call(this, {
kind: "event",
operationId: _classPrivateFieldGet2(_running, this)?.id ?? null,
event
}),
persist: (entries) => {
for (const group of chunkEntries(entries)) _assertClassBrand(_DaemonSession_brand, this, _emit).call(this, {
kind: "persist",
entries: group
});
},
log: (level, text) => _assertClassBrand(_DaemonSession_brand, this, _emit).call(this, {
kind: "event",
operationId: _classPrivateFieldGet2(_running, this)?.id ?? null,
event: {
type: "log",
level,
message: text
}
})
});
_classPrivateFieldSet2(_opened, this, {
generation: message.generation,
session
});
_assertClassBrand(_DaemonSession_brand, this, _pump).call(this);
}
function _replay(after) {
const socket = _classPrivateFieldGet2(_socket, this);
if (!socket) return;
for (const kept of _classPrivateFieldGet2(_kept, this)) if (kept.seq > after) _assertClassBrand(_DaemonSession_brand, this, _send).call(this, socket, {
type: "frame",
seq: kept.seq,
frame: kept.frame
});
_assertClassBrand(_DaemonSession_brand, this, _send).call(this, socket, {
type: "caught-up",
lastSeq: _classPrivateFieldGet2(_seq, this)
});
_classPrivateFieldSet2(_live, this, true);
}
async function _prompt(id, input, whenBusy) {
if (_classPrivateFieldGet2(_operations, this).has(id)) return;
const operation = {
id,
input,
whenBusy,
state: { tag: "queued" }
};
_classPrivateFieldGet2(_operations, this).set(id, operation);
_assertClassBrand(_DaemonSession_brand, this, _forgetOldSettled).call(this);
const running = _classPrivateFieldGet2(_running, this);
const steer = _classPrivateFieldGet2(_opened, this)?.session.steer;
if (whenBusy === "steer" && running && steer) {
if (await steer.call(_classPrivateFieldGet2(_opened, this)?.session, input) && _classPrivateFieldGet2(_running, this) === running) {
operation.state = { tag: "running" };
running.folded.push(id);
_assertClassBrand(_DaemonSession_brand, this, _emit).call(this, {
kind: "start",
operationId: id
});
return;
}
}
_classPrivateFieldGet2(_queue, this).push(id);
_assertClassBrand(_DaemonSession_brand, this, _pump).call(this);
}
function _abort(id) {
const ids = id === void 0 ? [..._classPrivateFieldGet2(_operations, this).keys()] : _classPrivateFieldGet2(_operations, this).has(id) ? [id] : [];
for (const each of ids) {
const operation = _classPrivateFieldGet2(_operations, this).get(each);
if (!operation) continue;
if (operation.state.tag === "queued") {
const at = _classPrivateFieldGet2(_queue, this).indexOf(each);
if (at >= 0) _classPrivateFieldGet2(_queue, this).splice(at, 1);
_assertClassBrand(_DaemonSession_brand, this, _settle).call(this, operation, {
status: "unanswered",
reason: "aborted"
});
} else if (operation.state.tag === "running") _classPrivateFieldGet2(_running, this)?.controller.abort();
}
}
/** Start the next queued operation, if the session is open and idle. */
function _pump() {
const opened = _classPrivateFieldGet2(_opened, this);
if (_classPrivateFieldGet2(_running, this) || !opened) return;
const id = _classPrivateFieldGet2(_queue, this).shift();
if (id === void 0) return;
const operation = _classPrivateFieldGet2(_operations, this).get(id);
if (!operation || operation.state.tag !== "queued") {
_assertClassBrand(_DaemonSession_brand, this, _pump).call(this);
return;
}
const running = {
id,
folded: [],
controller: new AbortController()
};
_classPrivateFieldSet2(_running, this, running);
operation.state = { tag: "running" };
_assertClassBrand(_DaemonSession_brand, this, _emit).call(this, {
kind: "start",
operationId: id
});
_assertClassBrand(_DaemonSession_brand, this, _run).call(this, opened, operation, running);
}
async function _run(opened, operation, running) {
let outcome;
try {
outcome = await opened.session.run({
operationId: operation.id,
input: operation.input,
signal: running.controller.signal
});
if (running.controller.signal.aborted && outcome.status === "done") outcome = {
status: "unanswered",
reason: "aborted"
};
} catch (error) {
outcome = {
status: "unanswered",
reason: running.controller.signal.aborted ? "aborted" : errorText(error)
};
}
if (_classPrivateFieldGet2(_running, this) === running) _classPrivateFieldSet2(_running, this, void 0);
_assertClassBrand(_DaemonSession_brand, this, _settle).call(this, operation, outcome);
for (const folded of running.folded) {
const each = _classPrivateFieldGet2(_operations, this).get(folded);
if (each) _assertClassBrand(_DaemonSession_brand, this, _settle).call(this, each, outcome);
}
_assertClassBrand(_DaemonSession_brand, this, _pump).call(this);
}
function _settle(operation, outcome) {
if (operation.state.tag === "settled") return;
operation.state = {
tag: "settled",
outcome
};
_assertClassBrand(_DaemonSession_brand, this, _emit).call(this, {
kind: "settle",
operationId: operation.id,
outcome
});
}
function _emit(frame) {
_classPrivateFieldSet2(_seq, this, _classPrivateFieldGet2(_seq, this) + 1);
const seq = _classPrivateFieldGet2(_seq, this);
_classPrivateFieldGet2(_kept, this).push({
seq,
frame
});
if (_classPrivateFieldGet2(_kept, this).length > _classPrivateFieldGet2(_maxKeptFrames2, this)) _classPrivateFieldGet2(_kept, this).splice(0, _classPrivateFieldGet2(_kept, this).length - _classPrivateFieldGet2(_maxKeptFrames2, this));
const socket = _classPrivateFieldGet2(_socket, this);
if (socket && _classPrivateFieldGet2(_live, this)) _assertClassBrand(_DaemonSession_brand, this, _send).call(this, socket, {
type: "frame",
seq,
frame
});
}
function _send(socket, message) {
try {
socket.send(JSON.stringify(message));
} catch {}
}
function _forgetOldSettled() {
if (_classPrivateFieldGet2(_operations, this).size <= SETTLED_KEPT) return;
for (const [id, operation] of _classPrivateFieldGet2(_operations, this)) {
if (_classPrivateFieldGet2(_operations, this).size <= SETTLED_KEPT) return;
if (operation.state.tag === "settled") _classPrivateFieldGet2(_operations, this).delete(id);
}
}
function errorText(error) {
return error instanceof Error ? error.message : String(error);
}
/**
* A reference adapter that answers `echo: <text>` and needs no model or
* credentials. Use it for keyless smoke deploys of the whole path and in
* tests. It persists one entry per turn and counts them back after a
* restore, so a resumed session visibly remembers its history:
*
* - `slow <ms> <text>` waits `ms` before answering, and stops on abort.
* - `fail <reason>` settles the operation unanswered with `reason`.
* - anything else is echoed with the turn number: `echo: hi (turn 3)`.
*
* @experimental The API may change before it stabilizes.
*/
const echoAdapter = {
id: "echo",
version: "1",
capabilities: ["steer"],
open(context) {
let turns = context.restore.length;
const steered = [];
return {
async run(turn) {
const text = inputText(turn.input);
const slow = /^slow (\d+) ?(.*)$/s.exec(text);
if (slow) await sleep(Number(slow[1]), turn.signal);
const failure = /^fail ?(.*)$/s.exec(text);
if (failure) return {
status: "unanswered",
reason: failure[1] || "failed"
};
turns += 1;
const body = slow ? slow[2] ?? "" : text;
const answer = `echo: ${body}${steered.splice(0).map((s) => ` + ${s}`).join("")} (turn ${turns})`;
const messageId = `${turn.operationId}:assistant`;
context.emit({
type: "text-delta",
messageId,
delta: answer
});
context.emit({
type: "message",
message: {
id: messageId,
role: "assistant",
parts: [{
type: "text",
text: answer
}],
operationId: turn.operationId,
createdAt: Date.now()
}
});
context.persist([{
turn: turns,
text: body
}]);
return {
status: "done",
text: answer
};
},
steer(input) {
steered.push(inputText(input));
return true;
},
async close() {}
};
}
};
function sleep(ms, signal) {
return new Promise((resolve, reject) => {
if (signal.aborted) {
reject(/* @__PURE__ */ new Error("aborted"));
return;
}
const timer = setTimeout(() => {
signal.removeEventListener("abort", onAbort);
resolve();
}, ms);
const onAbort = () => {
clearTimeout(timer);
reject(/* @__PURE__ */ new Error("aborted"));
};
signal.addEventListener("abort", onAbort, { once: true });
});
}
//#endregion
export { echoAdapter as n, ContainerDaemon as t };
//# sourceMappingURL=daemon-core-Buubj-y1.js.map