@tomflow/proflow-execution-browser-extension 0.1.37 → 0.1.39
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 +687 -19
- package/dist/extension/content.js +267 -28
- package/dist/extension/tasks.js +74 -3
- package/dist/src/bridge.js +59 -6
- package/dist/src/carrier-attention-view.d.ts +13 -0
- package/dist/src/carrier-attention-view.js +54 -0
- package/dist/src/carrier-attention.d.ts +26 -0
- package/dist/src/carrier-attention.js +44 -0
- package/dist/src/carrier-continuation-control.d.ts +44 -0
- package/dist/src/carrier-continuation-control.js +114 -0
- package/dist/src/carrier-permission-attempt.d.ts +18 -0
- package/dist/src/carrier-permission-attempt.js +68 -0
- package/dist/src/carrier-permission-lifecycle.d.ts +34 -0
- package/dist/src/carrier-permission-lifecycle.js +73 -0
- package/dist/src/carrier-permission.d.ts +16 -0
- package/dist/src/carrier-permission.js +65 -0
- package/dist/src/chatgpt-runtime-adapter.d.ts +16 -0
- package/dist/src/chatgpt-runtime-adapter.js +173 -0
- package/dist/src/composer-submit.d.ts +12 -0
- package/dist/src/composer-submit.js +22 -0
- package/dist/src/pairing.js +13 -0
- package/extension/background.ts +622 -17
- package/extension/content.ts +40 -39
- package/extension/tasks.html +6 -0
- package/extension/tasks.ts +93 -5
- package/manifest.json +1 -1
- package/package.json +3 -3
- package/proflow.module.json +1 -1
|
@@ -4,6 +4,248 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
+
// packages/execution-browser-extension/src/carrier-attention.ts
|
|
8
|
+
function createCarrierAttentionRegistry(idFactory = () => crypto.randomUUID()) {
|
|
9
|
+
const byTab = /* @__PURE__ */ new Map();
|
|
10
|
+
return Object.freeze({
|
|
11
|
+
derive(input) {
|
|
12
|
+
const current = byTab.get(input.tabId);
|
|
13
|
+
if (current?.contentInstanceId === input.contentInstanceId && current.url === input.url && current.permissionFingerprint === input.permissionFingerprint) {
|
|
14
|
+
const refreshed = { ...current, ...input };
|
|
15
|
+
byTab.set(input.tabId, refreshed);
|
|
16
|
+
return refreshed;
|
|
17
|
+
}
|
|
18
|
+
const occurrenceRef = idFactory();
|
|
19
|
+
const attention = {
|
|
20
|
+
...input,
|
|
21
|
+
occurrenceRef,
|
|
22
|
+
attentionRef: `carrier-attention:${input.tabId}:${occurrenceRef}`
|
|
23
|
+
};
|
|
24
|
+
byTab.set(input.tabId, attention);
|
|
25
|
+
return attention;
|
|
26
|
+
},
|
|
27
|
+
find(attentionRef) {
|
|
28
|
+
for (const attention of byTab.values())
|
|
29
|
+
if (attention.attentionRef === attentionRef) return attention;
|
|
30
|
+
return null;
|
|
31
|
+
},
|
|
32
|
+
current(tabId) {
|
|
33
|
+
return byTab.get(tabId) ?? null;
|
|
34
|
+
},
|
|
35
|
+
values() {
|
|
36
|
+
return [...byTab.values()];
|
|
37
|
+
},
|
|
38
|
+
delete(attentionRef) {
|
|
39
|
+
for (const [tabId, attention] of byTab)
|
|
40
|
+
if (attention.attentionRef === attentionRef) return byTab.delete(tabId);
|
|
41
|
+
return false;
|
|
42
|
+
},
|
|
43
|
+
removeTab(tabId) {
|
|
44
|
+
return byTab.delete(tabId);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// packages/execution-browser-extension/src/carrier-continuation-control.ts
|
|
50
|
+
function parseDenials(value) {
|
|
51
|
+
if (value === void 0) return [];
|
|
52
|
+
if (!Array.isArray(value) || value.length > 128) return null;
|
|
53
|
+
const parsed = [];
|
|
54
|
+
for (const item of value) {
|
|
55
|
+
if (typeof item !== "object" || item === null || Array.isArray(item))
|
|
56
|
+
return null;
|
|
57
|
+
const attentionRef = Reflect.get(item, "attentionRef");
|
|
58
|
+
const tabId = Reflect.get(item, "tabId");
|
|
59
|
+
const taskId = Reflect.get(item, "taskId");
|
|
60
|
+
const roleRef = Reflect.get(item, "roleRef");
|
|
61
|
+
const workerRef = Reflect.get(item, "workerRef");
|
|
62
|
+
const url2 = Reflect.get(item, "url");
|
|
63
|
+
const contentInstanceId = Reflect.get(item, "contentInstanceId");
|
|
64
|
+
const permissionFingerprint = Reflect.get(item, "permissionFingerprint");
|
|
65
|
+
if (typeof attentionRef !== "string" || !Number.isInteger(tabId) || taskId !== null && typeof taskId !== "string" || roleRef !== null && typeof roleRef !== "string" || workerRef !== null && typeof workerRef !== "string" || typeof url2 !== "string" || typeof contentInstanceId !== "string" || typeof permissionFingerprint !== "string")
|
|
66
|
+
return null;
|
|
67
|
+
parsed.push({
|
|
68
|
+
attentionRef,
|
|
69
|
+
tabId,
|
|
70
|
+
taskId,
|
|
71
|
+
roleRef,
|
|
72
|
+
workerRef,
|
|
73
|
+
url: url2,
|
|
74
|
+
contentInstanceId,
|
|
75
|
+
permissionFingerprint
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return parsed;
|
|
79
|
+
}
|
|
80
|
+
function createCarrierContinuationControl(initial) {
|
|
81
|
+
const byTab = /* @__PURE__ */ new Map();
|
|
82
|
+
const load = (value) => {
|
|
83
|
+
const denials = parseDenials(value);
|
|
84
|
+
byTab.clear();
|
|
85
|
+
if (!denials) return false;
|
|
86
|
+
for (const denial of denials) byTab.set(denial.tabId, denial);
|
|
87
|
+
return true;
|
|
88
|
+
};
|
|
89
|
+
if (initial !== void 0) load(initial);
|
|
90
|
+
return Object.freeze({
|
|
91
|
+
beginDenied(denial) {
|
|
92
|
+
byTab.set(denial.tabId, { ...denial });
|
|
93
|
+
},
|
|
94
|
+
cancelDenied(attentionRef) {
|
|
95
|
+
for (const [tabId, denial] of byTab)
|
|
96
|
+
if (denial.attentionRef === attentionRef) return byTab.delete(tabId);
|
|
97
|
+
return false;
|
|
98
|
+
},
|
|
99
|
+
hasMatchingPermissionDenial(context) {
|
|
100
|
+
const denial = byTab.get(context.tabId);
|
|
101
|
+
return denial?.contentInstanceId === context.contentInstanceId && denial.url === context.url && denial.permissionFingerprint === context.permissionFingerprint && denial.taskId === context.taskId && denial.roleRef === context.roleRef && denial.workerRef === context.workerRef;
|
|
102
|
+
},
|
|
103
|
+
hasMatchingDispatchDenial(context) {
|
|
104
|
+
if (context.conversationLocator === null) return false;
|
|
105
|
+
for (const denial of byTab.values())
|
|
106
|
+
if (denial.taskId === context.taskId && denial.roleRef === context.roleRef && denial.workerRef === context.workerRef && denial.url === context.conversationLocator)
|
|
107
|
+
return true;
|
|
108
|
+
return false;
|
|
109
|
+
},
|
|
110
|
+
consumeRecovery(previous, current) {
|
|
111
|
+
const denial = byTab.get(current.tabId);
|
|
112
|
+
if (!denial) return null;
|
|
113
|
+
if (denial.url !== current.url || denial.contentInstanceId !== current.contentInstanceId) {
|
|
114
|
+
byTab.delete(current.tabId);
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
if (current.pageState !== "IDLE") return null;
|
|
118
|
+
if (previous && (previous.tabId !== denial.tabId || previous.url !== denial.url || previous.contentInstanceId !== denial.contentInstanceId || previous.pageState !== "BLOCKED" || previous.blockerFacts?.fingerprint !== denial.permissionFingerprint)) {
|
|
119
|
+
byTab.delete(current.tabId);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
byTab.delete(current.tabId);
|
|
123
|
+
return { ...denial };
|
|
124
|
+
},
|
|
125
|
+
suppressRecovery(previous, current) {
|
|
126
|
+
return this.consumeRecovery(previous, current) !== null;
|
|
127
|
+
},
|
|
128
|
+
snapshot() {
|
|
129
|
+
return [...byTab.values()].map((denial) => ({ ...denial }));
|
|
130
|
+
},
|
|
131
|
+
load
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// packages/execution-browser-extension/src/carrier-permission-attempt.ts
|
|
136
|
+
function parsedAttempts(value) {
|
|
137
|
+
const result = /* @__PURE__ */ new Map();
|
|
138
|
+
if (value === void 0) return { attempts: result, valid: true };
|
|
139
|
+
if (!Array.isArray(value)) return { attempts: result, valid: false };
|
|
140
|
+
let valid = value.length <= 256;
|
|
141
|
+
for (const candidate of value.slice(0, 256)) {
|
|
142
|
+
if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) {
|
|
143
|
+
valid = false;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const tabId = Reflect.get(candidate, "tabId");
|
|
147
|
+
const key = Reflect.get(candidate, "key");
|
|
148
|
+
if (!Number.isInteger(tabId) || tabId < 0 || typeof key !== "string" || key.length === 0 || key.length > 1e3) {
|
|
149
|
+
valid = false;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (result.has(tabId)) valid = false;
|
|
153
|
+
result.set(tabId, key);
|
|
154
|
+
}
|
|
155
|
+
return { attempts: result, valid };
|
|
156
|
+
}
|
|
157
|
+
function createCarrierPermissionAttemptRegistry(initial) {
|
|
158
|
+
const attempts = parsedAttempts(initial).attempts;
|
|
159
|
+
return Object.freeze({
|
|
160
|
+
has(tabId, key) {
|
|
161
|
+
return attempts.get(tabId) === key;
|
|
162
|
+
},
|
|
163
|
+
begin(tabId, key) {
|
|
164
|
+
attempts.set(tabId, key);
|
|
165
|
+
},
|
|
166
|
+
release(tabId, key) {
|
|
167
|
+
if (attempts.get(tabId) !== key) return false;
|
|
168
|
+
return attempts.delete(tabId);
|
|
169
|
+
},
|
|
170
|
+
observe(tabId, currentKey) {
|
|
171
|
+
const attempted = attempts.get(tabId);
|
|
172
|
+
if (attempted === void 0 || attempted === currentKey) return false;
|
|
173
|
+
return attempts.delete(tabId);
|
|
174
|
+
},
|
|
175
|
+
load(value) {
|
|
176
|
+
const parsed = parsedAttempts(value);
|
|
177
|
+
attempts.clear();
|
|
178
|
+
for (const [tabId, key] of parsed.attempts) attempts.set(tabId, key);
|
|
179
|
+
return parsed.valid;
|
|
180
|
+
},
|
|
181
|
+
snapshot() {
|
|
182
|
+
return [...attempts].map(([tabId, key]) => ({ tabId, key }));
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// packages/execution-browser-extension/src/carrier-permission-lifecycle.ts
|
|
188
|
+
async function resolveRoutineCarrierPermission(input) {
|
|
189
|
+
const denied = () => input.humanDenied?.() ? { status: "HUMAN_REQUIRED", reason: "HUMAN_DENIED" } : null;
|
|
190
|
+
const maxClassifications = Math.max(1, input.maxClassifications ?? 40);
|
|
191
|
+
let decision = null;
|
|
192
|
+
for (let attempt = 0; attempt < maxClassifications; attempt += 1) {
|
|
193
|
+
const beforeClassification = denied();
|
|
194
|
+
if (beforeClassification) return beforeClassification;
|
|
195
|
+
try {
|
|
196
|
+
decision = await input.port.classify();
|
|
197
|
+
} catch {
|
|
198
|
+
return {
|
|
199
|
+
status: "HUMAN_REQUIRED",
|
|
200
|
+
reason: "PERMISSION_CLASSIFICATION_FAILED"
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const afterClassification = denied();
|
|
204
|
+
if (afterClassification) return afterClassification;
|
|
205
|
+
if (decision.decision !== "DEFER") break;
|
|
206
|
+
if (!await input.port.revalidate()) return { status: "STALE" };
|
|
207
|
+
if (attempt === maxClassifications - 1)
|
|
208
|
+
return {
|
|
209
|
+
status: "HUMAN_REQUIRED",
|
|
210
|
+
reason: "PERMISSION_CONTEXT_DEFER_TIMEOUT"
|
|
211
|
+
};
|
|
212
|
+
await input.port.waitBeforeReclassify?.();
|
|
213
|
+
}
|
|
214
|
+
if (!decision)
|
|
215
|
+
return {
|
|
216
|
+
status: "HUMAN_REQUIRED",
|
|
217
|
+
reason: "PERMISSION_CLASSIFICATION_FAILED"
|
|
218
|
+
};
|
|
219
|
+
if (decision.decision !== "AUTO_ALLOW")
|
|
220
|
+
return { status: "HUMAN_REQUIRED", reason: decision.reason };
|
|
221
|
+
if (!input.facts.actions.includes("allowAlways"))
|
|
222
|
+
return {
|
|
223
|
+
status: "HUMAN_REQUIRED",
|
|
224
|
+
reason: "AUTO_ALLOW_ACTION_UNAVAILABLE"
|
|
225
|
+
};
|
|
226
|
+
if (input.autoAlreadyAttempted)
|
|
227
|
+
return {
|
|
228
|
+
status: "HUMAN_REQUIRED",
|
|
229
|
+
reason: "AUTO_ALLOW_REALITY_UNCONFIRMED"
|
|
230
|
+
};
|
|
231
|
+
if (!await input.port.revalidate()) return { status: "STALE" };
|
|
232
|
+
const beforeAction = denied();
|
|
233
|
+
if (beforeAction) return beforeAction;
|
|
234
|
+
try {
|
|
235
|
+
await input.port.act("allowAlways");
|
|
236
|
+
} catch {
|
|
237
|
+
return { status: "HUMAN_REQUIRED", reason: "AUTO_ALLOW_FAILED" };
|
|
238
|
+
}
|
|
239
|
+
return await input.port.released() ? { status: "RELEASED", action: "allowAlways" } : { status: "HUMAN_REQUIRED", reason: "AUTO_ALLOW_REALITY_UNCONFIRMED" };
|
|
240
|
+
}
|
|
241
|
+
async function resolveHumanCarrierPermission(input) {
|
|
242
|
+
if (!await input.revalidate()) throw new Error("STALE_PERMISSION");
|
|
243
|
+
await input.act(input.action);
|
|
244
|
+
if (!await input.released())
|
|
245
|
+
throw new Error("PERMISSION_ACTION_REALITY_UNCONFIRMED");
|
|
246
|
+
return "RELEASED";
|
|
247
|
+
}
|
|
248
|
+
|
|
7
249
|
// node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/external.js
|
|
8
250
|
var external_exports = {};
|
|
9
251
|
__export(external_exports, {
|
|
@@ -13544,6 +13786,13 @@ function createCollaborationCarrierApplication(options) {
|
|
|
13544
13786
|
return Object.freeze({ deliverMessage, recoverPending });
|
|
13545
13787
|
}
|
|
13546
13788
|
|
|
13789
|
+
// packages/execution-browser-extension/src/recovery-trigger.ts
|
|
13790
|
+
function shouldTriggerObserverRecovery(previous, current) {
|
|
13791
|
+
if (current.pageState !== "IDLE") return false;
|
|
13792
|
+
if (!previous) return true;
|
|
13793
|
+
return previous.pageState !== "IDLE" || previous.url !== current.url || previous.contentInstanceId !== current.contentInstanceId || previous.activityKind !== current.activityKind;
|
|
13794
|
+
}
|
|
13795
|
+
|
|
13547
13796
|
// packages/execution-browser-extension/src/system-observer.ts
|
|
13548
13797
|
var SYSTEM_OBSERVER_VIEWS = [
|
|
13549
13798
|
"task",
|
|
@@ -13866,33 +14115,61 @@ function createTaskObserver(options) {
|
|
|
13866
14115
|
return Object.freeze({ advance, drive });
|
|
13867
14116
|
}
|
|
13868
14117
|
|
|
13869
|
-
// packages/execution-browser-extension/src/recovery-trigger.ts
|
|
13870
|
-
function shouldTriggerObserverRecovery(previous, current) {
|
|
13871
|
-
if (current.pageState !== "IDLE") return false;
|
|
13872
|
-
if (!previous) return true;
|
|
13873
|
-
return previous.pageState !== "IDLE" || previous.url !== current.url || previous.contentInstanceId !== current.contentInstanceId || previous.activityKind !== current.activityKind;
|
|
13874
|
-
}
|
|
13875
|
-
|
|
13876
14118
|
// packages/execution-browser-extension/extension/background.ts
|
|
13877
14119
|
var extensionInstanceId = `extension:${crypto.randomUUID()}`;
|
|
13878
14120
|
var sessions = /* @__PURE__ */ new Map();
|
|
14121
|
+
var permissionHandling = /* @__PURE__ */ new Map();
|
|
14122
|
+
var permissionAutoAttempts = createCarrierPermissionAttemptRegistry();
|
|
14123
|
+
var carrierAttentions = createCarrierAttentionRegistry();
|
|
14124
|
+
var carrierContinuationControl = createCarrierContinuationControl();
|
|
13879
14125
|
var BROWSER_CARRIER_KEEPALIVE_KEY = "proflowBrowserSnapshot";
|
|
13880
14126
|
var BROWSER_CARRIER_KEEPALIVE_MS = 2e4;
|
|
13881
14127
|
var BROWSER_BRIDGE_FETCH_TIMEOUT_MS = 5e3;
|
|
14128
|
+
var snapshotPersistence = Promise.resolve();
|
|
14129
|
+
var transientPermissionAttemptsRestore = null;
|
|
13882
14130
|
var sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
13883
|
-
|
|
13884
|
-
|
|
14131
|
+
function persistSnapshot() {
|
|
14132
|
+
const value = {
|
|
13885
14133
|
proflowBrowserSnapshot: {
|
|
13886
14134
|
extensionInstanceId,
|
|
13887
14135
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13888
14136
|
sessions: [...sessions.values()],
|
|
14137
|
+
permissionAutoAttempts: permissionAutoAttempts.snapshot(),
|
|
14138
|
+
carrierContinuationDenials: carrierContinuationControl.snapshot(),
|
|
13889
14139
|
recoveryScan: "BOUNDED_ON_START"
|
|
13890
14140
|
}
|
|
13891
|
-
}
|
|
14141
|
+
};
|
|
14142
|
+
snapshotPersistence = snapshotPersistence.catch(() => void 0).then(() => chrome.storage.session.set(value));
|
|
14143
|
+
return snapshotPersistence;
|
|
13892
14144
|
}
|
|
13893
14145
|
function isRecord(value) {
|
|
13894
14146
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13895
14147
|
}
|
|
14148
|
+
function restoreTransientPermissionAttempts() {
|
|
14149
|
+
if (transientPermissionAttemptsRestore)
|
|
14150
|
+
return transientPermissionAttemptsRestore;
|
|
14151
|
+
transientPermissionAttemptsRestore = (async () => {
|
|
14152
|
+
try {
|
|
14153
|
+
const stored = await chrome.storage.session.get(
|
|
14154
|
+
BROWSER_CARRIER_KEEPALIVE_KEY
|
|
14155
|
+
);
|
|
14156
|
+
const snapshot = stored[BROWSER_CARRIER_KEEPALIVE_KEY];
|
|
14157
|
+
const validSnapshot = isRecord(snapshot);
|
|
14158
|
+
const attemptsLoaded = permissionAutoAttempts.load(
|
|
14159
|
+
validSnapshot ? snapshot.permissionAutoAttempts : void 0
|
|
14160
|
+
);
|
|
14161
|
+
const denialsLoaded = carrierContinuationControl.load(
|
|
14162
|
+
validSnapshot ? snapshot.carrierContinuationDenials : void 0
|
|
14163
|
+
);
|
|
14164
|
+
return attemptsLoaded && denialsLoaded;
|
|
14165
|
+
} catch {
|
|
14166
|
+
permissionAutoAttempts.load(void 0);
|
|
14167
|
+
carrierContinuationControl.load(void 0);
|
|
14168
|
+
return false;
|
|
14169
|
+
}
|
|
14170
|
+
})();
|
|
14171
|
+
return transientPermissionAttemptsRestore;
|
|
14172
|
+
}
|
|
13896
14173
|
function parseConfig(value) {
|
|
13897
14174
|
if (!isRecord(value)) return null;
|
|
13898
14175
|
const endpoint = value.endpoint;
|
|
@@ -14104,6 +14381,8 @@ var taskObserver = createTaskObserver({
|
|
|
14104
14381
|
},
|
|
14105
14382
|
carrier: {
|
|
14106
14383
|
async requestWake(input) {
|
|
14384
|
+
if (carrierContinuationControl.hasMatchingDispatchDenial(input))
|
|
14385
|
+
throw new Error("CARRIER_CONTINUATION_HUMAN_DENIED");
|
|
14107
14386
|
return invokeObserverApplication("task.wake", input);
|
|
14108
14387
|
}
|
|
14109
14388
|
}
|
|
@@ -14197,8 +14476,14 @@ async function persistSystemObserverState(result) {
|
|
|
14197
14476
|
}
|
|
14198
14477
|
var observerRecoveryInFlight = null;
|
|
14199
14478
|
var observerRecoveryRetryCount = 0;
|
|
14479
|
+
var nextRecoverySuppressions = [];
|
|
14480
|
+
function suppressNextObserverRecovery(denials) {
|
|
14481
|
+
nextRecoverySuppressions = denials;
|
|
14482
|
+
}
|
|
14200
14483
|
function runObserverRecovery() {
|
|
14201
14484
|
if (observerRecoveryInFlight) return observerRecoveryInFlight;
|
|
14485
|
+
const suppressedContinuations = nextRecoverySuppressions;
|
|
14486
|
+
nextRecoverySuppressions = [];
|
|
14202
14487
|
observerRecoveryInFlight = (async () => {
|
|
14203
14488
|
let recoveryNeedsRetry = false;
|
|
14204
14489
|
await collaborationCarrier.recoverPending(50).catch(() => void 0);
|
|
@@ -14211,6 +14496,10 @@ function runObserverRecovery() {
|
|
|
14211
14496
|
if (!isRecord(candidate) || typeof candidate.signalRef !== "string" || typeof candidate.executionRef !== "string" || typeof candidate.taskId !== "string" || typeof candidate.workerRef !== "string")
|
|
14212
14497
|
continue;
|
|
14213
14498
|
try {
|
|
14499
|
+
if (suppressedContinuations.some(
|
|
14500
|
+
(denial) => denial.taskId === candidate.taskId && denial.workerRef === candidate.workerRef
|
|
14501
|
+
))
|
|
14502
|
+
continue;
|
|
14214
14503
|
const decision = candidate.kind === "RECOVERY_RESUME" ? await taskObserver.drive(candidate.taskId, {
|
|
14215
14504
|
trigger: "RECOVERY_RESUME",
|
|
14216
14505
|
ref: candidate.executionRef,
|
|
@@ -14249,6 +14538,10 @@ function runObserverRecovery() {
|
|
|
14249
14538
|
}).catch(() => {
|
|
14250
14539
|
recoveryNeedsRetry = true;
|
|
14251
14540
|
});
|
|
14541
|
+
if (suppressedContinuations.some(
|
|
14542
|
+
(denial) => denial.taskId === candidate.taskId
|
|
14543
|
+
))
|
|
14544
|
+
continue;
|
|
14252
14545
|
await taskObserver.drive(candidate.taskId).catch(() => {
|
|
14253
14546
|
recoveryNeedsRetry = true;
|
|
14254
14547
|
});
|
|
@@ -14302,6 +14595,340 @@ async function contentCommand(tabId, command) {
|
|
|
14302
14595
|
}
|
|
14303
14596
|
return response.value;
|
|
14304
14597
|
}
|
|
14598
|
+
function carrierIdentity(url2) {
|
|
14599
|
+
try {
|
|
14600
|
+
const parsed = new URL(url2);
|
|
14601
|
+
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
14602
|
+
if (parsed.protocol !== "https:" || parsed.hostname !== "chatgpt.com" || segments[0] !== "g" || !segments[1]?.startsWith("g-"))
|
|
14603
|
+
return null;
|
|
14604
|
+
return {
|
|
14605
|
+
roleRef: segments[1],
|
|
14606
|
+
workerRef: segments[2] === "c" && segments[3] ? segments[3] : null
|
|
14607
|
+
};
|
|
14608
|
+
} catch {
|
|
14609
|
+
return null;
|
|
14610
|
+
}
|
|
14611
|
+
}
|
|
14612
|
+
function permissionAttemptKey(observed) {
|
|
14613
|
+
return observed.blockerFacts ? `${observed.url}:${observed.blockerFacts.fingerprint}` : null;
|
|
14614
|
+
}
|
|
14615
|
+
function setCarrierAttention(observed, reason) {
|
|
14616
|
+
const facts = observed.blockerFacts;
|
|
14617
|
+
if (!facts) return;
|
|
14618
|
+
const identity = carrierIdentity(observed.url);
|
|
14619
|
+
carrierAttentions.derive({
|
|
14620
|
+
tabId: observed.tabId,
|
|
14621
|
+
contentInstanceId: observed.contentInstanceId,
|
|
14622
|
+
url: observed.url,
|
|
14623
|
+
permissionFingerprint: facts.fingerprint,
|
|
14624
|
+
taskId: facts.taskId,
|
|
14625
|
+
roleRef: identity?.roleRef ?? null,
|
|
14626
|
+
workerRef: identity?.workerRef ?? null,
|
|
14627
|
+
targetHost: facts.targetHost,
|
|
14628
|
+
operationId: facts.operationId,
|
|
14629
|
+
reason,
|
|
14630
|
+
actions: facts.actions.filter(
|
|
14631
|
+
(action) => action === "allowOnce" || action === "deny"
|
|
14632
|
+
),
|
|
14633
|
+
observedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
14634
|
+
});
|
|
14635
|
+
void publishCarrierAttentions();
|
|
14636
|
+
}
|
|
14637
|
+
function carrierAttentionViews() {
|
|
14638
|
+
return carrierAttentions.values().map(
|
|
14639
|
+
({
|
|
14640
|
+
attentionRef,
|
|
14641
|
+
occurrenceRef,
|
|
14642
|
+
taskId,
|
|
14643
|
+
roleRef,
|
|
14644
|
+
workerRef,
|
|
14645
|
+
targetHost,
|
|
14646
|
+
operationId,
|
|
14647
|
+
reason,
|
|
14648
|
+
actions,
|
|
14649
|
+
observedAt
|
|
14650
|
+
}) => ({
|
|
14651
|
+
attentionRef,
|
|
14652
|
+
occurrenceRef,
|
|
14653
|
+
taskId,
|
|
14654
|
+
roleRef,
|
|
14655
|
+
workerRef,
|
|
14656
|
+
targetHost,
|
|
14657
|
+
operationId,
|
|
14658
|
+
reason,
|
|
14659
|
+
actions,
|
|
14660
|
+
observedAt
|
|
14661
|
+
})
|
|
14662
|
+
);
|
|
14663
|
+
}
|
|
14664
|
+
async function publishCarrierAttentions() {
|
|
14665
|
+
const config2 = await bridgeConfig().catch(() => null);
|
|
14666
|
+
if (!config2) return;
|
|
14667
|
+
const query = `?extensionInstanceId=${encodeURIComponent(extensionInstanceId)}`;
|
|
14668
|
+
const response = await bridgeFetch(config2, `/v1/carrier/attentions${query}`, {
|
|
14669
|
+
method: "POST",
|
|
14670
|
+
body: JSON.stringify({ carrierAttentions: carrierAttentionViews() })
|
|
14671
|
+
});
|
|
14672
|
+
if (!response.ok) throw new Error("CARRIER_ATTENTION_PUBLISH_REJECTED");
|
|
14673
|
+
}
|
|
14674
|
+
function rawPermissionFingerprint(value) {
|
|
14675
|
+
if (!isRecord(value) || !isRecord(value.blockerFacts)) return null;
|
|
14676
|
+
return typeof value.blockerFacts.fingerprint === "string" ? value.blockerFacts.fingerprint : null;
|
|
14677
|
+
}
|
|
14678
|
+
function parsePermissionFacts(value) {
|
|
14679
|
+
if (!isRecord(value) || value.kind !== "ACTION_PERMISSION") return void 0;
|
|
14680
|
+
const actions = value.actions;
|
|
14681
|
+
if (value.targetHost !== null && typeof value.targetHost !== "string" || typeof value.operationId !== "string" || value.taskId !== null && typeof value.taskId !== "string" || !Array.isArray(actions) || actions.some(
|
|
14682
|
+
(action) => action !== "allowAlways" && action !== "allowOnce" && action !== "deny"
|
|
14683
|
+
) || typeof value.fingerprint !== "string")
|
|
14684
|
+
return void 0;
|
|
14685
|
+
return {
|
|
14686
|
+
kind: "ACTION_PERMISSION",
|
|
14687
|
+
targetHost: value.targetHost,
|
|
14688
|
+
operationId: value.operationId,
|
|
14689
|
+
taskId: value.taskId,
|
|
14690
|
+
actions: [...actions],
|
|
14691
|
+
fingerprint: value.fingerprint
|
|
14692
|
+
};
|
|
14693
|
+
}
|
|
14694
|
+
function parseSnapshotObservation(value, tab) {
|
|
14695
|
+
if (!isRecord(value) || tab.id === void 0 || tab.windowId === void 0)
|
|
14696
|
+
return null;
|
|
14697
|
+
const pageState = value.pageState;
|
|
14698
|
+
const activityKind = value.activityKind;
|
|
14699
|
+
if (typeof value.url !== "string" || typeof value.contentInstanceId !== "string" || pageState !== "IDLE" && pageState !== "BUSY" && pageState !== "BLOCKED" && pageState !== "UNKNOWN" || activityKind !== null && activityKind !== "GENERATING" && activityKind !== "ACTION_PERMISSION" && activityKind !== "ACTION_RUNNING" && activityKind !== "WAITING_HUMAN" && activityKind !== "WAITING_PEER" && activityKind !== "RECOVERING" || typeof value.observedAt !== "string")
|
|
14700
|
+
return null;
|
|
14701
|
+
const blockerFacts = parsePermissionFacts(value.blockerFacts);
|
|
14702
|
+
if (activityKind === "ACTION_PERMISSION" && blockerFacts === void 0)
|
|
14703
|
+
return null;
|
|
14704
|
+
return {
|
|
14705
|
+
tabId: tab.id,
|
|
14706
|
+
windowId: tab.windowId,
|
|
14707
|
+
url: value.url,
|
|
14708
|
+
contentInstanceId: value.contentInstanceId,
|
|
14709
|
+
pageState,
|
|
14710
|
+
activityKind,
|
|
14711
|
+
...blockerFacts ? { blockerFacts } : {},
|
|
14712
|
+
observedAt: value.observedAt
|
|
14713
|
+
};
|
|
14714
|
+
}
|
|
14715
|
+
async function waitForPermissionReleased(tabId, fingerprint) {
|
|
14716
|
+
for (let attempt = 0; attempt < 40; attempt += 1) {
|
|
14717
|
+
const current = sessions.get(tabId);
|
|
14718
|
+
if (current && current.blockerFacts?.fingerprint !== fingerprint)
|
|
14719
|
+
return true;
|
|
14720
|
+
try {
|
|
14721
|
+
const value = await contentCommand(tabId, { operation: "observe" });
|
|
14722
|
+
if (rawPermissionFingerprint(value) !== fingerprint) return true;
|
|
14723
|
+
} catch {
|
|
14724
|
+
}
|
|
14725
|
+
await sleep(250);
|
|
14726
|
+
}
|
|
14727
|
+
return false;
|
|
14728
|
+
}
|
|
14729
|
+
async function handleActionPermission(observed) {
|
|
14730
|
+
const facts = observed.blockerFacts;
|
|
14731
|
+
const key = permissionAttemptKey(observed);
|
|
14732
|
+
if (observed.pageState !== "BLOCKED" || observed.activityKind !== "ACTION_PERMISSION" || !facts || !key)
|
|
14733
|
+
return;
|
|
14734
|
+
if (permissionHandling.get(observed.tabId) === key) return;
|
|
14735
|
+
const existing = carrierAttentions.current(observed.tabId);
|
|
14736
|
+
if (existing?.contentInstanceId === observed.contentInstanceId && existing.permissionFingerprint === facts.fingerprint)
|
|
14737
|
+
return;
|
|
14738
|
+
permissionHandling.set(observed.tabId, key);
|
|
14739
|
+
try {
|
|
14740
|
+
const identity = carrierIdentity(observed.url);
|
|
14741
|
+
const humanDenied = () => carrierContinuationControl.hasMatchingPermissionDenial({
|
|
14742
|
+
tabId: observed.tabId,
|
|
14743
|
+
contentInstanceId: observed.contentInstanceId,
|
|
14744
|
+
url: observed.url,
|
|
14745
|
+
permissionFingerprint: facts.fingerprint,
|
|
14746
|
+
taskId: facts.taskId,
|
|
14747
|
+
roleRef: identity?.roleRef ?? null,
|
|
14748
|
+
workerRef: identity?.workerRef ?? null
|
|
14749
|
+
});
|
|
14750
|
+
if (humanDenied()) {
|
|
14751
|
+
setCarrierAttention(observed, "HUMAN_DENIED");
|
|
14752
|
+
return;
|
|
14753
|
+
}
|
|
14754
|
+
if (!await restoreTransientPermissionAttempts()) {
|
|
14755
|
+
setCarrierAttention(observed, "PERMISSION_ATTEMPT_STATE_UNAVAILABLE");
|
|
14756
|
+
return;
|
|
14757
|
+
}
|
|
14758
|
+
if (!identity || !facts.taskId) {
|
|
14759
|
+
setCarrierAttention(observed, "PERMISSION_CONTEXT_INCOMPLETE");
|
|
14760
|
+
return;
|
|
14761
|
+
}
|
|
14762
|
+
const result = await resolveRoutineCarrierPermission({
|
|
14763
|
+
facts,
|
|
14764
|
+
autoAlreadyAttempted: permissionAutoAttempts.has(observed.tabId, key),
|
|
14765
|
+
humanDenied,
|
|
14766
|
+
port: {
|
|
14767
|
+
async classify() {
|
|
14768
|
+
const value = await invokeObserverApplication(
|
|
14769
|
+
"browser.permission.classify",
|
|
14770
|
+
{
|
|
14771
|
+
taskId: facts.taskId,
|
|
14772
|
+
roleRef: identity.roleRef,
|
|
14773
|
+
...identity.workerRef ? { workerRef: identity.workerRef } : {},
|
|
14774
|
+
conversationLocator: observed.url,
|
|
14775
|
+
targetHost: facts.targetHost,
|
|
14776
|
+
operationId: facts.operationId
|
|
14777
|
+
}
|
|
14778
|
+
);
|
|
14779
|
+
if (!isRecord(value) || value.decision !== "AUTO_ALLOW" && value.decision !== "DEFER" && value.decision !== "HUMAN_REQUIRED" || typeof value.reason !== "string")
|
|
14780
|
+
return {
|
|
14781
|
+
decision: "HUMAN_REQUIRED",
|
|
14782
|
+
reason: "PERMISSION_CLASSIFICATION_INVALID"
|
|
14783
|
+
};
|
|
14784
|
+
return {
|
|
14785
|
+
decision: value.decision,
|
|
14786
|
+
reason: value.reason
|
|
14787
|
+
};
|
|
14788
|
+
},
|
|
14789
|
+
revalidate() {
|
|
14790
|
+
const current = observationFor(observed.tabId);
|
|
14791
|
+
return current.contentInstanceId === observed.contentInstanceId && current.url === observed.url && current.blockerFacts?.fingerprint === facts.fingerprint;
|
|
14792
|
+
},
|
|
14793
|
+
waitBeforeReclassify: () => sleep(250),
|
|
14794
|
+
async act(action) {
|
|
14795
|
+
permissionAutoAttempts.begin(observed.tabId, key);
|
|
14796
|
+
await persistSnapshot();
|
|
14797
|
+
await contentCommand(observed.tabId, {
|
|
14798
|
+
operation: "permissionAction",
|
|
14799
|
+
permissionFingerprint: facts.fingerprint,
|
|
14800
|
+
permissionAction: action
|
|
14801
|
+
});
|
|
14802
|
+
},
|
|
14803
|
+
released: () => waitForPermissionReleased(observed.tabId, facts.fingerprint)
|
|
14804
|
+
}
|
|
14805
|
+
});
|
|
14806
|
+
if (result.status === "RELEASED") {
|
|
14807
|
+
permissionAutoAttempts.release(observed.tabId, key);
|
|
14808
|
+
carrierAttentions.removeTab(observed.tabId);
|
|
14809
|
+
void publishCarrierAttentions();
|
|
14810
|
+
await persistSnapshot();
|
|
14811
|
+
return;
|
|
14812
|
+
}
|
|
14813
|
+
if (result.status === "HUMAN_REQUIRED")
|
|
14814
|
+
setCarrierAttention(observed, result.reason);
|
|
14815
|
+
} catch {
|
|
14816
|
+
setCarrierAttention(observed, "AUTO_ALLOW_FAILED");
|
|
14817
|
+
} finally {
|
|
14818
|
+
if (permissionHandling.get(observed.tabId) === key)
|
|
14819
|
+
permissionHandling.delete(observed.tabId);
|
|
14820
|
+
}
|
|
14821
|
+
}
|
|
14822
|
+
var carrierBlockerStrategies = /* @__PURE__ */ new Map([["ACTION_PERMISSION", handleActionPermission]]);
|
|
14823
|
+
function handleCarrierBlocker(observed) {
|
|
14824
|
+
if (observed.pageState !== "BLOCKED" || observed.activityKind === null)
|
|
14825
|
+
return;
|
|
14826
|
+
const strategy = carrierBlockerStrategies.get(observed.activityKind);
|
|
14827
|
+
if (strategy) void strategy(observed);
|
|
14828
|
+
}
|
|
14829
|
+
function processContentObservation(observed, triggerRecovery) {
|
|
14830
|
+
const previous = sessions.get(observed.tabId);
|
|
14831
|
+
sessions.set(observed.tabId, observed);
|
|
14832
|
+
permissionAutoAttempts.observe(
|
|
14833
|
+
observed.tabId,
|
|
14834
|
+
permissionAttemptKey(observed)
|
|
14835
|
+
);
|
|
14836
|
+
const attention = carrierAttentions.current(observed.tabId);
|
|
14837
|
+
if (attention && (observed.contentInstanceId !== attention.contentInstanceId || observed.url !== attention.url || observed.blockerFacts?.fingerprint !== attention.permissionFingerprint)) {
|
|
14838
|
+
carrierAttentions.removeTab(observed.tabId);
|
|
14839
|
+
void publishCarrierAttentions();
|
|
14840
|
+
}
|
|
14841
|
+
handleCarrierBlocker(observed);
|
|
14842
|
+
const shouldRecover = triggerRecovery && shouldTriggerObserverRecovery(previous, observed);
|
|
14843
|
+
const suppressed = shouldRecover && carrierContinuationControl.suppressRecovery(previous, observed);
|
|
14844
|
+
void persistSnapshot();
|
|
14845
|
+
if (shouldRecover && !suppressed) void runObserverRecovery();
|
|
14846
|
+
}
|
|
14847
|
+
async function rebuildCarrierAttentionsFromTabs() {
|
|
14848
|
+
const consumedDenials = [];
|
|
14849
|
+
const tabs = await chrome.tabs.query({ url: "https://chatgpt.com/g/*" });
|
|
14850
|
+
for (const tab of tabs) {
|
|
14851
|
+
if (tab.id === void 0 || tab.windowId === void 0) continue;
|
|
14852
|
+
try {
|
|
14853
|
+
const response = await chrome.tabs.sendMessage(tab.id, {
|
|
14854
|
+
type: "PROFLOW_PAGE_SNAPSHOT_REQUEST"
|
|
14855
|
+
});
|
|
14856
|
+
if (!isRecord(response) || response.ok !== true) continue;
|
|
14857
|
+
const observed = parseSnapshotObservation(response.value, tab);
|
|
14858
|
+
if (observed) {
|
|
14859
|
+
processContentObservation(observed, false);
|
|
14860
|
+
const consumed = carrierContinuationControl.consumeRecovery(
|
|
14861
|
+
void 0,
|
|
14862
|
+
observed
|
|
14863
|
+
);
|
|
14864
|
+
if (consumed) consumedDenials.push(consumed);
|
|
14865
|
+
}
|
|
14866
|
+
} catch {
|
|
14867
|
+
}
|
|
14868
|
+
}
|
|
14869
|
+
await persistSnapshot();
|
|
14870
|
+
await publishCarrierAttentions().catch(() => void 0);
|
|
14871
|
+
return [
|
|
14872
|
+
...consumedDenials,
|
|
14873
|
+
...carrierContinuationControl.snapshot().filter(
|
|
14874
|
+
(denial) => !consumedDenials.some(
|
|
14875
|
+
(consumed) => consumed.attentionRef === denial.attentionRef
|
|
14876
|
+
)
|
|
14877
|
+
)
|
|
14878
|
+
];
|
|
14879
|
+
}
|
|
14880
|
+
async function decideCarrierAttention(attentionRef, action) {
|
|
14881
|
+
const attention = carrierAttentions.find(attentionRef);
|
|
14882
|
+
if (!attention?.actions.includes(action))
|
|
14883
|
+
throw new Error("CARRIER_ATTENTION_ACTION_DENIED");
|
|
14884
|
+
await resolveHumanCarrierPermission({
|
|
14885
|
+
action,
|
|
14886
|
+
revalidate() {
|
|
14887
|
+
const current = observationFor(attention.tabId);
|
|
14888
|
+
return current.contentInstanceId === attention.contentInstanceId && current.url === attention.url && current.blockerFacts?.fingerprint === attention.permissionFingerprint;
|
|
14889
|
+
},
|
|
14890
|
+
async act(semanticAction) {
|
|
14891
|
+
if (semanticAction === "deny") {
|
|
14892
|
+
carrierContinuationControl.beginDenied({
|
|
14893
|
+
attentionRef: attention.attentionRef,
|
|
14894
|
+
tabId: attention.tabId,
|
|
14895
|
+
taskId: attention.taskId,
|
|
14896
|
+
roleRef: attention.roleRef,
|
|
14897
|
+
workerRef: attention.workerRef,
|
|
14898
|
+
url: attention.url,
|
|
14899
|
+
contentInstanceId: attention.contentInstanceId,
|
|
14900
|
+
permissionFingerprint: attention.permissionFingerprint
|
|
14901
|
+
});
|
|
14902
|
+
await persistSnapshot();
|
|
14903
|
+
}
|
|
14904
|
+
try {
|
|
14905
|
+
await contentCommand(attention.tabId, {
|
|
14906
|
+
operation: "permissionAction",
|
|
14907
|
+
permissionFingerprint: attention.permissionFingerprint,
|
|
14908
|
+
permissionAction: semanticAction
|
|
14909
|
+
});
|
|
14910
|
+
} catch (error46) {
|
|
14911
|
+
if (semanticAction === "deny") {
|
|
14912
|
+
carrierContinuationControl.cancelDenied(attention.attentionRef);
|
|
14913
|
+
await persistSnapshot();
|
|
14914
|
+
}
|
|
14915
|
+
throw error46;
|
|
14916
|
+
}
|
|
14917
|
+
},
|
|
14918
|
+
released: () => waitForPermissionReleased(
|
|
14919
|
+
attention.tabId,
|
|
14920
|
+
attention.permissionFingerprint
|
|
14921
|
+
)
|
|
14922
|
+
});
|
|
14923
|
+
permissionAutoAttempts.release(
|
|
14924
|
+
attention.tabId,
|
|
14925
|
+
`${attention.url}:${attention.permissionFingerprint}`
|
|
14926
|
+
);
|
|
14927
|
+
carrierAttentions.delete(attention.attentionRef);
|
|
14928
|
+
void publishCarrierAttentions();
|
|
14929
|
+
await persistSnapshot();
|
|
14930
|
+
return { attentionRef, action, status: "APPLIED" };
|
|
14931
|
+
}
|
|
14305
14932
|
async function waitForSubmittedMessage(tabId, fingerprint) {
|
|
14306
14933
|
for (let attempt = 0; attempt < 60; attempt += 1) {
|
|
14307
14934
|
try {
|
|
@@ -14327,6 +14954,14 @@ function text(value, name) {
|
|
|
14327
14954
|
return value;
|
|
14328
14955
|
}
|
|
14329
14956
|
async function executeCommand(command) {
|
|
14957
|
+
if (command.type === "CARRIER_ATTENTION_ACTION") {
|
|
14958
|
+
if (command.action !== "allowOnce" && command.action !== "deny")
|
|
14959
|
+
throw new Error("ATTENTION_ACTION_INVALID");
|
|
14960
|
+
return decideCarrierAttention(
|
|
14961
|
+
text(command.attentionRef, "ATTENTION_REF"),
|
|
14962
|
+
command.action
|
|
14963
|
+
);
|
|
14964
|
+
}
|
|
14330
14965
|
if (command.type === "LIST_TABS") {
|
|
14331
14966
|
const tabs = await chrome.tabs.query({ url: "https://chatgpt.com/g/*" });
|
|
14332
14967
|
return tabs.map((tab) => tab.id).filter((tabId2) => tabId2 !== void 0).map((tabId2) => sessions.get(tabId2)).filter((value) => value !== void 0);
|
|
@@ -14520,6 +15155,7 @@ async function runBridgeLoop() {
|
|
|
14520
15155
|
})
|
|
14521
15156
|
});
|
|
14522
15157
|
if (!hello.ok) throw new Error("BRIDGE_HELLO_REJECTED");
|
|
15158
|
+
await publishCarrierAttentions();
|
|
14523
15159
|
let lastHeartbeatAt = Date.now();
|
|
14524
15160
|
let lastExtensionKeepaliveAt = Date.now();
|
|
14525
15161
|
while (true) {
|
|
@@ -14709,16 +15345,12 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
14709
15345
|
return true;
|
|
14710
15346
|
}
|
|
14711
15347
|
if (message.type === "PROFLOW_CONTENT_OBSERVATION" && message.observation && sender.tab?.id !== void 0 && sender.tab.windowId !== void 0) {
|
|
14712
|
-
const previous = sessions.get(sender.tab.id);
|
|
14713
15348
|
const observed = {
|
|
14714
15349
|
...message.observation,
|
|
14715
15350
|
tabId: sender.tab.id,
|
|
14716
15351
|
windowId: sender.tab.windowId
|
|
14717
15352
|
};
|
|
14718
|
-
|
|
14719
|
-
void persistSnapshot();
|
|
14720
|
-
if (shouldTriggerObserverRecovery(previous, observed))
|
|
14721
|
-
void runObserverRecovery();
|
|
15353
|
+
processContentObservation(observed, true);
|
|
14722
15354
|
sendResponse({ accepted: true, extensionInstanceId });
|
|
14723
15355
|
return;
|
|
14724
15356
|
}
|
|
@@ -14732,6 +15364,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
14732
15364
|
extensionInstanceId,
|
|
14733
15365
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14734
15366
|
sessions: [...sessions.values()],
|
|
15367
|
+
carrierAttentions: carrierAttentionViews(),
|
|
14735
15368
|
taskApplicationConfigured: application !== null,
|
|
14736
15369
|
approvalApplicationConfigured: approval !== null,
|
|
14737
15370
|
systemObserver: observerState ? {
|
|
@@ -14745,6 +15378,26 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
14745
15378
|
);
|
|
14746
15379
|
return true;
|
|
14747
15380
|
}
|
|
15381
|
+
if (message.type === "PROFLOW_CARRIER_ATTENTION_ACTION") {
|
|
15382
|
+
if (!message.input) {
|
|
15383
|
+
sendResponse({ ok: false, error: "CARRIER_ATTENTION_MESSAGE_INVALID" });
|
|
15384
|
+
return;
|
|
15385
|
+
}
|
|
15386
|
+
const attentionRef = message.input.attentionRef;
|
|
15387
|
+
const action = message.input.action;
|
|
15388
|
+
if (typeof attentionRef !== "string" || action !== "allowOnce" && action !== "deny") {
|
|
15389
|
+
sendResponse({ ok: false, error: "CARRIER_ATTENTION_MESSAGE_INVALID" });
|
|
15390
|
+
return;
|
|
15391
|
+
}
|
|
15392
|
+
void decideCarrierAttention(attentionRef, action).then(
|
|
15393
|
+
(value) => sendResponse({ ok: true, value }),
|
|
15394
|
+
(error46) => sendResponse({
|
|
15395
|
+
ok: false,
|
|
15396
|
+
error: error46 instanceof Error ? error46.message : "CARRIER_ATTENTION_ACTION_FAILED"
|
|
15397
|
+
})
|
|
15398
|
+
);
|
|
15399
|
+
return true;
|
|
15400
|
+
}
|
|
14748
15401
|
if (message.type === "PROFLOW_APPROVAL_APPLICATION") {
|
|
14749
15402
|
if (typeof message.operation !== "string" || !message.input) {
|
|
14750
15403
|
sendResponse({
|
|
@@ -14799,9 +15452,15 @@ async function openTaskPage() {
|
|
|
14799
15452
|
const body = await response.json();
|
|
14800
15453
|
if (response.ok && isRecord(body) && typeof body.url === "string" && body.url.startsWith(`${bridge.endpoint}/tasks/bootstrap/`)) {
|
|
14801
15454
|
const webUrl = `${bridge.endpoint}/tasks`;
|
|
14802
|
-
const [existing] = await chrome.tabs.query({
|
|
15455
|
+
const [existing] = await chrome.tabs.query({
|
|
15456
|
+
url: webUrl,
|
|
15457
|
+
currentWindow: true
|
|
15458
|
+
});
|
|
14803
15459
|
if (existing?.id !== void 0) {
|
|
14804
|
-
await chrome.tabs.update(existing.id, {
|
|
15460
|
+
await chrome.tabs.update(existing.id, {
|
|
15461
|
+
url: body.url,
|
|
15462
|
+
active: true
|
|
15463
|
+
});
|
|
14805
15464
|
} else {
|
|
14806
15465
|
await chrome.tabs.create({ url: body.url, active: true });
|
|
14807
15466
|
}
|
|
@@ -14822,27 +15481,36 @@ async function openTaskPage() {
|
|
|
14822
15481
|
await chrome.tabs.create({ url: fallbackUrl, active: true });
|
|
14823
15482
|
}
|
|
14824
15483
|
async function startBackgroundRuntime() {
|
|
15484
|
+
await restoreTransientPermissionAttempts();
|
|
14825
15485
|
await bootstrapManagedRuntimeConfig();
|
|
14826
15486
|
await persistSnapshot();
|
|
14827
15487
|
void runBridgeLoop();
|
|
14828
15488
|
void runProvisioningBridgeLoop();
|
|
15489
|
+
const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
|
|
15490
|
+
suppressNextObserverRecovery(suppressedContinuations);
|
|
14829
15491
|
void runObserverRecovery();
|
|
14830
15492
|
}
|
|
14831
15493
|
chrome.action.onClicked.addListener(() => {
|
|
14832
15494
|
void openTaskPage();
|
|
14833
15495
|
});
|
|
14834
15496
|
chrome.runtime.onInstalled.addListener(() => {
|
|
14835
|
-
void
|
|
15497
|
+
void restoreTransientPermissionAttempts().then(async () => {
|
|
15498
|
+
await bootstrapManagedRuntimeConfig();
|
|
14836
15499
|
await persistSnapshot();
|
|
14837
15500
|
void runBridgeLoop();
|
|
15501
|
+
const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
|
|
15502
|
+
suppressNextObserverRecovery(suppressedContinuations);
|
|
14838
15503
|
void runObserverRecovery();
|
|
14839
15504
|
});
|
|
14840
15505
|
});
|
|
14841
15506
|
chrome.runtime.onStartup.addListener(() => {
|
|
14842
15507
|
sessions.clear();
|
|
14843
|
-
void
|
|
15508
|
+
void restoreTransientPermissionAttempts().then(async () => {
|
|
15509
|
+
await bootstrapManagedRuntimeConfig();
|
|
14844
15510
|
await persistSnapshot();
|
|
14845
15511
|
void runBridgeLoop();
|
|
15512
|
+
const suppressedContinuations = await rebuildCarrierAttentionsFromTabs();
|
|
15513
|
+
suppressNextObserverRecovery(suppressedContinuations);
|
|
14846
15514
|
void runObserverRecovery();
|
|
14847
15515
|
});
|
|
14848
15516
|
});
|