@rudderjs/ai 1.3.0 → 1.5.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 (53) hide show
  1. package/README.md +101 -8
  2. package/boost/guidelines.md +14 -2
  3. package/boost/skills/ai-tools/SKILL.md +14 -5
  4. package/dist/agent.d.ts +97 -1
  5. package/dist/agent.d.ts.map +1 -1
  6. package/dist/agent.js +692 -83
  7. package/dist/agent.js.map +1 -1
  8. package/dist/conversation-persistence.d.ts +46 -0
  9. package/dist/conversation-persistence.d.ts.map +1 -0
  10. package/dist/conversation-persistence.js +152 -0
  11. package/dist/conversation-persistence.js.map +1 -0
  12. package/dist/conversation.d.ts +2 -7
  13. package/dist/conversation.d.ts.map +1 -1
  14. package/dist/conversation.js +3 -1
  15. package/dist/conversation.js.map +1 -1
  16. package/dist/handoff.d.ts +95 -0
  17. package/dist/handoff.d.ts.map +1 -0
  18. package/dist/handoff.js +78 -0
  19. package/dist/handoff.js.map +1 -0
  20. package/dist/index.d.ts +8 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +7 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/providers/anthropic.d.ts +9 -1
  25. package/dist/providers/anthropic.d.ts.map +1 -1
  26. package/dist/providers/anthropic.js +5 -5
  27. package/dist/providers/anthropic.js.map +1 -1
  28. package/dist/providers/bedrock.d.ts +60 -0
  29. package/dist/providers/bedrock.d.ts.map +1 -0
  30. package/dist/providers/bedrock.js +167 -0
  31. package/dist/providers/bedrock.js.map +1 -0
  32. package/dist/providers/openai.d.ts +5 -0
  33. package/dist/providers/openai.d.ts.map +1 -1
  34. package/dist/providers/openai.js +6 -0
  35. package/dist/providers/openai.js.map +1 -1
  36. package/dist/providers/openrouter.d.ts +43 -0
  37. package/dist/providers/openrouter.d.ts.map +1 -0
  38. package/dist/providers/openrouter.js +21 -0
  39. package/dist/providers/openrouter.js.map +1 -0
  40. package/dist/server/provider.d.ts.map +1 -1
  41. package/dist/server/provider.js +15 -0
  42. package/dist/server/provider.js.map +1 -1
  43. package/dist/sub-agent-run-store.d.ts +143 -0
  44. package/dist/sub-agent-run-store.d.ts.map +1 -0
  45. package/dist/sub-agent-run-store.js +80 -0
  46. package/dist/sub-agent-run-store.js.map +1 -0
  47. package/dist/tool.d.ts +59 -0
  48. package/dist/tool.d.ts.map +1 -1
  49. package/dist/tool.js +32 -0
  50. package/dist/tool.js.map +1 -1
  51. package/dist/types.d.ts +136 -7
  52. package/dist/types.d.ts.map +1 -1
  53. package/package.json +3 -2
package/README.md CHANGED
@@ -11,11 +11,12 @@ pnpm add @rudderjs/ai
11
11
  Install the provider SDK(s) you need:
12
12
 
13
13
  ```bash
14
- pnpm add @anthropic-ai/sdk # Anthropic (Claude)
15
- pnpm add openai # OpenAI (GPT)
16
- pnpm add @google/genai # Google (Gemini)
17
- pnpm add cohere-ai # Cohere (reranking + embeddings)
18
- # Ollama, Jina no extra package needed
14
+ pnpm add @anthropic-ai/sdk # Anthropic (Claude)
15
+ pnpm add openai # OpenAI (GPT) — also used for OpenRouter / Mistral / DeepSeek / Groq / xAI / Ollama
16
+ pnpm add @google/genai # Google (Gemini)
17
+ pnpm add cohere-ai # Cohere (reranking + embeddings)
18
+ pnpm add @aws-sdk/client-bedrock-runtime # AWS Bedrock
19
+ # Jina — no extra package needed
19
20
  ```
20
21
 
21
22
  ## Runtime Compatibility
