@stigmer/sdk 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 (58) hide show
  1. package/__tests__/errors.test.js +42 -0
  2. package/__tests__/errors.test.js.map +1 -1
  3. package/__tests__/guest-auth.test.d.ts +2 -0
  4. package/__tests__/guest-auth.test.d.ts.map +1 -0
  5. package/__tests__/guest-auth.test.js +223 -0
  6. package/__tests__/guest-auth.test.js.map +1 -0
  7. package/__tests__/sharing.test.d.ts +2 -0
  8. package/__tests__/sharing.test.d.ts.map +1 -0
  9. package/__tests__/sharing.test.js +106 -0
  10. package/__tests__/sharing.test.js.map +1 -0
  11. package/gen/agentshare.d.ts +45 -0
  12. package/gen/agentshare.d.ts.map +1 -0
  13. package/gen/agentshare.js +142 -0
  14. package/gen/agentshare.js.map +1 -0
  15. package/gen/authorization-config.d.ts.map +1 -1
  16. package/gen/authorization-config.js +1 -0
  17. package/gen/authorization-config.js.map +1 -1
  18. package/gen/client.d.ts +4 -0
  19. package/gen/client.d.ts.map +1 -1
  20. package/gen/client.js +4 -0
  21. package/gen/client.js.map +1 -1
  22. package/gen/environment.d.ts +2 -0
  23. package/gen/environment.d.ts.map +1 -1
  24. package/gen/environment.js +8 -0
  25. package/gen/environment.js.map +1 -1
  26. package/gen/platformclient.d.ts +2 -1
  27. package/gen/platformclient.d.ts.map +1 -1
  28. package/gen/platformclient.js +8 -0
  29. package/gen/platformclient.js.map +1 -1
  30. package/gen/session.d.ts +2 -2
  31. package/gen/session.d.ts.map +1 -1
  32. package/gen/session.js +2 -2
  33. package/gen/session.js.map +1 -1
  34. package/guest-auth.d.ts +175 -0
  35. package/guest-auth.d.ts.map +1 -0
  36. package/guest-auth.js +227 -0
  37. package/guest-auth.js.map +1 -0
  38. package/index.d.ts +3 -0
  39. package/index.d.ts.map +1 -1
  40. package/index.js +5 -0
  41. package/index.js.map +1 -1
  42. package/package.json +2 -2
  43. package/sharing.d.ts +76 -0
  44. package/sharing.d.ts.map +1 -0
  45. package/sharing.js +117 -0
  46. package/sharing.js.map +1 -0
  47. package/src/__tests__/errors.test.ts +56 -0
  48. package/src/__tests__/guest-auth.test.ts +287 -0
  49. package/src/__tests__/sharing.test.ts +159 -0
  50. package/src/gen/agentshare.ts +148 -0
  51. package/src/gen/authorization-config.ts +1 -0
  52. package/src/gen/client.ts +5 -0
  53. package/src/gen/environment.ts +7 -1
  54. package/src/gen/platformclient.ts +7 -1
  55. package/src/gen/session.ts +3 -3
  56. package/src/guest-auth.ts +334 -0
  57. package/src/index.ts +25 -0
  58. package/src/sharing.ts +135 -0
