snow-ai 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,6 +13,8 @@
13
13
 
14
14
  **QQ Group**: 910298558
15
15
 
16
+ **LinuxDO AI Community**: [https://linux.do](https://linux.do)
17
+
16
18
  _Agentic coding in your terminal_
17
19
 
18
20
  </div>
@@ -62,6 +64,7 @@ _Agentic coding in your terminal_
62
64
  - [LSP Configuration and Usage](docs/usage/en/19.LSP%20Configuration.md) - LSP config file, language server installation, ACE tool usage (definition/outline)
63
65
  - [SSE Service Mode](docs/usage/en/20.SSE%20Service%20Mode.md) - SSE server startup, API endpoints explanation, tool confirmation flow, permission configuration, YOLO mode, client integration examples
64
66
  - [Custom StatusLine Guide](docs/usage/en/21.Custom%20StatusLine%20Guide.md) - User-level StatusLine plugins, hook structure, override behavior, bilingual examples
67
+ - [Team Mode Guide](docs/usage/en/22.Team%20Mode%20Guide.md) - Multi-agent collaboration, parallel task execution, team management
65
68
 
66
69
  ### Recommended ROLE.md
67
70
 
@@ -75,7 +78,7 @@ _Agentic coding in your terminal_
75
78
 
76
79
  ### Prerequisites
77
80
 
78
- - **Node.js >= 16.x** (Requires ES2020 features support)
81
+ - **Node.js >= 18.x** (Requires ES2020 features support)
79
82
  - npm >= 8.3.0
80
83
 
81
84
  Check your Node.js version:
@@ -84,12 +87,12 @@ Check your Node.js version:
84
87
  node --version
85
88
  ```
86
89
 
87
- If your version is below 16.x, please upgrade first:
90
+ If your version is below 18.x, please upgrade first:
88
91
 
89
92
  ```bash
90
93
  # Using nvm (recommended)
91
- nvm install 16
92
- nvm use 16
94
+ nvm install 18
95
+ nvm use 18
93
96
 
94
97
  # Or download from official website
95
98
  # https://nodejs.org/
@@ -120,33 +123,39 @@ npm run link # builds and globally links snow
120
123
  ### Project Structure
121
124
 
122
125
  ```
123
- .snow/ # User configuration directory
126
+ source/ # Source code
127
+ ├── agents/ # AI agents implementation
128
+ ├── api/ # LLM API adapters
129
+ ├── hooks/ # React hooks for conversation
130
+ ├── i18n/ # Internationalization
131
+ ├── mcp/ # Model Context Protocol
132
+ ├── prompt/ # System prompt templates
133
+ ├── types/ # TypeScript type definitions
134
+ ├── ui/ # UI components (Ink)
135
+ └── utils/ # Utility functions
136
+
137
+ bundle/ # Build output (single-file executable)
138
+ dist/ # TypeScript compilation output
139
+ docs/ # Documentation
140
+ JetBrains/ # JetBrains plugin source
141
+ scripts/ # Build and utility scripts
142
+ VSIX/ # VSCode extension source
143
+ ```
144
+
145
+ ### User Configuration Directory
146
+
147
+ After running snow, `.snow/` directory is created in your home folder:
148
+
149
+ ```
150
+ ~/.snow/ # User configuration directory
124
151
  ├── log/ # Runtime logs (local, can be deleted)
125
152
  ├── profiles/ # Configuration profiles
126
153
  ├── sessions/ # Conversation history
127
- ├── snapshots/ # File snapshots
128
- ├── todos/ # TODO lists
129
154
  ├── tasks/ # Async tasks
130
- ├── task-logs/ # Async task logs
131
- ├── history/ # Command history
132
- ├── commands/ # Custom commands
133
155
  ├── hooks/ # Workflow hooks
134
- ├── sse-daemons/ # SSE daemon processes
135
- ├── sse-logs/ # SSE service logs
136
- ├── usage/ # Usage statistics
137
- ├── active-profile.json # Current active profile
138
156
  ├── config.json # API configuration
139
- ├── custom-headers.json # Custom request headers
140
157
  ├── mcp-config.json # MCP configuration
141
- ├── lsp-config.json # LSP configuration
142
- ├── proxy-config.json # Proxy settings
143
- ├── codebase.json # Codebase index settings
144
- ├── sub-agents.json # Sub-agent configuration
145
- ├── sensitive-commands.json # Sensitive command rules
146
- ├── theme.json # Theme settings
147
- ├── language.json # Language settings
148
- ├── history.json # History settings
149
- └── system-prompt.json # Custom system prompts
158
+ └── ... # Other config files
150
159
  ```
151
160
 
152
161
  ## Star History
package/bundle/cli.mjs CHANGED
@@ -45643,7 +45643,7 @@ var require_jsonfile = __commonJS({
45643
45643
  callback(null, obj2);
45644
45644
  });
45645
45645
  }
