@tomflow/proflow-execution-browser-extension 0.1.20 → 0.1.22

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,7 @@
1
+ # @tomflow/proflow-execution-browser-extension
2
+
3
+ ## 0.1.22
4
+
5
+ ### Patch Changes
6
+
7
+ - Make Browser Extension static materialization version-idempotent, freeze real-user install/remove acceptance paths, and remove unsupported Reload/Disable-Enable test scenarios.
@@ -7,6 +7,29 @@ export declare function materializeProductionConfig(input: {
7
7
  }): Promise<{
8
8
  loadDir: string;
9
9
  }>;
10
+ export type RunningBridgeProbe = {
11
+ kind: "ABSENT";
12
+ } | {
13
+ kind: "PRESENT";
14
+ identity?: {
15
+ extensionId: string;
16
+ extensionInstanceId: string;
17
+ };
18
+ };
19
+ export declare function classifyBrowserLiveSetup(input: {
20
+ baseSetupReady: boolean;
21
+ evidenceInstanceId?: string;
22
+ bridgeProbe: RunningBridgeProbe;
23
+ }): {
24
+ readonly setupReady: boolean;
25
+ issueCode?: never;
26
+ } | {
27
+ setupReady: boolean;
28
+ issueCode: "EXTENSION_SESSION_OFFLINE";
29
+ } | {
30
+ setupReady: boolean;
31
+ issueCode: "EXTENSION_SESSION_REVALIDATION_REQUIRED";
32
+ };
10
33
  export declare function pairBrowserExtensionSetup(context: ModuleCommandContext, options?: {
11
34
  timeoutMs?: number;
12
35
  onWaiting?: (input: {
@@ -24,7 +47,7 @@ export declare const behaviorAdapter: {
24
47
  ok: true;
25
48
  status: "SUCCEEDED";
26
49
  moduleRef: "execution-browser-extension";
27
- moduleVersion: "0.1.20";
50
+ moduleVersion: "0.1.22";
28
51
  data: {
29
52
  loadDir: string;
30
53
  };
@@ -37,7 +60,7 @@ export declare const behaviorAdapter: {
37
60
  readonly ok: true;
38
61
  readonly status: "SUCCEEDED";
39
62
  readonly moduleRef: "execution-browser-extension";
40
- readonly moduleVersion: "0.1.20";
63
+ readonly moduleVersion: "0.1.22";
41
64
  };
42
65
  observedEffects: never[];
43
66
  }>;
@@ -47,17 +70,23 @@ export declare const behaviorAdapter: {
47
70
  ok: true;
48
71
  status: "SUCCEEDED";
49
72
  moduleRef: "execution-browser-extension";
50
- moduleVersion: "0.1.20";
73
+ moduleVersion: "0.1.22";
51
74
  data: {
52
75
  setupStatus: "ACTION_REQUIRED" | "READY";
53
76
  runtimeStatus: "NOT_APPLICABLE";
54
- issues?: {
77
+ issues?: ({
55
78
  scope: "SETUP";
56
79
  code: string;
57
80
  message: string;
58
81
  relatedModuleRefs: string[];
59
82
  nextCommand: string;
60
- }[];
83
+ } | {
84
+ scope: "SETUP";
85
+ code: "EXTENSION_SESSION_OFFLINE" | "EXTENSION_SESSION_REVALIDATION_REQUIRED" | undefined;
86
+ message: string;
87
+ relatedModuleRefs: string[];
88
+ nextCommand: string;
89
+ })[];
61
90
  };
62
91
  };
63
92
  observedEffects: never[];
@@ -66,7 +95,7 @@ export declare const behaviorAdapter: {
66
95
  result: {
67
96
  contract: "deployment.result.v1";
68
97
  moduleRef: "execution-browser-extension";
69
- moduleVersion: "0.1.20";
98
+ moduleVersion: "0.1.22";
70
99
  ok: false;
71
100
  status: "ACTION_REQUIRED";
72
101
  data: {
@@ -98,14 +127,14 @@ export declare const behaviorAdapter: {
98
127
  readonly ok: true;
99
128
  readonly status: "SUCCEEDED";
100
129
  readonly moduleRef: "execution-browser-extension";
101
- readonly moduleVersion: "0.1.20";
130
+ readonly moduleVersion: "0.1.22";
102
131
  };
103
132
  observedEffects: string[];
104
133
  } | {
105
134
  result: {
106
135
  contract: "deployment.result.v1";
107
136
  moduleRef: "execution-browser-extension";
108
- moduleVersion: "0.1.20";
137
+ moduleVersion: "0.1.22";
109
138
  ok: false;
110
139
  status: "FAILED";
111
140
  error: {
@@ -138,7 +167,7 @@ export declare const behaviorAdapter: {
138
167
  ok: true;
139
168
  status: "SUCCEEDED";
140
169
  moduleRef: "execution-browser-extension";
141
- moduleVersion: "0.1.20";
170
+ moduleVersion: "0.1.22";
142
171
  data: {
143
172
  docs: string;
144
173
  };
@@ -151,11 +180,11 @@ export declare const behaviorAdapter: {
151
180
  readonly ok: true;
152
181
  readonly status: "SUCCEEDED";
153
182
  readonly moduleRef: "execution-browser-extension";
154
- readonly moduleVersion: "0.1.20";
183
+ readonly moduleVersion: "0.1.22";
155
184
  } | {
156
185
  contract: "deployment.result.v1";
157
186
  moduleRef: "execution-browser-extension";
158
- moduleVersion: "0.1.20";
187
+ moduleVersion: "0.1.22";
159
188
  ok: false;
160
189
  status: "FAILED";
161
190
  error: {
@@ -172,7 +201,7 @@ export declare const behaviorAdapter: {
172
201
  readonly ok: true;
173
202
  readonly status: "SUCCEEDED";
174
203
  readonly moduleRef: "execution-browser-extension";
175
- readonly moduleVersion: "0.1.20";
204
+ readonly moduleVersion: "0.1.22";
176
205
  };
177
206
  observedEffects: never[];
178
207
  }>;
@@ -1,5 +1,5 @@
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";
@@ -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) {
@@ -255,6 +281,21 @@ async function persistPairedBrowserExtension(context, prepared, identity) {
255
281
  await writeFile(verificationFile(context), `${JSON.stringify(evidence, null, 2)}\n`, { mode: 0o600 });
256
282
  return identity;
257
283
  }
284
+ export function classifyBrowserLiveSetup(input) {
285
+ if (!input.baseSetupReady || input.bridgeProbe.kind === "ABSENT")
286
+ return { setupReady: input.baseSetupReady };
287
+ if (!input.bridgeProbe.identity)
288
+ return {
289
+ setupReady: false,
290
+ issueCode: "EXTENSION_SESSION_OFFLINE",
291
+ };
292
+ if (input.bridgeProbe.identity.extensionInstanceId !== input.evidenceInstanceId)
293
+ return {
294
+ setupReady: false,
295
+ issueCode: "EXTENSION_SESSION_REVALIDATION_REQUIRED",
296
+ };
297
+ return { setupReady: true };
298
+ }
258
299
  function connectionRefused(error) {
259
300
  if (!(error instanceof TypeError))
260
301
  return false;
@@ -392,31 +433,57 @@ export const behaviorAdapter = {
392
433
  loadDir,
393
434
  })
394
435
  : "MISSING";
395
- const setupReady = Boolean(setup &&
436
+ const baseSetupReady = Boolean(setup &&
396
437
  evidence &&
397
438
  setup.extensionId === evidence.extensionId &&
398
439
  chromeState === "ENABLED");
440
+ let bridgeProbe = { kind: "ABSENT" };
441
+ if (baseSetupReady && evidence) {
442
+ const facts = await readModuleSharedFacts(context, descriptor.moduleRef);
443
+ const bridgeEndpoint = factString(facts, "bridgeEndpoint");
444
+ const bridgeTokenFile = factString(facts, "bridgeTokenFile");
445
+ if (bridgeEndpoint && bridgeTokenFile) {
446
+ try {
447
+ bridgeProbe = await probeRunningBridgeSession({ bridgeEndpoint, bridgeTokenFile }, evidence.extensionId, 500);
448
+ }
449
+ catch {
450
+ bridgeProbe = { kind: "PRESENT" };
451
+ }
452
+ }
453
+ }
454
+ const live = classifyBrowserLiveSetup({
455
+ baseSetupReady,
456
+ ...(evidence ? { evidenceInstanceId: evidence.extensionInstanceId } : {}),
457
+ bridgeProbe,
458
+ });
459
+ const issue = !baseSetupReady
460
+ ? {
461
+ scope: "SETUP",
462
+ code: "EXTENSION_LOAD_REQUIRED",
463
+ message: "Chrome 扩展尚未加载或缺少可验证的运行证据",
464
+ relatedModuleRefs: ["chrome-runtime"],
465
+ nextCommand: "platform setup",
466
+ }
467
+ : live.setupReady
468
+ ? undefined
469
+ : {
470
+ scope: "SETUP",
471
+ code: live.issueCode,
472
+ message: live.issueCode === "EXTENSION_SESSION_OFFLINE"
473
+ ? "Chrome 扩展已加载,但当前运行会话未在线"
474
+ : "Chrome 扩展已重新启动,需要自动刷新当前运行会话证据",
475
+ relatedModuleRefs: ["execution-runtime"],
476
+ nextCommand: "platform setup",
477
+ };
399
478
  return {
400
479
  result: {
401
480
  ...base,
402
481
  data: {
403
- setupStatus: setupReady
482
+ setupStatus: live.setupReady
404
483
  ? "READY"
405
484
  : "ACTION_REQUIRED",
406
485
  runtimeStatus: "NOT_APPLICABLE",
407
- ...(setupReady
408
- ? {}
409
- : {
410
- issues: [
411
- {
412
- scope: "SETUP",
413
- code: "EXTENSION_LOAD_REQUIRED",
414
- message: "Chrome 扩展尚未加载或缺少可验证的运行证据",
415
- relatedModuleRefs: ["chrome-runtime"],
416
- nextCommand: "platform setup",
417
- },
418
- ],
419
- }),
486
+ ...(issue ? { issues: [issue] } : {}),
420
487
  },
421
488
  },
422
489
  observedEffects: [],
@@ -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.20";
6
+ readonly moduleVersion: "0.1.22";
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.20",
6
+ moduleVersion: "0.1.22",
7
7
  kind: "browser-extension",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
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.20",
5
- "permissions": ["tabs", "storage", "sidePanel"],
6
- "host_permissions": ["https://chatgpt.com/*", "http://127.0.0.1/*"],
4
+ "version": "0.1.22",
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.20",
3
+ "version": "0.1.22",
4
4
  "description": "Execution-owned MV3 Browser executor, evidence provider and browser application surface.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -31,8 +31,8 @@
31
31
  "@tomflow/proflow-module-contract": "^0.1.13"
32
32
  },
33
33
  "devDependencies": {
34
- "@tomflow/proflow-execution-runtime": "^0.1.15",
35
- "@tomflow/proflow-deployment-conformance": "^0.1.13"
34
+ "@tomflow/proflow-deployment-conformance": "^0.1.13",
35
+ "@tomflow/proflow-execution-runtime": "^0.1.15"
36
36
  },
37
37
  "keywords": [
38
38
  "proflow",
@@ -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.20",
6
+ "moduleVersion": "0.1.22",
7
7
  "kind": "browser-extension",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",