@agentforge-io/core 0.2.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 (151) hide show
  1. package/dist/adapters/billing/billing-adapter.interface.d.ts +41 -0
  2. package/dist/adapters/billing/billing-adapter.interface.js +5 -0
  3. package/dist/adapters/billing/stripe/stripe.adapter.d.ts +30 -0
  4. package/dist/adapters/billing/stripe/stripe.adapter.js +122 -0
  5. package/dist/adapters/email/email-adapter.interface.d.ts +25 -0
  6. package/dist/adapters/email/email-adapter.interface.js +6 -0
  7. package/dist/adapters/email/noop.adapter.d.ts +10 -0
  8. package/dist/adapters/email/noop.adapter.js +15 -0
  9. package/dist/adapters/email/resend.adapter.d.ts +8 -0
  10. package/dist/adapters/email/resend.adapter.js +39 -0
  11. package/dist/adapters/job-queue/in-memory.d.ts +43 -0
  12. package/dist/adapters/job-queue/in-memory.js +154 -0
  13. package/dist/adapters/job-queue/job-queue.types.d.ts +76 -0
  14. package/dist/adapters/job-queue/job-queue.types.js +5 -0
  15. package/dist/adapters/prepared-stream/prepared-stream.types.d.ts +23 -0
  16. package/dist/adapters/prepared-stream/prepared-stream.types.js +5 -0
  17. package/dist/adapters/rate-limiter/in-memory.d.ts +19 -0
  18. package/dist/adapters/rate-limiter/in-memory.js +63 -0
  19. package/dist/adapters/rate-limiter/rate-limiter.types.d.ts +42 -0
  20. package/dist/adapters/rate-limiter/rate-limiter.types.js +5 -0
  21. package/dist/adapters/rate-limiter/redis.d.ts +31 -0
  22. package/dist/adapters/rate-limiter/redis.js +47 -0
  23. package/dist/adapters/upload/noop.adapter.d.ts +9 -0
  24. package/dist/adapters/upload/noop.adapter.js +14 -0
  25. package/dist/adapters/upload/s3.adapter.d.ts +38 -0
  26. package/dist/adapters/upload/s3.adapter.js +69 -0
  27. package/dist/adapters/upload/upload-adapter.interface.d.ts +37 -0
  28. package/dist/adapters/upload/upload-adapter.interface.js +15 -0
  29. package/dist/ai/index.d.ts +15 -0
  30. package/dist/ai/index.js +43 -0
  31. package/dist/billing/index.d.ts +12 -0
  32. package/dist/billing/index.js +28 -0
  33. package/dist/constants.d.ts +3 -0
  34. package/dist/constants.js +8 -0
  35. package/dist/domain/agent.d.ts +59 -0
  36. package/dist/domain/agent.js +2 -0
  37. package/dist/domain/api-key.d.ts +28 -0
  38. package/dist/domain/api-key.js +2 -0
  39. package/dist/domain/auth-identity.d.ts +10 -0
  40. package/dist/domain/auth-identity.js +2 -0
  41. package/dist/domain/chat-token.d.ts +39 -0
  42. package/dist/domain/chat-token.js +2 -0
  43. package/dist/domain/connector-auth.d.ts +42 -0
  44. package/dist/domain/connector-auth.js +2 -0
  45. package/dist/domain/connector.d.ts +52 -0
  46. package/dist/domain/connector.js +2 -0
  47. package/dist/domain/conversation.d.ts +26 -0
  48. package/dist/domain/conversation.js +2 -0
  49. package/dist/domain/email-token.d.ts +11 -0
  50. package/dist/domain/email-token.js +2 -0
  51. package/dist/domain/external-user.d.ts +23 -0
  52. package/dist/domain/external-user.js +2 -0
  53. package/dist/domain/index.d.ts +5 -0
  54. package/dist/domain/index.js +24 -0
  55. package/dist/domain/mcp-server.d.ts +33 -0
  56. package/dist/domain/mcp-server.js +2 -0
  57. package/dist/domain/plan.d.ts +20 -0
  58. package/dist/domain/plan.js +2 -0
  59. package/dist/domain/platform-secret.d.ts +24 -0
  60. package/dist/domain/platform-secret.js +8 -0
  61. package/dist/domain/refresh-token.d.ts +15 -0
  62. package/dist/domain/refresh-token.js +2 -0
  63. package/dist/domain/subscription.d.ts +21 -0
  64. package/dist/domain/subscription.js +2 -0
  65. package/dist/domain/tenant.d.ts +21 -0
  66. package/dist/domain/tenant.js +2 -0
  67. package/dist/domain/usage-record.d.ts +15 -0
  68. package/dist/domain/usage-record.js +2 -0
  69. package/dist/domain/user.d.ts +43 -0
  70. package/dist/domain/user.js +2 -0
  71. package/dist/factory.d.ts +68 -0
  72. package/dist/factory.js +56 -0
  73. package/dist/index.d.ts +14 -0
  74. package/dist/index.js +59 -0
  75. package/dist/repositories/in-memory.d.ts +30 -0
  76. package/dist/repositories/in-memory.js +82 -0
  77. package/dist/repositories/index.d.ts +67 -0
  78. package/dist/repositories/index.js +16 -0
  79. package/dist/services/agent-config.service.d.ts +45 -0
  80. package/dist/services/agent-config.service.js +114 -0
  81. package/dist/services/agent-job.worker.d.ts +32 -0
  82. package/dist/services/agent-job.worker.js +97 -0
  83. package/dist/services/agent-runner.service.d.ts +35 -0
  84. package/dist/services/agent-runner.service.js +224 -0
  85. package/dist/services/agent.service.d.ts +171 -0
  86. package/dist/services/agent.service.js +329 -0
  87. package/dist/services/api-key.service.d.ts +41 -0
  88. package/dist/services/api-key.service.js +80 -0
  89. package/dist/services/auth.service.d.ts +133 -0
  90. package/dist/services/auth.service.js +411 -0
  91. package/dist/services/billing.service.d.ts +67 -0
  92. package/dist/services/billing.service.js +254 -0
  93. package/dist/services/chat-token.service.d.ts +29 -0
  94. package/dist/services/chat-token.service.js +113 -0
  95. package/dist/services/connector-registry.service.d.ts +156 -0
  96. package/dist/services/connector-registry.service.js +278 -0
  97. package/dist/services/conversation.service.d.ts +47 -0
  98. package/dist/services/conversation.service.js +101 -0
  99. package/dist/services/email-templates.d.ts +18 -0
  100. package/dist/services/email-templates.js +39 -0
  101. package/dist/services/email.service.d.ts +26 -0
  102. package/dist/services/email.service.js +42 -0
  103. package/dist/services/errors.d.ts +7 -0
  104. package/dist/services/errors.js +27 -0
  105. package/dist/services/in-memory-prepared-stream.store.d.ts +13 -0
  106. package/dist/services/in-memory-prepared-stream.store.js +35 -0
  107. package/dist/services/index.d.ts +13 -0
  108. package/dist/services/index.js +40 -0
  109. package/dist/services/mcp-client.service.d.ts +64 -0
  110. package/dist/services/mcp-client.service.js +157 -0
  111. package/dist/services/mcp-server.service.d.ts +44 -0
  112. package/dist/services/mcp-server.service.js +147 -0
  113. package/dist/services/oauth.service.d.ts +73 -0
  114. package/dist/services/oauth.service.js +174 -0
  115. package/dist/services/oauth2.service.d.ts +57 -0
  116. package/dist/services/oauth2.service.js +82 -0
  117. package/dist/services/orchestrator.service.d.ts +45 -0
  118. package/dist/services/orchestrator.service.js +180 -0
  119. package/dist/services/plan.service.d.ts +54 -0
  120. package/dist/services/plan.service.js +120 -0
  121. package/dist/services/prepared-stream.service.d.ts +23 -0
  122. package/dist/services/prepared-stream.service.js +43 -0
  123. package/dist/services/refresh-token.service.d.ts +38 -0
  124. package/dist/services/refresh-token.service.js +73 -0
  125. package/dist/services/secrets/crypto.d.ts +37 -0
  126. package/dist/services/secrets/crypto.js +110 -0
  127. package/dist/services/secrets/known-keys.d.ts +38 -0
  128. package/dist/services/secrets/known-keys.js +50 -0
  129. package/dist/services/secrets.service.d.ts +91 -0
  130. package/dist/services/secrets.service.js +193 -0
  131. package/dist/services/tenant-billing.service.d.ts +121 -0
  132. package/dist/services/tenant-billing.service.js +290 -0
  133. package/dist/services/tenant.service.d.ts +54 -0
  134. package/dist/services/tenant.service.js +96 -0
  135. package/dist/services/tool-registry.service.d.ts +42 -0
  136. package/dist/services/tool-registry.service.js +101 -0
  137. package/dist/services/upload.service.d.ts +37 -0
  138. package/dist/services/upload.service.js +84 -0
  139. package/dist/services/usage.service.d.ts +34 -0
  140. package/dist/services/usage.service.js +108 -0
  141. package/dist/types/agent.types.d.ts +160 -0
  142. package/dist/types/agent.types.js +2 -0
  143. package/dist/types/billing.types.d.ts +82 -0
  144. package/dist/types/billing.types.js +3 -0
  145. package/dist/types/config.types.d.ts +127 -0
  146. package/dist/types/config.types.js +9 -0
  147. package/dist/types/hooks.d.ts +85 -0
  148. package/dist/types/hooks.js +2 -0
  149. package/dist/types/index.d.ts +3 -0
  150. package/dist/types/index.js +19 -0
  151. package/package.json +36 -0
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AgentRunnerService = void 0;
7
+ const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
8
+ const crypto_1 = require("crypto");
9
+ const noopLogger = {
10
+ log: () => { }, warn: () => { }, debug: () => { }, error: () => { },
11
+ };
12
+ /**
13
+ * Framework-free runner for Claude. Handles the agentic loop (tool calls) for
14
+ * sync runs and exposes streaming as an `AsyncGenerator<StreamChunk>` so any
15
+ * transport (SSE, fetch+ReadableStream, WebSocket, etc.) can consume it.
16
+ */
17
+ class AgentRunnerService {
18
+ constructor(anthropicConfig, toolRegistry, opts = {}) {
19
+ this.anthropicConfig = anthropicConfig;
20
+ this.toolRegistry = toolRegistry;
21
+ this.client = new sdk_1.default({
22
+ apiKey: anthropicConfig.apiKey,
23
+ baseURL: anthropicConfig.baseURL,
24
+ });
25
+ this.logger = opts.logger ?? noopLogger;
26
+ }
27
+ // ─── Run (non-streaming) ──────────────────────────────────────────────────
28
+ async run(agent, messages, context, overrides) {
29
+ const messageId = (0, crypto_1.randomUUID)();
30
+ const model = overrides?.model ?? agent.model ?? this.anthropicConfig.defaultModel ?? 'claude-opus-4-6';
31
+ const maxTokens = overrides?.maxTokens ?? agent.maxTokens ?? this.anthropicConfig.defaultMaxTokens ?? 4096;
32
+ const temperature = overrides?.temperature ?? agent.temperature ?? 1;
33
+ const systemPrompt = overrides?.systemPromptSuffix
34
+ ? `${agent.systemPrompt}\n\n${overrides.systemPromptSuffix}`
35
+ : agent.systemPrompt;
36
+ const { tools, extras } = this.buildToolList(agent, overrides);
37
+ const toolCalls = [];
38
+ let currentMessages = [...messages];
39
+ let totalUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
40
+ let finalContent = '';
41
+ let stopReason = 'end_turn';
42
+ while (true) {
43
+ const response = await this.client.messages.create({
44
+ model,
45
+ max_tokens: maxTokens,
46
+ temperature,
47
+ system: systemPrompt,
48
+ messages: currentMessages,
49
+ tools: tools,
50
+ });
51
+ totalUsage = {
52
+ inputTokens: totalUsage.inputTokens + response.usage.input_tokens,
53
+ outputTokens: totalUsage.outputTokens + response.usage.output_tokens,
54
+ totalTokens: totalUsage.totalTokens + response.usage.input_tokens + response.usage.output_tokens,
55
+ cacheCreationInputTokens: (totalUsage.cacheCreationInputTokens ?? 0) +
56
+ (response.usage.cache_creation_input_tokens ?? 0),
57
+ cacheReadInputTokens: (totalUsage.cacheReadInputTokens ?? 0) +
58
+ (response.usage.cache_read_input_tokens ?? 0),
59
+ };
60
+ stopReason = response.stop_reason ?? 'end_turn';
61
+ if (response.stop_reason === 'tool_use') {
62
+ currentMessages = [...currentMessages, { role: 'assistant', content: response.content }];
63
+ const toolResults = [];
64
+ for (const block of response.content) {
65
+ if (block.type === 'tool_use') {
66
+ const start = Date.now();
67
+ let output = '';
68
+ let error;
69
+ try {
70
+ output = await this.dispatchTool(block.name, block.input, context, extras);
71
+ }
72
+ catch (err) {
73
+ error = err instanceof Error ? err.message : String(err);
74
+ output = `Error executing tool ${block.name}: ${error}`;
75
+ }
76
+ toolCalls.push({
77
+ toolName: block.name,
78
+ toolUseId: block.id,
79
+ input: block.input,
80
+ output,
81
+ error,
82
+ durationMs: Date.now() - start,
83
+ });
84
+ toolResults.push({
85
+ type: 'tool_result',
86
+ tool_use_id: block.id,
87
+ content: output,
88
+ is_error: !!error,
89
+ });
90
+ }
91
+ }
92
+ currentMessages = [...currentMessages, { role: 'user', content: toolResults }];
93
+ }
94
+ else {
95
+ finalContent = response.content
96
+ .filter((b) => b.type === 'text')
97
+ .map((b) => b.text)
98
+ .join('');
99
+ break;
100
+ }
101
+ }
102
+ return {
103
+ messageId,
104
+ conversationId: context.conversationId,
105
+ content: finalContent,
106
+ role: 'assistant',
107
+ toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
108
+ usage: totalUsage,
109
+ model,
110
+ stopReason,
111
+ createdAt: new Date(),
112
+ };
113
+ }
114
+ // ─── Run (streaming) ──────────────────────────────────────────────────────
115
+ async *stream(agent, messages, context, overrides) {
116
+ const messageId = (0, crypto_1.randomUUID)();
117
+ const model = overrides?.model ?? agent.model ?? this.anthropicConfig.defaultModel ?? 'claude-opus-4-6';
118
+ const maxTokens = overrides?.maxTokens ?? agent.maxTokens ?? this.anthropicConfig.defaultMaxTokens ?? 4096;
119
+ const temperature = overrides?.temperature ?? agent.temperature ?? 1;
120
+ const systemPrompt = overrides?.systemPromptSuffix
121
+ ? `${agent.systemPrompt}\n\n${overrides.systemPromptSuffix}`
122
+ : agent.systemPrompt;
123
+ const { tools, extras } = this.buildToolList(agent, overrides);
124
+ let currentMessages = [...messages];
125
+ let totalUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
126
+ while (true) {
127
+ const stream = this.client.messages.stream({
128
+ model,
129
+ max_tokens: maxTokens,
130
+ temperature,
131
+ system: systemPrompt,
132
+ messages: currentMessages,
133
+ tools: tools,
134
+ });
135
+ for await (const event of stream) {
136
+ if (event.type === 'content_block_start') {
137
+ if (event.content_block.type === 'tool_use') {
138
+ yield {
139
+ type: 'tool_use_start',
140
+ toolName: event.content_block.name,
141
+ toolUseId: event.content_block.id,
142
+ };
143
+ }
144
+ }
145
+ else if (event.type === 'content_block_delta') {
146
+ if (event.delta.type === 'text_delta') {
147
+ yield { type: 'text_delta', delta: event.delta.text };
148
+ }
149
+ }
150
+ else if (event.type === 'message_delta') {
151
+ const deltaUsage = event.usage;
152
+ totalUsage = {
153
+ inputTokens: totalUsage.inputTokens + (deltaUsage?.input_tokens ?? 0),
154
+ outputTokens: totalUsage.outputTokens + (deltaUsage?.output_tokens ?? 0),
155
+ totalTokens: totalUsage.totalTokens +
156
+ (deltaUsage?.input_tokens ?? 0) +
157
+ (deltaUsage?.output_tokens ?? 0),
158
+ };
159
+ }
160
+ }
161
+ const finalMessage = await stream.finalMessage();
162
+ if (finalMessage.stop_reason === 'tool_use') {
163
+ currentMessages = [...currentMessages, { role: 'assistant', content: finalMessage.content }];
164
+ const toolResults = [];
165
+ for (const block of finalMessage.content) {
166
+ if (block.type === 'tool_use') {
167
+ let output = '';
168
+ try {
169
+ output = await this.dispatchTool(block.name, block.input, context, extras);
170
+ }
171
+ catch (err) {
172
+ output = `Error: ${err instanceof Error ? err.message : String(err)}`;
173
+ }
174
+ yield { type: 'tool_result', toolName: block.name, result: output };
175
+ toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: output });
176
+ }
177
+ }
178
+ currentMessages = [...currentMessages, { role: 'user', content: toolResults }];
179
+ }
180
+ else {
181
+ break;
182
+ }
183
+ }
184
+ yield { type: 'usage', usage: totalUsage };
185
+ yield { type: 'done', messageId };
186
+ }
187
+ /**
188
+ * Merge `agent.tools[]` (resolved via the global registry) with any
189
+ * per-call extras (e.g. the user's connector tools).
190
+ *
191
+ * Returns:
192
+ * - `tools`: the Anthropic-shaped array sent to the LLM
193
+ * - `extras`: a name→definition map so `dispatchTool` can route execution
194
+ * for tools that aren't in the global registry
195
+ *
196
+ * Extras with the same name as a global tool shadow the global one — useful
197
+ * when a connector wants to override the built-in `http_request`, for
198
+ * example. The shadowing only lasts for this call.
199
+ */
200
+ buildToolList(agent, overrides) {
201
+ const fromRegistry = agent.tools?.length
202
+ ? this.toolRegistry.getToolsForAgent(agent.id, agent.tools)
203
+ : [];
204
+ const extras = new Map();
205
+ const extrasSchema = [];
206
+ for (const t of overrides?.extraTools ?? []) {
207
+ extras.set(t.name, t);
208
+ extrasSchema.push({
209
+ name: t.name,
210
+ description: t.description,
211
+ input_schema: t.inputSchema,
212
+ });
213
+ }
214
+ const tools = [...fromRegistry, ...extrasSchema];
215
+ return { tools: tools.length ? tools : undefined, extras };
216
+ }
217
+ async dispatchTool(name, input, context, extras) {
218
+ const extra = extras.get(name);
219
+ if (extra)
220
+ return extra.execute(input, context);
221
+ return this.toolRegistry.execute(name, input, context);
222
+ }
223
+ }
224
+ exports.AgentRunnerService = AgentRunnerService;
@@ -0,0 +1,171 @@
1
+ import type { AgentDefinition, McpServerConfig } from '../types/config.types';
2
+ import type { AgentResponse, AgentOverrides, StreamChunk } from '../types/agent.types';
3
+ import type { SdkHooks } from '../types/hooks';
4
+ import type { AgentRunnerService } from './agent-runner.service';
5
+ import type { ConversationService } from './conversation.service';
6
+ import type { ConnectorRegistryService } from './connector-registry.service';
7
+ /**
8
+ * Minimal record the host's agent-config layer must supply to resolve
9
+ * agents by `(tenantId, slug)` or by id. The SDK doesn't care where this
10
+ * data comes from — DB, in-memory, JSON file — only that the resolver
11
+ * implements this contract.
12
+ *
13
+ * Fields are intentionally a strict subset of `AgentDefinition`; the SDK
14
+ * maps them via `toAgentDefinition` below.
15
+ */
16
+ export interface AgentRecord {
17
+ id: string;
18
+ tenantId?: string;
19
+ slug?: string;
20
+ name: string;
21
+ description?: string;
22
+ model?: string;
23
+ systemPrompt: string;
24
+ context?: string;
25
+ temperature?: number;
26
+ topP?: number;
27
+ maxTokens?: number;
28
+ tools?: string[];
29
+ mcpServers?: McpServerConfig[];
30
+ metadata?: Record<string, unknown>;
31
+ isActive?: boolean;
32
+ }
33
+ /**
34
+ * Host-supplied resolver for per-tenant agent configurations. The SDK never
35
+ * persists agents itself; the host owns that. Inject an implementation when
36
+ * the host wants slug-based lookups; otherwise the SDK falls back to the
37
+ * `config.agents` array.
38
+ */
39
+ export interface AgentResolver {
40
+ findBySlug(tenantId: string, slug: string): Promise<AgentRecord | null>;
41
+ findByIdForTenant(id: string, tenantId: string): Promise<AgentRecord | null>;
42
+ findById(id: string): Promise<AgentRecord | null>;
43
+ }
44
+ export interface AgentNotFoundError extends Error {
45
+ status: 404;
46
+ }
47
+ export declare class AgentForbiddenError extends Error {
48
+ status: number;
49
+ code: string;
50
+ constructor(reason: string);
51
+ }
52
+ /**
53
+ * Resolve params for agent lookup. Either an `agentId` (UUID — comes from
54
+ * either the DB or the hardcoded `config.agents` array) or a tenant-scoped
55
+ * `slug` (only meaningful in B2B requests). Both can be present; slug wins
56
+ * because that's the only form a tenant's API-key caller can guess.
57
+ */
58
+ export interface AgentResolveParams {
59
+ agentId?: string;
60
+ agentSlug?: string;
61
+ /** Required when resolving by slug. Pass `req.user.tenantId` from B2B paths. */
62
+ tenantId?: string;
63
+ }
64
+ export declare class AgentService {
65
+ private readonly agents;
66
+ private readonly runner;
67
+ private readonly conversations;
68
+ /** When wired, agents created via the admin UI are looked up here first;
69
+ * the hardcoded `agents` array remains a fallback for legacy installs. */
70
+ private readonly resolver?;
71
+ /** Host-supplied hooks for observing runtime events. The host owns
72
+ * persistence of usage/audit; the SDK only emits. */
73
+ private readonly hooks?;
74
+ /** When wired, every streamMessage / sendMessage call attaches the
75
+ * authenticated user's connector tools (Gmail, Drive, …) on the fly
76
+ * via `overrides.extraTools`. Optional — connectors are opt-in. */
77
+ private readonly connectorRegistry?;
78
+ constructor(agents: AgentDefinition[], runner: AgentRunnerService, conversations: ConversationService,
79
+ /** When wired, agents created via the admin UI are looked up here first;
80
+ * the hardcoded `agents` array remains a fallback for legacy installs. */
81
+ resolver?: AgentResolver | undefined,
82
+ /** Host-supplied hooks for observing runtime events. The host owns
83
+ * persistence of usage/audit; the SDK only emits. */
84
+ hooks?: SdkHooks | undefined,
85
+ /** When wired, every streamMessage / sendMessage call attaches the
86
+ * authenticated user's connector tools (Gmail, Drive, …) on the fly
87
+ * via `overrides.extraTools`. Optional — connectors are opt-in. */
88
+ connectorRegistry?: ConnectorRegistryService | undefined);
89
+ /**
90
+ * Fetch the connector tools the user has authorized, swallowing failures.
91
+ * The agent loop must keep working even if a connector's refresh token is
92
+ * dead — the toolbelt just shrinks. Specific tools may still surface their
93
+ * own auth errors when actually invoked.
94
+ */
95
+ private resolveExtraTools;
96
+ private dispatchUsage;
97
+ private dispatchTurnComplete;
98
+ listAgents(_userId?: string): AgentDefinition[];
99
+ /**
100
+ * Legacy synchronous lookup against the hardcoded `config.agents` array.
101
+ * Kept for backwards compat (existing callers like the orchestrator still
102
+ * use it). New code paths should call `resolveAgent` which also hits the DB.
103
+ */
104
+ getAgent(agentId: string): AgentDefinition;
105
+ /**
106
+ * Resolve an agent from any combination of id/slug. Order:
107
+ * 1. `agentSlug` + `tenantId` against the DB. This is the SDK path.
108
+ * 2. `agentId` against the DB (UI may store agentId in conversations).
109
+ * 3. `agentId` against the hardcoded `config.agents` array (fallback).
110
+ *
111
+ * Returns the runtime `AgentDefinition` ready to feed the runner.
112
+ */
113
+ resolveAgent(params: AgentResolveParams): Promise<AgentDefinition>;
114
+ createConversation(params: {
115
+ userId: string;
116
+ agentId?: string;
117
+ agentSlug?: string;
118
+ tenantId?: string;
119
+ title?: string;
120
+ metadata?: Record<string, unknown>;
121
+ initialMessage?: string;
122
+ }): Promise<{
123
+ conversation: import("..").Conversation;
124
+ firstResponse: AgentResponse;
125
+ } | {
126
+ conversation: import("..").Conversation;
127
+ firstResponse?: undefined;
128
+ }>;
129
+ sendMessage(params: {
130
+ conversationId: string;
131
+ userId: string;
132
+ content: string;
133
+ overrides?: AgentOverrides;
134
+ }): Promise<AgentResponse>;
135
+ streamMessage(params: {
136
+ conversationId: string;
137
+ userId: string;
138
+ content: string;
139
+ overrides?: AgentOverrides;
140
+ }): AsyncGenerator<StreamChunk>;
141
+ getConversation(conversationId: string, userId: string): Promise<import("../types/agent.types").ConversationHistory>;
142
+ listConversations(userId: string, options?: {
143
+ agentId?: string;
144
+ limit?: number;
145
+ offset?: number;
146
+ }): Promise<import("..").Conversation[]>;
147
+ /**
148
+ * Create a conversation and stream the first assistant reply in one go.
149
+ *
150
+ * Designed for the public chat surface: the widget POSTs a single endpoint
151
+ * and expects a `conversation` SSE event followed by the streamed chunks.
152
+ * The caller (PublicChatController) is responsible for surfacing the
153
+ * conversation id via a custom SSE event before the chunks start flowing.
154
+ */
155
+ streamCreateConversation(params: {
156
+ userId: string;
157
+ agentId?: string;
158
+ agentSlug?: string;
159
+ tenantId?: string;
160
+ title?: string;
161
+ metadata?: Record<string, unknown>;
162
+ content: string;
163
+ overrides?: AgentOverrides;
164
+ }): AsyncGenerator<{
165
+ kind: 'conversation';
166
+ conversationId: string;
167
+ } | {
168
+ kind: 'chunk';
169
+ chunk: StreamChunk;
170
+ }>;
171
+ }