@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
@@ -3,6 +3,8 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
3
  import { isTerminalPhase } from "../execution/execution-phases.js";
4
4
  import { useWorkspaceEditorsStoreRef, } from "../internal/store/index.js";
5
5
  import { PLAN_DOCUMENT_ENTRY_ID, PLAN_DOCUMENT_PATH } from "./plan-document.js";
6
+ import { ARTIFACT_DOCUMENT_ENTRY_ID } from "./artifact-document.js";
7
+ import { artifactKey } from "./useSessionArtifacts.js";
6
8
  /**
7
9
  * Create a {@link SessionPanelController} for a viewer instance.
8
10
  */
@@ -81,6 +83,13 @@ export function useSessionPanel({ phase, hasChanges, planKey = null, defaultView
81
83
  editorsStore.openPreview(entryId, path, options);
82
84
  setIsOpen(true);
83
85
  }, [editorsStore]);
86
+ const openArtifact = useCallback((artifact) => {
87
+ editorsStore.openPreview(ARTIFACT_DOCUMENT_ENTRY_ID, artifactKey(artifact));
88
+ setIsOpen(true);
89
+ }, [editorsStore]);
90
+ const pinArtifact = useCallback((artifact) => {
91
+ editorsStore.pin(ARTIFACT_DOCUMENT_ENTRY_ID, artifactKey(artifact));
92
+ }, [editorsStore]);
84
93
  const activateEditor = useCallback((entryId, path) => editorsStore.activate(entryId, path), [editorsStore]);
85
94
  const pinEditor = useCallback((entryId, path) => editorsStore.pin(entryId, path), [editorsStore]);
86
95
  const closeEditor = useCallback((entryId, path) => editorsStore.close(entryId, path), [editorsStore]);
