codeep 2.15.0 → 2.17.0

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 (41) hide show
  1. package/README.md +41 -7
  2. package/dist/acp/serverHandlers.js +1 -1
  3. package/dist/acp/session.js +22 -1
  4. package/dist/config/index.js +20 -4
  5. package/dist/config/providers.d.ts +3 -2
  6. package/dist/config/providers.js +163 -69
  7. package/dist/renderer/App.d.ts +89 -0
  8. package/dist/renderer/App.js +637 -43
  9. package/dist/renderer/Screen.d.ts +1 -0
  10. package/dist/renderer/Screen.js +8 -3
  11. package/dist/renderer/commands/helpers.d.ts +189 -0
  12. package/dist/renderer/commands/helpers.js +345 -0
  13. package/dist/renderer/commands/registry.js +2 -1
  14. package/dist/renderer/commands.js +218 -267
  15. package/dist/renderer/components/AgentTimeline.d.ts +44 -0
  16. package/dist/renderer/components/AgentTimeline.js +157 -0
  17. package/dist/renderer/components/Autocomplete.d.ts +25 -0
  18. package/dist/renderer/components/Autocomplete.js +35 -0
  19. package/dist/renderer/components/Status.d.ts +2 -0
  20. package/dist/renderer/layout.d.ts +5 -1
  21. package/dist/renderer/layout.js +12 -0
  22. package/dist/renderer/main.js +110 -30
  23. package/dist/utils/agent.js +1 -1
  24. package/dist/utils/agents.d.ts +1 -1
  25. package/dist/utils/agents.js +1 -1
  26. package/dist/utils/checkpoints.d.ts +1 -1
  27. package/dist/utils/checkpoints.js +1 -1
  28. package/dist/utils/diffPreview.d.ts +31 -0
  29. package/dist/utils/diffPreview.js +102 -0
  30. package/dist/utils/git.d.ts +28 -0
  31. package/dist/utils/git.js +111 -1
  32. package/dist/utils/mentions.d.ts +195 -0
  33. package/dist/utils/mentions.js +672 -0
  34. package/dist/utils/resourceImpact.d.ts +25 -0
  35. package/dist/utils/resourceImpact.js +54 -0
  36. package/dist/utils/tokenTracker.js +52 -37
  37. package/dist/utils/webFetch.d.ts +101 -0
  38. package/dist/utils/webFetch.js +375 -0
  39. package/dist/version.d.ts +1 -1
  40. package/dist/version.js +1 -1
  41. package/package.json +2 -1
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Broad operational-impact estimate for hosted LLM inference.
3
+ *
4
+ * This is deliberately a range, not a meter reading:
5
+ * - 0.3–1.5 J/token covers published H100 inference benchmarks.
6
+ * - 0.27–1.08 L/kWh spans efficient direct cooling and a full-stack
7
+ * production estimate that also captures associated infrastructure.
8
+ *
9
+ * Model size, batching, context length, hardware, data-centre location and
10
+ * provider efficiency can move the real result outside this band. Local
11
+ * models are included because their token usage still consumes electricity,
12
+ * but Codeep cannot measure the device directly.
13
+ */
14
+ const ENERGY_JOULES_PER_TOKEN = { low: 0.3, high: 1.5 };
15
+ const WATER_LITRES_PER_KWH = { low: 0.27, high: 1.08 };
16
+ export function estimateResourceImpact(totalTokens) {
17
+ const tokens = Number.isFinite(totalTokens) ? Math.max(0, totalTokens) : 0;
18
+ const energyWhLow = (tokens * ENERGY_JOULES_PER_TOKEN.low) / 3600;
19
+ const energyWhHigh = (tokens * ENERGY_JOULES_PER_TOKEN.high) / 3600;
20
+ return {
21
+ energyWhLow,
22
+ energyWhHigh,
23
+ waterMlLow: (energyWhLow / 1000) * WATER_LITRES_PER_KWH.low * 1000,
24
+ waterMlHigh: (energyWhHigh / 1000) * WATER_LITRES_PER_KWH.high * 1000,
25
+ };
26
+ }
27
+ function compact(value) {
28
+ if (value === 0)
29
+ return '0';
30
+ if (value < 0.01)
31
+ return value.toFixed(3);
32
+ if (value < 1)
33
+ return value.toFixed(2);
34
+ if (value < 10)
35
+ return value.toFixed(1);
36
+ return Math.round(value).toLocaleString('en-US');
37
+ }
38
+ export function formatResourceImpact(estimate) {
39
+ const energy = estimate.energyWhHigh >= 1000
40
+ ? `${compact(estimate.energyWhLow / 1000)}–${compact(estimate.energyWhHigh / 1000)} kWh`
41
+ : `${compact(estimate.energyWhLow)}–${compact(estimate.energyWhHigh)} Wh`;
42
+ const water = estimate.waterMlHigh >= 1000
43
+ ? `${compact(estimate.waterMlLow / 1000)}–${compact(estimate.waterMlHigh / 1000)} L`
44
+ : `${compact(estimate.waterMlLow)}–${compact(estimate.waterMlHigh)} mL`;
45
+ return { energy, water };
46
+ }
47
+ export function formatResourceImpactReport(totalTokens) {
48
+ const formatted = formatResourceImpact(estimateResourceImpact(totalTokens));
49
+ return [
50
+ '### Estimated compute impact',
51
+ `**Electricity:** ${formatted.energy} · **Cooling water:** ${formatted.water}`,
52
+ '_Research-based range, not a provider measurement. Actual usage varies widely by model, hardware, batching, context length, data-centre location, and cooling system._',
53
+ ];
54
+ }
@@ -2,13 +2,14 @@
2
2
  * Token and cost tracking for API usage
