@nelsonlongxiang/dsh-open-a2a-net 0.6.30 → 0.6.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/README_zh.md +3 -0
- package/assets/nexusDist/assets/index-D5H8R8de.js +9 -0
- package/assets/nexusDist/assets/index-D9GYZyGZ.css +1 -0
- package/assets/nexusDist/index.html +2 -2
- package/cli/a2a.mjs +445 -57
- package/lib/a2a-client.js +9 -4
- package/lib/auth-observer.js +254 -0
- package/lib/blob-store.js +210 -0
- package/lib/card.js +4 -2
- package/lib/cli-deposit.js +122 -7
- package/lib/client.js +64 -64
- package/lib/client.js.map +1 -1
- package/lib/faces/admin.js +133 -43
- package/lib/faces/canvas-notify.js +12 -3
- package/lib/faces/files.js +155 -0
- package/lib/faces/nodes.js +171 -0
- package/lib/faces/session-log.js +162 -0
- package/lib/faces/wire.js +206 -39
- package/lib/index.js +809 -1720
- package/lib/joined-store.js +23 -0
- package/lib/ledger-conservation.js +97 -0
- package/lib/legacy/teams-bridge-inbound.js +156 -0
- package/lib/node-bind.js +534 -0
- package/lib/node-github.js +72 -0
- package/lib/node-self.js +453 -0
- package/lib/node-store.js +484 -0
- package/lib/node-tasks.js +342 -0
- package/lib/origin-claim.js +246 -0
- package/lib/peer-directory.js +134 -0
- package/lib/receipt.js +26 -1
- package/lib/skill/SKILL.md +3 -1
- package/lib/skill/references/cli.md +82 -3
- package/lib/skill/references/collaboration.md +146 -73
- package/lib/skill/references/discovery.md +29 -0
- package/lib/skill/references/intake.md +107 -0
- package/lib/skill/references/router.md +96 -0
- package/lib/skill/references/setup.md +2 -1
- package/lib/task-auth.js +483 -0
- package/lib/task-ledger.js +324 -12
- package/lib/team-store.js +24 -1
- package/lib/tools/act.js +383 -0
- package/lib/tools/files.js +201 -0
- package/lib/tools/info.js +684 -0
- package/lib/types/a2a-client.d.ts +10 -4
- package/lib/types/auth-observer.d.ts +110 -0
- package/lib/types/blob-store.d.ts +83 -0
- package/lib/types/cli-deposit.d.ts +38 -0
- package/lib/types/faces/admin.d.ts +14 -2
- package/lib/types/faces/canvas-notify.d.ts +4 -1
- package/lib/types/faces/files.d.ts +53 -0
- package/lib/types/faces/nodes.d.ts +69 -0
- package/lib/types/faces/session-log.d.ts +44 -0
- package/lib/types/faces/wire.d.ts +50 -5
- package/lib/types/index.d.ts +27 -0
- package/lib/types/joined-store.d.ts +9 -0
- package/lib/types/ledger-conservation.d.ts +77 -0
- package/lib/types/legacy/teams-bridge-inbound.d.ts +94 -0
- package/lib/types/node-bind.d.ts +220 -0
- package/lib/types/node-github.d.ts +35 -0
- package/lib/types/node-self.d.ts +178 -0
- package/lib/types/node-store.d.ts +180 -0
- package/lib/types/node-tasks.d.ts +121 -0
- package/lib/types/origin-claim.d.ts +119 -0
- package/lib/types/peer-directory.d.ts +39 -0
- package/lib/types/receipt.d.ts +12 -0
- package/lib/types/task-auth.d.ts +271 -0
- package/lib/types/task-ledger.d.ts +143 -6
- package/lib/types/team-store.d.ts +9 -0
- package/lib/types/tools/act.d.ts +52 -0
- package/lib/types/tools/files.d.ts +38 -0
- package/lib/types/tools/info.d.ts +102 -0
- package/lib/types/types.d.ts +6 -0
- package/nexus-stage/src/canvas-ops.ts +17 -2
- package/nexus-stage/src/canvas-wire.ts +27 -19
- package/nexus-stage/src/federation.ts +1 -0
- package/nexus-stage/src/main.ts +41 -18
- package/nexus-stage/src/planning-member-handles.ts +34 -0
- package/nexus-stage/src/planning-mirror.ts +47 -3
- package/nexus-stage/src/planning-reachability.ts +28 -0
- package/nexus-stage/src/planning-types.ts +1 -1
- package/nexus-stage/src/planning-view.ts +30 -27
- package/nexus-stage/src/planning.css +4 -0
- package/nexus-stage/src/wb-directory.ts +13 -0
- package/nexus-stage/src/workbench.css +3 -0
- package/nexus-stage/src/workbench.ts +5 -1
- package/package.json +1 -1
- package/assets/nexusDist/assets/index-C_x3iAth.js +0 -9
- package/assets/nexusDist/assets/index-Dz8N80tI.css +0 -1
package/lib/joined-store.js
CHANGED
|
@@ -26,6 +26,7 @@ export class JoinedSessions {
|
|
|
26
26
|
path;
|
|
27
27
|
/** Session ids, most recently joined first. */
|
|
28
28
|
ids = [];
|
|
29
|
+
listeners = new Set();
|
|
29
30
|
/**
|
|
30
31
|
* @param path - persistence file (`<dsh-home>/a2a/joined.json`); empty = no persistence.
|
|
31
32
|
*/
|
|
@@ -54,8 +55,11 @@ export class JoinedSessions {
|
|
|
54
55
|
* @param id - the joined session id.
|
|
55
56
|
*/
|
|
56
57
|
add(id) {
|
|
58
|
+
const before = this.ids.join('\n');
|
|
57
59
|
this.ids = [id, ...this.ids.filter(entry => entry !== id)].slice(0, JOIN_CAP);
|
|
58
60
|
this.persist();
|
|
61
|
+
if (this.ids.join('\n') !== before)
|
|
62
|
+
this.notify();
|
|
59
63
|
}
|
|
60
64
|
/**
|
|
61
65
|
* Forget one join intent (the leave operation; a no-op when absent).
|
|
@@ -66,6 +70,25 @@ export class JoinedSessions {
|
|
|
66
70
|
return;
|
|
67
71
|
this.ids = this.ids.filter(entry => entry !== id);
|
|
68
72
|
this.persist();
|
|
73
|
+
this.notify();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* #114 S6: observe changes — the listener runs after every write that
|
|
77
|
+
* changed the store (never on restore or reload). A throwing listener
|
|
78
|
+
* cannot break the write.
|
|
79
|
+
* @returns the unsubscribe function.
|
|
80
|
+
*/
|
|
81
|
+
onChange(listener) {
|
|
82
|
+
this.listeners.add(listener);
|
|
83
|
+
return () => { this.listeners.delete(listener); };
|
|
84
|
+
}
|
|
85
|
+
notify() {
|
|
86
|
+
for (const listener of this.listeners) {
|
|
87
|
+
try {
|
|
88
|
+
listener();
|
|
89
|
+
}
|
|
90
|
+
catch { /* a listener's failure is its own */ }
|
|
91
|
+
}
|
|
69
92
|
}
|
|
70
93
|
/**
|
|
71
94
|
* F7 (wake-intent self-heal): re-read the persisted snapshot into memory.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const ARCHIVE_ENDS = ['receipt', 'echo', 'abandoned', 'cancelled', 'evicted'];
|
|
2
|
+
const intAtLeast0 = (v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= Number.MAX_SAFE_INTEGER;
|
|
3
|
+
/**
|
|
4
|
+
* Restore-classify one snapshot's conservation block:
|
|
5
|
+
* - absent block → legacy bootstrap from what the rows prove;
|
|
6
|
+
* - present, fully valid (every field a non-negative integer, archiveTrimmed
|
|
7
|
+
* bounded by the lifetime archived total, optional damaged marker a
|
|
8
|
+
* non-empty string) → valid, counters load as persisted;
|
|
9
|
+
* - anything else (partial, negative, fractional, null body, unbounded trim)
|
|
10
|
+
* → damaged: counters stay zero and the verdict refuses conserved.
|
|
11
|
+
*/
|
|
12
|
+
export function classifyConservationBlock(raw) {
|
|
13
|
+
if (raw === undefined)
|
|
14
|
+
return { kind: 'legacy' };
|
|
15
|
+
if (raw === null || typeof raw !== 'object')
|
|
16
|
+
return { kind: 'damaged', reason: 'conservation-block-invalid' };
|
|
17
|
+
const saved = raw;
|
|
18
|
+
const trackedOk = intAtLeast0(saved.trackedTotal);
|
|
19
|
+
const trimmedOk = intAtLeast0(saved.archiveTrimmed);
|
|
20
|
+
const restoreOk = intAtLeast0(saved.restoreTrimmed);
|
|
21
|
+
const byEndRaw = saved.archivedByEnd;
|
|
22
|
+
const byEnd = byEndRaw !== null && typeof byEndRaw === 'object' ? byEndRaw : undefined;
|
|
23
|
+
const byEndOk = byEnd !== undefined && ARCHIVE_ENDS.every(key => intAtLeast0(byEnd[key]));
|
|
24
|
+
if (!(trackedOk && trimmedOk && restoreOk && byEndOk))
|
|
25
|
+
return { kind: 'damaged', reason: 'conservation-block-invalid' };
|
|
26
|
+
const archivedByEnd = {};
|
|
27
|
+
let archivedTotal = 0;
|
|
28
|
+
for (const key of ARCHIVE_ENDS) {
|
|
29
|
+
archivedByEnd[key] = byEnd[key];
|
|
30
|
+
archivedTotal += byEnd[key];
|
|
31
|
+
}
|
|
32
|
+
if (saved.archiveTrimmed > archivedTotal)
|
|
33
|
+
return { kind: 'damaged', reason: 'conservation-block-invalid' };
|
|
34
|
+
const damaged = saved.damaged;
|
|
35
|
+
if (damaged !== undefined && (typeof damaged !== 'string' || damaged === ''))
|
|
36
|
+
return { kind: 'damaged', reason: 'conservation-block-invalid' };
|
|
37
|
+
return { kind: 'valid', snapshot: { trackedTotal: saved.trackedTotal, archivedByEnd, archiveTrimmed: saved.archiveTrimmed, restoreTrimmed: saved.restoreTrimmed, ...(typeof damaged === 'string' ? { damaged } : {}) } };
|
|
38
|
+
}
|
|
39
|
+
/** The counters themselves — one mutable holder the ledger owns. */
|
|
40
|
+
export class ConservationCounters {
|
|
41
|
+
trackedTotal = 0;
|
|
42
|
+
archivedByEnd = { receipt: 0, echo: 0, abandoned: 0, cancelled: 0, evicted: 0 };
|
|
43
|
+
archiveTrimmed = 0;
|
|
44
|
+
restoreTrimmed = 0;
|
|
45
|
+
damaged;
|
|
46
|
+
/** Legacy bootstrap: the kept rows plus this load's cuts are all the snapshot proves. */
|
|
47
|
+
legacyBootstrap(owedCount, archive, restoreTrimmed, classify) {
|
|
48
|
+
this.trackedTotal = owedCount + archive.length + restoreTrimmed;
|
|
49
|
+
this.archiveTrimmed = 0;
|
|
50
|
+
this.restoreTrimmed = restoreTrimmed;
|
|
51
|
+
for (const row of archive)
|
|
52
|
+
this.archivedByEnd[classify(row)] += 1;
|
|
53
|
+
}
|
|
54
|
+
/** Valid-block load: counters EXACTLY as persisted (review P2: an undercount stays red — never repaired upward); restoreTrimmed ADDS this load's cuts to the persisted lifetime (review P2: neither overwrite nor max). */
|
|
55
|
+
loadFrom(snapshot, owedCount, archiveCount) {
|
|
56
|
+
this.trackedTotal = snapshot.trackedTotal;
|
|
57
|
+
this.archiveTrimmed = snapshot.archiveTrimmed;
|
|
58
|
+
this.restoreTrimmed += snapshot.restoreTrimmed;
|
|
59
|
+
for (const key of ARCHIVE_ENDS)
|
|
60
|
+
this.archivedByEnd[key] = snapshot.archivedByEnd[key];
|
|
61
|
+
if (snapshot.damaged !== undefined)
|
|
62
|
+
this.damaged = snapshot.damaged;
|
|
63
|
+
void owedCount;
|
|
64
|
+
void archiveCount;
|
|
65
|
+
}
|
|
66
|
+
/** The persisted shape (damaged rides along once stamped). */
|
|
67
|
+
toSnapshot() {
|
|
68
|
+
return {
|
|
69
|
+
trackedTotal: this.trackedTotal,
|
|
70
|
+
archivedByEnd: { ...this.archivedByEnd },
|
|
71
|
+
archiveTrimmed: this.archiveTrimmed,
|
|
72
|
+
restoreTrimmed: this.restoreTrimmed,
|
|
73
|
+
...(this.damaged !== undefined ? { damaged: this.damaged } : {}),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** The verdict's count half (the ledger supplies rows, owed count, duplicates). */
|
|
77
|
+
verdict(owedCount, archiveCount, duplicateTaskIds) {
|
|
78
|
+
const archivedTotal = ARCHIVE_ENDS.reduce((n, key) => n + this.archivedByEnd[key], 0);
|
|
79
|
+
const delta = this.trackedTotal - (owedCount + archivedTotal + this.restoreTrimmed);
|
|
80
|
+
// review P2: the archive lost rows only to its live cap or to the load cut.
|
|
81
|
+
const archiveLoss = archivedTotal - archiveCount - this.archiveTrimmed;
|
|
82
|
+
const trimConsistent = archiveLoss >= 0 && archiveLoss <= this.restoreTrimmed;
|
|
83
|
+
const damaged = this.damaged !== undefined ? this.damaged : trimConsistent ? undefined : 'archive-trim-inconsistent';
|
|
84
|
+
return {
|
|
85
|
+
conserved: duplicateTaskIds.length === 0 && delta === 0 && damaged === undefined,
|
|
86
|
+
delta,
|
|
87
|
+
trackedTotal: this.trackedTotal,
|
|
88
|
+
owed: owedCount,
|
|
89
|
+
archivedByEnd: { ...this.archivedByEnd },
|
|
90
|
+
archivedTotal,
|
|
91
|
+
archiveTrimmed: this.archiveTrimmed,
|
|
92
|
+
restoreTrimmed: this.restoreTrimmed,
|
|
93
|
+
duplicateTaskIds,
|
|
94
|
+
...(damaged !== undefined ? { damaged } : {}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the inbound bridge. The bodies are byte-identical to their apply()
|
|
3
|
+
* originals (same two-space indent); only the four capture points arrive as
|
|
4
|
+
* deps.
|
|
5
|
+
*/
|
|
6
|
+
export function createTeamsBridgeInbound(deps) {
|
|
7
|
+
const { ctx, config, liveAgent, fromClause, sanitizeFromClause, proofHeader, } = deps;
|
|
8
|
+
function teamsRegistry() {
|
|
9
|
+
const candidate = ctx.get('teams');
|
|
10
|
+
if (candidate === undefined || candidate === null)
|
|
11
|
+
return undefined;
|
|
12
|
+
if (typeof candidate.describeTarget !== 'function' || typeof candidate.startRound !== 'function' || typeof candidate.listTeams !== 'function')
|
|
13
|
+
return undefined;
|
|
14
|
+
return candidate;
|
|
15
|
+
}
|
|
16
|
+
/** Reply-wait parity with the steer path's 180s deadline: native-teams
|
|
17
|
+
* rounds settle on their own cadence, but a wedged seam must not park a
|
|
18
|
+
* caller past a bounded window (config.nativeRoundWaitMs). */
|
|
19
|
+
/** The claim table changes at registry-edit cadence: a short memo dedupes
|
|
20
|
+
* the double probe (callers pre-check, the round re-verifies) without
|
|
21
|
+
* pretending the answer is permanent. */
|
|
22
|
+
const BRIDGE_CLAIM_TTL_MS = 5_000;
|
|
23
|
+
const bridgeClaimCache = new Map();
|
|
24
|
+
const bridgeTimers = new Set();
|
|
25
|
+
ctx.effect(() => () => {
|
|
26
|
+
for (const timer of bridgeTimers)
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Whether the native-teams registry claims `team` as an unambiguous local
|
|
31
|
+
* target, memoized for {@link BRIDGE_CLAIM_TTL_MS}. Ordinary misses never
|
|
32
|
+
* throw (the D2 query contract); anything that does throw is treated as a
|
|
33
|
+
* miss — the bridge is a guest here. The memo is skipped entirely while
|
|
34
|
+
* the bridge is off, so the flag gates the probe itself.
|
|
35
|
+
*/
|
|
36
|
+
async function nativeTeamsClaims(team) {
|
|
37
|
+
if (config.nativeTeamsInbound !== true)
|
|
38
|
+
return false;
|
|
39
|
+
const cached = bridgeClaimCache.get(team);
|
|
40
|
+
if (cached !== undefined && Date.now() - cached.at < BRIDGE_CLAIM_TTL_MS)
|
|
41
|
+
return cached.claimed;
|
|
42
|
+
const teams = teamsRegistry();
|
|
43
|
+
let claimed = false;
|
|
44
|
+
if (teams !== undefined) {
|
|
45
|
+
try {
|
|
46
|
+
const descriptor = await teams.describeTarget(team);
|
|
47
|
+
claimed = descriptor.plane === 'local' && descriptor.ambiguous !== true && descriptor.localLabel !== undefined;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
claimed = false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
bridgeClaimCache.set(team, { at: Date.now(), claimed });
|
|
54
|
+
// Bounded memo: probe-miss names accumulate one tiny row each; past a
|
|
55
|
+
// generous cap, drop the whole table (a cold re-probe costs one local
|
|
56
|
+
// describeTarget call).
|
|
57
|
+
if (bridgeClaimCache.size > 512)
|
|
58
|
+
bridgeClaimCache.clear();
|
|
59
|
+
return claimed;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolve everything the round needs BEFORE any caller is told the
|
|
63
|
+
* dispatch happened: the claim, the seam, and a parent initiator. The
|
|
64
|
+
* `error` variant is the only fast-failure shape — `not-claimed` simply
|
|
65
|
+
* hands the address back to the standard resolution chain.
|
|
66
|
+
*/
|
|
67
|
+
async function nativeTeamsPrepare(team) {
|
|
68
|
+
if (!await nativeTeamsClaims(team))
|
|
69
|
+
return { ok: false, reason: 'not-claimed' };
|
|
70
|
+
const teams = teamsRegistry();
|
|
71
|
+
if (teams === undefined)
|
|
72
|
+
return { ok: false, reason: 'not-claimed' };
|
|
73
|
+
const parent = liveAgent();
|
|
74
|
+
if (parent === undefined)
|
|
75
|
+
return { ok: false, reason: 'error', error: 'No live DSH initiator is available to parent the native-teams round.' };
|
|
76
|
+
deps.taint?.(parent);
|
|
77
|
+
// The alpha.4 Session face dropped the events member (the widened
|
|
78
|
+
// BridgeTeamsRegistry accepts it optional) — the raw Agent carries the
|
|
79
|
+
// ambient Session whose shape no longer overlaps, so project through the
|
|
80
|
+
// widened structural face explicitly (type-level only; the runtime value
|
|
81
|
+
// is the same live agent).
|
|
82
|
+
const parentFace = parent;
|
|
83
|
+
return { ok: true, teams, parent: parentFace };
|
|
84
|
+
}
|
|
85
|
+
/** The A2A envelope rides the round message so the dispatcher sees the network origin. */
|
|
86
|
+
function bridgeEnvelope(team, caller, message, taskId, proofClause, headerBuilder) {
|
|
87
|
+
const from = caller === '' ? 'an unknown node' : caller;
|
|
88
|
+
const taskPrefix = taskId === undefined ? '' : `(task ${taskId}) `;
|
|
89
|
+
const builder = headerBuilder ?? proofHeader;
|
|
90
|
+
const header = builder !== undefined && taskId !== undefined ? builder(team, taskId, from, proofClause) : `[A2A direct] ${taskPrefix}${proofClause} ${sanitizeFromClause(from)} (routed to ${team}) sent:`;
|
|
91
|
+
return `${header}\n\n${message}`;
|
|
92
|
+
}
|
|
93
|
+
/** The projection for a round that outlived the reply window: unlike the
|
|
94
|
+
* steer deadline's text, this must NOT promise a receipt — native-teams
|
|
95
|
+
* rounds route none in this slice. */
|
|
96
|
+
function bridgeUnsettledReply(team) {
|
|
97
|
+
return `The native-teams round for "${team}" is still running past the reply window; it was delivered and keeps going. Native-teams rounds route no A2A receipt in this slice — reconcile with a follow-up route (continuity rides the team's own durable round chain).`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Fire the round and wait, bounded. The caller's signal (when it has one)
|
|
101
|
+
* cancels the round itself; the deadline releases the caller with the
|
|
102
|
+
* unsettled projection while the round keeps running detached.
|
|
103
|
+
* @param prepared - a ready dispatch (claim, seam, parent) from {@link nativeTeamsPrepare}.
|
|
104
|
+
*/
|
|
105
|
+
async function nativeTeamsRound(prepared, team, caller, message, taskId, proofClause, external, headerBuilder) {
|
|
106
|
+
const controller = new AbortController();
|
|
107
|
+
// One listener, always removed after the race: an external abort cancels
|
|
108
|
+
// the round through its own controller.
|
|
109
|
+
const onExternalAbort = () => { controller.abort(); };
|
|
110
|
+
if (external !== undefined) {
|
|
111
|
+
if (external.aborted)
|
|
112
|
+
controller.abort();
|
|
113
|
+
else
|
|
114
|
+
external.addEventListener('abort', onExternalAbort);
|
|
115
|
+
}
|
|
116
|
+
if (controller.signal.aborted)
|
|
117
|
+
return { ok: false, error: 'aborted before the native-teams round was dispatched', phase: 'pre-dispatch' };
|
|
118
|
+
let roundError;
|
|
119
|
+
let deadlineTimer;
|
|
120
|
+
const deadline = new Promise(resolve => {
|
|
121
|
+
deadlineTimer = setTimeout(() => {
|
|
122
|
+
if (deadlineTimer !== undefined)
|
|
123
|
+
bridgeTimers.delete(deadlineTimer);
|
|
124
|
+
resolve({ kind: 'deadline' });
|
|
125
|
+
}, config.nativeRoundWaitMs ?? 180_000);
|
|
126
|
+
deadlineTimer.unref?.();
|
|
127
|
+
bridgeTimers.add(deadlineTimer);
|
|
128
|
+
});
|
|
129
|
+
const verdict = await Promise.race([
|
|
130
|
+
prepared.teams.startRound({ team, message: bridgeEnvelope(team, caller, message, taskId, proofClause, headerBuilder) }, prepared.parent, controller.signal).then((reply) => ({ kind: 'settled', reply }), (error) => { roundError = error; return { kind: 'failed' }; }),
|
|
131
|
+
deadline,
|
|
132
|
+
new Promise(resolve => {
|
|
133
|
+
if (controller.signal.aborted)
|
|
134
|
+
resolve({ kind: 'aborted' });
|
|
135
|
+
else
|
|
136
|
+
controller.signal.addEventListener('abort', () => resolve({ kind: 'aborted' }), { once: true });
|
|
137
|
+
}),
|
|
138
|
+
]);
|
|
139
|
+
// Hygiene: the losing deadline timer stops here (not 180s later), and
|
|
140
|
+
// the external-signal listener does not outlive the round.
|
|
141
|
+
if (deadlineTimer !== undefined) {
|
|
142
|
+
clearTimeout(deadlineTimer);
|
|
143
|
+
bridgeTimers.delete(deadlineTimer);
|
|
144
|
+
}
|
|
145
|
+
if (external !== undefined)
|
|
146
|
+
external.removeEventListener('abort', onExternalAbort);
|
|
147
|
+
if (verdict.kind === 'settled')
|
|
148
|
+
return { ok: true, reply: verdict.reply, settled: true };
|
|
149
|
+
if (verdict.kind === 'deadline')
|
|
150
|
+
return { ok: true, reply: bridgeUnsettledReply(team), settled: false };
|
|
151
|
+
if (verdict.kind === 'aborted')
|
|
152
|
+
return { ok: false, error: `the wait for the native-teams round "${team}" was aborted (the round was cancelled with it)`, aborted: true };
|
|
153
|
+
return { ok: false, error: `the native-teams round for "${team}" failed: ${String(roundError)}` };
|
|
154
|
+
}
|
|
155
|
+
return { teamsRegistry, nativeTeamsClaims, nativeTeamsPrepare, nativeTeamsRound };
|
|
156
|
+
}
|