@@ -111,6 +120,8 @@ export function useSessionPanel({ phase, hasChanges, planKey = null, defaultView
111
120
  pinEditor,
112
121
  closeEditor,
113
122
  openPlanDocument,
123
+ openArtifact,
124
+ pinArtifact,
114
125
  notifySelection,
115
126
  }), [
116
127
  editorsStore,
@@ -124,6 +135,8 @@ export function useSessionPanel({ phase, hasChanges, planKey = null, defaultView
124
135
  pinEditor,
125
136
  closeEditor,
126
137
  openPlanDocument,
138
+ openArtifact,
139
+ pinArtifact,
127
140
  notifySelection,
128
141
  ]);
129
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useSessionPanel.js","sourceRoot":"","sources":["../../src/session/useSessionPanel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useSessionPanel.js","sourceRoot":"","sources":["../../src/session/useSessionPanel.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexe
2
2
  import type { SurfaceRailView } from "../workspace/WorkspaceSurface.js";
3
3
  import type { SelectedThreadItem } from "../internal/store/selection-store.js";
4
4
  import type { ApplyResourceResult } from "../library/useApplyResource.js";
5
+ import { type SessionArtifactEntry } from "./useSessionArtifacts.js";
5
6
  import { type SetupTabProps } from "./facets/SetupTab.js";
6
7
  /** Options for {@link useSessionRailViews}. */
7
8
  export interface UseSessionRailViewsOptions {
@@ -23,6 +24,17 @@ export interface UseSessionRailViewsOptions {
23
24
  * of the preview modal.
24
25
  */
25
26
  readonly onOpenPlan?: (executionId: string) => void;
27
+ /**
28
+ * Open a (non-plan) artifact as an editor-pane document tab. Routed to the
29
+ * Artifacts facet so clicking an artifact opens it in the editor area (VS
30
+ * Code "each file is a tab") instead of the preview modal.
31
+ */
32
+ readonly onOpenArtifact?: (entry: SessionArtifactEntry) => void;
33
+ /**
34
+ * Pin a (non-plan) artifact's document tab — the double-click half of the
35
+ * Artifacts facet's open/activate split. Routed through to the facet's rows.
36
+ */
37
+ readonly onActivateArtifact?: (entry: SessionArtifactEntry) => void;
26
38
  /**
27
39
  * Whether to offer the execution-derived facets (Changes / Artifacts /
28
40
  * Usage). The launcher passes `false` — before a session exists there are no
@@ -41,5 +53,5 @@ export interface UseSessionRailViewsOptions {
41
53
  * tab rules — Changes/Artifacts surface only when data exists (with count
42
54
  * badges), Inspect only when a thread item is selected.
43
55
  */
44
- export declare function useSessionRailViews({ allExecutions, org, sessionConfig, selectedItem, onApplied, onImplementPlan, onOpenPlan, includeExecutionFacets, }: UseSessionRailViewsOptions): readonly SurfaceRailView[];
56
+ export declare function useSessionRailViews({ allExecutions, org, sessionConfig, selectedItem, onApplied, onImplementPlan, onOpenPlan, onOpenArtifact, onActivateArtifact, includeExecutionFacets, }: UseSessionRailViewsOptions): readonly SurfaceRailView[];
45
57
  //# sourceMappingURL=useSessionRailViews.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSessionRailViews.d.ts","sourceRoot":"","sources":["../../src/session/useSessionRailViews.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6DAA6D,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAG1E,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAMpE,+CAA+C;AAC/C,MAAM,WAAW,0BAA0B;IACzC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,SAAS,cAAc,EAAE,CAAC;IAClD,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IAClD,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACjD,mEAAmE;IACnE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC3D,6EAA6E;IAC7E,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD;;;;;OAKG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAC3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,aAAa,EACb,GAAG,EACH,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,EACf,UAAU,EACV,sBAA6B,GAC9B,EAAE,0BAA0B,GAAG,SAAS,eAAe,EAAE,CA6EzD"}
1
+ {"version":3,"file":"useSessionRailViews.d.ts","sourceRoot":"","sources":["../../src/session/useSessionRailViews.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6DAA6D,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAMpE,+CAA+C;AAC/C,MAAM,WAAW,0BAA0B;IACzC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,SAAS,cAAc,EAAE,CAAC;IAClD,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IAClD,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACjD,mEAAmE;IACnE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC3D,6EAA6E;IAC7E,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChE;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACpE;;;;;OAKG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAC3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,aAAa,EACb,GAAG,EACH,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,EACf,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,sBAA6B,GAC9B,EAAE,0BAA0B,GAAG,SAAS,eAAe,EAAE,CAiFzD"}
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useMemo } from "react";
4
4
  import { useSessionWriteBacks } from "./useSessionWriteBacks.js";
5
- import { useSessionArtifacts } from "./useSessionArtifacts.js";
5
+ import { useSessionArtifacts, } from "./useSessionArtifacts.js";
6
6
  import { SetupTab } from "./facets/SetupTab.js";
7
7
  import { ChangesTab } from "./facets/ChangesTab.js";
8
8
  import { ArtifactsTab } from "./facets/ArtifactsTab.js";
@@ -18,7 +18,7 @@ import { InspectTab } from "./facets/InspectTab.js";
18
18
  * tab rules — Changes/Artifacts surface only when data exists (with count
19
19
  * badges), Inspect only when a thread item is selected.
20
20
  */
21
- export function useSessionRailViews({ allExecutions, org, sessionConfig, selectedItem, onApplied, onImplementPlan, onOpenPlan, includeExecutionFacets = true, }) {
21
+ export function useSessionRailViews({ allExecutions, org, sessionConfig, selectedItem, onApplied, onImplementPlan, onOpenPlan, onOpenArtifact, onActivateArtifact, includeExecutionFacets = true, }) {
22
22
  const { hasWriteBacks, writeBackCount } = useSessionWriteBacks(allExecutions);
23
23
  const { hasArtifacts, artifactCount } = useSessionArtifacts(allExecutions);
24
24
  return useMemo(() => {
@@ -47,7 +47,7 @@ export function useSessionRailViews({ allExecutions, org, sessionConfig, selecte
47
47
  label: "Artifacts",
48
48
  icon: _jsx(ArtifactsIcon, {}),
49
49
  badge: artifactCount,
50
- content: (_jsx(ArtifactsTab, { executions: allExecutions, org: org, onApplied: onApplied, onImplementPlan: onImplementPlan, onOpenPlan: onOpenPlan })),
50
+ content: (_jsx(ArtifactsTab, { executions: allExecutions, org: org, onApplied: onApplied, onImplementPlan: onImplementPlan, onOpenPlan: onOpenPlan, onOpenArtifact: onOpenArtifact, onActivateArtifact: onActivateArtifact })),
51
51
  });
52
52
  }
53
53
  views.push({
@@ -78,6 +78,8 @@ export function useSessionRailViews({ allExecutions, org, sessionConfig, selecte
78
78
  onApplied,
79
79
  onImplementPlan,
80
80
  onOpenPlan,
81
+ onOpenArtifact,
82
+ onActivateArtifact,
81
83
  selectedItem,
82
84
  ]);
83
85
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useSessionRailViews.js","sourceRoot":"","sources":["../../src/session/useSessionRailViews.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useSessionRailViews.js","sourceRoot":"","sources":["../../src/session/useSessionRailViews.tsx"],"names":[],"mappings":"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"}
@@ -42,6 +42,7 @@ import {
42
42
  SecretsIcon,
43
43
  AlertTriangleIcon,
44
44
  ResolveSpinner,
45
+ XIcon,
45
46
  } from "./icons.js";
46
47
 
47
48
  /**
@@ -168,6 +169,18 @@ export interface SessionComposerSubmitContext {
168
169
  * `undefined` for ordinary submissions.
169
170
  */
170
171
  readonly buildFromPlan?: boolean;
172
+ /**
173
+ * ID of the execution this submission supersedes (edit-and-resubmit).
174
+ *
175
+ * Never set by the composer itself — the session viewer merges it into
176
+ * the context when the user submits while the composer is in editing
177
+ * mode (see `SessionComposerProps.isEditing`). Pass to execution
178
+ * creation as `supersedesExecutionId`; chat threads hide the superseded
179
+ * execution so the edited message replaces the original in place.
180
+ *
181
+ * `undefined` for ordinary submissions.
182
+ */
183
+ readonly supersedesExecutionId?: string;
171
184
  }
172
185
 
173
186
  /** Props for {@link SessionComposer}. */
@@ -202,6 +215,26 @@ export interface SessionComposerProps {
202
215
  /** `true` while a stop request is in flight — shows a spinner on the Stop button. */
203
216
  readonly isStopping?: boolean;
204
217
 
218
+ /**
219
+ * Marks the composer as editing a previously sent message
220
+ * (edit-and-resubmit). Renders an "Editing message" banner above the
221
+ * textarea with a cancel (X) affordance; Escape in the textarea also
222
+ * cancels. The banner is purely presentational — the viewer owns the
223
+ * editing state and attaches the supersede link on submit.
224
+ *
225
+ * Opt-in: when omitted, the composer behaves exactly as before.
226
+ */
227
+ readonly isEditing?: boolean;
228
+ /**
229
+ * Called when the user cancels editing (banner X or Escape).
230
+ *
231
+ * The consumer clears its editing state and typically clears the
232
+ * prefilled text via {@link SessionComposerHandle.setMessage}.
233
+ * Required for the editing banner to render its cancel affordance;
234
+ * ignored when `isEditing` is false.
235
+ */
236
+ readonly onCancelEdit?: () => void;
237
+
205
238
  /**
206
239
  * Currently selected execution harness.
207
240
  *
@@ -531,6 +564,8 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
531
564
  disabled = false,
532
565
  onStop,
533
566
  isStopping = false,
567
+ isEditing = false,
568
+ onCancelEdit,
534
569
  harness,
535
570
  onHarnessChange,
536
571
  showHarnessSelector = false,
@@ -1139,13 +1174,21 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
1139
1174
 
1140
1175
  const handleTextareaKeyDown = useCallback(
1141
1176
  (e: KeyboardEvent<HTMLTextAreaElement>) => {
1177
+ // Escape exits edit-and-resubmit mode — same reflex as dismissing a
1178
+ // popover. Only intercepted while editing so it never shadows other
1179
+ // Escape behaviors (e.g. closing an open picker above the textarea).
1180
+ if (isEditing && onCancelEdit && e.key === "Escape") {
1181
+ e.preventDefault();
1182
+ onCancelEdit();
1183
+ return;
1184
+ }
1142
1185
  if (!canSend && e.key === "Enter" && !e.shiftKey) {
1143
1186
  e.preventDefault();
1144
1187
  return;
1145
1188
  }
1146
1189
  composer.textareaProps.onKeyDown(e);
1147
1190
  },
1148
- [canSend, composer.textareaProps],
1191
+ [canSend, composer.textareaProps, isEditing, onCancelEdit],
1149
1192
  );
1150
1193
 
1151
1194
  const workspaceCount = workspace?.entries.length ?? 0;
@@ -1393,6 +1436,31 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
1393
1436
  onDragLeave={handleDragLeave}
1394
1437
  onDrop={handleDrop}
1395
1438
  >
1439
+ {/* Zone 0.5: Edit-and-resubmit banner. Rendered inside the card so the
1440
+ editing state visually owns the text below it — the user reads
1441
+ "Editing message" and the prefilled prompt as one unit. */}
1442
+ {isEditing && (
1443
+ <div
1444
+ role="status"
1445
+ className="flex items-center justify-between gap-2 rounded-t-xl border-b border-border bg-muted px-3 py-1.5"
1446
+ >
1447
+ <span className="text-xs font-medium text-muted-foreground">
1448
+ Editing message
1449
+ </span>
1450
+ {onCancelEdit && (
1451
+ <button
1452
+ type="button"
1453
+ onClick={onCancelEdit}
1454
+ aria-label="Cancel editing"
1455
+ title="Cancel editing (Esc)"
1456
+ className="rounded p-0.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
1457
+ >
1458
+ <XIcon />
1459
+ </button>
1460
+ )}
1461
+ </div>
1462
+ )}
1463
+
1396
1464
  {/* Zone 1: Textarea */}
1397
1465
  <div className="relative">
1398
1466
  <textarea
@@ -0,0 +1,128 @@
1
+ import { describe, it, expect, vi, afterEach } from "vitest";
2
+ import { render, screen, cleanup, fireEvent, waitFor } from "@testing-library/react";
3
+ import type { ReactNode } from "react";
4
+ import type { Stigmer } from "@stigmer/sdk";
5
+ import { StigmerContext } from "../../context";
6
+ import { ModelRegistryContext } from "../../models/ModelRegistryContext";
7
+ import { SessionComposer } from "../SessionComposer";
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Helpers
11
+ // ---------------------------------------------------------------------------
12
+
13
+ function createMinimalStigmerMock(): Stigmer {
14
+ return {
15
+ agentExecution: { uploadAttachment: vi.fn() },
16
+ environment: { getPersonal: vi.fn().mockResolvedValue(null) },
17
+ baseUrl: "http://localhost:8080",
18
+ getAuthCredential: vi.fn().mockResolvedValue("test-token"),
19
+ config: {
20
+ baseUrl: "http://localhost:8080",
21
+ getAccessToken: vi.fn().mockResolvedValue(""),
22
+ },
23
+ } as unknown as Stigmer;
24
+ }
25
+
26
+ function createWrapper(client: Stigmer) {
27
+ return function Wrapper({ children }: { children: ReactNode }) {
28
+ return (
29
+ <StigmerContext.Provider value={client}>
30
+ <ModelRegistryContext.Provider
31
+ value={{ models: [], isLoading: false, error: null, refetch: vi.fn() }}
32
+ >
33
+ {children}
34
+ </ModelRegistryContext.Provider>
35
+ </StigmerContext.Provider>
36
+ );
37
+ };
38
+ }
39
+
40
+ function renderComposer(
41
+ props?: Partial<React.ComponentProps<typeof SessionComposer>>,
42
+ ) {
43
+ const client = createMinimalStigmerMock();
44
+ const onSubmit = vi.fn();
45
+ const result = render(
46
+ <SessionComposer onSubmit={onSubmit} {...props} />,
47
+ { wrapper: createWrapper(client) },
48
+ );
49
+ return { ...result, onSubmit, client };
50
+ }
51
+
52
+ function getTextarea(): HTMLTextAreaElement {
53
+ return document.querySelector("textarea") as HTMLTextAreaElement;
54
+ }
55
+
56
+ afterEach(cleanup);
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // Tests
60
+ // ---------------------------------------------------------------------------
61
+
62
+ describe("SessionComposer — editing mode (edit-and-resubmit)", () => {
63
+ it("renders no editing banner by default (backward compatible)", () => {
64
+ renderComposer();
65
+
66
+ expect(screen.queryByText("Editing message")).toBeNull();
67
+ expect(
68
+ screen.queryByRole("button", { name: "Cancel editing" }),
69
+ ).toBeNull();
70
+ });
71
+
72
+ it("renders the editing banner with a cancel affordance while isEditing", () => {
73
+ renderComposer({ isEditing: true, onCancelEdit: vi.fn() });
74
+
75
+ expect(screen.getByText("Editing message")).toBeTruthy();
76
+ expect(
77
+ screen.getByRole("button", { name: "Cancel editing" }),
78
+ ).toBeTruthy();
79
+ });
80
+
81
+ it("clicking the banner X calls onCancelEdit", () => {
82
+ const onCancelEdit = vi.fn();
83
+ renderComposer({ isEditing: true, onCancelEdit });
84
+
85
+ fireEvent.click(screen.getByRole("button", { name: "Cancel editing" }));
86
+ expect(onCancelEdit).toHaveBeenCalledTimes(1);
87
+ });
88
+
89
+ it("Escape in the textarea calls onCancelEdit while editing", () => {
90
+ const onCancelEdit = vi.fn();
91
+ renderComposer({ isEditing: true, onCancelEdit });
92
+
93
+ fireEvent.keyDown(getTextarea(), { key: "Escape" });
94
+ expect(onCancelEdit).toHaveBeenCalledTimes(1);
95
+ });
96
+
97
+ it("Escape does nothing when not editing", () => {
98
+ const onCancelEdit = vi.fn();
99
+ renderComposer({ isEditing: false, onCancelEdit });
100
+
101
+ fireEvent.keyDown(getTextarea(), { key: "Escape" });
102
+ expect(onCancelEdit).not.toHaveBeenCalled();
103
+ });
104
+
105
+ it("Enter still submits while editing — cancel is Escape-only", async () => {
106
+ const onCancelEdit = vi.fn();
107
+ const { onSubmit } = renderComposer({ isEditing: true, onCancelEdit });
108
+
109
+ const textarea = getTextarea();
110
+ fireEvent.change(textarea, { target: { value: "corrected message" } });
111
+ fireEvent.keyDown(textarea, { key: "Enter", shiftKey: false });
112
+
113
+ await waitFor(() => {
114
+ expect(onSubmit).toHaveBeenCalledTimes(1);
115
+ });
116
+ expect(onSubmit.mock.calls[0][0]).toBe("corrected message");
117
+ expect(onCancelEdit).not.toHaveBeenCalled();
118
+ });
119
+
120
+ it("renders the banner without a cancel button when onCancelEdit is omitted", () => {
121
+ renderComposer({ isEditing: true });
122
+
123
+ expect(screen.getByText("Editing message")).toBeTruthy();
124
+ expect(
125
+ screen.queryByRole("button", { name: "Cancel editing" }),
126
+ ).toBeNull();
127
+ });
128
+ });
@@ -0,0 +1,79 @@
1
+ "use client";
2
+
3
+ import { cn } from "@stigmer/theme";
4
+
5
+ /** Props for {@link ArtifactApplyButton}. */
6
+ export interface ArtifactApplyButtonProps {
7
+ /** CTA label (`"Apply to org"` / `"Push Skill to org"`). */
8
+ readonly label: string;
9
+ /**
10
+ * Whether the producing execution is terminal. The apply/push action is only
11
+ * enabled once the execution has finished; a mid-run artifact renders the
12
+ * button disabled (its content may still change).
13
+ */
14
+ readonly isTerminal: boolean;
15
+ /** `true` while the apply/push is in-flight. */
16
+ readonly isApplying: boolean;
17
+ /** Perform the apply/push. */
18
+ readonly onApply: () => void;
19
+ }
20
+
21
+ /**
22
+ * The primary "Apply to [org]" / "Push Skill to [org]" action for a detected
23
+ * artifact resource, shared by every artifact chrome (the preview modal's
24
+ * action bar and the editor-area `ArtifactDocument` toolbar) so its
25
+ * terminal-gating, in-flight, and disabled states are single-source.
26
+ *
27
+ * All visual properties flow through `--stgm-*` tokens (DD-005).
28
+ */
29
+ export function ArtifactApplyButton({
30
+ label,
31
+ isTerminal,
32
+ isApplying,
33
+ onApply,
34
+ }: ArtifactApplyButtonProps) {
35
+ const canApply = isTerminal && !isApplying;
36
+
37
+ return (
38
+ <button
39
+ type="button"
40
+ onClick={canApply ? onApply : undefined}
41
+ disabled={!canApply}
42
+ aria-busy={isApplying}
43
+ className={cn(
44
+ "rounded-md px-4 py-1.5 text-xs font-medium transition-colors",
45
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
46
+ "disabled:cursor-not-allowed",
47
+ canApply
48
+ ? "bg-primary text-primary-foreground hover:bg-primary-hover"
49
+ : "bg-muted text-muted-foreground",
50
+ )}
51
+ >
52
+ {isApplying ? (
53
+ <span className="inline-flex items-center gap-1.5">
54
+ <SpinnerIcon />
55
+ Applying{"\u2026"}
56
+ </span>
57
+ ) : (
58
+ label
59
+ )}
60
+ </button>
61
+ );
62
+ }
63
+
64
+ function SpinnerIcon() {
65
+ return (
66
+ <svg
67
+ width="12"
68
+ height="12"
69
+ viewBox="0 0 12 12"
70
+ fill="none"
71
+ stroke="currentColor"
72
+ strokeWidth="1.5"
73
+ className="shrink-0 animate-spin"
74
+ aria-hidden="true"
75
+ >
76
+ <path d="M6 1.5A4.5 4.5 0 1 1 1.5 6" strokeLinecap="round" />
77
+ </svg>
78
+ );
79
+ }