@@ -45,6 +46,17 @@ export default {
45
46
  ollama: { driver: 'ollama', baseUrl: 'http://localhost:11434' },
46
47
  cohere: { driver: 'cohere', apiKey: process.env.COHERE_API_KEY! },
47
48
  jina: { driver: 'jina', apiKey: process.env.JINA_API_KEY! },
49
+ openrouter: {
50
+ driver: 'openrouter',
51
+ apiKey: process.env.OPENROUTER_API_KEY!,
52
+ siteUrl: process.env.APP_URL, // optional — sent as HTTP-Referer
53
+ siteName: 'My App', // optional — sent as X-Title
54
+ },
55
+ bedrock: {
56
+ driver: 'bedrock',
57
+ region: process.env.AWS_REGION ?? 'us-east-1',
58
+ // credentials are read from the AWS chain (env, IAM, ~/.aws/credentials)
59
+ },
48
60
  },
49
61
  }
50
62
 
@@ -231,7 +243,59 @@ new Researcher().asTool({
231
243
  })
232
244
  ```
233
245
 
234
- The wrapped subagent runs via `prompt()` (non-streaming) regardless of how the parent was invoked. Token deltas from the subagent are not surfaced as `tool-update` chunks in the parent streamif you need that, write the wrapping tool by hand and drive `agent.stream(...)` yourself.
246
+ The wrapped subagent runs via `prompt()` (non-streaming) by default to surface inner-agent progress as `tool-update` chunks in the parent stream, pass `streaming: true` (or a custom `(chunk) => SubAgentUpdate | null` projector). Pass `suspendable: { runStore }` to opt into the propagation protocol when the sub-agent pauses on a **client tool call** (`finishReason: 'client_tool_calls'`) or an **approval gate** (`finishReason: 'tool_approval_required'`) the parent loop halts, the snapshot persists in the run store with a `pauseKind: 'client_tool' | 'approval'` discriminator, and the host resumes via `Agent.resumeAsTool(subRunId, results, { runStore, agent, approvedToolCallIds? })`. See `docs/guide/ai.md` for the full flow. `InMemorySubAgentRunStore` works for tests; `CachedSubAgentRunStore` plugs into `@rudderjs/cache` for cross-process persistence. Suspend without streaming throws at builder time.
247
+
248
+ ### Handoffs — `handoff()`
249
+
250
+ Sometimes a parent agent shouldn't *call* a specialist and incorporate its result — it should *step out* and let the specialist own the rest of the conversation. That's a handoff.
251
+
252
+ ```ts
253
+ import { Agent, handoff } from '@rudderjs/ai'
254
+
255
+ class SalesAgent extends Agent {
256
+ instructions() { return 'You handle pricing, plans, and upgrades.' }
257
+ }
258
+ class SupportAgent extends Agent {
259
+ instructions() { return 'You triage bugs and walk users through fixes.' }
260
+ }
261
+
262
+ class TriageAgent extends Agent {
263
+ instructions() { return 'Greet the user, then route them to the right specialist.' }
264
+ tools() {
265
+ return [
266
+ handoff(SalesAgent, { when: 'pricing or sales questions' }),
267
+ handoff(SupportAgent, { when: 'bug reports or technical issues' }),
268
+ ]
269
+ }
270
+ }
271
+
272
+ const r = await new TriageAgent().prompt('What does the Pro plan cost?')
273
+ console.log(r.text) // "The Pro plan is $49/month..." (from SalesAgent)
274
+ console.log(r.handoffPath) // ['TriageAgent', 'SalesAgent']
275
+ ```
276
+
277
+ How it differs from `asTool`:
278
+
279
+ | | `asTool` (call-and-return) | `handoff` (control transfer) |
280
+ |---|---|---|
281
+ | Parent loop | continues after subagent finishes | ends |
282
+ | Conversation owner | parent | child |
283
+ | Final `text` | parent's | last child in the chain |
284
+ | `r.steps` | parent steps + a single tool-result step for the subagent | parent steps + each agent's steps merged in order |
285
+ | Use case | "look something up and use it" | "transfer to the right specialist" |
286
+
287
+ Default: the model writes a transition message (`{ message: string }`) that becomes the child's first user message. The full prior conversation flows through to the child — but the child uses its own `instructions()` as the system message. Multi-hop is supported (Triage → Sales → Billing); cycles are bounded by `MAX_HANDOFFS = 5` and surface a clear error.
288
+
289
+ ```ts
290
+ // Custom name + payload
291
+ handoff(SalesAgent, {
292
+ name: 'pivotToSales',
293
+ description: 'Transfer the user to a sales specialist.',
294
+ inputSchema: z.object({ urgency: z.enum(['low', 'high']), context: z.string() }),
295
+ })
296
+ ```
297
+
298
+ In `agent.stream()`, a `'handoff'` `StreamChunk` is emitted right before control transfers, with `{ from, to, message? }` for UIs to render a transition indicator before the next agent's chunks arrive.
235
299
 
236
300
  ### Tool execution context
237
301
 
@@ -252,7 +316,7 @@ const myTool = toolDefinition({
252
316
  })
253
317
  ```
