@shawnowen/comet-mcp 2.4.1 → 2.4.2
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/README.md +12 -1
- package/dist/binding-reaper.d.ts +46 -0
- package/dist/binding-reaper.js +73 -0
- package/dist/http-server.js +121 -0
- package/dist/index.js +310 -6
- package/dist/project-config.d.ts +46 -0
- package/dist/project-config.js +166 -0
- package/dist/tab-groups.d.ts +21 -1
- package/dist/tab-groups.js +184 -0
- package/dist/window-bindings.d.ts +48 -0
- package/dist/window-bindings.js +85 -0
- package/extension/background.js +38 -17
- package/extension/manifest.json +16 -1
- package/extension/perplexity-capability-manifest.json +1181 -0
- package/extension/perplexity-capability-manifest.schema.json +142 -0
- package/extension/session-logic.js +696 -25
- package/extension/session-manager.html +13 -1
- package/extension/sidepanel.css +21 -6
- package/extension/sidepanel.js +598 -68
- package/package.json +1 -1
- package/dist/discovery/capability-entry.d.ts +0 -215
- package/dist/discovery/capability-entry.js +0 -13
- package/dist/discovery/description-template.d.ts +0 -40
- package/dist/discovery/description-template.js +0 -61
- package/dist/discovery/golden-queries.fixture.d.ts +0 -22
- package/dist/discovery/golden-queries.fixture.js +0 -137
- package/dist/discovery/mcp-source.d.ts +0 -38
- package/dist/discovery/mcp-source.js +0 -70
- package/dist/discovery/metadata-completeness.d.ts +0 -48
- package/dist/discovery/metadata-completeness.js +0 -83
- package/dist/discovery/registry.d.ts +0 -35
- package/dist/discovery/registry.js +0 -35
- package/dist/discovery/safety.d.ts +0 -44
- package/dist/discovery/safety.js +0 -59
- package/dist/discovery/schema-validator.d.ts +0 -36
- package/dist/discovery/schema-validator.js +0 -257
- package/dist/discovery/source-error.d.ts +0 -47
- package/dist/discovery/source-error.js +0 -95
- package/dist/discovery/tool-meta.d.ts +0 -41
- package/dist/discovery/tool-meta.js +0 -229
- package/dist/discovery/virtual-tools.d.ts +0 -20
- package/dist/discovery/virtual-tools.js +0 -69
- package/dist/task-thread-aggregator.d.ts +0 -34
- package/dist/task-thread-aggregator.js +0 -480
- package/dist/task-thread-canonical.d.ts +0 -142
- package/dist/task-thread-canonical.js +0 -116
|
@@ -799,6 +799,28 @@
|
|
|
799
799
|
return filtered;
|
|
800
800
|
}
|
|
801
801
|
|
|
802
|
+
function normalizeArchiveWorkflowStatus(status) {
|
|
803
|
+
const raw = String(status || "")
|
|
804
|
+
.trim()
|
|
805
|
+
.toLowerCase();
|
|
806
|
+
if (raw === "done") return "done";
|
|
807
|
+
if (raw === "trashed") return "trashed";
|
|
808
|
+
return "pending";
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
function fsPartitionTaskthreadGroups(groups) {
|
|
812
|
+
const pending = [];
|
|
813
|
+
const done = [];
|
|
814
|
+
|
|
815
|
+
for (const group of Array.isArray(groups) ? groups : []) {
|
|
816
|
+
const status = normalizeArchiveWorkflowStatus(group?.status);
|
|
817
|
+
if (status === "pending") pending.push(group);
|
|
818
|
+
if (status === "done") done.push(group);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
return { pending, done };
|
|
822
|
+
}
|
|
823
|
+
|
|
802
824
|
// Extended filter engine for the full-screen filter bar
|
|
803
825
|
function fsApplyAdvancedFilters(groups, opts) {
|
|
804
826
|
let filtered = groups;
|
|
@@ -814,7 +836,10 @@
|
|
|
814
836
|
|
|
815
837
|
// Status filter
|
|
816
838
|
if (opts.status && opts.status !== "all") {
|
|
817
|
-
|
|
839
|
+
const expectedStatus = normalizeArchiveWorkflowStatus(opts.status);
|
|
840
|
+
filtered = filtered.filter(
|
|
841
|
+
(g) => normalizeArchiveWorkflowStatus(g.status) === expectedStatus
|
|
842
|
+
);
|
|
818
843
|
}
|
|
819
844
|
|
|
820
845
|
// Color filter (array of active colors)
|
|
@@ -927,8 +952,8 @@
|
|
|
927
952
|
break;
|
|
928
953
|
}
|
|
929
954
|
case "status": {
|
|
930
|
-
sectionKey = group.status
|
|
931
|
-
const statusLabels = { pending: "Pending", done: "Done",
|
|
955
|
+
sectionKey = normalizeArchiveWorkflowStatus(group.status);
|
|
956
|
+
const statusLabels = { pending: "Pending", done: "Done", trashed: "Trashed" };
|
|
932
957
|
sectionLabel = statusLabels[sectionKey] || sectionKey;
|
|
933
958
|
break;
|
|
934
959
|
}
|
|
@@ -1913,15 +1938,107 @@
|
|
|
1913
1938
|
"restore",
|
|
1914
1939
|
"archive",
|
|
1915
1940
|
"rename",
|
|
1941
|
+
"update_description",
|
|
1942
|
+
"bulk_update_descriptions",
|
|
1943
|
+
"rename_window",
|
|
1944
|
+
"rename_group",
|
|
1945
|
+
"rename_tab",
|
|
1946
|
+
"rename_archive",
|
|
1947
|
+
"update_task_status",
|
|
1948
|
+
"save_snapshot",
|
|
1949
|
+
"manage_selected_item",
|
|
1916
1950
|
"mark_pending",
|
|
1917
1951
|
"mark_done",
|
|
1918
1952
|
"dispatch_to_fleet",
|
|
1919
1953
|
"get_fleet_status",
|
|
1920
1954
|
"open_orchestrator_url",
|
|
1921
1955
|
"invoke_slash_command",
|
|
1956
|
+
"bind_bwoa_session",
|
|
1957
|
+
"snapshot_bwoa_window",
|
|
1958
|
+
"delegate_bwoa_spoke",
|
|
1959
|
+
"complete_bwoa_spoke",
|
|
1922
1960
|
]);
|
|
1923
1961
|
|
|
1924
1962
|
const READ_ONLY_ROUTER_INTENTS = new Set(["inspect", "search", "get_fleet_status"]);
|
|
1963
|
+
const BWOA_DEFAULT_SPACE_URL =
|
|
1964
|
+
"https://www.perplexity.ai/spaces/hub-browser-agent-window-all-t-dcF8yEn2RFejcQJxYBf3Zg";
|
|
1965
|
+
|
|
1966
|
+
const BWOA_MUTATING_INTENTS = new Set([
|
|
1967
|
+
"bind_bwoa_session",
|
|
1968
|
+
"snapshot_bwoa_window",
|
|
1969
|
+
"delegate_bwoa_spoke",
|
|
1970
|
+
"complete_bwoa_spoke",
|
|
1971
|
+
]);
|
|
1972
|
+
|
|
1973
|
+
function normalizeRole(value) {
|
|
1974
|
+
return String(value || "")
|
|
1975
|
+
.trim()
|
|
1976
|
+
.toLowerCase()
|
|
1977
|
+
.replace(/[\s-]+/g, "_");
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
function isPrimeRouterActor(data) {
|
|
1981
|
+
const principal = data?.principal || {};
|
|
1982
|
+
const activeWindowScope = data?.activeWindowScope || {};
|
|
1983
|
+
const roles = [
|
|
1984
|
+
data?.actorRole,
|
|
1985
|
+
data?.role,
|
|
1986
|
+
data?.actor,
|
|
1987
|
+
principal.role,
|
|
1988
|
+
principal.actorRole,
|
|
1989
|
+
activeWindowScope.actorRole,
|
|
1990
|
+
].map(normalizeRole);
|
|
1991
|
+
return (
|
|
1992
|
+
data?.prime === true ||
|
|
1993
|
+
principal.prime === true ||
|
|
1994
|
+
roles.includes("prime") ||
|
|
1995
|
+
roles.includes("equanaut_prime") ||
|
|
1996
|
+
roles.includes("equanautprime")
|
|
1997
|
+
);
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
function isExtensionOwnedMetadataTarget(target) {
|
|
2001
|
+
const source = String(target?.sourceFamily || target?.source || "").toLowerCase();
|
|
2002
|
+
const entityType = String(target?.entityType || target?.type || "").toLowerCase();
|
|
2003
|
+
return !!(
|
|
2004
|
+
target?.extensionOwned === true ||
|
|
2005
|
+
target?.extensionManaged === true ||
|
|
2006
|
+
target?.managedByExtension === true ||
|
|
2007
|
+
[
|
|
2008
|
+
"archived",
|
|
2009
|
+
"archive",
|
|
2010
|
+
"recent",
|
|
2011
|
+
"saved",
|
|
2012
|
+
"unified",
|
|
2013
|
+
"selected",
|
|
2014
|
+
"selected_item",
|
|
2015
|
+
"task-thread",
|
|
2016
|
+
"task_thread",
|
|
2017
|
+
"gateway",
|
|
2018
|
+
].includes(source) ||
|
|
2019
|
+
[
|
|
2020
|
+
"archive",
|
|
2021
|
+
"archive-tab",
|
|
2022
|
+
"recent-window",
|
|
2023
|
+
"recent-tab",
|
|
2024
|
+
"selected-item",
|
|
2025
|
+
"task-thread",
|
|
2026
|
+
"window-label",
|
|
2027
|
+
].includes(entityType)
|
|
2028
|
+
);
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
function isPrimeLiveTargetVerified(target) {
|
|
2032
|
+
const owner = normalizeRole(target?.profileOwner || target?.owner);
|
|
2033
|
+
const displayRole = normalizeRole(target?.displayRole);
|
|
2034
|
+
if (owner !== "agent") return false;
|
|
2035
|
+
return !!(
|
|
2036
|
+
displayRole === "top_agents" ||
|
|
2037
|
+
target?.extensionOwned === true ||
|
|
2038
|
+
target?.extensionManaged === true ||
|
|
2039
|
+
target?.managedByExtension === true
|
|
2040
|
+
);
|
|
2041
|
+
}
|
|
1925
2042
|
|
|
1926
2043
|
function isCapabilityUsable(capability) {
|
|
1927
2044
|
return !!(
|
|
@@ -2027,6 +2144,38 @@
|
|
|
2027
2144
|
return record.status || record.taskStatus || record.state || fallback || "unknown";
|
|
2028
2145
|
}
|
|
2029
2146
|
|
|
2147
|
+
function catalogPrimeOperationsForSource(sourceFamily) {
|
|
2148
|
+
const source = String(sourceFamily || "").toLowerCase();
|
|
2149
|
+
if (source === "live") {
|
|
2150
|
+
return [
|
|
2151
|
+
"inspect",
|
|
2152
|
+
"search",
|
|
2153
|
+
"update_description",
|
|
2154
|
+
"bulk_update_descriptions",
|
|
2155
|
+
"rename_window",
|
|
2156
|
+
"rename_group",
|
|
2157
|
+
"rename_tab",
|
|
2158
|
+
"save_snapshot",
|
|
2159
|
+
];
|
|
2160
|
+
}
|
|
2161
|
+
if (["archived", "archive", "recent", "saved", "unified", "selected"].includes(source)) {
|
|
2162
|
+
return [
|
|
2163
|
+
"inspect",
|
|
2164
|
+
"search",
|
|
2165
|
+
"update_description",
|
|
2166
|
+
"bulk_update_descriptions",
|
|
2167
|
+
"rename_archive",
|
|
2168
|
+
"rename_tab",
|
|
2169
|
+
"update_task_status",
|
|
2170
|
+
"manage_selected_item",
|
|
2171
|
+
];
|
|
2172
|
+
}
|
|
2173
|
+
if (source === "gateway") {
|
|
2174
|
+
return ["inspect", "search", "update_description"];
|
|
2175
|
+
}
|
|
2176
|
+
return ["inspect", "search"];
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2030
2179
|
function normalizeCatalogRecord(record, sourceFamily, index) {
|
|
2031
2180
|
const source = sourceFamily || "unknown";
|
|
2032
2181
|
const nativeId =
|
|
@@ -2060,10 +2209,461 @@
|
|
|
2060
2209
|
record.closedAt ||
|
|
2061
2210
|
null,
|
|
2062
2211
|
allowedOperations: ["inspect", "search"],
|
|
2212
|
+
primeAllowedOperations: catalogPrimeOperationsForSource(source),
|
|
2213
|
+
extensionOwned: record.extensionOwned !== false,
|
|
2063
2214
|
readOnly: true,
|
|
2064
2215
|
};
|
|
2065
2216
|
}
|
|
2066
2217
|
|
|
2218
|
+
function normalizeBwoaStatus(value) {
|
|
2219
|
+
const status = normalizeRole(value || "active");
|
|
2220
|
+
if (
|
|
2221
|
+
["active", "pending", "running", "paused", "completed", "stale", "failed"].includes(status)
|
|
2222
|
+
) {
|
|
2223
|
+
return status;
|
|
2224
|
+
}
|
|
2225
|
+
return "active";
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
function normalizeTrackedUrl(record, index) {
|
|
2229
|
+
const url = String(record?.url || record?.href || "").trim();
|
|
2230
|
+
return {
|
|
2231
|
+
id: String(record?.id || record?.bookmarkId || record?.tabId || `url-${index + 1}`),
|
|
2232
|
+
title: String(record?.title || record?.name || url || "Untitled"),
|
|
2233
|
+
url,
|
|
2234
|
+
source: String(record?.source || record?.sourceFamily || "tracked"),
|
|
2235
|
+
taskThreadId: stringOrNull(record?.taskThreadId || record?.threadId),
|
|
2236
|
+
description: normalizeEntityDescription(record),
|
|
2237
|
+
};
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
function normalizeBwoaSpoke(record, index) {
|
|
2241
|
+
return {
|
|
2242
|
+
id: String(record?.id || record?.agentId || `spoke-${index + 1}`),
|
|
2243
|
+
agentId: stringOrNull(record?.agentId || record?.id),
|
|
2244
|
+
taskThreadId: stringOrNull(record?.taskThreadId || record?.threadId),
|
|
2245
|
+
threadUrl: stringOrNull(record?.threadUrl || record?.url || record?.orchestratorUrl),
|
|
2246
|
+
goal: String(record?.goal || record?.taskGoal || record?.title || ""),
|
|
2247
|
+
successBenchmark: String(record?.successBenchmark || record?.benchmark || ""),
|
|
2248
|
+
status: normalizeBwoaStatus(record?.status || "pending"),
|
|
2249
|
+
successScore:
|
|
2250
|
+
record?.successScore === undefined || record?.successScore === null
|
|
2251
|
+
? null
|
|
2252
|
+
: Number(record.successScore),
|
|
2253
|
+
finalSummary: String(record?.finalSummary || record?.summary || ""),
|
|
2254
|
+
logsReference: stringOrNull(record?.logsReference || record?.logRef || record?.threadUrl),
|
|
2255
|
+
};
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
function normalizeBwoaTab(record, index) {
|
|
2259
|
+
return {
|
|
2260
|
+
id: String(record?.id || record?.tabId || `tab-${index + 1}`),
|
|
2261
|
+
tabId: record?.tabId === undefined ? null : Number(record.tabId),
|
|
2262
|
+
groupId: record?.groupId === undefined ? null : Number(record.groupId),
|
|
2263
|
+
windowId: record?.windowId === undefined ? null : Number(record.windowId),
|
|
2264
|
+
title: String(record?.title || record?.url || "Untitled"),
|
|
2265
|
+
url: stringOrNull(record?.url),
|
|
2266
|
+
active: !!record?.active,
|
|
2267
|
+
pinned: !!record?.pinned,
|
|
2268
|
+
description: normalizeEntityDescription(record),
|
|
2269
|
+
taskThreadId: stringOrNull(record?.taskThreadId || record?.threadId),
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
function normalizeBwoaGroup(record, index) {
|
|
2274
|
+
const tabs = Array.isArray(record?.tabs) ? record.tabs : [];
|
|
2275
|
+
return {
|
|
2276
|
+
id: String(record?.id || record?.groupId || `group-${index + 1}`),
|
|
2277
|
+
groupId: record?.groupId === undefined ? record?.id || null : Number(record.groupId),
|
|
2278
|
+
windowId: record?.windowId === undefined ? null : Number(record.windowId),
|
|
2279
|
+
title: String(record?.title || record?.name || "Untitled Group"),
|
|
2280
|
+
color: String(record?.color || "grey"),
|
|
2281
|
+
status: normalizeBwoaStatus(record?.status || "active"),
|
|
2282
|
+
description: normalizeEntityDescription(record),
|
|
2283
|
+
taskThreadId: stringOrNull(record?.taskThreadId || record?.threadId),
|
|
2284
|
+
tabs: tabs.map((tab, tabIndex) => normalizeBwoaTab(tab, tabIndex)),
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
function buildBwoaWindowHubSession(input) {
|
|
2289
|
+
const data = input || {};
|
|
2290
|
+
const now = data.updatedAt || data.lastSnapshotAt || data.createdAt || new Date().toISOString();
|
|
2291
|
+
const epoaSessionId = String(data.epoaSessionId || data.primeSessionId || "").trim();
|
|
2292
|
+
const windowId =
|
|
2293
|
+
data.windowId === undefined || data.windowId === null || data.windowId === ""
|
|
2294
|
+
? null
|
|
2295
|
+
: Number(data.windowId);
|
|
2296
|
+
const taskThreadId = String(data.taskThreadId || data.threadId || "").trim();
|
|
2297
|
+
const groups = (Array.isArray(data.tabGroups) ? data.tabGroups : data.groups || []).map(
|
|
2298
|
+
(group, index) => normalizeBwoaGroup(group, index)
|
|
2299
|
+
);
|
|
2300
|
+
const openTabs = (Array.isArray(data.openTabs) ? data.openTabs : data.tabs || []).map(
|
|
2301
|
+
(tab, index) => normalizeBwoaTab(tab, index)
|
|
2302
|
+
);
|
|
2303
|
+
|
|
2304
|
+
return {
|
|
2305
|
+
schemaVersion: "bwoa.window-hub-session.v1",
|
|
2306
|
+
id: String(
|
|
2307
|
+
data.id ||
|
|
2308
|
+
data.sessionKey ||
|
|
2309
|
+
[
|
|
2310
|
+
"bwoa",
|
|
2311
|
+
epoaSessionId || "unbound-prime",
|
|
2312
|
+
windowId === null ? "window-unknown" : `window-${windowId}`,
|
|
2313
|
+
].join(":")
|
|
2314
|
+
),
|
|
2315
|
+
epoaSessionId,
|
|
2316
|
+
bwoaSpaceUrl: String(data.bwoaSpaceUrl || data.spaceUrl || BWOA_DEFAULT_SPACE_URL),
|
|
2317
|
+
windowId,
|
|
2318
|
+
windowOrdinal: Number(data.windowOrdinal || data.windowNumber || 1),
|
|
2319
|
+
tabGroupId:
|
|
2320
|
+
data.tabGroupId === undefined || data.tabGroupId === null || data.tabGroupId === ""
|
|
2321
|
+
? null
|
|
2322
|
+
: Number(data.tabGroupId),
|
|
2323
|
+
taskThreadId,
|
|
2324
|
+
agentId: String(data.agentId || "bwoa-window-hub"),
|
|
2325
|
+
status: normalizeBwoaStatus(data.status || "active"),
|
|
2326
|
+
name: String(data.name || data.title || "Window Hub Orchestrator"),
|
|
2327
|
+
description: normalizeEntityDescription(data),
|
|
2328
|
+
bookmarkedUrls: (data.bookmarkedUrls || data.bookmarks || []).map(normalizeTrackedUrl),
|
|
2329
|
+
trackedUrls: (data.trackedUrls || []).map(normalizeTrackedUrl),
|
|
2330
|
+
tabGroups: groups,
|
|
2331
|
+
openTabs,
|
|
2332
|
+
spawnedSpokes: (data.spawnedSpokes || data.spokes || []).map(normalizeBwoaSpoke),
|
|
2333
|
+
lastSnapshotAt: now,
|
|
2334
|
+
createdAt: data.createdAt || now,
|
|
2335
|
+
updatedAt: now,
|
|
2336
|
+
auditTrail: Array.isArray(data.auditTrail) ? data.auditTrail : [],
|
|
2337
|
+
};
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
function countBwoaWindowHubSession(session) {
|
|
2341
|
+
const data = session || {};
|
|
2342
|
+
const groups = Array.isArray(data.tabGroups) ? data.tabGroups : [];
|
|
2343
|
+
const openTabs = Array.isArray(data.openTabs) ? data.openTabs : [];
|
|
2344
|
+
const groupTabs = groups.reduce(
|
|
2345
|
+
(sum, group) => sum + (Array.isArray(group.tabs) ? group.tabs.length : 0),
|
|
2346
|
+
0
|
|
2347
|
+
);
|
|
2348
|
+
return {
|
|
2349
|
+
tabGroups: groups.length,
|
|
2350
|
+
openTabs: openTabs.length || groupTabs,
|
|
2351
|
+
bookmarkedUrls: (data.bookmarkedUrls || []).length,
|
|
2352
|
+
trackedUrls: (data.trackedUrls || []).length,
|
|
2353
|
+
spawnedSpokes: (data.spawnedSpokes || []).length,
|
|
2354
|
+
activeSpokes: (data.spawnedSpokes || []).filter((spoke) =>
|
|
2355
|
+
["active", "running", "pending"].includes(normalizeBwoaStatus(spoke.status))
|
|
2356
|
+
).length,
|
|
2357
|
+
};
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
function buildBwoaDelegationEnvelope(input) {
|
|
2361
|
+
const data = input || {};
|
|
2362
|
+
const session = buildBwoaWindowHubSession(data.session || data);
|
|
2363
|
+
const goal = String(data.goal || data.taskGoal || "").trim();
|
|
2364
|
+
const taskThreadId = String(data.taskThreadId || session.taskThreadId || "").trim();
|
|
2365
|
+
return {
|
|
2366
|
+
schemaVersion: "bwoa.delegation-envelope.v1",
|
|
2367
|
+
goal,
|
|
2368
|
+
successBenchmark: String(data.successBenchmark || data.benchmark || ""),
|
|
2369
|
+
windowId: session.windowId,
|
|
2370
|
+
windowOrdinal: session.windowOrdinal,
|
|
2371
|
+
taskThreadId,
|
|
2372
|
+
allowedTargets: Array.isArray(data.allowedTargets)
|
|
2373
|
+
? data.allowedTargets
|
|
2374
|
+
: [
|
|
2375
|
+
{
|
|
2376
|
+
entityType: "window",
|
|
2377
|
+
windowId: session.windowId,
|
|
2378
|
+
scope: "bwoa_window",
|
|
2379
|
+
},
|
|
2380
|
+
],
|
|
2381
|
+
requiredReportFormat:
|
|
2382
|
+
data.requiredReportFormat ||
|
|
2383
|
+
"Session Report with deployed spokes, benchmark, final output summary, success score, pass/fail status, and logs reference.",
|
|
2384
|
+
bwoaSpaceUrl: session.bwoaSpaceUrl,
|
|
2385
|
+
createdAt: data.createdAt || new Date().toISOString(),
|
|
2386
|
+
};
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
function normalizeBwoaConfigItem(record, index, fallbackKind) {
|
|
2390
|
+
const value = record || {};
|
|
2391
|
+
const id = value.id || value.name || value.path || value.url || `${fallbackKind}-${index + 1}`;
|
|
2392
|
+
return {
|
|
2393
|
+
id: String(id),
|
|
2394
|
+
kind: String(value.kind || fallbackKind),
|
|
2395
|
+
name: String(value.name || value.title || id),
|
|
2396
|
+
purpose: String(value.purpose || value.description || ""),
|
|
2397
|
+
required: value.required !== false,
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
function buildBwoaWindowHubConfiguration(input) {
|
|
2402
|
+
const data = input || {};
|
|
2403
|
+
const session = buildBwoaWindowHubSession(data.session || data);
|
|
2404
|
+
const windowOrdinal = Number(data.windowOrdinal || session.windowOrdinal || 1);
|
|
2405
|
+
const spaceUrl = String(data.bwoaSpaceUrl || data.spaceUrl || session.bwoaSpaceUrl);
|
|
2406
|
+
const defaultConnections = [
|
|
2407
|
+
{
|
|
2408
|
+
id: "epoa-control-channel",
|
|
2409
|
+
kind: "conversation",
|
|
2410
|
+
name: "EPOA to BWOA direct channel",
|
|
2411
|
+
purpose:
|
|
2412
|
+
"Codex Prime sends only compact session envelopes, delegation envelopes, and report requests.",
|
|
2413
|
+
},
|
|
2414
|
+
{
|
|
2415
|
+
id: "bwoa-perplexity-space",
|
|
2416
|
+
kind: "space",
|
|
2417
|
+
name: "Hub Browser Agent Window All Tabs",
|
|
2418
|
+
purpose: spaceUrl,
|
|
2419
|
+
},
|
|
2420
|
+
{
|
|
2421
|
+
id: "comet-bridge",
|
|
2422
|
+
kind: "mcp",
|
|
2423
|
+
name: "Comet-Bridge",
|
|
2424
|
+
purpose:
|
|
2425
|
+
"Authoritative browser control, tab group inventory, lifecycle metadata, and top-display window binding.",
|
|
2426
|
+
},
|
|
2427
|
+
{
|
|
2428
|
+
id: "task-thread-registry",
|
|
2429
|
+
kind: "metadata",
|
|
2430
|
+
name: "Task Thread Registry",
|
|
2431
|
+
purpose: "Joins BWOA hub state to spawned spoke work and completion reports.",
|
|
2432
|
+
},
|
|
2433
|
+
];
|
|
2434
|
+
const defaultSkills = [
|
|
2435
|
+
"bwoa-window-hub",
|
|
2436
|
+
"comet-browser-control-toolkit",
|
|
2437
|
+
"comet-connect",
|
|
2438
|
+
"comet-workspace",
|
|
2439
|
+
"comet-task-threads",
|
|
2440
|
+
"comet-delegate",
|
|
2441
|
+
"comet-session",
|
|
2442
|
+
"comet-skill-inventory",
|
|
2443
|
+
"15-comet-review",
|
|
2444
|
+
].map((name) => ({
|
|
2445
|
+
id: name,
|
|
2446
|
+
kind: "skill",
|
|
2447
|
+
name,
|
|
2448
|
+
purpose: "BWOA browser orchestration surface",
|
|
2449
|
+
}));
|
|
2450
|
+
const defaultFiles = [
|
|
2451
|
+
"codex-comet-browser-control-toolkit/skills/bwoa-window-hub/SKILL.md",
|
|
2452
|
+
"codex-comet-browser-control-toolkit/commands/bwoa-window-hub.md",
|
|
2453
|
+
"docs/BWOA-WINDOW-HUB-ORCHESTRATOR.md",
|
|
2454
|
+
"comet-mcp/extension/session-logic.js",
|
|
2455
|
+
"test/bwoa-window-hub-session.test.mjs",
|
|
2456
|
+
"specs/086-branch-window-hub/contracts/bwoa-window-hub-session.md",
|
|
2457
|
+
"specs/086-branch-window-hub/quickstart.md",
|
|
2458
|
+
].map((path) => ({
|
|
2459
|
+
id: path,
|
|
2460
|
+
kind: "file",
|
|
2461
|
+
name: path,
|
|
2462
|
+
purpose: "Source-level BWOA contract evidence",
|
|
2463
|
+
}));
|
|
2464
|
+
|
|
2465
|
+
return {
|
|
2466
|
+
schemaVersion: "bwoa.window-hub-configuration.v1",
|
|
2467
|
+
id: String(data.id || `bwoa-window-${windowOrdinal}-configuration`),
|
|
2468
|
+
role: "browser_window_orchestrator_agent",
|
|
2469
|
+
windowOrdinal,
|
|
2470
|
+
bwoaSpaceUrl: spaceUrl,
|
|
2471
|
+
profileOwner: "agent",
|
|
2472
|
+
displayRole: "top_agents",
|
|
2473
|
+
primaryMode: String(data.primaryMode || "Computer"),
|
|
2474
|
+
planningMode: String(data.planningMode || "Orchestrator"),
|
|
2475
|
+
settings: {
|
|
2476
|
+
oneWindowPerHub: true,
|
|
2477
|
+
oneManagedTabGroupPerWindow: true,
|
|
2478
|
+
preserveOpenTabs: true,
|
|
2479
|
+
preserveTrackedUrls: true,
|
|
2480
|
+
snapshotCadence: ["bind", "pre_delegate", "post_delegate", "complete", "handoff"],
|
|
2481
|
+
authoritativeState: ["extension_storage", "mcp_metadata", "snapshots", "task_threads"],
|
|
2482
|
+
prohibitedAutomation: ["chrome", "puppeteer", "playwright_keyboard", "codex_browser"],
|
|
2483
|
+
...(data.settings || {}),
|
|
2484
|
+
},
|
|
2485
|
+
connections: (data.connections || defaultConnections).map((item, index) =>
|
|
2486
|
+
normalizeBwoaConfigItem(item, index, "connection")
|
|
2487
|
+
),
|
|
2488
|
+
requiredSkills: (data.requiredSkills || defaultSkills).map((item, index) =>
|
|
2489
|
+
normalizeBwoaConfigItem(item, index, "skill")
|
|
2490
|
+
),
|
|
2491
|
+
requiredFiles: (data.requiredFiles || defaultFiles).map((item, index) =>
|
|
2492
|
+
normalizeBwoaConfigItem(item, index, "file")
|
|
2493
|
+
),
|
|
2494
|
+
instructionBlocks: data.instructionBlocks || [
|
|
2495
|
+
"Bind one Codex/EPOA session to one BWOA Space and one top-display Comet window.",
|
|
2496
|
+
"Snapshot tab groups, open tabs, bookmarked URLs, and tracked URLs before delegating spoke work.",
|
|
2497
|
+
"Delegate only bounded spoke goals with success benchmarks and allowed targets.",
|
|
2498
|
+
"Return the required Session Report upward to EPOA after every spoke completes or blocks.",
|
|
2499
|
+
],
|
|
2500
|
+
threadProtocol: {
|
|
2501
|
+
epoaToBwoa: "bwoa.delegation-envelope.v1",
|
|
2502
|
+
bwoaState: "bwoa.window-hub-session.v1",
|
|
2503
|
+
bwoaToEpoa: "Session Report",
|
|
2504
|
+
bwoaToSpoke: "bounded task-thread with benchmark, allowed targets, and logs reference",
|
|
2505
|
+
...(data.threadProtocol || {}),
|
|
2506
|
+
},
|
|
2507
|
+
session,
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
function safeBwoaJson(value) {
|
|
2512
|
+
try {
|
|
2513
|
+
return JSON.stringify(value, null, 2);
|
|
2514
|
+
} catch (_err) {
|
|
2515
|
+
return "{}";
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
function buildBwoaEpoaHandoffPrompt(input) {
|
|
2520
|
+
const data = input || {};
|
|
2521
|
+
const session = buildBwoaWindowHubSession(data.session || data);
|
|
2522
|
+
const configuration = buildBwoaWindowHubConfiguration({
|
|
2523
|
+
...data,
|
|
2524
|
+
session,
|
|
2525
|
+
});
|
|
2526
|
+
const goal = String(
|
|
2527
|
+
data.goal ||
|
|
2528
|
+
"Bind this BWOA Space to the current EPOA session and maintain Window #1 browser task context."
|
|
2529
|
+
).trim();
|
|
2530
|
+
return [
|
|
2531
|
+
"# EPOA to BWOA Handoff",
|
|
2532
|
+
"",
|
|
2533
|
+
`Goal: ${goal}`,
|
|
2534
|
+
"",
|
|
2535
|
+
"You are BWOA, the Browser Window Orchestrator Agent for Window #1. Treat Codex/EPOA as the only upstream orchestrator for this browser-window hub.",
|
|
2536
|
+
"",
|
|
2537
|
+
"Required operating rules:",
|
|
2538
|
+
"- Keep this Perplexity Space as the conversational surface only.",
|
|
2539
|
+
"- Keep durable state in Comet-Bridge extension storage, MCP metadata, snapshots, and task-thread records.",
|
|
2540
|
+
"- Preserve tab groups, open tabs, bookmarked URLs, and tracked URLs for the full task lifecycle.",
|
|
2541
|
+
"- Delegate bounded browser work to spoke task threads only through the delegation envelope.",
|
|
2542
|
+
"- Return the required Session Report to EPOA after every spoke completes or blocks.",
|
|
2543
|
+
"- Do not mutate human-owned or bottom-display browser targets.",
|
|
2544
|
+
"- Do not replace Comet-Bridge with Chrome, Puppeteer, Playwright-as-keyboard, or Codex Browser.",
|
|
2545
|
+
"",
|
|
2546
|
+
"Configuration:",
|
|
2547
|
+
"```json",
|
|
2548
|
+
safeBwoaJson(configuration),
|
|
2549
|
+
"```",
|
|
2550
|
+
"",
|
|
2551
|
+
"Current BWOA session:",
|
|
2552
|
+
"```json",
|
|
2553
|
+
safeBwoaJson(session),
|
|
2554
|
+
"```",
|
|
2555
|
+
].join("\n");
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
function buildBwoaSpokePrompt(input) {
|
|
2559
|
+
const data = input || {};
|
|
2560
|
+
const envelope = buildBwoaDelegationEnvelope(data.envelope || data);
|
|
2561
|
+
return [
|
|
2562
|
+
"# BWOA to Spoke Delegation",
|
|
2563
|
+
"",
|
|
2564
|
+
`Goal: ${envelope.goal || "Complete the delegated browser task."}`,
|
|
2565
|
+
`Success Benchmark: ${envelope.successBenchmark || "Meet the delegated success criteria."}`,
|
|
2566
|
+
`Window Scope: Window #${envelope.windowOrdinal} (${envelope.windowId || "unbound"})`,
|
|
2567
|
+
`Task Thread: ${envelope.taskThreadId || "unbound"}`,
|
|
2568
|
+
"",
|
|
2569
|
+
"Allowed targets:",
|
|
2570
|
+
"```json",
|
|
2571
|
+
safeBwoaJson(envelope.allowedTargets),
|
|
2572
|
+
"```",
|
|
2573
|
+
"",
|
|
2574
|
+
"Delegation envelope:",
|
|
2575
|
+
"```json",
|
|
2576
|
+
safeBwoaJson(envelope),
|
|
2577
|
+
"```",
|
|
2578
|
+
"",
|
|
2579
|
+
"Return exactly this report shape to BWOA/EPOA:",
|
|
2580
|
+
"",
|
|
2581
|
+
"### Session Report: <task or goal>",
|
|
2582
|
+
"- **Spoke Agent(s) Deployed:** <ids or none>",
|
|
2583
|
+
"- **Success Benchmark:** <1-2 sentences>",
|
|
2584
|
+
"- **Final Output Summary:** <compressed result>",
|
|
2585
|
+
"- **Success Score:** <0-100>%",
|
|
2586
|
+
"- **Status:** <PASS|FAIL>",
|
|
2587
|
+
"- **Logs Reference:** <thread URL or record id>",
|
|
2588
|
+
].join("\n");
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
function validateBwoaRouterIntent(input) {
|
|
2592
|
+
const data = input || {};
|
|
2593
|
+
const intent = String(data.intent || "");
|
|
2594
|
+
if (!BWOA_MUTATING_INTENTS.has(intent)) return null;
|
|
2595
|
+
|
|
2596
|
+
const activeWindowScope = data.activeWindowScope || {};
|
|
2597
|
+
const target = data.target || {};
|
|
2598
|
+
const policyTier = isPrimeRouterActor(data) ? "prime" : "normal";
|
|
2599
|
+
|
|
2600
|
+
if (policyTier !== "prime") {
|
|
2601
|
+
return denyRouterIntent(
|
|
2602
|
+
intent,
|
|
2603
|
+
"BWOA_PRIME_REQUIRED",
|
|
2604
|
+
"BWOA session mutation requires Equanaut Prime or EPOA authority.",
|
|
2605
|
+
activeWindowScope,
|
|
2606
|
+
policyTier
|
|
2607
|
+
);
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
if (normalizeRole(target.profileOwner) === "human") {
|
|
2611
|
+
return denyRouterIntent(
|
|
2612
|
+
intent,
|
|
2613
|
+
"HUMAN_PROFILE_DENIED",
|
|
2614
|
+
"BWOA cannot mutate human-owned browser state.",
|
|
2615
|
+
activeWindowScope,
|
|
2616
|
+
policyTier
|
|
2617
|
+
);
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
const targetDisplayRole = normalizeRole(target.displayRole);
|
|
2621
|
+
if (targetDisplayRole === "primary_user" || targetDisplayRole === "bottom_user") {
|
|
2622
|
+
return denyRouterIntent(
|
|
2623
|
+
intent,
|
|
2624
|
+
"BOTTOM_DISPLAY_MUTATION_DENIED",
|
|
2625
|
+
"BWOA targets must remain in the top-display agent workspace.",
|
|
2626
|
+
activeWindowScope,
|
|
2627
|
+
policyTier
|
|
2628
|
+
);
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
const session = buildBwoaWindowHubSession(data.session || target);
|
|
2632
|
+
const activeWindowId = activeWindowScope.windowId ? String(activeWindowScope.windowId) : "";
|
|
2633
|
+
const targetWindowId =
|
|
2634
|
+
session.windowId === null ? String(target.windowId || "") : String(session.windowId);
|
|
2635
|
+
if (targetWindowId && activeWindowId && targetWindowId !== activeWindowId) {
|
|
2636
|
+
if (!isPrimeLiveTargetVerified({ ...target, windowId: targetWindowId })) {
|
|
2637
|
+
return denyRouterIntent(
|
|
2638
|
+
intent,
|
|
2639
|
+
"BWOA_TARGET_UNVERIFIED",
|
|
2640
|
+
"BWOA cross-window mutation requires verified top-display agent ownership.",
|
|
2641
|
+
activeWindowScope,
|
|
2642
|
+
policyTier
|
|
2643
|
+
);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
return {
|
|
2648
|
+
intent,
|
|
2649
|
+
target,
|
|
2650
|
+
session,
|
|
2651
|
+
scope: "bwoa_window_hub",
|
|
2652
|
+
mutation: true,
|
|
2653
|
+
requiresConfirmation: false,
|
|
2654
|
+
preview: data.preview || `${intent} for Window #${session.windowOrdinal}`,
|
|
2655
|
+
audit: {
|
|
2656
|
+
requestedBy: "equanaut_prime",
|
|
2657
|
+
activeWindowId: activeWindowId || "unknown",
|
|
2658
|
+
targetWindowId: targetWindowId || "unknown",
|
|
2659
|
+
policyTier,
|
|
2660
|
+
reason: data.reason || "bwoa_orchestration",
|
|
2661
|
+
createdAt: new Date().toISOString(),
|
|
2662
|
+
},
|
|
2663
|
+
allowed: true,
|
|
2664
|
+
};
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2067
2667
|
function normalizeFleetRecord(record, index) {
|
|
2068
2668
|
const base = normalizeCatalogRecord(record, "fleet", index);
|
|
2069
2669
|
return {
|
|
@@ -2094,6 +2694,18 @@
|
|
|
2094
2694
|
const gatewayTools = (data.gatewayTools || []).map((r, i) =>
|
|
2095
2695
|
normalizeCatalogRecord(r, "gateway", i)
|
|
2096
2696
|
);
|
|
2697
|
+
const selectedItems = (data.selectedItems || []).map((r, i) =>
|
|
2698
|
+
normalizeCatalogRecord(r, "selected", i)
|
|
2699
|
+
);
|
|
2700
|
+
const lifecycleBindings = (data.lifecycleBindings || []).map((r, i) =>
|
|
2701
|
+
normalizeCatalogRecord(r, "lifecycle", i)
|
|
2702
|
+
);
|
|
2703
|
+
const windowLabels = (data.windowLabels || []).map((r, i) =>
|
|
2704
|
+
normalizeCatalogRecord(r, "window-label", i)
|
|
2705
|
+
);
|
|
2706
|
+
const descriptions = (data.descriptions || []).map((r, i) =>
|
|
2707
|
+
normalizeCatalogRecord(r, "description", i)
|
|
2708
|
+
);
|
|
2097
2709
|
const slashCommands = Array.isArray(data.slashCommands)
|
|
2098
2710
|
? buildEquanautSlashCommandCatalog(data.slashCommands)
|
|
2099
2711
|
: buildEquanautSlashCommandCatalog();
|
|
@@ -2108,6 +2720,10 @@
|
|
|
2108
2720
|
unifiedThreads,
|
|
2109
2721
|
fleetMembers,
|
|
2110
2722
|
gatewayTools,
|
|
2723
|
+
selectedItems,
|
|
2724
|
+
lifecycleBindings,
|
|
2725
|
+
windowLabels,
|
|
2726
|
+
descriptions,
|
|
2111
2727
|
slashCommands,
|
|
2112
2728
|
plugins,
|
|
2113
2729
|
freshness: {
|
|
@@ -2129,6 +2745,10 @@
|
|
|
2129
2745
|
gatewayTools: (c.gatewayTools || []).length,
|
|
2130
2746
|
slashCommands: (c.slashCommands || []).length,
|
|
2131
2747
|
plugins: (c.plugins || []).length,
|
|
2748
|
+
selectedItems: (c.selectedItems || []).length,
|
|
2749
|
+
lifecycleBindings: (c.lifecycleBindings || []).length,
|
|
2750
|
+
windowLabels: (c.windowLabels || []).length,
|
|
2751
|
+
descriptions: (c.descriptions || []).length,
|
|
2132
2752
|
};
|
|
2133
2753
|
}
|
|
2134
2754
|
|
|
@@ -2174,7 +2794,7 @@
|
|
|
2174
2794
|
};
|
|
2175
2795
|
}
|
|
2176
2796
|
|
|
2177
|
-
function denyRouterIntent(intent, code, message, activeWindowScope) {
|
|
2797
|
+
function denyRouterIntent(intent, code, message, activeWindowScope, policyTier = "normal") {
|
|
2178
2798
|
return {
|
|
2179
2799
|
intent,
|
|
2180
2800
|
scope: "denied",
|
|
@@ -2185,6 +2805,7 @@
|
|
|
2185
2805
|
audit: {
|
|
2186
2806
|
requestedBy: "sidepanel",
|
|
2187
2807
|
activeWindowId: activeWindowScope?.windowId || "unknown",
|
|
2808
|
+
policyTier,
|
|
2188
2809
|
createdAt: new Date().toISOString(),
|
|
2189
2810
|
},
|
|
2190
2811
|
allowed: false,
|
|
@@ -2197,16 +2818,22 @@
|
|
|
2197
2818
|
const target = data.target || {};
|
|
2198
2819
|
const activeWindowScope = data.activeWindowScope || {};
|
|
2199
2820
|
const activeWindowId = activeWindowScope.windowId ? String(activeWindowScope.windowId) : "";
|
|
2821
|
+
const isPrime = isPrimeRouterActor(data);
|
|
2822
|
+
const policyTier = isPrime ? "prime" : "normal";
|
|
2200
2823
|
|
|
2201
2824
|
if (!SUPPORTED_ROUTER_INTENTS.includes(intent)) {
|
|
2202
2825
|
return denyRouterIntent(
|
|
2203
2826
|
intent || "unknown",
|
|
2204
2827
|
"UNSUPPORTED_INTENT",
|
|
2205
2828
|
`Unsupported router intent: ${intent || "unknown"}`,
|
|
2206
|
-
activeWindowScope
|
|
2829
|
+
activeWindowScope,
|
|
2830
|
+
policyTier
|
|
2207
2831
|
);
|
|
2208
2832
|
}
|
|
2209
2833
|
|
|
2834
|
+
const bwoaDecision = validateBwoaRouterIntent(data);
|
|
2835
|
+
if (bwoaDecision) return bwoaDecision;
|
|
2836
|
+
|
|
2210
2837
|
const mutation = !READ_ONLY_ROUTER_INTENTS.has(intent);
|
|
2211
2838
|
if (!mutation) {
|
|
2212
2839
|
return {
|
|
@@ -2219,57 +2846,78 @@
|
|
|
2219
2846
|
audit: {
|
|
2220
2847
|
requestedBy: "sidepanel",
|
|
2221
2848
|
activeWindowId: activeWindowId || "unknown",
|
|
2849
|
+
policyTier,
|
|
2222
2850
|
createdAt: new Date().toISOString(),
|
|
2223
2851
|
},
|
|
2224
2852
|
allowed: true,
|
|
2225
2853
|
};
|
|
2226
2854
|
}
|
|
2227
2855
|
|
|
2228
|
-
if (
|
|
2856
|
+
if (
|
|
2857
|
+
normalizeRole(activeWindowScope.profileOwner) === "human" ||
|
|
2858
|
+
normalizeRole(target.profileOwner) === "human"
|
|
2859
|
+
) {
|
|
2229
2860
|
return denyRouterIntent(
|
|
2230
2861
|
intent,
|
|
2231
2862
|
"HUMAN_PROFILE_DENIED",
|
|
2232
|
-
"
|
|
2233
|
-
activeWindowScope
|
|
2863
|
+
"Agents cannot mutate human-owned browser profile or window state.",
|
|
2864
|
+
activeWindowScope,
|
|
2865
|
+
policyTier
|
|
2234
2866
|
);
|
|
2235
2867
|
}
|
|
2236
2868
|
|
|
2237
|
-
|
|
2869
|
+
const targetDisplayRole = normalizeRole(target.displayRole);
|
|
2870
|
+
if (targetDisplayRole === "primary_user" || targetDisplayRole === "bottom_user") {
|
|
2238
2871
|
return denyRouterIntent(
|
|
2239
2872
|
intent,
|
|
2240
2873
|
"BOTTOM_DISPLAY_MUTATION_DENIED",
|
|
2241
|
-
"
|
|
2242
|
-
activeWindowScope
|
|
2874
|
+
"Agents cannot mutate primary or bottom-display user browser windows.",
|
|
2875
|
+
activeWindowScope,
|
|
2876
|
+
policyTier
|
|
2243
2877
|
);
|
|
2244
2878
|
}
|
|
2245
2879
|
|
|
2246
2880
|
const targetWindowId = target.windowId ? String(target.windowId) : "";
|
|
2247
2881
|
const allowOtherWindow =
|
|
2248
2882
|
activeWindowScope.mutationPolicy && activeWindowScope.mutationPolicy.allowOtherWindowMutation;
|
|
2249
|
-
|
|
2883
|
+
const crossWindowMutation = !!(
|
|
2250
2884
|
targetWindowId &&
|
|
2251
2885
|
activeWindowId &&
|
|
2252
|
-
targetWindowId !== activeWindowId
|
|
2253
|
-
|
|
2254
|
-
) {
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2886
|
+
targetWindowId !== activeWindowId
|
|
2887
|
+
);
|
|
2888
|
+
if (crossWindowMutation && !allowOtherWindow) {
|
|
2889
|
+
if (isPrime && isPrimeLiveTargetVerified(target)) {
|
|
2890
|
+
// Prime may continue after verified top-display or extension-managed ownership.
|
|
2891
|
+
} else if (isPrime) {
|
|
2892
|
+
return denyRouterIntent(
|
|
2893
|
+
intent,
|
|
2894
|
+
"PRIME_TARGET_UNVERIFIED",
|
|
2895
|
+
"Equanaut Prime cross-window live mutation requires top-display agent ownership or extension-managed target proof.",
|
|
2896
|
+
activeWindowScope,
|
|
2897
|
+
policyTier
|
|
2898
|
+
);
|
|
2899
|
+
} else {
|
|
2900
|
+
return denyRouterIntent(
|
|
2901
|
+
intent,
|
|
2902
|
+
"OTHER_WINDOW_MUTATION_DENIED",
|
|
2903
|
+
"Normal sidepanel requests may mutate only the active sidepanel window. Open or rebind the target first.",
|
|
2904
|
+
activeWindowScope,
|
|
2905
|
+
policyTier
|
|
2906
|
+
);
|
|
2907
|
+
}
|
|
2261
2908
|
}
|
|
2262
2909
|
|
|
2263
2910
|
if (
|
|
2264
2911
|
["open", "restore", "open_orchestrator_url"].includes(intent) &&
|
|
2265
2912
|
activeWindowScope.displayRole &&
|
|
2266
|
-
activeWindowScope.displayRole !== "top_agents"
|
|
2913
|
+
normalizeRole(activeWindowScope.displayRole) !== "top_agents"
|
|
2267
2914
|
) {
|
|
2268
2915
|
return denyRouterIntent(
|
|
2269
2916
|
intent,
|
|
2270
2917
|
"TOP_DISPLAY_REQUIRED",
|
|
2271
2918
|
"Open and restore actions must use the top-display agent workspace.",
|
|
2272
|
-
activeWindowScope
|
|
2919
|
+
activeWindowScope,
|
|
2920
|
+
policyTier
|
|
2273
2921
|
);
|
|
2274
2922
|
}
|
|
2275
2923
|
|
|
@@ -2280,21 +2928,31 @@
|
|
|
2280
2928
|
intent,
|
|
2281
2929
|
"FLEET_TARGET_UNAVAILABLE",
|
|
2282
2930
|
"Dispatch requires a live or reachable fleet target.",
|
|
2283
|
-
activeWindowScope
|
|
2931
|
+
activeWindowScope,
|
|
2932
|
+
policyTier
|
|
2284
2933
|
);
|
|
2285
2934
|
}
|
|
2286
2935
|
}
|
|
2287
2936
|
|
|
2937
|
+
const extensionOwnedMetadata = isExtensionOwnedMetadataTarget(target);
|
|
2938
|
+
const scope =
|
|
2939
|
+
intent === "dispatch_to_fleet"
|
|
2940
|
+
? "fleet"
|
|
2941
|
+
: isPrime && (extensionOwnedMetadata || crossWindowMutation)
|
|
2942
|
+
? "prime_global"
|
|
2943
|
+
: "active_window";
|
|
2944
|
+
|
|
2288
2945
|
return {
|
|
2289
2946
|
intent,
|
|
2290
2947
|
target,
|
|
2291
|
-
scope
|
|
2948
|
+
scope,
|
|
2292
2949
|
mutation: true,
|
|
2293
2950
|
requiresConfirmation: !!data.requiresConfirmation,
|
|
2294
2951
|
preview: data.preview || `${intent} ${target.title || target.id || "target"}`,
|
|
2295
2952
|
audit: {
|
|
2296
2953
|
requestedBy: "sidepanel",
|
|
2297
2954
|
activeWindowId: activeWindowId || "unknown",
|
|
2955
|
+
policyTier,
|
|
2298
2956
|
reason: data.reason || "user_request",
|
|
2299
2957
|
createdAt: new Date().toISOString(),
|
|
2300
2958
|
},
|
|
@@ -2307,6 +2965,8 @@
|
|
|
2307
2965
|
fsFuzzyMatch,
|
|
2308
2966
|
fsFormatEventDescription,
|
|
2309
2967
|
fsApplyFilters,
|
|
2968
|
+
normalizeArchiveWorkflowStatus,
|
|
2969
|
+
fsPartitionTaskthreadGroups,
|
|
2310
2970
|
fsApplyAdvancedFilters,
|
|
2311
2971
|
fsSortGroups,
|
|
2312
2972
|
fsGroupBy,
|
|
@@ -2357,13 +3017,24 @@
|
|
|
2357
3017
|
groupAndSortForDeletion,
|
|
2358
3018
|
SUPPORTED_ROUTER_INTENTS,
|
|
2359
3019
|
selectEquanautRouterRoute,
|
|
3020
|
+
isPrimeRouterActor,
|
|
3021
|
+
isExtensionOwnedMetadataTarget,
|
|
3022
|
+
isPrimeLiveTargetVerified,
|
|
2360
3023
|
normalizeEntityDescription,
|
|
2361
3024
|
normalizeCatalogRecord,
|
|
2362
3025
|
buildGlobalContextCatalog,
|
|
2363
3026
|
countGlobalContextCatalog,
|
|
2364
3027
|
buildAgentContextEnvelope,
|
|
3028
|
+
buildBwoaWindowHubSession,
|
|
3029
|
+
countBwoaWindowHubSession,
|
|
3030
|
+
buildBwoaDelegationEnvelope,
|
|
3031
|
+
buildBwoaWindowHubConfiguration,
|
|
3032
|
+
buildBwoaEpoaHandoffPrompt,
|
|
3033
|
+
buildBwoaSpokePrompt,
|
|
3034
|
+
validateBwoaRouterIntent,
|
|
2365
3035
|
validateRouterIntent,
|
|
2366
3036
|
DEFAULT_DOMAIN_DISPLAY_MAP,
|
|
3037
|
+
BWOA_DEFAULT_SPACE_URL,
|
|
2367
3038
|
};
|
|
2368
3039
|
|
|
2369
3040
|
// Browser: register on globalThis
|