@casimesh/agent-runtime 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ssvasan369 and the Autonomous AI Mesh contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # @casimesh/agent-runtime
2
+
3
+ Runs agents for the Autonomous AI Mesh: supervision with a restart policy, model adapters (a deterministic rule-based
4
+ model and Claude via the Anthropic SDK), a tool registry, scoped memory, an in-process organization bus for agents to
5
+ help each other, and the observe → reason → act → verify pipeline that records each step of every task.
6
+
7
+ A mesh Node Server uses it to host its agents. You can also use it on its own:
8
+
9
+ ```ts
10
+ import { AgentRuntime, ClaudeModel, RuleBasedModel } from "@casimesh/agent-runtime";
11
+
12
+ const runtime = new AgentRuntime({
13
+ // Agents whose `model` names Claude use it; everything else uses the rule-based model.
14
+ claude: process.env.ANTHROPIC_API_KEY ? new ClaudeModel({ apiKey: process.env.ANTHROPIC_API_KEY }) : undefined,
15
+ fallback: new RuleBasedModel({
16
+ "terrain.analysis": ({ input }) => ({ area: input.area, slope: "moderate" }),
17
+ }),
18
+ });
19
+
20
+ runtime.onStatus((report) => console.log(report.agentId, report.status));
21
+ runtime.start({
22
+ id: "agt_analyst",
23
+ organizationId: "org_mapping",
24
+ nodeId: "node_c",
25
+ name: "Terrain Analyst",
26
+ kind: "standard",
27
+ capabilities: [{ name: "terrain.analysis", version: "1.0.0" }],
28
+ model: null,
29
+ });
30
+
31
+ const result = await runtime.execute("agt_analyst", {
32
+ id: "tsk_1",
33
+ capability: "terrain.analysis",
34
+ input: { area: "sector-7" },
35
+ });
36
+ console.log(result.output, result.steps.map((s) => s.name)); // observe, reason, act, verify
37
+ ```
38
+
39
+ Custom tools are Zod-validated and offered to models as JSON Schema:
40
+
41
+ ```ts
42
+ import { z } from "zod";
43
+
44
+ new AgentRuntime({
45
+ tools: [
46
+ {
47
+ name: "elevation",
48
+ description: "Elevation of a grid cell in metres",
49
+ input: z.object({ cell: z.string() }),
50
+ run: ({ cell }) => ({ cell, metres: 412 }),
51
+ },
52
+ ],
53
+ });
54
+ ```
55
+
56
+ Requires Node 22+ or Bun. MIT licensed.
package/index.d.ts ADDED
@@ -0,0 +1,328 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { z } from 'zod';
3
+ import { Agent, TaskParty, TaskStep } from '@casimesh/contracts';
4
+
5
+ /** A handled task, as an agent remembers it. */
6
+ interface MemoryEntry {
7
+ readonly taskId: string;
8
+ readonly capability: string;
9
+ readonly summary: string;
10
+ readonly at: string;
11
+ }
12
+ /** Memory scoped to one agent: facts it keeps plus a capped history of the tasks it handled. */
13
+ interface AgentMemory {
14
+ get(key: string): unknown;
15
+ set(key: string, value: unknown): void;
16
+ delete(key: string): void;
17
+ entries(): ReadonlyMap<string, unknown>;
18
+ remember(entry: MemoryEntry): void;
19
+ history(): readonly MemoryEntry[];
20
+ }
21
+ /** Where agents' memories live. In-memory for now; a persistent store can implement the same port. */
22
+ interface MemoryStore {
23
+ forAgent(agentId: string): AgentMemory;
24
+ drop(agentId: string): void;
25
+ }
26
+ declare class InMemoryMemoryStore implements MemoryStore {
27
+ private readonly memories;
28
+ forAgent(agentId: string): AgentMemory;
29
+ drop(agentId: string): void;
30
+ }
31
+
32
+ /** The work handed to an agent: one capability request (ADR-0020). */
33
+ interface TaskRequest {
34
+ readonly id: string;
35
+ readonly capability: string;
36
+ readonly input: Readonly<Record<string, unknown>>;
37
+ /** Who asked; absent for requests between colleagues on the org bus. */
38
+ readonly requester?: TaskParty | undefined;
39
+ }
40
+ /** What an agent returns for a task, with the provenance steps that produced it. */
41
+ interface TaskResult {
42
+ readonly output: Record<string, unknown>;
43
+ readonly steps: readonly TaskStep[];
44
+ /** The model that reasoned about the task; null when the rule-based model did. */
45
+ readonly model: string | null;
46
+ }
47
+ /** The agent fields the runtime needs; a contracts `Agent` satisfies it. */
48
+ type AgentSpec = Pick<Agent, "id" | "organizationId" | "nodeId" | "name" | "kind" | "capabilities" | "model">;
49
+ /** Lifecycle reports from the runtime; the node records them as `agent.status_changed` events. */
50
+ type AgentStatusReport = {
51
+ readonly agentId: string;
52
+ readonly status: "running";
53
+ } | {
54
+ readonly agentId: string;
55
+ readonly status: "starting";
56
+ readonly attempt: number;
57
+ } | {
58
+ readonly agentId: string;
59
+ readonly status: "stopped";
60
+ } | {
61
+ readonly agentId: string;
62
+ readonly status: "error";
63
+ readonly reason: string;
64
+ };
65
+ type Clock = () => Date;
66
+
67
+ /** What a tool can reach while it runs on behalf of an agent. */
68
+ interface ToolContext {
69
+ readonly agent: AgentSpec;
70
+ readonly memory: AgentMemory;
71
+ /** Asks a colleague in the same organization for a capability over the org bus (internal collaboration). */
72
+ collaborate(capability: string, input: Record<string, unknown>): Promise<Record<string, unknown>>;
73
+ }
74
+ interface Tool<I = unknown> {
75
+ /** `^[a-zA-Z0-9_-]{1,64}$`, as model APIs require. */
76
+ readonly name: string;
77
+ readonly description: string;
78
+ readonly input: z.ZodType<I>;
79
+ run(input: I, context: ToolContext): unknown | Promise<unknown>;
80
+ }
81
+ /** A tool as a model sees it: name, description and a JSON Schema for its input. */
82
+ interface ToolSpec {
83
+ readonly name: string;
84
+ readonly description: string;
85
+ readonly inputSchema: Record<string, unknown> & {
86
+ type: "object";
87
+ };
88
+ }
89
+ /** Named tools with validated input, shared by every agent of a runtime. */
90
+ declare class ToolRegistry {
91
+ private readonly tools;
92
+ register<I>(tool: Tool<I>): this;
93
+ has(name: string): boolean;
94
+ specs(): ToolSpec[];
95
+ run(name: string, input: unknown, context: ToolContext): Promise<unknown>;
96
+ }
97
+ /** Tools every agent has: ask a colleague, and keep or recall facts in its own memory. */
98
+ declare function builtInTools(): ToolRegistry;
99
+
100
+ /** A tool call the model made while reasoning, with what the tool returned. */
101
+ interface ToolCall {
102
+ readonly name: string;
103
+ readonly input: unknown;
104
+ readonly result: unknown;
105
+ }
106
+ interface ModelRequest {
107
+ /** Model id (e.g. `claude-opus-5-5`), or null for the rule-based model. */
108
+ readonly model: string | null;
109
+ readonly system: string;
110
+ readonly prompt: string;
111
+ /** The task itself, for models that work on structure rather than text. */
112
+ readonly capability: string;
113
+ readonly input: Readonly<Record<string, unknown>>;
114
+ readonly tools: readonly ToolSpec[];
115
+ /** Runs a tool on the agent's behalf; the adapter owns the tool-use loop. */
116
+ runTool(name: string, input: unknown): Promise<unknown>;
117
+ }
118
+ interface ModelResponse {
119
+ /** The model's final answer, as text. */
120
+ readonly text: string;
121
+ /** The answer parsed as a JSON object, when it is one. */
122
+ readonly output: Record<string, unknown> | null;
123
+ readonly toolCalls: readonly ToolCall[];
124
+ /** The model that answered; null for the rule-based model. */
125
+ readonly model: string | null;
126
+ }
127
+ /** Port for anything that can reason about a task: a rule set, Claude, or another provider. */
128
+ interface ModelAdapter {
129
+ readonly name: string;
130
+ generate(request: ModelRequest): Promise<ModelResponse>;
131
+ }
132
+ /** Extracts a JSON object from a model answer: the whole text, or the first fenced or braced block. */
133
+ declare function parseJsonObject(text: string): Record<string, unknown> | null;
134
+
135
+ /** The part of the Anthropic client this adapter uses, so tests can substitute a fake. */
136
+ interface MessagesClient {
137
+ messages: {
138
+ create(params: Anthropic.MessageCreateParamsNonStreaming): Promise<Anthropic.Message>;
139
+ };
140
+ }
141
+ interface ClaudeModelOptions {
142
+ readonly apiKey?: string | undefined;
143
+ readonly client?: MessagesClient | undefined;
144
+ /** Used when an agent names no model. */
145
+ readonly defaultModel?: string | undefined;
146
+ readonly maxTokens?: number | undefined;
147
+ /** Model turns per task, tool calls included. */
148
+ readonly maxTurns?: number | undefined;
149
+ }
150
+ declare const DEFAULT_CLAUDE_MODEL = "claude-opus-5-5";
151
+ /** Claude through the Anthropic Messages API, with tool use (ADR-0020). */
152
+ declare class ClaudeModel implements ModelAdapter {
153
+ readonly name = "claude";
154
+ private readonly client;
155
+ private readonly defaultModel;
156
+ private readonly maxTokens;
157
+ private readonly maxTurns;
158
+ constructor(options: ClaudeModelOptions);
159
+ generate(request: ModelRequest): Promise<ModelResponse>;
160
+ }
161
+
162
+ /** A task that could not be completed. `code` ends up in the task's `error` (ADR-0020). */
163
+ declare class TaskFailure extends Error {
164
+ readonly code: string;
165
+ constructor(code: string, message: string);
166
+ }
167
+ /** The addressed agent is not running on this runtime, or nobody in the organization offers the capability. */
168
+ declare class AgentUnavailableError extends TaskFailure {
169
+ constructor(message: string);
170
+ }
171
+
172
+ type Handler = (task: TaskRequest) => Promise<TaskResult>;
173
+ /** Who should take a request: a specific agent, or any agent offering the capability (optionally not `except`). */
174
+ type Recipient = {
175
+ readonly agentId: string;
176
+ } | {
177
+ readonly capability: string;
178
+ readonly except?: string;
179
+ };
180
+ /**
181
+ * In-process request/reply between the running agents of each organization (ADR-0020). The Mesh Agent hands tasks
182
+ * to providers over it, and agents ask colleagues for help without going through the mesh.
183
+ */
184
+ declare class OrgBus {
185
+ private readonly organizations;
186
+ /** Opens an agent's mailbox. Returns a function that closes it. */
187
+ serve(organizationId: string, agentId: string, capabilities: readonly string[], handle: Handler): () => void;
188
+ /** Agents of the organization currently able to take `capability`, in a stable order. */
189
+ providers(organizationId: string, capability: string): string[];
190
+ request(organizationId: string, to: Recipient, task: TaskRequest): Promise<TaskResult>;
191
+ }
192
+
193
+ interface PipelineContext {
194
+ readonly agent: AgentSpec;
195
+ readonly task: TaskRequest;
196
+ readonly model: ModelAdapter;
197
+ /** The model id to ask for; null for the rule-based model. */
198
+ readonly modelId: string | null;
199
+ /** Why a different model than the agent's own was used, if one was. */
200
+ readonly modelNote?: string | undefined;
201
+ readonly tools: ToolRegistry;
202
+ readonly toolContext: ToolContext;
203
+ readonly memory: AgentMemory;
204
+ readonly clock: Clock;
205
+ }
206
+ /**
207
+ * observe → reason → act → verify (deck slide 05). Every stage leaves a step in the task's provenance.
208
+ * Tool calls happen while the model reasons; the act step records what they did.
209
+ */
210
+ declare function runPipeline(context: PipelineContext): Promise<TaskResult>;
211
+
212
+ /** What a rule sees: the task, and a way to call the agent's tools. */
213
+ interface RuleContext {
214
+ readonly capability: string;
215
+ readonly input: Readonly<Record<string, unknown>>;
216
+ callTool(name: string, input: unknown): Promise<unknown>;
217
+ }
218
+ /** Produces a task's output deterministically. */
219
+ type Rule = (context: RuleContext) => Record<string, unknown> | Promise<Record<string, unknown>>;
220
+ /**
221
+ * Deterministic "reasoning" from rules keyed by capability name (exact, then dotted prefix, then `*`). Used in tests
222
+ * and whenever an agent has no usable model, so the mesh works without network access or API keys.
223
+ */
224
+ declare class RuleBasedModel implements ModelAdapter {
225
+ private readonly rules;
226
+ readonly name = "rule-based";
227
+ constructor(rules?: Readonly<Record<string, Rule>>);
228
+ generate(request: ModelRequest): Promise<ModelResponse>;
229
+ private ruleFor;
230
+ }
231
+
232
+ /** How often a crashing agent is restarted before it is left in `error`. */
233
+ interface RestartPolicy {
234
+ readonly maxRestarts: number;
235
+ readonly windowMs: number;
236
+ readonly initialBackoffMs: number;
237
+ readonly maxBackoffMs: number;
238
+ }
239
+ declare const DEFAULT_RESTART_POLICY: RestartPolicy;
240
+ /** A started agent. Stopping it releases whatever it holds (mailbox, timers). */
241
+ interface AgentInstance {
242
+ stop(): Promise<void>;
243
+ }
244
+ /** Starts an instance. Throwing, or calling `crash` later, counts as a crash. */
245
+ type Launch = (agent: AgentSpec, crash: (reason: string) => void) => Promise<AgentInstance>;
246
+ /** Keeps agents running: starts them, restarts them after crashes with exponential backoff, and reports status. */
247
+ declare class Supervisor {
248
+ private readonly launch;
249
+ private readonly report;
250
+ private readonly policy;
251
+ private readonly now;
252
+ private readonly agents;
253
+ constructor(launch: Launch, report: (status: AgentStatusReport) => void, policy?: RestartPolicy, now?: () => number);
254
+ /** Starts the agent unless it is already running or starting. An agent left in `error` can be started again. */
255
+ start(agent: AgentSpec): void;
256
+ stop(agentId: string): Promise<void>;
257
+ isRunning(agentId: string): boolean;
258
+ /** Agents being supervised (running, starting or waiting to restart). */
259
+ supervised(): string[];
260
+ stopAll(): Promise<void>;
261
+ private attempt;
262
+ private crashed;
263
+ }
264
+
265
+ /** What an agent's custom behaviour can reach. */
266
+ interface BehaviourContext {
267
+ readonly agent: AgentSpec;
268
+ readonly memory: AgentMemory;
269
+ /** Reports a crash; the supervisor restarts the agent according to the restart policy. */
270
+ crash(reason: string): void;
271
+ }
272
+ /** Optional per-agent hooks; without them an agent handles tasks with the default pipeline. */
273
+ interface AgentBehaviour {
274
+ /** Runs when the agent starts. Throwing counts as a crash. */
275
+ start?(context: BehaviourContext): void | Promise<void>;
276
+ stop?(): void | Promise<void>;
277
+ /** Handles a task instead of the default observe → reason → act → verify pipeline. */
278
+ handle?(task: TaskRequest, context: BehaviourContext): Promise<TaskResult>;
279
+ }
280
+ interface AgentRuntimeOptions {
281
+ /** Used for agents whose `model` names a Claude model. Absent when no API key is configured. */
282
+ readonly claude?: ModelAdapter | undefined;
283
+ /** Used for every other agent, and for Claude agents when `claude` is absent. Default: rule-based. */
284
+ readonly fallback?: ModelAdapter | undefined;
285
+ readonly tools?: readonly Tool[] | undefined;
286
+ readonly memory?: MemoryStore | undefined;
287
+ readonly restartPolicy?: Partial<RestartPolicy> | undefined;
288
+ readonly behaviours?: ((agent: AgentSpec) => AgentBehaviour | undefined) | undefined;
289
+ readonly clock?: Clock | undefined;
290
+ }
291
+ /** How deep colleagues may ask each other for help within one task. */
292
+ declare const MAX_COLLABORATION_DEPTH = 3;
293
+ /**
294
+ * Runs a node's agents (ADR-0020): supervision, per-agent mailboxes on the org bus, model selection, tools and memory.
295
+ * The node server drives it through its `AgentRuntime` port and records the status reports as events.
296
+ */
297
+ declare class AgentRuntime {
298
+ private readonly options;
299
+ private readonly bus;
300
+ private readonly supervisor;
301
+ private readonly tools;
302
+ private readonly memory;
303
+ private readonly fallback;
304
+ private readonly clock;
305
+ private readonly specs;
306
+ private readonly listeners;
307
+ constructor(options?: AgentRuntimeOptions);
308
+ /** Subscribes to lifecycle reports. Returns an unsubscribe function. */
309
+ onStatus(listener: (report: AgentStatusReport) => void): () => void;
310
+ start(agent: AgentSpec): void;
311
+ /** Picks up a changed name, model or capability list; a running agent's mailbox is reopened. */
312
+ update(agent: AgentSpec): void;
313
+ stop(agentId: string): Promise<void>;
314
+ isRunning(agentId: string): boolean;
315
+ /** Hands a task to a running agent through its organization's bus, and waits for the result. */
316
+ execute(agentId: string, task: TaskRequest): Promise<TaskResult>;
317
+ /** Running agents of an organization offering `capability`. */
318
+ providers(organizationId: string, capability: string): string[];
319
+ stopAll(): Promise<void>;
320
+ /** Reopens the mailbox of each running agent with its current spec. */
321
+ private readonly mailboxes;
322
+ private launch;
323
+ private handle;
324
+ private selectModel;
325
+ private emit;
326
+ }
327
+
328
+ export { type AgentBehaviour, type AgentInstance, type AgentMemory, AgentRuntime, type AgentRuntimeOptions, type AgentSpec, type AgentStatusReport, AgentUnavailableError, type BehaviourContext, ClaudeModel, type ClaudeModelOptions, type Clock, DEFAULT_CLAUDE_MODEL, DEFAULT_RESTART_POLICY, InMemoryMemoryStore, MAX_COLLABORATION_DEPTH, type MemoryEntry, type MemoryStore, type MessagesClient, type ModelAdapter, type ModelRequest, type ModelResponse, OrgBus, type Recipient, type RestartPolicy, type Rule, RuleBasedModel, type RuleContext, Supervisor, TaskFailure, type TaskRequest, type TaskResult, type Tool, type ToolCall, type ToolContext, ToolRegistry, type ToolSpec, builtInTools, parseJsonObject, runPipeline };
package/index.js ADDED
@@ -0,0 +1,562 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { z } from 'zod';
3
+
4
+ // src/claude-model.ts
5
+
6
+ // src/model.ts
7
+ function parseJsonObject(text) {
8
+ const candidates = [text, /```(?:json)?\s*([\s\S]*?)```/.exec(text)?.[1], /\{[\s\S]*\}/.exec(text)?.[0]];
9
+ for (const candidate of candidates) {
10
+ if (!candidate) continue;
11
+ try {
12
+ const value = JSON.parse(candidate.trim());
13
+ if (value && typeof value === "object" && !Array.isArray(value)) return value;
14
+ } catch {
15
+ }
16
+ }
17
+ return null;
18
+ }
19
+
20
+ // src/claude-model.ts
21
+ var DEFAULT_CLAUDE_MODEL = "claude-opus-5-5";
22
+ var ClaudeModel = class {
23
+ name = "claude";
24
+ client;
25
+ defaultModel;
26
+ maxTokens;
27
+ maxTurns;
28
+ constructor(options) {
29
+ this.client = options.client ?? new Anthropic({ apiKey: options.apiKey });
30
+ this.defaultModel = options.defaultModel ?? DEFAULT_CLAUDE_MODEL;
31
+ this.maxTokens = options.maxTokens ?? 2048;
32
+ this.maxTurns = options.maxTurns ?? 6;
33
+ }
34
+ async generate(request) {
35
+ const model = request.model ?? this.defaultModel;
36
+ const tools = request.tools.map((tool) => ({
37
+ name: tool.name,
38
+ description: tool.description,
39
+ input_schema: tool.inputSchema
40
+ }));
41
+ const messages = [{ role: "user", content: request.prompt }];
42
+ const toolCalls = [];
43
+ for (let turn = 0; turn < this.maxTurns; turn++) {
44
+ const response = await this.client.messages.create({
45
+ model,
46
+ max_tokens: this.maxTokens,
47
+ system: request.system,
48
+ messages,
49
+ ...tools.length > 0 && { tools }
50
+ });
51
+ const uses = response.content.filter((block) => block.type === "tool_use");
52
+ if (response.stop_reason !== "tool_use" || uses.length === 0) {
53
+ const text = response.content.filter((block) => block.type === "text").map((block) => block.text).join("\n").trim();
54
+ return { text, output: parseJsonObject(text), toolCalls, model: response.model };
55
+ }
56
+ messages.push({ role: "assistant", content: response.content });
57
+ const results = [];
58
+ for (const use of uses) {
59
+ try {
60
+ const result = await request.runTool(use.name, use.input);
61
+ toolCalls.push({ name: use.name, input: use.input, result });
62
+ results.push({ type: "tool_result", tool_use_id: use.id, content: JSON.stringify(result ?? null) });
63
+ } catch (error) {
64
+ results.push({
65
+ type: "tool_result",
66
+ tool_use_id: use.id,
67
+ content: error instanceof Error ? error.message : String(error),
68
+ is_error: true
69
+ });
70
+ }
71
+ }
72
+ messages.push({ role: "user", content: results });
73
+ }
74
+ return { text: "", output: null, toolCalls, model };
75
+ }
76
+ };
77
+
78
+ // src/errors.ts
79
+ var TaskFailure = class extends Error {
80
+ constructor(code, message) {
81
+ super(message);
82
+ this.code = code;
83
+ this.name = "TaskFailure";
84
+ }
85
+ code;
86
+ };
87
+ var AgentUnavailableError = class extends TaskFailure {
88
+ constructor(message) {
89
+ super("agent-unavailable", message);
90
+ this.name = "AgentUnavailableError";
91
+ }
92
+ };
93
+
94
+ // src/memory.ts
95
+ var HISTORY_LIMIT = 50;
96
+ var InMemoryMemoryStore = class {
97
+ memories = /* @__PURE__ */ new Map();
98
+ forAgent(agentId) {
99
+ let memory = this.memories.get(agentId);
100
+ if (!memory) {
101
+ memory = createMemory();
102
+ this.memories.set(agentId, memory);
103
+ }
104
+ return memory;
105
+ }
106
+ drop(agentId) {
107
+ this.memories.delete(agentId);
108
+ }
109
+ };
110
+ function createMemory() {
111
+ const facts = /* @__PURE__ */ new Map();
112
+ const log = [];
113
+ return {
114
+ get: (key) => facts.get(key),
115
+ set: (key, value) => void facts.set(key, value),
116
+ delete: (key) => void facts.delete(key),
117
+ entries: () => facts,
118
+ remember: (entry) => {
119
+ log.push(entry);
120
+ if (log.length > HISTORY_LIMIT) log.splice(0, log.length - HISTORY_LIMIT);
121
+ },
122
+ history: () => log
123
+ };
124
+ }
125
+
126
+ // src/org-bus.ts
127
+ var OrgBus = class {
128
+ organizations = /* @__PURE__ */ new Map();
129
+ /** Opens an agent's mailbox. Returns a function that closes it. */
130
+ serve(organizationId, agentId, capabilities, handle) {
131
+ const mailboxes = this.organizations.get(organizationId) ?? /* @__PURE__ */ new Map();
132
+ this.organizations.set(organizationId, mailboxes);
133
+ const mailbox = { agentId, capabilities: new Set(capabilities), handle };
134
+ mailboxes.set(agentId, mailbox);
135
+ return () => {
136
+ if (mailboxes.get(agentId) === mailbox) mailboxes.delete(agentId);
137
+ if (mailboxes.size === 0) this.organizations.delete(organizationId);
138
+ };
139
+ }
140
+ /** Agents of the organization currently able to take `capability`, in a stable order. */
141
+ providers(organizationId, capability) {
142
+ return [...this.organizations.get(organizationId)?.values() ?? []].filter((m) => m.capabilities.has(capability)).map((m) => m.agentId).sort();
143
+ }
144
+ async request(organizationId, to, task) {
145
+ const mailboxes = this.organizations.get(organizationId);
146
+ const mailbox = "agentId" in to ? mailboxes?.get(to.agentId) : [...mailboxes?.values() ?? []].filter((m) => m.agentId !== to.except && m.capabilities.has(to.capability)).sort((a, b) => a.agentId.localeCompare(b.agentId))[0];
147
+ if (!mailbox) {
148
+ throw new AgentUnavailableError(
149
+ "agentId" in to ? `Agent ${to.agentId} is not running` : `No running agent of organization ${organizationId} offers ${to.capability}`
150
+ );
151
+ }
152
+ return mailbox.handle(task);
153
+ }
154
+ };
155
+
156
+ // src/pipeline.ts
157
+ var SUMMARY_LIMIT = 300;
158
+ var clip = (text) => text.length > SUMMARY_LIMIT ? `${text.slice(0, SUMMARY_LIMIT - 1)}\u2026` : text;
159
+ async function runPipeline(context) {
160
+ const { agent, task, memory, clock } = context;
161
+ const steps = [];
162
+ const step = (name, summary) => steps.push({ name, at: clock().toISOString(), summary: clip(summary) });
163
+ const keys = Object.keys(task.input).sort();
164
+ const priors = memory.history().filter((entry) => entry.capability === task.capability).length;
165
+ const from = !task.requester ? " from a colleague" : task.requester.organizationId === agent.organizationId ? " from an agent of its own organization" : task.requester.nodeId === agent.nodeId ? " from another organization on this node" : " from an organization on another node";
166
+ step(
167
+ "observe",
168
+ `${agent.name} received ${task.capability}${from} with ${keys.length > 0 ? `input ${keys.join(", ")}` : "no input"}; ${priors} earlier ${task.capability} task(s) in memory`
169
+ );
170
+ let response;
171
+ try {
172
+ response = await context.model.generate({
173
+ model: context.modelId,
174
+ system: systemPrompt(agent),
175
+ prompt: taskPrompt(task),
176
+ capability: task.capability,
177
+ input: task.input,
178
+ tools: context.tools.specs(),
179
+ runTool: (name, input) => context.tools.run(name, input, context.toolContext)
180
+ });
181
+ } catch (error) {
182
+ if (error instanceof TaskFailure) throw error;
183
+ throw new TaskFailure("model-error", error instanceof Error ? error.message : String(error));
184
+ }
185
+ const reasoner = response.model ?? "the rule-based model";
186
+ step("reason", `${reasoner} reasoned about the task${context.modelNote ? ` (${context.modelNote})` : ""}`);
187
+ step(
188
+ "act",
189
+ response.toolCalls.length > 0 ? `Used ${response.toolCalls.length} tool call(s): ${response.toolCalls.map((c) => c.name).join(", ")}` : "No tools needed"
190
+ );
191
+ const output = response.output;
192
+ if (!output || Object.keys(output).length === 0) {
193
+ step("verify", "The answer was not a non-empty JSON object");
194
+ throw new TaskFailure("invalid-output", `${agent.name} did not produce a JSON object for ${task.capability}`);
195
+ }
196
+ step("verify", `Output is a JSON object with ${Object.keys(output).length} field(s)`);
197
+ memory.remember({
198
+ taskId: task.id,
199
+ capability: task.capability,
200
+ summary: clip(JSON.stringify(output)),
201
+ at: clock().toISOString()
202
+ });
203
+ return { output, steps, model: response.model };
204
+ }
205
+ function systemPrompt(agent) {
206
+ const capabilities = agent.capabilities.map((c) => c.description ? `${c.name} (${c.description})` : c.name);
207
+ return [
208
+ `You are ${agent.name}, an autonomous agent in an AI mesh.`,
209
+ `Your capabilities: ${capabilities.join(", ") || "none"}.`,
210
+ "Other agents send you capability requests. Use your tools when they help;",
211
+ "`collaborate` asks a colleague in your organization for a capability you lack.",
212
+ "Answer with a single JSON object and nothing else."
213
+ ].join(" ");
214
+ }
215
+ function taskPrompt(task) {
216
+ return `Capability requested: ${task.capability}
217
+ Input (JSON):
218
+ ${JSON.stringify(task.input, null, 2)}`;
219
+ }
220
+
221
+ // src/rule-based-model.ts
222
+ var RuleBasedModel = class {
223
+ constructor(rules = {}) {
224
+ this.rules = rules;
225
+ }
226
+ rules;
227
+ name = "rule-based";
228
+ async generate(request) {
229
+ const toolCalls = [];
230
+ const rule = this.ruleFor(request.capability) ?? defaultRule;
231
+ const output = await rule({
232
+ capability: request.capability,
233
+ input: request.input,
234
+ callTool: async (name, input) => {
235
+ const result = await request.runTool(name, input);
236
+ toolCalls.push({ name, input, result });
237
+ return result;
238
+ }
239
+ });
240
+ return { text: JSON.stringify(output), output, toolCalls, model: null };
241
+ }
242
+ ruleFor(capability) {
243
+ const parts = capability.split(".");
244
+ for (let i = parts.length; i > 0; i--) {
245
+ const rule = this.rules[parts.slice(0, i).join(".")];
246
+ if (rule) return rule;
247
+ }
248
+ return this.rules["*"];
249
+ }
250
+ };
251
+ var defaultRule = ({ capability, input }) => ({
252
+ capability,
253
+ status: "handled",
254
+ summary: `Handled ${capability} with the rule-based model`,
255
+ inputKeys: Object.keys(input).sort()
256
+ });
257
+
258
+ // src/supervisor.ts
259
+ var DEFAULT_RESTART_POLICY = {
260
+ maxRestarts: 3,
261
+ windowMs: 6e4,
262
+ initialBackoffMs: 500,
263
+ maxBackoffMs: 1e4
264
+ };
265
+ var Supervisor = class {
266
+ constructor(launch, report, policy = DEFAULT_RESTART_POLICY, now = Date.now) {
267
+ this.launch = launch;
268
+ this.report = report;
269
+ this.policy = policy;
270
+ this.now = now;
271
+ }
272
+ launch;
273
+ report;
274
+ policy;
275
+ now;
276
+ agents = /* @__PURE__ */ new Map();
277
+ /** Starts the agent unless it is already running or starting. An agent left in `error` can be started again. */
278
+ start(agent) {
279
+ const current = this.agents.get(agent.id);
280
+ if (current && !current.failed) {
281
+ current.agent = agent;
282
+ return;
283
+ }
284
+ const supervised = {
285
+ agent,
286
+ instance: void 0,
287
+ generation: (current?.generation ?? 0) + 1,
288
+ crashes: [],
289
+ timer: void 0,
290
+ failed: false
291
+ };
292
+ this.agents.set(agent.id, supervised);
293
+ void this.attempt(supervised, 1);
294
+ }
295
+ async stop(agentId) {
296
+ const supervised = this.agents.get(agentId);
297
+ if (!supervised) return;
298
+ this.agents.delete(agentId);
299
+ supervised.generation += 1;
300
+ clearTimeout(supervised.timer);
301
+ const instance = supervised.instance;
302
+ supervised.instance = void 0;
303
+ await instance?.stop().catch(() => {
304
+ });
305
+ this.report({ agentId, status: "stopped" });
306
+ }
307
+ isRunning(agentId) {
308
+ return this.agents.get(agentId)?.instance !== void 0;
309
+ }
310
+ /** Agents being supervised (running, starting or waiting to restart). */
311
+ supervised() {
312
+ return [...this.agents.entries()].filter(([, s]) => !s.failed).map(([id]) => id);
313
+ }
314
+ async stopAll() {
315
+ await Promise.all([...this.agents.keys()].map((id) => this.stop(id)));
316
+ }
317
+ async attempt(supervised, attempt) {
318
+ const generation = supervised.generation;
319
+ const { id } = supervised.agent;
320
+ this.report({ agentId: id, status: "starting", attempt });
321
+ let instance;
322
+ try {
323
+ instance = await this.launch(supervised.agent, (reason) => {
324
+ if (supervised.generation === generation && supervised.instance === instance) {
325
+ supervised.instance = void 0;
326
+ void instance.stop().catch(() => {
327
+ });
328
+ this.crashed(supervised, reason);
329
+ }
330
+ });
331
+ } catch (error) {
332
+ if (supervised.generation === generation) this.crashed(supervised, reasonOf(error));
333
+ return;
334
+ }
335
+ if (supervised.generation !== generation) {
336
+ await instance.stop().catch(() => {
337
+ });
338
+ return;
339
+ }
340
+ supervised.instance = instance;
341
+ this.report({ agentId: id, status: "running" });
342
+ }
343
+ crashed(supervised, reason) {
344
+ const now = this.now();
345
+ supervised.crashes = [...supervised.crashes.filter((t) => now - t < this.policy.windowMs), now];
346
+ const restarts = supervised.crashes.length - 1;
347
+ if (restarts >= this.policy.maxRestarts) {
348
+ supervised.failed = true;
349
+ this.report({
350
+ agentId: supervised.agent.id,
351
+ status: "error",
352
+ reason: `${reason} (gave up after ${restarts} restart${restarts === 1 ? "" : "s"})`
353
+ });
354
+ return;
355
+ }
356
+ this.report({ agentId: supervised.agent.id, status: "error", reason });
357
+ const backoff = Math.min(this.policy.initialBackoffMs * 2 ** restarts, this.policy.maxBackoffMs);
358
+ const generation = supervised.generation;
359
+ supervised.timer = setTimeout(() => {
360
+ if (supervised.generation === generation) void this.attempt(supervised, restarts + 2);
361
+ }, backoff);
362
+ }
363
+ };
364
+ var reasonOf = (error) => error instanceof Error ? error.message : String(error);
365
+ var TOOL_NAME = /^[a-zA-Z0-9_-]{1,64}$/;
366
+ var ToolRegistry = class {
367
+ tools = /* @__PURE__ */ new Map();
368
+ register(tool) {
369
+ if (!TOOL_NAME.test(tool.name)) throw new Error(`Invalid tool name: ${tool.name}`);
370
+ if (this.tools.has(tool.name)) throw new Error(`Tool already registered: ${tool.name}`);
371
+ this.tools.set(tool.name, tool);
372
+ return this;
373
+ }
374
+ has(name) {
375
+ return this.tools.has(name);
376
+ }
377
+ specs() {
378
+ return [...this.tools.values()].map((tool) => {
379
+ const { $schema: _schema, ...schema } = z.toJSONSchema(tool.input);
380
+ return { name: tool.name, description: tool.description, inputSchema: { ...schema, type: "object" } };
381
+ });
382
+ }
383
+ async run(name, input, context) {
384
+ const tool = this.tools.get(name);
385
+ if (!tool) throw new TaskFailure("unknown-tool", `No tool named ${name}`);
386
+ const parsed = tool.input.safeParse(input);
387
+ if (!parsed.success) throw new TaskFailure("invalid-tool-input", `${name}: ${parsed.error.message}`);
388
+ return tool.run(parsed.data, context);
389
+ }
390
+ };
391
+ function builtInTools() {
392
+ return new ToolRegistry().register({
393
+ name: "collaborate",
394
+ description: "Ask another agent of your own organization to perform a capability, and get its output.",
395
+ input: z.object({ capability: z.string(), input: z.record(z.string(), z.unknown()).default({}) }),
396
+ run: ({ capability, input }, context) => context.collaborate(capability, input)
397
+ }).register({
398
+ name: "remember",
399
+ description: "Store a fact in your memory for later tasks.",
400
+ input: z.object({ key: z.string().max(100), value: z.unknown() }),
401
+ run: ({ key, value }, context) => {
402
+ context.memory.set(key, value);
403
+ return { stored: key };
404
+ }
405
+ }).register({
406
+ name: "recall",
407
+ description: "Read a fact from your memory.",
408
+ input: z.object({ key: z.string().max(100) }),
409
+ run: ({ key }, context) => ({ key, value: context.memory.get(key) ?? null })
410
+ });
411
+ }
412
+
413
+ // src/runtime.ts
414
+ var MAX_COLLABORATION_DEPTH = 3;
415
+ var AgentRuntime = class {
416
+ constructor(options = {}) {
417
+ this.options = options;
418
+ this.tools = builtInTools();
419
+ for (const tool of options.tools ?? []) this.tools.register(tool);
420
+ this.memory = options.memory ?? new InMemoryMemoryStore();
421
+ this.fallback = options.fallback ?? new RuleBasedModel();
422
+ this.clock = options.clock ?? (() => /* @__PURE__ */ new Date());
423
+ this.supervisor = new Supervisor(
424
+ (agent, crash) => this.launch(agent, crash),
425
+ (report) => this.emit(report),
426
+ { ...DEFAULT_RESTART_POLICY, ...options.restartPolicy }
427
+ );
428
+ }
429
+ options;
430
+ bus = new OrgBus();
431
+ supervisor;
432
+ tools;
433
+ memory;
434
+ fallback;
435
+ clock;
436
+ specs = /* @__PURE__ */ new Map();
437
+ listeners = /* @__PURE__ */ new Set();
438
+ /** Subscribes to lifecycle reports. Returns an unsubscribe function. */
439
+ onStatus(listener) {
440
+ this.listeners.add(listener);
441
+ return () => this.listeners.delete(listener);
442
+ }
443
+ start(agent) {
444
+ this.specs.set(agent.id, agent);
445
+ this.supervisor.start(agent);
446
+ }
447
+ /** Picks up a changed name, model or capability list; a running agent's mailbox is reopened. */
448
+ update(agent) {
449
+ if (!this.specs.has(agent.id)) return;
450
+ this.specs.set(agent.id, agent);
451
+ const reopen = this.mailboxes.get(agent.id);
452
+ if (reopen) reopen(agent);
453
+ }
454
+ async stop(agentId) {
455
+ await this.supervisor.stop(agentId);
456
+ this.specs.delete(agentId);
457
+ }
458
+ isRunning(agentId) {
459
+ return this.supervisor.isRunning(agentId);
460
+ }
461
+ /** Hands a task to a running agent through its organization's bus, and waits for the result. */
462
+ async execute(agentId, task) {
463
+ const agent = this.specs.get(agentId);
464
+ if (!agent) throw new AgentUnavailableError(`Agent ${agentId} is not running on this node`);
465
+ return this.bus.request(agent.organizationId, { agentId }, task);
466
+ }
467
+ /** Running agents of an organization offering `capability`. */
468
+ providers(organizationId, capability) {
469
+ return this.bus.providers(organizationId, capability);
470
+ }
471
+ async stopAll() {
472
+ await this.supervisor.stopAll();
473
+ this.specs.clear();
474
+ }
475
+ /** Reopens the mailbox of each running agent with its current spec. */
476
+ mailboxes = /* @__PURE__ */ new Map();
477
+ async launch(agent, crash) {
478
+ const memory = this.memory.forAgent(agent.id);
479
+ const behaviour = this.options.behaviours?.(agent);
480
+ const context = { agent, memory, crash };
481
+ await behaviour?.start?.(context);
482
+ let close = () => {
483
+ };
484
+ const open = (spec) => {
485
+ close();
486
+ close = this.bus.serve(
487
+ spec.organizationId,
488
+ spec.id,
489
+ spec.capabilities.map((c) => c.name),
490
+ (task) => this.handle(spec.id, task, behaviour, context)
491
+ );
492
+ };
493
+ open(agent);
494
+ this.mailboxes.set(agent.id, open);
495
+ return {
496
+ stop: async () => {
497
+ close();
498
+ this.mailboxes.delete(agent.id);
499
+ await behaviour?.stop?.();
500
+ }
501
+ };
502
+ }
503
+ async handle(agentId, task, behaviour, context) {
504
+ const agent = this.specs.get(agentId) ?? context.agent;
505
+ if (behaviour?.handle) return behaviour.handle(task, { ...context, agent });
506
+ const memory = this.memory.forAgent(agent.id);
507
+ const { adapter, modelId, note } = this.selectModel(agent);
508
+ let collaborations = 0;
509
+ const toolContext = {
510
+ agent,
511
+ memory,
512
+ collaborate: async (capability, input) => {
513
+ const depth = (task.depth ?? 0) + 1;
514
+ if (depth > MAX_COLLABORATION_DEPTH) {
515
+ throw new TaskFailure("collaboration-too-deep", `Collaboration deeper than ${MAX_COLLABORATION_DEPTH}`);
516
+ }
517
+ const request = {
518
+ id: `${task.id}.c${++collaborations}`,
519
+ capability,
520
+ input,
521
+ depth
522
+ };
523
+ const result = await this.bus.request(agent.organizationId, { capability, except: agent.id }, request);
524
+ return result.output;
525
+ }
526
+ };
527
+ return runPipeline({
528
+ agent,
529
+ task,
530
+ model: adapter,
531
+ modelId,
532
+ modelNote: note,
533
+ tools: this.tools,
534
+ toolContext,
535
+ memory,
536
+ clock: this.clock
537
+ });
538
+ }
539
+ selectModel(agent) {
540
+ if (!agent.model) return { adapter: this.fallback, modelId: null };
541
+ if (/^claude/i.test(agent.model)) {
542
+ if (this.options.claude) return { adapter: this.options.claude, modelId: agent.model };
543
+ return {
544
+ adapter: this.fallback,
545
+ modelId: null,
546
+ note: `${agent.model} is not configured on this node (no ANTHROPIC_API_KEY), so the rule-based model answered`
547
+ };
548
+ }
549
+ return {
550
+ adapter: this.fallback,
551
+ modelId: null,
552
+ note: `no adapter for ${agent.model}, so the rule-based model answered`
553
+ };
554
+ }
555
+ emit(report) {
556
+ for (const listener of this.listeners) listener(report);
557
+ }
558
+ };
559
+
560
+ export { AgentRuntime, AgentUnavailableError, ClaudeModel, DEFAULT_CLAUDE_MODEL, DEFAULT_RESTART_POLICY, InMemoryMemoryStore, MAX_COLLABORATION_DEPTH, OrgBus, RuleBasedModel, Supervisor, TaskFailure, ToolRegistry, builtInTools, parseJsonObject, runPipeline };
561
+ //# sourceMappingURL=index.js.map
562
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/model.ts","../src/claude-model.ts","../src/errors.ts","../src/memory.ts","../src/org-bus.ts","../src/pipeline.ts","../src/rule-based-model.ts","../src/supervisor.ts","../src/tools.ts","../src/runtime.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ToolSpec } from \"./tools.ts\";\n\n/** A tool call the model made while reasoning, with what the tool returned. */\nexport interface ToolCall {\n readonly name: string;\n readonly input: unknown;\n readonly result: unknown;\n}\n\nexport interface ModelRequest {\n /** Model id (e.g. `claude-opus-5-5`), or null for the rule-based model. */\n readonly model: string | null;\n readonly system: string;\n readonly prompt: string;\n /** The task itself, for models that work on structure rather than text. */\n readonly capability: string;\n readonly input: Readonly<Record<string, unknown>>;\n readonly tools: readonly ToolSpec[];\n /** Runs a tool on the agent's behalf; the adapter owns the tool-use loop. */\n runTool(name: string, input: unknown): Promise<unknown>;\n}\n\nexport interface ModelResponse {\n /** The model's final answer, as text. */\n readonly text: string;\n /** The answer parsed as a JSON object, when it is one. */\n readonly output: Record<string, unknown> | null;\n readonly toolCalls: readonly ToolCall[];\n /** The model that answered; null for the rule-based model. */\n readonly model: string | null;\n}\n\n/** Port for anything that can reason about a task: a rule set, Claude, or another provider. */\nexport interface ModelAdapter {\n readonly name: string;\n generate(request: ModelRequest): Promise<ModelResponse>;\n}\n\n/** Extracts a JSON object from a model answer: the whole text, or the first fenced or braced block. */\nexport function parseJsonObject(text: string): Record<string, unknown> | null {\n const candidates = [text, /```(?:json)?\\s*([\\s\\S]*?)```/.exec(text)?.[1], /\\{[\\s\\S]*\\}/.exec(text)?.[0]];\n for (const candidate of candidates) {\n if (!candidate) continue;\n try {\n const value: unknown = JSON.parse(candidate.trim());\n if (value && typeof value === \"object\" && !Array.isArray(value)) return value as Record<string, unknown>;\n } catch {\n // not JSON: try the next candidate\n }\n }\n return null;\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport { type ModelAdapter, type ModelRequest, type ModelResponse, parseJsonObject, type ToolCall } from \"./model.ts\";\n\n/** The part of the Anthropic client this adapter uses, so tests can substitute a fake. */\nexport interface MessagesClient {\n messages: {\n create(params: Anthropic.MessageCreateParamsNonStreaming): Promise<Anthropic.Message>;\n };\n}\n\nexport interface ClaudeModelOptions {\n readonly apiKey?: string | undefined;\n readonly client?: MessagesClient | undefined;\n /** Used when an agent names no model. */\n readonly defaultModel?: string | undefined;\n readonly maxTokens?: number | undefined;\n /** Model turns per task, tool calls included. */\n readonly maxTurns?: number | undefined;\n}\n\nexport const DEFAULT_CLAUDE_MODEL = \"claude-opus-5-5\";\n\n/** Claude through the Anthropic Messages API, with tool use (ADR-0020). */\nexport class ClaudeModel implements ModelAdapter {\n readonly name = \"claude\";\n private readonly client: MessagesClient;\n private readonly defaultModel: string;\n private readonly maxTokens: number;\n private readonly maxTurns: number;\n\n constructor(options: ClaudeModelOptions) {\n this.client = options.client ?? new Anthropic({ apiKey: options.apiKey });\n this.defaultModel = options.defaultModel ?? DEFAULT_CLAUDE_MODEL;\n this.maxTokens = options.maxTokens ?? 2048;\n this.maxTurns = options.maxTurns ?? 6;\n }\n\n async generate(request: ModelRequest): Promise<ModelResponse> {\n const model = request.model ?? this.defaultModel;\n const tools: Anthropic.Tool[] = request.tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema,\n }));\n const messages: Anthropic.MessageParam[] = [{ role: \"user\", content: request.prompt }];\n const toolCalls: ToolCall[] = [];\n\n for (let turn = 0; turn < this.maxTurns; turn++) {\n const response = await this.client.messages.create({\n model,\n max_tokens: this.maxTokens,\n system: request.system,\n messages,\n ...(tools.length > 0 && { tools }),\n });\n const uses = response.content.filter((block): block is Anthropic.ToolUseBlock => block.type === \"tool_use\");\n if (response.stop_reason !== \"tool_use\" || uses.length === 0) {\n const text = response.content\n .filter((block): block is Anthropic.TextBlock => block.type === \"text\")\n .map((block) => block.text)\n .join(\"\\n\")\n .trim();\n return { text, output: parseJsonObject(text), toolCalls, model: response.model };\n }\n\n messages.push({ role: \"assistant\", content: response.content });\n const results: Anthropic.ToolResultBlockParam[] = [];\n for (const use of uses) {\n try {\n const result = await request.runTool(use.name, use.input);\n toolCalls.push({ name: use.name, input: use.input, result });\n results.push({ type: \"tool_result\", tool_use_id: use.id, content: JSON.stringify(result ?? null) });\n } catch (error) {\n results.push({\n type: \"tool_result\",\n tool_use_id: use.id,\n content: error instanceof Error ? error.message : String(error),\n is_error: true,\n });\n }\n }\n messages.push({ role: \"user\", content: results });\n }\n return { text: \"\", output: null, toolCalls, model };\n }\n}\n","/** A task that could not be completed. `code` ends up in the task's `error` (ADR-0020). */\nexport class TaskFailure extends Error {\n constructor(\n readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"TaskFailure\";\n }\n}\n\n/** The addressed agent is not running on this runtime, or nobody in the organization offers the capability. */\nexport class AgentUnavailableError extends TaskFailure {\n constructor(message: string) {\n super(\"agent-unavailable\", message);\n this.name = \"AgentUnavailableError\";\n }\n}\n","/** A handled task, as an agent remembers it. */\nexport interface MemoryEntry {\n readonly taskId: string;\n readonly capability: string;\n readonly summary: string;\n readonly at: string;\n}\n\n/** Memory scoped to one agent: facts it keeps plus a capped history of the tasks it handled. */\nexport interface AgentMemory {\n get(key: string): unknown;\n set(key: string, value: unknown): void;\n delete(key: string): void;\n entries(): ReadonlyMap<string, unknown>;\n remember(entry: MemoryEntry): void;\n history(): readonly MemoryEntry[];\n}\n\n/** Where agents' memories live. In-memory for now; a persistent store can implement the same port. */\nexport interface MemoryStore {\n forAgent(agentId: string): AgentMemory;\n drop(agentId: string): void;\n}\n\nexport const HISTORY_LIMIT = 50;\n\nexport class InMemoryMemoryStore implements MemoryStore {\n private readonly memories = new Map<string, AgentMemory>();\n\n forAgent(agentId: string): AgentMemory {\n let memory = this.memories.get(agentId);\n if (!memory) {\n memory = createMemory();\n this.memories.set(agentId, memory);\n }\n return memory;\n }\n\n drop(agentId: string): void {\n this.memories.delete(agentId);\n }\n}\n\nfunction createMemory(): AgentMemory {\n const facts = new Map<string, unknown>();\n const log: MemoryEntry[] = [];\n return {\n get: (key) => facts.get(key),\n set: (key, value) => void facts.set(key, value),\n delete: (key) => void facts.delete(key),\n entries: () => facts,\n remember: (entry) => {\n log.push(entry);\n if (log.length > HISTORY_LIMIT) log.splice(0, log.length - HISTORY_LIMIT);\n },\n history: () => log,\n };\n}\n","import { AgentUnavailableError } from \"./errors.ts\";\nimport type { TaskRequest, TaskResult } from \"./types.ts\";\n\ntype Handler = (task: TaskRequest) => Promise<TaskResult>;\n\ninterface Mailbox {\n readonly agentId: string;\n readonly capabilities: ReadonlySet<string>;\n readonly handle: Handler;\n}\n\n/** Who should take a request: a specific agent, or any agent offering the capability (optionally not `except`). */\nexport type Recipient = { readonly agentId: string } | { readonly capability: string; readonly except?: string };\n\n/**\n * In-process request/reply between the running agents of each organization (ADR-0020). The Mesh Agent hands tasks\n * to providers over it, and agents ask colleagues for help without going through the mesh.\n */\nexport class OrgBus {\n private readonly organizations = new Map<string, Map<string, Mailbox>>();\n\n /** Opens an agent's mailbox. Returns a function that closes it. */\n serve(organizationId: string, agentId: string, capabilities: readonly string[], handle: Handler): () => void {\n const mailboxes = this.organizations.get(organizationId) ?? new Map<string, Mailbox>();\n this.organizations.set(organizationId, mailboxes);\n const mailbox = { agentId, capabilities: new Set(capabilities), handle };\n mailboxes.set(agentId, mailbox);\n return () => {\n if (mailboxes.get(agentId) === mailbox) mailboxes.delete(agentId);\n if (mailboxes.size === 0) this.organizations.delete(organizationId);\n };\n }\n\n /** Agents of the organization currently able to take `capability`, in a stable order. */\n providers(organizationId: string, capability: string): string[] {\n return [...(this.organizations.get(organizationId)?.values() ?? [])]\n .filter((m) => m.capabilities.has(capability))\n .map((m) => m.agentId)\n .sort();\n }\n\n async request(organizationId: string, to: Recipient, task: TaskRequest): Promise<TaskResult> {\n const mailboxes = this.organizations.get(organizationId);\n const mailbox =\n \"agentId\" in to\n ? mailboxes?.get(to.agentId)\n : [...(mailboxes?.values() ?? [])]\n .filter((m) => m.agentId !== to.except && m.capabilities.has(to.capability))\n .sort((a, b) => a.agentId.localeCompare(b.agentId))[0];\n if (!mailbox) {\n throw new AgentUnavailableError(\n \"agentId\" in to\n ? `Agent ${to.agentId} is not running`\n : `No running agent of organization ${organizationId} offers ${to.capability}`,\n );\n }\n return mailbox.handle(task);\n }\n}\n","import type { TaskStep } from \"@casimesh/contracts\";\nimport { TaskFailure } from \"./errors.ts\";\nimport type { AgentMemory } from \"./memory.ts\";\nimport type { ModelAdapter, ModelResponse } from \"./model.ts\";\nimport type { ToolContext, ToolRegistry } from \"./tools.ts\";\nimport type { AgentSpec, Clock, TaskRequest, TaskResult } from \"./types.ts\";\n\nexport interface PipelineContext {\n readonly agent: AgentSpec;\n readonly task: TaskRequest;\n readonly model: ModelAdapter;\n /** The model id to ask for; null for the rule-based model. */\n readonly modelId: string | null;\n /** Why a different model than the agent's own was used, if one was. */\n readonly modelNote?: string | undefined;\n readonly tools: ToolRegistry;\n readonly toolContext: ToolContext;\n readonly memory: AgentMemory;\n readonly clock: Clock;\n}\n\nconst SUMMARY_LIMIT = 300;\nconst clip = (text: string) => (text.length > SUMMARY_LIMIT ? `${text.slice(0, SUMMARY_LIMIT - 1)}…` : text);\n\n/**\n * observe → reason → act → verify (deck slide 05). Every stage leaves a step in the task's provenance.\n * Tool calls happen while the model reasons; the act step records what they did.\n */\nexport async function runPipeline(context: PipelineContext): Promise<TaskResult> {\n const { agent, task, memory, clock } = context;\n const steps: TaskStep[] = [];\n const step = (name: TaskStep[\"name\"], summary: string) =>\n steps.push({ name, at: clock().toISOString(), summary: clip(summary) });\n\n // observe\n const keys = Object.keys(task.input).sort();\n const priors = memory.history().filter((entry) => entry.capability === task.capability).length;\n const from = !task.requester\n ? \" from a colleague\"\n : task.requester.organizationId === agent.organizationId\n ? \" from an agent of its own organization\"\n : task.requester.nodeId === agent.nodeId\n ? \" from another organization on this node\"\n : \" from an organization on another node\";\n step(\n \"observe\",\n `${agent.name} received ${task.capability}${from}` +\n ` with ${keys.length > 0 ? `input ${keys.join(\", \")}` : \"no input\"}; ${priors} earlier ${task.capability} task(s) in memory`,\n );\n\n // reason (+ tool use)\n let response: ModelResponse;\n try {\n response = await context.model.generate({\n model: context.modelId,\n system: systemPrompt(agent),\n prompt: taskPrompt(task),\n capability: task.capability,\n input: task.input,\n tools: context.tools.specs(),\n runTool: (name, input) => context.tools.run(name, input, context.toolContext),\n });\n } catch (error) {\n if (error instanceof TaskFailure) throw error;\n throw new TaskFailure(\"model-error\", error instanceof Error ? error.message : String(error));\n }\n const reasoner = response.model ?? \"the rule-based model\";\n step(\"reason\", `${reasoner} reasoned about the task${context.modelNote ? ` (${context.modelNote})` : \"\"}`);\n\n // act\n step(\n \"act\",\n response.toolCalls.length > 0\n ? `Used ${response.toolCalls.length} tool call(s): ${response.toolCalls.map((c) => c.name).join(\", \")}`\n : \"No tools needed\",\n );\n\n // verify\n const output = response.output;\n if (!output || Object.keys(output).length === 0) {\n step(\"verify\", \"The answer was not a non-empty JSON object\");\n throw new TaskFailure(\"invalid-output\", `${agent.name} did not produce a JSON object for ${task.capability}`);\n }\n step(\"verify\", `Output is a JSON object with ${Object.keys(output).length} field(s)`);\n\n memory.remember({\n taskId: task.id,\n capability: task.capability,\n summary: clip(JSON.stringify(output)),\n at: clock().toISOString(),\n });\n return { output, steps, model: response.model };\n}\n\nfunction systemPrompt(agent: AgentSpec): string {\n const capabilities = agent.capabilities.map((c) => (c.description ? `${c.name} (${c.description})` : c.name));\n return [\n `You are ${agent.name}, an autonomous agent in an AI mesh.`,\n `Your capabilities: ${capabilities.join(\", \") || \"none\"}.`,\n \"Other agents send you capability requests. Use your tools when they help;\",\n \"`collaborate` asks a colleague in your organization for a capability you lack.\",\n \"Answer with a single JSON object and nothing else.\",\n ].join(\" \");\n}\n\nfunction taskPrompt(task: TaskRequest): string {\n return `Capability requested: ${task.capability}\\nInput (JSON):\\n${JSON.stringify(task.input, null, 2)}`;\n}\n","import type { ModelAdapter, ModelRequest, ModelResponse, ToolCall } from \"./model.ts\";\n\n/** What a rule sees: the task, and a way to call the agent's tools. */\nexport interface RuleContext {\n readonly capability: string;\n readonly input: Readonly<Record<string, unknown>>;\n callTool(name: string, input: unknown): Promise<unknown>;\n}\n\n/** Produces a task's output deterministically. */\nexport type Rule = (context: RuleContext) => Record<string, unknown> | Promise<Record<string, unknown>>;\n\n/**\n * Deterministic \"reasoning\" from rules keyed by capability name (exact, then dotted prefix, then `*`). Used in tests\n * and whenever an agent has no usable model, so the mesh works without network access or API keys.\n */\nexport class RuleBasedModel implements ModelAdapter {\n readonly name = \"rule-based\";\n\n constructor(private readonly rules: Readonly<Record<string, Rule>> = {}) {}\n\n async generate(request: ModelRequest): Promise<ModelResponse> {\n const toolCalls: ToolCall[] = [];\n const rule = this.ruleFor(request.capability) ?? defaultRule;\n const output = await rule({\n capability: request.capability,\n input: request.input,\n callTool: async (name, input) => {\n const result = await request.runTool(name, input);\n toolCalls.push({ name, input, result });\n return result;\n },\n });\n return { text: JSON.stringify(output), output, toolCalls, model: null };\n }\n\n private ruleFor(capability: string): Rule | undefined {\n const parts = capability.split(\".\");\n for (let i = parts.length; i > 0; i--) {\n const rule = this.rules[parts.slice(0, i).join(\".\")];\n if (rule) return rule;\n }\n return this.rules[\"*\"];\n }\n}\n\n/** Without a specific rule, report what was handled; enough to trace a delegation end to end. */\nconst defaultRule: Rule = ({ capability, input }) => ({\n capability,\n status: \"handled\",\n summary: `Handled ${capability} with the rule-based model`,\n inputKeys: Object.keys(input).sort(),\n});\n","import type { AgentSpec, AgentStatusReport } from \"./types.ts\";\n\n/** How often a crashing agent is restarted before it is left in `error`. */\nexport interface RestartPolicy {\n readonly maxRestarts: number;\n readonly windowMs: number;\n readonly initialBackoffMs: number;\n readonly maxBackoffMs: number;\n}\n\nexport const DEFAULT_RESTART_POLICY: RestartPolicy = {\n maxRestarts: 3,\n windowMs: 60_000,\n initialBackoffMs: 500,\n maxBackoffMs: 10_000,\n};\n\n/** A started agent. Stopping it releases whatever it holds (mailbox, timers). */\nexport interface AgentInstance {\n stop(): Promise<void>;\n}\n\n/** Starts an instance. Throwing, or calling `crash` later, counts as a crash. */\nexport type Launch = (agent: AgentSpec, crash: (reason: string) => void) => Promise<AgentInstance>;\n\ninterface Supervised {\n agent: AgentSpec;\n instance: AgentInstance | undefined;\n /** Bumped on every start and stop, so late results of an abandoned launch are discarded. */\n generation: number;\n crashes: number[];\n timer: ReturnType<typeof setTimeout> | undefined;\n failed: boolean;\n}\n\n/** Keeps agents running: starts them, restarts them after crashes with exponential backoff, and reports status. */\nexport class Supervisor {\n private readonly agents = new Map<string, Supervised>();\n\n constructor(\n private readonly launch: Launch,\n private readonly report: (status: AgentStatusReport) => void,\n private readonly policy: RestartPolicy = DEFAULT_RESTART_POLICY,\n private readonly now: () => number = Date.now,\n ) {}\n\n /** Starts the agent unless it is already running or starting. An agent left in `error` can be started again. */\n start(agent: AgentSpec): void {\n const current = this.agents.get(agent.id);\n if (current && !current.failed) {\n current.agent = agent;\n return;\n }\n const supervised: Supervised = {\n agent,\n instance: undefined,\n generation: (current?.generation ?? 0) + 1,\n crashes: [],\n timer: undefined,\n failed: false,\n };\n this.agents.set(agent.id, supervised);\n void this.attempt(supervised, 1);\n }\n\n async stop(agentId: string): Promise<void> {\n const supervised = this.agents.get(agentId);\n if (!supervised) return;\n this.agents.delete(agentId);\n supervised.generation += 1;\n clearTimeout(supervised.timer);\n const instance = supervised.instance;\n supervised.instance = undefined;\n await instance?.stop().catch(() => {});\n this.report({ agentId, status: \"stopped\" });\n }\n\n isRunning(agentId: string): boolean {\n return this.agents.get(agentId)?.instance !== undefined;\n }\n\n /** Agents being supervised (running, starting or waiting to restart). */\n supervised(): string[] {\n return [...this.agents.entries()].filter(([, s]) => !s.failed).map(([id]) => id);\n }\n\n async stopAll(): Promise<void> {\n await Promise.all([...this.agents.keys()].map((id) => this.stop(id)));\n }\n\n private async attempt(supervised: Supervised, attempt: number): Promise<void> {\n const generation = supervised.generation;\n const { id } = supervised.agent;\n this.report({ agentId: id, status: \"starting\", attempt });\n let instance: AgentInstance;\n try {\n instance = await this.launch(supervised.agent, (reason) => {\n if (supervised.generation === generation && supervised.instance === instance) {\n supervised.instance = undefined;\n void instance.stop().catch(() => {});\n this.crashed(supervised, reason);\n }\n });\n } catch (error) {\n if (supervised.generation === generation) this.crashed(supervised, reasonOf(error));\n return;\n }\n if (supervised.generation !== generation) {\n await instance.stop().catch(() => {});\n return;\n }\n supervised.instance = instance;\n this.report({ agentId: id, status: \"running\" });\n }\n\n private crashed(supervised: Supervised, reason: string): void {\n const now = this.now();\n supervised.crashes = [...supervised.crashes.filter((t) => now - t < this.policy.windowMs), now];\n const restarts = supervised.crashes.length - 1;\n if (restarts >= this.policy.maxRestarts) {\n supervised.failed = true;\n this.report({\n agentId: supervised.agent.id,\n status: \"error\",\n reason: `${reason} (gave up after ${restarts} restart${restarts === 1 ? \"\" : \"s\"})`,\n });\n return;\n }\n this.report({ agentId: supervised.agent.id, status: \"error\", reason });\n const backoff = Math.min(this.policy.initialBackoffMs * 2 ** restarts, this.policy.maxBackoffMs);\n const generation = supervised.generation;\n supervised.timer = setTimeout(() => {\n if (supervised.generation === generation) void this.attempt(supervised, restarts + 2);\n }, backoff);\n }\n}\n\nconst reasonOf = (error: unknown) => (error instanceof Error ? error.message : String(error));\n","import { z } from \"zod\";\nimport { TaskFailure } from \"./errors.ts\";\nimport type { AgentMemory } from \"./memory.ts\";\nimport type { AgentSpec } from \"./types.ts\";\n\n/** What a tool can reach while it runs on behalf of an agent. */\nexport interface ToolContext {\n readonly agent: AgentSpec;\n readonly memory: AgentMemory;\n /** Asks a colleague in the same organization for a capability over the org bus (internal collaboration). */\n collaborate(capability: string, input: Record<string, unknown>): Promise<Record<string, unknown>>;\n}\n\nexport interface Tool<I = unknown> {\n /** `^[a-zA-Z0-9_-]{1,64}$`, as model APIs require. */\n readonly name: string;\n readonly description: string;\n readonly input: z.ZodType<I>;\n run(input: I, context: ToolContext): unknown | Promise<unknown>;\n}\n\n/** A tool as a model sees it: name, description and a JSON Schema for its input. */\nexport interface ToolSpec {\n readonly name: string;\n readonly description: string;\n readonly inputSchema: Record<string, unknown> & { type: \"object\" };\n}\n\nconst TOOL_NAME = /^[a-zA-Z0-9_-]{1,64}$/;\n\n/** Named tools with validated input, shared by every agent of a runtime. */\nexport class ToolRegistry {\n private readonly tools = new Map<string, Tool>();\n\n register<I>(tool: Tool<I>): this {\n if (!TOOL_NAME.test(tool.name)) throw new Error(`Invalid tool name: ${tool.name}`);\n if (this.tools.has(tool.name)) throw new Error(`Tool already registered: ${tool.name}`);\n this.tools.set(tool.name, tool as Tool);\n return this;\n }\n\n has(name: string): boolean {\n return this.tools.has(name);\n }\n\n specs(): ToolSpec[] {\n return [...this.tools.values()].map((tool) => {\n const { $schema: _schema, ...schema } = z.toJSONSchema(tool.input) as Record<string, unknown>;\n return { name: tool.name, description: tool.description, inputSchema: { ...schema, type: \"object\" } };\n });\n }\n\n async run(name: string, input: unknown, context: ToolContext): Promise<unknown> {\n const tool = this.tools.get(name);\n if (!tool) throw new TaskFailure(\"unknown-tool\", `No tool named ${name}`);\n const parsed = tool.input.safeParse(input);\n if (!parsed.success) throw new TaskFailure(\"invalid-tool-input\", `${name}: ${parsed.error.message}`);\n return tool.run(parsed.data, context);\n }\n}\n\n/** Tools every agent has: ask a colleague, and keep or recall facts in its own memory. */\nexport function builtInTools(): ToolRegistry {\n return new ToolRegistry()\n .register({\n name: \"collaborate\",\n description: \"Ask another agent of your own organization to perform a capability, and get its output.\",\n input: z.object({ capability: z.string(), input: z.record(z.string(), z.unknown()).default({}) }),\n run: ({ capability, input }, context) => context.collaborate(capability, input),\n })\n .register({\n name: \"remember\",\n description: \"Store a fact in your memory for later tasks.\",\n input: z.object({ key: z.string().max(100), value: z.unknown() }),\n run: ({ key, value }, context) => {\n context.memory.set(key, value);\n return { stored: key };\n },\n })\n .register({\n name: \"recall\",\n description: \"Read a fact from your memory.\",\n input: z.object({ key: z.string().max(100) }),\n run: ({ key }, context) => ({ key, value: context.memory.get(key) ?? null }),\n });\n}\n","import { AgentUnavailableError, TaskFailure } from \"./errors.ts\";\nimport { type AgentMemory, InMemoryMemoryStore, type MemoryStore } from \"./memory.ts\";\nimport type { ModelAdapter } from \"./model.ts\";\nimport { OrgBus } from \"./org-bus.ts\";\nimport { runPipeline } from \"./pipeline.ts\";\nimport { RuleBasedModel } from \"./rule-based-model.ts\";\nimport { DEFAULT_RESTART_POLICY, type RestartPolicy, Supervisor } from \"./supervisor.ts\";\nimport { builtInTools, type Tool, type ToolContext, type ToolRegistry } from \"./tools.ts\";\nimport type { AgentSpec, AgentStatusReport, Clock, TaskRequest, TaskResult } from \"./types.ts\";\n\n/** What an agent's custom behaviour can reach. */\nexport interface BehaviourContext {\n readonly agent: AgentSpec;\n readonly memory: AgentMemory;\n /** Reports a crash; the supervisor restarts the agent according to the restart policy. */\n crash(reason: string): void;\n}\n\n/** Optional per-agent hooks; without them an agent handles tasks with the default pipeline. */\nexport interface AgentBehaviour {\n /** Runs when the agent starts. Throwing counts as a crash. */\n start?(context: BehaviourContext): void | Promise<void>;\n stop?(): void | Promise<void>;\n /** Handles a task instead of the default observe → reason → act → verify pipeline. */\n handle?(task: TaskRequest, context: BehaviourContext): Promise<TaskResult>;\n}\n\nexport interface AgentRuntimeOptions {\n /** Used for agents whose `model` names a Claude model. Absent when no API key is configured. */\n readonly claude?: ModelAdapter | undefined;\n /** Used for every other agent, and for Claude agents when `claude` is absent. Default: rule-based. */\n readonly fallback?: ModelAdapter | undefined;\n readonly tools?: readonly Tool[] | undefined;\n readonly memory?: MemoryStore | undefined;\n readonly restartPolicy?: Partial<RestartPolicy> | undefined;\n readonly behaviours?: ((agent: AgentSpec) => AgentBehaviour | undefined) | undefined;\n readonly clock?: Clock | undefined;\n}\n\n/** How deep colleagues may ask each other for help within one task. */\nexport const MAX_COLLABORATION_DEPTH = 3;\n\ninterface InternalRequest extends TaskRequest {\n readonly depth?: number;\n}\n\n/**\n * Runs a node's agents (ADR-0020): supervision, per-agent mailboxes on the org bus, model selection, tools and memory.\n * The node server drives it through its `AgentRuntime` port and records the status reports as events.\n */\nexport class AgentRuntime {\n private readonly bus = new OrgBus();\n private readonly supervisor: Supervisor;\n private readonly tools: ToolRegistry;\n private readonly memory: MemoryStore;\n private readonly fallback: ModelAdapter;\n private readonly clock: Clock;\n private readonly specs = new Map<string, AgentSpec>();\n private readonly listeners = new Set<(report: AgentStatusReport) => void>();\n\n constructor(private readonly options: AgentRuntimeOptions = {}) {\n this.tools = builtInTools();\n for (const tool of options.tools ?? []) this.tools.register(tool);\n this.memory = options.memory ?? new InMemoryMemoryStore();\n this.fallback = options.fallback ?? new RuleBasedModel();\n this.clock = options.clock ?? (() => new Date());\n this.supervisor = new Supervisor(\n (agent, crash) => this.launch(agent, crash),\n (report) => this.emit(report),\n { ...DEFAULT_RESTART_POLICY, ...options.restartPolicy },\n );\n }\n\n /** Subscribes to lifecycle reports. Returns an unsubscribe function. */\n onStatus(listener: (report: AgentStatusReport) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n start(agent: AgentSpec): void {\n this.specs.set(agent.id, agent);\n this.supervisor.start(agent);\n }\n\n /** Picks up a changed name, model or capability list; a running agent's mailbox is reopened. */\n update(agent: AgentSpec): void {\n if (!this.specs.has(agent.id)) return;\n this.specs.set(agent.id, agent);\n const reopen = this.mailboxes.get(agent.id);\n if (reopen) reopen(agent);\n }\n\n async stop(agentId: string): Promise<void> {\n await this.supervisor.stop(agentId);\n this.specs.delete(agentId);\n }\n\n isRunning(agentId: string): boolean {\n return this.supervisor.isRunning(agentId);\n }\n\n /** Hands a task to a running agent through its organization's bus, and waits for the result. */\n async execute(agentId: string, task: TaskRequest): Promise<TaskResult> {\n const agent = this.specs.get(agentId);\n if (!agent) throw new AgentUnavailableError(`Agent ${agentId} is not running on this node`);\n return this.bus.request(agent.organizationId, { agentId }, task);\n }\n\n /** Running agents of an organization offering `capability`. */\n providers(organizationId: string, capability: string): string[] {\n return this.bus.providers(organizationId, capability);\n }\n\n async stopAll(): Promise<void> {\n await this.supervisor.stopAll();\n this.specs.clear();\n }\n\n /** Reopens the mailbox of each running agent with its current spec. */\n private readonly mailboxes = new Map<string, (agent: AgentSpec) => void>();\n\n private async launch(agent: AgentSpec, crash: (reason: string) => void) {\n const memory = this.memory.forAgent(agent.id);\n const behaviour = this.options.behaviours?.(agent);\n const context: BehaviourContext = { agent, memory, crash };\n await behaviour?.start?.(context);\n\n let close = () => {};\n const open = (spec: AgentSpec) => {\n close();\n close = this.bus.serve(\n spec.organizationId,\n spec.id,\n spec.capabilities.map((c) => c.name),\n (task) => this.handle(spec.id, task, behaviour, context),\n );\n };\n open(agent);\n this.mailboxes.set(agent.id, open);\n return {\n stop: async () => {\n close();\n this.mailboxes.delete(agent.id);\n await behaviour?.stop?.();\n },\n };\n }\n\n private async handle(\n agentId: string,\n task: InternalRequest,\n behaviour: AgentBehaviour | undefined,\n context: BehaviourContext,\n ): Promise<TaskResult> {\n const agent = this.specs.get(agentId) ?? context.agent;\n if (behaviour?.handle) return behaviour.handle(task, { ...context, agent });\n\n const memory = this.memory.forAgent(agent.id);\n const { adapter, modelId, note } = this.selectModel(agent);\n let collaborations = 0;\n const toolContext: ToolContext = {\n agent,\n memory,\n collaborate: async (capability, input) => {\n const depth = (task.depth ?? 0) + 1;\n if (depth > MAX_COLLABORATION_DEPTH) {\n throw new TaskFailure(\"collaboration-too-deep\", `Collaboration deeper than ${MAX_COLLABORATION_DEPTH}`);\n }\n const request: InternalRequest = {\n id: `${task.id}.c${++collaborations}`,\n capability,\n input,\n depth,\n };\n const result = await this.bus.request(agent.organizationId, { capability, except: agent.id }, request);\n return result.output;\n },\n };\n return runPipeline({\n agent,\n task,\n model: adapter,\n modelId,\n modelNote: note,\n tools: this.tools,\n toolContext,\n memory,\n clock: this.clock,\n });\n }\n\n private selectModel(agent: AgentSpec): { adapter: ModelAdapter; modelId: string | null; note?: string } {\n if (!agent.model) return { adapter: this.fallback, modelId: null };\n if (/^claude/i.test(agent.model)) {\n if (this.options.claude) return { adapter: this.options.claude, modelId: agent.model };\n return {\n adapter: this.fallback,\n modelId: null,\n note: `${agent.model} is not configured on this node (no ANTHROPIC_API_KEY), so the rule-based model answered`,\n };\n }\n return {\n adapter: this.fallback,\n modelId: null,\n note: `no adapter for ${agent.model}, so the rule-based model answered`,\n };\n }\n\n private emit(report: AgentStatusReport): void {\n for (const listener of this.listeners) listener(report);\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@casimesh/agent-runtime",
3
+ "version": "0.1.0",
4
+ "description": "Agent runtime: supervision, model adapters (rule-based, Claude), tools, scoped memory, org bus and the observe → reason → act → verify pipeline (ADR-0020).",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "ai-mesh",
8
+ "agents",
9
+ "runtime",
10
+ "claude",
11
+ "anthropic",
12
+ "casimesh"
13
+ ],
14
+ "type": "module",
15
+ "sideEffects": false,
16
+ "exports": {
17
+ ".": {
18
+ "types": "./index.d.ts",
19
+ "import": "./index.js"
20
+ }
21
+ },
22
+ "types": "./index.d.ts",
23
+ "engines": {
24
+ "node": ">=22"
25
+ },
26
+ "dependencies": {
27
+ "@anthropic-ai/sdk": "0.128.0",
28
+ "@casimesh/contracts": "^0.1.0",
29
+ "zod": "4.6.5"
30
+ }
31
+ }