twelveai 0.3.0 → 0.4.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.
@@ -0,0 +1,325 @@
1
+ /** Shared request/response types for the TwelveAI chat API. */
2
+ interface TwelveAIOptions {
3
+ /** Your workspace API key (sk_live_... / sk_test_...). */
4
+ apiKey: string;
5
+ /** Engine base URL. Defaults to the hosted platform. */
6
+ baseUrl?: string;
7
+ /**
8
+ * Auth your server adds when the SDK performs client-fetch hand-offs against
9
+ * YOUR OWN API (the engine hands the resolved request back without any
10
+ * credentials). Static headers, or a function returning them per request.
11
+ */
12
+ clientAuth?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
13
+ /** Custom fetch implementation (tests, polyfills). Defaults to global fetch. */
14
+ fetch?: typeof globalThis.fetch;
15
+ /** Max auto-resume rounds for client-fetch hand-offs per chat() call. Default 3. */
16
+ maxHandoffRounds?: number;
17
+ }
18
+ interface Attachment {
19
+ /** Public URL, or a data: URL. */
20
+ url?: string;
21
+ /** Base64 content (alternative to url). */
22
+ data?: string;
23
+ mediaType?: string;
24
+ /** A WhatsApp media id, if the engine should fetch it via your connected WhatsApp. */
25
+ whatsappMediaId?: string;
26
+ }
27
+ interface ChatInput {
28
+ /** The end user's message. Optional when resuming or sending only attachments. */
29
+ message?: string;
30
+ /** Your id for this end user (alias: userId). Required for customer-scoped agents. */
31
+ customerId?: string;
32
+ /** Continue an existing conversation with the token from the previous turn. */
33
+ continuation?: string;
34
+ /** The user approved a pending action (PIN/OTP collected on your side). */
35
+ confirmed?: boolean;
36
+ /** Sandbox: tools return sample data; nothing real is called or moved. */
37
+ sandbox?: boolean;
38
+ channel?: string;
39
+ /** Force a specific agent instead of routing. */
40
+ intent?: string;
41
+ /** Customer tier to sync for this turn's caps. */
42
+ tier?: string;
43
+ /** Routing reasoning: 'off' | 'auto' (default) | 'always'. */
44
+ reasoning?: 'off' | 'auto' | 'always';
45
+ /**
46
+ * Short-lived end-user session token, forwarded verbatim on tool bindings
47
+ * with auth type 'customer_token'. Never stored by the engine.
48
+ */
49
+ customerToken?: string;
50
+ /** Images / voice notes attached to this turn. */
51
+ attachments?: Attachment[];
52
+ metadata?: Record<string, unknown>;
53
+ }
54
+ interface ToolCall {
55
+ name: string;
56
+ arguments: Record<string, unknown>;
57
+ result: unknown;
58
+ }
59
+ interface HandoffRequest {
60
+ method: string;
61
+ url: string;
62
+ headers?: Record<string, string>;
63
+ body?: Record<string, unknown>;
64
+ }
65
+ interface PendingToolCall {
66
+ id: string;
67
+ name: string;
68
+ arguments: Record<string, unknown>;
69
+ /** Client-fetch hand-off: the resolved request your server should perform. */
70
+ request?: HandoffRequest;
71
+ }
72
+ interface ToolResult {
73
+ id: string;
74
+ result: unknown;
75
+ }
76
+ interface ChatResponse {
77
+ ok: boolean;
78
+ sandbox?: boolean;
79
+ /** The assistant's reply to show the user. */
80
+ message: string | null;
81
+ intent: string | null;
82
+ toolCalls: ToolCall[];
83
+ /** A write awaiting the user's confirmation (resend with confirmed: true). */
84
+ pendingConfirmation: {
85
+ tool: string;
86
+ arguments: Record<string, unknown>;
87
+ } | null;
88
+ /**
89
+ * Client-executed tool calls YOUR system must run. With auto-execution on
90
+ * (the default), read hand-offs are already completed by the SDK; anything
91
+ * left here is yours to handle (typically a money move awaiting PIN).
92
+ */
93
+ pendingToolCalls: PendingToolCall[] | null;
94
+ /** Pass this back on the next turn to continue the conversation. */
95
+ continuation: string | null;
96
+ escalated?: boolean;
97
+ policy?: string | null;
98
+ autonomy?: string | null;
99
+ fee?: {
100
+ feeNgn: number;
101
+ amountNgn: number;
102
+ totalNgn: number;
103
+ } | null;
104
+ usage?: {
105
+ inputTokens: number;
106
+ outputTokens: number;
107
+ };
108
+ billing?: Record<string, unknown>;
109
+ latencyMs?: number;
110
+ metadata?: Record<string, unknown>;
111
+ error?: string;
112
+ /** HTTP status of the underlying call. */
113
+ status: number;
114
+ /** Hand-offs the SDK auto-executed to complete this turn (for observability). */
115
+ executedHandoffs?: Array<{
116
+ name: string;
117
+ method: string;
118
+ url: string;
119
+ ok: boolean;
120
+ }>;
121
+ }
122
+ /**
123
+ * Executor for one client-fetch hand-off. Return the tool result the engine
124
+ * resumes with. The default executor performs `call.request` with your
125
+ * `clientAuth` headers and returns `{ ok, data }`.
126
+ */
127
+ type HandoffExecutor = (call: PendingToolCall) => Promise<unknown>;
128
+ interface ClassifyResponse {
129
+ ok: boolean;
130
+ /** The winning agent intent, or null when nothing matched. */
131
+ intent: string | null;
132
+ label: string | null;
133
+ /** Deterministic confidence in [0, 0.95]; 0 = no match. */
134
+ confidence: number;
135
+ alternatives: Array<{
136
+ intent: string;
137
+ label: string;
138
+ confidence?: number;
139
+ matchedKeywords?: string[];
140
+ }>;
141
+ /** The exact keywords that selected the winning intent (explainability). */
142
+ matchedKeywords?: string[];
143
+ /** Raw keyword-hit count for the winner, and its lead over the runner-up. */
144
+ score?: number;
145
+ margin?: number;
146
+ /** True when the winning intent is classifier-only (your systems handle it). */
147
+ classifyOnly?: boolean;
148
+ /** Extracted entities: amount, account_number, phone, bank {name, code}, currency. */
149
+ entities: Record<string, unknown>;
150
+ status: number;
151
+ error?: string;
152
+ }
153
+
154
+ /**
155
+ * Management API - everything the console can do, callable from code. Thin,
156
+ * typed-enough wrappers over the engine's management endpoints, all
157
+ * authenticated with the same x-api-key as chat. Every method resolves to
158
+ * `{ ok, status, ...payload }` and never throws on HTTP errors.
159
+ */
160
+ interface ManageResult {
161
+ ok: boolean;
162
+ status: number;
163
+ error?: string;
164
+ [key: string]: unknown;
165
+ }
166
+ interface CreateAgentInput {
167
+ intent: string;
168
+ label?: string;
169
+ keywords: string[];
170
+ /** With instructions (and optionally tools) this creates a FULL chat agent; without, a classifier-only intent. */
171
+ systemPrompt?: string;
172
+ tools?: string[];
173
+ requiresCustomer?: boolean;
174
+ }
175
+ interface CreateToolInput {
176
+ name: string;
177
+ description: string;
178
+ sideEffect: 'read' | 'write';
179
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
180
+ /** {placeholders} become the tool's arguments; {customer_id} is filled per turn. */
181
+ url: string;
182
+ execution?: 'hosted' | 'client';
183
+ /** A real example response - drives result parsing and the sandbox. */
184
+ sampleResponse?: unknown;
185
+ }
186
+ interface BindToolInput {
187
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
188
+ url: string;
189
+ resultPath?: string | null;
190
+ sampleResponse?: unknown;
191
+ execution?: 'hosted' | 'client';
192
+ auth?: Record<string, unknown>;
193
+ }
194
+ type Request = (method: string, path: string, body?: Record<string, unknown>) => Promise<ManageResult>;
195
+ /** Build the management namespaces over one authenticated request function. */
196
+ declare function buildManage(request: Request): {
197
+ agents: {
198
+ list: () => Promise<ManageResult>;
199
+ create: (input: CreateAgentInput) => Promise<ManageResult>;
200
+ update: (intent: string, patch: Record<string, unknown>) => Promise<ManageResult>;
201
+ enable: (intent: string) => Promise<ManageResult>;
202
+ disable: (intent: string) => Promise<ManageResult>;
203
+ delete: (intent: string) => Promise<ManageResult>;
204
+ };
205
+ tools: {
206
+ list: () => Promise<ManageResult>;
207
+ create: (input: CreateToolInput) => Promise<ManageResult>;
208
+ bind: (name: string, binding: BindToolInput) => Promise<ManageResult>;
209
+ test: (name: string) => Promise<ManageResult>;
210
+ importOpenApi: (input: {
211
+ url?: string;
212
+ spec?: unknown;
213
+ execution?: "hosted" | "client";
214
+ dryRun?: boolean;
215
+ auth?: Record<string, unknown>;
216
+ }) => Promise<ManageResult>;
217
+ };
218
+ plugins: {
219
+ list: () => Promise<ManageResult>;
220
+ install: (id: string) => Promise<ManageResult>;
221
+ uninstall: (id: string) => Promise<ManageResult>;
222
+ };
223
+ customers: {
224
+ list: (opts?: {
225
+ limit?: number;
226
+ range?: string;
227
+ }) => Promise<ManageResult>;
228
+ upsert: (input: {
229
+ externalId: string;
230
+ tier?: string | null;
231
+ name?: string;
232
+ email?: string;
233
+ status?: string;
234
+ }) => Promise<ManageResult>;
235
+ get: (externalId: string) => Promise<ManageResult>;
236
+ };
237
+ settings: {
238
+ get: () => Promise<ManageResult>;
239
+ update: (patch: Record<string, unknown>) => Promise<ManageResult>;
240
+ };
241
+ billing: {
242
+ get: () => Promise<ManageResult>;
243
+ topup: (amountNgn: number, email?: string) => Promise<ManageResult>;
244
+ };
245
+ usage: {
246
+ summary: () => Promise<ManageResult>;
247
+ events: (limit?: number) => Promise<ManageResult>;
248
+ event: (id: number | string) => Promise<ManageResult>;
249
+ analytics: (days?: number) => Promise<ManageResult>;
250
+ };
251
+ manifest: () => Promise<ManageResult>;
252
+ };
253
+ type Manage = ReturnType<typeof buildManage>;
254
+
255
+ /**
256
+ * The TwelveAI client. One call does the whole conversation protocol:
257
+ *
258
+ * const twelve = new TwelveAI({ apiKey: process.env.TWELVE_API_KEY! })
259
+ * const res = await twelve.chat({ message: "what's my balance?", customerId: 'cus_123' })
260
+ * console.log(res.message)
261
+ *
262
+ * Client-fetch hand-offs (tools configured as "my app calls it") are executed
263
+ * automatically against your own API - the engine never holds your credentials;
264
+ * you supply them once via `clientAuth` and the SDK completes the loop. Money
265
+ * moves are never auto-executed: they surface in `pendingToolCalls` /
266
+ * `pendingConfirmation` for your PIN flow, then you call `confirm()` or
267
+ * `resume()`.
268
+ */
269
+ declare class TwelveAI {
270
+ private readonly apiKey;
271
+ private readonly baseUrl;
272
+ private readonly fetchImpl;
273
+ private readonly clientAuth;
274
+ private readonly maxHandoffRounds;
275
+ /**
276
+ * Everything the console can do, from code: agents, tools, plugins,
277
+ * customers, settings, billing, usage. `twelve.manage.plugins.install('bills')`.
278
+ */
279
+ readonly manage: Manage;
280
+ constructor(options: TwelveAIOptions);
281
+ /**
282
+ * Low-level authenticated call to any engine endpoint. Returns
283
+ * `{ ok, status, ...payload }`; never throws on HTTP errors.
284
+ */
285
+ api(method: string, path: string, body?: Record<string, unknown>): Promise<ManageResult>;
286
+ /**
287
+ * Send one chat turn and return the completed result. Read hand-offs are
288
+ * auto-executed (see class docs); pass `autoExecute: false` to get the raw
289
+ * paused response instead, or `onHandoff` to execute them yourself.
290
+ */
291
+ chat(input: ChatInput, opts?: {
292
+ autoExecute?: boolean;
293
+ onHandoff?: HandoffExecutor;
294
+ }): Promise<ChatResponse>;
295
+ /** Resume a paused turn with tool results your system produced. */
296
+ resume(continuation: string, toolResults: ToolResult[], input?: Pick<ChatInput, 'customerId' | 'channel' | 'sandbox' | 'customerToken'>): Promise<ChatResponse>;
297
+ /**
298
+ * Approve a pending action (after your PIN/OTP step) - resends the turn with
299
+ * `confirmed: true` so the engine proceeds.
300
+ */
301
+ confirm(continuation: string, input?: Omit<ChatInput, 'continuation' | 'confirmed'>): Promise<ChatResponse>;
302
+ /**
303
+ * Level-0 integration: classify a message WITHOUT running the conversation.
304
+ * Returns the intent, a deterministic confidence score, and cheap extracted
305
+ * entities (amount / account number / phone) - you keep your existing flows
306
+ * and make the call yourself. Free: no tools run, nothing is stored.
307
+ */
308
+ classify(input: {
309
+ message: string;
310
+ reasoning?: 'off' | 'auto' | 'always';
311
+ }): Promise<ClassifyResponse>;
312
+ private chatBody;
313
+ private post;
314
+ /**
315
+ * Execute client-fetch hand-offs and resume until the turn completes. Only
316
+ * calls that carry a resolved `request` are auto-executed - a hand-off
317
+ * without one (e.g. a money move awaiting your PIN flow) stops the loop and
318
+ * is returned to you untouched.
319
+ */
320
+ private completeHandoffs;
321
+ /** Default hand-off executor: perform the request with your clientAuth headers. */
322
+ private performHandoff;
323
+ }
324
+
325
+ export { type Attachment as A, type BindToolInput as B, type ChatInput as C, type HandoffExecutor as H, type Manage as M, type PendingToolCall as P, TwelveAI as T, type ChatResponse as a, type ClassifyResponse as b, type CreateAgentInput as c, type CreateToolInput as d, type HandoffRequest as e, type ManageResult as f, type ToolCall as g, type ToolResult as h, type TwelveAIOptions as i, buildManage as j };
package/dist/index.cjs CHANGED
@@ -21,12 +21,59 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  TwelveAI: () => TwelveAI,
24
+ buildManage: () => buildManage,
24
25
  createJwksVerifier: () => createJwksVerifier,