254
318
 
255
- The primary consumer is `@rudderjs/panels`'s `runAgentTool`, which uses
319
+ The primary consumer is `@pilotiq-pro/ai`'s `runAgentTool`, which uses
256
320
  `ctx.toolCallId` to correlate sub-agent suspensions with the parent's
257
321
  `run_agent` call (see "Pausing the loop from a server tool" below).
258
322
 
@@ -316,6 +380,17 @@ internally. Tool authors should construct chunks via the
316
380
  `pauseForClientTools()` factory rather than by hand so future shape
317
381
  changes stay source-compatible.
318
382
 
383
+ **Approval pauses:** the sibling `pauseForApproval(toolCall, isClientTool, resumeHandle?)`
384
+ chunk halts the parent loop when a sub-agent's inner approval gate fires
385
+ (inner `finishReason === 'tool_approval_required'`). The parent's loop
386
+ sets `loopFinishReason = 'tool_approval_required'` and surfaces the
387
+ gated call on `pendingApprovalToolCall`. The wrapping `asTool({ suspendable })`
388
+ generator persists a snapshot with `pauseKind: 'approval'` and yields
389
+ this chunk automatically — hand-rolled tools that wrap their own
390
+ approval-gated sub-agents can yield it directly. Resume with
391
+ `Agent.resumeAsTool(subRunId, [], { runStore, agent, approvedToolCallIds: [...] })`
392
+ (or `rejectedToolCallIds`).
393
+
319
394
  **Resuming:** that's caller territory — `@rudderjs/ai` knows nothing about
320
395
  the resume protocol. The canonical implementation is in
321
396
  `@rudderjs/panels`'s `subAgentResume.ts`, which uses a runStore to persist
