@raisindb/client 0.5.8 → 0.5.10

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.
Files changed (40) hide show
  1. package/README.md +32 -0
  2. package/dist/{chunk-IFV4ECHC.mjs → chunk-ASOWGNQZ.mjs} +3 -3
  3. package/dist/{chunk-ZUUSBLVP.mjs → chunk-FYWYSNQG.mjs} +3 -3
  4. package/dist/{chunk-765DLJMZ.mjs → chunk-NOPZAMIV.mjs} +31 -2
  5. package/dist/chunk-NOPZAMIV.mjs.map +1 -0
  6. package/dist/{chunk-AULHRX5C.mjs → chunk-TPZNJNZR.mjs} +2 -2
  7. package/dist/{chunk-VMUT6PIO.mjs → chunk-ZCRYQCXS.mjs} +2 -2
  8. package/dist/{conversation-list-store-BaeGM2lx.d.mts → conversation-list-store-CqgIk8Rn.d.mts} +915 -3
  9. package/dist/{conversation-list-store-BaeGM2lx.d.ts → conversation-list-store-CqgIk8Rn.d.ts} +915 -3
  10. package/dist/{index-C4pX6FVI.d.mts → index-BD3rutlF.d.mts} +1 -1
  11. package/dist/{index-DCtNAWZ0.d.ts → index-CDUAMIub.d.ts} +1 -1
  12. package/dist/index.d.mts +4 -4
  13. package/dist/index.d.ts +4 -4
  14. package/dist/index.js +934 -6
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +902 -10
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/react.d.mts +2 -2
  19. package/dist/react.d.ts +2 -2
  20. package/dist/react.js +30 -1
  21. package/dist/react.js.map +1 -1
  22. package/dist/react.mjs +3 -3
  23. package/dist/{svelte-sql-DN3NpM4c.d.ts → svelte-sql-D9YU1wYS.d.ts} +1 -1
  24. package/dist/{svelte-sql-BhMxrqn_.d.mts → svelte-sql-l1wmTWM4.d.mts} +1 -1
  25. package/dist/svelte.d.mts +2 -2
  26. package/dist/svelte.d.ts +2 -2
  27. package/dist/svelte.js +30 -1
  28. package/dist/svelte.js.map +1 -1
  29. package/dist/svelte.mjs +3 -3
  30. package/dist/vue.d.mts +2 -2
  31. package/dist/vue.d.ts +2 -2
  32. package/dist/vue.js +30 -1
  33. package/dist/vue.js.map +1 -1
  34. package/dist/vue.mjs +2 -2
  35. package/package.json +1 -1
  36. package/dist/chunk-765DLJMZ.mjs.map +0 -1
  37. /package/dist/{chunk-IFV4ECHC.mjs.map → chunk-ASOWGNQZ.mjs.map} +0 -0
  38. /package/dist/{chunk-ZUUSBLVP.mjs.map → chunk-FYWYSNQG.mjs.map} +0 -0
  39. /package/dist/{chunk-AULHRX5C.mjs.map → chunk-TPZNJNZR.mjs.map} +0 -0
  40. /package/dist/{chunk-VMUT6PIO.mjs.map → chunk-ZCRYQCXS.mjs.map} +0 -0
package/dist/index.js CHANGED
@@ -27,6 +27,8 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
27
27
  // src/index.ts
28
28
  var src_exports = {};
