@miiflow/assistant-ui 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ import {prepare,layout,clearCache}from'@chenglou/pretext';var u={spacing:{messageBetween:"1rem",messagePx:"0.875rem",messagePy:"0.625rem",container:"1rem",composerPadding:"1rem"},typography:{message:{fontSize:"1rem",lineHeight:1.5,letterSpacing:"0px"},caption:{fontSize:"0.875rem",lineHeight:1.4},small:{fontSize:"0.8125rem",lineHeight:1.3}},borderRadius:{message:"0.5rem",input:"1rem",panel:"0.5rem",button:"0.5rem",chip:"0.25rem"},colors:{primary:"var(--chat-primary, #106997)",secondary:"var(--chat-secondary, #56C18A)",error:"var(--chat-error, #B1001B)",warning:"var(--chat-warning, #DD9652)",messageBg:"var(--chat-message-bg, rgba(0, 0, 0, 0.03))",userMessageBg:"var(--chat-user-message-bg, var(--chat-primary, #106997))",userMessageText:"var(--chat-user-message-text, #ffffff)",panelBg:"var(--chat-panel-bg, rgba(0, 0, 0, 0.02))",panelBorder:"var(--chat-panel-border, rgba(0, 0, 0, 0.06))",border:"var(--chat-border, rgba(0, 0, 0, 0.06))",borderHover:"var(--chat-border-hover, rgba(0, 0, 0, 0.12))",text:"var(--chat-text, #1D2033)",subtle:"var(--chat-text-subtle, rgba(0, 0, 0, 0.5))",placeholder:"var(--chat-placeholder, rgba(0, 0, 0, 0.4))",status:{pending:{main:"rgba(0, 0, 0, 0.3)",bg:"rgba(0, 0, 0, 0.05)"},running:{main:"rgb(99, 102, 241)",bg:"rgba(99, 102, 241, 0.08)"},completed:{main:"rgb(16, 185, 129)",bg:"rgba(16, 185, 129, 0.08)"},failed:{main:"rgb(239, 68, 68)",bg:"rgba(239, 68, 68, 0.08)"}}},shadows:{subtle:"0 1px 2px rgba(0, 0, 0, 0.04)",input:"0 2px 8px rgba(0, 0, 0, 0.08)",inputFocus:"0 4px 16px rgba(0, 0, 0, 0.12)",button:"0 1px 3px rgba(0, 0, 0, 0.08)",buttonHover:"0 2px 6px rgba(0, 0, 0, 0.12)",primary:"0 2px 6px rgba(16, 105, 151, 0.3)",primaryHover:"0 4px 12px rgba(16, 105, 151, 0.4)"},animations:{messageEntrance:{initial:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{duration:.3,ease:[.4,0,.2,1]}},fadeIn:{initial:{opacity:0},animate:{opacity:1},transition:{duration:.2}}}};var h=16,x=h*u.typography.message.lineHeight,f=`400 ${h}px "Inter", "Assistant", -apple-system, sans-serif`,y=512,t=new Map;function v(e){let r=t.get(e);return r&&(t.delete(e),t.set(e,r)),r}function T(e,r){if(t.set(e,r),t.size>y){let a=t.keys().next().value;a!==void 0&&t.delete(a);}}function P(e,r,a={}){if(!e||r<=0)return {height:0,lineCount:0};if(typeof document>"u")return null;let n=a.font??f,s=a.lineHeightPx??x,i=Math.round(r),o=`${n}|${s}|${i}|${e}`,c=v(o);if(c)return c;try{let m=prepare(e,n),g=layout(m,i,s),p={height:g.height,lineCount:g.lineCount};return T(o,p),p}catch{return null}}function A(){t.clear();try{clearCache();}catch{}}export{u as a,P as b,A as c};//# sourceMappingURL=chunk-O2ILSWHS.js.map
2
+ //# sourceMappingURL=chunk-O2ILSWHS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/styles/tokens.ts","../src/utils/measureMessage.ts"],"names":["chatTokens","DEFAULT_FONT_PX","DEFAULT_LINE_HEIGHT_PX","DEFAULT_FONT","CACHE_MAX","cache","cacheGet","key","hit","cacheSet","value","oldest","measureMessageHeight","text","maxWidth","options","font","lineHeightPx","snappedWidth","cached","prepared","prepare","result","layout","measured","clearMeasurementCache","clearCache"],"mappings":"0DAKO,IAAMA,EAAa,CACxB,OAAA,CAAS,CAEP,cAAA,CAAgB,MAAA,CAEhB,UAAW,UAAA,CAEX,SAAA,CAAW,WAEX,SAAA,CAAW,MAAA,CAEX,gBAAiB,MACnB,CAAA,CAEA,WAAY,CACV,OAAA,CAAS,CACP,QAAA,CAAU,MAAA,CACV,UAAA,CAAY,GAAA,CACZ,cAAe,KACjB,CAAA,CACA,QAAS,CACP,QAAA,CAAU,WACV,UAAA,CAAY,GACd,EACA,KAAA,CAAO,CACL,SAAU,WAAA,CACV,UAAA,CAAY,GACd,CACF,CAAA,CAEA,aAAc,CACZ,OAAA,CAAS,QAAA,CACT,KAAA,CAAO,OACP,KAAA,CAAO,QAAA,CACP,OAAQ,QAAA,CACR,IAAA,CAAM,SACR,CAAA,CAEA,MAAA,CAAQ,CAEN,OAAA,CAAS,8BAAA,CACT,UAAW,gCAAA,CACX,KAAA,CAAO,6BACP,OAAA,CAAS,8BAAA,CAGT,UAAW,6CAAA,CACX,aAAA,CAAe,4DACf,eAAA,CAAiB,wCAAA,CAGjB,QAAS,2CAAA,CACT,WAAA,CAAa,gDAGb,MAAA,CAAQ,yCAAA,CACR,YAAa,+CAAA,CAGb,IAAA,CAAM,4BACN,MAAA,CAAQ,6CAAA,CACR,YAAa,6CAAA,CAGb,MAAA,CAAQ,CACN,OAAA,CAAS,CACP,KAAM,oBAAA,CACN,EAAA,CAAI,qBACN,CAAA,CACA,QAAS,CACP,IAAA,CAAM,oBACN,EAAA,CAAI,0BACN,EACA,SAAA,CAAW,CACT,KAAM,mBAAA,CACN,EAAA,CAAI,0BACN,CAAA,CACA,MAAA,CAAQ,CACN,IAAA,CAAM,kBAAA,CACN,GAAI,yBACN,CACF,CACF,CAAA,CAEA,QAAS,CACP,MAAA,CAAQ,gCACR,KAAA,CAAO,+BAAA,CACP,WAAY,gCAAA,CACZ,MAAA,CAAQ,gCACR,WAAA,CAAa,+BAAA,CACb,QAAS,mCAAA,CACT,YAAA,CAAc,oCAChB,CAAA,CAEA,UAAA,CAAY,CACV,eAAA,CAAiB,CACf,OAAA,CAAS,CAAE,QAAS,CAAA,CAAG,CAAA,CAAG,CAAE,CAAA,CAC5B,OAAA,CAAS,CAAE,OAAA,CAAS,CAAA,CAAG,EAAG,CAAE,CAAA,CAC5B,WAAY,CAAE,QAAA,CAAU,GAAK,IAAA,CAAM,CAAC,GAAK,CAAA,CAAG,EAAA,CAAK,CAAC,CAAE,CACtD,EACA,MAAA,CAAQ,CACN,QAAS,CAAE,OAAA,CAAS,CAAE,CAAA,CACtB,OAAA,CAAS,CAAE,OAAA,CAAS,CAAE,EACtB,UAAA,CAAY,CAAE,SAAU,EAAI,CAC9B,CACF,CACF,ECjFA,IAAMC,CAAAA,CAAkB,EAAA,CAClBC,EACLD,CAAAA,CAAkBD,CAAAA,CAAW,WAAW,OAAA,CAAQ,UAAA,CAE3CG,EAAe,CAAA,IAAA,EAAOF,CAAe,qDAErCG,CAAAA,CAAY,GAAA,CACZC,CAAAA,CAAQ,IAAI,IAElB,SAASC,CAAAA,CAASC,EAAuC,CACxD,IAAMC,EAAMH,CAAAA,CAAM,GAAA,CAAIE,CAAG,CAAA,CACzB,OAAIC,IAEHH,CAAAA,CAAM,MAAA,CAAOE,CAAG,CAAA,CAChBF,CAAAA,CAAM,IAAIE,CAAAA,CAAKC,CAAG,CAAA,CAAA,CAEZA,CACR,CAEA,SAASC,CAAAA,CAASF,EAAaG,CAAAA,CAA2B,CAEzD,GADAL,CAAAA,CAAM,GAAA,CAAIE,EAAKG,CAAK,CAAA,CAChBL,EAAM,IAAA,CAAOD,CAAAA,CAAW,CAC3B,IAAMO,CAAAA,CAASN,EAAM,IAAA,EAAK,CAAE,MAAK,CAAE,KAAA,CAC/BM,IAAW,MAAA,EAAWN,CAAAA,CAAM,OAAOM,CAAM,EAC9C,CACD,CAOO,SAASC,EACfC,CAAAA,CACAC,CAAAA,CACAC,EAA0B,EAAC,CACL,CACtB,GAAI,CAACF,GAAQC,CAAAA,EAAY,CAAA,CAAG,OAAO,CAAE,OAAQ,CAAA,CAAG,SAAA,CAAW,CAAE,CAAA,CAC7D,GAAI,OAAO,QAAA,CAAa,GAAA,CAAa,OAAO,IAAA,CAE5C,IAAME,EAAOD,CAAAA,CAAQ,IAAA,EAAQZ,EACvBc,CAAAA,CAAeF,CAAAA,CAAQ,cAAgBb,CAAAA,CAGvCgB,CAAAA,CAAe,KAAK,KAAA,CAAMJ,CAAQ,EAClCP,CAAAA,CAAM,CAAA,EAAGS,CAAI,CAAA,CAAA,EAAIC,CAAY,IAAIC,CAAY,CAAA,CAAA,EAAIL,CAAI,CAAA,CAAA,CAErDM,CAAAA,CAASb,EAASC,CAAG,CAAA,CAC3B,GAAIY,CAAAA,CAAQ,OAAOA,EAEnB,GAAI,CACH,IAAMC,CAAAA,CAAWC,QAAQR,CAAAA,CAAMG,CAAI,EAC7BM,CAAAA,CAASC,MAAAA,CAAOH,EAAUF,CAAAA,CAAcD,CAAY,EACpDO,CAAAA,CAAyB,CAC9B,OAAQF,CAAAA,CAAO,MAAA,CACf,UAAWA,CAAAA,CAAO,SACnB,EACA,OAAAb,CAAAA,CAASF,EAAKiB,CAAQ,CAAA,CACfA,CACR,CAAA,KAAQ,CACP,OAAO,IACR,CACD,CAMO,SAASC,CAAAA,EAA8B,CAC7CpB,CAAAA,CAAM,KAAA,GACN,GAAI,CACHqB,aACD,CAAA,KAAQ,CAER,CACD","file":"chunk-O2ILSWHS.js","sourcesContent":["/**\n * Design tokens for the chat UI.\n * These map to CSS custom properties for easy theming.\n */\n\nexport const chatTokens = {\n spacing: {\n /** Vertical spacing between messages (16px) */\n messageBetween: \"1rem\",\n /** Message bubble horizontal padding (14px) */\n messagePx: \"0.875rem\",\n /** Message bubble vertical padding (10px) */\n messagePy: \"0.625rem\",\n /** Container padding (16px) */\n container: \"1rem\",\n /** Composer padding (16px) */\n composerPadding: \"1rem\",\n },\n\n typography: {\n message: {\n fontSize: \"1rem\",\n lineHeight: 1.5,\n letterSpacing: \"0px\",\n },\n caption: {\n fontSize: \"0.875rem\",\n lineHeight: 1.4,\n },\n small: {\n fontSize: \"0.8125rem\",\n lineHeight: 1.3,\n },\n },\n\n borderRadius: {\n message: \"0.5rem\",\n input: \"1rem\",\n panel: \"0.5rem\",\n button: \"0.5rem\",\n chip: \"0.25rem\",\n },\n\n colors: {\n // CSS custom property references\n primary: \"var(--chat-primary, #106997)\",\n secondary: \"var(--chat-secondary, #56C18A)\",\n error: \"var(--chat-error, #B1001B)\",\n warning: \"var(--chat-warning, #DD9652)\",\n\n // Message backgrounds\n messageBg: \"var(--chat-message-bg, rgba(0, 0, 0, 0.03))\",\n userMessageBg: \"var(--chat-user-message-bg, var(--chat-primary, #106997))\",\n userMessageText: \"var(--chat-user-message-text, #ffffff)\",\n\n // Panel backgrounds\n panelBg: \"var(--chat-panel-bg, rgba(0, 0, 0, 0.02))\",\n panelBorder: \"var(--chat-panel-border, rgba(0, 0, 0, 0.06))\",\n\n // Borders\n border: \"var(--chat-border, rgba(0, 0, 0, 0.06))\",\n borderHover: \"var(--chat-border-hover, rgba(0, 0, 0, 0.12))\",\n\n // Text\n text: \"var(--chat-text, #1D2033)\",\n subtle: \"var(--chat-text-subtle, rgba(0, 0, 0, 0.5))\",\n placeholder: \"var(--chat-placeholder, rgba(0, 0, 0, 0.4))\",\n\n // Status colors\n status: {\n pending: {\n main: \"rgba(0, 0, 0, 0.3)\",\n bg: \"rgba(0, 0, 0, 0.05)\",\n },\n running: {\n main: \"rgb(99, 102, 241)\",\n bg: \"rgba(99, 102, 241, 0.08)\",\n },\n completed: {\n main: \"rgb(16, 185, 129)\",\n bg: \"rgba(16, 185, 129, 0.08)\",\n },\n failed: {\n main: \"rgb(239, 68, 68)\",\n bg: \"rgba(239, 68, 68, 0.08)\",\n },\n },\n },\n\n shadows: {\n subtle: \"0 1px 2px rgba(0, 0, 0, 0.04)\",\n input: \"0 2px 8px rgba(0, 0, 0, 0.08)\",\n inputFocus: \"0 4px 16px rgba(0, 0, 0, 0.12)\",\n button: \"0 1px 3px rgba(0, 0, 0, 0.08)\",\n buttonHover: \"0 2px 6px rgba(0, 0, 0, 0.12)\",\n primary: \"0 2px 6px rgba(16, 105, 151, 0.3)\",\n primaryHover: \"0 4px 12px rgba(16, 105, 151, 0.4)\",\n },\n\n animations: {\n messageEntrance: {\n initial: { opacity: 0, y: 8 },\n animate: { opacity: 1, y: 0 },\n transition: { duration: 0.3, ease: [0.4, 0, 0.2, 1] },\n },\n fadeIn: {\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n transition: { duration: 0.2 },\n },\n },\n} as const;\n\nexport type ChatTokens = typeof chatTokens;\n","/**\n * Off-DOM text measurement for chat message bodies.\n *\n * Wraps `@chenglou/pretext` (canvas-based, no layout reflow) so callers can\n * compute a paragraph's pixel height before React renders it. Used to reserve\n * vertical space for streaming assistant messages and prevent scroll jitter.\n *\n * Notes:\n * - We avoid `system-ui` in the font shorthand because pretext is inaccurate\n * with it on macOS. The font family stays in sync with `--chat-font-family`\n * minus the `system-ui` token.\n * - The cache is a small FIFO keyed by `(text, font, maxWidth, lineHeight)`.\n * Chat threads are bounded so this stays cheap.\n */\n\nimport { clearCache, layout, prepare } from \"@chenglou/pretext\";\nimport { chatTokens } from \"../styles/tokens\";\n\nexport interface MeasureOptions {\n\t/** CSS font shorthand. Defaults to the chat message body font. */\n\tfont?: string;\n\t/** Line height in pixels. Defaults to message body fontSize × lineHeight. */\n\tlineHeightPx?: number;\n}\n\nexport interface MeasuredText {\n\theight: number;\n\tlineCount: number;\n}\n\nconst DEFAULT_FONT_PX = 16; // matches chatTokens.typography.message.fontSize \"1rem\"\nconst DEFAULT_LINE_HEIGHT_PX =\n\tDEFAULT_FONT_PX * chatTokens.typography.message.lineHeight;\n\nconst DEFAULT_FONT = `400 ${DEFAULT_FONT_PX}px \"Inter\", \"Assistant\", -apple-system, sans-serif`;\n\nconst CACHE_MAX = 512;\nconst cache = new Map<string, MeasuredText>();\n\nfunction cacheGet(key: string): MeasuredText | undefined {\n\tconst hit = cache.get(key);\n\tif (hit) {\n\t\t// LRU bump\n\t\tcache.delete(key);\n\t\tcache.set(key, hit);\n\t}\n\treturn hit;\n}\n\nfunction cacheSet(key: string, value: MeasuredText): void {\n\tcache.set(key, value);\n\tif (cache.size > CACHE_MAX) {\n\t\tconst oldest = cache.keys().next().value;\n\t\tif (oldest !== undefined) cache.delete(oldest);\n\t}\n}\n\n/**\n * Measure the rendered height of a plain-text message body without touching\n * the DOM. Returns `null` if measurement is not possible in this environment\n * (e.g. SSR, no canvas).\n */\nexport function measureMessageHeight(\n\ttext: string,\n\tmaxWidth: number,\n\toptions: MeasureOptions = {},\n): MeasuredText | null {\n\tif (!text || maxWidth <= 0) return { height: 0, lineCount: 0 };\n\tif (typeof document === \"undefined\") return null;\n\n\tconst font = options.font ?? DEFAULT_FONT;\n\tconst lineHeightPx = options.lineHeightPx ?? DEFAULT_LINE_HEIGHT_PX;\n\n\t// Snap maxWidth so subpixel container resizes share cache entries.\n\tconst snappedWidth = Math.round(maxWidth);\n\tconst key = `${font}|${lineHeightPx}|${snappedWidth}|${text}`;\n\n\tconst cached = cacheGet(key);\n\tif (cached) return cached;\n\n\ttry {\n\t\tconst prepared = prepare(text, font);\n\t\tconst result = layout(prepared, snappedWidth, lineHeightPx);\n\t\tconst measured: MeasuredText = {\n\t\t\theight: result.height,\n\t\t\tlineCount: result.lineCount,\n\t\t};\n\t\tcacheSet(key, measured);\n\t\treturn measured;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Drop pretext's internal caches and our LRU. Call after the active font\n * family changes (e.g. branding swap) so measurements use the new metrics.\n */\nexport function clearMeasurementCache(): void {\n\tcache.clear();\n\ttry {\n\t\tclearCache();\n\t} catch {\n\t\t/* pretext may not be loaded in SSR */\n\t}\n}\n"]}
@@ -1,6 +1,6 @@
1
- import { C as ChatMessage } from '../message-BnGtSz1P.js';
1
+ import { C as ChatMessage } from '../message-BrHFdwb2.js';
2
2
  import { B as BrandingData } from '../branding-SzYU4ncD.js';
