instar 1.3.615 → 1.3.617
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/dashboard/mandates.js +30 -9
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +53 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +23 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/coordination/AccountFollowMeMandateDelivery.d.ts +64 -0
- package/dist/coordination/AccountFollowMeMandateDelivery.d.ts.map +1 -0
- package/dist/coordination/AccountFollowMeMandateDelivery.js +92 -0
- package/dist/coordination/AccountFollowMeMandateDelivery.js.map +1 -0
- package/dist/coordination/DeliveredMandateStore.d.ts +67 -0
- package/dist/coordination/DeliveredMandateStore.d.ts.map +1 -0
- package/dist/coordination/DeliveredMandateStore.js +80 -0
- package/dist/coordination/DeliveredMandateStore.js.map +1 -0
- package/dist/core/AccountFollowMeSpendSlice.d.ts +197 -0
- package/dist/core/AccountFollowMeSpendSlice.d.ts.map +1 -0
- package/dist/core/AccountFollowMeSpendSlice.js +196 -0
- package/dist/core/AccountFollowMeSpendSlice.js.map +1 -0
- package/dist/core/AnthropicSubscriptionRouter.d.ts +28 -0
- package/dist/core/AnthropicSubscriptionRouter.d.ts.map +1 -1
- package/dist/core/AnthropicSubscriptionRouter.js +17 -0
- package/dist/core/AnthropicSubscriptionRouter.js.map +1 -1
- package/dist/core/MeshRpc.d.ts +37 -1
- package/dist/core/MeshRpc.d.ts.map +1 -1
- package/dist/core/MeshRpc.js +30 -0
- package/dist/core/MeshRpc.js.map +1 -1
- package/dist/lifeline/ServerSupervisor.d.ts +12 -0
- package/dist/lifeline/ServerSupervisor.d.ts.map +1 -1
- package/dist/lifeline/ServerSupervisor.js +36 -2
- package/dist/lifeline/ServerSupervisor.js.map +1 -1
- package/dist/server/AgentServer.d.ts +27 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +80 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +31 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +93 -3
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +47 -47
- package/upgrades/1.3.616.md +34 -0
- package/upgrades/1.3.617.md +22 -0
- package/upgrades/side-effects/supervisor-sustained-starvation-fix.md +81 -0
- package/upgrades/side-effects/ws52-account-follow-me-r7a-spend-slice.md +70 -0
- package/upgrades/side-effects/ws52-one-dashboard-mandate-delivery.md +74 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WS5.2 R7a — per-account spend-slice ORCHESTRATION (the LEASE-SLICED ceiling, owned by the
|
|
3
|
+
* fenced single-writer). This is the cohesive control-plane unit on top of the durable
|
|
4
|
+
* `AccountFollowMeGrantLedger` (AccountFollowMeGrants.ts), kept PURE + injectable so the
|
|
5
|
+
* distributed math is unit-testable without a live mesh.
|
|
6
|
+
*
|
|
7
|
+
* Spec bounds enforced here (docs/specs/ws52-account-follow-me-security.md §R7a, §S5, §I5):
|
|
8
|
+
*
|
|
9
|
+
* (a) FENCED single-writer issuance. Slices are issued ONLY by the current `FencedLease` holder;
|
|
10
|
+
* a non-holder issuing is refused (`not-lease-holder`). Issuance is epoch-fenced: a renew
|
|
11
|
+
* stamped with a stale lease epoch is void (`stale-lease-epoch`). On a holder FAILOVER the new
|
|
12
|
+
* holder constructs `SliceIssuer` over the SAME durable ledger and re-derives outstanding
|
|
13
|
+
* slices BEFORE issuing — the ledger's sum-of-leases bound holds across the handoff with no
|
|
14
|
+
* double-allocation (proven in AccountFollowMeGrants).
|
|
15
|
+
*
|
|
16
|
+
* (b) `maxSpend` is denominated in provider quota-FRACTION (0..1), reusing AccountQuotaSnapshot.
|
|
17
|
+
* The issuer takes the ceiling as a fraction; per-slice consumption is the durable grant amount.
|
|
18
|
+
*
|
|
19
|
+
* (c) The requester-side renewal CONTROL PLANE is rate-capped + coalesced + P19-breaker-protected,
|
|
20
|
+
* so N VMs on one hot account produce O(per-account-cap) renewal RPCs — never an O(N) herd:
|
|
21
|
+
* - per-(account,machine) in-flight COALESCING: a VM with an outstanding renewal does not
|
|
22
|
+
* start a second (`coalesced-in-flight`);
|
|
23
|
+
* - per-account renewal RATE CAP with EXPONENTIAL backoff after each refusal/failure;
|
|
24
|
+
* - a P19 sustained-FAILURE breaker: after `breakerThreshold` consecutive failures the VM
|
|
25
|
+
* FAILS CLOSED TO ITS OWN ACCOUNT (`breaker-open`) instead of retry-storming a slow/
|
|
26
|
+
* partitioned/unreachable holder. The breaker re-closes after `breakerCooldownMs`.
|
|
27
|
+
*
|
|
28
|
+
* (d) FIRST-SLICE-under-partition: a VM that never received a slice is treated identically to a
|
|
29
|
+
* VM whose slice is exhausted — it FAILS CLOSED TO ITS OWN ACCOUNT until it obtains its first
|
|
30
|
+
* slice (the `decideAccountUse` consultation below).
|
|
31
|
+
*
|
|
32
|
+
* INVARIANT (load-bearing): fail-closed-to-OWN-account on EVERY uncertainty — no slice, exhausted,
|
|
33
|
+
* partition, breaker open, no mandate, ledger error. A borrowed account is NEVER overspent past its
|
|
34
|
+
* grant. Everything stays dark behind `multiMachine.accountFollowMe` at the wiring layer.
|
|
35
|
+
*/
|
|
36
|
+
import { type GrantStore } from './AccountFollowMeGrants.js';
|
|
37
|
+
export interface SliceIssuerConfig {
|
|
38
|
+
/** This machine's id — must equal the lease holder for issuance to be authorized. */
|
|
39
|
+
selfMachineId: string;
|
|
40
|
+
/**
|
|
41
|
+
* The current effective lease epoch + whether THIS machine holds the lease at it. Read live so a
|
|
42
|
+
* mid-flight failover (we lost the lease) refuses issuance rather than double-allocating.
|
|
43
|
+
*/
|
|
44
|
+
holdsLease: () => boolean;
|
|
45
|
+
currentLeaseEpoch: () => number;
|
|
46
|
+
now?: () => number;
|
|
47
|
+
}
|
|
48
|
+
/** The renewal request a requesting VM sends to the holder (the `slice-renew` verb payload, decoded). */
|
|
49
|
+
export interface SliceRenewRequest {
|
|
50
|
+
grantId: string;
|
|
51
|
+
mandateId: string;
|
|
52
|
+
accountId: string;
|
|
53
|
+
/** Requesting machine's routing fingerprint (carried in the verb; bound into the grant). */
|
|
54
|
+
requestingMachineFp: string;
|
|
55
|
+
/** Slice size requested (provider quota-fraction). */
|
|
56
|
+
amount: number;
|
|
57
|
+
/** Absolute expiry of the slice (ms since epoch). */
|
|
58
|
+
expiresAt: number;
|
|
59
|
+
}
|
|
60
|
+
export interface SliceIssuanceContext {
|
|
61
|
+
/** The account's spend ceiling (provider quota-fraction, 0..1) — from the live grant/quota policy. */
|
|
62
|
+
ceiling: number;
|
|
63
|
+
}
|
|
64
|
+
export type SliceIssueOutcome = {
|
|
65
|
+
ok: true;
|
|
66
|
+
grantId: string;
|
|
67
|
+
amount: number;
|
|
68
|
+
leaseEpoch: number;
|
|
69
|
+
expiresAt: number;
|
|
70
|
+
} | {
|
|
71
|
+
ok: false;
|
|
72
|
+
reason: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* The HOLDER-side issuer. Runs ON the fenced lease holder (the `slice-renew` handler wires this).
|
|
76
|
+
* Refuses unless this machine genuinely holds the lease right now, then delegates the sum-of-leases
|
|
77
|
+
* accounting to the durable ledger (single source of truth, re-derived on every call → failover-safe).
|
|
78
|
+
*/
|
|
79
|
+
export declare class SliceIssuer {
|
|
80
|
+
private readonly cfg;
|
|
81
|
+
private readonly ledger;
|
|
82
|
+
private readonly now;
|
|
83
|
+
constructor(store: GrantStore, cfg: SliceIssuerConfig);
|
|
84
|
+
/** Outstanding committed slices for an account (re-derived from the durable ledger). */
|
|
85
|
+
outstandingFor(accountId: string): number;
|
|
86
|
+
/**
|
|
87
|
+
* Issue (or re-issue) a slice in response to a renew request. FENCED: refuses unless this machine
|
|
88
|
+
* holds the lease at the current epoch. The slice is stamped with the CURRENT lease epoch, so it is
|
|
89
|
+
* void at a later epoch (consume/renew checks via the ledger). The ledger enforces the sum-of-leases
|
|
90
|
+
* ceiling and single-use grant ids.
|
|
91
|
+
*/
|
|
92
|
+
issueForRenew(req: SliceRenewRequest, ctx: SliceIssuanceContext): SliceIssueOutcome;
|
|
93
|
+
}
|
|
94
|
+
export interface SliceLeaseState {
|
|
95
|
+
/** The grant id of the slice this VM currently holds for the account, if any. */
|
|
96
|
+
grantId?: string;
|
|
97
|
+
/** Remaining unspent budget on the held slice (provider quota-fraction). */
|
|
98
|
+
remaining: number;
|
|
99
|
+
/** Lease epoch the held slice was issued under — void if the holder advanced past it. */
|
|
100
|
+
leaseEpoch: number;
|
|
101
|
+
/** Absolute expiry of the held slice (ms since epoch). */
|
|
102
|
+
expiresAt: number;
|
|
103
|
+
}
|
|
104
|
+
export interface RenewControlConfig {
|
|
105
|
+
/**
|
|
106
|
+
* Minimum interval between renewal RPCs for ONE account on this machine (ms). The per-account
|
|
107
|
+
* rate cap — combined with coalescing + the holder's own ceiling, the worst-case fleet renewal
|
|
108
|
+
* rate is O(per-account-cap), independent of N. Default 5000.
|
|
109
|
+
*/
|
|
110
|
+
minRenewIntervalMs?: number;
|
|
111
|
+
/** Exponential-backoff multiplier applied to the interval after each refusal/failure. Default 2. */
|
|
112
|
+
backoffMultiplier?: number;
|
|
113
|
+
/** Backoff ceiling (ms) so the interval cannot grow unbounded. Default 300000 (5m). */
|
|
114
|
+
maxRenewIntervalMs?: number;
|
|
115
|
+
/** Consecutive failures before the P19 breaker opens (fail closed to own account). Default 3. */
|
|
116
|
+
breakerThreshold?: number;
|
|
117
|
+
/** How long the breaker stays open before a probe is allowed again (ms). Default 60000. */
|
|
118
|
+
breakerCooldownMs?: number;
|
|
119
|
+
now?: () => number;
|
|
120
|
+
}
|
|
121
|
+
export type RenewAttemptDecision = {
|
|
122
|
+
proceed: true;
|
|
123
|
+
} | {
|
|
124
|
+
proceed: false;
|
|
125
|
+
reason: 'coalesced-in-flight' | 'rate-capped' | 'breaker-open';
|
|
126
|
+
};
|
|
127
|
+
export type RenewOutcomeKind = 'issued' | 'refused' | 'failed';
|
|
128
|
+
/**
|
|
129
|
+
* The per-machine requester-side renewal control plane for ONE account. Pure state-machine: a caller
|
|
130
|
+
* asks `shouldAttempt()` before sending a `slice-renew` RPC, marks `beginAttempt()` when it sends,
|
|
131
|
+
* and reports `recordOutcome()` with the result. It enforces coalescing, the rate cap with
|
|
132
|
+
* exponential backoff, and the P19 breaker — so the transport above it can be a thin RPC.
|
|
133
|
+
*/
|
|
134
|
+
export declare class SliceRenewalControl {
|
|
135
|
+
private readonly minInterval;
|
|
136
|
+
private readonly backoffMul;
|
|
137
|
+
private readonly maxInterval;
|
|
138
|
+
private readonly breakerThreshold;
|
|
139
|
+
private readonly breakerCooldownMs;
|
|
140
|
+
private readonly now;
|
|
141
|
+
private inFlight;
|
|
142
|
+
private lastAttemptAt;
|
|
143
|
+
/** Current backoff interval (grows on refusal/failure, resets on success). */
|
|
144
|
+
private currentInterval;
|
|
145
|
+
private consecutiveFailures;
|
|
146
|
+
private breakerOpenedAt;
|
|
147
|
+
constructor(cfg?: RenewControlConfig);
|
|
148
|
+
/** Is the P19 breaker currently open (a probe not yet allowed)? */
|
|
149
|
+
breakerOpen(): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* May this VM send a renewal RPC for the account right now? Refuses (fail-closed at the call site)
|
|
152
|
+
* when a renewal is already in flight (coalescing), the rate cap has not elapsed, or the breaker is
|
|
153
|
+
* open. The caller treats any `proceed:false` as "use my OWN account this turn."
|
|
154
|
+
*/
|
|
155
|
+
shouldAttempt(): RenewAttemptDecision;
|
|
156
|
+
/** Mark a renewal RPC as started (coalescing latch). Must be paired with recordOutcome(). */
|
|
157
|
+
beginAttempt(): void;
|
|
158
|
+
/**
|
|
159
|
+
* Report the RPC result, advancing the control state:
|
|
160
|
+
* - issued → reset backoff + breaker (the channel is healthy again);
|
|
161
|
+
* - refused → grant-level refusal (e.g. would-exceed-ceiling); back off, but NOT a transport
|
|
162
|
+
* failure, so it does not advance the breaker (the holder answered);
|
|
163
|
+
* - failed → transport failure (timeout/partition/unreachable); back off AND advance the breaker.
|
|
164
|
+
*/
|
|
165
|
+
recordOutcome(kind: RenewOutcomeKind): void;
|
|
166
|
+
}
|
|
167
|
+
export type AccountUseDecision = {
|
|
168
|
+
use: 'borrowed';
|
|
169
|
+
remaining: number;
|
|
170
|
+
reason: 'live-slice';
|
|
171
|
+
} | {
|
|
172
|
+
use: 'own';
|
|
173
|
+
reason: 'follow-me-disabled' | 'not-a-borrowed-account' | 'no-slice' | 'slice-exhausted' | 'slice-expired' | 'stale-lease-epoch';
|
|
174
|
+
};
|
|
175
|
+
export interface AccountUseQuery {
|
|
176
|
+
/** Master dark gate (`multiMachine.accountFollowMe`). When false → ALWAYS own account. */
|
|
177
|
+
followMeEnabled: boolean;
|
|
178
|
+
/** Is the candidate account a BORROWED (follow-me / metadata-only-credentialed) account? */
|
|
179
|
+
isBorrowedAccount: boolean;
|
|
180
|
+
/** The slice this VM currently holds for the candidate account (undefined ⇒ never received one). */
|
|
181
|
+
slice: SliceLeaseState | undefined;
|
|
182
|
+
/** The current effective lease epoch (a slice from an older epoch is void). */
|
|
183
|
+
currentLeaseEpoch: number;
|
|
184
|
+
now: number;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The SELECTION-TIME consultation (R7a(b)/(d), S5, §6.2). Returns whether a candidate BORROWED
|
|
188
|
+
* account may be used this turn, or whether the call must FALL BACK to this machine's OWN account.
|
|
189
|
+
*
|
|
190
|
+
* Fail-closed-to-own-account on EVERY uncertainty: flag off, not a borrowed account, no slice ever
|
|
191
|
+
* received (first-slice-under-partition), exhausted slice, expired slice, or a stale-epoch slice all
|
|
192
|
+
* resolve to `own`. ONLY a live, unexpired, current-epoch slice with remaining budget yields
|
|
193
|
+
* `borrowed`. This is pure — the router/pool wiring calls it and routes accordingly; when off it can
|
|
194
|
+
* never be reached so default behavior is byte-identical.
|
|
195
|
+
*/
|
|
196
|
+
export declare function decideAccountUse(q: AccountUseQuery): AccountUseDecision;
|
|
197
|
+
//# sourceMappingURL=AccountFollowMeSpendSlice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccountFollowMeSpendSlice.d.ts","sourceRoot":"","sources":["../../src/core/AccountFollowMeSpendSlice.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WS5.2 R7a — per-account spend-slice ORCHESTRATION (the LEASE-SLICED ceiling, owned by the
|
|
3
|
+
* fenced single-writer). This is the cohesive control-plane unit on top of the durable
|
|
4
|
+
* `AccountFollowMeGrantLedger` (AccountFollowMeGrants.ts), kept PURE + injectable so the
|
|
5
|
+
* distributed math is unit-testable without a live mesh.
|
|
6
|
+
*
|
|
7
|
+
* Spec bounds enforced here (docs/specs/ws52-account-follow-me-security.md §R7a, §S5, §I5):
|
|
8
|
+
*
|
|
9
|
+
* (a) FENCED single-writer issuance. Slices are issued ONLY by the current `FencedLease` holder;
|
|
10
|
+
* a non-holder issuing is refused (`not-lease-holder`). Issuance is epoch-fenced: a renew
|
|
11
|
+
* stamped with a stale lease epoch is void (`stale-lease-epoch`). On a holder FAILOVER the new
|
|
12
|
+
* holder constructs `SliceIssuer` over the SAME durable ledger and re-derives outstanding
|
|
13
|
+
* slices BEFORE issuing — the ledger's sum-of-leases bound holds across the handoff with no
|
|
14
|
+
* double-allocation (proven in AccountFollowMeGrants).
|
|
15
|
+
*
|
|
16
|
+
* (b) `maxSpend` is denominated in provider quota-FRACTION (0..1), reusing AccountQuotaSnapshot.
|
|
17
|
+
* The issuer takes the ceiling as a fraction; per-slice consumption is the durable grant amount.
|
|
18
|
+
*
|
|
19
|
+
* (c) The requester-side renewal CONTROL PLANE is rate-capped + coalesced + P19-breaker-protected,
|
|
20
|
+
* so N VMs on one hot account produce O(per-account-cap) renewal RPCs — never an O(N) herd:
|
|
21
|
+
* - per-(account,machine) in-flight COALESCING: a VM with an outstanding renewal does not
|
|
22
|
+
* start a second (`coalesced-in-flight`);
|
|
23
|
+
* - per-account renewal RATE CAP with EXPONENTIAL backoff after each refusal/failure;
|
|
24
|
+
* - a P19 sustained-FAILURE breaker: after `breakerThreshold` consecutive failures the VM
|
|
25
|
+
* FAILS CLOSED TO ITS OWN ACCOUNT (`breaker-open`) instead of retry-storming a slow/
|
|
26
|
+
* partitioned/unreachable holder. The breaker re-closes after `breakerCooldownMs`.
|
|
27
|
+
*
|
|
28
|
+
* (d) FIRST-SLICE-under-partition: a VM that never received a slice is treated identically to a
|
|
29
|
+
* VM whose slice is exhausted — it FAILS CLOSED TO ITS OWN ACCOUNT until it obtains its first
|
|
30
|
+
* slice (the `decideAccountUse` consultation below).
|
|
31
|
+
*
|
|
32
|
+
* INVARIANT (load-bearing): fail-closed-to-OWN-account on EVERY uncertainty — no slice, exhausted,
|
|
33
|
+
* partition, breaker open, no mandate, ledger error. A borrowed account is NEVER overspent past its
|
|
34
|
+
* grant. Everything stays dark behind `multiMachine.accountFollowMe` at the wiring layer.
|
|
35
|
+
*/
|
|
36
|
+
import { AccountFollowMeGrantLedger, } from './AccountFollowMeGrants.js';
|
|
37
|
+
/**
|
|
38
|
+
* The HOLDER-side issuer. Runs ON the fenced lease holder (the `slice-renew` handler wires this).
|
|
39
|
+
* Refuses unless this machine genuinely holds the lease right now, then delegates the sum-of-leases
|
|
40
|
+
* accounting to the durable ledger (single source of truth, re-derived on every call → failover-safe).
|
|
41
|
+
*/
|
|
42
|
+
export class SliceIssuer {
|
|
43
|
+
cfg;
|
|
44
|
+
ledger;
|
|
45
|
+
now;
|
|
46
|
+
constructor(store, cfg) {
|
|
47
|
+
this.cfg = cfg;
|
|
48
|
+
this.now = cfg.now ?? Date.now;
|
|
49
|
+
this.ledger = new AccountFollowMeGrantLedger(store, this.now);
|
|
50
|
+
}
|
|
51
|
+
/** Outstanding committed slices for an account (re-derived from the durable ledger). */
|
|
52
|
+
outstandingFor(accountId) {
|
|
53
|
+
return this.ledger.outstandingFor(accountId);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Issue (or re-issue) a slice in response to a renew request. FENCED: refuses unless this machine
|
|
57
|
+
* holds the lease at the current epoch. The slice is stamped with the CURRENT lease epoch, so it is
|
|
58
|
+
* void at a later epoch (consume/renew checks via the ledger). The ledger enforces the sum-of-leases
|
|
59
|
+
* ceiling and single-use grant ids.
|
|
60
|
+
*/
|
|
61
|
+
issueForRenew(req, ctx) {
|
|
62
|
+
// (a) FENCED single-writer: only the live lease holder may issue. A non-holder (e.g. a stale
|
|
63
|
+
// ex-holder mid-failover) refuses — the safe direction (no double-allocation).
|
|
64
|
+
if (!this.cfg.holdsLease()) {
|
|
65
|
+
return { ok: false, reason: 'not-lease-holder' };
|
|
66
|
+
}
|
|
67
|
+
const leaseEpoch = this.cfg.currentLeaseEpoch();
|
|
68
|
+
const result = this.ledger.issue({
|
|
69
|
+
grantId: req.grantId,
|
|
70
|
+
mandateId: req.mandateId,
|
|
71
|
+
accountId: req.accountId,
|
|
72
|
+
targetFingerprint: req.requestingMachineFp,
|
|
73
|
+
amount: req.amount,
|
|
74
|
+
ceiling: ctx.ceiling,
|
|
75
|
+
leaseEpoch,
|
|
76
|
+
expiresAt: req.expiresAt,
|
|
77
|
+
});
|
|
78
|
+
if (!result.ok)
|
|
79
|
+
return { ok: false, reason: result.reason };
|
|
80
|
+
return {
|
|
81
|
+
ok: true,
|
|
82
|
+
grantId: result.grant.grantId,
|
|
83
|
+
amount: result.grant.amount,
|
|
84
|
+
leaseEpoch: result.grant.leaseEpoch,
|
|
85
|
+
expiresAt: result.grant.expiresAt,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The per-machine requester-side renewal control plane for ONE account. Pure state-machine: a caller
|
|
91
|
+
* asks `shouldAttempt()` before sending a `slice-renew` RPC, marks `beginAttempt()` when it sends,
|
|
92
|
+
* and reports `recordOutcome()` with the result. It enforces coalescing, the rate cap with
|
|
93
|
+
* exponential backoff, and the P19 breaker — so the transport above it can be a thin RPC.
|
|
94
|
+
*/
|
|
95
|
+
export class SliceRenewalControl {
|
|
96
|
+
minInterval;
|
|
97
|
+
backoffMul;
|
|
98
|
+
maxInterval;
|
|
99
|
+
breakerThreshold;
|
|
100
|
+
breakerCooldownMs;
|
|
101
|
+
now;
|
|
102
|
+
inFlight = false;
|
|
103
|
+
lastAttemptAt = -Infinity;
|
|
104
|
+
/** Current backoff interval (grows on refusal/failure, resets on success). */
|
|
105
|
+
currentInterval;
|
|
106
|
+
consecutiveFailures = 0;
|
|
107
|
+
breakerOpenedAt = null;
|
|
108
|
+
constructor(cfg = {}) {
|
|
109
|
+
this.minInterval = cfg.minRenewIntervalMs ?? 5000;
|
|
110
|
+
this.backoffMul = cfg.backoffMultiplier ?? 2;
|
|
111
|
+
this.maxInterval = cfg.maxRenewIntervalMs ?? 300000;
|
|
112
|
+
this.breakerThreshold = cfg.breakerThreshold ?? 3;
|
|
113
|
+
this.breakerCooldownMs = cfg.breakerCooldownMs ?? 60000;
|
|
114
|
+
this.now = cfg.now ?? Date.now;
|
|
115
|
+
this.currentInterval = this.minInterval;
|
|
116
|
+
}
|
|
117
|
+
/** Is the P19 breaker currently open (a probe not yet allowed)? */
|
|
118
|
+
breakerOpen() {
|
|
119
|
+
if (this.breakerOpenedAt === null)
|
|
120
|
+
return false;
|
|
121
|
+
return this.now() - this.breakerOpenedAt < this.breakerCooldownMs;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* May this VM send a renewal RPC for the account right now? Refuses (fail-closed at the call site)
|
|
125
|
+
* when a renewal is already in flight (coalescing), the rate cap has not elapsed, or the breaker is
|
|
126
|
+
* open. The caller treats any `proceed:false` as "use my OWN account this turn."
|
|
127
|
+
*/
|
|
128
|
+
shouldAttempt() {
|
|
129
|
+
if (this.inFlight)
|
|
130
|
+
return { proceed: false, reason: 'coalesced-in-flight' };
|
|
131
|
+
if (this.breakerOpen())
|
|
132
|
+
return { proceed: false, reason: 'breaker-open' };
|
|
133
|
+
if (this.now() - this.lastAttemptAt < this.currentInterval) {
|
|
134
|
+
return { proceed: false, reason: 'rate-capped' };
|
|
135
|
+
}
|
|
136
|
+
return { proceed: true };
|
|
137
|
+
}
|
|
138
|
+
/** Mark a renewal RPC as started (coalescing latch). Must be paired with recordOutcome(). */
|
|
139
|
+
beginAttempt() {
|
|
140
|
+
this.inFlight = true;
|
|
141
|
+
this.lastAttemptAt = this.now();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Report the RPC result, advancing the control state:
|
|
145
|
+
* - issued → reset backoff + breaker (the channel is healthy again);
|
|
146
|
+
* - refused → grant-level refusal (e.g. would-exceed-ceiling); back off, but NOT a transport
|
|
147
|
+
* failure, so it does not advance the breaker (the holder answered);
|
|
148
|
+
* - failed → transport failure (timeout/partition/unreachable); back off AND advance the breaker.
|
|
149
|
+
*/
|
|
150
|
+
recordOutcome(kind) {
|
|
151
|
+
this.inFlight = false;
|
|
152
|
+
if (kind === 'issued') {
|
|
153
|
+
this.currentInterval = this.minInterval;
|
|
154
|
+
this.consecutiveFailures = 0;
|
|
155
|
+
this.breakerOpenedAt = null;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
// Back off on any non-success.
|
|
159
|
+
this.currentInterval = Math.min(this.currentInterval * this.backoffMul, this.maxInterval);
|
|
160
|
+
if (kind === 'failed') {
|
|
161
|
+
this.consecutiveFailures += 1;
|
|
162
|
+
if (this.consecutiveFailures >= this.breakerThreshold && this.breakerOpenedAt === null) {
|
|
163
|
+
this.breakerOpenedAt = this.now();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* The SELECTION-TIME consultation (R7a(b)/(d), S5, §6.2). Returns whether a candidate BORROWED
|
|
170
|
+
* account may be used this turn, or whether the call must FALL BACK to this machine's OWN account.
|
|
171
|
+
*
|
|
172
|
+
* Fail-closed-to-own-account on EVERY uncertainty: flag off, not a borrowed account, no slice ever
|
|
173
|
+
* received (first-slice-under-partition), exhausted slice, expired slice, or a stale-epoch slice all
|
|
174
|
+
* resolve to `own`. ONLY a live, unexpired, current-epoch slice with remaining budget yields
|
|
175
|
+
* `borrowed`. This is pure — the router/pool wiring calls it and routes accordingly; when off it can
|
|
176
|
+
* never be reached so default behavior is byte-identical.
|
|
177
|
+
*/
|
|
178
|
+
export function decideAccountUse(q) {
|
|
179
|
+
if (!q.followMeEnabled)
|
|
180
|
+
return { use: 'own', reason: 'follow-me-disabled' };
|
|
181
|
+
if (!q.isBorrowedAccount)
|
|
182
|
+
return { use: 'own', reason: 'not-a-borrowed-account' };
|
|
183
|
+
const s = q.slice;
|
|
184
|
+
// (d) first-slice-under-partition: never received a slice → own account.
|
|
185
|
+
if (!s || !s.grantId)
|
|
186
|
+
return { use: 'own', reason: 'no-slice' };
|
|
187
|
+
// A slice from a superseded lease epoch is void (the holder failed over).
|
|
188
|
+
if (s.leaseEpoch < q.currentLeaseEpoch)
|
|
189
|
+
return { use: 'own', reason: 'stale-lease-epoch' };
|
|
190
|
+
if (s.expiresAt <= q.now)
|
|
191
|
+
return { use: 'own', reason: 'slice-expired' };
|
|
192
|
+
if (!(s.remaining > 0))
|
|
193
|
+
return { use: 'own', reason: 'slice-exhausted' };
|
|
194
|
+
return { use: 'borrowed', remaining: s.remaining, reason: 'live-slice' };
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=AccountFollowMeSpendSlice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccountFollowMeSpendSlice.js","sourceRoot":"","sources":["../../src/core/AccountFollowMeSpendSlice.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import type { IntelligenceProvider, IntelligenceOptions } from './types.js';
|
|
31
31
|
import type { AgentSdkCreditSnapshot } from '../providers/primitives/observability/usageMeterProvider.js';
|
|
32
|
+
import type { AccountUseDecision } from './AccountFollowMeSpendSlice.js';
|
|
32
33
|
export type SubscriptionPathMode = 'auto' | 'force';
|
|
33
34
|
export interface SubscriptionRouteInfo {
|
|
34
35
|
/** Which path served (or was chosen for) the call. */
|
|
@@ -58,11 +59,38 @@ export interface AnthropicSubscriptionRouterOptions {
|
|
|
58
59
|
onRoute?: (info: SubscriptionRouteInfo) => void;
|
|
59
60
|
/** Observability tap — auto-mode fallback after a primary failure. */
|
|
60
61
|
onDegrade?: (info: SubscriptionDegradeInfo) => void;
|
|
62
|
+
/**
|
|
63
|
+
* WS5.2 R7a (S5, §6.2) — OPTIONAL slice consultation. When account follow-me is enabled and
|
|
64
|
+
* wired, the routing layer injects this to decide, AT SELECTION TIME, whether the subscription
|
|
65
|
+
* path may use a BORROWED (follow-me) account this call or must fall back to this machine's OWN
|
|
66
|
+
* account. It returns the same `AccountUseDecision` as `decideAccountUse` — `use:'own'` on EVERY
|
|
67
|
+
* uncertainty (no slice / exhausted / expired / stale epoch / first-slice-under-partition / flag
|
|
68
|
+
* off), `use:'borrowed'` only on a live current-epoch slice with remaining budget.
|
|
69
|
+
*
|
|
70
|
+
* ABSENT (the default, and ALWAYS when `multiMachine.accountFollowMe` is off) ⇒ this hook is
|
|
71
|
+
* never invoked, so routing is BYTE-IDENTICAL to today. The router NEVER overspends a borrowed
|
|
72
|
+
* account: it never reaches for one unless this consultation says `borrowed`, and a borrowed
|
|
73
|
+
* selection here only ever scopes the subscription-pool path the pool provider already uses
|
|
74
|
+
* (the pool's own account selection honors the decision via `onSliceConsult`).
|
|
75
|
+
*/
|
|
76
|
+
consultSlice?: (options?: IntelligenceOptions) => AccountUseDecision;
|
|
77
|
+
/** Observability tap — the slice consultation result for a subscription-path call. */
|
|
78
|
+
onSliceConsult?: (info: {
|
|
79
|
+
decision: AccountUseDecision;
|
|
80
|
+
component?: string;
|
|
81
|
+
}) => void;
|
|
61
82
|
}
|
|
62
83
|
export declare class AnthropicSubscriptionRouter implements IntelligenceProvider {
|
|
63
84
|
private readonly opts;
|
|
64
85
|
private readonly safetyMarginFraction;
|
|
65
86
|
constructor(options: AnthropicSubscriptionRouterOptions);
|
|
87
|
+
/**
|
|
88
|
+
* WS5.2 R7a — run the (optional) slice consultation before a subscription-pool call. NO-OP when
|
|
89
|
+
* `consultSlice` is unwired (the default / flag-off), so today's behavior is byte-identical. When
|
|
90
|
+
* wired it surfaces the decision (own vs borrowed) to observability + the pool's account selection;
|
|
91
|
+
* the router never overspends — a `use:'own'` keeps the pool on this machine's own account.
|
|
92
|
+
*/
|
|
93
|
+
private consultSliceForSubscription;
|
|
66
94
|
evaluate(prompt: string, options?: IntelligenceOptions): Promise<string>;
|
|
67
95
|
}
|
|
68
96
|
//# sourceMappingURL=AnthropicSubscriptionRouter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnthropicSubscriptionRouter.d.ts","sourceRoot":"","sources":["../../src/core/AnthropicSubscriptionRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE5E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6DAA6D,CAAC;
|
|
1
|
+
{"version":3,"file":"AnthropicSubscriptionRouter.d.ts","sourceRoot":"","sources":["../../src/core/AnthropicSubscriptionRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE5E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6DAA6D,CAAC;AAC1G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpD,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,IAAI,EAAE,YAAY,GAAG,mBAAmB,CAAC;IACzC,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,YAAY,GAAG,mBAAmB,CAAC;IACzC,EAAE,EAAE,YAAY,GAAG,mBAAmB,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kCAAkC;IACjD,4EAA4E;IAC5E,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,qCAAqC;IACrC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,+EAA+E;IAC/E,aAAa,EAAE,MAAM,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAC5D,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAChD,sEAAsE;IACtE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACpD;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,kBAAkB,CAAC;IACrE,sFAAsF;IACtF,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,kBAAkB,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACvF;AAID,qBAAa,2BAA4B,YAAW,oBAAoB;IACtE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqC;IAC1D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;gBAElC,OAAO,EAAE,kCAAkC;IAWvD;;;;;OAKG;IACH,OAAO,CAAC,2BAA2B;IAM7B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;CA2C/E"}
|
|
@@ -40,10 +40,23 @@ export class AnthropicSubscriptionRouter {
|
|
|
40
40
|
throw new Error(`AnthropicSubscriptionRouter: safetyMarginFraction must be in [0,1], got ${this.safetyMarginFraction}`);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* WS5.2 R7a — run the (optional) slice consultation before a subscription-pool call. NO-OP when
|
|
45
|
+
* `consultSlice` is unwired (the default / flag-off), so today's behavior is byte-identical. When
|
|
46
|
+
* wired it surfaces the decision (own vs borrowed) to observability + the pool's account selection;
|
|
47
|
+
* the router never overspends — a `use:'own'` keeps the pool on this machine's own account.
|
|
48
|
+
*/
|
|
49
|
+
consultSliceForSubscription(options, component) {
|
|
50
|
+
if (!this.opts.consultSlice)
|
|
51
|
+
return;
|
|
52
|
+
const decision = this.opts.consultSlice(options);
|
|
53
|
+
this.opts.onSliceConsult?.({ decision, component });
|
|
54
|
+
}
|
|
43
55
|
async evaluate(prompt, options) {
|
|
44
56
|
const component = options?.attribution?.component;
|
|
45
57
|
if (this.opts.mode === 'force') {
|
|
46
58
|
this.opts.onRoute?.({ path: 'subscription-pool', reason: 'forced-subscription-mode', component });
|
|
59
|
+
this.consultSliceForSubscription(options, component);
|
|
47
60
|
// No fallback by design — force mode guarantees zero `claude -p`
|
|
48
61
|
// traffic; a pool failure must surface, not silently re-route.
|
|
49
62
|
return this.opts.pool.evaluate(prompt, options);
|
|
@@ -61,6 +74,8 @@ export class AnthropicSubscriptionRouter {
|
|
|
61
74
|
? 'subscription-pool'
|
|
62
75
|
: 'sdk-credit';
|
|
63
76
|
this.opts.onRoute?.({ path: primaryLabel, reason: decision.reason, component });
|
|
77
|
+
if (primaryLabel === 'subscription-pool')
|
|
78
|
+
this.consultSliceForSubscription(options, component);
|
|
64
79
|
try {
|
|
65
80
|
return await primary.evaluate(prompt, options);
|
|
66
81
|
}
|
|
@@ -75,6 +90,8 @@ export class AnthropicSubscriptionRouter {
|
|
|
75
90
|
reason: `fallback-after-primary-failure: ${reason.slice(0, 200)}`,
|
|
76
91
|
component,
|
|
77
92
|
});
|
|
93
|
+
if (fallbackLabel === 'subscription-pool')
|
|
94
|
+
this.consultSliceForSubscription(options, component);
|
|
78
95
|
return fallback.evaluate(prompt, options);
|
|
79
96
|
}
|
|
80
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnthropicSubscriptionRouter.js","sourceRoot":"","sources":["../../src/core/AnthropicSubscriptionRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"AnthropicSubscriptionRouter.js","sourceRoot":"","sources":["../../src/core/AnthropicSubscriptionRouter.ts"],"names":[],"mappings":"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"}
|
package/dist/core/MeshRpc.d.ts
CHANGED
|
@@ -60,6 +60,17 @@ export type MeshCommand = {
|
|
|
60
60
|
} | {
|
|
61
61
|
type: 'secret-share';
|
|
62
62
|
encrypted: string;
|
|
63
|
+
} | {
|
|
64
|
+
type: 'slice-renew';
|
|
65
|
+
mandateId: string;
|
|
66
|
+
accountId: string;
|
|
67
|
+
requestingMachineFp: string;
|
|
68
|
+
amount: number;
|
|
69
|
+
expiresAt: number;
|
|
70
|
+
} | {
|
|
71
|
+
type: 'account-follow-me-mandate-deliver';
|
|
72
|
+
/** The R4a-signed bundle: the mandate + its asymmetric issuance signature. */
|
|
73
|
+
portable: import('../coordination/AccountFollowMeMandateBridge.js').PortableMandate;
|
|
63
74
|
} | {
|
|
64
75
|
type: 'pool-stream-ticket';
|
|
65
76
|
session: string;
|
|
@@ -171,7 +182,7 @@ export declare function verifyEnvelope(env: MeshEnvelope, deps: VerifyEnvelopeDe
|
|
|
171
182
|
ok: boolean;
|
|
172
183
|
reason: VerifyReason;
|
|
173
184
|
};
|
|
174
|
-
export type RbacReason = 'ok' | 'not-router' | 'claim-unauthorized' | 'release-unauthorized' | 'drain-unauthorized';
|
|
185
|
+
export type RbacReason = 'ok' | 'not-router' | 'claim-unauthorized' | 'release-unauthorized' | 'drain-unauthorized' | 'slice-renew-unauthorized' | 'mandate-deliver-unauthorized';
|
|
175
186
|
export interface RbacDeps {
|
|
176
187
|
/** The machine currently holding the router lease (verify-on-read, §L1), or null. */
|
|
177
188
|
routerHolder: () => MachineId | null;
|
|
@@ -179,6 +190,31 @@ export interface RbacDeps {
|
|
|
179
190
|
ownerOf: (session: string) => MachineId | null;
|
|
180
191
|
/** The machine the router last assigned (via place/transfer) for a session, or null. */
|
|
181
192
|
placementTargetOf: (session: string) => MachineId | null;
|
|
193
|
+
/**
|
|
194
|
+
* WS5.2 R7a — the operator-mandate gate for the `slice-renew` verb. Returns true ONLY when the
|
|
195
|
+
* authorizing mandate authorizes (sender, accountId, requesting fingerprint) for account follow-me
|
|
196
|
+
* — deny-by-default. INJECTED so the dangerous authority decision is a real check, never an
|
|
197
|
+
* inherit. ABSENT ⇒ the verb is refused (fail-closed): on a build without the seam wired, a
|
|
198
|
+
* slice-renew can never be authorized. Mirrors the deny-by-default discipline of R3a/R4a.
|
|
199
|
+
*/
|
|
200
|
+
authorizeSliceRenew?: (args: {
|
|
201
|
+
sender: MachineId;
|
|
202
|
+
mandateId: string;
|
|
203
|
+
accountId: string;
|
|
204
|
+
requestingMachineFp: string;
|
|
205
|
+
}) => boolean;
|
|
206
|
+
/**
|
|
207
|
+
* WS5.2 R4a — the gate for `account-follow-me-mandate-deliver`. Returns true ONLY when account
|
|
208
|
+
* follow-me is ENABLED on this machine AND the sender is THIS machine's trusted operator machine
|
|
209
|
+
* (the verified-operator binding). Deny-by-default: ABSENT ⇒ the verb is refused (fail-closed) —
|
|
210
|
+
* on a build without the seam wired, or on a non-dev/dark agent, a delivered mandate can never be
|
|
211
|
+
* accepted at the gate. This is ONLY the coarse "should I even look at it" gate; the LOAD-BEARING
|
|
212
|
+
* authority is the R4a asymmetric signature verification in the handler, which re-binds to the
|
|
213
|
+
* authenticated sender + registered operator key. Mirrors the deny-by-default discipline of R3a.
|
|
214
|
+
*/
|
|
215
|
+
authorizeMandateDeliver?: (args: {
|
|
216
|
+
sender: MachineId;
|
|
217
|
+
}) => boolean;
|
|
182
218
|
}
|
|
183
219
|
/**
|
|
184
220
|
* Per-command authorization gate (spec §L0). A valid signature proves WHO; this
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MeshRpc.d.ts","sourceRoot":"","sources":["../../src/core/MeshRpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAE/B,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GACxG;IAWE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB,GACD;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"MeshRpc.d.ts","sourceRoot":"","sources":["../../src/core/MeshRpc.ts"],"names":[],"mappings":"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"}
|