@apteva/web-sdk 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +224 -33
- package/dist/apps.d.ts +34 -0
- package/dist/apps.d.ts.map +1 -0
- package/dist/apps.js +30 -0
- package/dist/apps.js.map +1 -0
- package/dist/client.d.ts +34 -11
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +350 -121
- package/dist/client.js.map +1 -1
- package/dist/components.d.ts +42 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +36 -0
- package/dist/components.js.map +1 -0
- package/dist/extensions.d.ts +17 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +4 -0
- package/dist/extensions.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +28 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0 — 2026-09-07
|
|
4
|
+
|
|
5
|
+
- Add typed app-owned extensions through `defineAppExtension` and `client.use`.
|
|
6
|
+
- Add project/install-scoped app handles, HTTP/MCP request options, and app SSE subscriptions sharing live client credentials.
|
|
7
|
+
- Add framework-independent component references, manifest metadata types and a local export registry.
|
|
8
|
+
- Expose installed-app discovery and explicit metadata/version compatibility checks.
|
|
9
|
+
- Fix caller cancellation being overridden by request timeouts; retain cancellation and timeouts through response-body reads.
|
|
10
|
+
- Add abortable fetch subscriptions with SSE resume IDs, optional cursor queries, bounded opt-in deduplication, configurable reconnect delay and terminal auth handling.
|
|
11
|
+
- Add coordinated host-owned access-token renewal without automatically replaying HTTP requests.
|
|
12
|
+
- Preserve legacy Channel Chat APIs; app-specific extensions and UI stay in app-owned packages.
|
|
13
|
+
|
|
14
|
+
## 0.5.5 — 2026-08-15
|
|
15
|
+
|
|
16
|
+
- Add a generic, opaque `accessToken` credential to `AptevaClient`, including
|
|
17
|
+
runtime `setAccessToken(...)` and `getAccessToken()` helpers. The SDK is not
|
|
18
|
+
coupled to Auth or any other token issuer.
|
|
19
|
+
- Give `accessToken` precedence over `apiKey`, send it only in the Bearer
|
|
20
|
+
header, omit cookies, and force authenticated fetch streaming for SSE.
|
|
21
|
+
- Keep legacy `apiKey: "uk_…"` behavior as a compatibility fallback while
|
|
22
|
+
removing token-prefix inference from the recommended integration.
|
|
23
|
+
- Deprecate the Channel Chat-specific `client.delegatedUsers.create(...)`
|
|
24
|
+
flow in favor of server-policy-controlled application-user tokens.
|
|
25
|
+
|
|
3
26
|
## 0.5.4 — 2026-08-13
|
|
4
27
|
|
|
5
28
|
- Add `client.delegatedUsers.create(...)` for trusted-backend minting of
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Browser SDK for calling [apteva-server](https://github.com/apteva/server). Framework-agnostic. ~3 KB minified + gzipped.
|
|
4
4
|
|
|
5
|
-
- **Auth** — session cookies,
|
|
5
|
+
- **Auth transport** — session cookies, private API keys, and opaque application-user access tokens. The SDK does not depend on a particular token issuer.
|
|
6
6
|
- **App data** — `client.app("crm").get("/contacts")` reverse-proxies through `/api/apps/<name>/*`.
|
|
7
7
|
- **App tools** — `client.app("crm").tool("contacts_search", {…})` posts an MCP `tools/call`, unwraps the JSON-RPC envelope, returns the tool's natural shape.
|
|
8
8
|
- **Static-app mode** — when the UI is hosted by apteva-server itself (`runtime.kind: static`), `pickBaseURL` and `pickKioskKey` read the `<script>window.__APTEVA_APP__</script>` block the server injects.
|
|
@@ -22,8 +22,7 @@ import { AptevaClient } from "@apteva/web-sdk";
|
|
|
22
22
|
|
|
23
23
|
const apteva = new AptevaClient({
|
|
24
24
|
baseURL: "https://agents.example.com",
|
|
25
|
-
// Optional. Omit to rely on
|
|
26
|
-
apiKey: process.env.NEXT_PUBLIC_APTEVA_KEY,
|
|
25
|
+
// Optional. Omit to rely on an apteva-server session cookie.
|
|
27
26
|
});
|
|
28
27
|
|
|
29
28
|
// Sign in (sets the session cookie on the apteva-server domain).
|
|
@@ -40,22 +39,36 @@ const { leads } = await apteva.app("flexylead").tool<{ leads: Lead[] }>(
|
|
|
40
39
|
);
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
##
|
|
42
|
+
## Authentication carriers
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
With no bearer credential, the SDK sends `credentials: "include"` so an
|
|
45
|
+
apteva-server session cookie flows automatically. Private platform integrations
|
|
46
|
+
can provide `apiKey`. Browser applications should provide an opaque
|
|
47
|
+
`accessToken` issued by their trusted authentication flow.
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
`accessToken` takes precedence over `apiKey`. It is sent only through the
|
|
50
|
+
`Authorization: Bearer` header, cookie credentials are omitted, and SSE uses
|
|
51
|
+
authenticated `fetch()` streaming. The SDK does not inspect its prefix or know
|
|
52
|
+
whether Auth, another Apteva app, or a customer service issued it.
|
|
48
53
|
|
|
49
54
|
```ts
|
|
50
55
|
const apteva = new AptevaClient({
|
|
51
56
|
baseURL: "...",
|
|
52
|
-
|
|
57
|
+
accessToken: loginResult.apteva_access_token, // application user
|
|
58
|
+
// apiKey: process.env.APTEVA_API_KEY, // trusted backend only
|
|
53
59
|
projectId: "proj_123", // routes project-scoped app HTTP and MCP calls
|
|
54
60
|
onUnauthorized: () => router.push("/login"), // fires once per 401
|
|
55
61
|
timeoutMs: 30_000, // default, 0 disables
|
|
56
62
|
});
|
|
63
|
+
|
|
64
|
+
// Replace an expired token without rebuilding the client.
|
|
65
|
+
apteva.setAccessToken(refreshed.apteva_access_token);
|
|
57
66
|
```
|
|
58
67
|
|
|
68
|
+
The example above deliberately leaves login outside the SDK. Auth can return
|
|
69
|
+
`apteva_access_token`, but the Web SDK remains decoupled and accepts any opaque
|
|
70
|
+
bearer token that apteva-server recognizes.
|
|
71
|
+
|
|
59
72
|
## App HTTP routes
|
|
60
73
|
|
|
61
74
|
`client.app(name)` returns a handle with `get / post / put / patch / del` that route to `/api/apps/<name>/<path>`. Same auth, same proxy, same error model.
|
|
@@ -80,6 +93,185 @@ If the MCP call returns a JSON-RPC error, the SDK throws `AptevaError(-1, messag
|
|
|
80
93
|
|
|
81
94
|
For lower-level usage, `client.callTool(appName, toolName, args)` and the standalone `unwrapMCP(envelope)` are both exported.
|
|
82
95
|
|
|
96
|
+
## App-owned extensions and web components
|
|
97
|
+
|
|
98
|
+
Apps can publish a headless client and frontend components from their own
|
|
99
|
+
versioned package. The core SDK supplies transport, component references, and
|
|
100
|
+
metadata checks; it has no React dependency and does not import executable UI
|
|
101
|
+
from a server. A dashboard wrapper and an external package can share the same
|
|
102
|
+
component source, receiving an app handle instead of implementing authentication
|
|
103
|
+
and requests again.
|
|
104
|
+
|
|
105
|
+
### Typed extensions
|
|
106
|
+
|
|
107
|
+
`defineAppExtension` preserves the extension's return type. `client.use` supplies
|
|
108
|
+
an authenticated app handle. Each call creates a new instance: retain it in your
|
|
109
|
+
host (for example with React's `useMemo`), and close subscriptions when unmounting.
|
|
110
|
+
An async `create` is supported; `use` then returns its Promise unchanged.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { AptevaClient, defineAppExtension } from "@apteva/web-sdk";
|
|
114
|
+
|
|
115
|
+
// Illustrative app-owned API. Replace routes and wire types with your app's contract.
|
|
116
|
+
const itemsExtension = defineAppExtension({
|
|
117
|
+
app: "example",
|
|
118
|
+
create: ({ app }) => ({
|
|
119
|
+
list: (signal?: AbortSignal) =>
|
|
120
|
+
app.get<Array<{ id: string; title: string }>>("/items", { signal }),
|
|
121
|
+
}),
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const client = new AptevaClient({ baseURL: "https://agents.example.com", accessToken });
|
|
125
|
+
const items = client.use(itemsExtension, { projectId: "p1", installId: 42 });
|
|
126
|
+
const rows = await items.list(); // typed result
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Extensions contain the app's own business logic and API contract validation.
|
|
130
|
+
A Conversations extension and its chat, inbox, and approval UI belong in the
|
|
131
|
+
Conversations package. The existing `client.chat` remains a Channel Chat API;
|
|
132
|
+
it is not redirected to Conversations.
|
|
133
|
+
|
|
134
|
+
### Shared app transport
|
|
135
|
+
|
|
136
|
+
`client.app(name, { projectId, installId })` scopes HTTP, MCP, and subscriptions
|
|
137
|
+
together. It exposes `name`, `projectId`, and `installId` for host context and
|
|
138
|
+
reads the client's current credentials on each request or reconnection.
|
|
139
|
+
Explicit handle scope overrides routing query parameters. With no explicit
|
|
140
|
+
project scope, the existing client default and query-override behavior remain.
|
|
141
|
+
The platform still validates the selected installation and project.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const app = client.app("example", { projectId: "p1", installId: 42 });
|
|
145
|
+
const controller = new AbortController();
|
|
146
|
+
|
|
147
|
+
await app.post("/items", { title: "Hello" }, { signal: controller.signal });
|
|
148
|
+
await app.tool("items_list", {}, { signal: controller.signal });
|
|
149
|
+
|
|
150
|
+
const subscription = app.subscribe<{ id: string; title: string }>(
|
|
151
|
+
"/events",
|
|
152
|
+
(row, metadata) => console.log(row, metadata.event, metadata.id),
|
|
153
|
+
{ signal: controller.signal, eventTypes: ["item.updated"] },
|
|
154
|
+
);
|
|
155
|
+
subscription.close();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
All HTTP helpers accept `RequestInit`; MCP accepts it as the third argument.
|
|
159
|
+
Cancellation works alongside the client timeout, including while reading the
|
|
160
|
+
response body. App paths must start with `/` and remain inside the app route.
|
|
161
|
+
Use the raw client methods for platform endpoints. No HTTP method is retried
|
|
162
|
+
automatically. Pass an app-supported idempotency header or body field explicitly
|
|
163
|
+
when the app contract permits a write to be retried.
|
|
164
|
+
|
|
165
|
+
### Component exports and manifest metadata
|
|
166
|
+
|
|
167
|
+
`AppComponentReference` is the existing `{ app, name, props? }` message shape;
|
|
168
|
+
`ChatComponent` remains a compatible name. `AppComponentSpec` mirrors existing
|
|
169
|
+
`provides.ui_components` metadata, including slots, prop schemas and widget
|
|
170
|
+
settings. There is no second server declaration format.
|
|
171
|
+
|
|
172
|
+
`AppComponentRegistry<T>` maps those app/component names to local frontend
|
|
173
|
+
exports. It accepts framework-specific components or host-owned loaders without
|
|
174
|
+
adding a framework dependency. Registration rejects duplicate names atomically
|
|
175
|
+
and returns an idempotent unregister function; unknown references resolve to
|
|
176
|
+
`undefined` so the host can render a fallback.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import { AppComponentRegistry } from "@apteva/web-sdk";
|
|
180
|
+
import { ItemCard } from "./components/ItemCard"; // or an app-owned frontend package
|
|
181
|
+
|
|
182
|
+
const components = new AppComponentRegistry<typeof ItemCard>();
|
|
183
|
+
const unregister = components.register("example", { "item-card": ItemCard });
|
|
184
|
+
const Component = components.resolve({ app: "example", name: "item-card" });
|
|
185
|
+
// Render Component using your framework and validated, appropriate props.
|
|
186
|
+
unregister();
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`AppComponentContext` defines a host-injected `app: AppHandle`. Pass this trusted
|
|
190
|
+
context separately from message data; do not let message props replace it.
|
|
191
|
+
The host handles rendering, slots, schema validation, loading/error boundaries,
|
|
192
|
+
theme and component lifecycle. Registry membership alone does not establish
|
|
193
|
+
installation, compatibility, identity or authorization. Existing dashboard
|
|
194
|
+
module loading remains a host concern; installing this SDK does not port an
|
|
195
|
+
existing component's fetch calls or styling automatically.
|
|
196
|
+
|
|
197
|
+
### Installed-app discovery and compatibility
|
|
198
|
+
|
|
199
|
+
`client.apps.list({ projectId? }, requestInit?)` wraps the existing `/api/apps`
|
|
200
|
+
endpoint and defaults to the client's project. This endpoint retains its current
|
|
201
|
+
platform permissions; application-user tokens are not guaranteed access. Hosts
|
|
202
|
+
can instead supply metadata they have already obtained through an authorized
|
|
203
|
+
flow. Extension setup does not automatically perform discovery.
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
import { checkAppCompatibility, assertAppCompatibility } from "@apteva/web-sdk";
|
|
207
|
+
|
|
208
|
+
const installed = (await client.apps.list()).find(app => app.install_id === 42);
|
|
209
|
+
const requirements = {
|
|
210
|
+
app: "example",
|
|
211
|
+
version: { description: "1.x", accepts: (version: string) => version.startsWith("1.") },
|
|
212
|
+
tools: ["items_list"],
|
|
213
|
+
components: ["item-card"],
|
|
214
|
+
};
|
|
215
|
+
const result = checkAppCompatibility(installed, requirements); // { compatible, issues }
|
|
216
|
+
assertAppCompatibility(installed, requirements); // AptevaError if incompatible
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Version policy belongs to the app package: supply a predicate (including a semver
|
|
220
|
+
library if needed). These checks validate advertised app identity, version,
|
|
221
|
+
tools and components. They do not infer API schema versions, backend health,
|
|
222
|
+
permissions or unadvertised capabilities. App extensions should separately
|
|
223
|
+
validate any app-owned versioned API contract they require.
|
|
224
|
+
|
|
225
|
+
### Subscription recovery
|
|
226
|
+
|
|
227
|
+
Generic subscriptions accept `signal`; already-aborted signals open no connection.
|
|
228
|
+
Bearer credentials use authenticated fetch streaming. Cookie clients can opt into
|
|
229
|
+
fetch with `transport: "fetch"`. `lastEventId`, `cursorParam`, `deduplicate`, and
|
|
230
|
+
`reconnectDelayMs` also select fetch streaming, even if an EventSource was supplied.
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
const subscription = app.subscribe("/events", onEvent, {
|
|
234
|
+
signal: controller.signal,
|
|
235
|
+
lastEventId: savedEventId,
|
|
236
|
+
cursorParam: "since_id", // only if this app accepts SSE IDs here
|
|
237
|
+
deduplicate: true, // only if the app promises unique IDs per event
|
|
238
|
+
deduplicationWindow: 1000,
|
|
239
|
+
reconnectDelayMs: 1000,
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Fetch streams preserve SSE IDs across reconnects, send `Last-Event-ID`, and
|
|
244
|
+
optionally send the same ID in the app's cursor query parameter. Deduplication
|
|
245
|
+
is opt-in and bounded to the most recent 1000 delivered IDs by default; ID-less
|
|
246
|
+
updates are always delivered. It does not persist across new subscriptions.
|
|
247
|
+
Message-row IDs and SSE IDs are not interchangeable unless the backend says so.
|
|
248
|
+
Named events still require `eventTypes`. Malformed JSON is skipped; a throwing
|
|
249
|
+
fetch-stream event/open callback is reported and closes the subscription.
|
|
250
|
+
|
|
251
|
+
Reconnect delay defaults to 1000ms. Closing or aborting cancels the active reader
|
|
252
|
+
and any pending reconnect. Fetch streams stop on 204 or 403, and on 401 unless
|
|
253
|
+
credentials can be renewed once before a successful connection. Other failures
|
|
254
|
+
reconnect. Native EventSource retains the browser's own reconnect behavior.
|
|
255
|
+
The SDK cannot supply replay, a gap-free history/live handoff, or durable delivery
|
|
256
|
+
unless the app backend implements those contracts.
|
|
257
|
+
|
|
258
|
+
### Host-owned credential renewal
|
|
259
|
+
|
|
260
|
+
Configure `refreshAccessToken: async () => tokenOrUndefined` on the client to
|
|
261
|
+
reuse your own authentication flow. Concurrent 401s coordinate one in-flight
|
|
262
|
+
refresh. `client.refreshAccessToken()` can also be called proactively; it returns
|
|
263
|
+
whether a new token was applied. A login/logout/token replacement during a
|
|
264
|
+
refresh wins over the late result. An undefined result leaves credentials intact.
|
|
265
|
+
|
|
266
|
+
A failed HTTP request still throws its original 401 and triggers `onUnauthorized`
|
|
267
|
+
after the renewal attempt; it is never replayed. Subsequent calls use the new
|
|
268
|
+
token. Requests with a caller-supplied Authorization header do not trigger
|
|
269
|
+
renewal. Fetch SSE can reconnect once with renewed credentials; another 401
|
|
270
|
+
before a successful connection terminates the subscription. Automatic renewal
|
|
271
|
+
failure preserves the original 401; direct `refreshAccessToken()` calls expose
|
|
272
|
+
hook errors. The SDK transports opaque credentials and makes no identity or
|
|
273
|
+
permission decisions.
|
|
274
|
+
|
|
83
275
|
## Agents
|
|
84
276
|
|
|
85
277
|
`client.agents` wraps the core `/api/agents/*` routes — the running apteva-core child processes.
|
|
@@ -149,7 +341,10 @@ sub.close();
|
|
|
149
341
|
|
|
150
342
|
For any other SSE endpoint, `client.subscribe(path, params, onEvent, opts?)` is the generic form `telemetry.stream` is built on.
|
|
151
343
|
|
|
152
|
-
With an API key, `subscribe`/`stream` use authenticated fetch
|
|
344
|
+
With an API key or access token, `subscribe`/`stream` use authenticated fetch
|
|
345
|
+
streaming and send the credential in the `Authorization` header. Access tokens
|
|
346
|
+
are never placed in query strings. Cookie-authenticated clients use native
|
|
347
|
+
`EventSource`; in runtimes without it, pass a polyfill via `opts.EventSource`.
|
|
153
348
|
|
|
154
349
|
## Chat
|
|
155
350
|
|
|
@@ -201,27 +396,20 @@ sub.close();
|
|
|
201
396
|
|
|
202
397
|
Always address Channel Chat with `chat.id`. `thread_id` is informational and must not be used for message delivery. `instance_id` is a legacy response alias; new code should use `agent_id`.
|
|
203
398
|
|
|
204
|
-
For a website user who is not an Apteva account,
|
|
205
|
-
|
|
399
|
+
For a logged-in website user who is not an Apteva platform account, initialize
|
|
400
|
+
the SDK with the application-user token returned by the site's authentication
|
|
401
|
+
flow:
|
|
206
402
|
|
|
207
403
|
```ts
|
|
208
|
-
//
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
subjectType: "website_user",
|
|
214
|
-
subjectId: authenticatedSiteUser.id,
|
|
215
|
-
agentId: 4,
|
|
216
|
-
allowedOrigins: ["https://customer.example"],
|
|
217
|
-
conversationDirective: "Help this visitor choose a subscription plan.",
|
|
218
|
-
expiresIn: 3600,
|
|
219
|
-
});
|
|
404
|
+
// `login` belongs to the website/Auth integration, not @apteva/web-sdk.
|
|
405
|
+
const login = await websiteAuth.login(email, password);
|
|
406
|
+
if (!login.apteva_access_token) {
|
|
407
|
+
throw new Error("No Apteva access policy is configured for this client");
|
|
408
|
+
}
|
|
220
409
|
|
|
221
|
-
// Return token.access_token to that authenticated website user. Browser code:
|
|
222
410
|
const browserClient = new AptevaClient({
|
|
223
411
|
baseURL: "https://agents.example.com",
|
|
224
|
-
|
|
412
|
+
accessToken: login.apteva_access_token,
|
|
225
413
|
});
|
|
226
414
|
const chat = await browserClient.chat.createOrResume(4, {
|
|
227
415
|
title: "Customer support",
|
|
@@ -236,15 +424,16 @@ const lastMessage = history.at(-1);
|
|
|
236
424
|
if (lastMessage) await browserClient.chat.markSeen(chat.id, lastMessage.id);
|
|
237
425
|
```
|
|
238
426
|
|
|
239
|
-
The browser never submits `subject_id`, `project_id`, or a directive
|
|
240
|
-
creates the conversation.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
`
|
|
244
|
-
|
|
245
|
-
|
|
427
|
+
The browser never submits `subject_id`, `project_id`, scopes, or a directive
|
|
428
|
+
when it creates the conversation. Trusted identity comes from the credential;
|
|
429
|
+
server policy selects permitted apps, actions, and agent IDs; Channel Chat
|
|
430
|
+
enforces its chat-specific resources. Reusing the same subject, project, agent,
|
|
431
|
+
and `conversationKey` atomically resumes the same conversation.
|
|
432
|
+
|
|
433
|
+
`client.delegatedUsers.create(...)` remains available for older trusted-backend
|
|
434
|
+
integrations, but is deprecated and is no longer the recommended website flow.
|
|
246
435
|
|
|
247
|
-
**Rendering note:** `ChatMessage.components[]` carries the agent's `respond(components=…)` attachments.
|
|
436
|
+
**Rendering note:** `ChatMessage.components[]` carries the agent's `respond(components=…)` attachments. Use `AppComponentRegistry` to resolve these references against app-owned frontend exports, then render them in your host framework. The SDK does not dynamically load server-provided UI.
|
|
248
437
|
|
|
249
438
|
A complete reference chat UI (message list, composer, streaming bubbles, optimistic send) lives in [`examples/dashboard/src/components/ChatCard.tsx`](./examples/dashboard/src/components/ChatCard.tsx).
|
|
250
439
|
|
|
@@ -284,7 +473,9 @@ The same code also works fine when hosted externally (Vercel, etc.) — `pickBas
|
|
|
284
473
|
|
|
285
474
|
## SSE transports
|
|
286
475
|
|
|
287
|
-
Prefer `client.subscribe()` and the typed stream helpers. They select
|
|
476
|
+
Prefer `client.subscribe()` and the typed stream helpers. They select
|
|
477
|
+
authenticated fetch streaming for API keys and access tokens, and credentialed
|
|
478
|
+
native `EventSource` for cookie sessions. Access tokens never enter the URL.
|
|
288
479
|
|
|
289
480
|
`sseURL()` remains available for endpoints that explicitly accept an API key in the query string, or for external clients that must construct their own `EventSource`:
|
|
290
481
|
|
package/dist/apps.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AppComponentSpec } from "./components.js";
|
|
2
|
+
/** Relevant fields of the existing platform /api/apps response. */
|
|
3
|
+
export interface InstalledApp {
|
|
4
|
+
install_id: number;
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
project_id: string;
|
|
8
|
+
status: string;
|
|
9
|
+
display_name?: string;
|
|
10
|
+
source?: string;
|
|
11
|
+
ui_components?: AppComponentSpec[];
|
|
12
|
+
surfaces?: {
|
|
13
|
+
mcp_tool_names?: string[];
|
|
14
|
+
http_routes?: string[];
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface AppRequirements {
|
|
18
|
+
app: string;
|
|
19
|
+
/** App packages choose their version policy; no implied wire/API version. */
|
|
20
|
+
version?: {
|
|
21
|
+
description: string;
|
|
22
|
+
accepts(version: string): boolean;
|
|
23
|
+
};
|
|
24
|
+
tools?: readonly string[];
|
|
25
|
+
components?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
export interface AppCompatibility {
|
|
28
|
+
compatible: boolean;
|
|
29
|
+
issues: string[];
|
|
30
|
+
}
|
|
31
|
+
/** Checks advertised metadata only. This never grants access to an app. */
|
|
32
|
+
export declare function checkAppCompatibility(installed: InstalledApp | undefined, requirements: AppRequirements): AppCompatibility;
|
|
33
|
+
export declare function assertAppCompatibility(installed: InstalledApp | undefined, requirements: AppRequirements): void;
|
|
34
|
+
//# sourceMappingURL=apps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../src/apps.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACnC,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACrE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,2EAA2E;AAC3E,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,YAAY,GAAG,SAAS,EACnC,YAAY,EAAE,eAAe,GAC5B,gBAAgB,CAiBlB;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,YAAY,GAAG,SAAS,EACnC,YAAY,EAAE,eAAe,GAC5B,IAAI,CAGN"}
|
package/dist/apps.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AptevaError } from "./errors.js";
|
|
2
|
+
/** Checks advertised metadata only. This never grants access to an app. */
|
|
3
|
+
export function checkAppCompatibility(installed, requirements) {
|
|
4
|
+
const issues = [];
|
|
5
|
+
if (!installed) {
|
|
6
|
+
issues.push(`app ${requirements.app} is not installed`);
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
if (installed.name !== requirements.app)
|
|
10
|
+
issues.push(`expected app ${requirements.app}, got ${installed.name}`);
|
|
11
|
+
if (requirements.version && !requirements.version.accepts(installed.version)) {
|
|
12
|
+
issues.push(`version ${installed.version} does not satisfy ${requirements.version.description}`);
|
|
13
|
+
}
|
|
14
|
+
for (const tool of requirements.tools ?? []) {
|
|
15
|
+
if (!installed.surfaces?.mcp_tool_names?.includes(tool))
|
|
16
|
+
issues.push(`missing tool: ${tool}`);
|
|
17
|
+
}
|
|
18
|
+
for (const name of requirements.components ?? []) {
|
|
19
|
+
if (!installed.ui_components?.some((component) => component.name === name))
|
|
20
|
+
issues.push(`missing component: ${name}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return { compatible: issues.length === 0, issues };
|
|
24
|
+
}
|
|
25
|
+
export function assertAppCompatibility(installed, requirements) {
|
|
26
|
+
const result = checkAppCompatibility(installed, requirements);
|
|
27
|
+
if (!result.compatible)
|
|
28
|
+
throw new AptevaError(0, `incompatible app: ${result.issues.join("; ")}`);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=apps.js.map
|
package/dist/apps.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../src/apps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAgC1C,2EAA2E;AAC3E,MAAM,UAAU,qBAAqB,CACnC,SAAmC,EACnC,YAA6B;IAE7B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,CAAC,GAAG,mBAAmB,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,IAAI,SAAS,CAAC,IAAI,KAAK,YAAY,CAAC,GAAG;YAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,YAAY,CAAC,GAAG,SAAS,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAChH,IAAI,YAAY,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7E,MAAM,CAAC,IAAI,CAAC,WAAW,SAAS,CAAC,OAAO,qBAAqB,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACnG,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YAC5C,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;YACjD,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;QACxH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,SAAmC,EACnC,YAA6B;IAE7B,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,MAAM,IAAI,WAAW,CAAC,CAAC,EAAE,qBAAqB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACpG,CAAC"}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AppExtension, AppScope } from "./extensions.js";
|
|
2
|
+
import type { InstalledApp } from "./apps.js";
|
|
3
|
+
import type { Agent, AgentConfig, AgentCoreEvent, AgentCreateInput, AgentCreateResult, AgentDeleteResult, AgentPauseResult, AgentRestartResult, AgentStatus, AgentSystemMCPResult, AgentUpdateInput, AptevaClientOptions, AuthStatus, ChannelInfo, Chat, CreateChatOptions, CreateOrResumeChatOptions, ChatCreateResult, CreateDelegatedUserInput, DelegatedUserToken, ChatHistoryMessage, ChatMessage, ChatMessagesQuery, ChatSendInput, ChatSendOptions, ChatStreamOptions, MCPCallResponse, Project, StreamHandle, SubscribeOptions, SSEEventMetadata, TelemetryEvent, TelemetryPeriod, TelemetryQuery, TelemetryStats, Thread, TimelineBucket, UpdateChatOptions, User } from "./types.js";
|
|
2
4
|
export declare class AptevaClient {
|
|
3
5
|
private readonly baseURL;
|
|
4
6
|
private apiKey?;
|
|
7
|
+
private accessToken?;
|
|
5
8
|
private readonly projectId?;
|
|
6
9
|
private readonly fetchImpl;
|
|
7
10
|
private readonly onUnauthorized?;
|
|
8
11
|
private readonly timeoutMs;
|
|
12
|
+
private readonly refreshTokenHook?;
|
|
13
|
+
private credentialRevision;
|
|
14
|
+
private pendingTokenRefresh?;
|
|
9
15
|
private readonly pendingChatResolutions;
|
|
10
16
|
constructor(opts: AptevaClientOptions);
|
|
11
17
|
setApiKey(key: string | undefined): void;
|
|
12
18
|
getApiKey(): string | undefined;
|
|
19
|
+
setAccessToken(token: string | undefined): void;
|
|
20
|
+
getAccessToken(): string | undefined;
|
|
21
|
+
/** Refresh once for concurrent callers. Undefined leaves credentials unchanged. */
|
|
22
|
+
refreshAccessToken(): Promise<boolean>;
|
|
23
|
+
private renewAfterUnauthorized;
|
|
13
24
|
readonly auth: {
|
|
14
25
|
register: (email: string, password: string, name?: string) => Promise<{
|
|
15
26
|
user: User;
|
|
@@ -34,6 +45,7 @@ export declare class AptevaClient {
|
|
|
34
45
|
list: () => Promise<Project[]>;
|
|
35
46
|
get: (id: string) => Promise<Project>;
|
|
36
47
|
};
|
|
48
|
+
/** @deprecated Prefer AptevaClient({ accessToken }). */
|
|
37
49
|
readonly delegatedUsers: {
|
|
38
50
|
create: (input: CreateDelegatedUserInput) => Promise<DelegatedUserToken>;
|
|
39
51
|
};
|
|
@@ -57,7 +69,7 @@ export declare class AptevaClient {
|
|
|
57
69
|
togglePause: (id: number) => Promise<AgentPauseResult>;
|
|
58
70
|
event: <R = unknown>(id: number, body: Record<string, unknown>) => Promise<R>;
|
|
59
71
|
control: <R = unknown>(id: number, body: Record<string, unknown>) => Promise<R>;
|
|
60
|
-
events: <E = AgentCoreEvent>(id: number, onEvent: (event: E) => void, opts?: SubscribeOptions) => StreamHandle;
|
|
72
|
+
events: <E = AgentCoreEvent>(id: number, onEvent: (event: E, metadata: SSEEventMetadata) => void, opts?: SubscribeOptions) => StreamHandle;
|
|
61
73
|
};
|
|
62
74
|
readonly telemetry: {
|
|
63
75
|
query: (q: TelemetryQuery) => Promise<TelemetryEvent[]>;
|
|
@@ -82,29 +94,40 @@ export declare class AptevaClient {
|
|
|
82
94
|
last_seen_id: number;
|
|
83
95
|
}>;
|
|
84
96
|
};
|
|
85
|
-
app<T = unknown>(name: string): AppHandle<T>;
|
|
86
|
-
|
|
97
|
+
app<T = unknown>(name: string, scope?: AppScope): AppHandle<T>;
|
|
98
|
+
/** Create an extension instance. Retain it in the host; use() does not cache. */
|
|
99
|
+
use<T>(extension: AppExtension<T>, scope?: AppScope): T;
|
|
100
|
+
readonly apps: {
|
|
101
|
+
/** Requires the platform's existing app-list permission. No auth bypass. */
|
|
102
|
+
list: (scope?: Pick<AppScope, "projectId">, init?: RequestInit) => Promise<InstalledApp[]>;
|
|
103
|
+
};
|
|
104
|
+
callTool<R>(appName: string, toolName: string, args: Record<string, unknown>, init?: RequestInit): Promise<R>;
|
|
87
105
|
get<R>(path: string, init?: RequestInit): Promise<R>;
|
|
88
106
|
post<R>(path: string, body?: unknown, init?: RequestInit): Promise<R>;
|
|
89
107
|
put<R>(path: string, body?: unknown, init?: RequestInit): Promise<R>;
|
|
90
108
|
patch<R>(path: string, body?: unknown, init?: RequestInit): Promise<R>;
|
|
91
109
|
del<R>(path: string, init?: RequestInit): Promise<R>;
|
|
92
110
|
sseURL(path: string, params?: Record<string, string | number | undefined>): string;
|
|
93
|
-
subscribe<E>(path: string, params: Record<string, string | number | undefined> | undefined, onEvent: (event: E) => void, opts?: SubscribeOptions): StreamHandle;
|
|
111
|
+
subscribe<E>(path: string, params: Record<string, string | number | undefined> | undefined, onEvent: (event: E, metadata: SSEEventMetadata) => void, opts?: SubscribeOptions): StreamHandle;
|
|
94
112
|
private subscribeWithFetch;
|
|
95
113
|
private bindAbortSignal;
|
|
96
114
|
private appPath;
|
|
115
|
+
private bearerToken;
|
|
116
|
+
private isAccessTokenCredential;
|
|
97
117
|
private request;
|
|
98
118
|
}
|
|
99
119
|
export declare function unwrapMCP<R>(env: MCPCallResponse<unknown>): R;
|
|
100
120
|
export interface AppHandle<TDefault = unknown> {
|
|
101
121
|
readonly name: string;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
122
|
+
readonly projectId?: string;
|
|
123
|
+
readonly installId?: number;
|
|
124
|
+
get<R = TDefault>(path: string, init?: RequestInit): Promise<R>;
|
|
125
|
+
post<R = TDefault>(path: string, body?: unknown, init?: RequestInit): Promise<R>;
|
|
126
|
+
put<R = TDefault>(path: string, body?: unknown, init?: RequestInit): Promise<R>;
|
|
127
|
+
patch<R = TDefault>(path: string, body?: unknown, init?: RequestInit): Promise<R>;
|
|
128
|
+
del<R = TDefault>(path: string, init?: RequestInit): Promise<R>;
|
|
129
|
+
tool<R = TDefault>(name: string, args?: Record<string, unknown>, init?: RequestInit): Promise<R>;
|
|
130
|
+
subscribe<E>(path: string, onEvent: (event: E, metadata: SSEEventMetadata) => void, opts?: SubscribeOptions): StreamHandle;
|
|
108
131
|
mcpURL(queryParams?: Record<string, string>): string;
|
|
109
132
|
}
|
|
110
133
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,IAAI,EACJ,iBAAiB,EACjB,yBAAyB,EACzB,gBAAgB,EAChB,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,iBAAiB,EAEjB,eAAe,EACf,OAAO,EAEP,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,MAAM,EACN,cAAc,EACd,iBAAiB,EACjB,IAAI,EACL,MAAM,YAAY,CAAC;AAIpB,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAa;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoC;gBAE/D,IAAI,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|