@stigmer/react 3.1.3 → 3.1.4

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 (151) hide show
  1. package/composer/SessionComposer.d.ts +31 -0
  2. package/composer/SessionComposer.d.ts.map +1 -1
  3. package/composer/SessionComposer.js +12 -4
  4. package/composer/SessionComposer.js.map +1 -1
  5. package/execution/ArtifactApplyButton.d.ts +25 -0
  6. package/execution/ArtifactApplyButton.d.ts.map +1 -0
  7. package/execution/ArtifactApplyButton.js +21 -0
  8. package/execution/ArtifactApplyButton.js.map +1 -0
  9. package/execution/ArtifactContentBody.d.ts +36 -0
  10. package/execution/ArtifactContentBody.d.ts.map +1 -0
  11. package/execution/ArtifactContentBody.js +62 -0
  12. package/execution/ArtifactContentBody.js.map +1 -0
  13. package/execution/ArtifactDocument.d.ts +48 -0
  14. package/execution/ArtifactDocument.d.ts.map +1 -0
  15. package/execution/ArtifactDocument.js +89 -0
  16. package/execution/ArtifactDocument.js.map +1 -0
  17. package/execution/ArtifactPreviewModal.d.ts +4 -4
  18. package/execution/ArtifactPreviewModal.d.ts.map +1 -1
  19. package/execution/ArtifactPreviewModal.js +15 -142
  20. package/execution/ArtifactPreviewModal.js.map +1 -1
  21. package/execution/ArtifactRow.d.ts +49 -0
  22. package/execution/ArtifactRow.d.ts.map +1 -0
  23. package/execution/ArtifactRow.js +56 -0
  24. package/execution/ArtifactRow.js.map +1 -0
  25. package/execution/ArtifactsWidget.d.ts +6 -9
  26. package/execution/ArtifactsWidget.d.ts.map +1 -1
  27. package/execution/ArtifactsWidget.js +15 -19
  28. package/execution/ArtifactsWidget.js.map +1 -1
  29. package/execution/index.d.ts +8 -2
  30. package/execution/index.d.ts.map +1 -1
  31. package/execution/index.js +4 -1
  32. package/execution/index.js.map +1 -1
  33. package/execution/useArtifactContent.d.ts +6 -1
  34. package/execution/useArtifactContent.d.ts.map +1 -1
  35. package/execution/useArtifactContent.js +7 -2
  36. package/execution/useArtifactContent.js.map +1 -1
  37. package/execution/useArtifactInspection.d.ts +85 -0
  38. package/execution/useArtifactInspection.d.ts.map +1 -0
  39. package/execution/useArtifactInspection.js +143 -0
  40. package/execution/useArtifactInspection.js.map +1 -0
  41. package/execution/useCreateAgentExecution.d.ts +11 -0
  42. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  43. package/execution/useCreateAgentExecution.js +1 -0
  44. package/execution/useCreateAgentExecution.js.map +1 -1
  45. package/index.d.ts +3 -3
  46. package/index.d.ts.map +1 -1
  47. package/index.js +2 -2
  48. package/index.js.map +1 -1
  49. package/internal/MermaidDiagram.d.ts +47 -0
  50. package/internal/MermaidDiagram.d.ts.map +1 -0
  51. package/internal/MermaidDiagram.js +118 -0
  52. package/internal/MermaidDiagram.js.map +1 -0
  53. package/internal/markdown-components.d.ts.map +1 -1
  54. package/internal/markdown-components.js +34 -0
  55. package/internal/markdown-components.js.map +1 -1
  56. package/internal/mermaid-loader.d.ts +26 -0
  57. package/internal/mermaid-loader.d.ts.map +1 -0
  58. package/internal/mermaid-loader.js +34 -0
  59. package/internal/mermaid-loader.js.map +1 -0
  60. package/internal/mermaid-theme-css.d.ts +41 -0
  61. package/internal/mermaid-theme-css.d.ts.map +1 -0
  62. package/internal/mermaid-theme-css.js +179 -0
  63. package/internal/mermaid-theme-css.js.map +1 -0
  64. package/internal/slug.d.ts +9 -5
  65. package/internal/slug.d.ts.map +1 -1
  66. package/internal/slug.js +10 -6
  67. package/internal/slug.js.map +1 -1
  68. package/package.json +5 -4
  69. package/session/SessionViewer.d.ts.map +1 -1
  70. package/session/SessionViewer.js +91 -18
  71. package/session/SessionViewer.js.map +1 -1
  72. package/session/artifact-document.d.ts +13 -0
  73. package/session/artifact-document.d.ts.map +1 -0
  74. package/session/artifact-document.js +22 -0
  75. package/session/artifact-document.js.map +1 -0
  76. package/session/facets/ArtifactsTab.d.ts +30 -4
  77. package/session/facets/ArtifactsTab.d.ts.map +1 -1
  78. package/session/facets/ArtifactsTab.js +32 -10
  79. package/session/facets/ArtifactsTab.js.map +1 -1
  80. package/session/index.d.ts +2 -1
  81. package/session/index.d.ts.map +1 -1
  82. package/session/index.js +4 -1
  83. package/session/index.js.map +1 -1
  84. package/session/useSessionArtifacts.d.ts +17 -0
  85. package/session/useSessionArtifacts.d.ts.map +1 -1
  86. package/session/useSessionArtifacts.js +16 -5
  87. package/session/useSessionArtifacts.js.map +1 -1
  88. package/session/useSessionConversation.d.ts +17 -1
  89. package/session/useSessionConversation.d.ts.map +1 -1
  90. package/session/useSessionConversation.js +32 -4
  91. package/session/useSessionConversation.js.map +1 -1
  92. package/session/useSessionPageFlow.d.ts.map +1 -1
  93. package/session/useSessionPageFlow.js +1 -0
  94. package/session/useSessionPageFlow.js.map +1 -1
  95. package/session/useSessionPanel.d.ts +20 -0
  96. package/session/useSessionPanel.d.ts.map +1 -1
  97. package/session/useSessionPanel.js +13 -0
  98. package/session/useSessionPanel.js.map +1 -1
  99. package/session/useSessionRailViews.d.ts +13 -1
  100. package/session/useSessionRailViews.d.ts.map +1 -1
  101. package/session/useSessionRailViews.js +5 -3
  102. package/session/useSessionRailViews.js.map +1 -1
  103. package/src/composer/SessionComposer.tsx +69 -1
  104. package/src/composer/__tests__/SessionComposer-editing.test.tsx +128 -0
  105. package/src/execution/ArtifactApplyButton.tsx +79 -0
  106. package/src/execution/ArtifactContentBody.tsx +255 -0
  107. package/src/execution/ArtifactDocument.tsx +344 -0
  108. package/src/execution/ArtifactPreviewModal.tsx +39 -405
  109. package/src/execution/ArtifactRow.tsx +165 -0
  110. package/src/execution/ArtifactsWidget.tsx +24 -33
  111. package/src/execution/__tests__/ArtifactContentBody.test.tsx +131 -0
  112. package/src/execution/__tests__/ArtifactDocument.test.tsx +100 -0
  113. package/src/execution/__tests__/ArtifactRow.test.tsx +139 -0
  114. package/src/execution/__tests__/ArtifactsWidget.test.tsx +78 -0
  115. package/src/execution/__tests__/message-entry.test.tsx +50 -2
  116. package/src/execution/__tests__/useArtifactInspection.test.tsx +151 -0
  117. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +35 -0
  118. package/src/execution/index.ts +14 -2
  119. package/src/execution/useArtifactContent.ts +7 -0
  120. package/src/execution/useArtifactInspection.ts +252 -0
  121. package/src/execution/useCreateAgentExecution.ts +12 -0
  122. package/src/index.ts +11 -2
  123. package/src/internal/MermaidDiagram.tsx +164 -0
  124. package/src/internal/__tests__/a11y/mermaid-theme.a11y.test.tsx +122 -0
  125. package/src/internal/__tests__/markdown-components.test.tsx +93 -1
  126. package/src/internal/__tests__/mermaid-diagram.test.tsx +282 -0
  127. package/src/internal/markdown-components.tsx +36 -1
  128. package/src/internal/mermaid-loader.ts +44 -0
  129. package/src/internal/mermaid-theme-css.ts +178 -0
  130. package/src/internal/slug.ts +10 -6
  131. package/src/session/SessionViewer.tsx +177 -33
  132. package/src/session/__tests__/SessionViewer-artifactTabs.test.tsx +210 -0
  133. package/src/session/__tests__/SessionViewer-editResubmit.test.tsx +233 -0
  134. package/src/session/__tests__/useSessionArtifacts.test.ts +57 -0
  135. package/src/session/__tests__/useSessionConversation.test.tsx +172 -1
  136. package/src/session/__tests__/useSessionPanel.test.ts +70 -1
  137. package/src/session/artifact-document.ts +23 -0
  138. package/src/session/facets/ArtifactsTab.tsx +66 -18
  139. package/src/session/facets/__tests__/ArtifactsTab.test.tsx +111 -47
  140. package/src/session/index.ts +5 -1
  141. package/src/session/useSessionArtifacts.ts +16 -5
  142. package/src/session/useSessionConversation.ts +48 -6
  143. package/src/session/useSessionPageFlow.ts +1 -0
  144. package/src/session/useSessionPanel.ts +41 -0
  145. package/src/session/useSessionRailViews.tsx +21 -1
  146. package/styles.css +1 -1
  147. package/execution/ArtifactCard.d.ts +0 -81
  148. package/execution/ArtifactCard.d.ts.map +0 -1
  149. package/execution/ArtifactCard.js +0 -130
  150. package/execution/ArtifactCard.js.map +0 -1
  151. package/src/execution/ArtifactCard.tsx +0 -320
