@centerforagenticai/pi-multi-account 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +29 -0
  3. package/README.md +999 -0
  4. package/config/models/pi-multi-account.v1.json +32 -0
  5. package/config/subscription-plans.v1.json +122 -0
  6. package/package.json +76 -0
  7. package/packages/pi-anthropic-oauth/LICENSE +21 -0
  8. package/packages/pi-anthropic-oauth/package.json +54 -0
  9. package/packages/pi-anthropic-oauth/src/auth.ts +396 -0
  10. package/packages/pi-anthropic-oauth/src/context.ts +116 -0
  11. package/packages/pi-anthropic-oauth/src/convert.ts +303 -0
  12. package/packages/pi-anthropic-oauth/src/index.ts +37 -0
  13. package/packages/pi-anthropic-oauth/src/prompt.ts +137 -0
  14. package/packages/pi-anthropic-oauth/src/stream.ts +476 -0
  15. package/packages/pi-antigravity/LICENSE +21 -0
  16. package/packages/pi-antigravity/package.json +77 -0
  17. package/packages/pi-antigravity/src/auth/index.ts +14 -0
  18. package/packages/pi-antigravity/src/auth/oauth.ts +442 -0
  19. package/packages/pi-antigravity/src/client/client.ts +561 -0
  20. package/packages/pi-antigravity/src/client/index.ts +1 -0
  21. package/packages/pi-antigravity/src/context.ts +110 -0
  22. package/packages/pi-antigravity/src/diagnostics/diagnostics.ts +96 -0
  23. package/packages/pi-antigravity/src/diagnostics/index.ts +1 -0
  24. package/packages/pi-antigravity/src/image/image.ts +336 -0
  25. package/packages/pi-antigravity/src/image/index.ts +1 -0
  26. package/packages/pi-antigravity/src/index.ts +280 -0
  27. package/packages/pi-antigravity/src/models/discovery.ts +154 -0
  28. package/packages/pi-antigravity/src/models/grouping.ts +424 -0
  29. package/packages/pi-antigravity/src/models/index.ts +3 -0
  30. package/packages/pi-antigravity/src/models/models.ts +500 -0
  31. package/packages/pi-antigravity/src/stream/index.ts +1 -0
  32. package/packages/pi-antigravity/src/stream/stream.ts +1478 -0
  33. package/packages/pi-antigravity/src/types/enums.ts +42 -0
  34. package/packages/pi-antigravity/src/types/index.ts +2 -0
  35. package/packages/pi-antigravity/src/types/types.ts +292 -0
  36. package/packages/pi-antigravity/src/usage/index.ts +1 -0
  37. package/packages/pi-antigravity/src/usage/usage.ts +416 -0
  38. package/packages/pi-antigravity/src/utils/http.ts +91 -0
  39. package/packages/pi-antigravity/src/utils/index.ts +3 -0
  40. package/packages/pi-antigravity/src/utils/security.ts +73 -0
  41. package/packages/pi-antigravity/src/utils/util.ts +132 -0
  42. package/scripts/multi-account.mjs +44 -0
  43. package/src/account-labels.ts +223 -0
  44. package/src/account-plan-assignment.ts +340 -0
  45. package/src/account-rate-history.ts +372 -0
  46. package/src/anthropic-adaptive-stream.ts +531 -0
  47. package/src/anthropic-alias-stream.ts +140 -0
  48. package/src/anthropic-context-compat.ts +80 -0
  49. package/src/api-pricing.ts +579 -0
  50. package/src/bounded-file-lines.ts +97 -0
  51. package/src/catalog-rebinding.ts +177 -0
  52. package/src/catalog-registration-probe.ts +111 -0
  53. package/src/codex-adapter.ts +345 -0
  54. package/src/codex-model-defaults.ts +785 -0
  55. package/src/command-completions.ts +404 -0
  56. package/src/commands.ts +2000 -0
  57. package/src/compaction.ts +14 -0
  58. package/src/config.ts +1317 -0
  59. package/src/continuation.ts +569 -0
  60. package/src/cooldowns.ts +110 -0
  61. package/src/cost-digest-store.ts +332 -0
  62. package/src/cost-digest.ts +1044 -0
  63. package/src/cost-history.ts +251 -0
  64. package/src/cost-period-closer.ts +160 -0
  65. package/src/cost-report-json.ts +318 -0
  66. package/src/cost-report-reader.ts +368 -0
  67. package/src/cost-report-render.ts +207 -0
  68. package/src/cost-report.ts +1104 -0
  69. package/src/coverage-attestation.ts +397 -0
  70. package/src/credential-lifecycle.ts +169 -0
  71. package/src/credential-refresh.ts +248 -0
  72. package/src/declaration-notice-marker.ts +238 -0
  73. package/src/diagnostic-store.ts +276 -0
  74. package/src/diagnostics.ts +309 -0
  75. package/src/discovery.ts +471 -0
  76. package/src/duration.ts +13 -0
  77. package/src/error-classification.ts +256 -0
  78. package/src/fuzzy.ts +15 -0
  79. package/src/group-policy.ts +81 -0
  80. package/src/history-store.ts +897 -0
  81. package/src/index.ts +5572 -0
  82. package/src/lifecycle.ts +378 -0
  83. package/src/logical-dispatch.ts +279 -0
  84. package/src/logical-model-selector.ts +254 -0
  85. package/src/logical-model-switcher.ts +430 -0
  86. package/src/logical-provider-attribution.ts +544 -0
  87. package/src/logical-provider.ts +1237 -0
  88. package/src/logical-route-indicator.ts +215 -0
  89. package/src/machine-lease.ts +445 -0
  90. package/src/model-support.ts +66 -0
  91. package/src/models-declaration.ts +1091 -0
  92. package/src/openai-adapter.ts +117 -0
  93. package/src/openrouter-budget.ts +304 -0
  94. package/src/openrouter-fallback.ts +146 -0
  95. package/src/period-boundaries.ts +376 -0
  96. package/src/pi-anthropic-oauth.d.ts +6 -0
  97. package/src/preflight.ts +253 -0
  98. package/src/pricing-cache.ts +235 -0
  99. package/src/project-identity.ts +100 -0
  100. package/src/provider-registration.ts +942 -0
  101. package/src/rate-formula.ts +163 -0
  102. package/src/recovery-engine.ts +853 -0
  103. package/src/recovery-output.ts +837 -0
  104. package/src/recovery-plan.ts +239 -0
  105. package/src/report-range.ts +203 -0
  106. package/src/route-resolver.ts +789 -0
  107. package/src/routing-config-transaction.ts +232 -0
  108. package/src/routing.ts +1163 -0
  109. package/src/runtime-state.ts +630 -0
  110. package/src/session-account-groups.ts +284 -0
  111. package/src/session-restore.ts +287 -0
  112. package/src/shared-usage.ts +1392 -0
  113. package/src/standalone-cli.ts +720 -0
  114. package/src/status-view.ts +578 -0
  115. package/src/subscription-plan-catalog.ts +346 -0
  116. package/src/tier-model-resolver.ts +46 -0
  117. package/src/upstream-anthropic.ts +315 -0
  118. package/src/upstream-antigravity.ts +327 -0
  119. package/src/usage-fetch.ts +1634 -0
  120. package/src/usage.ts +1026 -0
  121. package/src/vendor.ts +87 -0
  122. package/src/warmer.ts +231 -0
  123. package/src/watchdog.ts +219 -0
  124. package/src/window-history.ts +270 -0
