@agent-relay/factory 0.1.56 → 0.1.57

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 (60) hide show
  1. package/README.md +9 -1
  2. package/dist/cost/index.d.ts +3 -0
  3. package/dist/cost/index.d.ts.map +1 -0
  4. package/dist/cost/index.js +3 -0
  5. package/dist/cost/index.js.map +1 -0
  6. package/dist/cost/ledger.d.ts +69 -0
  7. package/dist/cost/ledger.d.ts.map +1 -0
  8. package/dist/cost/ledger.js +162 -0
  9. package/dist/cost/ledger.js.map +1 -0
  10. package/dist/cost/pricing.d.ts +18 -0
  11. package/dist/cost/pricing.d.ts.map +1 -0
  12. package/dist/cost/pricing.js +54 -0
  13. package/dist/cost/pricing.js.map +1 -0
  14. package/dist/fleet/internal-fleet-client.d.ts +3 -1
  15. package/dist/fleet/internal-fleet-client.d.ts.map +1 -1
  16. package/dist/fleet/internal-fleet-client.js +81 -0
  17. package/dist/fleet/internal-fleet-client.js.map +1 -1
  18. package/dist/fleet/relay-fleet-client.d.ts +3 -1
  19. package/dist/fleet/relay-fleet-client.d.ts.map +1 -1
  20. package/dist/fleet/relay-fleet-client.js +48 -0
  21. package/dist/fleet/relay-fleet-client.js.map +1 -1
  22. package/dist/hosted/index.d.ts +1 -1
  23. package/dist/hosted/index.d.ts.map +1 -1
  24. package/dist/hosted/index.js +1 -1
  25. package/dist/hosted/index.js.map +1 -1
  26. package/dist/hosted/orchestrator.d.ts +1 -0
  27. package/dist/hosted/orchestrator.d.ts.map +1 -1
  28. package/dist/hosted/orchestrator.js +190 -1
  29. package/dist/hosted/orchestrator.js.map +1 -1
  30. package/dist/hosted/types.d.ts +4 -0
  31. package/dist/hosted/types.d.ts.map +1 -1
  32. package/dist/index.d.ts +4 -3
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +2 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/observability/events.d.ts +683 -15
  37. package/dist/observability/events.d.ts.map +1 -1
  38. package/dist/observability/events.js +41 -0
  39. package/dist/observability/events.js.map +1 -1
  40. package/dist/orchestrator/factory.d.ts.map +1 -1
  41. package/dist/orchestrator/factory.js +311 -33
  42. package/dist/orchestrator/factory.js.map +1 -1
  43. package/dist/ports/fleet.d.ts +11 -0
  44. package/dist/ports/fleet.d.ts.map +1 -1
  45. package/dist/ports/index.d.ts +1 -1
  46. package/dist/ports/index.d.ts.map +1 -1
  47. package/dist/ports/state.d.ts +21 -5
  48. package/dist/ports/state.d.ts.map +1 -1
  49. package/dist/telemetry.d.ts +9 -0
  50. package/dist/telemetry.d.ts.map +1 -0
  51. package/dist/telemetry.js +8 -0
  52. package/dist/telemetry.js.map +1 -0
  53. package/dist/testing/fakes.d.ts +4 -1
  54. package/dist/testing/fakes.d.ts.map +1 -1
  55. package/dist/testing/fakes.js +12 -0
  56. package/dist/testing/fakes.js.map +1 -1
  57. package/dist/triage/schema.d.ts +42 -42
  58. package/dist/types.d.ts +3 -0
  59. package/dist/types.d.ts.map +1 -1
  60. package/package.json +6 -2
