jinzd-ai-cli 0.4.266 → 0.4.268

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 (33) hide show
  1. package/dist/{batch-FQU6HK3Z.js → batch-2N2YMRX2.js} +2 -2
  2. package/dist/{chunk-QW76RX6G.js → chunk-2FQGMR34.js} +1 -1
  3. package/dist/{chunk-Y2X24VYB.js → chunk-74BK22BM.js} +4 -4
  4. package/dist/{chunk-TJNBSR3I.js → chunk-7US7K3CD.js} +1 -1
  5. package/dist/{chunk-FA3HGXXM.js → chunk-EPVJS4F6.js} +3 -1
  6. package/dist/{chunk-V4D7YD24.js → chunk-R7GERZDA.js} +145 -4
  7. package/dist/{chunk-GWOZET2E.js → chunk-RRQZRSXW.js} +1 -1
  8. package/dist/{chunk-LGJ7EX2F.js → chunk-UT2WAJJG.js} +1 -1
  9. package/dist/{chunk-CEJUB4YV.js → chunk-VGVKJTHF.js} +1 -1
  10. package/dist/{chunk-UCHND2K6.js → chunk-VNCBY4KY.js} +193 -2
  11. package/dist/{chunk-3O4VLKD4.js → chunk-WNG3YVZX.js} +1 -1
  12. package/dist/{chunk-N2E6GFLZ.js → chunk-WWLXW4SY.js} +1 -1
  13. package/dist/{chunk-LHY7ST6X.js → chunk-XDITAGE5.js} +1 -1
  14. package/dist/{chunk-FIDEG2PG.js → chunk-YLSM7RF6.js} +3 -3
  15. package/dist/{chunk-XEVURCAM.js → chunk-Z7CZ72RP.js} +3 -3
  16. package/dist/{ci-GZH3QMME.js → ci-3RWVJSZ3.js} +4 -4
  17. package/dist/{ci-format-VKP2MGYJ.js → ci-format-M6HVCXCG.js} +2 -2
  18. package/dist/{constants-ICAF6I3J.js → constants-G6VN7SJL.js} +1 -1
  19. package/dist/{doctor-cli-CO6BJWRW.js → doctor-cli-Y3SVVJBO.js} +4 -4
  20. package/dist/electron-server.js +915 -410
  21. package/dist/{hub-4APIRQ73.js → hub-5T5HKOAR.js} +1 -1
  22. package/dist/index.js +87 -134
  23. package/dist/{persistent-memory-YD3SHSUH.js → persistent-memory-XVSSR277.js} +2 -2
  24. package/dist/{persistent-memory-YPO25MOP.js → persistent-memory-YBWIZWQP.js} +2 -2
  25. package/dist/{pr-CDOPCAPK.js → pr-NF5IWLH3.js} +4 -4
  26. package/dist/{run-tests-QNNP2HCD.js → run-tests-33X3D7PV.js} +2 -2
  27. package/dist/{run-tests-4XRHKHN5.js → run-tests-Y44SCLIO.js} +2 -2
  28. package/dist/{server-B4A7LHZ5.js → server-3LERX42X.js} +5 -5
  29. package/dist/{server-53GM3CRH.js → server-NJ3ZNPQW.js} +114 -38
  30. package/dist/{task-orchestrator-WNV6PT6Z.js → task-orchestrator-JN2WFZSF.js} +5 -5
  31. package/dist/{usage-E3FEYSBU.js → usage-IFTNXTWC.js} +4 -6
  32. package/package.json +1 -1
  33. package/dist/chunk-YRD6M5XI.js +0 -149
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-CEJUB4YV.js";
4
+ } from "./chunk-VGVKJTHF.js";
5
5
  import "./chunk-TU3L3PW7.js";
6
- import "./chunk-LGJ7EX2F.js";
6
+ import "./chunk-UT2WAJJG.js";
7
7
  import {
8
8
  atomicWriteFileSync
9
9
  } from "./chunk-IW3Q7AE5.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONFIG_DIR_NAME,
4
4
  PLUGINS_DIR_NAME
5
- } from "./chunk-LGJ7EX2F.js";
5
+ } from "./chunk-UT2WAJJG.js";
6
6
  import {
7
7
  atomicWriteFileSync
8
8
  } from "./chunk-IW3Q7AE5.js";
@@ -7,7 +7,7 @@ import {
7
7
  searchPersistentMemories,
8
8
  touchMemoryReferences,
9
9
  updateMemoryEntry
10
- } from "./chunk-3O4VLKD4.js";
10
+ } from "./chunk-WNG3YVZX.js";
11
11
  import {
12
12
  indexProject
13
13
  } from "./chunk-GLSR2NR3.js";