25
26
  verifySignedRequest: () => verifySignedRequest,
26
27
  verifyWebhook: () => verifyWebhook
27
28
  });
28
29
  module.exports = __toCommonJS(index_exports);
29
30
 
31
+ // src/manage.ts
32
+ function buildManage(request) {
33
+ return {
34
+ agents: {
35
+ list: () => request("GET", "/v1/agents"),
36
+ create: (input) => request("POST", "/v1/agents", { ...input }),
37
+ update: (intent, patch) => request("PUT", "/v1/agents", { intent, ...patch }),
38
+ enable: (intent) => request("PUT", "/v1/agents", { intent, enabled: true }),
39
+ disable: (intent) => request("PUT", "/v1/agents", { intent, enabled: false }),
40
+ delete: (intent) => request("DELETE", `/v1/agents/${encodeURIComponent(intent)}`)
41
+ },
42
+ tools: {
43
+ list: () => request("GET", "/v1/tools"),
44
+ create: (input) => request("POST", "/v1/tools", { ...input }),
45
+ bind: (name, binding) => request("PUT", `/v1/tools/${encodeURIComponent(name)}`, { ...binding }),
46
+ test: (name) => request("POST", `/v1/tools/${encodeURIComponent(name)}/test`),
47
+ importOpenApi: (input) => request("POST", "/v1/tools/import", { ...input })
48
+ },
49
+ plugins: {
50
+ list: () => request("GET", "/v1/plugins"),
51
+ install: (id) => request("POST", `/v1/plugins/${encodeURIComponent(id)}/install`),
52
+ uninstall: (id) => request("POST", `/v1/plugins/${encodeURIComponent(id)}/uninstall`)
53
+ },
54
+ customers: {
55
+ list: (opts = {}) => request("GET", `/v1/customers?limit=${opts.limit ?? 100}${opts.range ? `&range=${opts.range}` : ""}`),
56
+ upsert: (input) => request("POST", "/v1/customers", { ...input }),
57
+ get: (externalId) => request("GET", `/v1/customers/${encodeURIComponent(externalId)}`)
58
+ },
59
+ settings: {
60
+ get: () => request("GET", "/v1/settings"),
61
+ update: (patch) => request("PUT", "/v1/settings", patch)
62
+ },
63
+ billing: {
64
+ get: () => request("GET", "/v1/billing"),
65
+ topup: (amountNgn, email) => request("POST", "/v1/billing/topup", { amount: amountNgn, ...email ? { email } : {} })
66
+ },
67
+ usage: {
68
+ summary: () => request("GET", "/v1/usage"),
69
+ events: (limit = 20) => request("GET", `/v1/usage/events?limit=${limit}`),
70
+ event: (id) => request("GET", `/v1/usage/events/${id}`),
71
+ analytics: (days = 30) => request("GET", `/v1/usage/analytics?days=${days}`)
72
+ },
73
+ manifest: () => request("GET", "/v1/manifest")
74
+ };
75
+ }
76
+
30
77
  // src/client.ts
