@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.
@@ -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.34";
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.34";
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.34";
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.34";
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.34";
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.34";
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.34";
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.34";
183
+ readonly moduleVersion: "0.1.35";
184
184
  } | {
185
185
  contract: "deployment.result.v1";
186
186
  moduleRef: "execution-browser-extension";
187
- moduleVersion: "0.1.34";
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.34";
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.34";
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.34",
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 = 0;
14522
- let lastExtensionKeepaliveAt = 0;
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(() => ({}));
@@ -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;
@@ -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: session !== undefined && now().getTime() - session.lastHeartbeatAt <= freshnessMs,
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
- lastCommandResultAt = now().toISOString();
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 heartbeat is not fresh"));
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;
@@ -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
- let lastHeartbeatAt = 0;
1010
- let lastExtensionKeepaliveAt = 0;
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "ProFlow Execution Browser",
4
- "version": "0.1.34",
4
+ "version": "0.1.35",
5
5
  "permissions": [
6
6
  "tabs",
7
7
  "storage"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-execution-browser-extension",
3
- "version": "0.1.34",
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-execution-contracts": "^0.1.10",
31
- "@tomflow/proflow-module-contract": "^0.1.13"
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",
@@ -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.34",
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",