@tomflow/proflow-execution-browser-extension 0.1.12 → 0.1.13

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.
@@ -3,7 +3,7 @@ export const descriptor = {
3
3
  contractVersion: "1.0.0",
4
4
  moduleRef: "execution-browser-extension",
5
5
  packageName: "@tomflow/proflow-execution-browser-extension",
6
- moduleVersion: "0.1.12",
6
+ moduleVersion: "0.1.13",
7
7
  kind: "browser-extension",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
@@ -16,6 +16,10 @@ export const descriptor = {
16
16
  contractRef: "execution-browser-executor",
17
17
  version: "1.0.0",
18
18
  },
19
+ {
20
+ contractRef: "custom-gpt-web-provisioning",
21
+ version: "1.0.0",
22
+ },
19
23
  ],
20
24
  requires: [
21
25
  {
@@ -13912,6 +13912,7 @@ async function bootstrapManagedRuntimeConfig() {
13912
13912
  if (!isRecord(raw)) return;
13913
13913
  const managed = raw;
13914
13914
  const bridge = parseConfig(managed.proflowRuntimeBridge);
13915
+ const provisioning = parseConfig(managed.proflowProvisioningBridge);
13915
13916
  const task = parseConfig(managed.proflowTaskApplication);
13916
13917
  const approval = parseConfig(managed.proflowApprovalApplication);
13917
13918
  if (!bridge || !task || !approval) {
@@ -13919,6 +13920,7 @@ async function bootstrapManagedRuntimeConfig() {
13919
13920
  }
13920
13921
  await chrome.storage.local.set({
13921
13922
  proflowRuntimeBridge: bridge,
13923
+ ...provisioning ? { proflowProvisioningBridge: provisioning } : {},
13922
13924
  proflowTaskApplication: task,
13923
13925
  proflowApprovalApplication: approval
13924
13926
  });
@@ -13927,6 +13929,10 @@ async function bridgeConfig() {
13927
13929
  const stored = await chrome.storage.local.get("proflowRuntimeBridge");
13928
13930
  return parseConfig(stored.proflowRuntimeBridge);
13929
13931
  }
13932
+ async function provisioningBridgeConfig() {
13933
+ const stored = await chrome.storage.local.get("proflowProvisioningBridge");
13934
+ return parseConfig(stored.proflowProvisioningBridge);
13935
+ }
13930
13936
  async function taskApplicationConfig() {
13931
13937
  const stored = await chrome.storage.local.get("proflowTaskApplication");
13932
13938
  return parseConfig(stored.proflowTaskApplication);
@@ -14379,6 +14385,68 @@ async function executeCommand(command) {
14379
14385
  }
14380
14386
  throw new Error("BROWSER_PRIMITIVE_UNAVAILABLE");
14381
14387
  }
14388
+ function missingProvisioningReceiver(error46) {
14389
+ const message = error46 instanceof Error ? error46.message : String(error46);
14390
+ return message.includes("Could not establish connection") || message.includes("Receiving end does not exist");
14391
+ }
14392
+ function isEditorUrl(url2) {
14393
+ return url2 === "https://chatgpt.com/gpts/editor" || Boolean(url2?.startsWith("https://chatgpt.com/gpts/editor/"));
14394
+ }
14395
+ async function provisioningContentCommand(tabId, operation, request) {
14396
+ let receiverReloaded = false;
14397
+ for (let attempt = 0; attempt < 60; attempt += 1) {
14398
+ let response;
14399
+ try {
14400
+ response = await chrome.tabs.sendMessage(tabId, {
14401
+ type: "PROFLOW_PROVISIONING_COMMAND",
14402
+ operation,
14403
+ request
14404
+ });
14405
+ } catch (error46) {
14406
+ if (!receiverReloaded && missingProvisioningReceiver(error46)) {
14407
+ try {
14408
+ const tab = await chrome.tabs.get(tabId);
14409
+ if (tab.status === "complete" && isEditorUrl(tab.url)) {
14410
+ await chrome.tabs.reload(tabId);
14411
+ receiverReloaded = true;
14412
+ }
14413
+ } catch {
14414
+ }
14415
+ }
14416
+ if (attempt === 59) throw error46;
14417
+ await sleep(250);
14418
+ continue;
14419
+ }
14420
+ if (!isRecord(response) || response.ok !== true) {
14421
+ const detail = isRecord(response) && typeof response.error === "string" ? response.error : "PROVISIONING_CONTENT_FAILED";
14422
+ if ((detail === "PROVISIONING_SURFACE_NOT_READY" || detail === "GPT_EDITOR_CONFIGURE_SURFACE_NOT_READY") && attempt < 59) {
14423
+ await sleep(250);
14424
+ continue;
14425
+ }
14426
+ throw new Error(detail);
14427
+ }
14428
+ return response.value;
14429
+ }
14430
+ throw new Error("PROVISIONING_CONTENT_TIMEOUT");
14431
+ }
14432
+ async function executeProvisioningCommand(command) {
14433
+ if (!isRecord(command.request))
14434
+ throw new Error("PROVISIONING_COMMAND_INVALID");
14435
+ let editorUrl = "https://chatgpt.com/gpts/editor";
14436
+ if (command.type === "FINALIZE_CUSTOM_GPT_AUTH") {
14437
+ const carrierUrl = new URL(text(command.request.carrierUrl, "CARRIER_URL"));
14438
+ const match = /^\/g\/(g-[A-Za-z0-9_-]+)$/.exec(carrierUrl.pathname);
14439
+ if (carrierUrl.origin !== "https://chatgpt.com" || carrierUrl.username !== "" || carrierUrl.password !== "" || carrierUrl.search !== "" || carrierUrl.hash !== "" || !match?.[1])
14440
+ throw new Error("PROVISIONING_CARRIER_URL_INVALID");
14441
+ editorUrl = `https://chatgpt.com/gpts/editor/${match[1]}`;
14442
+ }
14443
+ const tab = await chrome.tabs.create({ url: editorUrl, active: true });
14444
+ return provisioningContentCommand(
14445
+ numeric(tab.id, "TAB_ID"),
14446
+ command.type,
14447
+ command.request
14448
+ );
14449
+ }
14382
14450
  async function bridgeFetch(config2, path, init = {}) {
14383
14451
  return fetch(`${config2.endpoint}${path}`, {
14384
14452
  ...init,
@@ -14471,7 +14539,127 @@ async function runBridgeLoop() {
14471
14539
  }
14472
14540
  }
14473
14541
  }
14542
+ var provisioningBridgeLoopStarted = false;
14543
+ async function runProvisioningBridgeLoop() {
14544
+ if (provisioningBridgeLoopStarted) return;
14545
+ provisioningBridgeLoopStarted = true;
14546
+ while (true) {
14547
+ const config2 = await provisioningBridgeConfig();
14548
+ if (!config2) {
14549
+ await sleep(1e3);
14550
+ continue;
14551
+ }
14552
+ const query = `?extensionInstanceId=${encodeURIComponent(extensionInstanceId)}`;
14553
+ try {
14554
+ const hello = await bridgeFetch(
14555
+ config2,
14556
+ "/v1/provisioning/session/hello",
14557
+ {
14558
+ method: "POST",
14559
+ body: JSON.stringify({
14560
+ extensionId: chrome.runtime.id,
14561
+ extensionInstanceId
14562
+ })
14563
+ }
14564
+ );
14565
+ if (!hello.ok) throw new Error("PROVISIONING_BRIDGE_HELLO_REJECTED");
14566
+ let lastHeartbeatAt = 0;
14567
+ while (true) {
14568
+ if (Date.now() - lastHeartbeatAt >= 5e3) {
14569
+ const heartbeat = await bridgeFetch(
14570
+ config2,
14571
+ `/v1/provisioning/session/heartbeat${query}`,
14572
+ { method: "POST", body: "{}" }
14573
+ );
14574
+ if (!heartbeat.ok)
14575
+ throw new Error("PROVISIONING_BRIDGE_HEARTBEAT_REJECTED");
14576
+ lastHeartbeatAt = Date.now();
14577
+ }
14578
+ const response = await bridgeFetch(
14579
+ config2,
14580
+ `/v1/provisioning/commands/next${query}`
14581
+ );
14582
+ if (response.status === 204) {
14583
+ await sleep(250);
14584
+ continue;
14585
+ }
14586
+ if (!response.ok) throw new Error("PROVISIONING_BRIDGE_POLL_REJECTED");
14587
+ const command = await response.json();
14588
+ const commandHeartbeat = setInterval(() => {
14589
+ void bridgeFetch(
14590
+ config2,
14591
+ `/v1/provisioning/session/heartbeat${query}`,
14592
+ { method: "POST", body: "{}" }
14593
+ ).catch(() => void 0);
14594
+ }, 2e3);
14595
+ let result;
14596
+ try {
14597
+ result = {
14598
+ commandId: command.commandId,
14599
+ ok: true,
14600
+ value: await executeProvisioningCommand(command)
14601
+ };
14602
+ } catch (error46) {
14603
+ result = {
14604
+ commandId: command.commandId,
14605
+ ok: false,
14606
+ error: error46 instanceof Error ? error46.message : "PROVISIONING_EXTENSION_COMMAND_FAILED"
14607
+ };
14608
+ } finally {
14609
+ clearInterval(commandHeartbeat);
14610
+ }
14611
+ const reported = await bridgeFetch(
14612
+ config2,
14613
+ `/v1/provisioning/commands/result${query}`,
14614
+ { method: "POST", body: JSON.stringify(result) }
14615
+ );
14616
+ if (!reported.ok)
14617
+ throw new Error("PROVISIONING_BRIDGE_RESULT_REJECTED");
14618
+ }
14619
+ } catch {
14620
+ await sleep(1e3);
14621
+ }
14622
+ }
14623
+ }
14624
+ function provisioningRelayBase64(bytes) {
14625
+ let binary = "";
14626
+ for (let offset = 0; offset < bytes.length; offset += 32768)
14627
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
14628
+ return btoa(binary);
14629
+ }
14474
14630
  chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
14631
+ if (message.type === "PROFLOW_PROVISIONING_RELAY_FETCH") {
14632
+ const rawUrl = typeof message.url === "string" ? message.url : "";
14633
+ let parsed;
14634
+ try {
14635
+ parsed = new URL(rawUrl);
14636
+ } catch {
14637
+ sendResponse({ ok: false, error: "KNOWLEDGE_RELAY_URL_INVALID" });
14638
+ return;
14639
+ }
14640
+ if (parsed.protocol !== "http:" || parsed.hostname !== "127.0.0.1" || !parsed.pathname.startsWith("/v1/provisioning/files/") || parsed.username !== "" || parsed.password !== "" || parsed.search !== "" || parsed.hash !== "") {
14641
+ sendResponse({ ok: false, error: "KNOWLEDGE_RELAY_URL_INVALID" });
14642
+ return;
14643
+ }
14644
+ void fetch(parsed.toString(), { cache: "no-store" }).then(
14645
+ async (response) => {
14646
+ if (!response.ok) {
14647
+ sendResponse({
14648
+ ok: false,
14649
+ error: `KNOWLEDGE_RELAY_FETCH_FAILED:${response.status}`
14650
+ });
14651
+ return;
14652
+ }
14653
+ const bytes = new Uint8Array(await response.arrayBuffer());
14654
+ sendResponse({ ok: true, base64: provisioningRelayBase64(bytes) });
14655
+ },
14656
+ (error46) => sendResponse({
14657
+ ok: false,
14658
+ error: error46 instanceof Error ? `KNOWLEDGE_RELAY_FETCH_FAILED:${error46.message}` : "KNOWLEDGE_RELAY_FETCH_FAILED"
14659
+ })
14660
+ );
14661
+ return true;
14662
+ }
14475
14663
  if (message.type === "PROFLOW_CONTENT_OBSERVATION" && message.observation && sender.tab?.id !== void 0 && sender.tab.windowId !== void 0) {
14476
14664
  const observed = {
14477
14665
  ...message.observation,
@@ -14554,6 +14742,7 @@ async function startBackgroundRuntime() {
14554
14742
  await bootstrapManagedRuntimeConfig();
14555
14743
  await persistSnapshot();
14556
14744
  void runBridgeLoop();
14745
+ void runProvisioningBridgeLoop();
14557
14746
  void runObserverRecovery();
14558
14747
  }
14559
14748
  chrome.runtime.onInstalled.addListener(() => {
@@ -0,0 +1 @@
1
+ export {};