@columenlabs/lumen-ai 0.1.252 → 0.1.253

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.
@@ -16,7 +16,7 @@ import { webLookupTools } from '../subagents/web.js';
16
16
  import { bearings } from './bearings.js';
17
17
  import { CHATGPT_REDIRECT, SigninError, finishChatgpt, startChatgpt, testChatgpt, } from './chatgpt.js';
18
18
  import { ALL_MODELS, DEFAULT_OUT, Meter, PROVIDERS, XAI_BASE_URL, effortParams, } from './models.js';
19
- import { DEFAULT_CAP, State, keyDocName, keyState, ownKeyUsd, ownPlanCalls, planDocName, waitText, withProvider, } from './state.js';
19
+ import { DEFAULT_CAP, State, keyDocName, keyState, ownKeyUsd, ownPlanCalls, ownPlanUsd, planDocName, waitText, withProvider, } from './state.js';
20
20
  import { Docs } from './store.js';
21
21
  import { toolName, withDeadline } from './tools.js';
22
22
  import { scrapeqlTools, webFetchTools } from './web.js';
@@ -410,6 +410,7 @@ export class Assistant {
410
410
  title: message.split('\n')[0] || 'Chat',
411
411
  own_usd: ownKeyUsd(paying, onPayer),
412
412
  own_plan_calls: ownPlanCalls(paying, onPayer),
413
+ own_plan_usd: ownPlanUsd(paying, onPayer),
413
414
  }, end.parts)
414
415
  .catch(() => undefined);
415
416
  const total = end.parts.reduce((a, m) => ({
@@ -1096,6 +1097,7 @@ export class Assistant {
1096
1097
  title: o.run?.title ?? task?.label ?? o.task,
1097
1098
  own_usd: ownKeyUsd(paying, [part]),
1098
1099
  own_plan_calls: ownPlanCalls(paying, [part]),
1100
+ own_plan_usd: ownPlanUsd(paying, [part]),
1099
1101
  }, [part])
1100
1102
  .catch(() => undefined);
1101
1103
  }
@@ -1185,6 +1187,7 @@ export class Assistant {
1185
1187
  title: o.run?.title ?? task?.label ?? o.task,
1186
1188
  own_usd: ownKeyUsd(paying, [part]),
1187
1189
  own_plan_calls: ownPlanCalls(paying, [part]),
1190
+ own_plan_usd: ownPlanUsd(paying, [part]),
1188
1191
  }, [part])
1189
1192
  .catch(() => undefined);
1190
1193
  }
@@ -104,8 +104,19 @@ export type SpendRow = UsagePart & {
104
104
  };
105
105
  /** The provider a part ran on: by its model id, else by the model's name at the end of its label. */
106
106
  export declare function providerOfPart(p: UsagePart): AssistantProvider | undefined;
107
- /** Spend rows with the provider each ran on, so a page can tell a removed key's spend apart. */
108
- export declare function withProvider<R extends UsagePart>(rows: R[]): R[];
107
+ /**
108
+ * What a part's tokens cost at its model's API rates: the estimate shown for a plan sign-in's calls,
109
+ * which cost the person nothing. Cache writes count as plain input. Undefined for an unknown model.
110
+ */
111
+ export declare function listUsd(p: UsagePart): number | undefined;
112
+ /**
113
+ * Spend rows with the provider each ran on, so a page can tell a removed key's spend apart, and
114
+ * a $0 row (a plan's calls) with what it would cost at API rates (`list_usd`).
115
+ */
116
+ export declare function withProvider<R extends UsagePart>(rows: R[]): (R & {
117
+ provider?: "anthropic" | "openai" | "xai" | undefined;
118
+ list_usd?: number | undefined;
119
+ })[];
109
120
  /** USD of `parts` the person's own API keys paid: a provider signed in with a plan costs $0. */
