@arbidocs/react 0.5.63 → 0.5.65

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 (60) hide show
  1. package/README.md +9 -0
  2. package/dist/annotations/freeze/index.cjs +14 -14
  3. package/dist/annotations/freeze/index.js +3 -3
  4. package/dist/artifacts/index.cjs +49 -49
  5. package/dist/artifacts/index.js +10 -10
  6. package/dist/bundle-DCWPYNGD.cjs +14 -0
  7. package/dist/{bundle-IC65W2AO.cjs.map → bundle-DCWPYNGD.cjs.map} +1 -1
  8. package/dist/bundle-JCKKGEJE.js +5 -0
  9. package/dist/{bundle-YNOX7VIL.js.map → bundle-JCKKGEJE.js.map} +1 -1
  10. package/dist/calls/livekit/index.cjs +47 -47
  11. package/dist/calls/livekit/index.js +8 -8
  12. package/dist/{chunk-TGSEQGM3.cjs → chunk-2PMH4DTL.cjs} +4 -4
  13. package/dist/{chunk-TGSEQGM3.cjs.map → chunk-2PMH4DTL.cjs.map} +1 -1
  14. package/dist/{chunk-ZTPJNKF2.js → chunk-6QGAXWHR.js} +5 -5
  15. package/dist/{chunk-ZTPJNKF2.js.map → chunk-6QGAXWHR.js.map} +1 -1
  16. package/dist/{chunk-NIKPG4PW.js → chunk-A2XSLTIP.js} +3 -3
  17. package/dist/{chunk-NIKPG4PW.js.map → chunk-A2XSLTIP.js.map} +1 -1
  18. package/dist/{chunk-PC4O3JDV.cjs → chunk-B6I2HRRF.cjs} +3 -3
  19. package/dist/{chunk-PC4O3JDV.cjs.map → chunk-B6I2HRRF.cjs.map} +1 -1
  20. package/dist/{chunk-SI7DJWBT.js → chunk-CHLDCP3J.js} +3 -3
  21. package/dist/{chunk-SI7DJWBT.js.map → chunk-CHLDCP3J.js.map} +1 -1
  22. package/dist/{chunk-3BFSALPC.cjs → chunk-FZ4P7W67.cjs} +5 -5
  23. package/dist/{chunk-3BFSALPC.cjs.map → chunk-FZ4P7W67.cjs.map} +1 -1
  24. package/dist/{chunk-ER4LFZG3.js → chunk-HZUMY365.js} +247 -65
  25. package/dist/chunk-HZUMY365.js.map +1 -0
  26. package/dist/{chunk-DVL7EFZZ.cjs → chunk-MN4BTKHE.cjs} +249 -67
  27. package/dist/chunk-MN4BTKHE.cjs.map +1 -0
  28. package/dist/{chunk-BLBXADTN.cjs → chunk-MS3T4C4Q.cjs} +7 -7
  29. package/dist/{chunk-BLBXADTN.cjs.map → chunk-MS3T4C4Q.cjs.map} +1 -1
  30. package/dist/{chunk-NNWMHMEC.js → chunk-MZ7EYCGH.js} +3 -3
  31. package/dist/{chunk-NNWMHMEC.js.map → chunk-MZ7EYCGH.js.map} +1 -1
  32. package/dist/{chunk-NCMSQACC.js → chunk-PLF2OEZZ.js} +5 -5
  33. package/dist/{chunk-NCMSQACC.js.map → chunk-PLF2OEZZ.js.map} +1 -1
  34. package/dist/{chunk-4DTTEUVY.js → chunk-QL6CHRQ5.js} +4 -4
  35. package/dist/{chunk-4DTTEUVY.js.map → chunk-QL6CHRQ5.js.map} +1 -1
  36. package/dist/{chunk-ZWFMFOGP.cjs → chunk-WEJHHBA2.cjs} +3 -3
  37. package/dist/{chunk-ZWFMFOGP.cjs.map → chunk-WEJHHBA2.cjs.map} +1 -1
  38. package/dist/{chunk-GOJHU7RZ.cjs → chunk-XFF66SHT.cjs} +26 -26
  39. package/dist/{chunk-GOJHU7RZ.cjs.map → chunk-XFF66SHT.cjs.map} +1 -1
  40. package/dist/{chunk-3NBPMR3X.js → chunk-Y2WKLPN3.js} +5 -5
  41. package/dist/{chunk-3NBPMR3X.js.map → chunk-Y2WKLPN3.js.map} +1 -1
  42. package/dist/{chunk-LMW46NBD.cjs → chunk-ZDAILE45.cjs} +6 -6
  43. package/dist/{chunk-LMW46NBD.cjs.map → chunk-ZDAILE45.cjs.map} +1 -1
  44. package/dist/document-tools/core.cjs +103 -103
  45. package/dist/document-tools/core.js +7 -7
  46. package/dist/document-tools/index.cjs +106 -106
  47. package/dist/document-tools/index.js +9 -9
  48. package/dist/index.cjs +1308 -1308
  49. package/dist/index.d.cts +104 -24
  50. package/dist/index.d.ts +104 -24
  51. package/dist/index.js +24 -24
  52. package/dist/shell/index.cjs +36 -36
  53. package/dist/shell/index.js +5 -5
  54. package/dist/ui/index.cjs +195 -195
  55. package/dist/ui/index.js +4 -4
  56. package/package.json +3 -3
  57. package/dist/bundle-IC65W2AO.cjs +0 -14
  58. package/dist/bundle-YNOX7VIL.js +0 -5
  59. package/dist/chunk-DVL7EFZZ.cjs.map +0 -1
  60. package/dist/chunk-ER4LFZG3.js.map +0 -1
