@mcp-b/react-components 0.47.0 → 0.48.0

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 (127) hide show
  1. package/dist/{CodeBlock-DMHZiw86.js → CodeBlock-BSJl682D.js} +1 -1
  2. package/dist/Correspondent-7K6uNLUm.d.ts +64 -0
  3. package/dist/{FileTree-BHebfvkK.js → FileTree-DvE0hNZu.js} +1 -1
  4. package/dist/{SetupChecklist-CwRjIDH4.js → SetupChecklist-DeTU9YpW.js} +1 -1
  5. package/dist/{ThinkChat-DLDta57t.js → ThinkChat-DiI6hhDP.js} +3 -3
  6. package/dist/{Workspace-C_zHq9KZ.d.ts → Workspace-LIoU30n7.d.ts} +13 -2
  7. package/dist/{WorkspaceFileView-ChIJz-fl.js → WorkspaceFileView-C_WnYm-a.js} +3 -3
  8. package/dist/{WorkspaceLive-DLGhtIly.d.ts → WorkspaceLive-DfjH1Ypm.d.ts} +12 -0
  9. package/dist/{WorkspaceMessageResponse-Dg_aNpoj.js → WorkspaceMessageResponse-BqOezptB.js} +4 -1
  10. package/dist/components/agents-sdk/AgentActivity.js +1 -1
  11. package/dist/components/agents-sdk/AgentChat.js +10 -10
  12. package/dist/components/agents-sdk/AgentEvent.js +1 -1
  13. package/dist/components/agents-sdk/BrowserLiveScreen.js +1 -1
  14. package/dist/components/agents-sdk/BrowserLiveView.js +1 -1
  15. package/dist/components/agents-sdk/BrowserReplay.js +1 -1
  16. package/dist/components/agents-sdk/BrowserRunPanel.js +1 -1
  17. package/dist/components/agents-sdk/ManagerOffice.d.ts +41 -50
  18. package/dist/components/agents-sdk/ManagerOffice.js +360 -979
  19. package/dist/components/agents-sdk/McpConnectionRequest.js +2 -2
  20. package/dist/components/agents-sdk/McpConnectorForm.js +1 -1
  21. package/dist/components/agents-sdk/McpPluginCatalog.js +2 -2
  22. package/dist/components/agents-sdk/McpServerPicker.js +2 -2
  23. package/dist/components/agents-sdk/ModelSelector.js +3 -3
  24. package/dist/components/agents-sdk/PromptInputApproval.js +1 -1
  25. package/dist/components/agents-sdk/PromptInputCommands.js +1 -1
  26. package/dist/components/agents-sdk/SubagentRunIndicator.js +1 -1
  27. package/dist/components/agents-sdk/SubagentRunSelector.js +1 -1
  28. package/dist/components/agents-sdk/ThinkChat.js +1 -1
  29. package/dist/components/agents-sdk/ThinkChatActivity.js +1 -1
  30. package/dist/components/agents-sdk/ThinkChatToolPanels.js +2 -2
  31. package/dist/components/agents-sdk/ThinkExecutionDetail.js +2 -2
  32. package/dist/components/agents-sdk/ThinkExecutionStatus.js +1 -1
  33. package/dist/components/agents-sdk/ThinkExecutionWorkbench.js +3 -3
  34. package/dist/components/agents-sdk/ThinkFullApp.d.ts +3 -3
  35. package/dist/components/agents-sdk/ThinkFullApp.js +9 -4
  36. package/dist/components/agents-sdk/ThinkFullAppViewSwitch.js +1 -1
  37. package/dist/components/agents-sdk/ThinkRecoveryNotice.js +1 -1
  38. package/dist/components/agents-sdk/ThinkRoutineBrowser.js +2 -2
  39. package/dist/components/agents-sdk/ThinkRoutineDetail.js +1 -1
  40. package/dist/components/agents-sdk/ThinkRoutineForm.js +4 -4
  41. package/dist/components/agents-sdk/ThinkRoutineLibrary.js +3 -3
  42. package/dist/components/agents-sdk/ThinkRoutineRuns.js +1 -1
  43. package/dist/components/agents-sdk/ThinkSidepanel.js +10 -10
  44. package/dist/components/agents-sdk/ThinkThreadPicker.js +4 -4
  45. package/dist/components/agents-sdk/Workspace.d.ts +2 -2
  46. package/dist/components/agents-sdk/Workspace.js +13 -10
  47. package/dist/components/agents-sdk/WorkspaceBrowser.d.ts +1 -1
  48. package/dist/components/agents-sdk/WorkspaceBrowser.js +1 -1
  49. package/dist/components/agents-sdk/WorkspaceConcept.d.ts +3 -2
  50. package/dist/components/agents-sdk/WorkspaceConcept.js +3 -3
  51. package/dist/components/agents-sdk/WorkspaceCorrespondence.d.ts +5 -9
  52. package/dist/components/agents-sdk/WorkspaceCorrespondence.js +44 -44
  53. package/dist/components/agents-sdk/WorkspaceExecution.d.ts +30 -21
  54. package/dist/components/agents-sdk/WorkspaceExecution.js +104 -167
  55. package/dist/components/agents-sdk/WorkspaceExplorer.d.ts +1 -1
  56. package/dist/components/agents-sdk/WorkspaceExplorer.js +1 -1
  57. package/dist/components/agents-sdk/WorkspaceFileView.js +1 -1
  58. package/dist/components/agents-sdk/WorkspaceHeader.js +1 -1
  59. package/dist/components/agents-sdk/WorkspaceLive.d.ts +1 -1
  60. package/dist/components/agents-sdk/WorkspaceLive.js +33 -5
  61. package/dist/components/agents-sdk/WorkspaceMessageResponse.js +1 -1
  62. package/dist/components/agents-sdk/WorkspaceMountManager.js +2 -2
  63. package/dist/components/agents-sdk/WorkspaceProject.d.ts +43 -5
  64. package/dist/components/agents-sdk/WorkspaceProject.js +62 -25
  65. package/dist/components/agents-sdk/WorkspaceUserScript.js +4 -4
  66. package/dist/components/ai-sdk/Activity.js +1 -1
  67. package/dist/components/ai-sdk/AgentChatStartScreen.js +1 -1
  68. package/dist/components/ai-sdk/Approval.js +2 -2
  69. package/dist/components/ai-sdk/Artifact.js +3 -3
  70. package/dist/components/ai-sdk/ChainOfThought.js +1 -1
  71. package/dist/components/ai-sdk/Checkpoint.js +1 -1
  72. package/dist/components/ai-sdk/CodeBlock.js +1 -1
  73. package/dist/components/ai-sdk/ComposerLink.js +1 -1
  74. package/dist/components/ai-sdk/ConnectedAppCards.d.ts +7 -0
  75. package/dist/components/ai-sdk/ConnectedAppCards.js +48 -80
  76. package/dist/components/ai-sdk/Conversation.js +1 -1
  77. package/dist/components/ai-sdk/Correspondent.d.ts +2 -0
  78. package/dist/components/ai-sdk/Correspondent.js +145 -0
  79. package/dist/components/ai-sdk/Goal.js +1 -1
  80. package/dist/components/ai-sdk/InlineCitation.js +1 -1
  81. package/dist/components/ai-sdk/MediaPreviewCard.js +1 -1
  82. package/dist/components/ai-sdk/Message.js +1 -1
  83. package/dist/components/ai-sdk/MessageScroller.js +1 -1
  84. package/dist/components/ai-sdk/MessageScrollerVirtual.js +1 -1
  85. package/dist/components/ai-sdk/Plan.js +1 -1
  86. package/dist/components/ai-sdk/PromptInput.js +5 -5
  87. package/dist/components/ai-sdk/Queue.js +1 -1
  88. package/dist/components/ai-sdk/Reasoning.js +1 -1
  89. package/dist/components/ai-sdk/Sources.js +1 -1
  90. package/dist/components/ai-sdk/Task.js +1 -1
  91. package/dist/components/extension/ChatGptSignInScreen.js +1 -1
  92. package/dist/components/extension/CodexModelSelector.js +2 -2
  93. package/dist/components/extension/ConversationTabPicker.js +2 -2
  94. package/dist/components/foundations/Checkbox.js +1 -1
  95. package/dist/components/foundations/Collapsible.js +1 -1
  96. package/dist/components/foundations/ContextMenu.js +1 -1
  97. package/dist/components/foundations/Menubar.js +1 -1
  98. package/dist/components/foundations/SearchField.js +1 -1
  99. package/dist/components/foundations/Select.js +1 -1
  100. package/dist/components/foundations/Stepper.js +1 -1
  101. package/dist/components/foundations/Toast.js +1 -1
  102. package/dist/components/foundations/ToggleGroup.d.ts +1 -1
  103. package/dist/components/foundations/ToggleGroup.js +1 -1
  104. package/dist/components/foundations/icons.js +1 -1
  105. package/dist/components/general-purpose/Commit.js +2 -2
  106. package/dist/components/general-purpose/EnvironmentVariables.js +2 -2
  107. package/dist/components/general-purpose/FileTree.js +1 -1
  108. package/dist/components/general-purpose/PricingBillingToggle.js +1 -1
  109. package/dist/components/general-purpose/PricingPlanCard.js +2 -2
  110. package/dist/components/general-purpose/PricingUsageCalculator.js +2 -2
  111. package/dist/components/general-purpose/ResponsiveSidebarShell.js +1 -1
  112. package/dist/components/general-purpose/SettingsFormDialog.js +2 -2
  113. package/dist/components/general-purpose/SetupChecklist.js +1 -1
  114. package/dist/components/general-purpose/Terminal.js +2 -2
  115. package/dist/components/general-purpose/TestResults.js +1 -1
  116. package/dist/components/general-purpose/ThemeModeControl.js +2 -2
  117. package/dist/components/general-purpose/WebPreview.js +2 -2
  118. package/dist/components/nanites/AgentConnection.js +2 -2
  119. package/dist/components/nanites/AgentToolDetail.js +5 -5
  120. package/dist/{copy-button-CSDuDfdP.js → copy-button-Dk2vRe9j.js} +1 -1
  121. package/dist/styles/base.css +2 -2
  122. package/dist/styles/correspondent.css +73 -0
  123. package/dist/styles/index.css +1 -0
  124. package/dist/styles/manager-office.css +380 -1086
  125. package/dist/{workspace-assets-CxpEHsac.js → workspace-assets-GqsCYxqT.js} +16 -2
  126. package/package.json +2 -2
  127. package/dist/{icons-cuEtsgj9.js → icons-CeGfXO21.js} +1 -1