@@ -1,81 +0,0 @@
1
- import type { ExecutionArtifact } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/artifact_pb";
2
- /** Props for {@link ArtifactCard}. */
3
- export interface ArtifactCardProps {
4
- /** The execution artifact to render. */
5
- readonly artifact: ExecutionArtifact;
6
- /** ID of the execution that produced this artifact — used for content fetching. */
7
- readonly executionId: string;
8
- /**
9
- * Organization slug — used for skill package detection which fetches
10
- * `SKILL.md` frontmatter via the artifact content RPC.
11
- */
12
- readonly org: string;
13
- /**
14
- * Called when the user clicks "Preview". The consumer is responsible
15
- * for rendering a preview UI (e.g., {@link ArtifactPreviewModal}).
16
- *
17
- * When omitted, the Preview action is not rendered.
18
- */
19
- readonly onPreview?: (artifact: ExecutionArtifact) => void;
20
- /**
21
- * When `true`, another artifact in the list shares the same display
22
- * `name` but has a different `sandbox_path`. The card renders the
23
- * parent directory from `sandbox_path` as a muted subtitle for
24
- * disambiguation.
25
- *
26
- * Set by {@link ArtifactsWidget} via {@link useSessionArtifacts}.
27
- * Defaults to `false`.
28
- */
29
- readonly hasNameCollision?: boolean;
30
- /** Additional CSS classes for the root element. */
31
- readonly className?: string;
32
- }
33
- /**
34
- * Renders a single execution artifact as a compact summary card with
35
- * automatic Stigmer resource detection and a download link.
36
- *
37
- * The card's role is **signal and navigate**: it tells the user what
38
- * the artifact is (file/directory, size, detected resource type) and
39
- * provides two actions — Preview and Download. The Apply/Push CTA
40
- * lives exclusively in {@link ArtifactPreviewModal} so the user must
41
- * review content before acting (review-before-apply pattern).
42
- *
43
- * Internally orchestrates the detection pipeline:
44
- *
45
- * - **FILE artifacts**: Fetches text content via {@link useArtifactContent},
46
- * then detects Agent/McpServer YAML via {@link useDetectStigmerResource}.
47
- * Only text files under 256 KB are fetched for detection.
48
- *
49
- * - **DIRECTORY artifacts**: Detects skill packages via
50
- * {@link useDetectSkillPackage} (checks for `SKILL.md` in the ZIP
51
- * archive entries).
52
- *
53
- * Detection results are surfaced as a type badge ("Agent detected",
54
- * "Skill · N files"). Non-Stigmer artifacts render with file info
55
- * and a download link only — no error messages or "not detected"
56
- * indicators (detection is silent).
57
- *
58
- * @example
59
- * ```tsx
60
- * const { artifacts } = useExecutionArtifacts(execution);
61
- *
62
- * {artifacts.map((artifact) => (
63
- * <ArtifactCard
64
- * key={artifact.storageKey}
65
- * artifact={artifact}
66
- * executionId={execution.metadata!.id}
67
- * org={activeOrg}
68
- * onPreview={(a) => setPreviewArtifact(a)}
69
- * />
70
- * ))}
71
- * ```
72
- *
73
- * @see {@link ArtifactPreviewModal} — full preview with Apply/Push CTA
74
- * @see {@link ArtifactsWidget} — container that composes cards + modal
75
- * @see {@link useExecutionArtifacts} — extracts artifact metadata from an execution
76
- * @see {@link useArtifactContent} — content-fetching hook (headless alternative)
77
- * @see {@link useDetectStigmerResource} — YAML resource detection (headless)
78
- * @see {@link useDetectSkillPackage} — skill package detection (headless)
79
- */
80
- export declare function ArtifactCard({ artifact, executionId, org, onPreview, hasNameCollision, className, }: ArtifactCardProps): import("react/jsx-runtime").JSX.Element;
81
- //# sourceMappingURL=ArtifactCard.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ArtifactCard.d.ts","sourceRoot":"","sources":["../../src/execution/ArtifactCard.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kEAAkE,CAAC;AAiB1G,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,mFAAmF;IACnF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC3D;;;;;;;;OAQG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC,mDAAmD;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,WAAW,EACX,GAAG,EACH,SAAS,EACT,gBAAwB,EACxB,SAAS,GACV,EAAE,iBAAiB,2CA+HnB"}
@@ -1,130 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { ExecutionArtifactKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
4
- import { cn } from "@stigmer/theme";
5
- import { useArtifactContent } from "./useArtifactContent.js";
6
- import { useArtifactDownload } from "./useArtifactDownload.js";
7
- import { isTextArtifact, formatArtifactSize } from "./artifact-utils.js";
8
- import { useDetectStigmerResource } from "../library/useDetectStigmerResource.js";
9
- import { useDetectSkillPackage } from "../library/useDetectSkillPackage.js";
10
- /**
11
- * Artifacts larger than this threshold skip the content fetch used for
12
- * resource detection. Stigmer resource YAML files are typically under
13
- * 10 KB — 256 KB is generous without risking large payloads for log
14
- * files or binary-adjacent text content.
15
- */
16
- const MAX_DETECTION_SIZE = 256 * 1024;
17
- /**
18
- * Renders a single execution artifact as a compact summary card with
19
- * automatic Stigmer resource detection and a download link.
20
- *
21
- * The card's role is **signal and navigate**: it tells the user what
22
- * the artifact is (file/directory, size, detected resource type) and
23
- * provides two actions — Preview and Download. The Apply/Push CTA
24
- * lives exclusively in {@link ArtifactPreviewModal} so the user must
25
- * review content before acting (review-before-apply pattern).
26
- *
27
- * Internally orchestrates the detection pipeline:
28
- *
29
- * - **FILE artifacts**: Fetches text content via {@link useArtifactContent},
30
- * then detects Agent/McpServer YAML via {@link useDetectStigmerResource}.
31
- * Only text files under 256 KB are fetched for detection.
32
- *
33
- * - **DIRECTORY artifacts**: Detects skill packages via
34
- * {@link useDetectSkillPackage} (checks for `SKILL.md` in the ZIP
35
- * archive entries).
36
- *
37
- * Detection results are surfaced as a type badge ("Agent detected",
38
- * "Skill · N files"). Non-Stigmer artifacts render with file info
39
- * and a download link only — no error messages or "not detected"
40
- * indicators (detection is silent).
41
- *
42
- * @example
43
- * ```tsx
44
- * const { artifacts } = useExecutionArtifacts(execution);
45
- *
46
- * {artifacts.map((artifact) => (
47
- * <ArtifactCard
48
- * key={artifact.storageKey}
49
- * artifact={artifact}
50
- * executionId={execution.metadata!.id}
51
- * org={activeOrg}
52
- * onPreview={(a) => setPreviewArtifact(a)}
53
- * />
54
- * ))}
55
- * ```
56
- *
57
- * @see {@link ArtifactPreviewModal} — full preview with Apply/Push CTA
58
- * @see {@link ArtifactsWidget} — container that composes cards + modal
59
- * @see {@link useExecutionArtifacts} — extracts artifact metadata from an execution
60
- * @see {@link useArtifactContent} — content-fetching hook (headless alternative)
61
- * @see {@link useDetectStigmerResource} — YAML resource detection (headless)
62
- * @see {@link useDetectSkillPackage} — skill package detection (headless)
63
- */
64
- export function ArtifactCard({ artifact, executionId, org, onPreview, hasNameCollision = false, className, }) {
65
- // ---------------------------------------------------------------------------
66
- // Detection orchestration
67
- // ---------------------------------------------------------------------------
68
- const isDirectory = artifact.kind === ExecutionArtifactKind.DIRECTORY;
69
- const canDetectYaml = !isDirectory &&
70
- isTextArtifact(artifact) &&
71
- Number(artifact.sizeBytes) < MAX_DETECTION_SIZE;
72
- const { content, isLoading: isContentLoading } = useArtifactContent(canDetectYaml ? executionId : null, canDetectYaml ? artifact.storageKey : null, undefined, artifact.contentHash || undefined);
73
- const yamlDetection = useDetectStigmerResource(canDetectYaml ? content : null);
74
- const { detection: skillDetection, isLoading: isSkillLoading } = useDetectSkillPackage(isDirectory ? artifact : null, isDirectory ? executionId : null);
75
- // ---------------------------------------------------------------------------
76
- // Derived detection state
77
- // ---------------------------------------------------------------------------
78
- const isDetected = yamlDetection.detected || skillDetection.detected;
79
- const isDetecting = (canDetectYaml && isContentLoading) || (isDirectory && isSkillLoading);
80
- let detectionLabel = null;
81
- if (yamlDetection.detected) {
82
- detectionLabel = `${yamlDetection.displayName} detected`;
83
- }
84
- else if (skillDetection.detected) {
85
- const count = skillDetection.fileCount;
86
- detectionLabel = `Skill \u00B7 ${count} ${count === 1 ? "file" : "files"}`;
87
- }
88
- const canPreview = !!onPreview && (isTextArtifact(artifact) || isDirectory);
89
- const { download, isDownloading } = useArtifactDownload(executionId);
90
- const parentDir = hasNameCollision && artifact.sandboxPath
91
- ? parentDirectory(artifact.sandboxPath)
92
- : null;
93
- // ---------------------------------------------------------------------------
94
- // Render
95
- // ---------------------------------------------------------------------------
96
- return (_jsxs("div", { role: "article", "aria-label": artifact.name, className: cn("rounded-md border border-border p-3", className), children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: isDirectory ? _jsx(FolderIcon, {}) : _jsx(FileIcon, {}) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "truncate text-sm font-medium text-foreground", children: [artifact.name, isDirectory && "/"] }), parentDir && (_jsx("div", { className: "truncate text-xs text-muted-foreground", children: parentDir })), _jsx("div", { className: "text-xs tabular-nums text-muted-foreground", children: formatArtifactSize(artifact.sizeBytes) })] })] }), isDetecting && !isDetected && (_jsx("div", { className: "mt-1.5 h-5 w-28 animate-pulse rounded-full bg-muted", "aria-hidden": "true" })), detectionLabel && (_jsx("span", { className: "mt-1.5 inline-flex items-center rounded-full bg-primary-subtle px-2 py-0.5 text-xs font-medium text-primary", children: detectionLabel })), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1", children: [canPreview && (_jsx("button", { type: "button", onClick: () => onPreview(artifact), className: cn("text-xs font-medium text-primary transition-colors hover:text-primary-muted", FOCUS_RING_CLASSES), children: "Preview" })), _jsxs("button", { type: "button", onClick: () => download(artifact.storageKey, artifact.name), disabled: isDownloading, className: cn("inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground disabled:opacity-50", FOCUS_RING_CLASSES), children: [_jsx(DownloadIcon, {}), isDownloading ? "Preparing…" : isDirectory ? "Download ZIP" : "Download"] })] })] }));
97
- }
98
- // ---------------------------------------------------------------------------
99
- // Helpers
100
- // ---------------------------------------------------------------------------
101
- /**
102
- * Extracts a human-readable parent directory label from a sandbox path.
103
- * Given `/workspace/configs/agent.yaml` returns `configs/`.
104
- * Returns `null` when the path has no meaningful parent segment.
105
- */
106
- function parentDirectory(sandboxPath) {
107
- const lastSlash = sandboxPath.lastIndexOf("/");
108
- if (lastSlash <= 0)
109
- return null;
110
- const parent = sandboxPath.slice(0, lastSlash);
111
- const segment = parent.slice(parent.lastIndexOf("/") + 1);
112
- return segment ? `${segment}/` : null;
113
- }
114
- // ---------------------------------------------------------------------------
115
- // Shared style constants
116
- // ---------------------------------------------------------------------------
117
- const FOCUS_RING_CLASSES = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-sm";
118
- // ---------------------------------------------------------------------------
119
- // Inline SVG icons
120
- // ---------------------------------------------------------------------------
121
- function FileIcon() {
122
- return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M8 1H4C3.45 1 3 1.45 3 2V12C3 12.55 3.45 13 4 13H10C10.55 13 11 12.55 11 12V4L8 1Z" }), _jsx("path", { d: "M8 1V4H11" })] }));
123
- }
124
- function FolderIcon() {
125
- return (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M13 11C13 11.55 12.55 12 12 12H2C1.45 12 1 11.55 1 11V3C1 2.45 1.45 2 2 2H5L7 4H12C12.55 4 13 4.45 13 5V11Z" }) }));
126
- }
127
- function DownloadIcon() {
128
- return (_jsxs("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "shrink-0", "aria-hidden": "true", children: [_jsx("path", { d: "M6 1.5V8.5" }), _jsx("path", { d: "M3 6L6 9L9 6" }), _jsx("path", { d: "M2 10.5H10" })] }));
129
- }
130
- //# sourceMappingURL=ArtifactCard.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ArtifactCard.js","sourceRoot":"","sources":["../../src/execution/ArtifactCard.tsx"],"names":[],"mappings":"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"}
@@ -1,320 +0,0 @@
1
- "use client";
2
-
3
- import type { ExecutionArtifact } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/artifact_pb";
4
- import { ExecutionArtifactKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
- import { cn } from "@stigmer/theme";
6
- import { useArtifactContent } from "./useArtifactContent.js";
7
- import { useArtifactDownload } from "./useArtifactDownload.js";
8
- import { isTextArtifact, formatArtifactSize } from "./artifact-utils.js";
9
- import { useDetectStigmerResource } from "../library/useDetectStigmerResource.js";
10
- import { useDetectSkillPackage } from "../library/useDetectSkillPackage.js";
11
-
12
- /**
13
- * Artifacts larger than this threshold skip the content fetch used for
14
- * resource detection. Stigmer resource YAML files are typically under
15
- * 10 KB — 256 KB is generous without risking large payloads for log
16
- * files or binary-adjacent text content.
17
- */
18
- const MAX_DETECTION_SIZE = 256 * 1024;
19
-
20
- /** Props for {@link ArtifactCard}. */
21
- export interface ArtifactCardProps {
22
- /** The execution artifact to render. */
23
- readonly artifact: ExecutionArtifact;
24
- /** ID of the execution that produced this artifact — used for content fetching. */
25
- readonly executionId: string;
26
- /**
27
- * Organization slug — used for skill package detection which fetches
28
- * `SKILL.md` frontmatter via the artifact content RPC.
29
- */
30
- readonly org: string;
31
- /**
32
- * Called when the user clicks "Preview". The consumer is responsible
33
- * for rendering a preview UI (e.g., {@link ArtifactPreviewModal}).
34
- *
35
- * When omitted, the Preview action is not rendered.
36
- */
37
- readonly onPreview?: (artifact: ExecutionArtifact) => void;
38
- /**
39
- * When `true`, another artifact in the list shares the same display
40
- * `name` but has a different `sandbox_path`. The card renders the
41
- * parent directory from `sandbox_path` as a muted subtitle for
42
- * disambiguation.
43
- *
44
- * Set by {@link ArtifactsWidget} via {@link useSessionArtifacts}.
45
- * Defaults to `false`.
46
- */
47
- readonly hasNameCollision?: boolean;
48
- /** Additional CSS classes for the root element. */
49
- readonly className?: string;
50
- }
51
-
52
- /**
53
- * Renders a single execution artifact as a compact summary card with
54
- * automatic Stigmer resource detection and a download link.
55
- *
56
- * The card's role is **signal and navigate**: it tells the user what
57
- * the artifact is (file/directory, size, detected resource type) and
58
- * provides two actions — Preview and Download. The Apply/Push CTA
59
- * lives exclusively in {@link ArtifactPreviewModal} so the user must
60
- * review content before acting (review-before-apply pattern).
61
- *
62
- * Internally orchestrates the detection pipeline:
63
- *
64
- * - **FILE artifacts**: Fetches text content via {@link useArtifactContent},
65
- * then detects Agent/McpServer YAML via {@link useDetectStigmerResource}.
66
- * Only text files under 256 KB are fetched for detection.
67
- *
68
- * - **DIRECTORY artifacts**: Detects skill packages via
69
- * {@link useDetectSkillPackage} (checks for `SKILL.md` in the ZIP
70
- * archive entries).
71
- *
72
- * Detection results are surfaced as a type badge ("Agent detected",
73
- * "Skill · N files"). Non-Stigmer artifacts render with file info
74
- * and a download link only — no error messages or "not detected"
75
- * indicators (detection is silent).
76
- *
77
- * @example
78
- * ```tsx
79
- * const { artifacts } = useExecutionArtifacts(execution);
80
- *
81
- * {artifacts.map((artifact) => (
82
- * <ArtifactCard
83
- * key={artifact.storageKey}
84
- * artifact={artifact}
85
- * executionId={execution.metadata!.id}
86
- * org={activeOrg}
87
- * onPreview={(a) => setPreviewArtifact(a)}
88
- * />
89
- * ))}
90
- * ```
91
- *
92
- * @see {@link ArtifactPreviewModal} — full preview with Apply/Push CTA
93
- * @see {@link ArtifactsWidget} — container that composes cards + modal
94
- * @see {@link useExecutionArtifacts} — extracts artifact metadata from an execution
95
- * @see {@link useArtifactContent} — content-fetching hook (headless alternative)
96
- * @see {@link useDetectStigmerResource} — YAML resource detection (headless)
97
- * @see {@link useDetectSkillPackage} — skill package detection (headless)
98
- */
99
- export function ArtifactCard({
100
- artifact,
101
- executionId,
102
- org,
103
- onPreview,
104
- hasNameCollision = false,
105
- className,
106
- }: ArtifactCardProps) {
107
- // ---------------------------------------------------------------------------
108
- // Detection orchestration
109
- // ---------------------------------------------------------------------------
110
-
111
- const isDirectory = artifact.kind === ExecutionArtifactKind.DIRECTORY;
112
- const canDetectYaml =
113
- !isDirectory &&
114
- isTextArtifact(artifact) &&
115
- Number(artifact.sizeBytes) < MAX_DETECTION_SIZE;
116
-
117
- const { content, isLoading: isContentLoading } = useArtifactContent(
118
- canDetectYaml ? executionId : null,
119
- canDetectYaml ? artifact.storageKey : null,
120
- undefined,
121
- artifact.contentHash || undefined,
122
- );
123
-
124
- const yamlDetection = useDetectStigmerResource(
125
- canDetectYaml ? content : null,
126
- );
127
-
128
- const { detection: skillDetection, isLoading: isSkillLoading } =
129
- useDetectSkillPackage(
130
- isDirectory ? artifact : null,
131
- isDirectory ? executionId : null,
132
- );
133
-
134
- // ---------------------------------------------------------------------------
135
- // Derived detection state
136
- // ---------------------------------------------------------------------------
137
-
138
- const isDetected = yamlDetection.detected || skillDetection.detected;
139
- const isDetecting =
140
- (canDetectYaml && isContentLoading) || (isDirectory && isSkillLoading);
141
-
142
- let detectionLabel: string | null = null;
143
- if (yamlDetection.detected) {
144
- detectionLabel = `${yamlDetection.displayName} detected`;
145
- } else if (skillDetection.detected) {
146
- const count = skillDetection.fileCount;
147
- detectionLabel = `Skill \u00B7 ${count} ${count === 1 ? "file" : "files"}`;
148
- }
149
-
150
- const canPreview = !!onPreview && (isTextArtifact(artifact) || isDirectory);
151
-
152
- const { download, isDownloading } = useArtifactDownload(executionId);
153
-
154
- const parentDir =
155
- hasNameCollision && artifact.sandboxPath
156
- ? parentDirectory(artifact.sandboxPath)
157
- : null;
158
-
159
- // ---------------------------------------------------------------------------
160
- // Render
161
- // ---------------------------------------------------------------------------
162
-
163
- return (
164
- <div
165
- role="article"
166
- aria-label={artifact.name}
167
- className={cn("rounded-md border border-border p-3", className)}
168
- >
169
- {/* Header: icon + name + size */}
170
- <div className="flex items-start gap-2">
171
- <span className="mt-0.5 shrink-0 text-muted-foreground">
172
- {isDirectory ? <FolderIcon /> : <FileIcon />}
173
- </span>
174
- <div className="min-w-0 flex-1">
175
- <div className="truncate text-sm font-medium text-foreground">
176
- {artifact.name}
177
- {isDirectory && "/"}
178
- </div>
179
- {parentDir && (
180
- <div className="truncate text-xs text-muted-foreground">
181
- {parentDir}
182
- </div>
183
- )}
184
- <div className="text-xs tabular-nums text-muted-foreground">
185
- {formatArtifactSize(artifact.sizeBytes)}
186
- </div>
187
- </div>
188
- </div>
189
-
190
- {/* Detection badge */}
191
- {isDetecting && !isDetected && (
192
- <div
193
- className="mt-1.5 h-5 w-28 animate-pulse rounded-full bg-muted"
194
- aria-hidden="true"
195
- />
196
- )}
197
- {detectionLabel && (
198
- <span className="mt-1.5 inline-flex items-center rounded-full bg-primary-subtle px-2 py-0.5 text-xs font-medium text-primary">
199
- {detectionLabel}
200
- </span>
201
- )}
202
-
203
- {/* Secondary actions: Preview + Download */}
204
- <div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1">
205
- {canPreview && (
206
- <button
207
- type="button"
208
- onClick={() => onPreview!(artifact)}
209
- className={cn(
210
- "text-xs font-medium text-primary transition-colors hover:text-primary-muted",
211
- FOCUS_RING_CLASSES,
212
- )}
213
- >
214
- Preview
215
- </button>
216
- )}
217
- <button
218
- type="button"
219
- onClick={() => download(artifact.storageKey, artifact.name)}
220
- disabled={isDownloading}
221
- className={cn(
222
- "inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground disabled:opacity-50",
223
- FOCUS_RING_CLASSES,
224
- )}
225
- >
226
- <DownloadIcon />
227
- {isDownloading ? "Preparing…" : isDirectory ? "Download ZIP" : "Download"}
228
- </button>
229
- </div>
230
-
231
- </div>
232
- );
233
- }
234
-
235
- // ---------------------------------------------------------------------------
236
- // Helpers
237
- // ---------------------------------------------------------------------------
238
-
239
- /**
240
- * Extracts a human-readable parent directory label from a sandbox path.
241
- * Given `/workspace/configs/agent.yaml` returns `configs/`.
242
- * Returns `null` when the path has no meaningful parent segment.
243
- */
244
- function parentDirectory(sandboxPath: string): string | null {
245
- const lastSlash = sandboxPath.lastIndexOf("/");
246
- if (lastSlash <= 0) return null;
247
- const parent = sandboxPath.slice(0, lastSlash);
248
- const segment = parent.slice(parent.lastIndexOf("/") + 1);
249
- return segment ? `${segment}/` : null;
250
- }
251
-
252
- // ---------------------------------------------------------------------------
253
- // Shared style constants
254
- // ---------------------------------------------------------------------------
255
-
256
- const FOCUS_RING_CLASSES =
257
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-sm";
258
-
259
- // ---------------------------------------------------------------------------
260
- // Inline SVG icons
261
- // ---------------------------------------------------------------------------
262
-
263
- function FileIcon() {
264
- return (
265
- <svg
266
- width="14"
267
- height="14"
268
- viewBox="0 0 14 14"
269
- fill="none"
270
- stroke="currentColor"
271
- strokeWidth="1.5"
272
- strokeLinecap="round"
273
- strokeLinejoin="round"
274
- aria-hidden="true"
275
- >
276
- <path d="M8 1H4C3.45 1 3 1.45 3 2V12C3 12.55 3.45 13 4 13H10C10.55 13 11 12.55 11 12V4L8 1Z" />
277
- <path d="M8 1V4H11" />
278
- </svg>
279
- );
280
- }
281
-
282
- function FolderIcon() {
283
- return (
284
- <svg
285
- width="14"
286
- height="14"
287
- viewBox="0 0 14 14"
288
- fill="none"
289
- stroke="currentColor"
290
- strokeWidth="1.5"
291
- strokeLinecap="round"
292
- strokeLinejoin="round"
293
- aria-hidden="true"
294
- >
295
- <path d="M13 11C13 11.55 12.55 12 12 12H2C1.45 12 1 11.55 1 11V3C1 2.45 1.45 2 2 2H5L7 4H12C12.55 4 13 4.45 13 5V11Z" />
296
- </svg>
297
- );
298
- }
299
-
300
- function DownloadIcon() {
301
- return (
302
- <svg
303
- width="10"
304
- height="10"
305
- viewBox="0 0 12 12"
306
- fill="none"
307
- stroke="currentColor"
308
- strokeWidth="1.5"
309
- strokeLinecap="round"
310
- strokeLinejoin="round"
311
- className="shrink-0"
312
- aria-hidden="true"
313
- >
314
- <path d="M6 1.5V8.5" />
315
- <path d="M3 6L6 9L9 6" />
316
- <path d="M2 10.5H10" />
317
- </svg>
318
- );
319
- }
320
-