mitra-interactions-sdk 1.0.60-beta.42 → 1.0.60-beta.43
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 +472 -461
- package/dist/index.d.mts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +24 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +24 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,461 +1,472 @@
|
|
|
1
|
-
# Mitra Interactions SDK
|
|
2
|
-
|
|
3
|
-
SDK para interações com a plataforma Mitra via endpoints `/interactions/`.
|
|
4
|
-
|
|
5
|
-
## Permissões: `dev` vs `business`
|
|
6
|
-
|
|
7
|
-
`userType` no token de login:
|
|
8
|
-
- `dev` — chama tudo
|
|
9
|
-
- `business` — chama apenas execução (SF), auth SSO e integrações. Outras chamadas retornam **403**.
|
|
10
|
-
|
|
11
|
-
> Não confundir com o pacote `mitra-business-sdk` (SDK separado, usado pelo agente IA).
|
|
12
|
-
|
|
13
|
-
**Bloqueado para `business`:** CRUD REST (`*RecordMitra`).
|
|
14
|
-
|
|
15
|
-
> SF tipo JAVASCRIPT herda o `userType` do caller — se chamar funções bloqueadas, retorna 403 para business.
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Instalação
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
npm install mitra-interactions-sdk
|
|
23
|
-
# ou
|
|
24
|
-
yarn add mitra-interactions-sdk
|
|
25
|
-
# ou
|
|
26
|
-
pnpm add mitra-interactions-sdk
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Configuração
|
|
30
|
-
|
|
31
|
-
Antes de usar qualquer função, configure o SDK. O `token` é **opcional** — Server Functions públicas podem ser chamadas sem autenticação.
|
|
32
|
-
|
|
33
|
-
> **Importante:** Quando usado, o token é um JWT de autenticação da plataforma Mitra. **Nunca deixe o token estático no código.** Utilize variáveis de ambiente para armazená-lo de forma segura.
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import { configureSdkMitra } from 'mitra-interactions-sdk';
|
|
37
|
-
|
|
38
|
-
// Configuração completa (com autenticação)
|
|
39
|
-
const instance = configureSdkMitra({
|
|
40
|
-
baseURL: process.env.MITRA_BASE_URL || 'https://api.mitra.com',
|
|
41
|
-
token: process.env.MITRA_TOKEN!, // Opcional — necessário apenas para endpoints autenticados
|
|
42
|
-
authUrl: 'https://coder.mitralab.io/sdk-auth/', // Opcional — necessário para login e token refresh
|
|
43
|
-
projectId: 123, // Opcional — se informado, torna projectId opcional em TODOS os métodos
|
|
44
|
-
integrationURL: 'https://api0.mitraecp.com:1003', // Opcional — necessário para integrações
|
|
45
|
-
onTokenRefresh: (session) => { // Opcional — chamado quando o token é renovado automaticamente
|
|
46
|
-
localStorage.setItem('mitra_session', JSON.stringify(session));
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Configuração mínima (sem token — apenas para Server Functions públicas)
|
|
51
|
-
const instance = configureSdkMitra({
|
|
52
|
-
baseURL: 'https://api.mitra.com',
|
|
53
|
-
projectId: 123
|
|
54
|
-
});
|
|
55
|
-
await instance.executeServerFunction({ serverFunctionId: 42 }); // OK — sem token
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
> **`projectId` global:** Se você passar `projectId` no `configureSdkMitra`, ele será usado como fallback em **todos** os métodos do SDK. Assim, não é necessário passar `projectId` em cada chamada individual — basta configurar uma vez.
|
|
59
|
-
|
|
60
|
-
`configureSdkMitra` retorna uma `MitraInstance` que também pode ser usada diretamente:
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
await instance.executeServerFunction({ serverFunctionId: 42 }); // projectId já vem do configureSdkMitra
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## Autenticação (Login)
|
|
67
|
-
|
|
68
|
-
Login via popup ou redirect seguro hospedado no domínio Mitra. Credenciais nunca passam pelo código do desenvolvedor. O SDK é **auto-configurado** após o login.
|
|
69
|
-
|
|
70
|
-
> **Nota:** `authUrl` e `projectId` são **obrigatórios** para login. Porém, se já foram passados no `configureSdkMitra()`, não é necessário repeti-los — o SDK usa os valores configurados como fallback.
|
|
71
|
-
|
|
72
|
-
### Login via Popup (padrão)
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
import { loginWithGoogleMitra, loginWithMicrosoftMitra } from 'mitra-interactions-sdk';
|
|
76
|
-
|
|
77
|
-
// Primeira vez — sem configureSdkMitra: authUrl e projectId são obrigatórios
|
|
78
|
-
const result = await loginWithGoogleMitra({
|
|
79
|
-
authUrl: 'https://stg.mitralab.io/legacy',
|
|
80
|
-
projectId: 'uuid-do-projeto'
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Se já chamou configureSdkMitra({ authUrl, projectId }), basta:
|
|
84
|
-
const result = await loginWithGoogleMitra();
|
|
85
|
-
const result = await loginWithMicrosoftMitra();
|
|
86
|
-
|
|
87
|
-
// result: { token, baseURL, refreshToken }
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
`create` separa a intenção do SSO sem quebrar integrações existentes:
|
|
91
|
-
|
|
92
|
-
| Valor | Comportamento |
|
|
93
|
-
| --- | --- |
|
|
94
|
-
| omitido | Fluxo combinado compatível: autentica e cria o vínculo quando o app permite |
|
|
95
|
-
| `false` | Login estrito: exige acesso efetivo existente e nunca cria o vínculo |
|
|
96
|
-
| `true` | Signup explícito: cria o vínculo quando o app permite |
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
await loginWithGoogleMitra({ create: false }); // Entrar
|
|
100
|
-
await loginWithGoogleMitra({ create: true }); // Criar conta
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
O login estrito pode retornar `APP_ACCESS_REQUIRED` quando não existe acesso ou
|
|
104
|
-
`APP_ACCESS_REVOKED` quando o vínculo foi desligado. Signup bloqueado retorna
|
|
105
|
-
`SIGNUP_NOT_ALLOWED`. O mesmo campo é preservado no modo redirect.
|
|
106
|
-
|
|
107
|
-
### Login via Redirect (mobile)
|
|
108
|
-
|
|
109
|
-
No celular o popup vira aba — use `mode: 'redirect'`: a página de auth navega de volta pro app com `#codeMitra`/`#stateMitra` no fragment, e o app conclui com `exchangeSsoCodeMitra`.
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
import { loginWithGoogleMitra, exchangeSsoCodeMitra } from 'mitra-interactions-sdk';
|
|
113
|
-
|
|
114
|
-
// 1. Iniciar login — o navegador navega para fora da página
|
|
115
|
-
await loginWithGoogleMitra({ mode: 'redirect' });
|
|
116
|
-
|
|
117
|
-
// 2. No boot do app, se houver #codeMitra/#stateMitra no fragment:
|
|
118
|
-
const session = await exchangeSsoCodeMitra({ code, state });
|
|
119
|
-
// A SDK valida o nonce (anti-CSRF), troca o code no BFF e configura o SDK.
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### Token Refresh Automático
|
|
123
|
-
|
|
124
|
-
Quando qualquer requisição retorna **403**, o SDK tenta renovar o token automaticamente via iframe invisível (usa o cookie de sessão do provider). Se o refresh funcionar, a requisição é retentada com o novo token — transparente para o desenvolvedor.
|
|
125
|
-
|
|
126
|
-
O callback `onTokenRefresh` é chamado após renovação bem-sucedida:
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
configureSdkMitra({
|
|
130
|
-
baseURL: '...',
|
|
131
|
-
token: '...',
|
|
132
|
-
authUrl: 'https://coder.mitralab.io/sdk-auth/',
|
|
133
|
-
projectId: 123,
|
|
134
|
-
onTokenRefresh: (session) => {
|
|
135
|
-
// Atualiza o token salvo (ex: localStorage, store, etc.)
|
|
136
|
-
localStorage.setItem('mitra_token', session.token);
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## Métodos Disponíveis
|
|
142
|
-
|
|
143
|
-
### executeServerFunctionMitra
|
|
144
|
-
|
|
145
|
-
Executa uma Server Function de forma **síncrona** (timeout de 60s no backend). Retorna o resultado diretamente.
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
import { executeServerFunctionMitra } from 'mitra-interactions-sdk';
|
|
149
|
-
|
|
150
|
-
const result = await executeServerFunctionMitra({
|
|
151
|
-
projectId: 123,
|
|
152
|
-
serverFunctionId: 101,
|
|
153
|
-
input: { // Opcional - objeto de entrada para a função
|
|
154
|
-
arg1: 'valor1'
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
// result: { status, result: { executionId, executionStatus, output, logs, error, durationMs } }
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### executeServerFunctionAsyncMitra
|
|
161
|
-
|
|
162
|
-
Executa uma Server Function de forma **assíncrona**. Retorna um `executionId` imediatamente. Use `stopServerFunctionExecutionMitra` para parar ou `getServerFunctionExecutionMitra` (mitra-sdk) para consultar o resultado.
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
import { executeServerFunctionAsyncMitra } from 'mitra-interactions-sdk';
|
|
166
|
-
|
|
167
|
-
const result = await executeServerFunctionAsyncMitra({
|
|
168
|
-
projectId: 123,
|
|
169
|
-
serverFunctionId: 101,
|
|
170
|
-
input: { // Opcional - objeto de entrada para a função
|
|
171
|
-
arg1: 'valor1'
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
// result: { status, result: { executionId, executionStatus } }
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### stopServerFunctionExecutionMitra
|
|
178
|
-
|
|
179
|
-
Para a execução de uma Server Function em andamento.
|
|
180
|
-
|
|
181
|
-
```typescript
|
|
182
|
-
import { stopServerFunctionExecutionMitra } from 'mitra-interactions-sdk';
|
|
183
|
-
|
|
184
|
-
const result = await stopServerFunctionExecutionMitra({
|
|
185
|
-
projectId: 123,
|
|
186
|
-
executionId: 'exec-uuid-aqui'
|
|
187
|
-
});
|
|
188
|
-
// result: { status, result: { executionId, executionStatus: "CANCELLED" | "ALREADY_FINISHED" } }
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Server Functions Públicas (sem autenticação)
|
|
192
|
-
|
|
193
|
-
A SF deve ter `publicExecution = true` (via `togglePublicExecutionMitra` do mitra-sdk). Não exigem token.
|
|
194
|
-
|
|
195
|
-
```typescript
|
|
196
|
-
import {
|
|
197
|
-
executePublicServerFunctionMitra,
|
|
198
|
-
executePublicServerFunctionAsyncMitra,
|
|
199
|
-
getPublicServerFunctionExecutionMitra
|
|
200
|
-
} from 'mitra-interactions-sdk';
|
|
201
|
-
|
|
202
|
-
// Síncrona (timeout 5min)
|
|
203
|
-
const res = await executePublicServerFunctionMitra({ projectId, serverFunctionId, input: { x: 1 } });
|
|
204
|
-
// { executionId, status, output, logs, error, durationMs }
|
|
205
|
-
|
|
206
|
-
// Assíncrona + polling
|
|
207
|
-
const async1 = await executePublicServerFunctionAsyncMitra({ projectId, serverFunctionId });
|
|
208
|
-
const status = await getPublicServerFunctionExecutionMitra({ projectId, executionId: async1.executionId });
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### Dynamic Schema CRUD
|
|
212
|
-
|
|
213
|
-
> 🔒 `userType=dev` only. Falha 403 para business. Em telas com business, envelopar em SF tipo SQL.
|
|
214
|
-
|
|
215
|
-
CRUD completo em tabelas do projeto via Dynamic Schema (usa header `X-TenantID`).
|
|
216
|
-
|
|
217
|
-
Todos os endpoints suportam o parâmetro opcional `jdbcConnectionConfigId` para operar em datasources adicionais (PostgreSQL, Oracle, SQL Server, etc.) ao invés do banco principal do tenant.
|
|
218
|
-
|
|
219
|
-
- `listRecordsMitra(...)` → `ListRecordsResponse` `{ content, page, size, totalElements, totalPages }` - Lista registros com paginação
|
|
220
|
-
- `getRecordMitra(...)` → `Record<string, any>` - Busca registro por ID
|
|
221
|
-
- `createRecordMitra(...)` → `Record<string, any>` - Cria registro (201)
|
|
222
|
-
- `updateRecordMitra(...)` → `Record<string, any>` - Atualiza registro (PUT)
|
|
223
|
-
- `patchRecordMitra(...)` → `Record<string, any>` - Atualiza parcialmente (PATCH)
|
|
224
|
-
- `deleteRecordMitra(...)` → `void` - Remove registro (204 No Content)
|
|
225
|
-
- `createRecordsBatchMitra(...)` → `Record<string, any>[]` - Cria múltiplos registros (201)
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
import { listRecordsMitra, createRecordMitra, updateRecordMitra, deleteRecordMitra } from 'mitra-interactions-sdk';
|
|
229
|
-
|
|
230
|
-
// Listar registros
|
|
231
|
-
const result = await listRecordsMitra({
|
|
232
|
-
projectId: 123,
|
|
233
|
-
tableName: 'produtos',
|
|
234
|
-
page: 0,
|
|
235
|
-
size: 20
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// Criar registro
|
|
239
|
-
await createRecordMitra({
|
|
240
|
-
projectId: 123,
|
|
241
|
-
tableName: 'produtos',
|
|
242
|
-
data: { nome: 'Produto A', preco: 99.90 }
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
// Atualizar registro
|
|
246
|
-
await updateRecordMitra({
|
|
247
|
-
projectId: 123,
|
|
248
|
-
tableName: 'produtos',
|
|
249
|
-
id: 1,
|
|
250
|
-
data: { nome: 'Produto A Atualizado', preco: 89.90, version: 0 }
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// Deletar registro
|
|
254
|
-
await deleteRecordMitra({ projectId: 123, tableName: 'produtos', id: 1 });
|
|
255
|
-
|
|
256
|
-
// Usando datasource adicional (jdbcConnectionConfigId)
|
|
257
|
-
const result2 = await listRecordsMitra({
|
|
258
|
-
projectId: 123,
|
|
259
|
-
tableName: 'clientes',
|
|
260
|
-
jdbcConnectionConfigId: 5
|
|
261
|
-
});
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
## Agent Chat (copilot)
|
|
265
|
-
|
|
266
|
-
Chat com o agente de IA embarcado. **REST-first, tudo pela BFF no `baseURL` normal** (`/agentAiShortcut/*` — herda `fetchWithRefresh` e CORS): chats (`createChat`/`listChats`/`readChat`/`renameChat`/`deleteChat`), histórico (`listChatMessages`), credenciais e modelos. `projectId` obrigatório em todas (opcional na chamada se veio do `configureSdkMitra`). **Só o prompt é streaming** — um WebSocket por task em `wss://{origin}/copilot/ws/tasks/{taskId}?token=JWT`, aberto pela SDK quando a conversa começa (WS não passa por preflight de CORS).
|
|
267
|
-
|
|
268
|
-
Precisa de `token` e `baseURL` configurados (o login já deixa pronto). O transporte do prompt aceita `transport: 'ws' | 'http'` — `'ws'` é o default; `'http'` é **funcional**: `POST /copilot/api/v1/tasks/{id}/inputs` + SSE em `/events` via fetch, com a MESMA paridade de eventos do WS (pra ambientes onde WebSocket não rola, ex.: serverless).
|
|
269
|
-
|
|
270
|
-
### Gerenciar os chats — `manageAgentChatMitra`
|
|
271
|
-
|
|
272
|
-
Tudo HTTP: listar (com filtros), renomear e deletar (= arquivar).
|
|
273
|
-
|
|
274
|
-
```typescript
|
|
275
|
-
import { manageAgentChatMitra } from 'mitra-interactions-sdk';
|
|
276
|
-
|
|
277
|
-
const chats = await manageAgentChatMitra({ action: 'list' }); // AgentChat[]
|
|
278
|
-
const doAgente = await manageAgentChatMitra({ action: 'list', agentId: 'uuid-do-agente' }); // só os chats de um agente business
|
|
279
|
-
const busca = await manageAgentChatMitra({ action: 'list', search: 'vendas', page: 0, size: 20 });
|
|
280
|
-
const renamed = await manageAgentChatMitra({ action: 'rename', taskId, name: 'Novo nome' });
|
|
281
|
-
const deleted = await manageAgentChatMitra({ action: 'delete', taskId }); // arquiva (some da lista default)
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
- `action: 'list'` → `AgentChat[]` — `{ id, name, agentType, agentId, archived, createdAt, updatedAt }`. Filtros: `agentId?`, `archived?`, `search?`, `page?`, `size?`.
|
|
285
|
-
- `action: 'rename'` → `{ taskId, name }` (POST `/agentAiShortcut/renameChat`)
|
|
286
|
-
- `action: 'delete'` → `{ taskId, deleted }` (POST `/agentAiShortcut/deleteChat` — arquiva, o histórico não é destruído)
|
|
287
|
-
|
|
288
|
-
### Abrir uma session — `getAgentTaskMitra`
|
|
289
|
-
|
|
290
|
-
Retorna uma `AgentTaskSession` que encapsula o ciclo de vida do chat. A task é criada via BFF (`POST /agentAiShortcut/createChat`) no primeiro `send()`; o WS da task conecta em seguida. Abrir a mesma `taskId` duas vezes devolve a **mesma** instância (cache).
|
|
291
|
-
|
|
292
|
-
```typescript
|
|
293
|
-
import { getAgentTaskMitra } from 'mitra-interactions-sdk';
|
|
294
|
-
|
|
295
|
-
// Chat novo — SEMPRE com agentId (sessão sem agente não executa nada).
|
|
296
|
-
// taskId é preenchido no primeiro send() (evento taskCreated)
|
|
297
|
-
const session = getAgentTaskMitra({ create: true, agentId: 'uuid-do-agente', agentType: 'ANTHROPIC_CLAUDE_OPUS', name: 'Meu chat' });
|
|
298
|
-
|
|
299
|
-
// Chat existente
|
|
300
|
-
const existing = getAgentTaskMitra({ taskId: 'uuid-da-task' });
|
|
301
|
-
await existing.loadHistory({ limit: 50 });
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
`getAgentTaskMitra({ create: true, agentType?, name?, agentId?, reasoningEffort?, transport? })` ou `getAgentTaskMitra({ taskId, transport? })`.
|
|
305
|
-
|
|
306
|
-
**Agente autônomo**: a autonomia é **propriedade do AGENTE** (`autonomous` em `createAgentMitra`/`updateAgentMitra`, no `mitra-sdk`) — não existe flag na criação do chat. Ao criar um chat contra um agente autônomo (`getAgentTaskMitra({ create: true, agentId })`), o copilot deriva a autonomia do agente e o chat já nasce **sem dono** (`user_id NULL` — a dona é o agente), usando a connection anexada ao agente como credencial. Exige auth `AGENT_WRITE` (chave de SF ou token de app EDIT) — usuário business comum não abre chat autônomo. Depois de criado, dirigir/listar é igual ao chat normal (`getAgentTaskMitra({ taskId })`, `send`, `manageAgentChatMitra({ list, agentId })`).
|
|
307
|
-
|
|
308
|
-
- `agentType` vem de `manageAgentCredentialMitra({ action: 'list_models' })` — ex.: `'ANTHROPIC_CLAUDE_OPUS'`, `'OPENAI_GPT5'`. Default: `'ANTHROPIC_CLAUDE_OPUS'`.
|
|
309
|
-
- **`agentId`**: id de um agente business (CRUD via `mitra-sdk`: `listAgentsMitra` e família). A sessão sobe com o system prompt do agente e um token escopado — as tools enxergam só as Server Functions dele. **Sem `agentId`: sessão business sem agente** — sem system prompt e sem acesso às Server Functions (as tools recusam); não há adoção automática de agente único. Na prática, sempre passe `agentId`.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
session
|
|
343
|
-
|
|
344
|
-
session.on
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
//
|
|
372
|
-
|
|
373
|
-
//
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
//
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
const {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
```typescript
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
//
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
1
|
+
# Mitra Interactions SDK
|
|
2
|
+
|
|
3
|
+
SDK para interações com a plataforma Mitra via endpoints `/interactions/`.
|
|
4
|
+
|
|
5
|
+
## Permissões: `dev` vs `business`
|
|
6
|
+
|
|
7
|
+
`userType` no token de login:
|
|
8
|
+
- `dev` — chama tudo
|
|
9
|
+
- `business` — chama apenas execução (SF), auth SSO e integrações. Outras chamadas retornam **403**.
|
|
10
|
+
|
|
11
|
+
> Não confundir com o pacote `mitra-business-sdk` (SDK separado, usado pelo agente IA).
|
|
12
|
+
|
|
13
|
+
**Bloqueado para `business`:** CRUD REST (`*RecordMitra`).
|
|
14
|
+
|
|
15
|
+
> SF tipo JAVASCRIPT herda o `userType` do caller — se chamar funções bloqueadas, retorna 403 para business.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Instalação
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install mitra-interactions-sdk
|
|
23
|
+
# ou
|
|
24
|
+
yarn add mitra-interactions-sdk
|
|
25
|
+
# ou
|
|
26
|
+
pnpm add mitra-interactions-sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Configuração
|
|
30
|
+
|
|
31
|
+
Antes de usar qualquer função, configure o SDK. O `token` é **opcional** — Server Functions públicas podem ser chamadas sem autenticação.
|
|
32
|
+
|
|
33
|
+
> **Importante:** Quando usado, o token é um JWT de autenticação da plataforma Mitra. **Nunca deixe o token estático no código.** Utilize variáveis de ambiente para armazená-lo de forma segura.
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { configureSdkMitra } from 'mitra-interactions-sdk';
|
|
37
|
+
|
|
38
|
+
// Configuração completa (com autenticação)
|
|
39
|
+
const instance = configureSdkMitra({
|
|
40
|
+
baseURL: process.env.MITRA_BASE_URL || 'https://api.mitra.com',
|
|
41
|
+
token: process.env.MITRA_TOKEN!, // Opcional — necessário apenas para endpoints autenticados
|
|
42
|
+
authUrl: 'https://coder.mitralab.io/sdk-auth/', // Opcional — necessário para login e token refresh
|
|
43
|
+
projectId: 123, // Opcional — se informado, torna projectId opcional em TODOS os métodos
|
|
44
|
+
integrationURL: 'https://api0.mitraecp.com:1003', // Opcional — necessário para integrações
|
|
45
|
+
onTokenRefresh: (session) => { // Opcional — chamado quando o token é renovado automaticamente
|
|
46
|
+
localStorage.setItem('mitra_session', JSON.stringify(session));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Configuração mínima (sem token — apenas para Server Functions públicas)
|
|
51
|
+
const instance = configureSdkMitra({
|
|
52
|
+
baseURL: 'https://api.mitra.com',
|
|
53
|
+
projectId: 123
|
|
54
|
+
});
|
|
55
|
+
await instance.executeServerFunction({ serverFunctionId: 42 }); // OK — sem token
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
> **`projectId` global:** Se você passar `projectId` no `configureSdkMitra`, ele será usado como fallback em **todos** os métodos do SDK. Assim, não é necessário passar `projectId` em cada chamada individual — basta configurar uma vez.
|
|
59
|
+
|
|
60
|
+
`configureSdkMitra` retorna uma `MitraInstance` que também pode ser usada diretamente:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
await instance.executeServerFunction({ serverFunctionId: 42 }); // projectId já vem do configureSdkMitra
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Autenticação (Login)
|
|
67
|
+
|
|
68
|
+
Login via popup ou redirect seguro hospedado no domínio Mitra. Credenciais nunca passam pelo código do desenvolvedor. O SDK é **auto-configurado** após o login.
|
|
69
|
+
|
|
70
|
+
> **Nota:** `authUrl` e `projectId` são **obrigatórios** para login. Porém, se já foram passados no `configureSdkMitra()`, não é necessário repeti-los — o SDK usa os valores configurados como fallback.
|
|
71
|
+
|
|
72
|
+
### Login via Popup (padrão)
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { loginWithGoogleMitra, loginWithMicrosoftMitra } from 'mitra-interactions-sdk';
|
|
76
|
+
|
|
77
|
+
// Primeira vez — sem configureSdkMitra: authUrl e projectId são obrigatórios
|
|
78
|
+
const result = await loginWithGoogleMitra({
|
|
79
|
+
authUrl: 'https://stg.mitralab.io/legacy',
|
|
80
|
+
projectId: 'uuid-do-projeto'
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Se já chamou configureSdkMitra({ authUrl, projectId }), basta:
|
|
84
|
+
const result = await loginWithGoogleMitra();
|
|
85
|
+
const result = await loginWithMicrosoftMitra();
|
|
86
|
+
|
|
87
|
+
// result: { token, baseURL, refreshToken }
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`create` separa a intenção do SSO sem quebrar integrações existentes:
|
|
91
|
+
|
|
92
|
+
| Valor | Comportamento |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| omitido | Fluxo combinado compatível: autentica e cria o vínculo quando o app permite |
|
|
95
|
+
| `false` | Login estrito: exige acesso efetivo existente e nunca cria o vínculo |
|
|
96
|
+
| `true` | Signup explícito: cria o vínculo quando o app permite |
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
await loginWithGoogleMitra({ create: false }); // Entrar
|
|
100
|
+
await loginWithGoogleMitra({ create: true }); // Criar conta
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
O login estrito pode retornar `APP_ACCESS_REQUIRED` quando não existe acesso ou
|
|
104
|
+
`APP_ACCESS_REVOKED` quando o vínculo foi desligado. Signup bloqueado retorna
|
|
105
|
+
`SIGNUP_NOT_ALLOWED`. O mesmo campo é preservado no modo redirect.
|
|
106
|
+
|
|
107
|
+
### Login via Redirect (mobile)
|
|
108
|
+
|
|
109
|
+
No celular o popup vira aba — use `mode: 'redirect'`: a página de auth navega de volta pro app com `#codeMitra`/`#stateMitra` no fragment, e o app conclui com `exchangeSsoCodeMitra`.
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { loginWithGoogleMitra, exchangeSsoCodeMitra } from 'mitra-interactions-sdk';
|
|
113
|
+
|
|
114
|
+
// 1. Iniciar login — o navegador navega para fora da página
|
|
115
|
+
await loginWithGoogleMitra({ mode: 'redirect' });
|
|
116
|
+
|
|
117
|
+
// 2. No boot do app, se houver #codeMitra/#stateMitra no fragment:
|
|
118
|
+
const session = await exchangeSsoCodeMitra({ code, state });
|
|
119
|
+
// A SDK valida o nonce (anti-CSRF), troca o code no BFF e configura o SDK.
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Token Refresh Automático
|
|
123
|
+
|
|
124
|
+
Quando qualquer requisição retorna **403**, o SDK tenta renovar o token automaticamente via iframe invisível (usa o cookie de sessão do provider). Se o refresh funcionar, a requisição é retentada com o novo token — transparente para o desenvolvedor.
|
|
125
|
+
|
|
126
|
+
O callback `onTokenRefresh` é chamado após renovação bem-sucedida:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
configureSdkMitra({
|
|
130
|
+
baseURL: '...',
|
|
131
|
+
token: '...',
|
|
132
|
+
authUrl: 'https://coder.mitralab.io/sdk-auth/',
|
|
133
|
+
projectId: 123,
|
|
134
|
+
onTokenRefresh: (session) => {
|
|
135
|
+
// Atualiza o token salvo (ex: localStorage, store, etc.)
|
|
136
|
+
localStorage.setItem('mitra_token', session.token);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Métodos Disponíveis
|
|
142
|
+
|
|
143
|
+
### executeServerFunctionMitra
|
|
144
|
+
|
|
145
|
+
Executa uma Server Function de forma **síncrona** (timeout de 60s no backend). Retorna o resultado diretamente.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import { executeServerFunctionMitra } from 'mitra-interactions-sdk';
|
|
149
|
+
|
|
150
|
+
const result = await executeServerFunctionMitra({
|
|
151
|
+
projectId: 123,
|
|
152
|
+
serverFunctionId: 101,
|
|
153
|
+
input: { // Opcional - objeto de entrada para a função
|
|
154
|
+
arg1: 'valor1'
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// result: { status, result: { executionId, executionStatus, output, logs, error, durationMs } }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### executeServerFunctionAsyncMitra
|
|
161
|
+
|
|
162
|
+
Executa uma Server Function de forma **assíncrona**. Retorna um `executionId` imediatamente. Use `stopServerFunctionExecutionMitra` para parar ou `getServerFunctionExecutionMitra` (mitra-sdk) para consultar o resultado.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { executeServerFunctionAsyncMitra } from 'mitra-interactions-sdk';
|
|
166
|
+
|
|
167
|
+
const result = await executeServerFunctionAsyncMitra({
|
|
168
|
+
projectId: 123,
|
|
169
|
+
serverFunctionId: 101,
|
|
170
|
+
input: { // Opcional - objeto de entrada para a função
|
|
171
|
+
arg1: 'valor1'
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
// result: { status, result: { executionId, executionStatus } }
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### stopServerFunctionExecutionMitra
|
|
178
|
+
|
|
179
|
+
Para a execução de uma Server Function em andamento.
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import { stopServerFunctionExecutionMitra } from 'mitra-interactions-sdk';
|
|
183
|
+
|
|
184
|
+
const result = await stopServerFunctionExecutionMitra({
|
|
185
|
+
projectId: 123,
|
|
186
|
+
executionId: 'exec-uuid-aqui'
|
|
187
|
+
});
|
|
188
|
+
// result: { status, result: { executionId, executionStatus: "CANCELLED" | "ALREADY_FINISHED" } }
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Server Functions Públicas (sem autenticação)
|
|
192
|
+
|
|
193
|
+
A SF deve ter `publicExecution = true` (via `togglePublicExecutionMitra` do mitra-sdk). Não exigem token.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import {
|
|
197
|
+
executePublicServerFunctionMitra,
|
|
198
|
+
executePublicServerFunctionAsyncMitra,
|
|
199
|
+
getPublicServerFunctionExecutionMitra
|
|
200
|
+
} from 'mitra-interactions-sdk';
|
|
201
|
+
|
|
202
|
+
// Síncrona (timeout 5min)
|
|
203
|
+
const res = await executePublicServerFunctionMitra({ projectId, serverFunctionId, input: { x: 1 } });
|
|
204
|
+
// { executionId, status, output, logs, error, durationMs }
|
|
205
|
+
|
|
206
|
+
// Assíncrona + polling
|
|
207
|
+
const async1 = await executePublicServerFunctionAsyncMitra({ projectId, serverFunctionId });
|
|
208
|
+
const status = await getPublicServerFunctionExecutionMitra({ projectId, executionId: async1.executionId });
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Dynamic Schema CRUD
|
|
212
|
+
|
|
213
|
+
> 🔒 `userType=dev` only. Falha 403 para business. Em telas com business, envelopar em SF tipo SQL.
|
|
214
|
+
|
|
215
|
+
CRUD completo em tabelas do projeto via Dynamic Schema (usa header `X-TenantID`).
|
|
216
|
+
|
|
217
|
+
Todos os endpoints suportam o parâmetro opcional `jdbcConnectionConfigId` para operar em datasources adicionais (PostgreSQL, Oracle, SQL Server, etc.) ao invés do banco principal do tenant.
|
|
218
|
+
|
|
219
|
+
- `listRecordsMitra(...)` → `ListRecordsResponse` `{ content, page, size, totalElements, totalPages }` - Lista registros com paginação
|
|
220
|
+
- `getRecordMitra(...)` → `Record<string, any>` - Busca registro por ID
|
|
221
|
+
- `createRecordMitra(...)` → `Record<string, any>` - Cria registro (201)
|
|
222
|
+
- `updateRecordMitra(...)` → `Record<string, any>` - Atualiza registro (PUT)
|
|
223
|
+
- `patchRecordMitra(...)` → `Record<string, any>` - Atualiza parcialmente (PATCH)
|
|
224
|
+
- `deleteRecordMitra(...)` → `void` - Remove registro (204 No Content)
|
|
225
|
+
- `createRecordsBatchMitra(...)` → `Record<string, any>[]` - Cria múltiplos registros (201)
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { listRecordsMitra, createRecordMitra, updateRecordMitra, deleteRecordMitra } from 'mitra-interactions-sdk';
|
|
229
|
+
|
|
230
|
+
// Listar registros
|
|
231
|
+
const result = await listRecordsMitra({
|
|
232
|
+
projectId: 123,
|
|
233
|
+
tableName: 'produtos',
|
|
234
|
+
page: 0,
|
|
235
|
+
size: 20
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Criar registro
|
|
239
|
+
await createRecordMitra({
|
|
240
|
+
projectId: 123,
|
|
241
|
+
tableName: 'produtos',
|
|
242
|
+
data: { nome: 'Produto A', preco: 99.90 }
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Atualizar registro
|
|
246
|
+
await updateRecordMitra({
|
|
247
|
+
projectId: 123,
|
|
248
|
+
tableName: 'produtos',
|
|
249
|
+
id: 1,
|
|
250
|
+
data: { nome: 'Produto A Atualizado', preco: 89.90, version: 0 }
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Deletar registro
|
|
254
|
+
await deleteRecordMitra({ projectId: 123, tableName: 'produtos', id: 1 });
|
|
255
|
+
|
|
256
|
+
// Usando datasource adicional (jdbcConnectionConfigId)
|
|
257
|
+
const result2 = await listRecordsMitra({
|
|
258
|
+
projectId: 123,
|
|
259
|
+
tableName: 'clientes',
|
|
260
|
+
jdbcConnectionConfigId: 5
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Agent Chat (copilot)
|
|
265
|
+
|
|
266
|
+
Chat com o agente de IA embarcado. **REST-first, tudo pela BFF no `baseURL` normal** (`/agentAiShortcut/*` — herda `fetchWithRefresh` e CORS): chats (`createChat`/`listChats`/`readChat`/`renameChat`/`deleteChat`), histórico (`listChatMessages`), credenciais e modelos. `projectId` obrigatório em todas (opcional na chamada se veio do `configureSdkMitra`). **Só o prompt é streaming** — um WebSocket por task em `wss://{origin}/copilot/ws/tasks/{taskId}?token=JWT`, aberto pela SDK quando a conversa começa (WS não passa por preflight de CORS).
|
|
267
|
+
|
|
268
|
+
Precisa de `token` e `baseURL` configurados (o login já deixa pronto). O transporte do prompt aceita `transport: 'ws' | 'http'` — `'ws'` é o default; `'http'` é **funcional**: `POST /copilot/api/v1/tasks/{id}/inputs` + SSE em `/events` via fetch, com a MESMA paridade de eventos do WS (pra ambientes onde WebSocket não rola, ex.: serverless).
|
|
269
|
+
|
|
270
|
+
### Gerenciar os chats — `manageAgentChatMitra`
|
|
271
|
+
|
|
272
|
+
Tudo HTTP: listar (com filtros), renomear e deletar (= arquivar).
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
import { manageAgentChatMitra } from 'mitra-interactions-sdk';
|
|
276
|
+
|
|
277
|
+
const chats = await manageAgentChatMitra({ action: 'list' }); // AgentChat[]
|
|
278
|
+
const doAgente = await manageAgentChatMitra({ action: 'list', agentId: 'uuid-do-agente' }); // só os chats de um agente business
|
|
279
|
+
const busca = await manageAgentChatMitra({ action: 'list', search: 'vendas', page: 0, size: 20 });
|
|
280
|
+
const renamed = await manageAgentChatMitra({ action: 'rename', taskId, name: 'Novo nome' });
|
|
281
|
+
const deleted = await manageAgentChatMitra({ action: 'delete', taskId }); // arquiva (some da lista default)
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
- `action: 'list'` → `AgentChat[]` — `{ id, name, agentType, agentId, archived, createdAt, updatedAt }`. Filtros: `agentId?`, `archived?`, `search?`, `page?`, `size?`.
|
|
285
|
+
- `action: 'rename'` → `{ taskId, name }` (POST `/agentAiShortcut/renameChat`)
|
|
286
|
+
- `action: 'delete'` → `{ taskId, deleted }` (POST `/agentAiShortcut/deleteChat` — arquiva, o histórico não é destruído)
|
|
287
|
+
|
|
288
|
+
### Abrir uma session — `getAgentTaskMitra`
|
|
289
|
+
|
|
290
|
+
Retorna uma `AgentTaskSession` que encapsula o ciclo de vida do chat. A task é criada via BFF (`POST /agentAiShortcut/createChat`) no primeiro `send()`; o WS da task conecta em seguida. Abrir a mesma `taskId` duas vezes devolve a **mesma** instância (cache).
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
import { getAgentTaskMitra } from 'mitra-interactions-sdk';
|
|
294
|
+
|
|
295
|
+
// Chat novo — SEMPRE com agentId (sessão sem agente não executa nada).
|
|
296
|
+
// taskId é preenchido no primeiro send() (evento taskCreated)
|
|
297
|
+
const session = getAgentTaskMitra({ create: true, agentId: 'uuid-do-agente', agentType: 'ANTHROPIC_CLAUDE_OPUS', name: 'Meu chat' });
|
|
298
|
+
|
|
299
|
+
// Chat existente
|
|
300
|
+
const existing = getAgentTaskMitra({ taskId: 'uuid-da-task' });
|
|
301
|
+
await existing.loadHistory({ limit: 50 });
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
`getAgentTaskMitra({ create: true, agentType?, name?, agentId?, reasoningEffort?, transport?, userId? })` ou `getAgentTaskMitra({ taskId, transport?, userId? })`.
|
|
305
|
+
|
|
306
|
+
**Agente autônomo**: a autonomia é **propriedade do AGENTE** (`autonomous` em `createAgentMitra`/`updateAgentMitra`, no `mitra-sdk`) — não existe flag na criação do chat. Ao criar um chat contra um agente autônomo (`getAgentTaskMitra({ create: true, agentId })`), o copilot deriva a autonomia do agente e o chat já nasce **sem dono** (`user_id NULL` — a dona é o agente), usando a connection anexada ao agente como credencial. Exige auth `AGENT_WRITE` (chave de SF ou token de app EDIT) — usuário business comum não abre chat autônomo. Depois de criado, dirigir/listar é igual ao chat normal (`getAgentTaskMitra({ taskId })`, `send`, `manageAgentChatMitra({ list, agentId })`).
|
|
307
|
+
|
|
308
|
+
- `agentType` vem de `manageAgentCredentialMitra({ action: 'list_models' })` — ex.: `'ANTHROPIC_CLAUDE_OPUS'`, `'OPENAI_GPT5'`. Default: `'ANTHROPIC_CLAUDE_OPUS'`.
|
|
309
|
+
- **`agentId`**: id de um agente business (CRUD via `mitra-sdk`: `listAgentsMitra` e família). A sessão sobe com o system prompt do agente e um token escopado — as tools enxergam só as Server Functions dele. **Sem `agentId`: sessão business sem agente** — sem system prompt e sem acesso às Server Functions (as tools recusam); não há adoção automática de agente único. Na prática, sempre passe `agentId`.
|
|
310
|
+
|
|
311
|
+
**Agir em nome do dono (`userId`)**: uma Server Function disparada por webhook/cron pode abrir e dirigir o chat de um usuário específico, em nome dele — o chat é normal, com dono; o turno roda com a identidade e a credencial do dono (connection do agente primeiro, senão a conta dele). Exige `AGENT_WRITE` no app (senão 403); o backend decide a autorização, a SDK só repassa. Tudo opcional: ausente = comportamento de sempre, byte a byte.
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
// SF reagindo a webhook: continua a thread da pessoa atendida
|
|
315
|
+
const task = getAgentTaskMitra({ create: true, agentId, userId: 'uuid-do-usuario' }); // chat nasce DELE
|
|
316
|
+
const dela = await manageAgentChatMitra({ action: 'list', userId: 'uuid-do-usuario' }); // chats DELA
|
|
317
|
+
const mesma = getAgentTaskMitra({ taskId, userId: 'uuid-do-usuario' }); // defensivo: 404 se o chat não for dela
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Erros nomeados: `403` sem `AGENT_WRITE`; `400 AUTONOMOUS_TASK_HAS_NO_OWNER` (userId + agente autônomo é contradição); `404` quando o `userId` defensivo não bate com o dono real. Nunca invente `userId` de texto do usuário — use o id do vínculo canal→usuário da sua aplicação.
|
|
321
|
+
|
|
322
|
+
#### Propriedades (somente leitura)
|
|
323
|
+
|
|
324
|
+
| Propriedade | Tipo | Descrição |
|
|
325
|
+
|-------------|------|-----------|
|
|
326
|
+
| `taskId` | `string \| null` | `null` até o primeiro `send()` num chat novo |
|
|
327
|
+
| `task` | `AgentChat \| null` | Metadados do chat |
|
|
328
|
+
| `isNew` | `boolean` | Se foi aberto via `{ create: true }` |
|
|
329
|
+
| `status` | `AgentTaskStatus` | `opening` · `idle` · `streaming` · `cancelled` · `error` · `closed` |
|
|
330
|
+
| `history` | `AgentTimelineItem[]` | Linha do tempo canônica — `{ id, kind: 'user' \| 'agent', text, at }` ou `{ id, kind: 'tool', tool: AgentToolEvent, at }` (tool já desempacotada, mesmo shape do evento do streaming) |
|
|
331
|
+
| `content` | `string` | Conteúdo acumulado do turno atual |
|
|
332
|
+
| `queue` | `QueuedItem[]` | Mensagens enfileiradas (enviadas enquanto streamava) |
|
|
333
|
+
|
|
334
|
+
#### Métodos
|
|
335
|
+
|
|
336
|
+
- `send(prompt, { reasoningEffort?, agentType? })` → `void` — dispara um turno (`message` no WS ou POST `/inputs`). Se já está streamando, **enfileira** (FIFO, máx 10; as opções viajam com o item). `reasoningEffort`: intensidade desta mensagem — valores válidos vêm das `reasoningOptions` do modelo em `list_models` (**nunca invente**; fora do registro = `INVALID_REASONING_EFFORT`); herda o default de `getAgentTaskMitra({ create, reasoningEffort })` quando omitido. `agentType`: troca o modelo nesta mensagem — **só dentro do mesmo harness** (Claude↔Codex em conversa iniciada = `HARNESS_SWITCH`).
|
|
337
|
+
- `cancel()` → `Promise<void>` — interrompe o turno atual (WS `interrupt`, safety net de 10s).
|
|
338
|
+
- `respondApproval(approved)` → `void` — responde um pedido de aprovação do agente (WS `approval_response`).
|
|
339
|
+
- `loadHistory({ limit? })` → `Promise<AgentTimelineItem[]>` — histórico persistido via REST, já no formato canônico da timeline (renderizou o streaming, renderizou o histórico).
|
|
340
|
+
- `editQueueItem(id, text)` / `removeQueueItem(id)` / `clearQueue()` — manipulam a fila.
|
|
341
|
+
- `on(event, handler)` → função de unsubscribe — assina eventos da session.
|
|
342
|
+
- `close()` — encerra a session, fecha o WS e libera os listeners.
|
|
343
|
+
|
|
344
|
+
#### Eventos (`session.on`)
|
|
345
|
+
|
|
346
|
+
`statusChange` · `historyLoaded` · `taskCreated` · `turnStart` · `delta` (`{ delta, kind: 'text' | 'thinking' }`) · `tool` (`{ tool, toolId?, input?, content?, phase: 'call' | 'result' }`) · `turnEnd` (`{ content }`) · `cancelled` · `queueChange` · `error` (`{ code?, error }`) · `raw` (eventos não mapeados do stream, ex.: `workspace`).
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
const session = getAgentTaskMitra({ create: true, agentId: 'uuid-do-agente' });
|
|
350
|
+
|
|
351
|
+
session.on('delta', ({ delta, kind }) => { if (kind === 'text') process.stdout.write(delta); });
|
|
352
|
+
session.on('tool', ({ tool, phase }) => console.log('🔧', phase, tool));
|
|
353
|
+
session.on('turnEnd', ({ content }) => console.log('\n✓ fim do turno'));
|
|
354
|
+
session.on('taskCreated', ({ task }) => console.log('chat criado:', task.id));
|
|
355
|
+
session.on('error', ({ error }) => console.error(error));
|
|
356
|
+
|
|
357
|
+
session.send('Analise estas vendas e gere um resumo');
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Credenciais do agente — `manageAgentCredentialMitra`
|
|
361
|
+
|
|
362
|
+
Função única, toda HTTP **via BFF** (`/agentAiShortcut/listProviders`, `saveCredential`, `oauthStart`...). Providers: `'anthropic'` e `'openai'`. API key via `save`/`remove` (ambos); **OAuth (`auth`/`connect`) é exclusivo do anthropic; device flow (`device_auth`/`device_poll`) é exclusivo do openai** — fluxo trocado falha rápido com erro claro.
|
|
363
|
+
|
|
364
|
+
**`projectId` é obrigatório** em todas as actions (opcional na chamada se já veio do `configureSdkMitra`) — é ele que define de qual app é a credencial; o BFF resolve `projectId → appId` e cunha o token de app.
|
|
365
|
+
|
|
366
|
+
> 🔒 Tokens/keys nunca voltam crus — o backend devolve só status, e-mail da conta e a key mascarada.
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { manageAgentCredentialMitra } from 'mitra-interactions-sdk';
|
|
370
|
+
|
|
371
|
+
// Status por provider (pra montar a UI de conexão)
|
|
372
|
+
const { providers } = await manageAgentCredentialMitra({ action: 'list_providers' });
|
|
373
|
+
// AgentCredentialStatus[]: { provider, connected, credentialType, accountEmail, maskedApiKey }
|
|
374
|
+
|
|
375
|
+
// Modelos selecionáveis → use o agentType em getAgentTaskMitra
|
|
376
|
+
const { models } = await manageAgentCredentialMitra({ action: 'list_models' });
|
|
377
|
+
// AgentModel[]: { model, name, provider, agentType, reasoningOptions }
|
|
378
|
+
// reasoningOptions = registro das intensidades válidas por modelo (variam por
|
|
379
|
+
// harness) — monte o seletor de reasoning a partir DAQUI, nunca hardcode.
|
|
380
|
+
// Round-trip: os valores vêm em minúsculo e são aceitos na entrada COMO ESTÃO.
|
|
381
|
+
|
|
382
|
+
// Com agentId: o que o PRÓXIMO TURNO daquele agente consegue rodar.
|
|
383
|
+
// Agente com connection → catálogo da connection, SEMPRE (é ela que roda o
|
|
384
|
+
// turno, mesmo que o caller tenha credencial própria). Sem connection →
|
|
385
|
+
// fallback pro catálogo da credencial do usuário.
|
|
386
|
+
const doAgente = await manageAgentCredentialMitra({ action: 'list_models', agentId: 'uuid-do-agente' });
|
|
387
|
+
// Erros nomeados (err.code, HTTP 400 — reaja pelo código):
|
|
388
|
+
// NO_CREDENTIAL_AVAILABLE → nenhuma credencial utilizável (nunca vem lista
|
|
389
|
+
// vazia nesse caso) — mande conectar um provider
|
|
390
|
+
// CONNECTION_NOT_FOUND → a connection do agente não existe mais
|
|
391
|
+
|
|
392
|
+
// API key
|
|
393
|
+
await manageAgentCredentialMitra({ action: 'save', target: 'openai', key: 'sk-...' });
|
|
394
|
+
await manageAgentCredentialMitra({ action: 'remove', target: 'anthropic' });
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
OAuth (só Anthropic) — `auth` devolve o que mostrar, `connect` finaliza:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
const { authUrl, state } = await manageAgentCredentialMitra({ action: 'auth', target: 'anthropic' });
|
|
401
|
+
// app abre authUrl; usuário autoriza e copia o código
|
|
402
|
+
const { connected, email } = await manageAgentCredentialMitra({ action: 'connect', target: 'anthropic', code, state });
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Device flow (só OpenAI) — mostre `userCode` + `verificationUri` e faça polling:
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
const { deviceAuthId, userCode, verificationUri, intervalSeconds } =
|
|
409
|
+
await manageAgentCredentialMitra({ action: 'device_auth', target: 'openai' });
|
|
410
|
+
// app mostra: "abra {verificationUri} e digite {userCode}"; depois, a cada intervalSeconds:
|
|
411
|
+
const { connected } = await manageAgentCredentialMitra({ action: 'device_poll', target: 'openai', deviceAuthId });
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Tipos TypeScript
|
|
415
|
+
|
|
416
|
+
Todos os tipos estão incluídos:
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
import type {
|
|
420
|
+
MitraConfig,
|
|
421
|
+
// Login
|
|
422
|
+
LoginOptions,
|
|
423
|
+
LoginResponse,
|
|
424
|
+
// Options
|
|
425
|
+
ExecuteServerFunctionOptions,
|
|
426
|
+
ExecuteServerFunctionAsyncOptions,
|
|
427
|
+
StopServerFunctionExecutionOptions,
|
|
428
|
+
ListRecordsOptions,
|
|
429
|
+
GetRecordOptions,
|
|
430
|
+
CreateRecordOptions,
|
|
431
|
+
UpdateRecordOptions,
|
|
432
|
+
PatchRecordOptions,
|
|
433
|
+
DeleteRecordOptions,
|
|
434
|
+
CreateRecordsBatchOptions,
|
|
435
|
+
// Responses
|
|
436
|
+
ExecuteServerFunctionResponse,
|
|
437
|
+
ExecuteServerFunctionAsyncResponse,
|
|
438
|
+
StopServerFunctionExecutionResponse,
|
|
439
|
+
ListRecordsResponse,
|
|
440
|
+
// Agent Chat
|
|
441
|
+
AgentChat,
|
|
442
|
+
AgentMessage,
|
|
443
|
+
AgentTaskSession,
|
|
444
|
+
AgentTaskStatus,
|
|
445
|
+
SendOptions,
|
|
446
|
+
ManageAgentChatOptions,
|
|
447
|
+
GetAgentTaskOptions,
|
|
448
|
+
// Agent Credentials
|
|
449
|
+
ManageAgentCredentialOptions,
|
|
450
|
+
ListAgentModelsResult,
|
|
451
|
+
ListAgentProvidersResult
|
|
452
|
+
} from 'mitra-interactions-sdk';
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## Tratamento de Erros
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
try {
|
|
459
|
+
const result = await executeServerFunctionMitra({
|
|
460
|
+
projectId: 123,
|
|
461
|
+
serverFunctionId: 456
|
|
462
|
+
});
|
|
463
|
+
} catch (error) {
|
|
464
|
+
console.log('Erro:', error.message);
|
|
465
|
+
console.log('Status:', error.status);
|
|
466
|
+
console.log('Detalhes:', error.details);
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Licença
|
|
471
|
+
|
|
472
|
+
MIT
|