@arbidocs/tui 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -153,6 +153,24 @@ var ChatLog = class extends piTui.Container {
153
153
  this.addChild(new SystemMessage(message, level));
154
154
  this.addChild(new piTui.Spacer(1));
155
155
  }
156
+ /** Add a received DM message (cyan label with sender email). */
157
+ addDm(senderEmail, text) {
158
+ const container = new piTui.Container();
159
+ const label = new piTui.Text(colors.accent(senderEmail), 1, 0);
160
+ const content = new piTui.Text(colors.text(text), 1, 0);
161
+ container.addChild(label);
162
+ container.addChild(content);
163
+ this.addChild(container);
164
+ this.addChild(new piTui.Spacer(1));
165
+ }
166
+ /** Remove all messages from the chat log. */
167
+ clearMessages() {
168
+ this.activeAssistant = null;
169
+ this.activeSteps = [];
170
+ while (this.children.length > 0) {
171
+ this.removeChild(this.children[this.children.length - 1]);
172
+ }
173
+ }
156
174
  /** Start a new assistant streaming response. */
157
175
  startAssistant() {
158
176
  this.activeAssistant = new AssistantMessage();
@@ -229,14 +247,67 @@ var ArbiEditor = class extends piTui.Editor {
229
247
  super.handleInput(data);
230
248
  }
231
249
  };
250
+ var LEVEL_STYLE = {
251
+ info: chalk__default.default.dim.cyan,
252
+ success: chalk__default.default.dim.green,
253
+ warning: chalk__default.default.dim.yellow,
254
+ error: chalk__default.default.dim.red
255
+ };
256
+ function formatTimestamp() {
257
+ const now = /* @__PURE__ */ new Date();
258
+ const hh = String(now.getHours()).padStart(2, "0");
259
+ const mm = String(now.getMinutes()).padStart(2, "0");
260
+ const ss = String(now.getSeconds()).padStart(2, "0");
261
+ return `${hh}:${mm}:${ss}`;
262
+ }
263
+ var ToastContainer = class extends piTui.Container {
264
+ activeToasts = [];
265
+ renderCallback = null;
266
+ /** Set the callback used to trigger a TUI re-render after toast changes. */
267
+ setRenderCallback(cb) {
268
+ this.renderCallback = cb;
269
+ }
270
+ /** Show a toast notification that auto-dismisses after `durationMs`. */
271
+ show(message, level = "info", durationMs = 5e3) {
272
+ const styleFn = LEVEL_STYLE[level];
273
+ const formatted = styleFn(`[${formatTimestamp()}] ${message}`);
274
+ const text = new piTui.Text(formatted, 1, 0);
275
+ const timer = setTimeout(() => {
276
+ this.dismiss(text);
277
+ }, durationMs);
278
+ this.activeToasts.push({ text, timer });
279
+ this.addChild(text);
280
+ this.renderCallback?.();
281
+ }
282
+ /** Remove all active toasts immediately. */
283
+ clear() {
284
+ for (const toast of this.activeToasts) {
285
+ clearTimeout(toast.timer);
286
+ this.removeChild(toast.text);
287
+ }
288
+ this.activeToasts = [];
289
+ this.renderCallback?.();
290
+ }
291
+ dismiss(text) {
292
+ const idx = this.activeToasts.findIndex((t) => t.text === text);
293
+ if (idx !== -1) {
294
+ clearTimeout(this.activeToasts[idx].timer);
295
+ this.activeToasts.splice(idx, 1);
296
+ this.removeChild(text);
297
+ this.renderCallback?.();
298
+ }
299
+ }
300
+ };
232
301
 
233
302
  // src/commands.ts
