@arbidocs/blocks 0.4.76 → 0.4.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/dist/agents/index.cjs +346 -258
  2. package/dist/agents/index.js +5 -5
  3. package/dist/agents/tasks/TaskActivityTimeline.d.ts +1 -1
  4. package/dist/agents/tasks/WorkflowThreadStrip.d.ts +15 -4
  5. package/dist/agents/workflows/SchemaForm.d.ts +6 -1
  6. package/dist/agents/workflows/StepBarFrame.d.ts +75 -0
  7. package/dist/agents/workflows/StepParts.d.ts +109 -0
  8. package/dist/agents/workflows/WorkflowRunner.d.ts +15 -2
  9. package/dist/agents/workflows/WorkflowStepBar.d.ts +9 -11
  10. package/dist/agents/workflows/index.d.ts +5 -2
  11. package/dist/agents/workflows/planSteps.d.ts +8 -1
  12. package/dist/agents/workflows/run.d.ts +61 -8
  13. package/dist/agents/workflows/stepWindow.d.ts +59 -0
  14. package/dist/agents/workflows/types.d.ts +133 -4
  15. package/dist/agents/workflows/useWorkflowPreview.d.ts +2 -1
  16. package/dist/agents/workflows/useWorkflowView.d.ts +19 -0
  17. package/dist/chat/ChatPage.d.ts +1 -1
  18. package/dist/chat/WorkflowStepChip.d.ts +24 -0
  19. package/dist/chat/chat-page-types.d.ts +9 -0
  20. package/dist/chat/index.cjs +130 -122
  21. package/dist/chat/index.d.ts +1 -0
  22. package/dist/chat/index.js +2 -2
  23. package/dist/{chunk-TKB7TVMW.js → chunk-5OC5CGYX.js} +168 -100
  24. package/dist/chunk-5OC5CGYX.js.map +1 -0
  25. package/dist/{chunk-ZWA7UUZL.cjs → chunk-7YUFMNFW.cjs} +2 -54
  26. package/dist/chunk-7YUFMNFW.cjs.map +1 -0
  27. package/dist/chunk-A24C6BNA.js +92 -0
  28. package/dist/chunk-A24C6BNA.js.map +1 -0
  29. package/dist/chunk-AINNADMT.cjs +62 -0
  30. package/dist/chunk-AINNADMT.cjs.map +1 -0
  31. package/dist/chunk-CWAZNXC5.js +441 -0
  32. package/dist/chunk-CWAZNXC5.js.map +1 -0
  33. package/dist/{chunk-UIWLDSTF.js → chunk-EWSEQEPL.js} +71 -7
  34. package/dist/chunk-EWSEQEPL.js.map +1 -0
  35. package/dist/chunk-FE4ULGOR.js +151 -0
  36. package/dist/chunk-FE4ULGOR.js.map +1 -0
  37. package/dist/chunk-FT5FFXSJ.js +60 -0
  38. package/dist/chunk-FT5FFXSJ.js.map +1 -0
  39. package/dist/{chunk-WJEKRSPH.js → chunk-ICBAFX5B.js} +3 -3
  40. package/dist/{chunk-WJEKRSPH.js.map → chunk-ICBAFX5B.js.map} +1 -1
  41. package/dist/{chunk-7CVF3DK2.cjs → chunk-IF6VAYIA.cjs} +5 -5
  42. package/dist/{chunk-7CVF3DK2.cjs.map → chunk-IF6VAYIA.cjs.map} +1 -1
  43. package/dist/chunk-MLAHDAN5.cjs +450 -0
  44. package/dist/chunk-MLAHDAN5.cjs.map +1 -0
  45. package/dist/{chunk-IPGKTUF7.cjs → chunk-MP6FK43E.cjs} +71 -5
  46. package/dist/chunk-MP6FK43E.cjs.map +1 -0
  47. package/dist/{chunk-5EBGRG3X.js → chunk-OPA2Y6YZ.js} +3 -54
  48. package/dist/chunk-OPA2Y6YZ.js.map +1 -0
  49. package/dist/{chunk-7FKARMA3.cjs → chunk-SSDISIDW.cjs} +190 -122
  50. package/dist/chunk-SSDISIDW.cjs.map +1 -0
  51. package/dist/chunk-TZR36PPP.cjs +95 -0
  52. package/dist/chunk-TZR36PPP.cjs.map +1 -0
  53. package/dist/chunk-VFIZYSZB.cjs +2783 -0
  54. package/dist/chunk-VFIZYSZB.cjs.map +1 -0
  55. package/dist/chunk-WXRCMIAE.js +2707 -0
  56. package/dist/chunk-WXRCMIAE.js.map +1 -0
  57. package/dist/{chunk-HITAN7JF.cjs → chunk-XMBYDLZQ.cjs} +4 -4
  58. package/dist/{chunk-HITAN7JF.cjs.map → chunk-XMBYDLZQ.cjs.map} +1 -1
  59. package/dist/{chunk-MK6NJQGF.js → chunk-XQDM6T6C.js} +3 -3
  60. package/dist/{chunk-MK6NJQGF.js.map → chunk-XQDM6T6C.js.map} +1 -1
  61. package/dist/chunk-ZVBPRMHJ.cjs +153 -0
  62. package/dist/chunk-ZVBPRMHJ.cjs.map +1 -0
  63. package/dist/connect/docx.cjs +10 -88
  64. package/dist/connect/docx.cjs.map +1 -1
  65. package/dist/connect/docx.js +6 -86
  66. package/dist/connect/docx.js.map +1 -1
  67. package/dist/connect/index.cjs +468 -49
  68. package/dist/connect/index.cjs.map +1 -1
  69. package/dist/connect/index.d.ts +2 -0
  70. package/dist/connect/index.js +454 -37
  71. package/dist/connect/index.js.map +1 -1
  72. package/dist/connection/ConnectedTagMatrix.d.ts +20 -0
  73. package/dist/connection/ConnectedWorkflowRunner.d.ts +28 -2
  74. package/dist/connection/WorkflowRunThread.d.ts +21 -0
  75. package/dist/connection/WorkflowRunnerDialogs.d.ts +37 -0
  76. package/dist/connection/useWorkflowThread.d.ts +12 -0
  77. package/dist/document-tools/index.cjs +7 -143
  78. package/dist/document-tools/index.cjs.map +1 -1
  79. package/dist/document-tools/index.js +5 -144
  80. package/dist/document-tools/index.js.map +1 -1
  81. package/dist/docx/index.cjs +18 -17
  82. package/dist/docx/index.cjs.map +1 -1
  83. package/dist/docx/index.js +3 -2
  84. package/dist/docx/index.js.map +1 -1
  85. package/dist/facts/index.cjs +1 -1
  86. package/dist/facts/index.js +1 -1
  87. package/dist/files/index.cjs +1 -1
  88. package/dist/files/index.js +1 -1
  89. package/dist/home/index.cjs +1 -1
  90. package/dist/home/index.js +1 -1
  91. package/dist/index.cjs +560 -431
  92. package/dist/index.cjs.map +1 -1
  93. package/dist/index.d.ts +1 -0
  94. package/dist/index.js +10 -9
  95. package/dist/index.js.map +1 -1
  96. package/dist/shell/index.cjs +1 -1
  97. package/dist/shell/index.js +1 -1
  98. package/dist/studio/index.cjs +4 -4
  99. package/dist/studio/index.js +3 -3
  100. package/dist/tags/TagMatrix.d.ts +64 -0
  101. package/dist/tags/index.d.ts +3 -0
  102. package/dist/tags/tagMatrixModel.d.ts +39 -0
  103. package/dist/workflow-canvas/StepActionSettings.d.ts +132 -0
  104. package/dist/workflow-canvas/StepInspector.d.ts +25 -2
  105. package/dist/workflow-canvas/WorkflowBuilder.d.ts +11 -3
  106. package/dist/workflow-canvas/WorkflowCanvas.d.ts +27 -2
  107. package/dist/workflow-canvas/edit.d.ts +9 -1
  108. package/dist/workflow-canvas/index.cjs +882 -102
  109. package/dist/workflow-canvas/index.cjs.map +1 -1
  110. package/dist/workflow-canvas/index.js +849 -69
  111. package/dist/workflow-canvas/index.js.map +1 -1
  112. package/package.json +4 -4
  113. package/src/workflow-canvas/canvas.css +9 -0
  114. package/dist/chunk-22P5KNIM.js +0 -1422
  115. package/dist/chunk-22P5KNIM.js.map +0 -1
  116. package/dist/chunk-5EBGRG3X.js.map +0 -1
  117. package/dist/chunk-7FKARMA3.cjs.map +0 -1
  118. package/dist/chunk-IPGKTUF7.cjs.map +0 -1
  119. package/dist/chunk-TKB7TVMW.js.map +0 -1
  120. package/dist/chunk-UIWLDSTF.js.map +0 -1
  121. package/dist/chunk-VYRKO3XU.cjs +0 -1469
  122. package/dist/chunk-VYRKO3XU.cjs.map +0 -1
  123. package/dist/chunk-ZWA7UUZL.cjs.map +0 -1
