made-refine 0.2.0 → 0.2.1-beta.1

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/README.md CHANGED
@@ -31,7 +31,7 @@ This detects your framework, installs the package, previews file changes, and ap
31
31
  - Renders inside Shadow DOM for full CSS isolation from your app
32
32
  - Babel/Vite plugin adds source location metadata to every JSX element
33
33
  - Hooks into React DevTools fiber tree for component name resolution
34
- - Built-in MCP server enables hands-free agent workflows
34
+ - Integrates with the desktop app MCP broker for hands-free agent workflows
35
35
 
36
36
  ## Supported frameworks
37
37
 
package/dist/cli.cjs CHANGED
@@ -8435,185 +8435,8 @@ function installPackage(cwd) {
8435
8435
  console.log(import_picocolors.default.dim(` ${cmd}`));
8436
8436
  }
8437
8437
  }
8438
- var BABEL_JSON_CONFIG_FILES = [".babelrc", ".babelrc.json", "babel.config.json"];
8439
- var BABEL_JS_CONFIG_FILES = [
8440
- ".babelrc.js",
8441
- ".babelrc.cjs",
8442
- ".babelrc.mjs",
8443
- "babel.config.js",
8444
- "babel.config.cjs",
8445
- "babel.config.mjs"
8446
- ];
8447
- function findBabelConfigFile(cwd) {
8448
- for (const file of BABEL_JSON_CONFIG_FILES) {
8449
- const absolutePath = import_path2.default.join(cwd, file);
8450
- if (import_fs2.default.existsSync(absolutePath)) {
8451
- return {
8452
- absolutePath,
8453
- relativePath: file,
8454
- kind: "json"
8455
- };
8456
- }
8457
- }
8458
- for (const file of BABEL_JS_CONFIG_FILES) {
8459
- const absolutePath = import_path2.default.join(cwd, file);
8460
- if (import_fs2.default.existsSync(absolutePath)) {
8461
- return {
8462
- absolutePath,
8463
- relativePath: file,
8464
- kind: "js"
8465
- };
8466
- }
8467
- }
8468
- const packageJsonPath = import_path2.default.join(cwd, "package.json");
8469
- if (import_fs2.default.existsSync(packageJsonPath)) {
8470
- try {
8471
- const packageJson = JSON.parse(import_fs2.default.readFileSync(packageJsonPath, "utf-8"));
8472
- if (packageJson.babel !== void 0) {
8473
- return {
8474
- absolutePath: packageJsonPath,
8475
- relativePath: "package.json#babel",
8476
- kind: "package-json"
8477
- };
8478
- }
8479
- } catch {
8480
- }
8481
- }
8482
- return null;
8483
- }
8484
- function isMadeRefinePlugin(plugin) {
8485
- if (typeof plugin === "string") {
8486
- return plugin === "made-refine/babel";
8487
- }
8488
- if (Array.isArray(plugin) && typeof plugin[0] === "string") {
8489
- return plugin[0] === "made-refine/babel";
8490
- }
8491
- return false;
8492
- }
8493
- function hasMadeRefinePlugin(plugins) {
8494
- if (!Array.isArray(plugins)) return false;
8495
- return plugins.some((plugin) => isMadeRefinePlugin(plugin));
8496
- }
8497
- function ensureMadeRefineInDevelopmentEnv(config) {
8498
- if (hasMadeRefinePlugin(config.plugins)) {
8499
- return "already-configured";
8500
- }
8501
- const existingEnv = config.env;
8502
- if (existingEnv !== void 0 && (typeof existingEnv !== "object" || existingEnv === null || Array.isArray(existingEnv))) {
8503
- return "unsupported-shape";
8504
- }
8505
- if (!config.env) {
8506
- config.env = {};
8507
- }
8508
- const env = config.env;
8509
- const existingDevelopment = env.development;
8510
- if (existingDevelopment !== void 0 && (typeof existingDevelopment !== "object" || existingDevelopment === null || Array.isArray(existingDevelopment))) {
8511
- return "unsupported-shape";
8512
- }
8513
- if (!env.development) {
8514
- env.development = {};
8515
- }
8516
- const development = env.development;
8517
- if (hasMadeRefinePlugin(development.plugins)) {
8518
- return "already-configured";
8519
- }
8520
- if (development.plugins === void 0) {
8521
- development.plugins = ["made-refine/babel"];
8522
- return "updated";
8523
- }
8524
- if (!Array.isArray(development.plugins)) {
8525
- return "unsupported-shape";
8526
- }
8527
- development.plugins = [...development.plugins, "made-refine/babel"];
8528
- return "updated";
8529
- }
8530
- function printManualNextBabelInstructions() {
8531
- console.log(
8532
- import_picocolors.default.dim(
8533
- " env: { development: { plugins: ['made-refine/babel'] } }\n (or add 'made-refine/babel' in your existing Babel plugin list)"
8534
- )
8535
- );
8536
- }
8537
- function configureNextBabel(cwd) {
8538
- const configFile = findBabelConfigFile(cwd);
8539
- if (!configFile) {
8540
- console.log(
8541
- import_picocolors.default.yellow(" \u26A0 No existing Babel config found \u2014 skipping Babel config to preserve SWC/Turbopack defaults.")
8542
- );
8543
- console.log(import_picocolors.default.dim(" Source detection will use React fiber fallback (less precise than Babel attributes)."));
8544
- return;
8545
- }
8546
- if (configFile.kind === "js") {
8547
- console.log(import_picocolors.default.yellow(` \u26A0 Found ${configFile.relativePath} (JS Babel config) \u2014 verify/add plugin manually:`));
8548
- printManualNextBabelInstructions();
8549
- return;
8550
- }
8551
- if (configFile.kind === "package-json") {
8552
- let packageJson;
8553
- try {
8554
- packageJson = JSON.parse(import_fs2.default.readFileSync(configFile.absolutePath, "utf-8"));
8555
- } catch {
8556
- console.log(import_picocolors.default.yellow(" \u26A0 Could not parse package.json \u2014 add plugin manually:"));
8557
- printManualNextBabelInstructions();
8558
- return;
8559
- }
8560
- if (typeof packageJson !== "object" || packageJson === null || Array.isArray(packageJson)) {
8561
- console.log(import_picocolors.default.yellow(" \u26A0 package.json has unsupported shape \u2014 add plugin manually:"));
8562
- printManualNextBabelInstructions();
8563
- return;
8564
- }
8565
- const pkg = packageJson;
8566
- if (typeof pkg.babel !== "object" || pkg.babel === null || Array.isArray(pkg.babel)) {
8567
- console.log(import_picocolors.default.yellow(" \u26A0 package.json#babel has unsupported shape \u2014 add plugin manually:"));
8568
- printManualNextBabelInstructions();
8569
- return;
8570
- }
8571
- const result2 = ensureMadeRefineInDevelopmentEnv(pkg.babel);
8572
- if (result2 === "already-configured") {
8573
- console.log(import_picocolors.default.dim(" package.json#babel \u2014 already configured"));
8574
- return;
8575
- }
8576
- if (result2 === "unsupported-shape") {
8577
- console.log(import_picocolors.default.yellow(" \u26A0 package.json#babel has unsupported shape \u2014 add plugin manually:"));
8578
- printManualNextBabelInstructions();
8579
- return;
8580
- }
8581
- import_fs2.default.writeFileSync(configFile.absolutePath, `${JSON.stringify(pkg, null, 2)}
8582
- `, "utf-8");
8583
- console.log(import_picocolors.default.green(' \u2713 Updated package.json#babel (added "made-refine/babel" in development env)'));
8584
- return;
8585
- }
8586
- const content = import_fs2.default.readFileSync(configFile.absolutePath, "utf-8");
8587
- let parsed;
8588
- try {
8589
- parsed = JSON.parse(content);
8590
- } catch {
8591
- console.log(import_picocolors.default.yellow(` \u26A0 Could not parse ${configFile.relativePath} as JSON \u2014 add plugin manually:`));
8592
- printManualNextBabelInstructions();
8593
- return;
8594
- }
8595
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
8596
- console.log(import_picocolors.default.yellow(` \u26A0 ${configFile.relativePath} has unsupported shape \u2014 add plugin manually:`));
8597
- printManualNextBabelInstructions();
8598
- return;
8599
- }
8600
- const result = ensureMadeRefineInDevelopmentEnv(parsed);
8601
- if (result === "already-configured") {
8602
- console.log(import_picocolors.default.dim(` ${configFile.relativePath} \u2014 already configured`));
8603
- return;
8604
- }
8605
- if (result === "unsupported-shape") {
8606
- console.log(import_picocolors.default.yellow(` \u26A0 ${configFile.relativePath} has unsupported shape \u2014 add plugin manually:`));
8607
- printManualNextBabelInstructions();
8608
- return;
8609
- }
8610
- import_fs2.default.writeFileSync(configFile.absolutePath, `${JSON.stringify(parsed, null, 2)}
8611
- `, "utf-8");
8612
- console.log(import_picocolors.default.green(` \u2713 Updated ${configFile.relativePath} (added "made-refine/babel" in development env)`));
8613
- }
8614
8438
  async function setupNextJs(cwd) {
8615
8439
  console.log(import_picocolors.default.bold("\nConfiguring for Next.js...\n"));
8616
- configureNextBabel(cwd);
8617
8440
  const preloadSrc = import_path2.default.join(cwd, "node_modules/made-refine/dist/preload/preload.js");
8618
8441
  const publicDir = import_path2.default.join(cwd, "public");
8619
8442
  const preloadDest = import_path2.default.join(publicDir, "made-refine-preload.js");
package/dist/index.js CHANGED
@@ -2425,44 +2425,335 @@ function hslToRgb(h, s, l) {
2425
2425
  }
2426
2426
 
2427
2427
  // src/mcp-client.ts
2428
- var MCP_BASE = "http://127.0.0.1:4747";
2429
- var cachedToken = null;
2430
- async function getSessionToken(forceRefresh = false) {
2431
- if (!forceRefresh && cachedToken) return cachedToken;
2428
+ var PROTOCOL_VERSION = 1;
2429
+ var BOOTSTRAP_TIMEOUT_MS = 2500;
2430
+ var REQUEST_TIMEOUT_MS = 3e3;
2431
+ var SESSION_EXPIRY_SKEW_MS = 5e3;
2432
+ var CLIENT_NAME = "made-refine";
2433
+ var DEFAULT_CLIENT_VERSION = "unknown";
2434
+ var BOOTSTRAP_ENV_KEYS = [
2435
+ "MADE_REFINE_MCP_BOOTSTRAP_URL",
2436
+ "VITE_MADE_REFINE_MCP_BOOTSTRAP_URL",
2437
+ "NEXT_PUBLIC_MADE_REFINE_MCP_BOOTSTRAP_URL"
2438
+ ];
2439
+ var CLIENT_VERSION_ENV_KEYS = [
2440
+ "MADE_REFINE_VERSION",
2441
+ "VITE_MADE_REFINE_VERSION",
2442
+ "NEXT_PUBLIC_MADE_REFINE_VERSION"
2443
+ ];
2444
+ var cachedSession = null;
2445
+ function getTimeoutSignal(timeoutMs) {
2446
+ const timeout = AbortSignal.timeout;
2447
+ return typeof timeout === "function" ? timeout(timeoutMs) : void 0;
2448
+ }
2449
+ function getRuntimeMcpConfig() {
2450
+ if (typeof window === "undefined") return null;
2451
+ const config = window.__MADE_REFINE_CONFIG__;
2452
+ const bootstrapUrl = config?.mcp?.bootstrapUrl ?? config?.mcpBootstrapUrl ?? window.__MADE_REFINE_MCP_BOOTSTRAP_URL__;
2453
+ if (!config?.mcp && typeof bootstrapUrl !== "string") return null;
2454
+ return {
2455
+ ...config?.mcp ?? {},
2456
+ ...typeof bootstrapUrl === "string" ? { bootstrapUrl } : {}
2457
+ };
2458
+ }
2459
+ function toNonEmptyString(value) {
2460
+ if (typeof value !== "string") return null;
2461
+ const trimmed = value.trim();
2462
+ return trimmed.length > 0 ? trimmed : null;
2463
+ }
2464
+ function getStaticProcessEnvValue(key) {
2465
+ switch (key) {
2466
+ case "MADE_REFINE_MCP_BOOTSTRAP_URL":
2467
+ return toNonEmptyString(typeof process !== "undefined" ? process.env?.MADE_REFINE_MCP_BOOTSTRAP_URL : void 0);
2468
+ case "VITE_MADE_REFINE_MCP_BOOTSTRAP_URL":
2469
+ return toNonEmptyString(typeof process !== "undefined" ? process.env?.VITE_MADE_REFINE_MCP_BOOTSTRAP_URL : void 0);
2470
+ case "NEXT_PUBLIC_MADE_REFINE_MCP_BOOTSTRAP_URL":
2471
+ return toNonEmptyString(typeof process !== "undefined" ? process.env?.NEXT_PUBLIC_MADE_REFINE_MCP_BOOTSTRAP_URL : void 0);
2472
+ case "MADE_REFINE_VERSION":
2473
+ return toNonEmptyString(typeof process !== "undefined" ? process.env?.MADE_REFINE_VERSION : void 0);
2474
+ case "VITE_MADE_REFINE_VERSION":
2475
+ return toNonEmptyString(typeof process !== "undefined" ? process.env?.VITE_MADE_REFINE_VERSION : void 0);
2476
+ case "NEXT_PUBLIC_MADE_REFINE_VERSION":
2477
+ return toNonEmptyString(typeof process !== "undefined" ? process.env?.NEXT_PUBLIC_MADE_REFINE_VERSION : void 0);
2478
+ default:
2479
+ return null;
2480
+ }
2481
+ }
2482
+ function getDynamicProcessEnvValue(keys) {
2483
+ const processLike = globalThis.process;
2484
+ const env = processLike?.env;
2485
+ if (!env) return null;
2486
+ for (const key of keys) {
2487
+ const value = toNonEmptyString(env[key]);
2488
+ if (value) return value;
2489
+ }
2490
+ return null;
2491
+ }
2492
+ function getEnvValue(keys) {
2493
+ for (const key of keys) {
2494
+ const processValue = getStaticProcessEnvValue(key);
2495
+ if (processValue) return processValue;
2496
+ }
2497
+ return getDynamicProcessEnvValue(keys);
2498
+ }
2499
+ function normalizeUrl(value) {
2500
+ if (typeof value !== "string") return null;
2501
+ const trimmed = value.trim();
2502
+ if (!trimmed) return null;
2503
+ if (/^https?:\/\//i.test(trimmed)) {
2504
+ return trimmed.replace(/\/+$/, "");
2505
+ }
2506
+ if (typeof window === "undefined" || !window.location?.origin) return null;
2432
2507
  try {
2433
- const res = await fetch(`${MCP_BASE}/api/health`, { signal: AbortSignal.timeout(2e3) });
2434
- if (!res.ok) return null;
2435
- const data = await res.json();
2436
- cachedToken = typeof data.sessionToken === "string" ? data.sessionToken : null;
2437
- return cachedToken;
2508
+ return new URL(trimmed, window.location.origin).toString().replace(/\/+$/, "");
2438
2509
  } catch {
2439
2510
  return null;
2440
2511
  }
2441
2512
  }
2442
- async function postWithSessionToken(path, payload) {
2443
- const send = async (token2) => {
2513
+ function normalizeBootstrapUrl(value) {
2514
+ const normalized = normalizeUrl(value);
2515
+ if (!normalized) return null;
2516
+ try {
2517
+ const url = new URL(normalized);
2518
+ const normalizedPathname = url.pathname.replace(/\/+$/, "");
2519
+ url.pathname = normalizedPathname.endsWith("/v1/bootstrap") ? normalizedPathname : `${normalizedPathname}/v1/bootstrap`;
2520
+ return url.toString();
2521
+ } catch {
2522
+ return normalized.endsWith("/v1/bootstrap") ? normalized : `${normalized}/v1/bootstrap`;
2523
+ }
2524
+ }
2525
+ function toSafeBootstrapUrl(value) {
2526
+ const normalized = normalizeBootstrapUrl(value);
2527
+ if (!normalized) return null;
2528
+ return isLoopbackHttpUrl(normalized) ? normalized : null;
2529
+ }
2530
+ function joinUrl(base, path) {
2531
+ return `${base.replace(/\/+$/, "")}${path}`;
2532
+ }
2533
+ function readString(record, key) {
2534
+ const value = record?.[key];
2535
+ if (typeof value !== "string") return null;
2536
+ const trimmed = value.trim();
2537
+ return trimmed.length > 0 ? trimmed : null;
2538
+ }
2539
+ function parseExpiresAt(value) {
2540
+ if (typeof value !== "string") return null;
2541
+ const timestamp = Date.parse(value);
2542
+ return Number.isFinite(timestamp) ? timestamp : null;
2543
+ }
2544
+ function readNumber(record, key) {
2545
+ const value = record?.[key];
2546
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
2547
+ return value;
2548
+ }
2549
+ function isLoopbackIpv4(hostname) {
2550
+ if (!/^127(?:\.\d{1,3}){3}$/.test(hostname)) return false;
2551
+ const segments = hostname.split(".");
2552
+ return segments.every((segment) => {
2553
+ const value = Number(segment);
2554
+ return Number.isInteger(value) && value >= 0 && value <= 255;
2555
+ });
2556
+ }
2557
+ function isLoopbackHostname(hostname) {
2558
+ if (hostname === "localhost" || hostname.endsWith(".localhost")) return true;
2559
+ if (hostname === "::1" || hostname === "[::1]") return true;
2560
+ return isLoopbackIpv4(hostname);
2561
+ }
2562
+ function isLoopbackHttpUrl(value) {
2563
+ try {
2564
+ const url = new URL(value);
2565
+ if (url.protocol !== "http:" && url.protocol !== "https:") return false;
2566
+ return isLoopbackHostname(url.hostname);
2567
+ } catch {
2568
+ return false;
2569
+ }
2570
+ }
2571
+ function buildBootstrapRequestBody(runtimeConfig) {
2572
+ const locationPath = typeof window !== "undefined" ? window.location.pathname : "";
2573
+ const locationOrigin = typeof window !== "undefined" ? window.location.origin : null;
2574
+ return {
2575
+ protocolVersion: PROTOCOL_VERSION,
2576
+ projectFingerprint: {
2577
+ path: runtimeConfig?.projectFingerprint?.path || locationPath || "unknown",
2578
+ gitRemoteHash: runtimeConfig?.projectFingerprint?.gitRemoteHash ?? null
2579
+ },
2580
+ ...runtimeConfig?.workspaceId ? {
2581
+ workspaceId: runtimeConfig.workspaceId
2582
+ } : {},
2583
+ client: {
2584
+ name: CLIENT_NAME,
2585
+ version: runtimeConfig?.clientVersion ?? getEnvValue(CLIENT_VERSION_ENV_KEYS) ?? DEFAULT_CLIENT_VERSION,
2586
+ origin: locationOrigin
2587
+ }
2588
+ };
2589
+ }
2590
+ function resolveBootstrapUrl() {
2591
+ const runtimeConfig = getRuntimeMcpConfig();
2592
+ const runtimeUrl = toSafeBootstrapUrl(runtimeConfig?.bootstrapUrl);
2593
+ if (runtimeUrl) return runtimeUrl;
2594
+ const envUrl = toSafeBootstrapUrl(getEnvValue(BOOTSTRAP_ENV_KEYS));
2595
+ if (envUrl) return envUrl;
2596
+ return null;
2597
+ }
2598
+ function isSessionUsable(session, bootstrapUrl) {
2599
+ if (!session) return false;
2600
+ if (session.bootstrapUrl !== bootstrapUrl) return false;
2601
+ if (session.expiresAt == null) return true;
2602
+ return Date.now() < session.expiresAt - SESSION_EXPIRY_SKEW_MS;
2603
+ }
2604
+ async function readJsonRecord(response) {
2605
+ try {
2606
+ const data = await response.json();
2607
+ if (!data || typeof data !== "object") return null;
2608
+ return data;
2609
+ } catch {
2610
+ return null;
2611
+ }
2612
+ }
2613
+ async function bootstrapSession(force = false) {
2614
+ const bootstrapUrl = resolveBootstrapUrl();
2615
+ if (!bootstrapUrl) {
2616
+ cachedSession = null;
2617
+ return null;
2618
+ }
2619
+ if (!force && isSessionUsable(cachedSession, bootstrapUrl)) {
2620
+ return cachedSession;
2621
+ }
2622
+ const runtimeConfig = getRuntimeMcpConfig();
2623
+ try {
2624
+ const response = await fetch(bootstrapUrl, {
2625
+ method: "POST",
2626
+ headers: { "Content-Type": "application/json" },
2627
+ body: JSON.stringify(buildBootstrapRequestBody(runtimeConfig)),
2628
+ signal: getTimeoutSignal(BOOTSTRAP_TIMEOUT_MS)
2629
+ });
2630
+ if (!response.ok) {
2631
+ cachedSession = null;
2632
+ return null;
2633
+ }
2634
+ const data = await readJsonRecord(response);
2635
+ const protocolVersion = readNumber(data, "protocolVersion");
2636
+ if (protocolVersion !== PROTOCOL_VERSION) {
2637
+ cachedSession = null;
2638
+ return null;
2639
+ }
2640
+ const ingestBaseUrl = normalizeUrl(readString(data, "ingestBaseUrl"));
2641
+ if (!ingestBaseUrl || !isLoopbackHttpUrl(ingestBaseUrl)) {
2642
+ cachedSession = null;
2643
+ return null;
2644
+ }
2645
+ const nextSession = {
2646
+ bootstrapUrl,
2647
+ ingestBaseUrl,
2648
+ serverInstanceId: readString(data, "serverInstanceId"),
2649
+ projectId: readString(data, "projectId"),
2650
+ sessionId: readString(data, "sessionId"),
2651
+ accessToken: readString(data, "accessToken"),
2652
+ expiresAt: parseExpiresAt(data?.expiresAt)
2653
+ };
2654
+ cachedSession = nextSession;
2655
+ return nextSession;
2656
+ } catch {
2657
+ cachedSession = null;
2658
+ return null;
2659
+ }
2660
+ }
2661
+ async function refreshSessionToken(session) {
2662
+ try {
2444
2663
  const headers = { "Content-Type": "application/json" };
2445
- if (token2) headers["X-Session-Token"] = token2;
2446
- return fetch(`${MCP_BASE}${path}`, {
2664
+ if (session.accessToken) {
2665
+ headers.Authorization = `Bearer ${session.accessToken}`;
2666
+ }
2667
+ const response = await fetch(joinUrl(session.ingestBaseUrl, "/v1/sessions/refresh"), {
2447
2668
  method: "POST",
2448
2669
  headers,
2449
- body: JSON.stringify(payload)
2670
+ body: JSON.stringify({
2671
+ protocolVersion: PROTOCOL_VERSION,
2672
+ projectId: session.projectId,
2673
+ sessionId: session.sessionId
2674
+ }),
2675
+ signal: getTimeoutSignal(REQUEST_TIMEOUT_MS)
2450
2676
  });
2677
+ if (response.status === 404 || response.status === 405) {
2678
+ return null;
2679
+ }
2680
+ if (!response.ok) {
2681
+ return null;
2682
+ }
2683
+ const data = await readJsonRecord(response);
2684
+ const nextToken = readString(data, "accessToken");
2685
+ if (!nextToken) {
2686
+ return null;
2687
+ }
2688
+ const refreshedSession = {
2689
+ ...session,
2690
+ accessToken: nextToken,
2691
+ expiresAt: parseExpiresAt(data?.expiresAt) ?? session.expiresAt
2692
+ };
2693
+ cachedSession = refreshedSession;
2694
+ return refreshedSession;
2695
+ } catch {
2696
+ return null;
2697
+ }
2698
+ }
2699
+ function createIdempotencyKey() {
2700
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2701
+ return crypto.randomUUID();
2702
+ }
2703
+ const timestamp = Date.now().toString(36);
2704
+ const random = Math.random().toString(36).slice(2, 12);
2705
+ return `${timestamp}-${random}`;
2706
+ }
2707
+ async function sendAnnotationRequest(session, path, payload, idempotencyKey) {
2708
+ const headers = {
2709
+ "Content-Type": "application/json",
2710
+ "X-Idempotency-Key": idempotencyKey
2451
2711
  };
2452
- let token = await getSessionToken();
2453
- let res = await send(token);
2454
- if (res.status === 403) {
2455
- cachedToken = null;
2456
- token = await getSessionToken(true);
2457
- res = await send(token);
2712
+ if (session.accessToken) {
2713
+ headers.Authorization = `Bearer ${session.accessToken}`;
2714
+ }
2715
+ return fetch(joinUrl(session.ingestBaseUrl, path), {
2716
+ method: "POST",
2717
+ headers,
2718
+ body: JSON.stringify(payload),
2719
+ signal: getTimeoutSignal(REQUEST_TIMEOUT_MS)
2720
+ });
2721
+ }
2722
+ async function toClientResponse(response) {
2723
+ const data = await readJsonRecord(response);
2724
+ const bodyOk = data?.ok;
2725
+ const parsedOk = typeof bodyOk === "boolean" ? bodyOk : response.ok;
2726
+ return {
2727
+ ok: parsedOk && response.ok,
2728
+ id: readString(data, "id") ?? ""
2729
+ };
2730
+ }
2731
+ async function postWithSessionToken(path, payload) {
2732
+ const idempotencyKey = createIdempotencyKey();
2733
+ let session = await bootstrapSession();
2734
+ if (!session) return { ok: false, id: "" };
2735
+ let response;
2736
+ try {
2737
+ response = await sendAnnotationRequest(session, path, payload, idempotencyKey);
2738
+ } catch {
2739
+ return { ok: false, id: "" };
2740
+ }
2741
+ if (response.status === 401 || response.status === 403) {
2742
+ session = await refreshSessionToken(session) ?? await bootstrapSession(true);
2743
+ if (!session) return { ok: false, id: "" };
2744
+ try {
2745
+ response = await sendAnnotationRequest(session, path, payload, idempotencyKey);
2746
+ } catch {
2747
+ return { ok: false, id: "" };
2748
+ }
2458
2749
  }
2459
- return res.json();
2750
+ return toClientResponse(response);
2460
2751
  }
2461
2752
  async function sendEditToAgent(edit) {
2462
- return postWithSessionToken("/api/edit", edit);
2753
+ return postWithSessionToken("/v1/annotations/edit", edit);
2463
2754
  }
2464
2755
  async function sendCommentToAgent(comment) {
2465
- return postWithSessionToken("/api/comment", comment);
2756
+ return postWithSessionToken("/v1/annotations/comment", comment);
2466
2757
  }
2467
2758
 
2468
2759
  // src/provider.tsx