@thehammer/danx-session-telemetry 0.1.39 → 0.1.42

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/README.md CHANGED
File without changes
@@ -0,0 +1 @@
1
+ f4864e2bc2491a9df2c4f0c3ec86da8a35ad36225049696e9e2ca5b544931859
@@ -1,5 +1,9 @@
1
- /** The one tool a sub-agent reaches the dashboard API through (the MCP server key is `danx-dashboard`). */
2
- export declare const DASHBOARD_API_TOOL_NAME = "mcp__danx-dashboard__danxbot_api";
1
+ /** The `danxbot_api` tool of a dispatched worker's `danx-dashboard` server. */
2
+ export declare const DISPATCH_API_TOOL_NAME = "mcp__danx-dashboard__danxbot_api";
3
+ /** The `danxbot_api` tool of the danxbot plugin's server, which an operator session's sub-agent calls. */
4
+ export declare const PLUGIN_API_TOOL_NAME = "mcp__plugin_danxbot_danx-dashboard__danxbot_api";
5
+ /** Every tool name a sub-agent reaches the dashboard API through. */
6
+ export declare const DASHBOARD_API_TOOL_NAMES: ReadonlySet<string>;
3
7
  /** A card id as the issue routes name it, e.g. `DX-3962`. Also the wire's validation for every card id a claim carries. */
4
8
  export declare const ISSUE_ID_PATTERN: RegExp;
5
9
  /** Longest card id a claim may carry (`dispatches.issue_id` is `VARCHAR(32)`). */
@@ -46,8 +46,14 @@
46
46
  * Pure bookkeeping — no `node:` imports, so it rides the browser-safe subpath too.
47
47
  */
48
48
  import { MAIN_SOURCE } from "./usage-ledger.js";
49
- /** The one tool a sub-agent reaches the dashboard API through (the MCP server key is `danx-dashboard`). */
50
- export const DASHBOARD_API_TOOL_NAME = "mcp__danx-dashboard__danxbot_api";
49
+ // DX-4578: both names are live, neither a fallback. A dispatched worker's clean-room config names the server `danx-dashboard`; an operator
50
+ // session's sub-agent reaches it through the danxbot plugin's server (`plugin:danxbot:danx-dashboard`, tools `mcp__plugin_danxbot_danx-dashboard__*`).
51
+ /** The `danxbot_api` tool of a dispatched worker's `danx-dashboard` server. */
52
+ export const DISPATCH_API_TOOL_NAME = "mcp__danx-dashboard__danxbot_api";
53
+ /** The `danxbot_api` tool of the danxbot plugin's server, which an operator session's sub-agent calls. */
54
+ export const PLUGIN_API_TOOL_NAME = "mcp__plugin_danxbot_danx-dashboard__danxbot_api";
55
+ /** Every tool name a sub-agent reaches the dashboard API through. */
56
+ export const DASHBOARD_API_TOOL_NAMES = new Set([DISPATCH_API_TOOL_NAME, PLUGIN_API_TOOL_NAME]);
51
57
  /** A card id as the issue routes name it, e.g. `DX-3962`. Also the wire's validation for every card id a claim carries. */
52
58
  export const ISSUE_ID_PATTERN = /^[A-Za-z][A-Za-z0-9]*-[0-9]+$/;
53
59
  /** Longest card id a claim may carry (`dispatches.issue_id` is `VARCHAR(32)`). */
@@ -102,7 +108,7 @@ function resultSucceeded(block) {
102
108
  }
103
109
  /** The transition a `tool_use` block asks for, or `null` when it is not a claim or release of a card. */