@@ -10,6 +10,8 @@ export { ConnectedSkillUpload } from '../connection/ConnectedSkillUpload';
10
10
  export { useConnectedAiTask, useConnectedChat, ConnectedAssistantDock, useWorkspaceDocs, useSemanticSearch, toRedlineMarkdown, redlineStats, textToArtifact, type AiTaskStatus, type AiRunOptions, type SearchChunk, type ArtifactEvent, } from '../connection/ai';
11
11
  export { StreamedArtifact, type StreamedArtifactProps } from '../connection/StreamedArtifact';
12
12
  export { ConnectedWorkflowRunner, DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, type ConnectedWorkflowRunnerProps, type ConnectedWorkflowRunnerLabels, } from '../connection/ConnectedWorkflowRunner';
13
+ export { WorkflowRunThread, type WorkflowRunThreadProps } from '../connection/WorkflowRunThread';
14
+ export { ConnectedTagMatrix, type ConnectedTagMatrixProps } from '../connection/ConnectedTagMatrix';
13
15
  export { useConnectedShellWorkspaces, type UseConnectedShellWorkspacesOptions, } from '../connection/useConnectedShellWorkspaces';
14
16
  export { ConnectedProfileCard, ConnectedSecuritySection, ConnectedNotificationPreferences, ConnectedSessionsRow, ConnectedLogoutDialog, ConnectedDangerZone, ConnectedIdentityVerification, ConnectedRequireVerified, defaultUnmetPasswordRequirement, type SettingsNotify, type ConnectedProfileCardProps, type ConnectedSecuritySectionProps, type ConnectedNotificationPreferencesProps, type ConnectedSessionsRowProps, type ConnectedLogoutDialogProps, type ConnectedDangerZoneProps, type ConnectedIdentityVerificationProps, type ConnectedRequireVerifiedProps, } from '../connection/ConnectedSettings';
