snow-ai 0.7.29 → 0.7.30

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/bundle/cli.mjs CHANGED
@@ -48418,168 +48418,10 @@ var require_lib4 = __commonJS({
48418
48418
  }
48419
48419
  });
48420
48420
 
48421
- // dist/utils/core/logger.js
48422
- var logger_exports = {};
48423
- __export(logger_exports, {
48424
- LogLevel: () => LogLevel,
48425
- Logger: () => Logger,
48426
- default: () => logger_default,
48427
- logger: () => logger
48428
- });
48429
- import fs7 from "node:fs";
48430
- import path7 from "node:path";
48431
- import { homedir } from "node:os";
48432
- function getDefaultLogger() {
48433
- if (!_defaultLogger) {
48434
- _defaultLogger = new Logger();
48435
- }
48436
- return _defaultLogger;
48437
- }
48438
- var LogLevel, Logger, _defaultLogger, logger, logger_default;
48439
- var init_logger = __esm({
48440
- "dist/utils/core/logger.js"() {
48441
- "use strict";
48442
- (function(LogLevel3) {
48443
- LogLevel3[LogLevel3["ERROR"] = 0] = "ERROR";
48444
- LogLevel3[LogLevel3["WARN"] = 1] = "WARN";
48445
- LogLevel3[LogLevel3["INFO"] = 2] = "INFO";
48446
- LogLevel3[LogLevel3["DEBUG"] = 3] = "DEBUG";
48447
- })(LogLevel || (LogLevel = {}));
48448
- Logger = class {
48449
- constructor(config3 = {}) {
48450
- Object.defineProperty(this, "logDir", {
48451
- enumerable: true,
48452
- configurable: true,
48453
- writable: true,
48454
- value: void 0
48455
- });
48456
- Object.defineProperty(this, "maxFileSize", {
48457
- enumerable: true,
48458
- configurable: true,
48459
- writable: true,
48460
- value: void 0
48461
- });
48462
- this.logDir = config3.logDir || path7.join(homedir(), ".snow", "log");
48463
- this.maxFileSize = config3.maxFileSize || 10 * 1024 * 1024;
48464
- this.ensureLogDirectory();
48465
- }
48466
- ensureLogDirectory() {
48467
- if (!fs7.existsSync(this.logDir)) {
48468
- fs7.mkdirSync(this.logDir, { recursive: true });
48469
- }
48470
- }
48471
- formatDate(date5) {
48472
- const year = date5.getFullYear();
48473
- const month = String(date5.getMonth() + 1).padStart(2, "0");
48474
- const day = String(date5.getDate()).padStart(2, "0");
48475
- return `${year}-${month}-${day}`;
48476
- }
48477
- formatTimestamp(date5) {
48478
- return date5.toISOString();
48479
- }
48480
- getLogFilePath(level) {
48481
- const dateString = this.formatDate(/* @__PURE__ */ new Date());
48482
- const levelName = LogLevel[level].toLowerCase();
48483
- return path7.join(this.logDir, `${dateString}-${levelName}.log`);
48484
- }
48485
- shouldRotateLog(filePath) {
48486
- if (!fs7.existsSync(filePath)) {
48487
- return false;
48488
- }
48489
- const stats = fs7.statSync(filePath);
48490
- return stats.size >= this.maxFileSize;
48491
- }
48492
- rotateLog(filePath) {
48493
- const timestamp = Date.now();
48494
- const ext = path7.extname(filePath);
48495
- const basename7 = path7.basename(filePath, ext);
48496
- const dirname13 = path7.dirname(filePath);
48497
- const rotatedPath = path7.join(dirname13, `${basename7}-${timestamp}${ext}`);
48498
- fs7.renameSync(filePath, rotatedPath);
48499
- }
48500
- writeLog(level, message, meta) {
48501
- const timestamp = this.formatTimestamp(/* @__PURE__ */ new Date());
48502
- const levelName = LogLevel[level].toUpperCase().padEnd(5);
48503
- const logEntry = {
48504
- timestamp,
48505
- level: levelName.trim(),
48506
- message,
48507
- ...meta && { meta }
48508
- };
48509
- const logLine = JSON.stringify(logEntry) + "\n";
48510
- const filePath = this.getLogFilePath(level);
48511
- if (this.shouldRotateLog(filePath)) {
48512
- this.rotateLog(filePath);
48513
- }
48514
- fs7.appendFileSync(filePath, logLine, "utf8");
48515
- }
48516
- error(message, meta) {
48517
- this.writeLog(LogLevel.ERROR, message, meta);
48518
- }
48519
- warn(message, meta) {
48520
- this.writeLog(LogLevel.WARN, message, meta);
48521
- }
48522
- info(message, meta) {
48523
- this.writeLog(LogLevel.INFO, message, meta);
48524
- }
48525
- debug(message, meta) {
48526
- this.writeLog(LogLevel.DEBUG, message, meta);
48527
- }
48528
- log(level, message, meta) {
48529
- this.writeLog(level, message, meta);
48530
- }
48531
- };
48532
- _defaultLogger = null;
48533
- logger = {
48534
- error(message, meta) {
48535
- getDefaultLogger().error(message, meta);
48536
- },
48537
- warn(message, meta) {
48538
- getDefaultLogger().warn(message, meta);
48539
- },
48540
- info(message, meta) {
48541
- getDefaultLogger().info(message, meta);
48542
- },
48543
- debug(message, meta) {
48544
- getDefaultLogger().debug(message, meta);
48545
- },
48546
- log(level, message, meta) {
48547
- getDefaultLogger().log(level, message, meta);
48548
- }
48549
- };
48550
- logger_default = logger;
48551
- }
48552
- });
48553
-
48554
48421
  // dist/utils/config/workingDirConfig.js
48555
- import path8 from "path";
48422
+ import path7 from "path";
48556
48423
  import process17 from "process";
