@runmark/sdk 0.1.0 → 0.1.3

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 ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ## 0.1.3
6
+
7
+ - Add typed repository runtime webhook management, evidence pagination, replay, rotation status,
8
+ run/HITL fetch helpers, and a Standard Webhooks-compatible signature verifier.
9
+ - Add immutable `dev`/`main` endpoint lanes, strict all/selected-agent scopes, disabled-first test
10
+ setup, repository-wide delivery search/detail APIs, deleted-endpoint history, and claimed attempt
11
+ URL/timestamp/secret-revision/next-retry evidence.
12
+
13
+ ## 0.1.2
14
+
15
+ - Add request-ID submission and lookup, durable cancellation, HITL request
16
+ correlation, active-organization forwarding, and replay-cursor contracts.
17
+ - Add durable response/error types and preserve typed API error codes.
18
+ - Validate and bound JSON/SSE responses, including fragmented CRLF events,
19
+ malformed envelopes, oversized bodies/events, and reader cancellation.
package/README.md CHANGED
@@ -1,81 +1,273 @@
1
- # @skyforge-ai/sdk
1
+ # @runmark/sdk
2
+
3
+ Runtime lifecycle webhooks use Standard Webhooks signatures and at-least-once delivery. Use
4
+ `verifyWebhookSignature` against the exact raw request bytes before parsing JSON, reject timestamps
5
+ outside the default five-minute window, and deduplicate on the immutable event `id`. Delivery order
6
+ may differ from the run-local `sequence`; use the repository-bound `cursor` for replay ranges.
7
+
8
+ Webhook payloads are intentionally minimized. Follow the version-pinned run and human-action URLs
9
+ with an authorized repository token when full evidence is required. Endpoint secrets are shown only
10
+ once when created or rotated, and overlapping revisions remain valid for 24 hours.
11
+
12
+ Endpoints are created disabled and bind immutably to the exact lowercase `dev` or `main` lane.
13
+ Configure an explicit `agent_scope`, send a targeted test while disabled, then enable the endpoint.
14
+ Use `skyforge.webhooks.listRepositoryDeliveries(...)` for repository-wide server-side search and
15
+ cursor pagination, and `skyforge.webhooks.getDelivery(...)` to retrieve the exact persisted body and
16
+ claimed URL/timestamp/revision evidence for every retained attempt. Endpoint edits and rotations
17
+ affect later claims without rewriting earlier attempt evidence.
18
+
19
+ Server-side TypeScript SDK for calling Skyforge agent chat APIs from trusted
20
+ backend code.
21
+
22
+ Use this package from Express apps, Next.js route handlers, serverless
23
+ functions, jobs, and backend proxies. Do not use it in browser code.
24
+
25
+ ```text
26
+ Browser
27
+ -> your backend
28
+ -> @runmark/sdk
29
+ -> Skyforge API
30
+ ```
31
+
32
+ Use `@runmark/agent-chat` when you need the browser or React chat UI.
33
+
34
+ ## When To Use It
35
+
36
+ - Send messages to a configured Skyforge agent branch from your backend.
37
+ - Build an app proxy for `@runmark/agent-chat`.
38
+ - Resume a known Skyforge chat by `chatId`.
39
+ - Attach optional host-app mapping metadata with `externalId`.
40
+ - Build server-side chat recovery, search, or history using agent-scoped chat
41
+ lookup.
42
+ - Upload, list, and delete files attached to a chat.
43
+ - Stream durable run events and submit human actions.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ npm install @runmark/sdk
49
+ ```
50
+
51
+ ## Requirements
52
+
53
+ - Node.js `24.17.0` or newer
54
+ - A server-side Skyforge API token
55
+ - Native `fetch`, `FormData`, `ReadableStream`, and `AbortSignal`
56
+
57
+ ## Client Setup
2
58
 
3
- Server-side TypeScript SDK for Skyforge agent chat integrations.
59
+ ```ts
60
+ import { SkyforgeClient } from "@runmark/sdk";
61
+
62
+ const skyforge = new SkyforgeClient({
63
+ apiKey: process.env.SKYFORGE_API_TOKEN!,
64
+ baseUrl: process.env.SKYFORGE_API_BASE_URL ?? "https://api.skyforge.ai",
65
+ });
66
+ ```
4
67
 
5
- This package is internal for now and is not published to npm. `private: true`
6
- is intentionally retained until a release process, package metadata, and npm
7
- publishing policy are approved.
68
+ Common server-side environment variables:
8
69
 
9
- ## Runtime
70
+ ```bash
71
+ SKYFORGE_API_BASE_URL=https://api.skyforge.ai
72
+ SKYFORGE_API_TOKEN=
73
+ SKYFORGE_AGENT_ID=
74
+ SKYFORGE_AGENT_BRANCH_ID=
75
+ ```
10
76
 
11
- - Node.js 24.17.0 or newer.
12
- - Server-only. The SDK throws in browser-like environments.
13
- - Zero runtime dependencies.
14
- - Uses native `fetch`, `FormData`, `ReadableStream`, and `AbortSignal`.
77
+ `SKYFORGE_API_TOKEN` must stay on the server. Never bundle it into frontend
78
+ code.
15
79
 
16
- ## Authentication
80
+ ## Auth And Security Model
17
81
 
18
- Every request uses the existing Skyforge chat routes and sends:
82
+ The SDK sends:
19
83
 
20
84
  ```http
