codetyper-cli 0.2.2 → 0.2.4

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/dist/index.js CHANGED
@@ -27465,8 +27465,10 @@ var init_paths = __esm(() => {
27465
27465
  config: join(DIRS.config, "config.json"),
27466
27466
  keybindings: join(DIRS.config, "keybindings.json"),
27467
27467
  credentials: join(DIRS.data, "credentials.json"),
27468
+ vars: join(DIRS.config, "vars.json"),
27468
27469
  history: join(DIRS.data, "history.json"),
27469
27470
  modelsCache: join(DIRS.cache, "models.json"),
27471
+ copilotTokenCache: join(DIRS.cache, "copilot-token.json"),
27470
27472
  frecency: join(DIRS.cache, "frecency.json"),
27471
27473
  kvStore: join(DIRS.state, "kv.json"),
27472
27474
  settings: join(DIRS.config, "settings.json")
@@ -37144,11 +37146,25 @@ __export(exports_token, {
37144
37146
  getOAuthToken: () => getOAuthToken,
37145
37147
  buildHeaders: () => buildHeaders
37146
37148
  });
37147
- import { readFile } from "fs/promises";
37149
+ import { readFile, writeFile, mkdir } from "fs/promises";
37148
37150
  import { existsSync } from "fs";
37149
37151
  import { homedir as homedir2, platform } from "os";
37150
37152
  import { join as join2 } from "path";
37151
- var getConfigDir = () => {
37153
+ var loadCachedToken = async () => {
37154
+ try {
37155
+ const data = await readFile(FILES.copilotTokenCache, "utf-8");
37156
+ const token = JSON.parse(data);
37157
+ if (token.expires_at > Date.now() / 1000 + 60) {
37158
+ return token;
37159
+ }
37160
+ } catch {}
37161
+ return null;
37162
+ }, saveCachedToken = async (token) => {
37163
+ try {
37164
+ await mkdir(DIRS.cache, { recursive: true });
37165
+ await writeFile(FILES.copilotTokenCache, JSON.stringify(token), "utf-8");
37166
+ } catch {}
37167
+ }, getConfigDir = () => {
37152
37168
  const home = homedir2();
37153
37169
  const os4 = platform();
37154
37170
  if (process.env.XDG_CONFIG_HOME && existsSync(process.env.XDG_CONFIG_HOME)) {
@@ -37200,6 +37216,11 @@ var getConfigDir = () => {
37200
37216
  if (currentState.githubToken && currentState.githubToken.expires_at > Date.now() / 1000) {
37201
37217
  return currentState.githubToken;
37202
37218
  }
37219
+ const cachedToken = await loadCachedToken();
37220
+ if (cachedToken) {
37221
+ setGitHubToken(cachedToken);
37222
+ return cachedToken;
37223
+ }
37203
37224
  const response2 = await source_default2.get(COPILOT_AUTH_URL, {
37204
37225
  headers: {
37205
37226
  Authorization: `token ${currentState.oauthToken}`,
@@ -37210,6 +37231,7 @@ var getConfigDir = () => {
37210
37231
  throw new Error("Failed to refresh Copilot token");
37211
37232
  }
37212
37233
  setGitHubToken(response2);
37234
+ saveCachedToken(response2).catch(() => {});
37213
37235
  return response2;
37214
37236
  }, buildHeaders = (token) => ({
37215
37237
  Authorization: `Bearer ${token.token}`,
@@ -37223,6 +37245,7 @@ var getConfigDir = () => {
37223
37245
  var init_token = __esm(() => {
37224
37246
  init_source4();
37225
37247
  init_copilot();
37248
+ init_paths();
37226
37249
  init_state();
37227
37250
  });
37228
37251
 
@@ -65586,7 +65609,8 @@ var logIdCounter = 0, generateLogId = () => `log-${++logIdCounter}-${Date.now()}
65586
65609
  inputTokens: 0,
65587
65610
  outputTokens: 0,
65588
65611
  thinkingStartTime: null,
65589
- lastThinkingDuration: 0
65612
+ lastThinkingDuration: 0,
65613
+ contextMaxTokens: 128000
65590
65614
  }), createInitialStreamingState = () => ({
65591
65615
  logId: null,
65592
65616
  content: "",
@@ -65638,7 +65662,15 @@ var init_app = __esm(async () => {
65638
65662
  isCompacting: false,
65639
65663
  streamingLog: createInitialStreamingState(),
65640
65664
  suggestions: createInitialSuggestionState(),
65641
- cascadeEnabled: true
65665
+ cascadeEnabled: true,
65666
+ mcpServers: [],
65667
+ brain: {
65668
+ status: "disconnected",
65669
+ user: null,
65670
+ knowledgeCount: 0,
65671
+ memoryCount: 0,
65672
+ showBanner: true
65673
+ }
65642
65674
  });
65643
65675
  let inputInsertFn = null;
65644
65676
  const setInputInsertFn = (fn) => {
@@ -65678,6 +65710,8 @@ var init_app = __esm(async () => {
65678
65710
  const streamingLogIsActive = () => store.streamingLog.isStreaming;
65679
65711
  const suggestions = () => store.suggestions;
65680
65712
  const cascadeEnabled = () => store.cascadeEnabled;
65713
+ const mcpServers = () => store.mcpServers;
65714
+ const brain = () => store.brain;
65681
65715
  const setMode = (newMode) => {
65682
65716
  setStore("mode", newMode);
65683
65717
  };
@@ -65826,6 +65860,58 @@ var init_app = __esm(async () => {
65826
65860
  const toggleCascadeEnabled = () => {
65827
65861
  setStore("cascadeEnabled", !store.cascadeEnabled);
65828
65862
  };
65863
+ const setBrainStatus = (status) => {
65864
+ setStore("brain", {
65865
+ ...store.brain,
65866
+ status
65867
+ });
65868
+ };
65869
+ const setBrainUser = (user) => {
65870
+ setStore("brain", {
65871
+ ...store.brain,
65872
+ user
65873
+ });
65874
+ };
65875
+ const setBrainCounts = (knowledgeCount, memoryCount) => {
65876
+ setStore("brain", {
65877
+ ...store.brain,
65878
+ knowledgeCount,
65879
+ memoryCount
65880
+ });
65881
+ };
65882
+ const setBrainShowBanner = (showBanner) => {
65883
+ setStore("brain", {
65884
+ ...store.brain,
65885
+ showBanner
65886
+ });
65887
+ };
65888
+ const dismissBrainBanner = () => {
65889
+ setStore("brain", {
65890
+ ...store.brain,
65891
+ showBanner: false
65892
+ });
65893
+ };
65894
+ const setMcpServers = (servers) => {
65895
+ setStore("mcpServers", servers);
65896
+ };
65897
+ const addMcpServer = (server) => {
65898
+ setStore(produce((s) => {
65899
+ const existingIndex = s.mcpServers.findIndex((srv) => srv.id === server.id);
65900
+ if (existingIndex !== -1) {
65901
+ s.mcpServers[existingIndex] = server;
65902
+ } else {
65903
+ s.mcpServers.push(server);
65904
+ }
65905
+ }));
65906
+ };
65907
+ const updateMcpServerStatus = (id, status) => {
65908
+ setStore(produce((s) => {
65909
+ const server = s.mcpServers.find((srv) => srv.id === id);
65910
+ if (server) {
65911
+ server.status = status;
65912
+ }
65913
+ }));
65914
+ };
65829
65915
  const startThinking = () => {
65830
65916
  setStore("sessionStats", {
65831
65917
  ...store.sessionStats,
@@ -65850,6 +65936,12 @@ var init_app = __esm(async () => {
65850
65936
  const resetSessionStats = () => {
65851
65937
  setStore("sessionStats", createInitialSessionStats());
65852
65938
  };
65939
+ const setContextMaxTokens = (maxTokens) => {
65940
+ setStore("sessionStats", {
65941
+ ...store.sessionStats,
65942
+ contextMaxTokens: maxTokens
65943
+ });
65944
+ };
65853
65945
  const toggleTodos = () => {
65854
65946
  setStore("todosVisible", !store.todosVisible);
65855
65947
  };
@@ -66007,6 +66099,8 @@ var init_app = __esm(async () => {
66007
66099
  streamingLogIsActive,
66008
66100
  suggestions,
66009
66101
  cascadeEnabled,
66102
+ mcpServers,
66103
+ brain,
66010
66104
  setMode,
66011
66105
  setScreenMode,
66012
66106
  setInteractionMode,
@@ -66038,10 +66132,19 @@ var init_app = __esm(async () => {
66038
66132
  setProvider,
66039
66133
  setCascadeEnabled,
66040
66134
  toggleCascadeEnabled,
66135
+ setBrainStatus,
66136
+ setBrainUser,
66137
+ setBrainCounts,
66138
+ setBrainShowBanner,
66139
+ dismissBrainBanner,
66140
+ setMcpServers,
66141
+ addMcpServer,
66142
+ updateMcpServerStatus,
66041
66143
  startThinking,
66042
66144
  stopThinking,
66043
66145
  addTokens,
66044
66146
  resetSessionStats,
66147
+ setContextMaxTokens,
66045
66148
  toggleTodos,
66046
66149
  toggleDebugLog,
66047
66150
  setInterruptPending,
@@ -66085,7 +66188,15 @@ var init_app = __esm(async () => {
66085
66188
  exitPending: false,
66086
66189
  isCompacting: false,
66087
66190
  streamingLog: createInitialStreamingState(),
66088
- suggestions: createInitialSuggestionState()
66191
+ suggestions: createInitialSuggestionState(),
66192
+ mcpServers: [],
66193
+ brain: {
66194
+ status: "disconnected",
66195
+ user: null,
66196
+ knowledgeCount: 0,
66197
+ memoryCount: 0,
66198
+ showBanner: true
66199
+ }
66089
66200
  };
66090
66201
  appStore = {
66091
66202
  getState: () => {
@@ -66115,7 +66226,9 @@ var init_app = __esm(async () => {
66115
66226
  exitPending: storeRef.exitPending(),
66116
66227
  isCompacting: storeRef.isCompacting(),
66117
66228
  streamingLog: storeRef.streamingLog(),
66118
- suggestions: storeRef.suggestions()
66229
+ suggestions: storeRef.suggestions(),
66230
+ mcpServers: storeRef.mcpServers(),
66231
+ brain: storeRef.brain()
66119
66232
  };
66120
66233
  },
66121
66234
  addLog: (entry) => {
@@ -66223,6 +66336,11 @@ var init_app = __esm(async () => {
66223
66336
  return;
66224
66337
  storeRef.resetSessionStats();
66225
66338
  },
66339
+ setContextMaxTokens: (maxTokens) => {
66340
+ if (!storeRef)
66341
+ return;
66342
+ storeRef.setContextMaxTokens(maxTokens);
66343
+ },
66226
66344
  toggleTodos: () => {
66227
66345
  if (!storeRef)
66228
66346
  return;
@@ -66292,6 +66410,46 @@ var init_app = __esm(async () => {
66292
66410
  if (!storeRef)
66293
66411
  return;
66294
66412
  storeRef.toggleCascadeEnabled();
66413
+ },
66414
+ setBrainStatus: (status) => {
66415
+ if (!storeRef)
66416
+ return;
66417
+ storeRef.setBrainStatus(status);
66418
+ },
66419
+ setBrainUser: (user) => {
66420
+ if (!storeRef)
66421
+ return;
66422
+ storeRef.setBrainUser(user);
66423
+ },
66424
+ setBrainCounts: (knowledge, memory) => {
66425
+ if (!storeRef)
66426
+ return;
66427
+ storeRef.setBrainCounts(knowledge, memory);
66428
+ },
66429
+ setBrainShowBanner: (show) => {
66430
+ if (!storeRef)
66431
+ return;
66432
+ storeRef.setBrainShowBanner(show);
66433
+ },
66434
+ dismissBrainBanner: () => {
66435
+ if (!storeRef)
66436
+ return;
66437
+ storeRef.dismissBrainBanner();
66438
+ },
66439
+ setMcpServers: (servers) => {
66440
+ if (!storeRef)
66441
+ return;
66442
+ storeRef.setMcpServers(servers);
66443
+ },
66444
+ addMcpServer: (server) => {
66445
+ if (!storeRef)
66446
+ return;
66447
+ storeRef.addMcpServer(server);
66448
+ },
66449
+ updateMcpServerStatus: (id, status) => {
66450
+ if (!storeRef)
66451
+ return;
66452
+ storeRef.updateMcpServerStatus(id, status);
66295
66453
  }
66296
66454
  };
66297
66455
  });
@@ -66380,76 +66538,74 @@ function DebugLogPanel() {
66380
66538
  return msg.substring(0, maxLen - 3) + "...";
66381
66539
  };
66382
66540
  return (() => {
66383
- var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$5 = createElement("text"), _el$6 = createTextNode(` (`), _el$7 = createTextNode(`)`), _el$8 = createElement("scrollbox"), _el$9 = createElement("box"), _el$0 = createElement("box"), _el$1 = createElement("text");
66541
+ var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$4 = createTextNode(`Debug Logs (`), _el$5 = createTextNode(`)`), _el$6 = createElement("scrollbox"), _el$7 = createElement("box"), _el$8 = createElement("box"), _el$9 = createElement("text");
66384
66542
  insertNode(_el$, _el$2);
66543
+ insertNode(_el$, _el$6);
66385
66544
  insertNode(_el$, _el$8);
66386
- insertNode(_el$, _el$0);
66387
66545
  setProp(_el$, "flexDirection", "column");
66388
66546
  setProp(_el$, "width", "20%");
66389
66547
  setProp(_el$, "border", ["top", "bottom", "left", "right"]);
66390
66548
  insertNode(_el$2, _el$3);
66391
- insertNode(_el$2, _el$5);
66392
66549
  setProp(_el$2, "paddingLeft", 1);
66393
66550
  setProp(_el$2, "paddingRight", 1);
66394
66551
  setProp(_el$2, "border", ["bottom"]);
66395
- insertNode(_el$3, createTextNode(`Debug Logs`));
66396
- insertNode(_el$5, _el$6);
66397
- insertNode(_el$5, _el$7);
66398
- insert(_el$5, () => entries2().length, _el$7);
66399
- insertNode(_el$8, _el$9);
66552
+ setProp(_el$2, "flexDirection", "row");
66553
+ insertNode(_el$3, _el$4);
66554
+ insertNode(_el$3, _el$5);
66555
+ insert(_el$3, () => entries2().length, _el$5);
66556
+ insertNode(_el$6, _el$7);
66400
66557
  var _ref$ = scrollboxRef;
66401
- typeof _ref$ === "function" ? use(_ref$, _el$8) : scrollboxRef = _el$8;
66402
- setProp(_el$8, "stickyStart", "bottom");
66403
- setProp(_el$8, "flexGrow", 1);
66404
- setProp(_el$8, "paddingLeft", 1);
66405
- setProp(_el$8, "paddingRight", 1);
66406
- setProp(_el$9, "flexDirection", "column");
66407
- insert(_el$9, createComponent2(For, {
66558
+ typeof _ref$ === "function" ? use(_ref$, _el$6) : scrollboxRef = _el$6;
66559
+ setProp(_el$6, "stickyStart", "bottom");
66560
+ setProp(_el$6, "flexGrow", 1);
66561
+ setProp(_el$6, "paddingLeft", 1);
66562
+ setProp(_el$6, "paddingRight", 1);
66563
+ setProp(_el$7, "flexDirection", "column");
66564
+ insert(_el$7, createComponent2(For, {
66408
66565
  get each() {
66409
66566
  return entries2();
66410
66567
  },
66411
66568
  children: (entry) => (() => {
66412
- var _el$11 = createElement("box"), _el$12 = createElement("text"), _el$13 = createTextNode(` `), _el$14 = createElement("text"), _el$15 = createTextNode(`[`), _el$16 = createTextNode(`] `), _el$18 = createElement("text");
66413
- insertNode(_el$11, _el$12);
66414
- insertNode(_el$11, _el$14);
66415
- insertNode(_el$11, _el$18);
66416
- setProp(_el$11, "flexDirection", "row");
66569
+ var _el$1 = createElement("box"), _el$10 = createElement("text"), _el$11 = createTextNode(` `), _el$12 = createElement("text"), _el$13 = createTextNode(`[`), _el$14 = createTextNode(`] `), _el$16 = createElement("text");
66570
+ insertNode(_el$1, _el$10);
66571
+ insertNode(_el$1, _el$12);
66572
+ insertNode(_el$1, _el$16);
66573
+ setProp(_el$1, "flexDirection", "row");
66574
+ insertNode(_el$10, _el$11);
66575
+ insert(_el$10, () => formatTime(entry.timestamp), _el$11);
66417
66576
  insertNode(_el$12, _el$13);
66418
- insert(_el$12, () => formatTime(entry.timestamp), _el$13);
66419
- insertNode(_el$14, _el$15);
66420
- insertNode(_el$14, _el$16);
66421
- insert(_el$14, () => getTypeLabel(entry.type), _el$16);
66422
- setProp(_el$18, "wrapMode", "word");
66423
- insert(_el$18, () => truncateMessage(entry.message, 50));
66577
+ insertNode(_el$12, _el$14);
66578
+ insert(_el$12, () => getTypeLabel(entry.type), _el$14);
66579
+ setProp(_el$16, "wrapMode", "word");
66580
+ insert(_el$16, () => truncateMessage(entry.message, 50));
66424
66581
  effect((_p$) => {
66425
- var _v$0 = theme.colors.textDim, _v$1 = getTypeColor(entry.type), _v$10 = theme.colors.text;
66426
- _v$0 !== _p$.e && (_p$.e = setProp(_el$12, "fg", _v$0, _p$.e));
66427
- _v$1 !== _p$.t && (_p$.t = setProp(_el$14, "fg", _v$1, _p$.t));
66428
- _v$10 !== _p$.a && (_p$.a = setProp(_el$18, "fg", _v$10, _p$.a));
66582
+ var _v$9 = theme.colors.textDim, _v$0 = getTypeColor(entry.type), _v$1 = theme.colors.text;
66583
+ _v$9 !== _p$.e && (_p$.e = setProp(_el$10, "fg", _v$9, _p$.e));
66584
+ _v$0 !== _p$.t && (_p$.t = setProp(_el$12, "fg", _v$0, _p$.t));
66585
+ _v$1 !== _p$.a && (_p$.a = setProp(_el$16, "fg", _v$1, _p$.a));
66429
66586
  return _p$;
66430
66587
  }, {
66431
66588
  e: undefined,
66432
66589
  t: undefined,
66433
66590
  a: undefined
66434
66591
  });
66435
- return _el$11;
66592
+ return _el$1;
66436
66593
  })()
66437
66594
  }));
66438
- insertNode(_el$0, _el$1);
66439
- setProp(_el$0, "paddingLeft", 1);
66440
- setProp(_el$0, "border", ["top"]);
66441
- insertNode(_el$1, createTextNode(`Shift+PgUp/PgDn scroll`));
66595
+ insertNode(_el$8, _el$9);
66596
+ setProp(_el$8, "paddingLeft", 1);
66597
+ setProp(_el$8, "border", ["top"]);
66598
+ insertNode(_el$9, createTextNode(`Shift+PgUp/PgDn scroll`));
66442
66599
  effect((_p$) => {
66443
- var _v$ = theme.colors.border, _v$2 = theme.colors.background, _v$3 = theme.colors.border, _v$4 = theme.colors.accent, _v$5 = TextAttributes.BOLD, _v$6 = theme.colors.textDim, _v$7 = stickyEnabled(), _v$8 = theme.colors.border, _v$9 = theme.colors.textDim;
66600
+ var _v$ = theme.colors.border, _v$2 = theme.colors.background, _v$3 = theme.colors.border, _v$4 = theme.colors.accent, _v$5 = TextAttributes.BOLD, _v$6 = stickyEnabled(), _v$7 = theme.colors.border, _v$8 = theme.colors.textDim;
66444
66601
  _v$ !== _p$.e && (_p$.e = setProp(_el$, "borderColor", _v$, _p$.e));
66445
66602
  _v$2 !== _p$.t && (_p$.t = setProp(_el$, "backgroundColor", _v$2, _p$.t));
66446
66603
  _v$3 !== _p$.a && (_p$.a = setProp(_el$2, "borderColor", _v$3, _p$.a));
66447
66604
  _v$4 !== _p$.o && (_p$.o = setProp(_el$3, "fg", _v$4, _p$.o));
66448
66605
  _v$5 !== _p$.i && (_p$.i = setProp(_el$3, "attributes", _v$5, _p$.i));
66449
- _v$6 !== _p$.n && (_p$.n = setProp(_el$5, "fg", _v$6, _p$.n));
66450
- _v$7 !== _p$.s && (_p$.s = setProp(_el$8, "stickyScroll", _v$7, _p$.s));
66451
- _v$8 !== _p$.h && (_p$.h = setProp(_el$0, "borderColor", _v$8, _p$.h));
66452
- _v$9 !== _p$.r && (_p$.r = setProp(_el$1, "fg", _v$9, _p$.r));
66606
+ _v$6 !== _p$.n && (_p$.n = setProp(_el$6, "stickyScroll", _v$6, _p$.n));
66607
+ _v$7 !== _p$.s && (_p$.s = setProp(_el$8, "borderColor", _v$7, _p$.s));
66608
+ _v$8 !== _p$.h && (_p$.h = setProp(_el$9, "fg", _v$8, _p$.h));
66453
66609
  return _p$;
66454
66610
  }, {
66455
66611
  e: undefined,
@@ -66459,8 +66615,7 @@ function DebugLogPanel() {
66459
66615
  i: undefined,
66460
66616
  n: undefined,
66461
66617
  s: undefined,
66462
- h: undefined,
66463
- r: undefined
66618
+ h: undefined
66464
66619
  });
66465
66620
  return _el$;
66466
66621
  })();
@@ -66618,6 +66773,7 @@ var formatMessages = (messages) => messages.map((msg) => {
66618
66773
  if (delta?.tool_calls) {
66619
66774
  for (const tc of delta.tool_calls) {
66620
66775
  addDebugLog("api", `Tool call chunk: ${JSON.stringify(tc)}`);
66776
+ console.log("Debug: Tool call chunk received:", JSON.stringify(tc));
66621
66777
  onChunk({ type: "tool_call", toolCall: tc });
66622
66778
  }
66623
66779
  }
@@ -66935,10 +67091,22 @@ var init_models2 = __esm(() => {
66935
67091
  });
66936
67092
 
66937
67093
  // src/providers/ollama/chat.ts
66938
- var formatMessages2 = (messages) => messages.map((msg) => ({
66939
- role: msg.role,
66940
- content: msg.content
66941
- })), formatTools = (tools) => {
67094
+ var formatMessages2 = (messages) => messages.map((msg) => {
67095
+ const formatted = {
67096
+ role: msg.role,
67097
+ content: msg.content
67098
+ };
67099
+ if (msg.tool_calls && msg.tool_calls.length > 0) {
67100
+ formatted.tool_calls = msg.tool_calls.map((tc) => ({
67101
+ id: tc.id,
67102
+ function: {
67103
+ name: tc.function.name,
67104
+ arguments: typeof tc.function.arguments === "string" ? JSON.parse(tc.function.arguments) : tc.function.arguments
67105
+ }
67106
+ }));
67107
+ }
67108
+ return formatted;
67109
+ }), formatTools = (tools) => {
66942
67110
  if (!tools || tools.length === 0)
66943
67111
  return;
66944
67112
  return tools.map((tool) => ({
@@ -67235,7 +67403,7 @@ Available models:`,
67235
67403
  });
67236
67404
 
67237
67405
  // src/providers/credentials.ts
67238
- import { readFile as readFile2, writeFile, mkdir } from "fs/promises";
67406
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
67239
67407
  import { existsSync as existsSync3 } from "fs";
67240
67408
  var loadCredentials = async () => {
67241
67409
  if (!existsSync3(FILES.credentials)) {
@@ -67248,8 +67416,8 @@ var loadCredentials = async () => {
67248
67416
  return {};
67249
67417
  }
67250
67418
  }, saveCredentials = async (credentials) => {
67251
- await mkdir(DIRS.data, { recursive: true });
67252
- await writeFile(FILES.credentials, JSON.stringify(credentials, null, 2), {
67419
+ await mkdir2(DIRS.data, { recursive: true });
67420
+ await writeFile2(FILES.credentials, JSON.stringify(credentials, null, 2), {
67253
67421
  mode: CREDENTIALS_FILE_MODE
67254
67422
  });
67255
67423
  };
@@ -73304,12 +73472,11 @@ class MCPClient {
73304
73472
  var init_client = () => {};
73305
73473
 
73306
73474
  // src/services/mcp/manager.ts
73307
- import fs12 from "fs/promises";
73308
- import path12 from "path";
73309
- import os6 from "os";
73475
+ import fs15 from "fs/promises";
73476
+ import path13 from "path";
73310
73477
  var CONFIG_LOCATIONS, state3, loadConfigFile = async (filePath2) => {
73311
73478
  try {
73312
- const content = await fs12.readFile(filePath2, "utf-8");
73479
+ const content = await fs15.readFile(filePath2, "utf-8");
73313
73480
  return JSON.parse(content);
73314
73481
  } catch {
73315
73482
  return null;
@@ -73326,9 +73493,9 @@ var CONFIG_LOCATIONS, state3, loadConfigFile = async (filePath2) => {
73326
73493
  return merged;
73327
73494
  }, saveMCPConfig = async (config2, global3 = false) => {
73328
73495
  const filePath2 = global3 ? CONFIG_LOCATIONS.global : CONFIG_LOCATIONS.local;
73329
- const dir = path12.dirname(filePath2);
73330
- await fs12.mkdir(dir, { recursive: true });
73331
- await fs12.writeFile(filePath2, JSON.stringify(config2, null, 2), "utf-8");
73496
+ const dir = path13.dirname(filePath2);
73497
+ await fs15.mkdir(dir, { recursive: true });
73498
+ await fs15.writeFile(filePath2, JSON.stringify(config2, null, 2), "utf-8");
73332
73499
  }, initializeMCP = async () => {
73333
73500
  if (state3.initialized)
73334
73501
  return;
@@ -73440,9 +73607,10 @@ var CONFIG_LOCATIONS, state3, loadConfigFile = async (filePath2) => {
73440
73607
  };
73441
73608
  var init_manager = __esm(() => {
73442
73609
  init_client();
73610
+ init_paths();
73443
73611
  CONFIG_LOCATIONS = {
73444
- global: path12.join(os6.homedir(), ".codetyper", "mcp.json"),
73445
- local: path12.join(process.cwd(), ".codetyper", "mcp.json")
73612
+ global: path13.join(DIRS.config, "mcp.json"),
73613
+ local: path13.join(process.cwd(), LOCAL_CONFIG_DIR, "mcp.json")
73446
73614
  };
73447
73615
  state3 = {
73448
73616
  clients: new Map,
@@ -73586,12 +73754,12 @@ var createEmptyIndex = (model) => ({
73586
73754
  });
73587
73755
 
73588
73756
  // src/services/learning/vector-store.ts
73589
- import * as fs13 from "fs/promises";
73590
- import * as path13 from "path";
73591
- var getIndexPath = (baseDir) => path13.join(baseDir, EMBEDDING_STORAGE.INDEX_FILE), loadIndex = async (baseDir, model) => {
73757
+ import * as fs16 from "fs/promises";
73758
+ import * as path14 from "path";
73759
+ var getIndexPath = (baseDir) => path14.join(baseDir, EMBEDDING_STORAGE.INDEX_FILE), loadIndex = async (baseDir, model) => {
73592
73760
  const indexPath = getIndexPath(baseDir);
73593
73761
  try {
73594
- const data = await fs13.readFile(indexPath, "utf-8");
73762
+ const data = await fs16.readFile(indexPath, "utf-8");
73595
73763
  const index = JSON.parse(data);
73596
73764
  if (index.version !== EMBEDDING_STORAGE.VERSION || index.model !== model) {
73597
73765
  return createEmptyIndex(model);
@@ -73602,8 +73770,8 @@ var getIndexPath = (baseDir) => path13.join(baseDir, EMBEDDING_STORAGE.INDEX_FIL
73602
73770
  }
73603
73771
  }, saveIndex = async (baseDir, index) => {
73604
73772
  const indexPath = getIndexPath(baseDir);
73605
- await fs13.mkdir(baseDir, { recursive: true });
73606
- await fs13.writeFile(indexPath, JSON.stringify(index, null, 2), "utf-8");
73773
+ await fs16.mkdir(baseDir, { recursive: true });
73774
+ await fs16.writeFile(indexPath, JSON.stringify(index, null, 2), "utf-8");
73607
73775
  }, upsertEmbedding = (index, id, embedding) => {
73608
73776
  const stored = {
73609
73777
  id,
@@ -73625,8 +73793,8 @@ var init_vector_store = __esm(() => {
73625
73793
  });
73626
73794
 
73627
73795
  // src/services/learning/semantic-search.ts
73628
- import * as path14 from "path";
73629
- var globalIndex = null, localIndex = null, getGlobalIndexDir = () => path14.join(getGlobalConfigDir(), "learnings"), getLocalIndexDir = () => path14.join(getLocalConfigDir(), "learnings"), getGlobalIndex = async () => {
73796
+ import * as path15 from "path";
73797
+ var globalIndex = null, localIndex = null, getGlobalIndexDir = () => path15.join(getGlobalConfigDir(), "learnings"), getLocalIndexDir = () => path15.join(getLocalConfigDir(), "learnings"), getGlobalIndex = async () => {
73630
73798
  if (!isEmbeddingAvailable()) {
73631
73799
  return null;
73632
73800
  }
@@ -73692,7 +73860,7 @@ var init_semantic_search = __esm(() => {
73692
73860
  var version_default;
73693
73861
  var init_version = __esm(() => {
73694
73862
  version_default = {
73695
- version: "0.2.2"
73863
+ version: "0.2.4"
73696
73864
  };
73697
73865
  });
73698
73866
 
@@ -74022,9 +74190,9 @@ var init_mcp_registry = __esm(() => {
74022
74190
 
74023
74191
  // src/services/mcp/registry.ts
74024
74192
  import { homedir as homedir4 } from "os";
74025
- import { join as join13 } from "path";
74193
+ import { join as join14 } from "path";
74026
74194
  var registryCache = null, getCacheFilePath = () => {
74027
- return join13(homedir4(), ".codetyper", MCP_REGISTRY_CACHE.FILE_NAME);
74195
+ return join14(homedir4(), ".codetyper", MCP_REGISTRY_CACHE.FILE_NAME);
74028
74196
  }, loadCache = async () => {
74029
74197
  try {
74030
74198
  const cachePath = getCacheFilePath();
@@ -74181,7 +74349,7 @@ var registryCache = null, getCacheFilePath = () => {
74181
74349
  const instances = getServerInstances();
74182
74350
  return instances.some((instance) => instance.config.name === serverId || instance.config.name.toLowerCase() === serverId.toLowerCase());
74183
74351
  }, installServer = async (server, options2 = {}) => {
74184
- const { global: global3 = false, connect = true, customArgs } = options2;
74352
+ const { global: global3 = false, connect: connect2 = true, customArgs } = options2;
74185
74353
  if (isServerInstalled(server.id)) {
74186
74354
  return {
74187
74355
  success: false,
@@ -74199,7 +74367,7 @@ var registryCache = null, getCacheFilePath = () => {
74199
74367
  enabled: true
74200
74368
  }, global3);
74201
74369
  let connected = false;
74202
- if (connect) {
74370
+ if (connect2) {
74203
74371
  try {
74204
74372
  await connectServer(server.id);
74205
74373
  connected = true;
@@ -74858,15 +75026,27 @@ var PROVIDER_ENV_VARS = {
74858
75026
  ollama: "OLLAMA_HOST"
74859
75027
  };
74860
75028
  var configState = getDefaults();
75029
+ var configLoaded = false;
75030
+ var configLoadPromise = null;
74861
75031
  var loadConfig = async () => {
74862
- try {
74863
- const data = await fs2.readFile(FILES.config, "utf-8");
74864
- const loaded = JSON.parse(data);
74865
- delete loaded.models;
74866
- configState = { ...getDefaults(), ...loaded };
74867
- } catch {
74868
- configState = getDefaults();
75032
+ if (configLoaded) {
75033
+ return;
75034
+ }
75035
+ if (configLoadPromise) {
75036
+ return configLoadPromise;
74869
75037
  }
75038
+ configLoadPromise = (async () => {
75039
+ try {
75040
+ const data = await fs2.readFile(FILES.config, "utf-8");
75041
+ const loaded = JSON.parse(data);
75042
+ delete loaded.models;
75043
+ configState = { ...getDefaults(), ...loaded };
75044
+ } catch {
75045
+ configState = getDefaults();
75046
+ }
75047
+ configLoaded = true;
75048
+ })();
75049
+ return configLoadPromise;
74870
75050
  };
74871
75051
  var saveConfig = async () => {
74872
75052
  try {
@@ -76462,7 +76642,7 @@ Read-only tools only:
76462
76642
 
76463
76643
  - You are in READ-ONLY mode - you cannot modify files
76464
76644
  - Always search before answering questions about the codebase
76465
- - If asked to make changes, explain that you're in Ask mode and suggest switching to Agent mode (Ctrl+Tab)
76645
+ - If asked to make changes, explain that you're in Ask mode and suggest switching to Agent mode (Ctrl+M)
76466
76646
  - For general programming questions, you can answer without searching`;
76467
76647
  var buildAskPrompt = (context) => {
76468
76648
  const envSection = `
@@ -79066,15 +79246,36 @@ var MODE_PROMPT_BUILDERS = {
79066
79246
  prContext: ctx.prContext
79067
79247
  })
79068
79248
  };
79249
+ var execGitCommand = (args) => {
79250
+ return new Promise((resolve4, reject) => {
79251
+ const { spawn: spawn2 } = __require("child_process");
79252
+ const proc = spawn2("git", args, { cwd: process.cwd() });
79253
+ let stdout = "";
79254
+ let stderr = "";
79255
+ proc.stdout.on("data", (data) => {
79256
+ stdout += data.toString();
79257
+ });
79258
+ proc.stderr.on("data", (data) => {
79259
+ stderr += data.toString();
79260
+ });
79261
+ proc.on("close", (code) => {
79262
+ if (code === 0) {
79263
+ resolve4(stdout.trim());
79264
+ } else {
79265
+ reject(new Error(stderr || `git exited with code ${code}`));
79266
+ }
79267
+ });
79268
+ proc.on("error", reject);
79269
+ });
79270
+ };
79069
79271
  var getGitContext = async () => {
79070
79272
  try {
79071
- const { execSync } = await import("child_process");
79072
- const branch = execSync("git branch --show-current", {
79073
- encoding: "utf-8"
79074
- }).trim();
79075
- const status2 = execSync("git status --short", { encoding: "utf-8" }).trim() || "(clean)";
79076
- const commits = execSync("git log --oneline -5", { encoding: "utf-8" }).trim().split(`
79077
- `).filter(Boolean);
79273
+ const [branch, status2, commits] = await Promise.all([
79274
+ execGitCommand(["branch", "--show-current"]),
79275
+ execGitCommand(["status", "--short"]).then((s) => s || "(clean)"),
79276
+ execGitCommand(["log", "--oneline", "-5"]).then((s) => s.split(`
79277
+ `).filter(Boolean))
79278
+ ]);
79078
79279
  return { isGitRepo: true, branch, status: status2, recentCommits: commits };
79079
79280
  } catch {
79080
79281
  return { isGitRepo: false };
@@ -79484,6 +79685,266 @@ var initSuggestionService = (cwd) => {
79484
79685
  clearSuggestions();
79485
79686
  };
79486
79687
 
79688
+ // src/services/brain.ts
79689
+ init_paths();
79690
+ import fs6 from "fs/promises";
79691
+
79692
+ // src/constants/brain.ts
79693
+ var BRAIN_DISABLED = true;
79694
+ var BRAIN_DEFAULTS = {
79695
+ BASE_URL: "http://localhost:5001",
79696
+ PROJECT_ID: 1
79697
+ };
79698
+ var BRAIN_ENDPOINTS = {
79699
+ HEALTH: "/",
79700
+ AUTH_REGISTER: "/auth/register",
79701
+ AUTH_LOGIN: "/auth/login",
79702
+ AUTH_LOGOUT: "/auth/logout",
79703
+ AUTH_REFRESH: "/auth/refresh",
79704
+ AUTH_ME: "/auth/me",
79705
+ KNOWLEDGE_LEARN: "/api/knowledge/learn",
79706
+ KNOWLEDGE_RECALL: "/api/knowledge/recall",
79707
+ KNOWLEDGE_RELATE: "/api/knowledge/relate",
79708
+ KNOWLEDGE_EXTRACT: "/api/knowledge/extract",
79709
+ KNOWLEDGE_CONTEXT: "/api/knowledge/context",
79710
+ KNOWLEDGE_CONCEPTS: "/api/knowledge/concepts",
79711
+ KNOWLEDGE_STATS: "/api/knowledge/stats",
79712
+ MEMORY_STATUS: "/api/memory/status",
79713
+ MEMORY_STATS: "/api/memory/stats",
79714
+ MEMORY_SEARCH: "/api/memory/search",
79715
+ MEMORY_STORE: "/api/memory/store",
79716
+ MEMORY_TOP: "/api/memory/top",
79717
+ MEMORY_FEEDBACK: "/api/memory/feedback",
79718
+ GRAPHQL: "/graphql"
79719
+ };
79720
+ var BRAIN_TIMEOUTS = {
79721
+ HEALTH: 3000,
79722
+ AUTH: 1e4,
79723
+ KNOWLEDGE: 15000,
79724
+ MEMORY: 1e4,
79725
+ EXTRACT: 30000
79726
+ };
79727
+ var BRAIN_ERRORS = {
79728
+ NOT_RUNNING: "Brain service not available. Start the API server at localhost:5001",
79729
+ NOT_AUTHENTICATED: "Not authenticated. Please login or set an API key.",
79730
+ INVALID_API_KEY: "Invalid API key. Please check your credentials.",
79731
+ CONNECTION_FAILED: "Failed to connect to Brain service.",
79732
+ RECALL_FAILED: "Failed to recall knowledge from Brain.",
79733
+ LEARN_FAILED: "Failed to store knowledge in Brain.",
79734
+ EXTRACT_FAILED: "Failed to extract concepts from content."
79735
+ };
79736
+ var BRAIN_BANNER = {
79737
+ TITLE: "CodeTyper has a Brain!",
79738
+ CTA: "Login and get an API key to enable long-term memory",
79739
+ URL: "http://localhost:5001",
79740
+ LOGIN_URL: "http://localhost:5173/docs/login",
79741
+ EMOJI_CONNECTED: "\uD83E\uDDE0",
79742
+ EMOJI_DISCONNECTED: "\uD83D\uDCA4"
79743
+ };
79744
+ var BRAIN_HEADERS = {
79745
+ API_KEY: "api-key",
79746
+ AUTHORIZATION: "Authorization",
79747
+ CONTENT_TYPE: "Content-Type"
79748
+ };
79749
+
79750
+ // src/api/brain/index.ts
79751
+ init_source4();
79752
+ var buildHeaders2 = (apiKey, accessToken) => ({
79753
+ [BRAIN_HEADERS.CONTENT_TYPE]: "application/json",
79754
+ ...apiKey ? { [BRAIN_HEADERS.API_KEY]: apiKey } : {},
79755
+ ...accessToken ? { [BRAIN_HEADERS.AUTHORIZATION]: `Bearer ${accessToken}` } : {}
79756
+ });
79757
+ var getBaseUrl = (customUrl) => {
79758
+ return customUrl ?? BRAIN_DEFAULTS.BASE_URL;
79759
+ };
79760
+ var checkHealth = async (baseUrl) => {
79761
+ const url = `${getBaseUrl(baseUrl)}${BRAIN_ENDPOINTS.HEALTH}`;
79762
+ const response2 = await source_default2.get(url, {
79763
+ timeout: { request: BRAIN_TIMEOUTS.HEALTH }
79764
+ }).json();
79765
+ return response2;
79766
+ };
79767
+ var logout2 = async (refreshToken2, baseUrl) => {
79768
+ const url = `${getBaseUrl(baseUrl)}${BRAIN_ENDPOINTS.AUTH_LOGOUT}`;
79769
+ await source_default2.post(url, {
79770
+ json: { refresh_token: refreshToken2 },
79771
+ timeout: { request: BRAIN_TIMEOUTS.AUTH }
79772
+ });
79773
+ };
79774
+ var getKnowledgeStats = async (projectId, apiKey, baseUrl) => {
79775
+ const url = `${getBaseUrl(baseUrl)}${BRAIN_ENDPOINTS.KNOWLEDGE_STATS}?project_id=${projectId}`;
79776
+ const response2 = await source_default2.get(url, {
79777
+ ...{ headers: buildHeaders2(apiKey) },
79778
+ timeout: { request: BRAIN_TIMEOUTS.KNOWLEDGE }
79779
+ }).json();
79780
+ return response2;
79781
+ };
79782
+ var getMemoryStats = async (apiKey, baseUrl) => {
79783
+ const url = `${getBaseUrl(baseUrl)}${BRAIN_ENDPOINTS.MEMORY_STATS}`;
79784
+ const response2 = await source_default2.get(url, {
79785
+ ...{ headers: buildHeaders2(apiKey) },
79786
+ timeout: { request: BRAIN_TIMEOUTS.MEMORY }
79787
+ }).json();
79788
+ return response2;
79789
+ };
79790
+
79791
+ // src/services/brain.ts
79792
+ var brainState = {
79793
+ status: "disconnected",
79794
+ user: null,
79795
+ projectId: BRAIN_DEFAULTS.PROJECT_ID,
79796
+ knowledgeCount: 0,
79797
+ memoryCount: 0,
79798
+ lastError: null
79799
+ };
79800
+ var cachedCredentials = null;
79801
+ var cachedVars = null;
79802
+ var loadVarsFile = async () => {
79803
+ if (cachedVars) {
79804
+ return cachedVars;
79805
+ }
79806
+ try {
79807
+ const data = await fs6.readFile(FILES.vars, "utf-8");
79808
+ cachedVars = JSON.parse(data);
79809
+ return cachedVars;
79810
+ } catch {
79811
+ return {};
79812
+ }
79813
+ };
79814
+ var saveVarsFile = async (vars) => {
79815
+ try {
79816
+ await fs6.mkdir(DIRS.config, { recursive: true });
79817
+ await fs6.writeFile(FILES.vars, JSON.stringify(vars, null, 2), "utf-8");
79818
+ cachedVars = vars;
79819
+ } catch (error2) {
79820
+ throw new Error(`Failed to save vars file: ${error2}`);
79821
+ }
79822
+ };
79823
+ var getCredentialsPath = () => {
79824
+ return `${DIRS.data}/brain-credentials.json`;
79825
+ };
79826
+ var loadCredentials2 = async () => {
79827
+ if (cachedCredentials) {
79828
+ return cachedCredentials;
79829
+ }
79830
+ try {
79831
+ const data = await fs6.readFile(getCredentialsPath(), "utf-8");
79832
+ cachedCredentials = JSON.parse(data);
79833
+ return cachedCredentials;
79834
+ } catch {
79835
+ return null;
79836
+ }
79837
+ };
79838
+ var clearCredentials2 = async () => {
79839
+ try {
79840
+ await fs6.unlink(getCredentialsPath());
79841
+ cachedCredentials = null;
79842
+ } catch {}
79843
+ try {
79844
+ const vars = await loadVarsFile();
79845
+ await saveVarsFile({
79846
+ ...vars,
79847
+ brainApiKey: undefined,
79848
+ brainJwtToken: undefined
79849
+ });
79850
+ } catch {}
79851
+ };
79852
+ var getApiKey2 = async () => {
79853
+ const envKey = process.env.CODETYPER_BRAIN_API_KEY;
79854
+ if (envKey) {
79855
+ return envKey;
79856
+ }
79857
+ const vars = await loadVarsFile();
79858
+ return vars.brainApiKey;
79859
+ };
79860
+ var getJwtToken = async () => {
79861
+ const vars = await loadVarsFile();
79862
+ return vars.brainJwtToken;
79863
+ };
79864
+ var setApiKey = async (apiKey) => {
79865
+ const vars = await loadVarsFile();
79866
+ await saveVarsFile({ ...vars, brainApiKey: apiKey });
79867
+ };
79868
+ var setJwtToken = async (jwtToken) => {
79869
+ const vars = await loadVarsFile();
79870
+ await saveVarsFile({ ...vars, brainJwtToken: jwtToken });
79871
+ };
79872
+ var logout3 = async () => {
79873
+ try {
79874
+ const credentials = await loadCredentials2();
79875
+ if (credentials?.refreshToken) {
79876
+ await logout2(credentials.refreshToken);
79877
+ }
79878
+ } catch {} finally {
79879
+ await clearCredentials2();
79880
+ updateState({
79881
+ status: "disconnected",
79882
+ user: null,
79883
+ knowledgeCount: 0,
79884
+ memoryCount: 0
79885
+ });
79886
+ }
79887
+ };
79888
+ var getAuthToken = async () => {
79889
+ const apiKey = await getApiKey2();
79890
+ if (apiKey) {
79891
+ return apiKey;
79892
+ }
79893
+ return getJwtToken();
79894
+ };
79895
+ var connect = async () => {
79896
+ if (BRAIN_DISABLED) {
79897
+ return false;
79898
+ }
79899
+ try {
79900
+ updateState({ status: "connecting" });
79901
+ await checkHealth();
79902
+ const authToken = await getAuthToken();
79903
+ if (!authToken) {
79904
+ updateState({ status: "disconnected", lastError: null });
79905
+ return false;
79906
+ }
79907
+ const projectId = brainState.projectId ?? BRAIN_DEFAULTS.PROJECT_ID;
79908
+ const statsResponse = await getKnowledgeStats(projectId, authToken);
79909
+ if (statsResponse.success && statsResponse.data) {
79910
+ updateState({
79911
+ status: "connected",
79912
+ knowledgeCount: statsResponse.data.total_concepts,
79913
+ lastError: null
79914
+ });
79915
+ try {
79916
+ const memoryStats = await getMemoryStats(authToken);
79917
+ updateState({ memoryCount: memoryStats.totalNodes });
79918
+ } catch {}
79919
+ return true;
79920
+ }
79921
+ updateState({ status: "error", lastError: BRAIN_ERRORS.INVALID_API_KEY });
79922
+ return false;
79923
+ } catch (error2) {
79924
+ const errorMessage2 = error2 instanceof Error ? error2.message : BRAIN_ERRORS.CONNECTION_FAILED;
79925
+ updateState({ status: "error", lastError: errorMessage2 });
79926
+ return false;
79927
+ }
79928
+ };
79929
+ var getState2 = () => {
79930
+ return { ...brainState };
79931
+ };
79932
+ var updateState = (updates) => {
79933
+ brainState = { ...brainState, ...updates };
79934
+ };
79935
+ var isAuthenticated = async () => {
79936
+ const apiKey = await getApiKey2();
79937
+ const jwtToken = await getJwtToken();
79938
+ return apiKey !== undefined || jwtToken !== undefined;
79939
+ };
79940
+ var initialize = async () => {
79941
+ const hasAuth = await isAuthenticated();
79942
+ if (hasAuth) {
79943
+ return connect();
79944
+ }
79945
+ return false;
79946
+ };
79947
+
79487
79948
  // src/services/chat-tui/files.ts
79488
79949
  var import_fast_glob2 = __toESM(require_out4(), 1);
79489
79950
  import { readFile as readFile5, stat as stat2 } from "fs/promises";
@@ -79543,7 +80004,7 @@ var AUTH_MESSAGES = {
79543
80004
  2. Enter code: ${code}
79544
80005
 
79545
80006
  Waiting for authentication...`,
79546
- LOGGED_IN_AS: (login, name) => `Logged in as: ${login}${name ? ` (${name})` : ""}`
80007
+ LOGGED_IN_AS: (login2, name) => `Logged in as: ${login2}${name ? ` (${name})` : ""}`
79547
80008
  };
79548
80009
  var MODEL_MESSAGES = {
79549
80010
  MODEL_AUTO: "Model set to auto - the provider will choose the best model.",
@@ -79772,6 +80233,30 @@ var initializeTheme = async () => {
79772
80233
  themeActions.setTheme(savedTheme);
79773
80234
  }
79774
80235
  };
80236
+ var initializeBrain = async () => {
80237
+ if (BRAIN_DISABLED) {
80238
+ appStore.setBrainStatus("disconnected");
80239
+ appStore.setBrainShowBanner(false);
80240
+ return;
80241
+ }
80242
+ try {
80243
+ appStore.setBrainStatus("connecting");
80244
+ const connected = await initialize();
80245
+ if (connected) {
80246
+ const state2 = getState2();
80247
+ appStore.setBrainStatus("connected");
80248
+ appStore.setBrainUser(state2.user);
80249
+ appStore.setBrainCounts(state2.knowledgeCount, state2.memoryCount);
80250
+ appStore.setBrainShowBanner(false);
80251
+ } else {
80252
+ appStore.setBrainStatus("disconnected");
80253
+ appStore.setBrainShowBanner(true);
80254
+ }
80255
+ } catch {
80256
+ appStore.setBrainStatus("disconnected");
80257
+ appStore.setBrainShowBanner(true);
80258
+ }
80259
+ };
79775
80260
  var rebuildSystemPromptForMode = async (state2, newMode, appendPrompt) => {
79776
80261
  if (state2.currentMode === newMode) {
79777
80262
  return;
@@ -79787,16 +80272,21 @@ var rebuildSystemPromptForMode = async (state2, newMode, appendPrompt) => {
79787
80272
  var initializeChatService = async (options2) => {
79788
80273
  const initialMode = appStore.getState().interactionMode;
79789
80274
  const state2 = await createInitialState4(options2, initialMode);
79790
- await validateProvider(state2);
79791
- await buildSystemPrompt(state2, options2);
79792
- await initializeTheme();
80275
+ await Promise.all([
80276
+ validateProvider(state2),
80277
+ buildSystemPrompt(state2, options2),
80278
+ initializeTheme()
80279
+ ]);
79793
80280
  const session = await initializeSession(state2, options2);
79794
80281
  if (state2.messages.length === 0) {
79795
80282
  state2.messages.push({ role: "system", content: state2.systemPrompt });
79796
80283
  }
79797
- await addInitialContextFiles(state2, options2.files);
79798
- await initializePermissions();
80284
+ await Promise.all([
80285
+ addInitialContextFiles(state2, options2.files),
80286
+ initializePermissions()
80287
+ ]);
79799
80288
  initSuggestionService(process.cwd());
80289
+ initializeBrain().catch(() => {});
79800
80290
  return { state: state2, session };
79801
80291
  };
79802
80292
  // node_modules/uuid/dist-node/stringify.js
@@ -93666,7 +94156,7 @@ var processLines = (lines, offset, limit) => {
93666
94156
  };
93667
94157
  };
93668
94158
  // src/tools/read/execute.ts
93669
- import fs6 from "fs/promises";
94159
+ import fs7 from "fs/promises";
93670
94160
  import path7 from "path";
93671
94161
  var createDeniedResult2 = (filePath2) => ({
93672
94162
  success: false,
@@ -93711,8 +94201,8 @@ var checkPermission2 = async (fullPath, autoApprove) => {
93711
94201
  const { allowed } = await promptFilePermission("Read", fullPath);
93712
94202
  return allowed;
93713
94203
  };
93714
- var readDirectory = async (fullPath) => fs6.readdir(fullPath);
93715
- var readFileContent = async (fullPath) => fs6.readFile(fullPath, "utf-8");
94204
+ var readDirectory = async (fullPath) => fs7.readdir(fullPath);
94205
+ var readFileContent = async (fullPath) => fs7.readFile(fullPath, "utf-8");
93716
94206
  var executeRead = async (args, ctx) => {
93717
94207
  const { filePath: filePath2, offset = 0, limit = READ_DEFAULTS.MAX_LINES } = args;
93718
94208
  const fullPath = resolvePath(filePath2, ctx.workingDir);
@@ -93724,7 +94214,7 @@ var executeRead = async (args, ctx) => {
93724
94214
  status: "running"
93725
94215
  });
93726
94216
  try {
93727
- const stat3 = await fs6.stat(fullPath);
94217
+ const stat3 = await fs7.stat(fullPath);
93728
94218
  if (stat3.isDirectory()) {
93729
94219
  const files = await readDirectory(fullPath);
93730
94220
  return createDirectoryResult(filePath2, files);
@@ -93751,7 +94241,7 @@ var writeParams = exports_external.object({
93751
94241
  content: exports_external.string().describe("The content to write to the file")
93752
94242
  });
93753
94243
  // src/tools/write/execute.ts
93754
- import fs7 from "fs/promises";
94244
+ import fs8 from "fs/promises";
93755
94245
  import path8 from "path";
93756
94246
 
93757
94247
  // src/constants/write.ts
@@ -94090,7 +94580,7 @@ var resolvePaths = (filePath2, workingDir3) => {
94090
94580
  };
94091
94581
  var readExistingContent = async (fullPath) => {
94092
94582
  try {
94093
- const content = await fs7.readFile(fullPath, "utf-8");
94583
+ const content = await fs8.readFile(fullPath, "utf-8");
94094
94584
  return { exists: true, content };
94095
94585
  } catch {
94096
94586
  return { exists: false, content: "" };
@@ -94106,10 +94596,10 @@ var checkPermission3 = async (fullPath, relativePath, exists, autoApprove) => {
94106
94596
  return allowed;
94107
94597
  };
94108
94598
  var ensureDirectory = async (fullPath) => {
94109
- await fs7.mkdir(path8.dirname(fullPath), { recursive: true });
94599
+ await fs8.mkdir(path8.dirname(fullPath), { recursive: true });
94110
94600
  };
94111
94601
  var writeContent = async (fullPath, content) => {
94112
- await fs7.writeFile(fullPath, content, "utf-8");
94602
+ await fs8.writeFile(fullPath, content, "utf-8");
94113
94603
  };
94114
94604
  var executeWrite = async (args, ctx) => {
94115
94605
  const { filePath: filePath2, content } = args;
@@ -94193,7 +94683,7 @@ var validateUniqueness = (content, oldString, replaceAll, relativePath) => {
94193
94683
  };
94194
94684
  var countOccurrences = (content, search) => content.split(search).length - 1;
94195
94685
  // src/tools/edit/execute.ts
94196
- import fs8 from "fs/promises";
94686
+ import fs9 from "fs/promises";
94197
94687
  import path9 from "path";
94198
94688
  var createDeniedResult4 = (relativePath) => ({
94199
94689
  success: false,
@@ -94235,7 +94725,7 @@ var executeEdit = async (args, ctx) => {
94235
94725
  const { filePath: filePath2, oldString, newString, replaceAll = false } = args;
94236
94726
  const { fullPath, relativePath } = resolvePath2(filePath2, ctx.workingDir);
94237
94727
  try {
94238
- const content = await fs8.readFile(fullPath, "utf-8");
94728
+ const content = await fs9.readFile(fullPath, "utf-8");
94239
94729
  const existsError = validateTextExists(content, oldString, relativePath);
94240
94730
  if (existsError)
94241
94731
  return existsError;
@@ -94252,7 +94742,7 @@ var executeEdit = async (args, ctx) => {
94252
94742
  const newContent = applyEdit(content, oldString, newString, replaceAll);
94253
94743
  const diff = generateDiff(content, newContent);
94254
94744
  const diffOutput = formatDiff(diff, relativePath);
94255
- await fs8.writeFile(fullPath, newContent, "utf-8");
94745
+ await fs9.writeFile(fullPath, newContent, "utf-8");
94256
94746
  const replacements2 = replaceAll ? countOccurrences(content, oldString) : 1;
94257
94747
  return createSuccessResult2(relativePath, fullPath, diffOutput, replacements2, diff.additions, diff.deletions);
94258
94748
  } catch (error49) {
@@ -94818,50 +95308,6 @@ ${formattedResults}`,
94818
95308
  }
94819
95309
  };
94820
95310
  };
94821
- var parseSearchResults = (html, maxResults) => {
94822
- const results = [];
94823
- const resultPattern = /<a[^>]+class="result-link"[^>]*href="([^"]+)"[^>]*>([^<]+)<\/a>[\s\S]*?<td[^>]*class="result-snippet"[^>]*>([^<]+)/gi;
94824
- const altPattern = /<a[^>]+rel="nofollow"[^>]*href="([^"]+)"[^>]*>([^<]+)<\/a>[\s\S]*?<span[^>]*>([^<]{20,})/gi;
94825
- let match;
94826
- while ((match = resultPattern.exec(html)) !== null && results.length < maxResults) {
94827
- const [, url2, title, snippet] = match;
94828
- if (url2 && title && !url2.includes("duckduckgo.com")) {
94829
- results.push({
94830
- title: decodeHtmlEntities(title.trim()),
94831
- url: decodeUrl(url2),
94832
- snippet: decodeHtmlEntities(snippet.trim())
94833
- });
94834
- }
94835
- }
94836
- if (results.length === 0) {
94837
- while ((match = altPattern.exec(html)) !== null && results.length < maxResults) {
94838
- const [, url2, title, snippet] = match;
94839
- if (url2 && title && !url2.includes("duckduckgo.com")) {
94840
- results.push({
94841
- title: decodeHtmlEntities(title.trim()),
94842
- url: decodeUrl(url2),
94843
- snippet: decodeHtmlEntities(snippet.trim())
94844
- });
94845
- }
94846
- }
94847
- }
94848
- if (results.length === 0) {
94849
- const linkPattern = /<a[^>]+href="(https?:\/\/(?!duckduckgo)[^"]+)"[^>]*>([^<]{10,100})<\/a>/gi;
94850
- const seenUrls = new Set;
94851
- while ((match = linkPattern.exec(html)) !== null && results.length < maxResults) {
94852
- const [, url2, title] = match;
94853
- if (!seenUrls.has(url2) && !url2.includes("duckduckgo")) {
94854
- seenUrls.add(url2);
94855
- results.push({
94856
- title: decodeHtmlEntities(title.trim()),
94857
- url: decodeUrl(url2),
94858
- snippet: ""
94859
- });
94860
- }
94861
- }
94862
- }
94863
- return results;
94864
- };
94865
95311
  var decodeHtmlEntities = (text) => {
94866
95312
  const entities = {
94867
95313
  "&amp;": "&",
@@ -94880,22 +95326,32 @@ var decodeHtmlEntities = (text) => {
94880
95326
  decoded = decoded.replace(/&#(\d+);/g, (_3, code) => String.fromCharCode(parseInt(code, 10)));
94881
95327
  return decoded;
94882
95328
  };
94883
- var decodeUrl = (url2) => {
94884
- if (url2.includes("uddg=")) {
94885
- const match = url2.match(/uddg=([^&]+)/);
94886
- if (match) {
94887
- return decodeURIComponent(match[1]);
95329
+ var parseRssResults = (rss, maxResults) => {
95330
+ const results = [];
95331
+ const itemPattern = /<item>([\s\S]*?)<\/item>/gi;
95332
+ let match;
95333
+ while ((match = itemPattern.exec(rss)) !== null && results.length < maxResults) {
95334
+ const itemContent = match[1];
95335
+ const titleMatch = itemContent.match(/<title>([^<]+)<\/title>/);
95336
+ const linkMatch = itemContent.match(/<link>([^<]+)<\/link>/);
95337
+ const descMatch = itemContent.match(/<description>([^<]*)<\/description>/);
95338
+ if (titleMatch && linkMatch) {
95339
+ results.push({
95340
+ title: decodeHtmlEntities(titleMatch[1].trim()),
95341
+ url: linkMatch[1].trim(),
95342
+ snippet: descMatch ? decodeHtmlEntities(descMatch[1].trim()) : ""
95343
+ });
94888
95344
  }
94889
95345
  }
94890
- return url2;
95346
+ return results;
94891
95347
  };
94892
95348
  var performSearch = async (query, maxResults, signal) => {
94893
95349
  const encodedQuery = encodeURIComponent(query);
94894
- const searchUrl = `https://lite.duckduckgo.com/lite/?q=${encodedQuery}`;
95350
+ const searchUrl = `https://www.bing.com/search?q=${encodedQuery}&format=rss`;
94895
95351
  const response2 = await fetch(searchUrl, {
94896
95352
  headers: {
94897
95353
  "User-Agent": WEB_SEARCH_DEFAULTS.USER_AGENT,
94898
- Accept: "text/html",
95354
+ Accept: "application/rss+xml, text/xml",
94899
95355
  "Accept-Language": "en-US,en;q=0.9"
94900
95356
  },
94901
95357
  signal
@@ -94903,8 +95359,8 @@ var performSearch = async (query, maxResults, signal) => {
94903
95359
  if (!response2.ok) {
94904
95360
  throw new Error(`Search request failed: ${response2.status}`);
94905
95361
  }
94906
- const html = await response2.text();
94907
- return parseSearchResults(html, maxResults);
95362
+ const rss = await response2.text();
95363
+ return parseRssResults(rss, maxResults);
94908
95364
  };
94909
95365
  var executeWebSearch = async (args, ctx) => {
94910
95366
  const { query, maxResults = 5 } = args;
@@ -94937,9 +95393,537 @@ var webSearchTool = {
94937
95393
  parameters: webSearchParams,
94938
95394
  execute: executeWebSearch
94939
95395
  };
94940
- // src/services/lsp/index.ts
95396
+ // src/constants/web-fetch.ts
95397
+ var WEB_FETCH_DEFAULTS = {
95398
+ TIMEOUT_MS: 30000,
95399
+ MAX_CONTENT_LENGTH: 500000,
95400
+ USER_AGENT: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
95401
+ };
95402
+ var WEB_FETCH_TITLES = {
95403
+ FETCHING: (url2) => `Fetching: ${url2}`,
95404
+ SUCCESS: "Content fetched",
95405
+ FAILED: "Fetch failed",
95406
+ TIMEOUT: "Fetch timed out"
95407
+ };
95408
+ var WEB_FETCH_MESSAGES = {
95409
+ URL_REQUIRED: "URL is required",
95410
+ INVALID_URL: (url2) => `Invalid URL: ${url2}`,
95411
+ TIMEOUT: "Request timed out",
95412
+ FETCH_ERROR: (error49) => `Fetch failed: ${error49}`,
95413
+ CONTENT_TOO_LARGE: "Content exceeds maximum size limit",
95414
+ REDIRECT_DETECTED: (from2, to) => `Redirected from ${from2} to ${to}`
95415
+ };
95416
+ var WEB_FETCH_DESCRIPTION = `Fetch content from a URL and convert HTML to markdown.
95417
+
95418
+ Use this tool when you need to:
95419
+ - Read documentation from a URL
95420
+ - Fetch API responses
95421
+ - Get content from web pages
95422
+
95423
+ The content will be converted to markdown for readability.
95424
+ HTML will be cleaned and converted. JSON responses are formatted.
95425
+
95426
+ Note: This tool cannot access authenticated or private URLs.
95427
+ For GitHub URLs, prefer using the \`bash\` tool with \`gh\` CLI instead.`;
95428
+ var HTML_REMOVE_ELEMENTS = [
95429
+ "script",
95430
+ "style",
95431
+ "noscript",
95432
+ "iframe",
95433
+ "svg",
95434
+ "canvas",
95435
+ "video",
95436
+ "audio",
95437
+ "nav",
95438
+ "footer",
95439
+ "aside"
95440
+ ];
95441
+
95442
+ // src/tools/web-fetch/params.ts
95443
+ var webFetchParams = exports_external.object({
95444
+ url: exports_external.string().describe("The URL to fetch content from"),
95445
+ prompt: exports_external.string().optional().describe("Optional prompt to extract specific information from the content"),
95446
+ timeout: exports_external.number().optional().describe("Timeout in milliseconds (default: 30000)")
95447
+ });
95448
+
95449
+ // src/tools/web-fetch/execute.ts
95450
+ var createErrorResult7 = (error49) => ({
95451
+ success: false,
95452
+ title: WEB_FETCH_TITLES.FAILED,
95453
+ output: "",
95454
+ error: error49
95455
+ });
95456
+ var createSuccessResult5 = (url2, content, contentType) => ({
95457
+ success: true,
95458
+ title: WEB_FETCH_TITLES.SUCCESS,
95459
+ output: content,
95460
+ metadata: {
95461
+ url: url2,
95462
+ contentType,
95463
+ contentLength: content.length
95464
+ }
95465
+ });
95466
+ var validateUrl = (url2) => {
95467
+ try {
95468
+ const parsed = new URL(url2);
95469
+ if (parsed.protocol === "http:") {
95470
+ parsed.protocol = "https:";
95471
+ }
95472
+ if (!["https:", "http:"].includes(parsed.protocol)) {
95473
+ return null;
95474
+ }
95475
+ return parsed;
95476
+ } catch {
95477
+ return null;
95478
+ }
95479
+ };
95480
+ var removeElements = (html, tags) => {
95481
+ let result = html;
95482
+ for (const tag of tags) {
95483
+ const selfClosingPattern = new RegExp(`<${tag}[^>]*/>`, "gi");
95484
+ const openClosePattern = new RegExp(`<${tag}[^>]*>[\\s\\S]*?</${tag}>`, "gi");
95485
+ result = result.replace(selfClosingPattern, "");
95486
+ result = result.replace(openClosePattern, "");
95487
+ }
95488
+ return result;
95489
+ };
95490
+ var decodeHtmlEntities2 = (text) => {
95491
+ const entities = {
95492
+ "&amp;": "&",
95493
+ "&lt;": "<",
95494
+ "&gt;": ">",
95495
+ "&quot;": '"',
95496
+ "&#39;": "'",
95497
+ "&nbsp;": " ",
95498
+ "&#x27;": "'",
95499
+ "&#x2F;": "/",
95500
+ "&mdash;": "—",
95501
+ "&ndash;": "–",
95502
+ "&hellip;": "…",
95503
+ "&rsquo;": "'",
95504
+ "&lsquo;": "'",
95505
+ "&rdquo;": '"',
95506
+ "&ldquo;": '"',
95507
+ "&copy;": "©",
95508
+ "&reg;": "®",
95509
+ "&trade;": "™"
95510
+ };
95511
+ let decoded = text;
95512
+ for (const [entity, char] of Object.entries(entities)) {
95513
+ decoded = decoded.replace(new RegExp(entity, "g"), char);
95514
+ }
95515
+ decoded = decoded.replace(/&#(\d+);/g, (_3, code) => String.fromCharCode(parseInt(code, 10)));
95516
+ decoded = decoded.replace(/&#x([0-9a-fA-F]+);/g, (_3, code) => String.fromCharCode(parseInt(code, 16)));
95517
+ return decoded;
95518
+ };
95519
+ var htmlToMarkdown = (html) => {
95520
+ let content = removeElements(html, HTML_REMOVE_ELEMENTS);
95521
+ const bodyMatch = content.match(/<body[^>]*>([\s\S]*)<\/body>/i);
95522
+ if (bodyMatch) {
95523
+ content = bodyMatch[1];
95524
+ }
95525
+ content = content.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, `
95526
+ # $1
95527
+ `);
95528
+ content = content.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, `
95529
+ ## $1
95530
+ `);
95531
+ content = content.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, `
95532
+ ### $1
95533
+ `);
95534
+ content = content.replace(/<h4[^>]*>([\s\S]*?)<\/h4>/gi, `
95535
+ #### $1
95536
+ `);
95537
+ content = content.replace(/<h5[^>]*>([\s\S]*?)<\/h5>/gi, `
95538
+ ##### $1
95539
+ `);
95540
+ content = content.replace(/<h6[^>]*>([\s\S]*?)<\/h6>/gi, `
95541
+ ###### $1
95542
+ `);
95543
+ content = content.replace(/<a[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/gi, "[$2]($1)");
95544
+ content = content.replace(/<img[^>]*src="([^"]*)"[^>]*alt="([^"]*)"[^>]*\/?>/gi, "![$2]($1)");
95545
+ content = content.replace(/<img[^>]*src="([^"]*)"[^>]*\/?>/gi, "![]($1)");
95546
+ content = content.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi, "**$1**");
95547
+ content = content.replace(/<b[^>]*>([\s\S]*?)<\/b>/gi, "**$1**");
95548
+ content = content.replace(/<em[^>]*>([\s\S]*?)<\/em>/gi, "*$1*");
95549
+ content = content.replace(/<i[^>]*>([\s\S]*?)<\/i>/gi, "*$1*");
95550
+ content = content.replace(/<code[^>]*>([\s\S]*?)<\/code>/gi, "`$1`");
95551
+ content = content.replace(/<pre[^>]*>([\s\S]*?)<\/pre>/gi, "\n```\n$1\n```\n");
95552
+ content = content.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, `- $1
95553
+ `);
95554
+ content = content.replace(/<\/?[ou]l[^>]*>/gi, `
95555
+ `);
95556
+ content = content.replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, `
95557
+ $1
95558
+ `);
95559
+ content = content.replace(/<br\s*\/?>/gi, `
95560
+ `);
95561
+ content = content.replace(/<hr\s*\/?>/gi, `
95562
+ ---
95563
+ `);
95564
+ content = content.replace(/<blockquote[^>]*>([\s\S]*?)<\/blockquote>/gi, (_3, text) => {
95565
+ return text.split(`
95566
+ `).map((line2) => `> ${line2}`).join(`
95567
+ `);
95568
+ });
95569
+ content = content.replace(/<[^>]+>/g, "");
95570
+ content = decodeHtmlEntities2(content);
95571
+ content = content.replace(/\n{3,}/g, `
95572
+
95573
+ `);
95574
+ content = content.replace(/[ \t]+/g, " ");
95575
+ content = content.trim();
95576
+ return content;
95577
+ };
95578
+ var formatJson = (json2) => {
95579
+ try {
95580
+ const parsed = JSON.parse(json2);
95581
+ return "```json\n" + JSON.stringify(parsed, null, 2) + "\n```";
95582
+ } catch {
95583
+ return json2;
95584
+ }
95585
+ };
95586
+ var processContent = (content, contentType) => {
95587
+ const type = contentType.toLowerCase();
95588
+ if (type.includes("json")) {
95589
+ return formatJson(content);
95590
+ }
95591
+ if (type.includes("html") || type.includes("xhtml")) {
95592
+ return htmlToMarkdown(content);
95593
+ }
95594
+ return content;
95595
+ };
95596
+ var truncateContent = (content, maxLength) => {
95597
+ if (content.length <= maxLength) {
95598
+ return content;
95599
+ }
95600
+ const truncated = content.slice(0, maxLength);
95601
+ const lastNewline = truncated.lastIndexOf(`
95602
+ `);
95603
+ const cutPoint = lastNewline > maxLength * 0.8 ? lastNewline : maxLength;
95604
+ return truncated.slice(0, cutPoint) + `
95605
+
95606
+ ... (content truncated, showing first ` + Math.round(maxLength / 1000) + "KB)";
95607
+ };
95608
+ var executeWebFetch = async (args, ctx) => {
95609
+ const { url: url2, timeout = WEB_FETCH_DEFAULTS.TIMEOUT_MS } = args;
95610
+ if (!url2 || url2.trim().length === 0) {
95611
+ return createErrorResult7(WEB_FETCH_MESSAGES.URL_REQUIRED);
95612
+ }
95613
+ const parsedUrl = validateUrl(url2);
95614
+ if (!parsedUrl) {
95615
+ return createErrorResult7(WEB_FETCH_MESSAGES.INVALID_URL(url2));
95616
+ }
95617
+ ctx.onMetadata?.({
95618
+ title: WEB_FETCH_TITLES.FETCHING(parsedUrl.hostname),
95619
+ status: "running"
95620
+ });
95621
+ try {
95622
+ const controller = new AbortController;
95623
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
95624
+ ctx.abort.signal.addEventListener("abort", () => controller.abort());
95625
+ const response2 = await fetch(parsedUrl.toString(), {
95626
+ headers: {
95627
+ "User-Agent": WEB_FETCH_DEFAULTS.USER_AGENT,
95628
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,application/json,text/plain;q=0.8",
95629
+ "Accept-Language": "en-US,en;q=0.9"
95630
+ },
95631
+ signal: controller.signal,
95632
+ redirect: "follow"
95633
+ });
95634
+ clearTimeout(timeoutId);
95635
+ if (!response2.ok) {
95636
+ return createErrorResult7(WEB_FETCH_MESSAGES.FETCH_ERROR(`HTTP ${response2.status}`));
95637
+ }
95638
+ const finalUrl = new URL(response2.url);
95639
+ if (finalUrl.host !== parsedUrl.host) {
95640
+ return {
95641
+ success: true,
95642
+ title: WEB_FETCH_TITLES.SUCCESS,
95643
+ output: WEB_FETCH_MESSAGES.REDIRECT_DETECTED(parsedUrl.host, finalUrl.host),
95644
+ metadata: {
95645
+ redirectUrl: response2.url,
95646
+ originalUrl: url2
95647
+ }
95648
+ };
95649
+ }
95650
+ const contentType = response2.headers.get("content-type") || "text/plain";
95651
+ let content = await response2.text();
95652
+ if (content.length > WEB_FETCH_DEFAULTS.MAX_CONTENT_LENGTH) {
95653
+ content = truncateContent(content, WEB_FETCH_DEFAULTS.MAX_CONTENT_LENGTH);
95654
+ }
95655
+ const processed = processContent(content, contentType);
95656
+ return createSuccessResult5(response2.url, processed, contentType);
95657
+ } catch (error49) {
95658
+ if (ctx.abort.signal.aborted) {
95659
+ return createErrorResult7(WEB_FETCH_MESSAGES.TIMEOUT);
95660
+ }
95661
+ const message2 = error49 instanceof Error ? error49.message : String(error49);
95662
+ return createErrorResult7(WEB_FETCH_MESSAGES.FETCH_ERROR(message2));
95663
+ }
95664
+ };
95665
+ var webFetchTool = {
95666
+ name: "web_fetch",
95667
+ description: WEB_FETCH_DESCRIPTION,
95668
+ parameters: webFetchParams,
95669
+ execute: executeWebFetch
95670
+ };
95671
+ // src/tools/multi-edit/execute.ts
94941
95672
  import fs10 from "fs/promises";
94942
- import path11 from "path";
95673
+ import path10 from "path";
95674
+
95675
+ // src/constants/multi-edit.ts
95676
+ var MULTI_EDIT_DEFAULTS = {
95677
+ MAX_EDITS: 50,
95678
+ MAX_FILE_SIZE: 1024 * 1024
95679
+ };
95680
+ var MULTI_EDIT_TITLES = {
95681
+ VALIDATING: (count) => `Validating ${count} edits...`,
95682
+ APPLYING: (current, total) => `Applying edit ${current}/${total}`,
95683
+ SUCCESS: (count) => `Applied ${count} edits`,
95684
+ PARTIAL: (success3, failed) => `Applied ${success3} edits, ${failed} failed`,
95685
+ FAILED: "Multi-edit failed",
95686
+ ROLLBACK: "Rolling back changes..."
95687
+ };
95688
+ var MULTI_EDIT_MESSAGES = {
95689
+ NO_EDITS: "No edits provided",
95690
+ TOO_MANY_EDITS: (max) => `Too many edits (max: ${max})`,
95691
+ VALIDATION_FAILED: "Validation failed for one or more edits",
95692
+ ATOMIC_FAILURE: "Atomic edit failed - all changes rolled back",
95693
+ DUPLICATE_FILE: (path10) => `Multiple edits to same file must be ordered: ${path10}`,
95694
+ OLD_STRING_NOT_FOUND: (path10, preview) => `Old string not found in ${path10}: "${preview}..."`,
95695
+ OLD_STRING_NOT_UNIQUE: (path10, count) => `Old string found ${count} times in ${path10} (must be unique)`,
95696
+ FILE_NOT_FOUND: (path10) => `File not found: ${path10}`,
95697
+ FILE_TOO_LARGE: (path10) => `File too large: ${path10}`
95698
+ };
95699
+ var MULTI_EDIT_DESCRIPTION = `Edit multiple files in a single atomic operation.
95700
+
95701
+ Use this tool when you need to:
95702
+ - Make related changes across multiple files
95703
+ - Refactor code that spans several files
95704
+ - Apply consistent changes to many files
95705
+
95706
+ All edits are validated before any changes are applied.
95707
+ If any edit fails validation, no changes are made.
95708
+
95709
+ Each edit requires:
95710
+ - file_path: Absolute path to the file
95711
+ - old_string: The exact text to find and replace
95712
+ - new_string: The replacement text
95713
+
95714
+ The old_string must be unique in the file. If it appears multiple times,
95715
+ provide more context to make it unique.`;
95716
+
95717
+ // src/tools/multi-edit/params.ts
95718
+ var editItemSchema = exports_external.object({
95719
+ file_path: exports_external.string().describe("Absolute path to the file to edit"),
95720
+ old_string: exports_external.string().describe("The exact text to find and replace"),
95721
+ new_string: exports_external.string().describe("The replacement text")
95722
+ });
95723
+ var multiEditParams = exports_external.object({
95724
+ edits: exports_external.array(editItemSchema).min(1).describe("Array of edits to apply atomically")
95725
+ });
95726
+
95727
+ // src/tools/multi-edit/execute.ts
95728
+ var createErrorResult8 = (error49) => ({
95729
+ success: false,
95730
+ title: MULTI_EDIT_TITLES.FAILED,
95731
+ output: "",
95732
+ error: error49
95733
+ });
95734
+ var createSuccessResult6 = (results, totalEdits) => {
95735
+ const successful = results.filter((r) => r.success);
95736
+ const failed = results.filter((r) => !r.success);
95737
+ const diffOutput = successful.map((r) => `## ${path10.basename(r.path)}
95738
+
95739
+ ${r.diff}`).join(`
95740
+
95741
+ ---
95742
+
95743
+ `);
95744
+ const totalAdditions = successful.reduce((sum, r) => sum + (r.additions ?? 0), 0);
95745
+ const totalDeletions = successful.reduce((sum, r) => sum + (r.deletions ?? 0), 0);
95746
+ const title = failed.length > 0 ? MULTI_EDIT_TITLES.PARTIAL(successful.length, failed.length) : MULTI_EDIT_TITLES.SUCCESS(successful.length);
95747
+ let output = diffOutput;
95748
+ if (failed.length > 0) {
95749
+ output += `
95750
+
95751
+ ## Failed Edits
95752
+
95753
+ ` + failed.map((r) => `- ${r.path}: ${r.error}`).join(`
95754
+ `);
95755
+ }
95756
+ return {
95757
+ success: failed.length === 0,
95758
+ title,
95759
+ output,
95760
+ metadata: {
95761
+ totalEdits,
95762
+ successful: successful.length,
95763
+ failed: failed.length,
95764
+ totalAdditions,
95765
+ totalDeletions
95766
+ }
95767
+ };
95768
+ };
95769
+ var validateEdit = async (edit, workingDir3) => {
95770
+ const fullPath = path10.isAbsolute(edit.file_path) ? edit.file_path : path10.join(workingDir3, edit.file_path);
95771
+ try {
95772
+ const stat3 = await fs10.stat(fullPath);
95773
+ if (!stat3.isFile()) {
95774
+ return { valid: false, error: `Not a file: ${edit.file_path}` };
95775
+ }
95776
+ if (stat3.size > MULTI_EDIT_DEFAULTS.MAX_FILE_SIZE) {
95777
+ return { valid: false, error: MULTI_EDIT_MESSAGES.FILE_TOO_LARGE(edit.file_path) };
95778
+ }
95779
+ const content = await fs10.readFile(fullPath, "utf-8");
95780
+ if (!content.includes(edit.old_string)) {
95781
+ const preview = edit.old_string.slice(0, 50);
95782
+ return {
95783
+ valid: false,
95784
+ error: MULTI_EDIT_MESSAGES.OLD_STRING_NOT_FOUND(edit.file_path, preview)
95785
+ };
95786
+ }
95787
+ const occurrences = content.split(edit.old_string).length - 1;
95788
+ if (occurrences > 1) {
95789
+ return {
95790
+ valid: false,
95791
+ error: MULTI_EDIT_MESSAGES.OLD_STRING_NOT_UNIQUE(edit.file_path, occurrences)
95792
+ };
95793
+ }
95794
+ return { valid: true, fileContent: content };
95795
+ } catch (error49) {
95796
+ if (error49.code === "ENOENT") {
95797
+ return { valid: false, error: MULTI_EDIT_MESSAGES.FILE_NOT_FOUND(edit.file_path) };
95798
+ }
95799
+ const message2 = error49 instanceof Error ? error49.message : String(error49);
95800
+ return { valid: false, error: message2 };
95801
+ }
95802
+ };
95803
+ var checkPermissions = async (edits, workingDir3, autoApprove) => {
95804
+ const denied = [];
95805
+ for (const edit of edits) {
95806
+ const fullPath = path10.isAbsolute(edit.file_path) ? edit.file_path : path10.join(workingDir3, edit.file_path);
95807
+ if (!autoApprove && !isFileOpAllowed("Edit", fullPath)) {
95808
+ const { allowed } = await promptFilePermission("Edit", fullPath, `Edit file: ${edit.file_path}`);
95809
+ if (!allowed) {
95810
+ denied.push(edit.file_path);
95811
+ }
95812
+ }
95813
+ }
95814
+ return { allowed: denied.length === 0, denied };
95815
+ };
95816
+ var applyEdit2 = async (edit, workingDir3, fileContent) => {
95817
+ const fullPath = path10.isAbsolute(edit.file_path) ? edit.file_path : path10.join(workingDir3, edit.file_path);
95818
+ try {
95819
+ const newContent = fileContent.replace(edit.old_string, edit.new_string);
95820
+ const diff = generateDiff(fileContent, newContent);
95821
+ const relativePath = path10.relative(workingDir3, fullPath);
95822
+ const diffOutput = formatDiff(diff, relativePath);
95823
+ await fs10.writeFile(fullPath, newContent, "utf-8");
95824
+ return {
95825
+ path: edit.file_path,
95826
+ success: true,
95827
+ diff: diffOutput,
95828
+ additions: diff.additions,
95829
+ deletions: diff.deletions
95830
+ };
95831
+ } catch (error49) {
95832
+ const message2 = error49 instanceof Error ? error49.message : String(error49);
95833
+ return {
95834
+ path: edit.file_path,
95835
+ success: false,
95836
+ error: message2
95837
+ };
95838
+ }
95839
+ };
95840
+ var rollback = async (backups) => {
95841
+ for (const backup of backups) {
95842
+ try {
95843
+ await fs10.writeFile(backup.path, backup.content, "utf-8");
95844
+ } catch {}
95845
+ }
95846
+ };
95847
+ var executeMultiEdit = async (args, ctx) => {
95848
+ const { edits } = args;
95849
+ if (edits.length === 0) {
95850
+ return createErrorResult8(MULTI_EDIT_MESSAGES.NO_EDITS);
95851
+ }
95852
+ if (edits.length > MULTI_EDIT_DEFAULTS.MAX_EDITS) {
95853
+ return createErrorResult8(MULTI_EDIT_MESSAGES.TOO_MANY_EDITS(MULTI_EDIT_DEFAULTS.MAX_EDITS));
95854
+ }
95855
+ ctx.onMetadata?.({
95856
+ title: MULTI_EDIT_TITLES.VALIDATING(edits.length),
95857
+ status: "running"
95858
+ });
95859
+ const validations = new Map;
95860
+ const errors5 = [];
95861
+ for (const edit of edits) {
95862
+ const validation = await validateEdit(edit, ctx.workingDir);
95863
+ validations.set(edit.file_path, { validation, edit });
95864
+ if (!validation.valid) {
95865
+ errors5.push(validation.error ?? "Unknown error");
95866
+ }
95867
+ }
95868
+ if (errors5.length > 0) {
95869
+ return createErrorResult8(MULTI_EDIT_MESSAGES.VALIDATION_FAILED + `:
95870
+ ` + errors5.join(`
95871
+ `));
95872
+ }
95873
+ const permCheck = await checkPermissions(edits, ctx.workingDir, ctx.autoApprove ?? false);
95874
+ if (!permCheck.allowed) {
95875
+ return createErrorResult8(`Permission denied for: ${permCheck.denied.join(", ")}`);
95876
+ }
95877
+ const backups = [];
95878
+ const results = [];
95879
+ let failed = false;
95880
+ for (let i2 = 0;i2 < edits.length; i2++) {
95881
+ const edit = edits[i2];
95882
+ const data = validations.get(edit.file_path);
95883
+ if (!data?.validation.fileContent)
95884
+ continue;
95885
+ ctx.onMetadata?.({
95886
+ title: MULTI_EDIT_TITLES.APPLYING(i2 + 1, edits.length),
95887
+ status: "running"
95888
+ });
95889
+ const fullPath = path10.isAbsolute(edit.file_path) ? edit.file_path : path10.join(ctx.workingDir, edit.file_path);
95890
+ backups.push({
95891
+ path: fullPath,
95892
+ content: data.validation.fileContent
95893
+ });
95894
+ const result = await applyEdit2(edit, ctx.workingDir, data.validation.fileContent);
95895
+ results.push(result);
95896
+ if (!result.success) {
95897
+ failed = true;
95898
+ break;
95899
+ }
95900
+ if (result.success) {
95901
+ const newContent = data.validation.fileContent.replace(edit.old_string, edit.new_string);
95902
+ validations.set(edit.file_path, {
95903
+ ...data,
95904
+ validation: { ...data.validation, fileContent: newContent }
95905
+ });
95906
+ }
95907
+ }
95908
+ if (failed) {
95909
+ ctx.onMetadata?.({
95910
+ title: MULTI_EDIT_TITLES.ROLLBACK,
95911
+ status: "running"
95912
+ });
95913
+ await rollback(backups);
95914
+ return createErrorResult8(MULTI_EDIT_MESSAGES.ATOMIC_FAILURE);
95915
+ }
95916
+ return createSuccessResult6(results, edits.length);
95917
+ };
95918
+ var multiEditTool = {
95919
+ name: "multi_edit",
95920
+ description: MULTI_EDIT_DESCRIPTION,
95921
+ parameters: multiEditParams,
95922
+ execute: executeMultiEdit
95923
+ };
95924
+ // src/services/lsp/index.ts
95925
+ import fs12 from "fs/promises";
95926
+ import path12 from "path";
94943
95927
  import { EventEmitter as EventEmitter14 } from "events";
94944
95928
 
94945
95929
  // src/services/lsp/client.ts
@@ -95339,11 +96323,11 @@ var createLSPClient = (process14, serverId, root) => {
95339
96323
 
95340
96324
  // src/services/lsp/server.ts
95341
96325
  import { spawn as spawn3, execSync } from "child_process";
95342
- import path10 from "path";
95343
- import fs9 from "fs/promises";
96326
+ import path11 from "path";
96327
+ import fs11 from "fs/promises";
95344
96328
  var fileExists = async (filePath2) => {
95345
96329
  try {
95346
- await fs9.access(filePath2);
96330
+ await fs11.access(filePath2);
95347
96331
  return true;
95348
96332
  } catch {
95349
96333
  return false;
@@ -95351,15 +96335,15 @@ var fileExists = async (filePath2) => {
95351
96335
  };
95352
96336
  var findProjectRoot = async (startDir, patterns) => {
95353
96337
  let currentDir = startDir;
95354
- const root = path10.parse(currentDir).root;
96338
+ const root = path11.parse(currentDir).root;
95355
96339
  while (currentDir !== root) {
95356
96340
  for (const pattern of patterns) {
95357
- const checkPath = path10.join(currentDir, pattern);
96341
+ const checkPath = path11.join(currentDir, pattern);
95358
96342
  if (await fileExists(checkPath)) {
95359
96343
  return currentDir;
95360
96344
  }
95361
96345
  }
95362
- currentDir = path10.dirname(currentDir);
96346
+ currentDir = path11.dirname(currentDir);
95363
96347
  }
95364
96348
  return null;
95365
96349
  };
@@ -95518,13 +96502,13 @@ var SERVERS = {
95518
96502
  };
95519
96503
  var getServersForFile = (filePath2) => {
95520
96504
  const ext = "." + (filePath2.split(".").pop() ?? "");
95521
- const fileName = path10.basename(filePath2);
96505
+ const fileName = path11.basename(filePath2);
95522
96506
  return Object.values(SERVERS).filter((server) => {
95523
96507
  return server.extensions.includes(ext) || server.extensions.includes(fileName);
95524
96508
  });
95525
96509
  };
95526
96510
  var findRootForServer = async (filePath2, server) => {
95527
- const dir = path10.dirname(filePath2);
96511
+ const dir = path11.dirname(filePath2);
95528
96512
  return findProjectRoot(dir, server.rootPatterns);
95529
96513
  };
95530
96514
  var spawnServer = async (server, root) => {
@@ -95616,11 +96600,11 @@ var spawnClient = async (server, root) => {
95616
96600
  }
95617
96601
  };
95618
96602
  var openFile = async (filePath2) => {
95619
- const absolutePath = path11.resolve(filePath2);
96603
+ const absolutePath = path12.resolve(filePath2);
95620
96604
  const clients = await getClientsForFile(absolutePath);
95621
96605
  if (clients.length === 0)
95622
96606
  return;
95623
- const content = await fs10.readFile(absolutePath, "utf-8");
96607
+ const content = await fs12.readFile(absolutePath, "utf-8");
95624
96608
  for (const client of clients) {
95625
96609
  if (!client.isFileOpen(absolutePath)) {
95626
96610
  await client.openFile(absolutePath, content);
@@ -95628,7 +96612,7 @@ var openFile = async (filePath2) => {
95628
96612
  }
95629
96613
  };
95630
96614
  var updateFile = async (filePath2, content) => {
95631
- const absolutePath = path11.resolve(filePath2);
96615
+ const absolutePath = path12.resolve(filePath2);
95632
96616
  const clients = await getClientsForFile(absolutePath);
95633
96617
  for (const client of clients) {
95634
96618
  if (client.isFileOpen(absolutePath)) {
@@ -95639,7 +96623,7 @@ var updateFile = async (filePath2, content) => {
95639
96623
  }
95640
96624
  };
95641
96625
  var closeFile = async (filePath2) => {
95642
- const absolutePath = path11.resolve(filePath2);
96626
+ const absolutePath = path12.resolve(filePath2);
95643
96627
  const clients = await getClientsForFile(absolutePath);
95644
96628
  for (const client of clients) {
95645
96629
  if (client.isFileOpen(absolutePath)) {
@@ -95648,7 +96632,7 @@ var closeFile = async (filePath2) => {
95648
96632
  }
95649
96633
  };
95650
96634
  var getHover = async (filePath2, position) => {
95651
- const absolutePath = path11.resolve(filePath2);
96635
+ const absolutePath = path12.resolve(filePath2);
95652
96636
  const clients = await getClientsForFile(absolutePath);
95653
96637
  for (const client of clients) {
95654
96638
  const hover = await client.getHover(absolutePath, position);
@@ -95658,7 +96642,7 @@ var getHover = async (filePath2, position) => {
95658
96642
  return null;
95659
96643
  };
95660
96644
  var getDefinition = async (filePath2, position) => {
95661
- const absolutePath = path11.resolve(filePath2);
96645
+ const absolutePath = path12.resolve(filePath2);
95662
96646
  const clients = await getClientsForFile(absolutePath);
95663
96647
  for (const client of clients) {
95664
96648
  const definition = await client.getDefinition(absolutePath, position);
@@ -95668,7 +96652,7 @@ var getDefinition = async (filePath2, position) => {
95668
96652
  return null;
95669
96653
  };
95670
96654
  var getReferences = async (filePath2, position, includeDeclaration = true) => {
95671
- const absolutePath = path11.resolve(filePath2);
96655
+ const absolutePath = path12.resolve(filePath2);
95672
96656
  const clients = await getClientsForFile(absolutePath);
95673
96657
  const allRefs = [];
95674
96658
  for (const client of clients) {
@@ -95685,7 +96669,7 @@ var getReferences = async (filePath2, position, includeDeclaration = true) => {
95685
96669
  });
95686
96670
  };
95687
96671
  var getCompletions = async (filePath2, position) => {
95688
- const absolutePath = path11.resolve(filePath2);
96672
+ const absolutePath = path12.resolve(filePath2);
95689
96673
  const clients = await getClientsForFile(absolutePath);
95690
96674
  const allCompletions = [];
95691
96675
  for (const client of clients) {
@@ -95695,7 +96679,7 @@ var getCompletions = async (filePath2, position) => {
95695
96679
  return allCompletions;
95696
96680
  };
95697
96681
  var getDocumentSymbols = async (filePath2) => {
95698
- const absolutePath = path11.resolve(filePath2);
96682
+ const absolutePath = path12.resolve(filePath2);
95699
96683
  const clients = await getClientsForFile(absolutePath);
95700
96684
  for (const client of clients) {
95701
96685
  const symbols = await client.getDocumentSymbols(absolutePath);
@@ -95710,7 +96694,7 @@ var getDiagnostics = (filePath2) => {
95710
96694
  const clientDiagnostics = client.getAllDiagnostics();
95711
96695
  for (const [uri, diagnostics] of clientDiagnostics) {
95712
96696
  if (filePath2) {
95713
- const expectedUri = `file://${path11.resolve(filePath2)}`;
96697
+ const expectedUri = `file://${path12.resolve(filePath2)}`;
95714
96698
  if (uri !== expectedUri)
95715
96699
  continue;
95716
96700
  }
@@ -95772,7 +96756,7 @@ var lspService = {
95772
96756
  };
95773
96757
 
95774
96758
  // src/tools/lsp.ts
95775
- import fs11 from "fs/promises";
96759
+ import fs13 from "fs/promises";
95776
96760
  var PositionSchema = exports_external.object({
95777
96761
  line: exports_external.number().describe("Zero-based line number"),
95778
96762
  character: exports_external.number().describe("Zero-based character offset")
@@ -95889,7 +96873,7 @@ Examples:
95889
96873
  execute: async (args) => {
95890
96874
  const { operation, file: file2, position } = args;
95891
96875
  try {
95892
- await fs11.access(file2);
96876
+ await fs13.access(file2);
95893
96877
  } catch {
95894
96878
  return {
95895
96879
  success: false,
@@ -95967,6 +96951,754 @@ Examples:
95967
96951
  };
95968
96952
  }
95969
96953
  };
96954
+ // src/constants/apply-patch.ts
96955
+ var PATCH_DEFAULTS = {
96956
+ FUZZ: 2,
96957
+ MAX_FUZZ: 3,
96958
+ IGNORE_WHITESPACE: false,
96959
+ IGNORE_CASE: false,
96960
+ CONTEXT_LINES: 3
96961
+ };
96962
+ var PATCH_PATTERNS = {
96963
+ HUNK_HEADER: /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$/,
96964
+ FILE_HEADER_OLD: /^--- (.+?)(?:\t.*)?$/,
96965
+ FILE_HEADER_NEW: /^\+\+\+ (.+?)(?:\t.*)?$/,
96966
+ GIT_DIFF: /^diff --git a\/(.+) b\/(.+)$/,
96967
+ INDEX_LINE: /^index [a-f0-9]+\.\.[a-f0-9]+(?: \d+)?$/,
96968
+ BINARY_FILE: /^Binary files .+ differ$/,
96969
+ NEW_FILE: /^new file mode \d+$/,
96970
+ DELETED_FILE: /^deleted file mode \d+$/,
96971
+ RENAME_FROM: /^rename from (.+)$/,
96972
+ RENAME_TO: /^rename to (.+)$/,
96973
+ NO_NEWLINE: /^\$/
96974
+ };
96975
+ var LINE_PREFIXES2 = {
96976
+ CONTEXT: " ",
96977
+ ADDITION: "+",
96978
+ DELETION: "-"
96979
+ };
96980
+ var PATCH_ERRORS = {
96981
+ INVALID_PATCH: "Invalid patch format",
96982
+ PARSE_FAILED: (detail) => `Failed to parse patch: ${detail}`,
96983
+ HUNK_FAILED: (index, reason) => `Hunk #${index + 1} failed: ${reason}`,
96984
+ FILE_NOT_FOUND: (path13) => `Target file not found: ${path13}`,
96985
+ CONTEXT_MISMATCH: (line2) => `Context mismatch at line ${line2}`,
96986
+ FUZZY_MATCH_FAILED: (hunk) => `Could not find match for hunk #${hunk + 1} even with fuzzy matching`,
96987
+ ALREADY_APPLIED: "Patch appears to be already applied",
96988
+ REVERSED_PATCH: "Patch appears to be reversed",
96989
+ BINARY_NOT_SUPPORTED: "Binary patches are not supported",
96990
+ WRITE_FAILED: (path13, error49) => `Failed to write patched file ${path13}: ${error49}`
96991
+ };
96992
+ var PATCH_MESSAGES = {
96993
+ PARSING: "Parsing patch...",
96994
+ APPLYING: (file2) => `Applying patch to ${file2}`,
96995
+ APPLIED: (files, hunks) => `Successfully applied ${hunks} hunk(s) to ${files} file(s)`,
96996
+ DRY_RUN: (files, hunks) => `Dry run: ${hunks} hunk(s) would be applied to ${files} file(s)`,
96997
+ FUZZY_APPLIED: (hunk, offset) => `Hunk #${hunk + 1} applied with fuzzy offset of ${offset}`,
96998
+ ROLLBACK_AVAILABLE: "Rollback is available if needed",
96999
+ SKIPPED_BINARY: (file2) => `Skipped binary file: ${file2}`
97000
+ };
97001
+ var PATCH_TITLES = {
97002
+ APPLYING: (file2) => `Patching: ${file2}`,
97003
+ SUCCESS: (files) => `Patched ${files} file(s)`,
97004
+ PARTIAL: (success3, failed) => `Partial success: ${success3} patched, ${failed} failed`,
97005
+ FAILED: "Patch failed",
97006
+ DRY_RUN: "Patch dry run",
97007
+ VALIDATING: "Validating patch"
97008
+ };
97009
+ var SPECIAL_PATHS = {
97010
+ DEV_NULL: "/dev/null",
97011
+ A_PREFIX: "a/",
97012
+ B_PREFIX: "b/"
97013
+ };
97014
+
97015
+ // src/tools/apply-patch/params.ts
97016
+ var applyPatchParams = exports_external.object({
97017
+ patch: exports_external.string().describe("The unified diff patch content to apply"),
97018
+ targetFile: exports_external.string().optional().describe("Override the target file path from the patch header"),
97019
+ dryRun: exports_external.boolean().optional().default(false).describe("Validate and preview changes without actually applying them"),
97020
+ fuzz: exports_external.number().int().min(0).max(PATCH_DEFAULTS.MAX_FUZZ).optional().default(PATCH_DEFAULTS.FUZZ).describe(`Context line tolerance for fuzzy matching (0-${PATCH_DEFAULTS.MAX_FUZZ})`),
97021
+ reverse: exports_external.boolean().optional().default(false).describe("Apply the patch in reverse (undo the changes)")
97022
+ });
97023
+
97024
+ // src/tools/apply-patch/execute.ts
97025
+ import fs14 from "fs/promises";
97026
+ import { dirname as dirname2, join as join9, isAbsolute as isAbsolute2 } from "path";
97027
+
97028
+ // src/tools/apply-patch/parser.ts
97029
+ var parsePatch2 = (patchContent) => {
97030
+ const lines = patchContent.split(`
97031
+ `);
97032
+ const files = [];
97033
+ let currentFile = null;
97034
+ let currentHunk = null;
97035
+ let lineIndex = 0;
97036
+ while (lineIndex < lines.length) {
97037
+ const line2 = lines[lineIndex];
97038
+ const gitDiffMatch = line2.match(PATCH_PATTERNS.GIT_DIFF);
97039
+ if (gitDiffMatch) {
97040
+ if (currentFile && (currentFile.hunks.length > 0 || currentFile.isBinary)) {
97041
+ files.push(currentFile);
97042
+ }
97043
+ currentFile = createEmptyFilePatch(gitDiffMatch[1], gitDiffMatch[2]);
97044
+ currentHunk = null;
97045
+ lineIndex++;
97046
+ continue;
97047
+ }
97048
+ const oldHeaderMatch = line2.match(PATCH_PATTERNS.FILE_HEADER_OLD);
97049
+ if (oldHeaderMatch) {
97050
+ if (!currentFile) {
97051
+ currentFile = createEmptyFilePatch("", "");
97052
+ }
97053
+ currentFile.oldPath = cleanPath(oldHeaderMatch[1]);
97054
+ if (currentFile.oldPath === SPECIAL_PATHS.DEV_NULL) {
97055
+ currentFile.isNew = true;
97056
+ }
97057
+ lineIndex++;
97058
+ continue;
97059
+ }
97060
+ const newHeaderMatch = line2.match(PATCH_PATTERNS.FILE_HEADER_NEW);
97061
+ if (newHeaderMatch) {
97062
+ if (!currentFile) {
97063
+ currentFile = createEmptyFilePatch("", "");
97064
+ }
97065
+ currentFile.newPath = cleanPath(newHeaderMatch[1]);
97066
+ if (currentFile.newPath === SPECIAL_PATHS.DEV_NULL) {
97067
+ currentFile.isDeleted = true;
97068
+ }
97069
+ lineIndex++;
97070
+ continue;
97071
+ }
97072
+ if (PATCH_PATTERNS.INDEX_LINE.test(line2)) {
97073
+ lineIndex++;
97074
+ continue;
97075
+ }
97076
+ if (PATCH_PATTERNS.BINARY_FILE.test(line2)) {
97077
+ if (currentFile) {
97078
+ currentFile.isBinary = true;
97079
+ }
97080
+ lineIndex++;
97081
+ continue;
97082
+ }
97083
+ if (PATCH_PATTERNS.NEW_FILE.test(line2)) {
97084
+ if (currentFile) {
97085
+ currentFile.isNew = true;
97086
+ }
97087
+ lineIndex++;
97088
+ continue;
97089
+ }
97090
+ if (PATCH_PATTERNS.DELETED_FILE.test(line2)) {
97091
+ if (currentFile) {
97092
+ currentFile.isDeleted = true;
97093
+ }
97094
+ lineIndex++;
97095
+ continue;
97096
+ }
97097
+ const renameFromMatch = line2.match(PATCH_PATTERNS.RENAME_FROM);
97098
+ if (renameFromMatch) {
97099
+ if (currentFile) {
97100
+ currentFile.isRenamed = true;
97101
+ currentFile.oldPath = cleanPath(renameFromMatch[1]);
97102
+ }
97103
+ lineIndex++;
97104
+ continue;
97105
+ }
97106
+ const renameToMatch = line2.match(PATCH_PATTERNS.RENAME_TO);
97107
+ if (renameToMatch) {
97108
+ if (currentFile) {
97109
+ currentFile.newPath = cleanPath(renameToMatch[1]);
97110
+ }
97111
+ lineIndex++;
97112
+ continue;
97113
+ }
97114
+ const hunkMatch = line2.match(PATCH_PATTERNS.HUNK_HEADER);
97115
+ if (hunkMatch) {
97116
+ if (currentHunk && currentFile) {
97117
+ currentFile.hunks.push(currentHunk);
97118
+ }
97119
+ currentHunk = {
97120
+ oldStart: parseInt(hunkMatch[1], 10),
97121
+ oldLines: hunkMatch[2] ? parseInt(hunkMatch[2], 10) : 1,
97122
+ newStart: parseInt(hunkMatch[3], 10),
97123
+ newLines: hunkMatch[4] ? parseInt(hunkMatch[4], 10) : 1,
97124
+ lines: [],
97125
+ header: line2
97126
+ };
97127
+ lineIndex++;
97128
+ continue;
97129
+ }
97130
+ if (currentHunk) {
97131
+ const patchLine = parsePatchLine(line2, currentHunk);
97132
+ if (patchLine) {
97133
+ currentHunk.lines.push(patchLine);
97134
+ }
97135
+ }
97136
+ lineIndex++;
97137
+ }
97138
+ if (currentHunk && currentFile) {
97139
+ currentFile.hunks.push(currentHunk);
97140
+ }
97141
+ if (currentFile && (currentFile.hunks.length > 0 || currentFile.isBinary)) {
97142
+ files.push(currentFile);
97143
+ }
97144
+ return {
97145
+ files,
97146
+ rawPatch: patchContent
97147
+ };
97148
+ };
97149
+ var createEmptyFilePatch = (oldPath, newPath) => ({
97150
+ oldPath: cleanPath(oldPath),
97151
+ newPath: cleanPath(newPath),
97152
+ hunks: [],
97153
+ isBinary: false,
97154
+ isNew: false,
97155
+ isDeleted: false,
97156
+ isRenamed: false
97157
+ });
97158
+ var cleanPath = (path13) => {
97159
+ if (path13.startsWith(SPECIAL_PATHS.A_PREFIX)) {
97160
+ return path13.slice(2);
97161
+ }
97162
+ if (path13.startsWith(SPECIAL_PATHS.B_PREFIX)) {
97163
+ return path13.slice(2);
97164
+ }
97165
+ return path13;
97166
+ };
97167
+ var parsePatchLine = (line2, _hunk) => {
97168
+ if (PATCH_PATTERNS.NO_NEWLINE.test(line2)) {
97169
+ return null;
97170
+ }
97171
+ if (line2 === "") {
97172
+ return null;
97173
+ }
97174
+ const prefix = line2[0];
97175
+ const content = line2.slice(1);
97176
+ const typeMap = {
97177
+ [LINE_PREFIXES2.CONTEXT]: "context",
97178
+ [LINE_PREFIXES2.ADDITION]: "addition",
97179
+ [LINE_PREFIXES2.DELETION]: "deletion"
97180
+ };
97181
+ const type = typeMap[prefix];
97182
+ if (!type) {
97183
+ return {
97184
+ type: "context",
97185
+ content: line2
97186
+ };
97187
+ }
97188
+ return {
97189
+ type,
97190
+ content
97191
+ };
97192
+ };
97193
+ var validatePatch = (patch) => {
97194
+ const errors5 = [];
97195
+ const warnings = [];
97196
+ let hunkCount = 0;
97197
+ if (patch.files.length === 0) {
97198
+ errors5.push(PATCH_ERRORS.INVALID_PATCH);
97199
+ return {
97200
+ valid: false,
97201
+ errors: errors5,
97202
+ warnings,
97203
+ fileCount: 0,
97204
+ hunkCount: 0
97205
+ };
97206
+ }
97207
+ for (const file2 of patch.files) {
97208
+ if (file2.isBinary) {
97209
+ warnings.push(PATCH_ERRORS.BINARY_NOT_SUPPORTED);
97210
+ continue;
97211
+ }
97212
+ if (!file2.newPath && !file2.isDeleted) {
97213
+ errors5.push(`Missing target path for file`);
97214
+ }
97215
+ for (const hunk of file2.hunks) {
97216
+ hunkCount++;
97217
+ let contextCount = 0;
97218
+ let additionCount = 0;
97219
+ let deletionCount = 0;
97220
+ for (const line2 of hunk.lines) {
97221
+ if (line2.type === "context")
97222
+ contextCount++;
97223
+ if (line2.type === "addition")
97224
+ additionCount++;
97225
+ if (line2.type === "deletion")
97226
+ deletionCount++;
97227
+ }
97228
+ const expectedOld = contextCount + deletionCount;
97229
+ const expectedNew = contextCount + additionCount;
97230
+ if (expectedOld !== hunk.oldLines) {
97231
+ warnings.push(`Hunk line count mismatch: expected ${hunk.oldLines} old lines, found ${expectedOld}`);
97232
+ }
97233
+ if (expectedNew !== hunk.newLines) {
97234
+ warnings.push(`Hunk line count mismatch: expected ${hunk.newLines} new lines, found ${expectedNew}`);
97235
+ }
97236
+ }
97237
+ }
97238
+ return {
97239
+ valid: errors5.length === 0,
97240
+ errors: errors5,
97241
+ warnings,
97242
+ fileCount: patch.files.length,
97243
+ hunkCount
97244
+ };
97245
+ };
97246
+ var getTargetPath = (filePatch) => {
97247
+ if (filePatch.isNew) {
97248
+ return filePatch.newPath;
97249
+ }
97250
+ if (filePatch.isDeleted) {
97251
+ return filePatch.oldPath;
97252
+ }
97253
+ return filePatch.newPath || filePatch.oldPath;
97254
+ };
97255
+ var reversePatch = (patch) => {
97256
+ return {
97257
+ ...patch,
97258
+ oldPath: patch.newPath,
97259
+ newPath: patch.oldPath,
97260
+ isNew: patch.isDeleted,
97261
+ isDeleted: patch.isNew,
97262
+ hunks: patch.hunks.map((hunk) => ({
97263
+ ...hunk,
97264
+ oldStart: hunk.newStart,
97265
+ oldLines: hunk.newLines,
97266
+ newStart: hunk.oldStart,
97267
+ newLines: hunk.oldLines,
97268
+ lines: hunk.lines.map((line2) => ({
97269
+ ...line2,
97270
+ type: line2.type === "addition" ? "deletion" : line2.type === "deletion" ? "addition" : line2.type
97271
+ }))
97272
+ }))
97273
+ };
97274
+ };
97275
+
97276
+ // src/tools/apply-patch/matcher.ts
97277
+ var DEFAULT_MATCH_OPTIONS = {
97278
+ fuzz: PATCH_DEFAULTS.FUZZ,
97279
+ ignoreWhitespace: PATCH_DEFAULTS.IGNORE_WHITESPACE,
97280
+ ignoreCase: PATCH_DEFAULTS.IGNORE_CASE
97281
+ };
97282
+ var normalizeLine = (line2, options2) => {
97283
+ let normalized = line2;
97284
+ if (options2.ignoreWhitespace) {
97285
+ normalized = normalized.replace(/\s+/g, " ").trim();
97286
+ }
97287
+ if (options2.ignoreCase) {
97288
+ normalized = normalized.toLowerCase();
97289
+ }
97290
+ return normalized;
97291
+ };
97292
+ var extractOriginalLines = (hunk) => {
97293
+ return hunk.lines.filter((line2) => line2.type === "context" || line2.type === "deletion").map((line2) => line2.content);
97294
+ };
97295
+ var checkMatchAtPosition = (fileLines, originalLines, startLine, options2) => {
97296
+ let matchCount = 0;
97297
+ let totalLines = originalLines.length;
97298
+ if (startLine + originalLines.length > fileLines.length) {
97299
+ return { matches: false, confidence: 0 };
97300
+ }
97301
+ for (let i2 = 0;i2 < originalLines.length; i2++) {
97302
+ const fileLine = normalizeLine(fileLines[startLine + i2], options2);
97303
+ const patchLine = normalizeLine(originalLines[i2], options2);
97304
+ if (fileLine === patchLine) {
97305
+ matchCount++;
97306
+ }
97307
+ }
97308
+ const confidence = totalLines > 0 ? matchCount / totalLines : 0;
97309
+ const requiredMatches = Math.max(1, totalLines - options2.fuzz);
97310
+ const matches = matchCount >= requiredMatches;
97311
+ return { matches, confidence };
97312
+ };
97313
+ var findHunkPosition = (fileContent, hunk, options2 = {}) => {
97314
+ const fullOptions = {
97315
+ ...DEFAULT_MATCH_OPTIONS,
97316
+ ...options2
97317
+ };
97318
+ const fileLines = fileContent.split(`
97319
+ `);
97320
+ const originalLines = extractOriginalLines(hunk);
97321
+ if (originalLines.length === 0) {
97322
+ const targetLine = Math.min(hunk.oldStart - 1, fileLines.length);
97323
+ return {
97324
+ found: true,
97325
+ lineNumber: targetLine,
97326
+ offset: 0,
97327
+ confidence: 1
97328
+ };
97329
+ }
97330
+ const expectedLine = hunk.oldStart - 1;
97331
+ const exactMatch = checkMatchAtPosition(fileLines, originalLines, expectedLine, fullOptions);
97332
+ if (exactMatch.matches && exactMatch.confidence === 1) {
97333
+ return {
97334
+ found: true,
97335
+ lineNumber: expectedLine,
97336
+ offset: 0,
97337
+ confidence: exactMatch.confidence
97338
+ };
97339
+ }
97340
+ const maxOffset = fullOptions.fuzz * PATCH_DEFAULTS.CONTEXT_LINES;
97341
+ let bestMatch = null;
97342
+ for (let offset = 1;offset <= maxOffset; offset++) {
97343
+ const beforePos = expectedLine - offset;
97344
+ if (beforePos >= 0) {
97345
+ const beforeMatch = checkMatchAtPosition(fileLines, originalLines, beforePos, fullOptions);
97346
+ if (beforeMatch.matches) {
97347
+ if (!bestMatch || beforeMatch.confidence > bestMatch.confidence) {
97348
+ bestMatch = {
97349
+ found: true,
97350
+ lineNumber: beforePos,
97351
+ offset: -offset,
97352
+ confidence: beforeMatch.confidence
97353
+ };
97354
+ }
97355
+ }
97356
+ }
97357
+ const afterPos = expectedLine + offset;
97358
+ if (afterPos < fileLines.length) {
97359
+ const afterMatch = checkMatchAtPosition(fileLines, originalLines, afterPos, fullOptions);
97360
+ if (afterMatch.matches) {
97361
+ if (!bestMatch || afterMatch.confidence > bestMatch.confidence) {
97362
+ bestMatch = {
97363
+ found: true,
97364
+ lineNumber: afterPos,
97365
+ offset,
97366
+ confidence: afterMatch.confidence
97367
+ };
97368
+ }
97369
+ }
97370
+ }
97371
+ if (bestMatch && bestMatch.confidence === 1) {
97372
+ break;
97373
+ }
97374
+ }
97375
+ if (bestMatch) {
97376
+ return bestMatch;
97377
+ }
97378
+ if (exactMatch.confidence > 0.5) {
97379
+ return {
97380
+ found: true,
97381
+ lineNumber: expectedLine,
97382
+ offset: 0,
97383
+ confidence: exactMatch.confidence
97384
+ };
97385
+ }
97386
+ return {
97387
+ found: false,
97388
+ lineNumber: -1,
97389
+ offset: 0,
97390
+ confidence: 0
97391
+ };
97392
+ };
97393
+ var isHunkApplied = (fileContent, hunk, options2 = {}) => {
97394
+ const fullOptions = {
97395
+ ...DEFAULT_MATCH_OPTIONS,
97396
+ ...options2
97397
+ };
97398
+ const fileLines = fileContent.split(`
97399
+ `);
97400
+ let additionsPresent = 0;
97401
+ let deletionsAbsent = 0;
97402
+ for (const line2 of hunk.lines) {
97403
+ const normalizedContent = normalizeLine(line2.content, fullOptions);
97404
+ if (line2.type === "addition") {
97405
+ const found = fileLines.some((fl) => normalizeLine(fl, fullOptions) === normalizedContent);
97406
+ if (found)
97407
+ additionsPresent++;
97408
+ }
97409
+ if (line2.type === "deletion") {
97410
+ const found = fileLines.some((fl) => normalizeLine(fl, fullOptions) === normalizedContent);
97411
+ if (!found)
97412
+ deletionsAbsent++;
97413
+ }
97414
+ }
97415
+ const totalAdditions = hunk.lines.filter((l) => l.type === "addition").length;
97416
+ const totalDeletions = hunk.lines.filter((l) => l.type === "deletion").length;
97417
+ const additionsMatch = totalAdditions === 0 || additionsPresent >= totalAdditions * 0.8;
97418
+ const deletionsMatch = totalDeletions === 0 || deletionsAbsent >= totalDeletions * 0.8;
97419
+ return additionsMatch && deletionsMatch;
97420
+ };
97421
+ var previewHunkApplication = (fileContent, hunk, position) => {
97422
+ const fileLines = fileContent.split(`
97423
+ `);
97424
+ const resultLines = [];
97425
+ for (let i2 = 0;i2 < position; i2++) {
97426
+ resultLines.push(fileLines[i2]);
97427
+ }
97428
+ let originalLinesConsumed = 0;
97429
+ for (const line2 of hunk.lines) {
97430
+ if (line2.type === "context" || line2.type === "deletion") {
97431
+ originalLinesConsumed++;
97432
+ }
97433
+ }
97434
+ for (const line2 of hunk.lines) {
97435
+ if (line2.type === "context") {
97436
+ resultLines.push(line2.content);
97437
+ } else if (line2.type === "addition") {
97438
+ resultLines.push(line2.content);
97439
+ }
97440
+ }
97441
+ for (let i2 = position + originalLinesConsumed;i2 < fileLines.length; i2++) {
97442
+ resultLines.push(fileLines[i2]);
97443
+ }
97444
+ return {
97445
+ success: true,
97446
+ preview: resultLines
97447
+ };
97448
+ };
97449
+
97450
+ // src/tools/apply-patch/execute.ts
97451
+ var rollbackStore = new Map;
97452
+ var executeApplyPatch = async (params, ctx) => {
97453
+ try {
97454
+ const parsedPatch = parsePatch2(params.patch);
97455
+ const validation = validatePatch(parsedPatch);
97456
+ if (!validation.valid) {
97457
+ return {
97458
+ success: false,
97459
+ title: PATCH_TITLES.FAILED,
97460
+ output: "",
97461
+ error: validation.errors.join(`
97462
+ `)
97463
+ };
97464
+ }
97465
+ const results = [];
97466
+ let totalPatched = 0;
97467
+ let totalFailed = 0;
97468
+ for (let filePatch of parsedPatch.files) {
97469
+ if (filePatch.isBinary) {
97470
+ results.push({
97471
+ success: true,
97472
+ filePath: getTargetPath(filePatch),
97473
+ hunksApplied: 0,
97474
+ hunksFailed: 0,
97475
+ hunkResults: [],
97476
+ error: PATCH_MESSAGES.SKIPPED_BINARY(getTargetPath(filePatch))
97477
+ });
97478
+ continue;
97479
+ }
97480
+ if (params.reverse) {
97481
+ filePatch = reversePatch(filePatch);
97482
+ }
97483
+ const targetPath = params.targetFile ?? getTargetPath(filePatch);
97484
+ const absolutePath = isAbsolute2(targetPath) ? targetPath : join9(ctx.workingDir, targetPath);
97485
+ const result = await applyFilePatch(filePatch, absolutePath, {
97486
+ fuzz: params.fuzz ?? PATCH_DEFAULTS.FUZZ,
97487
+ dryRun: params.dryRun ?? false
97488
+ });
97489
+ results.push(result);
97490
+ if (result.success) {
97491
+ totalPatched++;
97492
+ } else {
97493
+ totalFailed++;
97494
+ }
97495
+ }
97496
+ const output = formatPatchResults(results, params.dryRun ?? false);
97497
+ const success3 = totalFailed === 0;
97498
+ const title = params.dryRun ? PATCH_TITLES.DRY_RUN : totalFailed === 0 ? PATCH_TITLES.SUCCESS(totalPatched) : totalPatched > 0 ? PATCH_TITLES.PARTIAL(totalPatched, totalFailed) : PATCH_TITLES.FAILED;
97499
+ return {
97500
+ success: success3,
97501
+ title,
97502
+ output,
97503
+ error: success3 ? undefined : `${totalFailed} file(s) failed to patch`
97504
+ };
97505
+ } catch (error49) {
97506
+ const message2 = error49 instanceof Error ? error49.message : String(error49);
97507
+ return {
97508
+ success: false,
97509
+ title: PATCH_TITLES.FAILED,
97510
+ output: "",
97511
+ error: PATCH_ERRORS.PARSE_FAILED(message2)
97512
+ };
97513
+ }
97514
+ };
97515
+ var applyFilePatch = async (filePatch, targetPath, options2) => {
97516
+ const hunkResults = [];
97517
+ let currentContent;
97518
+ let originalContent;
97519
+ try {
97520
+ if (filePatch.isNew) {
97521
+ currentContent = "";
97522
+ originalContent = "";
97523
+ } else {
97524
+ try {
97525
+ currentContent = await fs14.readFile(targetPath, "utf-8");
97526
+ originalContent = currentContent;
97527
+ } catch {
97528
+ return {
97529
+ success: false,
97530
+ filePath: targetPath,
97531
+ hunksApplied: 0,
97532
+ hunksFailed: filePatch.hunks.length,
97533
+ hunkResults: [],
97534
+ error: PATCH_ERRORS.FILE_NOT_FOUND(targetPath)
97535
+ };
97536
+ }
97537
+ }
97538
+ if (filePatch.isDeleted) {
97539
+ if (!options2.dryRun) {
97540
+ rollbackStore.set(targetPath, {
97541
+ filePath: targetPath,
97542
+ originalContent,
97543
+ patchedContent: "",
97544
+ timestamp: Date.now()
97545
+ });
97546
+ await fs14.unlink(targetPath);
97547
+ }
97548
+ return {
97549
+ success: true,
97550
+ filePath: targetPath,
97551
+ hunksApplied: 1,
97552
+ hunksFailed: 0,
97553
+ hunkResults: [
97554
+ {
97555
+ success: true,
97556
+ hunkIndex: 0,
97557
+ appliedAt: 0
97558
+ }
97559
+ ],
97560
+ newContent: ""
97561
+ };
97562
+ }
97563
+ let hunksApplied = 0;
97564
+ let hunksFailed = 0;
97565
+ for (let i2 = 0;i2 < filePatch.hunks.length; i2++) {
97566
+ const hunk = filePatch.hunks[i2];
97567
+ if (isHunkApplied(currentContent, hunk, { fuzz: options2.fuzz })) {
97568
+ hunkResults.push({
97569
+ success: true,
97570
+ hunkIndex: i2,
97571
+ appliedAt: hunk.oldStart - 1
97572
+ });
97573
+ hunksApplied++;
97574
+ continue;
97575
+ }
97576
+ const position = findHunkPosition(currentContent, hunk, { fuzz: options2.fuzz });
97577
+ if (!position.found) {
97578
+ hunkResults.push({
97579
+ success: false,
97580
+ hunkIndex: i2,
97581
+ error: PATCH_ERRORS.FUZZY_MATCH_FAILED(i2)
97582
+ });
97583
+ hunksFailed++;
97584
+ continue;
97585
+ }
97586
+ const preview = previewHunkApplication(currentContent, hunk, position.lineNumber);
97587
+ if (!preview.success) {
97588
+ hunkResults.push({
97589
+ success: false,
97590
+ hunkIndex: i2,
97591
+ error: preview.error ?? PATCH_ERRORS.HUNK_FAILED(i2, "unknown")
97592
+ });
97593
+ hunksFailed++;
97594
+ continue;
97595
+ }
97596
+ currentContent = preview.preview.join(`
97597
+ `);
97598
+ hunksApplied++;
97599
+ hunkResults.push({
97600
+ success: true,
97601
+ hunkIndex: i2,
97602
+ appliedAt: position.lineNumber,
97603
+ fuzzyOffset: position.offset !== 0 ? position.offset : undefined
97604
+ });
97605
+ }
97606
+ if (!options2.dryRun && hunksApplied > 0) {
97607
+ rollbackStore.set(targetPath, {
97608
+ filePath: targetPath,
97609
+ originalContent,
97610
+ patchedContent: currentContent,
97611
+ timestamp: Date.now()
97612
+ });
97613
+ await fs14.mkdir(dirname2(targetPath), { recursive: true });
97614
+ await fs14.writeFile(targetPath, currentContent, "utf-8");
97615
+ }
97616
+ return {
97617
+ success: hunksFailed === 0,
97618
+ filePath: targetPath,
97619
+ hunksApplied,
97620
+ hunksFailed,
97621
+ hunkResults,
97622
+ newContent: currentContent
97623
+ };
97624
+ } catch (error49) {
97625
+ const message2 = error49 instanceof Error ? error49.message : String(error49);
97626
+ return {
97627
+ success: false,
97628
+ filePath: targetPath,
97629
+ hunksApplied: 0,
97630
+ hunksFailed: filePatch.hunks.length,
97631
+ hunkResults,
97632
+ error: PATCH_ERRORS.WRITE_FAILED(targetPath, message2)
97633
+ };
97634
+ }
97635
+ };
97636
+ var formatPatchResults = (results, dryRun) => {
97637
+ const lines = [];
97638
+ for (const result of results) {
97639
+ lines.push(`${result.success ? "✓" : "✗"} ${result.filePath}`);
97640
+ if (result.hunksApplied > 0 || result.hunksFailed > 0) {
97641
+ lines.push(` ${result.hunksApplied} hunk(s) applied, ${result.hunksFailed} failed`);
97642
+ }
97643
+ for (const hunk of result.hunkResults) {
97644
+ if (hunk.fuzzyOffset) {
97645
+ lines.push(` ${PATCH_MESSAGES.FUZZY_APPLIED(hunk.hunkIndex, hunk.fuzzyOffset)}`);
97646
+ }
97647
+ }
97648
+ if (result.error) {
97649
+ lines.push(` Error: ${result.error}`);
97650
+ }
97651
+ }
97652
+ if (dryRun) {
97653
+ lines.push("");
97654
+ lines.push("(dry run - no changes were made)");
97655
+ } else if (results.some((r) => r.success)) {
97656
+ lines.push("");
97657
+ lines.push(PATCH_MESSAGES.ROLLBACK_AVAILABLE);
97658
+ }
97659
+ return lines.join(`
97660
+ `);
97661
+ };
97662
+
97663
+ // src/tools/apply-patch/index.ts
97664
+ var APPLY_PATCH_DESCRIPTION = `Apply a unified diff patch to one or more files.
97665
+
97666
+ Use this tool to:
97667
+ - Apply changes from a diff/patch
97668
+ - Update files based on patch content
97669
+ - Preview changes before applying (dry run)
97670
+
97671
+ Parameters:
97672
+ - patch: The unified diff content (required)
97673
+ - targetFile: Override the target file path (optional)
97674
+ - dryRun: Preview without applying changes (default: false)
97675
+ - fuzz: Context line tolerance 0-3 (default: 2)
97676
+ - reverse: Apply patch in reverse to undo changes (default: false)
97677
+
97678
+ The tool supports:
97679
+ - Standard unified diff format (git diff, diff -u)
97680
+ - Fuzzy context matching when lines have shifted
97681
+ - Creating new files
97682
+ - Deleting files
97683
+ - Rollback on failure
97684
+
97685
+ Example patch format:
97686
+ \`\`\`
97687
+ --- a/src/example.ts
97688
+ +++ b/src/example.ts
97689
+ @@ -10,6 +10,7 @@ function example() {
97690
+ const a = 1;
97691
+ const b = 2;
97692
+ + const c = 3;
97693
+ return a + b;
97694
+ }
97695
+ \`\`\``;
97696
+ var applyPatchTool = {
97697
+ name: "apply_patch",
97698
+ description: APPLY_PATCH_DESCRIPTION,
97699
+ parameters: applyPatchParams,
97700
+ execute: executeApplyPatch
97701
+ };
95970
97702
  // src/services/mcp/tools.ts
95971
97703
  init_manager();
95972
97704
  var getMCPToolsForApi = async () => {
@@ -96056,12 +97788,15 @@ var tools = [
96056
97788
  readTool,
96057
97789
  writeTool,
96058
97790
  editTool,
97791
+ multiEditTool,
96059
97792
  globToolDefinition,
96060
97793
  grepToolDefinition,
96061
97794
  todoWriteTool,
96062
97795
  todoReadTool,
96063
97796
  webSearchTool,
96064
- lspTool
97797
+ webFetchTool,
97798
+ lspTool,
97799
+ applyPatchTool
96065
97800
  ];
96066
97801
  var READ_ONLY_TOOLS = new Set([
96067
97802
  "read",
@@ -96069,6 +97804,7 @@ var READ_ONLY_TOOLS = new Set([
96069
97804
  "grep",
96070
97805
  "todo_read",
96071
97806
  "web_search",
97807
+ "web_fetch",
96072
97808
  "lsp"
96073
97809
  ]);
96074
97810
  var toolMap = new Map(tools.map((t2) => [t2.name, t2]));
@@ -98029,17 +99765,17 @@ var isCorrection = (message2) => {
98029
99765
  return feedback.type === "negative" && feedback.confidence >= 0.6;
98030
99766
  };
98031
99767
  // src/services/provider-quality/persistence.ts
98032
- import { join as join11 } from "path";
99768
+ import { join as join12 } from "path";
98033
99769
  import { homedir as homedir3 } from "os";
98034
- var QUALITY_DATA_DIR = join11(homedir3(), ".config", "codetyper");
99770
+ var QUALITY_DATA_DIR = join12(homedir3(), ".config", "codetyper");
98035
99771
  var QUALITY_DATA_FILE = "provider-quality.json";
98036
99772
  var getQualityDataPath = () => {
98037
- return join11(QUALITY_DATA_DIR, QUALITY_DATA_FILE);
99773
+ return join12(QUALITY_DATA_DIR, QUALITY_DATA_FILE);
98038
99774
  };
98039
99775
  var ensureDataDir = async () => {
98040
- const fs14 = await import("fs/promises");
99776
+ const fs17 = await import("fs/promises");
98041
99777
  try {
98042
- await fs14.mkdir(QUALITY_DATA_DIR, { recursive: true });
99778
+ await fs17.mkdir(QUALITY_DATA_DIR, { recursive: true });
98043
99779
  } catch {}
98044
99780
  };
98045
99781
  var createDefaultScores = () => {
@@ -98066,20 +99802,20 @@ var createDefaultScores = () => {
98066
99802
  return scores;
98067
99803
  };
98068
99804
  var loadQualityData = async () => {
98069
- const fs14 = await import("fs/promises");
99805
+ const fs17 = await import("fs/promises");
98070
99806
  const filePath2 = getQualityDataPath();
98071
99807
  try {
98072
- const content = await fs14.readFile(filePath2, "utf-8");
99808
+ const content = await fs17.readFile(filePath2, "utf-8");
98073
99809
  return JSON.parse(content);
98074
99810
  } catch {
98075
99811
  return {};
98076
99812
  }
98077
99813
  };
98078
99814
  var saveQualityData = async (data) => {
98079
- const fs14 = await import("fs/promises");
99815
+ const fs17 = await import("fs/promises");
98080
99816
  await ensureDataDir();
98081
99817
  const filePath2 = getQualityDataPath();
98082
- await fs14.writeFile(filePath2, JSON.stringify(data, null, 2));
99818
+ await fs17.writeFile(filePath2, JSON.stringify(data, null, 2));
98083
99819
  };
98084
99820
  var getProviderQuality = async (providerId) => {
98085
99821
  const allData = await loadQualityData();
@@ -98637,7 +100373,7 @@ var handleMessage = async (state4, message2, callbacks) => {
98637
100373
  }
98638
100374
  if (isReadOnlyMode) {
98639
100375
  const modeLabel = interactionMode === "ask" ? "Ask" : "Code Review";
98640
- callbacks.onLog("system", `${modeLabel} mode: Read-only tools only (Ctrl+Tab to switch modes)`);
100376
+ callbacks.onLog("system", `${modeLabel} mode: Read-only tools only (Ctrl+M to switch modes)`);
98641
100377
  }
98642
100378
  let processedMessage = await processFileReferences(state4, message2);
98643
100379
  if (interactionMode === "code-review") {
@@ -99229,7 +100965,7 @@ await init_providers2();
99229
100965
  // src/services/hooks-service.ts
99230
100966
  import { spawn as spawn7 } from "child_process";
99231
100967
  import { readFile as readFile7, access, constants as constants2 } from "fs/promises";
99232
- import { join as join12, isAbsolute as isAbsolute2, resolve as resolve6 } from "path";
100968
+ import { join as join13, isAbsolute as isAbsolute3, resolve as resolve6 } from "path";
99233
100969
 
99234
100970
  // src/constants/hooks.ts
99235
100971
  var HOOKS_CONFIG_FILE = "hooks.json";
@@ -99264,8 +101000,8 @@ var loadHooksFromFile = async (filePath2) => {
99264
101000
  }
99265
101001
  };
99266
101002
  var loadHooks = async (workingDir3) => {
99267
- const globalPath = join12(DIRS.config, HOOKS_CONFIG_FILE);
99268
- const localPath = join12(workingDir3, LOCAL_CONFIG_DIR, HOOKS_CONFIG_FILE);
101003
+ const globalPath = join13(DIRS.config, HOOKS_CONFIG_FILE);
101004
+ const localPath = join13(workingDir3, LOCAL_CONFIG_DIR, HOOKS_CONFIG_FILE);
99269
101005
  const [globalHooks, localHooks] = await Promise.all([
99270
101006
  loadHooksFromFile(globalPath),
99271
101007
  loadHooksFromFile(localPath)
@@ -99282,7 +101018,7 @@ var getHooksForEvent = (event) => {
99282
101018
  return allHooks.filter((hook) => hook.event === event);
99283
101019
  };
99284
101020
  var resolveScriptPath = (script, workingDir3) => {
99285
- if (isAbsolute2(script)) {
101021
+ if (isAbsolute3(script)) {
99286
101022
  return script;
99287
101023
  }
99288
101024
  return resolve6(workingDir3, script);
@@ -99772,7 +101508,7 @@ var {
99772
101508
  const clearContexts = () => {
99773
101509
  setStore("contextStack", []);
99774
101510
  };
99775
- const register = (binding) => {
101511
+ const register2 = (binding) => {
99776
101512
  const id = generateKeybindId();
99777
101513
  const fullBinding = {
99778
101514
  ...binding,
@@ -99834,7 +101570,7 @@ var {
99834
101570
  pushContext,
99835
101571
  popContext,
99836
101572
  clearContexts,
99837
- register,
101573
+ register: register2,
99838
101574
  unregister,
99839
101575
  enable,
99840
101576
  disable,
@@ -100224,7 +101960,7 @@ function InputArea(props) {
100224
101960
  };
100225
101961
  const isMenuOpen = createMemo(() => {
100226
101962
  const mode = app.mode();
100227
- return app.commandMenu().isOpen || mode === "command_menu" || mode === "model_select" || mode === "theme_select" || mode === "agent_select" || mode === "mode_select" || mode === "mcp_select" || mode === "mcp_add" || mode === "file_picker" || mode === "permission_prompt" || mode === "learning_prompt" || mode === "help_menu" || mode === "help_detail";
101963
+ return app.commandMenu().isOpen || mode === "command_menu" || mode === "model_select" || mode === "theme_select" || mode === "agent_select" || mode === "mode_select" || mode === "mcp_select" || mode === "mcp_add" || mode === "file_picker" || mode === "permission_prompt" || mode === "learning_prompt" || mode === "help_menu" || mode === "help_detail" || mode === "brain_menu" || mode === "brain_login" || mode === "provider_select" || mode === "mcp_browse";
100228
101964
  });
100229
101965
  const placeholder = () => props.placeholder ?? "Ask anything... (@ for files, / for commands)";
100230
101966
  const borderColor = createMemo(() => {
@@ -100235,7 +101971,7 @@ function InputArea(props) {
100235
101971
  return theme.colors.border;
100236
101972
  });
100237
101973
  useKeyboard((evt) => {
100238
- if (evt.ctrl && evt.name === "tab") {
101974
+ if (evt.ctrl && evt.name === "m") {
100239
101975
  app.toggleInteractionMode();
100240
101976
  evt.preventDefault();
100241
101977
  evt.stopPropagation();
@@ -100404,7 +102140,9 @@ var MODE_DISPLAY_CONFIG = {
100404
102140
  provider_select: { text: "Select Provider", color: "magenta" },
100405
102141
  learning_prompt: { text: "Save Learning?", color: "cyan" },
100406
102142
  help_menu: { text: "Help", color: "cyan" },
100407
- help_detail: { text: "Help Detail", color: "cyan" }
102143
+ help_detail: { text: "Help Detail", color: "cyan" },
102144
+ brain_menu: { text: "Brain Settings", color: "magenta" },
102145
+ brain_login: { text: "Brain Login", color: "magenta" }
100408
102146
  };
100409
102147
  var DEFAULT_MODE_DISPLAY = {
100410
102148
  text: "Ready",
@@ -100481,6 +102219,11 @@ var SLASH_COMMANDS = [
100481
102219
  name: "logout",
100482
102220
  description: "Sign out from provider",
100483
102221
  category: "account"
102222
+ },
102223
+ {
102224
+ name: "brain",
102225
+ description: "Configure CodeTyper Brain (memory & knowledge)",
102226
+ category: "account"
100484
102227
  }
100485
102228
  ];
100486
102229
  var COMMAND_CATEGORIES = [
@@ -100492,10 +102235,11 @@ var COMMAND_CATEGORIES = [
100492
102235
 
100493
102236
  // src/tui-solid/components/command-menu.tsx
100494
102237
  var filterCommands = (commands, filter2) => {
102238
+ let availableCommands = BRAIN_DISABLED ? commands.filter((cmd) => cmd.name !== "brain") : [...commands];
100495
102239
  if (!filter2)
100496
- return [...commands];
102240
+ return availableCommands;
100497
102241
  const query = filter2.toLowerCase();
100498
- return commands.filter((cmd) => cmd.name.toLowerCase().includes(query) || cmd.description.toLowerCase().includes(query));
102242
+ return availableCommands.filter((cmd) => cmd.name.toLowerCase().includes(query) || cmd.description.toLowerCase().includes(query));
100499
102243
  };
100500
102244
  var groupCommandsByCategory = (commands) => {
100501
102245
  return COMMAND_CATEGORIES.map((cat) => ({
@@ -101445,9 +103189,24 @@ function CenteredModal(props) {
101445
103189
 
101446
103190
  // src/constants/home.ts
101447
103191
  var HOME_VARS = {
101448
- title: "Welcome to CodeTyper - Your AI Coding Assistant",
101449
- subTitle: "Type a prompt below to start a new session"
101450
- };
103192
+ subTitle: "Type a prompt below to start"
103193
+ };
103194
+ var ASCII_LOGO = [
103195
+ " ██████╗ ██████╗ ██████╗ ███████╗ ████████╗ ██╗ ██╗ ██████╗ ███████╗ ██████╗ ",
103196
+ "██╔════╝ ██╔═══██╗ ██╔══██╗ ██╔════╝ ╚══██╔══╝ ╚██╗ ██╔╝ ██╔══██╗ ██╔════╝ ██╔══██╗",
103197
+ "██║ ██║ ██║ ██║ ██║ █████╗ ██║ ╚████╔╝ ██████╔╝ █████╗ ██████╔╝",
103198
+ "██║ ██║ ██║ ██║ ██║ ██╔══╝ ██║ ╚██╔╝ ██╔═══╝ ██╔══╝ ██╔══██╗",
103199
+ "╚██████╗ ╚██████╔╝ ██████╔╝ ███████╗ ██║ ██║ ██║ ███████╗ ██║ ██║",
103200
+ " ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝"
103201
+ ];
103202
+ var ASCII_LOGO_GRADIENT = [
103203
+ "#00FFFF",
103204
+ "#00D4FF",
103205
+ "#00AAFF",
103206
+ "#0080FF",
103207
+ "#0055FF",
103208
+ "#AA00FF"
103209
+ ];
101451
103210
 
101452
103211
  // src/tui-solid/routes/home.tsx
101453
103212
  function Home(props) {
@@ -101466,9 +103225,9 @@ function Home(props) {
101466
103225
  app.setMode("idle");
101467
103226
  };
101468
103227
  return (() => {
101469
- var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("box"), _el$4 = createElement("text"), _el$5 = createElement("text"), _el$6 = createElement("box");
103228
+ var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("box"), _el$4 = createElement("text"), _el$5 = createElement("box");
101470
103229
  insertNode(_el$, _el$2);
101471
- insertNode(_el$, _el$6);
103230
+ insertNode(_el$, _el$5);
101472
103231
  setProp(_el$, "flexDirection", "column");
101473
103232
  setProp(_el$, "flexGrow", 1);
101474
103233
  insertNode(_el$2, _el$3);
@@ -101478,14 +103237,10 @@ function Home(props) {
101478
103237
  setProp(_el$2, "flexDirection", "column");
101479
103238
  insert(_el$2, createComponent2(Logo, {}), _el$3);
101480
103239
  insertNode(_el$3, _el$4);
101481
- insertNode(_el$3, _el$5);
101482
103240
  setProp(_el$3, "marginTop", 2);
101483
- setProp(_el$3, "flexDirection", "column");
101484
- setProp(_el$3, "alignItems", "center");
101485
- insert(_el$4, () => HOME_VARS.title);
101486
- insert(_el$5, () => HOME_VARS.subTitle);
101487
- setProp(_el$6, "marginTop", 2);
101488
- insert(_el$6, createComponent2(InputArea, {
103241
+ insert(_el$4, () => HOME_VARS.subTitle);
103242
+ setProp(_el$5, "marginTop", 2);
103243
+ insert(_el$5, createComponent2(InputArea, {
101489
103244
  onSubmit: handleSubmit,
101490
103245
  placeholder: "What would you like to build today?"
101491
103246
  }));
@@ -101586,15 +103341,13 @@ function Home(props) {
101586
103341
  }
101587
103342
  }), null);
101588
103343
  effect((_p$) => {
101589
- var _v$ = theme.colors.background, _v$2 = theme.colors.textDim, _v$3 = theme.colors.textDim;
103344
+ var _v$ = theme.colors.background, _v$2 = theme.colors.textDim;
101590
103345
  _v$ !== _p$.e && (_p$.e = setProp(_el$, "backgroundColor", _v$, _p$.e));
101591
103346
  _v$2 !== _p$.t && (_p$.t = setProp(_el$4, "fg", _v$2, _p$.t));
101592
- _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
101593
103347
  return _p$;
101594
103348
  }, {
101595
103349
  e: undefined,
101596
- t: undefined,
101597
- a: undefined
103350
+ t: undefined
101598
103351
  });
101599
103352
  return _el$;
101600
103353
  })();
@@ -101629,6 +103382,17 @@ await __promiseAll([
101629
103382
  init_theme2(),
101630
103383
  init_app()
101631
103384
  ]);
103385
+
103386
+ // src/constants/token.ts
103387
+ var TOKEN_WARNING_THRESHOLD = 0.75;
103388
+ var TOKEN_CRITICAL_THRESHOLD = 0.9;
103389
+ var PRUNE_PROTECTED_TOOLS = new Set([
103390
+ "skill",
103391
+ "todo_read",
103392
+ "todo_write"
103393
+ ]);
103394
+
103395
+ // src/tui-solid/components/header.tsx
101632
103396
  var MODE_LABELS = {
101633
103397
  agent: "Agent",
101634
103398
  ask: "Ask",
@@ -101644,6 +103408,24 @@ var MODE_COLORS = {
101644
103408
  ask: "info",
101645
103409
  "code-review": "success"
101646
103410
  };
103411
+ var BRAIN_STATUS_COLORS = {
103412
+ connected: "success",
103413
+ connecting: "warning",
103414
+ disconnected: "textDim",
103415
+ error: "error"
103416
+ };
103417
+ var TOKEN_STATUS_COLORS = {
103418
+ normal: "textDim",
103419
+ warning: "warning",
103420
+ critical: "error",
103421
+ compacting: "info"
103422
+ };
103423
+ var formatTokenCount = (tokens) => {
103424
+ if (tokens >= 1000) {
103425
+ return `${(tokens / 1000).toFixed(1)}K`;
103426
+ }
103427
+ return tokens.toString();
103428
+ };
101647
103429
  function Header(props) {
101648
103430
  const theme = useTheme();
101649
103431
  const app = useAppStore();
@@ -101652,119 +103434,274 @@ function Header(props) {
101652
103434
  const colorKey = MODE_COLORS[app.interactionMode()];
101653
103435
  return theme.colors[colorKey];
101654
103436
  });
103437
+ const brainColor = createMemo(() => {
103438
+ const brain = app.brain();
103439
+ const colorKey = BRAIN_STATUS_COLORS[brain.status];
103440
+ return theme.colors[colorKey];
103441
+ });
103442
+ const shouldShowBrainBanner = createMemo(() => {
103443
+ if (BRAIN_DISABLED)
103444
+ return false;
103445
+ const brain = app.brain();
103446
+ return brain.showBanner && brain.status === "disconnected";
103447
+ });
103448
+ const contextUsage = createMemo(() => {
103449
+ const stats = app.sessionStats();
103450
+ const totalTokens = stats.inputTokens + stats.outputTokens;
103451
+ const maxTokens = stats.contextMaxTokens;
103452
+ const usagePercent = maxTokens > 0 ? totalTokens / maxTokens * 100 : 0;
103453
+ let status2 = "normal";
103454
+ if (app.isCompacting()) {
103455
+ status2 = "compacting";
103456
+ } else if (usagePercent >= TOKEN_CRITICAL_THRESHOLD * 100) {
103457
+ status2 = "critical";
103458
+ } else if (usagePercent >= TOKEN_WARNING_THRESHOLD * 100) {
103459
+ status2 = "warning";
103460
+ }
103461
+ return {
103462
+ current: totalTokens,
103463
+ max: maxTokens,
103464
+ percent: usagePercent,
103465
+ status: status2
103466
+ };
103467
+ });
103468
+ const tokenColor = createMemo(() => {
103469
+ const colorKey = TOKEN_STATUS_COLORS[contextUsage().status];
103470
+ return theme.colors[colorKey];
103471
+ });
101655
103472
  return (() => {
101656
- var _el$ = createElement("box"), _el$2 = createElement("box"), _el$5 = createElement("text"), _el$6 = createTextNode(`v`), _el$7 = createElement("text"), _el$9 = createElement("box"), _el$0 = createElement("text"), _el$1 = createTextNode(`[`), _el$10 = createTextNode(`]`), _el$14 = createElement("text"), _el$15 = createTextNode(` - `), _el$17 = createElement("box"), _el$18 = createElement("box"), _el$19 = createElement("text"), _el$21 = createElement("text"), _el$22 = createElement("box"), _el$23 = createElement("text"), _el$25 = createElement("text");
101657
- insertNode(_el$, _el$2);
101658
- insertNode(_el$, _el$17);
101659
- setProp(_el$, "flexDirection", "row");
101660
- setProp(_el$, "justifyContent", "space-between");
101661
- setProp(_el$, "paddingLeft", 1);
101662
- setProp(_el$, "paddingRight", 1);
101663
- setProp(_el$, "border", ["bottom"]);
101664
- insertNode(_el$2, _el$5);
101665
- insertNode(_el$2, _el$7);
101666
- insertNode(_el$2, _el$9);
101667
- setProp(_el$2, "flexDirection", "row");
101668
- setProp(_el$2, "gap", 1);
101669
- insert(_el$2, createComponent2(Show, {
103473
+ var _el$ = createElement("box"), _el$11 = createElement("box"), _el$12 = createElement("box"), _el$15 = createElement("text"), _el$16 = createTextNode(`v`), _el$17 = createElement("text"), _el$19 = createElement("box"), _el$20 = createElement("text"), _el$21 = createTextNode(`[`), _el$22 = createTextNode(`]`), _el$26 = createElement("text"), _el$27 = createTextNode(` - `), _el$29 = createElement("box"), _el$43 = createElement("box"), _el$44 = createElement("text"), _el$46 = createElement("text"), _el$47 = createElement("box"), _el$48 = createElement("text"), _el$50 = createElement("text");
103474
+ insertNode(_el$, _el$11);
103475
+ setProp(_el$, "flexDirection", "column");
103476
+ insert(_el$, createComponent2(Show, {
103477
+ get when() {
103478
+ return shouldShowBrainBanner();
103479
+ },
103480
+ get children() {
103481
+ var _el$2 = createElement("box"), _el$3 = createElement("box"), _el$4 = createElement("text"), _el$5 = createElement("text"), _el$6 = createElement("text"), _el$8 = createElement("text"), _el$9 = createTextNode(`:`), _el$0 = createElement("text"), _el$1 = createElement("text");
103482
+ insertNode(_el$2, _el$3);
103483
+ insertNode(_el$2, _el$1);
103484
+ setProp(_el$2, "flexDirection", "row");
103485
+ setProp(_el$2, "justifyContent", "space-between");
103486
+ setProp(_el$2, "paddingLeft", 1);
103487
+ setProp(_el$2, "paddingRight", 1);
103488
+ setProp(_el$2, "backgroundColor", "#1a1a2e");
103489
+ insertNode(_el$3, _el$4);
103490
+ insertNode(_el$3, _el$5);
103491
+ insertNode(_el$3, _el$6);
103492
+ insertNode(_el$3, _el$8);
103493
+ insertNode(_el$3, _el$0);
103494
+ setProp(_el$3, "flexDirection", "row");
103495
+ setProp(_el$3, "gap", 1);
103496
+ setProp(_el$4, "fg", "#ff69b4");
103497
+ insert(_el$4, () => BRAIN_BANNER.EMOJI_CONNECTED);
103498
+ setProp(_el$5, "fg", "#ffffff");
103499
+ insert(_el$5, () => BRAIN_BANNER.TITLE);
103500
+ insertNode(_el$6, createTextNode(`-`));
103501
+ insertNode(_el$8, _el$9);
103502
+ insert(_el$8, () => BRAIN_BANNER.CTA, _el$9);
103503
+ insert(_el$0, () => BRAIN_BANNER.URL);
103504
+ insertNode(_el$1, createTextNode(`[Ctrl+B dismiss]`));
103505
+ effect((_p$) => {
103506
+ var _v$ = TextAttributes.BOLD, _v$2 = TextAttributes.BOLD, _v$3 = theme.colors.textDim, _v$4 = theme.colors.textDim, _v$5 = theme.colors.info, _v$6 = TextAttributes.UNDERLINE, _v$7 = theme.colors.textDim;
103507
+ _v$ !== _p$.e && (_p$.e = setProp(_el$4, "attributes", _v$, _p$.e));
103508
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$5, "attributes", _v$2, _p$.t));
103509
+ _v$3 !== _p$.a && (_p$.a = setProp(_el$6, "fg", _v$3, _p$.a));
103510
+ _v$4 !== _p$.o && (_p$.o = setProp(_el$8, "fg", _v$4, _p$.o));
103511
+ _v$5 !== _p$.i && (_p$.i = setProp(_el$0, "fg", _v$5, _p$.i));
103512
+ _v$6 !== _p$.n && (_p$.n = setProp(_el$0, "attributes", _v$6, _p$.n));
103513
+ _v$7 !== _p$.s && (_p$.s = setProp(_el$1, "fg", _v$7, _p$.s));
103514
+ return _p$;
103515
+ }, {
103516
+ e: undefined,
103517
+ t: undefined,
103518
+ a: undefined,
103519
+ o: undefined,
103520
+ i: undefined,
103521
+ n: undefined,
103522
+ s: undefined
103523
+ });
103524
+ return _el$2;
103525
+ }
103526
+ }), _el$11);
103527
+ insertNode(_el$11, _el$12);
103528
+ insertNode(_el$11, _el$29);
103529
+ setProp(_el$11, "flexDirection", "row");
103530
+ setProp(_el$11, "justifyContent", "space-between");
103531
+ setProp(_el$11, "paddingLeft", 1);
103532
+ setProp(_el$11, "paddingRight", 1);
103533
+ setProp(_el$11, "border", ["bottom"]);
103534
+ insertNode(_el$12, _el$15);
103535
+ insertNode(_el$12, _el$17);
103536
+ insertNode(_el$12, _el$19);
103537
+ setProp(_el$12, "flexDirection", "row");
103538
+ setProp(_el$12, "gap", 1);
103539
+ insert(_el$12, createComponent2(Show, {
101670
103540
  get when() {
101671
103541
  return showBanner();
101672
103542
  },
101673
103543
  get children() {
101674
- var _el$3 = createElement("text");
101675
- insertNode(_el$3, createTextNode(`CodeTyper`));
103544
+ var _el$13 = createElement("text");
103545
+ insertNode(_el$13, createTextNode(`CodeTyper`));
101676
103546
  effect((_p$) => {
101677
- var _v$ = theme.colors.primary, _v$2 = TextAttributes.BOLD;
101678
- _v$ !== _p$.e && (_p$.e = setProp(_el$3, "fg", _v$, _p$.e));
101679
- _v$2 !== _p$.t && (_p$.t = setProp(_el$3, "attributes", _v$2, _p$.t));
103547
+ var _v$8 = theme.colors.primary, _v$9 = TextAttributes.BOLD;
103548
+ _v$8 !== _p$.e && (_p$.e = setProp(_el$13, "fg", _v$8, _p$.e));
103549
+ _v$9 !== _p$.t && (_p$.t = setProp(_el$13, "attributes", _v$9, _p$.t));
101680
103550
  return _p$;
101681
103551
  }, {
101682
103552
  e: undefined,
101683
103553
  t: undefined
101684
103554
  });
101685
- return _el$3;
103555
+ return _el$13;
101686
103556
  }
101687
- }), _el$5);
101688
- insertNode(_el$5, _el$6);
101689
- insert(_el$5, () => app.version(), null);
101690
- insertNode(_el$7, createTextNode(`|`));
101691
- insertNode(_el$9, _el$0);
101692
- insertNode(_el$9, _el$14);
101693
- setProp(_el$9, "flexDirection", "row");
101694
- insertNode(_el$0, _el$1);
101695
- insertNode(_el$0, _el$10);
101696
- insert(_el$0, () => MODE_LABELS[app.interactionMode()], _el$10);
101697
- insert(_el$9, createComponent2(Show, {
103557
+ }), _el$15);
103558
+ insertNode(_el$15, _el$16);
103559
+ insert(_el$15, () => app.version(), null);
103560
+ insertNode(_el$17, createTextNode(`|`));
103561
+ insertNode(_el$19, _el$20);
103562
+ insertNode(_el$19, _el$26);
103563
+ setProp(_el$19, "flexDirection", "row");
103564
+ insertNode(_el$20, _el$21);
103565
+ insertNode(_el$20, _el$22);
103566
+ insert(_el$20, () => MODE_LABELS[app.interactionMode()], _el$22);
103567
+ insert(_el$19, createComponent2(Show, {
101698
103568
  get when() {
101699
103569
  return app.currentAgent() !== "default";
101700
103570
  },
101701
103571
  get children() {
101702
- var _el$11 = createElement("text"), _el$12 = createTextNode(` @`);
101703
- insertNode(_el$11, _el$12);
101704
- insert(_el$11, () => app.currentAgent(), null);
103572
+ var _el$23 = createElement("text"), _el$24 = createTextNode(` @`);
103573
+ insertNode(_el$23, _el$24);
103574
+ insert(_el$23, () => app.currentAgent(), null);
101705
103575
  effect((_p$) => {
101706
- var _v$3 = theme.colors.secondary, _v$4 = TextAttributes.BOLD;
101707
- _v$3 !== _p$.e && (_p$.e = setProp(_el$11, "fg", _v$3, _p$.e));
101708
- _v$4 !== _p$.t && (_p$.t = setProp(_el$11, "attributes", _v$4, _p$.t));
103576
+ var _v$0 = theme.colors.secondary, _v$1 = TextAttributes.BOLD;
103577
+ _v$0 !== _p$.e && (_p$.e = setProp(_el$23, "fg", _v$0, _p$.e));
103578
+ _v$1 !== _p$.t && (_p$.t = setProp(_el$23, "attributes", _v$1, _p$.t));
101709
103579
  return _p$;
101710
103580
  }, {
101711
103581
  e: undefined,
101712
103582
  t: undefined
101713
103583
  });
101714
- return _el$11;
103584
+ return _el$23;
103585
+ }
103586
+ }), _el$26);
103587
+ insertNode(_el$26, _el$27);
103588
+ insert(_el$26, () => MODE_DESCRIPTIONS[app.interactionMode()], null);
103589
+ insertNode(_el$29, _el$43);
103590
+ insertNode(_el$29, _el$47);
103591
+ setProp(_el$29, "flexDirection", "row");
103592
+ setProp(_el$29, "gap", 2);
103593
+ insert(_el$29, createComponent2(Show, {
103594
+ get when() {
103595
+ return contextUsage().max > 0;
103596
+ },
103597
+ get children() {
103598
+ var _el$30 = createElement("box"), _el$31 = createElement("text"), _el$32 = createElement("text"), _el$34 = createElement("text");
103599
+ insertNode(_el$30, _el$31);
103600
+ insertNode(_el$30, _el$32);
103601
+ insertNode(_el$30, _el$34);
103602
+ setProp(_el$30, "flexDirection", "row");
103603
+ insert(_el$31, () => formatTokenCount(contextUsage().current));
103604
+ insertNode(_el$32, createTextNode(`/`));
103605
+ insert(_el$34, () => formatTokenCount(contextUsage().max));
103606
+ insert(_el$30, createComponent2(Show, {
103607
+ get when() {
103608
+ return contextUsage().status === "compacting";
103609
+ },
103610
+ get children() {
103611
+ var _el$35 = createElement("text");
103612
+ insertNode(_el$35, createTextNode(` [compacting]`));
103613
+ effect((_$p) => setProp(_el$35, "fg", theme.colors.info, _$p));
103614
+ return _el$35;
103615
+ }
103616
+ }), null);
103617
+ effect((_p$) => {
103618
+ var _v$10 = tokenColor(), _v$11 = theme.colors.textDim, _v$12 = theme.colors.textDim;
103619
+ _v$10 !== _p$.e && (_p$.e = setProp(_el$31, "fg", _v$10, _p$.e));
103620
+ _v$11 !== _p$.t && (_p$.t = setProp(_el$32, "fg", _v$11, _p$.t));
103621
+ _v$12 !== _p$.a && (_p$.a = setProp(_el$34, "fg", _v$12, _p$.a));
103622
+ return _p$;
103623
+ }, {
103624
+ e: undefined,
103625
+ t: undefined,
103626
+ a: undefined
103627
+ });
103628
+ return _el$30;
101715
103629
  }
101716
- }), _el$14);
101717
- insertNode(_el$14, _el$15);
101718
- insert(_el$14, () => MODE_DESCRIPTIONS[app.interactionMode()], null);
101719
- insertNode(_el$17, _el$18);
101720
- insertNode(_el$17, _el$22);
101721
- setProp(_el$17, "flexDirection", "row");
101722
- setProp(_el$17, "gap", 2);
101723
- insertNode(_el$18, _el$19);
101724
- insertNode(_el$18, _el$21);
101725
- setProp(_el$18, "flexDirection", "row");
101726
- insertNode(_el$19, createTextNode(`Provider: `));
101727
- insert(_el$21, () => app.provider());
101728
- insertNode(_el$22, _el$23);
101729
- insertNode(_el$22, _el$25);
101730
- setProp(_el$22, "flexDirection", "row");
101731
- insertNode(_el$23, createTextNode(`Model: `));
101732
- insert(_el$25, () => app.model() || "auto");
101733
- insert(_el$17, createComponent2(Show, {
103630
+ }), _el$43);
103631
+ insert(_el$29, createComponent2(Show, {
103632
+ when: !BRAIN_DISABLED,
103633
+ get children() {
103634
+ var _el$37 = createElement("box"), _el$38 = createElement("text");
103635
+ insertNode(_el$37, _el$38);
103636
+ setProp(_el$37, "flexDirection", "row");
103637
+ insert(_el$38, (() => {
103638
+ var _c$ = memo2(() => app.brain().status === "connected");
103639
+ return () => _c$() ? BRAIN_BANNER.EMOJI_CONNECTED : memo2(() => app.brain().status === "connecting")() ? "..." : BRAIN_BANNER.EMOJI_DISCONNECTED;
103640
+ })());
103641
+ insert(_el$37, createComponent2(Show, {
103642
+ get when() {
103643
+ return app.brain().status === "connected";
103644
+ },
103645
+ get children() {
103646
+ var _el$39 = createElement("text"), _el$40 = createTextNode(` `), _el$41 = createTextNode(`K/`), _el$42 = createTextNode(`M`);
103647
+ insertNode(_el$39, _el$40);
103648
+ insertNode(_el$39, _el$41);
103649
+ insertNode(_el$39, _el$42);
103650
+ insert(_el$39, () => app.brain().knowledgeCount, _el$41);
103651
+ insert(_el$39, () => app.brain().memoryCount, _el$42);
103652
+ effect((_$p) => setProp(_el$39, "fg", theme.colors.textDim, _$p));
103653
+ return _el$39;
103654
+ }
103655
+ }), null);
103656
+ effect((_$p) => setProp(_el$38, "fg", brainColor(), _$p));
103657
+ return _el$37;
103658
+ }
103659
+ }), _el$43);
103660
+ insertNode(_el$43, _el$44);
103661
+ insertNode(_el$43, _el$46);
103662
+ setProp(_el$43, "flexDirection", "row");
103663
+ insertNode(_el$44, createTextNode(`Provider: `));
103664
+ insert(_el$46, () => app.provider());
103665
+ insertNode(_el$47, _el$48);
103666
+ insertNode(_el$47, _el$50);
103667
+ setProp(_el$47, "flexDirection", "row");
103668
+ insertNode(_el$48, createTextNode(`Model: `));
103669
+ insert(_el$50, () => app.model() || "auto");
103670
+ insert(_el$29, createComponent2(Show, {
101734
103671
  get when() {
101735
103672
  return app.sessionId();
101736
103673
  },
101737
103674
  get children() {
101738
- var _el$26 = createElement("box"), _el$27 = createElement("text"), _el$29 = createElement("text");
101739
- insertNode(_el$26, _el$27);
101740
- insertNode(_el$26, _el$29);
101741
- setProp(_el$26, "flexDirection", "row");
101742
- insertNode(_el$27, createTextNode(`Session: `));
101743
- insert(_el$29, () => app.sessionId()?.replace("session-", "").slice(-5));
103675
+ var _el$51 = createElement("box"), _el$52 = createElement("text"), _el$54 = createElement("text");
103676
+ insertNode(_el$51, _el$52);
103677
+ insertNode(_el$51, _el$54);
103678
+ setProp(_el$51, "flexDirection", "row");
103679
+ insertNode(_el$52, createTextNode(`Session: `));
103680
+ insert(_el$54, () => app.sessionId()?.replace("session-", "").slice(-5));
101744
103681
  effect((_p$) => {
101745
- var _v$5 = theme.colors.textDim, _v$6 = theme.colors.info;
101746
- _v$5 !== _p$.e && (_p$.e = setProp(_el$27, "fg", _v$5, _p$.e));
101747
- _v$6 !== _p$.t && (_p$.t = setProp(_el$29, "fg", _v$6, _p$.t));
103682
+ var _v$13 = theme.colors.textDim, _v$14 = theme.colors.info;
103683
+ _v$13 !== _p$.e && (_p$.e = setProp(_el$52, "fg", _v$13, _p$.e));
103684
+ _v$14 !== _p$.t && (_p$.t = setProp(_el$54, "fg", _v$14, _p$.t));
101748
103685
  return _p$;
101749
103686
  }, {
101750
103687
  e: undefined,
101751
103688
  t: undefined
101752
103689
  });
101753
- return _el$26;
103690
+ return _el$51;
101754
103691
  }
101755
103692
  }), null);
101756
103693
  effect((_p$) => {
101757
- var _v$7 = theme.colors.border, _v$8 = theme.colors.textDim, _v$9 = theme.colors.textDim, _v$0 = modeColor(), _v$1 = TextAttributes.BOLD, _v$10 = theme.colors.textDim, _v$11 = theme.colors.textDim, _v$12 = theme.colors.secondary, _v$13 = theme.colors.textDim, _v$14 = theme.colors.accent;
101758
- _v$7 !== _p$.e && (_p$.e = setProp(_el$, "borderColor", _v$7, _p$.e));
101759
- _v$8 !== _p$.t && (_p$.t = setProp(_el$5, "fg", _v$8, _p$.t));
101760
- _v$9 !== _p$.a && (_p$.a = setProp(_el$7, "fg", _v$9, _p$.a));
101761
- _v$0 !== _p$.o && (_p$.o = setProp(_el$0, "fg", _v$0, _p$.o));
101762
- _v$1 !== _p$.i && (_p$.i = setProp(_el$0, "attributes", _v$1, _p$.i));
101763
- _v$10 !== _p$.n && (_p$.n = setProp(_el$14, "fg", _v$10, _p$.n));
101764
- _v$11 !== _p$.s && (_p$.s = setProp(_el$19, "fg", _v$11, _p$.s));
101765
- _v$12 !== _p$.h && (_p$.h = setProp(_el$21, "fg", _v$12, _p$.h));
101766
- _v$13 !== _p$.r && (_p$.r = setProp(_el$23, "fg", _v$13, _p$.r));
101767
- _v$14 !== _p$.d && (_p$.d = setProp(_el$25, "fg", _v$14, _p$.d));
103694
+ var _v$15 = theme.colors.border, _v$16 = theme.colors.textDim, _v$17 = theme.colors.textDim, _v$18 = modeColor(), _v$19 = TextAttributes.BOLD, _v$20 = theme.colors.textDim, _v$21 = theme.colors.textDim, _v$22 = theme.colors.secondary, _v$23 = theme.colors.textDim, _v$24 = theme.colors.accent;
103695
+ _v$15 !== _p$.e && (_p$.e = setProp(_el$11, "borderColor", _v$15, _p$.e));
103696
+ _v$16 !== _p$.t && (_p$.t = setProp(_el$15, "fg", _v$16, _p$.t));
103697
+ _v$17 !== _p$.a && (_p$.a = setProp(_el$17, "fg", _v$17, _p$.a));
103698
+ _v$18 !== _p$.o && (_p$.o = setProp(_el$20, "fg", _v$18, _p$.o));
103699
+ _v$19 !== _p$.i && (_p$.i = setProp(_el$20, "attributes", _v$19, _p$.i));
103700
+ _v$20 !== _p$.n && (_p$.n = setProp(_el$26, "fg", _v$20, _p$.n));
103701
+ _v$21 !== _p$.s && (_p$.s = setProp(_el$44, "fg", _v$21, _p$.s));
103702
+ _v$22 !== _p$.h && (_p$.h = setProp(_el$46, "fg", _v$22, _p$.h));
103703
+ _v$23 !== _p$.r && (_p$.r = setProp(_el$48, "fg", _v$23, _p$.r));
103704
+ _v$24 !== _p$.d && (_p$.d = setProp(_el$50, "fg", _v$24, _p$.d));
101768
103705
  return _p$;
101769
103706
  }, {
101770
103707
  e: undefined,
@@ -101793,7 +103730,6 @@ await __promiseAll([
101793
103730
  init_solid(),
101794
103731
  init_solid(),
101795
103732
  init_solid(),
101796
- init_solid(),
101797
103733
  init_theme2(),
101798
103734
  init_app()
101799
103735
  ]);
@@ -102636,13 +104572,25 @@ function LogPanel() {
102636
104572
  },
102637
104573
  get fallback() {
102638
104574
  return (() => {
102639
- var _el$4 = createElement("box"), _el$5 = createElement("text");
104575
+ var _el$4 = createElement("box"), _el$5 = createElement("box"), _el$6 = createElement("text");
102640
104576
  insertNode(_el$4, _el$5);
102641
104577
  setProp(_el$4, "flexGrow", 1);
102642
104578
  setProp(_el$4, "alignItems", "center");
102643
104579
  setProp(_el$4, "justifyContent", "center");
102644
- insertNode(_el$5, createTextNode(`No messages yet. Type your prompt below.`));
102645
- effect((_$p) => setProp(_el$5, "fg", theme.colors.textDim, _$p));
104580
+ setProp(_el$4, "flexDirection", "column");
104581
+ insert(_el$4, createComponent2(For, {
104582
+ each: ASCII_LOGO,
104583
+ children: (line2, index) => (() => {
104584
+ var _el$7 = createElement("text");
104585
+ insert(_el$7, line2);
104586
+ effect((_$p) => setProp(_el$7, "fg", ASCII_LOGO_GRADIENT[index()] ?? theme.colors.primary, _$p));
104587
+ return _el$7;
104588
+ })()
104589
+ }), _el$5);
104590
+ insertNode(_el$5, _el$6);
104591
+ setProp(_el$5, "marginTop", 2);
104592
+ insert(_el$6, () => HOME_VARS.subTitle);
104593
+ effect((_$p) => setProp(_el$6, "fg", theme.colors.textDim, _$p));
102646
104594
  return _el$4;
102647
104595
  })();
102648
104596
  },
@@ -102939,15 +104887,9 @@ function StatusBar() {
102939
104887
  const totalTokens = createMemo(() => app.sessionStats().inputTokens + app.sessionStats().outputTokens);
102940
104888
  const hints = createMemo(() => {
102941
104889
  const result = [];
102942
- if (!isProcessing()) {
102943
- result.push("^Tab toggle mode");
102944
- }
102945
104890
  if (isProcessing()) {
102946
104891
  result.push(app.interruptPending() ? STATUS_HINTS.INTERRUPT_CONFIRM : STATUS_HINTS.INTERRUPT);
102947
104892
  }
102948
- if (app.todosVisible()) {
102949
- result.push(STATUS_HINTS.TOGGLE_TODOS);
102950
- }
102951
104893
  result.push(formatDuration2(elapsed()));
102952
104894
  if (totalTokens() > 0) {
102953
104895
  result.push(`↓ ${formatTokens(totalTokens())} tokens`);
@@ -103329,13 +105271,13 @@ var FIELD_ORDER = ["name", "command", "args", "scope"];
103329
105271
  var FIELD_LABELS = {
103330
105272
  name: "Server Name",
103331
105273
  command: "Command",
103332
- args: "Arguments (space-separated)",
105274
+ args: "Arguments (use quotes for paths with spaces)",
103333
105275
  scope: "Scope"
103334
105276
  };
103335
105277
  var FIELD_PLACEHOLDERS = {
103336
- name: "e.g., sqlite",
105278
+ name: "e.g., filesystem",
103337
105279
  command: "e.g., npx",
103338
- args: "e.g., @modelcontextprotocol/server-sqlite",
105280
+ args: 'e.g., -y @modelcontextprotocol/server-filesystem "/path/to/dir"',
103339
105281
  scope: ""
103340
105282
  };
103341
105283
  function MCPAddForm(props) {
@@ -103457,10 +105399,25 @@ function MCPAddForm(props) {
103457
105399
  evt.preventDefault();
103458
105400
  return;
103459
105401
  }
105402
+ if (evt.name === "space") {
105403
+ setFieldValue(field, getFieldValue(field) + " ");
105404
+ setError(null);
105405
+ evt.preventDefault();
105406
+ return;
105407
+ }
105408
+ if (evt.ctrl && evt.name === "v") {
105409
+ return;
105410
+ }
103460
105411
  if (evt.name.length === 1 && !evt.ctrl && !evt.meta) {
103461
105412
  setFieldValue(field, getFieldValue(field) + evt.name);
103462
105413
  setError(null);
103463
105414
  evt.preventDefault();
105415
+ return;
105416
+ }
105417
+ if (evt.sequence && evt.sequence.length > 1 && !evt.ctrl && !evt.meta) {
105418
+ setFieldValue(field, getFieldValue(field) + evt.sequence);
105419
+ setError(null);
105420
+ evt.preventDefault();
103464
105421
  }
103465
105422
  });
103466
105423
  const renderField = (field) => {
@@ -104579,7 +106536,7 @@ var HELP_TOPICS = [
104579
106536
  shortDescription: "Switch mode",
104580
106537
  fullDescription: "Switch between Agent (full access), Ask (read-only), and Code Review modes.",
104581
106538
  usage: "/mode",
104582
- shortcuts: ["Ctrl+Tab"],
106539
+ shortcuts: ["Ctrl+M"],
104583
106540
  category: "commands"
104584
106541
  },
104585
106542
  {
@@ -104650,11 +106607,11 @@ var HELP_TOPICS = [
104650
106607
  category: "shortcuts"
104651
106608
  },
104652
106609
  {
104653
- id: "shortcut-ctrltab",
104654
- name: "Ctrl+Tab",
106610
+ id: "shortcut-ctrlm",
106611
+ name: "Ctrl+M",
104655
106612
  shortDescription: "Cycle modes",
104656
106613
  fullDescription: "Cycle through interaction modes.",
104657
- shortcuts: ["Ctrl+Tab"],
106614
+ shortcuts: ["Ctrl+M"],
104658
106615
  category: "shortcuts"
104659
106616
  }
104660
106617
  ];
@@ -105139,9 +107096,567 @@ function TodoPanel(props) {
105139
107096
 
105140
107097
  // src/tui-solid/routes/session.tsx
105141
107098
  await init_debug_log_panel();
107099
+
107100
+ // src/tui-solid/components/brain-menu.tsx
107101
+ init_server();
107102
+ await __promiseAll([
107103
+ init_solid(),
107104
+ init_solid(),
107105
+ init_solid(),
107106
+ init_solid(),
107107
+ init_solid(),
107108
+ init_solid(),
107109
+ init_solid(),
107110
+ init_solid(),
107111
+ init_solid(),
107112
+ init_core2(),
107113
+ init_theme2(),
107114
+ init_app()
107115
+ ]);
107116
+ function BrainMenu(props) {
107117
+ const theme = useTheme();
107118
+ const app = useAppStore();
107119
+ const isActive = () => props.isActive ?? true;
107120
+ const [view, setView] = createSignal("main");
107121
+ const [selectedIndex, setSelectedIndex] = createSignal(0);
107122
+ const [jwtToken, setJwtToken2] = createSignal("");
107123
+ const [apiKey, setApiKey2] = createSignal("");
107124
+ const [error49, setError] = createSignal(null);
107125
+ const [loading, setLoading] = createSignal(false);
107126
+ const isConnected = () => app.brain().status === "connected";
107127
+ const menuItems = () => {
107128
+ const items = [];
107129
+ if (!isConnected()) {
107130
+ items.push({
107131
+ id: "login",
107132
+ label: "Login with Email",
107133
+ description: "Get JWT token from the web portal",
107134
+ action: () => {
107135
+ setView("login_url");
107136
+ setSelectedIndex(0);
107137
+ }
107138
+ });
107139
+ items.push({
107140
+ id: "apikey",
107141
+ label: "Use API Key",
107142
+ description: "Enter your API key directly",
107143
+ action: () => {
107144
+ setView("apikey");
107145
+ setSelectedIndex(0);
107146
+ }
107147
+ });
107148
+ } else {
107149
+ items.push({
107150
+ id: "logout",
107151
+ label: "Logout",
107152
+ description: "Disconnect from CodeTyper Brain",
107153
+ action: async () => {
107154
+ setLoading(true);
107155
+ try {
107156
+ await props.onLogout();
107157
+ } catch (err) {
107158
+ setError(err instanceof Error ? err.message : "Logout failed");
107159
+ } finally {
107160
+ setLoading(false);
107161
+ }
107162
+ }
107163
+ });
107164
+ }
107165
+ items.push({
107166
+ id: "close",
107167
+ label: "Close",
107168
+ description: "Return to session",
107169
+ action: () => props.onClose()
107170
+ });
107171
+ return items;
107172
+ };
107173
+ const handleJwtSubmit = async () => {
107174
+ if (!jwtToken()) {
107175
+ setError("JWT token is required");
107176
+ return;
107177
+ }
107178
+ setLoading(true);
107179
+ setError(null);
107180
+ try {
107181
+ await props.onSetJwtToken(jwtToken());
107182
+ setView("main");
107183
+ setJwtToken2("");
107184
+ } catch (err) {
107185
+ setError(err instanceof Error ? err.message : "Failed to set JWT token");
107186
+ } finally {
107187
+ setLoading(false);
107188
+ }
107189
+ };
107190
+ const handleApiKey = async () => {
107191
+ if (!apiKey()) {
107192
+ setError("API key is required");
107193
+ return;
107194
+ }
107195
+ setLoading(true);
107196
+ setError(null);
107197
+ try {
107198
+ await props.onSetApiKey(apiKey());
107199
+ setView("main");
107200
+ setApiKey2("");
107201
+ } catch (err) {
107202
+ setError(err instanceof Error ? err.message : "Failed to set API key");
107203
+ } finally {
107204
+ setLoading(false);
107205
+ }
107206
+ };
107207
+ useKeyboard((evt) => {
107208
+ if (!isActive())
107209
+ return;
107210
+ if (evt.name === "escape") {
107211
+ if (view() !== "main") {
107212
+ setView("main");
107213
+ setError(null);
107214
+ setSelectedIndex(0);
107215
+ } else {
107216
+ props.onClose();
107217
+ }
107218
+ evt.preventDefault();
107219
+ evt.stopPropagation();
107220
+ return;
107221
+ }
107222
+ if (view() === "main") {
107223
+ if (evt.name === "up") {
107224
+ setSelectedIndex((prev) => prev > 0 ? prev - 1 : menuItems().length - 1);
107225
+ evt.preventDefault();
107226
+ return;
107227
+ }
107228
+ if (evt.name === "down") {
107229
+ setSelectedIndex((prev) => prev < menuItems().length - 1 ? prev + 1 : 0);
107230
+ evt.preventDefault();
107231
+ return;
107232
+ }
107233
+ if (evt.name === "return") {
107234
+ const item = menuItems()[selectedIndex()];
107235
+ if (item && !item.disabled) {
107236
+ item.action();
107237
+ }
107238
+ evt.preventDefault();
107239
+ return;
107240
+ }
107241
+ }
107242
+ if (view() === "login_url") {
107243
+ if (evt.name === "return") {
107244
+ setView("jwt_input");
107245
+ evt.preventDefault();
107246
+ return;
107247
+ }
107248
+ }
107249
+ if (view() === "jwt_input") {
107250
+ if (evt.name === "return") {
107251
+ handleJwtSubmit();
107252
+ evt.preventDefault();
107253
+ return;
107254
+ }
107255
+ if (evt.name === "backspace") {
107256
+ setJwtToken2((prev) => prev.slice(0, -1));
107257
+ evt.preventDefault();
107258
+ return;
107259
+ }
107260
+ if (evt.name.length === 1 && !evt.ctrl && !evt.meta) {
107261
+ setJwtToken2((prev) => prev + evt.name);
107262
+ evt.preventDefault();
107263
+ return;
107264
+ }
107265
+ }
107266
+ if (view() === "apikey") {
107267
+ if (evt.name === "return") {
107268
+ handleApiKey();
107269
+ evt.preventDefault();
107270
+ return;
107271
+ }
107272
+ if (evt.name === "backspace") {
107273
+ setApiKey2((prev) => prev.slice(0, -1));
107274
+ evt.preventDefault();
107275
+ return;
107276
+ }
107277
+ if (evt.name.length === 1 && !evt.ctrl && !evt.meta) {
107278
+ setApiKey2((prev) => prev + evt.name);
107279
+ evt.preventDefault();
107280
+ return;
107281
+ }
107282
+ }
107283
+ });
107284
+ const getStatusColor = () => {
107285
+ const status2 = app.brain().status;
107286
+ const colorMap = {
107287
+ connected: theme.colors.success,
107288
+ connecting: theme.colors.warning,
107289
+ disconnected: theme.colors.textDim,
107290
+ error: theme.colors.error
107291
+ };
107292
+ return colorMap[status2] ?? theme.colors.textDim;
107293
+ };
107294
+ const getStatusText2 = () => {
107295
+ const status2 = app.brain().status;
107296
+ const textMap = {
107297
+ connected: "Connected",
107298
+ connecting: "Connecting...",
107299
+ disconnected: "Not connected",
107300
+ error: "Connection error"
107301
+ };
107302
+ return textMap[status2] ?? "Unknown";
107303
+ };
107304
+ return (() => {
107305
+ var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$4 = createElement("text"), _el$6 = createElement("box"), _el$7 = createElement("text"), _el$9 = createElement("text");
107306
+ insertNode(_el$, _el$2);
107307
+ insertNode(_el$, _el$6);
107308
+ setProp(_el$, "flexDirection", "column");
107309
+ setProp(_el$, "border", ["top", "bottom", "left", "right"]);
107310
+ setProp(_el$, "paddingLeft", 1);
107311
+ setProp(_el$, "paddingRight", 1);
107312
+ setProp(_el$, "width", 60);
107313
+ insertNode(_el$2, _el$3);
107314
+ insertNode(_el$2, _el$4);
107315
+ setProp(_el$2, "marginBottom", 1);
107316
+ setProp(_el$2, "flexDirection", "row");
107317
+ setProp(_el$2, "gap", 1);
107318
+ setProp(_el$3, "fg", "#ff69b4");
107319
+ insert(_el$3, () => BRAIN_BANNER.EMOJI_CONNECTED);
107320
+ insertNode(_el$4, createTextNode(`CodeTyper Brain`));
107321
+ insertNode(_el$6, _el$7);
107322
+ insertNode(_el$6, _el$9);
107323
+ setProp(_el$6, "marginBottom", 1);
107324
+ setProp(_el$6, "flexDirection", "row");
107325
+ insertNode(_el$7, createTextNode(`Status: `));
107326
+ insert(_el$9, getStatusText2);
107327
+ insert(_el$6, createComponent2(Show, {
107328
+ get when() {
107329
+ return isConnected();
107330
+ },
107331
+ get children() {
107332
+ var _el$0 = createElement("text"), _el$1 = createTextNode(` (`), _el$11 = createTextNode(`K / `), _el$12 = createTextNode(`M)`);
107333
+ insertNode(_el$0, _el$1);
107334
+ insertNode(_el$0, _el$11);
107335
+ insertNode(_el$0, _el$12);
107336
+ insert(_el$0, () => app.brain().knowledgeCount, _el$11);
107337
+ insert(_el$0, () => app.brain().memoryCount, _el$12);
107338
+ effect((_$p) => setProp(_el$0, "fg", theme.colors.textDim, _$p));
107339
+ return _el$0;
107340
+ }
107341
+ }), null);
107342
+ insert(_el$, createComponent2(Show, {
107343
+ get when() {
107344
+ return memo2(() => !!isConnected())() && app.brain().user;
107345
+ },
107346
+ get children() {
107347
+ var _el$13 = createElement("box"), _el$14 = createElement("text"), _el$16 = createElement("text");
107348
+ insertNode(_el$13, _el$14);
107349
+ insertNode(_el$13, _el$16);
107350
+ setProp(_el$13, "marginBottom", 1);
107351
+ setProp(_el$13, "flexDirection", "row");
107352
+ insertNode(_el$14, createTextNode(`User: `));
107353
+ insert(_el$16, () => app.brain().user?.display_name ?? app.brain().user?.email);
107354
+ effect((_p$) => {
107355
+ var _v$ = theme.colors.textDim, _v$2 = theme.colors.info;
107356
+ _v$ !== _p$.e && (_p$.e = setProp(_el$14, "fg", _v$, _p$.e));
107357
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$16, "fg", _v$2, _p$.t));
107358
+ return _p$;
107359
+ }, {
107360
+ e: undefined,
107361
+ t: undefined
107362
+ });
107363
+ return _el$13;
107364
+ }
107365
+ }), null);
107366
+ insert(_el$, createComponent2(Show, {
107367
+ get when() {
107368
+ return error49();
107369
+ },
107370
+ get children() {
107371
+ var _el$17 = createElement("box"), _el$18 = createElement("text");
107372
+ insertNode(_el$17, _el$18);
107373
+ setProp(_el$17, "marginBottom", 1);
107374
+ insert(_el$18, error49);
107375
+ effect((_$p) => setProp(_el$18, "fg", theme.colors.error, _$p));
107376
+ return _el$17;
107377
+ }
107378
+ }), null);
107379
+ insert(_el$, createComponent2(Show, {
107380
+ get when() {
107381
+ return view() === "main";
107382
+ },
107383
+ get children() {
107384
+ return [(() => {
107385
+ var _el$19 = createElement("box");
107386
+ setProp(_el$19, "flexDirection", "column");
107387
+ insert(_el$19, createComponent2(For, {
107388
+ get each() {
107389
+ return menuItems();
107390
+ },
107391
+ children: (item, index) => {
107392
+ const isSelected = () => index() === selectedIndex();
107393
+ return (() => {
107394
+ var _el$62 = createElement("box"), _el$63 = createElement("box"), _el$64 = createElement("text"), _el$65 = createElement("text"), _el$66 = createElement("box"), _el$67 = createElement("text");
107395
+ insertNode(_el$62, _el$63);
107396
+ insertNode(_el$62, _el$66);
107397
+ setProp(_el$62, "flexDirection", "column");
107398
+ setProp(_el$62, "marginBottom", 1);
107399
+ insertNode(_el$63, _el$64);
107400
+ insertNode(_el$63, _el$65);
107401
+ setProp(_el$63, "flexDirection", "row");
107402
+ insert(_el$64, () => isSelected() ? "> " : " ");
107403
+ insert(_el$65, () => item.label);
107404
+ insertNode(_el$66, _el$67);
107405
+ setProp(_el$66, "marginLeft", 4);
107406
+ insert(_el$67, () => item.description);
107407
+ effect((_p$) => {
107408
+ var _v$21 = isSelected() ? theme.colors.accent : undefined, _v$22 = isSelected() ? TextAttributes.BOLD : TextAttributes.NONE, _v$23 = isSelected() ? theme.colors.accent : undefined, _v$24 = isSelected() ? TextAttributes.BOLD : TextAttributes.NONE, _v$25 = theme.colors.textDim;
107409
+ _v$21 !== _p$.e && (_p$.e = setProp(_el$64, "fg", _v$21, _p$.e));
107410
+ _v$22 !== _p$.t && (_p$.t = setProp(_el$64, "attributes", _v$22, _p$.t));
107411
+ _v$23 !== _p$.a && (_p$.a = setProp(_el$65, "fg", _v$23, _p$.a));
107412
+ _v$24 !== _p$.o && (_p$.o = setProp(_el$65, "attributes", _v$24, _p$.o));
107413
+ _v$25 !== _p$.i && (_p$.i = setProp(_el$67, "fg", _v$25, _p$.i));
107414
+ return _p$;
107415
+ }, {
107416
+ e: undefined,
107417
+ t: undefined,
107418
+ a: undefined,
107419
+ o: undefined,
107420
+ i: undefined
107421
+ });
107422
+ return _el$62;
107423
+ })();
107424
+ }
107425
+ }));
107426
+ return _el$19;
107427
+ })(), (() => {
107428
+ var _el$20 = createElement("box"), _el$21 = createElement("text"), _el$22 = createTextNode(`: `), _el$23 = createElement("text");
107429
+ insertNode(_el$20, _el$21);
107430
+ insertNode(_el$20, _el$23);
107431
+ setProp(_el$20, "marginTop", 1);
107432
+ setProp(_el$20, "flexDirection", "column");
107433
+ insertNode(_el$21, _el$22);
107434
+ insert(_el$21, () => BRAIN_BANNER.CTA, _el$22);
107435
+ insert(_el$21, () => BRAIN_BANNER.URL, null);
107436
+ insertNode(_el$23, createTextNode(`Arrow keys navigate | Enter select | Esc close`));
107437
+ effect((_p$) => {
107438
+ var _v$3 = theme.colors.info, _v$4 = theme.colors.textDim;
107439
+ _v$3 !== _p$.e && (_p$.e = setProp(_el$21, "fg", _v$3, _p$.e));
107440
+ _v$4 !== _p$.t && (_p$.t = setProp(_el$23, "fg", _v$4, _p$.t));
107441
+ return _p$;
107442
+ }, {
107443
+ e: undefined,
107444
+ t: undefined
107445
+ });
107446
+ return _el$20;
107447
+ })()];
107448
+ }
107449
+ }), null);
107450
+ insert(_el$, createComponent2(Show, {
107451
+ get when() {
107452
+ return view() === "login_url";
107453
+ },
107454
+ get children() {
107455
+ return [(() => {
107456
+ var _el$25 = createElement("box"), _el$26 = createElement("box"), _el$27 = createElement("text"), _el$29 = createElement("box"), _el$30 = createElement("text"), _el$31 = createElement("box"), _el$32 = createElement("text"), _el$34 = createElement("box"), _el$35 = createElement("text");
107457
+ insertNode(_el$25, _el$26);
107458
+ insertNode(_el$25, _el$29);
107459
+ insertNode(_el$25, _el$31);
107460
+ insertNode(_el$25, _el$34);
107461
+ setProp(_el$25, "flexDirection", "column");
107462
+ insertNode(_el$26, _el$27);
107463
+ setProp(_el$26, "marginBottom", 1);
107464
+ insertNode(_el$27, createTextNode(`1. Go to this page to login:`));
107465
+ insertNode(_el$29, _el$30);
107466
+ setProp(_el$29, "marginBottom", 1);
107467
+ insert(_el$30, () => BRAIN_BANNER.LOGIN_URL);
107468
+ insertNode(_el$31, _el$32);
107469
+ setProp(_el$31, "marginBottom", 1);
107470
+ insertNode(_el$32, createTextNode(`2. After logging in, copy your JWT token`));
107471
+ insertNode(_el$34, _el$35);
107472
+ setProp(_el$34, "marginBottom", 1);
107473
+ insertNode(_el$35, createTextNode(`3. Press Enter to input your token`));
107474
+ effect((_p$) => {
107475
+ var _v$5 = theme.colors.text, _v$6 = theme.colors.accent, _v$7 = TextAttributes.BOLD, _v$8 = theme.colors.text, _v$9 = theme.colors.text;
107476
+ _v$5 !== _p$.e && (_p$.e = setProp(_el$27, "fg", _v$5, _p$.e));
107477
+ _v$6 !== _p$.t && (_p$.t = setProp(_el$30, "fg", _v$6, _p$.t));
107478
+ _v$7 !== _p$.a && (_p$.a = setProp(_el$30, "attributes", _v$7, _p$.a));
107479
+ _v$8 !== _p$.o && (_p$.o = setProp(_el$32, "fg", _v$8, _p$.o));
107480
+ _v$9 !== _p$.i && (_p$.i = setProp(_el$35, "fg", _v$9, _p$.i));
107481
+ return _p$;
107482
+ }, {
107483
+ e: undefined,
107484
+ t: undefined,
107485
+ a: undefined,
107486
+ o: undefined,
107487
+ i: undefined
107488
+ });
107489
+ return _el$25;
107490
+ })(), (() => {
107491
+ var _el$37 = createElement("box"), _el$38 = createElement("text");
107492
+ insertNode(_el$37, _el$38);
107493
+ setProp(_el$37, "marginTop", 1);
107494
+ insertNode(_el$38, createTextNode(`Enter continue | Esc back`));
107495
+ effect((_$p) => setProp(_el$38, "fg", theme.colors.textDim, _$p));
107496
+ return _el$37;
107497
+ })()];
107498
+ }
107499
+ }), null);
107500
+ insert(_el$, createComponent2(Show, {
107501
+ get when() {
107502
+ return view() === "jwt_input";
107503
+ },
107504
+ get children() {
107505
+ return [(() => {
107506
+ var _el$40 = createElement("box"), _el$41 = createElement("box"), _el$42 = createElement("text"), _el$44 = createElement("box"), _el$45 = createElement("text");
107507
+ insertNode(_el$40, _el$41);
107508
+ setProp(_el$40, "flexDirection", "column");
107509
+ insertNode(_el$41, _el$42);
107510
+ insertNode(_el$41, _el$44);
107511
+ setProp(_el$41, "marginBottom", 1);
107512
+ setProp(_el$41, "flexDirection", "column");
107513
+ insertNode(_el$42, createTextNode(`JWT Token:`));
107514
+ insertNode(_el$44, _el$45);
107515
+ setProp(_el$44, "border", ["top", "bottom", "left", "right"]);
107516
+ setProp(_el$44, "paddingLeft", 1);
107517
+ setProp(_el$44, "paddingRight", 1);
107518
+ insert(_el$45, (() => {
107519
+ var _c$ = memo2(() => !!jwtToken());
107520
+ return () => _c$() ? "*".repeat(Math.min(jwtToken().length, 40)) : " ";
107521
+ })());
107522
+ insert(_el$40, createComponent2(Show, {
107523
+ get when() {
107524
+ return loading();
107525
+ },
107526
+ get children() {
107527
+ var _el$46 = createElement("text");
107528
+ insertNode(_el$46, createTextNode(`Saving token...`));
107529
+ effect((_$p) => setProp(_el$46, "fg", theme.colors.warning, _$p));
107530
+ return _el$46;
107531
+ }
107532
+ }), null);
107533
+ effect((_p$) => {
107534
+ var _v$0 = theme.colors.accent, _v$1 = theme.colors.accent, _v$10 = theme.colors.text;
107535
+ _v$0 !== _p$.e && (_p$.e = setProp(_el$42, "fg", _v$0, _p$.e));
107536
+ _v$1 !== _p$.t && (_p$.t = setProp(_el$44, "borderColor", _v$1, _p$.t));
107537
+ _v$10 !== _p$.a && (_p$.a = setProp(_el$45, "fg", _v$10, _p$.a));
107538
+ return _p$;
107539
+ }, {
107540
+ e: undefined,
107541
+ t: undefined,
107542
+ a: undefined
107543
+ });
107544
+ return _el$40;
107545
+ })(), (() => {
107546
+ var _el$48 = createElement("box"), _el$49 = createElement("text");
107547
+ insertNode(_el$48, _el$49);
107548
+ setProp(_el$48, "marginTop", 1);
107549
+ insertNode(_el$49, createTextNode(`Enter save | Esc back`));
107550
+ effect((_$p) => setProp(_el$49, "fg", theme.colors.textDim, _$p));
107551
+ return _el$48;
107552
+ })()];
107553
+ }
107554
+ }), null);
107555
+ insert(_el$, createComponent2(Show, {
107556
+ get when() {
107557
+ return view() === "apikey";
107558
+ },
107559
+ get children() {
107560
+ return [(() => {
107561
+ var _el$51 = createElement("box"), _el$52 = createElement("box"), _el$53 = createElement("text"), _el$55 = createElement("box"), _el$56 = createElement("text");
107562
+ insertNode(_el$51, _el$52);
107563
+ setProp(_el$51, "flexDirection", "column");
107564
+ insertNode(_el$52, _el$53);
107565
+ insertNode(_el$52, _el$55);
107566
+ setProp(_el$52, "marginBottom", 1);
107567
+ setProp(_el$52, "flexDirection", "column");
107568
+ insertNode(_el$53, createTextNode(`API Key:`));
107569
+ insertNode(_el$55, _el$56);
107570
+ setProp(_el$55, "border", ["top", "bottom", "left", "right"]);
107571
+ setProp(_el$55, "paddingLeft", 1);
107572
+ setProp(_el$55, "paddingRight", 1);
107573
+ insert(_el$56, (() => {
107574
+ var _c$2 = memo2(() => !!apiKey());
107575
+ return () => _c$2() ? "*".repeat(Math.min(apiKey().length, 40)) : " ";
107576
+ })());
107577
+ insert(_el$51, createComponent2(Show, {
107578
+ get when() {
107579
+ return loading();
107580
+ },
107581
+ get children() {
107582
+ var _el$57 = createElement("text");
107583
+ insertNode(_el$57, createTextNode(`Setting API key...`));
107584
+ effect((_$p) => setProp(_el$57, "fg", theme.colors.warning, _$p));
107585
+ return _el$57;
107586
+ }
107587
+ }), null);
107588
+ effect((_p$) => {
107589
+ var _v$11 = theme.colors.accent, _v$12 = theme.colors.accent, _v$13 = theme.colors.text;
107590
+ _v$11 !== _p$.e && (_p$.e = setProp(_el$53, "fg", _v$11, _p$.e));
107591
+ _v$12 !== _p$.t && (_p$.t = setProp(_el$55, "borderColor", _v$12, _p$.t));
107592
+ _v$13 !== _p$.a && (_p$.a = setProp(_el$56, "fg", _v$13, _p$.a));
107593
+ return _p$;
107594
+ }, {
107595
+ e: undefined,
107596
+ t: undefined,
107597
+ a: undefined
107598
+ });
107599
+ return _el$51;
107600
+ })(), (() => {
107601
+ var _el$59 = createElement("box"), _el$60 = createElement("text");
107602
+ insertNode(_el$59, _el$60);
107603
+ setProp(_el$59, "marginTop", 1);
107604
+ insertNode(_el$60, createTextNode(`Enter save | Esc back`));
107605
+ effect((_$p) => setProp(_el$60, "fg", theme.colors.textDim, _$p));
107606
+ return _el$59;
107607
+ })()];
107608
+ }
107609
+ }), null);
107610
+ effect((_p$) => {
107611
+ var _v$14 = theme.colors.accent, _v$15 = theme.colors.background, _v$16 = TextAttributes.BOLD, _v$17 = theme.colors.accent, _v$18 = TextAttributes.BOLD, _v$19 = theme.colors.textDim, _v$20 = getStatusColor();
107612
+ _v$14 !== _p$.e && (_p$.e = setProp(_el$, "borderColor", _v$14, _p$.e));
107613
+ _v$15 !== _p$.t && (_p$.t = setProp(_el$, "backgroundColor", _v$15, _p$.t));
107614
+ _v$16 !== _p$.a && (_p$.a = setProp(_el$3, "attributes", _v$16, _p$.a));
107615
+ _v$17 !== _p$.o && (_p$.o = setProp(_el$4, "fg", _v$17, _p$.o));
107616
+ _v$18 !== _p$.i && (_p$.i = setProp(_el$4, "attributes", _v$18, _p$.i));
107617
+ _v$19 !== _p$.n && (_p$.n = setProp(_el$7, "fg", _v$19, _p$.n));
107618
+ _v$20 !== _p$.s && (_p$.s = setProp(_el$9, "fg", _v$20, _p$.s));
107619
+ return _p$;
107620
+ }, {
107621
+ e: undefined,
107622
+ t: undefined,
107623
+ a: undefined,
107624
+ o: undefined,
107625
+ i: undefined,
107626
+ n: undefined,
107627
+ s: undefined
107628
+ });
107629
+ return _el$;
107630
+ })();
107631
+ }
107632
+
107633
+ // src/tui-solid/routes/session.tsx
107634
+ init_mcp();
105142
107635
  function Session(props) {
105143
107636
  const theme = useTheme();
105144
107637
  const app = useAppStore();
107638
+ onMount(async () => {
107639
+ if (props.mcpServers && props.mcpServers.length > 0) {
107640
+ app.setMcpServers(props.mcpServers);
107641
+ }
107642
+ try {
107643
+ await initializeMCP();
107644
+ const instances = getServerInstances();
107645
+ const servers = [];
107646
+ for (const [id, instance] of instances) {
107647
+ servers.push({
107648
+ id,
107649
+ name: instance.config.name || id,
107650
+ status: instance.state === "connected" ? "connected" : instance.state === "error" ? "error" : "disconnected",
107651
+ description: instance.config.command
107652
+ });
107653
+ }
107654
+ if (servers.length > 0) {
107655
+ app.setMcpServers(servers);
107656
+ }
107657
+ } catch {}
107658
+ });
107659
+ const mcpServers = createMemo(() => app.mcpServers());
105145
107660
  const [selectedHelpTopic, setSelectedHelpTopic] = createSignal(null);
105146
107661
  const handleCommandSelect = (command) => {
105147
107662
  const lowerCommand = command.toLowerCase();
@@ -105173,6 +107688,10 @@ function Session(props) {
105173
107688
  app.transitionFromCommandMenu("help_menu");
105174
107689
  return;
105175
107690
  }
107691
+ if (lowerCommand === "brain" && !BRAIN_DISABLED) {
107692
+ app.transitionFromCommandMenu("brain_menu");
107693
+ return;
107694
+ }
105176
107695
  app.closeCommandMenu();
105177
107696
  props.onCommand(command);
105178
107697
  };
@@ -105233,6 +107752,18 @@ function Session(props) {
105233
107752
  setSelectedHelpTopic(null);
105234
107753
  app.setMode("idle");
105235
107754
  };
107755
+ const handleBrainMenuClose = () => {
107756
+ app.setMode("idle");
107757
+ };
107758
+ const handleBrainSetJwtToken = async (jwtToken) => {
107759
+ await props.onBrainSetJwtToken?.(jwtToken);
107760
+ };
107761
+ const handleBrainSetApiKey = async (apiKey) => {
107762
+ await props.onBrainSetApiKey?.(apiKey);
107763
+ };
107764
+ const handleBrainLogout = async () => {
107765
+ await props.onBrainLogout?.();
107766
+ };
105236
107767
  return (() => {
105237
107768
  var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("box");
105238
107769
  insertNode(_el$, _el$2);
@@ -105366,7 +107897,7 @@ function Session(props) {
105366
107897
  get children() {
105367
107898
  return createComponent2(MCPSelect, {
105368
107899
  get servers() {
105369
- return props.mcpServers ?? [];
107900
+ return mcpServers();
105370
107901
  },
105371
107902
  get onSelect() {
105372
107903
  return props.onMCPSelect;
@@ -105544,6 +108075,25 @@ function Session(props) {
105544
108075
  }
105545
108076
  });
105546
108077
  }
108078
+ }), createComponent2(Match, {
108079
+ get when() {
108080
+ return app.mode() === "brain_menu" && !BRAIN_DISABLED;
108081
+ },
108082
+ get children() {
108083
+ return createComponent2(CenteredModal, {
108084
+ get children() {
108085
+ return createComponent2(BrainMenu, {
108086
+ onSetJwtToken: handleBrainSetJwtToken,
108087
+ onSetApiKey: handleBrainSetApiKey,
108088
+ onLogout: handleBrainLogout,
108089
+ onClose: handleBrainMenuClose,
108090
+ get isActive() {
108091
+ return app.mode() === "brain_menu";
108092
+ }
108093
+ });
108094
+ }
108095
+ });
108096
+ }
105547
108097
  })];
105548
108098
  }
105549
108099
  }), null);
@@ -105613,8 +108163,12 @@ function AppContent(props) {
105613
108163
  if (props.cascadeEnabled !== undefined) {
105614
108164
  app.setCascadeEnabled(props.cascadeEnabled);
105615
108165
  }
105616
- if (props.sessionId) {
105617
- route.goToSession(props.sessionId);
108166
+ if (!route.isSession()) {
108167
+ const sessionId = props.sessionId ?? `session-${Date.now()}`;
108168
+ batch(() => {
108169
+ app.setSessionInfo(sessionId, app.provider(), app.model());
108170
+ route.goToSession(sessionId);
108171
+ });
105618
108172
  }
105619
108173
  if (props.availableModels && props.availableModels.length > 0) {
105620
108174
  app.setAvailableModels(props.availableModels);
@@ -105822,6 +108376,15 @@ function AppContent(props) {
105822
108376
  onCascadeToggle: handleCascadeToggle,
105823
108377
  onPermissionResponse: handlePermissionResponse,
105824
108378
  onLearningResponse: handleLearningResponse,
108379
+ get onBrainSetJwtToken() {
108380
+ return props.onBrainSetJwtToken;
108381
+ },
108382
+ get onBrainSetApiKey() {
108383
+ return props.onBrainSetApiKey;
108384
+ },
108385
+ get onBrainLogout() {
108386
+ return props.onBrainLogout;
108387
+ },
105825
108388
  get plan() {
105826
108389
  return props.plan;
105827
108390
  },
@@ -105916,8 +108479,8 @@ var showContextFiles = (contextFiles) => {
105916
108479
  ` + source_default.bold("Context Files:"));
105917
108480
  if (contextFiles.size > 0) {
105918
108481
  console.log(source_default.gray(" Pending (will be included in next message):"));
105919
- for (const [path15] of contextFiles) {
105920
- console.log(` - ${filePath(basename6(path15))}`);
108482
+ for (const [path16] of contextFiles) {
108483
+ console.log(` - ${filePath(basename6(path16))}`);
105921
108484
  }
105922
108485
  }
105923
108486
  if (files.length > 0) {
@@ -105937,10 +108500,10 @@ var removeFile = (filename, contextFiles) => {
105937
108500
  warningMessage("Please specify a file to remove");
105938
108501
  return;
105939
108502
  }
105940
- for (const [path15] of contextFiles) {
105941
- if (path15.includes(filename) || basename7(path15) === filename) {
105942
- contextFiles.delete(path15);
105943
- successMessage(`Removed: ${basename7(path15)}`);
108503
+ for (const [path16] of contextFiles) {
108504
+ if (path16.includes(filename) || basename7(path16) === filename) {
108505
+ contextFiles.delete(path16);
108506
+ successMessage(`Removed: ${basename7(path16)}`);
105944
108507
  return;
105945
108508
  }
105946
108509
  }
@@ -106254,8 +108817,8 @@ init_source();
106254
108817
 
106255
108818
  // src/services/agent-loader.ts
106256
108819
  var import_fast_glob5 = __toESM(require_out4(), 1);
106257
- import fs14 from "fs/promises";
106258
- import path15 from "path";
108820
+ import fs17 from "fs/promises";
108821
+ import path16 from "path";
106259
108822
  var AGENT_PATTERNS = [
106260
108823
  ".codetyper/agent/**/*.agent.md",
106261
108824
  ".codetyper/agents/**/*.agent.md",
@@ -106274,11 +108837,11 @@ var DEFAULT_AGENT = {
106274
108837
  };
106275
108838
  var cachedRegistry = null;
106276
108839
  var extractNameFromFile = (filePath2) => {
106277
- const basename8 = path15.basename(filePath2, ".agent.md");
108840
+ const basename8 = path16.basename(filePath2, ".agent.md");
106278
108841
  return basename8.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
106279
108842
  };
106280
108843
  var extractIdFromFile = (filePath2) => {
106281
- return path15.basename(filePath2, ".agent.md").toLowerCase();
108844
+ return path16.basename(filePath2, ".agent.md").toLowerCase();
106282
108845
  };
106283
108846
  var parseFrontmatter = (content) => {
106284
108847
  const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;
@@ -106328,7 +108891,7 @@ var parseFrontmatter = (content) => {
106328
108891
  };
106329
108892
  var parseAgentFile = async (filePath2) => {
106330
108893
  try {
106331
- const content = await fs14.readFile(filePath2, "utf-8");
108894
+ const content = await fs17.readFile(filePath2, "utf-8");
106332
108895
  const { data: frontmatter, body } = parseFrontmatter(content);
106333
108896
  const id = extractIdFromFile(filePath2);
106334
108897
  const name = frontmatter.name ?? extractNameFromFile(filePath2);
@@ -106877,9 +109440,9 @@ var sendMessage = async (content, state4) => {
106877
109440
  let userMessage = content;
106878
109441
  if (state4.contextFiles.size > 0) {
106879
109442
  const contextParts = [];
106880
- for (const [path16, fileContent] of state4.contextFiles) {
106881
- const ext = extname4(path16).slice(1) || "txt";
106882
- contextParts.push(`File: ${basename8(path16)}
109443
+ for (const [path17, fileContent] of state4.contextFiles) {
109444
+ const ext = extname4(path17).slice(1) || "txt";
109445
+ contextParts.push(`File: ${basename8(path17)}
106883
109446
  \`\`\`${ext}
106884
109447
  ${fileContent}
106885
109448
  \`\`\``);
@@ -107035,9 +109598,9 @@ var executePrintMode2 = async (prompt2, state4) => {
107035
109598
  let userMessage = processedPrompt;
107036
109599
  if (state4.contextFiles.size > 0) {
107037
109600
  const contextParts = [];
107038
- for (const [path16, fileContent] of state4.contextFiles) {
107039
- const ext = extname5(path16).slice(1) || "txt";
107040
- contextParts.push(`File: ${basename9(path16)}
109601
+ for (const [path17, fileContent] of state4.contextFiles) {
109602
+ const ext = extname5(path17).slice(1) || "txt";
109603
+ contextParts.push(`File: ${basename9(path17)}
107041
109604
  \`\`\`${ext}
107042
109605
  ${fileContent}
107043
109606
  \`\`\``);
@@ -107606,8 +110169,8 @@ var handlePlan = async (options2) => {
107606
110169
  ]
107607
110170
  };
107608
110171
  if (output) {
107609
- const fs15 = await import("fs/promises");
107610
- await fs15.writeFile(output, JSON.stringify(plan, null, 2));
110172
+ const fs18 = await import("fs/promises");
110173
+ await fs18.writeFile(output, JSON.stringify(plan, null, 2));
107611
110174
  successMessage(`Plan saved to ${filePath(output)}`);
107612
110175
  } else {
107613
110176
  hightLigthedJson(plan);
@@ -107632,8 +110195,8 @@ var handleValidate = async (options2) => {
107632
110195
  console.log();
107633
110196
  startSpinner("Validating plan...");
107634
110197
  try {
107635
- const fs15 = await import("fs/promises");
107636
- const planData = await fs15.readFile(planFile, "utf-8");
110198
+ const fs18 = await import("fs/promises");
110199
+ const planData = await fs18.readFile(planFile, "utf-8");
107637
110200
  const plan = JSON.parse(planData);
107638
110201
  await new Promise((resolve4) => setTimeout(resolve4, 1000));
107639
110202
  const config2 = await getConfig();
@@ -107914,14 +110477,89 @@ var onLearningDetected = async (candidate) => {
107914
110477
 
107915
110478
  // src/commands/components/execute/execute.tsx
107916
110479
  init_mcp();
110480
+ var parseArgs = (argsString) => {
110481
+ const trimmed = argsString.trim();
110482
+ if (!trimmed)
110483
+ return;
110484
+ const args = [];
110485
+ let current = "";
110486
+ let inQuote = null;
110487
+ for (let i2 = 0;i2 < trimmed.length; i2++) {
110488
+ const char = trimmed[i2];
110489
+ if (inQuote) {
110490
+ if (char === inQuote) {
110491
+ inQuote = null;
110492
+ } else {
110493
+ current += char;
110494
+ }
110495
+ } else if (char === '"' || char === "'") {
110496
+ inQuote = char;
110497
+ } else if (char === " " || char === "\t") {
110498
+ if (current) {
110499
+ args.push(current);
110500
+ current = "";
110501
+ }
110502
+ } else {
110503
+ current += char;
110504
+ }
110505
+ }
110506
+ if (current) {
110507
+ args.push(current);
110508
+ }
110509
+ return args.length > 0 ? args : undefined;
110510
+ };
107917
110511
  var defaultHandleMCPAdd = async (data) => {
107918
- const serverArgs = data.args.trim() ? data.args.trim().split(/\s+/) : undefined;
110512
+ const serverArgs = parseArgs(data.args);
107919
110513
  await addServer(data.name, {
107920
110514
  command: data.command,
107921
110515
  args: serverArgs,
107922
110516
  enabled: true
107923
110517
  }, data.isGlobal);
107924
- await connectServer(data.name);
110518
+ appStore.addMcpServer({
110519
+ id: data.name,
110520
+ name: data.name,
110521
+ status: "disconnected",
110522
+ description: data.command
110523
+ });
110524
+ try {
110525
+ await connectServer(data.name);
110526
+ appStore.updateMcpServerStatus(data.name, "connected");
110527
+ } catch {
110528
+ appStore.updateMcpServerStatus(data.name, "error");
110529
+ }
110530
+ };
110531
+ var defaultHandleBrainSetJwtToken = async (jwtToken) => {
110532
+ await setJwtToken(jwtToken);
110533
+ const connected = await connect();
110534
+ if (connected) {
110535
+ const state4 = getState2();
110536
+ appStore.setBrainStatus("connected");
110537
+ appStore.setBrainUser(state4.user);
110538
+ appStore.setBrainCounts(state4.knowledgeCount, state4.memoryCount);
110539
+ appStore.setBrainShowBanner(false);
110540
+ } else {
110541
+ throw new Error("Failed to connect with the provided JWT token.");
110542
+ }
110543
+ };
110544
+ var defaultHandleBrainSetApiKey = async (apiKey) => {
110545
+ await setApiKey(apiKey);
110546
+ const connected = await connect();
110547
+ if (connected) {
110548
+ const state4 = getState2();
110549
+ appStore.setBrainStatus("connected");
110550
+ appStore.setBrainUser(state4.user);
110551
+ appStore.setBrainCounts(state4.knowledgeCount, state4.memoryCount);
110552
+ appStore.setBrainShowBanner(false);
110553
+ } else {
110554
+ throw new Error("Failed to connect with the provided API key.");
110555
+ }
110556
+ };
110557
+ var defaultHandleBrainLogout = async () => {
110558
+ await logout3();
110559
+ appStore.setBrainStatus("disconnected");
110560
+ appStore.setBrainUser(null);
110561
+ appStore.setBrainCounts(0, 0);
110562
+ appStore.setBrainShowBanner(true);
107925
110563
  };
107926
110564
  var renderApp = async (props) => {
107927
110565
  const {
@@ -107953,6 +110591,9 @@ var renderApp = async (props) => {
107953
110591
  onMCPAdd: props.handleMCPAdd ?? defaultHandleMCPAdd,
107954
110592
  onPermissionResponse: props.handlePermissionResponse ?? (() => {}),
107955
110593
  onLearningResponse: props.handleLearningResponse ?? (() => {}),
110594
+ onBrainSetJwtToken: props.handleBrainSetJwtToken ?? defaultHandleBrainSetJwtToken,
110595
+ onBrainSetApiKey: props.handleBrainSetApiKey ?? defaultHandleBrainSetApiKey,
110596
+ onBrainLogout: props.handleBrainLogout ?? defaultHandleBrainLogout,
107956
110597
  plan: props.plan
107957
110598
  });
107958
110599
  props.handleExit();
@@ -107962,34 +110603,34 @@ var renderApp = async (props) => {
107962
110603
  init_terminal2();
107963
110604
 
107964
110605
  // src/services/project-setup-service.ts
107965
- import fs15 from "fs/promises";
107966
- import path16 from "path";
110606
+ import fs18 from "fs/promises";
110607
+ import path17 from "path";
107967
110608
  var CODETYPER_DIR = ".codetyper";
107968
110609
  var AGENTS_DIR = "agents";
107969
110610
  var GITIGNORE_ENTRY = ".codetyper/";
107970
110611
  var fileExists2 = async (filePath2) => {
107971
110612
  try {
107972
- await fs15.access(filePath2);
110613
+ await fs18.access(filePath2);
107973
110614
  return true;
107974
110615
  } catch {
107975
110616
  return false;
107976
110617
  }
107977
110618
  };
107978
110619
  var isGitRepository = async (workingDir3) => {
107979
- return fileExists2(path16.join(workingDir3, ".git"));
110620
+ return fileExists2(path17.join(workingDir3, ".git"));
107980
110621
  };
107981
110622
  var ensureDirectoryExists = async (dirPath) => {
107982
110623
  try {
107983
- await fs15.mkdir(dirPath, { recursive: true });
110624
+ await fs18.mkdir(dirPath, { recursive: true });
107984
110625
  } catch {}
107985
110626
  };
107986
110627
  var addToGitignore = async (workingDir3) => {
107987
- const gitignorePath = path16.join(workingDir3, ".gitignore");
110628
+ const gitignorePath = path17.join(workingDir3, ".gitignore");
107988
110629
  try {
107989
110630
  let content = "";
107990
110631
  const exists = await fileExists2(gitignorePath);
107991
110632
  if (exists) {
107992
- content = await fs15.readFile(gitignorePath, "utf-8");
110633
+ content = await fs18.readFile(gitignorePath, "utf-8");
107993
110634
  const lines = content.split(`
107994
110635
  `).map((line2) => line2.trim());
107995
110636
  if (lines.includes(GITIGNORE_ENTRY) || lines.includes(CODETYPER_DIR)) {
@@ -108001,7 +110642,7 @@ var addToGitignore = async (workingDir3) => {
108001
110642
  ` : `${content}
108002
110643
  ${GITIGNORE_ENTRY}
108003
110644
  `;
108004
- await fs15.writeFile(gitignorePath, newContent, "utf-8");
110645
+ await fs18.writeFile(gitignorePath, newContent, "utf-8");
108005
110646
  return true;
108006
110647
  } catch {
108007
110648
  return false;
@@ -108242,17 +110883,17 @@ ${agent.prompt}
108242
110883
  `;
108243
110884
  };
108244
110885
  var createDefaultAgents = async (workingDir3) => {
108245
- const agentsDir = path16.join(workingDir3, CODETYPER_DIR, AGENTS_DIR);
110886
+ const agentsDir = path17.join(workingDir3, CODETYPER_DIR, AGENTS_DIR);
108246
110887
  const created = [];
108247
110888
  await ensureDirectoryExists(agentsDir);
108248
110889
  for (const agent of DEFAULT_AGENTS) {
108249
- const filePath2 = path16.join(agentsDir, `${agent.id}.agent.md`);
110890
+ const filePath2 = path17.join(agentsDir, `${agent.id}.agent.md`);
108250
110891
  if (await fileExists2(filePath2)) {
108251
110892
  continue;
108252
110893
  }
108253
110894
  try {
108254
110895
  const content = generateAgentFile(agent);
108255
- await fs15.writeFile(filePath2, content, "utf-8");
110896
+ await fs18.writeFile(filePath2, content, "utf-8");
108256
110897
  created.push(agent.id);
108257
110898
  } catch {}
108258
110899
  }
@@ -108277,12 +110918,12 @@ var setupProject = async (workingDir3) => {
108277
110918
  };
108278
110919
  var getSetupStatus = async (workingDir3) => {
108279
110920
  const hasGit = await isGitRepository(workingDir3);
108280
- const hasCodetyperDir = await fileExists2(path16.join(workingDir3, CODETYPER_DIR));
110921
+ const hasCodetyperDir = await fileExists2(path17.join(workingDir3, CODETYPER_DIR));
108281
110922
  let agentCount = 0;
108282
110923
  if (hasCodetyperDir) {
108283
- const agentsDir = path16.join(workingDir3, CODETYPER_DIR, AGENTS_DIR);
110924
+ const agentsDir = path17.join(workingDir3, CODETYPER_DIR, AGENTS_DIR);
108284
110925
  if (await fileExists2(agentsDir)) {
108285
- const files = await fs15.readdir(agentsDir);
110926
+ const files = await fs18.readdir(agentsDir);
108286
110927
  agentCount = files.filter((f) => f.endsWith(".agent.md")).length;
108287
110928
  }
108288
110929
  }
@@ -108598,13 +111239,13 @@ var approvePlan = () => {
108598
111239
 
108599
111240
  // src/utils/ensure-directories.ts
108600
111241
  init_paths();
108601
- import { mkdir as mkdir3 } from "fs/promises";
111242
+ import { mkdir as mkdir4 } from "fs/promises";
108602
111243
  var ensureXdgDirectories = async () => {
108603
- await mkdir3(DIRS.config, { recursive: true });
108604
- await mkdir3(DIRS.data, { recursive: true });
108605
- await mkdir3(DIRS.cache, { recursive: true });
108606
- await mkdir3(DIRS.state, { recursive: true });
108607
- await mkdir3(DIRS.sessions, { recursive: true });
111244
+ await mkdir4(DIRS.config, { recursive: true });
111245
+ await mkdir4(DIRS.data, { recursive: true });
111246
+ await mkdir4(DIRS.cache, { recursive: true });
111247
+ await mkdir4(DIRS.state, { recursive: true });
111248
+ await mkdir4(DIRS.sessions, { recursive: true });
108608
111249
  };
108609
111250
 
108610
111251
  // src/index.ts
@@ -108970,4 +111611,4 @@ ${plan.steps.map((s) => `${s.id}. ${s.description}`).join(`
108970
111611
  });
108971
111612
  program2.parse(process.argv);
108972
111613
 
108973
- //# debugId=0B841F2DBC1F214564756E2164756E21
111614
+ //# debugId=6760CDEC64E149A464756E2164756E21