@codemieai/code 0.15.3 → 0.15.5

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 (208) hide show
  1. package/dist/agents/core/AgentCLI.d.ts.map +1 -1
  2. package/dist/agents/core/AgentCLI.js +9 -0
  3. package/dist/agents/core/AgentCLI.js.map +1 -1
  4. package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
  5. package/dist/agents/core/BaseAgentAdapter.js +34 -9
  6. package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
  7. package/dist/agents/plugins/claude/claude.models.d.ts +58 -0
  8. package/dist/agents/plugins/claude/claude.models.d.ts.map +1 -1
  9. package/dist/agents/plugins/claude/claude.models.js +196 -10
  10. package/dist/agents/plugins/claude/claude.models.js.map +1 -1
  11. package/dist/agents/plugins/claude/claude.plugin.d.ts.map +1 -1
  12. package/dist/agents/plugins/claude/claude.plugin.js +147 -45
  13. package/dist/agents/plugins/claude/claude.plugin.js.map +1 -1
  14. package/dist/agents/plugins/claude/plugin/statusline.bundle.mjs +729 -0
  15. package/dist/agents/plugins/claude/statusline-installer.d.ts +1 -1
  16. package/dist/agents/plugins/claude/statusline-installer.d.ts.map +1 -1
  17. package/dist/agents/plugins/claude/statusline-installer.js +41 -3
  18. package/dist/agents/plugins/claude/statusline-installer.js.map +1 -1
  19. package/dist/agents/plugins/codex/codex-models.d.ts.map +1 -1
  20. package/dist/agents/plugins/codex/codex-models.js +109 -8
  21. package/dist/agents/plugins/codex/codex-models.js.map +1 -1
  22. package/dist/agents/plugins/codex/codex.correlation.d.ts +39 -0
  23. package/dist/agents/plugins/codex/codex.correlation.d.ts.map +1 -0
  24. package/dist/agents/plugins/codex/codex.correlation.js +150 -0
  25. package/dist/agents/plugins/codex/codex.correlation.js.map +1 -0
  26. package/dist/agents/plugins/codex/codex.plugin.d.ts.map +1 -1
  27. package/dist/agents/plugins/codex/codex.plugin.js +8 -40
  28. package/dist/agents/plugins/codex/codex.plugin.js.map +1 -1
  29. package/dist/agents/plugins/kimi/kimi.env-model.d.ts +27 -0
  30. package/dist/agents/plugins/kimi/kimi.env-model.d.ts.map +1 -0
  31. package/dist/agents/plugins/kimi/kimi.env-model.js +52 -0
  32. package/dist/agents/plugins/kimi/kimi.env-model.js.map +1 -0
  33. package/dist/agents/plugins/kimi/kimi.session.d.ts +6 -0
  34. package/dist/agents/plugins/kimi/kimi.session.d.ts.map +1 -1
  35. package/dist/agents/plugins/kimi/kimi.session.js +24 -2
  36. package/dist/agents/plugins/kimi/kimi.session.js.map +1 -1
  37. package/dist/agents/plugins/opencode/opencode-dynamic-models.js +1 -1
  38. package/dist/agents/plugins/opencode/opencode-dynamic-models.js.map +1 -1
  39. package/dist/cli/commands/analytics/cost/cost-enricher.d.ts +19 -2
  40. package/dist/cli/commands/analytics/cost/cost-enricher.d.ts.map +1 -1
  41. package/dist/cli/commands/analytics/cost/cost-enricher.js +171 -14
  42. package/dist/cli/commands/analytics/cost/cost-enricher.js.map +1 -1
  43. package/dist/cli/commands/analytics/cost/local-models.d.ts +15 -0
  44. package/dist/cli/commands/analytics/cost/local-models.d.ts.map +1 -0
  45. package/dist/cli/commands/analytics/cost/local-models.js +21 -0
  46. package/dist/cli/commands/analytics/cost/local-models.js.map +1 -0
  47. package/dist/cli/commands/analytics/cost/types.d.ts +60 -0
  48. package/dist/cli/commands/analytics/cost/types.d.ts.map +1 -1
  49. package/dist/cli/commands/analytics/cost/types.js.map +1 -1
  50. package/dist/cli/commands/analytics/cost/usage-readers.d.ts +25 -2
  51. package/dist/cli/commands/analytics/cost/usage-readers.d.ts.map +1 -1
  52. package/dist/cli/commands/analytics/cost/usage-readers.js +61 -3
  53. package/dist/cli/commands/analytics/cost/usage-readers.js.map +1 -1
  54. package/dist/cli/commands/analytics/formatter.d.ts +11 -0
  55. package/dist/cli/commands/analytics/formatter.d.ts.map +1 -1
  56. package/dist/cli/commands/analytics/formatter.js +28 -0
  57. package/dist/cli/commands/analytics/formatter.js.map +1 -1
  58. package/dist/cli/commands/analytics/index.d.ts.map +1 -1
  59. package/dist/cli/commands/analytics/index.js +113 -72
  60. package/dist/cli/commands/analytics/index.js.map +1 -1
  61. package/dist/cli/commands/analytics/otel-loader.d.ts.map +1 -1
  62. package/dist/cli/commands/analytics/otel-loader.js +60 -14
  63. package/dist/cli/commands/analytics/otel-loader.js.map +1 -1
  64. package/dist/cli/commands/analytics/otel-pricing.d.ts +38 -0
  65. package/dist/cli/commands/analytics/otel-pricing.d.ts.map +1 -0
  66. package/dist/cli/commands/analytics/otel-pricing.js +33 -0
  67. package/dist/cli/commands/analytics/otel-pricing.js.map +1 -0
  68. package/dist/cli/commands/analytics/report/client/app.js +279 -18
  69. package/dist/cli/commands/analytics/report/output-target.d.ts +22 -0
  70. package/dist/cli/commands/analytics/report/output-target.d.ts.map +1 -0
  71. package/dist/cli/commands/analytics/report/output-target.js +56 -0
  72. package/dist/cli/commands/analytics/report/output-target.js.map +1 -0
  73. package/dist/cli/commands/analytics/report/payload-builder.d.ts.map +1 -1
  74. package/dist/cli/commands/analytics/report/payload-builder.js +6 -0
  75. package/dist/cli/commands/analytics/report/payload-builder.js.map +1 -1
  76. package/dist/cli/commands/analytics/report/report-generator.d.ts +1 -1
  77. package/dist/cli/commands/analytics/report/report-generator.js +1 -1
  78. package/dist/cli/commands/analytics/report/session-report.d.ts +1 -3
  79. package/dist/cli/commands/analytics/report/session-report.d.ts.map +1 -1
  80. package/dist/cli/commands/analytics/report/session-report.js +1 -3
  81. package/dist/cli/commands/analytics/report/session-report.js.map +1 -1
  82. package/dist/cli/commands/analytics/report/template.html +6 -6
  83. package/dist/cli/commands/analytics/report/types.d.ts +17 -1
  84. package/dist/cli/commands/analytics/report/types.d.ts.map +1 -1
  85. package/dist/cli/commands/analytics/sources/sessions-source.d.ts.map +1 -1
  86. package/dist/cli/commands/analytics/sources/sessions-source.js +9 -11
  87. package/dist/cli/commands/analytics/sources/sessions-source.js.map +1 -1
  88. package/dist/cli/commands/analytics/sources/types.d.ts +0 -2
  89. package/dist/cli/commands/analytics/sources/types.d.ts.map +1 -1
  90. package/dist/cli/commands/analytics/types.d.ts +13 -7
  91. package/dist/cli/commands/analytics/types.d.ts.map +1 -1
  92. package/dist/cli/commands/doctor/checks/NpmPrefixOverrideCheck.d.ts +9 -0
  93. package/dist/cli/commands/doctor/checks/NpmPrefixOverrideCheck.d.ts.map +1 -0
  94. package/dist/cli/commands/doctor/checks/NpmPrefixOverrideCheck.js +42 -0
  95. package/dist/cli/commands/doctor/checks/NpmPrefixOverrideCheck.js.map +1 -0
  96. package/dist/cli/commands/doctor/checks/index.d.ts +1 -0
  97. package/dist/cli/commands/doctor/checks/index.d.ts.map +1 -1
  98. package/dist/cli/commands/doctor/checks/index.js +1 -0
  99. package/dist/cli/commands/doctor/checks/index.js.map +1 -1
  100. package/dist/cli/commands/doctor/index.d.ts.map +1 -1
  101. package/dist/cli/commands/doctor/index.js +2 -1
  102. package/dist/cli/commands/doctor/index.js.map +1 -1
  103. package/dist/cli/commands/models.d.ts.map +1 -1
  104. package/dist/cli/commands/models.js +16 -3
  105. package/dist/cli/commands/models.js.map +1 -1
  106. package/dist/cli/commands/proxy/connect-orchestrator.js +1 -1
  107. package/dist/cli/commands/proxy/connect-orchestrator.js.map +1 -1
  108. package/dist/cli/commands/proxy/connectors/tenant-catalog.d.ts +16 -4
  109. package/dist/cli/commands/proxy/connectors/tenant-catalog.d.ts.map +1 -1
  110. package/dist/cli/commands/proxy/connectors/tenant-catalog.js +42 -14
  111. package/dist/cli/commands/proxy/connectors/tenant-catalog.js.map +1 -1
  112. package/dist/cli/commands/proxy/connectors/vscode-models.d.ts +18 -0
  113. package/dist/cli/commands/proxy/connectors/vscode-models.d.ts.map +1 -1
  114. package/dist/cli/commands/proxy/connectors/vscode-models.js +58 -0
  115. package/dist/cli/commands/proxy/connectors/vscode-models.js.map +1 -1
  116. package/dist/cli/commands/proxy/connectors/vscode.d.ts +2 -2
  117. package/dist/cli/commands/proxy/connectors/vscode.d.ts.map +1 -1
  118. package/dist/cli/commands/proxy/connectors/vscode.js +27 -38
  119. package/dist/cli/commands/proxy/connectors/vscode.js.map +1 -1
  120. package/dist/cli/commands/update.d.ts.map +1 -1
  121. package/dist/cli/commands/update.js +4 -3
  122. package/dist/cli/commands/update.js.map +1 -1
  123. package/dist/frameworks/plugins/codegraph.plugin.js +2 -2
  124. package/dist/frameworks/plugins/codegraph.plugin.js.map +1 -1
  125. package/dist/providers/core/codemie-auth-helpers.d.ts.map +1 -1
  126. package/dist/providers/core/codemie-auth-helpers.js +6 -1
  127. package/dist/providers/core/codemie-auth-helpers.js.map +1 -1
  128. package/dist/providers/core/default-agent-hooks.d.ts.map +1 -1
  129. package/dist/providers/core/default-agent-hooks.js +9 -0
  130. package/dist/providers/core/default-agent-hooks.js.map +1 -1
  131. package/dist/providers/plugins/bedrock/bedrock.template.d.ts.map +1 -1
  132. package/dist/providers/plugins/bedrock/bedrock.template.js +5 -31
  133. package/dist/providers/plugins/bedrock/bedrock.template.js.map +1 -1
  134. package/dist/providers/plugins/sso/proxy/plugins/background-request-normalizer.plugin.d.ts +44 -0
  135. package/dist/providers/plugins/sso/proxy/plugins/background-request-normalizer.plugin.d.ts.map +1 -0
  136. package/dist/providers/plugins/sso/proxy/plugins/background-request-normalizer.plugin.js +106 -0
  137. package/dist/providers/plugins/sso/proxy/plugins/background-request-normalizer.plugin.js.map +1 -0
  138. package/dist/providers/plugins/sso/proxy/plugins/index.d.ts +3 -1
  139. package/dist/providers/plugins/sso/proxy/plugins/index.d.ts.map +1 -1
  140. package/dist/providers/plugins/sso/proxy/plugins/index.js +5 -1
  141. package/dist/providers/plugins/sso/proxy/plugins/index.js.map +1 -1
  142. package/dist/providers/plugins/sso/proxy/plugins/routing-header-injector.plugin.d.ts +67 -0
  143. package/dist/providers/plugins/sso/proxy/plugins/routing-header-injector.plugin.d.ts.map +1 -0
  144. package/dist/providers/plugins/sso/proxy/plugins/routing-header-injector.plugin.js +203 -0
  145. package/dist/providers/plugins/sso/proxy/plugins/routing-header-injector.plugin.js.map +1 -0
  146. package/dist/providers/plugins/sso/sso.http-client.d.ts +95 -0
  147. package/dist/providers/plugins/sso/sso.http-client.d.ts.map +1 -1
  148. package/dist/providers/plugins/sso/sso.http-client.js +79 -0
  149. package/dist/providers/plugins/sso/sso.http-client.js.map +1 -1
  150. package/dist/providers/plugins/sso/sso.models.d.ts +7 -0
  151. package/dist/providers/plugins/sso/sso.models.d.ts.map +1 -1
  152. package/dist/providers/plugins/sso/sso.models.js +22 -14
  153. package/dist/providers/plugins/sso/sso.models.js.map +1 -1
  154. package/dist/utils/bedrock-pricing.mjs +111 -0
  155. package/dist/utils/cli-bin.d.ts.map +1 -1
  156. package/dist/utils/cli-bin.js +3 -4
  157. package/dist/utils/cli-bin.js.map +1 -1
  158. package/dist/utils/cli-updater.d.ts +1 -0
  159. package/dist/utils/cli-updater.d.ts.map +1 -1
  160. package/dist/utils/cli-updater.js +37 -9
  161. package/dist/utils/cli-updater.js.map +1 -1
  162. package/dist/utils/credential-crypto.d.ts +51 -0
  163. package/dist/utils/credential-crypto.d.ts.map +1 -0
  164. package/dist/utils/credential-crypto.js +96 -0
  165. package/dist/utils/credential-crypto.js.map +1 -0
  166. package/dist/utils/model-normalizer.d.ts +6 -0
  167. package/dist/utils/model-normalizer.d.ts.map +1 -1
  168. package/dist/utils/model-normalizer.js +37 -19
  169. package/dist/utils/model-normalizer.js.map +1 -1
  170. package/dist/utils/npm-prefix.d.ts +48 -0
  171. package/dist/utils/npm-prefix.d.ts.map +1 -0
  172. package/dist/utils/npm-prefix.js +142 -0
  173. package/dist/utils/npm-prefix.js.map +1 -0
  174. package/dist/utils/paths.d.ts +7 -0
  175. package/dist/utils/paths.d.ts.map +1 -1
  176. package/dist/utils/paths.js +10 -0
  177. package/dist/utils/paths.js.map +1 -1
  178. package/dist/utils/platform.d.ts +10 -0
  179. package/dist/utils/platform.d.ts.map +1 -0
  180. package/dist/utils/platform.js +14 -0
  181. package/dist/utils/platform.js.map +1 -0
  182. package/dist/utils/price-resolution.d.ts +42 -0
  183. package/dist/utils/price-resolution.d.ts.map +1 -0
  184. package/dist/utils/price-resolution.js +112 -0
  185. package/dist/utils/price-resolution.js.map +1 -0
  186. package/dist/utils/pricing.d.ts +65 -6
  187. package/dist/utils/pricing.d.ts.map +1 -1
  188. package/dist/utils/pricing.js +91 -117
  189. package/dist/utils/pricing.js.map +1 -1
  190. package/dist/utils/pricing.json +201 -20
  191. package/dist/utils/processes.d.ts.map +1 -1
  192. package/dist/utils/processes.js +6 -3
  193. package/dist/utils/processes.js.map +1 -1
  194. package/dist/utils/routing-headers.mjs +104 -0
  195. package/dist/utils/security.d.ts +0 -32
  196. package/dist/utils/security.d.ts.map +1 -1
  197. package/dist/utils/security.js +20 -102
  198. package/dist/utils/security.js.map +1 -1
  199. package/package.json +4 -2
  200. package/scripts/bundle-statusline.mjs +37 -0
  201. package/scripts/copy-plugins.js +19 -2
  202. package/src/utils/tips.json +9 -9
  203. package/dist/agents/plugins/claude/plugin/__tests__/statusline.test.ts +0 -323
  204. package/dist/agents/plugins/claude/plugin/statusline.mjs +0 -282
  205. package/dist/cli/commands/analytics/exporter.d.ts +0 -20
  206. package/dist/cli/commands/analytics/exporter.d.ts.map +0 -1
  207. package/dist/cli/commands/analytics/exporter.js +0 -91
  208. package/dist/cli/commands/analytics/exporter.js.map +0 -1
