arcy.js 0.1.1 → 0.1.3

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.
@@ -1,4 +1,5 @@
1
- import { CHAT_CONTRACT, CHAT_GLOBAL, FALLBACK_CHROME, carriesFiles, droppedFiles, FONT_KEY_PROPERTY, PANEL_GAP, dragTransform, MOBILE_MARGIN, surfaceWidth, PANEL_MARGIN, clampOffsetX, panelHeight, TOOLTIP_CSS, BAR_TRAY_CLASS, ATTACHABLE_TYPES, POLICY_LINK_CLASS } from './chunk-6HBSGVRN.js';
1
+ import { CHAT_CONTRACT, CHAT_GLOBAL, FALLBACK_CHROME, resolveImageUrl, carriesFiles, droppedFiles, FONT_KEY_PROPERTY, PANEL_GAP, dragTransform, MOBILE_MARGIN, surfaceWidth, PANEL_MARGIN, clampOffsetX, panelHeight, TOOLTIP_CSS, BAR_TRAY_CLASS, ATTACHABLE_TYPES, POLICY_LINK_CLASS } from './chunk-DW3GUQ6J.js';
2
+ export { resolveImageUrl } from './chunk-DW3GUQ6J.js';
2
3
  import { normalizeOptionReply, validateFillReply, fetchFlowCatalog } from './chunk-CQ2DESAJ.js';
3
4
  import { injectStyles, applyNonce } from './chunk-LGWYJSYX.js';
4
5
 
@@ -344,7 +345,7 @@ var TRANSCRIPT_CSS = `
344
345
  .${MSG_CLASS}[data-role="system"] {
345
346
  align-self: flex-start;
346
347
  background: var(--_arcy-assistant-bg, #f2f4f7);
347
- color: var(--_arcy-main-text, #101828);
348
+ color: var(--_arcy-assistant-text, var(--_arcy-main-text, #101828));
348
349
  }
349
350
 
350
351
  /* \u2500\u2500 Rendered markdown inside an answer (D1023, ADR 0129; D1034) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
@@ -399,7 +400,7 @@ var TRANSCRIPT_CSS = `
399
400
  font-size: 0.9em;
400
401
  padding: 1px 4px;
401
402
  border-radius: 4px;