@@ -26,7 +26,7 @@ import {
26
26
  runHook,
27
27
  runLifecycleHooks,
28
28
  runTool
29
- } from "./chunk-QW76RX6G.js";
29
+ } from "./chunk-2FQGMR34.js";
30
30
  import {
31
31
  buildTruncatedArgumentsError,
32
32
  getDangerLevel,
@@ -43,14 +43,14 @@ import {
43
43
  } from "./chunk-4BKXL7SM.js";
44
44
  import {
45
45
  runTestsTool
46
- } from "./chunk-N2E6GFLZ.js";
46
+ } from "./chunk-WWLXW4SY.js";
47
47
  import {
48
48
  CONFIG_DIR_NAME,
49
49
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
50
50
  SUBAGENT_ALLOWED_TOOLS,
51
51
  SUBAGENT_DEFAULT_MAX_ROUNDS,
52
52
  SUBAGENT_MAX_ROUNDS_LIMIT
53
- } from "./chunk-LGJ7EX2F.js";
53
+ } from "./chunk-UT2WAJJG.js";
54
54
  import {
55
55
  loadChatIndex,
56
56
  searchChatMemory
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-LGJ7EX2F.js";
4
+ } from "./chunk-UT2WAJJG.js";
5
5
 
6
6
  // src/cli/ci-format.ts