@@ -1,13 +1,137 @@
1
1
  'use strict';
2
2
 
3
+ var chunkN73IMVFF_cjs = require('./chunk-N73IMVFF.cjs');
3
4
  var chunkGQAXAZN7_cjs = require('./chunk-GQAXAZN7.cjs');
5
+ var chunkWEJHHBA2_cjs = require('./chunk-WEJHHBA2.cjs');
4
6
  var chunkY7S2SQH3_cjs = require('./chunk-Y7S2SQH3.cjs');
5
- var chunkN73IMVFF_cjs = require('./chunk-N73IMVFF.cjs');
6
- var chunkZWFMFOGP_cjs = require('./chunk-ZWFMFOGP.cjs');
7
7
  var client = require('@arbidocs/client');
8
8
  var react = require('react');
9
9
  var reactQuery = require('@tanstack/react-query');
10
10
 
11
+ // src/session/thread-tabs.ts
12
+ var threadTabId = (tab) => tab.conversationId ?? "new";
13
+ var MAX_THREAD_TABS = 12;
14
+ var withView = (threads, tabId, view) => threads.map((tab) => tabId !== null && threadTabId(tab) === tabId ? { ...tab, view } : tab);
15
+ function selectThreadTabIn(tabs, tabId, leaving) {
16
+ const target = tabs.threads.find((tab) => threadTabId(tab) === tabId);
17
+ if (!target) return { tabs, show: null };
18
+ const isActive = tabs.activeThread === tabId;
19
+ if (isActive && leaving.conversationId === target.conversationId) return { tabs, show: null };
20
+ return {
21
+ tabs: {
22
+ ...tabs,
23
+ // Re-opening the active tab saves nothing: its live composer is the cleared one.
24
+ threads: isActive ? tabs.threads : withView(tabs.threads, tabs.activeThread, leaving.view),
25
+ activeThread: tabId,
26
+ threadScrollRestore: target.view?.scrollTop ?? null
27
+ },
28
+ show: { conversationId: target.conversationId, view: target.view }
29
+ };
30
+ }
31
+ function openThreadTabIn(tabs, conversationId, leaving) {
32
+ const tabId = conversationId ?? "new";
33
+ const existing = tabs.threads.find((tab) => threadTabId(tab) === tabId);
34
+ if (existing) {
35
+ const threads2 = tabs.threads.map(
36
+ (tab) => threadTabId(tab) === tabId && tab.view ? { ...tab, view: { ...tab.view, scrollTop: null, cursor: null } } : tab
37
+ );
38
+ return { tabId, ...selectThreadTabIn({ ...tabs, threads: threads2 }, tabId, leaving) };
39
+ }
40
+ const fresh = { conversationId, view: void 0 };
41
+ const onlyNewChat = tabs.threads.length === 1 && tabs.threads[0].conversationId === null;
42
+ if (conversationId && onlyNewChat)
43
+ return {
44
+ tabId,
45
+ tabs: { ...tabs, threads: [{ conversationId }], activeThread: tabId },
46
+ show: fresh
47
+ };
48
+ let threads = [...withView(tabs.threads, tabs.activeThread, leaving.view), { conversationId }];
49
+ if (threads.length > MAX_THREAD_TABS) {
50
+ const evict = threads.findIndex(
51
+ (tab, i) => i < threads.length - 1 && threadTabId(tab) !== tabs.activeThread
52
+ );
53
+ if (evict !== -1) threads = threads.filter((_, i) => i !== evict);
54
+ }
55
+ return { tabId, tabs: { ...tabs, threads, activeThread: tabId }, show: fresh };
56
+ }
57
+ function closeThreadTabIn(tabs, tabId) {
58
+ const threads = tabs.threads.filter((tab) => threadTabId(tab) !== tabId);
59
+ if (threads.length === 0)
60
+ return { tabs: { ...tabs, threads: [], activeThread: null }, show: "list" };
61
+ if (tabs.activeThread !== tabId) return { tabs: { ...tabs, threads }, show: null };
62
+ const index = tabs.threads.findIndex((tab) => threadTabId(tab) === tabId);
63
+ const next = threads[Math.min(index, threads.length - 1)];
64
+ return {
65
+ tabs: { ...tabs, threads, activeThread: threadTabId(next) },
66
+ show: { conversationId: next.conversationId, view: next.view }
67
+ };
68
+ }
69
+ function showThreadListIn(tabs, leaving) {
70
+ return {
71
+ ...tabs,
72
+ activeThread: null,
73
+ threads: tabs.threads.map(
74
+ (tab) => threadTabId(tab) === tabs.activeThread ? { ...tab, view: { ...leaving.view, scrollTop: null } } : tab.view ? { ...tab, view: { ...tab.view, scrollTop: null } } : tab
75
+ )
76
+ };
77
+ }
78
+ function renameThreadTabIn(tabs, fromId, toId) {
79
+ if (fromId === toId || !tabs.threads.some((tab) => threadTabId(tab) === fromId)) return tabs;
80
+ const taken = tabs.threads.some((tab) => threadTabId(tab) === toId);
81
+ return {
82
+ ...tabs,
83
+ activeThread: tabs.activeThread === fromId ? toId : tabs.activeThread,
84
+ threads: taken ? tabs.threads.filter((tab) => threadTabId(tab) !== fromId) : tabs.threads.map(
85
+ (tab) => threadTabId(tab) === fromId ? { ...tab, conversationId: toId } : tab
86
+ )
87
+ };
88
+ }
89
+ function withThreadDrafts(threads, drafts) {
90
+ let changed = false;
91
+ const next = threads.map((tab) => {
92
+ const draft = drafts[threadTabId(tab)];
93
+ if (!draft || !tab.view || tab.view.draft) return tab;
94
+ changed = true;
95
+ return { ...tab, view: { ...tab.view, draft } };
96
+ });
97
+ return changed ? next : threads;
98
+ }
99
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
100
+ var stringOrNull = (v) => typeof v === "string" ? v : null;
101
+ var stringOrUndefined = (v) => typeof v === "string" ? v : void 0;
102
+ function parseView(value) {
103
+ if (!isRecord(value)) return void 0;
104
+ return {
105
+ cursor: stringOrNull(value.cursor),
106
+ draft: "",
107
+ editingMessageId: stringOrNull(value.editingMessageId),
108
+ preEditDraft: null,
109
+ preEditCursor: stringOrNull(value.preEditCursor),
110
+ chatModel: stringOrUndefined(value.chatModel),
111
+ chatModelName: stringOrUndefined(value.chatModelName),
112
+ scrollTop: typeof value.scrollTop === "number" && Number.isFinite(value.scrollTop) ? value.scrollTop : null
113
+ };
114
+ }
115
+ function parseSavedThreadTabs(threads, activeThread) {
116
+ const tabs = [];
117
+ for (const entry of Array.isArray(threads) ? threads : []) {
118
+ if (!isRecord(entry)) continue;
119
+ const { conversationId } = entry;
120
+ if (conversationId !== null && typeof conversationId !== "string") continue;
121
+ const view = parseView(entry.view);
122
+ const tab = view ? { conversationId, view } : { conversationId };
123
+ if (!tabs.some((t) => threadTabId(t) === threadTabId(tab))) tabs.push(tab);
124
+ }
125
+ const active = typeof activeThread === "string" ? activeThread : null;
126
+ return {
127
+ threads: tabs,
128
+ activeThread: active && tabs.some((tab) => threadTabId(tab) === active) ? active : null
129
+ };
130
+ }
131
+ var savedThreadTabs = (threads) => threads.map(
132
+ (tab) => tab.view ? { ...tab, view: { ...tab.view, draft: "", preEditDraft: null } } : tab
133
+ );
134
+
11
135
  // src/session/layout.ts