@@ -0,0 +1,729 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/agents/plugins/claude/plugin/statusline.ts
4
+ import fs from "fs/promises";
5
+ import os3 from "os";
6
+ import path from "path";
7
+ import { fileURLToPath } from "url";
8
+
9
+ // src/utils/exec.ts
10
+ import { spawn } from "child_process";
11
+ import os from "os";
12
+ async function exec(command, args = [], options = {}) {
13
+ return new Promise((resolve, reject) => {
14
+ const isWindows = os.platform() === "win32";
15
+ let useShell = false;
16
+ if (options.shell !== void 0) {
17
+ useShell = options.shell;
18
+ }
19
+ const stdio = options.interactive ? "inherit" : "pipe";
20
+ let finalCommand = command;
21
+ let finalArgs = args;
22
+ if (useShell && args.length > 0) {
23
+ const needsQuoting = (arg) => arg.includes(" ") || arg.includes('"') || isWindows && /[&|<>^%()[\]{}]/.test(arg);
24
+ const quotedArgs = args.map(
25
+ (arg) => needsQuoting(arg) ? `"${arg.replace(/"/g, '\\"')}"` : arg
26
+ );
27
+ finalCommand = `${command} ${quotedArgs.join(" ")}`;
28
+ finalArgs = [];
29
+ }
30
+ const child = spawn(finalCommand, finalArgs, {
31
+ cwd: options.cwd || process.cwd(),
32
+ env: { ...process.env, ...options.env },
33
+ shell: useShell,
34
+ windowsHide: isWindows,
35
+ // Hide console window on Windows
36
+ stdio
37
+ });
38
+ let stdout = "";
39
+ let stderr = "";
40
+ let timeoutId = null;
41
+ const cleanup = () => {
42
+ if (timeoutId) {
43
+ clearTimeout(timeoutId);
44
+ timeoutId = null;
45
+ }
46
+ };
47
+ if (!options.interactive) {
48
+ child.stdout?.on("data", (data) => {
49
+ stdout += data.toString();
50
+ });
51
+ child.stderr?.on("data", (data) => {
52
+ stderr += data.toString();
53
+ });
54
+ }
55
+ child.on("error", (error) => {
56
+ cleanup();
57
+ reject(new Error(`Failed to execute ${command}: ${error.message}`));
58
+ });
59
+ child.on("close", (code, signal) => {
60
+ cleanup();
61
+ if (code === null) {
62
+ reject(new Error(`Command terminated by signal ${signal ?? "unknown"}`));
63
+ return;
64
+ }
65
+ const result = {
66
+ code,
67
+ stdout: stdout.trim(),
68
+ stderr: stderr.trim(),
69
+ signal
70
+ };
71
+ if (options.interactive && code !== 0) {
72
+ reject(new Error(`Command exited with code ${code}`));
73
+ } else {
74
+ resolve(result);
75
+ }
76
+ });
77
+ if (options.timeout) {
78
+ timeoutId = setTimeout(() => {
79
+ child.kill();
80
+ reject(new Error(`Command timed out after ${options.timeout}ms`));
81
+ }, options.timeout);
82
+ }
83
+ });
84
+ }
85
+
86
+ // src/utils/routing-headers.mjs
87
+ var CODEMIE_ROUTING_HEADERS = [
88
+ "x-codemie-routed-model",
89
+ "x-codemie-requested-model",
90
+ "x-codemie-routing-tier",
91
+ "x-codemie-routing-decision-source",
92
+ "x-codemie-routing-source",
93
+ "x-codemie-routing-router-type",
94
+ "x-codemie-routing-family",
95
+ "x-codemie-routing-classifier-model",
96
+ "x-codemie-routing-classifier-cost-usd",
97
+ "x-codemie-routing-counterfactual-model"
98
+ ];
99
+ function hasAnyHeader(message, headerNames) {
100
+ return headerNames.some((name) => message?.[name] != null);
101
+ }
102
+ function parseRoutingHeaders(message) {
103
+ if (!hasAnyHeader(message, CODEMIE_ROUTING_HEADERS)) return null;
104
+ const routingTier = normalizeRoutingTier(message["x-codemie-routing-tier"]);
105
+ const classifierCostUSD = parseOptFloat(message["x-codemie-routing-classifier-cost-usd"]);
106
+ return {
107
+ ...message["x-codemie-requested-model"] != null && { requestedModel: message["x-codemie-requested-model"] },
108
+ ...routingTier != null && { routingTier },
109
+ ...message["x-codemie-routing-tier"] != null && { routingTierRaw: message["x-codemie-routing-tier"] },
110
+ ...message["x-codemie-routed-model"] != null && { routedModel: message["x-codemie-routed-model"] },
111
+ ...message["x-codemie-routing-classifier-model"] != null && { classifierModel: message["x-codemie-routing-classifier-model"] },
112
+ ...message["x-codemie-routing-router-type"] != null && { routerType: message["x-codemie-routing-router-type"] },
113
+ ...message["x-codemie-routing-source"] != null && { routingSource: message["x-codemie-routing-source"] },
114
+ ...message["x-codemie-routing-decision-source"] != null && { decisionSource: message["x-codemie-routing-decision-source"] },
115
+ // Opaque passthrough of whichever backend mechanism made the decision — informational only.
116
+ ...message["x-codemie-routing-family"] != null && { routingFamily: message["x-codemie-routing-family"] },
117
+ // Backend-computed counterfactual: the model this turn's usage should be repriced at to
118
+ // estimate "what this would have cost unrouted" — see cost-enricher.ts's `buildModelTimeline`.
119
+ ...message["x-codemie-routing-counterfactual-model"] != null && { counterfactualModel: message["x-codemie-routing-counterfactual-model"] },
120
+ // Known iff the proxy reported a classifier cost for this turn — absence means "no
121
+ // classifier ran / not measured", not "zero".
122
+ routingCostKnown: classifierCostUSD != null,
123
+ ...classifierCostUSD != null && { classifierCostUSD }
124
+ };
125
+ }
126
+ function parseOptFloat(s) {
127
+ if (s == null) return void 0;
128
+ const v = parseFloat(s);
129
+ return Number.isNaN(v) ? void 0 : v;
130
+ }
131
+ function normalizeRoutingTier(raw) {
132
+ if (raw == null) return void 0;
133
+ const key = String(raw).trim().toLowerCase();
134
+ const map = {
135
+ "simple": "simple",
136
+ "efficient": "middle",
137
+ "medium": "middle",
138
+ "capable": "complex",
139
+ "complex": "complex",
140
+ "reasoning": "reasoning"
141
+ };
142
+ return map[key] ?? key;
143
+ }
144
+
145
+ // src/utils/bedrock-pricing.mjs
146
+ function parseBackendModelName(message) {
147
+ return message?.["x-litellm-model-name"] ?? null;
148
+ }
149
+ var BEDROCK_REGION_PATTERN = /(?:^|\/)([a-z0-9-]+)\.anthropic\./i;
150
+ function bedrockEndpointRegion(rawModelId) {
151
+ if (!rawModelId) return null;
152
+ const match = BEDROCK_REGION_PATTERN.exec(String(rawModelId).toLowerCase());
153
+ return match ? match[1] : null;
154
+ }
155
+ function isBedrockRegionalPremium(rawModelId) {
156
+ const region = bedrockEndpointRegion(rawModelId);
157
+ return region != null && region !== "global";
158
+ }
159
+ function applyBedrockRegionalPremium(price, rawModelId) {
160
+ if (price == null || price.bedrockRegionalMultiplier == null || !isBedrockRegionalPremium(rawModelId)) {
161
+ return price;
162
+ }
163
+ const multiplier = price.bedrockRegionalMultiplier;
164
+ return {
165
+ ...price,
166
+ ...price.input != null && { input: price.input * multiplier },
167
+ ...price.output != null && { output: price.output * multiplier },
168
+ ...price.cacheRead != null && { cacheRead: price.cacheRead * multiplier },
169
+ ...price.cacheCreation != null && { cacheCreation: price.cacheCreation * multiplier },
170
+ ...price.cacheWrite != null && { cacheWrite: price.cacheWrite * multiplier },
171
+ ...price.cacheWrite1h != null && { cacheWrite1h: price.cacheWrite1h * multiplier }
172
+ };
173
+ }
174
+
175
+ // src/utils/credential-crypto.ts
176
+ import * as crypto from "crypto";
177
+ import * as os2 from "os";
178
+ import { URL } from "url";
179
+ function deriveMachineEncryptionKey() {
180
+ const machineId = os2.hostname() + os2.platform() + os2.arch();
181
+ const hex = crypto.createHash("sha256").update(machineId).digest("hex");
182
+ return crypto.createHash("sha256").update(hex).digest();
183
+ }
184
+ function decryptWithKey(text, key) {
185
+ const parts = text.split(":");
186
+ if (parts.length === 3) {
187
+ const iv2 = Buffer.from(parts[0], "hex");
188
+ const authTag = Buffer.from(parts[1], "hex");
189
+ const decipher2 = crypto.createDecipheriv("aes-256-gcm", key, iv2);
190
+ decipher2.setAuthTag(authTag);
191
+ return decipher2.update(parts[2], "hex", "utf8") + decipher2.final("utf8");
192
+ }
193
+ const iv = Buffer.from(parts[0], "hex");
194
+ const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
195
+ return decipher.update(parts[1], "hex", "utf8") + decipher.final("utf8");
196
+ }
197
+ function normalizeUrlForKey(baseUrl) {
198
+ try {
199
+ const parsed = new URL(baseUrl);
200
+ if (parsed.host && (parsed.protocol === "http:" || parsed.protocol === "https:")) {
201
+ return `${parsed.protocol}//${parsed.host}`.toLowerCase();
202
+ }
203
+ } catch {
204
+ }
205
+ return baseUrl.replace(/\/$/, "").toLowerCase();
206
+ }
207
+ function hashStorageKey(normalized) {
208
+ return `sso-${crypto.createHash("sha256").update(normalized).digest("hex")}`;
209
+ }
210
+ function deriveUrlStorageKey(baseUrl) {
211
+ return hashStorageKey(normalizeUrlForKey(baseUrl));
212
+ }
213
+ function deriveLegacyUrlStorageKey(baseUrl) {
214
+ return hashStorageKey(baseUrl.replace(/\/$/, "").toLowerCase());
215
+ }
216
+
217
+ // src/utils/model-normalizer.ts
218
+ var VENDOR_PREFIX_PATTERN = /^(?:openai[./]|azure\/|vertex_ai\/|anthropic\/|moonshotai\.|qwen\.)/i;
219
+ function normalizeModelName(modelName) {
220
+ const bedrockMatch = modelName.match(/^(?:bedrock\/)?(?:converse\/)?[a-z0-9-]+\.anthropic\.(claude-[a-z0-9-]+?)(?:-v\d+:\d+)?$/);
221
+ if (bedrockMatch) {
222
+ return bedrockMatch[1];
223
+ }
224
+ if (modelName.startsWith("kimi-code/")) {
225
+ return modelName.slice("kimi-code/".length);
226
+ }
227
+ const vendorPrefixMatch = modelName.match(VENDOR_PREFIX_PATTERN);
228
+ if (vendorPrefixMatch) {
229
+ return modelName.slice(vendorPrefixMatch[0].length);
230
+ }
231
+ return modelName;
232
+ }
233
+
234
+ // src/utils/price-resolution.ts
235
+ var SNAPSHOT_SUFFIX_PATTERN = /-(?:\d{8}|\d{4}-\d{2}-\d{2}|latest|preview)$/;
236
+ var CLAUDE_VERSION_FIRST_PATTERN = /^claude-(\d+(?:-\d+)*)-(opus|sonnet|haiku)(-.+)?$/;
237
+ function priceTableKey(rawKey) {
238
+ return rawKey.toLowerCase().replace(/\./g, "-");
239
+ }
240
+ function canonicalizeModelId(model) {
241
+ return priceTableKey(normalizeModelName(model)).replace(/@/g, "-").replace(/-vertex$/, "");
242
+ }
243
+ function reorderClaudeVersionFamily(id) {
244
+ const match = id.match(CLAUDE_VERSION_FIRST_PATTERN);
245
+ if (!match) {
246
+ return null;
247
+ }
248
+ const [, version, family, rest = ""] = match;
249
+ return `claude-${family}-${version}${rest}`;
250
+ }
251
+ function withoutSnapshot(key) {
252
+ const stripped = key.replace(SNAPSHOT_SUFFIX_PATTERN, "");
253
+ return stripped === key ? null : stripped;
254
+ }
255
+ function priceKeyCandidates(model) {
256
+ const canonical = canonicalizeModelId(model);
257
+ const candidates = [{ key: canonical, match: "exact" }];
258
+ const snapshot = withoutSnapshot(canonical);
259
+ if (snapshot) {
260
+ candidates.push({ key: snapshot, match: "snapshot" });
261
+ }
262
+ const reordered = reorderClaudeVersionFamily(canonical);
263
+ if (reordered) {
264
+ candidates.push({ key: reordered, match: "reordered" });
265
+ const reorderedSnapshot = withoutSnapshot(reordered);
266
+ if (reorderedSnapshot) {
267
+ candidates.push({ key: reorderedSnapshot, match: "reordered" });
268
+ }
269
+ }
270
+ return candidates;
271
+ }
272
+ function resolvePriceKey(model, lookup) {
273
+ for (const { key, match } of priceKeyCandidates(model)) {
274
+ const value = key ? lookup(key) : void 0;
275
+ if (value !== void 0) {
276
+ return { key, match, value };
277
+ }
278
+ }
279
+ return null;
280
+ }
281
+
282
+ // src/agents/plugins/claude/plugin/statusline.ts
283
+ var HOME = process.env.CODEMIE_HOME || path.join(os3.homedir(), ".codemie");
284
+ var CACHE_FILE = path.join(HOME, "budget-cache.json");
285
+ var CONFIG_FILE = path.join(HOME, "codemie-cli.config.json");
286
+ var CREDS_DIR = path.join(HOME, "credentials");
287
+ var CACHE_TTL_MS = 6e4;
288
+ var CACHE_SCHEMA = 2;
289
+ var ENCRYPTION_KEY = deriveMachineEncryptionKey();
290
+ async function readCredsFile(filePath) {
291
+ try {
292
+ return JSON.parse(decryptWithKey(await fs.readFile(filePath, "utf8"), ENCRYPTION_KEY));
293
+ } catch {
294
+ return null;
295
+ }
296
+ }
297
+ async function readStoredCredsFile(jwtPrefix, codeMieUrl) {
298
+ const current = await readCredsFile(path.join(CREDS_DIR, `${jwtPrefix}${deriveUrlStorageKey(codeMieUrl)}.enc`));
299
+ if (current) return current;
300
+ return readCredsFile(path.join(CREDS_DIR, `${jwtPrefix}${deriveLegacyUrlStorageKey(codeMieUrl)}.enc`));
301
+ }
302
+ async function getAuthHeaders(codeMieUrl) {
303
+ const sso = await readStoredCredsFile("", codeMieUrl);
304
+ if (sso?.cookies) {
305
+ return { cookie: Object.entries(sso.cookies).map(([k, v]) => `${k}=${v}`).join(";") };
306
+ }
307
+ const jwt = await readStoredCredsFile("jwt-", codeMieUrl);
308
+ if (jwt?.token) {
309
+ return { authorization: `Bearer ${jwt.token}` };
310
+ }
311
+ return null;
312
+ }
313
+ function matchBudgetRow(rows, userEmail) {
314
+ if (!Array.isArray(rows) || !userEmail) return null;
315
+ const target = `${userEmail.trim().toLowerCase()} (cli)`;
316
+ return rows.find((r) => r.project_name?.trim().toLowerCase() === target) ?? null;
317
+ }
318
+ function formatBudgetSegment(row) {
319
+ if (!row) return null;
320
+ const pct = Math.round(row.total ?? 0);
321
+ const reset = row.budget_reset_at ? new Date(row.budget_reset_at).toLocaleDateString() : "?";
322
+ return {
323
+ text: `$${row.current_spending.toFixed(2)} (${pct}%) resets ${reset}`,
324
+ pct
325
+ };
326
+ }
327
+ function extractBasicInfo(ctx) {
328
+ const cwd = ctx?.workspace?.current_dir ?? ctx?.cwd ?? "";
329
+ return {
330
+ projectName: cwd ? path.basename(cwd) : "",
331
+ cwd,
332
+ transcriptPath: ctx?.transcript_path ?? "",
333
+ modelId: ctx?.model?.id ?? "",
334
+ model: ctx?.model?.display_name ?? "",
335
+ ctxPct: ctx?.context_window?.used_percentage ?? null,
336
+ tokIn: ctx?.context_window?.total_input_tokens ?? null,
337
+ tokOut: ctx?.context_window?.total_output_tokens ?? null,
338
+ cost: ctx?.cost?.total_cost_usd ?? null,
339
+ durationMs: ctx?.cost?.total_duration_ms ?? null
340
+ };
341
+ }
342
+ var ROUTED_MODEL_TAIL_BYTES = 65536;
343
+ var ROUTED_MODEL_TAIL_MAX_BYTES = 8 * 1024 * 1024;
344
+ function normalizeModelId(modelId) {
345
+ if (!modelId) return "";
346
+ return modelId.toLowerCase().replace(/^(?:bedrock\/)?(?:converse\/)?/, "").replace(/^[a-z0-9-]+\.anthropic\./, "").replace(/-v\d+:\d+$/, "");
347
+ }
348
+ function parseLastAssistantTurn(tailText) {
349
+ if (!tailText) return null;
350
+ const lines = tailText.split("\n");
351
+ for (let i = lines.length - 1; i >= 0; i--) {
352
+ const line = lines[i].trim();
353
+ if (!line) continue;
354
+ let parsed;
355
+ try {
356
+ parsed = JSON.parse(line);
357
+ } catch {
358
+ continue;
359
+ }
360
+ const message = parsed?.message;
361
+ if (parsed?.type === "assistant" && message?.model && message.model !== "<synthetic>") {
362
+ return { responseModel: message.model, headerRoutedModel: parseRoutingHeaders(message)?.routedModel ?? null };
363
+ }
364
+ }
365
+ return null;
366
+ }
367
+ async function defaultReadTail(filePath, maxBytes) {
368
+ const handle = await fs.open(filePath, "r");
369
+ try {
370
+ const { size } = await handle.stat();
371
+ const start = Math.max(0, size - maxBytes);
372
+ const length = size - start;
373
+ if (length <= 0) return "";
374
+ const { buffer, bytesRead } = await handle.read({ buffer: Buffer.alloc(length), position: start });
375
+ return buffer.toString("utf8", 0, bytesRead);
376
+ } finally {
377
+ await handle.close();
378
+ }
379
+ }
380
+ function parseRouterModelIds(env) {
381
+ if (!env.CODEMIE_ROUTER_MODEL_IDS) return /* @__PURE__ */ new Set();
382
+ try {
383
+ const parsed = JSON.parse(env.CODEMIE_ROUTER_MODEL_IDS);
384
+ return new Set(Array.isArray(parsed) ? parsed : []);
385
+ } catch {
386
+ return /* @__PURE__ */ new Set();
387
+ }
388
+ }
389
+ function isRoutingConfigured(env, modelId) {
390
+ return parseRouterModelIds(env).has(modelId);
391
+ }
392
+ function parseModelLabels(env) {
393
+ if (!env.CODEMIE_MODEL_LABELS) return {};
394
+ try {
395
+ const parsed = JSON.parse(env.CODEMIE_MODEL_LABELS);
396
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
397
+ } catch {
398
+ return {};
399
+ }
400
+ }
401
+ async function resolveActualModel(transcriptPath, { readTail = defaultReadTail, labels = {} } = {}) {
402
+ if (!transcriptPath) return null;
403
+ let turn = null;
404
+ let bytes = ROUTED_MODEL_TAIL_BYTES;
405
+ for (; ; ) {
406
+ let tail;
407
+ try {
408
+ tail = await readTail(transcriptPath, bytes);
409
+ } catch {
410
+ return null;
411
+ }
412
+ turn = parseLastAssistantTurn(tail);
413
+ if (turn || Buffer.byteLength(tail, "utf8") < bytes || bytes >= ROUTED_MODEL_TAIL_MAX_BYTES) break;
414
+ bytes = Math.min(bytes * 8, ROUTED_MODEL_TAIL_MAX_BYTES);
415
+ }
416
+ if (!turn) return null;
417
+ const candidate = turn.headerRoutedModel ?? turn.responseModel;
418
+ if (!candidate) return null;
419
+ const normalized = normalizeModelId(candidate);
420
+ return labels[candidate] ?? labels[normalized] ?? normalized;
421
+ }
422
+ var PRICING_FILENAME = "codemie-pricing.json";
423
+ var COST_CACHE_FILE = path.join(HOME, "statusline-cost-cache.json");
424
+ var COST_CACHE_SCHEMA = 1;
425
+ async function sourceSignature(paths, stat) {
426
+ const parts = [];
427
+ for (const p of paths) {
428
+ try {
429
+ const { size, mtimeMs } = await stat(p);
430
+ parts.push(`${p}:${size}:${mtimeMs}`);
431
+ } catch {
432
+ parts.push(`${p}:absent`);
433
+ }
434
+ }
435
+ return parts.join("|");
436
+ }
437
+ async function defaultReadPrices() {
438
+ const here = path.dirname(fileURLToPath(import.meta.url));
439
+ return JSON.parse(await fs.readFile(path.join(here, PRICING_FILENAME), "utf8"));
440
+ }
441
+ var NORMALIZED_TABLES = /* @__PURE__ */ new WeakMap();
442
+ function normalizedTable(table) {
443
+ const cached = NORMALIZED_TABLES.get(table);
444
+ if (cached) return cached;
445
+ const normalized = /* @__PURE__ */ new Map();
446
+ const ambiguous = /* @__PURE__ */ new Set();
447
+ for (const [rawKey, rate] of Object.entries(table)) {
448
+ if (rawKey.startsWith("_")) continue;
449
+ const key = priceTableKey(rawKey);
450
+ if (normalized.has(key) && JSON.stringify(normalized.get(key)) !== JSON.stringify(rate)) ambiguous.add(key);
451
+ normalized.set(key, rate);
452
+ }
453
+ for (const key of ambiguous) normalized.delete(key);
454
+ NORMALIZED_TABLES.set(table, normalized);
455
+ return normalized;
456
+ }
457
+ function lookupRate(table, modelId) {
458
+ if (!table || !modelId) return null;
459
+ const rates = normalizedTable(table);
460
+ const hit = resolvePriceKey(modelId, (key) => rates.get(key));
461
+ return hit ? applyBedrockRegionalPremium(hit.value, modelId) : null;
462
+ }
463
+ function messageCost(rate, usage) {
464
+ const cacheWriteRate = rate.cacheCreation ?? rate.cacheWrite ?? 0;
465
+ const split = usage.cache_creation;
466
+ const write5m = split?.ephemeral_5m_input_tokens ?? 0;
467
+ const write1h = split?.ephemeral_1h_input_tokens ?? 0;
468
+ const cacheWrite = write5m || write1h ? write5m * cacheWriteRate + write1h * (rate.cacheWrite1h ?? cacheWriteRate) : (usage.cache_creation_input_tokens ?? 0) * cacheWriteRate;
469
+ return ((usage.input_tokens ?? 0) * (rate.input ?? 0) + (usage.output_tokens ?? 0) * (rate.output ?? 0) + (usage.cache_read_input_tokens ?? 0) * (rate.cacheRead ?? 0) + cacheWrite) / 1e6;
470
+ }
471
+ async function computeSessionCost(transcriptPath, {
472
+ readFile = fs.readFile,
473
+ readDir = fs.readdir,
474
+ writeFile = fs.writeFile,
475
+ stat = fs.stat,
476
+ readPrices = defaultReadPrices
477
+ } = {}) {
478
+ if (!transcriptPath) return null;
479
+ let table;
480
+ try {
481
+ table = await readPrices();
482
+ } catch {
483
+ return null;
484
+ }
485
+ const subagentDir = path.join(
486
+ path.dirname(transcriptPath),
487
+ path.basename(transcriptPath, ".jsonl"),
488
+ "subagents"
489
+ );
490
+ const sourcePaths = [transcriptPath];
491
+ try {
492
+ for (const name of await readDir(subagentDir)) {
493
+ if (name.endsWith(".jsonl")) sourcePaths.push(path.join(subagentDir, name));
494
+ }
495
+ } catch {
496
+ }
497
+ const signature = await sourceSignature(sourcePaths, stat);
498
+ try {
499
+ const cached = JSON.parse(await readFile(COST_CACHE_FILE, "utf8"));
500
+ if (cached.schema === COST_CACHE_SCHEMA && cached.signature === signature && typeof cached.cost === "number" && typeof cached.exact === "boolean") {
501
+ return { cost: cached.cost, exact: cached.exact };
502
+ }
503
+ } catch {
504
+ }
505
+ const sources = [];
506
+ for (const sourcePath of sourcePaths) {
507
+ try {
508
+ sources.push(await readFile(sourcePath, "utf8"));
509
+ } catch {
510
+ }
511
+ }
512
+ const byMessage = /* @__PURE__ */ new Map();
513
+ let anon = 0;
514
+ for (const raw of sources) {
515
+ for (const line of raw.split("\n")) {
516
+ if (!line) continue;
517
+ let message;
518
+ try {
519
+ message = JSON.parse(line)?.message;
520
+ } catch {
521
+ continue;
522
+ }
523
+ if (!message?.usage) continue;
524
+ const id = message.id ?? `anon:${anon++}`;
525
+ const model = parseBackendModelName(message) ?? parseRoutingHeaders(message)?.routedModel ?? message.model ?? "";
526
+ byMessage.set(id, { model, usage: message.usage });
527
+ }
528
+ }
529
+ let cost = 0;
530
+ let exact = true;
531
+ for (const { model, usage } of byMessage.values()) {
532
+ const rate = lookupRate(table, model);
533
+ if (!rate) {
534
+ exact = false;
535
+ continue;
536
+ }
537
+ cost += messageCost(rate, usage);
538
+ }
539
+ const result = { cost, exact };
540
+ try {
541
+ await writeFile(COST_CACHE_FILE, JSON.stringify({ schema: COST_CACHE_SCHEMA, signature, ...result }), "utf8");
542
+ } catch {
543
+ }
544
+ return result;
545
+ }
546
+ function formatDuration(ms) {
547
+ if (typeof ms !== "number" || Number.isNaN(ms) || ms < 0) return null;
548
+ const mins = Math.floor(ms / 6e4);
549
+ const secs = Math.floor(ms % 6e4 / 1e3);
550
+ return `${mins}m ${secs}s`;
551
+ }
552
+ function fmt(n) {
553
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
554
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
555
+ return String(n);
556
+ }
557
+ var C = {
558
+ reset: "\x1B[0m",
559
+ purple: "\x1B[38;2;177;185;249m",
560
+ green: "\x1B[0;32m",
561
+ yellow: "\x1B[0;33m",
562
+ red: "\x1B[0;31m",
563
+ cyan: "\x1B[0;36m",
564
+ blue: "\x1B[0;94m",
565
+ gray: "\x1B[0;37m"
566
+ };
567
+ var c = (color, text) => `${color}${text}${C.reset}`;
568
+ function ctxBar(pct) {
569
+ if (typeof pct !== "number" || Number.isNaN(pct)) return null;
570
+ const clamped = Math.max(0, Math.min(100, pct));
571
+ const color = clamped >= 90 ? C.red : clamped >= 70 ? C.yellow : C.green;
572
+ const filled = Math.floor(clamped / 10);
573
+ const bar = "\u2588".repeat(filled) + "\u2591".repeat(10 - filled);
574
+ return `${c(color, bar)} ${pct}%`;
575
+ }
576
+ function buildStatusLine({ projectName, branch, model, actualModel, ctxPct, tokIn, tokOut, cost, costExact, durationMs }) {
577
+ const parts = [];
578
+ if (projectName) parts.push(c(C.purple, `[${projectName}]`));
579
+ if (branch) parts.push(c(C.blue, `(${branch})`));
580
+ if (model) parts.push(c(C.cyan, `[${actualModel ? `${model} \u2192 ${actualModel}` : model}]`));
581
+ const bar = ctxBar(ctxPct);
582
+ if (bar) parts.push(bar);
583
+ const stats = [];
584
+ if (tokIn != null) stats.push(`in:${fmt(tokIn)}`);
585
+ if (tokOut != null) stats.push(`out:${fmt(tokOut)}`);
586
+ if (stats.length) parts.push(c(C.gray, stats.join(" ")));
587
+ if (typeof cost === "number" && !Number.isNaN(cost)) {
588
+ parts.push(c(C.yellow, `${costExact ? "" : "~"}$${cost.toFixed(4)}`));
589
+ }
590
+ const dur = formatDuration(durationMs);
591
+ if (dur) parts.push(c(C.gray, dur));
592
+ return parts.join(" | ");
593
+ }
594
+ function readStdin() {
595
+ return new Promise((resolve) => {
596
+ let data = "";
597
+ process.stdin.setEncoding("utf8");
598
+ process.stdin.on("data", (chunk) => {
599
+ data += chunk;
600
+ });
601
+ process.stdin.on("end", () => resolve(data));
602
+ process.stdin.on("error", () => resolve(data));
603
+ });
604
+ }
605
+ async function gitBranch(cwd) {
606
+ try {
607
+ const { stdout } = await exec("git", ["--no-optional-locks", "symbolic-ref", "--short", "HEAD"], { cwd, timeout: 2e3 });
608
+ if (stdout.trim()) return stdout.trim();
609
+ } catch {
610
+ }
611
+ try {
612
+ const { stdout } = await exec("git", ["--no-optional-locks", "rev-parse", "--short", "HEAD"], { cwd, timeout: 2e3 });
613
+ return stdout.trim() || "";
614
+ } catch {
615
+ return "";
616
+ }
617
+ }
618
+ async function resolveBudget({
619
+ readFile = fs.readFile,
620
+ writeFile = fs.writeFile,
621
+ fetchImpl = fetch,
622
+ getAuthHeadersImpl = getAuthHeaders
623
+ } = {}) {
624
+ let config;
625
+ try {
626
+ config = JSON.parse(await readFile(CONFIG_FILE, "utf8"));
627
+ } catch {
628
+ return { budget: null, budgetError: null };
629
+ }
630
+ const sessionProfile = process.env.CODEMIE_PROFILE_NAME;
631
+ const profileName = sessionProfile && config.profiles?.[sessionProfile] ? sessionProfile : config.activeProfile;
632
+ try {
633
+ const cache = JSON.parse(await readFile(CACHE_FILE, "utf8"));
634
+ const validShape = cache.schema === CACHE_SCHEMA && cache.profile === profileName && typeof cache.value === "object" && cache.value !== null && typeof cache.value.text === "string";
635
+ if (validShape && Date.now() - cache.ts < CACHE_TTL_MS) {
636
+ return { budget: cache.value, budgetError: null };
637
+ }
638
+ } catch {
639
+ }
640
+ const profile = config.profiles?.[profileName];
641
+ const { baseUrl } = profile ?? {};
642
+ const codeMieUrl = config.workspace?.codeMieUrl;
643
+ const userEmail = config.userEmail;
644
+ if (!profile || !codeMieUrl || !baseUrl || !userEmail) {
645
+ return { budget: null, budgetError: null };
646
+ }
647
+ let headers;
648
+ try {
649
+ headers = await getAuthHeadersImpl(codeMieUrl);
650
+ } catch (e) {
651
+ return { budget: null, budgetError: e instanceof Error ? e.message : String(e) };
652
+ }
653
+ if (!headers) {
654
+ return { budget: null, budgetError: "reauthenticate" };
655
+ }
656
+ try {
657
+ const res = await fetchImpl(`${baseUrl}/v1/analytics/budget_usage`, {
658
+ headers: { "Content-Type": "application/json", "X-CodeMie-Client": "codemie-cli", ...headers }
659
+ });
660
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
661
+ const contentType = res.headers?.get?.("content-type") ?? "";
662
+ if (!contentType.includes("json")) return { budget: null, budgetError: null };
663
+ const json = await res.json();
664
+ const row = matchBudgetRow(json?.data?.rows, userEmail);
665
+ if (!row) throw new Error("budget row not found");
666
+ const budget = formatBudgetSegment(row);
667
+ await writeFile(CACHE_FILE, JSON.stringify({ schema: CACHE_SCHEMA, profile: profileName, ts: Date.now(), value: budget }), "utf8");
668
+ return { budget, budgetError: null };
669
+ } catch (e) {
670
+ const code = e instanceof Error && e.cause && typeof e.cause === "object" && "code" in e.cause ? e.cause.code : void 0;
671
+ const message = e instanceof Error ? e.message : String(e);
672
+ return { budget: null, budgetError: code ? `budget: ${code}` : message };
673
+ }
674
+ }
675
+ async function main() {
676
+ const stdinRaw = await readStdin();
677
+ let basic;
678
+ try {
679
+ basic = extractBasicInfo(JSON.parse(stdinRaw));
680
+ } catch {
681
+ basic = extractBasicInfo({});
682
+ }
683
+ const labels = parseModelLabels(process.env);
684
+ const nominalLabel = labels[basic.modelId];
685
+ if (nominalLabel) basic.model = nominalLabel;
686
+ const branchPromise = basic.cwd ? gitBranch(basic.cwd) : Promise.resolve("");
687
+ const [branch, actualModel, priced] = await Promise.all([
688
+ branchPromise,
689
+ isRoutingConfigured(process.env, basic.modelId) ? resolveActualModel(basic.transcriptPath, { labels }) : Promise.resolve(null),
690
+ computeSessionCost(basic.transcriptPath)
691
+ ]);
692
+ const cost = priced ? priced.cost : basic.cost;
693
+ const costExact = priced ? priced.exact : false;
694
+ process.stdout.write(buildStatusLine({ ...basic, branch, actualModel, cost, costExact }));
695
+ }
696
+ function isMainModule(argv1, metaUrl) {
697
+ if (!argv1) return false;
698
+ try {
699
+ return fileURLToPath(metaUrl) === argv1;
700
+ } catch {
701
+ return false;
702
+ }
703
+ }
704
+ if (isMainModule(process.argv[1], import.meta.url)) {
705
+ main().catch(() => {
706
+ process.stdout.write("");
707
+ });
708
+ }
709
+ export {
710
+ buildStatusLine,
711
+ computeSessionCost,
712
+ ctxBar,
713
+ extractBasicInfo,
714
+ fmt,
715
+ formatBudgetSegment,
716
+ formatDuration,
717
+ getAuthHeaders,
718
+ isMainModule,
719
+ isRoutingConfigured,
720
+ lookupRate,
721
+ main,
722
+ matchBudgetRow,
723
+ normalizeModelId,
724
+ parseLastAssistantTurn,
725
+ parseModelLabels,
726
+ parseRouterModelIds,
727
+ resolveActualModel,
728
+ resolveBudget
729
+ };