@blocks-network/sdk 0.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +632 -0
- package/dist/cli/run.d.ts +39 -0
- package/dist/cli/run.js +2 -0
- package/dist/config-loader.d.ts +10 -0
- package/dist/config-loader.js +1 -0
- package/dist/defaults.d.ts +7 -0
- package/dist/defaults.js +1 -0
- package/dist/env.d.ts +5 -0
- package/dist/env.js +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +1 -0
- package/dist/runtime/agent-auth.d.ts +94 -0
- package/dist/runtime/agent-auth.js +1 -0
- package/dist/runtime/agent-instance.d.ts +233 -0
- package/dist/runtime/agent-instance.js +1 -0
- package/dist/runtime/agent-registry.d.ts +270 -0
- package/dist/runtime/agent-registry.js +1 -0
- package/dist/runtime/artifacts.d.ts +65 -0
- package/dist/runtime/artifacts.js +1 -0
- package/dist/runtime/auth-provider.d.ts +39 -0
- package/dist/runtime/auth-provider.js +1 -0
- package/dist/runtime/cdm-config.d.ts +16 -0
- package/dist/runtime/cdm-config.js +1 -0
- package/dist/runtime/channel-manager.d.ts +125 -0
- package/dist/runtime/channel-manager.js +1 -0
- package/dist/runtime/consumer-auth.d.ts +112 -0
- package/dist/runtime/consumer-auth.js +1 -0
- package/dist/runtime/credential-cache.d.ts +40 -0
- package/dist/runtime/credential-cache.js +1 -0
- package/dist/runtime/file-input.d.ts +37 -0
- package/dist/runtime/file-input.js +1 -0
- package/dist/runtime/file-upload.d.ts +112 -0
- package/dist/runtime/file-upload.js +1 -0
- package/dist/runtime/part-helpers.d.ts +52 -0
- package/dist/runtime/part-helpers.js +1 -0
- package/dist/runtime/protocol-version.d.ts +18 -0
- package/dist/runtime/protocol-version.js +1 -0
- package/dist/runtime/pubnub-client.d.ts +8 -0
- package/dist/runtime/pubnub-client.js +1 -0
- package/dist/runtime/pubnub-types.d.ts +119 -0
- package/dist/runtime/pubnub-types.js +1 -0
- package/dist/runtime/rpc-client.d.ts +45 -0
- package/dist/runtime/rpc-client.js +1 -0
- package/dist/runtime/stream-context.d.ts +69 -0
- package/dist/runtime/stream-context.js +1 -0
- package/dist/runtime/stream-ref.d.ts +74 -0
- package/dist/runtime/stream-ref.js +1 -0
- package/dist/runtime/stream-registry.d.ts +133 -0
- package/dist/runtime/stream-registry.js +1 -0
- package/dist/runtime/stream-setup-helper.d.ts +87 -0
- package/dist/runtime/stream-setup-helper.js +1 -0
- package/dist/runtime/task-client.d.ts +259 -0
- package/dist/runtime/task-client.js +1 -0
- package/dist/runtime/task-session.d.ts +224 -0
- package/dist/runtime/task-session.js +1 -0
- package/dist/runtime/write-affinity.d.ts +22 -0
- package/dist/runtime/write-affinity.js +1 -0
- package/dist/runtime/write-affinity.test.d.ts +1 -0
- package/dist/runtime/write-affinity.test.js +1 -0
- package/dist/stream/bytes.d.ts +14 -0
- package/dist/stream/bytes.js +1 -0
- package/dist/stream/descriptor.d.ts +47 -0
- package/dist/stream/descriptor.js +1 -0
- package/dist/stream/index.d.ts +11 -0
- package/dist/stream/index.js +1 -0
- package/dist/stream/stream-bundle.d.ts +82 -0
- package/dist/stream/stream-bundle.js +1 -0
- package/dist/stream/stream-client.d.ts +192 -0
- package/dist/stream/stream-client.js +1 -0
- package/dist/stream/types.d.ts +75 -0
- package/dist/stream/types.js +1 -0
- package/dist/stream/validate.d.ts +15 -0
- package/dist/stream/validate.js +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Credential Cache
|
|
3
|
+
*
|
|
4
|
+
* In-memory map that survives pipe-task handler exit. Caches ownerId,
|
|
5
|
+
* writeToken (T2), and associated streamIds for each task so that
|
|
6
|
+
* instance-level APIs (publishTerminal, failStream) can operate after
|
|
7
|
+
* the per-task PubNub client is destroyed.
|
|
8
|
+
*
|
|
9
|
+
* Lifecycle:
|
|
10
|
+
* - Populated during task setup from StartTask message.
|
|
11
|
+
* - StreamIds added via addStream() during createStream() calls.
|
|
12
|
+
* - Survives pipe-task handler exit.
|
|
13
|
+
* - Removed when the task reaches terminal state.
|
|
14
|
+
* - Not persisted across process restart.
|
|
15
|
+
*/
|
|
16
|
+
export interface CachedCredentials {
|
|
17
|
+
ownerId: string;
|
|
18
|
+
orgId: string;
|
|
19
|
+
writeToken: string;
|
|
20
|
+
agentName: string;
|
|
21
|
+
environment: string;
|
|
22
|
+
streamIds: Set<string>;
|
|
23
|
+
}
|
|
24
|
+
export declare class CredentialCache {
|
|
25
|
+
private readonly entries;
|
|
26
|
+
/** Store credentials for a task. */
|
|
27
|
+
set(taskId: string, creds: Omit<CachedCredentials, 'streamIds'>): void;
|
|
28
|
+
/** Get cached credentials for a task. */
|
|
29
|
+
get(taskId: string): CachedCredentials | undefined;
|
|
30
|
+
/** Add a stream ID to a task's cache entry. */
|
|
31
|
+
addStream(taskId: string, streamId: string): void;
|
|
32
|
+
/** Remove a task's cache entry entirely. */
|
|
33
|
+
remove(taskId: string): void;
|
|
34
|
+
/** Check if a task has cached credentials. */
|
|
35
|
+
has(taskId: string): boolean;
|
|
36
|
+
/** Get all task IDs with cached credentials. */
|
|
37
|
+
taskIds(): string[];
|
|
38
|
+
/** Clear all entries. */
|
|
39
|
+
clear(): void;
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class CredentialCache{constructor(){this.entries=new Map}set(e,t){const r=this.entries.get(e);if(r)return r.ownerId=t.ownerId,r.orgId=t.orgId,r.writeToken=t.writeToken,r.agentName=t.agentName,void(r.environment=t.environment);this.entries.set(e,{...t,streamIds:new Set})}get(e){return this.entries.get(e)}addStream(e,t){const r=this.entries.get(e);r&&r.streamIds.add(t)}remove(e){this.entries.delete(e)}has(e){return this.entries.has(e)}taskIds(){return[...this.entries.keys()]}clear(){this.entries.clear()}}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a consumer-supplied file input into a form the SDK can
|
|
3
|
+
* hand to `buildArtifactRef` (which wants `Uint8Array`) and
|
|
4
|
+
* `uploadToStorage` (which wants a `Blob`-or-bytes).
|
|
5
|
+
*
|
|
6
|
+
* Accepts the four shapes a browser or Node consumer might provide:
|
|
7
|
+
* - `Uint8Array` (including Node `Buffer`, which extends Uint8Array).
|
|
8
|
+
* - `ArrayBuffer`.
|
|
9
|
+
* - `Blob` (browser-native; also available in Node 18+).
|
|
10
|
+
* - `File` (browser-native subclass of Blob; also Node 20+).
|
|
11
|
+
*
|
|
12
|
+
* Returned shape is a three-field handle:
|
|
13
|
+
* - `size`: byte length, available synchronously for every input
|
|
14
|
+
* shape (the caller uses it to choose inline vs upload path).
|
|
15
|
+
* - `uploadBody`: the canonical body to hand to `uploadToStorage`.
|
|
16
|
+
* Blobs pass through unchanged — no pre-copy. Uint8Array /
|
|
17
|
+
* ArrayBuffer inputs are returned as raw bytes so
|
|
18
|
+
* `uploadToStorage` can wrap them in a Blob on demand.
|
|
19
|
+
* - `getBytes()`: a lazy accessor that returns a `Uint8Array` view
|
|
20
|
+
* of the input contents. For `Uint8Array` / `ArrayBuffer` inputs
|
|
21
|
+
* it's effectively free; for `Blob` / `File` inputs it performs
|
|
22
|
+
* one `arrayBuffer()` read, cached against repeat calls. Callers
|
|
23
|
+
* on the upload path **MUST NOT** call `getBytes()`, because it
|
|
24
|
+
* pulls the full Blob into memory — that defeats the streaming
|
|
25
|
+
* upload. `getBytes()` exists only for the inline-artifact path
|
|
26
|
+
* (files under `shouldInlineArtifact()` threshold, default 16 KB).
|
|
27
|
+
*
|
|
28
|
+
* Throws `TypeError` for unsupported inputs synchronously — malformed
|
|
29
|
+
* shapes surface immediately at call site rather than at first
|
|
30
|
+
* `getBytes()`.
|
|
31
|
+
*/
|
|
32
|
+
export interface NormalizedFileInput {
|
|
33
|
+
readonly size: number;
|
|
34
|
+
readonly uploadBody: Uint8Array | Blob;
|
|
35
|
+
getBytes(): Promise<Uint8Array>;
|
|
36
|
+
}
|
|
37
|
+
export declare function normalizeFileInput(input: Uint8Array | ArrayBuffer | Blob | File): NormalizedFileInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function normalizeFileInput(e){if(e instanceof Uint8Array)return{size:e.byteLength,uploadBody:e,getBytes:async()=>e};if(e instanceof ArrayBuffer){const r=new Uint8Array(e);return{size:r.byteLength,uploadBody:r,getBytes:async()=>r}}if("undefined"!=typeof Blob&&e instanceof Blob){let r;return{size:e.size,uploadBody:e,getBytes:async()=>(r||(r=new Uint8Array(await e.arrayBuffer())),r)}}throw new TypeError("Unsupported file input: expected Uint8Array, ArrayBuffer, Blob, or File")}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared pre-signed URL upload helper for the task artifacts initiative.
|
|
3
|
+
*
|
|
4
|
+
* Implements the three-step upload handshake:
|
|
5
|
+
* 1. request-upload -> Backend returns uploadUrl, formFields, uploadId
|
|
6
|
+
* 2. S3 multipart POST -> SDK uploads directly to PubNub Files storage
|
|
7
|
+
* 3. confirm-upload -> Backend validates and returns result
|
|
8
|
+
*
|
|
9
|
+
* Used by both consumer input (task-client.ts) and provider output
|
|
10
|
+
* (agent-instance.ts). File bytes never flow through the backend.
|
|
11
|
+
*/
|
|
12
|
+
import type { AgentAuth } from './agent-auth.js';
|
|
13
|
+
import type { AuthProvider } from './auth-provider.js';
|
|
14
|
+
/** Fields returned by the backend for direct S3 upload. */
|
|
15
|
+
export interface UploadFormField {
|
|
16
|
+
key: string;
|
|
17
|
+
value: string;
|
|
18
|
+
}
|
|
19
|
+
/** Response from POST /api/v1/files/request-upload (consumer input). */
|
|
20
|
+
export interface RequestUploadResponseConsumer {
|
|
21
|
+
uploadSessionId: string;
|
|
22
|
+
uploadId: string;
|
|
23
|
+
uploadUrl: string;
|
|
24
|
+
formFields: UploadFormField[];
|
|
25
|
+
}
|
|
26
|
+
/** Response from POST /api/v1/files/request-upload (provider output). */
|
|
27
|
+
export interface RequestUploadResponseProvider {
|
|
28
|
+
uploadId: string;
|
|
29
|
+
uploadUrl: string;
|
|
30
|
+
formFields: UploadFormField[];
|
|
31
|
+
}
|
|
32
|
+
/** Response from POST /api/v1/files/confirm-upload (consumer input). */
|
|
33
|
+
export interface ConfirmUploadResponseConsumer {
|
|
34
|
+
uploadId: string;
|
|
35
|
+
}
|
|
36
|
+
/** Response from POST /api/v1/files/confirm-upload (provider output). */
|
|
37
|
+
export interface ConfirmUploadResponseProvider {
|
|
38
|
+
uploadId: string;
|
|
39
|
+
artifactRef: {
|
|
40
|
+
kind: 'file';
|
|
41
|
+
channel: string;
|
|
42
|
+
mimeType: string;
|
|
43
|
+
size: number;
|
|
44
|
+
fileId: string;
|
|
45
|
+
fileName: string;
|
|
46
|
+
hash?: string;
|
|
47
|
+
expiresAt?: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Parameters for a consumer-input request-upload call. */
|
|
51
|
+
export interface ConsumerUploadParams {
|
|
52
|
+
role: 'consumer-input';
|
|
53
|
+
agentName: string;
|
|
54
|
+
fileName: string;
|
|
55
|
+
fileSize: number;
|
|
56
|
+
mimeType: string;
|
|
57
|
+
partId: string;
|
|
58
|
+
uploadSessionId?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Parameters for a provider-output request-upload call. */
|
|
61
|
+
export interface ProviderUploadParams {
|
|
62
|
+
role: 'provider-output';
|
|
63
|
+
taskId: string;
|
|
64
|
+
fileName: string;
|
|
65
|
+
fileSize: number;
|
|
66
|
+
mimeType: string;
|
|
67
|
+
outputId?: string;
|
|
68
|
+
}
|
|
69
|
+
/** Auth context for making backend HTTP calls. */
|
|
70
|
+
export interface FileUploadAuth {
|
|
71
|
+
baseUrl: string;
|
|
72
|
+
authProvider?: AuthProvider;
|
|
73
|
+
agentAuth?: AgentAuth;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Request a pre-signed upload URL from the backend.
|
|
77
|
+
* Returns the upload URL, form fields, upload ID, and (for consumer input)
|
|
78
|
+
* the upload session ID.
|
|
79
|
+
*/
|
|
80
|
+
export declare function requestUpload(auth: FileUploadAuth, params: ConsumerUploadParams): Promise<RequestUploadResponseConsumer>;
|
|
81
|
+
export declare function requestUpload(auth: FileUploadAuth, params: ProviderUploadParams): Promise<RequestUploadResponseProvider>;
|
|
82
|
+
/**
|
|
83
|
+
* Upload file data directly to PubNub Files storage via S3 pre-signed URL.
|
|
84
|
+
* Constructs a multipart/form-data body with all form fields first,
|
|
85
|
+
* then appends the file as the last field named "file".
|
|
86
|
+
*
|
|
87
|
+
* Uses the native `FormData` + `Blob` types available in both Node 18+
|
|
88
|
+
* and all modern browsers. `fetch` computes the multipart boundary
|
|
89
|
+
* automatically -- do NOT set `Content-Type` manually.
|
|
90
|
+
*
|
|
91
|
+
* Returns void on success (S3 returns 204 No Content).
|
|
92
|
+
* Throws on failure (e.g., 400 EntityTooLarge for oversized files).
|
|
93
|
+
*/
|
|
94
|
+
export declare function uploadToStorage(uploadUrl: string, formFields: UploadFormField[], fileData: Uint8Array | ArrayBuffer | Blob, fileName: string, mimeType: string): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Confirm a completed upload with the backend.
|
|
97
|
+
*
|
|
98
|
+
* For consumer input: returns { uploadId }.
|
|
99
|
+
* For provider output: the backend publishes the typed artifact event
|
|
100
|
+
* on the task channel and returns { uploadId, artifactRef }.
|
|
101
|
+
*/
|
|
102
|
+
export declare function confirmUpload(auth: FileUploadAuth, uploadId: string): Promise<ConfirmUploadResponseConsumer>;
|
|
103
|
+
export declare function confirmUpload(auth: FileUploadAuth, uploadId: string, expectArtifactRef: true): Promise<ConfirmUploadResponseProvider>;
|
|
104
|
+
/**
|
|
105
|
+
* Run the complete three-step upload flow for a single file.
|
|
106
|
+
* Shared by consumer input and provider output paths.
|
|
107
|
+
*/
|
|
108
|
+
export declare function uploadFile(auth: FileUploadAuth, params: ConsumerUploadParams, fileData: Uint8Array | ArrayBuffer | Blob): Promise<{
|
|
109
|
+
uploadSessionId: string;
|
|
110
|
+
uploadId: string;
|
|
111
|
+
}>;
|
|
112
|
+
export declare function uploadFile(auth: FileUploadAuth, params: ProviderUploadParams, fileData: Uint8Array | ArrayBuffer | Blob): Promise<ConfirmUploadResponseProvider>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CURRENT_PROTOCOL_VERSION as t,PROTOCOL_VERSION_HEADER as o}from"./protocol-version.js";import{captureAffinity as a,injectAffinity as e}from"./write-affinity.js";async function r(r,n,i){const s=`${r.baseUrl.replace(/\/+$/,"")}${n}`,u=a=>{const n={"Content-Type":"application/json",[o]:t},s=r.authProvider?.getAuthHeader();return s&&(n.Authorization=s),a&&e(n),{method:"POST",headers:n,body:JSON.stringify(i)}};if(r.agentAuth)return r.agentAuth.authenticatedFetch(s,u(!1));const d=await fetch(s,u(!0));if(a(d.headers),401===d.status&&r.authProvider){if(await r.authProvider.onAuthFailure()){const t=await fetch(s,u(!0));return a(t.headers),t}}return d}export async function requestUpload(t,o){const a=await r(t,"/api/v1/files/request-upload",o);if(!a.ok){const t=await a.text().catch(()=>"");throw new Error(`request-upload failed: HTTP ${a.status} ${t}`)}return a.json()}export async function uploadToStorage(t,o,a,e,r){const n=new FormData;for(const t of o)n.append(t.key,t.value);const i=a instanceof Blob?a:new Blob([a],{type:r});n.append("file",i,e);const s=await fetch(t,{method:"POST",body:n});if(!s.ok){const t=await s.text().catch(()=>"");throw new Error(`S3 upload failed: HTTP ${s.status} ${t}`)}}export async function confirmUpload(t,o,a){const e=await r(t,"/api/v1/files/confirm-upload",{uploadId:o});if(!e.ok){const t=await e.text().catch(()=>"");throw new Error(`confirm-upload failed: HTTP ${e.status} ${t}`)}return e.json()}export async function uploadFile(t,o,a){const e=await requestUpload(t,o);if(await uploadToStorage(e.uploadUrl,e.formFields,a,o.fileName,o.mimeType),"provider-output"===o.role){return await confirmUpload(t,e.uploadId,!0)}const r=e;return await confirmUpload(t,e.uploadId),{uploadSessionId:r.uploadSessionId,uploadId:e.uploadId}}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Part builder helpers for constructing SendMessageRequestPart objects.
|
|
3
|
+
*
|
|
4
|
+
* These simplify the consumer experience by handling wire format field
|
|
5
|
+
* names and file reading automatically.
|
|
6
|
+
*
|
|
7
|
+
* Browser-safe: no top-level `node:fs` import. The Node-only
|
|
8
|
+
* `filePartFromPath` helper lazy-imports `node:fs` on call so browser
|
|
9
|
+
* bundlers can tree-shake it out of consumer bundles that don't use
|
|
10
|
+
* filesystem paths.
|
|
11
|
+
*/
|
|
12
|
+
import type { SendMessageRequestPart } from './task-client.js';
|
|
13
|
+
/**
|
|
14
|
+
* Build a text request part.
|
|
15
|
+
*
|
|
16
|
+
* @param text The text content.
|
|
17
|
+
* @param partId The part ID (defaults to 'text'). Must match a declared
|
|
18
|
+
* io.inputs[].id in the agent's card.
|
|
19
|
+
*/
|
|
20
|
+
export declare function textPart(text: string, partId?: string): SendMessageRequestPart;
|
|
21
|
+
/**
|
|
22
|
+
* Build a file request part from raw file data.
|
|
23
|
+
*
|
|
24
|
+
* Universal: works in both Node and browser. No filesystem access.
|
|
25
|
+
* For Node-only file-path convenience, use `filePartFromPath`.
|
|
26
|
+
*
|
|
27
|
+
* Accepts `Uint8Array`, `ArrayBuffer`, `Blob`, or `File`. Browser
|
|
28
|
+
* consumers can pass a `File` from `<input type="file">` directly.
|
|
29
|
+
*
|
|
30
|
+
* @param data Raw file data.
|
|
31
|
+
* @param options Optional overrides for partId, fileName, and contentType.
|
|
32
|
+
*/
|
|
33
|
+
export declare function filePart(data: Uint8Array | ArrayBuffer | Blob | File, options?: {
|
|
34
|
+
partId?: string;
|
|
35
|
+
fileName?: string;
|
|
36
|
+
contentType?: string;
|
|
37
|
+
}): SendMessageRequestPart;
|
|
38
|
+
/**
|
|
39
|
+
* Build a file request part from a filesystem path (Node-only).
|
|
40
|
+
*
|
|
41
|
+
* Lazy-imports `node:fs` on first call so this helper can coexist
|
|
42
|
+
* with browser bundlers without pulling `node:fs` into the bundle.
|
|
43
|
+
* Not available in browsers.
|
|
44
|
+
*
|
|
45
|
+
* @param path Filesystem path.
|
|
46
|
+
* @param options Optional overrides for partId, fileName, and contentType.
|
|
47
|
+
*/
|
|
48
|
+
export declare function filePartFromPath(path: string, options?: {
|
|
49
|
+
partId?: string;
|
|
50
|
+
fileName?: string;
|
|
51
|
+
contentType?: string;
|
|
52
|
+
}): Promise<SendMessageRequestPart>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){const t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return t>=0?e.slice(t+1):e}export function textPart(e,t="text"){return{partId:t,text:e}}export function filePart(e,t){const n=t?.partId??"file",i="undefined"!=typeof File&&e instanceof File?e.name:void 0,a="undefined"!=typeof Blob&&e instanceof Blob&&e.type?e.type:void 0;return{partId:n,file:e,fileName:t?.fileName??i??"file",contentType:t?.contentType??a??"application/octet-stream"}}export async function filePartFromPath(t,n){const{readFileSync:i}=await import("node:fs"),a=i(t),o=new Uint8Array(a);return{partId:n?.partId??"file",file:o,fileName:n?.fileName??e(t),contentType:n?.contentType??"application/octet-stream"}}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol versioning constants and helpers for the Blocks Node SDK.
|
|
3
|
+
*
|
|
4
|
+
* Centralizes the protocol version contract so no other file needs to
|
|
5
|
+
* hardcode version strings or header names.
|
|
6
|
+
*/
|
|
7
|
+
/** Current protocol version used by this SDK build. */
|
|
8
|
+
export declare const CURRENT_PROTOCOL_VERSION = "2026-05-01";
|
|
9
|
+
/** All protocol versions this SDK can speak. */
|
|
10
|
+
export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly string[];
|
|
11
|
+
/** Protocol versions that are deprecated but still functional. */
|
|
12
|
+
export declare const DEPRECATED_PROTOCOL_VERSIONS: readonly string[];
|
|
13
|
+
/** HTTP header name for protocol version negotiation. */
|
|
14
|
+
export declare const PROTOCOL_VERSION_HEADER = "Blocks-Protocol-Version";
|
|
15
|
+
/** SDK package version (kept in sync with package.json manually). */
|
|
16
|
+
export declare const SDK_VERSION = "0.1.27";
|
|
17
|
+
/** Check whether a given protocol version is supported by this SDK. */
|
|
18
|
+
export declare function isProtocolVersionSupported(version: string): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CURRENT_PROTOCOL_VERSION="2026-05-01";export const SUPPORTED_PROTOCOL_VERSIONS=["2026-05-01"];export const DEPRECATED_PROTOCOL_VERSIONS=[];export const PROTOCOL_VERSION_HEADER="Blocks-Protocol-Version";export const SDK_VERSION="0.1.27";export function isProtocolVersionSupported(O){return SUPPORTED_PROTOCOL_VERSIONS.includes(O)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"pubnub";export const createPubNubClient=r=>{if(!r.subscribeKey||!r.publishKey)throw new Error("PUBNUB keys not configured");return new e({publishKey:r.publishKey,subscribeKey:r.subscribeKey,userId:r.userId??"blocks-agent",enableEventEngine:!0,...void 0!==r.presenceTimeout?{presenceTimeout:r.presenceTimeout}:{}})};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for PubNub SDK compatibility.
|
|
3
|
+
*
|
|
4
|
+
* The PubNub SDK has a strict `Payload` type that doesn't accept `unknown`.
|
|
5
|
+
* This file provides type-safe interfaces and helpers that work with both:
|
|
6
|
+
* - Node.js PubNub SDK (pubnub package)
|
|
7
|
+
* - PubNub Functions runtime (built-in pubnub module)
|
|
8
|
+
*/
|
|
9
|
+
import type PubNub from 'pubnub';
|
|
10
|
+
import type { Payload } from 'pubnub';
|
|
11
|
+
/**
|
|
12
|
+
* Cast any JSON-serializable object to PubNub's Payload type.
|
|
13
|
+
* Use this when publishing messages that don't strictly satisfy the Payload type.
|
|
14
|
+
*/
|
|
15
|
+
export declare const asPayload: (obj: Record<string, unknown>) => Payload;
|
|
16
|
+
/**
|
|
17
|
+
* Cast to Payload or undefined for meta fields.
|
|
18
|
+
*/
|
|
19
|
+
export declare const asPayloadMeta: (obj: Record<string, unknown>) => Payload | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* JSON-serializable value that's compatible with PubNub's Payload type.
|
|
22
|
+
* Use this instead of `unknown` for message properties.
|
|
23
|
+
*/
|
|
24
|
+
export type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
|
|
25
|
+
export interface JsonObject {
|
|
26
|
+
[key: string]: JsonValue;
|
|
27
|
+
}
|
|
28
|
+
export type JsonArray = JsonValue[];
|
|
29
|
+
/**
|
|
30
|
+
* Convert an object to a PubNub-compatible Payload.
|
|
31
|
+
* This is a type assertion helper that ensures type safety at the boundary.
|
|
32
|
+
*/
|
|
33
|
+
export declare const toPayload: <T extends JsonObject>(obj: T) => Payload;
|
|
34
|
+
/**
|
|
35
|
+
* Safely cast a message from PubNub to a typed object.
|
|
36
|
+
*/
|
|
37
|
+
export declare const fromPayload: <T>(payload: unknown) => T;
|
|
38
|
+
/**
|
|
39
|
+
* Partial PubNub client interface for publish operations.
|
|
40
|
+
* Compatible with both full SDK and Functions runtime.
|
|
41
|
+
*/
|
|
42
|
+
export interface PubNubPublisher {
|
|
43
|
+
publish(params: {
|
|
44
|
+
channel: string;
|
|
45
|
+
message: Payload;
|
|
46
|
+
storeInHistory?: boolean;
|
|
47
|
+
sendByPost?: boolean;
|
|
48
|
+
meta?: Payload;
|
|
49
|
+
}): Promise<{
|
|
50
|
+
timetoken: string | number;
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Partial PubNub client interface for message actions.
|
|
55
|
+
*/
|
|
56
|
+
export interface PubNubMessageActions {
|
|
57
|
+
addMessageAction?(params: {
|
|
58
|
+
channel: string;
|
|
59
|
+
messageTimetoken: string;
|
|
60
|
+
action: {
|
|
61
|
+
type: string;
|
|
62
|
+
value: string;
|
|
63
|
+
};
|
|
64
|
+
}): Promise<unknown>;
|
|
65
|
+
getMessageActions?(params: {
|
|
66
|
+
channel: string;
|
|
67
|
+
start?: string;
|
|
68
|
+
limit?: number;
|
|
69
|
+
}): Promise<{
|
|
70
|
+
data?: Array<{
|
|
71
|
+
type: string;
|
|
72
|
+
value: string;
|
|
73
|
+
actionTimetoken?: string;
|
|
74
|
+
}>;
|
|
75
|
+
}>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Message entry from fetchMessages response.
|
|
79
|
+
*/
|
|
80
|
+
export interface FetchedMessage {
|
|
81
|
+
message: unknown;
|
|
82
|
+
timetoken: string;
|
|
83
|
+
meta?: unknown;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Partial PubNub client interface for fetching message history.
|
|
87
|
+
* Uses a permissive signature to be compatible with the actual SDK's overloaded methods.
|
|
88
|
+
*/
|
|
89
|
+
export interface PubNubFetcher {
|
|
90
|
+
fetchMessages?(params: {
|
|
91
|
+
channels: string[];
|
|
92
|
+
count?: number;
|
|
93
|
+
start?: string;
|
|
94
|
+
end?: string;
|
|
95
|
+
}): Promise<{
|
|
96
|
+
channels?: Record<string, FetchedMessage[]>;
|
|
97
|
+
}>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Type helper to safely pass PubNub to functions expecting partial interfaces.
|
|
101
|
+
* The SDK uses overloaded methods that don't directly match our simpler types.
|
|
102
|
+
*/
|
|
103
|
+
export declare const asPubNubFetcher: (pubnub: unknown) => PubNubFetcher | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Combined partial PubNub interface for task index operations.
|
|
106
|
+
*/
|
|
107
|
+
export type PartialPubNubForIndex = PubNubPublisher & Partial<PubNubMessageActions> & Partial<PubNubFetcher>;
|
|
108
|
+
/**
|
|
109
|
+
* Full PubNub client with all optional methods.
|
|
110
|
+
*/
|
|
111
|
+
export type FullPubNub = PubNub;
|
|
112
|
+
/**
|
|
113
|
+
* Check if a PubNub client supports message actions.
|
|
114
|
+
*/
|
|
115
|
+
export declare const supportsMessageActions: (pubnub: PartialPubNubForIndex) => pubnub is PartialPubNubForIndex & Required<PubNubMessageActions>;
|
|
116
|
+
/**
|
|
117
|
+
* Check if a PubNub client supports fetchMessages.
|
|
118
|
+
*/
|
|
119
|
+
export declare const supportsFetchMessages: (pubnub: PartialPubNubForIndex) => pubnub is PartialPubNubForIndex & Required<PubNubFetcher>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const asPayload=t=>t;export const asPayloadMeta=t=>t;export const toPayload=t=>t;export const fromPayload=t=>t;export const asPubNubFetcher=t=>{if(!t||"object"!=typeof t)return;return"function"==typeof t.fetchMessages?t:void 0};export const supportsMessageActions=t=>"function"==typeof t.addMessageAction;export const supportsFetchMessages=t=>"function"==typeof t.fetchMessages;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared JSON-RPC infrastructure for calling the Blocks backend RPC endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - `withRetry()` — exponential-backoff retry for transient network errors
|
|
6
|
+
* - `rpcEndpoint()` — builds the RPC URL from a backend base URL
|
|
7
|
+
* - `callRpc()` — sends a JSON-RPC 2.0 request with retry and error handling
|
|
8
|
+
* - `RpcError` — structured error for JSON-RPC error responses
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentAuth } from './agent-auth.js';
|
|
11
|
+
import type { AuthProvider } from './auth-provider.js';
|
|
12
|
+
export interface RpcClientConfig {
|
|
13
|
+
subscribeKey: string;
|
|
14
|
+
authProvider?: AuthProvider;
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
agentAuth?: AgentAuth;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Retry helper for transient network errors (DNS failures, timeouts, etc.)
|
|
20
|
+
*/
|
|
21
|
+
export declare function withRetry<T>(fn: () => Promise<T>, maxRetries?: number, baseDelayMs?: number): Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Build the RPC gateway URL from a backend base URL.
|
|
24
|
+
* baseUrl must be a root URL (e.g. http://localhost:3001).
|
|
25
|
+
*/
|
|
26
|
+
export declare function rpcEndpoint(subscribeKey: string, baseUrl?: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Structured error for JSON-RPC error responses.
|
|
29
|
+
*/
|
|
30
|
+
export declare class RpcError extends Error {
|
|
31
|
+
code?: number;
|
|
32
|
+
rpcMessage: string;
|
|
33
|
+
data?: unknown;
|
|
34
|
+
constructor(rpcMessage: string, code?: number, data?: unknown);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Send a JSON-RPC 2.0 request to the Blocks backend RPC endpoint.
|
|
38
|
+
*
|
|
39
|
+
* Handles:
|
|
40
|
+
* - JSON-RPC envelope construction
|
|
41
|
+
* - Authorization header (Bearer token) when an auth provider supplies one
|
|
42
|
+
* - Transient-error retry via `withRetry()`
|
|
43
|
+
* - HTTP and JSON-RPC error mapping to `RpcError`
|
|
44
|
+
*/
|
|
45
|
+
export declare function callRpc<T>(config: RpcClientConfig, method: string, params: Record<string, unknown>): Promise<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CURRENT_PROTOCOL_VERSION as r,PROTOCOL_VERSION_HEADER as t}from"./protocol-version.js";import{captureAffinity as e,injectAffinity as o}from"./write-affinity.js";export async function withRetry(r,t=3,e=500){let o;for(let n=0;n<t;n++)try{return await r()}catch(r){o=r;const a=String(r);if(!(a.includes("ENOTFOUND")||a.includes("ETIMEDOUT")||a.includes("ECONNRESET")||a.includes("NetworkIssues"))||n===t-1)throw r;const s=e*Math.pow(2,n)+100*Math.random();await new Promise(r=>setTimeout(r,s))}throw o}export function rpcEndpoint(r,t){return t?`${t.replace(/\/+$/,"")}/api/v1/rpc`:`https://ps.pndsn.com/v1/blocks/sub-key/${r}/rpc`}export class RpcError extends Error{constructor(r,t,e){super(`[RPC] ${r}`),this.name="RpcError",this.rpcMessage=r,this.code=t,this.data=e}}export async function callRpc(n,a,s){const i=rpcEndpoint(n.subscribeKey,n.baseUrl),c=`rpc-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,h=e=>{const a={"Content-Type":"application/json",[t]:r},s=n.authProvider?.getAuthHeader();return s&&(a.Authorization=s),e&&o(a),a},u={jsonrpc:"2.0",id:c,method:a,params:s},p=async()=>{let r;if(n.agentAuth?r=await n.agentAuth.authenticatedFetch(i,{method:"POST",headers:h(!1),body:JSON.stringify(u)}):(r=await fetch(i,{method:"POST",headers:h(!0),body:JSON.stringify(u)}),e(r.headers)),!r.ok)throw new RpcError(`HTTP ${r.status}`,r.status);const t=await r.json();if(t.error){const r=t.error.data?.message??t.error.message??"Unknown RPC error";throw new RpcError(r,t.error.code,t.error.data)}return t.result};return withRetry(async()=>{try{return await p()}catch(r){if(r instanceof RpcError&&401===r.code&&n.authProvider&&!n.agentAuth){if(await n.authProvider.onAuthFailure())return p()}throw r}})}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream Processing Context
|
|
3
|
+
*
|
|
4
|
+
* Wraps a StreamClient from the Stream SDK and manages the onActivate
|
|
5
|
+
* callback lifecycle. Each embedded stream ID maps to one processing
|
|
6
|
+
* context. The context owns the StreamClient instance and provides the
|
|
7
|
+
* stream object interface to onActivate callbacks.
|
|
8
|
+
*
|
|
9
|
+
* onActivate runs as an async task (microtask/promise) on the stream
|
|
10
|
+
* processing context, not the handler thread. Unhandled errors in
|
|
11
|
+
* onActivate trigger automatic failStream.
|
|
12
|
+
*
|
|
13
|
+
* `StreamObject.end()` is task-scoped: it delegates to the agent-instance
|
|
14
|
+
* `releaseStream(streamId, taskId)` hook, which evicts the per-task handle
|
|
15
|
+
* cache entry, releases the registry taskId, and — only when the last
|
|
16
|
+
* ref-holder releases — tears down the underlying StreamClient. On shared
|
|
17
|
+
* streams the teardown never publishes a `stream_end` marker (see
|
|
18
|
+
* SDK_CONTRACT §8.4.1a shared-affinity carve-out).
|
|
19
|
+
*/
|
|
20
|
+
import type { StreamClient, InboundMessage } from '../stream/index.js';
|
|
21
|
+
/** Hook the agent-instance passes to the stream wrapper so `end()` can
|
|
22
|
+
* route through the registry + handle-cache eviction path. Decouples
|
|
23
|
+
* stream-context.ts from agent-instance.ts (no import cycle). */
|
|
24
|
+
export interface AgentInstanceHooks {
|
|
25
|
+
releaseStream: (streamId: string, taskId: string) => Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/** The stream object passed to onActivate and returned from createStream. */
|
|
28
|
+
export interface StreamObject {
|
|
29
|
+
readonly streamId: string;
|
|
30
|
+
readonly channel: string;
|
|
31
|
+
readonly isActive: boolean;
|
|
32
|
+
readonly external: boolean;
|
|
33
|
+
write(data: string | Uint8Array | unknown): void;
|
|
34
|
+
end(): Promise<void>;
|
|
35
|
+
readonly inbound: AsyncIterable<InboundMessage>;
|
|
36
|
+
onEnd(cb: () => void): void;
|
|
37
|
+
/** T7a token (only available on external streams). */
|
|
38
|
+
readonly token?: string;
|
|
39
|
+
/** Activate an external stream (only available on external streams). */
|
|
40
|
+
activate?(opts?: {
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
export type OnActivateCallback = (stream: StreamObject) => void | Promise<void>;
|
|
45
|
+
export type FailStreamCallback = (streamId: string, error: string) => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Create a StreamObject wrapper around a StreamClient.
|
|
48
|
+
* This is the shape passed to onActivate and returned from createStream.
|
|
49
|
+
*
|
|
50
|
+
* `hooks.releaseStream` — when provided, `end()` delegates to it so the
|
|
51
|
+
* agent-instance can run task-scoped cleanup (registry release,
|
|
52
|
+
* handle-cache eviction, affinity-gated teardown). Omit for synthetic
|
|
53
|
+
* test wrappers with no agent-instance owner — `end()` falls back to
|
|
54
|
+
* calling `client.end()` directly.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createStreamObject(streamId: string, client: StreamClient, taskId?: string, hooks?: AgentInstanceHooks): StreamObject;
|
|
57
|
+
/**
|
|
58
|
+
* Create a StreamObject for an external stream (no StreamClient).
|
|
59
|
+
* write() and inbound throw; token and activate are available.
|
|
60
|
+
*/
|
|
61
|
+
export declare function createExternalStreamObject(streamId: string, channel: string, t7aToken: string, activateFn: (opts?: {
|
|
62
|
+
metadata?: Record<string, unknown>;
|
|
63
|
+
}) => Promise<void>): StreamObject;
|
|
64
|
+
/**
|
|
65
|
+
* Run the onActivate callback on the stream processing context.
|
|
66
|
+
* Returns a promise that resolves when the callback completes.
|
|
67
|
+
* If the callback throws, the error is caught and failStream is called.
|
|
68
|
+
*/
|
|
69
|
+
export declare function runOnActivate(streamId: string, streamObject: StreamObject, callback: OnActivateCallback, failStreamCb: FailStreamCallback): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function createStreamObject(e,t,r,n){return{get streamId(){return e},get channel(){return t.channel},get isActive(){return t.isActive},get external(){return!1},write(e){t.write(e)},async end(){n&&r?await n.releaseStream(e,r):await t.end()},get inbound(){return t.inbound},onEnd(e){t.onEnd(e)}}}export function createExternalStreamObject(e,t,r,n){let a=!1;const o=[];return{get streamId(){return e},get channel(){return t},get isActive(){return!a},get external(){return!0},write(){throw new Error("Cannot write to an external stream -- use Stream SDK directly")},async end(){a=!0;for(const e of o)e();o.length=0},get inbound(){throw new Error("Cannot read from an external stream")},onEnd(e){o.push(e)},get token(){return r},activate:n}}export function runOnActivate(e,t,r,n){return Promise.resolve().then(()=>r(t)).catch(async t=>{const r=t instanceof Error?t.message:String(t);console.error(`[StreamContext] onActivate error for stream "${e}":`,r);try{await n(e,"stream_crashed")}catch(t){console.error(`[StreamContext] failStream error for "${e}":`,t)}})}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StreamRef - Consumer-side bridge between task events and Stream SDK.
|
|
3
|
+
*
|
|
4
|
+
* StreamRef wraps a StreamDescriptor and provides open() to create a
|
|
5
|
+
* StreamClient via fromDescriptor(). open() is idempotent while the
|
|
6
|
+
* stream client is active and must not create duplicate clients.
|
|
7
|
+
*
|
|
8
|
+
* When the owning `TaskSession` is in a terminal state at the time
|
|
9
|
+
* `open()` is called, the SDK short-circuits with `StreamUnavailableError`
|
|
10
|
+
* instead of constructing a dead client against an already-revoked PAM
|
|
11
|
+
* token. Stream data is live-only; on reconnect after termination, only
|
|
12
|
+
* the descriptor metadata and task artifacts remain accessible.
|
|
13
|
+
*/
|
|
14
|
+
import { StreamClient, type StreamDescriptor, type StreamClientFromDescriptorOptions } from '../stream/index.js';
|
|
15
|
+
export { type StreamDescriptor } from '../stream/index.js';
|
|
16
|
+
/**
|
|
17
|
+
* Thrown by `StreamRef.open()` when the owning session's task is in a
|
|
18
|
+
* terminal state. The error's `terminalState` field lets consumers branch
|
|
19
|
+
* programmatically; the message points at accessible alternatives
|
|
20
|
+
* (`ref.descriptor`, `session.listArtifacts()`, `session.state`).
|
|
21
|
+
*/
|
|
22
|
+
export declare class StreamUnavailableError extends Error {
|
|
23
|
+
readonly taskId: string;
|
|
24
|
+
readonly streamId: string;
|
|
25
|
+
readonly declaredStream?: string;
|
|
26
|
+
readonly terminalState: string;
|
|
27
|
+
constructor(message: string, fields: {
|
|
28
|
+
taskId: string;
|
|
29
|
+
streamId: string;
|
|
30
|
+
declaredStream?: string;
|
|
31
|
+
terminalState: string;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export declare class StreamRef {
|
|
35
|
+
readonly descriptor: StreamDescriptor;
|
|
36
|
+
private _client;
|
|
37
|
+
private _clientEnded;
|
|
38
|
+
private readonly _sdkOptions;
|
|
39
|
+
private readonly _onOpen?;
|
|
40
|
+
private readonly _sessionState?;
|
|
41
|
+
constructor(descriptor: StreamDescriptor, sdkOptions: StreamClientFromDescriptorOptions, hooks?: {
|
|
42
|
+
onOpen?: (client: StreamClient) => void;
|
|
43
|
+
sessionState?: () => string | undefined;
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Open a StreamClient from this ref's descriptor.
|
|
47
|
+
*
|
|
48
|
+
* Resolution order (first match wins):
|
|
49
|
+
*
|
|
50
|
+
* 1. If a StreamClient was previously opened and is still active,
|
|
51
|
+
* return that same client (idempotency). This also applies while
|
|
52
|
+
* the session is draining after a terminal event — a consumer
|
|
53
|
+
* that holds a live client MUST continue to receive it.
|
|
54
|
+
* 2. If the previously opened client has already ended, throw a
|
|
55
|
+
* generic Error ("already been ended"). The terminal short-
|
|
56
|
+
* circuit does NOT fire in this path, because "already ended"
|
|
57
|
+
* is the more specific signal for "no new client here".
|
|
58
|
+
* 3. If the owning session's task is in a terminal state
|
|
59
|
+
* (`completed`, `failed`, `canceled`) AND no client has ever
|
|
60
|
+
* been constructed for this ref, throw `StreamUnavailableError`.
|
|
61
|
+
* Stream data is live-only; use `ref.descriptor`,
|
|
62
|
+
* `session.listArtifacts()`, or `session.state` to inspect a
|
|
63
|
+
* terminal session.
|
|
64
|
+
* 4. Otherwise, construct a new StreamClient from the descriptor.
|
|
65
|
+
*
|
|
66
|
+
* Uses descriptor.format for the wire format. No caller-supplied format
|
|
67
|
+
* override is accepted.
|
|
68
|
+
*/
|
|
69
|
+
open(options?: {
|
|
70
|
+
reorderTimeoutMs?: number;
|
|
71
|
+
}): StreamClient;
|
|
72
|
+
/** Whether this ref's stream client is currently active. */
|
|
73
|
+
get isOpen(): boolean;
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{StreamClient as t}from"../stream/index.js";import{TERMINAL_STATES as e}from"./task-session.js";export class StreamUnavailableError extends Error{constructor(t,e){super(t),this.name="StreamUnavailableError",this.taskId=e.taskId,this.streamId=e.streamId,this.declaredStream=e.declaredStream,this.terminalState=e.terminalState}}export class StreamRef{constructor(t,e,s){this._client=null,this._clientEnded=!1,this.descriptor=t,this._sdkOptions=e,this._onOpen=s?.onOpen,this._sessionState=s?.sessionState}open(s){if(this._client&&this._client.isActive)return this._client;if(this._clientEnded)throw new Error(`StreamRef for "${this.descriptor.streamId}" has already been ended and cannot be reopened`);const r=this._sessionState?.();if(r&&e.has(r)){const t=this.descriptor.declaredStream??this.descriptor.streamId;throw new StreamUnavailableError(`Cannot open stream "${t}" on task "${this.descriptor.taskId}": the task is in terminal state "${r}" and stream data is live-only (not persisted after a task ends). The stream's metadata remains available on \`ref.descriptor\`; task artifacts are available via \`session.listArtifacts()\`; the final task state is in \`session.state\`.`,{taskId:this.descriptor.taskId,streamId:this.descriptor.streamId,declaredStream:this.descriptor.declaredStream,terminalState:r})}const i=void 0!==s?.reorderTimeoutMs?{...this._sdkOptions,reorderTimeoutMs:s.reorderTimeoutMs}:this._sdkOptions,a=t.fromDescriptor(this.descriptor,i);return a.onEnd(()=>{this._clientEnded=!0,this._client=null}),this._client=a,this._onOpen?.(a),a}get isOpen(){return null!==this._client&&this._client.isActive}}
|