@@ -1,22 +1,25 @@
1
1
  import { t as cx } from "../../class-names-BiMDVpUo.js";
2
- import { S as FileIcon, d as CheckIcon } from "../../icons-cuEtsgj9.js";
2
+ import { S as FileIcon, d as CheckIcon } from "../../icons-CeGfXO21.js";
3
3
  import { Button } from "../foundations/Button.js";
4
- import { IconButton } from "../foundations/IconButton.js";
5
- import { a as formatErrorMessage } from "../../format-COCyV98Z.js";
6
4
  import { Field } from "../foundations/Field.js";
7
5
  import { Textarea } from "../foundations/Textarea.js";
8
- import { Input } from "../foundations/Input.js";
9
- import { DescriptionList } from "../foundations/DescriptionList.js";
6
+ import { IconButton } from "../foundations/IconButton.js";
7
+ import { a as formatErrorMessage } from "../../format-COCyV98Z.js";
10
8
  import { Card, CardAction, CardContent, CardFooter, CardHeader, CardTitle } from "../foundations/Card.js";
9
+ import { DescriptionList } from "../foundations/DescriptionList.js";
10
+ import { Input } from "../foundations/Input.js";
11
11
  import { EmailMessageCard, SlackMessageCard } from "../ai-sdk/ConnectedAppCards.js";