21
- Authorization: Bearer <skyforge_api_token>
85
+ Authorization: Bearer <SKYFORGE_API_TOKEN>
22
86
  ```
23
87
 
24
- The SDK does not set cookies, `X-CSRF-Token`, `credentials: "include"`, or call
25
- `/api/auth/csrf`.
88
+ It does not require browser cookies, CSRF tokens, browser credentials, or
89
+ frontend auth routes.
90
+
91
+ Use your own app authentication and tenancy checks before deciding which
92
+ Skyforge agent, branch, chat, or `externalId` a request may use. `externalId`
93
+ is metadata for mapping chats back to your app; it is not authentication and it
94
+ does not bypass Skyforge API-token authorization.
95
+
96
+ ## Send a Message
26
97
 
27
- ## Response Shape
98
+ ```ts
99
+ const response = await skyforge.agentBranches.sendMessage({
100
+ agentBranchId: process.env.SKYFORGE_AGENT_BRANCH_ID!,
101
+ message: "Help me plan this outdoor event.",
102
+ externalId: "event_123",
103
+ requestId: crypto.randomUUID(),
104
+ });
28
105
 
29
- SDK method inputs use camelCase. Request bodies are serialized to the existing
30
- backend field names.
106
+ console.log(response.request_id, response.agent_run_id, response.chat_id, response.terminal);
107
+ ```
31
108
 
32
- V1 response payloads intentionally mirror the backend DTOs, including snake_case
33
- fields such as `chat_id`, `agent_branch_id`, and `pending_human_actions`. The SDK
34
- does not translate response fields to camelCase.
109
+ `externalId` is optional host-app mapping metadata. Use it for values your app
110
+ already understands, such as an event ID, support ticket ID, session ID,
111
+ project ID, or case ID.
35
112
 
36
- ## Usage
113
+ When continuing an existing Skyforge chat, pass `chatId`:
37
114
 
38
115
  ```ts
39
- import { SkyforgeClient } from "@skyforge-ai/sdk";
116
+ await skyforge.agentBranches.sendMessage({
117
+ agentBranchId: process.env.SKYFORGE_AGENT_BRANCH_ID!,
118
+ chatId: "skyforge-chat-id",
119
+ externalId: "event_123",
120
+ message: "Summarize the current event status.",
121
+ structuredContext: {
122
+ weather: "windy",
123
+ },
124
+ });
125
+ ```
40
126
 
41
- const skyforge = new SkyforgeClient({
42
- apiKey: process.env.SKYFORGE_API_TOKEN!,
43
- baseUrl: "https://api.skyforge.ai",
127
+ Skyforge may reject a request that tries to continue an existing `chatId` with a
128
+ different `externalId` than the chat already has.
129
+
130
+ Response fields mirror the Skyforge API payloads and use API field names such
131
+ as `chat_id`, `external_id`, `agent_branch_id`, and `pending_human_actions`.
132
+
133
+ Every turn is a durable worker-owned run, regardless of the branch's legacy
134
+ runtime mode. `terminal=false` means the HTTP delivery returned before
135
+ execution resolved; preserve `request_id`, `agent_run_id`, and `chat_id` for
136
+ lookup, event replay, and explicit cancellation. Delivery timeout or abort does
137
+ not fail or cancel the run.
138
+
139
+ ## Request Recovery And Cancellation
140
+
141
+ Use one request ID for one immutable submission contract. An exact retry can
142
+ resolve to the existing run; changing delivery mode or semantic inputs returns
143
+ generic `409 request_id_conflict`.
144
+
145
+ ```ts
146
+ const lookup = await skyforge.agentBranches.lookupRequest({
147
+ agentBranchId: process.env.SKYFORGE_AGENT_BRANCH_ID!,
148
+ requestId,
44
149
  });