15
17
  export { useConnectedDocxNotifications } from '../connection/useConnectedDocxNotifications';
@@ -1,30 +1,35 @@
1
1
  "use client";
2
2
  import { SettingsSection, ProfileCard, AvatarPicker, IdentityVerificationCard, IdentityVerificationDialog, RequireVerified, SettingsCard, SettingsActionRow, PasswordChangeDialog, EMAIL_NOTIFICATION_KEYS, EMAIL_NOTIFICATION_CATEGORIES, NotificationCategoryList, toNotificationCategories, toActiveSessionViews, SettingsRow, ActiveSessionsDialog, LogoutDialog, toLogoutSessionViews, SettingsDangerZone, DeleteAccountDialog, toDeleteBlockerViews } from '../chunk-GJV2G4FC.js';
3
- import { useWorkspaceDocs } from '../chunk-MK6NJQGF.js';
4
- export { ConnectedAssistantDock, redlineStats, textToArtifact, toRedlineMarkdown, useConnectedAiTask, useConnectedChat, useSemanticSearch, useWorkspaceDocs } from '../chunk-MK6NJQGF.js';
3
+ import { useWorkspaceDocs } from '../chunk-XQDM6T6C.js';
4
+ export { ConnectedAssistantDock, redlineStats, textToArtifact, toRedlineMarkdown, useConnectedAiTask, useConnectedChat, useSemanticSearch, useWorkspaceDocs } from '../chunk-XQDM6T6C.js';
5
+ import { ConnectedNativeDocxEditor } from '../chunk-A24C6BNA.js';
5
6
  import { ConnectionProvider, useConnection } from '../chunk-OYMWV45N.js';
6
7
  export { ConnectionProvider, SESSION_EXPIRED_MESSAGE, isAuthenticated, useConnection } from '../chunk-OYMWV45N.js';
7
- import { WorkflowRunner, initialRunInputs, workflowSteps, fromPlanSteps, stepStatesFromActivity, toPlanSteps, runThreadTitle, useWorkflowView } from '../chunk-22P5KNIM.js';
8
- import '../chunk-EVUEIBNU.js';
8
+ import { SignDocumentDialog } from '../chunk-FE4ULGOR.js';
9
+ import '../chunk-OPA2Y6YZ.js';
10
+ import { TagMatrix, tagMatrixMarkdown } from '../chunk-CWAZNXC5.js';
11
+ import { splitDocRef, WorkflowStepBar, stepLevels, WorkflowRunner, initialRunInputs, workflowSteps, fromPlanSteps, stepStatesFromActivity, toPlanSteps, runThreadTitle, useWorkflowView, stepFields } from '../chunk-WXRCMIAE.js';
9
12
  import '../chunk-XD2M6LIG.js';
13
+ import '../chunk-EVUEIBNU.js';
10
14
  import { StreamedArtifactFrame } from '../chunk-LOJVUGBJ.js';
11
15
  import '../chunk-VILAPTCB.js';
12
- import { ChatPage } from '../chunk-UIWLDSTF.js';
16
+ import { ChatPage } from '../chunk-EWSEQEPL.js';
13
17
  import '../chunk-KZJAG7T3.js';
14
18
  import '../chunk-HOXKR26S.js';
15
19
  import '../chunk-AA3PT6KR.js';
16
20
  import '../chunk-NPLYHR2E.js';
17
21
  import { initials } from '../chunk-OXF2IFXG.js';
18
- import '../chunk-TX2ZICS7.js';
22
+ import { ModalScaffold } from '../chunk-TX2ZICS7.js';
19
23
  import '../chunk-7F6CBP3Z.js';
20
24
  import '../chunk-VUNV25KB.js';
21
- import { lazy, useState, Suspense, useCallback, useEffect, useMemo, useRef } from 'react';
25
+ import { lazy, useState, Suspense, useEffect, useRef, useCallback, useMemo } from 'react';
22
26
  import { QueryClient, QueryClientProvider, useQueryClient, useQuery } from '@tanstack/react-query';
23
- import { ArbiProvider, useConversations, useRunConversation, useUploadSkillFiles, ArtifactCanvas, useArbi, useDocuments, useWorkspaceUsers, useWorkspaces, useShellWorkspaces, useProfile, useUpdateProfile, useRequestEmailChange, useConfirmEmailChange, useNameEditor, useAvatarCrop, useEmailChange, ImageCropModal, useIdentityVerification, usePasswordChange, usePasswordChangeForm, useNotificationPreferences, useSessions, useCurrentSessionId, useTerminateSession, useLogoutAllSessions, useDeleteAccount, useDeleteAccountFlow, useArbiWebSocket, notify, useWorkNotifications, useAgentSession, useStartAgentSession, useCloseAgentSession, AiAnswer, ArbiWebSocketProvider, useCreateWork, useActOnStep, useConversationActivity, useConversationThreads, useArbiChat } from '@arbidocs/react';
27
+ import { ArbiProvider, useConversations, useRunConversation, useUploadSkillFiles, ArtifactCanvas, useArbiChat, useArbi, useDocuments, useTagMatrix, useUpdateTagFields, useInvalidateTagData, useWorkspaceUsers, useWorkspaces, useShellWorkspaces, useProfile, useUpdateProfile, useRequestEmailChange, useConfirmEmailChange, useNameEditor, useAvatarCrop, useEmailChange, ImageCropModal, useIdentityVerification, usePasswordChange, usePasswordChangeForm, useNotificationPreferences, useSessions, useCurrentSessionId, useTerminateSession, useLogoutAllSessions, useDeleteAccount, useDeleteAccountFlow, useArbiWebSocket, notify, useWorkNotifications, useAgentSession, useStartAgentSession, useCloseAgentSession, ArbiWebSocketProvider, useCreateWork, useActOnStep, useConversationActivity, useConversationThreads, useTags, AiAnswer } from '@arbidocs/react';
24
28
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
25
29
  import { Button, Label, Input, cn } from '@arbidocs/react/ui';