45646
- function readFileSync31(file2, options3) {
45646
+ function readFileSync32(file2, options3) {
45647
45647
  options3 = options3 || {};
45648
45648
  if (typeof options3 === "string") {
45649
45649
  options3 = { encoding: options3 };
@@ -45696,7 +45696,7 @@ var require_jsonfile = __commonJS({
45696
45696
  }
45697
45697
  fs56.writeFile(file2, str2, options3, callback);
45698
45698
  }
45699
- function writeFileSync24(file2, obj2, options3) {
45699
+ function writeFileSync25(file2, obj2, options3) {
45700
45700
  options3 = options3 || {};
45701
45701
  var fs56 = options3.fs || _fs;
45702
45702
  var str2 = stringify2(obj2, options3);
@@ -45709,9 +45709,9 @@ var require_jsonfile = __commonJS({
45709
45709
  }
45710
45710
  var jsonfile = {
45711
45711
  readFile: readFile3,
45712
- readFileSync: readFileSync31,
45712
+ readFileSync: readFileSync32,
45713
45713
  writeFile: writeFile4,
45714
- writeFileSync: writeFileSync24
45714
+ writeFileSync: writeFileSync25
45715
45715
  };
45716
45716
  module2.exports = jsonfile;
45717
45717
  }
@@ -65573,6 +65573,9 @@ Alternatively, use \`strategy: "theirs"\` to auto-accept all teammate changes, o
65573
65573
  - You can also send new work to standby teammates via \`team-message_teammate\` \u2014 they will wake up and resume.
65574
65574
 
65575
65575
  ### 7. Completion (**follow this order exactly**)
65576
+
65577
+ **EXTREMELY CRITICAL \u2014 DO NOT SKIP CLEANUP**: Many models consistently forget the final cleanup steps after merging. This leaves orphaned teammates and wasted worktrees. You MUST complete ALL steps below without exception.
65578
+
65576
65579
  1. Call \`team-wait_for_teammates\` \u2014 it returns when all teammates are on standby
65577
65580
  2. Review the returned messages and results
65578
65581
  3. **Shut down all teammates** with \`team-shutdown_teammate\`
@@ -65581,6 +65584,8 @@ Alternatively, use \`strategy: "theirs"\` to auto-accept all teammate changes, o
65581
65584
  6. Call \`team-cleanup_team\` to remove worktrees (will refuse if unmerged work exists)
65582
65585
  7. Synthesize results and report to the user
65583
65586
 
65587
+ **POST-COMPLETION VERIFICATION**: After step 6, confirm cleanup succeeded. If any teammate is still running or any worktree remains, you have FAILED to complete the team workflow.
65588
+
65584
65589
  ## Workflow Template (follow this in your FIRST response)
65585
65590
 
65586
65591
  1. **Decompose** the task into parallel workstreams (spend \u22641 paragraph on this)
@@ -65592,7 +65597,7 @@ Alternatively, use \`strategy: "theirs"\` to auto-accept all teammate changes, o
65592
65597
  7. **Synthesize** results and report back to the user
65593
65598
  8. **Clean up** \u2014 call \`team-cleanup_team\` to remove worktrees and disband
65594
65599
 
65595
- \u26A0\uFE0F **CRITICAL ORDER**: \`spawn_teammate\` MUST be called BEFORE \`create_task\`. The team is created on first spawn \u2014 calling \`create_task\` without an active team will fail.
65600
+ **CRITICAL ORDER**: \`spawn_teammate\` MUST be called BEFORE \`create_task\`. The team is created on first spawn \u2014 calling \`create_task\` without an active team will fail.
65596
65601
 
65597
65602
  PLACEHOLDER_FOR_TOOL_DISCOVERY_SECTION
65598
65603
 
@@ -104529,7 +104534,7 @@ ${error40.message}`;
104529
104534
  value: true
104530
104535
  });
104531
104536
  exports22.readFile = readFile3;
104532
- exports22.readFileSync = readFileSync31;
104537
+ exports22.readFileSync = readFileSync32;
104533
104538
  var _fs = _interopRequireDefault(__require("fs"));
104534
104539
  function _interopRequireDefault(obj2) {
104535
104540
  return obj2 && obj2.__esModule ? obj2 : {
@@ -104559,7 +104564,7 @@ ${error40.message}`;
104559
104564
  throw error40;
104560
104565
  }
104561
104566
  }
104562
- function readFileSync31(filepath, options3 = {}) {
104567
+ function readFileSync32(filepath, options3 = {}) {
104563
104568
  const throwNotFound = options3.throwNotFound === true;
104564
104569
  try {
104565
104570
  const content = _fs.default.readFileSync(filepath, "utf8");
@@ -219736,8 +219741,8 @@ ${error40.message}`;
219736
219741
  }
219737
219742
  return x;
219738
219743
  };
219739
- var defaultReadPackageSync = function defaultReadPackageSync2(readFileSync31, pkgfile) {
219740
- var body = readFileSync31(pkgfile);
219744
+ var defaultReadPackageSync = function defaultReadPackageSync2(readFileSync32, pkgfile) {
219745
+ var body = readFileSync32(pkgfile);
219741
219746
  try {
219742
219747
  var pkg = JSON.parse(body);
219743
219748
  return pkg;
@@ -219757,7 +219762,7 @@ ${error40.message}`;
219757
219762
  }
219758
219763
  var opts = normalizeOptions(x, options3);
219759
219764
  var isFile = opts.isFile || defaultIsFile;
219760
- var readFileSync31 = opts.readFileSync || fs56.readFileSync;
219765
+ var readFileSync32 = opts.readFileSync || fs56.readFileSync;
219761
219766
  var isDirectory = opts.isDirectory || defaultIsDir;
219762
219767
  var realpathSync = opts.realpathSync || defaultRealpathSync;
219763
219768
  var readPackageSync2 = opts.readPackageSync || defaultReadPackageSync;
@@ -219819,7 +219824,7 @@ ${error40.message}`;
219819
219824
  if (!isFile(pkgfile)) {
219820
219825
  return loadpkg(path62.dirname(dir));
219821
219826
  }
219822
- var pkg = readPackageSync2(readFileSync31, pkgfile);
219827
+ var pkg = readPackageSync2(readFileSync32, pkgfile);
219823
219828
  if (pkg && opts.packageFilter) {
219824
219829
  pkg = opts.packageFilter(pkg, dir);
219825
219830
  }
@@ -219832,7 +219837,7 @@ ${error40.message}`;
219832
219837
  var pkgfile = path62.join(maybeRealpathSync(realpathSync, x2, opts), "/package.json");
219833
219838
  if (isFile(pkgfile)) {
219834
219839
  try {
219835
- var pkg = readPackageSync2(readFileSync31, pkgfile);
219840
+ var pkg = readPackageSync2(readFileSync32, pkgfile);
219836
219841
  } catch (e) {
219837
219842
  }
219838
219843
  if (pkg && opts.packageFilter) {
@@ -306623,7 +306628,7 @@ var require_xlsx = __commonJS({
306623
306628
  if (DBF_SUPPORTED_VERSIONS.indexOf(n[0]) > -1 && n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
306624
306629
  return read_prn(data, d, o, str2);
306625
306630
  }
306626
- function readFileSync31(filename, opts) {
306631
+ function readFileSync32(filename, opts) {
306627
306632
  var o = opts || {};
306628
306633
  o.type = "file";
306629
306634
  return readSync(filename, o);
@@ -306858,7 +306863,7 @@ var require_xlsx = __commonJS({
306858
306863
  if (ext.match(/^\.[a-z]+$/)) o.bookType = ext.slice(1);
306859
306864
  o.bookType = _BT[o.bookType] || o.bookType;
306860
306865
  }
306861
- function writeFileSync24(wb, filename, opts) {
306866
+ function writeFileSync25(wb, filename, opts) {
306862
306867
  var o = opts || {};
306863
306868
  o.type = "file";
306864
306869
  o.file = filename;
@@ -307459,11 +307464,11 @@ var require_xlsx = __commonJS({
307459
307464
  if (typeof parse_xlscfb !== "undefined") XLSX3.parse_xlscfb = parse_xlscfb;
307460
307465
  XLSX3.parse_zip = parse_zip;
307461
307466
  XLSX3.read = readSync;
307462
- XLSX3.readFile = readFileSync31;
307463
- XLSX3.readFileSync = readFileSync31;
307467
+ XLSX3.readFile = readFileSync32;
307468
+ XLSX3.readFileSync = readFileSync32;
307464
307469
  XLSX3.write = writeSync;
307465
- XLSX3.writeFile = writeFileSync24;
307466
- XLSX3.writeFileSync = writeFileSync24;
307470
+ XLSX3.writeFile = writeFileSync25;
307471
+ XLSX3.writeFileSync = writeFileSync25;
307467
307472
  XLSX3.writeFileAsync = writeFileAsync;
307468
307473
  XLSX3.utils = utils3;
307469
307474
  XLSX3.writeXLSX = writeSyncXLSX;
@@ -437253,9 +437258,9 @@ function getTeamConfigPath(teamName) {
437253
437258
  return join20(getTeamDir(teamName), "config.json");
437254
437259
  }
437255
437260
  function createTeam(teamName, leadInstanceId) {
437256
- const existing = getActiveTeam();
437261
+ const existing = getTeam(teamName);
437257
437262
  if (existing) {
437258
- throw new Error(`An active team "${existing.name}" already exists. Clean it up before creating a new one.`);
437263
+ throw new Error(`Team "${teamName}" already exists.`);
437259
437264
  }
437260
437265
  const teamDir = getTeamDir(teamName);
437261
437266
  ensureDir(teamDir);
@@ -437739,6 +437744,17 @@ function mergeTeammateBranch(teamName, memberName, strategy = "manual") {
437739
437744
  return { success: true, merged: true, commitCount, filesChanged };
437740
437745
  } catch (mergeError) {
437741
437746
  const conflictFiles = getConflictedFiles();
437747
+ if (strategy === "auto" && conflictFiles.length > 0) {
437748
+ return {
437749
+ success: false,
437750
+ merged: false,
437751
+ hasConflicts: true,
437752
+ commitCount,
437753
+ filesChanged: 0,
437754
+ conflictFiles,
437755
+ error: `Merge conflicts in ${conflictFiles.length} file(s). Awaiting AI resolution.`
437756
+ };
437757
+ }
437742
437758
  if (strategy !== "manual" || conflictFiles.length === 0) {
437743
437759
  try {
437744
437760
  execSync4("git merge --abort", { stdio: "pipe" });
@@ -438409,7 +438425,7 @@ ${role ? `Your role: ${role}` : ""}
438409
438425
 
438410
438426
  ### Other Teammates`;
438411
438427
  if (otherTeammates.length > 0) {
438412
- teamContext += "\n" + otherTeammates.map((t) => `- ${t.memberName}${t.role ? ` (${t.role})` : ""} [${t.instanceId}]`).join("\n");
438428
+ teamContext += "\n" + otherTeammates.map((t) => `- ${t.memberName}${t.role ? ` (${t.role})` : ""} [ID: ${t.memberId}]`).join("\n");
438413
438429
  } else {
438414
438430
  teamContext += "\nNo other teammates are currently active.";
438415
438431
  }
@@ -438663,7 +438679,7 @@ ${msg.content}`
438663
438679
  const sent = teamTracker.sendMessageToLead(instanceId, content);
438664
438680
  resultContent = sent ? "Message sent to team lead." : "Failed to send message to team lead.";
438665
438681
  } else {
438666
- let targetTeammate = teamTracker.findByMemberName(target) || teamTracker.findByMemberId(target);
438682
+ let targetTeammate = teamTracker.findByMemberName(target) || teamTracker.findByMemberId(target) || teamTracker.getTeammate(target);
438667
438683
  if (targetTeammate) {
438668
438684
  const sent = teamTracker.sendMessageToTeammate(instanceId, targetTeammate.instanceId, content);
438669
438685
  resultContent = sent ? `Message sent to ${targetTeammate.memberName}.` : `Failed to send message to ${target}.`;
@@ -440150,15 +440166,15 @@ async function rollbackTeamState(sessionId, targetMessageIndex) {
440150
440166
  return 0;
440151
440167
  const { teamTracker: teamTracker2 } = await Promise.resolve().then(() => (init_teamTracker(), teamTracker_exports));
440152
440168
  const { cleanupTeamWorktrees: cleanupTeamWorktrees2 } = await Promise.resolve().then(() => (init_teamWorktree(), teamWorktree_exports));
440153
- const { disbandTeam: disbandTeam2, getActiveTeam: getActiveTeam2 } = await Promise.resolve().then(() => (init_teamConfig(), teamConfig_exports));
440169
+ const { disbandTeam: disbandTeam2 } = await Promise.resolve().then(() => (init_teamConfig(), teamConfig_exports));
440154
440170
  teamTracker2.abortAllTeammates();
440155
440171
  const teamNames = /* @__PURE__ */ new Set();
440156
440172
  for (const event of events) {
440157
440173
  teamNames.add(event.teamName);
440158
440174
  }
440159
- const activeTeam = getActiveTeam2();
440160
- if (activeTeam) {
440161
- teamNames.add(activeTeam.name);
440175
+ const ownTeamName = teamTracker2.getActiveTeamName();
440176
+ if (ownTeamName) {
440177
+ teamNames.add(ownTeamName);
440162
440178
  }
440163
440179
  let cleanedCount = 0;
440164
440180
  for (const teamName of teamNames) {
@@ -440194,6 +440210,28 @@ function deleteTeamSnapshotsFromIndex(sessionId, targetMessageIndex) {
440194
440210
  if (changed)
440195
440211
  saveSnapshotData(data);
440196
440212
  }
440213
+ function deleteTeamSnapshotsByTeamName(sessionId, teamName) {
440214
+ const data = readSnapshotData();
440215
+ let changed = false;
440216
+ for (const key of Object.keys(data)) {
440217
+ if (!key.startsWith(`${sessionId}:`))
440218
+ continue;
440219
+ const events = data[key];
440220
+ if (!events)
440221
+ continue;
440222
+ const filtered = events.filter((e) => e.teamName !== teamName);
440223
+ if (filtered.length !== events.length) {
440224
+ changed = true;
440225
+ if (filtered.length === 0) {
440226
+ delete data[key];
440227
+ } else {
440228
+ data[key] = filtered;
440229
+ }
440230
+ }
440231
+ }
440232
+ if (changed)
440233
+ saveSnapshotData(data);
440234
+ }
440197
440235
  function clearAllTeamSnapshots(sessionId) {
440198
440236
  const data = readSnapshotData();
440199
440237
  let changed = false;
@@ -440214,7 +440252,7 @@ var init_teamSnapshot = __esm({
440214
440252
  });
440215
440253
 
440216
440254
  // dist/mcp/team.js
440217
- import { existsSync as existsSync23 } from "fs";
440255
+ import { existsSync as existsSync23, readFileSync as readFileSync21, writeFileSync as writeFileSync15 } from "fs";
440218
440256
  function getTeamMCPTools() {
440219
440257
  return teamService.getTools();
440220
440258
  }
@@ -440231,6 +440269,111 @@ var init_team = __esm({
440231
440269
  init_teamSnapshot();
440232
440270
  init_subAgentMessageHandler();
440233
440271
  TeamService = class {
440272
+ getOwnTeam() {
440273
+ const teamName = teamTracker.getActiveTeamName();
440274
+ if (!teamName)
440275
+ return null;
440276
+ const team = getTeam(teamName);
440277
+ return team && team.status === "active" ? team : null;
440278
+ }
440279
+ /**
440280
+ * Use AI to resolve Git merge conflicts in the working directory.
440281
+ * Reads each conflicted file, sends it to the configured LLM for intelligent
440282
+ * resolution, writes the resolved content back, and stages the file.
440283
+ * Falls back to `git checkout --theirs` when AI resolution fails for a file.
440284
+ */
440285
+ async aiResolveConflicts(conflictFiles, memberName) {
440286
+ const { getOpenAiConfig: getOpenAiConfig2 } = await Promise.resolve().then(() => (init_apiConfig(), apiConfig_exports));
440287
+ const { createStreamingChatCompletion: createStreamingChatCompletion2 } = await Promise.resolve().then(() => (init_chat(), chat_exports));
440288
+ const { createStreamingAnthropicCompletion: createStreamingAnthropicCompletion2 } = await Promise.resolve().then(() => (init_anthropic(), anthropic_exports));
440289
+ const { createStreamingGeminiCompletion: createStreamingGeminiCompletion2 } = await Promise.resolve().then(() => (init_gemini(), gemini_exports));
440290
+ const { createStreamingResponse: createStreamingResponse2 } = await Promise.resolve().then(() => (init_responses(), responses_exports));
440291
+ const { execSync: execSync11 } = await import("child_process");
440292
+ const config3 = getOpenAiConfig2();
440293
+ const model = config3.advancedModel || config3.basicModel || "gpt-4o-mini";
440294
+ const method = config3.requestMethod || "chat";
440295
+ const resolved = [];
440296
+ const failed = [];
440297
+ for (const file2 of conflictFiles) {
440298
+ let content;
440299
+ try {
440300
+ content = readFileSync21(file2, "utf8");
440301
+ } catch {
440302
+ failed.push(file2);
440303
+ continue;
440304
+ }
440305
+ if (!content.includes("<<<<<<<")) {
440306
+ try {
440307
+ execSync11(`git add "${file2}"`, { stdio: "pipe" });
440308
+ resolved.push(file2);
440309
+ } catch {
440310
+ failed.push(file2);
440311
+ }
440312
+ continue;
440313
+ }
440314
+ const prompt = [
440315
+ "You are resolving a Git merge conflict.",
440316
+ "Below is the content of a file with conflict markers.",
440317
+ "",
440318
+ "- `<<<<<<< HEAD` marks the current branch (main/lead).",
440319
+ "- `=======` separates the two versions.",
440320
+ `- \`>>>>>>>\` marks the incoming branch (teammate "${memberName}").`,
440321
+ "",
440322
+ "Rules:",
440323
+ "- Produce the correctly merged file that preserves ALL intended changes from BOTH sides.",
440324
+ "- If changes are complementary (e.g. different functions added), include both.",
440325
+ "- If changes directly conflict (e.g. same line modified differently), combine them intelligently.",
440326
+ "- Output ONLY the resolved file content. No explanations, no markdown fences, no extra text.",
440327
+ "",
440328
+ `File: ${file2}`,
440329
+ "---",
440330
+ content
440331
+ ].join("\n");
440332
+ const messages = [{ role: "user", content: prompt }];
440333
+ let aiResult = "";
440334
+ try {
440335
+ const collectContent = async (stream) => {
440336
+ for await (const chunk2 of stream) {
440337
+ if (chunk2.type === "content" && chunk2.content) {
440338
+ aiResult += chunk2.content;
440339
+ }
440340
+ }
440341
+ };
440342
+ switch (method) {
440343
+ case "anthropic":
440344
+ await collectContent(createStreamingAnthropicCompletion2({ model, messages, max_tokens: config3.maxTokens || 8192, temperature: 0, disableThinking: true }));
440345
+ break;
440346
+ case "gemini":
440347
+ await collectContent(createStreamingGeminiCompletion2({ model, messages }));
440348
+ break;
440349
+ case "responses":
440350
+ await collectContent(createStreamingResponse2({ model, messages }));
440351
+ break;
440352
+ case "chat":
440353
+ default:
440354
+ await collectContent(createStreamingChatCompletion2({ model, messages, temperature: 0 }));
440355
+ break;
440356
+ }
440357
+ if (aiResult && !aiResult.includes("<<<<<<<")) {
440358
+ writeFileSync15(file2, aiResult, "utf8");
440359
+ execSync11(`git add "${file2}"`, { stdio: "pipe" });
440360
+ resolved.push(file2);
440361
+ } else {
440362
+ throw new Error("AI output still contains conflict markers or is empty");
440363
+ }
440364
+ } catch (aiError) {
440365
+ console.error(`[Team] AI conflict resolution failed for ${file2}, falling back to --theirs:`, aiError);
440366
+ try {
440367
+ execSync11(`git checkout --theirs "${file2}"`, { stdio: "pipe" });
440368
+ execSync11(`git add "${file2}"`, { stdio: "pipe" });
440369
+ resolved.push(file2);
440370
+ } catch {
440371
+ failed.push(file2);
440372
+ }
440373
+ }
440374
+ }
440375
+ return { resolved, failed };
440376
+ }
440234
440377
  async execute(options3) {
440235
440378
  const { toolName, args: args2 } = options3;
440236
440379
  switch (toolName) {
@@ -440280,7 +440423,7 @@ var init_team = __esm({
440280
440423
  if (!isGitRepo()) {
440281
440424
  throw new Error("Agent Teams require a Git repository. Initialize git first.");
440282
440425
  }
440283
- let team = getActiveTeam();
440426
+ let team = this.getOwnTeam();
440284
440427
  const isNewTeam = !team;
440285
440428
  if (!team) {
440286
440429
  const teamName = `team-${Date.now()}`;
@@ -440323,7 +440466,7 @@ var init_team = __esm({
440323
440466
  if (!targetId || !content) {
440324
440467
  throw new Error('message_teammate requires "target_id" and "content"');
440325
440468
  }
440326
- let teammate = teamTracker.findByMemberId(targetId) || teamTracker.findByMemberName(targetId);
440469
+ let teammate = teamTracker.findByMemberId(targetId) || teamTracker.findByMemberName(targetId) || teamTracker.getTeammate(targetId);
440327
440470
  if (!teammate) {
440328
440471
  return {
440329
440472
  success: false,
@@ -440353,7 +440496,7 @@ var init_team = __esm({
440353
440496
  if (!targetId) {
440354
440497
  throw new Error('shutdown_teammate requires "target_id"');
440355
440498
  }
440356
- let teammate = teamTracker.findByMemberId(targetId) || teamTracker.findByMemberName(targetId);
440499
+ let teammate = teamTracker.findByMemberId(targetId) || teamTracker.findByMemberName(targetId) || teamTracker.getTeammate(targetId);
440357
440500
  if (!teammate) {
440358
440501
  return {
440359
440502
  success: false,
@@ -440452,7 +440595,7 @@ var init_team = __esm({
440452
440595
  };
440453
440596
  }
440454
440597
  createTask(args2) {
440455
- const team = getActiveTeam();
440598
+ const team = this.getOwnTeam();
440456
440599
  if (!team) {
440457
440600
  throw new Error("No active team. You must call spawn_teammate first \u2014 the team is created automatically when the first teammate is spawned. Call spawn_teammate, then create_task.");
440458
440601
  }
@@ -440472,7 +440615,7 @@ var init_team = __esm({
440472
440615
  };
440473
440616
  }
440474
440617
  updateTask(args2) {
440475
- const team = getActiveTeam();
440618
+ const team = this.getOwnTeam();
440476
440619
  if (!team) {
440477
440620
  throw new Error("No active team.");
440478
440621
  }
@@ -440492,7 +440635,7 @@ var init_team = __esm({
440492
440635
  return { success: true, result: `Task ${taskId} updated.` };
440493
440636
  }
440494
440637
  listTasks() {
440495
- const team = getActiveTeam();
440638
+ const team = this.getOwnTeam();
440496
440639
  if (!team) {
440497
440640
  return { success: true, result: "No active team.", tasks: [] };
440498
440641
  }
@@ -440524,8 +440667,8 @@ var init_team = __esm({
440524
440667
  }))
440525
440668
  };
440526
440669
  }
440527
- mergeTeammateWork(args2) {
440528
- const team = getActiveTeam();
440670
+ async mergeTeammateWork(args2) {
440671
+ const team = this.getOwnTeam();
440529
440672
  if (!team) {
440530
440673
  throw new Error("No active team.");
440531
440674
  }
@@ -440558,6 +440701,25 @@ var init_team = __esm({
440558
440701
  success: true,
440559
440702
  result: `${member.name} has no changes to merge.`
440560
440703
  };
440704
+ } else if (result2.hasConflicts && strategy === "auto") {
440705
+ const aiResult = await this.aiResolveConflicts(result2.conflictFiles || [], member.name);
440706
+ if (aiResult.failed.length > 0) {
440707
+ abortCurrentMerge();
440708
+ return {
440709
+ success: false,
440710
+ error: `AI conflict resolution failed for ${aiResult.failed.length} file(s): ${aiResult.failed.join(", ")}`,
440711
+ conflictFiles: aiResult.failed
440712
+ };
440713
+ }
440714
+ const mergeComplete = completeMerge(`[Snow Team] AI-resolved merge of ${member.name}'s work`);
440715
+ if (mergeComplete.success) {
440716
+ return {
440717
+ success: true,
440718
+ result: `Merged ${result2.commitCount} commit(s) from ${member.name}. AI resolved conflicts in ${aiResult.resolved.length} file(s): ${aiResult.resolved.join(", ")}.`,
440719
+ autoResolved: aiResult.resolved
440720
+ };
440721
+ }
440722
+ return { success: false, error: mergeComplete.error };
440561
440723
  } else if (result2.hasConflicts) {
440562
440724
  return {
440563
440725
  success: false,
@@ -440574,8 +440736,8 @@ var init_team = __esm({
440574
440736
  };
440575
440737
  }
440576
440738
  }
440577
- mergeAllTeammateWork(args2) {
440578
- const team = getActiveTeam();
440739
+ async mergeAllTeammateWork(args2) {
440740
+ const team = this.getOwnTeam();
440579
440741
  if (!team) {
440580
440742
  throw new Error("No active team.");
440581
440743
  }
@@ -440612,6 +440774,39 @@ var init_team = __esm({
440612
440774
  commits: mergeResult.commitCount,
440613
440775
  files: mergeResult.filesChanged
440614
440776
  });
440777
+ } else if (mergeResult.hasConflicts && strategy === "auto") {
440778
+ const aiResult = await this.aiResolveConflicts(mergeResult.conflictFiles || [], member.name);
440779
+ if (aiResult.failed.length > 0) {
440780
+ abortCurrentMerge();
440781
+ results.push({
440782
+ name: member.name,
440783
+ merged: false,
440784
+ commits: mergeResult.commitCount,
440785
+ files: 0,
440786
+ error: `AI conflict resolution failed for: ${aiResult.failed.join(", ")}`,
440787
+ conflictFiles: aiResult.failed
440788
+ });
440789
+ break;
440790
+ }
440791
+ const mergeComplete = completeMerge(`[Snow Team] AI-resolved merge of ${member.name}'s work`);
440792
+ if (mergeComplete.success) {
440793
+ results.push({
440794
+ name: member.name,
440795
+ merged: true,
440796
+ commits: mergeResult.commitCount,
440797
+ files: (mergeResult.conflictFiles || []).length,
440798
+ autoResolved: aiResult.resolved
440799
+ });
440800
+ } else {
440801
+ results.push({
440802
+ name: member.name,
440803
+ merged: false,
440804
+ commits: mergeResult.commitCount,
440805
+ files: 0,
440806
+ error: mergeComplete.error
440807
+ });
440808
+ break;
440809
+ }
440615
440810
  } else if (mergeResult.hasConflicts) {
440616
440811
  results.push({
440617
440812
  name: member.name,
@@ -440645,6 +440840,7 @@ var init_team = __esm({
440645
440840
  }
440646
440841
  const mergedCount = results.filter((r) => r.merged).length;
440647
440842
  const totalCommits = results.reduce((sum, r) => sum + r.commits, 0);
440843
+ const allAutoResolved = results.flatMap((r) => r.autoResolved || []);
440648
440844
  const failedResult = results.find((r) => {
440649
440845
  var _a20;
440650
440846
  return r.error && !((_a20 = r.conflictFiles) == null ? void 0 : _a20.length);
@@ -440656,10 +440852,12 @@ var init_team = __esm({
440656
440852
  results
440657
440853
  };
440658
440854
  }
440855
+ const autoInfo = allAutoResolved.length > 0 ? ` AI resolved conflicts in ${allAutoResolved.length} file(s): ${allAutoResolved.join(", ")}.` : "";
440659
440856
  return {
440660
440857
  success: true,
440661
- result: `All teammate work merged. ${mergedCount} teammate(s) with changes, ${totalCommits} total commit(s).`,
440662
- results
440858
+ result: `All teammate work merged. ${mergedCount} teammate(s) with changes, ${totalCommits} total commit(s).${autoInfo}`,
440859
+ results,
440860
+ autoResolved: allAutoResolved.length > 0 ? allAutoResolved : void 0
440663
440861
  };
440664
440862
  }
440665
440863
  resolveMergeConflicts() {
@@ -440697,7 +440895,7 @@ var init_team = __esm({
440697
440895
  return { success: false, error: result2.error };
440698
440896
  }
440699
440897
  async cleanupTeam() {
440700
- const team = getActiveTeam();
440898
+ const team = this.getOwnTeam();
440701
440899
  if (!team) {
440702
440900
  return { success: false, error: "No active team to clean up." };
440703
440901
  }
@@ -440731,6 +440929,10 @@ var init_team = __esm({
440731
440929
  disbandTeam(team.name);
440732
440930
  teamTracker.clearActiveTeam();
440733
440931
  clearAllTeammateStreamEntries();
440932
+ const ctx = getConversationContext();
440933
+ if (ctx) {
440934
+ deleteTeamSnapshotsByTeamName(ctx.sessionId, team.name);
440935
+ }
440734
440936
  return {
440735
440937
  success: true,
440736
440938
  result: `Team "${team.name}" has been cleaned up. Worktrees removed, team disbanded.`
@@ -440743,7 +440945,7 @@ var init_team = __esm({
440743
440945
  if (!targetId || approved === void 0) {
440744
440946
  throw new Error('approve_plan requires "target_id" and "approved"');
440745
440947
  }
440746
- let teammate = teamTracker.findByMemberId(targetId) || teamTracker.findByMemberName(targetId);
440948
+ let teammate = teamTracker.findByMemberId(targetId) || teamTracker.findByMemberName(targetId) || teamTracker.getTeammate(targetId);
440747
440949
  if (!teammate) {
440748
440950
  return { success: false, error: `Teammate "${targetId}" not found.` };
440749
440951
  }
@@ -440869,18 +441071,18 @@ var init_team = __esm({
440869
441071
  type: "object",
440870
441072
  properties: {
440871
441073
  name: { type: "string", description: "The name of the teammate whose work to merge." },
440872
- strategy: { type: "string", enum: ["manual", "theirs", "ours"], description: '"manual" (default): pause on conflicts for you to resolve. "theirs": auto-accept all teammate changes on conflict. "ours": auto-keep main branch changes on conflict.' }
441074
+ strategy: { type: "string", enum: ["manual", "theirs", "ours", "auto"], description: `"manual" (default): pause on conflicts for you to resolve. "theirs": auto-accept all teammate changes on conflict. "ours": auto-keep main branch changes on conflict. "auto": try normal merge, auto-resolve conflicts by accepting teammate's version.` }
440873
441075
  },
440874
441076
  required: ["name"]
440875
441077
  }
440876
441078
  },
440877
441079
  {
440878
441080
  name: "merge_all_teammate_work",
440879
- description: `Merge ALL teammates' branches sequentially. Stops on first conflict (in "manual" mode) so you can resolve it. MUST call before cleanup_team.`,
441081
+ description: `Merge ALL teammates' branches sequentially. Stops on first conflict (in "manual" mode) so you can resolve it. With "auto" strategy, conflicts are auto-resolved and merging continues. MUST call before cleanup_team.`,
440880
441082
  inputSchema: {
440881
441083
  type: "object",
440882
441084
  properties: {
440883
- strategy: { type: "string", enum: ["manual", "theirs", "ours"], description: '"manual" (default): stop on conflicts for resolution. "theirs": auto-accept teammate changes. "ours": auto-keep main branch.' }
441085
+ strategy: { type: "string", enum: ["manual", "theirs", "ours", "auto"], description: `"manual" (default): stop on conflicts for resolution. "theirs": auto-accept teammate changes. "ours": auto-keep main branch. "auto": try normal merge, auto-resolve conflicts by accepting teammate's version.` }
440884
441086
  },
440885
441087
  required: []
440886
441088
  }
@@ -448882,7 +449084,7 @@ var init_LSPClient = __esm({
448882
449084
 
448883
449085
  // dist/mcp/lsp/LSPServerRegistry.js
448884
449086
  import { exec as exec6 } from "child_process";
448885
- import { existsSync as existsSync25, mkdirSync as mkdirSync16, readFileSync as readFileSync21, writeFileSync as writeFileSync15 } from "fs";
449087
+ import { existsSync as existsSync25, mkdirSync as mkdirSync16, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "fs";
448886
449088
  import { homedir as homedir14 } from "os";
448887
449089
  import { join as join26 } from "path";
448888
449090
  import { promisify } from "util";
@@ -448963,14 +449165,14 @@ function loadServersFromDisk() {
448963
449165
  ensureConfigDirectory5();
448964
449166
  if (!existsSync25(LSP_CONFIG_FILE)) {
448965
449167
  try {
448966
- writeFileSync15(LSP_CONFIG_FILE, JSON.stringify(getDefaultConfigFile(), null, 2), "utf8");
449168
+ writeFileSync16(LSP_CONFIG_FILE, JSON.stringify(getDefaultConfigFile(), null, 2), "utf8");
448967
449169
  } catch (error40) {
448968
449170
  console.debug("Failed to write default lsp-config.json:", error40);
448969
449171
  }
448970
449172
  return DEFAULT_LSP_SERVERS;
448971
449173
  }
448972
449174
  try {
448973
- const configText = readFileSync21(LSP_CONFIG_FILE, "utf8");
449175
+ const configText = readFileSync22(LSP_CONFIG_FILE, "utf8");
448974
449176
  const parsed = JSON.parse(configText);
448975
449177
  const serversFromConfig = parseLspConfigFile(parsed);
448976
449178
  return serversFromConfig ?? DEFAULT_LSP_SERVERS;
@@ -453146,7 +453348,7 @@ __export(languageConfig_exports, {
453146
453348
  });
453147
453349
  import { homedir as homedir16 } from "os";
453148
453350
  import { join as join29 } from "path";
453149
- import { existsSync as existsSync27, mkdirSync as mkdirSync17, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "fs";
453351
+ import { existsSync as existsSync27, mkdirSync as mkdirSync17, readFileSync as readFileSync23, writeFileSync as writeFileSync17 } from "fs";
453150
453352
  function ensureConfigDirectory6() {
453151
453353
  if (!existsSync27(CONFIG_DIR7)) {
453152
453354
  mkdirSync17(CONFIG_DIR7, { recursive: true });
@@ -453159,7 +453361,7 @@ function loadLanguageConfig() {
453159
453361
  return DEFAULT_CONFIG3;
453160
453362
  }
453161
453363
  try {
453162
- const configData = readFileSync22(LANGUAGE_CONFIG_FILE, "utf-8");
453364
+ const configData = readFileSync23(LANGUAGE_CONFIG_FILE, "utf-8");
453163
453365
  const config3 = JSON.parse(configData);
453164
453366
  return {
453165
453367
  ...DEFAULT_CONFIG3,
@@ -453173,7 +453375,7 @@ function saveLanguageConfig(config3) {
453173
453375
  ensureConfigDirectory6();
453174
453376
  try {
453175
453377
  const configData = JSON.stringify(config3, null, 2);
453176
- writeFileSync16(LANGUAGE_CONFIG_FILE, configData, "utf-8");
453378
+ writeFileSync17(LANGUAGE_CONFIG_FILE, configData, "utf-8");
453177
453379
  } catch (error40) {
453178
453380
  console.error("Failed to save language config:", error40);
453179
453381
  }
@@ -459378,6 +459580,9 @@ function extractMultimodalContent(result2) {
459378
459580
  images: images.length > 0 ? images : void 0
459379
459581
  };
459380
459582
  }
459583
+ if (typeof result2 === "string") {
459584
+ return { textContent: result2 };
459585
+ }
459381
459586
  return {
459382
459587
  textContent: JSON.stringify(result2)
459383
459588
  };
@@ -459556,12 +459761,31 @@ ${injectedSummary}`
459556
459761
  }
459557
459762
  } else {
459558
459763
  const toolResult = await executeMCPTool(toolCall.function.name, args2, abortSignal, onTokenUpdate);
459764
+ let editDiffData;
459765
+ if (typeof toolResult === "object" && toolResult !== null && (toolCall.function.name === "filesystem-edit" || toolCall.function.name === "filesystem-edit_search")) {
459766
+ if (toolResult.oldContent && toolResult.newContent) {
459767
+ editDiffData = {
459768
+ oldContent: toolResult.oldContent,
459769
+ newContent: toolResult.newContent,
459770
+ filename: args2["filePath"],
459771
+ completeOldContent: toolResult.completeOldContent,
459772
+ completeNewContent: toolResult.completeNewContent,
459773
+ contextStartLine: toolResult.contextStartLine
459774
+ };
459775
+ } else if (toolResult.results && Array.isArray(toolResult.results)) {
459776
+ editDiffData = {
459777
+ batchResults: toolResult.results,
459778
+ isBatch: true
459779
+ };
459780
+ }
459781
+ }
459559
459782
  const { textContent, images } = extractMultimodalContent(toolResult);
459560
459783
  result2 = {
459561
459784
  tool_call_id: toolCall.id,
459562
459785
  role: "tool",
459563
459786
  content: textContent,
459564
- images
459787
+ images,
459788
+ editDiffData
459565
459789
  };
459566
459790
  }
459567
459791
  } catch (error40) {
@@ -461872,28 +462096,34 @@ function buildToolResultMessages(toolResults, receivedToolCalls, parallelGroupId
461872
462096
  return resultMessages;
461873
462097
  }
461874
462098
  function extractEditDiffData(toolCall, result2) {
462099
+ if (toolCall.function.name !== "filesystem-edit" && toolCall.function.name !== "filesystem-edit_search") {
462100
+ return void 0;
462101
+ }
461875
462102
  const isError2 = result2.content.startsWith("Error:");
461876
- if ((toolCall.function.name === "filesystem-edit" || toolCall.function.name === "filesystem-edit_search") && !isError2) {
461877
- try {
461878
- const resultData = JSON.parse(result2.content);
461879
- if (resultData.oldContent && resultData.newContent) {
461880
- return {
461881
- oldContent: resultData.oldContent,
461882
- newContent: resultData.newContent,
461883
- filename: JSON.parse(toolCall.function.arguments).filePath,
461884
- completeOldContent: resultData.completeOldContent,
461885
- completeNewContent: resultData.completeNewContent,
461886
- contextStartLine: resultData.contextStartLine
461887
- };
461888
- }
461889
- if (resultData.results && Array.isArray(resultData.results)) {
461890
- return {
461891
- batchResults: resultData.results,
461892
- isBatch: true
461893
- };
461894
- }
461895
- } catch {
462103
+ if (isError2)
462104
+ return void 0;
462105
+ if (result2.editDiffData) {
462106
+ return result2.editDiffData;
462107
+ }
462108
+ try {
462109
+ const resultData = JSON.parse(result2.content);
462110
+ if (resultData.oldContent && resultData.newContent) {
462111
+ return {
462112
+ oldContent: resultData.oldContent,
462113
+ newContent: resultData.newContent,
462114
+ filename: JSON.parse(toolCall.function.arguments).filePath,
462115
+ completeOldContent: resultData.completeOldContent,
462116
+ completeNewContent: resultData.completeNewContent,
462117
+ contextStartLine: resultData.contextStartLine
462118
+ };
462119
+ }
462120
+ if (resultData.results && Array.isArray(resultData.results)) {
462121
+ return {
462122
+ batchResults: resultData.results,
462123
+ isBatch: true
462124
+ };
461896
462125
  }
462126
+ } catch {
461897
462127
  }
461898
462128
  return void 0;
461899
462129
  }
@@ -462505,7 +462735,7 @@ __export(taskExecutor_exports, {
462505
462735
  executeTaskInBackground: () => executeTaskInBackground
462506
462736
  });
462507
462737
  import { spawn as spawn9 } from "child_process";
462508
- import { writeFileSync as writeFileSync17, appendFileSync, existsSync as existsSync28, mkdirSync as mkdirSync18 } from "fs";
462738
+ import { writeFileSync as writeFileSync18, appendFileSync, existsSync as existsSync28, mkdirSync as mkdirSync18 } from "fs";
462509
462739
  import { join as join31 } from "path";
462510
462740
  import { homedir as homedir18 } from "os";
462511
462741
  function ensureLogDir() {
@@ -462530,7 +462760,7 @@ async function executeTaskInBackground(taskId, prompt) {
462530
462760
  const cliPath = process.argv[1] || "";
462531
462761
  const logPath = getLogPath(taskId);
462532
462762
  ensureLogDir();
462533
- writeFileSync17(logPath, `Task ${taskId} execution log
462763
+ writeFileSync18(logPath, `Task ${taskId} execution log
462534
462764
  `, "utf-8");
462535
462765
  writeLog(taskId, `Starting background task with prompt: ${prompt.slice(0, 100)}...`);
462536
462766
  writeLog(taskId, `CLI path: ${cliPath}`);
@@ -464014,7 +464244,7 @@ __export(role_exports, {
464014
464244
  import fs44 from "fs/promises";
464015
464245
  import path52 from "path";
464016
464246
  import { homedir as homedir19 } from "os";
464017
- import { existsSync as existsSync29, readdirSync as readdirSync3, readFileSync as readFileSync23 } from "fs";
464247
+ import { existsSync as existsSync29, readdirSync as readdirSync3, readFileSync as readFileSync24 } from "fs";
464018
464248
  import crypto5 from "crypto";
464019
464249
  function getRoleConfigPath(location, projectRoot) {
464020
464250
  if (location === "global") {
@@ -464028,7 +464258,7 @@ function readRoleConfig(location, projectRoot) {
464028
464258
  if (!existsSync29(configPath))
464029
464259
  return {};
464030
464260
  try {
464031
- const content = readFileSync23(configPath, "utf-8");
464261
+ const content = readFileSync24(configPath, "utf-8");
464032
464262
  return JSON.parse(content);
464033
464263
  } catch {
464034
464264
  return {};
@@ -468547,7 +468777,7 @@ var init_useTerminalSize = __esm({
468547
468777
  });
468548
468778
 
468549
468779
  // dist/ui/themes/index.js
468550
- import { existsSync as existsSync31, readFileSync as readFileSync24 } from "fs";
468780
+ import { existsSync as existsSync31, readFileSync as readFileSync25 } from "fs";
468551
468781
  import { homedir as homedir21 } from "os";
468552
468782
  import { join as join33 } from "path";
468553
468783
  function loadCustomThemeColors() {
@@ -468556,7 +468786,7 @@ function loadCustomThemeColors() {
468556
468786
  return defaultCustomColors;
468557
468787
  }
468558
468788
  try {
468559
- const data = readFileSync24(configPath, "utf-8");
468789
+ const data = readFileSync25(configPath, "utf-8");
468560
468790
  const config3 = JSON.parse(data);
468561
468791
  if (config3.customColors) {
468562
468792
  const colors = { ...defaultCustomColors, ...config3.customColors };
@@ -468794,7 +469024,7 @@ var init_themes = __esm({
468794
469024
  // dist/utils/config/themeConfig.js
468795
469025
  import { homedir as homedir22 } from "os";
468796
469026
  import { join as join34 } from "path";
468797
- import { existsSync as existsSync32, mkdirSync as mkdirSync19, readFileSync as readFileSync25, writeFileSync as writeFileSync18 } from "fs";
469027
+ import { existsSync as existsSync32, mkdirSync as mkdirSync19, readFileSync as readFileSync26, writeFileSync as writeFileSync19 } from "fs";
468798
469028
  function ensureConfigDirectory7() {
468799
469029
  if (!existsSync32(CONFIG_DIR8)) {
468800
469030
  mkdirSync19(CONFIG_DIR8, { recursive: true });
@@ -468807,7 +469037,7 @@ function loadThemeConfig() {
468807
469037
  return DEFAULT_CONFIG4;
468808
469038
  }
468809
469039
  try {
468810
- const configData = readFileSync25(THEME_CONFIG_FILE, "utf-8");
469040
+ const configData = readFileSync26(THEME_CONFIG_FILE, "utf-8");
468811
469041
  const config3 = JSON.parse(configData);
468812
469042
  return {
468813
469043
  ...DEFAULT_CONFIG4,
@@ -468821,7 +469051,7 @@ function saveThemeConfig(config3) {
468821
469051
  ensureConfigDirectory7();
468822
469052
  try {
468823
469053
  const configData = JSON.stringify(config3, null, 2);
468824
- writeFileSync18(THEME_CONFIG_FILE, configData, "utf-8");
469054
+ writeFileSync19(THEME_CONFIG_FILE, configData, "utf-8");
468825
469055
  } catch (error40) {
468826
469056
  console.error("Failed to save theme config:", error40);
468827
469057
  }
@@ -477790,7 +478020,7 @@ __export(SystemPromptConfigScreen_exports, {
477790
478020
  default: () => SystemPromptConfigScreen
477791
478021
  });
477792
478022
  import { spawn as spawn10, execSync as execSync6 } from "child_process";
477793
- import { writeFileSync as writeFileSync19, readFileSync as readFileSync26, existsSync as existsSync33, unlinkSync as unlinkSync6 } from "fs";
478023
+ import { writeFileSync as writeFileSync20, readFileSync as readFileSync27, existsSync as existsSync33, unlinkSync as unlinkSync6 } from "fs";
477794
478024
  import { join as join35 } from "path";
477795
478025
  import { platform as platform4, tmpdir as tmpdir4 } from "os";
477796
478026
  function checkCommandExists2(command) {
@@ -477924,7 +478154,7 @@ function SystemPromptConfigScreen({ onBack }) {
477924
478154
  return;
477925
478155
  }
477926
478156
  const tempFile = join35(tmpdir4(), `snow-prompt-${Date.now()}.txt`);
477927
- writeFileSync19(tempFile, prompt.content || "", "utf8");
478157
+ writeFileSync20(tempFile, prompt.content || "", "utf8");
477928
478158
  if (process.stdin.isTTY) {
477929
478159
  process.stdin.pause();
477930
478160
  }
@@ -477938,7 +478168,7 @@ function SystemPromptConfigScreen({ onBack }) {
477938
478168
  }
477939
478169
  if (existsSync33(tempFile)) {
477940
478170
  try {
477941
- const editedContent = readFileSync26(tempFile, "utf8");
478171
+ const editedContent = readFileSync27(tempFile, "utf8");
477942
478172
  const newConfig = {
477943
478173
  ...config3,
477944
478174
  prompts: config3.prompts.map((p, i) => i === selectedIndex ? {
@@ -554809,10 +555039,13 @@ function ThemeSettingsScreen({ onBack, inlineMode = false }) {
554809
555039
  var _a20;
554810
555040
  const { themeType, setThemeType, diffOpacity, setDiffOpacity: setDiffOpacity2 } = useTheme();
554811
555041
  const { t } = useI18n();
555042
+ const { stdout } = use_stdout_default();
554812
555043
  const [selectedTheme, setSelectedTheme] = (0, import_react88.useState)(themeType);
554813
555044
  const [infoText, setInfoText] = (0, import_react88.useState)("");
554814
555045
  const [screen, setScreen] = (0, import_react88.useState)("main");
554815
555046
  const [simpleMode, setSimpleModeState] = (0, import_react88.useState)(() => getSimpleMode());
555047
+ const terminalHeight = (stdout == null ? void 0 : stdout.rows) || 24;
555048
+ const themeMenuHeight = Math.max(4, Math.min(8, terminalHeight - 18));
554816
555049
  (0, import_react88.useEffect)(() => {
554817
555050
  setSimpleModeState(getSimpleMode());
554818
555051
  }, []);
@@ -554954,7 +555187,7 @@ function ThemeSettingsScreen({ onBack, inlineMode = false }) {
554954
555187
  ((_a20 = themeOptions.find((opt) => opt.value === selectedTheme)) == null ? void 0 : _a20.label.replace("\u2713 ", "")) || selectedTheme
554955
555188
  )
554956
555189
  ),
554957
- import_react88.default.createElement(Menu_default, { options: themeOptions, onSelect: handleSelect, onSelectionChange: handleSelectionChange }),
555190
+ import_react88.default.createElement(Menu_default, { options: themeOptions, onSelect: handleSelect, onSelectionChange: handleSelectionChange, maxHeight: themeMenuHeight }),
554958
555191
  import_react88.default.createElement(
554959
555192
  Box_default,
554960
555193
  { flexDirection: "column", paddingX: 1 },
@@ -554962,7 +555195,7 @@ function ThemeSettingsScreen({ onBack, inlineMode = false }) {
554962
555195
  import_react88.default.createElement(DiffViewer, { oldContent: sampleOldCode2, newContent: sampleNewCode2, filename: "example.ts" }),
554963
555196
  import_react88.default.createElement(
554964
555197
  Box_default,
554965
- { marginTop: 1, flexDirection: "column" },
555198
+ { flexDirection: "column" },
554966
555199
  import_react88.default.createElement(Text, { color: "gray", dimColor: true }, t.themeSettings.userMessagePreview),
554967
555200
  import_react88.default.createElement(UserMessagePreview, { content: t.themeSettings.userMessageSample })
554968
555201
  )
@@ -565046,7 +565279,7 @@ var init_useSessionSave = __esm({
565046
565279
 
565047
565280
  // dist/utils/config/permissionsConfig.js
565048
565281
  import { join as join38 } from "path";
565049
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync20, existsSync as existsSync35, mkdirSync as mkdirSync20 } from "fs";
565282
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync21, existsSync as existsSync35, mkdirSync as mkdirSync20 } from "fs";
565050
565283
  function getSnowDirPath2(workingDirectory) {
565051
565284
  return join38(workingDirectory, SNOW_DIR5);
565052
565285
  }
@@ -565066,7 +565299,7 @@ function loadPermissionsConfig(workingDirectory) {
565066
565299
  return { ...DEFAULT_CONFIG5 };
565067
565300
  }
565068
565301
  try {
565069
- const configData = readFileSync27(configPath, "utf-8");
565302
+ const configData = readFileSync28(configPath, "utf-8");
565070
565303
  const config3 = JSON.parse(configData);
565071
565304
  return {
565072
565305
  alwaysApprovedTools: Array.isArray(config3.alwaysApprovedTools) ? config3.alwaysApprovedTools : []
@@ -565081,7 +565314,7 @@ function savePermissionsConfig(workingDirectory, config3) {
565081
565314
  const configPath = getPermissionsFilePath(workingDirectory);
565082
565315
  try {
565083
565316
  const configData = JSON.stringify(config3, null, 2);
565084
- writeFileSync20(configPath, configData, "utf-8");
565317
+ writeFileSync21(configPath, configData, "utf-8");
565085
565318
  } catch (error40) {
565086
565319
  console.error("Failed to save permissions config:", error40);
565087
565320
  throw error40;
@@ -581162,7 +581395,7 @@ __export(MCPConfigScreen_exports, {
581162
581395
  default: () => MCPConfigScreen
581163
581396
  });
581164
581397
  import { spawn as spawn12, execSync as execSync9 } from "child_process";
581165
- import { writeFileSync as writeFileSync21, readFileSync as readFileSync28, existsSync as existsSync36 } from "fs";
581398
+ import { writeFileSync as writeFileSync22, readFileSync as readFileSync29, existsSync as existsSync36 } from "fs";
581166
581399
  import { join as join41 } from "path";
581167
581400
  import { homedir as homedir23, platform as platform5 } from "os";
581168
581401
  function checkCommandExists3(command) {
@@ -581218,7 +581451,7 @@ function MCPConfigScreen({ onBack }) {
581218
581451
  const openEditor = async () => {
581219
581452
  const config3 = getMCPConfig();
581220
581453
  const originalContent = JSON.stringify(config3, null, 2);
581221
- writeFileSync21(MCP_CONFIG_FILE2, originalContent, "utf8");
581454
+ writeFileSync22(MCP_CONFIG_FILE2, originalContent, "utf8");
581222
581455
  const editor = getSystemEditor2();
581223
581456
  if (!editor) {
581224
581457
  console.error("No text editor found! Please set the EDITOR or VISUAL environment variable.");
@@ -581258,18 +581491,18 @@ function MCPConfigScreen({ onBack }) {
581258
581491
  }
581259
581492
  if (existsSync36(MCP_CONFIG_FILE2)) {
581260
581493
  try {
581261
- const editedContent = readFileSync28(MCP_CONFIG_FILE2, "utf8");
581494
+ const editedContent = readFileSync29(MCP_CONFIG_FILE2, "utf8");
581262
581495
  const parsedConfig = JSON.parse(editedContent);
581263
581496
  const validationErrors = validateMCPConfig(parsedConfig);
581264
581497
  if (validationErrors.length === 0) {
581265
581498
  console.log("MCP configuration saved successfully ! Please use `snow` restart!");
581266
581499
  } else {
581267
- writeFileSync21(MCP_CONFIG_FILE2, originalContent, "utf8");
581500
+ writeFileSync22(MCP_CONFIG_FILE2, originalContent, "utf8");
581268
581501
  console.error("Configuration errors:", validationErrors.join(", "));
581269
581502
  console.error("Changes have been reverted to the previous valid configuration.");
581270
581503
  }
581271
581504
  } catch (parseError) {
581272
- writeFileSync21(MCP_CONFIG_FILE2, originalContent, "utf8");
581505
+ writeFileSync22(MCP_CONFIG_FILE2, originalContent, "utf8");
581273
581506
  console.error("Invalid JSON format. Changes have been reverted to the previous valid configuration.");
581274
581507
  }
581275
581508
  }
@@ -581785,7 +582018,7 @@ __export(sseDaemon_exports, {
581785
582018
  stopDaemon: () => stopDaemon
581786
582019
  });
581787
582020
  import { spawn as spawn13, execSync as execSync10 } from "child_process";
581788
- import { existsSync as existsSync37, readFileSync as readFileSync29, writeFileSync as writeFileSync22, unlinkSync as unlinkSync7, readdirSync as readdirSync5, mkdirSync as mkdirSync21 } from "fs";
582021
+ import { existsSync as existsSync37, readFileSync as readFileSync30, writeFileSync as writeFileSync23, unlinkSync as unlinkSync7, readdirSync as readdirSync5, mkdirSync as mkdirSync21 } from "fs";
581789
582022
  import { join as join42 } from "path";
581790
582023
  import { homedir as homedir24 } from "os";
581791
582024
  function getTranslation() {
@@ -581809,7 +582042,7 @@ function startDaemon(port = 3e3, workDir, timeout2 = 3e5) {
581809
582042
  const logFile = getLogFilePath(port);
581810
582043
  if (existsSync37(pidFile)) {
581811
582044
  try {
581812
- const daemonInfo2 = JSON.parse(readFileSync29(pidFile, "utf-8"));
582045
+ const daemonInfo2 = JSON.parse(readFileSync30(pidFile, "utf-8"));
581813
582046
  const { pid } = daemonInfo2;
581814
582047
  try {
581815
582048
  process.kill(pid, 0);
@@ -581874,7 +582107,7 @@ function startDaemon(port = 3e3, workDir, timeout2 = 3e5) {
581874
582107
  startTime: (/* @__PURE__ */ new Date()).toISOString()
581875
582108
  };
581876
582109
  try {
581877
- writeFileSync22(pidFile, JSON.stringify(daemonInfo, null, 2));
582110
+ writeFileSync23(pidFile, JSON.stringify(daemonInfo, null, 2));
581878
582111
  const t2 = getTranslation();
581879
582112
  console.log(t2.daemonStarted);
581880
582113
  console.log(`${t2.pid}: ${child.pid}`);
@@ -581919,7 +582152,7 @@ function stopDaemon(target) {
581919
582152
  const isPort = target <= 65535 && existsSync37(pidFile);
581920
582153
  if (isPort) {
581921
582154
  try {
581922
- const daemonInfo = JSON.parse(readFileSync29(pidFile, "utf-8"));
582155
+ const daemonInfo = JSON.parse(readFileSync30(pidFile, "utf-8"));
581923
582156
  killProcess(daemonInfo.pid, pidFile);
581924
582157
  } catch (error40) {
581925
582158
  const t = getTranslation();
@@ -581935,7 +582168,7 @@ function stopDaemon(target) {
581935
582168
  let found = false;
581936
582169
  for (const pidFile2 of allPidFiles) {
581937
582170
  try {
581938
- const daemonInfo = JSON.parse(readFileSync29(pidFile2, "utf-8"));
582171
+ const daemonInfo = JSON.parse(readFileSync30(pidFile2, "utf-8"));
581939
582172
  if (daemonInfo.pid === target) {
581940
582173
  found = true;
581941
582174
  killProcess(daemonInfo.pid, pidFile2);
@@ -582004,7 +582237,7 @@ function daemonStatus() {
582004
582237
  const stoppedPidFiles = [];
582005
582238
  for (const pidFile of allPidFiles) {
582006
582239
  try {
582007
- const daemonInfo = JSON.parse(readFileSync29(pidFile, "utf-8"));
582240
+ const daemonInfo = JSON.parse(readFileSync30(pidFile, "utf-8"));
582008
582241
  const { pid } = daemonInfo;
582009
582242
  try {
582010
582243
  process.kill(pid, 0);
@@ -583249,7 +583482,7 @@ var daemonLogger_exports = {};
583249
583482
  __export(daemonLogger_exports, {
583250
583483
  DaemonLogger: () => DaemonLogger
583251
583484
  });
583252
- import { existsSync as existsSync38, statSync, renameSync as renameSync2, writeFileSync as writeFileSync23, appendFileSync as appendFileSync2, mkdirSync as mkdirSync22 } from "fs";
583485
+ import { existsSync as existsSync38, statSync, renameSync as renameSync2, writeFileSync as writeFileSync24, appendFileSync as appendFileSync2, mkdirSync as mkdirSync22 } from "fs";
583253
583486
  import { join as join43, dirname as dirname12, basename as basename6 } from "path";
583254
583487
  var DaemonLogger;
583255
583488
  var init_daemonLogger = __esm({
@@ -583355,7 +583588,7 @@ var init_daemonLogger = __esm({
583355
583588
  this.cleanupOldArchives(archiveDateDir, logFileName);
583356
583589
  } catch (error40) {
583357
583590
  try {
583358
- writeFileSync23(this.logFilePath, "", "utf-8");
583591
+ writeFileSync24(this.logFilePath, "", "utf-8");
583359
583592
  } catch {
583360
583593
  }
583361
583594
  }
@@ -596690,7 +596923,7 @@ var require_package3 = __commonJS({
596690
596923
  "package.json"(exports2, module2) {
596691
596924
  module2.exports = {
596692
596925
  name: "snow-ai",
596693
- version: "0.7.1",
596926
+ version: "0.7.2",
596694
596927
  description: "Agentic coding in your terminal",
596695
596928
  license: "MIT",
596696
596929
  bin: {
@@ -598120,7 +598353,7 @@ var meow_default = meow;
598120
598353
 
598121
598354
  // dist/cli.js
598122
598355
  import { spawn as spawn14 } from "child_process";
598123
- import { readFileSync as readFileSync30 } from "fs";
598356
+ import { readFileSync as readFileSync31 } from "fs";
598124
598357
  import { join as join44 } from "path";
598125
598358
  import { fileURLToPath as fileURLToPath6 } from "url";
598126
598359
  delete process.env["NO_COLOR"];
@@ -598199,7 +598432,7 @@ if (!isQuickCommand) {
598199
598432
  process.stdout.write("\u280B Loading...\r");
598200
598433
  }
598201
598434
  var __dirname2 = fileURLToPath6(new URL(".", import.meta.url));
598202
- var packageJson = JSON.parse(readFileSync30(join44(__dirname2, "../package.json"), "utf-8"));
598435
+ var packageJson = JSON.parse(readFileSync31(join44(__dirname2, "../package.json"), "utf-8"));
598203
598436
  var VERSION2 = packageJson.version;
598204
598437
  async function loadDependencies() {
598205
598438
  await Promise.resolve().then(() => (init_utils2(), utils_exports));
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-ai",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "Agentic coding in your terminal",
5
5
  "license": "MIT",
6
6
  "bin": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-ai",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "Agentic coding in your terminal",
5
5
  "license": "MIT",
6
6
  "bin": {