package/src/sharing.ts ADDED
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Agent-sharing helpers — the single source of truth for the hosted chat
3
+ * URL shape, the embed snippet, and client-side `allowed_origins`
4
+ * validation. Framework-free by design: consumed by the web console and
5
+ * desktop app (via `@stigmer/react`), the `stigmer` CLI, and any platform
6
+ * builder that wants to construct share links or embed snippets itself.
7
+ *
8
+ * The canonical URL shape is `<app-origin>/chat/<org>/<slug>` (a T01
9
+ * design decision), and `embed.js` is served from the root of that same
10
+ * app origin (T04). Callers supply the origin — resolving it is a host
11
+ * concern (the console knows its `appUrl`, the CLI resolves it from the
12
+ * backend type) — while the path and snippet shapes live here so every
13
+ * surface emits byte-identical output.
14
+ */
15
+
16
+ /** Maximum number of allowed origins (proto: `repeated.max_items = 32`). */
17
+ export const MAX_ALLOWED_ORIGINS = 32;
18
+
19
+ /**
20
+ * Exact web origin: scheme://host[:port] — no path, query, fragment, or
21
+ * trailing slash. Mirrors the CEL expression `allowed_origins.format` on
22
+ * `AgentShareSpec` (`apis/ai/stigmer/agentic/agentshare/v1/spec.proto`).
23
+ *
24
+ * The proto is the source of truth — if the CEL expression changes, this
25
+ * pattern must change with it. Mirroring it client-side gives immediate
26
+ * feedback instead of a round-trip rejection.
27
+ */
28
+ const ORIGIN_PATTERN =
29
+ /^https?:\/\/[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*(:[0-9]{1,5})?$/;
30
+
31
+ /**
32
+ * Validate a single `allowed_origins` entry.
33
+ *
34
+ * Returns `null` when valid, or a user-facing message explaining what
35
+ * to fix (DD-006: errors state what happened and what to do).
36
+ */
37
+ export function validateOrigin(value: string): string | null {
38
+ const trimmed = value.trim();
39
+ if (!trimmed) return "Enter an origin, like https://example.com";
40
+ if (!ORIGIN_PATTERN.test(trimmed)) {
41
+ return "Must be an exact web origin like https://example.com — no path, query, or trailing slash";
42
+ }
43
+ return null;
44
+ }
45
+
46
+ /**
47
+ * Query parameter carrying the share-link token on a locked link:
48
+ * `/chat/<org>/<slug>?k=<token>`. Short by design — the token rides every
49
+ * copied link, and `k` (for "key") is the platform's one-character
50
+ * convention, mirrored by the hosted page and the embed widget.
51
+ */
52
+ export const LINK_TOKEN_PARAM = "k";
53
+
54
+ /**
55
+ * The hosted chat page path for a shared agent: `/chat/<org>/<slug>`
56
+ * (the AgentShare's org and slug — the slug defaults to the agent's),
57
+ * plus `?k=<token>` when the share link is locked with a rotatable
58
+ * token (`AgentShareStatus.share_link_token`).
59
+ *
60
+ * Useful on its own when the caller renders relative to the current
61
+ * origin (e.g. a host that never configured an absolute app URL).
62
+ */
63
+ export function chatPath(org: string, slug: string, linkToken?: string): string {
64
+ const path = `/chat/${org}/${slug}`;
65
+ return linkToken
66
+ ? `${path}?${LINK_TOKEN_PARAM}=${encodeURIComponent(linkToken)}`
67
+ : path;
68
+ }
69
+
70
+ /**
71
+ * The absolute hosted chat URL for a shared agent:
72
+ * `<appOrigin>/chat/<org>/<slug>[?k=<token>]`.
73
+ *
74
+ * A trailing slash on `appOrigin` is tolerated so callers can pass
75
+ * user-configured values verbatim. An empty `appOrigin` degrades to the
76
+ * relative {@link chatPath} — the same graceful fallback a host without a
77
+ * configured public origin gets in the share dialog.
78
+ */
79
+ export function buildChatUrl(
80
+ appOrigin: string,
81
+ org: string,
82
+ slug: string,
83
+ linkToken?: string,
84
+ ): string {
85
+ return stripTrailingSlash(appOrigin) + chatPath(org, slug, linkToken);
86
+ }
87
+
88
+ /**
89
+ * Append the share-link token to an already-built chat URL.
90
+ *
91
+ * For hosts that construct the base URL through their own callback (the
92
+ * share dialog's `buildShareUrl` prop) rather than {@link buildChatUrl}.
93
+ * A `null`/empty token returns the URL unchanged, so callers can pass
94
+ * `share.status?.shareLinkToken` straight through. Emits the identical
95
+ * `?k=` shape as {@link chatPath} — one URL grammar across every surface.
96
+ */
97
+ export function appendLinkToken(url: string, linkToken: string | null | undefined): string {
98
+ if (!linkToken) return url;
99
+ const separator = url.includes("?") ? "&" : "?";
100
+ return `${url}${separator}${LINK_TOKEN_PARAM}=${encodeURIComponent(linkToken)}`;
101
+ }
102
+
103
+ /**
104
+ * The embed loader URL: `embed.js` lives at the root of the app origin
105
+ * (the loader derives the chat-page origin from its own script URL, so
106
+ * the two must share an origin). An empty `appOrigin` degrades to the
107
+ * relative `/embed.js`.
108
+ */
109
+ export function buildEmbedLoaderUrl(appOrigin: string): string {
110
+ return `${stripTrailingSlash(appOrigin)}/embed.js`;
111
+ }
112
+
113
+ /**
114
+ * The two-line embed snippet an owner pastes into any website: the
115
+ * loader script plus the `<stigmer-agent>` element where the widget
116
+ * renders. A locked share link adds the `token` attribute, which the
117
+ * widget forwards as `?k=` on its iframe URL. Every surface (share
118
+ * dialog, CLI, docs) emits exactly this.
119
+ */
120
+ export function buildEmbedSnippet(
121
+ appOrigin: string,
122
+ org: string,
123
+ slug: string,
124
+ linkToken?: string,
125
+ ): string {
126
+ const tokenAttribute = linkToken ? ` token="${linkToken}"` : "";
127
+ return [
128
+ `<script src="${buildEmbedLoaderUrl(appOrigin)}" async></script>`,
129
+ `<stigmer-agent org="${org}" agent="${slug}"${tokenAttribute}></stigmer-agent>`,
130
+ ].join("\n");
131
+ }
132
+
133
+ function stripTrailingSlash(origin: string): string {
134
+ return origin.endsWith("/") ? origin.slice(0, -1) : origin;
135
+ }