@zihin/agent-client 0.4.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/LICENSE +21 -0
- package/README.md +92 -1
- package/dist/index.d.mts +153 -9
- package/dist/index.d.ts +153 -9
- package/dist/index.js +300 -21
- package/dist/index.mjs +299 -21
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @module errors
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
type ZihinErrorKind = 'config' | 'auth' | 'trial_expired' | 'no_subscription' | 'quota_exceeded' | 'not_found' | 'rate_limit' | 'timeout' | 'aborted' | 'server' | 'network' | 'protocol' | 'blocked' | 'unknown';
|
|
8
9
|
/** Contexto opcional anexado a um erro para correlação/depuração. */
|
|
9
10
|
interface ErrorMeta {
|
|
10
11
|
/** Ex.: "POST llm.zihin.ai/api/v2/agents/abc/stream". */
|
|
@@ -23,6 +24,14 @@ interface ZihinErrorOptions extends ErrorMeta {
|
|
|
23
24
|
* handoff) — é o handle que liga um erro daqui à execução no console/telemetria.
|
|
24
25
|
*/
|
|
25
26
|
executionId?: string;
|
|
27
|
+
/** Sessão do turno — para o chamador retomar/inspecionar a conversa depois de um erro. */
|
|
28
|
+
sessionId?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Só em `kind: 'timeout'` vindo do desfecho do turno (`done.timeout_clock`): qual relógio do BE
|
|
31
|
+
* encerrou o turno — `turn`, `first_signal`, `idle` ou `call`. Ausente num timeout de
|
|
32
|
+
* transporte/local, onde o turno pode nem ter terminado.
|
|
33
|
+
*/
|
|
34
|
+
timeoutClock?: TimeoutClock;
|
|
26
35
|
}
|
|
27
36
|
declare class ZihinAgentError extends Error {
|
|
28
37
|
readonly kind: ZihinErrorKind;
|
|
@@ -33,6 +42,8 @@ declare class ZihinAgentError extends Error {
|
|
|
33
42
|
readonly attempts?: number;
|
|
34
43
|
readonly endpoint?: string;
|
|
35
44
|
readonly executionId?: string;
|
|
45
|
+
readonly sessionId?: string;
|
|
46
|
+
readonly timeoutClock?: TimeoutClock;
|
|
36
47
|
constructor(kind: ZihinErrorKind, message: string, opts?: ZihinErrorOptions);
|
|
37
48
|
}
|
|
38
49
|
/**
|
|
@@ -109,7 +120,15 @@ interface Attachment {
|
|
|
109
120
|
interface InvokeOptions {
|
|
110
121
|
temperature?: number;
|
|
111
122
|
maxTokens?: number;
|
|
112
|
-
/**
|
|
123
|
+
/**
|
|
124
|
+
* Teto do TURNO desta chamada (ms); sobrepõe o do cliente. Vai ao BE como `options.timeout_ms`
|
|
125
|
+
* e o BE o honra (desde 30/09/2026, contrato de tempo §4), mas **só para encurtar**: o prazo
|
|
126
|
+
* efetivo é `min(prazo da plataforma, pedido)` — no `/stream` o canal chat dá 150s. Pedir mais
|
|
127
|
+
* não alonga. Um turno cortado por esse prazo sai `TIMEOUT` com `timeoutClock: 'turn'`.
|
|
128
|
+
*
|
|
129
|
+
* O relógio do turno no BE só começa DEPOIS da carga (config, tools, MCP frio). O deadline
|
|
130
|
+
* local soma `DEADLINE_GRACE_MS` a este valor para ainda receber o desfecho do servidor.
|
|
131
|
+
*/
|
|
113
132
|
timeoutMs?: number;
|
|
114
133
|
/** Just-in-time tool loading (Sprint 33). */
|
|
115
134
|
jitMode?: boolean;
|
|
@@ -121,8 +140,35 @@ interface InvokeAgentParams {
|
|
|
121
140
|
message?: string;
|
|
122
141
|
/** Anexos multimodais. `message` OU `attachments` é obrigatório. */
|
|
123
142
|
attachments?: Attachment[];
|
|
124
|
-
/** Continuidade de conversa (Supabase agent_sessions). */
|
|
143
|
+
/** Continuidade de conversa (Supabase agent_sessions). Não combina com `sessionFrom`. */
|
|
125
144
|
sessionId?: string;
|
|
145
|
+
/**
|
|
146
|
+
* Identidade da pessoa do outro lado (memória por pessoa, denylist, gate de engajamento). Só vale
|
|
147
|
+
* sob API key **admin/owner**. Para continuar conversas que um webhook já gravava, use o MESMO
|
|
148
|
+
* valor que o webhook usava. Enviado como `consumer_key`.
|
|
149
|
+
*/
|
|
150
|
+
consumerKey?: string;
|
|
151
|
+
/**
|
|
152
|
+
* Contexto estruturado que o **modelo lê** — bloco de plataforma junto da mensagem do usuário
|
|
153
|
+
* (não no system prompt). **Fica gravado** com a mensagem (`declared_context`) e se repete em
|
|
154
|
+
* todo turno; o BE redige segredos por nome de chave E por formato de valor (ex.: `sk-…`), o
|
|
155
|
+
* que pode alterar valores legítimos — ids que vão a tools ou ao `sessionFrom` ficam melhor em
|
|
156
|
+
* `bindings`. Plano, só escalares. Tools também o recebem. Só vale sob key admin/owner.
|
|
157
|
+
* ⚠️ Credencial não vai aqui nem em `bindings`: use um secret do tenant.
|
|
158
|
+
*/
|
|
159
|
+
context?: Record<string, ContextValue>;
|
|
160
|
+
/**
|
|
161
|
+
* Valores que **só as tools** recebem — nunca vão ao prompt (ex.: id interno de fornecedor).
|
|
162
|
+
* Plano, só escalares; **nunca gravado** nem redigido (vive só no contexto das tools durante o
|
|
163
|
+
* turno). Só vale sob key admin/owner.
|
|
164
|
+
*/
|
|
165
|
+
bindings?: Record<string, ContextValue>;
|
|
166
|
+
/**
|
|
167
|
+
* Deriva o `session_id` dos valores destes campos de `context ∪ bindings`, com a MESMA função
|
|
168
|
+
* do webhook (`derive: [campo]`) — o mesmo valor cai na mesma sessão pelos dois caminhos. Não
|
|
169
|
+
* combina com `sessionId`. O id derivado volta em `AgentResult.sessionId`.
|
|
170
|
+
*/
|
|
171
|
+
sessionFrom?: string[];
|
|
126
172
|
options?: InvokeOptions;
|
|
127
173
|
metadata?: {
|
|
128
174
|
traceId?: string;
|
|
@@ -137,6 +183,15 @@ interface InvokeAgentParams {
|
|
|
137
183
|
*/
|
|
138
184
|
includeRaw?: boolean;
|
|
139
185
|
}
|
|
186
|
+
/** Valor aceito em `context`/`bindings`: plano e escalar (regra 8 do contrato de entrada). */
|
|
187
|
+
type ContextValue = string | number | boolean | null;
|
|
188
|
+
/** Campo que o BE recebeu e NÃO aplicou (evento `metadata.ignored_fields`). */
|
|
189
|
+
interface IgnoredField {
|
|
190
|
+
/** Nome no fio (`context`, `bindings`, `session_from`, `consumer_key`, `options.temperature`…). */
|
|
191
|
+
field: string;
|
|
192
|
+
/** Motivo reportado pelo BE (ex.: papel da key insuficiente), quando houver. */
|
|
193
|
+
reason?: string;
|
|
194
|
+
}
|
|
140
195
|
interface Usage {
|
|
141
196
|
inputTokens?: number;
|
|
142
197
|
outputTokens?: number;
|
|
@@ -175,23 +230,71 @@ interface AgentResult {
|
|
|
175
230
|
}>;
|
|
176
231
|
iterations?: number;
|
|
177
232
|
executionTimeMs?: number;
|
|
233
|
+
/** `execution_id` do turno (evento `metrics`) — handle de correlação no console/telemetria. */
|
|
234
|
+
executionId?: string;
|
|
235
|
+
/** Campos do pedido que o BE aplicou (`metadata.accepted_fields`). Ausente = backend antigo. */
|
|
236
|
+
acceptedFields?: string[];
|
|
237
|
+
/** Campos do pedido que o BE recebeu e ignorou (`metadata.ignored_fields`). */
|
|
238
|
+
ignoredFields?: IgnoredField[];
|
|
239
|
+
/**
|
|
240
|
+
* `true` = o `content` é a resposta ENLATADA de um gate da plataforma (conversa em atendimento
|
|
241
|
+
* humano, consumidor bloqueado, sessão suspensa), não do agente: nenhum modelo rodou. Em canal
|
|
242
|
+
* conversacional ela pode ser entregue à pessoa; numa automação, trate como "não respondido".
|
|
243
|
+
*/
|
|
244
|
+
gated?: boolean;
|
|
245
|
+
/**
|
|
246
|
+
* Desfecho do turno, lido do `done` (`exitReason` do motor). `undefined` = backend antigo ou
|
|
247
|
+
* stream cortado antes do `done`. Só chegam aqui os desfechos cujo `content` é resposta
|
|
248
|
+
* (`COMPLETED`, `LENGTH`), o `PAUSED` (aprovação pendente ou agente pausado) e desfechos novos.
|
|
249
|
+
* `TIMEOUT`, `ERROR`, `CANCELLED`, `SUSPENDED` e os de bloqueio viram `ZihinAgentError` — o
|
|
250
|
+
* `content` desses turnos é a mensagem de falha/recusa do motor (`errorFromDoneChunk`).
|
|
251
|
+
*/
|
|
252
|
+
outcome?: AgentOutcome;
|
|
253
|
+
/** `true` quando a resposta foi cortada pelo teto de saída do modelo (`done.truncated`). */
|
|
254
|
+
truncated?: boolean;
|
|
255
|
+
/** Motivo do corte quando `truncated` (ex.: `length`). */
|
|
256
|
+
finishReason?: string;
|
|
178
257
|
/** Eventos SSE brutos coletados (para depuração / casos avançados). */
|
|
179
258
|
raw: AgentStreamChunk[];
|
|
180
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* Desfecho do turno (`done.outcome` = `resolveTurnOutcome` do motor). `COMPLETED` e `LENGTH`
|
|
262
|
+
* contam como sucesso no BE (`isSuccessfulOutcome`); os demais valores são repassados como vêm.
|
|
263
|
+
* Aberto (`string & {}`) porque o BE pode acrescentar desfechos (ex.: os de bloqueio).
|
|
264
|
+
*/
|
|
265
|
+
type AgentOutcome = 'COMPLETED' | 'LENGTH' | 'TIMEOUT' | 'ERROR' | 'CANCELLED' | 'PAUSED' | 'SUSPENDED' | 'BUDGET_EXCEEDED' | 'QUOTA_EXCEEDED' | 'SESSION_BUSY' | 'CONFLICT' | (string & {});
|
|
266
|
+
/**
|
|
267
|
+
* Qual relógio encerrou o turno (contrato de tempo §2): `turn` (prazo do turno, inclusive o
|
|
268
|
+
* `options.timeoutMs` pedido), `first_signal` (o provedor não começou a responder), `idle`
|
|
269
|
+
* (silêncio entre pedaços do stream do provedor) ou `call` (chamada ao modelo sem stream).
|
|
270
|
+
*/
|
|
271
|
+
type TimeoutClock = 'turn' | 'first_signal' | 'idle' | 'call' | (string & {});
|
|
181
272
|
/**
|
|
182
273
|
* Chunk normalizado emitido por `streamAgent`. Mapeia os tipos de evento SSE do BE:
|
|
183
274
|
* metadata, status, attachments, phase, thinking, tool, action_proposed, token,
|
|
184
275
|
* warning, response, metrics.
|
|
185
276
|
*/
|
|
186
|
-
type AgentStreamChunk =
|
|
277
|
+
type AgentStreamChunk =
|
|
278
|
+
/**
|
|
279
|
+
* Abertura do stream. `acceptedFields`/`ignoredFields` dizem o que o BE fez com cada campo do
|
|
280
|
+
* pedido (ausentes = backend anterior ao contrato de entrada). Se o chamador mandou
|
|
281
|
+
* `context`/`bindings`/`sessionFrom` e o BE não os aceitou, o `streamAgent` lança
|
|
282
|
+
* `ZihinAgentError('config')` ANTES de entregar este chunk — nunca segue em silêncio.
|
|
283
|
+
*/
|
|
284
|
+
{
|
|
187
285
|
type: 'metadata';
|
|
188
286
|
requestId?: string;
|
|
189
287
|
agentId?: string;
|
|
190
288
|
sessionId?: string;
|
|
289
|
+
acceptedFields?: string[];
|
|
290
|
+
ignoredFields?: IgnoredField[];
|
|
191
291
|
data: unknown;
|
|
192
|
-
}
|
|
292
|
+
}
|
|
293
|
+
/** `blocked` = motivo do bloqueio do turno (`agent_paused`, `budget_exceeded`…), quando houver. */
|
|
294
|
+
| {
|
|
193
295
|
type: 'status';
|
|
194
296
|
phase?: string;
|
|
297
|
+
blocked?: string;
|
|
195
298
|
data: unknown;
|
|
196
299
|
} | {
|
|
197
300
|
type: 'attachments';
|
|
@@ -250,9 +353,20 @@ type AgentStreamChunk = {
|
|
|
250
353
|
sessionId?: string;
|
|
251
354
|
data: unknown;
|
|
252
355
|
}
|
|
253
|
-
/**
|
|
356
|
+
/**
|
|
357
|
+
* Fim LIMPO do stream (`utils/sse.js`). Sem ele, o stream foi cortado no meio. Carrega o
|
|
358
|
+
* desfecho do turno: `{ outcome, timed_out?, timeout_clock?, truncated?, finish_reason? }`
|
|
359
|
+
* (aditivo — backend antigo manda `{}`). Um turno que o motor encerrou por tempo chega aqui
|
|
360
|
+
* com `outcome: 'TIMEOUT'` (idem ERROR e os bloqueios), DEPOIS de um `response` cujo `content`
|
|
361
|
+
* é a mensagem de falha — use `errorFromDoneChunk` para não publicá-lo como resposta.
|
|
362
|
+
*/
|
|
254
363
|
| {
|
|
255
364
|
type: 'done';
|
|
365
|
+
outcome?: AgentOutcome;
|
|
366
|
+
timedOut?: boolean;
|
|
367
|
+
timeoutClock?: TimeoutClock;
|
|
368
|
+
truncated?: boolean;
|
|
369
|
+
finishReason?: string;
|
|
256
370
|
data: unknown;
|
|
257
371
|
} | {
|
|
258
372
|
type: 'response';
|
|
@@ -263,6 +377,8 @@ type AgentStreamChunk = {
|
|
|
263
377
|
type: string;
|
|
264
378
|
[k: string]: unknown;
|
|
265
379
|
}>;
|
|
380
|
+
/** Resposta ENLATADA de um gate (handoff humano, denylist, sessão suspensa) — não do agente. */
|
|
381
|
+
gated?: boolean;
|
|
266
382
|
data: unknown;
|
|
267
383
|
} | {
|
|
268
384
|
type: 'metrics';
|
|
@@ -270,6 +386,7 @@ type AgentStreamChunk = {
|
|
|
270
386
|
model?: string;
|
|
271
387
|
iterations?: number;
|
|
272
388
|
executionTimeMs?: number;
|
|
389
|
+
executionId?: string;
|
|
273
390
|
data: unknown;
|
|
274
391
|
} | {
|
|
275
392
|
type: 'unknown';
|
|
@@ -589,8 +706,13 @@ type TimeoutOperation = keyof typeof OPERATION_TIMEOUT_MS;
|
|
|
589
706
|
* Folga somada ao `options.timeoutMs` do chamador para formar o deadline LOCAL. O mesmo número vai
|
|
590
707
|
* ao BE como `options.timeout_ms` (o teto que ele deve respeitar); sem folga, os dois relógios
|
|
591
708
|
* disparam juntos e o erro do servidor — que tem request_id — perde a corrida para o nosso abort.
|
|
709
|
+
*
|
|
710
|
+
* 30s, não 10s: o relógio do turno no BE só começa DEPOIS da carga (config, tools, gates — um MCP
|
|
711
|
+
* frio leva dezenas de segundos), então o tempo de parede visto daqui é `carga + prazo` (contrato
|
|
712
|
+
* de tempo §4). Com 10s, um `timeoutMs: 60000` num agente com MCP abortava aos 70s e trocava o
|
|
713
|
+
* `done { outcome: 'TIMEOUT' }` do servidor por um abort cego.
|
|
592
714
|
*/
|
|
593
|
-
declare const DEADLINE_GRACE_MS =
|
|
715
|
+
declare const DEADLINE_GRACE_MS = 30000;
|
|
594
716
|
|
|
595
717
|
/**
|
|
596
718
|
* Listagem de agentes do tenant (GET /api/v2/agents). Alimenta o dropdown do nó n8n (#17)
|
|
@@ -689,7 +811,7 @@ declare function createClient(config: ZihinClientConfig): ZihinAgentClient;
|
|
|
689
811
|
* O regex no nome só vale como FALLBACK para backends que ainda não emitem `timed_out`
|
|
690
812
|
* (self-hosted/antigos). Some numa major futura, depois do rename no BE.
|
|
691
813
|
*/
|
|
692
|
-
declare function classifyStreamErrorKind(code: string, timedOut?: boolean): 'timeout' | 'server';
|
|
814
|
+
declare function classifyStreamErrorKind(code: string, timedOut?: boolean): 'timeout' | 'server' | 'config';
|
|
693
815
|
/**
|
|
694
816
|
* Converte o chunk `type: 'error'` (evento terminal do BE) num `ZihinAgentError` — a MESMA regra
|
|
695
817
|
* que o `invokeAgent` aplica, exportada para quem consome `streamAgent` direto (o adapter do
|
|
@@ -698,6 +820,28 @@ declare function classifyStreamErrorKind(code: string, timedOut?: boolean): 'tim
|
|
|
698
820
|
declare function errorFromStreamChunk(chunk: Extract<AgentStreamChunk, {
|
|
699
821
|
type: 'error';
|
|
700
822
|
}>): ZihinAgentError;
|
|
823
|
+
/**
|
|
824
|
+
* Converte o `done` de um turno que NÃO produziu resposta num `ZihinAgentError`; devolve
|
|
825
|
+
* `undefined` quando o `content` é resposta. Mesma regra do `invokeAgent`, exportada para quem
|
|
826
|
+
* consome `streamAgent` direto (o Paperclip) não reimplementá-la.
|
|
827
|
+
*
|
|
828
|
+
* Por que erro e não um campo no resultado: nesses turnos o BE já emitiu um `response` com a
|
|
829
|
+
* mensagem de falha do motor em `content` (contrato de tempo §6). Como campo, cada shell teria
|
|
830
|
+
* de lembrar de checá-lo — e o que esquecesse publicaria a falha como resposta, que é o defeito
|
|
831
|
+
* que isto fecha (#81). Como erro, o caminho seguro é o default.
|
|
832
|
+
*
|
|
833
|
+
* TIMEOUT: `outcome: 'TIMEOUT'` é a fonte primária; `timed_out: true` sozinho também conta (o BE
|
|
834
|
+
* só o emite com TIMEOUT). Vira `kind: 'timeout'`, `code: 'TURN_TIMEOUT'`, com `timeoutClock`.
|
|
835
|
+
* Nenhum é retentável por default: o turno pode ter executado tools com efeito colateral
|
|
836
|
+
* (exceção: `SESSION_BUSY`, em que o turno nem começou).
|
|
837
|
+
*/
|
|
838
|
+
declare function errorFromDoneChunk(chunk: Extract<AgentStreamChunk, {
|
|
839
|
+
type: 'done';
|
|
840
|
+
}>, ctx?: {
|
|
841
|
+
executionId?: string;
|
|
842
|
+
sessionId?: string;
|
|
843
|
+
blocked?: string;
|
|
844
|
+
}): ZihinAgentError | undefined;
|
|
701
845
|
|
|
702
846
|
/**
|
|
703
847
|
* Security utilities — portado de n8n-nodes-zihin/src/utils/security.ts (zero-dep).
|
|
@@ -821,4 +965,4 @@ declare function signRequest(payload: string, secretKey: string, timestamp?: num
|
|
|
821
965
|
*/
|
|
822
966
|
declare const MAX_TASK_PAYLOAD_BYTES: number;
|
|
823
967
|
|
|
824
|
-
export { type AgentResult, type AgentStreamChunk, type AgentSummary, type Attachment, type AttachmentType, type CancelTaskParams, type CancelTaskResult, type CreateTriggerParams, DEADLINE_GRACE_MS, DEFAULT_LIMITS, type DelegateTaskParams, type DeleteTriggerParams, type DispatchAgentParams, type DispatchResult, type ExecutionStatus, type FindOrCreateResult, type GetExecutionParams, type GetTaskParams, type GetTriggerParams, type InvokeAgentParams, type InvokeOptions, type ListTasksParams, type ListTriggersParams, MAX_TASK_PAYLOAD_BYTES, OPERATION_TIMEOUT_MS, type QueryExtraction, type ResponseTransformMode, type RetryInfo, type SignedRequestHeaders, type Source, type TaskDossier, type TaskExecution, type TaskInfo, type TaskListPage, type TimeoutOperation, type TriggerInfo, type TriggerMode, type TriggerRef, type UpdateTriggerParams, type Usage, ZihinAgentClient, ZihinAgentError, type ZihinClientConfig, type ZihinErrorKind, classifyStreamErrorKind, createClient, errorFromStreamChunk, isCommercialBlock, sanitizeApiError, signRequest, validateApiKeyFormat, validateBaseUrl, validatePromptSize };
|
|
968
|
+
export { type AgentOutcome, type AgentResult, type AgentStreamChunk, type AgentSummary, type Attachment, type AttachmentType, type CancelTaskParams, type CancelTaskResult, type ContextValue, type CreateTriggerParams, DEADLINE_GRACE_MS, DEFAULT_LIMITS, type DelegateTaskParams, type DeleteTriggerParams, type DispatchAgentParams, type DispatchResult, type ExecutionStatus, type FindOrCreateResult, type GetExecutionParams, type GetTaskParams, type GetTriggerParams, type IgnoredField, type InvokeAgentParams, type InvokeOptions, type ListTasksParams, type ListTriggersParams, MAX_TASK_PAYLOAD_BYTES, OPERATION_TIMEOUT_MS, type QueryExtraction, type ResponseTransformMode, type RetryInfo, type SignedRequestHeaders, type Source, type TaskDossier, type TaskExecution, type TaskInfo, type TaskListPage, type TimeoutClock, type TimeoutOperation, type TriggerInfo, type TriggerMode, type TriggerRef, type UpdateTriggerParams, type Usage, ZihinAgentClient, ZihinAgentError, type ZihinClientConfig, type ZihinErrorKind, classifyStreamErrorKind, createClient, errorFromDoneChunk, errorFromStreamChunk, isCommercialBlock, sanitizeApiError, signRequest, validateApiKeyFormat, validateBaseUrl, validatePromptSize };
|