7
7
  var DEFAULT_CI_THRESHOLDS = {
@@ -1,5 +1,5 @@
1
1
  // src/core/constants.ts
2
- var VERSION = "0.4.266";
2
+ var VERSION = "0.4.268";
3
3
  var APP_NAME = "ai-cli";
4
4
  var CONFIG_DIR_NAME = ".aicli";
5
5
  var CONFIG_FILE_NAME = "config.json";
@@ -82,6 +82,7 @@ var SUBAGENT_ALLOWED_TOOLS = /* @__PURE__ */ new Set([
82
82
  "find_references",
83
83
  "search_code"
84
84
  ]);
85
+ var CONTEXT_PRESSURE_THRESHOLD = 0.8;
85
86
  var TEST_TIMEOUT = 3e5;
86
87
  var AGENTIC_BEHAVIOR_GUIDELINE = `# Important Behavioral Guidelines
87
88
 
@@ -155,6 +156,7 @@ export {
155
156
  SUBAGENT_DEFAULT_MAX_ROUNDS,
156
157
  SUBAGENT_MAX_ROUNDS_LIMIT,
157
158
  SUBAGENT_ALLOWED_TOOLS,
159
+ CONTEXT_PRESSURE_THRESHOLD,
158
160
  TEST_TIMEOUT,
159
161
  AGENTIC_BEHAVIOR_GUIDELINE,
160
162
  buildUserIdentityPrompt,
@@ -1,12 +1,150 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- computeCost,
4
- formatCost
5
- } from "./chunk-YRD6M5XI.js";
6
2
  import {
7
3
  atomicWriteFileSync
8
4
  } from "./chunk-IW3Q7AE5.js";
9
5
 
6
+ // src/core/pricing.ts
7
+ var DEEPSEEK_CNY_PER_USD = 6.9;
8
+ var DEEPSEEK_TIME_PRICING_EFFECTIVE_AT = /* @__PURE__ */ new Date("2026-08-16T16:00:00.000Z");
9
+ function deepSeekCnyPricing(cacheRead, input, output) {
10
+ return {
11
+ cacheRead: cacheRead / DEEPSEEK_CNY_PER_USD,
12
+ input: input / DEEPSEEK_CNY_PER_USD,
13
+ output: output / DEEPSEEK_CNY_PER_USD
14
+ };
15
+ }
16
+ function getDeepSeekV4Pricing(model, at) {
17
+ const isPro = model.startsWith("deepseek-v4-pro");
18
+ const isFlash = model.startsWith("deepseek-v4-flash");
19
+ if (!isPro && !isFlash) return null;
20
+ if (at < DEEPSEEK_TIME_PRICING_EFFECTIVE_AT) {
21
+ return isPro ? deepSeekCnyPricing(0.025, 3, 6) : deepSeekCnyPricing(0.02, 1, 2);
22
+ }
23
+ const beijingHour = (at.getUTCHours() + 8) % 24;
24
+ const isPeak = beijingHour >= 9 && beijingHour < 12 || beijingHour >= 14 && beijingHour < 18;
25
+ if (isPro) {
26
+ return isPeak ? deepSeekCnyPricing(0.3, 9, 27) : deepSeekCnyPricing(0.15, 4.5, 13.5);
27
+ }
28
+ return isPeak ? deepSeekCnyPricing(0.1, 3, 9) : deepSeekCnyPricing(0.05, 1.5, 4.5);
29
+ }
30
+ var PRICING_TABLE = {
31
+ // ── Anthropic Claude ──────────────────────────────────────────
32
+ "claude-opus-4-8": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
33
+ "claude-opus-4-7": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
34
+ "claude-opus-4-6": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
35
+ "claude-opus-4-5": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
36
+ "claude-sonnet-4-6": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
37
+ "claude-sonnet-4-5-20250929": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
38
+ "claude-haiku-4-5-20251001": { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.1 },
39
+ "claude-haiku-4-5": { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.1 },
40
+ // Legacy Claude 3.x families (prefix fallback handles minor date suffixes)
41
+ "claude-3-5-sonnet": { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 },
42
+ "claude-3-5-haiku": { input: 0.8, output: 4, cacheWrite: 1, cacheRead: 0.08 },
43
+ "claude-3-opus": { input: 15, output: 75, cacheWrite: 18.75, cacheRead: 1.5 },
44
+ // ── OpenAI ────────────────────────────────────────────────────
45
+ // GAP (v0.4.184): the GPT-5 family (gpt-5, gpt-5-mini/nano, gpt-5.4, gpt-5.4-pro)
46
+ // and o4-mini are in the provider's model list but have NO verified pricing yet —
47
+ // left unpriced on purpose so `aicli usage` shows "—" (unknown) rather than a
48
+ // deceptive $0.00. Add real rates when confirmed from the official pricing page.
49
+ "gpt-4o": { input: 2.5, output: 10, cacheRead: 1.25 },
50
+ "gpt-4o-mini": { input: 0.15, output: 0.6, cacheRead: 0.075 },
51
+ "gpt-4-turbo": { input: 10, output: 30 },
52
+ "gpt-4": { input: 30, output: 60 },
53
+ "gpt-4.1": { input: 2, output: 8, cacheRead: 0.5 },
54
+ "gpt-4.1-mini": { input: 0.4, output: 1.6, cacheRead: 0.1 },
55
+ "gpt-4.1-nano": { input: 0.1, output: 0.4, cacheRead: 0.025 },
56
+ "o1": { input: 15, output: 60, cacheRead: 7.5 },
57
+ "o1-mini": { input: 3, output: 12, cacheRead: 1.5 },
58
+ "o3": { input: 10, output: 40, cacheRead: 2.5 },
59
+ "o3-mini": { input: 1.1, output: 4.4, cacheRead: 0.55 },
60
+ // ── Google Gemini ─────────────────────────────────────────────
61
+ "gemini-2.5-pro": { input: 1.25, output: 10 },
62
+ "gemini-2.5-flash": { input: 0.3, output: 2.5 },
63
+ "gemini-2.0-flash": { input: 0.1, output: 0.4 },
64
+ "gemini-1.5-pro": { input: 1.25, output: 5 },
65
+ "gemini-1.5-flash": { input: 0.075, output: 0.3 },
66
+ // ── DeepSeek ──────────────────────────────────────────────────
67
+ // V4 family (2026-04-23+):1M context, Thinking / Non-Thinking dual-mode, 384K max output
68
+ // 费率 2026-08-01 对 api-docs.deepseek.com/quick_start/pricing 官方 USD 表逐项核对。
69
+ // 修正前 pro 三项整齐高 4×(官方降过价未跟)、flash cacheRead 高 10×(像是按 input 的
70
+ // 20% 拍脑袋而非抄文档)——`aicli usage` 因此系统性高报 DeepSeek 成本。
71
+ // 待办:官方已公告峰谷定价(北京时间 9-12 点、14-18 点为平时 2 倍),本表仍是单一费率,
72
+ // 届时高峰时段会低报;等该策略实际生效后再决定是否引入时段维度。
73
+ // Legacy aliases:retires 2026-07-24 UTC 15:59,官方 route 到 V4 Flash。
74
+ // 这几条只服务历史 session 的成本回算,保留当时的费率口径,不随现价改动。
75
+ "deepseek-chat": { input: 0.14, output: 0.28, cacheRead: 0.028 },
76
+ "deepseek-reasoner": { input: 0.14, output: 0.28, cacheRead: 0.028 },
77
+ "deepseek-v3": { input: 0.27, output: 1.1, cacheRead: 0.07 },
78
+ // ── Moonshot Kimi ─────────────────────────────────────────────
79
+ "moonshot-v1-8k": { input: 0.17, output: 0.17 },
80
+ "moonshot-v1-32k": { input: 0.33, output: 0.33 },
81
+ "moonshot-v1-128k": { input: 0.83, output: 0.83 },
82
+ "kimi-k2": { input: 0.6, output: 2.5 },
83
+ "kimi-latest": { input: 0.6, output: 2.5 },
84
+ // Kimi K3(2026-07 旗舰,1M 上下文)官方定价 platform.kimi.ai/pricing/chat-k3:
85
+ // 输入 cache-miss $3.00 / cache-hit $0.30,输出 $15.00(/MTok)。
86
+ "kimi-k3": { input: 3, output: 15, cacheRead: 0.3 },
87
+ // ── Zhipu GLM ─────────────────────────────────────────────────
88
+ "glm-4-plus": { input: 0.7, output: 0.7 },
89
+ "glm-4": { input: 0.14, output: 0.14 },
90
+ "glm-4-flash": { input: 0, output: 0 },
91
+ "glm-4.5": { input: 0.29, output: 1.14 },
92
+ "glm-4.6": { input: 0.6, output: 2.2 },
93
+ "glm-4.6v": { input: 0.6, output: 2.2 },
94
+ "glm-5": { input: 0.85, output: 2.85 },
95
+ // GLM-5.2(2026-06)官方直连 API 定价 $1.40 / $4.40。
96
+ "glm-5.2": { input: 1.4, output: 4.4 },
97
+ // GLM-5V-Turbo(2026-04 视觉编程旗舰)官方直连 API 定价 $1.20 / $4.00。
98
+ "glm-5v-turbo": { input: 1.2, output: 4 },
99
+ "glm-5.1": { input: 0.95, output: 3.15 },
100
+ "glm-5.1-reasoning": { input: 1.4, output: 4.4 },
101
+ "glm-5.1-air": { input: 0.4, output: 1.2 },
102
+ "glm-z1": { input: 0.5, output: 1.5 },
103
+ "glm-z1-air": { input: 0.2, output: 0.6 },
104
+ "glm-z1-flash": { input: 0, output: 0 }
105
+ // ── MiniMax (海螺) ────────────────────────────────────────────
106
+ // GAP (v0.4.184): MiniMax-M3 / M2.x are unpriced — no verified rate anchor yet.
107
+ // Unpriced → `aicli usage` shows "—" (unknown), not a false $0.00. Add when confirmed.
108
+ // ── OpenRouter (pass-through — actual cost depends on underlying model) ──
109
+ // Left empty by design: model IDs are "vendor/model" (e.g. anthropic/claude-sonnet-4)
110
+ // and the real price is set by the underlying model + OpenRouter markup, not statically
111
+ // resolvable here. Shows "—" (unknown) in `aicli usage`.
112
+ // ── Ollama (local, zero cost) ─────────────────────────────────
113
+ // Handled via provider check below (FREE_PROVIDERS → genuine $0.00, not "unknown").
114
+ };
115
+ var FREE_PROVIDERS = /* @__PURE__ */ new Set(["ollama"]);
116
+ function getPricing(provider, model, at = /* @__PURE__ */ new Date()) {
117
+ if (FREE_PROVIDERS.has(provider.toLowerCase())) {
118
+ return { input: 0, output: 0 };
119
+ }
120
+ const key = model.toLowerCase();
121
+ if (provider.toLowerCase() === "deepseek") {
122
+ const dynamicPricing = getDeepSeekV4Pricing(key, at);
123
+ if (dynamicPricing) return dynamicPricing;
124
+ }
125
+ if (PRICING_TABLE[key]) return PRICING_TABLE[key];
126
+ const keys = Object.keys(PRICING_TABLE).sort((a, b) => b.length - a.length);
127
+ for (const k of keys) {
128
+ if (key.startsWith(k)) return PRICING_TABLE[k];
129
+ }
130
+ return null;
131
+ }
132
+ function computeCost(provider, model, usage, at = /* @__PURE__ */ new Date()) {
133
+ const p = getPricing(provider, model, at);
134
+ if (!p) return null;
135
+ const input = usage.inputTokens * p.input;
136
+ const output = usage.outputTokens * p.output;
137
+ const cacheWrite = (usage.cacheCreationTokens ?? 0) * (p.cacheWrite ?? p.input);
138
+ const cacheRead = (usage.cacheReadTokens ?? 0) * (p.cacheRead ?? p.input);
139
+ return (input + output + cacheWrite + cacheRead) / 1e6;
140
+ }
141
+ function formatCost(amount) {
142
+ if (amount === 0) return "$0.0000";
143
+ if (amount < 0.01) return `$${amount.toFixed(4)}`;
144
+ if (amount < 1) return `$${amount.toFixed(3)}`;
145
+ return `$${amount.toFixed(2)}`;
146
+ }
147
+
10
148
  // src/core/cost-tracker.ts
11
149
  import { existsSync, readFileSync } from "fs";
12
150
  import { join } from "path";
@@ -261,5 +399,8 @@ var CostTracker = class _CostTracker {
261
399
  };
262
400
 
263
401
  export {
402
+ getPricing,
403
+ computeCost,
404
+ formatCost,
264
405
  CostTracker
265
406
  };
@@ -6,7 +6,7 @@ import {
6
6
  MEMORY_FILE_NAME,
7
7
  MEMORY_MAX_CHARS,
8
8
  MEMORY_STORE_FILE_NAME
9
- } from "./chunk-FA3HGXXM.js";
9
+ } from "./chunk-EPVJS4F6.js";
10
10
  import {
11
11
  atomicWriteFileSync
12
12
  } from "./chunk-6BUTA5VW.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.266";
4
+ var VERSION = "0.4.268";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-LGJ7EX2F.js";
11
+ } from "./chunk-UT2WAJJG.js";
12
12
  import {
13
13
  atomicWriteFileSync
14
14
  } from "./chunk-IW3Q7AE5.js";
@@ -1,17 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ computeCost
4
+ } from "./chunk-R7GERZDA.js";
5
+ import {
6
+ estimateTokens,
3
7
  truncateForPersist
4
- } from "./chunk-Y2X24VYB.js";
8
+ } from "./chunk-74BK22BM.js";
5
9
  import {
6
10
  APP_NAME,
7
11
  CONFIG_DIR_NAME,
12
+ CONTEXT_PRESSURE_THRESHOLD,
8
13
  DEV_STATE_FILE_NAME,
9
14
  MCP_CALL_TIMEOUT,
10
15
  MCP_CONNECT_TIMEOUT,
11
16
  MCP_PROTOCOL_VERSION,
12
17
  MCP_TOOL_PREFIX,
13
18
  VERSION
14
- } from "./chunk-LGJ7EX2F.js";
19
+ } from "./chunk-UT2WAJJG.js";
15
20
  import {
16
21
  atomicWriteFileSync
17
22
  } from "./chunk-IW3Q7AE5.js";
@@ -975,6 +980,38 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
975
980
  return committedSize < originalSize;
976
981
  }
977
982
 
983
+ // src/core/context-pressure.ts
984
+ function estimateConversationTokens(input) {
985
+ let total = 0;
986
+ if (input.systemPrompt) total += estimateTokens(input.systemPrompt);
987
+ for (const msg of input.messages) {
988
+ if (typeof msg.content === "string") {
989
+ total += estimateTokens(msg.content);
990
+ } else if (Array.isArray(msg.content)) {
991
+ for (const part of msg.content) {
992
+ if (part.type === "text" && part.text) total += estimateTokens(part.text);
993
+ }
994
+ }
995
+ if (msg.toolCalls) {
996
+ for (const tc of msg.toolCalls) {
997
+ total += estimateTokens(JSON.stringify(tc.arguments));
998
+ }
999
+ }
1000
+ }
1001
+ return total;
1002
+ }
1003
+ function evaluateContextPressure(input) {
1004
+ if (input.contextWindow <= 0) return { shouldCompact: false, ratio: null, percent: null };
1005
+ const ratio = input.estimatedTokens / input.contextWindow;
1006
+ const threshold = input.threshold ?? CONTEXT_PRESSURE_THRESHOLD;
1007
+ return {
1008
+ shouldCompact: input.autoCompactEnabled && ratio >= threshold,
1009
+ ratio,
1010
+ percent: Math.round(ratio * 100)
1011
+ };
1012
+ }
1013
+ var AUTO_COMPACT_INSTRUCTION = "Preserve key context, compress old content, ensure seamless continuation";
1014
+
978
1015
  // src/repl/dev-state.ts
979
1016
  import { existsSync as existsSync3, readFileSync as readFileSync3, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
980
1017
  import { join as join3 } from "path";
@@ -1127,6 +1164,119 @@ function applyThinkCommand(sub, state) {
1127
1164
  return stay(`Unknown /think option "${sub}" \u2014 expected on | off | low | high | max | status`);
1128
1165
  }
1129
1166
 
1167
+ // src/core/profile-command.ts
1168
+ var PROFILE_FIELDS = ["name", "nickname", "role", "bio", "interests", "locale", "extra"];
1169
+ function stripSurroundingQuotes(value) {
1170
+ const pairs = [['"', '"'], ["'", "'"], ["\u201C", "\u201D"], ["\u2018", "\u2019"], ["\u300C", "\u300D"]];
1171
+ for (const [open, close] of pairs) {
1172
+ if (value.length >= 2 && value.startsWith(open) && value.endsWith(close)) {
1173
+ return value.slice(open.length, value.length - close.length).trim();
1174
+ }
1175
+ }
1176
+ return value;
1177
+ }
1178
+ function showRows(profile) {
1179
+ const rows = [];
1180
+ if (profile.name) rows.push(["Name", profile.name]);
1181
+ if (profile.nickname) rows.push(["Nickname", profile.nickname]);
1182
+ if (profile.role) rows.push(["Role", profile.role]);
1183
+ if (profile.bio) rows.push(["Bio", profile.bio]);
1184
+ if (profile.interests?.length) rows.push(["Interests", profile.interests.join(", ")]);
1185
+ if (profile.locale) rows.push(["Locale", profile.locale]);
1186
+ if (profile.extra) {
1187
+ rows.push(["Extra", profile.extra.length > 80 ? `${profile.extra.slice(0, 80)}\u2026` : profile.extra]);
1188
+ }
1189
+ return rows;
1190
+ }
1191
+ function applyProfileCommand(args, profile) {
1192
+ const sub = (args[0] ?? "show").toLowerCase();
1193
+ if (sub === "show" || sub === "view") {
1194
+ const rows = showRows(profile);
1195
+ if (rows.length === 0) {
1196
+ return {
1197
+ summary: "No profile configured yet.",
1198
+ rows: [],
1199
+ details: ["Set one with /profile set <field> <value> \u2014 it is injected into every conversation."],
1200
+ changed: false,
1201
+ isError: false
1202
+ };
1203
+ }
1204
+ return {
1205
+ summary: "\u{1F464} Your Profile",
1206
+ rows,
1207
+ details: ["This identity is injected into every AI conversation."],
1208
+ changed: false,
1209
+ isError: false
1210
+ };
1211
+ }
1212
+ if (sub === "clear") {
1213
+ return {
1214
+ profile: {},
1215
+ summary: "Profile cleared. The AI will no longer know who you are.",
1216
+ rows: [],
1217
+ details: [],
1218
+ changed: true,
1219
+ isError: false
1220
+ };
1221
+ }
1222
+ if (sub === "set") {
1223
+ const field = args[1];
1224
+ const value = args.slice(2).join(" ").trim();
1225
+ if (!field || !PROFILE_FIELDS.includes(field)) {
1226
+ return {
1227
+ summary: "Usage: /profile set <field> <value>",
1228
+ rows: [],
1229
+ details: [`Fields: ${PROFILE_FIELDS.join(", ")}`],
1230
+ changed: false,
1231
+ isError: true
1232
+ };
1233
+ }
1234
+ if (!value) {
1235
+ return {
1236
+ summary: `Usage: /profile set ${field} <value>`,
1237
+ rows: [],
1238
+ details: [],
1239
+ changed: false,
1240
+ isError: true
1241
+ };
1242
+ }
1243
+ const updated = { ...profile };
1244
+ if (field === "interests") {
1245
+ updated.interests = value.split(",").map((s) => stripSurroundingQuotes(s.trim())).filter(Boolean);
1246
+ } else {
1247
+ updated[field] = stripSurroundingQuotes(value);
1248
+ }
1249
+ const shown = field === "interests" ? (updated.interests ?? []).join(", ") : stripSurroundingQuotes(value);
1250
+ return {
1251
+ profile: updated,
1252
+ summary: `Profile updated: ${field} = ${shown}`,
1253
+ rows: [],
1254
+ details: [],
1255
+ changed: true,
1256
+ isError: false
1257
+ };
1258
+ }
1259
+ if (sub === "edit") {
1260
+ return {
1261
+ summary: "Interactive editing lives in the setup wizard.",
1262
+ rows: [],
1263
+ details: [
1264
+ "Run `aicli config` in a terminal, or use /profile set <field> <value> here.",
1265
+ `Fields: ${PROFILE_FIELDS.join(", ")}`
1266
+ ],
1267
+ changed: false,
1268
+ isError: false
1269
+ };
1270
+ }
1271
+ return {
1272
+ summary: `Unknown /profile option "${args[0]}" \u2014 expected show | set | clear | edit`,
1273
+ rows: [],
1274
+ details: [],
1275
+ changed: false,
1276
+ isError: true
1277
+ };
1278
+ }
1279
+
1130
1280
  // src/core/git-diff.ts
1131
1281
  import { execFileSync } from "child_process";
1132
1282
  function readGitDiff(options = {}) {
@@ -1138,15 +1288,56 @@ function readGitDiff(options = {}) {
1138
1288
  }).trim();
1139
1289
  }
1140
1290
 
1291
+ // src/core/session-cost.ts
1292
+ function buildSessionCostReport(input) {
1293
+ const { usage } = input;
1294
+ const totalTokens = usage.inputTokens + usage.outputTokens + usage.cacheCreationTokens + usage.cacheReadTokens;
1295
+ if (totalTokens === 0) {
1296
+ return { hasUsage: false, totalTokens: 0, cacheHitPct: null, cost: null, costSource: "unknown", savings: null };
1297
+ }
1298
+ const liveCost = computeCost(input.provider, input.model, usage);
1299
+ const useAccrual = input.accruedUsd > 0;
1300
+ const cost = useAccrual ? input.accruedUsd : liveCost;
1301
+ const costSource = useAccrual ? input.accrualIncomplete ? "accrued-partial" : "accrued" : liveCost != null ? "estimated" : "unknown";
1302
+ let savings = null;
1303
+ if (liveCost != null && usage.cacheReadTokens > 0) {
1304
+ const withoutCache = computeCost(input.provider, input.model, {
1305
+ inputTokens: usage.inputTokens + usage.cacheReadTokens,
1306
+ outputTokens: usage.outputTokens,
1307
+ cacheCreationTokens: usage.cacheCreationTokens,
1308
+ cacheReadTokens: 0
1309
+ });
1310
+ if (withoutCache != null) savings = withoutCache - liveCost;
1311
+ }
1312
+ const cacheHitPct = usage.cacheReadTokens > 0 ? Math.round(usage.cacheReadTokens / (usage.cacheReadTokens + usage.inputTokens) * 100) : null;
1313
+ return { hasUsage: true, totalTokens, cacheHitPct, cost, costSource, savings };
1314
+ }
1315
+ function costSourceNote(source) {
1316
+ switch (source) {
1317
+ case "accrued-partial":
1318
+ return "(partial \u2014 some turns had unknown pricing)";
1319
+ case "estimated":
1320
+ return "(estimated at current rates)";
1321
+ default:
1322
+ return null;
1323
+ }
1324
+ }
1325
+
1141
1326
  export {
1142
1327
  applyThinkCommand,
1328
+ applyProfileCommand,
1143
1329
  readGitDiff,
1144
1330
  scanDirTree,
1145
1331
  scanProject,
1146
1332
  buildInitPrompt,
1333
+ buildSessionCostReport,
1334
+ costSourceNote,
1147
1335
  parseSimpleYaml,
1148
1336
  persistToolRound,
1149
1337
  autoTrimSessionIfNeeded,
1338
+ estimateConversationTokens,
1339
+ evaluateContextPressure,
1340
+ AUTO_COMPACT_INSTRUCTION,
1150
1341
  SNAPSHOT_PROMPT,
1151
1342
  sessionHasMeaningfulContent,
1152
1343
  saveDevState,
@@ -6,7 +6,7 @@ import {
6
6
  MEMORY_FILE_NAME,
7
7
  MEMORY_MAX_CHARS,
8
8
  MEMORY_STORE_FILE_NAME
9
- } from "./chunk-LGJ7EX2F.js";
9
+ } from "./chunk-UT2WAJJG.js";
10
10
  import {
11
11
  DEFAULT_PATTERNS,
12
12
  redactString
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-LGJ7EX2F.js";
4
+ } from "./chunk-UT2WAJJG.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TEST_TIMEOUT
3
- } from "./chunk-FA3HGXXM.js";
3
+ } from "./chunk-EPVJS4F6.js";
4
4
 
5
5
  // src/tools/builtin/run-tests.ts
6
6
  import { execSync, spawnSync } from "child_process";
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-AUEX6RNY.js";
5
5
  import {
6
6
  ConfigManager
7
- } from "./chunk-CEJUB4YV.js";
7
+ } from "./chunk-VGVKJTHF.js";
8
8
  import {
9
9
  getActivePluginAssets,
10
10
  getPendingHookTrust,
@@ -14,7 +14,7 @@ import {
14
14
  listHooks,
15
15
  listInstalledPlugins,
16
16
  resetStats
17
- } from "./chunk-QW76RX6G.js";
17
+ } from "./chunk-2FQGMR34.js";
18
18
  import {
19
19
  getGitRoot
20
20
  } from "./chunk-HOSJZMQS.js";
@@ -26,7 +26,7 @@ import {
26
26
  MCP_PROJECT_CONFIG_NAME,
27
27
  MEMORY_FILE_NAME,
28
28
  VERSION
29
- } from "./chunk-LGJ7EX2F.js";
29
+ } from "./chunk-UT2WAJJG.js";
30
30
 
31
31
  // src/diagnostics/doctor-report.ts
32
32
  import { existsSync as existsSync3, statSync as statSync2 } from "fs";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  evaluateCiGate,
4
4
  normalizeCiThresholds
5
- } from "./chunk-TJNBSR3I.js";
5
+ } from "./chunk-7US7K3CD.js";
6
6
  import {
7
7
  buildReviewPrompt,
8
8
  buildSecurityReviewPrompt,
@@ -16,10 +16,10 @@ import {
16
16
  } from "./chunk-AUEX6RNY.js";
17
17
  import {
18
18
  ConfigManager
19
- } from "./chunk-CEJUB4YV.js";
19
+ } from "./chunk-VGVKJTHF.js";
20
20
  import {
21
21
  VERSION
22
- } from "./chunk-LGJ7EX2F.js";
22
+ } from "./chunk-UT2WAJJG.js";
23
23
 
24
24
  // src/cli/ci.ts
25
25
  import { execFileSync } from "child_process";
@@ -3,15 +3,15 @@ import {
3
3
  CI_COMMENT_MARKER,
4
4
  countSeverity,
5
5
  runCi
6
- } from "./chunk-XEVURCAM.js";
7
- import "./chunk-TJNBSR3I.js";
6
+ } from "./chunk-Z7CZ72RP.js";
7
+ import "./chunk-7US7K3CD.js";
8
8
  import "./chunk-HLWUDRBO.js";
9
9
  import "./chunk-6YZEZFX5.js";
10
10
  import "./chunk-AUEX6RNY.js";
11
- import "./chunk-CEJUB4YV.js";
11
+ import "./chunk-VGVKJTHF.js";
12
12
  import "./chunk-3OBY7WSS.js";
13
13
  import "./chunk-TU3L3PW7.js";
14
- import "./chunk-LGJ7EX2F.js";
14
+ import "./chunk-UT2WAJJG.js";
15
15
  import "./chunk-IW3Q7AE5.js";
16
16
  export {
17
17
  CI_COMMENT_MARKER,
@@ -6,8 +6,8 @@ import {
6
6
  formatCiResult,
7
7
  formatCiSarif,
8
8
  normalizeCiThresholds
9
- } from "./chunk-TJNBSR3I.js";
10
- import "./chunk-LGJ7EX2F.js";
9
+ } from "./chunk-7US7K3CD.js";
10
+ import "./chunk-UT2WAJJG.js";
11
11
  export {
12
12
  DEFAULT_CI_THRESHOLDS,
13
13
  detectCiGateSignals,
@@ -38,7 +38,7 @@ import {
38
38
  TEST_TIMEOUT,
39
39
  VERSION,
40
40
  buildUserIdentityPrompt
41
- } from "./chunk-LGJ7EX2F.js";
41
+ } from "./chunk-UT2WAJJG.js";
42
42
  export {
43
43
  AGENTIC_BEHAVIOR_GUIDELINE,
44
44
  APP_NAME,
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  formatDoctorReport,
4
4
  runDoctorCli
5
- } from "./chunk-FIDEG2PG.js";
5
+ } from "./chunk-YLSM7RF6.js";
6
6
  import "./chunk-AUEX6RNY.js";
7
- import "./chunk-CEJUB4YV.js";
8
- import "./chunk-QW76RX6G.js";
7
+ import "./chunk-VGVKJTHF.js";
8
+ import "./chunk-2FQGMR34.js";
9
9
  import "./chunk-3OBY7WSS.js";
10
10
  import "./chunk-TU3L3PW7.js";
11
11
  import "./chunk-HOSJZMQS.js";
12
- import "./chunk-LGJ7EX2F.js";
12
+ import "./chunk-UT2WAJJG.js";
13
13
  import "./chunk-IW3Q7AE5.js";
14
14
  export {
15
15
  formatDoctorReport,