@useago/sdk 0.3.1 → 0.3.2

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.
@@ -0,0 +1,181 @@
1
+ //#region src/devtools/initDevPanel.ts
2
+ var stateEl;
3
+ var logEl;
4
+ var getStateFn = () => ({});
5
+ function renderState() {
6
+ if (!stateEl) return;
7
+ stateEl.textContent = JSON.stringify(getStateFn(), null, 2);
8
+ }
9
+ function logLine(text, kind) {
10
+ if (!logEl) return;
11
+ const line = document.createElement("div");
12
+ line.className = `dev-log-line dev-log-${kind}`;
13
+ line.textContent = `${(/* @__PURE__ */ new Date()).toLocaleTimeString()} ${text}`;
14
+ logEl.appendChild(line);
15
+ logEl.scrollTop = logEl.scrollHeight;
16
+ }
17
+ var COLLAPSE_KEY = "devPanelCollapsed";
18
+ function setCollapsed(panel, collapsed) {
19
+ panel.classList.toggle("collapsed", collapsed);
20
+ const toggle = panel.querySelector(".dev-toggle");
21
+ if (toggle) {
22
+ toggle.textContent = collapsed ? "▢" : "—";
23
+ toggle.title = collapsed ? "Expand dev tools" : "Collapse dev tools";
24
+ toggle.setAttribute("aria-expanded", String(!collapsed));
25
+ }
26
+ try {
27
+ localStorage.setItem(COLLAPSE_KEY, collapsed ? "1" : "0");
28
+ } catch {}
29
+ }
30
+ function initDevPanel(options) {
31
+ const { store, client, target } = options;
32
+ getStateFn = store.get;
33
+ injectStyles();
34
+ const host = typeof target === "string" ? document.querySelector(target) : target instanceof Element ? target : document.body;
35
+ const panel = document.createElement("aside");
36
+ panel.id = "dev-panel";
37
+ (host ?? document.body).appendChild(panel);
38
+ panel.innerHTML = `
39
+ <div class="dev-head">
40
+ <span class="dev-badge">DEV</span>
41
+ <span class="dev-title">DEV TOOLS · client-side function state — not for production</span>
42
+ <button type="button" class="dev-toggle" aria-label="Toggle dev tools">—</button>
43
+ </div>
44
+ <div class="dev-body">
45
+ <div class="dev-fns">Registered functions: <code>${(client.getRegisteredFunctions?.() ?? []).map((f) => f.name).join(", ") || "—"}</code></div>
46
+ <div class="dev-section-label">JSON object (built by the agent)</div>
47
+ <pre class="dev-state" id="dev-state"></pre>
48
+ <div class="dev-section-label">Function calls</div>
49
+ <div class="dev-log" id="dev-log"></div>
50
+ </div>
51
+ `;
52
+ stateEl = panel.querySelector("#dev-state");
53
+ logEl = panel.querySelector("#dev-log");
54
+ panel.querySelector(".dev-toggle")?.addEventListener("click", (e) => {
55
+ e.stopPropagation();
56
+ setCollapsed(panel, !panel.classList.contains("collapsed"));
57
+ });
58
+ panel.addEventListener("click", () => {
59
+ if (panel.classList.contains("collapsed")) setCollapsed(panel, false);
60
+ });
61
+ let startCollapsed = false;
62
+ try {
63
+ startCollapsed = localStorage.getItem(COLLAPSE_KEY) === "1";
64
+ } catch {}
65
+ setCollapsed(panel, startCollapsed);
66
+ client.on("function:invoke", ({ functionName, arguments: args }) => {
67
+ logLine(`→ ${functionName}(${JSON.stringify(args ?? {})})`, "invoke");
68
+ });
69
+ client.on("function:result", ({ result, error }) => {
70
+ logLine(error ? `✗ error: ${error}` : `← ${JSON.stringify(result)}`, error ? "error" : "result");
71
+ });
72
+ store.subscribe(renderState);
73
+ renderState();
74
+ }
75
+ var STYLE_ID = "dev-panel-styles";
76
+ function injectStyles() {
77
+ if (document.getElementById(STYLE_ID)) return;
78
+ const style = document.createElement("style");
79
+ style.id = STYLE_ID;
80
+ style.textContent = PANEL_CSS;
81
+ document.head.appendChild(style);
82
+ }
83
+ var PANEL_CSS = `
84
+ #dev-panel {
85
+ position: fixed;
86
+ top: 16px;
87
+ right: 16px;
88
+ width: min(360px, calc(100vw - 32px));
89
+ max-width: calc(100vw - 32px);
90
+ box-sizing: border-box;
91
+ max-height: calc(100vh - 32px);
92
+ display: flex;
93
+ flex-direction: column;
94
+ gap: 8px;
95
+ padding: 12px 14px;
96
+ background: #0f1419;
97
+ color: #d7e0e8;
98
+ border: 1px solid #2a3441;
99
+ border-radius: 12px;
100
+ box-shadow: 0 20px 50px -20px rgba(0,0,0,.6);
101
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
102
+ font-size: 12px;
103
+ z-index: 1000;
104
+ }
105
+ #dev-panel .dev-head { display: flex; align-items: center; gap: 8px; }
106
+ #dev-panel .dev-toggle {
107
+ margin-left: auto;
108
+ flex: none;
109
+ width: 22px;
110
+ height: 22px;
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ background: transparent;
115
+ color: #7c8a99;
116
+ border: 1px solid #2a3441;
117
+ border-radius: 6px;
118
+ font-size: 12px;
119
+ line-height: 1;
120
+ cursor: pointer;
121
+ }
122
+ #dev-panel .dev-toggle:hover { color: #d7e0e8; border-color: #3a4655; }
123
+ #dev-panel .dev-body { display: flex; flex-direction: column; gap: 8px; }
124
+
125
+ /* Collapsed: shrink to a small clickable widget showing only the DEV badge. */
126
+ #dev-panel.collapsed {
127
+ width: auto;
128
+ cursor: pointer;
129
+ padding: 8px 10px;
130
+ }
131
+ #dev-panel.collapsed .dev-title,
132
+ #dev-panel.collapsed .dev-body { display: none; }
133
+ #dev-panel.collapsed .dev-toggle { margin-left: 6px; }
134
+ #dev-panel .dev-badge {
135
+ background: #f59e0b;
136
+ color: #1c1206;
137
+ font-weight: 700;
138
+ font-size: 10px;
139
+ letter-spacing: .08em;
140
+ padding: 2px 6px;
141
+ border-radius: 5px;
142
+ }
143
+ #dev-panel .dev-title { color: #f59e0b; font-size: 11px; line-height: 1.3; }
144
+ #dev-panel .dev-fns { color: #7c8a99; font-size: 11px; }
145
+ #dev-panel .dev-fns code { color: #9ecbff; }
146
+ #dev-panel .dev-section-label {
147
+ color: #7c8a99;
148
+ text-transform: uppercase;
149
+ letter-spacing: .08em;
150
+ font-size: 10px;
151
+ margin-top: 4px;
152
+ }
153
+ #dev-panel .dev-state {
154
+ margin: 0;
155
+ padding: 8px;
156
+ background: #060a0e;
157
+ border-radius: 8px;
158
+ overflow: auto;
159
+ max-height: 40vh;
160
+ white-space: pre;
161
+ color: #c8e6c9;
162
+ }
163
+ #dev-panel .dev-log {
164
+ display: flex;
165
+ flex-direction: column;
166
+ gap: 2px;
167
+ overflow-y: auto;
168
+ max-height: 24vh;
169
+ background: #060a0e;
170
+ border-radius: 8px;
171
+ padding: 6px 8px;
172
+ }
173
+ #dev-panel .dev-log-line { white-space: pre-wrap; word-break: break-word; line-height: 1.4; }
174
+ #dev-panel .dev-log-invoke { color: #9ecbff; }
175
+ #dev-panel .dev-log-result { color: #86efac; }
176
+ #dev-panel .dev-log-error { color: #fca5a5; }
177
+ `;
178
+ //#endregion
179
+ export { initDevPanel };
180
+
181
+ //# sourceMappingURL=devtools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devtools.js","names":[],"sources":["../src/devtools/initDevPanel.ts"],"sourcesContent":["import type { AgoClient } from \"../client/AgoClient\";\nimport type { Store } from \"../state/createStore\";\n\n/** Options for {@link initDevPanel}. */\nexport interface DevPanelOptions {\n /** The store whose state the panel renders live. */\n store: Store<unknown>;\n /**\n * Client to read registered functions from and listen to function events on.\n * Typed structurally so a mock client works too.\n */\n client: Pick<AgoClient, \"on\" | \"getRegisteredFunctions\">;\n /** Where to mount: a CSS selector, an Element, or `document.body` (default). */\n target?: string | Element;\n}\n\nlet stateEl: HTMLElement | null;\nlet logEl: HTMLElement | null;\nlet getStateFn: () => unknown = () => ({});\n\n// Re-render the JSON object. Wired to the store's subscribe() in initDevPanel.\nfunction renderState(): void {\n if (!stateEl) return;\n stateEl.textContent = JSON.stringify(getStateFn(), null, 2);\n}\n\nfunction logLine(text: string, kind: \"invoke\" | \"result\" | \"error\"): void {\n if (!logEl) return;\n const line = document.createElement(\"div\");\n line.className = `dev-log-line dev-log-${kind}`;\n const time = new Date().toLocaleTimeString();\n line.textContent = `${time} ${text}`;\n logEl.appendChild(line);\n logEl.scrollTop = logEl.scrollHeight;\n}\n\nconst COLLAPSE_KEY = \"devPanelCollapsed\";\n\nfunction setCollapsed(panel: HTMLElement, collapsed: boolean): void {\n panel.classList.toggle(\"collapsed\", collapsed);\n const toggle = panel.querySelector<HTMLButtonElement>(\".dev-toggle\");\n if (toggle) {\n toggle.textContent = collapsed ? \"▢\" : \"—\";\n toggle.title = collapsed ? \"Expand dev tools\" : \"Collapse dev tools\";\n toggle.setAttribute(\"aria-expanded\", String(!collapsed));\n }\n try {\n localStorage.setItem(COLLAPSE_KEY, collapsed ? \"1\" : \"0\");\n } catch {\n // localStorage may be unavailable; collapse state just won't persist.\n }\n}\n\nexport function initDevPanel(options: DevPanelOptions): void {\n const { store, client, target } = options;\n getStateFn = store.get;\n injectStyles();\n const host =\n typeof target === \"string\"\n ? document.querySelector(target)\n : target instanceof Element\n ? target\n : document.body;\n const panel = document.createElement(\"aside\");\n panel.id = \"dev-panel\";\n (host ?? document.body).appendChild(panel);\n\n const registered = client.getRegisteredFunctions?.() ?? [];\n const fnNames = registered.map((f) => f.name).join(\", \") || \"—\";\n\n panel.innerHTML = `\n <div class=\"dev-head\">\n <span class=\"dev-badge\">DEV</span>\n <span class=\"dev-title\">DEV TOOLS · client-side function state — not for production</span>\n <button type=\"button\" class=\"dev-toggle\" aria-label=\"Toggle dev tools\">—</button>\n </div>\n <div class=\"dev-body\">\n <div class=\"dev-fns\">Registered functions: <code>${fnNames}</code></div>\n <div class=\"dev-section-label\">JSON object (built by the agent)</div>\n <pre class=\"dev-state\" id=\"dev-state\"></pre>\n <div class=\"dev-section-label\">Function calls</div>\n <div class=\"dev-log\" id=\"dev-log\"></div>\n </div>\n `;\n\n stateEl = panel.querySelector<HTMLElement>(\"#dev-state\");\n logEl = panel.querySelector<HTMLElement>(\"#dev-log\");\n\n const toggle = panel.querySelector<HTMLButtonElement>(\".dev-toggle\");\n toggle?.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n setCollapsed(panel, !panel.classList.contains(\"collapsed\"));\n });\n // When collapsed, the whole widget acts as an expand button.\n panel.addEventListener(\"click\", () => {\n if (panel.classList.contains(\"collapsed\")) setCollapsed(panel, false);\n });\n\n let startCollapsed = false;\n try {\n startCollapsed = localStorage.getItem(COLLAPSE_KEY) === \"1\";\n } catch {\n // ignore\n }\n setCollapsed(panel, startCollapsed);\n\n client.on(\"function:invoke\", ({ functionName, arguments: args }) => {\n logLine(`→ ${functionName}(${JSON.stringify(args ?? {})})`, \"invoke\");\n });\n client.on(\"function:result\", ({ result, error }) => {\n logLine(\n error ? `✗ error: ${error}` : `← ${JSON.stringify(result)}`,\n error ? \"error\" : \"result\",\n );\n });\n\n // Re-render the JSON object on every state change, then paint the initial state.\n store.subscribe(renderState);\n renderState();\n}\n\nconst STYLE_ID = \"dev-panel-styles\";\n\nfunction injectStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n const style = document.createElement(\"style\");\n style.id = STYLE_ID;\n style.textContent = PANEL_CSS;\n document.head.appendChild(style);\n}\n\nconst PANEL_CSS = `\n#dev-panel {\n position: fixed;\n top: 16px;\n right: 16px;\n width: min(360px, calc(100vw - 32px));\n max-width: calc(100vw - 32px);\n box-sizing: border-box;\n max-height: calc(100vh - 32px);\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px 14px;\n background: #0f1419;\n color: #d7e0e8;\n border: 1px solid #2a3441;\n border-radius: 12px;\n box-shadow: 0 20px 50px -20px rgba(0,0,0,.6);\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n z-index: 1000;\n}\n#dev-panel .dev-head { display: flex; align-items: center; gap: 8px; }\n#dev-panel .dev-toggle {\n margin-left: auto;\n flex: none;\n width: 22px;\n height: 22px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n color: #7c8a99;\n border: 1px solid #2a3441;\n border-radius: 6px;\n font-size: 12px;\n line-height: 1;\n cursor: pointer;\n}\n#dev-panel .dev-toggle:hover { color: #d7e0e8; border-color: #3a4655; }\n#dev-panel .dev-body { display: flex; flex-direction: column; gap: 8px; }\n\n/* Collapsed: shrink to a small clickable widget showing only the DEV badge. */\n#dev-panel.collapsed {\n width: auto;\n cursor: pointer;\n padding: 8px 10px;\n}\n#dev-panel.collapsed .dev-title,\n#dev-panel.collapsed .dev-body { display: none; }\n#dev-panel.collapsed .dev-toggle { margin-left: 6px; }\n#dev-panel .dev-badge {\n background: #f59e0b;\n color: #1c1206;\n font-weight: 700;\n font-size: 10px;\n letter-spacing: .08em;\n padding: 2px 6px;\n border-radius: 5px;\n}\n#dev-panel .dev-title { color: #f59e0b; font-size: 11px; line-height: 1.3; }\n#dev-panel .dev-fns { color: #7c8a99; font-size: 11px; }\n#dev-panel .dev-fns code { color: #9ecbff; }\n#dev-panel .dev-section-label {\n color: #7c8a99;\n text-transform: uppercase;\n letter-spacing: .08em;\n font-size: 10px;\n margin-top: 4px;\n}\n#dev-panel .dev-state {\n margin: 0;\n padding: 8px;\n background: #060a0e;\n border-radius: 8px;\n overflow: auto;\n max-height: 40vh;\n white-space: pre;\n color: #c8e6c9;\n}\n#dev-panel .dev-log {\n display: flex;\n flex-direction: column;\n gap: 2px;\n overflow-y: auto;\n max-height: 24vh;\n background: #060a0e;\n border-radius: 8px;\n padding: 6px 8px;\n}\n#dev-panel .dev-log-line { white-space: pre-wrap; word-break: break-word; line-height: 1.4; }\n#dev-panel .dev-log-invoke { color: #9ecbff; }\n#dev-panel .dev-log-result { color: #86efac; }\n#dev-panel .dev-log-error { color: #fca5a5; }\n`;\n"],"mappings":";AAgBA,IAAI;AACJ,IAAI;AACJ,IAAI,oBAAmC,EAAE;AAGzC,SAAS,cAAoB;AAC3B,KAAI,CAAC,QAAS;AACd,SAAQ,cAAc,KAAK,UAAU,YAAY,EAAE,MAAM,EAAE;;AAG7D,SAAS,QAAQ,MAAc,MAA2C;AACxE,KAAI,CAAC,MAAO;CACZ,MAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,MAAK,YAAY,wBAAwB;AAEzC,MAAK,cAAc,oBADN,IAAI,MAAM,EAAC,oBACF,CAAK,IAAI;AAC/B,OAAM,YAAY,KAAK;AACvB,OAAM,YAAY,MAAM;;AAG1B,IAAM,eAAe;AAErB,SAAS,aAAa,OAAoB,WAA0B;AAClE,OAAM,UAAU,OAAO,aAAa,UAAU;CAC9C,MAAM,SAAS,MAAM,cAAiC,cAAc;AACpE,KAAI,QAAQ;AACV,SAAO,cAAc,YAAY,MAAM;AACvC,SAAO,QAAQ,YAAY,qBAAqB;AAChD,SAAO,aAAa,iBAAiB,OAAO,CAAC,UAAU,CAAC;;AAE1D,KAAI;AACF,eAAa,QAAQ,cAAc,YAAY,MAAM,IAAI;SACnD;;AAKV,SAAgB,aAAa,SAAgC;CAC3D,MAAM,EAAE,OAAO,QAAQ,WAAW;AAClC,cAAa,MAAM;AACnB,eAAc;CACd,MAAM,OACJ,OAAO,WAAW,WACd,SAAS,cAAc,OAAO,GAC9B,kBAAkB,UAChB,SACA,SAAS;CACjB,MAAM,QAAQ,SAAS,cAAc,QAAQ;AAC7C,OAAM,KAAK;AACX,EAAC,QAAQ,SAAS,MAAM,YAAY,MAAM;AAK1C,OAAM,YAAY;;;;;;;0DAHC,OAAO,0BAA0B,IAAI,EAAE,EAC/B,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,IAAI,IASG;;;;;;;AAQ/D,WAAU,MAAM,cAA2B,aAAa;AACxD,SAAQ,MAAM,cAA2B,WAAW;AAErC,OAAM,cAAiC,cACtD,EAAQ,iBAAiB,UAAU,MAAM;AACvC,IAAE,iBAAiB;AACnB,eAAa,OAAO,CAAC,MAAM,UAAU,SAAS,YAAY,CAAC;GAC3D;AAEF,OAAM,iBAAiB,eAAe;AACpC,MAAI,MAAM,UAAU,SAAS,YAAY,CAAE,cAAa,OAAO,MAAM;GACrE;CAEF,IAAI,iBAAiB;AACrB,KAAI;AACF,mBAAiB,aAAa,QAAQ,aAAa,KAAK;SAClD;AAGR,cAAa,OAAO,eAAe;AAEnC,QAAO,GAAG,oBAAoB,EAAE,cAAc,WAAW,WAAW;AAClE,UAAQ,KAAK,aAAa,GAAG,KAAK,UAAU,QAAQ,EAAE,CAAC,CAAC,IAAI,SAAS;GACrE;AACF,QAAO,GAAG,oBAAoB,EAAE,QAAQ,YAAY;AAClD,UACE,QAAQ,YAAY,UAAU,KAAK,KAAK,UAAU,OAAO,IACzD,QAAQ,UAAU,SACnB;GACD;AAGF,OAAM,UAAU,YAAY;AAC5B,cAAa;;AAGf,IAAM,WAAW;AAEjB,SAAS,eAAqB;AAC5B,KAAI,SAAS,eAAe,SAAS,CAAE;CACvC,MAAM,QAAQ,SAAS,cAAc,QAAQ;AAC7C,OAAM,KAAK;AACX,OAAM,cAAc;AACpB,UAAS,KAAK,YAAY,MAAM;;AAGlC,IAAM,YAAY"}
package/dist/index.cjs CHANGED
@@ -1,16 +1,28 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_AgoClient = require("./AgoClient-D0l1GTRs.cjs");
2
+ const require_AgoClient = require("./AgoClient-wMVUQqCD.cjs");
3
3
  const require_createMockClient = require("./createMockClient-Ci_N2tH8.cjs");
