@stigmer/react 3.1.7 → 3.1.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.
Files changed (206) hide show
  1. package/agent/AgentDetailView.d.ts +9 -1
  2. package/agent/AgentDetailView.d.ts.map +1 -1
  3. package/agent/AgentDetailView.js +15 -4
  4. package/agent/AgentDetailView.js.map +1 -1
  5. package/environment/EnvironmentListPanel.d.ts.map +1 -1
  6. package/environment/EnvironmentListPanel.js +11 -3
  7. package/environment/EnvironmentListPanel.js.map +1 -1
  8. package/environment/EnvironmentPicker.d.ts +17 -1
  9. package/environment/EnvironmentPicker.d.ts.map +1 -1
  10. package/environment/EnvironmentPicker.js +3 -2
  11. package/environment/EnvironmentPicker.js.map +1 -1
  12. package/environment/EnvironmentVariableEditor.d.ts.map +1 -1
  13. package/environment/EnvironmentVariableEditor.js +9 -3
  14. package/environment/EnvironmentVariableEditor.js.map +1 -1
  15. package/environment/index.d.ts +1 -0
  16. package/environment/index.d.ts.map +1 -1
  17. package/environment/index.js +1 -0
  18. package/environment/index.js.map +1 -1
  19. package/environment/shareRestriction.d.ts +13 -0
  20. package/environment/shareRestriction.d.ts.map +1 -0
  21. package/environment/shareRestriction.js +15 -0
  22. package/environment/shareRestriction.js.map +1 -0
  23. package/execution/ToolCallItem.d.ts.map +1 -1
  24. package/execution/ToolCallItem.js +12 -0
  25. package/execution/ToolCallItem.js.map +1 -1
  26. package/execution/ToolRunGroup.js +4 -0
  27. package/execution/ToolRunGroup.js.map +1 -1
  28. package/execution/WriteBackCard.d.ts +14 -5
  29. package/execution/WriteBackCard.d.ts.map +1 -1
  30. package/execution/WriteBackCard.js +103 -32
  31. package/execution/WriteBackCard.js.map +1 -1
  32. package/execution/WriteBacksWidget.d.ts +1 -1
  33. package/execution/WriteBacksWidget.js +2 -2
  34. package/execution/WriteBacksWidget.js.map +1 -1
  35. package/execution/index.d.ts +2 -0
  36. package/execution/index.d.ts.map +1 -1
  37. package/execution/index.js +1 -0
  38. package/execution/index.js.map +1 -1
  39. package/execution/write-back-utils.d.ts +57 -0
  40. package/execution/write-back-utils.d.ts.map +1 -0
  41. package/execution/write-back-utils.js +81 -0
  42. package/execution/write-back-utils.js.map +1 -0
  43. package/index.d.ts +6 -2
  44. package/index.d.ts.map +1 -1
  45. package/index.js +6 -1
  46. package/index.js.map +1 -1
  47. package/internal/dev/dom-counter.d.ts.map +1 -1
  48. package/internal/dev/dom-counter.js +2 -2
  49. package/internal/dev/dom-counter.js.map +1 -1
  50. package/internal/dev/enabled.d.ts +7 -0
  51. package/internal/dev/enabled.d.ts.map +1 -0
  52. package/internal/dev/enabled.js +38 -0
  53. package/internal/dev/enabled.js.map +1 -0
  54. package/internal/dev/profiler-wrapper.d.ts +3 -3
  55. package/internal/dev/profiler-wrapper.d.ts.map +1 -1
  56. package/internal/dev/profiler-wrapper.js +5 -5
  57. package/internal/dev/profiler-wrapper.js.map +1 -1
  58. package/internal/dev/use-key-stability.d.ts.map +1 -1
  59. package/internal/dev/use-key-stability.js +2 -2
  60. package/internal/dev/use-key-stability.js.map +1 -1
  61. package/internal/dev/use-render-tracer.d.ts +2 -2
  62. package/internal/dev/use-render-tracer.d.ts.map +1 -1
  63. package/internal/dev/use-render-tracer.js +4 -4
  64. package/internal/dev/use-render-tracer.js.map +1 -1
  65. package/internal/dev/use-stream-rate.d.ts +2 -1
  66. package/internal/dev/use-stream-rate.d.ts.map +1 -1
  67. package/internal/dev/use-stream-rate.js +4 -3
  68. package/internal/dev/use-stream-rate.js.map +1 -1
  69. package/library/ResourceVisibilityControl.d.ts +3 -0
  70. package/library/ResourceVisibilityControl.d.ts.map +1 -1
  71. package/library/ResourceVisibilityControl.js +22 -8
  72. package/library/ResourceVisibilityControl.js.map +1 -1
  73. package/library/useUpdateVisibility.d.ts +5 -3
  74. package/library/useUpdateVisibility.d.ts.map +1 -1
  75. package/library/useUpdateVisibility.js +7 -2
  76. package/library/useUpdateVisibility.js.map +1 -1
  77. package/library/visibilityLevels.d.ts +17 -0
  78. package/library/visibilityLevels.d.ts.map +1 -1
  79. package/library/visibilityLevels.js +32 -0
  80. package/library/visibilityLevels.js.map +1 -1
  81. package/package.json +4 -4
  82. package/session/NewSessionViewer.d.ts +11 -1
  83. package/session/NewSessionViewer.d.ts.map +1 -1
  84. package/session/NewSessionViewer.js +28 -8
  85. package/session/NewSessionViewer.js.map +1 -1
  86. package/session/SessionViewer.d.ts +9 -2
  87. package/session/SessionViewer.d.ts.map +1 -1
  88. package/session/SessionViewer.js +26 -12
  89. package/session/SessionViewer.js.map +1 -1
  90. package/session/audience.d.ts +12 -4
  91. package/session/audience.d.ts.map +1 -1
  92. package/session/facets/ChangesTab.d.ts.map +1 -1
  93. package/session/facets/ChangesTab.js +3 -1
  94. package/session/facets/ChangesTab.js.map +1 -1
  95. package/session/useNewSessionFlow.d.ts +12 -0
  96. package/session/useNewSessionFlow.d.ts.map +1 -1
  97. package/session/useNewSessionFlow.js +13 -1
  98. package/session/useNewSessionFlow.js.map +1 -1
  99. package/session/useSessionPageFlow.d.ts +13 -0
  100. package/session/useSessionPageFlow.d.ts.map +1 -1
  101. package/session/useSessionPageFlow.js +7 -2
  102. package/session/useSessionPageFlow.js.map +1 -1
  103. package/sharing/ShareAgentDialog.d.ts +57 -0
  104. package/sharing/ShareAgentDialog.d.ts.map +1 -0
  105. package/sharing/ShareAgentDialog.js +478 -0
  106. package/sharing/ShareAgentDialog.js.map +1 -0
  107. package/sharing/SharedAgentChat.d.ts +84 -0
  108. package/sharing/SharedAgentChat.d.ts.map +1 -0
  109. package/sharing/SharedAgentChat.js +80 -0
  110. package/sharing/SharedAgentChat.js.map +1 -0
  111. package/sharing/index.d.ts +18 -0
  112. package/sharing/index.d.ts.map +1 -0
  113. package/sharing/index.js +12 -0
  114. package/sharing/index.js.map +1 -0
  115. package/sharing/useAgentShare.d.ts +43 -0
  116. package/sharing/useAgentShare.d.ts.map +1 -0
  117. package/sharing/useAgentShare.js +54 -0
  118. package/sharing/useAgentShare.js.map +1 -0
  119. package/sharing/useRotateShareLink.d.ts +45 -0
  120. package/sharing/useRotateShareLink.d.ts.map +1 -0
  121. package/sharing/useRotateShareLink.js +58 -0
  122. package/sharing/useRotateShareLink.js.map +1 -0
  123. package/sharing/useSaveAgentShare.d.ts +105 -0
  124. package/sharing/useSaveAgentShare.d.ts.map +1 -0
  125. package/sharing/useSaveAgentShare.js +97 -0
  126. package/sharing/useSaveAgentShare.js.map +1 -0
  127. package/sharing/useShareAgent.d.ts +69 -0
  128. package/sharing/useShareAgent.d.ts.map +1 -0
  129. package/sharing/useShareAgent.js +42 -0
  130. package/sharing/useShareAgent.js.map +1 -0
  131. package/sharing/useShareToolReadiness.d.ts +52 -0
  132. package/sharing/useShareToolReadiness.d.ts.map +1 -0
  133. package/sharing/useShareToolReadiness.js +89 -0
  134. package/sharing/useShareToolReadiness.js.map +1 -0
  135. package/sharing/useSharedAgentProfile.d.ts +85 -0
  136. package/sharing/useSharedAgentProfile.d.ts.map +1 -0
  137. package/sharing/useSharedAgentProfile.js +73 -0
  138. package/sharing/useSharedAgentProfile.js.map +1 -0
  139. package/src/agent/AgentDetailView.tsx +28 -3
  140. package/src/environment/EnvironmentListPanel.tsx +47 -18
  141. package/src/environment/EnvironmentPicker.tsx +23 -2
  142. package/src/environment/EnvironmentVariableEditor.tsx +27 -17
  143. package/src/environment/__tests__/shareRestriction.test.ts +35 -0
  144. package/src/environment/index.ts +5 -0
  145. package/src/environment/shareRestriction.ts +22 -0
  146. package/src/execution/ToolCallItem.tsx +19 -1
  147. package/src/execution/ToolRunGroup.tsx +4 -0
  148. package/src/execution/WriteBackCard.tsx +285 -88
  149. package/src/execution/WriteBacksWidget.tsx +5 -5
  150. package/src/execution/__tests__/ToolCallItem.test.tsx +51 -0
  151. package/src/execution/__tests__/ToolRunGroup.test.tsx +22 -0
  152. package/src/execution/__tests__/WriteBackCard.test.tsx +64 -10
  153. package/src/execution/__tests__/write-back-utils.test.ts +135 -0
  154. package/src/execution/index.ts +7 -0
  155. package/src/execution/write-back-utils.ts +107 -0
  156. package/src/index.ts +38 -0
  157. package/src/internal/dev/__tests__/use-key-stability.test.ts +4 -0
  158. package/src/internal/dev/__tests__/use-render-tracer.test.ts +4 -0
  159. package/src/internal/dev/dom-counter.ts +2 -3
  160. package/src/internal/dev/enabled.ts +39 -0
  161. package/src/internal/dev/profiler-wrapper.tsx +5 -6
  162. package/src/internal/dev/use-key-stability.ts +2 -3
  163. package/src/internal/dev/use-render-tracer.ts +4 -5
  164. package/src/internal/dev/use-stream-rate.ts +4 -4
  165. package/src/library/ResourceVisibilityControl.tsx +23 -7
  166. package/src/library/__tests__/visibilityLevels.test.ts +33 -0
  167. package/src/library/useUpdateVisibility.ts +9 -3
  168. package/src/library/visibilityLevels.ts +36 -0
  169. package/src/session/NewSessionViewer.tsx +67 -31
  170. package/src/session/SessionViewer.tsx +67 -36
  171. package/src/session/__tests__/audienceWiring.test.tsx +99 -0
  172. package/src/session/__tests__/useNewSessionFlow.test.tsx +75 -1
  173. package/src/session/__tests__/useSessionPageFlow.guest.test.tsx +112 -0
  174. package/src/session/audience.ts +12 -4
  175. package/src/session/facets/ChangesTab.tsx +6 -4
  176. package/src/session/useNewSessionFlow.ts +26 -1
  177. package/src/session/useSessionPageFlow.ts +24 -2
  178. package/src/sharing/ShareAgentDialog.tsx +1489 -0
  179. package/src/sharing/SharedAgentChat.tsx +283 -0
  180. package/src/sharing/__tests__/ShareAgentDialog.test.tsx +926 -0
  181. package/src/sharing/__tests__/SharedAgentChat.test.tsx +222 -0
  182. package/src/sharing/__tests__/useAgentShare.test.tsx +149 -0
  183. package/src/sharing/__tests__/useRotateShareLink.test.tsx +96 -0
  184. package/src/sharing/__tests__/useSaveAgentShare.test.tsx +241 -0
  185. package/src/sharing/__tests__/useShareAgent.test.tsx +131 -0
  186. package/src/sharing/__tests__/useShareToolReadiness.test.tsx +219 -0
  187. package/src/sharing/__tests__/useSharedAgentProfile.test.tsx +201 -0
  188. package/src/sharing/index.ts +32 -0
  189. package/src/sharing/useAgentShare.ts +91 -0
  190. package/src/sharing/useRotateShareLink.ts +81 -0
  191. package/src/sharing/useSaveAgentShare.ts +186 -0
  192. package/src/sharing/useShareAgent.tsx +107 -0
  193. package/src/sharing/useShareToolReadiness.ts +131 -0
  194. package/src/sharing/useSharedAgentProfile.ts +132 -0
  195. package/src/switch/Switch.tsx +97 -0
  196. package/src/switch/__tests__/Switch.test.tsx +107 -0
  197. package/src/switch/index.ts +2 -0
  198. package/styles.css +1 -1
  199. package/switch/Switch.d.ts +47 -0
  200. package/switch/Switch.d.ts.map +1 -0
  201. package/switch/Switch.js +41 -0
  202. package/switch/Switch.js.map +1 -0
  203. package/switch/index.d.ts +3 -0
  204. package/switch/index.d.ts.map +1 -0
  205. package/switch/index.js +2 -0
  206. package/switch/index.js.map +1 -0
