@zihin/agent-client 0.1.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/http.js ADDED
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ /**
3
+ * Transporte HTTP do núcleo: resolução/validação de base URL (SSRF), headers de auth,
4
+ * deadline via AbortController que cobre TODO o request (headers + corpo/stream),
5
+ * e retry com exponential backoff + jitter.
6
+ *
7
+ * Política de retry (evita duplicar efeito colateral):
8
+ * - 'idempotent' (GET): retenta em erro de rede, 429 e 5xx.
9
+ * - 'side-effecting' (POST: invoke/dispatch/create): retenta SÓ em 429/503 (servidor disse
10
+ * "tente depois", sem ter processado). NUNCA em erro de rede — o request pode ter sido
11
+ * recebido e processado mesmo com o socket caindo na volta.
12
+ *
13
+ * @module http
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.DEFAULT_MAX_TOTAL_BYTES = exports.DEFAULT_MAX_EVENT_BYTES = exports.DEFAULT_MAX_RETRIES = exports.DEFAULT_TIMEOUT_MS = exports.DEFAULT_BASE_URL = void 0;
17
+ exports.resolveConfig = resolveConfig;
18
+ exports.endpointLabel = endpointLabel;
19
+ exports.buildHeaders = buildHeaders;
20
+ exports.createDeadline = createDeadline;
21
+ exports.requestBuffered = requestBuffered;
22
+ exports.openStream = openStream;
23
+ exports.parseBody = parseBody;
24
+ const errors_1 = require("./errors");
25
+ const security_1 = require("./security");
26
+ exports.DEFAULT_BASE_URL = 'https://llm.zihin.ai';
27
+ exports.DEFAULT_TIMEOUT_MS = 120_000;
28
+ exports.DEFAULT_MAX_RETRIES = 2;
29
+ exports.DEFAULT_MAX_EVENT_BYTES = 1 * 1024 * 1024; // 1MB por evento/linha SSE
30
+ exports.DEFAULT_MAX_TOTAL_BYTES = 64 * 1024 * 1024; // 64MB por stream
31
+ /** Resolve o fetch no momento da chamada (honra injeção e mudanças de globalThis.fetch). */
32
+ function resolveFetch(injected) {
33
+ const f = injected ?? globalThis.fetch;
34
+ if (typeof f !== 'function') {
35
+ throw new errors_1.ZihinAgentError('config', 'Global fetch is unavailable in this runtime.');
36
+ }
37
+ return f;
38
+ }
39
+ /** Valida a config e devolve valores efetivos. Lança ZihinAgentError('config') se inválida. */
40
+ function resolveConfig(config) {
41
+ const keyCheck = (0, security_1.validateApiKeyFormat)(config.apiKey ?? '');
42
+ if (!keyCheck.valid) {
43
+ throw new errors_1.ZihinAgentError('config', keyCheck.error || 'Invalid API key.');
44
+ }
45
+ const urlCheck = (0, security_1.validateBaseUrl)(config.baseUrl ?? '', {
46
+ allowCustomDomains: config.allowCustomBaseUrl,
47
+ allowHttp: config.allowHttp,
48
+ allowLocalhost: config.allowHttp,
49
+ });
50
+ if (!urlCheck.valid) {
51
+ throw new errors_1.ZihinAgentError('config', urlCheck.error || 'Invalid base URL.');
52
+ }
53
+ // Preflight de runtime: sem fetch, dá um erro claro em vez de um TypeError cru rotulado de "network".
54
+ if (typeof (config.fetch ?? globalThis.fetch) !== 'function') {
55
+ throw new errors_1.ZihinAgentError('config', 'Global fetch is unavailable in this runtime. Use Node >=18 or pass a `fetch` implementation in the client config.');
56
+ }
57
+ return {
58
+ apiKey: config.apiKey.trim(),
59
+ baseUrl: urlCheck.sanitizedUrl || exports.DEFAULT_BASE_URL,
60
+ timeoutMs: config.timeoutMs ?? exports.DEFAULT_TIMEOUT_MS,
61
+ maxRetries: config.maxRetries ?? exports.DEFAULT_MAX_RETRIES,
62
+ maxStreamEventBytes: config.maxStreamEventBytes ?? exports.DEFAULT_MAX_EVENT_BYTES,
63
+ maxStreamTotalBytes: config.maxStreamTotalBytes ?? exports.DEFAULT_MAX_TOTAL_BYTES,
64
+ fetchImpl: config.fetch,
65
+ onRetry: config.onRetry,
66
+ };
67
+ }
68
+ /** Rótulo de endpoint para mensagens de erro/observabilidade: "POST host/path". */
69
+ function endpointLabel(method, url) {
70
+ try {
71
+ const u = new URL(url);
72
+ return `${method} ${u.host}${u.pathname}`;
73
+ }
74
+ catch {
75
+ return method;
76
+ }
77
+ }
78
+ /** Lê o header Retry-After (segundos ou data HTTP) em ms, com teto. */
79
+ function retryAfterMs(headers, capMs = 30_000) {
80
+ const raw = headers.get('retry-after');
81
+ if (!raw)
82
+ return undefined;
83
+ const secs = Number(raw);
84
+ if (Number.isFinite(secs))
85
+ return Math.min(Math.max(0, secs * 1000), capMs);
86
+ const when = Date.parse(raw);
87
+ if (Number.isFinite(when))
88
+ return Math.min(Math.max(0, when - Date.now()), capMs);
89
+ return undefined;
90
+ }
91
+ function buildHeaders(apiKey, extra = {}) {
92
+ return {
93
+ 'Content-Type': 'application/json',
94
+ Accept: 'application/json',
95
+ 'X-Api-Key': apiKey,
96
+ ...extra,
97
+ };
98
+ }
99
+ /** Espera `ms`, mas rejeita com 'aborted' imediatamente se o signal do chamador disparar. */
100
+ function delay(ms, signal) {
101
+ return new Promise((resolve, reject) => {
102
+ if (signal?.aborted) {
103
+ reject(new errors_1.ZihinAgentError('aborted', 'Request was aborted by the caller.'));
104
+ return;
105
+ }
106
+ const onAbort = () => {
107
+ clearTimeout(timer);
108
+ reject(new errors_1.ZihinAgentError('aborted', 'Request was aborted by the caller.'));
109
+ };
110
+ const timer = setTimeout(() => {
111
+ if (signal)
112
+ signal.removeEventListener('abort', onAbort);
113
+ resolve();
114
+ }, ms);
115
+ if (signal)
116
+ signal.addEventListener('abort', onAbort, { once: true });
117
+ });
118
+ }
119
+ /** Backoff exponencial 1s→10s com jitter (metade fixa + metade aleatória), evita thundering herd. */
120
+ function backoffMs(attempt) {
121
+ const base = Math.min(1000 * 2 ** attempt, 10_000);
122
+ return base / 2 + Math.random() * (base / 2);
123
+ }
124
+ /**
125
+ * Cria um deadline que aborta o request após `timeoutMs` (cobre headers E corpo/stream) e
126
+ * propaga o abort do chamador. Mantenha vivo até o corpo/stream terminar; chame dispose() ao fim.
127
+ */
128
+ function createDeadline(timeoutMs, callerSignal) {
129
+ const controller = new AbortController();
130
+ let timedOut = false;
131
+ let abortedByCaller = false;
132
+ const timer = setTimeout(() => {
133
+ timedOut = true;
134
+ controller.abort();
135
+ }, timeoutMs);
136
+ const onAbort = () => {
137
+ abortedByCaller = true;
138
+ controller.abort();
139
+ };
140
+ if (callerSignal) {
141
+ if (callerSignal.aborted)
142
+ onAbort();
143
+ else
144
+ callerSignal.addEventListener('abort', onAbort, { once: true });
145
+ }
146
+ return {
147
+ signal: controller.signal,
148
+ dispose: () => {
149
+ clearTimeout(timer);
150
+ if (callerSignal)
151
+ callerSignal.removeEventListener('abort', onAbort);
152
+ },
153
+ timedOut: () => timedOut,
154
+ abortedByCaller: () => abortedByCaller,
155
+ };
156
+ }
157
+ function shouldRetryStatus(status, policy) {
158
+ if (policy === 'idempotent')
159
+ return status >= 500 || status === 429;
160
+ return status === 429 || status === 503; // side-effecting: só "tente depois"
161
+ }
162
+ /**
163
+ * Executa um request lendo o corpo inteiro dentro do deadline (P1: timeout cobre o download).
164
+ * Retorna mesmo em não-2xx (o chamador converte via errorFromResponse).
165
+ */
166
+ async function requestBuffered(args) {
167
+ const endpoint = endpointLabel(args.method, args.url);
168
+ const doFetch = resolveFetch(args.fetchImpl);
169
+ let lastError = null;
170
+ for (let attempt = 0; attempt <= args.maxRetries; attempt++) {
171
+ const d = createDeadline(args.timeoutMs, args.callerSignal);
172
+ try {
173
+ const res = await doFetch(args.url, {
174
+ method: args.method,
175
+ headers: args.headers,
176
+ body: args.body,
177
+ signal: d.signal,
178
+ redirect: 'error', // 3xx para outro host vazaria a X-Api-Key
179
+ cache: 'no-store', // evita cache stale (ex.: polling em Next.js/edge)
180
+ });
181
+ if (shouldRetryStatus(res.status, args.policy) && attempt < args.maxRetries) {
182
+ const wait = retryAfterMs(res.headers) ?? backoffMs(attempt);
183
+ try {
184
+ await res.body?.cancel();
185
+ }
186
+ catch {
187
+ /* ignore */
188
+ }
189
+ d.dispose();
190
+ args.onRetry?.({ endpoint, attempt: attempt + 1, delayMs: wait, reason: 'status', status: res.status });
191
+ await delay(wait, args.callerSignal);
192
+ continue;
193
+ }
194
+ const text = await res.text(); // dentro do deadline
195
+ d.dispose();
196
+ return { status: res.status, ok: res.ok, text, endpoint, attempts: attempt + 1 };
197
+ }
198
+ catch (err) {
199
+ d.dispose();
200
+ const meta = { endpoint, attempts: attempt + 1 };
201
+ if (d.timedOut())
202
+ throw new errors_1.ZihinAgentError('timeout', `Request timed out after ${args.timeoutMs}ms.`, meta);
203
+ if (d.abortedByCaller())
204
+ throw new errors_1.ZihinAgentError('aborted', 'Request was aborted by the caller.', meta);
205
+ lastError = (0, errors_1.errorFromThrow)(err, args.timeoutMs, meta);
206
+ // S1: erro de rede só é retentável em método idempotente.
207
+ const canRetry = args.policy === 'idempotent' && lastError.retryable && attempt < args.maxRetries;
208
+ if (!canRetry)
209
+ throw lastError;
210
+ const wait = backoffMs(attempt);
211
+ args.onRetry?.({ endpoint, attempt: attempt + 1, delayMs: wait, reason: 'network' });
212
+ await delay(wait, args.callerSignal);
213
+ }
214
+ }
215
+ throw lastError ?? new errors_1.ZihinAgentError('unknown', 'Max retries exceeded.', { endpoint });
216
+ }
217
+ /**
218
+ * Abre um POST SSE. Retenta só pré-stream em 429/503 (POST side-effecting). Em sucesso/4xx
219
+ * devolve a Response COM o deadline ainda ativo — o consumidor do stream chama deadline.dispose()
220
+ * ao finalizar (P1: o timeout cobre toda a duração do stream, e o abort do chamador continua ligado).
221
+ */
222
+ async function openStream(args) {
223
+ const endpoint = endpointLabel('POST', args.url);
224
+ const doFetch = resolveFetch(args.fetchImpl);
225
+ for (let attempt = 0; attempt <= args.maxRetries; attempt++) {
226
+ const d = createDeadline(args.timeoutMs, args.callerSignal);
227
+ try {
228
+ const response = await doFetch(args.url, {
229
+ method: 'POST',
230
+ headers: { ...args.headers, Accept: 'text/event-stream' },
231
+ body: args.body,
232
+ signal: d.signal,
233
+ redirect: 'error',
234
+ cache: 'no-store',
235
+ });
236
+ if (shouldRetryStatus(response.status, 'side-effecting') && attempt < args.maxRetries) {
237
+ const wait = retryAfterMs(response.headers) ?? backoffMs(attempt);
238
+ try {
239
+ await response.body?.cancel();
240
+ }
241
+ catch {
242
+ /* ignore */
243
+ }
244
+ d.dispose();
245
+ args.onRetry?.({
246
+ endpoint,
247
+ attempt: attempt + 1,
248
+ delayMs: wait,
249
+ reason: 'status',
250
+ status: response.status,
251
+ });
252
+ await delay(wait, args.callerSignal);
253
+ continue;
254
+ }
255
+ return { response, deadline: d, endpoint }; // NÃO dá dispose: o stream ainda vai ser lido
256
+ }
257
+ catch (err) {
258
+ d.dispose();
259
+ const meta = { endpoint, attempts: attempt + 1 };
260
+ if (d.timedOut())
261
+ throw new errors_1.ZihinAgentError('timeout', `Request timed out after ${args.timeoutMs}ms.`, meta);
262
+ if (d.abortedByCaller())
263
+ throw new errors_1.ZihinAgentError('aborted', 'Request was aborted by the caller.', meta);
264
+ // S1: POST não retenta em erro de rede.
265
+ throw (0, errors_1.errorFromThrow)(err, args.timeoutMs, meta);
266
+ }
267
+ }
268
+ throw new errors_1.ZihinAgentError('unknown', 'Max retries exceeded.', { endpoint });
269
+ }
270
+ /** Faz parse seguro de um corpo (JSON quando possível, senão {message}). */
271
+ function parseBody(text) {
272
+ if (!text)
273
+ return {};
274
+ try {
275
+ return JSON.parse(text);
276
+ }
277
+ catch {
278
+ return { message: text };
279
+ }
280
+ }
281
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @zihin/agent-client — núcleo de invocação de agente Zihin.ai.
3
+ *
4
+ * Padrão híbrido (verificado contra o BE em 2026-06-28):
5
+ * • Direto: client.invokeAgent / client.streamAgent → POST /api/v2/agents/:id/stream
6
+ * • Triggers: client.createTrigger / dispatchAgent / getExecution → async + callback
7
+ * • Auxiliar: client.listAgents → GET /api/v2/agents (dropdown)
8
+ *
9
+ * Zero dependência de plataforma (n8n / Paperclip). Segurança reusada de `security.ts`.
10
+ *
11
+ * @example
12
+ * import { createClient } from '@zihin/agent-client';
13
+ * const zihin = createClient({ apiKey: process.env.ZIHIN_API_KEY! });
14
+ * const res = await zihin.invokeAgent({ agentId, message: 'Olá' });
15
+ * console.log(res.content, res.usage, res.sessionId);
16
+ */
17
+ export { ZihinAgentClient, createClient } from './client';
18
+ export { ZihinAgentError, type ZihinErrorKind } from './errors';
19
+ export type { AgentSummary } from './agents';
20
+ export type { AgentResult, AgentStreamChunk, Attachment, AttachmentType, CreateTriggerParams, DeleteTriggerParams, DispatchAgentParams, DispatchResult, ExecutionStatus, FindOrCreateResult, GetExecutionParams, GetTriggerParams, InvokeAgentParams, InvokeOptions, ListTriggersParams, RetryInfo, Source, TriggerInfo, TriggerMode, TriggerRef, Usage, ZihinClientConfig, } from './types';
21
+ export { validateApiKeyFormat, validateBaseUrl, validatePromptSize, sanitizeApiError, signRequest, DEFAULT_LIMITS, } from './security';
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ /**
3
+ * @zihin/agent-client — núcleo de invocação de agente Zihin.ai.
4
+ *
5
+ * Padrão híbrido (verificado contra o BE em 2026-06-28):
6
+ * • Direto: client.invokeAgent / client.streamAgent → POST /api/v2/agents/:id/stream
7
+ * • Triggers: client.createTrigger / dispatchAgent / getExecution → async + callback
8
+ * • Auxiliar: client.listAgents → GET /api/v2/agents (dropdown)
9
+ *
10
+ * Zero dependência de plataforma (n8n / Paperclip). Segurança reusada de `security.ts`.
11
+ *
12
+ * @example
13
+ * import { createClient } from '@zihin/agent-client';
14
+ * const zihin = createClient({ apiKey: process.env.ZIHIN_API_KEY! });
15
+ * const res = await zihin.invokeAgent({ agentId, message: 'Olá' });
16
+ * console.log(res.content, res.usage, res.sessionId);
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.DEFAULT_LIMITS = exports.signRequest = exports.sanitizeApiError = exports.validatePromptSize = exports.validateBaseUrl = exports.validateApiKeyFormat = exports.ZihinAgentError = exports.createClient = exports.ZihinAgentClient = void 0;
20
+ var client_1 = require("./client");
21
+ Object.defineProperty(exports, "ZihinAgentClient", { enumerable: true, get: function () { return client_1.ZihinAgentClient; } });
22
+ Object.defineProperty(exports, "createClient", { enumerable: true, get: function () { return client_1.createClient; } });
23
+ var errors_1 = require("./errors");
24
+ Object.defineProperty(exports, "ZihinAgentError", { enumerable: true, get: function () { return errors_1.ZihinAgentError; } });
25
+ // Primitivas de segurança reutilizáveis pelos shells.
26
+ var security_1 = require("./security");
27
+ Object.defineProperty(exports, "validateApiKeyFormat", { enumerable: true, get: function () { return security_1.validateApiKeyFormat; } });
28
+ Object.defineProperty(exports, "validateBaseUrl", { enumerable: true, get: function () { return security_1.validateBaseUrl; } });
29
+ Object.defineProperty(exports, "validatePromptSize", { enumerable: true, get: function () { return security_1.validatePromptSize; } });
30
+ Object.defineProperty(exports, "sanitizeApiError", { enumerable: true, get: function () { return security_1.sanitizeApiError; } });
31
+ Object.defineProperty(exports, "signRequest", { enumerable: true, get: function () { return security_1.signRequest; } });
32
+ Object.defineProperty(exports, "DEFAULT_LIMITS", { enumerable: true, get: function () { return security_1.DEFAULT_LIMITS; } });
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAEH,mCAA0D;AAAjD,0GAAA,gBAAgB,OAAA;AAAE,sGAAA,YAAY,OAAA;AACvC,mCAAgE;AAAvD,yGAAA,eAAe,OAAA;AA2BxB,sDAAsD;AACtD,uCAOoB;AANnB,gHAAA,oBAAoB,OAAA;AACpB,2GAAA,eAAe,OAAA;AACf,8GAAA,kBAAkB,OAAA;AAClB,4GAAA,gBAAgB,OAAA;AAChB,uGAAA,WAAW,OAAA;AACX,0GAAA,cAAc,OAAA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Helpers internos compartilhados (parsing defensivo de respostas do BE).
3
+ * Centralizados aqui para não divergir entre invoke/triggers/agents.
4
+ *
5
+ * @module internal
6
+ */
7
+ import type { Usage } from './types';
8
+ /** Tamanho em bytes UTF-8 de uma string, portável (sem depender de Node Buffer). */
9
+ export declare function utf8Len(s: string): number;
10
+ export declare function rec(x: unknown): Record<string, unknown>;
11
+ export declare function str(x: unknown): string | undefined;
12
+ export declare function num(x: unknown): number | undefined;
13
+ export declare function parseUsage(usageRaw: unknown): Usage | undefined;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /**
3
+ * Helpers internos compartilhados (parsing defensivo de respostas do BE).
4
+ * Centralizados aqui para não divergir entre invoke/triggers/agents.
5
+ *
6
+ * @module internal
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.utf8Len = utf8Len;
10
+ exports.rec = rec;
11
+ exports.str = str;
12
+ exports.num = num;
13
+ exports.parseUsage = parseUsage;
14
+ // TextEncoder existe em Node, edge e browser (ao contrário de Buffer, que é só Node).
15
+ const _utf8 = new TextEncoder();
16
+ /** Tamanho em bytes UTF-8 de uma string, portável (sem depender de Node Buffer). */
17
+ function utf8Len(s) {
18
+ return _utf8.encode(s).length;
19
+ }
20
+ function rec(x) {
21
+ return x && typeof x === 'object' ? x : {};
22
+ }
23
+ function str(x) {
24
+ return typeof x === 'string' ? x : undefined;
25
+ }
26
+ function num(x) {
27
+ return typeof x === 'number' ? x : undefined;
28
+ }
29
+ function parseUsage(usageRaw) {
30
+ const u = rec(usageRaw);
31
+ if (Object.keys(u).length === 0)
32
+ return undefined;
33
+ return {
34
+ inputTokens: num(u.input_tokens) ?? num(u.prompt_tokens),
35
+ outputTokens: num(u.output_tokens) ?? num(u.completion_tokens),
36
+ totalTokens: num(u.total_tokens),
37
+ costUsd: num(u.cost_usd),
38
+ };
39
+ }
40
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAQH,0BAEC;AAED,kBAEC;AAED,kBAEC;AAED,kBAEC;AAED,gCASC;AA7BD,sFAAsF;AACtF,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;AAEhC,oFAAoF;AACpF,SAAgB,OAAO,CAAC,CAAS;IAChC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC/B,CAAC;AAED,SAAgB,GAAG,CAAC,CAAU;IAC7B,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAA6B,CAAC,CAAC,CAAC,EAAE,CAAC;AACzE,CAAC;AAED,SAAgB,GAAG,CAAC,CAAU;IAC7B,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC;AAED,SAAgB,GAAG,CAAC,CAAU;IAC7B,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC;AAED,SAAgB,UAAU,CAAC,QAAiB;IAC3C,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAClD,OAAO;QACN,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC;QACxD,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAC9D,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC;QAChC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;KACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Caminho A — invocação direta de agente (POST /api/v2/agents/:id/stream).
3
+ * `streamAgent` emite deltas ao vivo; `invokeAgent` buffeia o stream e consolida
4
+ * o evento `response` (content/sources/session_id/blocks) com o `metrics` (usage/model).
5
+ *
6
+ * @module invoke
7
+ */
8
+ import { type ResolvedConfig } from './http';
9
+ import type { AgentResult, AgentStreamChunk, InvokeAgentParams } from './types';
10
+ /**
11
+ * Emite chunks normalizados do agente ao vivo. Para quem quer streaming (UI, logs).
12
+ * O deadline (timeout + abort do chamador) cobre toda a duração do stream e é liberado no fim.
13
+ */
14
+ export declare function streamAgent(cfg: ResolvedConfig, params: InvokeAgentParams): AsyncGenerator<AgentStreamChunk>;
15
+ /**
16
+ * Invoca o agente e retorna o resultado final consolidado. Buffeia o SSE até `response`+`metrics`.
17
+ */
18
+ export declare function invokeAgent(cfg: ResolvedConfig, params: InvokeAgentParams): Promise<AgentResult>;