150
+
151
+ if (!lookup.terminal) {
152
+ await skyforge.agentRuns.cancel({
153
+ agentRunId: lookup.agent_run_id,
154
+ reason: "User requested cancellation",
155
+ });
156
+ }
45
157
  ```
46
158
 
47
- ### Get Agent Branch State
159
+ Cancellation is cooperative. It prevents new provider/tool calls after the
160
+ worker observes the request, but cannot undo an already transmitted external
161
+ side effect. Do not translate client disconnect or an SDK `AbortSignal` into a
162
+ cancellation request.
163
+
164
+ ## Recover Chats By External ID
165
+
166
+ Use `skyforge.chats.list(...)` from your backend to recover chats for an agent.
167
+ The lookup is agent-scoped and can be narrowed to one branch.
48
168
 
49
169
  ```ts
50
- const state = await skyforge.agentBranches.getState({
51
- agentBranchId: "11111111-1111-1111-1111-111111111111",
52
- chatId: "22222222-2222-2222-2222-222222222222",
170
+ const { chats, nextCursor } = await skyforge.chats.list({
171
+ agentId: process.env.SKYFORGE_AGENT_ID!,
172
+ externalId: "event_123",
53
173
  });
54
174
 
55
- console.log(state.chat_id, state.messages);
175
+ for (const chat of chats) {
176
+ console.log(chat.chat_id, chat.external_id, chat.agent_branch_name);
177
+ }
178
+
179
+ console.log(nextCursor);
180
+ ```
181
+
182
+ The SDK calls:
183
+
184
+ ```text
185
+ GET /api/skyforge-chat/agents/{agent_id}/chats
56
186
  ```
57
187
 
58
- ### Send Message
188
+ Supported query params are `agent_branch_id`, `chat_id`, `external_id`,
189
+ `limit`, and `cursor`. The raw API response field is `next_cursor`; the SDK
190
+ normalizes it to `nextCursor`.
191
+
192
+ List items include:
193
+
194
+ - `agent_id`
195
+ - `agent_branch_id`
196
+ - `agent_branch_name`
197
+ - `chat_id`
198
+ - `external_id`
199
+ - `chat_title`
200
+ - `created_at`
201
+ - `updated_at`
202
+
203
+ ## Chat Lookup Examples
204
+
205
+ Find one known chat:
59
206
 
60
207
  ```ts
61
- const response = await skyforge.agentBranches.sendMessage({
62
- agentBranchId: "11111111-1111-1111-1111-111111111111",
63
- chatId: "22222222-2222-2222-2222-222222222222",
64
- message: "Summarize the latest run.",
65
- structuredContext: {
66
- priority: "high",
67
- },
208
+ const { chats } = await skyforge.chats.list({
209
+ agentId: process.env.SKYFORGE_AGENT_ID!,
210
+ chatId: "skyforge-chat-id",
68
211
  });
69
212
 
70
- console.log(response.chat_id, response.agent_run_id);
213
+ const chat = chats[0];
71
214
  ```
72
215
 
73
- ### Stream Run Events
216
+ Narrow lookup to one branch:
217
+
218
+ ```ts
219
+ const page = await skyforge.chats.list({
220
+ agentId: process.env.SKYFORGE_AGENT_ID!,
221
+ agentBranchId: process.env.SKYFORGE_AGENT_BRANCH_ID!,
222
+ externalId: "event_123",
223
+ limit: 20,
224
+ });
225
+ ```
226
+
227
+ Paginate through results:
228
+
229
+ ```ts
230
+ let cursor: string | undefined;
231
+
232
+ do {
233
+ const page = await skyforge.chats.list({
234
+ agentId: process.env.SKYFORGE_AGENT_ID!,
235
+ externalId: "event_123",
236
+ cursor,
237
+ });
238
+
239
+ for (const chat of page.chats) {
240
+ // Render or store the chat mapping in your app.
241
+ console.log(chat.chat_id, chat.updated_at);
242
+ }
243
+
244
+ cursor = page.nextCursor ?? undefined;
245
+ } while (cursor);
246
+ ```
247
+
248
+ ## Build a SaaS Chat History
249
+
250
+ Use `externalId` when your app already has a record that should own the
251
+ conversation, such as an event, ticket, project, or session. Your backend can
252
+ later call `skyforge.chats.list({ agentId, externalId })` to build a chat
253
+ history or resume-chat experience in your own product.
254
+
255
+ Skyforge provides the lookup primitive. Your SaaS app still owns the end-user
256
+ history UI, app-level permissions, and the decision about which `externalId` is
257
+ valid for the current user. Treat browser-provided external IDs as metadata,
258
+ not trusted identity.
259
+
260
+ The public [`Skyforge-AI/api-starter`](https://github.com/Skyforge-AI/api-starter)
261
+ uses `@runmark/sdk` on the backend and `@runmark/agent-chat` in the browser. To
262
+ add a chat-history UI to your own app, call `skyforge.chats.list(...)` from
263
+ your backend and pass the selected `chatId` to the chat component.
264
+
265
+ ## Stream Run Events
74
266
 
75
267
  ```ts
76
268
  const events = await skyforge.agentRuns.streamEvents({
77
- agentRunId: "33333333-3333-3333-3333-333333333333",
78
- afterSequence: 12,
269
+ agentRunId: "agent-run-id",
270
+ afterSequence: 0,
79
271
  });
80
272
 
81
273
  for await (const event of events) {
@@ -83,26 +275,66 @@ for await (const event of events) {
83
275
  }
84
276
  ```
85
277
 
86
- Breaking out of the loop cancels the underlying response reader.
278
+ Breaking out of the loop cancels the underlying stream reader.
87
279
 
88
- ### Submit Human Action
280
+ `afterSequence` is an explicit persisted replay cursor. The low-level SDK does
281
+ not run an infinite reconnect loop or deduplicate events for you; reconnect
282
+ with the last applied sequence and ignore duplicate sequence values in the
283
+ consumer. The parser supports CRLF/chunk boundaries and multiline data, rejects
284
+ malformed or oversized events, and always releases its reader.
285
+
286
+ ## Source References
287
+
288
+ When Advanced RAG injects labeled sources into an answer, chat messages may
289
+ include `source_references`. These references are safe public metadata for the
290
+ labels visible in the assistant text, such as `[S1]`; they are not the hidden
291
+ RAG prompt or full source documents.
292
+
293
+ ```ts
294
+ const reply = await skyforge.agentBranches.sendMessage({
295
+ agentBranchId: process.env.SKYFORGE_AGENT_BRANCH_ID!,
296
+ message: "What does Advanced RAG change?",
297
+ });
298
+
299
+ for (const message of reply.messages) {
300
+ for (const source of message.source_references ?? []) {
301
+ console.log(source.display_label, source.snippet, source.source_type);
302
+ }
303
+ }
304
+ ```
305
+
306
+ For run-based integrations, source references can also be loaded after the run
307
+ completes:
308
+
309
+ ```ts
310
+ const { source_references } = await skyforge.agentRuns.getSourceReferences({
311
+ agentRunId: "agent-run-id",
312
+ });
313
+ ```
314
+
315
+ Match references by exact `source_label` or `display_label`, never by array
316
+ position. Source links are not part of the MVP source-reference contract.
317
+
318
+ ## Submit a Human Action
89
319
 
90
320
  ```ts
91
321
  await skyforge.humanActions.submit({
92
- humanActionRequestId: "44444444-4444-4444-4444-444444444444",
322
+ humanActionRequestId: "human-action-request-id",
323
+ requestId: crypto.randomUUID(),
324
+ activeOrganizationId: "organization-id",
93
325
  values: {
94
326
  approved: true,
95
327
  },
96
328
  });
97
329
  ```
98
330
 
99
- ### Uploaded Files
331
+ ## Upload a Chat File
100
332
 
101
333
  ```ts
102
334
  const upload = await skyforge.uploadedFiles.upload({
103
- agentBranchId: "11111111-1111-1111-1111-111111111111",
104
- chatId: "22222222-2222-2222-2222-222222222222",
105
- file: new Blob(["notes"], { type: "text/plain" }),
335
+ agentBranchId: process.env.SKYFORGE_AGENT_BRANCH_ID!,
336
+ chatId: "chat-id",
337
+ file: new Uint8Array([104, 101, 108, 108, 111]),
106
338
  filename: "notes.txt",
107
339
  contentType: "text/plain",
108
340
  });
@@ -121,99 +353,107 @@ await skyforge.uploadedFiles.delete({
121
353
 
122
354
  `filename` is required and must not be blank.
123
355
 
124
- ## Tests
356
+ ## Using With Express
125
357
 
126
- Run the fast SDK unit tests:
358
+ Use your backend as the app proxy for browser chat requests. The browser calls
359
+ your server; your server calls Skyforge with the API token.
127
360
 
128
- ```bash
129
- cd packages/skyforge-sdk
130
- npm test
131
- ```
361
+ ```ts
362
+ import express from "express";
363
+ import { SkyforgeClient } from "@runmark/sdk";
132
364
 
133
- The opt-in live suite requires a running local Skyforge backend and a valid
134
- local API token with access to the selected agent branch. It uses only
135
- `Authorization: Bearer <skyforge_api_token>` through the existing
136
- `/api/skyforge-chat/...` routes.
365
+ const app = express();
366
+ app.use(express.json());
137
367
 
138
- Live test environment variables can be stored in `.e2e.env` at the package
139
- root. Copy the example file and fill in your local token:
368
+ const skyforge = new SkyforgeClient({
369
+ apiKey: process.env.SKYFORGE_API_TOKEN!,
370
+ baseUrl: process.env.SKYFORGE_API_BASE_URL ?? "https://api.skyforge.ai",
371
+ });
140
372
 
141
- ```bash
142
- cd packages/skyforge-sdk
143
- cp .e2e.env.example .e2e.env
373
+ app.post("/api/skyforge-chat/agent_branches/:agentBranchId/messages", async (req, res, next) => {
374
+ try {
375
+ if (req.params.agentBranchId !== process.env.SKYFORGE_AGENT_BRANCH_ID) {
376
+ res.status(403).json({ error: { message: "Agent branch is not allowed." } });
377
+ return;
378
+ }
379
+
380
+ const data = await skyforge.agentBranches.sendMessage({
381
+ agentBranchId: req.params.agentBranchId,
382
+ chatId: req.body.chat_id,
383
+ externalId: req.session?.ticketId ?? req.body.external_id,
384
+ message: req.body.message,
385
+ structuredContext: req.body.structured_context,
386
+ retrievalScope: req.body.retrieval_scope,
387
+ });
388
+
389
+ res.json({ message: "ok", data });
390
+ } catch (error) {
391
+ next(error);
392
+ }
393
+ });
144
394
  ```
145
395
 
146
- `.e2e.env` is ignored by git. Shell environment variables take precedence over
147
- values in the file.
396
+ Backend proxies can supply or override `externalId` from trusted app context,
397
+ such as a signed-in user session, event, ticket, project, or case ID. Do not
398
+ treat browser-provided `external_id` as identity.
148
399
 
149
- ```bash
150
- cd packages/skyforge-sdk
151
-
152
- SKYFORGE_SDK_LIVE=1 \
153
- SKYFORGE_API_BASE_URL=http://localhost:3000 \
154
- SKYFORGE_API_TOKEN=... \
155
- SKYFORGE_AGENT_BRANCH_ID=... \
156
- npm run test:live
157
- ```
400
+ ## Using With Next.js Route Handlers
158
401
 
159
- With `.e2e.env` populated, this is enough:
402
+ ```ts
403
+ import { NextResponse } from "next/server";
404
+ import { SkyforgeClient } from "@runmark/sdk";
160
405
 
161
- ```bash
162
- npm run test:live
163
- ```
406
+ const skyforge = new SkyforgeClient({
407
+ apiKey: process.env.SKYFORGE_API_TOKEN!,
408
+ baseUrl: process.env.SKYFORGE_API_BASE_URL ?? "https://api.skyforge.ai",
409
+ });
164
410
 
165
- Optional live test controls:
411
+ export async function POST(request: Request) {
412
+ const body = await request.json();
413
+ const data = await skyforge.agentBranches.sendMessage({
414
+ agentBranchId: process.env.SKYFORGE_AGENT_BRANCH_ID!,
415
+ chatId: body.chat_id,
416
+ externalId: body.external_id,
417
+ message: body.message,
418
+ });
166
419
 
167
- ```bash
168
- SKYFORGE_SDK_LIVE_UPLOADS=1
169
- SKYFORGE_SDK_LIVE_HITL_REQUEST_ID=...
170
- SKYFORGE_SDK_LIVE_EXISTING_CHAT_ID=...
171
- SKYFORGE_SDK_LIVE_TIMEOUT_MS=60000
172
- SKYFORGE_SDK_LIVE_HITL_TIMEOUT_MS=120000
173
- SKYFORGE_SDK_LIVE_EVENT_TIMEOUT_MS=15000
174
- SKYFORGE_SDK_LIVE_MESSAGE="SDK live smoke test. Reply with a short confirmation."
175
- SKYFORGE_SDK_LIVE_EXPECT_PENDING_HITL=1
176
- SKYFORGE_SDK_LIVE_EXPECT_BUBBLED_HITL=1
177
- SKYFORGE_SDK_LIVE_SUBMIT_PENDING_HITL=1
178
- SKYFORGE_SDK_LIVE_HITL_VALUES='{"decision":"approve","notes":"Approved by SDK live test."}'
420
+ return NextResponse.json({ message: "ok", data });
421
+ }
179
422
  ```
180
423
 
181
- ### HITL Bubbling Demo
424
+ ## Error Handling
182
425
 
183
- The repository seed includes a TailYew `hitl-bubbling-demo` parent agent. The
184
- SDK package has a convenience live command for that seeded local fixture:
426
+ Non-2xx Skyforge API responses throw `SkyforgeApiError`.
185
427
 
186
- ```bash
187
- cd packages/skyforge-sdk
188
-
189
- SKYFORGE_API_TOKEN=... \
190
- npm run test:live:hitl-bubbling-demo
428
+ ```ts
429
+ import { SkyforgeApiError } from "@runmark/sdk";
430
+
431
+ try {
432
+ await skyforge.agentBranches.getState({
433
+ agentBranchId: process.env.SKYFORGE_AGENT_BRANCH_ID!,
434
+ });
435
+ } catch (error) {
436
+ if (error instanceof SkyforgeApiError) {
437
+ console.error(error.status, error.code, error.requestId);
438
+ }
439
+ throw error;
440
+ }
191
441
  ```
192
442
 
193
- If `.e2e.env` contains `SKYFORGE_API_TOKEN`, you can run:
443
+ Avoid logging API tokens, authorization headers, or full request payloads.
194
444
 
195
- ```bash
196
- npm run test:live:hitl-bubbling-demo
197
- ```
445
+ Successful responses must be JSON envelopes with non-null `data`; malformed,
446
+ empty, wrong-content-type, or oversized responses are rejected rather than
447
+ cast to the requested type. Error bodies are bounded before parsing.
198
448
 
199
- This command sets:
449
+ ## Compatibility
200
450
 
201
- ```bash
202
- SKYFORGE_SDK_LIVE=1
203
- SKYFORGE_API_BASE_URL=http://127.0.0.1:3000
204
- SKYFORGE_AGENT_BRANCH_ID=9ab14d38-55d1-4a9c-bc56-0df2c03aee02
205
- SKYFORGE_SDK_LIVE_MESSAGE="Use ask_skyforge_agent to ask the human-workflow-demo child agent to look up Bulbasaur. Do not answer without calling the child agent."
206
- SKYFORGE_SDK_LIVE_TIMEOUT_MS=180000
207
- SKYFORGE_SDK_LIVE_HITL_TIMEOUT_MS=120000
208
- SKYFORGE_SDK_LIVE_EVENT_TIMEOUT_MS=15000
209
- SKYFORGE_SDK_LIVE_EXPECT_PENDING_HITL=1
210
- SKYFORGE_SDK_LIVE_EXPECT_BUBBLED_HITL=1
211
- SKYFORGE_SDK_LIVE_SUBMIT_PENDING_HITL=1
212
- ```
213
-
214
- `SKYFORGE_API_TOKEN` is still required and is not set by the script. Use a valid
215
- local API token with access to the seeded TailYew repository/branch. You can
216
- override the base URL, branch ID, message, HITL values, or timeout by setting
217
- the same environment variables before running the command.
218
-
219
- Do not expose Skyforge API tokens in browser code. This SDK is server-side only.
451
+ The durable request-ID, lookup, cancellation, and HITL correlation APIs are
452
+ additive in `0.1.2`. Existing callers may omit request IDs, but embedded and
453
+ retry-sensitive integrations should supply them. The SDK remains server-only
454
+ and throws if constructed in a browser environment.
455
+
456
+ ## Related Package
457
+
458
+ Use `@runmark/agent-chat` for the browser and React chat UI. Keep this SDK on
459
+ the backend and expose only the app-specific proxy routes your frontend needs.
package/dist/client.d.ts CHANGED
@@ -1,15 +1,41 @@
1
- import type { DeleteUploadedFileParams, GetAgentBranchStateParams, SendMessageParams, SkyforgeAgentRunEventEnvelope, SkyforgeChatMessageResponse, SkyforgeChatStateResponse, SkyforgeChatUploadedFileListResponse, SkyforgeChatUploadedFileUploadResponse, SkyforgeClientOptions, StreamAgentRunEventsParams, SubmitHumanActionParams, UploadFileParams, ListUploadedFilesParams } from "./types.js";
1
+ import type { CancelAgentRunParams, CancelAgentRunResponse, CreateWebhookEndpointParams, CreateWebhookReplayParams, DeleteUploadedFileParams, GetAgentRunSourceReferencesParams, GetAgentRunParams, GetAgentBranchStateParams, GetRepositoryWebhookDeliveryParams, ListChatsParams, ListWebhookAttemptsParams, ListWebhookDeliveriesParams, ListWebhookEndpointsParams, ListRepositoryWebhookDeliveriesParams, ListUploadedFilesParams, LookupAgentRunRequestParams, SendMessageParams, SkyforgeAgentRunEventEnvelope, SkyforgeAgentRunRequestLookupResponse, SkyforgeChatSourceReferencesResponse, SkyforgeChatListResponse, SkyforgeChatMessageResponse, SkyforgeChatStateResponse, SkyforgeChatUploadedFileListResponse, SkyforgeChatUploadedFileUploadResponse, SkyforgeClientOptions, StreamAgentRunEventsParams, SubmitHumanActionParams, GetHumanActionParams, HumanActionRequestDto, JsonObject, RepositoryWebhookDeliveryDetail, RepositoryWebhookDeliveryListResponse, UpdateWebhookEndpointParams, WebhookAttemptListResponse, WebhookDeliveryListResponse, WebhookEndpointHealth, WebhookEndpointParams, WebhookEndpointSecretResponse, WebhookEndpointSummary, WebhookReplaySummary, WebhookTestDeliveryResponse, UploadFileParams } from "./types.js";
2
2
  export declare class SkyforgeClient {
3
3
  readonly agentBranches: {
4
4
  getState: (params: GetAgentBranchStateParams) => Promise<SkyforgeChatStateResponse>;
5
5
  sendMessage: (params: SendMessageParams) => Promise<SkyforgeChatMessageResponse>;
6
+ lookupRequest: (params: LookupAgentRunRequestParams) => Promise<SkyforgeAgentRunRequestLookupResponse>;
7
+ };
8
+ readonly chats: {
9
+ list: (params: ListChatsParams) => Promise<SkyforgeChatListResponse>;
6
10
  };
7
11
  readonly agentRuns: {
12
+ get: (params: GetAgentRunParams) => Promise<JsonObject>;
8
13
  streamEvents: (params: StreamAgentRunEventsParams) => Promise<AsyncIterable<SkyforgeAgentRunEventEnvelope>>;
14
+ getSourceReferences: (params: GetAgentRunSourceReferencesParams) => Promise<SkyforgeChatSourceReferencesResponse>;
15
+ cancel: (params: CancelAgentRunParams) => Promise<CancelAgentRunResponse>;
9
16
  };
10
17
  readonly humanActions: {
18
+ get: (params: GetHumanActionParams) => Promise<HumanActionRequestDto>;
11
19
  submit: (params: SubmitHumanActionParams) => Promise<SkyforgeChatMessageResponse>;
12
20
  };
21
+ readonly webhooks: {
22
+ create: (params: CreateWebhookEndpointParams) => Promise<WebhookEndpointSecretResponse>;
23
+ list: (params: ListWebhookEndpointsParams) => Promise<WebhookEndpointSummary[]>;
24
+ get: (params: WebhookEndpointParams) => Promise<WebhookEndpointSummary>;
25
+ update: (params: UpdateWebhookEndpointParams) => Promise<WebhookEndpointSummary>;
26
+ delete: (params: WebhookEndpointParams) => Promise<string>;
27
+ enable: (params: WebhookEndpointParams) => Promise<WebhookEndpointSummary>;
28
+ disable: (params: WebhookEndpointParams) => Promise<WebhookEndpointSummary>;
29
+ rotateSecret: (params: WebhookEndpointParams) => Promise<WebhookEndpointSecretResponse>;
30
+ test: (params: WebhookEndpointParams) => Promise<WebhookTestDeliveryResponse>;
31
+ health: (params: WebhookEndpointParams) => Promise<WebhookEndpointHealth>;
32
+ listDeliveries: (params: ListWebhookDeliveriesParams) => Promise<WebhookDeliveryListResponse>;
33
+ listAttempts: (params: ListWebhookAttemptsParams) => Promise<WebhookAttemptListResponse>;
34
+ listRepositoryDeliveries: (params: ListRepositoryWebhookDeliveriesParams) => Promise<RepositoryWebhookDeliveryListResponse>;
35
+ getDelivery: (params: GetRepositoryWebhookDeliveryParams) => Promise<RepositoryWebhookDeliveryDetail>;
36
+ replay: (params: CreateWebhookReplayParams) => Promise<WebhookReplaySummary>;
37
+ listReplays: (params: WebhookEndpointParams) => Promise<WebhookReplaySummary[]>;
38
+ };
13
39
  readonly uploadedFiles: {
14
40
  list: (params: ListUploadedFilesParams) => Promise<SkyforgeChatUploadedFileListResponse>;
15
41
  upload: (params: UploadFileParams) => Promise<SkyforgeChatUploadedFileUploadResponse>;
@@ -18,9 +44,30 @@ export declare class SkyforgeClient {
18
44
  private readonly baseUrl;
19
45
  private readonly http;
20
46
  constructor(options: SkyforgeClientOptions);
47
+ private getAgentRun;
48
+ private getHumanAction;
49
+ private createWebhookEndpoint;
50
+ private listWebhookEndpoints;
51
+ private getWebhookEndpoint;
52
+ private updateWebhookEndpoint;
53
+ private deleteWebhookEndpoint;
54
+ private webhookEndpointAction;
55
+ private rotateWebhookSecret;
56
+ private testWebhookEndpoint;
57
+ private getWebhookHealth;
58
+ private listWebhookDeliveries;
59
+ private listWebhookAttempts;
60
+ private listRepositoryWebhookDeliveries;
61
+ private getRepositoryWebhookDelivery;
62
+ private replayWebhookEvents;
63
+ private listWebhookReplays;
21
64
  private getAgentBranchState;
65
+ private listChats;
22
66
  private sendMessage;
67
+ private lookupRequest;
23
68
  private streamEvents;
69
+ private getSourceReferences;
70
+ private cancelAgentRun;
24
71
  private submitHumanAction;
25
72
  private listUploadedFiles;
26
73
  private uploadFile;