@rool-dev/sdk 2.0.0-dev.4adc2c2 → 2.0.0-dev.66fd5c8

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 CHANGED
@@ -201,6 +201,8 @@ const path = "/rool-drive/documents/report.pdf";
201
201
 
202
202
  const storage = await files.getStorageUsage();
203
203
  console.log(storage.usedBytes, storage.availableBytes);
204
+ const { maxUploadBytes } = await files.options(path);
205
+ console.log(maxUploadBytes);
204
206
  await files.createDirectory("/rool-drive/documents");
205
207
  const written = await files.write(path, reportBlob, {
206
208
  contentType: "application/pdf",
@@ -209,6 +211,11 @@ const written = await files.write(path, reportBlob, {
209
211
  if (totalBytes) renderUploadProgress(transferredBytes / totalBytes);
210
212
  },
211
213
  });
214
+ await files.write(
215
+ "/rool-drive/documents/archive.bin",
216
+ () => createArchiveStream(),
217
+ { contentType: "application/octet-stream" },
218
+ );
212
219
  const info = await files.stat(path);
213
220
  const documents = await files.list("/rool-drive/documents");
214
221
  const response = await files.read(path, {
@@ -234,7 +241,7 @@ for (const result of deleted) {
234
241
  }
235
242
  ```
236
243
 
237
- Paths are absolute machine paths under `/space` or `/rool-drive`. `list()` without a path enumerates those storage roots; pass `{ recursive: true }` to enumerate a complete subtree. File and directory metadata has a discriminating `kind` field. Reads return the native `Response` so callers can stream the body. `readMultiple()` hydrates ordered small files in one request and returns an `ok` result with binary-safe bytes and validators, or a per-file HTTP failure. A batch accepts at most 128 paths, 2 MiB per successful file, and 16 MiB across successful files. Writes accept any `BodyInit`, including `Blob` and `ReadableStream`, and return the same complete file metadata as `stat()` and `list()`. `onUploadProgress` reports transferred bytes and includes the total size when it is known; successful completion is confirmed by the `write()` promise. Copy and move operations overwrite by default; pass `{ overwrite: false }` for create-only behavior.
244
+ Paths are absolute machine paths under `/space` or `/rool-drive`. `list()` without a path enumerates those storage roots; pass `{ recursive: true }` to enumerate a complete subtree. File and directory metadata has a discriminating `kind` field. Reads return the native `Response` so callers can stream the body. `readMultiple()` hydrates ordered small files in one request and returns an `ok` result with binary-safe bytes and validators, or a per-file HTTP failure. A batch accepts at most 128 paths, 2 MiB per successful file, and 16 MiB across successful files. Writes accept any `BodyInit`, including `Blob` and `ReadableStream`, and return the same complete file metadata as `stat()` and `list()`. Pass a function that creates a fresh `ReadableStream` when an upload must be replayable after a machine route change; a directly passed stream remains one-shot. `onUploadProgress` reports transferred bytes and includes the total size when it is known; successful completion is confirmed by the `write()` promise. `options(path)` reports `maxUploadBytes` for that path's storage root. Calling `options()` without a path reports whole-DAV capabilities and returns `null` for `maxUploadBytes` because `/space` and `/rool-drive` have different limits. Copy and move operations overwrite by default; pass `{ overwrite: false }` for create-only behavior.
238
245
 
239
246
  `deleteMultiple()` sends independent DAV requests with at most eight in flight. It accepts plain paths and targets carrying their own HTTP preconditions, and returns one ordered success or failure result per target. The requests are not atomic. A directory target recursively deletes its contents, so callers should omit redundant descendants; duplicate and overlapping targets otherwise remain independent and can race.
240
247
 
@@ -313,30 +320,29 @@ const defaultAgent = await machine.agents.get("rool");
313
320
  if (!defaultAgent) throw new Error("Rool agent is unavailable");
314
321
 
315
322
  const conversation = defaultAgent.conversation("research-chat");
323
+ const stopWatching = conversation.watch((view) => {
324
+ renderConversation({
325
+ turns: view.turns,
326
+ output: view.output,
327
+ isRunning: view.isRunning,
328
+ loading: view.loading,
329
+ error: view.error,
330
+ });
331
+ });
332
+
316
333
  await conversation.prompt("Explain the result.", { effort: "reasoning" });
317
334
 
318
- renderSettled(await conversation.listTurns());
319
- clearUnsettled();
320
- await conversation.follow({
321
- onEvent: (event) => {
322
- if (event.type !== "output.delta") return;
323
- if (event.content.type === "text") {
324
- renderUnsettledText(event.content.text);
325
- } else if (event.content.type === "tool_call") {
326
- showRunningTool(event.content.id, event.content.name);
327
- } else if (event.content.type === "tool_result") {
328
- showToolResult(event.content.id, event.content.content);
329
- }
330
- },
331
- });
332
- renderSettled(await conversation.listTurns());
335
+ // When this conversation leaves the UI:
336
+ stopWatching();
333
337
  ```
334
338
 
335
339
  `prompt()` starts the conversation's current run and resolves once the server accepts it. The agent runs as a detached job. A conversation can only have one current run; call `cancel()` and wait for `follow()` to finish before prompting again. The `readOnly` option is accepted for compatibility with legacy prompting but currently has no effect.
336
340
 
337
- `follow()` performs one `GET` of the conversation's current run. It receives the complete unsettled part of the conversation and then continues with new events until that response ends. Tool calls and their results arrive as `output.delta` events with matching IDs. A tool result contains nested content parts and an optional `error` flag. `follow()` returns `false` when there is no current run. A client can always render the conversation from its durable turns plus the events from its latest `follow()` call.
341
+ `watch()` is the normal UI API. It fetches only turns after the last turn it has seen, follows the current run, and refreshes the durable turns when that stream ends. `turns` contains saved history through the current user message while a run is active; `output` contains that run's replayed and live output. The first listener starts the work and removing the last listener stops it. Saved turns remain cached on the conversation handle for the next listener.
342
+
343
+ `follow()` is the lower-level streaming API. It performs one `GET` of the conversation's current run. It receives the complete current-run output and then continues with new events until that response ends. Tool calls and their results arrive as `output.delta` events with matching IDs. A tool result contains nested content parts and an optional `error` flag. `follow()` returns `false` when there is no current run. Aborting `follow()` only stops that request; call `cancel()` to stop the detached job.
338
344
 
339
- A `conversation_changed` account event tells clients to fetch the durable turns and follow the current run again. Aborting `follow()` only stops watching. Call `cancel()` to stop the detached job.
345
+ The SDK uses `conversation_changed` account events to wake active watchers. A watcher also refreshes after prompting, cancellation, stream completion, connection failure, and account event-token replacement.
340
346
 
341
347
  Prompt attachments are existing `/space` or `/rool-drive` paths. Pass a durable user turn's `id` as `replaceTurnId` to replace that message and everything after it. This supports edits and rerolls, including the first message. A replacement gets a new user turn ID; use that ID to edit it again.
342
348
 
@@ -354,12 +360,12 @@ await conversation.prompt("Return the number of records.", {
354
360
  await conversation.follow();
355
361
 
356
362
  const turns = await conversation.listTurns();
357
- const part = turns.at(-1)?.body.content[0];
363
+ const part = turns.at(-1)?.content[0];
358
364
  if (part?.type !== "json") throw new Error("No structured result");
359
365
  console.log(part.value); // { count: ... }
360
366
  ```
361
367
 
362
- Custom agent definitions currently contain one plain system prompt. The server owns the executable agent implementation.
368
+ A custom agent's `system` field contains instructions added after Rool's built-in machine context. Each conversation can add another instruction layer without changing the agent or its metadata.
363
369
 
364
370
  ```typescript
365
371
  const researcher = await machine.agents.create("researcher", {
@@ -369,10 +375,15 @@ const customConversation = await researcher.createConversation({
369
375
  name: "Climate report",
370
376
  visibility: "private",
371
377
  });
378
+ await customConversation.replaceInstructions(
379
+ "For this conversation, compare at least two sources.",
380
+ );
372
381
  await customConversation.prompt("Investigate this claim.");
373
382
  ```
374
383
 
375
- Agents expose `replace()` and `delete()`. Conversations expose metadata replacement, listing, durable turn reads, rename, and deletion. Listed and fetched conversation metadata includes server-managed ISO 8601 `createdAt` and `updatedAt` timestamps plus `isRunning`, which can drive a running indicator without opening every run stream. Visibility defaults to private. The built-in `rool` agent cannot be replaced or deleted.
384
+ `getInstructions()` returns the conversation instructions. `replaceInstructions("")` clears them. Metadata changes do not affect them. New instructions apply to the next run; a run already in progress keeps the instructions it started with.
385
+
386
+ Agents expose `replace()` and `delete()`. Conversations expose instruction and metadata replacement, listing, durable turn reads, rename, and deletion. Listed and fetched conversation metadata includes server-managed ISO 8601 `createdAt` and `updatedAt` timestamps plus `isRunning`, which can drive a running indicator without opening every run stream. Visibility defaults to private. The built-in `rool` agent cannot be replaced or deleted.
376
387
 
377
388
  ## Members and invites
378
389
 
@@ -427,6 +438,19 @@ const updated = await client.rotateGiftCode(giftId);
427
438
 
428
439
  Gift failures are `RoolProblem` errors. `gift_invalid` means the code or gift is unavailable to the caller. `gift_claimed` means it was already claimed.
429
440
 
441
+ ## Speechmatics
442
+
443
+ Voice input transcribes the user's speech with Speechmatics' real-time API. Rool mints a short-lived key without exposing its long-lived provider key; hand the temporary key to the Speechmatics real-time SDK and stream the user's mic audio to it.
444
+
445
+ ```typescript
446
+ const { token, expiresAt, ttl } = await client.getSpeechmaticsToken({
447
+ ttl: 300,
448
+ });
449
+ // speechmaticsRealtimeClient.start(token, { transcription_config: { language: "en" } })
450
+ ```
451
+
452
+ The key expires after `ttl` seconds (60–3600, default 300). `expiresAt` is the epoch-milliseconds moment the key stops being accepted. A token request fails with `insufficient_credits` when the account's balance is too low and with `speechmatics_unavailable` when Speechmatics cannot issue a key.
453
+
430
454
  ## API problems
431
455
 
432
456
  Each problem `type` links to its entry below.
@@ -611,6 +635,18 @@ The gift has already been claimed. A claimed gift cannot be claimed again or giv
611
635
 
612
636
  The gift update is empty or contains an invalid note or archived value.
613
637
 
638
+ <a id="problem-insufficient_credits"></a>
639
+
640
+ ### `insufficient_credits`
641
+
642
+ The account's credit balance is too low to mint a speech transcription key. Top up the balance and try again.
643
+
644
+ <a id="problem-speechmatics_unavailable"></a>
645
+
646
+ ### `speechmatics_unavailable`
647
+
648
+ Speechmatics could not issue a transcription key right now. Try again shortly.
649
+
614
650
  ## Development
615
651
 
616
652
  ```bash
package/dist/agents.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { RoolClientEvent } from "./events.js";
1
2
  import type { MachineFilePath } from "./files.js";
2
3
  export type MachinePromptEffort = "quick" | "standard" | "reasoning" | "research";
3
4
  export type MachineAssistantFinish = "stop" | "tool_calls" | "length" | "safety" | "error" | "credits" | "cancelled";
@@ -24,7 +25,10 @@ export type MachineConversationContentPart = {
24
25
  type: "json";
25
26
  value: unknown;
26
27
  };
27
- export interface MachineConversationTurnBody {
28
+ export interface MachineConversationTurn {
29
+ id: string;
30
+ userId?: string;
31
+ createdAt: string;
28
32
  role: MachineConversationTurnRole;
29
33
  content: MachineConversationContentPart[];
30
34
  request?: Record<string, unknown>;
@@ -36,13 +40,8 @@ export interface MachineConversationTurnBody {
36
40
  };
37
41
  aside?: boolean;
38
42
  }
39
- export interface MachineConversationTurn {
40
- id: string;
41
- userId?: string;
42
- createdAt: string;
43
- body: MachineConversationTurnBody;
44
- }
45
43
  export interface MachineAgentDefinition {
44
+ /** Instructions added after Rool's built-in machine context. */
46
45
  system: string;
47
46
  }
48
47
  export type MachineAgentCreateInput = MachineAgentDefinition;
@@ -95,12 +94,25 @@ export interface MachineConversationFollowOptions extends AgentRequestOptions {
95
94
  onEvent?: (event: MachineRunEvent) => void;
96
95
  }
97
96
  export type MachineConversationCancelOptions = AgentRequestOptions;
97
+ export interface MachineConversationView {
98
+ readonly turns: readonly MachineConversationTurn[];
99
+ readonly output: readonly MachineConversationContentPart[];
100
+ readonly isRunning: boolean;
101
+ readonly loading: boolean;
102
+ readonly error: unknown;
103
+ }
104
+ export type MachineConversationListener = (view: MachineConversationView) => void;
98
105
  export interface MachineConversation {
99
106
  readonly id: string;
100
107
  readonly agent: MachineAgent;
101
108
  get(options?: AgentRequestOptions): Promise<MachineConversationState | undefined>;
102
109
  listTurns(options?: AgentRequestOptions): Promise<MachineConversationTurn[]>;
110
+ watch(listener: MachineConversationListener): () => void;
103
111
  replace(metadata: MachineConversationMetadataInput, options?: AgentRequestOptions): Promise<MachineConversationMetadata>;
112
+ /** Return conversation-specific instructions; an empty string means none. */
113
+ getInstructions(options?: AgentRequestOptions): Promise<string>;
114
+ /** Replace conversation-specific instructions; pass an empty string to clear. */
115
+ replaceInstructions(instructions: string, options?: AgentRequestOptions): Promise<string>;
104
116
  prompt(text: string, options?: MachineConversationPromptOptions): Promise<void>;
105
117
  follow(options?: MachineConversationFollowOptions): Promise<boolean>;
106
118
  cancel(options?: MachineConversationCancelOptions): Promise<boolean>;
@@ -124,7 +136,8 @@ export interface MachineAgents {
124
136
  interface AgentTransport {
125
137
  request(path: string, init?: RequestInit, allowHttpErrors?: boolean): Promise<Response>;
126
138
  requestJson<T>(path: string, init?: RequestInit): Promise<T>;
139
+ subscribeEvents(listener: (event: RoolClientEvent) => void): () => void;
127
140
  }
128
- export declare function createMachineAgents(machinePath: string, transport: AgentTransport): MachineAgents;
141
+ export declare function createMachineAgents(machineId: string, machinePath: string, transport: AgentTransport): MachineAgents;
129
142
  export {};
130
143
  //# sourceMappingURL=agents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
package/dist/agents.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import { throwProblemResponse } from "./problem.js";
2
2
  const VALID_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
3
3
  const MAX_EVENT_BYTES = 1024 * 1024;
4
+ const WATCH_RETRY_MAX_MS = 5_000;
4
5
  class MachineAgentState {
6
+ machineId;
5
7
  machinePath;
6
8
  transport;
7
9
  agents = new Map();
8
- constructor(machinePath, transport) {
10
+ constructor(machineId, machinePath, transport) {
11
+ this.machineId = machineId;
9
12
  this.machinePath = machinePath;
10
13
  this.transport = transport;
11
14
  }
@@ -73,17 +76,32 @@ class MachineAgentState {
73
76
  if (!response.ok)
74
77
  await throwProblemResponse(response);
75
78
  const metadata = (await response.json());
76
- const turns = await this.listTurns(agentId, conversationId, options);
77
- return { ...metadata, turns };
79
+ const update = await this.readTurnUpdate(agentId, conversationId, undefined, options.signal);
80
+ return { ...metadata, isRunning: update.isRunning, turns: update.turns };
78
81
  }
79
82
  async listTurns(agentId, conversationId, options = {}) {
80
- const { turns } = await this.transport.requestJson(`${this.conversationPath(agentId, conversationId)}/turns`, { signal: options.signal });
81
- return turns.map(turnFromWire);
83
+ return (await this.readTurnUpdate(agentId, conversationId, undefined, options.signal)).turns;
84
+ }
85
+ async readTurnUpdate(agentId, conversationId, after, signal) {
86
+ const query = after ? `?${new URLSearchParams({ after }).toString()}` : "";
87
+ return this.transport.requestJson(`${this.conversationPath(agentId, conversationId)}/turns${query}`, { signal });
88
+ }
89
+ subscribeEvents(listener) {
90
+ return this.transport.subscribeEvents(listener);
82
91
  }
83
92
  replaceConversation(agentId, conversationId, metadata, options = {}) {
84
93
  validateMetadata(metadata);
85
94
  return this.transport.requestJson(this.conversationPath(agentId, conversationId), jsonRequest("PUT", metadata, options.signal));
86
95
  }
96
+ async getConversationInstructions(agentId, conversationId, options = {}) {
97
+ const result = await this.transport.requestJson(`${this.conversationPath(agentId, conversationId)}/instructions`, { signal: options.signal });
98
+ return result.instructions;
99
+ }
100
+ async replaceConversationInstructions(agentId, conversationId, instructions, options = {}) {
101
+ validateInstructions(instructions);
102
+ const result = await this.transport.requestJson(`${this.conversationPath(agentId, conversationId)}/instructions`, jsonRequest("PUT", { instructions }, options.signal));
103
+ return result.instructions;
104
+ }
87
105
  async deleteConversation(agent, conversationId, options = {}) {
88
106
  await this.transport.request(this.conversationPath(agent.id, conversationId), { method: "DELETE", signal: options.signal });
89
107
  agent.forgetConversation(conversationId);
@@ -230,6 +248,21 @@ class ConversationClient {
230
248
  agent;
231
249
  id;
232
250
  state;
251
+ listeners = new Set();
252
+ turns = [];
253
+ output = [];
254
+ isRunning = false;
255
+ loading = true;
256
+ error = null;
257
+ watchController = null;
258
+ unsubscribeEvents = null;
259
+ syncRequested = false;
260
+ syncLoop = null;
261
+ retryTimer = null;
262
+ retryMs = 250;
263
+ followController = null;
264
+ followTask = null;
265
+ followRetryMs = 250;
233
266
  constructor(agent, id, state) {
234
267
  this.agent = agent;
235
268
  this.id = id;
@@ -241,17 +274,44 @@ class ConversationClient {
241
274
  listTurns(options = {}) {
242
275
  return this.state.listTurns(this.agent.id, this.id, options);
243
276
  }
277
+ watch(listener) {
278
+ this.listeners.add(listener);
279
+ listener(this.view());
280
+ if (!this.watchController)
281
+ this.startWatching();
282
+ return () => {
283
+ this.listeners.delete(listener);
284
+ if (this.listeners.size === 0)
285
+ this.stopWatching();
286
+ };
287
+ }
244
288
  replace(metadata, options) {
245
289
  return this.state.replaceConversation(this.agent.id, this.id, metadata, options);
246
290
  }
247
- prompt(text, options = {}) {
248
- return this.state.prompt(this.agent.id, this.id, text, options);
291
+ getInstructions(options) {
292
+ return this.state.getConversationInstructions(this.agent.id, this.id, options);
293
+ }
294
+ replaceInstructions(instructions, options) {
295
+ return this.state.replaceConversationInstructions(this.agent.id, this.id, instructions, options);
296
+ }
297
+ async prompt(text, options = {}) {
298
+ try {
299
+ await this.state.prompt(this.agent.id, this.id, text, options);
300
+ }
301
+ finally {
302
+ this.requestSync();
303
+ }
249
304
  }
250
305
  follow(options) {
251
306
  return this.state.follow(this.agent.id, this.id, options);
252
307
  }
253
- cancel(options) {
254
- return this.state.cancel(this.agent.id, this.id, options);
308
+ async cancel(options) {
309
+ try {
310
+ return await this.state.cancel(this.agent.id, this.id, options);
311
+ }
312
+ finally {
313
+ this.requestSync();
314
+ }
255
315
  }
256
316
  async rename(name, options = {}) {
257
317
  const current = await this.get(options);
@@ -265,25 +325,178 @@ class ConversationClient {
265
325
  delete(options) {
266
326
  return this.state.deleteConversation(this.agent, this.id, options);
267
327
  }
328
+ startWatching() {
329
+ const controller = new AbortController();
330
+ this.watchController = controller;
331
+ this.unsubscribeEvents = this.state.subscribeEvents((event) => {
332
+ const matchesConversation = event.type === "conversation_changed" &&
333
+ event.machineId === this.state.machineId &&
334
+ event.agentId === this.agent.id &&
335
+ event.conversationId === this.id;
336
+ if (event.type === "session" || matchesConversation) {
337
+ if (!this.followTask || event.type === "session")
338
+ this.requestSync();
339
+ }
340
+ });
341
+ this.requestSync();
342
+ }
343
+ stopWatching() {
344
+ this.watchController?.abort();
345
+ this.watchController = null;
346
+ this.followController?.abort();
347
+ this.followController = null;
348
+ this.unsubscribeEvents?.();
349
+ this.unsubscribeEvents = null;
350
+ this.syncRequested = false;
351
+ if (this.retryTimer)
352
+ clearTimeout(this.retryTimer);
353
+ this.retryTimer = null;
354
+ }
355
+ requestSync() {
356
+ const controller = this.watchController;
357
+ if (!controller || controller.signal.aborted)
358
+ return;
359
+ this.syncRequested = true;
360
+ if (this.retryTimer)
361
+ clearTimeout(this.retryTimer);
362
+ this.retryTimer = null;
363
+ if (this.syncLoop)
364
+ return;
365
+ const loop = this.runSyncLoop(controller);
366
+ this.syncLoop = loop;
367
+ const finished = () => {
368
+ if (this.syncLoop === loop)
369
+ this.syncLoop = null;
370
+ const current = this.watchController;
371
+ if (current && this.syncRequested && !current.signal.aborted) {
372
+ this.requestSync();
373
+ }
374
+ };
375
+ void loop.then(finished, finished);
376
+ }
377
+ async runSyncLoop(controller) {
378
+ while (this.watchController === controller &&
379
+ !controller.signal.aborted &&
380
+ this.syncRequested) {
381
+ this.syncRequested = false;
382
+ try {
383
+ const after = this.turns.at(-1)?.id;
384
+ const update = await this.state.readTurnUpdate(this.agent.id, this.id, after, controller.signal);
385
+ if (controller.signal.aborted)
386
+ return;
387
+ this.turns = update.reset
388
+ ? update.turns
389
+ : [...this.turns, ...update.turns];
390
+ this.isRunning = update.isRunning;
391
+ this.loading = false;
392
+ this.error = null;
393
+ this.retryMs = 250;
394
+ if (!this.isRunning || (update.reset && this.followTask)) {
395
+ this.followController?.abort();
396
+ this.output = [];
397
+ }
398
+ this.emit();
399
+ if (this.isRunning)
400
+ this.ensureFollow(controller);
401
+ }
402
+ catch (error) {
403
+ if (controller.signal.aborted || isAbortError(error))
404
+ return;
405
+ this.loading = false;
406
+ this.error = error;
407
+ this.emit();
408
+ this.scheduleRetry(controller);
409
+ return;
410
+ }
411
+ }
412
+ }
413
+ scheduleRetry(controller) {
414
+ if (this.retryTimer || this.watchController !== controller)
415
+ return;
416
+ const delay = this.retryMs;
417
+ this.retryMs = Math.min(this.retryMs * 2, WATCH_RETRY_MAX_MS);
418
+ this.retryTimer = setTimeout(() => {
419
+ this.retryTimer = null;
420
+ this.requestSync();
421
+ }, delay);
422
+ }
423
+ ensureFollow(watchController) {
424
+ if (this.followTask || this.watchController !== watchController)
425
+ return;
426
+ const controller = new AbortController();
427
+ this.followController = controller;
428
+ this.output = [];
429
+ this.emit();
430
+ const task = this.runFollow(controller);
431
+ this.followTask = task;
432
+ const finished = () => {
433
+ if (this.followTask === task)
434
+ this.followTask = null;
435
+ if (this.followController === controller)
436
+ this.followController = null;
437
+ const current = this.watchController;
438
+ if (current && !current.signal.aborted)
439
+ this.requestSync();
440
+ };
441
+ void task.then(finished, finished);
442
+ }
443
+ async runFollow(controller) {
444
+ let streamFailed = null;
445
+ try {
446
+ await this.state.follow(this.agent.id, this.id, {
447
+ signal: controller.signal,
448
+ onEvent: (event) => {
449
+ if (event.type === "output.delta") {
450
+ this.output = [...this.output, event.content];
451
+ this.error = null;
452
+ this.emit();
453
+ }
454
+ else if (event.type === "error" &&
455
+ event.code === "run_stream_failed") {
456
+ streamFailed = new Error(event.detail);
457
+ }
458
+ },
459
+ });
460
+ if (streamFailed)
461
+ throw streamFailed;
462
+ this.followRetryMs = 250;
463
+ }
464
+ catch (error) {
465
+ if (controller.signal.aborted || isAbortError(error))
466
+ return;
467
+ this.error = error;
468
+ this.emit();
469
+ const delay = this.followRetryMs;
470
+ this.followRetryMs = Math.min(this.followRetryMs * 2, WATCH_RETRY_MAX_MS);
471
+ await abortableDelay(delay, controller.signal);
472
+ }
473
+ }
474
+ view() {
475
+ let end = this.turns.length;
476
+ if (this.isRunning) {
477
+ for (let index = this.turns.length - 1; index >= 0; index--) {
478
+ if (this.turns[index].role !== "user")
479
+ continue;
480
+ end = index + 1;
481
+ break;
482
+ }
483
+ }
484
+ return {
485
+ turns: this.turns.slice(0, end),
486
+ output: [...this.output],
487
+ isRunning: this.isRunning,
488
+ loading: this.loading,
489
+ error: this.error,
490
+ };
491
+ }
492
+ emit() {
493
+ const view = this.view();
494
+ for (const listener of this.listeners)
495
+ listener(view);
496
+ }
268
497
  }
269
- export function createMachineAgents(machinePath, transport) {
270
- return new MachineAgentState(machinePath, transport);
271
- }
272
- function turnFromWire(turn) {
273
- return {
274
- id: turn.id,
275
- ...(turn.userId ? { userId: turn.userId } : {}),
276
- createdAt: turn.createdAt,
277
- body: {
278
- role: turn.role,
279
- content: turn.content,
280
- ...(turn.request ? { request: turn.request } : {}),
281
- ...(turn.finish ? { finish: turn.finish } : {}),
282
- ...(turn.error ? { error: turn.error } : {}),
283
- ...(turn.usage ? { usage: turn.usage } : {}),
284
- ...(turn.aside !== undefined ? { aside: turn.aside } : {}),
285
- },
286
- };
498
+ export function createMachineAgents(machineId, machinePath, transport) {
499
+ return new MachineAgentState(machineId, machinePath, transport);
287
500
  }
288
501
  function parseRunEvent(line) {
289
502
  const value = JSON.parse(line);
@@ -312,7 +525,7 @@ function parseRunEvent(line) {
312
525
  }
313
526
  function validateDefinition(definition) {
314
527
  if (!definition || typeof definition.system !== "string") {
315
- throw new Error("Agent system prompt must be a string");
528
+ throw new Error("Agent system instructions must be a string");
316
529
  }
317
530
  }
318
531
  function validateMetadata(metadata) {
@@ -323,6 +536,11 @@ function validateMetadata(metadata) {
323
536
  throw new Error("Conversation name must be a string");
324
537
  }
325
538
  }
539
+ function validateInstructions(instructions) {
540
+ if (typeof instructions !== "string") {
541
+ throw new Error("Conversation instructions must be a string");
542
+ }
543
+ }
326
544
  function validateAttachment(path) {
327
545
  const supported = path.startsWith("/space/") || path.startsWith("/rool-drive/");
328
546
  if (!supported) {
@@ -345,4 +563,21 @@ function jsonRequest(method, body, signal) {
345
563
  function randomId() {
346
564
  return globalThis.crypto.randomUUID();
347
565
  }
566
+ function isAbortError(error) {
567
+ return (error instanceof Error &&
568
+ (error.name === "AbortError" || error.message.includes("was aborted")));
569
+ }
570
+ async function abortableDelay(milliseconds, signal) {
571
+ if (signal.aborted)
572
+ return;
573
+ await new Promise((resolve) => {
574
+ const timeout = setTimeout(finish, milliseconds);
575
+ signal.addEventListener("abort", finish, { once: true });
576
+ function finish() {
577
+ clearTimeout(timeout);
578
+ signal.removeEventListener("abort", finish);
579
+ resolve();
580
+ }
581
+ });
582
+ }
348
583
  //# sourceMappingURL=agents.js.map