12
- import { i as WorkspaceDeleteControl, r as httpUrl, t as FaviconMark } from "../../workspace-assets-CxpEHsac.js";
12
+ import { i as WorkspaceDeleteControl, r as httpUrl, t as FaviconMark } from "../../workspace-assets-GqsCYxqT.js";
13
13
  import * as React from "react";
14
+ import { createElement } from "react";
14
15
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
15
- import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
16
+ import { hashKey, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
16
17
  //#region src/components/agents-sdk/WorkspaceCorrespondence.tsx
17
18
  const SAVE_DEBOUNCE_MS = 400;
18
19
  const SEND_BLOCKED_MESSAGE = "Your edit has not saved, so nothing was sent. Retry the save first.";
19
20
  const FILE_MISSING_MESSAGE = "The file is no longer in the workspace.";
21
+ const SAVE_UNAVAILABLE_MESSAGE = "Saving is no longer available.";
22
+ const SEND_UNAVAILABLE_MESSAGE = "Sending is no longer available.";
20
23
  function fieldValue(fields, name) {
21
24
  return fields.find((field) => field.name === name)?.value;
22
25
  }
@@ -298,11 +301,17 @@ function WorkspaceCorrespondenceCard({ body, fields, kind, path, icon, saveState
298
301
  * flushes the outstanding edit first and refuses when that save fails — the
299
302
  * agent must never be told to send content the workspace does not hold.
300
303
  *
301
- * Interaction state belongs to one file. The adapter resets it when the
302
- * source's query key changes, but hosts should still key this element by path
303
- * where a placement can swap files, so React reconciles it as a new card.
304
+ * Interaction state belongs to one query identity. The keyed session makes a
305
+ * source swap a real unmount, so an old save or send cannot settle onto the
306
+ * next file.
304
307
  */
305
- function WorkspaceCorrespondenceFile({ fallback = null, source, ...props }) {
308
+ function WorkspaceCorrespondenceFile(props) {
309
+ return /* @__PURE__ */ createElement(WorkspaceCorrespondenceFileSession, {
310
+ ...props,
311
+ key: hashKey(props.source.queryOptions.queryKey)
312
+ });
313
+ }
314
+ function WorkspaceCorrespondenceFileSession({ fallback = null, source, ...props }) {
306
315
  const queryClient = useQueryClient();
307
316
  const persisted = useQuery(source.queryOptions).data ?? null;
308
317
  const path = persisted?.path;
@@ -316,20 +325,9 @@ function WorkspaceCorrespondenceFile({ fallback = null, source, ...props }) {
316
325
  const savePromiseRef = React.useRef(null);
317
326
  /** The last projection this card rendered, kept for the sent snapshot. */
318
327
  const lastShownRef = React.useRef(null);
319
- const identity = String(source.queryOptions.queryKey);
320
- const [seenIdentity, setSeenIdentity] = React.useState(identity);
321
- if (identity !== seenIdentity) {
322
- setSeenIdentity(identity);
323
- setDraft(null);
324
- setSessionSent(false);
325
- attemptedDraftRef.current = null;
326
- savedDraftRef.current = null;
327
- savePromiseRef.current = null;
328
- lastShownRef.current = null;
329
- }
330
328
  const saveMutation = useMutation({
331
329
  mutationFn: async (next) => {
332
- if (!source.onChange) return;
330
+ if (!source.onChange) throw new Error(SAVE_UNAVAILABLE_MESSAGE);
333
331
  if (path === void 0) throw new Error(FILE_MISSING_MESSAGE);
334
332
  await source.onChange(path, next);
335
333
  },
@@ -357,36 +355,34 @@ function WorkspaceCorrespondenceFile({ fallback = null, source, ...props }) {
357
355
  savePromiseRef.current = settled;
358
356
  return settled;
359
357
  }, [mutateSaveAsync]);
360
- const sendMutation = useMutation({ mutationFn: async () => {
361
- if (!source.onSend) return;
362
- if (path === void 0) throw new Error(FILE_MISSING_MESSAGE);
363
- await source.onSend(path);
364
- } });
365
- const { mutateAsync: mutateSendAsync } = sendMutation;
358
+ const { mutateAsync: mutateSendAsync } = useMutation({
359
+ mutationFn: async () => {
360
+ if (!source.onSend) throw new Error(SEND_UNAVAILABLE_MESSAGE);
361
+ if (path === void 0) throw new Error(FILE_MISSING_MESSAGE);
362
+ await source.onSend(path);
363
+ },
364
+ onSuccess: () => queryClient.invalidateQueries({
365
+ queryKey: source.queryOptions.queryKey,
366
+ exact: true
367
+ })
368
+ });
366
369
  const canSave = source.onChange != null;
370
+ const settled = persisted?.state === "sent" || persisted?.state === void 0 && sessionSent;
371
+ const runDebouncedSave = React.useEffectEvent((next) => {
372
+ runSave(next);
373
+ });
367
374
  React.useEffect(() => {
368
- if (!canSave || path === void 0 || sessionSent || draft === null) return;
375
+ if (!canSave || path === void 0 || settled || draft === null) return;
369
376
  if (draft === savedDraftRef.current || draft === attemptedDraftRef.current) return;
370
377
  if (savePending) return;
371
- const timer = setTimeout(() => void runSave(draft), SAVE_DEBOUNCE_MS);
378
+ const timer = setTimeout(() => runDebouncedSave(draft), SAVE_DEBOUNCE_MS);
372
379
  return () => clearTimeout(timer);
373
380
  }, [
374
381
  canSave,
375
382
  draft,
376
383
  path,
377
- runSave,
378
384
  savePending,
379
- sessionSent
380
- ]);
381
- const { reset: resetSave } = saveMutation;
382
- const { reset: resetSend } = sendMutation;
383
- React.useEffect(() => {
384
- resetSave();
385
- resetSend();
386
- }, [
387
- identity,
388
- resetSave,
389
- resetSend
385
+ settled
390
386
  ]);
391
387
  const send = React.useCallback(async () => {
392
388
  if (savePromiseRef.current !== null && !await savePromiseRef.current) throw new Error(SEND_BLOCKED_MESSAGE);
@@ -395,13 +391,17 @@ function WorkspaceCorrespondenceFile({ fallback = null, source, ...props }) {
395
391
  if (!await runSave(outstanding)) throw new Error(SEND_BLOCKED_MESSAGE);
396
392
  }
397
393
  await mutateSendAsync();
394
+ if (persisted) lastShownRef.current = draft === null ? persisted : {
395
+ ...persisted,
396
+ ...draft
397
+ };
398
398
  setSessionSent(true);
399
399
  }, [
400
400
  draft,
401
401
  mutateSendAsync,
402
+ persisted,
402
403
  runSave
403
404
  ]);
404
- if (persisted) lastShownRef.current = persisted;
405
405
  const shown = persisted ?? (sessionSent ? lastShownRef.current : null);
406
406
  if (!shown) return fallback;
407
407
  const visible = draft ?? shown;
@@ -10,51 +10,60 @@ interface WorkspaceExecutionParam {
10
10
  label: string;
11
11
  type: WorkspaceExecutionParamType;
12
12
  /**
13
- * Whether the module's schema lists this property as required. Optional
14
- * string and number fields may run empty and are omitted from the submitted
15
- * values; required ones refuse the run until filled.
13
+ * Whether the module's schema lists this property as required. This is a
14
+ * presentation hint only; the execution runtime owns argument validation.
16
15
  */
17
16
  required: boolean;
18
- value: string | number | boolean;
17
+ value?: string | number | boolean;
19
18
  }
20
19
  interface WorkspaceExecutionRun {
21
20
  path: string;
22
21
  label: string;
22
+ }
23
+ interface WorkspaceExecutionRunView extends WorkspaceExecutionRun {
23
24
  onOpen?: () => void;
24
25
  }
26
+ interface WorkspaceExecutionOutcome {
27
+ /** Serialized return value from the existing execution runtime. */
28
+ result: unknown;
29
+ logs: readonly string[];
30
+ /** Result and log files emitted when the runtime overflowed its inline bounds. */
31
+ runs: readonly WorkspaceExecutionRun[];
32
+ }
33
+ interface WorkspaceExecutionViewOutcome extends Omit<WorkspaceExecutionOutcome, "runs"> {
34
+ runs: readonly WorkspaceExecutionRunView[];
35
+ }
25
36
  interface WorkspaceExecution {
26
37
  /** Workspace path of the module file. */
27
38
  path: string;
28
39
  name: string;
29
40
  description?: string;
30
- /**
31
- * Hostnames or URLs the model said this operates on. Shown like user-script
32
- * Sites. Not a run argument and not parsed from the JavaScript.
33
- */
34
- sites?: readonly string[];
35
- /** Brand mark. Defaults to the first site favicon, then `TerminalIcon`. */
41
+ /** Brand mark. Defaults to `TerminalIcon`. */
36
42
  icon?: React.ReactNode;
37
43
  parameters: readonly WorkspaceExecutionParam[];
38
44
  /** Recent result peeks, newest first. Not a results directory. */
39
45
  runs?: readonly WorkspaceExecutionRun[];
46
+ }
47
+ /** Data-only execution projection hydrated with card actions outside Query. */
48
+ interface WorkspaceExecutionView extends WorkspaceExecution {
49
+ runs?: readonly WorkspaceExecutionRunView[];
40
50
  /**
41
- * Runs the module with the submitted values and resolves with its visible
42
- * result files. The card owns the run lifecycle: a resolved promise shows a
43
- * completed run even when the array is empty; returned files enrich that row.
51
+ * Runs the module with the submitted values. The card owns the run lifecycle;
52
+ * inline output and any overflow files enrich the completed row.
44
53
  */
45
- onRun?: (parameters: readonly WorkspaceExecutionParam[]) => Promise<readonly WorkspaceExecutionRun[]>;
54
+ onRun?: (parameters: readonly WorkspaceExecutionParam[]) => Promise<WorkspaceExecutionViewOutcome>;
46
55
  onOpen?: () => void;
47
56
  onDelete?: () => void | Promise<void>;
48
57
  }
49
58
  interface WorkspaceExecutionSource {
50
59
  queryOptions: WorkspaceConceptQueryOptions<readonly WorkspaceExecution[]>;
51
- /** Runs the module with the submitted values and returns its visible result files. */
52
- onRun?: (path: string, parameters: readonly WorkspaceExecutionParam[]) => Promise<readonly WorkspaceExecutionRun[]>;
60
+ /** Runs the module with the submitted values and returns its visible outcome. */
61
+ onRun?: (path: string, parameters: readonly WorkspaceExecutionParam[]) => Promise<WorkspaceExecutionOutcome>;
53
62
  onOpen?: (path: string) => void;
54
63
  onDelete?: (path: string) => void | Promise<void>;
55
64
  }
56
65
  interface WorkspaceExecutionCardProps extends Omit<CardProps, "children" | "hover" | "size" | "title"> {
57
- module: WorkspaceExecution;
66
+ module: WorkspaceExecutionView;
58
67
  }
59
68
  interface WorkspaceExecutionFileProps extends Omit<WorkspaceExecutionCardProps, "module"> {
60
69
  path: string;
@@ -62,15 +71,14 @@ interface WorkspaceExecutionFileProps extends Omit<WorkspaceExecutionCardProps,
62
71
  fallback?: React.ReactNode;
63
72
  }
64
73
  interface WorkspaceExecutionsPanelProps extends Omit<React.HTMLAttributes<HTMLElement>, "children"> {
65
- modules: readonly WorkspaceExecution[];
74
+ modules: readonly WorkspaceExecutionView[];
75
+ loading?: boolean;
66
76
  /** Query failure to show instead of the empty state. Loaded modules win. */
67
77
  error?: string;
68
78
  onRetry?: () => void;
69
79
  }
70
80
  declare function WorkspaceExecutionCard({
71
- className,
72
81
  module,
73
- ref,
74
82
  ...props
75
83
  }: WorkspaceExecutionCardProps & {
76
84
  ref?: React.Ref<HTMLDivElement>;
@@ -93,6 +101,7 @@ declare function WorkspaceExecutionFile({
93
101
  declare function WorkspaceExecutionsPanel({
94
102
  className,
95
103
  error,
104
+ loading,
96
105
  modules,
97
106
  onRetry,
98
107
  ref,
@@ -103,4 +112,4 @@ declare function WorkspaceExecutionsPanel({
103
112
  /** Canonical workbench descriptor; hosts supply only the source adapter. */
104
113
  declare function workspaceExecutionsPanel(source: WorkspaceExecutionSource): ThinkFullAppPanel;
105
114
  //#endregion
106
- export { WorkspaceExecution, WorkspaceExecutionCard, WorkspaceExecutionCardProps, WorkspaceExecutionFile, WorkspaceExecutionFileProps, WorkspaceExecutionParam, WorkspaceExecutionParamType, WorkspaceExecutionRun, WorkspaceExecutionSource, WorkspaceExecutionsPanel, WorkspaceExecutionsPanelProps, workspaceExecutionsPanel };
115
+ export { WorkspaceExecution, WorkspaceExecutionCard, WorkspaceExecutionCardProps, WorkspaceExecutionFile, WorkspaceExecutionFileProps, WorkspaceExecutionOutcome, WorkspaceExecutionParam, WorkspaceExecutionParamType, WorkspaceExecutionRun, WorkspaceExecutionRunView, WorkspaceExecutionSource, WorkspaceExecutionView, WorkspaceExecutionViewOutcome, WorkspaceExecutionsPanel, WorkspaceExecutionsPanelProps, workspaceExecutionsPanel };
@@ -1,34 +1,33 @@
1
1
  import { t as cx } from "../../class-names-BiMDVpUo.js";
2
- import { P as MonitorIcon, S as FileIcon, Z as TerminalIcon, d as CheckIcon, z as PlayIcon } from "../../icons-cuEtsgj9.js";
2
+ import { K as SpinnerIcon, S as FileIcon, Z as TerminalIcon, d as CheckIcon, z as PlayIcon } from "../../icons-CeGfXO21.js";
3
3
  import { Button } from "../foundations/Button.js";
4
- import { IconButton } from "../foundations/IconButton.js";
5
- import { a as formatErrorMessage } from "../../format-COCyV98Z.js";
6
- import { EmptyState } from "../foundations/EmptyState.js";
7
4
  import { Field } from "../foundations/Field.js";
8
5
  import { Form } from "../foundations/Form.js";
9
- import { Input } from "../foundations/Input.js";
10
- import { DescriptionList } from "../foundations/DescriptionList.js";
11
- import { Switch } from "../foundations/Switch.js";
6
+ import { IconButton } from "../foundations/IconButton.js";
7
+ import { a as formatErrorMessage, o as formatUnknownValue, r as firstLine } from "../../format-COCyV98Z.js";
12
8
  import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "../foundations/Card.js";
13
- import { i as WorkspaceDeleteControl, n as WorkspaceComposerLink, r as httpUrl, t as FaviconMark } from "../../workspace-assets-CxpEHsac.js";
9
+ import { DescriptionList } from "../foundations/DescriptionList.js";
10
+ import { Input } from "../foundations/Input.js";
11
+ import { Checkbox } from "../foundations/Checkbox.js";
12
+ import { EmptyState } from "../foundations/EmptyState.js";
13
+ import { i as WorkspaceDeleteControl, n as WorkspaceComposerLink, r as httpUrl, t as FaviconMark } from "../../workspace-assets-GqsCYxqT.js";
14
14
  import * as React from "react";
15
+ import { createElement } from "react";
15
16
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
- import { useQuery } from "@tanstack/react-query";
17
+ import { useMutation, useQuery } from "@tanstack/react-query";
17
18
  //#region src/components/agents-sdk/WorkspaceExecution.tsx
18
19
  function draftFrom(parameters) {
19
- return Object.fromEntries(parameters.map((parameter) => [parameter.name, parameter.type === "boolean" ? Boolean(parameter.value) : String(parameter.value ?? "")]));
20
+ return Object.fromEntries(parameters.flatMap((parameter) => parameter.value === void 0 ? [] : [[parameter.name, parameter.type === "boolean" ? Boolean(parameter.value) : String(parameter.value)]]));
20
21
  }
21
22
  /**
22
- * Typed values for one run. Empty optional fields are omitted an absent
23
- * property is the schema's own "use the default" while empty required
24
- * fields and non-numeric numbers refuse the run with a field-level message.
23
+ * Values for one run. Empty and untouched fields stay absent so module
24
+ * defaults work. Schema types improve the input but never gate execution.
25
25
  */
26
26
  function collectRunParameters(parameters, draft) {
27
27
  const collected = [];
28
- const problems = [];
29
28
  for (const parameter of parameters) {
30
29
  if (parameter.type === "boolean") {
31
- collected.push({
30
+ if (Object.hasOwn(draft, parameter.name)) collected.push({
32
31
  ...parameter,
33
32
  value: Boolean(draft[parameter.name])
34
33
  });
@@ -36,19 +35,12 @@ function collectRunParameters(parameters, draft) {
36
35
  }
37
36
  const raw = draft[parameter.name];
38
37
  const text = (typeof raw === "string" ? raw : String(raw ?? "")).trim();
39
- if (text === "") {
40
- if (parameter.required) problems.push(`${parameter.label} is required.`);
41
- continue;
42
- }
38
+ if (text === "") continue;
43
39
  if (parameter.type === "number") {
44
40
  const numeric = Number(text);
45
- if (!Number.isFinite(numeric)) {
46
- problems.push(`${parameter.label} must be a number.`);
47
- continue;
48
- }
49
41
  collected.push({
50
42
  ...parameter,
51
- value: numeric
43
+ value: Number.isFinite(numeric) ? numeric : text
52
44
  });
53
45
  continue;
54
46
  }
@@ -57,66 +49,15 @@ function collectRunParameters(parameters, draft) {
57
49
  value: text
58
50
  });
59
51
  }
60
- return problems.length > 0 ? {
61
- status: "invalid",
62
- message: problems.join(" ")
63
- } : {
64
- status: "ok",
65
- parameters: collected
66
- };
52
+ return collected;
67
53
  }
68
54
  function snapshotValue(parameter) {
55
+ if (parameter.value === void 0) return "";
69
56
  if (parameter.type === "boolean") return parameter.value ? "Yes" : "No";
70
- return String(parameter.value ?? "");
71
- }
72
- function siteHref(value) {
73
- return httpUrl(value.includes("://") ? value : `https://${value}`);
74
- }
75
- function siteMarks(values) {
76
- const marks = [];
77
- for (const value of values) {
78
- const trimmed = value.trim();
79
- if (!trimmed) continue;
80
- const href = siteHref(trimmed);
81
- let site = trimmed;
82
- if (href) try {
83
- site = new URL(href).hostname.replace(/^www\./, "");
84
- } catch {
85
- site = trimmed;
86
- }
87
- if (!site || marks.some((mark) => mark.site === site)) continue;
88
- marks.push({
89
- site,
90
- href,
91
- hint: trimmed
92
- });
93
- }
94
- return marks;
57
+ return String(parameter.value);
95
58
  }
96
59
  function ExecutionIcon({ module }) {
97
- if (module.icon) return module.icon;
98
- const href = siteMarks(module.sites ?? []).find((mark) => mark.href)?.href;
99
- return href ? /* @__PURE__ */ jsx(FaviconMark, {
100
- href,
101
- fallback: /* @__PURE__ */ jsx(TerminalIcon, {})
102
- }) : /* @__PURE__ */ jsx(TerminalIcon, {});
103
- }
104
- function SiteDetails({ sites }) {
105
- const marks = siteMarks(sites);
106
- if (marks.length === 0) return null;
107
- return /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsx(DescriptionList.Term, { children: "Sites" }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: /* @__PURE__ */ jsx("div", {
108
- className: "sigvelo-cluster",
109
- children: marks.map(({ href, hint, site }) => /* @__PURE__ */ jsx(WorkspaceComposerLink, {
110
- kind: "tab",
111
- value: site,
112
- label: site,
113
- hint: hint === site ? void 0 : hint,
114
- icon: /* @__PURE__ */ jsx(FaviconMark, {
115
- href,
116
- fallback: /* @__PURE__ */ jsx(MonitorIcon, {})
117
- })
118
- }, site))
119
- }) })] });
60
+ return module.icon ?? /* @__PURE__ */ jsx(TerminalIcon, {});
120
61
  }
121
62
  function RunLinks({ runs }) {
122
63
  return /* @__PURE__ */ jsx("div", {
@@ -129,61 +70,63 @@ function RunLinks({ runs }) {
129
70
  }, run.path))
130
71
  });
131
72
  }
132
- function RunDetails({ runState, runs }) {
133
- const completed = runState.status === "completed";
134
- return /* @__PURE__ */ jsxs(Fragment, { children: [completed ? /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsx(DescriptionList.Term, { children: "Last run" }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: /* @__PURE__ */ jsxs("div", {
135
- className: "sigvelo-cluster",
136
- children: [/* @__PURE__ */ jsxs("span", {
137
- className: "workspace-execution-outcome",
138
- children: [/* @__PURE__ */ jsx(CheckIcon, { size: 14 }), "Completed"]
139
- }), runState.runs.length > 0 ? /* @__PURE__ */ jsx(RunLinks, { runs: runState.runs }) : null]
140
- }) })] }) : null, runs.length > 0 ? /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsx(DescriptionList.Term, { children: completed ? "Earlier" : runs.length === 1 ? "Last" : "Runs" }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: /* @__PURE__ */ jsx(RunLinks, { runs }) })] }) : null] });
73
+ function RunDetails({ outcome, runs }) {
74
+ const completed = outcome !== void 0;
75
+ const result = outcome?.result != null ? firstLine(formatUnknownValue(outcome.result)) : "";
76
+ const log = outcome ? firstLine(outcome.logs.join("\n")) : "";
77
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
78
+ completed ? /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsx(DescriptionList.Term, { children: "Last run" }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: /* @__PURE__ */ jsxs("div", {
79
+ className: "sigvelo-cluster",
80
+ children: [/* @__PURE__ */ jsxs("span", {
81
+ className: "workspace-execution-outcome",
82
+ children: [/* @__PURE__ */ jsx(CheckIcon, { size: 14 }), "Completed"]
83
+ }), outcome.runs.length > 0 ? /* @__PURE__ */ jsx(RunLinks, { runs: outcome.runs }) : null]
84
+ }) })] }) : null,
85
+ result ? /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsx(DescriptionList.Term, { children: "Result" }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: result })] }) : null,
86
+ log ? /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsx(DescriptionList.Term, { children: "Log" }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: log })] }) : null,
87
+ runs.length > 0 ? /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsx(DescriptionList.Term, { children: completed ? "Earlier" : runs.length === 1 ? "Last" : "Runs" }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: /* @__PURE__ */ jsx(RunLinks, { runs }) })] }) : null
88
+ ] });
141
89
  }