@@ -0,0 +1,544 @@
1
+ /**
2
+ * Physical attribution for turns served through the logical provider.
3
+ *
4
+ * Every attempt closes over one validated physical route. The exact terminal
5
+ * assistant object is the only correlation key shared with `message_end`; no
6
+ * latest-route cell or request identifier exists.
7
+ */
8
+
9
+ import type { AssistantMessage, ProviderResponse } from "@earendil-works/pi-ai";
10
+ import { isManagedFamily } from "./config.js";
11
+ import type { ProviderFailureSignal } from "./error-classification.js";
12
+ import {
13
+ NOOP_LOGICAL_ATTRIBUTION_ATTEMPT,
14
+ type LogicalAttributionAttempt,
15
+ type LogicalAttributionLifecycle,
16
+ type LogicalAttributionResponse,
17
+ type LogicalRouteFact,
18
+ type LogicalTerminalFailureFact,
19
+ type LogicalTerminalOutcome,
20
+ type ManagedAssistantRecordOutcome,
21
+ } from "./logical-provider.js";
22
+ import { isCanonicalManagedProviderId } from "./runtime-state.js";
23
+ import { providerTypeFor, type ProviderType } from "./vendor.js";
24
+
25
+ export { NOOP_LOGICAL_ATTRIBUTION_ATTEMPT } from "./logical-provider.js";
26
+ export type {
27
+ LogicalAttributionAttempt,
28
+ LogicalAttributionLifecycle,
29
+ LogicalAttributionResponse,
30
+ LogicalRouteFact,
31
+ LogicalTerminalOutcome,
32
+ ManagedAssistantRecordOutcome,
33
+ } from "./logical-provider.js";
34
+
35
+ /** Bounded, sanitized output from the raw store. */
36
+ export type LogicalAttributionStoreObservation = Readonly<{
37
+ kind: "response" | "authentication" | "model-support" | "health" | "payload" | "tokens" | "cost";
38
+ route: LogicalRouteFact;
39
+ status?: number;
40
+ success?: boolean;
41
+ supported?: boolean;
42
+ health?: Readonly<{
43
+ healthy?: boolean;
44
+ live?: boolean;
45
+ expiresAt?: number;
46
+ }>;
47
+ input?: number;
48
+ output?: number;
49
+ amount?: number;
50
+ }>;
51
+
52
+ export type AttributionDiagnostic = Readonly<{
53
+ code: string;
54
+ reason?: string;
55
+ [key: string]: unknown;
56
+ }>;
57
+
58
+ export type AttributionStoreOptions = {
59
+ onObservation?: (observation: LogicalAttributionStoreObservation) => void;
60
+ onDiagnostic?: (diagnostic: AttributionDiagnostic) => void;
61
+ onShutdownAbort?: (route: LogicalRouteFact) => void;
62
+ /**
63
+ * Raw response is transient. Production must immediately project its headers
64
+ * into a bounded fact and RETURN it, so the store can bind that fact to this
65
+ * exact attempt and deliver it through {@link onAssociation}. Keying response
66
+ * facts only by physical provider let two concurrent attempts on one provider,
67
+ * or a stale-generation attempt, consume each other's response facts.
68
+ */
69
+ onResponse?: (
70
+ route: LogicalRouteFact,
71
+ response: ProviderResponse,
72
+ ) => ProviderFailureSignal | void;
73
+ /** Complete terminal message is transient. Production must project it immediately. */
74
+ onTerminal?: (
75
+ route: LogicalRouteFact,
76
+ message: AssistantMessage,
77
+ ) => void | Promise<ManagedAssistantRecordOutcome>;
78
+ /** Exact-object association is transient and consumed by the session coordinator. */
79
+ onAssociation?: (
80
+ route: LogicalRouteFact,
81
+ message: AssistantMessage,
82
+ outcome: TerminalOutcome,
83
+ failure: LogicalTerminalFailureFact | undefined,
84
+ /** Bounded response fact bound to THIS attempt, never keyed by provider. */
85
+ response: ProviderFailureSignal | undefined,
86
+ ) => void;
87
+ onSettle?: () => void;
88
+ onShutdownComplete?: () => void;
89
+ };
90
+
91
+ export type LogicalHistoryResult =
92
+ | { readonly status: "accepted"; readonly cleaned: true }
93
+ | { readonly status: "not-found"; readonly cleaned: false };
94
+
95
+ export type AttributionStore = LogicalAttributionLifecycle & {
96
+ messageEnd(message: AssistantMessage): Promise<LogicalHistoryResult>;
97
+ /** Rejects only active, not-yet-terminal attempts; owned terminal history remains valid. */
98
+ cancelActiveAttempts(): void;
99
+ recordDiagnostic(diagnostic: unknown): void;
100
+ activeAttempts(): number;
101
+ snapshot(): unknown;
102
+ drain(): unknown;
103
+ };
104
+
105
+ const MAX_TERMINAL_RECORDS = 64;
106
+ const MAX_PENDING_TERMINAL_WRITES = 64;
107
+ const MAX_EMITTED_RECORDS = 256;
108
+ const MAX_DIAGNOSTICS = 64;
109
+
110
+ function pushBounded<T>(into: T[], value: T, limit: number): void {
111
+ into.push(value);
112
+ if (into.length > limit) into.splice(0, into.length - limit);
113
+ }
114
+
115
+ function isManagedProviderType(
116
+ value: unknown,
117
+ ): value is Exclude<ProviderType, "openrouter"> {
118
+ return value === "subscription" || value === "owning-vendor-api";
119
+ }
120
+
121
+ function providerTypeMatchesFamily(
122
+ family: LogicalRouteFact["family"],
123
+ providerType: Exclude<ProviderType, "openrouter">,
124
+ ): boolean {
125
+ return (
126
+ providerTypeFor(
127
+ family,
128
+ providerType === "owning-vendor-api" ? "api_key" : "oauth",
129
+ ) === providerType
130
+ );
131
+ }
132
+
133
+ /** Validate identity first, then project only the permitted route fields. */
134
+ export function canonicalAttributionRoute(
135
+ route: LogicalRouteFact,
136
+ ): LogicalRouteFact | undefined {
137
+ if (typeof route !== "object" || route === null) return undefined;
138
+ const candidate = route as unknown as Record<string, unknown>;
139
+ const providerId = candidate.providerId;
140
+ const family = candidate.family;
141
+ const providerType = candidate.providerType;
142
+ const accountFingerprint = candidate.accountFingerprint;
143
+ if (
144
+ typeof providerId !== "string" ||
145
+ typeof family !== "string" ||
146
+ !isManagedFamily(family) ||
147
+ !isManagedProviderType(providerType) ||
148
+ typeof accountFingerprint !== "string"
149
+ ) {
150
+ return undefined;
151
+ }
152
+ if (!providerTypeMatchesFamily(family, providerType)) return undefined;
153
+ if (!isCanonicalManagedProviderId(providerId, family)) return undefined;
154
+ if (accountFingerprint !== providerId) return undefined;
155
+ return Object.freeze({
156
+ providerId,
157
+ family,
158
+ providerType,
159
+ accountFingerprint: providerId,
160
+ });
161
+ }
162
+
163
+ type TerminalOutcome = "finish" | "fail" | "abort";
164
+
165
+ type AttemptRecord = {
166
+ readonly route: LogicalRouteFact;
167
+ readonly generation: number;
168
+ active: boolean;
169
+ terminalOutcome?: TerminalOutcome;
170
+ terminalBarrier?: Promise<LogicalTerminalOutcome>;
171
+ /** Latest bounded response fact observed for THIS attempt, retired with it. */
172
+ responseFact?: ProviderFailureSignal;
173
+ };
174
+
175
+ type TerminalRecord = Readonly<{
176
+ route: LogicalRouteFact;
177
+ outcome: TerminalOutcome;
178
+ }>;
179
+
180
+ function finiteNumber(value: unknown): number | undefined {
181
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
182
+ }
183
+
184
+ function projectedHealth(value: unknown): LogicalAttributionStoreObservation["health"] {
185
+ if (typeof value !== "object" || value === null) return undefined;
186
+ const candidate = value as Record<string, unknown>;
187
+ const healthy = typeof candidate.healthy === "boolean" ? candidate.healthy : undefined;
188
+ const live = typeof candidate.live === "boolean" ? candidate.live : undefined;
189
+ const expiresAt = finiteNumber(candidate.expiresAt);
190
+ if (healthy === undefined && live === undefined && expiresAt === undefined) {
191
+ return undefined;
192
+ }
193
+ return Object.freeze({
194
+ ...(healthy === undefined ? {} : { healthy }),
195
+ ...(live === undefined ? {} : { live }),
196
+ ...(expiresAt === undefined ? {} : { expiresAt }),
197
+ });
198
+ }
199
+
200
+ function isAssistantMessage(value: unknown): value is AssistantMessage {
201
+ return (
202
+ typeof value === "object" &&
203
+ value !== null &&
204
+ (value as { role?: unknown }).role === "assistant"
205
+ );
206
+ }
207
+
208
+ const createAssistantAssociations = () =>
209
+ new WeakMap<AssistantMessage, AttemptRecord>();
210
+
211
+ /** Build one reusable raw attribution store. Session permanence is added outside. */
212
+ export function createAttributionStore(
213
+ options: AttributionStoreOptions = {},
214
+ ): AttributionStore {
215
+ let generation = 0;
216
+ const attemptRecords = new Set<AttemptRecord>();
217
+ let assistantAssociations = createAssistantAssociations();
218
+ let publicTerminals = new WeakMap<AssistantMessage, AssistantMessage>();
219
+ let publishedPhysical = new WeakSet<AssistantMessage>();
220
+ let terminalOwners = new WeakMap<AssistantMessage, AttemptRecord>();
221
+ let terminalRecords: TerminalRecord[] = [];
222
+ let emittedRecords: LogicalAttributionStoreObservation[] = [];
223
+ let pendingTerminalWrites = 0;
224
+ let diagnosticCount = 0;
225
+ let invalidRouteDiagnosed = false;
226
+ let emittingDiagnostic = false;
227
+
228
+ const callbackFailureDiagnostic = (error: unknown): AttributionDiagnostic =>
229
+ Object.freeze({
230
+ code: "attribution.callback-failed",
231
+ reason: "attribution.callback-failed",
232
+ });
233
+
234
+ const attributionDiagnostic = (diagnostic: AttributionDiagnostic): void => {
235
+ if (diagnosticCount >= MAX_DIAGNOSTICS) return;
236
+ diagnosticCount += 1;
237
+ emittingDiagnostic = true;
238
+ try {
239
+ safeAttributionCall(() => options.onDiagnostic?.(diagnostic));
240
+ } finally {
241
+ emittingDiagnostic = false;
242
+ }
243
+ };
244
+
245
+ const safeAttributionCall = (
246
+ call: () => void | Promise<void>,
247
+ ): void | Promise<void> => {
248
+ try {
249
+ const result = call();
250
+ if (result instanceof Promise) {
251
+ return result.catch((error: unknown) => {
252
+ if (!emittingDiagnostic) {
253
+ attributionDiagnostic(callbackFailureDiagnostic(error));
254
+ }
255
+ });
256
+ }
257
+ return undefined;
258
+ } catch (error) {
259
+ if (!emittingDiagnostic) {
260
+ attributionDiagnostic(callbackFailureDiagnostic(error));
261
+ }
262
+ return undefined;
263
+ }
264
+ };
265
+
266
+ const safeTerminalCall = (
267
+ route: LogicalRouteFact,
268
+ message: AssistantMessage,
269
+ ): Promise<LogicalTerminalOutcome> => {
270
+ try {
271
+ const result = options.onTerminal?.(route, message);
272
+ if (result === undefined) return Promise.resolve({ status: "not-attempted" });
273
+ return Promise.resolve(result).then(
274
+ (value) =>
275
+ typeof value === "object" && value !== null &&
276
+ (value as { status?: unknown }).status === "retained"
277
+ ? { status: "retained" }
278
+ : { status: "failed" },
279
+ (error: unknown) => {
280
+ attributionDiagnostic(callbackFailureDiagnostic(error));
281
+ return { status: "failed" };
282
+ },
283
+ );
284
+ } catch (error) {
285
+ attributionDiagnostic(callbackFailureDiagnostic(error));
286
+ return Promise.resolve({ status: "failed" });
287
+ }
288
+ };
289
+
290
+ const observe = (observation: LogicalAttributionStoreObservation): void => {
291
+ pushBounded(emittedRecords, observation, MAX_EMITTED_RECORDS);
292
+ safeAttributionCall(() => options.onObservation?.(observation));
293
+ };
294
+
295
+ const isCurrent = (record: AttemptRecord): boolean =>
296
+ record.generation === generation;
297
+
298
+ const beginAttempt = (route: LogicalRouteFact): LogicalAttributionAttempt => {
299
+ const canonicalRoute = canonicalAttributionRoute(route);
300
+ if (canonicalRoute === undefined) {
301
+ if (!invalidRouteDiagnosed) {
302
+ invalidRouteDiagnosed = true;
303
+ attributionDiagnostic({ code: "attribution.invalid-route" });
304
+ }
305
+ return NOOP_LOGICAL_ATTRIBUTION_ATTEMPT;
306
+ }
307
+ const attemptGeneration = generation;
308
+ const record: AttemptRecord = {
309
+ route: canonicalRoute,
310
+ generation: attemptGeneration,
311
+ active: true,
312
+ };
313
+ attemptRecords.add(record);
314
+
315
+ const terminal =
316
+ (outcome: TerminalOutcome) =>
317
+ (
318
+ message: AssistantMessage,
319
+ failure?: LogicalTerminalFailureFact,
320
+ ): boolean => {
321
+ if (!isCurrent(record) || !isAssistantMessage(message)) return false;
322
+ if (record.terminalOutcome !== undefined) {
323
+ return record.terminalOutcome === outcome;
324
+ }
325
+ if (!record.active) return false;
326
+ const terminalOwner = terminalOwners.get(message);
327
+ record.terminalOutcome = outcome;
328
+ record.active = false;
329
+ if (terminalOwner === undefined) {
330
+ terminalOwners.set(message, record);
331
+ assistantAssociations.set(message, record);
332
+ if (pendingTerminalWrites >= MAX_PENDING_TERMINAL_WRITES) {
333
+ attributionDiagnostic({ code: "attribution.terminal-capacity" });
334
+ record.terminalBarrier = Promise.resolve({ status: "not-attempted-capacity" });
335
+ } else {
336
+ pendingTerminalWrites += 1;
337
+ let resolveBarrier!: (result: LogicalTerminalOutcome) => void;
338
+ const barrier = new Promise<LogicalTerminalOutcome>((resolve) => {
339
+ resolveBarrier = resolve;
340
+ });
341
+ // Install the shared barrier before invoking any external callback so
342
+ // a reentrant second attempt cannot observe a half-owned terminal. The
343
+ // callback itself still starts synchronously, before the terminal yields.
344
+ record.terminalBarrier = barrier.finally(() => {
345
+ pendingTerminalWrites -= 1;
346
+ });
347
+ void safeTerminalCall(record.route, message).then(resolveBarrier);
348
+ }
349
+ } else {
350
+ // Exact-object ambiguity must still reach onAssociation so routing can
351
+ // fail closed, but the first owner remains authoritative for both
352
+ // accounting and history. Every claimant awaits the same barrier.
353
+ record.terminalBarrier =
354
+ terminalOwner.terminalBarrier ??
355
+ Promise.resolve({ status: "not-attempted" });
356
+ }
357
+ let associationAccepted = true;
358
+ try {
359
+ options.onAssociation?.(
360
+ record.route,
361
+ message,
362
+ outcome,
363
+ failure,
364
+ record.responseFact,
365
+ );
366
+ } catch (error) {
367
+ associationAccepted = false;
368
+ attributionDiagnostic(callbackFailureDiagnostic(error));
369
+ }
370
+ pushBounded(
371
+ terminalRecords,
372
+ Object.freeze({ route: record.route, outcome }),
373
+ MAX_TERMINAL_RECORDS,
374
+ );
375
+ attemptRecords.delete(record);
376
+ return associationAccepted;
377
+ };
378
+
379
+ return Object.freeze({
380
+ onResponse: (response: LogicalAttributionResponse): void => {
381
+ if (!isCurrent(record) || !record.active) return;
382
+ const status = finiteNumber(response?.status);
383
+ observe(Object.freeze({
384
+ kind: "response",
385
+ route: record.route,
386
+ ...(status === undefined ? {} : { status }),
387
+ }));
388
+ if (status !== undefined) {
389
+ // Capture the projected fact on THIS attempt record so the terminal
390
+ // association carries the response fact bound to the exact attempt,
391
+ // never one keyed by physical provider that a concurrent or stale
392
+ // attempt could overwrite.
393
+ try {
394
+ const fact = options.onResponse?.(
395
+ record.route,
396
+ response as ProviderResponse,
397
+ );
398
+ if (fact !== undefined && fact !== null) record.responseFact = fact;
399
+ } catch (error) {
400
+ attributionDiagnostic(callbackFailureDiagnostic(error));
401
+ }
402
+ }
403
+ },
404
+ onAuthentication: (success: boolean): void => {
405
+ if (!isCurrent(record) || !record.active || typeof success !== "boolean") return;
406
+ observe(Object.freeze({ kind: "authentication", route: record.route, success }));
407
+ },
408
+ onModelSupport: (supported: boolean): void => {
409
+ if (!isCurrent(record) || !record.active || typeof supported !== "boolean") return;
410
+ observe(Object.freeze({ kind: "model-support", route: record.route, supported }));
411
+ },
412
+ onHealth: (health: unknown): void => {
413
+ if (!isCurrent(record) || !record.active) return;
414
+ const projected = projectedHealth(health);
415
+ observe(Object.freeze({
416
+ kind: "health",
417
+ route: record.route,
418
+ ...(projected === undefined ? {} : { health: projected }),
419
+ }));
420
+ },
421
+ onPayload: (_payload: unknown): void => {
422
+ if (!isCurrent(record) || !record.active) return;
423
+ observe(Object.freeze({ kind: "payload", route: record.route }));
424
+ },
425
+ finish: terminal("finish"),
426
+ fail: terminal("fail"),
427
+ abort: terminal("abort"),
428
+ waitForTerminal: (): Promise<LogicalTerminalOutcome> =>
429
+ record.terminalBarrier ?? Promise.resolve({ status: "not-attempted" }),
430
+ bindPublicTerminal: (physical: AssistantMessage, publicMessage: AssistantMessage): void => {
431
+ if (!isCurrent(record) || terminalOwners.get(physical) !== record ||
432
+ !assistantAssociations.has(physical) || publicTerminals.has(publicMessage)) return;
433
+ publicTerminals.set(publicMessage, physical);
434
+ publishedPhysical.add(physical);
435
+ },
436
+ });
437
+ };
438
+
439
+ const messageEnd = async (message: AssistantMessage): Promise<LogicalHistoryResult> => {
440
+ const physical = publicTerminals.get(message) ?? message;
441
+ if (physical === message && publishedPhysical.has(message)) {
442
+ return { status: "not-found", cleaned: false };
443
+ }
444
+ const record = assistantAssociations.get(physical);
445
+ if (record === undefined || record.generation !== generation) {
446
+ return { status: "not-found", cleaned: false };
447
+ }
448
+ // Reserve the exact physical owner before the writer barrier yields control.
449
+ assistantAssociations.delete(physical);
450
+ publicTerminals.delete(message);
451
+ try {
452
+ await (record.terminalBarrier ?? Promise.resolve({ status: "not-attempted" }));
453
+ let input: number | undefined;
454
+ let output: number | undefined;
455
+ let amount: number | undefined;
456
+ try {
457
+ input = finiteNumber(physical.usage.input);
458
+ output = finiteNumber(physical.usage.output);
459
+ amount = finiteNumber(physical.usage.cost.total);
460
+ } catch {
461
+ // A malformed terminal object cannot escape the fail-soft boundary.
462
+ }
463
+ if (input !== undefined || output !== undefined) {
464
+ observe(Object.freeze({
465
+ kind: "tokens",
466
+ route: record.route,
467
+ ...(input === undefined ? {} : { input }),
468
+ ...(output === undefined ? {} : { output }),
469
+ }));
470
+ }
471
+ if (amount !== undefined) {
472
+ observe(Object.freeze({ kind: "cost", route: record.route, amount }));
473
+ }
474
+ return { status: "accepted", cleaned: true };
475
+ } finally {
476
+ assistantAssociations.delete(physical);
477
+ publicTerminals.delete(message);
478
+ }
479
+ };
480
+
481
+ return {
482
+ beginAttempt,
483
+ messageEnd,
484
+
485
+ cancelActiveAttempts: (): void => {
486
+ for (const record of attemptRecords) {
487
+ if (!isCurrent(record) || !record.active) continue;
488
+ record.active = false;
489
+ attemptRecords.delete(record);
490
+ }
491
+ },
492
+
493
+ recordDiagnostic: (diagnostic: unknown): void => {
494
+ attributionDiagnostic(callbackFailureDiagnostic(diagnostic));
495
+ },
496
+
497
+ settle: (): void => {
498
+ generation += 1;
499
+ attemptRecords.clear();
500
+ assistantAssociations = createAssistantAssociations();
501
+ publicTerminals = new WeakMap<AssistantMessage, AssistantMessage>();
502
+ publishedPhysical = new WeakSet<AssistantMessage>();
503
+ terminalOwners = new WeakMap<AssistantMessage, AttemptRecord>();
504
+ safeAttributionCall(() => options.onSettle?.());
505
+ },
506
+
507
+ shutdown: (): void => {
508
+ try {
509
+ generation += 1;
510
+ for (const record of attemptRecords) {
511
+ if (record.active) {
512
+ safeAttributionCall(() => options.onShutdownAbort?.(record.route));
513
+ }
514
+ }
515
+ attemptRecords.clear();
516
+ assistantAssociations = createAssistantAssociations();
517
+ publicTerminals = new WeakMap<AssistantMessage, AssistantMessage>();
518
+ publishedPhysical = new WeakSet<AssistantMessage>();
519
+ terminalOwners = new WeakMap<AssistantMessage, AttemptRecord>();
520
+ terminalRecords = [];
521
+ emittedRecords = [];
522
+ invalidRouteDiagnosed = false;
523
+ } finally {
524
+ safeAttributionCall(() => options.onShutdownComplete?.());
525
+ }
526
+ },
527
+
528
+ activeAttempts: (): number => {
529
+ let active = 0;
530
+ for (const record of attemptRecords) {
531
+ if (record.active && record.generation === generation) active += 1;
532
+ }
533
+ return active;
534
+ },
535
+
536
+ snapshot: () => ({ terminal: [...terminalRecords] }),
537
+
538
+ drain: () => {
539
+ const drained = emittedRecords;
540
+ emittedRecords = [];
541
+ return drained;
542
+ },
543
+ };
544
+ }