@tomflow/proflow-execution-browser-extension 0.1.21 → 0.1.23

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/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @tomflow/proflow-execution-browser-extension
2
+
3
+ ## 0.1.23
4
+
5
+ ### Patch Changes
6
+
7
+ - Wait for Chrome unpacked-extension registration to become observably enabled after heartbeat pairing before Browser setup reports success.
8
+
9
+ ## 0.1.22
10
+
11
+ ### Patch Changes
12
+
13
+ - Make Browser Extension static materialization version-idempotent, freeze real-user install/remove acceptance paths, and remove unsupported Reload/Disable-Enable test scenarios.
@@ -47,7 +47,7 @@ export declare const behaviorAdapter: {
47
47
  ok: true;
48
48
  status: "SUCCEEDED";
49
49
  moduleRef: "execution-browser-extension";
50
- moduleVersion: "0.1.21";
50
+ moduleVersion: "0.1.23";
51
51
  data: {
52
52
  loadDir: string;
53
53
  };
@@ -60,7 +60,7 @@ export declare const behaviorAdapter: {
60
60
  readonly ok: true;
61
61
  readonly status: "SUCCEEDED";
62
62
  readonly moduleRef: "execution-browser-extension";
63
- readonly moduleVersion: "0.1.21";
63
+ readonly moduleVersion: "0.1.23";
64
64
  };
65
65
  observedEffects: never[];
66
66
  }>;
