@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.
- package/dist/adapters/billing/billing-adapter.interface.d.ts +41 -0
- package/dist/adapters/billing/billing-adapter.interface.js +5 -0
- package/dist/adapters/billing/stripe/stripe.adapter.d.ts +30 -0
- package/dist/adapters/billing/stripe/stripe.adapter.js +122 -0
- package/dist/adapters/email/email-adapter.interface.d.ts +25 -0
- package/dist/adapters/email/email-adapter.interface.js +6 -0
- package/dist/adapters/email/noop.adapter.d.ts +10 -0
- package/dist/adapters/email/noop.adapter.js +15 -0
- package/dist/adapters/email/resend.adapter.d.ts +8 -0
- package/dist/adapters/email/resend.adapter.js +39 -0
- package/dist/adapters/job-queue/in-memory.d.ts +43 -0
- package/dist/adapters/job-queue/in-memory.js +154 -0
- package/dist/adapters/job-queue/job-queue.types.d.ts +76 -0
- package/dist/adapters/job-queue/job-queue.types.js +5 -0
- package/dist/adapters/prepared-stream/prepared-stream.types.d.ts +23 -0
- package/dist/adapters/prepared-stream/prepared-stream.types.js +5 -0
- package/dist/adapters/rate-limiter/in-memory.d.ts +19 -0
- package/dist/adapters/rate-limiter/in-memory.js +63 -0
- package/dist/adapters/rate-limiter/rate-limiter.types.d.ts +42 -0
- package/dist/adapters/rate-limiter/rate-limiter.types.js +5 -0
- package/dist/adapters/rate-limiter/redis.d.ts +31 -0
- package/dist/adapters/rate-limiter/redis.js +47 -0
- package/dist/adapters/upload/noop.adapter.d.ts +9 -0
- package/dist/adapters/upload/noop.adapter.js +14 -0
- package/dist/adapters/upload/s3.adapter.d.ts +38 -0
- package/dist/adapters/upload/s3.adapter.js +69 -0
- package/dist/adapters/upload/upload-adapter.interface.d.ts +37 -0
- package/dist/adapters/upload/upload-adapter.interface.js +15 -0
- package/dist/ai/index.d.ts +15 -0
- package/dist/ai/index.js +43 -0
- package/dist/billing/index.d.ts +12 -0
- package/dist/billing/index.js +28 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +8 -0
- package/dist/domain/agent.d.ts +59 -0
- package/dist/domain/agent.js +2 -0
- package/dist/domain/api-key.d.ts +28 -0
- package/dist/domain/api-key.js +2 -0
- package/dist/domain/auth-identity.d.ts +10 -0
- package/dist/domain/auth-identity.js +2 -0
- package/dist/domain/chat-token.d.ts +39 -0
- package/dist/domain/chat-token.js +2 -0
- package/dist/domain/connector-auth.d.ts +42 -0
- package/dist/domain/connector-auth.js +2 -0
- package/dist/domain/connector.d.ts +52 -0
- package/dist/domain/connector.js +2 -0
- package/dist/domain/conversation.d.ts +26 -0
- package/dist/domain/conversation.js +2 -0
- package/dist/domain/email-token.d.ts +11 -0
- package/dist/domain/email-token.js +2 -0
- package/dist/domain/external-user.d.ts +23 -0
- package/dist/domain/external-user.js +2 -0
- package/dist/domain/index.d.ts +5 -0
- package/dist/domain/index.js +24 -0
- package/dist/domain/mcp-server.d.ts +33 -0
- package/dist/domain/mcp-server.js +2 -0
- package/dist/domain/plan.d.ts +20 -0
- package/dist/domain/plan.js +2 -0
- package/dist/domain/platform-secret.d.ts +24 -0
- package/dist/domain/platform-secret.js +8 -0
- package/dist/domain/refresh-token.d.ts +15 -0
- package/dist/domain/refresh-token.js +2 -0
- package/dist/domain/subscription.d.ts +21 -0
- package/dist/domain/subscription.js +2 -0
- package/dist/domain/tenant.d.ts +21 -0
- package/dist/domain/tenant.js +2 -0
- package/dist/domain/usage-record.d.ts +15 -0
- package/dist/domain/usage-record.js +2 -0
- package/dist/domain/user.d.ts +43 -0
- package/dist/domain/user.js +2 -0
- package/dist/factory.d.ts +68 -0
- package/dist/factory.js +56 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +59 -0
- package/dist/repositories/in-memory.d.ts +30 -0
- package/dist/repositories/in-memory.js +82 -0
- package/dist/repositories/index.d.ts +67 -0
- package/dist/repositories/index.js +16 -0
- package/dist/services/agent-config.service.d.ts +45 -0
- package/dist/services/agent-config.service.js +114 -0
- package/dist/services/agent-job.worker.d.ts +32 -0
- package/dist/services/agent-job.worker.js +97 -0
- package/dist/services/agent-runner.service.d.ts +35 -0
- package/dist/services/agent-runner.service.js +224 -0
- package/dist/services/agent.service.d.ts +171 -0
- package/dist/services/agent.service.js +329 -0
- package/dist/services/api-key.service.d.ts +41 -0
- package/dist/services/api-key.service.js +80 -0
- package/dist/services/auth.service.d.ts +133 -0
- package/dist/services/auth.service.js +411 -0
- package/dist/services/billing.service.d.ts +67 -0
- package/dist/services/billing.service.js +254 -0
- package/dist/services/chat-token.service.d.ts +29 -0
- package/dist/services/chat-token.service.js +113 -0
- package/dist/services/connector-registry.service.d.ts +156 -0
- package/dist/services/connector-registry.service.js +278 -0
- package/dist/services/conversation.service.d.ts +47 -0
- package/dist/services/conversation.service.js +101 -0
- package/dist/services/email-templates.d.ts +18 -0
- package/dist/services/email-templates.js +39 -0
- package/dist/services/email.service.d.ts +26 -0
- package/dist/services/email.service.js +42 -0
- package/dist/services/errors.d.ts +7 -0
- package/dist/services/errors.js +27 -0
- package/dist/services/in-memory-prepared-stream.store.d.ts +13 -0
- package/dist/services/in-memory-prepared-stream.store.js +35 -0
- package/dist/services/index.d.ts +13 -0
- package/dist/services/index.js +40 -0
- package/dist/services/mcp-client.service.d.ts +64 -0
- package/dist/services/mcp-client.service.js +157 -0
- package/dist/services/mcp-server.service.d.ts +44 -0
- package/dist/services/mcp-server.service.js +147 -0
- package/dist/services/oauth.service.d.ts +73 -0
- package/dist/services/oauth.service.js +174 -0
- package/dist/services/oauth2.service.d.ts +57 -0
- package/dist/services/oauth2.service.js +82 -0
- package/dist/services/orchestrator.service.d.ts +45 -0
- package/dist/services/orchestrator.service.js +180 -0
- package/dist/services/plan.service.d.ts +54 -0
- package/dist/services/plan.service.js +120 -0
- package/dist/services/prepared-stream.service.d.ts +23 -0
- package/dist/services/prepared-stream.service.js +43 -0
- package/dist/services/refresh-token.service.d.ts +38 -0
- package/dist/services/refresh-token.service.js +73 -0
- package/dist/services/secrets/crypto.d.ts +37 -0
- package/dist/services/secrets/crypto.js +110 -0
- package/dist/services/secrets/known-keys.d.ts +38 -0
- package/dist/services/secrets/known-keys.js +50 -0
- package/dist/services/secrets.service.d.ts +91 -0
- package/dist/services/secrets.service.js +193 -0
- package/dist/services/tenant-billing.service.d.ts +121 -0
- package/dist/services/tenant-billing.service.js +290 -0
- package/dist/services/tenant.service.d.ts +54 -0
- package/dist/services/tenant.service.js +96 -0
- package/dist/services/tool-registry.service.d.ts +42 -0
- package/dist/services/tool-registry.service.js +101 -0
- package/dist/services/upload.service.d.ts +37 -0
- package/dist/services/upload.service.js +84 -0
- package/dist/services/usage.service.d.ts +34 -0
- package/dist/services/usage.service.js +108 -0
- package/dist/types/agent.types.d.ts +160 -0
- package/dist/types/agent.types.js +2 -0
- package/dist/types/billing.types.d.ts +82 -0
- package/dist/types/billing.types.js +3 -0
- package/dist/types/config.types.d.ts +127 -0
- package/dist/types/config.types.js +9 -0
- package/dist/types/hooks.d.ts +85 -0
- package/dist/types/hooks.js +2 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +19 -0
- 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
|
+
}
|