agent-embassy 1.6.1 → 1.7.1
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/CHANGELOG.md +33 -0
- package/README.md +9 -9
- package/README.zh-CN.md +9 -9
- package/SECURITY.md +34 -77
- package/dist/src/gateway/acp-client.d.ts +117 -0
- package/dist/src/gateway/acp-client.js +382 -0
- package/dist/src/gateway/acp-client.js.map +1 -0
- package/dist/src/gateway/acp-provider.d.ts +65 -0
- package/dist/src/gateway/acp-provider.js +163 -0
- package/dist/src/gateway/acp-provider.js.map +1 -0
- package/dist/src/gateway/claude-helper-protocol.d.ts +3 -1
- package/dist/src/gateway/claude-helper-protocol.js +15 -5
- package/dist/src/gateway/claude-helper-protocol.js.map +1 -1
- package/dist/src/gateway/claude-helper-supervisor.d.ts +3 -1
- package/dist/src/gateway/claude-helper-supervisor.js +16 -2
- package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
- package/dist/src/gateway/claude-helper.js +4 -3
- package/dist/src/gateway/claude-helper.js.map +1 -1
- package/dist/src/gateway/claude-peer.d.ts +1 -1
- package/dist/src/gateway/claude-peer.js +11 -13
- package/dist/src/gateway/claude-peer.js.map +1 -1
- package/dist/src/gateway/claude-runtime.d.ts +0 -20
- package/dist/src/gateway/claude-runtime.js +6 -127
- package/dist/src/gateway/claude-runtime.js.map +1 -1
- package/dist/src/gateway/cli-copy.d.ts +1 -1
- package/dist/src/gateway/cli-copy.en.d.ts +3 -1
- package/dist/src/gateway/cli-copy.en.js +5 -2
- package/dist/src/gateway/cli-copy.en.js.map +1 -1
- package/dist/src/gateway/cli-copy.js +2 -0
- package/dist/src/gateway/cli-copy.js.map +1 -1
- package/dist/src/gateway/cli-copy.zh-CN.d.ts +3 -1
- package/dist/src/gateway/cli-copy.zh-CN.js +5 -2
- package/dist/src/gateway/cli-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/cli.d.ts +2 -2
- package/dist/src/gateway/cli.js +73 -6
- package/dist/src/gateway/cli.js.map +1 -1
- package/dist/src/gateway/codex-app-server.d.ts +5 -74
- package/dist/src/gateway/codex-app-server.js +9 -599
- package/dist/src/gateway/codex-app-server.js.map +1 -1
- package/dist/src/gateway/codex-doctor.d.ts +33 -0
- package/dist/src/gateway/codex-doctor.js +148 -0
- package/dist/src/gateway/codex-doctor.js.map +1 -0
- package/dist/src/gateway/codex-local-transport.d.ts +13 -26
- package/dist/src/gateway/codex-local-transport.js +31 -76
- package/dist/src/gateway/codex-local-transport.js.map +1 -1
- package/dist/src/gateway/compatibility.d.ts +6 -66
- package/dist/src/gateway/compatibility.js +14 -296
- package/dist/src/gateway/compatibility.js.map +1 -1
- package/dist/src/gateway/config.d.ts +9 -0
- package/dist/src/gateway/config.js +6 -2
- package/dist/src/gateway/config.js.map +1 -1
- package/dist/src/gateway/control.d.ts +16 -1
- package/dist/src/gateway/control.js +128 -59
- package/dist/src/gateway/control.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.d.ts +1 -1
- package/dist/src/gateway/dashboard-copy.en.d.ts +19 -44
- package/dist/src/gateway/dashboard-copy.en.js +42 -67
- package/dist/src/gateway/dashboard-copy.en.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.js +19 -44
- package/dist/src/gateway/dashboard-copy.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +19 -44
- package/dist/src/gateway/dashboard-copy.zh-CN.js +42 -67
- package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/dashboard-model.d.ts +41 -76
- package/dist/src/gateway/dashboard-model.js +167 -257
- package/dist/src/gateway/dashboard-model.js.map +1 -1
- package/dist/src/gateway/dashboard.d.ts +0 -3
- package/dist/src/gateway/dashboard.js +77 -76
- package/dist/src/gateway/dashboard.js.map +1 -1
- package/dist/src/gateway/deepseek-detect.d.ts +7 -6
- package/dist/src/gateway/deepseek-detect.js +31 -115
- package/dist/src/gateway/deepseek-detect.js.map +1 -1
- package/dist/src/gateway/live-dashboard-app/app.js +175 -621
- package/dist/src/gateway/live-dashboard-command.js +2 -4
- package/dist/src/gateway/live-dashboard-command.js.map +1 -1
- package/dist/src/gateway/live-dashboard-http.d.ts +1 -2
- package/dist/src/gateway/live-dashboard-http.js +14 -15
- package/dist/src/gateway/live-dashboard-http.js.map +1 -1
- package/dist/src/gateway/progress-watch-machine.d.ts +1 -4
- package/dist/src/gateway/progress-watch-machine.js.map +1 -1
- package/dist/src/gateway/provenance-envelope.d.ts +3 -2
- package/dist/src/gateway/provenance-envelope.js +44 -11
- package/dist/src/gateway/provenance-envelope.js.map +1 -1
- package/dist/src/gateway/providers.d.ts +19 -85
- package/dist/src/gateway/providers.js +132 -835
- package/dist/src/gateway/providers.js.map +1 -1
- package/dist/src/gateway/server.d.ts +8 -9
- package/dist/src/gateway/server.js +63 -99
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +48 -51
- package/dist/src/gateway/service.js +748 -540
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/store.d.ts +20 -29
- package/dist/src/gateway/store.js +306 -838
- package/dist/src/gateway/store.js.map +1 -1
- package/dist/src/gateway/types.d.ts +63 -54
- package/dist/src/gateway/types.js +51 -91
- package/dist/src/gateway/types.js.map +1 -1
- package/docs/CONFIGURATION.md +11 -10
- package/docs/CONFIGURATION.zh-CN.md +10 -9
- package/docs/DASHBOARD.md +4 -38
- package/docs/DASHBOARD.zh-CN.md +4 -2
- package/docs/GATEWAY-ARCHITECTURE.md +61 -119
- package/package.json +1 -1
- package/skills/embassy-peer/SKILL.md +6 -6
|
@@ -111,7 +111,9 @@ var Embassy;
|
|
|
111
111
|
function chipKindFor(state, direction, safeErrorCode) {
|
|
112
112
|
const semantics = window.EMBASSY_BOOT.semantics;
|
|
113
113
|
return (deliveryOverride(semantics.deliveryChipBySafeErrorCode, state, safeErrorCode) ??
|
|
114
|
-
deliveryOverride(semantics.
|
|
114
|
+
deliveryOverride(semantics.deliveryChipByTargetProvider, state, direction === undefined
|
|
115
|
+
? undefined
|
|
116
|
+
: Embassy.parseDirection(direction)?.targetProvider) ??
|
|
115
117
|
presentation("delivery", state));
|
|
116
118
|
}
|
|
117
119
|
Embassy.chipKindFor = chipKindFor;
|
|
@@ -127,10 +129,6 @@ var Embassy;
|
|
|
127
129
|
return presentation("health", state);
|
|
128
130
|
}
|
|
129
131
|
Embassy.healthChipKind = healthChipKind;
|
|
130
|
-
function compatibilityChipKind(state) {
|
|
131
|
-
return presentation("compatibility", state);
|
|
132
|
-
}
|
|
133
|
-
Embassy.compatibilityChipKind = compatibilityChipKind;
|
|
134
132
|
function overallChipKind(state) {
|
|
135
133
|
return presentation("overall", state);
|
|
136
134
|
}
|
|
@@ -163,7 +161,10 @@ var Embassy;
|
|
|
163
161
|
return semantics.deliveryMeaningBySafeErrorCode.SENDER_NOT_PAIRED;
|
|
164
162
|
}
|
|
165
163
|
if (state === "delivered" && direction !== undefined) {
|
|
166
|
-
|
|
164
|
+
const target = Embassy.parseDirection(direction)?.targetProvider;
|
|
165
|
+
if (target !== undefined) {
|
|
166
|
+
return semantics.deliveryMeaningByTargetProvider[target];
|
|
167
|
+
}
|
|
167
168
|
}
|
|
168
169
|
if (state === "abandoned" && safeErrorCode !== undefined) {
|
|
169
170
|
const byCode = semantics.deliveryMeaningBySafeErrorCode;
|
|
@@ -185,8 +186,6 @@ var Embassy;
|
|
|
185
186
|
return `peer.meaning.${camelCaseToken(state)}`;
|
|
186
187
|
case "health":
|
|
187
188
|
return `health.meaning.${camelCaseToken(state)}`;
|
|
188
|
-
case "compatibility":
|
|
189
|
-
return `compatibility.meaning.${camelCaseToken(state)}`;
|
|
190
189
|
case "overall":
|
|
191
190
|
return `overall.${camelCaseToken(state)}`;
|
|
192
191
|
case "party":
|
|
@@ -244,6 +243,24 @@ var Embassy;
|
|
|
244
243
|
})(Embassy || (Embassy = {}));
|
|
245
244
|
var Embassy;
|
|
246
245
|
(function (Embassy) {
|
|
246
|
+
Embassy.GATEWAY_PROVIDERS = ["claude", "codex", "deepseek", "grok"];
|
|
247
|
+
function parseDirection(direction) {
|
|
248
|
+
const separator = direction.indexOf("_to_");
|
|
249
|
+
if (separator < 1 || separator !== direction.lastIndexOf("_to_")) {
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
const sourceProvider = direction.slice(0, separator);
|
|
253
|
+
const targetProvider = direction.slice(separator + 4);
|
|
254
|
+
const providers = Embassy.GATEWAY_PROVIDERS;
|
|
255
|
+
if (sourceProvider === targetProvider || !providers.includes(sourceProvider) ||
|
|
256
|
+
!providers.includes(targetProvider))
|
|
257
|
+
return undefined;
|
|
258
|
+
return {
|
|
259
|
+
sourceProvider: sourceProvider,
|
|
260
|
+
targetProvider: targetProvider,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
Embassy.parseDirection = parseDirection;
|
|
247
264
|
Embassy.TERMINAL_DELIVERY_STATES = [
|
|
248
265
|
"delivered",
|
|
249
266
|
"unconfirmed",
|
|
@@ -258,17 +275,10 @@ var Embassy;
|
|
|
258
275
|
Embassy.PULSE_WINDOW_MS = 3_600_000;
|
|
259
276
|
const HEALTH_WORST_FIRST = [
|
|
260
277
|
"offline",
|
|
261
|
-
"incompatible",
|
|
262
278
|
"degraded",
|
|
263
279
|
"connecting",
|
|
264
280
|
"healthy",
|
|
265
281
|
];
|
|
266
|
-
const COMPATIBILITY_WORST_FIRST = [
|
|
267
|
-
"incompatible",
|
|
268
|
-
"expired",
|
|
269
|
-
"unknown",
|
|
270
|
-
"compatible",
|
|
271
|
-
];
|
|
272
282
|
function compareText(left, right) {
|
|
273
283
|
return left < right ? -1 : left > right ? 1 : 0;
|
|
274
284
|
}
|
|
@@ -334,18 +344,6 @@ var Embassy;
|
|
|
334
344
|
return worst;
|
|
335
345
|
}
|
|
336
346
|
Embassy.worstConnectorHealth = worstConnectorHealth;
|
|
337
|
-
function worstCompatibility(model) {
|
|
338
|
-
let worst;
|
|
339
|
-
for (const connector of model.connectors) {
|
|
340
|
-
if (worst === undefined ||
|
|
341
|
-
COMPATIBILITY_WORST_FIRST.indexOf(connector.compatibility) <
|
|
342
|
-
COMPATIBILITY_WORST_FIRST.indexOf(worst)) {
|
|
343
|
-
worst = connector.compatibility;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
return worst;
|
|
347
|
-
}
|
|
348
|
-
Embassy.worstCompatibility = worstCompatibility;
|
|
349
347
|
function pulse(model) {
|
|
350
348
|
const generatedMs = parseTimestampMs(model.generatedAt);
|
|
351
349
|
const cutoffMs = generatedMs === undefined ? undefined : generatedMs - Embassy.PULSE_WINDOW_MS;
|
|
@@ -369,10 +367,6 @@ var Embassy;
|
|
|
369
367
|
};
|
|
370
368
|
}
|
|
371
369
|
Embassy.pulse = pulse;
|
|
372
|
-
function isMonitorOnly(route) {
|
|
373
|
-
return route.safeErrorCode === "CODEX_WRITES_DISABLED";
|
|
374
|
-
}
|
|
375
|
-
Embassy.isMonitorOnly = isMonitorOnly;
|
|
376
370
|
function hasLifecycleTruncation(group) {
|
|
377
371
|
for (let index = 1; index < group.events.length; index += 1) {
|
|
378
372
|
const previous = group.events[index - 1];
|
|
@@ -436,24 +430,22 @@ var Embassy;
|
|
|
436
430
|
}
|
|
437
431
|
Embassy.extractSuccessions = extractSuccessions;
|
|
438
432
|
function overviewProps(model, nowMs) {
|
|
439
|
-
const
|
|
433
|
+
const nonReadyConsentEdgeCount = model.graph.consentEdgeCount - model.graph.readyConsentEdgeCount;
|
|
440
434
|
return {
|
|
441
435
|
generatedAt: model.generatedAt,
|
|
442
436
|
inboundMode: model.inboundMode,
|
|
443
437
|
overall: model.overall,
|
|
444
438
|
statusStrip: {
|
|
445
439
|
broker: model.health,
|
|
446
|
-
|
|
447
|
-
codexConnector: worstConnectorHealth(model, "codex"),
|
|
448
|
-
compatibility: worstCompatibility(model),
|
|
440
|
+
providers: Embassy.GATEWAY_PROVIDERS.map((provider) => ({ provider, health: worstConnectorHealth(model, provider) })),
|
|
449
441
|
},
|
|
450
442
|
exchange: model.exchange,
|
|
451
|
-
|
|
452
|
-
queueCodexToClaude: queueSplit(model, "claude", nowMs),
|
|
443
|
+
providerQueues: Embassy.GATEWAY_PROVIDERS.map((provider) => ({ provider, queue: queueSplit(model, provider, nowMs) })),
|
|
453
444
|
graph: model.graph,
|
|
454
|
-
|
|
445
|
+
degradedConsentEdgeCopyKey: nonReadyConsentEdgeCount <= 0
|
|
455
446
|
? undefined
|
|
456
|
-
:
|
|
447
|
+
: nonReadyConsentEdgeCount === 1 &&
|
|
448
|
+
!model.graph.consentEdgeCountIsLowerBound
|
|
457
449
|
? "app.overview.degradedEdge"
|
|
458
450
|
: "app.overview.degradedEdges",
|
|
459
451
|
attention: attentionViews(model),
|
|
@@ -463,30 +455,40 @@ var Embassy;
|
|
|
463
455
|
}
|
|
464
456
|
Embassy.overviewProps = overviewProps;
|
|
465
457
|
function deliveriesGroups(model) {
|
|
466
|
-
return model.activity.map((group) =>
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
458
|
+
return model.activity.map((group) => {
|
|
459
|
+
const parsed = parseDirection(group.direction);
|
|
460
|
+
if (parsed === undefined)
|
|
461
|
+
throw new Error("INVALID_MESSAGE_DIRECTION");
|
|
462
|
+
return {
|
|
463
|
+
key: deliveryGroupKey(group),
|
|
464
|
+
group,
|
|
465
|
+
routePair: `${group.sourceAlias} → ${group.targetAlias}`,
|
|
466
|
+
sourceProvider: parsed.sourceProvider,
|
|
467
|
+
targetProvider: parsed.targetProvider,
|
|
468
|
+
eventsTruncated: hasLifecycleTruncation(group),
|
|
469
|
+
};
|
|
470
|
+
});
|
|
472
471
|
}
|
|
473
472
|
Embassy.deliveriesGroups = deliveriesGroups;
|
|
473
|
+
function matchesProviderFilters(view, from, to) {
|
|
474
|
+
const parsed = parseDirection(view.group.direction);
|
|
475
|
+
return parsed !== undefined && (from === "all" || parsed.sourceProvider === from) &&
|
|
476
|
+
(to === "all" || parsed.targetProvider === to);
|
|
477
|
+
}
|
|
478
|
+
Embassy.matchesProviderFilters = matchesProviderFilters;
|
|
474
479
|
function routesProps(model, nowMs) {
|
|
475
|
-
const
|
|
476
|
-
.filter((route) => route.provider === "codex")
|
|
477
|
-
.map((route) => ({
|
|
480
|
+
const routes = model.routes.map((route) => ({
|
|
478
481
|
route,
|
|
479
|
-
monitorOnly: isMonitorOnly(route),
|
|
480
482
|
oldestAgeMs: routeOldestAgeMs(route, nowMs),
|
|
481
483
|
}));
|
|
482
484
|
return {
|
|
483
485
|
inboundMode: model.inboundMode,
|
|
484
486
|
peers: model.peers,
|
|
485
487
|
peersOmitted: model.omissions.availablePeers,
|
|
486
|
-
|
|
488
|
+
routes,
|
|
487
489
|
routesOmitted: model.omissions.routes,
|
|
488
|
-
|
|
489
|
-
|
|
490
|
+
consentEdges: model.consentEdges,
|
|
491
|
+
consentEdgesOmitted: model.omissions.consentEdges,
|
|
490
492
|
graph: model.graph,
|
|
491
493
|
successions: extractSuccessions(model),
|
|
492
494
|
};
|
|
@@ -527,7 +529,6 @@ var Embassy;
|
|
|
527
529
|
return {
|
|
528
530
|
connectors: model.connectors,
|
|
529
531
|
connectorsOmitted: model.omissions.connectors,
|
|
530
|
-
compatibilityChecks: model.compatibilityChecks ?? [],
|
|
531
532
|
expiredCount: model.accounting.expired,
|
|
532
533
|
...(model.deadlinePressure === undefined
|
|
533
534
|
? {}
|
|
@@ -542,6 +543,7 @@ var Embassy;
|
|
|
542
543
|
Embassy.adapter = {
|
|
543
544
|
overviewProps,
|
|
544
545
|
deliveriesGroups,
|
|
546
|
+
matchesProviderFilters,
|
|
545
547
|
routesProps,
|
|
546
548
|
activityRows,
|
|
547
549
|
diagnosticsProps,
|
|
@@ -549,9 +551,7 @@ var Embassy;
|
|
|
549
551
|
routeOldestAgeMs,
|
|
550
552
|
pulse,
|
|
551
553
|
worstConnectorHealth,
|
|
552
|
-
worstCompatibility,
|
|
553
554
|
extractSuccessions,
|
|
554
|
-
isMonitorOnly,
|
|
555
555
|
hasLifecycleTruncation,
|
|
556
556
|
deliveriesTruncated,
|
|
557
557
|
deliveryGroupKey,
|
|
@@ -935,14 +935,6 @@ var Embassy;
|
|
|
935
935
|
}
|
|
936
936
|
return (React.createElement(StatusCard, { label: props.label, detail: t(`health.meaning.${Embassy.camelCaseToken(health)}`), chip: React.createElement(Embassy.StateChip, { domain: "health", state: health, small: true }) }));
|
|
937
937
|
}
|
|
938
|
-
function CompatStatusCard(props) {
|
|
939
|
-
const t = Embassy.useT();
|
|
940
|
-
const compatibility = props.compatibility;
|
|
941
|
-
if (compatibility === undefined) {
|
|
942
|
-
return (React.createElement(StatusCard, { label: t("app.overview.compat"), detail: undefined, chip: React.createElement("span", { className: "chip chip--small", "data-kind": "inert" }, t("app.overview.connectorMissing")) }));
|
|
943
|
-
}
|
|
944
|
-
return (React.createElement(StatusCard, { label: t("app.overview.compat"), detail: t(`compatibility.meaning.${Embassy.camelCaseToken(compatibility)}`), chip: React.createElement(Embassy.StateChip, { domain: "compatibility", state: compatibility, small: true }) }));
|
|
945
|
-
}
|
|
946
938
|
function ExchangeNode(props) {
|
|
947
939
|
const party = props.party;
|
|
948
940
|
return (React.createElement("div", { className: "exchange-node" },
|
|
@@ -980,7 +972,7 @@ var Embassy;
|
|
|
980
972
|
function attentionScopeParts(item, t) {
|
|
981
973
|
const parts = [];
|
|
982
974
|
if (item.provider !== undefined) {
|
|
983
|
-
parts.push(
|
|
975
|
+
parts.push(t(`provider.${item.provider}`));
|
|
984
976
|
}
|
|
985
977
|
if (item.alias !== undefined)
|
|
986
978
|
parts.push(item.alias);
|
|
@@ -1032,25 +1024,9 @@ var Embassy;
|
|
|
1032
1024
|
function OverviewTab(props) {
|
|
1033
1025
|
const t = Embassy.useT();
|
|
1034
1026
|
const { data, onViewDeliveries } = props;
|
|
1035
|
-
const strip = data.statusStrip;
|
|
1036
|
-
const queueOut = data.queueClaudeToCodex;
|
|
1037
|
-
const queueIn = data.queueCodexToClaude;
|
|
1038
1027
|
const openInbound = data.inboundMode === "open";
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
const nextActionLine = (who, action) => action === "none"
|
|
1042
|
-
? null
|
|
1043
|
-
: `${t("next.label")} · ${who}: ${t(window.EMBASSY_BOOT.semantics.nextActionCopyKeys[action])}`;
|
|
1044
|
-
const boardNotes = [
|
|
1045
|
-
!openInbound && !hasPair && showEdges
|
|
1046
|
-
? `${t("app.overview.noPair.title")} — ${t("app.overview.noPair.body")}`
|
|
1047
|
-
: null,
|
|
1048
|
-
data.degradedPairCopyKey === undefined
|
|
1049
|
-
? null
|
|
1050
|
-
: t(data.degradedPairCopyKey),
|
|
1051
|
-
nextActionLine(t("provider.claude"), data.exchange.claude.nextAction),
|
|
1052
|
-
nextActionLine(t("provider.codex"), data.exchange.codex.nextAction),
|
|
1053
|
-
].filter((line) => line !== null);
|
|
1028
|
+
const hasConsentEdge = data.graph.consentEdgeCount > 0 ||
|
|
1029
|
+
data.graph.consentEdgeCountIsLowerBound;
|
|
1054
1030
|
const showAttention = data.attention.length > 0 || data.attentionOmitted > 0;
|
|
1055
1031
|
const maxPulse = data.pulse.bars.reduce((largest, bar) => Math.max(largest, bar.count), 1);
|
|
1056
1032
|
const selectPulseState = React.useCallback((state) => {
|
|
@@ -1065,10 +1041,8 @@ var Embassy;
|
|
|
1065
1041
|
React.createElement("section", { className: "section", "aria-labelledby": stripId },
|
|
1066
1042
|
React.createElement("h2", { className: "mono-label section-label", id: stripId }, t("app.overview.statusStrip")),
|
|
1067
1043
|
React.createElement("div", { className: "status-strip" },
|
|
1068
|
-
React.createElement(HealthStatusCard, { label: t("app.overview.broker"), health:
|
|
1069
|
-
React.createElement(HealthStatusCard, { label: t(
|
|
1070
|
-
React.createElement(HealthStatusCard, { label: t("app.overview.codexConn"), health: strip.codexConnector }),
|
|
1071
|
-
React.createElement(CompatStatusCard, { compatibility: strip.compatibility }))),
|
|
1044
|
+
React.createElement(HealthStatusCard, { label: t("app.overview.broker"), health: data.statusStrip.broker }),
|
|
1045
|
+
data.statusStrip.providers.map(({ provider, health }) => (React.createElement(HealthStatusCard, { key: provider, label: t(`provider.${provider}`), health: health }))))),
|
|
1072
1046
|
React.createElement("section", { className: "section", "aria-labelledby": exchangeId },
|
|
1073
1047
|
React.createElement("div", { className: "row section-label section-head" },
|
|
1074
1048
|
React.createElement("h2", { className: "mono-label", id: exchangeId }, t("exchange.eyebrow")),
|
|
@@ -1080,30 +1054,12 @@ var Embassy;
|
|
|
1080
1054
|
: "inbound.paired.badge")),
|
|
1081
1055
|
React.createElement("p", null, t(openInbound
|
|
1082
1056
|
? "inbound.open.body"
|
|
1083
|
-
:
|
|
1057
|
+
: hasConsentEdge
|
|
1084
1058
|
? "inbound.paired.body"
|
|
1085
1059
|
: "inbound.noPair.body"))),
|
|
1086
|
-
React.createElement("div", { className: "exchange-board" },
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
selectable: data.exchange.claude.selectable ?? "—",
|
|
1090
|
-
total: data.exchange.claude.total,
|
|
1091
|
-
}) }),
|
|
1092
|
-
showEdges ? (React.createElement("div", { className: "exchange-edges" },
|
|
1093
|
-
React.createElement(ExchangeEdge, { direction: "out", label: t("app.overview.queueC2x"), queue: queueOut }),
|
|
1094
|
-
React.createElement(ExchangeEdge, { direction: "in", label: t("app.overview.queueX2c"), queue: queueIn }))) : (React.createElement("div", { className: "no-pair" },
|
|
1095
|
-
React.createElement("span", { className: "no-pair__label" }, t(openInbound
|
|
1096
|
-
? "inbound.open.badge"
|
|
1097
|
-
: "app.overview.noPair.title")),
|
|
1098
|
-
React.createElement("span", { className: "no-pair__body" }, t(openInbound
|
|
1099
|
-
? "inbound.open.body"
|
|
1100
|
-
: "app.overview.noPair.body")))),
|
|
1101
|
-
React.createElement(ExchangeNode, { title: t("app.overview.node.codex.title"), sub: t("app.overview.node.codex.sub"), party: data.exchange.codex, countLine: t("app.overview.count.codex", {
|
|
1102
|
-
ready: data.exchange.codex.ready,
|
|
1103
|
-
total: data.exchange.codex.total,
|
|
1104
|
-
monitorOnly: data.exchange.codex.monitorOnly ?? 0,
|
|
1105
|
-
}) })),
|
|
1106
|
-
boardNotes.length === 0 ? null : (React.createElement("div", { className: "exchange-notes stack-sm" }, boardNotes.map((line) => (React.createElement("p", { className: "text-xs text-body-muted", key: line }, line)))))),
|
|
1060
|
+
React.createElement("div", { className: "exchange-board" }, data.exchange.parties.map((party) => (React.createElement(ExchangeNode, { key: party.kind, title: t(`provider.${party.kind}`), sub: party.kind, party: party, countLine: `${party.ready}/${party.total}` })))),
|
|
1061
|
+
React.createElement("div", { className: "exchange-edges" }, data.providerQueues.map(({ provider, queue }) => (React.createElement(ExchangeEdge, { key: provider, direction: "in", label: t(`provider.${provider}`), queue: queue })))),
|
|
1062
|
+
data.degradedConsentEdgeCopyKey === undefined ? null : (React.createElement("p", { className: "text-xs text-body-muted" }, t(data.degradedConsentEdgeCopyKey)))),
|
|
1107
1063
|
showAttention ? (React.createElement("section", { className: "section", "aria-labelledby": attentionId },
|
|
1108
1064
|
React.createElement("div", { className: "row section-label section-head" },
|
|
1109
1065
|
React.createElement("h2", { className: "mono-label", id: attentionId }, t("attention.eyebrow")),
|
|
@@ -1139,18 +1095,6 @@ var Embassy;
|
|
|
1139
1095
|
"abandoned",
|
|
1140
1096
|
];
|
|
1141
1097
|
const DELIVERY_STATE_FILTERS_COVER_THE_UNION = true;
|
|
1142
|
-
const DIRECTION_FILTERS = [
|
|
1143
|
-
"claude_to_codex",
|
|
1144
|
-
"codex_to_claude",
|
|
1145
|
-
];
|
|
1146
|
-
const DIRECTION_COPY_KEYS = {
|
|
1147
|
-
claude_to_codex: "direction.claudeToCodex",
|
|
1148
|
-
codex_to_claude: "direction.codexToClaude",
|
|
1149
|
-
};
|
|
1150
|
-
const DIRECTION_PILL_COPY_KEYS = {
|
|
1151
|
-
claude_to_codex: "direction.claudeToCodex",
|
|
1152
|
-
codex_to_claude: "app.deliveries.dir.codexToClaude",
|
|
1153
|
-
};
|
|
1154
1098
|
const SEND_TO_CODEX_CMD = "embassy send-to-codex --from <alias> --to <alias>";
|
|
1155
1099
|
const countFormatters = new Map();
|
|
1156
1100
|
function fmtCount(locale, value) {
|
|
@@ -1273,7 +1217,9 @@ var Embassy;
|
|
|
1273
1217
|
React.createElement("div", { className: "detail-pane__sub" },
|
|
1274
1218
|
props.view.routePair,
|
|
1275
1219
|
" \u00B7 ",
|
|
1276
|
-
t(
|
|
1220
|
+
t(`provider.${props.view.sourceProvider}`),
|
|
1221
|
+
" \u2192 ",
|
|
1222
|
+
t(`provider.${props.view.targetProvider}`))),
|
|
1277
1223
|
React.createElement("div", null,
|
|
1278
1224
|
React.createElement(Embassy.MonoLabel, { className: "section-label section-label--lifecycle" }, t("app.deliveries.lifecycle")),
|
|
1279
1225
|
React.createElement(DeliveryLifecycle, { group: group }),
|
|
@@ -1326,8 +1272,6 @@ var Embassy;
|
|
|
1326
1272
|
pair_removed: "watches.reason.pairRemoved",
|
|
1327
1273
|
endpoint_retired: "watches.reason.endpointRetired",
|
|
1328
1274
|
tracking_disabled: "watches.reason.trackingDisabled",
|
|
1329
|
-
legacy_upgrade: "watches.reason.legacyUpgrade",
|
|
1330
|
-
legacy_done: "watches.reason.legacyDone",
|
|
1331
1275
|
};
|
|
1332
1276
|
function ProgressWatchRegister(props) {
|
|
1333
1277
|
const t = Embassy.useT();
|
|
@@ -1385,7 +1329,8 @@ var Embassy;
|
|
|
1385
1329
|
const [locale] = Embassy.useLocale();
|
|
1386
1330
|
const captionId = React.useId();
|
|
1387
1331
|
const searchId = React.useId();
|
|
1388
|
-
const [
|
|
1332
|
+
const [fromProvider, setFromProvider] = React.useState("all");
|
|
1333
|
+
const [toProvider, setToProvider] = React.useState("all");
|
|
1389
1334
|
const [stateFilter, setStateFilter] = React.useState("all");
|
|
1390
1335
|
const [viewMode, setViewMode] = React.useState("byRoute");
|
|
1391
1336
|
const [query, setQuery] = React.useState("");
|
|
@@ -1409,10 +1354,9 @@ var Embassy;
|
|
|
1409
1354
|
clearPreset?.();
|
|
1410
1355
|
}, [preset]);
|
|
1411
1356
|
const needle = query.trim().toLowerCase();
|
|
1412
|
-
const filtered = React.useMemo(() => groups.filter((view) => (
|
|
1413
|
-
view.group.direction === directionFilter) &&
|
|
1357
|
+
const filtered = React.useMemo(() => groups.filter((view) => Embassy.adapter.matchesProviderFilters(view, fromProvider, toProvider) &&
|
|
1414
1358
|
(stateFilter === "all" || view.group.state === stateFilter) &&
|
|
1415
|
-
matchesQuery(view, needle)), [groups,
|
|
1359
|
+
matchesQuery(view, needle)), [groups, fromProvider, toProvider, stateFilter, needle]);
|
|
1416
1360
|
const pairs = React.useMemo(() => groupByRoutePair(filtered), [filtered]);
|
|
1417
1361
|
const ordered = React.useMemo(() => (viewMode === "flat" ? filtered : pairs.flatMap((pair) => pair.rows)), [viewMode, filtered, pairs]);
|
|
1418
1362
|
const selectedView = ordered.find((view) => view.key === selectedKey);
|
|
@@ -1483,14 +1427,19 @@ var Embassy;
|
|
|
1483
1427
|
}))) : null),
|
|
1484
1428
|
React.createElement("div", { className: "filters" },
|
|
1485
1429
|
React.createElement("div", { className: "filter-group" },
|
|
1486
|
-
React.createElement(Embassy.MonoLabel, null, t("app.deliveries.
|
|
1487
|
-
React.createElement("div", { className: "pill-row", role: "group", "aria-label": t("app.deliveries.
|
|
1488
|
-
React.createElement(Embassy.FilterPill, { active:
|
|
1489
|
-
|
|
1490
|
-
} }, t("app.deliveries.
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
} }, t(
|
|
1430
|
+
React.createElement(Embassy.MonoLabel, null, t("app.deliveries.fromProvider")),
|
|
1431
|
+
React.createElement("div", { className: "pill-row", role: "group", "aria-label": t("app.deliveries.fromProvider") },
|
|
1432
|
+
React.createElement(Embassy.FilterPill, { active: fromProvider === "all", onClick: () => {
|
|
1433
|
+
setFromProvider("all");
|
|
1434
|
+
} }, t("app.deliveries.providerAll")),
|
|
1435
|
+
Embassy.GATEWAY_PROVIDERS.map((provider) => (React.createElement(Embassy.FilterPill, { key: provider, active: fromProvider === provider, onClick: () => {
|
|
1436
|
+
setFromProvider(provider);
|
|
1437
|
+
} }, t(`provider.${provider}`)))))),
|
|
1438
|
+
React.createElement("div", { className: "filter-group" },
|
|
1439
|
+
React.createElement(Embassy.MonoLabel, null, t("app.deliveries.toProvider")),
|
|
1440
|
+
React.createElement("div", { className: "pill-row", role: "group", "aria-label": t("app.deliveries.toProvider") },
|
|
1441
|
+
React.createElement(Embassy.FilterPill, { active: toProvider === "all", onClick: () => { setToProvider("all"); } }, t("app.deliveries.providerAll")),
|
|
1442
|
+
Embassy.GATEWAY_PROVIDERS.map((provider) => (React.createElement(Embassy.FilterPill, { key: provider, active: toProvider === provider, onClick: () => { setToProvider(provider); } }, t(`provider.${provider}`)))))),
|
|
1494
1443
|
React.createElement("div", { className: "filter-group" },
|
|
1495
1444
|
React.createElement(Embassy.MonoLabel, null, t("app.deliveries.view.label")),
|
|
1496
1445
|
React.createElement("div", { className: "pill-row", role: "group", "aria-label": t("app.deliveries.view.label") },
|
|
@@ -1528,464 +1477,92 @@ var Embassy;
|
|
|
1528
1477
|
})(Embassy || (Embassy = {}));
|
|
1529
1478
|
var Embassy;
|
|
1530
1479
|
(function (Embassy) {
|
|
1531
|
-
const TOPOLOGY_ROW_HEIGHT_PX = 64;
|
|
1532
|
-
const TOPOLOGY_PADDING_PX = 18;
|
|
1533
|
-
const TOPOLOGY_EDGE_WIDTH_PX = 220;
|
|
1534
|
-
const SELECT_CLAUDE_COMMAND = "embassy select-claude --alias <alias>";
|
|
1535
|
-
const REGISTER_CODEX_COMMAND = "embassy register-codex --alias codex-<name>@<host>";
|
|
1536
|
-
const SUCCEEDS_COMMAND = "embassy register-codex --alias <new> --succeeds <old>";
|
|
1537
|
-
const ROUTE_COUNTER_ROWS = [
|
|
1538
|
-
["accepted", "diagnostics.accepted"],
|
|
1539
|
-
["delivered", "diagnostics.delivered"],
|
|
1540
|
-
["unconfirmed", "diagnostics.unconfirmed"],
|
|
1541
|
-
["failed", "diagnostics.failed"],
|
|
1542
|
-
["ambiguous", "diagnostics.ambiguous"],
|
|
1543
|
-
["expired", "diagnostics.expired"],
|
|
1544
|
-
["cancelled", "diagnostics.cancelled"],
|
|
1545
|
-
["abandoned", "diagnostics.abandoned"],
|
|
1546
|
-
["rejected", "diagnostics.rejected"],
|
|
1547
|
-
["bytesAccepted", "diagnostics.bytesAccepted"],
|
|
1548
|
-
];
|
|
1549
|
-
const countFormatters = new Map();
|
|
1550
|
-
function formatCount(value, locale) {
|
|
1551
|
-
const existing = countFormatters.get(locale);
|
|
1552
|
-
if (existing !== undefined)
|
|
1553
|
-
return existing.format(value);
|
|
1554
|
-
const formatter = new Intl.NumberFormat(locale);
|
|
1555
|
-
countFormatters.set(locale, formatter);
|
|
1556
|
-
return formatter.format(value);
|
|
1557
|
-
}
|
|
1558
|
-
function isReadyCodexRoute(route) {
|
|
1559
|
-
return (route.enabled &&
|
|
1560
|
-
route.compatibility === "compatible" &&
|
|
1561
|
-
(route.state === "idle" || route.state === "busy"));
|
|
1562
|
-
}
|
|
1563
|
-
function rowIdentity(alias, host) {
|
|
1564
|
-
return `${alias}\u0000${host}`;
|
|
1565
|
-
}
|
|
1566
1480
|
function canRequestStaleCodexRegistrationRemoval(route) {
|
|
1567
1481
|
return route.provider === "codex" && route.state === "stale";
|
|
1568
1482
|
}
|
|
1569
1483
|
Embassy.canRequestStaleCodexRegistrationRemoval = canRequestStaleCodexRegistrationRemoval;
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
}
|
|
1575
|
-
function topologyEdges(data) {
|
|
1576
|
-
const claudeIndices = new Map(data.peers.map((peer, index) => [peer.alias, index]));
|
|
1577
|
-
const codexIndices = new Map(data.codexRoutes.map((view, index) => [view.route.alias, index]));
|
|
1578
|
-
const edges = [];
|
|
1579
|
-
for (const pair of data.pairs) {
|
|
1580
|
-
const claudeIndex = claudeIndices.get(pair.claudeAlias);
|
|
1581
|
-
const codexIndex = codexIndices.get(pair.codexAlias);
|
|
1582
|
-
if (claudeIndex === undefined || codexIndex === undefined)
|
|
1583
|
-
continue;
|
|
1584
|
-
edges.push({
|
|
1585
|
-
claudeIndex,
|
|
1586
|
-
codexIndex,
|
|
1587
|
-
claudeAlias: pair.claudeAlias,
|
|
1588
|
-
codexAlias: pair.codexAlias,
|
|
1589
|
-
state: pair.state,
|
|
1590
|
-
});
|
|
1591
|
-
}
|
|
1592
|
-
return edges;
|
|
1593
|
-
}
|
|
1594
|
-
function isEdgeEndpoint(edge, side, index) {
|
|
1595
|
-
return side === "claude"
|
|
1596
|
-
? index === edge.claudeIndex
|
|
1597
|
-
: index === edge.codexIndex;
|
|
1598
|
-
}
|
|
1599
|
-
function chipHighlight(focus, edges, side, index) {
|
|
1600
|
-
if (focus === undefined)
|
|
1601
|
-
return undefined;
|
|
1602
|
-
if (focus.side === side && focus.index === index)
|
|
1603
|
-
return "on";
|
|
1604
|
-
if (focus.side !== side &&
|
|
1605
|
-
edges.some((edge) => isEdgeEndpoint(edge, focus.side, focus.index) &&
|
|
1606
|
-
isEdgeEndpoint(edge, side, index))) {
|
|
1607
|
-
return "on";
|
|
1608
|
-
}
|
|
1609
|
-
return "off";
|
|
1610
|
-
}
|
|
1611
|
-
function edgeHighlight(focus, edge) {
|
|
1612
|
-
if (focus === undefined)
|
|
1613
|
-
return undefined;
|
|
1614
|
-
return isEdgeEndpoint(edge, focus.side, focus.index) ? "on" : "off";
|
|
1615
|
-
}
|
|
1616
|
-
function TopologyColumn(props) {
|
|
1617
|
-
const { side, highlightAt, onFocusChange } = props;
|
|
1618
|
-
if (props.items.length === 0) {
|
|
1619
|
-
return (React.createElement("div", { className: "topology__col" },
|
|
1620
|
-
React.createElement("p", { className: "topology__empty" }, props.emptyText)));
|
|
1621
|
-
}
|
|
1622
|
-
return (React.createElement("div", { className: "topology__col" },
|
|
1623
|
-
React.createElement("div", { role: "list", "aria-label": props.listLabel }, props.items.map((item, index) => (React.createElement("div", { key: item.key, role: "listitem", className: side === "claude"
|
|
1624
|
-
? "topo-row topo-row--left"
|
|
1625
|
-
: "topo-row topo-row--right", onMouseEnter: () => {
|
|
1626
|
-
onFocusChange({ side, index });
|
|
1627
|
-
}, onMouseLeave: () => {
|
|
1628
|
-
onFocusChange(undefined);
|
|
1629
|
-
} },
|
|
1630
|
-
React.createElement("span", { className: "topo-chip", "data-side": side, "data-candidate": item.candidate ? "true" : undefined, "data-highlight": highlightAt(side, index), tabIndex: 0, onFocus: () => {
|
|
1631
|
-
onFocusChange({ side, index });
|
|
1632
|
-
}, onBlur: () => {
|
|
1633
|
-
onFocusChange(undefined);
|
|
1634
|
-
} }, item.alias),
|
|
1635
|
-
React.createElement("span", { className: "sr-only" }, item.srLabel)))))));
|
|
1636
|
-
}
|
|
1637
|
-
function TopologyEdgeSvg(props) {
|
|
1638
|
-
const height = TOPOLOGY_PADDING_PX * 2 + props.rows * TOPOLOGY_ROW_HEIGHT_PX;
|
|
1639
|
-
return (React.createElement("svg", { className: "topology__svg", width: TOPOLOGY_EDGE_WIDTH_PX, height: height, viewBox: `0 0 ${TOPOLOGY_EDGE_WIDTH_PX} ${height}`, "aria-hidden": "true", focusable: "false" }, props.edges.map((edge) => {
|
|
1640
|
-
const highlight = edgeHighlight(props.focus, edge);
|
|
1641
|
-
const stroke = highlight === "on"
|
|
1642
|
-
? props.focusSide === "codex"
|
|
1643
|
-
? "var(--action-blue)"
|
|
1644
|
-
: "var(--coral-accent, var(--coral))"
|
|
1645
|
-
: edge.state === "ready"
|
|
1646
|
-
? "var(--hairline)"
|
|
1647
|
-
: "var(--warning)";
|
|
1648
|
-
return (React.createElement("path", { key: `${edge.claudeAlias}\0${edge.codexAlias}`, fill: "none", d: `M 0 ${topologyRowCenterY(edge.claudeIndex)} C 80 ${topologyRowCenterY(edge.claudeIndex)} 140 ${topologyRowCenterY(edge.codexIndex)} ${TOPOLOGY_EDGE_WIDTH_PX} ${topologyRowCenterY(edge.codexIndex)}`, style: {
|
|
1649
|
-
stroke,
|
|
1650
|
-
strokeDasharray: edge.state === "ready" ? undefined : "5 4",
|
|
1651
|
-
strokeWidth: highlight === "on" ? 2 : 1.25,
|
|
1652
|
-
opacity: highlight === "off" ? 0.2 : 1,
|
|
1653
|
-
} }));
|
|
1654
|
-
})));
|
|
1655
|
-
}
|
|
1656
|
-
function DetailRow(props) {
|
|
1657
|
-
return (React.createElement("p", { className: "detail-row" },
|
|
1658
|
-
React.createElement("span", { className: "detail-label" },
|
|
1659
|
-
props.label,
|
|
1660
|
-
": "),
|
|
1661
|
-
props.children));
|
|
1662
|
-
}
|
|
1663
|
-
function AbsentDetail(props) {
|
|
1664
|
-
const t = Embassy.useT();
|
|
1665
|
-
return (React.createElement("p", { className: "detail-row" },
|
|
1666
|
-
React.createElement("span", { className: "detail-value detail-value--mono" }, props.fields.join(" · ")),
|
|
1667
|
-
React.createElement("span", { className: "detail-label" },
|
|
1668
|
-
" \u2014 ",
|
|
1669
|
-
t("app.routes.detail.absent"))));
|
|
1484
|
+
Embassy.canOfferConsentEdgeCandidate = (route) => route.enabled && (route.state === "idle" || route.state === "busy" || route.state === "awaiting_approval");
|
|
1485
|
+
function sameEdge(edge, aliases) {
|
|
1486
|
+
const actual = edge.endpoints.map(({ alias }) => alias);
|
|
1487
|
+
return aliases.every((alias) => actual.includes(alias));
|
|
1670
1488
|
}
|
|
1671
|
-
function
|
|
1672
|
-
const t = Embassy.useT();
|
|
1673
|
-
return (React.createElement("span", { className: "lower-bound" }, t("app.lowerBound", { count: props.count })));
|
|
1674
|
-
}
|
|
1675
|
-
function AccordionRow(props) {
|
|
1676
|
-
const t = Embassy.useT();
|
|
1677
|
-
const baseId = React.useId();
|
|
1678
|
-
const buttonId = `${baseId}-summary`;
|
|
1679
|
-
const panelId = `${baseId}-panel`;
|
|
1680
|
-
return (React.createElement("div", { className: "accordion" },
|
|
1681
|
-
React.createElement("button", { type: "button", id: buttonId, className: "accordion__row", "aria-label": t(props.open
|
|
1682
|
-
? "app.routes.collapseDetails"
|
|
1683
|
-
: "app.routes.expandDetails", { alias: props.alias }), "aria-expanded": props.open, "aria-controls": props.open ? panelId : undefined, onClick: props.onToggle },
|
|
1684
|
-
React.createElement("span", { className: "accordion__alias" }, props.alias),
|
|
1685
|
-
props.head,
|
|
1686
|
-
React.createElement("span", { className: "accordion__marker", "aria-hidden": "true" }, props.open ? "−" : "+")),
|
|
1687
|
-
props.open ? (React.createElement("div", { className: "accordion__panel", id: panelId, role: "region", "aria-labelledby": buttonId },
|
|
1688
|
-
React.createElement("div", { className: "detail-list" }, props.children))) : null));
|
|
1689
|
-
}
|
|
1690
|
-
function PeerAccordionRow(props) {
|
|
1691
|
-
const t = Embassy.useT();
|
|
1692
|
-
const peer = props.peer;
|
|
1693
|
-
const selectionLabel = peer.selected
|
|
1694
|
-
? t("status.selected")
|
|
1695
|
-
: peer.selectable
|
|
1696
|
-
? t("status.available")
|
|
1697
|
-
: t("status.notSelectable");
|
|
1698
|
-
return (React.createElement(AccordionRow, { alias: peer.alias, open: props.open, onToggle: props.onToggle, head: React.createElement(React.Fragment, null,
|
|
1699
|
-
peer.selected ? (React.createElement("span", { className: "status-dot", title: t("status.selected"), "aria-hidden": "true" })) : null,
|
|
1700
|
-
React.createElement(Embassy.StateChip, { domain: "peer", state: peer.state, small: true }),
|
|
1701
|
-
peer.selected ? (React.createElement("span", { className: "chip chip--small", "data-kind": "positive" }, selectionLabel)) : null) },
|
|
1702
|
-
React.createElement(DetailRow, { label: t("column.state") },
|
|
1703
|
-
React.createElement(Embassy.StateChip, { domain: "peer", state: peer.state, small: true })),
|
|
1704
|
-
React.createElement(DetailRow, { label: t("column.compatibility") },
|
|
1705
|
-
React.createElement(Embassy.StateChip, { domain: "compatibility", state: peer.compatibility, small: true })),
|
|
1706
|
-
React.createElement(DetailRow, { label: t("column.validation") },
|
|
1707
|
-
React.createElement("span", { className: "chip chip--small", "data-kind": peer.validated ? "positive" : "warning" }, t(peer.validated
|
|
1708
|
-
? "status.validated"
|
|
1709
|
-
: "status.validationRejected"))),
|
|
1710
|
-
React.createElement(DetailRow, { label: t("column.selection") },
|
|
1711
|
-
React.createElement("span", { className: "chip chip--small", "data-kind": peer.selected ? "positive" : "inert" }, selectionLabel)),
|
|
1712
|
-
peer.selectionGuidance === undefined ? null : (React.createElement("p", { className: "detail-row" }, t(`peer.reason.${Embassy.camelCaseToken(peer.selectionGuidance)}`))),
|
|
1713
|
-
React.createElement(DetailRow, { label: t("column.host") },
|
|
1714
|
-
React.createElement("span", { className: "detail-value detail-value--mono" }, peer.host)),
|
|
1715
|
-
React.createElement(DetailRow, { label: t("column.observed") }, peer.lastSeenAt === undefined ? (t("time.unavailable")) : (React.createElement(Embassy.TimeAgo, { iso: peer.lastSeenAt }))),
|
|
1716
|
-
peer.safeErrorCode === undefined ? null : (React.createElement(DetailRow, { label: t("column.issue") },
|
|
1717
|
-
React.createElement("span", { className: "detail-value detail-value--mono" }, peer.safeErrorCode))),
|
|
1718
|
-
React.createElement(AbsentDetail, { fields: ["binding", "renames", "discovery"] }),
|
|
1719
|
-
peer.selected || peer.selectable
|
|
1720
|
-
? props.codexRoutes.map((view) => {
|
|
1721
|
-
const codexAlias = view.route.alias;
|
|
1722
|
-
const paired = props.pairs.some((pair) => pair.claudeAlias === peer.alias &&
|
|
1723
|
-
pair.codexAlias === codexAlias);
|
|
1724
|
-
return (React.createElement(ActionControl, { key: codexAlias, action: {
|
|
1725
|
-
action: paired ? "unpair" : "pair",
|
|
1726
|
-
claudeAlias: peer.alias,
|
|
1727
|
-
codexAlias,
|
|
1728
|
-
}, consequence: t(paired
|
|
1729
|
-
? "app.routes.unpairCmd.consequence"
|
|
1730
|
-
: "app.routes.pairCmd.consequence", { claude: peer.alias, codex: codexAlias }), enabled: props.actionsEnabled, onAction: props.onAction }));
|
|
1731
|
-
})
|
|
1732
|
-
: null));
|
|
1733
|
-
}
|
|
1734
|
-
function RouteCountersTable(props) {
|
|
1735
|
-
const t = Embassy.useT();
|
|
1736
|
-
const [locale] = Embassy.useLocale();
|
|
1737
|
-
return (React.createElement("details", { className: "details-block" },
|
|
1738
|
-
React.createElement("summary", null, t("app.routes.counters")),
|
|
1739
|
-
React.createElement("div", { className: "details-block__content" },
|
|
1740
|
-
React.createElement("div", { className: "table-wrap" },
|
|
1741
|
-
React.createElement("table", { className: "data-table" },
|
|
1742
|
-
React.createElement("caption", { className: "table-caption" }, `${t("app.routes.counters")} — ${props.alias}`),
|
|
1743
|
-
React.createElement("tbody", null, ROUTE_COUNTER_ROWS.map(([field, copyKey]) => (React.createElement("tr", { key: field },
|
|
1744
|
-
React.createElement("th", { scope: "row" }, t(copyKey)),
|
|
1745
|
-
React.createElement("td", { className: "cell-mono" }, formatCount(props.counters[field], locale)))))))))));
|
|
1746
|
-
}
|
|
1747
|
-
function CodexAccordionRow(props) {
|
|
1748
|
-
const t = Embassy.useT();
|
|
1749
|
-
const [locale] = Embassy.useLocale();
|
|
1750
|
-
const route = props.view.route;
|
|
1751
|
-
return (React.createElement(AccordionRow, { alias: route.alias, open: props.open, onToggle: props.onToggle, head: React.createElement(React.Fragment, null,
|
|
1752
|
-
React.createElement("span", { className: "status-dot", title: t("app.routes.registered"), "aria-hidden": "true" }),
|
|
1753
|
-
React.createElement(Embassy.StateChip, { domain: "route", state: route.state, small: true }),
|
|
1754
|
-
props.view.monitorOnly ? (React.createElement("span", { className: "chip chip--small", "data-kind": "warning" }, t("app.routes.monitorOnly"))) : null) },
|
|
1755
|
-
React.createElement(DetailRow, { label: t("column.state") },
|
|
1756
|
-
React.createElement(Embassy.StateChip, { domain: "route", state: route.state, small: true })),
|
|
1757
|
-
React.createElement(DetailRow, { label: t("column.compatibility") },
|
|
1758
|
-
React.createElement(Embassy.StateChip, { domain: "compatibility", state: route.compatibility, small: true })),
|
|
1759
|
-
React.createElement(DetailRow, { label: t("column.selection") },
|
|
1760
|
-
React.createElement("span", { className: "chip chip--small", "data-kind": route.enabled ? "positive" : "inert" }, route.enabled ? t("status.enabled") : t("status.disabled"))),
|
|
1761
|
-
React.createElement(DetailRow, { label: t("app.routes.queueDepth") },
|
|
1762
|
-
React.createElement("span", { className: "detail-value detail-value--mono" }, formatCount(route.queueDepth, locale))),
|
|
1763
|
-
props.view.oldestAgeMs === undefined ? null : (React.createElement(DetailRow, { label: t("app.overview.oldest") },
|
|
1764
|
-
React.createElement("span", { className: "detail-value detail-value--mono" }, Embassy.fmtAge(props.view.oldestAgeMs)))),
|
|
1765
|
-
props.view.monitorOnly ? (React.createElement("p", { className: "detail-row" }, t("app.routes.monitorOnlyReason"))) : null,
|
|
1766
|
-
React.createElement(DetailRow, { label: t("column.host") },
|
|
1767
|
-
React.createElement("span", { className: "detail-value detail-value--mono" }, route.host)),
|
|
1768
|
-
React.createElement(DetailRow, { label: t("column.observed") }, route.lastSeenAt === undefined ? (t("time.unavailable")) : (React.createElement(Embassy.TimeAgo, { iso: route.lastSeenAt }))),
|
|
1769
|
-
route.safeErrorCode === undefined ? null : (React.createElement(DetailRow, { label: t("column.issue") },
|
|
1770
|
-
React.createElement("span", { className: "detail-value detail-value--mono" }, route.safeErrorCode))),
|
|
1771
|
-
React.createElement(AbsentDetail, { fields: ["policy", "identity lock", "registered"] }),
|
|
1772
|
-
React.createElement(RouteCountersTable, { alias: route.alias, counters: route.counters }),
|
|
1773
|
-
canRequestStaleCodexRegistrationRemoval(route) ? (React.createElement(ActionControl, { action: {
|
|
1774
|
-
action: "remove_stale_codex_registration",
|
|
1775
|
-
alias: route.alias,
|
|
1776
|
-
}, consequence: t("app.routes.removeStaleCodex.consequence", {
|
|
1777
|
-
alias: route.alias,
|
|
1778
|
-
}), enabled: props.actionsEnabled, onAction: props.onAction })) : null));
|
|
1779
|
-
}
|
|
1780
|
-
function successionScope(item, t) {
|
|
1781
|
-
const parts = [];
|
|
1782
|
-
if (item.provider !== undefined)
|
|
1783
|
-
parts.push(t(`provider.${item.provider}`));
|
|
1784
|
-
if (item.alias !== undefined)
|
|
1785
|
-
parts.push(item.alias);
|
|
1786
|
-
if (item.host !== undefined)
|
|
1787
|
-
parts.push(item.host);
|
|
1788
|
-
if (item.code !== undefined)
|
|
1789
|
-
parts.push(item.code);
|
|
1790
|
-
return parts.join(" · ");
|
|
1791
|
-
}
|
|
1792
|
-
function SuccessionCard(props) {
|
|
1793
|
-
const t = Embassy.useT();
|
|
1794
|
-
const item = props.view.item;
|
|
1795
|
-
const scope = successionScope(item, t);
|
|
1796
|
-
return (React.createElement("article", { className: "succession-card" },
|
|
1797
|
-
React.createElement("div", { className: "succession-card__head" },
|
|
1798
|
-
React.createElement("div", { className: "chip-row" },
|
|
1799
|
-
React.createElement(Embassy.MonoLabel, null, "succession"),
|
|
1800
|
-
React.createElement(Embassy.StateChip, { domain: "severity", state: item.severity, small: true })),
|
|
1801
|
-
item.timestamp === undefined ? null : (React.createElement(Embassy.TimeAgo, { iso: item.timestamp }))),
|
|
1802
|
-
React.createElement("h3", { className: "card__title succession-card__title" }, t(`guidance.${props.view.guidanceKey}.title`)),
|
|
1803
|
-
React.createElement("p", { className: "card__body" }, t(`guidance.${props.view.guidanceKey}.body`)),
|
|
1804
|
-
scope === "" ? null : (React.createElement("p", { className: "attention-item__scope" },
|
|
1805
|
-
t("attention.scope"),
|
|
1806
|
-
": ",
|
|
1807
|
-
scope)),
|
|
1808
|
-
React.createElement("p", { className: "card__body" }, t(`guidance.${props.view.guidanceKey}.action`)),
|
|
1809
|
-
React.createElement(AbsentDetail, { fields: ["predecessor", "successor", "drain outcome"] }),
|
|
1810
|
-
React.createElement("p", { className: "succession-note" }, t("app.routes.successions.note")),
|
|
1811
|
-
React.createElement(Embassy.CopyCmd, { cmd: props.view.command })));
|
|
1812
|
-
}
|
|
1813
|
-
function actionLabelKey(action) {
|
|
1814
|
-
switch (action.action) {
|
|
1815
|
-
case "pair":
|
|
1816
|
-
return "live.action.pair";
|
|
1817
|
-
case "unpair":
|
|
1818
|
-
return "live.action.unpair";
|
|
1819
|
-
case "remove_stale_codex_registration":
|
|
1820
|
-
return "live.action.removeStaleCodexRegistration";
|
|
1821
|
-
case "refresh_dashboard":
|
|
1822
|
-
return "live.action.refresh";
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
function ActionControl(props) {
|
|
1489
|
+
function ActionButton(props) {
|
|
1826
1490
|
const t = Embassy.useT();
|
|
1827
1491
|
const [confirming, setConfirming] = React.useState(false);
|
|
1828
1492
|
const [pending, setPending] = React.useState(false);
|
|
1829
|
-
const [result, setResult] = React.useState(
|
|
1830
|
-
const
|
|
1831
|
-
switch (props.action.action) {
|
|
1832
|
-
case "refresh_dashboard":
|
|
1833
|
-
return props.action.action;
|
|
1834
|
-
case "remove_stale_codex_registration":
|
|
1835
|
-
return `${props.action.action}:${props.action.alias}`;
|
|
1836
|
-
case "pair":
|
|
1837
|
-
case "unpair":
|
|
1838
|
-
return `${props.action.action}:${props.action.claudeAlias}:${props.action.codexAlias}`;
|
|
1839
|
-
}
|
|
1840
|
-
})();
|
|
1841
|
-
React.useEffect(() => {
|
|
1842
|
-
setConfirming(false);
|
|
1843
|
-
setPending(false);
|
|
1844
|
-
setResult(undefined);
|
|
1845
|
-
}, [actionIdentity]);
|
|
1846
|
-
const baseLabel = t(actionLabelKey(props.action));
|
|
1847
|
-
const label = (() => {
|
|
1848
|
-
switch (props.action.action) {
|
|
1849
|
-
case "refresh_dashboard":
|
|
1850
|
-
return baseLabel;
|
|
1851
|
-
case "remove_stale_codex_registration":
|
|
1852
|
-
return `${baseLabel}: ${props.action.alias}`;
|
|
1853
|
-
case "pair":
|
|
1854
|
-
case "unpair":
|
|
1855
|
-
return `${baseLabel}: ${props.action.claudeAlias} ↔ ${props.action.codexAlias}`;
|
|
1856
|
-
}
|
|
1857
|
-
})();
|
|
1858
|
-
const confirm = async () => {
|
|
1859
|
-
if (!props.enabled || pending)
|
|
1860
|
-
return;
|
|
1493
|
+
const [result, setResult] = React.useState();
|
|
1494
|
+
const run = () => {
|
|
1861
1495
|
setPending(true);
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1496
|
+
props.onAction(props.action).then((next) => {
|
|
1497
|
+
setResult(next);
|
|
1498
|
+
setPending(false);
|
|
1499
|
+
setConfirming(false);
|
|
1500
|
+
});
|
|
1867
1501
|
};
|
|
1868
|
-
|
|
1869
|
-
React.createElement("
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
})))
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
React.createElement("button", { type: "button", className: "btn btn--ghost", disabled: pending, onClick: () => {
|
|
1880
|
-
setConfirming(false);
|
|
1881
|
-
} }, t("live.action.cancel")))) : (React.createElement("button", { type: "button", className: "btn btn--ghost", disabled: !props.enabled, onClick: () => {
|
|
1882
|
-
setResult(undefined);
|
|
1883
|
-
setConfirming(true);
|
|
1884
|
-
} }, label))));
|
|
1502
|
+
if (confirming)
|
|
1503
|
+
return React.createElement("span", { className: "row-baseline" },
|
|
1504
|
+
React.createElement("button", { type: "button", disabled: pending, onClick: run }, pending ? t("live.action.pending") : t("live.action.confirm")),
|
|
1505
|
+
React.createElement("button", { type: "button", disabled: pending, onClick: () => { setConfirming(false); } }, t("live.action.cancel")));
|
|
1506
|
+
return React.createElement("span", { className: "stack-sm" },
|
|
1507
|
+
React.createElement("button", { type: "button", disabled: !props.enabled, onClick: () => { setResult(undefined); setConfirming(true); } }, props.label),
|
|
1508
|
+
result === undefined ? null : React.createElement("span", { className: "footnote" }, t(result.ok ? "live.action.succeeded" : "live.action.failed", { code: result.code })));
|
|
1509
|
+
}
|
|
1510
|
+
function edgeLabel(edge, t) {
|
|
1511
|
+
const labels = edge.endpoints.map(({ provider, alias }) => t("app.routes.consentEndpoint", { provider: t(`provider.${provider}`), alias }));
|
|
1512
|
+
return t("app.routes.consentEdge", { left: labels[0] ?? "", right: labels[1] ?? "" });
|
|
1885
1513
|
}
|
|
1886
1514
|
function RoutesTab(props) {
|
|
1887
1515
|
const t = Embassy.useT();
|
|
1888
|
-
const data = props
|
|
1889
|
-
const
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
:
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
alias: view.route.alias,
|
|
1909
|
-
candidate: !data.pairs.some((pair) => pair.codexAlias === view.route.alias),
|
|
1910
|
-
srLabel: t(`route.${Embassy.camelCaseToken(view.route.state)}`),
|
|
1911
|
-
}));
|
|
1912
|
-
return (React.createElement("div", { className: "tab-panel" },
|
|
1913
|
-
React.createElement("section", { className: "section", "aria-label": t("app.routes.topology") },
|
|
1914
|
-
React.createElement(Embassy.MonoLabel, { className: "section-label" }, t("app.routes.topology")),
|
|
1915
|
-
React.createElement("div", { className: "inbound-policy", "data-inbound-mode": data.inboundMode },
|
|
1916
|
-
React.createElement("span", { className: "chip chip--small", "data-kind": openInbound ? "warning" : "inert" }, t(openInbound
|
|
1917
|
-
? "inbound.open.badge"
|
|
1918
|
-
: "inbound.paired.badge")),
|
|
1919
|
-
React.createElement("p", null, t(openInbound
|
|
1920
|
-
? "inbound.open.body"
|
|
1921
|
-
: hasPair
|
|
1922
|
-
? "inbound.paired.body"
|
|
1923
|
-
: "inbound.noPair.body"))),
|
|
1924
|
-
React.createElement("div", { className: "topology" },
|
|
1925
|
-
React.createElement("div", { className: "topology__heads" },
|
|
1926
|
-
React.createElement(Embassy.MonoLabel, { className: "topology__head--claude" }, t("provider.claude")),
|
|
1927
|
-
React.createElement(Embassy.MonoLabel, { className: "topology__head--codex" }, t("provider.codex"))),
|
|
1928
|
-
React.createElement("div", { className: "topology__cols" },
|
|
1929
|
-
React.createElement(TopologyColumn, { side: "claude", items: claudeItems, listLabel: t("app.routes.candidates"), emptyText: t("app.routes.noPeers"), highlightAt: highlightAt, onFocusChange: setFocus }),
|
|
1930
|
-
React.createElement(TopologyEdgeSvg, { rows: Math.max(claudeItems.length, codexItems.length), edges: edges, focus: focus, focusSide: focus === undefined ? undefined : focus.side }),
|
|
1931
|
-
React.createElement(TopologyColumn, { side: "codex", items: codexItems, listLabel: t("app.routes.codexRoutes"), emptyText: t("app.routes.noCodex"), highlightAt: highlightAt, onFocusChange: setFocus })),
|
|
1932
|
-
!hasPair ? (React.createElement("p", { className: "topology__empty" }, t(openInbound
|
|
1933
|
-
? "inbound.open.body"
|
|
1934
|
-
: "app.routes.noPairInline"))) : (React.createElement("ul", { className: "topology__edge-list", "aria-label": t("app.routes.pairs") }, data.pairs.map((pair) => (React.createElement("li", { key: `${pair.claudeAlias}\0${pair.codexAlias}` },
|
|
1935
|
-
t("app.routes.pairDescription", {
|
|
1936
|
-
claude: pair.claudeAlias,
|
|
1937
|
-
codex: pair.codexAlias,
|
|
1938
|
-
}),
|
|
1516
|
+
const { data } = props;
|
|
1517
|
+
const candidates = [];
|
|
1518
|
+
for (let left = 0; left < data.routes.length; left += 1) {
|
|
1519
|
+
for (let right = left + 1; right < data.routes.length; right += 1) {
|
|
1520
|
+
const a = data.routes[left]?.route;
|
|
1521
|
+
const b = data.routes[right]?.route;
|
|
1522
|
+
if (a === undefined || b === undefined || !Embassy.canOfferConsentEdgeCandidate(a) || !Embassy.canOfferConsentEdgeCandidate(b) || a.provider === b.provider || a.host !== b.host)
|
|
1523
|
+
continue;
|
|
1524
|
+
if (!data.consentEdges.some((edge) => sameEdge(edge, [a.alias, b.alias])))
|
|
1525
|
+
candidates.push([a, b]);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
return React.createElement("div", { className: "tab-panel" },
|
|
1529
|
+
React.createElement("section", { className: "section" },
|
|
1530
|
+
React.createElement("h2", { className: "mono-label section-label" }, t("app.routes.topology")),
|
|
1531
|
+
React.createElement("p", null, t("app.routes.pairSummary", { ready: data.graph.readyConsentEdgeCount, total: data.graph.consentEdgeCount })),
|
|
1532
|
+
React.createElement("ul", { className: "pair-list" }, data.consentEdges.map((edge) => {
|
|
1533
|
+
const aliases = edge.endpoints.map(({ alias }) => alias);
|
|
1534
|
+
return React.createElement("li", { key: aliases.join("\0") },
|
|
1535
|
+
React.createElement("code", null, edgeLabel(edge, t)),
|
|
1939
1536
|
" ",
|
|
1940
|
-
React.createElement(Embassy.StateChip, { domain: "route", state:
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
React.createElement(Embassy.
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
React.createElement("div", { className: "row-baseline row-baseline--split section-label" },
|
|
1970
|
-
React.createElement(Embassy.MonoLabel, null, t("app.routes.codexRoutes")),
|
|
1971
|
-
data.routesOmitted > 0 ? (React.createElement(LowerBoundBadge, { count: data.codexRoutes.length })) : null),
|
|
1972
|
-
data.codexRoutes.length === 0 ? (React.createElement("div", { className: "empty-state" },
|
|
1973
|
-
React.createElement("p", { className: "empty-state__text" }, t("app.routes.noCodex")))) : (React.createElement("div", null, data.codexRoutes.map((view, index) => {
|
|
1974
|
-
const identity = rowIdentity(view.route.alias, view.route.host);
|
|
1975
|
-
return (React.createElement(CodexAccordionRow, { key: `${identity}|${index}`, view: view, open: openRoute === identity, actionsEnabled: props.actionsEnabled, onAction: props.onAction, onToggle: () => {
|
|
1976
|
-
setOpenRoute(openRoute === identity ? undefined : identity);
|
|
1977
|
-
} }));
|
|
1978
|
-
}))),
|
|
1979
|
-
React.createElement(Embassy.Rule, null),
|
|
1980
|
-
React.createElement("div", { className: "stack routes-register" },
|
|
1981
|
-
React.createElement("p", { className: "text-xs text-body-muted" }, t("app.routes.registerHint")),
|
|
1982
|
-
React.createElement(Embassy.CopyCmd, { cmd: REGISTER_CODEX_COMMAND }))),
|
|
1983
|
-
React.createElement("section", { className: "section", "aria-label": t("app.routes.successions") },
|
|
1984
|
-
React.createElement(Embassy.MonoLabel, { className: "section-label" }, t("app.routes.successions")),
|
|
1985
|
-
data.successions.length === 0 ? (React.createElement("div", { className: "empty-state" },
|
|
1986
|
-
React.createElement("p", { className: "empty-state__text" }, t("app.routes.successions.empty")),
|
|
1987
|
-
React.createElement("p", { className: "succession-note" }, t("app.routes.successions.note")),
|
|
1988
|
-
React.createElement(Embassy.CopyCmd, { cmd: SUCCEEDS_COMMAND }))) : (React.createElement("div", { className: "stack-lg" }, data.successions.map((view, index) => (React.createElement(SuccessionCard, { key: `${view.guidanceKey}|${view.item.alias ?? ""}|${index}`, view: view }))))))));
|
|
1537
|
+
React.createElement(Embassy.StateChip, { domain: "route", state: edge.state === "ready" ? "idle" : "stale", small: true }),
|
|
1538
|
+
React.createElement(ActionButton, { action: { action: "unpair", aliases }, label: t("live.action.unpair"), enabled: props.actionsEnabled, onAction: props.onAction }));
|
|
1539
|
+
})),
|
|
1540
|
+
data.consentEdgesOmitted > 0 ? React.createElement("p", { className: "footnote" }, t("app.omitted.pairs", { count: data.consentEdgesOmitted })) : null),
|
|
1541
|
+
Embassy.GATEWAY_PROVIDERS.map((provider) => {
|
|
1542
|
+
const routes = data.routes.filter((view) => view.route.provider === provider);
|
|
1543
|
+
return React.createElement("section", { className: "section", key: provider, "aria-label": t(`provider.${provider}`) },
|
|
1544
|
+
React.createElement("h2", { className: "mono-label section-label" }, t(`provider.${provider}`)),
|
|
1545
|
+
React.createElement("ul", null, routes.map(({ route, oldestAgeMs }) => React.createElement("li", { key: `${route.alias}\0${route.host}` },
|
|
1546
|
+
React.createElement("code", null, route.alias),
|
|
1547
|
+
" \u00B7 ",
|
|
1548
|
+
React.createElement(Embassy.StateChip, { domain: "route", state: route.state, small: true }),
|
|
1549
|
+
" \u00B7 ",
|
|
1550
|
+
t("app.routes.queueDepth"),
|
|
1551
|
+
": ",
|
|
1552
|
+
route.queueDepth,
|
|
1553
|
+
oldestAgeMs === undefined ? "" : ` · ${Embassy.fmtAge(oldestAgeMs)}`,
|
|
1554
|
+
canRequestStaleCodexRegistrationRemoval(route) ? React.createElement(ActionButton, { action: { action: "remove_stale_codex_registration", alias: route.alias }, label: t("live.action.removeStaleCodexRegistration"), enabled: props.actionsEnabled, onAction: props.onAction }) : null))),
|
|
1555
|
+
React.createElement("p", { className: "footnote" }, t("app.routes.unpairedProvider", { provider: t(`provider.${provider}`), count: data.graph.unpairedReadyByProvider[provider] })));
|
|
1556
|
+
}),
|
|
1557
|
+
React.createElement("section", { className: "section" },
|
|
1558
|
+
React.createElement("h2", { className: "mono-label section-label" }, t("app.routes.candidates")),
|
|
1559
|
+
React.createElement("ul", null, candidates.map(([left, right]) => React.createElement("li", { key: `${left.alias}\0${right.alias}` },
|
|
1560
|
+
React.createElement("code", null,
|
|
1561
|
+
left.alias,
|
|
1562
|
+
" \u2194 ",
|
|
1563
|
+
right.alias),
|
|
1564
|
+
React.createElement(ActionButton, { action: { action: "pair", aliases: [left.alias, right.alias] }, label: t("live.action.pair"), enabled: props.actionsEnabled, onAction: props.onAction })))),
|
|
1565
|
+
React.createElement(ActionButton, { action: { action: "refresh_dashboard" }, label: t("live.action.refresh"), enabled: props.actionsEnabled, onAction: props.onAction })));
|
|
1989
1566
|
}
|
|
1990
1567
|
Embassy.RoutesTab = RoutesTab;
|
|
1991
1568
|
})(Embassy || (Embassy = {}));
|
|
@@ -2078,7 +1655,7 @@ var Embassy;
|
|
|
2078
1655
|
function alertScope(item, t) {
|
|
2079
1656
|
const parts = [];
|
|
2080
1657
|
if (item.provider !== undefined) {
|
|
2081
|
-
parts.push(t(item.provider
|
|
1658
|
+
parts.push(t(`provider.${item.provider}`));
|
|
2082
1659
|
}
|
|
2083
1660
|
if (item.alias !== undefined)
|
|
2084
1661
|
parts.push(item.alias);
|
|
@@ -2235,7 +1812,7 @@ var Embassy;
|
|
|
2235
1812
|
React.createElement("th", { scope: "col" }, t("app.diag.col.protocol")),
|
|
2236
1813
|
React.createElement("th", { scope: "col" }, t("app.diag.col.version")),
|
|
2237
1814
|
React.createElement("th", { scope: "col" }, t("diagnostics.health")),
|
|
2238
|
-
React.createElement("th", { scope: "col" }, t("
|
|
1815
|
+
React.createElement("th", { scope: "col" }, t("column.observed")),
|
|
2239
1816
|
React.createElement("th", { scope: "col" }, t("diagnostics.registry.title")),
|
|
2240
1817
|
React.createElement("th", { scope: "col" }, t("column.issue")))),
|
|
2241
1818
|
React.createElement("tbody", null, connectors.length === 0 ? (React.createElement("tr", null,
|
|
@@ -2249,16 +1826,13 @@ var Embassy;
|
|
|
2249
1826
|
? "diagnostics.registry.state.emptySinceBoot"
|
|
2250
1827
|
: "diagnostics.registry.state.noParseableRecordSinceBoot";
|
|
2251
1828
|
return (React.createElement("tr", { key: `${connector.provider}|${connector.host}|${index}` },
|
|
2252
|
-
React.createElement("th", { scope: "row" }, connector.provider
|
|
2253
|
-
? t("provider.claude")
|
|
2254
|
-
: t("provider.codex")),
|
|
1829
|
+
React.createElement("th", { scope: "row" }, t(`provider.${connector.provider}`)),
|
|
2255
1830
|
React.createElement("td", { className: "cell-mono" }, connector.host),
|
|
2256
1831
|
React.createElement("td", { className: "cell-mono" }, connector.protocol ?? DIAGNOSTICS_ABSENT_FIELD),
|
|
2257
1832
|
React.createElement("td", { className: "cell-mono" }, connector.protocolVersion ?? DIAGNOSTICS_ABSENT_FIELD),
|
|
2258
1833
|
React.createElement("td", null,
|
|
2259
1834
|
React.createElement(Embassy.StateChip, { domain: "health", state: connector.health, small: true })),
|
|
2260
|
-
React.createElement("td", null,
|
|
2261
|
-
React.createElement(Embassy.StateChip, { domain: "compatibility", state: connector.compatibility, small: true })),
|
|
1835
|
+
React.createElement("td", null, connector.lastSeenAt === undefined ? (DIAGNOSTICS_ABSENT_FIELD) : (React.createElement(Embassy.TimeAgo, { iso: connector.lastSeenAt }))),
|
|
2262
1836
|
React.createElement("td", null, observation === undefined || stateKey === undefined ? (DIAGNOSTICS_ABSENT_FIELD) : (React.createElement("div", { className: "stack-sm" },
|
|
2263
1837
|
React.createElement("span", null, t(stateKey)),
|
|
2264
1838
|
React.createElement("span", { className: "cell-note" },
|
|
@@ -2282,39 +1856,16 @@ var Embassy;
|
|
|
2282
1856
|
observation.rejectedCodesOmitted === 0 ? null : (React.createElement("span", { className: "cell-note" }, t("diagnostics.registry.rejectedCodesOmitted", {
|
|
2283
1857
|
count: formatDiagnosticsCount(observation.rejectedCodesOmitted, locale),
|
|
2284
1858
|
})))))),
|
|
2285
|
-
React.createElement("td", { className: "cell-mono" }, connector.safeErrorCode
|
|
1859
|
+
React.createElement("td", { className: "cell-mono" }, connector.safeErrorCode === undefined &&
|
|
1860
|
+
connector.codexDoctor === undefined
|
|
1861
|
+
? DIAGNOSTICS_ABSENT_FIELD
|
|
1862
|
+
: (React.createElement("div", { className: "stack-sm" },
|
|
1863
|
+
connector.safeErrorCode === undefined
|
|
1864
|
+
? null
|
|
1865
|
+
: React.createElement("code", null, connector.safeErrorCode),
|
|
1866
|
+
connector.codexDoctor?.conditions.map((condition) => (React.createElement("span", { key: condition, className: "cell-note" }, t(`diagnostics.codexDoctor.${condition}`)))))))));
|
|
2286
1867
|
}))))));
|
|
2287
1868
|
}
|
|
2288
|
-
function DiagnosticsCompatibilityTable(props) {
|
|
2289
|
-
const t = Embassy.useT();
|
|
2290
|
-
return (React.createElement("div", { className: "table-wrap" },
|
|
2291
|
-
React.createElement("table", { className: "data-table" },
|
|
2292
|
-
React.createElement("caption", { className: "sr-only" }, t("diagnostics.compatibilityChecks.caption")),
|
|
2293
|
-
React.createElement("thead", null,
|
|
2294
|
-
React.createElement("tr", null,
|
|
2295
|
-
React.createElement("th", { scope: "col" }, t("app.diag.col.provider")),
|
|
2296
|
-
React.createElement("th", { scope: "col" }, t("diagnostics.version")),
|
|
2297
|
-
React.createElement("th", { scope: "col" }, t("diagnostics.testedVersion")),
|
|
2298
|
-
React.createElement("th", { scope: "col" }, t("diagnostics.supportedMajor")),
|
|
2299
|
-
React.createElement("th", { scope: "col" }, t("diagnostics.tier")),
|
|
2300
|
-
React.createElement("th", { scope: "col" }, t("diagnostics.checkedAt")),
|
|
2301
|
-
React.createElement("th", { scope: "col" }, t("diagnostics.failure")),
|
|
2302
|
-
React.createElement("th", { scope: "col" }, t("column.issue")))),
|
|
2303
|
-
React.createElement("tbody", null, props.checks.length === 0 ? (React.createElement("tr", null,
|
|
2304
|
-
React.createElement("td", { colSpan: 8 }, t("diagnostics.compatibilityChecks.empty")))) : (props.checks.map((check) => (React.createElement("tr", { key: check.surface },
|
|
2305
|
-
React.createElement("th", { scope: "row" }, t(`provider.${check.surface}`)),
|
|
2306
|
-
"notDetected" in check ? (React.createElement("td", { colSpan: 7 }, t("compatibilityTier.notDetected"))) : (React.createElement(React.Fragment, null,
|
|
2307
|
-
React.createElement("td", { className: "cell-mono" }, check.version),
|
|
2308
|
-
React.createElement("td", { className: "cell-mono" }, check.testedVersion ?? DIAGNOSTICS_ABSENT_FIELD),
|
|
2309
|
-
React.createElement("td", { className: "cell-mono" }, check.supportedMajor ?? DIAGNOSTICS_ABSENT_FIELD),
|
|
2310
|
-
React.createElement("td", null, t(check.tier === "schema_attested" && check.writesCovered
|
|
2311
|
-
? "compatibilityTier.schema_attested.writesCovered"
|
|
2312
|
-
: `compatibilityTier.${check.tier}`)),
|
|
2313
|
-
React.createElement("td", null,
|
|
2314
|
-
React.createElement(Embassy.TimeAgo, { iso: check.checkedAt })),
|
|
2315
|
-
React.createElement("td", { className: "cell-mono" }, check.failure ?? DIAGNOSTICS_ABSENT_FIELD),
|
|
2316
|
-
React.createElement("td", { className: "cell-mono" }, check.safeErrorCode ?? DIAGNOSTICS_ABSENT_FIELD)))))))))));
|
|
2317
|
-
}
|
|
2318
1869
|
function DiagnosticsCounterTable(props) {
|
|
2319
1870
|
return (React.createElement("div", { className: "table-wrap counters-list" },
|
|
2320
1871
|
React.createElement("table", { className: "data-table data-table--counters" },
|
|
@@ -2457,6 +2008,12 @@ var Embassy;
|
|
|
2457
2008
|
count: formatDiagnosticsCount(omissions.routes, locale),
|
|
2458
2009
|
}),
|
|
2459
2010
|
},
|
|
2011
|
+
{
|
|
2012
|
+
field: "consentEdges",
|
|
2013
|
+
text: t("diagnostics.omissions.consentEdges", {
|
|
2014
|
+
count: formatDiagnosticsCount(omissions.consentEdges, locale),
|
|
2015
|
+
}),
|
|
2016
|
+
},
|
|
2460
2017
|
{
|
|
2461
2018
|
field: "upstreamMessageEvents",
|
|
2462
2019
|
text: t("diagnostics.omissions.upstreamMessageEvents", {
|
|
@@ -2491,6 +2048,7 @@ var Embassy;
|
|
|
2491
2048
|
const nothingOmitted = omissions.connectors === 0 &&
|
|
2492
2049
|
omissions.availablePeers === 0 &&
|
|
2493
2050
|
omissions.routes === 0 &&
|
|
2051
|
+
omissions.consentEdges === 0 &&
|
|
2494
2052
|
omissions.upstreamMessageEvents === 0 &&
|
|
2495
2053
|
omissions.messageGroups === 0 &&
|
|
2496
2054
|
omissions.messageEvents === 0 &&
|
|
@@ -2577,10 +2135,6 @@ var Embassy;
|
|
|
2577
2135
|
React.createElement(DiagnosticsConnectorTable, { connectors: data.connectors }),
|
|
2578
2136
|
React.createElement("p", { className: "footnote" }, t("app.diag.versions.rangeAbsent")))),
|
|
2579
2137
|
React.createElement("div", { className: "grid-2" },
|
|
2580
|
-
React.createElement("section", { className: "card", "aria-labelledby": "provider-compatibility-title" },
|
|
2581
|
-
React.createElement("div", { className: "card__head" },
|
|
2582
|
-
React.createElement("h3", { className: "card__title", id: "provider-compatibility-title" }, t("app.diag.providerCompatibility.title"))),
|
|
2583
|
-
React.createElement(DiagnosticsCompatibilityTable, { checks: data.compatibilityChecks })),
|
|
2584
2138
|
React.createElement(Embassy.AbsentFeature, { title: t("app.diag.lease.title"), body: t("app.diag.lease.absent"), cmd: "embassy status" })),
|
|
2585
2139
|
React.createElement("section", { className: "section", "aria-labelledby": limitsHeadingId },
|
|
2586
2140
|
React.createElement("h2", { className: "mono-label section-label", id: limitsHeadingId }, t("app.diag.limits")),
|