@nimblebrain/synapse 0.2.1 → 0.2.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.
Files changed (34) hide show
  1. package/dist/{chunk-Y4ZDNAYQ.cjs → chunk-MQNKIR7K.cjs} +31 -8
  2. package/dist/chunk-MQNKIR7K.cjs.map +1 -0
  3. package/dist/{chunk-7KEYXJWD.js → chunk-QY4IBJKV.js} +31 -8
  4. package/dist/chunk-QY4IBJKV.js.map +1 -0
  5. package/dist/codegen/cli.cjs +1 -1
  6. package/dist/codegen/cli.js +1 -1
  7. package/dist/codegen/index.d.cts +1 -1
  8. package/dist/codegen/index.d.ts +1 -1
  9. package/dist/index.cjs +4 -4
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +2 -2
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +3 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/react/index.cjs +30 -2
  16. package/dist/react/index.cjs.map +1 -1
  17. package/dist/react/index.d.cts +7 -2
  18. package/dist/react/index.d.ts +7 -2
  19. package/dist/react/index.js +29 -2
  20. package/dist/react/index.js.map +1 -1
  21. package/dist/{server-NNW54YW5.js → server-7BRGSPT3.js} +13 -13
  22. package/dist/{server-NNW54YW5.js.map → server-7BRGSPT3.js.map} +1 -1
  23. package/dist/{server-3BDZ5S72.cjs → server-SRE7E3G3.cjs} +13 -13
  24. package/dist/{server-3BDZ5S72.cjs.map → server-SRE7E3G3.cjs.map} +1 -1
  25. package/dist/synapse-runtime.iife.global.js +1 -1
  26. package/dist/{types-DElq_otH.d.cts → types-CG7zrCn-.d.cts} +31 -3
  27. package/dist/{types-DElq_otH.d.ts → types-CG7zrCn-.d.ts} +31 -3
  28. package/dist/vite/index.cjs +6 -6
  29. package/dist/vite/index.cjs.map +1 -1
  30. package/dist/vite/index.js +6 -6
  31. package/dist/vite/index.js.map +1 -1
  32. package/package.json +1 -1
  33. package/dist/chunk-7KEYXJWD.js.map +0 -1
  34. package/dist/chunk-Y4ZDNAYQ.cjs.map +0 -1