package/README.md CHANGED
@@ -434,12 +434,20 @@ import {
434
434
  const state = new DurableObjectHostedFactoryStateStore(durableObjectState.storage)
435
435
  const factory = createHostedFactory(
436
436
  { workspaceId, ownerId: isolateId, config },
437
- { state, discovery, fleet, completions, mergeGate, writeback },
437
+ { state, discovery, fleet, completions, mergeGate, writeback, reporter },
438
438
  )
439
439
 
440
440
  await factory.runOnce() // invoke from cron/alarm and safe webhook wakeups
441
441
  ```
442
442
 
443
+ The optional `reporter` implements the canonical `FactoryEventReporter`.
444
+ Hosted runs persist a deterministic run ID per workspace and issue, then emit
445
+ lifecycle events only after the corresponding fenced state write. Worker hosts
446
+ that only need the Factory-owned wire schema, event creator, and reporter types
447
+ should import `@agent-relay/factory/telemetry`; unlike the broader
448
+ `@agent-relay/factory/observability` surface, it does not export the
449
+ filesystem-backed outbox or instance identity helpers.
450
+
443
451
  The Durable Object adapter stores each workspace independently and performs
444
452
  lease claims plus lifecycle writes in storage transactions. Every mutation is
445
453
  checked against the current owner and monotonically increasing lease epoch; an
@@ -0,0 +1,3 @@
1
+ export * from './ledger.js';
2
+ export * from './pricing.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cost/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './ledger.js';
2
+ export * from './pricing.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cost/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA"}
@@ -0,0 +1,69 @@
1
+ export declare const COST_LEDGER_ROLES: readonly ["implementer", "reviewer", "babysitter", "triage", "workflow"];
2
+ export type CostLedgerRole = (typeof COST_LEDGER_ROLES)[number];
3
+ /** Matches the closed cloud-event bound for one role's model breakdown. */
4
+ export declare const MAX_RUN_COST_MODELS_PER_ROLE = 32;
5
+ export declare const RUN_COST_OTHER_MODELS_ID = "factory/other-models";
6
+ export interface CostLedgerRecord {
7
+ runId: string;
8
+ role: CostLedgerRole;
9
+ model: string;
10
+ inputTokens: number | null;
11
+ outputTokens: number | null;
12
+ usd: number | null;
13
+ }
14
+ export type CostLedgerRecordInput = Omit<CostLedgerRecord, 'usd'>;
15
+ export interface CostModelBreakdown {
16
+ model: string;
17
+ inputTokens: number | null;
18
+ outputTokens: number | null;
19
+ usd: number | null;
20
+ }
21
+ export interface CostRoleBreakdown {
22
+ role: CostLedgerRole;
23
+ inputTokens: number | null;
24
+ outputTokens: number | null;
25
+ usd: number | null;
26
+ byModel: CostModelBreakdown[];
27
+ }
28
+ export interface RunCostTotal {
29
+ runId: string;
30
+ inputTokens: number | null;
31
+ outputTokens: number | null;
32
+ usd: number | null;
33
+ byRole: CostRoleBreakdown[];
34
+ }
35
+ export interface UnpricedModelCostRecord extends CostLedgerRecord {
36
+ usd: null;
37
+ }
38
+ export type UnpricedModelListener = (record: UnpricedModelCostRecord) => void;
39
+ export interface CostLedgerRecordOptions {
40
+ /**
41
+ * Deterministic logical identity for cumulative runtime updates. Factory uses
42
+ * run id + agent name, so a later usage report replaces rather than doubles
43
+ * the same spawned agent.
44
+ */
45
+ entryId?: string;
46
+ /** Rehydrating durable usage must not emit a duplicate unpriced-model notice. */
47
+ notifyUnpriced?: boolean;
48
+ }
49
+ /**
50
+ * In-memory accounting seam for one Factory process. Durable run records retain
51
+ * the completion aggregate; this ledger keeps the detailed live attribution.
52
+ */
53
+ export declare class CostLedger {
54
+ #private;
55
+ record(input: CostLedgerRecordInput, options?: CostLedgerRecordOptions): CostLedgerRecord;
56
+ hasEntry(entryId: string): boolean;
57
+ getRunRecords(runId: string): CostLedgerRecord[];
58
+ getRunTotal(runId: string): RunCostTotal;
59
+ getRunByRole(runId: string): CostRoleBreakdown[];
60
+ onUnpricedModel(listener: UnpricedModelListener): () => void;
61
+ }
62
+ /**
63
+ * Produces the deterministic, privacy-safe shape persisted and emitted when a
64
+ * run completes. The detailed ledger remains available through
65
+ * getRunRecords(); excess model buckets are folded into one aggregate instead
66
+ * of making the bounded observability event invalid.
67
+ */
68
+ export declare const boundedRunCostTotal: (total: RunCostTotal) => RunCostTotal;
69
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/cost/ledger.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,0EAMpB,CAAA;AAEV,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/D,2EAA2E;AAC3E,eAAO,MAAM,4BAA4B,KAAK,CAAA;AAC9C,eAAO,MAAM,wBAAwB,yBAAyB,CAAA;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,cAAc,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAA;AAEjE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAA;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,OAAO,EAAE,kBAAkB,EAAE,CAAA;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,MAAM,EAAE,iBAAiB,EAAE,CAAA;CAC5B;AAED,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,GAAG,EAAE,IAAI,CAAA;CACV;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAA;AAE7E,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iFAAiF;IACjF,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED;;;GAGG;AACH,qBAAa,UAAU;;IAMrB,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,GAAE,uBAA4B,GAAG,gBAAgB;IAc7F,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIlC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,EAAE;IAMhD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY;IAWxC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAkBhD,eAAe,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,IAAI;CAiB7D;AAiBD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,YAAY,KAAG,YAKxD,CAAA"}
@@ -0,0 +1,162 @@
1
+ import { estimateCostUsd, hasModelPricing, roundUsd } from './pricing.js';
2
+ export const COST_LEDGER_ROLES = [
3
+ 'implementer',
4
+ 'reviewer',
5
+ 'babysitter',
6
+ 'triage',
7
+ 'workflow',
8
+ ];
9
+ /** Matches the closed cloud-event bound for one role's model breakdown. */
10
+ export const MAX_RUN_COST_MODELS_PER_ROLE = 32;
11
+ export const RUN_COST_OTHER_MODELS_ID = 'factory/other-models';
12
+ /**
13
+ * In-memory accounting seam for one Factory process. Durable run records retain
14
+ * the completion aggregate; this ledger keeps the detailed live attribution.
15
+ */
16
+ export class CostLedger {
17
+ #records = new Map();
18
+ #unpricedListeners = new Set();
19
+ #reportedUnpricedModels = new Set();
20
+ #nextEntry = 0;
21
+ record(input, options = {}) {
22
+ const normalized = normalizeRecordInput(input);
23
+ const unpriced = !hasModelPricing(normalized.model);
24
+ const usd = normalized.inputTokens === null || normalized.outputTokens === null
25
+ ? null
26
+ : estimateCostUsd(normalized.model, normalized.inputTokens, normalized.outputTokens);
27
+ const record = { ...normalized, usd };
28
+ const entryId = options.entryId ?? `entry:${this.#nextEntry++}`;
29
+ this.#records.set(entryId, record);
30
+ if (unpriced && options.notifyUnpriced !== false)
31
+ this.#emitUnpriced(record);
32
+ return structuredClone(record);
33
+ }
34
+ hasEntry(entryId) {
35
+ return this.#records.has(entryId);
36
+ }
37
+ getRunRecords(runId) {
38
+ return [...this.#records.values()]
39
+ .filter((record) => record.runId === runId)
40
+ .map((record) => structuredClone(record));
41
+ }
42
+ getRunTotal(runId) {
43
+ const byRole = this.getRunByRole(runId);
44
+ return {
45
+ runId,
46
+ inputTokens: nullableSum(byRole.map((entry) => entry.inputTokens)),
47
+ outputTokens: nullableSum(byRole.map((entry) => entry.outputTokens)),
48
+ usd: nullableUsdSum(byRole.map((entry) => entry.usd)),
49
+ byRole,
50
+ };
51
+ }
52
+ getRunByRole(runId) {
53
+ const records = this.getRunRecords(runId);
54
+ const roles = new Map();
55
+ for (const record of records) {
56
+ const current = roles.get(record.role) ?? [];
57
+ current.push(record);
58
+ roles.set(record.role, current);
59
+ }
60
+ return [...roles].map(([role, roleRecords]) => ({
61
+ role,
62
+ inputTokens: nullableSum(roleRecords.map((record) => record.inputTokens)),
63
+ outputTokens: nullableSum(roleRecords.map((record) => record.outputTokens)),
64
+ usd: nullableUsdSum(roleRecords.map((record) => record.usd)),
65
+ byModel: modelBreakdowns(roleRecords),
66
+ })).sort((left, right) => roleIndex(left.role) - roleIndex(right.role));
67
+ }
68
+ onUnpricedModel(listener) {
69
+ this.#unpricedListeners.add(listener);
70
+ return () => this.#unpricedListeners.delete(listener);
71
+ }
72
+ #emitUnpriced(record) {
73
+ const key = `${record.runId}\0${record.model}`;
74
+ if (this.#reportedUnpricedModels.has(key))
75
+ return;
76
+ this.#reportedUnpricedModels.add(key);
77
+ for (const listener of this.#unpricedListeners) {
78
+ try {
79
+ listener(structuredClone(record));
80
+ }
81
+ catch {
82
+ // Cost accounting is an observability aid, never a run dependency.
83
+ }
84
+ }
85
+ }
86
+ }
87
+ const modelBreakdowns = (records) => {
88
+ const models = new Map();
89
+ for (const record of records) {
90
+ const current = models.get(record.model) ?? [];
91
+ current.push(record);
92
+ models.set(record.model, current);
93
+ }
94
+ return [...models].map(([model, modelRecords]) => ({
95
+ model,
96
+ inputTokens: nullableSum(modelRecords.map((record) => record.inputTokens)),
97
+ outputTokens: nullableSum(modelRecords.map((record) => record.outputTokens)),
98
+ usd: nullableUsdSum(modelRecords.map((record) => record.usd)),
99
+ })).sort((left, right) => compareModelIds(left.model, right.model));
100
+ };
101
+ /**
102
+ * Produces the deterministic, privacy-safe shape persisted and emitted when a
103
+ * run completes. The detailed ledger remains available through
104
+ * getRunRecords(); excess model buckets are folded into one aggregate instead
105
+ * of making the bounded observability event invalid.
106
+ */
107
+ export const boundedRunCostTotal = (total) => ({
108
+ ...structuredClone(total),
109
+ byRole: total.byRole
110
+ .map((role) => ({ ...structuredClone(role), byModel: boundedModels(role.byModel) }))
111
+ .sort((left, right) => roleIndex(left.role) - roleIndex(right.role)),
112
+ });
113
+ const boundedModels = (models) => {
114
+ const sorted = structuredClone(models).sort((left, right) => compareModelIds(left.model, right.model));
115
+ if (sorted.length <= MAX_RUN_COST_MODELS_PER_ROLE)
116
+ return sorted;
117
+ const candidates = sorted.filter((entry) => entry.model !== RUN_COST_OTHER_MODELS_ID);
118
+ const overflow = [
119
+ ...sorted.filter((entry) => entry.model === RUN_COST_OTHER_MODELS_ID),
120
+ ...candidates.slice(MAX_RUN_COST_MODELS_PER_ROLE - 1),
121
+ ];
122
+ return [
123
+ ...candidates.slice(0, MAX_RUN_COST_MODELS_PER_ROLE - 1),
124
+ {
125
+ model: RUN_COST_OTHER_MODELS_ID,
126
+ inputTokens: nullableSum(overflow.map((entry) => entry.inputTokens)),
127
+ outputTokens: nullableSum(overflow.map((entry) => entry.outputTokens)),
128
+ usd: nullableUsdSum(overflow.map((entry) => entry.usd)),
129
+ },
130
+ ];
131
+ };
132
+ const roleIndex = (role) => COST_LEDGER_ROLES.indexOf(role);
133
+ const compareModelIds = (left, right) => left < right ? -1 : left > right ? 1 : 0;
134
+ const normalizeRecordInput = (input) => ({
135
+ runId: boundedIdentifier(input.runId, 'unknown-run'),
136
+ role: COST_LEDGER_ROLES.includes(input.role) ? input.role : 'triage',
137
+ model: boundedModelId(input.model),
138
+ inputTokens: tokenCount(input.inputTokens),
139
+ outputTokens: tokenCount(input.outputTokens),
140
+ });
141
+ const boundedIdentifier = (value, fallback) => {
142
+ const normalized = typeof value === 'string' ? value.trim() : '';
143
+ return (normalized || fallback).slice(0, 256);
144
+ };
145
+ const boundedModelId = (value) => {
146
+ const normalized = boundedIdentifier(value, 'unknown');
147
+ return /^[a-zA-Z0-9][a-zA-Z0-9._:/-]{0,119}$/u.test(normalized)
148
+ ? normalized
149
+ : 'unknown';
150
+ };
151
+ const tokenCount = (value) => value !== null && Number.isSafeInteger(value) && value >= 0 ? value : null;
152
+ const nullableSum = (values) => {
153
+ const known = values.filter((value) => value !== null);
154
+ if (known.length === 0)
155
+ return null;
156
+ return known.reduce((sum, value) => sum >= Number.MAX_SAFE_INTEGER - value ? Number.MAX_SAFE_INTEGER : sum + value, 0);
157
+ };
158
+ const nullableUsdSum = (values) => {
159
+ const total = nullableSum(values);
160
+ return total === null ? null : roundUsd(total);
161
+ };
162
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/cost/ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface ModelPricing {
2
+ costPer1MInput: number;
3
+ costPer1MOutput: number;
4
+ }
5
+ /**
6
+ * Factory's metered model catalog. Keep the shape aligned with NightCTO's
7
+ * openrouter-client model ladder so model-routing work can share prices later.
8
+ */
9
+ export declare const MODEL_PRICING: Readonly<Record<string, ModelPricing>>;
10
+ export interface EstimateCostUsdOptions {
11
+ /** A bounded accounting notice; callback failures are deliberately ignored. */
12
+ onUnpricedModel?: (model: string) => void;
13
+ }
14
+ export declare function hasModelPricing(model: string): boolean;
15
+ /** Estimate a metered model cost without ever making accounting control flow fatal. */
16
+ export declare function estimateCostUsd(model: string, inputTokens: number, outputTokens: number, options?: EstimateCostUsdOptions): number | null;
17
+ export declare const roundUsd: (value: number) => number;
18
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/cost/pricing.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAyB/D,CAAA;AAEF,MAAM,WAAW,sBAAsB;IACrC,+EAA+E;IAC/E,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAC1C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,sBAA2B,GACnC,MAAM,GAAG,IAAI,CAef;AAED,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,KAAG,MAAkC,CAAA"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Factory's metered model catalog. Keep the shape aligned with NightCTO's
3
+ * openrouter-client model ladder so model-routing work can share prices later.
4
+ */
5
+ export const MODEL_PRICING = Object.freeze({
6
+ 'deepseek/deepseek-chat-v3-0324': {
7
+ costPer1MInput: 0.27,
8
+ costPer1MOutput: 1.1,
9
+ },
10
+ 'openai/gpt-4o-mini': {
11
+ costPer1MInput: 0.15,
12
+ costPer1MOutput: 0.6,
13
+ },
14
+ 'anthropic/claude-haiku-4.5': {
15
+ costPer1MInput: 1,
16
+ costPer1MOutput: 5,
17
+ },
18
+ 'anthropic/claude-sonnet-4.5': {
19
+ costPer1MInput: 3,
20
+ costPer1MOutput: 15,
21
+ },
22
+ 'openai/gpt-5.4': {
23
+ costPer1MInput: 5,
24
+ costPer1MOutput: 15,
25
+ },
26
+ 'openai/gpt-5.4-pro': {
27
+ costPer1MInput: 15,
28
+ costPer1MOutput: 60,
29
+ },
30
+ });
31
+ export function hasModelPricing(model) {
32
+ return Object.prototype.hasOwnProperty.call(MODEL_PRICING, model);
33
+ }
34
+ /** Estimate a metered model cost without ever making accounting control flow fatal. */
35
+ export function estimateCostUsd(model, inputTokens, outputTokens, options = {}) {
36
+ if (!hasModelPricing(model)) {
37
+ try {
38
+ options.onUnpricedModel?.(model);
39
+ }
40
+ catch {
41
+ // Observability and accounting callbacks must never affect a run.
42
+ }
43
+ return null;
44
+ }
45
+ const pricing = MODEL_PRICING[model];
46
+ if (!validTokenCount(inputTokens) || !validTokenCount(outputTokens))
47
+ return null;
48
+ const inputCost = (inputTokens / 1_000_000) * pricing.costPer1MInput;
49
+ const outputCost = (outputTokens / 1_000_000) * pricing.costPer1MOutput;
50
+ return roundUsd(inputCost + outputCost);
51
+ }
52
+ export const roundUsd = (value) => Number(value.toFixed(6));
53
+ const validTokenCount = (value) => Number.isSafeInteger(value) && value >= 0;
54
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/cost/pricing.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAA2C,MAAM,CAAC,MAAM,CAAC;IACjF,gCAAgC,EAAE;QAChC,cAAc,EAAE,IAAI;QACpB,eAAe,EAAE,GAAG;KACrB;IACD,oBAAoB,EAAE;QACpB,cAAc,EAAE,IAAI;QACpB,eAAe,EAAE,GAAG;KACrB;IACD,4BAA4B,EAAE;QAC5B,cAAc,EAAE,CAAC;QACjB,eAAe,EAAE,CAAC;KACnB;IACD,6BAA6B,EAAE;QAC7B,cAAc,EAAE,CAAC;QACjB,eAAe,EAAE,EAAE;KACpB;IACD,gBAAgB,EAAE;QAChB,cAAc,EAAE,CAAC;QACjB,eAAe,EAAE,EAAE;KACpB;IACD,oBAAoB,EAAE;QACpB,cAAc,EAAE,EAAE;QAClB,eAAe,EAAE,EAAE;KACpB;CACF,CAAC,CAAA;AAOF,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAA;AACnE,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,WAAmB,EACnB,YAAoB,EACpB,UAAkC,EAAE;IAEpC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,OAAO,CAAC,eAAe,EAAE,CAAC,KAAK,CAAC,CAAA;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;QACpE,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAE,CAAA;IACrC,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAA;IAEhF,MAAM,SAAS,GAAG,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,cAAc,CAAA;IACpE,MAAM,UAAU,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,eAAe,CAAA;IACvE,OAAO,QAAQ,CAAC,SAAS,GAAG,UAAU,CAAC,CAAA;AACzC,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AAE3E,MAAM,eAAe,GAAG,CAAC,KAAa,EAAW,EAAE,CACjD,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import type { BrokerEvent, ListAgent, SendMessageInput, SpawnPtyInput } from '@agent-relay/harness-driver';
2
2
  import type { PreviewConfig } from '../config/schema.js';
3
- import type { AgentMessage, AgentPidResolution, Capability, FleetClient, FleetTrackedAgent, PreviewReference, PreviewStartInput, PreviewSweepInput, PreviewSweepResult, RosterEntry, SendInput, SpawnInput, SpawnResult } from '../ports/fleet.js';
3
+ import type { AgentMessage, AgentPidResolution, AgentUsage, Capability, FleetClient, FleetTrackedAgent, PreviewReference, PreviewStartInput, PreviewSweepInput, PreviewSweepResult, RosterEntry, SendInput, SpawnInput, SpawnResult } from '../ports/fleet.js';
4
4
  import type { Logger } from '../ports/system.js';
5
5
  import { type PreviewManager } from '../node/tailscale-preview.js';
6
6
  type SpawnedHandleLike = {
@@ -70,6 +70,7 @@ type DeliveryFailedListener = (info: {
70
70
  reason?: string;
71
71
  }) => void;
72
72
  type AgentMessageListener = (message: AgentMessage) => void;
73
+ type AgentUsageListener = (usage: AgentUsage) => void | Promise<void>;
73
74
  export declare const capabilityCli: Record<Capability, string>;
74
75
  export declare class InternalFleetClient implements FleetClient {
75
76
  #private;
@@ -111,6 +112,7 @@ export declare class InternalFleetClient implements FleetClient {
111
112
  sendInput(name: string, data: string): Promise<void>;
112
113
  onDeliveryFailed(listener: DeliveryFailedListener): () => void;
113
114
  onAgentMessage(listener: AgentMessageListener): () => void;
115
+ onAgentUsage(listener: AgentUsageListener): () => void;
114
116
  onAgentExit(listener: AgentExitListener): () => void;
115
117
  preserveInfrastructureOnDispose(): void;
116
118
  dispose(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"internal-fleet-client.d.ts","sourceRoot":"","sources":["../../src/fleet/internal-fleet-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"internal-fleet-client.d.ts","sourceRoot":"","sources":["../../src/fleet/internal-fleet-client.ts"],"names":[],"mappings":"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"}
@@ -46,6 +46,7 @@ export class InternalFleetClient {
46
46
  #agentExitListeners = new Set();
47
47
  #deliveryFailedListeners = new Set();
48
48
  #agentMessageListeners = new Set();
49
+ #agentUsageListeners = new Set();
49
50
  #eventUnsubscribers = [];
50
51
  #seenEvents = [];
51
52
  #seenEventKeys = new Set();
@@ -436,6 +437,13 @@ export class InternalFleetClient {
436
437
  this.#agentMessageListeners.delete(listener);
437
438
  };
438
439
  }
440
+ onAgentUsage(listener) {
441
+ this.#ensureEventSubscription();
442
+ this.#agentUsageListeners.add(listener);
443
+ return () => {
444
+ this.#agentUsageListeners.delete(listener);
445
+ };
446
+ }
439
447
  onAgentExit(listener) {
440
448
  this.#ensureEventSubscription();
441
449
  this.#agentExitListeners.add(listener);
@@ -474,6 +482,7 @@ export class InternalFleetClient {
474
482
  this.#agentExitListeners.clear();
475
483
  this.#deliveryFailedListeners.clear();
476
484
  this.#agentMessageListeners.clear();
485
+ this.#agentUsageListeners.clear();
477
486
  this.#failedDeliveries.clear();
478
487
  this.#failedDeliveryIds.length = 0;
479
488
  this.#readyAgentNames.clear();
@@ -521,6 +530,11 @@ export class InternalFleetClient {
521
530
  this.#client.connectEvents?.();
522
531
  }
523
532
  #handleBrokerEvent(event) {
533
+ const usage = agentUsageFromRuntimeEvent(event);
534
+ if (usage) {
535
+ this.#emitAgentUsage(usage, eventIdentity(event));
536
+ return;
537
+ }
524
538
  if (event.kind === 'worker_ready') {
525
539
  this.#markAgentReady(event.name);
526
540
  return;
@@ -723,6 +737,26 @@ export class InternalFleetClient {
723
737
  listener(message);
724
738
  }
725
739
  }
740
+ #emitAgentUsage(usage, identity) {
741
+ if (this.#rememberEvent(identity))
742
+ return;
743
+ for (const listener of this.#agentUsageListeners) {
744
+ try {
745
+ void Promise.resolve(listener({ ...usage })).catch((error) => {
746
+ this.#logger?.warn?.('[factory-sdk] agent usage listener rejected an update', {
747
+ name: usage.name,
748
+ error,
749
+ });
750
+ });
751
+ }
752
+ catch (error) {
753
+ this.#logger?.warn?.('[factory-sdk] agent usage listener rejected an update', {
754
+ name: usage.name,
755
+ error,
756
+ });
757
+ }
758
+ }
759
+ }
726
760
  #emitAgentExit(name, reason, identity) {
727
761
  if (this.#rememberEvent(identity)) {
728
762
  return;
@@ -1062,6 +1096,53 @@ function messageInputFrom(input) {
1062
1096
  ...(input.mode ? { mode: input.mode } : {}),
1063
1097
  };
1064
1098
  }
1099
+ /**
1100
+ * Harness Driver versions predating the typed usage event still forward
1101
+ * provider events through onEvent. Normalize the stable field aliases here so
1102
+ * upgrading the runtime does not require an orchestration rewrite.
1103
+ */
1104
+ function agentUsageFromRuntimeEvent(event) {
1105
+ const record = runtimeRecord(event);
1106
+ const kind = runtimeString(record, 'kind', 'type');
1107
+ if (!kind || !['agent_usage', 'usage_updated', 'usage.updated', 'token_usage'].includes(kind)) {
1108
+ return undefined;
1109
+ }
1110
+ const agent = runtimeRecord(record?.agent);
1111
+ const usage = runtimeRecord(record?.usage);
1112
+ const name = runtimeString(record, 'name', 'agent_name', 'agentName')
1113
+ ?? runtimeString(agent, 'name', 'agent_name', 'agentName');
1114
+ if (!name)
1115
+ return undefined;
1116
+ const model = runtimeString(record, 'model', 'model_id', 'modelId')
1117
+ ?? runtimeString(usage, 'model', 'model_id', 'modelId');
1118
+ return {
1119
+ name,
1120
+ ...(model ? { model } : {}),
1121
+ inputTokens: runtimeTokenCount(runtimeValue(record, 'inputTokens', 'input_tokens', 'promptTokens', 'prompt_tokens')
1122
+ ?? runtimeValue(usage, 'inputTokens', 'input_tokens', 'promptTokens', 'prompt_tokens')),
1123
+ outputTokens: runtimeTokenCount(runtimeValue(record, 'outputTokens', 'output_tokens', 'completionTokens', 'completion_tokens')
1124
+ ?? runtimeValue(usage, 'outputTokens', 'output_tokens', 'completionTokens', 'completion_tokens')),
1125
+ };
1126
+ }
1127
+ const runtimeRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value)
1128
+ ? value
1129
+ : undefined;
1130
+ const runtimeString = (record, ...keys) => {
1131
+ for (const key of keys) {
1132
+ const value = record?.[key];
1133
+ if (typeof value === 'string' && value.trim())
1134
+ return value.trim();
1135
+ }
1136
+ return undefined;
1137
+ };
1138
+ const runtimeValue = (record, ...keys) => {
1139
+ for (const key of keys) {
1140
+ if (record && Object.prototype.hasOwnProperty.call(record, key))
1141
+ return record[key];
1142
+ }
1143
+ return undefined;
1144
+ };
1145
+ const runtimeTokenCount = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : null;
1065
1146
  function eventIdentity(event) {
1066
1147
  const record = event;
1067
1148
  const stable = record.event_id ?? record.delivery_id;