juno-code 1.0.32 → 1.0.34

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.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var fs3 = require('fs-extra');
4
+ var fs2 = require('fs-extra');
5
5
  var path3 = require('path');
6
- var os3 = require('os');
6
+ var os4 = require('os');
7
7
  var url = require('url');
8
8
  var module$1 = require('module');
9
9
  var semver = require('semver');
@@ -52,9 +52,9 @@ function _interopNamespace(e) {
52
52
  return Object.freeze(n);
53
53
  }
54
54
 
55
- var fs3__default = /*#__PURE__*/_interopDefault(fs3);
55
+ var fs2__default = /*#__PURE__*/_interopDefault(fs2);
56
56
  var path3__namespace = /*#__PURE__*/_interopNamespace(path3);
57
- var os3__namespace = /*#__PURE__*/_interopNamespace(os3);
57
+ var os4__namespace = /*#__PURE__*/_interopNamespace(os4);
58
58
  var semver__default = /*#__PURE__*/_interopDefault(semver);
59
59
  var nodeFs__namespace = /*#__PURE__*/_interopNamespace(nodeFs);
60
60
  var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
@@ -341,8 +341,8 @@ var init_service_installer = __esm({
341
341
  "src/utils/service-installer.ts"() {
342
342
  init_version();
343
343
  ServiceInstaller = class {
344
- static SERVICES_DIR = path3__namespace.join(os3.homedir(), ".juno_code", "services");
345
- static VERSION_FILE = path3__namespace.join(os3.homedir(), ".juno_code", "services", ".version");
344
+ static SERVICES_DIR = path3__namespace.join(os4.homedir(), ".juno_code", "services");
345
+ static VERSION_FILE = path3__namespace.join(os4.homedir(), ".juno_code", "services", ".version");
346
346
  /**
347
347
  * Get the current package version
348
348
  */
@@ -351,12 +351,12 @@ var init_service_installer = __esm({
351
351
  const __dirname2 = path3__namespace.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href))));
352
352
  const require3 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
353
353
  let packageJsonPath = path3__namespace.join(__dirname2, "..", "..", "package.json");
354
- if (fs3__default.default.existsSync(packageJsonPath)) {
354
+ if (fs2__default.default.existsSync(packageJsonPath)) {
355
355
  const packageJson2 = require3(packageJsonPath);
356
356
  return packageJson2.version;
357
357
  }
358
358
  packageJsonPath = path3__namespace.join(__dirname2, "..", "..", "..", "package.json");
359
- if (fs3__default.default.existsSync(packageJsonPath)) {
359
+ if (fs2__default.default.existsSync(packageJsonPath)) {
360
360
  const packageJson2 = require3(packageJsonPath);
361
361
  return packageJson2.version;
362
362
  }
@@ -370,11 +370,11 @@ var init_service_installer = __esm({
370
370
  */
371
371
  static async getInstalledVersion() {
372
372
  try {
373
- const exists = await fs3__default.default.pathExists(this.VERSION_FILE);
373
+ const exists = await fs2__default.default.pathExists(this.VERSION_FILE);
374
374
  if (!exists) {
375
375
  return null;
376
376
  }
377
- const version3 = await fs3__default.default.readFile(this.VERSION_FILE, "utf-8");
377
+ const version3 = await fs2__default.default.readFile(this.VERSION_FILE, "utf-8");
378
378
  return version3.trim();
379
379
  } catch {
380
380
  return null;
@@ -385,7 +385,7 @@ var init_service_installer = __esm({
385
385
  */
386
386
  static async saveVersion() {
387
387
  const version3 = this.getPackageVersion();
388
- await fs3__default.default.writeFile(this.VERSION_FILE, version3, "utf-8");
388
+ await fs2__default.default.writeFile(this.VERSION_FILE, version3, "utf-8");
389
389
  }
390
390
  /**
391
391
  * Check if services need to be updated based on version
@@ -397,7 +397,7 @@ var init_service_installer = __esm({
397
397
  if (!installedVersion) {
398
398
  return true;
399
399
  }
400
- const exists = await fs3__default.default.pathExists(this.SERVICES_DIR);
400
+ const exists = await fs2__default.default.pathExists(this.SERVICES_DIR);
401
401
  if (!exists) {
402
402
  return true;
403
403
  }
@@ -405,8 +405,10 @@ var init_service_installer = __esm({
405
405
  return true;
406
406
  }
407
407
  if (semver__default.default.eq(packageVersion, installedVersion)) {
408
- const codexExists = await fs3__default.default.pathExists(path3__namespace.join(this.SERVICES_DIR, "codex.py"));
409
- const claudeExists = await fs3__default.default.pathExists(path3__namespace.join(this.SERVICES_DIR, "claude.py"));
408
+ const installedCodex = path3__namespace.join(this.SERVICES_DIR, "codex.py");
409
+ const installedClaude = path3__namespace.join(this.SERVICES_DIR, "claude.py");
410
+ const codexExists = await fs2__default.default.pathExists(installedCodex);
411
+ const claudeExists = await fs2__default.default.pathExists(installedClaude);
410
412
  if (!codexExists || !claudeExists) {
411
413
  return true;
412
414
  }
@@ -414,15 +416,32 @@ var init_service_installer = __esm({
414
416
  const packageServicesDir = this.getPackageServicesDir();
415
417
  const packageCodex = path3__namespace.join(packageServicesDir, "codex.py");
416
418
  const packageClaude = path3__namespace.join(packageServicesDir, "claude.py");
417
- const packageCodexExists = await fs3__default.default.pathExists(packageCodex);
418
- const packageClaudeExists = await fs3__default.default.pathExists(packageClaude);
419
- if (packageCodexExists || packageClaudeExists) {
420
- const isDevelopment2 = packageServicesDir.includes("/src/");
421
- if (isDevelopment2) {
419
+ const packageCodexExists = await fs2__default.default.pathExists(packageCodex);
420
+ const packageClaudeExists = await fs2__default.default.pathExists(packageClaude);
421
+ if (packageCodexExists) {
422
+ const [pkg, inst] = await Promise.all([
423
+ fs2__default.default.readFile(packageCodex, "utf-8"),
424
+ fs2__default.default.readFile(installedCodex, "utf-8")
425
+ ]);
426
+ if (pkg !== inst) {
422
427
  return true;
423
428
  }
424
429
  }
430
+ if (packageClaudeExists) {
431
+ const [pkg, inst] = await Promise.all([
432
+ fs2__default.default.readFile(packageClaude, "utf-8"),
433
+ fs2__default.default.readFile(installedClaude, "utf-8")
434
+ ]);
435
+ if (pkg !== inst) {
436
+ return true;
437
+ }
438
+ }
439
+ const isDevelopment2 = packageServicesDir.includes("/src/");
440
+ if (isDevelopment2) {
441
+ return true;
442
+ }
425
443
  } catch {
444
+ return true;
426
445
  }
427
446
  }
428
447
  return false;
@@ -436,11 +455,11 @@ var init_service_installer = __esm({
436
455
  static getPackageServicesDir() {
437
456
  const __dirname2 = path3__namespace.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href))));
438
457
  let servicesPath = path3__namespace.join(__dirname2, "..", "..", "templates", "services");
439
- if (fs3__default.default.existsSync(servicesPath)) {
458
+ if (fs2__default.default.existsSync(servicesPath)) {
440
459
  return servicesPath;
441
460
  }
442
461
  servicesPath = path3__namespace.join(__dirname2, "..", "templates", "services");
443
- if (fs3__default.default.existsSync(servicesPath)) {
462
+ if (fs2__default.default.existsSync(servicesPath)) {
444
463
  return servicesPath;
445
464
  }
446
465
  throw new Error("Could not find services directory in package");
@@ -451,18 +470,18 @@ var init_service_installer = __esm({
451
470
  */
452
471
  static async install(silent = false) {
453
472
  try {
454
- await fs3__default.default.ensureDir(this.SERVICES_DIR);
473
+ await fs2__default.default.ensureDir(this.SERVICES_DIR);
455
474
  const packageServicesDir = this.getPackageServicesDir();
456
- await fs3__default.default.copy(packageServicesDir, this.SERVICES_DIR, {
475
+ await fs2__default.default.copy(packageServicesDir, this.SERVICES_DIR, {
457
476
  overwrite: true,
458
477
  preserveTimestamps: true
459
478
  });
460
- const files = await fs3__default.default.readdir(this.SERVICES_DIR);
479
+ const files = await fs2__default.default.readdir(this.SERVICES_DIR);
461
480
  for (const file of files) {
462
481
  const filePath = path3__namespace.join(this.SERVICES_DIR, file);
463
- const stat = await fs3__default.default.stat(filePath);
482
+ const stat = await fs2__default.default.stat(filePath);
464
483
  if (stat.isFile() && (file.endsWith(".py") || file.endsWith(".sh"))) {
465
- await fs3__default.default.chmod(filePath, 493);
484
+ await fs2__default.default.chmod(filePath, 493);
466
485
  }
467
486
  }
468
487
  await this.saveVersion();
@@ -509,11 +528,11 @@ var init_service_installer = __esm({
509
528
  */
510
529
  static async isInstalled() {
511
530
  try {
512
- const exists = await fs3__default.default.pathExists(this.SERVICES_DIR);
531
+ const exists = await fs2__default.default.pathExists(this.SERVICES_DIR);
513
532
  if (!exists) {
514
533
  return false;
515
534
  }
516
- const files = await fs3__default.default.readdir(this.SERVICES_DIR);
535
+ const files = await fs2__default.default.readdir(this.SERVICES_DIR);
517
536
  return files.length > 0;
518
537
  } catch {
519
538
  return false;
@@ -536,11 +555,11 @@ var init_service_installer = __esm({
536
555
  */
537
556
  static async listServices() {
538
557
  try {
539
- const exists = await fs3__default.default.pathExists(this.SERVICES_DIR);
558
+ const exists = await fs2__default.default.pathExists(this.SERVICES_DIR);
540
559
  if (!exists) {
541
560
  return [];
542
561
  }
543
- const files = await fs3__default.default.readdir(this.SERVICES_DIR);
562
+ const files = await fs2__default.default.readdir(this.SERVICES_DIR);
544
563
  return files.filter((file) => file.endsWith(".py") || file.endsWith(".sh"));
545
564
  } catch {
546
565
  return [];
@@ -551,9 +570,9 @@ var init_service_installer = __esm({
551
570
  */
552
571
  static async uninstall() {
553
572
  try {
554
- const exists = await fs3__default.default.pathExists(this.SERVICES_DIR);
573
+ const exists = await fs2__default.default.pathExists(this.SERVICES_DIR);
555
574
  if (exists) {
556
- await fs3__default.default.remove(this.SERVICES_DIR);
575
+ await fs2__default.default.remove(this.SERVICES_DIR);
557
576
  console.log("\u2713 Services uninstalled");
558
577
  }
559
578
  } catch (error) {
@@ -1129,17 +1148,17 @@ async function ensureHooksConfig(baseDir) {
1129
1148
  try {
1130
1149
  const configDir = path3__namespace.join(baseDir, ".juno_task");
1131
1150
  const configPath = path3__namespace.join(configDir, "config.json");
1132
- await fs3__default.default.ensureDir(configDir);
1133
- const configExists = await fs3__default.default.pathExists(configPath);
1151
+ await fs2__default.default.ensureDir(configDir);
1152
+ const configExists = await fs2__default.default.pathExists(configPath);
1134
1153
  const allHookTypes = getDefaultHooks();
1135
1154
  if (!configExists) {
1136
1155
  const defaultConfig = {
1137
1156
  ...DEFAULT_CONFIG,
1138
1157
  hooks: allHookTypes
1139
1158
  };
1140
- await fs3__default.default.writeJson(configPath, defaultConfig, { spaces: 2 });
1159
+ await fs2__default.default.writeJson(configPath, defaultConfig, { spaces: 2 });
1141
1160
  } else {
1142
- const existingConfig = await fs3__default.default.readJson(configPath);
1161
+ const existingConfig = await fs2__default.default.readJson(configPath);
1143
1162
  let needsUpdate = false;
1144
1163
  if (!existingConfig.hooks) {
1145
1164
  existingConfig.hooks = allHookTypes;
@@ -1157,7 +1176,7 @@ async function ensureHooksConfig(baseDir) {
1157
1176
  needsUpdate = true;
1158
1177
  }
1159
1178
  if (needsUpdate) {
1160
- await fs3__default.default.writeJson(configPath, existingConfig, { spaces: 2 });
1179
+ await fs2__default.default.writeJson(configPath, existingConfig, { spaces: 2 });
1161
1180
  }
1162
1181
  }
1163
1182
  } catch (error) {
@@ -3312,13 +3331,9 @@ var init_advanced_logger = __esm({
3312
3331
  /**
3313
3332
  * Output formatted log
3314
3333
  */
3315
- output(formatted, level) {
3334
+ output(formatted, _level) {
3316
3335
  if (this.options.output === "console" || this.options.output === "both") {
3317
- if (level >= 3 /* WARN */) {
3318
- console.error(formatted);
3319
- } else {
3320
- console.log(formatted);
3321
- }
3336
+ console.error(formatted);
3322
3337
  }
3323
3338
  if (this.options.output === "file" || this.options.output === "both") {
3324
3339
  this.writeToFile(formatted);
@@ -4875,7 +4890,7 @@ var init_config2 = __esm({
4875
4890
  return cached;
4876
4891
  }
4877
4892
  try {
4878
- const configContent = await fs3__default.default.readFile(configPath, "utf-8");
4893
+ const configContent = await fs2__default.default.readFile(configPath, "utf-8");
4879
4894
  const config = JSON.parse(configContent);
4880
4895
  this.validateConfig(config);
4881
4896
  const resolvedConfig = this.resolveConfigPaths(config, path3__namespace.dirname(configPath));
@@ -4897,7 +4912,7 @@ var init_config2 = __esm({
4897
4912
  const rootDir = path3__namespace.parse(currentDir).root;
4898
4913
  while (currentDir !== rootDir) {
4899
4914
  const configPath = path3__namespace.join(currentDir, ".juno_task", "mcp.json");
4900
- if (await fs3__default.default.pathExists(configPath)) {
4915
+ if (await fs2__default.default.pathExists(configPath)) {
4901
4916
  return configPath;
4902
4917
  }
4903
4918
  currentDir = path3__namespace.dirname(currentDir);
@@ -5083,7 +5098,7 @@ var init_logger = __esm({
5083
5098
  * Matches Python's generate_log_file function
5084
5099
  */
5085
5100
  async initialize(subagent = "mcp") {
5086
- await fs3__default.default.ensureDir(this.logDirectory);
5101
+ await fs2__default.default.ensureDir(this.logDirectory);
5087
5102
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").split("T");
5088
5103
  const dateStr = timestamp[0];
5089
5104
  const timeStr = timestamp[1].split("-")[0].substring(0, 6);
@@ -5092,7 +5107,7 @@ var init_logger = __esm({
5092
5107
  this.logFilePath = path3__namespace.default.join(this.logDirectory, logFileName);
5093
5108
  const header = `# Juno-Task TypeScript Log - Started ${(/* @__PURE__ */ new Date()).toISOString()}
5094
5109
  `;
5095
- await fs3__default.default.writeFile(this.logFilePath, header);
5110
+ await fs2__default.default.writeFile(this.logFilePath, header);
5096
5111
  }
5097
5112
  /**
5098
5113
  * Format log message matching Python version format
@@ -5110,7 +5125,7 @@ var init_logger = __esm({
5110
5125
  if (!this.logFilePath) {
5111
5126
  throw new Error("Logger not initialized. Call initialize() first.");
5112
5127
  }
5113
- await fs3__default.default.appendFile(this.logFilePath, message);
5128
+ await fs2__default.default.appendFile(this.logFilePath, message);
5114
5129
  }
5115
5130
  /**
5116
5131
  * Log message at specified level
@@ -5396,8 +5411,8 @@ var init_terminal_progress_writer = __esm({
5396
5411
  this.options.stream.write("\r\x1B[K");
5397
5412
  if (typeof content === "string") {
5398
5413
  this.options.stream.write(content);
5399
- if (!content.endsWith("\n") && !content.endsWith(os3.EOL)) {
5400
- this.options.stream.write(os3.EOL);
5414
+ if (!content.endsWith("\n") && !content.endsWith(os4.EOL)) {
5415
+ this.options.stream.write(os4.EOL);
5401
5416
  }
5402
5417
  } else {
5403
5418
  console.error(content);
@@ -5405,8 +5420,8 @@ var init_terminal_progress_writer = __esm({
5405
5420
  } else {
5406
5421
  if (typeof content === "string") {
5407
5422
  this.options.stream.write(content);
5408
- if (!content.endsWith("\n") && !content.endsWith(os3.EOL)) {
5409
- this.options.stream.write(os3.EOL);
5423
+ if (!content.endsWith("\n") && !content.endsWith(os4.EOL)) {
5424
+ this.options.stream.write(os4.EOL);
5410
5425
  }
5411
5426
  } else {
5412
5427
  console.error(content);
@@ -6014,7 +6029,7 @@ var init_client = __esm({
6014
6029
  `${serverName}`,
6015
6030
  // Assume it's in PATH
6016
6031
  `/usr/local/bin/${serverName}`,
6017
- path3__namespace.default.resolve(os3__namespace.default.homedir(), `.local/bin/${serverName}`),
6032
+ path3__namespace.default.resolve(os4__namespace.default.homedir(), `.local/bin/${serverName}`),
6018
6033
  path3__namespace.default.resolve(this.options.workingDirectory || process.cwd(), `${serverName}`)
6019
6034
  ];
6020
6035
  for (const serverPath of possiblePaths) {
@@ -7023,7 +7038,7 @@ var init_shell_backend = __esm({
7023
7038
  });
7024
7039
  try {
7025
7040
  const scriptPath = await this.findScriptForSubagent(subagentType);
7026
- const result = await this.executeScript(scriptPath, request, toolId);
7041
+ const result = await this.executeScript(scriptPath, request, toolId, subagentType);
7027
7042
  const duration = Date.now() - startTime;
7028
7043
  await this.emitProgressEvent({
7029
7044
  sessionId: request.metadata?.sessionId || "unknown",
@@ -7040,8 +7055,9 @@ var init_shell_backend = __esm({
7040
7055
  phase: "completion"
7041
7056
  }
7042
7057
  });
7058
+ const structuredResult = this.buildStructuredOutput(subagentType, result);
7043
7059
  return {
7044
- content: result.output,
7060
+ content: structuredResult.content,
7045
7061
  status: result.success ? "completed" : "failed",
7046
7062
  startTime: new Date(startTime),
7047
7063
  endTime: /* @__PURE__ */ new Date(),
@@ -7049,6 +7065,7 @@ var init_shell_backend = __esm({
7049
7065
  error: result.error ? { type: "shell_execution", message: result.error, timestamp: /* @__PURE__ */ new Date() } : void 0,
7050
7066
  progressEvents: [],
7051
7067
  // Progress events are handled via callbacks
7068
+ ...structuredResult.metadata ? { metadata: structuredResult.metadata } : void 0,
7052
7069
  request
7053
7070
  };
7054
7071
  } catch (error) {
@@ -7119,7 +7136,7 @@ var init_shell_backend = __esm({
7119
7136
  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");
7120
7137
  const logDir = path3__namespace.join(this.config.workingDirectory, ".juno_task", "logs");
7121
7138
  try {
7122
- await fs3__default.default.ensureDir(logDir);
7139
+ await fs2__default.default.ensureDir(logDir);
7123
7140
  } catch (error) {
7124
7141
  if (this.config?.debug) {
7125
7142
  engineLogger.warn(`Failed to create log directory: ${error instanceof Error ? error.message : String(error)}`);
@@ -7144,7 +7161,7 @@ var init_shell_backend = __esm({
7144
7161
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
7145
7162
  const logEntry = `[${timestamp}] ${message}
7146
7163
  `;
7147
- await fs3__default.default.appendFile(this.logFilePath, logEntry, "utf-8");
7164
+ await fs2__default.default.appendFile(this.logFilePath, logEntry, "utf-8");
7148
7165
  } catch (error) {
7149
7166
  if (this.config?.debug) {
7150
7167
  engineLogger.warn(`Failed to write to log file: ${error instanceof Error ? error.message : String(error)}`);
@@ -7214,8 +7231,8 @@ var init_shell_backend = __esm({
7214
7231
  /**
7215
7232
  * Execute a shell script
7216
7233
  */
7217
- async executeScript(scriptPath, request, toolId) {
7218
- return new Promise((resolve9, reject) => {
7234
+ async executeScript(scriptPath, request, toolId, subagentType) {
7235
+ return new Promise(async (resolve9, reject) => {
7219
7236
  const startTime = Date.now();
7220
7237
  const isPython = scriptPath.endsWith(".py");
7221
7238
  const env2 = {
@@ -7228,6 +7245,19 @@ var init_shell_backend = __esm({
7228
7245
  JUNO_ITERATION: String(request.arguments?.iteration || 1),
7229
7246
  JUNO_TOOL_ID: toolId
7230
7247
  };
7248
+ let captureDir = null;
7249
+ let capturePath = null;
7250
+ if (subagentType === "claude") {
7251
+ try {
7252
+ captureDir = await nodeFs.promises.mkdtemp(path3__namespace.join(os4__namespace.default.tmpdir(), "juno-shell-"));
7253
+ capturePath = path3__namespace.join(captureDir, `subagent_${toolId}.json`);
7254
+ env2.JUNO_SUBAGENT_CAPTURE_PATH = capturePath;
7255
+ } catch (error) {
7256
+ if (this.config?.debug) {
7257
+ engineLogger.warn(`Failed to prepare subagent capture path: ${error instanceof Error ? error.message : String(error)}`);
7258
+ }
7259
+ }
7260
+ }
7231
7261
  const command = isPython ? "python3" : "bash";
7232
7262
  const args = [scriptPath];
7233
7263
  if (isPython && request.arguments?.instruction) {
@@ -7302,20 +7332,46 @@ var init_shell_backend = __esm({
7302
7332
  }
7303
7333
  });
7304
7334
  child.on("close", (exitCode) => {
7305
- if (isProcessKilled) return;
7306
- const duration = Date.now() - startTime;
7307
- const success = exitCode === 0;
7308
- if (this.config.debug) {
7309
- engineLogger.debug(`Script execution completed with exit code: ${exitCode}, duration: ${duration}ms`);
7310
- engineLogger.debug(`Stdout length: ${stdout2.length}, Stderr length: ${stderr.length}`);
7311
- }
7312
- resolve9({
7313
- success,
7314
- output: stdout2,
7315
- error: stderr || void 0,
7316
- exitCode: exitCode || 0,
7317
- duration
7318
- });
7335
+ void (async () => {
7336
+ if (isProcessKilled) return;
7337
+ const duration = Date.now() - startTime;
7338
+ const success = exitCode === 0;
7339
+ let subAgentResponse;
7340
+ if (capturePath) {
7341
+ try {
7342
+ const captured = await nodeFs.promises.readFile(capturePath, "utf-8");
7343
+ if (captured.trim()) {
7344
+ subAgentResponse = JSON.parse(captured);
7345
+ }
7346
+ } catch (error) {
7347
+ if (this.config?.debug) {
7348
+ engineLogger.warn(`Failed to read subagent capture: ${error instanceof Error ? error.message : String(error)}`);
7349
+ }
7350
+ } finally {
7351
+ if (captureDir) {
7352
+ try {
7353
+ await nodeFs.promises.rm(captureDir, { recursive: true, force: true });
7354
+ } catch (cleanupError) {
7355
+ if (this.config?.debug) {
7356
+ engineLogger.warn(`Failed to clean capture directory: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`);
7357
+ }
7358
+ }
7359
+ }
7360
+ }
7361
+ }
7362
+ if (this.config.debug) {
7363
+ engineLogger.debug(`Script execution completed with exit code: ${exitCode}, duration: ${duration}ms`);
7364
+ engineLogger.debug(`Stdout length: ${stdout2.length}, Stderr length: ${stderr.length}`);
7365
+ }
7366
+ resolve9({
7367
+ success,
7368
+ output: stdout2,
7369
+ error: stderr || void 0,
7370
+ exitCode: exitCode || 0,
7371
+ duration,
7372
+ ...subAgentResponse ? { subAgentResponse } : void 0
7373
+ });
7374
+ })();
7319
7375
  });
7320
7376
  child.on("error", (error) => {
7321
7377
  if (isProcessKilled) return;
@@ -7347,6 +7403,66 @@ var init_shell_backend = __esm({
7347
7403
  });
7348
7404
  });
7349
7405
  }
7406
+ /**
7407
+ * Build a structured, JSON-parsable result payload for programmatic capture while
7408
+ * preserving the shell backend's existing on-screen streaming behavior.
7409
+ */
7410
+ buildStructuredOutput(subagentType, result) {
7411
+ if (subagentType === "claude") {
7412
+ const claudeEvent = result.subAgentResponse ?? this.extractLastJsonEvent(result.output);
7413
+ const isError = claudeEvent?.is_error ?? claudeEvent?.subtype === "error" ?? !result.success;
7414
+ const structuredPayload = {
7415
+ type: "result",
7416
+ subtype: claudeEvent?.subtype || (isError ? "error" : "success"),
7417
+ is_error: isError,
7418
+ result: claudeEvent?.result ?? claudeEvent?.error ?? claudeEvent?.content ?? result.output,
7419
+ error: claudeEvent?.error,
7420
+ stderr: result.error,
7421
+ datetime: claudeEvent?.datetime,
7422
+ counter: claudeEvent?.counter,
7423
+ session_id: claudeEvent?.session_id,
7424
+ num_turns: claudeEvent?.num_turns,
7425
+ duration_ms: claudeEvent?.duration_ms ?? result.duration,
7426
+ exit_code: result.exitCode,
7427
+ total_cost_usd: claudeEvent?.total_cost_usd,
7428
+ usage: claudeEvent?.usage,
7429
+ modelUsage: claudeEvent?.modelUsage || claudeEvent?.model_usage || {},
7430
+ permission_denials: claudeEvent?.permission_denials || [],
7431
+ uuid: claudeEvent?.uuid,
7432
+ sub_agent_response: claudeEvent
7433
+ };
7434
+ const metadata = {
7435
+ ...claudeEvent ? { subAgentResponse: claudeEvent } : void 0,
7436
+ structuredOutput: true,
7437
+ contentType: "application/json",
7438
+ rawOutput: result.output
7439
+ };
7440
+ return {
7441
+ content: JSON.stringify(structuredPayload),
7442
+ metadata
7443
+ };
7444
+ }
7445
+ return { content: result.output, metadata: result.metadata };
7446
+ }
7447
+ /**
7448
+ * Extract the last valid JSON object from a script's stdout to use as a structured payload fallback.
7449
+ */
7450
+ extractLastJsonEvent(output) {
7451
+ if (!output) {
7452
+ return null;
7453
+ }
7454
+ const lines = output.split("\n").map((line) => line.trim()).filter(Boolean);
7455
+ for (let i = lines.length - 1; i >= 0; i--) {
7456
+ try {
7457
+ const parsed = JSON.parse(lines[i]);
7458
+ if (parsed && typeof parsed === "object") {
7459
+ return parsed;
7460
+ }
7461
+ } catch {
7462
+ }
7463
+ }
7464
+ return null;
7465
+ }
7350
7466
  /**
7351
7467
  * Parse streaming events from script output
7352
7468
  * Handles both JSON format (Claude) and TEXT format (Codex)
@@ -7871,7 +7987,7 @@ var init_concurrent_feedback_collector = __esm({
7871
7987
  process.stdin.removeAllListeners("data");
7872
7988
  process.stdin.removeAllListeners("end");
7873
7989
  if (this.options.verbose) {
7874
- process.stderr.write(`${os3.EOL}[feedback-collector] Stopped. Total submissions: ${this.submissionCount}${os3.EOL}`);
7990
+ process.stderr.write(`${os4.EOL}[feedback-collector] Stopped. Total submissions: ${this.submissionCount}${os4.EOL}`);
7875
7991
  }
7876
7992
  }
7877
7993
  /**
@@ -7934,7 +8050,7 @@ var init_concurrent_feedback_collector = __esm({
7934
8050
  chalk15__default.default.blue.bold("\u2551") + chalk15__default.default.gray(" Exit: Press Ctrl-D (or Ctrl-Z on Windows)") + " ".repeat(16) + chalk15__default.default.blue.bold("\u2551"),
7935
8051
  chalk15__default.default.blue.bold("\u255A" + border + "\u255D"),
7936
8052
  chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Type F+Enter to start giving feedback)")
7937
- ].join(os3.EOL) + os3.EOL
8053
+ ].join(os4.EOL) + os4.EOL
7938
8054
  );
7939
8055
  }
7940
8056
  /**
@@ -7944,7 +8060,7 @@ var init_concurrent_feedback_collector = __esm({
7944
8060
  this.progressTimer = setInterval(() => {
7945
8061
  this.progressTick += 1;
7946
8062
  const elapsed = ((Date.now() - this.startTime.getTime()) / 1e3).toFixed(1);
7947
- process.stderr.write(`[progress] tick=${this.progressTick} elapsed=${elapsed}s${os3.EOL}`);
8063
+ process.stderr.write(`[progress] tick=${this.progressTick} elapsed=${elapsed}s${os4.EOL}`);
7948
8064
  }, this.options.progressInterval);
7949
8065
  }
7950
8066
  /**
@@ -7954,10 +8070,10 @@ var init_concurrent_feedback_collector = __esm({
7954
8070
  this.feedbackMode = "feedback" /* FEEDBACK */;
7955
8071
  setFeedbackActive(true);
7956
8072
  this.buffer = "";
7957
- process.stdout.write(os3.EOL + chalk15__default.default.yellow.bold("\u{1F4DD} FEEDBACK MODE") + chalk15__default.default.gray(" - Type feedback (multiline ok), then Q+Enter to submit | MCP progress paused") + os3.EOL);
8073
+ process.stdout.write(os4.EOL + chalk15__default.default.yellow.bold("\u{1F4DD} FEEDBACK MODE") + chalk15__default.default.gray(" - Type feedback (multiline ok), then Q+Enter to submit | MCP progress paused") + os4.EOL);
7958
8074
  process.stdout.write(chalk15__default.default.cyan.bold("> "));
7959
8075
  if (this.options.verbose) {
7960
- process.stderr.write(`[feedback-collector] Entered FEEDBACK mode - MCP progress buffering activated${os3.EOL}`);
8076
+ process.stderr.write(`[feedback-collector] Entered FEEDBACK mode - MCP progress buffering activated${os4.EOL}`);
7961
8077
  }
7962
8078
  }
7963
8079
  /**
@@ -7967,7 +8083,7 @@ var init_concurrent_feedback_collector = __esm({
7967
8083
  this.feedbackMode = "normal" /* NORMAL */;
7968
8084
  setFeedbackActive(false);
7969
8085
  if (this.options.verbose) {
7970
- process.stderr.write(`[feedback-collector] Exited FEEDBACK mode - MCP progress restored${os3.EOL}`);
8086
+ process.stderr.write(`[feedback-collector] Exited FEEDBACK mode - MCP progress restored${os4.EOL}`);
7971
8087
  }
7972
8088
  }
7973
8089
  /**
@@ -8010,7 +8126,7 @@ var init_concurrent_feedback_collector = __esm({
8010
8126
  clearInterval(this.progressTimer);
8011
8127
  }
8012
8128
  if (this.options.verbose) {
8013
- process.stderr.write(`${os3.EOL}[feedback-collector] EOF received. Total submissions: ${this.submissionCount}${os3.EOL}`);
8129
+ process.stderr.write(`${os4.EOL}[feedback-collector] EOF received. Total submissions: ${this.submissionCount}${os4.EOL}`);
8014
8130
  }
8015
8131
  });
8016
8132
  }
@@ -8025,7 +8141,7 @@ var init_concurrent_feedback_collector = __esm({
8025
8141
  return;
8026
8142
  }
8027
8143
  if (trimmed.length > 0) {
8028
- process.stdout.write(chalk15__default.default.gray("Type F+Enter to enter feedback mode, or Ctrl-D to exit") + os3.EOL);
8144
+ process.stdout.write(chalk15__default.default.gray("Type F+Enter to enter feedback mode, or Ctrl-D to exit") + os4.EOL);
8029
8145
  process.stdout.write(chalk15__default.default.cyan.bold("> "));
8030
8146
  }
8031
8147
  return;
@@ -8034,10 +8150,10 @@ var init_concurrent_feedback_collector = __esm({
8034
8150
  if (trimmed === "q") {
8035
8151
  this.submitFeedback();
8036
8152
  this.exitFeedbackMode();
8037
- process.stdout.write(os3.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Type F+Enter for another feedback, or Ctrl-D to exit)") + os3.EOL);
8153
+ process.stdout.write(os4.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Type F+Enter for another feedback, or Ctrl-D to exit)") + os4.EOL);
8038
8154
  return;
8039
8155
  }
8040
- this.buffer += line + os3.EOL;
8156
+ this.buffer += line + os4.EOL;
8041
8157
  }
8042
8158
  }
8043
8159
  /**
@@ -8047,18 +8163,18 @@ var init_concurrent_feedback_collector = __esm({
8047
8163
  const content = this.buffer.trimEnd();
8048
8164
  this.buffer = "";
8049
8165
  if (content.length === 0) {
8050
- process.stdout.write(os3.EOL + chalk15__default.default.yellow("\u26A0\uFE0F No feedback content to submit") + os3.EOL);
8166
+ process.stdout.write(os4.EOL + chalk15__default.default.yellow("\u26A0\uFE0F No feedback content to submit") + os4.EOL);
8051
8167
  return;
8052
8168
  }
8053
- process.stdout.write(os3.EOL + chalk15__default.default.green.bold("\u2705 Feedback registered and being processed...") + os3.EOL);
8169
+ process.stdout.write(os4.EOL + chalk15__default.default.green.bold("\u2705 Feedback registered and being processed...") + os4.EOL);
8054
8170
  if (this.options.verbose) {
8055
- process.stdout.write(chalk15__default.default.gray("Feedback content:") + os3.EOL);
8056
- process.stdout.write(content + os3.EOL);
8057
- process.stdout.write(chalk15__default.default.cyan("===== END BLOCK =====") + os3.EOL);
8171
+ process.stdout.write(chalk15__default.default.gray("Feedback content:") + os4.EOL);
8172
+ process.stdout.write(content + os4.EOL);
8173
+ process.stdout.write(chalk15__default.default.cyan("===== END BLOCK =====") + os4.EOL);
8058
8174
  }
8059
8175
  flushBufferedProgress();
8060
8176
  this.enqueueSubmission(content).catch((err) => {
8061
- process.stderr.write(`${os3.EOL}[feedback-collector] Error submitting feedback: ${err}${os3.EOL}`);
8177
+ process.stderr.write(`${os4.EOL}[feedback-collector] Error submitting feedback: ${err}${os4.EOL}`);
8062
8178
  });
8063
8179
  }
8064
8180
  /**
@@ -8084,18 +8200,18 @@ var init_concurrent_feedback_collector = __esm({
8084
8200
  this.submissions.push(submission);
8085
8201
  if (this.options.onSubmit) {
8086
8202
  if (this.options.verbose) {
8087
- process.stderr.write(`${os3.EOL}[feedback-collector ${n}] Using custom submission handler${os3.EOL}`);
8203
+ process.stderr.write(`${os4.EOL}[feedback-collector ${n}] Using custom submission handler${os4.EOL}`);
8088
8204
  }
8089
8205
  try {
8090
8206
  await this.options.onSubmit(input);
8091
8207
  if (this.options.verbose) {
8092
- process.stderr.write(`[feedback-collector ${n}] Custom handler completed${os3.EOL}`);
8208
+ process.stderr.write(`[feedback-collector ${n}] Custom handler completed${os4.EOL}`);
8093
8209
  }
8094
- process.stdout.write(os3.EOL + chalk15__default.default.green("\u2705 Feedback submitted successfully. You can type another block.") + os3.EOL);
8095
- process.stdout.write(os3.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Ready for next feedback)") + os3.EOL);
8210
+ process.stdout.write(os4.EOL + chalk15__default.default.green("\u2705 Feedback submitted successfully. You can type another block.") + os4.EOL);
8211
+ process.stdout.write(os4.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Ready for next feedback)") + os4.EOL);
8096
8212
  } catch (error) {
8097
- process.stderr.write(`[feedback-collector ${n}] Custom handler error: ${error}${os3.EOL}`);
8098
- process.stdout.write(os3.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os3.EOL);
8213
+ process.stderr.write(`[feedback-collector ${n}] Custom handler error: ${error}${os4.EOL}`);
8214
+ process.stdout.write(os4.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os4.EOL);
8099
8215
  }
8100
8216
  } else {
8101
8217
  await this.runCommandWithInput(n, input);
@@ -8106,7 +8222,7 @@ var init_concurrent_feedback_collector = __esm({
8106
8222
  */
8107
8223
  async runCommandWithInput(n, input) {
8108
8224
  if (this.options.verbose) {
8109
- process.stderr.write(`${os3.EOL}[feedback-collector ${n}] Launching "${this.options.command}" ${this.options.commandArgs.join(" ")}${os3.EOL}`);
8225
+ process.stderr.write(`${os4.EOL}[feedback-collector ${n}] Launching "${this.options.command}" ${this.options.commandArgs.join(" ")}${os4.EOL}`);
8110
8226
  }
8111
8227
  return new Promise((resolve9) => {
8112
8228
  const child = child_process.spawn(this.options.command, this.options.commandArgs, {
@@ -8124,25 +8240,25 @@ var init_concurrent_feedback_collector = __esm({
8124
8240
  });
8125
8241
  child.on("close", (code) => {
8126
8242
  if (this.options.verbose) {
8127
- process.stderr.write(`[feedback-collector ${n}] exit code ${code ?? 0}${os3.EOL}`);
8243
+ process.stderr.write(`[feedback-collector ${n}] exit code ${code ?? 0}${os4.EOL}`);
8128
8244
  }
8129
8245
  if (code === 0) {
8130
- process.stdout.write(os3.EOL + chalk15__default.default.green("\u2705 Feedback submitted successfully. You can type another block.") + os3.EOL);
8131
- process.stdout.write(os3.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Ready for next feedback)") + os3.EOL);
8246
+ process.stdout.write(os4.EOL + chalk15__default.default.green("\u2705 Feedback submitted successfully. You can type another block.") + os4.EOL);
8247
+ process.stdout.write(os4.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Ready for next feedback)") + os4.EOL);
8132
8248
  } else {
8133
- process.stdout.write(os3.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os3.EOL);
8249
+ process.stdout.write(os4.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os4.EOL);
8134
8250
  }
8135
8251
  resolve9();
8136
8252
  });
8137
8253
  child.on("error", (err) => {
8138
- process.stderr.write(`[feedback-collector ${n}] error: ${err.message}${os3.EOL}`);
8139
- process.stdout.write(os3.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os3.EOL);
8254
+ process.stderr.write(`[feedback-collector ${n}] error: ${err.message}${os4.EOL}`);
8255
+ process.stdout.write(os4.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os4.EOL);
8140
8256
  resolve9();
8141
8257
  });
8142
8258
  if (child.stdin) {
8143
8259
  child.stdin.write(input);
8144
- if (!input.endsWith(os3.EOL)) {
8145
- child.stdin.write(os3.EOL);
8260
+ if (!input.endsWith(os4.EOL)) {
8261
+ child.stdin.write(os4.EOL);
8146
8262
  }
8147
8263
  child.stdin.end();
8148
8264
  }
@@ -12843,7 +12959,7 @@ var init_main = __esm({
12843
12959
  return await this.collectInteractivePrompt();
12844
12960
  } else {
12845
12961
  const defaultPromptPath = path3__namespace.join(process.cwd(), ".juno_task", "prompt.md");
12846
- if (await fs3__default.default.pathExists(defaultPromptPath)) {
12962
+ if (await fs2__default.default.pathExists(defaultPromptPath)) {
12847
12963
  console.error(chalk15__default.default.blue(`\u{1F4C4} Using default prompt: ${chalk15__default.default.cyan(".juno_task/prompt.md")}`));
12848
12964
  return await this.loadPromptFromFile(defaultPromptPath);
12849
12965
  } else {
@@ -12871,7 +12987,7 @@ var init_main = __esm({
12871
12987
  }
12872
12988
  try {
12873
12989
  const resolvedPath = path3__namespace.resolve(prompt);
12874
- return await fs3__default.default.pathExists(resolvedPath);
12990
+ return await fs2__default.default.pathExists(resolvedPath);
12875
12991
  } catch {
12876
12992
  return false;
12877
12993
  }
@@ -12879,7 +12995,7 @@ var init_main = __esm({
12879
12995
  async loadPromptFromFile(filePath) {
12880
12996
  try {
12881
12997
  const resolvedPath = path3__namespace.resolve(filePath);
12882
- const content = await fs3__default.default.readFile(resolvedPath, "utf-8");
12998
+ const content = await fs2__default.default.readFile(resolvedPath, "utf-8");
12883
12999
  if (!content.trim()) {
12884
13000
  throw new FileSystemError(
12885
13001
  "Prompt file is empty",
@@ -13086,7 +13202,11 @@ var init_main = __esm({
13086
13202
  \u274C Execution failed (${elapsed})`));
13087
13203
  }
13088
13204
  const lastIteration = result.iterations[result.iterations.length - 1];
13089
- if (lastIteration && lastIteration.toolResult.content && !this.hasStreamedJsonOutput) {
13205
+ const structuredOutput = lastIteration?.toolResult.metadata?.structuredOutput === true;
13206
+ const shouldPrintResult = Boolean(
13207
+ lastIteration && lastIteration.toolResult.content && (!this.hasStreamedJsonOutput || structuredOutput)
13208
+ );
13209
+ if (shouldPrintResult) {
13090
13210
  console.error(chalk15__default.default.blue("\n\u{1F4C4} Result:"));
13091
13211
  console.log(lastIteration.toolResult.content);
13092
13212
  }
@@ -13287,7 +13407,7 @@ async function validateJSONFile(configSchema, baseDir) {
13287
13407
  const warnings = [];
13288
13408
  const filePath = path3__namespace.default.join(baseDir, configSchema.file);
13289
13409
  try {
13290
- const exists = await fs3__default.default.pathExists(filePath);
13410
+ const exists = await fs2__default.default.pathExists(filePath);
13291
13411
  if (!exists) {
13292
13412
  if (configSchema.required) {
13293
13413
  errors.push({
@@ -13310,7 +13430,7 @@ async function validateJSONFile(configSchema, baseDir) {
13310
13430
  return { isValid: !configSchema.required, errors, warnings };
13311
13431
  }
13312
13432
  try {
13313
- await fs3__default.default.access(filePath, fs3__default.default.constants.R_OK);
13433
+ await fs2__default.default.access(filePath, fs2__default.default.constants.R_OK);
13314
13434
  } catch (accessError) {
13315
13435
  errors.push({
13316
13436
  file: configSchema.file,
@@ -13326,7 +13446,7 @@ async function validateJSONFile(configSchema, baseDir) {
13326
13446
  }
13327
13447
  let jsonData;
13328
13448
  try {
13329
- const fileContent = await fs3__default.default.readFile(filePath, "utf8");
13449
+ const fileContent = await fs2__default.default.readFile(filePath, "utf8");
13330
13450
  jsonData = JSON.parse(fileContent);
13331
13451
  } catch (parseError) {
13332
13452
  const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
@@ -13424,7 +13544,7 @@ async function validateJSONConfigs(baseDir = process.cwd(), backendType = "mcp")
13424
13544
  }
13425
13545
  function displayValidationResults(result) {
13426
13546
  if (result.isValid && result.warnings.length === 0) {
13427
- console.log(chalk15__default.default.green("\u2705 All configuration files are valid\n"));
13547
+ console.error(chalk15__default.default.green("\u2705 All configuration files are valid\n"));
13428
13548
  return;
13429
13549
  }
13430
13550
  if (result.errors.length > 0) {
@@ -13461,7 +13581,7 @@ function displayValidationResults(result) {
13461
13581
  }
13462
13582
  async function logValidationResults(result, baseDir = process.cwd()) {
13463
13583
  const logDir = path3__namespace.default.join(baseDir, ".juno_task", "logs");
13464
- await fs3__default.default.ensureDir(logDir);
13584
+ await fs2__default.default.ensureDir(logDir);
13465
13585
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
13466
13586
  const logFile = path3__namespace.default.join(logDir, `startup-validation-${timestamp}.log`);
13467
13587
  const logContent = [
@@ -13504,7 +13624,7 @@ async function logValidationResults(result, baseDir = process.cwd()) {
13504
13624
  logContent.push(``);
13505
13625
  }
13506
13626
  }
13507
- await fs3__default.default.writeFile(logFile, logContent.join("\n"));
13627
+ await fs2__default.default.writeFile(logFile, logContent.join("\n"));
13508
13628
  return logFile;
13509
13629
  }
13510
13630
  async function validateStartupConfigs(baseDir = process.cwd(), verbose = false) {
@@ -13838,7 +13958,7 @@ var TemplateEngine = class {
13838
13958
  let overallError;
13839
13959
  try {
13840
13960
  if (!options.dryRun) {
13841
- await fs3__default.default.ensureDir(targetDirectory);
13961
+ await fs2__default.default.ensureDir(targetDirectory);
13842
13962
  }
13843
13963
  for (const template of templates) {
13844
13964
  try {
@@ -15188,7 +15308,7 @@ This directory contains specification documents for your project.
15188
15308
  const fileName = this.getTemplateFileName(template);
15189
15309
  const targetPath = path3__namespace.join(targetDirectory, fileName);
15190
15310
  try {
15191
- const fileExists = await fs3__default.default.pathExists(targetPath);
15311
+ const fileExists = await fs2__default.default.pathExists(targetPath);
15192
15312
  if (fileExists && !options.force && options.onConflict !== "overwrite") {
15193
15313
  return {
15194
15314
  path: targetPath,
@@ -15210,10 +15330,10 @@ This directory contains specification documents for your project.
15210
15330
  }
15211
15331
  if (options.createBackup && fileExists) {
15212
15332
  const backupPath = `${targetPath}.backup.${Date.now()}`;
15213
- await fs3__default.default.copy(targetPath, backupPath);
15333
+ await fs2__default.default.copy(targetPath, backupPath);
15214
15334
  }
15215
- await fs3__default.default.ensureDir(path3__namespace.dirname(targetPath));
15216
- await fs3__default.default.writeFile(targetPath, renderedContent, "utf8");
15335
+ await fs2__default.default.ensureDir(path3__namespace.dirname(targetPath));
15336
+ await fs2__default.default.writeFile(targetPath, renderedContent, "utf8");
15217
15337
  return {
15218
15338
  path: targetPath,
15219
15339
  content: renderedContent,
@@ -15477,7 +15597,7 @@ var SimpleInitTUI = class {
15477
15597
  }
15478
15598
  async confirmSave(targetDirectory) {
15479
15599
  const junoTaskPath = path3__namespace.join(targetDirectory, ".juno_task");
15480
- if (await fs3__default.default.pathExists(junoTaskPath)) {
15600
+ if (await fs2__default.default.pathExists(junoTaskPath)) {
15481
15601
  console.log(chalk15__default.default.yellow(" \u26A0\uFE0F .juno_task directory already exists"));
15482
15602
  console.log(chalk15__default.default.gray(" Would you like to:"));
15483
15603
  console.log(chalk15__default.default.gray(" 1) Override existing files"));
@@ -15522,16 +15642,16 @@ var SimpleProjectGenerator = class {
15522
15642
  async generate() {
15523
15643
  const { targetDirectory, variables, force } = this.context;
15524
15644
  console.log(chalk15__default.default.blue("\u{1F4C1} Creating project directory..."));
15525
- await fs3__default.default.ensureDir(targetDirectory);
15645
+ await fs2__default.default.ensureDir(targetDirectory);
15526
15646
  const junoTaskDir = path3__namespace.join(targetDirectory, ".juno_task");
15527
- const junoTaskExists = await fs3__default.default.pathExists(junoTaskDir);
15647
+ const junoTaskExists = await fs2__default.default.pathExists(junoTaskDir);
15528
15648
  if (junoTaskExists && !force) {
15529
15649
  throw new ValidationError(
15530
15650
  "Project already initialized. Directory .juno_task already exists.",
15531
15651
  ["Use --force flag to overwrite existing files", "Choose a different directory"]
15532
15652
  );
15533
15653
  }
15534
- await fs3__default.default.ensureDir(junoTaskDir);
15654
+ await fs2__default.default.ensureDir(junoTaskDir);
15535
15655
  console.log(chalk15__default.default.blue("\u2699\uFE0F Creating project configuration..."));
15536
15656
  await this.createConfigFile(junoTaskDir, targetDirectory);
15537
15657
  console.log(chalk15__default.default.blue("\u{1F527} Setting up MCP configuration..."));
@@ -15565,21 +15685,21 @@ var SimpleProjectGenerator = class {
15565
15685
  const promptContent = await templateEngine.render(promptTemplate, templateContext);
15566
15686
  const initContent = await templateEngine.render(initTemplate, templateContext);
15567
15687
  const implementContent = await templateEngine.render(implementTemplate, templateContext);
15568
- await fs3__default.default.writeFile(path3__namespace.join(junoTaskDir, "prompt.md"), promptContent);
15569
- await fs3__default.default.writeFile(path3__namespace.join(junoTaskDir, "init.md"), initContent);
15570
- await fs3__default.default.writeFile(path3__namespace.join(junoTaskDir, "implement.md"), implementContent);
15688
+ await fs2__default.default.writeFile(path3__namespace.join(junoTaskDir, "prompt.md"), promptContent);
15689
+ await fs2__default.default.writeFile(path3__namespace.join(junoTaskDir, "init.md"), initContent);
15690
+ await fs2__default.default.writeFile(path3__namespace.join(junoTaskDir, "implement.md"), implementContent);
15571
15691
  const userFeedbackTemplate = templateEngine.getBuiltInTemplate("USER_FEEDBACK.md");
15572
15692
  if (userFeedbackTemplate) {
15573
15693
  const userFeedbackContent = await templateEngine.render(userFeedbackTemplate, templateContext);
15574
- await fs3__default.default.writeFile(path3__namespace.join(junoTaskDir, "USER_FEEDBACK.md"), userFeedbackContent);
15694
+ await fs2__default.default.writeFile(path3__namespace.join(junoTaskDir, "USER_FEEDBACK.md"), userFeedbackContent);
15575
15695
  }
15576
15696
  const planTemplate = templateEngine.getBuiltInTemplate("plan.md");
15577
15697
  if (planTemplate) {
15578
15698
  const planContent = await templateEngine.render(planTemplate, templateContext);
15579
- await fs3__default.default.writeFile(path3__namespace.join(junoTaskDir, "plan.md"), planContent);
15699
+ await fs2__default.default.writeFile(path3__namespace.join(junoTaskDir, "plan.md"), planContent);
15580
15700
  }
15581
15701
  const specsDir = path3__namespace.join(junoTaskDir, "specs");
15582
- await fs3__default.default.ensureDir(specsDir);
15702
+ await fs2__default.default.ensureDir(specsDir);
15583
15703
  const specsReadmeContent = `# Project Specifications
15584
15704
 
15585
15705
  This directory contains detailed specifications for the project components.
@@ -15596,7 +15716,7 @@ This directory contains detailed specifications for the project components.
15596
15716
  - Avoid conflicts with existing file names
15597
15717
  - Use \`.md\` extension for all specification files
15598
15718
  `;
15599
- await fs3__default.default.writeFile(path3__namespace.join(specsDir, "README.md"), specsReadmeContent);
15719
+ await fs2__default.default.writeFile(path3__namespace.join(specsDir, "README.md"), specsReadmeContent);
15600
15720
  const requirementsContent = `# Requirements Specification
15601
15721
 
15602
15722
  ## Functional Requirements
@@ -15643,7 +15763,7 @@ This directory contains detailed specifications for the project components.
15643
15763
  - Code quality: Clean, maintainable codebase
15644
15764
  - Documentation: Complete and accurate documentation
15645
15765
  `;
15646
- await fs3__default.default.writeFile(path3__namespace.join(specsDir, "requirements.md"), requirementsContent);
15766
+ await fs2__default.default.writeFile(path3__namespace.join(specsDir, "requirements.md"), requirementsContent);
15647
15767
  const architectureContent = `# Architecture Specification
15648
15768
 
15649
15769
  ## System Overview
@@ -15725,7 +15845,7 @@ This project uses AI-assisted development with juno-code to achieve: ${variables
15725
15845
  - Performance monitoring
15726
15846
  - Security best practices
15727
15847
  `;
15728
- await fs3__default.default.writeFile(path3__namespace.join(specsDir, "architecture.md"), architectureContent);
15848
+ await fs2__default.default.writeFile(path3__namespace.join(specsDir, "architecture.md"), architectureContent);
15729
15849
  const claudeContent = `# Claude Development Session Learnings
15730
15850
 
15731
15851
  ## Project Overview
@@ -15797,7 +15917,7 @@ This file will be updated as development progresses to track:
15797
15917
  - Solutions to complex problems
15798
15918
  - Performance improvements and optimizations
15799
15919
  `;
15800
- await fs3__default.default.writeFile(path3__namespace.join(targetDirectory, "CLAUDE.md"), claudeContent);
15920
+ await fs2__default.default.writeFile(path3__namespace.join(targetDirectory, "CLAUDE.md"), claudeContent);
15801
15921
  const agentsContent = `# AI Agent Selection and Performance
15802
15922
 
15803
15923
  ## Available Agents
@@ -15861,7 +15981,7 @@ Track agent performance for:
15861
15981
  4. **Feedback Loop**: Provide feedback to improve agent performance
15862
15982
  5. **Performance Monitoring**: Track and optimize agent usage
15863
15983
  `;
15864
- await fs3__default.default.writeFile(path3__namespace.join(targetDirectory, "AGENTS.md"), agentsContent);
15984
+ await fs2__default.default.writeFile(path3__namespace.join(targetDirectory, "AGENTS.md"), agentsContent);
15865
15985
  const readmeContent = `# ${variables.PROJECT_NAME}
15866
15986
 
15867
15987
  ${variables.DESCRIPTION}
@@ -15958,7 +16078,7 @@ ${variables.GIT_URL}` : ""}
15958
16078
  Created with juno-code on ${variables.CURRENT_DATE}
15959
16079
  ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
15960
16080
  `;
15961
- await fs3__default.default.writeFile(path3__namespace.join(targetDirectory, "README.md"), readmeContent);
16081
+ await fs2__default.default.writeFile(path3__namespace.join(targetDirectory, "README.md"), readmeContent);
15962
16082
  console.log(chalk15__default.default.blue("\u{1F4E6} Installing utility scripts..."));
15963
16083
  await this.copyScriptsFromTemplates(junoTaskDir);
15964
16084
  console.log(chalk15__default.default.blue("\u{1F40D} Installing Python requirements..."));
@@ -16010,7 +16130,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16010
16130
  hooks: getDefaultHooks()
16011
16131
  };
16012
16132
  const configPath = path3__namespace.join(junoTaskDir, "config.json");
16013
- await fs3__default.default.writeFile(configPath, JSON.stringify(configContent, null, 2));
16133
+ await fs2__default.default.writeFile(configPath, JSON.stringify(configContent, null, 2));
16014
16134
  console.log(chalk15__default.default.green(` \u2713 Created .juno_task/config.json with ${this.context.subagent} as default subagent`));
16015
16135
  }
16016
16136
  async createMcpFile(junoTaskDir, targetDirectory) {
@@ -16064,7 +16184,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16064
16184
  }
16065
16185
  };
16066
16186
  const mcpPath = path3__namespace.join(junoTaskDir, "mcp.json");
16067
- await fs3__default.default.writeFile(mcpPath, JSON.stringify(mcpContent, null, 2));
16187
+ await fs2__default.default.writeFile(mcpPath, JSON.stringify(mcpContent, null, 2));
16068
16188
  console.log(chalk15__default.default.green(` \u2713 Created .juno_task/mcp.json with roundtable-ai server configuration`));
16069
16189
  }
16070
16190
  getDefaultModelForSubagent(subagent) {
@@ -16083,7 +16203,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16083
16203
  async copyScriptsFromTemplates(junoTaskDir) {
16084
16204
  try {
16085
16205
  const scriptsDir = path3__namespace.join(junoTaskDir, "scripts");
16086
- await fs3__default.default.ensureDir(scriptsDir);
16206
+ await fs2__default.default.ensureDir(scriptsDir);
16087
16207
  const __filename2 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
16088
16208
  const __dirname2 = path3__namespace.dirname(__filename2);
16089
16209
  let templatesScriptsDir;
@@ -16094,11 +16214,11 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16094
16214
  } else {
16095
16215
  templatesScriptsDir = path3__namespace.join(__dirname2, "../../templates/scripts");
16096
16216
  }
16097
- if (!await fs3__default.default.pathExists(templatesScriptsDir)) {
16217
+ if (!await fs2__default.default.pathExists(templatesScriptsDir)) {
16098
16218
  console.log(chalk15__default.default.yellow(" \u26A0\uFE0F Template scripts directory not found, skipping script installation"));
16099
16219
  return;
16100
16220
  }
16101
- const scriptFiles = await fs3__default.default.readdir(templatesScriptsDir);
16221
+ const scriptFiles = await fs2__default.default.readdir(templatesScriptsDir);
16102
16222
  if (scriptFiles.length === 0) {
16103
16223
  console.log(chalk15__default.default.gray(" \u2139\uFE0F No template scripts found to install"));
16104
16224
  return;
@@ -16107,11 +16227,11 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16107
16227
  for (const scriptFile of scriptFiles) {
16108
16228
  const sourcePath = path3__namespace.join(templatesScriptsDir, scriptFile);
16109
16229
  const destPath = path3__namespace.join(scriptsDir, scriptFile);
16110
- const stats = await fs3__default.default.stat(sourcePath);
16230
+ const stats = await fs2__default.default.stat(sourcePath);
16111
16231
  if (stats.isFile()) {
16112
- await fs3__default.default.copy(sourcePath, destPath);
16232
+ await fs2__default.default.copy(sourcePath, destPath);
16113
16233
  if (scriptFile.endsWith(".sh")) {
16114
- await fs3__default.default.chmod(destPath, 493);
16234
+ await fs2__default.default.chmod(destPath, 493);
16115
16235
  }
16116
16236
  copiedCount++;
16117
16237
  console.log(chalk15__default.default.green(` \u2713 Installed script: ${scriptFile}`));
@@ -16134,7 +16254,7 @@ ${variables.EDITOR ? `using ${variables.EDITOR} as primary AI subagent` : ""}
16134
16254
  try {
16135
16255
  const scriptsDir = path3__namespace.join(junoTaskDir, "scripts");
16136
16256
  const installScript = path3__namespace.join(scriptsDir, "install_requirements.sh");
16137
- if (!await fs3__default.default.pathExists(installScript)) {
16257
+ if (!await fs2__default.default.pathExists(installScript)) {
16138
16258
  console.log(chalk15__default.default.yellow(" \u26A0\uFE0F install_requirements.sh not found, skipping Python dependencies installation"));
16139
16259
  console.log(chalk15__default.default.gray(" You can install dependencies manually: juno-kanban, roundtable-ai"));
16140
16260
  return;
@@ -16431,20 +16551,20 @@ init_types();
16431
16551
  async function loadInitPrompt(directory) {
16432
16552
  const junoTaskDir = path3__namespace.join(directory, ".juno_task");
16433
16553
  const initFile = path3__namespace.join(junoTaskDir, "init.md");
16434
- if (!await fs3__default.default.pathExists(junoTaskDir)) {
16554
+ if (!await fs2__default.default.pathExists(junoTaskDir)) {
16435
16555
  throw new FileSystemError(
16436
16556
  'No .juno_task directory found. Run "juno-code init" first.',
16437
16557
  junoTaskDir
16438
16558
  );
16439
16559
  }
16440
- if (!await fs3__default.default.pathExists(initFile)) {
16560
+ if (!await fs2__default.default.pathExists(initFile)) {
16441
16561
  throw new FileSystemError(
16442
16562
  "No init.md file found in .juno_task directory",
16443
16563
  initFile
16444
16564
  );
16445
16565
  }
16446
16566
  try {
16447
- const content = await fs3__default.default.readFile(initFile, "utf-8");
16567
+ const content = await fs2__default.default.readFile(initFile, "utf-8");
16448
16568
  if (!content.trim()) {
16449
16569
  throw new FileSystemError(
16450
16570
  "init.md file is empty. Please add task instructions.",
@@ -17476,8 +17596,8 @@ Focus on ${request.intelligence === "basic" ? "basic functionality" : request.in
17476
17596
  for (const scenario of scenarios) {
17477
17597
  const testContent = await this.generateTestContent(request, scenario, template);
17478
17598
  const testFilePath = this.resolveTestFilePath(request, scenario);
17479
- await fs3__default.default.ensureDir(path3__namespace.dirname(testFilePath));
17480
- await fs3__default.default.writeFile(testFilePath, testContent);
17599
+ await fs2__default.default.ensureDir(path3__namespace.dirname(testFilePath));
17600
+ await fs2__default.default.writeFile(testFilePath, testContent);
17481
17601
  testFiles.push(testFilePath);
17482
17602
  }
17483
17603
  return testFiles;
@@ -17729,8 +17849,8 @@ var TestExecutionEngine = class {
17729
17849
  async collectCoverage(request) {
17730
17850
  const coverageFile = path3__namespace.join(request.workingDirectory, "coverage", "coverage-summary.json");
17731
17851
  try {
17732
- if (await fs3__default.default.pathExists(coverageFile)) {
17733
- const coverageData = await fs3__default.default.readJson(coverageFile);
17852
+ if (await fs2__default.default.pathExists(coverageFile)) {
17853
+ const coverageData = await fs2__default.default.readJson(coverageFile);
17734
17854
  return {
17735
17855
  lines: coverageData.total?.lines?.pct || 0,
17736
17856
  functions: coverageData.total?.functions?.pct || 0,
@@ -17913,8 +18033,8 @@ var TestReportEngine = class {
17913
18033
  suggestions: analysis.suggestions,
17914
18034
  recommendations: analysis.recommendations
17915
18035
  };
17916
- await fs3__default.default.ensureDir(path3__namespace.dirname(outputPath));
17917
- await fs3__default.default.writeJson(outputPath, report, { spaces: 2 });
18036
+ await fs2__default.default.ensureDir(path3__namespace.dirname(outputPath));
18037
+ await fs2__default.default.writeJson(outputPath, report, { spaces: 2 });
17918
18038
  return outputPath;
17919
18039
  }
17920
18040
  async generateHTMLReport(analysis, outputPath, includeVisualizations) {
@@ -17977,8 +18097,8 @@ var TestReportEngine = class {
17977
18097
  </body>
17978
18098
  </html>
17979
18099
  `.trim();
17980
- await fs3__default.default.ensureDir(path3__namespace.dirname(outputPath));
17981
- await fs3__default.default.writeFile(outputPath, html);
18100
+ await fs2__default.default.ensureDir(path3__namespace.dirname(outputPath));
18101
+ await fs2__default.default.writeFile(outputPath, html);
17982
18102
  return outputPath;
17983
18103
  }
17984
18104
  generateCharts(analysis) {
@@ -18035,8 +18155,8 @@ ${analysis.suggestions.map((suggestion) => `- ${suggestion}`).join("\n")}
18035
18155
 
18036
18156
  ${analysis.recommendations.map((rec) => `- ${rec}`).join("\n")}
18037
18157
  `.trim();
18038
- await fs3__default.default.ensureDir(path3__namespace.dirname(outputPath));
18039
- await fs3__default.default.writeFile(outputPath, markdown);
18158
+ await fs2__default.default.ensureDir(path3__namespace.dirname(outputPath));
18159
+ await fs2__default.default.writeFile(outputPath, markdown);
18040
18160
  return outputPath;
18041
18161
  }
18042
18162
  async displayConsoleReport(analysis) {
@@ -18376,7 +18496,7 @@ async function compactConfigFile(filePath, options = {}) {
18376
18496
  preserveDays = 30,
18377
18497
  preservePatterns = []
18378
18498
  } = options;
18379
- const originalContent = await fs3__default.default.readFile(filePath, "utf-8");
18499
+ const originalContent = await fs2__default.default.readFile(filePath, "utf-8");
18380
18500
  const originalSize = originalContent.length;
18381
18501
  let backupPath = "";
18382
18502
  if (createBackup && !dryRun) {
@@ -18385,7 +18505,7 @@ async function compactConfigFile(filePath, options = {}) {
18385
18505
  const basename11 = path3__namespace.basename(filePath, ext);
18386
18506
  const dirname12 = path3__namespace.dirname(filePath);
18387
18507
  backupPath = path3__namespace.join(dirname12, `${basename11}.backup.${timestamp}${ext}`);
18388
- await fs3__default.default.writeFile(backupPath, originalContent, "utf-8");
18508
+ await fs2__default.default.writeFile(backupPath, originalContent, "utf-8");
18389
18509
  }
18390
18510
  const compactionAnalysis = analyzeMarkdownStructure(originalContent);
18391
18511
  const compactedContent = compactMarkdownContent(
@@ -18400,7 +18520,7 @@ async function compactConfigFile(filePath, options = {}) {
18400
18520
  const compactedSize = finalContent.length;
18401
18521
  const reductionPercentage = Math.round((originalSize - compactedSize) / originalSize * 100);
18402
18522
  if (!dryRun) {
18403
- await fs3__default.default.writeFile(filePath, finalContent, "utf-8");
18523
+ await fs2__default.default.writeFile(filePath, finalContent, "utf-8");
18404
18524
  }
18405
18525
  return {
18406
18526
  originalSize,
@@ -18530,7 +18650,7 @@ function formatFileSize(bytes) {
18530
18650
  }
18531
18651
  async function shouldCompactFile(filePath, sizeThresholdKB = 50, ageThresholdDays = 30) {
18532
18652
  try {
18533
- const stats = await fs3__default.default.stat(filePath);
18653
+ const stats = await fs2__default.default.stat(filePath);
18534
18654
  const sizeKB = stats.size / 1024;
18535
18655
  if (sizeKB > sizeThresholdKB) {
18536
18656
  return true;
@@ -18552,19 +18672,19 @@ async function archiveResolvedIssues(options) {
18552
18672
  feedbackFile,
18553
18673
  archiveDir = path3__namespace.join(path3__namespace.dirname(feedbackFile), "archives"),
18554
18674
  openIssuesThreshold = 10} = options;
18555
- if (!await fs3__default.default.pathExists(feedbackFile)) {
18675
+ if (!await fs2__default.default.pathExists(feedbackFile)) {
18556
18676
  throw new Error(`Feedback file does not exist: ${feedbackFile}`);
18557
18677
  }
18558
- const content = await fs3__default.default.readFile(feedbackFile, "utf-8");
18678
+ const content = await fs2__default.default.readFile(feedbackFile, "utf-8");
18559
18679
  const parsed = parseUserFeedback(content);
18560
18680
  const warningsGenerated = [];
18561
18681
  if (parsed.openIssues.length > openIssuesThreshold) {
18562
18682
  const warning = `Found ${parsed.openIssues.length} open issues (threshold: ${openIssuesThreshold}). Consider reviewing and prioritizing.`;
18563
18683
  warningsGenerated.push(warning);
18564
18684
  const logFile = path3__namespace.join(path3__namespace.dirname(feedbackFile), "logs", "feedback-warnings.log");
18565
- await fs3__default.default.ensureDir(path3__namespace.dirname(logFile));
18685
+ await fs2__default.default.ensureDir(path3__namespace.dirname(logFile));
18566
18686
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
18567
- await fs3__default.default.appendFile(logFile, `[${timestamp}] ${warning}
18687
+ await fs2__default.default.appendFile(logFile, `[${timestamp}] ${warning}
18568
18688
  `);
18569
18689
  }
18570
18690
  if (parsed.resolvedIssues.length === 0) {
@@ -18581,10 +18701,10 @@ async function archiveResolvedIssues(options) {
18581
18701
  const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
18582
18702
  const archiveFile = path3__namespace.join(archiveDir, `USER_FEEDBACK_archive_${currentYear}.md`);
18583
18703
  {
18584
- await fs3__default.default.ensureDir(archiveDir);
18704
+ await fs2__default.default.ensureDir(archiveDir);
18585
18705
  await appendToArchive(archiveFile, parsed.resolvedIssues);
18586
18706
  const compactedContent = generateCompactedFeedback(parsed.openIssues, parsed.metadata);
18587
- await fs3__default.default.writeFile(feedbackFile, compactedContent, "utf-8");
18707
+ await fs2__default.default.writeFile(feedbackFile, compactedContent, "utf-8");
18588
18708
  }
18589
18709
  {
18590
18710
  console.log(chalk15__default.default.green(`\u2705 Archived ${parsed.resolvedIssues.length} resolved issues`));
@@ -18631,8 +18751,8 @@ function parseUserFeedback(content) {
18631
18751
  async function appendToArchive(archiveFile, resolvedIssues) {
18632
18752
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
18633
18753
  let archiveContent = "";
18634
- if (await fs3__default.default.pathExists(archiveFile)) {
18635
- archiveContent = await fs3__default.default.readFile(archiveFile, "utf-8");
18754
+ if (await fs2__default.default.pathExists(archiveFile)) {
18755
+ archiveContent = await fs2__default.default.readFile(archiveFile, "utf-8");
18636
18756
  } else {
18637
18757
  const year = path3__namespace.basename(archiveFile).match(/(\d{4})/)?.[1] || (/* @__PURE__ */ new Date()).getFullYear();
18638
18758
  archiveContent = `# User Feedback Archive ${year}
@@ -18666,7 +18786,7 @@ ${resolvedIssue}
18666
18786
  `- Last updated: ${timestamp}`
18667
18787
  );
18668
18788
  }
18669
- await fs3__default.default.writeFile(archiveFile, archiveContent, "utf-8");
18789
+ await fs2__default.default.writeFile(archiveFile, archiveContent, "utf-8");
18670
18790
  }
18671
18791
  function generateCompactedFeedback(openIssues, metadata) {
18672
18792
  let content = metadata.trim() + "\n";
@@ -18691,15 +18811,15 @@ async function shouldArchive(feedbackFile, options = {}) {
18691
18811
  // 50KB
18692
18812
  lineCountThreshold = 500
18693
18813
  } = options;
18694
- if (!await fs3__default.default.pathExists(feedbackFile)) {
18814
+ if (!await fs2__default.default.pathExists(feedbackFile)) {
18695
18815
  return {
18696
18816
  shouldArchive: false,
18697
18817
  reasons: [],
18698
18818
  stats: { openIssuesCount: 0, resolvedIssuesCount: 0, fileSizeBytes: 0, lineCount: 0 }
18699
18819
  };
18700
18820
  }
18701
- const content = await fs3__default.default.readFile(feedbackFile, "utf-8");
18702
- const stats = await fs3__default.default.stat(feedbackFile);
18821
+ const content = await fs2__default.default.readFile(feedbackFile, "utf-8");
18822
+ const stats = await fs2__default.default.stat(feedbackFile);
18703
18823
  const parsed = parseUserFeedback(content);
18704
18824
  const lineCount = content.split("\n").length;
18705
18825
  const reasons = [];
@@ -18773,16 +18893,16 @@ var EnhancedFeedbackFileManager = class {
18773
18893
  this.feedbackFile = feedbackFile;
18774
18894
  }
18775
18895
  async ensureExists() {
18776
- if (!await fs3__default.default.pathExists(this.feedbackFile)) {
18896
+ if (!await fs2__default.default.pathExists(this.feedbackFile)) {
18777
18897
  await this.createInitialFile();
18778
18898
  }
18779
18899
  }
18780
18900
  async addFeedback(issue, testCriteria) {
18781
18901
  await this.ensureExists();
18782
18902
  try {
18783
- const content = await fs3__default.default.readFile(this.feedbackFile, "utf-8");
18903
+ const content = await fs2__default.default.readFile(this.feedbackFile, "utf-8");
18784
18904
  const updatedContent = this.addIssueToContent(content, issue, testCriteria);
18785
- await fs3__default.default.writeFile(this.feedbackFile, updatedContent, "utf-8");
18905
+ await fs2__default.default.writeFile(this.feedbackFile, updatedContent, "utf-8");
18786
18906
  } catch (error) {
18787
18907
  throw new ValidationError(
18788
18908
  `Failed to save feedback: ${error}`,
@@ -18795,12 +18915,12 @@ var EnhancedFeedbackFileManager = class {
18795
18915
  */
18796
18916
  async repairMalformedFile() {
18797
18917
  try {
18798
- const content = await fs3__default.default.readFile(this.feedbackFile, "utf-8");
18918
+ const content = await fs2__default.default.readFile(this.feedbackFile, "utf-8");
18799
18919
  const hasOpenIssues = content.includes("<OPEN_ISSUES>");
18800
18920
  const hasClosingTag = content.includes("</OPEN_ISSUES>");
18801
18921
  if (!hasOpenIssues || !hasClosingTag) {
18802
18922
  const backupPath = this.feedbackFile + ".backup." + Date.now();
18803
- await fs3__default.default.writeFile(backupPath, content, "utf-8");
18923
+ await fs2__default.default.writeFile(backupPath, content, "utf-8");
18804
18924
  const existingIssues = this.extractIssuesFromMalformedContent(content);
18805
18925
  await this.createInitialFile(existingIssues);
18806
18926
  }
@@ -18832,8 +18952,8 @@ List any features you'd like to see added or bugs you've encountered.
18832
18952
 
18833
18953
  <!-- Resolved issues will be moved here -->
18834
18954
  `;
18835
- await fs3__default.default.ensureDir(path3__namespace.dirname(this.feedbackFile));
18836
- await fs3__default.default.writeFile(this.feedbackFile, initialContent, "utf-8");
18955
+ await fs2__default.default.ensureDir(path3__namespace.dirname(this.feedbackFile));
18956
+ await fs2__default.default.writeFile(this.feedbackFile, initialContent, "utf-8");
18837
18957
  }
18838
18958
  addIssueToContent(content, issue, testCriteria) {
18839
18959
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -18949,17 +19069,17 @@ async function handleCompactCommand(subArgs, options) {
18949
19069
  if (subArgs.length > 0) {
18950
19070
  for (const filePath of subArgs) {
18951
19071
  const resolvedPath = path3__namespace.resolve(filePath);
18952
- if (await fs3__default.default.pathExists(resolvedPath)) {
19072
+ if (await fs2__default.default.pathExists(resolvedPath)) {
18953
19073
  filesToCompact.push(resolvedPath);
18954
19074
  } else {
18955
19075
  console.warn(chalk15__default.default.yellow(`\u26A0\uFE0F File not found: ${filePath}`));
18956
19076
  }
18957
19077
  }
18958
19078
  } else {
18959
- if (await fs3__default.default.pathExists(defaultClaudeFile)) {
19079
+ if (await fs2__default.default.pathExists(defaultClaudeFile)) {
18960
19080
  filesToCompact.push(defaultClaudeFile);
18961
19081
  }
18962
- if (await fs3__default.default.pathExists(defaultAgentsFile)) {
19082
+ if (await fs2__default.default.pathExists(defaultAgentsFile)) {
18963
19083
  filesToCompact.push(defaultAgentsFile);
18964
19084
  }
18965
19085
  }
@@ -19893,11 +20013,11 @@ var GitManager = class {
19893
20013
  */
19894
20014
  async updateJunoTaskConfig(gitUrl) {
19895
20015
  const configPath = path3__namespace.join(this.workingDirectory, ".juno_task", "init.md");
19896
- if (!await fs3__default.default.pathExists(configPath)) {
20016
+ if (!await fs2__default.default.pathExists(configPath)) {
19897
20017
  return;
19898
20018
  }
19899
20019
  try {
19900
- let content = await fs3__default.default.readFile(configPath, "utf-8");
20020
+ let content = await fs2__default.default.readFile(configPath, "utf-8");
19901
20021
  const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
19902
20022
  if (frontmatterMatch) {
19903
20023
  let frontmatter = frontmatterMatch[1];
@@ -19918,7 +20038,7 @@ GIT_URL: ${gitUrl}
19918
20038
  `;
19919
20039
  content = frontmatter + content;
19920
20040
  }
19921
- await fs3__default.default.writeFile(configPath, content, "utf-8");
20041
+ await fs2__default.default.writeFile(configPath, content, "utf-8");
19922
20042
  } catch (error) {
19923
20043
  console.warn(`Warning: Failed to update juno-code configuration: ${error}`);
19924
20044
  }
@@ -21850,6 +21970,11 @@ var QUICK_REFERENCE = [
21850
21970
  description: "Shell completion setup",
21851
21971
  usage: "juno-code completion <install|uninstall>"
21852
21972
  },
21973
+ {
21974
+ name: "services",
21975
+ description: "Manage service scripts (use --force to refresh codex.py/claude.py)",
21976
+ usage: "juno-code services install --force"
21977
+ },
21853
21978
  {
21854
21979
  name: "help",
21855
21980
  description: "Show help information",
@@ -22418,11 +22543,12 @@ init_service_installer();
22418
22543
  function createServicesCommand() {
22419
22544
  const servicesCmd = new commander.Command("services").description("Manage juno-code service scripts").addHelpText("after", `
22420
22545
  Examples:
22421
- $ juno-code services install Install service scripts to ~/.juno_code/services/
22422
- $ juno-code services list List installed service scripts
22423
- $ juno-code services status Check installation status
22424
- $ juno-code services uninstall Remove all service scripts
22425
- $ juno-code services path Show services directory path
22546
+ $ juno-code services install Install service scripts to ~/.juno_code/services/
22547
+ $ juno-code services install --force Reinstall/refresh service scripts (codex.py/claude.py)
22548
+ $ juno-code services list List installed service scripts
22549
+ $ juno-code services status Check installation status
22550
+ $ juno-code services uninstall Remove all service scripts
22551
+ $ juno-code services path Show services directory path
22426
22552
 
22427
22553
  Service scripts are Python/shell scripts that provide additional functionality
22428
22554
  and can be customized by users. They are installed to ~/.juno_code/services/
@@ -22596,7 +22722,7 @@ var ShellDetector = class _ShellDetector {
22596
22722
  * Get shell configuration file path
22597
22723
  */
22598
22724
  getConfigPath(shell) {
22599
- const homeDir = os3__namespace.homedir();
22725
+ const homeDir = os4__namespace.homedir();
22600
22726
  switch (shell) {
22601
22727
  case "bash":
22602
22728
  if (process.platform === "darwin") {
@@ -22620,7 +22746,7 @@ var ShellDetector = class _ShellDetector {
22620
22746
  * Get shell completion script installation path
22621
22747
  */
22622
22748
  getCompletionPath(shell) {
22623
- const homeDir = os3__namespace.homedir();
22749
+ const homeDir = os4__namespace.homedir();
22624
22750
  switch (shell) {
22625
22751
  case "bash":
22626
22752
  if (process.platform === "darwin") {
@@ -22675,10 +22801,10 @@ autoload -U compinit && compinit`;
22675
22801
  */
22676
22802
  async isSourceCommandPresent(configPath, sourceCommand) {
22677
22803
  try {
22678
- if (!await fs3__default.default.pathExists(configPath)) {
22804
+ if (!await fs2__default.default.pathExists(configPath)) {
22679
22805
  return false;
22680
22806
  }
22681
- const content = await fs3__default.default.readFile(configPath, "utf-8");
22807
+ const content = await fs2__default.default.readFile(configPath, "utf-8");
22682
22808
  return content.includes("juno-code completion");
22683
22809
  } catch {
22684
22810
  return false;
@@ -22700,15 +22826,15 @@ autoload -U compinit && compinit`;
22700
22826
  continue;
22701
22827
  }
22702
22828
  try {
22703
- const completionExists = await fs3__default.default.pathExists(shell.completionPath);
22704
- const configExists = await fs3__default.default.pathExists(shell.configPath);
22829
+ const completionExists = await fs2__default.default.pathExists(shell.completionPath);
22830
+ const configExists = await fs2__default.default.pathExists(shell.configPath);
22705
22831
  const isSourced = configExists && await this.isSourceCommandPresent(
22706
22832
  shell.configPath,
22707
22833
  this.getSourceCommand(shell.name, shell.completionPath)
22708
22834
  );
22709
22835
  let lastInstalled;
22710
22836
  if (completionExists) {
22711
- const stats = await fs3__default.default.stat(shell.completionPath);
22837
+ const stats = await fs2__default.default.stat(shell.completionPath);
22712
22838
  lastInstalled = stats.mtime;
22713
22839
  }
22714
22840
  statuses.push({
@@ -22734,7 +22860,7 @@ autoload -U compinit && compinit`;
22734
22860
  async ensureCompletionDirectory(shell) {
22735
22861
  const completionPath = this.getCompletionPath(shell);
22736
22862
  const completionDir = path3__namespace.dirname(completionPath);
22737
- await fs3__default.default.ensureDir(completionDir);
22863
+ await fs2__default.default.ensureDir(completionDir);
22738
22864
  }
22739
22865
  /**
22740
22866
  * Ensure directory exists for shell configuration
@@ -22742,7 +22868,7 @@ autoload -U compinit && compinit`;
22742
22868
  async ensureConfigDirectory(shell) {
22743
22869
  const configPath = this.getConfigPath(shell);
22744
22870
  const configDir = path3__namespace.dirname(configPath);
22745
- await fs3__default.default.ensureDir(configDir);
22871
+ await fs2__default.default.ensureDir(configDir);
22746
22872
  }
22747
22873
  /**
22748
22874
  * Get shell version information
@@ -22766,15 +22892,15 @@ autoload -U compinit && compinit`;
22766
22892
  try {
22767
22893
  const configPath = this.getConfigPath(shell);
22768
22894
  const configDir = path3__namespace.dirname(configPath);
22769
- await fs3__default.default.access(configDir, fs3__default.default.constants.W_OK);
22895
+ await fs2__default.default.access(configDir, fs2__default.default.constants.W_OK);
22770
22896
  } catch {
22771
22897
  issues.push(`Cannot write to ${shell} configuration directory`);
22772
22898
  }
22773
22899
  try {
22774
22900
  const completionPath = this.getCompletionPath(shell);
22775
22901
  const completionDir = path3__namespace.dirname(completionPath);
22776
- await fs3__default.default.ensureDir(completionDir);
22777
- await fs3__default.default.access(completionDir, fs3__default.default.constants.W_OK);
22902
+ await fs2__default.default.ensureDir(completionDir);
22903
+ await fs2__default.default.access(completionDir, fs2__default.default.constants.W_OK);
22778
22904
  } catch {
22779
22905
  issues.push(`Cannot write to ${shell} completion directory`);
22780
22906
  }
@@ -22845,10 +22971,10 @@ var ContextAwareCompletion = class {
22845
22971
  async getSessionIds() {
22846
22972
  try {
22847
22973
  const sessionDir = path3__namespace.join(process.cwd(), ".juno_task", "sessions");
22848
- if (!await fs3__default.default.pathExists(sessionDir)) {
22974
+ if (!await fs2__default.default.pathExists(sessionDir)) {
22849
22975
  return [];
22850
22976
  }
22851
- const sessions = await fs3__default.default.readdir(sessionDir);
22977
+ const sessions = await fs2__default.default.readdir(sessionDir);
22852
22978
  return sessions.filter((name) => name.match(/^session_\d+$/)).map((name) => name.replace("session_", "")).sort((a, b) => parseInt(b) - parseInt(a));
22853
22979
  } catch {
22854
22980
  return [];
@@ -22862,8 +22988,8 @@ var ContextAwareCompletion = class {
22862
22988
  const builtinTemplates = ["basic", "advanced", "research", "development"];
22863
22989
  const customTemplatesDir = path3__namespace.join(process.cwd(), ".juno_task", "templates");
22864
22990
  let customTemplates = [];
22865
- if (await fs3__default.default.pathExists(customTemplatesDir)) {
22866
- const files = await fs3__default.default.readdir(customTemplatesDir);
22991
+ if (await fs2__default.default.pathExists(customTemplatesDir)) {
22992
+ const files = await fs2__default.default.readdir(customTemplatesDir);
22867
22993
  customTemplates = files.filter((name) => name.endsWith(".md") || name.endsWith(".hbs")).map((name) => path3__namespace.basename(name, path3__namespace.extname(name)));
22868
22994
  }
22869
22995
  return [...builtinTemplates, ...customTemplates].sort();
@@ -22898,7 +23024,7 @@ var ContextAwareCompletion = class {
22898
23024
  */
22899
23025
  expandPath(inputPath) {
22900
23026
  if (inputPath.startsWith("~/")) {
22901
- return path3__namespace.join(os3__namespace.homedir(), inputPath.slice(2));
23027
+ return path3__namespace.join(os4__namespace.homedir(), inputPath.slice(2));
22902
23028
  }
22903
23029
  if (inputPath.startsWith("./") || inputPath.startsWith("../")) {
22904
23030
  return path3__namespace.resolve(inputPath);
@@ -22940,7 +23066,7 @@ var CompletionInstaller = class {
22940
23066
  await this.shellDetector.ensureConfigDirectory(shell);
22941
23067
  const script = this.generateEnhancedCompletion(shell, "juno-code");
22942
23068
  const completionPath = this.shellDetector.getCompletionPath(shell);
22943
- await fs3__default.default.writeFile(completionPath, script, "utf-8");
23069
+ await fs2__default.default.writeFile(completionPath, script, "utf-8");
22944
23070
  const configPath = this.shellDetector.getConfigPath(shell);
22945
23071
  const sourceCommand = this.shellDetector.getSourceCommand(shell, completionPath);
22946
23072
  const warnings = [];
@@ -22948,7 +23074,7 @@ var CompletionInstaller = class {
22948
23074
  const isPresent = await this.shellDetector.isSourceCommandPresent(configPath, sourceCommand);
22949
23075
  if (!isPresent) {
22950
23076
  try {
22951
- await fs3__default.default.appendFile(configPath, `
23077
+ await fs2__default.default.appendFile(configPath, `
22952
23078
 
22953
23079
  ${sourceCommand}
22954
23080
  `);
@@ -22979,8 +23105,8 @@ ${sourceCommand}
22979
23105
  async uninstall(shell) {
22980
23106
  try {
22981
23107
  const completionPath = this.shellDetector.getCompletionPath(shell);
22982
- if (await fs3__default.default.pathExists(completionPath)) {
22983
- await fs3__default.default.remove(completionPath);
23108
+ if (await fs2__default.default.pathExists(completionPath)) {
23109
+ await fs2__default.default.remove(completionPath);
22984
23110
  return true;
22985
23111
  }
22986
23112
  return false;
@@ -22994,7 +23120,7 @@ ${sourceCommand}
22994
23120
  async isInstalled(shell) {
22995
23121
  try {
22996
23122
  const completionPath = this.shellDetector.getCompletionPath(shell);
22997
- return await fs3__default.default.pathExists(completionPath);
23123
+ return await fs2__default.default.pathExists(completionPath);
22998
23124
  } catch {
22999
23125
  return false;
23000
23126
  }