26
30
  import { useStreamedArtifact } from '@arbidocs/react/artifacts';
27
- import { ExternalLink, UserCircle, KeyRound, Radio, Loader2 } from 'lucide-react';
31
+ import { ExternalLink, UserCircle, KeyRound, Radio, Loader2, MessageSquare } from 'lucide-react';
32
+ import { useOptionalDocumentTools, DocumentToolsProvider } from '@arbidocs/react/document-tools';
28
33
  import { useNotify } from '@arbidocs/react/shell';
29
34
 
30
35
  function ConnectionBoundWebSocket({ children }) {
@@ -185,8 +190,15 @@ function StreamedArtifact({
185
190
  }
186
191
  var STARTING = /* @__PURE__ */ new Set(["pending", "running"]);
187
192
  function formValues(step, inputs) {
188
- if (step.kind !== "form") return void 0;
189
- return Object.fromEntries(step.inputs.map((f) => [f.name, inputs[f.name] ?? ""]));
193
+ const fields = stepFields(step);
194
+ if (!fields.length) return void 0;
195
+ if (step.kind === "form")
196
+ return Object.fromEntries(fields.map((f) => [f.name, inputs[f.name] ?? ""]));
197
+ const given = fields.flatMap((f) => {
198
+ const v = inputs[f.name];
199
+ return v === void 0 || v === "" ? [] : [[f.name, v]];
200
+ });
201
+ return given.length ? Object.fromEntries(given) : void 0;
190
202
  }
191
203
  var ANSWER_RETRY_CAP = 16;
192
204
  function answerRetryDelay(attempt) {
@@ -212,7 +224,7 @@ function useAnswerRetry(missing, refetch) {
212
224
  }
213
225
  function useWorkflowThread(workflow, options = {}) {
214
226
  const arbi = useArbi();
215
- const { ensureWorkspaceOpen } = useConnection();
227
+ const { ensureWorkspaceOpen, status } = useConnection();
216
228
  const { wsId } = useWorkspaceDocs();
217
229
  const [threadId, setThreadId] = useState(options.conversationId);
218
230
  const [localInputs, setLocalInputs] = useState(
@@ -223,6 +235,17 @@ function useWorkflowThread(workflow, options = {}) {
223
235
  const createWork = useCreateWork();
224
236
  const actOnStep = useActOnStep();
225
237
  const conversations = useConversations(wsId, { enabled: !!threadId, live: true });
238
+ const members = useWorkspaceUsers(wsId, {
239
+ enabled: status === "authenticated" && !!wsId,
240
+ beforeFetch: ensureWorkspaceOpen
241
+ });
242
+ const nameOf = useCallback(
243
+ (id) => {
244
+ const u = members.data?.find((m) => m.user.external_id === id)?.user;
245
+ return u ? [u.given_name, u.family_name].filter(Boolean).join(" ") || u.email : void 0;
246
+ },
247
+ [members.data]
248
+ );
226
249
  const conversation = conversations.data?.find((c) => c.external_id === threadId);
227
250
  const steps = useMemo(
228
251
  () => workflowSteps(workflow).length > 0 ? workflowSteps(workflow) : fromPlanSteps(conversation?.plan?.steps ?? []),
@@ -234,7 +257,7 @@ function useWorkflowThread(workflow, options = {}) {
234
257
  [activity.data]
235
258
  );
236
259
  const working = steps.some(
237
- (s) => s.kind === "agent" && STARTING.has(serverStates[s.id]?.status ?? "pending")
260
+ (s) => (s.kind === "agent" || s.kind === "action") && STARTING.has(serverStates[s.id]?.status ?? "pending")
238
261
  );
239
262
  const threads = useConversationThreads(wsId, threadId, { enabled: !!threadId, live: working });
240
263
  const answers = useMemo(() => {
@@ -306,7 +329,13 @@ function useWorkflowThread(workflow, options = {}) {
306
329
  setLocalStates((s) => ({ ...s, [step.id]: { status: "done" } }));
307
330
  options.onStarted?.(id);
308
331
  }
309
- await act(id, { step: step.id, action: "complete", inputs: formValues(step, values) });
332
+ const documents = step.kind === "upload" ? options.documentsFor?.(step.id) : void 0;
333
+ await act(id, {
334
+ step: step.id,
335
+ action: "complete",
336
+ inputs: formValues(step, values),
337
+ ...documents?.length ? { documents } : {}
338
+ });
310
339
  },
311
340
  [inputs, options, localStates, threadId, ensureWorkspaceOpen, createWork, workflow, act]
312
341
  );
@@ -328,6 +357,21 @@ function useWorkflowThread(workflow, options = {}) {
328
357
  },
329
358
  [arbi, threadId, refresh]
330
359
  );
360
+ const sendBack = useCallback(
361
+ async (stepId, to, note) => {
362
+ if (!threadId) return;
363
+ await act(threadId, { step: stepId, action: "send_back", to, ...note ? { note } : {} });
364
+ },
365
+ [threadId, act]
366
+ );
367
+ const decline = useCallback(
368
+ async (stepId, note) => {
369
+ if (!threadId) return;
370
+ await act(threadId, { step: stepId, action: "decline", ...note ? { note } : {} });
371
+ },
372
+ [threadId, act]
373
+ );
374
+ const loaded = !options.conversationId || activity.isSuccess || activity.isError;
331
375
  const view = useWorkflowView({
332
376
  steps,
333
377
  states,
@@ -336,12 +380,208 @@ function useWorkflowThread(workflow, options = {}) {
336
380
  complete,
337
381
  skip,
338
382
  retry,
383
+ sendBack,
384
+ decline,
385
+ nameOf,
386
+ loaded,
339
387
  isLocked: (id) => states[id]?.status === "done"
340
388
  });
341
- return { view, conversationId: threadId, conversation };
389
+ const people = useMemo(
390
+ () => (members.data ?? []).filter((m) => !m.user.external_id.startsWith("agt-")).map((m) => ({
391
+ value: m.user.external_id,
392
+ label: nameOf(m.user.external_id) ?? m.user.external_id
393
+ })),
394
+ [members.data, nameOf]
395
+ );
396
+ return { view, conversationId: threadId, conversation, nameOf, people };
397
+ }
398
+ function WorkflowRunThread({
399
+ conversationId,
400
+ workspaceId,
401
+ aside,
402
+ stepTitle,
403
+ targetMessageId,
404
+ onOpenCitation,
405
+ labels,
406
+ className
407
+ }) {
408
+ const chat = useArbiChat({ workspaceId });
409
+ const listed = chat.threads.some((t) => t.id === conversationId);
410
+ const { selectThread, activeThreadId } = chat;
411
+ useEffect(() => {
412
+ if (listed && activeThreadId !== conversationId) selectThread(conversationId);
413
+ }, [listed, activeThreadId, conversationId, selectThread]);
414
+ return /* @__PURE__ */ jsx(
415
+ ChatPage,
416
+ {
417
+ chat: { ...chat, threads: chat.threads.filter((t) => t.id === conversationId) },
418
+ singleThread: true,
419
+ documentsRequired: false,
420
+ aside,
421
+ asideBreakpoint: 52,
422
+ workflowStepTitle: stepTitle,
423
+ targetMessageId,
424
+ onOpenCitation,
425
+ labels,
426
+ className: className ?? "h-[min(78dvh,860px)] min-h-[480px] rounded-xl border border-border"
427
+ }
428
+ );
429
+ }
430
+ var DEFAULT_WORKFLOW_RUNNER_DIALOG_LABELS = {
431
+ loadingDocument: "Opening the document\u2026",
432
+ documentFailed: "The document could not be opened.",
433
+ reviewTitle: "Review",
434
+ reviewDescription: "Each document against each review column.",
435
+ document: "Document",
436
+ empty: "\u2014",
437
+ wordTitle: "Tracked changes"
438
+ };
439
+ function WorkflowSignDialog({
440
+ docRef,
441
+ onClose,
442
+ labels
443
+ }) {
444
+ const arbi = useArbi();
445
+ const { user, ensureWorkspaceOpen } = useConnection();
446
+ const tools = useOptionalDocumentTools();
447
+ const { id, version } = splitDocRef(docRef);
448
+ const [pdf, setPdf] = useState(null);
449
+ const [failed, setFailed] = useState(false);
450
+ useEffect(() => {
451
+ let live = true;
452
+ void (async () => {
453
+ try {
454
+ await ensureWorkspaceOpen();
455
+ const res = await arbi.documents.download(id, version);
456
+ if (!res.ok) throw new Error(String(res.status));
457
+ const blob = await res.blob();
458
+ if (live) setPdf(blob);
459
+ } catch {
460
+ if (live) setFailed(true);
461
+ }
462
+ })();
463
+ return () => {
464
+ live = false;
465
+ };
466
+ }, [arbi, id, version, ensureWorkspaceOpen]);
467
+ if (!pdf)
468
+ return /* @__PURE__ */ jsx(
469
+ ModalScaffold,
470
+ {
471
+ open: true,
472
+ onOpenChange: (o) => !o && onClose(),
473
+ title: labels.loadingDocument,
474
+ size: "sm",
475
+ testId: "workflow-sign-loading",
476
+ children: /* @__PURE__ */ jsx(ModalScaffold.Body, { children: /* @__PURE__ */ jsx("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: failed ? labels.documentFailed : /* @__PURE__ */ jsxs(Fragment, { children: [
477
+ /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }),
478
+ " ",
479
+ labels.loadingDocument
480
+ ] }) }) })
481
+ }
482
+ );
483
+ const dialog = /* @__PURE__ */ jsx(SignDocumentDialog, { open: true, onOpenChange: (o) => !o && onClose(), documentId: id, pdfBlob: pdf });
484
+ return tools ? dialog : /* @__PURE__ */ jsx(
485
+ DocumentToolsProvider,
486
+ {
487
+ client: arbi.getClient().fetch,
488
+ user: user ? { name: user.name, email: user.email } : null,
489
+ children: dialog
490
+ }
491
+ );
492
+ }
493
+ function WorkflowWordDialog({
494
+ docRef,
495
+ title,
496
+ onClose,
497
+ labels
498
+ }) {
499
+ const { id } = splitDocRef(docRef);
500
+ return /* @__PURE__ */ jsx(
501
+ ModalScaffold,
502
+ {
503
+ open: true,
504
+ onOpenChange: (o) => !o && onClose(),
505
+ title: title ?? labels.wordTitle,
506
+ size: "xl",
507
+ testId: "workflow-word-dialog",
508
+ children: /* @__PURE__ */ jsx(ModalScaffold.Body, { className: "h-[70dvh] p-0", children: /* @__PURE__ */ jsx(ConnectedNativeDocxEditor, { documentId: id, title: title ?? labels.wordTitle }) })
509
+ }
510
+ );
511
+ }
512
+ function WorkflowReviewGridDialog({
513
+ tags,
514
+ documents,
515
+ onClose,
516
+ onOpenDocument,
517
+ labels
518
+ }) {
519
+ const { workspaceId } = useConnection();
520
+ const allTags = useTags(workspaceId ?? void 0);
521
+ const all = useDocuments(workspaceId ?? void 0);
522
+ const docs = {
523
+ isLoading: all.isLoading,
524
+ data: (all.data ?? []).filter((d) => documents.includes(d.external_id))
525
+ };
526
+ const columns = useMemo(
527
+ () => tags.map((id) => ({
528
+ id,
529
+ name: allTags.data?.find((t) => t.external_id === id)?.name ?? id
530
+ })),
531
+ [tags, allTags.data]
532
+ );
533
+ return /* @__PURE__ */ jsx(
534
+ ModalScaffold,
535
+ {
536
+ open: true,
537
+ onOpenChange: (o) => !o && onClose(),
538
+ title: labels.reviewTitle,
539
+ description: labels.reviewDescription,
540
+ showDescription: true,
541
+ size: "xl",
542
+ testId: "workflow-review-grid",
543
+ children: /* @__PURE__ */ jsx(ModalScaffold.Body, { className: "overflow-auto", children: docs.isLoading ? /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
544
+ /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }),
545
+ " ",
546
+ labels.loadingDocument
547
+ ] }) : /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-sm", children: [
548
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
549
+ /* @__PURE__ */ jsx("th", { className: "sticky left-0 border-b border-border bg-card p-2 text-left font-medium", children: labels.document }),
550
+ columns.map((c) => /* @__PURE__ */ jsx("th", { className: "border-b border-border p-2 text-left font-medium", children: c.name }, c.id))
551
+ ] }) }),
552
+ /* @__PURE__ */ jsx("tbody", { children: (docs.data ?? []).map((d) => /* @__PURE__ */ jsxs("tr", { "data-testid": `workflow-review-grid-row-${d.external_id}`, children: [
553
+ /* @__PURE__ */ jsx("td", { className: "sticky left-0 max-w-56 border-b border-border bg-card p-2 align-top", children: /* @__PURE__ */ jsx(Cell, { onClick: onOpenDocument && (() => onOpenDocument(d.external_id)), children: d.file_name ?? d.external_id }) }),
554
+ columns.map((c) => {
555
+ const note = d.doctags?.find((t) => t.tag_ext_id === c.id)?.note;
556
+ return /* @__PURE__ */ jsx(
557
+ "td",
558
+ {
559
+ className: "max-w-72 border-b border-border p-2 align-top text-muted-foreground",
560
+ children: /* @__PURE__ */ jsx("span", { className: "line-clamp-4 whitespace-pre-line", children: note || labels.empty })
561
+ },
562
+ c.id
563
+ );
564
+ })
565
+ ] }, d.external_id)) })
566
+ ] }) })
567
+ }
568
+ );
569
+ }
570
+ function Cell({ onClick, children }) {
571
+ return onClick ? /* @__PURE__ */ jsx(
572
+ "button",
573
+ {
574
+ type: "button",
575
+ onClick,
576
+ className: "truncate text-left font-medium text-primary hover:underline",
577
+ children
578
+ }
579
+ ) : /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children });
342
580
  }