29
29
  __export(src_exports, {
30
+ AgentRunsApi: () => AgentRunsApi,
31
+ AgentRunsWsApi: () => AgentRunsWsApi,
30
32
  AllNodeEventTypes: () => AllNodeEventTypes,
31
33
  Archetypes: () => Archetypes,
32
34
  AuthManager: () => AuthManager,
@@ -67,6 +69,7 @@ __export(src_exports, {
67
69
  McpClient: () => McpClient,
68
70
  MemoryTokenStorage: () => MemoryTokenStorage,
69
71
  NodeBuilder: () => NodeBuilder,
72
+ NodeDevApi: () => NodeDevApi,
70
73
  NodeEventType: () => NodeEventType,
71
74
  NodeFileSource: () => NodeFileSource,
72
75
  NodeHelpers: () => NodeHelpers,
@@ -96,6 +99,7 @@ __export(src_exports, {
96
99
  UploadErrorCode: () => UploadErrorCode,
97
100
  UploadManager: () => UploadManager,
98
101
  Uploader: () => Uploader,
102
+ VisitorChatError: () => VisitorChatError,
99
103
  WorkspaceClient: () => WorkspaceClient,
100
104
  WorkspaceManager: () => WorkspaceManager,
101
105
  calculateChunkCount: () => calculateChunkCount,
@@ -117,6 +121,7 @@ __export(src_exports, {
117
121
  createSqlHandler: () => createSqlHandler,
118
122
  createSubscriptionAdapter: () => createSubscriptionAdapter,
119
123
  decodeMessage: () => decodeMessage,
124
+ defaultVisitorSessionStore: () => defaultVisitorSessionStore,
120
125
  encodeMessage: () => encodeMessage,
121
126
  getChunkRange: () => getChunkRange,
122
127
  getContentType: () => getContentType,
@@ -134,12 +139,14 @@ __export(src_exports, {
134
139
  isTerminalEvent: () => isTerminalEvent,
135
140
  isWebSocketClient: () => isWebSocketClient,
136
141
  logger: () => logger,
142
+ newControlId: () => newControlId,
137
143
  normalizeHomePath: () => normalizeHomePath,
138
144
  projectPlansFromMessages: () => projectPlansFromMessages,
139
145
  readTokensFromFragment: () => readTokensFromFragment,
140
146
  rowsToObjects: () => rowsToObjects,
141
147
  setLogLevel: () => setLogLevel,
142
148
  sleep: () => sleep,
149
+ subjectOf: () => subjectOf,
143
150
  useConversation: () => useConversation,
144
151
  useConversationList: () => useConversationList,
145
152
  useFlow: () => useFlow,
@@ -953,12 +960,23 @@ var RequestType = /* @__PURE__ */ ((RequestType2) => {
953
960
  RequestType2["FlowCancel"] = "flow_cancel";
954
961
  RequestType2["FlowSubscribeEvents"] = "flow_subscribe_events";
955
962
  RequestType2["FlowUnsubscribeEvents"] = "flow_unsubscribe_events";
963
+ RequestType2["AgentRunCreate"] = "agent_run_create";
964
+ RequestType2["AgentRunGet"] = "agent_run_get";
965
+ RequestType2["AgentRunBySubject"] = "agent_run_by_subject";
966
+ RequestType2["AgentRunList"] = "agent_run_list";
967
+ RequestType2["AgentRunEvents"] = "agent_run_events";
968
+ RequestType2["AgentRunSubscribe"] = "agent_run_subscribe";
969
+ RequestType2["AgentRunUnsubscribe"] = "agent_run_unsubscribe";
970
+ RequestType2["AgentRunControl"] = "agent_run_control";
971
+ RequestType2["AgentRunChildren"] = "agent_run_children";
956
972
  RequestType2["FunctionInvoke"] = "function_invoke";
957
973
  RequestType2["FunctionInvokeSync"] = "function_invoke_sync";
958
974
  RequestType2["ScheduledInvocationCreate"] = "scheduled_invocation_create";
959
975
  RequestType2["ScheduledInvocationCancel"] = "scheduled_invocation_cancel";
960
976
  RequestType2["ScheduledInvocationList"] = "scheduled_invocation_list";
961
977
  RequestType2["ScheduledInvocationGet"] = "scheduled_invocation_get";
978
+ RequestType2["VisitorChatStart"] = "visitor_chat_start";
979
+ RequestType2["VisitorChatSend"] = "visitor_chat_send";
962
980
  return RequestType2;
963
981
  })(RequestType || {});
964
982
  var ResponseStatus = /* @__PURE__ */ ((ResponseStatus2) => {
@@ -1242,7 +1260,8 @@ var EventHandler = class {
1242
1260
  this.filterSubscriptions.set(hash, {
1243
1261
  serverId: subscriptionId,
1244
1262
  filters: {},
1245
- callbacks: /* @__PURE__ */ new Set([callback])
1263
+ callbacks: /* @__PURE__ */ new Set([callback]),
1264
+ synthetic: true
1246
1265
  });
1247
1266
  this.subscriptions.set(subscriptionId, hash);
1248
1267
  this.callbackToHash.set(callback, hash);
@@ -1277,11 +1296,12 @@ var EventHandler = class {
1277
1296
  async restoreSubscriptions(options) {
1278
1297
  if (!options?.retry) {
1279
1298
  for (const entry of this.filterSubscriptions.values()) {
1299
+ if (entry.synthetic) continue;
1280
1300
  this.subscriptions.delete(entry.serverId);
1281
1301
  entry.restorePending = true;
1282
1302
  }
1283
1303
  }
1284
- const entriesToRestore = Array.from(this.filterSubscriptions.entries()).filter(([, entry]) => entry.restorePending);
1304
+ const entriesToRestore = Array.from(this.filterSubscriptions.entries()).filter(([, entry]) => entry.restorePending && !entry.synthetic);
1285
1305
  let failureCount = 0;
1286
1306
  let lastError;
1287
1307
  for (const [hash, entry] of entriesToRestore) {
@@ -3437,6 +3457,417 @@ function createAsyncQueue() {
3437
3457
  };
3438
3458
  }
3439
3459
 
3460
+ // src/agent-run-children.ts
3461
+ function spawnBody(o) {
3462
+ return {
3463
+ objective: o.objective,
3464
+ budgets: o.budgets,
3465
+ on_exceeded: o.onExceeded,
3466
+ spawn_key: o.spawnKey,
3467
+ subject: o.subject,
3468
+ as_agent: o.asAgent,
3469
+ agent_ref: o.agentRef,
3470
+ input: o.input ?? null,
3471
+ executor_config: o.executorConfig,
3472
+ reducer: o.reducer,
3473
+ inherit_reducer: o.inheritReducer ?? false
3474
+ };
3475
+ }
3476
+ function checkpointBody(o) {
3477
+ return {
3478
+ fence: o.fence,
3479
+ operation_id: o.operationId,
3480
+ reason: o.reason,
3481
+ summary: o.summary,
3482
+ transcript_cutoff: o.transcriptCutoff,
3483
+ state: o.state,
3484
+ large_refs: o.largeRefs ?? []
3485
+ };
3486
+ }
3487
+
3488
+ // src/agent-runs.ts
3489
+ function createRunBody(options) {
3490
+ return {
3491
+ subject: options.subject,
3492
+ branch: options.branch,
3493
+ agent_ref: options.agentRef,
3494
+ create_key: options.createKey,
3495
+ budgets: options.budgets,
3496
+ input: options.input ?? null,
3497
+ reducer: options.reducer,
3498
+ executor_config: options.executorConfig,
3499
+ control_capability: options.controlCapability,
3500
+ as_agent: options.asAgent
3501
+ };
3502
+ }
3503
+ function subjectOf(subject) {
3504
+ if (typeof subject !== "string") return subject;
3505
+ const cut = subject.indexOf(":/");
3506
+ if (cut <= 0) throw new Error(`subject must be "workspace:/path", got "${subject}"`);
3507
+ return { workspace: subject.slice(0, cut), path: subject.slice(cut + 1) };
3508
+ }
3509
+ var controlCounter = 0;
3510
+ function newControlId(prefix = "ctl") {
3511
+ controlCounter += 1;
3512
+ const rand = Math.random().toString(36).slice(2, 10);
3513
+ return `${prefix}-${Date.now().toString(36)}-${controlCounter}-${rand}`;
3514
+ }
3515
+ var AgentRunsApi = class {
3516
+ constructor(repository, transport) {
3517
+ this.repository = repository;
3518
+ this.transport = transport;
3519
+ }
3520
+ base(runId, rest = "") {
3521
+ const repo = encodeURIComponent(this.repository);
3522
+ const run = runId ? `/${encodeURIComponent(runId)}` : "";
3523
+ return `/api/agent-runs/${repo}${run}${rest}`;
3524
+ }
3525
+ /** Create a run, or get back the subject's live run. */
3526
+ create(options) {
3527
+ return this.transport.request("POST", this.base(), createRunBody(options));
3528
+ }
3529
+ /** Every run about `subject` you may see, newest (the live one) first. */
3530
+ bySubject(subject, limit = 20) {
3531
+ const s = subjectOf(subject);
3532
+ const q = new URLSearchParams({ subject: `${s.workspace}:${s.path ?? ""}`, limit: String(limit) });
3533
+ if (s.node_id) q.set("subject_node_id", s.node_id);
3534
+ return this.transport.request("GET", `${this.base()}?${q.toString()}`);
3535
+ }
3536
+ /** Read a run (record + effective projection). */
3537
+ get(runId) {
3538
+ return this.transport.request("GET", this.base(runId));
3539
+ }
3540
+ /** Your runs in one status (default "running"). */
3541
+ list(status = "running", limit = 50) {
3542
+ return this.transport.request("GET", `${this.base()}?status=${status}&limit=${limit}`);
3543
+ }
3544
+ /** Durable events after `afterSeq` (gap-free; page with the last seq). */
3545
+ events(runId, afterSeq = 0, limit = 500) {
3546
+ return this.transport.request("GET", this.base(runId, `/events?after_seq=${afterSeq}&limit=${limit}`));
3547
+ }
3548
+ /** Any control. Retrying with the same `controlId` is a no-op. */
3549
+ control(runId, command, controlId = newControlId(command.command), capability) {
3550
+ return this.transport.request("POST", this.base(runId, "/control"), {
3551
+ control_id: controlId,
3552
+ command,
3553
+ capability
3554
+ });
3555
+ }
3556
+ stop(runId, reason, controlId) {
3557
+ return this.control(runId, { command: "stop", reason }, controlId);
3558
+ }
3559
+ pause(runId, controlId) {
3560
+ return this.control(runId, { command: "pause" }, controlId);
3561
+ }
3562
+ resume(runId, controlId) {
3563
+ return this.control(runId, { command: "resume" }, controlId);
3564
+ }
3565
+ /** Queue input for the run's next safe boundary. */
3566
+ steer(runId, input, controlId) {
3567
+ return this.control(runId, { command: "steer", input }, controlId);
3568
+ }
3569
+ /** Decide an approval request; the digest ties it to one changeset. */
3570
+ approve(runId, requestId, subjectDigest, reject, controlId) {
3571
+ const decision = reject ? { decision: "reject", reason: reject.reason } : { decision: "approve" };
3572
+ return this.control(
3573
+ runId,
3574
+ { command: "approve", request_id: requestId, decision, subject_digest: subjectDigest },
3575
+ controlId
3576
+ );
3577
+ }
3578
+ /** Answer an input request. */
3579
+ answer(runId, requestId, value, controlId) {
3580
+ return this.control(runId, { command: "provide_input", request_id: requestId, value }, controlId);
3581
+ }
3582
+ /**
3583
+ * Stream the run's events: replay after `afterSeq`, then live. Ends after
3584
+ * the run's terminal event. Resume after a disconnect with the last `seq`.
3585
+ */
3586
+ async *stream(runId, afterSeq = 0, signal) {
3587
+ const response = await this.transport.fetch(
3588
+ this.transport.url(this.base(runId, `/stream?after_seq=${afterSeq}`)),
3589
+ { headers: { ...this.transport.headers(), Accept: "text/event-stream" }, signal }
3590
+ );
3591
+ if (!response.ok || !response.body) {
3592
+ throw new Error(`agent run stream failed: ${response.status} ${await response.text()}`);
3593
+ }
3594
+ const reader = response.body.getReader();
3595
+ const decoder = new TextDecoder();
3596
+ let buffer = "";
3597
+ for (; ; ) {
3598
+ const { value, done } = await reader.read();
3599
+ if (done) return;
3600
+ buffer += decoder.decode(value, { stream: true });
3601
+ let cut;
3602
+ while ((cut = buffer.indexOf("\n\n")) >= 0) {
3603
+ const block = buffer.slice(0, cut);
3604
+ buffer = buffer.slice(cut + 2);
3605
+ let event = "message";
3606
+ let data = "";
3607
+ for (const line of block.split("\n")) {
3608
+ if (line.startsWith("event:")) event = line.slice(6).trim();
3609
+ else if (line.startsWith("data:")) data += line.slice(5).trim();
3610
+ }
3611
+ if (event === "end") return;
3612
+ if (event === "error") throw new Error(`agent run stream error: ${data}`);
3613
+ if (event === "run-event" && data) yield JSON.parse(data);
3614
+ }
3615
+ }
3616
+ }
3617
+ // ---- client-driven runs -------------------------------------------------
3618
+ /** Take the lease of a queued client-driven run. */
3619
+ acquire(runId) {
3620
+ return this.transport.request("POST", this.base(runId, "/lease/acquire"), {});
3621
+ }
3622
+ renew(runId, fence) {
3623
+ return this.transport.request("POST", this.base(runId, "/lease/renew"), { fence });
3624
+ }
3625
+ release(runId, fence) {
3626
+ return this.transport.request("POST", this.base(runId, "/lease/release"), { fence });
3627
+ }
3628
+ /** Begin an operation; returns the active operation (its `op_id`). */
3629
+ begin(runId, fence, op) {
3630
+ return this.transport.request("POST", this.base(runId, "/operations"), { fence, ...op });
3631
+ }
3632
+ /** Record an operation's result. */
3633
+ finish(runId, fence, opId, result) {
3634
+ return this.transport.request("POST", this.base(runId, "/operations/finish"), { fence, op_id: opId, ...result });
3635
+ }
3636
+ /** Open approval/input requests and wait (`kind: "approval" | "input"`). */
3637
+ wait(runId, fence, requests) {
3638
+ return this.transport.request("POST", this.base(runId, "/wait"), { fence, requests });
3639
+ }
3640
+ /** End a client-driven run. */
3641
+ complete(runId, fence, status, outcome) {
3642
+ return this.transport.request("POST", this.base(runId, "/complete"), { fence, status, outcome });
3643
+ }
3644
+ // ── Child runs, mailbox, checkpoints, usage ──────────────────────────────
3645
+ /** Spawn a child with a typed objective; its budgets come out of this run's. */
3646
+ spawnChild(runId, options) {
3647
+ const q = options.branch ? `?branch=${encodeURIComponent(options.branch)}` : "";
3648
+ return this.transport.request("POST", this.base(runId, `/children${q}`), spawnBody(options));
3649
+ }
3650
+ /** Every child of a run: the parent's link plus the child's live status. */
3651
+ children(runId) {
3652
+ return this.transport.request("GET", this.base(runId, "/children"));
3653
+ }
3654
+ /** Inspect one child: record, events after `afterSeq`, usage, checkpoint. */
3655
+ inspectChild(runId, childId, afterSeq = 0, limit = 200) {
3656
+ const rest = `/children/${encodeURIComponent(childId)}?after_seq=${afterSeq}&limit=${limit}`;
3657
+ return this.transport.request("GET", this.base(runId, rest));
3658
+ }
3659
+ /** Message, steer, interrupt or resume a child (idempotent per `controlId`). */
3660
+ controlChild(runId, childId, action, controlId = newControlId(action.action)) {
3661
+ const rest = `/children/${encodeURIComponent(childId)}/control`;
3662
+ return this.transport.request("POST", this.base(runId, rest), { control_id: controlId, ...action });
3663
+ }
3664
+ messageChild(runId, childId, message, controlId) {
3665
+ return this.controlChild(runId, childId, { action: "message", message }, controlId);
3666
+ }
3667
+ steerChild(runId, childId, input, controlId) {
3668
+ return this.controlChild(runId, childId, { action: "steer", input }, controlId);
3669
+ }
3670
+ interruptChild(runId, childId, reason, mode = "stop", controlId) {
3671
+ return this.controlChild(runId, childId, { action: "interrupt", mode, reason }, controlId);
3672
+ }
3673
+ /** A client-driven parent waits (under its lease) for a child's hand-back. */
3674
+ waitChild(runId, childId, fence, expiresAtMs) {
3675
+ const rest = `/children/${encodeURIComponent(childId)}/wait`;
3676
+ return this.transport.request("POST", this.base(runId, rest), { fence, expires_at_ms: expiresAtMs });
3677
+ }
3678
+ /** Unacknowledged mailbox items (hand-backs and child messages). */
3679
+ mailbox(runId) {
3680
+ return this.transport.request("GET", this.base(runId, "/mailbox"));
3681
+ }
3682
+ /** Acknowledge mailbox items up to `upTo`. */
3683
+ ackMailbox(runId, upTo) {
3684
+ return this.transport.request("POST", this.base(runId, "/mailbox/ack"), { up_to: upTo });
3685
+ }
3686
+ /** A child posts a message to its parent's mailbox (idempotent per id). */
3687
+ postToParent(runId, messageId, message) {
3688
+ return this.transport.request("POST", this.base(runId, "/post-to-parent"), { message_id: messageId, message });
3689
+ }
3690
+ /** Write a structured checkpoint (compaction keeps state, not prose). */
3691
+ checkpoint(runId, options) {
3692
+ return this.transport.request("POST", this.base(runId, "/checkpoints"), checkpointBody(options));
3693
+ }
3694
+ /** Read a checkpoint (default: latest) with its structured state. */
3695
+ readCheckpoint(runId, checkpointNo) {
3696
+ return this.transport.request("GET", this.base(runId, `/checkpoints/${checkpointNo ?? "latest"}`));
3697
+ }
3698
+ /** Usage accounting: own, children, reserved, spare. */
3699
+ usage(runId) {
3700
+ return this.transport.request("GET", this.base(runId, "/usage"));
3701
+ }
3702
+ };
3703
+
3704
+ // src/agent-runs-ws.ts
3705
+ var TERMINAL = ["completed", "failed", "stopped"];
3706
+ var AgentRunsWsApi = class {
3707
+ constructor(context, sendRequest, eventHandler) {
3708
+ this.context = context;
3709
+ this.sendRequest = sendRequest;
3710
+ this.eventHandler = eventHandler;
3711
+ }
3712
+ call(type, payload) {
3713
+ return this.sendRequest(payload, type, this.context);
3714
+ }
3715
+ /** Create a run, or get back the subject's live run. */
3716
+ create(options) {
3717
+ return this.call("agent_run_create" /* AgentRunCreate */, createRunBody(options));
3718
+ }
3719
+ /** Read a run (record + effective projection). */
3720
+ get(runId) {
3721
+ return this.call("agent_run_get" /* AgentRunGet */, { run_id: runId });
3722
+ }
3723
+ /**
3724
+ * Every run about `subject` (a conversation, a document) you may see,
3725
+ * newest first — the live run, if there is one, comes first.
3726
+ */
3727
+ bySubject(subject, limit = 20) {
3728
+ return this.call("agent_run_by_subject" /* AgentRunBySubject */, { ...subjectOf(subject), limit });
3729
+ }
3730
+ /** The newest run of `subject`, or null. */
3731
+ async latest(subject) {
3732
+ const [first] = await this.bySubject(subject, 1);
3733
+ return first ?? null;
3734
+ }
3735
+ /** Your runs in one status (default "running"). */
3736
+ list(status = "running", limit = 50) {
3737
+ return this.call("agent_run_list" /* AgentRunList */, { status, limit });
3738
+ }
3739
+ /** Durable events after `afterSeq`. */
3740
+ events(runId, afterSeq = 0, limit = 500) {
3741
+ return this.call("agent_run_events" /* AgentRunEvents */, { run_id: runId, after_seq: afterSeq, limit });
3742
+ }
3743
+ /** The children a run spawned, with their current status. */
3744
+ children(runId) {
3745
+ return this.call("agent_run_children" /* AgentRunChildren */, { run_id: runId });
3746
+ }
3747
+ /** Any control. Retrying with the same `controlId` is a no-op. */
3748
+ control(runId, command, controlId = newControlId(command.command), capability) {
3749
+ return this.call("agent_run_control" /* AgentRunControl */, { run_id: runId, control_id: controlId, command, capability });
3750
+ }
3751
+ stop(runId, reason, controlId) {
3752
+ return this.control(runId, { command: "stop", reason }, controlId);
3753
+ }
3754
+ pause(runId, controlId) {
3755
+ return this.control(runId, { command: "pause" }, controlId);
3756
+ }
3757
+ resume(runId, controlId) {
3758
+ return this.control(runId, { command: "resume" }, controlId);
3759
+ }
3760
+ /** Queue input for the run's next safe boundary. */
3761
+ steer(runId, input, controlId) {
3762
+ return this.control(runId, { command: "steer", input }, controlId);
3763
+ }
3764
+ /** Decide an approval request; the digest ties it to one changeset. */
3765
+ approve(runId, requestId, subjectDigest, reject, controlId) {
3766
+ const decision = reject ? { decision: "reject", reason: reject.reason } : { decision: "approve" };
3767
+ return this.control(runId, { command: "approve", request_id: requestId, decision, subject_digest: subjectDigest }, controlId);
3768
+ }
3769
+ /** Answer an input request. */
3770
+ answer(runId, requestId, value, controlId) {
3771
+ return this.control(runId, { command: "provide_input", request_id: requestId, value }, controlId);
3772
+ }
3773
+ /**
3774
+ * Follow a run: replay after `afterSeq`, then live, until the run ends.
3775
+ *
3776
+ * Events that reach the socket before the subscription is known here are
3777
+ * not lost: the durable log is read once the listener is in place, live
3778
+ * events are held until that read is merged, and every seq is delivered
3779
+ * exactly once, in order.
3780
+ */
3781
+ async subscribe(runId, options = {}) {
3782
+ let last = options.afterSeq ?? 0;
3783
+ let ready = false;
3784
+ let closed = false;
3785
+ const held = [];
3786
+ const buffer = [];
3787
+ const waiters = [];
3788
+ let resolveDone;
3789
+ const done = new Promise((r) => resolveDone = r);
3790
+ const close = (ended) => {
3791
+ if (closed) return;
3792
+ closed = true;
3793
+ if (ended) options.onEnd?.(last);
3794
+ for (const w of waiters.splice(0)) w({ value: void 0, done: true });
3795
+ resolveDone();
3796
+ };
3797
+ const deliver = (ev) => {
3798
+ if (closed || ev.seq <= last) return;
3799
+ last = ev.seq;
3800
+ options.onEvent?.(ev);
3801
+ const w = waiters.shift();
3802
+ if (w) w({ value: ev, done: false });
3803
+ else buffer.push(ev);
3804
+ };
3805
+ const listener = (message) => {
3806
+ if (message.event_type === "agent_run_end") {
3807
+ if (ready) close(true);
3808
+ else held.push({ seq: Number.MAX_SAFE_INTEGER });
3809
+ return;
3810
+ }
3811
+ const ev = message.payload;
3812
+ if (ready) deliver(ev);
3813
+ else held.push(ev);
3814
+ };
3815
+ const response = await this.call("agent_run_subscribe" /* AgentRunSubscribe */, {
3816
+ run_id: runId,
3817
+ after_seq: last
3818
+ });
3819
+ const subscriptionId = response.subscription_id;
3820
+ this.eventHandler.addFlowEventListener(subscriptionId, listener);
3821
+ const unsubscribe = async () => {
3822
+ this.eventHandler.removeFlowEventListener(subscriptionId);
3823
+ close(false);
3824
+ await this.call("agent_run_unsubscribe" /* AgentRunUnsubscribe */, { subscription_id: subscriptionId }).catch(() => void 0);
3825
+ };
3826
+ options.signal?.addEventListener("abort", () => void unsubscribe(), { once: true });
3827
+ for (; ; ) {
3828
+ const page = await this.events(runId, last, 500);
3829
+ page.forEach(deliver);
3830
+ if (page.length < 500) break;
3831
+ }
3832
+ ready = true;
3833
+ const endSeen = held.some((e) => e.seq === Number.MAX_SAFE_INTEGER);
3834
+ held.filter((e) => e.seq !== Number.MAX_SAFE_INTEGER).sort((a, b) => a.seq - b.seq).forEach(deliver);
3835
+ if (endSeen) close(true);
3836
+ else {
3837
+ const view = await this.get(runId).catch(() => null);
3838
+ const finalized = !view?.run?.domain || view.run.domain.finalized !== false;
3839
+ if (view && TERMINAL.includes(view.status) && finalized) {
3840
+ const tail = await this.events(runId, last, 500).catch(() => []);
3841
+ tail.forEach(deliver);
3842
+ this.eventHandler.removeFlowEventListener(subscriptionId);
3843
+ close(true);
3844
+ }
3845
+ }
3846
+ void done.then(() => this.eventHandler.removeFlowEventListener(subscriptionId));
3847
+ return {
3848
+ get lastSeq() {
3849
+ return last;
3850
+ },
3851
+ done,
3852
+ unsubscribe,
3853
+ [Symbol.asyncIterator]() {
3854
+ return {
3855
+ next: () => {
3856
+ const ev = buffer.shift();
3857
+ if (ev) return Promise.resolve({ value: ev, done: false });
3858
+ if (closed) return Promise.resolve({ value: void 0, done: true });
3859
+ return new Promise((r) => waiters.push(r));
3860
+ },
3861
+ return: async () => {
3862
+ await unsubscribe();
3863
+ return { value: void 0, done: true };
3864
+ }
3865
+ };
3866
+ }
3867
+ };
3868
+ }
3869
+ };
3870
+
3440
3871
  // src/functions-api.ts
3441
3872
  var FunctionsApi = class {
3442
3873
  constructor(repository, context, sendRequest) {
@@ -4062,7 +4493,8 @@ function normalizeHomePath(home) {
4062
4493
  // src/conversations.ts
4063
4494
  var DEFAULT_SEND_MESSAGE_INACTIVITY_TIMEOUT_MS = 12e4;
4064
4495
  var ConversationManager = class {
4065
- constructor(baseUrl, repository, authManager, options = {}, executeSql) {
4496
+ constructor(baseUrl, repository, authManager, options = {}, executeSql, visitor) {
4497
+ this.visitor = visitor;
4066
4498
  this.baseUrl = baseUrl.replace(/\/$/, "");
4067
4499
  this.repository = repository;
4068
4500
  this.authManager = authManager;
@@ -4183,6 +4615,45 @@ var ConversationManager = class {
4183
4615
  ]
4184
4616
  };
4185
4617
  }
4618
+ /**
4619
+ * Start (or resume) an ANONYMOUS conversation with an agent — a public
4620
+ * website's chat, without login.
4621
+ *
4622
+ * Works on an anonymous connection only, and only with an agent that allows
4623
+ * anonymous visitors (`anonymous.enabled: true` on its raisin:AIAgent). The
4624
+ * server keeps the conversation in an ephemeral visitor session that only
4625
+ * this browser session can read; the session secret is kept in
4626
+ * sessionStorage (override with `options.store`), so a reload continues the
4627
+ * same conversation. Then use `sendMessage`, `getMessages`, `subscribe` and
4628
+ * `ConversationStore` / `useConversation` exactly as for a signed-in user.
4629
+ *
4630
+ * @example
4631
+ * ```typescript
4632
+ * const convo = await db.conversations.startAnonymous('/agents/website-assistant');
4633
+ * for await (const ev of db.conversations.sendMessage(convo.conversationPath, 'Hello')) {
4634
+ * if (ev.type === 'text_chunk') append(ev.text);
4635
+ * if (ev.type === 'failed') showLimit(ev.code); // e.g. RATE_LIMITED, LIMIT_REACHED
4636
+ * }
4637
+ * ```
4638
+ */
4639
+ async startAnonymous(agent, options) {
4640
+ if (!this.visitor) {
4641
+ throw new Error("Anonymous chat needs a WebSocket database: use client.database(repo).");
4642
+ }
4643
+ return this.visitor.start(this.normalizeAgentPath(agent), options);
4644
+ }
4645
+ /** Forget the stored anonymous session for `agent` (the next start begins a new one). */
4646
+ forgetAnonymous(agent, options) {
4647
+ this.visitor?.forget(this.normalizeAgentPath(agent), options);
4648
+ }
4649
+ /** Whether this tab remembers an anonymous conversation with `agent`. */
4650
+ hasStoredAnonymous(agent, options) {
4651
+ return this.visitor?.remembers(this.normalizeAgentPath(agent), options) ?? false;
4652
+ }
4653
+ /** Whether `conversationPath` is an anonymous conversation of this client. */
4654
+ isAnonymous(conversationPath) {
4655
+ return this.visitor?.isAnonymous(conversationPath) ?? false;
4656
+ }
4186
4657
  /**
4187
4658
  * Open an existing conversation by path.
4188
4659
  * Returns null if not found.
@@ -4228,6 +4699,7 @@ var ConversationManager = class {
4228
4699
  * Mark a conversation as read by setting unread_count to 0.
4229
4700
  */
4230
4701
  async markAsRead(conversationPath) {
4702
+ if (this.isAnonymous(conversationPath)) return;
4231
4703
  const workspace = "raisin:access_control";
4232
4704
  await this.sqlQuery(
4233
4705
  `UPDATE '${workspace}' SET properties = jsonb_set(properties, '{unread_count}', '0'::jsonb) WHERE path = $1 AND node_type = 'raisin:Conversation'`,
@@ -4238,6 +4710,7 @@ var ConversationManager = class {
4238
4710
  * Mark a single message as read by the current user.
4239
4711
  */
4240
4712
  async markMessageAsRead(messagePath) {
4713
+ if (messagePath.startsWith("/visitors/")) return;
4241
4714
  const workspace = "raisin:access_control";
4242
4715
  const now = (/* @__PURE__ */ new Date()).toISOString();
4243
4716
  await this.sqlQuery(
@@ -4262,6 +4735,18 @@ var ConversationManager = class {
4262
4735
  */
4263
4736
  async *sendMessage(conversationPath, content, options) {
4264
4737
  const shouldStream = options?.stream !== false;
4738
+ if (this.visitor?.isAnonymous(conversationPath)) {
4739
+ if (!shouldStream) {
4740
+ await this.visitor.post(conversationPath, content);
4741
+ yield { type: "waiting", timestamp: (/* @__PURE__ */ new Date()).toISOString() };
4742
+ return;
4743
+ }
4744
+ yield* this.visitor.stream(conversationPath, content, {
4745
+ signal: options?.signal,
4746
+ inactivityTimeoutMs: options?.inactivityTimeoutMs ?? DEFAULT_SEND_MESSAGE_INACTIVITY_TIMEOUT_MS
4747
+ });
4748
+ return;
4749
+ }
4265
4750
  logger.debug("[ConversationManager] Starting SSE stream for message send");
4266
4751
  if (!shouldStream) {
4267
4752
  await this.createUserMessage(conversationPath, content);
@@ -4349,6 +4834,10 @@ var ConversationManager = class {
4349
4834
  */
4350
4835
  async createUserMessage(conversationPath, content) {
4351
4836
  logger.debug("[ConversationManager] Creating user message", { path: conversationPath });
4837
+ if (this.visitor?.isAnonymous(conversationPath)) {
4838
+ await this.visitor.post(conversationPath, content);
4839
+ return;
4840
+ }
4352
4841
  const workspace = "raisin:access_control";
4353
4842
  const properties = await this.loadConversationProperties(conversationPath, workspace);
4354
4843
  const flowInstanceId = typeof properties?.flow_instance_id === "string" ? properties.flow_instance_id.trim() : "";
@@ -4400,6 +4889,12 @@ var ConversationManager = class {
4400
4889
  * initiated messages, etc.). Auto-reconnects on disconnect.
4401
4890
  */
4402
4891
  subscribe(conversationPath, onEvent, options) {
4892
+ if (this.visitor?.isAnonymous(conversationPath)) {
4893
+ const stop = this.visitor.listen(conversationPath, onEvent);
4894
+ options?.signal?.addEventListener("abort", stop, { once: true });
4895
+ return { unsubscribe: stop, waitUntilConnected: async () => {
4896
+ } };
4897
+ }
4403
4898
  logger.info("[ConversationManager] Subscribing to SSE", { path: conversationPath });
4404
4899
  const sseUrl = `${this.baseUrl}/api/conversations/${this.repository}/events`;
4405
4900
  const headers = {};
@@ -4839,6 +5334,272 @@ var ConversationManager = class {
4839
5334
  }
4840
5335
  };
4841
5336
 
5337
+ // src/visitor-chat.ts
5338
+ function defaultVisitorSessionStore() {
5339
+ const memory = /* @__PURE__ */ new Map();
5340
+ const storage = () => {
5341
+ try {
5342
+ return typeof sessionStorage !== "undefined" ? sessionStorage : null;
5343
+ } catch {
5344
+ return null;
5345
+ }
5346
+ };
5347
+ return {
5348
+ get(key) {
5349
+ try {
5350
+ return storage()?.getItem(key) ?? memory.get(key) ?? null;
5351
+ } catch {
5352
+ return memory.get(key) ?? null;
5353
+ }
5354
+ },
5355
+ set(key, value) {
5356
+ memory.set(key, value);
5357
+ try {
5358
+ storage()?.setItem(key, value);
5359
+ } catch {
5360
+ }
5361
+ },
5362
+ remove(key) {
5363
+ memory.delete(key);
5364
+ try {
5365
+ storage()?.removeItem(key);
5366
+ } catch {
5367
+ }
5368
+ }
5369
+ };
5370
+ }
5371
+ var VisitorChatError = class extends Error {
5372
+ constructor(message, code) {
5373
+ super(message);
5374
+ this.name = "VisitorChatError";
5375
+ this.code = code;
5376
+ }
5377
+ };
5378
+ var REBIND_CODES = /* @__PURE__ */ new Set(["NO_SESSION", "UNKNOWN_CONVERSATION"]);
5379
+ function asError(err) {
5380
+ const e = err;
5381
+ return new VisitorChatError(e?.message ?? String(err), e?.code ?? "UNAVAILABLE");
5382
+ }
5383
+ var VisitorChat = class {
5384
+ constructor(repository, send, events, onReconnected) {
5385
+ this.repository = repository;
5386
+ this.send = send;
5387
+ this.events = events;
5388
+ this.byPath = /* @__PURE__ */ new Map();
5389
+ this.token = null;
5390
+ onReconnected?.(() => {
5391
+ void this.rebindAll();
5392
+ });
5393
+ }
5394
+ /** Whether `conversationPath` is a visitor conversation started here. */
5395
+ isAnonymous(conversationPath) {
5396
+ return this.byPath.has(conversationPath);
5397
+ }
5398
+ storeOf(options) {
5399
+ if (options.store === false) return null;
5400
+ return options.store ?? defaultVisitorSessionStore();
5401
+ }
5402
+ keyOf(agent, options) {
5403
+ return options.storageKey ?? `raisindb:visitor:${this.repository}:${agent}`;
5404
+ }
5405
+ /** Start (or resume) a visitor conversation with `agent` (`/agents/<name>`). */
5406
+ async start(agent, options = {}) {
5407
+ const store = this.storeOf(options);
5408
+ const key = this.keyOf(agent, options);
5409
+ const sessionToken = options.sessionToken ?? this.token ?? store?.get(`${key}:session`) ?? void 0;
5410
+ const conversationId = options.newConversation ? void 0 : options.conversationId ?? store?.get(`${key}:conversation`) ?? void 0;
5411
+ let res;
5412
+ try {
5413
+ res = await this.send(
5414
+ { agent, session_token: sessionToken, conversation_id: conversationId },
5415
+ "visitor_chat_start"
5416
+ );
5417
+ } catch (err) {
5418
+ const e = asError(err);
5419
+ if ((conversationId || sessionToken) && !options.conversationId && !options.sessionToken && ["UNKNOWN_CONVERSATION", "INVALID_CONVERSATION", "SESSION_EXPIRED", "SESSION_MISMATCH"].includes(e.code)) {
5420
+ store?.remove(`${key}:conversation`);
5421
+ if (e.code !== "UNKNOWN_CONVERSATION" && e.code !== "INVALID_CONVERSATION") {
5422
+ store?.remove(`${key}:session`);
5423
+ this.token = null;
5424
+ }
5425
+ return this.start(agent, { ...options, newConversation: true });
5426
+ }
5427
+ throw e;
5428
+ }
5429
+ const token = res.session_token ?? sessionToken ?? this.token;
5430
+ if (!token) throw new VisitorChatError("the server returned no session", "UNAVAILABLE");
5431
+ this.token = token;
5432
+ store?.set(`${key}:session`, token);
5433
+ store?.set(`${key}:conversation`, res.conversation_id);
5434
+ const path = res.conversation_path;
5435
+ let entry = this.byPath.get(path);
5436
+ if (!entry) {
5437
+ entry = {
5438
+ agent: res.agent,
5439
+ conversationId: res.conversation_id,
5440
+ subscriptionId: res.subscription_id,
5441
+ listeners: /* @__PURE__ */ new Set(),
5442
+ options
5443
+ };
5444
+ this.byPath.set(path, entry);
5445
+ }
5446
+ this.route(entry);
5447
+ const now = (/* @__PURE__ */ new Date()).toISOString();
5448
+ return {
5449
+ id: res.conversation_id,
5450
+ type: "ai_chat",
5451
+ agentRef: res.agent,
5452
+ conversationPath: path,
5453
+ conversationWorkspace: res.conversation_workspace,
5454
+ anonymous: true,
5455
+ conversationId: res.conversation_id,
5456
+ sessionToken: token,
5457
+ limits: res.limits,
5458
+ initialEvents: [{ type: "waiting", timestamp: now }]
5459
+ };
5460
+ }
5461
+ /** Route the server's forwarded events for this conversation to its listeners. */
5462
+ route(entry) {
5463
+ this.events.removeFlowEventListener(entry.subscriptionId);
5464
+ this.events.addFlowEventListener(entry.subscriptionId, (msg) => {
5465
+ const event = msg.payload;
5466
+ if (!event || typeof event.type !== "string") return;
5467
+ for (const listener of entry.listeners) {
5468
+ try {
5469
+ listener(event);
5470
+ } catch (err) {
5471
+ logger.error("[VisitorChat] listener failed", err);
5472
+ }
5473
+ }
5474
+ });
5475
+ }
5476
+ /** Re-prove the session on a new connection, for every conversation started here. */
5477
+ async rebindAll() {
5478
+ for (const entry of this.byPath.values()) {
5479
+ try {
5480
+ await this.send(
5481
+ { agent: entry.agent, session_token: this.token, conversation_id: entry.conversationId },
5482
+ "visitor_chat_start"
5483
+ );
5484
+ this.route(entry);
5485
+ } catch (err) {
5486
+ logger.warn("[VisitorChat] could not resume a conversation after reconnect", err);
5487
+ }
5488
+ }
5489
+ }
5490
+ /** Listen to a visitor conversation's events. Returns an unsubscribe function. */
5491
+ listen(conversationPath, listener) {
5492
+ const entry = this.require(conversationPath);
5493
+ entry.listeners.add(listener);
5494
+ return () => {
5495
+ entry.listeners.delete(listener);
5496
+ };
5497
+ }
5498
+ require(conversationPath) {
5499
+ const entry = this.byPath.get(conversationPath);
5500
+ if (!entry) {
5501
+ throw new VisitorChatError(
5502
+ "not a visitor conversation of this client; call startAnonymous first",
5503
+ "UNKNOWN_CONVERSATION"
5504
+ );
5505
+ }
5506
+ return entry;
5507
+ }
5508
+ /** Make sure this connection is bound (after a reconnect nothing else may read the home). */
5509
+ async ensureBound(conversationPath) {
5510
+ const entry = this.require(conversationPath);
5511
+ await this.send(
5512
+ { agent: entry.agent, session_token: this.token, conversation_id: entry.conversationId },
5513
+ "visitor_chat_start"
5514
+ ).catch((err) => {
5515
+ throw asError(err);
5516
+ });
5517
+ }
5518
+ /** Send one visitor message. Events arrive through {@link listen}. */
5519
+ async post(conversationPath, text) {
5520
+ const entry = this.require(conversationPath);
5521
+ const once = async () => await this.send(
5522
+ { conversation_id: entry.conversationId, text },
5523
+ "visitor_chat_send"
5524
+ );
5525
+ try {
5526
+ const res = await once();
5527
+ return { messageId: res.message_id, messagesLeft: res.messages_left };
5528
+ } catch (err) {
5529
+ const e = asError(err);
5530
+ if (!REBIND_CODES.has(e.code)) throw e;
5531
+ await this.ensureBound(conversationPath);
5532
+ this.route(entry);
5533
+ const res = await once().catch((again) => {
5534
+ throw asError(again);
5535
+ });
5536
+ return { messageId: res.message_id, messagesLeft: res.messages_left };
5537
+ }
5538
+ }
5539
+ /**
5540
+ * Send one visitor message and stream the turn: `text_chunk`,
5541
+ * `tool_call_started`, `tool_call_completed`, … until `done`. A refusal
5542
+ * ends the stream with `failed` (its `code` says why). No event for
5543
+ * `inactivityTimeoutMs` ends it with a synthetic `waiting`.
5544
+ */
5545
+ async *stream(conversationPath, text, options = {}) {
5546
+ const queue = [];
5547
+ let wake = null;
5548
+ const push = (event) => {
5549
+ queue.push(event);
5550
+ wake?.();
5551
+ };
5552
+ const stop = this.listen(conversationPath, push);
5553
+ const onAbort = () => push({ type: "failed", error: "aborted", code: "ABORTED", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
5554
+ options.signal?.addEventListener("abort", onAbort, { once: true });
5555
+ const timeout = options.inactivityTimeoutMs ?? 12e4;
5556
+ try {
5557
+ try {
5558
+ await this.post(conversationPath, text);
5559
+ } catch (err) {
5560
+ const e = asError(err);
5561
+ yield { type: "failed", error: e.message, code: e.code, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
5562
+ return;
5563
+ }
5564
+ for (; ; ) {
5565
+ if (!queue.length) {
5566
+ const idle = await new Promise((resolve) => {
5567
+ const timer = timeout > 0 ? setTimeout(() => resolve(true), timeout) : null;
5568
+ wake = () => {
5569
+ if (timer) clearTimeout(timer);
5570
+ resolve(false);
5571
+ };
5572
+ });
5573
+ wake = null;
5574
+ if (idle && !queue.length) {
5575
+ yield { type: "waiting", timestamp: (/* @__PURE__ */ new Date()).toISOString() };
5576
+ return;
5577
+ }
5578
+ }
5579
+ const event = queue.shift();
5580
+ yield event;
5581
+ if (event.type === "done" || event.type === "failed" || event.type === "waiting") return;
5582
+ }
5583
+ } finally {
5584
+ stop();
5585
+ options.signal?.removeEventListener("abort", onAbort);
5586
+ }
5587
+ }
5588
+ /** Whether the store remembers a conversation with `agent`. */
5589
+ remembers(agent, options = {}) {
5590
+ const store = this.storeOf(options);
5591
+ return !!store?.get(`${this.keyOf(agent, options)}:conversation`);
5592
+ }
5593
+ /** Forget the stored session (e.g. a "new chat" button that should start a new session). */
5594
+ forget(agent, options = {}) {
5595
+ const store = this.storeOf(options);
5596
+ const key = this.keyOf(agent, options);
5597
+ store?.remove(`${key}:session`);
5598
+ store?.remove(`${key}:conversation`);
5599
+ this.token = null;
5600
+ }
5601
+ };
5602
+
4842
5603
  // src/flow-client.ts
4843
5604
  var FlowClient = class _FlowClient {
4844
5605
  /**
@@ -5615,6 +6376,16 @@ var Database = class _Database {
5615
6376
  }
5616
6377
  return this._flowsApi;
5617
6378
  }
6379
+ /**
6380
+ * Durable agent runs over this WebSocket connection: find a subject's run,
6381
+ * follow it live (gap-free, resumable), control it, list its children.
6382
+ */
6383
+ runs() {
6384
+ if (!this._runsApi) {
6385
+ this._runsApi = new AgentRunsWsApi(this._context, this.sendRequest, this.eventHandler);
6386
+ }
6387
+ return this._runsApi;
6388
+ }
5618
6389
  /**
5619
6390
  * Get FunctionsApi for invoking server-side functions via WebSocket
5620
6391
  */
@@ -5721,7 +6492,13 @@ var Database = class _Database {
5721
6492
  this.repository,
5722
6493
  this.httpOptions.authManager,
5723
6494
  {},
5724
- (query, params) => this.executeSql(query, params)
6495
+ (query, params) => this.executeSql(query, params),
6496
+ new VisitorChat(
6497
+ this.repository,
6498
+ (payload, requestType) => this.sendRequest(payload, requestType),
6499
+ this.eventHandler,
6500
+ this.httpOptions.onReconnected
6501
+ )
5725
6502
  );
5726
6503
  }
5727
6504
  return this._conversationManager;
@@ -7351,6 +8128,82 @@ function readTokensFromFragment(hashOrUrl) {
7351
8128
  return { accessToken, refreshToken: params.get("refresh_token") };
7352
8129
  }
7353
8130
 
8131
+ // src/node-dev.ts
8132
+ var NodeDevApi = class {
8133
+ constructor(repository, transport) {
8134
+ this.repository = repository;
8135
+ this.transport = transport;
8136
+ }
8137
+ /** Call any method by name (the typed helpers below all use this). */
8138
+ call(method, request) {
8139
+ const branch = typeof request.branch === "string" ? `?branch=${encodeURIComponent(request.branch)}` : "";
8140
+ return this.transport.request(
8141
+ "POST",
8142
+ `/api/node-dev/${encodeURIComponent(this.repository)}/${method}${branch}`,
8143
+ request
8144
+ );
8145
+ }
8146
+ changeset(o) {
8147
+ const { idempotencyKey, ...rest } = o;
8148
+ return { ...rest, idempotency_key: idempotencyKey };
8149
+ }
8150
+ stat(target, o = {}) {
8151
+ return this.call("stat", { ...o, target });
8152
+ }
8153
+ read(target, o = {}) {
8154
+ return this.call("read", { ...o, target });
8155
+ }
8156
+ list(target, o = {}) {
8157
+ return this.call("list", { ...o, target });
8158
+ }
8159
+ diff(target, from, to, o = {}) {
8160
+ return this.call("diff", { ...o, target, from, to });
8161
+ }
8162
+ /** Changes inside the roots after `since` (a cursor from a previous call). */
8163
+ watch(since, o = {}) {
8164
+ return this.call("watch", { ...o, since });
8165
+ }
8166
+ dryRun(o) {
8167
+ return this.call("dry_run", this.changeset(o));
8168
+ }
8169
+ propose(o) {
8170
+ return this.call(
8171
+ "propose",
8172
+ this.changeset(o)
8173
+ );
8174
+ }
8175
+ getChangeset(changesetId, o = {}) {
8176
+ return this.call("get_changeset", { ...o, changeset_id: changesetId });
8177
+ }
8178
+ listChangesets(o = {}) {
8179
+ return this.call("list_changesets", { ...o });
8180
+ }
8181
+ /** Commit; pass the reviewed digest to bind the commit to that approval. */
8182
+ commit(changesetId, expectedDigest, o = {}) {
8183
+ return this.call("commit", { ...o, changeset_id: changesetId, expected_digest: expectedDigest });
8184
+ }
8185
+ discard(changesetId, o = {}) {
8186
+ return this.call("discard", { ...o, changeset_id: changesetId });
8187
+ }
8188
+ /** Propose and commit in one call. */
8189
+ apply(o) {
8190
+ return this.call("apply", this.changeset(o));
8191
+ }
8192
+ forkBranch(name, o = {}) {
8193
+ return this.call("fork_branch", { ...o, name });
8194
+ }
8195
+ diffBranch(base = "main", o = {}) {
8196
+ return this.call("diff_branch", { ...o, base });
8197
+ }
8198
+ mergeBranch(target, o = {}) {
8199
+ const { dryRun, ...rest } = o;
8200
+ return this.call("merge_branch", { ...rest, target, dry_run: dryRun });
8201
+ }
8202
+ discardBranch(o = {}) {
8203
+ return this.call("discard_branch", { ...o });
8204
+ }
8205
+ };
8206
+
7354
8207
  // src/http-client.ts
7355
8208
  var RaisinHttpClient = class extends import_events3.EventEmitter {
7356
8209
  constructor(baseUrl, options = {}) {
@@ -8076,6 +8929,33 @@ var RaisinHttpClient = class extends import_events3.EventEmitter {
8076
8929
  * @param input - Input data passed to the function
8077
8930
  * @returns Execution ID and job ID for tracking
8078
8931
  */
8932
+ /**
8933
+ * Durable agent runs of `repository`: create, read, control, stream, and
8934
+ * drive them directly (see {@link AgentRunsApi}).
8935
+ */
8936
+ agentRuns(repository) {
8937
+ return new AgentRunsApi(repository, {
8938
+ request: async (method, path, body) => (await this.request({ method, path, body })).data,
8939
+ url: (path) => `${this.baseUrl}${path}`,
8940
+ headers: () => {
8941
+ const token = this.authManager.getAccessToken();
8942
+ const headers = {};
8943
+ if (token) headers["Authorization"] = `Bearer ${token}`;
8944
+ return headers;
8945
+ },
8946
+ fetch: this.fetchImpl
8947
+ });
8948
+ }
8949
+ /**
8950
+ * The node-development surface of `repository`: typed reads, atomic
8951
+ * changesets with review and idempotency, branch worktrees (see
8952
+ * {@link NodeDevApi}).
8953
+ */
8954
+ nodeDev(repository) {
8955
+ return new NodeDevApi(repository, {
8956
+ request: async (method, path, body) => (await this.request({ method, path, body })).data
8957
+ });
8958
+ }
8079
8959
  async invokeFunction(repository, functionName, input, options) {
8080
8960
  const requestTimeoutMs = options?.requestTimeoutMs ?? this.options.requestTimeout;
8081
8961
  let waitTimeoutMs = options?.waitTimeoutMs;
@@ -8279,6 +9159,14 @@ var HttpDatabase = class _HttpDatabase {
8279
9159
  /**
8280
9160
  * Get FunctionsApi for invoking server-side functions via HTTP
8281
9161
  */
9162
+ /** Durable agent runs of this repository. */
9163
+ agentRuns() {
9164
+ return this.client.agentRuns(this.repository);
9165
+ }
9166
+ /** The node-development surface of this repository. */
9167
+ nodeDev() {
9168
+ return this.client.nodeDev(this.repository);
9169
+ }
8282
9170
  functions() {
8283
9171
  return new HttpFunctionsApi(
8284
9172
  this.repository,
@@ -9477,7 +10365,11 @@ var _RaisinClient = class _RaisinClient extends import_events4.EventEmitter {
9477
10365
  void 0,
9478
10366
  () => this.getUploadManager(),
9479
10367
  (options) => this.signAssetUrl(options),
9480
- { httpBaseUrl: this._httpBaseUrl, authManager: this.authManager }
10368
+ {
10369
+ httpBaseUrl: this._httpBaseUrl,
10370
+ authManager: this.authManager,
10371
+ onReconnected: (callback) => this.onReconnected(callback)
10372
+ }
9481
10373
  );
9482
10374
  }
9483
10375
  /**
@@ -10857,6 +11749,34 @@ var ConversationStore = class {
10857
11749
  this._watchdogIntervalMs = options.watchdogIntervalMs ?? 3e4;
10858
11750
  if (this._conversationPath) {
10859
11751
  this.ensureSubscription();
11752
+ } else if (this.createOptions?.anonymous) {
11753
+ void this.resumeAnonymous();
11754
+ }
11755
+ }
11756
+ anonymousOptions() {
11757
+ const a = this.createOptions?.anonymous;
11758
+ if (!a) return null;
11759
+ return a === true ? {} : a;
11760
+ }
11761
+ /**
11762
+ * Resume the visitor conversation this tab already has (the session secret
11763
+ * and conversation id live in sessionStorage), and load its history. A tab
11764
+ * without one starts nothing until the first message.
11765
+ */
11766
+ async resumeAnonymous() {
11767
+ const opts = this.anonymousOptions();
11768
+ if (!opts || !this.createOptions || this._conversationPath) return;
11769
+ const agent = this.createOptions.participant;
11770
+ try {
11771
+ if (!this.manager.hasStoredAnonymous(agent, opts)) return;
11772
+ const convo = await this.manager.startAnonymous(agent, opts);
11773
+ if (this._conversationPath) return;
11774
+ this._conversationPath = convo.conversationPath;
11775
+ this._conversationType = convo.type;
11776
+ this.ensureSubscription();
11777
+ await this.loadMessages();
11778
+ } catch (err) {
11779
+ logger.debug("[ConversationStore] No visitor conversation to resume", err);
10860
11780
  }
10861
11781
  }
10862
11782
  // ==========================================================================
@@ -10911,7 +11831,8 @@ var ConversationStore = class {
10911
11831
  throw new Error("No conversationPath and no createOptions provided");
10912
11832
  }
10913
11833
  try {
10914
- const convo = await this.manager.create({
11834
+ const anonymous = this.anonymousOptions();
11835
+ const convo = anonymous ? await this.manager.startAnonymous(this.createOptions.participant, anonymous) : await this.manager.create({
10915
11836
  participant: this.createOptions.participant,
10916
11837
  input: this.createOptions.input
10917
11838
  });
@@ -12727,6 +13648,8 @@ function createRaisinVue(vue) {
12727
13648
  }
12728
13649
  // Annotate the CommonJS export names for ESM import in node:
12729
13650
  0 && (module.exports = {
13651
+ AgentRunsApi,
13652
+ AgentRunsWsApi,
12730
13653
  AllNodeEventTypes,
12731
13654
  Archetypes,
12732
13655
  AuthManager,
@@ -12767,6 +13690,7 @@ function createRaisinVue(vue) {
12767
13690
  McpClient,
12768
13691
  MemoryTokenStorage,
12769
13692
  NodeBuilder,
13693
+ NodeDevApi,
12770
13694
  NodeEventType,
12771
13695
  NodeFileSource,
12772
13696
  NodeHelpers,
@@ -12796,6 +13720,7 @@ function createRaisinVue(vue) {
12796
13720
  UploadErrorCode,
12797
13721
  UploadManager,
12798
13722
  Uploader,
13723
+ VisitorChatError,
12799
13724
  WorkspaceClient,
12800
13725
  WorkspaceManager,
12801
13726
  calculateChunkCount,
@@ -12817,6 +13742,7 @@ function createRaisinVue(vue) {
12817
13742
  createSqlHandler,
12818
13743
  createSubscriptionAdapter,
12819
13744
  decodeMessage,
13745
+ defaultVisitorSessionStore,
12820
13746
  encodeMessage,
12821
13747
  getChunkRange,
12822
13748
  getContentType,
@@ -12834,12 +13760,14 @@ function createRaisinVue(vue) {
12834
13760
  isTerminalEvent,
12835
13761
  isWebSocketClient,
12836
13762
  logger,
13763
+ newControlId,
12837
13764
  normalizeHomePath,
12838
13765
  projectPlansFromMessages,
12839
13766
  readTokensFromFragment,
12840
13767
  rowsToObjects,
12841
13768
  setLogLevel,
12842
13769
  sleep,
13770
+ subjectOf,
12843
13771
  useConversation,
12844
13772
  useConversationList,
12845
13773
  useFlow,