@amalgm/chat 0.1.0

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 (183) hide show
  1. package/PURPOSE.md +107 -0
  2. package/README.md +41 -0
  3. package/dist/contract/chat-input.d.ts +144 -0
  4. package/dist/contract/chat-input.d.ts.map +1 -0
  5. package/dist/contract/chat-input.js +261 -0
  6. package/dist/contract/chat-input.js.map +1 -0
  7. package/dist/contract/create.d.ts +191 -0
  8. package/dist/contract/create.d.ts.map +1 -0
  9. package/dist/contract/create.js +249 -0
  10. package/dist/contract/create.js.map +1 -0
  11. package/dist/contract/freeze.d.ts +85 -0
  12. package/dist/contract/freeze.d.ts.map +1 -0
  13. package/dist/contract/freeze.js +151 -0
  14. package/dist/contract/freeze.js.map +1 -0
  15. package/dist/contract/harnesses.d.ts +21 -0
  16. package/dist/contract/harnesses.d.ts.map +1 -0
  17. package/dist/contract/harnesses.js +39 -0
  18. package/dist/contract/harnesses.js.map +1 -0
  19. package/dist/contract/index.d.ts +17 -0
  20. package/dist/contract/index.d.ts.map +1 -0
  21. package/dist/contract/index.js +17 -0
  22. package/dist/contract/index.js.map +1 -0
  23. package/dist/contract/input.d.ts +45 -0
  24. package/dist/contract/input.d.ts.map +1 -0
  25. package/dist/contract/input.js +78 -0
  26. package/dist/contract/input.js.map +1 -0
  27. package/dist/contract/models.d.ts +57 -0
  28. package/dist/contract/models.d.ts.map +1 -0
  29. package/dist/contract/models.js +380 -0
  30. package/dist/contract/models.js.map +1 -0
  31. package/dist/contract/payload-merge.d.ts +76 -0
  32. package/dist/contract/payload-merge.d.ts.map +1 -0
  33. package/dist/contract/payload-merge.js +215 -0
  34. package/dist/contract/payload-merge.js.map +1 -0
  35. package/dist/events/constructors.d.ts +53 -0
  36. package/dist/events/constructors.d.ts.map +1 -0
  37. package/dist/events/constructors.js +217 -0
  38. package/dist/events/constructors.js.map +1 -0
  39. package/dist/events/index.d.ts +12 -0
  40. package/dist/events/index.d.ts.map +1 -0
  41. package/dist/events/index.js +12 -0
  42. package/dist/events/index.js.map +1 -0
  43. package/dist/events/schema.d.ts +455 -0
  44. package/dist/events/schema.d.ts.map +1 -0
  45. package/dist/events/schema.js +228 -0
  46. package/dist/events/schema.js.map +1 -0
  47. package/dist/events/tool-display.d.ts +22 -0
  48. package/dist/events/tool-display.d.ts.map +1 -0
  49. package/dist/events/tool-display.js +60 -0
  50. package/dist/events/tool-display.js.map +1 -0
  51. package/dist/events/tool-shape.d.ts +48 -0
  52. package/dist/events/tool-shape.d.ts.map +1 -0
  53. package/dist/events/tool-shape.js +225 -0
  54. package/dist/events/tool-shape.js.map +1 -0
  55. package/dist/index.d.ts +27 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +26 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/normalizers/claude.d.ts +628 -0
  60. package/dist/normalizers/claude.d.ts.map +1 -0
  61. package/dist/normalizers/claude.js +603 -0
  62. package/dist/normalizers/claude.js.map +1 -0
  63. package/dist/normalizers/codex.d.ts +352 -0
  64. package/dist/normalizers/codex.d.ts.map +1 -0
  65. package/dist/normalizers/codex.js +485 -0
  66. package/dist/normalizers/codex.js.map +1 -0
  67. package/dist/normalizers/cursor.d.ts +34 -0
  68. package/dist/normalizers/cursor.d.ts.map +1 -0
  69. package/dist/normalizers/cursor.js +197 -0
  70. package/dist/normalizers/cursor.js.map +1 -0
  71. package/dist/normalizers/index.d.ts +13 -0
  72. package/dist/normalizers/index.d.ts.map +1 -0
  73. package/dist/normalizers/index.js +13 -0
  74. package/dist/normalizers/index.js.map +1 -0
  75. package/dist/normalizers/opencode.d.ts +81 -0
  76. package/dist/normalizers/opencode.d.ts.map +1 -0
  77. package/dist/normalizers/opencode.js +640 -0
  78. package/dist/normalizers/opencode.js.map +1 -0
  79. package/dist/normalizers/pi.d.ts +28 -0
  80. package/dist/normalizers/pi.d.ts.map +1 -0
  81. package/dist/normalizers/pi.js +160 -0
  82. package/dist/normalizers/pi.js.map +1 -0
  83. package/dist/ports.d.ts +14 -0
  84. package/dist/ports.d.ts.map +1 -0
  85. package/dist/ports.js +7 -0
  86. package/dist/ports.js.map +1 -0
  87. package/dist/transcript/index.d.ts +14 -0
  88. package/dist/transcript/index.d.ts.map +1 -0
  89. package/dist/transcript/index.js +12 -0
  90. package/dist/transcript/index.js.map +1 -0
  91. package/dist/transcript/message-reducer.d.ts +167 -0
  92. package/dist/transcript/message-reducer.d.ts.map +1 -0
  93. package/dist/transcript/message-reducer.js +400 -0
  94. package/dist/transcript/message-reducer.js.map +1 -0
  95. package/dist/transcript/part-accumulator.d.ts +24 -0
  96. package/dist/transcript/part-accumulator.d.ts.map +1 -0
  97. package/dist/transcript/part-accumulator.js +30 -0
  98. package/dist/transcript/part-accumulator.js.map +1 -0
  99. package/dist/transcript/tool-display.d.ts +14 -0
  100. package/dist/transcript/tool-display.d.ts.map +1 -0
  101. package/dist/transcript/tool-display.js +125 -0
  102. package/dist/transcript/tool-display.js.map +1 -0
  103. package/dist/transcript/tool-shape.d.ts +34 -0
  104. package/dist/transcript/tool-shape.d.ts.map +1 -0
  105. package/dist/transcript/tool-shape.js +216 -0
  106. package/dist/transcript/tool-shape.js.map +1 -0
  107. package/dist/turns/index.d.ts +11 -0
  108. package/dist/turns/index.d.ts.map +1 -0
  109. package/dist/turns/index.js +11 -0
  110. package/dist/turns/index.js.map +1 -0
  111. package/dist/turns/queries.d.ts +36 -0
  112. package/dist/turns/queries.d.ts.map +1 -0
  113. package/dist/turns/queries.js +37 -0
  114. package/dist/turns/queries.js.map +1 -0
  115. package/dist/turns/replay.d.ts +105 -0
  116. package/dist/turns/replay.d.ts.map +1 -0
  117. package/dist/turns/replay.js +163 -0
  118. package/dist/turns/replay.js.map +1 -0
  119. package/dist/turns/status.d.ts +49 -0
  120. package/dist/turns/status.d.ts.map +1 -0
  121. package/dist/turns/status.js +56 -0
  122. package/dist/turns/status.js.map +1 -0
  123. package/dist/turns/turn-store.d.ts +109 -0
  124. package/dist/turns/turn-store.d.ts.map +1 -0
  125. package/dist/turns/turn-store.js +169 -0
  126. package/dist/turns/turn-store.js.map +1 -0
  127. package/dist/usage/finalize.d.ts +57 -0
  128. package/dist/usage/finalize.d.ts.map +1 -0
  129. package/dist/usage/finalize.js +139 -0
  130. package/dist/usage/finalize.js.map +1 -0
  131. package/dist/usage/index.d.ts +11 -0
  132. package/dist/usage/index.d.ts.map +1 -0
  133. package/dist/usage/index.js +11 -0
  134. package/dist/usage/index.js.map +1 -0
  135. package/dist/usage/model-catalog.d.ts +50 -0
  136. package/dist/usage/model-catalog.d.ts.map +1 -0
  137. package/dist/usage/model-catalog.js +344 -0
  138. package/dist/usage/model-catalog.js.map +1 -0
  139. package/dist/usage/normalize.d.ts +103 -0
  140. package/dist/usage/normalize.d.ts.map +1 -0
  141. package/dist/usage/normalize.js +71 -0
  142. package/dist/usage/normalize.js.map +1 -0
  143. package/dist/usage/ports.d.ts +141 -0
  144. package/dist/usage/ports.d.ts.map +1 -0
  145. package/dist/usage/ports.js +113 -0
  146. package/dist/usage/ports.js.map +1 -0
  147. package/dist/usage/tokens.d.ts +79 -0
  148. package/dist/usage/tokens.d.ts.map +1 -0
  149. package/dist/usage/tokens.js +98 -0
  150. package/dist/usage/tokens.js.map +1 -0
  151. package/dist/warm/client-cache.d.ts +47 -0
  152. package/dist/warm/client-cache.d.ts.map +1 -0
  153. package/dist/warm/client-cache.js +48 -0
  154. package/dist/warm/client-cache.js.map +1 -0
  155. package/dist/warm/envelope-cache.d.ts +79 -0
  156. package/dist/warm/envelope-cache.d.ts.map +1 -0
  157. package/dist/warm/envelope-cache.js +85 -0
  158. package/dist/warm/envelope-cache.js.map +1 -0
  159. package/dist/warm/index.d.ts +16 -0
  160. package/dist/warm/index.d.ts.map +1 -0
  161. package/dist/warm/index.js +11 -0
  162. package/dist/warm/index.js.map +1 -0
  163. package/dist/warm/payload.d.ts +137 -0
  164. package/dist/warm/payload.d.ts.map +1 -0
  165. package/dist/warm/payload.js +112 -0
  166. package/dist/warm/payload.js.map +1 -0
  167. package/dist/warm/revision.d.ts +70 -0
  168. package/dist/warm/revision.d.ts.map +1 -0
  169. package/dist/warm/revision.js +63 -0
  170. package/dist/warm/revision.js.map +1 -0
  171. package/dist/warm/store-policy.d.ts +57 -0
  172. package/dist/warm/store-policy.d.ts.map +1 -0
  173. package/dist/warm/store-policy.js +89 -0
  174. package/dist/warm/store-policy.js.map +1 -0
  175. package/dist/wire/frames.d.ts +208 -0
  176. package/dist/wire/frames.d.ts.map +1 -0
  177. package/dist/wire/frames.js +245 -0
  178. package/dist/wire/frames.js.map +1 -0
  179. package/dist/wire/index.d.ts +7 -0
  180. package/dist/wire/index.d.ts.map +1 -0
  181. package/dist/wire/index.js +7 -0
  182. package/dist/wire/index.js.map +1 -0
  183. package/package.json +72 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Usage normalization — engine `chat-core/usage.js:65-116,204-206`, ported
