@tomflow/proflow-execution-browser-extension 0.1.3 → 0.1.5
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/DOCS.md +29 -0
- package/SETUP.md +7 -0
- package/dist/deployment/adapter.d.ts +99 -45
- package/dist/deployment/adapter.js +244 -167
- package/dist/deployment/descriptor.d.ts +7 -69
- package/dist/deployment/descriptor.js +24 -82
- package/dist/src/configure.d.ts +4 -0
- package/dist/src/configure.js +42 -0
- package/manifest.json +1 -1
- package/package.json +10 -17
- package/proflow.module.json +7 -83
- package/CHANGELOG.md +0 -19
- package/self-install.mjs +0 -35
package/DOCS.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @tomflow/proflow-execution-browser-extension — Module Docs
|
|
2
|
+
|
|
3
|
+
Module ref: `execution-browser-extension`
|
|
4
|
+
Domain: `execution`
|
|
5
|
+
Kind: `browser-extension`
|
|
6
|
+
|
|
7
|
+
Execution-owned MV3 Browser executor, evidence provider and browser application surface.
|
|
8
|
+
|
|
9
|
+
## Standard management surface
|
|
10
|
+
|
|
11
|
+
`install / uninstall / status / setup / docs / start / stop`
|
|
12
|
+
|
|
13
|
+
## Provides
|
|
14
|
+
|
|
15
|
+
- `execution-browser-executor` `1.0.0`
|
|
16
|
+
|
|
17
|
+
## Requires
|
|
18
|
+
|
|
19
|
+
- `execution` `>=1.0.0 <2.0.0`
|
|
20
|
+
- `task-orchestration` `>=1.0.0 <2.0.0`
|
|
21
|
+
- `agent-runtime` `>=1.0.0 <2.0.0`
|
|
22
|
+
|
|
23
|
+
## Public setup inputs
|
|
24
|
+
|
|
25
|
+
- None. Deterministic/private values and cross-Module shared facts are not public configuration.
|
|
26
|
+
|
|
27
|
+
## Ownership boundary
|
|
28
|
+
|
|
29
|
+
Module business APIs and any module-specific extra commands remain package-owned. Platform does not proxy or interpret them. Current human/external preparation is documented in `SETUP.md`.
|
package/SETUP.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# @tomflow/proflow-execution-browser-extension — Module Setup
|
|
2
|
+
|
|
3
|
+
After Module.install materializes the deployment directory and deterministic local configuration, load the unpacked extension in Chrome when requested. Confirm the real extension Service Worker is running, then rerun Module.setup so it can re-observe Chrome reality and record evidence. Endpoints, tokens and evidence paths are not user configuration.
|
|
4
|
+
|
|
5
|
+
## Completion
|
|
6
|
+
|
|
7
|
+
Setup is complete only when the Module's own `status` reports `setupStatus=READY`. Re-running setup must re-observe reality; it must not resume from a blind historical step index.
|
|
@@ -1,76 +1,130 @@
|
|
|
1
|
+
import { type ModuleCommandContext } from "@tomflow/proflow-module-contract";
|
|
2
|
+
export declare function browserExtensionLoadDir(workspaceRoot: string): string;
|
|
3
|
+
export declare function materializeProductionConfig(input: {
|
|
4
|
+
moduleRef: string;
|
|
5
|
+
config: Record<string, string>;
|
|
6
|
+
workspaceRoot: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
loadDir: string;
|
|
9
|
+
}>;
|
|
1
10
|
export declare const behaviorAdapter: {
|
|
2
|
-
readonly
|
|
11
|
+
readonly install: (context: ModuleCommandContext) => Promise<{
|
|
3
12
|
result: {
|
|
4
13
|
contract: "deployment.result.v1";
|
|
14
|
+
ok: true;
|
|
15
|
+
status: "SUCCEEDED";
|
|
5
16
|
moduleRef: "execution-browser-extension";
|
|
6
|
-
moduleVersion: "0.1.
|
|
7
|
-
|
|
8
|
-
|
|
17
|
+
moduleVersion: "0.1.5";
|
|
18
|
+
data: {
|
|
19
|
+
loadDir: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
observedEffects: string[];
|
|
23
|
+
}>;
|
|
24
|
+
readonly uninstall: (_context: ModuleCommandContext) => Promise<{
|
|
25
|
+
result: {
|
|
26
|
+
readonly contract: "deployment.result.v1";
|
|
27
|
+
readonly ok: true;
|
|
28
|
+
readonly status: "SUCCEEDED";
|
|
29
|
+
readonly moduleRef: "execution-browser-extension";
|
|
30
|
+
readonly moduleVersion: "0.1.5";
|
|
9
31
|
};
|
|
10
32
|
observedEffects: never[];
|
|
11
|
-
}
|
|
12
|
-
readonly
|
|
33
|
+
}>;
|
|
34
|
+
readonly status: (context: ModuleCommandContext) => Promise<{
|
|
35
|
+
result: {
|
|
36
|
+
contract: "deployment.result.v1";
|
|
37
|
+
ok: true;
|
|
38
|
+
status: "SUCCEEDED";
|
|
39
|
+
moduleRef: "execution-browser-extension";
|
|
40
|
+
moduleVersion: "0.1.5";
|
|
41
|
+
data: {
|
|
42
|
+
setupStatus: "ACTION_REQUIRED" | "READY";
|
|
43
|
+
runtimeStatus: "RUNNING" | "STOPPED";
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
observedEffects: string[];
|
|
47
|
+
}>;
|
|
48
|
+
readonly setup: (context: ModuleCommandContext) => Promise<{
|
|
13
49
|
result: {
|
|
14
50
|
contract: "deployment.result.v1";
|
|
15
51
|
moduleRef: "execution-browser-extension";
|
|
16
|
-
moduleVersion: "0.1.
|
|
17
|
-
ok:
|
|
18
|
-
status:
|
|
52
|
+
moduleVersion: "0.1.5";
|
|
53
|
+
ok: false;
|
|
54
|
+
status: "FAILED";
|
|
55
|
+
error: {
|
|
56
|
+
code: "SETUP_FAILED" | "START_FAILED";
|
|
57
|
+
message: string;
|
|
58
|
+
retryable: boolean;
|
|
59
|
+
};
|
|
19
60
|
};
|
|
20
61
|
observedEffects: never[];
|
|
21
|
-
}
|
|
22
|
-
readonly status: () => {
|
|
62
|
+
} | {
|
|
23
63
|
result: {
|
|
24
64
|
contract: "deployment.result.v1";
|
|
25
65
|
moduleRef: "execution-browser-extension";
|
|
26
|
-
moduleVersion: "0.1.
|
|
27
|
-
ok:
|
|
28
|
-
status:
|
|
66
|
+
moduleVersion: "0.1.5";
|
|
67
|
+
ok: false;
|
|
68
|
+
status: "ACTION_REQUIRED";
|
|
29
69
|
actionRequired: {
|
|
30
70
|
action: string;
|
|
31
71
|
description: string;
|
|
32
72
|
};
|
|
33
73
|
};
|
|
34
74
|
observedEffects: never[];
|
|
35
|
-
}
|
|
36
|
-
|
|
75
|
+
} | {
|
|
76
|
+
result: {
|
|
77
|
+
readonly contract: "deployment.result.v1";
|
|
78
|
+
readonly ok: true;
|
|
79
|
+
readonly status: "SUCCEEDED";
|
|
80
|
+
readonly moduleRef: "execution-browser-extension";
|
|
81
|
+
readonly moduleVersion: "0.1.5";
|
|
82
|
+
};
|
|
83
|
+
observedEffects: string[];
|
|
84
|
+
}>;
|
|
85
|
+
readonly docs: (_context: ModuleCommandContext) => Promise<{
|
|
37
86
|
result: {
|
|
38
87
|
contract: "deployment.result.v1";
|
|
88
|
+
ok: true;
|
|
89
|
+
status: "SUCCEEDED";
|
|
39
90
|
moduleRef: "execution-browser-extension";
|
|
40
|
-
moduleVersion: "0.1.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
status: string;
|
|
46
|
-
message: string;
|
|
47
|
-
}[];
|
|
91
|
+
moduleVersion: "0.1.5";
|
|
92
|
+
data: {
|
|
93
|
+
docs: string;
|
|
94
|
+
setup: string;
|
|
95
|
+
};
|
|
48
96
|
};
|
|
49
97
|
observedEffects: never[];
|
|
50
|
-
}
|
|
51
|
-
readonly
|
|
98
|
+
}>;
|
|
99
|
+
readonly start: (context: ModuleCommandContext) => Promise<{
|
|
52
100
|
result: {
|
|
101
|
+
readonly contract: "deployment.result.v1";
|
|
102
|
+
readonly ok: true;
|
|
103
|
+
readonly status: "SUCCEEDED";
|
|
104
|
+
readonly moduleRef: "execution-browser-extension";
|
|
105
|
+
readonly moduleVersion: "0.1.5";
|
|
106
|
+
} | {
|
|
53
107
|
contract: "deployment.result.v1";
|
|
54
108
|
moduleRef: "execution-browser-extension";
|
|
55
|
-
moduleVersion: "0.1.
|
|
56
|
-
ok:
|
|
57
|
-
status:
|
|
109
|
+
moduleVersion: "0.1.5";
|
|
110
|
+
ok: false;
|
|
111
|
+
status: "FAILED";
|
|
112
|
+
error: {
|
|
113
|
+
code: "SETUP_FAILED" | "START_FAILED";
|
|
114
|
+
message: string;
|
|
115
|
+
retryable: boolean;
|
|
116
|
+
};
|
|
58
117
|
};
|
|
59
118
|
observedEffects: never[];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
moduleRef: string;
|
|
72
|
-
config: Record<string, string>;
|
|
73
|
-
workspaceRoot: string;
|
|
74
|
-
}): {
|
|
75
|
-
behaviorAdapter: Record<string, unknown>;
|
|
119
|
+
}>;
|
|
120
|
+
readonly stop: (_context: ModuleCommandContext) => Promise<{
|
|
121
|
+
result: {
|
|
122
|
+
readonly contract: "deployment.result.v1";
|
|
123
|
+
readonly ok: true;
|
|
124
|
+
readonly status: "SUCCEEDED";
|
|
125
|
+
readonly moduleRef: "execution-browser-extension";
|
|
126
|
+
readonly moduleVersion: "0.1.5";
|
|
127
|
+
};
|
|
128
|
+
observedEffects: never[];
|
|
129
|
+
}>;
|
|
76
130
|
};
|
|
@@ -1,78 +1,46 @@
|
|
|
1
1
|
import { cp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { basename, dirname, join } from "node:path";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { deterministicLoopbackPort, ensureModuleSecretFile, moduleWorkspaceStateDirectory, readModuleSharedFacts, writeModuleSharedFacts, } from "@tomflow/proflow-module-contract";
|
|
4
5
|
import { descriptor } from "./descriptor.js";
|
|
5
6
|
const base = {
|
|
6
7
|
contract: "deployment.result.v1",
|
|
8
|
+
ok: true,
|
|
9
|
+
status: "SUCCEEDED",
|
|
7
10
|
moduleRef: descriptor.moduleRef,
|
|
8
11
|
moduleVersion: descriptor.moduleVersion,
|
|
9
12
|
};
|
|
10
|
-
|
|
11
|
-
describe: () => ({
|
|
12
|
-
result: { ...base, ok: true, status: "SUCCEEDED" },
|
|
13
|
-
observedEffects: [],
|
|
14
|
-
}),
|
|
15
|
-
preflight: () => ({
|
|
16
|
-
result: { ...base, ok: true, status: "SUCCEEDED" },
|
|
17
|
-
observedEffects: [],
|
|
18
|
-
}),
|
|
19
|
-
status: () => ({
|
|
20
|
-
result: {
|
|
21
|
-
...base,
|
|
22
|
-
ok: false,
|
|
23
|
-
status: "ACTION_REQUIRED",
|
|
24
|
-
actionRequired: {
|
|
25
|
-
action: "verify-real-carrier",
|
|
26
|
-
description: "Load in real Chrome and collect ChatGPT E3/E4 evidence",
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
observedEffects: [],
|
|
30
|
-
}),
|
|
31
|
-
verify: () => ({
|
|
32
|
-
result: {
|
|
33
|
-
...base,
|
|
34
|
-
ok: true,
|
|
35
|
-
status: "SUCCEEDED",
|
|
36
|
-
checks: [
|
|
37
|
-
{
|
|
38
|
-
id: "extension-package",
|
|
39
|
-
status: "PASS",
|
|
40
|
-
message: "The MV3 package is structurally verified; real Carrier readiness remains ACTION_REQUIRED in status",
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
},
|
|
44
|
-
observedEffects: [],
|
|
45
|
-
}),
|
|
46
|
-
doctor: () => ({
|
|
47
|
-
result: { ...base, ok: true, status: "SUCCEEDED" },
|
|
48
|
-
observedEffects: [],
|
|
49
|
-
}),
|
|
50
|
-
};
|
|
51
|
-
function loopbackEndpoint(value, key) {
|
|
52
|
-
const url = new URL(value);
|
|
53
|
-
if (url.protocol !== "http:" ||
|
|
54
|
-
url.hostname !== "127.0.0.1" ||
|
|
55
|
-
url.pathname !== "/" ||
|
|
56
|
-
url.search !== "" ||
|
|
57
|
-
url.hash !== "") {
|
|
58
|
-
throw new Error(`${key} must be a loopback HTTP origin`);
|
|
59
|
-
}
|
|
60
|
-
return value.replace(/\/$/, "");
|
|
61
|
-
}
|
|
62
|
-
async function credential(file, key) {
|
|
63
|
-
const token = (await readFile(file, "utf8")).trim();
|
|
64
|
-
if (token.length < 32)
|
|
65
|
-
throw new Error(`${key} must contain at least 32 characters`);
|
|
66
|
-
return token;
|
|
67
|
-
}
|
|
13
|
+
const factString = (facts, name) => (typeof facts?.[name] === "string" ? String(facts[name]) : undefined);
|
|
68
14
|
function packageRoot() {
|
|
69
15
|
const candidate = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
70
16
|
return basename(candidate) === "dist" ? dirname(candidate) : candidate;
|
|
71
17
|
}
|
|
72
18
|
export function browserExtensionLoadDir(workspaceRoot) {
|
|
73
|
-
return join(workspaceRoot, ".proflow", "deployment", "browser-extension", "execution-browser-extension");
|
|
19
|
+
return join(resolve(workspaceRoot), ".proflow", "deployment", "browser-extension", "execution-browser-extension");
|
|
20
|
+
}
|
|
21
|
+
const stateDir = (context) => moduleWorkspaceStateDirectory(context, descriptor.moduleRef);
|
|
22
|
+
const setupFile = (context) => join(stateDir(context), "setup.json");
|
|
23
|
+
const verificationFile = (context) => join(stateDir(context), "verification.json");
|
|
24
|
+
const executorConfigFile = (context) => join(stateDir(context), "browser-executor.json");
|
|
25
|
+
async function credential(file) {
|
|
26
|
+
const value = (await readFile(file, "utf8")).trim();
|
|
27
|
+
if (value.length < 32)
|
|
28
|
+
throw new Error(`credential ${file} is invalid`);
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
function loopbackEndpoint(value, name) {
|
|
32
|
+
const url = new URL(value);
|
|
33
|
+
if (url.protocol !== "http:" ||
|
|
34
|
+
url.hostname !== "127.0.0.1" ||
|
|
35
|
+
url.pathname !== "/" ||
|
|
36
|
+
url.search ||
|
|
37
|
+
url.hash)
|
|
38
|
+
throw new Error(`${name} must be a loopback HTTP origin`);
|
|
39
|
+
return value.replace(/\/$/, "");
|
|
74
40
|
}
|
|
75
41
|
export async function materializeProductionConfig(input) {
|
|
42
|
+
const context = { workspaceRoot: input.workspaceRoot };
|
|
43
|
+
const loadDir = await installPackage(context);
|
|
76
44
|
const required = [
|
|
77
45
|
"bridge.endpoint",
|
|
78
46
|
"bridge.token",
|
|
@@ -81,31 +49,31 @@ export async function materializeProductionConfig(input) {
|
|
|
81
49
|
"approvalApplication.endpoint",
|
|
82
50
|
"approvalApplication.token",
|
|
83
51
|
];
|
|
84
|
-
for (const
|
|
85
|
-
if (!input.config[
|
|
86
|
-
throw new Error(`missing required browser config ${
|
|
87
|
-
}
|
|
52
|
+
for (const name of required)
|
|
53
|
+
if (!input.config[name])
|
|
54
|
+
throw new Error(`missing required browser config ${name}`);
|
|
88
55
|
const runtimeConfig = {
|
|
89
56
|
proflowRuntimeBridge: {
|
|
90
57
|
endpoint: loopbackEndpoint(input.config["bridge.endpoint"] ?? "", "bridge.endpoint"),
|
|
91
|
-
token: await credential(input.config["bridge.token"] ?? ""
|
|
58
|
+
token: await credential(input.config["bridge.token"] ?? ""),
|
|
92
59
|
},
|
|
93
60
|
proflowTaskApplication: {
|
|
94
61
|
endpoint: loopbackEndpoint(input.config["taskApplication.endpoint"] ?? "", "taskApplication.endpoint"),
|
|
95
|
-
token: await credential(input.config["taskApplication.token"] ?? ""
|
|
62
|
+
token: await credential(input.config["taskApplication.token"] ?? ""),
|
|
96
63
|
},
|
|
97
64
|
proflowApprovalApplication: {
|
|
98
65
|
endpoint: loopbackEndpoint(input.config["approvalApplication.endpoint"] ?? "", "approvalApplication.endpoint"),
|
|
99
|
-
token: await credential(input.config["approvalApplication.token"] ?? ""
|
|
66
|
+
token: await credential(input.config["approvalApplication.token"] ?? ""),
|
|
100
67
|
},
|
|
101
68
|
};
|
|
69
|
+
await writeFile(join(loadDir, "runtime-config.json"), `${JSON.stringify(runtimeConfig, null, 2)}\n`, { mode: 0o600 });
|
|
70
|
+
return { loadDir };
|
|
71
|
+
}
|
|
72
|
+
async function installPackage(context) {
|
|
102
73
|
const sourceRoot = packageRoot();
|
|
103
|
-
const loadDir = browserExtensionLoadDir(
|
|
74
|
+
const loadDir = browserExtensionLoadDir(context.workspaceRoot);
|
|
104
75
|
await mkdir(join(loadDir, "dist"), { recursive: true });
|
|
105
|
-
await cp(join(sourceRoot, "dist", "extension"), join(loadDir, "dist", "extension"), {
|
|
106
|
-
recursive: true,
|
|
107
|
-
force: true,
|
|
108
|
-
});
|
|
76
|
+
await cp(join(sourceRoot, "dist", "extension"), join(loadDir, "dist", "extension"), { recursive: true, force: true });
|
|
109
77
|
await cp(join(sourceRoot, "extension"), join(loadDir, "extension"), {
|
|
110
78
|
recursive: true,
|
|
111
79
|
force: true,
|
|
@@ -113,112 +81,221 @@ export async function materializeProductionConfig(input) {
|
|
|
113
81
|
await cp(join(sourceRoot, "manifest.json"), join(loadDir, "manifest.json"), {
|
|
114
82
|
force: true,
|
|
115
83
|
});
|
|
116
|
-
|
|
117
|
-
return { loadDir };
|
|
84
|
+
return loadDir;
|
|
118
85
|
}
|
|
119
|
-
async function
|
|
120
|
-
|
|
86
|
+
async function readSetup(context) {
|
|
87
|
+
try {
|
|
88
|
+
const raw = JSON.parse(await readFile(setupFile(context), "utf8"));
|
|
89
|
+
return typeof raw.extensionId === "string" &&
|
|
90
|
+
/^[a-z]{32}$/.test(raw.extensionId)
|
|
91
|
+
? raw
|
|
92
|
+
: undefined;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
121
95
|
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function readEvidence(context, loadDir) {
|
|
122
99
|
try {
|
|
123
|
-
const raw = JSON.parse(await readFile(
|
|
124
|
-
|
|
125
|
-
raw.moduleVersion
|
|
126
|
-
raw.loadDir
|
|
127
|
-
typeof raw.extensionId
|
|
128
|
-
raw.extensionId
|
|
129
|
-
raw.serviceWorker
|
|
130
|
-
typeof raw.observedAt
|
|
131
|
-
Number.isNaN(Date.parse(raw.observedAt))
|
|
132
|
-
|
|
133
|
-
|
|
100
|
+
const raw = JSON.parse(await readFile(verificationFile(context), "utf8"));
|
|
101
|
+
return raw.contract === "proflow.browser-extension-verification.v1" &&
|
|
102
|
+
raw.moduleVersion === descriptor.moduleVersion &&
|
|
103
|
+
raw.loadDir === loadDir &&
|
|
104
|
+
typeof raw.extensionId === "string" &&
|
|
105
|
+
/^[a-z]{32}$/.test(raw.extensionId) &&
|
|
106
|
+
raw.serviceWorker === "RUNNING" &&
|
|
107
|
+
typeof raw.observedAt === "string" &&
|
|
108
|
+
!Number.isNaN(Date.parse(raw.observedAt))
|
|
109
|
+
? raw
|
|
110
|
+
: undefined;
|
|
134
111
|
}
|
|
135
112
|
catch {
|
|
136
113
|
return undefined;
|
|
137
114
|
}
|
|
138
115
|
}
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
116
|
+
function input(context) {
|
|
117
|
+
const value = context.input;
|
|
118
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
119
|
+
return {};
|
|
120
|
+
const extensionId = Reflect.get(value, "extensionId"), serviceWorker = Reflect.get(value, "serviceWorker"), observedAt = Reflect.get(value, "observedAt");
|
|
121
|
+
return {
|
|
122
|
+
...(typeof extensionId === "string" ? { extensionId } : {}),
|
|
123
|
+
...(serviceWorker === "RUNNING"
|
|
124
|
+
? { serviceWorker: "RUNNING" }
|
|
125
|
+
: {}),
|
|
126
|
+
...(typeof observedAt === "string" ? { observedAt } : {}),
|
|
146
127
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
128
|
+
}
|
|
129
|
+
async function ownFacts(context) {
|
|
130
|
+
await mkdir(stateDir(context), { recursive: true, mode: 0o700 });
|
|
131
|
+
const loadDir = browserExtensionLoadDir(context.workspaceRoot);
|
|
132
|
+
const bridgeTokenFile = await ensureModuleSecretFile(context, descriptor.moduleRef, "bridge");
|
|
133
|
+
const bridgePort = deterministicLoopbackPort(context, descriptor.moduleRef, "bridge");
|
|
134
|
+
const facts = {
|
|
135
|
+
loadDir,
|
|
136
|
+
bridgeTokenFile,
|
|
137
|
+
bridgeEndpoint: `http://127.0.0.1:${bridgePort}`,
|
|
138
|
+
verificationEvidenceFile: verificationFile(context),
|
|
155
139
|
};
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
140
|
+
const setup = await readSetup(context);
|
|
141
|
+
if (setup)
|
|
142
|
+
facts.extensionId = setup.extensionId;
|
|
143
|
+
try {
|
|
144
|
+
await readFile(executorConfigFile(context), "utf8");
|
|
145
|
+
facts.browserExecutorConfigPath = executorConfigFile(context);
|
|
146
|
+
}
|
|
147
|
+
catch { }
|
|
148
|
+
await writeModuleSharedFacts(context, descriptor.moduleRef, facts);
|
|
149
|
+
return facts;
|
|
150
|
+
}
|
|
151
|
+
async function materialize(context, setup) {
|
|
152
|
+
const host = await readModuleSharedFacts(context, "platform-host");
|
|
153
|
+
const endpoint = factString(host, "endpoint"), taskTokenFile = factString(host, "taskApplicationTokenFile"), approvalTokenFile = factString(host, "approvalApplicationTokenFile");
|
|
154
|
+
if (!endpoint || !taskTokenFile || !approvalTokenFile)
|
|
155
|
+
throw new Error("platform-host application shared facts are unavailable");
|
|
156
|
+
const facts = await ownFacts(context);
|
|
157
|
+
const loadDir = String(facts.loadDir);
|
|
158
|
+
const bridgeTokenFile = String(facts.bridgeTokenFile);
|
|
159
|
+
const bridgeEndpoint = String(facts.bridgeEndpoint);
|
|
160
|
+
const runtimeConfig = {
|
|
161
|
+
proflowRuntimeBridge: {
|
|
162
|
+
endpoint: bridgeEndpoint,
|
|
163
|
+
token: await credential(bridgeTokenFile),
|
|
164
|
+
},
|
|
165
|
+
proflowTaskApplication: {
|
|
166
|
+
endpoint,
|
|
167
|
+
token: await credential(taskTokenFile),
|
|
168
|
+
},
|
|
169
|
+
proflowApprovalApplication: {
|
|
170
|
+
endpoint,
|
|
171
|
+
token: await credential(approvalTokenFile),
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
await writeFile(join(loadDir, "runtime-config.json"), `${JSON.stringify(runtimeConfig, null, 2)}\n`, { mode: 0o600 });
|
|
175
|
+
await writeFile(executorConfigFile(context), `${JSON.stringify({ platformHost: { endpoint, tokenFile: taskTokenFile }, bridge: { extensionId: setup.extensionId, tokenFile: bridgeTokenFile, host: "127.0.0.1", port: Number(new URL(bridgeEndpoint).port) } }, null, 2)}\n`, { mode: 0o600 });
|
|
176
|
+
await writeModuleSharedFacts(context, descriptor.moduleRef, {
|
|
177
|
+
...facts,
|
|
178
|
+
extensionId: setup.extensionId,
|
|
179
|
+
browserExecutorConfigPath: executorConfigFile(context),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const failed = (code, message, retryable = true) => ({
|
|
183
|
+
...base,
|
|
184
|
+
ok: false,
|
|
185
|
+
status: "FAILED",
|
|
186
|
+
error: { code, message, retryable },
|
|
187
|
+
});
|
|
188
|
+
export const behaviorAdapter = {
|
|
189
|
+
install: async (context) => {
|
|
190
|
+
const loadDir = await installPackage(context);
|
|
191
|
+
return {
|
|
192
|
+
result: { ...base, data: { ...(await ownFacts(context)), loadDir } },
|
|
193
|
+
observedEffects: ["Materialize the unpacked MV3 extension package"],
|
|
194
|
+
};
|
|
195
|
+
},
|
|
196
|
+
uninstall: async (_context) => ({
|
|
197
|
+
result: base,
|
|
198
|
+
observedEffects: [],
|
|
199
|
+
}),
|
|
200
|
+
status: async (context) => {
|
|
201
|
+
const loadDir = browserExtensionLoadDir(context.workspaceRoot);
|
|
202
|
+
const setup = await readSetup(context);
|
|
203
|
+
const evidence = await readEvidence(context, loadDir);
|
|
204
|
+
return {
|
|
205
|
+
result: {
|
|
206
|
+
...base,
|
|
207
|
+
data: {
|
|
208
|
+
setupStatus: setup && evidence
|
|
209
|
+
? "READY"
|
|
210
|
+
: "ACTION_REQUIRED",
|
|
211
|
+
runtimeStatus: evidence ? "RUNNING" : "STOPPED",
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
observedEffects: evidence
|
|
215
|
+
? ["Observes real Chrome MV3 load evidence"]
|
|
216
|
+
: [],
|
|
217
|
+
};
|
|
218
|
+
},
|
|
219
|
+
setup: async (context) => {
|
|
220
|
+
await mkdir(stateDir(context), { recursive: true, mode: 0o700 });
|
|
221
|
+
const supplied = input(context);
|
|
222
|
+
let setup = await readSetup(context);
|
|
223
|
+
if (supplied.extensionId) {
|
|
224
|
+
if (!/^[a-z]{32}$/.test(supplied.extensionId))
|
|
225
|
+
return {
|
|
226
|
+
result: failed("SETUP_FAILED", "extensionId must be a canonical 32-character Chromium extension id", false),
|
|
227
|
+
observedEffects: [],
|
|
228
|
+
};
|
|
229
|
+
setup = { extensionId: supplied.extensionId };
|
|
230
|
+
await writeFile(setupFile(context), `${JSON.stringify(setup, null, 2)}\n`, { mode: 0o600 });
|
|
231
|
+
}
|
|
232
|
+
if (!setup)
|
|
233
|
+
return {
|
|
234
|
+
result: {
|
|
235
|
+
...base,
|
|
236
|
+
ok: false,
|
|
237
|
+
status: "ACTION_REQUIRED",
|
|
238
|
+
actionRequired: {
|
|
239
|
+
action: "load-unpacked-extension",
|
|
240
|
+
description: `Load ${browserExtensionLoadDir(context.workspaceRoot)} in Chrome, copy its extensionId, then rerun Module.setup with extensionId.`,
|
|
170
241
|
},
|
|
242
|
+
},
|
|
171
243
|
observedEffects: [],
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
: {
|
|
182
|
-
...boundBase,
|
|
183
|
-
ok: false,
|
|
184
|
-
status: "ACTION_REQUIRED",
|
|
185
|
-
actionRequired: {
|
|
186
|
-
action: "configure-browser-extension",
|
|
187
|
-
description: "Browser Extension runtime config is not materialized",
|
|
188
|
-
},
|
|
189
|
-
},
|
|
244
|
+
};
|
|
245
|
+
try {
|
|
246
|
+
await materialize(context, setup);
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
return {
|
|
250
|
+
result: failed("SETUP_FAILED", error instanceof Error
|
|
251
|
+
? error.message
|
|
252
|
+
: "browser extension config materialization failed"),
|
|
190
253
|
observedEffects: [],
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
observedEffects: evidence
|
|
218
|
-
? ["Observes real Chrome MV3 load evidence"]
|
|
219
|
-
: [],
|
|
220
|
-
};
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
if (supplied.serviceWorker === "RUNNING") {
|
|
257
|
+
const evidence = {
|
|
258
|
+
contract: "proflow.browser-extension-verification.v1",
|
|
259
|
+
moduleVersion: descriptor.moduleVersion,
|
|
260
|
+
loadDir: browserExtensionLoadDir(context.workspaceRoot),
|
|
261
|
+
extensionId: setup.extensionId,
|
|
262
|
+
serviceWorker: "RUNNING",
|
|
263
|
+
observedAt: supplied.observedAt ?? new Date().toISOString(),
|
|
264
|
+
};
|
|
265
|
+
await writeFile(verificationFile(context), `${JSON.stringify(evidence, null, 2)}\n`, { mode: 0o600 });
|
|
266
|
+
return {
|
|
267
|
+
result: base,
|
|
268
|
+
observedEffects: ["Records real Chrome MV3 load evidence"],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
result: {
|
|
273
|
+
...base,
|
|
274
|
+
ok: false,
|
|
275
|
+
status: "ACTION_REQUIRED",
|
|
276
|
+
actionRequired: {
|
|
277
|
+
action: "reload-and-verify-extension",
|
|
278
|
+
description: "Reload the unpacked extension after runtime config materialization, confirm its MV3 service worker is RUNNING, then rerun Module.setup with serviceWorker=RUNNING.",
|
|
279
|
+
},
|
|
221
280
|
},
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
281
|
+
observedEffects: [],
|
|
282
|
+
};
|
|
283
|
+
},
|
|
284
|
+
docs: async (_context) => ({
|
|
285
|
+
result: { ...base, data: { docs: "DOCS.md", setup: "SETUP.md" } },
|
|
286
|
+
observedEffects: [],
|
|
287
|
+
}),
|
|
288
|
+
start: async (context) => {
|
|
289
|
+
const loadDir = browserExtensionLoadDir(context.workspaceRoot);
|
|
290
|
+
return {
|
|
291
|
+
result: (await readEvidence(context, loadDir))
|
|
292
|
+
? base
|
|
293
|
+
: failed("START_FAILED", "browser extension setup is not READY"),
|
|
294
|
+
observedEffects: [],
|
|
295
|
+
};
|
|
296
|
+
},
|
|
297
|
+
stop: async (_context) => ({
|
|
298
|
+
result: base,
|
|
299
|
+
observedEffects: [],
|
|
300
|
+
}),
|
|
301
|
+
};
|
|
@@ -3,11 +3,10 @@ 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.
|
|
6
|
+
readonly moduleVersion: "0.1.5";
|
|
7
7
|
readonly kind: "browser-extension";
|
|
8
8
|
readonly templateVersion: "1.0.0";
|
|
9
9
|
readonly platformCompatibility: ">=1.0.0 <2.0.0";
|
|
10
|
-
readonly installClass: "core";
|
|
11
10
|
readonly identity: {
|
|
12
11
|
readonly domain: "execution";
|
|
13
12
|
readonly summary: "Execution-owned MV3 Browser executor, evidence provider and browser application surface.";
|
|
@@ -34,75 +33,14 @@ export declare const descriptor: {
|
|
|
34
33
|
readonly kind: "human";
|
|
35
34
|
readonly action: "Load and verify the unpacked MV3 extension in the real Chrome profile";
|
|
36
35
|
}];
|
|
37
|
-
readonly configSlots: readonly [
|
|
38
|
-
readonly key: "bridge.endpoint";
|
|
39
|
-
readonly type: "url";
|
|
40
|
-
readonly required: true;
|
|
41
|
-
readonly description: "Loopback Browser Reality Bridge endpoint";
|
|
42
|
-
}, {
|
|
43
|
-
readonly key: "bridge.token";
|
|
44
|
-
readonly type: "path";
|
|
45
|
-
readonly required: true;
|
|
46
|
-
readonly sensitive: true;
|
|
47
|
-
readonly description: "File containing the Browser Reality Bridge extension token";
|
|
48
|
-
}, {
|
|
49
|
-
readonly key: "taskApplication.endpoint";
|
|
50
|
-
readonly type: "url";
|
|
51
|
-
readonly required: true;
|
|
52
|
-
readonly description: "Loopback Platform Host Task application endpoint";
|
|
53
|
-
}, {
|
|
54
|
-
readonly key: "taskApplication.token";
|
|
55
|
-
readonly type: "path";
|
|
56
|
-
readonly required: true;
|
|
57
|
-
readonly sensitive: true;
|
|
58
|
-
readonly description: "File containing the Platform Host Task application token";
|
|
59
|
-
}, {
|
|
60
|
-
readonly key: "approvalApplication.endpoint";
|
|
61
|
-
readonly type: "url";
|
|
62
|
-
readonly required: true;
|
|
63
|
-
readonly description: "Loopback Platform Host Approval application endpoint";
|
|
64
|
-
}, {
|
|
65
|
-
readonly key: "approvalApplication.token";
|
|
66
|
-
readonly type: "path";
|
|
67
|
-
readonly required: true;
|
|
68
|
-
readonly sensitive: true;
|
|
69
|
-
readonly description: "File containing the Platform Host Approval application token";
|
|
70
|
-
}, {
|
|
71
|
-
readonly key: "verificationEvidenceFile";
|
|
72
|
-
readonly type: "path";
|
|
73
|
-
readonly required: true;
|
|
74
|
-
readonly description: "JSON evidence file written after real Chrome loads the Deployment-managed MV3 extension and its Service Worker runs";
|
|
75
|
-
}, {
|
|
76
|
-
readonly key: "chromeRuntimeModuleRef";
|
|
77
|
-
readonly type: "moduleRef";
|
|
78
|
-
readonly required: false;
|
|
79
|
-
readonly description: "External resource module governing the Chrome runtime";
|
|
80
|
-
readonly default: "chrome-runtime";
|
|
81
|
-
}, {
|
|
82
|
-
readonly key: "carrierModuleRef";
|
|
83
|
-
readonly type: "moduleRef";
|
|
84
|
-
readonly required: false;
|
|
85
|
-
readonly description: "External resource module governing the Custom GPT carrier";
|
|
86
|
-
readonly default: "chatgpt-carrier";
|
|
87
|
-
}];
|
|
88
|
-
readonly lifecycle: {
|
|
89
|
-
readonly supported: readonly ["describe", "preflight", "status", "verify", "doctor"];
|
|
90
|
-
};
|
|
91
|
-
readonly verification: {
|
|
92
|
-
readonly checks: readonly [{
|
|
93
|
-
readonly id: "real-carrier-e3-e4";
|
|
94
|
-
readonly description: "Real Chrome and ChatGPT E3/E4 evidence is present";
|
|
95
|
-
readonly lifecycle: "verify";
|
|
96
|
-
}];
|
|
97
|
-
};
|
|
36
|
+
readonly configSlots: readonly [];
|
|
98
37
|
readonly effects: readonly [{
|
|
99
38
|
readonly kind: "external-resource";
|
|
100
|
-
readonly description: "
|
|
39
|
+
readonly description: "Materialize the unpacked MV3 extension package";
|
|
101
40
|
readonly retention: "preserve";
|
|
102
41
|
}];
|
|
103
|
-
readonly documentation:
|
|
104
|
-
readonly
|
|
105
|
-
readonly
|
|
106
|
-
|
|
107
|
-
}];
|
|
42
|
+
readonly documentation: {
|
|
43
|
+
readonly docs: "DOCS.md";
|
|
44
|
+
readonly setup: "SETUP.md";
|
|
45
|
+
};
|
|
108
46
|
};
|
|
@@ -3,113 +3,55 @@ 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.
|
|
6
|
+
moduleVersion: "0.1.5",
|
|
7
7
|
kind: "browser-extension",
|
|
8
8
|
templateVersion: "1.0.0",
|
|
9
9
|
platformCompatibility: ">=1.0.0 <2.0.0",
|
|
10
|
-
installClass: "core",
|
|
11
10
|
identity: {
|
|
12
11
|
domain: "execution",
|
|
13
12
|
summary: "Execution-owned MV3 Browser executor, evidence provider and browser application surface.",
|
|
14
13
|
},
|
|
15
|
-
provides: [
|
|
16
|
-
requires: [
|
|
17
|
-
{ contractRef: "execution", versionRange: ">=1.0.0 <2.0.0" },
|
|
18
|
-
{ contractRef: "task-orchestration", versionRange: ">=1.0.0 <2.0.0" },
|
|
19
|
-
{ contractRef: "agent-runtime", versionRange: ">=1.0.0 <2.0.0" },
|
|
20
|
-
],
|
|
21
|
-
requirements: [
|
|
22
|
-
{ kind: "runtime", runtime: "browser", versionRange: ">=1" },
|
|
14
|
+
provides: [
|
|
23
15
|
{
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
contractRef: "execution-browser-executor",
|
|
17
|
+
version: "1.0.0",
|
|
26
18
|
},
|
|
27
19
|
],
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
key: "bridge.endpoint",
|
|
31
|
-
type: "url",
|
|
32
|
-
required: true,
|
|
33
|
-
description: "Loopback Browser Reality Bridge endpoint",
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
key: "bridge.token",
|
|
37
|
-
type: "path",
|
|
38
|
-
required: true,
|
|
39
|
-
sensitive: true,
|
|
40
|
-
description: "File containing the Browser Reality Bridge extension token",
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
key: "taskApplication.endpoint",
|
|
44
|
-
type: "url",
|
|
45
|
-
required: true,
|
|
46
|
-
description: "Loopback Platform Host Task application endpoint",
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
key: "taskApplication.token",
|
|
50
|
-
type: "path",
|
|
51
|
-
required: true,
|
|
52
|
-
sensitive: true,
|
|
53
|
-
description: "File containing the Platform Host Task application token",
|
|
54
|
-
},
|
|
20
|
+
requires: [
|
|
55
21
|
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
required: true,
|
|
59
|
-
description: "Loopback Platform Host Approval application endpoint",
|
|
22
|
+
contractRef: "execution",
|
|
23
|
+
versionRange: ">=1.0.0 <2.0.0",
|
|
60
24
|
},
|
|
61
25
|
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
required: true,
|
|
65
|
-
sensitive: true,
|
|
66
|
-
description: "File containing the Platform Host Approval application token",
|
|
26
|
+
contractRef: "task-orchestration",
|
|
27
|
+
versionRange: ">=1.0.0 <2.0.0",
|
|
67
28
|
},
|
|
68
29
|
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
required: true,
|
|
72
|
-
description: "JSON evidence file written after real Chrome loads the Deployment-managed MV3 extension and its Service Worker runs",
|
|
30
|
+
contractRef: "agent-runtime",
|
|
31
|
+
versionRange: ">=1.0.0 <2.0.0",
|
|
73
32
|
},
|
|
33
|
+
],
|
|
34
|
+
requirements: [
|
|
74
35
|
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
description: "External resource module governing the Chrome runtime",
|
|
79
|
-
default: "chrome-runtime",
|
|
36
|
+
kind: "runtime",
|
|
37
|
+
runtime: "browser",
|
|
38
|
+
versionRange: ">=1",
|
|
80
39
|
},
|
|
81
40
|
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
required: false,
|
|
85
|
-
description: "External resource module governing the Custom GPT carrier",
|
|
86
|
-
default: "chatgpt-carrier",
|
|
41
|
+
kind: "human",
|
|
42
|
+
action: "Load and verify the unpacked MV3 extension in the real Chrome profile",
|
|
87
43
|
},
|
|
88
44
|
],
|
|
89
|
-
|
|
90
|
-
supported: ["describe", "preflight", "status", "verify", "doctor"],
|
|
91
|
-
},
|
|
92
|
-
verification: {
|
|
93
|
-
checks: [
|
|
94
|
-
{
|
|
95
|
-
id: "real-carrier-e3-e4",
|
|
96
|
-
description: "Real Chrome and ChatGPT E3/E4 evidence is present",
|
|
97
|
-
lifecycle: "verify",
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
},
|
|
45
|
+
configSlots: [],
|
|
101
46
|
effects: [
|
|
102
47
|
{
|
|
103
48
|
kind: "external-resource",
|
|
104
|
-
description: "
|
|
49
|
+
description: "Materialize the unpacked MV3 extension package",
|
|
105
50
|
retention: "preserve",
|
|
106
51
|
},
|
|
107
52
|
],
|
|
108
|
-
documentation:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
description: "Package-owned module overview",
|
|
113
|
-
},
|
|
114
|
-
],
|
|
53
|
+
documentation: {
|
|
54
|
+
docs: "DOCS.md",
|
|
55
|
+
setup: "SETUP.md",
|
|
56
|
+
},
|
|
115
57
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { materializeProductionConfig } from "../deployment/adapter.js";
|
|
5
|
+
function workspaceFromArgs(args) {
|
|
6
|
+
if (args[0] !== "materialize-config") {
|
|
7
|
+
throw new Error("Usage: proflow-execution-browser-extension materialize-config [--workspace /absolute/path]");
|
|
8
|
+
}
|
|
9
|
+
const workspaceIndex = args.indexOf("--workspace");
|
|
10
|
+
if (workspaceIndex < 0)
|
|
11
|
+
return process.cwd();
|
|
12
|
+
const value = args[workspaceIndex + 1];
|
|
13
|
+
if (!value || args.length !== 3) {
|
|
14
|
+
throw new Error("Usage: proflow-execution-browser-extension materialize-config [--workspace /absolute/path]");
|
|
15
|
+
}
|
|
16
|
+
return resolve(value);
|
|
17
|
+
}
|
|
18
|
+
export async function materializeBrowserExtensionConfig(workspaceRoot) {
|
|
19
|
+
const configPath = resolve(workspaceRoot, ".proflow", "config", "execution-browser-extension.json");
|
|
20
|
+
const parsed = JSON.parse(await readFile(configPath, "utf8"));
|
|
21
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
22
|
+
throw new Error("execution-browser-extension config must be a JSON object");
|
|
23
|
+
}
|
|
24
|
+
const config = Object.fromEntries(Object.entries(parsed).map(([key, value]) => {
|
|
25
|
+
if (typeof value !== "string") {
|
|
26
|
+
throw new Error(`browser extension config ${key} must be a string`);
|
|
27
|
+
}
|
|
28
|
+
return [key, value];
|
|
29
|
+
}));
|
|
30
|
+
return materializeProductionConfig({
|
|
31
|
+
moduleRef: "execution-browser-extension",
|
|
32
|
+
config,
|
|
33
|
+
workspaceRoot,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async function main() {
|
|
37
|
+
const workspaceRoot = workspaceFromArgs(process.argv.slice(2));
|
|
38
|
+
const result = await materializeBrowserExtensionConfig(workspaceRoot);
|
|
39
|
+
process.stdout.write(`${JSON.stringify({ status: "MATERIALIZED", ...result })}\n`);
|
|
40
|
+
}
|
|
41
|
+
if (import.meta.main)
|
|
42
|
+
await main();
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomflow/proflow-execution-browser-extension",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Execution-owned MV3 Browser executor, evidence provider and browser application surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"./bridge": "./dist/src/bridge.js",
|
|
12
12
|
"./deployment/adapter": "./dist/deployment/adapter.js",
|
|
13
13
|
"./deployment/descriptor": "./dist/deployment/descriptor.js",
|
|
14
|
-
"./runtime-composition": "./dist/src/runtime-composition.js"
|
|
14
|
+
"./runtime-composition": "./dist/src/runtime-composition.js",
|
|
15
|
+
"./configure": "./dist/src/configure.js"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"dist",
|
|
@@ -21,15 +22,16 @@
|
|
|
21
22
|
"proflow.module.json",
|
|
22
23
|
"conformance.json",
|
|
23
24
|
"README.md",
|
|
24
|
-
"
|
|
25
|
+
"DOCS.md",
|
|
26
|
+
"SETUP.md"
|
|
25
27
|
],
|
|
26
28
|
"dependencies": {
|
|
27
|
-
"@tomflow/proflow-execution-contracts": "^0.1.
|
|
29
|
+
"@tomflow/proflow-execution-contracts": "^0.1.4",
|
|
30
|
+
"@tomflow/proflow-module-contract": "^0.1.4"
|
|
28
31
|
},
|
|
29
32
|
"devDependencies": {
|
|
30
|
-
"@tomflow/proflow-
|
|
31
|
-
"@tomflow/proflow-deployment-conformance": "^0.1.
|
|
32
|
-
"@tomflow/proflow-execution-runtime": "^0.1.2"
|
|
33
|
+
"@tomflow/proflow-execution-runtime": "^0.1.7",
|
|
34
|
+
"@tomflow/proflow-deployment-conformance": "^0.1.4"
|
|
33
35
|
},
|
|
34
36
|
"keywords": [
|
|
35
37
|
"proflow",
|
|
@@ -38,20 +40,11 @@
|
|
|
38
40
|
],
|
|
39
41
|
"proflow": {
|
|
40
42
|
"module": true,
|
|
41
|
-
"installClass": "core",
|
|
42
|
-
"installRequires": [
|
|
43
|
-
"@tomflow/proflow-agent-runtime",
|
|
44
|
-
"@tomflow/proflow-chatgpt-carrier",
|
|
45
|
-
"@tomflow/proflow-chrome-runtime",
|
|
46
|
-
"@tomflow/proflow-execution-contracts",
|
|
47
|
-
"@tomflow/proflow-execution-runtime",
|
|
48
|
-
"@tomflow/proflow-task-orchestration"
|
|
49
|
-
],
|
|
50
43
|
"descriptor": "./dist/deployment/descriptor.js",
|
|
51
44
|
"manifest": "./proflow.module.json"
|
|
52
45
|
},
|
|
53
46
|
"bin": {
|
|
54
|
-
"proflow-execution-browser-extension": "./
|
|
47
|
+
"proflow-execution-browser-extension": "./dist/src/configure.js"
|
|
55
48
|
},
|
|
56
49
|
"scripts": {
|
|
57
50
|
"test": "node --test tests/**/*.test.ts",
|
package/proflow.module.json
CHANGED
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
"contractVersion": "1.0.0",
|
|
4
4
|
"moduleRef": "execution-browser-extension",
|
|
5
5
|
"packageName": "@tomflow/proflow-execution-browser-extension",
|
|
6
|
-
"moduleVersion": "0.1.
|
|
6
|
+
"moduleVersion": "0.1.5",
|
|
7
7
|
"kind": "browser-extension",
|
|
8
8
|
"templateVersion": "1.0.0",
|
|
9
9
|
"platformCompatibility": ">=1.0.0 <2.0.0",
|
|
10
|
-
"installClass": "core",
|
|
11
10
|
"identity": {
|
|
12
11
|
"domain": "execution",
|
|
13
12
|
"summary": "Execution-owned MV3 Browser executor, evidence provider and browser application surface."
|
|
@@ -43,91 +42,16 @@
|
|
|
43
42
|
"action": "Load and verify the unpacked MV3 extension in the real Chrome profile"
|
|
44
43
|
}
|
|
45
44
|
],
|
|
46
|
-
"configSlots": [
|
|
47
|
-
{
|
|
48
|
-
"key": "bridge.endpoint",
|
|
49
|
-
"type": "url",
|
|
50
|
-
"required": true,
|
|
51
|
-
"description": "Loopback Browser Reality Bridge endpoint"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"key": "bridge.token",
|
|
55
|
-
"type": "path",
|
|
56
|
-
"required": true,
|
|
57
|
-
"sensitive": true,
|
|
58
|
-
"description": "File containing the Browser Reality Bridge extension token"
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
"key": "taskApplication.endpoint",
|
|
62
|
-
"type": "url",
|
|
63
|
-
"required": true,
|
|
64
|
-
"description": "Loopback Platform Host Task application endpoint"
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
"key": "taskApplication.token",
|
|
68
|
-
"type": "path",
|
|
69
|
-
"required": true,
|
|
70
|
-
"sensitive": true,
|
|
71
|
-
"description": "File containing the Platform Host Task application token"
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"key": "approvalApplication.endpoint",
|
|
75
|
-
"type": "url",
|
|
76
|
-
"required": true,
|
|
77
|
-
"description": "Loopback Platform Host Approval application endpoint"
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
"key": "approvalApplication.token",
|
|
81
|
-
"type": "path",
|
|
82
|
-
"required": true,
|
|
83
|
-
"sensitive": true,
|
|
84
|
-
"description": "File containing the Platform Host Approval application token"
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"key": "verificationEvidenceFile",
|
|
88
|
-
"type": "path",
|
|
89
|
-
"required": true,
|
|
90
|
-
"description": "JSON evidence file written after real Chrome loads the Deployment-managed MV3 extension and its Service Worker runs"
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
"key": "chromeRuntimeModuleRef",
|
|
94
|
-
"type": "moduleRef",
|
|
95
|
-
"required": false,
|
|
96
|
-
"description": "External resource module governing the Chrome runtime",
|
|
97
|
-
"default": "chrome-runtime"
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
"key": "carrierModuleRef",
|
|
101
|
-
"type": "moduleRef",
|
|
102
|
-
"required": false,
|
|
103
|
-
"description": "External resource module governing the Custom GPT carrier",
|
|
104
|
-
"default": "chatgpt-carrier"
|
|
105
|
-
}
|
|
106
|
-
],
|
|
107
|
-
"lifecycle": {
|
|
108
|
-
"supported": ["describe", "preflight", "status", "verify", "doctor"]
|
|
109
|
-
},
|
|
110
|
-
"verification": {
|
|
111
|
-
"checks": [
|
|
112
|
-
{
|
|
113
|
-
"id": "real-carrier-e3-e4",
|
|
114
|
-
"description": "Real Chrome and ChatGPT E3/E4 evidence is present",
|
|
115
|
-
"lifecycle": "verify"
|
|
116
|
-
}
|
|
117
|
-
]
|
|
118
|
-
},
|
|
45
|
+
"configSlots": [],
|
|
119
46
|
"effects": [
|
|
120
47
|
{
|
|
121
48
|
"kind": "external-resource",
|
|
122
|
-
"description": "
|
|
49
|
+
"description": "Materialize the unpacked MV3 extension package",
|
|
123
50
|
"retention": "preserve"
|
|
124
51
|
}
|
|
125
52
|
],
|
|
126
|
-
"documentation":
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
"description": "Package-owned module overview"
|
|
131
|
-
}
|
|
132
|
-
]
|
|
53
|
+
"documentation": {
|
|
54
|
+
"docs": "DOCS.md",
|
|
55
|
+
"setup": "SETUP.md"
|
|
56
|
+
}
|
|
133
57
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# @tomflow/proflow-execution-browser-extension
|
|
2
|
-
|
|
3
|
-
## 0.1.3
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Real-1 final remediation and black-box release closure
|
|
8
|
-
|
|
9
|
-
## 0.1.2
|
|
10
|
-
|
|
11
|
-
### Patch Changes
|
|
12
|
-
|
|
13
|
-
- Close the Real-1 global Platform control-plane contract across every published ProFlow package. Platform CLI now owns one durable global Workspace binding with canonical identity, cross-process operation locking, cwd/`--workspace` install targeting, cross-directory instance commands, whole-instance uninstall/rebind, and deterministic npm/yarn/pnpm Workspace package-manager selection. Every package-owned install entry, including newly generated Module Template packages, delegates to the Shell-global `platform` command and fails closed when that global CLI is unavailable; Deployment Conformance and the formal test plans mechanically enforce the same rule across all 24 packages.
|
|
14
|
-
|
|
15
|
-
## 0.1.1
|
|
16
|
-
|
|
17
|
-
### Patch Changes
|
|
18
|
-
|
|
19
|
-
- Close Real-1 deployment graph and Fresh Workspace bootstrap gaps: remove Contract-library runtime-provider aliases, correct Execution/Model dependency direction, materialize logical/moduleRef providers through `installRequires`, enforce repository graph validation, and keep self-install executables stable without package-manager worktree mutation.
|
package/self-install.mjs
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawnSync } from "node:child_process";
|
|
3
|
-
|
|
4
|
-
const [command, ...rest] = process.argv.slice(2);
|
|
5
|
-
const usage =
|
|
6
|
-
"Usage: npx @tomflow/proflow-execution-browser-extension install\n";
|
|
7
|
-
if (command === "--help" || command === "-h") {
|
|
8
|
-
process.stdout.write(usage);
|
|
9
|
-
process.exit(0);
|
|
10
|
-
}
|
|
11
|
-
if (command !== "install" || rest.length > 0) {
|
|
12
|
-
process.stderr.write(usage);
|
|
13
|
-
process.exit(2);
|
|
14
|
-
}
|
|
15
|
-
const executable = process.platform === "win32" ? "platform.cmd" : "platform";
|
|
16
|
-
const result = spawnSync(
|
|
17
|
-
executable,
|
|
18
|
-
[
|
|
19
|
-
"install",
|
|
20
|
-
"@tomflow/proflow-execution-browser-extension",
|
|
21
|
-
"--workspace",
|
|
22
|
-
process.cwd(),
|
|
23
|
-
],
|
|
24
|
-
{ cwd: process.cwd(), env: process.env, stdio: "inherit" },
|
|
25
|
-
);
|
|
26
|
-
if (result.error) {
|
|
27
|
-
if (result.error.code === "ENOENT") {
|
|
28
|
-
process.stderr.write(
|
|
29
|
-
"GLOBAL_PLATFORM_CLI_REQUIRED: install @tomflow/proflow-platform-cli globally before package-owned install\n",
|
|
30
|
-
);
|
|
31
|
-
process.exit(127);
|
|
32
|
-
}
|
|
33
|
-
throw result.error;
|
|
34
|
-
}
|
|
35
|
-
process.exit(result.status ?? 1);
|