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.js +201 -143
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/cli.mjs +200 -142
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/index.js +32 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +32 -3
- package/dist/index.mjs.map +1 -1
- package/dist/templates/services/__pycache__/codex.cpython-38.pyc +0 -0
- package/dist/templates/services/claude.py +14 -0
- package/dist/templates/services/codex.py +254 -16
- package/package.json +1 -1
package/dist/bin/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
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 (
|
|
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 (
|
|
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
|
|
337
|
+
const exists = await fs2.pathExists(this.VERSION_FILE);
|
|
338
338
|
if (!exists) {
|
|
339
339
|
return null;
|
|
340
340
|
}
|
|
341
|
-
const version3 = await
|
|
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
|
|
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
|
|
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
|
|
373
|
-
const
|
|
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
|
|
382
|
-
const packageClaudeExists = await
|
|
383
|
-
if (packageCodexExists
|
|
384
|
-
const
|
|
385
|
-
|
|
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 (
|
|
422
|
+
if (fs2.existsSync(servicesPath)) {
|
|
404
423
|
return servicesPath;
|
|
405
424
|
}
|
|
406
425
|
servicesPath = path3.join(__dirname2, "..", "templates", "services");
|
|
407
|
-
if (
|
|
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
|
|
437
|
+
await fs2.ensureDir(this.SERVICES_DIR);
|
|
419
438
|
const packageServicesDir = this.getPackageServicesDir();
|
|
420
|
-
await
|
|
439
|
+
await fs2.copy(packageServicesDir, this.SERVICES_DIR, {
|
|
421
440
|
overwrite: true,
|
|
422
441
|
preserveTimestamps: true
|
|
423
442
|
});
|
|
424
|
-
const files = await
|
|
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
|
|
446
|
+
const stat = await fs2.stat(filePath);
|
|
428
447
|
if (stat.isFile() && (file.endsWith(".py") || file.endsWith(".sh"))) {
|
|
429
|
-
await
|
|
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
|
|
495
|
+
const exists = await fs2.pathExists(this.SERVICES_DIR);
|
|
477
496
|
if (!exists) {
|
|
478
497
|
return false;
|
|
479
498
|
}
|
|
480
|
-
const files = await
|
|
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
|
|
522
|
+
const exists = await fs2.pathExists(this.SERVICES_DIR);
|
|
504
523
|
if (!exists) {
|
|
505
524
|
return [];
|
|
506
525
|
}
|
|
507
|
-
const files = await
|
|
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
|
|
537
|
+
const exists = await fs2.pathExists(this.SERVICES_DIR);
|
|
519
538
|
if (exists) {
|
|
520
|
-
await
|
|
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
|
|
1097
|
-
const configExists = await
|
|
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
|
|
1123
|
+
await fs2.writeJson(configPath, defaultConfig, { spaces: 2 });
|
|
1105
1124
|
} else {
|
|
1106
|
-
const existingConfig = await
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
15196
|
+
await fs2.copy(targetPath, backupPath);
|
|
15141
15197
|
}
|
|
15142
|
-
await
|
|
15143
|
-
await
|
|
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
|
|
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
|
|
15508
|
+
await fs2.ensureDir(targetDirectory);
|
|
15453
15509
|
const junoTaskDir = path3.join(targetDirectory, ".juno_task");
|
|
15454
|
-
const junoTaskExists = await
|
|
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
|
|
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
|
|
15496
|
-
await
|
|
15497
|
-
await
|
|
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
|
|
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
|
|
15562
|
+
await fs2.writeFile(path3.join(junoTaskDir, "plan.md"), planContent);
|
|
15507
15563
|
}
|
|
15508
15564
|
const specsDir = path3.join(junoTaskDir, "specs");
|
|
15509
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
16093
|
+
const stats = await fs2.stat(sourcePath);
|
|
16038
16094
|
if (stats.isFile()) {
|
|
16039
|
-
await
|
|
16095
|
+
await fs2.copy(sourcePath, destPath);
|
|
16040
16096
|
if (scriptFile.endsWith(".sh")) {
|
|
16041
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
17405
|
-
await
|
|
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
|
|
17658
|
-
const coverageData = await
|
|
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
|
|
17842
|
-
await
|
|
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
|
|
17906
|
-
await
|
|
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
|
|
17964
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
18538
|
+
if (!await fs2.pathExists(feedbackFile)) {
|
|
18481
18539
|
throw new Error(`Feedback file does not exist: ${feedbackFile}`);
|
|
18482
18540
|
}
|
|
18483
|
-
const content = await
|
|
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
|
|
18548
|
+
await fs2.ensureDir(path3.dirname(logFile));
|
|
18491
18549
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
18492
|
-
await
|
|
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
|
|
18567
|
+
await fs2.ensureDir(archiveDir);
|
|
18510
18568
|
await appendToArchive(archiveFile, parsed.resolvedIssues);
|
|
18511
18569
|
const compactedContent = generateCompactedFeedback(parsed.openIssues, parsed.metadata);
|
|
18512
|
-
await
|
|
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
|
|
18560
|
-
archiveContent = await
|
|
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
|
|
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
|
|
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
|
|
18627
|
-
const stats = await
|
|
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
|
|
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
|
|
18766
|
+
const content = await fs2.readFile(this.feedbackFile, "utf-8");
|
|
18709
18767
|
const updatedContent = this.addIssueToContent(content, issue, testCriteria);
|
|
18710
|
-
await
|
|
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
|
|
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
|
|
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
|
|
18761
|
-
await
|
|
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
|
|
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
|
|
18942
|
+
if (await fs2.pathExists(defaultClaudeFile)) {
|
|
18885
18943
|
filesToCompact.push(defaultClaudeFile);
|
|
18886
18944
|
}
|
|
18887
|
-
if (await
|
|
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
|
|
19879
|
+
if (!await fs2.pathExists(configPath)) {
|
|
19822
19880
|
return;
|
|
19823
19881
|
}
|
|
19824
19882
|
try {
|
|
19825
|
-
let content = await
|
|
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
|
|
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
|
|
22661
|
+
if (!await fs2.pathExists(configPath)) {
|
|
22604
22662
|
return false;
|
|
22605
22663
|
}
|
|
22606
|
-
const content = await
|
|
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
|
|
22629
|
-
const configExists = await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
22702
|
-
await
|
|
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
|
|
22831
|
+
if (!await fs2.pathExists(sessionDir)) {
|
|
22774
22832
|
return [];
|
|
22775
22833
|
}
|
|
22776
|
-
const sessions = await
|
|
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
|
|
22791
|
-
const files = await
|
|
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
|
|
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
|
|
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
|
|
22908
|
-
await
|
|
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
|
|
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);
|