12
136
  var PANEL_MODES = ["main", "docked", "overlay", "popout"];
13
137
  var defaultPinned = () => typeof window === "undefined" || window.innerWidth >= 640;
@@ -19,26 +143,36 @@ function defaultLayoutState() {
19
143
  panels: { main: null, docked: null, overlay: null, popout: null, modes: {}, sizes: {} },
20
144
  focusedArea: "main"
21
145
  },
22
- tabs: { dm: [], activeDm: null, dmMessageId: null, projects: [], activeProject: null },
146
+ tabs: {
147
+ threads: [],
148
+ activeThread: null,
149
+ threadScrollRestore: null,
150
+ dm: [],
151
+ activeDm: null,
152
+ dmMessageId: null,
153
+ projects: [],
154
+ activeProject: null
155
+ },
23
156
  views: { tabs: {}, filters: {}, values: {}, transient: {} },
24
157
  grid: { states: {}, rowHeights: {}, labelWidths: {}, savedViews: {} }
25
158
  };
26
159
  }
27
- var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
28
- var recordOf = (value, keep) => isRecord(value) ? Object.fromEntries(Object.entries(value).filter(([, v]) => keep(v))) : {};
160
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
161
+ var recordOf = (value, keep) => isRecord2(value) ? Object.fromEntries(Object.entries(value).filter(([, v]) => keep(v))) : {};
29
162
  var isString = (v) => typeof v === "string";