343
581
  var DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS = {
344
582
  notify: "Ask to approve",
583
+ showInThread: "Show in the thread",
584
+ currentStep: "Current step",
345
585
  notified: "Notified.",
346
586
  openThread: "Open the thread",
347
587
  loadingAnswer: "Fetching the answer\u2026"
@@ -352,17 +592,56 @@ function ConnectedWorkflowRunner({
352
592
  onOpenConversation,
353
593
  emptyHint,
354
594
  connectedLabels,
595
+ onOpenDocument,
596
+ onOpenDraft,
597
+ onOpenMessage,
598
+ actions: hostActions,
599
+ dialogLabels,
600
+ layout = "thread",
355
601
  testIdPrefix = "workflow-run",
356
602
  ...runnerProps
357
603
  }) {
358
604
  const l = { ...DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, ...connectedLabels };
605
+ const dl = { ...DEFAULT_WORKFLOW_RUNNER_DIALOG_LABELS, ...dialogLabels };
359
606
  const arbi = useArbi();
360
- const { ensureWorkspaceOpen } = useConnection();
607
+ const { ensureWorkspaceOpen, user } = useConnection();
361
608
  const { wsId } = useWorkspaceDocs();
362
609
  const { data: docs = [], refetch } = useDocuments(wsId);
363
610
  const [uploading, setUploading] = useState(false);
364
- const { view, conversationId } = useWorkflowThread(workflow, options);
365
611
  const [added, setAdded] = useState({});
612
+ const addedRef = useRef(added);
613
+ addedRef.current = added;
614
+ const { view, conversationId, people } = useWorkflowThread(workflow, {
615
+ ...options,
616
+ // An upload step records exactly the files added on it (else the server's guess).
617
+ documentsFor: options?.documentsFor ?? ((stepId) => Object.entries(addedRef.current).flatMap(([doc, step]) => step === stepId ? [doc] : []))
618
+ });
619
+ const [dialog, setDialog] = useState(null);
620
+ const inThread = layout === "thread" && !!conversationId;
621
+ const [target, setTarget] = useState(void 0);
622
+ const nameOfDoc = useCallback(
623
+ (id) => docs.find((d) => d.external_id === id)?.file_name ?? void 0,
624
+ [docs]
625
+ );
626
+ const actions = useMemo(
627
+ () => ({
628
+ me: user?.externalId,
629
+ openDocument: onOpenDocument && ((ref) => {
630
+ const { id, version } = splitDocRef(ref);
631
+ onOpenDocument(id, version);
632
+ }),
633
+ openDraft: onOpenDraft && ((draftId) => onOpenDraft(draftId)),
634
+ // In the thread layout an answer is right there: scroll to it.
635
+ openMessage: inThread ? setTarget : onOpenMessage,
636
+ sign: hostActions?.sign ?? ((_step, state) => {
637
+ const w = state.waiting;
638
+ if (w?.doc_ext_id) setDialog({ kind: "sign", docRef: w.doc_ext_id });
639
+ }),
640
+ openRedline: hostActions?.openRedline ?? ((ref) => setDialog({ kind: "word", docRef: ref, title: nameOfDoc(splitDocRef(ref).id) ?? "" })),
641
+ openReview: hostActions?.openReview ?? ((tags, documents) => setDialog({ kind: "review", tags, documents }))
642
+ }),
643
+ [user?.externalId, onOpenDocument, onOpenDraft, onOpenMessage, hostActions, nameOfDoc, inThread]
644
+ );
366
645
  const onUpload = useCallback(
367
646
  async (files2, step) => {
368
647
  if (!files2.length) return;
@@ -394,6 +673,23 @@ function ConnectedWorkflowRunner({
394
673
  }, [reading, refetch]);
395
674
  const renderAgentOutput = (step, state) => {
396
675
  const status = state?.status;
676
+ if (inThread) {
677
+ const id = state?.responseId;
678
+ return id && status === "done" ? /* @__PURE__ */ jsxs(
679
+ Button,
680
+ {
681
+ variant: "outline",
682
+ size: "sm",
683
+ onClick: () => setTarget(id),
684
+ "data-testid": `${testIdPrefix}-${step.id}-show-in-thread`,
685
+ children: [
686
+ /* @__PURE__ */ jsx(MessageSquare, { className: "size-4" }),
687
+ " ",
688
+ l.showInThread
689
+ ]
690
+ }
691
+ ) : null;
692
+ }
397
693
  if (!state?.text && status !== "done") return null;
398
694
  if (!state?.text && state?.responseId) {
399
695
  return /* @__PURE__ */ jsxs(
@@ -419,6 +715,34 @@ function ConnectedWorkflowRunner({
419
715
  }
420
716
  );
421
717
  };
718
+ const runner = (compact) => /* @__PURE__ */ jsx(
719
+ WorkflowRunner,
720
+ {
721
+ people,
722
+ ...runnerProps,
723
+ workflow,
724
+ run: view,
725
+ renderAgentOutput,
726
+ renderReview: (step) => conversationId ? /* @__PURE__ */ jsx(
727
+ ReviewNotify,
728
+ {
729
+ conversationId,
730
+ workspaceId: wsId,
731
+ labels: l,
732
+ testId: `${testIdPrefix}-${step.id}`
733
+ }
734
+ ) : null,
735
+ onUpload,
736
+ uploading,
737
+ files,
738
+ actions,
739
+ nameOfDoc,
740
+ testIdPrefix,
741
+ hideStepBar: compact,
742
+ compact,
743
+ className: compact ? void 0 : runnerProps.className
744
+ }
745
+ );
422
746
  return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
423
747
  conversationId && onOpenConversation && /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs(
424
748
  Button,
@@ -434,26 +758,47 @@ function ConnectedWorkflowRunner({
434
758
  ]
435
759
  }
436
760
  ) }),
437
- /* @__PURE__ */ jsx(
438
- WorkflowRunner,
761
+ inThread && conversationId ? /* @__PURE__ */ jsxs(Fragment, { children: [
762
+ /* @__PURE__ */ jsx(
763
+ WorkflowStepBar,
764
+ {
765
+ run: view,
766
+ levels: stepLevels(view.steps),
767
+ doneTitle: (workflow.run.kind === "steps" ? workflow.run.completion?.title : void 0) ?? runnerProps.labels?.complete ?? "Done",
768
+ icon: (key) => key && runnerProps.renderIcon ? runnerProps.renderIcon(key) : void 0,
769
+ tid: (suffix) => `${testIdPrefix}-${suffix}`
770
+ }
771
+ ),
772
+ /* @__PURE__ */ jsx(
773
+ WorkflowRunThread,
774
+ {
775
+ conversationId,
776
+ workspaceId: wsId,
777
+ stepTitle: (id) => view.steps.find((s) => s.id === id)?.title,
778
+ targetMessageId: target,
779
+ labels: { workflows: l.currentStep },
780
+ aside: runner(true)
781
+ }
782
+ )
783
+ ] }) : runner(false),
784
+ dialog?.kind === "sign" && /* @__PURE__ */ jsx(WorkflowSignDialog, { docRef: dialog.docRef, onClose: () => setDialog(null), labels: dl }),
785
+ dialog?.kind === "word" && /* @__PURE__ */ jsx(
786
+ WorkflowWordDialog,
439
787
  {
440
- ...runnerProps,
441
- workflow,
442
- run: view,
443
- renderAgentOutput,
444
- renderReview: (step) => conversationId ? /* @__PURE__ */ jsx(
445
- ReviewNotify,
446
- {
447
- conversationId,
448
- workspaceId: wsId,
449
- labels: l,
450
- testId: `${testIdPrefix}-${step.id}`
451
- }
452
- ) : null,
453
- onUpload,
454
- uploading,
455
- files,
456
- testIdPrefix
788
+ docRef: dialog.docRef,
789
+ title: dialog.title || void 0,
790
+ onClose: () => setDialog(null),
791
+ labels: dl
792
+ }
793
+ ),
794
+ dialog?.kind === "review" && /* @__PURE__ */ jsx(
795
+ WorkflowReviewGridDialog,
796
+ {
797
+ tags: dialog.tags,
798
+ documents: dialog.documents,
799
+ onClose: () => setDialog(null),
800
+ onOpenDocument: onOpenDocument && ((id) => onOpenDocument(id)),
801
+ labels: dl
457
802
  }
458
803
  )
459
804
  ] });
@@ -530,6 +875,78 @@ function ReviewNotify({
530
875
  ] })
531
876
  ] });
