sideagent 0.2.0 → 0.4.0

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/README.md CHANGED
@@ -45,6 +45,16 @@ import { AgentChat } from "sideagent";
45
45
  />
46
46
  ```
47
47
 
48
+ ### sideagent Cloud
49
+
50
+ With an agent hosted on sideagent Cloud, pass its publishable key instead of `endpoint`. The key names the agent and its host, so the chat derives the URL (`https://<host>/v1/agents/<agentId>`) and sends the key in the `x-sideagent-key` header on every request. The key is public: it is safe in the browser and proves nothing on its own.
51
+
52
+ ```tsx
53
+ <AgentChat publishableKey="pk_live_…" />
54
+ ```
55
+
56
+ Pass `endpoint` as well to send the requests somewhere else, such as a proxy in front of sideagent Cloud. A malformed key, or neither prop, throws during render. `parsePublishableKey` and `publishableEndpoint` are exported from `sideagent/keys`.
57
+
48
58
  ### Docked sidebar
49
59
 
50
60
  Wrap your app in `AgentProvider` to dock the chat on the right, side by side with the app instead of over it. It takes the same props as `AgentChat`. The user drags the panel's left edge (or uses the arrow keys on it) to resize; the width is remembered. Outside `AgentProvider`, sidebar mode overlays the page.
@@ -0,0 +1,10 @@
1
+ // src/server/message-text.ts
2
+ function messageText(content) {
3
+ if (typeof content === "string") return content;
4
+ if (!Array.isArray(content)) return "";
5
+ return content.map((p) => p?.type === "text" && typeof p.text === "string" ? p.text : "").join("");
6
+ }
7
+
8
+ export {
9
+ messageText
10
+ };
@@ -0,0 +1,43 @@
1
+ // src/keys.ts
2
+ var PUBLISHABLE_KEY_HEADER = "x-sideagent-key";
3
+ var AGENT_ID = /^agt_[a-z0-9]{16}$/;
4
+ var HOST = /^[a-z0-9.-]+(:\d+)?$/i;
5
+ var LOOPBACK = /^(localhost|127\.0\.0\.1)(:\d+)?$/i;
6
+ function b64url(s) {
7
+ let bin = "";
8
+ for (const b of new TextEncoder().encode(s)) bin += String.fromCharCode(b);
9
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
10
+ }
11
+ function fromB64url(s) {
12
+ const bin = atob(s.replace(/-/g, "+").replace(/_/g, "/"));
13
+ return new TextDecoder("utf-8", { fatal: true }).decode(Uint8Array.from(bin, (c) => c.charCodeAt(0)));
14
+ }
15
+ function publishableKey(environment, host, agentId) {
16
+ return `pk_${environment}_${b64url(`${host}$${agentId}`)}`;
17
+ }
18
+ function parsePublishableKey(key) {
19
+ const m = /^pk_(test|live)_([A-Za-z0-9_-]+)$/.exec(key);
20
+ if (!m) return null;
21
+ let decoded;
22
+ try {
23
+ decoded = fromB64url(m[2]);
24
+ } catch {
25
+ return null;
26
+ }
27
+ const at = decoded.lastIndexOf("$");
28
+ if (at <= 0) return null;
29
+ const host = decoded.slice(0, at);
30
+ const agentId = decoded.slice(at + 1);
31
+ if (!AGENT_ID.test(agentId) || !HOST.test(host)) return null;
32
+ return { environment: m[1], host, agentId };
33
+ }
34
+ function publishableEndpoint({ host, agentId }) {
35
+ return `${LOOPBACK.test(host) ? "http" : "https"}://${host}/v1/agents/${agentId}`;
36
+ }
37
+
38
+ export {
39
+ PUBLISHABLE_KEY_HEADER,
40
+ publishableKey,
41
+ parsePublishableKey,
42
+ publishableEndpoint
43
+ };
package/dist/index.d.ts CHANGED
@@ -32,8 +32,10 @@ interface AgentHooks {
32
32
 
33
33
  type AgentChatMode = "floating" | "sidebar";
34
34
  interface AgentChatProps {
35
- /** URL of your sideagent endpoint, e.g. "/api/agent". */
36
- endpoint: string;
35
+ /** URL of your sideagent endpoint, e.g. "/api/agent". With `publishableKey`, overrides the URL the key names. */
36
+ endpoint?: string;
37
+ /** sideagent Cloud publishable key (`pk_live_…`). Requests go to the agent it names and carry it. */
38
+ publishableKey?: string;
37
39
  /** Starting layout. The user can switch; their choice is remembered. */
38
40
  mode?: AgentChatMode;
39
41
  title?: string;
@@ -59,19 +61,23 @@ interface AgentChatProps {
59
61
  /** Set false to hide the layout switcher. */
60
62
  allowModeSwitch?: boolean;
61
63
  }
62
- interface AgentControls {
63
- open: boolean;
64
- setOpen: (open: boolean) => void;
65
- }
66
- /** Open or close the assistant from anywhere under `AgentProvider`. */
67
- declare function useAgent(): AgentControls;
64
+
65
+ /** The panel shell: open/close, floating or docked layout, resize, history and session loading. */
66
+ declare function AgentChat(props: AgentChatProps): react.JSX.Element;
67
+
68
68
  /** Lays the app and a docked sidebar chat side by side, and shares open state via `useAgent`. Takes the same props as AgentChat. */
69
69
  declare function AgentProvider({ children, className, style, ...chat }: AgentChatProps & {
70
70
  children: ReactNode;
71
71
  className?: string;
72
72
  style?: CSSProperties;
73
73
  }): react.JSX.Element;
74
- declare function AgentChat(props: AgentChatProps): react.JSX.Element;
74
+
75
+ interface AgentControls {
76
+ open: boolean;
77
+ setOpen: (open: boolean) => void;
78
+ }
79
+ /** Open or close the assistant from anywhere under `AgentProvider`. */
80
+ declare function useAgent(): AgentControls;
75
81
 
76
82
  interface TransportOptions {
77
83
  endpoint: string;