@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/README.md +156 -0
- package/dist/agents.d.ts +21 -0
- package/dist/agents.js +52 -0
- package/dist/agents.js.map +1 -0
- package/dist/client.d.ts +43 -0
- package/dist/client.js +75 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +35 -0
- package/dist/errors.js +89 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.d.ts +98 -0
- package/dist/http.js +281 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +13 -0
- package/dist/internal.js +40 -0
- package/dist/internal.js.map +1 -0
- package/dist/invoke.d.ts +18 -0
- package/dist/invoke.js +233 -0
- package/dist/invoke.js.map +1 -0
- package/dist/security.d.ts +82 -0
- package/dist/security.js +251 -0
- package/dist/security.js.map +1 -0
- package/dist/sse.d.ts +27 -0
- package/dist/sse.js +138 -0
- package/dist/sse.js.map +1 -0
- package/dist/triggers.d.ts +43 -0
- package/dist/triggers.js +241 -0
- package/dist/triggers.js.map +1 -0
- package/dist/types.d.ts +268 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# @zihin/agent-client
|
|
2
|
+
|
|
3
|
+
Núcleo de **invocação de agente** Zihin.ai — o padrão único que n8n, Paperclip e integrações
|
|
4
|
+
futuras usam para acionar agentes hospedados na Zihin. Zero dependência de plataforma.
|
|
5
|
+
|
|
6
|
+
> Contexto e decisões: `docs/issues/PLANO-padrao-agent-client.md` (issue #16). Contrato verificado
|
|
7
|
+
> contra o BE (`zihin-agent-builder/server-llm`) em 2026-06-28.
|
|
8
|
+
|
|
9
|
+
## A ideia
|
|
10
|
+
|
|
11
|
+
Toda entrada externa na Zihin atravessa um **agente** (RBAC, quota, HITL, auditoria, memória) — não
|
|
12
|
+
a call crua de LLM. Este pacote esconde os detalhes de transporte (SSE, triggers) atrás de uma API
|
|
13
|
+
simples, e oferece **dois estilos** de invocação:
|
|
14
|
+
|
|
15
|
+
| Estilo | Método | Quando usar |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| **Direto / imediato** | `invokeAgent` / `streamAgent` | espera a resposta (n8n, request/resposta). Zero setup. |
|
|
18
|
+
| **Assíncrono / desacoplado** | `createTrigger` + `dispatchAgent` (+ `getExecution`) | dispara e recebe via callback (serverless, execução longa). |
|
|
19
|
+
|
|
20
|
+
## Instalação
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @zihin/agent-client
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Requer Node >= 18 (usa `fetch`/`ReadableStream` globais).
|
|
27
|
+
|
|
28
|
+
## Uso — caminho direto
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { createClient } from '@zihin/agent-client';
|
|
32
|
+
|
|
33
|
+
const zihin = createClient({ apiKey: process.env.ZIHIN_API_KEY! }); // zhn_live_*
|
|
34
|
+
|
|
35
|
+
// Imediato — buffeia o SSE e consolida response + metrics
|
|
36
|
+
const res = await zihin.invokeAgent({
|
|
37
|
+
agentId: 'uuid-do-agente',
|
|
38
|
+
message: 'Qual a previsão de vendas?',
|
|
39
|
+
sessionId: previousSessionId, // opcional, continua a conversa
|
|
40
|
+
});
|
|
41
|
+
console.log(res.content); // texto final
|
|
42
|
+
console.log(res.usage); // { inputTokens, outputTokens, totalTokens, costUsd }
|
|
43
|
+
console.log(res.sessionId); // guarde para a próxima mensagem
|
|
44
|
+
console.log(res.model); // modelo efetivo
|
|
45
|
+
|
|
46
|
+
// Ao vivo — deltas conforme o agente pensa/usa tools/responde
|
|
47
|
+
for await (const chunk of zihin.streamAgent({ agentId, message: 'Olá' })) {
|
|
48
|
+
if (chunk.type === 'token') process.stdout.write(chunk.content);
|
|
49
|
+
if (chunk.type === 'tool') console.log('tool:', chunk.tool);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Uso — caminho assíncrono (triggers)
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// 1x: provisiona (ou reaproveita) um webhook ligado ao agente.
|
|
57
|
+
// PREFIRA findOrCreateTrigger — o BE não tem unicidade de nome, então createTrigger
|
|
58
|
+
// repetido cria duplicatas. findOrCreate reusa por (agente + nome).
|
|
59
|
+
const { triggerId, webhookUrl, created } = await zihin.findOrCreateTrigger({
|
|
60
|
+
agentId,
|
|
61
|
+
name: 'Integração X',
|
|
62
|
+
mode: 'async',
|
|
63
|
+
callbackUrl: 'https://minha-plataforma.com/webhook/zihin',
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// N vezes: dispara (responde 202 na hora; resultado chega no callback)
|
|
67
|
+
const { accepted, executionId } = await zihin.dispatchAgent({
|
|
68
|
+
triggerId,
|
|
69
|
+
payload: { message: 'Processa este pedido' },
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// opcional: polling do resultado em vez de callback
|
|
73
|
+
const exec = await zihin.getExecution({ triggerId, executionId });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
> O modo `sync` do trigger (`mode: 'sync'`) responde 200 + JSON na hora (`dispatchResult.agentResponse`).
|
|
77
|
+
|
|
78
|
+
### Ciclo de vida do trigger
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
await zihin.listTriggers({ agentId }); // lista (filtros: agentId/triggerType/enabledOnly)
|
|
82
|
+
await zihin.getTrigger({ triggerId }); // detalhe (inclui webhookUrl)
|
|
83
|
+
await zihin.deleteTrigger({ triggerId }); // remove (requer key admin/owner; editor → 403)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Dropdown de agentes
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const agents = await zihin.listAgents(); // GET /api/v2/agents
|
|
90
|
+
// [{ id, name, commercialName, status, toolsCount, ... }]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Permissões da API key
|
|
94
|
+
|
|
95
|
+
- `invokeAgent` / `streamAgent` — qualquer role.
|
|
96
|
+
- `createTrigger` / `getExecution` — exigem key **admin** ou **editor** (default é admin). Keys
|
|
97
|
+
`member` recebem `ZihinAgentError` com `kind: 'auth'`.
|
|
98
|
+
|
|
99
|
+
## Erros
|
|
100
|
+
|
|
101
|
+
Todos os erros são `ZihinAgentError` com `kind` (`config | auth | not_found | rate_limit | timeout |
|
|
102
|
+
aborted | server | network | protocol | unknown`), `status`, `code`, `retryable` e — para depurar em
|
|
103
|
+
produção externa — `endpoint` (`"POST host/path"`), `attempts` e **`requestId`** (handle do BE para o
|
|
104
|
+
suporte correlacionar). Erros de rede carregam a causa-raiz (`ECONNREFUSED`/`ENOTFOUND`/TLS…) na
|
|
105
|
+
mensagem. As mensagens redigem **só segredos** (key/Bearer/stack) — `request_id`/`trace_id` são
|
|
106
|
+
preservados. Cancele com `AbortSignal` via `params.signal`.
|
|
107
|
+
|
|
108
|
+
## Robustez (timeout / retry / limites)
|
|
109
|
+
|
|
110
|
+
- **Timeout cobre tudo** — headers e o corpo/stream inteiro. `timeoutMs` (default 120s, igual ao cap
|
|
111
|
+
do BE) é o tempo máximo total da chamada; `AbortSignal` do chamador funciona durante todo o stream.
|
|
112
|
+
- **Retry sem duplicar efeito** — GET (idempotente) retenta em rede/429/5xx; POST com efeito
|
|
113
|
+
(`invokeAgent`/`dispatchAgent`/`createTrigger`) retenta **só em 429/503** e **nunca em erro de
|
|
114
|
+
rede** (o request pode ter sido processado). Backoff exponencial 1s→10s com jitter.
|
|
115
|
+
- **Anti-DoS de memória** — limites de stream `maxStreamEventBytes` (1MB) e `maxStreamTotalBytes`
|
|
116
|
+
(64MB); estourar aborta com `protocol`. Configuráveis no `createClient`.
|
|
117
|
+
- **`includeRaw`** — por padrão `invokeAgent` não retém os eventos brutos (`raw: []`) para economizar
|
|
118
|
+
memória; passe `includeRaw: true` para recebê-los. `streamAgent` sempre entrega os chunks ao vivo.
|
|
119
|
+
- **Segurança de transporte** — `redirect: 'error'` (um 3xx para outro host vazaria a key) e
|
|
120
|
+
`cache: 'no-store'` (evita polling stale em Next.js/edge) em toda requisição. `Retry-After` do
|
|
121
|
+
servidor é respeitado em 429/503.
|
|
122
|
+
|
|
123
|
+
### Observabilidade e portabilidade
|
|
124
|
+
|
|
125
|
+
- **Hooks** (opt-in, sem `console`): `onRetry(info)` (a cada retentativa, com `endpoint`/`attempt`/
|
|
126
|
+
`delayMs`/`reason`/`status`) e `onError(err)`.
|
|
127
|
+
- **`fetch` injetável** — `fetch?` na config; por padrão usa `globalThis.fetch` (Node ≥18). Um
|
|
128
|
+
preflight dá erro `config` claro se não houver fetch.
|
|
129
|
+
- **Portável** — sem `Buffer`; `node:crypto` só é carregado se você usar `signRequest`. Roda em Node;
|
|
130
|
+
para edge/serverless, injete `fetch` se necessário.
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const zihin = createClient({
|
|
134
|
+
apiKey,
|
|
135
|
+
timeoutMs: 60_000,
|
|
136
|
+
maxRetries: 2,
|
|
137
|
+
maxStreamEventBytes: 2 * 1024 * 1024,
|
|
138
|
+
onRetry: (info) => myLogger.warn('zihin retry', info),
|
|
139
|
+
// fetch: customFetch, // ambientes sem fetch global
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
> SSRF: a validação de base/callback URL é por nome de host. Com `allowCustomBaseUrl: true` um host
|
|
144
|
+
> que resolva para IP privado (DNS rebinding) passa — mantenha o whitelist em ambiente sensível.
|
|
145
|
+
|
|
146
|
+
## Segurança
|
|
147
|
+
|
|
148
|
+
Reusa as primitivas de `security.ts`: validação SSRF da base URL (whitelist Zihin por padrão; libere
|
|
149
|
+
com `allowCustomBaseUrl`), limites de payload, sanitização de erro, validação de formato de key e HMAC
|
|
150
|
+
opcional.
|
|
151
|
+
|
|
152
|
+
## Dev
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npm run build && npm test # smoke test offline (mocka fetch), sem rede
|
|
156
|
+
```
|
package/dist/agents.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Listagem de agentes do tenant (GET /api/v2/agents). Alimenta o dropdown do nó n8n (#17)
|
|
3
|
+
* e o select de `agentId` no Paperclip (#20). Aceita key `zhn_live_*` (agents:read em todos os roles).
|
|
4
|
+
*
|
|
5
|
+
* @module agents
|
|
6
|
+
*/
|
|
7
|
+
import { type ResolvedConfig } from './http';
|
|
8
|
+
export interface AgentSummary {
|
|
9
|
+
id: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
commercialName?: string;
|
|
12
|
+
bio?: string;
|
|
13
|
+
type?: string;
|
|
14
|
+
status?: string;
|
|
15
|
+
tags?: string[];
|
|
16
|
+
toolsCount?: number;
|
|
17
|
+
}
|
|
18
|
+
/** Lista os agentes acessíveis pelo tenant da key. */
|
|
19
|
+
export declare function listAgents(cfg: ResolvedConfig, opts?: {
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}): Promise<AgentSummary[]>;
|
package/dist/agents.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Listagem de agentes do tenant (GET /api/v2/agents). Alimenta o dropdown do nó n8n (#17)
|
|
4
|
+
* e o select de `agentId` no Paperclip (#20). Aceita key `zhn_live_*` (agents:read em todos os roles).
|
|
5
|
+
*
|
|
6
|
+
* @module agents
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.listAgents = listAgents;
|
|
10
|
+
const errors_1 = require("./errors");
|
|
11
|
+
const http_1 = require("./http");
|
|
12
|
+
const internal_1 = require("./internal");
|
|
13
|
+
/** Lista os agentes acessíveis pelo tenant da key. */
|
|
14
|
+
async function listAgents(cfg, opts = {}) {
|
|
15
|
+
const res = await (0, http_1.requestBuffered)({
|
|
16
|
+
method: 'GET',
|
|
17
|
+
url: `${cfg.baseUrl}/api/v2/agents`,
|
|
18
|
+
headers: (0, http_1.buildHeaders)(cfg.apiKey),
|
|
19
|
+
timeoutMs: cfg.timeoutMs,
|
|
20
|
+
maxRetries: cfg.maxRetries,
|
|
21
|
+
policy: 'idempotent',
|
|
22
|
+
callerSignal: opts.signal,
|
|
23
|
+
fetchImpl: cfg.fetchImpl,
|
|
24
|
+
onRetry: cfg.onRetry,
|
|
25
|
+
});
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
throw (0, errors_1.errorFromResponse)(res.status, (0, http_1.parseBody)(res.text), { endpoint: res.endpoint, attempts: res.attempts });
|
|
28
|
+
}
|
|
29
|
+
let json;
|
|
30
|
+
try {
|
|
31
|
+
json = JSON.parse(res.text);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
throw new errors_1.ZihinAgentError('protocol', 'Expected JSON from GET /api/v2/agents.');
|
|
35
|
+
}
|
|
36
|
+
const data = (0, internal_1.rec)(json).data;
|
|
37
|
+
const list = Array.isArray(data) ? data : [];
|
|
38
|
+
return list.map((item) => {
|
|
39
|
+
const a = (0, internal_1.rec)(item);
|
|
40
|
+
return {
|
|
41
|
+
id: (0, internal_1.str)(a.id) ?? '',
|
|
42
|
+
name: (0, internal_1.str)(a.name),
|
|
43
|
+
commercialName: (0, internal_1.str)(a.commercial_name),
|
|
44
|
+
bio: (0, internal_1.str)(a.bio),
|
|
45
|
+
type: (0, internal_1.str)(a.type),
|
|
46
|
+
status: (0, internal_1.str)(a.status),
|
|
47
|
+
tags: Array.isArray(a.tags) ? a.tags.filter((t) => typeof t === 'string') : undefined,
|
|
48
|
+
toolsCount: typeof a.tools_count === 'number' ? a.tools_count : undefined,
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAkBH,gCAyCC;AAzDD,qCAA8D;AAC9D,iCAAuF;AACvF,yCAAsC;AAatC,sDAAsD;AAC/C,KAAK,UAAU,UAAU,CAC/B,GAAmB,EACnB,OAAiC,EAAE;IAEnC,MAAM,GAAG,GAAG,MAAM,IAAA,sBAAe,EAAC;QACjC,MAAM,EAAE,KAAK;QACb,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,gBAAgB;QACnC,OAAO,EAAE,IAAA,mBAAY,EAAC,GAAG,CAAC,MAAM,CAAC;QACjC,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,MAAM,EAAE,YAAY;QACpB,YAAY,EAAE,IAAI,CAAC,MAAM;QACzB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,OAAO,EAAE,GAAG,CAAC,OAAO;KACpB,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,IAAA,0BAAiB,EAAC,GAAG,CAAC,MAAM,EAAE,IAAA,gBAAS,EAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9G,CAAC;IAED,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACJ,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,IAAI,wBAAe,CAAC,UAAU,EAAE,wCAAwC,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,cAAG,EAAC,IAAI,CAAC,CAAC,IAAI,CAAC;IAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,CAAC,GAAG,IAAA,cAAG,EAAC,IAAI,CAAC,CAAC;QACpB,OAAO;YACN,EAAE,EAAE,IAAA,cAAG,EAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;YACnB,IAAI,EAAE,IAAA,cAAG,EAAC,CAAC,CAAC,IAAI,CAAC;YACjB,cAAc,EAAE,IAAA,cAAG,EAAC,CAAC,CAAC,eAAe,CAAC;YACtC,GAAG,EAAE,IAAA,cAAG,EAAC,CAAC,CAAC,GAAG,CAAC;YACf,IAAI,EAAE,IAAA,cAAG,EAAC,CAAC,CAAC,IAAI,CAAC;YACjB,MAAM,EAAE,IAAA,cAAG,EAAC,CAAC,CAAC,MAAM,CAAC;YACrB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAc,CAAC,CAAC,CAAC,SAAS;YACnG,UAAU,EAAE,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;SACzE,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZihinAgentClient — fachada do núcleo. Carrega a config uma vez (auth, baseUrl, timeout,
|
|
3
|
+
* retries) e expõe os dois caminhos do padrão híbrido:
|
|
4
|
+
* • Direto: invokeAgent / streamAgent (POST /stream, SSE bufferizado)
|
|
5
|
+
* • Triggers: createTrigger / dispatchAgent / getExecution (async + callback)
|
|
6
|
+
* • Auxiliar: listAgents (dropdown de agentes)
|
|
7
|
+
*
|
|
8
|
+
* @module client
|
|
9
|
+
*/
|
|
10
|
+
import { type AgentSummary } from './agents';
|
|
11
|
+
import type { AgentResult, AgentStreamChunk, CreateTriggerParams, DeleteTriggerParams, DispatchAgentParams, DispatchResult, ExecutionStatus, FindOrCreateResult, GetExecutionParams, GetTriggerParams, InvokeAgentParams, ListTriggersParams, TriggerInfo, TriggerRef, ZihinClientConfig } from './types';
|
|
12
|
+
export declare class ZihinAgentClient {
|
|
13
|
+
private readonly cfg;
|
|
14
|
+
constructor(config: ZihinClientConfig);
|
|
15
|
+
/** Base URL efetiva (após validação SSRF). */
|
|
16
|
+
get baseUrl(): string;
|
|
17
|
+
/** Invoca o agente e retorna o resultado final consolidado (response + metrics). */
|
|
18
|
+
invokeAgent(params: InvokeAgentParams): Promise<AgentResult>;
|
|
19
|
+
/** Emite deltas ao vivo do agente (async iterator). */
|
|
20
|
+
streamAgent(params: InvokeAgentParams): AsyncGenerator<AgentStreamChunk>;
|
|
21
|
+
/** Provisiona (1x) um trigger de webhook ligado a um agente. */
|
|
22
|
+
createTrigger(params: CreateTriggerParams): Promise<TriggerRef>;
|
|
23
|
+
/** Reaproveita (por agente+nome) ou cria um trigger — evita duplicação. */
|
|
24
|
+
findOrCreateTrigger(params: CreateTriggerParams): Promise<FindOrCreateResult>;
|
|
25
|
+
/** Lista os triggers do tenant (filtros opcionais). */
|
|
26
|
+
listTriggers(params?: ListTriggersParams): Promise<TriggerInfo[]>;
|
|
27
|
+
/** Obtém um trigger pelo id (inclui webhookUrl). */
|
|
28
|
+
getTrigger(params: GetTriggerParams): Promise<TriggerInfo>;
|
|
29
|
+
/** Remove um trigger (requer key admin/owner). */
|
|
30
|
+
deleteTrigger(params: DeleteTriggerParams): Promise<{
|
|
31
|
+
deleted: boolean;
|
|
32
|
+
}>;
|
|
33
|
+
/** Dispara um trigger: 202 (async) ou JSON imediato (sync). */
|
|
34
|
+
dispatchAgent(params: DispatchAgentParams): Promise<DispatchResult>;
|
|
35
|
+
/** Consulta o resultado de uma execução disparada por trigger (polling). */
|
|
36
|
+
getExecution(params: GetExecutionParams): Promise<ExecutionStatus>;
|
|
37
|
+
/** Lista os agentes do tenant (dropdown). */
|
|
38
|
+
listAgents(opts?: {
|
|
39
|
+
signal?: AbortSignal;
|
|
40
|
+
}): Promise<AgentSummary[]>;
|
|
41
|
+
}
|
|
42
|
+
/** Açúcar: cria um cliente a partir da config. */
|
|
43
|
+
export declare function createClient(config: ZihinClientConfig): ZihinAgentClient;
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ZihinAgentClient — fachada do núcleo. Carrega a config uma vez (auth, baseUrl, timeout,
|
|
4
|
+
* retries) e expõe os dois caminhos do padrão híbrido:
|
|
5
|
+
* • Direto: invokeAgent / streamAgent (POST /stream, SSE bufferizado)
|
|
6
|
+
* • Triggers: createTrigger / dispatchAgent / getExecution (async + callback)
|
|
7
|
+
* • Auxiliar: listAgents (dropdown de agentes)
|
|
8
|
+
*
|
|
9
|
+
* @module client
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ZihinAgentClient = void 0;
|
|
13
|
+
exports.createClient = createClient;
|
|
14
|
+
const agents_1 = require("./agents");
|
|
15
|
+
const http_1 = require("./http");
|
|
16
|
+
const invoke_1 = require("./invoke");
|
|
17
|
+
const triggers_1 = require("./triggers");
|
|
18
|
+
class ZihinAgentClient {
|
|
19
|
+
constructor(config) {
|
|
20
|
+
this.cfg = (0, http_1.resolveConfig)(config);
|
|
21
|
+
}
|
|
22
|
+
/** Base URL efetiva (após validação SSRF). */
|
|
23
|
+
get baseUrl() {
|
|
24
|
+
return this.cfg.baseUrl;
|
|
25
|
+
}
|
|
26
|
+
// ---- Caminho A: direto (SSE) ----
|
|
27
|
+
/** Invoca o agente e retorna o resultado final consolidado (response + metrics). */
|
|
28
|
+
invokeAgent(params) {
|
|
29
|
+
return (0, invoke_1.invokeAgent)(this.cfg, params);
|
|
30
|
+
}
|
|
31
|
+
/** Emite deltas ao vivo do agente (async iterator). */
|
|
32
|
+
streamAgent(params) {
|
|
33
|
+
return (0, invoke_1.streamAgent)(this.cfg, params);
|
|
34
|
+
}
|
|
35
|
+
// ---- Caminho B: triggers (async/callback) ----
|
|
36
|
+
/** Provisiona (1x) um trigger de webhook ligado a um agente. */
|
|
37
|
+
createTrigger(params) {
|
|
38
|
+
return (0, triggers_1.createTrigger)(this.cfg, params);
|
|
39
|
+
}
|
|
40
|
+
/** Reaproveita (por agente+nome) ou cria um trigger — evita duplicação. */
|
|
41
|
+
findOrCreateTrigger(params) {
|
|
42
|
+
return (0, triggers_1.findOrCreateTrigger)(this.cfg, params);
|
|
43
|
+
}
|
|
44
|
+
/** Lista os triggers do tenant (filtros opcionais). */
|
|
45
|
+
listTriggers(params = {}) {
|
|
46
|
+
return (0, triggers_1.listTriggers)(this.cfg, params);
|
|
47
|
+
}
|
|
48
|
+
/** Obtém um trigger pelo id (inclui webhookUrl). */
|
|
49
|
+
getTrigger(params) {
|
|
50
|
+
return (0, triggers_1.getTrigger)(this.cfg, params);
|
|
51
|
+
}
|
|
52
|
+
/** Remove um trigger (requer key admin/owner). */
|
|
53
|
+
deleteTrigger(params) {
|
|
54
|
+
return (0, triggers_1.deleteTrigger)(this.cfg, params);
|
|
55
|
+
}
|
|
56
|
+
/** Dispara um trigger: 202 (async) ou JSON imediato (sync). */
|
|
57
|
+
dispatchAgent(params) {
|
|
58
|
+
return (0, triggers_1.dispatchAgent)(this.cfg, params);
|
|
59
|
+
}
|
|
60
|
+
/** Consulta o resultado de uma execução disparada por trigger (polling). */
|
|
61
|
+
getExecution(params) {
|
|
62
|
+
return (0, triggers_1.getExecution)(this.cfg, params);
|
|
63
|
+
}
|
|
64
|
+
// ---- Auxiliar ----
|
|
65
|
+
/** Lista os agentes do tenant (dropdown). */
|
|
66
|
+
listAgents(opts = {}) {
|
|
67
|
+
return (0, agents_1.listAgents)(this.cfg, opts);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.ZihinAgentClient = ZihinAgentClient;
|
|
71
|
+
/** Açúcar: cria um cliente a partir da config. */
|
|
72
|
+
function createClient(config) {
|
|
73
|
+
return new ZihinAgentClient(config);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAsGH,oCAEC;AAtGD,qCAAyD;AACzD,iCAA4D;AAC5D,qCAAoD;AACpD,yCAQoB;AAmBpB,MAAa,gBAAgB;IAG5B,YAAY,MAAyB;QACpC,IAAI,CAAC,GAAG,GAAG,IAAA,oBAAa,EAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,8CAA8C;IAC9C,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;IACzB,CAAC;IAED,oCAAoC;IAEpC,oFAAoF;IACpF,WAAW,CAAC,MAAyB;QACpC,OAAO,IAAA,oBAAW,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,uDAAuD;IACvD,WAAW,CAAC,MAAyB;QACpC,OAAO,IAAA,oBAAW,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,iDAAiD;IAEjD,gEAAgE;IAChE,aAAa,CAAC,MAA2B;QACxC,OAAO,IAAA,wBAAa,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,2EAA2E;IAC3E,mBAAmB,CAAC,MAA2B;QAC9C,OAAO,IAAA,8BAAmB,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,uDAAuD;IACvD,YAAY,CAAC,SAA6B,EAAE;QAC3C,OAAO,IAAA,uBAAY,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,oDAAoD;IACpD,UAAU,CAAC,MAAwB;QAClC,OAAO,IAAA,qBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,kDAAkD;IAClD,aAAa,CAAC,MAA2B;QACxC,OAAO,IAAA,wBAAa,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,+DAA+D;IAC/D,aAAa,CAAC,MAA2B;QACxC,OAAO,IAAA,wBAAa,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,4EAA4E;IAC5E,YAAY,CAAC,MAA0B;QACtC,OAAO,IAAA,uBAAY,EAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,qBAAqB;IAErB,6CAA6C;IAC7C,UAAU,CAAC,OAAiC,EAAE;QAC7C,OAAO,IAAA,mBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;CACD;AAnED,4CAmEC;AAED,kDAAkD;AAClD,SAAgB,YAAY,CAAC,MAAyB;IACrD,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Erros do @zihin/agent-client — sanitizados (sem vazar key/Bearer/stack), mas COMPLETOS:
|
|
3
|
+
* carregam endpoint, nº de tentativas e request_id do BE para depuração em produção externa.
|
|
4
|
+
*
|
|
5
|
+
* @module errors
|
|
6
|
+
*/
|
|
7
|
+
export type ZihinErrorKind = 'config' | 'auth' | 'not_found' | 'rate_limit' | 'timeout' | 'aborted' | 'server' | 'network' | 'protocol' | 'unknown';
|
|
8
|
+
/** Contexto opcional anexado a um erro para correlação/depuração. */
|
|
9
|
+
export interface ErrorMeta {
|
|
10
|
+
/** Ex.: "POST llm.zihin.ai/api/v2/agents/abc/stream". */
|
|
11
|
+
endpoint?: string;
|
|
12
|
+
/** Número de tentativas feitas antes de falhar. */
|
|
13
|
+
attempts?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ZihinErrorOptions extends ErrorMeta {
|
|
16
|
+
status?: number;
|
|
17
|
+
code?: string;
|
|
18
|
+
retryable?: boolean;
|
|
19
|
+
/** request_id do BE (NÃO é segredo) — handle para o suporte correlacionar nos logs. */
|
|
20
|
+
requestId?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class ZihinAgentError extends Error {
|
|
23
|
+
readonly kind: ZihinErrorKind;
|
|
24
|
+
readonly status?: number;
|
|
25
|
+
readonly code?: string;
|
|
26
|
+
readonly retryable: boolean;
|
|
27
|
+
readonly requestId?: string;
|
|
28
|
+
readonly attempts?: number;
|
|
29
|
+
readonly endpoint?: string;
|
|
30
|
+
constructor(kind: ZihinErrorKind, message: string, opts?: ZihinErrorOptions);
|
|
31
|
+
}
|
|
32
|
+
/** Mapeia um status HTTP + corpo (já parseado) para um ZihinAgentError completo. */
|
|
33
|
+
export declare function errorFromResponse(status: number, body: unknown, meta?: ErrorMeta): ZihinAgentError;
|
|
34
|
+
/** Normaliza qualquer throw (network/abort/timeout) para ZihinAgentError, com a causa-raiz. */
|
|
35
|
+
export declare function errorFromThrow(err: unknown, timeoutMs?: number, meta?: ErrorMeta): ZihinAgentError;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Erros do @zihin/agent-client — sanitizados (sem vazar key/Bearer/stack), mas COMPLETOS:
|
|
4
|
+
* carregam endpoint, nº de tentativas e request_id do BE para depuração em produção externa.
|
|
5
|
+
*
|
|
6
|
+
* @module errors
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.ZihinAgentError = void 0;
|
|
10
|
+
exports.errorFromResponse = errorFromResponse;
|
|
11
|
+
exports.errorFromThrow = errorFromThrow;
|
|
12
|
+
const internal_1 = require("./internal");
|
|
13
|
+
const security_1 = require("./security");
|
|
14
|
+
class ZihinAgentError extends Error {
|
|
15
|
+
constructor(kind, message, opts = {}) {
|
|
16
|
+
super(buildMessage(message, opts));
|
|
17
|
+
this.name = 'ZihinAgentError';
|
|
18
|
+
this.kind = kind;
|
|
19
|
+
this.status = opts.status;
|
|
20
|
+
this.code = opts.code;
|
|
21
|
+
this.requestId = opts.requestId;
|
|
22
|
+
this.attempts = opts.attempts;
|
|
23
|
+
this.endpoint = opts.endpoint;
|
|
24
|
+
this.retryable =
|
|
25
|
+
opts.retryable ?? (kind === 'rate_limit' || kind === 'server' || kind === 'network');
|
|
26
|
+
// Mantém a cadeia de protótipo correta ao transpilar para ES5/ES2021.
|
|
27
|
+
Object.setPrototypeOf(this, ZihinAgentError.prototype);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.ZihinAgentError = ZihinAgentError;
|
|
31
|
+
/** Compõe uma mensagem completa: base + endpoint + tentativas + request_id. */
|
|
32
|
+
function buildMessage(base, opts) {
|
|
33
|
+
let s = base;
|
|
34
|
+
if (opts.endpoint)
|
|
35
|
+
s += ` [${opts.endpoint}]`;
|
|
36
|
+
if (opts.attempts && opts.attempts > 1)
|
|
37
|
+
s += ` (after ${opts.attempts} attempts)`;
|
|
38
|
+
if (opts.requestId)
|
|
39
|
+
s += ` (request_id: ${opts.requestId})`;
|
|
40
|
+
return s;
|
|
41
|
+
}
|
|
42
|
+
function extractRequestId(body) {
|
|
43
|
+
const b = (0, internal_1.rec)(body);
|
|
44
|
+
return (0, internal_1.str)(b.request_id) ?? (0, internal_1.str)(b.requestId) ?? (0, internal_1.str)((0, internal_1.rec)(b.error).request_id);
|
|
45
|
+
}
|
|
46
|
+
/** Mapeia um status HTTP + corpo (já parseado) para um ZihinAgentError completo. */
|
|
47
|
+
function errorFromResponse(status, body, meta = {}) {
|
|
48
|
+
const sanitized = (0, security_1.sanitizeApiError)(body);
|
|
49
|
+
const message = sanitized.message;
|
|
50
|
+
const code = sanitized.code;
|
|
51
|
+
const base = { status, code, requestId: extractRequestId(body), ...meta };
|
|
52
|
+
if (status === 401)
|
|
53
|
+
return new ZihinAgentError('auth', message || 'Authentication failed.', base);
|
|
54
|
+
if (status === 403)
|
|
55
|
+
return new ZihinAgentError('auth', message ||
|
|
56
|
+
'This API key lacks permission. Use an admin/editor key (member keys cannot create triggers or read telemetry).', base);
|
|
57
|
+
if (status === 404)
|
|
58
|
+
return new ZihinAgentError('not_found', message || 'Resource not found.', base);
|
|
59
|
+
if (status === 429)
|
|
60
|
+
return new ZihinAgentError('rate_limit', message || 'Rate limit exceeded.', { ...base, retryable: true });
|
|
61
|
+
if (status >= 500)
|
|
62
|
+
return new ZihinAgentError('server', message || `Server error (${status}).`, { ...base, retryable: true });
|
|
63
|
+
return new ZihinAgentError('unknown', message || `Request failed (${status}).`, base);
|
|
64
|
+
}
|
|
65
|
+
// Códigos de rede permanentes (não adianta retentar): DNS e TLS.
|
|
66
|
+
const NON_RETRYABLE_NET = /^(ENOTFOUND|EAI_AGAIN|CERT_|ERR_TLS|UNABLE_TO_VERIFY|DEPTH_ZERO)/;
|
|
67
|
+
/** Normaliza qualquer throw (network/abort/timeout) para ZihinAgentError, com a causa-raiz. */
|
|
68
|
+
function errorFromThrow(err, timeoutMs, meta = {}) {
|
|
69
|
+
if (err instanceof ZihinAgentError)
|
|
70
|
+
return err;
|
|
71
|
+
const name = err?.name;
|
|
72
|
+
if (name === 'TimeoutError') {
|
|
73
|
+
return new ZihinAgentError('timeout', `Request timed out after ${timeoutMs ?? '?'}ms.`, {
|
|
74
|
+
...meta,
|
|
75
|
+
retryable: false,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (name === 'AbortError') {
|
|
79
|
+
return new ZihinAgentError('aborted', 'Request was aborted by the caller.', { ...meta, retryable: false });
|
|
80
|
+
}
|
|
81
|
+
// Erros de fetch escondem a causa-raiz em err.cause.code (ENOTFOUND/ECONNREFUSED/TLS...).
|
|
82
|
+
const cause = err?.cause;
|
|
83
|
+
const causeCode = cause?.code;
|
|
84
|
+
const sanitized = (0, security_1.sanitizeApiError)(err);
|
|
85
|
+
const detail = causeCode || sanitized.message || 'Network error';
|
|
86
|
+
const retryable = causeCode ? !NON_RETRYABLE_NET.test(causeCode) : true;
|
|
87
|
+
return new ZihinAgentError('network', `Network error: ${detail}`, { ...meta, retryable });
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transporte HTTP do núcleo: resolução/validação de base URL (SSRF), headers de auth,
|
|
3
|
+
* deadline via AbortController que cobre TODO o request (headers + corpo/stream),
|
|
4
|
+
* e retry com exponential backoff + jitter.
|
|
5
|
+
*
|
|
6
|
+
* Política de retry (evita duplicar efeito colateral):
|
|
7
|
+
* - 'idempotent' (GET): retenta em erro de rede, 429 e 5xx.
|
|
8
|
+
* - 'side-effecting' (POST: invoke/dispatch/create): retenta SÓ em 429/503 (servidor disse
|
|
9
|
+
* "tente depois", sem ter processado). NUNCA em erro de rede — o request pode ter sido
|
|
10
|
+
* recebido e processado mesmo com o socket caindo na volta.
|
|
11
|
+
*
|
|
12
|
+
* @module http
|
|
13
|
+
*/
|
|
14
|
+
import type { RetryInfo, ZihinClientConfig } from './types';
|
|
15
|
+
export declare const DEFAULT_BASE_URL = "https://llm.zihin.ai";
|
|
16
|
+
export declare const DEFAULT_TIMEOUT_MS = 120000;
|
|
17
|
+
export declare const DEFAULT_MAX_RETRIES = 2;
|
|
18
|
+
export declare const DEFAULT_MAX_EVENT_BYTES: number;
|
|
19
|
+
export declare const DEFAULT_MAX_TOTAL_BYTES: number;
|
|
20
|
+
export type RetryPolicy = 'idempotent' | 'side-effecting';
|
|
21
|
+
export interface ResolvedConfig {
|
|
22
|
+
apiKey: string;
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
timeoutMs: number;
|
|
25
|
+
maxRetries: number;
|
|
26
|
+
maxStreamEventBytes: number;
|
|
27
|
+
maxStreamTotalBytes: number;
|
|
28
|
+
/** fetch injetado explicitamente; se ausente, usa `globalThis.fetch` no momento da chamada. */
|
|
29
|
+
fetchImpl?: typeof fetch;
|
|
30
|
+
onRetry?: (info: RetryInfo) => void;
|
|
31
|
+
}
|
|
32
|
+
/** Valida a config e devolve valores efetivos. Lança ZihinAgentError('config') se inválida. */
|
|
33
|
+
export declare function resolveConfig(config: ZihinClientConfig): ResolvedConfig;
|
|
34
|
+
/** Rótulo de endpoint para mensagens de erro/observabilidade: "POST host/path". */
|
|
35
|
+
export declare function endpointLabel(method: string, url: string): string;
|
|
36
|
+
export declare function buildHeaders(apiKey: string, extra?: Record<string, string>): Record<string, string>;
|
|
37
|
+
export interface Deadline {
|
|
38
|
+
signal: AbortSignal;
|
|
39
|
+
dispose: () => void;
|
|
40
|
+
timedOut: () => boolean;
|
|
41
|
+
abortedByCaller: () => boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Cria um deadline que aborta o request após `timeoutMs` (cobre headers E corpo/stream) e
|
|
45
|
+
* propaga o abort do chamador. Mantenha vivo até o corpo/stream terminar; chame dispose() ao fim.
|
|
46
|
+
*/
|
|
47
|
+
export declare function createDeadline(timeoutMs: number, callerSignal?: AbortSignal): Deadline;
|
|
48
|
+
export interface BufferedResponse {
|
|
49
|
+
status: number;
|
|
50
|
+
ok: boolean;
|
|
51
|
+
text: string;
|
|
52
|
+
/** "POST host/path" — para o chamador anexar ao erro. */
|
|
53
|
+
endpoint: string;
|
|
54
|
+
/** Tentativas feitas (1 = sem retry). */
|
|
55
|
+
attempts: number;
|
|
56
|
+
}
|
|
57
|
+
export interface BufferedRequest {
|
|
58
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
59
|
+
url: string;
|
|
60
|
+
headers: Record<string, string>;
|
|
61
|
+
body?: string;
|
|
62
|
+
timeoutMs: number;
|
|
63
|
+
maxRetries: number;
|
|
64
|
+
policy: RetryPolicy;
|
|
65
|
+
callerSignal?: AbortSignal;
|
|
66
|
+
fetchImpl?: typeof fetch;
|
|
67
|
+
onRetry?: (info: RetryInfo) => void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Executa um request lendo o corpo inteiro dentro do deadline (P1: timeout cobre o download).
|
|
71
|
+
* Retorna mesmo em não-2xx (o chamador converte via errorFromResponse).
|
|
72
|
+
*/
|
|
73
|
+
export declare function requestBuffered(args: BufferedRequest): Promise<BufferedResponse>;
|
|
74
|
+
export interface StreamHandle {
|
|
75
|
+
response: Response;
|
|
76
|
+
/** Mantenha vivo durante a iteração do stream; dispose() ao terminar/abortar. */
|
|
77
|
+
deadline: Deadline;
|
|
78
|
+
/** "POST host/path" — para o chamador anexar ao erro no caminho !ok. */
|
|
79
|
+
endpoint: string;
|
|
80
|
+
}
|
|
81
|
+
export interface StreamRequest {
|
|
82
|
+
url: string;
|
|
83
|
+
headers: Record<string, string>;
|
|
84
|
+
body?: string;
|
|
85
|
+
timeoutMs: number;
|
|
86
|
+
maxRetries: number;
|
|
87
|
+
callerSignal?: AbortSignal;
|
|
88
|
+
fetchImpl?: typeof fetch;
|
|
89
|
+
onRetry?: (info: RetryInfo) => void;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Abre um POST SSE. Retenta só pré-stream em 429/503 (POST side-effecting). Em sucesso/4xx
|
|
93
|
+
* devolve a Response COM o deadline ainda ativo — o consumidor do stream chama deadline.dispose()
|
|
94
|
+
* ao finalizar (P1: o timeout cobre toda a duração do stream, e o abort do chamador continua ligado).
|
|
95
|
+
*/
|
|
96
|
+
export declare function openStream(args: StreamRequest): Promise<StreamHandle>;
|
|
97
|
+
/** Faz parse seguro de um corpo (JSON quando possível, senão {message}). */
|
|
98
|
+
export declare function parseBody(text: string): unknown;
|