@t4h/agent-runtime 0.1.1 → 0.2.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 +77 -5
- package/catalog/agents.catalog.yaml +123 -0
- package/dist/catalog.d.ts +13 -0
- package/dist/catalog.js +39 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cli.js +33 -8
- package/dist/cli.js.map +1 -1
- package/dist/connector.d.ts +13 -0
- package/dist/connector.js +208 -0
- package/dist/connector.js.map +1 -0
- package/dist/env.d.ts +56 -0
- package/dist/env.js +134 -0
- package/dist/env.js.map +1 -0
- package/dist/evals.js +1 -1
- package/dist/host.d.ts +111 -13
- package/dist/host.js +251 -43
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +16 -4
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/notifier.d.ts +1 -1
- package/dist/policy.js +12 -1
- package/dist/policy.js.map +1 -1
- package/dist/prompt.d.ts +8 -0
- package/dist/prompt.js +10 -3
- package/dist/prompt.js.map +1 -1
- package/dist/round.js +2 -1
- package/dist/round.js.map +1 -1
- package/dist/runtime-tools.d.ts +1 -1
- package/dist/runtime-tools.js +3 -3
- package/dist/runtime-tools.js.map +1 -1
- package/dist/signature.d.ts +34 -0
- package/dist/signature.js +87 -0
- package/dist/signature.js.map +1 -0
- package/dist/start.d.ts +31 -0
- package/dist/start.js +109 -0
- package/dist/start.js.map +1 -0
- package/dist/store/long-term.d.ts +63 -3
- package/dist/store/long-term.js +71 -11
- package/dist/store/long-term.js.map +1 -1
- package/dist/store/migrations.d.ts +1 -1
- package/dist/store/migrations.js +24 -0
- package/dist/store/migrations.js.map +1 -1
- package/dist/wiring.d.ts +11 -0
- package/dist/wiring.js +32 -0
- package/dist/wiring.js.map +1 -0
- package/package.json +13 -6
- package/proto/t4h/agents/v1/agents.proto +176 -0
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# @t4h/agent-runtime
|
|
2
2
|
|
|
3
3
|
Runtime dos **colaboradores digitais** da Tech for Humans. Um agente é uma pasta
|
|
4
|
-
(`agent.yaml`, `persona.md`, `skills/`, `evals/`); este pacote faz o resto
|
|
4
|
+
(`agent.yaml`, `persona.md`, `skills/`, `evals/`); este pacote faz o resto, como o
|
|
5
|
+
`@t4h/mcp-provider-sdk` faz para os providers:
|
|
5
6
|
|
|
6
7
|
- valida o `agent.yaml` (schema v1 em `schema/agent.schema.json` + regras entre campos);
|
|
7
|
-
- caixa de entrada no Postgres: junta eventos por assunto, descarta repetido
|
|
8
|
+
- caixa de entrada no Postgres: junta eventos por assunto, descarta repetido (por fonte),
|
|
9
|
+
ordena por prioridade; evento novo acorda o agente, e o cron fica como rede de segurança;
|
|
8
10
|
- rodadas com lock, teto de itens e de tempo, backoff e exceção para o DRI;
|
|
9
11
|
- portão de política em toda chamada de ferramenta: nível por rotina (shadow, copilot,
|
|
10
12
|
agent, autonomous), proibidas, motivo obrigatório, idempotência, janela e teto por hora;
|
|
@@ -12,13 +14,83 @@ Runtime dos **colaboradores digitais** da Tech for Humans. Um agente é uma past
|
|
|
12
14
|
- memória curta (SQLite, uma execução) e longa (Postgres);
|
|
13
15
|
- acesso aos sistemas só pelo Enterprise MCP Gateway, com a identidade própria do agente
|
|
14
16
|
(client do Keycloak com service account);
|
|
15
|
-
- cérebro: Claude Agent SDK isolado (sem ferramentas built-in, sem config do disco)
|
|
17
|
+
- cérebro: Claude Agent SDK isolado (sem ferramentas built-in, sem config do disco);
|
|
18
|
+
- o conector `agents_<círculo>` (proto, handlers e catálogo base, versionados juntos),
|
|
19
|
+
o ambiente validado no boot e o processo inteiro em `startAgents()`.
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
[
|
|
21
|
+
Cada círculo cria o seu repositório de agentes a partir de um template (ver
|
|
22
|
+
[Usar como template](../../web/src/content/agents/01-usar-como-template.md)). A documentação
|
|
23
|
+
completa está na seção **Agentes** do site do gateway.
|
|
19
24
|
|
|
20
25
|
```bash
|
|
21
26
|
pnpm --filter @t4h/agent-runtime build
|
|
22
27
|
pnpm --filter @t4h/agent-runtime test # sem modelo: ScriptedBrain + PGlite
|
|
23
28
|
t4h-agent validate agents/ # valida os agent.yaml de um repositório
|
|
29
|
+
t4h-agent catalog financeiro --endpoint agentes-financeiro.example.com:443 > catalog.yaml
|
|
24
30
|
```
|
|
31
|
+
|
|
32
|
+
## Entrypoint de um repositório de agentes
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { startAgents } from '@t4h/agent-runtime';
|
|
36
|
+
|
|
37
|
+
await startAgents({ agentsDir: 'agents', pluginsDir: process.env.PLUGINS_DIR });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`startAgents` carrega os agentes, valida o ambiente (`loadAgentEnv`), abre o banco e roda
|
|
41
|
+
as migrações, sobe o webhook de eventos, o cron e o conector gRPC (`createProviderServer`
|
|
42
|
+
do SDK, auditoria em JSON no stdout) e trata SIGINT/SIGTERM parando na ordem: entrada,
|
|
43
|
+
conector, conversas em andamento, banco. Opções: `wiring` (substitui o gateway por um stub
|
|
44
|
+
local; recusado em produção), `notifier`, `brain`. Fora de produção, sem as variáveis do
|
|
45
|
+
passaporte, sobe sem o conector (com aviso).
|
|
46
|
+
|
|
47
|
+
## Conector `agents_<círculo>`
|
|
48
|
+
|
|
49
|
+
Contrato em `proto/t4h/agents/v1/agents.proto` (`AGENTS_SERVICE_FQN`, `agentsProtoPath()`),
|
|
50
|
+
handlers em `agentsConnectorHandlers(host)` e catálogo base em
|
|
51
|
+
`catalog/agents.catalog.yaml` (`agentsCatalog({ circle, endpoint })` ou
|
|
52
|
+
`t4h-agent catalog`). O slug segue `^agents_[a-z0-9_]+$`. Os grants são por tabela:
|
|
53
|
+
|
|
54
|
+
| Tabela | Tools | Quem recebe |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `agente` | `agents_list`, `agent_ask`, `agent_answer` | quem pode ver e conversar com os agentes |
|
|
57
|
+
| `acao` | `agent_explain`, `action_correct` | quem audita e corrige |
|
|
58
|
+
| `proposta` | `agent_proposals`, `proposal_decide` | quem aprova (líder do time, DRI) |
|
|
59
|
+
| `controle` | `agent_block`, `routine_cap` | só Segurança e o DRI |
|
|
60
|
+
|
|
61
|
+
A conversa é assíncrona: o gateway corta a chamada ao provider em
|
|
62
|
+
`PROVIDER_CALL_TIMEOUT_MS` (30 s por padrão). `agent_ask` espera até `AGENTS_ASK_WAIT_MS`
|
|
63
|
+
(20 s) e, se a resposta não veio, devolve `running` com o `ask_id`; `agent_answer` busca
|
|
64
|
+
depois, de qualquer réplica, e só para quem perguntou.
|
|
65
|
+
|
|
66
|
+
## Eventos
|
|
67
|
+
|
|
68
|
+
`POST /agents/:id/events` com `x-t4h-source: <fonte>` e
|
|
69
|
+
`x-t4h-signature: t=<unix s>,v1=<hex>`, onde `v1 = HMAC-SHA256(segredo da fonte, "<t>.<corpo cru>")`
|
|
70
|
+
(`signEvent()` monta o header). Tolerância de 300 s. O id do evento é gravado como
|
|
71
|
+
`<fonte>:<id>`. `POST /agents/:id/rounds` só existe fora de produção.
|
|
72
|
+
|
|
73
|
+
## Ambiente
|
|
74
|
+
|
|
75
|
+
| Variável | Produção | Padrão / fora de produção |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `DATABASE_URL` | `postgres://…` obrigatório | `pglite:<pasta>` ou em memória |
|
|
78
|
+
| `EVENTS_HMAC_SECRETS` | `fonte=segredo,…`, ao menos uma | sem: aceita sem assinatura |
|
|
79
|
+
| `EVENTS_PORT` / `EVENTS_WAKE_DEBOUNCE_MS` | | 8080 / 10000 |
|
|
80
|
+
| `GATEWAY_URL`, `KEYCLOAK_ISSUER` | obrigatórios | sem `GATEWAY_URL`: `wiring` local |
|
|
81
|
+
| `AGENT_<ID>_CLIENT_SECRET` | um por agente (hífen vira `_`) | |
|
|
82
|
+
| `GATEWAY_DEV_TOKEN` | proibido | token fixo no lugar do Keycloak |
|
|
83
|
+
| `ANTHROPIC_API_KEY` | obrigatório (ou `CLAUDE_CODE_USE_BEDROCK`/`_VERTEX`) | |
|
|
84
|
+
| `AGENTS_ASK_WAIT_MS` | | 20000, abaixo de `PROVIDER_CALL_TIMEOUT_MS` (30000) |
|
|
85
|
+
| `PORT`, `GATEWAY_JWKS_URL`, `GATEWAY_ISSUER`, `SERVICE_AUDIENCE`, mTLS | como em `loadProviderEnv()` | sem passaporte: sem conector |
|
|
86
|
+
|
|
87
|
+
## Da 0.1 para a 0.2
|
|
88
|
+
|
|
89
|
+
- O conector (proto, handlers, catálogo) e o wiring do gateway saíram do template e
|
|
90
|
+
vieram para cá; o template deixa de depender de `@t4h/mcp-provider-sdk` e `@grpc/grpc-js`.
|
|
91
|
+
- `AskAgent` agora devolve `ask_id`/`status` e ganhou `GetAnswer`; `conversation_id` virou
|
|
92
|
+
`thread_id`. RPCs novas: `SetBlocked` e `CapRoutine` (tabela `controle`).
|
|
93
|
+
- `host.listen(port, secret)` virou `host.listen(port, { secrets, allowManualRounds, production })`;
|
|
94
|
+
`EVENTS_HMAC_SECRET` virou `EVENTS_HMAC_SECRETS` (por fonte, com timestamp) e
|
|
95
|
+
`verifySignature` saiu (use `verifyEventSignature`).
|
|
96
|
+
- Migração aditiva: tabela `agent_conversation` e coluna `agent_event.source`.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Catálogo do conector de agentes de um círculo, gerado por
|
|
2
|
+
# t4h-agent catalog {{circle}} --endpoint {{endpoint}}
|
|
3
|
+
# a partir do catálogo base do @t4h/agent-runtime (versionado junto do proto). Não edite à
|
|
4
|
+
# mão: gere de novo com a versão do runtime que o círculo usa.
|
|
5
|
+
#
|
|
6
|
+
# Cada chave de inputSchema.properties é um campo do request no proto (snake_case). Grants
|
|
7
|
+
# (URN `agents_{{circle}}:<resourceTable>:<campo>`) seguem o fluxo de permissões da
|
|
8
|
+
# plataforma, nunca este arquivo:
|
|
9
|
+
# agente: agents, agent_id, ask_id, status, answer, error quem pode ver e conversar com os agentes
|
|
10
|
+
# acao: actions, action_id, status, routine_level quem audita e corrige
|
|
11
|
+
# proposta: proposals, action_id, status, result_json quem aprova (líder do time, DRI)
|
|
12
|
+
# controle: agent_id, blocked, routine, level só Segurança e o DRI
|
|
13
|
+
subservice: agents_{{circle}}
|
|
14
|
+
endpoints:
|
|
15
|
+
local: '{{local_endpoint}}'
|
|
16
|
+
production: '{{endpoint}}'
|
|
17
|
+
tools:
|
|
18
|
+
- name: agents_list
|
|
19
|
+
rpc: ListAgents
|
|
20
|
+
description: 'Lista os colaboradores digitais deste círculo: o que cada um faz, o nível de cada rotina agora (e por que desceu, se desceu), DRI, time e se está bloqueado.'
|
|
21
|
+
resourceTable: agente
|
|
22
|
+
readOnly: true
|
|
23
|
+
inputSchema: { type: object, properties: {} }
|
|
24
|
+
|
|
25
|
+
- name: agent_ask
|
|
26
|
+
rpc: AskAgent
|
|
27
|
+
description: 'Conversa com um agente. Ele só lê, com o acesso dele. Se a resposta vier com status "running", chame agent_answer com o ask_id em alguns segundos; se vier "error", agent_answer traz o motivo. Cada pessoa tem um teto de perguntas em andamento com o mesmo agente. Para pedir uma ação, abra a demanda pelo canal normal.'
|
|
28
|
+
resourceTable: agente
|
|
29
|
+
readOnly: false
|
|
30
|
+
inputSchema:
|
|
31
|
+
type: object
|
|
32
|
+
properties:
|
|
33
|
+
agent_id: { type: string }
|
|
34
|
+
message: { type: string }
|
|
35
|
+
thread_id: { type: string, description: 'Opcional: para continuar uma conversa, passe o ask_id da primeira pergunta (ou um id seu: até 64 letras, dígitos, "_" ou "-"). O agente recebe as últimas trocas desse fio feitas por você.' }
|
|
36
|
+
required: [agent_id, message]
|
|
37
|
+
|
|
38
|
+
- name: agent_answer
|
|
39
|
+
rpc: GetAnswer
|
|
40
|
+
description: 'Busca a resposta de uma pergunta feita com agent_ask. Enquanto vier "running", espere alguns segundos e chame de novo. Só quem perguntou lê a resposta.'
|
|
41
|
+
resourceTable: agente
|
|
42
|
+
readOnly: true
|
|
43
|
+
inputSchema:
|
|
44
|
+
type: object
|
|
45
|
+
properties:
|
|
46
|
+
ask_id: { type: string }
|
|
47
|
+
required: [ask_id]
|
|
48
|
+
|
|
49
|
+
- name: agent_explain
|
|
50
|
+
rpc: ExplainActions
|
|
51
|
+
description: 'Mostra o que um agente fez, em que modo (executou, propôs, só registrou, foi barrado) e com que motivo. Filtra por assunto (ex.: ticket:123).'
|
|
52
|
+
resourceTable: acao
|
|
53
|
+
readOnly: true
|
|
54
|
+
inputSchema:
|
|
55
|
+
type: object
|
|
56
|
+
properties:
|
|
57
|
+
agent_id: { type: string }
|
|
58
|
+
subject: { type: string }
|
|
59
|
+
limit: { type: integer, minimum: 1, maximum: 100 }
|
|
60
|
+
required: [agent_id]
|
|
61
|
+
|
|
62
|
+
- name: agent_proposals
|
|
63
|
+
rpc: ListProposals
|
|
64
|
+
description: 'Propostas de um agente esperando aprovação de uma pessoa (rotinas no nível Copiloto).'
|
|
65
|
+
resourceTable: proposta
|
|
66
|
+
readOnly: true
|
|
67
|
+
inputSchema:
|
|
68
|
+
type: object
|
|
69
|
+
properties:
|
|
70
|
+
agent_id: { type: string }
|
|
71
|
+
required: [agent_id]
|
|
72
|
+
|
|
73
|
+
- name: proposal_decide
|
|
74
|
+
rpc: DecideProposal
|
|
75
|
+
description: 'Aprova ou recusa uma proposta. Aprovada, a ação roda na hora com a identidade do agente e fica registrada com quem aprovou.'
|
|
76
|
+
resourceTable: proposta
|
|
77
|
+
readOnly: false
|
|
78
|
+
inputSchema:
|
|
79
|
+
type: object
|
|
80
|
+
properties:
|
|
81
|
+
action_id: { type: integer }
|
|
82
|
+
approve: { type: boolean }
|
|
83
|
+
note: { type: string }
|
|
84
|
+
required: [action_id, approve]
|
|
85
|
+
|
|
86
|
+
- name: action_correct
|
|
87
|
+
rpc: CorrectAction
|
|
88
|
+
description: 'Corrige uma ação que o agente executou: diga o que estava errado e o certo. Vira aprendizado e conta no disjuntor, que desce o nível da rotina se os erros passarem do limite.'
|
|
89
|
+
resourceTable: acao
|
|
90
|
+
readOnly: false
|
|
91
|
+
inputSchema:
|
|
92
|
+
type: object
|
|
93
|
+
properties:
|
|
94
|
+
action_id: { type: integer }
|
|
95
|
+
note: { type: string }
|
|
96
|
+
required: [action_id, note]
|
|
97
|
+
|
|
98
|
+
- name: agent_block
|
|
99
|
+
rpc: SetBlocked
|
|
100
|
+
description: 'Bloqueio de emergência: blocked=true para tudo o que o agente faz na hora, sem deploy (motivo obrigatório); blocked=false libera. Avisa o DRI e Segurança.'
|
|
101
|
+
resourceTable: controle
|
|
102
|
+
readOnly: false
|
|
103
|
+
inputSchema:
|
|
104
|
+
type: object
|
|
105
|
+
properties:
|
|
106
|
+
agent_id: { type: string }
|
|
107
|
+
blocked: { type: boolean }
|
|
108
|
+
reason: { type: string }
|
|
109
|
+
required: [agent_id, blocked]
|
|
110
|
+
|
|
111
|
+
- name: routine_cap
|
|
112
|
+
rpc: CapRoutine
|
|
113
|
+
description: 'Limita o nível de uma rotina do agente (shadow, copilot ou agent), com motivo. Com level vazio, tira o teto e volta a valer o nível do manifesto. Avisa o DRI e Segurança.'
|
|
114
|
+
resourceTable: controle
|
|
115
|
+
readOnly: false
|
|
116
|
+
inputSchema:
|
|
117
|
+
type: object
|
|
118
|
+
properties:
|
|
119
|
+
agent_id: { type: string }
|
|
120
|
+
routine: { type: string }
|
|
121
|
+
level: { type: string, enum: ['', shadow, copilot, agent] }
|
|
122
|
+
reason: { type: string }
|
|
123
|
+
required: [agent_id, routine, level]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** `agents_<círculo>`: o schema do catálogo não aceita hífen no subservice. */
|
|
2
|
+
export declare const AGENTS_SLUG_PATTERN: RegExp;
|
|
3
|
+
export declare function agentsCatalogPath(): string;
|
|
4
|
+
export interface AgentsCatalogOptions {
|
|
5
|
+
/** Nome do círculo em minúsculas, com `_` no lugar de hífen: `financeiro`, `dados_bi`. */
|
|
6
|
+
circle: string;
|
|
7
|
+
/** Endpoint gRPC de produção do conector (`host:porta`). */
|
|
8
|
+
endpoint: string;
|
|
9
|
+
/** Endpoint para TARGET_ENV=local. Padrão: o mesmo de `endpoint`. */
|
|
10
|
+
localEndpoint?: string;
|
|
11
|
+
}
|
|
12
|
+
/** O catálogo de `agents_<círculo>` em YAML, pronto para o repositório de catálogos. */
|
|
13
|
+
export declare function agentsCatalog(o: AgentsCatalogOptions): string;
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catálogo do conector `agents_<círculo>`: o base (`catalog/agents.catalog.yaml`) mora
|
|
3
|
+
* aqui, versionado junto do proto, para tool e RPC nunca se desencontrarem. O repositório
|
|
4
|
+
* de catálogos do gateway gera o de cada círculo com `t4h-agent catalog`, sem escrever à mão.
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync } from 'node:fs';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { parse as parseYaml } from 'yaml';
|
|
9
|
+
/** `agents_<círculo>`: o schema do catálogo não aceita hífen no subservice. */
|
|
10
|
+
export const AGENTS_SLUG_PATTERN = /^agents_[a-z0-9_]+$/;
|
|
11
|
+
/** Mesmo padrão de endpoint do schema do catálogo (`host:porta`). */
|
|
12
|
+
const ENDPOINT_PATTERN = /^[a-zA-Z0-9.-]+:[0-9]{1,5}$/;
|
|
13
|
+
/** O subservice tem no máximo 50 caracteres (schema do catálogo). */
|
|
14
|
+
const MAX_SUBSERVICE = 50;
|
|
15
|
+
export function agentsCatalogPath() {
|
|
16
|
+
return fileURLToPath(new URL('../catalog/agents.catalog.yaml', import.meta.url));
|
|
17
|
+
}
|
|
18
|
+
/** O catálogo de `agents_<círculo>` em YAML, pronto para o repositório de catálogos. */
|
|
19
|
+
export function agentsCatalog(o) {
|
|
20
|
+
const slug = `agents_${o.circle}`;
|
|
21
|
+
if (!AGENTS_SLUG_PATTERN.test(slug) || slug.length > MAX_SUBSERVICE) {
|
|
22
|
+
throw new Error(`círculo "${o.circle}" inválido: use minúsculas, dígitos e _ (o slug ${slug} precisa casar ${AGENTS_SLUG_PATTERN} e ter até ${MAX_SUBSERVICE} caracteres)`);
|
|
23
|
+
}
|
|
24
|
+
const local = o.localEndpoint ?? o.endpoint;
|
|
25
|
+
for (const e of [o.endpoint, local]) {
|
|
26
|
+
if (!ENDPOINT_PATTERN.test(e))
|
|
27
|
+
throw new Error(`endpoint "${e}" inválido: use host:porta`);
|
|
28
|
+
}
|
|
29
|
+
const yaml = readFileSync(agentsCatalogPath(), 'utf8')
|
|
30
|
+
.replaceAll('{{circle}}', o.circle)
|
|
31
|
+
.replaceAll('{{local_endpoint}}', local)
|
|
32
|
+
.replaceAll('{{endpoint}}', o.endpoint);
|
|
33
|
+
// Falha aqui, e não no apply, se a substituição quebrar o YAML.
|
|
34
|
+
const parsed = parseYaml(yaml);
|
|
35
|
+
if (parsed.subservice !== slug)
|
|
36
|
+
throw new Error(`catálogo base gerou subservice "${parsed.subservice}", esperado ${slug}`);
|
|
37
|
+
return yaml;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAE1C,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAEzD,qEAAqE;AACrE,MAAM,gBAAgB,GAAG,6BAA6B,CAAC;AAEvD,qEAAqE;AACrE,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,MAAM,UAAU,iBAAiB;IAC/B,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACnF,CAAC;AAWD,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,CAAuB;IACnD,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,MAAM,EAAE,CAAC;IAClC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,MAAM,mDAAmD,IAAI,kBAAkB,mBAAmB,cAAc,cAAc,cAAc,CAAC,CAAC;IAC9K,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,QAAQ,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,4BAA4B,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,IAAI,GAAG,YAAY,CAAC,iBAAiB,EAAE,EAAE,MAAM,CAAC;SACnD,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC;SAClC,UAAU,CAAC,oBAAoB,EAAE,KAAK,CAAC;SACvC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1C,gEAAgE;IAChE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAA4B,CAAC;IAC1D,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAC,UAAU,eAAe,IAAI,EAAE,CAAC,CAAC;IAC3H,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* t4h-agent validate
|
|
2
|
+
* t4h-agent validate [pasta agents/] valida todos os agent.yaml (schema + regras)
|
|
3
|
+
* t4h-agent catalog <círculo> --endpoint <host:porta> imprime o catálogo de agents_<círculo>
|
|
4
|
+
* [--local-endpoint <host:porta>]
|
|
3
5
|
*/
|
|
4
|
-
import {
|
|
6
|
+
import { parseArgs } from 'node:util';
|
|
7
|
+
import { agentsCatalog } from './catalog.js';
|
|
5
8
|
import { effectiveLevel } from './levels.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
try {
|
|
9
|
+
import { loadAgents } from './manifest.js';
|
|
10
|
+
const USAGE = `uso:
|
|
11
|
+
t4h-agent validate [pasta]
|
|
12
|
+
t4h-agent catalog <círculo> --endpoint <host:porta> [--local-endpoint <host:porta>]`;
|
|
13
|
+
function validate(dir = 'agents') {
|
|
12
14
|
const agents = loadAgents(dir);
|
|
13
15
|
for (const a of agents) {
|
|
14
16
|
const m = a.manifest;
|
|
@@ -20,6 +22,29 @@ try {
|
|
|
20
22
|
}
|
|
21
23
|
console.info(`\n${agents.length} agente(s) válido(s).`);
|
|
22
24
|
}
|
|
25
|
+
function catalog(args) {
|
|
26
|
+
const { values, positionals } = parseArgs({
|
|
27
|
+
args,
|
|
28
|
+
allowPositionals: true,
|
|
29
|
+
options: { endpoint: { type: 'string' }, 'local-endpoint': { type: 'string' } },
|
|
30
|
+
});
|
|
31
|
+
const [circle] = positionals;
|
|
32
|
+
if (!circle || !values.endpoint || positionals.length > 1)
|
|
33
|
+
throw new Error(USAGE);
|
|
34
|
+
// Só o YAML no stdout: dá para redirecionar direto para o catalog.yaml.
|
|
35
|
+
process.stdout.write(agentsCatalog({ circle, endpoint: values.endpoint, ...(values['local-endpoint'] ? { localEndpoint: values['local-endpoint'] } : {}) }));
|
|
36
|
+
}
|
|
37
|
+
const [cmd, ...rest] = process.argv.slice(2);
|
|
38
|
+
try {
|
|
39
|
+
if (cmd === 'validate')
|
|
40
|
+
validate(rest[0]);
|
|
41
|
+
else if (cmd === 'catalog')
|
|
42
|
+
catalog(rest);
|
|
43
|
+
else {
|
|
44
|
+
console.error(USAGE);
|
|
45
|
+
process.exit(2);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
23
48
|
catch (e) {
|
|
24
49
|
console.error(e.message);
|
|
25
50
|
process.exit(1);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ProviderHandlers } from '@t4h/mcp-provider-sdk';
|
|
2
|
+
import { type AgentHost } from './host.js';
|
|
3
|
+
export declare const AGENTS_SERVICE_FQN = "t4h.agents.v1.AgentsService";
|
|
4
|
+
/** O proto do conector, publicado com o pacote (o gateway o puxa por reflection). */
|
|
5
|
+
export declare function agentsProtoPath(): string;
|
|
6
|
+
export interface AgentsConnectorOptions {
|
|
7
|
+
/** Quantas ações `ExplainActions` devolve sem `limit` (padrão 20) e no máximo (100). */
|
|
8
|
+
historyLimit?: {
|
|
9
|
+
default: number;
|
|
10
|
+
max: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare function agentsConnectorHandlers(host: AgentHost, opts?: AgentsConnectorOptions): ProviderHandlers;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handlers do conector de agentes do círculo (`proto/t4h/agents/v1/agents.proto`).
|
|
3
|
+
*
|
|
4
|
+
* Mesmo modelo de qualquer provider do gateway: o gateway autentica e autoriza (grants URN
|
|
5
|
+
* por papel, concedidos pela plataforma), manda a FieldMask e o passaporte; aqui só
|
|
6
|
+
* executamos e projetamos. `ctx.user` é auditoria e "quem pergunta": nunca autorização.
|
|
7
|
+
* Quem pode bloquear ou limitar um agente é decidido pelo grant da tabela `controle`.
|
|
8
|
+
*/
|
|
9
|
+
import { status as grpcStatus } from '@grpc/grpc-js';
|
|
10
|
+
import { applyFieldMask, ProviderError } from '@t4h/mcp-provider-sdk';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { HostError } from './host.js';
|
|
13
|
+
import { effectiveLevel } from './levels.js';
|
|
14
|
+
import { CONVERSATION_ROUTINE } from './store/long-term.js';
|
|
15
|
+
export const AGENTS_SERVICE_FQN = 't4h.agents.v1.AgentsService';
|
|
16
|
+
/** O proto do conector, publicado com o pacote (o gateway o puxa por reflection). */
|
|
17
|
+
export function agentsProtoPath() {
|
|
18
|
+
return fileURLToPath(new URL('../proto/t4h/agents/v1/agents.proto', import.meta.url));
|
|
19
|
+
}
|
|
20
|
+
/** Tetos que uma pessoa pode pôr numa rotina pelo conector. */
|
|
21
|
+
const CAP_LEVELS = ['shadow', 'copilot', 'agent'];
|
|
22
|
+
function toAction(a) {
|
|
23
|
+
return {
|
|
24
|
+
id: String(a.id),
|
|
25
|
+
subject: a.subject ?? '',
|
|
26
|
+
routine: a.routine,
|
|
27
|
+
tool: a.tool,
|
|
28
|
+
mode: a.mode,
|
|
29
|
+
status: a.status,
|
|
30
|
+
level: a.level,
|
|
31
|
+
reason: a.reason ?? '',
|
|
32
|
+
input_json: JSON.stringify(a.input),
|
|
33
|
+
note: a.note ?? '',
|
|
34
|
+
created_at: new Date(a.created_at).toISOString(),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function agentOr404(host, id) {
|
|
38
|
+
if (!id || !host.agents.has(id))
|
|
39
|
+
throw new ProviderError(grpcStatus.NOT_FOUND, `agente "${id}" não existe neste conector`);
|
|
40
|
+
return host.agent(id);
|
|
41
|
+
}
|
|
42
|
+
function routineOr404(a, routine) {
|
|
43
|
+
const spec = a.manifest.routines[routine];
|
|
44
|
+
if (!routine || !spec)
|
|
45
|
+
throw new ProviderError(grpcStatus.NOT_FOUND, `${a.manifest.id} não tem a rotina "${routine}"`);
|
|
46
|
+
return spec;
|
|
47
|
+
}
|
|
48
|
+
/** O id de ação chega como texto (uint64 com `longs: String`). */
|
|
49
|
+
function actionId(raw) {
|
|
50
|
+
const id = Number(raw);
|
|
51
|
+
if (!Number.isSafeInteger(id) || id <= 0)
|
|
52
|
+
throw new ProviderError(grpcStatus.INVALID_ARGUMENT, 'action_id inválido');
|
|
53
|
+
return id;
|
|
54
|
+
}
|
|
55
|
+
const HOST_STATUS = {
|
|
56
|
+
unavailable: grpcStatus.UNAVAILABLE,
|
|
57
|
+
resource_exhausted: grpcStatus.RESOURCE_EXHAUSTED,
|
|
58
|
+
invalid_argument: grpcStatus.INVALID_ARGUMENT,
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Erro de regra do host (não existe, já decidida, bloqueado) vira FAILED_PRECONDITION;
|
|
62
|
+
* desligando, teto de conversas e pedido malformado têm status próprio.
|
|
63
|
+
*/
|
|
64
|
+
function precondition(e) {
|
|
65
|
+
if (e instanceof ProviderError)
|
|
66
|
+
throw e;
|
|
67
|
+
if (e instanceof HostError)
|
|
68
|
+
throw new ProviderError(HOST_STATUS[e.code], e.message);
|
|
69
|
+
throw new ProviderError(grpcStatus.FAILED_PRECONDITION, e.message);
|
|
70
|
+
}
|
|
71
|
+
async function levelNow(host, a, routine) {
|
|
72
|
+
const spec = a.manifest.routines[routine];
|
|
73
|
+
if (!spec)
|
|
74
|
+
return '';
|
|
75
|
+
const caps = await host.store.levelCaps(a.manifest.id);
|
|
76
|
+
return effectiveLevel({ stage: a.manifest.stage, manifestLevel: spec.level, cap: caps.get(routine)?.cap ?? null });
|
|
77
|
+
}
|
|
78
|
+
export function agentsConnectorHandlers(host, opts = {}) {
|
|
79
|
+
const limits = opts.historyLimit ?? { default: 20, max: 100 };
|
|
80
|
+
// ── agente ──────────────────────────────────────────────────────────────────────
|
|
81
|
+
const listAgents = async (ctx) => {
|
|
82
|
+
const agents = await Promise.all([...host.agents.values()].map(async (a) => {
|
|
83
|
+
const m = a.manifest;
|
|
84
|
+
const caps = await host.store.levelCaps(m.id);
|
|
85
|
+
return {
|
|
86
|
+
id: m.id,
|
|
87
|
+
name: m.name,
|
|
88
|
+
description: m.description,
|
|
89
|
+
stage: m.stage,
|
|
90
|
+
dri: m.owner.dri,
|
|
91
|
+
team: `${m.team.area}/${m.team.team}`,
|
|
92
|
+
blocked: Boolean(await host.store.killSwitch(m.id)),
|
|
93
|
+
routines: Object.entries(m.routines).map(([name, r]) => ({
|
|
94
|
+
name,
|
|
95
|
+
does: r.does,
|
|
96
|
+
level: effectiveLevel({ stage: m.stage, manifestLevel: r.level, cap: caps.get(name)?.cap ?? null }),
|
|
97
|
+
target: r.target ?? r.level,
|
|
98
|
+
capped_reason: caps.get(name)?.reason ?? '',
|
|
99
|
+
})),
|
|
100
|
+
};
|
|
101
|
+
}));
|
|
102
|
+
return applyFieldMask({ agents }, ctx.fieldMaskPaths);
|
|
103
|
+
};
|
|
104
|
+
const askAgent = async (ctx) => {
|
|
105
|
+
const { agent_id, message, thread_id } = ctx.request;
|
|
106
|
+
agentOr404(host, agent_id);
|
|
107
|
+
if (!message?.trim())
|
|
108
|
+
throw new ProviderError(grpcStatus.INVALID_ARGUMENT, 'message é obrigatório');
|
|
109
|
+
const r = await host.ask(agent_id, { email: ctx.user.email, kind: 'person' }, message, thread_id || undefined).catch(precondition);
|
|
110
|
+
// Sem o ask_id, quem perguntou não tem como buscar a resposta: vai sempre.
|
|
111
|
+
return applyFieldMask({ agent_id, ask_id: r.ask_id, status: r.status, answer: r.answer ?? '' }, ctx.fieldMaskPaths, {
|
|
112
|
+
alwaysInclude: ['agent_id', 'ask_id', 'status'],
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
const getAnswer = async (ctx) => {
|
|
116
|
+
const askId = ctx.request.ask_id?.trim();
|
|
117
|
+
if (!askId)
|
|
118
|
+
throw new ProviderError(grpcStatus.INVALID_ARGUMENT, 'ask_id é obrigatório');
|
|
119
|
+
// Pergunta de outra pessoa responde igual a uma que não existe.
|
|
120
|
+
const row = await host.answer(askId, ctx.user.email);
|
|
121
|
+
if (!row)
|
|
122
|
+
throw new ProviderError(grpcStatus.NOT_FOUND, `pergunta "${askId}" não existe`);
|
|
123
|
+
return applyFieldMask({ ask_id: row.id, agent_id: row.agent_id, status: row.status, answer: row.answer ?? '', error: row.error ?? '' }, ctx.fieldMaskPaths, { alwaysInclude: ['ask_id', 'status'] });
|
|
124
|
+
};
|
|
125
|
+
// ── acao ────────────────────────────────────────────────────────────────────────
|
|
126
|
+
const explainActions = async (ctx) => {
|
|
127
|
+
agentOr404(host, ctx.request.agent_id);
|
|
128
|
+
// As conversas ficam de fora: guardam quem perguntou o quê, e só quem perguntou lê
|
|
129
|
+
// (pelo agent_answer).
|
|
130
|
+
const rows = await host.store.history(ctx.request.agent_id, {
|
|
131
|
+
excludeRoutine: CONVERSATION_ROUTINE,
|
|
132
|
+
...(ctx.request.subject ? { subject: ctx.request.subject } : {}),
|
|
133
|
+
limit: Math.min(ctx.request.limit || limits.default, limits.max),
|
|
134
|
+
});
|
|
135
|
+
return applyFieldMask({ actions: rows.map(toAction) }, ctx.fieldMaskPaths);
|
|
136
|
+
};
|
|
137
|
+
const correctAction = async (ctx) => {
|
|
138
|
+
const id = actionId(ctx.request.action_id);
|
|
139
|
+
if (!ctx.request.note?.trim())
|
|
140
|
+
throw new ProviderError(grpcStatus.INVALID_ARGUMENT, 'note é obrigatório: diga o que estava errado e o certo');
|
|
141
|
+
const row = await host.correctAction(id, ctx.user.email, ctx.request.note).catch(precondition);
|
|
142
|
+
const level = await levelNow(host, host.agent(row.agent_id), row.routine);
|
|
143
|
+
return applyFieldMask({ action_id: String(row.id), status: row.status, routine_level: level }, ctx.fieldMaskPaths, { alwaysInclude: ['action_id'] });
|
|
144
|
+
};
|
|
145
|
+
// ── proposta ────────────────────────────────────────────────────────────────────
|
|
146
|
+
const listProposals = async (ctx) => {
|
|
147
|
+
agentOr404(host, ctx.request.agent_id);
|
|
148
|
+
return applyFieldMask({ proposals: (await host.pendingProposals(ctx.request.agent_id)).map(toAction) }, ctx.fieldMaskPaths);
|
|
149
|
+
};
|
|
150
|
+
const decideProposal = async (ctx) => {
|
|
151
|
+
const id = actionId(ctx.request.action_id);
|
|
152
|
+
const row = await host
|
|
153
|
+
.decideProposal(id, ctx.request.approve ? 'approved' : 'rejected', ctx.user.email, ctx.request.note || undefined)
|
|
154
|
+
.catch(precondition);
|
|
155
|
+
return applyFieldMask({ action_id: String(row.id), status: row.status, result_json: JSON.stringify(row.result ?? null) }, ctx.fieldMaskPaths, {
|
|
156
|
+
alwaysInclude: ['action_id'],
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
// ── controle ────────────────────────────────────────────────────────────────────
|
|
160
|
+
const setBlocked = async (ctx) => {
|
|
161
|
+
const { agent_id, blocked } = ctx.request;
|
|
162
|
+
agentOr404(host, agent_id);
|
|
163
|
+
const reason = ctx.request.reason?.trim() ?? '';
|
|
164
|
+
if (blocked) {
|
|
165
|
+
if (!reason)
|
|
166
|
+
throw new ProviderError(grpcStatus.INVALID_ARGUMENT, 'reason é obrigatório ao bloquear');
|
|
167
|
+
await host.kill(agent_id, ctx.user.email, reason);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
await host.unblock(agent_id, ctx.user.email, reason || undefined);
|
|
171
|
+
}
|
|
172
|
+
const now = Boolean(await host.store.killSwitch(agent_id));
|
|
173
|
+
return applyFieldMask({ agent_id, blocked: now }, ctx.fieldMaskPaths, { alwaysInclude: ['agent_id'] });
|
|
174
|
+
};
|
|
175
|
+
const capRoutine = async (ctx) => {
|
|
176
|
+
const { agent_id, routine } = ctx.request;
|
|
177
|
+
const a = agentOr404(host, agent_id);
|
|
178
|
+
routineOr404(a, routine);
|
|
179
|
+
const level = ctx.request.level?.trim() ?? '';
|
|
180
|
+
const reason = ctx.request.reason?.trim() ?? '';
|
|
181
|
+
if (!level) {
|
|
182
|
+
await host.restore(agent_id, routine, ctx.user.email, reason || undefined);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
if (!CAP_LEVELS.includes(level)) {
|
|
186
|
+
throw new ProviderError(grpcStatus.INVALID_ARGUMENT, `level "${level}" inválido: use ${CAP_LEVELS.join(', ')} ou vazio para restaurar`);
|
|
187
|
+
}
|
|
188
|
+
if (!reason)
|
|
189
|
+
throw new ProviderError(grpcStatus.INVALID_ARGUMENT, 'reason é obrigatório ao limitar o nível');
|
|
190
|
+
await host.demote(agent_id, routine, level, ctx.user.email, reason);
|
|
191
|
+
}
|
|
192
|
+
return applyFieldMask({ agent_id, routine, level: await levelNow(host, a, routine) }, ctx.fieldMaskPaths, {
|
|
193
|
+
alwaysInclude: ['agent_id', 'routine'],
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
ListAgents: listAgents,
|
|
198
|
+
AskAgent: askAgent,
|
|
199
|
+
GetAnswer: getAnswer,
|
|
200
|
+
ExplainActions: explainActions,
|
|
201
|
+
ListProposals: listProposals,
|
|
202
|
+
DecideProposal: decideProposal,
|
|
203
|
+
CorrectAction: correctAction,
|
|
204
|
+
SetBlocked: setBlocked,
|
|
205
|
+
CapRoutine: capRoutine,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=connector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector.js","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambiente do processo dos agentes, num lugar só e fail-fast: espelha o `loadProviderEnv()`
|
|
3
|
+
* do SDK de providers (e o reusa para o conector). Combinação inválida falha no boot, não
|
|
4
|
+
* na primeira rodada.
|
|
5
|
+
*
|
|
6
|
+
* Em produção (`NODE_ENV=production`) não há atalho: Postgres de verdade, eventos
|
|
7
|
+
* assinados, identidade própria de cada agente no Keycloak, chave do modelo e o conector
|
|
8
|
+
* com mTLS. Fora de produção, o que faltar cai no modo local (PGlite, eventos sem
|
|
9
|
+
* assinatura, sem conector, `wiring` de stub no lugar do gateway).
|
|
10
|
+
*/
|
|
11
|
+
import { type ProviderEnv } from '@t4h/mcp-provider-sdk';
|
|
12
|
+
import type { LoadedAgent } from './manifest.js';
|
|
13
|
+
export interface AgentEnv {
|
|
14
|
+
nodeEnv: string;
|
|
15
|
+
isProduction: boolean;
|
|
16
|
+
/** `postgres://…` em produção; fora dela também `pglite:<pasta>` ou ausente (em memória). */
|
|
17
|
+
databaseUrl?: string;
|
|
18
|
+
events: {
|
|
19
|
+
port: number;
|
|
20
|
+
/** Segredo HMAC por fonte. Vazio só fora de produção. */
|
|
21
|
+
secrets: Map<string, string>;
|
|
22
|
+
/** `POST /agents/:id/rounds`: fora de produção sim; em produção, nunca. */
|
|
23
|
+
allowManualRounds: boolean;
|
|
24
|
+
/** Espera entre o evento novo e a rodada que ele dispara (junta a rajada). */
|
|
25
|
+
wakeDebounceMs: number;
|
|
26
|
+
};
|
|
27
|
+
/** Ausente fora de produção sem `GATEWAY_URL`: quem sobe passa um `wiring` de stub. */
|
|
28
|
+
gateway?: {
|
|
29
|
+
url: string;
|
|
30
|
+
/** Só fora de produção: token fixo no lugar do client_credentials. */
|
|
31
|
+
devToken?: string;
|
|
32
|
+
keycloakIssuer?: string;
|
|
33
|
+
/** `AGENT_<ID>_CLIENT_SECRET` de cada agente, pelo id do agente. */
|
|
34
|
+
clientSecrets: Map<string, string>;
|
|
35
|
+
};
|
|
36
|
+
/** Ambiente do conector gRPC (`loadProviderEnv`). Ausente fora de produção sem passaporte configurado. */
|
|
37
|
+
connector?: ProviderEnv;
|
|
38
|
+
/**
|
|
39
|
+
* `PROVIDER_REQUIRE_CALL_BINDING=1`: o conector recusa passaporte sem o vínculo com a
|
|
40
|
+
* chamada (`requireCallBinding` do SDK de providers). Desligado por padrão, como no SDK.
|
|
41
|
+
*/
|
|
42
|
+
requireCallBinding: boolean;
|
|
43
|
+
/** Quanto `agent_ask` espera a resposta antes de devolver `running`. */
|
|
44
|
+
askWaitMs: number;
|
|
45
|
+
debug: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** Padrão do gateway para cortar a chamada ao provider (`PROVIDER_CALL_TIMEOUT_MS`). */
|
|
48
|
+
export declare const GATEWAY_CALL_TIMEOUT_MS = 30000;
|
|
49
|
+
export declare const DEFAULT_WAKE_DEBOUNCE_MS = 10000;
|
|
50
|
+
/** `AGENT_<ID>_CLIENT_SECRET`: hífen vira `_`, tudo em maiúsculas. */
|
|
51
|
+
export declare function agentSecretVar(agentId: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* Lê e valida o ambiente para estes agentes. Junta todos os problemas numa mensagem só
|
|
54
|
+
* (quem sobe o processo corrige tudo de uma vez) e lança.
|
|
55
|
+
*/
|
|
56
|
+
export declare function loadAgentEnv(agents: LoadedAgent[], env?: NodeJS.ProcessEnv): AgentEnv;
|