@stigmer/react 3.0.5 → 3.0.7-dev.20260611143057

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 (137) hide show
  1. package/agent/AgentDetailView.d.ts.map +1 -1
  2. package/agent/AgentDetailView.js +1 -1
  3. package/agent/AgentDetailView.js.map +1 -1
  4. package/agent-instance/AgentInstanceDetailPanel.d.ts.map +1 -1
  5. package/agent-instance/AgentInstanceDetailPanel.js +2 -13
  6. package/agent-instance/AgentInstanceDetailPanel.js.map +1 -1
  7. package/agent-instance/AgentInstanceList.d.ts.map +1 -1
  8. package/agent-instance/AgentInstanceList.js +2 -13
  9. package/agent-instance/AgentInstanceList.js.map +1 -1
  10. package/agent-instance/CreateAgentInstanceDialog.d.ts.map +1 -1
  11. package/agent-instance/CreateAgentInstanceDialog.js +1 -1
  12. package/agent-instance/CreateAgentInstanceDialog.js.map +1 -1
  13. package/composer/SessionComposer.d.ts +14 -0
  14. package/composer/SessionComposer.d.ts.map +1 -1
  15. package/composer/SessionComposer.js +15 -9
  16. package/composer/SessionComposer.js.map +1 -1
  17. package/index.d.ts +3 -3
  18. package/index.d.ts.map +1 -1
  19. package/index.js +1 -1
  20. package/index.js.map +1 -1
  21. package/library/InstanceVisibilitySelector.d.ts +30 -23
  22. package/library/InstanceVisibilitySelector.d.ts.map +1 -1
  23. package/library/InstanceVisibilitySelector.js +22 -145
  24. package/library/InstanceVisibilitySelector.js.map +1 -1
  25. package/library/ResourceVisibilityControl.d.ts +23 -6
  26. package/library/ResourceVisibilityControl.d.ts.map +1 -1
  27. package/library/ResourceVisibilityControl.js +38 -9
  28. package/library/ResourceVisibilityControl.js.map +1 -1
  29. package/library/ScopeToggle.d.ts +1 -1
  30. package/library/ScopeToggle.js +1 -1
  31. package/library/VisibilityOptionRow.d.ts +52 -0
  32. package/library/VisibilityOptionRow.d.ts.map +1 -0
  33. package/library/VisibilityOptionRow.js +92 -0
  34. package/library/VisibilityOptionRow.js.map +1 -0
  35. package/library/VisibilitySelector.d.ts +98 -0
  36. package/library/VisibilitySelector.d.ts.map +1 -0
  37. package/library/VisibilitySelector.js +193 -0
  38. package/library/VisibilitySelector.js.map +1 -0
  39. package/library/index.d.ts +4 -2
  40. package/library/index.d.ts.map +1 -1
  41. package/library/index.js +2 -1
  42. package/library/index.js.map +1 -1
  43. package/library/useUpdateVisibility.d.ts +5 -4
  44. package/library/useUpdateVisibility.d.ts.map +1 -1
  45. package/library/useUpdateVisibility.js +5 -4
  46. package/library/useUpdateVisibility.js.map +1 -1
  47. package/library/visibilityLevels.d.ts +96 -0
  48. package/library/visibilityLevels.d.ts.map +1 -0
  49. package/library/visibilityLevels.js +97 -0
  50. package/library/visibilityLevels.js.map +1 -0
  51. package/mcp-server/McpServerDetailView.d.ts +1 -11
  52. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  53. package/mcp-server/McpServerDetailView.js +3 -6
  54. package/mcp-server/McpServerDetailView.js.map +1 -1
  55. package/package.json +4 -4
  56. package/resource-detail/types.d.ts +1 -1
  57. package/session/NewSessionViewer.d.ts +32 -1
  58. package/session/NewSessionViewer.d.ts.map +1 -1
  59. package/session/NewSessionViewer.js +20 -9
  60. package/session/NewSessionViewer.js.map +1 -1
  61. package/session/SessionViewer.d.ts +24 -1
  62. package/session/SessionViewer.d.ts.map +1 -1
  63. package/session/SessionViewer.js +18 -12
  64. package/session/SessionViewer.js.map +1 -1
  65. package/session/audience.d.ts +21 -0
  66. package/session/audience.d.ts.map +1 -0
  67. package/session/audience.js +2 -0
  68. package/session/audience.js.map +1 -0
  69. package/session/index.d.ts +2 -0
  70. package/session/index.d.ts.map +1 -1
  71. package/session/index.js.map +1 -1
  72. package/session/runtime-env.d.ts +47 -0
  73. package/session/runtime-env.d.ts.map +1 -0
  74. package/session/runtime-env.js +20 -0
  75. package/session/runtime-env.js.map +1 -0
  76. package/session/useNewSessionFlow.d.ts +25 -0
  77. package/session/useNewSessionFlow.d.ts.map +1 -1
  78. package/session/useNewSessionFlow.js +20 -8
  79. package/session/useNewSessionFlow.js.map +1 -1
  80. package/session/useSessionPageFlow.d.ts +27 -2
  81. package/session/useSessionPageFlow.d.ts.map +1 -1
  82. package/session/useSessionPageFlow.js +34 -13
  83. package/session/useSessionPageFlow.js.map +1 -1
  84. package/skill/SkillDetailView.d.ts.map +1 -1
  85. package/skill/SkillDetailView.js +1 -1
  86. package/skill/SkillDetailView.js.map +1 -1
  87. package/src/agent/AgentDetailView.tsx +1 -0
  88. package/src/agent-instance/AgentInstanceDetailPanel.tsx +7 -32
  89. package/src/agent-instance/AgentInstanceList.tsx +7 -32
  90. package/src/agent-instance/CreateAgentInstanceDialog.tsx +1 -0
  91. package/src/composer/SessionComposer.tsx +30 -8
  92. package/src/composer/__tests__/SessionComposer-lockAgent.test.tsx +150 -0
  93. package/src/index.ts +10 -2
  94. package/src/library/InstanceVisibilitySelector.tsx +44 -283
  95. package/src/library/ResourceVisibilityControl.tsx +54 -8
  96. package/src/library/ScopeToggle.tsx +1 -1
  97. package/src/library/VisibilityOptionRow.tsx +244 -0
  98. package/src/library/VisibilitySelector.tsx +436 -0
  99. package/src/library/__tests__/VisibilitySelector.test.tsx +256 -0
  100. package/src/library/index.ts +13 -2
  101. package/src/library/useUpdateVisibility.ts +5 -4
  102. package/src/library/visibilityLevels.ts +174 -0
  103. package/src/mcp-server/McpServerDetailView.tsx +10 -35
  104. package/src/resource-detail/types.ts +1 -1
  105. package/src/session/NewSessionViewer.tsx +61 -12
  106. package/src/session/SessionViewer.tsx +51 -15
  107. package/src/session/__tests__/audienceWiring.test.tsx +274 -0
  108. package/src/session/__tests__/useNewSessionFlow.test.tsx +122 -0
  109. package/src/session/__tests__/useSessionPageFlow.runtimeEnv.test.tsx +170 -0
  110. package/src/session/audience.ts +20 -0
  111. package/src/session/index.ts +3 -0
  112. package/src/session/runtime-env.ts +57 -0
  113. package/src/session/useNewSessionFlow.ts +44 -9
  114. package/src/session/useSessionPageFlow.ts +65 -17
  115. package/src/skill/SkillDetailView.tsx +1 -0
  116. package/src/workflow/WorkflowDetailView.tsx +1 -0
  117. package/src/workflow/instance/CreateWorkflowInstanceDialog.tsx +1 -0
  118. package/src/workflow/instance/WorkflowInstanceDetailPanel.tsx +7 -32
  119. package/src/workflow/instance/WorkflowInstanceList.tsx +7 -32
  120. package/styles.css +1 -1
  121. package/workflow/WorkflowDetailView.d.ts.map +1 -1
  122. package/workflow/WorkflowDetailView.js +1 -1
  123. package/workflow/WorkflowDetailView.js.map +1 -1
  124. package/workflow/instance/CreateWorkflowInstanceDialog.d.ts.map +1 -1
  125. package/workflow/instance/CreateWorkflowInstanceDialog.js +1 -1
  126. package/workflow/instance/CreateWorkflowInstanceDialog.js.map +1 -1
  127. package/workflow/instance/WorkflowInstanceDetailPanel.d.ts.map +1 -1
  128. package/workflow/instance/WorkflowInstanceDetailPanel.js +2 -13
  129. package/workflow/instance/WorkflowInstanceDetailPanel.js.map +1 -1
  130. package/workflow/instance/WorkflowInstanceList.d.ts.map +1 -1
  131. package/workflow/instance/WorkflowInstanceList.js +2 -13
  132. package/workflow/instance/WorkflowInstanceList.js.map +1 -1
  133. package/library/VisibilityToggle.d.ts +0 -53
  134. package/library/VisibilityToggle.d.ts.map +0 -1
  135. package/library/VisibilityToggle.js +0 -100
  136. package/library/VisibilityToggle.js.map +0 -1
  137. package/src/library/VisibilityToggle.tsx +0 -280
