@astralform/js 0.2.3 → 1.0.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/dist/index.d.ts CHANGED
@@ -1,579 +1,513 @@
1
+ interface AgentIdentity {
2
+ name: string;
3
+ displayName?: string | null;
4
+ avatarUrl?: string | null;
5
+ description?: string | null;
6
+ }
7
+ type TaskStatus = "pending" | "in_progress" | "completed" | "deleted";
8
+ interface TodoItem {
9
+ id: number;
10
+ subject: string;
11
+ status: TaskStatus;
12
+ description?: string | null;
13
+ activeForm?: string | null;
14
+ owner?: string | null;
15
+ blockedBy?: number[] | null;
16
+ blocks?: number[] | null;
17
+ priority?: number | null;
18
+ }
19
+ interface TodoUpdatePayload {
20
+ todos: TodoItem[];
21
+ }
22
+ interface TitleGeneratedPayload {
23
+ title: string;
24
+ }
25
+ interface SubagentStartPayload {
26
+ agent: AgentIdentity;
27
+ taskCallId?: string | null;
28
+ }
29
+ interface SubagentStopPayload {
30
+ agent: AgentIdentity;
31
+ taskCallId?: string | null;
32
+ }
33
+ interface ContextWarningPayload {
34
+ /** Known values: "info" | "warning" | "critical". Typed as string for forward compat. */
35
+ severity: string;
36
+ utilizationPct: number;
37
+ remainingTokens: number;
38
+ windowTokens: number;
39
+ inputTokens: number;
40
+ message: string;
41
+ }
42
+ interface ContextUpdatePayload {
43
+ phase?: string | null;
44
+ updatedAt?: number | null;
45
+ context: Record<string, unknown>;
46
+ }
1
47
  /**
2
- * BlockBuilder pure rendering engine. Zero default behavior.
3
- *
4
- * Clients register handlers that map events to blocks.
5
- * Both live streaming and restore go through the same engine.
6
- *
7
- * import { BlockBuilder, standardHandlers } from "@astralform/js";
8
- * const builder = new BlockBuilder();
9
- * builder.registerHandlers(standardHandlers);
48
+ * A single memory entry returned by ``memory_recall``. Backend may add
49
+ * fields over time, so the shape is intentionally open-ended.
10
50
  */