@@ -45,7 +45,7 @@ var KeyboardForwarder = class {
45
45
  if (this.destroyed) return;
46
46
  if (this.shouldForward(event, config)) {
47
47
  event.preventDefault();
48
- transport.send("ui/keydown", {
48
+ transport.send("synapse/keydown", {
49
49
  key: event.key,
50
50
  ctrlKey: event.ctrlKey,
51
51
  metaKey: event.metaKey,
@@ -241,7 +241,7 @@ function createSynapse(options) {
241
241
  currentTheme = { mode, primaryColor: currentTheme.primaryColor, tokens };
242
242
  for (const cb of themeCallbacks) cb(currentTheme);
243
243
  });
244
- const unsubNbTheme = transport.onMessage("ui/themeChanged", (params) => {
244
+ const unsubNbTheme = transport.onMessage("synapse/theme-changed", (params) => {
245
245
  if (!params) return;
246
246
  const mode = params.mode === "dark" || params.mode === "light" ? params.mode : currentTheme.mode;
247
247
  const tokens = params.tokens && typeof params.tokens === "object" ? params.tokens : currentTheme.tokens;
@@ -251,7 +251,7 @@ function createSynapse(options) {
251
251
  const themeCallbacks = /* @__PURE__ */ new Set();
252
252
  const dataCallbacks = /* @__PURE__ */ new Set();
253
253
  const actionCallbacks = /* @__PURE__ */ new Set();
254
- const unsubData = transport.onMessage("ui/datachanged", (params) => {
254
+ const unsubData = transport.onMessage("synapse/data-changed", (params) => {
255
255
  if (!params) return;
256
256
  const event = {
257
257
  source: "agent",
@@ -260,7 +260,7 @@ function createSynapse(options) {
260
260
  };
261
261
  for (const cb of dataCallbacks) cb(event);
262
262
  });
263
- const unsubAction = transport.onMessage("ui/action", (params) => {
263
+ const unsubAction = transport.onMessage("synapse/action", (params) => {
264
264
  if (!params || typeof params.type !== "string") return;
265
265
  const action = {
266
266
  type: params.type,
@@ -315,7 +315,7 @@ function createSynapse(options) {
315
315
  },
316
316
  action(action, params) {
317
317
  if (!isNB()) return;
318
- transport.send("ui/action", { action, ...params });
318
+ transport.send("synapse/action", { action, ...params });
319
319
  },
320
320
  chat(message, context) {
321
321
  const textBlock = { type: "text", text: message };
@@ -342,7 +342,7 @@ function createSynapse(options) {
342
342
  downloadFile(filename, content, mimeType) {
343
343
  if (!isNB()) return;
344
344
  const data = typeof content === "string" ? content : "[Blob content not serializable]";
345
- transport.send("ui/download-file", {
345
+ transport.send("synapse/download-file", {
346
346
  data,
347
347
  filename,
348
348
  mimeType: mimeType ?? "application/octet-stream"
@@ -354,6 +354,29 @@ function createSynapse(options) {
354
354
  window.open(url, "_blank", "noopener");
355
355
  }
356
356
  },
357
+ async requestFile(options2) {
358
+ if (!isNB()) {
359
+ throw new Error("requestFile is not supported in this host");
360
+ }
361
+ const result = await transport.request("synapse/request-file", {
362
+ accept: options2?.accept,
363
+ maxSize: options2?.maxSize ?? 26214400,
364
+ multiple: false
365
+ });
366
+ return result ?? null;
367
+ },
368
+ async requestFiles(options2) {
369
+ if (!isNB()) {
370
+ throw new Error("requestFiles is not supported in this host");
371
+ }
372
+ const result = await transport.request("synapse/request-file", {
373
+ accept: options2?.accept,
374
+ maxSize: options2?.maxSize ?? 26214400,
375
+ multiple: true
376
+ });
377
+ if (!result) return [];
378
+ return Array.isArray(result) ? result : [result];
379
+ },
357
380
  _onMessage(method, callback) {
358
381
  return transport.onMessage(method, callback);
359
382
  },
@@ -379,5 +402,5 @@ function createSynapse(options) {
379
402
  }
380
403
 
381
404
  exports.createSynapse = createSynapse;
382
- //# sourceMappingURL=chunk-Y4ZDNAYQ.cjs.map
383
- //# sourceMappingURL=chunk-Y4ZDNAYQ.cjs.map
405
+ //# sourceMappingURL=chunk-MQNKIR7K.cjs.map
406
+ //# sourceMappingURL=chunk-MQNKIR7K.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/detection.ts","../src/keyboard.ts","../src/result-parser.ts","../src/transport.ts","../src/core.ts"],"names":["options"],"mappings":"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","file":"chunk-MQNKIR7K.cjs","sourcesContent":["import type { HostInfo, SynapseTheme } from \"./types\";\n\nconst DEFAULT_THEME: SynapseTheme = {\n mode: \"light\",\n primaryColor: \"#6366f1\",\n tokens: {},\n};\n\n/**\n * Detect the host environment from the ext-apps `ui/initialize` response.\n *\n * Handles missing or malformed fields gracefully — never throws.\n */\nexport function detectHost(initResponse: unknown): HostInfo {\n const resp = initResponse as Record<string, unknown> | null | undefined;\n\n const serverInfo = safeObj(resp?.serverInfo);\n const serverName = typeof serverInfo?.name === \"string\" ? serverInfo.name : \"unknown\";\n\n const protocolVersion =\n typeof resp?.protocolVersion === \"string\" ? resp.protocolVersion : \"unknown\";\n\n const hostContext = safeObj(resp?.hostContext);\n const theme = extractTheme(hostContext?.theme);\n\n return {\n isNimbleBrain: serverName === \"nimblebrain\",\n serverName,\n protocolVersion,\n theme,\n };\n}\n\nfunction extractTheme(raw: unknown): SynapseTheme {\n const obj = safeObj(raw);\n if (!obj) return { ...DEFAULT_THEME };\n\n const mode = obj.mode === \"light\" || obj.mode === \"dark\" ? obj.mode : DEFAULT_THEME.mode;\n\n const primaryColor =\n typeof obj.primaryColor === \"string\" ? obj.primaryColor : DEFAULT_THEME.primaryColor;\n\n const tokens =\n obj.tokens !== null && typeof obj.tokens === \"object\" && !Array.isArray(obj.tokens)\n ? (obj.tokens as Record<string, string>)\n : {};\n\n return { mode, primaryColor, tokens };\n}\n\nfunction safeObj(value: unknown): Record<string, unknown> | undefined {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n return undefined;\n}\n","import type { SynapseTransport } from \"./transport.js\";\nimport type { KeyForwardConfig } from \"./types.js\";\n\n/**\n * Forward keyboard shortcuts from the iframe document to the host.\n *\n * By default, forwards all Ctrl/Cmd+key combos and Escape.\n * Apps can customize via `forwardKeys` config.\n */\nexport class KeyboardForwarder {\n private listener: (event: KeyboardEvent) => void;\n private destroyed = false;\n\n constructor(transport: SynapseTransport, customKeys?: KeyForwardConfig[]) {\n const config = customKeys ?? null; // null = default behavior\n\n this.listener = (event: KeyboardEvent) => {\n if (this.destroyed) return;\n if (this.shouldForward(event, config)) {\n event.preventDefault();\n transport.send(\"synapse/keydown\", {\n key: event.key,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n });\n }\n };\n\n document.addEventListener(\"keydown\", this.listener);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n document.removeEventListener(\"keydown\", this.listener);\n }\n\n private shouldForward(event: KeyboardEvent, config: KeyForwardConfig[] | null): boolean {\n // Empty array = forwarding disabled\n if (config && config.length === 0) return false;\n\n // Custom config: match exactly\n if (config) {\n return config.some(\n (k) =>\n event.key.toLowerCase() === k.key.toLowerCase() &&\n (k.ctrl === undefined || event.ctrlKey === k.ctrl) &&\n (k.meta === undefined || event.metaKey === k.meta) &&\n (k.shift === undefined || event.shiftKey === k.shift) &&\n (k.alt === undefined || event.altKey === k.alt),\n );\n }\n\n // Default: forward all Ctrl/Cmd combos + Escape,\n // EXCEPT clipboard shortcuts (c, v, x, a) which the browser must handle natively.\n if (event.key === \"Escape\") return true;\n if (event.ctrlKey || event.metaKey) {\n const key = event.key.toLowerCase();\n if (key === \"c\" || key === \"v\" || key === \"x\" || key === \"a\") return false;\n return true;\n }\n return false;\n }\n}\n","import type { ToolCallResult } from \"./types.js\";\n\n/**\n * Normalize a raw tool call response into a consistent `ToolCallResult`.\n *\n * Handles three shapes:\n * 1. MCP `CallToolResult` — has a `content` array with typed blocks.\n * 2. Raw JSON object (NimbleBrain bridge) — used as-is.\n * 3. Null / undefined — returns `{ data: null, isError: false }`.\n */\nexport function parseToolResult(raw: unknown): ToolCallResult {\n if (raw == null) {\n return { data: null, isError: false };\n }\n\n if (isCallToolResult(raw)) {\n return parseCallToolResult(raw);\n }\n\n // Raw JSON object — pass through.\n return { data: raw, isError: false };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ninterface McpTextBlock {\n type: \"text\";\n text: string;\n}\n\ninterface McpCallToolResult {\n content: unknown[];\n isError?: boolean;\n}\n\nfunction isCallToolResult(value: unknown): value is McpCallToolResult {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n return Array.isArray((value as Record<string, unknown>).content);\n}\n\nfunction isTextBlock(block: unknown): block is McpTextBlock {\n if (block === null || typeof block !== \"object\" || Array.isArray(block)) {\n return false;\n }\n const obj = block as Record<string, unknown>;\n return obj.type === \"text\" && typeof obj.text === \"string\";\n}\n\nfunction parseCallToolResult(result: McpCallToolResult): ToolCallResult {\n const isError = result.isError === true;\n const content = result.content;\n\n if (content.length === 0) {\n return { data: null, isError };\n }\n\n const firstText = content.find(isTextBlock);\n\n if (!firstText) {\n // No text blocks — return the full content array so callers can inspect it.\n return { data: content, isError };\n }\n\n // Try to parse JSON from the text block.\n try {\n return { data: JSON.parse(firstText.text), isError };\n } catch {\n // Invalid JSON — return the raw string.\n return { data: firstText.text, isError };\n }\n}\n","import type {\n JsonRpcMessage,\n JsonRpcNotification,\n JsonRpcRequest,\n JsonRpcResponse,\n} from \"./types.js\";\n\ntype PendingEntry = {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n};\n\ntype MessageHandler = (params: Record<string, unknown> | undefined) => void;\n\nexport class SynapseTransport {\n private counter = 0;\n private destroyed = false;\n private pending = new Map<string, PendingEntry>();\n private handlers = new Map<string, Set<MessageHandler>>();\n private listener: (event: MessageEvent) => void;\n\n constructor() {\n this.listener = (event: MessageEvent) => this.handleMessage(event);\n window.addEventListener(\"message\", this.listener);\n }\n\n send(method: string, params?: Record<string, unknown>): void {\n if (this.destroyed) return;\n\n const msg: JsonRpcNotification = {\n jsonrpc: \"2.0\",\n method,\n ...(params !== undefined && { params }),\n };\n window.parent.postMessage(msg, \"*\");\n }\n\n request(method: string, params?: Record<string, unknown>): Promise<unknown> {\n if (this.destroyed) {\n return Promise.reject(new Error(\"Transport destroyed\"));\n }\n\n const id = `syn-${++this.counter}`;\n const msg: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n method,\n id,\n ...(params !== undefined && { params }),\n };\n\n return new Promise<unknown>((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n window.parent.postMessage(msg, \"*\");\n });\n }\n\n onMessage(method: string, callback: MessageHandler): () => void {\n if (!this.handlers.has(method)) {\n this.handlers.set(method, new Set());\n }\n this.handlers.get(method)?.add(callback);\n\n return () => {\n const set = this.handlers.get(method);\n if (set) {\n set.delete(callback);\n if (set.size === 0) {\n this.handlers.delete(method);\n }\n }\n };\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n window.removeEventListener(\"message\", this.listener);\n\n const error = new Error(\"Transport destroyed\");\n for (const entry of this.pending.values()) {\n entry.reject(error);\n }\n this.pending.clear();\n this.handlers.clear();\n }\n\n private handleMessage(event: MessageEvent): void {\n if (this.destroyed) return;\n\n const data = event.data as JsonRpcMessage;\n if (!data || data.jsonrpc !== \"2.0\") return;\n\n // Response to a pending request\n if (\"id\" in data && data.id && !(\"method\" in data)) {\n const response = data as JsonRpcResponse;\n const entry = this.pending.get(response.id);\n if (!entry) return;\n this.pending.delete(response.id);\n\n if (response.error) {\n const err = new Error(response.error.message);\n (err as any).code = response.error.code;\n (err as any).data = response.error.data;\n entry.reject(err);\n } else {\n entry.resolve(response.result);\n }\n return;\n }\n\n // Incoming notification\n if (\"method\" in data && !(\"id\" in data && data.id)) {\n const notification = data as JsonRpcNotification;\n const set = this.handlers.get(notification.method);\n if (set) {\n for (const handler of set) {\n handler(notification.params);\n }\n }\n }\n }\n}\n","import { detectHost } from \"./detection.js\";\nimport { KeyboardForwarder } from \"./keyboard.js\";\nimport { parseToolResult } from \"./result-parser.js\";\nimport { SynapseTransport } from \"./transport.js\";\nimport type {\n AgentAction,\n DataChangedEvent,\n FileResult,\n HostInfo,\n RequestFileOptions,\n Synapse,\n SynapseOptions,\n SynapseTheme,\n ToolCallResult,\n} from \"./types.js\";\n\n/**\n * Create a Synapse instance.\n *\n * Wraps the ext-apps protocol handshake via `SynapseTransport` and provides\n * a typed, framework-agnostic API for calling tools, reacting to data changes,\n * dispatching actions, and pushing LLM-visible state.\n *\n * In non-NimbleBrain hosts, NB-specific methods degrade to no-ops.\n */\nexport function createSynapse(options: SynapseOptions): Synapse {\n const { name, version, internal = false, forwardKeys } = options;\n\n const transport = new SynapseTransport();\n let hostInfo: HostInfo | null = null;\n let currentTheme: SynapseTheme = {\n mode: \"light\",\n primaryColor: \"#6366f1\",\n tokens: {},\n };\n let destroyed = false;\n\n // --- Debounce for setVisibleState ---\n let stateTimer: ReturnType<typeof setTimeout> | null = null;\n\n // --- Keyboard forwarding ---\n let keyboard: KeyboardForwarder | null = null;\n\n // --- ext-apps handshake ---\n // We send ui/initialize as a JSON-RPC request and wait for the response.\n const ready = transport\n .request(\"ui/initialize\", {\n protocolVersion: \"2026-01-26\",\n clientInfo: { name, version },\n capabilities: {},\n })\n .then((result) => {\n hostInfo = detectHost(result);\n currentTheme = hostInfo.theme;\n\n // Send initialized notification per ext-apps spec\n transport.send(\"ui/notifications/initialized\", {});\n\n // Set up keyboard forwarding after we know the host\n keyboard = new KeyboardForwarder(transport, forwardKeys);\n });\n\n // Listen for theme changes from the host\n const unsubTheme = transport.onMessage(\"ui/notifications/host-context-changed\", (params) => {\n if (!params) return;\n const mode = params.theme === \"dark\" ? \"dark\" : \"light\";\n const tokens =\n params.tokens && typeof params.tokens === \"object\"\n ? (params.tokens as Record<string, string>)\n : currentTheme.tokens;\n currentTheme = { mode, primaryColor: currentTheme.primaryColor, tokens };\n for (const cb of themeCallbacks) cb(currentTheme);\n });\n\n // Also listen for NB-specific synapse/theme-changed message\n const unsubNbTheme = transport.onMessage(\"synapse/theme-changed\", (params) => {\n if (!params) return;\n const mode =\n params.mode === \"dark\" || params.mode === \"light\" ? params.mode : currentTheme.mode;\n const tokens =\n params.tokens && typeof params.tokens === \"object\"\n ? (params.tokens as Record<string, string>)\n : currentTheme.tokens;\n currentTheme = { mode, primaryColor: currentTheme.primaryColor, tokens };\n for (const cb of themeCallbacks) cb(currentTheme);\n });\n\n const themeCallbacks = new Set<(theme: SynapseTheme) => void>();\n const dataCallbacks = new Set<(event: DataChangedEvent) => void>();\n const actionCallbacks = new Set<(action: AgentAction) => void>();\n\n // Listen for data change events\n const unsubData = transport.onMessage(\"synapse/data-changed\", (params) => {\n if (!params) return;\n const event: DataChangedEvent = {\n source: \"agent\",\n server: (params.server as string) ?? \"\",\n tool: (params.tool as string) ?? \"\",\n };\n for (const cb of dataCallbacks) cb(event);\n });\n\n // Listen for agent actions (typed, declarative commands from the server)\n const unsubAction = transport.onMessage(\"synapse/action\", (params) => {\n if (!params || typeof params.type !== \"string\") return;\n const action: AgentAction = {\n type: params.type as string,\n payload: (params.payload as Record<string, unknown>) ?? {},\n requiresConfirmation: params.requiresConfirmation === true,\n label: typeof params.label === \"string\" ? params.label : undefined,\n };\n for (const cb of actionCallbacks) cb(action);\n });\n\n const isNB = () => hostInfo?.isNimbleBrain === true;\n\n const synapse: Synapse = {\n get ready() {\n return ready;\n },\n\n get isNimbleBrainHost() {\n return isNB();\n },\n\n get destroyed() {\n return destroyed;\n },\n\n async callTool<TInput = Record<string, unknown>, TOutput = unknown>(\n toolName: string,\n args?: TInput,\n ): Promise<ToolCallResult<TOutput>> {\n const params: Record<string, unknown> = {\n name: toolName,\n arguments: args ?? {},\n };\n // Internal apps can cross-call\n if (internal) {\n params.server = name;\n }\n const raw = await transport.request(\"tools/call\", params);\n return parseToolResult(raw) as ToolCallResult<TOutput>;\n },\n\n onDataChanged(callback: (event: DataChangedEvent) => void): () => void {\n dataCallbacks.add(callback);\n return () => {\n dataCallbacks.delete(callback);\n };\n },\n\n onAction(callback: (action: AgentAction) => void): () => void {\n actionCallbacks.add(callback);\n return () => {\n actionCallbacks.delete(callback);\n };\n },\n\n getTheme(): SynapseTheme {\n return { ...currentTheme };\n },\n\n onThemeChanged(callback: (theme: SynapseTheme) => void): () => void {\n themeCallbacks.add(callback);\n return () => {\n themeCallbacks.delete(callback);\n };\n },\n\n action(action: string, params?: Record<string, unknown>): void {\n if (!isNB()) return;\n transport.send(\"synapse/action\", { action, ...params });\n },\n\n chat(message: string, context?: { action?: string; entity?: string }): void {\n const textBlock: Record<string, unknown> = { type: \"text\", text: message };\n if (isNB() && context) {\n textBlock._meta = { context };\n }\n transport.send(\"ui/message\", {\n role: \"user\",\n content: [textBlock],\n });\n },\n\n setVisibleState(state: Record<string, unknown>, summary?: string): void {\n // Debounce: 250ms\n if (stateTimer) clearTimeout(stateTimer);\n stateTimer = setTimeout(() => {\n transport.send(\"ui/update-model-context\", {\n structuredContent: state,\n ...(summary !== undefined && {\n content: [{ type: \"text\", text: summary }],\n }),\n });\n stateTimer = null;\n }, 250);\n },\n\n downloadFile(filename: string, content: string | Blob, mimeType?: string): void {\n if (!isNB()) return;\n const data = typeof content === \"string\" ? content : \"[Blob content not serializable]\";\n transport.send(\"synapse/download-file\", {\n data,\n filename,\n mimeType: mimeType ?? \"application/octet-stream\",\n });\n },\n\n openLink(url: string): void {\n transport.send(\"ui/open-link\", { url });\n if (!isNB()) {\n window.open(url, \"_blank\", \"noopener\");\n }\n },\n\n async requestFile(options?: RequestFileOptions): Promise<FileResult | null> {\n if (!isNB()) {\n throw new Error(\"requestFile is not supported in this host\");\n }\n const result = await transport.request(\"synapse/request-file\", {\n accept: options?.accept,\n maxSize: options?.maxSize ?? 26_214_400,\n multiple: false,\n });\n return (result as FileResult) ?? null;\n },\n\n async requestFiles(options?: RequestFileOptions): Promise<FileResult[]> {\n if (!isNB()) {\n throw new Error(\"requestFiles is not supported in this host\");\n }\n const result = await transport.request(\"synapse/request-file\", {\n accept: options?.accept,\n maxSize: options?.maxSize ?? 26_214_400,\n multiple: true,\n });\n if (!result) return [];\n return Array.isArray(result) ? (result as FileResult[]) : [result as FileResult];\n },\n\n _onMessage(\n method: string,\n callback: (params: Record<string, unknown> | undefined) => void,\n ): () => void {\n return transport.onMessage(method, callback);\n },\n\n _request(method: string, params?: Record<string, unknown>): Promise<unknown> {\n return transport.request(method, params);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n if (stateTimer) clearTimeout(stateTimer);\n keyboard?.destroy();\n unsubTheme();\n unsubNbTheme();\n unsubData();\n unsubAction();\n themeCallbacks.clear();\n dataCallbacks.clear();\n actionCallbacks.clear();\n transport.destroy();\n },\n };\n\n return synapse;\n}\n"]}
@@ -43,7 +43,7 @@ var KeyboardForwarder = class {
43
43
  if (this.destroyed) return;
44
44
  if (this.shouldForward(event, config)) {
45
45
  event.preventDefault();
46
- transport.send("ui/keydown", {
46
+ transport.send("synapse/keydown", {
47
47
  key: event.key,
48
48
  ctrlKey: event.ctrlKey,
49
49
  metaKey: event.metaKey,
@@ -239,7 +239,7 @@ function createSynapse(options) {
239
239
  currentTheme = { mode, primaryColor: currentTheme.primaryColor, tokens };
240
240
  for (const cb of themeCallbacks) cb(currentTheme);
241
241
  });
242
- const unsubNbTheme = transport.onMessage("ui/themeChanged", (params) => {
242
+ const unsubNbTheme = transport.onMessage("synapse/theme-changed", (params) => {
243
243
  if (!params) return;
244
244
  const mode = params.mode === "dark" || params.mode === "light" ? params.mode : currentTheme.mode;
245
245
  const tokens = params.tokens && typeof params.tokens === "object" ? params.tokens : currentTheme.tokens;
@@ -249,7 +249,7 @@ function createSynapse(options) {
249
249
  const themeCallbacks = /* @__PURE__ */ new Set();
250
250
  const dataCallbacks = /* @__PURE__ */ new Set();
251
251
  const actionCallbacks = /* @__PURE__ */ new Set();
252
- const unsubData = transport.onMessage("ui/datachanged", (params) => {
252
+ const unsubData = transport.onMessage("synapse/data-changed", (params) => {
253
253
  if (!params) return;
254
254
  const event = {
255
255
  source: "agent",
@@ -258,7 +258,7 @@ function createSynapse(options) {
258
258
  };
259
259
  for (const cb of dataCallbacks) cb(event);
260
260
  });
261
- const unsubAction = transport.onMessage("ui/action", (params) => {
261
+ const unsubAction = transport.onMessage("synapse/action", (params) => {
262
262
  if (!params || typeof params.type !== "string") return;
263
263
  const action = {
264
264
  type: params.type,
@@ -313,7 +313,7 @@ function createSynapse(options) {
313
313
  },
314
314
  action(action, params) {
315
315
  if (!isNB()) return;
316
- transport.send("ui/action", { action, ...params });
316
+ transport.send("synapse/action", { action, ...params });
317
317
  },
318
318
  chat(message, context) {
319
319
  const textBlock = { type: "text", text: message };
@@ -340,7 +340,7 @@ function createSynapse(options) {
340
340
  downloadFile(filename, content, mimeType) {
341
341
  if (!isNB()) return;
342
342
  const data = typeof content === "string" ? content : "[Blob content not serializable]";
343
- transport.send("ui/download-file", {
343
+ transport.send("synapse/download-file", {
344
344
  data,
345
345
  filename,
346
346
  mimeType: mimeType ?? "application/octet-stream"
@@ -352,6 +352,29 @@ function createSynapse(options) {
352
352
  window.open(url, "_blank", "noopener");
353
353
  }
354
354
  },
355
+ async requestFile(options2) {
356
+ if (!isNB()) {
357
+ throw new Error("requestFile is not supported in this host");
358
+ }
359
+ const result = await transport.request("synapse/request-file", {
360
+ accept: options2?.accept,
361
+ maxSize: options2?.maxSize ?? 26214400,
362
+ multiple: false
363
+ });
364
+ return result ?? null;
365
+ },
366
+ async requestFiles(options2) {
367
+ if (!isNB()) {
368
+ throw new Error("requestFiles is not supported in this host");
369
+ }
370
+ const result = await transport.request("synapse/request-file", {
371
+ accept: options2?.accept,
372
+ maxSize: options2?.maxSize ?? 26214400,
373
+ multiple: true
374
+ });
375
+ if (!result) return [];
376
+ return Array.isArray(result) ? result : [result];
377
+ },
355
378
  _onMessage(method, callback) {
356
379
  return transport.onMessage(method, callback);
357
380
  },
@@ -377,5 +400,5 @@ function createSynapse(options) {
377
400
  }
378
401
 
379
402
  export { createSynapse };
380
- //# sourceMappingURL=chunk-7KEYXJWD.js.map
381
- //# sourceMappingURL=chunk-7KEYXJWD.js.map
403
+ //# sourceMappingURL=chunk-QY4IBJKV.js.map
404
+ //# sourceMappingURL=chunk-QY4IBJKV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/detection.ts","../src/keyboard.ts","../src/result-parser.ts","../src/transport.ts","../src/core.ts"],"names":["options"],"mappings":"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","file":"chunk-QY4IBJKV.js","sourcesContent":["import type { HostInfo, SynapseTheme } from \"./types\";\n\nconst DEFAULT_THEME: SynapseTheme = {\n mode: \"light\",\n primaryColor: \"#6366f1\",\n tokens: {},\n};\n\n/**\n * Detect the host environment from the ext-apps `ui/initialize` response.\n *\n * Handles missing or malformed fields gracefully — never throws.\n */\nexport function detectHost(initResponse: unknown): HostInfo {\n const resp = initResponse as Record<string, unknown> | null | undefined;\n\n const serverInfo = safeObj(resp?.serverInfo);\n const serverName = typeof serverInfo?.name === \"string\" ? serverInfo.name : \"unknown\";\n\n const protocolVersion =\n typeof resp?.protocolVersion === \"string\" ? resp.protocolVersion : \"unknown\";\n\n const hostContext = safeObj(resp?.hostContext);\n const theme = extractTheme(hostContext?.theme);\n\n return {\n isNimbleBrain: serverName === \"nimblebrain\",\n serverName,\n protocolVersion,\n theme,\n };\n}\n\nfunction extractTheme(raw: unknown): SynapseTheme {\n const obj = safeObj(raw);\n if (!obj) return { ...DEFAULT_THEME };\n\n const mode = obj.mode === \"light\" || obj.mode === \"dark\" ? obj.mode : DEFAULT_THEME.mode;\n\n const primaryColor =\n typeof obj.primaryColor === \"string\" ? obj.primaryColor : DEFAULT_THEME.primaryColor;\n\n const tokens =\n obj.tokens !== null && typeof obj.tokens === \"object\" && !Array.isArray(obj.tokens)\n ? (obj.tokens as Record<string, string>)\n : {};\n\n return { mode, primaryColor, tokens };\n}\n\nfunction safeObj(value: unknown): Record<string, unknown> | undefined {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n return undefined;\n}\n","import type { SynapseTransport } from \"./transport.js\";\nimport type { KeyForwardConfig } from \"./types.js\";\n\n/**\n * Forward keyboard shortcuts from the iframe document to the host.\n *\n * By default, forwards all Ctrl/Cmd+key combos and Escape.\n * Apps can customize via `forwardKeys` config.\n */\nexport class KeyboardForwarder {\n private listener: (event: KeyboardEvent) => void;\n private destroyed = false;\n\n constructor(transport: SynapseTransport, customKeys?: KeyForwardConfig[]) {\n const config = customKeys ?? null; // null = default behavior\n\n this.listener = (event: KeyboardEvent) => {\n if (this.destroyed) return;\n if (this.shouldForward(event, config)) {\n event.preventDefault();\n transport.send(\"synapse/keydown\", {\n key: event.key,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n });\n }\n };\n\n document.addEventListener(\"keydown\", this.listener);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n document.removeEventListener(\"keydown\", this.listener);\n }\n\n private shouldForward(event: KeyboardEvent, config: KeyForwardConfig[] | null): boolean {\n // Empty array = forwarding disabled\n if (config && config.length === 0) return false;\n\n // Custom config: match exactly\n if (config) {\n return config.some(\n (k) =>\n event.key.toLowerCase() === k.key.toLowerCase() &&\n (k.ctrl === undefined || event.ctrlKey === k.ctrl) &&\n (k.meta === undefined || event.metaKey === k.meta) &&\n (k.shift === undefined || event.shiftKey === k.shift) &&\n (k.alt === undefined || event.altKey === k.alt),\n );\n }\n\n // Default: forward all Ctrl/Cmd combos + Escape,\n // EXCEPT clipboard shortcuts (c, v, x, a) which the browser must handle natively.\n if (event.key === \"Escape\") return true;\n if (event.ctrlKey || event.metaKey) {\n const key = event.key.toLowerCase();\n if (key === \"c\" || key === \"v\" || key === \"x\" || key === \"a\") return false;\n return true;\n }\n return false;\n }\n}\n","import type { ToolCallResult } from \"./types.js\";\n\n/**\n * Normalize a raw tool call response into a consistent `ToolCallResult`.\n *\n * Handles three shapes:\n * 1. MCP `CallToolResult` — has a `content` array with typed blocks.\n * 2. Raw JSON object (NimbleBrain bridge) — used as-is.\n * 3. Null / undefined — returns `{ data: null, isError: false }`.\n */\nexport function parseToolResult(raw: unknown): ToolCallResult {\n if (raw == null) {\n return { data: null, isError: false };\n }\n\n if (isCallToolResult(raw)) {\n return parseCallToolResult(raw);\n }\n\n // Raw JSON object — pass through.\n return { data: raw, isError: false };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ninterface McpTextBlock {\n type: \"text\";\n text: string;\n}\n\ninterface McpCallToolResult {\n content: unknown[];\n isError?: boolean;\n}\n\nfunction isCallToolResult(value: unknown): value is McpCallToolResult {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n return Array.isArray((value as Record<string, unknown>).content);\n}\n\nfunction isTextBlock(block: unknown): block is McpTextBlock {\n if (block === null || typeof block !== \"object\" || Array.isArray(block)) {\n return false;\n }\n const obj = block as Record<string, unknown>;\n return obj.type === \"text\" && typeof obj.text === \"string\";\n}\n\nfunction parseCallToolResult(result: McpCallToolResult): ToolCallResult {\n const isError = result.isError === true;\n const content = result.content;\n\n if (content.length === 0) {\n return { data: null, isError };\n }\n\n const firstText = content.find(isTextBlock);\n\n if (!firstText) {\n // No text blocks — return the full content array so callers can inspect it.\n return { data: content, isError };\n }\n\n // Try to parse JSON from the text block.\n try {\n return { data: JSON.parse(firstText.text), isError };\n } catch {\n // Invalid JSON — return the raw string.\n return { data: firstText.text, isError };\n }\n}\n","import type {\n JsonRpcMessage,\n JsonRpcNotification,\n JsonRpcRequest,\n JsonRpcResponse,\n} from \"./types.js\";\n\ntype PendingEntry = {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n};\n\ntype MessageHandler = (params: Record<string, unknown> | undefined) => void;\n\nexport class SynapseTransport {\n private counter = 0;\n private destroyed = false;\n private pending = new Map<string, PendingEntry>();\n private handlers = new Map<string, Set<MessageHandler>>();\n private listener: (event: MessageEvent) => void;\n\n constructor() {\n this.listener = (event: MessageEvent) => this.handleMessage(event);\n window.addEventListener(\"message\", this.listener);\n }\n\n send(method: string, params?: Record<string, unknown>): void {\n if (this.destroyed) return;\n\n const msg: JsonRpcNotification = {\n jsonrpc: \"2.0\",\n method,\n ...(params !== undefined && { params }),\n };\n window.parent.postMessage(msg, \"*\");\n }\n\n request(method: string, params?: Record<string, unknown>): Promise<unknown> {\n if (this.destroyed) {\n return Promise.reject(new Error(\"Transport destroyed\"));\n }\n\n const id = `syn-${++this.counter}`;\n const msg: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n method,\n id,\n ...(params !== undefined && { params }),\n };\n\n return new Promise<unknown>((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n window.parent.postMessage(msg, \"*\");\n });\n }\n\n onMessage(method: string, callback: MessageHandler): () => void {\n if (!this.handlers.has(method)) {\n this.handlers.set(method, new Set());\n }\n this.handlers.get(method)?.add(callback);\n\n return () => {\n const set = this.handlers.get(method);\n if (set) {\n set.delete(callback);\n if (set.size === 0) {\n this.handlers.delete(method);\n }\n }\n };\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n window.removeEventListener(\"message\", this.listener);\n\n const error = new Error(\"Transport destroyed\");\n for (const entry of this.pending.values()) {\n entry.reject(error);\n }\n this.pending.clear();\n this.handlers.clear();\n }\n\n private handleMessage(event: MessageEvent): void {\n if (this.destroyed) return;\n\n const data = event.data as JsonRpcMessage;\n if (!data || data.jsonrpc !== \"2.0\") return;\n\n // Response to a pending request\n if (\"id\" in data && data.id && !(\"method\" in data)) {\n const response = data as JsonRpcResponse;\n const entry = this.pending.get(response.id);\n if (!entry) return;\n this.pending.delete(response.id);\n\n if (response.error) {\n const err = new Error(response.error.message);\n (err as any).code = response.error.code;\n (err as any).data = response.error.data;\n entry.reject(err);\n } else {\n entry.resolve(response.result);\n }\n return;\n }\n\n // Incoming notification\n if (\"method\" in data && !(\"id\" in data && data.id)) {\n const notification = data as JsonRpcNotification;\n const set = this.handlers.get(notification.method);\n if (set) {\n for (const handler of set) {\n handler(notification.params);\n }\n }\n }\n }\n}\n","import { detectHost } from \"./detection.js\";\nimport { KeyboardForwarder } from \"./keyboard.js\";\nimport { parseToolResult } from \"./result-parser.js\";\nimport { SynapseTransport } from \"./transport.js\";\nimport type {\n AgentAction,\n DataChangedEvent,\n FileResult,\n HostInfo,\n RequestFileOptions,\n Synapse,\n SynapseOptions,\n SynapseTheme,\n ToolCallResult,\n} from \"./types.js\";\n\n/**\n * Create a Synapse instance.\n *\n * Wraps the ext-apps protocol handshake via `SynapseTransport` and provides\n * a typed, framework-agnostic API for calling tools, reacting to data changes,\n * dispatching actions, and pushing LLM-visible state.\n *\n * In non-NimbleBrain hosts, NB-specific methods degrade to no-ops.\n */\nexport function createSynapse(options: SynapseOptions): Synapse {\n const { name, version, internal = false, forwardKeys } = options;\n\n const transport = new SynapseTransport();\n let hostInfo: HostInfo | null = null;\n let currentTheme: SynapseTheme = {\n mode: \"light\",\n primaryColor: \"#6366f1\",\n tokens: {},\n };\n let destroyed = false;\n\n // --- Debounce for setVisibleState ---\n let stateTimer: ReturnType<typeof setTimeout> | null = null;\n\n // --- Keyboard forwarding ---\n let keyboard: KeyboardForwarder | null = null;\n\n // --- ext-apps handshake ---\n // We send ui/initialize as a JSON-RPC request and wait for the response.\n const ready = transport\n .request(\"ui/initialize\", {\n protocolVersion: \"2026-01-26\",\n clientInfo: { name, version },\n capabilities: {},\n })\n .then((result) => {\n hostInfo = detectHost(result);\n currentTheme = hostInfo.theme;\n\n // Send initialized notification per ext-apps spec\n transport.send(\"ui/notifications/initialized\", {});\n\n // Set up keyboard forwarding after we know the host\n keyboard = new KeyboardForwarder(transport, forwardKeys);\n });\n\n // Listen for theme changes from the host\n const unsubTheme = transport.onMessage(\"ui/notifications/host-context-changed\", (params) => {\n if (!params) return;\n const mode = params.theme === \"dark\" ? \"dark\" : \"light\";\n const tokens =\n params.tokens && typeof params.tokens === \"object\"\n ? (params.tokens as Record<string, string>)\n : currentTheme.tokens;\n currentTheme = { mode, primaryColor: currentTheme.primaryColor, tokens };\n for (const cb of themeCallbacks) cb(currentTheme);\n });\n\n // Also listen for NB-specific synapse/theme-changed message\n const unsubNbTheme = transport.onMessage(\"synapse/theme-changed\", (params) => {\n if (!params) return;\n const mode =\n params.mode === \"dark\" || params.mode === \"light\" ? params.mode : currentTheme.mode;\n const tokens =\n params.tokens && typeof params.tokens === \"object\"\n ? (params.tokens as Record<string, string>)\n : currentTheme.tokens;\n currentTheme = { mode, primaryColor: currentTheme.primaryColor, tokens };\n for (const cb of themeCallbacks) cb(currentTheme);\n });\n\n const themeCallbacks = new Set<(theme: SynapseTheme) => void>();\n const dataCallbacks = new Set<(event: DataChangedEvent) => void>();\n const actionCallbacks = new Set<(action: AgentAction) => void>();\n\n // Listen for data change events\n const unsubData = transport.onMessage(\"synapse/data-changed\", (params) => {\n if (!params) return;\n const event: DataChangedEvent = {\n source: \"agent\",\n server: (params.server as string) ?? \"\",\n tool: (params.tool as string) ?? \"\",\n };\n for (const cb of dataCallbacks) cb(event);\n });\n\n // Listen for agent actions (typed, declarative commands from the server)\n const unsubAction = transport.onMessage(\"synapse/action\", (params) => {\n if (!params || typeof params.type !== \"string\") return;\n const action: AgentAction = {\n type: params.type as string,\n payload: (params.payload as Record<string, unknown>) ?? {},\n requiresConfirmation: params.requiresConfirmation === true,\n label: typeof params.label === \"string\" ? params.label : undefined,\n };\n for (const cb of actionCallbacks) cb(action);\n });\n\n const isNB = () => hostInfo?.isNimbleBrain === true;\n\n const synapse: Synapse = {\n get ready() {\n return ready;\n },\n\n get isNimbleBrainHost() {\n return isNB();\n },\n\n get destroyed() {\n return destroyed;\n },\n\n async callTool<TInput = Record<string, unknown>, TOutput = unknown>(\n toolName: string,\n args?: TInput,\n ): Promise<ToolCallResult<TOutput>> {\n const params: Record<string, unknown> = {\n name: toolName,\n arguments: args ?? {},\n };\n // Internal apps can cross-call\n if (internal) {\n params.server = name;\n }\n const raw = await transport.request(\"tools/call\", params);\n return parseToolResult(raw) as ToolCallResult<TOutput>;\n },\n\n onDataChanged(callback: (event: DataChangedEvent) => void): () => void {\n dataCallbacks.add(callback);\n return () => {\n dataCallbacks.delete(callback);\n };\n },\n\n onAction(callback: (action: AgentAction) => void): () => void {\n actionCallbacks.add(callback);\n return () => {\n actionCallbacks.delete(callback);\n };\n },\n\n getTheme(): SynapseTheme {\n return { ...currentTheme };\n },\n\n onThemeChanged(callback: (theme: SynapseTheme) => void): () => void {\n themeCallbacks.add(callback);\n return () => {\n themeCallbacks.delete(callback);\n };\n },\n\n action(action: string, params?: Record<string, unknown>): void {\n if (!isNB()) return;\n transport.send(\"synapse/action\", { action, ...params });\n },\n\n chat(message: string, context?: { action?: string; entity?: string }): void {\n const textBlock: Record<string, unknown> = { type: \"text\", text: message };\n if (isNB() && context) {\n textBlock._meta = { context };\n }\n transport.send(\"ui/message\", {\n role: \"user\",\n content: [textBlock],\n });\n },\n\n setVisibleState(state: Record<string, unknown>, summary?: string): void {\n // Debounce: 250ms\n if (stateTimer) clearTimeout(stateTimer);\n stateTimer = setTimeout(() => {\n transport.send(\"ui/update-model-context\", {\n structuredContent: state,\n ...(summary !== undefined && {\n content: [{ type: \"text\", text: summary }],\n }),\n });\n stateTimer = null;\n }, 250);\n },\n\n downloadFile(filename: string, content: string | Blob, mimeType?: string): void {\n if (!isNB()) return;\n const data = typeof content === \"string\" ? content : \"[Blob content not serializable]\";\n transport.send(\"synapse/download-file\", {\n data,\n filename,\n mimeType: mimeType ?? \"application/octet-stream\",\n });\n },\n\n openLink(url: string): void {\n transport.send(\"ui/open-link\", { url });\n if (!isNB()) {\n window.open(url, \"_blank\", \"noopener\");\n }\n },\n\n async requestFile(options?: RequestFileOptions): Promise<FileResult | null> {\n if (!isNB()) {\n throw new Error(\"requestFile is not supported in this host\");\n }\n const result = await transport.request(\"synapse/request-file\", {\n accept: options?.accept,\n maxSize: options?.maxSize ?? 26_214_400,\n multiple: false,\n });\n return (result as FileResult) ?? null;\n },\n\n async requestFiles(options?: RequestFileOptions): Promise<FileResult[]> {\n if (!isNB()) {\n throw new Error(\"requestFiles is not supported in this host\");\n }\n const result = await transport.request(\"synapse/request-file\", {\n accept: options?.accept,\n maxSize: options?.maxSize ?? 26_214_400,\n multiple: true,\n });\n if (!result) return [];\n return Array.isArray(result) ? (result as FileResult[]) : [result as FileResult];\n },\n\n _onMessage(\n method: string,\n callback: (params: Record<string, unknown> | undefined) => void,\n ): () => void {\n return transport.onMessage(method, callback);\n },\n\n _request(method: string, params?: Record<string, unknown>): Promise<unknown> {\n return transport.request(method, params);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n if (stateTimer) clearTimeout(stateTimer);\n keyboard?.destroy();\n unsubTheme();\n unsubNbTheme();\n unsubData();\n unsubAction();\n themeCallbacks.clear();\n dataCallbacks.clear();\n actionCallbacks.clear();\n transport.destroy();\n },\n };\n\n return synapse;\n}\n"]}
@@ -58,7 +58,7 @@ async function runCodegen(args2) {
58
58
  }
59
59
  }
60
60
  async function runPreview(args2) {
61
- const { startPreview } = await import('../server-3BDZ5S72.cjs');
61
+ const { startPreview } = await import('../server-SRE7E3G3.cjs');
62
62
  const flags = parseFlags(args2, ["server", "ui", "server-port", "ui-port", "port"]);
63
63
  if (!flags.server || !flags.ui) {
64
64
  console.error("Usage:");
@@ -56,7 +56,7 @@ async function runCodegen(args2) {
56
56
  }
57
57
  }
58
58
  async function runPreview(args2) {
59
- const { startPreview } = await import('../server-NNW54YW5.js');
59
+ const { startPreview } = await import('../server-7BRGSPT3.js');
60
60
  const flags = parseFlags(args2, ["server", "ui", "server-port", "ui-port", "port"]);
61
61
  if (!flags.server || !flags.ui) {
62
62
  console.error("Usage:");
@@ -1,4 +1,4 @@
1
- import { i as ToolDefinition } from '../types-DElq_otH.cjs';
1
+ import { i as ToolDefinition } from '../types-CG7zrCn-.cjs';
2
2
 
3
3
  /**
4
4
  * Read tool definitions from a manifest.json file.
@@ -1,4 +1,4 @@
1
- import { i as ToolDefinition } from '../types-DElq_otH.js';
1
+ import { i as ToolDefinition } from '../types-CG7zrCn-.js';
2
2
 
3
3
  /**
4
4
  * Read tool definitions from a manifest.json file.
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkY4ZDNAYQ_cjs = require('./chunk-Y4ZDNAYQ.cjs');
3
+ var chunkMQNKIR7K_cjs = require('./chunk-MQNKIR7K.cjs');
4
4
 
5
5
  // src/store.ts
6
6
  function createStore(synapse, config) {
@@ -28,7 +28,7 @@ function createStore(synapse, config) {
28
28
  function schedulePersist() {
29
29
  if (persistTimer) clearTimeout(persistTimer);
30
30
  persistTimer = setTimeout(() => {
31
- synapse._request("ui/persistState", {
31
+ synapse._request("synapse/persist-state", {
32
32
  state,
33
33
  version: config.version
34
34
  }).catch(() => {
@@ -38,7 +38,7 @@ function createStore(synapse, config) {
38
38
  }
39
39
  let unsubStateLoaded;
40
40
  if (config.persist) {
41
- unsubStateLoaded = synapse._onMessage("ui/stateLoaded", (params) => {
41
+ unsubStateLoaded = synapse._onMessage("synapse/state-loaded", (params) => {
42
42
  if (!params?.state) return;
43
43
  let loaded = params.state;
44
44
  const loadedVersion = params.version ?? 1;
@@ -80,7 +80,7 @@ function createStore(synapse, config) {
80
80
 
81
81
  Object.defineProperty(exports, "createSynapse", {
82
82
  enumerable: true,
83
- get: function () { return chunkY4ZDNAYQ_cjs.createSynapse; }
83
+ get: function () { return chunkMQNKIR7K_cjs.createSynapse; }
84
84
  });
85
85
  exports.createStore = createStore;
86
86
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"ui/persistState\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"ui/stateLoaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
1
+ {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"synapse/persist-state\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"synapse/state-loaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as SynapseOptions, a as Synapse, A as ActionReducer, b as StoreConfig, c as Store } from './types-DElq_otH.cjs';
2
- export { d as AgentAction, B as BuiltinActionType, D as DataChangedEvent, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, e as NotifyPayload, f as StateAcknowledgement, g as StoreDispatch, h as SynapseTheme, T as ToolCallResult, i as ToolDefinition, V as VisibleState } from './types-DElq_otH.cjs';
1
+ import { S as SynapseOptions, a as Synapse, A as ActionReducer, b as StoreConfig, c as Store } from './types-CG7zrCn-.cjs';
2
+ export { d as AgentAction, B as BuiltinActionType, D as DataChangedEvent, F as FileResult, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, e as NotifyPayload, R as RequestFileOptions, f as StateAcknowledgement, g as StoreDispatch, h as SynapseTheme, T as ToolCallResult, i as ToolDefinition, V as VisibleState } from './types-CG7zrCn-.cjs';
3
3
 
4
4
  /**
5
5
  * Create a Synapse instance.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as SynapseOptions, a as Synapse, A as ActionReducer, b as StoreConfig, c as Store } from './types-DElq_otH.js';
2
- export { d as AgentAction, B as BuiltinActionType, D as DataChangedEvent, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, e as NotifyPayload, f as StateAcknowledgement, g as StoreDispatch, h as SynapseTheme, T as ToolCallResult, i as ToolDefinition, V as VisibleState } from './types-DElq_otH.js';
1
+ import { S as SynapseOptions, a as Synapse, A as ActionReducer, b as StoreConfig, c as Store } from './types-CG7zrCn-.js';
2
+ export { d as AgentAction, B as BuiltinActionType, D as DataChangedEvent, F as FileResult, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, e as NotifyPayload, R as RequestFileOptions, f as StateAcknowledgement, g as StoreDispatch, h as SynapseTheme, T as ToolCallResult, i as ToolDefinition, V as VisibleState } from './types-CG7zrCn-.js';
3
3
 
4
4
  /**
5
5
  * Create a Synapse instance.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { createSynapse } from './chunk-7KEYXJWD.js';
1
+ export { createSynapse } from './chunk-QY4IBJKV.js';
2
2
 
3
3
  // src/store.ts
4
4
  function createStore(synapse, config) {
@@ -26,7 +26,7 @@ function createStore(synapse, config) {
26
26
  function schedulePersist() {
27
27
  if (persistTimer) clearTimeout(persistTimer);
28
28
  persistTimer = setTimeout(() => {
29
- synapse._request("ui/persistState", {
29
+ synapse._request("synapse/persist-state", {
30
30
  state,
31
31
  version: config.version
32
32
  }).catch(() => {
@@ -36,7 +36,7 @@ function createStore(synapse, config) {
36
36
  }
37
37
  let unsubStateLoaded;
38
38
  if (config.persist) {
39
- unsubStateLoaded = synapse._onMessage("ui/stateLoaded", (params) => {
39
+ unsubStateLoaded = synapse._onMessage("synapse/state-loaded", (params) => {
40
40
  if (!params?.state) return;
41
41
  let loaded = params.state;
42
42
  const loadedVersion = params.version ?? 1;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"ui/persistState\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"ui/stateLoaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
1
+ {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"synapse/persist-state\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"synapse/state-loaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkY4ZDNAYQ_cjs = require('../chunk-Y4ZDNAYQ.cjs');
3
+ var chunkMQNKIR7K_cjs = require('../chunk-MQNKIR7K.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
@@ -8,7 +8,7 @@ var SynapseContext = react.createContext(null);
8
8
  function SynapseProvider({ children, ...options }) {
9
9
  const ref = react.useRef(null);
10
10
  if (ref.current === null || ref.current.destroyed) {
11
- ref.current = chunkY4ZDNAYQ_cjs.createSynapse(options);
11
+ ref.current = chunkMQNKIR7K_cjs.createSynapse(options);
12
12
  }
13
13
  return /* @__PURE__ */ jsxRuntime.jsx(SynapseContext.Provider, { value: ref.current, children });
14
14
  }
@@ -111,6 +111,33 @@ function useVisibleState(factory, deps) {
111
111
  }, [...deps ?? [], push]);
112
112
  if (!factory) return push;
113
113
  }
114
+ function useFileUpload() {
115
+ const synapse = useSynapseContext();
116
+ const [isPending, setIsPending] = react.useState(false);
117
+ const requestFile = react.useCallback(
118
+ async (options) => {
119
+ setIsPending(true);
120
+ try {
121
+ return await synapse.requestFile(options);
122
+ } finally {
123
+ setIsPending(false);
124
+ }
125
+ },
126
+ [synapse]
127
+ );
128
+ const requestFiles = react.useCallback(
129
+ async (options) => {
130
+ setIsPending(true);
131
+ try {
132
+ return await synapse.requestFiles(options);
133
+ } finally {
134
+ setIsPending(false);
135
+ }
136
+ },
137
+ [synapse]
138
+ );
139
+ return { requestFile, requestFiles, isPending };
140
+ }
114
141
  function useStore(store) {
115
142
  const state = react.useSyncExternalStore(
116
143
  (onStoreChange) => store.subscribe(onStoreChange),
@@ -126,6 +153,7 @@ exports.useAgentAction = useAgentAction;
126
153
  exports.useCallTool = useCallTool;
127
154
  exports.useChat = useChat;
128
155
  exports.useDataSync = useDataSync;
156
+ exports.useFileUpload = useFileUpload;
129
157
  exports.useStore = useStore;
130
158
  exports.useSynapse = useSynapse;
131
159
  exports.useTheme = useTheme;