@@ -10,8 +10,7 @@ import type { ResourceRef } from "@stigmer/sdk";
10
10
  import { getUserMessage } from "@stigmer/sdk";
11
11
  import { useUpdateAgentInstance } from "./useUpdateAgentInstance";
12
12
  import { useDeleteAgentInstance } from "./useDeleteAgentInstance";
13
- import { useUpdateVisibility } from "../library/useUpdateVisibility";
14
- import { InstanceVisibilitySelector } from "../library/InstanceVisibilitySelector";
13
+ import { ResourceVisibilityControl } from "../library/ResourceVisibilityControl";
15
14
  import { PermissionGate } from "../iam-policy/PermissionGate";
16
15
  import { SharePanel } from "../iam-policy/SharePanel";
17
16
  import { EnvironmentPicker } from "../environment/EnvironmentPicker";
@@ -55,7 +54,6 @@ export function AgentInstanceDetailPanel({
55
54
 
56
55
  const { update, isUpdating } = useUpdateAgentInstance();
57
56
  const { deleteInstance, isDeleting } = useDeleteAgentInstance();
58
- const { updateVisibility, isPending: isVisibilityPending } = useUpdateVisibility("agentInstance", id || null);
59
57
  const { environments } = useEnvironmentList(org);
60
58
 
61
59
  const [isEditingEnvs, setIsEditingEnvs] = useState(false);
@@ -64,14 +62,6 @@ export function AgentInstanceDetailPanel({
64
62
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
65
63
  const [deleteError, setDeleteError] = useState<Error | null>(null);
66
64
 
67
- const handleVisibilityChange = useCallback(
68
- async (v: ApiResourceVisibility) => {
69
- await updateVisibility(v);
70
- onUpdated?.();
71
- },
72
- [updateVisibility, onUpdated],
73
- );
74
-
75
65
  const handleStartEditEnvs = useCallback(() => {
76
66
  const currentRefs: ResourceRef[] = (spec?.environmentRefs ?? []).map((ref) => ({
77
67
  org: ref.org || org,
@@ -254,21 +244,12 @@ export function AgentInstanceDetailPanel({
254
244
  {/* Visibility */}
255
245
  <div className="px-4 py-3">
256
246
  <h4 className="text-xs font-medium text-muted-foreground mb-2">Visibility</h4>
257
- <PermissionGate
258
- resource={{ kind: "agent_instance", id }}
259
- relation="can_edit"
260
- fallback={
261
- <span className="text-sm text-foreground">
262
- {VISIBILITY_LABELS[meta?.visibility ?? 0] ?? "Private"}
263
- </span>
264
- }
265
- >
266
- <InstanceVisibilitySelector
267
- visibility={meta?.visibility ?? ApiResourceVisibility.visibility_private}
268
- onVisibilityChange={handleVisibilityChange}
269
- isPending={isVisibilityPending}
270
- />
271
- </PermissionGate>
247
+ <ResourceVisibilityControl
248
+ kind="agentInstance"
249
+ resourceId={id}
250
+ visibility={meta?.visibility ?? ApiResourceVisibility.visibility_private}
251
+ onChanged={onUpdated}
252
+ />
272
253
  </div>
273
254
 
274
255
  {/* Share Panel */}
@@ -344,12 +325,6 @@ export function AgentInstanceDetailPanel({
344
325
  );
345
326
  }
346
327
 
347
- const VISIBILITY_LABELS: Record<number, string> = {
348
- [ApiResourceVisibility.visibility_private]: "Private",
349
- [ApiResourceVisibility.visibility_org]: "Organization",
350
- [ApiResourceVisibility.visibility_public]: "Public",
351
- };
352
-
353
328
  function CloseIcon() {
354
329
  return (
355
330
  <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
@@ -6,8 +6,7 @@ import type { AgentInstance } from "@stigmer/protos/ai/stigmer/agentic/agentinst
6
6
  import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
7
7
  import { useAgentInstances } from "./useAgentInstances";
8
8
  import { useEnvironmentList } from "../environment/useEnvironmentList";
9
- import { useUpdateVisibility } from "../library/useUpdateVisibility";
10
- import { InstanceVisibilitySelector } from "../library/InstanceVisibilitySelector";
9
+ import { ResourceVisibilityControl } from "../library/ResourceVisibilityControl";
11
10
  import { PermissionGate } from "../iam-policy/PermissionGate";
12
11
  import { AgentInstanceEmptyState } from "./AgentInstanceEmptyState";
13
12
 
@@ -175,18 +174,9 @@ function InstanceRow({
175
174
  const meta = instance.metadata;
176
175
  const id = meta?.id ?? "";
177
176
  const isPersonal = meta?.labels?.[PERSONAL_LABEL] === "true";
178
- const { updateVisibility, isPending } = useUpdateVisibility("agentInstance", id || null);
179
177
 
180
178
  const envRefs = instance.spec?.environmentRefs ?? [];
181
179
 
182
- const handleVisibilityChange = useCallback(
183
- async (v: ApiResourceVisibility) => {
184
- await updateVisibility(v);
185
- refetch();
186
- },
187
- [updateVisibility, refetch],
188
- );
189
-
190
180
  return (
191
181
  <tr
192
182
  className={cn(
@@ -245,21 +235,12 @@ function InstanceRow({
245
235
 
246
236
  <td className="px-4 py-2.5" onClick={(e) => e.stopPropagation()}>
247
237
  {id ? (
248
- <PermissionGate
249
- resource={{ kind: "agent_instance", id }}
250
- relation="can_edit"
251
- fallback={
252
- <span className="text-xs text-muted-foreground">
253
- {VISIBILITY_LABELS[meta?.visibility ?? 0] ?? "Private"}
254
- </span>
255
- }
256
- >
257
- <InstanceVisibilitySelector
258
- visibility={meta?.visibility ?? ApiResourceVisibility.visibility_private}
259
- onVisibilityChange={handleVisibilityChange}
260
- isPending={isPending}
261
- />
262
- </PermissionGate>
238
+ <ResourceVisibilityControl
239
+ kind="agentInstance"
240
+ resourceId={id}
241
+ visibility={meta?.visibility ?? ApiResourceVisibility.visibility_private}
242
+ onChanged={refetch}
243
+ />
263
244
  ) : (
264
245
  <span className="text-xs text-muted-foreground">{"\u2014"}</span>
265
246
  )}
@@ -304,12 +285,6 @@ function InstanceRow({
304
285
  );
305
286
  }
306
287
 
307
- const VISIBILITY_LABELS: Record<number, string> = {
308
- [ApiResourceVisibility.visibility_private]: "Private",
309
- [ApiResourceVisibility.visibility_org]: "Organization",
310
- [ApiResourceVisibility.visibility_public]: "Public",
311
- };
312
-
313
288
  function LoadingSkeleton() {
314
289
  return (
315
290
  <div className="space-y-2 py-4">
@@ -203,6 +203,7 @@ export function CreateAgentInstanceDialog({
203
203
  <InstanceVisibilitySelector
204
204
  visibility={visibility}
205
205
  onVisibilityChange={setVisibility}
206
+ mode="create"
206
207
  disabled={isCreating}
207
208
  />
208
209
  </div>
@@ -309,6 +309,21 @@ export interface SessionComposerProps {
309
309
  */
310
310
  readonly isDefaultAgent?: boolean;
311
311
 
312
+ /**
313
+ * Lock the current agent: the Agent entry is removed from the
314
+ * Configure menu so the user cannot swap or deselect it.
315
+ *
316
+ * Locking does not unwire the agent machinery — `initialAgentRef`
317
+ * resolution still runs on mount, and when the agent requires
318
+ * credentials the environment form stays reachable in the Configure
319
+ * menu until setup completes (lock ≠ unwire). Pair with
320
+ * `initialAgentRef` to pin a pre-configured agent in end-user-facing
321
+ * embeds (see `SessionViewer` / `NewSessionViewer` `audience`).
322
+ *
323
+ * @default false
324
+ */
325
+ readonly lockAgent?: boolean;
326
+
312
327
  /**
313
328
  * Currently selected MCP server usages.
314
329
  * When `onMcpServerUsagesChange` is provided, a MCP server trigger
@@ -496,6 +511,7 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
496
511
  initialAgentRef,
497
512
  initialInstanceId,
498
513
  isDefaultAgent = false,
514
+ lockAgent = false,
499
515
  mcpServerUsages,
500
516
  onMcpServerUsagesChange,
501
517
  skillRefs,
@@ -1140,13 +1156,19 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
1140
1156
  (agentSetup.state.status === "needsEnvVars" ||
1141
1157
  agentSetup.state.status === "resolving" ||
1142
1158
  agentSetup.state.status === "submitting");
1143
- items.push({
1144
- id: "agent",
1145
- icon: <AgentIcon />,
1146
- label: "Agent",
1147
- count: agentRef || agentPending ? 1 : 0,
1148
- hasWarning: agentPending && agentSetup.state.status === "needsEnvVars",
1149
- });
1159
+ // A locked agent stays out of the menu unless setup is pending:
1160
+ // the env-collection form lives in this panel and must remain
1161
+ // reachable until the agent resolves (lock ≠ unwire). Once
1162
+ // resolved, the entry disappears and the agent cannot be swapped.
1163
+ if (!lockAgent || agentPending) {
1164
+ items.push({
1165
+ id: "agent",
1166
+ icon: <AgentIcon />,
1167
+ label: "Agent",
1168
+ count: agentRef || agentPending ? 1 : 0,
1169
+ hasWarning: agentPending && agentSetup.state.status === "needsEnvVars",
1170
+ });
1171
+ }
1150
1172
  }
1151
1173
  if (showMcp) {
1152
1174
  items.push({
@@ -1174,7 +1196,7 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
1174
1196
  });
1175
1197
  }
1176
1198
  return items;
1177
- }, [showAgent, agentRef, agentSetup.state, showMcp, mcpCount, mcpSetup.needsSetupCount, showSkills, skillCount, showSessionVars, sessionVarCount]);
1199
+ }, [showAgent, lockAgent, agentRef, agentSetup.state, showMcp, mcpCount, mcpSetup.needsSetupCount, showSkills, skillCount, showSessionVars, sessionVarCount]);
1178
1200
 
1179
1201
  const renderConfigPanel = useCallback(
1180
1202
  (panelId: string): React.ReactNode => {
@@ -0,0 +1,150 @@
1
+ import { describe, it, expect, vi, beforeAll, beforeEach, afterEach } from "vitest";
2
+ import { render, screen, cleanup, fireEvent } 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
+
8
+ // Without a StigmerProvider the portal container is null, and Base UI's
9
+ // Portal renders nothing — pin it to document.body so the popover mounts.
10
+ vi.mock("../../portal-container", () => ({
11
+ useStigmerPortalContainer: () => document.body,
12
+ }));
13
+
14
+ // Controllable agent-setup state — lets these tests drive the lock × setup
15
+ // matrix directly instead of exercising the full resolution state machine
16
+ // (which is covered by useAgentSetup's own tests).
17
+ const mockAgentSetup = {
18
+ state: { status: "idle" } as Record<string, unknown>,
19
+ resolveAgent: vi.fn(),
20
+ resolveToInstance: vi.fn(),
21
+ submitEnvVars: vi.fn(),
22
+ reset: vi.fn(),
23
+ };
24
+ vi.mock("../../agent/useAgentSetup", () => ({
25
+ useAgentSetup: () => mockAgentSetup,
26
+ }));
27
+
28
+ import { SessionComposer } from "../SessionComposer";
29
+
30
+ // Base UI's Popover positioner observes its anchor; happy-dom lacks
31
+ // ResizeObserver, so provide a no-op shim.
32
+ beforeAll(() => {
33
+ if (!("ResizeObserver" in globalThis)) {
34
+ (globalThis as unknown as { ResizeObserver: unknown }).ResizeObserver =
35
+ class {
36
+ observe() {}
37
+ unobserve() {}
38
+ disconnect() {}
39
+ };
40
+ }
41
+ });
42
+
43
+ function createMinimalStigmerMock(): Stigmer {
44
+ return {
45
+ agentExecution: { uploadAttachment: vi.fn() },
46
+ environment: { getPersonal: vi.fn().mockResolvedValue(null) },
47
+ baseUrl: "http://localhost:8080",
48
+ getAuthCredential: vi.fn().mockResolvedValue("test-token"),
49
+ config: {
50
+ baseUrl: "http://localhost:8080",
51
+ getAccessToken: vi.fn().mockResolvedValue(""),
52
+ },
53
+ } as unknown as Stigmer;
54
+ }
55
+
56
+ function createWrapper(client: Stigmer) {
57
+ return function Wrapper({ children }: { children: ReactNode }) {
58
+ return (
59
+ <StigmerContext.Provider value={client}>
60
+ <ModelRegistryContext.Provider
61
+ value={{ models: [], isLoading: false, error: null, refetch: vi.fn() }}
62
+ >
63
+ {children}
64
+ </ModelRegistryContext.Provider>
65
+ </StigmerContext.Provider>
66
+ );
67
+ };
68
+ }
69
+
70
+ function renderComposer(
71
+ props?: Partial<React.ComponentProps<typeof SessionComposer>>,
72
+ ) {
73
+ const client = createMinimalStigmerMock();
74
+ return render(
75
+ <SessionComposer
76
+ onSubmit={vi.fn()}
77
+ org="acme"
78
+ agentRef={null}
79
+ onAgentRefChange={vi.fn()}
80
+ onSkillRefsChange={vi.fn()}
81
+ skillRefs={[]}
82
+ {...props}
83
+ />,
84
+ { wrapper: createWrapper(client) },
85
+ );
86
+ }
87
+
88
+ function openConfigureMenu() {
89
+ fireEvent.click(
90
+ screen.getByRole("button", { name: "Configure agent, tools, and skills" }),
91
+ );
92
+ }
93
+
94
+ beforeEach(() => {
95
+ mockAgentSetup.state = { status: "idle" };
96
+ });
97
+
98
+ afterEach(cleanup);
99
+
100
+ describe("SessionComposer — lockAgent", () => {
101
+ it("shows the Agent entry in the Configure menu by default", () => {
102
+ renderComposer();
103
+ openConfigureMenu();
104
+
105
+ expect(screen.getByRole("menuitem", { name: /Agent/ })).toBeTruthy();
106
+ });
107
+
108
+ it("hides the Agent entry when locked, leaving other entries intact", () => {
109
+ renderComposer({
110
+ lockAgent: true,
111
+ agentRef: { org: "acme", slug: "support-bot" },
112
+ });
113
+ openConfigureMenu();
114
+
115
+ expect(screen.queryByRole("menuitem", { name: /Agent/ })).toBeNull();
116
+ expect(screen.getByRole("menuitem", { name: /Skills/ })).toBeTruthy();
117
+ });
118
+
119
+ it("keeps the Agent entry reachable while a locked agent needs env vars", () => {
120
+ // A pinned agent that requires credentials: resolution is pending and
121
+ // the env form lives in the Configure > Agent panel — lock ≠ unwire.
122
+ mockAgentSetup.state = {
123
+ status: "needsEnvVars",
124
+ agentName: "Support Bot",
125
+ agentRef: { org: "acme", slug: "support-bot" },
126
+ missingVariables: [{ key: "API_KEY", isSecret: true }],
127
+ error: null,
128
+ };
129
+ renderComposer({ lockAgent: true });
130
+
131
+ // The composer surfaces the pending setup both as a warning banner...
132
+ expect(screen.getByText("Agent needs configuration before use")).toBeTruthy();
133
+
134
+ // ...and as a (warning-marked) Configure menu entry, despite the lock.
135
+ openConfigureMenu();
136
+ expect(screen.getByRole("menuitem", { name: /Agent/ })).toBeTruthy();
137
+ });
138
+
139
+ it("removes the Agent entry once the locked agent has resolved", () => {
140
+ mockAgentSetup.state = { status: "idle" };
141
+ renderComposer({
142
+ lockAgent: true,
143
+ agentRef: { org: "acme", slug: "support-bot" },
144
+ });
145
+
146
+ expect(screen.queryByText("Agent needs configuration before use")).toBeNull();
147
+ openConfigureMenu();
148
+ expect(screen.queryByRole("menuitem", { name: /Agent/ })).toBeNull();
149
+ });
150
+ });
package/src/index.ts CHANGED
@@ -150,6 +150,8 @@ export type {
150
150
  SearchResultGroup,
151
151
  SessionViewerProps,
152
152
  NewSessionViewerProps,
153
+ RuntimeEnvProvider,
154
+ SessionAudience,
153
155
  SessionInspectorProps,
154
156
  SessionInspectorTabId,
155
157
  UseSessionInspectorOptions,
@@ -853,7 +855,11 @@ export {
853
855
  useExportResource,
854
856
  useImportResource,
855
857
  ImportResourceDialog,
856
- VisibilityToggle,
858
+ VisibilitySelector,
859
+ VisibilityBadge,
860
+ blueprintVisibilityLevels,
861
+ INSTANCE_VISIBILITY_LEVELS,
862
+ visibilityLabel,
857
863
  useUpdateVisibility,
858
864
  } from "./library";
859
865
  export type {
@@ -873,7 +879,9 @@ export type {
873
879
  ImportPreview,
874
880
  UseImportResourceReturn,
875
881
  ImportResourceDialogProps,
876
- VisibilityToggleProps,
882
+ VisibilitySelectorProps,
883
+ VisibilityLevelOption,
884
+ BlueprintVisibilityLevelsContext,
877
885
  VisibilityResourceKind,
878
886
  UseUpdateVisibilityReturn,
879
887
  } from "./library";