arcy.js 0.1.1 → 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.
@@ -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
 
@@ -2437,14 +2438,6 @@ var MAIN_CLASS = "arcy-chat-main";
2437
2438
  var MARK_CLASS = "arcy-chat-mark";
2438
2439
  var MARK_LINK_CLASS = "arcy-chat-mark-link";
2439
2440
  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
2441
  var ARCY_HOME_URL = "https://arcyai.com";
2449
2442
  var WELCOME_CLASS = "arcy-chat-welcome";
2450
2443
  var STARTER_CLASS = "arcy-chat-starter";
@@ -3864,4 +3857,4 @@ if (typeof window !== "undefined") {
3864
3857
  }
3865
3858
  }
3866
3859
 
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 };
3860
+ 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;
@@ -2964,7 +2984,7 @@ function headers(sessionToken) {
2964
2984
  }
2965
2985
  async function fetchFlowCatalog(options) {
2966
2986
  const {
2967
- apiBase = DEFAULT_API_BASE3,
2987
+ apiBase = DEFAULT_API_BASE4,
2968
2988
  sessionToken,
2969
2989
  sessionId,
2970
2990
  setTimeoutImpl = (fn, ms) => setTimeout(fn, ms),
@@ -3001,7 +3021,7 @@ async function fetchFlowCatalog(options) {
3001
3021
  }
3002
3022
  async function fetchFlowRun(flowCvid, options) {
3003
3023
  const {
3004
- apiBase = DEFAULT_API_BASE3,
3024
+ apiBase = DEFAULT_API_BASE4,
3005
3025
  sessionToken,
3006
3026
  sessionId,
3007
3027
  setTimeoutImpl = (fn, ms) => setTimeout(fn, ms),
@@ -3040,10 +3060,10 @@ async function fetchFlowRun(flowCvid, options) {
3040
3060
  reason: "network"
3041
3061
  });
3042
3062
  }
3043
- var DEFAULT_API_BASE3, FLOW_CATALOG_PATH, FLOW_RUN_PATH, FLOW_FETCH_TIMEOUT_MS;
3063
+ var DEFAULT_API_BASE4, FLOW_CATALOG_PATH, FLOW_RUN_PATH, FLOW_FETCH_TIMEOUT_MS;
3044
3064
  var init_api = __esm({
3045
3065
  "src/flow/api.ts"() {
3046
- DEFAULT_API_BASE3 = "https://api.arcyai.com";
3066
+ DEFAULT_API_BASE4 = "https://api.arcyai.com";
3047
3067
  FLOW_CATALOG_PATH = "/api/v1/sdk/flows/catalog";
3048
3068
  FLOW_RUN_PATH = "/api/v1/sdk/flows";
3049
3069
  FLOW_FETCH_TIMEOUT_MS = 8e3;
@@ -3139,7 +3159,7 @@ function headers2(sessionToken) {
3139
3159
  }
3140
3160
  async function postAgentQuery(options) {
3141
3161
  const {
3142
- apiBase = DEFAULT_API_BASE4,
3162
+ apiBase = DEFAULT_API_BASE5,
3143
3163
  publicKey,
3144
3164
  sessionId,
3145
3165
  sessionToken,
@@ -3196,10 +3216,10 @@ async function postAgentQuery(options) {
3196
3216
  })();
3197
3217
  return bounded2(attempt, timeoutMs, setTimeoutImpl, { ok: false, reason: "network" });
3198
3218
  }
3199
- var DEFAULT_API_BASE4, AGENT_QUERY_PATH, AGENT_QUERY_TIMEOUT_MS, CAP_DENIAL_REASONS;
3219
+ var DEFAULT_API_BASE5, AGENT_QUERY_PATH, AGENT_QUERY_TIMEOUT_MS, CAP_DENIAL_REASONS;
3200
3220
  var init_chat_api = __esm({
3201
3221
  "src/shell/chat-api.ts"() {
3202
- DEFAULT_API_BASE4 = "https://api.arcyai.com";
3222
+ DEFAULT_API_BASE5 = "https://api.arcyai.com";
3203
3223
  AGENT_QUERY_PATH = "/api/v1/sdk/agent/query";
3204
3224
  AGENT_QUERY_TIMEOUT_MS = 2e4;
3205
3225
  CAP_DENIAL_REASONS = /* @__PURE__ */ new Set([
@@ -3217,14 +3237,14 @@ var init_chat_api = __esm({
3217
3237
  function web(family, fallback = SANS_FALLBACK) {
3218
3238
  return { family, fallback, stack: `"${family}", ${fallback}` };
3219
3239
  }
3220
- function fontFaceCss(key, assetBase = DEFAULT_API_BASE4) {
3240
+ function fontFaceCss(key, assetBase = DEFAULT_API_BASE5) {
3221
3241
  const entry = CATALOG[key];
3222
3242
  if (!entry?.family) return "";
3223
3243
  return SUBSETS.map(
3224
3244
  ([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
3245
  ).join("\n");
3226
3246
  }
3227
- function applyFont(host, doc, assetBase = DEFAULT_API_BASE4) {
3247
+ function applyFont(host, doc, assetBase = DEFAULT_API_BASE5) {
3228
3248
  try {
3229
3249
  const key = host.style.getPropertyValue(FONT_KEY_PROPERTY).trim();
3230
3250
  const entry = key ? CATALOG[key] : void 0;
@@ -3351,7 +3371,7 @@ function toRows(conversations, imageLabel, currentConversationId) {
3351
3371
  }
3352
3372
  async function fetchConversations(options) {
3353
3373
  const {
3354
- apiBase = DEFAULT_API_BASE4,
3374
+ apiBase = DEFAULT_API_BASE5,
3355
3375
  sessionToken,
3356
3376
  visitorId,
3357
3377
  setTimeoutImpl = (fn, ms) => setTimeout(fn, ms),
@@ -3453,7 +3473,7 @@ function readMessages(body) {
3453
3473
  }
3454
3474
  async function fetchConversationMessages(options) {
3455
3475
  const {
3456
- apiBase = DEFAULT_API_BASE4,
3476
+ apiBase = DEFAULT_API_BASE5,
3457
3477
  sessionToken,
3458
3478
  conversationId,
3459
3479
  visitorId,
@@ -3521,7 +3541,7 @@ function feedbackPath(conversationId, messageId) {
3521
3541
  }
3522
3542
  async function postAnswerFeedback(options) {
3523
3543
  const {
3524
- apiBase = DEFAULT_API_BASE4,
3544
+ apiBase = DEFAULT_API_BASE5,
3525
3545
  sessionToken,
3526
3546
  conversationId,
3527
3547
  messageId,
@@ -3695,7 +3715,7 @@ async function uploadImage(file, alreadyAttached, options) {
3695
3715
  const validation = validateFile(file, alreadyAttached);
3696
3716
  if (!validation.ok) return { ok: false, reason: validation.reason };
3697
3717
  const {
3698
- apiBase = DEFAULT_API_BASE4,
3718
+ apiBase = DEFAULT_API_BASE5,
3699
3719
  sessionToken,
3700
3720
  env,
3701
3721
  timeoutMs = UPLOAD_TIMEOUT_MS
@@ -3749,7 +3769,7 @@ async function uploadImage(file, alreadyAttached, options) {
3749
3769
  });
3750
3770
  }
3751
3771
  async function discardUpload(objectKey, options) {
3752
- const { apiBase = DEFAULT_API_BASE4, sessionToken, fetchImpl } = options;
3772
+ const { apiBase = DEFAULT_API_BASE5, sessionToken, fetchImpl } = options;
3753
3773
  if (!fetchImpl || !sessionToken || !objectKey) return false;
3754
3774
  try {
3755
3775
  const response = await fetchImpl(`${apiBase}${DISCARD_PATH}`, {
@@ -3806,14 +3826,6 @@ __export(chat_exports, {
3806
3826
  mount: () => mount,
3807
3827
  resolveImageUrl: () => resolveImageUrl
3808
3828
  });
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
3829
  function icon(doc, path, size2 = 17) {
3818
3830
  const svg = doc.createElementNS(SVG_NS5, "svg");
3819
3831
  svg.setAttribute("viewBox", "0 0 24 24");
@@ -3945,7 +3957,7 @@ function mount(context) {
3945
3957
  context.bar.setDisabled(true);
3946
3958
  transcript.setPending(true);
3947
3959
  void postAgentQuery({
3948
- apiBase: context.apiBase ?? DEFAULT_API_BASE4,
3960
+ apiBase: context.apiBase ?? DEFAULT_API_BASE5,
3949
3961
  publicKey: context.publicKey ?? "",
3950
3962
  sessionId: context.getSessionId?.() ?? "",
3951
3963
  sessionToken: context.getSessionToken?.() ?? "",
@@ -4775,6 +4787,7 @@ var init_chat = __esm({
4775
4787
  init_api();
4776
4788
  init_renderable_flows();
4777
4789
  init_chat_api();
4790
+ init_image_url();
4778
4791
  init_fonts();
4779
4792
  init_conversation_list();
4780
4793
  init_conversation_messages();
@@ -11348,6 +11361,7 @@ init_chat_contract();
11348
11361
  // src/shell/tokens.ts
11349
11362
  init_chat_contract();
11350
11363
  init_host();
11364
+ init_image_url();
11351
11365
  init_warn();
11352
11366
  init_storage();
11353
11367
  var HEX = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
@@ -11515,13 +11529,12 @@ function applyTokens(host, tokens) {
11515
11529
  var TOKEN_KEY_PREFIX = "arcy.tokens.";
11516
11530
  var MAX_STORED = 4096;
11517
11531
  var MAX_NAME = 100;
11518
- var MAX_URL = 2048;
11519
11532
  function readIdentity(value) {
11520
11533
  const raw = object(value);
11521
11534
  if (!raw) return null;
11522
11535
  const name = typeof raw.name === "string" ? raw.name.slice(0, MAX_NAME) : "";
11523
11536
  const url = raw.logoUrl;
11524
- const logoUrl = typeof url === "string" && url.length <= MAX_URL && /^https:\/\//i.test(url) ? url : null;
11537
+ const logoUrl = isRenderableImageUrl(url) ? url : null;
11525
11538
  return { name, logoUrl };
11526
11539
  }
11527
11540
  function createTokenCache(token, raw = browserLocalStorage()) {
@@ -11553,6 +11566,7 @@ function createTokenCache(token, raw = browserLocalStorage()) {
11553
11566
  }
11554
11567
 
11555
11568
  // src/api.ts
11569
+ init_image_url();
11556
11570
  init_state2();
11557
11571
 
11558
11572
  // src/session/visit.ts
@@ -12219,22 +12233,34 @@ function createSessionStore({
12219
12233
  fill,
12220
12234
  windowMs = SESSION_WINDOW_MS
12221
12235
  }) {
12222
- function touch() {
12223
- const at = now();
12236
+ function alive(at) {
12224
12237
  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;
12238
+ if (existing && typeof existing.id === "string" && existing.id.length > 0 && typeof existing.seen === "number" && at - existing.seen < windowMs) {
12239
+ return existing;
12231
12240
  }
12241
+ return null;
12242
+ }
12243
+ function mint(at) {
12232
12244
  const id = ulid(at, fill);
12233
12245
  writeJson(store, key, { id, seen: at });
12234
12246
  return id;
12235
12247
  }
12248
+ function touch() {
12249
+ const at = now();
12250
+ const existing = alive(at);
12251
+ if (!existing) return mint(at);
12252
+ if (at - existing.seen >= TOUCH_WRITE_INTERVAL_MS) {
12253
+ writeJson(store, key, { id: existing.id, seen: at });
12254
+ }
12255
+ return existing.id;
12256
+ }
12257
+ function current() {
12258
+ const at = now();
12259
+ return alive(at)?.id ?? mint(at);
12260
+ }
12236
12261
  return {
12237
12262
  touch,
12263
+ current,
12238
12264
  peek: () => readJson(store, key),
12239
12265
  clear() {
12240
12266
  store.removeItem(key);
@@ -12251,7 +12277,7 @@ var FLUSH_INTERVAL_MS = 5e3;
12251
12277
  var MAX_EVENTS_PER_REQUEST = 100;
12252
12278
  var MAX_REQUEST_BYTES = 64 * 1024;
12253
12279
  var MAX_QUEUED_EVENTS = 1e3;
12254
- var DEFAULT_API_BASE2 = "https://api.arcyai.com";
12280
+ var DEFAULT_API_BASE3 = "https://api.arcyai.com";
12255
12281
  var TELEMETRY_PATH = "/api/v1/sdk/telemetry";
12256
12282
  function utf8Length(value) {
12257
12283
  let bytes = 0;
@@ -12287,7 +12313,7 @@ function chunkEvents(events) {
12287
12313
  function createTransport(options) {
12288
12314
  const {
12289
12315
  token,
12290
- apiBase = DEFAULT_API_BASE2,
12316
+ apiBase = DEFAULT_API_BASE3,
12291
12317
  fetchImpl,
12292
12318
  sendBeacon,
12293
12319
  setTimeoutImpl = (fn, ms) => setTimeout(fn, ms),
@@ -12684,7 +12710,7 @@ function createTelemetry(options) {
12684
12710
  if (typeof raw !== "string") return void 0;
12685
12711
  return normalizeRoute(raw, win?.location?.href) ?? void 0;
12686
12712
  }
12687
- const ownOrigin = (apiBase ?? DEFAULT_API_BASE2).replace(/\/+$/, "");
12713
+ const ownOrigin = (apiBase ?? DEFAULT_API_BASE3).replace(/\/+$/, "");
12688
12714
  let uninstallNetworkWatch = null;
12689
12715
  return {
12690
12716
  start() {
@@ -12761,7 +12787,7 @@ function createTelemetry(options) {
12761
12787
  capture(name, payload, fields2);
12762
12788
  },
12763
12789
  flush: () => transport.flush(false),
12764
- sessionId: () => session.touch(),
12790
+ sessionId: () => session.current(),
12765
12791
  resetSession: () => session.clear(),
12766
12792
  stopped: () => transport.stopped(),
12767
12793
  state: () => consent.state()
@@ -13078,16 +13104,12 @@ function createArcyInternals(internalOptions = {}) {
13078
13104
  const chrome = raw?.chrome && typeof raw.chrome === "object" && !Array.isArray(raw.chrome) ? { ...FALLBACK_CHROME, ...raw.chrome } : FALLBACK_CHROME;
13079
13105
  const welcomeIconUrl = raw?.welcomeIconUrl;
13080
13106
  const chatBarIconUrl = raw?.chatBarIconUrl;
13107
+ const apiBase = resolveApiBase();
13081
13108
  return {
13082
13109
  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,
13110
+ logoUrl: resolveImageUrl(identity2.logoUrl, apiBase),
13111
+ welcomeIconUrl: resolveImageUrl(welcomeIconUrl, apiBase),
13112
+ chatBarIconUrl: resolveImageUrl(chatBarIconUrl, apiBase),
13091
13113
  welcomeMessage: text(raw?.welcomeMessage),
13092
13114
  inputPlaceholder: text(raw?.inputPlaceholder),
13093
13115
  welcomeHeadline: text(raw?.welcomeHeadline),
@@ -13730,7 +13752,8 @@ function createArcyInternals(internalOptions = {}) {
13730
13752
  getConfig: () => bootstrap?.config() ?? null,
13731
13753
  selectLocale,
13732
13754
  getShellState: () => shellState,
13733
- getTokens: () => tokens
13755
+ getTokens: () => tokens,
13756
+ getWidgetChrome: () => readWidgetChrome()
13734
13757
  };
13735
13758
  }
13736
13759
 
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-IU4IJMGO.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.2",
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",