48557
- function getSnowDirPath() {
48558
- return path8.join(process17.cwd(), SNOW_DIR);
48559
- }
48560
- function getConfigFilePath() {
48561
- return path8.join(getSnowDirPath(), WORKING_DIR_FILE);
48562
- }
48563
- async function ensureSnowDir() {
48564
- const snowDir = getSnowDirPath();
48565
- try {
48566
- await import_fs_extra.default.ensureDir(snowDir);
48567
- } catch (error40) {
48568
- logger.error("Failed to create .snow directory", error40);
48569
- throw error40;
48570
- }
48571
- }
48572
- async function loadWorkingDirConfig() {
48573
- const configPath = getConfigFilePath();
48574
- try {
48575
- if (await import_fs_extra.default.pathExists(configPath)) {
48576
- const content = await import_fs_extra.default.readFile(configPath, "utf-8");
48577
- const config3 = JSON.parse(content);
48578
- return config3;
48579
- }
48580
- } catch (error40) {
48581
- logger.error("Failed to load working directory config", error40);
48582
- }
48424
+ function createDefaultWorkingDirConfig() {
48583
48425
  return {
48584
48426
  directories: [
48585
48427
  {
@@ -48590,18 +48432,26 @@ async function loadWorkingDirConfig() {
48590
48432
  ]
48591
48433
  };
48592
48434
  }
48593
- async function saveWorkingDirConfig(config3) {
48594
- await ensureSnowDir();
48595
- const configPath = getConfigFilePath();
48596
- try {
48597
- await import_fs_extra.default.writeFile(configPath, JSON.stringify(config3, null, 2), "utf-8");
48598
- } catch (error40) {
48599
- logger.error("Failed to save working directory config", error40);
48600
- throw error40;
48435
+ function toWorkingDirConfig(directories) {
48436
+ if (!Array.isArray(directories)) {
48437
+ return createDefaultWorkingDirConfig();
48601
48438
  }
48439
+ return {
48440
+ directories
48441
+ };
48442
+ }
48443
+ function loadWorkingDirConfig() {
48444
+ const settings = readSettings("project");
48445
+ return Promise.resolve(toWorkingDirConfig(settings.workingDirectories));
48446
+ }
48447
+ function saveWorkingDirConfig(config3) {
48448
+ updateSettings("project", (settings) => {
48449
+ settings.workingDirectories = config3.directories;
48450
+ });
48451
+ return Promise.resolve();
48602
48452
  }
48603
48453
  async function addWorkingDirectory(dirPath) {
48604
- const absolutePath = path8.resolve(dirPath);
48454
+ const absolutePath = path7.resolve(dirPath);
48605
48455
  try {
48606
48456
  const stats = await import_fs_extra.default.stat(absolutePath);
48607
48457
  if (!stats.isDirectory()) {
@@ -48656,14 +48506,12 @@ async function addSSHWorkingDirectory(sshConfig, remotePath, displayName) {
48656
48506
  await saveWorkingDirConfig(config3);
48657
48507
  return true;
48658
48508
  }
48659
- var import_fs_extra, SNOW_DIR, WORKING_DIR_FILE;
48509
+ var import_fs_extra;
48660
48510
  var init_workingDirConfig = __esm({
48661
48511
  "dist/utils/config/workingDirConfig.js"() {
48662
48512
  "use strict";
48663
48513
  import_fs_extra = __toESM(require_lib4(), 1);
48664
- init_logger();
48665
- SNOW_DIR = ".snow";
48666
- WORKING_DIR_FILE = "working-dirs.json";
48514
+ init_unifiedSettings();
48667
48515
  }
48668
48516
  });
48669
48517
 
@@ -51094,6 +50942,139 @@ var init_esm2 = __esm({
51094
50942
  }
51095
50943
  });
51096
50944
 
50945
+ // dist/utils/core/logger.js
50946
+ var logger_exports = {};
50947
+ __export(logger_exports, {
50948
+ LogLevel: () => LogLevel,
50949
+ Logger: () => Logger,
50950
+ default: () => logger_default,
50951
+ logger: () => logger
50952
+ });
50953
+ import fs8 from "node:fs";
50954
+ import path8 from "node:path";
50955
+ import { homedir } from "node:os";
50956
+ function getDefaultLogger() {
50957
+ if (!_defaultLogger) {
50958
+ _defaultLogger = new Logger();
50959
+ }
50960
+ return _defaultLogger;
50961
+ }
50962
+ var LogLevel, Logger, _defaultLogger, logger, logger_default;
50963
+ var init_logger = __esm({
50964
+ "dist/utils/core/logger.js"() {
50965
+ "use strict";
50966
+ (function(LogLevel3) {
50967
+ LogLevel3[LogLevel3["ERROR"] = 0] = "ERROR";
50968
+ LogLevel3[LogLevel3["WARN"] = 1] = "WARN";
50969
+ LogLevel3[LogLevel3["INFO"] = 2] = "INFO";
50970
+ LogLevel3[LogLevel3["DEBUG"] = 3] = "DEBUG";
50971
+ })(LogLevel || (LogLevel = {}));
50972
+ Logger = class {
50973
+ constructor(config3 = {}) {
50974
+ Object.defineProperty(this, "logDir", {
50975
+ enumerable: true,
50976
+ configurable: true,
50977
+ writable: true,
50978
+ value: void 0
50979
+ });
50980
+ Object.defineProperty(this, "maxFileSize", {
50981
+ enumerable: true,
50982
+ configurable: true,
50983
+ writable: true,
50984
+ value: void 0
50985
+ });
50986
+ this.logDir = config3.logDir || path8.join(homedir(), ".snow", "log");
50987
+ this.maxFileSize = config3.maxFileSize || 10 * 1024 * 1024;
50988
+ this.ensureLogDirectory();
50989
+ }
50990
+ ensureLogDirectory() {
50991
+ if (!fs8.existsSync(this.logDir)) {
50992
+ fs8.mkdirSync(this.logDir, { recursive: true });
50993
+ }
50994
+ }
50995
+ formatDate(date5) {
50996
+ const year = date5.getFullYear();
50997
+ const month = String(date5.getMonth() + 1).padStart(2, "0");
50998
+ const day = String(date5.getDate()).padStart(2, "0");
50999
+ return `${year}-${month}-${day}`;
51000
+ }
51001
+ formatTimestamp(date5) {
51002
+ return date5.toISOString();
51003
+ }
51004
+ getLogFilePath(level) {
51005
+ const dateString = this.formatDate(/* @__PURE__ */ new Date());
51006
+ const levelName = LogLevel[level].toLowerCase();
51007
+ return path8.join(this.logDir, `${dateString}-${levelName}.log`);
51008
+ }
51009
+ shouldRotateLog(filePath) {
51010
+ if (!fs8.existsSync(filePath)) {
51011
+ return false;
51012
+ }
51013
+ const stats = fs8.statSync(filePath);
51014
+ return stats.size >= this.maxFileSize;
51015
+ }
51016
+ rotateLog(filePath) {
51017
+ const timestamp = Date.now();
51018
+ const ext = path8.extname(filePath);
51019
+ const basename7 = path8.basename(filePath, ext);
51020
+ const dirname13 = path8.dirname(filePath);
51021
+ const rotatedPath = path8.join(dirname13, `${basename7}-${timestamp}${ext}`);
51022
+ fs8.renameSync(filePath, rotatedPath);
51023
+ }
51024
+ writeLog(level, message, meta) {
51025
+ const timestamp = this.formatTimestamp(/* @__PURE__ */ new Date());
51026
+ const levelName = LogLevel[level].toUpperCase().padEnd(5);
51027
+ const logEntry = {
51028
+ timestamp,
51029
+ level: levelName.trim(),
51030
+ message,
51031
+ ...meta && { meta }
51032
+ };
51033
+ const logLine = JSON.stringify(logEntry) + "\n";
51034
+ const filePath = this.getLogFilePath(level);
51035
+ if (this.shouldRotateLog(filePath)) {
51036
+ this.rotateLog(filePath);
51037
+ }
51038
+ fs8.appendFileSync(filePath, logLine, "utf8");
51039
+ }
51040
+ error(message, meta) {
51041
+ this.writeLog(LogLevel.ERROR, message, meta);
51042
+ }
51043
+ warn(message, meta) {
51044
+ this.writeLog(LogLevel.WARN, message, meta);
51045
+ }
51046
+ info(message, meta) {
51047
+ this.writeLog(LogLevel.INFO, message, meta);
51048
+ }
51049
+ debug(message, meta) {
51050
+ this.writeLog(LogLevel.DEBUG, message, meta);
51051
+ }
51052
+ log(level, message, meta) {
51053
+ this.writeLog(level, message, meta);
51054
+ }
51055
+ };
51056
+ _defaultLogger = null;
51057
+ logger = {
51058
+ error(message, meta) {
51059
+ getDefaultLogger().error(message, meta);
51060
+ },
51061
+ warn(message, meta) {
51062
+ getDefaultLogger().warn(message, meta);
51063
+ },
51064
+ info(message, meta) {
51065
+ getDefaultLogger().info(message, meta);
51066
+ },
51067
+ debug(message, meta) {
51068
+ getDefaultLogger().debug(message, meta);
51069
+ },
51070
+ log(level, message, meta) {
51071
+ getDefaultLogger().log(level, message, meta);
51072
+ }
51073
+ };
51074
+ logger_default = logger;
51075
+ }
51076
+ });
51077
+
51097
51078
  // node_modules/sql.js/dist/sql-wasm.js
51098
51079
  var require_sql_wasm = __commonJS({
51099
51080
  "node_modules/sql.js/dist/sql-wasm.js"(exports2, module2) {
@@ -57785,9 +57766,9 @@ import { createHash, randomUUID } from "crypto";
57785
57766
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
57786
57767
  import { homedir as homedir3 } from "os";
57787
57768
  import { join as join5 } from "path";
57788
- function ensureSnowDir2() {
57789
- if (!existsSync3(SNOW_DIR2)) {
57790
- mkdirSync2(SNOW_DIR2, { recursive: true });
57769
+ function ensureSnowDir() {
57770
+ if (!existsSync3(SNOW_DIR)) {
57771
+ mkdirSync2(SNOW_DIR, { recursive: true });
57791
57772
  }
57792
57773
  }
57793
57774
  function generateDevUserId() {
@@ -57796,7 +57777,7 @@ function generateDevUserId() {
57796
57777
  return `user_${hash}_account__session_${sessionId}`;
57797
57778
  }
57798
57779
  function getDevUserId() {
57799
- ensureSnowDir2();
57780
+ ensureSnowDir();
57800
57781
  if (existsSync3(DEV_USER_ID_FILE)) {
57801
57782
  const userId2 = readFileSync5(DEV_USER_ID_FILE, "utf-8").trim();
57802
57783
  if (userId2) {
@@ -57813,12 +57794,12 @@ function isDevMode() {
57813
57794
  function enableDevMode() {
57814
57795
  process.env["SNOW_DEV_MODE"] = "true";
57815
57796
  }
57816
- var SNOW_DIR2, DEV_USER_ID_FILE;
57797
+ var SNOW_DIR, DEV_USER_ID_FILE;
57817
57798
  var init_devMode = __esm({
57818
57799
  "dist/utils/core/devMode.js"() {
57819
57800
  "use strict";
57820
- SNOW_DIR2 = join5(homedir3(), ".snow");
57821
- DEV_USER_ID_FILE = join5(SNOW_DIR2, "dev-user-id");
57801
+ SNOW_DIR = join5(homedir3(), ".snow");
57802
+ DEV_USER_ID_FILE = join5(SNOW_DIR, "dev-user-id");
57822
57803
  }
57823
57804
  });
57824
57805
 
@@ -448379,7 +448360,7 @@ ${conversationTranscript}`
448379
448360
  return messages;
448380
448361
  }
448381
448362
  async function compressWithChatCompletions(modelName, conversationMessages, customSystemPrompts, options3) {
448382
- var _a20;
448363
+ var _a20, _b14;
448383
448364
  const messages = prepareMessagesForCompression(conversationMessages, customSystemPrompts);
448384
448365
  let summary = "";
448385
448366
  let usage = {
@@ -448392,8 +448373,11 @@ async function compressWithChatCompletions(modelName, conversationMessages, cust
448392
448373
  messages,
448393
448374
  stream: true
448394
448375
  })) {
448376
+ if (chunk2.type === "reasoning_delta" && chunk2.delta) {
448377
+ (_a20 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _a20.call(options3, chunk2.delta);
448378
+ }
448395
448379
  if (chunk2.type === "content" && chunk2.content) {
448396
- (_a20 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _a20.call(options3, chunk2.content);
448380
+ (_b14 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _b14.call(options3, chunk2.content);
448397
448381
  summary += chunk2.content;
448398
448382
  }
448399
448383
  if (chunk2.type === "usage" && chunk2.usage) {
@@ -448410,7 +448394,7 @@ async function compressWithChatCompletions(modelName, conversationMessages, cust
448410
448394
  return { summary, usage };
448411
448395
  }
448412
448396
  async function compressWithResponses(modelName, conversationMessages, customSystemPrompts, options3) {
448413
- var _a20;
448397
+ var _a20, _b14;
448414
448398
  const messages = prepareMessagesForCompression(conversationMessages, customSystemPrompts);
448415
448399
  let summary = "";
448416
448400
  let usage = {
@@ -448423,8 +448407,11 @@ async function compressWithResponses(modelName, conversationMessages, customSyst
448423
448407
  messages,
448424
448408
  stream: true
448425
448409
  })) {
448410
+ if (chunk2.type === "reasoning_delta" && chunk2.delta) {
448411
+ (_a20 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _a20.call(options3, chunk2.delta);
448412
+ }
448426
448413
  if (chunk2.type === "content" && chunk2.content) {
448427
- (_a20 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _a20.call(options3, chunk2.content);
448414
+ (_b14 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _b14.call(options3, chunk2.content);
448428
448415
  summary += chunk2.content;
448429
448416
  }
448430
448417
  if (chunk2.type === "usage" && chunk2.usage) {
@@ -448441,7 +448428,7 @@ async function compressWithResponses(modelName, conversationMessages, customSyst
448441
448428
  return { summary, usage };
448442
448429
  }
448443
448430
  async function compressWithGemini(modelName, conversationMessages, customSystemPrompts, options3) {
448444
- var _a20;
448431
+ var _a20, _b14;
448445
448432
  const messages = prepareMessagesForCompression(conversationMessages, customSystemPrompts);
448446
448433
  let summary = "";
448447
448434
  let usage = {
@@ -448453,8 +448440,11 @@ async function compressWithGemini(modelName, conversationMessages, customSystemP
448453
448440
  model: modelName,
448454
448441
  messages
448455
448442
  })) {
448443
+ if (chunk2.type === "reasoning_delta" && chunk2.delta) {
448444
+ (_a20 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _a20.call(options3, chunk2.delta);
448445
+ }
448456
448446
  if (chunk2.type === "content" && chunk2.content) {
448457
- (_a20 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _a20.call(options3, chunk2.content);
448447
+ (_b14 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _b14.call(options3, chunk2.content);
448458
448448
  summary += chunk2.content;
448459
448449
  }
448460
448450
  if (chunk2.type === "usage" && chunk2.usage) {
@@ -448471,7 +448461,7 @@ async function compressWithGemini(modelName, conversationMessages, customSystemP
448471
448461
  return { summary, usage };
448472
448462
  }
448473
448463
  async function compressWithAnthropic(modelName, conversationMessages, customSystemPrompts, options3) {
448474
- var _a20;
448464
+ var _a20, _b14;
448475
448465
  const messages = prepareMessagesForCompression(conversationMessages, customSystemPrompts);
448476
448466
  let summary = "";
448477
448467
  let usage = {
@@ -448486,8 +448476,11 @@ async function compressWithAnthropic(modelName, conversationMessages, customSyst
448486
448476
  disableThinking: true
448487
448477
  // Context compression 不使用 Extended Thinking
448488
448478
  })) {
448479
+ if (chunk2.type === "reasoning_delta" && chunk2.delta) {
448480
+ (_a20 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _a20.call(options3, chunk2.delta);
448481
+ }
448489
448482
  if (chunk2.type === "content" && chunk2.content) {
448490
- (_a20 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _a20.call(options3, chunk2.content);
448483
+ (_b14 = options3 == null ? void 0 : options3.onStreamStart) == null ? void 0 : _b14.call(options3, chunk2.content);
448491
448484
  summary += chunk2.content;
448492
448485
  }
448493
448486
  if (chunk2.type === "usage" && chunk2.usage) {
@@ -451052,12 +451045,12 @@ function deleteTeamData(teamName) {
451052
451045
  return false;
451053
451046
  }
451054
451047
  }
451055
- var SNOW_DIR3, TEAMS_DIR;
451048
+ var SNOW_DIR2, TEAMS_DIR;
451056
451049
  var init_teamConfig = __esm({
451057
451050
  "dist/utils/team/teamConfig.js"() {
451058
451051
  "use strict";
451059
- SNOW_DIR3 = join21(homedir10(), ".snow");
451060
- TEAMS_DIR = join21(SNOW_DIR3, "teams");
451052
+ SNOW_DIR2 = join21(homedir10(), ".snow");
451053
+ TEAMS_DIR = join21(SNOW_DIR2, "teams");
451061
451054
  }
451062
451055
  });
451063
451056
 
@@ -451213,12 +451206,12 @@ function clearTasks(teamName) {
451213
451206
  writeTaskList(teamName, { tasks: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
451214
451207
  }
451215
451208
  }
451216
- var SNOW_DIR4, TEAMS_DIR2;
451209
+ var SNOW_DIR3, TEAMS_DIR2;
451217
451210
  var init_teamTaskList = __esm({
451218
451211
  "dist/utils/team/teamTaskList.js"() {
451219
451212
  "use strict";
451220
- SNOW_DIR4 = join22(homedir11(), ".snow");
451221
- TEAMS_DIR2 = join22(SNOW_DIR4, "teams");
451213
+ SNOW_DIR3 = join22(homedir11(), ".snow");
451214
+ TEAMS_DIR2 = join22(SNOW_DIR3, "teams");
451222
451215
  }
451223
451216
  });
451224
451217
 
@@ -469584,7 +469577,12 @@ async function appendUserMessageAndSyncContext(options3) {
469584
469577
  if (updatedSession) {
469585
469578
  const { convertSessionMessagesToUI: convertSessionMessagesToUI2 } = await Promise.resolve().then(() => (init_sessionConverter(), sessionConverter_exports));
469586
469579
  const uiMessages = convertSessionMessagesToUI2(updatedSession.messages);
469587
- setConversationContext2(updatedSession.id, uiMessages.length);
469580
+ const compressedSummaryIndex = uiMessages.findIndex((msg) => {
469581
+ var _a20;
469582
+ return (msg == null ? void 0 : msg.role) === "user" && ((_a20 = msg.content) == null ? void 0 : _a20.trim()) && !msg.subAgentDirected;
469583
+ });
469584
+ const snapshotMessageIndex = updatedSession.compressedFrom != null ? Math.max(0, compressedSummaryIndex) : uiMessages.length;
469585
+ setConversationContext2(updatedSession.id, snapshotMessageIndex);
469588
469586
  }
469589
469587
  } catch (error40) {
469590
469588
  console.error("Failed to set conversation context:", error40);
@@ -471636,26 +471634,71 @@ async function executeContextCompression(sessionId, onStatusUpdate) {
471636
471634
  let compressionStreamStarted = false;
471637
471635
  let compressionStreamScore = 0;
471638
471636
  let compressionProgress = 0;
471639
- const notifyCompressionStreamStarted = (content) => {
471640
- compressionStreamStarted = true;
471641
- compressionStreamScore += Math.max(1, Math.ceil(((content == null ? void 0 : content.length) ?? 0) / 1500));
471642
- const nextProgress = Math.min(90, 10 + Math.floor((1 - Math.exp(-compressionStreamScore / 800)) * 80));
471643
- if (nextProgress <= compressionProgress) {
471644
- return;
471637
+ let compressionStreamLineBuffer = "";
471638
+ const compressionStreamLines = [];
471639
+ const MAX_COMPRESSION_STREAM_LINES = 80;
471640
+ const MAX_COMPRESSION_STREAM_LINE_LENGTH = 120;
471641
+ const appendCompressionStreamLine = (line) => {
471642
+ compressionStreamLines.push(line);
471643
+ if (compressionStreamLines.length > MAX_COMPRESSION_STREAM_LINES) {
471644
+ compressionStreamLines.splice(0, compressionStreamLines.length - MAX_COMPRESSION_STREAM_LINES);
471645
471645
  }
471646
- compressionProgress = nextProgress;
471646
+ };
471647
+ const emitCompressionStreamUpdate = () => {
471647
471648
  onStatusUpdate == null ? void 0 : onStatusUpdate({
471648
471649
  step: "compressing",
471649
471650
  sessionId,
471650
471651
  progress: compressionProgress,
471651
- streamStarted: compressionStreamStarted
471652
+ streamStarted: compressionStreamStarted,
471653
+ streamContent: compressionStreamLines.join("\n")
471652
471654
  });
471653
471655
  };
471656
+ const flushCompressionStreamBuffer = (force = false) => {
471657
+ if (!compressionStreamStarted) {
471658
+ return;
471659
+ }
471660
+ if (force && compressionStreamLineBuffer) {
471661
+ appendCompressionStreamLine(compressionStreamLineBuffer);
471662
+ compressionStreamLineBuffer = "";
471663
+ }
471664
+ if (compressionStreamLines.length === 0) {
471665
+ return;
471666
+ }
471667
+ emitCompressionStreamUpdate();
471668
+ };
471669
+ const notifyCompressionStreamStarted = (content) => {
471670
+ if (!content) {
471671
+ return;
471672
+ }
471673
+ compressionStreamStarted = true;
471674
+ compressionStreamLineBuffer += content.replace(/\r\n?/g, "\n");
471675
+ let shouldEmit = false;
471676
+ const lineParts = compressionStreamLineBuffer.split("\n");
471677
+ compressionStreamLineBuffer = lineParts.pop() ?? "";
471678
+ for (const line of lineParts) {
471679
+ appendCompressionStreamLine(line);
471680
+ shouldEmit = true;
471681
+ }
471682
+ while (compressionStreamLineBuffer.length >= MAX_COMPRESSION_STREAM_LINE_LENGTH) {
471683
+ appendCompressionStreamLine(compressionStreamLineBuffer.slice(0, MAX_COMPRESSION_STREAM_LINE_LENGTH));
471684
+ compressionStreamLineBuffer = compressionStreamLineBuffer.slice(MAX_COMPRESSION_STREAM_LINE_LENGTH);
471685
+ shouldEmit = true;
471686
+ }
471687
+ compressionStreamScore += Math.max(1, Math.ceil(content.length / 1500));
471688
+ const nextProgress = Math.min(90, 10 + Math.floor((1 - Math.exp(-compressionStreamScore / 800)) * 80));
471689
+ if (nextProgress > compressionProgress) {
471690
+ compressionProgress = nextProgress;
471691
+ }
471692
+ if (shouldEmit) {
471693
+ emitCompressionStreamUpdate();
471694
+ }
471695
+ };
471654
471696
  onStatusUpdate == null ? void 0 : onStatusUpdate({
471655
471697
  step: "compressing",
471656
471698
  sessionId,
471657
471699
  progress: 0,
471658
- streamStarted: false
471700
+ streamStarted: false,
471701
+ streamContent: ""
471659
471702
  });
471660
471703
  if (useHybridCompress) {
471661
471704
  const apiConfig = getSnowConfig();
@@ -471665,6 +471708,7 @@ async function executeContextCompression(sessionId, onStatusUpdate) {
471665
471708
  maxTokens: apiConfig.maxTokens,
471666
471709
  onStreamStart: notifyCompressionStreamStarted
471667
471710
  });
471711
+ flushCompressionStreamBuffer(true);
471668
471712
  if (!hybridResult.compressed) {
471669
471713
  onStatusUpdate == null ? void 0 : onStatusUpdate({
471670
471714
  step: "skipped",
@@ -471701,6 +471745,7 @@ ${first3.content || ""}`;
471701
471745
  compressedSession2.summary = currentSession.summary;
471702
471746
  compressedSession2.compressedFrom = currentSession.id;
471703
471747
  compressedSession2.compressedAt = Date.now();
471748
+ compressedSession2.originalMessageIndex = currentSession.messages.length;
471704
471749
  if (currentSession.hasGoal) {
471705
471750
  compressedSession2.hasGoal = true;
471706
471751
  }
@@ -471746,6 +471791,7 @@ ${first3.content || ""}`;
471746
471791
  const compressionResult = await compressContext(chatMessages, {
471747
471792
  onStreamStart: notifyCompressionStreamStarted
471748
471793
  });
471794
+ flushCompressionStreamBuffer(true);
471749
471795
  if (!compressionResult) {
471750
471796
  onStatusUpdate == null ? void 0 : onStatusUpdate({
471751
471797
  step: "skipped",
@@ -473003,7 +473049,12 @@ async function handlePendingMessages(options3) {
473003
473049
  if (updatedSession) {
473004
473050
  const { convertSessionMessagesToUI: convertSessionMessagesToUI2 } = await Promise.resolve().then(() => (init_sessionConverter(), sessionConverter_exports));
473005
473051
  const uiMessages = convertSessionMessagesToUI2(updatedSession.messages);
473006
- setConversationContext2(updatedSession.id, uiMessages.length);
473052
+ const compressedSummaryIndex = uiMessages.findIndex((msg) => {
473053
+ var _a20;
473054
+ return (msg == null ? void 0 : msg.role) === "user" && ((_a20 = msg.content) == null ? void 0 : _a20.trim()) && !msg.subAgentDirected;
473055
+ });
473056
+ const snapshotMessageIndex = updatedSession.compressedFrom != null ? Math.max(0, compressedSummaryIndex) : uiMessages.length;
473057
+ setConversationContext2(updatedSession.id, snapshotMessageIndex);
473007
473058
  }
473008
473059
  } catch (error40) {
473009
473060
  console.error("Failed to save pending user message:", error40);
@@ -567474,7 +567525,7 @@ function getSystemEditor2() {
567474
567525
  }
567475
567526
  return null;
567476
567527
  }
567477
- function getConfigFilePath2(scope) {
567528
+ function getConfigFilePath(scope) {
567478
567529
  if (scope === "project") {
567479
567530
  return join36(process.cwd(), ".snow", "mcp-config.draft.json");
567480
567531
  }
@@ -567484,7 +567535,7 @@ function getConfigByScope(scope) {
567484
567535
  return scope === "project" ? getProjectMCPConfig() : getGlobalMCPConfig();
567485
567536
  }
567486
567537
  function openEditorForScope(scope, onBack, i18nMessages) {
567487
- const configFilePath = getConfigFilePath2(scope);
567538
+ const configFilePath = getConfigFilePath(scope);
567488
567539
  const config3 = getConfigByScope(scope);
567489
567540
  const originalContent = JSON.stringify(config3, null, 2);
567490
567541
  const dir = join36(configFilePath, "..");
@@ -568120,6 +568171,66 @@ var init_WelcomeScreen = __esm({
568120
568171
  function sanitizeInput2(str2) {
568121
568172
  return str2.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\t/g, " ").replace(/\x1b\[[IO]/g, "").replace(/(^|\s+)\[(?:I|O)(?=(?:\s|$|["'~\\\/]|[A-Za-z]:))/g, "$1").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
568122
568173
  }
568174
+ function decodeStrictBase64(base64Data) {
568175
+ if (base64Data.length <= 100)
568176
+ return null;
568177
+ if (base64Data.length % 4 !== 0)
568178
+ return null;
568179
+ if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(base64Data))
568180
+ return null;
568181
+ const decoded = Buffer.from(base64Data, "base64");
568182
+ if (decoded.length === 0)
568183
+ return null;
568184
+ return decoded;
568185
+ }
568186
+ function hasAscii(bytes, offset, text2) {
568187
+ if (bytes.length < offset + text2.length)
568188
+ return false;
568189
+ for (let index = 0; index < text2.length; index += 1) {
568190
+ if (bytes[offset + index] !== text2.charCodeAt(index))
568191
+ return false;
568192
+ }
568193
+ return true;
568194
+ }
568195
+ function hasPngSignature(bytes) {
568196
+ const signature = [137, 80, 78, 71, 13, 10, 26, 10];
568197
+ return signature.every((value, index) => bytes[index] === value);
568198
+ }
568199
+ function isCompleteImageData(bytes, mimeType) {
568200
+ if (mimeType === "image/png") {
568201
+ return bytes.length >= 45 && hasPngSignature(bytes) && bytes[bytes.length - 12] === 0 && bytes[bytes.length - 11] === 0 && bytes[bytes.length - 10] === 0 && bytes[bytes.length - 9] === 0 && hasAscii(bytes, bytes.length - 8, "IEND");
568202
+ }
568203
+ if (mimeType === "image/jpeg") {
568204
+ return bytes.length >= 4 && bytes[0] === 255 && bytes[1] === 216 && bytes[bytes.length - 2] === 255 && bytes[bytes.length - 1] === 217;
568205
+ }
568206
+ if (mimeType === "image/gif") {
568207
+ return bytes.length >= 14 && (hasAscii(bytes, 0, "GIF87a") || hasAscii(bytes, 0, "GIF89a")) && bytes[bytes.length - 1] === 59;
568208
+ }
568209
+ if (mimeType === "image/webp") {
568210
+ if (bytes.length < 20 || !hasAscii(bytes, 0, "RIFF") || !hasAscii(bytes, 8, "WEBP")) {
568211
+ return false;
568212
+ }
568213
+ const riffSize = (bytes.at(4) ?? 0) + (bytes.at(5) ?? 0) * 256 + (bytes.at(6) ?? 0) * 65536 + (bytes.at(7) ?? 0) * 16777216;
568214
+ return riffSize === bytes.length - 8;
568215
+ }
568216
+ return false;
568217
+ }
568218
+ function parsePastedImageDataUrl(input2) {
568219
+ const trimmed = input2.trim();
568220
+ if (!trimmed)
568221
+ return null;
568222
+ const markdownImageMatch = trimmed.match(/^!\[[^\]]*\]\((data:image\/(?:png|jpe?g|gif|webp);base64,[\s\S]+)\)$/i);
568223
+ const dataUrl = (markdownImageMatch == null ? void 0 : markdownImageMatch[1]) ?? trimmed;
568224
+ const dataUrlMatch = dataUrl.match(/^data:(image\/(?:png|jpe?g|gif|webp));base64,([\s\S]+)$/i);
568225
+ if (!dataUrlMatch)
568226
+ return null;
568227
+ const mimeType = (dataUrlMatch[1] || "image/png").toLowerCase().replace("image/jpg", "image/jpeg");
568228
+ const base64Data = (dataUrlMatch[2] || "").replace(/\s/g, "");
568229
+ const decoded = decodeStrictBase64(base64Data);
568230
+ if (!decoded || !isCompleteImageData(decoded, mimeType))
568231
+ return null;
568232
+ return { base64Data, mimeType };
568233
+ }
568123
568234
  var TextBuffer;
568124
568235
  var init_textBuffer = __esm({
568125
568236
  "dist/utils/ui/textBuffer.js"() {
@@ -568373,6 +568484,13 @@ var init_textBuffer = __esm({
568373
568484
  if (!sanitized) {
568374
568485
  return;
568375
568486
  }
568487
+ const pastedImage = parsePastedImageDataUrl(sanitized);
568488
+ if (pastedImage) {
568489
+ this.lastTextPlaceholderId = null;
568490
+ this.lastTextPlaceholderAt = 0;
568491
+ this.insertImage(pastedImage.base64Data, pastedImage.mimeType);
568492
+ return;
568493
+ }
568376
568494
  const charCount = sanitized.length;
568377
568495
  const hasPastingIndicator = this.tempPastingPlaceholder !== null;
568378
568496
  if (this.tempPastingPlaceholder) {
@@ -571557,8 +571675,9 @@ var init_editing = __esm({
571557
571675
  function clipboardHandler(ctx) {
571558
571676
  const { input: input2, key, options: options3, refs } = ctx;
571559
571677
  const { pasteFromClipboard } = options3;
571560
- const isPasteShortcut = process.platform === "darwin" ? key.ctrl && input2 === "v" : key.meta && input2 === "v";
571561
- if (isPasteShortcut) {
571678
+ const isLegacyImagePasteShortcut = process.platform === "darwin" ? key.ctrl && input2 === "v" : key.meta && input2 === "v";
571679
+ const isForwardedSystemPasteShortcut = process.platform !== "darwin" && key.ctrl && input2 === "v";
571680
+ if (isLegacyImagePasteShortcut || isForwardedSystemPasteShortcut) {
571562
571681
  refs.lastPasteShortcutAt.current = Date.now();
571563
571682
  pasteFromClipboard();
571564
571683
  return true;
@@ -571675,7 +571794,8 @@ function commandPanelHandler(ctx) {
571675
571794
  const selectedCommand = filteredCommands[commandSelectedIndex];
571676
571795
  if (selectedCommand) {
571677
571796
  if (inlineTrigger) {
571678
- buffer.replaceRange(inlineTrigger.slashIndex, inlineTrigger.endIndex, "/" + selectedCommand.name);
571797
+ const inlineInsertionText = !inlineTrigger.isAtStart && isInlineInsertionCommand(selectedCommand) ? selectedCommand.insertionText : void 0;
571798
+ buffer.replaceRange(inlineTrigger.slashIndex, inlineTrigger.endIndex, inlineInsertionText ?? "/" + selectedCommand.name);
571679
571799
  } else {
571680
571800
  buffer.setText("/" + selectedCommand.name);
571681
571801
  buffer.setCursorPosition(buffer.text.length);
@@ -572029,7 +572149,8 @@ function regularInputHandler(ctx) {
572029
572149
  const now = Date.now();
572030
572150
  const isPasteShortcutActive = now - refs.lastPasteShortcutAt.current <= pasteShortcutTimeoutMs;
572031
572151
  const isSingleCharInput = input2.length === 1;
572032
- const isSmallMultiCharInput = input2.length > 1 && !input2.includes("\n");
572152
+ const looksLikeImageDataPaste = /data:image\/(?:png|jpe?g|gif|webp);base64,/i.test(input2);
572153
+ const isSmallMultiCharInput = input2.length > 1 && input2.length <= pasteIndicatorThreshold && !input2.includes("\n") && !looksLikeImageDataPaste;
572033
572154
  if (isSingleCharInput && !refs.isProcessingInput.current) {
572034
572155
  buffer.insert(input2);
572035
572156
  const text2 = buffer.getFullText();
@@ -577226,7 +577347,7 @@ function getDelayAwareColor(waitingSeconds, baseColor, criticalColor) {
577226
577347
  }
577227
577348
  return baseColor;
577228
577349
  }
577229
- function LoadingIndicator({ isStreaming, isStopping, isSaving, isCompressing, hasPendingToolConfirmation, hasPendingUserQuestion, hasBlockingOverlay, terminalWidth, animationFrame, retryStatus, codebaseSearchStatus, isReasoning, streamTokenCount, elapsedSeconds, currentModel, teamMode }) {
577350
+ function LoadingIndicator({ isStreaming, isStopping, isSaving, isCompressing, isAutoCompressing = false, hasPendingToolConfirmation, hasPendingUserQuestion, hasBlockingOverlay, terminalWidth, animationFrame, retryStatus, codebaseSearchStatus, isReasoning, streamTokenCount, elapsedSeconds, currentModel, teamMode }) {
577230
577351
  const { theme: theme14 } = useTheme();
577231
577352
  const { t } = useI18n();
577232
577353
  const teammateStream = (0, import_react124.useSyncExternalStore)(subscribeTeammateStream, getTeammateStreamSnapshot);
@@ -577238,11 +577359,12 @@ function LoadingIndicator({ isStreaming, isStopping, isSaving, isCompressing, ha
577238
577359
  ].join("|");
577239
577360
  const previousStreamActivityMarkerRef = (0, import_react124.useRef)(null);
577240
577361
  const lastStreamActivityElapsedSecondsRef = (0, import_react124.useRef)(elapsedSeconds);
577241
- if (!isStreaming || isCompressing || previousStreamActivityMarkerRef.current !== streamActivityMarker) {
577362
+ const shouldIgnoreStreamDelay = isCompressing || isAutoCompressing;
577363
+ if (!isStreaming || shouldIgnoreStreamDelay || previousStreamActivityMarkerRef.current !== streamActivityMarker) {
577242
577364
  previousStreamActivityMarkerRef.current = streamActivityMarker;
577243
577365
  lastStreamActivityElapsedSecondsRef.current = elapsedSeconds;
577244
577366
  }
577245
- const waitingForStreamSeconds = isStreaming && !isCompressing ? Math.max(0, elapsedSeconds - lastStreamActivityElapsedSecondsRef.current) : 0;
577367
+ const waitingForStreamSeconds = isStreaming && !shouldIgnoreStreamDelay ? Math.max(0, elapsedSeconds - lastStreamActivityElapsedSecondsRef.current) : 0;
577246
577368
  const streamDelayStage = getStreamDelayStage(waitingForStreamSeconds);
577247
577369
  const loadingShimmerColors = STREAM_DELAY_SHIMMER_COLORS[streamDelayStage];
577248
577370
  const loadingIconColor = getDelayAwareColor(waitingForStreamSeconds, [theme14.colors.cyan, theme14.colors.menuInfo][animationFrame % 2], STREAM_DELAY_SHIMMER_COLORS.critical.base);
@@ -579286,7 +579408,7 @@ var init_ChatFooter = __esm({
579286
579408
  !props.showReviewCommitPanel && !props.showIdeSelectPanel && !props.showDiffReviewPanel && !props.showSkillsListPanel && import_react132.default.createElement(
579287
579409
  import_react132.default.Fragment,
579288
579410
  null,
579289
- import_react132.default.createElement(LoadingIndicator, { isStreaming: props.isStreaming, isStopping: props.isStopping, isSaving: props.isSaving, isCompressing: props.isCompressing, hasPendingToolConfirmation: props.hasPendingToolConfirmation, hasPendingUserQuestion: props.hasPendingUserQuestion, hasBlockingOverlay: props.hasBlockingOverlay, terminalWidth: props.terminalWidth, animationFrame: props.animationFrame, retryStatus: props.retryStatus, codebaseSearchStatus: props.codebaseSearchStatus, isReasoning: props.isReasoning, streamTokenCount: props.streamTokenCount, elapsedSeconds: props.elapsedSeconds, currentModel: props.currentModel, teamMode: props.teamMode }),
579411
+ import_react132.default.createElement(LoadingIndicator, { isStreaming: props.isStreaming, isStopping: props.isStopping, isSaving: props.isSaving, isCompressing: props.isCompressing, isAutoCompressing: props.isAutoCompressing, hasPendingToolConfirmation: props.hasPendingToolConfirmation, hasPendingUserQuestion: props.hasPendingUserQuestion, hasBlockingOverlay: props.hasBlockingOverlay, terminalWidth: props.terminalWidth, animationFrame: props.animationFrame, retryStatus: props.retryStatus, codebaseSearchStatus: props.codebaseSearchStatus, isReasoning: props.isReasoning, streamTokenCount: props.streamTokenCount, elapsedSeconds: props.elapsedSeconds, currentModel: props.currentModel, teamMode: props.teamMode }),
579290
579412
  props.btwPrompt ? import_react132.default.createElement(
579291
579413
  import_react132.Suspense,
579292
579414
  { fallback: import_react132.default.createElement(
@@ -579451,14 +579573,14 @@ var init_useSessionSave = __esm({
579451
579573
  // dist/utils/config/permissionsConfig.js
579452
579574
  import { join as join39 } from "path";
579453
579575
  import { readFileSync as readFileSync26, writeFileSync as writeFileSync19, existsSync as existsSync35, mkdirSync as mkdirSync18 } from "fs";
579454
- function getSnowDirPath2(workingDirectory) {
579455
- return join39(workingDirectory, SNOW_DIR5);
579576
+ function getSnowDirPath(workingDirectory) {
579577
+ return join39(workingDirectory, SNOW_DIR4);
579456
579578
  }
579457
579579
  function getPermissionsFilePath(workingDirectory) {
579458
- return join39(getSnowDirPath2(workingDirectory), PERMISSIONS_FILE);
579580
+ return join39(getSnowDirPath(workingDirectory), PERMISSIONS_FILE);
579459
579581
  }
579460
579582
  function ensureConfigDirectory7(workingDirectory) {
579461
- const snowDir = getSnowDirPath2(workingDirectory);
579583
+ const snowDir = getSnowDirPath(workingDirectory);
579462
579584
  if (!existsSync35(snowDir)) {
579463
579585
  mkdirSync18(snowDir, { recursive: true });
579464
579586
  }
@@ -579522,11 +579644,11 @@ function removeToolFromPermissions(workingDirectory, toolName) {
579522
579644
  function clearAllPermissions(workingDirectory) {
579523
579645
  savePermissionsConfig(workingDirectory, { alwaysApprovedTools: [] });
579524
579646
  }
579525
- var SNOW_DIR5, PERMISSIONS_FILE, DEFAULT_CONFIG6;
579647
+ var SNOW_DIR4, PERMISSIONS_FILE, DEFAULT_CONFIG6;
579526
579648
  var init_permissionsConfig = __esm({
579527
579649
  "dist/utils/config/permissionsConfig.js"() {
579528
579650
  "use strict";
579529
- SNOW_DIR5 = ".snow";
579651
+ SNOW_DIR4 = ".snow";
579530
579652
  PERMISSIONS_FILE = "permissions.json";
579531
579653
  DEFAULT_CONFIG6 = {
579532
579654
  alwaysApprovedTools: []
@@ -580276,6 +580398,14 @@ function resolveSnapshotIndex(liveMessages, liveIndex, sessionMessages) {
580276
580398
  }
580277
580399
  return liveIndex;
580278
580400
  }
580401
+ function getCompressedSummarySnapshotIndex(sessionMessages) {
580402
+ const uiMessages = convertSessionMessagesToUI(sessionMessages);
580403
+ const firstUserIndex = uiMessages.findIndex((msg) => {
580404
+ var _a20;
580405
+ return (msg == null ? void 0 : msg.role) === "user" && ((_a20 = msg.content) == null ? void 0 : _a20.trim()) && !msg.subAgentDirected;
580406
+ });
580407
+ return firstUserIndex >= 0 ? firstUserIndex : 0;
580408
+ }
580279
580409
  function useRollback(props) {
580280
580410
  const { messages, setMessages, snapshotState, clearSavedMessages, setRemountKey, setRestoreInputContent, currentContextPercentageRef, streamingState } = props;
580281
580411
  const { stdout } = use_stdout_default();
@@ -580299,7 +580429,7 @@ function useRollback(props) {
580299
580429
  const performRollback = async (selectedIndex, rollbackFiles, rollbackConversation, selectedFiles) => {
580300
580430
  var _a20;
580301
580431
  const currentSession = sessionManager.getCurrentSession();
580302
- const sIdx = getSnapshotIndex(selectedIndex);
580432
+ const sIdx = (currentSession == null ? void 0 : currentSession.compressedFrom) != null && selectedIndex === 0 ? getCompressedSummarySnapshotIndex(currentSession.messages) : getSnapshotIndex(selectedIndex);
580303
580433
  if (rollbackFiles && currentSession) {
580304
580434
  if (selectedFiles && selectedFiles.length > 0) {
580305
580435
  await hashBasedSnapshotManager.rollbackToMessageIndex(currentSession.id, sIdx, selectedFiles);
@@ -580449,7 +580579,8 @@ function useRollback(props) {
580449
580579
  const currentSession = sessionManager.getCurrentSession();
580450
580580
  if (!currentSession)
580451
580581
  return;
580452
- const sIdx = getSnapshotIndex(selectedIndex);
580582
+ const isCompressedSummaryRollback = selectedIndex === 0 && currentSession.compressedFrom != null;
580583
+ const sIdx = isCompressedSummaryRollback ? getCompressedSummarySnapshotIndex(currentSession.messages) : getSnapshotIndex(selectedIndex);
580453
580584
  if (selectedIndex === 0 && currentSession.compressedFrom !== void 0 && currentSession.compressedFrom !== null) {
580454
580585
  const filePaths2 = await hashBasedSnapshotManager.getFilesToRollback(currentSession.id, sIdx);
580455
580586
  const nbCount2 = getNotebookRollbackCount(currentSession.id, sIdx);
@@ -583544,7 +583675,7 @@ function clampProgress(progress) {
583544
583675
  return Math.max(0, Math.min(100, Math.round(progress)));
583545
583676
  }
583546
583677
  function buildProgressBar(progress, terminalWidth) {
583547
- const barWidth = Math.max(20, Math.min(46, terminalWidth - 12));
583678
+ const barWidth = Math.max(4, Math.min(46, terminalWidth - 12));
583548
583679
  const filled = Math.max(0, Math.min(barWidth, Math.round(progress / 100 * barWidth)));
583549
583680
  const empty = barWidth - filled;
583550
583681
  return {
@@ -583552,6 +583683,50 @@ function buildProgressBar(progress, terminalWidth) {
583552
583683
  emptyBar: "\u25B1".repeat(empty)
583553
583684
  };
583554
583685
  }
583686
+ function getSafeLineWidth(terminalWidth, reservedColumns = 0) {
583687
+ return Math.max(1, terminalWidth - reservedColumns);
583688
+ }
583689
+ function getSafeIndentedLineWidth(terminalWidth) {
583690
+ return getSafeLineWidth(terminalWidth, INDENT_WIDTH + STREAM_VIEWPORT_RESERVED_COLUMNS);
583691
+ }
583692
+ function normalizeStreamContent(content) {
583693
+ return (content == null ? void 0 : content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/[\t\v\f]+/g, " ")) ?? "";
583694
+ }
583695
+ function sliceByVisualWidth(text2, maxWidth) {
583696
+ if (!text2 || maxWidth <= 0) {
583697
+ return "";
583698
+ }
583699
+ let result2 = "";
583700
+ let width = 0;
583701
+ for (const char of text2) {
583702
+ const charWidth = stringWidth4(char);
583703
+ if (width + charWidth > maxWidth) {
583704
+ break;
583705
+ }
583706
+ result2 += char;
583707
+ width += charWidth;
583708
+ }
583709
+ return result2;
583710
+ }
583711
+ function buildStreamViewportLines(content, terminalWidth) {
583712
+ const width = getSafeLineWidth(terminalWidth, STREAM_VIEWPORT_INDENT_WIDTH + STREAM_VIEWPORT_RESERVED_COLUMNS);
583713
+ const logicalLines = normalizeStreamContent(content).split("\n");
583714
+ const visibleLines = logicalLines.slice(-STREAM_VIEWPORT_HEIGHT);
583715
+ return [
583716
+ ...Array(Math.max(0, STREAM_VIEWPORT_HEIGHT - visibleLines.length)).fill({
583717
+ text: " "
583718
+ }),
583719
+ ...visibleLines.map((line) => ({
583720
+ text: sliceByVisualWidth(line || " ", width) || " "
583721
+ }))
583722
+ ];
583723
+ }
583724
+ function buildSafeInlineText(text2, terminalWidth) {
583725
+ return sliceByVisualWidth(text2, getSafeLineWidth(terminalWidth, 1)) || " ";
583726
+ }
583727
+ function buildSafeIndentedText(text2, terminalWidth) {
583728
+ return sliceByVisualWidth(text2, getSafeIndentedLineWidth(terminalWidth)) || " ";
583729
+ }
583555
583730
  function CompressionStatus({ status, terminalWidth }) {
583556
583731
  const { theme: theme14 } = useTheme();
583557
583732
  const [animatedProgress, setAnimatedProgress] = import_react151.default.useState(0);
@@ -583587,37 +583762,38 @@ function CompressionStatus({ status, terminalWidth }) {
583587
583762
  if (step === "compressing") {
583588
583763
  const progress = clampProgress(animatedProgress);
583589
583764
  const { filledBar, emptyBar } = buildProgressBar(progress, terminalWidth);
583765
+ const streamViewportLines = buildStreamViewportLines(status.streamContent, terminalWidth);
583766
+ const safeTitle = buildSafeInlineText("\u2735 Compacting conversation...", terminalWidth);
583767
+ const sessionLine = sessionId ? buildSafeIndentedText(`Session: ${sessionId}`, terminalWidth) : void 0;
583768
+ const progressLine = buildSafeIndentedText(`${filledBar}${emptyBar} ${progress}%`, terminalWidth);
583769
+ const messageLine = message ? buildSafeIndentedText(message, terminalWidth) : void 0;
583590
583770
  return import_react151.default.createElement(
583591
583771
  Box_default,
583592
583772
  { flexDirection: "column", width: terminalWidth },
583593
583773
  import_react151.default.createElement(
583594
583774
  Box_default,
583595
- null,
583596
- import_react151.default.createElement(Text, { color: theme14.colors.menuInfo }, "\u2735 Compacting conversation...")
583775
+ { height: 1 },
583776
+ import_react151.default.createElement(Text, { color: theme14.colors.menuInfo, wrap: "truncate" }, safeTitle)
583597
583777
  ),
583598
- sessionId && import_react151.default.createElement(
583778
+ import_react151.default.createElement(Box_default, { paddingLeft: STREAM_VIEWPORT_INDENT_WIDTH, marginTop: 1, flexDirection: "column" }, streamViewportLines.map((line, index) => import_react151.default.createElement(
583599
583779
  Box_default,
583600
- { paddingLeft: 2, marginTop: 1 },
583601
- import_react151.default.createElement(Text, { dimColor: true }, "Session: "),
583602
- import_react151.default.createElement(Text, { color: theme14.colors.menuSecondary }, sessionId)
583780
+ { key: `compression-stream-line-${index}`, height: 1 },
583781
+ import_react151.default.createElement(Text, { italic: true, dimColor: true, color: theme14.colors.menuSecondary, wrap: "truncate" }, line.text)
583782
+ ))),
583783
+ sessionLine && import_react151.default.createElement(
583784
+ Box_default,
583785
+ { paddingLeft: 2, marginTop: 1, height: 1 },
583786
+ import_react151.default.createElement(Text, { color: theme14.colors.menuSecondary, wrap: "truncate" }, sessionLine)
583603
583787
  ),
583604
583788
  import_react151.default.createElement(
583605
583789
  Box_default,
583606
- { paddingLeft: 2, marginTop: 1 },
583607
- import_react151.default.createElement(Text, { color: theme14.colors.text }, filledBar),
583608
- import_react151.default.createElement(Text, { dimColor: true }, emptyBar),
583609
- import_react151.default.createElement(
583610
- Text,
583611
- { dimColor: true },
583612
- " ",
583613
- progress,
583614
- "%"
583615
- )
583790
+ { paddingLeft: 2, marginTop: 1, height: 1 },
583791
+ import_react151.default.createElement(Text, { color: theme14.colors.text, wrap: "truncate" }, progressLine)
583616
583792
  ),
583617
- message && import_react151.default.createElement(
583793
+ messageLine && import_react151.default.createElement(
583618
583794
  Box_default,
583619
- { paddingLeft: 2, marginTop: 1 },
583620
- import_react151.default.createElement(Text, { dimColor: true, wrap: "truncate" }, message)
583795
+ { paddingLeft: 2, marginTop: 1, height: 1 },
583796
+ import_react151.default.createElement(Text, { dimColor: true, wrap: "truncate" }, messageLine)
583621
583797
  )
583622
583798
  );
583623
583799
  }
@@ -583676,13 +583852,14 @@ function CompressionStatus({ status, terminalWidth }) {
583676
583852
  )
583677
583853
  );
583678
583854
  }
583679
- var import_react151, stepIcons, stepLabels;
583855
+ var import_react151, stepIcons, stepLabels, STREAM_VIEWPORT_HEIGHT, STREAM_VIEWPORT_RESERVED_COLUMNS, STREAM_VIEWPORT_INDENT_WIDTH, INDENT_WIDTH;
583680
583856
  var init_CompressionStatus = __esm({
583681
583857
  async "dist/ui/components/compression/CompressionStatus.js"() {
583682
583858
  "use strict";
583683
583859
  import_react151 = __toESM(require_react(), 1);
583684
583860
  await init_src();
583685
583861
  await init_build2();
583862
+ init_string_width4();
583686
583863
  init_ThemeContext();
583687
583864
  stepIcons = {
583688
583865
  saving: { icon: "\u25C9", color: "yellow" },
@@ -583702,6 +583879,10 @@ var init_CompressionStatus = __esm({
583702
583879
  failed: "Compression failed",
583703
583880
  skipped: "Compression skipped"
583704
583881
  };
583882
+ STREAM_VIEWPORT_HEIGHT = 5;
583883
+ STREAM_VIEWPORT_RESERVED_COLUMNS = 8;
583884
+ STREAM_VIEWPORT_INDENT_WIDTH = 2;
583885
+ INDENT_WIDTH = 2;
583705
583886
  }
583706
583887
  });
583707
583888
 
@@ -593518,6 +593699,7 @@ function ChatScreen({ autoResume, resumeSessionId: resumeSessionId2, enableYolo,
593518
593699
  fileUpdateNotification,
593519
593700
  currentProfileName: panelState.currentProfileName,
593520
593701
  isCompressing,
593702
+ isAutoCompressing: streamingState.isAutoCompressing,
593521
593703
  compressionError,
593522
593704
  backgroundProcesses: backgroundProcesses.processes,
593523
593705
  showBackgroundPanel: backgroundProcesses.showPanel,
@@ -595274,15 +595456,15 @@ ${formatMessage(t.foundInvalidPids, {
595274
595456
  console.log(t.autoCleanupHint);
595275
595457
  }
595276
595458
  }
595277
- var SNOW_DIR6, DAEMON_DIR, LOG_DIR;
595459
+ var SNOW_DIR5, DAEMON_DIR, LOG_DIR;
595278
595460
  var init_sseDaemon = __esm({
595279
595461
  "dist/utils/sse/sseDaemon.js"() {
595280
595462
  "use strict";
595281
595463
  init_languageConfig();
595282
595464
  init_i18n();
595283
- SNOW_DIR6 = join42(homedir24(), ".snow");
595284
- DAEMON_DIR = join42(SNOW_DIR6, "sse-daemons");
595285
- LOG_DIR = join42(SNOW_DIR6, "sse-logs");
595465
+ SNOW_DIR5 = join42(homedir24(), ".snow");
595466
+ DAEMON_DIR = join42(SNOW_DIR5, "sse-daemons");
595467
+ LOG_DIR = join42(SNOW_DIR5, "sse-logs");
595286
595468
  if (!existsSync37(DAEMON_DIR)) {
595287
595469
  mkdirSync20(DAEMON_DIR, { recursive: true });
595288
595470
  }
@@ -609918,7 +610100,7 @@ var require_package3 = __commonJS({
609918
610100
  "package.json"(exports2, module2) {
609919
610101
  module2.exports = {
609920
610102
  name: "snow-ai",
609921
- version: "0.7.29",
610103
+ version: "0.7.30",
609922
610104
  description: "Agentic coding in your terminal",
609923
610105
  license: "MIT",
609924
610106
  bin: {
@@ -611379,6 +611561,7 @@ import path6 from "node:path";
611379
611561
  var LEGACY_FILES = {
611380
611562
  codebase: "codebase.json",
611381
611563
  connection: "connection.json",
611564
+ workingDirs: "working-dirs.json",
611382
611565
  disabledBuiltin: "disabled-builtin-tools.json",
611383
611566
  disabledMcp: "disabled-mcp-tools.json",
611384
611567
  optInMcp: "opt-in-mcp-tools.json",
@@ -611464,6 +611647,14 @@ function migrateScope(scope, workingDirectory) {
611464
611647
  return false;
611465
611648
  });
611466
611649
  }
611650
+ tryMigrate(LEGACY_FILES.workingDirs, (data) => {
611651
+ if (Array.isArray(data.directories) && settings.workingDirectories === void 0) {
611652
+ const isWorkingDirectory = (d) => !!d && typeof d === "object" && typeof d["path"] === "string" && typeof d["isDefault"] === "boolean" && typeof d["addedAt"] === "number";
611653
+ settings.workingDirectories = data.directories.filter(isWorkingDirectory);
611654
+ return true;
611655
+ }
611656
+ return false;
611657
+ });
611467
611658
  tryMigrate(LEGACY_FILES.disabledBuiltin, (data) => {
611468
611659
  if (Array.isArray(data.disabledServices) && settings.disabledBuiltInServices === void 0) {
611469
611660
  settings.disabledBuiltInServices = data.disabledServices.filter((v) => typeof v === "string");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-ai",
3
- "version": "0.7.29",
3
+ "version": "0.7.30",
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.29",
3
+ "version": "0.7.30",
4
4
  "description": "Agentic coding in your terminal",
5
5
  "license": "MIT",
6
6
  "bin": {