142
- function ExecutionFields({ draft, parameters, runState, runs, sites, onDraftChange }) {
90
+ function ExecutionFields({ draft, outcome, parameters, runs, onDraftChange }) {
143
91
  const fieldId = React.useId();
144
92
  const editing = draft != null && onDraftChange != null;
145
- const siteItems = siteMarks(sites ?? []);
146
93
  const runItems = runs ?? [];
147
94
  const visibleParameters = editing ? parameters : parameters.filter((parameter) => snapshotValue(parameter) !== "");
148
- if (visibleParameters.length === 0 && siteItems.length === 0 && runItems.length === 0 && runState.status !== "completed") return null;
95
+ if (visibleParameters.length === 0 && runItems.length === 0 && outcome === void 0) return null;
149
96
  return /* @__PURE__ */ jsxs(DescriptionList.Root, {
150
97
  align: "start",
151
98
  variant: "divided",
152
- children: [
153
- siteItems.length > 0 ? /* @__PURE__ */ jsx(SiteDetails, { sites: sites ?? [] }) : null,
154
- visibleParameters.map((parameter) => {
155
- const id = `${fieldId}-${parameter.name}`;
156
- const href = parameter.type === "string" ? httpUrl(String(editing ? draft?.[parameter.name] ?? parameter.value : parameter.value)) : void 0;
157
- return /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsxs(DescriptionList.Term, {
158
- id: parameter.type === "boolean" ? id : void 0,
159
- children: [href ? /* @__PURE__ */ jsx(FaviconMark, { href }) : null, editing && parameter.type !== "boolean" ? /* @__PURE__ */ jsx("label", {
160
- htmlFor: id,
161
- children: parameter.label
162
- }) : parameter.label]
163
- }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: editing && parameter.type === "boolean" ? /* @__PURE__ */ jsx(Switch.Root, {
164
- size: "sm",
165
- checked: Boolean(draft?.[parameter.name]),
166
- "aria-labelledby": id,
167
- onCheckedChange: (checked) => {
168
- if (typeof checked === "boolean") onDraftChange?.(parameter.name, checked);
169
- },
170
- children: /* @__PURE__ */ jsx(Switch.Thumb, {})
171
- }) : editing ? /* @__PURE__ */ jsx(Input, {
172
- id,
173
- name: parameter.name,
174
- type: href ? "url" : void 0,
175
- required: parameter.required || void 0,
176
- value: String(draft?.[parameter.name] ?? ""),
177
- autoComplete: "off",
178
- inputMode: parameter.type === "number" ? "decimal" : void 0,
179
- onChange: (event) => onDraftChange?.(parameter.name, event.currentTarget.value)
180
- }) : snapshotValue(parameter) })] }, parameter.name);
181
- }),
182
- /* @__PURE__ */ jsx(RunDetails, {
183
- runState,
184
- runs: runItems
185
- })
186
- ]
99
+ children: [visibleParameters.map((parameter) => {
100
+ const id = `${fieldId}-${parameter.name}`;
101
+ const parameterLabel = editing && parameter.required ? `${parameter.label} (required)` : parameter.label;
102
+ const href = parameter.type === "string" ? httpUrl(String(editing ? draft?.[parameter.name] ?? parameter.value : parameter.value)) : void 0;
103
+ return /* @__PURE__ */ jsxs(DescriptionList.Item, { children: [/* @__PURE__ */ jsxs(DescriptionList.Term, {
104
+ id: parameter.type === "boolean" ? id : void 0,
105
+ children: [href ? /* @__PURE__ */ jsx(FaviconMark, { href }) : null, editing && parameter.type !== "boolean" ? /* @__PURE__ */ jsx("label", {
106
+ htmlFor: id,
107
+ children: parameterLabel
108
+ }) : parameterLabel]
109
+ }), /* @__PURE__ */ jsx(DescriptionList.Details, { children: editing && parameter.type === "boolean" ? /* @__PURE__ */ jsx(Checkbox.Root, {
110
+ checked: draft?.[parameter.name] === true,
111
+ indeterminate: draft?.[parameter.name] === void 0,
112
+ "aria-labelledby": id,
113
+ onCheckedChange: (checked) => {
114
+ if (typeof checked === "boolean") onDraftChange?.(parameter.name, checked);
115
+ },
116
+ children: /* @__PURE__ */ jsx(Checkbox.Indicator, {})
117
+ }) : editing ? /* @__PURE__ */ jsx(Input, {
118
+ id,
119
+ name: parameter.name,
120
+ type: href ? "url" : void 0,
121
+ value: String(draft?.[parameter.name] ?? ""),
122
+ autoComplete: "off",
123
+ inputMode: parameter.type === "number" ? "decimal" : void 0,
124
+ onChange: (event) => onDraftChange?.(parameter.name, event.currentTarget.value)
125
+ }) : snapshotValue(parameter) })] }, parameter.name);
126
+ }), /* @__PURE__ */ jsx(RunDetails, {
127
+ outcome,
128
+ runs: runItems
129
+ })]
187
130
  });
