@tomflow/proflow-execution-browser-extension 0.1.34 → 0.1.35
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/dist/deployment/adapter.d.ts +10 -10
- package/dist/deployment/descriptor.d.ts +1 -1
- package/dist/deployment/descriptor.js +1 -1
- package/dist/extension/background.js +5 -3
- package/dist/src/bridge.d.ts +2 -0
- package/dist/src/bridge.js +23 -9
- package/dist/src/runtime-composition.d.ts +2 -0
- package/extension/background.ts +7 -3
- package/manifest.json +1 -1
- package/package.json +3 -3
- package/proflow.module.json +1 -1
|
@@ -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.
|
|
50
|
+
moduleVersion: "0.1.35";
|
|
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.
|
|
63
|
+
readonly moduleVersion: "0.1.35";
|
|
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.
|
|
73
|
+
moduleVersion: "0.1.35";
|
|
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.
|
|
98
|
+
moduleVersion: "0.1.35";
|
|
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.
|
|
130
|
+
readonly moduleVersion: "0.1.35";
|
|
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.
|
|
137
|
+
moduleVersion: "0.1.35";
|
|
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.
|
|
170
|
+
moduleVersion: "0.1.35";
|
|
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.
|
|
183
|
+
readonly moduleVersion: "0.1.35";
|
|
184
184
|
} | {
|
|
185
185
|
contract: "deployment.result.v1";
|
|
186
186
|
moduleRef: "execution-browser-extension";
|
|
187
|
-
moduleVersion: "0.1.
|
|
187
|
+
moduleVersion: "0.1.35";
|
|
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.
|
|
204
|
+
readonly moduleVersion: "0.1.35";
|
|
205
205
|
};
|
|
206
206
|
observedEffects: never[];
|
|
207
207
|
}>;
|
|
@@ -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.
|
|
6
|
+
readonly moduleVersion: "0.1.35";
|
|
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.
|
|
6
|
+
moduleVersion: "0.1.35",
|
|
7
7
|
kind: "browser-extension",
|
|
8
8
|
templateVersion: "1.0.0",
|
|
9
9
|
platformCompatibility: ">=1.0.0 <2.0.0",
|
|
@@ -13878,6 +13878,7 @@ var extensionInstanceId = `extension:${crypto.randomUUID()}`;
|
|
|
13878
13878
|
var sessions = /* @__PURE__ */ new Map();
|
|
13879
13879
|
var BROWSER_CARRIER_KEEPALIVE_KEY = "proflowBrowserSnapshot";
|
|
13880
13880
|
var BROWSER_CARRIER_KEEPALIVE_MS = 2e4;
|
|
13881
|
+
var BROWSER_BRIDGE_FETCH_TIMEOUT_MS = 5e3;
|
|
13881
13882
|
var sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
13882
13883
|
async function persistSnapshot() {
|
|
13883
13884
|
await chrome.storage.session.set({
|
|
@@ -14491,6 +14492,7 @@ async function executeProvisioningCommand(command) {
|
|
|
14491
14492
|
async function bridgeFetch(config2, path, init = {}) {
|
|
14492
14493
|
return fetch(`${config2.endpoint}${path}`, {
|
|
14493
14494
|
...init,
|
|
14495
|
+
signal: init.signal ?? AbortSignal.timeout(BROWSER_BRIDGE_FETCH_TIMEOUT_MS),
|
|
14494
14496
|
headers: {
|
|
14495
14497
|
authorization: `Bearer ${config2.token}`,
|
|
14496
14498
|
"content-type": "application/json",
|
|
@@ -14503,7 +14505,7 @@ async function runBridgeLoop() {
|
|
|
14503
14505
|
if (bridgeLoopStarted) return;
|
|
14504
14506
|
bridgeLoopStarted = true;
|
|
14505
14507
|
while (true) {
|
|
14506
|
-
const config2 = await bridgeConfig();
|
|
14508
|
+
const config2 = await bridgeConfig().catch(() => null);
|
|
14507
14509
|
if (!config2) {
|
|
14508
14510
|
await sleep(1e3);
|
|
14509
14511
|
continue;
|
|
@@ -14518,8 +14520,8 @@ async function runBridgeLoop() {
|
|
|
14518
14520
|
})
|
|
14519
14521
|
});
|
|
14520
14522
|
if (!hello.ok) throw new Error("BRIDGE_HELLO_REJECTED");
|
|
14521
|
-
let lastHeartbeatAt =
|
|
14522
|
-
let lastExtensionKeepaliveAt =
|
|
14523
|
+
let lastHeartbeatAt = Date.now();
|
|
14524
|
+
let lastExtensionKeepaliveAt = Date.now();
|
|
14523
14525
|
while (true) {
|
|
14524
14526
|
if (Date.now() - lastExtensionKeepaliveAt >= BROWSER_CARRIER_KEEPALIVE_MS) {
|
|
14525
14527
|
await chrome.storage.session.get(BROWSER_CARRIER_KEEPALIVE_KEY).catch(() => ({}));
|
package/dist/src/bridge.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export declare function createBrowserRealityBridgeServer(options: BrowserReality
|
|
|
25
25
|
browser: BrowserRealityPort;
|
|
26
26
|
status(): {
|
|
27
27
|
online: boolean;
|
|
28
|
+
sessionOnline: boolean;
|
|
29
|
+
commandConsumerReady: boolean;
|
|
28
30
|
extensionInstanceId: string | null;
|
|
29
31
|
queuedCommands: number;
|
|
30
32
|
pendingCommands: number;
|
package/dist/src/bridge.js
CHANGED
|
@@ -118,6 +118,7 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
118
118
|
let lastCommandPollAt = null;
|
|
119
119
|
let lastCommandDeliveredAt = null;
|
|
120
120
|
let lastCommandResultAt = null;
|
|
121
|
+
let lastCommandConsumerAt = null;
|
|
121
122
|
let closed = false;
|
|
122
123
|
let endpoint = "";
|
|
123
124
|
const taskBootstrap = new Map();
|
|
@@ -125,6 +126,13 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
125
126
|
const taskCookie = "proflow_tasks_session";
|
|
126
127
|
const taskBootstrapTtlMs = 60_000;
|
|
127
128
|
const taskSessionTtlMs = 8 * 60 * 60_000;
|
|
129
|
+
const sessionOnline = () => !closed &&
|
|
130
|
+
session !== undefined &&
|
|
131
|
+
now().getTime() - session.lastHeartbeatAt <= freshnessMs;
|
|
132
|
+
const commandConsumerReady = () => sessionOnline() &&
|
|
133
|
+
lastCommandConsumerAt !== null &&
|
|
134
|
+
now().getTime() - lastCommandConsumerAt <= freshnessMs;
|
|
135
|
+
const online = commandConsumerReady;
|
|
128
136
|
const pruneTaskWebState = () => {
|
|
129
137
|
const current = now().getTime();
|
|
130
138
|
for (const [key, expiresAt] of taskBootstrap)
|
|
@@ -189,7 +197,9 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
189
197
|
approvalApplicationConfigured: true,
|
|
190
198
|
systemObserver: null,
|
|
191
199
|
browserCarrier: {
|
|
192
|
-
online:
|
|
200
|
+
online: commandConsumerReady(),
|
|
201
|
+
sessionOnline: sessionOnline(),
|
|
202
|
+
commandConsumerReady: commandConsumerReady(),
|
|
193
203
|
extensionInstanceId: session?.extensionInstanceId ?? null,
|
|
194
204
|
queuedCommands: queue.length,
|
|
195
205
|
pendingCommands: pending.size,
|
|
@@ -245,6 +255,7 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
245
255
|
lastCommandPollAt = null;
|
|
246
256
|
lastCommandDeliveredAt = null;
|
|
247
257
|
lastCommandResultAt = null;
|
|
258
|
+
lastCommandConsumerAt = null;
|
|
248
259
|
}
|
|
249
260
|
session = {
|
|
250
261
|
extensionInstanceId,
|
|
@@ -254,10 +265,10 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
254
265
|
return;
|
|
255
266
|
}
|
|
256
267
|
if (request.method === "GET" && url.pathname === "/v1/session/status") {
|
|
257
|
-
const online = session !== undefined &&
|
|
258
|
-
now().getTime() - session.lastHeartbeatAt <= freshnessMs;
|
|
259
268
|
send(response, 200, {
|
|
260
|
-
online,
|
|
269
|
+
online: commandConsumerReady(),
|
|
270
|
+
sessionOnline: sessionOnline(),
|
|
271
|
+
commandConsumerReady: commandConsumerReady(),
|
|
261
272
|
extensionInstanceId: session?.extensionInstanceId ?? null,
|
|
262
273
|
});
|
|
263
274
|
return;
|
|
@@ -276,6 +287,7 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
276
287
|
if (request.method === "GET" && url.pathname === "/v1/commands/next") {
|
|
277
288
|
const stamp = now();
|
|
278
289
|
session.lastHeartbeatAt = stamp.getTime();
|
|
290
|
+
lastCommandConsumerAt = stamp.getTime();
|
|
279
291
|
lastCommandPollAt = stamp.toISOString();
|
|
280
292
|
const command = queue.shift();
|
|
281
293
|
if (command) {
|
|
@@ -297,7 +309,10 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
297
309
|
throw new BrowserRealityBridgeError("BRIDGE_INPUT_INVALID", "command result is stale or unknown");
|
|
298
310
|
pending.delete(commandId);
|
|
299
311
|
clearTimeout(command.timer);
|
|
300
|
-
|
|
312
|
+
const resultStamp = now();
|
|
313
|
+
session.lastHeartbeatAt = resultStamp.getTime();
|
|
314
|
+
lastCommandConsumerAt = resultStamp.getTime();
|
|
315
|
+
lastCommandResultAt = resultStamp.toISOString();
|
|
301
316
|
if (body.ok === true)
|
|
302
317
|
command.resolve(body.value);
|
|
303
318
|
else
|
|
@@ -329,12 +344,9 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
329
344
|
if (!address || typeof address === "string")
|
|
330
345
|
throw new Error("bridge address missing");
|
|
331
346
|
endpoint = `http://127.0.0.1:${address.port}`;
|
|
332
|
-
const online = () => !closed &&
|
|
333
|
-
session !== undefined &&
|
|
334
|
-
now().getTime() - session.lastHeartbeatAt <= freshnessMs;
|
|
335
347
|
const requestCommand = (command) => {
|
|
336
348
|
if (!online())
|
|
337
|
-
return Promise.reject(new BrowserRealityBridgeError("BRIDGE_OFFLINE", "extension
|
|
349
|
+
return Promise.reject(new BrowserRealityBridgeError("BRIDGE_OFFLINE", "extension command consumer is not ready"));
|
|
338
350
|
const commandId = `browser-command:${idFactory()}`;
|
|
339
351
|
return new Promise((resolve, reject) => {
|
|
340
352
|
const timer = setTimeout(() => {
|
|
@@ -406,6 +418,8 @@ export async function createBrowserRealityBridgeServer(options) {
|
|
|
406
418
|
status() {
|
|
407
419
|
return {
|
|
408
420
|
online: online(),
|
|
421
|
+
sessionOnline: sessionOnline(),
|
|
422
|
+
commandConsumerReady: commandConsumerReady(),
|
|
409
423
|
extensionInstanceId: session?.extensionInstanceId ?? null,
|
|
410
424
|
queuedCommands: queue.length,
|
|
411
425
|
pendingCommands: pending.size,
|
|
@@ -88,6 +88,8 @@ export declare function createBrowserExecutorComposition(options: BrowserExecuto
|
|
|
88
88
|
bridgeEndpoint: string;
|
|
89
89
|
bridgeStatus: () => {
|
|
90
90
|
online: boolean;
|
|
91
|
+
sessionOnline: boolean;
|
|
92
|
+
commandConsumerReady: boolean;
|
|
91
93
|
extensionInstanceId: string | null;
|
|
92
94
|
queuedCommands: number;
|
|
93
95
|
pendingCommands: number;
|
package/extension/background.ts
CHANGED
|
@@ -143,6 +143,7 @@ const extensionInstanceId = `extension:${crypto.randomUUID()}`;
|
|
|
143
143
|
const sessions = new Map<number, ContentObservation>();
|
|
144
144
|
const BROWSER_CARRIER_KEEPALIVE_KEY = "proflowBrowserSnapshot";
|
|
145
145
|
const BROWSER_CARRIER_KEEPALIVE_MS = 20_000;
|
|
146
|
+
const BROWSER_BRIDGE_FETCH_TIMEOUT_MS = 5_000;
|
|
146
147
|
|
|
147
148
|
const sleep = (milliseconds: number) =>
|
|
148
149
|
new Promise<void>((resolve) => setTimeout(resolve, milliseconds));
|
|
@@ -978,6 +979,7 @@ async function bridgeFetch(
|
|
|
978
979
|
): Promise<Response> {
|
|
979
980
|
return fetch(`${config.endpoint}${path}`, {
|
|
980
981
|
...init,
|
|
982
|
+
signal: init.signal ?? AbortSignal.timeout(BROWSER_BRIDGE_FETCH_TIMEOUT_MS),
|
|
981
983
|
headers: {
|
|
982
984
|
authorization: `Bearer ${config.token}`,
|
|
983
985
|
"content-type": "application/json",
|
|
@@ -991,7 +993,7 @@ async function runBridgeLoop() {
|
|
|
991
993
|
if (bridgeLoopStarted) return;
|
|
992
994
|
bridgeLoopStarted = true;
|
|
993
995
|
while (true) {
|
|
994
|
-
const config = await bridgeConfig();
|
|
996
|
+
const config = await bridgeConfig().catch(() => null);
|
|
995
997
|
if (!config) {
|
|
996
998
|
await sleep(1_000);
|
|
997
999
|
continue;
|
|
@@ -1006,8 +1008,10 @@ async function runBridgeLoop() {
|
|
|
1006
1008
|
}),
|
|
1007
1009
|
});
|
|
1008
1010
|
if (!hello.ok) throw new Error("BRIDGE_HELLO_REJECTED");
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
+
// Hello only establishes a session. The first inner-loop action must be
|
|
1012
|
+
// a real command poll so Runtime readiness cannot be granted by hello alone.
|
|
1013
|
+
let lastHeartbeatAt = Date.now();
|
|
1014
|
+
let lastExtensionKeepaliveAt = Date.now();
|
|
1011
1015
|
while (true) {
|
|
1012
1016
|
if (
|
|
1013
1017
|
Date.now() - lastExtensionKeepaliveAt >=
|
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.35",
|
|
4
4
|
"description": "Execution-owned MV3 Browser executor, evidence provider and browser application surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"SETUP.md"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@tomflow/proflow-
|
|
31
|
-
"@tomflow/proflow-
|
|
30
|
+
"@tomflow/proflow-module-contract": "^0.1.13",
|
|
31
|
+
"@tomflow/proflow-execution-contracts": "^0.1.10"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@tomflow/proflow-deployment-conformance": "^0.1.13",
|
package/proflow.module.json
CHANGED
|
@@ -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.
|
|
6
|
+
"moduleVersion": "0.1.35",
|
|
7
7
|
"kind": "browser-extension",
|
|
8
8
|
"templateVersion": "1.0.0",
|
|
9
9
|
"platformCompatibility": ">=1.0.0 <2.0.0",
|