juno-code 1.0.31 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import fs3 from 'fs-extra';
2
+ import fs2 from 'fs-extra';
3
3
  import * as path3 from 'path';
4
4
  import path3__default, { dirname, join } from 'path';
5
5
  import * as os3 from 'os';
@@ -315,12 +315,12 @@ var init_service_installer = __esm({
315
315
  const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
316
316
  const require3 = createRequire(import.meta.url);
317
317
  let packageJsonPath = path3.join(__dirname2, "..", "..", "package.json");
318
- if (fs3.existsSync(packageJsonPath)) {
318
+ if (fs2.existsSync(packageJsonPath)) {
319
319
  const packageJson2 = require3(packageJsonPath);
320
320
  return packageJson2.version;
321
321
  }
322
322
  packageJsonPath = path3.join(__dirname2, "..", "..", "..", "package.json");
323
- if (fs3.existsSync(packageJsonPath)) {
323
+ if (fs2.existsSync(packageJsonPath)) {
324
324
  const packageJson2 = require3(packageJsonPath);
325
325
  return packageJson2.version;
326
326
  }
@@ -334,11 +334,11 @@ var init_service_installer = __esm({
334
334
  */
335
335
  static async getInstalledVersion() {
336
336
  try {
337
- const exists = await fs3.pathExists(this.VERSION_FILE);
337
+ const exists = await fs2.pathExists(this.VERSION_FILE);
338
338
  if (!exists) {
339
339
  return null;
340
340
  }
341
- const version3 = await fs3.readFile(this.VERSION_FILE, "utf-8");
341
+ const version3 = await fs2.readFile(this.VERSION_FILE, "utf-8");
342
342
  return version3.trim();
343
343
  } catch {
344
344
  return null;
@@ -349,7 +349,7 @@ var init_service_installer = __esm({
349
349
  */
350
350
  static async saveVersion() {
351
351
  const version3 = this.getPackageVersion();
352
- await fs3.writeFile(this.VERSION_FILE, version3, "utf-8");
352
+ await fs2.writeFile(this.VERSION_FILE, version3, "utf-8");
353
353
  }
354
354
  /**
355
355
  * Check if services need to be updated based on version
@@ -361,7 +361,7 @@ var init_service_installer = __esm({
361
361
  if (!installedVersion) {
362
362
  return true;
363
363
  }
364
- const exists = await fs3.pathExists(this.SERVICES_DIR);
364
+ const exists = await fs2.pathExists(this.SERVICES_DIR);
365
365
  if (!exists) {
366
366
  return true;
367
367
  }
@@ -369,8 +369,10 @@ var init_service_installer = __esm({
369
369
  return true;
370
370
  }
371
371
  if (semver.eq(packageVersion, installedVersion)) {
372
- const codexExists = await fs3.pathExists(path3.join(this.SERVICES_DIR, "codex.py"));
373
- const claudeExists = await fs3.pathExists(path3.join(this.SERVICES_DIR, "claude.py"));
372
+ const installedCodex = path3.join(this.SERVICES_DIR, "codex.py");
373
+ const installedClaude = path3.join(this.SERVICES_DIR, "claude.py");
374
+ const codexExists = await fs2.pathExists(installedCodex);
375
+ const claudeExists = await fs2.pathExists(installedClaude);
374
376
  if (!codexExists || !claudeExists) {
375
377
  return true;
376
378
  }
@@ -378,15 +380,32 @@ var init_service_installer = __esm({
378
380
  const packageServicesDir = this.getPackageServicesDir();
379
381
  const packageCodex = path3.join(packageServicesDir, "codex.py");
380
382
  const packageClaude = path3.join(packageServicesDir, "claude.py");
381
- const packageCodexExists = await fs3.pathExists(packageCodex);
382
- const packageClaudeExists = await fs3.pathExists(packageClaude);
383
- if (packageCodexExists || packageClaudeExists) {
384
- const isDevelopment2 = packageServicesDir.includes("/src/");
385
- if (isDevelopment2) {
383
+ const packageCodexExists = await fs2.pathExists(packageCodex);
384
+ const packageClaudeExists = await fs2.pathExists(packageClaude);
385
+ if (packageCodexExists) {
386
+ const [pkg, inst] = await Promise.all([
387
+ fs2.readFile(packageCodex, "utf-8"),
388
+ fs2.readFile(installedCodex, "utf-8")
389
+ ]);
390
+ if (pkg !== inst) {
386
391
  return true;
387
392
  }
388
393
  }
394
+ if (packageClaudeExists) {
395
+ const [pkg, inst] = await Promise.all([
396
+ fs2.readFile(packageClaude, "utf-8"),
397
+ fs2.readFile(installedClaude, "utf-8")
398
+ ]);
399
+ if (pkg !== inst) {
400
+ return true;
401
+ }
402
+ }
403
+ const isDevelopment2 = packageServicesDir.includes("/src/");
404
+ if (isDevelopment2) {
405
+ return true;
406
+ }
389
407
  } catch {
408
+ return true;
390
409
  }
391
410
  }
392
411
  return false;
@@ -400,11 +419,11 @@ var init_service_installer = __esm({
400
419
  static getPackageServicesDir() {
401
420
  const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
402
421
  let servicesPath = path3.join(__dirname2, "..", "..", "templates", "services");
403
- if (fs3.existsSync(servicesPath)) {
422
+ if (fs2.existsSync(servicesPath)) {
404
423
  return servicesPath;
405
424
  }
406
425
  servicesPath = path3.join(__dirname2, "..", "templates", "services");
407
- if (fs3.existsSync(servicesPath)) {
426
+ if (fs2.existsSync(servicesPath)) {
408
427
  return servicesPath;
409
428
  }
410
429
  throw new Error("Could not find services directory in package");
@@ -415,18 +434,18 @@ var init_service_installer = __esm({
415
434
  */
416
435
  static async install(silent = false) {
417
436
  try {
418
- await fs3.ensureDir(this.SERVICES_DIR);
437
+ await fs2.ensureDir(this.SERVICES_DIR);
419
438
  const packageServicesDir = this.getPackageServicesDir();
420
- await fs3.copy(packageServicesDir, this.SERVICES_DIR, {
439
+ await fs2.copy(packageServicesDir, this.SERVICES_DIR, {
421
440
  overwrite: true,
422
441
  preserveTimestamps: true
423
442
  });
424
- const files = await fs3.readdir(this.SERVICES_DIR);
443
+ const files = await fs2.readdir(this.SERVICES_DIR);
425
444
  for (const file of files) {
426
445
  const filePath = path3.join(this.SERVICES_DIR, file);
427
- const stat = await fs3.stat(filePath);
446
+ const stat = await fs2.stat(filePath);
428
447
  if (stat.isFile() && (file.endsWith(".py") || file.endsWith(".sh"))) {
429
- await fs3.chmod(filePath, 493);
448
+ await fs2.chmod(filePath, 493);
430
449
  }
431
450
  }
432
451
  await this.saveVersion();
@@ -473,11 +492,11 @@ var init_service_installer = __esm({
473
492
  */
474
493
  static async isInstalled() {
475
494
  try {
476
- const exists = await fs3.pathExists(this.SERVICES_DIR);
495
+ const exists = await fs2.pathExists(this.SERVICES_DIR);
477
496
  if (!exists) {
478
497
  return false;
479
498
  }
480
- const files = await fs3.readdir(this.SERVICES_DIR);
499
+ const files = await fs2.readdir(this.SERVICES_DIR);
481
500
  return files.length > 0;
482
501
  } catch {
483
502
  return false;
@@ -500,11 +519,11 @@ var init_service_installer = __esm({
500
519
  */
501
520
  static async listServices() {
502
521
  try {
503
- const exists = await fs3.pathExists(this.SERVICES_DIR);
522
+ const exists = await fs2.pathExists(this.SERVICES_DIR);
504
523
  if (!exists) {
505
524
  return [];
506
525
  }
507
- const files = await fs3.readdir(this.SERVICES_DIR);
526
+ const files = await fs2.readdir(this.SERVICES_DIR);
508
527
  return files.filter((file) => file.endsWith(".py") || file.endsWith(".sh"));
509
528
  } catch {
510
529
  return [];
@@ -515,9 +534,9 @@ var init_service_installer = __esm({
515
534
  */
516
535
  static async uninstall() {
517
536
  try {
518
- const exists = await fs3.pathExists(this.SERVICES_DIR);
537
+ const exists = await fs2.pathExists(this.SERVICES_DIR);
519
538
  if (exists) {
520
- await fs3.remove(this.SERVICES_DIR);
539
+ await fs2.remove(this.SERVICES_DIR);
521
540
  console.log("\u2713 Services uninstalled");
522
541
  }
523
542
  } catch (error) {
@@ -1093,17 +1112,17 @@ async function ensureHooksConfig(baseDir) {
1093
1112
  try {
1094
1113
  const configDir = path3.join(baseDir, ".juno_task");
1095
1114
  const configPath = path3.join(configDir, "config.json");
1096
- await fs3.ensureDir(configDir);
1097
- const configExists = await fs3.pathExists(configPath);
1115
+ await fs2.ensureDir(configDir);
1116
+ const configExists = await fs2.pathExists(configPath);
1098
1117
  const allHookTypes = getDefaultHooks();
1099
1118
  if (!configExists) {
1100
1119
  const defaultConfig = {
1101
1120
  ...DEFAULT_CONFIG,
1102
1121
  hooks: allHookTypes
1103
1122
  };
1104
- await fs3.writeJson(configPath, defaultConfig, { spaces: 2 });
1123
+ await fs2.writeJson(configPath, defaultConfig, { spaces: 2 });
1105
1124
  } else {
1106
- const existingConfig = await fs3.readJson(configPath);
1125
+ const existingConfig = await fs2.readJson(configPath);
1107
1126
  let needsUpdate = false;
1108
1127
  if (!existingConfig.hooks) {
1109
1128
  existingConfig.hooks = allHookTypes;
@@ -1121,7 +1140,7 @@ async function ensureHooksConfig(baseDir) {
1121
1140
  needsUpdate = true;
1122
1141
  }
1123
1142
  if (needsUpdate) {
1124
- await fs3.writeJson(configPath, existingConfig, { spaces: 2 });
1143
+ await fs2.writeJson(configPath, existingConfig, { spaces: 2 });
1125
1144
  }
1126
1145
  }
1127
1146
  } catch (error) {
@@ -1174,6 +1193,8 @@ var init_config = __esm({
1174
1193
  JUNO_CODE_MCP_RETRIES: "mcpRetries",
1175
1194
  JUNO_CODE_MCP_SERVER_PATH: "mcpServerPath",
1176
1195
  JUNO_CODE_MCP_SERVER_NAME: "mcpServerName",
1196
+ // Hook settings
1197
+ JUNO_CODE_HOOK_COMMAND_TIMEOUT: "hookCommandTimeout",
1177
1198
  // TUI settings
1178
1199
  JUNO_CODE_INTERACTIVE: "interactive",
1179
1200
  JUNO_CODE_HEADLESS_MODE: "headlessMode",
@@ -1197,6 +1218,8 @@ var init_config = __esm({
1197
1218
  JUNO_TASK_MCP_RETRIES: "mcpRetries",
1198
1219
  JUNO_TASK_MCP_SERVER_PATH: "mcpServerPath",
1199
1220
  JUNO_TASK_MCP_SERVER_NAME: "mcpServerName",
1221
+ // Hook settings
1222
+ JUNO_TASK_HOOK_COMMAND_TIMEOUT: "hookCommandTimeout",
1200
1223
  // TUI settings
1201
1224
  JUNO_TASK_INTERACTIVE: "interactive",
1202
1225
  JUNO_TASK_HEADLESS_MODE: "headlessMode",
@@ -1228,6 +1251,8 @@ var init_config = __esm({
1228
1251
  mcpRetries: z.number().int().min(0).max(10).describe("Number of retries for MCP operations"),
1229
1252
  mcpServerPath: z.string().optional().describe("Path to MCP server executable (auto-discovered if not specified)"),
1230
1253
  mcpServerName: z.string().optional().describe('Named MCP server to connect to (e.g., "roundtable-ai")'),
1254
+ // Hook settings
1255
+ hookCommandTimeout: z.number().int().min(1e3).max(36e5).optional().describe("Timeout for individual hook commands in milliseconds (default: 300000 = 5 minutes)"),
1231
1256
  // TUI settings
1232
1257
  interactive: z.boolean().describe("Enable interactive mode"),
1233
1258
  headlessMode: z.boolean().describe("Enable headless mode (no TUI)"),
@@ -3337,7 +3362,8 @@ var init_advanced_logger = __esm({
3337
3362
  async function executeHook(hookType, hooks, context = {}, options = {}) {
3338
3363
  const startTime = Date.now();
3339
3364
  const {
3340
- commandTimeout = 3e4,
3365
+ commandTimeout = 3e5,
3366
+ // 5 minutes default (increased from 30s to support long-running hook scripts)
3341
3367
  env: env2 = {},
3342
3368
  continueOnError = true,
3343
3369
  logContext = "SYSTEM" /* SYSTEM */
@@ -3412,8 +3438,12 @@ async function executeHook(hookType, hooks, context = {}, options = {}) {
3412
3438
  env: execEnv,
3413
3439
  // Capture both stdout and stderr
3414
3440
  all: true,
3415
- reject: false
3441
+ reject: false,
3416
3442
  // Don't throw on non-zero exit codes
3443
+ // Use input: '' to provide empty stdin and properly close it (sends EOF)
3444
+ // This prevents commands from hanging waiting for stdin while still
3445
+ // allowing internal pipe operations to work correctly
3446
+ input: ""
3417
3447
  });
3418
3448
  const duration = Date.now() - commandStartTime;
3419
3449
  const success2 = result2.exitCode === 0;
@@ -3559,6 +3589,12 @@ function createExecutionRequest(options) {
3559
3589
  if (options.mcpServerName !== void 0) {
3560
3590
  result.mcpServerName = options.mcpServerName;
3561
3591
  }
3592
+ if (options.resume !== void 0) {
3593
+ result.resume = options.resume;
3594
+ }
3595
+ if (options.continueConversation !== void 0) {
3596
+ result.continueConversation = options.continueConversation;
3597
+ }
3562
3598
  return result;
3563
3599
  }
3564
3600
  var DEFAULT_ERROR_RECOVERY_CONFIG, DEFAULT_RATE_LIMIT_CONFIG, DEFAULT_PROGRESS_CONFIG, ExecutionEngine;
@@ -3909,6 +3945,8 @@ var init_engine = __esm({
3909
3945
  maxIterations: context.request.maxIterations,
3910
3946
  instruction: context.request.instruction
3911
3947
  }
3948
+ }, {
3949
+ commandTimeout: this.engineConfig.config.hookCommandTimeout
3912
3950
  });
3913
3951
  }
3914
3952
  } catch (error) {
@@ -3941,6 +3979,8 @@ var init_engine = __esm({
3941
3979
  duration: context.endTime ? context.endTime.getTime() - context.startTime.getTime() : 0,
3942
3980
  success: context.status === "completed" /* COMPLETED */
3943
3981
  }
3982
+ }, {
3983
+ commandTimeout: this.engineConfig.config.hookCommandTimeout
3944
3984
  });
3945
3985
  }
3946
3986
  } catch (error) {
@@ -3992,6 +4032,8 @@ var init_engine = __esm({
3992
4032
  maxIterations: context.request.maxIterations,
3993
4033
  subagent: context.request.subagent
3994
4034
  }
4035
+ }, {
4036
+ commandTimeout: this.engineConfig.config.hookCommandTimeout
3995
4037
  });
3996
4038
  }
3997
4039
  } catch (error) {
@@ -4009,6 +4051,8 @@ var init_engine = __esm({
4009
4051
  ...context.request.allowedTools !== void 0 && { allowedTools: context.request.allowedTools },
4010
4052
  ...context.request.appendAllowedTools !== void 0 && { appendAllowedTools: context.request.appendAllowedTools },
4011
4053
  ...context.request.disallowedTools !== void 0 && { disallowedTools: context.request.disallowedTools },
4054
+ ...context.request.resume !== void 0 && { resume: context.request.resume },
4055
+ ...context.request.continueConversation !== void 0 && { continueConversation: context.request.continueConversation },
4012
4056
  iteration: iterationNumber
4013
4057
  },
4014
4058
  timeout: context.request.timeoutMs || this.engineConfig.config.mcpTimeout,
@@ -4056,6 +4100,8 @@ var init_engine = __esm({
4056
4100
  duration: iterationResult.duration,
4057
4101
  toolCallStatus: iterationResult.toolResult.status
4058
4102
  }
4103
+ }, {
4104
+ commandTimeout: this.engineConfig.config.hookCommandTimeout
4059
4105
  });
4060
4106
  }
4061
4107
  } catch (error) {
@@ -4104,6 +4150,8 @@ var init_engine = __esm({
4104
4150
  error: mcpError.message,
4105
4151
  errorType: mcpError.type
4106
4152
  }
4153
+ }, {
4154
+ commandTimeout: this.engineConfig.config.hookCommandTimeout
4107
4155
  });
4108
4156
  }
4109
4157
  } catch (hookError) {
@@ -4810,7 +4858,7 @@ var init_config2 = __esm({
4810
4858
  return cached;
4811
4859
  }
4812
4860
  try {
4813
- const configContent = await fs3.readFile(configPath, "utf-8");
4861
+ const configContent = await fs2.readFile(configPath, "utf-8");
4814
4862
  const config = JSON.parse(configContent);
4815
4863
  this.validateConfig(config);
4816
4864
  const resolvedConfig = this.resolveConfigPaths(config, path3.dirname(configPath));
@@ -4832,7 +4880,7 @@ var init_config2 = __esm({
4832
4880
  const rootDir = path3.parse(currentDir).root;
4833
4881
  while (currentDir !== rootDir) {
4834
4882
  const configPath = path3.join(currentDir, ".juno_task", "mcp.json");
4835
- if (await fs3.pathExists(configPath)) {
4883
+ if (await fs2.pathExists(configPath)) {
4836
4884
  return configPath;
4837
4885
  }
4838
4886
  currentDir = path3.dirname(currentDir);
@@ -5018,7 +5066,7 @@ var init_logger = __esm({
5018
5066
  * Matches Python's generate_log_file function
5019
5067
  */
5020
5068
  async initialize(subagent = "mcp") {
5021
- await fs3.ensureDir(this.logDirectory);
5069
+ await fs2.ensureDir(this.logDirectory);
5022
5070
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").split("T");
5023
5071
  const dateStr = timestamp[0];
5024
5072
  const timeStr = timestamp[1].split("-")[0].substring(0, 6);
@@ -5027,7 +5075,7 @@ var init_logger = __esm({
5027
5075
  this.logFilePath = path3__default.join(this.logDirectory, logFileName);
5028
5076
  const header = `# Juno-Task TypeScript Log - Started ${(/* @__PURE__ */ new Date()).toISOString()}
5029
5077
  `;
5030
- await fs3.writeFile(this.logFilePath, header);
5078
+ await fs2.writeFile(this.logFilePath, header);
5031
5079
  }
5032
5080
  /**
5033
5081
  * Format log message matching Python version format
@@ -5045,7 +5093,7 @@ var init_logger = __esm({
5045
5093
  if (!this.logFilePath) {
5046
5094
  throw new Error("Logger not initialized. Call initialize() first.");
5047
5095
  }
5048
- await fs3.appendFile(this.logFilePath, message);
5096
+ await fs2.appendFile(this.logFilePath, message);
5049
5097
  }
5050
5098
  /**
5051
5099
  * Log message at specified level
@@ -7054,7 +7102,7 @@ var init_shell_backend = __esm({
7054
7102
  const timestamp = now.getFullYear().toString() + (now.getMonth() + 1).toString().padStart(2, "0") + now.getDate().toString().padStart(2, "0") + "_" + now.getHours().toString().padStart(2, "0") + now.getMinutes().toString().padStart(2, "0") + now.getSeconds().toString().padStart(2, "0");
7055
7103
  const logDir = path3.join(this.config.workingDirectory, ".juno_task", "logs");
7056
7104
  try {
7057
- await fs3.ensureDir(logDir);
7105
+ await fs2.ensureDir(logDir);
7058
7106
  } catch (error) {
7059
7107
  if (this.config?.debug) {
7060
7108
  engineLogger.warn(`Failed to create log directory: ${error instanceof Error ? error.message : String(error)}`);
@@ -7079,7 +7127,7 @@ var init_shell_backend = __esm({
7079
7127
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
7080
7128
  const logEntry = `[${timestamp}] ${message}
7081
7129
  `;
7082
- await fs3.appendFile(this.logFilePath, logEntry, "utf-8");
7130
+ await fs2.appendFile(this.logFilePath, logEntry, "utf-8");
7083
7131
  } catch (error) {
7084
7132
  if (this.config?.debug) {
7085
7133
  engineLogger.warn(`Failed to write to log file: ${error instanceof Error ? error.message : String(error)}`);
@@ -7190,6 +7238,12 @@ var init_shell_backend = __esm({
7190
7238
  args.push("--disallowedTools");
7191
7239
  args.push(...request.arguments.disallowedTools);
7192
7240
  }
7241
+ if (isPython && request.arguments?.resume) {
7242
+ args.push("--resume", request.arguments.resume);
7243
+ }
7244
+ if (isPython && request.arguments?.continueConversation) {
7245
+ args.push("--continue");
7246
+ }
7193
7247
  if (this.config.debug) {
7194
7248
  engineLogger.debug(`Executing script: ${command} ${args.join(" ")}`);
7195
7249
  engineLogger.debug(`Working directory: ${this.config.workingDirectory}`);
@@ -12613,7 +12667,9 @@ async function mainCommandHandler(args, options, command) {
12613
12667
  tools: options.tools,
12614
12668
  allowedTools: options.allowedTools,
12615
12669
  appendAllowedTools: options.appendAllowedTools,
12616
- disallowedTools: options.disallowedTools
12670
+ disallowedTools: options.disallowedTools,
12671
+ resume: options.resume,
12672
+ continueConversation: options.continue
12617
12673
  });
12618
12674
  const coordinator = new MainExecutionCoordinator(config, options.verbose, options.enableFeedback || false);
12619
12675
  const result = await coordinator.execute(executionRequest);
@@ -12770,7 +12826,7 @@ var init_main = __esm({
12770
12826
  return await this.collectInteractivePrompt();
12771
12827
  } else {
12772
12828
  const defaultPromptPath = path3.join(process.cwd(), ".juno_task", "prompt.md");
12773
- if (await fs3.pathExists(defaultPromptPath)) {
12829
+ if (await fs2.pathExists(defaultPromptPath)) {
12774
12830
  console.error(chalk15.blue(`\u{1F4C4} Using default prompt: ${chalk15.cyan(".juno_task/prompt.md")}`));
12775
12831
  return await this.loadPromptFromFile(defaultPromptPath);
12776
12832
  } else {
@@ -12798,7 +12854,7 @@ var init_main = __esm({
12798
12854
  }
12799
12855
  try {
12800
12856
  const resolvedPath = path3.resolve(prompt);
12801
- return await fs3.pathExists(resolvedPath);
12857
+ return await fs2.pathExists(resolvedPath);
12802
12858
  } catch {
12803
12859
  return false;
12804
12860
  }
@@ -12806,7 +12862,7 @@ var init_main = __esm({
12806
12862
  async loadPromptFromFile(filePath) {
12807
12863
  try {
12808
12864
  const resolvedPath = path3.resolve(filePath);
12809
- const content = await fs3.readFile(resolvedPath, "utf-8");
12865
+ const content = await fs2.readFile(resolvedPath, "utf-8");
12810
12866
  if (!content.trim()) {
12811
12867
  throw new FileSystemError(
12812
12868
  "Prompt file is empty",
@@ -13214,7 +13270,7 @@ async function validateJSONFile(configSchema, baseDir) {
13214
13270
  const warnings = [];
13215
13271
  const filePath = path3__default.join(baseDir, configSchema.file);
13216
13272
  try {
13217
- const exists = await fs3.pathExists(filePath);
13273
+ const exists = await fs2.pathExists(filePath);
13218
13274
  if (!exists) {
13219
13275
  if (configSchema.required) {
13220
13276
  errors.push({
@@ -13237,7 +13293,7 @@ async function validateJSONFile(configSchema, baseDir) {
13237
13293
  return { isValid: !configSchema.required, errors, warnings };
13238
13294
  }
13239
13295
  try {
13240
- await fs3.access(filePath, fs3.constants.R_OK);
13296
+ await fs2.access(filePath, fs2.constants.R_OK);
13241
13297
  } catch (accessError) {
13242
13298
  errors.push({
13243
13299
  file: configSchema.file,
@@ -13253,7 +13309,7 @@ async function validateJSONFile(configSchema, baseDir) {
13253
13309
  }
13254
13310
  let jsonData;
13255
13311
  try {
13256
- const fileContent = await fs3.readFile(filePath, "utf8");
13312
+ const fileContent = await fs2.readFile(filePath, "utf8");
13257
13313
  jsonData = JSON.parse(fileContent);
13258
13314
  } catch (parseError) {
13259
13315
  const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
@@ -13388,7 +13444,7 @@ function displayValidationResults(result) {
13388
13444
  }
13389
13445
  async function logValidationResults(result, baseDir = process.cwd()) {
13390
13446
  const logDir = path3__default.join(baseDir, ".juno_task", "logs");
13391
- await fs3.ensureDir(logDir);
13447
+ await fs2.ensureDir(logDir);
13392
13448
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
13393
13449
  const logFile = path3__default.join(logDir, `startup-validation-${timestamp}.log`);
13394
13450
  const logContent = [
@@ -13431,7 +13487,7 @@ async function logValidationResults(result, baseDir = process.cwd()) {
13431
13487
  logContent.push(``);
13432
13488
  }
13433
13489
  }
13434
- await fs3.writeFile(logFile, logContent.join("\n"));
13490
+ await fs2.writeFile(logFile, logContent.join("\n"));
13435
13491
  return logFile;
13436
13492
  }
13437
13493
  async function validateStartupConfigs(baseDir = process.cwd(), verbose = false) {
@@ -13765,7 +13821,7 @@ var TemplateEngine = class {
13765
13821
  let overallError;
13766
13822
  try {
13767
13823
  if (!options.dryRun) {
13768
- await fs3.ensureDir(targetDirectory);
13824
+ await fs2.ensureDir(targetDirectory);
13769
13825
  }
13770
13826
  for (const template of templates) {
13771
13827
  try {
@@ -15115,7 +15171,7 @@ This directory contains specification documents for your project.
15115
15171
  const fileName = this.getTemplateFileName(template);
15116
15172
  const targetPath = path3.join(targetDirectory, fileName);
15117
15173
  try {
15118
- const fileExists = await fs3.pathExists(targetPath);
15174
+ const fileExists = await fs2.pathExists(targetPath);
15119
15175
  if (fileExists && !options.force && options.onConflict !== "overwrite") {
15120
15176
  return {
15121
15177
  path: targetPath,
@@ -15137,10 +15193,10 @@ This directory contains specification documents for your project.
15137
15193
  }
15138
15194
  if (options.createBackup && fileExists) {
15139
15195
  const backupPath = `${targetPath}.backup.${Date.now()}`;
15140
- await fs3.copy(targetPath, backupPath);
15196
+ await fs2.copy(targetPath, backupPath);
15141
15197
  }
15142
- await fs3.ensureDir(path3.dirname(targetPath));
15143
- await fs3.writeFile(targetPath, renderedContent, "utf8");
15198
+ await fs2.ensureDir(path3.dirname(targetPath));
15199
+ await fs2.writeFile(targetPath, renderedContent, "utf8");
15144
15200
  return {
15145
15201
  path: targetPath,
15146
15202
  content: renderedContent,
@@ -15404,7 +15460,7 @@ var SimpleInitTUI = class {
15404
15460
  }
15405
15461
  async confirmSave(targetDirectory) {
15406
15462
  const junoTaskPath = path3.join(targetDirectory, ".juno_task");
15407
- if (await fs3.pathExists(junoTaskPath)) {
15463
+ if (await fs2.pathExists(junoTaskPath)) {
15408
15464
  console.log(chalk15.yellow(" \u26A0\uFE0F .juno_task directory already exists"));
15409
15465
  console.log(chalk15.gray(" Would you like to:"));
15410
15466
  console.log(chalk15.gray(" 1) Override existing files"));
@@ -15449,16 +15505,16 @@ var SimpleProjectGenerator = class {
15449
15505
  async generate() {
15450
15506
  const { targetDirectory, variables, force } = this.context;
15451
15507
  console.log(chalk15.blue("\u{1F4C1} Creating project directory..."));
15452
- await fs3.ensureDir(targetDirectory);
15508
+ await fs2.ensureDir(targetDirectory);
15453
15509
  const junoTaskDir = path3.join(targetDirectory, ".juno_task");
15454
- const junoTaskExists = await fs3.pathExists(junoTaskDir);
15510
+ const junoTaskExists = await fs2.pathExists(junoTaskDir);
15455
15511
  if (junoTaskExists && !force) {
15456
15512
  throw new ValidationError(
15457
15513
  "Project already initialized. Directory .juno_task already exists.",
15458
15514
  ["Use --force flag to overwrite existing files", "Choose a different directory"]
15459
15515
  );
15460
15516
  }
15461
- await fs3.ensureDir(junoTaskDir);
15517
+ await fs2.ensureDir(junoTaskDir);
15462
15518
  console.log(chalk15.blue("\u2699\uFE0F Creating project configuration..."));
15463
15519
  await this.createConfigFile(junoTaskDir, targetDirectory);
15464
15520
  console.log(chalk15.blue("\u{1F527} Setting up MCP configuration..."));
@@ -15492,21 +15548,21 @@ var SimpleProjectGenerator = class {
15492
15548
  const promptContent = await templateEngine.render(promptTemplate, templateContext);
15493
15549
  const initContent = await templateEngine.render(initTemplate, templateContext);
15494
15550
  const implementContent = await templateEngine.render(implementTemplate, templateContext);
15495
- await fs3.writeFile(path3.join(junoTaskDir, "prompt.md"), promptContent);
15496
- await fs3.writeFile(path3.join(junoTaskDir, "init.md"), initContent);
15497
- await fs3.writeFile(path3.join(junoTaskDir, "implement.md"), implementContent);
15551
+ await fs2.writeFile(path3.join(junoTaskDir, "prompt.md"), promptContent);
15552
+ await fs2.writeFile(path3.join(junoTaskDir, "init.md"), initContent);
15553
+ await fs2.writeFile(path3.join(junoTaskDir, "implement.md"), implementContent);
15498
15554
  const userFeedbackTemplate = templateEngine.getBuiltInTemplate("USER_FEEDBACK.md");
15499
15555
  if (userFeedbackTemplate) {
15500
15556
  const userFeedbackContent = await templateEngine.render(userFeedbackTemplate, templateContext);
15501
- await fs3.writeFile(path3.join(junoTaskDir, "USER_FEEDBACK.md"), userFeedbackContent);
15557
+ await fs2.writeFile(path3.join(junoTaskDir, "USER_FEEDBACK.md"), userFeedbackContent);
15502
15558
  }
15503
15559
  const planTemplate = templateEngine.getBuiltInTemplate("plan.md");
15504
15560
  if (planTemplate) {
15505
15561
  const planContent = await templateEngine.render(planTemplate, templateContext);
15506
- await fs3.writeFile(path3.join(junoTaskDir, "plan.md"), planContent);
15562
+ await fs2.writeFile(path3.join(junoTaskDir, "plan.md"), planContent);
15507
15563
  }
15508
15564
  const specsDir = path3.join(junoTaskDir, "specs");
15509
- await fs3.ensureDir(specsDir);
15565
+ await fs2.ensureDir(specsDir);
15510
15566
  const specsReadmeContent = `# Project Specifications
15511
15567
 
15512
15568
  This directory contains detailed specifications for the project components.
@@ -15523,7 +15579,7 @@ This directory contains detailed specifications for the project components.
15523
15579
  - Avoid conflicts with existing file names
15524
15580
  - Use \`.md\` extension for all specification files
15525
15581
  `;
15526
- await fs3.writeFile(path3.join(specsDir, "README.md"), specsReadmeContent);
15582
+ await fs2.writeFile(path3.join(specsDir, "README.md"), specsReadmeContent);
15527
15583
  const requirementsContent = `# Requirements Specification
15528
15584
 
15529
15585
  ## Functional Requirements
@@ -15570,7 +15626,7 @@ This directory contains detailed specifications for the project components.
15570
15626
  - Code quality: Clean, maintainable codebase
15571
15627
  - Documentation: Complete and accurate documentation
15572
15628
  `;
15573
- await fs3.writeFile(path3.join(specsDir, "requirements.md"), requirementsContent);
15629
+ await fs2.writeFile(path3.join(specsDir, "requirements.md"), requirementsContent);
15574
15630
  const architectureContent = `# Architecture Specification
15575
15631
 
15576
15632
  ## System Overview
@@ -15652,7 +15708,7 @@ This project uses AI-assisted development with juno-code to achieve: ${variables
15652
15708
  - Performance monitoring
15653
15709
  - Security best practices
15654
15710
  `;
15655
- await fs3.writeFile(path3.join(specsDir, "architecture.md"), architectureContent);
15711
+ await fs2.writeFile(path3.join(specsDir, "architecture.md"), architectureContent);
15656
15712
  const claudeContent = `# Claude Development Session Learnings
15657
15713
 
15658
15714
  ## Project Overview
@@ -15724,7 +15780,7 @@ This file will be updated as development progresses to track:
15724
15780
  - Solutions to complex problems
15725
15781
  - Performance improvements and optimizations
15726
15782
  `;
15727
- await fs3.writeFile(path3.join(targetDirectory, "CLAUDE.md"), claudeContent);
15783
+ await fs2.writeFile(path3.join(targetDirectory, "CLAUDE.md"), claudeContent);
15728
15784
  const agentsContent = `# AI Agent Selection and Performance
15729
15785
 
15730
15786
  ## Available Agents
@@ -15788,7 +15844,7 @@ Track agent performance for:
15788
15844
  4. **Feedback Loop**: Provide feedback to improve agent performance
15789
15845
  5. **Performance Monitoring**: Track and optimize agent usage
15790
15846
  `;
15791
- await fs3.writeFile(path3.join(targetDirectory, "AGENTS.md"), agentsContent);
15847
+ await fs2.writeFile(path3.join(targetDirectory, "AGENTS.md"), agentsContent);
15792
15848
  const readmeContent = `# ${variables.PROJECT_NAME}
15793
15849
 
15794
15850
  ${variables.DESCRIPTION}
@@ -15885,7 +15941,7 @@ ${variables.GIT_URL}` : ""}
15885
15941
  Created with juno-code on ${variables.CURRENT_DATE}
15886
15942
  ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
15887
15943
  `;
15888
- await fs3.writeFile(path3.join(targetDirectory, "README.md"), readmeContent);
15944
+ await fs2.writeFile(path3.join(targetDirectory, "README.md"), readmeContent);
15889
15945
  console.log(chalk15.blue("\u{1F4E6} Installing utility scripts..."));
15890
15946
  await this.copyScriptsFromTemplates(junoTaskDir);
15891
15947
  console.log(chalk15.blue("\u{1F40D} Installing Python requirements..."));
@@ -15937,7 +15993,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
15937
15993
  hooks: getDefaultHooks()
15938
15994
  };
15939
15995
  const configPath = path3.join(junoTaskDir, "config.json");
15940
- await fs3.writeFile(configPath, JSON.stringify(configContent, null, 2));
15996
+ await fs2.writeFile(configPath, JSON.stringify(configContent, null, 2));
15941
15997
  console.log(chalk15.green(` \u2713 Created .juno_task/config.json with ${this.context.subagent} as default subagent`));
15942
15998
  }
15943
15999
  async createMcpFile(junoTaskDir, targetDirectory) {
@@ -15991,7 +16047,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
15991
16047
  }
15992
16048
  };
15993
16049
  const mcpPath = path3.join(junoTaskDir, "mcp.json");
15994
- await fs3.writeFile(mcpPath, JSON.stringify(mcpContent, null, 2));
16050
+ await fs2.writeFile(mcpPath, JSON.stringify(mcpContent, null, 2));
15995
16051
  console.log(chalk15.green(` \u2713 Created .juno_task/mcp.json with roundtable-ai server configuration`));
15996
16052
  }
15997
16053
  getDefaultModelForSubagent(subagent) {
@@ -16010,7 +16066,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16010
16066
  async copyScriptsFromTemplates(junoTaskDir) {
16011
16067
  try {
16012
16068
  const scriptsDir = path3.join(junoTaskDir, "scripts");
16013
- await fs3.ensureDir(scriptsDir);
16069
+ await fs2.ensureDir(scriptsDir);
16014
16070
  const __filename2 = fileURLToPath(import.meta.url);
16015
16071
  const __dirname2 = path3.dirname(__filename2);
16016
16072
  let templatesScriptsDir;
@@ -16021,11 +16077,11 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16021
16077
  } else {
16022
16078
  templatesScriptsDir = path3.join(__dirname2, "../../templates/scripts");
16023
16079
  }
16024
- if (!await fs3.pathExists(templatesScriptsDir)) {
16080
+ if (!await fs2.pathExists(templatesScriptsDir)) {
16025
16081
  console.log(chalk15.yellow(" \u26A0\uFE0F Template scripts directory not found, skipping script installation"));
16026
16082
  return;
16027
16083
  }
16028
- const scriptFiles = await fs3.readdir(templatesScriptsDir);
16084
+ const scriptFiles = await fs2.readdir(templatesScriptsDir);
16029
16085
  if (scriptFiles.length === 0) {
16030
16086
  console.log(chalk15.gray(" \u2139\uFE0F No template scripts found to install"));
16031
16087
  return;
@@ -16034,11 +16090,11 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16034
16090
  for (const scriptFile of scriptFiles) {
16035
16091
  const sourcePath = path3.join(templatesScriptsDir, scriptFile);
16036
16092
  const destPath = path3.join(scriptsDir, scriptFile);
16037
- const stats = await fs3.stat(sourcePath);
16093
+ const stats = await fs2.stat(sourcePath);
16038
16094
  if (stats.isFile()) {
16039
- await fs3.copy(sourcePath, destPath);
16095
+ await fs2.copy(sourcePath, destPath);
16040
16096
  if (scriptFile.endsWith(".sh")) {
16041
- await fs3.chmod(destPath, 493);
16097
+ await fs2.chmod(destPath, 493);
16042
16098
  }
16043
16099
  copiedCount++;
16044
16100
  console.log(chalk15.green(` \u2713 Installed script: ${scriptFile}`));
@@ -16061,7 +16117,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16061
16117
  try {
16062
16118
  const scriptsDir = path3.join(junoTaskDir, "scripts");
16063
16119
  const installScript = path3.join(scriptsDir, "install_requirements.sh");
16064
- if (!await fs3.pathExists(installScript)) {
16120
+ if (!await fs2.pathExists(installScript)) {
16065
16121
  console.log(chalk15.yellow(" \u26A0\uFE0F install_requirements.sh not found, skipping Python dependencies installation"));
16066
16122
  console.log(chalk15.gray(" You can install dependencies manually: juno-kanban, roundtable-ai"));
16067
16123
  return;
@@ -16358,20 +16414,20 @@ init_types();
16358
16414
  async function loadInitPrompt(directory) {
16359
16415
  const junoTaskDir = path3.join(directory, ".juno_task");
16360
16416
  const initFile = path3.join(junoTaskDir, "init.md");
16361
- if (!await fs3.pathExists(junoTaskDir)) {
16417
+ if (!await fs2.pathExists(junoTaskDir)) {
16362
16418
  throw new FileSystemError(
16363
16419
  'No .juno_task directory found. Run "juno-code init" first.',
16364
16420
  junoTaskDir
16365
16421
  );
16366
16422
  }
16367
- if (!await fs3.pathExists(initFile)) {
16423
+ if (!await fs2.pathExists(initFile)) {
16368
16424
  throw new FileSystemError(
16369
16425
  "No init.md file found in .juno_task directory",
16370
16426
  initFile
16371
16427
  );
16372
16428
  }
16373
16429
  try {
16374
- const content = await fs3.readFile(initFile, "utf-8");
16430
+ const content = await fs2.readFile(initFile, "utf-8");
16375
16431
  if (!content.trim()) {
16376
16432
  throw new FileSystemError(
16377
16433
  "init.md file is empty. Please add task instructions.",
@@ -16417,6 +16473,8 @@ async function startCommandHandler(args, options, command) {
16417
16473
  allowedTools: options.allowedTools,
16418
16474
  appendAllowedTools: options.appendAllowedTools,
16419
16475
  disallowedTools: options.disallowedTools,
16476
+ resume: options.resume,
16477
+ continue: options.continue,
16420
16478
  directory: options.directory,
16421
16479
  verbose: options.verbose,
16422
16480
  quiet: options.quiet,
@@ -17401,8 +17459,8 @@ Focus on ${request.intelligence === "basic" ? "basic functionality" : request.in
17401
17459
  for (const scenario of scenarios) {
17402
17460
  const testContent = await this.generateTestContent(request, scenario, template);
17403
17461
  const testFilePath = this.resolveTestFilePath(request, scenario);
17404
- await fs3.ensureDir(path3.dirname(testFilePath));
17405
- await fs3.writeFile(testFilePath, testContent);
17462
+ await fs2.ensureDir(path3.dirname(testFilePath));
17463
+ await fs2.writeFile(testFilePath, testContent);
17406
17464
  testFiles.push(testFilePath);
17407
17465
  }
17408
17466
  return testFiles;
@@ -17654,8 +17712,8 @@ var TestExecutionEngine = class {
17654
17712
  async collectCoverage(request) {
17655
17713
  const coverageFile = path3.join(request.workingDirectory, "coverage", "coverage-summary.json");
17656
17714
  try {
17657
- if (await fs3.pathExists(coverageFile)) {
17658
- const coverageData = await fs3.readJson(coverageFile);
17715
+ if (await fs2.pathExists(coverageFile)) {
17716
+ const coverageData = await fs2.readJson(coverageFile);
17659
17717
  return {
17660
17718
  lines: coverageData.total?.lines?.pct || 0,
17661
17719
  functions: coverageData.total?.functions?.pct || 0,
@@ -17838,8 +17896,8 @@ var TestReportEngine = class {
17838
17896
  suggestions: analysis.suggestions,
17839
17897
  recommendations: analysis.recommendations
17840
17898
  };
17841
- await fs3.ensureDir(path3.dirname(outputPath));
17842
- await fs3.writeJson(outputPath, report, { spaces: 2 });
17899
+ await fs2.ensureDir(path3.dirname(outputPath));
17900
+ await fs2.writeJson(outputPath, report, { spaces: 2 });
17843
17901
  return outputPath;
17844
17902
  }
17845
17903
  async generateHTMLReport(analysis, outputPath, includeVisualizations) {
@@ -17902,8 +17960,8 @@ var TestReportEngine = class {
17902
17960
  </body>
17903
17961
  </html>
17904
17962
  `.trim();
17905
- await fs3.ensureDir(path3.dirname(outputPath));
17906
- await fs3.writeFile(outputPath, html);
17963
+ await fs2.ensureDir(path3.dirname(outputPath));
17964
+ await fs2.writeFile(outputPath, html);
17907
17965
  return outputPath;
17908
17966
  }
17909
17967
  generateCharts(analysis) {
@@ -17960,8 +18018,8 @@ ${analysis.suggestions.map((suggestion) => `- ${suggestion}`).join("\n")}
17960
18018
 
17961
18019
  ${analysis.recommendations.map((rec) => `- ${rec}`).join("\n")}
17962
18020
  `.trim();
17963
- await fs3.ensureDir(path3.dirname(outputPath));
17964
- await fs3.writeFile(outputPath, markdown);
18021
+ await fs2.ensureDir(path3.dirname(outputPath));
18022
+ await fs2.writeFile(outputPath, markdown);
17965
18023
  return outputPath;
17966
18024
  }
17967
18025
  async displayConsoleReport(analysis) {
@@ -18301,7 +18359,7 @@ async function compactConfigFile(filePath, options = {}) {
18301
18359
  preserveDays = 30,
18302
18360
  preservePatterns = []
18303
18361
  } = options;
18304
- const originalContent = await fs3.readFile(filePath, "utf-8");
18362
+ const originalContent = await fs2.readFile(filePath, "utf-8");
18305
18363
  const originalSize = originalContent.length;
18306
18364
  let backupPath = "";
18307
18365
  if (createBackup && !dryRun) {
@@ -18310,7 +18368,7 @@ async function compactConfigFile(filePath, options = {}) {
18310
18368
  const basename11 = path3.basename(filePath, ext);
18311
18369
  const dirname12 = path3.dirname(filePath);
18312
18370
  backupPath = path3.join(dirname12, `${basename11}.backup.${timestamp}${ext}`);
18313
- await fs3.writeFile(backupPath, originalContent, "utf-8");
18371
+ await fs2.writeFile(backupPath, originalContent, "utf-8");
18314
18372
  }
18315
18373
  const compactionAnalysis = analyzeMarkdownStructure(originalContent);
18316
18374
  const compactedContent = compactMarkdownContent(
@@ -18325,7 +18383,7 @@ async function compactConfigFile(filePath, options = {}) {
18325
18383
  const compactedSize = finalContent.length;
18326
18384
  const reductionPercentage = Math.round((originalSize - compactedSize) / originalSize * 100);
18327
18385
  if (!dryRun) {
18328
- await fs3.writeFile(filePath, finalContent, "utf-8");
18386
+ await fs2.writeFile(filePath, finalContent, "utf-8");
18329
18387
  }
18330
18388
  return {
18331
18389
  originalSize,
@@ -18455,7 +18513,7 @@ function formatFileSize(bytes) {
18455
18513
  }
18456
18514
  async function shouldCompactFile(filePath, sizeThresholdKB = 50, ageThresholdDays = 30) {
18457
18515
  try {
18458
- const stats = await fs3.stat(filePath);
18516
+ const stats = await fs2.stat(filePath);
18459
18517
  const sizeKB = stats.size / 1024;
18460
18518
  if (sizeKB > sizeThresholdKB) {
18461
18519
  return true;
@@ -18477,19 +18535,19 @@ async function archiveResolvedIssues(options) {
18477
18535
  feedbackFile,
18478
18536
  archiveDir = path3.join(path3.dirname(feedbackFile), "archives"),
18479
18537
  openIssuesThreshold = 10} = options;
18480
- if (!await fs3.pathExists(feedbackFile)) {
18538
+ if (!await fs2.pathExists(feedbackFile)) {
18481
18539
  throw new Error(`Feedback file does not exist: ${feedbackFile}`);
18482
18540
  }
18483
- const content = await fs3.readFile(feedbackFile, "utf-8");
18541
+ const content = await fs2.readFile(feedbackFile, "utf-8");
18484
18542
  const parsed = parseUserFeedback(content);
18485
18543
  const warningsGenerated = [];
18486
18544
  if (parsed.openIssues.length > openIssuesThreshold) {
18487
18545
  const warning = `Found ${parsed.openIssues.length} open issues (threshold: ${openIssuesThreshold}). Consider reviewing and prioritizing.`;
18488
18546
  warningsGenerated.push(warning);
18489
18547
  const logFile = path3.join(path3.dirname(feedbackFile), "logs", "feedback-warnings.log");
18490
- await fs3.ensureDir(path3.dirname(logFile));
18548
+ await fs2.ensureDir(path3.dirname(logFile));
18491
18549
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
18492
- await fs3.appendFile(logFile, `[${timestamp}] ${warning}
18550
+ await fs2.appendFile(logFile, `[${timestamp}] ${warning}
18493
18551
  `);
18494
18552
  }
18495
18553
  if (parsed.resolvedIssues.length === 0) {
@@ -18506,10 +18564,10 @@ async function archiveResolvedIssues(options) {
18506
18564
  const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
18507
18565
  const archiveFile = path3.join(archiveDir, `USER_FEEDBACK_archive_${currentYear}.md`);
18508
18566
  {
18509
- await fs3.ensureDir(archiveDir);
18567
+ await fs2.ensureDir(archiveDir);
18510
18568
  await appendToArchive(archiveFile, parsed.resolvedIssues);
18511
18569
  const compactedContent = generateCompactedFeedback(parsed.openIssues, parsed.metadata);
18512
- await fs3.writeFile(feedbackFile, compactedContent, "utf-8");
18570
+ await fs2.writeFile(feedbackFile, compactedContent, "utf-8");
18513
18571
  }
18514
18572
  {
18515
18573
  console.log(chalk15.green(`\u2705 Archived ${parsed.resolvedIssues.length} resolved issues`));
@@ -18556,8 +18614,8 @@ function parseUserFeedback(content) {
18556
18614
  async function appendToArchive(archiveFile, resolvedIssues) {
18557
18615
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
18558
18616
  let archiveContent = "";
18559
- if (await fs3.pathExists(archiveFile)) {
18560
- archiveContent = await fs3.readFile(archiveFile, "utf-8");
18617
+ if (await fs2.pathExists(archiveFile)) {
18618
+ archiveContent = await fs2.readFile(archiveFile, "utf-8");
18561
18619
  } else {
18562
18620
  const year = path3.basename(archiveFile).match(/(\d{4})/)?.[1] || (/* @__PURE__ */ new Date()).getFullYear();
18563
18621
  archiveContent = `# User Feedback Archive ${year}
@@ -18591,7 +18649,7 @@ ${resolvedIssue}
18591
18649
  `- Last updated: ${timestamp}`
18592
18650
  );
18593
18651
  }
18594
- await fs3.writeFile(archiveFile, archiveContent, "utf-8");
18652
+ await fs2.writeFile(archiveFile, archiveContent, "utf-8");
18595
18653
  }
18596
18654
  function generateCompactedFeedback(openIssues, metadata) {
18597
18655
  let content = metadata.trim() + "\n";
@@ -18616,15 +18674,15 @@ async function shouldArchive(feedbackFile, options = {}) {
18616
18674
  // 50KB
18617
18675
  lineCountThreshold = 500
18618
18676
  } = options;
18619
- if (!await fs3.pathExists(feedbackFile)) {
18677
+ if (!await fs2.pathExists(feedbackFile)) {
18620
18678
  return {
18621
18679
  shouldArchive: false,
18622
18680
  reasons: [],
18623
18681
  stats: { openIssuesCount: 0, resolvedIssuesCount: 0, fileSizeBytes: 0, lineCount: 0 }
18624
18682
  };
18625
18683
  }
18626
- const content = await fs3.readFile(feedbackFile, "utf-8");
18627
- const stats = await fs3.stat(feedbackFile);
18684
+ const content = await fs2.readFile(feedbackFile, "utf-8");
18685
+ const stats = await fs2.stat(feedbackFile);
18628
18686
  const parsed = parseUserFeedback(content);
18629
18687
  const lineCount = content.split("\n").length;
18630
18688
  const reasons = [];
@@ -18698,16 +18756,16 @@ var EnhancedFeedbackFileManager = class {
18698
18756
  this.feedbackFile = feedbackFile;
18699
18757
  }
18700
18758
  async ensureExists() {
18701
- if (!await fs3.pathExists(this.feedbackFile)) {
18759
+ if (!await fs2.pathExists(this.feedbackFile)) {
18702
18760
  await this.createInitialFile();
18703
18761
  }
18704
18762
  }
18705
18763
  async addFeedback(issue, testCriteria) {
18706
18764
  await this.ensureExists();
18707
18765
  try {
18708
- const content = await fs3.readFile(this.feedbackFile, "utf-8");
18766
+ const content = await fs2.readFile(this.feedbackFile, "utf-8");
18709
18767
  const updatedContent = this.addIssueToContent(content, issue, testCriteria);
18710
- await fs3.writeFile(this.feedbackFile, updatedContent, "utf-8");
18768
+ await fs2.writeFile(this.feedbackFile, updatedContent, "utf-8");
18711
18769
  } catch (error) {
18712
18770
  throw new ValidationError(
18713
18771
  `Failed to save feedback: ${error}`,
@@ -18720,12 +18778,12 @@ var EnhancedFeedbackFileManager = class {
18720
18778
  */
18721
18779
  async repairMalformedFile() {
18722
18780
  try {
18723
- const content = await fs3.readFile(this.feedbackFile, "utf-8");
18781
+ const content = await fs2.readFile(this.feedbackFile, "utf-8");
18724
18782
  const hasOpenIssues = content.includes("<OPEN_ISSUES>");
18725
18783
  const hasClosingTag = content.includes("</OPEN_ISSUES>");
18726
18784
  if (!hasOpenIssues || !hasClosingTag) {
18727
18785
  const backupPath = this.feedbackFile + ".backup." + Date.now();
18728
- await fs3.writeFile(backupPath, content, "utf-8");
18786
+ await fs2.writeFile(backupPath, content, "utf-8");
18729
18787
  const existingIssues = this.extractIssuesFromMalformedContent(content);
18730
18788
  await this.createInitialFile(existingIssues);
18731
18789
  }
@@ -18757,8 +18815,8 @@ List any features you'd like to see added or bugs you've encountered.
18757
18815
 
18758
18816
  <!-- Resolved issues will be moved here -->
18759
18817
  `;
18760
- await fs3.ensureDir(path3.dirname(this.feedbackFile));
18761
- await fs3.writeFile(this.feedbackFile, initialContent, "utf-8");
18818
+ await fs2.ensureDir(path3.dirname(this.feedbackFile));
18819
+ await fs2.writeFile(this.feedbackFile, initialContent, "utf-8");
18762
18820
  }
18763
18821
  addIssueToContent(content, issue, testCriteria) {
18764
18822
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -18874,17 +18932,17 @@ async function handleCompactCommand(subArgs, options) {
18874
18932
  if (subArgs.length > 0) {
18875
18933
  for (const filePath of subArgs) {
18876
18934
  const resolvedPath = path3.resolve(filePath);
18877
- if (await fs3.pathExists(resolvedPath)) {
18935
+ if (await fs2.pathExists(resolvedPath)) {
18878
18936
  filesToCompact.push(resolvedPath);
18879
18937
  } else {
18880
18938
  console.warn(chalk15.yellow(`\u26A0\uFE0F File not found: ${filePath}`));
18881
18939
  }
18882
18940
  }
18883
18941
  } else {
18884
- if (await fs3.pathExists(defaultClaudeFile)) {
18942
+ if (await fs2.pathExists(defaultClaudeFile)) {
18885
18943
  filesToCompact.push(defaultClaudeFile);
18886
18944
  }
18887
- if (await fs3.pathExists(defaultAgentsFile)) {
18945
+ if (await fs2.pathExists(defaultAgentsFile)) {
18888
18946
  filesToCompact.push(defaultAgentsFile);
18889
18947
  }
18890
18948
  }
@@ -19818,11 +19876,11 @@ var GitManager = class {
19818
19876
  */
19819
19877
  async updateJunoTaskConfig(gitUrl) {
19820
19878
  const configPath = path3.join(this.workingDirectory, ".juno_task", "init.md");
19821
- if (!await fs3.pathExists(configPath)) {
19879
+ if (!await fs2.pathExists(configPath)) {
19822
19880
  return;
19823
19881
  }
19824
19882
  try {
19825
- let content = await fs3.readFile(configPath, "utf-8");
19883
+ let content = await fs2.readFile(configPath, "utf-8");
19826
19884
  const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
19827
19885
  if (frontmatterMatch) {
19828
19886
  let frontmatter = frontmatterMatch[1];
@@ -19843,7 +19901,7 @@ GIT_URL: ${gitUrl}
19843
19901
  `;
19844
19902
  content = frontmatter + content;
19845
19903
  }
19846
- await fs3.writeFile(configPath, content, "utf-8");
19904
+ await fs2.writeFile(configPath, content, "utf-8");
19847
19905
  } catch (error) {
19848
19906
  console.warn(`Warning: Failed to update juno-code configuration: ${error}`);
19849
19907
  }
@@ -22600,10 +22658,10 @@ autoload -U compinit && compinit`;
22600
22658
  */
22601
22659
  async isSourceCommandPresent(configPath, sourceCommand) {
22602
22660
  try {
22603
- if (!await fs3.pathExists(configPath)) {
22661
+ if (!await fs2.pathExists(configPath)) {
22604
22662
  return false;
22605
22663
  }
22606
- const content = await fs3.readFile(configPath, "utf-8");
22664
+ const content = await fs2.readFile(configPath, "utf-8");
22607
22665
  return content.includes("juno-code completion");
22608
22666
  } catch {
22609
22667
  return false;
@@ -22625,15 +22683,15 @@ autoload -U compinit && compinit`;
22625
22683
  continue;
22626
22684
  }
22627
22685
  try {
22628
- const completionExists = await fs3.pathExists(shell.completionPath);
22629
- const configExists = await fs3.pathExists(shell.configPath);
22686
+ const completionExists = await fs2.pathExists(shell.completionPath);
22687
+ const configExists = await fs2.pathExists(shell.configPath);
22630
22688
  const isSourced = configExists && await this.isSourceCommandPresent(
22631
22689
  shell.configPath,
22632
22690
  this.getSourceCommand(shell.name, shell.completionPath)
22633
22691
  );
22634
22692
  let lastInstalled;
22635
22693
  if (completionExists) {
22636
- const stats = await fs3.stat(shell.completionPath);
22694
+ const stats = await fs2.stat(shell.completionPath);
22637
22695
  lastInstalled = stats.mtime;
22638
22696
  }
22639
22697
  statuses.push({
@@ -22659,7 +22717,7 @@ autoload -U compinit && compinit`;
22659
22717
  async ensureCompletionDirectory(shell) {
22660
22718
  const completionPath = this.getCompletionPath(shell);
22661
22719
  const completionDir = path3.dirname(completionPath);
22662
- await fs3.ensureDir(completionDir);
22720
+ await fs2.ensureDir(completionDir);
22663
22721
  }
22664
22722
  /**
22665
22723
  * Ensure directory exists for shell configuration
@@ -22667,7 +22725,7 @@ autoload -U compinit && compinit`;
22667
22725
  async ensureConfigDirectory(shell) {
22668
22726
  const configPath = this.getConfigPath(shell);
22669
22727
  const configDir = path3.dirname(configPath);
22670
- await fs3.ensureDir(configDir);
22728
+ await fs2.ensureDir(configDir);
22671
22729
  }
22672
22730
  /**
22673
22731
  * Get shell version information
@@ -22691,15 +22749,15 @@ autoload -U compinit && compinit`;
22691
22749
  try {
22692
22750
  const configPath = this.getConfigPath(shell);
22693
22751
  const configDir = path3.dirname(configPath);
22694
- await fs3.access(configDir, fs3.constants.W_OK);
22752
+ await fs2.access(configDir, fs2.constants.W_OK);
22695
22753
  } catch {
22696
22754
  issues.push(`Cannot write to ${shell} configuration directory`);
22697
22755
  }
22698
22756
  try {
22699
22757
  const completionPath = this.getCompletionPath(shell);
22700
22758
  const completionDir = path3.dirname(completionPath);
22701
- await fs3.ensureDir(completionDir);
22702
- await fs3.access(completionDir, fs3.constants.W_OK);
22759
+ await fs2.ensureDir(completionDir);
22760
+ await fs2.access(completionDir, fs2.constants.W_OK);
22703
22761
  } catch {
22704
22762
  issues.push(`Cannot write to ${shell} completion directory`);
22705
22763
  }
@@ -22770,10 +22828,10 @@ var ContextAwareCompletion = class {
22770
22828
  async getSessionIds() {
22771
22829
  try {
22772
22830
  const sessionDir = path3.join(process.cwd(), ".juno_task", "sessions");
22773
- if (!await fs3.pathExists(sessionDir)) {
22831
+ if (!await fs2.pathExists(sessionDir)) {
22774
22832
  return [];
22775
22833
  }
22776
- const sessions = await fs3.readdir(sessionDir);
22834
+ const sessions = await fs2.readdir(sessionDir);
22777
22835
  return sessions.filter((name) => name.match(/^session_\d+$/)).map((name) => name.replace("session_", "")).sort((a, b) => parseInt(b) - parseInt(a));
22778
22836
  } catch {
22779
22837
  return [];
@@ -22787,8 +22845,8 @@ var ContextAwareCompletion = class {
22787
22845
  const builtinTemplates = ["basic", "advanced", "research", "development"];
22788
22846
  const customTemplatesDir = path3.join(process.cwd(), ".juno_task", "templates");
22789
22847
  let customTemplates = [];
22790
- if (await fs3.pathExists(customTemplatesDir)) {
22791
- const files = await fs3.readdir(customTemplatesDir);
22848
+ if (await fs2.pathExists(customTemplatesDir)) {
22849
+ const files = await fs2.readdir(customTemplatesDir);
22792
22850
  customTemplates = files.filter((name) => name.endsWith(".md") || name.endsWith(".hbs")).map((name) => path3.basename(name, path3.extname(name)));
22793
22851
  }
22794
22852
  return [...builtinTemplates, ...customTemplates].sort();
@@ -22865,7 +22923,7 @@ var CompletionInstaller = class {
22865
22923
  await this.shellDetector.ensureConfigDirectory(shell);
22866
22924
  const script = this.generateEnhancedCompletion(shell, "juno-code");
22867
22925
  const completionPath = this.shellDetector.getCompletionPath(shell);
22868
- await fs3.writeFile(completionPath, script, "utf-8");
22926
+ await fs2.writeFile(completionPath, script, "utf-8");
22869
22927
  const configPath = this.shellDetector.getConfigPath(shell);
22870
22928
  const sourceCommand = this.shellDetector.getSourceCommand(shell, completionPath);
22871
22929
  const warnings = [];
@@ -22873,7 +22931,7 @@ var CompletionInstaller = class {
22873
22931
  const isPresent = await this.shellDetector.isSourceCommandPresent(configPath, sourceCommand);
22874
22932
  if (!isPresent) {
22875
22933
  try {
22876
- await fs3.appendFile(configPath, `
22934
+ await fs2.appendFile(configPath, `
22877
22935
 
22878
22936
  ${sourceCommand}
22879
22937
  `);
@@ -22904,8 +22962,8 @@ ${sourceCommand}
22904
22962
  async uninstall(shell) {
22905
22963
  try {
22906
22964
  const completionPath = this.shellDetector.getCompletionPath(shell);
22907
- if (await fs3.pathExists(completionPath)) {
22908
- await fs3.remove(completionPath);
22965
+ if (await fs2.pathExists(completionPath)) {
22966
+ await fs2.remove(completionPath);
22909
22967
  return true;
22910
22968
  }
22911
22969
  return false;
@@ -22919,7 +22977,7 @@ ${sourceCommand}
22919
22977
  async isInstalled(shell) {
22920
22978
  try {
22921
22979
  const completionPath = this.shellDetector.getCompletionPath(shell);
22922
- return await fs3.pathExists(completionPath);
22980
+ return await fs2.pathExists(completionPath);
22923
22981
  } catch {
22924
22982
  return false;
22925
22983
  }
@@ -23694,7 +23752,7 @@ function handleCLIError(error, verbose = false) {
23694
23752
  process.exit(EXIT_CODES.UNEXPECTED_ERROR);
23695
23753
  }
23696
23754
  function setupGlobalOptions(program) {
23697
- program.option("-v, --verbose", "Enable verbose output with detailed progress").option("-q, --quiet", "Disable rich formatting, use plain text").option("-c, --config <path>", "Configuration file path (.json, .toml, pyproject.toml)").option("-l, --log-file <path>", "Log file path (auto-generated if not specified)").option("--no-color", "Disable colored output").option("--log-level <level>", "Log level for output (error, warn, info, debug, trace)", "info").option("-s, --subagent <name>", "Subagent to use (claude, cursor, codex, gemini)").option("-b, --backend <type>", "Backend to use (mcp, shell)").option("-m, --model <name>", "Model to use (subagent-specific)").option("--agents <config>", "Agents configuration (forwarded to shell backend, ignored for MCP)").option("--tools <tools...>", 'Specify the list of available tools from the built-in set (only works with --print mode). Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read"). Passed to shell backend, ignored for MCP.').option("--allowed-tools <tools...>", 'Permission-based filtering of specific tool instances (e.g. "Bash(git:*) Edit"). Default when not specified: Task, Bash, Glob, Grep, ExitPlanMode, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, Skill, SlashCommand, EnterPlanMode. Passed to shell backend, ignored for MCP.').option("--disallowed-tools <tools...>", "Disallowed tools for Claude (passed to shell backend, ignored for MCP). By default, no tools are disallowed").option("--append-allowed-tools <tools...>", "Append tools to the default allowed-tools list (mutually exclusive with --allowed-tools). Passed to shell backend, ignored for MCP.").option("--mcp-timeout <number>", "MCP server timeout in milliseconds", parseInt).option("--enable-feedback", "Enable interactive feedback mode (F+Enter to enter, Q+Enter to submit)");
23755
+ program.option("-v, --verbose", "Enable verbose output with detailed progress").option("-q, --quiet", "Disable rich formatting, use plain text").option("-c, --config <path>", "Configuration file path (.json, .toml, pyproject.toml)").option("-l, --log-file <path>", "Log file path (auto-generated if not specified)").option("--no-color", "Disable colored output").option("--log-level <level>", "Log level for output (error, warn, info, debug, trace)", "info").option("-s, --subagent <name>", "Subagent to use (claude, cursor, codex, gemini)").option("-b, --backend <type>", "Backend to use (mcp, shell)").option("-m, --model <name>", "Model to use (subagent-specific)").option("--agents <config>", "Agents configuration (forwarded to shell backend, ignored for MCP)").option("--tools <tools...>", 'Specify the list of available tools from the built-in set (only works with --print mode). Use "" to disable all tools, "default" to use all tools, or specify tool names (e.g. "Bash,Edit,Read"). Passed to shell backend, ignored for MCP.').option("--allowed-tools <tools...>", 'Permission-based filtering of specific tool instances (e.g. "Bash(git:*) Edit"). Default when not specified: Task, Bash, Glob, Grep, ExitPlanMode, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, Skill, SlashCommand, EnterPlanMode. Passed to shell backend, ignored for MCP.').option("--disallowed-tools <tools...>", "Disallowed tools for Claude (passed to shell backend, ignored for MCP). By default, no tools are disallowed").option("--append-allowed-tools <tools...>", "Append tools to the default allowed-tools list (mutually exclusive with --allowed-tools). Passed to shell backend, ignored for MCP.").option("--mcp-timeout <number>", "MCP server timeout in milliseconds", parseInt).option("--enable-feedback", "Enable interactive feedback mode (F+Enter to enter, Q+Enter to submit)").option("-r, --resume <sessionId>", "Resume a conversation by session ID (shell backend only)").option("--continue", "Continue the most recent conversation (shell backend only)");
23698
23756
  program.exitOverride((err) => {
23699
23757
  if (err.code === "commander.helpDisplayed") {
23700
23758
  process.exit(0);