30
163
  var isNumber = (v) => typeof v === "number" && Number.isFinite(v);
31
164
  var isAny = (v) => v !== void 0;
32
165
  var isMode = (v) => PANEL_MODES.includes(v);
33
- var isSize = (v) => isRecord(v) && isNumber(v.width) && isNumber(v.height);
166
+ var isSize = (v) => isRecord2(v) && isNumber(v.width) && isNumber(v.height);
34
167
  var isList = (v) => Array.isArray(v);
35
- var stringOrNull = (v) => isString(v) ? v : null;
168
+ var stringOrNull2 = (v) => isString(v) ? v : null;
36
169
  function parseSavedLayout(saved) {
37
- if (!isRecord(saved) || saved.version !== 1) return null;
38
- const shell = isRecord(saved.shell) ? saved.shell : {};
39
- const panels = isRecord(shell.panels) ? shell.panels : {};
40
- const views = isRecord(saved.views) ? saved.views : {};
41
- const grid = isRecord(saved.grid) ? saved.grid : {};
170
+ if (!isRecord2(saved) || saved.version !== 1) return null;
171
+ const shell = isRecord2(saved.shell) ? saved.shell : {};
172
+ const panels = isRecord2(shell.panels) ? shell.panels : {};
173
+ const tabs = isRecord2(saved.tabs) ? saved.tabs : {};
174
+ const views = isRecord2(saved.views) ? saved.views : {};
175
+ const grid = isRecord2(saved.grid) ? saved.grid : {};
42
176
  const defaults = defaultLayoutState();
43
177
  return {
44
178
  version: 1,
@@ -47,19 +181,20 @@ function parseSavedLayout(saved) {
47
181
  page: isString(shell.page) ? shell.page : defaults.shell.page,
48
182
  sidebarPinned: typeof shell.sidebarPinned === "boolean" ? shell.sidebarPinned : defaults.shell.sidebar.pinned,
49
183
  panels: {
50
- main: stringOrNull(panels.main),
51
- docked: stringOrNull(panels.docked),
184
+ main: stringOrNull2(panels.main),
185
+ docked: stringOrNull2(panels.docked),
52
186
  modes: recordOf(panels.modes, isMode),
53
187
  sizes: recordOf(panels.sizes, isSize)
54
188
  }
55
189
  },
190
+ tabs: parseSavedThreadTabs(tabs.threads, tabs.activeThread),
56
191
  views: {
57
192
  tabs: recordOf(views.tabs, isString),
58
193
  filters: recordOf(views.filters, isAny),
59
194
  values: recordOf(views.values, isAny)
60
195
  },
61
196
  grid: {
62
- states: recordOf(grid.states, isRecord),
197
+ states: recordOf(grid.states, isRecord2),
63
198
  rowHeights: recordOf(grid.rowHeights, isNumber),
64
199
  labelWidths: recordOf(grid.labelWidths, isNumber),
65
200
  savedViews: recordOf(grid.savedViews, isList)
@@ -67,7 +202,7 @@ function parseSavedLayout(saved) {
67
202
  };
68
203
  }
69
204
  function savedLayoutOf(layout, migrated) {
70
- const { shell, views, grid } = layout;
205
+ const { shell, tabs, views, grid } = layout;
71
206
  return {
72
207
  version: 1,
73
208
  migrated,
@@ -82,6 +217,7 @@ function savedLayoutOf(layout, migrated) {
82
217
  sizes: shell.panels.sizes
83
218
  }
84
219
  },
220
+ tabs: { threads: savedThreadTabs(tabs.threads), activeThread: tabs.activeThread },
85
221
  views: { tabs: views.tabs, filters: views.filters, values: views.values },
86
222
  grid
87
223
  };
@@ -95,6 +231,7 @@ function restoreLayout(current, saved) {
95
231
  sidebar: { ...current.shell.sidebar, pinned: saved.shell.sidebarPinned },
96
232
  panels: { ...current.shell.panels, ...saved.shell.panels }
97
233
  },
234
+ tabs: { ...current.tabs, ...saved.tabs },
98
235
  views: { ...saved.views, transient: current.views.transient },
99
236
  grid: saved.grid
100
237
  };
@@ -128,8 +265,11 @@ function panelPlace(panels, panelId) {
128
265
  }
129
266
  var isPanelOpen = (state, panelId) => panelPlace(state.shell.panels, panelId) !== null;
130
267
  var dmTabId = (tab) => tab.recipientId ?? "new";
131
- function createArbiLayoutStore({ persist } = {}) {
132
- let layout = defaultLayoutState();
268
+ function createArbiLayoutStore({
269
+ persist,
270
+ initial
271
+ } = {}) {
272
+ let layout = { ...defaultLayoutState(), ...initial };
133
273
  let migrated = [];
134
274
  let isHydrated = !persist;
135
275
  const listeners = /* @__PURE__ */ new Set();
@@ -138,7 +278,7 @@ function createArbiLayoutStore({ persist } = {}) {
138
278
  };
139
279
  const update = (next) => {
140
280
  if (next === layout) return;
141
- const persisted = next.views.tabs !== layout.views.tabs || next.views.filters !== layout.views.filters || next.views.values !== layout.views.values || next.grid !== layout.grid || next.shell.page !== layout.shell.page || next.shell.sidebar.pinned !== layout.shell.sidebar.pinned || next.shell.panels !== layout.shell.panels;
281
+ const persisted = next.tabs.threads !== layout.tabs.threads || next.tabs.activeThread !== layout.tabs.activeThread || next.views.tabs !== layout.views.tabs || next.views.filters !== layout.views.filters || next.views.values !== layout.views.values || next.grid !== layout.grid || next.shell.page !== layout.shell.page || next.shell.sidebar.pinned !== layout.shell.sidebar.pinned || next.shell.panels !== layout.shell.panels;
142
282
  layout = next;
143
283
  listeners.forEach((listener) => listener());
144
284
  if (persisted) save();
@@ -171,6 +311,41 @@ function createArbiLayoutStore({ persist } = {}) {
171
311
  },
172
312
  hydrated: () => hydration,
173
313
  isHydrated: () => isHydrated,
314
+ threads: {
315
+ open: (conversationId, leaving) => {
316
+ const change = openThreadTabIn(layout.tabs, conversationId, leaving);
317
+ tabs(change.tabs);
318
+ return { tabId: change.tabId, show: change.show };
319
+ },
320
+ close: (tabId) => {
321
+ const change = closeThreadTabIn(layout.tabs, tabId);
322
+ tabs(change.tabs);
323
+ return change.show;
324
+ },
325
+ select: (tabId, leaving) => {
326
+ const change = selectThreadTabIn(layout.tabs, tabId, leaving);
327
+ if (change.tabs !== layout.tabs) tabs(change.tabs);
328
+ return change.show;
329
+ },
330
+ showList: (leaving) => tabs(showThreadListIn(layout.tabs, leaving)),
331
+ rename: (fromId, toId) => {
332
+ const next = renameThreadTabIn(layout.tabs, fromId, toId);
333
+ if (next !== layout.tabs) tabs(next);
334
+ },
335
+ clear: () => {
336
+ if (layout.tabs.threads.length > 0 || layout.tabs.activeThread !== null)
337
+ tabs({ threads: [], activeThread: null });
338
+ },
339
+ restoreDrafts: (drafts) => {
340
+ const threads = withThreadDrafts(layout.tabs.threads, drafts);
341
+ if (threads !== layout.tabs.threads) tabs({ threads });
342
+ },
343
+ consumeScrollRestore: () => {
344
+ const value = layout.tabs.threadScrollRestore;
345
+ if (value !== null) tabs({ threadScrollRestore: null });
346
+ return value;
347
+ }
348
+ },
174
349
  setPage: (page) => {
175
350
  if (layout.shell.page !== page || layout.shell.focusedArea !== "main")
176
351
  shell({ page, focusedArea: "main" });
@@ -437,8 +612,6 @@ var agentControl = {
437
612
  };
438
613
 
439
614
  // src/session/store.ts
440
- var threadTabId = (tab) => tab.conversationId ?? "new";
441
- var MAX_THREAD_TABS = 12;
442
615
  var DEFAULT_DOCUMENT_VIEWER_STATE = {
443
616
  tab: "pdf",
444
617
  compareId: null,
@@ -471,8 +644,6 @@ var EMPTY_SESSION_STATE = {
471
644
  activeCitationKey: null,
472
645
  chatModel: void 0,
473
646
  chatModelName: void 0,
474
- threadTabs: [],
475
- activeThreadTabId: null,
476
647
  newConversationAssistantMode: "always",
477
648
  pendingTools: null,
478
649
  autoSendDraft: false,
@@ -482,7 +653,7 @@ var EMPTY_SESSION_STATE = {
482
653
  messageTimers: {},
483
654
  ...defaultLayoutState()
484
655
  };
485
- var selectViewingDocumentId = (state) => state.viewingDocument ? chunkZWFMFOGP_cjs.parseVersionRef(state.viewingDocument.id).docId : null;
656
+ var selectViewingDocumentId = (state) => state.viewingDocument ? chunkWEJHHBA2_cjs.parseVersionRef(state.viewingDocument.id).docId : null;
486
657
  var conversationKey = (state) => state.conversationId ?? "new";
487
658
  var selectDraft = (state) => state.drafts[conversationKey(state)] ?? "";
488
659
  var selectIsGenerating = (conversationId) => (state) => !!conversationId && !!state.generating[conversationId]?.isGenerating;
@@ -502,6 +673,7 @@ function layoutActionsOf(layout) {
502
673
  delete actions.hydrated;
503
674
  delete actions.isHydrated;
504
675
  delete actions.reset;
676
+ delete actions.threads;
505
677
  return actions;
506
678
  }
507
679
  function withoutNew(record) {
@@ -513,12 +685,18 @@ function createArbiSessionStore(initial = {}, {
513
685
  persist,
514
686
  workspace = createArbiWorkspaceStore({ workspaceId: initial.workspaceId ?? null })
515
687
  } = {}) {
516
- const layout = createArbiLayoutStore({ persist });
688
+ const { shell, tabs, views, grid, ...rest } = initial;
689
+ const layout = createArbiLayoutStore({
690
+ persist,
691
+ initial: Object.fromEntries(
692
+ Object.entries({ shell, tabs, views, grid }).filter(([, part]) => part !== void 0)
693
+ )
694
+ });
517
695
  if (initial.workspaceStatus) workspace.setWorkspaceStatus(initial.workspaceStatus);
518
696
  let state = {
519
697
  ...EMPTY_SESSION_STATE,
698
+ ...rest,
520
699
  ...layout.getLayout(),
521
- ...initial,
522
700
  ...workspace.getState()
523
701
  };
524
702
  const listeners = /* @__PURE__ */ new Set();
@@ -570,6 +748,35 @@ function createArbiSessionStore(initial = {}, {
570
748
  else delete drafts[key];
571
749
  setDrafts(drafts);
572
750
  };
751
+ const composer = () => ({
752
+ conversationId: state.conversationId,
753
+ view: {
754
+ cursor: state.cursor,
755
+ draft: selectDraft(state),
756
+ editingMessageId: state.editingMessageId,
757
+ preEditDraft: state.editingMessageId ? preEdit.draft : null,
758
+ preEditCursor: state.editingMessageId ? preEdit.cursor : null,
759
+ chatModel: state.chatModel,
760
+ chatModelName: state.chatModelName,
761
+ scrollTop: null
762
+ }
763
+ });
764
+ const show = (next) => {
765
+ if (next === null) return;
766
+ if (next === "list") {
767
+ preEdit = { draft: "", cursor: null };
768
+ return update({ conversationId: null, cursor: null, editingMessageId: null });
769
+ }
770
+ const view = next.view;
771
+ preEdit = { draft: view?.preEditDraft ?? "", cursor: view?.preEditCursor ?? null };
772
+ update({
773
+ conversationId: next.conversationId,
774
+ cursor: view?.cursor ?? null,
775
+ editingMessageId: view?.editingMessageId ?? null,
776
+ chatModel: view?.chatModel,
777
+ chatModelName: view?.chatModelName
778
+ });
779
+ };
573
780
  return {
574
781
  ...layoutActionsOf(layout),
575
782
  layoutHydrated: () => layout.hydrated(),
@@ -600,10 +807,9 @@ function createArbiSessionStore(initial = {}, {
600
807
  pinnedDocumentId: null,
601
808
  newAgentChat: null,
602
809
  newChatDocumentId: null,
603
- messageTimers: {},
604
- threadTabs: [],
605
- activeThreadTabId: null
810
+ messageTimers: {}
606
811
  });
812
+ layout.threads.clear();
607
813
  },
608
814
  setConversationId: (conversationId) => {
609
815
  if (state.conversationId !== conversationId)
@@ -671,13 +877,9 @@ function createArbiSessionStore(initial = {}, {
671
877
  conversationDocuments: move(state.conversationDocuments),
672
878
  conversationDocumentAutoAdd: move(state.conversationDocumentAutoAdd),
673
879
  conversationFacts: move(state.conversationFacts),
674
- conversationId: state.conversationId ?? toId,
675
- // The new chat's tab is now the conversation's.
676
- threadTabs: state.threadTabs.map(
677
- (tab) => threadTabId(tab) === fromId ? { conversationId: toId } : tab
678
- ),
679
- activeThreadTabId: state.activeThreadTabId === fromId ? toId : state.activeThreadTabId
880
+ conversationId: state.conversationId ?? toId
680
881
  });
882
+ layout.threads.rename(fromId, toId);
681
883
  if (fromId in state.drafts) setDrafts(move(state.drafts));
682
884
  },
683
885
  setConversationFacts: (conversationId, factIds) => update({ conversationFacts: { ...state.conversationFacts, [conversationId]: factIds } }),
@@ -704,37 +906,17 @@ function createArbiSessionStore(initial = {}, {
704
906
  if (state.chatModel !== chatModel) update({ chatModel });
705
907
  },
706
908
  openThreadTab: (conversationId) => {
707
- const id = conversationId ?? "new";
708
- const others = state.threadTabs.filter((tab) => threadTabId(tab) !== id);
709
- const threadTabs = [...others, { conversationId }].slice(-MAX_THREAD_TABS);
710
- update({
711
- threadTabs,
712
- activeThreadTabId: id,
713
- ...conversationId === null ? { newChatDocumentId: null } : {}
714
- });
715
- if (state.conversationId !== conversationId)
716
- update({ conversationId, cursor: null, editingMessageId: null });
717
- return id;
718
- },
719
- closeThreadTab: (tabId) => {
720
- const threadTabs = state.threadTabs.filter((tab) => threadTabId(tab) !== tabId);
721
- if (threadTabs.length === state.threadTabs.length) return;
722
- if (state.activeThreadTabId !== tabId) return update({ threadTabs });
723
- const next = threadTabs.at(-1);
724
- update({ threadTabs, activeThreadTabId: next ? threadTabId(next) : null });
725
- if (next && state.conversationId !== next.conversationId)
726
- update({ conversationId: next.conversationId, cursor: null, editingMessageId: null });
909
+ if (conversationId === null) update({ newAgentChat: null, newChatDocumentId: null });
910
+ else if (state.newAgentChat) update({ newAgentChat: null });
911
+ const { tabId, show: next } = layout.threads.open(conversationId, composer());
912
+ show(next);
913
+ return tabId;
727
914
  },
915
+ closeThreadTab: (tabId) => show(layout.threads.close(tabId)),
728
916
  selectThreadTab: (tabId) => {
729
- if (tabId === null) {
730
- if (state.activeThreadTabId !== null) update({ activeThreadTabId: null });
731
- return;
732
- }
733
- const tab = state.threadTabs.find((t) => threadTabId(t) === tabId);
734
- if (!tab) return;
735
- update({ activeThreadTabId: tabId });
736
- if (state.conversationId !== tab.conversationId)
737
- update({ conversationId: tab.conversationId, cursor: null, editingMessageId: null });
917
+ if (tabId !== null) return show(layout.threads.select(tabId, composer()));
918
+ layout.threads.showList(composer());
919
+ show("list");
738
920
  },
739
921
  setChatModelName: (chatModelName) => {
740
922
  if (state.chatModelName !== chatModelName) update({ chatModelName });
@@ -1217,7 +1399,7 @@ function useParsedDocument(docId, stage = "final", options) {
1217
1399
  return reactQuery.useQuery({
1218
1400
  queryKey: chunkGQAXAZN7_cjs.arbiQueryKeys.parsedDoc(docId ?? "", stage),
1219
1401
  queryFn: () => {
1220
- const { docId: id, version } = chunkZWFMFOGP_cjs.parseVersionRef(docId);
1402
+ const { docId: id, version } = chunkWEJHHBA2_cjs.parseVersionRef(docId);
1221
1403
  return arbi.documents.getParsedContent(
1222
1404
  id,
1223
1405
  stage,
@@ -1554,5 +1736,5 @@ exports.useTransientView = useTransientView;
1554
1736
  exports.useUserUsageToday = useUserUsageToday;
1555
1737
  exports.useWorkspaceActivity = useWorkspaceActivity;
1556
1738
  exports.useWorkspaces = useWorkspaces;
1557
- //# sourceMappingURL=chunk-DVL7EFZZ.cjs.map
1558
- //# sourceMappingURL=chunk-DVL7EFZZ.cjs.map
1739
+ //# sourceMappingURL=chunk-MN4BTKHE.cjs.map
1740
+ //# sourceMappingURL=chunk-MN4BTKHE.cjs.map