4
4
  const require_functions = require("./functions--c6lx3ic.cjs");
5
5
  //#region src/state/createStore.ts
6
- function createStore(initial) {
6
+ function createStore(initial, persist) {
7
+ const storage = persist ? persist.storage ?? (typeof localStorage !== "undefined" ? localStorage : void 0) : void 0;
7
8
  let state = initial;
9
+ if (persist && storage) try {
10
+ const raw = storage.getItem(persist.key);
11
+ if (raw != null) state = JSON.parse(raw);
12
+ } catch {}
8
13
  const subscribers = /* @__PURE__ */ new Set();
14
+ const notify = () => subscribers.forEach((fn) => fn(state));
15
+ function persistState() {
16
+ if (persist && storage) try {
17
+ storage.setItem(persist.key, JSON.stringify(state));
18
+ } catch {}
19
+ }
9
20
  return {
10
21
  get: () => state,
11
22
  set: (next) => {
12
23
  state = next;
13
- subscribers.forEach((fn) => fn(state));
24
+ persistState();
25
+ notify();
14
26
  },
15
27
  subscribe: (fn) => {
16
28
  subscribers.add(fn);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/state/createStore.ts","../src/functions/defineFunction.ts","../src/streaming/helpers.ts","../src/auto/createAgo.ts","../src/helpers/factory.ts"],"sourcesContent":["/**\n * A minimal observable store: a single value plus synchronous subscriptions.\n *\n * ```ts\n * const store = createStore({ count: 0 });\n * const unsubscribe = store.subscribe((state) => save(state));\n * store.set({ count: 1 }); // listeners fire synchronously\n * ```\n */\nexport interface Store<T> {\n /** Current state. */\n get(): T;\n /** Replace the state and notify subscribers synchronously. */\n set(next: T): void;\n /** Register a listener; returns a function that removes it. */\n subscribe(listener: (state: T) => void): () => void;\n}\n\nexport function createStore<T>(initial: T): Store<T> {\n let state = initial;\n const subscribers = new Set<(state: T) => void>();\n\n return {\n get: () => state,\n set: (next: T) => {\n state = next;\n subscribers.forEach((fn) => fn(state));\n },\n subscribe: (fn: (state: T) => void) => {\n subscribers.add(fn);\n return () => {\n subscribers.delete(fn);\n };\n },\n };\n}\n","import type { ClientFunctionDefinition } from \"./types\";\n\n/**\n * Create a reusable function definition.\n * Returns the same object — this is an identity function for discoverability and type-checking.\n *\n * ```ts\n * // Define once, reuse anywhere\n * export const lookupOrder = defineFunction({\n * name: \"lookupOrder\",\n * description: \"Look up an order by ID\",\n * parameters: { type: \"object\", properties: { id: { type: \"string\" } }, required: [\"id\"] },\n * handler: async (args) => fetchOrder(args.id as string),\n * });\n *\n * // Register with client\n * client.registerFunction(lookupOrder);\n *\n * // Or use in React\n * useAgoFunction(lookupOrder.name, lookupOrder);\n * ```\n */\nexport function defineFunction(\n definition: ClientFunctionDefinition\n): ClientFunctionDefinition {\n return definition;\n}\n","import type { AgoClient } from \"../client/AgoClient\";\nimport type {\n AgoMessage,\n AgoClientEvents,\n ToolCallData,\n ClientFunctionInvocation,\n} from \"../client/types\";\n\n/**\n * Subscribe to complete messages with a simple callback. Returns an unsubscribe function.\n *\n * ```ts\n * const unsub = onMessage(client, (msg) => console.log(msg.content));\n * // later: unsub();\n * ```\n */\nexport function onMessage(\n client: AgoClient,\n callback: (message: AgoMessage) => void\n): () => void {\n client.on(\"message:complete\", callback);\n return () => client.off(\"message:complete\", callback);\n}\n\n/**\n * Subscribe to streaming text chunks.\n *\n * ```ts\n * onMessageChunk(client, ({ content }) => {\n * outputEl.textContent += content;\n * });\n * ```\n */\nexport function onMessageChunk(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:chunk\"]) => void\n): () => void {\n client.on(\"message:chunk\", callback);\n return () => client.off(\"message:chunk\", callback);\n}\n\n/**\n * Subscribe to message start events.\n */\nexport function onMessageStart(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:start\"]) => void\n): () => void {\n client.on(\"message:start\", callback);\n return () => client.off(\"message:start\", callback);\n}\n\n/**\n * Subscribe to message errors.\n */\nexport function onMessageError(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:error\"]) => void\n): () => void {\n client.on(\"message:error\", callback);\n return () => client.off(\"message:error\", callback);\n}\n\n/**\n * Subscribe to tool call events.\n */\nexport function onToolCall(\n client: AgoClient,\n callback: (toolCall: ToolCallData) => void\n): () => void {\n client.on(\"toolCall:received\", callback);\n return () => client.off(\"toolCall:received\", callback);\n}\n\n/**\n * Subscribe to client function invocations.\n */\nexport function onFunctionInvoke(\n client: AgoClient,\n callback: (data: ClientFunctionInvocation) => void\n): () => void {\n client.on(\"function:invoke\", callback);\n return () => client.off(\"function:invoke\", callback);\n}\n\n/**\n * Send a message and iterate over chunks as an async generator.\n * Gives you full control over how you process the stream.\n *\n * ```ts\n * for await (const chunk of createMessageStream(client, \"Hello!\")) {\n * console.log(chunk.type, chunk.data);\n * }\n * ```\n */\nexport async function* createMessageStream(\n client: AgoClient,\n content: string,\n options?: { conversationId?: string; agentId?: string; files?: File[] }\n): AsyncGenerator<\n | { type: \"start\"; data: AgoClientEvents[\"message:start\"] }\n | { type: \"chunk\"; data: AgoClientEvents[\"message:chunk\"] }\n | { type: \"complete\"; data: AgoMessage }\n | { type: \"error\"; data: AgoClientEvents[\"message:error\"] }\n | { type: \"toolCall\"; data: ToolCallData }\n> {\n type StreamEvent =\n | { type: \"start\"; data: AgoClientEvents[\"message:start\"] }\n | { type: \"chunk\"; data: AgoClientEvents[\"message:chunk\"] }\n | { type: \"complete\"; data: AgoMessage }\n | { type: \"error\"; data: AgoClientEvents[\"message:error\"] }\n | { type: \"toolCall\"; data: ToolCallData };\n\n const queue: StreamEvent[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n const push = (event: StreamEvent) => {\n queue.push(event);\n resolve?.();\n };\n\n const onStart = (data: AgoClientEvents[\"message:start\"]) => push({ type: \"start\", data });\n const onChunk = (data: AgoClientEvents[\"message:chunk\"]) => push({ type: \"chunk\", data });\n const onComplete = (data: AgoMessage) => {\n push({ type: \"complete\", data });\n done = true;\n resolve?.();\n };\n const onError = (data: AgoClientEvents[\"message:error\"]) => {\n push({ type: \"error\", data });\n done = true;\n resolve?.();\n };\n const onTool = (data: ToolCallData) => push({ type: \"toolCall\", data });\n\n client.on(\"message:start\", onStart);\n client.on(\"message:chunk\", onChunk);\n client.on(\"message:complete\", onComplete);\n client.on(\"message:error\", onError);\n client.on(\"toolCall:received\", onTool);\n\n // Fire the request (don't await — we'll consume events via the generator)\n client.sendMessage(content, options).catch(() => {\n done = true;\n resolve?.();\n });\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n resolve = null;\n }\n }\n } finally {\n client.off(\"message:start\", onStart);\n client.off(\"message:chunk\", onChunk);\n client.off(\"message:complete\", onComplete);\n client.off(\"message:error\", onError);\n client.off(\"toolCall:received\", onTool);\n }\n}\n","import { AgoClient } from \"../client/AgoClient\";\nimport type { AgoConfig } from \"../client/types\";\n\n/**\n * Auto-detect AGO configuration from the DOM environment.\n *\n * Checks (in order of priority):\n * 1. `window.AGO` global object (widget config)\n * 2. `<meta>` tags: `<meta name=\"ago-api-key\" content=\"...\">`\n * 3. `data-ago-*` attributes on `<body>` or `<script data-ago-api-key=\"...\">`\n * 4. Explicit overrides passed as argument\n *\n * Returns null if no API key can be found.\n */\nexport function autoDetectConfig(\n overrides?: Partial<AgoConfig>\n): AgoConfig | null {\n let baseUrl: string | undefined;\n let widgetId: string | undefined;\n let agent: string | undefined;\n let permission: string | undefined;\n let userEmail: string | undefined;\n let userJwt: string | undefined;\n\n // 1. window.AGO (widget config format)\n if (typeof window !== \"undefined\" && (window as unknown as Record<string, unknown>).AGO) {\n const ago = (window as unknown as Record<string, unknown>).AGO as Record<string, unknown>;\n baseUrl = ago.basepath as string | undefined;\n widgetId = ago.widgetId as string | undefined;\n agent = (ago.agent as string | undefined) || (ago.defaultAgent as string | undefined);\n permission = ago.permission as string | undefined;\n userEmail = ago.email as string | undefined;\n userJwt = ago.jwt as string | undefined;\n }\n\n // 2. Meta tags\n if (typeof document !== \"undefined\") {\n const getMeta = (name: string) =>\n document.querySelector(`meta[name=\"${name}\"]`)?.getAttribute(\"content\") || undefined;\n\n baseUrl = baseUrl || getMeta(\"ago-base-url\");\n widgetId = widgetId || getMeta(\"ago-widget-id\");\n agent = agent || getMeta(\"ago-agent\") || getMeta(\"ago-agent-id\");\n permission = permission || getMeta(\"ago-permission\");\n userEmail = userEmail || getMeta(\"ago-user-email\");\n }\n\n // 3. data-ago-* attributes on body or script tags\n if (typeof document !== \"undefined\") {\n const sources = [\n document.body,\n ...Array.from(document.querySelectorAll(\"script[data-ago-base-url]\")),\n ].filter(Boolean);\n\n for (const el of sources) {\n if (!el) continue;\n baseUrl = baseUrl || el.getAttribute(\"data-ago-base-url\") || undefined;\n widgetId = widgetId || el.getAttribute(\"data-ago-widget-id\") || undefined;\n agent = agent || el.getAttribute(\"data-ago-agent\") || el.getAttribute(\"data-ago-agent-id\") || undefined;\n permission = permission || el.getAttribute(\"data-ago-permission\") || undefined;\n userEmail = userEmail || el.getAttribute(\"data-ago-user-email\") || undefined;\n }\n }\n\n // 4. Apply overrides\n baseUrl = overrides?.baseUrl || baseUrl;\n widgetId = overrides?.widgetId || widgetId;\n agent = overrides?.agent || overrides?.defaultAgentId || agent;\n permission = overrides?.permission || permission;\n userEmail = overrides?.userEmail || userEmail;\n userJwt = overrides?.userJwt || userJwt;\n const debug = overrides?.debug;\n\n if (!baseUrl) {\n return null;\n }\n\n return {\n baseUrl,\n widgetId,\n agent,\n permission,\n userEmail,\n userJwt,\n debug,\n };\n}\n\n/**\n * Create an AgoClient with zero configuration.\n * Auto-detects config from window.AGO, meta tags, and data-ago-* attributes.\n *\n * ```html\n * <!-- In your HTML -->\n * <meta name=\"ago-base-url\" content=\"https://YOUR-DOMAIN.useago.com\">\n *\n * <!-- Or on a script tag -->\n * <script src=\"app.js\" data-ago-base-url=\"https://YOUR-DOMAIN.useago.com\"></script>\n * ```\n *\n * ```ts\n * import { createAgo } from \"@useago/sdk\";\n *\n * // Zero config — picks up from DOM\n * const client = createAgo();\n *\n * // Or with partial overrides\n * const client = createAgo({ debug: true });\n * ```\n *\n * Throws if no base URL can be detected.\n */\nexport function createAgo(overrides?: Partial<AgoConfig>): AgoClient {\n const config = autoDetectConfig(overrides);\n\n if (!config) {\n throw new Error(\n \"createAgo(): could not detect AGO configuration. \" +\n \"Set window.AGO, add <meta name=\\\"ago-base-url\\\">, or pass { baseUrl } explicitly.\"\n );\n }\n\n return new AgoClient(config);\n}\n","import type {\n ClientFunctionDefinition,\n ClientFunctionHandler,\n} from \"../functions/types\";\n\n/**\n * Attach a handler to a pre-built function definition.\n *\n * Pre-built helpers (`showToast`, `trackEvent`, ...) ship with a no-op or\n * console-logging default handler. Use `withHandler` to wire them up to\n * your actual implementation without mutating the original definition.\n *\n * ```ts\n * import { showToast, withHandler } from \"@useago/sdk\";\n *\n * client.register(\n * withHandler(showToast, (args) => {\n * myToast(args.message as string);\n * return { shown: true };\n * })\n * );\n * ```\n */\nexport function withHandler<T extends ClientFunctionDefinition>(\n definition: T,\n handler: ClientFunctionHandler\n): T {\n return { ...definition, handler };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/state/createStore.ts","../src/functions/defineFunction.ts","../src/streaming/helpers.ts","../src/auto/createAgo.ts","../src/helpers/factory.ts"],"sourcesContent":["/**\n * A minimal observable store: one value, synchronous subscriptions, and\n * optional persistence via {@link PersistOptions} (localStorage by default).\n *\n * ```ts\n * const store = createStore({ count: 0 });\n * store.subscribe((state) => save(state));\n * store.set({ count: 1 }); // listeners fire synchronously\n *\n * const cart = createStore({ items: [] }, { key: \"cart\" }); // persisted\n * ```\n */\nexport interface Store<T> {\n /** Current state. */\n get(): T;\n /** Replace the state and notify subscribers synchronously. */\n set(next: T): void;\n /** Register a listener; returns a function that removes it. */\n subscribe(listener: (state: T) => void): () => void;\n}\n\n/** The slice of the Web Storage API that {@link createStore} relies on. */\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\">;\n\nexport interface PersistOptions {\n /** Key under which the state is JSON-serialized. */\n key: string;\n /** Storage backend; defaults to `globalThis.localStorage`. */\n storage?: StorageLike;\n}\n\nexport function createStore<T>(initial: T, persist?: PersistOptions): Store<T> {\n // Resolve a storage backend lazily; absence (SSR, disabled storage) degrades\n // to a pure in-memory store rather than throwing.\n const storage: StorageLike | undefined = persist\n ? (persist.storage ??\n (typeof localStorage !== \"undefined\" ? localStorage : undefined))\n : undefined;\n\n let state = initial;\n\n // Restore a previous snapshot; disabled storage or malformed JSON keeps the\n // initial value.\n if (persist && storage) {\n try {\n const raw = storage.getItem(persist.key);\n if (raw != null) {\n state = JSON.parse(raw) as T;\n }\n } catch {\n /* ignore */\n }\n }\n\n const subscribers = new Set<(state: T) => void>();\n const notify = () => subscribers.forEach((fn) => fn(state));\n\n function persistState() {\n if (persist && storage) {\n try {\n storage.setItem(persist.key, JSON.stringify(state));\n } catch {\n /* ignore */\n }\n }\n }\n\n return {\n get: () => state,\n set: (next: T) => {\n state = next;\n persistState();\n notify();\n },\n subscribe: (fn: (state: T) => void) => {\n subscribers.add(fn);\n return () => {\n subscribers.delete(fn);\n };\n },\n };\n}\n","import type { ClientFunctionDefinition } from \"./types\";\n\n/**\n * Create a reusable function definition.\n * Returns the same object — this is an identity function for discoverability and type-checking.\n *\n * ```ts\n * // Define once, reuse anywhere\n * export const lookupOrder = defineFunction({\n * name: \"lookupOrder\",\n * description: \"Look up an order by ID\",\n * parameters: { type: \"object\", properties: { id: { type: \"string\" } }, required: [\"id\"] },\n * handler: async (args) => fetchOrder(args.id as string),\n * });\n *\n * // Register with client\n * client.registerFunction(lookupOrder);\n *\n * // Or use in React\n * useAgoFunction(lookupOrder.name, lookupOrder);\n * ```\n */\nexport function defineFunction(\n definition: ClientFunctionDefinition\n): ClientFunctionDefinition {\n return definition;\n}\n","import type { AgoClient } from \"../client/AgoClient\";\nimport type {\n AgoMessage,\n AgoClientEvents,\n ToolCallData,\n ClientFunctionInvocation,\n} from \"../client/types\";\n\n/**\n * Subscribe to complete messages with a simple callback. Returns an unsubscribe function.\n *\n * ```ts\n * const unsub = onMessage(client, (msg) => console.log(msg.content));\n * // later: unsub();\n * ```\n */\nexport function onMessage(\n client: AgoClient,\n callback: (message: AgoMessage) => void\n): () => void {\n client.on(\"message:complete\", callback);\n return () => client.off(\"message:complete\", callback);\n}\n\n/**\n * Subscribe to streaming text chunks.\n *\n * ```ts\n * onMessageChunk(client, ({ content }) => {\n * outputEl.textContent += content;\n * });\n * ```\n */\nexport function onMessageChunk(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:chunk\"]) => void\n): () => void {\n client.on(\"message:chunk\", callback);\n return () => client.off(\"message:chunk\", callback);\n}\n\n/**\n * Subscribe to message start events.\n */\nexport function onMessageStart(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:start\"]) => void\n): () => void {\n client.on(\"message:start\", callback);\n return () => client.off(\"message:start\", callback);\n}\n\n/**\n * Subscribe to message errors.\n */\nexport function onMessageError(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:error\"]) => void\n): () => void {\n client.on(\"message:error\", callback);\n return () => client.off(\"message:error\", callback);\n}\n\n/**\n * Subscribe to tool call events.\n */\nexport function onToolCall(\n client: AgoClient,\n callback: (toolCall: ToolCallData) => void\n): () => void {\n client.on(\"toolCall:received\", callback);\n return () => client.off(\"toolCall:received\", callback);\n}\n\n/**\n * Subscribe to client function invocations.\n */\nexport function onFunctionInvoke(\n client: AgoClient,\n callback: (data: ClientFunctionInvocation) => void\n): () => void {\n client.on(\"function:invoke\", callback);\n return () => client.off(\"function:invoke\", callback);\n}\n\n/**\n * Send a message and iterate over chunks as an async generator.\n * Gives you full control over how you process the stream.\n *\n * ```ts\n * for await (const chunk of createMessageStream(client, \"Hello!\")) {\n * console.log(chunk.type, chunk.data);\n * }\n * ```\n */\nexport async function* createMessageStream(\n client: AgoClient,\n content: string,\n options?: { conversationId?: string; agentId?: string; files?: File[] }\n): AsyncGenerator<\n | { type: \"start\"; data: AgoClientEvents[\"message:start\"] }\n | { type: \"chunk\"; data: AgoClientEvents[\"message:chunk\"] }\n | { type: \"complete\"; data: AgoMessage }\n | { type: \"error\"; data: AgoClientEvents[\"message:error\"] }\n | { type: \"toolCall\"; data: ToolCallData }\n> {\n type StreamEvent =\n | { type: \"start\"; data: AgoClientEvents[\"message:start\"] }\n | { type: \"chunk\"; data: AgoClientEvents[\"message:chunk\"] }\n | { type: \"complete\"; data: AgoMessage }\n | { type: \"error\"; data: AgoClientEvents[\"message:error\"] }\n | { type: \"toolCall\"; data: ToolCallData };\n\n const queue: StreamEvent[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n const push = (event: StreamEvent) => {\n queue.push(event);\n resolve?.();\n };\n\n const onStart = (data: AgoClientEvents[\"message:start\"]) => push({ type: \"start\", data });\n const onChunk = (data: AgoClientEvents[\"message:chunk\"]) => push({ type: \"chunk\", data });\n const onComplete = (data: AgoMessage) => {\n push({ type: \"complete\", data });\n done = true;\n resolve?.();\n };\n const onError = (data: AgoClientEvents[\"message:error\"]) => {\n push({ type: \"error\", data });\n done = true;\n resolve?.();\n };\n const onTool = (data: ToolCallData) => push({ type: \"toolCall\", data });\n\n client.on(\"message:start\", onStart);\n client.on(\"message:chunk\", onChunk);\n client.on(\"message:complete\", onComplete);\n client.on(\"message:error\", onError);\n client.on(\"toolCall:received\", onTool);\n\n // Fire the request (don't await — we'll consume events via the generator)\n client.sendMessage(content, options).catch(() => {\n done = true;\n resolve?.();\n });\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n resolve = null;\n }\n }\n } finally {\n client.off(\"message:start\", onStart);\n client.off(\"message:chunk\", onChunk);\n client.off(\"message:complete\", onComplete);\n client.off(\"message:error\", onError);\n client.off(\"toolCall:received\", onTool);\n }\n}\n","import { AgoClient } from \"../client/AgoClient\";\nimport type { AgoConfig } from \"../client/types\";\n\n/**\n * Auto-detect AGO configuration from the DOM environment.\n *\n * Checks (in order of priority):\n * 1. `window.AGO` global object (widget config)\n * 2. `<meta>` tags: `<meta name=\"ago-api-key\" content=\"...\">`\n * 3. `data-ago-*` attributes on `<body>` or `<script data-ago-api-key=\"...\">`\n * 4. Explicit overrides passed as argument\n *\n * Returns null if no API key can be found.\n */\nexport function autoDetectConfig(\n overrides?: Partial<AgoConfig>\n): AgoConfig | null {\n let baseUrl: string | undefined;\n let widgetId: string | undefined;\n let agent: string | undefined;\n let permission: string | undefined;\n let userEmail: string | undefined;\n let userJwt: string | undefined;\n\n // 1. window.AGO (widget config format)\n if (typeof window !== \"undefined\" && (window as unknown as Record<string, unknown>).AGO) {\n const ago = (window as unknown as Record<string, unknown>).AGO as Record<string, unknown>;\n baseUrl = ago.basepath as string | undefined;\n widgetId = ago.widgetId as string | undefined;\n agent = (ago.agent as string | undefined) || (ago.defaultAgent as string | undefined);\n permission = ago.permission as string | undefined;\n userEmail = ago.email as string | undefined;\n userJwt = ago.jwt as string | undefined;\n }\n\n // 2. Meta tags\n if (typeof document !== \"undefined\") {\n const getMeta = (name: string) =>\n document.querySelector(`meta[name=\"${name}\"]`)?.getAttribute(\"content\") || undefined;\n\n baseUrl = baseUrl || getMeta(\"ago-base-url\");\n widgetId = widgetId || getMeta(\"ago-widget-id\");\n agent = agent || getMeta(\"ago-agent\") || getMeta(\"ago-agent-id\");\n permission = permission || getMeta(\"ago-permission\");\n userEmail = userEmail || getMeta(\"ago-user-email\");\n }\n\n // 3. data-ago-* attributes on body or script tags\n if (typeof document !== \"undefined\") {\n const sources = [\n document.body,\n ...Array.from(document.querySelectorAll(\"script[data-ago-base-url]\")),\n ].filter(Boolean);\n\n for (const el of sources) {\n if (!el) continue;\n baseUrl = baseUrl || el.getAttribute(\"data-ago-base-url\") || undefined;\n widgetId = widgetId || el.getAttribute(\"data-ago-widget-id\") || undefined;\n agent = agent || el.getAttribute(\"data-ago-agent\") || el.getAttribute(\"data-ago-agent-id\") || undefined;\n permission = permission || el.getAttribute(\"data-ago-permission\") || undefined;\n userEmail = userEmail || el.getAttribute(\"data-ago-user-email\") || undefined;\n }\n }\n\n // 4. Apply overrides\n baseUrl = overrides?.baseUrl || baseUrl;\n widgetId = overrides?.widgetId || widgetId;\n agent = overrides?.agent || overrides?.defaultAgentId || agent;\n permission = overrides?.permission || permission;\n userEmail = overrides?.userEmail || userEmail;\n userJwt = overrides?.userJwt || userJwt;\n const debug = overrides?.debug;\n\n if (!baseUrl) {\n return null;\n }\n\n return {\n baseUrl,\n widgetId,\n agent,\n permission,\n userEmail,\n userJwt,\n debug,\n };\n}\n\n/**\n * Create an AgoClient with zero configuration.\n * Auto-detects config from window.AGO, meta tags, and data-ago-* attributes.\n *\n * ```html\n * <!-- In your HTML -->\n * <meta name=\"ago-base-url\" content=\"https://YOUR-DOMAIN.useago.com\">\n *\n * <!-- Or on a script tag -->\n * <script src=\"app.js\" data-ago-base-url=\"https://YOUR-DOMAIN.useago.com\"></script>\n * ```\n *\n * ```ts\n * import { createAgo } from \"@useago/sdk\";\n *\n * // Zero config — picks up from DOM\n * const client = createAgo();\n *\n * // Or with partial overrides\n * const client = createAgo({ debug: true });\n * ```\n *\n * Throws if no base URL can be detected.\n */\nexport function createAgo(overrides?: Partial<AgoConfig>): AgoClient {\n const config = autoDetectConfig(overrides);\n\n if (!config) {\n throw new Error(\n \"createAgo(): could not detect AGO configuration. \" +\n \"Set window.AGO, add <meta name=\\\"ago-base-url\\\">, or pass { baseUrl } explicitly.\"\n );\n }\n\n return new AgoClient(config);\n}\n","import type {\n ClientFunctionDefinition,\n ClientFunctionHandler,\n} from \"../functions/types\";\n\n/**\n * Attach a handler to a pre-built function definition.\n *\n * Pre-built helpers (`showToast`, `trackEvent`, ...) ship with a no-op or\n * console-logging default handler. Use `withHandler` to wire them up to\n * your actual implementation without mutating the original definition.\n *\n * ```ts\n * import { showToast, withHandler } from \"@useago/sdk\";\n *\n * client.register(\n * withHandler(showToast, (args) => {\n * myToast(args.message as string);\n * return { shown: true };\n * })\n * );\n * ```\n */\nexport function withHandler<T extends ClientFunctionDefinition>(\n definition: T,\n handler: ClientFunctionHandler\n): T {\n return { ...definition, handler };\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { AgoClient } from "./client/AgoClient";
2
2
  export type { AgoAgent, AgoClientEvents, AgoConfig, AgoEventHandler, AgoEventName, AgoMessage, AgoSource, ClientFunction, ClientFunctionInvocation, Conversation, FormField, FormSchema, FunctionDefinition, FunctionSchema, MessageStatus, SendMessageOptions, SSEChunkData, ToolCallData, ToolCallType, } from "./client/types";
3
3
  export { AgoApiError, AgoError, AgoFunctionError, AgoNetworkError, AgoStreamError, } from "./client/errors";
4
4
  export { createStore } from "./state/createStore";
5
- export type { Store } from "./state/createStore";
5
+ export type { Store, PersistOptions } from "./state/createStore";
6
6
  export { ClientContextRegistry } from "./state/ClientContextRegistry";
7
7
  export type { ContextEntry, ContextSnapshot, DynamicContextProvider, } from "./state/ClientContextRegistry";
8
8
  export { defineFunction } from "./functions/defineFunction";
package/dist/index.js CHANGED
@@ -1,15 +1,27 @@
1
- import { a as ClientContextRegistry, c as AgoApiError, d as AgoNetworkError, f as AgoStreamError, i as isStreamNetworkError, l as AgoError, n as EventEmitter, o as FunctionRegistry, r as SSEHandler, s as logger, t as AgoClient, u as AgoFunctionError } from "./AgoClient-CNT-8sh_.js";
1
+ import { a as ClientContextRegistry, c as AgoApiError, d as AgoNetworkError, f as AgoStreamError, i as isStreamNetworkError, l as AgoError, n as EventEmitter, o as FunctionRegistry, r as SSEHandler, s as logger, t as AgoClient, u as AgoFunctionError } from "./AgoClient-DPZdN5n2.js";
2
2
  import { t as createMockClient } from "./createMockClient-U0ae_AYy.js";
3
3
  import { a as highlightElement, c as setLocalStorage, d as showNotification, f as showToast, i as getUserLocation, l as setTheme, m as trackEvent, o as openUrl, p as submitForm, r as getLocalStorage, s as scrollToElement, t as copyToClipboard, u as showConfirmDialog } from "./functions-C9F1dnmh.js";
4
4
  //#region src/state/createStore.ts
5
- function createStore(initial) {
5
+ function createStore(initial, persist) {
6
+ const storage = persist ? persist.storage ?? (typeof localStorage !== "undefined" ? localStorage : void 0) : void 0;
6
7
  let state = initial;
8
+ if (persist && storage) try {
9
+ const raw = storage.getItem(persist.key);
10
+ if (raw != null) state = JSON.parse(raw);
11
+ } catch {}
7
12
  const subscribers = /* @__PURE__ */ new Set();
13
+ const notify = () => subscribers.forEach((fn) => fn(state));
14
+ function persistState() {
15
+ if (persist && storage) try {
16
+ storage.setItem(persist.key, JSON.stringify(state));
17
+ } catch {}
18
+ }
8
19
  return {
9
20
  get: () => state,
10
21
  set: (next) => {
11
22
  state = next;
12
- subscribers.forEach((fn) => fn(state));
23
+ persistState();
24
+ notify();
13
25
  },
14
26
  subscribe: (fn) => {
15
27
  subscribers.add(fn);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/state/createStore.ts","../src/functions/defineFunction.ts","../src/streaming/helpers.ts","../src/auto/createAgo.ts","../src/helpers/factory.ts"],"sourcesContent":["/**\n * A minimal observable store: a single value plus synchronous subscriptions.\n *\n * ```ts\n * const store = createStore({ count: 0 });\n * const unsubscribe = store.subscribe((state) => save(state));\n * store.set({ count: 1 }); // listeners fire synchronously\n * ```\n */\nexport interface Store<T> {\n /** Current state. */\n get(): T;\n /** Replace the state and notify subscribers synchronously. */\n set(next: T): void;\n /** Register a listener; returns a function that removes it. */\n subscribe(listener: (state: T) => void): () => void;\n}\n\nexport function createStore<T>(initial: T): Store<T> {\n let state = initial;\n const subscribers = new Set<(state: T) => void>();\n\n return {\n get: () => state,\n set: (next: T) => {\n state = next;\n subscribers.forEach((fn) => fn(state));\n },\n subscribe: (fn: (state: T) => void) => {\n subscribers.add(fn);\n return () => {\n subscribers.delete(fn);\n };\n },\n };\n}\n","import type { ClientFunctionDefinition } from \"./types\";\n\n/**\n * Create a reusable function definition.\n * Returns the same object — this is an identity function for discoverability and type-checking.\n *\n * ```ts\n * // Define once, reuse anywhere\n * export const lookupOrder = defineFunction({\n * name: \"lookupOrder\",\n * description: \"Look up an order by ID\",\n * parameters: { type: \"object\", properties: { id: { type: \"string\" } }, required: [\"id\"] },\n * handler: async (args) => fetchOrder(args.id as string),\n * });\n *\n * // Register with client\n * client.registerFunction(lookupOrder);\n *\n * // Or use in React\n * useAgoFunction(lookupOrder.name, lookupOrder);\n * ```\n */\nexport function defineFunction(\n definition: ClientFunctionDefinition\n): ClientFunctionDefinition {\n return definition;\n}\n","import type { AgoClient } from \"../client/AgoClient\";\nimport type {\n AgoMessage,\n AgoClientEvents,\n ToolCallData,\n ClientFunctionInvocation,\n} from \"../client/types\";\n\n/**\n * Subscribe to complete messages with a simple callback. Returns an unsubscribe function.\n *\n * ```ts\n * const unsub = onMessage(client, (msg) => console.log(msg.content));\n * // later: unsub();\n * ```\n */\nexport function onMessage(\n client: AgoClient,\n callback: (message: AgoMessage) => void\n): () => void {\n client.on(\"message:complete\", callback);\n return () => client.off(\"message:complete\", callback);\n}\n\n/**\n * Subscribe to streaming text chunks.\n *\n * ```ts\n * onMessageChunk(client, ({ content }) => {\n * outputEl.textContent += content;\n * });\n * ```\n */\nexport function onMessageChunk(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:chunk\"]) => void\n): () => void {\n client.on(\"message:chunk\", callback);\n return () => client.off(\"message:chunk\", callback);\n}\n\n/**\n * Subscribe to message start events.\n */\nexport function onMessageStart(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:start\"]) => void\n): () => void {\n client.on(\"message:start\", callback);\n return () => client.off(\"message:start\", callback);\n}\n\n/**\n * Subscribe to message errors.\n */\nexport function onMessageError(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:error\"]) => void\n): () => void {\n client.on(\"message:error\", callback);\n return () => client.off(\"message:error\", callback);\n}\n\n/**\n * Subscribe to tool call events.\n */\nexport function onToolCall(\n client: AgoClient,\n callback: (toolCall: ToolCallData) => void\n): () => void {\n client.on(\"toolCall:received\", callback);\n return () => client.off(\"toolCall:received\", callback);\n}\n\n/**\n * Subscribe to client function invocations.\n */\nexport function onFunctionInvoke(\n client: AgoClient,\n callback: (data: ClientFunctionInvocation) => void\n): () => void {\n client.on(\"function:invoke\", callback);\n return () => client.off(\"function:invoke\", callback);\n}\n\n/**\n * Send a message and iterate over chunks as an async generator.\n * Gives you full control over how you process the stream.\n *\n * ```ts\n * for await (const chunk of createMessageStream(client, \"Hello!\")) {\n * console.log(chunk.type, chunk.data);\n * }\n * ```\n */\nexport async function* createMessageStream(\n client: AgoClient,\n content: string,\n options?: { conversationId?: string; agentId?: string; files?: File[] }\n): AsyncGenerator<\n | { type: \"start\"; data: AgoClientEvents[\"message:start\"] }\n | { type: \"chunk\"; data: AgoClientEvents[\"message:chunk\"] }\n | { type: \"complete\"; data: AgoMessage }\n | { type: \"error\"; data: AgoClientEvents[\"message:error\"] }\n | { type: \"toolCall\"; data: ToolCallData }\n> {\n type StreamEvent =\n | { type: \"start\"; data: AgoClientEvents[\"message:start\"] }\n | { type: \"chunk\"; data: AgoClientEvents[\"message:chunk\"] }\n | { type: \"complete\"; data: AgoMessage }\n | { type: \"error\"; data: AgoClientEvents[\"message:error\"] }\n | { type: \"toolCall\"; data: ToolCallData };\n\n const queue: StreamEvent[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n const push = (event: StreamEvent) => {\n queue.push(event);\n resolve?.();\n };\n\n const onStart = (data: AgoClientEvents[\"message:start\"]) => push({ type: \"start\", data });\n const onChunk = (data: AgoClientEvents[\"message:chunk\"]) => push({ type: \"chunk\", data });\n const onComplete = (data: AgoMessage) => {\n push({ type: \"complete\", data });\n done = true;\n resolve?.();\n };\n const onError = (data: AgoClientEvents[\"message:error\"]) => {\n push({ type: \"error\", data });\n done = true;\n resolve?.();\n };\n const onTool = (data: ToolCallData) => push({ type: \"toolCall\", data });\n\n client.on(\"message:start\", onStart);\n client.on(\"message:chunk\", onChunk);\n client.on(\"message:complete\", onComplete);\n client.on(\"message:error\", onError);\n client.on(\"toolCall:received\", onTool);\n\n // Fire the request (don't await — we'll consume events via the generator)\n client.sendMessage(content, options).catch(() => {\n done = true;\n resolve?.();\n });\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n resolve = null;\n }\n }\n } finally {\n client.off(\"message:start\", onStart);\n client.off(\"message:chunk\", onChunk);\n client.off(\"message:complete\", onComplete);\n client.off(\"message:error\", onError);\n client.off(\"toolCall:received\", onTool);\n }\n}\n","import { AgoClient } from \"../client/AgoClient\";\nimport type { AgoConfig } from \"../client/types\";\n\n/**\n * Auto-detect AGO configuration from the DOM environment.\n *\n * Checks (in order of priority):\n * 1. `window.AGO` global object (widget config)\n * 2. `<meta>` tags: `<meta name=\"ago-api-key\" content=\"...\">`\n * 3. `data-ago-*` attributes on `<body>` or `<script data-ago-api-key=\"...\">`\n * 4. Explicit overrides passed as argument\n *\n * Returns null if no API key can be found.\n */\nexport function autoDetectConfig(\n overrides?: Partial<AgoConfig>\n): AgoConfig | null {\n let baseUrl: string | undefined;\n let widgetId: string | undefined;\n let agent: string | undefined;\n let permission: string | undefined;\n let userEmail: string | undefined;\n let userJwt: string | undefined;\n\n // 1. window.AGO (widget config format)\n if (typeof window !== \"undefined\" && (window as unknown as Record<string, unknown>).AGO) {\n const ago = (window as unknown as Record<string, unknown>).AGO as Record<string, unknown>;\n baseUrl = ago.basepath as string | undefined;\n widgetId = ago.widgetId as string | undefined;\n agent = (ago.agent as string | undefined) || (ago.defaultAgent as string | undefined);\n permission = ago.permission as string | undefined;\n userEmail = ago.email as string | undefined;\n userJwt = ago.jwt as string | undefined;\n }\n\n // 2. Meta tags\n if (typeof document !== \"undefined\") {\n const getMeta = (name: string) =>\n document.querySelector(`meta[name=\"${name}\"]`)?.getAttribute(\"content\") || undefined;\n\n baseUrl = baseUrl || getMeta(\"ago-base-url\");\n widgetId = widgetId || getMeta(\"ago-widget-id\");\n agent = agent || getMeta(\"ago-agent\") || getMeta(\"ago-agent-id\");\n permission = permission || getMeta(\"ago-permission\");\n userEmail = userEmail || getMeta(\"ago-user-email\");\n }\n\n // 3. data-ago-* attributes on body or script tags\n if (typeof document !== \"undefined\") {\n const sources = [\n document.body,\n ...Array.from(document.querySelectorAll(\"script[data-ago-base-url]\")),\n ].filter(Boolean);\n\n for (const el of sources) {\n if (!el) continue;\n baseUrl = baseUrl || el.getAttribute(\"data-ago-base-url\") || undefined;\n widgetId = widgetId || el.getAttribute(\"data-ago-widget-id\") || undefined;\n agent = agent || el.getAttribute(\"data-ago-agent\") || el.getAttribute(\"data-ago-agent-id\") || undefined;\n permission = permission || el.getAttribute(\"data-ago-permission\") || undefined;\n userEmail = userEmail || el.getAttribute(\"data-ago-user-email\") || undefined;\n }\n }\n\n // 4. Apply overrides\n baseUrl = overrides?.baseUrl || baseUrl;\n widgetId = overrides?.widgetId || widgetId;\n agent = overrides?.agent || overrides?.defaultAgentId || agent;\n permission = overrides?.permission || permission;\n userEmail = overrides?.userEmail || userEmail;\n userJwt = overrides?.userJwt || userJwt;\n const debug = overrides?.debug;\n\n if (!baseUrl) {\n return null;\n }\n\n return {\n baseUrl,\n widgetId,\n agent,\n permission,\n userEmail,\n userJwt,\n debug,\n };\n}\n\n/**\n * Create an AgoClient with zero configuration.\n * Auto-detects config from window.AGO, meta tags, and data-ago-* attributes.\n *\n * ```html\n * <!-- In your HTML -->\n * <meta name=\"ago-base-url\" content=\"https://YOUR-DOMAIN.useago.com\">\n *\n * <!-- Or on a script tag -->\n * <script src=\"app.js\" data-ago-base-url=\"https://YOUR-DOMAIN.useago.com\"></script>\n * ```\n *\n * ```ts\n * import { createAgo } from \"@useago/sdk\";\n *\n * // Zero config — picks up from DOM\n * const client = createAgo();\n *\n * // Or with partial overrides\n * const client = createAgo({ debug: true });\n * ```\n *\n * Throws if no base URL can be detected.\n */\nexport function createAgo(overrides?: Partial<AgoConfig>): AgoClient {\n const config = autoDetectConfig(overrides);\n\n if (!config) {\n throw new Error(\n \"createAgo(): could not detect AGO configuration. \" +\n \"Set window.AGO, add <meta name=\\\"ago-base-url\\\">, or pass { baseUrl } explicitly.\"\n );\n }\n\n return new AgoClient(config);\n}\n","import type {\n ClientFunctionDefinition,\n ClientFunctionHandler,\n} from \"../functions/types\";\n\n/**\n * Attach a handler to a pre-built function definition.\n *\n * Pre-built helpers (`showToast`, `trackEvent`, ...) ship with a no-op or\n * console-logging default handler. Use `withHandler` to wire them up to\n * your actual implementation without mutating the original definition.\n *\n * ```ts\n * import { showToast, withHandler } from \"@useago/sdk\";\n *\n * client.register(\n * withHandler(showToast, (args) => {\n * myToast(args.message as string);\n * return { shown: true };\n * })\n * );\n * ```\n */\nexport function withHandler<T extends ClientFunctionDefinition>(\n definition: T,\n handler: ClientFunctionHandler\n): T {\n return { ...definition, handler };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/state/createStore.ts","../src/functions/defineFunction.ts","../src/streaming/helpers.ts","../src/auto/createAgo.ts","../src/helpers/factory.ts"],"sourcesContent":["/**\n * A minimal observable store: one value, synchronous subscriptions, and\n * optional persistence via {@link PersistOptions} (localStorage by default).\n *\n * ```ts\n * const store = createStore({ count: 0 });\n * store.subscribe((state) => save(state));\n * store.set({ count: 1 }); // listeners fire synchronously\n *\n * const cart = createStore({ items: [] }, { key: \"cart\" }); // persisted\n * ```\n */\nexport interface Store<T> {\n /** Current state. */\n get(): T;\n /** Replace the state and notify subscribers synchronously. */\n set(next: T): void;\n /** Register a listener; returns a function that removes it. */\n subscribe(listener: (state: T) => void): () => void;\n}\n\n/** The slice of the Web Storage API that {@link createStore} relies on. */\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\">;\n\nexport interface PersistOptions {\n /** Key under which the state is JSON-serialized. */\n key: string;\n /** Storage backend; defaults to `globalThis.localStorage`. */\n storage?: StorageLike;\n}\n\nexport function createStore<T>(initial: T, persist?: PersistOptions): Store<T> {\n // Resolve a storage backend lazily; absence (SSR, disabled storage) degrades\n // to a pure in-memory store rather than throwing.\n const storage: StorageLike | undefined = persist\n ? (persist.storage ??\n (typeof localStorage !== \"undefined\" ? localStorage : undefined))\n : undefined;\n\n let state = initial;\n\n // Restore a previous snapshot; disabled storage or malformed JSON keeps the\n // initial value.\n if (persist && storage) {\n try {\n const raw = storage.getItem(persist.key);\n if (raw != null) {\n state = JSON.parse(raw) as T;\n }\n } catch {\n /* ignore */\n }\n }\n\n const subscribers = new Set<(state: T) => void>();\n const notify = () => subscribers.forEach((fn) => fn(state));\n\n function persistState() {\n if (persist && storage) {\n try {\n storage.setItem(persist.key, JSON.stringify(state));\n } catch {\n /* ignore */\n }\n }\n }\n\n return {\n get: () => state,\n set: (next: T) => {\n state = next;\n persistState();\n notify();\n },\n subscribe: (fn: (state: T) => void) => {\n subscribers.add(fn);\n return () => {\n subscribers.delete(fn);\n };\n },\n };\n}\n","import type { ClientFunctionDefinition } from \"./types\";\n\n/**\n * Create a reusable function definition.\n * Returns the same object — this is an identity function for discoverability and type-checking.\n *\n * ```ts\n * // Define once, reuse anywhere\n * export const lookupOrder = defineFunction({\n * name: \"lookupOrder\",\n * description: \"Look up an order by ID\",\n * parameters: { type: \"object\", properties: { id: { type: \"string\" } }, required: [\"id\"] },\n * handler: async (args) => fetchOrder(args.id as string),\n * });\n *\n * // Register with client\n * client.registerFunction(lookupOrder);\n *\n * // Or use in React\n * useAgoFunction(lookupOrder.name, lookupOrder);\n * ```\n */\nexport function defineFunction(\n definition: ClientFunctionDefinition\n): ClientFunctionDefinition {\n return definition;\n}\n","import type { AgoClient } from \"../client/AgoClient\";\nimport type {\n AgoMessage,\n AgoClientEvents,\n ToolCallData,\n ClientFunctionInvocation,\n} from \"../client/types\";\n\n/**\n * Subscribe to complete messages with a simple callback. Returns an unsubscribe function.\n *\n * ```ts\n * const unsub = onMessage(client, (msg) => console.log(msg.content));\n * // later: unsub();\n * ```\n */\nexport function onMessage(\n client: AgoClient,\n callback: (message: AgoMessage) => void\n): () => void {\n client.on(\"message:complete\", callback);\n return () => client.off(\"message:complete\", callback);\n}\n\n/**\n * Subscribe to streaming text chunks.\n *\n * ```ts\n * onMessageChunk(client, ({ content }) => {\n * outputEl.textContent += content;\n * });\n * ```\n */\nexport function onMessageChunk(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:chunk\"]) => void\n): () => void {\n client.on(\"message:chunk\", callback);\n return () => client.off(\"message:chunk\", callback);\n}\n\n/**\n * Subscribe to message start events.\n */\nexport function onMessageStart(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:start\"]) => void\n): () => void {\n client.on(\"message:start\", callback);\n return () => client.off(\"message:start\", callback);\n}\n\n/**\n * Subscribe to message errors.\n */\nexport function onMessageError(\n client: AgoClient,\n callback: (data: AgoClientEvents[\"message:error\"]) => void\n): () => void {\n client.on(\"message:error\", callback);\n return () => client.off(\"message:error\", callback);\n}\n\n/**\n * Subscribe to tool call events.\n */\nexport function onToolCall(\n client: AgoClient,\n callback: (toolCall: ToolCallData) => void\n): () => void {\n client.on(\"toolCall:received\", callback);\n return () => client.off(\"toolCall:received\", callback);\n}\n\n/**\n * Subscribe to client function invocations.\n */\nexport function onFunctionInvoke(\n client: AgoClient,\n callback: (data: ClientFunctionInvocation) => void\n): () => void {\n client.on(\"function:invoke\", callback);\n return () => client.off(\"function:invoke\", callback);\n}\n\n/**\n * Send a message and iterate over chunks as an async generator.\n * Gives you full control over how you process the stream.\n *\n * ```ts\n * for await (const chunk of createMessageStream(client, \"Hello!\")) {\n * console.log(chunk.type, chunk.data);\n * }\n * ```\n */\nexport async function* createMessageStream(\n client: AgoClient,\n content: string,\n options?: { conversationId?: string; agentId?: string; files?: File[] }\n): AsyncGenerator<\n | { type: \"start\"; data: AgoClientEvents[\"message:start\"] }\n | { type: \"chunk\"; data: AgoClientEvents[\"message:chunk\"] }\n | { type: \"complete\"; data: AgoMessage }\n | { type: \"error\"; data: AgoClientEvents[\"message:error\"] }\n | { type: \"toolCall\"; data: ToolCallData }\n> {\n type StreamEvent =\n | { type: \"start\"; data: AgoClientEvents[\"message:start\"] }\n | { type: \"chunk\"; data: AgoClientEvents[\"message:chunk\"] }\n | { type: \"complete\"; data: AgoMessage }\n | { type: \"error\"; data: AgoClientEvents[\"message:error\"] }\n | { type: \"toolCall\"; data: ToolCallData };\n\n const queue: StreamEvent[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n const push = (event: StreamEvent) => {\n queue.push(event);\n resolve?.();\n };\n\n const onStart = (data: AgoClientEvents[\"message:start\"]) => push({ type: \"start\", data });\n const onChunk = (data: AgoClientEvents[\"message:chunk\"]) => push({ type: \"chunk\", data });\n const onComplete = (data: AgoMessage) => {\n push({ type: \"complete\", data });\n done = true;\n resolve?.();\n };\n const onError = (data: AgoClientEvents[\"message:error\"]) => {\n push({ type: \"error\", data });\n done = true;\n resolve?.();\n };\n const onTool = (data: ToolCallData) => push({ type: \"toolCall\", data });\n\n client.on(\"message:start\", onStart);\n client.on(\"message:chunk\", onChunk);\n client.on(\"message:complete\", onComplete);\n client.on(\"message:error\", onError);\n client.on(\"toolCall:received\", onTool);\n\n // Fire the request (don't await — we'll consume events via the generator)\n client.sendMessage(content, options).catch(() => {\n done = true;\n resolve?.();\n });\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n resolve = null;\n }\n }\n } finally {\n client.off(\"message:start\", onStart);\n client.off(\"message:chunk\", onChunk);\n client.off(\"message:complete\", onComplete);\n client.off(\"message:error\", onError);\n client.off(\"toolCall:received\", onTool);\n }\n}\n","import { AgoClient } from \"../client/AgoClient\";\nimport type { AgoConfig } from \"../client/types\";\n\n/**\n * Auto-detect AGO configuration from the DOM environment.\n *\n * Checks (in order of priority):\n * 1. `window.AGO` global object (widget config)\n * 2. `<meta>` tags: `<meta name=\"ago-api-key\" content=\"...\">`\n * 3. `data-ago-*` attributes on `<body>` or `<script data-ago-api-key=\"...\">`\n * 4. Explicit overrides passed as argument\n *\n * Returns null if no API key can be found.\n */\nexport function autoDetectConfig(\n overrides?: Partial<AgoConfig>\n): AgoConfig | null {\n let baseUrl: string | undefined;\n let widgetId: string | undefined;\n let agent: string | undefined;\n let permission: string | undefined;\n let userEmail: string | undefined;\n let userJwt: string | undefined;\n\n // 1. window.AGO (widget config format)\n if (typeof window !== \"undefined\" && (window as unknown as Record<string, unknown>).AGO) {\n const ago = (window as unknown as Record<string, unknown>).AGO as Record<string, unknown>;\n baseUrl = ago.basepath as string | undefined;\n widgetId = ago.widgetId as string | undefined;\n agent = (ago.agent as string | undefined) || (ago.defaultAgent as string | undefined);\n permission = ago.permission as string | undefined;\n userEmail = ago.email as string | undefined;\n userJwt = ago.jwt as string | undefined;\n }\n\n // 2. Meta tags\n if (typeof document !== \"undefined\") {\n const getMeta = (name: string) =>\n document.querySelector(`meta[name=\"${name}\"]`)?.getAttribute(\"content\") || undefined;\n\n baseUrl = baseUrl || getMeta(\"ago-base-url\");\n widgetId = widgetId || getMeta(\"ago-widget-id\");\n agent = agent || getMeta(\"ago-agent\") || getMeta(\"ago-agent-id\");\n permission = permission || getMeta(\"ago-permission\");\n userEmail = userEmail || getMeta(\"ago-user-email\");\n }\n\n // 3. data-ago-* attributes on body or script tags\n if (typeof document !== \"undefined\") {\n const sources = [\n document.body,\n ...Array.from(document.querySelectorAll(\"script[data-ago-base-url]\")),\n ].filter(Boolean);\n\n for (const el of sources) {\n if (!el) continue;\n baseUrl = baseUrl || el.getAttribute(\"data-ago-base-url\") || undefined;\n widgetId = widgetId || el.getAttribute(\"data-ago-widget-id\") || undefined;\n agent = agent || el.getAttribute(\"data-ago-agent\") || el.getAttribute(\"data-ago-agent-id\") || undefined;\n permission = permission || el.getAttribute(\"data-ago-permission\") || undefined;\n userEmail = userEmail || el.getAttribute(\"data-ago-user-email\") || undefined;\n }\n }\n\n // 4. Apply overrides\n baseUrl = overrides?.baseUrl || baseUrl;\n widgetId = overrides?.widgetId || widgetId;\n agent = overrides?.agent || overrides?.defaultAgentId || agent;\n permission = overrides?.permission || permission;\n userEmail = overrides?.userEmail || userEmail;\n userJwt = overrides?.userJwt || userJwt;\n const debug = overrides?.debug;\n\n if (!baseUrl) {\n return null;\n }\n\n return {\n baseUrl,\n widgetId,\n agent,\n permission,\n userEmail,\n userJwt,\n debug,\n };\n}\n\n/**\n * Create an AgoClient with zero configuration.\n * Auto-detects config from window.AGO, meta tags, and data-ago-* attributes.\n *\n * ```html\n * <!-- In your HTML -->\n * <meta name=\"ago-base-url\" content=\"https://YOUR-DOMAIN.useago.com\">\n *\n * <!-- Or on a script tag -->\n * <script src=\"app.js\" data-ago-base-url=\"https://YOUR-DOMAIN.useago.com\"></script>\n * ```\n *\n * ```ts\n * import { createAgo } from \"@useago/sdk\";\n *\n * // Zero config — picks up from DOM\n * const client = createAgo();\n *\n * // Or with partial overrides\n * const client = createAgo({ debug: true });\n * ```\n *\n * Throws if no base URL can be detected.\n */\nexport function createAgo(overrides?: Partial<AgoConfig>): AgoClient {\n const config = autoDetectConfig(overrides);\n\n if (!config) {\n throw new Error(\n \"createAgo(): could not detect AGO configuration. \" +\n \"Set window.AGO, add <meta name=\\\"ago-base-url\\\">, or pass { baseUrl } explicitly.\"\n );\n }\n\n return new AgoClient(config);\n}\n","import type {\n ClientFunctionDefinition,\n ClientFunctionHandler,\n} from \"../functions/types\";\n\n/**\n * Attach a handler to a pre-built function definition.\n *\n * Pre-built helpers (`showToast`, `trackEvent`, ...) ship with a no-op or\n * console-logging default handler. Use `withHandler` to wire them up to\n * your actual implementation without mutating the original definition.\n *\n * ```ts\n * import { showToast, withHandler } from \"@useago/sdk\";\n *\n * client.register(\n * withHandler(showToast, (args) => {\n * myToast(args.message as string);\n * return { shown: true };\n * })\n * );\n * ```\n */\nexport function withHandler<T extends ClientFunctionDefinition>(\n definition: T,\n handler: ClientFunctionHandler\n): T {\n return { ...definition, handler };\n}\n"],"mappings":"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"}
package/dist/react.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-BqCkTl7Q.cjs");
3
- const require_AgoClient = require("./AgoClient-D0l1GTRs.cjs");
3
+ const require_AgoClient = require("./AgoClient-wMVUQqCD.cjs");
4
4
  const require_createMockClient = require("./createMockClient-Ci_N2tH8.cjs");
5
5
  let react = require("react");
6
6
  react = require_rolldown_runtime.__toESM(react, 1);
package/dist/react.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll, r as __toESM, t as __commonJSMin } from "./rolldown-runtime-CNZpIYwj.js";
2
- import { t as AgoClient } from "./AgoClient-CNT-8sh_.js";
2
+ import { t as AgoClient } from "./AgoClient-DPZdN5n2.js";
3
3
  import { t as createMockClient } from "./createMockClient-U0ae_AYy.js";
4
4
  import React, { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -1,10 +1,13 @@
1
1
  /**
2
- * A minimal observable store: a single value plus synchronous subscriptions.
2
+ * A minimal observable store: one value, synchronous subscriptions, and
3
+ * optional persistence via {@link PersistOptions} (localStorage by default).
3
4
  *
4
5
  * ```ts
5
6
  * const store = createStore({ count: 0 });
6
- * const unsubscribe = store.subscribe((state) => save(state));
7
+ * store.subscribe((state) => save(state));
7
8
  * store.set({ count: 1 }); // listeners fire synchronously
9
+ *
10
+ * const cart = createStore({ items: [] }, { key: "cart" }); // persisted
8
11
  * ```
9
12
  */
10
13
  export interface Store<T> {
@@ -15,4 +18,13 @@ export interface Store<T> {
15
18
  /** Register a listener; returns a function that removes it. */
16
19
  subscribe(listener: (state: T) => void): () => void;
17
20
  }
18
- export declare function createStore<T>(initial: T): Store<T>;
21
+ /** The slice of the Web Storage API that {@link createStore} relies on. */
22
+ type StorageLike = Pick<Storage, "getItem" | "setItem">;
23
+ export interface PersistOptions {
24
+ /** Key under which the state is JSON-serialized. */
25
+ key: string;
26
+ /** Storage backend; defaults to `globalThis.localStorage`. */
27
+ storage?: StorageLike;
28
+ }
29
+ export declare function createStore<T>(initial: T, persist?: PersistOptions): Store<T>;
30
+ export {};
package/dist/vue.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./rolldown-runtime-BqCkTl7Q.cjs");
3
- const require_AgoClient = require("./AgoClient-D0l1GTRs.cjs");
3
+ const require_AgoClient = require("./AgoClient-wMVUQqCD.cjs");
4
4
  let vue = require("vue");
5
5
  //#region src/vue/symbols.ts
6
6
  var AGO_CLIENT_KEY = Symbol("ago-client");
package/dist/vue.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as AgoClient } from "./AgoClient-CNT-8sh_.js";
1
+ import { t as AgoClient } from "./AgoClient-DPZdN5n2.js";
2
2
  import { computed, inject, onMounted, onScopeDispose, onUnmounted, ref, shallowRef } from "vue";
3
3
  //#region src/vue/symbols.ts
4
4
  var AGO_CLIENT_KEY = Symbol("ago-client");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useago/sdk",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "JavaScript SDK for AGO Chat integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -36,6 +36,11 @@
36
36
  "import": "./dist/widget.js",
37
37
  "require": "./dist/widget.cjs",
38
38
  "types": "./dist/widget.d.ts"
39
+ },
40
+ "./devtools": {
41
+ "import": "./dist/devtools.js",
42
+ "require": "./dist/devtools.cjs",
43
+ "types": "./dist/devtools.d.ts"
39
44
  }
40
45
  },
41
46
  "publishConfig": {