pi-commandcode-provider 0.4.0 → 0.4.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.4.2 - 2026-07-05
6
+
7
+ - Fix Oh My Pi extension validation by avoiding the missing `calculateCost` export from OMP's legacy `pi-ai` shim.
8
+ - Add a regression test that locks the local Command Code cost calculation to pi-ai's upstream `calculateCost` behavior.
9
+
10
+ ### Contributors
11
+
12
+ - @CoderTCY — reported the Oh My Pi installation failure.
13
+
14
+ ## 0.4.1 - 2026-06-16
15
+
16
+ - Use the explicit `$COMMANDCODE_API_KEY` provider registration syntax expected by newer pi versions, removing the startup deprecation warning while keeping legacy placeholder compatibility.
17
+ - Refresh development dependency lockfile entries to resolve npm audit findings for `tsx`/`esbuild` and `protobufjs`.
18
+
19
+ ### Contributors
20
+
21
+ - @plumj-am — fixed the pi provider `apiKey` deprecation warning.
22
+ - @cad0p — reported retry/deprecation-related issues that helped validate the current behavior.
23
+ - @bl4zee1g — reported provider availability concerns that prompted additional local/live validation.
24
+
5
25
  ## 0.4.0 - 2026-06-02
6
26
 
7
27
  - Add retry mechanism for transient HTTP errors (429, 5xx) and stream-level errors, configurable via pi `settings.json` `retry.provider` fields (`timeoutMs`, `maxRetries`, `maxRetryDelayMs`). Supports exponential backoff with jitter and `Retry-After` header.
package/index.ts CHANGED
@@ -12,10 +12,11 @@
12
12
  * Models are fetched from Command Code's Provider API at startup.
13
13
  */
14
14
 
15
- import { AssistantMessageEventStream, calculateCost } from "@earendil-works/pi-ai"
15
+ import { AssistantMessageEventStream } from "@earendil-works/pi-ai"
16
16
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"
17
17
 
18
18
  import { COMMAND_CODE_CLI_VERSION, createStreamCommandCode, DEFAULT_API_BASE } from "./src/core.ts"
19
+ import { calculateCommandCodeCost } from "./src/cost.ts"
19
20
  import { DEFAULT_MODELS_URL, fetchCommandCodeModels } from "./src/models.ts"
20
21
  import { getApiKey, login, refreshToken } from "./src/oauth.ts"
21
22
 