110
121
  export declare function ownKeyUsd(paying: {
111
122
  payer: AssistantPayer;
@@ -116,6 +127,11 @@ export declare function ownPlanCalls(paying: {
116
127
  payer: AssistantPayer;
117
128
  plans: Paying['plans'];
118
129
  }, parts: UsagePart[]): number;
130
+ /** Those plan calls at the models' API rates: an estimate of what the plan saved the person. */
131
+ export declare function ownPlanUsd(paying: {
132
+ payer: AssistantPayer;
133
+ plans: Paying['plans'];
134
+ }, parts: UsagePart[]): number;
119
135
  /**
120
136
  * What counts toward the person's own cap: own rows paid by an API key (a plan sign-in costs
121
137
  * nothing per call), on a provider they can still pay with. A row from before ways were recorded
@@ -282,7 +298,8 @@ export declare class State {
282
298
  * Adds one answer's use to a chat or run in this month's history (`usage:YYYY-MM`): one entry a
283
299
  * chat or run, its parts merged, the newest `USAGE_KEPT` kept. `title` names a new entry only;
284
300
  * `own_usd` is what of this answer the person's own key or plan paid, added to the entry's;
285
- * `own_plan_calls` the calls their plan sign-in answered (free to them, so counted, not priced).
301
+ * `own_plan_calls` the calls their plan sign-in answered (free to them, so counted, not priced),
302
+ * `own_plan_usd` those calls at API rates (an estimate).
286
303
  */
287
304
  addUsage(id: string, e: {
288
305
  id: string;
@@ -291,6 +308,7 @@ export declare class State {
291
308
  title: string;
292
309
  own_usd?: number;
293
310
  own_plan_calls?: number;
311
+ own_plan_usd?: number;
294
312
  }, parts: UsagePart[]): Promise<void>;
295
313
  /** One month's history (this month by default) beside its spend, and the months that have one. */
296
314
  usage(id: string, month?: string): Promise<UsageHistory>;
@@ -14,11 +14,30 @@ export function providerOfPart(p) {
14
14
  KNOWN_MODELS.find((x) => p.label === x.label || p.label.endsWith(` · ${x.label}`));
15
15
  return m?.provider;
16
16
  }
17
- /** Spend rows with the provider each ran on, so a page can tell a removed key's spend apart. */
17
+ /**
18
+ * What a part's tokens cost at its model's API rates: the estimate shown for a plan sign-in's calls,
19
+ * which cost the person nothing. Cache writes count as plain input. Undefined for an unknown model.
20
+ */
21
+ export function listUsd(p) {
22
+ const m = KNOWN_MODELS.find((x) => x.id === p.model) ??
23
+ KNOWN_MODELS.find((x) => p.label === x.label || p.label.endsWith(` · ${x.label}`));
24
+ if (!m)
25
+ return undefined;
26
+ return (Math.max(0, p.in - p.read) * m.in + p.read * m.read + p.out * m.out) / 1e6;
27
+ }
28
+ /**
29
+ * Spend rows with the provider each ran on, so a page can tell a removed key's spend apart, and
30
+ * a $0 row (a plan's calls) with what it would cost at API rates (`list_usd`).
31
+ */
18
32
  export function withProvider(rows) {
19
33
  return rows.map((r) => {
20
34
  const provider = providerOfPart(r);
21
- return provider ? { ...r, provider } : r;
35
+ const list = r.calls && r.usd < 0.0005 ? listUsd(r) : undefined;
36
+ return {
37
+ ...r,
38
+ ...(provider ? { provider } : {}),
39
+ ...(list !== undefined ? { list_usd: list } : {}),
40
+ };
22
41
  });
23
42
  }
24
43
  /** USD of `parts` the person's own API keys paid: a provider signed in with a plan costs $0. */
@@ -43,6 +62,17 @@ export function ownPlanCalls(paying, parts) {
43
62
  })
44
63
  .reduce((a, p) => a + p.calls, 0);
45
64
  }
65
+ /** Those plan calls at the models' API rates: an estimate of what the plan saved the person. */
66
+ export function ownPlanUsd(paying, parts) {
67
+ if (paying.payer !== 'own')
68
+ return 0;
69
+ return parts
70
+ .filter((p) => {
71
+ const prov = providerOfPart(p);
72
+ return !!(prov && paying.plans[prov]);
73
+ })
74
+ .reduce((a, p) => a + (listUsd(p) ?? 0), 0);
75
+ }
46
76
  /**
47
77
  * What counts toward the person's own cap: own rows paid by an API key (a plan sign-in costs
48
78
  * nothing per call), on a provider they can still pay with. A row from before ways were recorded
@@ -364,7 +394,8 @@ export class State {
364
394
  * Adds one answer's use to a chat or run in this month's history (`usage:YYYY-MM`): one entry a
365
395
  * chat or run, its parts merged, the newest `USAGE_KEPT` kept. `title` names a new entry only;
366
396
  * `own_usd` is what of this answer the person's own key or plan paid, added to the entry's;
367
- * `own_plan_calls` the calls their plan sign-in answered (free to them, so counted, not priced).
397
+ * `own_plan_calls` the calls their plan sign-in answered (free to them, so counted, not priced),
398
+ * `own_plan_usd` those calls at API rates (an estimate).
368
399
  */
369
400
  async addUsage(id, e, parts) {
370
401
  if (!parts.some((p) => p.calls))
@@ -378,6 +409,7 @@ export class State {
378
409
  const sum = (k) => merged.reduce((a, p) => a + p[k], 0);
379
410
  const own = (prev?.own_usd ?? 0) + (e.own_usd ?? 0);
380
411
  const plan = (prev?.own_plan_calls ?? 0) + (e.own_plan_calls ?? 0);
412
+ const planUsd = (prev?.own_plan_usd ?? 0) + (e.own_plan_usd ?? 0);
381
413
  entries.unshift({
382
414
  id: e.id,
383
415
  kind: e.kind,
@@ -392,6 +424,7 @@ export class State {
392
424
  usd: sum('usd'),
393
425
  ...(own > 0 ? { own_usd: own } : {}),
394
426
  ...(plan > 0 ? { own_plan_calls: plan } : {}),
427
+ ...(planUsd > 0 ? { own_plan_usd: planUsd } : {}),
395
428
  parts: merged,
396
429
  });
397
430
  return { entries: entries.slice(0, USAGE_KEPT) };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@columenlabs/lumen-ai",
3
- "version": "0.1.252",
3
+ "version": "0.1.253",
4
4
  "description": "Lumen's assistant and agent parts: a chat assistant's server (Claude tiers, tools over MCP, the web, hand off, spend caps), serving an MCP server from a Worker, read-only tool sets and metered tool calls.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -56,8 +56,8 @@
56
56
  "@ai-sdk/openai": "4.0.108",
57
57
  "@anthropic-ai/sdk": "0.133.0",
58
58
  "@cloudflare/think": "0.23.0",
59
- "@columenlabs/lumen-ops": "0.1.252",
60
- "@columenlabs/lumen-ui-types": "0.1.252",
59
+ "@columenlabs/lumen-ops": "0.1.253",
60
+ "@columenlabs/lumen-ui-types": "0.1.253",
61
61
  "agents": "0.32.0",
62
62
  "ai": "7.0.162",
63
63
  "just-bash": "3.6.0",