portable-agent-layer 0.62.0 → 0.62.1

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.
@@ -18,6 +18,20 @@
18
18
  "Bash(stat //*)",
19
19
  "Bash(readlink //*)",
20
20
  "Bash(lsof *)",
21
+ "Bash(rtk read *)",
22
+ "Bash(rtk ls *)",
23
+ "Bash(rtk tree *)",
24
+ "Bash(rtk find *)",
25
+ "Bash(rtk grep *)",
26
+ "Bash(rtk rg *)",
27
+ "Bash(rtk wc *)",
28
+ "Bash(rtk diff *)",
29
+ "Bash(rtk json *)",
30
+ "Bash(rtk log *)",
31
+ "Bash(rtk deps *)",
32
+ "Bash(rtk env *)",
33
+ "Bash(rtk smart *)",
34
+ "Bash(rtk gain *)",
21
35
  "Bash(bun ~/.pal/skills/*/tools/*.ts *)",
22
36
  "Bash(bun ~/.pal/tools/*.ts *)",
23
37
  "Bash(node --experimental-strip-types ~/.pal/skills/consulting-report/tools/generate-pdf.ts *)"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portable-agent-layer",
3
- "version": "0.62.0",
3
+ "version": "0.62.1",
4
4
  "description": "PAL — Portable Agent Layer: persistent personal context for AI coding assistants",
5
5
  "type": "module",