11
-
12
- interface UserBlock {
13
- type: "user";
51
+ interface MemoryRecord {
14
52
  id: string;
15
53
  content: string;
16
- createdAt?: number;
54
+ [key: string]: unknown;
17
55
  }
18
- interface TextBlock {
19
- type: "text";
20
- id: string;
21
- content: string;
22
- isStreaming: boolean;
56
+ interface MemoryRecallPayload {
57
+ memories: MemoryRecord[];
23
58
  }
24
- interface ThinkingBlock {
25
- type: "thinking";
26
- id: string;
27
- content: string;
28
- isActive: boolean;
29
- durationMs?: number;
59
+ interface MemoryUpdatePayload {
60
+ /** Known values: "created" | "updated" | "deleted". Typed as string for forward compat. */
61
+ action: string;
62
+ memoryId?: string | null;
63
+ key?: string | null;
64
+ namespace?: string | null;
30
65
  }
31
- interface AgentBlock {
32
- type: "agent";
33
- id: string;
34
- agentName: string;
35
- displayName?: string;
36
- avatarUrl?: string;
66
+ interface DesktopStreamPayload {
67
+ url: string;
68
+ sandboxId?: string | null;
37
69
  }
38
- interface SubagentBlock {
39
- type: "subagent";
40
- id: string;
41
- agentName: string;
42
- displayName: string;
43
- toolCallId: string;
44
- avatarUrl?: string;
45
- description?: string;
46
- content: string;
47
- isActive: boolean;
70
+ interface AttachmentStagedPayload {
71
+ attachmentId: string;
72
+ filename: string;
73
+ contentType?: string | null;
74
+ sizeBytes?: number | null;
48
75
  }
49
- interface ToolBlock {
50
- type: "tool";
51
- id: string;
52
- callId: string;
53
- toolName: string;
54
- displayName?: string;
55
- description?: string;
56
- arguments?: Record<string, unknown>;
57
- status: string;
58
- iconUrl?: string;
59
- toolCategory?: string;
60
- sources?: {
61
- title: string;
62
- url: string;
63
- snippet?: string;
64
- }[];
65
- durationMs?: number;
66
- result?: string;
67
- }
68
- interface CapsuleBlock {
69
- type: "capsule";
70
- id: string;
71
- callId: string;
72
- toolName: string;
73
- command?: string;
74
- output: string;
75
- durationMs?: number;
76
- isActive: boolean;
76
+ interface WorkspaceReadyPayload {
77
+ sandboxId: string;
78
+ workspacePath?: string | null;
77
79
  }
78
- interface AssetBlock {
79
- type: "asset";
80
- id: string;
80
+ interface AssetCreatedPayload {
81
81
  assetId: string;
82
- name: string;
83
- url: string;
84
- mediaType: string;
85
- sizeBytes: number;
82
+ filename: string;
83
+ url?: string | null;
84
+ contentType?: string | null;
86
85
  }
87
- interface TodoBlock {
88
- type: "todo";
89
- id: string;
90
- todos: {
91
- content: string;
92
- status: string;
93
- }[];
86
+ interface ToolApprovalRequestedPayload {
87
+ toolName: string;
88
+ callId: string;
89
+ arguments: Record<string, unknown>;
90
+ riskLevel?: string | null;
91
+ reason?: string | null;
94
92
  }
95
- interface EditorBlock {
96
- type: "editor";
97
- id: string;
93
+ interface ToolApprovalGrantedPayload {
94
+ toolName: string;
98
95
  callId: string;
99
- path: string;
100
- language: string;
101
- content: string;
102
- isStreaming: boolean;
103
96
  }
104
- interface ErrorBlock {
105
- type: "error";
106
- id: string;
107
- message: string;
97
+ interface ToolPermissionDeniedPayload {
98
+ toolName: string;
99
+ callId: string;
100
+ reason?: string | null;
101
+ /** Known values: "hook" | "rule" | "user" | "timeout" | "circuit_breaker". */
102
+ deniedBy?: string | null;
108
103
  }
109
- interface DesktopStreamBlock {
110
- type: "desktop_stream";
111
- id: string;
112
- url: string;
113
- authKey: string;
114
- sandboxId: string;
104
+ interface ToolHarnessWarningPayload {
105
+ toolName: string;
106
+ callId: string;
107
+ message?: string | null;
108
+ details?: Record<string, unknown> | null;
115
109
  }
116
- interface AttachmentBlock {
117
- type: "attachment";
118
- id: string;
119
- files: {
120
- name: string;
121
- path: string;
122
- mediaType: string;
123
- sizeBytes: number;
124
- }[];
125
- }
126
- type Block = UserBlock | TextBlock | ThinkingBlock | AgentBlock | SubagentBlock | ToolBlock | CapsuleBlock | AssetBlock | TodoBlock | EditorBlock | DesktopStreamBlock | AttachmentBlock | ErrorBlock;
127
- type EventHandler$1 = (event: ChatEvent, builder: BlockBuilder) => void;
128
- declare class BlockBuilder {
129
- private _blocks;
130
- private _handlers;
131
- private _onChange;
132
- activeTextId: string | null;
133
- activeThinkingId: string | null;
134
- thinkingStartMs: number | null;
135
- activeEditorId: string | null;
136
- activeTodoId: string | null;
137
- on(eventType: string, handler: EventHandler$1 | null): void;
138
- registerHandlers(handlers: Record<string, EventHandler$1 | null>): void;
139
- processEvent(event: ChatEvent): void;
140
- getBlocks(): Block[];
141
- reset(): void;
142
- setOnChange(fn: (() => void) | null): void;
143
- addBlock(block: Block): void;
144
- updateBlock<T extends Block["type"]>(id: string, updater: (block: Extract<Block, {
145
- type: T;
146
- }>) => Extract<Block, {
147
- type: T;
148
- }>): void;
149
- /** Update any block by id with a partial update (type-loose for handlers). */
150
- patchBlock(id: string, patch: Partial<Block>): void;
151
- findBlock(predicate: (b: Block) => boolean): Block | undefined;
152
- nextId(): string;
153
- private _notify;
110
+ interface UserUnavailablePayload {
111
+ consecutiveTimeouts: number;
112
+ toolName?: string | null;
113
+ }
114
+ interface PromptSuggestionPayload {
115
+ suggestions: string[];
154
116
  }
155
117
 
156
- interface AstralformConfig {
157
- apiKey: string;
118
+ interface AstralformBaseConfig {
119
+ /** Override the default API origin. Defaults to https://api.astralform.ai. */
158
120
  baseURL?: string;
159
- userId: string;
121
+ /** Supply a custom fetch (SSR, testing, custom interceptors). */
160
122
  fetch?: typeof globalThis.fetch;
161
123
  }
124
+ interface AstralformApiKeyConfig extends AstralformBaseConfig {
125
+ /** Project API key (`sk_live_...` or `sk_test_...`). */
126
+ apiKey: string;
127
+ /**
128
+ * The customer's own identifier for the end user making this call.
129
+ * Sent as the `X-End-User-ID` header. Required in API-key mode.
130
+ */
131
+ userId: string;
132
+ }
133
+ interface AstralformUserTokenConfig extends AstralformBaseConfig {
134
+ /**
135
+ * OIDC access token issued by the Astralform Identity Provider.
136
+ * Expect this to be short-lived; use `client.updateAccessToken()` after
137
+ * refreshing to hot-swap without re-instantiating the client.
138
+ */
139
+ accessToken: string;
140
+ /**
141
+ * Active project context. Sent as the `X-Project-ID` header. The backend
142
+ * verifies the token's developer has access to this project on every
143
+ * request; switching projects is a local `updateProjectId()` call.
144
+ *
145
+ * Optional so a pre-pick client (right after login, before the user has
146
+ * chosen a team/project) can still call account-scoped discovery routes
147
+ * like `listTeams()` / `listProjects(teamId)`. Project-scoped calls
148
+ * (conversations, messages, chat) will error out until one is set.
149
+ */
150
+ projectId?: string;
151
+ /**
152
+ * Optional end-user override — lets a developer acting under a user
153
+ * token impersonate a downstream end-user identity for testing
154
+ * purposes. When set, sent alongside `X-Project-ID` as `X-End-User-ID`
155
+ * so memory, rate limits, and conversations scope to the specified
156
+ * end-user rather than the developer themselves.
157
+ *
158
+ * Use `client.updateEndUserId()` to rotate at runtime.
159
+ */
160
+ endUserId?: string;
161
+ }
162
+ type AstralformConfig = AstralformApiKeyConfig | AstralformUserTokenConfig;
162
163
  declare const ChatEventType: {
163
164
  readonly Connected: "connected";
164
- readonly BlocksChanged: "blocks_changed";
165
+ readonly Disconnected: "disconnected";
166
+ readonly MessageStart: "message_start";
167
+ readonly MessageStop: "message_stop";
168
+ readonly BlockStart: "block_start";
169
+ readonly BlockDelta: "block_delta";
170
+ readonly BlockStop: "block_stop";
171
+ readonly Stall: "stall";
172
+ readonly Retry: "retry";
173
+ readonly Error: "error";
174
+ readonly Keepalive: "keepalive";
165
175
  readonly UserMessage: "user_message";
166
176
  readonly TitleGenerated: "title_generated";
167
- readonly ModelInfo: "model_info";
168
- readonly Chunk: "chunk";
169
- readonly ToolCall: "tool_call";
170
- readonly ToolExecuting: "tool_executing";
171
- readonly ToolProgress: "tool_progress";
172
- readonly ToolCompleted: "tool_completed";
173
- readonly ToolEnd: "tool_end";
174
- readonly AgentStart: "agent_start";
175
- readonly AgentEnd: "agent_end";
176
- readonly ThinkingDelta: "thinking_delta";
177
- readonly ThinkingComplete: "thinking_complete";
178
- readonly SubagentStart: "subagent_start";
179
- readonly SubagentChunk: "subagent_chunk";
180
- readonly SubagentUpdate: "subagent_update";
181
- readonly SubagentEnd: "subagent_end";
182
- readonly SubagentToolUse: "subagent_tool_use";
183
- readonly CapsuleOutput: "capsule_output";
184
- readonly CapsuleOutputChunk: "capsule_output_chunk";
185
- readonly AssetCreated: "asset_created";
186
177
  readonly TodoUpdate: "todo_update";
187
- readonly EditorContentStart: "editor_content_start";
188
- readonly EditorContentDelta: "editor_content_delta";
189
- readonly EditorContentEnd: "editor_content_end";
190
- readonly Complete: "complete";
191
- readonly Error: "error";
192
- readonly Disconnected: "disconnected";
193
- readonly Retry: "retry";
194
178
  readonly ContextUpdate: "context_update";
179
+ readonly SubagentStart: "subagent_start";
180
+ readonly SubagentStop: "subagent_stop";
181
+ readonly ContextWarning: "context_warning";
182
+ readonly MemoryRecall: "memory_recall";
183
+ readonly MemoryUpdate: "memory_update";
195
184
  readonly DesktopStream: "desktop_stream";
196
185
  readonly AttachmentStaged: "attachment_staged";
197
186
  readonly WorkspaceReady: "workspace_ready";
187
+ readonly AssetCreated: "asset_created";
188
+ readonly ToolApprovalRequested: "tool_approval_requested";
189
+ readonly ToolApprovalGranted: "tool_approval_granted";
190
+ readonly ToolPermissionDenied: "tool_permission_denied";
191
+ readonly ToolHarnessWarning: "tool_harness_warning";
192
+ readonly UserUnavailable: "user_unavailable";
193
+ readonly PromptSuggestion: "prompt_suggestion";
194
+ readonly StateChanged: "state_changed";
195
+ readonly Custom: "custom";
198
196
  };
199
- interface UserMessageEvent {
200
- type: "user_message";
201
- content: string;
202
- created_at?: number;
203
- }
204
- interface TitleGeneratedEvent {
205
- type: "title_generated";
206
- title: string;
197
+ type ChatEventTypeValue = (typeof ChatEventType)[keyof typeof ChatEventType];
198
+ type WireBlockKind = "text" | "thinking" | "tool_use";
199
+ type WireBlockStatus = "streaming" | "awaiting_client_result" | "ok" | "error" | "denied" | "cancelled";
200
+ type WireStopReason = "end_turn" | "tool_use" | "max_tokens" | "context_overflow" | "error";
201
+ interface WireTextDelta {
202
+ channel: "text";
203
+ text: string;
207
204
  }
208
- interface MessageStartEvent {
209
- type: "message_start";
210
- message_id: string;
211
- conversation_id: string;
212
- model_display_name?: string;
213
- agent_name?: string;
214
- agent_display_name?: string;
215
- }
216
- interface ContentBlockDeltaEvent {
217
- type: "content_block_delta";
218
- index: number;
219
- delta: {
220
- type: "text_delta";
221
- text: string;
222
- };
205
+ interface WireThinkingDelta {
206
+ channel: "thinking";
207
+ text: string;
223
208
  }
224
- interface ToolUseStartEvent {
225
- type: "tool_use_start";
226
- index: number;
227
- call_id: string;
228
- tool: string;
229
- display_name?: string;
230
- description?: string;
231
- arguments: Record<string, unknown>;
232
- is_client_tool: boolean;
233
- tool_category?: string;
234
- icon_url?: string;
209
+ interface WireSignatureDelta {
210
+ channel: "signature";
211
+ signature: string;
235
212
  }
236
- interface ToolUseEndEvent {
237
- type: "tool_use_end";
238
- call_id: string;
239
- tool: string;
240
- result?: string;
241
- sources?: {
242
- title: string;
243
- url: string;
244
- snippet?: string;
245
- }[];
246
- duration_ms?: number;
247
- }
248
- interface ToolExecutingEvent {
249
- type: "tool_executing";
250
- call_id: string;
251
- tool: string;
213
+ interface WireInputDelta {
214
+ channel: "input";
215
+ partial_json: string;
252
216
  }
253
- interface ToolProgressEvent {
254
- type: "tool_progress";
255
- call_id: string;
256
- tool: string;
257
- index: number;
258
- total: number;
259
- item: {
260
- title: string;
261
- url: string;
262
- snippet?: string;
263
- };
264
- }
265
- interface AgentStartEvent {
266
- type: "agent_start";
267
- agent_name: string;
268
- agent_display_name?: string;
269
- avatar_url?: string;
217
+ interface WireInputArgDelta {
218
+ channel: "input_arg";
219
+ arg_name: string;
220
+ text: string;
270
221
  }
271
- interface AgentEndEvent {
272
- type: "agent_end";
273
- agent_name: string;
222
+ interface WireOutputDelta {
223
+ channel: "output";
224
+ stream: "stdout" | "stderr" | "progress";
225
+ chunk: string;
274
226
  }
275
- interface SubagentStartEvent {
276
- type: "subagent_start";
277
- agent_name: string;
278
- display_name: string;
279
- tool_call_id: string;
280
- avatar_url?: string;
281
- description?: string;
227
+ interface WireStatusDelta {
228
+ channel: "status";
229
+ status: "executing" | "awaiting_client_result" | "awaiting_approval" | "denied";
230
+ note?: string;
282
231
  }
283
- interface SubagentContentDeltaEvent {
284
- type: "subagent_content_delta";
285
- agent_name: string;
286
- tool_call_id: string;
287
- delta: {
288
- type: "text_delta";
289
- text: string;
290
- };
232
+ type WireBlockDeltaPayload = WireTextDelta | WireThinkingDelta | WireSignatureDelta | WireInputDelta | WireInputArgDelta | WireOutputDelta | WireStatusDelta;
233
+ interface WireEnvelope {
234
+ seq: number;
235
+ ts: number;
236
+ job_id: string;
291
237
  }
292
- interface SubagentUpdateEvent {
293
- type: "subagent_update";
294
- agent_name: string;
295
- display_name: string;
296
- tool_call_id: string;
297
- }
298
- interface SubagentEndEvent {
299
- type: "subagent_end";
300
- agent_name: string;
301
- display_name: string;
302
- tool_call_id: string;
303
- }
304
- interface ThinkingDeltaEvent {
305
- type: "thinking_delta";
306
- delta: {
307
- type: "thinking";
308
- text: string;
238
+ interface WireMessageStart extends WireEnvelope {
239
+ type: "message_start";
240
+ turn_id: string;
241
+ model: string;
242
+ agent_name?: string | null;
243
+ agent_display_name?: string | null;
244
+ agent_avatar_url?: string | null;
245
+ }
246
+ interface WireBlockStart extends WireEnvelope {
247
+ type: "block_start";
248
+ turn_id: string;
249
+ path: number[];
250
+ parent_path?: number[] | null;
251
+ kind: WireBlockKind;
252
+ metadata: Record<string, unknown>;
253
+ }
254
+ interface WireBlockDelta extends WireEnvelope {
255
+ type: "block_delta";
256
+ turn_id: string;
257
+ path: number[];
258
+ delta: WireBlockDeltaPayload;
259
+ }
260
+ interface WireBlockStop extends WireEnvelope {
261
+ type: "block_stop";
262
+ turn_id: string;
263
+ path: number[];
264
+ status: WireBlockStatus;
265
+ final: Record<string, unknown>;
266
+ }
267
+ interface WireMessageStop extends WireEnvelope {
268
+ type: "message_stop";
269
+ turn_id: string;
270
+ stop_reason: WireStopReason;
271
+ usage: {
272
+ input_tokens?: number;
273
+ output_tokens?: number;
274
+ cached_tokens?: number;
309
275
  };
276
+ ttfb_ms?: number | null;
277
+ total_ms: number;
278
+ stall_count: number;
310
279
  }
311
- interface ThinkingCompleteEvent {
312
- type: "thinking_complete";
280
+ interface WireStallWarning extends WireEnvelope {
281
+ type: "stall";
282
+ since_last_event_ms: number;
283
+ stall_count: number;
313
284
  }
314
- interface CapsuleOutputEvent {
315
- type: "capsule_output";
316
- tool_name: string;
317
- agent_name: string;
318
- command?: string;
319
- output: string;
320
- duration_ms?: number;
321
- call_id?: string;
322
- }
323
- interface CapsuleOutputChunkEvent {
324
- type: "capsule_output_chunk";
325
- call_id: string;
326
- stream: "stdout" | "stderr";
327
- chunk: string;
328
- }
329
- interface TodoUpdateEvent {
330
- type: "todo_update";
331
- todos: TodoItem[];
332
- }
333
- interface MessageStopEvent {
334
- type: "message_stop";
335
- stop_reason: "end_turn" | "tool_use";
336
- title?: string;
337
- metrics?: Record<string, unknown>;
338
- job_id?: string;
285
+ interface WireRetryEvent extends WireEnvelope {
286
+ type: "retry";
287
+ attempt: number;
288
+ reason: string;
289
+ backoff_ms: number;
290
+ strategy?: string | null;
291
+ max_attempts?: number | null;
292
+ context_recovery?: Record<string, unknown> | null;
339
293
  }
340
- interface SSEErrorEvent {
294
+ interface WireErrorEvent extends WireEnvelope {
341
295
  type: "error";
342
296
  code: string;
343
297
  message: string;
344
- }
345
- interface SubagentToolUseEvent {
346
- type: "subagent_tool_use";
347
- agent_name: string;
348
- tool: string;
349
- tool_call_id: string;
350
- result?: string;
351
- }
352
- interface AssetCreatedEvent {
353
- type: "asset_created";
354
- asset_id: string;
298
+ block_path?: number[] | null;
299
+ retry_after?: number;
300
+ retry_after_sec?: number;
301
+ reset_at?: number | string;
302
+ scope?: string;
303
+ policy_id?: string;
304
+ limit?: number;
305
+ remaining?: number;
306
+ request_id?: string;
307
+ }
308
+ interface WireKeepalive extends WireEnvelope {
309
+ type: "keepalive";
310
+ since_last_event_ms: number;
311
+ }
312
+ interface WireCustomEvent extends WireEnvelope {
313
+ type: "custom";
355
314
  name: string;
356
- url: string;
357
- media_type: string;
358
- size_bytes: number;
359
- }
360
- interface EditorContentStartEvent {
361
- type: "editor_content_start";
362
- call_id: string;
363
- path: string;
364
- language: string;
365
- }
366
- interface EditorContentDeltaEvent {
367
- type: "editor_content_delta";
368
- call_id: string;
369
- path: string;
370
- delta: string;
371
- }
372
- interface EditorContentEndEvent {
373
- type: "editor_content_end";
374
- call_id: string;
375
- }
376
- interface RetryEvent {
377
- type: "retry";
378
- attempt: number;
379
- max_attempts: number;
380
- delay_seconds: number;
381
- }
382
- interface ContextUpdateEvent {
383
- type: "context_update";
384
- context: Record<string, unknown>;
385
- phase?: string;
386
- updated_at?: number;
387
- }
388
- interface DesktopStreamEvent {
389
- type: "desktop_stream";
390
- url: string;
391
- auth_key: string;
392
- sandbox_id: string;
315
+ data: Record<string, unknown>;
393
316
  }
394
- interface AttachmentStagedEvent {
395
- type: "attachment_staged";
396
- files: {
397
- name: string;
398
- path: string;
399
- media_type: string;
400
- size_bytes: number;
401
- }[];
402
- }
403
- interface WorkspaceReadyEvent {
404
- type: "workspace_ready";
405
- conversation_id: string;
406
- sandbox_id: string;
317
+ type WireEvent = WireMessageStart | WireBlockStart | WireBlockDelta | WireBlockStop | WireMessageStop | WireStallWarning | WireRetryEvent | WireErrorEvent | WireKeepalive | WireCustomEvent;
318
+ interface TurnUsage {
319
+ inputTokens: number;
320
+ outputTokens: number;
321
+ cachedTokens: number;
407
322
  }
408
- type SSEEvent = MessageStartEvent | UserMessageEvent | TitleGeneratedEvent | ContentBlockDeltaEvent | ToolUseStartEvent | ToolUseEndEvent | ToolExecutingEvent | ToolProgressEvent | AgentStartEvent | AgentEndEvent | SubagentStartEvent | SubagentContentDeltaEvent | SubagentUpdateEvent | SubagentEndEvent | SubagentToolUseEvent | ThinkingDeltaEvent | ThinkingCompleteEvent | CapsuleOutputEvent | CapsuleOutputChunkEvent | TodoUpdateEvent | MessageStopEvent | AssetCreatedEvent | EditorContentStartEvent | EditorContentDeltaEvent | EditorContentEndEvent | RetryEvent | ContextUpdateEvent | DesktopStreamEvent | AttachmentStagedEvent | WorkspaceReadyEvent | SSEErrorEvent;
409
- type ChatEvent = {
410
- type: "connected";
411
- } | {
412
- type: "user_message";
413
- content: string;
414
- createdAt?: number;
415
- } | {
416
- type: "title_generated";
417
- title: string;
323
+ type BlockDeltaPayload = {
324
+ channel: "text";
325
+ text: string;
418
326
  } | {
419
- type: "chunk";
327
+ channel: "thinking";
420
328
  text: string;
421
329
  } | {
422
- type: "tool_call";
423
- request: ToolCallRequest;
330
+ channel: "signature";
331
+ signature: string;
424
332
  } | {
425
- type: "tool_executing";
426
- name: string;
427
- call_id?: string;
333
+ channel: "input";
334
+ partialJson: string;
428
335
  } | {
429
- type: "tool_completed";
430
- name: string;
431
- result: string;
336
+ channel: "inputArg";
337
+ argName: string;
338
+ text: string;
432
339
  } | {
433
- type: "tool_progress";
434
- callId: string;
435
- tool: string;
436
- index: number;
437
- total: number;
438
- item: {
439
- title: string;
440
- url: string;
441
- snippet?: string;
442
- };
340
+ channel: "output";
341
+ stream: "stdout" | "stderr" | "progress";
342
+ chunk: string;
443
343
  } | {
444
- type: "tool_end";
445
- callId: string;
446
- toolName: string;
447
- result?: string;
448
- sources?: {
449
- title: string;
450
- url: string;
451
- snippet?: string;
452
- }[];
453
- durationMs?: number;
454
- } | {
455
- type: "agent_start";
456
- agentName: string;
457
- agentDisplayName?: string;
458
- avatarUrl?: string;
344
+ channel: "status";
345
+ status: "executing" | "awaiting_client_result" | "awaiting_approval" | "denied";
346
+ note?: string;
347
+ };
348
+ type ChatEvent = {
349
+ type: "connected";
459
350
  } | {
460
- type: "agent_end";
461
- agentName: string;
351
+ type: "disconnected";
462
352
  } | {
463
- type: "thinking_delta";
464
- text: string;
353
+ type: "message_start";
354
+ turnId: string;
355
+ model: string;
356
+ agentName?: string | null;
357
+ agentDisplayName?: string | null;
358
+ agentAvatarUrl?: string | null;
465
359
  } | {
466
- type: "thinking_complete";
360
+ type: "message_stop";
361
+ turnId: string;
362
+ jobId: string;
363
+ stopReason: WireStopReason;
364
+ usage: TurnUsage;
365
+ ttfbMs?: number | null;
366
+ totalMs: number;
367
+ stallCount: number;
467
368
  } | {
468
- type: "subagent_start";
469
- agentName: string;
470
- displayName: string;
471
- toolCallId: string;
472
- avatarUrl?: string;
473
- description?: string;
369
+ type: "block_start";
370
+ turnId: string;
371
+ path: number[];
372
+ parentPath?: number[] | null;
373
+ kind: WireBlockKind;
374
+ metadata: Record<string, unknown>;
474
375
  } | {
475
- type: "subagent_chunk";
476
- agentName: string;
477
- toolCallId: string;
478
- text: string;
376
+ type: "block_delta";
377
+ turnId: string;
378
+ path: number[];
379
+ delta: BlockDeltaPayload;
479
380
  } | {
480
- type: "subagent_update";
481
- agentName: string;
482
- displayName: string;
483
- toolCallId: string;
381
+ type: "block_stop";
382
+ turnId: string;
383
+ path: number[];
384
+ status: WireBlockStatus;
385
+ final: Record<string, unknown>;
484
386
  } | {
485
- type: "subagent_end";
486
- agentName: string;
487
- displayName: string;
488
- toolCallId: string;
387
+ type: "stall";
388
+ sinceLastEventMs: number;
389
+ stallCount: number;
489
390
  } | {
490
- type: "capsule_output";
491
- toolName: string;
492
- agentName: string;
493
- command?: string;
494
- output: string;
495
- durationMs?: number;
496
- callId?: string;
391
+ type: "retry";
392
+ attempt: number;
393
+ reason: string;
394
+ backoffMs: number;
395
+ strategy?: string | null;
396
+ maxAttempts?: number | null;
397
+ contextRecovery?: Record<string, unknown> | null;
497
398
  } | {
498
- type: "capsule_output_chunk";
499
- callId: string;
500
- stream: "stdout" | "stderr";
501
- chunk: string;
399
+ type: "error";
400
+ code: string;
401
+ message: string;
402
+ blockPath: number[] | null;
502
403
  } | {
503
- type: "todo_update";
504
- todos: TodoItem[];
404
+ type: "keepalive";
405
+ sinceLastEventMs: number;
505
406
  } | {
506
- type: "complete";
407
+ type: "user_message";
507
408
  content: string;
508
- conversationId: string;
509
- messageId: string;
510
- title?: string;
511
- metrics?: Record<string, unknown>;
512
- job_id?: string;
513
- } | {
514
- type: "subagent_tool_use";
515
- agentName: string;
516
- toolName: string;
517
- toolCallId: string;
518
- result?: string;
409
+ createdAt?: number;
519
410
  } | {
520
- type: "asset_created";
521
- assetId: string;
522
- name: string;
523
- url: string;
524
- mediaType: string;
525
- sizeBytes: number;
411
+ type: "title_generated";
412
+ title: string;
526
413
  } | {
527
- type: "retry";
528
- attempt: number;
529
- maxAttempts: number;
530
- delaySeconds: number;
414
+ type: "todo_update";
415
+ todos: TodoItem[];
531
416
  } | {
532
417
  type: "context_update";
533
418
  context: Record<string, unknown>;
534
- phase?: string;
535
- updatedAt?: number;
419
+ phase?: string | null;
420
+ updatedAt?: number | null;
536
421
  } | {
537
- type: "editor_content_start";
538
- callId: string;
539
- path: string;
540
- language: string;
422
+ type: "subagent_start";
423
+ agent: AgentIdentity;
424
+ taskCallId?: string | null;
541
425
  } | {
542
- type: "editor_content_delta";
543
- callId: string;
544
- path: string;
545
- delta: string;
426
+ type: "subagent_stop";
427
+ agent: AgentIdentity;
428
+ taskCallId?: string | null;
546
429
  } | {
547
- type: "editor_content_end";
548
- callId: string;
430
+ type: "context_warning";
431
+ /** Known values: "info" | "warning" | "critical". Typed as string for forward compat. */
432
+ severity: string;
433
+ utilizationPct: number;
434
+ remainingTokens: number;
435
+ windowTokens: number;
436
+ inputTokens: number;
437
+ message: string;
438
+ } | {
439
+ type: "memory_recall";
440
+ memories: MemoryRecord[];
441
+ } | {
442
+ type: "memory_update";
443
+ /** Known values: "created" | "updated" | "deleted". */
444
+ action: string;
445
+ memoryId?: string | null;
446
+ key?: string | null;
447
+ namespace?: string | null;
549
448
  } | {
550
449
  type: "desktop_stream";
551
450
  url: string;
552
- authKey: string;
553
- sandboxId: string;
451
+ sandboxId?: string | null;
554
452
  } | {
555
453
  type: "attachment_staged";
556
- files: {
557
- name: string;
558
- path: string;
559
- mediaType: string;
560
- sizeBytes: number;
561
- }[];
454
+ attachmentId: string;
455
+ filename: string;
456
+ contentType?: string | null;
457
+ sizeBytes?: number | null;
562
458
  } | {
563
459
  type: "workspace_ready";
564
- conversationId: string;
565
460
  sandboxId: string;
461
+ workspacePath?: string | null;
566
462
  } | {
567
- type: "model_info";
568
- name: string;
463
+ type: "asset_created";
464
+ assetId: string;
465
+ filename: string;
466
+ url?: string | null;
467
+ contentType?: string | null;
569
468
  } | {
570
- type: "blocks_changed";
571
- blocks: Block[];
469
+ type: "tool_approval_requested";
470
+ toolName: string;
471
+ callId: string;
472
+ arguments: Record<string, unknown>;
473
+ riskLevel?: string | null;
474
+ reason?: string | null;
572
475
  } | {
573
- type: "error";
574
- error: Error;
476
+ type: "tool_approval_granted";
477
+ toolName: string;
478
+ callId: string;
575
479
  } | {
576
- type: "disconnected";
480
+ type: "tool_permission_denied";
481
+ toolName: string;
482
+ callId: string;
483
+ reason?: string | null;
484
+ /** Known values: "hook" | "rule" | "user" | "timeout" | "circuit_breaker". */
485
+ deniedBy?: string | null;
486
+ } | {
487
+ type: "tool_harness_warning";
488
+ toolName: string;
489
+ callId: string;
490
+ message?: string | null;
491
+ details?: Record<string, unknown> | null;
492
+ } | {
493
+ type: "user_unavailable";
494
+ consecutiveTimeouts: number;
495
+ toolName?: string | null;
496
+ } | {
497
+ type: "prompt_suggestion";
498
+ suggestions: string[];
499
+ } | {
500
+ type: "state_changed";
501
+ /**
502
+ * Job lifecycle state. Known values from the backend today include
503
+ * "queued" | "running" | "waiting_for_tool" | "completed" | "failed".
504
+ * Typed as string for forward compat.
505
+ */
506
+ state: string;
507
+ } | {
508
+ type: "custom";
509
+ name: string;
510
+ data: Record<string, unknown>;
577
511
  };
578
512
  interface Conversation {
579
513
  id: string;
@@ -592,12 +526,20 @@ interface Message {
592
526
  createdAt: string;
593
527
  toolCalls?: ToolCallRequest[];
594
528
  }
529
+ interface UIComponentsConfig {
530
+ enabled: boolean;
531
+ /** Protocol slug (e.g. "a2ui"). Null when disabled. */
532
+ protocol: string | null;
533
+ /** MIME type to match against embedded resources (e.g. "application/json+a2ui"). */
534
+ mimeType: string | null;
535
+ }
595
536
  interface ProjectStatus {
596
537
  isReady: boolean;
597
538
  llmConfigured: boolean;
598
539
  llmProvider?: string;
599
540
  llmModel?: string;
600
541
  message: string;
542
+ uiComponents: UIComponentsConfig;
601
543
  }
602
544
  interface AgentInfo {
603
545
  name: string;
@@ -607,52 +549,67 @@ interface AgentInfo {
607
549
  isEnabled: boolean;
608
550
  avatarUrl?: string;
609
551
  }
552
+ interface TeamSummary {
553
+ id: string;
554
+ name: string;
555
+ slug: string;
556
+ isDefault: boolean;
557
+ /** Caller's role in this team (e.g. "owner", "admin", "member"). */
558
+ role: string;
559
+ }
560
+ interface ProjectSummary {
561
+ id: string;
562
+ name: string;
563
+ teamId: string;
564
+ createdAt: string;
565
+ updatedAt: string;
566
+ }
610
567
  interface SkillInfo {
611
568
  name: string;
612
569
  displayName: string;
613
570
  description: string;
614
571
  isEnabled: boolean;
615
572
  }
616
- interface SubagentState {
617
- agentName: string;
618
- displayName: string;
619
- avatarUrl?: string;
620
- description?: string;
621
- content: string;
622
- isActive: boolean;
623
- }
624
- interface ToolState {
625
- toolName: string;
626
- displayName?: string;
627
- description?: string;
628
- arguments?: Record<string, unknown>;
629
- callId: string;
630
- status: "calling" | "executing" | "completed";
631
- isClientTool: boolean;
632
- }
633
- interface CapsuleOutput {
634
- toolName: string;
635
- agentName: string;
636
- command?: string;
637
- output: string;
638
- durationMs?: number;
639
- callId?: string;
640
- }
641
- interface Source {
642
- title: string;
643
- url: string;
644
- }
645
- interface TodoItem {
646
- content: string;
647
- status: "pending" | "in_progress" | "completed";
648
- id?: string;
649
- }
650
573
  interface JobCreateResponse {
651
574
  job_id: string;
652
575
  conversation_id: string;
653
576
  message_id: string;
654
577
  status: string;
655
578
  }
579
+ interface JobStatus {
580
+ jobId: string;
581
+ status: string;
582
+ createdAt: string | null;
583
+ startedAt: string | null;
584
+ completedAt: string | null;
585
+ errorMessage: string | null;
586
+ inputTokens: number;
587
+ outputTokens: number;
588
+ }
589
+ interface ActiveJob {
590
+ jobId: string | null;
591
+ status: string;
592
+ }
593
+ interface JobSummary {
594
+ jobId: string;
595
+ status: string;
596
+ replacesJobId: string | null;
597
+ responseContent: Record<string, unknown> | null;
598
+ metrics: Record<string, unknown> | null;
599
+ createdAt: string | null;
600
+ }
601
+ interface FeedbackRequest {
602
+ /** 1 for thumbs up, -1 for thumbs down. */
603
+ rating: 1 | -1;
604
+ comment?: string | null;
605
+ }
606
+ interface FeedbackResponse {
607
+ id: string;
608
+ jobId: string;
609
+ rating: number;
610
+ comment: string | null;
611
+ createdAt: string;
612
+ }
656
613
  interface ChatStreamRequest {
657
614
  message?: string;
658
615
  conversation_id?: string;
@@ -663,6 +620,7 @@ interface ChatStreamRequest {
663
620
  upload_ids?: string[];
664
621
  agent_name?: string;
665
622
  enable_search?: boolean;
623
+ plan_mode?: boolean;
666
624
  }
667
625
  interface ToolResultRequest {
668
626
  conversation_id: string;
@@ -675,6 +633,14 @@ interface ToolResult {
675
633
  result: string;
676
634
  is_error: boolean;
677
635
  }
636
+ type ToolApprovalDecision = "allow" | "deny";
637
+ type ToolApprovalScope = "once" | "conversation" | "always";
638
+ interface ToolApprovalRequest {
639
+ job_id: string;
640
+ call_id: string;
641
+ decision: ToolApprovalDecision;
642
+ scope: ToolApprovalScope;
643
+ }
678
644
  interface ToolDefinition {
679
645
  name: string;
680
646
  description: string;
@@ -711,6 +677,7 @@ interface SendOptions$1 {
711
677
  uploadIds?: string[];
712
678
  agentName?: string;
713
679
  enableSearch?: boolean;
680
+ planMode?: boolean;
714
681
  }
715
682
  interface ConversationAsset {
716
683
  id: string;
@@ -725,11 +692,53 @@ interface ConversationAsset {
725
692
  }
726
693
 
727
694
  declare class AstralformClient {
728
- private readonly apiKey;
729
695
  private readonly baseURL;
730
- private readonly userId;
731
696
  private readonly fetchFn;
697
+ /**
698
+ * Auth state is mutable so callers can rotate access tokens or switch
699
+ * project context without re-instantiating the client. API-key mode is
700
+ * effectively immutable in practice but uses the same shape for uniformity.
701
+ */
702
+ private auth;
732
703
  constructor(config: AstralformConfig);
704
+ /**
705
+ * Replace the current OIDC access token without reconstructing the client.
706
+ * Use after refreshing via the host's token manager (e.g., Supabase JS SDK).
707
+ * Throws if the client was created in API-key mode.
708
+ */
709
+ updateAccessToken(accessToken: string): void;
710
+ /**
711
+ * Swap the active project for a user-token client. The backend verifies the
712
+ * current developer has access to the new project; a 403 comes back if not.
713
+ */
714
+ updateProjectId(projectId: string): void;
715
+ /**
716
+ * Set (or clear) the end-user override for user-token mode.
717
+ *
718
+ * Pass `null` or an empty string to clear — subsequent requests go
719
+ * back to scoping against the developer's own identity. Throws if
720
+ * called in API-key mode, where end-user context already travels via
721
+ * the constructor's `userId` field.
722
+ */
723
+ updateEndUserId(endUserId: string | null): void;
724
+ /** Current end-user override in user-token mode, or `null` if unset. */
725
+ get endUserId(): string | null;
726
+ /**
727
+ * Active project for user-token mode, or `null` if pre-pick (client
728
+ * was constructed without one). For API-key mode the project is baked
729
+ * into the key, so this getter returns `null` there too — use
730
+ * `authMode` to disambiguate.
731
+ */
732
+ get projectId(): string | null;
733
+ /** Which auth mode this client was constructed with. */
734
+ get authMode(): "api_key" | "user_token";
735
+ /**
736
+ * Authorization + identity headers for the current auth mode, without
737
+ * `Content-Type`. Suitable for JSON requests (paired with the JSON header
738
+ * in the `headers` getter) and for multipart uploads where the browser
739
+ * must set its own `Content-Type` boundary.
740
+ */
741
+ private get authHeaders();
733
742
  private get headers();
734
743
  private request;
735
744
  get<T>(path: string): Promise<T>;
@@ -749,13 +758,46 @@ declare class AstralformClient {
749
758
  getSkills(): Promise<SkillInfo[]>;
750
759
  getConversationEvents(conversationId: string, jobId?: string): Promise<ConversationEvent[]>;
751
760
  submitToolResult(request: ToolResultRequest): Promise<void>;
761
+ submitToolApproval(request: ToolApprovalRequest): Promise<void>;
752
762
  private mapAsset;
753
763
  uploadFile(conversationId: string, file: Blob, filename?: string): Promise<ConversationAsset>;
754
764
  listUploads(conversationId: string): Promise<ConversationAsset[]>;
755
765
  listOutputs(conversationId: string): Promise<ConversationAsset[]>;
766
+ listTeams(): Promise<TeamSummary[]>;
767
+ listProjects(teamId: string): Promise<ProjectSummary[]>;
756
768
  createJob(request: ChatStreamRequest): Promise<JobCreateResponse>;
757
769
  streamJobEvents(jobId: string, afterSeq?: number, signal?: AbortSignal): AsyncGenerator<ChatStreamEvent>;
758
770
  cancelJob(jobId: string): Promise<void>;
771
+ getJob(jobId: string): Promise<JobStatus>;
772
+ submitFeedback(jobId: string, request: FeedbackRequest): Promise<FeedbackResponse>;
773
+ getActiveJob(conversationId: string): Promise<ActiveJob>;
774
+ listJobs(conversationId: string): Promise<JobSummary[]>;
775
+ }
776
+
777
+ /**
778
+ * Minimal adapter contract. Frontends extend this with a `render()`
779
+ * method (or equivalent) returning their framework's view type.
780
+ */
781
+ interface ProtocolAdapter {
782
+ /** IANA-style MIME type this adapter handles (e.g. ``application/json+a2ui``). */
783
+ readonly mimeType: string;
784
+ }
785
+ /**
786
+ * MIME-keyed adapter map, generic on the adapter subtype so consumers
787
+ * can register richer shapes without casting on every read.
788
+ */
789
+ declare class ProtocolRegistry<T extends ProtocolAdapter = ProtocolAdapter> {
790
+ private adapters;
791
+ /** Register or replace the adapter for a MIME type. */
792
+ register(adapter: T): void;
793
+ /** Remove the adapter for a MIME type. No-op if not registered. */
794
+ unregister(mimeType: string): void;
795
+ /** Returns the adapter for a MIME type, or ``null`` if none is registered. */
796
+ get(mimeType: string): T | null;
797
+ has(mimeType: string): boolean;
798
+ /** Drop every adapter. Called when a session disconnects. */
799
+ clear(): void;
800
+ listMimeTypes(): string[];
759
801
  }
760
802
 
761
803
  interface ChatStorage {
@@ -796,31 +838,38 @@ declare class ToolRegistry {
796
838
  }
797
839
 
798
840
  type ChatEventHandler = (event: ChatEvent) => void;
841
+ /**
842
+ * ChatSession — translates the backend wire protocol into typed ChatEvents
843
+ * for consumers. Owns HTTP + SSE plumbing, conversation state, and the
844
+ * client-tool round-trip. Does NOT own block construction — consumers
845
+ * build their own block state from the typed events.
846
+ */
799
847
  declare class ChatSession {
800
848
  readonly client: AstralformClient;
801
849
  readonly toolRegistry: ToolRegistry;
802
850
  readonly storage: ChatStorage;
803
- readonly blockBuilder: BlockBuilder;
851
+ /**
852
+ * Pluggable UI protocol adapters. Consumers register a framework-
853
+ * specific adapter (e.g. React) for each MIME type they can render,
854
+ * typically gated on ``session.projectStatus.uiComponents.protocol``.
855
+ * ``ToolBlock``-style consumers look up the adapter for an incoming
856
+ * embedded resource and hand off rendering.
857
+ */
858
+ readonly protocols: ProtocolRegistry<ProtocolAdapter>;
804
859
  conversationId: string | null;
805
860
  conversations: Conversation[];
806
861
  messages: Message[];
807
- streamingContent: string;
808
862
  isStreaming: boolean;
809
- executingTool: string | null;
810
863
  projectStatus: ProjectStatus | null;
811
864
  agents: AgentInfo[];
812
865
  skills: SkillInfo[];
813
866
  enabledClientTools: Set<string>;
814
867
  modelDisplayName: string | null;
815
- thinkingContent: string;
816
- isThinking: boolean;
817
- activeSubagents: Map<string, SubagentState>;
818
- capsuleOutputs: CapsuleOutput[];
819
- todos: TodoItem[];
820
- activeTools: Map<string, ToolState>;
868
+ private accumulatedText;
869
+ private currentTextPath;
821
870
  private handlers;
822
871
  private abortController;
823
- constructor(config: AstralformConfig, storage?: ChatStorage, blockBuilder?: BlockBuilder);
872
+ constructor(config: AstralformConfig, storage?: ChatStorage);
824
873
  on(handler: ChatEventHandler): () => void;
825
874
  private emit;
826
875
  connect(): Promise<void>;
@@ -836,16 +885,22 @@ declare class ChatSession {
836
885
  currentJobId: string | null;
837
886
  private consumeJobStream;
838
887
  /**
839
- * Shared event consumption loop used by both consumeJobStream and reconnectToJob.
888
+ * Shared event consumption loop. Parses each wire event, updates
889
+ * minimal session state, and emits typed ChatEvents to consumers.
840
890
  */
841
891
  private consumeEventStream;
892
+ private dispatchWireEvent;
842
893
  /**
843
- * Apply a single SSE event to session state and notify consumers.
844
- * Shared between live streaming and historical event replay.
894
+ * State mutations driven by wire events. Kept separate from translation so
895
+ * the pure wire → ChatEvent mapping can live in translate.ts and be reused
896
+ * by the replay path.
897
+ *
898
+ * ``messageId`` is the server-assigned assistant message id for the current
899
+ * turn; empty in the reconnect and conversation-switch replay paths where
900
+ * messages have already been loaded from REST and shouldn't be re-pushed.
845
901
  */
846
- private applyEvent;
902
+ private applyWireSideEffects;
847
903
  private executeClientTools;
848
- private completeStream;
849
904
  /**
850
905
  * Load conversation context (messages) without replaying events.
851
906
  * Used before reconnectToJob — SSE replay handles event replay.
@@ -854,33 +909,35 @@ declare class ChatSession {
854
909
  /**
855
910
  * Reconnect to a running job's SSE stream (e.g. after page reload).
856
911
  * Replays all events from the beginning and continues live.
857
- * Does NOT reset BlockBuilder — caller controls reset.
858
912
  */
859
913
  reconnectToJob(jobId: string): Promise<void>;
860
- /** Detach from the SSE stream without cancelling the job.
861
- * The backend job keeps running — caller can reconnect later. */
914
+ /** Detach from the SSE stream without cancelling the job. */
862
915
  detach(): void;
863
916
  /** Stop the job and disconnect (explicit user action). */
864
917
  disconnect(): void;
865
918
  createNewConversation(): Promise<string>;
866
- switchConversation(id: string, jobId?: string): Promise<void>;
919
+ switchConversation(id: string, jobId?: string,
920
+ /**
921
+ * User prompt that triggered this job, if known. Emitted as a
922
+ * synthetic ``user_message`` ChatEvent right before the first
923
+ * ``message_start`` of the replay. User messages aren't persisted
924
+ * in ``job_events``, so without this the restored conversation
925
+ * would show the agent response with no visible prompt above it.
926
+ */
927
+ userMessageContent?: string): Promise<void>;
867
928
  deleteConversation(id: string): Promise<void>;
868
929
  toggleClientTool(name: string): boolean;
869
930
  }
870
931
 
871
- /**
872
- * Standard event handlers for BlockBuilder.
873
- *
874
- * These define the default event→block mapping rules. Clients import
875
- * and register them explicitly:
876
- *
877
- * import { BlockBuilder, standardHandlers } from "@astralform/js";
878
- * const builder = new BlockBuilder();
879
- * builder.registerHandlers(standardHandlers);
880
- */
881
-
882
- declare const standardHandlers: Record<string, EventHandler$1>;
883
-
932
+ interface RateLimitErrorDetails {
933
+ retryAfterSec?: number;
934
+ resetAt?: number;
935
+ scope?: string;
936
+ policyId?: string;
937
+ limit?: number;
938
+ remaining?: number;
939
+ requestId?: string;
940
+ }
884
941
  declare class AstralformError extends Error {
885
942
  code: string;
886
943
  constructor(message: string, code: string);
@@ -889,7 +946,14 @@ declare class AuthenticationError extends AstralformError {
889
946
  constructor(message?: string);
890
947
  }
891
948
  declare class RateLimitError extends AstralformError {
892
- constructor(message?: string);
949
+ readonly retryAfterSec?: number;
950
+ readonly resetAt?: number;
951
+ readonly scope?: string;
952
+ readonly policyId?: string;
953
+ readonly limit?: number;
954
+ readonly remaining?: number;
955
+ readonly requestId?: string;
956
+ constructor(message?: string, details?: RateLimitErrorDetails);
893
957
  }
894
958
  declare class LLMNotConfiguredError extends AstralformError {
895
959
  constructor(message?: string);
@@ -916,12 +980,18 @@ declare function streamJobSSE(options: StreamJobSSEOptions): AsyncGenerator<Chat
916
980
  *
917
981
  * Sits on top of ChatSession and manages the state machine for
918
982
  * multi-conversation SSE streaming. Framework-agnostic: emits
919
- * callbacks instead of writing to any state management library.
983
+ * typed events to registered handlers. Block construction is NOT
984
+ * the SDK's concern — consumers build their own block tree from
985
+ * the forwarded ``ChatEvent`` instances.
920
986
  *
921
987
  * import { ChatSession, StreamManager } from "@astralform/js";
922
988
  * const session = new ChatSession({ ... });
923
989
  * const manager = new StreamManager(session);
924
- * manager.on("blocksChanged", (convId, blocks) => { ... });
990
+ * manager.on((event) => {
991
+ * if (event.type === "event") {
992
+ * // event.event is a typed ChatEvent — dispatch to your reducer
993
+ * }
994
+ * });
925
995
  * await manager.send("Hello");
926
996
  */
927
997
 
@@ -930,15 +1000,12 @@ interface SendOptions {
930
1000
  enableSearch?: boolean;
931
1001
  agentName?: string;
932
1002
  uploadIds?: string[];
1003
+ planMode?: boolean;
933
1004
  }
934
1005
  type StreamManagerEvent = {
935
1006
  type: "stateChange";
936
1007
  state: StreamState;
937
1008
  conversationId: string | null;
938
- } | {
939
- type: "blocksChanged";
940
- conversationId: string;
941
- blocks: Block[];
942
1009
  } | {
943
1010
  type: "conversationChanged";
944
1011
  conversationId: string | null;
@@ -978,10 +1045,81 @@ declare class StreamManager {
978
1045
  deleteConversation(id: string): Promise<void>;
979
1046
  stop(): void;
980
1047
  destroy(): void;
981
- private prepareUserBlock;
982
1048
  private finalizeStream;
983
1049
  private restore;
984
1050
  private setActiveConversation;
985
1051
  }
986
1052
 
987
- export { type AgentBlock, type AgentEndEvent, type AgentInfo, type AgentStartEvent, type AssetBlock, AstralformClient, type AstralformConfig, AstralformError, type AttachmentBlock, type AttachmentStagedEvent, AuthenticationError, type Block, BlockBuilder, type CapsuleBlock, type CapsuleOutput, type CapsuleOutputChunkEvent, type CapsuleOutputEvent, type ChatEvent, ChatEventType, ChatSession, type ChatStorage, type ChatStreamEvent, type ChatStreamRequest, ConnectionError, type ContentBlockDeltaEvent, type Conversation, type ConversationAsset, type ConversationEvent, type DesktopStreamBlock, type DesktopStreamEvent, type EditorBlock, type ErrorBlock, type EventHandler$1 as EventHandler, InMemoryStorage, type JobCreateResponse, LLMNotConfiguredError, type Message, type MessageStartEvent, type MessageStopEvent, type ProjectStatus, RateLimitError, type RetryEvent, type SSEErrorEvent, type SSEEvent, type SendOptions, ServerError, type SkillInfo, type Source, StreamAbortedError, type StreamJobSSEOptions, StreamManager, type StreamManagerEvent, type StreamState, type SubagentBlock, type SubagentContentDeltaEvent, type SubagentEndEvent, type SubagentStartEvent, type SubagentState, type SubagentToolUseEvent, type TextBlock, type ThinkingBlock, type ThinkingCompleteEvent, type ThinkingDeltaEvent, type TodoBlock, type TodoItem, type TodoUpdateEvent, type ToolBlock, type ToolCallRequest, type ToolDefinition, type ToolExecutingEvent, type ToolHandler, type ToolProgressEvent, ToolRegistry, type ToolResult, type ToolResultRequest, type ToolState, type ToolUseEndEvent, type ToolUseStartEvent, type UserBlock, type WorkspaceReadyEvent, generateId, standardHandlers, streamJobSSE };
1053
+ /**
1054
+ * Translate a WireBlockDeltaPayload into the consumer-facing shape. Returns
1055
+ * ``null`` for unknown channels so forward-compatible backends can add new
1056
+ * ones without breaking old clients.
1057
+ */
1058
+ declare function translateDelta(wire: WireBlockDeltaPayload): BlockDeltaPayload | null;
1059
+
1060
+ /**
1061
+ * Raw SSE event shape returned by GET /v1/conversations/{id}/events.
1062
+ * Mirrors what JobEventWriter persists to the job_events table.
1063
+ */
1064
+ interface RawSseEvent {
1065
+ seq: number;
1066
+ event: string;
1067
+ data: Record<string, unknown>;
1068
+ /** Epoch ms when the event was persisted (from job_events.created_at). */
1069
+ created_at?: number;
1070
+ }
1071
+ /**
1072
+ * Map a raw SSE event (persisted in job_events) into the SDK ChatEvent
1073
+ * format. Returns an array because some rows (malformed / ``done`` sentinels)
1074
+ * map to zero events.
1075
+ */
1076
+ declare function mapSseToChat(raw: RawSseEvent): ChatEvent[];
1077
+ /**
1078
+ * Replay persisted SSE events through the provided handler, interleaving
1079
+ * user messages from session.messages at the first message_start of each
1080
+ * turn (user messages aren't persisted in job_events).
1081
+ */
1082
+ declare function replayEvents(sseEvents: RawSseEvent[], userMessages: {
1083
+ role: string;
1084
+ content: string;
1085
+ }[], handleEvent: (event: ChatEvent) => void, addBlock: (block: {
1086
+ type: "user";
1087
+ id: string;
1088
+ content: string;
1089
+ }) => void): void;
1090
+
1091
+ /**
1092
+ * Parsed shape of an MCP-style embedded resource, as emitted by the
1093
+ * backend's UI component tools (``render_surface``, ``update_surface``).
1094
+ */
1095
+ interface EmbeddedResource {
1096
+ /** IANA-style MIME type, e.g. "application/json+a2ui". */
1097
+ mimeType: string;
1098
+ /** Opaque URI (e.g. "a2ui://surface/my-form"). */
1099
+ uri: string;
1100
+ /** Protocol-specific payload — shape depends on ``mimeType``. */
1101
+ payload: Record<string, unknown>;
1102
+ }
1103
+ /**
1104
+ * Detect whether a value is an embedded resource wrapper. The check is
1105
+ * purposely loose — any object with ``_embedded_resource: true`` is
1106
+ * accepted, which matches the MCP convention and keeps the SDK
1107
+ * forward-compatible with future protocols.
1108
+ */
1109
+ declare function isEmbeddedResource(value: unknown): value is {
1110
+ _embedded_resource: true;
1111
+ mime_type?: string;
1112
+ uri?: string;
1113
+ payload?: Record<string, unknown>;
1114
+ };
1115
+ /**
1116
+ * Parse an embedded resource from arbitrary tool output. Returns
1117
+ * ``null`` when the value isn't an embedded resource or is malformed.
1118
+ *
1119
+ * Accepts either an object (the preferred wire format) or a JSON
1120
+ * string containing one (defense in depth — some transport layers
1121
+ * historically serialized tool results before sending).
1122
+ */
1123
+ declare function parseEmbeddedResource(value: unknown): EmbeddedResource | null;
1124
+
1125
+ export { type ActiveJob, type AgentIdentity, type AgentInfo, type AssetCreatedPayload, type AstralformApiKeyConfig, AstralformClient, type AstralformConfig, AstralformError, type AstralformUserTokenConfig, type AttachmentStagedPayload, AuthenticationError, type BlockDeltaPayload, type ChatEvent, ChatEventType, type ChatEventTypeValue, ChatSession, type ChatStorage, type ChatStreamEvent, type ChatStreamRequest, ConnectionError, type ContextUpdatePayload, type ContextWarningPayload, type Conversation, type ConversationAsset, type ConversationEvent, type DesktopStreamPayload, type EmbeddedResource, type FeedbackRequest, type FeedbackResponse, InMemoryStorage, type JobCreateResponse, type JobStatus, type JobSummary, LLMNotConfiguredError, type MemoryRecallPayload, type MemoryRecord, type MemoryUpdatePayload, type Message, type ProjectStatus, type ProjectSummary, type PromptSuggestionPayload, type ProtocolAdapter, ProtocolRegistry, RateLimitError, type RateLimitErrorDetails, type RawSseEvent, type SendOptions, ServerError, type SkillInfo, StreamAbortedError, type StreamJobSSEOptions, StreamManager, type StreamManagerEvent, type StreamState, type SubagentStartPayload, type SubagentStopPayload, type TaskStatus, type TeamSummary, type TitleGeneratedPayload, type TodoItem, type TodoUpdatePayload, type ToolApprovalDecision, type ToolApprovalGrantedPayload, type ToolApprovalRequest, type ToolApprovalRequestedPayload, type ToolApprovalScope, type ToolCallRequest, type ToolDefinition, type ToolHandler, type ToolHarnessWarningPayload, type ToolPermissionDeniedPayload, ToolRegistry, type ToolResult, type ToolResultRequest, type TurnUsage, type UIComponentsConfig, type UserUnavailablePayload, type WireBlockDelta, type WireBlockDeltaPayload, type WireBlockKind, type WireBlockStart, type WireBlockStatus, type WireBlockStop, type WireCustomEvent, type WireErrorEvent, type WireEvent, type WireInputArgDelta, type WireInputDelta, type WireKeepalive, type WireMessageStart, type WireMessageStop, type WireOutputDelta, type WireRetryEvent, type WireSignatureDelta, type WireStallWarning, type WireStatusDelta, type WireStopReason, type WireTextDelta, type WireThinkingDelta, type WorkspaceReadyPayload, generateId, isEmbeddedResource, mapSseToChat, parseEmbeddedResource, replayEvents, streamJobSSE, translateDelta };