@blinq_ai/widget 0.1.0 → 0.1.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.
package/dist/index.cjs CHANGED
@@ -31,7 +31,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  BlinqWidget: () => BlinqWidget,
34
+ EMBED_WIDGET_STYLES: () => EMBED_WIDGET_STYLES,
35
+ PageToolRegistry: () => PageToolRegistry,
36
+ WidgetEmbedShell: () => WidgetEmbedShell,
37
+ collectNormalizedPageContext: () => collectNormalizedPageContext,
34
38
  createBlinqWidget: () => createBlinqWidget,
39
+ detectNativeWebMcpSupport: () => detectNativeWebMcpSupport,
35
40
  init: () => init,
36
41
  initFromConfig: () => initFromConfig
37
42
  });
@@ -574,6 +579,12 @@ function collectNormalizedPageContext() {
574
579
  }
575
580
 
576
581
  // src/page-tools.ts
582
+ var DEFAULT_ACTION_POLICY = {
583
+ actions_enabled: true,
584
+ action_mode: "execute_with_confirmation",
585
+ pointer_overlay_enabled: true
586
+ };
587
+ var GUIDANCE_SAFE_TOOL_NAMES = /* @__PURE__ */ new Set(["blinq.scroll_to_element"]);
577
588
  function isBrowser2() {
578
589
  return typeof window !== "undefined" && typeof document !== "undefined";
579
590
  }
@@ -670,6 +681,12 @@ function findTarget(selector) {
670
681
  }
671
682
  return target;
672
683
  }