402
- background: color-mix(in srgb, var(--_arcy-main-text, #101828) 8%, transparent);
403
+ background: color-mix(in srgb, currentColor 12%, transparent);
403
404
  white-space: pre-wrap;
404
405
  overflow-wrap: break-word;
405
406
  }
@@ -408,8 +409,8 @@ var TRANSCRIPT_CSS = `
408
409
  margin: 0 0 8px;
409
410
  padding: 10px 12px;
410
411
  border-radius: 8px;
411
- background: color-mix(in srgb, var(--_arcy-main-text, #101828) 6%, transparent);
412
- border: 1px solid color-mix(in srgb, var(--_arcy-main-text, #101828) 10%, transparent);
412
+ background: color-mix(in srgb, currentColor 10%, transparent);
413
+ border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
413
414
  overflow-x: auto;
414
415
  white-space: pre;
415
416
  }
@@ -592,13 +593,14 @@ var TRANSCRIPT_CSS = `
592
593
  padding: 12px;
593
594
  border-radius: 12px;
594
595
  background: var(--_arcy-assistant-bg, #f2f4f7);
596
+ color: var(--_arcy-assistant-text, var(--_arcy-main-text, #101828));
595
597
  }
596
598
 
597
599
  .${PENDING_CLASS} span {
598
600
  width: 6px;
599
601
  height: 6px;
600
602
  border-radius: 999px;
601
- background: color-mix(in srgb, var(--_arcy-main-text, #101828) 45%, transparent);
603
+ background: color-mix(in srgb, currentColor 55%, transparent);
602
604
  animation: arcy-chat-typing 1.2s ease-in-out infinite;
603
605
  }
604
606
 
@@ -2437,14 +2439,6 @@ var MAIN_CLASS = "arcy-chat-main";
2437
2439
  var MARK_CLASS = "arcy-chat-mark";
2438
2440
  var MARK_LINK_CLASS = "arcy-chat-mark-link";
2439
2441
  var POLICY_CLASS = POLICY_LINK_CLASS;
2440
- function resolveImageUrl(value, apiBase) {
2441
- if (typeof value !== "string" || value.length === 0) return null;
2442
- if (/^https:\/\//i.test(value)) return value;
2443
- if (value.startsWith("/") && !value.startsWith("//")) {
2444
- return `${(apiBase ?? DEFAULT_API_BASE).replace(/\/+$/, "")}${value}`;
2445
- }
2446
- return null;
2447
- }
2448
2442
  var ARCY_HOME_URL = "https://arcyai.com";
2449
2443
  var WELCOME_CLASS = "arcy-chat-welcome";
2450
2444
  var STARTER_CLASS = "arcy-chat-starter";
@@ -3864,4 +3858,4 @@ if (typeof window !== "undefined") {
3864
3858
  }
3865
3859
  }
3866
3860
 
3867
- export { ARCY_HOME_URL, BODY_CLASS, CATALOG_RETRY_MS, CHAT_CSS, CHIPS_CLASS, CHIP_CLASS, HEADER_BUTTON_CLASS, HEADER_CLASS2 as HEADER_CLASS, HEADER_ICON_CLASS, HEADER_NAME_CLASS, MAIN_CLASS, MARK_CLASS, MARK_LINK_CLASS, PANEL_CLASS, POLICY_CLASS, STARTER_CLASS, STARTER_ROW_CLASS, STRIP_CLASS, WELCOME_CLASS, mount, resolveImageUrl };
3861
+ export { ARCY_HOME_URL, BODY_CLASS, CATALOG_RETRY_MS, CHAT_CSS, CHIPS_CLASS, CHIP_CLASS, HEADER_BUTTON_CLASS, HEADER_CLASS2 as HEADER_CLASS, HEADER_ICON_CLASS, HEADER_NAME_CLASS, MAIN_CLASS, MARK_CLASS, MARK_LINK_CLASS, PANEL_CLASS, POLICY_CLASS, STARTER_CLASS, STARTER_ROW_CLASS, STRIP_CLASS, WELCOME_CLASS, mount };
@@ -216,4 +216,19 @@ function clampOffsetX(x, width, viewportWidth) {
216
216
  return Math.min(maxX, Math.max(-maxX, x));
217
217
  }
218
218
 
219
- export { ATTACHABLE_TYPES, BAR_TRAY_CLASS, CHAT_CONTRACT, CHAT_GLOBAL, FALLBACK_CHROME, FONT_KEY_PROPERTY, MOBILE_MARGIN, PANEL_GAP, PANEL_MARGIN, POLICY_LINK_CLASS, TOOLTIP_CSS, carriesFiles, clampOffsetX, dragTransform, droppedFiles, panelHeight, readViewport, surfaceWidth };
219
+ // src/shell/image-url.ts
220
+ var DEFAULT_API_BASE = "https://api.arcyai.com";
221
+ var MAX_URL = 2048;
222
+ function isRenderableImageUrl(value) {
223
+ if (typeof value !== "string") return false;
224
+ if (value.length === 0 || value.length > MAX_URL) return false;
225
+ if (/^https:\/\//i.test(value)) return true;
226
+ return value.startsWith("/") && !value.startsWith("//");
227
+ }
228
+ function resolveImageUrl(value, apiBase) {
229
+ if (!isRenderableImageUrl(value)) return null;
230
+ if (/^https:\/\//i.test(value)) return value;
231
+ return `${(apiBase ?? DEFAULT_API_BASE).replace(/\/+$/, "")}${value}`;
232
+ }
233
+
234
+ export { ATTACHABLE_TYPES, BAR_TRAY_CLASS, CHAT_CONTRACT, CHAT_GLOBAL, FALLBACK_CHROME, FONT_KEY_PROPERTY, MOBILE_MARGIN, PANEL_GAP, PANEL_MARGIN, POLICY_LINK_CLASS, TOOLTIP_CSS, carriesFiles, clampOffsetX, dragTransform, droppedFiles, isRenderableImageUrl, panelHeight, readViewport, resolveImageUrl, surfaceWidth };
package/dist/index.cjs CHANGED
@@ -922,6 +922,26 @@ var init_viewport = __esm({
922
922
  }
923
923
  });
924
924
 
925
+ // src/shell/image-url.ts
926
+ function isRenderableImageUrl(value) {
927
+ if (typeof value !== "string") return false;
928
+ if (value.length === 0 || value.length > MAX_URL) return false;
929
+ if (/^https:\/\//i.test(value)) return true;
930
+ return value.startsWith("/") && !value.startsWith("//");
931
+ }
932
+ function resolveImageUrl(value, apiBase) {
933
+ if (!isRenderableImageUrl(value)) return null;
934
+ if (/^https:\/\//i.test(value)) return value;
935
+ return `${(apiBase ?? DEFAULT_API_BASE2).replace(/\/+$/, "")}${value}`;
936
+ }
937
+ var DEFAULT_API_BASE2, MAX_URL;
938
+ var init_image_url = __esm({
939
+ "src/shell/image-url.ts"() {
940
+ DEFAULT_API_BASE2 = "https://api.arcyai.com";
941
+ MAX_URL = 2048;
942
+ }
943
+ });
944
+
925
945
  // src/shell/state.ts
926
946
  function readPosition(value) {
927
947
  if (!value || typeof value !== "object") return null;
@@ -1573,7 +1593,7 @@ var init_transcript = __esm({
1573
1593
  .${MSG_CLASS}[data-role="system"] {
1574
1594
  align-self: flex-start;
1575
1595
  background: var(--_arcy-assistant-bg, #f2f4f7);
1576
- color: var(--_arcy-main-text, #101828);
1596
+ color: var(--_arcy-assistant-text, var(--_arcy-main-text, #101828));
1577
1597
  }
1578
1598
 
1579
1599
  /* \u2500\u2500 Rendered markdown inside an answer (D1023, ADR 0129; D1034) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
@@ -1628,7 +1648,7 @@ var init_transcript = __esm({
1628
1648
  font-size: 0.9em;
1629
1649
  padding: 1px 4px;
1630
1650
  border-radius: 4px;
1631
- background: color-mix(in srgb, var(--_arcy-main-text, #101828) 8%, transparent);
1651
+ background: color-mix(in srgb, currentColor 12%, transparent);
1632
1652
  white-space: pre-wrap;
1633
1653
  overflow-wrap: break-word;
1634
1654
  }
@@ -1637,8 +1657,8 @@ var init_transcript = __esm({
1637
1657
  margin: 0 0 8px;
1638
1658
  padding: 10px 12px;
1639
1659
  border-radius: 8px;
1640
- background: color-mix(in srgb, var(--_arcy-main-text, #101828) 6%, transparent);
1641
- border: 1px solid color-mix(in srgb, var(--_arcy-main-text, #101828) 10%, transparent);
1660
+ background: color-mix(in srgb, currentColor 10%, transparent);
1661
+ border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
1642
1662
  overflow-x: auto;
1643
1663
  white-space: pre;
1644
1664
  }
@@ -1821,13 +1841,14 @@ var init_transcript = __esm({
1821
1841
  padding: 12px;
1822
1842
  border-radius: 12px;
1823
1843
  background: var(--_arcy-assistant-bg, #f2f4f7);
1844
+ color: var(--_arcy-assistant-text, var(--_arcy-main-text, #101828));
1824
1845
  }
1825
1846
 
1826
1847
  .${PENDING_CLASS} span {
1827
1848
  width: 6px;
1828
1849
  height: 6px;
1829
1850
  border-radius: 999px;
1830
- background: color-mix(in srgb, var(--_arcy-main-text, #101828) 45%, transparent);
1851
+ background: color-mix(in srgb, currentColor 55%, transparent);
1831
1852
  animation: arcy-chat-typing 1.2s ease-in-out infinite;
1832
1853
  }
1833
1854
 
@@ -2964,7 +2985,7 @@ function headers(sessionToken) {
2964
2985
  }
2965
2986
  async function fetchFlowCatalog(options) {
2966
2987
  const {
2967
- apiBase = DEFAULT_API_BASE3,
2988
+ apiBase = DEFAULT_API_BASE4,
2968
2989
  sessionToken,
2969
2990
  sessionId,
2970
2991
  setTimeoutImpl = (fn, ms) => setTimeout(fn, ms),
@@ -3001,7 +3022,7 @@ async function fetchFlowCatalog(options) {
3001
3022
  }
3002
3023
  async function fetchFlowRun(flowCvid, options) {
3003
3024
  const {
3004
- apiBase = DEFAULT_API_BASE3,
3025
+ apiBase = DEFAULT_API_BASE4,
3005
3026
  sessionToken,
3006
3027
  sessionId,
3007
3028
  setTimeoutImpl = (fn, ms) => setTimeout(fn, ms),
@@ -3040,10 +3061,10 @@ async function fetchFlowRun(flowCvid, options) {
3040
3061
  reason: "network"
3041
3062
  });
3042
3063
  }
3043
- var DEFAULT_API_BASE3, FLOW_CATALOG_PATH, FLOW_RUN_PATH, FLOW_FETCH_TIMEOUT_MS;
3064
+ var DEFAULT_API_BASE4, FLOW_CATALOG_PATH, FLOW_RUN_PATH, FLOW_FETCH_TIMEOUT_MS;
3044
3065
  var init_api = __esm({
3045
3066
  "src/flow/api.ts"() {
3046
- DEFAULT_API_BASE3 = "https://api.arcyai.com";
3067
+ DEFAULT_API_BASE4 = "https://api.arcyai.com";
3047
3068
  FLOW_CATALOG_PATH = "/api/v1/sdk/flows/catalog";
3048
3069
  FLOW_RUN_PATH = "/api/v1/sdk/flows";
3049
3070
  FLOW_FETCH_TIMEOUT_MS = 8e3;
@@ -3139,7 +3160,7 @@ function headers2(sessionToken) {
3139
3160
  }
3140
3161
  async function postAgentQuery(options) {
3141
3162
  const {
3142
- apiBase = DEFAULT_API_BASE4,
3163
+ apiBase = DEFAULT_API_BASE5,
3143
3164
  publicKey,
3144
3165
  sessionId,
3145
3166
  sessionToken,
@@ -3196,10 +3217,10 @@ async function postAgentQuery(options) {
3196
3217
  })();
3197
3218
  return bounded2(attempt, timeoutMs, setTimeoutImpl, { ok: false, reason: "network" });
3198
3219
  }
3199
- var DEFAULT_API_BASE4, AGENT_QUERY_PATH, AGENT_QUERY_TIMEOUT_MS, CAP_DENIAL_REASONS;
3220
+ var DEFAULT_API_BASE5, AGENT_QUERY_PATH, AGENT_QUERY_TIMEOUT_MS, CAP_DENIAL_REASONS;
3200
3221
  var init_chat_api = __esm({
3201
3222
  "src/shell/chat-api.ts"() {
3202
- DEFAULT_API_BASE4 = "https://api.arcyai.com";
3223
+ DEFAULT_API_BASE5 = "https://api.arcyai.com";
3203
3224
  AGENT_QUERY_PATH = "/api/v1/sdk/agent/query";
3204
3225
  AGENT_QUERY_TIMEOUT_MS = 2e4;
3205
3226
  CAP_DENIAL_REASONS = /* @__PURE__ */ new Set([
@@ -3217,14 +3238,14 @@ var init_chat_api = __esm({
3217
3238
  function web(family, fallback = SANS_FALLBACK) {
3218
3239
  return { family, fallback, stack: `"${family}", ${fallback}` };
3219
3240
  }
3220
- function fontFaceCss(key, assetBase = DEFAULT_API_BASE4) {
3241
+ function fontFaceCss(key, assetBase = DEFAULT_API_BASE5) {
3221
3242
  const entry = CATALOG[key];
3222
3243
  if (!entry?.family) return "";
3223
3244
  return SUBSETS.map(
3224
3245
  ([subset, range]) => `@font-face{font-family:"${entry.family}";font-style:normal;font-weight:400;font-display:swap;src:url("${assetBase}/fonts/${key}-${subset}.woff2") format("woff2");unicode-range:${range};}`
3225
3246
  ).join("\n");
3226
3247
  }
3227
- function applyFont(host, doc, assetBase = DEFAULT_API_BASE4) {
3248
+ function applyFont(host, doc, assetBase = DEFAULT_API_BASE5) {
3228
3249
  try {
3229
3250
  const key = host.style.getPropertyValue(FONT_KEY_PROPERTY).trim();
3230
3251
  const entry = key ? CATALOG[key] : void 0;
@@ -3351,7 +3372,7 @@ function toRows(conversations, imageLabel, currentConversationId) {
3351
3372
  }
3352
3373
  async function fetchConversations(options) {
3353
3374
  const {
3354
- apiBase = DEFAULT_API_BASE4,
3375
+ apiBase = DEFAULT_API_BASE5,
3355
3376
  sessionToken,
3356
3377
  visitorId,
3357
3378
  setTimeoutImpl = (fn, ms) => setTimeout(fn, ms),
@@ -3453,7 +3474,7 @@ function readMessages(body) {
3453
3474
  }
3454
3475
  async function fetchConversationMessages(options) {
3455
3476
  const {
3456
- apiBase = DEFAULT_API_BASE4,
3477
+ apiBase = DEFAULT_API_BASE5,
3457
3478
  sessionToken,
3458
3479
  conversationId,
3459
3480
  visitorId,
@@ -3521,7 +3542,7 @@ function feedbackPath(conversationId, messageId) {
3521
3542
  }
3522
3543
  async function postAnswerFeedback(options) {
3523
3544
  const {
3524
- apiBase = DEFAULT_API_BASE4,
3545
+ apiBase = DEFAULT_API_BASE5,
3525
3546
  sessionToken,
3526
3547
  conversationId,
3527
3548
  messageId,
@@ -3695,7 +3716,7 @@ async function uploadImage(file, alreadyAttached, options) {
3695
3716
  const validation = validateFile(file, alreadyAttached);
3696
3717
  if (!validation.ok) return { ok: false, reason: validation.reason };
3697
3718
  const {
3698
- apiBase = DEFAULT_API_BASE4,
3719
+ apiBase = DEFAULT_API_BASE5,
3699
3720
  sessionToken,
3700
3721
  env,
3701
3722
  timeoutMs = UPLOAD_TIMEOUT_MS
@@ -3749,7 +3770,7 @@ async function uploadImage(file, alreadyAttached, options) {
3749
3770
  });
3750
3771
  }
3751
3772
  async function discardUpload(objectKey, options) {
3752
- const { apiBase = DEFAULT_API_BASE4, sessionToken, fetchImpl } = options;
3773
+ const { apiBase = DEFAULT_API_BASE5, sessionToken, fetchImpl } = options;
3753
3774
  if (!fetchImpl || !sessionToken || !objectKey) return false;
3754
3775
  try {
3755
3776
  const response = await fetchImpl(`${apiBase}${DISCARD_PATH}`, {
@@ -3806,14 +3827,6 @@ __export(chat_exports, {
3806
3827
  mount: () => mount,
3807
3828
  resolveImageUrl: () => resolveImageUrl
3808
3829
  });
3809
- function resolveImageUrl(value, apiBase) {
3810
- if (typeof value !== "string" || value.length === 0) return null;
3811
- if (/^https:\/\//i.test(value)) return value;
3812
- if (value.startsWith("/") && !value.startsWith("//")) {
3813
- return `${(apiBase ?? DEFAULT_API_BASE4).replace(/\/+$/, "")}${value}`;
3814
- }
3815
- return null;
3816
- }
3817
3830
  function icon(doc, path, size2 = 17) {
3818
3831
  const svg = doc.createElementNS(SVG_NS5, "svg");
3819
3832
  svg.setAttribute("viewBox", "0 0 24 24");
@@ -3945,7 +3958,7 @@ function mount(context) {
3945
3958
  context.bar.setDisabled(true);
3946
3959
  transcript.setPending(true);
3947
3960
  void postAgentQuery({
3948
- apiBase: context.apiBase ?? DEFAULT_API_BASE4,
3961
+ apiBase: context.apiBase ?? DEFAULT_API_BASE5,
3949
3962
  publicKey: context.publicKey ?? "",
3950
3963
  sessionId: context.getSessionId?.() ?? "",
3951
3964
  sessionToken: context.getSessionToken?.() ?? "",
@@ -4775,6 +4788,7 @@ var init_chat = __esm({
4775
4788
  init_api();
4776
4789
  init_renderable_flows();
4777
4790
  init_chat_api();
4791
+ init_image_url();
4778
4792
  init_fonts();
4779
4793
  init_conversation_list();
4780
4794
  init_conversation_messages();
@@ -11348,6 +11362,7 @@ init_chat_contract();
11348
11362
  // src/shell/tokens.ts
11349
11363
  init_chat_contract();
11350
11364
  init_host();
11365
+ init_image_url();
11351
11366
  init_warn();
11352
11367
  init_storage();
11353
11368
  var HEX = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
@@ -11515,13 +11530,12 @@ function applyTokens(host, tokens) {
11515
11530
  var TOKEN_KEY_PREFIX = "arcy.tokens.";
11516
11531
  var MAX_STORED = 4096;
11517
11532
  var MAX_NAME = 100;
11518
- var MAX_URL = 2048;
11519
11533
  function readIdentity(value) {
11520
11534
  const raw = object(value);
11521
11535
  if (!raw) return null;
11522
11536
  const name = typeof raw.name === "string" ? raw.name.slice(0, MAX_NAME) : "";
11523
11537
  const url = raw.logoUrl;
11524
- const logoUrl = typeof url === "string" && url.length <= MAX_URL && /^https:\/\//i.test(url) ? url : null;
11538
+ const logoUrl = isRenderableImageUrl(url) ? url : null;
11525
11539
  return { name, logoUrl };
11526
11540
  }
11527
11541
  function createTokenCache(token, raw = browserLocalStorage()) {
@@ -11553,6 +11567,7 @@ function createTokenCache(token, raw = browserLocalStorage()) {
11553
11567
  }
11554
11568
 
11555
11569
  // src/api.ts
11570
+ init_image_url();
11556
11571
  init_state2();
11557
11572
 
11558
11573
  // src/session/visit.ts
@@ -12219,22 +12234,34 @@ function createSessionStore({
12219
12234
  fill,
12220
12235
  windowMs = SESSION_WINDOW_MS
12221
12236
  }) {
12222
- function touch() {
12223
- const at = now();
12237
+ function alive(at) {
12224
12238
  const existing = readJson(store, key);
12225
- const alive = existing && typeof existing.id === "string" && existing.id.length > 0 && typeof existing.seen === "number" && at - existing.seen < windowMs;
12226
- if (alive) {
12227
- if (at - existing.seen >= TOUCH_WRITE_INTERVAL_MS) {
12228
- writeJson(store, key, { id: existing.id, seen: at });
12229
- }
12230
- return existing.id;
12239
+ if (existing && typeof existing.id === "string" && existing.id.length > 0 && typeof existing.seen === "number" && at - existing.seen < windowMs) {
12240
+ return existing;
12231
12241
  }
12242
+ return null;
12243
+ }
12244
+ function mint(at) {
12232
12245
  const id = ulid(at, fill);
12233
12246
  writeJson(store, key, { id, seen: at });
12234
12247
  return id;
12235
12248
  }
12249
+ function touch() {
12250
+ const at = now();
12251
+ const existing = alive(at);
12252
+ if (!existing) return mint(at);
12253
+ if (at - existing.seen >= TOUCH_WRITE_INTERVAL_MS) {
12254
+ writeJson(store, key, { id: existing.id, seen: at });
12255
+ }
12256
+ return existing.id;
12257
+ }
12258
+ function current() {
12259
+ const at = now();
12260
+ return alive(at)?.id ?? mint(at);
12261
+ }
12236
12262
  return {
12237
12263
  touch,
12264
+ current,
12238
12265
  peek: () => readJson(store, key),
12239
12266
  clear() {
12240
12267
  store.removeItem(key);
@@ -12251,7 +12278,7 @@ var FLUSH_INTERVAL_MS = 5e3;
12251
12278
  var MAX_EVENTS_PER_REQUEST = 100;
12252
12279
  var MAX_REQUEST_BYTES = 64 * 1024;
12253
12280
  var MAX_QUEUED_EVENTS = 1e3;
12254
- var DEFAULT_API_BASE2 = "https://api.arcyai.com";
12281
+ var DEFAULT_API_BASE3 = "https://api.arcyai.com";
12255
12282
  var TELEMETRY_PATH = "/api/v1/sdk/telemetry";
12256
12283
  function utf8Length(value) {
12257
12284
  let bytes = 0;
@@ -12287,7 +12314,7 @@ function chunkEvents(events) {
12287
12314
  function createTransport(options) {
12288
12315
  const {
12289
12316
  token,
12290
- apiBase = DEFAULT_API_BASE2,
12317
+ apiBase = DEFAULT_API_BASE3,
12291
12318
  fetchImpl,
12292
12319
  sendBeacon,
12293
12320
  setTimeoutImpl = (fn, ms) => setTimeout(fn, ms),
@@ -12684,7 +12711,7 @@ function createTelemetry(options) {
12684
12711
  if (typeof raw !== "string") return void 0;
12685
12712
  return normalizeRoute(raw, win?.location?.href) ?? void 0;
12686
12713
  }
12687
- const ownOrigin = (apiBase ?? DEFAULT_API_BASE2).replace(/\/+$/, "");
12714
+ const ownOrigin = (apiBase ?? DEFAULT_API_BASE3).replace(/\/+$/, "");
12688
12715
  let uninstallNetworkWatch = null;
12689
12716
  return {
12690
12717
  start() {
@@ -12761,7 +12788,7 @@ function createTelemetry(options) {
12761
12788
  capture(name, payload, fields2);
12762
12789
  },
12763
12790
  flush: () => transport.flush(false),
12764
- sessionId: () => session.touch(),
12791
+ sessionId: () => session.current(),
12765
12792
  resetSession: () => session.clear(),
12766
12793
  stopped: () => transport.stopped(),
12767
12794
  state: () => consent.state()
@@ -13078,16 +13105,12 @@ function createArcyInternals(internalOptions = {}) {
13078
13105
  const chrome = raw?.chrome && typeof raw.chrome === "object" && !Array.isArray(raw.chrome) ? { ...FALLBACK_CHROME, ...raw.chrome } : FALLBACK_CHROME;
13079
13106
  const welcomeIconUrl = raw?.welcomeIconUrl;
13080
13107
  const chatBarIconUrl = raw?.chatBarIconUrl;
13108
+ const apiBase = resolveApiBase();
13081
13109
  return {
13082
13110
  name: identity2.name,
13083
- logoUrl: identity2.logoUrl,
13084
- // Re-checked here rather than trusted, same as privacyPolicyUrl below:
13085
- // a rewritten bootstrap must not be able to point this at a
13086
- // non-`https` URL (ADR 0050).
13087
- welcomeIconUrl: typeof welcomeIconUrl === "string" && /^https:\/\//i.test(welcomeIconUrl) ? welcomeIconUrl : null,
13088
- // Same re-check, same reason: this renders into an `<img src>` on a
13089
- // page ARCY does not control (ADR 0050).
13090
- chatBarIconUrl: typeof chatBarIconUrl === "string" && /^https:\/\//i.test(chatBarIconUrl) ? chatBarIconUrl : null,
13111
+ logoUrl: resolveImageUrl(identity2.logoUrl, apiBase),
13112
+ welcomeIconUrl: resolveImageUrl(welcomeIconUrl, apiBase),
13113
+ chatBarIconUrl: resolveImageUrl(chatBarIconUrl, apiBase),
13091
13114
  welcomeMessage: text(raw?.welcomeMessage),
13092
13115
  inputPlaceholder: text(raw?.inputPlaceholder),
13093
13116
  welcomeHeadline: text(raw?.welcomeHeadline),
@@ -13730,7 +13753,8 @@ function createArcyInternals(internalOptions = {}) {
13730
13753
  getConfig: () => bootstrap?.config() ?? null,
13731
13754
  selectLocale,
13732
13755
  getShellState: () => shellState,
13733
- getTokens: () => tokens
13756
+ getTokens: () => tokens,
13757
+ getWidgetChrome: () => readWidgetChrome()
13734
13758
  };
13735
13759
  }
13736
13760
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DESIGN_MODE_PROTOCOL, DESIGN_MODE_EXIT, DESIGN_MODE_SCREENSHOT, DESIGN_MODE_PICK, DESIGN_MODE_READY } from './chunk-7VVKR3AO.js';
2
- import { FONT_KEY_PROPERTY, FALLBACK_CHROME, readViewport, POLICY_LINK_CLASS, BAR_TRAY_CLASS, ATTACHABLE_TYPES, TOOLTIP_CSS, surfaceWidth, clampOffsetX, dragTransform, carriesFiles, droppedFiles, MOBILE_MARGIN, CHAT_CONTRACT, CHAT_GLOBAL } from './chunk-6HBSGVRN.js';
2
+ import { FALLBACK_CHROME, resolveImageUrl, FONT_KEY_PROPERTY, isRenderableImageUrl, readViewport, POLICY_LINK_CLASS, BAR_TRAY_CLASS, ATTACHABLE_TYPES, TOOLTIP_CSS, surfaceWidth, clampOffsetX, dragTransform, carriesFiles, droppedFiles, MOBILE_MARGIN, CHAT_CONTRACT, CHAT_GLOBAL } from './chunk-DW3GUQ6J.js';
3
3
  import { createShellState, safeStore, browserSessionStorage, writeJson, browserLocalStorage, readJson, hasPendingPreview, createFlowRunState, FLOW_CONTRACT, FLOW_GLOBAL } from './chunk-FR6SJSDU.js';
4
4
  import { PICKER_CONTRACT, PICKER_GLOBAL } from './chunk-DKYMIAYF.js';
5
5
  import { warn, reportCspViolations, releaseHostFocus, Z_INDEX, createShell, injectStyles } from './chunk-LGWYJSYX.js';
@@ -2429,13 +2429,12 @@ function applyTokens(host, tokens) {
2429
2429
  var TOKEN_KEY_PREFIX = "arcy.tokens.";
2430
2430
  var MAX_STORED = 4096;
2431
2431
  var MAX_NAME = 100;
2432
- var MAX_URL = 2048;
2433
2432
  function readIdentity(value) {
2434
2433
  const raw = object(value);
2435
2434
  if (!raw) return null;
2436
2435
  const name = typeof raw.name === "string" ? raw.name.slice(0, MAX_NAME) : "";
2437
2436
  const url = raw.logoUrl;
2438
- const logoUrl = typeof url === "string" && url.length <= MAX_URL && /^https:\/\//i.test(url) ? url : null;
2437
+ const logoUrl = isRenderableImageUrl(url) ? url : null;
2439
2438
  return { name, logoUrl };
2440
2439
  }
2441
2440
  function createTokenCache(token, raw = browserLocalStorage()) {
@@ -3123,22 +3122,34 @@ function createSessionStore({
3123
3122
  fill,
3124
3123
  windowMs = SESSION_WINDOW_MS
3125
3124
  }) {
3126
- function touch() {
3127
- const at = now();
3125
+ function alive(at) {
3128
3126
  const existing = readJson(store, key);
3129
- const alive = existing && typeof existing.id === "string" && existing.id.length > 0 && typeof existing.seen === "number" && at - existing.seen < windowMs;
3130
- if (alive) {
3131
- if (at - existing.seen >= TOUCH_WRITE_INTERVAL_MS) {
3132
- writeJson(store, key, { id: existing.id, seen: at });
3133
- }
3134
- return existing.id;
3127
+ if (existing && typeof existing.id === "string" && existing.id.length > 0 && typeof existing.seen === "number" && at - existing.seen < windowMs) {
3128
+ return existing;
3135
3129
  }
3130
+ return null;
3131
+ }
3132
+ function mint(at) {
3136
3133
  const id = ulid(at, fill);
3137
3134
  writeJson(store, key, { id, seen: at });
3138
3135
  return id;
3139
3136
  }
3137
+ function touch() {
3138
+ const at = now();
3139
+ const existing = alive(at);
3140
+ if (!existing) return mint(at);
3141
+ if (at - existing.seen >= TOUCH_WRITE_INTERVAL_MS) {
3142
+ writeJson(store, key, { id: existing.id, seen: at });
3143
+ }
3144
+ return existing.id;
3145
+ }
3146
+ function current() {
3147
+ const at = now();
3148
+ return alive(at)?.id ?? mint(at);
3149
+ }
3140
3150
  return {
3141
3151
  touch,
3152
+ current,
3142
3153
  peek: () => readJson(store, key),
3143
3154
  clear() {
3144
3155
  store.removeItem(key);
@@ -3662,7 +3673,7 @@ function createTelemetry(options) {
3662
3673
  capture(name, payload, fields2);
3663
3674
  },
3664
3675
  flush: () => transport.flush(false),
3665
- sessionId: () => session.touch(),
3676
+ sessionId: () => session.current(),
3666
3677
  resetSession: () => session.clear(),
3667
3678
  stopped: () => transport.stopped(),
3668
3679
  state: () => consent.state()
@@ -3978,16 +3989,12 @@ function createArcyInternals(internalOptions = {}) {
3978
3989
  const chrome = raw?.chrome && typeof raw.chrome === "object" && !Array.isArray(raw.chrome) ? { ...FALLBACK_CHROME, ...raw.chrome } : FALLBACK_CHROME;
3979
3990
  const welcomeIconUrl = raw?.welcomeIconUrl;
3980
3991
  const chatBarIconUrl = raw?.chatBarIconUrl;
3992
+ const apiBase = resolveApiBase();
3981
3993
  return {
3982
3994
  name: identity2.name,
3983
- logoUrl: identity2.logoUrl,
3984
- // Re-checked here rather than trusted, same as privacyPolicyUrl below:
3985
- // a rewritten bootstrap must not be able to point this at a
3986
- // non-`https` URL (ADR 0050).
3987
- welcomeIconUrl: typeof welcomeIconUrl === "string" && /^https:\/\//i.test(welcomeIconUrl) ? welcomeIconUrl : null,
3988
- // Same re-check, same reason: this renders into an `<img src>` on a
3989
- // page ARCY does not control (ADR 0050).
3990
- chatBarIconUrl: typeof chatBarIconUrl === "string" && /^https:\/\//i.test(chatBarIconUrl) ? chatBarIconUrl : null,
3995
+ logoUrl: resolveImageUrl(identity2.logoUrl, apiBase),
3996
+ welcomeIconUrl: resolveImageUrl(welcomeIconUrl, apiBase),
3997
+ chatBarIconUrl: resolveImageUrl(chatBarIconUrl, apiBase),
3991
3998
  welcomeMessage: text(raw?.welcomeMessage),
3992
3999
  inputPlaceholder: text(raw?.inputPlaceholder),
3993
4000
  welcomeHeadline: text(raw?.welcomeHeadline),
@@ -4630,7 +4637,8 @@ function createArcyInternals(internalOptions = {}) {
4630
4637
  getConfig: () => bootstrap?.config() ?? null,
4631
4638
  selectLocale,
4632
4639
  getShellState: () => shellState,
4633
- getTokens: () => tokens
4640
+ getTokens: () => tokens,
4641
+ getWidgetChrome: () => readWidgetChrome()
4634
4642
  };
4635
4643
  }
4636
4644
 
@@ -4709,7 +4717,7 @@ var bundledChunks = {
4709
4717
  cdnBase: null,
4710
4718
  loadChat: (win, timeoutMs, setTimeoutImpl) => importChunk(
4711
4719
  win,
4712
- () => import('./chat-BK57WIAA.js'),
4720
+ () => import('./chat-HNE6525R.js'),
4713
4721
  CHAT_GLOBAL,
4714
4722
  CHAT_CONTRACT,
4715
4723
  "chat panel",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcy.js",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "ARCY — the universal JavaScript utility for embedding an AI agent that talks to, learns from, and acts on behalf of your users.",
5
5
  "license": "MIT",
6
6
  "type": "module",