104
110
  function transitionOf(block) {
105
- if (block.type !== "tool_use" || block.name !== DASHBOARD_API_TOOL_NAME)
111
+ if (block.type !== "tool_use" || typeof block.name !== "string" || !DASHBOARD_API_TOOL_NAMES.has(block.name))
106
112
  return null;
107
113
  const input = block.input;
108
114
  if (input === null || typeof input !== "object")
package/dist/pricing.d.ts CHANGED
@@ -114,15 +114,28 @@ export type PriceResult = {
114
114
  * cleanly, whatever its id looks like.
115
115
  */
116
116
  export declare function priceUsage(model: string, speed: string, tokens: PricedTokens): PriceResult;
117
+ /**
118
+ * The list price `priceUsage` charges for a model at a speed (a fast request on a model that bills fast at the standard rate reads the
119
+ * standard table), or `null` when the tables have none. The default `PriceLookup` of {@link priceLedgerCredit}.
120
+ */
121
+ export declare function listedPrice(model: string, speed: string): ModelPrice | null;
122
+ /**
123
+ * DX-4595 - dollars for `tokens` at `price` (USD per million tokens): each bucket with its own price. The ONE copy of the formula: `priceUsage`
124
+ * charges the list price with it, and spend pacing charges an account's own (editable) prices with it.
125
+ */
126
+ export declare function costOfTokens(tokens: PricedTokens, price: ModelPrice): number;
117
127
  /** True when `model` has a standard-speed price (used by tests + guards). */
118
128
  export declare function isPricedModel(model: string): boolean;
129
+ /** What a model costs at a speed, per million tokens; `null` when there is no price. */
130
+ export type PriceLookup = (model: string, speed: string) => ModelPrice | null;
119
131
  /**
120
132
  * DX-4508 — one ledger credit's cost, exactly as the server's usage-ledger writer stores it (moved here from
121
133
  * `src/dashboard/usage-ledger.ts` so the live sub-agent view, `subagent-live.ts`, prices a reply with the SAME rule
122
134
  * instead of a copy): a `<synthetic>` reply costs nothing and is never unpriced; a reply with no model is unpriced only
123
- * when it carries tokens; any other model goes through {@link priceUsage}, an unpriced one costing 0 and naming itself.
135
+ * when it carries tokens; any other model is priced by `priceOf` (the list prices by default, so as {@link priceUsage} does), an unpriced
136
+ * one costing 0 and naming itself. DX-4595: spend pacing passes an account's own prices as `priceOf` and so gets the same rule.
124
137
  */
125
- export declare function priceLedgerCredit(model: string | null, speed: string, tokens: PricedTokens): {
138
+ export declare function priceLedgerCredit(model: string | null, speed: string, tokens: PricedTokens, priceOf?: PriceLookup): {
126
139
  costUsd: number;
127
140
  unpriced: {
128
141
  model: string;
package/dist/pricing.js CHANGED
@@ -163,20 +163,29 @@ export function listListPrices() {
163
163
  * cleanly, whatever its id looks like.
164
164
  */
165
165
  export function priceUsage(model, speed, tokens) {
166
+ const price = listedPrice(model, speed);
167
+ return price === null ? { kind: "unpriced", model, speed } : { kind: "priced", costUsd: costOfTokens(tokens, price) };
168
+ }
169
+ /**
170
+ * The list price `priceUsage` charges for a model at a speed (a fast request on a model that bills fast at the standard rate reads the
171
+ * standard table), or `null` when the tables have none. The default `PriceLookup` of {@link priceLedgerCredit}.
172
+ */
173
+ export function listedPrice(model, speed) {
166
174
  const useFastTable = speed === FAST_SPEED && !FAST_BILLS_AT_STANDARD_RATE.has(model);
167
175
  const table = useFastTable ? FAST_PRICING : PRICING;
168
- if (!Object.hasOwn(table, model))
169
- return { kind: "unpriced", model, speed };
170
- const p = table[model];
171
- return {
172
- kind: "priced",
173
- costUsd: (tokens.input * p.input +
174
- tokens.output * p.output +
175
- tokens.cacheRead * p.cacheRead +
176
- tokens.cacheWrite5m * p.cacheWrite5m +
177
- tokens.cacheWrite1h * p.cacheWrite1h) /
178
- 1_000_000,
179
- };
176
+ return Object.hasOwn(table, model) ? table[model] : null;
177
+ }
178
+ /**
179
+ * DX-4595 - dollars for `tokens` at `price` (USD per million tokens): each bucket with its own price. The ONE copy of the formula: `priceUsage`
180
+ * charges the list price with it, and spend pacing charges an account's own (editable) prices with it.
181
+ */
182
+ export function costOfTokens(tokens, price) {
183
+ return ((tokens.input * price.input +
184
+ tokens.output * price.output +
185
+ tokens.cacheRead * price.cacheRead +
186
+ tokens.cacheWrite5m * price.cacheWrite5m +
187
+ tokens.cacheWrite1h * price.cacheWrite1h) /
188
+ 1_000_000);
180
189
  }
181
190
  /** True when `model` has a standard-speed price (used by tests + guards). */
182
191
  export function isPricedModel(model) {
@@ -188,15 +197,16 @@ export function isPricedModel(model) {
188
197
  * DX-4508 — one ledger credit's cost, exactly as the server's usage-ledger writer stores it (moved here from
189
198
  * `src/dashboard/usage-ledger.ts` so the live sub-agent view, `subagent-live.ts`, prices a reply with the SAME rule
190
199
  * instead of a copy): a `<synthetic>` reply costs nothing and is never unpriced; a reply with no model is unpriced only
191
- * when it carries tokens; any other model goes through {@link priceUsage}, an unpriced one costing 0 and naming itself.
200
+ * when it carries tokens; any other model is priced by `priceOf` (the list prices by default, so as {@link priceUsage} does), an unpriced
201
+ * one costing 0 and naming itself. DX-4595: spend pacing passes an account's own prices as `priceOf` and so gets the same rule.
192
202
  */
193
- export function priceLedgerCredit(model, speed, tokens) {
203
+ export function priceLedgerCredit(model, speed, tokens, priceOf = listedPrice) {
194
204
  if (model === SYNTHETIC_MODEL)
195
205
  return { costUsd: 0, unpriced: null };
196
206
  if (model === null) {
197
207
  const zero = tokens.input === 0 && tokens.output === 0 && tokens.cacheRead === 0 && tokens.cacheWrite5m === 0 && tokens.cacheWrite1h === 0;
198
208
  return zero ? { costUsd: 0, unpriced: null } : { costUsd: 0, unpriced: { model: "(none)", speed } };
199
209
  }
200
- const r = priceUsage(model, speed, tokens);
201
- return r.kind === "priced" ? { costUsd: r.costUsd, unpriced: null } : { costUsd: 0, unpriced: { model: r.model, speed: r.speed } };
210
+ const price = priceOf(model, speed);
211
+ return price === null ? { costUsd: 0, unpriced: { model, speed } } : { costUsd: costOfTokens(tokens, price), unpriced: null };
202
212
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thehammer/danx-session-telemetry",
3
- "version": "0.1.39",
3
+ "version": "0.1.42",
4
4
  "description": "Shared Claude Code transcript collector (DX-2962) — incremental JSONL tailing for the danxbot worker and the danx-dashboard-mcp desktop bridge, so both run identical collector code.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,6 +31,7 @@
31
31
  "node": ">=20"
32
32
  },
33
33
  "scripts": {
34
+ "prepublishOnly": "bash ../../scripts/assert-tree-contains-origin-main.sh @thehammer/danx-session-telemetry",
34
35
  "build": "tsc -p tsconfig.json",
35
36
  "verify:boot": "bash scripts/verify-boot.sh",
36
37
  "test": "vitest run",