234
303
  var commands = [
235
304
  { name: "help", description: "Show available commands" },
236
305
  { name: "login", description: "Log in (re-authenticate)" },
237
306
  { name: "register", description: "Register a new account" },
238
- { name: "workspace", description: "Switch workspace (or show selector)" },
307
+ { name: "create", description: "Create a new workspace: /create <name>" },
308
+ { name: "workspace", description: "Switch workspace: /workspace <id>" },
239
309
  { name: "workspaces", description: "List all workspaces" },
310
+ { name: "contacts", description: "List contacts (type @name to DM)" },
240
311
  { name: "docs", description: "List documents in current workspace" },
241
312
  { name: "conversations", description: "List conversations" },
242
313
  { name: "new", description: "Start fresh conversation (clear threading)" },
@@ -251,6 +322,10 @@ function formatHelpText() {
251
322
  "",
252
323
  ...lines,
253
324
  "",
325
+ "Direct messages:",
326
+ " @name \u2014 Switch to DM channel with a contact",
327
+ " @arbi \u2014 Switch back to AI chat",
328
+ "",
254
329
  "Keyboard shortcuts:",
255
330
  " Ctrl+N \u2014 New conversation",
256
331
  " Ctrl+W \u2014 Switch workspace",
@@ -425,12 +500,18 @@ async function handleCommand(tui, input2) {
425
500
  case "register":
426
501
  await handleRegister(tui);
427
502
  return true;
503
+ case "create":
504
+ await handleCreateWorkspace(tui, args.join(" "));
505
+ return true;
428
506
  case "workspace":
429
507
  await handleWorkspaceSwitch(tui, args[0]);
430
508
  return true;
431
509
  case "workspaces":
432
510
  await handleListWorkspaces(tui);
433
511
  return true;
512
+ case "contacts":
513
+ await handleListContacts(tui);
514
+ return true;
434
515
  case "docs":
435
516
  await handleListDocs(tui);
436
517
  return true;
@@ -504,6 +585,41 @@ async function handleRegister(tui) {
504
585
  tui.requestRender();
505
586
  }
506
587
  }
588
+ async function handleCreateWorkspace(tui, name) {
589
+ if (!tui.authContext) {
590
+ tui.chatLog.addSystem("Not authenticated. Use /login first.", "error");
591
+ tui.requestRender();
592
+ return;
593
+ }
594
+ if (!name.trim()) {
595
+ tui.chatLog.addSystem("Usage: /create <workspace name>", "warning");
596
+ tui.requestRender();
597
+ return;
598
+ }
599
+ try {
600
+ tui.chatLog.addSystem(`Creating workspace "${name}"...`);
601
+ tui.requestRender();
602
+ const ws = await core.workspaces.createWorkspace(tui.authContext.arbi, name.trim());
603
+ const { selectWorkspaceById } = await import('@arbidocs/core');
604
+ const selected = await selectWorkspaceById(
605
+ tui.authContext.arbi,
606
+ ws.external_id,
607
+ tui.authContext.loginResult.serverSessionKey,
608
+ tui.store.requireCredentials().signingPrivateKeyBase64
609
+ );
610
+ tui.state.workspaceId = selected.external_id;
611
+ tui.state.workspaceName = selected.name;
612
+ tui.state.conversationMessageId = null;
613
+ tui.store.updateConfig({ selectedWorkspaceId: selected.external_id });
614
+ await tui.refreshWorkspaceContext();
615
+ tui.chatLog.addSystem(`Created and switched to workspace: ${colors.accentBold(selected.name)}`);
616
+ tui.requestRender();
617
+ } catch (err) {
618
+ const msg = err instanceof Error ? err.message : String(err);
619
+ tui.chatLog.addSystem(`Failed to create workspace: ${msg}`, "error");
620
+ tui.requestRender();
621
+ }
622
+ }
507
623
  async function handleWorkspaceSwitch(tui, workspaceId) {
508
624
  if (!tui.authContext) {
509
625
  tui.chatLog.addSystem("Not authenticated. Please restart and log in.", "error");
@@ -580,6 +696,45 @@ async function handleListDocs(tui) {
580
696
  tui.requestRender();
581
697
  }
582
698
  }
699
+ async function handleListContacts(tui) {
700
+ if (!tui.authContext) {
701
+ tui.chatLog.addSystem("Not authenticated. Use /login first.", "error");
702
+ tui.requestRender();
703
+ return;
704
+ }
705
+ try {
706
+ const contactList = await core.contacts.listContacts(tui.authContext.arbi);
707
+ const registered = contactList.filter((c) => c.status === "registered");
708
+ const invited = contactList.filter((c) => c.status !== "registered");
709
+ if (registered.length === 0 && invited.length === 0) {
710
+ tui.chatLog.addSystem("No contacts. Use the web app to add contacts.");
711
+ } else {
712
+ const lines = [];
713
+ if (registered.length > 0) {
714
+ lines.push(`Contacts (${registered.length}):`, "");
715
+ for (const c of registered) {
716
+ const name = c.user ? `${c.user.given_name} ${c.user.family_name}`.trim() : "";
717
+ const nameStr = name ? colors.muted(` (${name})`) : "";
718
+ lines.push(` ${c.email}${nameStr}`);
719
+ }
720
+ }
721
+ if (invited.length > 0) {
722
+ if (lines.length > 0) lines.push("");
723
+ lines.push(`Pending invitations (${invited.length}):`);
724
+ for (const c of invited) {
725
+ lines.push(` ${c.email} \u2014 ${colors.muted(c.status)}`);
726
+ }
727
+ }
728
+ lines.push("", colors.muted("Type @name to start a DM with a registered contact."));
729
+ tui.chatLog.addSystem(lines.join("\n"));
730
+ }
731
+ tui.requestRender();
732
+ } catch (err) {
733
+ const msg = err instanceof Error ? err.message : String(err);
734
+ tui.chatLog.addSystem(`Failed to list contacts: ${msg}`, "error");
735
+ tui.requestRender();
736
+ }
737
+ }
583
738
  async function handleListConversations(tui) {
584
739
  if (!tui.authContext || !tui.state.workspaceId) {
585
740
  tui.chatLog.addSystem("No workspace selected. Use /workspace <id> first.", "warning");
@@ -614,7 +769,8 @@ function handleStatus(tui) {
614
769
  `Workspace: ${state.workspaceName ? colors.accent(state.workspaceName) : colors.muted("none")}`,
615
770
  `Workspace ID: ${state.workspaceId ?? colors.muted("none")}`,
616
771
  `Conversation: ${state.conversationMessageId ? colors.muted(state.conversationMessageId) : colors.muted("new")}`,
617
- `Status: ${state.activityStatus}`
772
+ `Status: ${state.activityStatus}`,
773
+ `WebSocket: ${tui.wsConnected ? colors.success("connected") : colors.muted("disconnected")}`
618
774
  ];
619
775
  tui.chatLog.addSystem(lines.join("\n"));
620
776
  tui.requestRender();
@@ -662,6 +818,263 @@ async function streamResponse(tui, response) {
662
818
  throw err;
663
819
  }
664
820
  }
821
+ function deriveEncryptionKeypair(signingPrivateKeyBase64) {
822
+ const signingPrivateKey = sdk.base64ToBytes(signingPrivateKeyBase64);
823
+ const ed25519PublicKey = signingPrivateKey.slice(32, 64);
824
+ return sdk.deriveEncryptionKeypairFromSigning({
825
+ publicKey: ed25519PublicKey,
826
+ secretKey: signingPrivateKey
827
+ });
828
+ }
829
+ async function resolveRecipient(tui, query) {
830
+ if (!tui.authContext) {
831
+ tui.chatLog.addSystem("Not authenticated. Use /login first.", "error");
832
+ tui.requestRender();
833
+ return null;
834
+ }
835
+ const queryLower = query.toLowerCase();
836
+ try {
837
+ const contactList = await core.contacts.listContacts(tui.authContext.arbi);
838
+ const registered = contactList.filter(
839
+ (c) => c.status === "registered" && c.user?.encryption_public_key
840
+ );
841
+ const matches = registered.filter((c) => {
842
+ const emailPrefix = c.email.split("@")[0]?.toLowerCase();
843
+ const givenName = c.user?.given_name?.toLowerCase();
844
+ return emailPrefix === queryLower || givenName === queryLower;
845
+ });
846
+ if (matches.length === 0) {
847
+ tui.chatLog.addSystem(
848
+ `No registered contact matching "${query}". Use /contacts to see available contacts.`,
849
+ "warning"
850
+ );
851
+ tui.requestRender();
852
+ return null;
853
+ }
854
+ if (matches.length > 1) {
855
+ const names = matches.map((c) => ` ${c.email} (${c.user?.given_name ?? ""} ${c.user?.family_name ?? ""})`).join("\n");
856
+ tui.chatLog.addSystem(
857
+ `Ambiguous match for "${query}". Be more specific:
858
+ ${names}`,
859
+ "warning"
860
+ );
861
+ tui.requestRender();
862
+ return null;
863
+ }
864
+ const contact = matches[0];
865
+ const user = contact.user;
866
+ return {
867
+ external_id: user.external_id,
868
+ email: contact.email,
869
+ encryption_public_key: user.encryption_public_key,
870
+ given_name: user.given_name,
871
+ family_name: user.family_name
872
+ };
873
+ } catch (err) {
874
+ const msg = err instanceof Error ? err.message : String(err);
875
+ tui.chatLog.addSystem(`Failed to resolve contact: ${msg}`, "error");
876
+ tui.requestRender();
877
+ return null;
878
+ }
879
+ }
880
+ async function handleChannelSwitch(tui, input2) {
881
+ const query = input2.slice(1).trim();
882
+ if (!query) {
883
+ tui.chatLog.addSystem("Usage: @username to switch to DM, @arbi to switch back.", "warning");
884
+ tui.requestRender();
885
+ return;
886
+ }
887
+ if (query.toLowerCase() === "arbi") {
888
+ switchToArbi(tui);
889
+ return;
890
+ }
891
+ const user = await resolveRecipient(tui, query);
892
+ if (!user) return;
893
+ await switchToDmChannel(tui, user);
894
+ }
895
+ async function switchToDmChannel(tui, user) {
896
+ if (!tui.authContext || !tui.encryptionKeys) {
897
+ tui.chatLog.addSystem("Not authenticated or encryption not initialized.", "error");
898
+ tui.requestRender();
899
+ return;
900
+ }
901
+ tui.currentDmChannel = { user };
902
+ tui.updateHeader();
903
+ tui.chatLog.clearMessages();
904
+ tui.chatLog.addSystem(
905
+ `Switched to DM with ${colors.accent(user.email)}. Type @arbi to switch back.`
906
+ );
907
+ tui.requestRender();
908
+ await loadDmHistory(tui, user);
909
+ }
910
+ function switchToArbi(tui) {
911
+ if (!tui.currentDmChannel) {
912
+ tui.chatLog.addSystem("Already in AI chat mode.", "info");
913
+ tui.requestRender();
914
+ return;
915
+ }
916
+ tui.currentDmChannel = null;
917
+ tui.updateHeader();
918
+ tui.chatLog.clearMessages();
919
+ tui.chatLog.addSystem("Switched back to AI chat.");
920
+ tui.requestRender();
921
+ }
922
+ async function loadDmHistory(tui, user) {
923
+ if (!tui.authContext || !tui.encryptionKeys) return;
924
+ const myExtId = tui.authContext.loginResult.userExtId;
925
+ try {
926
+ const allDms = await core.dm.listDMs(tui.authContext.arbi);
927
+ const conversation = allDms.filter(
928
+ (msg) => msg.type === "user_message" && (msg.sender.external_id === user.external_id && msg.recipient.external_id === myExtId || msg.sender.external_id === myExtId && msg.recipient.external_id === user.external_id)
929
+ );
930
+ conversation.sort(
931
+ (a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
932
+ );
933
+ const unreadIds = conversation.filter((msg) => !msg.read && msg.sender.external_id === user.external_id).map((msg) => msg.external_id);
934
+ if (unreadIds.length > 0) {
935
+ core.dm.markRead(tui.authContext.arbi, unreadIds).catch(() => {
936
+ });
937
+ }
938
+ for (const msg of conversation) {
939
+ const isSent = msg.sender.external_id === myExtId;
940
+ const plaintext = await decryptNotification(msg, myExtId, tui.encryptionKeys, user);
941
+ if (plaintext) {
942
+ displayDmMessage(tui, plaintext, isSent, user.email);
943
+ }
944
+ }
945
+ tui.requestRender();
946
+ } catch (err) {
947
+ const errMsg = err instanceof Error ? err.message : String(err);
948
+ tui.chatLog.addSystem(`Failed to load DM history: ${errMsg}`, "error");
949
+ tui.requestRender();
950
+ }
951
+ }
952
+ async function sendEncryptedDm(tui, plaintext) {
953
+ if (!tui.authContext || !tui.encryptionKeys || !tui.currentDmChannel) {
954
+ tui.chatLog.addSystem("Cannot send DM \u2014 not in a DM channel.", "error");
955
+ tui.requestRender();
956
+ return;
957
+ }
958
+ const recipient = tui.currentDmChannel.user;
959
+ try {
960
+ const encrypted = await sdk.encryptMessage(
961
+ plaintext,
962
+ recipient.encryption_public_key,
963
+ tui.encryptionKeys.secretKey
964
+ );
965
+ await core.dm.sendDM(tui.authContext.arbi, [
966
+ { recipient_ext_id: recipient.external_id, content: encrypted }
967
+ ]);
968
+ displayDmMessage(tui, plaintext, true, recipient.email);
969
+ tui.requestRender();
970
+ } catch (err) {
971
+ const msg = err instanceof Error ? err.message : String(err);
972
+ tui.chatLog.addSystem(`Failed to send DM: ${msg}`, "error");
973
+ tui.requestRender();
974
+ }
975
+ }
976
+ async function handleIncomingDm(tui, msg) {
977
+ if (!tui.currentDmChannel || !tui.encryptionKeys || !tui.authContext) {
978
+ return false;
979
+ }
980
+ const myExtId = tui.authContext.loginResult.userExtId;
981
+ const channelUserId = tui.currentDmChannel.user.external_id;
982
+ if (msg.sender.external_id !== channelUserId) {
983
+ return false;
984
+ }
985
+ const plaintext = await decryptNotification(
986
+ msg,
987
+ myExtId,
988
+ tui.encryptionKeys,
989
+ tui.currentDmChannel.user
990
+ );
991
+ if (plaintext) {
992
+ displayDmMessage(tui, plaintext, false, msg.sender.email);
993
+ tui.requestRender();
994
+ core.dm.markRead(tui.authContext.arbi, [msg.external_id]).catch(() => {
995
+ });
996
+ }
997
+ return true;
998
+ }
999
+ async function decryptNotification(notification, _myExtId, encryptionKeyPair, otherUser) {
1000
+ if (!notification.content) return null;
1001
+ try {
1002
+ return await sdk.decryptMessage(
1003
+ notification.content,
1004
+ otherUser.encryption_public_key,
1005
+ encryptionKeyPair.secretKey
1006
+ );
1007
+ } catch {
1008
+ return "[decryption failed]";
1009
+ }
1010
+ }
1011
+ function displayDmMessage(tui, text, isSent, senderEmail) {
1012
+ if (isSent) {
1013
+ tui.chatLog.addUser(text);
1014
+ } else {
1015
+ tui.chatLog.addDm(senderEmail, text);
1016
+ }
1017
+ }
1018
+
1019
+ // src/ws-handler.ts
1020
+ var DURATION_SHORT = 3e3;
1021
+ var DURATION_DEFAULT = 5e3;
1022
+ var DURATION_LONG = 8e3;
1023
+ function isNotification(msg) {
1024
+ return "sender" in msg && "recipient" in msg;
1025
+ }
1026
+ async function handleMessage(msg, toasts, tui) {
1027
+ if (sdk.isMessageType(msg, "task_update")) {
1028
+ handleTaskUpdate(msg, toasts);
1029
+ } else if (sdk.isMessageType(msg, "batch_complete")) {
1030
+ handleBatchComplete(msg, toasts);
1031
+ } else if (sdk.isMessageType(msg, "error")) {
1032
+ toasts.show(msg.message, "error", DURATION_LONG);
1033
+ } else if (isNotification(msg)) {
1034
+ if (msg.type === "user_message" && tui) {
1035
+ const handled = await handleIncomingDm(tui, msg);
1036
+ if (handled) return;
1037
+ }
1038
+ const text = msg.content ?? `Notification: ${msg.type}`;
1039
+ toasts.show(text, "info", DURATION_DEFAULT);
1040
+ }
1041
+ }
1042
+ function handleTaskUpdate(msg, toasts) {
1043
+ const progress = msg.progress > 0 ? ` (${Math.round(msg.progress)}%)` : "";
1044
+ const text = `\u{1F4C4} ${msg.file_name} \u2014 ${msg.status}${progress}`;
1045
+ let level = "info";
1046
+ let duration = DURATION_SHORT;
1047
+ if (msg.status === "completed") {
1048
+ level = "success";
1049
+ duration = DURATION_DEFAULT;
1050
+ } else if (msg.status === "failed") {
1051
+ level = "error";
1052
+ duration = DURATION_LONG;
1053
+ }
1054
+ toasts.show(text, level, duration);
1055
+ }
1056
+ function handleBatchComplete(msg, toasts) {
1057
+ const count = msg.doc_ext_ids.length;
1058
+ const text = `\u2713 Batch complete: ${msg.batch_type} \u2014 ${count} doc${count !== 1 ? "s" : ""}`;
1059
+ toasts.show(text, "success", DURATION_DEFAULT);
1060
+ }
1061
+ async function connectTuiWebSocket(options) {
1062
+ const { baseUrl, accessToken, toasts, tui } = options;
1063
+ try {
1064
+ const connection = await core.connectWebSocket({
1065
+ baseUrl,
1066
+ accessToken,
1067
+ onMessage: (msg) => handleMessage(msg, toasts, tui ?? null),
1068
+ onClose: (_code, _reason) => {
1069
+ toasts.show("WebSocket disconnected", "warning", DURATION_DEFAULT);
1070
+ }
1071
+ });
1072
+ return connection;
1073
+ } catch {
1074
+ toasts.show("WebSocket connection failed", "warning", DURATION_DEFAULT);
1075
+ return null;
1076
+ }
1077
+ }
665
1078
 
666
1079
  // src/tui.ts
667
1080
  var ArbiTui = class {
@@ -669,6 +1082,8 @@ var ArbiTui = class {
669
1082
  header;
670
1083
  /** The chat message log — public so command handlers can add messages. */
671
1084
  chatLog;
1085
+ /** Toast notifications from WebSocket events. */
1086
+ toastContainer;
672
1087
  /** The input editor. */
673
1088
  editor;
674
1089
  /** Application state — public so handlers can read/write it. */
@@ -679,6 +1094,12 @@ var ArbiTui = class {
679
1094
  workspaceContext = null;
680
1095
  /** Config store for persistence. */
681
1096
  store;
1097
+ /** Active WebSocket connection (null when not connected). */
1098
+ wsConnection = null;
1099
+ /** X25519 encryption keypair derived from signing key (null until login). */
1100
+ encryptionKeyPair = null;
1101
+ /** Current DM channel (null = AI chat mode). */
1102
+ dmChannel = null;
682
1103
  constructor(store) {
683
1104
  this.store = store;
684
1105
  this.state = {
@@ -691,6 +1112,8 @@ var ArbiTui = class {
691
1112
  this.tui = new piTui.TUI(new piTui.ProcessTerminal());
692
1113
  this.header = new piTui.Text(formatHeader(null, "starting..."), 1, 0);
693
1114
  this.chatLog = new ChatLog();
1115
+ this.toastContainer = new ToastContainer();
1116
+ this.toastContainer.setRenderCallback(() => this.tui.requestRender());
694
1117
  this.editor = new ArbiEditor(this.tui);
695
1118
  this.editor.setAutocompleteProvider(new piTui.CombinedAutocompleteProvider(commands));
696
1119
  this.editor.onSubmit = (text) => this.handleSubmit(text);
@@ -701,6 +1124,7 @@ var ArbiTui = class {
701
1124
  this.editor.onCtrlN = () => this.handleSubmit("/new");
702
1125
  this.tui.addChild(this.header);
703
1126
  this.tui.addChild(new piTui.Spacer(1));
1127
+ this.tui.addChild(this.toastContainer);
704
1128
  this.tui.addChild(this.chatLog);
705
1129
  this.tui.addChild(this.editor);
706
1130
  this.tui.setFocus(this.editor);
@@ -714,6 +1138,9 @@ var ArbiTui = class {
714
1138
  }
715
1139
  /** Gracefully shut down the TUI and exit. */
716
1140
  shutdown() {
1141
+ this.wsConnection?.close();
1142
+ this.wsConnection = null;
1143
+ this.toastContainer.clear();
717
1144
  this.tui.stop();
718
1145
  process.exit(0);
719
1146
  }
@@ -733,6 +1160,7 @@ var ArbiTui = class {
733
1160
  this.tui = new piTui.TUI(new piTui.ProcessTerminal());
734
1161
  this.tui.addChild(this.header);
735
1162
  this.tui.addChild(new piTui.Spacer(1));
1163
+ this.tui.addChild(this.toastContainer);
736
1164
  this.tui.addChild(this.chatLog);
737
1165
  this.editor = new ArbiEditor(this.tui);
738
1166
  this.editor.setAutocompleteProvider(new piTui.CombinedAutocompleteProvider(commands));
@@ -757,6 +1185,9 @@ var ArbiTui = class {
757
1185
  setAuthContext(ctx) {
758
1186
  this.authContext = ctx;
759
1187
  this.state.isAuthenticated = true;
1188
+ this.encryptionKeyPair = deriveEncryptionKeypair(
1189
+ this.store.requireCredentials().signingPrivateKeyBase64
1190
+ );
760
1191
  this.updateHeader();
761
1192
  }
762
1193
  /** Set workspace context after workspace selection. */
@@ -764,6 +1195,7 @@ var ArbiTui = class {
764
1195
  this.workspaceContext = ctx;
765
1196
  this.state.workspaceId = ctx.workspaceId;
766
1197
  this.updateHeader();
1198
+ this.connectWebSocket();
767
1199
  }
768
1200
  /** Refresh workspace context (after switching workspaces). */
769
1201
  async refreshWorkspaceContext() {
@@ -773,15 +1205,42 @@ var ArbiTui = class {
773
1205
  this.workspaceContext = ctx;
774
1206
  this.updateHeader();
775
1207
  }
1208
+ /** Whether the WebSocket is currently connected. */
1209
+ get wsConnected() {
1210
+ return this.wsConnection !== null;
1211
+ }
1212
+ /** Connect (or reconnect) WebSocket for real-time notifications. */
1213
+ connectWebSocket() {
1214
+ if (!this.workspaceContext) return;
1215
+ this.wsConnection?.close();
1216
+ this.wsConnection = null;
1217
+ const { config, accessToken } = this.workspaceContext;
1218
+ connectTuiWebSocket({
1219
+ baseUrl: config.baseUrl,
1220
+ accessToken,
1221
+ toasts: this.toastContainer,
1222
+ tui: this
1223
+ }).then((conn) => {
1224
+ this.wsConnection = conn;
1225
+ });
1226
+ }
776
1227
  // ── Input handling ─────────────────────────────────────────────────────
777
1228
  async handleSubmit(text) {
778
1229
  const trimmed = text.trim();
779
1230
  if (!trimmed) return;
1231
+ if (trimmed.startsWith("@")) {
1232
+ await handleChannelSwitch(this, trimmed);
1233
+ return;
1234
+ }
780
1235
  if (trimmed.startsWith("/")) {
781
1236
  const handled = await handleCommand(this, trimmed);
782
1237
  if (handled) return;
783
1238
  }
784
- await this.sendMessage(trimmed);
1239
+ if (this.dmChannel) {
1240
+ await sendEncryptedDm(this, trimmed);
1241
+ } else {
1242
+ await this.sendMessage(trimmed);
1243
+ }
785
1244
  }
786
1245
  handleAbort() {
787
1246
  if (this.state.activityStatus === "streaming") {
@@ -835,9 +1294,26 @@ var ArbiTui = class {
835
1294
  this.requestRender();
836
1295
  }
837
1296
  // ── UI Updates ─────────────────────────────────────────────────────────
1297
+ /** Update the header bar — public so dm-handler can call it. */
838
1298
  updateHeader() {
839
1299
  const statusText = this.state.activityStatus === "idle" ? colors.success("ready") : this.state.activityStatus === "streaming" ? colors.warning("streaming...") : this.state.activityStatus === "sending" ? colors.warning("sending...") : colors.error("error");
840
- this.header.setText(formatHeader(this.state.workspaceName, statusText));
1300
+ if (this.dmChannel) {
1301
+ this.header.setText(formatHeader(`DM: ${this.dmChannel.user.email}`, statusText));
1302
+ } else {
1303
+ this.header.setText(formatHeader(this.state.workspaceName, statusText));
1304
+ }
1305
+ }
1306
+ // ── DM channel accessors (used by dm-handler) ────────────────────────────
1307
+ /** Current DM channel (null = AI chat mode). */
1308
+ get currentDmChannel() {
1309
+ return this.dmChannel;
1310
+ }
1311
+ set currentDmChannel(ch) {
1312
+ this.dmChannel = ch;
1313
+ }
1314
+ /** Encryption keypair for E2E DM encryption. */
1315
+ get encryptionKeys() {
1316
+ return this.encryptionKeyPair;
841
1317
  }
842
1318
  };
843
1319
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/theme/theme.ts","../src/theme/syntax-theme.ts","../src/components/assistant-message.ts","../src/components/user-message.ts","../src/components/system-message.ts","../src/components/agent-step.ts","../src/components/chat-log.ts","../src/components/arbi-editor.ts","../src/commands.ts","../src/auth.ts","../src/command-handlers.ts","../src/event-handlers.ts","../src/tui.ts","../src/index.ts"],"names":["chalk","Container","Text","Markdown","Spacer","Editor","matchesKey","Key","input","password","createArbiClient","workspaces","ws","select","resolveAuth","confirm","resolveWorkspace","documents","conversations","streamSSE","TUI","ProcessTerminal","CombinedAutocompleteProvider","assistant","Command","FileConfigStore"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * ARBI TUI theme — color palette and component styling functions.\n *\n * Uses chalk for ANSI color output. All theme values are functions\n * that wrap text in the appropriate escape sequences.\n */\n\nimport chalk from 'chalk'\nimport type { MarkdownTheme, EditorTheme, SelectListTheme } from '@mariozechner/pi-tui'\n\n// ── Color palette ──────────────────────────────────────────────────────────\n\nexport const colors = {\n /** Primary accent — teal/cyan used for headings, prompts, highlights */\n accent: chalk.cyan,\n accentBold: chalk.bold.cyan,\n\n /** Secondary accent — blue for links and info */\n secondary: chalk.blue,\n\n /** Muted text — dim gray for borders, metadata */\n muted: chalk.gray,\n mutedDim: chalk.dim.gray,\n\n /** Success — green for completed states */\n success: chalk.green,\n\n /** Warning — yellow for pending states, code */\n warning: chalk.yellow,\n\n /** Error — red for error messages */\n error: chalk.red,\n errorBold: chalk.bold.red,\n\n /** Text — default and bold */\n text: chalk.white,\n textBold: chalk.bold.white,\n\n /** User message styling */\n userLabel: chalk.bold.green,\n userText: chalk.white,\n\n /** Assistant message styling */\n assistantLabel: chalk.bold.cyan,\n\n /** System message styling */\n systemText: chalk.dim,\n systemInfo: chalk.dim.cyan,\n systemError: chalk.dim.red,\n systemWarning: chalk.dim.yellow,\n\n /** Agent step styling */\n stepPending: chalk.dim.yellow,\n stepComplete: chalk.dim.green,\n} as const\n\n// ── Background functions ───────────────────────────────────────────────────\n\nexport const bgFn = {\n /** Subtle background for user messages */\n user: (text: string) => chalk.bgGray(text),\n\n /** Background for agent steps */\n agentStep: (text: string) => text,\n} as const\n\n// ── Component themes ───────────────────────────────────────────────────────\n\nexport const selectListTheme: SelectListTheme = {\n selectedPrefix: (s: string) => colors.accent(s),\n selectedText: (s: string) => colors.text(s),\n description: (s: string) => colors.muted(s),\n scrollInfo: (s: string) => colors.muted(s),\n noMatch: (s: string) => colors.muted(s),\n}\n\nexport const editorTheme: EditorTheme = {\n borderColor: (s: string) => colors.accent(s),\n selectList: selectListTheme,\n}\n\nexport const markdownTheme: MarkdownTheme = {\n heading: (s: string) => colors.accentBold(s),\n link: (s: string) => chalk.underline.blue(s),\n linkUrl: (s: string) => colors.muted(s),\n code: (s: string) => colors.warning(s),\n codeBlock: (s: string) => colors.text(s),\n codeBlockBorder: (s: string) => colors.muted(s),\n quote: (s: string) => chalk.italic.gray(s),\n quoteBorder: (s: string) => colors.muted(s),\n hr: (s: string) => colors.muted(s),\n listBullet: (s: string) => colors.accent(s),\n bold: (s: string) => chalk.bold(s),\n italic: (s: string) => chalk.italic(s),\n strikethrough: (s: string) => chalk.strikethrough(s),\n underline: (s: string) => chalk.underline(s),\n}\n\n// ── Header / Footer helpers ────────────────────────────────────────────────\n\nexport function formatHeader(workspaceName: string | null, status: string): string {\n const app = colors.accentBold('ARBI')\n const ws = workspaceName ? colors.muted(` | ${workspaceName}`) : ''\n const st = colors.muted(` | ${status}`)\n return `${app}${ws}${st}`\n}\n\nexport function formatPrompt(): string {\n return colors.accent('> ')\n}\n","/**\n * Syntax highlighting theme for code blocks in Markdown.\n *\n * Provides a highlightCode function compatible with pi-tui's\n * MarkdownTheme.highlightCode option.\n */\n\nimport chalk from 'chalk'\n\n/**\n * Simple keyword-based syntax highlighting for code blocks.\n * Returns an array of styled lines.\n *\n * For a first version, we apply basic keyword coloring. This can be\n * upgraded to use a proper highlighter (e.g., cli-highlight) later.\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function highlightCode(code: string, lang?: string): string[] {\n const lines = code.split('\\n')\n\n return lines.map((line) => {\n // Highlight common keywords\n let styled = line\n // String literals (double and single quoted)\n .replace(/([\"'])(?:(?=(\\\\?))\\2.)*?\\1/g, (m) => chalk.green(m))\n // Numbers\n .replace(/\\b(\\d+\\.?\\d*)\\b/g, (m) => chalk.yellow(m))\n // Comments (// and #)\n .replace(/(\\/\\/.*|#.*)$/g, (m) => chalk.gray(m))\n\n // Keywords (applied after strings/comments to avoid conflicts in simple cases)\n const keywords =\n /\\b(const|let|var|function|return|if|else|for|while|import|export|from|class|extends|new|async|await|try|catch|throw|type|interface|enum|def|self|None|True|False|print)\\b/g\n styled = styled.replace(keywords, (m) => chalk.cyan(m))\n\n return styled\n })\n}\n","/**\n * AssistantMessage — streaming markdown response from the RAG assistant.\n *\n * Wraps pi-tui's Markdown component. Call setText() as tokens arrive\n * to update the rendered content incrementally.\n */\n\nimport { Container, Markdown, Text } from '@mariozechner/pi-tui'\nimport { markdownTheme, colors } from '../theme/theme.js'\nimport { highlightCode } from '../theme/syntax-theme.js'\n\nconst assistantMarkdownTheme = {\n ...markdownTheme,\n highlightCode,\n}\n\nexport class AssistantMessage extends Container {\n private markdown: Markdown\n private label: Text\n\n constructor() {\n super()\n this.label = new Text(colors.assistantLabel('Assistant'), 1, 0)\n this.markdown = new Markdown('', 1, 0, assistantMarkdownTheme)\n this.addChild(this.label)\n this.addChild(this.markdown)\n }\n\n /** Update the response text (called as tokens stream in). */\n setText(text: string): void {\n this.markdown.setText(text)\n }\n}\n","/**\n * UserMessage — displays a user's submitted question.\n *\n * Wraps pi-tui's Markdown component with user-specific styling.\n */\n\nimport { Container, Markdown, Text } from '@mariozechner/pi-tui'\nimport { markdownTheme, colors } from '../theme/theme.js'\n\nexport class UserMessage extends Container {\n constructor(text: string) {\n super()\n const label = new Text(colors.userLabel('You'), 1, 0)\n const content = new Markdown(text, 1, 0, markdownTheme)\n this.addChild(label)\n this.addChild(content)\n }\n}\n","/**\n * SystemMessage — info, warning, and error messages.\n *\n * Wraps pi-tui's Text component with dim/accent styling.\n */\n\nimport { Text } from '@mariozechner/pi-tui'\nimport { colors } from '../theme/theme.js'\n\nexport type SystemMessageLevel = 'info' | 'warning' | 'error'\n\nexport class SystemMessage extends Text {\n constructor(message: string, level: SystemMessageLevel = 'info') {\n const styleFn =\n level === 'error'\n ? colors.systemError\n : level === 'warning'\n ? colors.systemWarning\n : colors.systemInfo\n super(styleFn(message), 1, 0)\n }\n}\n","/**\n * AgentStep — displays a single agent processing step.\n *\n * Shows the step focus/description with a status indicator.\n * Background changes from pending (yellow) to complete (green).\n */\n\nimport { Text } from '@mariozechner/pi-tui'\nimport { colors } from '../theme/theme.js'\n\nexport class AgentStep extends Text {\n private completed = false\n\n constructor(focus: string) {\n const styled = `${colors.stepPending('>')} ${colors.muted(focus)}`\n super(styled, 2, 0)\n }\n\n /** Mark this step as completed. */\n complete(): void {\n if (this.completed) return\n this.completed = true\n // Re-render would require knowing the original text — for now we leave styling as-is.\n // The step stays visible as context for the user.\n }\n}\n","/**\n * ChatLog — container managing the message list and streaming runs.\n *\n * Provides methods for adding user/system messages and managing\n * assistant streaming lifecycle (start → update → finalize).\n */\n\nimport { Container, Spacer } from '@mariozechner/pi-tui'\nimport { AssistantMessage } from './assistant-message.js'\nimport { UserMessage } from './user-message.js'\nimport { SystemMessage, type SystemMessageLevel } from './system-message.js'\nimport { AgentStep } from './agent-step.js'\n\nexport class ChatLog extends Container {\n /** Currently streaming assistant message (null when idle). */\n private activeAssistant: AssistantMessage | null = null\n\n /** Agent steps associated with the current streaming run. */\n private activeSteps: AgentStep[] = []\n\n /** Add a user message to the log. */\n addUser(text: string): void {\n this.addChild(new UserMessage(text))\n this.addChild(new Spacer(1))\n }\n\n /** Add a system/info/error message. */\n addSystem(message: string, level: SystemMessageLevel = 'info'): void {\n this.addChild(new SystemMessage(message, level))\n this.addChild(new Spacer(1))\n }\n\n /** Start a new assistant streaming response. */\n startAssistant(): void {\n this.activeAssistant = new AssistantMessage()\n this.activeSteps = []\n this.addChild(this.activeAssistant)\n }\n\n /** Update the active assistant message with accumulated text. */\n updateAssistant(text: string): void {\n this.activeAssistant?.setText(text)\n }\n\n /** Add an agent step to the current streaming run. */\n addAgentStep(focus: string): void {\n if (!this.activeAssistant) return\n const step = new AgentStep(focus)\n this.activeSteps.push(step)\n // Insert step before the assistant message content\n this.addChild(step)\n }\n\n /** Finalize the current assistant response. */\n finalizeAssistant(): void {\n for (const step of this.activeSteps) {\n step.complete()\n }\n this.activeAssistant = null\n this.activeSteps = []\n this.addChild(new Spacer(1))\n }\n}\n","/**\n * ArbiEditor — custom Editor with ARBI-specific keybindings.\n *\n * Extends pi-tui's Editor to add:\n * - Escape → abort active stream\n * - Ctrl+C → clear input / double-tap to exit\n * - Ctrl+D → exit\n * - Ctrl+W → workspace selector\n * - Ctrl+N → new conversation\n */\n\nimport { Editor, matchesKey, Key, type TUI } from '@mariozechner/pi-tui'\nimport { editorTheme } from '../theme/theme.js'\n\nexport class ArbiEditor extends Editor {\n /** Callback when Escape is pressed (abort streaming). */\n onEscape?: () => void\n\n /** Callback when Ctrl+C is pressed (clear or exit). */\n onCtrlC?: () => void\n\n /** Callback when Ctrl+D is pressed (exit). */\n onCtrlD?: () => void\n\n /** Callback when Ctrl+W is pressed (workspace selector). */\n onCtrlW?: () => void\n\n /** Callback when Ctrl+N is pressed (new conversation). */\n onCtrlN?: () => void\n\n /** Track Ctrl+C presses for double-tap exit. */\n private lastCtrlCTime = 0\n\n constructor(tui: TUI) {\n super(tui, editorTheme, { paddingX: 1 })\n }\n\n override handleInput(data: string): void {\n if (matchesKey(data, Key.escape)) {\n this.onEscape?.()\n return\n }\n\n if (matchesKey(data, Key.ctrl('c'))) {\n const now = Date.now()\n if (this.getText().trim()) {\n // First Ctrl+C with content: clear input\n this.setText('')\n this.lastCtrlCTime = now\n } else if (now - this.lastCtrlCTime < 1000) {\n // Double Ctrl+C within 1s: exit\n this.onCtrlC?.()\n } else {\n this.lastCtrlCTime = now\n this.onCtrlC?.()\n }\n return\n }\n\n if (matchesKey(data, Key.ctrl('d'))) {\n this.onCtrlD?.()\n return\n }\n\n if (matchesKey(data, Key.ctrl('w'))) {\n this.onCtrlW?.()\n return\n }\n\n if (matchesKey(data, Key.ctrl('n'))) {\n this.onCtrlN?.()\n return\n }\n\n // Pass all other input to the base Editor\n super.handleInput(data)\n }\n}\n","/**\n * Command registry — slash commands available in the TUI.\n *\n * Each command has a name, description, and optional argument hint.\n * Used for autocomplete and help display.\n */\n\nimport type { SlashCommand } from '@mariozechner/pi-tui'\n\nexport interface TuiCommand extends SlashCommand {\n name: string\n description: string\n}\n\nexport const commands: TuiCommand[] = [\n { name: 'help', description: 'Show available commands' },\n { name: 'login', description: 'Log in (re-authenticate)' },\n { name: 'register', description: 'Register a new account' },\n { name: 'workspace', description: 'Switch workspace (or show selector)' },\n { name: 'workspaces', description: 'List all workspaces' },\n { name: 'docs', description: 'List documents in current workspace' },\n { name: 'conversations', description: 'List conversations' },\n { name: 'new', description: 'Start fresh conversation (clear threading)' },\n { name: 'status', description: 'Show auth/workspace/connection status' },\n { name: 'exit', description: 'Exit TUI' },\n { name: 'quit', description: 'Exit TUI' },\n]\n\n/** Format all commands as a help string for display. */\nexport function formatHelpText(): string {\n const lines = commands\n .filter((c) => c.name !== 'quit') // Don't show duplicate exit/quit\n .map((c) => ` /${c.name} — ${c.description}`)\n return [\n 'Available commands:',\n '',\n ...lines,\n '',\n 'Keyboard shortcuts:',\n ' Ctrl+N — New conversation',\n ' Ctrl+W — Switch workspace',\n ' Ctrl+D — Exit',\n ' Escape — Abort streaming',\n ].join('\\n')\n}\n","/**\n * Authentication flows for the TUI.\n *\n * Handles login and registration using @inquirer/prompts for interactive input.\n * These flows run BEFORE the TUI takes over the terminal (pi-tui raw mode),\n * or after temporarily stopping the TUI.\n */\n\nimport 'fake-indexeddb/auto'\nimport { input, password, select, confirm } from '@inquirer/prompts'\nimport { createArbiClient } from '@arbidocs/sdk'\nimport type { ConfigStore, AuthContext } from '@arbidocs/core'\nimport { resolveAuth } from '@arbidocs/core'\n\n// ── Login ──────────────────────────────────────────────────────────────────\n\nexport interface LoginResult {\n authContext: AuthContext\n selectedWorkspaceId?: string\n selectedWorkspaceName?: string\n}\n\n/**\n * Interactive login flow. Prompts for email/password, authenticates,\n * and offers workspace selection.\n *\n * Must be called before the TUI starts (or after stopping it).\n */\nexport async function interactiveLogin(store: ConfigStore): Promise<LoginResult> {\n const config = store.requireConfig()\n\n const email = await input({ message: 'Email', validate: (v) => (v.trim() ? true : 'Required') })\n const pw = await password({\n message: 'Password',\n mask: '*',\n validate: (v) => (v ? true : 'Required'),\n })\n\n const arbi = createArbiClient({\n baseUrl: config.baseUrl,\n deploymentDomain: config.deploymentDomain,\n credentials: 'omit',\n })\n\n await arbi.crypto.initSodium()\n\n const loginResult = await arbi.auth.login({ email, password: pw })\n\n store.saveCredentials({\n email,\n signingPrivateKeyBase64: arbi.crypto.bytesToBase64(loginResult.signingPrivateKey),\n serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),\n })\n\n console.info(`Logged in as ${email}`)\n\n // Workspace selection\n const { data: workspaces } = await arbi.fetch.GET('/api/user/workspaces')\n const wsList = workspaces || []\n\n let selectedWorkspaceId: string | undefined\n let selectedWorkspaceName: string | undefined\n\n if (wsList.length === 1) {\n selectedWorkspaceId = wsList[0].external_id\n selectedWorkspaceName = wsList[0].name\n store.updateConfig({ selectedWorkspaceId })\n console.info(`Workspace: ${wsList[0].name}`)\n } else if (wsList.length > 1) {\n const choices = wsList.map((ws) => {\n const totalDocs = ws.shared_document_count + ws.private_document_count\n return {\n name: `${ws.name} (${totalDocs} docs)`,\n value: ws.external_id,\n description: ws.external_id,\n }\n })\n\n selectedWorkspaceId = await select({ message: 'Select workspace', choices })\n const ws = wsList.find((w) => w.external_id === selectedWorkspaceId)\n selectedWorkspaceName = ws?.name\n store.updateConfig({ selectedWorkspaceId })\n console.info(`Workspace: ${selectedWorkspaceName}`)\n } else {\n console.info('No workspaces found.')\n }\n\n // Re-resolve auth with saved credentials\n const authContext = await resolveAuth(store)\n\n return { authContext, selectedWorkspaceId, selectedWorkspaceName }\n}\n\n// ── Registration ───────────────────────────────────────────────────────────\n\n/**\n * Interactive registration flow. Prompts for email, verification code,\n * password, and name. Optionally logs in afterward.\n *\n * Must be called before the TUI starts (or after stopping it).\n */\nexport async function interactiveRegister(store: ConfigStore): Promise<LoginResult | null> {\n const config = store.requireConfig()\n\n const email = await input({ message: 'Email', validate: (v) => (v.trim() ? true : 'Required') })\n\n const arbi = createArbiClient({\n baseUrl: config.baseUrl,\n deploymentDomain: config.deploymentDomain,\n credentials: 'omit',\n })\n await arbi.crypto.initSodium()\n\n // Verification\n const codeMethod = await select({\n message: 'Verification method',\n choices: [\n { name: 'I have an invitation code', value: 'code' as const },\n { name: 'Send me a verification email', value: 'email' as const },\n ],\n })\n\n let verificationCode: string\n if (codeMethod === 'code') {\n verificationCode = await input({\n message: 'Invitation code',\n validate: (v) => (v.trim() ? true : 'Required'),\n })\n } else {\n console.info('Sending verification email...')\n const verifyResponse = await arbi.fetch.POST('/api/user/verify-email', {\n body: { email },\n })\n if (verifyResponse.error) {\n throw new Error(`Failed to send verification email: ${JSON.stringify(verifyResponse.error)}`)\n }\n console.info('Verification email sent. Check your inbox.')\n verificationCode = await input({\n message: 'Verification code',\n validate: (v) => (v.trim() ? true : 'Required'),\n })\n }\n\n // Password\n const pw = await password({\n message: 'Password',\n mask: '*',\n validate: (v) => (v ? true : 'Required'),\n })\n const confirmPw = await password({\n message: 'Confirm password',\n mask: '*',\n validate: (v) => (v ? true : 'Required'),\n })\n if (pw !== confirmPw) {\n throw new Error('Passwords do not match.')\n }\n\n // Name\n const firstName = (await input({ message: 'First name (optional)' })) || 'User'\n const lastName = (await input({ message: 'Last name (optional)' })) || ''\n\n // Register\n await arbi.auth.register({\n email,\n password: pw,\n verificationCode,\n firstName,\n lastName,\n })\n\n console.info(`\\nRegistered successfully as ${email}`)\n\n // Offer to log in\n const doLogin = await confirm({ message: 'Log in now?', default: true })\n if (doLogin) {\n return interactiveLogin(store)\n }\n\n return null\n}\n\n// ── Pre-flight auth check ──────────────────────────────────────────────────\n\n/**\n * Check if the user is authenticated. If not, offer to login or register.\n * Returns the auth context if successful, or exits the process.\n *\n * Called at startup before the TUI launches.\n */\nexport async function ensureAuthenticated(store: ConfigStore): Promise<LoginResult> {\n // Try existing credentials first\n try {\n const authContext = await resolveAuth(store)\n const config = store.requireConfig()\n return {\n authContext,\n selectedWorkspaceId: config.selectedWorkspaceId,\n }\n } catch {\n // Not authenticated — offer login/register\n console.info('Not authenticated.\\n')\n\n const action = await select({\n message: 'What would you like to do?',\n choices: [\n { name: 'Log in', value: 'login' as const },\n { name: 'Register a new account', value: 'register' as const },\n { name: 'Exit', value: 'exit' as const },\n ],\n })\n\n if (action === 'exit') {\n process.exit(0)\n }\n\n if (action === 'register') {\n const result = await interactiveRegister(store)\n if (!result) {\n console.info('Registration complete. Please restart to log in.')\n process.exit(0)\n }\n return result\n }\n\n // Login\n return interactiveLogin(store)\n }\n}\n","/**\n * Command handlers — dispatch logic for slash commands.\n *\n * Each handler receives the TUI context and performs its action,\n * typically displaying results in the chat log.\n */\n\nimport { workspaces, documents, conversations, resolveWorkspace } from '@arbidocs/core'\nimport type { ArbiTui } from './tui.js'\nimport { formatHelpText } from './commands.js'\nimport { interactiveLogin, interactiveRegister } from './auth.js'\nimport { colors } from './theme/theme.js'\n\n/** Dispatch a slash command. Returns true if handled. */\nexport async function handleCommand(tui: ArbiTui, input: string): Promise<boolean> {\n const trimmed = input.trim()\n if (!trimmed.startsWith('/')) return false\n\n const parts = trimmed.slice(1).split(/\\s+/)\n const cmd = parts[0]?.toLowerCase()\n const args = parts.slice(1)\n\n switch (cmd) {\n case 'help':\n tui.chatLog.addSystem(formatHelpText())\n tui.requestRender()\n return true\n\n case 'login':\n await handleLogin(tui)\n return true\n\n case 'register':\n await handleRegister(tui)\n return true\n\n case 'workspace':\n await handleWorkspaceSwitch(tui, args[0])\n return true\n\n case 'workspaces':\n await handleListWorkspaces(tui)\n return true\n\n case 'docs':\n await handleListDocs(tui)\n return true\n\n case 'conversations':\n await handleListConversations(tui)\n return true\n\n case 'new':\n handleNewConversation(tui)\n return true\n\n case 'status':\n handleStatus(tui)\n return true\n\n case 'exit':\n case 'quit':\n tui.shutdown()\n return true\n\n default:\n tui.chatLog.addSystem(\n `Unknown command: /${cmd}. Type /help for available commands.`,\n 'warning'\n )\n tui.requestRender()\n return true\n }\n}\n\nasync function handleLogin(tui: ArbiTui): Promise<void> {\n tui.chatLog.addSystem('Pausing TUI for login...')\n tui.requestRender()\n\n // Stop the TUI so @inquirer/prompts can use stdin\n tui.stopTui()\n\n try {\n const result = await interactiveLogin(tui.store)\n tui.setAuthContext(result.authContext)\n\n if (result.selectedWorkspaceId) {\n const wsCtx = await resolveWorkspace(tui.store, result.selectedWorkspaceId)\n tui.setWorkspaceContext(wsCtx)\n tui.state.workspaceName = result.selectedWorkspaceName ?? null\n }\n\n // Restart TUI\n tui.restartTui()\n tui.chatLog.addSystem('Logged in successfully.')\n tui.requestRender()\n } catch (err) {\n // Restart TUI even on error\n tui.restartTui()\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Login failed: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleRegister(tui: ArbiTui): Promise<void> {\n tui.chatLog.addSystem('Pausing TUI for registration...')\n tui.requestRender()\n\n // Stop the TUI so @inquirer/prompts can use stdin\n tui.stopTui()\n\n try {\n const result = await interactiveRegister(tui.store)\n\n if (result) {\n tui.setAuthContext(result.authContext)\n\n if (result.selectedWorkspaceId) {\n const wsCtx = await resolveWorkspace(tui.store, result.selectedWorkspaceId)\n tui.setWorkspaceContext(wsCtx)\n tui.state.workspaceName = result.selectedWorkspaceName ?? null\n }\n }\n\n // Restart TUI\n tui.restartTui()\n tui.chatLog.addSystem(\n result ? 'Registered and logged in.' : 'Registered. Use /login to log in.'\n )\n tui.requestRender()\n } catch (err) {\n // Restart TUI even on error\n tui.restartTui()\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Registration failed: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleWorkspaceSwitch(tui: ArbiTui, workspaceId?: string): Promise<void> {\n if (!tui.authContext) {\n tui.chatLog.addSystem('Not authenticated. Please restart and log in.', 'error')\n tui.requestRender()\n return\n }\n\n if (!workspaceId) {\n // Show workspace list for selection\n await handleListWorkspaces(tui)\n tui.chatLog.addSystem('Use /workspace <id> to switch.')\n tui.requestRender()\n return\n }\n\n try {\n tui.chatLog.addSystem(`Switching to workspace ${workspaceId}...`)\n tui.requestRender()\n\n const { selectWorkspaceById } = await import('@arbidocs/core')\n const ws = await selectWorkspaceById(\n tui.authContext.arbi,\n workspaceId,\n tui.authContext.loginResult.serverSessionKey,\n tui.store.requireCredentials().signingPrivateKeyBase64\n )\n\n // Update state\n tui.state.workspaceId = ws.external_id\n tui.state.workspaceName = ws.name\n tui.state.conversationMessageId = null\n\n // Update config\n tui.store.updateConfig({ selectedWorkspaceId: ws.external_id })\n\n // Refresh workspace context\n await tui.refreshWorkspaceContext()\n\n tui.chatLog.addSystem(`Switched to workspace: ${colors.accentBold(ws.name)}`)\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to switch workspace: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleListWorkspaces(tui: ArbiTui): Promise<void> {\n if (!tui.authContext) {\n tui.chatLog.addSystem('Not authenticated.', 'error')\n tui.requestRender()\n return\n }\n\n try {\n const wsList = await workspaces.listWorkspaces(tui.authContext.arbi)\n const lines = wsList.map((ws) => {\n const current = ws.external_id === tui.state.workspaceId ? colors.accent(' (current)') : ''\n return ` ${ws.external_id} ${ws.name}${current}`\n })\n tui.chatLog.addSystem(['Workspaces:', '', ...lines].join('\\n'))\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to list workspaces: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleListDocs(tui: ArbiTui): Promise<void> {\n if (!tui.authContext || !tui.state.workspaceId) {\n tui.chatLog.addSystem('No workspace selected. Use /workspace <id> first.', 'warning')\n tui.requestRender()\n return\n }\n\n try {\n const docs = await documents.listDocuments(tui.authContext.arbi, tui.state.workspaceId)\n if (docs.length === 0) {\n tui.chatLog.addSystem('No documents in this workspace.')\n } else {\n const lines = docs.map((d) => ` ${d.external_id} ${d.file_name ?? '(unnamed)'}`)\n tui.chatLog.addSystem([`Documents (${docs.length}):`, '', ...lines].join('\\n'))\n }\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to list documents: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleListConversations(tui: ArbiTui): Promise<void> {\n if (!tui.authContext || !tui.state.workspaceId) {\n tui.chatLog.addSystem('No workspace selected. Use /workspace <id> first.', 'warning')\n tui.requestRender()\n return\n }\n\n try {\n const convs = await conversations.listConversations(tui.authContext.arbi, tui.state.workspaceId)\n if (convs.length === 0) {\n tui.chatLog.addSystem('No conversations in this workspace.')\n } else {\n const lines = convs.map((c) => ` ${c.external_id} ${c.title ?? '(untitled)'}`)\n tui.chatLog.addSystem([`Conversations (${convs.length}):`, '', ...lines].join('\\n'))\n }\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to list conversations: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nfunction handleNewConversation(tui: ArbiTui): void {\n tui.state.conversationMessageId = null\n tui.store.clearChatSession()\n tui.chatLog.addSystem('Started new conversation.')\n tui.requestRender()\n}\n\nfunction handleStatus(tui: ArbiTui): void {\n const { state } = tui\n const lines = [\n `Authenticated: ${state.isAuthenticated ? colors.success('yes') : colors.error('no')}`,\n `Workspace: ${state.workspaceName ? colors.accent(state.workspaceName) : colors.muted('none')}`,\n `Workspace ID: ${state.workspaceId ?? colors.muted('none')}`,\n `Conversation: ${state.conversationMessageId ? colors.muted(state.conversationMessageId) : colors.muted('new')}`,\n `Status: ${state.activityStatus}`,\n ]\n tui.chatLog.addSystem(lines.join('\\n'))\n tui.requestRender()\n}\n","/**\n * SSE streaming event handler — wires @arbidocs/core streaming\n * into TUI component updates.\n */\n\nimport { streamSSE, type SSEStreamCallbacks, type SSEStreamResult } from '@arbidocs/core'\nimport type { ArbiTui } from './tui.js'\n\n/**\n * Stream an assistant response from the API into the TUI.\n *\n * 1. Creates an assistant message in the chat log\n * 2. Streams tokens into it via SSE callbacks\n * 3. Displays agent steps as they arrive\n * 4. Finalizes when complete\n *\n * Returns the full SSE result for caller to extract metadata.\n */\nexport async function streamResponse(tui: ArbiTui, response: Response): Promise<SSEStreamResult> {\n tui.chatLog.startAssistant()\n tui.state.activityStatus = 'streaming'\n tui.requestRender()\n\n let accumulated = ''\n\n const callbacks: SSEStreamCallbacks = {\n onStreamStart: (data) => {\n if (data.assistant_message_ext_id) {\n tui.state.conversationMessageId = data.assistant_message_ext_id as string\n }\n },\n\n onToken: (content) => {\n accumulated += content\n tui.chatLog.updateAssistant(accumulated)\n tui.requestRender()\n },\n\n onAgentStep: (data) => {\n const focus = data.focus || data.status || ''\n if (focus) {\n tui.chatLog.addAgentStep(focus)\n tui.requestRender()\n }\n },\n\n onError: (message) => {\n tui.chatLog.addSystem(`Stream error: ${message}`, 'error')\n tui.requestRender()\n },\n }\n\n try {\n const result = await streamSSE(response, callbacks)\n tui.chatLog.finalizeAssistant()\n tui.state.activityStatus = 'idle'\n tui.requestRender()\n return result\n } catch (err) {\n tui.chatLog.finalizeAssistant()\n tui.state.activityStatus = 'error'\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Streaming failed: ${msg}`, 'error')\n tui.requestRender()\n throw err\n }\n}\n","/**\n * ArbiTui — main orchestrator for the ARBI terminal UI.\n *\n * Manages state, component wiring, and lifecycle. Coordinates between\n * the editor input, chat log display, command dispatch, and SSE streaming.\n */\n\nimport {\n TUI,\n ProcessTerminal,\n Text,\n Spacer,\n CombinedAutocompleteProvider,\n} from '@mariozechner/pi-tui'\nimport {\n type AuthContext,\n type WorkspaceContext,\n type ConfigStore,\n assistant,\n documents,\n} from '@arbidocs/core'\nimport { ChatLog } from './components/chat-log.js'\nimport { ArbiEditor } from './components/arbi-editor.js'\nimport { handleCommand } from './command-handlers.js'\nimport { streamResponse } from './event-handlers.js'\nimport { commands } from './commands.js'\nimport { colors, formatHeader } from './theme/theme.js'\n\n// ── State ──────────────────────────────────────────────────────────────────\n\nexport interface TuiState {\n workspaceId: string | null\n workspaceName: string | null\n conversationMessageId: string | null\n activityStatus: 'idle' | 'sending' | 'streaming' | 'error'\n isAuthenticated: boolean\n}\n\n// ── Main TUI class ─────────────────────────────────────────────────────────\n\nexport class ArbiTui {\n private tui: TUI\n private header: Text\n\n /** The chat message log — public so command handlers can add messages. */\n readonly chatLog: ChatLog\n\n /** The input editor. */\n private editor: ArbiEditor\n\n /** Application state — public so handlers can read/write it. */\n state: TuiState\n\n /** Auth context from @arbidocs/core — set during init. */\n authContext: AuthContext | null = null\n\n /** Workspace context with tokens/headers — set when workspace is selected. */\n private workspaceContext: WorkspaceContext | null = null\n\n /** Config store for persistence. */\n readonly store: ConfigStore\n\n constructor(store: ConfigStore) {\n this.store = store\n\n this.state = {\n workspaceId: null,\n workspaceName: null,\n conversationMessageId: null,\n activityStatus: 'idle',\n isAuthenticated: false,\n }\n\n // Build TUI component tree\n this.tui = new TUI(new ProcessTerminal())\n\n // Header\n this.header = new Text(formatHeader(null, 'starting...'), 1, 0)\n\n // Chat log\n this.chatLog = new ChatLog()\n\n // Editor\n this.editor = new ArbiEditor(this.tui)\n this.editor.setAutocompleteProvider(new CombinedAutocompleteProvider(commands))\n\n // Wire editor callbacks\n this.editor.onSubmit = (text: string) => this.handleSubmit(text)\n this.editor.onEscape = () => this.handleAbort()\n this.editor.onCtrlC = () => this.shutdown()\n this.editor.onCtrlD = () => this.shutdown()\n this.editor.onCtrlW = () => this.handleSubmit('/workspaces')\n this.editor.onCtrlN = () => this.handleSubmit('/new')\n\n // Compose layout\n this.tui.addChild(this.header)\n this.tui.addChild(new Spacer(1))\n this.tui.addChild(this.chatLog)\n this.tui.addChild(this.editor)\n\n this.tui.setFocus(this.editor)\n }\n\n // ── Lifecycle ──────────────────────────────────────────────────────────\n\n /** Start the TUI event loop. */\n start(): void {\n this.tui.start()\n this.updateHeader()\n this.tui.requestRender()\n }\n\n /** Gracefully shut down the TUI and exit. */\n shutdown(): void {\n this.tui.stop()\n process.exit(0)\n }\n\n /**\n * Temporarily stop the TUI (releases terminal raw mode).\n * Used before interactive prompts that need stdin (login, register).\n */\n stopTui(): void {\n this.tui.stop()\n }\n\n /**\n * Restart the TUI after a stopTui() call.\n * Rebuilds the component tree with a fresh TUI instance since\n * pi-tui doesn't support stop/start cycling on the same instance.\n */\n restartTui(): void {\n this.tui = new TUI(new ProcessTerminal())\n\n // Re-compose layout\n this.tui.addChild(this.header)\n this.tui.addChild(new Spacer(1))\n this.tui.addChild(this.chatLog)\n\n // Create new editor (needs fresh TUI reference)\n this.editor = new ArbiEditor(this.tui)\n this.editor.setAutocompleteProvider(new CombinedAutocompleteProvider(commands))\n this.editor.onSubmit = (text: string) => this.handleSubmit(text)\n this.editor.onEscape = () => this.handleAbort()\n this.editor.onCtrlC = () => this.shutdown()\n this.editor.onCtrlD = () => this.shutdown()\n this.editor.onCtrlW = () => this.handleSubmit('/workspaces')\n this.editor.onCtrlN = () => this.handleSubmit('/new')\n\n this.tui.addChild(this.editor)\n this.tui.setFocus(this.editor)\n\n this.tui.start()\n this.updateHeader()\n this.tui.requestRender()\n }\n\n /** Request a render update. */\n requestRender(): void {\n this.tui.requestRender()\n }\n\n // ── Auth / Workspace ───────────────────────────────────────────────────\n\n /** Set authentication context after login. */\n setAuthContext(ctx: AuthContext): void {\n this.authContext = ctx\n this.state.isAuthenticated = true\n this.updateHeader()\n }\n\n /** Set workspace context after workspace selection. */\n setWorkspaceContext(ctx: WorkspaceContext): void {\n this.workspaceContext = ctx\n this.state.workspaceId = ctx.workspaceId\n // Workspace name will be set separately since WorkspaceContext doesn't include it\n this.updateHeader()\n }\n\n /** Refresh workspace context (after switching workspaces). */\n async refreshWorkspaceContext(): Promise<void> {\n if (!this.state.workspaceId || !this.authContext) return\n\n const { resolveWorkspace } = await import('@arbidocs/core')\n const ctx = await resolveWorkspace(this.store, this.state.workspaceId)\n this.workspaceContext = ctx\n this.updateHeader()\n }\n\n // ── Input handling ─────────────────────────────────────────────────────\n\n private async handleSubmit(text: string): Promise<void> {\n const trimmed = text.trim()\n if (!trimmed) return\n\n // Check for slash commands\n if (trimmed.startsWith('/')) {\n const handled = await handleCommand(this, trimmed)\n if (handled) return\n }\n\n // Regular message — send to assistant\n await this.sendMessage(trimmed)\n }\n\n private handleAbort(): void {\n if (this.state.activityStatus === 'streaming') {\n // TODO: implement AbortController for stream cancellation\n this.chatLog.addSystem('Abort requested (stream will complete current chunk).', 'warning')\n this.requestRender()\n }\n }\n\n // ── Messaging ──────────────────────────────────────────────────────────\n\n private async sendMessage(question: string): Promise<void> {\n if (!this.workspaceContext) {\n this.chatLog.addSystem(\n 'No workspace selected. Use /workspace <id> or /workspaces to choose one.',\n 'warning'\n )\n this.requestRender()\n return\n }\n\n // Display user message\n this.chatLog.addUser(question)\n this.state.activityStatus = 'sending'\n this.updateHeader()\n this.requestRender()\n\n try {\n // Get all docs in workspace for retrieval context\n const docs = await documents.listDocuments(\n this.workspaceContext.arbi,\n this.workspaceContext.workspaceId\n )\n const docIds = docs.map((d) => d.external_id as string)\n\n // Load chat session for conversation threading\n const session = this.store.getChatSession()\n const parentMessageExtId = this.state.conversationMessageId ?? session.lastMessageExtId\n\n // Query the assistant\n const response = await assistant.queryAssistant({\n baseUrl: this.workspaceContext.config.baseUrl,\n accessToken: this.workspaceContext.accessToken,\n workspaceKeyHeader: this.workspaceContext.workspaceKeyHeader,\n workspaceId: this.workspaceContext.workspaceId,\n question,\n docIds,\n parentMessageExtId,\n })\n\n // Stream the response into the chat log\n const result = await streamResponse(this, response)\n\n // Save conversation state for threading\n if (result.assistantMessageExtId) {\n this.state.conversationMessageId = result.assistantMessageExtId\n this.store.updateChatSession({ lastMessageExtId: result.assistantMessageExtId })\n }\n } catch (err) {\n this.state.activityStatus = 'error'\n const msg = err instanceof Error ? err.message : String(err)\n this.chatLog.addSystem(`Error: ${msg}`, 'error')\n }\n\n this.state.activityStatus = 'idle'\n this.updateHeader()\n this.requestRender()\n }\n\n // ── UI Updates ─────────────────────────────────────────────────────────\n\n private updateHeader(): void {\n const statusText =\n this.state.activityStatus === 'idle'\n ? colors.success('ready')\n : this.state.activityStatus === 'streaming'\n ? colors.warning('streaming...')\n : this.state.activityStatus === 'sending'\n ? colors.warning('sending...')\n : colors.error('error')\n\n this.header.setText(formatHeader(this.state.workspaceName, statusText))\n }\n}\n","/**\n * ARBI TUI — entry point\n *\n * Handles CLI argument parsing, authentication, and TUI launch.\n * Uses @arbidocs/core for auth and config, pi-tui for rendering.\n *\n * If not authenticated, offers interactive login/register before launching.\n *\n * Usage:\n * arbi-tui # Launch with default workspace\n * arbi-tui -w <workspace-id> # Launch with specific workspace\n */\n\n// Suppress SDK middleware logging\nconsole.debug = () => {}\nconst _origInfo = console.info\nconsole.info = (...args: unknown[]) => {\n if (typeof args[0] === 'string' && args[0].startsWith('[API]')) return\n _origInfo(...args)\n}\n\nimport { Command } from 'commander'\nimport { FileConfigStore, resolveWorkspace, workspaces } from '@arbidocs/core'\nimport { ArbiTui } from './tui.js'\nimport { ensureAuthenticated } from './auth.js'\n\nconst program = new Command()\n\nprogram\n .name('arbi-tui')\n .description('Interactive terminal UI for ARBI — chat with the RAG assistant')\n .version('0.1.0')\n .option('-w, --workspace <id>', 'Workspace ID to use')\n .action(async (opts: { workspace?: string }) => {\n const store = new FileConfigStore()\n\n // Ensure config exists\n try {\n store.requireConfig()\n } catch {\n console.error('Not configured. Run `arbi config set-url <url>` first.')\n process.exit(1)\n }\n\n // Authenticate — offers login/register if not already authenticated\n const { authContext, selectedWorkspaceId, selectedWorkspaceName } =\n await ensureAuthenticated(store)\n\n // Resolve workspace\n const workspaceId = opts.workspace || selectedWorkspaceId\n\n // Create and start TUI\n const tui = new ArbiTui(store)\n tui.setAuthContext(authContext)\n\n if (workspaceId) {\n try {\n const wsCtx = await resolveWorkspace(store, workspaceId)\n tui.setWorkspaceContext(wsCtx)\n\n // Get workspace name\n if (selectedWorkspaceName && workspaceId === selectedWorkspaceId) {\n tui.state.workspaceName = selectedWorkspaceName\n } else {\n const wsList = await workspaces.listWorkspaces(authContext.arbi)\n const ws = wsList.find((w) => w.external_id === workspaceId)\n if (ws) {\n tui.state.workspaceName = ws.name\n }\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to load workspace: ${msg}`, 'warning')\n tui.chatLog.addSystem('Use /workspaces to list and /workspace <id> to select.')\n }\n } else {\n tui.chatLog.addSystem(\n 'No workspace selected. Use /workspaces to list and /workspace <id> to select.'\n )\n }\n\n // Load chat session for conversation continuity\n const session = store.getChatSession()\n if (session.lastMessageExtId) {\n tui.state.conversationMessageId = session.lastMessageExtId\n }\n\n tui.chatLog.addSystem(\n 'Type a question to chat with the ARBI assistant. Use /help for commands.'\n )\n tui.start()\n })\n\nprogram.parse()\n"]}
1
+ {"version":3,"sources":["../src/theme/theme.ts","../src/theme/syntax-theme.ts","../src/components/assistant-message.ts","../src/components/user-message.ts","../src/components/system-message.ts","../src/components/agent-step.ts","../src/components/chat-log.ts","../src/components/arbi-editor.ts","../src/components/toast-container.ts","../src/commands.ts","../src/auth.ts","../src/command-handlers.ts","../src/event-handlers.ts","../src/dm-handler.ts","../src/ws-handler.ts","../src/tui.ts","../src/index.ts"],"names":["chalk","Container","Text","Markdown","Spacer","Editor","matchesKey","Key","input","password","createArbiClient","workspaces","ws","select","resolveAuth","confirm","resolveWorkspace","documents","contacts","conversations","streamSSE","base64ToBytes","deriveEncryptionKeypairFromSigning","dm","encryptMessage","decryptMessage","isMessageType","connectWebSocket","TUI","ProcessTerminal","CombinedAutocompleteProvider","assistant","Command","FileConfigStore"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * ARBI TUI theme — color palette and component styling functions.\n *\n * Uses chalk for ANSI color output. All theme values are functions\n * that wrap text in the appropriate escape sequences.\n */\n\nimport chalk from 'chalk'\nimport type { MarkdownTheme, EditorTheme, SelectListTheme } from '@mariozechner/pi-tui'\n\n// ── Color palette ──────────────────────────────────────────────────────────\n\nexport const colors = {\n /** Primary accent — teal/cyan used for headings, prompts, highlights */\n accent: chalk.cyan,\n accentBold: chalk.bold.cyan,\n\n /** Secondary accent — blue for links and info */\n secondary: chalk.blue,\n\n /** Muted text — dim gray for borders, metadata */\n muted: chalk.gray,\n mutedDim: chalk.dim.gray,\n\n /** Success — green for completed states */\n success: chalk.green,\n\n /** Warning — yellow for pending states, code */\n warning: chalk.yellow,\n\n /** Error — red for error messages */\n error: chalk.red,\n errorBold: chalk.bold.red,\n\n /** Text — default and bold */\n text: chalk.white,\n textBold: chalk.bold.white,\n\n /** User message styling */\n userLabel: chalk.bold.green,\n userText: chalk.white,\n\n /** Assistant message styling */\n assistantLabel: chalk.bold.cyan,\n\n /** System message styling */\n systemText: chalk.dim,\n systemInfo: chalk.dim.cyan,\n systemError: chalk.dim.red,\n systemWarning: chalk.dim.yellow,\n\n /** Agent step styling */\n stepPending: chalk.dim.yellow,\n stepComplete: chalk.dim.green,\n} as const\n\n// ── Background functions ───────────────────────────────────────────────────\n\nexport const bgFn = {\n /** Subtle background for user messages */\n user: (text: string) => chalk.bgGray(text),\n\n /** Background for agent steps */\n agentStep: (text: string) => text,\n} as const\n\n// ── Component themes ───────────────────────────────────────────────────────\n\nexport const selectListTheme: SelectListTheme = {\n selectedPrefix: (s: string) => colors.accent(s),\n selectedText: (s: string) => colors.text(s),\n description: (s: string) => colors.muted(s),\n scrollInfo: (s: string) => colors.muted(s),\n noMatch: (s: string) => colors.muted(s),\n}\n\nexport const editorTheme: EditorTheme = {\n borderColor: (s: string) => colors.accent(s),\n selectList: selectListTheme,\n}\n\nexport const markdownTheme: MarkdownTheme = {\n heading: (s: string) => colors.accentBold(s),\n link: (s: string) => chalk.underline.blue(s),\n linkUrl: (s: string) => colors.muted(s),\n code: (s: string) => colors.warning(s),\n codeBlock: (s: string) => colors.text(s),\n codeBlockBorder: (s: string) => colors.muted(s),\n quote: (s: string) => chalk.italic.gray(s),\n quoteBorder: (s: string) => colors.muted(s),\n hr: (s: string) => colors.muted(s),\n listBullet: (s: string) => colors.accent(s),\n bold: (s: string) => chalk.bold(s),\n italic: (s: string) => chalk.italic(s),\n strikethrough: (s: string) => chalk.strikethrough(s),\n underline: (s: string) => chalk.underline(s),\n}\n\n// ── Header / Footer helpers ────────────────────────────────────────────────\n\nexport function formatHeader(workspaceName: string | null, status: string): string {\n const app = colors.accentBold('ARBI')\n const ws = workspaceName ? colors.muted(` | ${workspaceName}`) : ''\n const st = colors.muted(` | ${status}`)\n return `${app}${ws}${st}`\n}\n\nexport function formatPrompt(): string {\n return colors.accent('> ')\n}\n","/**\n * Syntax highlighting theme for code blocks in Markdown.\n *\n * Provides a highlightCode function compatible with pi-tui's\n * MarkdownTheme.highlightCode option.\n */\n\nimport chalk from 'chalk'\n\n/**\n * Simple keyword-based syntax highlighting for code blocks.\n * Returns an array of styled lines.\n *\n * For a first version, we apply basic keyword coloring. This can be\n * upgraded to use a proper highlighter (e.g., cli-highlight) later.\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function highlightCode(code: string, lang?: string): string[] {\n const lines = code.split('\\n')\n\n return lines.map((line) => {\n // Highlight common keywords\n let styled = line\n // String literals (double and single quoted)\n .replace(/([\"'])(?:(?=(\\\\?))\\2.)*?\\1/g, (m) => chalk.green(m))\n // Numbers\n .replace(/\\b(\\d+\\.?\\d*)\\b/g, (m) => chalk.yellow(m))\n // Comments (// and #)\n .replace(/(\\/\\/.*|#.*)$/g, (m) => chalk.gray(m))\n\n // Keywords (applied after strings/comments to avoid conflicts in simple cases)\n const keywords =\n /\\b(const|let|var|function|return|if|else|for|while|import|export|from|class|extends|new|async|await|try|catch|throw|type|interface|enum|def|self|None|True|False|print)\\b/g\n styled = styled.replace(keywords, (m) => chalk.cyan(m))\n\n return styled\n })\n}\n","/**\n * AssistantMessage — streaming markdown response from the RAG assistant.\n *\n * Wraps pi-tui's Markdown component. Call setText() as tokens arrive\n * to update the rendered content incrementally.\n */\n\nimport { Container, Markdown, Text } from '@mariozechner/pi-tui'\nimport { markdownTheme, colors } from '../theme/theme.js'\nimport { highlightCode } from '../theme/syntax-theme.js'\n\nconst assistantMarkdownTheme = {\n ...markdownTheme,\n highlightCode,\n}\n\nexport class AssistantMessage extends Container {\n private markdown: Markdown\n private label: Text\n\n constructor() {\n super()\n this.label = new Text(colors.assistantLabel('Assistant'), 1, 0)\n this.markdown = new Markdown('', 1, 0, assistantMarkdownTheme)\n this.addChild(this.label)\n this.addChild(this.markdown)\n }\n\n /** Update the response text (called as tokens stream in). */\n setText(text: string): void {\n this.markdown.setText(text)\n }\n}\n","/**\n * UserMessage — displays a user's submitted question.\n *\n * Wraps pi-tui's Markdown component with user-specific styling.\n */\n\nimport { Container, Markdown, Text } from '@mariozechner/pi-tui'\nimport { markdownTheme, colors } from '../theme/theme.js'\n\nexport class UserMessage extends Container {\n constructor(text: string) {\n super()\n const label = new Text(colors.userLabel('You'), 1, 0)\n const content = new Markdown(text, 1, 0, markdownTheme)\n this.addChild(label)\n this.addChild(content)\n }\n}\n","/**\n * SystemMessage — info, warning, and error messages.\n *\n * Wraps pi-tui's Text component with dim/accent styling.\n */\n\nimport { Text } from '@mariozechner/pi-tui'\nimport { colors } from '../theme/theme.js'\n\nexport type SystemMessageLevel = 'info' | 'warning' | 'error'\n\nexport class SystemMessage extends Text {\n constructor(message: string, level: SystemMessageLevel = 'info') {\n const styleFn =\n level === 'error'\n ? colors.systemError\n : level === 'warning'\n ? colors.systemWarning\n : colors.systemInfo\n super(styleFn(message), 1, 0)\n }\n}\n","/**\n * AgentStep — displays a single agent processing step.\n *\n * Shows the step focus/description with a status indicator.\n * Background changes from pending (yellow) to complete (green).\n */\n\nimport { Text } from '@mariozechner/pi-tui'\nimport { colors } from '../theme/theme.js'\n\nexport class AgentStep extends Text {\n private completed = false\n\n constructor(focus: string) {\n const styled = `${colors.stepPending('>')} ${colors.muted(focus)}`\n super(styled, 2, 0)\n }\n\n /** Mark this step as completed. */\n complete(): void {\n if (this.completed) return\n this.completed = true\n // Re-render would require knowing the original text — for now we leave styling as-is.\n // The step stays visible as context for the user.\n }\n}\n","/**\n * ChatLog — container managing the message list and streaming runs.\n *\n * Provides methods for adding user/system messages and managing\n * assistant streaming lifecycle (start → update → finalize).\n */\n\nimport { Container, Spacer, Text } from '@mariozechner/pi-tui'\nimport { AssistantMessage } from './assistant-message.js'\nimport { UserMessage } from './user-message.js'\nimport { SystemMessage, type SystemMessageLevel } from './system-message.js'\nimport { AgentStep } from './agent-step.js'\nimport { colors } from '../theme/theme.js'\n\nexport class ChatLog extends Container {\n /** Currently streaming assistant message (null when idle). */\n private activeAssistant: AssistantMessage | null = null\n\n /** Agent steps associated with the current streaming run. */\n private activeSteps: AgentStep[] = []\n\n /** Add a user message to the log. */\n addUser(text: string): void {\n this.addChild(new UserMessage(text))\n this.addChild(new Spacer(1))\n }\n\n /** Add a system/info/error message. */\n addSystem(message: string, level: SystemMessageLevel = 'info'): void {\n this.addChild(new SystemMessage(message, level))\n this.addChild(new Spacer(1))\n }\n\n /** Add a received DM message (cyan label with sender email). */\n addDm(senderEmail: string, text: string): void {\n const container = new Container()\n const label = new Text(colors.accent(senderEmail), 1, 0)\n const content = new Text(colors.text(text), 1, 0)\n container.addChild(label)\n container.addChild(content)\n this.addChild(container)\n this.addChild(new Spacer(1))\n }\n\n /** Remove all messages from the chat log. */\n clearMessages(): void {\n this.activeAssistant = null\n this.activeSteps = []\n // Remove all children by iterating backwards\n while (this.children.length > 0) {\n this.removeChild(this.children[this.children.length - 1])\n }\n }\n\n /** Start a new assistant streaming response. */\n startAssistant(): void {\n this.activeAssistant = new AssistantMessage()\n this.activeSteps = []\n this.addChild(this.activeAssistant)\n }\n\n /** Update the active assistant message with accumulated text. */\n updateAssistant(text: string): void {\n this.activeAssistant?.setText(text)\n }\n\n /** Add an agent step to the current streaming run. */\n addAgentStep(focus: string): void {\n if (!this.activeAssistant) return\n const step = new AgentStep(focus)\n this.activeSteps.push(step)\n // Insert step before the assistant message content\n this.addChild(step)\n }\n\n /** Finalize the current assistant response. */\n finalizeAssistant(): void {\n for (const step of this.activeSteps) {\n step.complete()\n }\n this.activeAssistant = null\n this.activeSteps = []\n this.addChild(new Spacer(1))\n }\n}\n","/**\n * ArbiEditor — custom Editor with ARBI-specific keybindings.\n *\n * Extends pi-tui's Editor to add:\n * - Escape → abort active stream\n * - Ctrl+C → clear input / double-tap to exit\n * - Ctrl+D → exit\n * - Ctrl+W → workspace selector\n * - Ctrl+N → new conversation\n */\n\nimport { Editor, matchesKey, Key, type TUI } from '@mariozechner/pi-tui'\nimport { editorTheme } from '../theme/theme.js'\n\nexport class ArbiEditor extends Editor {\n /** Callback when Escape is pressed (abort streaming). */\n onEscape?: () => void\n\n /** Callback when Ctrl+C is pressed (clear or exit). */\n onCtrlC?: () => void\n\n /** Callback when Ctrl+D is pressed (exit). */\n onCtrlD?: () => void\n\n /** Callback when Ctrl+W is pressed (workspace selector). */\n onCtrlW?: () => void\n\n /** Callback when Ctrl+N is pressed (new conversation). */\n onCtrlN?: () => void\n\n /** Track Ctrl+C presses for double-tap exit. */\n private lastCtrlCTime = 0\n\n constructor(tui: TUI) {\n super(tui, editorTheme, { paddingX: 1 })\n }\n\n override handleInput(data: string): void {\n if (matchesKey(data, Key.escape)) {\n this.onEscape?.()\n return\n }\n\n if (matchesKey(data, Key.ctrl('c'))) {\n const now = Date.now()\n if (this.getText().trim()) {\n // First Ctrl+C with content: clear input\n this.setText('')\n this.lastCtrlCTime = now\n } else if (now - this.lastCtrlCTime < 1000) {\n // Double Ctrl+C within 1s: exit\n this.onCtrlC?.()\n } else {\n this.lastCtrlCTime = now\n this.onCtrlC?.()\n }\n return\n }\n\n if (matchesKey(data, Key.ctrl('d'))) {\n this.onCtrlD?.()\n return\n }\n\n if (matchesKey(data, Key.ctrl('w'))) {\n this.onCtrlW?.()\n return\n }\n\n if (matchesKey(data, Key.ctrl('n'))) {\n this.onCtrlN?.()\n return\n }\n\n // Pass all other input to the base Editor\n super.handleInput(data)\n }\n}\n","/**\n * ToastContainer — auto-dismissing notification toasts.\n *\n * Manages a list of styled Text children that appear briefly then\n * auto-remove themselves. Used for WebSocket event notifications.\n */\n\nimport { Container, Text } from '@mariozechner/pi-tui'\nimport chalk from 'chalk'\n\nexport type ToastLevel = 'info' | 'success' | 'warning' | 'error'\n\nconst LEVEL_STYLE: Record<ToastLevel, (s: string) => string> = {\n info: chalk.dim.cyan,\n success: chalk.dim.green,\n warning: chalk.dim.yellow,\n error: chalk.dim.red,\n}\n\nfunction formatTimestamp(): string {\n const now = new Date()\n const hh = String(now.getHours()).padStart(2, '0')\n const mm = String(now.getMinutes()).padStart(2, '0')\n const ss = String(now.getSeconds()).padStart(2, '0')\n return `${hh}:${mm}:${ss}`\n}\n\ninterface ActiveToast {\n text: Text\n timer: ReturnType<typeof setTimeout>\n}\n\nexport class ToastContainer extends Container {\n private activeToasts: ActiveToast[] = []\n private renderCallback: (() => void) | null = null\n\n /** Set the callback used to trigger a TUI re-render after toast changes. */\n setRenderCallback(cb: () => void): void {\n this.renderCallback = cb\n }\n\n /** Show a toast notification that auto-dismisses after `durationMs`. */\n show(message: string, level: ToastLevel = 'info', durationMs = 5000): void {\n const styleFn = LEVEL_STYLE[level]\n const formatted = styleFn(`[${formatTimestamp()}] ${message}`)\n const text = new Text(formatted, 1, 0)\n\n const timer = setTimeout(() => {\n this.dismiss(text)\n }, durationMs)\n\n this.activeToasts.push({ text, timer })\n this.addChild(text)\n this.renderCallback?.()\n }\n\n /** Remove all active toasts immediately. */\n clear(): void {\n for (const toast of this.activeToasts) {\n clearTimeout(toast.timer)\n this.removeChild(toast.text)\n }\n this.activeToasts = []\n this.renderCallback?.()\n }\n\n private dismiss(text: Text): void {\n const idx = this.activeToasts.findIndex((t) => t.text === text)\n if (idx !== -1) {\n clearTimeout(this.activeToasts[idx].timer)\n this.activeToasts.splice(idx, 1)\n this.removeChild(text)\n this.renderCallback?.()\n }\n }\n}\n","/**\n * Command registry — slash commands available in the TUI.\n *\n * Each command has a name, description, and optional argument hint.\n * Used for autocomplete and help display.\n */\n\nimport type { SlashCommand } from '@mariozechner/pi-tui'\n\nexport interface TuiCommand extends SlashCommand {\n name: string\n description: string\n}\n\nexport const commands: TuiCommand[] = [\n { name: 'help', description: 'Show available commands' },\n { name: 'login', description: 'Log in (re-authenticate)' },\n { name: 'register', description: 'Register a new account' },\n { name: 'create', description: 'Create a new workspace: /create <name>' },\n { name: 'workspace', description: 'Switch workspace: /workspace <id>' },\n { name: 'workspaces', description: 'List all workspaces' },\n { name: 'contacts', description: 'List contacts (type @name to DM)' },\n { name: 'docs', description: 'List documents in current workspace' },\n { name: 'conversations', description: 'List conversations' },\n { name: 'new', description: 'Start fresh conversation (clear threading)' },\n { name: 'status', description: 'Show auth/workspace/connection status' },\n { name: 'exit', description: 'Exit TUI' },\n { name: 'quit', description: 'Exit TUI' },\n]\n\n/** Format all commands as a help string for display. */\nexport function formatHelpText(): string {\n const lines = commands\n .filter((c) => c.name !== 'quit') // Don't show duplicate exit/quit\n .map((c) => ` /${c.name} — ${c.description}`)\n return [\n 'Available commands:',\n '',\n ...lines,\n '',\n 'Direct messages:',\n ' @name — Switch to DM channel with a contact',\n ' @arbi — Switch back to AI chat',\n '',\n 'Keyboard shortcuts:',\n ' Ctrl+N — New conversation',\n ' Ctrl+W — Switch workspace',\n ' Ctrl+D — Exit',\n ' Escape — Abort streaming',\n ].join('\\n')\n}\n","/**\n * Authentication flows for the TUI.\n *\n * Handles login and registration using @inquirer/prompts for interactive input.\n * These flows run BEFORE the TUI takes over the terminal (pi-tui raw mode),\n * or after temporarily stopping the TUI.\n */\n\nimport 'fake-indexeddb/auto'\nimport { input, password, select, confirm } from '@inquirer/prompts'\nimport { createArbiClient } from '@arbidocs/sdk'\nimport type { ConfigStore, AuthContext } from '@arbidocs/core'\nimport { resolveAuth } from '@arbidocs/core'\n\n// ── Login ──────────────────────────────────────────────────────────────────\n\nexport interface LoginResult {\n authContext: AuthContext\n selectedWorkspaceId?: string\n selectedWorkspaceName?: string\n}\n\n/**\n * Interactive login flow. Prompts for email/password, authenticates,\n * and offers workspace selection.\n *\n * Must be called before the TUI starts (or after stopping it).\n */\nexport async function interactiveLogin(store: ConfigStore): Promise<LoginResult> {\n const config = store.requireConfig()\n\n const email = await input({ message: 'Email', validate: (v) => (v.trim() ? true : 'Required') })\n const pw = await password({\n message: 'Password',\n mask: '*',\n validate: (v) => (v ? true : 'Required'),\n })\n\n const arbi = createArbiClient({\n baseUrl: config.baseUrl,\n deploymentDomain: config.deploymentDomain,\n credentials: 'omit',\n })\n\n await arbi.crypto.initSodium()\n\n const loginResult = await arbi.auth.login({ email, password: pw })\n\n store.saveCredentials({\n email,\n signingPrivateKeyBase64: arbi.crypto.bytesToBase64(loginResult.signingPrivateKey),\n serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),\n })\n\n console.info(`Logged in as ${email}`)\n\n // Workspace selection\n const { data: workspaces } = await arbi.fetch.GET('/api/user/workspaces')\n const wsList = workspaces || []\n\n let selectedWorkspaceId: string | undefined\n let selectedWorkspaceName: string | undefined\n\n if (wsList.length === 1) {\n selectedWorkspaceId = wsList[0].external_id\n selectedWorkspaceName = wsList[0].name\n store.updateConfig({ selectedWorkspaceId })\n console.info(`Workspace: ${wsList[0].name}`)\n } else if (wsList.length > 1) {\n const choices = wsList.map((ws) => {\n const totalDocs = ws.shared_document_count + ws.private_document_count\n return {\n name: `${ws.name} (${totalDocs} docs)`,\n value: ws.external_id,\n description: ws.external_id,\n }\n })\n\n selectedWorkspaceId = await select({ message: 'Select workspace', choices })\n const ws = wsList.find((w) => w.external_id === selectedWorkspaceId)\n selectedWorkspaceName = ws?.name\n store.updateConfig({ selectedWorkspaceId })\n console.info(`Workspace: ${selectedWorkspaceName}`)\n } else {\n console.info('No workspaces found.')\n }\n\n // Re-resolve auth with saved credentials\n const authContext = await resolveAuth(store)\n\n return { authContext, selectedWorkspaceId, selectedWorkspaceName }\n}\n\n// ── Registration ───────────────────────────────────────────────────────────\n\n/**\n * Interactive registration flow. Prompts for email, verification code,\n * password, and name. Optionally logs in afterward.\n *\n * Must be called before the TUI starts (or after stopping it).\n */\nexport async function interactiveRegister(store: ConfigStore): Promise<LoginResult | null> {\n const config = store.requireConfig()\n\n const email = await input({ message: 'Email', validate: (v) => (v.trim() ? true : 'Required') })\n\n const arbi = createArbiClient({\n baseUrl: config.baseUrl,\n deploymentDomain: config.deploymentDomain,\n credentials: 'omit',\n })\n await arbi.crypto.initSodium()\n\n // Verification\n const codeMethod = await select({\n message: 'Verification method',\n choices: [\n { name: 'I have an invitation code', value: 'code' as const },\n { name: 'Send me a verification email', value: 'email' as const },\n ],\n })\n\n let verificationCode: string\n if (codeMethod === 'code') {\n verificationCode = await input({\n message: 'Invitation code',\n validate: (v) => (v.trim() ? true : 'Required'),\n })\n } else {\n console.info('Sending verification email...')\n const verifyResponse = await arbi.fetch.POST('/api/user/verify-email', {\n body: { email },\n })\n if (verifyResponse.error) {\n throw new Error(`Failed to send verification email: ${JSON.stringify(verifyResponse.error)}`)\n }\n console.info('Verification email sent. Check your inbox.')\n verificationCode = await input({\n message: 'Verification code',\n validate: (v) => (v.trim() ? true : 'Required'),\n })\n }\n\n // Password\n const pw = await password({\n message: 'Password',\n mask: '*',\n validate: (v) => (v ? true : 'Required'),\n })\n const confirmPw = await password({\n message: 'Confirm password',\n mask: '*',\n validate: (v) => (v ? true : 'Required'),\n })\n if (pw !== confirmPw) {\n throw new Error('Passwords do not match.')\n }\n\n // Name\n const firstName = (await input({ message: 'First name (optional)' })) || 'User'\n const lastName = (await input({ message: 'Last name (optional)' })) || ''\n\n // Register\n await arbi.auth.register({\n email,\n password: pw,\n verificationCode,\n firstName,\n lastName,\n })\n\n console.info(`\\nRegistered successfully as ${email}`)\n\n // Offer to log in\n const doLogin = await confirm({ message: 'Log in now?', default: true })\n if (doLogin) {\n return interactiveLogin(store)\n }\n\n return null\n}\n\n// ── Pre-flight auth check ──────────────────────────────────────────────────\n\n/**\n * Check if the user is authenticated. If not, offer to login or register.\n * Returns the auth context if successful, or exits the process.\n *\n * Called at startup before the TUI launches.\n */\nexport async function ensureAuthenticated(store: ConfigStore): Promise<LoginResult> {\n // Try existing credentials first\n try {\n const authContext = await resolveAuth(store)\n const config = store.requireConfig()\n return {\n authContext,\n selectedWorkspaceId: config.selectedWorkspaceId,\n }\n } catch {\n // Not authenticated — offer login/register\n console.info('Not authenticated.\\n')\n\n const action = await select({\n message: 'What would you like to do?',\n choices: [\n { name: 'Log in', value: 'login' as const },\n { name: 'Register a new account', value: 'register' as const },\n { name: 'Exit', value: 'exit' as const },\n ],\n })\n\n if (action === 'exit') {\n process.exit(0)\n }\n\n if (action === 'register') {\n const result = await interactiveRegister(store)\n if (!result) {\n console.info('Registration complete. Please restart to log in.')\n process.exit(0)\n }\n return result\n }\n\n // Login\n return interactiveLogin(store)\n }\n}\n","/**\n * Command handlers — dispatch logic for slash commands.\n *\n * Each handler receives the TUI context and performs its action,\n * typically displaying results in the chat log.\n */\n\nimport { workspaces, documents, conversations, contacts, resolveWorkspace } from '@arbidocs/core'\nimport type { ArbiTui } from './tui.js'\nimport { formatHelpText } from './commands.js'\nimport { interactiveLogin, interactiveRegister } from './auth.js'\nimport { colors } from './theme/theme.js'\n\n/** Dispatch a slash command. Returns true if handled. */\nexport async function handleCommand(tui: ArbiTui, input: string): Promise<boolean> {\n const trimmed = input.trim()\n if (!trimmed.startsWith('/')) return false\n\n const parts = trimmed.slice(1).split(/\\s+/)\n const cmd = parts[0]?.toLowerCase()\n const args = parts.slice(1)\n\n switch (cmd) {\n case 'help':\n tui.chatLog.addSystem(formatHelpText())\n tui.requestRender()\n return true\n\n case 'login':\n await handleLogin(tui)\n return true\n\n case 'register':\n await handleRegister(tui)\n return true\n\n case 'create':\n await handleCreateWorkspace(tui, args.join(' '))\n return true\n\n case 'workspace':\n await handleWorkspaceSwitch(tui, args[0])\n return true\n\n case 'workspaces':\n await handleListWorkspaces(tui)\n return true\n\n case 'contacts':\n await handleListContacts(tui)\n return true\n\n case 'docs':\n await handleListDocs(tui)\n return true\n\n case 'conversations':\n await handleListConversations(tui)\n return true\n\n case 'new':\n handleNewConversation(tui)\n return true\n\n case 'status':\n handleStatus(tui)\n return true\n\n case 'exit':\n case 'quit':\n tui.shutdown()\n return true\n\n default:\n tui.chatLog.addSystem(\n `Unknown command: /${cmd}. Type /help for available commands.`,\n 'warning'\n )\n tui.requestRender()\n return true\n }\n}\n\nasync function handleLogin(tui: ArbiTui): Promise<void> {\n tui.chatLog.addSystem('Pausing TUI for login...')\n tui.requestRender()\n\n // Stop the TUI so @inquirer/prompts can use stdin\n tui.stopTui()\n\n try {\n const result = await interactiveLogin(tui.store)\n tui.setAuthContext(result.authContext)\n\n if (result.selectedWorkspaceId) {\n const wsCtx = await resolveWorkspace(tui.store, result.selectedWorkspaceId)\n tui.setWorkspaceContext(wsCtx)\n tui.state.workspaceName = result.selectedWorkspaceName ?? null\n }\n\n // Restart TUI\n tui.restartTui()\n tui.chatLog.addSystem('Logged in successfully.')\n tui.requestRender()\n } catch (err) {\n // Restart TUI even on error\n tui.restartTui()\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Login failed: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleRegister(tui: ArbiTui): Promise<void> {\n tui.chatLog.addSystem('Pausing TUI for registration...')\n tui.requestRender()\n\n // Stop the TUI so @inquirer/prompts can use stdin\n tui.stopTui()\n\n try {\n const result = await interactiveRegister(tui.store)\n\n if (result) {\n tui.setAuthContext(result.authContext)\n\n if (result.selectedWorkspaceId) {\n const wsCtx = await resolveWorkspace(tui.store, result.selectedWorkspaceId)\n tui.setWorkspaceContext(wsCtx)\n tui.state.workspaceName = result.selectedWorkspaceName ?? null\n }\n }\n\n // Restart TUI\n tui.restartTui()\n tui.chatLog.addSystem(\n result ? 'Registered and logged in.' : 'Registered. Use /login to log in.'\n )\n tui.requestRender()\n } catch (err) {\n // Restart TUI even on error\n tui.restartTui()\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Registration failed: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleCreateWorkspace(tui: ArbiTui, name: string): Promise<void> {\n if (!tui.authContext) {\n tui.chatLog.addSystem('Not authenticated. Use /login first.', 'error')\n tui.requestRender()\n return\n }\n\n if (!name.trim()) {\n tui.chatLog.addSystem('Usage: /create <workspace name>', 'warning')\n tui.requestRender()\n return\n }\n\n try {\n tui.chatLog.addSystem(`Creating workspace \"${name}\"...`)\n tui.requestRender()\n\n const ws = await workspaces.createWorkspace(tui.authContext.arbi, name.trim())\n\n // Auto-switch to the new workspace\n const { selectWorkspaceById } = await import('@arbidocs/core')\n const selected = await selectWorkspaceById(\n tui.authContext.arbi,\n ws.external_id,\n tui.authContext.loginResult.serverSessionKey,\n tui.store.requireCredentials().signingPrivateKeyBase64\n )\n\n tui.state.workspaceId = selected.external_id\n tui.state.workspaceName = selected.name\n tui.state.conversationMessageId = null\n tui.store.updateConfig({ selectedWorkspaceId: selected.external_id })\n await tui.refreshWorkspaceContext()\n\n tui.chatLog.addSystem(`Created and switched to workspace: ${colors.accentBold(selected.name)}`)\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to create workspace: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleWorkspaceSwitch(tui: ArbiTui, workspaceId?: string): Promise<void> {\n if (!tui.authContext) {\n tui.chatLog.addSystem('Not authenticated. Please restart and log in.', 'error')\n tui.requestRender()\n return\n }\n\n if (!workspaceId) {\n // Show workspace list for selection\n await handleListWorkspaces(tui)\n tui.chatLog.addSystem('Use /workspace <id> to switch.')\n tui.requestRender()\n return\n }\n\n try {\n tui.chatLog.addSystem(`Switching to workspace ${workspaceId}...`)\n tui.requestRender()\n\n const { selectWorkspaceById } = await import('@arbidocs/core')\n const ws = await selectWorkspaceById(\n tui.authContext.arbi,\n workspaceId,\n tui.authContext.loginResult.serverSessionKey,\n tui.store.requireCredentials().signingPrivateKeyBase64\n )\n\n // Update state\n tui.state.workspaceId = ws.external_id\n tui.state.workspaceName = ws.name\n tui.state.conversationMessageId = null\n\n // Update config\n tui.store.updateConfig({ selectedWorkspaceId: ws.external_id })\n\n // Refresh workspace context\n await tui.refreshWorkspaceContext()\n\n tui.chatLog.addSystem(`Switched to workspace: ${colors.accentBold(ws.name)}`)\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to switch workspace: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleListWorkspaces(tui: ArbiTui): Promise<void> {\n if (!tui.authContext) {\n tui.chatLog.addSystem('Not authenticated.', 'error')\n tui.requestRender()\n return\n }\n\n try {\n const wsList = await workspaces.listWorkspaces(tui.authContext.arbi)\n const lines = wsList.map((ws) => {\n const current = ws.external_id === tui.state.workspaceId ? colors.accent(' (current)') : ''\n return ` ${ws.external_id} ${ws.name}${current}`\n })\n tui.chatLog.addSystem(['Workspaces:', '', ...lines].join('\\n'))\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to list workspaces: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleListDocs(tui: ArbiTui): Promise<void> {\n if (!tui.authContext || !tui.state.workspaceId) {\n tui.chatLog.addSystem('No workspace selected. Use /workspace <id> first.', 'warning')\n tui.requestRender()\n return\n }\n\n try {\n const docs = await documents.listDocuments(tui.authContext.arbi, tui.state.workspaceId)\n if (docs.length === 0) {\n tui.chatLog.addSystem('No documents in this workspace.')\n } else {\n const lines = docs.map((d) => ` ${d.external_id} ${d.file_name ?? '(unnamed)'}`)\n tui.chatLog.addSystem([`Documents (${docs.length}):`, '', ...lines].join('\\n'))\n }\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to list documents: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleListContacts(tui: ArbiTui): Promise<void> {\n if (!tui.authContext) {\n tui.chatLog.addSystem('Not authenticated. Use /login first.', 'error')\n tui.requestRender()\n return\n }\n\n try {\n const contactList = await contacts.listContacts(tui.authContext.arbi)\n\n const registered = contactList.filter((c) => c.status === 'registered')\n const invited = contactList.filter((c) => c.status !== 'registered')\n\n if (registered.length === 0 && invited.length === 0) {\n tui.chatLog.addSystem('No contacts. Use the web app to add contacts.')\n } else {\n const lines: string[] = []\n\n if (registered.length > 0) {\n lines.push(`Contacts (${registered.length}):`, '')\n for (const c of registered) {\n const name = c.user\n ? `${c.user.given_name} ${c.user.family_name}`.trim()\n : ''\n const nameStr = name ? colors.muted(` (${name})`) : ''\n lines.push(` ${c.email}${nameStr}`)\n }\n }\n\n if (invited.length > 0) {\n if (lines.length > 0) lines.push('')\n lines.push(`Pending invitations (${invited.length}):`)\n for (const c of invited) {\n lines.push(` ${c.email} — ${colors.muted(c.status)}`)\n }\n }\n\n lines.push('', colors.muted('Type @name to start a DM with a registered contact.'))\n tui.chatLog.addSystem(lines.join('\\n'))\n }\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to list contacts: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nasync function handleListConversations(tui: ArbiTui): Promise<void> {\n if (!tui.authContext || !tui.state.workspaceId) {\n tui.chatLog.addSystem('No workspace selected. Use /workspace <id> first.', 'warning')\n tui.requestRender()\n return\n }\n\n try {\n const convs = await conversations.listConversations(tui.authContext.arbi, tui.state.workspaceId)\n if (convs.length === 0) {\n tui.chatLog.addSystem('No conversations in this workspace.')\n } else {\n const lines = convs.map((c) => ` ${c.external_id} ${c.title ?? '(untitled)'}`)\n tui.chatLog.addSystem([`Conversations (${convs.length}):`, '', ...lines].join('\\n'))\n }\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to list conversations: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\nfunction handleNewConversation(tui: ArbiTui): void {\n tui.state.conversationMessageId = null\n tui.store.clearChatSession()\n tui.chatLog.addSystem('Started new conversation.')\n tui.requestRender()\n}\n\nfunction handleStatus(tui: ArbiTui): void {\n const { state } = tui\n const lines = [\n `Authenticated: ${state.isAuthenticated ? colors.success('yes') : colors.error('no')}`,\n `Workspace: ${state.workspaceName ? colors.accent(state.workspaceName) : colors.muted('none')}`,\n `Workspace ID: ${state.workspaceId ?? colors.muted('none')}`,\n `Conversation: ${state.conversationMessageId ? colors.muted(state.conversationMessageId) : colors.muted('new')}`,\n `Status: ${state.activityStatus}`,\n `WebSocket: ${tui.wsConnected ? colors.success('connected') : colors.muted('disconnected')}`,\n ]\n tui.chatLog.addSystem(lines.join('\\n'))\n tui.requestRender()\n}\n","/**\n * SSE streaming event handler — wires @arbidocs/core streaming\n * into TUI component updates.\n */\n\nimport { streamSSE, type SSEStreamCallbacks, type SSEStreamResult } from '@arbidocs/core'\nimport type { ArbiTui } from './tui.js'\n\n/**\n * Stream an assistant response from the API into the TUI.\n *\n * 1. Creates an assistant message in the chat log\n * 2. Streams tokens into it via SSE callbacks\n * 3. Displays agent steps as they arrive\n * 4. Finalizes when complete\n *\n * Returns the full SSE result for caller to extract metadata.\n */\nexport async function streamResponse(tui: ArbiTui, response: Response): Promise<SSEStreamResult> {\n tui.chatLog.startAssistant()\n tui.state.activityStatus = 'streaming'\n tui.requestRender()\n\n let accumulated = ''\n\n const callbacks: SSEStreamCallbacks = {\n onStreamStart: (data) => {\n if (data.assistant_message_ext_id) {\n tui.state.conversationMessageId = data.assistant_message_ext_id as string\n }\n },\n\n onToken: (content) => {\n accumulated += content\n tui.chatLog.updateAssistant(accumulated)\n tui.requestRender()\n },\n\n onAgentStep: (data) => {\n const focus = data.focus || data.status || ''\n if (focus) {\n tui.chatLog.addAgentStep(focus)\n tui.requestRender()\n }\n },\n\n onError: (message) => {\n tui.chatLog.addSystem(`Stream error: ${message}`, 'error')\n tui.requestRender()\n },\n }\n\n try {\n const result = await streamSSE(response, callbacks)\n tui.chatLog.finalizeAssistant()\n tui.state.activityStatus = 'idle'\n tui.requestRender()\n return result\n } catch (err) {\n tui.chatLog.finalizeAssistant()\n tui.state.activityStatus = 'error'\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Streaming failed: ${msg}`, 'error')\n tui.requestRender()\n throw err\n }\n}\n","/**\n * DM handler — encryption setup, send/receive, channel switching.\n *\n * Manages the DM channel state and E2E encrypted messaging.\n * Uses the same ECDH encryption pattern as the React frontend.\n */\n\nimport { dm, contacts } from '@arbidocs/core'\nimport {\n base64ToBytes,\n deriveEncryptionKeypairFromSigning,\n encryptMessage,\n decryptMessage,\n type KeyPair,\n type WsNotificationResponse,\n} from '@arbidocs/sdk'\nimport type { ArbiTui } from './tui.js'\nimport { colors } from './theme/theme.js'\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface DmContact {\n external_id: string\n email: string\n encryption_public_key: string\n given_name: string\n family_name: string\n}\n\nexport interface DmChannel {\n user: DmContact\n}\n\n// ── Encryption keypair derivation ────────────────────────────────────────────\n\n/**\n * Derive X25519 encryption keypair from the stored Ed25519 signing key.\n * Called once after login.\n */\nexport function deriveEncryptionKeypair(signingPrivateKeyBase64: string): KeyPair {\n const signingPrivateKey = base64ToBytes(signingPrivateKeyBase64)\n // Ed25519 public key is the last 32 bytes of the 64-byte private key\n const ed25519PublicKey = signingPrivateKey.slice(32, 64)\n return deriveEncryptionKeypairFromSigning({\n publicKey: ed25519PublicKey,\n secretKey: signingPrivateKey,\n })\n}\n\n// ── Recipient resolution ─────────────────────────────────────────────────────\n\n/**\n * Resolve a @query to a contact user.\n * Matches by email prefix or given_name (case-insensitive).\n * Returns the matched contact user, or null if not found/ambiguous.\n */\nexport async function resolveRecipient(\n tui: ArbiTui,\n query: string\n): Promise<DmContact | null> {\n if (!tui.authContext) {\n tui.chatLog.addSystem('Not authenticated. Use /login first.', 'error')\n tui.requestRender()\n return null\n }\n\n const queryLower = query.toLowerCase()\n\n try {\n const contactList = await contacts.listContacts(tui.authContext.arbi)\n\n // Filter for registered contacts with encryption keys\n const registered = contactList.filter(\n (c) => c.status === 'registered' && c.user?.encryption_public_key\n )\n\n // Match by email prefix (before @) or given_name\n const matches = registered.filter((c) => {\n const emailPrefix = c.email.split('@')[0]?.toLowerCase()\n const givenName = c.user?.given_name?.toLowerCase()\n return emailPrefix === queryLower || givenName === queryLower\n })\n\n if (matches.length === 0) {\n tui.chatLog.addSystem(\n `No registered contact matching \"${query}\". Use /contacts to see available contacts.`,\n 'warning'\n )\n tui.requestRender()\n return null\n }\n\n if (matches.length > 1) {\n const names = matches.map((c) => ` ${c.email} (${c.user?.given_name ?? ''} ${c.user?.family_name ?? ''})`).join('\\n')\n tui.chatLog.addSystem(\n `Ambiguous match for \"${query}\". Be more specific:\\n${names}`,\n 'warning'\n )\n tui.requestRender()\n return null\n }\n\n const contact = matches[0]\n const user = contact.user!\n return {\n external_id: user.external_id,\n email: contact.email,\n encryption_public_key: user.encryption_public_key,\n given_name: user.given_name,\n family_name: user.family_name,\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to resolve contact: ${msg}`, 'error')\n tui.requestRender()\n return null\n }\n}\n\n// ── Channel switching ────────────────────────────────────────────────────────\n\n/**\n * Handle @input — switch to DM channel or back to arbi.\n */\nexport async function handleChannelSwitch(tui: ArbiTui, input: string): Promise<void> {\n const query = input.slice(1).trim() // Remove leading @\n\n if (!query) {\n tui.chatLog.addSystem('Usage: @username to switch to DM, @arbi to switch back.', 'warning')\n tui.requestRender()\n return\n }\n\n // @arbi — switch back to AI chat\n if (query.toLowerCase() === 'arbi') {\n switchToArbi(tui)\n return\n }\n\n // Resolve recipient\n const user = await resolveRecipient(tui, query)\n if (!user) return\n\n await switchToDmChannel(tui, user)\n}\n\n/**\n * Switch to a DM channel with a specific user.\n * Updates header, clears chat, loads DM history.\n */\nexport async function switchToDmChannel(tui: ArbiTui, user: DmContact): Promise<void> {\n if (!tui.authContext || !tui.encryptionKeys) {\n tui.chatLog.addSystem('Not authenticated or encryption not initialized.', 'error')\n tui.requestRender()\n return\n }\n\n // Set channel state\n tui.currentDmChannel = { user }\n tui.updateHeader()\n\n // Clear chat log for DM view\n tui.chatLog.clearMessages()\n\n tui.chatLog.addSystem(\n `Switched to DM with ${colors.accent(user.email)}. Type @arbi to switch back.`\n )\n tui.requestRender()\n\n // Fetch and display DM history\n await loadDmHistory(tui, user)\n}\n\n/**\n * Switch back to AI chat mode.\n */\nexport function switchToArbi(tui: ArbiTui): void {\n if (!tui.currentDmChannel) {\n tui.chatLog.addSystem('Already in AI chat mode.', 'info')\n tui.requestRender()\n return\n }\n\n tui.currentDmChannel = null\n tui.updateHeader()\n\n // Clear chat log for fresh AI view\n tui.chatLog.clearMessages()\n tui.chatLog.addSystem('Switched back to AI chat.')\n tui.requestRender()\n}\n\n// ── DM history ───────────────────────────────────────────────────────────────\n\n/**\n * Fetch all DMs and display the conversation with a specific user.\n */\nasync function loadDmHistory(tui: ArbiTui, user: DmContact): Promise<void> {\n if (!tui.authContext || !tui.encryptionKeys) return\n\n const myExtId = tui.authContext.loginResult.userExtId\n\n try {\n const allDms = await dm.listDMs(tui.authContext.arbi)\n\n // Filter for DMs between us and this user (type === 'user_message')\n const conversation = allDms.filter(\n (msg) =>\n msg.type === 'user_message' &&\n ((msg.sender.external_id === user.external_id && msg.recipient.external_id === myExtId) ||\n (msg.sender.external_id === myExtId && msg.recipient.external_id === user.external_id))\n )\n\n // Sort by created_at ascending\n conversation.sort(\n (a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime()\n )\n\n // Mark unread messages as read\n const unreadIds = conversation\n .filter((msg) => !msg.read && msg.sender.external_id === user.external_id)\n .map((msg) => msg.external_id)\n\n if (unreadIds.length > 0) {\n dm.markRead(tui.authContext.arbi, unreadIds).catch(() => {\n // Non-fatal — just log\n })\n }\n\n // Decrypt and display messages\n for (const msg of conversation) {\n const isSent = msg.sender.external_id === myExtId\n const plaintext = await decryptNotification(msg, myExtId!, tui.encryptionKeys, user)\n if (plaintext) {\n displayDmMessage(tui, plaintext, isSent, user.email)\n }\n }\n\n tui.requestRender()\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to load DM history: ${errMsg}`, 'error')\n tui.requestRender()\n }\n}\n\n// ── Send encrypted DM ────────────────────────────────────────────────────────\n\n/**\n * Encrypt and send a DM to the current channel's recipient.\n */\nexport async function sendEncryptedDm(tui: ArbiTui, plaintext: string): Promise<void> {\n if (!tui.authContext || !tui.encryptionKeys || !tui.currentDmChannel) {\n tui.chatLog.addSystem('Cannot send DM — not in a DM channel.', 'error')\n tui.requestRender()\n return\n }\n\n const recipient = tui.currentDmChannel.user\n\n try {\n // Encrypt the message\n const encrypted = await encryptMessage(\n plaintext,\n recipient.encryption_public_key,\n tui.encryptionKeys.secretKey\n )\n\n // Send via API\n await dm.sendDM(tui.authContext.arbi, [\n { recipient_ext_id: recipient.external_id, content: encrypted },\n ])\n\n // Display sent message in chat log\n displayDmMessage(tui, plaintext, true, recipient.email)\n tui.requestRender()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to send DM: ${msg}`, 'error')\n tui.requestRender()\n }\n}\n\n// ── Incoming DM handling (from WebSocket) ────────────────────────────────────\n\n/**\n * Handle an incoming WebSocket DM notification.\n * If we're in a DM channel with the sender, show it inline and return true.\n * Otherwise return false (caller shows toast).\n */\nexport async function handleIncomingDm(\n tui: ArbiTui,\n msg: WsNotificationResponse\n): Promise<boolean> {\n if (!tui.currentDmChannel || !tui.encryptionKeys || !tui.authContext) {\n return false\n }\n\n const myExtId = tui.authContext.loginResult.userExtId\n const channelUserId = tui.currentDmChannel.user.external_id\n\n // Check if this message is from the user we're chatting with\n if (msg.sender.external_id !== channelUserId) {\n return false\n }\n\n // Decrypt and display inline\n const plaintext = await decryptNotification(\n msg,\n myExtId!,\n tui.encryptionKeys,\n tui.currentDmChannel.user\n )\n\n if (plaintext) {\n displayDmMessage(tui, plaintext, false, msg.sender.email)\n tui.requestRender()\n\n // Mark as read\n dm.markRead(tui.authContext.arbi, [msg.external_id]).catch(() => {\n // Non-fatal\n })\n }\n\n return true\n}\n\n// ── Decryption helper ────────────────────────────────────────────────────────\n\n/**\n * Decrypt a notification's content field.\n *\n * For received messages: decrypt with sender's public key + our private key.\n * For sent messages: decrypt with recipient's public key + our private key.\n */\nasync function decryptNotification(\n notification: WsNotificationResponse,\n _myExtId: string,\n encryptionKeyPair: KeyPair,\n otherUser: DmContact\n): Promise<string | null> {\n if (!notification.content) return null\n\n try {\n // ECDH decryption uses the other party's public key in both cases\n return await decryptMessage(\n notification.content,\n otherUser.encryption_public_key,\n encryptionKeyPair.secretKey\n )\n } catch {\n return '[decryption failed]'\n }\n}\n\n// ── Display helper ───────────────────────────────────────────────────────────\n\n/**\n * Display a DM message in the chat log.\n * Sent messages show \"You:\", received show the sender's email.\n */\nfunction displayDmMessage(\n tui: ArbiTui,\n text: string,\n isSent: boolean,\n senderEmail: string\n): void {\n if (isSent) {\n tui.chatLog.addUser(text)\n } else {\n tui.chatLog.addDm(senderEmail, text)\n }\n}\n","/**\n * WebSocket handler — connects to backend WS and routes messages to toasts.\n *\n * Uses connectWebSocket() from @arbidocs/core for connection/auth,\n * and isMessageType() from @arbidocs/sdk for typed message routing.\n */\n\nimport { connectWebSocket, type WsConnection } from '@arbidocs/core'\nimport {\n isMessageType,\n type WebSocketServerMessage,\n type WsTaskUpdateMessage,\n type WsBatchCompleteMessage,\n type WsErrorMessage,\n type WsNotificationResponse,\n} from '@arbidocs/sdk'\nimport type { ArbiTui } from './tui.js'\nimport type { ToastContainer, ToastLevel } from './components/toast-container.js'\nimport { handleIncomingDm } from './dm-handler.js'\n\n// ── Duration constants ────────────────────────────────────────────────────────\n\nconst DURATION_SHORT = 3000 // frequent in-progress updates\nconst DURATION_DEFAULT = 5000 // completed tasks, batch, notifications\nconst DURATION_LONG = 8000 // errors — longer so user notices\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\n/** NotificationResponse uses NotificationType as its `type` field, not a single literal. */\nfunction isNotification(msg: WebSocketServerMessage): msg is WsNotificationResponse {\n return 'sender' in msg && 'recipient' in msg\n}\n\n// ── Message routing ───────────────────────────────────────────────────────────\n\nasync function handleMessage(\n msg: WebSocketServerMessage,\n toasts: ToastContainer,\n tui: ArbiTui | null\n): Promise<void> {\n if (isMessageType<WsTaskUpdateMessage>(msg, 'task_update')) {\n handleTaskUpdate(msg, toasts)\n } else if (isMessageType<WsBatchCompleteMessage>(msg, 'batch_complete')) {\n handleBatchComplete(msg, toasts)\n } else if (isMessageType<WsErrorMessage>(msg, 'error')) {\n toasts.show(msg.message, 'error', DURATION_LONG)\n } else if (isNotification(msg)) {\n // For user_message notifications, try to route to DM chat log\n if (msg.type === 'user_message' && tui) {\n const handled = await handleIncomingDm(tui, msg)\n if (handled) return\n }\n // Fall back to toast for non-DM notifications or when not in the right channel\n const text = msg.content ?? `Notification: ${msg.type}`\n toasts.show(text, 'info', DURATION_DEFAULT)\n }\n}\n\nfunction handleTaskUpdate(msg: WsTaskUpdateMessage, toasts: ToastContainer): void {\n const progress = msg.progress > 0 ? ` (${Math.round(msg.progress)}%)` : ''\n const text = `📄 ${msg.file_name} — ${msg.status}${progress}`\n\n let level: ToastLevel = 'info'\n let duration = DURATION_SHORT\n\n if (msg.status === 'completed') {\n level = 'success'\n duration = DURATION_DEFAULT\n } else if (msg.status === 'failed') {\n level = 'error'\n duration = DURATION_LONG\n }\n\n toasts.show(text, level, duration)\n}\n\nfunction handleBatchComplete(msg: WsBatchCompleteMessage, toasts: ToastContainer): void {\n const count = msg.doc_ext_ids.length\n const text = `✓ Batch complete: ${msg.batch_type} — ${count} doc${count !== 1 ? 's' : ''}`\n toasts.show(text, 'success', DURATION_DEFAULT)\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport interface TuiWsOptions {\n baseUrl: string\n accessToken: string\n toasts: ToastContainer\n tui?: ArbiTui\n}\n\n/**\n * Connect WebSocket and route messages to toast notifications.\n * Returns the connection handle for cleanup, or null on failure.\n */\nexport async function connectTuiWebSocket(options: TuiWsOptions): Promise<WsConnection | null> {\n const { baseUrl, accessToken, toasts, tui } = options\n\n try {\n const connection = await connectWebSocket({\n baseUrl,\n accessToken,\n onMessage: (msg) => handleMessage(msg, toasts, tui ?? null),\n onClose: (_code, _reason) => {\n toasts.show('WebSocket disconnected', 'warning', DURATION_DEFAULT)\n },\n })\n return connection\n } catch {\n // Auth failure or connection error — not fatal, just skip WS\n toasts.show('WebSocket connection failed', 'warning', DURATION_DEFAULT)\n return null\n }\n}\n","/**\n * ArbiTui — main orchestrator for the ARBI terminal UI.\n *\n * Manages state, component wiring, and lifecycle. Coordinates between\n * the editor input, chat log display, command dispatch, and SSE streaming.\n */\n\nimport {\n TUI,\n ProcessTerminal,\n Text,\n Spacer,\n CombinedAutocompleteProvider,\n} from '@mariozechner/pi-tui'\nimport {\n type AuthContext,\n type WorkspaceContext,\n type WsConnection,\n type ConfigStore,\n assistant,\n documents,\n} from '@arbidocs/core'\nimport type { KeyPair } from '@arbidocs/sdk'\nimport { ChatLog } from './components/chat-log.js'\nimport { ArbiEditor } from './components/arbi-editor.js'\nimport { ToastContainer } from './components/toast-container.js'\nimport { handleCommand } from './command-handlers.js'\nimport { streamResponse } from './event-handlers.js'\nimport { connectTuiWebSocket } from './ws-handler.js'\nimport {\n type DmChannel,\n deriveEncryptionKeypair,\n handleChannelSwitch,\n sendEncryptedDm,\n} from './dm-handler.js'\nimport { commands } from './commands.js'\nimport { colors, formatHeader } from './theme/theme.js'\n\n// ── State ──────────────────────────────────────────────────────────────────\n\nexport interface TuiState {\n workspaceId: string | null\n workspaceName: string | null\n conversationMessageId: string | null\n activityStatus: 'idle' | 'sending' | 'streaming' | 'error'\n isAuthenticated: boolean\n}\n\n// ── Main TUI class ─────────────────────────────────────────────────────────\n\nexport class ArbiTui {\n private tui: TUI\n private header: Text\n\n /** The chat message log — public so command handlers can add messages. */\n readonly chatLog: ChatLog\n\n /** Toast notifications from WebSocket events. */\n readonly toastContainer: ToastContainer\n\n /** The input editor. */\n private editor: ArbiEditor\n\n /** Application state — public so handlers can read/write it. */\n state: TuiState\n\n /** Auth context from @arbidocs/core — set during init. */\n authContext: AuthContext | null = null\n\n /** Workspace context with tokens/headers — set when workspace is selected. */\n private workspaceContext: WorkspaceContext | null = null\n\n /** Config store for persistence. */\n readonly store: ConfigStore\n\n /** Active WebSocket connection (null when not connected). */\n private wsConnection: WsConnection | null = null\n\n /** X25519 encryption keypair derived from signing key (null until login). */\n private encryptionKeyPair: KeyPair | null = null\n\n /** Current DM channel (null = AI chat mode). */\n private dmChannel: DmChannel | null = null\n\n constructor(store: ConfigStore) {\n this.store = store\n\n this.state = {\n workspaceId: null,\n workspaceName: null,\n conversationMessageId: null,\n activityStatus: 'idle',\n isAuthenticated: false,\n }\n\n // Build TUI component tree\n this.tui = new TUI(new ProcessTerminal())\n\n // Header\n this.header = new Text(formatHeader(null, 'starting...'), 1, 0)\n\n // Chat log\n this.chatLog = new ChatLog()\n\n // Toast container for WebSocket notifications\n this.toastContainer = new ToastContainer()\n this.toastContainer.setRenderCallback(() => this.tui.requestRender())\n\n // Editor\n this.editor = new ArbiEditor(this.tui)\n this.editor.setAutocompleteProvider(new CombinedAutocompleteProvider(commands))\n\n // Wire editor callbacks\n this.editor.onSubmit = (text: string) => this.handleSubmit(text)\n this.editor.onEscape = () => this.handleAbort()\n this.editor.onCtrlC = () => this.shutdown()\n this.editor.onCtrlD = () => this.shutdown()\n this.editor.onCtrlW = () => this.handleSubmit('/workspaces')\n this.editor.onCtrlN = () => this.handleSubmit('/new')\n\n // Compose layout\n this.tui.addChild(this.header)\n this.tui.addChild(new Spacer(1))\n this.tui.addChild(this.toastContainer)\n this.tui.addChild(this.chatLog)\n this.tui.addChild(this.editor)\n\n this.tui.setFocus(this.editor)\n }\n\n // ── Lifecycle ──────────────────────────────────────────────────────────\n\n /** Start the TUI event loop. */\n start(): void {\n this.tui.start()\n this.updateHeader()\n this.tui.requestRender()\n }\n\n /** Gracefully shut down the TUI and exit. */\n shutdown(): void {\n this.wsConnection?.close()\n this.wsConnection = null\n this.toastContainer.clear()\n this.tui.stop()\n process.exit(0)\n }\n\n /**\n * Temporarily stop the TUI (releases terminal raw mode).\n * Used before interactive prompts that need stdin (login, register).\n */\n stopTui(): void {\n this.tui.stop()\n }\n\n /**\n * Restart the TUI after a stopTui() call.\n * Rebuilds the component tree with a fresh TUI instance since\n * pi-tui doesn't support stop/start cycling on the same instance.\n */\n restartTui(): void {\n this.tui = new TUI(new ProcessTerminal())\n\n // Re-compose layout\n this.tui.addChild(this.header)\n this.tui.addChild(new Spacer(1))\n this.tui.addChild(this.toastContainer)\n this.tui.addChild(this.chatLog)\n\n // Create new editor (needs fresh TUI reference)\n this.editor = new ArbiEditor(this.tui)\n this.editor.setAutocompleteProvider(new CombinedAutocompleteProvider(commands))\n this.editor.onSubmit = (text: string) => this.handleSubmit(text)\n this.editor.onEscape = () => this.handleAbort()\n this.editor.onCtrlC = () => this.shutdown()\n this.editor.onCtrlD = () => this.shutdown()\n this.editor.onCtrlW = () => this.handleSubmit('/workspaces')\n this.editor.onCtrlN = () => this.handleSubmit('/new')\n\n this.tui.addChild(this.editor)\n this.tui.setFocus(this.editor)\n\n this.tui.start()\n this.updateHeader()\n this.tui.requestRender()\n }\n\n /** Request a render update. */\n requestRender(): void {\n this.tui.requestRender()\n }\n\n // ── Auth / Workspace ───────────────────────────────────────────────────\n\n /** Set authentication context after login. */\n setAuthContext(ctx: AuthContext): void {\n this.authContext = ctx\n this.state.isAuthenticated = true\n this.encryptionKeyPair = deriveEncryptionKeypair(\n this.store.requireCredentials().signingPrivateKeyBase64\n )\n this.updateHeader()\n }\n\n /** Set workspace context after workspace selection. */\n setWorkspaceContext(ctx: WorkspaceContext): void {\n this.workspaceContext = ctx\n this.state.workspaceId = ctx.workspaceId\n // Workspace name will be set separately since WorkspaceContext doesn't include it\n this.updateHeader()\n this.connectWebSocket()\n }\n\n /** Refresh workspace context (after switching workspaces). */\n async refreshWorkspaceContext(): Promise<void> {\n if (!this.state.workspaceId || !this.authContext) return\n\n const { resolveWorkspace } = await import('@arbidocs/core')\n const ctx = await resolveWorkspace(this.store, this.state.workspaceId)\n this.workspaceContext = ctx\n this.updateHeader()\n }\n\n /** Whether the WebSocket is currently connected. */\n get wsConnected(): boolean {\n return this.wsConnection !== null\n }\n\n /** Connect (or reconnect) WebSocket for real-time notifications. */\n private connectWebSocket(): void {\n if (!this.workspaceContext) return\n\n // Close existing connection before reconnecting\n this.wsConnection?.close()\n this.wsConnection = null\n\n const { config, accessToken } = this.workspaceContext\n\n connectTuiWebSocket({\n baseUrl: config.baseUrl,\n accessToken,\n toasts: this.toastContainer,\n tui: this,\n }).then((conn) => {\n this.wsConnection = conn\n })\n }\n\n // ── Input handling ─────────────────────────────────────────────────────\n\n private async handleSubmit(text: string): Promise<void> {\n const trimmed = text.trim()\n if (!trimmed) return\n\n // Check for @channel switching\n if (trimmed.startsWith('@')) {\n await handleChannelSwitch(this, trimmed)\n return\n }\n\n // Check for slash commands\n if (trimmed.startsWith('/')) {\n const handled = await handleCommand(this, trimmed)\n if (handled) return\n }\n\n // Route to DM or AI based on channel\n if (this.dmChannel) {\n await sendEncryptedDm(this, trimmed)\n } else {\n await this.sendMessage(trimmed)\n }\n }\n\n private handleAbort(): void {\n if (this.state.activityStatus === 'streaming') {\n // TODO: implement AbortController for stream cancellation\n this.chatLog.addSystem('Abort requested (stream will complete current chunk).', 'warning')\n this.requestRender()\n }\n }\n\n // ── Messaging ──────────────────────────────────────────────────────────\n\n private async sendMessage(question: string): Promise<void> {\n if (!this.workspaceContext) {\n this.chatLog.addSystem(\n 'No workspace selected. Use /workspace <id> or /workspaces to choose one.',\n 'warning'\n )\n this.requestRender()\n return\n }\n\n // Display user message\n this.chatLog.addUser(question)\n this.state.activityStatus = 'sending'\n this.updateHeader()\n this.requestRender()\n\n try {\n // Get all docs in workspace for retrieval context\n const docs = await documents.listDocuments(\n this.workspaceContext.arbi,\n this.workspaceContext.workspaceId\n )\n const docIds = docs.map((d) => d.external_id as string)\n\n // Load chat session for conversation threading\n const session = this.store.getChatSession()\n const parentMessageExtId = this.state.conversationMessageId ?? session.lastMessageExtId\n\n // Query the assistant\n const response = await assistant.queryAssistant({\n baseUrl: this.workspaceContext.config.baseUrl,\n accessToken: this.workspaceContext.accessToken,\n workspaceKeyHeader: this.workspaceContext.workspaceKeyHeader,\n workspaceId: this.workspaceContext.workspaceId,\n question,\n docIds,\n parentMessageExtId,\n })\n\n // Stream the response into the chat log\n const result = await streamResponse(this, response)\n\n // Save conversation state for threading\n if (result.assistantMessageExtId) {\n this.state.conversationMessageId = result.assistantMessageExtId\n this.store.updateChatSession({ lastMessageExtId: result.assistantMessageExtId })\n }\n } catch (err) {\n this.state.activityStatus = 'error'\n const msg = err instanceof Error ? err.message : String(err)\n this.chatLog.addSystem(`Error: ${msg}`, 'error')\n }\n\n this.state.activityStatus = 'idle'\n this.updateHeader()\n this.requestRender()\n }\n\n // ── UI Updates ─────────────────────────────────────────────────────────\n\n /** Update the header bar — public so dm-handler can call it. */\n updateHeader(): void {\n const statusText =\n this.state.activityStatus === 'idle'\n ? colors.success('ready')\n : this.state.activityStatus === 'streaming'\n ? colors.warning('streaming...')\n : this.state.activityStatus === 'sending'\n ? colors.warning('sending...')\n : colors.error('error')\n\n if (this.dmChannel) {\n this.header.setText(formatHeader(`DM: ${this.dmChannel.user.email}`, statusText))\n } else {\n this.header.setText(formatHeader(this.state.workspaceName, statusText))\n }\n }\n\n // ── DM channel accessors (used by dm-handler) ────────────────────────────\n\n /** Current DM channel (null = AI chat mode). */\n get currentDmChannel(): DmChannel | null {\n return this.dmChannel\n }\n\n set currentDmChannel(ch: DmChannel | null) {\n this.dmChannel = ch\n }\n\n /** Encryption keypair for E2E DM encryption. */\n get encryptionKeys(): KeyPair | null {\n return this.encryptionKeyPair\n }\n}\n","/**\n * ARBI TUI — entry point\n *\n * Handles CLI argument parsing, authentication, and TUI launch.\n * Uses @arbidocs/core for auth and config, pi-tui for rendering.\n *\n * If not authenticated, offers interactive login/register before launching.\n *\n * Usage:\n * arbi-tui # Launch with default workspace\n * arbi-tui -w <workspace-id> # Launch with specific workspace\n */\n\n// Suppress SDK middleware logging\nconsole.debug = () => {}\nconst _origInfo = console.info\nconsole.info = (...args: unknown[]) => {\n if (typeof args[0] === 'string' && args[0].startsWith('[API]')) return\n _origInfo(...args)\n}\n\nimport { Command } from 'commander'\nimport { FileConfigStore, resolveWorkspace, workspaces } from '@arbidocs/core'\nimport { ArbiTui } from './tui.js'\nimport { ensureAuthenticated } from './auth.js'\n\nconst program = new Command()\n\nprogram\n .name('arbi-tui')\n .description('Interactive terminal UI for ARBI — chat with the RAG assistant')\n .version('0.1.0')\n .option('-w, --workspace <id>', 'Workspace ID to use')\n .action(async (opts: { workspace?: string }) => {\n const store = new FileConfigStore()\n\n // Ensure config exists\n try {\n store.requireConfig()\n } catch {\n console.error('Not configured. Run `arbi config set-url <url>` first.')\n process.exit(1)\n }\n\n // Authenticate — offers login/register if not already authenticated\n const { authContext, selectedWorkspaceId, selectedWorkspaceName } =\n await ensureAuthenticated(store)\n\n // Resolve workspace\n const workspaceId = opts.workspace || selectedWorkspaceId\n\n // Create and start TUI\n const tui = new ArbiTui(store)\n tui.setAuthContext(authContext)\n\n if (workspaceId) {\n try {\n const wsCtx = await resolveWorkspace(store, workspaceId)\n tui.setWorkspaceContext(wsCtx)\n\n // Get workspace name\n if (selectedWorkspaceName && workspaceId === selectedWorkspaceId) {\n tui.state.workspaceName = selectedWorkspaceName\n } else {\n const wsList = await workspaces.listWorkspaces(authContext.arbi)\n const ws = wsList.find((w) => w.external_id === workspaceId)\n if (ws) {\n tui.state.workspaceName = ws.name\n }\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n tui.chatLog.addSystem(`Failed to load workspace: ${msg}`, 'warning')\n tui.chatLog.addSystem('Use /workspaces to list and /workspace <id> to select.')\n }\n } else {\n tui.chatLog.addSystem(\n 'No workspace selected. Use /workspaces to list and /workspace <id> to select.'\n )\n }\n\n // Load chat session for conversation continuity\n const session = store.getChatSession()\n if (session.lastMessageExtId) {\n tui.state.conversationMessageId = session.lastMessageExtId\n }\n\n tui.chatLog.addSystem(\n 'Type a question to chat with the ARBI assistant. Use /help for commands.'\n )\n tui.start()\n })\n\nprogram.parse()\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arbidocs/tui",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Interactive terminal UI for ARBI — chat-style RAG assistant with streaming responses",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",