31
78
  var DEFAULT_BASE_URL = "https://ai.twelveai.app";
32
79
  var TwelveAI = class {
@@ -35,6 +82,11 @@ var TwelveAI = class {
35
82
  fetchImpl;
36
83
  clientAuth;
37
84
  maxHandoffRounds;
85
+ /**
86
+ * Everything the console can do, from code: agents, tools, plugins,
87
+ * customers, settings, billing, usage. `twelve.manage.plugins.install('bills')`.
88
+ */
89
+ manage;
38
90
  constructor(options) {
39
91
  if (!options?.apiKey) throw new Error("TwelveAI: apiKey is required.");
40
92
  this.apiKey = options.apiKey;
@@ -45,6 +97,29 @@ var TwelveAI = class {
45
97
  if (typeof this.fetchImpl !== "function") {
46
98
  throw new Error("TwelveAI: global fetch is unavailable - pass options.fetch (Node 18+ has fetch built in).");
47
99
  }
100
+ this.manage = buildManage((method, path, body) => this.api(method, path, body));
101
+ }
102
+ /**
103
+ * Low-level authenticated call to any engine endpoint. Returns
104
+ * `{ ok, status, ...payload }`; never throws on HTTP errors.
105
+ */
106
+ async api(method, path, body) {
107
+ try {
108
+ const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
109
+ method,
110
+ headers: { "content-type": "application/json", "x-api-key": this.apiKey },
111
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
112
+ });
113
+ const data = await res.json().catch(() => ({}));
114
+ return {
115
+ ...data,
116
+ ok: res.ok && data.ok !== false,
117
+ status: res.status,
118
+ ...res.ok ? {} : { error: data.error ?? `Engine returned ${res.status}` }
119
+ };
120
+ } catch (error) {
121
+ return { ok: false, status: 0, error: error?.message || "Could not reach the engine." };
122
+ }
48
123
  }
49
124
  /**
50
125
  * Send one chat turn and return the completed result. Read hand-offs are
@@ -78,16 +153,18 @@ var TwelveAI = class {
78
153
  const res = await this.fetchImpl(`${this.baseUrl}/v1/classify`, {
79
154
  method: "POST",
80
155
  headers: { "content-type": "application/json", "x-api-key": this.apiKey },
81
- body: JSON.stringify({ message: input.message })
156
+ body: JSON.stringify({ message: input.message, ...input.reasoning ? { reasoning: input.reasoning } : {} })
82
157
  });
83
158
  const data = await res.json().catch(() => ({}));
84
159
  return {
160
+ intent: null,
161
+ label: null,
162
+ confidence: 0,
163
+ alternatives: [],
164
+ entities: {},
165
+ ...data,
166
+ // pass every field through (matchedKeywords, score, margin, classifyOnly, ...)
85
167
  ok: res.ok && data.ok !== false,
86
- intent: data.intent ?? null,
87
- label: data.label ?? null,
88
- confidence: data.confidence ?? 0,
89
- alternatives: data.alternatives ?? [],
90
- entities: data.entities ?? {},
91
168
  status: res.status,
92
169
  ...res.ok ? {} : { error: data.error ?? `Engine returned ${res.status}` }
93
170
  };
@@ -106,6 +183,7 @@ var TwelveAI = class {
106
183
  if (input.channel) body.channel = input.channel;
107
184
  if (input.intent) body.intent = input.intent;
108
185
  if (input.tier) body.tier = input.tier;
186
+ if (input.reasoning) body.reasoning = input.reasoning;
109
187
  if (input.customerToken) body.customerToken = input.customerToken;
110
188
  if (input.attachments?.length) body.attachments = input.attachments;
111
189
  if (input.metadata) body.metadata = input.metadata;
@@ -268,6 +346,7 @@ function header(headers, name) {
268
346
  // Annotate the CommonJS export names for ESM import in node:
269
347
  0 && (module.exports = {
270
348
  TwelveAI,
349
+ buildManage,
271
350
  createJwksVerifier,
272
351
  verifySignedRequest,
273
352
  verifyWebhook
package/dist/index.d.cts CHANGED
@@ -1,203 +1,4 @@
1
- /** Shared request/response types for the TwelveAI chat API. */
2
- interface TwelveAIOptions {
3
- /** Your workspace API key (sk_live_... / sk_test_...). */
4
- apiKey: string;
5
- /** Engine base URL. Defaults to the hosted platform. */
6
- baseUrl?: string;
7
- /**
8
- * Auth your server adds when the SDK performs client-fetch hand-offs against
9
- * YOUR OWN API (the engine hands the resolved request back without any
10
- * credentials). Static headers, or a function returning them per request.
11
- */
12
- clientAuth?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
13
- /** Custom fetch implementation (tests, polyfills). Defaults to global fetch. */
14
- fetch?: typeof globalThis.fetch;
15
- /** Max auto-resume rounds for client-fetch hand-offs per chat() call. Default 3. */
16
- maxHandoffRounds?: number;
17
- }
18
- interface Attachment {
19
- /** Public URL, or a data: URL. */
20
- url?: string;
21
- /** Base64 content (alternative to url). */
22
- data?: string;
23
- mediaType?: string;
24
- /** A WhatsApp media id, if the engine should fetch it via your connected WhatsApp. */
25
- whatsappMediaId?: string;
26
- }
27
- interface ChatInput {
28
- /** The end user's message. Optional when resuming or sending only attachments. */
29
- message?: string;
30
- /** Your id for this end user (alias: userId). Required for customer-scoped agents. */
31
- customerId?: string;
32
- /** Continue an existing conversation with the token from the previous turn. */
33
- continuation?: string;
34
- /** The user approved a pending action (PIN/OTP collected on your side). */
35
- confirmed?: boolean;
36
- /** Sandbox: tools return sample data; nothing real is called or moved. */
37
- sandbox?: boolean;
38
- channel?: string;
39
- /** Force a specific agent instead of routing. */
40
- intent?: string;
41
- /** Customer tier to sync for this turn's caps. */
42
- tier?: string;
43
- /**
44
- * Short-lived end-user session token, forwarded verbatim on tool bindings
45
- * with auth type 'customer_token'. Never stored by the engine.
46
- */
47
- customerToken?: string;
48
- /** Images / voice notes attached to this turn. */
49
- attachments?: Attachment[];
50
- metadata?: Record<string, unknown>;
51
- }
52
- interface ToolCall {
53
- name: string;
54
- arguments: Record<string, unknown>;
55
- result: unknown;
56
- }
57
- interface HandoffRequest {
58
- method: string;
59
- url: string;
60
- headers?: Record<string, string>;
61
- body?: Record<string, unknown>;
62
- }
63
- interface PendingToolCall {
64
- id: string;
65
- name: string;
66
- arguments: Record<string, unknown>;
67
- /** Client-fetch hand-off: the resolved request your server should perform. */
68
- request?: HandoffRequest;
69
- }
70
- interface ToolResult {
71
- id: string;
72
- result: unknown;
73
- }
74
- interface ChatResponse {
75
- ok: boolean;
76
- sandbox?: boolean;
77
- /** The assistant's reply to show the user. */
78
- message: string | null;
79
- intent: string | null;
80
- toolCalls: ToolCall[];
81
- /** A write awaiting the user's confirmation (resend with confirmed: true). */
82
- pendingConfirmation: {
83
- tool: string;
84
- arguments: Record<string, unknown>;
85
- } | null;
86
- /**
87
- * Client-executed tool calls YOUR system must run. With auto-execution on
88
- * (the default), read hand-offs are already completed by the SDK; anything
89
- * left here is yours to handle (typically a money move awaiting PIN).
90
- */
91
- pendingToolCalls: PendingToolCall[] | null;
92
- /** Pass this back on the next turn to continue the conversation. */
93
- continuation: string | null;
94
- escalated?: boolean;
95
- policy?: string | null;
96
- autonomy?: string | null;
97
- fee?: {
98
- feeNgn: number;
99
- amountNgn: number;
100
- totalNgn: number;
101
- } | null;
102
- usage?: {
103
- inputTokens: number;
104
- outputTokens: number;
105
- };
106
- billing?: Record<string, unknown>;
107
- latencyMs?: number;
108
- metadata?: Record<string, unknown>;
109
- error?: string;
110
- /** HTTP status of the underlying call. */
111
- status: number;
112
- /** Hand-offs the SDK auto-executed to complete this turn (for observability). */
113
- executedHandoffs?: Array<{
114
- name: string;
115
- method: string;
116
- url: string;
117
- ok: boolean;
118
- }>;
119
- }
120
- /**
121
- * Executor for one client-fetch hand-off. Return the tool result the engine
122
- * resumes with. The default executor performs `call.request` with your
123
- * `clientAuth` headers and returns `{ ok, data }`.
124
- */
125
- type HandoffExecutor = (call: PendingToolCall) => Promise<unknown>;
126
- interface ClassifyResponse {
127
- ok: boolean;
128
- /** The winning agent intent, or null when nothing matched. */
129
- intent: string | null;
130
- label: string | null;
131
- /** Deterministic confidence in [0, 0.95]; 0 = no match. */
132
- confidence: number;
133
- alternatives: Array<{
134
- intent: string;
135
- label: string;
136
- }>;
137
- /** Cheap extracted entities: amount, account_number, phone (when present). */
138
- entities: Record<string, unknown>;
139
- status: number;
140
- error?: string;
141
- }
142
-
143
- /**
144
- * The TwelveAI client. One call does the whole conversation protocol:
145
- *
146
- * const twelve = new TwelveAI({ apiKey: process.env.TWELVE_API_KEY! })
147
- * const res = await twelve.chat({ message: "what's my balance?", customerId: 'cus_123' })
148
- * console.log(res.message)
149
- *
150
- * Client-fetch hand-offs (tools configured as "my app calls it") are executed
151
- * automatically against your own API - the engine never holds your credentials;
152
- * you supply them once via `clientAuth` and the SDK completes the loop. Money
153
- * moves are never auto-executed: they surface in `pendingToolCalls` /
154
- * `pendingConfirmation` for your PIN flow, then you call `confirm()` or
155
- * `resume()`.
156
- */
157
- declare class TwelveAI {
158
- private readonly apiKey;
159
- private readonly baseUrl;
160
- private readonly fetchImpl;
161
- private readonly clientAuth;
162
- private readonly maxHandoffRounds;
163
- constructor(options: TwelveAIOptions);
164
- /**
165
- * Send one chat turn and return the completed result. Read hand-offs are
166
- * auto-executed (see class docs); pass `autoExecute: false` to get the raw
167
- * paused response instead, or `onHandoff` to execute them yourself.
168
- */
169
- chat(input: ChatInput, opts?: {
170
- autoExecute?: boolean;
171
- onHandoff?: HandoffExecutor;
172
- }): Promise<ChatResponse>;
173
- /** Resume a paused turn with tool results your system produced. */
174
- resume(continuation: string, toolResults: ToolResult[], input?: Pick<ChatInput, 'customerId' | 'channel' | 'sandbox' | 'customerToken'>): Promise<ChatResponse>;
175
- /**
176
- * Approve a pending action (after your PIN/OTP step) - resends the turn with
177
- * `confirmed: true` so the engine proceeds.
178
- */
179
- confirm(continuation: string, input?: Omit<ChatInput, 'continuation' | 'confirmed'>): Promise<ChatResponse>;
180
- /**
181
- * Level-0 integration: classify a message WITHOUT running the conversation.
182
- * Returns the intent, a deterministic confidence score, and cheap extracted
183
- * entities (amount / account number / phone) - you keep your existing flows
184
- * and make the call yourself. Free: no tools run, nothing is stored.
185
- */
186
- classify(input: {
187
- message: string;
188
- }): Promise<ClassifyResponse>;
189
- private chatBody;
190
- private post;
191
- /**
192
- * Execute client-fetch hand-offs and resume until the turn completes. Only
193
- * calls that carry a resolved `request` are auto-executed - a hand-off
194
- * without one (e.g. a money move awaiting your PIN flow) stops the loop and
195
- * is returned to you untouched.
196
- */
197
- private completeHandoffs;
198
- /** Default hand-off executor: perform the request with your clientAuth headers. */
199
- private performHandoff;
200
- }
1
+ export { A as Attachment, B as BindToolInput, C as ChatInput, a as ChatResponse, b as ClassifyResponse, c as CreateAgentInput, d as CreateToolInput, H as HandoffExecutor, e as HandoffRequest, M as Manage, f as ManageResult, P as PendingToolCall, g as ToolCall, h as ToolResult, T as TwelveAI, i as TwelveAIOptions, j as buildManage } from './client-C5vzks2N.cjs';
201
2
 
202
3
  /** Verify a TwelveAI webhook delivery: the x-webhook-secret header must match your secret. */
203
4
  declare function verifyWebhook(secret: string, headers: Record<string, string | string[] | undefined>): boolean;
@@ -252,4 +53,4 @@ declare function createJwksVerifier(options?: JwksVerifierOptions): (input: JwtR
252
53
  claims?: Record<string, unknown>;
253
54
  }>;
254
55
 
255
- export { type Attachment, type ChatInput, type ChatResponse, type ClassifyResponse, type HandoffExecutor, type HandoffRequest, type JwksVerifierOptions, type JwtRequestInput, type PendingToolCall, type SignedRequestInput, type ToolCall, type ToolResult, TwelveAI, type TwelveAIOptions, createJwksVerifier, verifySignedRequest, verifyWebhook };
56
+ export { type JwksVerifierOptions, type JwtRequestInput, type SignedRequestInput, createJwksVerifier, verifySignedRequest, verifyWebhook };