twelveai 0.3.1 → 0.6.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/cli.js ADDED
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ TwelveAI
4
+ } from "./chunk-7VVR7AFE.js";
5
+
6
+ // src/cli.ts
7
+ import { readFileSync } from "fs";
8
+ var HELP = `twelveai <command> [args]
9
+
10
+ Conversation
11
+ chat "<message>" [--customer <id>] [--sandbox] [--reasoning off|auto|always]
12
+ classify "<message>" [--reasoning off|auto|always]
13
+
14
+ Manage (everything the console does)
15
+ agents list | create --file <agent.json> | enable <intent> | disable <intent> | delete <intent>
16
+ tools list | create --file <tool.json> | bind <name> --file <binding.json> | test <name>
17
+ plugins list | install <id> | uninstall <id>
18
+ customers list | set <externalId> [--tier <tier>] [--name <name>] [--email <email>]
19
+ settings get | set --file <settings.json>
20
+ billing (show balance) | topup <amountNgn>
21
+ usage (summary) | requests [--limit <n>] | request <id>
22
+ manifest (the per-agent tool-call contract)
23
+
24
+ Auth: set TWELVE_API_KEY (and optionally TWELVE_BASE_URL).`;
25
+ function flag(args, name) {
26
+ const i = args.indexOf(`--${name}`);
27
+ return i >= 0 ? args[i + 1] : void 0;
28
+ }
29
+ var has = (args, name) => args.includes(`--${name}`);
30
+ var positional = (args) => args.filter((a, i) => !a.startsWith("--") && !(i > 0 && args[i - 1].startsWith("--")));
31
+ async function runCli(argv, deps) {
32
+ const [cmd, ...rest] = argv;
33
+ if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
34
+ deps.log(HELP);
35
+ return 0;
36
+ }
37
+ const apiKey = deps.env.TWELVE_API_KEY;
38
+ if (!apiKey) {
39
+ deps.error("Set TWELVE_API_KEY to use the CLI (find yours in the console under Settings).");
40
+ return 1;
41
+ }
42
+ const twelve = deps.client ?? new TwelveAI({ apiKey, baseUrl: deps.env.TWELVE_BASE_URL });
43
+ const m = twelve.manage;
44
+ const json = (v) => deps.log(JSON.stringify(v, null, 2));
45
+ const loadJson = (label) => {
46
+ const file = flag(rest, "file");
47
+ if (!file) {
48
+ deps.error(`--file <${label}.json> is required.`);
49
+ return null;
50
+ }
51
+ try {
52
+ return JSON.parse(deps.readFile(file));
53
+ } catch (e) {
54
+ deps.error(`Could not read ${file}: ${e.message}`);
55
+ return null;
56
+ }
57
+ };
58
+ const done = (r) => r.ok ? 0 : 1;
59
+ const pos = positional(rest);
60
+ const sub = pos[0];
61
+ switch (cmd) {
62
+ case "chat": {
63
+ if (!sub) return deps.error('Usage: twelveai chat "<message>"'), 1;
64
+ const r = await twelve.chat({
65
+ message: sub,
66
+ customerId: flag(rest, "customer"),
67
+ sandbox: has(rest, "sandbox") || void 0,
68
+ reasoning: flag(rest, "reasoning")
69
+ });
70
+ json(r);
71
+ return done(r);
72
+ }
73
+ case "classify": {
74
+ if (!sub) return deps.error('Usage: twelveai classify "<message>"'), 1;
75
+ const r = await twelve.classify({ message: sub, reasoning: flag(rest, "reasoning") });
76
+ json(r);
77
+ return done(r);
78
+ }
79
+ case "agents": {
80
+ if (sub === "list" || !sub) return json(await m.agents.list()), 0;
81
+ if (sub === "create") {
82
+ const b = loadJson("agent");
83
+ if (!b) return 1;
84
+ const r = await m.agents.create(b);
85
+ json(r);
86
+ return done(r);
87
+ }
88
+ if (sub === "enable" && pos[1]) {
89
+ const r = await m.agents.enable(pos[1]);
90
+ json(r);
91
+ return done(r);
92
+ }
93
+ if (sub === "disable" && pos[1]) {
94
+ const r = await m.agents.disable(pos[1]);
95
+ json(r);
96
+ return done(r);
97
+ }
98
+ if (sub === "delete" && pos[1]) {
99
+ const r = await m.agents.delete(pos[1]);
100
+ json(r);
101
+ return done(r);
102
+ }
103
+ deps.error("Usage: twelveai agents list | create --file a.json | enable <intent> | disable <intent> | delete <intent>");
104
+ return 1;
105
+ }
106
+ case "tools": {
107
+ if (sub === "list" || !sub) return json(await m.tools.list()), 0;
108
+ if (sub === "create") {
109
+ const b = loadJson("tool");
110
+ if (!b) return 1;
111
+ const r = await m.tools.create(b);
112
+ json(r);
113
+ return done(r);
114
+ }
115
+ if (sub === "bind" && pos[1]) {
116
+ const b = loadJson("binding");
117
+ if (!b) return 1;
118
+ const r = await m.tools.bind(pos[1], b);
119
+ json(r);
120
+ return done(r);
121
+ }
122
+ if (sub === "test" && pos[1]) {
123
+ const r = await m.tools.test(pos[1]);
124
+ json(r);
125
+ return done(r);
126
+ }
127
+ deps.error("Usage: twelveai tools list | create --file t.json | bind <name> --file b.json | test <name>");
128
+ return 1;
129
+ }
130
+ case "plugins": {
131
+ if (sub === "list" || !sub) return json(await m.plugins.list()), 0;
132
+ if (sub === "install" && pos[1]) {
133
+ const r = await m.plugins.install(pos[1]);
134
+ json(r);
135
+ return done(r);
136
+ }
137
+ if (sub === "uninstall" && pos[1]) {
138
+ const r = await m.plugins.uninstall(pos[1]);
139
+ json(r);
140
+ return done(r);
141
+ }
142
+ deps.error("Usage: twelveai plugins list | install <id> | uninstall <id>");
143
+ return 1;
144
+ }
145
+ case "customers": {
146
+ if (sub === "list" || !sub) return json(await m.customers.list({ limit: Number(flag(rest, "limit")) || 100 })), 0;
147
+ if (sub === "set" && pos[1]) {
148
+ const r = await m.customers.upsert({ externalId: pos[1], tier: flag(rest, "tier"), name: flag(rest, "name"), email: flag(rest, "email") });
149
+ json(r);
150
+ return done(r);
151
+ }
152
+ deps.error("Usage: twelveai customers list | set <externalId> --tier <tier>");
153
+ return 1;
154
+ }
155
+ case "settings": {
156
+ if (sub === "get" || !sub) return json(await m.settings.get()), 0;
157
+ if (sub === "set") {
158
+ const b = loadJson("settings");
159
+ if (!b) return 1;
160
+ const r = await m.settings.update(b);
161
+ json(r);
162
+ return done(r);
163
+ }
164
+ deps.error("Usage: twelveai settings get | set --file settings.json");
165
+ return 1;
166
+ }
167
+ case "billing":
168
+ return json(await m.billing.get()), 0;
169
+ case "topup": {
170
+ const amount = Number(sub);
171
+ if (!amount || amount < 5e3) return deps.error("Usage: twelveai topup <amountNgn> (minimum 5000)"), 1;
172
+ const r = await m.billing.topup(amount, flag(rest, "email"));
173
+ json(r);
174
+ return done(r);
175
+ }
176
+ case "usage":
177
+ return json(await m.usage.summary()), 0;
178
+ case "requests":
179
+ return json(await m.usage.events(Number(flag(rest, "limit")) || 20)), 0;
180
+ case "request": {
181
+ if (!sub) return deps.error("Usage: twelveai request <id>"), 1;
182
+ return json(await m.usage.event(sub)), 0;
183
+ }
184
+ case "manifest":
185
+ return json(await m.manifest()), 0;
186
+ default:
187
+ deps.error(`Unknown command "${cmd}".
188
+
189
+ ${HELP}`);
190
+ return 1;
191
+ }
192
+ }
193
+ var isMain = process.argv[1]?.endsWith("cli.js") || process.argv[1]?.endsWith("twelveai");
194
+ if (isMain) {
195
+ runCli(process.argv.slice(2), {
196
+ env: process.env,
197
+ log: (s) => console.log(s),
198
+ error: (s) => console.error(s),
199
+ readFile: (p) => readFileSync(p, "utf8")
200
+ }).then((code) => process.exit(code));
201
+ }
202
+ export {
203
+ runCli
204
+ };
@@ -0,0 +1,490 @@
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
+ /**
40
+ * Pin the turn to one agent, skipping the router entirely - no keyword pass,
41
+ * no AI pass, no mid-conversation switch. Use it when YOU already know the
42
+ * intent (a deep link, a menu choice, an IVR branch, a batch job), not on a
43
+ * general chat box: the pinned agent answers whatever the customer says next,
44
+ * with its own tools. Every pinned response carries `warning` saying so.
45
+ */
46
+ agent?: string;
47
+ /** Alias of `agent`, kept for existing integrations. */
48
+ intent?: string;
49
+ /** Customer tier to sync for this turn's caps. */
50
+ tier?: string;
51
+ /** Routing reasoning: 'off' | 'auto' (default) | 'always'. */
52
+ reasoning?: 'off' | 'auto' | 'always';
53
+ /**
54
+ * Short-lived end-user session token, forwarded verbatim on tool bindings
55
+ * with auth type 'customer_token'. Never stored by the engine.
56
+ */
57
+ customerToken?: string;
58
+ /** Images / voice notes attached to this turn. */
59
+ attachments?: Attachment[];
60
+ metadata?: Record<string, unknown>;
61
+ }
62
+ interface ToolCall {
63
+ name: string;
64
+ arguments: Record<string, unknown>;
65
+ result: unknown;
66
+ }
67
+ interface HandoffRequest {
68
+ method: string;
69
+ url: string;
70
+ headers?: Record<string, string>;
71
+ body?: Record<string, unknown>;
72
+ }
73
+ interface PendingToolCall {
74
+ id: string;
75
+ name: string;
76
+ arguments: Record<string, unknown>;
77
+ /** Client-fetch hand-off: the resolved request your server should perform. */
78
+ request?: HandoffRequest;
79
+ }
80
+ interface ToolResult {
81
+ id: string;
82
+ result: unknown;
83
+ }
84
+ interface ChatResponse {
85
+ ok: boolean;
86
+ sandbox?: boolean;
87
+ /** The assistant's reply to show the user. */
88
+ message: string | null;
89
+ intent: string | null;
90
+ /** Routing confidence for the intent, same scale as classify. Null on resumes and guide fallback. */
91
+ confidence?: number | null;
92
+ /**
93
+ * Non-fatal advice about how this turn was handled: set when you pinned an
94
+ * agent (the router was skipped), or when the pin named an agent that could
95
+ * not run. Never an error - the reply in `message` still stands.
96
+ */
97
+ warning?: string | null;
98
+ toolCalls: ToolCall[];
99
+ /** A write awaiting the user's confirmation (resend with confirmed: true). */
100
+ pendingConfirmation: {
101
+ tool: string;
102
+ arguments: Record<string, unknown>;
103
+ } | null;
104
+ /**
105
+ * Client-executed tool calls YOUR system must run. With auto-execution on
106
+ * (the default), read hand-offs are already completed by the SDK; anything
107
+ * left here is yours to handle (typically a money move awaiting PIN).
108
+ */
109
+ pendingToolCalls: PendingToolCall[] | null;
110
+ /** Pass this back on the next turn to continue the conversation. */
111
+ continuation: string | null;
112
+ escalated?: boolean;
113
+ policy?: string | null;
114
+ autonomy?: string | null;
115
+ fee?: {
116
+ feeNgn: number;
117
+ amountNgn: number;
118
+ totalNgn: number;
119
+ } | null;
120
+ usage?: {
121
+ inputTokens: number;
122
+ outputTokens: number;
123
+ };
124
+ billing?: Record<string, unknown>;
125
+ latencyMs?: number;
126
+ metadata?: Record<string, unknown>;
127
+ error?: string;
128
+ /** HTTP status of the underlying call. */
129
+ status: number;
130
+ /** Hand-offs the SDK auto-executed to complete this turn (for observability). */
131
+ executedHandoffs?: Array<{
132
+ name: string;
133
+ method: string;
134
+ url: string;
135
+ ok: boolean;
136
+ }>;
137
+ }
138
+ /**
139
+ * Executor for one client-fetch hand-off. Return the tool result the engine
140
+ * resumes with. The default executor performs `call.request` with your
141
+ * `clientAuth` headers and returns `{ ok, data }`.
142
+ */
143
+ type HandoffExecutor = (call: PendingToolCall) => Promise<unknown>;
144
+ interface ClassifyResponse {
145
+ ok: boolean;
146
+ /** The winning agent intent, or null when nothing matched. */
147
+ intent: string | null;
148
+ label: string | null;
149
+ /** Deterministic confidence in [0, 0.95]; 0 = no match. */
150
+ confidence: number;
151
+ alternatives: Array<{
152
+ intent: string;
153
+ label: string;
154
+ confidence?: number;
155
+ matchedKeywords?: string[];
156
+ }>;
157
+ /** The exact keywords that selected the winning intent (explainability). */
158
+ matchedKeywords?: string[];
159
+ /** Raw keyword-hit count for the winner, and its lead over the runner-up. */
160
+ score?: number;
161
+ margin?: number;
162
+ /** True when the winning intent is classifier-only (your systems handle it). */
163
+ classifyOnly?: boolean;
164
+ /** Extracted entities: amount, account_number, phone, bank {name, code}, currency. */
165
+ entities: Record<string, unknown>;
166
+ status: number;
167
+ error?: string;
168
+ }
169
+
170
+ /**
171
+ * Management API - everything the console can do, callable from code. Thin,
172
+ * typed-enough wrappers over the engine's management endpoints, all
173
+ * authenticated with the same x-api-key as chat. Every method resolves to
174
+ * `{ ok, status, ...payload }` and never throws on HTTP errors.
175
+ */
176
+ interface ManageResult {
177
+ ok: boolean;
178
+ status: number;
179
+ error?: string;
180
+ [key: string]: unknown;
181
+ }
182
+ /** A placeholder you may put in a tool's URL; the engine fills it per turn. */
183
+ interface ToolVariable {
184
+ /** Use it as `{name}` in the URL, path or query. */
185
+ name: string;
186
+ type: string;
187
+ description: string | null;
188
+ required: boolean;
189
+ }
190
+ /** One tool as GET /v1/tools returns it. */
191
+ interface ToolListItem {
192
+ name: string;
193
+ description: string;
194
+ sideEffect: 'read' | 'write';
195
+ permission: string | null;
196
+ kind: 'managed' | 'client' | 'http';
197
+ execution: 'hosted' | 'client';
198
+ binding: {
199
+ method: string;
200
+ url: string;
201
+ resultPath: string | null;
202
+ } | null;
203
+ hasAuth: boolean;
204
+ auth: {
205
+ type: string;
206
+ header: string | null;
207
+ } | null;
208
+ sampleResponse: unknown;
209
+ tenantSample?: boolean;
210
+ example: {
211
+ method: string;
212
+ url: string;
213
+ } | null;
214
+ /** Placeholders this tool understands - the click-to-insert list in the console. */
215
+ variables: ToolVariable[];
216
+ agents: string[];
217
+ editable: boolean;
218
+ }
219
+ interface ToolsResult extends ManageResult {
220
+ tools: ToolListItem[];
221
+ }
222
+ /** A published version of an agent pack, newest first. */
223
+ interface PluginRelease {
224
+ version: string;
225
+ date: string;
226
+ breaking?: boolean;
227
+ changes: string[];
228
+ }
229
+ /** Domain vocabulary a pack's tools use, so you can map it to your own API. */
230
+ interface PluginConcept {
231
+ term: string;
232
+ meaning: string;
233
+ }
234
+ interface PluginToolSpec {
235
+ name: string;
236
+ description: string | null;
237
+ sideEffect: 'read' | 'write' | null;
238
+ variables: ToolVariable[];
239
+ }
240
+ interface PluginListItem {
241
+ id: string;
242
+ name: string;
243
+ description: string;
244
+ category: string;
245
+ version: string;
246
+ intent: string;
247
+ tools: string[];
248
+ visibility: 'public' | 'private';
249
+ installed: boolean;
250
+ configured?: boolean;
251
+ managedByPlugin?: boolean;
252
+ installedVersion: string | null;
253
+ updateAvailable: boolean;
254
+ /** True when you run this agent outside the marketplace and could follow its releases. */
255
+ canTrack?: boolean;
256
+ details: {
257
+ about: string;
258
+ examples: string[];
259
+ dataSource: string;
260
+ concepts?: PluginConcept[];
261
+ } | null;
262
+ /** Per-tool placeholders, visible before you install. */
263
+ toolSpecs?: PluginToolSpec[];
264
+ /** Releases between the version you run and the current one. */
265
+ releases?: PluginRelease[];
266
+ }
267
+ interface PluginsResult extends ManageResult {
268
+ plugins: PluginListItem[];
269
+ }
270
+ /** One tool in GET /v1/manifest - the contract you code against. */
271
+ interface ManifestTool {
272
+ name: string;
273
+ description: string;
274
+ parameters: Record<string, unknown>;
275
+ sideEffect: 'read' | 'write';
276
+ permission: string | null;
277
+ managed: boolean;
278
+ execution: 'hosted' | 'client';
279
+ /** True when the ENGINE invokes this tool itself; it never appears as a model decision. */
280
+ automatic?: boolean;
281
+ binding: {
282
+ method: string;
283
+ url: string;
284
+ } | null;
285
+ }
286
+ interface ManifestResult extends ManageResult {
287
+ agents: Array<{
288
+ intent: string;
289
+ label: string;
290
+ requiresCustomer: boolean;
291
+ permissions: string[] | null;
292
+ tools: ManifestTool[];
293
+ }>;
294
+ }
295
+ /**
296
+ * Per-tool endpoint auth. A discriminated union on purpose: TypeScript rejects
297
+ * a bearer without a token, or an api_key missing its header/value, at compile
298
+ * time rather than at the first live call.
299
+ */
300
+ type ToolAuth = {
301
+ type: 'none';
302
+ } | {
303
+ type: 'bearer';
304
+ token: string;
305
+ } | {
306
+ type: 'api_key';
307
+ header: string;
308
+ value: string;
309
+ } | {
310
+ type: 'signed';
311
+ } | {
312
+ type: 'jwks';
313
+ } | {
314
+ type: 'customer_token';
315
+ } | {
316
+ type: 'oauth2';
317
+ tokenUrl: string;
318
+ clientId: string;
319
+ clientSecret: string;
320
+ scope?: string;
321
+ };
322
+ interface CreateAgentInput {
323
+ intent: string;
324
+ label?: string;
325
+ keywords: string[];
326
+ /** With instructions (and optionally tools) this creates a FULL chat agent; without, a classifier-only intent. */
327
+ systemPrompt?: string;
328
+ tools?: string[];
329
+ requiresCustomer?: boolean;
330
+ /**
331
+ * 'internal' makes this your own team's agent: used from the console's agent
332
+ * page, invisible to the API key your customers talk to. Default 'customer'.
333
+ */
334
+ audience?: 'customer' | 'internal';
335
+ /** An internal agent's remit, in plain words. Put in front of every turn and enforced by refusal. */
336
+ scope?: string;
337
+ }
338
+ interface CreateToolInput {
339
+ name: string;
340
+ description: string;
341
+ sideEffect: 'read' | 'write';
342
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
343
+ /** {placeholders} become the tool's arguments; {customer_id} is filled per turn. */
344
+ url: string;
345
+ execution?: 'hosted' | 'client';
346
+ /** A real example response - drives result parsing and the sandbox. */
347
+ sampleResponse?: unknown;
348
+ }
349
+ interface BindToolInput {
350
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
351
+ url: string;
352
+ resultPath?: string | null;
353
+ sampleResponse?: unknown;
354
+ execution?: 'hosted' | 'client';
355
+ auth?: ToolAuth;
356
+ }
357
+ type Request = (method: string, path: string, body?: Record<string, unknown>) => Promise<ManageResult>;
358
+ /** Build the management namespaces over one authenticated request function. */
359
+ declare function buildManage(request: Request): {
360
+ agents: {
361
+ list: () => Promise<ManageResult>;
362
+ create: (input: CreateAgentInput) => Promise<ManageResult>;
363
+ update: (intent: string, patch: Record<string, unknown>) => Promise<ManageResult>;
364
+ enable: (intent: string) => Promise<ManageResult>;
365
+ disable: (intent: string) => Promise<ManageResult>;
366
+ delete: (intent: string) => Promise<ManageResult>;
367
+ };
368
+ tools: {
369
+ list: () => Promise<ToolsResult>;
370
+ create: (input: CreateToolInput) => Promise<ManageResult>;
371
+ bind: (name: string, binding: BindToolInput) => Promise<ManageResult>;
372
+ test: (name: string) => Promise<ManageResult>;
373
+ importOpenApi: (input: {
374
+ url?: string;
375
+ spec?: unknown;
376
+ execution?: "hosted" | "client";
377
+ dryRun?: boolean;
378
+ auth?: ToolAuth;
379
+ }) => Promise<ManageResult>;
380
+ };
381
+ plugins: {
382
+ list: () => Promise<PluginsResult>;
383
+ install: (id: string) => Promise<PluginsResult>;
384
+ uninstall: (id: string) => Promise<PluginsResult>;
385
+ /** Follow a pack's releases for an agent you already run. Changes nothing today. */
386
+ track: (id: string) => Promise<PluginsResult>;
387
+ };
388
+ customers: {
389
+ list: (opts?: {
390
+ limit?: number;
391
+ range?: string;
392
+ }) => Promise<ManageResult>;
393
+ upsert: (input: {
394
+ externalId: string;
395
+ tier?: string | null;
396
+ name?: string;
397
+ email?: string;
398
+ status?: string;
399
+ }) => Promise<ManageResult>;
400
+ get: (externalId: string) => Promise<ManageResult>;
401
+ };
402
+ settings: {
403
+ get: () => Promise<ManageResult>;
404
+ update: (patch: Record<string, unknown>) => Promise<ManageResult>;
405
+ };
406
+ billing: {
407
+ get: () => Promise<ManageResult>;
408
+ topup: (amountNgn: number, email?: string) => Promise<ManageResult>;
409
+ };
410
+ usage: {
411
+ summary: () => Promise<ManageResult>;
412
+ events: (limit?: number) => Promise<ManageResult>;
413
+ event: (id: number | string) => Promise<ManageResult>;
414
+ analytics: (days?: number) => Promise<ManageResult>;
415
+ };
416
+ manifest: () => Promise<ManifestResult>;
417
+ };
418
+ type Manage = ReturnType<typeof buildManage>;
419
+
420
+ /**
421
+ * The TwelveAI client. One call does the whole conversation protocol:
422
+ *
423
+ * const twelve = new TwelveAI({ apiKey: process.env.TWELVE_API_KEY! })
424
+ * const res = await twelve.chat({ message: "what's my balance?", customerId: 'cus_123' })
425
+ * console.log(res.message)
426
+ *
427
+ * Client-fetch hand-offs (tools configured as "my app calls it") are executed
428
+ * automatically against your own API - the engine never holds your credentials;
429
+ * you supply them once via `clientAuth` and the SDK completes the loop. Money
430
+ * moves are never auto-executed: they surface in `pendingToolCalls` /
431
+ * `pendingConfirmation` for your PIN flow, then you call `confirm()` or
432
+ * `resume()`.
433
+ */
434
+ declare class TwelveAI {
435
+ private readonly apiKey;
436
+ private readonly baseUrl;
437
+ private readonly fetchImpl;
438
+ private readonly clientAuth;
439
+ private readonly maxHandoffRounds;
440
+ /**
441
+ * Everything the console can do, from code: agents, tools, plugins,
442
+ * customers, settings, billing, usage. `twelve.manage.plugins.install('bills')`.
443
+ */
444
+ readonly manage: Manage;
445
+ constructor(options: TwelveAIOptions);
446
+ /**
447
+ * Low-level authenticated call to any engine endpoint. Returns
448
+ * `{ ok, status, ...payload }`; never throws on HTTP errors.
449
+ */
450
+ api(method: string, path: string, body?: Record<string, unknown>): Promise<ManageResult>;
451
+ /**
452
+ * Send one chat turn and return the completed result. Read hand-offs are
453
+ * auto-executed (see class docs); pass `autoExecute: false` to get the raw
454
+ * paused response instead, or `onHandoff` to execute them yourself.
455
+ */
456
+ chat(input: ChatInput, opts?: {
457
+ autoExecute?: boolean;
458
+ onHandoff?: HandoffExecutor;
459
+ }): Promise<ChatResponse>;
460
+ /** Resume a paused turn with tool results your system produced. */
461
+ resume(continuation: string, toolResults: ToolResult[], input?: Pick<ChatInput, 'customerId' | 'channel' | 'sandbox' | 'customerToken'>): Promise<ChatResponse>;
462
+ /**
463
+ * Approve a pending action (after your PIN/OTP step) - resends the turn with
464
+ * `confirmed: true` so the engine proceeds.
465
+ */
466
+ confirm(continuation: string, input?: Omit<ChatInput, 'continuation' | 'confirmed'>): Promise<ChatResponse>;
467
+ /**
468
+ * Level-0 integration: classify a message WITHOUT running the conversation.
469
+ * Returns the intent, a deterministic confidence score, and cheap extracted
470
+ * entities (amount / account number / phone) - you keep your existing flows
471
+ * and make the call yourself. Free: no tools run, nothing is stored.
472
+ */
473
+ classify(input: {
474
+ message: string;
475
+ reasoning?: 'off' | 'auto' | 'always';
476
+ }): Promise<ClassifyResponse>;
477
+ private chatBody;
478
+ private post;
479
+ /**
480
+ * Execute client-fetch hand-offs and resume until the turn completes. Only
481
+ * calls that carry a resolved `request` are auto-executed - a hand-off
482
+ * without one (e.g. a money move awaiting your PIN flow) stops the loop and
483
+ * is returned to you untouched.
484
+ */
485
+ private completeHandoffs;
486
+ /** Default hand-off executor: perform the request with your clientAuth headers. */
487
+ private performHandoff;
488
+ }
489
+
490
+ 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 ManifestResult as g, type ManifestTool as h, type PluginConcept as i, type PluginListItem as j, type PluginRelease as k, type PluginToolSpec as l, type PluginsResult as m, type ToolAuth as n, type ToolCall as o, type ToolListItem as p, type ToolResult as q, type ToolVariable as r, type ToolsResult as s, type TwelveAIOptions as t, buildManage as u };