@@ -604,6 +679,21 @@ const response = await agent('You are helpful.').prompt('Follow up question', {
604
679
 
605
680
  Works with both `.prompt()` and `.stream()`. History messages are prepended after the system prompt, before the current user message.
606
681
 
682
+ ### Auto-persist conversations
683
+
684
+ Override `conversational()` on an agent class to auto-load and auto-save threads without threading user ids through every call site:
685
+
686
+ ```ts
687
+ class ChatAgent extends Agent {
688
+ conversational() { return { user: Auth.user()?.id } }
689
+ }
690
+
691
+ await new ChatAgent().prompt('Hi') // auto-loads + auto-saves
692
+ await new ChatAgent().prompt('Continue?') // resumes same thread (per user + class)
693
+ ```
694
+
695
+ Returning `false` (the default) keeps the agent stateless. Async returns are awaited; an optional `historyLimit` caps loaded messages. Per-call escape hatches: `prompt(input, { conversation: false })` or `agent.forUser(id).prompt()` / `agent.continue(id).prompt()` — explicit always wins. See `docs/guide/ai.md` for the full precedence chain.
696
+
607
697
  ### Model Selection
608
698
 
609
699
  Configure available models for user selection (used by `@rudderjs/panels` chat UI):
@@ -703,11 +793,14 @@ Under strict mode, only `respondWithSequence` entries count as valid responses;
703
793
  | xAI | *(none)* | `xai/grok-3` | ✓ | | | | | |
704
794
  | Mistral | *(none)* | `mistral/mistral-large` | ✓ | ✓ | | | | |
705
795
  | Azure OpenAI | `openai` | `azure/gpt-4o` | ✓ | | | | | |
796
+ | OpenRouter | `openai` | `openrouter/anthropic/claude-3.5-sonnet` | ✓ | | | | | |
797
+ | AWS Bedrock | `@aws-sdk/client-bedrock-runtime` | `bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0` | ✓ | | | | | |
706
798
 
707
799
  ## Notes
708
800
 
709
801
  - Provider SDKs are optional dependencies — install only what you use
710
802
  - `exactOptionalPropertyTypes` compatible
711
803
  - All adapters lazy-load their SDK on first use
712
- - Ollama, Groq, DeepSeek, xAI, Mistral reuse the OpenAI adapter (OpenAI-compatible API)
804
+ - Ollama, Groq, DeepSeek, xAI, Mistral, OpenRouter reuse the OpenAI adapter (OpenAI-compatible API)
713
805
  - Cohere requires `cohere-ai` SDK; Jina uses direct HTTP (no SDK needed)
806
+ - Bedrock uses the AWS credential chain (env vars / IAM roles / `~/.aws/credentials`); v1 supports Anthropic Claude models on Bedrock
@@ -29,7 +29,7 @@ await agent('You are helpful.').prompt('Hello') // simplest form
29
29
  Configure providers in `config/ai.ts`. The Node-only `AiProvider` lives at `@rudderjs/ai/server` (the main `@rudderjs/ai` entry is runtime-agnostic and has no provider class):
30
30
 
31
31
  ```ts
32
- // config/ai.ts — providers: anthropic, openai, google, ollama, deepseek, xai, groq, mistral, azure
32
+ // config/ai.ts — providers: anthropic, openai, google, ollama, deepseek, xai, groq, mistral, azure, openrouter, bedrock
33
33
  import type { AiConfig } from '@rudderjs/ai'
34
34
 
35
35
  export default {
@@ -91,7 +91,7 @@ class Planner extends Agent implements HasTools {
91
91
  }
92
92
  ```
93
93
 
94
- The subagent runs via `prompt()` (non-streaming); for `tool-update` chunks from a streaming subagent, write the wrapping tool by hand.
94
+ By default the subagent runs via `prompt()` (non-streaming). Pass `streaming: true` to surface inner progress as `tool-update` chunks (default projection emits `agent_start` / `tool_call` / `agent_done`, plus `agent_pending_approval` for inner approval gates); pass `(chunk) => SubAgentUpdate | null` for a custom projector. To propagate inner pauses upward through the parent loop, also pass `suspendable: { runStore }` (suspend without streaming throws at builder time) — `asTool` handles BOTH client-tool pauses AND approval pauses symmetrically, persisting a snapshot with a `pauseKind: 'client_tool' | 'approval'` discriminator. The host's continuation calls `Agent.resumeAsTool(subRunId, results, { runStore, agent })` for client-tool resumes, or `Agent.resumeAsTool(subRunId, [], { runStore, agent, approvedToolCallIds: [...] })` (or `rejectedToolCallIds`) for approval resumes. The returned `'paused'` variant carries `pauseKind` so the host can route the next round-trip correctly. `InMemorySubAgentRunStore` works for tests; `CachedSubAgentRunStore` plugs into `@rudderjs/cache` for multi-worker persistence.
95
95
 
96
96
  ### Middleware
97
97
 
@@ -135,6 +135,18 @@ const response = await myAgent.forUser('user-123').prompt('Hello') // creates c
135
135
  const follow = await myAgent.continue(response.conversationId).prompt('Follow up')
136
136
  ```
137
137
 
138
+ For chat agents that should always auto-persist for the active user, override `conversational()` on the class — `agent.prompt(input)` then auto-loads + auto-saves without each caller passing the user id:
139
+
140
+ ```ts
141
+ class ChatAgent extends Agent {
142
+ conversational() { return { user: Auth.user()?.id } } // null user → opt-out
143
+ }
144
+ await new ChatAgent().prompt('Hi') // auto-loads thread
145
+ await new ChatAgent().prompt('still you?') // resumes per (user, class)
146
+ ```
147
+
148
+ Returning `false` (default) keeps the agent stateless. Optional `historyLimit: N` caps loaded messages. Per-call `{ conversation: false }` opts out; `forUser`/`continue` always win.
149
+
138
150
  ### Streaming
139
151
 
140
152
  Use `.stream()` for real-time token delivery:
@@ -181,28 +181,37 @@ const secretTool = toolDefinition({
181
181
  })
182
182
  ```
183
183
 
184
- ### 9. Pause for client tools (from inside a server tool)
184
+ ### 9. Pause the parent loop from inside a server tool
185
185
 
186
186
  ```ts
187
- import { pauseForClientTools } from '@rudderjs/ai'
187
+ import { pauseForClientTools, pauseForApproval } from '@rudderjs/ai'
188
188
 
189
189
  const runSubAgentTool = toolDefinition({
190
190
  name: 'run_sub_agent',
191
- description: 'Run a sub-agent that may need browser tools',
191
+ description: 'Run a sub-agent that may need browser tools or approval',
192
192
  inputSchema: z.object({ task: z.string() }),
193
193
  }).server(async function* ({ task }, ctx) {
194
194
  const subResponse = await runSubAgent(task)
195
195
 
196
196
  if (subResponse.pendingClientToolCalls?.length) {
197
- // Pause the parent loop -- surface client tool calls to the browser
197
+ // Client-tool pause -- surface inner client tool calls to the browser
198
198
  yield pauseForClientTools(subResponse.pendingClientToolCalls, subResponse.resumeId)
199
199
  return undefined as never // unreachable after pause
200
200
  }
201
201
 
202
+ if (subResponse.pendingApprovalToolCall) {
203
+ // Approval pause -- surface the gated tool call for the user to approve/reject
204
+ const { toolCall, isClientTool } = subResponse.pendingApprovalToolCall
205
+ yield pauseForApproval(toolCall, isClientTool, subResponse.resumeId)
206
+ return undefined as never
207
+ }
208
+
202
209
  return subResponse.text
203
210
  })
204
211
  ```
205
212
 
213
+ `Agent.asTool({ suspendable })` does this automatically — yield manually only for hand-rolled sub-agent runners or non-agent tools that need a browser/approval round-trip.
214
+
206
215
  ### 10. Using tools with an agent
207
216
 
208
217
  ```ts
@@ -238,7 +247,7 @@ Tools are typically defined in `app/Tools/` or co-located with the agent that us
238
247
  - **Zod schemas required**: Tool input schemas must be Zod objects. They are converted to JSON Schema for each provider automatically.
239
248
  - **Generator vs async function**: Use `async function*` only when you need streaming progress yields. For simple tools, use a regular `async` function.
240
249
  - **modelOutput is optional**: Only use `.modelOutput()` when the tool returns large structured data that would waste model context. The default behavior is `JSON.stringify` of the result.
241
- - **Approval flow is two-step**: When a tool needs approval, the loop stops. You must resume with `approvedToolCallIds` or `rejectedToolCallIds` in the next `prompt()` call's options.
250
+ - **Approval flow is two-step**: When a tool needs approval, the loop stops. You must resume with `approvedToolCallIds` or `rejectedToolCallIds` in the next `prompt()` call's options. For approval-gated tools inside a sub-agent wrapped via `asTool({ suspendable })`, resume goes through `Agent.resumeAsTool(subRunId, [], { runStore, agent, approvedToolCallIds })` — the snapshot's `pauseKind: 'approval'` discriminator routes the resume contract.
242
251
  - **Client tool placeholder mode**: By default, client tools without `execute` get a placeholder result and the loop continues. Pass `toolCallStreamingMode: 'stop-on-client-tool'` to pause instead.
243
252
  - **exactOptionalPropertyTypes**: If your tsconfig has this enabled, do not pass `undefined` for optional tool parameters -- omit the key entirely.
244
253
  - **Tool name conventions**: Use `snake_case` for tool names (e.g. `get_weather`, `search_documents`). This matches what AI models expect.
package/dist/agent.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  import type { ServerToolBuilder } from './tool.js';
3
3
  import { QueuedPromptBuilder } from './queue-job.js';
4
- import type { AgentPromptOptions, AiMessage, AiMiddleware, AgentResponse, AgentStep, AgentStreamResponse, AnyTool, CacheableConfig, ConversationStore, HasMiddleware, HasTools, PrepareStepResult, StopCondition } from './types.js';
4
+ import type { SubAgentPauseKind, SubAgentRunStore } from './sub-agent-run-store.js';
5
+ import type { AgentPromptOptions, AiMessage, AiMiddleware, AgentResponse, AgentStep, AgentStreamResponse, AnyTool, CacheableConfig, ConversationalSpec, ConversationStore, SubAgentUpdate, HasMiddleware, HasTools, PrepareStepResult, StopCondition, StreamChunk, ToolCall } from './types.js';
5
6
  /** Stop after N steps */
6
7
  export declare function stepCountIs(n: number): StopCondition;
7
8
  /** Stop when a specific tool is called in the latest step */
@@ -51,6 +52,34 @@ export declare abstract class Agent {
51
52
  * }
52
53
  */
53
54
  cacheable(): CacheableConfig | undefined;
55
+ /**
56
+ * Opt into auto-persisted conversation behavior. Override on a subclass
57
+ * to declare *which* user owns the thread and (optionally) which
58
+ * specific thread, and the framework will load history before each
59
+ * `prompt()`/`stream()` call and append the new turn after it — without
60
+ * any caller having to remember `forUser()` / `continue()`.
61
+ *
62
+ * Returning `false` (the default) disables auto-persist; the agent runs
63
+ * stateless. Returning a {@link ConversationalSpec} opts in:
64
+ *
65
+ * @example
66
+ * class ChatAgent extends Agent {
67
+ * conversational() {
68
+ * return { user: Auth.user()?.id } // null user → falsy → opt-out
69
+ * }
70
+ * }
71
+ *
72
+ * await new ChatAgent().prompt('Hi') // auto-loads + auto-saves
73
+ *
74
+ * **Precedence (high → low):**
75
+ * 1. Explicit `agent.forUser(id).prompt()` / `agent.continue(id).prompt()`
76
+ * 2. Per-call `prompt(input, { conversation: false | {...} })`
77
+ * 3. This method's return value
78
+ *
79
+ * Async returns are supported — useful when the user identity is fetched
80
+ * from an async DI binding.
81
+ */
82
+ conversational(): false | ConversationalSpec | Promise<false | ConversationalSpec>;
54
83
  /**
55
84
  * Default for `AgentPromptOptions.parallelTools`. When `true` (default),
56
85
  * multiple tool calls within a single step run their `execute()` functions
@@ -102,15 +131,74 @@ export declare abstract class Agent {
102
131
  inputSchema: TInput;
103
132
  prompt: (input: z.infer<TInput>) => string;
104
133
  modelOutput?: (response: AgentResponse) => string | Promise<string>;
134
+ streaming?: AsToolStreamingOption;
135
+ suspendable?: AsToolSuspendableOption;
105
136
  }): ServerToolBuilder<z.infer<TInput>, AgentResponse>;
106
137
  asTool(options: {
107
138
  name: string;
108
139
  description: string;
109
140
  modelOutput?: (response: AgentResponse) => string | Promise<string>;
141
+ streaming?: AsToolStreamingOption;
142
+ suspendable?: AsToolSuspendableOption;
110
143
  }): ServerToolBuilder<{
111
144
  prompt: string;
112
145
  }, AgentResponse>;
146
+ /**
147
+ * Resume a sub-agent run that previously paused with either
148
+ * `pauseForClientTools` (client-tool pause) or `pauseForApproval`
149
+ * (approval pause), typically from {@link Agent.asTool} with
150
+ * `suspendable: { runStore }` set. The snapshot's `pauseKind`
151
+ * (default `'client_tool'`) selects the resume contract:
152
+ *
153
+ * - **`client_tool`** — `clientToolResults` must carry one entry per
154
+ * id in the snapshot's `pendingToolCallIds`. Results are appended
155
+ * to the inner-agent message history and the loop re-runs.
156
+ * - **`approval`** — `approvedToolCallIds` and/or
157
+ * `rejectedToolCallIds` must reference the single pending id.
158
+ * `clientToolResults` must be empty; the loop re-runs with the
159
+ * approval decision injected via `AgentPromptOptions`.
160
+ *
161
+ * Returns either a `'completed'` result (the inner agent finished),
162
+ * a `'paused'` continuation pointing at a fresh `subRunId` for the
163
+ * next round-trip, or stays `'paused'` if the inner loop hits another
164
+ * gate. The resume can pause on a different kind than it started on
165
+ * (e.g. an approval pause that, once approved, hits a client-tool
166
+ * pause on the next step).
167
+ *
168
+ * @example Client-tool resume
169
+ * const r = await Agent.resumeAsTool(subRunId, browserResults, { runStore, agent: subAgent })
170
+ *
171
+ * @example Approval resume
172
+ * const r = await Agent.resumeAsTool(subRunId, [], {
173
+ * runStore, agent: subAgent,
174
+ * approvedToolCallIds: ['inner-call-id'],
175
+ * })
176
+ */
177
+ static resumeAsTool(subRunId: string, clientToolResults: ReadonlyArray<{
178
+ toolCallId: string;
179
+ result: unknown;
180
+ }>, options: {
181
+ runStore: SubAgentRunStore;
182
+ agent: Agent;
183
+ approvedToolCallIds?: string[];
184
+ rejectedToolCallIds?: string[];
185
+ }): Promise<{
186
+ kind: 'completed';
187
+ response: AgentResponse;
188
+ } | {
189
+ kind: 'paused';
190
+ subRunId: string;
191
+ pauseKind: SubAgentPauseKind;
192
+ pendingToolCallIds: string[];
193
+ toolCall?: ToolCall;
194
+ isClientTool?: boolean;
195
+ }>;
113
196
  }
197
+ type ChunkProjector = (chunk: StreamChunk) => SubAgentUpdate | null;
198
+ type AsToolStreamingOption = boolean | ChunkProjector;
199
+ type AsToolSuspendableOption = {
200
+ runStore: SubAgentRunStore;
201
+ };
114
202
  /**
115
203
  * Wraps an Agent to add conversation memory.
116
204
  * Created via `agent.forUser(id)` or `agent.continue(id)`.
@@ -124,6 +212,13 @@ export declare class ConversableAgent {
124
212
  continue(conversationId: string): this;
125
213
  prompt(input: string, options?: AgentPromptOptions): Promise<AgentResponse>;
126
214
  stream(input: string, options?: AgentPromptOptions): AgentStreamResponse;
215
+ /**
216
+ * Translate the wrapper's explicit-form state (`forUser` / `continue`)
217
+ * into a {@link ConversationalSpec}. The explicit chain bypasses the
218
+ * agent's `conversational()` declaration entirely — `forUser` always
219
+ * wins over class defaults.
220
+ */
221
+ private toSpec;
127
222
  }
128
223
  /**
129
224
  * Create an anonymous agent inline.
@@ -160,4 +255,5 @@ export interface InvalidToolArgumentsError {
160
255
  message: string;
161
256
  }>;
162
257
  }
258
+ export {};
163
259
  //# sourceMappingURL=agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,KAAK,EAAmD,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAInG,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAMpD,OAAO,KAAK,EAAE,iBAAiB,EAAuB,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAYxG,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EAEZ,aAAa,EACb,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,eAAe,EAIf,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EAEd,aAAa,EACb,QAAQ,EAER,iBAAiB,EAEjB,aAAa,EACb,WAAW,EAEX,QAAQ,EAKT,MAAM,YAAY,CAAA;AA8BnB,yBAAyB;AACzB,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAEpD;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAK3D;AAID,8BAAsB,KAAK;IACzB,yCAAyC;IACzC,QAAQ,CAAC,YAAY,IAAI,MAAM;IAE/B,uFAAuF;IACvF,KAAK,IAAI,MAAM,GAAG,SAAS;IAE3B,sCAAsC;IACtC,QAAQ,IAAI,MAAM,EAAE;IAEpB,yDAAyD;IACzD,QAAQ,IAAI,MAAM;IAElB,uEAAuE;IACvE,WAAW,CAAC,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,QAAQ,EAAE,SAAS,EAAE,CAAA;KAAE,GAAG,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAErI,sDAAsD;IACtD,QAAQ,IAAI,aAAa,GAAG,aAAa,EAAE;IAI3C,wBAAwB;IACxB,WAAW,IAAI,MAAM,GAAG,SAAS;IAEjC,8BAA8B;IAC9B,SAAS,IAAI,MAAM,GAAG,SAAS;IAE/B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,SAAS,IAAI,eAAe,GAAG,SAAS;IAExC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,cAAc,IAAI,KAAK,GAAG,kBAAkB,GAAG,OAAO,CAAC,KAAK,GAAG,kBAAkB,CAAC;IAIlF;;;;;OAKG;IACH,aAAa,IAAI,OAAO;IAExB,kDAAkD;IAC5C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAejF,8CAA8C;IAC9C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,mBAAmB;IAIxE,gDAAgD;IAChD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,mBAAmB;IAIvE,sDAAsD;IACtD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB;IAIzC,wCAAwC;IACxC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB;IAIlD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE;QACxC,IAAI,EAAU,MAAM,CAAA;QACpB,WAAW,EAAG,MAAM,CAAA;QACpB,WAAW,EAAG,MAAM,CAAA;QACpB,MAAM,EAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,MAAM,CAAA;QAChD,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QACnE,SAAS,CAAC,EAAI,qBAAqB,CAAA;QACnC,WAAW,CAAC,EAAE,uBAAuB,CAAA;KACtC,GAAG,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IACrD,MAAM,CAAC,OAAO,EAAE;QACd,IAAI,EAAU,MAAM,CAAA;QACpB,WAAW,EAAG,MAAM,CAAA;QACpB,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QACnE,SAAS,CAAC,EAAI,qBAAqB,CAAA;QACnC,WAAW,CAAC,EAAE,uBAAuB,CAAA;KACtC,GAAG,iBAAiB,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,aAAa,CAAC;IAuHxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;WACU,YAAY,CACvB,QAAQ,EAAW,MAAM,EACzB,iBAAiB,EAAE,aAAa,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,EACzE,OAAO,EAAE;QACP,QAAQ,EAAc,gBAAgB,CAAA;QACtC,KAAK,EAAiB,KAAK,CAAA;QAC3B,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;QAC9B,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;KAC/B,GACA,OAAO,CACN;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,aAAa,CAAA;KAAE,GAC9C;QACE,IAAI,EAAgB,QAAQ,CAAA;QAC5B,QAAQ,EAAY,MAAM,CAAA;QAC1B,SAAS,EAAW,iBAAiB,CAAA;QACrC,kBAAkB,EAAE,MAAM,EAAE,CAAA;QAC5B,QAAQ,CAAC,EAAW,QAAQ,CAAA;QAC5B,YAAY,CAAC,EAAO,OAAO,CAAA;KAC5B,CACJ;CAmHF;AAID,KAAK,cAAc,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,cAAc,GAAG,IAAI,CAAA;AA+BnE,KAAK,qBAAqB,GAAI,OAAO,GAAG,cAAc,CAAA;AACtD,KAAK,uBAAuB,GAAG;IAAE,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAAA;AAkD7D;;;GAGG;AACH,qBAAa,gBAAgB;IAIf,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHlC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,eAAe,CAAoB;gBAEd,KAAK,EAAE,KAAK;IAEzC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK7B,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAKhC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAiBjF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,mBAAmB;IAkBxE;;;;;OAKG;IACH,OAAO,CAAC,MAAM;CAKf;AA6BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,KAAK,CACnB,qBAAqB,EAAE,MAAM,GAAG;IAC9B,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAA;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,UAAU,CAAC,EAAE,YAAY,EAAE,GAAG,SAAS,CAAA;CACxC,GACA,KAAK,GAAG,QAAQ,GAAG,aAAa,CAKlC;AAQD,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAEnE;AA0qDD;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,mBAAmB,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACjD"}