@@ -70,7 +70,7 @@ export declare const behaviorAdapter: {
70
70
  ok: true;
71
71
  status: "SUCCEEDED";
72
72
  moduleRef: "execution-browser-extension";
73
- moduleVersion: "0.1.21";
73
+ moduleVersion: "0.1.23";
74
74
  data: {
75
75
  setupStatus: "ACTION_REQUIRED" | "READY";
76
76
  runtimeStatus: "NOT_APPLICABLE";
@@ -95,7 +95,7 @@ export declare const behaviorAdapter: {
95
95
  result: {
96
96
  contract: "deployment.result.v1";
97
97
  moduleRef: "execution-browser-extension";
98
- moduleVersion: "0.1.21";
98
+ moduleVersion: "0.1.23";
99
99
  ok: false;
100
100
  status: "ACTION_REQUIRED";
101
101
  data: {
@@ -127,14 +127,14 @@ export declare const behaviorAdapter: {
127
127
  readonly ok: true;
128
128
  readonly status: "SUCCEEDED";
129
129
  readonly moduleRef: "execution-browser-extension";
130
- readonly moduleVersion: "0.1.21";
130
+ readonly moduleVersion: "0.1.23";
131
131
  };
132
132
  observedEffects: string[];
133
133
  } | {
134
134
  result: {
135
135
  contract: "deployment.result.v1";
136
136
  moduleRef: "execution-browser-extension";
137
- moduleVersion: "0.1.21";
137
+ moduleVersion: "0.1.23";
138
138
  ok: false;
139
139
  status: "FAILED";
140
140
  error: {
@@ -167,7 +167,7 @@ export declare const behaviorAdapter: {
167
167
  ok: true;
168
168
  status: "SUCCEEDED";
169
169
  moduleRef: "execution-browser-extension";
170
- moduleVersion: "0.1.21";
170
+ moduleVersion: "0.1.23";
171
171
  data: {
172
172
  docs: string;
173
173
  };
@@ -180,11 +180,11 @@ export declare const behaviorAdapter: {
180
180
  readonly ok: true;
181
181
  readonly status: "SUCCEEDED";
182
182
  readonly moduleRef: "execution-browser-extension";
183
- readonly moduleVersion: "0.1.21";
183
+ readonly moduleVersion: "0.1.23";
184
184
  } | {
185
185
  contract: "deployment.result.v1";
186
186
  moduleRef: "execution-browser-extension";
187
- moduleVersion: "0.1.21";
187
+ moduleVersion: "0.1.23";
188
188
  ok: false;
189
189
  status: "FAILED";
190
190
  error: {
@@ -201,7 +201,7 @@ export declare const behaviorAdapter: {
201
201
  readonly ok: true;
202
202
  readonly status: "SUCCEEDED";
203
203
  readonly moduleRef: "execution-browser-extension";
204
- readonly moduleVersion: "0.1.21";
204
+ readonly moduleVersion: "0.1.23";
205
205
  };
206
206
  observedEffects: never[];
207
207
  }>;
@@ -1,9 +1,9 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { cp, mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
3
  import { basename, dirname, join, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { deterministicLoopbackPort, ensureModuleSecretFile, moduleWorkspaceStateDirectory, readModuleSharedFacts, writeModuleSharedFacts, } from "@tomflow/proflow-module-contract";
6
- import { probeChromeExtensionState } from "../src/chrome-extension-state.js";
6
+ import { probeChromeExtensionState, waitForChromeExtensionEnabled, } from "../src/chrome-extension-state.js";
7
7
  import { openBrowserExtensionManager, runInteractiveBrowserExtensionSetup, } from "../src/install-workflow.js";
8
8
  import { createBrowserExtensionPairingServer } from "../src/pairing.js";
9
9
  import { descriptor } from "./descriptor.js";
@@ -40,6 +40,25 @@ function packageRoot() {
40
40
  export function browserExtensionLoadDir(workspaceRoot) {
41
41
  return join(resolve(workspaceRoot), ".proflow", "deployment", "browser-extension", "execution-browser-extension");
42
42
  }
43
+ const materializationFile = (context) => join(browserExtensionLoadDir(context.workspaceRoot), ".proflow-materialization.json");
44
+ async function materializationReady(context) {
45
+ const loadDir = browserExtensionLoadDir(context.workspaceRoot);
46
+ try {
47
+ const raw = JSON.parse(await readFile(materializationFile(context), "utf8"));
48
+ if (raw.contract !== "proflow.browser-extension-materialization.v1" ||
49
+ raw.moduleVersion !== descriptor.moduleVersion)
50
+ return false;
51
+ await Promise.all([
52
+ readFile(join(loadDir, "manifest.json")),
53
+ readFile(join(loadDir, "dist", "extension", "background.js")),
54
+ readFile(join(loadDir, "extension", "options.html")),
55
+ ]);
56
+ return true;
57
+ }
58
+ catch {
59
+ return false;
60
+ }
61
+ }
43
62
  const stateDir = (context) => moduleWorkspaceStateDirectory(context, descriptor.moduleRef);
44
63
  const setupFile = (context) => join(stateDir(context), "setup.json");
45
64
  const installFlowFile = (context) => join(stateDir(context), "install-flow.json");
@@ -93,8 +112,11 @@ export async function materializeProductionConfig(input) {
93
112
  return { loadDir };
94
113
  }
95
114
  async function installPackage(context) {
96
- const sourceRoot = packageRoot();
97
115
  const loadDir = browserExtensionLoadDir(context.workspaceRoot);
116
+ if (await materializationReady(context))
117
+ return loadDir;
118
+ const sourceRoot = packageRoot();
119
+ await rm(loadDir, { recursive: true, force: true });
98
120
  await mkdir(join(loadDir, "dist"), { recursive: true });
99
121
  await cp(join(sourceRoot, "dist", "extension"), join(loadDir, "dist", "extension"), { recursive: true, force: true });
100
122
  await cp(join(sourceRoot, "extension"), join(loadDir, "extension"), {
@@ -104,6 +126,10 @@ async function installPackage(context) {
104
126
  await cp(join(sourceRoot, "manifest.json"), join(loadDir, "manifest.json"), {
105
127
  force: true,
106
128
  });
129
+ await writeFile(materializationFile(context), `${JSON.stringify({
130
+ contract: "proflow.browser-extension-materialization.v1",
131
+ moduleVersion: descriptor.moduleVersion,
132
+ }, null, 2)}\n`, { mode: 0o600 });
107
133
  return loadDir;
108
134
  }
109
135
  async function readSetup(context) {
@@ -509,7 +535,7 @@ export const behaviorAdapter = {
509
535
  installFlow?.developerModeConfirmed !== true) {
510
536
  await persistDeveloperModeConfirmation(context);
511
537
  }
512
- await runInteractiveBrowserExtensionSetup({
538
+ const paired = await runInteractiveBrowserExtensionSetup({
513
539
  workspaceRoot: context.workspaceRoot,
514
540
  ...(input?.timeoutMs === undefined
515
541
  ? {}
@@ -517,6 +543,14 @@ export const behaviorAdapter = {
517
543
  ...(input?.desktop === undefined ? {} : { desktop: input.desktop }),
518
544
  ...(input?.pair === undefined ? {} : { pair: input.pair }),
519
545
  });
546
+ if (input?.pair === undefined) {
547
+ const chromeState = await waitForChromeExtensionEnabled({
548
+ extensionId: paired.extensionId,
549
+ loadDir: browserExtensionLoadDir(context.workspaceRoot),
550
+ }, { timeoutMs: 5_000 });
551
+ if (chromeState !== "ENABLED")
552
+ throw new Error(`Chrome extension registration did not stabilize as ENABLED after pairing (${chromeState})`);
553
+ }
520
554
  return {
521
555
  result: base,
522
556
  observedEffects: ["Materialize the unpacked MV3 extension package"],
@@ -3,7 +3,7 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "execution-browser-extension";
5
5
  readonly packageName: "@tomflow/proflow-execution-browser-extension";
6
- readonly moduleVersion: "0.1.21";
6
+ readonly moduleVersion: "0.1.23";
7
7
  readonly kind: "browser-extension";
8
8
  readonly templateVersion: "1.0.0";
9
9
  readonly platformCompatibility: ">=1.0.0 <2.0.0";
@@ -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.21",
6
+ moduleVersion: "0.1.23",
7
7
  kind: "browser-extension",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
@@ -1,4 +1,14 @@
1
1
  export type ChromeExtensionState = "ENABLED" | "DISABLED" | "MISSING" | "UNKNOWN";
2
+ export type ChromeExtensionStateProbe = () => Promise<ChromeExtensionState>;
3
+ export declare function waitForChromeExtensionEnabled(input: {
4
+ extensionId: string;
5
+ loadDir: string;
6
+ userDataRoot?: string;
7
+ }, options?: {
8
+ timeoutMs?: number;
9
+ intervalMs?: number;
10
+ probe?: ChromeExtensionStateProbe;
11
+ }): Promise<ChromeExtensionState>;
2
12
  export declare function probeChromeExtensionState(input: {
3
13
  extensionId: string;
4
14
  loadDir: string;
@@ -37,6 +37,18 @@ async function preferredProfiles(root) {
37
37
  ? [lastUsed, ...profiles.filter((name) => name !== lastUsed)]
38
38
  : profiles;
39
39
  }
40
+ export async function waitForChromeExtensionEnabled(input, options = {}) {
41
+ const timeoutMs = options.timeoutMs ?? 5_000;
42
+ const intervalMs = options.intervalMs ?? 100;
43
+ const probe = options.probe ?? (() => probeChromeExtensionState(input));
44
+ const deadline = Date.now() + timeoutMs;
45
+ let observed = await probe();
46
+ while (observed !== "ENABLED" && observed !== "DISABLED" && Date.now() < deadline) {
47
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
48
+ observed = await probe();
49
+ }
50
+ return observed;
51
+ }
40
52
  export async function probeChromeExtensionState(input) {
41
53
  const root = input.userDataRoot ?? defaultUserDataRoot();
42
54
  if (!root)
package/manifest.json CHANGED
@@ -1,17 +1,28 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "ProFlow Execution Browser",
4
- "version": "0.1.21",
5
- "permissions": ["tabs", "storage", "sidePanel"],
6
- "host_permissions": ["https://chatgpt.com/*", "http://127.0.0.1/*"],
4
+ "version": "0.1.23",
5
+ "permissions": [
6
+ "tabs",
7
+ "storage",
8
+ "sidePanel"
9
+ ],
10
+ "host_permissions": [
11
+ "https://chatgpt.com/*",
12
+ "http://127.0.0.1/*"
13
+ ],
7
14
  "background": {
8
15
  "service_worker": "dist/extension/background.js",
9
16
  "type": "module"
10
17
  },
11
18
  "content_scripts": [
12
19
  {
13
- "matches": ["https://chatgpt.com/g/*"],
14
- "js": ["dist/extension/content.js"],
20
+ "matches": [
21
+ "https://chatgpt.com/g/*"
22
+ ],
23
+ "js": [
24
+ "dist/extension/content.js"
25
+ ],
15
26
  "run_at": "document_idle"
16
27
  },
17
28
  {
@@ -19,7 +30,9 @@
19
30
  "https://chatgpt.com/gpts/editor",
20
31
  "https://chatgpt.com/gpts/editor/*"
21
32
  ],
22
- "js": ["dist/extension/provisioning-content.js"],
33
+ "js": [
34
+ "dist/extension/provisioning-content.js"
35
+ ],
23
36
  "run_at": "document_idle"
24
37
  }
25
38
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-execution-browser-extension",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "Execution-owned MV3 Browser executor, evidence provider and browser application surface.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -3,7 +3,7 @@
3
3
  "contractVersion": "1.0.0",
4
4
  "moduleRef": "execution-browser-extension",
5
5
  "packageName": "@tomflow/proflow-execution-browser-extension",
6
- "moduleVersion": "0.1.21",
6
+ "moduleVersion": "0.1.23",
7
7
  "kind": "browser-extension",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",