684
+ function shouldRequestConfirmation(toolName, readOnly) {
685
+ if (readOnly) {
686
+ return false;
687
+ }
688
+ return !GUIDANCE_SAFE_TOOL_NAMES.has(toolName);
689
+ }
673
690
  function isDuplicateNativeToolError(error) {
674
691
  if (!(error instanceof Error)) {
675
692
  return false;
@@ -831,6 +848,15 @@ function buildSemanticToolDefinition(descriptor) {
831
848
  }
832
849
  return null;
833
850
  }
851
+ function selectorFromArguments(argumentsPayload) {
852
+ for (const key of ["selector", "field_selector", "submit_selector", "form_selector"]) {
853
+ const value = argumentsPayload[key];
854
+ if (typeof value === "string" && value.trim()) {
855
+ return value.trim();
856
+ }
857
+ }
858
+ return null;
859
+ }
834
860
  function detectNativeWebMcpSupport() {
835
861
  if (!isBrowser2() || !window.isSecureContext) {
836
862
  return false;
@@ -846,10 +872,17 @@ var PageToolRegistry = class {
846
872
  nativeToolsActive = false;
847
873
  highlightLayer = null;
848
874
  highlightTimer = null;
875
+ actionPolicy = { ...DEFAULT_ACTION_POLICY };
849
876
  constructor(confirmationHandler) {
850
877
  this.confirmationHandler = confirmationHandler;
851
878
  this.refreshToolCatalog();
852
879
  }
880
+ setActionPolicy(nextPolicy) {
881
+ this.actionPolicy = {
882
+ ...DEFAULT_ACTION_POLICY,
883
+ ...nextPolicy
884
+ };
885
+ }
853
886
  buildBaseTools() {
854
887
  const tools = /* @__PURE__ */ new Map();
855
888
  tools.set("blinq.read_visible_page_context", {
@@ -1023,7 +1056,7 @@ var PageToolRegistry = class {
1023
1056
  }
1024
1057
  getToolCapabilities() {
1025
1058
  this.refreshToolCatalog();
1026
- return Array.from(this.tools.values()).map((tool) => tool.capability);
1059
+ return Array.from(this.tools.values()).filter((tool) => this.isToolAllowed(tool)).map((tool) => tool.capability);
1027
1060
  }
1028
1061
  clearHighlights() {
1029
1062
  if (this.highlightTimer !== null) {
@@ -1049,13 +1082,52 @@ var PageToolRegistry = class {
1049
1082
  this.highlightLayer = layer;
1050
1083
  return layer;
1051
1084
  }
1085
+ ensureHighlightStyle() {
1086
+ if (document.getElementById("blinq-highlight-style")) {
1087
+ return;
1088
+ }
1089
+ const style = document.createElement("style");
1090
+ style.id = "blinq-highlight-style";
1091
+ style.textContent = `
1092
+ @keyframes blinq-highlight-pulse {
1093
+ 0%, 100% { opacity: 0.55; transform: scale(1); }
1094
+ 50% { opacity: 1; transform: scale(1.02); }
1095
+ }
1096
+
1097
+ @keyframes blinq-highlight-ripple {
1098
+ 0% { opacity: 0.36; transform: translate(-50%, -50%) scale(0.8); }
1099
+ 100% { opacity: 0; transform: translate(-50%, -50%) scale(1.7); }
1100
+ }
1101
+
1102
+ @keyframes blinq-pointer-bob {
1103
+ 0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
1104
+ 50% { transform: translate3d(0, -2px, 0) scale(1.03); }
1105
+ }
1106
+ `;
1107
+ document.head.appendChild(style);
1108
+ }
1052
1109
  highlightTargets(targets, options) {
1053
1110
  if (!isBrowser2() || targets.length === 0) {
1054
1111
  return false;
1055
1112
  }
1056
1113
  this.clearHighlights();
1057
1114
  const layer = this.ensureHighlightLayer();
1115
+ this.ensureHighlightStyle();
1058
1116
  let highlightedCount = 0;
1117
+ let primaryRect = null;
1118
+ const backdrop = document.createElement("div");
1119
+ Object.assign(backdrop.style, {
1120
+ position: "fixed",
1121
+ inset: "0",
1122
+ background: "rgba(15, 23, 42, 0.08)",
1123
+ backdropFilter: "blur(1.5px)",
1124
+ opacity: "0",
1125
+ transition: "opacity 180ms ease"
1126
+ });
1127
+ layer.appendChild(backdrop);
1128
+ window.requestAnimationFrame(() => {
1129
+ backdrop.style.opacity = "1";
1130
+ });
1059
1131
  for (const target of targets) {
1060
1132
  if (!target.selector) {
1061
1133
  continue;
@@ -1069,21 +1141,30 @@ var PageToolRegistry = class {
1069
1141
  if (!element) {
1070
1142
  continue;
1071
1143
  }
1144
+ if (!primaryRect) {
1145
+ element.scrollIntoView({
1146
+ block: "center",
1147
+ inline: "nearest"
1148
+ });
1149
+ }
1072
1150
  const rect = element.getBoundingClientRect();
1073
1151
  if (rect.width <= 0 || rect.height <= 0) {
1074
1152
  continue;
1075
1153
  }
1154
+ if (!primaryRect) {
1155
+ primaryRect = rect;
1156
+ }
1076
1157
  const frame = document.createElement("div");
1077
1158
  Object.assign(frame.style, {
1078
1159
  position: "fixed",
1079
- left: `${Math.max(rect.left - 6, 4)}px`,
1080
- top: `${Math.max(rect.top - 6, 4)}px`,
1081
- width: `${Math.max(rect.width + 12, 18)}px`,
1082
- height: `${Math.max(rect.height + 12, 18)}px`,
1083
- border: "2px solid rgba(17, 17, 17, 0.92)",
1084
- borderRadius: "16px",
1085
- background: "rgba(17, 17, 17, 0.05)",
1086
- boxShadow: "0 0 0 1px rgba(255, 255, 255, 0.85), 0 18px 38px rgba(17, 17, 17, 0.14)",
1160
+ left: `${Math.max(rect.left - 8, 4)}px`,
1161
+ top: `${Math.max(rect.top - 8, 4)}px`,
1162
+ width: `${Math.max(rect.width + 16, 24)}px`,
1163
+ height: `${Math.max(rect.height + 16, 24)}px`,
1164
+ border: "3px solid rgba(17, 17, 17, 0.94)",
1165
+ borderRadius: "18px",
1166
+ background: "rgba(255, 255, 255, 0.16)",
1167
+ boxShadow: "0 0 0 1px rgba(255, 255, 255, 0.9), 0 24px 48px rgba(15, 23, 42, 0.18)",
1087
1168
  opacity: "0",
1088
1169
  transform: "scale(0.985)",
1089
1170
  transition: "opacity 180ms ease, transform 180ms ease"
@@ -1091,9 +1172,9 @@ var PageToolRegistry = class {
1091
1172
  const glow = document.createElement("div");
1092
1173
  Object.assign(glow.style, {
1093
1174
  position: "absolute",
1094
- inset: "-8px",
1095
- borderRadius: "20px",
1096
- border: "1px solid rgba(17, 17, 17, 0.14)",
1175
+ inset: "-10px",
1176
+ borderRadius: "22px",
1177
+ border: "1px solid rgba(37, 99, 235, 0.22)",
1097
1178
  animation: "blinq-highlight-pulse 1.2s ease-in-out infinite"
1098
1179
  });
1099
1180
  frame.appendChild(glow);
@@ -1102,15 +1183,15 @@ var PageToolRegistry = class {
1102
1183
  badge.textContent = target.label;
1103
1184
  Object.assign(badge.style, {
1104
1185
  position: "absolute",
1105
- top: "-14px",
1186
+ top: "-16px",
1106
1187
  left: "10px",
1107
- maxWidth: "min(220px, 70vw)",
1108
- padding: "4px 10px",
1188
+ maxWidth: "min(260px, 70vw)",
1189
+ padding: "6px 12px",
1109
1190
  borderRadius: "999px",
1110
1191
  background: "#111111",
1111
1192
  color: "#ffffff",
1112
1193
  fontFamily: '"Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
1113
- fontSize: "11px",
1194
+ fontSize: "12px",
1114
1195
  fontWeight: "600",
1115
1196
  lineHeight: "1.3",
1116
1197
  whiteSpace: "nowrap",
@@ -1127,16 +1208,57 @@ var PageToolRegistry = class {
1127
1208
  });
1128
1209
  highlightedCount += 1;
1129
1210
  }
1130
- if (!document.getElementById("blinq-highlight-style")) {
1131
- const style = document.createElement("style");
1132
- style.id = "blinq-highlight-style";
1133
- style.textContent = `
1134
- @keyframes blinq-highlight-pulse {
1135
- 0%, 100% { opacity: 0.55; transform: scale(1); }
1136
- 50% { opacity: 1; transform: scale(1.02); }
1137
- }
1211
+ if (this.actionPolicy.pointer_overlay_enabled && primaryRect) {
1212
+ const pointer = document.createElement("div");
1213
+ pointer.setAttribute("data-blinq-pointer", options?.interaction ?? "explain");
1214
+ pointer.innerHTML = `
1215
+ <div style="position:absolute;inset:0;border-radius:999px;background:rgba(255,255,255,0.92);box-shadow:0 14px 28px rgba(15,23,42,0.18);"></div>
1216
+ <svg viewBox="0 0 40 40" width="40" height="40" fill="none" aria-hidden="true" style="position:relative;z-index:1;">
1217
+ <path d="M8 5L28 22H18.4L23.2 34.8L17.8 36.8L13 24H6.6L8 5Z" fill="#111111"/>
1218
+ <path d="M8 5L28 22H18.4L23.2 34.8L17.8 36.8L13 24H6.6L8 5Z" stroke="#ffffff" stroke-width="1.4" stroke-linejoin="round"/>
1219
+ </svg>
1138
1220
  `;
1139
- document.head.appendChild(style);
1221
+ Object.assign(pointer.style, {
1222
+ position: "fixed",
1223
+ left: `${Math.max(primaryRect.left - 72, 12)}px`,
1224
+ top: `${Math.max(primaryRect.bottom + 44, 12)}px`,
1225
+ width: "40px",
1226
+ height: "40px",
1227
+ zIndex: "2147483647",
1228
+ opacity: "0",
1229
+ transform: "translate3d(0, 0, 0) scale(0.92)",
1230
+ transition: "left 380ms cubic-bezier(.22,1,.36,1), top 380ms cubic-bezier(.22,1,.36,1), opacity 180ms ease, transform 380ms cubic-bezier(.22,1,.36,1)",
1231
+ filter: "drop-shadow(0 16px 28px rgba(15, 23, 42, 0.2))",
1232
+ animation: "blinq-pointer-bob 1.1s ease-in-out infinite"
1233
+ });
1234
+ layer.appendChild(pointer);
1235
+ const pointerTargetLeft = Math.max(primaryRect.left + 14, 8);
1236
+ const pointerTargetTop = Math.max(primaryRect.top + 14, 8);
1237
+ window.requestAnimationFrame(() => {
1238
+ pointer.style.opacity = "1";
1239
+ pointer.style.left = `${pointerTargetLeft}px`;
1240
+ pointer.style.top = `${pointerTargetTop}px`;
1241
+ pointer.style.transform = "translate3d(0, 0, 0) scale(1)";
1242
+ });
1243
+ if (options?.interaction === "execute") {
1244
+ const ripple = document.createElement("div");
1245
+ Object.assign(ripple.style, {
1246
+ position: "fixed",
1247
+ left: `${primaryRect.left + Math.min(primaryRect.width, 32) / 2}px`,
1248
+ top: `${primaryRect.top + Math.min(primaryRect.height, 32) / 2}px`,
1249
+ width: "34px",
1250
+ height: "34px",
1251
+ borderRadius: "999px",
1252
+ border: "3px solid rgba(17, 17, 17, 0.58)",
1253
+ background: "rgba(17, 17, 17, 0.12)",
1254
+ pointerEvents: "none",
1255
+ opacity: "0",
1256
+ transform: "translate(-50%, -50%) scale(0.8)",
1257
+ animation: "blinq-highlight-ripple 560ms ease-out 1 forwards",
1258
+ animationDelay: "320ms"
1259
+ });
1260
+ layer.appendChild(ripple);
1261
+ }
1140
1262
  }
1141
1263
  if (highlightedCount === 0) {
1142
1264
  this.clearHighlights();
@@ -1147,8 +1269,38 @@ var PageToolRegistry = class {
1147
1269
  }, options?.durationMs ?? 2200);
1148
1270
  return true;
1149
1271
  }
1272
+ isToolAllowed(tool) {
1273
+ if (tool.capability.read_only) {
1274
+ return true;
1275
+ }
1276
+ if (GUIDANCE_SAFE_TOOL_NAMES.has(tool.capability.name)) {
1277
+ return this.actionPolicy.actions_enabled;
1278
+ }
1279
+ return this.actionPolicy.actions_enabled && this.actionPolicy.action_mode === "execute_with_confirmation";
1280
+ }
1281
+ async previewToolRequest(request, options) {
1282
+ const selector = selectorFromArguments(request.arguments);
1283
+ if (!selector) {
1284
+ return false;
1285
+ }
1286
+ const label = (request.target_summary || request.display_name || "").trim() || void 0;
1287
+ const highlighted = this.highlightTargets(
1288
+ [{ selector, label }],
1289
+ {
1290
+ durationMs: options?.durationMs ?? (options?.interaction === "execute" ? 1600 : 2200),
1291
+ interaction: options?.interaction ?? "explain"
1292
+ }
1293
+ );
1294
+ if (!highlighted) {
1295
+ return false;
1296
+ }
1297
+ await new Promise(
1298
+ (resolve) => window.setTimeout(resolve, options?.interaction === "execute" ? 520 : 240)
1299
+ );
1300
+ return true;
1301
+ }
1150
1302
  canExecuteWriteTools() {
1151
- return isBrowser2();
1303
+ return isBrowser2() && this.actionPolicy.actions_enabled && this.actionPolicy.action_mode === "execute_with_confirmation";
1152
1304
  }
1153
1305
  async executeTool(request) {
1154
1306
  let tool = this.tools.get(request.tool_name);
@@ -1164,7 +1316,22 @@ var PageToolRegistry = class {
1164
1316
  }
1165
1317
  const displayName = request.display_name ?? tool.capability.name;
1166
1318
  const targetSummary = request.target_summary ?? tool.describeTarget?.(request.arguments) ?? tool.capability.description;
1167
- const requiresConfirmation = request.requires_confirmation ?? !tool.capability.read_only;
1319
+ const requiresConfirmation = request.requires_confirmation ?? shouldRequestConfirmation(request.tool_name, tool.capability.read_only);
1320
+ if (request.tool_name !== "blinq.highlight_element") {
1321
+ await this.previewToolRequest(request, {
1322
+ interaction: tool.capability.read_only ? "explain" : "execute"
1323
+ });
1324
+ }
1325
+ if (!tool.capability.read_only && !this.isToolAllowed(tool)) {
1326
+ return {
1327
+ status: "success",
1328
+ result: {
1329
+ success: true,
1330
+ guided: true,
1331
+ preview_only: true
1332
+ }
1333
+ };
1334
+ }
1168
1335
  if (!tool.capability.read_only && requiresConfirmation) {
1169
1336
  const confirmed = await this.confirmationHandler({
1170
1337
  displayName,
@@ -1206,6 +1373,9 @@ var PageToolRegistry = class {
1206
1373
  this.refreshToolCatalog();
1207
1374
  this.unregisterNativeTools();
1208
1375
  for (const [toolName, tool] of this.tools) {
1376
+ if (!this.isToolAllowed(tool)) {
1377
+ continue;
1378
+ }
1209
1379
  const controller = new AbortController();
1210
1380
  try {
1211
1381
  modelContext.registerTool(
@@ -1248,6 +1418,7 @@ var PageToolRegistry = class {
1248
1418
 
1249
1419
  // src/embed-shell.tsx
1250
1420
  var React = __toESM(require("react"), 1);
1421
+ var import_lucide_react = require("lucide-react");
1251
1422
  var import_react = require("@assistant-ui/react");
1252
1423
  var import_jsx_runtime = require("react/jsx-runtime");
1253
1424
  function cn(...values) {
@@ -1304,87 +1475,44 @@ function Badge({
1304
1475
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn(badgeClassName(variant), className), ...props });
1305
1476
  }
1306
1477
  function LauncherIcon() {
1307
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1308
- "svg",
1309
- {
1310
- viewBox: "0 0 24 24",
1311
- width: "18",
1312
- height: "18",
1313
- fill: "none",
1314
- "aria-hidden": "true",
1315
- className: "blinq-launcher-agent",
1316
- children: [
1317
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-orbit", cx: "12", cy: "12", r: "9" }),
1318
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-spark", cx: "18.6", cy: "8.2", r: "1.2" }),
1319
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1320
- "path",
1321
- {
1322
- className: "blinq-agent-antenna",
1323
- d: "M12 4.8V6.8",
1324
- stroke: "currentColor",
1325
- strokeWidth: "1.6",
1326
- strokeLinecap: "round"
1327
- }
1328
- ),
1329
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-antenna-dot", cx: "12", cy: "4.1", r: "1.1", fill: "currentColor" }),
1330
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1331
- "rect",
1332
- {
1333
- className: "blinq-agent-head",
1334
- x: "7",
1335
- y: "7.4",
1336
- width: "10",
1337
- height: "9.2",
1338
- rx: "3.2",
1339
- fill: "currentColor"
1340
- }
1341
- ),
1342
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-eye", cx: "10.2", cy: "11.3", r: "0.9", fill: "#111111" }),
1343
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { className: "blinq-agent-eye", cx: "13.8", cy: "11.3", r: "0.9", fill: "#111111" }),
1344
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1345
- "path",
1346
- {
1347
- className: "blinq-agent-mouth",
1348
- d: "M10 14.2c.7.55 1.38.82 2 .82s1.3-.27 2-.82",
1349
- stroke: "#111111",
1350
- strokeWidth: "1.3",
1351
- strokeLinecap: "round"
1352
- }
1353
- ),
1354
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1355
- "path",
1356
- {
1357
- className: "blinq-agent-neck",
1358
- d: "M10.2 17.1h3.6",
1359
- stroke: "currentColor",
1360
- strokeWidth: "1.4",
1361
- strokeLinecap: "round"
1362
- }
1363
- )
1364
- ]
1365
- }
1366
- );
1478
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Bot, { "aria-hidden": "true", className: "blinq-launcher-icon", size: 30, strokeWidth: 1.7 });
1479
+ }
1480
+ function AssistantAvatar({
1481
+ avatarUrl,
1482
+ assistantName
1483
+ }) {
1484
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-avatar", "aria-hidden": "true", children: [
1485
+ avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: avatarUrl, alt: "", className: "blinq-avatar-image" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Bot, { className: "blinq-avatar-icon", size: 24, strokeWidth: 1.8 }),
1486
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-avatar-status" }),
1487
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-avatar-label", children: assistantName.slice(0, 1) })
1488
+ ] });
1367
1489
  }
1368
1490
  function CollapseIcon() {
1369
1491
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 12h12", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) });
1370
1492
  }
1371
1493
  function MicrophoneIcon({ listening }) {
1372
1494
  if (listening) {
1373
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "7", y: "7", width: "10", height: "10", rx: "2.5", fill: "currentColor" }) });
1495
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: [
1496
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8.25", stroke: "currentColor", strokeWidth: "1.65" }),
1497
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "9.1", y: "9.1", width: "5.8", height: "5.8", rx: "1.6", fill: "currentColor" })
1498
+ ] });
1374
1499
  }
1375
1500
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: [
1376
1501
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1377
1502
  "path",
1378
1503
  {
1379
- d: "M12 3.75a2.75 2.75 0 0 1 2.75 2.75v5.25a2.75 2.75 0 1 1-5.5 0V6.5A2.75 2.75 0 0 1 12 3.75Z",
1380
- fill: "currentColor"
1504
+ d: "M12 4.35a3.05 3.05 0 0 1 3.05 3.05v4.7a3.05 3.05 0 1 1-6.1 0V7.4A3.05 3.05 0 0 1 12 4.35Z",
1505
+ stroke: "currentColor",
1506
+ strokeWidth: "1.7"
1381
1507
  }
1382
1508
  ),
1383
1509
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1384
1510
  "path",
1385
1511
  {
1386
- d: "M7.5 10.5a.75.75 0 0 1 .75.75a3.75 3.75 0 1 0 7.5 0a.75.75 0 0 1 1.5 0A5.25 5.25 0 0 1 12.75 16.4V18.5H15a.75.75 0 0 1 0 1.5H9a.75.75 0 0 1 0-1.5h2.25v-2.1A5.25 5.25 0 0 1 6.75 11.25a.75.75 0 0 1 .75-.75Z",
1387
- fill: "currentColor"
1512
+ d: "M7.95 11.35a4.05 4.05 0 1 0 8.1 0M12 16.45v3.2M9.2 19.65h5.6",
1513
+ stroke: "currentColor",
1514
+ strokeWidth: "1.7",
1515
+ strokeLinecap: "round"
1388
1516
  }
1389
1517
  )
1390
1518
  ] });
@@ -1393,7 +1521,7 @@ function SendIcon() {
1393
1521
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1394
1522
  "path",
1395
1523
  {
1396
- d: "M5.5 12h11M12.5 5l6.5 7-6.5 7",
1524
+ d: "M5.5 18.5 18.5 5.5M8.25 5.5h10.25v10.25",
1397
1525
  stroke: "currentColor",
1398
1526
  strokeWidth: "1.8",
1399
1527
  strokeLinecap: "round",
@@ -1555,7 +1683,7 @@ function VoiceWaveform({
1555
1683
  const waveform = samples.length > 0 ? samples : [0.18];
1556
1684
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-recording-input", role: "status", "aria-live": "polite", children: [
1557
1685
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-recording-time", children: formatRecordingDuration(durationMs) }),
1558
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-recording-waveform", "aria-hidden": "true", children: waveform.map((sample, index) => {
1686
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-recording-wave-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-recording-waveform", "aria-hidden": "true", children: waveform.map((sample, index) => {
1559
1687
  const scale = Math.max(0.16, Math.min(1, sample));
1560
1688
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1561
1689
  "span",
@@ -1565,9 +1693,21 @@ function VoiceWaveform({
1565
1693
  },
1566
1694
  `voice-wave-${index}`
1567
1695
  );
1568
- }) })
1696
+ }) }) })
1569
1697
  ] });
1570
1698
  }
1699
+ function planStepStatusLabel(step, isCurrent) {
1700
+ if (step.status === "completed") {
1701
+ return "\u0413\u043E\u0442\u043E\u0432\u043E";
1702
+ }
1703
+ if (step.status === "failed") {
1704
+ return "\u041E\u0448\u0438\u0431\u043A\u0430";
1705
+ }
1706
+ if (step.status === "cancelled") {
1707
+ return "\u041E\u0442\u043C\u0435\u043D\u0435\u043D\u043E";
1708
+ }
1709
+ return isCurrent ? "\u0421\u0435\u0439\u0447\u0430\u0441" : "\u0414\u0430\u043B\u0435\u0435";
1710
+ }
1571
1711
  function ActionCard({
1572
1712
  item,
1573
1713
  accentColor,
@@ -1597,9 +1737,6 @@ function ActionCard({
1597
1737
  {
1598
1738
  type: "button",
1599
1739
  onClick: onApprove,
1600
- style: {
1601
- background: accentColor
1602
- },
1603
1740
  children: "\u0412\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C"
1604
1741
  }
1605
1742
  )
@@ -1615,17 +1752,17 @@ function PlanCard({
1615
1752
  onDecline
1616
1753
  }) {
1617
1754
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { className: "blinq-action-card blinq-plan-card", children: [
1618
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
1755
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-plan-header", children: [
1619
1756
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1620
1757
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: "\u041F\u043B\u0430\u043D" }),
1621
1758
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardDescription, { children: item.goal })
1622
1759
  ] }),
1623
1760
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: item.status === "completed" ? "default" : item.status === "failed" ? "outline" : "soft", children: item.status === "completed" ? "\u0413\u043E\u0442\u043E\u0432\u043E" : item.status === "failed" ? "\u041E\u0448\u0438\u0431\u043A\u0430" : item.status === "awaiting_navigation" ? "\u041F\u0435\u0440\u0435\u0445\u043E\u0434" : "\u0412 \u0440\u0430\u0431\u043E\u0442\u0435" })
1624
1761
  ] }) }),
1625
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, { className: "space-y-3", children: [
1762
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, { className: "blinq-plan-content", children: [
1626
1763
  item.progressLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-action-state", children: item.progressLabel }) : null,
1627
1764
  item.statusReason ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-card-description", children: item.statusReason }) : null,
1628
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-2", children: item.steps.map((step, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1765
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-plan-steps", children: item.steps.map((step, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1629
1766
  "div",
1630
1767
  {
1631
1768
  className: "blinq-plan-step",
@@ -1634,7 +1771,10 @@ function PlanCard({
1634
1771
  children: [
1635
1772
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-plan-step-index", children: index + 1 }),
1636
1773
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-plan-step-copy", children: [
1637
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: step.title }),
1774
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-plan-step-title-row", children: [
1775
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-plan-step-title", children: step.title }),
1776
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-plan-step-status-pill", children: planStepStatusLabel(step, index === item.currentStepIndex) })
1777
+ ] }),
1638
1778
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-plan-step-meta", children: step.status === "completed" ? "\u0412\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u043E" : step.status === "failed" ? "\u041E\u0448\u0438\u0431\u043A\u0430" : step.status === "cancelled" ? "\u041E\u0442\u043C\u0435\u043D\u0435\u043D\u043E" : index === item.currentStepIndex ? "\u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u0448\u0430\u0433" : "\u041E\u0436\u0438\u0434\u0430\u0435\u0442" })
1639
1779
  ] })
1640
1780
  ]
@@ -1648,6 +1788,53 @@ function PlanCard({
1648
1788
  ] })
1649
1789
  ] });
1650
1790
  }
1791
+ function GuideCard({
1792
+ guide,
1793
+ onStartGuide,
1794
+ onAdvanceGuide,
1795
+ onDismissGuide,
1796
+ onCompleteGuide,
1797
+ onRunGuideStep
1798
+ }) {
1799
+ const currentStep = guide.steps[Math.min(guide.currentStepIndex, Math.max(guide.steps.length - 1, 0))] ?? null;
1800
+ const isStarted = guide.state === "started";
1801
+ const isCompleted = guide.state === "completed";
1802
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { className: "blinq-guide-card", children: [
1803
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-plan-header", children: [
1804
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1805
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: "Guide \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435" }),
1806
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardDescription, { children: guide.summary || "\u041F\u043E\u0448\u0430\u0433\u043E\u0432\u0430\u044F \u043F\u043E\u043C\u043E\u0449\u044C \u043F\u043E \u0442\u0435\u043A\u0443\u0449\u0435\u043C\u0443 \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443." })
1807
+ ] }),
1808
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { variant: guide.source === "live" ? "soft" : "accent", children: guide.source === "live" ? "Live" : "Published" })
1809
+ ] }) }),
1810
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, { className: "blinq-guide-content", children: !isStarted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1811
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-card-description", children: "\u0410\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442 \u0443\u0436\u0435 \u043F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u0438\u043B guide \u0434\u043B\u044F \u044D\u0442\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B \u0438 \u043C\u043E\u0436\u0435\u0442 \u043F\u0440\u043E\u0432\u0435\u0441\u0442\u0438 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043F\u043E \u0448\u0430\u0433\u0430\u043C." }),
1812
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-actions", children: [
1813
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", variant: "outline", onClick: onDismissGuide, children: "\u0421\u043A\u0440\u044B\u0442\u044C" }),
1814
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", onClick: onStartGuide, children: "\u041D\u0430\u0447\u0430\u0442\u044C guide" })
1815
+ ] })
1816
+ ] }) : currentStep && !isCompleted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1817
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-guide-step-shell", children: [
1818
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-guide-step-meta", children: [
1819
+ "\u0428\u0430\u0433 ",
1820
+ Math.min(guide.currentStepIndex + 1, guide.totalSteps),
1821
+ " \u0438\u0437 ",
1822
+ guide.totalSteps
1823
+ ] }),
1824
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-guide-step-title", children: currentStep.title }),
1825
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-guide-step-copy", children: currentStep.body })
1826
+ ] }),
1827
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-actions", children: [
1828
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", variant: "outline", onClick: onDismissGuide, children: "\u0421\u043A\u0440\u044B\u0442\u044C" }),
1829
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", variant: "outline", onClick: onRunGuideStep, children: currentStep.actionKind ? "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C / \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u0448\u0430\u0433" : "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435" }),
1830
+ guide.currentStepIndex + 1 >= guide.totalSteps ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", onClick: onCompleteGuide, children: "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", onClick: onAdvanceGuide, children: "\u0414\u0430\u043B\u044C\u0448\u0435" })
1831
+ ] })
1832
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1833
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-card-description", children: "Guide \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D. \u041C\u043E\u0436\u043D\u043E \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C \u0440\u0430\u0431\u043E\u0442\u0443 \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435 \u0441\u0430\u043C\u043E\u0441\u0442\u043E\u044F\u0442\u0435\u043B\u044C\u043D\u043E." }),
1834
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, { type: "button", onClick: onDismissGuide, children: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C" }) })
1835
+ ] }) })
1836
+ ] });
1837
+ }
1651
1838
  function AssistantConversationThread({
1652
1839
  items,
1653
1840
  showThinkingIndicator,
@@ -1724,34 +1911,52 @@ function WidgetEmbedShell({
1724
1911
  onApproveAction,
1725
1912
  onDeclineAction,
1726
1913
  onApprovePlan,
1727
- onDeclinePlan
1914
+ onDeclinePlan,
1915
+ onStartGuide,
1916
+ onAdvanceGuide,
1917
+ onDismissGuide,
1918
+ onCompleteGuide,
1919
+ onRunGuideStep
1728
1920
  }) {
1729
1921
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1730
1922
  "div",
1731
1923
  {
1732
1924
  className: "blinq-shell",
1733
1925
  "data-side": state.side,
1926
+ "data-theme": state.themeVariant,
1734
1927
  style: { ["--blinq-accent"]: state.accentColor },
1735
1928
  children: [
1736
1929
  !state.minimized ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-panel", children: [
1737
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-header", children: [
1738
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-header-row", children: [
1739
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-header-copy", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-heading", children: state.assistantName }) }),
1740
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1741
- Button,
1742
- {
1743
- type: "button",
1744
- size: "icon-sm",
1745
- variant: "ghost",
1746
- "aria-label": "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u0438\u0434\u0436\u0435\u0442",
1747
- title: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u0438\u0434\u0436\u0435\u0442",
1748
- onClick: onCollapse,
1749
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapseIcon, {})
1750
- }
1751
- )
1930
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-header", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-header-row", children: [
1931
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantAvatar, { avatarUrl: state.avatarUrl, assistantName: state.assistantName }),
1932
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "blinq-header-copy", children: [
1933
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-heading", children: state.assistantName }),
1934
+ state.statusText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-status-line", children: state.statusText }) : null
1752
1935
  ] }),
1753
- state.statusText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-status-line", children: state.statusText }) : null
1754
- ] }),
1936
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1937
+ Button,
1938
+ {
1939
+ type: "button",
1940
+ size: "icon-sm",
1941
+ variant: "ghost",
1942
+ "aria-label": "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u0438\u0434\u0436\u0435\u0442",
1943
+ title: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u0438\u0434\u0436\u0435\u0442",
1944
+ onClick: onCollapse,
1945
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapseIcon, {})
1946
+ }
1947
+ )
1948
+ ] }) }),
1949
+ state.guide ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1950
+ GuideCard,
1951
+ {
1952
+ guide: state.guide,
1953
+ onStartGuide,
1954
+ onAdvanceGuide,
1955
+ onDismissGuide,
1956
+ onCompleteGuide,
1957
+ onRunGuideStep
1958
+ }
1959
+ ) : null,
1755
1960
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1756
1961
  AssistantConversationThread,
1757
1962
  {
@@ -1797,7 +2002,7 @@ function WidgetEmbedShell({
1797
2002
  Input,
1798
2003
  {
1799
2004
  value: state.inputValue,
1800
- placeholder: "\u041D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: \u043D\u0430\u0439\u0434\u0438 \u043D\u0443\u0436\u043D\u0443\u044E \u043A\u043D\u043E\u043F\u043A\u0443 \u0438\u043B\u0438 \u0437\u0430\u043F\u043E\u043B\u043D\u0438 \u0444\u043E\u0440\u043C\u0443",
2005
+ placeholder: "Type a message...",
1801
2006
  onChange: (event) => onInputChange(event.currentTarget.value),
1802
2007
  disabled: state.isSending
1803
2008
  }
@@ -1816,7 +2021,8 @@ function WidgetEmbedShell({
1816
2021
  )
1817
2022
  ] }) })
1818
2023
  }
1819
- )
2024
+ ),
2025
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "blinq-powered", children: "POWERED BY BLINQ" })
1820
2026
  ] }) : null,
1821
2027
  state.minimized ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1822
2028
  Button,
@@ -1827,7 +2033,7 @@ function WidgetEmbedShell({
1827
2033
  "aria-label": `\u041E\u0442\u043A\u0440\u044B\u0442\u044C ${state.assistantName}`,
1828
2034
  title: `\u041E\u0442\u043A\u0440\u044B\u0442\u044C ${state.assistantName}`,
1829
2035
  onClick: onOpen,
1830
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "blinq-launcher-badge", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LauncherIcon, {}) })
2036
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LauncherIcon, {})
1831
2037
  }
1832
2038
  ) : null
1833
2039
  ]
@@ -2237,6 +2443,41 @@ var SESSION_STORAGE_PREFIX = "blinq-widget-session";
2237
2443
  var MAX_STORED_HISTORY = 30;
2238
2444
  var MAX_HISTORY_FOR_REQUEST = 12;
2239
2445
  var DEFAULT_GREETING = "Blinq \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0435\u043D. \u0421\u043F\u0440\u043E\u0441\u0438\u0442\u0435 \u043F\u0440\u043E \u0442\u0435\u043A\u0443\u0449\u0443\u044E \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0443, \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0443 \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u044B \u0438\u043B\u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0448\u0430\u0433.";
2446
+ var PLAN_APPROVE_TEXTS = /* @__PURE__ */ new Set([
2447
+ "\u0434\u0430",
2448
+ "\u0430\u0433\u0430",
2449
+ "\u043E\u043A",
2450
+ "okay",
2451
+ "\u043E\u043A\u0435\u0439",
2452
+ "\u0445\u043E\u0440\u043E\u0448\u043E",
2453
+ "\u043B\u0430\u0434\u043D\u043E",
2454
+ "\u0434\u0435\u043B\u0430\u0439",
2455
+ "\u0441\u0434\u0435\u043B\u0430\u0439",
2456
+ "\u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044E",
2457
+ "yes",
2458
+ "ok",
2459
+ "sure",
2460
+ "go ahead",
2461
+ "approve",
2462
+ "\u0438\u04D9",
2463
+ "\u0438\u044F",
2464
+ "\u0438\u0441\u0442\u0435",
2465
+ "\u0436\u0430\u0440\u0430\u0439\u0434\u044B",
2466
+ "\u043C\u0430\u049B\u04B1\u043B"
2467
+ ]);
2468
+ var PLAN_DECLINE_TEXTS = /* @__PURE__ */ new Set([
2469
+ "\u043D\u0435\u0442",
2470
+ "\u043D\u0435 \u043D\u0430\u0434\u043E",
2471
+ "\u043D\u0435 \u043D\u0443\u0436\u043D\u043E",
2472
+ "\u043E\u0442\u043C\u0435\u043D\u0430",
2473
+ "\u043E\u0442\u043C\u0435\u043D\u0438",
2474
+ "cancel",
2475
+ "no",
2476
+ "stop",
2477
+ "\u0436\u043E\u049B",
2478
+ "\u0442\u043E\u049B\u0442\u0430",
2479
+ "\u043A\u0435\u0440\u0435\u043A \u0435\u043C\u0435\u0441"
2480
+ ]);
2240
2481
  function isBrowser3() {
2241
2482
  return typeof window !== "undefined" && typeof document !== "undefined";
2242
2483
  }
@@ -2270,9 +2511,9 @@ function getOrCreateFingerprint() {
2270
2511
  }
2271
2512
  function runtimeMessage(mode) {
2272
2513
  if (mode === "read-only-fallback") {
2273
- return "\u0413\u043E\u0442\u043E\u0432 \u043E\u0431\u044A\u044F\u0441\u043D\u0438\u0442\u044C \u0442\u0435\u043A\u0443\u0449\u0443\u044E \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0443 \u0438 \u043F\u043E\u0434\u0441\u043A\u0430\u0437\u0430\u0442\u044C \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0448\u0430\u0433.";
2514
+ return "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B. \u042F \u043C\u043E\u0433\u0443 \u043E\u0431\u044A\u044F\u0441\u043D\u044F\u0442\u044C \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438 \u043E\u0442\u0432\u0435\u0447\u0430\u0442\u044C \u043F\u043E \u0431\u0430\u0437\u0435 \u0437\u043D\u0430\u043D\u0438\u0439.";
2274
2515
  }
2275
- return "\u0413\u043E\u0442\u043E\u0432 \u043F\u043E\u043C\u043E\u0447\u044C \u0441 \u043E\u043D\u0431\u043E\u0440\u0434\u0438\u043D\u0433\u043E\u043C \u0438 \u0432\u043E\u043F\u0440\u043E\u0441\u0430\u043C\u0438 \u043F\u043E \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u0435.";
2516
+ return "\u0413\u043E\u0442\u043E\u0432 \u043F\u043E\u043C\u043E\u0433\u0430\u0442\u044C \u0441 \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043E\u043C, \u0437\u043D\u0430\u043D\u0438\u044F\u043C\u0438 \u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u043C\u0438 \u0448\u0430\u0433\u0430\u043C\u0438.";
2276
2517
  }
2277
2518
  function normalizedRouteFromUrl(value) {
2278
2519
  try {
@@ -2349,7 +2590,7 @@ var BlinqWidget = class {
2349
2590
  minimized = false;
2350
2591
  isSending = false;
2351
2592
  inputValue = "";
2352
- statusText = "\u041F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u043C \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u044B.";
2593
+ statusText = "";
2353
2594
  voiceSupported = false;
2354
2595
  voiceListening = false;
2355
2596
  voiceWaveform = [];
@@ -2359,6 +2600,7 @@ var BlinqWidget = class {
2359
2600
  confirmResolve = null;
2360
2601
  confirmItemId = null;
2361
2602
  activeRun = null;
2603
+ activeGuide = null;
2362
2604
  pendingAssistantIndicator = false;
2363
2605
  executedToolCounts = /* @__PURE__ */ new Map();
2364
2606
  lastAutoResumeKey = null;
@@ -2388,12 +2630,34 @@ var BlinqWidget = class {
2388
2630
  },
2389
2631
  onDeclinePlan: () => {
2390
2632
  void this.respondToPlan(false);
2633
+ },
2634
+ onStartGuide: () => {
2635
+ void this.startGuide();
2636
+ },
2637
+ onAdvanceGuide: () => {
2638
+ void this.advanceGuide();
2639
+ },
2640
+ onDismissGuide: () => {
2641
+ void this.dismissGuide();
2642
+ },
2643
+ onCompleteGuide: () => {
2644
+ void this.completeGuide();
2645
+ },
2646
+ onRunGuideStep: () => {
2647
+ void this.runGuideStep();
2391
2648
  }
2392
2649
  };
2393
2650
  constructor(options) {
2394
2651
  this.options = options;
2395
2652
  this.apiBaseUrl = options.apiBaseUrl ?? DEFAULT_API_BASE_URL;
2396
2653
  }
2654
+ currentActionPolicy() {
2655
+ return this.runtimeStatus?.action_policy ?? {
2656
+ actions_enabled: this.widgetConfig?.actions_enabled ?? true,
2657
+ action_mode: this.widgetConfig?.action_mode ?? "execute_with_confirmation",
2658
+ pointer_overlay_enabled: this.widgetConfig?.pointer_overlay_enabled ?? true
2659
+ };
2660
+ }
2397
2661
  async init() {
2398
2662
  await this.startSession();
2399
2663
  if (isBrowser3()) {
@@ -2403,8 +2667,10 @@ var BlinqWidget = class {
2403
2667
  this.render();
2404
2668
  this.setupVoiceInput();
2405
2669
  this.registry = new PageToolRegistry(this.confirmToolExecution.bind(this));
2670
+ this.registry.setActionPolicy(this.currentActionPolicy());
2406
2671
  const nativeRegistered = await this.registry.registerNativeTools();
2407
2672
  this.syncRuntimeStatus(nativeRegistered);
2673
+ this.syncGuideHighlight();
2408
2674
  if (this.shouldAutoResumeActiveRun()) {
2409
2675
  window.setTimeout(() => {
2410
2676
  void this.continueActiveRun();
@@ -2429,18 +2695,21 @@ var BlinqWidget = class {
2429
2695
  currentState() {
2430
2696
  return {
2431
2697
  minimized: this.minimized,
2432
- assistantName: this.widgetConfig?.ai_persona_name ?? "Blinq \u0410\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442",
2698
+ assistantName: this.widgetConfig?.name ?? "Blinq \u0410\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442",
2699
+ avatarUrl: this.widgetConfig?.avatar_url ?? null,
2433
2700
  runtimeLabel: "webmcp://embedded",
2434
2701
  statusText: this.statusText,
2435
2702
  showThinkingIndicator: this.pendingAssistantIndicator,
2436
2703
  inputValue: this.inputValue,
2437
- accentColor: "#111111",
2704
+ accentColor: this.widgetConfig?.theme_color ?? "#111111",
2705
+ themeVariant: "light",
2438
2706
  side: this.widgetConfig?.position === "bottom-left" ? "left" : "right",
2439
2707
  isSending: this.isSending,
2440
2708
  voiceSupported: this.voiceSupported,
2441
2709
  voiceListening: this.voiceListening,
2442
2710
  voiceWaveform: this.voiceWaveform,
2443
2711
  voiceDurationMs: this.voiceDurationMs,
2712
+ guide: this.activeGuide,
2444
2713
  items: this.items
2445
2714
  };
2446
2715
  }
@@ -2483,6 +2752,7 @@ var BlinqWidget = class {
2483
2752
  this.sessionToken = payload.session_token;
2484
2753
  this.widgetConfig = payload.widget_config;
2485
2754
  this.activeRun = payload.active_run ?? null;
2755
+ this.activeGuide = this.normalizeGuidePayload(payload.active_guide ?? payload.guide_offer ?? null);
2486
2756
  this.runtimeStatus = {
2487
2757
  ...payload.runtime,
2488
2758
  message: runtimeMessage(payload.runtime.mode)
@@ -2726,6 +2996,62 @@ var BlinqWidget = class {
2726
2996
  this.upsertPlanItem(this.activeRun);
2727
2997
  }
2728
2998
  }
2999
+ normalizeGuideStep(step) {
3000
+ return {
3001
+ id: step.id,
3002
+ position: step.position,
3003
+ title: step.title,
3004
+ body: step.body,
3005
+ targetSelector: step.target_selector ?? null,
3006
+ targetLabel: step.target_label ?? null,
3007
+ actionKind: step.action_kind ?? null,
3008
+ actionPayload: step.action_payload ?? null,
3009
+ expectedRoute: step.expected_route ?? null,
3010
+ completionMode: step.completion_mode
3011
+ };
3012
+ }
3013
+ normalizeGuidePayload(payload) {
3014
+ if (!payload) {
3015
+ return null;
3016
+ }
3017
+ const guide = payload.guide;
3018
+ return {
3019
+ id: guide.id,
3020
+ state: payload.state,
3021
+ source: guide.source,
3022
+ route: guide.route,
3023
+ summary: guide.summary ?? null,
3024
+ currentStepIndex: payload.state === "started" ? Math.min(payload.current_step_index, Math.max(guide.steps.length - 1, 0)) : payload.state === "completed" ? guide.steps.length : 0,
3025
+ totalSteps: guide.steps.length,
3026
+ steps: guide.steps.map((step) => this.normalizeGuideStep(step))
3027
+ };
3028
+ }
3029
+ setGuideState(payload, options) {
3030
+ const normalized = this.normalizeGuidePayload(payload);
3031
+ if (options?.clearIfFinished !== false && normalized && (normalized.state === "dismissed" || normalized.state === "completed")) {
3032
+ this.activeGuide = null;
3033
+ } else {
3034
+ this.activeGuide = normalized;
3035
+ }
3036
+ this.renderReactApp();
3037
+ this.syncGuideHighlight();
3038
+ }
3039
+ currentGuideStep() {
3040
+ if (!this.activeGuide || this.activeGuide.state !== "started") {
3041
+ return null;
3042
+ }
3043
+ return this.activeGuide.steps[Math.min(this.activeGuide.currentStepIndex, Math.max(this.activeGuide.steps.length - 1, 0))] ?? null;
3044
+ }
3045
+ syncGuideHighlight() {
3046
+ const step = this.currentGuideStep();
3047
+ if (!step?.targetSelector || !this.registry) {
3048
+ return;
3049
+ }
3050
+ this.registry.highlightTargets(
3051
+ [{ selector: step.targetSelector, label: step.targetLabel || step.title }],
3052
+ { interaction: step.actionKind ? "execute" : "explain", durationMs: 2100 }
3053
+ );
3054
+ }
2729
3055
  updateActionState(id, state) {
2730
3056
  this.items = this.items.map(
2731
3057
  (item) => item.type === "action" && item.id === id ? { ...item, state } : item
@@ -2739,8 +3065,24 @@ var BlinqWidget = class {
2739
3065
  const existingPlanItem = this.items.find(
2740
3066
  (item) => item.type === "plan" && item.id === this.planItemId(run.id)
2741
3067
  );
2742
- if (this.activeRun?.id && this.activeRun.id !== run.id) {
3068
+ const isNewActiveRun = Boolean(this.activeRun?.id && this.activeRun.id !== run.id);
3069
+ if (isNewActiveRun) {
2743
3070
  this.executedToolCounts.clear();
3071
+ this.items = this.items.map((item) => {
3072
+ if (item.type !== "plan" || item.id === this.planItemId(run.id)) {
3073
+ return item;
3074
+ }
3075
+ if (item.status === "completed" || item.status === "failed" || item.status === "abandoned") {
3076
+ return item;
3077
+ }
3078
+ return {
3079
+ ...item,
3080
+ status: "abandoned",
3081
+ approvalState: "declined",
3082
+ progressLabel: item.progressLabel ?? "\u041F\u043B\u0430\u043D \u0437\u0430\u043C\u0435\u043D\u0451\u043D \u043D\u043E\u0432\u044B\u043C \u0437\u0430\u043F\u0440\u043E\u0441\u043E\u043C.",
3083
+ statusReason: item.statusReason ?? "\u041F\u043B\u0430\u043D \u0437\u0430\u043C\u0435\u043D\u0451\u043D \u043D\u043E\u0432\u044B\u043C \u0437\u0430\u043F\u0440\u043E\u0441\u043E\u043C."
3084
+ };
3085
+ });
2744
3086
  }
2745
3087
  this.activeRun = {
2746
3088
  ...run,
@@ -2824,7 +3166,7 @@ var BlinqWidget = class {
2824
3166
  if (!this.runtimeStatus) {
2825
3167
  return;
2826
3168
  }
2827
- const mode = nativeRegistered ? "native-webmcp-active" : this.registry?.canExecuteWriteTools() ? "blinq-page-tools-active" : "read-only-fallback";
3169
+ const mode = nativeRegistered ? "native-webmcp-active" : this.registry ? "blinq-page-tools-active" : "read-only-fallback";
2828
3170
  this.runtimeStatus = {
2829
3171
  ...this.runtimeStatus,
2830
3172
  mode,
@@ -2838,6 +3180,124 @@ var BlinqWidget = class {
2838
3180
  this.statusText = text;
2839
3181
  this.renderReactApp();
2840
3182
  }
3183
+ async guideRequest(path, body) {
3184
+ if (!this.sessionToken) {
3185
+ throw new Error("\u0421\u0435\u0441\u0441\u0438\u044F \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0435\u0449\u0451 \u043D\u0435 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u0430");
3186
+ }
3187
+ const response = await fetch(`${this.apiBaseUrl}${path}`, {
3188
+ method: "POST",
3189
+ headers: {
3190
+ "Content-Type": "application/json",
3191
+ Authorization: `Bearer ${this.sessionToken}`
3192
+ },
3193
+ body: JSON.stringify(body)
3194
+ });
3195
+ if (!response.ok) {
3196
+ const payload = await response.json().catch(() => ({}));
3197
+ throw new Error(payload.detail ?? "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 guide");
3198
+ }
3199
+ return await response.json();
3200
+ }
3201
+ async startGuide() {
3202
+ if (!this.sessionId || !this.activeGuide) {
3203
+ return;
3204
+ }
3205
+ const payload = await this.guideRequest("/pub/guide/start", {
3206
+ session_id: this.sessionId,
3207
+ guide_id: this.activeGuide.source === "published" ? this.activeGuide.id : null
3208
+ });
3209
+ this.setGuideState(payload, { clearIfFinished: false });
3210
+ this.setStatus("Guide \u0437\u0430\u043F\u0443\u0449\u0435\u043D.");
3211
+ }
3212
+ async advanceGuide() {
3213
+ if (!this.sessionId) {
3214
+ return;
3215
+ }
3216
+ const payload = await this.guideRequest("/pub/guide/advance", {
3217
+ session_id: this.sessionId
3218
+ });
3219
+ this.setGuideState(payload);
3220
+ this.setStatus(payload.state === "completed" ? "Guide \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D." : "\u041F\u0435\u0440\u0435\u0445\u043E\u0434\u0438\u043C \u043A \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C\u0443 \u0448\u0430\u0433\u0443.");
3221
+ }
3222
+ async dismissGuide() {
3223
+ if (!this.sessionId) {
3224
+ return;
3225
+ }
3226
+ const payload = await this.guideRequest("/pub/guide/dismiss", {
3227
+ session_id: this.sessionId
3228
+ });
3229
+ this.setGuideState(payload);
3230
+ this.setStatus("Guide \u0441\u043A\u0440\u044B\u0442.");
3231
+ }
3232
+ async completeGuide() {
3233
+ if (!this.sessionId) {
3234
+ return;
3235
+ }
3236
+ const payload = await this.guideRequest("/pub/guide/complete", {
3237
+ session_id: this.sessionId
3238
+ });
3239
+ this.setGuideState(payload);
3240
+ this.setStatus("Guide \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D.");
3241
+ }
3242
+ async runGuideStep() {
3243
+ const step = this.currentGuideStep();
3244
+ if (!step || !this.registry) {
3245
+ return;
3246
+ }
3247
+ if (step.actionKind && step.actionPayload && this.currentActionPolicy().actions_enabled && this.currentActionPolicy().action_mode === "execute_with_confirmation") {
3248
+ const outcome = await this.registry.executeTool({
3249
+ tool_name: step.actionKind,
3250
+ display_name: step.title,
3251
+ target_summary: step.targetLabel || step.body,
3252
+ arguments: step.actionPayload
3253
+ });
3254
+ if (outcome.status === "success") {
3255
+ this.setStatus("\u0428\u0430\u0433 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435.");
3256
+ const deferredNavigationHref = outcome.result && typeof outcome.result.href === "string" && outcome.result.deferred_navigation ? outcome.result.href : null;
3257
+ await this.advanceGuide();
3258
+ if (deferredNavigationHref) {
3259
+ window.location.assign(deferredNavigationHref);
3260
+ }
3261
+ } else if (outcome.status === "cancelled") {
3262
+ this.setStatus("\u0412\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u0448\u0430\u0433\u0430 \u043E\u0442\u043C\u0435\u043D\u0435\u043D\u043E.");
3263
+ } else {
3264
+ await this.healGuideStep();
3265
+ }
3266
+ return;
3267
+ }
3268
+ if (step.targetSelector) {
3269
+ const highlighted = this.registry.highlightTargets(
3270
+ [{ selector: step.targetSelector, label: step.targetLabel || step.title }],
3271
+ { interaction: "explain", durationMs: 2200 }
3272
+ );
3273
+ if (highlighted) {
3274
+ this.setStatus("\u041F\u043E\u043A\u0430\u0437\u0430\u043B, \u043A\u0443\u0434\u0430 \u043D\u0430\u0436\u0430\u0442\u044C \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435.");
3275
+ } else {
3276
+ await this.healGuideStep();
3277
+ }
3278
+ }
3279
+ }
3280
+ async healGuideStep() {
3281
+ if (!this.sessionId || !this.activeGuide || !this.registry) {
3282
+ return;
3283
+ }
3284
+ this.setStatus("\u041A\u0430\u0436\u0435\u0442\u0441\u044F \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043F\u0435\u0440\u0435\u0435\u0445\u0430\u043B. \u0418\u0449\u0443 \u043D\u043E\u0432\u044B\u0435 \u0441\u043F\u043E\u0441\u043E\u0431\u044B \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u0418\u0418...");
3285
+ const pageContext = this.registry.collectPageContext();
3286
+ try {
3287
+ const payload = await this.guideRequest("/pub/guide/heal", {
3288
+ session_id: this.sessionId,
3289
+ step_index: this.activeGuide.currentStepIndex,
3290
+ page_context: pageContext
3291
+ });
3292
+ this.setGuideState(payload, { clearIfFinished: false });
3293
+ this.setStatus("\u0421\u0446\u0435\u043D\u0430\u0440\u0438\u0439 \u043F\u0435\u0440\u0435\u0441\u0442\u0440\u043E\u0435\u043D. \u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u044E...");
3294
+ window.setTimeout(() => {
3295
+ void this.runGuideStep();
3296
+ }, 1500);
3297
+ } catch (e) {
3298
+ this.setStatus("\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0435\u0440\u0435\u0441\u0442\u0440\u043E\u0438\u0442\u044C \u0448\u0430\u0433.");
3299
+ }
3300
+ }
2841
3301
  appendMessage(text, role, options) {
2842
3302
  const id = createConversationId("message");
2843
3303
  this.items = [
@@ -2898,6 +3358,19 @@ var BlinqWidget = class {
2898
3358
  currentRoute() {
2899
3359
  return normalizedRouteFromUrl(window.location.href);
2900
3360
  }
3361
+ normalizedUserPlanDecision(message) {
3362
+ const normalized = message.trim().toLowerCase();
3363
+ if (!normalized || !this.activeRun?.requires_approval) {
3364
+ return null;
3365
+ }
3366
+ if (PLAN_APPROVE_TEXTS.has(normalized)) {
3367
+ return true;
3368
+ }
3369
+ if (PLAN_DECLINE_TEXTS.has(normalized)) {
3370
+ return false;
3371
+ }
3372
+ return null;
3373
+ }
2901
3374
  shouldAutoResumeActiveRun() {
2902
3375
  if (!this.activeRun || this.activeRun.status !== "awaiting_navigation") {
2903
3376
  return false;
@@ -2996,7 +3469,13 @@ var BlinqWidget = class {
2996
3469
  }
2997
3470
  if (event === "highlight") {
2998
3471
  const highlight = JSON.parse(data);
2999
- this.registry?.highlightTargets(highlight.targets ?? []);
3472
+ this.registry?.highlightTargets(highlight.targets ?? [], { interaction: "explain" });
3473
+ }
3474
+ if (event === "guide") {
3475
+ this.hideThinkingIndicator();
3476
+ this.setGuideState(JSON.parse(data), {
3477
+ clearIfFinished: false
3478
+ });
3000
3479
  }
3001
3480
  if (event === "delta" && payload.text) {
3002
3481
  const normalizedChunk = normalizeAssistantStreamChunk(finalText, payload.text);
@@ -3078,6 +3557,18 @@ var BlinqWidget = class {
3078
3557
  let responseMessageId = null;
3079
3558
  try {
3080
3559
  this.appendMessage(message, "user");
3560
+ const directPlanDecision = this.normalizedUserPlanDecision(message);
3561
+ if (directPlanDecision !== null) {
3562
+ const finalText2 = await this.respondToPlan(directPlanDecision, {
3563
+ appendAssistantMessage: false,
3564
+ manageSendingState: false
3565
+ });
3566
+ if (finalText2.trim()) {
3567
+ this.finalizeAssistantMessage(finalText2, { persist: false });
3568
+ this.rememberMessage({ role: "assistant", text: finalText2 });
3569
+ }
3570
+ return finalText2;
3571
+ }
3081
3572
  const finalText = await this.streamChatStep(
3082
3573
  "/pub/chat",
3083
3574
  {
@@ -3138,16 +3629,19 @@ var BlinqWidget = class {
3138
3629
  this.renderReactApp();
3139
3630
  }
3140
3631
  }
3141
- async respondToPlan(approved) {
3632
+ async respondToPlan(approved, options) {
3142
3633
  if (!this.sessionId || !this.sessionToken || !this.activeRun) {
3143
- return;
3634
+ return "";
3144
3635
  }
3145
- if (this.isSending) {
3146
- return;
3636
+ const manageSendingState = options?.manageSendingState ?? true;
3637
+ if (manageSendingState && this.isSending) {
3638
+ return "";
3639
+ }
3640
+ if (manageSendingState) {
3641
+ this.isSending = true;
3642
+ this.showThinkingIndicator();
3643
+ this.renderReactApp();
3147
3644
  }
3148
- this.isSending = true;
3149
- this.showThinkingIndicator();
3150
- this.renderReactApp();
3151
3645
  try {
3152
3646
  const finalText = await this.streamChatStep(
3153
3647
  "/pub/plan/approve",
@@ -3159,14 +3653,17 @@ var BlinqWidget = class {
3159
3653
  },
3160
3654
  null
3161
3655
  );
3162
- if (finalText.trim()) {
3656
+ if (options?.appendAssistantMessage !== false && finalText.trim()) {
3163
3657
  this.finalizeAssistantMessage(finalText, { persist: false });
3164
3658
  this.rememberMessage({ role: "assistant", text: finalText });
3165
3659
  }
3660
+ return finalText;
3166
3661
  } finally {
3167
- this.hideThinkingIndicator();
3168
- this.isSending = false;
3169
- this.renderReactApp();
3662
+ if (manageSendingState) {
3663
+ this.hideThinkingIndicator();
3664
+ this.isSending = false;
3665
+ this.renderReactApp();
3666
+ }
3170
3667
  }
3171
3668
  }
3172
3669
  async endSession() {
@@ -3197,10 +3694,1257 @@ async function initFromConfig(config) {
3197
3694
  async function createBlinqWidget(options) {
3198
3695
  return init(options);
3199
3696
  }
3697
+
3698
+ // src/embed-styles.ts
3699
+ var EMBED_WIDGET_STYLES = `
3700
+ :host {
3701
+ all: initial;
3702
+ display: block;
3703
+ position: static;
3704
+ color-scheme: light;
3705
+ }
3706
+
3707
+ *, *::before, *::after {
3708
+ box-sizing: border-box;
3709
+ }
3710
+
3711
+ button,
3712
+ input {
3713
+ font: inherit;
3714
+ }
3715
+
3716
+ .blinq-shell {
3717
+ position: fixed;
3718
+ bottom: 24px;
3719
+ z-index: 2147483647;
3720
+ display: flex;
3721
+ flex-direction: column;
3722
+ gap: 12px;
3723
+ width: 432px;
3724
+ max-width: calc(100vw - 24px);
3725
+ pointer-events: none;
3726
+ font-family:
3727
+ "SF Pro Display",
3728
+ "SF Pro Text",
3729
+ "Inter",
3730
+ ui-sans-serif,
3731
+ system-ui,
3732
+ -apple-system,
3733
+ BlinkMacSystemFont,
3734
+ "Segoe UI",
3735
+ sans-serif;
3736
+ --blinq-accent: #111111;
3737
+ --blinq-text: rgba(18, 18, 20, 0.96);
3738
+ --blinq-text-soft: rgba(32, 34, 38, 0.82);
3739
+ --blinq-text-muted: rgba(56, 60, 66, 0.58);
3740
+ --blinq-glass-fill: linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(240, 243, 248, 0.52));
3741
+ --blinq-glass-fill-strong: linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(245, 247, 250, 0.62));
3742
+ --blinq-glass-fill-dense: linear-gradient(180deg, rgba(249, 250, 252, 0.92), rgba(231, 235, 241, 0.66));
3743
+ --blinq-glass-stroke: rgba(255, 255, 255, 0.68);
3744
+ --blinq-glass-stroke-soft: rgba(255, 255, 255, 0.5);
3745
+ --blinq-glass-edge: rgba(100, 109, 123, 0.14);
3746
+ --blinq-shadow:
3747
+ 0 28px 80px rgba(155, 164, 180, 0.22),
3748
+ 0 10px 30px rgba(174, 182, 193, 0.18);
3749
+ --blinq-shadow-soft:
3750
+ 0 14px 40px rgba(170, 177, 189, 0.18),
3751
+ 0 4px 14px rgba(202, 208, 216, 0.18);
3752
+ --blinq-inner-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.92);
3753
+ --blinq-blur: blur(28px) saturate(170%);
3754
+ --blinq-radius-panel: 32px;
3755
+ --blinq-radius-pill: 999px;
3756
+ --blinq-radius-bubble: 28px;
3757
+ --blinq-radius-card: 30px;
3758
+ }
3759
+
3760
+ .blinq-shell[data-side="left"] {
3761
+ left: 24px;
3762
+ align-items: flex-start;
3763
+ }
3764
+
3765
+ .blinq-shell[data-side="right"] {
3766
+ right: 24px;
3767
+ align-items: flex-end;
3768
+ }
3769
+
3770
+ .blinq-panel,
3771
+ .blinq-launcher {
3772
+ pointer-events: auto;
3773
+ }
3774
+
3775
+ .blinq-shell {
3776
+ width: 520px;
3777
+ }
3778
+
3779
+ .blinq-panel {
3780
+ position: relative;
3781
+ width: 100%;
3782
+ max-width: 432px;
3783
+ overflow: hidden;
3784
+ border-radius: var(--blinq-radius-panel);
3785
+ border: 1px solid var(--blinq-glass-stroke);
3786
+ background: var(--blinq-glass-fill);
3787
+ box-shadow: var(--blinq-shadow);
3788
+ backdrop-filter: var(--blinq-blur);
3789
+ -webkit-backdrop-filter: var(--blinq-blur);
3790
+ }
3791
+
3792
+ .blinq-panel::before,
3793
+ .blinq-launcher::before {
3794
+ content: "";
3795
+ position: absolute;
3796
+ inset: 0;
3797
+ pointer-events: none;
3798
+ border-radius: inherit;
3799
+ box-shadow: var(--blinq-inner-highlight);
3800
+ }
3801
+
3802
+ .blinq-launcher::after {
3803
+ content: "";
3804
+ position: absolute;
3805
+ inset: 1px;
3806
+ pointer-events: none;
3807
+ border-radius: inherit;
3808
+ background:
3809
+ radial-gradient(circle at 28% 22%, rgba(255, 255, 255, 0.82), transparent 32%),
3810
+ linear-gradient(135deg, rgba(255, 255, 255, 0.46), transparent 55%);
3811
+ opacity: 0.88;
3812
+ transition:
3813
+ opacity 180ms ease;
3814
+ }
3815
+
3816
+ .blinq-panel::after {
3817
+ content: "";
3818
+ position: absolute;
3819
+ inset: 0;
3820
+ pointer-events: none;
3821
+ border-radius: inherit;
3822
+ background:
3823
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.72), transparent 34%),
3824
+ radial-gradient(circle at bottom center, rgba(255, 255, 255, 0.26), transparent 38%);
3825
+ opacity: 0.95;
3826
+ }
3827
+
3828
+ .blinq-header,
3829
+ .blinq-thread,
3830
+ .blinq-composer {
3831
+ position: relative;
3832
+ z-index: 1;
3833
+ }
3834
+
3835
+ .blinq-header {
3836
+ display: flex;
3837
+ flex-direction: column;
3838
+ gap: 12px;
3839
+ padding: 18px 18px 10px;
3840
+ }
3841
+
3842
+ .blinq-header-row {
3843
+ display: flex;
3844
+ align-items: flex-start;
3845
+ justify-content: space-between;
3846
+ gap: 12px;
3847
+ }
3848
+
3849
+ .blinq-header-copy {
3850
+ display: flex;
3851
+ flex-direction: column;
3852
+ gap: 8px;
3853
+ min-width: 0;
3854
+ flex: 1;
3855
+ }
3856
+
3857
+ .blinq-heading {
3858
+ font-size: 17px;
3859
+ line-height: 1.15;
3860
+ font-weight: 600;
3861
+ letter-spacing: -0.03em;
3862
+ color: var(--blinq-text);
3863
+ }
3864
+
3865
+ .blinq-status-line {
3866
+ display: inline-flex;
3867
+ align-items: center;
3868
+ gap: 8px;
3869
+ max-width: fit-content;
3870
+ min-height: 32px;
3871
+ padding: 0 12px;
3872
+ border-radius: var(--blinq-radius-pill);
3873
+ border: 1px solid var(--blinq-glass-stroke-soft);
3874
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(242, 244, 248, 0.46));
3875
+ color: var(--blinq-text-soft);
3876
+ font-size: 12px;
3877
+ line-height: 1.35;
3878
+ box-shadow: var(--blinq-shadow-soft);
3879
+ backdrop-filter: blur(22px) saturate(170%);
3880
+ -webkit-backdrop-filter: blur(22px) saturate(170%);
3881
+ }
3882
+
3883
+ .blinq-status-line::before {
3884
+ content: "";
3885
+ width: 7px;
3886
+ height: 7px;
3887
+ border-radius: 999px;
3888
+ background: rgba(17, 17, 17, 0.74);
3889
+ box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.34);
3890
+ flex: none;
3891
+ }
3892
+
3893
+ .blinq-launcher {
3894
+ position: relative;
3895
+ display: inline-flex;
3896
+ align-items: center;
3897
+ justify-content: center;
3898
+ width: 76px;
3899
+ min-width: 76px;
3900
+ height: 76px;
3901
+ padding: 0;
3902
+ border-radius: 999px;
3903
+ border: 1px solid var(--blinq-glass-stroke);
3904
+ background: var(--blinq-glass-fill-strong);
3905
+ box-shadow: var(--blinq-shadow-soft);
3906
+ backdrop-filter: blur(26px) saturate(175%);
3907
+ -webkit-backdrop-filter: blur(26px) saturate(175%);
3908
+ color: var(--blinq-text);
3909
+ isolation: isolate;
3910
+ }
3911
+
3912
+ .blinq-launcher:hover {
3913
+ border-color: var(--blinq-glass-stroke);
3914
+ box-shadow: var(--blinq-shadow-soft);
3915
+ }
3916
+
3917
+ .blinq-launcher-icon-only {
3918
+ border-radius: 999px;
3919
+ }
3920
+
3921
+ .blinq-launcher-icon {
3922
+ position: relative;
3923
+ z-index: 1;
3924
+ width: 30px;
3925
+ height: 30px;
3926
+ color: rgba(17, 17, 17, 0.96);
3927
+ opacity: 1;
3928
+ filter:
3929
+ drop-shadow(0 1px 0 rgba(255, 255, 255, 0.66))
3930
+ drop-shadow(0 2px 6px rgba(17, 17, 17, 0.08));
3931
+ }
3932
+
3933
+ .blinq-thread {
3934
+ min-height: 0;
3935
+ }
3936
+
3937
+ .blinq-thread-viewport {
3938
+ width: 100%;
3939
+ }
3940
+
3941
+ .blinq-scroll {
3942
+ display: flex;
3943
+ flex-direction: column;
3944
+ gap: 12px;
3945
+ min-height: 0;
3946
+ max-height: 432px;
3947
+ padding: 6px 18px 14px;
3948
+ overflow-y: auto;
3949
+ }
3950
+
3951
+ .blinq-scroll::-webkit-scrollbar {
3952
+ width: 8px;
3953
+ }
3954
+
3955
+ .blinq-scroll::-webkit-scrollbar-thumb {
3956
+ background: rgba(144, 151, 162, 0.22);
3957
+ border-radius: 999px;
3958
+ }
3959
+
3960
+ .blinq-message {
3961
+ position: relative;
3962
+ max-width: 88%;
3963
+ padding: 14px 16px;
3964
+ border-radius: var(--blinq-radius-bubble);
3965
+ border: 1px solid var(--blinq-glass-stroke-soft);
3966
+ background: var(--blinq-glass-fill-strong);
3967
+ color: var(--blinq-text);
3968
+ font-size: 14px;
3969
+ line-height: 1.55;
3970
+ white-space: pre-wrap;
3971
+ box-shadow: var(--blinq-shadow-soft);
3972
+ backdrop-filter: blur(24px) saturate(170%);
3973
+ -webkit-backdrop-filter: blur(24px) saturate(170%);
3974
+ }
3975
+
3976
+ .blinq-message::before {
3977
+ content: "";
3978
+ position: absolute;
3979
+ inset: 0;
3980
+ border-radius: inherit;
3981
+ pointer-events: none;
3982
+ box-shadow: var(--blinq-inner-highlight);
3983
+ }
3984
+
3985
+ .blinq-message[data-role="assistant"] {
3986
+ align-self: flex-start;
3987
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(241, 244, 249, 0.58));
3988
+ }
3989
+
3990
+ .blinq-message[data-role="user"] {
3991
+ align-self: flex-end;
3992
+ background: linear-gradient(180deg, rgba(249, 250, 252, 0.94), rgba(227, 232, 238, 0.66));
3993
+ border-color: rgba(255, 255, 255, 0.74);
3994
+ }
3995
+
3996
+ .blinq-message[data-kind="artifact"] {
3997
+ width: 100%;
3998
+ max-width: 100%;
3999
+ padding: 0;
4000
+ border: 0;
4001
+ background: transparent;
4002
+ box-shadow: none;
4003
+ backdrop-filter: none;
4004
+ -webkit-backdrop-filter: none;
4005
+ }
4006
+
4007
+ .blinq-message[data-kind="artifact"]::before {
4008
+ display: none;
4009
+ }
4010
+
4011
+ .blinq-message-copy {
4012
+ display: block;
4013
+ }
4014
+
4015
+ .blinq-message-copy-reveal {
4016
+ animation: blinq-copy-reveal 240ms cubic-bezier(0.16, 1, 0.3, 1);
4017
+ will-change: opacity, transform;
4018
+ }
4019
+
4020
+ .blinq-thinking-card {
4021
+ max-width: fit-content;
4022
+ padding-right: 18px;
4023
+ }
4024
+
4025
+ .blinq-thinking {
4026
+ display: inline-flex;
4027
+ align-items: center;
4028
+ gap: 10px;
4029
+ color: var(--blinq-text-soft);
4030
+ font-size: 13px;
4031
+ }
4032
+
4033
+ .blinq-thinking-dots {
4034
+ display: inline-flex;
4035
+ align-items: center;
4036
+ gap: 4px;
4037
+ }
4038
+
4039
+ .blinq-thinking-dots > span {
4040
+ width: 6px;
4041
+ height: 6px;
4042
+ border-radius: 999px;
4043
+ background: rgba(17, 17, 17, 0.74);
4044
+ animation: blinq-thinking-pulse 1.2s ease-in-out infinite;
4045
+ }
4046
+
4047
+ .blinq-thinking-dots > span:nth-child(2) {
4048
+ animation-delay: 100ms;
4049
+ }
4050
+
4051
+ .blinq-thinking-dots > span:nth-child(3) {
4052
+ animation-delay: 200ms;
4053
+ }
4054
+
4055
+ .blinq-card {
4056
+ display: flex;
4057
+ flex-direction: column;
4058
+ gap: 12px;
4059
+ border-radius: var(--blinq-radius-card);
4060
+ border: 1px solid var(--blinq-glass-stroke-soft);
4061
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(240, 243, 248, 0.52));
4062
+ color: var(--blinq-text);
4063
+ box-shadow: var(--blinq-shadow-soft);
4064
+ backdrop-filter: blur(26px) saturate(170%);
4065
+ -webkit-backdrop-filter: blur(26px) saturate(170%);
4066
+ }
4067
+
4068
+ .blinq-card-header {
4069
+ display: flex;
4070
+ flex-direction: column;
4071
+ gap: 8px;
4072
+ padding: 16px 16px 0;
4073
+ }
4074
+
4075
+ .blinq-card-title {
4076
+ font-size: 15px;
4077
+ line-height: 1.2;
4078
+ font-weight: 600;
4079
+ letter-spacing: -0.02em;
4080
+ color: var(--blinq-text);
4081
+ }
4082
+
4083
+ .blinq-card-description {
4084
+ font-size: 13px;
4085
+ line-height: 1.45;
4086
+ color: var(--blinq-text-muted);
4087
+ }
4088
+
4089
+ .blinq-card-content {
4090
+ padding: 0 16px 16px;
4091
+ }
4092
+
4093
+ .blinq-action-card,
4094
+ .blinq-plan-card,
4095
+ .blinq-guide-card {
4096
+ align-self: stretch;
4097
+ }
4098
+
4099
+ .blinq-guide-content {
4100
+ display: flex;
4101
+ flex-direction: column;
4102
+ gap: 12px;
4103
+ }
4104
+
4105
+ .blinq-guide-step-shell {
4106
+ display: flex;
4107
+ flex-direction: column;
4108
+ gap: 8px;
4109
+ padding: 14px;
4110
+ border-radius: 22px;
4111
+ border: 1px solid rgba(255, 255, 255, 0.64);
4112
+ background:
4113
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.8), transparent 42%),
4114
+ linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(242, 245, 249, 0.56));
4115
+ box-shadow:
4116
+ inset 0 1px 0 rgba(255, 255, 255, 0.94),
4117
+ 0 10px 22px rgba(183, 191, 201, 0.13);
4118
+ }
4119
+
4120
+ .blinq-guide-step-meta {
4121
+ font-size: 11px;
4122
+ font-weight: 600;
4123
+ letter-spacing: 0.08em;
4124
+ text-transform: uppercase;
4125
+ color: var(--blinq-text-soft);
4126
+ }
4127
+
4128
+ .blinq-guide-step-title {
4129
+ font-size: 14px;
4130
+ line-height: 1.35;
4131
+ font-weight: 600;
4132
+ color: var(--blinq-text);
4133
+ }
4134
+
4135
+ .blinq-guide-step-copy {
4136
+ font-size: 13px;
4137
+ line-height: 1.5;
4138
+ color: var(--blinq-text-muted);
4139
+ }
4140
+
4141
+ .blinq-plan-step {
4142
+ display: flex;
4143
+ align-items: flex-start;
4144
+ gap: 12px;
4145
+ padding: 12px 13px;
4146
+ margin-top: 10px;
4147
+ border-radius: 24px;
4148
+ border: 1px solid rgba(255, 255, 255, 0.62);
4149
+ background:
4150
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.72), transparent 38%),
4151
+ linear-gradient(180deg, rgba(255, 255, 255, 0.76), rgba(238, 242, 247, 0.54));
4152
+ box-shadow:
4153
+ inset 0 1px 0 rgba(255, 255, 255, 0.94),
4154
+ 0 8px 20px rgba(189, 196, 206, 0.12);
4155
+ }
4156
+
4157
+ .blinq-plan-step:first-child {
4158
+ margin-top: 0;
4159
+ }
4160
+
4161
+ .blinq-plan-step-index {
4162
+ display: inline-flex;
4163
+ align-items: center;
4164
+ justify-content: center;
4165
+ width: 26px;
4166
+ height: 26px;
4167
+ border-radius: 999px;
4168
+ border: 1px solid rgba(255, 255, 255, 0.7);
4169
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(240, 243, 247, 0.62));
4170
+ color: rgba(17, 17, 17, 0.82);
4171
+ font-size: 11px;
4172
+ font-weight: 700;
4173
+ flex: none;
4174
+ }
4175
+
4176
+ .blinq-plan-step-copy {
4177
+ min-width: 0;
4178
+ display: flex;
4179
+ flex-direction: column;
4180
+ gap: 6px;
4181
+ color: var(--blinq-text);
4182
+ font-size: 13px;
4183
+ flex: 1;
4184
+ }
4185
+
4186
+ .blinq-plan-header {
4187
+ display: flex;
4188
+ align-items: flex-start;
4189
+ justify-content: space-between;
4190
+ gap: 12px;
4191
+ }
4192
+
4193
+ .blinq-plan-content {
4194
+ display: flex;
4195
+ flex-direction: column;
4196
+ gap: 12px;
4197
+ }
4198
+
4199
+ .blinq-plan-steps {
4200
+ display: flex;
4201
+ flex-direction: column;
4202
+ gap: 0;
4203
+ }
4204
+
4205
+ .blinq-plan-step-title-row {
4206
+ display: flex;
4207
+ align-items: flex-start;
4208
+ justify-content: space-between;
4209
+ gap: 10px;
4210
+ }
4211
+
4212
+ .blinq-plan-step-title {
4213
+ min-width: 0;
4214
+ font-size: 13px;
4215
+ line-height: 1.4;
4216
+ font-weight: 600;
4217
+ letter-spacing: -0.01em;
4218
+ }
4219
+
4220
+ .blinq-plan-step-status-pill {
4221
+ display: inline-flex;
4222
+ align-items: center;
4223
+ justify-content: center;
4224
+ min-height: 24px;
4225
+ padding: 0 10px;
4226
+ border-radius: 999px;
4227
+ border: 1px solid rgba(255, 255, 255, 0.58);
4228
+ background: rgba(255, 255, 255, 0.58);
4229
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.88);
4230
+ color: var(--blinq-text-soft);
4231
+ font-size: 11px;
4232
+ font-weight: 600;
4233
+ line-height: 1;
4234
+ letter-spacing: 0.01em;
4235
+ white-space: nowrap;
4236
+ }
4237
+
4238
+ .blinq-plan-step-meta {
4239
+ font-size: 12px;
4240
+ color: var(--blinq-text-muted);
4241
+ }
4242
+
4243
+ .blinq-plan-step[data-current="true"] {
4244
+ background:
4245
+ radial-gradient(circle at top left, rgba(255, 255, 255, 0.82), transparent 40%),
4246
+ linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(243, 246, 250, 0.64));
4247
+ border-color: rgba(255, 255, 255, 0.74);
4248
+ box-shadow:
4249
+ inset 0 1px 0 rgba(255, 255, 255, 0.96),
4250
+ 0 12px 26px rgba(183, 191, 201, 0.15);
4251
+ }
4252
+
4253
+ .blinq-plan-step[data-current="true"] .blinq-plan-step-index {
4254
+ box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.48);
4255
+ }
4256
+
4257
+ .blinq-plan-step[data-current="true"] .blinq-plan-step-status-pill {
4258
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(240, 243, 247, 0.66));
4259
+ color: var(--blinq-text);
4260
+ }
4261
+
4262
+ .blinq-plan-step[data-status="completed"] .blinq-plan-step-index {
4263
+ background: rgba(227, 232, 237, 0.88);
4264
+ }
4265
+
4266
+ .blinq-plan-step[data-status="completed"] .blinq-plan-step-status-pill {
4267
+ background: rgba(244, 246, 249, 0.78);
4268
+ }
4269
+
4270
+ .blinq-plan-step[data-status="failed"],
4271
+ .blinq-plan-step[data-status="cancelled"] {
4272
+ opacity: 0.72;
4273
+ }
4274
+
4275
+ .blinq-action-meta-row {
4276
+ display: flex;
4277
+ align-items: center;
4278
+ justify-content: space-between;
4279
+ gap: 8px;
4280
+ flex-wrap: wrap;
4281
+ }
4282
+
4283
+ .blinq-action-details {
4284
+ margin-top: 8px;
4285
+ }
4286
+
4287
+ .blinq-action-details > summary {
4288
+ display: inline-flex;
4289
+ align-items: center;
4290
+ min-height: 34px;
4291
+ padding: 0 12px;
4292
+ border-radius: 999px;
4293
+ border: 1px solid rgba(255, 255, 255, 0.56);
4294
+ background: rgba(255, 255, 255, 0.46);
4295
+ color: var(--blinq-text-soft);
4296
+ font-size: 12px;
4297
+ font-weight: 600;
4298
+ list-style: none;
4299
+ cursor: pointer;
4300
+ }
4301
+
4302
+ .blinq-action-details > summary::-webkit-details-marker {
4303
+ display: none;
4304
+ }
4305
+
4306
+ .blinq-code {
4307
+ margin-top: 10px;
4308
+ padding: 12px 14px;
4309
+ border-radius: 20px;
4310
+ border: 1px solid rgba(255, 255, 255, 0.56);
4311
+ background: rgba(255, 255, 255, 0.52);
4312
+ color: var(--blinq-text-soft);
4313
+ font-size: 12px;
4314
+ line-height: 1.5;
4315
+ white-space: pre-wrap;
4316
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
4317
+ }
4318
+
4319
+ .blinq-action-state {
4320
+ margin-top: 12px;
4321
+ font-size: 12px;
4322
+ line-height: 1.4;
4323
+ color: var(--blinq-text-muted);
4324
+ }
4325
+
4326
+ .blinq-action-state[data-state="approved"] {
4327
+ color: var(--blinq-text-soft);
4328
+ }
4329
+
4330
+ .blinq-action-state[data-state="declined"] {
4331
+ color: var(--blinq-text-muted);
4332
+ }
4333
+
4334
+ .blinq-actions {
4335
+ display: flex;
4336
+ gap: 10px;
4337
+ margin-top: 14px;
4338
+ }
4339
+
4340
+ .blinq-actions > * {
4341
+ flex: 1;
4342
+ }
4343
+
4344
+ .blinq-badge-pill {
4345
+ display: inline-flex;
4346
+ align-items: center;
4347
+ justify-content: center;
4348
+ min-height: 30px;
4349
+ padding: 0 12px;
4350
+ border-radius: 999px;
4351
+ border: 1px solid rgba(255, 255, 255, 0.54);
4352
+ background: rgba(255, 255, 255, 0.46);
4353
+ font-size: 11px;
4354
+ font-weight: 600;
4355
+ letter-spacing: 0.02em;
4356
+ color: var(--blinq-text-soft);
4357
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.82);
4358
+ }
4359
+
4360
+ .blinq-badge-pill-default {
4361
+ background: rgba(255, 255, 255, 0.5);
4362
+ }
4363
+
4364
+ .blinq-badge-pill-outline {
4365
+ background: rgba(247, 248, 250, 0.34);
4366
+ color: var(--blinq-text-muted);
4367
+ }
4368
+
4369
+ .blinq-badge-pill-soft {
4370
+ background: rgba(255, 255, 255, 0.68);
4371
+ color: var(--blinq-text-soft);
4372
+ }
4373
+
4374
+ .blinq-badge-pill-accent {
4375
+ background: rgba(243, 245, 249, 0.84);
4376
+ color: var(--blinq-text);
4377
+ }
4378
+
4379
+ .blinq-composer {
4380
+ padding: 8px 18px 18px;
4381
+ }
4382
+
4383
+ .blinq-composer-controls {
4384
+ display: flex;
4385
+ }
4386
+
4387
+ .blinq-input-shell {
4388
+ position: relative;
4389
+ width: 100%;
4390
+ }
4391
+
4392
+ .blinq-input,
4393
+ .blinq-recording-input {
4394
+ width: 100%;
4395
+ min-width: 0;
4396
+ height: 58px;
4397
+ padding: 0 54px 0 54px;
4398
+ border-radius: 999px;
4399
+ border: 1px solid var(--blinq-glass-stroke);
4400
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(239, 242, 247, 0.54));
4401
+ color: var(--blinq-text);
4402
+ box-shadow:
4403
+ var(--blinq-inner-highlight),
4404
+ 0 10px 26px rgba(183, 189, 198, 0.16);
4405
+ font-size: 13px;
4406
+ outline: none;
4407
+ backdrop-filter: blur(22px) saturate(170%);
4408
+ -webkit-backdrop-filter: blur(22px) saturate(170%);
4409
+ }
4410
+
4411
+ .blinq-input::placeholder {
4412
+ color: var(--blinq-text-muted);
4413
+ }
4414
+
4415
+ .blinq-recording-input {
4416
+ display: flex;
4417
+ align-items: center;
4418
+ gap: 12px;
4419
+ }
4420
+
4421
+ .blinq-recording-time {
4422
+ flex: none;
4423
+ min-width: 42px;
4424
+ font-size: 12px;
4425
+ font-weight: 600;
4426
+ letter-spacing: 0.04em;
4427
+ color: var(--blinq-text-soft);
4428
+ font-variant-numeric: tabular-nums;
4429
+ }
4430
+
4431
+ .blinq-recording-wave-shell {
4432
+ position: relative;
4433
+ display: flex;
4434
+ align-items: center;
4435
+ flex: 1 1 auto;
4436
+ min-width: 0;
4437
+ height: 30px;
4438
+ padding: 0 10px;
4439
+ border-radius: 999px;
4440
+ border: 1px solid rgba(255, 255, 255, 0.54);
4441
+ background:
4442
+ linear-gradient(180deg, rgba(255, 255, 255, 0.54), rgba(242, 245, 248, 0.34));
4443
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.84);
4444
+ overflow: hidden;
4445
+ }
4446
+
4447
+ .blinq-recording-wave-shell::before {
4448
+ content: "";
4449
+ position: absolute;
4450
+ left: 10px;
4451
+ right: 10px;
4452
+ top: 50%;
4453
+ height: 1px;
4454
+ border-radius: 999px;
4455
+ background: linear-gradient(90deg, transparent, rgba(17, 17, 17, 0.12), transparent);
4456
+ transform: translateY(-50%);
4457
+ pointer-events: none;
4458
+ }
4459
+
4460
+ .blinq-recording-waveform {
4461
+ position: relative;
4462
+ display: flex;
4463
+ align-items: center;
4464
+ gap: 4px;
4465
+ flex: 1;
4466
+ min-width: 0;
4467
+ height: 100%;
4468
+ overflow: hidden;
4469
+ }
4470
+
4471
+ .blinq-recording-waveform-bar {
4472
+ width: 4px;
4473
+ min-width: 4px;
4474
+ height: 62%;
4475
+ border-radius: 999px;
4476
+ background: linear-gradient(180deg, rgba(17, 17, 17, 0.14), rgba(17, 17, 17, 0.36));
4477
+ transform-origin: center;
4478
+ transition:
4479
+ transform 120ms ease,
4480
+ opacity 160ms ease;
4481
+ opacity: 0.92;
4482
+ box-shadow:
4483
+ 0 0 0 1px rgba(255, 255, 255, 0.26),
4484
+ 0 2px 8px rgba(17, 17, 17, 0.08);
4485
+ }
4486
+
4487
+ .blinq-button {
4488
+ display: inline-flex;
4489
+ align-items: center;
4490
+ justify-content: center;
4491
+ gap: 8px;
4492
+ border: 1px solid transparent;
4493
+ border-radius: 999px;
4494
+ color: var(--blinq-text);
4495
+ font-size: 14px;
4496
+ font-weight: 600;
4497
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(236, 239, 244, 0.5));
4498
+ box-shadow: var(--blinq-shadow-soft);
4499
+ backdrop-filter: blur(20px) saturate(170%);
4500
+ -webkit-backdrop-filter: blur(20px) saturate(170%);
4501
+ transition:
4502
+ transform 160ms ease,
4503
+ box-shadow 180ms ease,
4504
+ border-color 180ms ease,
4505
+ background 180ms ease,
4506
+ opacity 120ms ease;
4507
+ cursor: pointer;
4508
+ outline: none;
4509
+ }
4510
+
4511
+ .blinq-button:hover:not(:disabled) {
4512
+ transform: translateY(-1px);
4513
+ border-color: rgba(255, 255, 255, 0.82);
4514
+ box-shadow:
4515
+ 0 14px 28px rgba(175, 181, 191, 0.22),
4516
+ 0 4px 10px rgba(189, 195, 204, 0.16);
4517
+ }
4518
+
4519
+ .blinq-input-mic:hover:not(:disabled),
4520
+ .blinq-input-send:hover:not(:disabled) {
4521
+ transform: translateY(-50%);
4522
+ border-color: rgba(255, 255, 255, 0.82);
4523
+ box-shadow:
4524
+ 0 14px 28px rgba(175, 181, 191, 0.16),
4525
+ 0 4px 10px rgba(189, 195, 204, 0.12);
4526
+ }
4527
+
4528
+ .blinq-button:disabled {
4529
+ opacity: 0.52;
4530
+ cursor: not-allowed;
4531
+ }
4532
+
4533
+ .blinq-button:focus-visible,
4534
+ .blinq-input:focus-visible {
4535
+ box-shadow:
4536
+ 0 0 0 3px rgba(255, 255, 255, 0.68),
4537
+ 0 0 0 6px rgba(17, 17, 17, 0.08);
4538
+ }
4539
+
4540
+ .blinq-button-default {
4541
+ border-color: rgba(255, 255, 255, 0.74);
4542
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.84), rgba(237, 241, 247, 0.66));
4543
+ color: var(--blinq-text);
4544
+ }
4545
+
4546
+ .blinq-button-outline,
4547
+ .blinq-button-ghost {
4548
+ border-color: rgba(255, 255, 255, 0.58);
4549
+ background: rgba(255, 255, 255, 0.42);
4550
+ color: var(--blinq-text-soft);
4551
+ }
4552
+
4553
+ .blinq-button-destructive {
4554
+ border-color: rgba(255, 255, 255, 0.58);
4555
+ background: linear-gradient(180deg, rgba(248, 249, 251, 0.7), rgba(230, 233, 239, 0.54));
4556
+ color: var(--blinq-text);
4557
+ }
4558
+
4559
+ .blinq-button-md {
4560
+ height: 44px;
4561
+ padding: 0 16px;
4562
+ }
4563
+
4564
+ .blinq-button-sm {
4565
+ height: 38px;
4566
+ padding: 0 13px;
4567
+ font-size: 13px;
4568
+ }
4569
+
4570
+ .blinq-button-icon {
4571
+ width: 48px;
4572
+ height: 48px;
4573
+ padding: 0;
4574
+ }
4575
+
4576
+ .blinq-button-icon-sm {
4577
+ width: 38px;
4578
+ height: 38px;
4579
+ padding: 0;
4580
+ }
4581
+
4582
+ .blinq-input-mic,
4583
+ .blinq-input-send {
4584
+ position: absolute;
4585
+ top: 50%;
4586
+ z-index: 2;
4587
+ width: 42px;
4588
+ height: 42px;
4589
+ min-width: 42px;
4590
+ transform: translateY(-50%);
4591
+ }
4592
+
4593
+ .blinq-input-mic {
4594
+ left: 8px;
4595
+ }
4596
+
4597
+ .blinq-input-send {
4598
+ right: 8px;
4599
+ }
4600
+
4601
+ .blinq-panel {
4602
+ display: flex;
4603
+ flex-direction: column;
4604
+ height: min(720px, calc(100vh - 64px));
4605
+ max-width: 520px;
4606
+ border: 1px solid rgba(226, 232, 240, 0.96);
4607
+ border-radius: 30px;
4608
+ background: #ffffff;
4609
+ box-shadow:
4610
+ 0 28px 80px rgba(15, 23, 42, 0.14),
4611
+ 0 10px 28px rgba(15, 23, 42, 0.08);
4612
+ backdrop-filter: none;
4613
+ -webkit-backdrop-filter: none;
4614
+ }
4615
+
4616
+ .blinq-panel::before,
4617
+ .blinq-panel::after,
4618
+ .blinq-message::before,
4619
+ .blinq-status-line::before {
4620
+ display: none;
4621
+ }
4622
+
4623
+ .blinq-header {
4624
+ flex: none;
4625
+ gap: 0;
4626
+ padding: 22px 24px 18px;
4627
+ border-bottom: 1px solid rgba(226, 232, 240, 0.86);
4628
+ background: #ffffff;
4629
+ }
4630
+
4631
+ .blinq-header-row {
4632
+ align-items: center;
4633
+ gap: 14px;
4634
+ }
4635
+
4636
+ .blinq-header-copy {
4637
+ gap: 5px;
4638
+ }
4639
+
4640
+ .blinq-heading {
4641
+ font-size: 22px;
4642
+ line-height: 1.05;
4643
+ font-weight: 700;
4644
+ letter-spacing: -0.04em;
4645
+ color: #111827;
4646
+ }
4647
+
4648
+ .blinq-status-line {
4649
+ display: block;
4650
+ max-width: 100%;
4651
+ min-height: 0;
4652
+ padding: 0;
4653
+ border: 0;
4654
+ background: transparent;
4655
+ box-shadow: none;
4656
+ color: #6b7280;
4657
+ font-size: 13px;
4658
+ line-height: 1.35;
4659
+ backdrop-filter: none;
4660
+ -webkit-backdrop-filter: none;
4661
+ }
4662
+
4663
+ .blinq-avatar {
4664
+ position: relative;
4665
+ display: inline-flex;
4666
+ align-items: center;
4667
+ justify-content: center;
4668
+ width: 64px;
4669
+ min-width: 64px;
4670
+ height: 64px;
4671
+ overflow: visible;
4672
+ border: 1px solid rgba(226, 232, 240, 0.95);
4673
+ border-radius: 999px;
4674
+ background:
4675
+ radial-gradient(circle at 30% 20%, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.86)),
4676
+ #ffffff;
4677
+ box-shadow:
4678
+ 0 14px 26px rgba(15, 23, 42, 0.08),
4679
+ inset 0 1px 0 rgba(255, 255, 255, 0.9);
4680
+ color: #111827;
4681
+ flex: none;
4682
+ }
4683
+
4684
+ .blinq-avatar-image {
4685
+ width: 100%;
4686
+ height: 100%;
4687
+ border-radius: inherit;
4688
+ object-fit: cover;
4689
+ }
4690
+
4691
+ .blinq-avatar-icon {
4692
+ color: #111827;
4693
+ }
4694
+
4695
+ .blinq-avatar-status {
4696
+ position: absolute;
4697
+ right: 5px;
4698
+ bottom: 6px;
4699
+ width: 11px;
4700
+ height: 11px;
4701
+ border: 2px solid #ffffff;
4702
+ border-radius: 999px;
4703
+ background: #21d262;
4704
+ box-shadow: 0 0 0 1px rgba(15, 23, 42, 0.04);
4705
+ }
4706
+
4707
+ .blinq-avatar-label {
4708
+ display: none;
4709
+ }
4710
+
4711
+ .blinq-thread {
4712
+ display: flex;
4713
+ flex: 1 1 auto;
4714
+ min-height: 0;
4715
+ background: #ffffff;
4716
+ }
4717
+
4718
+ .blinq-thread-viewport {
4719
+ flex: 1 1 auto;
4720
+ height: 100%;
4721
+ }
4722
+
4723
+ .blinq-scroll {
4724
+ flex: 1 1 auto;
4725
+ gap: 12px;
4726
+ max-height: none;
4727
+ min-height: 0;
4728
+ padding: 30px 24px 20px;
4729
+ background: #ffffff;
4730
+ }
4731
+
4732
+ .blinq-message {
4733
+ max-width: 82%;
4734
+ padding: 10px 15px;
4735
+ border: 1px solid rgba(226, 232, 240, 0.96);
4736
+ border-radius: 18px;
4737
+ background: #ffffff;
4738
+ box-shadow: none;
4739
+ color: #111827;
4740
+ font-size: 15px;
4741
+ line-height: 1.48;
4742
+ backdrop-filter: none;
4743
+ -webkit-backdrop-filter: none;
4744
+ }
4745
+
4746
+ .blinq-message[data-role="assistant"] {
4747
+ background: #ffffff;
4748
+ }
4749
+
4750
+ .blinq-message[data-role="user"] {
4751
+ border-color: rgba(209, 213, 219, 0.96);
4752
+ background: #f8fafc;
4753
+ }
4754
+
4755
+ .blinq-card,
4756
+ .blinq-guide-step-shell,
4757
+ .blinq-plan-step {
4758
+ border-color: rgba(226, 232, 240, 0.92);
4759
+ background: #ffffff;
4760
+ box-shadow: none;
4761
+ backdrop-filter: none;
4762
+ -webkit-backdrop-filter: none;
4763
+ }
4764
+
4765
+ .blinq-composer {
4766
+ flex: none;
4767
+ padding: 18px 24px 8px;
4768
+ border-top: 1px solid rgba(226, 232, 240, 0.86);
4769
+ background: #ffffff;
4770
+ }
4771
+
4772
+ .blinq-input,
4773
+ .blinq-recording-input {
4774
+ height: 56px;
4775
+ padding: 0 60px 0 54px;
4776
+ border: 1px solid rgba(209, 213, 219, 0.92);
4777
+ border-radius: 999px;
4778
+ background: #ffffff;
4779
+ box-shadow: none;
4780
+ color: #111827;
4781
+ font-size: 15px;
4782
+ backdrop-filter: none;
4783
+ -webkit-backdrop-filter: none;
4784
+ }
4785
+
4786
+ .blinq-input::placeholder {
4787
+ color: #9ca3af;
4788
+ }
4789
+
4790
+ .blinq-input-mic {
4791
+ left: 7px;
4792
+ width: 42px;
4793
+ min-width: 42px;
4794
+ height: 42px;
4795
+ border: 0;
4796
+ background: transparent;
4797
+ box-shadow: none;
4798
+ color: #6b7280;
4799
+ }
4800
+
4801
+ .blinq-input-send {
4802
+ right: 7px;
4803
+ width: 42px;
4804
+ min-width: 42px;
4805
+ height: 42px;
4806
+ border: 0;
4807
+ background: #6b6f76;
4808
+ box-shadow: none;
4809
+ color: #ffffff;
4810
+ }
4811
+
4812
+ .blinq-input-send:hover:not(:disabled) {
4813
+ transform: translateY(-50%);
4814
+ background: #4b5563;
4815
+ box-shadow: none;
4816
+ }
4817
+
4818
+ .blinq-button-ghost {
4819
+ border-color: transparent;
4820
+ background: transparent;
4821
+ box-shadow: none;
4822
+ }
4823
+
4824
+ .blinq-powered {
4825
+ flex: none;
4826
+ padding: 0 24px 18px;
4827
+ color: #c0c4ca;
4828
+ font-size: 10px;
4829
+ font-weight: 800;
4830
+ letter-spacing: 0.16em;
4831
+ line-height: 1;
4832
+ text-align: center;
4833
+ }
4834
+
4835
+ @keyframes blinq-thinking-pulse {
4836
+ 0%, 100% {
4837
+ opacity: 0.28;
4838
+ transform: translateY(0);
4839
+ }
4840
+
4841
+ 50% {
4842
+ opacity: 1;
4843
+ transform: translateY(-1.5px);
4844
+ }
4845
+ }
4846
+
4847
+ @keyframes blinq-copy-reveal {
4848
+ 0% {
4849
+ opacity: 0;
4850
+ transform: translateY(3px);
4851
+ }
4852
+
4853
+ 100% {
4854
+ opacity: 1;
4855
+ transform: translateY(0);
4856
+ }
4857
+ }
4858
+
4859
+ @keyframes blinq-orbit-drift {
4860
+ from {
4861
+ transform: rotate(0deg);
4862
+ }
4863
+
4864
+ to {
4865
+ transform: rotate(360deg);
4866
+ }
4867
+ }
4868
+
4869
+ @keyframes blinq-orbit-pulse {
4870
+ 0%, 100% {
4871
+ transform: scale(1);
4872
+ opacity: 0.9;
4873
+ }
4874
+
4875
+ 50% {
4876
+ transform: scale(1.16);
4877
+ opacity: 1;
4878
+ }
4879
+ }
4880
+
4881
+ @keyframes blinq-core-breathe {
4882
+ 0%, 100% {
4883
+ transform: scale(1);
4884
+ }
4885
+
4886
+ 50% {
4887
+ transform: scale(1.04);
4888
+ }
4889
+ }
4890
+
4891
+ @media (max-width: 720px) {
4892
+ .blinq-shell {
4893
+ right: 12px;
4894
+ left: 12px;
4895
+ bottom: 12px;
4896
+ width: auto;
4897
+ max-width: none;
4898
+ align-items: stretch;
4899
+ }
4900
+
4901
+ .blinq-shell[data-side="left"],
4902
+ .blinq-shell[data-side="right"] {
4903
+ right: 12px;
4904
+ left: 12px;
4905
+ align-items: stretch;
4906
+ }
4907
+
4908
+ .blinq-panel,
4909
+ .blinq-launcher {
4910
+ width: 100%;
4911
+ max-width: none;
4912
+ }
4913
+
4914
+ .blinq-launcher {
4915
+ width: 76px;
4916
+ min-width: 76px;
4917
+ height: 76px;
4918
+ align-self: flex-end;
4919
+ }
4920
+
4921
+ .blinq-message {
4922
+ max-width: 92%;
4923
+ }
4924
+
4925
+ .blinq-actions {
4926
+ flex-direction: column;
4927
+ }
4928
+
4929
+ .blinq-input,
4930
+ .blinq-recording-input {
4931
+ height: 56px;
4932
+ }
4933
+
4934
+ .blinq-panel {
4935
+ height: min(700px, calc(100vh - 24px));
4936
+ }
4937
+ }
4938
+ `;
3200
4939
  // Annotate the CommonJS export names for ESM import in node:
3201
4940
  0 && (module.exports = {
3202
4941
  BlinqWidget,
4942
+ EMBED_WIDGET_STYLES,
4943
+ PageToolRegistry,
4944
+ WidgetEmbedShell,
4945
+ collectNormalizedPageContext,
3203
4946
  createBlinqWidget,
4947
+ detectNativeWebMcpSupport,
3204
4948
  init,
3205
4949
  initFromConfig
3206
4950
  });