@otakumesi/heph 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2677 @@
1
+ import { z } from "zod";
2
+ //#region ../core/src/errors.ts
3
+ var HephError = class extends Error {
4
+ code;
5
+ title;
6
+ details;
7
+ status;
8
+ constructor(options) {
9
+ super(options.message ?? options.title, hasCause(options) ? { cause: options.cause } : void 0);
10
+ this.name = "HephError";
11
+ this.code = options.code;
12
+ this.title = options.title;
13
+ if (options.details !== void 0) this.details = options.details;
14
+ if (options.status !== void 0) this.status = options.status;
15
+ }
16
+ };
17
+ function isHephError(error) {
18
+ return error instanceof HephError;
19
+ }
20
+ function toErrorDetails(error) {
21
+ if (error instanceof Error) return {
22
+ name: error.name,
23
+ message: error.message
24
+ };
25
+ return { message: String(error) };
26
+ }
27
+ function hasCause(options) {
28
+ return "cause" in options;
29
+ }
30
+ //#endregion
31
+ //#region ../core/src/context.ts
32
+ var ContextRenderer = class {
33
+ render(options) {
34
+ const slotValues = /* @__PURE__ */ new Map();
35
+ const manifestBlocks = [];
36
+ for (const block of options.blocks) {
37
+ const slot = options.template.slots[block.key];
38
+ const originalTokens = estimateTokens(block.content);
39
+ const truncatedContent = slot?.maxTokens ? truncateToTokens(block.content, slot.maxTokens) : block.content;
40
+ const tokens = estimateTokens(truncatedContent);
41
+ const existing = slotValues.get(block.key);
42
+ slotValues.set(block.key, existing ? `${existing}\n\n${truncatedContent}` : truncatedContent);
43
+ manifestBlocks.push({
44
+ key: block.key,
45
+ type: block.type,
46
+ tokens,
47
+ sourceRefs: block.sourceRefs ?? [],
48
+ truncated: tokens < originalTokens
49
+ });
50
+ }
51
+ for (const [key, slot] of Object.entries(options.template.slots)) {
52
+ const value = slotValues.get(key);
53
+ if (slot.required && isBlank(value)) throw new HephError({
54
+ code: "HEPH2001",
55
+ title: "Required context slot is missing",
56
+ message: `Context template ${options.template.id} requires slot ${key}.`,
57
+ status: 422,
58
+ details: {
59
+ templateId: options.template.id,
60
+ slot: key
61
+ }
62
+ });
63
+ }
64
+ const messages = options.template.messages.map((message) => ({
65
+ role: message.role,
66
+ content: interpolate(message.content, {
67
+ input: options.input,
68
+ runtime: options.runtime ?? {},
69
+ slots: slotValues
70
+ }).trim()
71
+ }));
72
+ return {
73
+ messages,
74
+ manifest: {
75
+ runId: options.runId,
76
+ contextTemplateId: options.template.id,
77
+ contextTemplateVersion: options.template.version,
78
+ blocks: manifestBlocks,
79
+ totalTokens: messages.reduce((sum, message) => sum + estimateTokens(message.content), 0),
80
+ createdAt: /* @__PURE__ */ new Date()
81
+ }
82
+ };
83
+ }
84
+ };
85
+ const defaultContextTemplate = {
86
+ id: "default",
87
+ version: "0.1.0",
88
+ slots: {
89
+ runtimePolicy: { required: true },
90
+ agentIdentity: { required: true },
91
+ developerRules: { maxTokens: 1200 },
92
+ currentTask: {
93
+ required: true,
94
+ maxTokens: 1200
95
+ },
96
+ sessionState: {
97
+ required: true,
98
+ maxTokens: 1500
99
+ },
100
+ openTasks: { maxTokens: 1e3 },
101
+ pendingApprovals: { maxTokens: 800 },
102
+ skills: { maxTokens: 2e3 },
103
+ memories: { maxTokens: 2e3 },
104
+ condensedHistory: { maxTokens: 2e3 },
105
+ recentMessages: { maxTokens: 3e3 },
106
+ domainContext: { maxTokens: 2500 },
107
+ workspaceContext: { maxTokens: 2500 },
108
+ artifacts: { maxTokens: 1500 },
109
+ teamContext: { maxTokens: 1500 },
110
+ toolManifest: {
111
+ required: true,
112
+ maxTokens: 2500
113
+ },
114
+ outputContract: { maxTokens: 1e3 }
115
+ },
116
+ messages: [
117
+ {
118
+ role: "system",
119
+ content: `
120
+ {{ runtimePolicy }}
121
+
122
+ {{ agentIdentity }}
123
+ `
124
+ },
125
+ {
126
+ role: "developer",
127
+ content: `
128
+ Developer rules:
129
+ {{ developerRules }}
130
+
131
+ Tool and safety policy:
132
+ {{ runtime.toolPolicy }}
133
+
134
+ Output contract:
135
+ {{ outputContract }}
136
+ `
137
+ },
138
+ {
139
+ role: "user",
140
+ content: `
141
+ Current task:
142
+ {{ currentTask }}
143
+
144
+ Current session state:
145
+ {{ sessionState }}
146
+
147
+ Open tasks:
148
+ {{ openTasks }}
149
+
150
+ Pending approvals or blocked actions:
151
+ {{ pendingApprovals }}
152
+
153
+ Active skills:
154
+ {{ skills }}
155
+
156
+ Relevant memory:
157
+ {{ memories }}
158
+
159
+ Condensed prior history:
160
+ {{ condensedHistory }}
161
+
162
+ Recent conversation:
163
+ {{ recentMessages }}
164
+
165
+ Domain context:
166
+ {{ domainContext }}
167
+
168
+ Workspace context:
169
+ {{ workspaceContext }}
170
+
171
+ Relevant artifacts:
172
+ {{ artifacts }}
173
+
174
+ Team context:
175
+ {{ teamContext }}
176
+
177
+ Available tools for this Run:
178
+ {{ toolManifest }}
179
+
180
+ User input:
181
+ {{ input }}
182
+ `
183
+ }
184
+ ]
185
+ };
186
+ function estimateTokens(content) {
187
+ if (!content) return 0;
188
+ return Math.max(1, Math.ceil(content.length / 4));
189
+ }
190
+ function truncateToTokens(content, maxTokens) {
191
+ const maxChars = Math.max(0, maxTokens * 4);
192
+ if (content.length <= maxChars) return content;
193
+ return `${content.slice(0, Math.max(0, maxChars - 16)).trimEnd()}\n[truncated]`;
194
+ }
195
+ function interpolate(template, values) {
196
+ return template.replaceAll(/\{\{\s*([\w.]+)\s*\}\}/g, (_match, key) => {
197
+ if (key === "input") return values.input;
198
+ if (key.startsWith("runtime.")) return values.runtime[key.slice(8)] ?? "";
199
+ return values.slots.get(key) ?? "";
200
+ });
201
+ }
202
+ function isBlank(value) {
203
+ return value === void 0 || value.trim().length === 0;
204
+ }
205
+ function messagesToText(messages) {
206
+ return messages.map((message) => `${message.role}: ${message.content}`).join("\n\n");
207
+ }
208
+ //#endregion
209
+ //#region ../core/src/definitions.ts
210
+ function defineAgent(definition) {
211
+ return {
212
+ id: definition.id,
213
+ version: definition.version ?? null,
214
+ instructions: definition.instructions,
215
+ model: definition.model ?? null,
216
+ tools: definition.tools ?? [],
217
+ mcp: normalizeMcpPolicy(definition.mcp, definition.allowAllMcpTools),
218
+ skills: normalizeSkillPolicy(definition.skills),
219
+ contextProviders: [...definition.contextProviders ?? [], ...definition.context ?? []],
220
+ contextTemplate: definition.contextTemplate ?? null,
221
+ metadata: definition.metadata ?? {}
222
+ };
223
+ }
224
+ function normalizeMcpPolicy(policy, allowAllTools) {
225
+ if (policy === void 0 || policy === null) return null;
226
+ if (Array.isArray(policy)) {
227
+ const normalized = { allowCapabilities: policy };
228
+ if (allowAllTools !== void 0) normalized.allowAllTools = allowAllTools;
229
+ return normalized;
230
+ }
231
+ if (allowAllTools !== void 0) return {
232
+ ...policy,
233
+ allowAllTools
234
+ };
235
+ return policy;
236
+ }
237
+ function normalizeSkillPolicy(policy) {
238
+ if (policy === void 0 || policy === null) return null;
239
+ if (policy === "all") return { allow: "all" };
240
+ if (Array.isArray(policy)) return { allow: policy };
241
+ return policy;
242
+ }
243
+ function defineContextProvider(definition) {
244
+ return {
245
+ id: definition.id,
246
+ load: definition.load
247
+ };
248
+ }
249
+ function defineContextTemplate(template) {
250
+ return template;
251
+ }
252
+ function defineTool(definition) {
253
+ const jsonSchema = toJsonSchema(definition.id, definition.inputSchema);
254
+ const tool = {
255
+ id: definition.id,
256
+ description: definition.description,
257
+ inputSchema: definition.inputSchema,
258
+ jsonSchema,
259
+ sideEffect: definition.sideEffect ?? false,
260
+ requiresApproval: definition.requiresApproval ?? false,
261
+ execute: definition.execute
262
+ };
263
+ if (definition.concurrencyKey !== void 0) tool.concurrencyKey = definition.concurrencyKey;
264
+ return tool;
265
+ }
266
+ const AgentSpec = { define: defineAgent };
267
+ const ContextProvider = { define: defineContextProvider };
268
+ const ContextTemplate = { define: defineContextTemplate };
269
+ const Tool = { define: defineTool };
270
+ function toJsonSchema(toolId, schema) {
271
+ try {
272
+ return z.toJSONSchema(schema);
273
+ } catch (cause) {
274
+ throw new HephError({
275
+ code: "HEPH3001",
276
+ title: "Tool schema is not JSON Schema representable",
277
+ message: `Tool ${toolId} uses a Zod schema that cannot be exposed to the model.`,
278
+ status: 422,
279
+ details: { toolId },
280
+ cause
281
+ });
282
+ }
283
+ }
284
+ //#endregion
285
+ //#region ../core/src/executor.ts
286
+ var MinimalRunExecutor = class {
287
+ async execute(ctx) {
288
+ await ctx.emit({
289
+ type: "turn.started",
290
+ payload: { executor: "minimal" }
291
+ });
292
+ const text = runInputText$1(ctx.run.input);
293
+ const response = text ? `Minimal executor received: ${text}` : "Minimal executor completed the run.";
294
+ await ctx.emit({
295
+ type: "message.started",
296
+ payload: { role: "assistant" }
297
+ });
298
+ await ctx.emit({
299
+ type: "message.delta",
300
+ payload: { text: response }
301
+ });
302
+ const message = await ctx.appendMessage({
303
+ role: "assistant",
304
+ content: response,
305
+ sourceRunId: ctx.run.id,
306
+ metadata: { executor: "minimal" }
307
+ });
308
+ await ctx.emit({
309
+ type: "message.completed",
310
+ payload: {
311
+ messageId: message.id,
312
+ role: message.role,
313
+ content: message.content
314
+ },
315
+ sourceRefs: [{
316
+ type: "message",
317
+ id: message.id
318
+ }]
319
+ });
320
+ await ctx.emit({
321
+ type: "turn.completed",
322
+ payload: { executor: "minimal" }
323
+ });
324
+ }
325
+ };
326
+ function runInputText$1(input) {
327
+ return "text" in input ? input.text : "";
328
+ }
329
+ //#endregion
330
+ //#region ../core/src/ids.ts
331
+ let fallbackCounter = 0;
332
+ function createId(prefix) {
333
+ const randomId = globalThis.crypto?.randomUUID?.();
334
+ if (randomId) return `${prefix}${randomId.replaceAll("-", "")}`;
335
+ fallbackCounter += 1;
336
+ return `${prefix}${Date.now().toString(36)}${fallbackCounter.toString(36)}`;
337
+ }
338
+ function createAgentSessionId() {
339
+ return createId("agent_");
340
+ }
341
+ function createRunId() {
342
+ return createId("run_");
343
+ }
344
+ function createMessageId() {
345
+ return createId("msg_");
346
+ }
347
+ function createRunEventId() {
348
+ return createId("evt_");
349
+ }
350
+ function createMemoryId() {
351
+ return createId("mem_");
352
+ }
353
+ function createInboxEventId() {
354
+ return createId("inbox_");
355
+ }
356
+ function createDeferredToolOperationId() {
357
+ return createId("op_");
358
+ }
359
+ function createMcpBindingId() {
360
+ return createId("mcpbind_");
361
+ }
362
+ function createSkillBindingId() {
363
+ return createId("skillbind_");
364
+ }
365
+ function createApprovalRequestId() {
366
+ return createId("approval_");
367
+ }
368
+ //#endregion
369
+ //#region ../core/src/providers.ts
370
+ function recentMessages(options = {}) {
371
+ const limit = options.limit ?? 20;
372
+ return defineContextProvider({
373
+ id: "recent-messages",
374
+ async load(ctx) {
375
+ const messages = await ctx.stores.messages.listMessages(ctx.agent.id, { limit });
376
+ if (messages.length === 0) return null;
377
+ return {
378
+ key: "recentMessages",
379
+ type: "message_history",
380
+ content: formatMessages(messages),
381
+ sourceRefs: messages.map((message) => ({
382
+ type: "message",
383
+ id: message.id
384
+ }))
385
+ };
386
+ }
387
+ });
388
+ }
389
+ function threadState() {
390
+ return defineContextProvider({
391
+ id: "thread-state",
392
+ async load(ctx) {
393
+ return {
394
+ key: "sessionState",
395
+ type: "state",
396
+ content: JSON.stringify(ctx.agent.state, null, 2)
397
+ };
398
+ }
399
+ });
400
+ }
401
+ function memorySearch(options = {}) {
402
+ const topK = options.topK ?? 8;
403
+ return defineContextProvider({
404
+ id: "memory-search",
405
+ async load(ctx) {
406
+ const query = "text" in ctx.input ? ctx.input.text : void 0;
407
+ const searchInput = {
408
+ scopes: options.scopes ?? defaultMemoryScopes(ctx.agent.id, ctx.spec.id, ctx.auth?.userId),
409
+ topK
410
+ };
411
+ const memories = await ctx.stores.memory.searchMemory(query === void 0 ? searchInput : {
412
+ ...searchInput,
413
+ query
414
+ });
415
+ if (memories.length === 0) return null;
416
+ return {
417
+ key: "memories",
418
+ type: "memory",
419
+ content: memories.map((memory) => {
420
+ const sourceRefs = memory.sourceRefs.map((ref) => `${ref.type}:${ref.id}`).join(", ");
421
+ return `- [${memory.kind}] ${memory.content} (sourceRefs: ${sourceRefs})`;
422
+ }).join("\n"),
423
+ sourceRefs: memories.map((memory) => ({
424
+ type: "memory",
425
+ id: memory.id
426
+ }))
427
+ };
428
+ }
429
+ });
430
+ }
431
+ function formatMessages(messages) {
432
+ return messages.map((message) => `${message.role}: ${message.content}`).join("\n");
433
+ }
434
+ function defaultMemoryScopes(sessionId, agentSpecId, userId) {
435
+ const scopes = [{
436
+ type: "session",
437
+ id: sessionId
438
+ }, {
439
+ type: "agent",
440
+ id: agentSpecId
441
+ }];
442
+ if (userId) scopes.push({
443
+ type: "user",
444
+ id: userId
445
+ });
446
+ return scopes;
447
+ }
448
+ function block(block) {
449
+ return block;
450
+ }
451
+ //#endregion
452
+ //#region ../core/src/queue.ts
453
+ var InProcessQueue = class {
454
+ concurrency;
455
+ onError;
456
+ jobs = [];
457
+ activeAgents = /* @__PURE__ */ new Set();
458
+ idleResolvers = /* @__PURE__ */ new Set();
459
+ activeCount = 0;
460
+ scheduled = false;
461
+ handler = null;
462
+ constructor(options = {}) {
463
+ this.concurrency = options.concurrency ?? 4;
464
+ this.onError = options.onError ?? ((error, job) => {
465
+ console.error("Unhandled Heph in-process queue error", {
466
+ error,
467
+ job
468
+ });
469
+ });
470
+ }
471
+ async startConsumer(handler) {
472
+ this.handler = handler;
473
+ this.schedule();
474
+ }
475
+ async enqueue(job) {
476
+ this.jobs.push(job);
477
+ this.schedule();
478
+ }
479
+ async onIdle() {
480
+ if (this.isIdle()) return;
481
+ await new Promise((resolve) => {
482
+ this.idleResolvers.add(resolve);
483
+ });
484
+ }
485
+ schedule() {
486
+ if (this.scheduled) return;
487
+ this.scheduled = true;
488
+ queueMicrotask(() => {
489
+ this.scheduled = false;
490
+ this.pump();
491
+ });
492
+ }
493
+ pump() {
494
+ if (!this.handler) {
495
+ this.resolveIdleIfNeeded();
496
+ return;
497
+ }
498
+ while (this.activeCount < this.concurrency) {
499
+ const index = this.jobs.findIndex((job) => !this.activeAgents.has(job.agentId));
500
+ if (index === -1) break;
501
+ const [job] = this.jobs.splice(index, 1);
502
+ if (!job) break;
503
+ this.activeCount += 1;
504
+ this.activeAgents.add(job.agentId);
505
+ this.handler(job).catch((error) => {
506
+ this.onError(error, job);
507
+ }).finally(() => {
508
+ this.activeCount -= 1;
509
+ this.activeAgents.delete(job.agentId);
510
+ this.resolveIdleIfNeeded();
511
+ this.schedule();
512
+ });
513
+ }
514
+ this.resolveIdleIfNeeded();
515
+ }
516
+ isIdle() {
517
+ return this.jobs.length === 0 && this.activeCount === 0;
518
+ }
519
+ resolveIdleIfNeeded() {
520
+ if (!this.isIdle()) return;
521
+ for (const resolve of this.idleResolvers) resolve();
522
+ this.idleResolvers.clear();
523
+ }
524
+ };
525
+ //#endregion
526
+ //#region ../core/src/skills.ts
527
+ function createInMemorySkillCatalog(skills) {
528
+ const byId = /* @__PURE__ */ new Map();
529
+ for (const skill of skills) byId.set(skill.id, cloneSkillPackage(skill));
530
+ return {
531
+ async getSkill(id) {
532
+ const skill = byId.get(id);
533
+ return skill ? cloneSkillPackage(skill) : null;
534
+ },
535
+ async listSkills() {
536
+ return Array.from(byId.values()).sort((a, b) => a.id.localeCompare(b.id)).map(cloneSkillPackage);
537
+ }
538
+ };
539
+ }
540
+ function cloneSkillPackage(skill) {
541
+ return {
542
+ ...skill,
543
+ source: { ...skill.source },
544
+ references: skill.references.map((ref) => ({
545
+ ...ref,
546
+ metadata: { ...ref.metadata }
547
+ })),
548
+ assets: skill.assets.map((ref) => ({
549
+ ...ref,
550
+ metadata: { ...ref.metadata }
551
+ })),
552
+ templates: skill.templates.map((ref) => ({
553
+ ...ref,
554
+ metadata: { ...ref.metadata }
555
+ })),
556
+ metadata: { ...skill.metadata },
557
+ loadedAt: new Date(skill.loadedAt)
558
+ };
559
+ }
560
+ //#endregion
561
+ //#region ../core/src/stores.ts
562
+ var InMemoryHephStore = class {
563
+ state = this;
564
+ messages = this;
565
+ inbox = this;
566
+ events = this;
567
+ memory = this;
568
+ mcpBindings = this;
569
+ skillBindings = this;
570
+ approvals = this;
571
+ deferredToolOperations = this;
572
+ agentSessions = /* @__PURE__ */ new Map();
573
+ runs = /* @__PURE__ */ new Map();
574
+ messageList = [];
575
+ inboxList = [];
576
+ inboxEvents = /* @__PURE__ */ new Map();
577
+ eventList = [];
578
+ eventSeqByRun = /* @__PURE__ */ new Map();
579
+ memoryItems = /* @__PURE__ */ new Map();
580
+ mcpBindingList = [];
581
+ mcpBindingsById = /* @__PURE__ */ new Map();
582
+ skillBindingList = [];
583
+ skillBindingsById = /* @__PURE__ */ new Map();
584
+ approvalRequests = /* @__PURE__ */ new Map();
585
+ deferredOperations = /* @__PURE__ */ new Map();
586
+ async createAgentSession(input) {
587
+ const now = /* @__PURE__ */ new Date();
588
+ const agent = {
589
+ id: input.id ?? createAgentSessionId(),
590
+ agentSpecId: input.agentSpecId,
591
+ agentSpecVersion: input.agentSpecVersion ?? null,
592
+ state: input.state ?? {},
593
+ activeRunId: null,
594
+ auth: input.auth ?? null,
595
+ metadata: input.metadata ?? {},
596
+ createdAt: now,
597
+ updatedAt: now
598
+ };
599
+ this.agentSessions.set(agent.id, cloneAgentSession(agent));
600
+ return cloneAgentSession(agent);
601
+ }
602
+ async getAgentSession(id) {
603
+ const agent = this.agentSessions.get(id);
604
+ return agent ? cloneAgentSession(agent) : null;
605
+ }
606
+ async updateAgentSession(id, patch) {
607
+ const existing = this.agentSessions.get(id);
608
+ if (!existing) throw notFound("AgentSession not found", { agentId: id });
609
+ const updated = {
610
+ ...existing,
611
+ ...patch,
612
+ id,
613
+ createdAt: existing.createdAt,
614
+ updatedAt: /* @__PURE__ */ new Date()
615
+ };
616
+ this.agentSessions.set(id, cloneAgentSession(updated));
617
+ return cloneAgentSession(updated);
618
+ }
619
+ async createRun(input) {
620
+ const now = /* @__PURE__ */ new Date();
621
+ const run = {
622
+ id: input.id ?? createRunId(),
623
+ agentId: input.agentId,
624
+ agentSpecId: input.agentSpecId,
625
+ agentSpecVersion: input.agentSpecVersion ?? null,
626
+ status: input.status,
627
+ input: input.input,
628
+ auth: input.auth ?? null,
629
+ contextManifest: null,
630
+ skillManifest: null,
631
+ toolManifest: null,
632
+ error: null,
633
+ metadata: input.metadata ?? {},
634
+ queuedAt: now,
635
+ startedAt: null,
636
+ completedAt: null,
637
+ createdAt: now,
638
+ updatedAt: now
639
+ };
640
+ this.runs.set(run.id, cloneRun(run));
641
+ return cloneRun(run);
642
+ }
643
+ async getRun(id) {
644
+ const run = this.runs.get(id);
645
+ return run ? cloneRun(run) : null;
646
+ }
647
+ async updateRun(id, patch) {
648
+ const existing = this.runs.get(id);
649
+ if (!existing) throw notFound("Run not found", { runId: id });
650
+ const updated = {
651
+ ...existing,
652
+ ...patch,
653
+ id,
654
+ createdAt: existing.createdAt,
655
+ updatedAt: /* @__PURE__ */ new Date()
656
+ };
657
+ this.runs.set(id, cloneRun(updated));
658
+ return cloneRun(updated);
659
+ }
660
+ async listRunsByAgent(agentId) {
661
+ return Array.from(this.runs.values()).filter((run) => run.agentId === agentId).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()).map(cloneRun);
662
+ }
663
+ async appendMessage(input) {
664
+ const message = {
665
+ id: input.id ?? createMessageId(),
666
+ agentId: input.agentId,
667
+ role: input.role,
668
+ content: input.content,
669
+ sourceRunId: input.sourceRunId ?? null,
670
+ auth: input.auth ?? null,
671
+ metadata: input.metadata ?? {},
672
+ createdAt: /* @__PURE__ */ new Date()
673
+ };
674
+ this.messageList.push(cloneMessage(message));
675
+ return cloneMessage(message);
676
+ }
677
+ async listMessages(agentId, options = {}) {
678
+ const messages = this.messageList.filter((message) => message.agentId === agentId).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
679
+ return (options.limit === void 0 ? messages : messages.slice(Math.max(0, messages.length - options.limit))).map(cloneMessage);
680
+ }
681
+ async appendInboxEvent(input) {
682
+ const now = /* @__PURE__ */ new Date();
683
+ const event = {
684
+ id: input.id ?? createInboxEventId(),
685
+ agentId: input.agentId,
686
+ type: input.input.type,
687
+ input: clonePlain(input.input),
688
+ status: "pending",
689
+ runId: null,
690
+ auth: input.auth ?? null,
691
+ metadata: input.metadata ?? {},
692
+ createdAt: now,
693
+ updatedAt: now,
694
+ claimedAt: null,
695
+ processedAt: null,
696
+ failedAt: null,
697
+ error: null
698
+ };
699
+ this.inboxList.push(cloneInboxEvent(event));
700
+ this.inboxEvents.set(event.id, cloneInboxEvent(event));
701
+ return cloneInboxEvent(event);
702
+ }
703
+ async getInboxEvent(id) {
704
+ const event = this.inboxEvents.get(id);
705
+ return event ? cloneInboxEvent(event) : null;
706
+ }
707
+ async listInboxEvents(agentId, options = {}) {
708
+ const events = this.inboxList.filter((event) => event.agentId === agentId).filter((event) => options.status === void 0 || event.status === options.status).filter((event) => options.types === void 0 || options.types.includes(event.type)).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
709
+ return (options.limit === void 0 ? events : events.slice(0, options.limit)).map(cloneInboxEvent);
710
+ }
711
+ async claimPendingInboxEvents(agentId, options = {}) {
712
+ const now = /* @__PURE__ */ new Date();
713
+ const pending = this.inboxList.filter((event) => event.agentId === agentId && event.status === "pending").filter((event) => options.types === void 0 || options.types.includes(event.type)).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
714
+ return (options.limit === void 0 ? pending : pending.slice(0, options.limit)).map((event) => {
715
+ return cloneInboxEvent(this.replaceInboxEvent({
716
+ ...event,
717
+ status: "processing",
718
+ claimedAt: now,
719
+ updatedAt: now
720
+ }));
721
+ });
722
+ }
723
+ async markInboxEventsProcessed(ids, runId) {
724
+ const now = /* @__PURE__ */ new Date();
725
+ return ids.map((id) => cloneInboxEvent(this.replaceInboxEvent({
726
+ ...this.getInboxEventOrThrow(id),
727
+ status: "processed",
728
+ runId,
729
+ processedAt: now,
730
+ updatedAt: now,
731
+ error: null
732
+ })));
733
+ }
734
+ async markInboxEventsFailed(ids, error) {
735
+ const now = /* @__PURE__ */ new Date();
736
+ return ids.map((id) => cloneInboxEvent(this.replaceInboxEvent({
737
+ ...this.getInboxEventOrThrow(id),
738
+ status: "failed",
739
+ failedAt: now,
740
+ updatedAt: now,
741
+ error
742
+ })));
743
+ }
744
+ async appendRunEvent(input) {
745
+ const seq = (this.eventSeqByRun.get(input.runId) ?? 0) + 1;
746
+ this.eventSeqByRun.set(input.runId, seq);
747
+ const event = {
748
+ id: input.id ?? createRunEventId(),
749
+ runId: input.runId,
750
+ seq,
751
+ type: input.type,
752
+ payload: input.payload ?? {},
753
+ sourceRefs: input.sourceRefs ?? [],
754
+ createdAt: /* @__PURE__ */ new Date()
755
+ };
756
+ this.eventList.push(cloneRunEvent(event));
757
+ return cloneRunEvent(event);
758
+ }
759
+ async listRunEvents(runId, options = {}) {
760
+ const after = options.after ?? 0;
761
+ const events = this.eventList.filter((event) => event.runId === runId && event.seq > after).sort((a, b) => a.seq - b.seq);
762
+ return (options.limit === void 0 ? events : events.slice(0, options.limit)).map(cloneRunEvent);
763
+ }
764
+ async putMemory(input) {
765
+ const now = /* @__PURE__ */ new Date();
766
+ const existing = input.id ? this.memoryItems.get(input.id) : void 0;
767
+ const item = {
768
+ id: input.id ?? createMemoryId(),
769
+ scope: input.scope,
770
+ kind: input.kind,
771
+ content: input.content,
772
+ sourceRefs: input.sourceRefs,
773
+ importance: input.importance ?? null,
774
+ confidence: input.confidence ?? null,
775
+ embeddingRef: input.embeddingRef ?? null,
776
+ expiresAt: input.expiresAt ?? null,
777
+ createdAt: existing?.createdAt ?? now,
778
+ updatedAt: now
779
+ };
780
+ this.memoryItems.set(item.id, cloneMemoryItem(item));
781
+ return cloneMemoryItem(item);
782
+ }
783
+ async searchMemory(input) {
784
+ const now = Date.now();
785
+ const query = input.query?.trim().toLowerCase();
786
+ const topK = input.topK ?? 8;
787
+ const scopes = input.scopes ?? [];
788
+ return Array.from(this.memoryItems.values()).filter((item) => item.expiresAt === null || item.expiresAt.getTime() > now).filter((item) => scopes.length === 0 || scopes.some((scope) => sameScope(scope, item.scope))).map((item) => ({
789
+ item,
790
+ score: scoreMemory(item, query)
791
+ })).filter(({ score }) => score > 0 || !query).sort((a, b) => b.score - a.score || b.item.updatedAt.getTime() - a.item.updatedAt.getTime()).slice(0, topK).map(({ item }) => cloneMemoryItem(item));
792
+ }
793
+ async createMcpBinding(input) {
794
+ const now = /* @__PURE__ */ new Date();
795
+ const binding = {
796
+ id: input.id ?? createMcpBindingId(),
797
+ agentId: input.agentId,
798
+ capabilityId: input.capabilityId,
799
+ accountRef: input.accountRef ?? null,
800
+ allowTools: clonePlain(input.allowTools),
801
+ status: "active",
802
+ metadata: input.metadata ?? {},
803
+ createdAt: now,
804
+ updatedAt: now,
805
+ removedAt: null
806
+ };
807
+ this.mcpBindingList.push(cloneMcpBinding(binding));
808
+ this.mcpBindingsById.set(binding.id, cloneMcpBinding(binding));
809
+ return cloneMcpBinding(binding);
810
+ }
811
+ async getMcpBinding(id) {
812
+ const binding = this.mcpBindingsById.get(id);
813
+ return binding ? cloneMcpBinding(binding) : null;
814
+ }
815
+ async listMcpBindings(agentId, options = {}) {
816
+ const status = options.status ?? "active";
817
+ return this.mcpBindingList.filter((binding) => binding.agentId === agentId).filter((binding) => status === "all" || binding.status === status).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()).map(cloneMcpBinding);
818
+ }
819
+ async removeMcpBinding(id) {
820
+ const existing = this.mcpBindingsById.get(id);
821
+ if (!existing) throw notFound("McpBinding not found", { bindingId: id });
822
+ const now = /* @__PURE__ */ new Date();
823
+ const updated = {
824
+ ...existing,
825
+ status: "removed",
826
+ updatedAt: now,
827
+ removedAt: existing.removedAt ?? now
828
+ };
829
+ this.replaceMcpBinding(updated);
830
+ return cloneMcpBinding(updated);
831
+ }
832
+ async createSkillBinding(input) {
833
+ const now = /* @__PURE__ */ new Date();
834
+ const binding = {
835
+ id: input.id ?? createSkillBindingId(),
836
+ agentId: input.agentId,
837
+ skillId: input.skillId,
838
+ name: input.name,
839
+ version: input.version ?? null,
840
+ source: { ...input.source },
841
+ allowReferences: input.allowReferences === void 0 ? [] : clonePlain(input.allowReferences),
842
+ status: "active",
843
+ metadata: input.metadata ?? {},
844
+ createdAt: now,
845
+ updatedAt: now,
846
+ removedAt: null
847
+ };
848
+ this.skillBindingList.push(cloneSkillBinding(binding));
849
+ this.skillBindingsById.set(binding.id, cloneSkillBinding(binding));
850
+ return cloneSkillBinding(binding);
851
+ }
852
+ async getSkillBinding(id) {
853
+ const binding = this.skillBindingsById.get(id);
854
+ return binding ? cloneSkillBinding(binding) : null;
855
+ }
856
+ async listSkillBindings(agentId, options = {}) {
857
+ const status = options.status ?? "active";
858
+ return this.skillBindingList.filter((binding) => binding.agentId === agentId).filter((binding) => status === "all" || binding.status === status).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()).map(cloneSkillBinding);
859
+ }
860
+ async removeSkillBinding(id) {
861
+ const existing = this.skillBindingsById.get(id);
862
+ if (!existing) throw notFound("SkillBinding not found", { bindingId: id });
863
+ const now = /* @__PURE__ */ new Date();
864
+ const updated = {
865
+ ...existing,
866
+ status: "removed",
867
+ updatedAt: now,
868
+ removedAt: existing.removedAt ?? now
869
+ };
870
+ this.replaceSkillBinding(updated);
871
+ return cloneSkillBinding(updated);
872
+ }
873
+ async createApprovalRequest(input) {
874
+ const now = /* @__PURE__ */ new Date();
875
+ const request = {
876
+ id: input.id ?? createApprovalRequestId(),
877
+ agentId: input.agentId,
878
+ runId: input.runId,
879
+ toolId: input.toolId,
880
+ input: clonePlain(input.input),
881
+ status: "pending",
882
+ requestedBy: input.requestedBy ?? null,
883
+ decidedBy: null,
884
+ metadata: input.metadata ?? {},
885
+ createdAt: now,
886
+ updatedAt: now,
887
+ decidedAt: null
888
+ };
889
+ this.approvalRequests.set(request.id, cloneApprovalRequest(request));
890
+ return cloneApprovalRequest(request);
891
+ }
892
+ async getApprovalRequest(id) {
893
+ const request = this.approvalRequests.get(id);
894
+ return request ? cloneApprovalRequest(request) : null;
895
+ }
896
+ async listApprovalRequests(runId, options = {}) {
897
+ const status = options.status ?? "all";
898
+ return Array.from(this.approvalRequests.values()).filter((request) => request.runId === runId).filter((request) => status === "all" || request.status === status).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()).map(cloneApprovalRequest);
899
+ }
900
+ async decideApprovalRequest(input) {
901
+ const existing = this.approvalRequests.get(input.id);
902
+ if (!existing) throw notFound("ApprovalRequest not found", { approvalRequestId: input.id });
903
+ const now = /* @__PURE__ */ new Date();
904
+ const updated = {
905
+ ...existing,
906
+ status: input.decision,
907
+ decidedBy: input.decidedBy ?? null,
908
+ metadata: {
909
+ ...existing.metadata,
910
+ ...input.metadata ?? {}
911
+ },
912
+ updatedAt: now,
913
+ decidedAt: now
914
+ };
915
+ this.approvalRequests.set(input.id, cloneApprovalRequest(updated));
916
+ return cloneApprovalRequest(updated);
917
+ }
918
+ async createDeferredToolOperation(input) {
919
+ const now = /* @__PURE__ */ new Date();
920
+ const operation = {
921
+ id: input.id ?? createDeferredToolOperationId(),
922
+ agentId: input.agentId,
923
+ runId: input.runId,
924
+ toolId: input.toolId,
925
+ toolCallId: input.toolCallId ?? null,
926
+ status: "pending",
927
+ resumePolicy: input.resumePolicy ?? "auto",
928
+ auth: input.auth ?? null,
929
+ result: null,
930
+ error: null,
931
+ metadata: input.metadata ?? {},
932
+ createdAt: now,
933
+ updatedAt: now,
934
+ completedAt: null
935
+ };
936
+ this.deferredOperations.set(operation.id, cloneDeferredToolOperation(operation));
937
+ return cloneDeferredToolOperation(operation);
938
+ }
939
+ async getDeferredToolOperation(id) {
940
+ const operation = this.deferredOperations.get(id);
941
+ return operation ? cloneDeferredToolOperation(operation) : null;
942
+ }
943
+ async completeDeferredToolOperation(input) {
944
+ const existing = this.deferredOperations.get(input.id);
945
+ if (!existing) throw notFound("DeferredToolOperation not found", { operationId: input.id });
946
+ if (existing.status !== "pending") return cloneDeferredToolOperation(existing);
947
+ const now = /* @__PURE__ */ new Date();
948
+ const updated = {
949
+ ...existing,
950
+ status: input.status,
951
+ result: input.result ?? null,
952
+ error: input.error ?? null,
953
+ metadata: {
954
+ ...existing.metadata,
955
+ ...input.metadata ?? {}
956
+ },
957
+ updatedAt: now,
958
+ completedAt: now
959
+ };
960
+ this.deferredOperations.set(updated.id, cloneDeferredToolOperation(updated));
961
+ return cloneDeferredToolOperation(updated);
962
+ }
963
+ replaceInboxEvent(updated) {
964
+ const index = this.inboxList.findIndex((event) => event.id === updated.id);
965
+ if (index === -1) throw notFound("InboxEvent not found", { inboxEventId: updated.id });
966
+ this.inboxList[index] = cloneInboxEvent(updated);
967
+ this.inboxEvents.set(updated.id, cloneInboxEvent(updated));
968
+ return cloneInboxEvent(updated);
969
+ }
970
+ getInboxEventOrThrow(id) {
971
+ const event = this.inboxEvents.get(id);
972
+ if (!event) throw notFound("InboxEvent not found", { inboxEventId: id });
973
+ return cloneInboxEvent(event);
974
+ }
975
+ replaceMcpBinding(updated) {
976
+ const index = this.mcpBindingList.findIndex((binding) => binding.id === updated.id);
977
+ if (index === -1) throw notFound("McpBinding not found", { bindingId: updated.id });
978
+ this.mcpBindingList[index] = cloneMcpBinding(updated);
979
+ this.mcpBindingsById.set(updated.id, cloneMcpBinding(updated));
980
+ return cloneMcpBinding(updated);
981
+ }
982
+ replaceSkillBinding(updated) {
983
+ const index = this.skillBindingList.findIndex((binding) => binding.id === updated.id);
984
+ if (index === -1) throw notFound("SkillBinding not found", { bindingId: updated.id });
985
+ this.skillBindingList[index] = cloneSkillBinding(updated);
986
+ this.skillBindingsById.set(updated.id, cloneSkillBinding(updated));
987
+ return cloneSkillBinding(updated);
988
+ }
989
+ };
990
+ function scoreMemory(item, query) {
991
+ const importance = item.importance ?? .5;
992
+ const confidence = item.confidence ?? .5;
993
+ const content = item.content.toLowerCase();
994
+ const queryScore = query && content.includes(query) ? 2 : 0;
995
+ return importance + confidence + queryScore;
996
+ }
997
+ function sameScope(a, b) {
998
+ return a.type === b.type && a.id === b.id;
999
+ }
1000
+ function notFound(message, details) {
1001
+ return new HephError({
1002
+ code: "HEPH5001",
1003
+ title: message,
1004
+ message,
1005
+ status: 404,
1006
+ details
1007
+ });
1008
+ }
1009
+ function cloneAgentSession(agent) {
1010
+ return {
1011
+ ...agent,
1012
+ state: { ...agent.state },
1013
+ metadata: { ...agent.metadata },
1014
+ auth: agent.auth ? { ...agent.auth } : null,
1015
+ createdAt: new Date(agent.createdAt),
1016
+ updatedAt: new Date(agent.updatedAt)
1017
+ };
1018
+ }
1019
+ function cloneRun(run) {
1020
+ return {
1021
+ ...run,
1022
+ input: clonePlain(run.input),
1023
+ auth: run.auth ? { ...run.auth } : null,
1024
+ contextManifest: run.contextManifest ? clonePlain(run.contextManifest) : null,
1025
+ skillManifest: run.skillManifest ? clonePlain(run.skillManifest) : null,
1026
+ toolManifest: run.toolManifest ? clonePlain(run.toolManifest) : null,
1027
+ error: run.error ? clonePlain(run.error) : null,
1028
+ metadata: { ...run.metadata },
1029
+ queuedAt: new Date(run.queuedAt),
1030
+ startedAt: run.startedAt ? new Date(run.startedAt) : null,
1031
+ completedAt: run.completedAt ? new Date(run.completedAt) : null,
1032
+ createdAt: new Date(run.createdAt),
1033
+ updatedAt: new Date(run.updatedAt)
1034
+ };
1035
+ }
1036
+ function cloneMessage(message) {
1037
+ return {
1038
+ ...message,
1039
+ auth: message.auth ? { ...message.auth } : null,
1040
+ metadata: { ...message.metadata },
1041
+ createdAt: new Date(message.createdAt)
1042
+ };
1043
+ }
1044
+ function cloneInboxEvent(event) {
1045
+ return {
1046
+ ...event,
1047
+ input: clonePlain(event.input),
1048
+ auth: event.auth ? { ...event.auth } : null,
1049
+ metadata: { ...event.metadata },
1050
+ createdAt: new Date(event.createdAt),
1051
+ updatedAt: new Date(event.updatedAt),
1052
+ claimedAt: event.claimedAt ? new Date(event.claimedAt) : null,
1053
+ processedAt: event.processedAt ? new Date(event.processedAt) : null,
1054
+ failedAt: event.failedAt ? new Date(event.failedAt) : null,
1055
+ error: event.error ? clonePlain(event.error) : null
1056
+ };
1057
+ }
1058
+ function cloneRunEvent(event) {
1059
+ return {
1060
+ ...event,
1061
+ payload: clonePlain(event.payload),
1062
+ sourceRefs: event.sourceRefs.map((ref) => ({ ...ref })),
1063
+ createdAt: new Date(event.createdAt)
1064
+ };
1065
+ }
1066
+ function cloneMemoryItem(item) {
1067
+ return {
1068
+ ...item,
1069
+ scope: { ...item.scope },
1070
+ sourceRefs: item.sourceRefs.map((ref) => ({ ...ref })),
1071
+ expiresAt: item.expiresAt ? new Date(item.expiresAt) : null,
1072
+ createdAt: new Date(item.createdAt),
1073
+ updatedAt: new Date(item.updatedAt)
1074
+ };
1075
+ }
1076
+ function cloneMcpBinding(binding) {
1077
+ return {
1078
+ ...binding,
1079
+ allowTools: clonePlain(binding.allowTools),
1080
+ metadata: { ...binding.metadata },
1081
+ createdAt: new Date(binding.createdAt),
1082
+ updatedAt: new Date(binding.updatedAt),
1083
+ removedAt: binding.removedAt ? new Date(binding.removedAt) : null
1084
+ };
1085
+ }
1086
+ function cloneSkillBinding(binding) {
1087
+ return {
1088
+ ...binding,
1089
+ source: { ...binding.source },
1090
+ allowReferences: clonePlain(binding.allowReferences),
1091
+ metadata: { ...binding.metadata },
1092
+ createdAt: new Date(binding.createdAt),
1093
+ updatedAt: new Date(binding.updatedAt),
1094
+ removedAt: binding.removedAt ? new Date(binding.removedAt) : null
1095
+ };
1096
+ }
1097
+ function cloneApprovalRequest(request) {
1098
+ return {
1099
+ ...request,
1100
+ input: clonePlain(request.input),
1101
+ requestedBy: request.requestedBy ? { ...request.requestedBy } : null,
1102
+ decidedBy: request.decidedBy ? { ...request.decidedBy } : null,
1103
+ metadata: { ...request.metadata },
1104
+ createdAt: new Date(request.createdAt),
1105
+ updatedAt: new Date(request.updatedAt),
1106
+ decidedAt: request.decidedAt ? new Date(request.decidedAt) : null
1107
+ };
1108
+ }
1109
+ function cloneDeferredToolOperation(operation) {
1110
+ return {
1111
+ ...operation,
1112
+ auth: operation.auth ? { ...operation.auth } : null,
1113
+ result: clonePlain(operation.result),
1114
+ error: operation.error ? clonePlain(operation.error) : null,
1115
+ metadata: { ...operation.metadata },
1116
+ createdAt: new Date(operation.createdAt),
1117
+ updatedAt: new Date(operation.updatedAt),
1118
+ completedAt: operation.completedAt ? new Date(operation.completedAt) : null
1119
+ };
1120
+ }
1121
+ function clonePlain(value) {
1122
+ return structuredClone(value);
1123
+ }
1124
+ //#endregion
1125
+ //#region ../core/src/runtime.ts
1126
+ var StreamableHttpMcpToolExecutor = class {
1127
+ async callTool(ctx) {
1128
+ const credentials = await ctx.resolved.resolveCredentials?.({
1129
+ auth: ctx.auth,
1130
+ agent: ctx.agent,
1131
+ run: ctx.run,
1132
+ binding: ctx.binding,
1133
+ app: ctx.app
1134
+ });
1135
+ const headers = new Headers({
1136
+ "Content-Type": "application/json",
1137
+ Accept: "application/json, text/event-stream"
1138
+ });
1139
+ for (const [key, value] of Object.entries(credentials?.headers ?? {})) headers.set(key, value);
1140
+ const rpcId = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}_${Math.random()}`;
1141
+ const requestInit = {
1142
+ method: "POST",
1143
+ headers,
1144
+ body: JSON.stringify({
1145
+ jsonrpc: "2.0",
1146
+ id: rpcId,
1147
+ method: "tools/call",
1148
+ params: {
1149
+ name: ctx.manifestTool.remoteToolName,
1150
+ arguments: ctx.input ?? {}
1151
+ }
1152
+ })
1153
+ };
1154
+ if (ctx.signal !== void 0) requestInit.signal = ctx.signal;
1155
+ const response = await fetch(ctx.resolved.endpoint, requestInit);
1156
+ const rawBody = await response.text();
1157
+ const parsed = parseMcpResponseBody(rawBody, response.headers.get("Content-Type"));
1158
+ if (!response.ok) throw new HephError({
1159
+ code: "HEPH7002",
1160
+ title: "MCP tool call failed",
1161
+ message: `MCP server returned HTTP ${response.status}.`,
1162
+ status: 503,
1163
+ details: {
1164
+ toolId: ctx.manifestTool.id,
1165
+ bindingId: ctx.binding.id,
1166
+ status: response.status,
1167
+ body: parsed ?? rawBody
1168
+ }
1169
+ });
1170
+ if (isJsonRpcError(parsed)) throw new HephError({
1171
+ code: "HEPH7002",
1172
+ title: "MCP tool call failed",
1173
+ message: "MCP server returned a JSON-RPC error.",
1174
+ status: 503,
1175
+ details: {
1176
+ toolId: ctx.manifestTool.id,
1177
+ bindingId: ctx.binding.id,
1178
+ error: parsed.error
1179
+ }
1180
+ });
1181
+ if (isRecord(parsed) && "result" in parsed) return parsed.result;
1182
+ return parsed;
1183
+ }
1184
+ };
1185
+ function createHeph(options) {
1186
+ const stores = options.stores ?? new InMemoryHephStore();
1187
+ const queue = options.queue ?? new InProcessQueue({ concurrency: options.execution?.concurrency ?? 4 });
1188
+ const executor = options.executor ?? new MinimalRunExecutor();
1189
+ const resolver = normalizeAgentSpecResolver(options.agents);
1190
+ const mcpResolver = options.mcp?.resolver ?? null;
1191
+ const mcpToolExecutor = options.mcp?.toolExecutor ?? new StreamableHttpMcpToolExecutor();
1192
+ const skillCatalog = options.skills?.catalog ?? createInMemorySkillCatalog([]);
1193
+ const renderer = new ContextRenderer();
1194
+ const app = options.app ?? {};
1195
+ const abortControllers = /* @__PURE__ */ new Map();
1196
+ const executionMode = options.execution?.mode ?? "single-process";
1197
+ const reducerOptions = {
1198
+ maxEventsPerRun: normalizeMaxEventsPerRun(options.inbox?.maxEventsPerRun),
1199
+ textSeparator: options.inbox?.textSeparator ?? "\n\n--- next message ---\n\n"
1200
+ };
1201
+ let consumerStarted = false;
1202
+ const runtime = {
1203
+ stores,
1204
+ queue,
1205
+ agents: {
1206
+ async create(input) {
1207
+ const spec = await resolveSpecOrThrow(resolver, input.spec, input.auth ?? null);
1208
+ const skillPackages = await resolveSkillPackagesForSession(spec, input.skills ?? []);
1209
+ const agent = await stores.state.createAgentSession({
1210
+ agentSpecId: spec.id,
1211
+ agentSpecVersion: spec.version,
1212
+ state: input.state,
1213
+ auth: input.auth ?? null,
1214
+ metadata: input.metadata
1215
+ });
1216
+ for (const skillPackage of skillPackages) await stores.skillBindings.createSkillBinding({
1217
+ agentId: agent.id,
1218
+ skillId: skillPackage.id,
1219
+ name: skillPackage.name,
1220
+ version: skillPackage.version,
1221
+ source: skillPackage.source,
1222
+ allowReferences: [],
1223
+ metadata: { description: skillPackage.description }
1224
+ });
1225
+ return agent;
1226
+ },
1227
+ async createAndRun(input) {
1228
+ const agent = await runtime.agents.create(input);
1229
+ const runInput = normalizeRunInput(input.input);
1230
+ const appended = await appendRunInputToInbox({
1231
+ agentId: agent.id,
1232
+ input: runInput,
1233
+ auth: input.auth ?? null,
1234
+ metadata: input.metadata,
1235
+ messageMetadata: {
1236
+ ...input.metadata ?? {},
1237
+ runInput: true
1238
+ }
1239
+ });
1240
+ const run = await scheduleAgent(agent.id);
1241
+ if (!run) throw new HephError({
1242
+ code: "HEPH4002",
1243
+ title: "Run was not scheduled",
1244
+ message: `AgentSession ${agent.id} did not produce a Run from its initial input.`,
1245
+ status: 409,
1246
+ details: {
1247
+ agentId: agent.id,
1248
+ inboxEventId: appended.inboxEvent.id
1249
+ }
1250
+ });
1251
+ return {
1252
+ agent,
1253
+ run,
1254
+ message: appended.message,
1255
+ inboxEvent: appended.inboxEvent,
1256
+ agent_id: agent.id,
1257
+ agent_spec_id: agent.agentSpecId,
1258
+ run_id: run.id
1259
+ };
1260
+ },
1261
+ async appendMessage(input) {
1262
+ await getAgentOrThrow(stores, input.agentId);
1263
+ const appended = await appendRunInputToInbox({
1264
+ agentId: input.agentId,
1265
+ input: {
1266
+ type: input.type ?? "user.message",
1267
+ text: input.content
1268
+ },
1269
+ auth: input.auth ?? null,
1270
+ metadata: input.metadata,
1271
+ messageMetadata: input.metadata
1272
+ });
1273
+ const shouldSchedule = input.schedule ?? true;
1274
+ if (!appended.message) throw new HephError({
1275
+ code: "HEPH4004",
1276
+ title: "Message was not stored",
1277
+ message: "The user message input did not produce a MessageStore record.",
1278
+ status: 500,
1279
+ details: {
1280
+ agentId: input.agentId,
1281
+ inboxEventId: appended.inboxEvent.id
1282
+ }
1283
+ });
1284
+ const inboxEvent = shouldSchedule ? await scheduleAfterAppend(input.agentId, appended.inboxEvent) : appended.inboxEvent;
1285
+ return {
1286
+ message: appended.message,
1287
+ inboxEvent,
1288
+ message_id: appended.message.id,
1289
+ inbox_event_id: inboxEvent.id,
1290
+ scheduled: shouldSchedule
1291
+ };
1292
+ },
1293
+ schedule(agentId) {
1294
+ return scheduleAgent(agentId);
1295
+ },
1296
+ get(agentId) {
1297
+ return stores.state.getAgentSession(agentId);
1298
+ },
1299
+ async addMcpBinding(input) {
1300
+ const agent = await getAgentOrThrow(stores, input.agentId);
1301
+ const spec = await resolveSpecOrThrow(resolver, agent.agentSpecId, input.auth ?? agent.auth);
1302
+ const bindingId = createMcpBindingId();
1303
+ const now = /* @__PURE__ */ new Date();
1304
+ const draft = {
1305
+ id: bindingId,
1306
+ agentId: agent.id,
1307
+ capabilityId: input.capabilityId,
1308
+ accountRef: input.accountRef ?? null,
1309
+ allowTools: Array.isArray(input.allowTools) ? [...input.allowTools] : input.allowTools,
1310
+ status: "active",
1311
+ metadata: input.metadata ?? {},
1312
+ createdAt: now,
1313
+ updatedAt: now,
1314
+ removedAt: null
1315
+ };
1316
+ enforceMcpPolicy(spec, draft);
1317
+ validateMcpCatalog(draft, await resolveMcpBindingOrThrow({
1318
+ resolver: mcpResolver,
1319
+ auth: input.auth ?? agent.auth,
1320
+ agent,
1321
+ binding: draft,
1322
+ app
1323
+ }));
1324
+ return stores.mcpBindings.createMcpBinding({
1325
+ id: bindingId,
1326
+ agentId: agent.id,
1327
+ capabilityId: input.capabilityId,
1328
+ accountRef: input.accountRef ?? null,
1329
+ allowTools: Array.isArray(input.allowTools) ? [...input.allowTools] : input.allowTools,
1330
+ metadata: input.metadata
1331
+ });
1332
+ },
1333
+ async listMcpBindings(agentId) {
1334
+ await getAgentOrThrow(stores, agentId);
1335
+ return stores.mcpBindings.listMcpBindings(agentId);
1336
+ },
1337
+ async removeMcpBinding(input) {
1338
+ const agent = await getAgentOrThrow(stores, input.agentId);
1339
+ const binding = await stores.mcpBindings.getMcpBinding(input.bindingId);
1340
+ if (!binding || binding.agentId !== agent.id) throw new HephError({
1341
+ code: "HEPH5001",
1342
+ title: "McpBinding not found",
1343
+ message: `McpBinding ${input.bindingId} was not found.`,
1344
+ status: 404,
1345
+ details: {
1346
+ agentId: input.agentId,
1347
+ bindingId: input.bindingId
1348
+ }
1349
+ });
1350
+ return stores.mcpBindings.removeMcpBinding(input.bindingId);
1351
+ }
1352
+ },
1353
+ runs: {
1354
+ async create(input) {
1355
+ const agent = await getAgentOrThrow(stores, input.agentId);
1356
+ return createRunForAgent({
1357
+ agent,
1358
+ input: normalizeRunInput(input.input),
1359
+ auth: input.auth ?? agent.auth,
1360
+ metadata: input.metadata,
1361
+ enqueue: input.enqueue ?? true
1362
+ });
1363
+ },
1364
+ get(runId) {
1365
+ return stores.state.getRun(runId);
1366
+ },
1367
+ async cancel(runId) {
1368
+ return cancelRun(runId);
1369
+ }
1370
+ },
1371
+ messages: {
1372
+ append(input) {
1373
+ return stores.messages.appendMessage({
1374
+ agentId: input.agentId,
1375
+ role: input.role,
1376
+ content: input.content,
1377
+ auth: input.auth ?? null,
1378
+ metadata: input.metadata
1379
+ });
1380
+ },
1381
+ list(agentId, listOptions) {
1382
+ return stores.messages.listMessages(agentId, listOptions);
1383
+ }
1384
+ },
1385
+ approvals: {
1386
+ get(approvalRequestId) {
1387
+ return stores.approvals.getApprovalRequest(approvalRequestId);
1388
+ },
1389
+ list(runId) {
1390
+ return stores.approvals.listApprovalRequests(runId);
1391
+ },
1392
+ async decide(input) {
1393
+ const request = await stores.approvals.decideApprovalRequest({
1394
+ id: input.approvalRequestId,
1395
+ decision: input.decision,
1396
+ decidedBy: input.auth ?? null,
1397
+ metadata: input.metadata
1398
+ });
1399
+ await stores.events.appendRunEvent({
1400
+ runId: request.runId,
1401
+ type: input.decision === "granted" ? "approval.granted" : "approval.rejected",
1402
+ payload: {
1403
+ approvalRequestId: request.id,
1404
+ toolId: request.toolId
1405
+ },
1406
+ sourceRefs: [{
1407
+ type: "approval_request",
1408
+ id: request.id
1409
+ }]
1410
+ });
1411
+ return request;
1412
+ }
1413
+ },
1414
+ tools: {
1415
+ call(runId, input) {
1416
+ return callTool(runId, input);
1417
+ },
1418
+ tryCall(runId, input) {
1419
+ return tryCallTool(runId, input);
1420
+ }
1421
+ },
1422
+ operations: {
1423
+ deferToolResult(input) {
1424
+ return deferToolResult(input);
1425
+ },
1426
+ get(operationId) {
1427
+ return stores.deferredToolOperations.getDeferredToolOperation(operationId);
1428
+ },
1429
+ complete(input) {
1430
+ return completeDeferredToolResult(input);
1431
+ }
1432
+ },
1433
+ renderRunContext(runId) {
1434
+ return renderRunContext(runId);
1435
+ },
1436
+ handleJob(job) {
1437
+ return handleJob(job);
1438
+ },
1439
+ async startWorker() {
1440
+ if (consumerStarted) return;
1441
+ if (!queue.startConsumer) throw new HephError({
1442
+ code: "HEPH4003",
1443
+ title: "Queue consumer is not available",
1444
+ message: "This QueueAdapter does not expose startConsumer(). Use handleJob() or an adapter-specific batch handler.",
1445
+ status: 422
1446
+ });
1447
+ consumerStarted = true;
1448
+ await queue.startConsumer((job) => handleJob(job));
1449
+ },
1450
+ async drain() {
1451
+ await queue.onIdle?.();
1452
+ }
1453
+ };
1454
+ if (options.execution?.autoStartConsumer ?? executionMode === "single-process") runtime.startWorker();
1455
+ return runtime;
1456
+ async function handleJob(job) {
1457
+ switch (job.type) {
1458
+ case "schedule_agent":
1459
+ await scheduleAgent(job.agentId);
1460
+ return;
1461
+ case "execute_run":
1462
+ case "resume_run":
1463
+ await executeRun(job.runId);
1464
+ return;
1465
+ case "cancel_run":
1466
+ await cancelRun(job.runId);
1467
+ return;
1468
+ case "ingest_memory": return;
1469
+ }
1470
+ }
1471
+ async function appendRunInputToInbox(input) {
1472
+ const normalized = normalizeRunInput(input.input);
1473
+ const message = "text" in normalized ? await stores.messages.appendMessage({
1474
+ agentId: input.agentId,
1475
+ role: "user",
1476
+ content: normalized.text,
1477
+ auth: input.auth,
1478
+ metadata: input.messageMetadata
1479
+ }) : null;
1480
+ const runInput = message ? addMessageIdToRunInput(normalized, message.id) : normalized;
1481
+ return {
1482
+ runInput,
1483
+ message,
1484
+ inboxEvent: await stores.inbox.appendInboxEvent({
1485
+ agentId: input.agentId,
1486
+ input: runInput,
1487
+ auth: input.auth,
1488
+ metadata: input.metadata
1489
+ })
1490
+ };
1491
+ }
1492
+ async function scheduleAfterAppend(agentId, inboxEvent) {
1493
+ if (inboxEvent.type === "steering.message") {
1494
+ await scheduleAgent(agentId);
1495
+ return await stores.inbox.getInboxEvent(inboxEvent.id) ?? inboxEvent;
1496
+ }
1497
+ await queue.enqueue({
1498
+ type: "schedule_agent",
1499
+ agentId
1500
+ });
1501
+ return inboxEvent;
1502
+ }
1503
+ async function scheduleAgent(agentId) {
1504
+ let agent = await getAgentOrThrow(stores, agentId);
1505
+ if (agent.activeRunId) {
1506
+ const activeRun = await stores.state.getRun(agent.activeRunId);
1507
+ if (activeRun && !isTerminalRun(activeRun)) {
1508
+ await processPendingCancellationEvents(agent, activeRun);
1509
+ await processPendingSteeringEvents(agent, activeRun);
1510
+ return null;
1511
+ }
1512
+ agent = await stores.state.updateAgentSession(agent.id, { activeRunId: null });
1513
+ }
1514
+ const nextPending = await stores.inbox.listInboxEvents(agent.id, {
1515
+ status: "pending",
1516
+ limit: 1
1517
+ });
1518
+ if (nextPending.length === 0) return null;
1519
+ const claimOptions = { types: [nextPending[0].type] };
1520
+ if (reducerOptions.maxEventsPerRun !== void 0) claimOptions.limit = reducerOptions.maxEventsPerRun;
1521
+ const claimed = await stores.inbox.claimPendingInboxEvents(agent.id, claimOptions);
1522
+ if (claimed.length === 0) return null;
1523
+ try {
1524
+ const inboxEventIds = claimed.map((event) => event.id);
1525
+ const run = await createRunForAgent({
1526
+ agent,
1527
+ input: reduceInboxEvents(claimed, reducerOptions.textSeparator),
1528
+ auth: firstAuth(claimed) ?? agent.auth,
1529
+ metadata: {
1530
+ inboxEventIds,
1531
+ inboxEventCount: claimed.length
1532
+ },
1533
+ sourceRefs: toInboxSourceRefs(claimed),
1534
+ enqueue: false
1535
+ });
1536
+ await stores.inbox.markInboxEventsProcessed(inboxEventIds, run.id);
1537
+ await queue.enqueue({
1538
+ type: "execute_run",
1539
+ agentId: agent.id,
1540
+ runId: run.id
1541
+ });
1542
+ return run;
1543
+ } catch (error) {
1544
+ await stores.inbox.markInboxEventsFailed(claimed.map((event) => event.id), toRunError(error));
1545
+ throw error;
1546
+ }
1547
+ }
1548
+ async function processPendingCancellationEvents(agent, activeRun) {
1549
+ const cancellationEvents = await stores.inbox.claimPendingInboxEvents(agent.id, { types: ["run.cancel_requested"] });
1550
+ if (cancellationEvents.length === 0) return;
1551
+ const cancelled = await cancelRun(activeRun.id, { sourceRefs: toInboxSourceRefs(cancellationEvents) });
1552
+ await stores.inbox.markInboxEventsProcessed(cancellationEvents.map((event) => event.id), cancelled.id);
1553
+ }
1554
+ async function processPendingSteeringEvents(agent, activeRun) {
1555
+ const steeringEvents = await stores.inbox.claimPendingInboxEvents(agent.id, { types: ["steering.message"] });
1556
+ for (const event of steeringEvents) await stores.events.appendRunEvent({
1557
+ runId: activeRun.id,
1558
+ type: "run.steering_received",
1559
+ payload: {
1560
+ agentId: agent.id,
1561
+ inboxEventId: event.id,
1562
+ input: event.input
1563
+ },
1564
+ sourceRefs: toInboxSourceRefs([event])
1565
+ });
1566
+ if (steeringEvents.length > 0) await stores.inbox.markInboxEventsProcessed(steeringEvents.map((event) => event.id), activeRun.id);
1567
+ }
1568
+ async function createRunForAgent(input) {
1569
+ const spec = await resolveSpecOrThrow(resolver, input.agent.agentSpecId, input.auth ?? input.agent.auth);
1570
+ const run = await stores.state.createRun({
1571
+ agentId: input.agent.id,
1572
+ agentSpecId: spec.id,
1573
+ agentSpecVersion: spec.version,
1574
+ status: "queued",
1575
+ input: input.input,
1576
+ auth: input.auth,
1577
+ metadata: input.metadata
1578
+ });
1579
+ await stores.state.updateAgentSession(input.agent.id, { activeRunId: run.id });
1580
+ await stores.events.appendRunEvent({
1581
+ runId: run.id,
1582
+ type: "run.queued",
1583
+ payload: {
1584
+ agentId: input.agent.id,
1585
+ agentSpecId: spec.id
1586
+ },
1587
+ sourceRefs: input.sourceRefs
1588
+ });
1589
+ if (input.enqueue) await queue.enqueue({
1590
+ type: "execute_run",
1591
+ agentId: input.agent.id,
1592
+ runId: run.id
1593
+ });
1594
+ return run;
1595
+ }
1596
+ async function cancelRun(runId, options = {}) {
1597
+ const run = await getRunOrThrow(stores, runId);
1598
+ if (isTerminalRun(run)) return run;
1599
+ abortControllers.get(run.id)?.abort();
1600
+ await stores.events.appendRunEvent({
1601
+ runId: run.id,
1602
+ type: "run.cancel_requested",
1603
+ payload: {},
1604
+ sourceRefs: options.sourceRefs
1605
+ });
1606
+ const cancelled = await stores.state.updateRun(run.id, {
1607
+ status: "cancelled",
1608
+ completedAt: /* @__PURE__ */ new Date()
1609
+ });
1610
+ await stores.events.appendRunEvent({
1611
+ runId: run.id,
1612
+ type: "run.cancelled",
1613
+ payload: {}
1614
+ });
1615
+ const agent = await stores.state.getAgentSession(run.agentId);
1616
+ if (agent?.activeRunId === run.id) await stores.state.updateAgentSession(agent.id, { activeRunId: null });
1617
+ await enqueueScheduleIfPending(run.agentId);
1618
+ return cancelled;
1619
+ }
1620
+ async function executeRun(runId) {
1621
+ const initialRun = await getRunOrThrow(stores, runId);
1622
+ if (isTerminalRun(initialRun)) return;
1623
+ const agent = await getAgentOrThrow(stores, initialRun.agentId);
1624
+ const spec = await resolveSpecOrThrow(resolver, initialRun.agentSpecId, initialRun.auth ?? agent.auth);
1625
+ const controller = new AbortController();
1626
+ abortControllers.set(initialRun.id, controller);
1627
+ try {
1628
+ const skillManifest = await createSkillManifestForRun(agent, initialRun);
1629
+ const runWithSkillManifest = await stores.state.updateRun(initialRun.id, { skillManifest });
1630
+ await stores.events.appendRunEvent({
1631
+ runId: runWithSkillManifest.id,
1632
+ type: "skill_manifest.created",
1633
+ payload: { skillCount: skillManifest.skills.length },
1634
+ sourceRefs: skillManifest.skills.map((skill) => ({
1635
+ type: "skill_binding",
1636
+ id: skill.bindingId
1637
+ }))
1638
+ });
1639
+ const toolManifest = await createToolManifestForRun(agent, spec, runWithSkillManifest);
1640
+ const runWithToolManifest = await stores.state.updateRun(runWithSkillManifest.id, { toolManifest });
1641
+ await stores.events.appendRunEvent({
1642
+ runId: runWithToolManifest.id,
1643
+ type: "tool_manifest.created",
1644
+ payload: {
1645
+ toolCount: toolManifest.tools.length,
1646
+ localToolCount: toolManifest.tools.filter((tool) => tool.source === "local").length,
1647
+ mcpToolCount: toolManifest.tools.filter((tool) => tool.source === "mcp").length
1648
+ },
1649
+ sourceRefs: toolManifest.tools.flatMap((tool) => tool.source === "mcp" ? [{
1650
+ type: "mcp_binding",
1651
+ id: tool.bindingId
1652
+ }] : [])
1653
+ });
1654
+ const running = await stores.state.updateRun(runWithToolManifest.id, {
1655
+ status: "running",
1656
+ startedAt: /* @__PURE__ */ new Date()
1657
+ });
1658
+ await stores.events.appendRunEvent({
1659
+ runId: running.id,
1660
+ type: "run.started",
1661
+ payload: {
1662
+ agentId: agent.id,
1663
+ agentSpecId: spec.id
1664
+ }
1665
+ });
1666
+ const renderedContext = await renderRunContext(running.id);
1667
+ const runWithContext = await stores.state.updateRun(running.id, { contextManifest: renderedContext.manifest });
1668
+ const callToolForRun = (input) => callTool(runWithContext.id, {
1669
+ ...input,
1670
+ auth: input.auth ?? runWithContext.auth,
1671
+ signal: input.signal ?? controller.signal
1672
+ });
1673
+ const tryCallToolForRun = (input) => tryCallTool(runWithContext.id, {
1674
+ ...input,
1675
+ auth: input.auth ?? runWithContext.auth,
1676
+ signal: input.signal ?? controller.signal
1677
+ });
1678
+ await executor.execute({
1679
+ auth: runWithContext.auth,
1680
+ agent,
1681
+ spec,
1682
+ run: runWithContext,
1683
+ renderedContext,
1684
+ stores,
1685
+ app,
1686
+ signal: controller.signal,
1687
+ emit(event) {
1688
+ return stores.events.appendRunEvent({
1689
+ ...event,
1690
+ runId: runWithContext.id
1691
+ }).then(() => void 0);
1692
+ },
1693
+ appendMessage(message) {
1694
+ return stores.messages.appendMessage({
1695
+ ...message,
1696
+ agentId: agent.id,
1697
+ auth: runWithContext.auth
1698
+ });
1699
+ },
1700
+ tools: {
1701
+ call: callToolForRun,
1702
+ tryCall: tryCallToolForRun
1703
+ },
1704
+ callTool: callToolForRun,
1705
+ tryCallTool: tryCallToolForRun,
1706
+ deferToolResult(input) {
1707
+ return deferToolResult({
1708
+ ...input,
1709
+ runId: input.runId ?? runWithContext.id,
1710
+ auth: input.auth ?? runWithContext.auth
1711
+ });
1712
+ }
1713
+ });
1714
+ const current = await getRunOrThrow(stores, running.id);
1715
+ if (current.status === "running") {
1716
+ await stores.state.updateRun(current.id, {
1717
+ status: "completed",
1718
+ completedAt: /* @__PURE__ */ new Date()
1719
+ });
1720
+ await stores.events.appendRunEvent({
1721
+ runId: current.id,
1722
+ type: "run.completed",
1723
+ payload: {}
1724
+ });
1725
+ await clearActiveRunIfCurrent(agent.id, current.id);
1726
+ await enqueueScheduleIfPending(agent.id);
1727
+ }
1728
+ } catch (error) {
1729
+ if ((await stores.state.getRun(initialRun.id))?.status === "cancelled") return;
1730
+ const runError = {
1731
+ message: error instanceof Error ? error.message : String(error),
1732
+ details: toErrorDetails(error)
1733
+ };
1734
+ if (error instanceof HephError) Object.assign(runError, { code: error.code });
1735
+ await stores.state.updateRun(initialRun.id, {
1736
+ status: "failed",
1737
+ completedAt: /* @__PURE__ */ new Date(),
1738
+ error: runError
1739
+ });
1740
+ await stores.events.appendRunEvent({
1741
+ runId: initialRun.id,
1742
+ type: "run.failed",
1743
+ payload: toErrorDetails(error)
1744
+ });
1745
+ await clearActiveRunIfCurrent(agent.id, initialRun.id);
1746
+ await enqueueScheduleIfPending(agent.id);
1747
+ } finally {
1748
+ abortControllers.delete(initialRun.id);
1749
+ }
1750
+ }
1751
+ async function deferToolResult(input) {
1752
+ const run = await getRunOrThrow(stores, input.runId);
1753
+ const agent = await getAgentOrThrow(stores, run.agentId);
1754
+ const operation = await stores.deferredToolOperations.createDeferredToolOperation({
1755
+ agentId: agent.id,
1756
+ runId: run.id,
1757
+ toolId: input.toolId,
1758
+ auth: input.auth ?? run.auth ?? agent.auth,
1759
+ ...input.operationId !== void 0 ? { id: input.operationId } : {},
1760
+ ...input.toolCallId !== void 0 ? { toolCallId: input.toolCallId } : {},
1761
+ ...input.resumePolicy !== void 0 ? { resumePolicy: input.resumePolicy } : {},
1762
+ ...input.metadata !== void 0 ? { metadata: input.metadata } : {}
1763
+ });
1764
+ await stores.events.appendRunEvent({
1765
+ runId: run.id,
1766
+ type: "tool.deferred",
1767
+ payload: {
1768
+ operationId: operation.id,
1769
+ toolId: operation.toolId,
1770
+ toolCallId: operation.toolCallId,
1771
+ resumePolicy: operation.resumePolicy
1772
+ },
1773
+ sourceRefs: [{
1774
+ type: "deferred_tool_operation",
1775
+ id: operation.id
1776
+ }]
1777
+ });
1778
+ return operation;
1779
+ }
1780
+ async function completeDeferredToolResult(input) {
1781
+ if (!await stores.deferredToolOperations.getDeferredToolOperation(input.operationId)) throw new HephError({
1782
+ code: "HEPH3005",
1783
+ title: "DeferredToolOperation not found",
1784
+ message: `DeferredToolOperation ${input.operationId} was not found.`,
1785
+ status: 404,
1786
+ details: { operationId: input.operationId }
1787
+ });
1788
+ const status = input.status ?? (input.error ? "failed" : "completed");
1789
+ const operation = await stores.deferredToolOperations.completeDeferredToolOperation({
1790
+ id: input.operationId,
1791
+ status,
1792
+ result: input.result,
1793
+ error: input.error,
1794
+ metadata: input.metadata
1795
+ });
1796
+ const message = await stores.messages.appendMessage({
1797
+ agentId: operation.agentId,
1798
+ role: "tool",
1799
+ content: input.content ?? renderDeferredToolResultContent(operation),
1800
+ sourceRunId: operation.runId,
1801
+ auth: input.auth ?? operation.auth,
1802
+ metadata: {
1803
+ type: "tool_result",
1804
+ deferredToolOperationId: operation.id,
1805
+ toolId: operation.toolId,
1806
+ toolCallId: operation.toolCallId,
1807
+ status: operation.status,
1808
+ ...input.metadata ?? {}
1809
+ }
1810
+ });
1811
+ const eventType = status === "completed" ? "deferred_tool.completed" : "deferred_tool.failed";
1812
+ await stores.events.appendRunEvent({
1813
+ runId: operation.runId,
1814
+ type: eventType,
1815
+ payload: {
1816
+ operationId: operation.id,
1817
+ toolId: operation.toolId,
1818
+ toolCallId: operation.toolCallId,
1819
+ status: operation.status,
1820
+ messageId: message.id,
1821
+ result: operation.result,
1822
+ error: operation.error
1823
+ },
1824
+ sourceRefs: [{
1825
+ type: "deferred_tool_operation",
1826
+ id: operation.id
1827
+ }, {
1828
+ type: "message",
1829
+ id: message.id
1830
+ }]
1831
+ });
1832
+ if (!(input.schedule ?? operation.resumePolicy === "auto")) return {
1833
+ operation,
1834
+ message,
1835
+ inboxEvent: null,
1836
+ scheduled: false
1837
+ };
1838
+ const inboxEvent = await stores.inbox.appendInboxEvent({
1839
+ agentId: operation.agentId,
1840
+ input: {
1841
+ type: "system.event",
1842
+ payload: {
1843
+ event: "deferred_tool.completed",
1844
+ operationId: operation.id,
1845
+ runId: operation.runId,
1846
+ toolId: operation.toolId,
1847
+ toolCallId: operation.toolCallId,
1848
+ status: operation.status
1849
+ },
1850
+ messageIds: [message.id]
1851
+ },
1852
+ auth: input.auth ?? operation.auth,
1853
+ metadata: {
1854
+ deferredToolOperationId: operation.id,
1855
+ toolId: operation.toolId,
1856
+ status: operation.status
1857
+ }
1858
+ });
1859
+ await queue.enqueue({
1860
+ type: "schedule_agent",
1861
+ agentId: operation.agentId
1862
+ });
1863
+ return {
1864
+ operation,
1865
+ message,
1866
+ inboxEvent,
1867
+ scheduled: true
1868
+ };
1869
+ }
1870
+ async function enqueueScheduleIfPending(agentId) {
1871
+ if ((await stores.inbox.listInboxEvents(agentId, {
1872
+ status: "pending",
1873
+ limit: 1
1874
+ })).length > 0) await queue.enqueue({
1875
+ type: "schedule_agent",
1876
+ agentId
1877
+ });
1878
+ }
1879
+ async function clearActiveRunIfCurrent(agentId, runId) {
1880
+ if ((await stores.state.getAgentSession(agentId))?.activeRunId === runId) await stores.state.updateAgentSession(agentId, { activeRunId: null });
1881
+ }
1882
+ async function resolveSkillPackagesForSession(spec, skillIds) {
1883
+ const uniqueSkillIds = unique(skillIds);
1884
+ if (uniqueSkillIds.length === 0) return [];
1885
+ const packages = [];
1886
+ for (const skillId of uniqueSkillIds) {
1887
+ enforceSkillPolicy(spec, skillId);
1888
+ const skillPackage = await skillCatalog.getSkill(skillId);
1889
+ if (!skillPackage) throw new HephError({
1890
+ code: "HEPH8003",
1891
+ title: "Skill not found",
1892
+ message: `Skill ${skillId} was not found in the configured SkillCatalog.`,
1893
+ status: 422,
1894
+ details: {
1895
+ agentSpecId: spec.id,
1896
+ skillId
1897
+ }
1898
+ });
1899
+ packages.push(skillPackage);
1900
+ }
1901
+ return packages;
1902
+ }
1903
+ async function createSkillManifestForRun(agent, run) {
1904
+ const bindings = await stores.skillBindings.listSkillBindings(agent.id);
1905
+ const skills = [];
1906
+ for (const binding of bindings) {
1907
+ const skillPackage = await skillCatalog.getSkill(binding.skillId);
1908
+ if (!skillPackage) throw new HephError({
1909
+ code: "HEPH8003",
1910
+ title: "Skill not found",
1911
+ message: `Skill ${binding.skillId} was not found in the configured SkillCatalog.`,
1912
+ status: 422,
1913
+ details: {
1914
+ agentId: agent.id,
1915
+ bindingId: binding.id,
1916
+ skillId: binding.skillId
1917
+ }
1918
+ });
1919
+ skills.push({
1920
+ bindingId: binding.id,
1921
+ skillId: binding.skillId,
1922
+ name: skillPackage.name,
1923
+ version: skillPackage.version,
1924
+ description: skillPackage.description,
1925
+ instructions: skillPackage.instructions,
1926
+ descriptionHash: await sha256Text(skillPackage.description),
1927
+ instructionHash: await sha256Text(skillPackage.instructions),
1928
+ source: { ...binding.source },
1929
+ availableReferences: filterSkillReferences(skillPackage.references, binding.allowReferences),
1930
+ availableAssets: skillPackage.assets.map(cloneSkillResourceRef),
1931
+ availableTemplates: skillPackage.templates.map(cloneSkillResourceRef),
1932
+ metadata: {
1933
+ ...skillPackage.metadata,
1934
+ ...binding.metadata
1935
+ }
1936
+ });
1937
+ }
1938
+ return {
1939
+ runId: run.id,
1940
+ skills,
1941
+ createdAt: /* @__PURE__ */ new Date()
1942
+ };
1943
+ }
1944
+ async function createToolManifestForRun(agent, spec, run) {
1945
+ const tools = spec.tools.map(toLocalManifestTool);
1946
+ const bindings = await stores.mcpBindings.listMcpBindings(agent.id);
1947
+ for (const binding of bindings) {
1948
+ enforceMcpPolicy(spec, binding);
1949
+ const resolved = await resolveMcpBindingOrThrow({
1950
+ resolver: mcpResolver,
1951
+ auth: run.auth ?? agent.auth,
1952
+ agent,
1953
+ binding,
1954
+ app
1955
+ });
1956
+ validateMcpCatalog(binding, resolved);
1957
+ tools.push(...filterMcpCatalog(binding, resolved).map((tool) => toMcpManifestTool(binding, tool)));
1958
+ }
1959
+ return {
1960
+ runId: run.id,
1961
+ tools,
1962
+ createdAt: /* @__PURE__ */ new Date()
1963
+ };
1964
+ }
1965
+ async function callTool(runId, input) {
1966
+ const run = await getRunOrThrow(stores, runId);
1967
+ if (run.status !== "running" && run.status !== "paused") throw new HephError({
1968
+ code: "HEPH3004",
1969
+ title: "Tool call is not allowed for this Run status",
1970
+ message: `Run ${run.id} is ${run.status}; tool calls require running or paused.`,
1971
+ status: 409,
1972
+ details: {
1973
+ runId: run.id,
1974
+ status: run.status,
1975
+ toolId: input.toolId
1976
+ }
1977
+ });
1978
+ if (!run.toolManifest) throw new HephError({
1979
+ code: "HEPH3003",
1980
+ title: "ToolManifest is not ready",
1981
+ message: `Run ${run.id} is ${run.status} but has no Run-scoped ToolManifest.`,
1982
+ status: 500,
1983
+ details: {
1984
+ runId: run.id,
1985
+ status: run.status,
1986
+ toolId: input.toolId
1987
+ }
1988
+ });
1989
+ const manifestTool = run.toolManifest.tools.find((tool) => tool.id === input.toolId);
1990
+ if (!manifestTool) throw new HephError({
1991
+ code: "HEPH3005",
1992
+ title: "Tool is not available for this Run",
1993
+ message: `Tool ${input.toolId} is not present in Run ${run.id}'s ToolManifest.`,
1994
+ status: 404,
1995
+ details: {
1996
+ runId: run.id,
1997
+ toolId: input.toolId
1998
+ }
1999
+ });
2000
+ const agent = await getAgentOrThrow(stores, run.agentId);
2001
+ const spec = await resolveSpecOrThrow(resolver, run.agentSpecId, input.auth ?? run.auth ?? agent.auth);
2002
+ const auth = input.auth ?? run.auth;
2003
+ const toolInput = input.input ?? {};
2004
+ await ensureToolApproval({
2005
+ run,
2006
+ agent,
2007
+ manifestTool,
2008
+ input: toolInput,
2009
+ auth,
2010
+ approvalRequestId: input.approvalRequestId
2011
+ });
2012
+ await stores.events.appendRunEvent({
2013
+ runId: run.id,
2014
+ type: "tool.started",
2015
+ payload: {
2016
+ toolId: manifestTool.id,
2017
+ displayName: manifestTool.displayName,
2018
+ source: manifestTool.source,
2019
+ input: toolInput
2020
+ },
2021
+ sourceRefs: toolSourceRefs(manifestTool, input.approvalRequestId)
2022
+ });
2023
+ try {
2024
+ const result = manifestTool.source === "local" ? await callLocalTool({
2025
+ spec,
2026
+ manifestTool,
2027
+ input: toolInput,
2028
+ auth,
2029
+ agent,
2030
+ run,
2031
+ signal: input.signal ?? new AbortController().signal
2032
+ }) : await callMcpTool({
2033
+ manifestTool,
2034
+ input: toolInput,
2035
+ auth,
2036
+ agent,
2037
+ run,
2038
+ signal: input.signal
2039
+ });
2040
+ await stores.events.appendRunEvent({
2041
+ runId: run.id,
2042
+ type: "tool.completed",
2043
+ payload: {
2044
+ toolId: manifestTool.id,
2045
+ source: manifestTool.source,
2046
+ result
2047
+ },
2048
+ sourceRefs: toolSourceRefs(manifestTool, input.approvalRequestId)
2049
+ });
2050
+ return {
2051
+ toolId: manifestTool.id,
2052
+ result,
2053
+ ok: true
2054
+ };
2055
+ } catch (error) {
2056
+ await stores.events.appendRunEvent({
2057
+ runId: run.id,
2058
+ type: "tool.failed",
2059
+ payload: {
2060
+ toolId: manifestTool.id,
2061
+ source: manifestTool.source,
2062
+ error: toErrorDetails(error)
2063
+ },
2064
+ sourceRefs: toolSourceRefs(manifestTool, input.approvalRequestId)
2065
+ });
2066
+ throw error;
2067
+ }
2068
+ }
2069
+ async function tryCallTool(runId, input) {
2070
+ try {
2071
+ return {
2072
+ ...await callTool(runId, input),
2073
+ ok: true
2074
+ };
2075
+ } catch (error) {
2076
+ if (shouldRethrowToolCallAttemptError(error)) throw error;
2077
+ return {
2078
+ toolId: input.toolId,
2079
+ ok: false,
2080
+ error: toRunError(error)
2081
+ };
2082
+ }
2083
+ }
2084
+ async function ensureToolApproval(input) {
2085
+ if (!(input.manifestTool.requiresApproval || input.manifestTool.sideEffect !== false)) return;
2086
+ if (input.approvalRequestId) {
2087
+ const request = await stores.approvals.getApprovalRequest(input.approvalRequestId);
2088
+ if (request && request.runId === input.run.id && request.toolId === input.manifestTool.id && request.status === "granted") return;
2089
+ throw new HephError({
2090
+ code: "HEPH3002",
2091
+ title: "Approval required",
2092
+ message: `Tool ${input.manifestTool.id} requires a granted approval request.`,
2093
+ status: 409,
2094
+ details: {
2095
+ approvalRequestId: input.approvalRequestId,
2096
+ runId: input.run.id,
2097
+ toolId: input.manifestTool.id,
2098
+ approvalStatus: request?.status ?? null
2099
+ }
2100
+ });
2101
+ }
2102
+ const approval = await stores.approvals.createApprovalRequest({
2103
+ agentId: input.agent.id,
2104
+ runId: input.run.id,
2105
+ toolId: input.manifestTool.id,
2106
+ input: input.input,
2107
+ requestedBy: input.auth,
2108
+ metadata: {
2109
+ toolSource: input.manifestTool.source,
2110
+ displayName: input.manifestTool.displayName
2111
+ }
2112
+ });
2113
+ if (input.run.status === "running") {
2114
+ await stores.state.updateRun(input.run.id, { status: "paused" });
2115
+ await stores.events.appendRunEvent({
2116
+ runId: input.run.id,
2117
+ type: "run.paused",
2118
+ payload: {
2119
+ reason: "approval_required",
2120
+ approvalRequestId: approval.id,
2121
+ toolId: input.manifestTool.id
2122
+ },
2123
+ sourceRefs: [{
2124
+ type: "approval_request",
2125
+ id: approval.id
2126
+ }]
2127
+ });
2128
+ }
2129
+ await stores.events.appendRunEvent({
2130
+ runId: input.run.id,
2131
+ type: "approval.requested",
2132
+ payload: {
2133
+ approvalRequestId: approval.id,
2134
+ toolId: input.manifestTool.id,
2135
+ displayName: input.manifestTool.displayName
2136
+ },
2137
+ sourceRefs: [...toolSourceRefs(input.manifestTool), {
2138
+ type: "approval_request",
2139
+ id: approval.id
2140
+ }]
2141
+ });
2142
+ throw new HephError({
2143
+ code: "HEPH3002",
2144
+ title: "Approval required",
2145
+ message: `Tool ${input.manifestTool.id} requires approval before execution.`,
2146
+ status: 409,
2147
+ details: {
2148
+ approvalRequestId: approval.id,
2149
+ runId: input.run.id,
2150
+ toolId: input.manifestTool.id
2151
+ }
2152
+ });
2153
+ }
2154
+ async function callLocalTool(input) {
2155
+ const tool = input.spec.tools.find((candidate) => candidate.id === input.manifestTool.id);
2156
+ if (!tool) throw new HephError({
2157
+ code: "HEPH3005",
2158
+ title: "Local tool is not registered",
2159
+ message: `Local tool ${input.manifestTool.id} is not registered on AgentSpec ${input.spec.id}.`,
2160
+ status: 500,
2161
+ details: {
2162
+ toolId: input.manifestTool.id,
2163
+ agentSpecId: input.spec.id
2164
+ }
2165
+ });
2166
+ const parsedInput = tool.inputSchema.parse(input.input);
2167
+ return tool.execute(parsedInput, {
2168
+ auth: input.auth,
2169
+ agent: input.agent,
2170
+ run: input.run,
2171
+ app,
2172
+ signal: input.signal
2173
+ });
2174
+ }
2175
+ async function callMcpTool(input) {
2176
+ const binding = await stores.mcpBindings.getMcpBinding(input.manifestTool.bindingId);
2177
+ if (!binding) throw new HephError({
2178
+ code: "HEPH7001",
2179
+ title: "MCP binding not found",
2180
+ message: `MCP binding ${input.manifestTool.bindingId} was not found.`,
2181
+ status: 500,
2182
+ details: {
2183
+ bindingId: input.manifestTool.bindingId,
2184
+ toolId: input.manifestTool.id
2185
+ }
2186
+ });
2187
+ const resolved = await resolveMcpBindingOrThrow({
2188
+ resolver: mcpResolver,
2189
+ auth: input.auth,
2190
+ agent: input.agent,
2191
+ binding,
2192
+ app
2193
+ });
2194
+ return mcpToolExecutor.callTool({
2195
+ auth: input.auth,
2196
+ agent: input.agent,
2197
+ run: input.run,
2198
+ binding,
2199
+ manifestTool: input.manifestTool,
2200
+ resolved,
2201
+ input: input.input,
2202
+ app,
2203
+ signal: input.signal
2204
+ });
2205
+ }
2206
+ async function renderRunContext(runId) {
2207
+ const run = await getRunOrThrow(stores, runId);
2208
+ const agent = await getAgentOrThrow(stores, run.agentId);
2209
+ const spec = await resolveSpecOrThrow(resolver, run.agentSpecId, run.auth ?? agent.auth);
2210
+ const providerBlocks = await loadProviderBlocks(spec.contextProviders, {
2211
+ auth: run.auth,
2212
+ agent,
2213
+ run,
2214
+ spec,
2215
+ input: run.input,
2216
+ stores,
2217
+ app
2218
+ });
2219
+ const builtInBlocks = createBuiltInBlocks({
2220
+ agent,
2221
+ spec,
2222
+ run,
2223
+ runtimePolicy: options.runtimePolicy ?? "Follow the active platform, security, tenant-boundary, and tool policies supplied by the runtime.",
2224
+ toolPolicy: options.toolPolicy ?? "Use only the tools listed in the Run-scoped ToolManifest."
2225
+ });
2226
+ const rendered = renderer.render({
2227
+ template: spec.contextTemplate ?? defaultContextTemplate,
2228
+ blocks: [...builtInBlocks, ...providerBlocks],
2229
+ runId: run.id,
2230
+ input: runInputText(run.input),
2231
+ runtime: { toolPolicy: options.toolPolicy ?? "Use only the tools listed in the Run-scoped ToolManifest." }
2232
+ });
2233
+ await stores.events.appendRunEvent({
2234
+ runId: run.id,
2235
+ type: "context.rendered",
2236
+ payload: {
2237
+ contextTemplateId: rendered.manifest.contextTemplateId,
2238
+ contextTemplateVersion: rendered.manifest.contextTemplateVersion,
2239
+ totalTokens: rendered.manifest.totalTokens,
2240
+ blocks: rendered.manifest.blocks.map((block) => ({
2241
+ key: block.key,
2242
+ type: block.type,
2243
+ tokens: block.tokens,
2244
+ truncated: block.truncated
2245
+ }))
2246
+ }
2247
+ });
2248
+ return rendered;
2249
+ }
2250
+ }
2251
+ function normalizeAgentSpecResolver(registration) {
2252
+ if (isAgentSpecResolver(registration)) return registration;
2253
+ const specs = /* @__PURE__ */ new Map();
2254
+ if (Array.isArray(registration)) for (const spec of registration) specs.set(spec.id, spec);
2255
+ else for (const [id, spec] of Object.entries(registration)) specs.set(id, spec);
2256
+ return { async resolve(id) {
2257
+ return specs.get(id) ?? null;
2258
+ } };
2259
+ }
2260
+ function isAgentSpecResolver(registration) {
2261
+ return typeof registration.resolve === "function";
2262
+ }
2263
+ async function resolveSpecOrThrow(resolver, id, auth) {
2264
+ const spec = await resolver.resolve(id, { auth });
2265
+ if (!spec) throw new HephError({
2266
+ code: "HEPH1001",
2267
+ title: "Agent spec not found",
2268
+ message: `Agent spec ${id} was not found.`,
2269
+ status: 404,
2270
+ details: { agentSpecId: id }
2271
+ });
2272
+ return spec;
2273
+ }
2274
+ async function getAgentOrThrow(stores, agentId) {
2275
+ const agent = await stores.state.getAgentSession(agentId);
2276
+ if (!agent) throw new HephError({
2277
+ code: "HEPH5001",
2278
+ title: "AgentSession not found",
2279
+ message: `AgentSession ${agentId} was not found.`,
2280
+ status: 404,
2281
+ details: { agentId }
2282
+ });
2283
+ return agent;
2284
+ }
2285
+ async function getRunOrThrow(stores, runId) {
2286
+ const run = await stores.state.getRun(runId);
2287
+ if (!run) throw new HephError({
2288
+ code: "HEPH4001",
2289
+ title: "Run not found",
2290
+ message: `Run ${runId} was not found.`,
2291
+ status: 404,
2292
+ details: { runId }
2293
+ });
2294
+ return run;
2295
+ }
2296
+ async function loadProviderBlocks(providers, ctx) {
2297
+ const blocks = [];
2298
+ for (const provider of providers) {
2299
+ const loaded = await provider.load(ctx);
2300
+ if (!loaded) continue;
2301
+ if (Array.isArray(loaded)) blocks.push(...loaded);
2302
+ else blocks.push(loaded);
2303
+ }
2304
+ return blocks;
2305
+ }
2306
+ function enforceMcpPolicy(spec, binding) {
2307
+ if (!spec.mcp) throw new HephError({
2308
+ code: "HEPH7001",
2309
+ title: "MCP is disabled for this AgentSpec",
2310
+ message: `AgentSpec ${spec.id} does not allow dynamic MCP bindings.`,
2311
+ status: 422,
2312
+ details: {
2313
+ agentSpecId: spec.id,
2314
+ capabilityId: binding.capabilityId
2315
+ }
2316
+ });
2317
+ if (!spec.mcp.allowCapabilities.includes(binding.capabilityId)) throw new HephError({
2318
+ code: "HEPH7001",
2319
+ title: "MCP capability is not allowed",
2320
+ message: `AgentSpec ${spec.id} does not allow MCP capability ${binding.capabilityId}.`,
2321
+ status: 422,
2322
+ details: {
2323
+ agentSpecId: spec.id,
2324
+ capabilityId: binding.capabilityId
2325
+ }
2326
+ });
2327
+ if (binding.allowTools === "all" && spec.mcp.allowAllTools !== true) throw new HephError({
2328
+ code: "HEPH7001",
2329
+ title: "MCP allowTools all is not allowed",
2330
+ message: `AgentSpec ${spec.id} must opt in before an MCP binding can expose all tools.`,
2331
+ status: 422,
2332
+ details: {
2333
+ agentSpecId: spec.id,
2334
+ capabilityId: binding.capabilityId
2335
+ }
2336
+ });
2337
+ }
2338
+ function enforceSkillPolicy(spec, skillId) {
2339
+ if (!spec.skills) throw new HephError({
2340
+ code: "HEPH8004",
2341
+ title: "Skills are disabled for this AgentSpec",
2342
+ message: `AgentSpec ${spec.id} does not allow session skill activation.`,
2343
+ status: 422,
2344
+ details: {
2345
+ agentSpecId: spec.id,
2346
+ skillId
2347
+ }
2348
+ });
2349
+ if (spec.skills.allow !== "all" && !spec.skills.allow.includes(skillId)) throw new HephError({
2350
+ code: "HEPH8004",
2351
+ title: "Skill is not allowed",
2352
+ message: `AgentSpec ${spec.id} does not allow skill ${skillId}.`,
2353
+ status: 422,
2354
+ details: {
2355
+ agentSpecId: spec.id,
2356
+ skillId
2357
+ }
2358
+ });
2359
+ }
2360
+ async function resolveMcpBindingOrThrow(input) {
2361
+ if (!input.resolver) throw new HephError({
2362
+ code: "HEPH7001",
2363
+ title: "MCP binding resolver is not configured",
2364
+ message: "createHeph({ mcp: { resolver } }) is required before MCP bindings can be resolved.",
2365
+ status: 422,
2366
+ details: {
2367
+ bindingId: input.binding.id,
2368
+ capabilityId: input.binding.capabilityId
2369
+ }
2370
+ });
2371
+ const resolved = await input.resolver.resolve({
2372
+ auth: input.auth,
2373
+ agent: input.agent,
2374
+ binding: input.binding,
2375
+ app: input.app
2376
+ });
2377
+ if (resolved.transport !== "streamable_http") throw new HephError({
2378
+ code: "HEPH7001",
2379
+ title: "Unsupported MCP transport",
2380
+ message: "The MCP MVP supports only Streamable HTTP bindings.",
2381
+ status: 422,
2382
+ details: {
2383
+ bindingId: input.binding.id,
2384
+ transport: resolved.transport
2385
+ }
2386
+ });
2387
+ if (!resolved.endpoint.trim()) throw new HephError({
2388
+ code: "HEPH7001",
2389
+ title: "MCP endpoint is missing",
2390
+ message: "Resolved MCP bindings must include a Streamable HTTP endpoint.",
2391
+ status: 422,
2392
+ details: { bindingId: input.binding.id }
2393
+ });
2394
+ return resolved;
2395
+ }
2396
+ function validateMcpCatalog(binding, resolved) {
2397
+ const toolNames = new Set(resolved.tools.map((tool) => tool.name));
2398
+ if (resolved.tools.filter((tool) => !tool.name.trim()).length > 0) throw new HephError({
2399
+ code: "HEPH7001",
2400
+ title: "MCP tool catalog is invalid",
2401
+ message: "MCP tool catalog entries must include non-empty tool names.",
2402
+ status: 422,
2403
+ details: {
2404
+ bindingId: binding.id,
2405
+ capabilityId: binding.capabilityId
2406
+ }
2407
+ });
2408
+ if (binding.allowTools !== "all") {
2409
+ const unknownTools = binding.allowTools.filter((toolName) => !toolNames.has(toolName));
2410
+ if (unknownTools.length > 0) throw new HephError({
2411
+ code: "HEPH7001",
2412
+ title: "MCP allowTools contains unknown tools",
2413
+ message: "MCP binding allowTools must name tools present in the resolved catalog.",
2414
+ status: 422,
2415
+ details: {
2416
+ bindingId: binding.id,
2417
+ capabilityId: binding.capabilityId,
2418
+ unknownTools
2419
+ }
2420
+ });
2421
+ }
2422
+ }
2423
+ function filterMcpCatalog(binding, resolved) {
2424
+ if (binding.allowTools === "all") return resolved.tools;
2425
+ const allowSet = new Set(binding.allowTools);
2426
+ return resolved.tools.filter((tool) => allowSet.has(tool.name));
2427
+ }
2428
+ function toolSourceRefs(tool, approvalRequestId) {
2429
+ const refs = tool.source === "mcp" ? [{
2430
+ type: "mcp_binding",
2431
+ id: tool.bindingId
2432
+ }] : [];
2433
+ if (approvalRequestId) refs.push({
2434
+ type: "approval_request",
2435
+ id: approvalRequestId
2436
+ });
2437
+ return refs;
2438
+ }
2439
+ function createBuiltInBlocks(input) {
2440
+ return [
2441
+ {
2442
+ key: "runtimePolicy",
2443
+ type: "policy",
2444
+ content: input.runtimePolicy
2445
+ },
2446
+ {
2447
+ key: "agentIdentity",
2448
+ type: "agent_identity",
2449
+ content: input.spec.instructions
2450
+ },
2451
+ {
2452
+ key: "currentTask",
2453
+ type: "input",
2454
+ content: runInputText(input.run.input)
2455
+ },
2456
+ {
2457
+ key: "sessionState",
2458
+ type: "state",
2459
+ content: JSON.stringify(input.agent.state, null, 2)
2460
+ },
2461
+ {
2462
+ key: "skills",
2463
+ type: "skill",
2464
+ content: formatSkillsBlock(input.run.skillManifest),
2465
+ sourceRefs: input.run.skillManifest?.skills.map((skill) => ({
2466
+ type: "skill_binding",
2467
+ id: skill.bindingId
2468
+ })) ?? []
2469
+ },
2470
+ {
2471
+ key: "toolManifest",
2472
+ type: "tool_manifest",
2473
+ content: JSON.stringify(input.run.toolManifest ?? createLocalToolManifest(input.run.id, input.spec.tools), null, 2)
2474
+ }
2475
+ ];
2476
+ }
2477
+ function createLocalToolManifest(runId, tools) {
2478
+ return {
2479
+ runId,
2480
+ tools: tools.map(toLocalManifestTool),
2481
+ createdAt: /* @__PURE__ */ new Date()
2482
+ };
2483
+ }
2484
+ function toLocalManifestTool(tool) {
2485
+ return {
2486
+ id: tool.id,
2487
+ displayName: tool.id,
2488
+ source: "local",
2489
+ localToolId: tool.id,
2490
+ description: tool.description,
2491
+ inputSchema: tool.jsonSchema,
2492
+ sideEffect: tool.sideEffect,
2493
+ requiresApproval: tool.requiresApproval,
2494
+ metadata: {}
2495
+ };
2496
+ }
2497
+ function toMcpManifestTool(binding, tool) {
2498
+ const sideEffect = tool.sideEffect ?? null;
2499
+ return {
2500
+ id: `mcp.${binding.id}.${tool.name}`,
2501
+ displayName: `${binding.capabilityId}.${tool.name}`,
2502
+ source: "mcp",
2503
+ bindingId: binding.id,
2504
+ capabilityId: binding.capabilityId,
2505
+ remoteToolName: tool.name,
2506
+ transport: "streamable_http",
2507
+ description: tool.description ?? "",
2508
+ inputSchema: tool.inputSchema ?? {
2509
+ type: "object",
2510
+ additionalProperties: true
2511
+ },
2512
+ sideEffect,
2513
+ requiresApproval: tool.requiresApproval ?? sideEffect !== false,
2514
+ metadata: tool.metadata ?? {}
2515
+ };
2516
+ }
2517
+ function normalizeRunInput(input) {
2518
+ if (typeof input === "string") return {
2519
+ type: "user.message",
2520
+ text: input
2521
+ };
2522
+ return input;
2523
+ }
2524
+ function renderDeferredToolResultContent(operation) {
2525
+ const lines = [`Deferred tool operation ${operation.id} ${operation.status}.`];
2526
+ lines.push(`- toolId: ${operation.toolId}`);
2527
+ lines.push(`- runId: ${operation.runId}`);
2528
+ if (operation.toolCallId) lines.push(`- toolCallId: ${operation.toolCallId}`);
2529
+ if (operation.error) lines.push(`- error: ${operation.error.message}`);
2530
+ if (operation.result !== null && operation.result !== void 0) lines.push(`- result: ${JSON.stringify(operation.result)}`);
2531
+ return lines.join("\n");
2532
+ }
2533
+ function addMessageIdToRunInput(input, messageId) {
2534
+ return {
2535
+ ...input,
2536
+ messageIds: [...input.messageIds ?? [], messageId]
2537
+ };
2538
+ }
2539
+ function reduceInboxEvents(events, textSeparator) {
2540
+ const messageIds = unique(events.flatMap((event) => event.input.messageIds ?? []));
2541
+ const textEvents = events.filter((event) => "text" in event.input);
2542
+ if (textEvents.length === events.length) {
2543
+ const first = textEvents[0];
2544
+ return {
2545
+ type: first?.input.type === "steering.message" || first?.input.type === "follow_up.message" ? first.input.type : "user.message",
2546
+ text: textEvents.map((event) => "text" in event.input ? event.input.text : "").join(textSeparator),
2547
+ messageIds,
2548
+ payload: {
2549
+ inboxEventIds: events.map((event) => event.id),
2550
+ reducedInboxEvents: events.map(toReducedInboxEvent)
2551
+ }
2552
+ };
2553
+ }
2554
+ if (events.length === 1) return {
2555
+ ...events[0].input,
2556
+ messageIds,
2557
+ payload: {
2558
+ ...typeof events[0].input.payload === "object" && events[0].input.payload !== null ? events[0].input.payload : {},
2559
+ reducedInboxEvents: events.map(toReducedInboxEvent)
2560
+ }
2561
+ };
2562
+ return {
2563
+ type: "system.event",
2564
+ messageIds,
2565
+ payload: {
2566
+ inboxEvents: events.map((event) => ({
2567
+ id: event.id,
2568
+ type: event.type,
2569
+ input: event.input
2570
+ })),
2571
+ reducedInboxEvents: events.map(toReducedInboxEvent)
2572
+ }
2573
+ };
2574
+ }
2575
+ function normalizeMaxEventsPerRun(value) {
2576
+ if (value === null) return;
2577
+ if (value === void 0) return 20;
2578
+ if (!Number.isFinite(value) || value < 1) throw new HephError({
2579
+ code: "HEPH4006",
2580
+ title: "Invalid inbox reducer configuration",
2581
+ message: "inbox.maxEventsPerRun must be a positive number or null.",
2582
+ status: 422,
2583
+ details: { maxEventsPerRun: value }
2584
+ });
2585
+ return Math.floor(value);
2586
+ }
2587
+ function toReducedInboxEvent(event) {
2588
+ const input = event.input;
2589
+ return {
2590
+ inboxEventId: event.id,
2591
+ type: event.type,
2592
+ messageIds: input.messageIds ?? [],
2593
+ text: "text" in input ? input.text : null
2594
+ };
2595
+ }
2596
+ function firstAuth(events) {
2597
+ return events.find((event) => event.auth !== null)?.auth ?? null;
2598
+ }
2599
+ function toInboxSourceRefs(events) {
2600
+ return events.map((event) => ({
2601
+ type: "inbox_event",
2602
+ id: event.id
2603
+ }));
2604
+ }
2605
+ function toRunError(error) {
2606
+ const runError = {
2607
+ message: error instanceof Error ? error.message : String(error),
2608
+ details: toErrorDetails(error)
2609
+ };
2610
+ if (error instanceof HephError) runError.code = error.code;
2611
+ return runError;
2612
+ }
2613
+ function shouldRethrowToolCallAttemptError(error) {
2614
+ if (!(error instanceof HephError)) return false;
2615
+ return error.code === "HEPH3002" || error.code === "HEPH3003" || error.code === "HEPH3004";
2616
+ }
2617
+ function isTerminalRun(run) {
2618
+ return run.status === "completed" || run.status === "failed" || run.status === "cancelled";
2619
+ }
2620
+ function unique(values) {
2621
+ return Array.from(new Set(values));
2622
+ }
2623
+ function runInputText(input) {
2624
+ return "text" in input ? input.text : JSON.stringify(input.payload ?? {});
2625
+ }
2626
+ function formatSkillsBlock(manifest) {
2627
+ if (!manifest || manifest.skills.length === 0) return "";
2628
+ return manifest.skills.map((skill) => {
2629
+ const version = skill.version ? `@${skill.version}` : "";
2630
+ const referenceLines = skill.availableReferences.length === 0 ? "" : `\nAvailable references:\n${skill.availableReferences.map((ref) => `- ${ref.id}: ${ref.pathOrRef}`).join("\n")}`;
2631
+ return `# ${skill.name}${version}\n\nDescription: ${skill.description}\n\nInstructions:\n${skill.instructions}${referenceLines}`;
2632
+ }).join("\n\n---\n\n");
2633
+ }
2634
+ function filterSkillReferences(references, allowReferences) {
2635
+ if (allowReferences === "all") return references.map(cloneSkillResourceRef);
2636
+ const allowSet = new Set(allowReferences);
2637
+ return references.filter((reference) => allowSet.has(reference.id)).map(cloneSkillResourceRef);
2638
+ }
2639
+ function cloneSkillResourceRef(ref) {
2640
+ return {
2641
+ ...ref,
2642
+ metadata: { ...ref.metadata }
2643
+ };
2644
+ }
2645
+ async function sha256Text(value) {
2646
+ const bytes = new TextEncoder().encode(value);
2647
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
2648
+ return `sha256:${Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
2649
+ }
2650
+ function parseMcpResponseBody(body, contentType) {
2651
+ const trimmed = body.trim();
2652
+ if (!trimmed) return null;
2653
+ if (contentType?.includes("text/event-stream")) {
2654
+ const lastData = trimmed.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).filter((line) => line && line !== "[DONE]").at(-1);
2655
+ if (!lastData) return null;
2656
+ try {
2657
+ return JSON.parse(lastData);
2658
+ } catch {
2659
+ return lastData;
2660
+ }
2661
+ }
2662
+ try {
2663
+ return JSON.parse(trimmed);
2664
+ } catch {
2665
+ return trimmed;
2666
+ }
2667
+ }
2668
+ function isJsonRpcError(value) {
2669
+ return isRecord(value) && "error" in value && value.error !== void 0 && value.error !== null;
2670
+ }
2671
+ function isRecord(value) {
2672
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2673
+ }
2674
+ //#endregion
2675
+ export { ContextRenderer as A, ContextProvider as C, defineContextProvider as D, defineAgent as E, isHephError as F, toErrorDetails as I, estimateTokens as M, messagesToText as N, defineContextTemplate as O, HephError as P, AgentSpec as S, Tool as T, createMessageId as _, InProcessQueue as a, createSkillBindingId as b, recentMessages as c, createApprovalRequestId as d, createDeferredToolOperationId as f, createMemoryId as g, createMcpBindingId as h, createInMemorySkillCatalog as i, defaultContextTemplate as j, defineTool as k, threadState as l, createInboxEventId as m, createHeph as n, block as o, createId as p, InMemoryHephStore as r, memorySearch as s, StreamableHttpMcpToolExecutor as t, createAgentSessionId as u, createRunEventId as v, ContextTemplate as w, MinimalRunExecutor as x, createRunId as y };
2676
+
2677
+ //# sourceMappingURL=src-DeheByi4.mjs.map