@astralform/js 9.0.0 → 9.2.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/README.md CHANGED
@@ -35,10 +35,24 @@ session.on((event) => {
35
35
  });
36
36
 
37
37
  await session.connect();
38
- await session.send("What is the capital of France?");
38
+
39
+ // A conversation's first message names its model — one the agent's team has
40
+ // connected. Later messages in the same conversation may omit it and reuse the
41
+ // conversation's model.
42
+ const models = await session.client.getModels(); // the list backs a model picker
43
+ const model = models[0];
44
+ if (!model) throw new Error("Connect a model provider for this agent first.");
45
+ await session.send("What is the capital of France?", {
46
+ provider: model.provider,
47
+ model: model.model,
48
+ });
39
49
  session.disconnect();
40
50
  ```
41
51
 
52
+ The examples below omit `provider` and `model` for brevity. On a conversation's first
53
+ message, pass them as above: newer Astralform servers reject a new conversation that
54
+ names no model, and every server accepts one that does.
55
+
42
56
  ## Features
43
57
 
44
58
  - **SSE Streaming** — Real-time token-by-token responses via Server-Sent Events
@@ -323,7 +337,11 @@ const skills = await client.getSkills();
323
337
  const commands = await client.listSkillCommands();
324
338
 
325
339
  // Job-based streaming
326
- const job = await client.createJob({ message: "Hello" });
340
+ const job = await client.createJob({
341
+ message: "Hello",
342
+ provider: "anthropic", // a new conversation names its model
343
+ model: "claude-sonnet-5",
344
+ });
327
345
  for await (const event of client.streamJobEvents(job.job_id)) {
328
346
  const data = JSON.parse(event.data);
329
347
  if (data.type === "block_delta" && data.delta.channel === "text") {
package/dist/index.cjs CHANGED
@@ -1029,7 +1029,11 @@ var AstralformClient = class {
1029
1029
  // `VoicePolishMode`; `structured` is the server's own default.
1030
1030
  defaultMode: isVoicePolishMode(raw.default_mode) ? raw.default_mode : "structured",
1031
1031
  silenceAutoStopSeconds: raw.silence_auto_stop_seconds ?? 2,
1032
- autoSend: raw.auto_send ?? true,
1032
+ // Deliberately not read from the wire. Auto-send was removed from the
1033
+ // platform (2026-09-14) and the server pins `auto_send` to false; an
1034
+ // older server still sending `true` must not make a client auto-send, so
1035
+ // an absent field and an explicit `true` both read as false.
1036
+ autoSend: false,
1033
1037
  maxRecordingSeconds: raw.max_recording_seconds ?? 300,
1034
1038
  supportsStreaming: Boolean(raw.supports_streaming),
1035
1039
  hotwords: raw.hotwords ?? []
@@ -3414,7 +3418,13 @@ var StreamManager = class _StreamManager {
3414
3418
  conversationId,
3415
3419
  position: "prepend",
3416
3420
  hasMore: completed ? page.hasMore : true,
3417
- complete: completed
3421
+ complete: completed,
3422
+ // Empty on the incomplete path, matching the blocks a consumer is
3423
+ // required to discard there: that page's cursor did not advance, so
3424
+ // these same turns replay from the start on the next request and
3425
+ // rehydrating from them now would key state to turns about to be
3426
+ // re-emitted.
3427
+ jobs: completed ? page.jobs : []
3418
3428
  });
3419
3429
  return emitted;
3420
3430
  } finally {
@@ -3503,7 +3513,7 @@ var StreamManager = class _StreamManager {
3503
3513
  this.oldestDrawnMessageId = plan[0]?.messageId ?? null;
3504
3514
  complete = true;
3505
3515
  if (stopReplay()) return false;
3506
- this.emit({ type: "restoreSettled", conversationId });
3516
+ this.emit({ type: "restoreSettled", conversationId, jobs });
3507
3517
  const versionCount = replayableJobs.filter(
3508
3518
  (j) => j.status === "completed"
3509
3519
  ).length;