UNPKG

kestrel.markets

Version:

A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.

208 lines (205 loc) 6.6 kB
import { ARTIFACT_REF_SHAPE, ArgShapeError, OPERATION_ID_SHAPE, VALIDATE_DOCUMENT_SHAPE, agentDescribe, agentOpNames, asAuthoredResponse, asBlotters, asBoundResponse, asEventCursor, asRequiredString, asSessionRef, createSdk, localTransport, remoteTransport } from "./bin-a4jbxqxk.js"; import"./bin-cv13fq8c.js"; import"./bin-kxzrsgjw.js"; import { DEFAULT_API } from "./bin-qewrvqtv.js"; import { EXIT } from "./bin-t9ggwnv5.js"; import"./bin-xx1qrxe3.js"; import"./bin-t58k60v9.js"; import"./bin-p5jfg5b0.js"; import"./bin-29be75ss.js"; import"./bin-n77kea5n.js"; import"./bin-mn7wcxhv.js"; import"./bin-8pchjxn2.js"; import"./bin-am3351y2.js"; import"./bin-73jr945c.js"; import"./bin-df1tn094.js"; import"./bin-3ft0k1jq.js"; import"./bin-2ywrx58g.js"; import"./bin-wckvcay0.js"; // src/cli/commands/agent.ts var AGENT_PROTOCOL_VERSION = "kestrel.agent/v1"; var AGENT_OPS = agentOpNames; class AgentRefusal extends Error { name = "AgentRefusal"; code; constructor(code, message) { super(message); this.code = code; } } function codeOf(e) { if (e !== null && typeof e === "object" && "code" in e) { const code = e.code; if (typeof code === "string" && code.length > 0) return code; } return "error"; } function problemOf(e) { if (e !== null && typeof e === "object" && "problem" in e) { const p = e.problem; if (p !== null && typeof p === "object") return p; } return; } function buildSdk(api, fetchImpl) { if (api === undefined) return createSdk(localTransport()); const baseUrl = api === "" || api === "default" ? DEFAULT_API : api; return createSdk(remoteTransport({ baseUrl, fetch: fetchImpl })); } async function drainProcessStdin() { if (typeof Bun !== "undefined") return await Bun.stdin.text(); const chunks = []; for await (const chunk of process.stdin) chunks.push(chunk); return Buffer.concat(chunks).toString("utf8"); } function requireSession(s) { if (s === undefined) { throw new AgentRefusal("no-session", "no active Session — issue `openSession` before a session verb"); } return s; } async function agentCommand(globals, io) { const readIn = io?.stdin ?? drainProcessStdin; const writeOut = io?.stdout ?? ((s) => void process.stdout.write(s)); const writeErr = io?.stderr ?? ((s) => void process.stderr.write(s)); const fetchImpl = io?.fetch ?? globalThis.fetch; const sdk = buildSdk(globals.api, fetchImpl); const emit = (kind, value) => { writeOut(JSON.stringify({ v: AGENT_PROTOCOL_VERSION, kind, value }) + ` `); }; const refuse = (code, message, problem) => { writeErr(JSON.stringify({ v: AGENT_PROTOCOL_VERSION, kind: "refusal", code, message, ...problem !== undefined ? { problem } : {} }) + ` `); }; const raw = await readIn(); const requestLines = raw.split(` `).filter((l) => l.trim().length > 0); if (requestLines.length === 0) { const interactiveTty = io?.stdin === undefined && Boolean(process.stdin.isTTY); if (!interactiveTty) { refuse("empty-request-stream", "agent mode read zero request lines from stdin — expected one JSONL verb envelope (`{ op, ... }`) per line"); return EXIT.USAGE; } } let session; for (const rawLine of requestLines) { let req; try { const parsed = JSON.parse(rawLine); if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) { throw new AgentRefusal("bad-request", "a request line must be a JSON object"); } req = parsed; } catch (e) { const code = e instanceof AgentRefusal ? e.code : "bad-request"; refuse(code, `unparseable request line: ${rawLine}`); return EXIT.USAGE; } const op = req["op"]; try { switch (op) { case "describe": emit("describe", agentDescribe(AGENT_PROTOCOL_VERSION)); break; case "catalog": emit("catalog", await sdk.catalog()); break; case "validate": emit("validate", await sdk.validate(asRequiredString(req["document"], "document", VALIDATE_DOCUMENT_SHAPE))); break; case "openSession": { const document = req["document"] !== undefined ? String(req["document"]) : undefined; const gated = await sdk.openSession(asSessionRef(req["subject"]), document); if (gated.gated) { emit("openSession", { gated: true, payment: gated.payment }); } else { session = gated.value; emit("openSession", { gated: false, sessionId: gated.value.sessionId }); } break; } case "start": emit("start", await requireSession(session).start()); break; case "advance": emit("advance", await requireSession(session).advance(asAuthoredResponse(req["response"]))); break; case "revise": emit("revise", await requireSession(session).revise(asAuthoredResponse(req["response"]))); break; case "submit": emit("submit", await requireSession(session).submit(asBoundResponse(req["response"]))); break; case "resume": emit("resume", await requireSession(session).resume(asEventCursor(req["after"]))); break; case "finalize": emit("finalize", await requireSession(session).finalize()); break; case "grade": emit("grade", await sdk.grade({ blotters: asBlotters(req["blotters"]) })); break; case "artifact": emit("artifact", await sdk.artifact(asRequiredString(req["ref"], "ref", ARTIFACT_REF_SHAPE))); break; case "resumeOperation": { const after = asEventCursor(req["after"]); const ref = { operationId: asRequiredString(req["operationId"], "operationId", OPERATION_ID_SHAPE), ...after !== undefined ? { after } : {} }; emit("resumeOperation", await sdk.resumeOperation(ref)); break; } default: refuse("unknown-op", `unknown agent op ${JSON.stringify(op)} — valid ops: ${AGENT_OPS.join(", ")} (see \`kestrel agent --help\`)`); return EXIT.USAGE; } } catch (e) { if (e instanceof ArgShapeError) { refuse(e.code, e.message); return EXIT.USAGE; } refuse(codeOf(e), e instanceof Error ? e.message : String(e), problemOf(e)); return EXIT.GENERIC; } } return EXIT.OK; } export { agentCommand, AGENT_PROTOCOL_VERSION, AGENT_OPS };