532
877
  }
878
+ function ConnectedTagMatrix({
879
+ parentId,
880
+ linksLimit = 3,
881
+ exportTitle,
882
+ onExported,
883
+ readOnly,
884
+ ...props
885
+ }) {
886
+ const arbi = useArbi();
887
+ const { workspaceId, status, ensureWorkspaceOpen } = useConnection();
888
+ const matrix = useTagMatrix({ parentId }, { linksLimit });
889
+ const update = useUpdateTagFields();
890
+ const invalidate = useInvalidateTagData();
891
+ const members = useWorkspaceUsers(workspaceId ?? void 0, {
892
+ enabled: status === "authenticated" && !!workspaceId,
893
+ beforeFetch: ensureWorkspaceOpen
894
+ });
895
+ const [error, setError] = useState(null);
896
+ const people = (members.data ?? []).map((m) => ({
897
+ value: m.user.external_id,
898
+ label: [m.user.given_name, m.user.family_name].filter(Boolean).join(" ") || m.user.email
899
+ }));
900
+ const fail = (e) => setError(e instanceof Error ? e.message : String(e));
901
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
902
+ /* @__PURE__ */ jsx(
903
+ TagMatrix,
904
+ {
905
+ ...props,
906
+ matrix: matrix.data,
907
+ isLoading: matrix.isLoading,
908
+ people,
909
+ onChangeValue: readOnly ? void 0 : async (tagId, fieldId, value) => {
910
+ setError(null);
911
+ await update.mutateAsync({ tagId, values: { [fieldId]: value } }).catch(fail);
912
+ },
913
+ onAddRow: readOnly ? void 0 : async (name) => {
914
+ setError(null);
915
+ try {
916
+ await ensureWorkspaceOpen();
917
+ await arbi.tags.create({ name, parentId });
918
+ await invalidate();
919
+ } catch (e) {
920
+ fail(e);
921
+ }
922
+ },
923
+ onExport: onExported && matrix.data ? async () => {
924
+ setError(null);
925
+ try {
926
+ const data = matrix.data;
927
+ if (!data) return;
928
+ const title = exportTitle ?? data.parent?.name ?? "Matrix";
929
+ const markdown = tagMatrixMarkdown(data, {
930
+ title,
931
+ nameOf: (id2) => people.find((p) => p.value === id2)?.label
932
+ });
933
+ await ensureWorkspaceOpen();
934
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
935
+ const uploaded = await arbi.documents.uploadFile(
936
+ new Blob([markdown], { type: "text/markdown" }),
937
+ `${title} (${stamp}).md`
938
+ );
939
+ const id = uploaded?.doc_ext_ids?.[0];
940
+ if (id) onExported(id);
941
+ } catch (e) {
942
+ fail(e);
943
+ }
944
+ } : void 0
945
+ }
946
+ ),
947
+ error && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-destructive", children: error })
948
+ ] });
949
+ }
533
950
  function useConnectedShellWorkspaces(options = {}) {
534
951
  const { workspaceId, setWorkspace } = useConnection();
535
952
  const query = useWorkspaces();
@@ -1128,6 +1545,6 @@ function ConnectedAgentChatPanel({
1128
1545
  ] });
