@stigmer/react 3.1.8 → 3.1.10
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/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/index.d.ts +2 -2
- package/index.d.ts.map +1 -1
- package/index.js +2 -2
- package/index.js.map +1 -1
- package/package.json +4 -4
- package/sharing/ShareAgentDialog.d.ts +10 -8
- package/sharing/ShareAgentDialog.d.ts.map +1 -1
- package/sharing/ShareAgentDialog.js +139 -54
- package/sharing/ShareAgentDialog.js.map +1 -1
- package/sharing/SharedAgentChat.d.ts +1 -1
- package/sharing/SharedAgentChat.d.ts.map +1 -1
- package/sharing/index.d.ts +4 -2
- package/sharing/index.d.ts.map +1 -1
- package/sharing/index.js +2 -1
- package/sharing/index.js.map +1 -1
- 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 +22 -19
- package/sharing/useRotateShareLink.d.ts.map +1 -1
- package/sharing/useRotateShareLink.js +22 -19
- package/sharing/useRotateShareLink.js.map +1 -1
- 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 +5 -4
- package/sharing/useShareAgent.d.ts.map +1 -1
- package/sharing/useShareAgent.js +5 -4
- package/sharing/useShareAgent.js.map +1 -1
- package/sharing/useShareToolReadiness.d.ts +29 -25
- package/sharing/useShareToolReadiness.d.ts.map +1 -1
- package/sharing/useShareToolReadiness.js +47 -51
- package/sharing/useShareToolReadiness.js.map +1 -1
- package/sharing/useSharedAgentProfile.d.ts +5 -4
- package/sharing/useSharedAgentProfile.d.ts.map +1 -1
- package/sharing/useSharedAgentProfile.js +6 -5
- package/sharing/useSharedAgentProfile.js.map +1 -1
- package/src/environment/EnvironmentPicker.tsx +23 -2
- package/src/index.ts +8 -4
- package/src/sharing/ShareAgentDialog.tsx +353 -119
- package/src/sharing/SharedAgentChat.tsx +1 -1
- package/src/sharing/__tests__/ShareAgentDialog.test.tsx +550 -369
- package/src/sharing/__tests__/useAgentShare.test.tsx +149 -0
- package/src/sharing/__tests__/useRotateShareLink.test.tsx +8 -8
- package/src/sharing/__tests__/useSaveAgentShare.test.tsx +241 -0
- package/src/sharing/__tests__/useShareAgent.test.tsx +6 -2
- package/src/sharing/__tests__/useShareToolReadiness.test.tsx +84 -47
- package/src/sharing/__tests__/useSharedAgentProfile.test.tsx +1 -1
- package/src/sharing/index.ts +9 -7
- package/src/sharing/useAgentShare.ts +91 -0
- package/src/sharing/useRotateShareLink.ts +30 -25
- package/src/sharing/useSaveAgentShare.ts +186 -0
- package/src/sharing/useShareAgent.tsx +5 -4
- package/src/sharing/useShareToolReadiness.ts +62 -60
- package/src/sharing/useSharedAgentProfile.ts +7 -6
- package/src/switch/Switch.tsx +6 -1
- package/src/switch/__tests__/Switch.test.tsx +19 -0
- package/switch/Switch.d.ts.map +1 -1
- package/switch/Switch.js +6 -1
- package/switch/Switch.js.map +1 -1
- package/sharing/useUpdateAgentSharing.d.ts +0 -86
- package/sharing/useUpdateAgentSharing.d.ts.map +0 -1
- package/sharing/useUpdateAgentSharing.js +0 -81
- package/sharing/useUpdateAgentSharing.js.map +0 -1
- package/src/sharing/__tests__/useUpdateAgentSharing.test.tsx +0 -200
- package/src/sharing/useUpdateAgentSharing.ts +0 -151
package/src/switch/Switch.tsx
CHANGED
|
@@ -69,9 +69,14 @@ export function Switch({
|
|
|
69
69
|
onClick={() => onCheckedChange(!checked)}
|
|
70
70
|
className={cn(
|
|
71
71
|
// Track. `relative` anchors both the thumb and the expanded hit area.
|
|
72
|
+
// Off state uses the form-control token (`--stgm-input`), NOT
|
|
73
|
+
// `bg-muted`: muted matches the popover surface in dark presets, which
|
|
74
|
+
// made the track invisible inside dialogs. Both track fills are
|
|
75
|
+
// registered as surface pairs in the theme contrast contract
|
|
76
|
+
// (@stigmer/theme contract/pairs.ts), so every preset is audited.
|
|
72
77
|
"relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors",
|
|
73
78
|
"motion-reduce:transition-none",
|
|
74
|
-
checked ? "bg-primary" : "bg-
|
|
79
|
+
checked ? "bg-primary" : "bg-input",
|
|
75
80
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
76
81
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
77
82
|
// Expanded invisible hit area (~44px tall) for touch targets.
|
|
@@ -69,6 +69,25 @@ describe("Switch", () => {
|
|
|
69
69
|
expect(onCheckedChange).not.toHaveBeenCalled();
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
+
it("fills the track with the contract-audited surface tokens", () => {
|
|
73
|
+
// bg-input (off) / bg-primary (on) are registered as surface pairs in
|
|
74
|
+
// the @stigmer/theme contrast contract — bg-muted is NOT valid here (it
|
|
75
|
+
// matches the popover surface in dark presets, making the track
|
|
76
|
+
// invisible inside dialogs).
|
|
77
|
+
const { rerender } = render(
|
|
78
|
+
<Switch checked={false} onCheckedChange={() => {}} aria-label="Enable sharing" />,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const el = screen.getByRole("switch");
|
|
82
|
+
expect(el.className).toContain("bg-input");
|
|
83
|
+
expect(el.className).not.toContain("bg-muted");
|
|
84
|
+
|
|
85
|
+
rerender(
|
|
86
|
+
<Switch checked onCheckedChange={() => {}} aria-label="Enable sharing" />,
|
|
87
|
+
);
|
|
88
|
+
expect(el.className).toContain("bg-primary");
|
|
89
|
+
});
|
|
90
|
+
|
|
72
91
|
it("supports aria-labelledby for external labels", () => {
|
|
73
92
|
render(
|
|
74
93
|
<>
|
package/switch/Switch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../src/switch/Switch.tsx"],"names":[],"mappings":"AAIA,gCAAgC;AAChC,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,iDAAiD;IACjD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,EACrB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,EAAE,EACF,SAAS,GACV,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../src/switch/Switch.tsx"],"names":[],"mappings":"AAIA,gCAAgC;AAChC,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,iDAAiD;IACjD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,EACrB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,EAAE,EACF,SAAS,GACV,EAAE,WAAW,2CAsCb"}
|
package/switch/Switch.js
CHANGED
|
@@ -29,7 +29,12 @@ import { cn } from "@stigmer/theme";
|
|
|
29
29
|
export function Switch({ checked, onCheckedChange, disabled, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, id, className, }) {
|
|
30
30
|
return (_jsx("button", { type: "button", role: "switch", id: id, "aria-checked": checked, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, disabled: disabled, onClick: () => onCheckedChange(!checked), className: cn(
|
|
31
31
|
// Track. `relative` anchors both the thumb and the expanded hit area.
|
|
32
|
-
|
|
32
|
+
// Off state uses the form-control token (`--stgm-input`), NOT
|
|
33
|
+
// `bg-muted`: muted matches the popover surface in dark presets, which
|
|
34
|
+
// made the track invisible inside dialogs. Both track fills are
|
|
35
|
+
// registered as surface pairs in the theme contrast contract
|
|
36
|
+
// (@stigmer/theme contract/pairs.ts), so every preset is audited.
|
|
37
|
+
"relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors", "motion-reduce:transition-none", checked ? "bg-primary" : "bg-input", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", "disabled:pointer-events-none disabled:opacity-50",
|
|
33
38
|
// Expanded invisible hit area (~44px tall) for touch targets.
|
|
34
39
|
"after:absolute after:-inset-3 after:content-['']", className), children: _jsx("span", { "aria-hidden": "true", className: cn("pointer-events-none block size-4 rounded-full bg-background shadow-sm transition-transform", "motion-reduce:transition-none", checked ? "translate-x-[18px]" : "translate-x-0.5") }) }));
|
|
35
40
|
}
|
package/switch/Switch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.js","sourceRoot":"","sources":["../../src/switch/Switch.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAuBpC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,MAAM,CAAC,EACrB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,EAAE,EACF,SAAS,GACG;IACZ,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,EACb,EAAE,EAAE,EAAE,kBACQ,OAAO,gBACT,SAAS,qBACJ,cAAc,EAC/B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,EACxC,SAAS,EAAE,EAAE;QACX,sEAAsE;QACtE,mFAAmF,EACnF,+BAA+B,EAC/B,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,EACnC,qGAAqG,EACrG,kDAAkD;QAClD,8DAA8D;QAC9D,kDAAkD,EAClD,SAAS,CACV,YAED,8BACc,MAAM,EAClB,SAAS,EAAE,EAAE,CACX,4FAA4F,EAC5F,+BAA+B,EAC/B,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,iBAAiB,CACnD,GACD,GACK,CACV,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"Switch.js","sourceRoot":"","sources":["../../src/switch/Switch.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAuBpC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,MAAM,CAAC,EACrB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,EAAE,EACF,SAAS,GACG;IACZ,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,EACb,EAAE,EAAE,EAAE,kBACQ,OAAO,gBACT,SAAS,qBACJ,cAAc,EAC/B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,EACxC,SAAS,EAAE,EAAE;QACX,sEAAsE;QACtE,8DAA8D;QAC9D,uEAAuE;QACvE,gEAAgE;QAChE,6DAA6D;QAC7D,kEAAkE;QAClE,mFAAmF,EACnF,+BAA+B,EAC/B,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,EACnC,qGAAqG,EACrG,kDAAkD;QAClD,8DAA8D;QAC9D,kDAAkD,EAClD,SAAS,CACV,YAED,8BACc,MAAM,EAClB,SAAS,EAAE,EAAE,CACX,4FAA4F,EAC5F,+BAA+B,EAC/B,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,iBAAiB,CACnD,GACD,GACK,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
2
|
-
import { AgentSharingAudience } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
3
|
-
/**
|
|
4
|
-
* Who can chat with a shared agent over its hosted link.
|
|
5
|
-
*
|
|
6
|
-
* - `"public"` — anyone with the link; visitors are anonymous guests.
|
|
7
|
-
* - `"org"` — signed-in members of the owning organization only.
|
|
8
|
-
* Membership is checked on every conversation turn, so access ends the
|
|
9
|
-
* moment a member leaves the org.
|
|
10
|
-
*/
|
|
11
|
-
export type SharingAudience = "public" | "org";
|
|
12
|
-
/**
|
|
13
|
-
* A complete sharing configuration to persist.
|
|
14
|
-
*
|
|
15
|
-
* Every field is required by design: the `updateSharing` RPC **replaces**
|
|
16
|
-
* the agent's whole `spec.sharing` block, so a caller must always supply
|
|
17
|
-
* the full configuration. A partial type here would let a toggle change
|
|
18
|
-
* silently wipe `allowedOrigins`, `messages`, or the `audience` — the
|
|
19
|
-
* required shape makes that mistake unrepresentable.
|
|
20
|
-
*/
|
|
21
|
-
export interface AgentSharingDraft {
|
|
22
|
-
/** Whether hosted-chat access for the configured audience is enabled. */
|
|
23
|
-
readonly enabled: boolean;
|
|
24
|
-
/** Who can chat: anyone with the link, or org members only. */
|
|
25
|
-
readonly audience: SharingAudience;
|
|
26
|
-
/**
|
|
27
|
-
* Exact web origins allowed to embed the shared agent
|
|
28
|
-
* (e.g. `https://example.com`). Stored now; enforced by the embed
|
|
29
|
-
* widget's Origin check. Embedding is public-audience only.
|
|
30
|
-
*/
|
|
31
|
-
readonly allowedOrigins: readonly string[];
|
|
32
|
-
/** Owner-customized visitor refusal copy. Empty strings mean platform defaults. */
|
|
33
|
-
readonly messages: {
|
|
34
|
-
/** Shown when a visitor exceeds the message rate limit. */
|
|
35
|
-
readonly rateLimited: string;
|
|
36
|
-
/** Shown when the org's credits are exhausted (sharing fails closed). */
|
|
37
|
-
readonly unavailable: string;
|
|
38
|
-
/** Shown when a conversation hits its turn limit or inactivity timeout. */
|
|
39
|
-
readonly conversationEnded: string;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Maps a proto {@link AgentSharingAudience} to the SDK's string union.
|
|
44
|
-
* Unspecified means public by contract (pre-audience shares keep their
|
|
45
|
-
* anyone-with-link behavior).
|
|
46
|
-
*/
|
|
47
|
-
export declare function sharingAudienceFromProto(audience: AgentSharingAudience | undefined): SharingAudience;
|
|
48
|
-
/** Return value of {@link useUpdateAgentSharing}. */
|
|
49
|
-
export interface UseUpdateAgentSharingReturn {
|
|
50
|
-
/**
|
|
51
|
-
* Persist the complete sharing configuration via the `updateSharing`
|
|
52
|
-
* RPC. Resolves with the updated agent.
|
|
53
|
-
*/
|
|
54
|
-
readonly updateSharing: (draft: AgentSharingDraft) => Promise<Agent | undefined>;
|
|
55
|
-
/** `true` while the RPC is in flight. */
|
|
56
|
-
readonly isPending: boolean;
|
|
57
|
-
/** The last error from the RPC, or `null`. */
|
|
58
|
-
readonly error: Error | null;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Behavior hook that updates an agent's sharing configuration.
|
|
62
|
-
*
|
|
63
|
-
* Wraps the targeted `stigmer.agent.updateSharing()` RPC (authorized by
|
|
64
|
-
* `can_edit`) with loading and error state management. The hook is
|
|
65
|
-
* stateless with respect to the agent — the caller refreshes the resource
|
|
66
|
-
* after a successful update (e.g. via `refetch` from `useAgent`), matching
|
|
67
|
-
* the {@link useUpdateVisibility} convention.
|
|
68
|
-
*
|
|
69
|
-
* Pass `null` for `agentId` to produce a stable no-op (useful while the
|
|
70
|
-
* agent is still loading).
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```tsx
|
|
74
|
-
* const { updateSharing, isPending } = useUpdateAgentSharing(agent.metadata.id);
|
|
75
|
-
*
|
|
76
|
-
* await updateSharing({
|
|
77
|
-
* enabled: true,
|
|
78
|
-
* audience: "public",
|
|
79
|
-
* allowedOrigins: ["https://example.com"],
|
|
80
|
-
* messages: { rateLimited: "", unavailable: "", conversationEnded: "" },
|
|
81
|
-
* });
|
|
82
|
-
* refetch();
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
85
|
-
export declare function useUpdateAgentSharing(agentId: string | null): UseUpdateAgentSharingReturn;
|
|
86
|
-
//# sourceMappingURL=useUpdateAgentSharing.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useUpdateAgentSharing.d.ts","sourceRoot":"","sources":["../../src/sharing/useUpdateAgentSharing.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oDAAoD,CAAC;AAEhF,OAAO,EACL,oBAAoB,EAGrB,MAAM,qDAAqD,CAAC;AAI7D;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE/C;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE;QACjB,2DAA2D;QAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,yEAAyE;QACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,2EAA2E;QAC3E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;KACpC,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,oBAAoB,GAAG,SAAS,GACzC,eAAe,CAEjB;AAQD,qDAAqD;AACrD,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IACjF,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,2BAA2B,CAsC7B"}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useCallback, useState } from "react";
|
|
3
|
-
import { create } from "@bufbuild/protobuf";
|
|
4
|
-
import { UpdateAgentSharingInputSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/io_pb";
|
|
5
|
-
import { AgentSharingAudience, AgentSharingSchema, AgentSharingMessagesSchema, } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
6
|
-
import { useStigmer } from "../hooks.js";
|
|
7
|
-
import { toError } from "../internal/toError.js";
|
|
8
|
-
/**
|
|
9
|
-
* Maps a proto {@link AgentSharingAudience} to the SDK's string union.
|
|
10
|
-
* Unspecified means public by contract (pre-audience shares keep their
|
|
11
|
-
* anyone-with-link behavior).
|
|
12
|
-
*/
|
|
13
|
-
export function sharingAudienceFromProto(audience) {
|
|
14
|
-
return audience === AgentSharingAudience.org ? "org" : "public";
|
|
15
|
-
}
|
|
16
|
-
function sharingAudienceToProto(audience) {
|
|
17
|
-
return audience === "org"
|
|
18
|
-
? AgentSharingAudience.org
|
|
19
|
-
: AgentSharingAudience.public;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Behavior hook that updates an agent's sharing configuration.
|
|
23
|
-
*
|
|
24
|
-
* Wraps the targeted `stigmer.agent.updateSharing()` RPC (authorized by
|
|
25
|
-
* `can_edit`) with loading and error state management. The hook is
|
|
26
|
-
* stateless with respect to the agent — the caller refreshes the resource
|
|
27
|
-
* after a successful update (e.g. via `refetch` from `useAgent`), matching
|
|
28
|
-
* the {@link useUpdateVisibility} convention.
|
|
29
|
-
*
|
|
30
|
-
* Pass `null` for `agentId` to produce a stable no-op (useful while the
|
|
31
|
-
* agent is still loading).
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```tsx
|
|
35
|
-
* const { updateSharing, isPending } = useUpdateAgentSharing(agent.metadata.id);
|
|
36
|
-
*
|
|
37
|
-
* await updateSharing({
|
|
38
|
-
* enabled: true,
|
|
39
|
-
* audience: "public",
|
|
40
|
-
* allowedOrigins: ["https://example.com"],
|
|
41
|
-
* messages: { rateLimited: "", unavailable: "", conversationEnded: "" },
|
|
42
|
-
* });
|
|
43
|
-
* refetch();
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
46
|
-
export function useUpdateAgentSharing(agentId) {
|
|
47
|
-
const stigmer = useStigmer();
|
|
48
|
-
const [isPending, setIsPending] = useState(false);
|
|
49
|
-
const [error, setError] = useState(null);
|
|
50
|
-
const updateSharing = useCallback(async (draft) => {
|
|
51
|
-
if (!agentId)
|
|
52
|
-
return undefined;
|
|
53
|
-
setIsPending(true);
|
|
54
|
-
setError(null);
|
|
55
|
-
try {
|
|
56
|
-
const input = create(UpdateAgentSharingInputSchema, {
|
|
57
|
-
resourceId: agentId,
|
|
58
|
-
sharing: create(AgentSharingSchema, {
|
|
59
|
-
enabled: draft.enabled,
|
|
60
|
-
audience: sharingAudienceToProto(draft.audience),
|
|
61
|
-
allowedOrigins: [...draft.allowedOrigins],
|
|
62
|
-
messages: create(AgentSharingMessagesSchema, {
|
|
63
|
-
rateLimited: draft.messages.rateLimited,
|
|
64
|
-
unavailable: draft.messages.unavailable,
|
|
65
|
-
conversationEnded: draft.messages.conversationEnded,
|
|
66
|
-
}),
|
|
67
|
-
}),
|
|
68
|
-
});
|
|
69
|
-
return await stigmer.agent.updateSharing(input);
|
|
70
|
-
}
|
|
71
|
-
catch (err) {
|
|
72
|
-
setError(toError(err));
|
|
73
|
-
throw err;
|
|
74
|
-
}
|
|
75
|
-
finally {
|
|
76
|
-
setIsPending(false);
|
|
77
|
-
}
|
|
78
|
-
}, [agentId, stigmer]);
|
|
79
|
-
return { updateSharing, isPending, error };
|
|
80
|
-
}
|
|
81
|
-
//# sourceMappingURL=useUpdateAgentSharing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useUpdateAgentSharing.js","sourceRoot":"","sources":["../../src/sharing/useUpdateAgentSharing.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,6BAA6B,EAAE,MAAM,mDAAmD,CAAC;AAClG,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,qDAAqD,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AA2CjD;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAA0C;IAE1C,OAAO,QAAQ,KAAK,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClE,CAAC;AAED,SAAS,sBAAsB,CAAC,QAAyB;IACvD,OAAO,QAAQ,KAAK,KAAK;QACvB,CAAC,CAAC,oBAAoB,CAAC,GAAG;QAC1B,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC;AAClC,CAAC;AAeD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAsB;IAEtB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,aAAa,GAAG,WAAW,CAC/B,KAAK,EAAE,KAAwB,EAA8B,EAAE;QAC7D,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAE/B,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,CAAC,6BAA6B,EAAE;gBAClD,UAAU,EAAE,OAAO;gBACnB,OAAO,EAAE,MAAM,CAAC,kBAAkB,EAAE;oBAClC,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,QAAQ,EAAE,sBAAsB,CAAC,KAAK,CAAC,QAAQ,CAAC;oBAChD,cAAc,EAAE,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC;oBACzC,QAAQ,EAAE,MAAM,CAAC,0BAA0B,EAAE;wBAC3C,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW;wBACvC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW;wBACvC,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,iBAAiB;qBACpD,CAAC;iBACH,CAAC;aACH,CAAC,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,OAAO,EAAE,OAAO,CAAC,CACnB,CAAC;IAEF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
import { renderHook, act, waitFor } from "@testing-library/react";
|
|
3
|
-
import type { ReactNode } from "react";
|
|
4
|
-
import type { UpdateAgentSharingInput } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/io_pb";
|
|
5
|
-
import { AgentSharingAudience } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
6
|
-
import { StigmerContext } from "../../context";
|
|
7
|
-
import {
|
|
8
|
-
sharingAudienceFromProto,
|
|
9
|
-
useUpdateAgentSharing,
|
|
10
|
-
type AgentSharingDraft,
|
|
11
|
-
} from "../useUpdateAgentSharing";
|
|
12
|
-
|
|
13
|
-
function createMockStigmer(overrides: {
|
|
14
|
-
updateSharing?: (input: UpdateAgentSharingInput) => Promise<unknown>;
|
|
15
|
-
} = {}) {
|
|
16
|
-
return {
|
|
17
|
-
agent: {
|
|
18
|
-
updateSharing:
|
|
19
|
-
overrides.updateSharing ?? vi.fn().mockResolvedValue({}),
|
|
20
|
-
},
|
|
21
|
-
} as never;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function wrapper(client: unknown) {
|
|
25
|
-
return function Wrapper({ children }: { children: ReactNode }) {
|
|
26
|
-
return (
|
|
27
|
-
<StigmerContext.Provider value={client as never}>
|
|
28
|
-
{children}
|
|
29
|
-
</StigmerContext.Provider>
|
|
30
|
-
);
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const FULL_DRAFT: AgentSharingDraft = {
|
|
35
|
-
enabled: true,
|
|
36
|
-
audience: "public",
|
|
37
|
-
allowedOrigins: ["https://example.com", "https://docs.example.com"],
|
|
38
|
-
messages: {
|
|
39
|
-
rateLimited: "Slow down, please.",
|
|
40
|
-
unavailable: "We're out of credits.",
|
|
41
|
-
conversationEnded: "This conversation has ended.",
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
describe("useUpdateAgentSharing", () => {
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
vi.restoreAllMocks();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("sends the complete sharing block — enabled, origins, and messages", async () => {
|
|
51
|
-
const updateSharing = vi.fn().mockResolvedValue({});
|
|
52
|
-
const client = createMockStigmer({ updateSharing });
|
|
53
|
-
|
|
54
|
-
const { result } = renderHook(() => useUpdateAgentSharing("agt_1"), {
|
|
55
|
-
wrapper: wrapper(client),
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
await act(() => result.current.updateSharing(FULL_DRAFT));
|
|
59
|
-
|
|
60
|
-
expect(updateSharing).toHaveBeenCalledTimes(1);
|
|
61
|
-
const input = updateSharing.mock.calls[0][0] as UpdateAgentSharingInput;
|
|
62
|
-
expect(input.resourceId).toBe("agt_1");
|
|
63
|
-
expect(input.sharing?.enabled).toBe(true);
|
|
64
|
-
expect(input.sharing?.allowedOrigins).toEqual([
|
|
65
|
-
"https://example.com",
|
|
66
|
-
"https://docs.example.com",
|
|
67
|
-
]);
|
|
68
|
-
expect(input.sharing?.messages?.rateLimited).toBe("Slow down, please.");
|
|
69
|
-
expect(input.sharing?.messages?.unavailable).toBe("We're out of credits.");
|
|
70
|
-
expect(input.sharing?.messages?.conversationEnded).toBe(
|
|
71
|
-
"This conversation has ended.",
|
|
72
|
-
);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("disabling still carries origins, messages, and audience (toggle never clobbers config)", async () => {
|
|
76
|
-
const updateSharing = vi.fn().mockResolvedValue({});
|
|
77
|
-
const client = createMockStigmer({ updateSharing });
|
|
78
|
-
|
|
79
|
-
const { result } = renderHook(() => useUpdateAgentSharing("agt_1"), {
|
|
80
|
-
wrapper: wrapper(client),
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
await act(() =>
|
|
84
|
-
result.current.updateSharing({
|
|
85
|
-
...FULL_DRAFT,
|
|
86
|
-
enabled: false,
|
|
87
|
-
audience: "org",
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const input = updateSharing.mock.calls[0][0] as UpdateAgentSharingInput;
|
|
92
|
-
expect(input.sharing?.enabled).toBe(false);
|
|
93
|
-
// The RPC replaces spec.sharing wholesale — a disable that dropped
|
|
94
|
-
// these fields would silently erase the owner's configuration (an
|
|
95
|
-
// audience drop would silently revert an org-only agent to public).
|
|
96
|
-
expect(input.sharing?.allowedOrigins).toEqual(FULL_DRAFT.allowedOrigins);
|
|
97
|
-
expect(input.sharing?.messages?.rateLimited).toBe(
|
|
98
|
-
FULL_DRAFT.messages.rateLimited,
|
|
99
|
-
);
|
|
100
|
-
expect(input.sharing?.audience).toBe(AgentSharingAudience.org);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("maps the audience union to the proto enum, writing public explicitly", async () => {
|
|
104
|
-
const updateSharing = vi.fn().mockResolvedValue({});
|
|
105
|
-
const client = createMockStigmer({ updateSharing });
|
|
106
|
-
|
|
107
|
-
const { result } = renderHook(() => useUpdateAgentSharing("agt_1"), {
|
|
108
|
-
wrapper: wrapper(client),
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
await act(() => result.current.updateSharing(FULL_DRAFT));
|
|
112
|
-
await act(() =>
|
|
113
|
-
result.current.updateSharing({ ...FULL_DRAFT, audience: "org" }),
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
const first = updateSharing.mock.calls[0][0] as UpdateAgentSharingInput;
|
|
117
|
-
const second = updateSharing.mock.calls[1][0] as UpdateAgentSharingInput;
|
|
118
|
-
// "public" persists as the explicit enum value, never unspecified —
|
|
119
|
-
// a console-managed share can't be downgraded by a later manifest
|
|
120
|
-
// that relies on the unspecified-means-public default.
|
|
121
|
-
expect(first.sharing?.audience).toBe(AgentSharingAudience.public);
|
|
122
|
-
expect(second.sharing?.audience).toBe(AgentSharingAudience.org);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("is a stable no-op when agentId is null", async () => {
|
|
126
|
-
const updateSharing = vi.fn();
|
|
127
|
-
const client = createMockStigmer({ updateSharing });
|
|
128
|
-
|
|
129
|
-
const { result } = renderHook(() => useUpdateAgentSharing(null), {
|
|
130
|
-
wrapper: wrapper(client),
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
const returned = await act(() => result.current.updateSharing(FULL_DRAFT));
|
|
134
|
-
expect(returned).toBeUndefined();
|
|
135
|
-
expect(updateSharing).not.toHaveBeenCalled();
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("exposes isPending during the request", async () => {
|
|
139
|
-
let resolveRpc: (v: unknown) => void = () => {};
|
|
140
|
-
const updateSharing = vi.fn().mockReturnValue(
|
|
141
|
-
new Promise((resolve) => {
|
|
142
|
-
resolveRpc = resolve;
|
|
143
|
-
}),
|
|
144
|
-
);
|
|
145
|
-
const client = createMockStigmer({ updateSharing });
|
|
146
|
-
|
|
147
|
-
const { result } = renderHook(() => useUpdateAgentSharing("agt_1"), {
|
|
148
|
-
wrapper: wrapper(client),
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
let pending: Promise<unknown>;
|
|
152
|
-
act(() => {
|
|
153
|
-
pending = result.current.updateSharing(FULL_DRAFT);
|
|
154
|
-
});
|
|
155
|
-
expect(result.current.isPending).toBe(true);
|
|
156
|
-
|
|
157
|
-
await act(async () => {
|
|
158
|
-
resolveRpc({});
|
|
159
|
-
await pending;
|
|
160
|
-
});
|
|
161
|
-
expect(result.current.isPending).toBe(false);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it("captures and rethrows RPC errors", async () => {
|
|
165
|
-
const failure = new Error("permission denied");
|
|
166
|
-
const updateSharing = vi.fn().mockRejectedValue(failure);
|
|
167
|
-
const client = createMockStigmer({ updateSharing });
|
|
168
|
-
|
|
169
|
-
const { result } = renderHook(() => useUpdateAgentSharing("agt_1"), {
|
|
170
|
-
wrapper: wrapper(client),
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
let caught: unknown;
|
|
174
|
-
await act(async () => {
|
|
175
|
-
try {
|
|
176
|
-
await result.current.updateSharing(FULL_DRAFT);
|
|
177
|
-
} catch (err) {
|
|
178
|
-
caught = err;
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
expect(caught).toBe(failure);
|
|
183
|
-
await waitFor(() => expect(result.current.error).toBe(failure));
|
|
184
|
-
expect(result.current.isPending).toBe(false);
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
describe("sharingAudienceFromProto", () => {
|
|
189
|
-
it("maps unspecified to public (pre-audience shares keep their behavior)", () => {
|
|
190
|
-
expect(sharingAudienceFromProto(undefined)).toBe("public");
|
|
191
|
-
expect(sharingAudienceFromProto(AgentSharingAudience.unspecified)).toBe(
|
|
192
|
-
"public",
|
|
193
|
-
);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it("maps the explicit values", () => {
|
|
197
|
-
expect(sharingAudienceFromProto(AgentSharingAudience.public)).toBe("public");
|
|
198
|
-
expect(sharingAudienceFromProto(AgentSharingAudience.org)).toBe("org");
|
|
199
|
-
});
|
|
200
|
-
});
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useCallback, useState } from "react";
|
|
4
|
-
import { create } from "@bufbuild/protobuf";
|
|
5
|
-
import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
6
|
-
import { UpdateAgentSharingInputSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/io_pb";
|
|
7
|
-
import {
|
|
8
|
-
AgentSharingAudience,
|
|
9
|
-
AgentSharingSchema,
|
|
10
|
-
AgentSharingMessagesSchema,
|
|
11
|
-
} from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
12
|
-
import { useStigmer } from "../hooks.js";
|
|
13
|
-
import { toError } from "../internal/toError.js";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Who can chat with a shared agent over its hosted link.
|
|
17
|
-
*
|
|
18
|
-
* - `"public"` — anyone with the link; visitors are anonymous guests.
|
|
19
|
-
* - `"org"` — signed-in members of the owning organization only.
|
|
20
|
-
* Membership is checked on every conversation turn, so access ends the
|
|
21
|
-
* moment a member leaves the org.
|
|
22
|
-
*/
|
|
23
|
-
export type SharingAudience = "public" | "org";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* A complete sharing configuration to persist.
|
|
27
|
-
*
|
|
28
|
-
* Every field is required by design: the `updateSharing` RPC **replaces**
|
|
29
|
-
* the agent's whole `spec.sharing` block, so a caller must always supply
|
|
30
|
-
* the full configuration. A partial type here would let a toggle change
|
|
31
|
-
* silently wipe `allowedOrigins`, `messages`, or the `audience` — the
|
|
32
|
-
* required shape makes that mistake unrepresentable.
|
|
33
|
-
*/
|
|
34
|
-
export interface AgentSharingDraft {
|
|
35
|
-
/** Whether hosted-chat access for the configured audience is enabled. */
|
|
36
|
-
readonly enabled: boolean;
|
|
37
|
-
/** Who can chat: anyone with the link, or org members only. */
|
|
38
|
-
readonly audience: SharingAudience;
|
|
39
|
-
/**
|
|
40
|
-
* Exact web origins allowed to embed the shared agent
|
|
41
|
-
* (e.g. `https://example.com`). Stored now; enforced by the embed
|
|
42
|
-
* widget's Origin check. Embedding is public-audience only.
|
|
43
|
-
*/
|
|
44
|
-
readonly allowedOrigins: readonly string[];
|
|
45
|
-
/** Owner-customized visitor refusal copy. Empty strings mean platform defaults. */
|
|
46
|
-
readonly messages: {
|
|
47
|
-
/** Shown when a visitor exceeds the message rate limit. */
|
|
48
|
-
readonly rateLimited: string;
|
|
49
|
-
/** Shown when the org's credits are exhausted (sharing fails closed). */
|
|
50
|
-
readonly unavailable: string;
|
|
51
|
-
/** Shown when a conversation hits its turn limit or inactivity timeout. */
|
|
52
|
-
readonly conversationEnded: string;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Maps a proto {@link AgentSharingAudience} to the SDK's string union.
|
|
58
|
-
* Unspecified means public by contract (pre-audience shares keep their
|
|
59
|
-
* anyone-with-link behavior).
|
|
60
|
-
*/
|
|
61
|
-
export function sharingAudienceFromProto(
|
|
62
|
-
audience: AgentSharingAudience | undefined,
|
|
63
|
-
): SharingAudience {
|
|
64
|
-
return audience === AgentSharingAudience.org ? "org" : "public";
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function sharingAudienceToProto(audience: SharingAudience): AgentSharingAudience {
|
|
68
|
-
return audience === "org"
|
|
69
|
-
? AgentSharingAudience.org
|
|
70
|
-
: AgentSharingAudience.public;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** Return value of {@link useUpdateAgentSharing}. */
|
|
74
|
-
export interface UseUpdateAgentSharingReturn {
|
|
75
|
-
/**
|
|
76
|
-
* Persist the complete sharing configuration via the `updateSharing`
|
|
77
|
-
* RPC. Resolves with the updated agent.
|
|
78
|
-
*/
|
|
79
|
-
readonly updateSharing: (draft: AgentSharingDraft) => Promise<Agent | undefined>;
|
|
80
|
-
/** `true` while the RPC is in flight. */
|
|
81
|
-
readonly isPending: boolean;
|
|
82
|
-
/** The last error from the RPC, or `null`. */
|
|
83
|
-
readonly error: Error | null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Behavior hook that updates an agent's sharing configuration.
|
|
88
|
-
*
|
|
89
|
-
* Wraps the targeted `stigmer.agent.updateSharing()` RPC (authorized by
|
|
90
|
-
* `can_edit`) with loading and error state management. The hook is
|
|
91
|
-
* stateless with respect to the agent — the caller refreshes the resource
|
|
92
|
-
* after a successful update (e.g. via `refetch` from `useAgent`), matching
|
|
93
|
-
* the {@link useUpdateVisibility} convention.
|
|
94
|
-
*
|
|
95
|
-
* Pass `null` for `agentId` to produce a stable no-op (useful while the
|
|
96
|
-
* agent is still loading).
|
|
97
|
-
*
|
|
98
|
-
* @example
|
|
99
|
-
* ```tsx
|
|
100
|
-
* const { updateSharing, isPending } = useUpdateAgentSharing(agent.metadata.id);
|
|
101
|
-
*
|
|
102
|
-
* await updateSharing({
|
|
103
|
-
* enabled: true,
|
|
104
|
-
* audience: "public",
|
|
105
|
-
* allowedOrigins: ["https://example.com"],
|
|
106
|
-
* messages: { rateLimited: "", unavailable: "", conversationEnded: "" },
|
|
107
|
-
* });
|
|
108
|
-
* refetch();
|
|
109
|
-
* ```
|
|
110
|
-
*/
|
|
111
|
-
export function useUpdateAgentSharing(
|
|
112
|
-
agentId: string | null,
|
|
113
|
-
): UseUpdateAgentSharingReturn {
|
|
114
|
-
const stigmer = useStigmer();
|
|
115
|
-
const [isPending, setIsPending] = useState(false);
|
|
116
|
-
const [error, setError] = useState<Error | null>(null);
|
|
117
|
-
|
|
118
|
-
const updateSharing = useCallback(
|
|
119
|
-
async (draft: AgentSharingDraft): Promise<Agent | undefined> => {
|
|
120
|
-
if (!agentId) return undefined;
|
|
121
|
-
|
|
122
|
-
setIsPending(true);
|
|
123
|
-
setError(null);
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const input = create(UpdateAgentSharingInputSchema, {
|
|
127
|
-
resourceId: agentId,
|
|
128
|
-
sharing: create(AgentSharingSchema, {
|
|
129
|
-
enabled: draft.enabled,
|
|
130
|
-
audience: sharingAudienceToProto(draft.audience),
|
|
131
|
-
allowedOrigins: [...draft.allowedOrigins],
|
|
132
|
-
messages: create(AgentSharingMessagesSchema, {
|
|
133
|
-
rateLimited: draft.messages.rateLimited,
|
|
134
|
-
unavailable: draft.messages.unavailable,
|
|
135
|
-
conversationEnded: draft.messages.conversationEnded,
|
|
136
|
-
}),
|
|
137
|
-
}),
|
|
138
|
-
});
|
|
139
|
-
return await stigmer.agent.updateSharing(input);
|
|
140
|
-
} catch (err) {
|
|
141
|
-
setError(toError(err));
|
|
142
|
-
throw err;
|
|
143
|
-
} finally {
|
|
144
|
-
setIsPending(false);
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
[agentId, stigmer],
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
return { updateSharing, isPending, error };
|
|
151
|
-
}
|