@@ -0,0 +1,112 @@
1
+ import { describe, it, expect, vi, afterEach } from "vitest";
2
+ import { renderHook, act } from "@testing-library/react";
3
+
4
+ // ---------------------------------------------------------------------------
5
+ // Guest-audience gating for useSessionPageFlow.
6
+ //
7
+ // A guest token cannot read the org default agent or derive the session's
8
+ // agent (`agentInstance.get` → `agent.get` are FGA-denied — sharing writes
9
+ // no tuples). The flow must put both lookups into their `null` no-op mode
10
+ // and send follow-ups without an agent override, continuing on the
11
+ // session's server-bound instance.
12
+ // ---------------------------------------------------------------------------
13
+
14
+ const mockSendFollowUp = vi.fn();
15
+
16
+ const mockConv = {
17
+ session: { spec: { agentInstanceId: "inst_bound" } },
18
+ isLoading: false,
19
+ completedExecutions: [] as unknown[],
20
+ activeStreamExecution: null,
21
+ workspaceEntries: [] as unknown[],
22
+ submitApproval: vi.fn(),
23
+ sendFollowUp: mockSendFollowUp,
24
+ };
25
+ vi.mock("../useSessionConversation", () => ({
26
+ useSessionConversation: () => mockConv,
27
+ }));
28
+
29
+ vi.mock("../../hooks", () => ({
30
+ useStigmer: () => ({ agent: { getByReference: vi.fn() } }),
31
+ }));
32
+
33
+ const useDefaultAgentSpy = vi.fn((_org: string | null) => ({
34
+ agent: null,
35
+ isLoading: false,
36
+ error: null,
37
+ }));
38
+ vi.mock("../../agent", () => ({
39
+ useDefaultAgent: (org: string | null) => useDefaultAgentSpy(org),
40
+ }));
41
+
42
+ const mockWorkspace = {
43
+ entries: [],
44
+ hasEntries: false,
45
+ toInput: vi.fn().mockReturnValue([]),
46
+ addGitRepo: vi.fn(),
47
+ addLocalPath: vi.fn(),
48
+ removeEntry: vi.fn(),
49
+ clear: vi.fn(),
50
+ };
51
+ vi.mock("../../workspace", () => ({
52
+ useWorkspaceEntries: () => mockWorkspace,
53
+ }));
54
+
55
+ const mockSessionVariables = {
56
+ variables: [],
57
+ isEmpty: true,
58
+ clear: vi.fn(),
59
+ };
60
+ vi.mock("../../execution/useSessionVariables", () => ({
61
+ useSessionVariables: () => mockSessionVariables,
62
+ }));
63
+
64
+ vi.mock("../usePersistedModel", () => ({
65
+ usePersistedModel: () => ["model-x", vi.fn()] as const,
66
+ }));
67
+
68
+ const useAgentRefFromSessionSpy = vi.fn((_instanceId: string | null) => ({
69
+ agentRef: null,
70
+ }));
71
+ vi.mock("../useAgentRefFromSession", () => ({
72
+ useAgentRefFromSession: (instanceId: string | null) =>
73
+ useAgentRefFromSessionSpy(instanceId),
74
+ }));
75
+
76
+ import { useSessionPageFlow } from "../useSessionPageFlow";
77
+
78
+ const OPTS = { sessionId: "ses_1", org: "acme" };
79
+
80
+ describe("useSessionPageFlow — guest audience", () => {
81
+ afterEach(() => {
82
+ vi.clearAllMocks();
83
+ });
84
+
85
+ it("disables the session→agent derivation and default-agent lookup", () => {
86
+ renderHook(() => useSessionPageFlow({ ...OPTS, audience: "guest" }));
87
+
88
+ expect(useAgentRefFromSessionSpy).toHaveBeenCalledWith(null);
89
+ expect(useDefaultAgentSpy).toHaveBeenCalledWith(null);
90
+ });
91
+
92
+ it("keeps both lookups active for other audiences", () => {
93
+ renderHook(() => useSessionPageFlow(OPTS));
94
+
95
+ expect(useAgentRefFromSessionSpy).toHaveBeenCalledWith("inst_bound");
96
+ expect(useDefaultAgentSpy).toHaveBeenCalledWith("acme");
97
+ });
98
+
99
+ it("sends follow-ups without an agent override", async () => {
100
+ const { result } = renderHook(() =>
101
+ useSessionPageFlow({ ...OPTS, audience: "guest" }),
102
+ );
103
+
104
+ await act(async () => {
105
+ await result.current.handleSubmit("follow up");
106
+ });
107
+
108
+ expect(mockSendFollowUp).toHaveBeenCalledTimes(1);
109
+ // No override: the execution continues on the session's bound instance.
110
+ expect(mockSendFollowUp.mock.calls[0][1].agentInstanceId).toBeUndefined();
111
+ });
112
+ });
@@ -12,9 +12,17 @@
12
12
  * Agent/Plan mode, and attaches workspaces, but never reconfigures
