@mitralab.io/functions-sdk 0.2.6 → 0.2.7
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/CHANGELOG.md +17 -0
- package/README.md +61 -500
- package/contracts/sdk-core-v0.2.12-beta.1.manifest.json +15 -0
- package/contracts/sdk-core-v0.2.12.manifest.json +15 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.2.7
|
|
6
|
+
|
|
7
|
+
Stable release of the 0.2.7-beta.0 line, already on the `beta` tag. This release only moves the
|
|
8
|
+
Core dependency to its stable number, so no runtime behavior in this package changes.
|
|
9
|
+
|
|
10
|
+
- Depend on `@mitralab.io/sdk-core@0.2.12`, the stable release of the 0.2.12-beta.1 surface: a
|
|
11
|
+
`cancel()` pressed before the agent turn starts waits for the box to admit the prompt and goes out
|
|
12
|
+
right after it.
|
|
13
|
+
- Pin the SDK-PARITY-001 corpus to Core `0.2.12` with its digest and immutable source commit.
|
|
14
|
+
|
|
15
|
+
## 0.2.7-beta.0
|
|
16
|
+
|
|
17
|
+
- Depend on `@mitralab.io/sdk-core@0.2.12-beta.1`: a `cancel()` pressed before the agent turn starts
|
|
18
|
+
waits for the box to admit the prompt and goes out right after it, instead of being dropped while
|
|
19
|
+
the answer kept coming. `cancelled` is only emitted once the stop was delivered.
|
|
20
|
+
- Pin the SDK-PARITY-001 corpus to Core `0.2.12-beta.1` with its digest and immutable source commit.
|
|
21
|
+
|
|
5
22
|
## 0.2.6
|
|
6
23
|
|
|
7
24
|
Stable release of the 0.2.6-beta.0 line, already on the `beta` tag. This release only moves the
|
package/README.md
CHANGED
|
@@ -1,539 +1,100 @@
|
|
|
1
1
|
# Mitra Functions SDK for JavaScript
|
|
2
2
|
|
|
3
|
-
JavaScript
|
|
3
|
+
SDK JavaScript e TypeScript para código que roda dentro de uma Server Function da Mitra: dados do app, outras Functions, queries, integrações, agentes e notificações, sempre no escopo do app da Function. Para app de browser, use [`@mitralab.io/platform-sdk`](https://www.npmjs.com/package/@mitralab.io/platform-sdk).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Shared API contracts and modules come from `@mitralab.io/sdk-core`. This package owns only the Server Function runtime adapter: environment configuration, token headers, optional request deadlines, credential redaction, redirect refusal, and one-attempt request policy. The core never receives or stores the token.
|
|
8
|
-
|
|
9
|
-
## Installation
|
|
5
|
+
## Instalação
|
|
10
6
|
|
|
11
7
|
```bash
|
|
12
8
|
npm install @mitralab.io/functions-sdk
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## Runtime integration
|
|
18
|
-
|
|
19
|
-
The SDK accepts the existing Server Function runtime variables:
|
|
11
|
+
No runtime de Server Functions da Mitra o pacote já vem instalado; instale no projeto para ter os tipos ou para rodar fora do runtime. Node 18 ou mais novo, ou outro runtime com `fetch` global.
|
|
20
12
|
|
|
21
|
-
|
|
22
|
-
- `MITRA_TOKEN`
|
|
23
|
-
- `MITRA_PROJECT_ID`
|
|
13
|
+
## Início rápido
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
```javascript
|
|
16
|
+
const { createClient } = require("@mitralab.io/functions-sdk")
|
|
26
17
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- `MITRA_APP_ID`
|
|
30
|
-
- `MITRA_DATA_SOURCE_ID`, retained for runtime compatibility when already resolved
|
|
31
|
-
- `MITRA_API_KEY`, read by `createClientFromApiKey()`
|
|
18
|
+
exports.handler = async (event, context) => {
|
|
19
|
+
const mitra = createClient()
|
|
32
20
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
unchanged as the bearer token and uses `MITRA_PROJECT_ID` as the app identifier. It does not
|
|
36
|
-
exchange, refresh, inspect, or alter the token. The deprecated bridge still receives the original
|
|
37
|
-
base URL. Neither token name represents a user-defined Function secret.
|
|
21
|
+
const order = await mitra.entities.Order.get(event.orderId)
|
|
22
|
+
const { data: items } = await mitra.entities.OrderItem.filter({ order_id: event.orderId })
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
import { createClient } from "@mitralab.io/functions-sdk"
|
|
43
|
-
|
|
44
|
-
const mitra = createClient()
|
|
45
|
-
|
|
46
|
-
export async function handler(input: { orderId: string }) {
|
|
47
|
-
const order = await mitra.entities.Order.get(input.orderId)
|
|
48
|
-
return { order }
|
|
24
|
+
return { order, items }
|
|
49
25
|
}
|
|
50
26
|
```
|
|
51
27
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
const mitra = createClient({
|
|
56
|
-
apiUrl: "https://api.example.com",
|
|
57
|
-
accessToken: process.env.MITRA_PLATFORM_ACCESS_TOKEN,
|
|
58
|
-
appId: "app-id",
|
|
59
|
-
dataSourceId: "data-source-id",
|
|
60
|
-
})
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
`createClientFromEnvironment(env)` is available when a function needs to supply a specific environment object, such as in tests.
|
|
64
|
-
|
|
65
|
-
### Authenticating with an api key
|
|
66
|
-
|
|
67
|
-
Outside the Functions runtime there is no token to inject. A process that runs on its own — a cron,
|
|
68
|
-
a background collector, another service — authenticates with an api key created in
|
|
69
|
-
**Settings -> API keys**:
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
import { createClientFromApiKey } from "@mitralab.io/functions-sdk"
|
|
73
|
-
|
|
74
|
-
const mitra = await createClientFromApiKey({
|
|
75
|
-
apiUrl: "https://api.example.com",
|
|
76
|
-
apiKey: process.env.MITRA_API_KEY,
|
|
77
|
-
appId: "app-id",
|
|
78
|
-
})
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
The factory is asynchronous because trading the key for a token is a network call. It fails there,
|
|
82
|
-
where the client is built, rather than inside an unrelated call later.
|
|
28
|
+
Dentro do runtime, `createClient()` lê a URL, o token e o app das variáveis de ambiente que a Mitra injeta, então não precisa de argumento.
|
|
83
29
|
|
|
84
|
-
|
|
85
|
-
product: read and write records, run queries, execute functions and integrations. A **Developer**
|
|
86
|
-
key adds authoring — schema, code, publishing. An **Administrator** key belongs to a workspace
|
|
87
|
-
rather than a product; the SDK issues the token for the configured `appId` from it, and the
|
|
88
|
-
platform decides on that call what this user actually reaches in that product.
|
|
30
|
+
Fora do runtime, num processo seu, autentique com uma API key criada em Configurações, API keys. `createClientFromApiKey()` lê `MITRA_API_URL`, `MITRA_APP_ID` e `MITRA_API_KEY` e já troca a chave por um token, para uma chave errada falhar ali:
|
|
89
31
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
its own when a request comes back unauthorized, which is why a process may stay up for weeks. Keep
|
|
93
|
-
the key where you keep passwords — it is valid until someone deletes it.
|
|
32
|
+
```javascript
|
|
33
|
+
const { createClientFromApiKey } = require("@mitralab.io/functions-sdk")
|
|
94
34
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
## Initialization
|
|
99
|
-
|
|
100
|
-
Entity and Custom Query operations use the app identity from the token and `X-App-Id`, so they are
|
|
101
|
-
available immediately. Custom Query execution sends only `parameters`; Data Manager resolves its
|
|
102
|
-
Data Source from the authenticated app.
|
|
103
|
-
|
|
104
|
-
`init()` and the optional `dataSourceId` configuration remain available for source compatibility.
|
|
105
|
-
When no Data Source is configured, `init()` resolves the nullable value from Code Studio and is
|
|
106
|
-
safe to call concurrently, but native Queries and Entities do not depend on it.
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
const mitra = createClient()
|
|
110
|
-
await mitra.init()
|
|
111
|
-
|
|
112
|
-
const result = await mitra.queries.execute("5df41c69-2a74-4db6-9cca-4af2b473941f", {
|
|
113
|
-
status: "active",
|
|
114
|
-
})
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## API
|
|
118
|
-
|
|
119
|
-
### Current user
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
const user = await mitra.auth.me()
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
The SDK only reads the current authenticated user. Login, logout, browser storage, and token refresh belong to the Platform SDK used by frontend applications.
|
|
126
|
-
|
|
127
|
-
### Entities
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
type Task = {
|
|
131
|
-
id: string
|
|
132
|
-
title: string
|
|
133
|
-
status: "pending" | "done"
|
|
35
|
+
async function loadOrder(orderId) {
|
|
36
|
+
const mitra = await createClientFromApiKey()
|
|
37
|
+
return mitra.entities.Order.get(orderId)
|
|
134
38
|
}
|
|
135
|
-
|
|
136
|
-
const tasks = mitra.entities.getTable<Task>("Task")
|
|
137
|
-
const { data: recent } = await tasks.list({ sort: "-created_at", limit: 20 })
|
|
138
|
-
const { data: pending } = await tasks.filter({ status: "pending" })
|
|
139
|
-
const created = await tasks.create({ title: "Review order" })
|
|
140
|
-
await tasks.update(created.id, { status: "done" })
|
|
141
|
-
await tasks.delete(created.id)
|
|
142
|
-
|
|
143
|
-
const dynamic = await mitra.entities.Task.list()
|
|
144
39
|
```
|
|
145
40
|
|
|
146
|
-
|
|
41
|
+
## O que dá para fazer
|
|
147
42
|
|
|
148
|
-
|
|
43
|
+
- `entities.<Tabela>`: `list`, `filter`, `get`, `create`, `bulkCreate`, `update`, `delete` e `deleteMany` nas tabelas do app.
|
|
44
|
+
- `queries`, `customQueries`, `sql` e `schema`: queries salvas, SQL parametrizado e estrutura das tabelas.
|
|
45
|
+
- `functions`, `publicFunctions` e `workflows`: chamar outras Server Functions e workflows do app.
|
|
46
|
+
- `integration.executeByAlias(alias, request)`: chama uma API externa configurada no app, com a credencial guardada na Mitra.
|
|
47
|
+
- `messenger.notify(texto)`: manda uma notificação ao usuário autenticado.
|
|
48
|
+
- `agentTasks.session(...)`: chat com agente, com `send`, `sendAndWait`, `cancel` e eventos como `accepted` e `turnEnd`.
|
|
49
|
+
- `currentApp`: definição, arquivos, build e publicação do app da Function.
|
|
50
|
+
- `functionsAdmin`, `integrationAdmin`, `agents`, `agentConnections`, `agentCredentials`, `imports` e `dataSources`: administração dos recursos do app.
|
|
149
51
|
|
|
150
|
-
|
|
151
|
-
const result = await mitra.queries.execute("5df41c69-2a74-4db6-9cca-4af2b473941f", {
|
|
152
|
-
customerId: "customer-id",
|
|
153
|
-
})
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### Server Functions
|
|
157
|
-
|
|
158
|
-
`execute` waits for a terminal execution response. `executeAsync` requests asynchronous execution and returns the pending execution record.
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
const completed = await mitra.functions.execute("function-id", { orderId: "order-id" })
|
|
162
|
-
const pending = await mitra.functions.executeAsync("function-id", { orderId: "order-id" })
|
|
163
|
-
const current = await mitra.functions.getExecution(pending.id)
|
|
164
|
-
await mitra.functions.cancelExecution(pending.id)
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Integrations
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
const resource = await mitra.integration.executeResource("resource-id", {
|
|
171
|
-
description: "Notebook",
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
const proxy = await mitra.integration.execute("config-id", {
|
|
175
|
-
method: "GET",
|
|
176
|
-
endpoint: "/users",
|
|
177
|
-
queryParams: { limit: "10" },
|
|
178
|
-
})
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Credentials configured for an integration are injected by the Integration service. Do not pass provider credentials through function input.
|
|
182
|
-
|
|
183
|
-
Use `integrationAdmin.list()` as the native equivalent of `listIntegrationsMitra`. It calls
|
|
184
|
-
`GET /integration/api/v1/template-configs`; the service filters app-scoped runtime tokens to the
|
|
185
|
-
current app and returns its real paginated `TemplateConfigSummary` values.
|
|
186
|
-
|
|
187
|
-
Native entity methods target the public Data Manager records API, which resolves the app Data
|
|
188
|
-
Source from the runtime token. That API does not accept the legacy `jdbcConnectionConfigId`
|
|
189
|
-
selector, so records that depend on it remain available only through the deprecated bridge. The
|
|
190
|
-
SDK does not emulate that selection with raw SQL.
|
|
191
|
-
|
|
192
|
-
### Native modules
|
|
193
|
-
|
|
194
|
-
The native client exposes all 24 application runtime and authoring modules from
|
|
195
|
-
`@mitralab.io/sdk-core` directly against the owning services. `currentApp` is an additional
|
|
196
|
-
Functions-specific convenience facade over the Core `apps` module:
|
|
197
|
-
|
|
198
|
-
| Area | Modules | Service |
|
|
199
|
-
| ------------------------ | --------------------------------------------------------------------------------- | --------------------------------------- |
|
|
200
|
-
| Identity and members | `auth`, `members` | IAM |
|
|
201
|
-
| Data | `dataSources`, `schema`, `entities`, `customQueries`, `queries`, `sql`, `imports` | Data Manager |
|
|
202
|
-
| Functions and automation | `functions`, `functionsAdmin`, `agents`, `workflows` | Functions |
|
|
203
|
-
| Apps | `apps`, `currentApp`, `context` | Code Studio and composed native modules |
|
|
204
|
-
| Agent runtime | `agentTasks`, `agentCredentials`, `agentConnections` | Copilot |
|
|
205
|
-
| Integrations | `integration`, `integrationAdmin`, `integrationTemplates`, `integrationResources` | Integration |
|
|
206
|
-
| Notifications | `messenger` | Messenger |
|
|
207
|
-
| Anonymous execution | `publicFunctions` | Functions public API |
|
|
52
|
+
## Configuração
|
|
208
53
|
|
|
209
|
-
|
|
210
|
-
`mitra-sdk` compatibility exports described below.
|
|
54
|
+
`createClient(config?)` usa o campo de `config` e, quando ele falta, a variável de ambiente. Em teste, `createClientFromEnvironment(env)` lê só do objeto que você passar.
|
|
211
55
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
`
|
|
56
|
+
| Campo | Variável | Obrigatório | Uso |
|
|
57
|
+
| ------------- | ---------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `apiUrl` | `MITRA_API_URL` ou `MITRA_BASE_URL` | sim | URL HTTP ou HTTPS do API gateway da Mitra, sem credencial, query ou fragmento |
|
|
59
|
+
| `accessToken` | `MITRA_PLATFORM_ACCESS_TOKEN` ou `MITRA_TOKEN` | sim, exceto com API key | token do runtime, enviado como `Bearer` |
|
|
60
|
+
| `appId` | `MITRA_APP_ID` ou `MITRA_PROJECT_ID` | sim | app em que o cliente atua |
|
|
61
|
+
| `apiKey` | `MITRA_API_KEY` | só em `createClientFromApiKey` | chave do app, para processo fora do runtime |
|
|
62
|
+
| `timeoutMs` | | não | prazo por requisição; sem ele, o SDK não impõe prazo, e dentro de uma Function vale o limite de tempo dela |
|
|
63
|
+
| `fetch` | | não | implementação de `fetch`; sem ela, usa a global |
|
|
64
|
+
| `WebSocket` | | não | implementação de WebSocket, como a do pacote `ws`, para a sessão de agente usar socket; sem ela, vale o WebSocket global, se houver, ou HTTP |
|
|
220
65
|
|
|
221
|
-
|
|
222
|
-
Without it, the fields are all null without consulting Scheduler. A Function with no schedule has
|
|
223
|
-
the same all-null shape, so those responses alone cannot distinguish absence from missing read
|
|
224
|
-
permission. Function bulk create, update, and patch prohibit all three cron fields; use the
|
|
225
|
-
single-Function methods for composed scheduling.
|
|
66
|
+
## Erros
|
|
226
67
|
|
|
227
|
-
|
|
228
|
-
list keep Function state and its composed cron fields in one contract.
|
|
68
|
+
`MitraApiError` traz `status`, `code`, `details`, `requestId` e `retryable`. O token não aparece na mensagem nem nos detalhes.
|
|
229
69
|
|
|
230
|
-
|
|
70
|
+
| Erro | Quando | O que fazer |
|
|
71
|
+
| ---------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
72
|
+
| `MitraConfigurationError` | configuração ausente ou inválida, ou `apps` usado com outro app | confira variáveis e argumentos; para o próprio app, use `currentApp` |
|
|
73
|
+
| `MitraApiError` `401` ou `403` | o token não dá acesso ao recurso | confira as permissões do app; nem todo módulo está liberado para o token do runtime |
|
|
74
|
+
| `MitraApiError` `429` ou `5xx` | limite de requisições ou falha no servidor | repita só se a operação puder ser repetida |
|
|
75
|
+
| `REQUEST_TIMEOUT`, `NETWORK_ERROR` | prazo estourado ou falha de rede, com `status` `0` | aumente `timeoutMs` ou repita, se a operação permitir |
|
|
76
|
+
| `INVALID_CREDENTIALS`, `AUTHENTICATION_FAILED` | a troca da API key falhou | confira a chave e o `appId` |
|
|
77
|
+
| `INVALID_RESPONSE` | resposta fora do formato esperado | atualize o SDK; se continuar, abra uma issue |
|
|
78
|
+
| `AgentTaskTurnError` | o turno do agente foi recusado ou terminou com erro | leia o `code` e decida se manda de novo |
|
|
231
79
|
|
|
232
|
-
|
|
233
|
-
Core also owns the direct channel to the chat's box: the session asks the Copilot where the chat
|
|
234
|
-
is served (`POST /copilot/api/v1/tasks/{taskId}/channel`) and then talks to that box, which runs
|
|
235
|
-
the turn. This package only wires the channel to the client's API URL and WebSocket.
|
|
80
|
+
## Boas práticas
|
|
236
81
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
82
|
+
- Crie o cliente dentro do handler. O token do runtime vale para aquela execução e dura pouco.
|
|
83
|
+
- O SDK faz uma tentativa por requisição e não repete, para não gravar duas vezes. `retryable` é só uma dica. O cliente por API key é a exceção: num `401`, ele pega um token novo e repete aquela requisição uma vez.
|
|
84
|
+
- Para o app da Function, use `currentApp`. `apps` só aceita o próprio app, e `apps.list()` e `apps.create()` não existem aqui.
|
|
85
|
+
- Function que só dispara um prompt para um agente pode retornar depois do evento `accepted`. Antes dele, o prompt pode se perder.
|
|
86
|
+
- `cancel()` chamado enquanto o prompt ainda está a caminho espera a box aceitar a mensagem e só então interrompe o turno; aguarde a promessa dele antes de dar o chat por parado. Se a box recusar a mensagem, nenhum stop sai e o evento `cancelled` não é emitido, então o stop não interrompe um turno seguinte.
|
|
87
|
+
- API key fica em variável de ambiente de processo de servidor, nunca em código de browser nem no repositório.
|
|
240
88
|
|
|
241
|
-
|
|
242
|
-
const session = mitra.agentTasks.session({
|
|
243
|
-
create: true,
|
|
244
|
-
agentId: "agent-id",
|
|
245
|
-
agentType: "CODEX",
|
|
246
|
-
})
|
|
89
|
+
## Migração do `mitra-sdk`
|
|
247
90
|
|
|
248
|
-
|
|
249
|
-
console.log(kind, delta)
|
|
250
|
-
})
|
|
91
|
+
Os exports do SDK legado continuam neste pacote, marcados `@deprecated`, para código de Function existente trocar a dependência sem reescrever os imports. `createClient()` configura o legado com o mesmo token e o mesmo app. Os tipos do Core que têm nome igual a um tipo legado saem com prefixo `Core`, como `CoreAgentConnection`.
|
|
251
92
|
|
|
252
|
-
|
|
253
|
-
console.log(result.content)
|
|
254
|
-
session.close()
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
Existing tasks use `mitra.agentTasks.session({ taskId })`. A new agent chat is created on the
|
|
258
|
-
box runtime (`runtime: "T3"`) unless the session names another runtime.
|
|
259
|
-
|
|
260
|
-
`transport` picks how the session tries to reach the box:
|
|
261
|
-
|
|
262
|
-
- `auto`, the default, uses the box WebSocket when the runtime has one and the box HTTP routes
|
|
263
|
-
otherwise: a `POST` per message and a Server-Sent Events (SSE) stream for events.
|
|
264
|
-
- `http` uses the box HTTP routes.
|
|
265
|
-
- `websocket` uses the box WebSocket.
|
|
266
|
-
|
|
267
|
-
Until the box offers the route the session asks for, the session falls back to the Copilot and
|
|
268
|
-
says so with `channelDeclined` (see below). The transport is a preference, not a guarantee.
|
|
269
|
-
|
|
270
|
-
The Serverless Functions runtime runs Node 20, which has no global `WebSocket`, so sessions
|
|
271
|
-
there reach the box over HTTP. Node 22 and newer have one. To use the socket on a runtime without
|
|
272
|
-
it, pass an implementation such as `ws` when you create the client; this package does not depend
|
|
273
|
-
on one:
|
|
274
|
-
|
|
275
|
-
```typescript
|
|
276
|
-
import WebSocket from "ws"
|
|
277
|
-
|
|
278
|
-
const mitra = createClient({ WebSocket })
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
The box is reached through the channel URL the Copilot returns, which carries a short-lived
|
|
282
|
-
grant; the runtime token is never sent to the box. The box routes use `globalThis.fetch`, not the
|
|
283
|
-
`fetch` given to the client, so a custom fetch that adds `Authorization` cannot leak the token
|
|
284
|
-
there. Core follows only a channel on the configured
|
|
285
|
-
API host or a Mitra box host. When the Copilot offers no channel, or the offer cannot be followed
|
|
286
|
-
(for example a `websocket` session with no WebSocket available), the session stays on the
|
|
287
|
-
Copilot: it opens `GET /copilot/api/v1/tasks/{taskId}/events` as an SSE stream with the runtime
|
|
288
|
-
token in `Authorization` plus `X-App-Id`, and sends input to `POST /inputs`. That fallback is
|
|
289
|
-
never silent: the session first emits a `raw` event of type `channelDeclined` with the reason.
|
|
290
|
-
|
|
291
|
-
`timeoutMs` also bounds `POST /channel`, which the Copilot holds open while the box boots. A
|
|
292
|
-
short `timeoutMs` can abort that request, and the session then falls back to the Copilot with
|
|
293
|
-
`channelDeclined` reason `unavailable`; leave it unset, or above the box boot time, for agent
|
|
294
|
-
chats. On the Copilot stream, `timeoutMs` applies only while waiting for the SSE response
|
|
295
|
-
headers. The parser ignores `hello` and `ping` keepalives, and a stream silent for 60 seconds counts
|
|
296
|
-
as a disconnect; Core then reconnects once and reconciles persisted messages. The box channel has
|
|
297
|
-
its own handshake, silence, redial, and admission deadlines in Core.
|
|
298
|
-
|
|
299
|
-
#### Send and return
|
|
300
|
-
|
|
301
|
-
A Function does not have to wait for the whole turn. Once the box admits the message, the turn
|
|
302
|
-
runs and is recorded without the Function, so it can send, wait for `accepted`, and return:
|
|
303
|
-
|
|
304
|
-
```typescript
|
|
305
|
-
export async function handler(input: { taskId: string; prompt: string }) {
|
|
306
|
-
const session = mitra.agentTasks.session({ taskId: input.taskId })
|
|
307
|
-
try {
|
|
308
|
-
await new Promise<void>((resolve, reject) => {
|
|
309
|
-
session.on("accepted", () => resolve())
|
|
310
|
-
session.on("error", ({ code, error }) =>
|
|
311
|
-
reject(new Error(code ? `${code}: ${error}` : error)),
|
|
312
|
-
)
|
|
313
|
-
session.send(input.prompt)
|
|
314
|
-
})
|
|
315
|
-
return { accepted: true }
|
|
316
|
-
} finally {
|
|
317
|
-
session.close()
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
`accepted` fires when the box starts the admitted turn, or after the Copilot's `202` on the
|
|
323
|
-
fallback. A refusal fires `error` instead, and a box that does not answer fails the send after
|
|
324
|
-
35 seconds. Returning before `accepted` may lose the message.
|
|
325
|
-
|
|
326
|
-
### App-scoped Code Studio access
|
|
327
|
-
|
|
328
|
-
The Functions runtime is fixed to the configured `appId`. `apps.list()` and `apps.create()`
|
|
329
|
-
reject locally because they are tenant-level operations. Every other `apps` method rejects
|
|
330
|
-
an app ID different from the configured runtime app before making a request.
|
|
331
|
-
|
|
332
|
-
Use `currentApp` when possible. It exposes the same current-app lifecycle without repeating
|
|
333
|
-
the app ID:
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
const app = await mitra.currentApp.get()
|
|
337
|
-
const published = await mitra.currentApp.get({ version: "PUBLISHED" })
|
|
338
|
-
await mitra.currentApp.update({ name: "Orders" })
|
|
339
|
-
await mitra.currentApp.mergeFiles({ "src/generated.ts": "export const ready = true" })
|
|
340
|
-
const previewDeploy = await mitra.currentApp.build()
|
|
341
|
-
await mitra.currentApp.publish({ externalAccess: true })
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
`build()` returns the `AppDeploy` created for preview polling. `get()` preserves the Core
|
|
345
|
-
`AppGetOptions`, and `publish()` preserves `AppPublishOptions`.
|
|
346
|
-
|
|
347
|
-
The client-side check prevents accidental cross-app calls, but it is not a security boundary.
|
|
348
|
-
Code Studio must also enforce the JWT `app_id` claim in the backend. Until that enforcement is
|
|
349
|
-
deployed, the access token must be treated as sensitive even though this SDK fixes the app ID.
|
|
350
|
-
|
|
351
|
-
### Public Functions
|
|
352
|
-
|
|
353
|
-
`publicFunctions` calls `/functions/public/v1` with a dedicated anonymous transport. It never
|
|
354
|
-
sends `Authorization` or `X-App-Id`.
|
|
355
|
-
|
|
356
|
-
```typescript
|
|
357
|
-
const result = await mitra.publicFunctions.execute("public-function-id", { value: 1 })
|
|
358
|
-
const queued = await mitra.publicFunctions.executeAsync("public-function-id", { value: 1 })
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
An asynchronous public execution returns its ID and initial status as fire-and-forget. The public
|
|
362
|
-
API does not expose anonymous polling or cancellation. Use synchronous `execute` when the caller
|
|
363
|
-
needs the result, or authenticated `functions.executeAsync` plus `functions.getExecution` when the
|
|
364
|
-
caller has an app-scoped token.
|
|
365
|
-
|
|
366
|
-
## Runtime authorization
|
|
367
|
-
|
|
368
|
-
The JWT `app_id` claim is the authority for application scope. `X-App-Id` carries runtime
|
|
369
|
-
context for protected service requests and must not be used by a backend as the authorization
|
|
370
|
-
boundary.
|
|
371
|
-
|
|
372
|
-
Against the current `origin/alpha` service and IAM policies, 109 of the 120 MCP capabilities
|
|
373
|
-
are usable or authorizable from an app-scoped Server Function. The `dataSources.bulk*` methods
|
|
374
|
-
compose the existing singular Data Manager endpoints, so they do not require a coordinated
|
|
375
|
-
service rollout. The remaining capabilities have these known constraints:
|
|
376
|
-
|
|
377
|
-
| Capability | Runtime behavior | Reason |
|
|
378
|
-
| ------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
379
|
-
| Member reads through `members.list()` | `403 INSUFFICIENT_PERMISSIONS` | `MEMBER_READ` is deliberately absent from the SF token policy. App context excludes members. |
|
|
380
|
-
| Function secret list/create/delete | `403 INSUFFICIENT_PERMISSIONS` | `FUNCTION_SECRET_READ`, `FUNCTION_SECRET_WRITE`, and `FUNCTION_SECRET_DELETE` are absent from the SF token policy. |
|
|
381
|
-
| Agent runtime operations | Configuration or service rejection without an agent context | The runtime must inject or otherwise provide the applicable `agent_id`. |
|
|
382
|
-
| `apps.list()` and `apps.create()` | Local `MitraConfigurationError` | Tenant-level app collection operations are not applicable to an app-scoped runtime. |
|
|
383
|
-
| `messenger.notify()` | Depends on the authenticated user's channel | The call is authorized, but delivery requires a configured notification channel. |
|
|
384
|
-
|
|
385
|
-
The methods remain part of the typed API so clients with a different authorized token can use
|
|
386
|
-
the shared contract. This SDK does not broaden IAM permissions or retry a rejected operation.
|
|
387
|
-
|
|
388
|
-
### Core and legacy type names
|
|
389
|
-
|
|
390
|
-
The deprecated `AgentConnection`, `AgentMessage`, `AgentModel`, and `ListTablesOptions` names keep
|
|
391
|
-
their original `mitra-sdk` meanings for source compatibility. Import the native Core contracts as
|
|
392
|
-
`CoreAgentConnection`, `CoreAgentMessage`, `CoreAgentModel`, and `CoreListTablesOptions`.
|
|
393
|
-
|
|
394
|
-
The deprecated package also owns `AgentTaskSession`, `AgentTimelineItem`, and `AgentToolEvent`.
|
|
395
|
-
Their native equivalents are exported as `CoreAgentTaskSession`, `CoreAgentTimelineItem`, and
|
|
396
|
-
`CoreAgentToolEvent`. New session options and results are available as
|
|
397
|
-
`CoreAgentTaskSessionOptions`, `AgentSendOptions`, `AgentSendAndWaitOptions`, and `AgentTurnResult`.
|
|
398
|
-
`sendAndWait()` rejects Agent turn failures with `AgentTaskTurnError`, preserving the service error
|
|
399
|
-
code when one is present.
|
|
400
|
-
|
|
401
|
-
## Errors and request behavior
|
|
402
|
-
|
|
403
|
-
API, timeout, invalid response, and network failures throw `MitraApiError`. The error exposes `status`, `code`, `details`, `requestId`, and `retryable`, preserving API metadata when it is provided. Configuration failures throw `MitraConfigurationError`.
|
|
404
|
-
|
|
405
|
-
When an API error omits `retryable`, the HTTP adapter classifies 4xx responses
|
|
406
|
-
as `false` and 5xx responses as `true`. This field is diagnostic classification
|
|
407
|
-
only. The SDK still makes one attempt and never retries a request automatically.
|
|
408
|
-
|
|
409
|
-
The Python package uses idiomatic specialized names for local failures. JavaScript `REQUEST_TIMEOUT` and `NETWORK_ERROR` map to Python `MitraNetworkError`, while JavaScript `INVALID_RESPONSE` maps to Python `MitraResponseError`. API responses use `MitraApiError` in both packages.
|
|
410
|
-
|
|
411
|
-
Every protected request sends `Authorization: Bearer <token>` and `X-App-Id`. Public Function
|
|
412
|
-
requests send neither header. Requests have no adapter-level deadline by default, so normal
|
|
413
|
-
long-running platform operations remain governed by the Server Function runtime. Set `timeoutMs`
|
|
414
|
-
to opt into a per-request deadline. Requests are never retried automatically, which avoids
|
|
415
|
-
replaying writes with unknown idempotency.
|
|
416
|
-
|
|
417
|
-
The access token is redacted from API error messages and error details.
|
|
418
|
-
|
|
419
|
-
## Contract parity
|
|
420
|
-
|
|
421
|
-
The test suite reads SDK-PARITY-001 version 0.2.0-beta.1 directly from the installed
|
|
422
|
-
`@mitralab.io/sdk-core` package. The `sdk-core-v0.2.0-beta.1` manifest pins the expected package
|
|
423
|
-
version, contract path, SHA-256 digest, and immutable source commit. The release gate rejects
|
|
424
|
-
publication unless the installed corpus matches its raw GitHub source byte for byte.
|
|
425
|
-
|
|
426
|
-
The JavaScript consumer requirement is exactly `httpAdapterCases: all`. Tests
|
|
427
|
-
execute all recorded 404, 503, and timeout cases through the public client and
|
|
428
|
-
the real `HttpClient`, using a mock fetch only at the network boundary. They
|
|
429
|
-
verify the request and the complete error semantics. Continuous integration and
|
|
430
|
-
release gates also download the canonical file from the public Core repository
|
|
431
|
-
at the pinned commit and compare it byte for byte with the installed package.
|
|
432
|
-
|
|
433
|
-
## Scope
|
|
434
|
-
|
|
435
|
-
The current draft expands the native client from the initial runtime operations to the complete
|
|
436
|
-
Core 0.2.0-beta.1 module surface listed above. Availability still depends on the runtime token
|
|
437
|
-
resources and the service constraints in the authorization matrix.
|
|
438
|
-
|
|
439
|
-
## Legacy compatibility
|
|
440
|
-
|
|
441
|
-
The runtime and type surface of `mitra-sdk@1.0.63-beta.39` is re-exported so existing Server
|
|
442
|
-
Function code can adopt `@mitralab.io/functions-sdk` without an import rewrite. Browser-only
|
|
443
|
-
bindings that exist only in `mitra-interactions-sdk`, including login and token refresh, are not
|
|
444
|
-
part of this package. Every re-export is the legacy binding itself, unchanged, and is marked
|
|
445
|
-
`@deprecated` with the new equivalent when one exists. Native raw SQL is available through `sql`;
|
|
446
|
-
app authoring and Agent runtime modules cover most builder and Agent SDK operations. Builder-specific
|
|
447
|
-
Git and direct-S3 flows have no one-to-one replacement and remain supported through the legacy
|
|
448
|
-
exports. Live Agent sessions have a native replacement through `agentTasks.session()`.
|
|
449
|
-
|
|
450
|
-
`getGitConfigMitra` remains legacy-only because credential minting is an internal Sandbox POST
|
|
451
|
-
authenticated between services and is not published for app tokens. The Sandbox already owns Git
|
|
452
|
-
setup and token renewal for Agent workspaces; the native Functions client does not expose that
|
|
453
|
-
secret-producing endpoint.
|
|
454
|
-
|
|
455
|
-
```typescript
|
|
456
|
-
import { createClient, listProjectsMitra } from "@mitralab.io/functions-sdk"
|
|
457
|
-
|
|
458
|
-
createClient()
|
|
459
|
-
const projects = await listProjectsMitra()
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
`createClient()` and `createClientFromEnvironment()` configure the deprecated SDK with
|
|
463
|
-
`MITRA_BASE_URL`, the resolved access token, and the app ID, so legacy code does not read the
|
|
464
|
-
environment itself. Native modules use the canonical API root directly and never route through the
|
|
465
|
-
BFF, even when that root was derived from an existing `MITRA_BASE_URL` value.
|
|
466
|
-
For explicit local configuration, `legacyBaseUrl` selects the deprecated BFF base; it falls back to
|
|
467
|
-
`apiUrl` only when omitted. The deprecated SDK receives `appId` as its `projectId` and accepts the
|
|
468
|
-
access token with or without a `Bearer` prefix.
|
|
469
|
-
|
|
470
|
-
The direct legacy dependency is pinned to the exact `mitra-sdk` version. Nothing in it is modified
|
|
471
|
-
or published by this package.
|
|
472
|
-
|
|
473
|
-
## Development
|
|
93
|
+
## Desenvolvimento
|
|
474
94
|
|
|
475
95
|
```bash
|
|
476
|
-
npm
|
|
96
|
+
npm ci
|
|
477
97
|
npm run check
|
|
478
98
|
```
|
|
479
99
|
|
|
480
|
-
|
|
481
|
-
registry, so the checked-in `package-lock.json` carries the registry `resolved` URL and integrity
|
|
482
|
-
for that exact version and `npm ci` reproduces it. Do not use a `file:` dependency or `npm link`.
|
|
483
|
-
|
|
484
|
-
To validate against a Core build that is not published yet, supply a tarball without changing
|
|
485
|
-
dependency metadata or the final lockfile:
|
|
486
|
-
|
|
487
|
-
```bash
|
|
488
|
-
npm install --no-save --package-lock=false /path/to/mitralab.io-sdk-core-0.2.0-beta.1.tgz
|
|
489
|
-
npm run lint && npm run typecheck && npm test && npm run build
|
|
490
|
-
MITRA_SDK_CORE_TARBALL=/path/to/mitralab.io-sdk-core-0.2.0-beta.1.tgz npm run smoke:package
|
|
491
|
-
git diff --exit-code -- package-lock.json
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
## Release order
|
|
495
|
-
|
|
496
|
-
Core moves first, then this package follows. `<core-version>` below is the Core release being
|
|
497
|
-
adopted, for example `0.2.0-beta.1`.
|
|
498
|
-
|
|
499
|
-
1. Merge and publish `@mitralab.io/sdk-core@<core-version>` under npm's `beta` dist-tag from its
|
|
500
|
-
immutable source commit.
|
|
501
|
-
2. Add `contracts/sdk-core-v<core-version>.manifest.json` carrying that full commit SHA:
|
|
502
|
-
|
|
503
|
-
```json
|
|
504
|
-
{
|
|
505
|
-
"source": {
|
|
506
|
-
"repository": "https://github.com/mitralab-dev/mitra-core-sdk",
|
|
507
|
-
"commit": "<full-core-commit-sha>",
|
|
508
|
-
"path": "contracts/v<core-version>/sdk-parity.json"
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
```
|
|
512
|
-
|
|
513
|
-
Point `scripts/check-contract-corpus.mjs` and the tests that read a manifest at the new file, so
|
|
514
|
-
the gate verifies the version being adopted.
|
|
515
|
-
|
|
516
|
-
3. Run `npm install --package-lock-only`, then verify that the Core lock entry is exactly
|
|
517
|
-
`<core-version>` with an npm registry URL and integrity.
|
|
518
|
-
4. Run `npm ci`, `npm run check`, and `npm run check:contracts:source`.
|
|
519
|
-
5. Publish this package under npm's `beta` dist-tag through the release workflow and run the
|
|
520
|
-
tarball smoke against the registry.
|
|
521
|
-
|
|
522
|
-
Steps 1 to 3 are already done for the current `0.2.0-beta.1` pin: Core is published, the manifest
|
|
523
|
-
carries its immutable source commit, and the lock records the registry `resolved` URL and integrity.
|
|
524
|
-
Steps 4 and 5 remain.
|
|
525
|
-
|
|
526
|
-
Stable `X.Y.Z` releases use npm's default `latest` dist-tag. The workflow accepts only that stable
|
|
527
|
-
form or the prerelease form `X.Y.Z-beta.N`.
|
|
528
|
-
|
|
529
|
-
`prepublishOnly` repeats the immutable-source check, so a direct `npm publish` cannot bypass the
|
|
530
|
-
pending Core provenance.
|
|
531
|
-
|
|
532
|
-
The contract source can be checked explicitly without changing the manifest or
|
|
533
|
-
lockfile:
|
|
534
|
-
|
|
535
|
-
```bash
|
|
536
|
-
node scripts/check-contract-corpus.mjs --canonical /path/to/sdk-parity.json
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
The package builds ESM, CommonJS, and TypeScript declarations in `dist/`. Tests enforce at least 80 percent coverage for lines, functions, branches, and statements.
|
|
100
|
+
O `check` roda format, lint, typecheck, testes, build, a conferência dos exports e do contrato com o Core, e um smoke test do pacote. A publicação no npm sai do workflow Release.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contract": "SDK-PARITY-001",
|
|
3
|
+
"version": "0.2.12-beta.1",
|
|
4
|
+
"dependency": {
|
|
5
|
+
"package": "@mitralab.io/sdk-core",
|
|
6
|
+
"version": "0.2.12-beta.1",
|
|
7
|
+
"contractPath": "contracts/v0.2.12-beta.1/sdk-parity.json"
|
|
8
|
+
},
|
|
9
|
+
"sha256": "272749b53557c5bd2a2160f6eed071933f22bd9b1d14c55e610a875f54e29ac3",
|
|
10
|
+
"source": {
|
|
11
|
+
"repository": "https://github.com/mitralab-dev/mitra-core-sdk",
|
|
12
|
+
"commit": "bbbf59254db9ccff87ea93e5f5ad1a29c278c5df",
|
|
13
|
+
"path": "contracts/v0.2.12-beta.1/sdk-parity.json"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contract": "SDK-PARITY-001",
|
|
3
|
+
"version": "0.2.12",
|
|
4
|
+
"dependency": {
|
|
5
|
+
"package": "@mitralab.io/sdk-core",
|
|
6
|
+
"version": "0.2.12",
|
|
7
|
+
"contractPath": "contracts/v0.2.12/sdk-parity.json"
|
|
8
|
+
},
|
|
9
|
+
"sha256": "685238cadcf898128a5dad60c30bcdd8dcc9a02f03077d765aee01f8d6e34709",
|
|
10
|
+
"source": {
|
|
11
|
+
"repository": "https://github.com/mitralab-dev/mitra-core-sdk",
|
|
12
|
+
"commit": "8a9bed056b49f3ffba79bd1acf14609c71e2abb4",
|
|
13
|
+
"path": "contracts/v0.2.12/sdk-parity.json"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mitralab.io/functions-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "JavaScript and TypeScript SDK for Mitra Server Functions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"node": ">=18.0.0"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@mitralab.io/sdk-core": "0.2.
|
|
70
|
+
"@mitralab.io/sdk-core": "0.2.12",
|
|
71
71
|
"mitra-sdk": "1.0.63-beta.42"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|