@iota-uz/sdk 0.4.34 → 0.4.36

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.
@@ -3015,7 +3015,10 @@ var ChatMachine = class {
3015
3015
  )
3016
3016
  });
3017
3017
  const normalized = normalizeRPCError(err, "Failed to send message");
3018
- this._updateInput({ inputError: normalized.userMessage });
3018
+ this._updateInput({
3019
+ message: content,
3020
+ inputError: normalized.userMessage
3021
+ });
3019
3022
  this._updateMessaging({
3020
3023
  streamError: normalized.userMessage,
3021
3024
  streamErrorRetryable: normalized.retryable
@@ -12689,7 +12692,9 @@ function ModelSelector() {
12689
12692
  }, [currentModel, models, setModel]);
12690
12693
  React.useEffect(() => {
12691
12694
  const handler = (e) => {
12692
- if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "m") {
12695
+ const isModifierPressed = e.metaKey || e.ctrlKey;
12696
+ const isShortcutKey = e.code === "KeyM" || e.key.toLowerCase() === "m";
12697
+ if (isModifierPressed && e.shiftKey && !e.altKey && isShortcutKey) {
12693
12698
  e.preventDefault();
12694
12699
  rotateModel();
12695
12700
  }
@@ -17065,6 +17070,140 @@ function useStreaming2(options = {}) {
17065
17070
  reset
17066
17071
  };
17067
17072
  }
17073
+ var TERMINAL = /* @__PURE__ */ new Set([
17074
+ "completed",
17075
+ "cancelled",
17076
+ "failed"
17077
+ ]);
17078
+ function useActiveRuns(dataSource, options = {}) {
17079
+ const [runs, setRuns] = React.useState({});
17080
+ const [ready, setReady] = React.useState(false);
17081
+ const onErrorRef = React.useRef(options.onError);
17082
+ onErrorRef.current = options.onError;
17083
+ const enabled = options.enabled ?? true;
17084
+ const retainTerminalMs = options.retainTerminalMs ?? 0;
17085
+ const emptyStateTimeoutMs = options.emptyStateTimeoutMs ?? 250;
17086
+ React.useEffect(() => {
17087
+ if (!enabled) {
17088
+ return;
17089
+ }
17090
+ if (!dataSource.subscribeActiveRuns) {
17091
+ return;
17092
+ }
17093
+ const controller = new AbortController();
17094
+ let stagingTimer;
17095
+ const staging = {};
17096
+ let sawSnapshotRow = false;
17097
+ const pendingTerminalTimers = /* @__PURE__ */ new Map();
17098
+ const flushSnapshot = () => {
17099
+ setRuns((prev) => ({ ...prev, ...staging }));
17100
+ setReady(true);
17101
+ stagingTimer = void 0;
17102
+ };
17103
+ const subscription = dataSource.subscribeActiveRuns({
17104
+ signal: controller.signal,
17105
+ onError: (evt) => onErrorRef.current?.(evt),
17106
+ onEvent: (evt) => {
17107
+ if (evt.event === "snapshot") {
17108
+ sawSnapshotRow = true;
17109
+ const pending2 = pendingTerminalTimers.get(evt.sessionId);
17110
+ if (pending2 !== void 0) {
17111
+ clearTimeout(pending2);
17112
+ pendingTerminalTimers.delete(evt.sessionId);
17113
+ }
17114
+ staging[evt.sessionId] = {
17115
+ runId: evt.runId,
17116
+ status: evt.status,
17117
+ updatedAt: evt.updatedAt
17118
+ };
17119
+ if (stagingTimer === void 0) {
17120
+ stagingTimer = setTimeout(flushSnapshot, 16);
17121
+ }
17122
+ return;
17123
+ }
17124
+ if (TERMINAL.has(evt.status)) {
17125
+ if (retainTerminalMs <= 0) {
17126
+ setRuns((prev) => {
17127
+ if (!(evt.sessionId in prev)) {
17128
+ return prev;
17129
+ }
17130
+ const next = { ...prev };
17131
+ delete next[evt.sessionId];
17132
+ return next;
17133
+ });
17134
+ return;
17135
+ }
17136
+ setRuns((prev) => ({
17137
+ ...prev,
17138
+ [evt.sessionId]: {
17139
+ runId: evt.runId,
17140
+ status: evt.status,
17141
+ updatedAt: evt.updatedAt
17142
+ }
17143
+ }));
17144
+ const existing = pendingTerminalTimers.get(evt.sessionId);
17145
+ if (existing !== void 0) {
17146
+ clearTimeout(existing);
17147
+ }
17148
+ const handle = setTimeout(() => {
17149
+ pendingTerminalTimers.delete(evt.sessionId);
17150
+ setRuns((prev) => {
17151
+ if (!(evt.sessionId in prev)) {
17152
+ return prev;
17153
+ }
17154
+ const next = { ...prev };
17155
+ delete next[evt.sessionId];
17156
+ return next;
17157
+ });
17158
+ }, retainTerminalMs);
17159
+ pendingTerminalTimers.set(evt.sessionId, handle);
17160
+ return;
17161
+ }
17162
+ const pending = pendingTerminalTimers.get(evt.sessionId);
17163
+ if (pending !== void 0) {
17164
+ clearTimeout(pending);
17165
+ pendingTerminalTimers.delete(evt.sessionId);
17166
+ }
17167
+ setRuns((prev) => ({
17168
+ ...prev,
17169
+ [evt.sessionId]: {
17170
+ runId: evt.runId,
17171
+ status: evt.status,
17172
+ updatedAt: evt.updatedAt
17173
+ }
17174
+ }));
17175
+ }
17176
+ });
17177
+ subscription?.catch((err) => {
17178
+ if (controller.signal.aborted) {
17179
+ return;
17180
+ }
17181
+ const surface = err instanceof Event ? err : new Event("error");
17182
+ onErrorRef.current?.(surface);
17183
+ });
17184
+ const readyTimeout = setTimeout(() => {
17185
+ if (!sawSnapshotRow) {
17186
+ setReady(true);
17187
+ }
17188
+ }, emptyStateTimeoutMs);
17189
+ return () => {
17190
+ controller.abort();
17191
+ if (stagingTimer !== void 0) {
17192
+ clearTimeout(stagingTimer);
17193
+ }
17194
+ clearTimeout(readyTimeout);
17195
+ for (const handle of pendingTerminalTimers.values()) {
17196
+ clearTimeout(handle);
17197
+ }
17198
+ pendingTerminalTimers.clear();
17199
+ };
17200
+ }, [dataSource, enabled, retainTerminalMs, emptyStateTimeoutMs]);
17201
+ const status = React.useCallback(
17202
+ (sessionId) => runs[sessionId]?.status,
17203
+ [runs]
17204
+ );
17205
+ return { runs, ready, status };
17206
+ }
17068
17207
 
17069
17208
  // ui/src/bichat/index.ts
17070
17209
  init_useTranslation();
@@ -19134,6 +19273,8 @@ function toStreamEvent(chunk) {
19134
19273
  return chunk.sessionId ? { type: "user_message", sessionId: chunk.sessionId } : null;
19135
19274
  case "interrupt":
19136
19275
  return chunk.interrupt ? { type: "interrupt", interrupt: chunk.interrupt, sessionId: chunk.sessionId } : null;
19276
+ case "text_block_end":
19277
+ return { type: "text_block_end", seq: chunk.textBlockSeq ?? 0 };
19137
19278
  case "done":
19138
19279
  return { type: "done", sessionId: chunk.sessionId, generationMs: chunk.generationMs };
19139
19280
  case "error":
@@ -19143,6 +19284,90 @@ function toStreamEvent(chunk) {
19143
19284
  }
19144
19285
  }
19145
19286
 
19287
+ // ui/src/bichat/utils/eventNames.ts
19288
+ var STREAM_EVENT_TYPES = [
19289
+ "chunk",
19290
+ "content",
19291
+ "thinking",
19292
+ "tool_start",
19293
+ "tool_end",
19294
+ "text_block_end",
19295
+ "snapshot",
19296
+ "interrupt",
19297
+ "citation",
19298
+ "usage",
19299
+ "ping",
19300
+ "stream_started",
19301
+ "done",
19302
+ "cancelled",
19303
+ "error",
19304
+ "failed"
19305
+ ];
19306
+ var TERMINAL_STREAM_EVENT_TYPES = [
19307
+ "done",
19308
+ "cancelled",
19309
+ "error",
19310
+ "failed"
19311
+ ];
19312
+ function isTerminalEvent(name) {
19313
+ return TERMINAL_STREAM_EVENT_TYPES.includes(name);
19314
+ }
19315
+
19316
+ // ui/src/bichat/data/openManagedEventSource.ts
19317
+ function openManagedEventSource(opts) {
19318
+ const graceMs = opts.connectGraceMs ?? 500;
19319
+ return new Promise((resolve, reject) => {
19320
+ const startedAt = Date.now();
19321
+ const es = new EventSource(opts.url, {
19322
+ withCredentials: opts.withCredentials ?? true
19323
+ });
19324
+ let settled = false;
19325
+ let sawEvent = false;
19326
+ const settle = (err) => {
19327
+ if (settled) {
19328
+ return;
19329
+ }
19330
+ settled = true;
19331
+ es.close();
19332
+ if (err) {
19333
+ reject(err);
19334
+ } else {
19335
+ resolve();
19336
+ }
19337
+ };
19338
+ if (opts.signal) {
19339
+ if (opts.signal.aborted) {
19340
+ settle();
19341
+ return;
19342
+ }
19343
+ opts.signal.addEventListener("abort", () => settle(), { once: true });
19344
+ }
19345
+ const forward = (name) => (evt) => {
19346
+ sawEvent = true;
19347
+ let parsed;
19348
+ try {
19349
+ parsed = JSON.parse(evt.data);
19350
+ } catch {
19351
+ parsed = { __unparseable: true, raw: String(evt.data) };
19352
+ }
19353
+ try {
19354
+ opts.onMessage(name, parsed);
19355
+ } catch {
19356
+ }
19357
+ };
19358
+ for (const name of opts.events) {
19359
+ es.addEventListener(name, forward(name));
19360
+ }
19361
+ es.onerror = (evt) => {
19362
+ opts.onError?.(evt);
19363
+ if (graceMs > 0 && !sawEvent && Date.now() - startedAt < graceMs) {
19364
+ const err = opts.onConnectError ? opts.onConnectError(evt) : new Error("EventSource failed to connect before first event");
19365
+ settle(err);
19366
+ }
19367
+ };
19368
+ });
19369
+ }
19370
+
19146
19371
  // ui/src/bichat/data/AttachmentUploader.ts
19147
19372
  init_chartSpec();
19148
19373
  var MIME_TO_EXTENSION = {
@@ -19397,6 +19622,26 @@ async function ensureAttachmentUpload(attachment, context, uploadFileFn) {
19397
19622
  }
19398
19623
 
19399
19624
  // ui/src/bichat/data/MessageTransport.ts
19625
+ var RunEventsConnectError = class extends Error {
19626
+ constructor(message, cause) {
19627
+ super(message);
19628
+ this.name = "RunEventsConnectError";
19629
+ this.cause = cause;
19630
+ }
19631
+ };
19632
+ function generateRequestId() {
19633
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
19634
+ return crypto.randomUUID();
19635
+ }
19636
+ const bytes = new Uint8Array(16);
19637
+ for (let i = 0; i < bytes.length; i++) {
19638
+ bytes[i] = Math.floor(Math.random() * 256);
19639
+ }
19640
+ bytes[6] = bytes[6] & 15 | 64;
19641
+ bytes[8] = bytes[8] & 63 | 128;
19642
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
19643
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
19644
+ }
19400
19645
  async function* sendMessage(deps, sessionId, content, attachments = [], signal, options) {
19401
19646
  const abortController = new AbortController();
19402
19647
  let onExternalAbort;
@@ -19424,12 +19669,14 @@ async function* sendMessage(deps, sessionId, content, attachments = [], signal,
19424
19669
  sessionId,
19425
19670
  attachmentCount: streamAttachments.length
19426
19671
  });
19672
+ const requestId = options?.requestId ?? generateRequestId();
19427
19673
  const payload = {
19428
19674
  sessionId,
19429
19675
  content,
19430
19676
  debugMode: options?.debugMode ?? false,
19431
19677
  replaceFromMessageId: options?.replaceFromMessageID,
19432
- attachments: streamAttachments
19678
+ attachments: streamAttachments,
19679
+ requestId
19433
19680
  };
19434
19681
  if (options?.reasoningEffort) {
19435
19682
  payload.reasoningEffort = options.reasoningEffort;
@@ -19470,10 +19717,14 @@ async function* sendMessage(deps, sessionId, content, attachments = [], signal,
19470
19717
  } catch (err) {
19471
19718
  if (err instanceof Error) {
19472
19719
  if (err.name === "AbortError") {
19473
- yield {
19474
- type: "error",
19475
- error: connectionTimedOut ? `Stream request timed out after ${deps.streamConnectTimeoutMs}ms` : "Stream cancelled"
19476
- };
19720
+ if (connectionTimedOut) {
19721
+ yield {
19722
+ type: "error",
19723
+ error: `Stream request timed out after ${deps.streamConnectTimeoutMs}ms`
19724
+ };
19725
+ } else {
19726
+ throw err;
19727
+ }
19477
19728
  } else {
19478
19729
  yield {
19479
19730
  type: "error",
@@ -19597,6 +19848,67 @@ async function resumeStream(deps, sessionId, runId, onChunk, signal) {
19597
19848
  }
19598
19849
  }
19599
19850
  }
19851
+ function subscribeRunEvents(deps, sessionId, runId, options) {
19852
+ const base = buildStreamUrl(deps, "/events");
19853
+ const qs = new URLSearchParams({ sessionId, runId });
19854
+ const url = `${base}?${qs.toString()}`;
19855
+ const withCursor = options.lastEventId ? `${url}&${new URLSearchParams({ lastEventId: options.lastEventId }).toString()}` : url;
19856
+ const settleController = new AbortController();
19857
+ if (options.signal) {
19858
+ if (options.signal.aborted) {
19859
+ settleController.abort();
19860
+ } else {
19861
+ options.signal.addEventListener("abort", () => settleController.abort(), {
19862
+ once: true
19863
+ });
19864
+ }
19865
+ }
19866
+ return openManagedEventSource({
19867
+ url: withCursor,
19868
+ events: STREAM_EVENT_TYPES,
19869
+ withCredentials: true,
19870
+ signal: settleController.signal,
19871
+ onError: options.onError,
19872
+ onConnectError: (evt) => new RunEventsConnectError(
19873
+ "EventSource failed to connect before first event",
19874
+ evt
19875
+ ),
19876
+ onMessage: (name, data) => {
19877
+ if (typeof data === "object" && data !== null && data.__unparseable) {
19878
+ options.onChunk({
19879
+ type: "error",
19880
+ error: `Failed to parse event: ${data.raw}`
19881
+ });
19882
+ return;
19883
+ }
19884
+ const parsed = data;
19885
+ if (!parsed.type) {
19886
+ parsed.type = name;
19887
+ }
19888
+ options.onChunk(parsed);
19889
+ if (isTerminalEvent(name) || isTerminalEvent(String(parsed.type))) {
19890
+ settleController.abort();
19891
+ }
19892
+ }
19893
+ });
19894
+ }
19895
+ function subscribeActiveRuns(deps, options) {
19896
+ const url = buildStreamUrl(deps, "/active-runs");
19897
+ return openManagedEventSource({
19898
+ url,
19899
+ events: ["snapshot", "update"],
19900
+ withCredentials: true,
19901
+ signal: options.signal,
19902
+ onError: options.onError,
19903
+ onMessage: (name, data) => {
19904
+ if (typeof data !== "object" || data === null || data.__unparseable) {
19905
+ return;
19906
+ }
19907
+ const body = data;
19908
+ options.onEvent({ event: name, ...body });
19909
+ }
19910
+ });
19911
+ }
19600
19912
  async function submitQuestionAnswers(callRPC, sessionId, questionId, answers) {
19601
19913
  try {
19602
19914
  const flatAnswers = {};
@@ -19865,6 +20177,39 @@ var HttpDataSource = class {
19865
20177
  signal
19866
20178
  );
19867
20179
  }
20180
+ /**
20181
+ * Open a native EventSource against GET /stream/events for the given
20182
+ * run. Used by components that want browser-native auto-reconnect
20183
+ * with Last-Event-ID (tab close, wifi drop, device switch). Prefer
20184
+ * over resumeStream when tailing an already-running generation that
20185
+ * another tab started.
20186
+ */
20187
+ subscribeRunEvents(sessionId, runId, options) {
20188
+ return subscribeRunEvents(
20189
+ {
20190
+ baseUrl: this.config.baseUrl,
20191
+ streamEndpoint: this.config.streamEndpoint
20192
+ },
20193
+ sessionId,
20194
+ runId,
20195
+ options
20196
+ );
20197
+ }
20198
+ /**
20199
+ * Subscribe to the per-tenant active-run fan-out
20200
+ * (GET /stream/active-runs). Never resolves until the caller aborts
20201
+ * via the signal; use from a top-level component (sidebar container)
20202
+ * that mounts for the lifetime of the chat app.
20203
+ */
20204
+ subscribeActiveRuns(options) {
20205
+ return subscribeActiveRuns(
20206
+ {
20207
+ baseUrl: this.config.baseUrl,
20208
+ streamEndpoint: this.config.streamEndpoint
20209
+ },
20210
+ options
20211
+ );
20212
+ }
19868
20213
  async *sendMessage(sessionId, content, attachments = [], signal, options) {
19869
20214
  this.abortController = new AbortController();
19870
20215
  let onExternalAbort;
@@ -19938,6 +20283,50 @@ function createHttpDataSource(config) {
19938
20283
  return new HttpDataSource(config);
19939
20284
  }
19940
20285
 
20286
+ // ui/src/bichat/utils/textBlocks.ts
20287
+ function splitIntoTextBlocks(content, offsets) {
20288
+ if (!content) {
20289
+ return [];
20290
+ }
20291
+ if (!offsets || offsets.length === 0) {
20292
+ return [{ seq: 0, content }];
20293
+ }
20294
+ const sanitized = [...offsets].map((n) => Math.max(0, Math.min(Math.floor(n), content.length))).sort((a, b) => a - b);
20295
+ const blocks = [];
20296
+ let cursor = 0;
20297
+ for (let i = 0; i < sanitized.length; i++) {
20298
+ const end = sanitized[i];
20299
+ if (end <= cursor) {
20300
+ continue;
20301
+ }
20302
+ const slice = content.slice(cursor, end);
20303
+ if (slice) {
20304
+ blocks.push({ seq: blocks.length, content: slice });
20305
+ }
20306
+ cursor = end;
20307
+ }
20308
+ if (cursor < content.length) {
20309
+ blocks.push({ seq: blocks.length, content: content.slice(cursor) });
20310
+ }
20311
+ return blocks;
20312
+ }
20313
+ function readTextBlockOffsets(partialMetadata) {
20314
+ if (!partialMetadata) {
20315
+ return [];
20316
+ }
20317
+ const raw = partialMetadata["text_block_offsets"];
20318
+ if (!Array.isArray(raw)) {
20319
+ return [];
20320
+ }
20321
+ const out = [];
20322
+ for (const entry of raw) {
20323
+ if (typeof entry === "number" && Number.isFinite(entry) && entry >= 0) {
20324
+ out.push(Math.floor(entry));
20325
+ }
20326
+ }
20327
+ return out;
20328
+ }
20329
+
19941
20330
  exports.ATTACHMENT_ACCEPT_ATTRIBUTE = ATTACHMENT_ACCEPT_ATTRIBUTE;
19942
20331
  exports.ActionButton = ActionButton;
19943
20332
  exports.ActivityTrace = ActivityTrace;
@@ -19989,6 +20378,8 @@ exports.QuestionForm = QuestionForm;
19989
20378
  exports.QuestionStep = QuestionStep;
19990
20379
  exports.RateLimiter = RateLimiter;
19991
20380
  exports.RetryActionArea = RetryActionArea;
20381
+ exports.RunEventsConnectError = RunEventsConnectError;
20382
+ exports.STREAM_EVENT_TYPES = STREAM_EVENT_TYPES;
19992
20383
  exports.ScreenReaderAnnouncer = ScreenReaderAnnouncer;
19993
20384
  exports.ScrollToBottomButton = ScrollToBottomButton;
19994
20385
  exports.SearchInput = MemoizedSearchInput;
@@ -20010,6 +20401,7 @@ exports.SourcesPanel = SourcesPanel;
20010
20401
  exports.StreamError = StreamError;
20011
20402
  exports.StreamingCursor = StreamingCursor;
20012
20403
  exports.SystemMessage = SystemMessage;
20404
+ exports.TERMINAL_STREAM_EVENT_TYPES = TERMINAL_STREAM_EVENT_TYPES;
20013
20405
  exports.TabbedChartGroup = TabbedChartGroup;
20014
20406
  exports.TabbedTableGroup = TabbedTableGroup;
20015
20407
  exports.ThemeProvider = ThemeProvider;
@@ -20047,6 +20439,7 @@ exports.groupSteps = groupSteps;
20047
20439
  exports.hasPermission = hasPermission;
20048
20440
  exports.isImageMimeType = isImageMimeType;
20049
20441
  exports.isPermissionDeniedError = isPermissionDeniedError;
20442
+ exports.isTerminalEvent = isTerminalEvent;
20050
20443
  exports.lightTheme = lightTheme;
20051
20444
  exports.listItemVariants = listItemVariants;
20052
20445
  exports.messageContainerVariants = messageContainerVariants;
@@ -20054,12 +20447,15 @@ exports.messageVariants = messageVariants;
20054
20447
  exports.parseBichatStream = parseBichatStream;
20055
20448
  exports.parseBichatStreamEvents = parseBichatStreamEvents;
20056
20449
  exports.parseSSEStream = parseSSEStream;
20450
+ exports.readTextBlockOffsets = readTextBlockOffsets;
20057
20451
  exports.scaleFadeVariants = scaleFadeVariants;
20058
20452
  exports.sessionItemVariants = sessionItemVariants;
20453
+ exports.splitIntoTextBlocks = splitIntoTextBlocks;
20059
20454
  exports.staggerContainerVariants = staggerContainerVariants;
20060
20455
  exports.toErrorDisplay = toErrorDisplay;
20061
20456
  exports.typingDotVariants = typingDotVariants;
20062
20457
  exports.useActionButtonContext = useActionButtonContext;
20458
+ exports.useActiveRuns = useActiveRuns;
20063
20459
  exports.useAttachments = useAttachments;
20064
20460
  exports.useAutoScroll = useAutoScroll;
20065
20461
  exports.useAvatarContext = useAvatarContext;