13
13
  * the agent. The organisms lock the agent and hide the integrator
14
14
  * pickers, in both the composer and the inspector's Setup tab.
15
+ * - `"guest"` — an anonymous visitor of a shared agent's public page or
16
+ * embed, authenticated by a guest token. Pure chat: everything
17
+ * `"endUser"` hides plus the model, harness, and Agent/Plan pickers,
18
+ * attachments, the workspace picker, and the session panel. Guest is
19
+ * behavioral, not just cosmetic — the organisms also skip the
20
+ * org-level reads a guest principal cannot make (default-agent
21
+ * resolution, session→agent derivation, personal environments) and
22
+ * never fall back to the org's default agent.
15
23
  *
16
- * A preset rather than individual flags: "end user" is a product intent,
17
- * and keeping it in one place lets the SDK evolve what that presentation
18
- * means without breaking embedders.
24
+ * A preset rather than individual flags: each audience is a product
25
+ * intent, and keeping it in one place lets the SDK evolve what that
26
+ * presentation means without breaking embedders.
19
27
  */
20
- export type SessionAudience = "integrator" | "endUser";
28
+ export type SessionAudience = "integrator" | "endUser" | "guest";
@@ -45,14 +45,16 @@ export function ChangesTab({
45
45
  const { writeBacks, hasWriteBacks } = useSessionWriteBacks(executions);
46
46
 
47
47
  if (hasWriteBacks) {
48
+ // Dense row groups matching the Artifacts facet's list — gap separates
49
+ // entries only in multi-repo sessions (single-entry lists stay seamless).
48
50
  return (
49
- <div role="list" className="space-y-2">
51
+ <ul role="list" className="flex flex-col gap-3">
50
52
  {writeBacks.map((entry) => (
51
- <div key={entry.writeBack.workspaceEntryName} role="listitem">
53
+ <li key={entry.writeBack.workspaceEntryName}>
52
54
  <WriteBackCard writeBack={entry.writeBack} />
53
- </div>
55
+ </li>
54
56
  ))}
55
- </div>
57
+ </ul>
56
58
  );
57
59
  }
58
60
 
@@ -17,6 +17,7 @@ import type { ExecutionTargetOption } from "./execution-target.js";
17
17
  import { useExecutionTarget } from "../execution-target-context.js";
18
18
  import { useRunnerAdapter } from "../runner-adapter.js";
19
19
  import { resolveExecutionRuntimeEnv, type RuntimeEnvProvider } from "./runtime-env.js";
20
+ import type { SessionAudience } from "./audience.js";
20
21
 
21
22
  const DEFAULT_AGENT_TIMEOUT_MS = 10_000;
22
23
 
@@ -80,6 +81,17 @@ export interface UseNewSessionFlowOptions {
80
81
  * @default DEFAULT_HARNESS ("native")
81
82
  */
82
83
  readonly defaultHarness?: HarnessOption;
84
+ /**
85
+ * Who this flow serves. `"guest"` adapts the orchestration to the
86
+ * guest principal's permission model: the org default-agent lookup
87
+ * (which a guest token cannot read) is skipped, and submission
88
+ * requires an explicit agent resolution instead of falling back to
89
+ * the org's default agent — a shared-agent page must never run
90
+ * anything but the pinned shared agent. See {@link SessionAudience}.
91
+ *
92
+ * @default "integrator"
93
+ */
94
+ readonly audience?: SessionAudience;
83
95
  }
84
96
 
85
97
  /** Return value of {@link useNewSessionFlow}. */
@@ -184,6 +196,7 @@ export function useNewSessionFlow(
184
196
  options: UseNewSessionFlowOptions,
185
197
  ): UseNewSessionFlowReturn {
186
198
  const { org, onSessionCreated, onError, getRuntimeEnv, defaultHarness } = options;
199
+ const isGuest = options.audience === "guest";
187
200
  const contextTarget = useExecutionTarget();
188
201
  const executionTarget = options.executionTarget ?? contextTarget;
189
202
  const adapter = useRunnerAdapter();
@@ -200,12 +213,15 @@ export function useNewSessionFlow(
200
213
  const { getModel, isLoading: isModelsLoading } = useModelRegistry({ harness });
201
214
  const { create: createSession } = useCreateSession();
202
215
  const { create: createExecution } = useCreateAgentExecution();
216
+ // Guests cannot read the org default agent (and must never run it) —
217
+ // `null` puts the hook in its stable no-op mode, and the submit path
218
+ // below fails closed instead of falling back.
203
219
  const {
204
220
  agent: defaultAgent,
205
221
  isLoading: isDefaultAgentLoading,
206
222
  error: defaultAgentError,
207
223
  waitForResolution: waitForDefaultAgent,
208
- } = useDefaultAgent(org);
224
+ } = useDefaultAgent(isGuest ? null : org);
209
225
  const workspace = useWorkspaceEntries();
210
226
  const sessionVariables = useSessionVariables();
211
227
 
@@ -315,6 +331,14 @@ export function useNewSessionFlow(
315
331
  agentRef,
316
332
  }));
317
333
  }