@@ -69,7 +70,7 @@ const MODEL_COSTS: Record<string, CommandCodeModelCost> = {
69
70
 
70
71
  const streamCommandCode = createStreamCommandCode({
71
72
  createStream: () => new AssistantMessageEventStream(),
72
- calculateCost,
73
+ calculateCost: calculateCommandCodeCost,
73
74
  apiBase: API_BASE,
74
75
  })
75
76
 
@@ -83,7 +84,7 @@ export default async function (pi: ExtensionAPI) {
83
84
  pi.registerProvider("commandcode", {
84
85
  name: "Command Code",
85
86
  baseUrl: API_BASE,
86
- apiKey: "COMMANDCODE_API_KEY",
87
+ apiKey: "$COMMANDCODE_API_KEY",
87
88
  authHeader: true,
88
89
  api: "commandcode-custom",
89
90
  streamSimple: streamCommandCode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-commandcode-provider",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "pi custom provider for Command Code API (commandcode.ai)",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -28,7 +28,7 @@
28
28
  "LICENSE"
29
29
  ],
30
30
  "scripts": {
31
- "test": "npm run typecheck && tsx tests/test-pure-functions.ts && tsx tests/test-models.ts && tsx tests/test-pricing.ts && tsx tests/test-oauth.ts && tsx tests/test-abort.ts && tsx tests/test-stream.ts && tsx tests/test-retry.ts && node tests/test-pi-local.mjs && node tests/test-omp-compat.mjs",
31
+ "test": "npm run typecheck && tsx tests/test-pure-functions.ts && tsx tests/test-models.ts && tsx tests/test-pricing.ts && tsx tests/test-cost.ts && tsx tests/test-oauth.ts && tsx tests/test-abort.ts && tsx tests/test-stream.ts && tsx tests/test-retry.ts && node tests/test-pi-local.mjs && node tests/test-omp-compat.mjs",
32
32
  "typecheck": "tsc --noEmit",
33
33
  "format:check": "prettier --check '**/*.{ts,mjs,json,md}'",
34
34
  "format": "prettier --write '**/*.{ts,mjs,json,md}'",
@@ -40,7 +40,8 @@
40
40
  "test:stream": "tsx tests/test-stream.ts",
41
41
  "test:retry": "tsx tests/test-retry.ts",
42
42
  "test:pi-local": "node tests/test-pi-local.mjs",
43
- "test:smoke": "node tests/test-smoke.mjs"
43
+ "test:smoke": "node tests/test-smoke.mjs",
44
+ "test:cost": "tsx tests/test-cost.ts"
44
45
  },
45
46
  "pi": {
46
47
  "extensions": [
@@ -50,7 +51,7 @@
50
51
  "devDependencies": {
51
52
  "@types/node": "25.6.0",
52
53
  "prettier": "^3.5.0",
53
- "tsx": "4.21.0",
54
+ "tsx": "4.22.4",
54
55
  "typescript": "6.0.3"
55
56
  },
56
57
  "dependencies": {
package/src/core.ts CHANGED
@@ -193,10 +193,17 @@ export function createStreamCommandCode(deps: CoreDependencies) {
193
193
  const stream = deps.createStream()
194
194
 
195
195
  async function run() {
196
- // OMP may pass the env-var name "COMMANDCODE_API_KEY" as the apiKey
197
- // value instead of resolving it. Filter out this specific string.
196
+ // OMP may pass the legacy env-var name "COMMANDCODE_API_KEY" (old pi)
197
+ // or "$COMMANDCODE_API_KEY" (new pi) as the apiKey value instead of
198
+ // resolving it. Filter out these specific strings.
199
+ const LEGACY_API_KEY_REF = "$COMMANDCODE_API_KEY"
200
+ const OLD_API_KEY_REF = "COMMANDCODE_API_KEY"
198
201
  const hostKey =
199
- options?.apiKey && options.apiKey !== "COMMANDCODE_API_KEY" ? options.apiKey : undefined
202
+ options?.apiKey &&
203
+ options.apiKey !== LEGACY_API_KEY_REF &&
204
+ options.apiKey !== OLD_API_KEY_REF
205
+ ? options.apiKey
206
+ : undefined
200
207
 
201
208
  const apiKey =
202
209
  hostKey ??
package/src/cost.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Local cost calculation for Command Code usage.
3
+ *
4
+ * Mirrors pi-ai's `calculateCost` arithmetic exactly. The provider ships its
5
+ * own copy because Oh My Pi's legacy pi-ai shim does not export
6
+ * `calculateCost`, which broke extension installation there (issue #24).
7
+ * `tests/test-cost.ts` locks this implementation to the pi-ai original.
8
+ */
9
+
10
+ import type { ModelLike, Usage } from "./types.ts"
11
+
12
+ export function calculateCommandCodeCost(model: ModelLike, usage: Usage): void {
13
+ usage.cost.input = (model.cost.input / 1_000_000) * usage.input
14
+ usage.cost.output = (model.cost.output / 1_000_000) * usage.output
15
+ usage.cost.cacheRead = (model.cost.cacheRead / 1_000_000) * usage.cacheRead
16
+ usage.cost.cacheWrite = (model.cost.cacheWrite / 1_000_000) * usage.cacheWrite
17
+ usage.cost.total =
18
+ usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite
19
+ }
package/src/types.ts CHANGED
@@ -50,11 +50,19 @@ export interface AssistantMessageLike {
50
50
  timestamp: number
51
51
  }
52
52
 
53
+ export interface ModelCost {
54
+ input: number
55
+ output: number
56
+ cacheRead: number
57
+ cacheWrite: number
58
+ }
59
+
53
60
  export interface ModelLike {
54
61
  id: string
55
62
  api: unknown
56
63
  provider: string
57
64
  maxTokens: number
65
+ cost: ModelCost
58
66
  }
59
67
 
60
68
  export interface MessageLike {