@tangle-network/agent-eval 0.120.2 → 0.120.3
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 +6 -0
- package/dist/analyst/index.d.ts +3111 -0
- package/dist/analyst/index.js +403 -0
- package/dist/analyst/index.js.map +1 -0
- package/dist/authenticity/index.d.ts +161 -0
- package/dist/authenticity/index.js +215 -0
- package/dist/authenticity/index.js.map +1 -0
- package/dist/belief-state/index.d.ts +1301 -0
- package/dist/belief-state/index.js +2152 -0
- package/dist/belief-state/index.js.map +1 -0
- package/dist/benchmarks/index.d.ts +974 -0
- package/dist/benchmarks/index.js +60 -0
- package/dist/benchmarks/index.js.map +1 -0
- package/dist/builder-eval/index.d.ts +695 -0
- package/dist/builder-eval/index.js +366 -0
- package/dist/builder-eval/index.js.map +1 -0
- package/dist/campaign/index.d.ts +7454 -0
- package/dist/campaign/index.js +272 -0
- package/dist/campaign/index.js.map +1 -0
- package/dist/chunk-3CDFMEMO.js +3878 -0
- package/dist/chunk-3CDFMEMO.js.map +1 -0
- package/dist/chunk-3RF76KTD.js +84 -0
- package/dist/chunk-3RF76KTD.js.map +1 -0
- package/dist/chunk-3XH4Y2SS.js +750 -0
- package/dist/chunk-3XH4Y2SS.js.map +1 -0
- package/dist/chunk-3YYRZDON.js +45 -0
- package/dist/chunk-3YYRZDON.js.map +1 -0
- package/dist/chunk-5BYTIDZ7.js +550 -0
- package/dist/chunk-5BYTIDZ7.js.map +1 -0
- package/dist/chunk-5CVUPHJ4.js +2668 -0
- package/dist/chunk-5CVUPHJ4.js.map +1 -0
- package/dist/chunk-ARU2PZFM.js +312 -0
- package/dist/chunk-ARU2PZFM.js.map +1 -0
- package/dist/chunk-BOD4O7OF.js +40 -0
- package/dist/chunk-BOD4O7OF.js.map +1 -0
- package/dist/chunk-CVJP5TMD.js +766 -0
- package/dist/chunk-CVJP5TMD.js.map +1 -0
- package/dist/chunk-DPZAEKA6.js +880 -0
- package/dist/chunk-DPZAEKA6.js.map +1 -0
- package/dist/chunk-DTJ6QUQB.js +131 -0
- package/dist/chunk-DTJ6QUQB.js.map +1 -0
- package/dist/chunk-GGE4NNQT.js +65 -0
- package/dist/chunk-GGE4NNQT.js.map +1 -0
- package/dist/chunk-H5UD2323.js +286 -0
- package/dist/chunk-H5UD2323.js.map +1 -0
- package/dist/chunk-HHWE3POT.js +94 -0
- package/dist/chunk-HHWE3POT.js.map +1 -0
- package/dist/chunk-HKUCJ437.js +787 -0
- package/dist/chunk-HKUCJ437.js.map +1 -0
- package/dist/chunk-JHCHEVET.js +274 -0
- package/dist/chunk-JHCHEVET.js.map +1 -0
- package/dist/chunk-K4DBDHLK.js +158 -0
- package/dist/chunk-K4DBDHLK.js.map +1 -0
- package/dist/chunk-K6N6XJJX.js +306 -0
- package/dist/chunk-K6N6XJJX.js.map +1 -0
- package/dist/chunk-MA6HLL3S.js +65 -0
- package/dist/chunk-MA6HLL3S.js.map +1 -0
- package/dist/chunk-MAZ26DC7.js +99 -0
- package/dist/chunk-MAZ26DC7.js.map +1 -0
- package/dist/chunk-MOXWMGPC.js +577 -0
- package/dist/chunk-MOXWMGPC.js.map +1 -0
- package/dist/chunk-NJC7U437.js +626 -0
- package/dist/chunk-NJC7U437.js.map +1 -0
- package/dist/chunk-NMN4WGSJ.js +1030 -0
- package/dist/chunk-NMN4WGSJ.js.map +1 -0
- package/dist/chunk-NPCTHQIO.js +91 -0
- package/dist/chunk-NPCTHQIO.js.map +1 -0
- package/dist/chunk-ONWEPEDO.js +57 -0
- package/dist/chunk-ONWEPEDO.js.map +1 -0
- package/dist/chunk-OYZAPX5G.js +1526 -0
- package/dist/chunk-OYZAPX5G.js.map +1 -0
- package/dist/chunk-P5MGQ2FY.js +7958 -0
- package/dist/chunk-P5MGQ2FY.js.map +1 -0
- package/dist/chunk-PC4UYEBM.js +166 -0
- package/dist/chunk-PC4UYEBM.js.map +1 -0
- package/dist/chunk-PJQFMIOX.js +1182 -0
- package/dist/chunk-PJQFMIOX.js.map +1 -0
- package/dist/chunk-PXD6ZFNY.js +1107 -0
- package/dist/chunk-PXD6ZFNY.js.map +1 -0
- package/dist/chunk-PXE2VKMX.js +140 -0
- package/dist/chunk-PXE2VKMX.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-QBRSJK47.js +622 -0
- package/dist/chunk-QBRSJK47.js.map +1 -0
- package/dist/chunk-S3UZOQ5Y.js +328 -0
- package/dist/chunk-S3UZOQ5Y.js.map +1 -0
- package/dist/chunk-SQQED7ZH.js +998 -0
- package/dist/chunk-SQQED7ZH.js.map +1 -0
- package/dist/chunk-SYV364BL.js +1266 -0
- package/dist/chunk-SYV364BL.js.map +1 -0
- package/dist/chunk-T4SQEITX.js +95 -0
- package/dist/chunk-T4SQEITX.js.map +1 -0
- package/dist/chunk-TT4KNT67.js +124 -0
- package/dist/chunk-TT4KNT67.js.map +1 -0
- package/dist/chunk-U5CHZ5M3.js +357 -0
- package/dist/chunk-U5CHZ5M3.js.map +1 -0
- package/dist/chunk-ULOKLHIQ.js +1937 -0
- package/dist/chunk-ULOKLHIQ.js.map +1 -0
- package/dist/chunk-VI2UW6B6.js +162 -0
- package/dist/chunk-VI2UW6B6.js.map +1 -0
- package/dist/chunk-VQMK5FMP.js +247 -0
- package/dist/chunk-VQMK5FMP.js.map +1 -0
- package/dist/chunk-VSMTAMNK.js +53 -0
- package/dist/chunk-VSMTAMNK.js.map +1 -0
- package/dist/chunk-VZSRQ272.js +149 -0
- package/dist/chunk-VZSRQ272.js.map +1 -0
- package/dist/chunk-WW2A73HW.js +159 -0
- package/dist/chunk-WW2A73HW.js.map +1 -0
- package/dist/chunk-X4UCIOTZ.js +136 -0
- package/dist/chunk-X4UCIOTZ.js.map +1 -0
- package/dist/chunk-XJYR7XFV.js +317 -0
- package/dist/chunk-XJYR7XFV.js.map +1 -0
- package/dist/chunk-ZET2UAYW.js +89 -0
- package/dist/chunk-ZET2UAYW.js.map +1 -0
- package/dist/chunk-ZMXDQ4K7.js +870 -0
- package/dist/chunk-ZMXDQ4K7.js.map +1 -0
- package/dist/chunk-ZZUXHH3R.js +99 -0
- package/dist/chunk-ZZUXHH3R.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -0
- package/dist/contract/index.d.ts +4972 -0
- package/dist/contract/index.js +1654 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/control.d.ts +1013 -0
- package/dist/control.js +34 -0
- package/dist/control.js.map +1 -0
- package/dist/fuzz.d.ts +759 -0
- package/dist/fuzz.js +714 -0
- package/dist/fuzz.js.map +1 -0
- package/dist/hosted/index.d.ts +730 -0
- package/dist/hosted/index.js +14 -0
- package/dist/hosted/index.js.map +1 -0
- package/dist/index.d.ts +16780 -0
- package/dist/index.js +12168 -0
- package/dist/index.js.map +1 -0
- package/dist/matrix/index.d.ts +155 -0
- package/dist/matrix/index.js +8 -0
- package/dist/matrix/index.js.map +1 -0
- package/dist/meta-eval/index.d.ts +1030 -0
- package/dist/meta-eval/index.js +417 -0
- package/dist/meta-eval/index.js.map +1 -0
- package/dist/multishot/index.d.ts +579 -0
- package/dist/multishot/index.js +589 -0
- package/dist/multishot/index.js.map +1 -0
- package/dist/openapi.json +992 -0
- package/dist/pipelines/index.d.ts +567 -0
- package/dist/pipelines/index.js +515 -0
- package/dist/pipelines/index.js.map +1 -0
- package/dist/reporting.d.ts +1277 -0
- package/dist/reporting.js +48 -0
- package/dist/reporting.js.map +1 -0
- package/dist/rl.d.ts +4092 -0
- package/dist/rl.js +1724 -0
- package/dist/rl.js.map +1 -0
- package/dist/run-campaign-75RTPVV5.js +14 -0
- package/dist/run-campaign-75RTPVV5.js.map +1 -0
- package/dist/storyboard/index.d.ts +279 -0
- package/dist/storyboard/index.js +767 -0
- package/dist/storyboard/index.js.map +1 -0
- package/dist/trace-attributes.d.ts +52 -0
- package/dist/trace-attributes.js +62 -0
- package/dist/trace-attributes.js.map +1 -0
- package/dist/traces.d.ts +2343 -0
- package/dist/traces.js +249 -0
- package/dist/traces.js.map +1 -0
- package/dist/wire/index.d.ts +1252 -0
- package/dist/wire/index.js +81 -0
- package/dist/wire/index.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cost-ledger.ts"],"sourcesContent":["import { z } from 'zod'\nimport { ValidationError } from './errors'\nimport { estimateCost, isModelPriced, resolveModelPricing } from './metrics'\n\nexport type CostChannel = 'agent' | 'judge' | 'verifier' | 'analyst' | 'driver' | (string & {})\n\nexport interface CostUsage {\n inputTokens: number\n /** Includes reasoning tokens when the provider bills them as output. */\n outputTokens: number\n /** Reasoning-token subset of outputTokens, when reported. */\n reasoningTokens?: number\n /** Prompt tokens served from a provider cache. */\n cachedTokens?: number\n /** Prompt tokens written into a provider cache. */\n cacheWriteTokens?: number\n}\n\ninterface CostCallBase {\n callId: string\n channel: CostChannel\n phase: string\n actor: string\n model: string\n maximumCostUsd?: number\n tags?: Record<string, string>\n timestamp: number\n}\n\nexport interface PendingCostCall extends CostCallBase {\n status: 'pending'\n}\n\nexport interface CostReceipt extends CostCallBase, CostUsage {\n status: 'settled'\n costUsd: number\n costUnknown: boolean\n usageUnknown?: boolean\n pricing?: {\n inputUsdPerThousand: number\n outputUsdPerThousand: number\n }\n actualCostUsd?: number\n error?: string\n}\n\nexport type CostLedgerRecord = PendingCostCall | CostReceipt\n\n/** @deprecated Read-only compatibility shape. New paid work uses `runPaidCall`. */\nexport type CostLedgerEntry = Omit<\n CostReceipt,\n 'status' | 'callId' | 'phase' | 'actor' | 'maximumCostUsd' | 'usageUnknown' | 'pricing' | 'error'\n>\n\nexport interface CostReceiptInput extends CostUsage {\n model: string\n actualCostUsd?: number\n costUnknown?: boolean\n usageUnknown?: boolean\n}\n\nexport type MaximumCharge =\n | { externallyEnforcedMaximumUsd: number }\n | ({ model: string } & CostUsage)\n\nexport interface RunPaidCallInput<T> {\n callId?: string\n channel: CostChannel\n phase: string\n actor: string\n /** Used before a provider receipt exists and on failures without one. */\n model?: string\n tags?: Record<string, string>\n signal?: AbortSignal\n /** Provider-enforced dollar maximum, or maximum priced token usage. Required when capped. */\n maximumCharge?: MaximumCharge\n /** `callId` can be forwarded as the provider's idempotency key. */\n execute(signal: AbortSignal, callId: string): Promise<T>\n receipt(value: T): CostReceiptInput\n receiptFromError?(error: Error): CostReceiptInput | undefined\n}\n\nexport type PaidCallResult<T> =\n | { succeeded: true; callId: string; value: T; receipt: CostReceipt }\n | { succeeded: false; callId?: string; error: Error; receipt?: CostReceipt }\n\nexport interface ChannelRollup {\n channel: CostChannel\n calls: number\n inputTokens: number\n outputTokens: number\n reasoningTokens?: number\n cachedTokens: number\n cacheWriteTokens?: number\n costUsd: number\n unpricedCalls: number\n unknownUsageCalls: number\n}\n\nexport interface CostLedgerSummary {\n totalCalls: number\n pendingCalls: number\n unresolvedCalls: number\n reservedCostUsd: number\n inputTokens: number\n outputTokens: number\n reasoningTokens?: number\n cachedTokens: number\n cacheWriteTokens?: number\n totalCostUsd: number\n byChannel: ChannelRollup[]\n unpricedModels: string[]\n fullyPriced: boolean\n usageComplete: boolean\n accountingComplete: boolean\n incompleteReasons: string[]\n}\n\nexport interface CostLedgerFilter {\n channel?: CostChannel\n phase?: string\n tags?: Record<string, string>\n}\n\nexport interface CostLedgerWaitOptions {\n /** Maximum time to wait for active provider calls. Default 5 seconds. */\n timeoutMs?: number\n}\n\n/** Append-only storage. `append` must atomically reject stale revisions. */\nexport interface CostLedgerPersistence {\n read(): { revision: string; events: string }\n append(expectedRevision: string, event: string): string | undefined\n}\n\nexport interface CostLedgerOptions {\n costCeilingUsd?: number\n persistence?: CostLedgerPersistence\n /** Import already-settled receipts without admitting new paid work. */\n receipts?: readonly CostReceipt[]\n}\n\nexport class CostCeilingReachedError extends ValidationError {\n constructor(\n ceilingUsd: number,\n committedAndReservedUsd: number,\n requestedUsd: number,\n phase: string,\n actor: string,\n ) {\n super(\n `CostLedger: reserving ${requestedUsd} for '${actor}' during '${phase}' would exceed ceiling ${ceilingUsd} with ${committedAndReservedUsd} already committed or reserved`,\n )\n }\n}\n\nexport class CostAccountingIncompleteError extends ValidationError {}\n\nexport class CostReservationExceededError extends ValidationError {\n constructor(actor: string, actualUsd: number, maximumUsd: number) {\n super(\n `CostLedger: '${actor}' charged ${actualUsd}, exceeding its enforced maximum ${maximumUsd}`,\n )\n }\n}\n\nexport class CostCallConflictError extends ValidationError {\n readonly callId?: string\n readonly receipt?: CostReceipt\n\n constructor(\n message: string,\n options: { callId?: string; receipt?: CostReceipt; cause?: unknown } = {},\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause })\n this.callId = options.callId\n this.receipt = options.receipt ? cloneReceipt(options.receipt) : undefined\n }\n}\n\nexport class CostLedgerPersistenceError extends ValidationError {\n readonly callId?: string\n readonly receipt?: CostReceipt\n\n constructor(cause: unknown, callId?: string, receipt?: CostReceipt) {\n super(\n `CostLedger: failed to persist${callId ? ` call '${callId}'` : ''}: ${toError(cause).message}`,\n { cause },\n )\n this.callId = callId\n this.receipt = receipt ? cloneReceipt(receipt) : undefined\n }\n}\n\nexport class CostReceiptCaptureError extends ValidationError {\n readonly callId: string\n readonly receipt?: CostReceipt\n readonly receiptError: Error\n\n constructor(callId: string, cause: unknown, receiptError: unknown, receipt?: CostReceipt) {\n super(`CostLedger: could not capture the provider receipt for call '${callId}'`, { cause })\n this.callId = callId\n this.receipt = receipt ? cloneReceipt(receipt) : undefined\n this.receiptError = toError(receiptError)\n }\n}\n\ninterface CostCallEventV1 {\n version: 1\n record: CostLedgerRecord\n}\n\ninterface CostCallEventV2 {\n version: 2\n record: CostReceipt\n}\n\ninterface CompletedTasksEvent {\n version: 1\n completedTasks: number\n}\n\ninterface CostLimitEvent {\n version: 1\n costCeilingUsd: number\n}\n\ntype CostCallEvent = CostCallEventV1 | CostCallEventV2\ntype CostLedgerEvent = CostCallEvent | CompletedTasksEvent | CostLimitEvent\n\n/** Run-wide paid-call admission, durable call state, receipts, and summaries. */\nexport class CostLedger {\n private readonly records = new Map<string, CostLedgerRecord>()\n private readonly activeCallIds = new Set<string>()\n private readonly lateCallIds = new Set<string>()\n private readonly idleWaiters = new Set<() => void>()\n private completedTasks = 0\n private revision = 'memory'\n private costLimitPersisted = false\n readonly costCeilingUsd?: number\n private readonly persistence?: CostLedgerPersistence\n\n constructor(input?: number | CostLedgerOptions) {\n const options = typeof input === 'number' ? { costCeilingUsd: input } : (input ?? {})\n this.persistence = options.persistence\n if (options.costCeilingUsd !== undefined) {\n assertNonNegative(options.costCeilingUsd, 'costCeilingUsd')\n }\n\n let persistedCostCeilingUsd: number | undefined\n if (this.persistence) {\n let stored: ReturnType<CostLedgerPersistence['read']>\n try {\n stored = this.persistence.read()\n } catch (cause) {\n throw new CostLedgerPersistenceError(cause)\n }\n assertString(stored.revision, 'persistence revision')\n this.revision = stored.revision\n const restored = parseEvents(stored.events)\n for (const record of restored.records) this.records.set(record.callId, record)\n this.completedTasks = restored.completedTasks\n persistedCostCeilingUsd = restored.costCeilingUsd\n }\n\n if (\n options.costCeilingUsd !== undefined &&\n persistedCostCeilingUsd !== undefined &&\n options.costCeilingUsd !== persistedCostCeilingUsd\n ) {\n throw new ValidationError(\n `CostLedger: requested cost ceiling ${options.costCeilingUsd} does not match persisted ceiling ${persistedCostCeilingUsd}`,\n )\n }\n this.costCeilingUsd = persistedCostCeilingUsd ?? options.costCeilingUsd\n this.costLimitPersisted =\n !this.persistence ||\n this.costCeilingUsd === undefined ||\n persistedCostCeilingUsd !== undefined\n\n if (\n this.costCeilingUsd !== undefined &&\n [...this.records.values()].some(\n (record) => record.status === 'pending' && record.maximumCostUsd === undefined,\n )\n ) {\n throw new ValidationError('CostLedger: capped event log contains an unbounded pending call')\n }\n\n if (options.receipts?.length) {\n const imported = options.receipts.map((receipt, index) =>\n parseImportedReceipt(receipt, `imported receipt ${index + 1}`),\n )\n this.ensureCostLimitPersisted()\n for (const receipt of imported) this.appendRecord(receipt)\n }\n }\n\n async runPaidCall<T>(input: RunPaidCallInput<T>): Promise<PaidCallResult<T>> {\n let callId: string | undefined\n let pending: PendingCostCall | undefined\n try {\n callId = resolveCallId(input.callId)\n validateAttribution(input)\n if (input.signal?.aborted) {\n return { succeeded: false, callId, error: abortError(input.signal) }\n }\n if (this.records.has(callId)) {\n return {\n succeeded: false,\n callId,\n error: new CostCallConflictError(`CostLedger: callId '${callId}' already exists`),\n }\n }\n this.ensureCostLimitPersisted(callId)\n\n const summary = this.summary()\n if (summary.unresolvedCalls > 0) {\n return {\n succeeded: false,\n callId,\n error: new CostAccountingIncompleteError(\n `CostLedger: ${summary.unresolvedCalls} unresolved call(s) must be reconciled before new paid work`,\n ),\n }\n }\n\n const maximumCostUsd = this.resolveMaximum(input.maximumCharge)\n if (this.costCeilingUsd !== undefined && this.hasIncompleteSettledCall()) {\n return {\n succeeded: false,\n callId,\n error: new CostAccountingIncompleteError(\n `CostLedger: accounting is incomplete; refusing paid call '${input.actor}' during '${input.phase}'`,\n ),\n }\n }\n if (this.costCeilingUsd !== undefined) {\n const committedAndReserved = summary.totalCostUsd + summary.reservedCostUsd\n if (committedAndReserved + maximumCostUsd! > this.costCeilingUsd) {\n return {\n succeeded: false,\n callId,\n error: new CostCeilingReachedError(\n this.costCeilingUsd,\n committedAndReserved,\n maximumCostUsd!,\n input.phase,\n input.actor,\n ),\n }\n }\n }\n\n pending = {\n status: 'pending',\n callId,\n channel: input.channel,\n phase: input.phase,\n actor: input.actor,\n model: pendingModel(input),\n ...(maximumCostUsd === undefined ? {} : { maximumCostUsd }),\n ...(input.tags ? { tags: { ...input.tags } } : {}),\n timestamp: Date.now(),\n }\n this.appendRecord(pending)\n this.activeCallIds.add(callId)\n } catch (error) {\n return { succeeded: false, ...(callId ? { callId } : {}), error: toError(error) }\n }\n\n try {\n return await this.execute(input, pending)\n } catch (error) {\n return { succeeded: false, callId: pending.callId, error: toError(error) }\n } finally {\n if (!this.lateCallIds.has(pending.callId)) this.releaseActiveCall(pending.callId)\n }\n }\n\n /** Wait until every call started by this ledger has produced a durable outcome. */\n async waitForIdle(options: CostLedgerWaitOptions = {}): Promise<boolean> {\n if (this.activeCallIds.size === 0) return true\n const timeoutMs = options.timeoutMs ?? 5_000\n assertTimeout(timeoutMs, 'waitForIdle.timeoutMs')\n return new Promise<boolean>((resolve) => {\n let timer: ReturnType<typeof setTimeout> | undefined\n const finish = (settled: boolean): void => {\n this.idleWaiters.delete(onIdle)\n if (timer !== undefined) clearTimeout(timer)\n resolve(settled)\n }\n const onIdle = (): void => finish(true)\n this.idleWaiters.add(onIdle)\n timer = setTimeout(() => finish(false), timeoutMs)\n if (this.activeCallIds.size === 0) onIdle()\n })\n }\n\n /** Settle a call left pending by a crashed process after reconciling with the provider. */\n reconcile(\n callId: string,\n observed: CostReceiptInput,\n options: { error?: string } = {},\n ): CostReceipt {\n const pending = [...this.records.values()].find(\n (record): record is PendingCostCall =>\n record.callId === callId && record.status === 'pending',\n )\n if (!pending) throw new CostCallConflictError(`CostLedger: no pending call '${callId}'`)\n if (this.activeCallIds.has(callId)) {\n throw new CostCallConflictError(`CostLedger: call '${callId}' is still active`)\n }\n this.ensureCostLimitPersisted(callId)\n return this.commitReceipt(pending, observed, options.error)\n }\n\n list(filter?: CostLedgerFilter): CostReceipt[] {\n return [...this.records.values()]\n .filter((record): record is CostReceipt => record.status === 'settled')\n .filter((receipt) => matches(receipt, filter))\n .map(cloneReceipt)\n }\n\n summary(filter?: CostLedgerFilter): CostLedgerSummary {\n const records = [...this.records.values()].filter((record) => matches(record, filter))\n const pending = records.filter(\n (record): record is PendingCostCall => record.status === 'pending',\n )\n const receipts = records.filter((record): record is CostReceipt => record.status === 'settled')\n const byChannel = new Map<string, ChannelRollup>()\n const unpriced = new Set<string>()\n const incompleteReasons: string[] = pending.map(\n (record) => `call '${record.callId}' for '${record.actor}' is pending`,\n )\n let inputTokens = 0\n let outputTokens = 0\n let reasoningTokens = 0\n let cachedTokens = 0\n let cacheWriteTokens = 0\n let totalCostUsd = 0\n\n for (const receipt of receipts) {\n inputTokens += receipt.inputTokens\n outputTokens += receipt.outputTokens\n reasoningTokens += receipt.reasoningTokens ?? 0\n cachedTokens += receipt.cachedTokens ?? 0\n cacheWriteTokens += receipt.cacheWriteTokens ?? 0\n totalCostUsd += receipt.costUsd\n if (receipt.costUnknown) {\n unpriced.add(receipt.model)\n incompleteReasons.push(\n receipt.error ?? `cost unknown for '${receipt.actor}' using '${receipt.model}'`,\n )\n }\n if (receipt.usageUnknown) {\n incompleteReasons.push(\n `token usage unknown for '${receipt.actor}' using '${receipt.model}'`,\n )\n }\n if (receipt.maximumCostUsd !== undefined && receipt.costUsd > receipt.maximumCostUsd) {\n incompleteReasons.push(\n `'${receipt.actor}' charged ${receipt.costUsd}, exceeding its enforced maximum ${receipt.maximumCostUsd}`,\n )\n }\n const rollup = byChannel.get(receipt.channel) ?? emptyRollup(receipt.channel)\n rollup.calls += 1\n rollup.inputTokens += receipt.inputTokens\n rollup.outputTokens += receipt.outputTokens\n rollup.reasoningTokens = (rollup.reasoningTokens ?? 0) + (receipt.reasoningTokens ?? 0)\n rollup.cachedTokens += receipt.cachedTokens ?? 0\n rollup.cacheWriteTokens = (rollup.cacheWriteTokens ?? 0) + (receipt.cacheWriteTokens ?? 0)\n rollup.costUsd += receipt.costUsd\n if (receipt.costUnknown) rollup.unpricedCalls += 1\n if (receipt.usageUnknown) rollup.unknownUsageCalls += 1\n byChannel.set(receipt.channel, rollup)\n }\n\n return {\n totalCalls: receipts.length,\n pendingCalls: pending.length,\n unresolvedCalls: pending.filter(\n (record) => !this.activeCallIds.has(record.callId) || this.lateCallIds.has(record.callId),\n ).length,\n reservedCostUsd: pending.reduce((sum, record) => sum + (record.maximumCostUsd ?? 0), 0),\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n cacheWriteTokens,\n totalCostUsd,\n byChannel: [...byChannel.values()].sort((a, b) => a.channel.localeCompare(b.channel)),\n unpricedModels: [...unpriced].sort(),\n fullyPriced: unpriced.size === 0,\n usageComplete: pending.length === 0 && receipts.every((receipt) => !receipt.usageUnknown),\n accountingComplete: incompleteReasons.length === 0,\n incompleteReasons: [...new Set(incompleteReasons)],\n }\n }\n\n markCompleted(count = 1): void {\n if (!Number.isInteger(count) || count < 0) {\n throw new ValidationError(\n `CostLedger.markCompleted: count must be a non-negative integer, got ${count}`,\n )\n }\n if (count === 0) return\n this.ensureCostLimitPersisted()\n this.appendEvent({ version: 1, completedTasks: count })\n this.completedTasks += count\n }\n\n costPerCompletedTask(): number | null {\n return this.completedTasks === 0 ? null : this.summary().totalCostUsd / this.completedTasks\n }\n\n private async execute<T>(\n input: RunPaidCallInput<T>,\n pending: PendingCostCall,\n ): Promise<PaidCallResult<T>> {\n const signal = input.signal ?? new AbortController().signal\n if (signal.aborted) {\n return this.commitOutcome(pending, abortError(signal), {\n model: pending.model,\n inputTokens: 0,\n outputTokens: 0,\n actualCostUsd: 0,\n })\n }\n\n const operation = Promise.resolve().then(() => input.execute(signal, pending.callId))\n const settled = await settle(operation, signal)\n if (settled.kind === 'aborted') {\n this.lateCallIds.add(pending.callId)\n this.captureLateOutcome(input, pending, operation)\n return paidFailure(pending.callId, abortError(signal))\n }\n if (settled.kind === 'error') {\n let observed: CostReceiptInput | undefined\n try {\n observed = input.receiptFromError?.(settled.error)\n } catch (receiptError) {\n return this.captureFailure(pending, settled.error, receiptError)\n }\n return this.commitOutcome(pending, settled.error, observed ?? unknownReceipt(pending.model))\n }\n\n try {\n const receipt = this.commitReceipt(pending, input.receipt(settled.value))\n if (receipt.maximumCostUsd !== undefined && receipt.costUsd > receipt.maximumCostUsd) {\n return paidFailure(\n pending.callId,\n new CostReservationExceededError(pending.actor, receipt.costUsd, receipt.maximumCostUsd),\n receipt,\n )\n }\n return { succeeded: true, callId: pending.callId, value: settled.value, receipt }\n } catch (receiptError) {\n if (\n receiptError instanceof CostLedgerPersistenceError ||\n receiptError instanceof CostCallConflictError\n ) {\n return paidFailure(pending.callId, receiptError)\n }\n return this.captureFailure(pending, receiptError, receiptError)\n }\n }\n\n private captureLateOutcome<T>(\n input: RunPaidCallInput<T>,\n pending: PendingCostCall,\n operation: Promise<T>,\n ): void {\n void operation\n .then(\n (value) => {\n if (this.records.get(pending.callId)?.status !== 'pending') return\n try {\n this.commitReceipt(pending, input.receipt(value))\n } catch {\n // A failed durable settlement leaves the reservation pending and blocks new paid work.\n }\n },\n (cause) => {\n if (this.records.get(pending.callId)?.status !== 'pending') return\n const error = toError(cause)\n try {\n const observed = input.receiptFromError?.(error)\n this.commitReceipt(pending, observed ?? unknownReceipt(pending.model), error.message)\n } catch (receiptError) {\n if (\n receiptError instanceof CostLedgerPersistenceError ||\n receiptError instanceof CostCallConflictError\n ) {\n return\n }\n this.captureFailure(pending, error, receiptError)\n }\n },\n )\n .finally(() => {\n this.lateCallIds.delete(pending.callId)\n this.releaseActiveCall(pending.callId)\n })\n }\n\n private releaseActiveCall(callId: string): void {\n this.activeCallIds.delete(callId)\n if (this.activeCallIds.size > 0) return\n for (const resolve of this.idleWaiters) resolve()\n this.idleWaiters.clear()\n }\n\n private commitOutcome<T>(\n pending: PendingCostCall,\n error: Error,\n observed: CostReceiptInput,\n ): PaidCallResult<T> {\n try {\n const receipt = this.commitReceipt(pending, observed, error.message)\n return paidFailure(pending.callId, error, receipt)\n } catch (receiptError) {\n if (\n receiptError instanceof CostLedgerPersistenceError ||\n receiptError instanceof CostCallConflictError\n ) {\n return paidFailure(pending.callId, receiptError)\n }\n return this.captureFailure(pending, error, receiptError)\n }\n }\n\n private captureFailure<T>(\n pending: PendingCostCall,\n cause: unknown,\n receiptError: unknown,\n ): PaidCallResult<T> {\n try {\n const receipt = this.commitReceipt(\n pending,\n unknownReceipt(pending.model),\n toError(receiptError).message,\n )\n return paidFailure(\n pending.callId,\n new CostReceiptCaptureError(pending.callId, cause, receiptError, receipt),\n receipt,\n )\n } catch (error) {\n const typed = error instanceof Error ? error : toError(error)\n return paidFailure(pending.callId, typed)\n }\n }\n\n private commitReceipt(\n pending: PendingCostCall,\n observed: CostReceiptInput,\n error?: string,\n ): CostReceipt {\n const receipt = buildReceipt(pending, observed, error)\n if (this.records.get(pending.callId)?.status !== 'pending') {\n throw new CostCallConflictError(`CostLedger: call '${pending.callId}' is not pending`)\n }\n this.appendRecord(receipt)\n return cloneReceipt(receipt)\n }\n\n private resolveMaximum(maximum: MaximumCharge | undefined): number | undefined {\n if (!maximum) {\n if (this.costCeilingUsd !== undefined) {\n throw new CostAccountingIncompleteError(\n 'CostLedger: capped paid calls require a hard maximumCharge before execution',\n )\n }\n return undefined\n }\n if ('externallyEnforcedMaximumUsd' in maximum) {\n assertNonNegative(\n maximum.externallyEnforcedMaximumUsd,\n 'maximumCharge.externallyEnforcedMaximumUsd',\n )\n return maximum.externallyEnforcedMaximumUsd\n }\n const priced = costForUsage(maximum.model, maximum)\n if (priced.costUnknown) {\n if (this.costCeilingUsd !== undefined) {\n throw new CostAccountingIncompleteError(\n `CostLedger: cannot reserve unpriced model '${maximum.model}' in a capped run`,\n )\n }\n return undefined\n }\n return priced.costUsd\n }\n\n private hasIncompleteSettledCall(): boolean {\n return [...this.records.values()].some(\n (record) =>\n record.status === 'settled' &&\n (record.costUnknown ||\n record.usageUnknown ||\n (record.maximumCostUsd !== undefined && record.costUsd > record.maximumCostUsd)),\n )\n }\n\n private appendRecord(record: CostLedgerRecord): void {\n const callId = record.callId\n const receipt = record.status === 'settled' ? record : undefined\n validateTransition(this.records, record)\n const event: CostCallEvent =\n record.status === 'settled' &&\n (record.reasoningTokens !== undefined || record.cacheWriteTokens !== undefined)\n ? { version: 2, record: cloneReceipt(record) }\n : { version: 1, record: cloneRecord(record) }\n this.appendEvent(event, callId, receipt)\n this.records.set(callId, cloneRecord(record))\n }\n\n private ensureCostLimitPersisted(callId?: string): void {\n if (this.costLimitPersisted || this.costCeilingUsd === undefined) return\n this.appendEvent({ version: 1, costCeilingUsd: this.costCeilingUsd }, callId)\n this.costLimitPersisted = true\n }\n\n private appendEvent(event: CostLedgerEvent, callId?: string, receipt?: CostReceipt): void {\n try {\n if (this.persistence) {\n const nextRevision = this.persistence.append(this.revision, `${JSON.stringify(event)}\\n`)\n if (nextRevision === undefined) {\n throw new CostCallConflictError(\n `CostLedger: persisted revision changed while writing call '${callId}'`,\n { callId, receipt },\n )\n }\n assertString(nextRevision, 'persistence revision')\n this.revision = nextRevision\n }\n } catch (cause) {\n if (cause instanceof CostCallConflictError) throw cause\n throw new CostLedgerPersistenceError(cause, callId, receipt)\n }\n }\n}\n\n/** Public callback surface for a shared cost ledger.\n *\n * Declaration bundles may expose this type through multiple package subpaths.\n * Keeping callback contracts structural lets those subpaths compose while the\n * concrete {@link CostLedger} retains its private durable state.\n */\nexport type CostLedgerHandle = Pick<CostLedger, Exclude<keyof CostLedger, 'waitForIdle'>> &\n Partial<Pick<CostLedger, 'waitForIdle'>>\n\n/** Return the canonical pricing-table key, or null when the model is unpriced. */\nexport function modelPriceKey(model: string): string | null {\n return isModelPriced(model) ? model : null\n}\n\nexport interface CostResult {\n costUsd: number\n costUnknown: boolean\n}\n\nexport function costForUsage(model: string, usage: CostUsage): CostResult {\n assertUsage(usage)\n if (!resolveModelPricing(model)) return { costUsd: 0, costUnknown: true }\n return {\n costUsd: estimateCost(\n usage.inputTokens + (usage.cachedTokens ?? 0) + (usage.cacheWriteTokens ?? 0),\n usage.outputTokens,\n model,\n ),\n costUnknown: false,\n }\n}\n\ntype Settled<T> =\n | { kind: 'value'; value: T }\n | { kind: 'error'; error: Error }\n | { kind: 'aborted' }\n\nasync function settle<T>(promise: Promise<T>, signal: AbortSignal): Promise<Settled<T>> {\n return await new Promise((resolve) => {\n let done = false\n const finish = (value: Settled<T>): void => {\n if (done) return\n done = true\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n }\n const onAbort = () => finish({ kind: 'aborted' })\n signal.addEventListener('abort', onAbort, { once: true })\n if (signal.aborted) onAbort()\n promise.then(\n (value) => finish({ kind: 'value', value }),\n (error) => finish({ kind: 'error', error: toError(error) }),\n )\n })\n}\n\nfunction buildReceipt(\n pending: PendingCostCall,\n observed: CostReceiptInput,\n error?: string,\n): CostReceipt {\n assertUsage(observed)\n assertString(observed.model, 'receipt.model')\n const estimated = costForUsage(observed.model, observed)\n const hasActual = observed.actualCostUsd !== undefined\n if (hasActual && observed.costUnknown === true) {\n throw new ValidationError(\n 'CostLedger: a receipt cannot have both actualCostUsd and costUnknown=true',\n )\n }\n if (hasActual) assertNonNegative(observed.actualCostUsd!, 'actualCostUsd')\n const usageUnknown = observed.usageUnknown === true\n const costUnknown =\n observed.costUnknown === true || (!hasActual && (usageUnknown || estimated.costUnknown))\n const resolvedPricing = !hasActual && !costUnknown ? resolveModelPricing(observed.model) : null\n return parseReceipt(\n {\n status: 'settled',\n callId: pending.callId,\n channel: pending.channel,\n phase: pending.phase,\n actor: pending.actor,\n model: observed.model,\n inputTokens: observed.inputTokens,\n outputTokens: observed.outputTokens,\n ...(observed.reasoningTokens === undefined\n ? {}\n : { reasoningTokens: observed.reasoningTokens }),\n ...(observed.cachedTokens === undefined ? {} : { cachedTokens: observed.cachedTokens }),\n ...(observed.cacheWriteTokens === undefined\n ? {}\n : { cacheWriteTokens: observed.cacheWriteTokens }),\n costUsd: costUnknown ? 0 : hasActual ? observed.actualCostUsd! : estimated.costUsd,\n costUnknown,\n usageUnknown,\n ...(resolvedPricing\n ? {\n pricing: {\n inputUsdPerThousand: resolvedPricing.input,\n outputUsdPerThousand: resolvedPricing.output,\n },\n }\n : {}),\n ...(hasActual ? { actualCostUsd: observed.actualCostUsd } : {}),\n ...(pending.maximumCostUsd === undefined ? {} : { maximumCostUsd: pending.maximumCostUsd }),\n ...(error ? { error } : {}),\n ...(pending.tags ? { tags: { ...pending.tags } } : {}),\n timestamp: pending.timestamp,\n },\n 'provider receipt',\n )\n}\n\nconst NonEmptyString = z.string().refine((value) => value.trim().length > 0, 'must be non-empty')\nconst TokenCount = z.number().int().nonnegative().finite()\nconst NonNegative = z.number().nonnegative().finite()\nconst Positive = z.number().positive().finite()\nconst Tags = z.record(NonEmptyString, z.string())\nconst CostPricingSchema = z.strictObject({\n inputUsdPerThousand: Positive,\n outputUsdPerThousand: Positive,\n})\nconst CostCallBaseShape = {\n callId: NonEmptyString,\n channel: NonEmptyString,\n phase: NonEmptyString,\n actor: NonEmptyString,\n model: NonEmptyString,\n maximumCostUsd: NonNegative.optional(),\n tags: Tags.optional(),\n timestamp: NonNegative,\n}\nconst PendingCostCallSchema = z.strictObject({\n status: z.literal('pending'),\n ...CostCallBaseShape,\n})\nconst CostReceiptBaseShape = {\n status: z.literal('settled'),\n ...CostCallBaseShape,\n inputTokens: TokenCount,\n outputTokens: TokenCount,\n cachedTokens: TokenCount.optional(),\n costUsd: NonNegative,\n costUnknown: z.boolean(),\n usageUnknown: z.boolean().default(false),\n pricing: CostPricingSchema.optional(),\n actualCostUsd: NonNegative.optional(),\n error: z.string().optional(),\n}\nconst LegacyCostReceiptSchema = z\n .strictObject(CostReceiptBaseShape)\n .superRefine((receipt, ctx) => validateCostReceipt(receipt, ctx))\nconst CostReceiptSchema = z\n .strictObject({\n ...CostReceiptBaseShape,\n reasoningTokens: TokenCount.optional(),\n cacheWriteTokens: TokenCount.optional(),\n })\n .superRefine((receipt, ctx) => validateCostReceipt(receipt, ctx))\n\nfunction validateCostReceipt(\n receipt: CostUsage & {\n costUsd: number\n costUnknown: boolean\n usageUnknown: boolean\n pricing?: NonNullable<CostReceipt['pricing']>\n actualCostUsd?: number\n },\n ctx: z.RefinementCtx,\n): void {\n if (receipt.reasoningTokens !== undefined && receipt.reasoningTokens > receipt.outputTokens) {\n ctx.addIssue({ code: 'custom', message: 'reasoningTokens must not exceed outputTokens' })\n }\n\n if (receipt.actualCostUsd !== undefined) {\n if (receipt.costUnknown || receipt.costUsd !== receipt.actualCostUsd) {\n ctx.addIssue({ code: 'custom', message: 'actual cost must be known and equal costUsd' })\n }\n if (receipt.pricing !== undefined) {\n ctx.addIssue({ code: 'custom', message: 'actual cost must not include estimated pricing' })\n }\n return\n }\n\n if (receipt.costUnknown) {\n if (receipt.costUsd !== 0) {\n ctx.addIssue({ code: 'custom', message: 'unknown cost must have costUsd 0' })\n }\n if (receipt.pricing !== undefined) {\n ctx.addIssue({ code: 'custom', message: 'unknown cost must not include estimated pricing' })\n }\n return\n }\n\n if (receipt.usageUnknown) {\n ctx.addIssue({ code: 'custom', message: 'known estimated cost requires known usage' })\n }\n if (!receipt.pricing) {\n ctx.addIssue({ code: 'custom', message: 'known estimated cost requires a pricing snapshot' })\n return\n }\n\n const expected = costFromPricing(receipt, receipt.pricing)\n if (receipt.costUsd !== expected) {\n ctx.addIssue({\n code: 'custom',\n message: `estimated cost ${receipt.costUsd} does not match pricing snapshot ${expected}`,\n })\n }\n}\n\nconst CostLedgerEventSchema = z.union([\n z.strictObject({\n version: z.literal(1),\n record: z.union([PendingCostCallSchema, LegacyCostReceiptSchema]),\n }),\n z.strictObject({\n version: z.literal(2),\n record: CostReceiptSchema,\n }),\n z.strictObject({\n version: z.literal(1),\n completedTasks: TokenCount,\n }),\n z.strictObject({\n version: z.literal(1),\n costCeilingUsd: NonNegative,\n }),\n])\n\nfunction parseEvents(serialized: string): {\n records: CostLedgerRecord[]\n completedTasks: number\n costCeilingUsd?: number\n} {\n const records = new Map<string, CostLedgerRecord>()\n let completedTasks = 0\n let costCeilingUsd: number | undefined\n let lineNumber = 0\n try {\n for (const line of serialized.split('\\n')) {\n if (!line.trim()) continue\n lineNumber += 1\n const event = CostLedgerEventSchema.parse(JSON.parse(line)) as CostLedgerEvent\n if ('record' in event) {\n const record = event.record\n validateTransition(records, record)\n records.set(record.callId, cloneRecord(record))\n } else if ('completedTasks' in event) {\n completedTasks += event.completedTasks\n if (!Number.isSafeInteger(completedTasks)) {\n throw new ValidationError('CostLedger: completed task count exceeds safe integer range')\n }\n } else {\n if (costCeilingUsd !== undefined) {\n throw new ValidationError('CostLedger: duplicate persisted cost ceiling')\n }\n costCeilingUsd = event.costCeilingUsd\n }\n }\n return {\n records: [...records.values()],\n completedTasks,\n ...(costCeilingUsd === undefined ? {} : { costCeilingUsd }),\n }\n } catch (cause) {\n throw new ValidationError(\n `CostLedger: invalid persisted event ${lineNumber || 1}: ${validationMessage(cause)}`,\n { cause },\n )\n }\n}\n\nfunction validateTransition(\n records: ReadonlyMap<string, CostLedgerRecord>,\n record: CostLedgerRecord,\n): void {\n const current = records.get(record.callId)\n if (!current) return\n if (record.status === 'pending' || current.status === 'settled') {\n throw new CostCallConflictError(`CostLedger: duplicate callId '${record.callId}'`)\n }\n if (!sameAttribution(current, record)) {\n throw new ValidationError(`CostLedger: receipt attribution changed for call '${record.callId}'`)\n }\n}\n\nfunction sameAttribution(before: CostCallBase, after: CostCallBase): boolean {\n return (\n before.channel === after.channel &&\n before.phase === after.phase &&\n before.actor === after.actor &&\n before.maximumCostUsd === after.maximumCostUsd &&\n before.timestamp === after.timestamp &&\n JSON.stringify(before.tags ?? {}) === JSON.stringify(after.tags ?? {})\n )\n}\n\nfunction parseReceipt(value: unknown, path: string): CostReceipt {\n try {\n return CostReceiptSchema.parse(value) as CostReceipt\n } catch (cause) {\n throw new ValidationError(`CostLedger: invalid ${path}: ${validationMessage(cause)}`, { cause })\n }\n}\n\nfunction parseImportedReceipt(value: unknown, path: string): CostReceipt {\n if (typeof value !== 'object' || value === null) return parseReceipt(value, path)\n const candidate = { ...value } as Record<string, unknown>\n if (\n candidate.status === 'settled' &&\n candidate.actualCostUsd === undefined &&\n candidate.costUnknown === false &&\n candidate.pricing === undefined &&\n typeof candidate.model === 'string'\n ) {\n const pricing = resolveModelPricing(candidate.model)\n if (pricing) {\n candidate.pricing = {\n inputUsdPerThousand: pricing.input,\n outputUsdPerThousand: pricing.output,\n }\n }\n }\n return parseReceipt(candidate, path)\n}\n\nfunction validateAttribution(\n input: Pick<RunPaidCallInput<unknown>, 'channel' | 'phase' | 'actor' | 'model' | 'tags'>,\n): void {\n assertString(input.channel, 'channel')\n assertString(input.phase, 'phase')\n assertString(input.actor, 'actor')\n if (input.model !== undefined) assertString(input.model, 'model')\n if (input.tags !== undefined) {\n const parsed = Tags.safeParse(input.tags)\n if (!parsed.success)\n throw new ValidationError(`CostLedger: invalid tags: ${parsed.error.message}`)\n }\n}\n\nfunction matches(record: CostCallBase, filter: CostLedgerFilter | undefined): boolean {\n if (!filter) return true\n if (filter.channel !== undefined && record.channel !== filter.channel) return false\n if (filter.phase !== undefined && record.phase !== filter.phase) return false\n return Object.entries(filter.tags ?? {}).every(([key, value]) => record.tags?.[key] === value)\n}\n\nfunction cloneRecord(record: CostLedgerRecord): CostLedgerRecord {\n if (record.status === 'settled') return cloneReceipt(record)\n const { tags, ...rest } = record\n return { ...rest, ...(tags ? { tags: { ...tags } } : {}) }\n}\n\nfunction cloneReceipt(receipt: CostReceipt): CostReceipt {\n const { pricing, tags, ...rest } = receipt\n return {\n ...rest,\n ...(tags ? { tags: { ...tags } } : {}),\n ...(pricing ? { pricing: { ...pricing } } : {}),\n }\n}\n\nfunction costFromPricing(usage: CostUsage, pricing: NonNullable<CostReceipt['pricing']>): number {\n return (\n ((usage.inputTokens + (usage.cachedTokens ?? 0) + (usage.cacheWriteTokens ?? 0)) / 1000) *\n pricing.inputUsdPerThousand +\n (usage.outputTokens / 1000) * pricing.outputUsdPerThousand\n )\n}\n\nfunction emptyRollup(channel: CostChannel): ChannelRollup {\n return {\n channel,\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n cachedTokens: 0,\n cacheWriteTokens: 0,\n costUsd: 0,\n unpricedCalls: 0,\n unknownUsageCalls: 0,\n }\n}\n\nfunction pendingModel(input: RunPaidCallInput<unknown>): string {\n if (input.model) return input.model\n if (input.maximumCharge && 'model' in input.maximumCharge) return input.maximumCharge.model\n return 'unknown'\n}\n\nfunction unknownReceipt(model: string): CostReceiptInput {\n return { model, inputTokens: 0, outputTokens: 0, costUnknown: true, usageUnknown: true }\n}\n\nfunction resolveCallId(input: string | undefined): string {\n if (input !== undefined) {\n assertString(input, 'callId')\n return input\n }\n if (typeof globalThis.crypto?.randomUUID !== 'function') {\n throw new ValidationError('CostLedger: crypto.randomUUID is required when callId is omitted')\n }\n return globalThis.crypto.randomUUID()\n}\n\nfunction abortError(signal: AbortSignal): Error {\n const reason = (signal as { reason?: unknown }).reason\n if (reason instanceof Error) return reason\n const error = new Error('CostLedger: paid call aborted')\n error.name = 'AbortError'\n return error\n}\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\nfunction paidFailure<T>(callId: string, error: Error, receipt?: CostReceipt): PaidCallResult<T> {\n return {\n succeeded: false,\n callId,\n error,\n ...(receipt ? { receipt: cloneReceipt(receipt) } : {}),\n }\n}\n\nfunction validationMessage(cause: unknown): string {\n return cause instanceof z.ZodError ? z.prettifyError(cause) : toError(cause).message\n}\n\nfunction assertUsage(usage: CostUsage): void {\n assertTokenCount(usage.inputTokens, 'inputTokens')\n assertTokenCount(usage.outputTokens, 'outputTokens')\n if (usage.reasoningTokens !== undefined) {\n assertTokenCount(usage.reasoningTokens, 'reasoningTokens')\n if (usage.reasoningTokens > usage.outputTokens) {\n throw new ValidationError('CostLedger: reasoningTokens must not exceed outputTokens')\n }\n }\n if (usage.cachedTokens !== undefined) assertTokenCount(usage.cachedTokens, 'cachedTokens')\n if (usage.cacheWriteTokens !== undefined) {\n assertTokenCount(usage.cacheWriteTokens, 'cacheWriteTokens')\n }\n}\n\nfunction assertTokenCount(value: unknown, name: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new ValidationError(\n `CostLedger: ${name} must be a non-negative integer, got ${String(value)}`,\n )\n }\n}\n\nfunction assertNonNegative(value: unknown, name: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {\n throw new ValidationError(\n `CostLedger: ${name} must be a non-negative finite number, got ${String(value)}`,\n )\n }\n}\n\nfunction assertTimeout(value: unknown, name: string): asserts value is number {\n if (\n typeof value !== 'number' ||\n !Number.isSafeInteger(value) ||\n value < 0 ||\n value > 2_147_483_647\n ) {\n throw new ValidationError(\n `CostLedger: ${name} must be a non-negative safe integer no greater than 2147483647, got ${String(value)}`,\n )\n }\n}\n\nfunction assertString(value: unknown, name: string): asserts value is string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new ValidationError(`CostLedger: ${name} must be a non-empty string`)\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// src/hosted/types.ts
|
|
2
|
+
var HOSTED_WIRE_VERSION = "2026-05-26.v1";
|
|
3
|
+
|
|
4
|
+
// src/hosted/client.ts
|
|
5
|
+
function sleep(ms) {
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
const t = setTimeout(resolve, ms);
|
|
8
|
+
if (typeof t.unref === "function")
|
|
9
|
+
t.unref();
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
async function post(tenant, path, body, opts = {}) {
|
|
13
|
+
const timeoutMs = tenant.timeoutMs ?? 3e4;
|
|
14
|
+
const maxRetries = tenant.retries ?? 2;
|
|
15
|
+
const f = tenant.fetchImpl ?? ((...args) => fetch(...args));
|
|
16
|
+
const base = tenant.endpoint.replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
17
|
+
const url = `${base}${path}`;
|
|
18
|
+
let lastError;
|
|
19
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
20
|
+
const ourTimeout = AbortSignal.timeout(timeoutMs);
|
|
21
|
+
const combinedSignal = opts.signal ? AbortSignal.any([opts.signal, ourTimeout]) : ourTimeout;
|
|
22
|
+
try {
|
|
23
|
+
const headers = {
|
|
24
|
+
"content-type": "application/json",
|
|
25
|
+
authorization: `Bearer ${tenant.apiKey}`,
|
|
26
|
+
"x-tangle-tenant-id": tenant.tenantId,
|
|
27
|
+
"x-tangle-wire-version": HOSTED_WIRE_VERSION
|
|
28
|
+
};
|
|
29
|
+
if (opts.idempotencyKey) headers["idempotency-key"] = opts.idempotencyKey;
|
|
30
|
+
const res = await f(url, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers,
|
|
33
|
+
body: JSON.stringify(body),
|
|
34
|
+
signal: combinedSignal
|
|
35
|
+
});
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
const retryable = res.status >= 500 || res.status === 408 || res.status === 429;
|
|
38
|
+
if (!retryable || attempt === maxRetries) {
|
|
39
|
+
const text = await res.text().catch(() => "");
|
|
40
|
+
throw new Error(`hosted ingest ${url} failed (${res.status}): ${text.slice(0, 500)}`);
|
|
41
|
+
}
|
|
42
|
+
await sleep(2 ** attempt * 200 + Math.random() * 200);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
return await res.json();
|
|
46
|
+
} catch (err) {
|
|
47
|
+
if (opts.signal?.aborted) throw err;
|
|
48
|
+
lastError = err;
|
|
49
|
+
if (attempt === maxRetries) throw err;
|
|
50
|
+
await sleep(2 ** attempt * 200 + Math.random() * 200);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
throw lastError ?? new Error("hosted ingest exhausted retries");
|
|
54
|
+
}
|
|
55
|
+
function createHostedClient(tenant) {
|
|
56
|
+
return {
|
|
57
|
+
tenant,
|
|
58
|
+
wireVersion: HOSTED_WIRE_VERSION,
|
|
59
|
+
async ingestEvalRun(event, idempotencyKey) {
|
|
60
|
+
return this.ingestEvalRuns([event], idempotencyKey);
|
|
61
|
+
},
|
|
62
|
+
async ingestEvalRuns(events, idempotencyKey) {
|
|
63
|
+
const body = { wireVersion: HOSTED_WIRE_VERSION, events };
|
|
64
|
+
return post(tenant, "/v1/ingest/eval-runs", body, {
|
|
65
|
+
idempotencyKey
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
async ingestTraces(spans, idempotencyKey) {
|
|
69
|
+
const body = { wireVersion: HOSTED_WIRE_VERSION, spans };
|
|
70
|
+
return post(tenant, "/v1/ingest/traces", body, {
|
|
71
|
+
idempotencyKey
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function hostedTenantFromEnv(overrides = {}) {
|
|
77
|
+
const env = overrides.env ?? process.env;
|
|
78
|
+
const endpoint = (overrides.endpoint ?? env.TANGLE_INGEST_URL ?? env.TANGLE_ORCHESTRATOR_URL)?.trim();
|
|
79
|
+
const apiKey = (overrides.apiKey ?? env.TANGLE_INGEST_API_KEY ?? env.TANGLE_API_KEY)?.trim();
|
|
80
|
+
const tenantId = (overrides.tenantId ?? env.TANGLE_TENANT_ID)?.trim();
|
|
81
|
+
if (!endpoint || !apiKey || !tenantId) return void 0;
|
|
82
|
+
const tenant = { endpoint: endpoint.replace(/\/+$/, ""), apiKey, tenantId };
|
|
83
|
+
if (overrides.fetchImpl) tenant.fetchImpl = overrides.fetchImpl;
|
|
84
|
+
if (overrides.timeoutMs !== void 0) tenant.timeoutMs = overrides.timeoutMs;
|
|
85
|
+
if (overrides.retries !== void 0) tenant.retries = overrides.retries;
|
|
86
|
+
return tenant;
|
|
87
|
+
}
|
|
88
|
+
function hostedClientFromEnv(overrides = {}) {
|
|
89
|
+
const tenant = hostedTenantFromEnv(overrides);
|
|
90
|
+
return tenant ? createHostedClient(tenant) : void 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
HOSTED_WIRE_VERSION,
|
|
95
|
+
createHostedClient,
|
|
96
|
+
hostedTenantFromEnv,
|
|
97
|
+
hostedClientFromEnv
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=chunk-ZZUXHH3R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hosted/types.ts","../src/hosted/client.ts"],"sourcesContent":["/**\n * # Hosted-tier wire format — the schema that EVERY orchestrator (ours,\n * a partner's self-hosted one, a future open implementation) must accept.\n *\n * **Stability:** every type in this file is committed under semver. New\n * minors only ADD optional fields. Breaking changes mean a major bump\n * (`HostedWireVersion` literal increment).\n *\n * The wire format is two event streams in one transport:\n *\n * 1. **Eval-run events** (`POST /v1/ingest/eval-runs`). Posted when a\n * campaign / improvement-loop completes (or per-generation if\n * streaming). Carries the structured result + per-cell scores +\n * surface diffs the orchestrator stores for the dashboard.\n *\n * 2. **Trace spans** (`POST /v1/ingest/traces`). Standard OTLP-shaped\n * spans with a few additional attributes so the orchestrator can\n * pivot from eval-run → underlying execution. Compatible with any\n * OTel collector.\n *\n * Both endpoints are authenticated with a bearer token + a tenant id\n * header. Tenants isolate everything downstream of ingest; no tenant\n * ever sees another tenant's data.\n */\n\nimport type { GateDecision, MutableSurface } from '../campaign/types'\nimport type { InsightReport } from '../contract/insight-report'\n\n// re-export so wire-format consumers can import the optional payload type\n// from `@tangle-network/agent-eval/hosted` without reaching into /contract.\nexport type { InsightReport } from '../contract/insight-report'\n\nexport const HOSTED_WIRE_VERSION = '2026-05-26.v1' as const\nexport type HostedWireVersion = typeof HOSTED_WIRE_VERSION\n\n// ── Transport headers ───────────────────────────────────────────────\n\n/** Every ingest request carries these. */\nexport interface HostedIngestHeaders {\n /** Bearer token. The orchestrator validates against the tenant key. */\n authorization: `Bearer ${string}`\n /** Stable tenant id (the orchestrator-side primary key for the tenant). */\n 'x-tangle-tenant-id': string\n /** Wire-version pin so the server can reject incompatible payloads. */\n 'x-tangle-wire-version': HostedWireVersion\n /** Optional idempotency key for retry-safe ingest. */\n 'idempotency-key'?: string\n}\n\n// ── Eval-run event ──────────────────────────────────────────────────\n\n/** Lifecycle stages of an eval-run as the substrate reports them. */\nexport type EvalRunStatus =\n | 'started'\n | 'baseline-complete'\n | 'generation-complete'\n | 'gate-decided'\n | 'finished'\n | 'errored'\n\nexport interface EvalRunCellScore {\n /** Stable scenario id from the consumer's scenario set. */\n scenarioId: string\n /** Repetition index when reps > 1; 0 for the default. */\n rep: number\n /** Composite score across all judges + dimensions for this cell. */\n compositeMean: number\n /** Per-judge → per-dimension scores; null where the judge did not run. */\n dimensions: Record<string, Record<string, number>>\n /** Per-cell error message if the dispatch threw. Null on success. */\n errorMessage?: string\n}\n\nexport interface EvalRunGenerationSnapshot {\n /** Generation index. 0 is baseline. */\n index: number\n /** Candidate surface fingerprint (stable hash) — pivot key into the\n * trace stream to fetch the underlying execution. */\n surfaceHash: string\n /** The candidate surface itself. May be omitted to avoid PII when the\n * consumer prefers not to ship verbatim prompts. */\n surface?: MutableSurface\n /** Per-cell scores for this generation. */\n cells: EvalRunCellScore[]\n /** Aggregate composite mean across all cells in this generation. */\n compositeMean: number\n /** Total $ spent across this generation. */\n costUsd: number\n /** Wall-clock duration of this generation. */\n durationMs: number\n}\n\n/**\n * The top-level eval-run event. One ingest call per logical eval-run;\n * generations stream in incrementally via repeated calls with the same\n * `runId`. The orchestrator deduplicates by `(runId, generation.index)`.\n */\nexport interface EvalRunEvent {\n /** Stable run id (the substrate's `runId`). UUID or substrate-generated. */\n runId: string\n /** Where this run was happening — derived from `RunCampaignOptions.runDir`. */\n runDir: string\n /** ISO-8601 timestamp the substrate recorded the event. */\n timestamp: string\n /** Lifecycle stage this event represents. */\n status: EvalRunStatus\n /** Free-form consumer tags (env, branch, model id, etc.). Searchable. */\n labels: Record<string, string>\n /** Baseline campaign snapshot. Present when status >= baseline-complete. */\n baseline?: EvalRunGenerationSnapshot\n /** Per-generation snapshots. Streams in; orchestrator appends. */\n generations: EvalRunGenerationSnapshot[]\n /** Final gate decision. Present when status >= gate-decided. */\n gateDecision?: GateDecision\n /** Held-out lift = winner-on-holdout - baseline-on-holdout. */\n holdoutLift?: number\n /** Total $ spent across baseline + every generation. */\n totalCostUsd: number\n /** Total wall-clock duration. */\n totalDurationMs: number\n /** Error message if status === 'errored'. */\n errorMessage?: string\n /** Rigor packet emitted alongside the run — distributional summary,\n * paired-bootstrap lift CI, judge stats, inter-rater agreement,\n * contamination check, failure clusters (when an analyst is wired),\n * outcome correlation (when downstream signal is supplied), and the\n * recommendations the dashboard surfaces verbatim. Additive; older\n * clients that don't know about this field continue to work. */\n insightReport?: InsightReport\n}\n\n// ── Trace span event ────────────────────────────────────────────────\n\n/**\n * OTel-shape span with a few additional attributes for eval-run pivoting.\n * Compatible with any OTLP collector — `name`, `traceId`, `spanId`,\n * `startTimeUnixNano`, `endTimeUnixNano`, `attributes` are stock OTel.\n */\nexport interface TraceSpanEvent {\n traceId: string\n spanId: string\n parentSpanId?: string\n name: string\n startTimeUnixNano: number\n endTimeUnixNano: number\n attributes: Record<string, string | number | boolean>\n events?: Array<{\n timeUnixNano: number\n name: string\n attributes?: Record<string, string | number | boolean>\n }>\n status?: { code: 'OK' | 'ERROR' | 'UNSET'; message?: string }\n /** Pivot back into the eval-run stream. */\n 'tangle.runId'?: string\n /** Pivot to the specific generation. */\n 'tangle.generation'?: number\n /** Pivot to the specific cell. */\n 'tangle.cellId'?: string\n /** Pivot to the specific scenario. */\n 'tangle.scenarioId'?: string\n}\n\n// ── Ingest request bodies ───────────────────────────────────────────\n\nexport interface IngestEvalRunsRequest {\n wireVersion: HostedWireVersion\n events: EvalRunEvent[]\n}\n\nexport interface IngestTracesRequest {\n wireVersion: HostedWireVersion\n spans: TraceSpanEvent[]\n}\n\nexport interface IngestResponse {\n /** Accepted events / spans count. */\n accepted: number\n /** Rejected events with reasons (validation failures, dup idempotency key, etc.). */\n rejected: Array<{ index: number; reason: string }>\n}\n","/**\n * # Hosted-tier ingest client.\n *\n * Ships eval-run events + trace spans to any orchestrator (ours, a\n * partner's self-hosted one, or a future open implementation) that\n * speaks the wire format in `./types.ts`.\n *\n * Three modes:\n * - **Ours:** point at `https://orchestrator.tangle.tools` (the host root —\n * the client appends the versioned `/v1/ingest/...` path itself; a trailing\n * `/v1` on the endpoint is tolerated and normalized away). We handle ingest\n * + storage + dashboard.\n * - **Self-hosted:** point at whatever URL runs the reference receiver\n * from `examples/hosted-ingest-server/`.\n * - **Off (default):** when `hostedTenant` is unset, nothing is sent.\n * Everything stays local.\n */\n\nimport {\n type EvalRunEvent,\n HOSTED_WIRE_VERSION,\n type HostedWireVersion,\n type IngestEvalRunsRequest,\n type IngestResponse,\n type IngestTracesRequest,\n type TraceSpanEvent,\n} from './types'\n\nexport interface HostedTenant {\n /** Orchestrator endpoint base URL (no trailing slash). Required. */\n endpoint: string\n /** Bearer token issued by the orchestrator. Required. */\n apiKey: string\n /** Tenant id — the orchestrator's primary key for this consumer. Required. */\n tenantId: string\n /** Optional `fetch` override (auth wrappers, custom agent, test mocks). */\n fetchImpl?: typeof fetch\n /** Per-call timeout in ms. Default 30s. */\n timeoutMs?: number\n /** Retries on 5xx / network errors. Default 2. */\n retries?: number\n}\n\nexport interface HostedClient {\n ingestEvalRun(event: EvalRunEvent, idempotencyKey?: string): Promise<IngestResponse>\n ingestEvalRuns(events: EvalRunEvent[], idempotencyKey?: string): Promise<IngestResponse>\n ingestTraces(spans: TraceSpanEvent[], idempotencyKey?: string): Promise<IngestResponse>\n readonly tenant: HostedTenant\n readonly wireVersion: HostedWireVersion\n}\n\ninterface RequestOptions {\n idempotencyKey?: string\n signal?: AbortSignal\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const t = setTimeout(resolve, ms)\n if (typeof (t as { unref?: () => void }).unref === 'function')\n (t as { unref: () => void }).unref()\n })\n}\n\nasync function post<TReq, TRes>(\n tenant: HostedTenant,\n path: string,\n body: TReq,\n opts: RequestOptions = {},\n): Promise<TRes> {\n const timeoutMs = tenant.timeoutMs ?? 30_000\n const maxRetries = tenant.retries ?? 2\n const f: typeof fetch = tenant.fetchImpl ?? ((...args) => fetch(...args))\n // `path` already carries the `/v1` version prefix (e.g. `/v1/ingest/eval-runs`).\n // Strip a trailing slash AND a trailing `/v1` from the endpoint so a base of\n // either `https://host` or `https://host/v1` resolves to the same correct URL\n // — callers routinely pass the versioned base and would otherwise hit\n // `/v1/v1/ingest/...` (404).\n const base = tenant.endpoint.replace(/\\/+$/, '').replace(/\\/v1$/, '')\n const url = `${base}${path}`\n\n let lastError: unknown\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const ourTimeout = AbortSignal.timeout(timeoutMs)\n const combinedSignal = opts.signal ? AbortSignal.any([opts.signal, ourTimeout]) : ourTimeout\n try {\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n authorization: `Bearer ${tenant.apiKey}`,\n 'x-tangle-tenant-id': tenant.tenantId,\n 'x-tangle-wire-version': HOSTED_WIRE_VERSION,\n }\n if (opts.idempotencyKey) headers['idempotency-key'] = opts.idempotencyKey\n\n const res = await f(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: combinedSignal,\n })\n if (!res.ok) {\n const retryable = res.status >= 500 || res.status === 408 || res.status === 429\n if (!retryable || attempt === maxRetries) {\n const text = await res.text().catch(() => '')\n throw new Error(`hosted ingest ${url} failed (${res.status}): ${text.slice(0, 500)}`)\n }\n await sleep(2 ** attempt * 200 + Math.random() * 200)\n continue\n }\n return (await res.json()) as TRes\n } catch (err) {\n if (opts.signal?.aborted) throw err\n lastError = err\n if (attempt === maxRetries) throw err\n await sleep(2 ** attempt * 200 + Math.random() * 200)\n }\n }\n throw lastError ?? new Error('hosted ingest exhausted retries')\n}\n\nexport function createHostedClient(tenant: HostedTenant): HostedClient {\n return {\n tenant,\n wireVersion: HOSTED_WIRE_VERSION,\n\n async ingestEvalRun(event, idempotencyKey) {\n return this.ingestEvalRuns([event], idempotencyKey)\n },\n\n async ingestEvalRuns(events, idempotencyKey) {\n const body: IngestEvalRunsRequest = { wireVersion: HOSTED_WIRE_VERSION, events }\n return post<IngestEvalRunsRequest, IngestResponse>(tenant, '/v1/ingest/eval-runs', body, {\n idempotencyKey,\n })\n },\n\n async ingestTraces(spans, idempotencyKey) {\n const body: IngestTracesRequest = { wireVersion: HOSTED_WIRE_VERSION, spans }\n return post<IngestTracesRequest, IngestResponse>(tenant, '/v1/ingest/traces', body, {\n idempotencyKey,\n })\n },\n }\n}\n\n/**\n * Build a `HostedClient` from environment, or `undefined` when ingest is not\n * configured — the canonical, fail-soft wiring every product uses so eval-run +\n * trace provenance lands in the Intelligence dashboard with ONE call:\n *\n * const hosted = hostedClientFromEnv()\n * // ...run the loop...\n * await emitLoopProvenance({ ..., hostedClient: hosted }) // no-op if undefined\n *\n * Returns `undefined` (NOT an error) when any of endpoint / apiKey / tenantId is\n * missing — so a product wires the ship call unconditionally and it stays a\n * no-op until the env is set. Env precedence:\n * - endpoint: `TANGLE_INGEST_URL` → `TANGLE_ORCHESTRATOR_URL`\n * - apiKey: `TANGLE_INGEST_API_KEY` → `TANGLE_API_KEY`\n * - tenantId: `TANGLE_TENANT_ID`\n * A trailing slash on the endpoint is stripped. Pass `overrides` to supply any\n * field directly (e.g. a fixed `tenantId` per product) — overrides win over env.\n */\n/**\n * Build a {@link HostedTenant} config from env — the input `selfImprove`'s\n * `hostedTenant` and `emitLoopProvenance` take. Same env precedence + overrides\n * as {@link hostedClientFromEnv}; returns `undefined` (not an error) when any of\n * endpoint / apiKey / tenantId is missing, so a product wires\n * `hostedTenant: hostedTenantFromEnv({ tenantId: 'my-agent' })` unconditionally\n * and it stays off until the env is set.\n */\nexport function hostedTenantFromEnv(\n overrides: Partial<HostedTenant> & { env?: Record<string, string | undefined> } = {},\n): HostedTenant | undefined {\n const env = overrides.env ?? process.env\n const endpoint = (\n overrides.endpoint ??\n env.TANGLE_INGEST_URL ??\n env.TANGLE_ORCHESTRATOR_URL\n )?.trim()\n const apiKey = (overrides.apiKey ?? env.TANGLE_INGEST_API_KEY ?? env.TANGLE_API_KEY)?.trim()\n const tenantId = (overrides.tenantId ?? env.TANGLE_TENANT_ID)?.trim()\n if (!endpoint || !apiKey || !tenantId) return undefined\n const tenant: HostedTenant = { endpoint: endpoint.replace(/\\/+$/, ''), apiKey, tenantId }\n if (overrides.fetchImpl) tenant.fetchImpl = overrides.fetchImpl\n if (overrides.timeoutMs !== undefined) tenant.timeoutMs = overrides.timeoutMs\n if (overrides.retries !== undefined) tenant.retries = overrides.retries\n return tenant\n}\n\nexport function hostedClientFromEnv(\n overrides: Partial<HostedTenant> & { env?: Record<string, string | undefined> } = {},\n): HostedClient | undefined {\n const tenant = hostedTenantFromEnv(overrides)\n return tenant ? createHostedClient(tenant) : undefined\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
buildOpenApi,
|
|
4
|
+
handleVersion,
|
|
5
|
+
runRpcBatch,
|
|
6
|
+
runRpcOnce,
|
|
7
|
+
startServer
|
|
8
|
+
} from "./chunk-NMN4WGSJ.js";
|
|
9
|
+
import "./chunk-NJC7U437.js";
|
|
10
|
+
import "./chunk-ZMXDQ4K7.js";
|
|
11
|
+
import "./chunk-VI2UW6B6.js";
|
|
12
|
+
import "./chunk-PC4UYEBM.js";
|
|
13
|
+
import "./chunk-ONWEPEDO.js";
|
|
14
|
+
import "./chunk-PZ5AY32C.js";
|
|
15
|
+
|
|
16
|
+
// src/cli.ts
|
|
17
|
+
import { writeFileSync } from "fs";
|
|
18
|
+
function parseArgs(argv) {
|
|
19
|
+
const [command, ...rest] = argv;
|
|
20
|
+
const positional = [];
|
|
21
|
+
const flags = {};
|
|
22
|
+
for (let i = 0; i < rest.length; i++) {
|
|
23
|
+
const tok = rest[i];
|
|
24
|
+
if (tok.startsWith("--")) {
|
|
25
|
+
const key = tok.slice(2);
|
|
26
|
+
const next = rest[i + 1];
|
|
27
|
+
if (next != null && !next.startsWith("--")) {
|
|
28
|
+
flags[key] = next;
|
|
29
|
+
i++;
|
|
30
|
+
} else {
|
|
31
|
+
flags[key] = "true";
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
positional.push(tok);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { command: command ?? "help", positional, flags };
|
|
38
|
+
}
|
|
39
|
+
var HELP = `agent-eval \u2014 wire-protocol entry point.
|
|
40
|
+
|
|
41
|
+
Commands:
|
|
42
|
+
serve [--port 5005] [--host 127.0.0.1]
|
|
43
|
+
Start the HTTP server. POST /v1/judge, GET /v1/rubrics, GET /v1/version, GET /openapi.json.
|
|
44
|
+
rpc <method>
|
|
45
|
+
Read one JSON object from stdin (the params for <method>), write one
|
|
46
|
+
JSON object to stdout. Method \u2208 {judge, listRubrics, version}.
|
|
47
|
+
rpc-batch <method>
|
|
48
|
+
Like 'rpc' but JSONL in / JSONL out.
|
|
49
|
+
openapi [--out openapi.json]
|
|
50
|
+
Write the OpenAPI 3.1 spec.
|
|
51
|
+
version
|
|
52
|
+
Print server + wire-protocol version JSON.
|
|
53
|
+
|
|
54
|
+
Without arguments, prints this help.`;
|
|
55
|
+
async function main() {
|
|
56
|
+
const { command, positional, flags } = parseArgs(process.argv.slice(2));
|
|
57
|
+
switch (command) {
|
|
58
|
+
case "serve": {
|
|
59
|
+
const port = Number(flags.port ?? 5005);
|
|
60
|
+
const host = flags.host ?? "127.0.0.1";
|
|
61
|
+
const server = startServer({ port, host });
|
|
62
|
+
const shutdown = (sig) => {
|
|
63
|
+
console.log(`[agent-eval] received ${sig}, shutting down`);
|
|
64
|
+
server.close(() => process.exit(0));
|
|
65
|
+
setTimeout(() => process.exit(1), 5e3).unref();
|
|
66
|
+
};
|
|
67
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
68
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
69
|
+
await new Promise(() => {
|
|
70
|
+
});
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
case "rpc": {
|
|
74
|
+
const [method] = positional;
|
|
75
|
+
return await runRpcOnce(method);
|
|
76
|
+
}
|
|
77
|
+
case "rpc-batch": {
|
|
78
|
+
const [method] = positional;
|
|
79
|
+
return await runRpcBatch(method);
|
|
80
|
+
}
|
|
81
|
+
case "openapi": {
|
|
82
|
+
const out = flags.out ?? "openapi.json";
|
|
83
|
+
const spec = buildOpenApi(handleVersion().version);
|
|
84
|
+
writeFileSync(out, `${JSON.stringify(spec, null, 2)}
|
|
85
|
+
`, "utf-8");
|
|
86
|
+
console.log(`[agent-eval] wrote OpenAPI 3.1 spec to ${out}`);
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
case "version": {
|
|
90
|
+
process.stdout.write(`${JSON.stringify(handleVersion(), null, 2)}
|
|
91
|
+
`);
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
case "help":
|
|
95
|
+
case "--help":
|
|
96
|
+
case "-h":
|
|
97
|
+
case "":
|
|
98
|
+
process.stdout.write(`${HELP}
|
|
99
|
+
`);
|
|
100
|
+
return 0;
|
|
101
|
+
default:
|
|
102
|
+
process.stderr.write(`unknown command: ${command}
|
|
103
|
+
${HELP}
|
|
104
|
+
`);
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
main().then((code) => process.exit(code)).catch((err) => {
|
|
109
|
+
console.error("[agent-eval] cli error:", err);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
});
|
|
112
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * agent-eval CLI.\n *\n * agent-eval serve [--port 5005] [--host 127.0.0.1]\n * agent-eval rpc <method> # one request from stdin → one response on stdout\n * agent-eval rpc-batch <method> # JSONL stdin → JSONL stdout\n * agent-eval openapi [--out path] # write OpenAPI spec\n * agent-eval version\n *\n * <method> is one of: judge, listRubrics, version. When omitted, the\n * stdin payload must be a full {method, params} envelope.\n */\nimport { writeFileSync } from 'node:fs'\nimport { handleVersion } from './wire/handlers'\nimport { buildOpenApi } from './wire/openapi'\nimport { runRpcBatch, runRpcOnce } from './wire/rpc'\nimport { startServer } from './wire/server'\n\ninterface Args {\n command: string\n positional: string[]\n flags: Record<string, string>\n}\n\nfunction parseArgs(argv: string[]): Args {\n const [command, ...rest] = argv\n const positional: string[] = []\n const flags: Record<string, string> = {}\n for (let i = 0; i < rest.length; i++) {\n const tok = rest[i]!\n if (tok.startsWith('--')) {\n const key = tok.slice(2)\n const next = rest[i + 1]\n if (next != null && !next.startsWith('--')) {\n flags[key] = next\n i++\n } else {\n flags[key] = 'true'\n }\n } else {\n positional.push(tok)\n }\n }\n return { command: command ?? 'help', positional, flags }\n}\n\nconst HELP = `agent-eval — wire-protocol entry point.\n\nCommands:\n serve [--port 5005] [--host 127.0.0.1]\n Start the HTTP server. POST /v1/judge, GET /v1/rubrics, GET /v1/version, GET /openapi.json.\n rpc <method>\n Read one JSON object from stdin (the params for <method>), write one\n JSON object to stdout. Method ∈ {judge, listRubrics, version}.\n rpc-batch <method>\n Like 'rpc' but JSONL in / JSONL out.\n openapi [--out openapi.json]\n Write the OpenAPI 3.1 spec.\n version\n Print server + wire-protocol version JSON.\n\nWithout arguments, prints this help.`\n\nasync function main(): Promise<number> {\n const { command, positional, flags } = parseArgs(process.argv.slice(2))\n\n switch (command) {\n case 'serve': {\n const port = Number(flags.port ?? 5005)\n const host = flags.host ?? '127.0.0.1'\n const server = startServer({ port, host })\n // Keep process alive on SIGINT/SIGTERM\n const shutdown = (sig: string) => {\n // eslint-disable-next-line no-console\n console.log(`[agent-eval] received ${sig}, shutting down`)\n server.close(() => process.exit(0))\n // Force exit after 5s if close hangs\n setTimeout(() => process.exit(1), 5000).unref()\n }\n process.on('SIGINT', () => shutdown('SIGINT'))\n process.on('SIGTERM', () => shutdown('SIGTERM'))\n // Block forever\n await new Promise(() => {})\n return 0\n }\n case 'rpc': {\n const [method] = positional\n return await runRpcOnce(method)\n }\n case 'rpc-batch': {\n const [method] = positional\n return await runRpcBatch(method)\n }\n case 'openapi': {\n const out = flags.out ?? 'openapi.json'\n const spec = buildOpenApi(handleVersion().version)\n writeFileSync(out, `${JSON.stringify(spec, null, 2)}\\n`, 'utf-8')\n // eslint-disable-next-line no-console\n console.log(`[agent-eval] wrote OpenAPI 3.1 spec to ${out}`)\n return 0\n }\n case 'version': {\n process.stdout.write(`${JSON.stringify(handleVersion(), null, 2)}\\n`)\n return 0\n }\n case 'help':\n case '--help':\n case '-h':\n case '':\n process.stdout.write(`${HELP}\\n`)\n return 0\n default:\n process.stderr.write(`unknown command: ${command}\\n${HELP}\\n`)\n return 1\n }\n}\n\nmain()\n .then((code) => process.exit(code))\n .catch((err) => {\n // eslint-disable-next-line no-console\n console.error('[agent-eval] cli error:', err)\n process.exit(1)\n })\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,SAAS,qBAAqB;AAY9B,SAAS,UAAU,MAAsB;AACvC,QAAM,CAAC,SAAS,GAAG,IAAI,IAAI;AAC3B,QAAM,aAAuB,CAAC;AAC9B,QAAM,QAAgC,CAAC;AACvC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,YAAM,MAAM,IAAI,MAAM,CAAC;AACvB,YAAM,OAAO,KAAK,IAAI,CAAC;AACvB,UAAI,QAAQ,QAAQ,CAAC,KAAK,WAAW,IAAI,GAAG;AAC1C,cAAM,GAAG,IAAI;AACb;AAAA,MACF,OAAO;AACL,cAAM,GAAG,IAAI;AAAA,MACf;AAAA,IACF,OAAO;AACL,iBAAW,KAAK,GAAG;AAAA,IACrB;AAAA,EACF;AACA,SAAO,EAAE,SAAS,WAAW,QAAQ,YAAY,MAAM;AACzD;AAEA,IAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBb,eAAe,OAAwB;AACrC,QAAM,EAAE,SAAS,YAAY,MAAM,IAAI,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAEtE,UAAQ,SAAS;AAAA,IACf,KAAK,SAAS;AACZ,YAAM,OAAO,OAAO,MAAM,QAAQ,IAAI;AACtC,YAAM,OAAO,MAAM,QAAQ;AAC3B,YAAM,SAAS,YAAY,EAAE,MAAM,KAAK,CAAC;AAEzC,YAAM,WAAW,CAAC,QAAgB;AAEhC,gBAAQ,IAAI,yBAAyB,GAAG,iBAAiB;AACzD,eAAO,MAAM,MAAM,QAAQ,KAAK,CAAC,CAAC;AAElC,mBAAW,MAAM,QAAQ,KAAK,CAAC,GAAG,GAAI,EAAE,MAAM;AAAA,MAChD;AACA,cAAQ,GAAG,UAAU,MAAM,SAAS,QAAQ,CAAC;AAC7C,cAAQ,GAAG,WAAW,MAAM,SAAS,SAAS,CAAC;AAE/C,YAAM,IAAI,QAAQ,MAAM;AAAA,MAAC,CAAC;AAC1B,aAAO;AAAA,IACT;AAAA,IACA,KAAK,OAAO;AACV,YAAM,CAAC,MAAM,IAAI;AACjB,aAAO,MAAM,WAAW,MAAM;AAAA,IAChC;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,CAAC,MAAM,IAAI;AACjB,aAAO,MAAM,YAAY,MAAM;AAAA,IACjC;AAAA,IACA,KAAK,WAAW;AACd,YAAM,MAAM,MAAM,OAAO;AACzB,YAAM,OAAO,aAAa,cAAc,EAAE,OAAO;AACjD,oBAAc,KAAK,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,GAAM,OAAO;AAEhE,cAAQ,IAAI,0CAA0C,GAAG,EAAE;AAC3D,aAAO;AAAA,IACT;AAAA,IACA,KAAK,WAAW;AACd,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,cAAc,GAAG,MAAM,CAAC,CAAC;AAAA,CAAI;AACpE,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,cAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI;AAChC,aAAO;AAAA,IACT;AACE,cAAQ,OAAO,MAAM,oBAAoB,OAAO;AAAA,EAAK,IAAI;AAAA,CAAI;AAC7D,aAAO;AAAA,EACX;AACF;AAEA,KAAK,EACF,KAAK,CAAC,SAAS,QAAQ,KAAK,IAAI,CAAC,EACjC,MAAM,CAAC,QAAQ;AAEd,UAAQ,MAAM,2BAA2B,GAAG;AAC5C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|