6
6
  "bin": {
@@ -26,17 +26,24 @@ export function flagshipAuthorModel(agent: AgentType): string | undefined {
26
26
  return FLAGSHIP_AUTHOR_MODEL[agent];
27
27
  }
28
28
 
29
+ export interface ModelPricing {
30
+ input: number;
31
+ output: number;
32
+ cacheWrite5m: number;
33
+ cacheWrite1h: number;
34
+ cacheRead: number;
35
+ }
36
+
37
+ export interface TokenUsage {
38
+ input: number;
39
+ output: number;
40
+ cacheWrite5m: number;
41
+ cacheWrite1h: number;
42
+ cacheRead: number;
43
+ }
44
+
29
45
  /** Pricing per million tokens (USD) — from https://platform.claude.com/docs/en/about-claude/pricing */
30
- export const MODEL_PRICING: Record<
31
- string,
32
- {
33
- input: number;
34
- output: number;
35
- cacheWrite5m: number;
36
- cacheWrite1h: number;
37
- cacheRead: number;
38
- }
39
- > = {
46
+ export const MODEL_PRICING: Record<string, ModelPricing> = {
40
47
  [HAIKU_MODEL]: {
41
48
  input: 1,
42
49
  output: 5,
@@ -51,6 +58,13 @@ export const MODEL_PRICING: Record<
51
58
  cacheWrite1h: 20,
52
59
  cacheRead: 1,
53
60
  },
61
+ "claude-opus-5": {
62
+ input: 5,
63
+ output: 25,
64
+ cacheWrite5m: 6.25,
65
+ cacheWrite1h: 10,
66
+ cacheRead: 0.5,
67
+ },
54
68
  "claude-opus-4-8": {
55
69
  input: 5,
56
70
  output: 25,
@@ -72,6 +86,13 @@ export const MODEL_PRICING: Record<
72
86
  cacheWrite1h: 10,
73
87
  cacheRead: 0.5,
74
88
  },
89
+ "claude-opus-4-5": {
90
+ input: 5,
91
+ output: 25,
92
+ cacheWrite5m: 6.25,
93
+ cacheWrite1h: 10,
94
+ cacheRead: 0.5,
95
+ },
75
96
  // Claude Sonnet 5 — introductory pricing through 2026-08-31; standard (3/15/3.75/6/0.30) applies from 2026-09-01.
76
97
  "claude-sonnet-5": {
77
98
  input: 2,
@@ -95,3 +116,37 @@ export const MODEL_PRICING: Record<
95
116
  cacheRead: 0.3,
96
117
  },
97
118
  };
119
+
120
+ function longestPrefixKey(model: string): string | null {
121
+ let best: string | null = null;
122
+ for (const key of Object.keys(MODEL_PRICING)) {
123
+ if (model.startsWith(key) && (best === null || key.length > best.length)) best = key;
124
+ }
125
+ return best;
126
+ }
127
+
128
+ /**
129
+ * Rates for a model ID. Transcripts carry variants of the same model — dated
130
+ * (`claude-opus-5-20260115`) and context-tagged (`claude-opus-5[1m]`) — so an
131
+ * exact miss falls back to the longest table key the ID starts with.
132
+ */
133
+ export function pricingFor(model: string): ModelPricing | null {
134
+ const exact = MODEL_PRICING[model];
135
+ if (exact) return exact;
136
+ const prefix = longestPrefixKey(model);
137
+ return prefix ? MODEL_PRICING[prefix] : null;
138
+ }
139
+
140
+ /** USD cost of a token usage record. Unpriced models bill as 0. */
141
+ export function costOfUsage(model: string, usage: TokenUsage): number {
142
+ const p = pricingFor(model);
143
+ if (!p) return 0;
144
+ return (
145
+ (usage.input * p.input +
146
+ usage.output * p.output +
147
+ usage.cacheWrite5m * p.cacheWrite5m +
148
+ usage.cacheWrite1h * p.cacheWrite1h +
149
+ usage.cacheRead * p.cacheRead) /
150
+ 1_000_000
151
+ );
152
+ }
@@ -9,7 +9,7 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
9
9
  import { homedir } from "node:os";
10
10
  import { resolve } from "node:path";
11
11
  import { parseArgs } from "node:util";
12
- import { MODEL_PRICING } from "../hooks/lib/models";
12
+ import { costOfUsage } from "../hooks/lib/models";
13
13
 
14
14
  // ── Types ──
15
15
 
@@ -142,16 +142,13 @@ function parseSession(filepath: string, sessionId: string): Usage {
142
142
  : (u.cache_creation_input_tokens ?? 0);
143
143
  const cacheWrite1h = cw1h ?? 0;
144
144
 
145
- const p = MODEL_PRICING[model];
146
- if (p) {
147
- usage.cost +=
148
- (input * p.input +
149
- output * p.output +
150
- cacheWrite5m * p.cacheWrite5m +
151
- cacheWrite1h * p.cacheWrite1h +
152
- cr * p.cacheRead) /
153
- 1_000_000;
154
- }
145
+ usage.cost += costOfUsage(model, {
146
+ input,
147
+ output,
148
+ cacheWrite5m,
149
+ cacheWrite1h,
150
+ cacheRead: cr,
151
+ });
155
152
 
156
153
  usage.input += input;
157
154
  usage.output += output;
@@ -13,7 +13,7 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
13
13
  import { homedir } from "node:os";
14
14
  import { resolve } from "node:path";
15
15
  import { parseArgs } from "node:util";
16
- import { MODEL_PRICING } from "../hooks/lib/models";
16
+ import { costOfUsage } from "../hooks/lib/models";
17
17
  import { palHome } from "../hooks/lib/paths";
18
18
  import { findBinaryOnPath } from "../hooks/lib/which";
19
19
 
@@ -59,34 +59,6 @@ function emptyTimeBuckets(): TimeBuckets {
59
59
 
60
60
  // ── Helpers ──
61
61
 
62
- function findPricing(model: string): (typeof MODEL_PRICING)[string] | null {
63
- if (MODEL_PRICING[model]) return MODEL_PRICING[model];
64
- for (const key of Object.keys(MODEL_PRICING)) {
65
- if (model.startsWith(key)) return MODEL_PRICING[key];
66
- }
67
- return null;
68
- }
69
-
70
- function costForUsage(
71
- model: string,
72
- input: number,
73
- output: number,
74
- cacheWrite5m: number,
75
- cacheWrite1h: number,
76
- cacheRead: number
77
- ): number {
78
- const p = findPricing(model);
79
- if (!p) return 0;
80
- return (
81
- (input * p.input +
82
- output * p.output +
83
- cacheWrite5m * p.cacheWrite5m +
84
- cacheWrite1h * p.cacheWrite1h +
85
- cacheRead * p.cacheRead) /
86
- 1_000_000
87
- );
88
- }
89
-
90
62
  function addToBucket(
91
63
  bucket: Bucket,
92
64
  model: string,
@@ -101,14 +73,13 @@ function addToBucket(
101
73
  bucket.cacheWrite5m += cacheWrite5m;
102
74
  bucket.cacheWrite1h += cacheWrite1h;
103
75
  bucket.cacheRead += cacheRead;
104
- bucket.cost += costForUsage(
105
- model,
76
+ bucket.cost += costOfUsage(model, {
106
77
  input,
107
78
  output,
108
79
  cacheWrite5m,
109
80
  cacheWrite1h,
110
- cacheRead
111
- );
81
+ cacheRead,
82
+ });
112
83
  bucket.calls++;
113
84
  }
114
85