3
- import '../streaming-DrnCgnnh.js';
3
+ import '../streaming-DURrv9_E.js';
4
4
 
5
5
  /**
6
6
  * Types for the Miiflow chat client (transport layer).
@@ -100,10 +100,14 @@ interface MiiflowChatResult {
100
100
  registerTools: (tools: ClientToolDefinition[]) => Promise<void>;
101
101
  /** Send a system event (invisible to chat, processed by assistant) */
102
102
  sendSystemEvent: (event: SystemEvent) => Promise<void>;
103
+ /** Append hidden page context to the thread (not rendered, no auto-reply) */
104
+ sendPageContext: (context: PageContext) => Promise<void>;
103
105
  /** Execute a client tool invocation (called when backend invokes a registered tool). Returns true if handled. */
104
106
  handleToolInvocation: (invocation: ToolInvocationRequest) => Promise<boolean>;
105
107
  /** Update the session externally (e.g. after token refresh) */
106
108
  updateSession: (session: EmbedSession) => void;
109
+ /** Stop the current streaming response (aborts fetch, preserves partial content) */
110
+ stopStreaming: () => void;
107
111
  }
108
112
  interface JSONSchemaProperty {
109
113
  type: "string" | "number" | "integer" | "boolean" | "array" | "object" | "null";
@@ -148,6 +152,25 @@ interface SystemEvent {
148
152
  followUpInstruction: string;
149
153
  metadata?: Record<string, unknown>;
150
154
  }
155
+ /**
156
+ * Ambient page context injected into the conversation.
157
+ *
158
+ * Unlike a SystemEvent, page context does NOT trigger an assistant response —
159
+ * it is stored as a hidden message in the thread so the model sees it on the
160
+ * next turn. Use it to describe the current page, registered client tools,
161
+ * relevant URLs, or any other context the assistant should be aware of.
162
+ *
163
+ * Append-only: each call adds a new entry. To avoid duplicates across
164
+ * re-renders, call from a `useEffect` with stable dependencies.
165
+ */
166
+ interface PageContext {
167
+ /** Short tag, e.g. "page_navigated" or "tools_registered". */
168
+ action: string;
169
+ /** Full text the model should see (tool usage hints, URLs, excerpts, etc). */
170
+ content: string;
171
+ /** Optional free-form metadata (url, pageId, toolNames, etc). */
172
+ metadata?: Record<string, unknown>;
173
+ }
151
174
  type WidgetEventType = "widget_ready" | "widget_opened" | "widget_closed" | "widget_reconnected" | "session_start" | "session_end" | "thread_started" | "new_message" | "message_sent" | "message_received" | "error" | "load_failed" | "assistant_response_timeout";
152
175
  type WidgetEventPayload = Record<string, unknown> | undefined;
153
176
  type WidgetEventCallback = (type: WidgetEventType, payload?: WidgetEventPayload) => void;
@@ -197,6 +220,13 @@ declare function uploadFile(config: MiiflowChatConfig, session: EmbedSession, fi
197
220
  * Send a system event to the backend (invisible to chat, processed by assistant).
198
221
  */
199
222
  declare function sendSystemEvent(config: MiiflowChatConfig, session: EmbedSession, systemEvent: SystemEvent): Promise<void>;
223
+ /**
224
+ * Append a hidden page-context message to the thread.
225
+ *
226
+ * Does not render in the UI and does not trigger an assistant response — the
227
+ * content is preserved in history so the LLM sees it on the next user turn.
228
+ */
229
+ declare function sendPageContext(config: MiiflowChatConfig, session: EmbedSession, context: PageContext): Promise<void>;
200
230
  /**
201
231
  * Send a tool execution result back to the backend.
202
232
  */
@@ -228,6 +258,42 @@ declare function isTokenExpired(token: string): boolean;
228
258
  */
229
259
  declare function getTimeUntilExpiry(token: string): number;
230
260
 
261
+ /**
262
+ * Off-DOM text measurement for chat message bodies.
263
+ *
264
+ * Wraps `@chenglou/pretext` (canvas-based, no layout reflow) so callers can
265
+ * compute a paragraph's pixel height before React renders it. Used to reserve
266
+ * vertical space for streaming assistant messages and prevent scroll jitter.
267
+ *
268
+ * Notes:
269
+ * - We avoid `system-ui` in the font shorthand because pretext is inaccurate
270
+ * with it on macOS. The font family stays in sync with `--chat-font-family`
271
+ * minus the `system-ui` token.
272
+ * - The cache is a small FIFO keyed by `(text, font, maxWidth, lineHeight)`.
273
+ * Chat threads are bounded so this stays cheap.
274
+ */
275
+ interface MeasureOptions {
276
+ /** CSS font shorthand. Defaults to the chat message body font. */
277
+ font?: string;
278
+ /** Line height in pixels. Defaults to message body fontSize × lineHeight. */
279
+ lineHeightPx?: number;
280
+ }
281
+ interface MeasuredText {
282
+ height: number;
283
+ lineCount: number;
284
+ }
285
+ /**
286
+ * Measure the rendered height of a plain-text message body without touching
287
+ * the DOM. Returns `null` if measurement is not possible in this environment
288
+ * (e.g. SSR, no canvas).
289
+ */
290
+ declare function measureMessageHeight(text: string, maxWidth: number, options?: MeasureOptions): MeasuredText | null;
291
+ /**
292
+ * Drop pretext's internal caches and our LRU. Call after the active font
293
+ * family changes (e.g. branding swap) so measurements use the new metrics.
294
+ */
295
+ declare function clearMeasurementCache(): void;
296
+
231
297
  /**
232
298
  * Client-side validator for tool definitions.
233
299
  * Validates tool definitions before they're sent to the backend.
@@ -246,4 +312,4 @@ declare function validateToolDefinition(tool: ClientToolDefinition): void;
246
312
  */
247
313
  declare function serializeToolDefinition(tool: ClientToolDefinition): Omit<ClientToolDefinition, "handler">;
248
314
 
249
- export { type ClientToolDefinition, type EmbedSession, type EmbedSessionBranding, type EmbedSessionConfig, type JSONSchemaObject, type JSONSchemaProperty, type MiiflowChatConfig, type MiiflowChatResult, type SystemEvent, type ToolExecutionResult, type ToolHandler, type ToolInvocationRequest, ToolValidationError, type WidgetEventCallback, type WidgetEventPayload, type WidgetEventType, createThread, getBackendBaseUrl, getOrCreateUserId, getTimeUntilExpiry, initSession, isTokenExpired, isTokenExpiringSoon, parseTokenExpiry, registerToolsOnBackend, sendSystemEvent, sendToolResult, serializeToolDefinition, updateUser, uploadFile, useMiiflowChat, validateToolDefinition };
315
+ export { type ClientToolDefinition, type EmbedSession, type EmbedSessionBranding, type EmbedSessionConfig, type JSONSchemaObject, type JSONSchemaProperty, type MeasureOptions, type MeasuredText, type MiiflowChatConfig, type MiiflowChatResult, type PageContext, type SystemEvent, type ToolExecutionResult, type ToolHandler, type ToolInvocationRequest, ToolValidationError, type WidgetEventCallback, type WidgetEventPayload, type WidgetEventType, clearMeasurementCache, createThread, getBackendBaseUrl, getOrCreateUserId, getTimeUntilExpiry, initSession, isTokenExpired, isTokenExpiringSoon, measureMessageHeight, parseTokenExpiry, registerToolsOnBackend, sendPageContext, sendSystemEvent, sendToolResult, serializeToolDefinition, updateUser, uploadFile, useMiiflowChat, validateToolDefinition };
@@ -1,9 +1,9 @@
1
- import {b}from'../chunk-NSTK5EUQ.js';import {useState,useRef,useEffect,useMemo,useCallback}from'react';function A(t){return t.baseUrl?t.baseUrl.replace(/\/api\/?$/,""):t.bundleUrl?.includes("localhost")||t.bundleUrl?.includes("127.0.0.1")||false?"http://localhost:8003":"https://api.miiflow.ai"}function N(){let t="miiflow-user-id",n=null;try{n=localStorage.getItem(t);}catch{}if(!n){n=`muid_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;try{localStorage.setItem(t,n);}catch{}}return n}async function ue(t){let n=A(t),u=await fetch(`${n}/api/embed/init`,{method:"POST",headers:{"Content-Type":"application/json","X-Embed-Public-Key":t.publicKey,"x-mii-user-id":N()},body:JSON.stringify({assistant_id:t.assistantId,user_data:{user_id:t.userId,name:t.userName,email:t.userEmail}})});if(!u.ok){let f=await u.text();throw new Error(`Init failed: ${u.status} - ${f}`)}let d=await u.json();if(!d.success)throw new Error(d.error||"Failed to initialize session");return {token:d.token,config:d.config,session_id:d.session_id}}async function ce(t,n){let u=A(t),d=await fetch(`${u}/api/embed/graphql`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"x-mii-user-id":N()},body:JSON.stringify({operationName:"CreateThread",variables:{input:{assistantId:n.config.assistant_id,name:"New Thread",isPreview:false}},query:`mutation CreateThread($input: CreateThreadInput!) {
1
+ export{c as clearMeasurementCache,b as measureMessageHeight}from'../chunk-O2ILSWHS.js';import {b}from'../chunk-NSTK5EUQ.js';import {useState,useRef,useEffect,useMemo,useCallback}from'react';function A(t){return t.baseUrl?t.baseUrl.replace(/\/api\/?$/,""):t.bundleUrl?.includes("localhost")||t.bundleUrl?.includes("127.0.0.1")||false?"http://localhost:8003":"https://api.miiflow.ai"}function U(){let t="miiflow-user-id",n=null;try{n=localStorage.getItem(t);}catch{}if(!n){n=`muid_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;try{localStorage.setItem(t,n);}catch{}}return n}async function me(t){let n=A(t),l=await fetch(`${n}/api/embed/init`,{method:"POST",headers:{"Content-Type":"application/json","X-Embed-Public-Key":t.publicKey,"x-mii-user-id":U()},body:JSON.stringify({assistant_id:t.assistantId,user_data:{user_id:t.userId,name:t.userName,email:t.userEmail}})});if(!l.ok){let d=await l.text();throw new Error(`Init failed: ${l.status} - ${d}`)}let c=await l.json();if(!c.success)throw new Error(c.error||"Failed to initialize session");return {token:c.token,config:c.config,session_id:c.session_id}}async function ge(t,n){let l=A(t),c=await fetch(`${l}/api/embed/graphql`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"x-mii-user-id":U()},body:JSON.stringify({operationName:"CreateThread",variables:{input:{assistantId:n.config.assistant_id,name:"New Thread",isPreview:false}},query:`mutation CreateThread($input: CreateThreadInput!) {
2
2
  createThread(input: $input) {
3
3
  thread { id status name isPreview }
4
4
  }
5
- }`})});if(!d.ok)throw new Error(`Failed to create thread: ${d.status}`);let f=await d.json(),_=f.data?.createThread?.thread?.id;if(!_)throw new Error("No thread ID returned");return {threadId:_,token:f.token}}async function ke(t,n,u){let d=A(t);await fetch(`${d}/api/embed/update`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify({user_data:u})});}async function de(t,n,u){let f=`${A(t)}/api/embed/upload-attachment`,_=new FormData;_.append("file",u);let g=await fetch(f,{method:"POST",headers:{Authorization:`Bearer ${n.token}`,"x-mii-user-id":N()},body:_});if(!g.ok){let O=await g.text();throw new Error(`Upload failed: ${g.status} - ${O}`)}let s=(await g.json()).attachment?.id;if(!s)throw new Error("No attachment ID returned");return s}async function pe(t,n,u){let d=A(t),f=await fetch(`${d}/api/embed/system-event`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"x-mii-user-id":N()},body:JSON.stringify({thread_id:n.config.thread_id,system_event:{action:u.action,description:u.description,followUpInstruction:u.followUpInstruction,metadata:u.metadata||{}}})});if(!f.ok){let g=await f.text();throw new Error(`Failed to send system event: ${f.status} - ${g}`)}let _=await f.json();if(!_.success)throw new Error(_.error||"Failed to send system event")}async function G(t,n,u){let d=A(t),f=await fetch(`${d}/api/embed/tool-result`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(u)});if(!f.ok){let g=await f.text();throw new Error(`Failed to send tool result: ${f.status} - ${g}`)}let _=await f.json();if(!_.success)throw new Error(`Failed to send tool result: ${_.error}`)}async function te(t,n,u){let d=A(t);if(u.length===1){let f=await fetch(`${d}/api/embed/register-tool`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(u[0])});if(!f.ok){let g=await f.text();throw new Error(`Failed to register tool: ${f.status} - ${g}`)}let _=await f.json();if(!_.success)throw new Error(`Failed to register tool: ${_.error||"Unknown error"}`)}else if(u.length>1){let f=await fetch(`${d}/api/embed/register-tools`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(u)});if(!f.ok){let g=await f.text();throw new Error(`Failed to register tools: ${f.status} - ${g}`)}let _=await f.json();if(!_.success)throw new Error(`Failed to register tools: ${_.error||"Unknown error"}`)}}var ge=new Set(["string","number","integer","boolean","array","object","null"]),Ce=/^[a-zA-Z_][a-zA-Z0-9_]*$/,w=class extends Error{constructor(n){super(n),this.name="ToolValidationError";}};function ie(t){if(!t.name)throw new w("Tool name is required");if(!t.description)throw new w("Tool description is required");if(!t.parameters)throw new w("Tool parameters schema is required");if(typeof t.handler!="function")throw new w("Tool handler must be a function");Se(t.name),Te(t.description),De(t.parameters);}function Se(t){if(typeof t!="string")throw new w("Tool name must be a string");if(t.length===0)throw new w("Tool name cannot be empty");if(t.length>64)throw new w("Tool name too long (max 64 characters)");if(!Ce.test(t))throw new w("Tool name must start with letter/underscore and contain only alphanumeric characters and underscores")}function Te(t){if(typeof t!="string")throw new w("Tool description must be a string");if(t.trim().length===0)throw new w("Tool description cannot be empty");if(t.length>500)throw new w("Tool description too long (max 500 characters)")}function De(t){if(typeof t!="object"||t===null||Array.isArray(t))throw new w("Parameters must be a JSON Schema object");if(t.type!=="object")throw new w("Parameters schema must be of type 'object' (function parameters)");if(t.properties&&typeof t.properties=="object")for(let[n,u]of Object.entries(t.properties))oe(n,u);if(t.required!==void 0){if(!Array.isArray(t.required))throw new w("'required' must be an array");for(let n of t.required)if(typeof n!="string")throw new w("'required' array must contain only strings")}if(t.additionalProperties!==void 0&&typeof t.additionalProperties!="boolean"&&(typeof t.additionalProperties!="object"||t.additionalProperties===null))throw new w("'additionalProperties' must be boolean or object")}function oe(t,n){if(typeof n!="object"||n===null||Array.isArray(n))throw new w(`Property '${t}' schema must be an object`);if(n.type!==void 0){let u=Array.isArray(n.type)?n.type:[n.type];for(let d of u)if(!ge.has(d))throw new w(`Invalid type '${d}' for property '${t}'. Valid types: ${Array.from(ge).join(", ")}`)}if(n.enum!==void 0&&!Array.isArray(n.enum))throw new w(`Property '${t}' enum must be an array`);if(n.properties&&typeof n.properties=="object")for(let[u,d]of Object.entries(n.properties))oe(`${t}.${u}`,d);n.items&&(Array.isArray(n.items)?n.items.forEach((u,d)=>{oe(`${t}[${d}]`,u);}):oe(`${t}[]`,n.items));}function re(t){return {name:t.name,description:t.description,parameters:t.parameters}}var Ie=21e3,xe=1e3,ve=3e4;function Ae(t,n){if(t.webSocketUrl){let g=new URL(t.webSocketUrl);return g.pathname=`/ws/assistant/thread/${n.config.thread_id}/`,g.searchParams.set("role","user"),g.searchParams.set("user_id",N()),g.searchParams.set("embed_token",n.token),g.toString()}let f=A(t).replace(/\/api$/,"").replace(/^https:/,"wss:").replace(/^http:/,"ws:"),_=N();return `${f}/ws/assistant/thread/${n.config.thread_id}/?role=user&user_id=${encodeURIComponent(_)}&embed_token=${encodeURIComponent(n.token)}`}function Me(t){let n=t?.config.branding;return n?{customName:n.custom_name,messageFontSize:n.message_font_size,welcomeMessage:n.welcome_message,chatboxPlaceholder:n.chatbox_placeholder,backgroundBubbleColor:n.background_bubble_color,headerBackgroundColor:n.header_background_color,showHeader:n.show_header,rotatingPlaceholders:n.rotating_placeholders,presetQuestions:n.preset_questions,chatbotLogo:n.chatbot_logo,assistantAvatar:n.assistant_avatar}:null}async function Ee(t,n,u,d){let f=new TextDecoder,_=Date.now(),g="",y=null,s=[],O,j,$=[],Z=false,m="answer",b="",R,M,D,z,F,P,W,q,E,J,H,L,X,V,ne=false,Q="",r=n.config.branding,c=()=>{(b||m==="tool")&&(s.push({type:m,content:b,toolName:R,toolDescription:M,success:D,status:z,subtaskId:F,planData:P,subtaskData:W,isSynthesis:q,isReplan:E,toolArgs:J,replanAttempt:H,maxReplans:L,failureReason:X,progress:V}),b="",R=void 0,M=void 0,D=void 0,z=void 0,F=void 0,P=void 0,W=void 0,q=void 0,E=void 0,J=void 0,H=void 0,L=void 0,X=void 0,V=void 0);},p=()=>{let C=s.map(h=>h);return (b||m==="tool")&&C.push({type:m,content:b,toolName:R,toolDescription:M,success:D,status:z,subtaskId:F,planData:P,subtaskData:W,isSynthesis:q,isReplan:E,toolArgs:J,replanAttempt:H,maxReplans:L,failureReason:X,progress:V}),C},l=()=>{let C=p();if(y)d.onMessageUpdate({id:y,textContent:g,reasoning:C,suggestedActions:O,medias:$.length>0?$:void 0});else {y=`assistant-${Date.now()}`;let h={id:y,textContent:g,participant:{id:"assistant",name:r?.custom_name||n.config.assistant_name,role:"assistant",avatarUrl:r?.assistant_avatar},createdAt:new Date().toISOString(),isStreaming:true,reasoning:C,suggestedActions:O,medias:$.length>0?$:void 0};d.onMessageCreate(h);}};for(;;){let{done:C,value:h}=await t.read();if(C)break;let k=f.decode(h,{stream:true}),I=(Q+k).split(`
6
- `);k.endsWith(`
7
- `)?Q="":Q=I.pop()||"";for(let v of I){if(!v.startsWith("data: "))continue;let S=v.slice(6);if(S==="[DONE]")break;try{let e=JSON.parse(S);if(e.type==="assistant_chunk"){if(e.is_tool_planned){(b||m!=="answer")&&(c(),m="answer"),s.push({type:"tool",content:"",toolName:e.tool_name,toolDescription:e.tool_description,status:"planned",subtaskId:e.subtask_id}),l();continue}if(e.is_tool_executing){for(let a=s.length-1;a>=0;a--){let o=s[a];if(o.type==="tool"&&o.toolName===e.tool_name&&(e.subtask_id===void 0||o.subtaskId===e.subtask_id)){s[a].status="executing";break}}l();continue}if(e.is_observation){for(let a=s.length-1;a>=0;a--){let o=s[a];if(o.type==="tool"&&o.toolName===e.tool_name&&(e.subtask_id===void 0||o.subtaskId===e.subtask_id)){s[a].status="completed";break}}l();continue}if(e.suggested_actions){O=e.suggested_actions.map(a=>({id:a.action,label:a.label,value:a.action})),l();continue}if(e.is_wave_start){(b||m!=="answer")&&(c(),m="answer"),s.push({type:"wave_start",content:"",waveNumber:e.wave_number,isParallel:!0,waveData:{waveNumber:e.wave_number,subtaskIds:e.subtask_ids||[],parallelCount:e.parallel_count||0,totalWaves:e.total_waves||1}}),l();continue}if(e.is_wave_complete){s.push({type:"wave_complete",content:"",waveNumber:e.wave_number,isParallel:!0,waveData:{waveNumber:e.wave_number,subtaskIds:[],parallelCount:0,totalWaves:0,completedIds:e.completed_ids||[],success:e.success,executionTime:e.execution_time}}),l();continue}if(e.is_parallel_subtask_start){s.push({type:"parallel_subtask_start",content:"",subtaskId:e.subtask_id,waveNumber:e.wave_number,isParallel:!0,parallelSubtaskData:{subtaskId:e.subtask_id,waveNumber:e.wave_number,description:e.description}}),l();continue}if(e.is_parallel_subtask_complete){s.push({type:"parallel_subtask_complete",content:"",subtaskId:e.subtask_id,waveNumber:e.wave_number,isParallel:!0,success:e.success,parallelSubtaskData:{subtaskId:e.subtask_id,waveNumber:e.wave_number,success:e.success,result:e.result,error:e.error,executionTime:e.execution_time}}),l();continue}if(e.is_multi_agent_planning){ne=!0,(b||m!=="answer")&&(c(),m="answer"),s.push({type:"multi_agent_planning",content:"",isMultiAgent:!0}),l();continue}if(e.is_reasoning&&e.reasoning_delta){let a=s.findIndex(o=>o.type==="thinking"&&o.isMultiAgent);a>=0?s[a]={...s[a],content:(s[a].content||"")+e.reasoning_delta}:s.push({type:"thinking",content:e.reasoning_delta,isMultiAgent:!0}),l();continue}if(e.is_multi_agent_planning_complete){let a=s.findIndex(o=>o.type==="multi_agent_planning"&&o.isMultiAgent);a>=0?s[a]={...s[a],subagentAllocations:e.subagents||[]}:s.push({type:"multi_agent_planning",content:"",isMultiAgent:!0,subagentAllocations:e.subagents||[]}),l();continue}if(e.is_multi_agent_execution_start)continue;if(e.is_subagent_start){s.push({type:"subagent_start",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,task:e.task,status:"running"}}),l();continue}if(e.is_subagent_progress){let a=s.findIndex(o=>o.type==="subagent_start"&&o.subagentInfo?.id===e.subagent_id);a!==-1&&s[a].subagentInfo&&(s[a]={...s[a],content:e.progress||""}),l();continue}if(e.is_subagent_complete){s.push({type:"subagent_complete",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,status:"completed",result:e.result,executionTime:e.execution_time}}),l();continue}if(e.is_subagent_failed){s.push({type:"subagent_failed",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,status:"failed",error:e.error}}),l();continue}if(e.is_synthesis_start&&ne){s.push({type:"synthesis",content:"",isMultiAgent:!0,isSynthesis:!0}),l();continue}if(e.plan_data){let a=e.plan_data;P={goal:a.goal||"",reasoning:a.reasoning||"",subtasks:(a.subtasks||[]).map(o=>({id:Number(o.id),description:o.description,required_tools:o.required_tools,dependencies:o.dependencies,status:"pending"})),total_subtasks:a.subtasks?.length||0,completed_subtasks:0,failed_subtasks:0,progress_percentage:0};}e.subtask_data&&(W=e.subtask_data),e.is_synthesis_start&&(q=!0),e.is_replan&&(E=!0),e.tool_args&&(J=e.tool_args),e.replan_attempt!==void 0&&(H=e.replan_attempt),e.max_replans!==void 0&&(L=e.max_replans),e.failure_reason&&(X=e.failure_reason),e.progress&&(V=e.progress);let i="answer";if(e.is_thinking?i="thinking":e.is_planning||e.is_plan_complete||e.is_replanning?i="planning":e.is_subtask_start||e.is_subtask_complete||e.is_subtask_failed?i="subtask":e.is_progress_update&&(i="progress"),i!==m&&(c(),m=i),e.tool_name&&(R=e.tool_name),e.success!==void 0&&(D=e.success),e.subtask_id!==void 0&&(F=e.subtask_id),i==="thinking"){b+=e.chunk||"";let a=b.match(/"thought"\s*:\s*"((?:[^"\\]|\\.)*)"/);a&&(b=a[1].replace(/\\n/g,`
8
- `).replace(/\\"/g,'"').replace(/\\t/g," ").replace(/\\\\/g,"\\"));}else if(i==="answer"){let a=e.chunk?.trim()||"",o=g.trim();a&&o&&a===o||(g+=e.chunk||"");}else b+=e.chunk||"";e.previous_message_id&&d.onUserMessageIdUpdate(u,e.previous_message_id),l();}else if(e.type==="claude_text"){g+=e.chunk||"";let i=s.find(a=>a.type==="claude_text");i?i.content+=e.chunk||"":s.push({type:"claude_text",content:e.chunk||"",orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_thinking")s.push({type:"claude_thinking",content:e.content||"",orchestrator:"claude_agent_sdk"}),l();else if(e.type==="claude_file_read"){let i={toolUseId:e.tool_use_id,operation:"read",filePath:e.file_path,status:e.status,content:e.content,totalLines:e.total_lines,language:e.language,error:e.error,durationMs:e.duration_ms},a=s.findIndex(o=>o.type==="file_operation"&&o.toolUseId===e.tool_use_id);a>=0?s[a].fileOperationData=i:s.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_file_edit"){let i={toolUseId:e.tool_use_id,operation:"edit",filePath:e.file_path,status:e.status,oldString:e.old_string,newString:e.new_string,error:e.error,durationMs:e.duration_ms},a=s.findIndex(o=>o.type==="file_operation"&&o.toolUseId===e.tool_use_id);a>=0?s[a].fileOperationData=i:s.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_file_write"){let i={toolUseId:e.tool_use_id,operation:"write",filePath:e.file_path,status:e.status,error:e.error,durationMs:e.duration_ms},a=s.findIndex(o=>o.type==="file_operation"&&o.toolUseId===e.tool_use_id);a>=0?s[a].fileOperationData=i:s.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_bash"){let i={toolUseId:e.tool_use_id,command:e.command,description:e.description,status:e.status,stdout:e.stdout,stderr:e.stderr,exitCode:e.exit_code,durationMs:e.duration_ms},a=s.findIndex(o=>o.type==="terminal"&&o.toolUseId===e.tool_use_id);a>=0?s[a].terminalData=i:s.push({type:"terminal",content:"",toolUseId:e.tool_use_id,terminalData:i,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_search"){let i={toolUseId:e.tool_use_id,tool:e.tool,pattern:e.pattern,path:e.path,status:e.status,results:(e.results||[]).map(o=>({filePath:o.file_path,lineNumber:o.line_number,snippet:o.snippet})),totalCount:e.total_count||0,error:e.error,durationMs:e.duration_ms},a=s.findIndex(o=>o.type==="search_results"&&o.toolUseId===e.tool_use_id);a>=0?s[a].searchResultsData=i:s.push({type:"search_results",content:"",toolUseId:e.tool_use_id,searchResultsData:i,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_web_search"||e.type==="claude_web_fetch"){let i={toolUseId:e.tool_use_id,operation:e.type==="claude_web_search"?"search":"fetch",query:e.query,url:e.url,status:e.status,results:e.results,content:e.content,error:e.error,durationMs:e.duration_ms},a=s.findIndex(o=>o.type==="web_operation"&&o.toolUseId===e.tool_use_id);a>=0?s[a].webOperationData=i:s.push({type:"web_operation",content:"",toolUseId:e.tool_use_id,webOperationData:i,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_subagent_start"){let i={subagentId:e.subagent_id,subagentType:e.subagent_type,description:e.description,prompt:e.prompt,status:"running",nestedChunks:[]};s.push({type:"subagent",content:"",toolUseId:e.parent_tool_use_id,subagentData:i,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_subagent_chunk"){let i=s.findIndex(a=>a.type==="subagent"&&a.subagentData?.subagentId===e.subagent_id);i>=0&&s[i].subagentData&&s[i].subagentData.nestedChunks.push({type:e.is_tool?"tool":"answer",content:e.chunk||"",toolName:e.tool_name,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="claude_subagent_complete"){let i=s.findIndex(a=>a.type==="subagent"&&a.subagentData?.subagentId===e.subagent_id);i>=0&&s[i].subagentData&&(s[i].subagentData.status="completed",s[i].subagentData.result=e.result,s[i].subagentData.durationMs=e.duration_ms),l();}else if(e.type==="claude_tool_use"||e.type==="claude_tool_result"){let i={toolUseId:e.tool_use_id,toolName:e.tool_name,toolDescription:e.tool_description,toolInput:e.tool_input,status:e.type==="claude_tool_use"?"pending":e.is_error?"error":"completed",content:e.content,isError:e.is_error,durationMs:e.duration_ms},a=s.findIndex(o=>o.claudeToolData?.toolUseId===e.tool_use_id);a>=0?s[a].claudeToolData=i:s.push({type:"tool",content:e.content||"",toolUseId:e.tool_use_id,toolName:e.tool_name,toolDescription:e.tool_description,status:i.status==="pending"?"planned":"completed",claudeToolData:i,orchestrator:"claude_agent_sdk"}),l();}else if(e.type==="clarification_needed"){c();let i={question:e.question||"",options:e.options||[],context:e.context,allowFreeText:e.allow_free_text!==!1,subtaskId:e.subtask_id,subtaskDescription:e.subtask_description,subagentName:e.subagent_name,subagentRole:e.subagent_role};s.push({type:"clarification_needed",content:i.question,clarificationData:i,subtaskId:e.subtask_id}),j=i,g||(g=i.question),l();}else if(e.type==="media"){let i=e.media_data;i&&($=[...$,{id:i.id,url:i.url,mediaType:i.media_type||"image",altText:i.alt_text}],l());}else if(e.type==="assistant_complete"){c(),Z=!0;let i=e.message?.text_content||g,a=e.message?.id,o=e.message?.metadata?.sources,T=(Date.now()-_)/1e3;d.onComplete(y,i,a,s,O,o,j,T),g=i,a&&(y=a);break}else if(e.type==="client_tool_invocation"&&e.invocation&&d.onToolInvocation)d.onToolInvocation(e.invocation);else {if(e.type==="error")throw new Error(e.error||"Stream error");if(e.type==="done"){if(y&&!Z){c();let i=(Date.now()-_)/1e3;d.onComplete(y,g||"",e.message_id,s,O,void 0,j,i);}else e.message_id&&y&&d.onMessageUpdate({id:y,isStreaming:!1});e.message_id&&(y=e.message_id);break}}}catch(e){if(e instanceof Error&&e.message!=="Stream error"&&(e.message.startsWith("Stream error")||e.message.startsWith("HTTP error")))throw e}}}return {assistantMsgId:y,assistantContent:g}}function Oe(t){let[n,u]=useState([]),[d,f]=useState(false),[_,g]=useState(null),[y,s]=useState(null),[O,j]=useState(true),[$,Z]=useState(null),m=useRef(t);m.current=t;let b$1=useRef(y);b$1.current=y;let R=useRef(d);R.current=d;let M=useRef(new Map),D=useRef(new Map);useEffect(()=>{let r=false;async function c(){try{let p=await ue(m.current);r||(s(p),j(!1));}catch(p){r||(Z(p instanceof Error?p.message:"Failed to initialize"),j(false));}}return c(),()=>{r=true;}},[t.publicKey,t.assistantId]);let z=useMemo(()=>Me(y),[y]),F=b(z),P=useRef(new Map),W=useCallback(async r=>{let c=b$1.current;if(!c)throw new Error("Not initialized");let p=await de(m.current,c,r);return P.current.set(p,{id:p,filename:r.name,mimeType:r.type,size:r.size,isImage:r.type.startsWith("image/"),isVideo:r.type.startsWith("video/"),isDocument:!r.type.startsWith("image/")&&!r.type.startsWith("video/")}),p},[]),q=useCallback(r=>{P.current.delete(r);},[]),E=useCallback(async r=>{let c=b$1.current;if(!c)throw new Error("Not initialized");let{invocation_id:p,tool_name:l,parameters:C}=r;console.log(`[Miiflow] Tool invocation received: "${l}" (id: ${p})`);let h=M.current.get(l);if(!h)return false;try{let k=await Promise.race([h(C),new Promise((ee,I)=>setTimeout(()=>I(new Error("Tool execution timeout (30s)")),3e4))]);return console.log(`[Miiflow] Tool "${l}" executed successfully (id: ${p})`),await G(m.current,c,{invocation_id:p,result:k}),console.log(`[Miiflow] Tool result sent for "${l}" (id: ${p})`),!0}catch(k){return console.error(`[Miiflow] Tool '${l}' execution failed:`,k),await G(m.current,c,{invocation_id:p,error:k instanceof Error?k.message:String(k)}),true}},[]);useEffect(()=>{if(!y)return;let r=y,c=null,p=null,l=null,C=0,h=false;function k(){if(h)return;let ee=Ae(m.current,r);c=new WebSocket(ee),c.onopen=()=>{console.log("[Miiflow] WebSocket connected"),C=0,p=setInterval(()=>{c?.readyState===WebSocket.OPEN&&c.send(JSON.stringify({type:"heartbeat"}));},Ie);},c.onmessage=I=>{try{let v=JSON.parse(I.data);v.type==="client_tool_invocation"&&v.invocation&&E(v.invocation).then(async S=>{if(!S){let e=m.current.onToolInvocationFallback;e&&await e(v.invocation)||G(m.current,r,{invocation_id:v.invocation.invocation_id,error:`No handler found for tool '${v.invocation.tool_name}'`}).catch(console.error);}}).catch(console.error);}catch{}},c.onclose=()=>{if(p&&(clearInterval(p),p=null),!h){let I=Math.min(xe*Math.pow(2,C),ve);C++,l=setTimeout(k,I);}},c.onerror=()=>{};}return k(),()=>{h=true,p&&clearInterval(p),l&&clearTimeout(l),c&&(c.onclose=null,c.close());}},[y,E]);let J=useCallback(async r=>{let c=b$1.current;if(!c)throw new Error("Not initialized");await pe(m.current,c,r);},[]),H=useCallback(async(r,c)=>{let p=b$1.current,l=!!r.trim(),C=c&&c.length>0;if(!l&&!C||R.current||!p)return;R.current=true;let h=`msg-${Date.now()}`,k=c?.map(S=>P.current.get(S)).filter(Boolean),ee={id:h,textContent:r,participant:{id:"user",name:m.current.userName||"You",role:"user"},createdAt:new Date().toISOString(),attachments:k?.length?k:void 0};c?.forEach(S=>P.current.delete(S));let I=`assistant-pending-${Date.now()}`,v={id:I,textContent:"",participant:{id:"assistant",name:p.config.branding?.custom_name||p.config.assistant_name,role:"assistant",avatarUrl:p.config.branding?.assistant_avatar},createdAt:new Date().toISOString(),isStreaming:true};u(S=>[...S,ee,v]),f(true),g(I),m.current.onUserMessageCreated?.({id:h,content:r});try{let S=A(m.current),e=await fetch(`${S}/assistant/message/stream/`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${p.token}`,"x-mii-user-id":N()},body:JSON.stringify({thread_id:p.config.thread_id,text_content:r,message_id:h,metadata:{},attachment_ids:c||[]})});if(!e.ok)throw new Error(`HTTP error: ${e.status}`);let i=e.body?.getReader();if(!i)throw new Error("No response body");let a=await Ee(i,p,h,{onMessageCreate:o=>{g(o.id),u(T=>[...T.filter(B=>B.id!==I),o]);},onMessageUpdate:o=>{u(T=>T.map(x=>x.id===o.id?{...x,...o}:x));},onUserMessageIdUpdate:(o,T)=>{u(x=>x.map(B=>B.id===o?{...B,id:T}:B));},onComplete:(o,T,x,B,ae,_e,be,ye)=>{o&&u(we=>we.map(se=>se.id===o?{...se,id:x||se.id,textContent:T,isStreaming:!1,reasoning:B,suggestedActions:ae,citations:_e,pendingClarification:be,executionTime:ye}:se)),m.current.onAssistantMessageComplete?.({id:x||o||"",content:T});},onToolInvocation:async o=>{if(!await E(o)){let x=m.current.onToolInvocationFallback;if(!(x?await x(o):!1)){let ae=b$1.current;ae&&await G(m.current,ae,{invocation_id:o.invocation_id,error:`No handler found for tool '${o.tool_name}'`});}}}});a.assistantMsgId&&u(o=>o.map(T=>T.id===a.assistantMsgId?{...T,isStreaming:!1}:T));}catch(S){console.error("[Miiflow] Send error:",S);let e=b$1.current,i={id:`error-${Date.now()}`,textContent:"Sorry, I encountered an error. Please try again.",participant:{id:"assistant",name:e?.config.branding?.custom_name||e?.config.assistant_name||"Assistant",role:"assistant",avatarUrl:e?.config.branding?.assistant_avatar},createdAt:new Date().toISOString()};u(a=>[...a.filter(o=>o.id!==I),i]),Z(S instanceof Error?S.message:"Send failed");}finally{f(false),g(null);}},[E]),L=useCallback(async()=>{let r=b$1.current;if(!r)throw new Error("Not initialized");let c=await ce(m.current,r);c.token||console.warn("[Miiflow] CreateThread did not return new token \u2014 tools may register to wrong thread");let p={...r,config:{...r.config,thread_id:c.threadId},token:c.token||r.token};if(b$1.current=p,s(p),u([]),D.current.size>0){console.log(`[Miiflow] Re-registering ${D.current.size} tools on new thread`);try{await te(m.current,p,Array.from(D.current.values()));}catch(l){console.warn("[Miiflow] Failed to re-register tools:",l);}}return c.threadId},[]),X=useCallback(async r=>{let c=b$1.current;if(!c)throw new Error("Not initialized");ie(r),M.current.set(r.name,r.handler);let p=re(r);D.current.set(r.name,p);try{await te(m.current,c,[p]),console.log(`[Miiflow] Tool registered: "${r.name}"`);}catch(l){throw M.current.delete(r.name),D.current.delete(r.name),l}},[]),V=useCallback(async r=>{let c=b$1.current;if(!c)throw new Error("Not initialized");for(let h of r)ie(h);let p=new Map(M.current),l=new Map(D.current),C=[];for(let h of r){M.current.set(h.name,h.handler);let k=re(h);D.current.set(h.name,k),C.push(k);}try{await te(m.current,c,C);let h=r.map(k=>k.name);console.log(`[Miiflow] Tools registered: ${JSON.stringify(h)} (${r.length} tools)`);}catch(h){throw M.current=p,D.current=l,h}},[]),ne=useMemo(()=>n.map(r=>({id:r.id,textContent:r.textContent?.replace(/\[ref:[^\]]+\]/g,"")||r.textContent,participant:r.participant,createdAt:r.createdAt,isStreaming:r.isStreaming,reasoning:r.reasoning,suggestedActions:r.suggestedActions,citations:r.citations,attachments:r.attachments,pendingClarification:r.pendingClarification,executionTime:r.executionTime})),[n]),Q=useCallback(r=>{s(r);},[]);return {messages:ne,isStreaming:d,streamingMessageId:_,sendMessage:H,uploadFile:W,removeUploadedAttachment:q,session:y,loading:O,error:$,branding:z,brandingCSSVars:F,startNewThread:L,registerTool:X,registerTools:V,sendSystemEvent:J,handleToolInvocation:E,updateSession:Q}}function le(t){try{let n=t.split(".");if(n.length!==3)return null;let u=n[1].replace(/-/g,"+").replace(/_/g,"/"),d=atob(u),f=JSON.parse(d);return typeof f.exp=="number"?f.exp*1e3:null}catch{return null}}function Pe(t,n){let u=le(t);return u===null?true:u-Date.now()<=n}function Ne(t){let n=le(t);return n===null?true:Date.now()>=n}function Ue(t){let n=le(t);return n===null?0:Math.max(0,n-Date.now())}export{w as ToolValidationError,ce as createThread,A as getBackendBaseUrl,N as getOrCreateUserId,Ue as getTimeUntilExpiry,ue as initSession,Ne as isTokenExpired,Pe as isTokenExpiringSoon,le as parseTokenExpiry,te as registerToolsOnBackend,pe as sendSystemEvent,G as sendToolResult,re as serializeToolDefinition,ke as updateUser,de as uploadFile,Oe as useMiiflowChat,ie as validateToolDefinition};//# sourceMappingURL=index.js.map
5
+ }`})});if(!c.ok)throw new Error(`Failed to create thread: ${c.status}`);let d=await c.json(),m=d.data?.createThread?.thread?.id;if(!m)throw new Error("No thread ID returned");return {threadId:m,token:d.token}}async function Oe(t,n,l){let c=A(t);await fetch(`${c}/api/embed/update`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify({user_data:l})});}async function he(t,n,l){let d=`${A(t)}/api/embed/upload-attachment`,m=new FormData;m.append("file",l);let p=await fetch(d,{method:"POST",headers:{Authorization:`Bearer ${n.token}`,"x-mii-user-id":U()},body:m});if(!p.ok){let T=await p.text();throw new Error(`Upload failed: ${p.status} - ${T}`)}let o=(await p.json()).attachment?.id;if(!o)throw new Error("No attachment ID returned");return o}async function _e(t,n,l){let c=A(t),d=await fetch(`${c}/api/embed/system-event`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"x-mii-user-id":U()},body:JSON.stringify({thread_id:n.config.thread_id,system_event:{action:l.action,description:l.description,followUpInstruction:l.followUpInstruction,metadata:l.metadata||{}}})});if(!d.ok){let p=await d.text();throw new Error(`Failed to send system event: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(m.error||"Failed to send system event")}async function be(t,n,l){let c=A(t),d=await fetch(`${c}/api/embed/page-context`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"x-mii-user-id":U()},body:JSON.stringify({thread_id:n.config.thread_id,page_context:{action:l.action,content:l.content,metadata:l.metadata||{}}})});if(!d.ok){let p=await d.text();throw new Error(`Failed to send page context: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(m.error||"Failed to send page context")}async function Q(t,n,l){let c=A(t),d=await fetch(`${c}/api/embed/tool-result`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(l)});if(!d.ok){let p=await d.text();throw new Error(`Failed to send tool result: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(`Failed to send tool result: ${m.error}`)}async function ae(t,n,l){let c=A(t);if(l.length===1){let d=await fetch(`${c}/api/embed/register-tool`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(l[0])});if(!d.ok){let p=await d.text();throw new Error(`Failed to register tool: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(`Failed to register tool: ${m.error||"Unknown error"}`)}else if(l.length>1){let d=await fetch(`${c}/api/embed/register-tools`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`},body:JSON.stringify(l)});if(!d.ok){let p=await d.text();throw new Error(`Failed to register tools: ${d.status} - ${p}`)}let m=await d.json();if(!m.success)throw new Error(`Failed to register tools: ${m.error||"Unknown error"}`)}}var Ce=new Set(["string","number","integer","boolean","array","object","null"]),Ne=/^[a-zA-Z_][a-zA-Z0-9_]*$/,y=class extends Error{constructor(n){super(n),this.name="ToolValidationError";}};function de(t){if(!t.name)throw new y("Tool name is required");if(!t.description)throw new y("Tool description is required");if(!t.parameters)throw new y("Tool parameters schema is required");if(typeof t.handler!="function")throw new y("Tool handler must be a function");Ue(t.name),$e(t.description),Re(t.parameters);}function Ue(t){if(typeof t!="string")throw new y("Tool name must be a string");if(t.length===0)throw new y("Tool name cannot be empty");if(t.length>64)throw new y("Tool name too long (max 64 characters)");if(!Ne.test(t))throw new y("Tool name must start with letter/underscore and contain only alphanumeric characters and underscores")}function $e(t){if(typeof t!="string")throw new y("Tool description must be a string");if(t.trim().length===0)throw new y("Tool description cannot be empty");if(t.length>500)throw new y("Tool description too long (max 500 characters)")}function Re(t){if(typeof t!="object"||t===null||Array.isArray(t))throw new y("Parameters must be a JSON Schema object");if(t.type!=="object")throw new y("Parameters schema must be of type 'object' (function parameters)");if(t.properties&&typeof t.properties=="object")for(let[n,l]of Object.entries(t.properties))ce(n,l);if(t.required!==void 0){if(!Array.isArray(t.required))throw new y("'required' must be an array");for(let n of t.required)if(typeof n!="string")throw new y("'required' array must contain only strings")}if(t.additionalProperties!==void 0&&typeof t.additionalProperties!="boolean"&&(typeof t.additionalProperties!="object"||t.additionalProperties===null))throw new y("'additionalProperties' must be boolean or object")}function ce(t,n){if(typeof n!="object"||n===null||Array.isArray(n))throw new y(`Property '${t}' schema must be an object`);if(n.type!==void 0){let l=Array.isArray(n.type)?n.type:[n.type];for(let c of l)if(!Ce.has(c))throw new y(`Invalid type '${c}' for property '${t}'. Valid types: ${Array.from(Ce).join(", ")}`)}if(n.enum!==void 0&&!Array.isArray(n.enum))throw new y(`Property '${t}' enum must be an array`);if(n.properties&&typeof n.properties=="object")for(let[l,c]of Object.entries(n.properties))ce(`${t}.${l}`,c);n.items&&(Array.isArray(n.items)?n.items.forEach((l,c)=>{ce(`${t}[${c}]`,l);}):ce(`${t}[]`,n.items));}function pe(t){return {name:t.name,description:t.description,parameters:t.parameters}}var Be=new Set(["image/jpeg","image/jpg","image/png","image/webp","image/bmp"]);function je(t){return Be.has(t.type)}function Fe(t){return new Promise((n,l)=>{let c=URL.createObjectURL(t),d=new Image;d.onload=()=>{URL.revokeObjectURL(c),n(d);},d.onerror=()=>{URL.revokeObjectURL(c),l(new Error("Failed to load image"));},d.src=c;})}function we(t,n,l,c){return new Promise((d,m)=>{let p=Math.round(t.naturalWidth*n),h=Math.round(t.naturalHeight*n),o=document.createElement("canvas");o.width=p,o.height=h;let T=o.getContext("2d");if(!T){m(new Error("Canvas 2D context unavailable"));return}T.drawImage(t,0,0,p,h),o.toBlob($=>{$?d($):m(new Error("Canvas toBlob returned null"));},c,l);})}async function Se(t){if(!je(t)||t.size<=4194304)return t;let n=await Fe(t),l=Math.min(1,4096/Math.max(n.naturalWidth,n.naturalHeight)),c="image/jpeg",d=[.85,.7,.5,.3,.15],m=[l,l*.75,l*.5,l*.25];for(let h of d){let o=await we(n,l,h,c);if(o.size<=4194304)return ye(o,t.name,c)}for(let h of m.slice(1))for(let o of d){let T=await we(n,h,o,c);if(T.size<=4194304)return ye(T,t.name,c)}let p=await we(n,.1,.1,c);return ye(p,t.name,c)}function ye(t,n,l){let c=n.replace(/\.[^.]+$/,".jpg");return new File([t],c,{type:l,lastModified:Date.now()})}var ze=21e3,We=1e3,qe=3e4;function Le(t,n){if(t.webSocketUrl){let p=new URL(t.webSocketUrl);return p.pathname=`/ws/assistant/thread/${n.config.thread_id}/`,p.searchParams.set("role","user"),p.searchParams.set("user_id",U()),p.searchParams.set("embed_token",n.token),p.toString()}let d=A(t).replace(/\/api$/,"").replace(/^https:/,"wss:").replace(/^http:/,"ws:"),m=U();return `${d}/ws/assistant/thread/${n.config.thread_id}/?role=user&user_id=${encodeURIComponent(m)}&embed_token=${encodeURIComponent(n.token)}`}function He(t){let n=t?.config.branding;return n?{customName:n.custom_name,messageFontSize:n.message_font_size,welcomeMessage:n.welcome_message,chatboxPlaceholder:n.chatbox_placeholder,backgroundBubbleColor:n.background_bubble_color,headerBackgroundColor:n.header_background_color,showHeader:n.show_header,rotatingPlaceholders:n.rotating_placeholders,presetQuestions:n.preset_questions,chatbotLogo:n.chatbot_logo,assistantAvatar:n.assistant_avatar}:null}async function Je(t,n,l,c){let d=new TextDecoder,m=Date.now(),p="",h=null,o=[],T,$,te,R=[],b=false,_="answer",C="",B,P,I,L,H,j,J,X,O,G,Y,V,K,Z,oe=false,ne="",se=n.config.branding,N=()=>{(C||_==="tool")&&(o.push({type:_,content:C,toolName:B,toolDescription:P,success:I,status:L,subtaskId:H,planData:j,subtaskData:J,isSynthesis:X,isReplan:O,toolArgs:G,replanAttempt:Y,maxReplans:V,failureReason:K,progress:Z}),C="",B=void 0,P=void 0,I=void 0,L=void 0,H=void 0,j=void 0,J=void 0,X=void 0,O=void 0,G=void 0,Y=void 0,V=void 0,K=void 0,Z=void 0);},r=()=>{let f=o.map(g=>g);return (C||_==="tool")&&f.push({type:_,content:C,toolName:B,toolDescription:P,success:I,status:L,subtaskId:H,planData:j,subtaskData:J,isSynthesis:X,isReplan:O,toolArgs:G,replanAttempt:Y,maxReplans:V,failureReason:K,progress:Z}),f},s=()=>{let f=r();if(h)c.onMessageUpdate({id:h,textContent:p,reasoning:f,suggestedActions:T,medias:R.length>0?R:void 0});else {h=`assistant-${Date.now()}`;let g={id:h,textContent:p,participant:{id:"assistant",name:se?.custom_name||n.config.assistant_name,role:"assistant",avatarUrl:se?.assistant_avatar},createdAt:new Date().toISOString(),isStreaming:true,reasoning:f,suggestedActions:T,medias:R.length>0?R:void 0};c.onMessageCreate(g);}};for(;;){let{done:f,value:g}=await t.read();if(f)break;let x=d.decode(g,{stream:true}),w=(ne+x).split(`
6
+ `);x.endsWith(`
7
+ `)?ne="":ne=w.pop()||"";for(let z of w){if(!z.startsWith("data: "))continue;let M=z.slice(6);if(M==="[DONE]")break;try{let e=JSON.parse(M);if(e.type==="assistant_chunk"){if(e.is_tool_planned){(C||_!=="answer")&&(N(),_="answer"),o.push({type:"tool",content:"",toolName:e.tool_name,toolDescription:e.tool_description,status:"planned",subtaskId:e.subtask_id}),s();continue}if(e.is_tool_executing){for(let a=o.length-1;a>=0;a--){let u=o[a];if(u.type==="tool"&&u.toolName===e.tool_name&&(e.subtask_id===void 0||u.subtaskId===e.subtask_id)){o[a].status="executing";break}}s();continue}if(e.is_observation){for(let a=o.length-1;a>=0;a--){let u=o[a];if(u.type==="tool"&&u.toolName===e.tool_name&&(e.subtask_id===void 0||u.subtaskId===e.subtask_id)){o[a].status="completed";break}}s();continue}if(e.suggested_actions){T=e.suggested_actions.map(a=>({id:a.action,label:a.label,value:a.action})),s();continue}if(e.is_wave_start){(C||_!=="answer")&&(N(),_="answer"),o.push({type:"wave_start",content:"",waveNumber:e.wave_number,isParallel:!0,waveData:{waveNumber:e.wave_number,subtaskIds:e.subtask_ids||[],parallelCount:e.parallel_count||0,totalWaves:e.total_waves||1}}),s();continue}if(e.is_wave_complete){o.push({type:"wave_complete",content:"",waveNumber:e.wave_number,isParallel:!0,waveData:{waveNumber:e.wave_number,subtaskIds:[],parallelCount:0,totalWaves:0,completedIds:e.completed_ids||[],success:e.success,executionTime:e.execution_time}}),s();continue}if(e.is_parallel_subtask_start){o.push({type:"parallel_subtask_start",content:"",subtaskId:e.subtask_id,waveNumber:e.wave_number,isParallel:!0,parallelSubtaskData:{subtaskId:e.subtask_id,waveNumber:e.wave_number,description:e.description}}),s();continue}if(e.is_parallel_subtask_complete){o.push({type:"parallel_subtask_complete",content:"",subtaskId:e.subtask_id,waveNumber:e.wave_number,isParallel:!0,success:e.success,parallelSubtaskData:{subtaskId:e.subtask_id,waveNumber:e.wave_number,success:e.success,result:e.result,error:e.error,executionTime:e.execution_time}}),s();continue}if(e.is_multi_agent_planning){oe=!0,(C||_!=="answer")&&(N(),_="answer"),o.push({type:"multi_agent_planning",content:"",isMultiAgent:!0}),s();continue}if(e.is_reasoning&&e.reasoning_delta){let a=o.findIndex(u=>u.type==="thinking"&&u.isMultiAgent);a>=0?o[a]={...o[a],content:(o[a].content||"")+e.reasoning_delta}:o.push({type:"thinking",content:e.reasoning_delta,isMultiAgent:!0}),s();continue}if(e.is_multi_agent_planning_complete){let a=o.findIndex(u=>u.type==="multi_agent_planning"&&u.isMultiAgent);a>=0?o[a]={...o[a],subagentAllocations:e.subagents||[]}:o.push({type:"multi_agent_planning",content:"",isMultiAgent:!0,subagentAllocations:e.subagents||[]}),s();continue}if(e.is_multi_agent_execution_start)continue;if(e.is_subagent_start){o.push({type:"subagent_start",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,task:e.task,status:"running"}}),s();continue}if(e.is_subagent_progress){let a=o.findIndex(u=>u.type==="subagent_start"&&u.subagentInfo?.id===e.subagent_id);a!==-1&&o[a].subagentInfo&&(o[a]={...o[a],content:e.progress||""}),s();continue}if(e.is_subagent_complete){o.push({type:"subagent_complete",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,status:"completed",result:e.result,executionTime:e.execution_time}}),s();continue}if(e.is_subagent_failed){o.push({type:"subagent_failed",content:"",isMultiAgent:!0,subagentInfo:{id:e.subagent_id,name:e.subagent_name,status:"failed",error:e.error}}),s();continue}if(e.is_synthesis_start&&oe){o.push({type:"synthesis",content:"",isMultiAgent:!0,isSynthesis:!0}),s();continue}if(e.plan_data){let a=e.plan_data;j={goal:a.goal||"",reasoning:a.reasoning||"",subtasks:(a.subtasks||[]).map(u=>({id:Number(u.id),description:u.description,required_tools:u.required_tools,dependencies:u.dependencies,status:"pending"})),total_subtasks:a.subtasks?.length||0,completed_subtasks:0,failed_subtasks:0,progress_percentage:0};}e.subtask_data&&(J=e.subtask_data),e.is_synthesis_start&&(X=!0),e.is_replan&&(O=!0),e.tool_args&&(G=e.tool_args),e.replan_attempt!==void 0&&(Y=e.replan_attempt),e.max_replans!==void 0&&(V=e.max_replans),e.failure_reason&&(K=e.failure_reason),e.progress&&(Z=e.progress);let i="answer";if(e.is_thinking?i="thinking":e.is_planning||e.is_plan_complete||e.is_replanning?i="planning":e.is_subtask_start||e.is_subtask_complete||e.is_subtask_failed?i="subtask":e.is_progress_update&&(i="progress"),i!==_&&(N(),_=i),e.tool_name&&(B=e.tool_name),e.success!==void 0&&(I=e.success),e.subtask_id!==void 0&&(H=e.subtask_id),i==="thinking"){C+=e.chunk||"";let a=C.match(/"thought"\s*:\s*"((?:[^"\\]|\\.)*)"/);a&&(C=a[1].replace(/\\n/g,`
8
+ `).replace(/\\"/g,'"').replace(/\\t/g," ").replace(/\\\\/g,"\\"));}else if(i==="answer"){let a=e.chunk?.trim()||"",u=p.trim();a&&u&&a===u||(p+=e.chunk||"");}else C+=e.chunk||"";e.previous_message_id&&c.onUserMessageIdUpdate(l,e.previous_message_id),s();}else if(e.type==="claude_text"){p+=e.chunk||"";let i=o.find(a=>a.type==="claude_text");i?i.content+=e.chunk||"":o.push({type:"claude_text",content:e.chunk||"",orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_thinking")o.push({type:"claude_thinking",content:e.content||"",orchestrator:"claude_agent_sdk"}),s();else if(e.type==="claude_file_read"){let i={toolUseId:e.tool_use_id,operation:"read",filePath:e.file_path,status:e.status,content:e.content,totalLines:e.total_lines,language:e.language,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="file_operation"&&u.toolUseId===e.tool_use_id);a>=0?o[a].fileOperationData=i:o.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_file_edit"){let i={toolUseId:e.tool_use_id,operation:"edit",filePath:e.file_path,status:e.status,oldString:e.old_string,newString:e.new_string,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="file_operation"&&u.toolUseId===e.tool_use_id);a>=0?o[a].fileOperationData=i:o.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_file_write"){let i={toolUseId:e.tool_use_id,operation:"write",filePath:e.file_path,status:e.status,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="file_operation"&&u.toolUseId===e.tool_use_id);a>=0?o[a].fileOperationData=i:o.push({type:"file_operation",content:"",toolUseId:e.tool_use_id,fileOperationData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_bash"){let i={toolUseId:e.tool_use_id,command:e.command,description:e.description,status:e.status,stdout:e.stdout,stderr:e.stderr,exitCode:e.exit_code,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="terminal"&&u.toolUseId===e.tool_use_id);a>=0?o[a].terminalData=i:o.push({type:"terminal",content:"",toolUseId:e.tool_use_id,terminalData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_search"){let i={toolUseId:e.tool_use_id,tool:e.tool,pattern:e.pattern,path:e.path,status:e.status,results:(e.results||[]).map(u=>({filePath:u.file_path,lineNumber:u.line_number,snippet:u.snippet})),totalCount:e.total_count||0,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="search_results"&&u.toolUseId===e.tool_use_id);a>=0?o[a].searchResultsData=i:o.push({type:"search_results",content:"",toolUseId:e.tool_use_id,searchResultsData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_web_search"||e.type==="claude_web_fetch"){let i={toolUseId:e.tool_use_id,operation:e.type==="claude_web_search"?"search":"fetch",query:e.query,url:e.url,status:e.status,results:e.results,content:e.content,error:e.error,durationMs:e.duration_ms},a=o.findIndex(u=>u.type==="web_operation"&&u.toolUseId===e.tool_use_id);a>=0?o[a].webOperationData=i:o.push({type:"web_operation",content:"",toolUseId:e.tool_use_id,webOperationData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_subagent_start"){let i={subagentId:e.subagent_id,subagentType:e.subagent_type,description:e.description,prompt:e.prompt,status:"running",nestedChunks:[]};o.push({type:"subagent",content:"",toolUseId:e.parent_tool_use_id,subagentData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_subagent_chunk"){let i=o.findIndex(a=>a.type==="subagent"&&a.subagentData?.subagentId===e.subagent_id);i>=0&&o[i].subagentData&&o[i].subagentData.nestedChunks.push({type:e.is_tool?"tool":"answer",content:e.chunk||"",toolName:e.tool_name,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="claude_subagent_complete"){let i=o.findIndex(a=>a.type==="subagent"&&a.subagentData?.subagentId===e.subagent_id);i>=0&&o[i].subagentData&&(o[i].subagentData.status="completed",o[i].subagentData.result=e.result,o[i].subagentData.durationMs=e.duration_ms),s();}else if(e.type==="claude_tool_use"||e.type==="claude_tool_result"){let i={toolUseId:e.tool_use_id,toolName:e.tool_name,toolDescription:e.tool_description,toolInput:e.tool_input,status:e.type==="claude_tool_use"?"pending":e.is_error?"error":"completed",content:e.content,isError:e.is_error,durationMs:e.duration_ms},a=o.findIndex(u=>u.claudeToolData?.toolUseId===e.tool_use_id);a>=0?o[a].claudeToolData=i:o.push({type:"tool",content:e.content||"",toolUseId:e.tool_use_id,toolName:e.tool_name,toolDescription:e.tool_description,status:i.status==="pending"?"planned":"completed",claudeToolData:i,orchestrator:"claude_agent_sdk"}),s();}else if(e.type==="clarification_needed"){N();let i={question:e.question||"",options:e.options||[],context:e.context,allowFreeText:e.allow_free_text!==!1,subtaskId:e.subtask_id,subtaskDescription:e.subtask_description,subagentName:e.subagent_name,subagentRole:e.subagent_role,toolCallId:e.tool_call_id};o.push({type:"clarification_needed",content:i.question,clarificationData:i,subtaskId:e.subtask_id}),$=i,p||(p=i.question),s();}else if(e.type==="tool_approval_needed"){N();let i={toolName:e.tool_name||"",toolDescription:e.tool_description||"",toolInputs:e.tool_inputs||{},toolSchema:e.tool_schema,toolCallId:e.tool_call_id};o.push({type:"tool_approval_needed",content:i.toolDescription,toolApprovalData:i}),te=i,s();}else if(e.type==="media"){let i=e.media_data;i&&(R=[...R,{id:i.id,url:i.url,mediaType:i.media_type||"image",altText:i.alt_text}],s());}else if(e.type==="assistant_complete"){N(),b=!0;let i=e.message?.text_content||p,a=e.message?.id,u=e.message?.metadata?.sources,W=(Date.now()-m)/1e3;c.onComplete(h,i,a,o,T,u,$,W,te),p=i,a&&(h=a);break}else if(e.type==="client_tool_invocation"&&e.invocation&&c.onToolInvocation)c.onToolInvocation(e.invocation);else {if(e.type==="error")throw new Error(e.error||"Stream error");if(e.type==="done"){if(h&&!b){N();let i=(Date.now()-m)/1e3;c.onComplete(h,p||"",e.message_id,o,T,void 0,$,i,te);}else e.message_id&&h&&c.onMessageUpdate({id:h,isStreaming:!1});e.message_id&&(h=e.message_id);break}}}catch(e){if(e instanceof Error&&e.message!=="Stream error"&&(e.message.startsWith("Stream error")||e.message.startsWith("HTTP error")))throw e}}}return {assistantMsgId:h,assistantContent:p}}function Xe(t){let[n,l]=useState([]),[c,d]=useState(false),[m,p]=useState(null),[h,o]=useState(null),[T,$]=useState(true),[te,R]=useState(null),b$1=useRef(t);b$1.current=t;let _=useRef(h);_.current=h;let C=useRef(c);C.current=c;let B=useRef(null),P=useRef(new Map),I=useRef(new Map);useEffect(()=>{let r=false;async function s(){try{let f=await me(b$1.current);r||(o(f),$(!1));}catch(f){r||(R(f instanceof Error?f.message:"Failed to initialize"),$(false));}}return s(),()=>{r=true;}},[t.publicKey,t.assistantId]);let L=useMemo(()=>He(h),[h]),H=b(L),j=useRef(new Map),J=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");if(r.type.startsWith("image/"))try{r=await Se(r);}catch(g){console.warn("Image compression failed, using original:",g);}let f=await he(b$1.current,s,r);return j.current.set(f,{id:f,filename:r.name,mimeType:r.type,size:r.size,isImage:r.type.startsWith("image/"),isVideo:r.type.startsWith("video/"),isDocument:!r.type.startsWith("image/")&&!r.type.startsWith("video/")}),f},[]),X=useCallback(r=>{j.current.delete(r);},[]),O=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");let{invocation_id:f,tool_name:g,parameters:x}=r;console.log(`[Miiflow] Tool invocation received: "${g}" (id: ${f})`);let k=P.current.get(g);if(!k)return false;try{let w=await Promise.race([k(x),new Promise((z,M)=>setTimeout(()=>M(new Error("Tool execution timeout (30s)")),3e4))]);return console.log(`[Miiflow] Tool "${g}" executed successfully (id: ${f})`),await Q(b$1.current,s,{invocation_id:f,result:w}),console.log(`[Miiflow] Tool result sent for "${g}" (id: ${f})`),!0}catch(w){return console.error(`[Miiflow] Tool '${g}' execution failed:`,w),await Q(b$1.current,s,{invocation_id:f,error:w instanceof Error?w.message:String(w)}),true}},[]);useEffect(()=>{if(!h)return;let r=h,s=null,f=null,g=null,x=0,k=false;function w(){if(k)return;let z=Le(b$1.current,r);s=new WebSocket(z),s.onopen=()=>{console.log("[Miiflow] WebSocket connected"),x=0,f=setInterval(()=>{s?.readyState===WebSocket.OPEN&&s.send(JSON.stringify({type:"heartbeat"}));},ze);},s.onmessage=M=>{try{let e=JSON.parse(M.data);e.type==="client_tool_invocation"&&e.invocation&&O(e.invocation).then(async i=>{if(!i){let a=b$1.current.onToolInvocationFallback;a&&await a(e.invocation)||Q(b$1.current,r,{invocation_id:e.invocation.invocation_id,error:`No handler found for tool '${e.invocation.tool_name}'`}).catch(console.error);}}).catch(console.error);}catch{}},s.onclose=()=>{if(f&&(clearInterval(f),f=null),!k){let M=Math.min(We*Math.pow(2,x),qe);x++,g=setTimeout(w,M);}},s.onerror=()=>{};}return w(),()=>{k=true,f&&clearInterval(f),g&&clearTimeout(g),s&&(s.onclose=null,s.close());}},[h,O]);let G=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");await _e(b$1.current,s,r);},[]),Y=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");await be(b$1.current,s,r);},[]),V=useCallback(async(r,s,f)=>{let g=_.current,x=!!r.trim(),k=s&&s.length>0;if(!x&&!k||C.current||!g)return;C.current=true;let w=`msg-${Date.now()}`,z=!!f?.is_clarification_response,M=s?.map(a=>j.current.get(a)).filter(Boolean);s?.forEach(a=>j.current.delete(a));let e=`assistant-pending-${Date.now()}`,i={id:e,textContent:"",participant:{id:"assistant",name:g.config.branding?.custom_name||g.config.assistant_name,role:"assistant",avatarUrl:g.config.branding?.assistant_avatar},createdAt:new Date().toISOString(),isStreaming:true};if(z)l(a=>[...a,i]);else {let a={id:w,textContent:r,participant:{id:"user",name:b$1.current.userName||"You",role:"user"},createdAt:new Date().toISOString(),attachments:M?.length?M:void 0};l(u=>[...u,a,i]),b$1.current.onUserMessageCreated?.({id:w,content:r});}d(true),p(e);try{let a=A(b$1.current),u=new AbortController;B.current=u;let W=await fetch(`${a}/assistant/message/stream/`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${g.token}`,"x-mii-user-id":U()},body:JSON.stringify({thread_id:g.config.thread_id,text_content:r,message_id:w,metadata:f||{},attachment_ids:s||[]}),signal:u.signal});if(!W.ok)throw new Error(`HTTP error: ${W.status}`);let re=W.body?.getReader();if(!re)throw new Error("No response body");let ie=await Je(re,g,w,{onMessageCreate:S=>{p(S.id),l(D=>[...D.filter(F=>F.id!==e),S]);},onMessageUpdate:S=>{l(D=>D.map(v=>v.id===S.id?{...v,...S}:v));},onUserMessageIdUpdate:(S,D)=>{l(v=>v.map(F=>F.id===S?{...F,id:D}:F));},onComplete:(S,D,v,F,le,xe,De,ve,Ae)=>{S&&l(Me=>Me.map(ue=>ue.id===S?{...ue,id:v||ue.id,textContent:D,isStreaming:!1,reasoning:F,suggestedActions:le,citations:xe,pendingClarification:De,pendingToolApproval:Ae,executionTime:ve}:ue)),b$1.current.onAssistantMessageComplete?.({id:v||S||"",content:D});},onToolInvocation:async S=>{if(!await O(S)){let v=b$1.current.onToolInvocationFallback;if(!(v?await v(S):!1)){let le=_.current;le&&await Q(b$1.current,le,{invocation_id:S.invocation_id,error:`No handler found for tool '${S.tool_name}'`});}}}});ie.assistantMsgId&&l(S=>S.map(D=>D.id===ie.assistantMsgId?{...D,isStreaming:!1}:D));}catch(a){if(a instanceof DOMException&&a.name==="AbortError")return;console.error("[Miiflow] Send error:",a);let u=_.current,W={id:`error-${Date.now()}`,textContent:"Sorry, I encountered an error. Please try again.",participant:{id:"assistant",name:u?.config.branding?.custom_name||u?.config.assistant_name||"Assistant",role:"assistant",avatarUrl:u?.config.branding?.assistant_avatar},createdAt:new Date().toISOString()};l(re=>[...re.filter(ie=>ie.id!==e),W]),R(a instanceof Error?a.message:"Send failed");}finally{B.current=null,d(false),p(null);}},[O]),K=useCallback(()=>{C.current&&(B.current?.abort(),B.current=null,l(r=>r.map(s=>s.isStreaming?{...s,isStreaming:false}:s)),C.current=false,d(false),p(null));},[]),Z=useCallback(async()=>{let r=_.current;if(!r)throw new Error("Not initialized");let s=await ge(b$1.current,r);s.token||console.warn("[Miiflow] CreateThread did not return new token \u2014 tools may register to wrong thread");let f={...r,config:{...r.config,thread_id:s.threadId},token:s.token||r.token};if(_.current=f,o(f),l([]),I.current.size>0){console.log(`[Miiflow] Re-registering ${I.current.size} tools on new thread`);try{await ae(b$1.current,f,Array.from(I.current.values()));}catch(g){console.warn("[Miiflow] Failed to re-register tools:",g);}}return s.threadId},[]),oe=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");de(r),P.current.set(r.name,r.handler);let f=pe(r);I.current.set(r.name,f);try{await ae(b$1.current,s,[f]),console.log(`[Miiflow] Tool registered: "${r.name}"`);}catch(g){throw P.current.delete(r.name),I.current.delete(r.name),g}},[]),ne=useCallback(async r=>{let s=_.current;if(!s)throw new Error("Not initialized");for(let k of r)de(k);let f=new Map(P.current),g=new Map(I.current),x=[];for(let k of r){P.current.set(k.name,k.handler);let w=pe(k);I.current.set(k.name,w),x.push(w);}try{await ae(b$1.current,s,x);let k=r.map(w=>w.name);console.log(`[Miiflow] Tools registered: ${JSON.stringify(k)} (${r.length} tools)`);}catch(k){throw P.current=f,I.current=g,k}},[]),se=useMemo(()=>n.filter(r=>r.participant.role!=="system").map(r=>({id:r.id,textContent:r.textContent?.replace(/\[ref:[^\]]+\]/g,"")||r.textContent,participant:r.participant,createdAt:r.createdAt,isStreaming:r.isStreaming,reasoning:r.reasoning,suggestedActions:r.suggestedActions,citations:r.citations,attachments:r.attachments,pendingClarification:r.pendingClarification,pendingToolApproval:r.pendingToolApproval,executionTime:r.executionTime})),[n]),N=useCallback(r=>{o(r);},[]);return {messages:se,isStreaming:c,streamingMessageId:m,sendMessage:V,uploadFile:J,removeUploadedAttachment:X,session:h,loading:T,error:te,branding:L,brandingCSSVars:H,startNewThread:Z,registerTool:oe,registerTools:ne,sendSystemEvent:G,sendPageContext:Y,handleToolInvocation:O,updateSession:N,stopStreaming:K}}function fe(t){try{let n=t.split(".");if(n.length!==3)return null;let l=n[1].replace(/-/g,"+").replace(/_/g,"/"),c=atob(l),d=JSON.parse(c);return typeof d.exp=="number"?d.exp*1e3:null}catch{return null}}function Ge(t,n){let l=fe(t);return l===null?true:l-Date.now()<=n}function Ye(t){let n=fe(t);return n===null?true:Date.now()>=n}function Ve(t){let n=fe(t);return n===null?0:Math.max(0,n-Date.now())}export{y as ToolValidationError,ge as createThread,A as getBackendBaseUrl,U as getOrCreateUserId,Ve as getTimeUntilExpiry,me as initSession,Ye as isTokenExpired,Ge as isTokenExpiringSoon,fe as parseTokenExpiry,ae as registerToolsOnBackend,be as sendPageContext,_e as sendSystemEvent,Q as sendToolResult,pe as serializeToolDefinition,Oe as updateUser,he as uploadFile,Xe as useMiiflowChat,de as validateToolDefinition};//# sourceMappingURL=index.js.map
9
9
  //# sourceMappingURL=index.js.map