3
+ * byte-exact. Every provider-flavored usage payload (Claude SDK snake_case,
4
+ * OpenAI camelCase, codex cumulative meters, opencode step records) funnels
5
+ * through `normalizeUsage` into one canonical `NormalizedUsage` shape.
6
+ */
7
+ import { type TokenList } from './tokens.js';
8
+ /**
9
+ * Engine `positiveOrNull()`: the numeric value when finite and > 0, else
10
+ * null.
11
+ */
12
+ export declare function positiveOrNull(value: unknown): number | null;
13
+ /**
14
+ * Loose input accepted by `normalizeUsage` — the union of every key
15
+ * spelling the engine recognizes across providers.
16
+ */
17
+ export interface UsageInput {
18
+ tokenList?: unknown;
19
+ cumulativeTokenList?: unknown;
20
+ previousCumulativeTokenList?: unknown;
21
+ /** Non-cached input tokens — unless `inputTokensAreTotal` is set. */
22
+ inputTokens?: unknown;
23
+ input_tokens?: unknown;
24
+ nonCachedInputTokens?: unknown;
25
+ /** Total input including cache buckets; decomposed into non-cached input. */
26
+ totalInputTokens?: unknown;
27
+ promptTokens?: unknown;
28
+ /** When truthy, `inputTokens` is treated as a total-input figure. */
29
+ inputTokensAreTotal?: unknown;
30
+ outputTokens?: unknown;
31
+ completionTokens?: unknown;
32
+ output_tokens?: unknown;
33
+ cacheReadTokens?: unknown;
34
+ cachedInputTokens?: unknown;
35
+ cache_read_input_tokens?: unknown;
36
+ cacheWriteTokens?: unknown;
37
+ cacheCreationInputTokens?: unknown;
38
+ cache_creation_input_tokens?: unknown;
39
+ thoughtTokens?: unknown;
40
+ reasoningTokens?: unknown;
41
+ inputContextSize?: unknown;
42
+ input_context_size?: unknown;
43
+ contextUsedTokens?: unknown;
44
+ usedTokens?: unknown;
45
+ lastUsedTokens?: unknown;
46
+ contextLimit?: unknown;
47
+ maxTokens?: unknown;
48
+ modelContextWindow?: unknown;
49
+ totalProcessedTokens?: unknown;
50
+ costUsd?: unknown;
51
+ costUSD?: unknown;
52
+ cost?: unknown;
53
+ marketCostUsd?: unknown;
54
+ operation?: unknown;
55
+ usageOperation?: unknown;
56
+ billable?: unknown;
57
+ source?: unknown;
58
+ exact?: unknown;
59
+ }
60
+ /**
61
+ * The canonical usage record. Laws:
62
+ * - `costUsd`/`marketCostUsd` are null when unknown — never zero. Zero
63
+ * means "measured as free"; null means "not measured".
64
+ * - `inputTokens` always means non-cached input; total-input figures are
65
+ * decomposed by subtracting the cache buckets (clamped at 0).
66
+ * - `inputContextSize` is the next-turn context footprint (defaults to the
67
+ * tokenList total).
68
+ * - `source` is a free-form provenance string (engine default `'runtime'`);
69
+ * well-known values include `'claude_agent_sdk_model_usage'`,
70
+ * `'codex_app_server_turn_delta'`, `'codex_app_server_step_sum'`,
71
+ * `'pi_rpc_step_sum'`, `'turn_sum'`, `'native_chat_turn'`.
72
+ */
73
+ export interface NormalizedUsage {
74
+ tokenList: TokenList;
75
+ cumulativeTokenList: TokenList | null;
76
+ previousCumulativeTokenList: TokenList | null;
77
+ inputTokens: number;
78
+ outputTokens: number;
79
+ cacheReadTokens: number;
80
+ cacheWriteTokens: number;
81
+ thoughtTokens: number;
82
+ inputContextSize: number;
83
+ contextUsedTokens: number | null;
84
+ contextLimit: number | null;
85
+ usedTokens: number | null;
86
+ lastUsedTokens: number | null;
87
+ maxTokens: number | null;
88
+ totalProcessedTokens: number | null;
89
+ costUsd: number | null;
90
+ marketCostUsd: number | null;
91
+ operation: string;
92
+ billable: boolean;
93
+ source: string;
94
+ exact: boolean;
95
+ }
96
+ /** Engine `normalizeUsage()`, byte-exact including every fallback chain. */
97
+ export declare function normalizeUsage(input?: UsageInput): NormalizedUsage;
98
+ /**
99
+ * Engine `providerFromModel()`: the provider prefix of a slash-qualified
100
+ * model id (`'anthropic/claude-sonnet-4.6'` → `'anthropic'`), else null.
101
+ */
102
+ export declare function providerFromModel(modelId: unknown): string | null;
103
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/usage/normalize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA4C,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAEvF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAG5D;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,qEAAqE;IACrE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qEAAqE;IACrE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB,mBAAmB,EAAE,SAAS,GAAG,IAAI,CAAC;IACtC,2BAA2B,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,GAAE,UAAe,GAAG,eAAe,CA8CtE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEjE"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Usage normalization — engine `chat-core/usage.js:65-116,204-206`, ported
3
+ * byte-exact. Every provider-flavored usage payload (Claude SDK snake_case,
4
+ * OpenAI camelCase, codex cumulative meters, opencode step records) funnels
5
+ * through `normalizeUsage` into one canonical `NormalizedUsage` shape.
6
+ */
7
+ import { n, nonNegativeOrNull, normalizeTokenList } from './tokens.js';
8
+ /**
9
+ * Engine `positiveOrNull()`: the numeric value when finite and > 0, else
10
+ * null.
11
+ */
12
+ export function positiveOrNull(value) {
13
+ const parsed = Number(value);
14
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
15
+ }
16
+ /** Engine `normalizeUsage()`, byte-exact including every fallback chain. */
17
+ export function normalizeUsage(input = {}) {
18
+ const cacheRead = n(input.cacheReadTokens ?? input.cachedInputTokens ?? input.cache_read_input_tokens);
19
+ const cacheWrite = n(input.cacheWriteTokens ?? input.cacheCreationInputTokens ?? input.cache_creation_input_tokens);
20
+ const output = n(input.outputTokens ?? input.completionTokens ?? input.output_tokens);
21
+ const thought = n(input.thoughtTokens ?? input.reasoningTokens);
22
+ const totalInput = input.totalInputTokens ?? input.promptTokens ?? (input.inputTokensAreTotal ? input.inputTokens : null);
23
+ const nonCachedInput = totalInput == null
24
+ ? n(input.inputTokens ?? input.input_tokens ?? input.nonCachedInputTokens)
25
+ : Math.max(0, n(totalInput) - cacheRead - cacheWrite);
26
+ const tokenList = normalizeTokenList({
27
+ tokenList: input.tokenList,
28
+ inputTokens: nonCachedInput,
29
+ outputTokens: output,
30
+ cacheReadTokens: cacheRead,
31
+ cacheWriteTokens: cacheWrite,
32
+ thoughtTokens: thought,
33
+ });
34
+ const inputContextSize = nonNegativeOrNull(input.inputContextSize ?? input.input_context_size)
35
+ ?? tokenList.total;
36
+ return {
37
+ tokenList,
38
+ cumulativeTokenList: input.cumulativeTokenList && typeof input.cumulativeTokenList === 'object'
39
+ ? normalizeTokenList({ tokenList: input.cumulativeTokenList })
40
+ : null,
41
+ previousCumulativeTokenList: input.previousCumulativeTokenList && typeof input.previousCumulativeTokenList === 'object'
42
+ ? normalizeTokenList({ tokenList: input.previousCumulativeTokenList })
43
+ : null,
44
+ inputTokens: nonCachedInput,
45
+ outputTokens: output,
46
+ cacheReadTokens: cacheRead,
47
+ cacheWriteTokens: cacheWrite,
48
+ thoughtTokens: thought,
49
+ inputContextSize,
50
+ contextUsedTokens: positiveOrNull(input.contextUsedTokens ?? input.usedTokens ?? inputContextSize),
51
+ contextLimit: positiveOrNull(input.contextLimit ?? input.maxTokens ?? input.modelContextWindow),
52
+ usedTokens: positiveOrNull(input.usedTokens ?? input.contextUsedTokens ?? inputContextSize),
53
+ lastUsedTokens: positiveOrNull(input.lastUsedTokens ?? input.contextUsedTokens ?? input.usedTokens ?? inputContextSize),
54
+ maxTokens: positiveOrNull(input.maxTokens ?? input.contextLimit ?? input.modelContextWindow),
55
+ totalProcessedTokens: positiveOrNull(input.totalProcessedTokens),
56
+ costUsd: (input.costUsd ?? input.costUSD ?? input.cost ?? null),
57
+ marketCostUsd: (input.marketCostUsd ?? null),
58
+ operation: String(input.operation || input.usageOperation || 'chat_step'),
59
+ billable: input.billable !== false,
60
+ source: (input.source || 'runtime'),
61
+ exact: input.exact === true,
62
+ };
63
+ }
64
+ /**
65
+ * Engine `providerFromModel()`: the provider prefix of a slash-qualified
66
+ * model id (`'anthropic/claude-sonnet-4.6'` → `'anthropic'`), else null.
67
+ */
68
+ export function providerFromModel(modelId) {
69
+ return typeof modelId === 'string' && modelId.includes('/') ? modelId.split('/')[0] ?? null : null;
70
+ }
71
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/usage/normalize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,iBAAiB,EAAE,kBAAkB,EAAkB,MAAM,aAAa,CAAC;AAEvF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D,CAAC;AAuFD,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,QAAoB,EAAE;IACnD,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,eAAe,IAAI,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACvG,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,wBAAwB,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACpH,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACtF,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC1H,MAAM,cAAc,GAAG,UAAU,IAAI,IAAI;QACvC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,oBAAoB,CAAC;QAC1E,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,kBAAkB,CAAC;QACnC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW,EAAE,cAAc;QAC3B,YAAY,EAAE,MAAM;QACpB,eAAe,EAAE,SAAS;QAC1B,gBAAgB,EAAE,UAAU;QAC5B,aAAa,EAAE,OAAO;KACvB,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,kBAAkB,CAAC;WACzF,SAAS,CAAC,KAAK,CAAC;IACrB,OAAO;QACL,SAAS;QACT,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,IAAI,OAAO,KAAK,CAAC,mBAAmB,KAAK,QAAQ;YAC7F,CAAC,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,mBAAmB,EAAE,CAAC;YAC9D,CAAC,CAAC,IAAI;QACR,2BAA2B,EAAE,KAAK,CAAC,2BAA2B,IAAI,OAAO,KAAK,CAAC,2BAA2B,KAAK,QAAQ;YACrH,CAAC,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,2BAA2B,EAAE,CAAC;YACtE,CAAC,CAAC,IAAI;QACR,WAAW,EAAE,cAAc;QAC3B,YAAY,EAAE,MAAM;QACpB,eAAe,EAAE,SAAS;QAC1B,gBAAgB,EAAE,UAAU;QAC5B,aAAa,EAAE,OAAO;QACtB,gBAAgB;QAChB,iBAAiB,EAAE,cAAc,CAAC,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,UAAU,IAAI,gBAAgB,CAAC;QAClG,YAAY,EAAE,cAAc,CAAC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,kBAAkB,CAAC;QAC/F,UAAU,EAAE,cAAc,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,iBAAiB,IAAI,gBAAgB,CAAC;QAC3F,cAAc,EAAE,cAAc,CAAC,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,UAAU,IAAI,gBAAgB,CAAC;QACvH,SAAS,EAAE,cAAc,CAAC,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,kBAAkB,CAAC;QAC5F,oBAAoB,EAAE,cAAc,CAAC,KAAK,CAAC,oBAAoB,CAAC;QAChE,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,IAAI,IAAI,CAAkB;QAChF,aAAa,EAAE,CAAC,KAAK,CAAC,aAAa,IAAI,IAAI,CAAkB;QAC7D,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,cAAc,IAAI,WAAW,CAAC;QACzE,QAAQ,EAAE,KAAK,CAAC,QAAQ,KAAK,KAAK;QAClC,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,SAAS,CAAW;QAC7C,KAAK,EAAE,KAAK,CAAC,KAAK,KAAK,IAAI;KAC5B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACrG,CAAC"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Usage host boundary — the ownership DECISIONS from engine
3
+ * `chat-core/usage.js` (`beginProxyTurn` :145-148,:159-173 and
4
+ * `logTurnUsage` :325-351) ported as pure functions, plus the port
5
+ * interfaces the host implements for the side effects (the proxy
6
+ * turn-start POST and the usage_logs db write) and the exact
7
+ * `usage_logs` row shape from engine `chat-server/db.js
8
+ * buildUsageLogRow` (:507).
9
+ *
10
+ * Ownership law: when `authMethod === 'amalgm'` the platform proxy meters
11
+ * and persists usage itself — the runtime must NOT double-log. Every other
12
+ * auth method is user-owned: the runtime finalizes the turn locally and
13
+ * writes one usage row, pricing it from the local catalog when the
14
+ * provider gave no cost.
15
+ */
16
+ import { type TurnUsageRecord, type UsageContract } from './finalize.js';
17
+ import type { NormalizedUsage } from './normalize.js';
18
+ export type { UsageContract } from './finalize.js';
19
+ /** Body POSTed to the proxy's `/internal/turn-start` (engine :159-173). */
20
+ export interface BeginProxyTurnBody {
21
+ sessionId: string | undefined;
22
+ messageId: string | undefined;
23
+ agentId: string | undefined;
24
+ harnessId: string | undefined;
25
+ authMethod: string | undefined;
26
+ usageOwner: string;
27
+ modelId: string | undefined;
28
+ internalModelId: string | undefined;
29
+ cliModel: string | undefined;
30
+ contextWindow: number | null;
31
+ maxTokens: number | null;
32
+ cwd: string | undefined;
33
+ mcpServers: unknown;
34
+ }
35
+ export type BeginProxyTurnDecision = {
36
+ skipped: true;
37
+ reason: 'not_amalgm';
38
+ } | {
39
+ skipped: false;
40
+ body: BeginProxyTurnBody;
41
+ };
42
+ /**
43
+ * The pure fork of engine `beginProxyTurn()`: non-amalgm auth skips the
44
+ * proxy entirely (`'not_amalgm'`); amalgm auth yields the exact
45
+ * turn-start body for the host's `BillingPort.beginTurn`. Token refresh,
46
+ * the POST, the 401 retry, and error mapping are host concerns.
47
+ */
48
+ export declare function decideBeginProxyTurn(contract: UsageContract): BeginProxyTurnDecision;
49
+ /**
50
+ * Host port for the proxy turn-start POST. The host owns base URL, token
51
+ * freshness (refresh + 401 retry-once), and mapping non-OK responses to
52
+ * coded errors (`AMALGM_PROXY_NOT_CONFIGURED`, `AMALGM_TURN_START_FAILED`,
53
+ * `balanceUsd` passthrough).
54
+ */
55
+ export interface BillingPort {
56
+ beginTurn(body: BeginProxyTurnBody): Promise<unknown>;
57
+ }
58
+ /** Camel-case payload the engine hands to `db.logUsage` (:339-349). */
59
+ export interface UsageLogPayload {
60
+ userId: string | undefined;
61
+ sessionId: string | undefined;
62
+ messageId: string | undefined;
63
+ agentId: string | undefined;
64
+ harnessId: string | undefined;
65
+ authMethod: string | undefined;
66
+ modelId: string | undefined;
67
+ usage: NormalizedUsage;
68
+ marketCostUsd: number | null;
69
+ }
70
+ /**
71
+ * The exact `usage_logs` row from engine `chat-server/db.js
72
+ * buildUsageLogRow` (:507). Note the boundary law: `NormalizedUsage`
73
+ * keeps unknown cost as null, but the persisted row coerces
74
+ * `cost_usd`/`market_cost_usd` to 0 (engine `?? 0`).
75
+ */
76
+ export interface UsageLogRow {
77
+ user_id: string | undefined;
78
+ session_id: string | null;
79
+ message_id: string | null;
80
+ agent_id: string | null;
81
+ harness_id: string | null;
82
+ auth_method: string | null;
83
+ provider: string | null;
84
+ model: string | null;
85
+ input_tokens: number;
86
+ output_tokens: number;
87
+ cache_read_tokens: number;
88
+ cache_write_tokens: number;
89
+ cost_usd: number;
90
+ market_cost_usd: number;
91
+ container_id: string | null;
92
+ }
93
+ /**
94
+ * Engine `buildUsageLogRow()`, byte-exact — except the engine's
95
+ * `process.env.AMALGM_CONTAINER_ID` read becomes the documented
96
+ * `options.containerId` parameter (falsy → null, matching the engine's
97
+ * `|| null`).
98
+ */
99
+ export declare function buildUsageLogRow({ userId, sessionId, messageId, agentId, harnessId, authMethod, modelId, usage, marketCostUsd }: UsageLogPayload, options?: {
100
+ containerId?: string | null | undefined;
101
+ }): UsageLogRow;
102
+ /** Host port for the usage_logs write (engine `db.logUsage`). */
103
+ export interface UsageLogPort {
104
+ logUsage(row: UsageLogRow): Promise<void>;
105
+ }
106
+ export type TurnUsageLogDecision = {
107
+ skipped: true;
108
+ source: 'proxy_owned_provider_usage';
109
+ reason: 'proxy_persists_usage_immediately';
110
+ } | {
111
+ skipped: true;
112
+ reason: 'no_turn_usage';
113
+ } | {
114
+ skipped: false;
115
+ source: 'local_turn_exact';
116
+ count: 1;
117
+ log: UsageLogPayload;
118
+ };
119
+ export interface DecideTurnUsageLogArgs {
120
+ contract: UsageContract;
121
+ messageId?: string | undefined;
122
+ usage?: NormalizedUsage | null | undefined;
123
+ usageRecords?: readonly TurnUsageRecord[] | null | undefined;
124
+ }
125
+ /**
126
+ * The pure decision of engine `logTurnUsage()` (:325-351):
127
+ *
128
+ * - amalgm auth → skip `{ skipped: true, source:
129
+ * 'proxy_owned_provider_usage', reason: 'proxy_persists_usage_immediately' }`
130
+ * (the proxy already persisted usage; logging here would double-bill).
131
+ * - no finalizable turn usage → skip `{ skipped: true, reason:
132
+ * 'no_turn_usage' }`.
133
+ * - otherwise → `{ skipped: false, source: 'local_turn_exact', count: 1 }`
134
+ * with the exact `db.logUsage` payload; `marketCostUsd` falls back to the
135
+ * local catalog (`calculateCost`) when the finalized usage carries none.
136
+ *
137
+ * The host performs the write:
138
+ * `usageLogPort.logUsage(buildUsageLogRow(decision.log, { containerId }))`.
139
+ */
140
+ export declare function decideTurnUsageLog({ contract, messageId, usage, usageRecords }: DecideTurnUsageLogArgs): TurnUsageLogDecision;
141
+ //# sourceMappingURL=ports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/usage/ports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Usage host boundary — the ownership DECISIONS from engine
3
+ * `chat-core/usage.js` (`beginProxyTurn` :145-148,:159-173 and
4
+ * `logTurnUsage` :325-351) ported as pure functions, plus the port
5
+ * interfaces the host implements for the side effects (the proxy
6
+ * turn-start POST and the usage_logs db write) and the exact
7
+ * `usage_logs` row shape from engine `chat-server/db.js
8
+ * buildUsageLogRow` (:507).
9
+ *
10
+ * Ownership law: when `authMethod === 'amalgm'` the platform proxy meters
11
+ * and persists usage itself — the runtime must NOT double-log. Every other
12
+ * auth method is user-owned: the runtime finalizes the turn locally and
13
+ * writes one usage row, pricing it from the local catalog when the
14
+ * provider gave no cost.
15
+ */
16
+ import { finalizeTurnUsage } from './finalize.js';
17
+ import { calculateCost } from './model-catalog.js';
18
+ /**
19
+ * The pure fork of engine `beginProxyTurn()`: non-amalgm auth skips the
20
+ * proxy entirely (`'not_amalgm'`); amalgm auth yields the exact
21
+ * turn-start body for the host's `BillingPort.beginTurn`. Token refresh,
22
+ * the POST, the 401 retry, and error mapping are host concerns.
23
+ */
24
+ export function decideBeginProxyTurn(contract) {
25
+ if (contract.authMethod !== 'amalgm') {
26
+ return { skipped: true, reason: 'not_amalgm' };
27
+ }
28
+ return {
29
+ skipped: false,
30
+ body: {
31
+ sessionId: contract.sessionId,
32
+ messageId: contract.assistantMessageId,
33
+ agentId: contract.agentId,
34
+ harnessId: contract.harness,
35
+ authMethod: contract.authMethod,
36
+ usageOwner: contract.usageOwner || 'platform_proxy',
37
+ modelId: contract.usageModelId || contract.modelId,
38
+ internalModelId: contract.modelId,
39
+ cliModel: contract.cliModel,
40
+ contextWindow: contract.contextWindow ?? null,
41
+ maxTokens: contract.maxTokens ?? null,
42
+ cwd: contract.cwd,
43
+ mcpServers: contract.mcpServers,
44
+ },
45
+ };
46
+ }
47
+ /**
48
+ * Engine `buildUsageLogRow()`, byte-exact — except the engine's
49
+ * `process.env.AMALGM_CONTAINER_ID` read becomes the documented
50
+ * `options.containerId` parameter (falsy → null, matching the engine's
51
+ * `|| null`).
52
+ */
53
+ export function buildUsageLogRow({ userId, sessionId, messageId, agentId, harnessId, authMethod, modelId, usage, marketCostUsd }, options = {}) {
54
+ const provider = modelId?.split('/')[0] || null;
55
+ return {
56
+ user_id: userId,
57
+ session_id: sessionId || null,
58
+ message_id: messageId || null,
59
+ agent_id: agentId || null,
60
+ harness_id: harnessId || null,
61
+ auth_method: authMethod || null,
62
+ provider,
63
+ model: modelId || null,
64
+ input_tokens: usage.inputTokens || 0,
65
+ output_tokens: usage.outputTokens || 0,
66
+ cache_read_tokens: usage.cacheReadTokens || 0,
67
+ cache_write_tokens: usage.cacheWriteTokens || 0,
68
+ cost_usd: usage.costUsd ?? 0,
69
+ market_cost_usd: marketCostUsd ?? usage.costUsd ?? 0,
70
+ container_id: options.containerId || null,
71
+ };
72
+ }
73
+ /**
74
+ * The pure decision of engine `logTurnUsage()` (:325-351):
75
+ *
76
+ * - amalgm auth → skip `{ skipped: true, source:
77
+ * 'proxy_owned_provider_usage', reason: 'proxy_persists_usage_immediately' }`
78
+ * (the proxy already persisted usage; logging here would double-bill).
79
+ * - no finalizable turn usage → skip `{ skipped: true, reason:
80
+ * 'no_turn_usage' }`.
81
+ * - otherwise → `{ skipped: false, source: 'local_turn_exact', count: 1 }`
82
+ * with the exact `db.logUsage` payload; `marketCostUsd` falls back to the
83
+ * local catalog (`calculateCost`) when the finalized usage carries none.
84
+ *
85
+ * The host performs the write:
86
+ * `usageLogPort.logUsage(buildUsageLogRow(decision.log, { containerId }))`.
87
+ */
88
+ export function decideTurnUsageLog({ contract, messageId, usage, usageRecords }) {
89
+ if (contract.authMethod === 'amalgm') {
90
+ return { skipped: true, source: 'proxy_owned_provider_usage', reason: 'proxy_persists_usage_immediately' };
91
+ }
92
+ const turnUsage = finalizeTurnUsage({ contract, usage, usageRecords });
93
+ if (!turnUsage)
94
+ return { skipped: true, reason: 'no_turn_usage' };
95
+ const marketCostUsd = turnUsage.marketCostUsd ?? calculateCost(contract.usageModelId || contract.modelId, turnUsage.inputTokens, turnUsage.outputTokens, turnUsage.cacheReadTokens, turnUsage.cacheWriteTokens);
96
+ return {
97
+ skipped: false,
98
+ source: 'local_turn_exact',
99
+ count: 1,
100
+ log: {
101
+ userId: contract.userId,
102
+ sessionId: contract.sessionId,
103
+ messageId,
104
+ agentId: contract.agentId,
105
+ harnessId: contract.harness,
106
+ authMethod: contract.authMethod,
107
+ modelId: contract.usageModelId || contract.modelId,
108
+ usage: turnUsage,
109
+ marketCostUsd,
110
+ },
111
+ };
112
+ }
113
+ //# sourceMappingURL=ports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/usage/ports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Token counting primitives — engine `chat-core/usage.js:11-63,118-127`,
3
+ * ported byte-exact. Owned by the usage module; the wire module imports
4
+ * `totalUsageTokens` for PromptUsage projection.
5
+ */
6
+ /** Engine `n()`: coerce to a finite number, else 0. */
7
+ export declare function n(value: unknown): number;
8
+ /**
9
+ * Engine `nonNegativeOrNull()`: the numeric value when finite and >= 0,
10
+ * else null. Note `Number(null)` is 0, so null coerces to 0 here — callers
11
+ * relying on "absent" must pass `undefined`.
12
+ */
13
+ export declare function nonNegativeOrNull(value: unknown): number | null;
14
+ /** The six-bucket token list every normalized usage record carries. */
15
+ export interface TokenList {
16
+ input: number;
17
+ output: number;
18
+ cacheRead: number;
19
+ cacheWrite: number;
20
+ thought: number;
21
+ total: number;
22
+ }
23
+ /**
24
+ * Loose input accepted by `normalizeTokenList`: either a nested
25
+ * `tokenList` (short or long key names) or flat `*Tokens` fields.
26
+ */
27
+ export interface TokenListInput {
28
+ tokenList?: unknown;
29
+ inputTokens?: unknown;
30
+ outputTokens?: unknown;
31
+ cacheReadTokens?: unknown;
32
+ cacheWriteTokens?: unknown;
33
+ thoughtTokens?: unknown;
34
+ totalTokens?: unknown;
35
+ }
36
+ /**
37
+ * Engine `normalizeTokenList()`: coerce any of the accepted key spellings
38
+ * into the canonical six-bucket list. `total` prefers an explicit
39
+ * non-negative total (nested or flat), else the computed sum of the four
40
+ * context buckets — `thought` is informational and never counted into the
41
+ * computed total.
42
+ */
43
+ export declare function normalizeTokenList(input?: TokenListInput): TokenList;
44
+ /**
45
+ * Engine `hasTokenListBuckets()`: true when any bucket coerces to a finite
46
+ * number. Mirrors the engine's `Number()` coercion exactly — `null`
47
+ * coerces to 0 (finite → true), `undefined` to NaN (→ false).
48
+ */
49
+ export declare function hasTokenListBuckets(tokenList?: Partial<Record<keyof TokenList, unknown>>): boolean;
50
+ /** Engine `zeroTokenList()`: a fresh all-zero list. */
51
+ export declare function zeroTokenList(): TokenList;
52
+ /**
53
+ * Engine `addTokenLists()`: bucket-wise sum, re-normalized (so `total` is
54
+ * recomputed from the four context buckets, never carried over).
55
+ */
56
+ export declare function addTokenLists(a?: Partial<TokenList>, b?: Partial<TokenList>): TokenList;
57
+ /**
58
+ * Engine `subtractTokenLists()`: bucket-wise `after - before`, clamped at
59
+ * 0 per bucket — a cumulative meter that reset (e.g. across compaction)
60
+ * can never produce a negative delta.
61
+ */
62
+ export declare function subtractTokenLists(after?: Partial<TokenList>, before?: Partial<TokenList>): TokenList;
63
+ export interface UsageLike {
64
+ tokenList?: {
65
+ total?: unknown;
66
+ } | undefined;
67
+ inputContextSize?: unknown;
68
+ inputTokens?: unknown;
69
+ outputTokens?: unknown;
70
+ cacheReadTokens?: unknown;
71
+ cacheWriteTokens?: unknown;
72
+ }
73
+ /**
74
+ * Total tokens for a usage record: tokenList total, else context size, else
75
+ * the sum of the four buckets. Precedence uses `||`, exactly as the engine —
76
+ * a zero total falls through to the next source.
77
+ */
78
+ export declare function totalUsageTokens(usage?: UsageLike): number;
79
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/usage/tokens.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,uDAAuD;AACvD,wBAAgB,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGxC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAG/D;AAED,uEAAuE;AACvE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,cAAmB,GAAG,SAAS,CAoBxE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,GAAE,OAAO,CAAC,MAAM,CAAC,MAAM,SAAS,EAAE,OAAO,CAAC,CAAM,GAAG,OAAO,CAGtG;AAED,uDAAuD;AACvD,wBAAgB,aAAa,IAAI,SAAS,CAEzC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAE,OAAO,CAAC,SAAS,CAAM,EAAE,CAAC,GAAE,OAAO,CAAC,SAAS,CAAM,GAAG,SAAS,CAQ/F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,OAAO,CAAC,SAAS,CAAM,EAAE,MAAM,GAAE,OAAO,CAAC,SAAS,CAAM,GAAG,SAAS,CAQ7G;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,SAAc,GAAG,MAAM,CAM9D"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Token counting primitives — engine `chat-core/usage.js:11-63,118-127`,
3
+ * ported byte-exact. Owned by the usage module; the wire module imports
4
+ * `totalUsageTokens` for PromptUsage projection.
5
+ */
6
+ /** Engine `n()`: coerce to a finite number, else 0. */
7
+ export function n(value) {
8
+ const parsed = Number(value || 0);
9
+ return Number.isFinite(parsed) ? parsed : 0;
10
+ }
11
+ /**
12
+ * Engine `nonNegativeOrNull()`: the numeric value when finite and >= 0,
13
+ * else null. Note `Number(null)` is 0, so null coerces to 0 here — callers
14
+ * relying on "absent" must pass `undefined`.
15
+ */
16
+ export function nonNegativeOrNull(value) {
17
+ const parsed = Number(value);
18
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
19
+ }
20
+ /**
21
+ * Engine `normalizeTokenList()`: coerce any of the accepted key spellings
22
+ * into the canonical six-bucket list. `total` prefers an explicit
23
+ * non-negative total (nested or flat), else the computed sum of the four
24
+ * context buckets — `thought` is informational and never counted into the
25
+ * computed total.
26
+ */
27
+ export function normalizeTokenList(input = {}) {
28
+ const tokenList = (input.tokenList && typeof input.tokenList === 'object'
29
+ ? input.tokenList
30
+ : {});
31
+ const inputTokens = n(tokenList['input'] ?? tokenList['inputTokens'] ?? input.inputTokens);
32
+ const outputTokens = n(tokenList['output'] ?? tokenList['outputTokens'] ?? input.outputTokens);
33
+ const cacheReadTokens = n(tokenList['cacheRead'] ?? tokenList['cacheReadTokens'] ?? input.cacheReadTokens);
34
+ const cacheWriteTokens = n(tokenList['cacheWrite'] ?? tokenList['cacheWriteTokens'] ?? input.cacheWriteTokens);
35
+ const thoughtTokens = n(tokenList['thought'] ?? tokenList['thoughtTokens'] ?? input.thoughtTokens);
36
+ const computedTotal = inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens;
37
+ const total = nonNegativeOrNull(tokenList['total'] ?? tokenList['totalTokens'] ?? input.totalTokens)
38
+ ?? computedTotal;
39
+ return {
40
+ input: inputTokens,
41
+ output: outputTokens,
42
+ cacheRead: cacheReadTokens,
43
+ cacheWrite: cacheWriteTokens,
44
+ thought: thoughtTokens,
45
+ total,
46
+ };
47
+ }
48
+ /**
49
+ * Engine `hasTokenListBuckets()`: true when any bucket coerces to a finite
50
+ * number. Mirrors the engine's `Number()` coercion exactly — `null`
51
+ * coerces to 0 (finite → true), `undefined` to NaN (→ false).
52
+ */
53
+ export function hasTokenListBuckets(tokenList = {}) {
54
+ return ['input', 'output', 'cacheRead', 'cacheWrite', 'thought', 'total']
55
+ .some((key) => Number.isFinite(Number(tokenList[key])));
56
+ }
57
+ /** Engine `zeroTokenList()`: a fresh all-zero list. */
58
+ export function zeroTokenList() {
59
+ return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, thought: 0, total: 0 };
60
+ }
61
+ /**
62
+ * Engine `addTokenLists()`: bucket-wise sum, re-normalized (so `total` is
63
+ * recomputed from the four context buckets, never carried over).
64
+ */
65
+ export function addTokenLists(a = {}, b = {}) {
66
+ return normalizeTokenList({
67
+ inputTokens: n(a.input) + n(b.input),
68
+ outputTokens: n(a.output) + n(b.output),
69
+ cacheReadTokens: n(a.cacheRead) + n(b.cacheRead),
70
+ cacheWriteTokens: n(a.cacheWrite) + n(b.cacheWrite),
71
+ thoughtTokens: n(a.thought) + n(b.thought),
72
+ });
73
+ }
74
+ /**
75
+ * Engine `subtractTokenLists()`: bucket-wise `after - before`, clamped at
76
+ * 0 per bucket — a cumulative meter that reset (e.g. across compaction)
77
+ * can never produce a negative delta.
78
+ */
79
+ export function subtractTokenLists(after = {}, before = {}) {
80
+ return normalizeTokenList({
81
+ inputTokens: Math.max(0, n(after.input) - n(before.input)),
82
+ outputTokens: Math.max(0, n(after.output) - n(before.output)),
83
+ cacheReadTokens: Math.max(0, n(after.cacheRead) - n(before.cacheRead)),
84
+ cacheWriteTokens: Math.max(0, n(after.cacheWrite) - n(before.cacheWrite)),
85
+ thoughtTokens: Math.max(0, n(after.thought) - n(before.thought)),
86
+ });
87
+ }
88
+ /**
89
+ * Total tokens for a usage record: tokenList total, else context size, else
90
+ * the sum of the four buckets. Precedence uses `||`, exactly as the engine —
91
+ * a zero total falls through to the next source.
92
+ */
93
+ export function totalUsageTokens(usage = {}) {
94
+ return (n(usage.tokenList?.total) ||
95
+ n(usage.inputContextSize) ||
96
+ n(usage.inputTokens) + n(usage.outputTokens) + n(usage.cacheReadTokens) + n(usage.cacheWriteTokens));
97
+ }
98
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/usage/tokens.ts"],"names":[],"mappings":"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"}