188
131
  }
189
132
  function ExecutionActions({ busy, module }) {
@@ -218,45 +161,32 @@ function ExecutionActions({ busy, module }) {
218
161
  function executionFormKey(module) {
219
162
  return `${module.path}:${JSON.stringify(module.parameters)}`;
220
163
  }
221
- function WorkspaceExecutionCard({ className, module, ref, ...props }) {
164
+ function WorkspaceExecutionCard({ module, ...props }) {
165
+ return /* @__PURE__ */ createElement(WorkspaceExecutionCardSession, {
166
+ ...props,
167
+ key: module.path,
168
+ module
169
+ });
170
+ }
171
+ function WorkspaceExecutionCardSession({ className, module, ref, ...props }) {
222
172
  const titleId = React.useId();
223
173
  const ariaLabel = props["aria-label"];
224
174
  const ariaLabelledBy = props["aria-labelledby"] ?? (ariaLabel ? void 0 : titleId);
225
175
  const editing = module.onRun != null;
226
176
  const [draft, setDraft] = React.useState(() => draftFrom(module.parameters));
227
- const [runState, setRunState] = React.useState({ status: "idle" });
228
- const [validationMessage, setValidationMessage] = React.useState("");
229
177
  const formKey = executionFormKey(module);
230
178
  const [seenFormKey, setSeenFormKey] = React.useState(formKey);
231
179
  if (formKey !== seenFormKey) {
232
180
  setSeenFormKey(formKey);
233
181
  setDraft(draftFrom(module.parameters));
234
- setValidationMessage("");
235
182
  }
236
- const busy = runState.status === "running";
237
- const run = async () => {
238
- if (!module.onRun || busy) return;
239
- const submission = collectRunParameters(module.parameters, draft);
240
- if (submission.status === "invalid") {
241
- setValidationMessage(submission.message);
242
- return;
243
- }
244
- setValidationMessage("");
245
- setRunState({ status: "running" });
246
- try {
247
- setRunState({
248
- status: "completed",
249
- runs: await module.onRun(submission.parameters)
250
- });
251
- } catch (error) {
252
- setRunState({
253
- status: "failed",
254
- message: formatErrorMessage(error)
255
- });
256
- }
257
- };
258
- const errorMessage = validationMessage || (runState.status === "failed" ? runState.message : "");
259
- const hasBody = module.parameters.length > 0 || (module.sites?.length ?? 0) > 0 || (module.runs?.length ?? 0) > 0 || runState.status === "completed" || editing || Boolean(errorMessage);
183
+ const runMutation = useMutation({ mutationFn: async () => {
184
+ if (!module.onRun) throw new Error("Execution is no longer available.");
185
+ return module.onRun(collectRunParameters(module.parameters, draft));
186
+ } });
187
+ const busy = runMutation.isPending;
188
+ const errorMessage = runMutation.isError ? formatErrorMessage(runMutation.error) : "";
189
+ const hasBody = module.parameters.length > 0 || (module.runs?.length ?? 0) > 0 || runMutation.isSuccess || editing || Boolean(errorMessage);
260
190
  const header = /* @__PURE__ */ jsxs(CardHeader, { children: [
261
191
  /* @__PURE__ */ jsxs(CardTitle, {
262
192
  id: titleId,
@@ -277,30 +207,27 @@ function WorkspaceExecutionCard({ className, module, ref, ...props }) {
277
207
  const body = hasBody ? /* @__PURE__ */ jsxs(CardContent, { children: [
278
208
  /* @__PURE__ */ jsx(ExecutionFields, {
279
209
  draft: editing ? draft : void 0,
210
+ outcome: runMutation.isSuccess ? runMutation.data : void 0,
280
211
  parameters: module.parameters,
281
- runState,
282
212
  runs: module.runs,
283
- sites: module.sites,
284
- onDraftChange: editing ? (name, value) => {
285
- setValidationMessage("");
286
- setDraft((current) => ({
287
- ...current,
288
- [name]: value
289
- }));
290
- } : void 0
213
+ onDraftChange: editing ? (name, value) => setDraft((current) => ({
214
+ ...current,
215
+ [name]: value
216
+ })) : void 0
291
217
  }),
292
218
  errorMessage ? /* @__PURE__ */ jsx(Field.Errors, { errors: [errorMessage] }) : null,
293
219
  /* @__PURE__ */ jsx("span", {
294
220
  className: "sigvelo-visually-hidden",
295
221
  role: "status",
296
222
  "aria-atomic": "true",
297
- children: errorMessage || (busy ? "Running" : runState.status === "completed" ? "Completed" : "")
223
+ children: errorMessage || (busy ? "Running" : runMutation.isSuccess ? "Completed" : "")
298
224
  })
299
225
  ] }) : null;
300
226
  const inner = editing ? /* @__PURE__ */ jsxs(Form, {
227
+ noValidate: true,
301
228
  onSubmit: (event) => {
302
229
  event.preventDefault();
303
- run();
230
+ if (!busy) runMutation.mutate();
304
231
  },
305
232
  children: [header, body]
306
233
  }) : /* @__PURE__ */ jsxs(Fragment, { children: [header, body] });
@@ -330,7 +257,7 @@ function WorkspaceExecutionFile({ fallback = null, path, source, ...props }) {
330
257
  * Workbench library. Same card as the inline placement. A query failure with
331
258
  * nothing loaded renders as a quiet inline error, never as an empty library.
332
259
  */
333
- function WorkspaceExecutionsPanel({ className, error, modules, onRetry, ref, ...props }) {
260
+ function WorkspaceExecutionsPanel({ className, error, loading = false, modules, onRetry, ref, ...props }) {
334
261
  return /* @__PURE__ */ jsx("section", {
335
262
  ref,
336
263
  "data-slot": "workspace-executions-panel",
@@ -351,6 +278,9 @@ function WorkspaceExecutionsPanel({ className, error, modules, onRetry, ref, ...
351
278
  onClick: onRetry,
352
279
  children: "Retry"
353
280
  }) : null
281
+ }) : loading ? /* @__PURE__ */ jsx(EmptyState, {
282
+ icon: /* @__PURE__ */ jsx(SpinnerIcon, {}),
283
+ title: "Loading modules"
354
284
  }) : /* @__PURE__ */ jsx(EmptyState, {
355
285
  icon: /* @__PURE__ */ jsx(TerminalIcon, {}),
356
286
  title: "No modules"
@@ -366,7 +296,13 @@ function executionWithSource(module, source) {
366
296
  return {
367
297
  ...module,
368
298
  runs: module.runs?.map(withOpen),
369
- onRun: onRun ? async (parameters) => (await onRun(module.path, parameters)).map(withOpen) : void 0,
299
+ onRun: onRun ? async (parameters) => {
300
+ const outcome = await onRun(module.path, parameters);
301
+ return {
302
+ ...outcome,
303
+ runs: outcome.runs.map(withOpen)
304
+ };
305
+ } : void 0,
370
306
  onOpen: onOpen ? () => onOpen(module.path) : void 0,
371
307
  onDelete: onDelete ? () => onDelete(module.path) : void 0
372
308
  };
@@ -376,6 +312,7 @@ function WorkspaceExecutionSourcePanel({ source }) {
376
312
  return /* @__PURE__ */ jsx(WorkspaceExecutionsPanel, {
377
313
  modules: (query.data ?? []).map((module) => executionWithSource(module, source)),
378
314
  error: query.isError ? formatErrorMessage(query.error) : void 0,
315
+ loading: query.isPending,
379
316
  onRetry: query.isError ? () => void query.refetch() : void 0,
380
317
  "aria-busy": query.isFetching || void 0
381
318
  });