@stigmer/react 3.12.7 → 3.12.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -3
- package/composer/ComposerToolbar.d.ts +1 -19
- package/composer/ComposerToolbar.d.ts.map +1 -1
- package/composer/ComposerToolbar.js +2 -7
- package/composer/ComposerToolbar.js.map +1 -1
- package/composer/SessionComposer.d.ts +0 -10
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +2 -2
- package/composer/SessionComposer.js.map +1 -1
- package/composer/index.d.ts +0 -1
- package/composer/index.d.ts.map +1 -1
- package/composer/index.js.map +1 -1
- package/conversation/ConversationTimelineView.d.ts +15 -1
- package/conversation/ConversationTimelineView.d.ts.map +1 -1
- package/conversation/ConversationTimelineView.js +3 -2
- package/conversation/ConversationTimelineView.js.map +1 -1
- package/conversation/ConversationsWorkbench.d.ts +14 -1
- package/conversation/ConversationsWorkbench.d.ts.map +1 -1
- package/conversation/ConversationsWorkbench.js +11 -2
- package/conversation/ConversationsWorkbench.js.map +1 -1
- package/execution/MessageThread.d.ts +33 -2
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +44 -6
- package/execution/MessageThread.js.map +1 -1
- package/execution/RecalledMemoriesCard.d.ts +47 -0
- package/execution/RecalledMemoriesCard.d.ts.map +1 -0
- package/execution/RecalledMemoriesCard.js +58 -0
- package/execution/RecalledMemoriesCard.js.map +1 -0
- package/execution/ResultView.d.ts.map +1 -1
- package/execution/ResultView.js +6 -0
- package/execution/ResultView.js.map +1 -1
- package/execution/ToolCallItem.d.ts.map +1 -1
- package/execution/ToolCallItem.js +13 -2
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/index.d.ts +2 -0
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +1 -0
- package/execution/index.js.map +1 -1
- package/execution/tool-categories.d.ts +1 -1
- package/execution/tool-categories.d.ts.map +1 -1
- package/execution/tool-categories.js +6 -0
- package/execution/tool-categories.js.map +1 -1
- package/identity-account/AccountPreferencesPanel.d.ts +2 -1
- package/identity-account/AccountPreferencesPanel.d.ts.map +1 -1
- package/identity-account/AccountPreferencesPanel.js +41 -3
- package/identity-account/AccountPreferencesPanel.js.map +1 -1
- package/identity-account/useAccountExecutionDefaults.d.ts +7 -0
- package/identity-account/useAccountExecutionDefaults.d.ts.map +1 -1
- package/identity-account/useAccountExecutionDefaults.js +5 -2
- package/identity-account/useAccountExecutionDefaults.js.map +1 -1
- package/index.d.ts +6 -6
- package/index.d.ts.map +1 -1
- package/index.js +2 -2
- package/index.js.map +1 -1
- package/internal/MemoryEnabledRow.d.ts +37 -0
- package/internal/MemoryEnabledRow.d.ts.map +1 -0
- package/internal/MemoryEnabledRow.js +25 -0
- package/internal/MemoryEnabledRow.js.map +1 -0
- package/internal/VirtualizedThread.d.ts +3 -1
- package/internal/VirtualizedThread.d.ts.map +1 -1
- package/internal/VirtualizedThread.js +3 -1
- package/internal/VirtualizedThread.js.map +1 -1
- package/internal/useAutoScroll.d.ts +18 -0
- package/internal/useAutoScroll.d.ts.map +1 -1
- package/internal/useAutoScroll.js +50 -0
- package/internal/useAutoScroll.js.map +1 -1
- package/memory/MemoryProposalCard.d.ts +35 -0
- package/memory/MemoryProposalCard.d.ts.map +1 -0
- package/memory/MemoryProposalCard.js +73 -0
- package/memory/MemoryProposalCard.js.map +1 -0
- package/memory/index.d.ts +2 -0
- package/memory/index.d.ts.map +1 -1
- package/memory/index.js +2 -0
- package/memory/index.js.map +1 -1
- package/memory/useMemory.d.ts +39 -0
- package/memory/useMemory.d.ts.map +1 -0
- package/memory/useMemory.js +43 -0
- package/memory/useMemory.js.map +1 -0
- package/organization/OrgPreferencesPanel.d.ts.map +1 -1
- package/organization/OrgPreferencesPanel.js +36 -4
- package/organization/OrgPreferencesPanel.js.map +1 -1
- package/package.json +4 -4
- package/session/AutoApproveIndicator.d.ts +18 -0
- package/session/AutoApproveIndicator.d.ts.map +1 -0
- package/session/AutoApproveIndicator.js +23 -0
- package/session/AutoApproveIndicator.js.map +1 -0
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +10 -9
- package/session/NewSessionViewer.js.map +1 -1
- package/session/SessionViewer.d.ts +21 -9
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +31 -21
- package/session/SessionViewer.js.map +1 -1
- package/session/facets/SetupTab.d.ts +43 -6
- package/session/facets/SetupTab.d.ts.map +1 -1
- package/session/facets/SetupTab.js +32 -36
- package/session/facets/SetupTab.js.map +1 -1
- package/session/facets/UsageTab.d.ts +2 -1
- package/session/facets/UsageTab.d.ts.map +1 -1
- package/session/facets/UsageTab.js +11 -5
- package/session/facets/UsageTab.js.map +1 -1
- package/session/facets/index.d.ts +1 -1
- package/session/facets/index.d.ts.map +1 -1
- package/session/facets/primitives.d.ts +58 -0
- package/session/facets/primitives.d.ts.map +1 -0
- package/session/facets/primitives.js +59 -0
- package/session/facets/primitives.js.map +1 -0
- package/session/index.d.ts +1 -1
- package/session/index.d.ts.map +1 -1
- package/session/index.js.map +1 -1
- package/session/useNewSessionFlow.d.ts +9 -4
- package/session/useNewSessionFlow.d.ts.map +1 -1
- package/session/useNewSessionFlow.js +20 -9
- package/session/useNewSessionFlow.js.map +1 -1
- package/session/useSessionPageFlow.d.ts +28 -10
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +16 -10
- package/session/useSessionPageFlow.js.map +1 -1
- package/settings/MemorySection.d.ts.map +1 -1
- package/settings/MemorySection.js +1 -1
- package/settings/MemorySection.js.map +1 -1
- package/src/attachment/__tests__/prepare-image.test.ts +12 -6
- package/src/composer/ComposerToolbar.tsx +0 -57
- package/src/composer/SessionComposer.tsx +1 -13
- package/src/composer/index.ts +0 -1
- package/src/conversation/ConversationTimelineView.tsx +17 -1
- package/src/conversation/ConversationsWorkbench.tsx +25 -0
- package/src/conversation/__tests__/ConversationTimelineView.layout.test.tsx +37 -1
- package/src/execution/MessageThread.tsx +75 -3
- package/src/execution/RecalledMemoriesCard.tsx +164 -0
- package/src/execution/ResultView.tsx +6 -0
- package/src/execution/ToolCallItem.tsx +18 -1
- package/src/execution/__tests__/RecalledMemoriesCard.test.tsx +123 -0
- package/src/execution/__tests__/message-thread-recalled-memories.test.tsx +216 -0
- package/src/execution/__tests__/message-thread-scroll-on-send.test.tsx +141 -0
- package/src/execution/__tests__/message-thread-slots.test.tsx +36 -0
- package/src/execution/index.ts +2 -0
- package/src/execution/tool-categories.ts +7 -0
- package/src/identity-account/AccountPreferencesPanel.tsx +89 -2
- package/src/identity-account/__tests__/AccountPreferencesPanel.test.tsx +112 -0
- package/src/identity-account/__tests__/useAccountExecutionDefaults.test.tsx +34 -1
- package/src/identity-account/useAccountExecutionDefaults.ts +12 -2
- package/src/index.ts +8 -1
- package/src/internal/MemoryEnabledRow.tsx +92 -0
- package/src/internal/VirtualizedThread.tsx +5 -0
- package/src/internal/__tests__/useAutoScroll.layout.test.tsx +105 -4
- package/src/internal/__tests__/useAutoScroll.test.tsx +41 -1
- package/src/internal/useAutoScroll.ts +54 -0
- package/src/memory/MemoryProposalCard.tsx +181 -0
- package/src/memory/__tests__/MemoryProposalCard.test.tsx +236 -0
- package/src/memory/__tests__/memoryHooks.test.tsx +63 -0
- package/src/memory/index.ts +5 -0
- package/src/memory/useMemory.ts +80 -0
- package/src/organization/OrgPreferencesPanel.tsx +52 -3
- package/src/organization/__tests__/OrgPreferencesPanel.test.tsx +65 -0
- package/src/session/AutoApproveIndicator.tsx +45 -0
- package/src/session/NewSessionViewer.tsx +18 -15
- package/src/session/SessionViewer.tsx +70 -32
- package/src/session/__tests__/NewSessionViewer.test.tsx +32 -0
- package/src/session/__tests__/SessionViewer-autoApprove.test.tsx +244 -0
- package/src/session/__tests__/SessionViewer-transcriptExport.test.tsx +60 -22
- package/src/session/__tests__/useNewSessionFlow.test.tsx +56 -0
- package/src/session/__tests__/useSessionPageFlow.autoApprove.test.tsx +87 -0
- package/src/session/facets/SetupTab.tsx +193 -157
- package/src/session/facets/UsageTab.tsx +38 -38
- package/src/session/facets/index.ts +1 -0
- package/src/session/facets/primitives.tsx +169 -0
- package/src/session/index.ts +1 -0
- package/src/session/useNewSessionFlow.ts +30 -15
- package/src/session/useSessionPageFlow.ts +44 -20
- package/src/settings/MemorySection.tsx +4 -2
- package/src/switch/Switch.tsx +4 -0
- package/src/workflow/__tests__/WorkflowExecutionViewer.approvals.test.tsx +26 -7
- package/src/workflow/__tests__/task-presentation.test.ts +49 -12
- package/src/workflow/__tests__/useWorkflowCanvas.dirty.test.tsx +7 -2
- package/src/workflow/__tests__/useWorkflowCanvas.drag.test.tsx +7 -2
- package/src/workflow/__tests__/workflow-thread-scroll-on-send.test.tsx +145 -0
- package/src/workflow/thread/WorkflowTaskThread.tsx +59 -32
- package/src/workflow/thread/task-presentation.ts +52 -7
- package/src/workspace/WorkspaceSurface.tsx +26 -3
- package/styles.css +1 -1
- package/switch/Switch.d.ts +3 -1
- package/switch/Switch.d.ts.map +1 -1
- package/switch/Switch.js +2 -2
- package/switch/Switch.js.map +1 -1
- package/workflow/thread/WorkflowTaskThread.d.ts +13 -0
- package/workflow/thread/WorkflowTaskThread.d.ts.map +1 -1
- package/workflow/thread/WorkflowTaskThread.js +33 -25
- package/workflow/thread/WorkflowTaskThread.js.map +1 -1
- package/workflow/thread/task-presentation.d.ts.map +1 -1
- package/workflow/thread/task-presentation.js +50 -7
- package/workflow/thread/task-presentation.js.map +1 -1
- package/workspace/WorkspaceSurface.js +11 -2
- package/workspace/WorkspaceSurface.js.map +1 -1
- package/src/composer/__tests__/ComposerToolbar-autoApprove.test.tsx +0 -80
- package/src/session/__tests__/SessionViewer-autoApproveToggle.test.tsx +0 -178
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { useId } from "react";
|
|
3
4
|
import type { McpServerUsageInput, ResourceRef } from "@stigmer/sdk";
|
|
4
|
-
import {
|
|
5
|
+
import { Copy, FileJson, FileText } from "lucide-react";
|
|
5
6
|
import type { HarnessOption } from "../../models/harness.js";
|
|
6
7
|
import { HARNESS_META } from "../../models/harness.js";
|
|
8
|
+
import { Switch } from "../../switch/Switch.js";
|
|
7
9
|
import type { ExecutionTargetOption } from "../execution-target.js";
|
|
8
10
|
import type { UseSessionVariablesReturn } from "../../execution/useSessionVariables.js";
|
|
11
|
+
import { useExportTranscript } from "../useExportTranscript.js";
|
|
12
|
+
import {
|
|
13
|
+
FACET_ROW_BUTTON,
|
|
14
|
+
FacetEmptyHint,
|
|
15
|
+
FacetKeyValueRow,
|
|
16
|
+
FacetRemoveButton,
|
|
17
|
+
FacetRow,
|
|
18
|
+
FacetSection,
|
|
19
|
+
} from "./primitives.js";
|
|
9
20
|
|
|
10
21
|
/** Interactive mutation callbacks for config items in SetupTab. */
|
|
11
22
|
export interface SetupTabMutationCallbacks {
|
|
@@ -17,6 +28,24 @@ export interface SetupTabMutationCallbacks {
|
|
|
17
28
|
readonly onRemoveSkill?: (ref: ResourceRef) => void;
|
|
18
29
|
}
|
|
19
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Wiring for the Run Config section's auto-approve switch — the session-level
|
|
33
|
+
* arming control (stigmer/stigmer#816 rework: config lives in Config, not the
|
|
34
|
+
* composer). Session-scoped: an explicit flip beats the account's
|
|
35
|
+
* `default_auto_approve` preference and the host's `approvalDefaults` for
|
|
36
|
+
* THIS conversation only, and is never persisted anywhere.
|
|
37
|
+
*
|
|
38
|
+
* Presence renders the switch; absence keeps the section read-only. Consumers
|
|
39
|
+
* must only wire it on surfaces whose viewer may submit approvals — never
|
|
40
|
+
* observer or guest audiences (the approval-submission withhold).
|
|
41
|
+
*/
|
|
42
|
+
export interface SetupTabAutoApprove {
|
|
43
|
+
/** Whether auto-approve is currently armed for this conversation. */
|
|
44
|
+
readonly armed: boolean;
|
|
45
|
+
/** Called with the next value when the user flips the switch. */
|
|
46
|
+
readonly onChange: (armed: boolean) => void;
|
|
47
|
+
}
|
|
48
|
+
|
|
20
49
|
/** Props for {@link SetupTab}. */
|
|
21
50
|
export interface SetupTabProps {
|
|
22
51
|
readonly agentRef: ResourceRef | null;
|
|
@@ -27,6 +56,23 @@ export interface SetupTabProps {
|
|
|
27
56
|
readonly harness: HarnessOption;
|
|
28
57
|
readonly executionTarget: ExecutionTargetOption | undefined;
|
|
29
58
|
readonly modelId: string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Session-level auto-approve switch in the Run Config section. When
|
|
61
|
+
* provided, the switch renders and is interactive at all times — including
|
|
62
|
+
* mid-run, where flipping it ON releases the in-flight execution's pending
|
|
63
|
+
* gates (the flow's standing responder). When absent (read-only audiences,
|
|
64
|
+
* demo fixtures), the section shows no approval control at all.
|
|
65
|
+
*/
|
|
66
|
+
readonly autoApprove?: SetupTabAutoApprove;
|
|
67
|
+
/**
|
|
68
|
+
* The session whose transcript the Session section exports. When provided,
|
|
69
|
+
* the facet renders Copy / Download Markdown / Download JSON actions
|
|
70
|
+
* (stigmer/stigmer#814's export, relocated from the header). Omit on the
|
|
71
|
+
* launcher (no session exists yet) and in inert fixtures. Deliberately not
|
|
72
|
+
* audience-gated: the export is `can_view`-scoped — it serializes exactly
|
|
73
|
+
* what the viewer already shows — so observers keep it.
|
|
74
|
+
*/
|
|
75
|
+
readonly sessionId?: string | null;
|
|
30
76
|
/**
|
|
31
77
|
* Interactive mutation callbacks. When provided, items render remove
|
|
32
78
|
* buttons. When absent, sections are read-only (DD-011).
|
|
@@ -43,15 +89,18 @@ export interface SetupTabProps {
|
|
|
43
89
|
}
|
|
44
90
|
|
|
45
91
|
/**
|
|
46
|
-
* Persistent session configuration panel (
|
|
47
|
-
*
|
|
92
|
+
* Persistent session configuration panel (Config facet) — shows run config
|
|
93
|
+
* (harness, model, target, and the session-level auto-approve switch), agent,
|
|
94
|
+
* MCP servers, skills, session variables, transcript export, and the host's
|
|
48
95
|
* access management control (via `accessSlot`).
|
|
49
96
|
*
|
|
50
|
-
*
|
|
97
|
+
* Rendered in the session panel's shared facet vocabulary (see
|
|
98
|
+
* `./primitives.tsx`): dense rows, quiet right-aligned metadata, and
|
|
99
|
+
* hover/focus-revealed actions — the Artifacts facet's idiom.
|
|
51
100
|
*
|
|
52
101
|
* When mutation callbacks are provided via `mutations`, items render
|
|
53
|
-
* inline remove
|
|
54
|
-
*
|
|
102
|
+
* inline remove affordances. When callbacks are absent, sections render
|
|
103
|
+
* read-only (backward compatible, DD-011).
|
|
55
104
|
*
|
|
56
105
|
* All visual properties flow through `--stgm-*` tokens (DD-005).
|
|
57
106
|
*/
|
|
@@ -64,6 +113,8 @@ export function SetupTab({
|
|
|
64
113
|
harness,
|
|
65
114
|
executionTarget,
|
|
66
115
|
modelId,
|
|
116
|
+
autoApprove,
|
|
117
|
+
sessionId,
|
|
67
118
|
mutations,
|
|
68
119
|
accessSlot,
|
|
69
120
|
}: SetupTabProps) {
|
|
@@ -75,6 +126,7 @@ export function SetupTab({
|
|
|
75
126
|
harness={harness}
|
|
76
127
|
executionTarget={executionTarget}
|
|
77
128
|
modelId={modelId}
|
|
129
|
+
autoApprove={autoApprove}
|
|
78
130
|
/>
|
|
79
131
|
|
|
80
132
|
<AgentSection
|
|
@@ -97,53 +149,13 @@ export function SetupTab({
|
|
|
97
149
|
<SessionVarsSection entries={sessionVariables.entries} />
|
|
98
150
|
)}
|
|
99
151
|
|
|
152
|
+
{sessionId && <TranscriptSection sessionId={sessionId} />}
|
|
153
|
+
|
|
100
154
|
{accessSlot && <section>{accessSlot}</section>}
|
|
101
155
|
</div>
|
|
102
156
|
);
|
|
103
157
|
}
|
|
104
158
|
|
|
105
|
-
// ---------------------------------------------------------------------------
|
|
106
|
-
// Shared section primitives
|
|
107
|
-
// ---------------------------------------------------------------------------
|
|
108
|
-
|
|
109
|
-
function SectionHeading({ children }: { children: React.ReactNode }) {
|
|
110
|
-
return (
|
|
111
|
-
<h3 className="stg:text-[0.65rem] stg:font-semibold stg:uppercase stg:tracking-wider stg:text-muted-foreground">
|
|
112
|
-
{children}
|
|
113
|
-
</h3>
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function EmptyHint({ children }: { children: React.ReactNode }) {
|
|
118
|
-
return (
|
|
119
|
-
<p className="stg:text-xs stg:text-muted-foreground/70">{children}</p>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function ItemPill({ children, className: cls }: { children: React.ReactNode; className?: string }) {
|
|
124
|
-
return (
|
|
125
|
-
<span className={cn(
|
|
126
|
-
"stg:inline-flex stg:items-center stg:gap-1.5 stg:rounded-md stg:bg-muted-subtle stg:px-2 stg:py-1 stg:text-xs stg:text-foreground",
|
|
127
|
-
cls,
|
|
128
|
-
)}>
|
|
129
|
-
{children}
|
|
130
|
-
</span>
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function RemoveButton({ onClick, label }: { onClick: () => void; label: string }) {
|
|
135
|
-
return (
|
|
136
|
-
<button
|
|
137
|
-
type="button"
|
|
138
|
-
onClick={onClick}
|
|
139
|
-
className="stg:shrink-0 stg:text-muted-foreground stg:hover:text-destructive stg:transition-colors"
|
|
140
|
-
aria-label={label}
|
|
141
|
-
>
|
|
142
|
-
<XIcon />
|
|
143
|
-
</button>
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
159
|
// ---------------------------------------------------------------------------
|
|
148
160
|
// Run config
|
|
149
161
|
// ---------------------------------------------------------------------------
|
|
@@ -152,33 +164,38 @@ function RunConfigSection({
|
|
|
152
164
|
harness,
|
|
153
165
|
executionTarget,
|
|
154
166
|
modelId,
|
|
167
|
+
autoApprove,
|
|
155
168
|
}: {
|
|
156
169
|
harness: HarnessOption;
|
|
157
170
|
executionTarget: ExecutionTargetOption | undefined;
|
|
158
171
|
modelId: string | undefined;
|
|
172
|
+
autoApprove: SetupTabAutoApprove | undefined;
|
|
159
173
|
}) {
|
|
174
|
+
const autoApproveLabelId = useId();
|
|
175
|
+
|
|
160
176
|
return (
|
|
161
|
-
<
|
|
162
|
-
<
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
{
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
<FacetSection heading="Run Config">
|
|
178
|
+
<FacetKeyValueRow label="Harness">
|
|
179
|
+
{HARNESS_META[harness]?.label ?? harness}
|
|
180
|
+
</FacetKeyValueRow>
|
|
181
|
+
{modelId && (
|
|
182
|
+
<FacetKeyValueRow label="Model">{modelId}</FacetKeyValueRow>
|
|
183
|
+
)}
|
|
184
|
+
{executionTarget && (
|
|
185
|
+
<FacetKeyValueRow label="Target">
|
|
186
|
+
{executionTarget === "local" ? "Local" : "Cloud"}
|
|
187
|
+
</FacetKeyValueRow>
|
|
188
|
+
)}
|
|
189
|
+
{autoApprove && (
|
|
190
|
+
<FacetKeyValueRow label="Auto-approve" labelId={autoApproveLabelId}>
|
|
191
|
+
<Switch
|
|
192
|
+
checked={autoApprove.armed}
|
|
193
|
+
onCheckedChange={autoApprove.onChange}
|
|
194
|
+
aria-labelledby={autoApproveLabelId}
|
|
195
|
+
/>
|
|
196
|
+
</FacetKeyValueRow>
|
|
197
|
+
)}
|
|
198
|
+
</FacetSection>
|
|
182
199
|
);
|
|
183
200
|
}
|
|
184
201
|
|
|
@@ -196,26 +213,25 @@ function AgentSection({
|
|
|
196
213
|
onRemove?: () => void;
|
|
197
214
|
}) {
|
|
198
215
|
return (
|
|
199
|
-
<
|
|
200
|
-
<SectionHeading>Agent</SectionHeading>
|
|
216
|
+
<FacetSection heading="Agent">
|
|
201
217
|
{agentRef ? (
|
|
202
|
-
<
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
</
|
|
218
|
+
<FacetRow
|
|
219
|
+
meta={isDefaultAgent ? "default" : undefined}
|
|
220
|
+
actions={
|
|
221
|
+
onRemove && !isDefaultAgent ? (
|
|
222
|
+
<FacetRemoveButton
|
|
223
|
+
onClick={onRemove}
|
|
224
|
+
label={`Remove agent ${agentRef.slug}`}
|
|
225
|
+
/>
|
|
226
|
+
) : undefined
|
|
227
|
+
}
|
|
228
|
+
>
|
|
229
|
+
<span className="stg:truncate">{agentRef.slug}</span>
|
|
230
|
+
</FacetRow>
|
|
215
231
|
) : (
|
|
216
|
-
<
|
|
232
|
+
<FacetEmptyHint>No agent selected — using platform default.</FacetEmptyHint>
|
|
217
233
|
)}
|
|
218
|
-
</
|
|
234
|
+
</FacetSection>
|
|
219
235
|
);
|
|
220
236
|
}
|
|
221
237
|
|
|
@@ -231,40 +247,36 @@ function McpSection({
|
|
|
231
247
|
onRemove?: (ref: ResourceRef) => void;
|
|
232
248
|
}) {
|
|
233
249
|
return (
|
|
234
|
-
<
|
|
235
|
-
<SectionHeading>
|
|
236
|
-
MCP Servers
|
|
237
|
-
{mcpServerUsages.length > 0 && (
|
|
238
|
-
<span className="stg:ml-1 stg:text-muted-foreground/60">({mcpServerUsages.length})</span>
|
|
239
|
-
)}
|
|
240
|
-
</SectionHeading>
|
|
250
|
+
<FacetSection heading="MCP Servers" count={mcpServerUsages.length}>
|
|
241
251
|
{mcpServerUsages.length > 0 ? (
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
<
|
|
252
|
+
mcpServerUsages.map((usage) => {
|
|
253
|
+
const slug = usage.mcpServerRef.slug;
|
|
254
|
+
const enabledCount = usage.enabledTools?.length;
|
|
255
|
+
return (
|
|
256
|
+
<FacetRow
|
|
257
|
+
key={`${usage.mcpServerRef.org}/${slug}`}
|
|
258
|
+
meta={
|
|
259
|
+
enabledCount != null && enabledCount > 0
|
|
260
|
+
? `${enabledCount} tool${enabledCount !== 1 ? "s" : ""}`
|
|
261
|
+
: undefined
|
|
262
|
+
}
|
|
263
|
+
actions={
|
|
264
|
+
onRemove ? (
|
|
265
|
+
<FacetRemoveButton
|
|
256
266
|
onClick={() => onRemove(usage.mcpServerRef)}
|
|
257
267
|
label={`Remove MCP server ${slug}`}
|
|
258
268
|
/>
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
269
|
+
) : undefined
|
|
270
|
+
}
|
|
271
|
+
>
|
|
272
|
+
<span className="stg:truncate">{slug}</span>
|
|
273
|
+
</FacetRow>
|
|
274
|
+
);
|
|
275
|
+
})
|
|
264
276
|
) : (
|
|
265
|
-
<
|
|
277
|
+
<FacetEmptyHint>No MCP servers attached.</FacetEmptyHint>
|
|
266
278
|
)}
|
|
267
|
-
</
|
|
279
|
+
</FacetSection>
|
|
268
280
|
);
|
|
269
281
|
}
|
|
270
282
|
|
|
@@ -280,31 +292,27 @@ function SkillsSection({
|
|
|
280
292
|
onRemove?: (ref: ResourceRef) => void;
|
|
281
293
|
}) {
|
|
282
294
|
return (
|
|
283
|
-
<
|
|
284
|
-
<SectionHeading>
|
|
285
|
-
Skills
|
|
286
|
-
{skillRefs.length > 0 && (
|
|
287
|
-
<span className="stg:ml-1 stg:text-muted-foreground/60">({skillRefs.length})</span>
|
|
288
|
-
)}
|
|
289
|
-
</SectionHeading>
|
|
295
|
+
<FacetSection heading="Skills" count={skillRefs.length}>
|
|
290
296
|
{skillRefs.length > 0 ? (
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
<
|
|
297
|
+
skillRefs.map((ref) => (
|
|
298
|
+
<FacetRow
|
|
299
|
+
key={`${ref.org}/${ref.slug}`}
|
|
300
|
+
actions={
|
|
301
|
+
onRemove ? (
|
|
302
|
+
<FacetRemoveButton
|
|
297
303
|
onClick={() => onRemove(ref)}
|
|
298
304
|
label={`Remove skill ${ref.slug}`}
|
|
299
305
|
/>
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
306
|
+
) : undefined
|
|
307
|
+
}
|
|
308
|
+
>
|
|
309
|
+
<span className="stg:truncate">{ref.slug}</span>
|
|
310
|
+
</FacetRow>
|
|
311
|
+
))
|
|
304
312
|
) : (
|
|
305
|
-
<
|
|
313
|
+
<FacetEmptyHint>No skills attached.</FacetEmptyHint>
|
|
306
314
|
)}
|
|
307
|
-
</
|
|
315
|
+
</FacetSection>
|
|
308
316
|
);
|
|
309
317
|
}
|
|
310
318
|
|
|
@@ -318,37 +326,65 @@ function SessionVarsSection({
|
|
|
318
326
|
entries: UseSessionVariablesReturn["entries"];
|
|
319
327
|
}) {
|
|
320
328
|
return (
|
|
321
|
-
<
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
<div className="stg:flex stg:flex-col stg:gap-1">
|
|
329
|
-
{entries.map((entry) => (
|
|
330
|
-
<ItemPill key={entry.id}>
|
|
331
|
-
<span className="stg:font-medium">{entry.key || "(unnamed)"}</span>
|
|
332
|
-
{entry.isSecret ? (
|
|
333
|
-
<span className="stg:text-muted-foreground">********</span>
|
|
329
|
+
<FacetSection heading="Session Variables" annotation="next message only">
|
|
330
|
+
{entries.map((entry) => (
|
|
331
|
+
<FacetRow
|
|
332
|
+
key={entry.id}
|
|
333
|
+
meta={
|
|
334
|
+
entry.isSecret ? (
|
|
335
|
+
"********"
|
|
334
336
|
) : (
|
|
335
|
-
<span className="stg:max-w-[140px] stg:truncate stg:
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
337
|
+
<span className="stg:inline-block stg:max-w-[140px] stg:truncate stg:align-bottom">
|
|
338
|
+
{entry.value}
|
|
339
|
+
</span>
|
|
340
|
+
)
|
|
341
|
+
}
|
|
342
|
+
>
|
|
343
|
+
<span className="stg:truncate stg:font-medium">
|
|
344
|
+
{entry.key || "(unnamed)"}
|
|
345
|
+
</span>
|
|
346
|
+
</FacetRow>
|
|
347
|
+
))}
|
|
348
|
+
</FacetSection>
|
|
341
349
|
);
|
|
342
350
|
}
|
|
343
351
|
|
|
344
352
|
// ---------------------------------------------------------------------------
|
|
345
|
-
//
|
|
353
|
+
// Transcript export (stigmer/stigmer#814, relocated from the viewer header)
|
|
346
354
|
// ---------------------------------------------------------------------------
|
|
347
355
|
|
|
348
|
-
function
|
|
356
|
+
function TranscriptSection({ sessionId }: { sessionId: string }) {
|
|
357
|
+
const exporter = useExportTranscript(sessionId);
|
|
358
|
+
|
|
349
359
|
return (
|
|
350
|
-
<
|
|
351
|
-
<
|
|
352
|
-
|
|
360
|
+
<FacetSection heading="Transcript">
|
|
361
|
+
<button
|
|
362
|
+
type="button"
|
|
363
|
+
onClick={() => void exporter.copyMarkdown()}
|
|
364
|
+
disabled={exporter.isExporting}
|
|
365
|
+
className={FACET_ROW_BUTTON}
|
|
366
|
+
>
|
|
367
|
+
<Copy className="stg:size-3.5 stg:shrink-0" aria-hidden="true" />
|
|
368
|
+
Copy transcript
|
|
369
|
+
</button>
|
|
370
|
+
<button
|
|
371
|
+
type="button"
|
|
372
|
+
onClick={() => void exporter.downloadMarkdown()}
|
|
373
|
+
disabled={exporter.isExporting}
|
|
374
|
+
className={FACET_ROW_BUTTON}
|
|
375
|
+
>
|
|
376
|
+
<FileText className="stg:size-3.5 stg:shrink-0" aria-hidden="true" />
|
|
377
|
+
Download Markdown
|
|
378
|
+
</button>
|
|
379
|
+
<button
|
|
380
|
+
type="button"
|
|
381
|
+
onClick={() => void exporter.downloadJson()}
|
|
382
|
+
disabled={exporter.isExporting}
|
|
383
|
+
className={FACET_ROW_BUTTON}
|
|
384
|
+
>
|
|
385
|
+
<FileJson className="stg:size-3.5 stg:shrink-0" aria-hidden="true" />
|
|
386
|
+
Download JSON
|
|
387
|
+
</button>
|
|
388
|
+
</FacetSection>
|
|
353
389
|
);
|
|
354
390
|
}
|
|
@@ -4,6 +4,7 @@ import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexe
|
|
|
4
4
|
import { ServiceTier } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
5
5
|
import { useSessionUsage, type ExecutionUsageEntry } from "../useSessionUsage.js";
|
|
6
6
|
import { UsageWidget, formatCost } from "../../execution/UsageWidget.js";
|
|
7
|
+
import { FacetSection } from "./primitives.js";
|
|
7
8
|
|
|
8
9
|
export interface UsageTabProps {
|
|
9
10
|
readonly executions: readonly AgentExecution[];
|
|
@@ -21,7 +22,8 @@ export interface UsageTabProps {
|
|
|
21
22
|
* left in control). Requested-vs-billed divergence is a platform alarm
|
|
22
23
|
* (`stigmer.billing.service_tier.mismatch`), not a per-row UI concern.
|
|
23
24
|
*
|
|
24
|
-
*
|
|
25
|
+
* Rendered in the session panel's shared facet vocabulary (see
|
|
26
|
+
* `./primitives.tsx`). Shows an empty state when no usage data is available.
|
|
25
27
|
*/
|
|
26
28
|
export function UsageTab({ executions }: UsageTabProps) {
|
|
27
29
|
const usage = useSessionUsage(executions);
|
|
@@ -37,7 +39,7 @@ export function UsageTab({ executions }: UsageTabProps) {
|
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
return (
|
|
40
|
-
<div className="stg:flex stg:flex-col stg:gap-
|
|
42
|
+
<div className="stg:flex stg:flex-col stg:gap-5">
|
|
41
43
|
<UsageWidget executions={executions} />
|
|
42
44
|
{usage.executionBreakdown.length > 0 && (
|
|
43
45
|
<ExecutionModelList
|
|
@@ -61,43 +63,41 @@ function ExecutionModelList({
|
|
|
61
63
|
readonly executions: readonly AgentExecution[];
|
|
62
64
|
}) {
|
|
63
65
|
return (
|
|
64
|
-
<
|
|
65
|
-
className="stg:flex stg:flex-col
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
<FacetSection heading="Models per run">
|
|
67
|
+
<div role="list" aria-label="Per-execution model and tier" className="stg:flex stg:flex-col">
|
|
68
|
+
{entries.map((entry, index) => {
|
|
69
|
+
const requestedTier = requestedTierLabel(executions, entry.executionId);
|
|
70
|
+
return (
|
|
71
|
+
<div
|
|
72
|
+
key={entry.executionId}
|
|
73
|
+
className="stg:flex stg:items-baseline stg:justify-between stg:gap-2 stg:px-2 stg:py-1 stg:text-xs"
|
|
74
|
+
role="listitem"
|
|
75
|
+
>
|
|
76
|
+
<span className="stg:min-w-0 stg:truncate stg:text-foreground">
|
|
77
|
+
<span className="stg:tabular-nums stg:text-muted-foreground">
|
|
78
|
+
#{index + 1}
|
|
79
|
+
</span>{" "}
|
|
80
|
+
{entry.resolvedModel || "—"}
|
|
81
|
+
{requestedTier && <RowBadge>{requestedTier} requested</RowBadge>}
|
|
82
|
+
{entry.isEstimated && <RowBadge>Estimated</RowBadge>}
|
|
83
|
+
</span>
|
|
84
|
+
<span className="stg:shrink-0 stg:tabular-nums stg:text-[0.65rem] stg:text-muted-foreground">
|
|
85
|
+
{formatCost(entry.billableCostUsd)}
|
|
86
|
+
</span>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
})}
|
|
71
90
|
</div>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
{entry.resolvedModel || "—"}
|
|
83
|
-
{requestedTier && (
|
|
84
|
-
<span className="stg:ml-1 stg:rounded stg:bg-muted stg:px-1 stg:py-0.5 stg:text-[10px] stg:font-medium stg:leading-none">
|
|
85
|
-
{requestedTier} requested
|
|
86
|
-
</span>
|
|
87
|
-
)}
|
|
88
|
-
{entry.isEstimated && (
|
|
89
|
-
<span className="stg:ml-1 stg:rounded stg:bg-muted stg:px-1 stg:py-0.5 stg:text-[10px] stg:font-medium stg:leading-none">
|
|
90
|
-
Estimated
|
|
91
|
-
</span>
|
|
92
|
-
)}
|
|
93
|
-
</span>
|
|
94
|
-
<span className="stg:shrink-0 stg:tabular-nums">
|
|
95
|
-
{formatCost(entry.billableCostUsd)}
|
|
96
|
-
</span>
|
|
97
|
-
</div>
|
|
98
|
-
);
|
|
99
|
-
})}
|
|
100
|
-
</div>
|
|
91
|
+
</FacetSection>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Quiet inline qualifier chip for a provenance row. */
|
|
96
|
+
function RowBadge({ children }: { readonly children: React.ReactNode }) {
|
|
97
|
+
return (
|
|
98
|
+
<span className="stg:ml-1 stg:rounded stg:bg-muted stg:px-1 stg:py-0.5 stg:text-[0.6rem] stg:font-medium stg:leading-none stg:text-muted-foreground">
|
|
99
|
+
{children}
|
|
100
|
+
</span>
|
|
101
101
|
);
|
|
102
102
|
}
|
|
103
103
|
|