@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.
- package/agent/AgentDetailView.d.ts +9 -1
- package/agent/AgentDetailView.d.ts.map +1 -1
- package/agent/AgentDetailView.js +15 -4
- package/agent/AgentDetailView.js.map +1 -1
- package/environment/EnvironmentListPanel.d.ts.map +1 -1
- package/environment/EnvironmentListPanel.js +11 -3
- package/environment/EnvironmentListPanel.js.map +1 -1
- package/environment/EnvironmentPicker.d.ts +17 -1
- package/environment/EnvironmentPicker.d.ts.map +1 -1
- package/environment/EnvironmentPicker.js +3 -2
- package/environment/EnvironmentPicker.js.map +1 -1
- package/environment/EnvironmentVariableEditor.d.ts.map +1 -1
- package/environment/EnvironmentVariableEditor.js +9 -3
- package/environment/EnvironmentVariableEditor.js.map +1 -1
- package/environment/index.d.ts +1 -0
- package/environment/index.d.ts.map +1 -1
- package/environment/index.js +1 -0
- package/environment/index.js.map +1 -1
- package/environment/shareRestriction.d.ts +13 -0
- package/environment/shareRestriction.d.ts.map +1 -0
- package/environment/shareRestriction.js +15 -0
- package/environment/shareRestriction.js.map +1 -0
- package/execution/ToolCallItem.d.ts.map +1 -1
- package/execution/ToolCallItem.js +12 -0
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/ToolRunGroup.js +4 -0
- package/execution/ToolRunGroup.js.map +1 -1
- package/execution/WriteBackCard.d.ts +14 -5
- package/execution/WriteBackCard.d.ts.map +1 -1
- package/execution/WriteBackCard.js +103 -32
- package/execution/WriteBackCard.js.map +1 -1
- package/execution/WriteBacksWidget.d.ts +1 -1
- package/execution/WriteBacksWidget.js +2 -2
- package/execution/WriteBacksWidget.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/write-back-utils.d.ts +57 -0
- package/execution/write-back-utils.d.ts.map +1 -0
- package/execution/write-back-utils.js +81 -0
- package/execution/write-back-utils.js.map +1 -0
- package/index.d.ts +6 -2
- package/index.d.ts.map +1 -1
- package/index.js +6 -1
- package/index.js.map +1 -1
- package/internal/dev/dom-counter.d.ts.map +1 -1
- package/internal/dev/dom-counter.js +2 -2
- package/internal/dev/dom-counter.js.map +1 -1
- package/internal/dev/enabled.d.ts +7 -0
- package/internal/dev/enabled.d.ts.map +1 -0
- package/internal/dev/enabled.js +38 -0
- package/internal/dev/enabled.js.map +1 -0
- package/internal/dev/profiler-wrapper.d.ts +3 -3
- package/internal/dev/profiler-wrapper.d.ts.map +1 -1
- package/internal/dev/profiler-wrapper.js +5 -5
- package/internal/dev/profiler-wrapper.js.map +1 -1
- package/internal/dev/use-key-stability.d.ts.map +1 -1
- package/internal/dev/use-key-stability.js +2 -2
- package/internal/dev/use-key-stability.js.map +1 -1
- package/internal/dev/use-render-tracer.d.ts +2 -2
- package/internal/dev/use-render-tracer.d.ts.map +1 -1
- package/internal/dev/use-render-tracer.js +4 -4
- package/internal/dev/use-render-tracer.js.map +1 -1
- package/internal/dev/use-stream-rate.d.ts +2 -1
- package/internal/dev/use-stream-rate.d.ts.map +1 -1
- package/internal/dev/use-stream-rate.js +4 -3
- package/internal/dev/use-stream-rate.js.map +1 -1
- package/library/ResourceVisibilityControl.d.ts +3 -0
- package/library/ResourceVisibilityControl.d.ts.map +1 -1
- package/library/ResourceVisibilityControl.js +22 -8
- package/library/ResourceVisibilityControl.js.map +1 -1
- package/library/useUpdateVisibility.d.ts +5 -3
- package/library/useUpdateVisibility.d.ts.map +1 -1
- package/library/useUpdateVisibility.js +7 -2
- package/library/useUpdateVisibility.js.map +1 -1
- package/library/visibilityLevels.d.ts +17 -0
- package/library/visibilityLevels.d.ts.map +1 -1
- package/library/visibilityLevels.js +32 -0
- package/library/visibilityLevels.js.map +1 -1
- package/package.json +4 -4
- package/session/NewSessionViewer.d.ts +11 -1
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +28 -8
- package/session/NewSessionViewer.js.map +1 -1
- package/session/SessionViewer.d.ts +9 -2
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +26 -12
- package/session/SessionViewer.js.map +1 -1
- package/session/audience.d.ts +12 -4
- package/session/audience.d.ts.map +1 -1
- package/session/facets/ChangesTab.d.ts.map +1 -1
- package/session/facets/ChangesTab.js +3 -1
- package/session/facets/ChangesTab.js.map +1 -1
- package/session/useNewSessionFlow.d.ts +12 -0
- package/session/useNewSessionFlow.d.ts.map +1 -1
- package/session/useNewSessionFlow.js +13 -1
- package/session/useNewSessionFlow.js.map +1 -1
- package/session/useSessionPageFlow.d.ts +13 -0
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +7 -2
- package/session/useSessionPageFlow.js.map +1 -1
- package/sharing/ShareAgentDialog.d.ts +57 -0
- package/sharing/ShareAgentDialog.d.ts.map +1 -0
- package/sharing/ShareAgentDialog.js +478 -0
- package/sharing/ShareAgentDialog.js.map +1 -0
- package/sharing/SharedAgentChat.d.ts +84 -0
- package/sharing/SharedAgentChat.d.ts.map +1 -0
- package/sharing/SharedAgentChat.js +80 -0
- package/sharing/SharedAgentChat.js.map +1 -0
- package/sharing/index.d.ts +18 -0
- package/sharing/index.d.ts.map +1 -0
- package/sharing/index.js +12 -0
- package/sharing/index.js.map +1 -0
- package/sharing/useAgentShare.d.ts +43 -0
- package/sharing/useAgentShare.d.ts.map +1 -0
- package/sharing/useAgentShare.js +54 -0
- package/sharing/useAgentShare.js.map +1 -0
- package/sharing/useRotateShareLink.d.ts +45 -0
- package/sharing/useRotateShareLink.d.ts.map +1 -0
- package/sharing/useRotateShareLink.js +58 -0
- package/sharing/useRotateShareLink.js.map +1 -0
- package/sharing/useSaveAgentShare.d.ts +105 -0
- package/sharing/useSaveAgentShare.d.ts.map +1 -0
- package/sharing/useSaveAgentShare.js +97 -0
- package/sharing/useSaveAgentShare.js.map +1 -0
- package/sharing/useShareAgent.d.ts +69 -0
- package/sharing/useShareAgent.d.ts.map +1 -0
- package/sharing/useShareAgent.js +42 -0
- package/sharing/useShareAgent.js.map +1 -0
- package/sharing/useShareToolReadiness.d.ts +52 -0
- package/sharing/useShareToolReadiness.d.ts.map +1 -0
- package/sharing/useShareToolReadiness.js +89 -0
- package/sharing/useShareToolReadiness.js.map +1 -0
- package/sharing/useSharedAgentProfile.d.ts +85 -0
- package/sharing/useSharedAgentProfile.d.ts.map +1 -0
- package/sharing/useSharedAgentProfile.js +73 -0
- package/sharing/useSharedAgentProfile.js.map +1 -0
- package/src/agent/AgentDetailView.tsx +28 -3
- package/src/environment/EnvironmentListPanel.tsx +47 -18
- package/src/environment/EnvironmentPicker.tsx +23 -2
- package/src/environment/EnvironmentVariableEditor.tsx +27 -17
- package/src/environment/__tests__/shareRestriction.test.ts +35 -0
- package/src/environment/index.ts +5 -0
- package/src/environment/shareRestriction.ts +22 -0
- package/src/execution/ToolCallItem.tsx +19 -1
- package/src/execution/ToolRunGroup.tsx +4 -0
- package/src/execution/WriteBackCard.tsx +285 -88
- package/src/execution/WriteBacksWidget.tsx +5 -5
- package/src/execution/__tests__/ToolCallItem.test.tsx +51 -0
- package/src/execution/__tests__/ToolRunGroup.test.tsx +22 -0
- package/src/execution/__tests__/WriteBackCard.test.tsx +64 -10
- package/src/execution/__tests__/write-back-utils.test.ts +135 -0
- package/src/execution/index.ts +7 -0
- package/src/execution/write-back-utils.ts +107 -0
- package/src/index.ts +38 -0
- package/src/internal/dev/__tests__/use-key-stability.test.ts +4 -0
- package/src/internal/dev/__tests__/use-render-tracer.test.ts +4 -0
- package/src/internal/dev/dom-counter.ts +2 -3
- package/src/internal/dev/enabled.ts +39 -0
- package/src/internal/dev/profiler-wrapper.tsx +5 -6
- package/src/internal/dev/use-key-stability.ts +2 -3
- package/src/internal/dev/use-render-tracer.ts +4 -5
- package/src/internal/dev/use-stream-rate.ts +4 -4
- package/src/library/ResourceVisibilityControl.tsx +23 -7
- package/src/library/__tests__/visibilityLevels.test.ts +33 -0
- package/src/library/useUpdateVisibility.ts +9 -3
- package/src/library/visibilityLevels.ts +36 -0
- package/src/session/NewSessionViewer.tsx +67 -31
- package/src/session/SessionViewer.tsx +67 -36
- package/src/session/__tests__/audienceWiring.test.tsx +99 -0
- package/src/session/__tests__/useNewSessionFlow.test.tsx +75 -1
- package/src/session/__tests__/useSessionPageFlow.guest.test.tsx +112 -0
- package/src/session/audience.ts +12 -4
- package/src/session/facets/ChangesTab.tsx +6 -4
- package/src/session/useNewSessionFlow.ts +26 -1
- package/src/session/useSessionPageFlow.ts +24 -2
- package/src/sharing/ShareAgentDialog.tsx +1489 -0
- package/src/sharing/SharedAgentChat.tsx +283 -0
- package/src/sharing/__tests__/ShareAgentDialog.test.tsx +926 -0
- package/src/sharing/__tests__/SharedAgentChat.test.tsx +222 -0
- package/src/sharing/__tests__/useAgentShare.test.tsx +149 -0
- package/src/sharing/__tests__/useRotateShareLink.test.tsx +96 -0
- package/src/sharing/__tests__/useSaveAgentShare.test.tsx +241 -0
- package/src/sharing/__tests__/useShareAgent.test.tsx +131 -0
- package/src/sharing/__tests__/useShareToolReadiness.test.tsx +219 -0
- package/src/sharing/__tests__/useSharedAgentProfile.test.tsx +201 -0
- package/src/sharing/index.ts +32 -0
- package/src/sharing/useAgentShare.ts +91 -0
- package/src/sharing/useRotateShareLink.ts +81 -0
- package/src/sharing/useSaveAgentShare.ts +186 -0
- package/src/sharing/useShareAgent.tsx +107 -0
- package/src/sharing/useShareToolReadiness.ts +131 -0
- package/src/sharing/useSharedAgentProfile.ts +132 -0
- package/src/switch/Switch.tsx +97 -0
- package/src/switch/__tests__/Switch.test.tsx +107 -0
- package/src/switch/index.ts +2 -0
- package/styles.css +1 -1
- package/switch/Switch.d.ts +47 -0
- package/switch/Switch.d.ts.map +1 -0
- package/switch/Switch.js +41 -0
- package/switch/Switch.js.map +1 -0
- package/switch/index.d.ts +3 -0
- package/switch/index.d.ts.map +1 -0
- package/switch/index.js +2 -0
- package/switch/index.js.map +1 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
3
|
+
import type { DetailAction } from "../resource-detail/types.js";
|
|
4
|
+
/** Arguments for {@link useShareAgent}. */
|
|
5
|
+
export interface UseShareAgentArgs {
|
|
6
|
+
/**
|
|
7
|
+
* The agent whose sharing is managed, or `null` while it is still
|
|
8
|
+
* loading. When `null`, {@link UseShareAgentReturn.action} is `null`
|
|
9
|
+
* and the dialog renders nothing — safe to call before the resource
|
|
10
|
+
* is ready.
|
|
11
|
+
*/
|
|
12
|
+
readonly agent: Agent | null;
|
|
13
|
+
/**
|
|
14
|
+
* Builds the absolute public chat URL for the shared agent. The host
|
|
15
|
+
* application owns URL construction (its configured public origin may
|
|
16
|
+
* differ from the rendering origin — e.g. the desktop app). When
|
|
17
|
+
* omitted, the dialog falls back to the relative `/chat/<org>/<slug>`.
|
|
18
|
+
*/
|
|
19
|
+
readonly buildShareUrl?: (org: string, slug: string) => string;
|
|
20
|
+
/**
|
|
21
|
+
* Called after any sharing change is persisted. Hosts typically pass
|
|
22
|
+
* the agent data hook's `refetch`.
|
|
23
|
+
*/
|
|
24
|
+
readonly onSharingChanged?: () => void;
|
|
25
|
+
/** Menu-item label. @default "Share" */
|
|
26
|
+
readonly label?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Return value of {@link useShareAgent}. */
|
|
29
|
+
export interface UseShareAgentReturn {
|
|
30
|
+
/**
|
|
31
|
+
* A ready-to-spread {@link DetailAction} for a kebab/overflow menu, or
|
|
32
|
+
* `null` when the agent is unavailable or the user lacks `can_edit`.
|
|
33
|
+
* Lives in the `"sharing"` group, beside "Manage access".
|
|
34
|
+
*/
|
|
35
|
+
readonly action: DetailAction | null;
|
|
36
|
+
/** The {@link ShareAgentDialog} node — render it once in the host tree. */
|
|
37
|
+
readonly dialog: ReactNode;
|
|
38
|
+
/** Imperatively open the dialog. */
|
|
39
|
+
readonly open: () => void;
|
|
40
|
+
/** Whether the dialog is currently open. */
|
|
41
|
+
readonly isOpen: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Wires the Share dialog to a kebab/overflow menu — the same trigger
|
|
45
|
+
* shape as {@link useManageAccess}, its conceptual sibling: Manage access
|
|
46
|
+
* governs who can *read* the blueprint; Share governs who can *chat* with
|
|
47
|
+
* the running agent (billed to the owning org).
|
|
48
|
+
*
|
|
49
|
+
* Owns the open-state and the `can_edit` gate — the same permission the
|
|
50
|
+
* AgentShare create/apply handlers enforce on the referenced agent, so
|
|
51
|
+
* the action never appears to a user whose changes would be rejected.
|
|
52
|
+
* Returns a `null` action while the agent is loading or the user cannot
|
|
53
|
+
* edit, so the host can unconditionally fold `action` into its actions
|
|
54
|
+
* array.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```tsx
|
|
58
|
+
* const share = useShareAgent({
|
|
59
|
+
* agent,
|
|
60
|
+
* buildShareUrl: (org, slug) => `${appOrigin}/chat/${org}/${slug}`,
|
|
61
|
+
* onSharingChanged: refetch,
|
|
62
|
+
* });
|
|
63
|
+
* // ...
|
|
64
|
+
* <ResourceDetailShell actions={share.action ? [...actions, share.action] : actions} ... />
|
|
65
|
+
* {share.dialog}
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function useShareAgent({ agent, buildShareUrl, onSharingChanged, label, }: UseShareAgentArgs): UseShareAgentReturn;
|
|
69
|
+
//# sourceMappingURL=useShareAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useShareAgent.d.ts","sourceRoot":"","sources":["../../src/sharing/useShareAgent.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oDAAoD,CAAC;AAEhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/D;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IACvC,wCAAwC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,KAAe,GAChB,EAAE,iBAAiB,GAAG,mBAAmB,CA2BzC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { useCheckPermission } from "../iam-policy/useCheckPermission.js";
|
|
5
|
+
import { ShareAgentDialog } from "./ShareAgentDialog.js";
|
|
6
|
+
/**
|
|
7
|
+
* Wires the Share dialog to a kebab/overflow menu — the same trigger
|
|
8
|
+
* shape as {@link useManageAccess}, its conceptual sibling: Manage access
|
|
9
|
+
* governs who can *read* the blueprint; Share governs who can *chat* with
|
|
10
|
+
* the running agent (billed to the owning org).
|
|
11
|
+
*
|
|
12
|
+
* Owns the open-state and the `can_edit` gate — the same permission the
|
|
13
|
+
* AgentShare create/apply handlers enforce on the referenced agent, so
|
|
14
|
+
* the action never appears to a user whose changes would be rejected.
|
|
15
|
+
* Returns a `null` action while the agent is loading or the user cannot
|
|
16
|
+
* edit, so the host can unconditionally fold `action` into its actions
|
|
17
|
+
* array.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* const share = useShareAgent({
|
|
22
|
+
* agent,
|
|
23
|
+
* buildShareUrl: (org, slug) => `${appOrigin}/chat/${org}/${slug}`,
|
|
24
|
+
* onSharingChanged: refetch,
|
|
25
|
+
* });
|
|
26
|
+
* // ...
|
|
27
|
+
* <ResourceDetailShell actions={share.action ? [...actions, share.action] : actions} ... />
|
|
28
|
+
* {share.dialog}
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function useShareAgent({ agent, buildShareUrl, onSharingChanged, label = "Share", }) {
|
|
32
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
33
|
+
const agentId = agent?.metadata?.id ?? null;
|
|
34
|
+
const { allowed: canEdit } = useCheckPermission(agentId ? { kind: "agent", id: agentId } : null, "can_edit");
|
|
35
|
+
const open = useCallback(() => setIsOpen(true), []);
|
|
36
|
+
const action = agent && canEdit
|
|
37
|
+
? { id: "share", label, group: "sharing", onAction: open }
|
|
38
|
+
: null;
|
|
39
|
+
const dialog = agent ? (_jsx(ShareAgentDialog, { open: isOpen, onOpenChange: setIsOpen, agent: agent, buildShareUrl: buildShareUrl, onSharingChanged: onSharingChanged })) : null;
|
|
40
|
+
return { action, dialog, open, isOpen };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=useShareAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useShareAgent.js","sourceRoot":"","sources":["../../src/sharing/useShareAgent.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AA2CzD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,KAAK,GAAG,OAAO,GACG;IAClB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,IAAI,CAAC;IAC5C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,kBAAkB,CAC7C,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,EAC/C,UAAU,CACX,CAAC;IAEF,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAEpD,MAAM,MAAM,GACV,KAAK,IAAI,OAAO;QACd,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC1D,CAAC,CAAC,IAAI,CAAC;IAEX,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CACrB,KAAC,gBAAgB,IACf,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,SAAS,EACvB,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,GAClC,CACH,CAAC,CAAC,CAAC,IAAI,CAAC;IAET,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
2
|
+
import type { AgentShareDraft } from "./useSaveAgentShare.js";
|
|
3
|
+
/**
|
|
4
|
+
* Readiness of a share's tool credentials for visitor executions.
|
|
5
|
+
*
|
|
6
|
+
* - `na` — nothing to check: the agent uses no MCP tools, sharing is
|
|
7
|
+
* off, the audience is org (bindings are public-audience only), or
|
|
8
|
+
* the deployment cannot serve guest chat (local mode).
|
|
9
|
+
* - `needs-credentials` — the agent uses MCP tools but the share has no
|
|
10
|
+
* environments bound: visitors' tool calls will fail until the owner
|
|
11
|
+
* binds credentials.
|
|
12
|
+
* - `checking` — lookups in flight.
|
|
13
|
+
* - `ready` — every environment bound to the share is shared with the
|
|
14
|
+
* organization.
|
|
15
|
+
* - `blocked` — one or more bound environments are private; their
|
|
16
|
+
* `org/slug` references are listed for the hint copy.
|
|
17
|
+
*/
|
|
18
|
+
export type ShareToolReadiness = {
|
|
19
|
+
readonly status: "na";
|
|
20
|
+
} | {
|
|
21
|
+
readonly status: "needs-credentials";
|
|
22
|
+
} | {
|
|
23
|
+
readonly status: "checking";
|
|
24
|
+
} | {
|
|
25
|
+
readonly status: "ready";
|
|
26
|
+
} | {
|
|
27
|
+
readonly status: "blocked";
|
|
28
|
+
readonly privateEnvironments: readonly string[];
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Data hook that checks whether a tool-using shared agent's credentials
|
|
32
|
+
* will work for visitors — i.e. whether the share binds environments
|
|
33
|
+
* (`environment_refs`) and each one is shared with the organization
|
|
34
|
+
* (`visibility_org`).
|
|
35
|
+
*
|
|
36
|
+
* Guest executions receive credentials exclusively from the share's own
|
|
37
|
+
* `environment_refs`, resolved through the org-shared environment seam
|
|
38
|
+
* (decision 011 — the agent's default instance stays pristine and is
|
|
39
|
+
* never consulted). So a tool-using agent with an empty binding list is
|
|
40
|
+
* *guaranteed* broken for visitors, and this hook says so explicitly
|
|
41
|
+
* (`needs-credentials`) instead of staying silent — the gap that made
|
|
42
|
+
* session 12's misconfiguration invisible until a visitor's first
|
|
43
|
+
* message failed.
|
|
44
|
+
*
|
|
45
|
+
* The check runs only when the share is enabled with a public audience
|
|
46
|
+
* (org-audience shares reject bindings at the proto boundary), the
|
|
47
|
+
* deployment is cloud (local mode has no guest runtime or secret
|
|
48
|
+
* gating), and the agent declares MCP server usages. All lookups run as
|
|
49
|
+
* the owner viewing the dialog, who can read the bound environments.
|
|
50
|
+
*/
|
|
51
|
+
export declare function useShareToolReadiness(agent: Agent, draft: AgentShareDraft): ShareToolReadiness;
|
|
52
|
+
//# sourceMappingURL=useShareToolReadiness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useShareToolReadiness.d.ts","sourceRoot":"","sources":["../../src/sharing/useShareToolReadiness.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oDAAoD,CAAC;AAIhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,GACxC;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GAC/B;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAKpF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,eAAe,GACrB,kBAAkB,CAwEpB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
4
|
+
import { useStigmer } from "../hooks.js";
|
|
5
|
+
import { useDeploymentMode } from "../deployment-mode.js";
|
|
6
|
+
const NA = { status: "na" };
|
|
7
|
+
const NEEDS_CREDENTIALS = { status: "needs-credentials" };
|
|
8
|
+
/**
|
|
9
|
+
* Data hook that checks whether a tool-using shared agent's credentials
|
|
10
|
+
* will work for visitors — i.e. whether the share binds environments
|
|
11
|
+
* (`environment_refs`) and each one is shared with the organization
|
|
12
|
+
* (`visibility_org`).
|
|
13
|
+
*
|
|
14
|
+
* Guest executions receive credentials exclusively from the share's own
|
|
15
|
+
* `environment_refs`, resolved through the org-shared environment seam
|
|
16
|
+
* (decision 011 — the agent's default instance stays pristine and is
|
|
17
|
+
* never consulted). So a tool-using agent with an empty binding list is
|
|
18
|
+
* *guaranteed* broken for visitors, and this hook says so explicitly
|
|
19
|
+
* (`needs-credentials`) instead of staying silent — the gap that made
|
|
20
|
+
* session 12's misconfiguration invisible until a visitor's first
|
|
21
|
+
* message failed.
|
|
22
|
+
*
|
|
23
|
+
* The check runs only when the share is enabled with a public audience
|
|
24
|
+
* (org-audience shares reject bindings at the proto boundary), the
|
|
25
|
+
* deployment is cloud (local mode has no guest runtime or secret
|
|
26
|
+
* gating), and the agent declares MCP server usages. All lookups run as
|
|
27
|
+
* the owner viewing the dialog, who can read the bound environments.
|
|
28
|
+
*/
|
|
29
|
+
export function useShareToolReadiness(agent, draft) {
|
|
30
|
+
const stigmer = useStigmer();
|
|
31
|
+
const deploymentMode = useDeploymentMode();
|
|
32
|
+
const [checked, setChecked] = useState(NA);
|
|
33
|
+
const hasMcpTools = (agent.spec?.mcpServerUsages?.length ?? 0) > 0;
|
|
34
|
+
const applicable = draft.enabled &&
|
|
35
|
+
draft.audience === "public" &&
|
|
36
|
+
deploymentMode === "cloud" &&
|
|
37
|
+
hasMcpTools;
|
|
38
|
+
// Stable key for the effect: the visibility lookups depend only on
|
|
39
|
+
// which environments are bound, not on the array's identity.
|
|
40
|
+
const refsKey = useMemo(() => draft.environmentRefs.map((ref) => `${ref.org}/${ref.slug}`).join(","), [draft.environmentRefs]);
|
|
41
|
+
const shouldFetch = applicable && refsKey !== "";
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!shouldFetch) {
|
|
44
|
+
setChecked(NA);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
let cancelled = false;
|
|
48
|
+
setChecked({ status: "checking" });
|
|
49
|
+
(async () => {
|
|
50
|
+
const privateRefs = [];
|
|
51
|
+
for (const ref of refsKey.split(",")) {
|
|
52
|
+
const [org, slug] = ref.split("/");
|
|
53
|
+
try {
|
|
54
|
+
const env = await stigmer.environment.getByReference({ org, slug });
|
|
55
|
+
if (env.metadata?.visibility !== ApiResourceVisibility.visibility_org) {
|
|
56
|
+
privateRefs.push(ref);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Unreadable ref (deleted, foreign): the runtime's merge will
|
|
61
|
+
// skip it for visitors too — surface it as blocking.
|
|
62
|
+
privateRefs.push(ref);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return privateRefs.length === 0
|
|
66
|
+
? { status: "ready" }
|
|
67
|
+
: { status: "blocked", privateEnvironments: privateRefs };
|
|
68
|
+
})().then((result) => {
|
|
69
|
+
if (!cancelled)
|
|
70
|
+
setChecked(result);
|
|
71
|
+
}, () => {
|
|
72
|
+
// The hint is best-effort pre-flight advice — a failed check must
|
|
73
|
+
// never block the dialog. The runtime error path still diagnoses.
|
|
74
|
+
if (!cancelled)
|
|
75
|
+
setChecked(NA);
|
|
76
|
+
});
|
|
77
|
+
return () => {
|
|
78
|
+
cancelled = true;
|
|
79
|
+
};
|
|
80
|
+
}, [shouldFetch, refsKey, stigmer]);
|
|
81
|
+
if (!applicable)
|
|
82
|
+
return NA;
|
|
83
|
+
// Zero bindings needs no lookup: a tool-using agent without bound
|
|
84
|
+
// credentials is broken for visitors by construction.
|
|
85
|
+
if (refsKey === "")
|
|
86
|
+
return NEEDS_CREDENTIALS;
|
|
87
|
+
return checked;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=useShareToolReadiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useShareToolReadiness.js","sourceRoot":"","sources":["../../src/sharing/useShareToolReadiness.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAyB1D,MAAM,EAAE,GAAuB,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAChD,MAAM,iBAAiB,GAAuB,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAY,EACZ,KAAsB;IAEtB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;IAC3C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAqB,EAAE,CAAC,CAAC;IAE/D,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACnE,MAAM,UAAU,GACd,KAAK,CAAC,OAAO;QACb,KAAK,CAAC,QAAQ,KAAK,QAAQ;QAC3B,cAAc,KAAK,OAAO;QAC1B,WAAW,CAAC;IAEd,mEAAmE;IACnE,6DAA6D;IAC7D,MAAM,OAAO,GAAG,OAAO,CACrB,GAAG,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAC5E,CAAC,KAAK,CAAC,eAAe,CAAC,CACxB,CAAC;IAEF,MAAM,WAAW,GAAG,UAAU,IAAI,OAAO,KAAK,EAAE,CAAC;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,UAAU,CAAC,EAAE,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAEnC,CAAC,KAAK,IAAiC,EAAE;YACvC,MAAM,WAAW,GAAa,EAAE,CAAC;YACjC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACnC,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;oBACpE,IACE,GAAG,CAAC,QAAQ,EAAE,UAAU,KAAK,qBAAqB,CAAC,cAAc,EACjE,CAAC;wBACD,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACxB,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,8DAA8D;oBAC9D,qDAAqD;oBACrD,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;YAED,OAAO,WAAW,CAAC,MAAM,KAAK,CAAC;gBAC7B,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE;gBACrB,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAC;QAC9D,CAAC,CAAC,EAAE,CAAC,IAAI,CACP,CAAC,MAAM,EAAE,EAAE;YACT,IAAI,CAAC,SAAS;gBAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC,EACD,GAAG,EAAE;YACH,kEAAkE;YAClE,kEAAkE;YAClE,IAAI,CAAC,SAAS;gBAAE,UAAU,CAAC,EAAE,CAAC,CAAC;QACjC,CAAC,CACF,CAAC;QAEF,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpC,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC3B,kEAAkE;IAClE,sDAAsD;IACtD,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,iBAAiB,CAAC;IAC7C,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type SharedAgentProfile } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/io_pb";
|
|
2
|
+
import type { SharingAudience } from "./useSaveAgentShare.js";
|
|
3
|
+
/** Options for {@link useSharedAgentProfile}. */
|
|
4
|
+
export interface UseSharedAgentProfileOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Which resolution path to use.
|
|
7
|
+
*
|
|
8
|
+
* - `"public"` (default) — the anonymous `getSharedProfile` RPC. An
|
|
9
|
+
* org-audience share answers NOT_FOUND here by design.
|
|
10
|
+
* - `"org"` — the authenticated `getSharedProfileForMember` RPC, which
|
|
11
|
+
* resolves org-audience shares for signed-in members of the owning
|
|
12
|
+
* organization (and public shares too). Requires a `StigmerProvider`
|
|
13
|
+
* whose client carries the member's token.
|
|
14
|
+
*/
|
|
15
|
+
readonly audience?: SharingAudience;
|
|
16
|
+
/**
|
|
17
|
+
* Share-link token from the URL's `?k=` parameter (public path only).
|
|
18
|
+
*
|
|
19
|
+
* Required when the share link has been locked with a rotatable token;
|
|
20
|
+
* harmless on plain links. On a locked link a missing or rotated-away
|
|
21
|
+
* token resolves to `profile === null`, indistinguishable from an
|
|
22
|
+
* agent that does not exist.
|
|
23
|
+
*/
|
|
24
|
+
readonly linkToken?: string;
|
|
25
|
+
}
|
|
26
|
+
/** Return value of {@link useSharedAgentProfile}. */
|
|
27
|
+
export interface UseSharedAgentProfileReturn {
|
|
28
|
+
/**
|
|
29
|
+
* The shared agent's public profile, or `null` while loading, on
|
|
30
|
+
* error, or when the agent is not shared.
|
|
31
|
+
*/
|
|
32
|
+
readonly profile: SharedAgentProfile | null;
|
|
33
|
+
/** `true` while the initial fetch or a refetch is in flight. */
|
|
34
|
+
readonly isLoading: boolean;
|
|
35
|
+
/** `true` while a background refetch is in flight and stale data is shown. */
|
|
36
|
+
readonly isRefetching: boolean;
|
|
37
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
38
|
+
readonly error: Error | null;
|
|
39
|
+
/** Discard cached data and re-fetch the profile from the server. */
|
|
40
|
+
readonly refetch: () => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Data hook that fetches a shared agent's public profile by the org and
|
|
44
|
+
* slug from the share URL (the share's slug — it defaults to the
|
|
45
|
+
* agent's, so existing links resolve unchanged).
|
|
46
|
+
*
|
|
47
|
+
* By default this hook calls the `getSharedProfile` endpoint, which is
|
|
48
|
+
* **public** — it requires no authentication. The server returns a
|
|
49
|
+
* trimmed projection safe for anonymous visitors: name, description,
|
|
50
|
+
* icon, and the default instance id needed to start a session
|
|
51
|
+
* (an identifier, not a capability — session creation still requires
|
|
52
|
+
* an authorized token, e.g. a guest token from `createGuestAuth`).
|
|
53
|
+
* With `{ audience: "org" }` it calls the authenticated
|
|
54
|
+
* `getSharedProfileForMember` endpoint instead, which resolves
|
|
55
|
+
* org-members-only shares for a signed-in member.
|
|
56
|
+
*
|
|
57
|
+
* **Not-shared handling:** the server answers NOT_FOUND for "this
|
|
58
|
+
* agent does not exist", "this agent is not shared", and (on the
|
|
59
|
+
* member path) "you are not a member of this organization" — all
|
|
60
|
+
* indistinguishable by design so a share URL leaks nothing. The hook
|
|
61
|
+
* maps that to `profile === null` without raising an error, matching
|
|
62
|
+
* `useAgent`'s not-found convention:
|
|
63
|
+
* `profile === null && !isLoading && !error` means unavailable.
|
|
64
|
+
*
|
|
65
|
+
* Pass `null` for either `org` or `slug` to skip fetching (stable
|
|
66
|
+
* no-op) — useful while route params are still resolving.
|
|
67
|
+
*
|
|
68
|
+
* **Note**: Although authentication is not required by the server,
|
|
69
|
+
* the hook still requires a `StigmerProvider` ancestor because it
|
|
70
|
+
* needs the transport configuration (API base URL) to make the
|
|
71
|
+
* request.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* const { profile, isLoading, error } = useSharedAgentProfile(org, slug);
|
|
76
|
+
*
|
|
77
|
+
* if (isLoading) return <Spinner />;
|
|
78
|
+
* if (error) return <ErrorCard error={error} />;
|
|
79
|
+
* if (!profile) return <AgentUnavailable />;
|
|
80
|
+
*
|
|
81
|
+
* return <h1>{profile.name}</h1>;
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function useSharedAgentProfile(org: string | null, slug: string | null, options?: UseSharedAgentProfileOptions): UseSharedAgentProfileReturn;
|
|
85
|
+
//# sourceMappingURL=useSharedAgentProfile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSharedAgentProfile.d.ts","sourceRoot":"","sources":["../../src/sharing/useSharedAgentProfile.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,wDAAwD,CAAC;AAIhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,iDAAiD;AACjD,MAAM,WAAW,4BAA4B;IAC3C;;;;;;;;;OASG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAEpC;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,qDAAqD;AACrD,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC5C,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,OAAO,CAAC,EAAE,4BAA4B,GACrC,2BAA2B,CA+B7B"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { create } from "@bufbuild/protobuf";
|
|
3
|
+
import { GetSharedProfileRequestSchema, } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/io_pb";
|
|
4
|
+
import { isNotFound } from "@stigmer/sdk";
|
|
5
|
+
import { useStigmer } from "../hooks.js";
|
|
6
|
+
import { useFetch } from "../internal/useFetch.js";
|
|
7
|
+
/**
|
|
8
|
+
* Data hook that fetches a shared agent's public profile by the org and
|
|
9
|
+
* slug from the share URL (the share's slug — it defaults to the
|
|
10
|
+
* agent's, so existing links resolve unchanged).
|
|
11
|
+
*
|
|
12
|
+
* By default this hook calls the `getSharedProfile` endpoint, which is
|
|
13
|
+
* **public** — it requires no authentication. The server returns a
|
|
14
|
+
* trimmed projection safe for anonymous visitors: name, description,
|
|
15
|
+
* icon, and the default instance id needed to start a session
|
|
16
|
+
* (an identifier, not a capability — session creation still requires
|
|
17
|
+
* an authorized token, e.g. a guest token from `createGuestAuth`).
|
|
18
|
+
* With `{ audience: "org" }` it calls the authenticated
|
|
19
|
+
* `getSharedProfileForMember` endpoint instead, which resolves
|
|
20
|
+
* org-members-only shares for a signed-in member.
|
|
21
|
+
*
|
|
22
|
+
* **Not-shared handling:** the server answers NOT_FOUND for "this
|
|
23
|
+
* agent does not exist", "this agent is not shared", and (on the
|
|
24
|
+
* member path) "you are not a member of this organization" — all
|
|
25
|
+
* indistinguishable by design so a share URL leaks nothing. The hook
|
|
26
|
+
* maps that to `profile === null` without raising an error, matching
|
|
27
|
+
* `useAgent`'s not-found convention:
|
|
28
|
+
* `profile === null && !isLoading && !error` means unavailable.
|
|
29
|
+
*
|
|
30
|
+
* Pass `null` for either `org` or `slug` to skip fetching (stable
|
|
31
|
+
* no-op) — useful while route params are still resolving.
|
|
32
|
+
*
|
|
33
|
+
* **Note**: Although authentication is not required by the server,
|
|
34
|
+
* the hook still requires a `StigmerProvider` ancestor because it
|
|
35
|
+
* needs the transport configuration (API base URL) to make the
|
|
36
|
+
* request.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
* const { profile, isLoading, error } = useSharedAgentProfile(org, slug);
|
|
41
|
+
*
|
|
42
|
+
* if (isLoading) return <Spinner />;
|
|
43
|
+
* if (error) return <ErrorCard error={error} />;
|
|
44
|
+
* if (!profile) return <AgentUnavailable />;
|
|
45
|
+
*
|
|
46
|
+
* return <h1>{profile.name}</h1>;
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function useSharedAgentProfile(org, slug, options) {
|
|
50
|
+
const stigmer = useStigmer();
|
|
51
|
+
const audience = options?.audience ?? "public";
|
|
52
|
+
const linkToken = options?.linkToken ?? "";
|
|
53
|
+
const fetchFn = org && slug
|
|
54
|
+
? async () => {
|
|
55
|
+
try {
|
|
56
|
+
// The member path is tokenless by contract: org-audience access
|
|
57
|
+
// is gated by live membership, and token-locked public shares
|
|
58
|
+
// deliberately refuse there (see getSharedProfileForMember).
|
|
59
|
+
return audience === "org"
|
|
60
|
+
? await stigmer.agentShare.getSharedProfileForMember({ org, slug })
|
|
61
|
+
: await stigmer.agentShare.getSharedProfile(create(GetSharedProfileRequestSchema, { org, slug, linkToken }));
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (isNotFound(err))
|
|
65
|
+
return null;
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
: null;
|
|
70
|
+
const { data: profile, isLoading, isRefetching, error, refetch } = useFetch(fetchFn, [org, slug, audience, linkToken, stigmer], null);
|
|
71
|
+
return { profile, isLoading, isRefetching, error, refetch };
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=useSharedAgentProfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSharedAgentProfile.js","sourceRoot":"","sources":["../../src/sharing/useSharedAgentProfile.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EACL,6BAA6B,GAE9B,MAAM,wDAAwD,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AA6CnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAkB,EAClB,IAAmB,EACnB,OAAsC;IAEtC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,QAAQ,CAAC;IAC/C,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;IAE3C,MAAM,OAAO,GACX,GAAG,IAAI,IAAI;QACT,CAAC,CAAC,KAAK,IAAI,EAAE;YACT,IAAI,CAAC;gBACH,gEAAgE;gBAChE,8DAA8D;gBAC9D,6DAA6D;gBAC7D,OAAO,QAAQ,KAAK,KAAK;oBACvB,CAAC,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,yBAAyB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;oBACnE,CAAC,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,gBAAgB,CACvC,MAAM,CAAC,6BAA6B,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAChE,CAAC;YACR,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,UAAU,CAAC,GAAG,CAAC;oBAAE,OAAO,IAAI,CAAC;gBACjC,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QACH,CAAC,CAAC,IAAI,CAAC;IAEX,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,QAAQ,CACzE,OAAO,EACP,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EACzC,IAAiC,CAClC,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -17,6 +17,7 @@ import { agentToInput } from "./internal/agentToInput.js";
|
|
|
17
17
|
import { ErrorMessage } from "../error/ErrorMessage.js";
|
|
18
18
|
import { VisibilityBadge } from "../library/VisibilitySelector.js";
|
|
19
19
|
import { useManageAccess } from "../access/useManageAccess.js";
|
|
20
|
+
import { useShareAgent } from "../sharing/useShareAgent.js";
|
|
20
21
|
import { ResourceDetailShell } from "../resource-detail/ResourceDetailShell.js";
|
|
21
22
|
import { Section } from "../resource-detail/Section.js";
|
|
22
23
|
import { useDetailTabs } from "../resource-detail/useDetailTabs.js";
|
|
@@ -127,6 +128,14 @@ export interface AgentDetailViewProps {
|
|
|
127
128
|
* Opens the create instance dialog.
|
|
128
129
|
*/
|
|
129
130
|
readonly onCreateInstanceClick?: () => void;
|
|
131
|
+
/**
|
|
132
|
+
* Builds the absolute public chat URL shown in the Share dialog.
|
|
133
|
+
* The host application owns URL construction — its configured public
|
|
134
|
+
* origin may differ from the rendering origin (e.g. the desktop app).
|
|
135
|
+
* When omitted, the dialog falls back to the relative
|
|
136
|
+
* `/chat/<org>/<slug>` path.
|
|
137
|
+
*/
|
|
138
|
+
readonly buildShareUrl?: (org: string, slug: string) => string;
|
|
130
139
|
/**
|
|
131
140
|
* Called when the user clicks an instance row in the Instances tab.
|
|
132
141
|
* Typically opens an instance detail panel.
|
|
@@ -204,6 +213,7 @@ export function AgentDetailView({
|
|
|
204
213
|
defaultTab,
|
|
205
214
|
editable = false,
|
|
206
215
|
onResourceUpdated,
|
|
216
|
+
buildShareUrl,
|
|
207
217
|
onCreateInstanceClick,
|
|
208
218
|
onInstanceClick,
|
|
209
219
|
onInstanceStartSessionClick,
|
|
@@ -306,6 +316,15 @@ export function AgentDetailView({
|
|
|
306
316
|
: undefined,
|
|
307
317
|
});
|
|
308
318
|
|
|
319
|
+
// Share — the sibling consent to Manage access: visibility governs who
|
|
320
|
+
// can read the blueprint; sharing governs who can chat with the running
|
|
321
|
+
// agent (billed to the owning org). Same null-until-ready contract.
|
|
322
|
+
const share = useShareAgent({
|
|
323
|
+
agent,
|
|
324
|
+
buildShareUrl,
|
|
325
|
+
onSharingChanged: refetch,
|
|
326
|
+
});
|
|
327
|
+
|
|
309
328
|
if (isLoading) return <LoadingSkeleton className={className} />;
|
|
310
329
|
if (error)
|
|
311
330
|
return <ErrorMessage error={error} retry={refetch} className={className} />;
|
|
@@ -344,9 +363,14 @@ export function AgentDetailView({
|
|
|
344
363
|
<VisibilityBadge visibility={meta.visibility} />
|
|
345
364
|
) : undefined;
|
|
346
365
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
:
|
|
366
|
+
// Share precedes Manage access within the "sharing" group.
|
|
367
|
+
const injectedActions = [share.action, access.action].filter(
|
|
368
|
+
(a): a is NonNullable<typeof a> => a != null,
|
|
369
|
+
);
|
|
370
|
+
const mergedActions =
|
|
371
|
+
injectedActions.length > 0
|
|
372
|
+
? [...(actions ?? []), ...injectedActions]
|
|
373
|
+
: actions;
|
|
350
374
|
|
|
351
375
|
let tabContent: React.ReactNode;
|
|
352
376
|
if (activeAdditionalTab) {
|
|
@@ -402,6 +426,7 @@ export function AgentDetailView({
|
|
|
402
426
|
{tabContent}
|
|
403
427
|
</ResourceDetailShell>
|
|
404
428
|
{access.dialog}
|
|
429
|
+
{share.dialog}
|
|
405
430
|
</>
|
|
406
431
|
);
|
|
407
432
|
}
|
|
@@ -4,8 +4,11 @@ import { useCallback, useMemo, useState } from "react";
|
|
|
4
4
|
import { cn } from "@stigmer/theme";
|
|
5
5
|
import { getUserMessage } from "@stigmer/sdk";
|
|
6
6
|
import type { Environment } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
|
|
7
|
+
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
8
|
+
import { ResourceVisibilityControl } from "../library/ResourceVisibilityControl.js";
|
|
7
9
|
import { useEnvironmentList } from "./useEnvironmentList.js";
|
|
8
10
|
import { EnvironmentVariableEditor } from "./EnvironmentVariableEditor.js";
|
|
11
|
+
import { isShareRestrictedEnvironment } from "./shareRestriction.js";
|
|
9
12
|
|
|
10
13
|
// ---------------------------------------------------------------------------
|
|
11
14
|
// Public API
|
|
@@ -175,6 +178,7 @@ export function EnvironmentListPanel({
|
|
|
175
178
|
isExpanded={isExpanded}
|
|
176
179
|
onToggle={() => handleToggle(env)}
|
|
177
180
|
readOnly={readOnly}
|
|
181
|
+
onVisibilityChanged={refetch}
|
|
178
182
|
/>
|
|
179
183
|
);
|
|
180
184
|
})}
|
|
@@ -191,11 +195,13 @@ function EnvironmentCard({
|
|
|
191
195
|
isExpanded,
|
|
192
196
|
onToggle,
|
|
193
197
|
readOnly,
|
|
198
|
+
onVisibilityChanged,
|
|
194
199
|
}: {
|
|
195
200
|
environment: Environment;
|
|
196
201
|
isExpanded: boolean;
|
|
197
202
|
onToggle: () => void;
|
|
198
203
|
readOnly: boolean;
|
|
204
|
+
onVisibilityChanged: () => void;
|
|
199
205
|
}) {
|
|
200
206
|
const name =
|
|
201
207
|
environment.metadata?.name || environment.metadata?.slug || "Unnamed";
|
|
@@ -203,6 +209,12 @@ function EnvironmentCard({
|
|
|
203
209
|
const variableCount = Object.keys(environment.spec?.data ?? {}).length;
|
|
204
210
|
const environmentId = environment.metadata?.id ?? "";
|
|
205
211
|
|
|
212
|
+
// Personal and OAuth-managed environments are never org-shareable
|
|
213
|
+
// (the backend rejects the transition) — offering the control would
|
|
214
|
+
// be an error trap, so it is structurally absent for them.
|
|
215
|
+
const showVisibilityControl =
|
|
216
|
+
!readOnly && environmentId !== "" && !isShareRestrictedEnvironment(environment);
|
|
217
|
+
|
|
206
218
|
return (
|
|
207
219
|
<div
|
|
208
220
|
role="listitem"
|
|
@@ -213,30 +225,47 @@ function EnvironmentCard({
|
|
|
213
225
|
: "border-border-muted hover:border-border",
|
|
214
226
|
)}
|
|
215
227
|
>
|
|
216
|
-
{/* Header — always visible
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
228
|
+
{/* Header — always visible. The expand toggle and the visibility
|
|
229
|
+
control are sibling interactive elements (nesting the selector
|
|
230
|
+
inside the toggle button would be invalid markup). */}
|
|
231
|
+
<div className="flex w-full items-center gap-3 px-3 py-2.5">
|
|
232
|
+
<button
|
|
233
|
+
type="button"
|
|
234
|
+
onClick={onToggle}
|
|
235
|
+
aria-expanded={isExpanded}
|
|
236
|
+
className="flex min-w-0 flex-1 items-center gap-3 text-left"
|
|
237
|
+
>
|
|
238
|
+
<ChevronIcon expanded={isExpanded} />
|
|
224
239
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
</span>
|
|
229
|
-
{description && (
|
|
230
|
-
<span className="block truncate text-xs text-muted-foreground">
|
|
231
|
-
{description}
|
|
240
|
+
<div className="min-w-0 flex-1">
|
|
241
|
+
<span className="block truncate text-sm font-medium text-foreground">
|
|
242
|
+
{name}
|
|
232
243
|
</span>
|
|
233
|
-
|
|
234
|
-
|
|
244
|
+
{description && (
|
|
245
|
+
<span className="block truncate text-xs text-muted-foreground">
|
|
246
|
+
{description}
|
|
247
|
+
</span>
|
|
248
|
+
)}
|
|
249
|
+
</div>
|
|
250
|
+
</button>
|
|
251
|
+
|
|
252
|
+
{showVisibilityControl && (
|
|
253
|
+
<ResourceVisibilityControl
|
|
254
|
+
kind="environment"
|
|
255
|
+
resourceId={environmentId}
|
|
256
|
+
visibility={
|
|
257
|
+
environment.metadata?.visibility ??
|
|
258
|
+
ApiResourceVisibility.visibility_private
|
|
259
|
+
}
|
|
260
|
+
onChanged={onVisibilityChanged}
|
|
261
|
+
className="shrink-0"
|
|
262
|
+
/>
|
|
263
|
+
)}
|
|
235
264
|
|
|
236
265
|
<span className="shrink-0 text-xs text-muted-foreground">
|
|
237
266
|
{variableCount} {variableCount === 1 ? "variable" : "variables"}
|
|
238
267
|
</span>
|
|
239
|
-
</
|
|
268
|
+
</div>
|
|
240
269
|
|
|
241
270
|
{/* Expanded content — variable editor */}
|
|
242
271
|
{isExpanded && environmentId && (
|