agent-embassy 1.6.0 → 1.7.0
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 +31 -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.en.d.ts +1 -1
- package/dist/src/gateway/cli-copy.en.js +2 -2
- package/dist/src/gateway/cli-copy.zh-CN.d.ts +1 -1
- package/dist/src/gateway/cli-copy.zh-CN.js +2 -2
- package/dist/src/gateway/cli.d.ts +1 -1
- package/dist/src/gateway/cli.js +26 -5
- 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 -597
- package/dist/src/gateway/codex-app-server.js.map +1 -1
- package/dist/src/gateway/codex-local-transport.d.ts +8 -26
- package/dist/src/gateway/codex-local-transport.js +26 -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 +89 -57
- 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 +14 -44
- package/dist/src/gateway/dashboard-copy.en.js +37 -67
- package/dist/src/gateway/dashboard-copy.en.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.js +14 -44
- package/dist/src/gateway/dashboard-copy.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +14 -44
- package/dist/src/gateway/dashboard-copy.zh-CN.js +37 -67
- package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/dashboard-model.d.ts +38 -76
- package/dist/src/gateway/dashboard-model.js +158 -256
- 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 +75 -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 +166 -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 +12 -84
- package/dist/src/gateway/providers.js +69 -806
- package/dist/src/gateway/providers.js.map +1 -1
- package/dist/src/gateway/server.d.ts +8 -9
- package/dist/src/gateway/server.js +51 -99
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +22 -49
- package/dist/src/gateway/service.js +196 -432
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/store.d.ts +20 -29
- package/dist/src/gateway/store.js +281 -827
- package/dist/src/gateway/store.js.map +1 -1
- package/dist/src/gateway/types.d.ts +55 -55
- package/dist/src/gateway/types.js +49 -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);
|
|
@@ -2188,7 +1765,7 @@ var Embassy;
|
|
|
2188
1765
|
var Embassy;
|
|
2189
1766
|
(function (Embassy) {
|
|
2190
1767
|
const DIAGNOSTICS_ABSENT_FIELD = "—";
|
|
2191
|
-
const DIAGNOSTICS_CONNECTOR_COLUMNS =
|
|
1768
|
+
const DIAGNOSTICS_CONNECTOR_COLUMNS = 7;
|
|
2192
1769
|
const diagnosticsNumberFormatters = new Map();
|
|
2193
1770
|
function diagnosticsNumberFormatter(locale) {
|
|
2194
1771
|
const existing = diagnosticsNumberFormatters.get(locale);
|
|
@@ -2235,7 +1812,6 @@ 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("app.diag.col.compat")),
|
|
2239
1815
|
React.createElement("th", { scope: "col" }, t("diagnostics.registry.title")),
|
|
2240
1816
|
React.createElement("th", { scope: "col" }, t("column.issue")))),
|
|
2241
1817
|
React.createElement("tbody", null, connectors.length === 0 ? (React.createElement("tr", null,
|
|
@@ -2249,16 +1825,12 @@ var Embassy;
|
|
|
2249
1825
|
? "diagnostics.registry.state.emptySinceBoot"
|
|
2250
1826
|
: "diagnostics.registry.state.noParseableRecordSinceBoot";
|
|
2251
1827
|
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")),
|
|
1828
|
+
React.createElement("th", { scope: "row" }, t(`provider.${connector.provider}`)),
|
|
2255
1829
|
React.createElement("td", { className: "cell-mono" }, connector.host),
|
|
2256
1830
|
React.createElement("td", { className: "cell-mono" }, connector.protocol ?? DIAGNOSTICS_ABSENT_FIELD),
|
|
2257
1831
|
React.createElement("td", { className: "cell-mono" }, connector.protocolVersion ?? DIAGNOSTICS_ABSENT_FIELD),
|
|
2258
1832
|
React.createElement("td", null,
|
|
2259
1833
|
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 })),
|
|
2262
1834
|
React.createElement("td", null, observation === undefined || stateKey === undefined ? (DIAGNOSTICS_ABSENT_FIELD) : (React.createElement("div", { className: "stack-sm" },
|
|
2263
1835
|
React.createElement("span", null, t(stateKey)),
|
|
2264
1836
|
React.createElement("span", { className: "cell-note" },
|
|
@@ -2285,36 +1857,6 @@ var Embassy;
|
|
|
2285
1857
|
React.createElement("td", { className: "cell-mono" }, connector.safeErrorCode ?? DIAGNOSTICS_ABSENT_FIELD)));
|
|
2286
1858
|
}))))));
|
|
2287
1859
|
}
|
|
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
1860
|
function DiagnosticsCounterTable(props) {
|
|
2319
1861
|
return (React.createElement("div", { className: "table-wrap counters-list" },
|
|
2320
1862
|
React.createElement("table", { className: "data-table data-table--counters" },
|
|
@@ -2457,6 +1999,12 @@ var Embassy;
|
|
|
2457
1999
|
count: formatDiagnosticsCount(omissions.routes, locale),
|
|
2458
2000
|
}),
|
|
2459
2001
|
},
|
|
2002
|
+
{
|
|
2003
|
+
field: "consentEdges",
|
|
2004
|
+
text: t("diagnostics.omissions.consentEdges", {
|
|
2005
|
+
count: formatDiagnosticsCount(omissions.consentEdges, locale),
|
|
2006
|
+
}),
|
|
2007
|
+
},
|
|
2460
2008
|
{
|
|
2461
2009
|
field: "upstreamMessageEvents",
|
|
2462
2010
|
text: t("diagnostics.omissions.upstreamMessageEvents", {
|
|
@@ -2491,6 +2039,7 @@ var Embassy;
|
|
|
2491
2039
|
const nothingOmitted = omissions.connectors === 0 &&
|
|
2492
2040
|
omissions.availablePeers === 0 &&
|
|
2493
2041
|
omissions.routes === 0 &&
|
|
2042
|
+
omissions.consentEdges === 0 &&
|
|
2494
2043
|
omissions.upstreamMessageEvents === 0 &&
|
|
2495
2044
|
omissions.messageGroups === 0 &&
|
|
2496
2045
|
omissions.messageEvents === 0 &&
|
|
@@ -2577,10 +2126,6 @@ var Embassy;
|
|
|
2577
2126
|
React.createElement(DiagnosticsConnectorTable, { connectors: data.connectors }),
|
|
2578
2127
|
React.createElement("p", { className: "footnote" }, t("app.diag.versions.rangeAbsent")))),
|
|
2579
2128
|
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
2129
|
React.createElement(Embassy.AbsentFeature, { title: t("app.diag.lease.title"), body: t("app.diag.lease.absent"), cmd: "embassy status" })),
|
|
2585
2130
|
React.createElement("section", { className: "section", "aria-labelledby": limitsHeadingId },
|
|
2586
2131
|
React.createElement("h2", { className: "mono-label section-label", id: limitsHeadingId }, t("app.diag.limits")),
|