agentenkit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -0
  3. package/dist/adapters/inline.d.ts +27 -0
  4. package/dist/adapters/inline.d.ts.map +1 -0
  5. package/dist/adapters/inline.js +41 -0
  6. package/dist/adapters/inline.js.map +1 -0
  7. package/dist/adapters/memory.d.ts +74 -0
  8. package/dist/adapters/memory.d.ts.map +1 -0
  9. package/dist/adapters/memory.js +194 -0
  10. package/dist/adapters/memory.js.map +1 -0
  11. package/dist/adapters/prisma.d.ts +176 -0
  12. package/dist/adapters/prisma.d.ts.map +1 -0
  13. package/dist/adapters/prisma.js +107 -0
  14. package/dist/adapters/prisma.js.map +1 -0
  15. package/dist/adapters/qstash.d.ts +36 -0
  16. package/dist/adapters/qstash.d.ts.map +1 -0
  17. package/dist/adapters/qstash.js +26 -0
  18. package/dist/adapters/qstash.js.map +1 -0
  19. package/dist/adapters/redis.d.ts +49 -0
  20. package/dist/adapters/redis.d.ts.map +1 -0
  21. package/dist/adapters/redis.js +60 -0
  22. package/dist/adapters/redis.js.map +1 -0
  23. package/dist/adapters/sqlite.d.ts +67 -0
  24. package/dist/adapters/sqlite.d.ts.map +1 -0
  25. package/dist/adapters/sqlite.js +199 -0
  26. package/dist/adapters/sqlite.js.map +1 -0
  27. package/dist/adapters/upstash.d.ts +48 -0
  28. package/dist/adapters/upstash.d.ts.map +1 -0
  29. package/dist/adapters/upstash.js +46 -0
  30. package/dist/adapters/upstash.js.map +1 -0
  31. package/dist/admin/default.d.ts +15 -0
  32. package/dist/admin/default.d.ts.map +1 -0
  33. package/dist/admin/default.js +22 -0
  34. package/dist/admin/default.js.map +1 -0
  35. package/dist/admin/memory.d.ts +29 -0
  36. package/dist/admin/memory.d.ts.map +1 -0
  37. package/dist/admin/memory.js +83 -0
  38. package/dist/admin/memory.js.map +1 -0
  39. package/dist/admin/postgres.d.ts +43 -0
  40. package/dist/admin/postgres.d.ts.map +1 -0
  41. package/dist/admin/postgres.js +201 -0
  42. package/dist/admin/postgres.js.map +1 -0
  43. package/dist/admin/sqlite.d.ts +35 -0
  44. package/dist/admin/sqlite.d.ts.map +1 -0
  45. package/dist/admin/sqlite.js +187 -0
  46. package/dist/admin/sqlite.js.map +1 -0
  47. package/dist/core/admin.d.ts +88 -0
  48. package/dist/core/admin.d.ts.map +1 -0
  49. package/dist/core/admin.js +147 -0
  50. package/dist/core/admin.js.map +1 -0
  51. package/dist/core/agent.d.ts +29 -0
  52. package/dist/core/agent.d.ts.map +1 -0
  53. package/dist/core/agent.js +41 -0
  54. package/dist/core/agent.js.map +1 -0
  55. package/dist/core/cache.d.ts +37 -0
  56. package/dist/core/cache.d.ts.map +1 -0
  57. package/dist/core/cache.js +68 -0
  58. package/dist/core/cache.js.map +1 -0
  59. package/dist/core/context.d.ts +13 -0
  60. package/dist/core/context.d.ts.map +1 -0
  61. package/dist/core/context.js +87 -0
  62. package/dist/core/context.js.map +1 -0
  63. package/dist/core/deleteThread.d.ts +14 -0
  64. package/dist/core/deleteThread.d.ts.map +1 -0
  65. package/dist/core/deleteThread.js +34 -0
  66. package/dist/core/deleteThread.js.map +1 -0
  67. package/dist/core/engine.d.ts +79 -0
  68. package/dist/core/engine.d.ts.map +1 -0
  69. package/dist/core/engine.js +489 -0
  70. package/dist/core/engine.js.map +1 -0
  71. package/dist/core/follow.d.ts +50 -0
  72. package/dist/core/follow.d.ts.map +1 -0
  73. package/dist/core/follow.js +153 -0
  74. package/dist/core/follow.js.map +1 -0
  75. package/dist/core/hitl.d.ts +98 -0
  76. package/dist/core/hitl.d.ts.map +1 -0
  77. package/dist/core/hitl.js +199 -0
  78. package/dist/core/hitl.js.map +1 -0
  79. package/dist/core/keys.d.ts +26 -0
  80. package/dist/core/keys.d.ts.map +1 -0
  81. package/dist/core/keys.js +32 -0
  82. package/dist/core/keys.js.map +1 -0
  83. package/dist/core/loop.d.ts +105 -0
  84. package/dist/core/loop.d.ts.map +1 -0
  85. package/dist/core/loop.js +234 -0
  86. package/dist/core/loop.js.map +1 -0
  87. package/dist/core/publish.d.ts +18 -0
  88. package/dist/core/publish.d.ts.map +1 -0
  89. package/dist/core/publish.js +34 -0
  90. package/dist/core/publish.js.map +1 -0
  91. package/dist/core/reclaim.d.ts +20 -0
  92. package/dist/core/reclaim.d.ts.map +1 -0
  93. package/dist/core/reclaim.js +56 -0
  94. package/dist/core/reclaim.js.map +1 -0
  95. package/dist/core/run.d.ts +8 -0
  96. package/dist/core/run.d.ts.map +1 -0
  97. package/dist/core/run.js +102 -0
  98. package/dist/core/run.js.map +1 -0
  99. package/dist/core/state.d.ts +50 -0
  100. package/dist/core/state.d.ts.map +1 -0
  101. package/dist/core/state.js +39 -0
  102. package/dist/core/state.js.map +1 -0
  103. package/dist/core/stop.d.ts +7 -0
  104. package/dist/core/stop.d.ts.map +1 -0
  105. package/dist/core/stop.js +15 -0
  106. package/dist/core/stop.js.map +1 -0
  107. package/dist/core/stream.d.ts +12 -0
  108. package/dist/core/stream.d.ts.map +1 -0
  109. package/dist/core/stream.js +21 -0
  110. package/dist/core/stream.js.map +1 -0
  111. package/dist/core/subagent.d.ts +77 -0
  112. package/dist/core/subagent.d.ts.map +1 -0
  113. package/dist/core/subagent.js +261 -0
  114. package/dist/core/subagent.js.map +1 -0
  115. package/dist/core/tools.d.ts +36 -0
  116. package/dist/core/tools.d.ts.map +1 -0
  117. package/dist/core/tools.js +22 -0
  118. package/dist/core/tools.js.map +1 -0
  119. package/dist/core/types.d.ts +286 -0
  120. package/dist/core/types.d.ts.map +1 -0
  121. package/dist/core/types.js +49 -0
  122. package/dist/core/types.js.map +1 -0
  123. package/dist/core/usage.d.ts +40 -0
  124. package/dist/core/usage.d.ts.map +1 -0
  125. package/dist/core/usage.js +43 -0
  126. package/dist/core/usage.js.map +1 -0
  127. package/dist/index.d.ts +25 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +23 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/ports/admin.d.ts +102 -0
  132. package/dist/ports/admin.d.ts.map +1 -0
  133. package/dist/ports/admin.js +2 -0
  134. package/dist/ports/admin.js.map +1 -0
  135. package/dist/ports/bus.d.ts +13 -0
  136. package/dist/ports/bus.d.ts.map +1 -0
  137. package/dist/ports/bus.js +2 -0
  138. package/dist/ports/bus.js.map +1 -0
  139. package/dist/ports/kv.d.ts +16 -0
  140. package/dist/ports/kv.d.ts.map +1 -0
  141. package/dist/ports/kv.js +2 -0
  142. package/dist/ports/kv.js.map +1 -0
  143. package/dist/ports/queue.d.ts +18 -0
  144. package/dist/ports/queue.d.ts.map +1 -0
  145. package/dist/ports/queue.js +2 -0
  146. package/dist/ports/queue.js.map +1 -0
  147. package/dist/ports/runtime.d.ts +260 -0
  148. package/dist/ports/runtime.d.ts.map +1 -0
  149. package/dist/ports/runtime.js +2 -0
  150. package/dist/ports/runtime.js.map +1 -0
  151. package/dist/ports/storage.d.ts +72 -0
  152. package/dist/ports/storage.d.ts.map +1 -0
  153. package/dist/ports/storage.js +2 -0
  154. package/dist/ports/storage.js.map +1 -0
  155. package/dist/runtime.d.ts +5 -0
  156. package/dist/runtime.d.ts.map +1 -0
  157. package/dist/runtime.js +177 -0
  158. package/dist/runtime.js.map +1 -0
  159. package/package.json +126 -0