334
+ } else if (isGuest) {
335
+ // Fail closed: a guest session is only ever created against the
336
+ // pinned shared agent's resolution. Reaching here means the pin
337
+ // has not been applied yet (or was cleared) — never substitute
338
+ // the org default agent for an anonymous visitor.
339
+ throw new Error(
340
+ "This agent is still loading. Please try again in a moment.",
341
+ );
318
342
  } else {
319
343
  let resolvedInstanceId = defaultAgent?.status?.defaultInstanceId;
320
344
  if (!resolvedInstanceId) {
@@ -375,6 +399,7 @@ export function useNewSessionFlow(
375
399
  [
376
400
  isSubmitting,
377
401
  org,
402
+ isGuest,
378
403
  harness,
379
404
  executionTarget,
380
405
  adapter,
@@ -18,6 +18,7 @@ import { resolveExecutionRuntimeEnv, type RuntimeEnvProvider } from "./runtime-e
18
18
  import { useAgentRefFromSession } from "./useAgentRefFromSession.js";
19
19
  import { usePersistedModel, type UsePersistedModelReturn } from "./usePersistedModel.js";
20
20
  import { specMcpUsagesToInput, specSkillRefsToInput } from "./session-spec-converters.js";
21
+ import type { SessionAudience } from "./audience.js";
21
22
 
22
23
  /**
23
24
  * Well-known Daytona sandbox workspace root. Used as the SDK safety-net
@@ -43,6 +44,18 @@ export interface UseSessionPageFlowOptions {
43
44
  * {@link RuntimeEnvProvider}.
44
45
  */
45
46
  readonly getRuntimeEnv?: RuntimeEnvProvider;
47
+ /**
48
+ * Who this flow serves. `"guest"` adapts the orchestration to the
49
+ * guest principal's permission model: the session→agent derivation
50
+ * (`agentInstance.get` → `agent.get`) and the org default-agent
51
+ * lookup — reads a guest token cannot make — are skipped. Follow-ups
52
+ * then carry no agent override and simply continue on the session's
53
+ * bound instance, which is exactly right for a shared-agent page.
54
+ * See {@link SessionAudience}.
55
+ *
56
+ * @default "integrator"
57
+ */
58
+ readonly audience?: SessionAudience;
46
59
  }
47
60
 
48
61
  /** Return value of {@link useSessionPageFlow}. */
@@ -226,6 +239,7 @@ export function useSessionPageFlow(
226
239
  options: UseSessionPageFlowOptions,
227
240
  ): UseSessionPageFlowReturn {
228
241
  const { sessionId, org, getRuntimeEnv } = options;
242
+ const isGuest = options.audience === "guest";
229
243
 
230
244
  const stigmer = useStigmer();
231
245
  const conv = useSessionConversation(sessionId, org);
@@ -291,9 +305,17 @@ export function useSessionPageFlow(
291
305
  // Agent — derive from session, allow mid-session changes
292
306
  // -------------------------------------------------------------------------
293
307
 
308
+ // Guests skip agent derivation entirely (`null` = the hooks' stable
309
+ // no-op): the reads are FGA-denied for a guest token, and a guest
310
+ // never overrides the session's agent — `resolution` stays null, so
311
+ // follow-ups continue on the bound instance without an override.
294
312
  const sessionInstanceId = conv.session?.spec?.agentInstanceId ?? null;
295
- const { agentRef: derivedAgentRef } = useAgentRefFromSession(sessionInstanceId);
296
- const { agent: defaultAgent, isLoading: isDefaultAgentLoading } = useDefaultAgent(org);
313
+ const { agentRef: derivedAgentRef } = useAgentRefFromSession(
314
+ isGuest ? null : sessionInstanceId,
315
+ );
316
+ const { agent: defaultAgent, isLoading: isDefaultAgentLoading } = useDefaultAgent(
317
+ isGuest ? null : org,
318
+ );
297
319
 
298
320
  const [agentRef, setAgentRef] = useState<ResourceRef | null>(null);
299
321
  const [resolution, setResolution] = useState<AgentResolution | null>(null);