1129
1546
  }
1130
1547
 
1131
- export { ArbiAppProvider, ConnectedAgentChatPanel, ConnectedDangerZone, ConnectedIdentityVerification, ConnectedLogoutDialog, ConnectedNotificationPreferences, ConnectedProfileCard, ConnectedRequireVerified, ConnectedSecuritySection, ConnectedSessionsRow, ConnectedSkillUpload, ConnectedTaskAccessRequest, ConnectedWorkflowRunner, DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, StreamedArtifact, defaultUnmetPasswordRequirement, useConnectedDocxNotifications, useConnectedShellWorkspaces, useConnectedWorkNotifications };
1548
+ export { ArbiAppProvider, ConnectedAgentChatPanel, ConnectedDangerZone, ConnectedIdentityVerification, ConnectedLogoutDialog, ConnectedNotificationPreferences, ConnectedProfileCard, ConnectedRequireVerified, ConnectedSecuritySection, ConnectedSessionsRow, ConnectedSkillUpload, ConnectedTagMatrix, ConnectedTaskAccessRequest, ConnectedWorkflowRunner, DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, StreamedArtifact, WorkflowRunThread, defaultUnmetPasswordRequirement, useConnectedDocxNotifications, useConnectedShellWorkspaces, useConnectedWorkNotifications };
1132
1549
  //# sourceMappingURL=index.js.map
1133
1550
  //# sourceMappingURL=index.js.map