@@ -0,0 +1,7 @@
1
+ import type { RuntimePorts } from '../ports/runtime.js';
2
+ import type { StopResult } from '../ports/runtime.js';
3
+ /** The whole stop mechanism (§2.1): one button, one behavior — everything
4
+ * stops immediately. The engine's poller sees CANCELLED on the hot cache and
5
+ * fires the abort; the durable state is the recovery truth (§3.4). */
6
+ export declare function stop(deps: RuntimePorts, threadId: string): Promise<StopResult>;
7
+ //# sourceMappingURL=stop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/core/stop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;uEAEuE;AACvE,wBAAsB,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAWpF"}
@@ -0,0 +1,15 @@
1
+ import { publish, setThreadState } from './publish.js';
2
+ /** The whole stop mechanism (§2.1): one button, one behavior — everything
3
+ * stops immediately. The engine's poller sees CANCELLED on the hot cache and
4
+ * fires the abort; the durable state is the recovery truth (§3.4). */
5
+ export async function stop(deps, threadId) {
6
+ const thread = await deps.storage.threads.get(threadId);
7
+ if (thread?.state !== 'RUNNING' && thread?.state !== 'WAITING_FOR_INPUT') {
8
+ return { accepted: false, error: `Cannot stop thread in state ${thread?.state ?? 'unknown'}` };
9
+ }
10
+ await deps.kv.set(`agent:state:${threadId}`, 'CANCELLED');
11
+ await setThreadState(deps, threadId, 'CANCELLED', thread.model);
12
+ await publish(deps, threadId, 'STATE_CHANGE', { state: 'CANCELLED' });
13
+ return { accepted: true };
14
+ }
15
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/core/stop.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGvD;;uEAEuE;AACvE,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAkB,EAAE,QAAgB;IAC7D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,MAAM,EAAE,KAAK,KAAK,SAAS,IAAI,MAAM,EAAE,KAAK,KAAK,mBAAmB,EAAE,CAAC;QACzE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,MAAM,EAAE,KAAK,IAAI,SAAS,EAAE,EAAE,CAAC;IACjG,CAAC;IAED,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,eAAe,QAAQ,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1D,MAAM,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IAEtE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,12 @@
1
+ /** Drain a `streamText` result, turning a provider failure into a throw.
2
+ *
3
+ * streamText reports a failure — an aborted call included — as an `error`
4
+ * part and then ends the stream NORMALLY, while its `text`/`usage`/`response`
5
+ * promises never settle. Awaiting those without rethrowing hangs the caller
6
+ * forever, still holding whatever it owns: for a run segment that is the
7
+ * thread's run lock, which wedges every later message on the thread.
8
+ *
9
+ * Draining fully first also means `onChunk` fires for every part that did
10
+ * arrive before the failure. */
11
+ export declare function drainOrThrow(fullStream: AsyncIterable<unknown>): Promise<void>;
12
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/core/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;iCASiC;AACjC,wBAAsB,YAAY,CAAC,UAAU,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpF"}
@@ -0,0 +1,21 @@
1
+ /** Drain a `streamText` result, turning a provider failure into a throw.
2
+ *
3
+ * streamText reports a failure — an aborted call included — as an `error`
4
+ * part and then ends the stream NORMALLY, while its `text`/`usage`/`response`
5
+ * promises never settle. Awaiting those without rethrowing hangs the caller
6
+ * forever, still holding whatever it owns: for a run segment that is the
7
+ * thread's run lock, which wedges every later message on the thread.
8
+ *
9
+ * Draining fully first also means `onChunk` fires for every part that did
10
+ * arrive before the failure. */
11
+ export async function drainOrThrow(fullStream) {
12
+ let streamError;
13
+ for await (const part of fullStream) {
14
+ if (part?.type === 'error' && streamError === undefined) {
15
+ streamError = part.error;
16
+ }
17
+ }
18
+ if (streamError !== undefined)
19
+ throw streamError;
20
+ }
21
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/core/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;iCASiC;AACjC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAkC;IACnE,IAAI,WAAoB,CAAC;IACzB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QACpC,IAAK,IAAiC,EAAE,IAAI,KAAK,OAAO,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YACtF,WAAW,GAAI,IAA4B,CAAC,KAAK,CAAC;QACpD,CAAC;IACH,CAAC;IACD,IAAI,WAAW,KAAK,SAAS;QAAE,MAAM,WAAW,CAAC;AACnD,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { z } from 'zod';
2
+ import type { NestedDescriptor, ProviderOptions, ResumeInfo, SubagentsConfig } from './types.js';
3
+ import type { RuntimePorts } from '../ports/runtime.js';
4
+ import type { RegisteredAgent } from './agent.js';
5
+ import { type HitlFrame } from './hitl.js';
6
+ import { type AgentRunState } from './state.js';
7
+ import { type LoopOutcome, type RunLedger } from './loop.js';
8
+ /** Everything a nested run needs from the run that spawned it (§2.7). The
9
+ * thread, lock, run id, abort signal and token ledger are the parent's; the
10
+ * message stream, step ceiling and toolset are the child's own. */
11
+ export interface SubagentCtx {
12
+ threadId: string;
13
+ depth: number;
14
+ sem: Semaphore;
15
+ ports: RuntimePorts;
16
+ /** Delegation config carried from the parent's spec (§2.7): flavor,
17
+ * default model, and extra tools for every spawned child. */
18
+ sub: SubagentsConfig;
19
+ /** The registered agent whose generation args every nested run inherits
20
+ * (§3.1) — its `system` and `tools` are overridden per child. */
21
+ agent: RegisteredAgent;
22
+ /** The run-wide token ledger (§2.7): a child's spend counts against the
23
+ * same safety cap the main agent is checked against. */
24
+ ledger: RunLedger;
25
+ /** Dispatch ticket persisted with any park raised beneath here (§2.5). */
26
+ resume: ResumeInfo;
27
+ /** The stream this spawner writes to — `null` when it is the main agent. */
28
+ agentId: string | null;
29
+ /** Calls already waiting on an approval above this level, innermost first. */
30
+ frames: HitlFrame[];
31
+ /** This spawner's own descriptor — absent when it is the main agent. Goes
32
+ * onto the frame it pushes, so an unwind can re-enter it (§2.7). */
33
+ descriptor?: NestedDescriptor;
34
+ tokenBudget?: number;
35
+ providerOptions?: ProviderOptions;
36
+ abortSignal?: AbortSignal;
37
+ /** The run's state, handed down unchanged (§2.10). */
38
+ state?: AgentRunState;
39
+ }
40
+ /** Run-scoped semaphore: sibling subagents queue instead of running away (§2.7) */
41
+ export declare class Semaphore {
42
+ private readonly limit;
43
+ private active;
44
+ private waiters;
45
+ constructor(limit: number);
46
+ acquire(): Promise<() => void>;
47
+ }
48
+ export declare function spawnSubagentTool(ctx: SubagentCtx): import("ai").Tool<z.ZodObject<{
49
+ name: z.ZodString;
50
+ instructions: z.ZodString;
51
+ model: z.ZodOptional<z.ZodString>;
52
+ }, "strip", z.ZodTypeAny, {
53
+ name: string;
54
+ instructions: string;
55
+ model?: string | undefined;
56
+ }, {
57
+ name: string;
58
+ instructions: string;
59
+ model?: string | undefined;
60
+ }>, any> & {
61
+ execute: (args: {
62
+ name: string;
63
+ instructions: string;
64
+ model?: string | undefined;
65
+ }, options: import("ai").ToolExecutionOptions) => PromiseLike<any>;
66
+ };
67
+ /** Run — or RE-ENTER — a nested agent (§2.7).
68
+ *
69
+ * Its turns live in the thread's message log under its own `agentId`, so a
70
+ * child that parked is resumed from exactly where it stopped rather than
71
+ * replayed from its brief. Replaying an LLM call is not a safe substitute:
72
+ * the model can take a different path and never make the call the human
73
+ * approved, and it re-pays for everything before the park. */
74
+ export declare function runNestedAgent(ctx: SubagentCtx, d: NestedDescriptor,
75
+ /** Seeds the stream on first entry; ignored once the child has turns. */
76
+ instructions: string | null, abortSignal: AbortSignal | undefined, frames: HitlFrame[]): Promise<LoopOutcome>;
77
+ //# sourceMappingURL=subagent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../src/core/subagent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,UAAU,EAEV,eAAe,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAE9D,OAAO,EAAW,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtE;;oEAEoE;AACpE,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,SAAS,CAAC;IACf,KAAK,EAAE,YAAY,CAAC;IACpB;kEAC8D;IAC9D,GAAG,EAAE,eAAe,CAAC;IACrB;sEACkE;IAClE,KAAK,EAAE,eAAe,CAAC;IACvB;6DACyD;IACzD,MAAM,EAAE,SAAS,CAAC;IAClB,0EAA0E;IAC1E,MAAM,EAAE,UAAU,CAAC;IACnB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,8EAA8E;IAC9E,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB;yEACqE;IACrE,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,sDAAsD;IACtD,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,mFAAmF;AACnF,qBAAa,SAAS;IAGR,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAsB;gBACR,KAAK,EAAE,MAAM;IAEpC,OAAO,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;CAoBrC;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW;;;;;;;;;;;;;;;;;;EAyHjD;AA+ED;;;;;;+DAM+D;AAC/D,wBAAsB,cAAc,CAClC,GAAG,EAAE,WAAW,EAChB,CAAC,EAAE,gBAAgB;AACnB,yEAAyE;AACzE,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,WAAW,EAAE,WAAW,GAAG,SAAS,EACpC,MAAM,EAAE,SAAS,EAAE,GAClB,OAAO,CAAC,WAAW,CAAC,CA0DtB"}
@@ -0,0 +1,261 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { tool } from 'ai';
3
+ import { z } from 'zod';
4
+ import { publish } from './publish.js';
5
+ import { HITL_PARKED, withHitl } from './hitl.js';
6
+ import { withRunState } from './state.js';
7
+ import { markPromptCaching } from './cache.js';
8
+ import { runLoop } from './loop.js';
9
+ /** Run-scoped semaphore: sibling subagents queue instead of running away (§2.7) */
10
+ export class Semaphore {
11
+ limit;
12
+ active = 0;
13
+ waiters = [];
14
+ constructor(limit) {
15
+ this.limit = limit;
16
+ }
17
+ async acquire() {
18
+ await new Promise((resolve) => {
19
+ if (this.active < this.limit) {
20
+ this.active++;
21
+ resolve();
22
+ }
23
+ else {
24
+ this.waiters.push(() => {
25
+ this.active++;
26
+ resolve();
27
+ });
28
+ }
29
+ });
30
+ let released = false;
31
+ return () => {
32
+ if (released)
33
+ return;
34
+ released = true;
35
+ this.active--;
36
+ this.waiters.shift()?.();
37
+ };
38
+ }
39
+ }
40
+ export function spawnSubagentTool(ctx) {
41
+ return tool({
42
+ description: 'Delegates a self-contained task to a subagent with an isolated context',
43
+ parameters: z.object({
44
+ name: z.string().describe('Short name for the sub-task'),
45
+ instructions: z
46
+ .string()
47
+ .describe('Complete, self-contained brief: goal, constraints, expected output format'),
48
+ model: z.string().optional(),
49
+ }),
50
+ execute: async (args, opts) => {
51
+ const { name, instructions, model } = args;
52
+ const depth = ctx.depth + 1;
53
+ if (depth > ctx.ports.config.subagentMaxDepth) {
54
+ return { error: `Max subagent depth (${ctx.ports.config.subagentMaxDepth}) reached` };
55
+ }
56
+ const release = await ctx.sem.acquire();
57
+ try {
58
+ // A nested run is a run (§2.9): same table, distinguished by depth and
59
+ // a parent. Its id is also the agentId its messages and events carry.
60
+ const run = await ctx.ports.admin.runs.start({
61
+ id: randomUUID(),
62
+ threadId: ctx.threadId,
63
+ // The spawner: another nested run, or the dispatched run itself.
64
+ parentRunId: ctx.agentId ?? ctx.resume.runId ?? null,
65
+ depth,
66
+ agent: name,
67
+ model: model ?? ctx.sub.model ?? 'gpt-4o',
68
+ // A nested run's "prompt" is the brief it was delegated (§2.7).
69
+ ...(ctx.ports.config.recordPayloads
70
+ ? {
71
+ prompt: instructions.length > ctx.ports.config.payloadCapChars
72
+ ? `${instructions.slice(0, ctx.ports.config.payloadCapChars)}…`
73
+ : instructions,
74
+ runState: ctx.state ?? null,
75
+ }
76
+ : {}),
77
+ });
78
+ await publish(ctx.ports, ctx.threadId, 'SUBAGENT_STARTED', {
79
+ agentId: run.id, name, depth,
80
+ });
81
+ const descriptor = {
82
+ agentId: run.id,
83
+ name,
84
+ model: model ?? ctx.sub.model ?? 'gpt-4o',
85
+ depth,
86
+ };
87
+ try {
88
+ const outcome = await runNestedAgent(ctx, descriptor, instructions, opts.abortSignal ?? ctx.abortSignal,
89
+ // This call is now the innermost thing waiting on any approval the
90
+ // child raises (§2.7).
91
+ [
92
+ {
93
+ agentId: ctx.agentId,
94
+ toolCallId: opts.toolCallId ?? run.id,
95
+ ...(ctx.descriptor ? { nested: ctx.descriptor } : {}),
96
+ },
97
+ ...ctx.frames,
98
+ ]);
99
+ if (outcome.parked) {
100
+ // The child is suspended, not finished: leave its SubagentRun
101
+ // RUNNING and hand the parent the sentinel so its segment ends
102
+ // too (§2.5). The child is re-entered on approval, from its own
103
+ // persisted turns — it never restarts.
104
+ return { [HITL_PARKED]: opts.toolCallId ?? run.id };
105
+ }
106
+ await closeNested(ctx, run, outcome, {
107
+ state: 'COMPLETED',
108
+ result: { text: outcome.text },
109
+ });
110
+ await publish(ctx.ports, ctx.threadId, 'SUBAGENT_COMPLETED', { agentId: run.id });
111
+ // The parent receives a capped result, keeping its own context small (§2.6)
112
+ return {
113
+ agentId: run.id,
114
+ result: outcome.text.slice(0, ctx.ports.config.subagentResultCapChars),
115
+ };
116
+ }
117
+ catch (err) {
118
+ const cancelled = (await ctx.ports.kv.get(`agent:state:${ctx.threadId}`)) === 'CANCELLED';
119
+ const state = cancelled ? 'CANCELLED' : 'FAILED';
120
+ const message = err instanceof Error ? err.message : String(err);
121
+ await closeNested(ctx, run, null, { state, error: message });
122
+ // Carry the reason: a bare state tells an operator a child died but
123
+ // not why, and a nested run's failure is otherwise invisible.
124
+ await publish(ctx.ports, ctx.threadId, 'SUBAGENT_FAILED', {
125
+ agentId: run.id,
126
+ state,
127
+ error: message,
128
+ });
129
+ // A user stop tears the whole run down (§2.1), so that one keeps
130
+ // propagating.
131
+ if (cancelled)
132
+ throw err;
133
+ // Anything else is reported TO THE PARENT as the delegation's
134
+ // result, the same way an approved tool's failure is reported to the
135
+ // model rather than thrown (§2.5): a delegated task that went wrong
136
+ // is news the agent can act on — retry, try another way, tell the
137
+ // user — not a reason to kill the run it was part of.
138
+ return { agentId: run.id, error: message };
139
+ }
140
+ }
141
+ finally {
142
+ release();
143
+ }
144
+ },
145
+ });
146
+ }
147
+ /** Close a nested run's record with the same detail a dispatched run gets
148
+ * (§2.9): how it ended, how long it took, what it cost. */
149
+ /** Stamp a nested run's prompt when caching is on, exactly as the main path
150
+ * does. */
151
+ function maybeCache(ports, messages) {
152
+ return ports.config.promptCaching ? markPromptCaching(messages) : messages;
153
+ }
154
+ async function closeNested(ctx, run, outcome, end) {
155
+ const endedAt = new Date();
156
+ await ctx.ports.admin.runs.patch(run.id, {
157
+ ...end,
158
+ endedAt,
159
+ durationMs: endedAt.getTime() - new Date(run.startedAt).getTime(),
160
+ ...(outcome
161
+ ? {
162
+ steps: outcome.steps,
163
+ inputTokens: outcome.attribution.inputTokens,
164
+ cachedInputTokens: outcome.attribution.cachedInputTokens,
165
+ outputTokens: outcome.attribution.outputTokens,
166
+ totalTokens: outcome.attribution.totalTokens,
167
+ }
168
+ : {}),
169
+ });
170
+ }
171
+ /** The toolset a nested run sees (§2.7): the delegation config's extra tools,
172
+ * HITL-wrapped exactly like the parent's, plus nesting while depth allows.
173
+ * Default is `spawnSubagent` alone — destructive tools reach a child only
174
+ * when a workflow grants them. */
175
+ function nestedTools(ctx, d, frames, abortSignal) {
176
+ const raw = {
177
+ ...(ctx.sub.tools ?? {}),
178
+ spawnSubagent: spawnSubagentTool({
179
+ ...ctx,
180
+ depth: d.depth,
181
+ agentId: d.agentId,
182
+ frames,
183
+ descriptor: d,
184
+ abortSignal,
185
+ }),
186
+ };
187
+ // A nested run's tools see the same state as its parent's (§2.10).
188
+ return withRunState(withHitl(ctx.ports, ctx.threadId, raw, {
189
+ resume: ctx.resume,
190
+ agentId: d.agentId,
191
+ frames,
192
+ nested: d,
193
+ }), ctx.state ?? {});
194
+ }
195
+ /** The delegation tool lets the MODEL name the child's model, so an unknown
196
+ * registry key is ordinary bad input rather than a failure. `resolveModel`
197
+ * throws on one (§3.3) — a `||` fallback can never catch that — so the child
198
+ * falls back to the model its parent is already running on, which is
199
+ * resolvable by construction. */
200
+ function resolveNestedModel(ctx, name) {
201
+ try {
202
+ return ctx.ports.resolveModel(name);
203
+ }
204
+ catch {
205
+ return ctx.ports.resolveModel(ctx.resume.model);
206
+ }
207
+ }
208
+ /** Run — or RE-ENTER — a nested agent (§2.7).
209
+ *
210
+ * Its turns live in the thread's message log under its own `agentId`, so a
211
+ * child that parked is resumed from exactly where it stopped rather than
212
+ * replayed from its brief. Replaying an LLM call is not a safe substitute:
213
+ * the model can take a different path and never make the call the human
214
+ * approved, and it re-pays for everything before the park. */
215
+ export async function runNestedAgent(ctx, d,
216
+ /** Seeds the stream on first entry; ignored once the child has turns. */
217
+ instructions, abortSignal, frames) {
218
+ const { ports, threadId } = ctx;
219
+ const persisted = await ports.storage.messages.list(threadId, { agentId: d.agentId });
220
+ if (persisted.length === 0) {
221
+ if (instructions === null) {
222
+ throw new Error(`Nested run ${d.agentId} has no turns and no brief to seed from`);
223
+ }
224
+ // Isolated context (§2.7): the brief is the only input — parent history
225
+ // is never forwarded.
226
+ persisted.push(await ports.storage.messages.append(threadId, {
227
+ role: 'user',
228
+ content: instructions,
229
+ agentId: d.agentId,
230
+ }));
231
+ }
232
+ const outcome = await runLoop(ports, ctx.agent, threadId, {
233
+ agentId: d.agentId,
234
+ // Its OWN run id, not its parent's: a nested run is a run (§2.7, §2.9),
235
+ // so its steps belong to its own record. Attributing them upward mixed
236
+ // two agents' steps into one timeline and made the indexes collide.
237
+ runId: d.agentId,
238
+ kind: ctx.sub.kind ?? 'stream-text',
239
+ model: resolveNestedModel(ctx, d.model).instance(),
240
+ // Stamped like the parent's (§2.6). A nested run re-sends its whole
241
+ // brief and history on every step, so it is exactly the shape caching
242
+ // is for — it was the one prompt in the system going out unstamped.
243
+ messages: maybeCache(ports, persisted.map((m) => ({ role: m.role, content: m.content }))),
244
+ tools: nestedTools(ctx, d, frames, abortSignal),
245
+ maxSteps: ports.config.subagentMaxSteps,
246
+ abortSignal: abortSignal ?? new AbortController().signal,
247
+ providerOptions: ctx.providerOptions,
248
+ tokenBudget: ctx.tokenBudget,
249
+ system: `You are the "${d.name}" subagent. Complete the task, then stop.`,
250
+ cacheSystemPrompt: ports.config.promptCaching,
251
+ onChunk: async (chunk) => {
252
+ // Namespaced into the shared thread event log → same multi-user pipeline (§2.2)
253
+ await publish(ports, threadId, 'SUBAGENT_CHUNK', { agentId: d.agentId, chunk });
254
+ },
255
+ }, ctx.ledger);
256
+ // Billing attribution per subagent (§4); the run-wide ledger was already
257
+ // advanced inside the loop.
258
+ await ports.storage.usage.record(threadId, { agentId: d.agentId, ...outcome.attribution });
259
+ return outcome;
260
+ }
261
+ //# sourceMappingURL=subagent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent.js","sourceRoot":"","sources":["../../src/core/subagent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type ToolExecutionOptions } from 'ai';
2
+ import type { z } from 'zod';
3
+ import type { AgentRunState } from './state.js';
4
+ /** What a tool's `execute` actually receives: the AI SDK's own options, plus
5
+ * the run's state (§2.10).
6
+ *
7
+ * The platform injects `state` at call time, but the SDK's own
8
+ * `ToolExecutionOptions` has no field for it — and a plain `tool()` cannot be
9
+ * told about it, because narrowing the options parameter is rejected as
10
+ * unsound. Hence `agentTool`. */
11
+ export interface ToolContext extends ToolExecutionOptions {
12
+ /** Whatever the caller attached to this run. Present for every tool of every
13
+ * run, including a nested one and a segment resumed after an approval. */
14
+ state: AgentRunState;
15
+ }
16
+ /** `tool()` with the run state typed.
17
+ *
18
+ * ```ts
19
+ * const lookupInvoice = agentTool({
20
+ * description: 'Find one invoice',
21
+ * parameters: z.object({ invoiceId: z.string() }),
22
+ * execute: async ({ invoiceId }, { state }) =>
23
+ * db.invoice.findFirst({ where: { id: invoiceId, orgId: state.orgId } }),
24
+ * });
25
+ * ```
26
+ *
27
+ * The result is an ordinary AI SDK tool — it composes with
28
+ * `markRequiresConfirmation` and can be passed anywhere `tool()` can. */
29
+ export declare function agentTool<PARAMETERS extends z.ZodTypeAny, RESULT>(spec: {
30
+ description?: string;
31
+ parameters: PARAMETERS;
32
+ execute: (args: z.infer<PARAMETERS>, ctx: ToolContext) => PromiseLike<RESULT>;
33
+ }): import("ai").Tool<PARAMETERS, RESULT> & {
34
+ execute: (args: PARAMETERS extends import("ai").Schema<any> ? PARAMETERS["_type"] : PARAMETERS extends z.ZodTypeAny ? z.TypeOf<PARAMETERS> : never, options: ToolExecutionOptions) => PromiseLike<RESULT>;
35
+ };
36
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/core/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,oBAAoB,EAAE,MAAM,IAAI,CAAC;AACrD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;kCAMkC;AAClC,MAAM,WAAW,WAAY,SAAQ,oBAAoB;IACvD;+EAC2E;IAC3E,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;;;;;;;;;;;0EAY0E;AAC1E,wBAAgB,SAAS,CAAC,UAAU,SAAS,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/E;;EAUA"}
@@ -0,0 +1,22 @@
1
+ import { tool } from 'ai';
2
+ /** `tool()` with the run state typed.
3
+ *
4
+ * ```ts
5
+ * const lookupInvoice = agentTool({
6
+ * description: 'Find one invoice',
7
+ * parameters: z.object({ invoiceId: z.string() }),
8
+ * execute: async ({ invoiceId }, { state }) =>
9
+ * db.invoice.findFirst({ where: { id: invoiceId, orgId: state.orgId } }),
10
+ * });
11
+ * ```
12
+ *
13
+ * The result is an ordinary AI SDK tool — it composes with
14
+ * `markRequiresConfirmation` and can be passed anywhere `tool()` can. */
15
+ export function agentTool(spec) {
16
+ const { execute, ...rest } = spec;
17
+ return tool({
18
+ ...rest,
19
+ execute: ((args, options) => execute(args, options)),
20
+ });
21
+ }
22
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/core/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAA6B,MAAM,IAAI,CAAC;AAiBrD;;;;;;;;;;;;0EAY0E;AAC1E,MAAM,UAAU,SAAS,CAA0C,IAIlE;IACC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAClC,OAAO,IAAI,CAAC;QACV,GAAG,IAAI;QACP,OAAO,EAAE,CAAC,CAAC,IAAyB,EAAE,OAA6B,EAAE,EAAE,CACrE,OAAO,CAAC,IAAI,EAAE,OAAsB,CAAC,CAGf;KACzB,CAAC,CAAC;AACL,CAAC"}