3
3
  */
4
4
  import { AsyncLocalStorage } from 'node:async_hooks';
5
- // Context window sizes per model (in tokens).
6
- // Keep this table in lockstep with `providers.ts` — entries for models that
7
- // aren't in the provider catalogue only show up if a user types an id by hand
8
- // and produce phantom estimates against the wrong context size.
5
+ import { formatResourceImpactReport } from './resourceImpact.js';
6
+ // Context window sizes per model (in tokens). Primarily mirrors providers.ts;
7
+ // retired aliases remain only where restored historical sessions still need a
8
+ // meaningful context/cost display.
9
9
  const MODEL_CONTEXT_WINDOWS = {
10
10
  // Z.AI / ZhipuAI
11
- 'glm-5.2': 200_000,
11
+ 'glm-5.2': 1_000_000,
12
+ 'glm-5.1': 200_000,
12
13
  'glm-5-turbo': 202_752,
13
14
  // OpenAI
14
15
  'gpt-5.6-sol': 1_050_000,
@@ -19,7 +20,7 @@ const MODEL_CONTEXT_WINDOWS = {
19
20
  'gpt-5.4-mini': 400_000,
20
21
  // Anthropic
21
22
  'claude-fable-5': 1_000_000,
22
- 'claude-opus-4-8': 1_000_000,
23
+ 'claude-opus-5': 1_000_000,
23
24
  'claude-sonnet-4-6': 1_000_000,
24
25
  'claude-sonnet-5': 1_000_000,
25
26
  'claude-haiku-4-5-20251001': 200_000,
@@ -28,28 +29,34 @@ const MODEL_CONTEXT_WINDOWS = {
28
29
  'deepseek-v4-flash': 1_000_000,
29
30
  // Google
30
31
  'gemini-3.1-pro-preview': 1_048_576,
31
- 'gemini-3.5-flash': 1_000_000,
32
- 'gemini-3.1-flash-lite': 1_048_576,
32
+ 'gemini-3.6-flash': 1_048_576,
33
+ 'gemini-3.5-flash': 1_048_576,
34
+ 'gemini-3.5-flash-lite': 1_048_576,
33
35
  'gemini-3-flash-preview': 1_000_000,
34
36
  // MiniMax
35
- 'MiniMax-M3': 524_288,
36
- // Kimi (Moonshot) — 256K across the K2.x line
37
+ 'MiniMax-M3': 1_000_000,
38
+ // Kimi (Moonshot) — 1M on K3, 256K across K2.x
39
+ 'kimi-k3': 1_000_000,
37
40
  'kimi-k2.7-code': 262_144,
38
41
  'kimi-k2.7-code-highspeed': 262_144,
39
42
  'kimi-k2.6': 262_144,
40
- 'kimi-k2.5': 262_144,
41
43
  'kimi-for-coding': 262_144,
44
+ 'kimi-for-coding-highspeed': 262_144,
45
+ 'k3': 1_000_000,
46
+ 'k3-256k': 262_144,
42
47
  // Grok (xAI)
43
48
  'grok-4.5': 500_000,
44
49
  'grok-build-0.1': 256_000,
45
50
  'grok-4.3': 1_000_000,
46
51
  'grok-code-fast-1': 256_000,
47
52
  'grok-4-fast-reasoning': 2_000_000,
48
- // Qwen (Alibaba) — 256K native (1M with extrapolation)
49
- 'qwen3-coder-plus': 262_144,
50
- 'qwen3-coder-next': 262_144,
51
- 'qwen3-coder-flash': 262_144,
53
+ // Qwen (Alibaba) — current hosted generation
52
54
  'qwen3.7-max': 1_000_000,
55
+ 'qwen3.8-max-preview': 1_000_000,
56
+ 'qwen3.7-plus': 1_000_000,
57
+ 'qwen3.6-plus': 1_000_000,
58
+ 'qwen3.5-plus': 1_000_000,
59
+ 'qwen3.6-flash': 1_000_000,
53
60
  'Qwen/Qwen3-Coder-480B-A35B-Instruct': 262_144,
54
61
  };
55
62
  const DEFAULT_CONTEXT_WINDOW = 128_000;
@@ -60,58 +67,65 @@ export function getModelContextWindow(model) {
60
67
  return MODEL_CONTEXT_WINDOWS[model] ?? DEFAULT_CONTEXT_WINDOW;
61
68
  }
62
69
  // Pricing table — USD per 1M tokens. Same rule as MODEL_CONTEXT_WINDOWS:
63
- // only list model ids that exist in `providers.ts`, otherwise typing an id
64
- // by hand can produce phantom cost estimates against stale rates.
70
+ // Primarily mirrors `providers.ts`. A few retired aliases remain so restored
71
+ // historical sessions still show the rate that applied when they were created.
65
72
  const MODEL_PRICING = {
66
73
  // Z.AI / ZhipuAI
67
- // GLM-5.2 per-token pricing isn't published yet — mirror GLM-5.1 (same tier,
68
- // its successor) provisionally so /cost stays sane; update when z.ai posts it.
69
- // Note: on the GLM Coding Plan (the default `z.ai` provider) billing is a flat
70
- // subscription, so this only affects the pay-per-use estimate.
71
- 'glm-5.2': { inputPer1M: 1.00, outputPer1M: 3.20 },
74
+ // Coding Plan is flat-fee; these official rates apply to pay-per-use.
75
+ 'glm-5.2': { inputPer1M: 1.40, outputPer1M: 4.40 },
76
+ 'glm-5.1': { inputPer1M: 1.40, outputPer1M: 4.40 },
72
77
  'glm-5-turbo': { inputPer1M: 1.20, outputPer1M: 4.00 },
73
78
  // OpenAI
74
79
  'gpt-5.6-sol': { inputPer1M: 5.00, outputPer1M: 30.00 },
75
- 'gpt-5.6-terra': { inputPer1M: 2.50, outputPer1M: 15.00 },
76
- 'gpt-5.6-luna': { inputPer1M: 1.00, outputPer1M: 6.00 },
80
+ 'gpt-5.6-terra': { inputPer1M: 2.00, outputPer1M: 12.00 },
81
+ 'gpt-5.6-luna': { inputPer1M: 0.20, outputPer1M: 1.20 },
77
82
  'gpt-5.5': { inputPer1M: 5.00, outputPer1M: 30.00 },
78
83
  'gpt-5.4': { inputPer1M: 2.50, outputPer1M: 15.00 },
79
84
  'gpt-5.4-mini': { inputPer1M: 0.75, outputPer1M: 4.50 },
80
85
  // Anthropic
81
86
  'claude-fable-5': { inputPer1M: 10.00, outputPer1M: 50.00 },
82
- 'claude-opus-4-8': { inputPer1M: 5.00, outputPer1M: 25.00 },
87
+ 'claude-opus-5': { inputPer1M: 5.00, outputPer1M: 25.00 },
83
88
  'claude-sonnet-4-6': { inputPer1M: 3.00, outputPer1M: 15.00 },
84
89
  'claude-sonnet-5': { inputPer1M: 3.00, outputPer1M: 15.00 },
85
90
  'claude-haiku-4-5-20251001': { inputPer1M: 1.00, outputPer1M: 5.00 },
86
91
  // DeepSeek (cache-miss input pricing)
87
- 'deepseek-v4-pro': { inputPer1M: 1.74, outputPer1M: 3.48 },
92
+ 'deepseek-v4-pro': { inputPer1M: 0.435, outputPer1M: 0.87 },
88
93
  'deepseek-v4-flash': { inputPer1M: 0.14, outputPer1M: 0.28 },
89
94
  // Google
90
95
  'gemini-3.1-pro-preview': { inputPer1M: 2.00, outputPer1M: 12.00 },
96
+ 'gemini-3.6-flash': { inputPer1M: 1.50, outputPer1M: 7.50 },
91
97
  'gemini-3.5-flash': { inputPer1M: 1.50, outputPer1M: 9.00 },
92
- 'gemini-3.1-flash-lite': { inputPer1M: 0.25, outputPer1M: 1.50 },
98
+ 'gemini-3.5-flash-lite': { inputPer1M: 0.30, outputPer1M: 2.50 },
93
99
  'gemini-3-flash-preview': { inputPer1M: 0.50, outputPer1M: 3.00 },
94
100
  // MiniMax
95
101
  'MiniMax-M3': { inputPer1M: 0.60, outputPer1M: 2.40 },
96
102
  // Kimi (Moonshot) — pay-per-use cache-miss rates; `kimi-for-coding` is the
97
103
  // subscription alias (flat-fee in reality, priced notionally like K2.7 Code).
98
- 'kimi-k2.7-code': { inputPer1M: 0.60, outputPer1M: 2.50 },
99
- 'kimi-k2.7-code-highspeed': { inputPer1M: 0.60, outputPer1M: 2.50 },
100
- 'kimi-k2.6': { inputPer1M: 0.55, outputPer1M: 2.20 },
101
- 'kimi-k2.5': { inputPer1M: 0.40, outputPer1M: 1.90 },
102
- 'kimi-for-coding': { inputPer1M: 0.60, outputPer1M: 2.50 },
104
+ 'kimi-k3': { inputPer1M: 3.00, outputPer1M: 15.00 },
105
+ 'kimi-k2.7-code': { inputPer1M: 0.95, outputPer1M: 4.00 },
106
+ // Kimi doesn't publish a distinct high-speed price in its main table.
107
+ // Leave that variant unpriced rather than presenting an invented estimate.
108
+ 'kimi-k2.6': { inputPer1M: 0.95, outputPer1M: 4.00 },
109
+ 'kimi-for-coding': { inputPer1M: 0.95, outputPer1M: 4.00 },
110
+ 'kimi-for-coding-highspeed': { inputPer1M: 0.95, outputPer1M: 4.00 },
111
+ 'k3': { inputPer1M: 3.00, outputPer1M: 15.00 },
112
+ 'k3-256k': { inputPer1M: 3.00, outputPer1M: 15.00 },
103
113
  // Grok (xAI)
104
114
  'grok-4.5': { inputPer1M: 2.00, outputPer1M: 6.00 },
105
115
  'grok-build-0.1': { inputPer1M: 1.00, outputPer1M: 2.00 },
106
116
  'grok-4.3': { inputPer1M: 1.25, outputPer1M: 2.50 },
107
117
  'grok-code-fast-1': { inputPer1M: 0.20, outputPer1M: 1.50 },
108
118
  'grok-4-fast-reasoning': { inputPer1M: 0.20, outputPer1M: 0.50 },
109
- // Qwen (Alibaba) — qwen3-coder-* 0–256K tier; the Coding Plan is flat-fee so
110
- // this only affects the pay-per-use estimate.
111
- 'qwen3-coder-plus': { inputPer1M: 0.28, outputPer1M: 1.65 },
112
- 'qwen3-coder-next': { inputPer1M: 0.28, outputPer1M: 1.65 },
113
- 'qwen3-coder-flash': { inputPer1M: 0.10, outputPer1M: 0.50 },
119
+ // Qwen (Alibaba) — list prices for the first context tier. Coding Plan
120
+ // variants are flat-fee; these rates describe pay-per-use calls.
121
+ // `qwen3.8-max-preview` is Token-Plan-only (credit-metered, promotional
122
+ // preview rate); Alibaba publishes no pay-per-use per-token price for it.
123
+ // Leave it unpriced rather than borrowing the GA qwen3.8-max rate.
114
124
  'qwen3.7-max': { inputPer1M: 2.50, outputPer1M: 7.50 },
125
+ 'qwen3.7-plus': { inputPer1M: 0.40, outputPer1M: 1.60 },
126
+ 'qwen3.6-plus': { inputPer1M: 0.40, outputPer1M: 2.40 },
127
+ 'qwen3.5-plus': { inputPer1M: 0.40, outputPer1M: 2.40 },
128
+ 'qwen3.6-flash': { inputPer1M: 0.25, outputPer1M: 1.50 },
115
129
  // ModelScope free tier — no per-token charge.
116
130
  'Qwen/Qwen3-Coder-480B-A35B-Instruct': { inputPer1M: 0, outputPer1M: 0 },
117
131
  };
@@ -362,6 +376,7 @@ export function formatCostReport() {
362
376
  lines.push(`**Estimated savings vs no caching:** $${cache.estimatedSavingsUsd.toFixed(4)}`);
363
377
  }
364
378
  }
379
+ lines.push('', ...formatResourceImpactReport(stats.totalTokens));
365
380
  // Models with no pricing entry don't contribute to cost — flag so users
366
381
  // aren't surprised the total looks low.
367
382
  const untracked = breakdown.filter(b => b.estimatedCost === 0 && (b.promptTokens + b.completionTokens) > 0);
@@ -0,0 +1,101 @@
1
+ /**
2
+ * `@web <url>` inline context — fetch a web page and attach its text
3
+ * content to the prompt, the same way `@file` attaches a file.
4
+ *
5
+ * Supported forms (anywhere in the message, like file mentions):
6
+ * @web https://example.com/docs → full URL
7
+ * @web example.com/docs → https:// is auto-prepended
8
+ * @web http://localhost:3000/api → dev servers work too
9
+ *
10
+ * The fetch is best-effort:
11
+ * - HTML is stripped to readable text (tags, scripts, styles removed).
12
+ * - Output is capped at `MAX_WEB_BYTES` (default 32 KB) so a single
13
+ * page can't blow the context window.
14
+ * - Markdown conversion is lightweight (headings, links, lists) — we
15
+ * don't run a full HTML→Markdown pipeline; the goal is "agent can
16
+ * read the page", not "pretty render".
17
+ * - Failures (network, non-2xx, non-text content type) surface as
18
+ * inline notifications, same as missing files.
19
+ *
20
+ * The fetcher is async, so `expandWebMentions` is async — unlike the
21
+ * sync `expandMentions` for files. Callers await it.
22
+ */
23
+ /** Max bytes of text we'll inline from a fetched page (32 KB). */
24
+ export declare const MAX_WEB_BYTES: number;
25
+ /** Result of expanding `@web` mentions in a prompt. */
26
+ export interface WebExpansionResult {
27
+ /** The prompt with fetched page text prepended. */
28
+ enrichedPrompt: string;
29
+ /** Successfully fetched pages. */
30
+ loaded: Array<{
31
+ url: string;
32
+ title: string;
33
+ content: string;
34
+ }>;
35
+ /** Mentions that couldn't be fetched, with a human-readable reason. */
36
+ failures: Array<{
37
+ mention: string;
38
+ reason: string;
39
+ }>;
40
+ }
41
+ /** One `@web` mention match. */
42
+ interface WebToken {
43
+ /** Full match including `@web `, for display. */
44
+ raw: string;
45
+ /** The URL (normalized: `https://` prepended if missing a scheme). */
46
+ url: string;
47
+ /** Start index of `raw` in the source. */
48
+ start: number;
49
+ /** End index (exclusive). */
50
+ end: number;
51
+ }
52
+ /**
53
+ * Extract all `@web` mentions from `text`. Pure (no network).
54
+ * Returns them in document order.
55
+ */
56
+ export declare function extractWebMentions(text: string): WebToken[];
57
+ export interface WebFetchOptions {
58
+ /**
59
+ * The fetch implementation. Defaults to the global `fetch` (Node 18+).
60
+ * Injected so tests can mock without hitting the network.
61
+ */
62
+ fetchImpl?: typeof fetch;
63
+ }
64
+ /**
65
+ * Expand all `@web` mentions in `prompt`: fetch each URL, convert the
66
+ * HTML to readable text, and prepend it as a `[Web pages]` block.
67
+ * Failures are collected, not thrown.
68
+ */
69
+ export declare function expandWebMentions(prompt: string, opts?: WebFetchOptions): Promise<WebExpansionResult>;
70
+ /**
71
+ * Reset the session web cache. Public so callers (e.g. `/web-cache clear`
72
+ * command, or tests) can force a fresh fetch.
73
+ */
74
+ export declare function clearWebCache(): void;
75
+ /**
76
+ * Stats about the session web cache — for `/web-cache status`.
77
+ */
78
+ export declare function webCacheStats(): {
79
+ entries: number;
80
+ maxEntries: number;
81
+ ttlMinutes: number;
82
+ };
83
+ /**
84
+ * Convert HTML to readable plain text + a title.
85
+ *
86
+ * Lightweight — no full parser dependency. Strips `<script>`, `<style>`,
87
+ * and tags, collapses whitespace, extracts `<title>` and the first
88
+ * `<h1>` as the page title. Good enough for the agent to read docs;
89
+ * not a faithful rendering.
90
+ */
91
+ export declare function htmlToText(html: string): {
92
+ title: string;
93
+ content: string;
94
+ };
95
+ /** Format the `[Web pages]` block prepended to the enriched prompt. */
96
+ export declare function formatWebBlock(pages: Array<{
97
+ url: string;
98
+ title: string;
99
+ content: string;
100
+ }>): string;
101
+ export {};