juno-code 1.0.51 → 1.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/dist/bin/cli.js +678 -82
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/cli.mjs +675 -79
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +369 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +367 -56
- package/dist/index.mjs.map +1 -1
- package/dist/templates/scripts/__pycache__/parallel_runner.cpython-313.pyc +0 -0
- package/dist/templates/scripts/install_requirements.sh +21 -0
- package/dist/templates/scripts/kanban.sh +6 -2
- package/dist/templates/scripts/parallel_runner.sh +602 -131
- package/dist/templates/services/__pycache__/pi.cpython-313.pyc +0 -0
- package/dist/templates/services/__pycache__/pi.cpython-38.pyc +0 -0
- package/dist/templates/services/pi.py +418 -51
- package/dist/templates/skills/claude/ralph-loop/scripts/kanban.sh +6 -2
- package/dist/templates/skills/codex/ralph-loop/scripts/kanban.sh +6 -2
- package/package.json +1 -1
package/dist/bin/cli.mjs
CHANGED
|
@@ -14,9 +14,10 @@ import * as yaml from 'js-yaml';
|
|
|
14
14
|
import { createHash } from 'crypto';
|
|
15
15
|
import chalk21 from 'chalk';
|
|
16
16
|
import { execa } from 'execa';
|
|
17
|
+
import * as childProcess from 'child_process';
|
|
17
18
|
import { spawn } from 'child_process';
|
|
19
|
+
import { inspect, promisify } from 'util';
|
|
18
20
|
import { EventEmitter } from 'events';
|
|
19
|
-
import { inspect } from 'util';
|
|
20
21
|
import { Command, Option } from 'commander';
|
|
21
22
|
import * as readline from 'readline';
|
|
22
23
|
import { createInterface } from 'readline';
|
|
@@ -259,14 +260,14 @@ function isModelCompatibleWithSubagent(model, subagent) {
|
|
|
259
260
|
}
|
|
260
261
|
}
|
|
261
262
|
function getConfiguredDefaultModelForSubagent(config, subagent) {
|
|
262
|
-
const legacyDefaultModel = config.defaultSubagent === subagent && typeof config.defaultModel === "string" && isModelCompatibleWithSubagent(config.defaultModel, subagent) ? config.defaultModel : void 0;
|
|
263
|
-
if (legacyDefaultModel) {
|
|
264
|
-
return legacyDefaultModel;
|
|
265
|
-
}
|
|
266
263
|
const modelFromMap = config.defaultModels?.[subagent];
|
|
267
264
|
if (typeof modelFromMap === "string" && isModelCompatibleWithSubagent(modelFromMap, subagent)) {
|
|
268
265
|
return modelFromMap;
|
|
269
266
|
}
|
|
267
|
+
const legacyDefaultModel = config.defaultSubagent === subagent && typeof config.defaultModel === "string" && isModelCompatibleWithSubagent(config.defaultModel, subagent) ? config.defaultModel : void 0;
|
|
268
|
+
if (legacyDefaultModel) {
|
|
269
|
+
return legacyDefaultModel;
|
|
270
|
+
}
|
|
270
271
|
return void 0;
|
|
271
272
|
}
|
|
272
273
|
var SUBAGENT_DEFAULT_MODELS;
|
|
@@ -834,6 +835,13 @@ async function ensureHooksConfig(baseDir) {
|
|
|
834
835
|
existingConfig.defaultModels = baseDefaults;
|
|
835
836
|
needsUpdate = true;
|
|
836
837
|
}
|
|
838
|
+
const selectedSubagentRaw = typeof existingConfig.defaultSubagent === "string" ? existingConfig.defaultSubagent : "claude";
|
|
839
|
+
const selectedSubagent = selectedSubagentRaw in SUBAGENT_DEFAULT_MODELS ? selectedSubagentRaw : "claude";
|
|
840
|
+
const selectedMapModel = existingConfig.defaultModels && typeof existingConfig.defaultModels === "object" ? existingConfig.defaultModels[selectedSubagent] : void 0;
|
|
841
|
+
if (typeof selectedMapModel === "string" && isModelCompatibleWithSubagent(selectedMapModel, selectedSubagent) && existingConfig.defaultModel !== selectedMapModel) {
|
|
842
|
+
existingConfig.defaultModel = selectedMapModel;
|
|
843
|
+
needsUpdate = true;
|
|
844
|
+
}
|
|
837
845
|
if (existingConfig.defaultMaxIterations === 50) {
|
|
838
846
|
existingConfig.defaultMaxIterations = DEFAULT_CONFIG.defaultMaxIterations;
|
|
839
847
|
needsUpdate = true;
|
|
@@ -2358,25 +2366,28 @@ var init_shell_backend = __esm({
|
|
|
2358
2366
|
const scriptPath = await this.findScriptForSubagent(subagentType);
|
|
2359
2367
|
const result = await this.executeScript(scriptPath, request, toolId, subagentType);
|
|
2360
2368
|
const duration = Date.now() - startTime;
|
|
2369
|
+
const structuredResult = this.buildStructuredOutput(subagentType, result);
|
|
2370
|
+
const structuredPayload = this.parseStructuredResultPayload(structuredResult.content);
|
|
2371
|
+
const structuredIndicatesError = structuredPayload?.is_error === true || structuredPayload?.subtype === "error";
|
|
2372
|
+
const executionSucceeded = result.success && !structuredIndicatesError;
|
|
2361
2373
|
await this.emitProgressEvent({
|
|
2362
2374
|
sessionId: request.metadata?.sessionId || "unknown",
|
|
2363
2375
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2364
2376
|
backend: "shell",
|
|
2365
2377
|
count: ++this.eventCounter,
|
|
2366
2378
|
type: "tool_result" /* TOOL_RESULT */,
|
|
2367
|
-
content: `${request.toolName} completed successfully (${duration}ms)`,
|
|
2379
|
+
content: executionSucceeded ? `${request.toolName} completed successfully (${duration}ms)` : `${request.toolName} completed with error (${duration}ms)`,
|
|
2368
2380
|
toolId,
|
|
2369
2381
|
metadata: {
|
|
2370
2382
|
toolName: request.toolName,
|
|
2371
2383
|
duration,
|
|
2372
|
-
success:
|
|
2384
|
+
success: executionSucceeded,
|
|
2373
2385
|
phase: "completion"
|
|
2374
2386
|
}
|
|
2375
2387
|
});
|
|
2376
|
-
const structuredResult = this.buildStructuredOutput(subagentType, result);
|
|
2377
2388
|
const toolResult = {
|
|
2378
2389
|
content: structuredResult.content,
|
|
2379
|
-
status:
|
|
2390
|
+
status: executionSucceeded ? "completed" /* COMPLETED */ : "failed" /* FAILED */,
|
|
2380
2391
|
startTime: new Date(startTime),
|
|
2381
2392
|
endTime: /* @__PURE__ */ new Date(),
|
|
2382
2393
|
duration,
|
|
@@ -2385,6 +2396,9 @@ var init_shell_backend = __esm({
|
|
|
2385
2396
|
};
|
|
2386
2397
|
if (result.error) {
|
|
2387
2398
|
toolResult.error = new Error(result.error);
|
|
2399
|
+
} else if (!executionSucceeded) {
|
|
2400
|
+
const structuredErrorMessage = typeof structuredPayload?.error === "string" && structuredPayload.error || typeof structuredPayload?.result === "string" && structuredPayload.result || `${request.toolName} reported a structured error`;
|
|
2401
|
+
toolResult.error = new Error(structuredErrorMessage);
|
|
2388
2402
|
}
|
|
2389
2403
|
if (structuredResult.metadata) {
|
|
2390
2404
|
toolResult.metadata = structuredResult.metadata;
|
|
@@ -2636,6 +2650,9 @@ var init_shell_backend = __esm({
|
|
|
2636
2650
|
if (isPython && subagentType === "pi" && request.arguments?.live === true) {
|
|
2637
2651
|
args.push("--live");
|
|
2638
2652
|
}
|
|
2653
|
+
if (isPython && subagentType === "pi" && request.arguments?.liveInteractiveSession === true) {
|
|
2654
|
+
args.push("--live-manual");
|
|
2655
|
+
}
|
|
2639
2656
|
if (isPython && this.config.debug) {
|
|
2640
2657
|
args.push("--verbose");
|
|
2641
2658
|
}
|
|
@@ -2918,8 +2935,19 @@ var init_shell_backend = __esm({
|
|
|
2918
2935
|
if (subagentType === "pi") {
|
|
2919
2936
|
const piEvent = result.subAgentResponse ?? this.extractLastJsonEvent(result.output);
|
|
2920
2937
|
if (piEvent) {
|
|
2921
|
-
|
|
2922
|
-
|
|
2938
|
+
const piNestedEvent = typeof piEvent.sub_agent_response === "object" && piEvent.sub_agent_response ? piEvent.sub_agent_response : void 0;
|
|
2939
|
+
const piSessionId = typeof piEvent.session_id === "string" && piEvent.session_id ? piEvent.session_id : typeof piEvent.sessionId === "string" && piEvent.sessionId ? piEvent.sessionId : typeof piEvent.id === "string" && piEvent.type === "session" ? piEvent.id : typeof piNestedEvent?.session_id === "string" && piNestedEvent.session_id ? piNestedEvent.session_id : typeof piNestedEvent?.sessionId === "string" && piNestedEvent.sessionId ? piNestedEvent.sessionId : typeof piNestedEvent?.id === "string" && piNestedEvent.type === "session" ? piNestedEvent.id : typeof piEvent.sub_agent_response?.session_id === "string" && piEvent.sub_agent_response.session_id ? piEvent.sub_agent_response.session_id : void 0;
|
|
2940
|
+
const sanitizedPiEvent = { ...piEvent };
|
|
2941
|
+
delete sanitizedPiEvent.messages;
|
|
2942
|
+
if (sanitizedPiEvent.sub_agent_response && typeof sanitizedPiEvent.sub_agent_response === "object") {
|
|
2943
|
+
const inner = { ...sanitizedPiEvent.sub_agent_response };
|
|
2944
|
+
delete inner.messages;
|
|
2945
|
+
delete inner.type;
|
|
2946
|
+
sanitizedPiEvent.sub_agent_response = inner;
|
|
2947
|
+
}
|
|
2948
|
+
const hasDirectResultText = typeof piEvent.result === "string";
|
|
2949
|
+
let resultText = hasDirectResultText ? piEvent.result : void 0;
|
|
2950
|
+
if (resultText === void 0 && Array.isArray(piEvent.messages)) {
|
|
2923
2951
|
for (let i = piEvent.messages.length - 1; i >= 0; i--) {
|
|
2924
2952
|
const msg = piEvent.messages[i];
|
|
2925
2953
|
if (msg?.role === "assistant") {
|
|
@@ -2939,16 +2967,11 @@ var init_shell_backend = __esm({
|
|
|
2939
2967
|
}
|
|
2940
2968
|
}
|
|
2941
2969
|
}
|
|
2942
|
-
if (resultText) {
|
|
2970
|
+
if (resultText === void 0 && typeof piEvent.error === "string") {
|
|
2971
|
+
resultText = piEvent.error;
|
|
2972
|
+
}
|
|
2973
|
+
if (resultText !== void 0) {
|
|
2943
2974
|
const isError = piEvent.is_error ?? !result.success;
|
|
2944
|
-
const sanitizedPiEvent = { ...piEvent };
|
|
2945
|
-
delete sanitizedPiEvent.messages;
|
|
2946
|
-
if (sanitizedPiEvent.sub_agent_response && typeof sanitizedPiEvent.sub_agent_response === "object") {
|
|
2947
|
-
const inner = { ...sanitizedPiEvent.sub_agent_response };
|
|
2948
|
-
delete inner.messages;
|
|
2949
|
-
delete inner.type;
|
|
2950
|
-
sanitizedPiEvent.sub_agent_response = inner;
|
|
2951
|
-
}
|
|
2952
2975
|
const usage = piEvent.usage;
|
|
2953
2976
|
const totalCostUsd = typeof piEvent.total_cost_usd === "number" ? piEvent.total_cost_usd : typeof usage?.cost?.total === "number" ? usage.cost.total : void 0;
|
|
2954
2977
|
const structuredPayload = {
|
|
@@ -2956,9 +2979,9 @@ var init_shell_backend = __esm({
|
|
|
2956
2979
|
subtype: piEvent.subtype || (isError ? "error" : "success"),
|
|
2957
2980
|
is_error: isError,
|
|
2958
2981
|
result: resultText,
|
|
2959
|
-
error: piEvent.error,
|
|
2982
|
+
error: isError ? piEvent.error ?? result.error ?? resultText : piEvent.error,
|
|
2960
2983
|
stderr: result.error,
|
|
2961
|
-
session_id:
|
|
2984
|
+
session_id: piSessionId,
|
|
2962
2985
|
exit_code: result.exitCode,
|
|
2963
2986
|
duration_ms: piEvent.duration_ms ?? result.duration,
|
|
2964
2987
|
total_cost_usd: totalCostUsd,
|
|
@@ -2976,6 +2999,57 @@ var init_shell_backend = __esm({
|
|
|
2976
2999
|
metadata
|
|
2977
3000
|
};
|
|
2978
3001
|
}
|
|
3002
|
+
const isSessionSnapshotOnly = piEvent.type === "session" || piEvent.subtype === "session";
|
|
3003
|
+
if (isSessionSnapshotOnly) {
|
|
3004
|
+
const errorMessage = result.error?.trim() || "Pi exited before emitting a terminal result event (session snapshot only).";
|
|
3005
|
+
const structuredPayload = {
|
|
3006
|
+
type: "result",
|
|
3007
|
+
subtype: "error",
|
|
3008
|
+
is_error: true,
|
|
3009
|
+
result: errorMessage,
|
|
3010
|
+
error: errorMessage,
|
|
3011
|
+
stderr: result.error,
|
|
3012
|
+
session_id: piSessionId,
|
|
3013
|
+
exit_code: result.exitCode,
|
|
3014
|
+
duration_ms: result.duration,
|
|
3015
|
+
sub_agent_response: sanitizedPiEvent
|
|
3016
|
+
};
|
|
3017
|
+
const metadata = {
|
|
3018
|
+
...piEvent ? { subAgentResponse: piEvent } : void 0,
|
|
3019
|
+
structuredOutput: true,
|
|
3020
|
+
contentType: "application/json",
|
|
3021
|
+
rawOutput: result.output
|
|
3022
|
+
};
|
|
3023
|
+
return {
|
|
3024
|
+
content: JSON.stringify(structuredPayload),
|
|
3025
|
+
metadata
|
|
3026
|
+
};
|
|
3027
|
+
}
|
|
3028
|
+
if (!result.success) {
|
|
3029
|
+
const errorMessage = result.error?.trim() || result.output?.trim() || "Unknown error";
|
|
3030
|
+
const structuredPayload = {
|
|
3031
|
+
type: "result",
|
|
3032
|
+
subtype: "error",
|
|
3033
|
+
is_error: true,
|
|
3034
|
+
result: errorMessage,
|
|
3035
|
+
error: errorMessage,
|
|
3036
|
+
stderr: result.error,
|
|
3037
|
+
session_id: piSessionId,
|
|
3038
|
+
exit_code: result.exitCode,
|
|
3039
|
+
duration_ms: result.duration,
|
|
3040
|
+
sub_agent_response: sanitizedPiEvent
|
|
3041
|
+
};
|
|
3042
|
+
const metadata = {
|
|
3043
|
+
...piEvent ? { subAgentResponse: piEvent } : void 0,
|
|
3044
|
+
structuredOutput: true,
|
|
3045
|
+
contentType: "application/json",
|
|
3046
|
+
rawOutput: result.output
|
|
3047
|
+
};
|
|
3048
|
+
return {
|
|
3049
|
+
content: JSON.stringify(structuredPayload),
|
|
3050
|
+
metadata
|
|
3051
|
+
};
|
|
3052
|
+
}
|
|
2979
3053
|
}
|
|
2980
3054
|
}
|
|
2981
3055
|
if (!result.success) {
|
|
@@ -3040,6 +3114,20 @@ var init_shell_backend = __esm({
|
|
|
3040
3114
|
}
|
|
3041
3115
|
return null;
|
|
3042
3116
|
}
|
|
3117
|
+
/**
|
|
3118
|
+
* Parse JSON structured output payload emitted by shell service wrappers.
|
|
3119
|
+
*/
|
|
3120
|
+
parseStructuredResultPayload(content) {
|
|
3121
|
+
try {
|
|
3122
|
+
const parsed = JSON.parse(content);
|
|
3123
|
+
if (!parsed || typeof parsed !== "object") {
|
|
3124
|
+
return null;
|
|
3125
|
+
}
|
|
3126
|
+
return parsed;
|
|
3127
|
+
} catch {
|
|
3128
|
+
return null;
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3043
3131
|
/**
|
|
3044
3132
|
* Extract the last valid JSON object from a script's stdout to use as a structured payload fallback.
|
|
3045
3133
|
*/
|
|
@@ -3298,6 +3386,179 @@ var init_shell_backend = __esm({
|
|
|
3298
3386
|
};
|
|
3299
3387
|
}
|
|
3300
3388
|
});
|
|
3389
|
+
function findPromptCommandSubstitutions(prompt) {
|
|
3390
|
+
const matches = [];
|
|
3391
|
+
let cursor = 0;
|
|
3392
|
+
while (cursor < prompt.length) {
|
|
3393
|
+
const singleQuotedStart = prompt.indexOf(SINGLE_QUOTED_MARKER, cursor);
|
|
3394
|
+
const tripleBacktickStart = prompt.indexOf(TRIPLE_BACKTICK_MARKER, cursor);
|
|
3395
|
+
const markerStart = chooseNearestMarker(singleQuotedStart, tripleBacktickStart);
|
|
3396
|
+
if (markerStart === null) {
|
|
3397
|
+
break;
|
|
3398
|
+
}
|
|
3399
|
+
if (markerStart === singleQuotedStart) {
|
|
3400
|
+
const parsedSingleQuoted = parseSingleQuotedSubstitution(prompt, markerStart);
|
|
3401
|
+
if (!parsedSingleQuoted) {
|
|
3402
|
+
cursor = markerStart + SINGLE_QUOTED_MARKER.length;
|
|
3403
|
+
continue;
|
|
3404
|
+
}
|
|
3405
|
+
matches.push(parsedSingleQuoted);
|
|
3406
|
+
cursor = parsedSingleQuoted.endIndex;
|
|
3407
|
+
continue;
|
|
3408
|
+
}
|
|
3409
|
+
const parsedTripleBacktick = parseTripleBacktickSubstitution(prompt, markerStart);
|
|
3410
|
+
if (!parsedTripleBacktick) {
|
|
3411
|
+
cursor = markerStart + TRIPLE_BACKTICK_MARKER.length;
|
|
3412
|
+
continue;
|
|
3413
|
+
}
|
|
3414
|
+
matches.push(parsedTripleBacktick);
|
|
3415
|
+
cursor = parsedTripleBacktick.endIndex;
|
|
3416
|
+
}
|
|
3417
|
+
return matches;
|
|
3418
|
+
}
|
|
3419
|
+
async function resolvePromptCommandSubstitutions(prompt, options) {
|
|
3420
|
+
const matches = findPromptCommandSubstitutions(prompt);
|
|
3421
|
+
if (matches.length === 0) {
|
|
3422
|
+
return prompt;
|
|
3423
|
+
}
|
|
3424
|
+
const executor = options.executor ?? createDefaultPromptCommandExecutor(options);
|
|
3425
|
+
let result = "";
|
|
3426
|
+
let cursor = 0;
|
|
3427
|
+
for (const match of matches) {
|
|
3428
|
+
result += prompt.slice(cursor, match.startIndex);
|
|
3429
|
+
const commandOutput = await executor(match.command);
|
|
3430
|
+
result += normalizeCommandOutput(commandOutput);
|
|
3431
|
+
cursor = match.endIndex;
|
|
3432
|
+
}
|
|
3433
|
+
result += prompt.slice(cursor);
|
|
3434
|
+
return result;
|
|
3435
|
+
}
|
|
3436
|
+
function chooseNearestMarker(singleQuotedStart, tripleBacktickStart) {
|
|
3437
|
+
const singleExists = singleQuotedStart >= 0;
|
|
3438
|
+
const tripleExists = tripleBacktickStart >= 0;
|
|
3439
|
+
if (!singleExists && !tripleExists) {
|
|
3440
|
+
return null;
|
|
3441
|
+
}
|
|
3442
|
+
if (!singleExists) {
|
|
3443
|
+
return tripleBacktickStart;
|
|
3444
|
+
}
|
|
3445
|
+
if (!tripleExists) {
|
|
3446
|
+
return singleQuotedStart;
|
|
3447
|
+
}
|
|
3448
|
+
return Math.min(singleQuotedStart, tripleBacktickStart);
|
|
3449
|
+
}
|
|
3450
|
+
function parseSingleQuotedSubstitution(prompt, markerStart) {
|
|
3451
|
+
const contentStart = markerStart + SINGLE_QUOTED_MARKER.length;
|
|
3452
|
+
const closingQuote = findClosingSingleQuote(prompt, contentStart);
|
|
3453
|
+
if (closingQuote < 0) {
|
|
3454
|
+
return null;
|
|
3455
|
+
}
|
|
3456
|
+
const raw = prompt.slice(markerStart, closingQuote + 1);
|
|
3457
|
+
const command = prompt.slice(contentStart, closingQuote);
|
|
3458
|
+
return {
|
|
3459
|
+
syntax: "single-quoted",
|
|
3460
|
+
startIndex: markerStart,
|
|
3461
|
+
endIndex: closingQuote + 1,
|
|
3462
|
+
command,
|
|
3463
|
+
raw
|
|
3464
|
+
};
|
|
3465
|
+
}
|
|
3466
|
+
function findClosingSingleQuote(prompt, startIndex) {
|
|
3467
|
+
let escaped = false;
|
|
3468
|
+
for (let index = startIndex; index < prompt.length; index++) {
|
|
3469
|
+
const char = prompt[index];
|
|
3470
|
+
if (char === "'" && !escaped) {
|
|
3471
|
+
return index;
|
|
3472
|
+
}
|
|
3473
|
+
if (char === "\\" && !escaped) {
|
|
3474
|
+
escaped = true;
|
|
3475
|
+
continue;
|
|
3476
|
+
}
|
|
3477
|
+
escaped = false;
|
|
3478
|
+
}
|
|
3479
|
+
return -1;
|
|
3480
|
+
}
|
|
3481
|
+
function parseTripleBacktickSubstitution(prompt, markerStart) {
|
|
3482
|
+
const contentStart = markerStart + TRIPLE_BACKTICK_MARKER.length;
|
|
3483
|
+
const closingBackticks = prompt.indexOf(TRIPLE_BACKTICK_CLOSER, contentStart);
|
|
3484
|
+
if (closingBackticks < 0) {
|
|
3485
|
+
return null;
|
|
3486
|
+
}
|
|
3487
|
+
const raw = prompt.slice(markerStart, closingBackticks + TRIPLE_BACKTICK_CLOSER.length);
|
|
3488
|
+
const command = prompt.slice(contentStart, closingBackticks);
|
|
3489
|
+
return {
|
|
3490
|
+
syntax: "triple-backtick",
|
|
3491
|
+
startIndex: markerStart,
|
|
3492
|
+
endIndex: closingBackticks + TRIPLE_BACKTICK_CLOSER.length,
|
|
3493
|
+
command,
|
|
3494
|
+
raw
|
|
3495
|
+
};
|
|
3496
|
+
}
|
|
3497
|
+
function createDefaultPromptCommandExecutor(options) {
|
|
3498
|
+
const execFile3 = promisify(childProcess.execFile);
|
|
3499
|
+
const maxBufferBytes = options.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES;
|
|
3500
|
+
const commandTimeoutMs = resolvePromptCommandTimeoutMs(options.commandTimeoutMs);
|
|
3501
|
+
const shell = process.env.SHELL || "/bin/bash";
|
|
3502
|
+
return async (command) => {
|
|
3503
|
+
const normalizedCommand = command.trim();
|
|
3504
|
+
if (!normalizedCommand) {
|
|
3505
|
+
return "";
|
|
3506
|
+
}
|
|
3507
|
+
const commandForExecution = wrapCommandForNonInteractiveExecution(normalizedCommand);
|
|
3508
|
+
try {
|
|
3509
|
+
const result = await execFile3(shell, ["-lc", commandForExecution], {
|
|
3510
|
+
cwd: options.workingDirectory,
|
|
3511
|
+
env: options.environment ?? process.env,
|
|
3512
|
+
maxBuffer: maxBufferBytes,
|
|
3513
|
+
timeout: commandTimeoutMs
|
|
3514
|
+
});
|
|
3515
|
+
const stdout2 = typeof result === "string" || Buffer.isBuffer(result) ? String(result) : String(result.stdout ?? "");
|
|
3516
|
+
return stdout2;
|
|
3517
|
+
} catch (error) {
|
|
3518
|
+
const failedCommand = normalizedCommand.replace(/\s+/g, " ").trim();
|
|
3519
|
+
const details = error && typeof error === "object" && "stderr" in error ? String(error.stderr ?? "").trim() : "";
|
|
3520
|
+
const timeoutDetected = error && typeof error === "object" && (("code" in error ? String(error.code ?? "").toUpperCase() === "ETIMEDOUT" : false) || "killed" in error && Boolean(error.killed) && String(error.signal ?? "").toUpperCase() === "SIGTERM" || "message" in error && /timed?\s*out/i.test(String(error.message ?? "")));
|
|
3521
|
+
if (timeoutDetected) {
|
|
3522
|
+
throw new Error(
|
|
3523
|
+
`Prompt command substitution timed out after ${commandTimeoutMs}ms for \`${failedCommand}\``
|
|
3524
|
+
);
|
|
3525
|
+
}
|
|
3526
|
+
const suffix = details ? `: ${details}` : "";
|
|
3527
|
+
throw new Error(`Prompt command substitution failed for \`${failedCommand}\`${suffix}`);
|
|
3528
|
+
}
|
|
3529
|
+
};
|
|
3530
|
+
}
|
|
3531
|
+
function resolvePromptCommandTimeoutMs(explicitTimeoutMs) {
|
|
3532
|
+
if (typeof explicitTimeoutMs === "number" && Number.isFinite(explicitTimeoutMs) && explicitTimeoutMs > 0) {
|
|
3533
|
+
return explicitTimeoutMs;
|
|
3534
|
+
}
|
|
3535
|
+
const envValue = process.env[COMMAND_TIMEOUT_ENV_KEY];
|
|
3536
|
+
if (envValue !== void 0) {
|
|
3537
|
+
const parsed = Number(envValue);
|
|
3538
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
3539
|
+
return parsed;
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
return DEFAULT_COMMAND_TIMEOUT_MS;
|
|
3543
|
+
}
|
|
3544
|
+
function wrapCommandForNonInteractiveExecution(command) {
|
|
3545
|
+
return `(${command}) </dev/null`;
|
|
3546
|
+
}
|
|
3547
|
+
function normalizeCommandOutput(output) {
|
|
3548
|
+
return output.replace(/\r?\n$/, "");
|
|
3549
|
+
}
|
|
3550
|
+
var SINGLE_QUOTED_MARKER, TRIPLE_BACKTICK_MARKER, TRIPLE_BACKTICK_CLOSER, DEFAULT_MAX_BUFFER_BYTES, DEFAULT_COMMAND_TIMEOUT_MS, COMMAND_TIMEOUT_ENV_KEY;
|
|
3551
|
+
var init_prompt_command_substitution = __esm({
|
|
3552
|
+
"src/core/prompt-command-substitution.ts"() {
|
|
3553
|
+
init_version();
|
|
3554
|
+
SINGLE_QUOTED_MARKER = "!'";
|
|
3555
|
+
TRIPLE_BACKTICK_MARKER = "!```";
|
|
3556
|
+
TRIPLE_BACKTICK_CLOSER = "```";
|
|
3557
|
+
DEFAULT_MAX_BUFFER_BYTES = 1024 * 1024;
|
|
3558
|
+
DEFAULT_COMMAND_TIMEOUT_MS = 3e4;
|
|
3559
|
+
COMMAND_TIMEOUT_ENV_KEY = "JUNO_CODE_PROMPT_SUBSTITUTION_TIMEOUT_MS";
|
|
3560
|
+
}
|
|
3561
|
+
});
|
|
3301
3562
|
function createExecutionEngine(config) {
|
|
3302
3563
|
return new ExecutionEngine({
|
|
3303
3564
|
config,
|
|
@@ -3348,6 +3609,9 @@ function createExecutionRequest(options) {
|
|
|
3348
3609
|
if (options.live !== void 0) {
|
|
3349
3610
|
result.live = options.live;
|
|
3350
3611
|
}
|
|
3612
|
+
if (options.liveInteractiveSession !== void 0) {
|
|
3613
|
+
result.liveInteractiveSession = options.liveInteractiveSession;
|
|
3614
|
+
}
|
|
3351
3615
|
return result;
|
|
3352
3616
|
}
|
|
3353
3617
|
var DEFAULT_ERROR_RECOVERY_CONFIG, DEFAULT_RATE_LIMIT_CONFIG, DEFAULT_PROGRESS_CONFIG, ExecutionEngine;
|
|
@@ -3358,6 +3622,7 @@ var init_engine = __esm({
|
|
|
3358
3622
|
init_hooks();
|
|
3359
3623
|
init_advanced_logger();
|
|
3360
3624
|
init_shell_backend();
|
|
3625
|
+
init_prompt_command_substitution();
|
|
3361
3626
|
DEFAULT_ERROR_RECOVERY_CONFIG = {
|
|
3362
3627
|
maxAttempts: {
|
|
3363
3628
|
connection: 3,
|
|
@@ -3654,7 +3919,8 @@ var init_engine = __esm({
|
|
|
3654
3919
|
if (!request.requestId?.trim()) {
|
|
3655
3920
|
throw new Error("Request ID is required");
|
|
3656
3921
|
}
|
|
3657
|
-
|
|
3922
|
+
const allowEmptyInstructionForPiLiveInteractiveSession = request.subagent === "pi" && request.live === true && request.liveInteractiveSession === true && typeof request.resume === "string" && request.resume.trim().length > 0;
|
|
3923
|
+
if (!request.instruction?.trim() && !allowEmptyInstructionForPiLiveInteractiveSession) {
|
|
3658
3924
|
throw new Error("Instruction is required");
|
|
3659
3925
|
}
|
|
3660
3926
|
if (!request.subagent?.trim()) {
|
|
@@ -3892,44 +4158,62 @@ var init_engine = __esm({
|
|
|
3892
4158
|
engineLogger.warn("Hook START_ITERATION failed", { error, iterationNumber });
|
|
3893
4159
|
}
|
|
3894
4160
|
this.emit("iteration:start", { context, iterationNumber });
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
4161
|
+
let toolRequest = null;
|
|
4162
|
+
try {
|
|
4163
|
+
const instructionTemplate = context.request.instruction;
|
|
4164
|
+
const resolvedInstruction = await resolvePromptCommandSubstitutions(instructionTemplate, {
|
|
4165
|
+
workingDirectory: context.request.workingDirectory,
|
|
4166
|
+
environment: {
|
|
4167
|
+
...process.env,
|
|
4168
|
+
JUNO_TASK_ROOT: process.env.JUNO_TASK_ROOT || context.request.workingDirectory
|
|
4169
|
+
}
|
|
4170
|
+
});
|
|
4171
|
+
this.emit("iteration:instruction-resolved", {
|
|
4172
|
+
context,
|
|
4173
|
+
iterationNumber,
|
|
4174
|
+
instruction: resolvedInstruction,
|
|
4175
|
+
templateInstruction: instructionTemplate
|
|
4176
|
+
});
|
|
4177
|
+
toolRequest = {
|
|
4178
|
+
toolName: this.getToolNameForSubagent(context.request.subagent),
|
|
4179
|
+
arguments: {
|
|
4180
|
+
instruction: resolvedInstruction,
|
|
4181
|
+
project_path: context.request.workingDirectory,
|
|
4182
|
+
...context.request.model !== void 0 && { model: context.request.model },
|
|
4183
|
+
...context.request.agents !== void 0 && { agents: context.request.agents },
|
|
4184
|
+
...context.request.tools !== void 0 && { tools: context.request.tools },
|
|
4185
|
+
...context.request.allowedTools !== void 0 && {
|
|
4186
|
+
allowedTools: context.request.allowedTools
|
|
4187
|
+
},
|
|
4188
|
+
...context.request.appendAllowedTools !== void 0 && {
|
|
4189
|
+
appendAllowedTools: context.request.appendAllowedTools
|
|
4190
|
+
},
|
|
4191
|
+
...context.request.disallowedTools !== void 0 && {
|
|
4192
|
+
disallowedTools: context.request.disallowedTools
|
|
4193
|
+
},
|
|
4194
|
+
...context.request.resume !== void 0 && { resume: context.request.resume },
|
|
4195
|
+
...context.request.continueConversation !== void 0 && {
|
|
4196
|
+
continueConversation: context.request.continueConversation
|
|
4197
|
+
},
|
|
4198
|
+
...context.request.thinking !== void 0 && { thinking: context.request.thinking },
|
|
4199
|
+
...context.request.live !== void 0 && { live: context.request.live },
|
|
4200
|
+
...context.request.liveInteractiveSession !== void 0 && {
|
|
4201
|
+
liveInteractiveSession: context.request.liveInteractiveSession
|
|
4202
|
+
},
|
|
4203
|
+
iteration: iterationNumber
|
|
3911
4204
|
},
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
4205
|
+
timeout: context.request.timeoutMs || this.engineConfig.config.mcpTimeout,
|
|
4206
|
+
priority: context.request.priority || "normal",
|
|
4207
|
+
metadata: {
|
|
4208
|
+
sessionId: context.sessionContext.sessionId,
|
|
4209
|
+
iterationNumber
|
|
3915
4210
|
},
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
metadata: {
|
|
3923
|
-
sessionId: context.sessionContext.sessionId,
|
|
3924
|
-
iterationNumber
|
|
3925
|
-
},
|
|
3926
|
-
progressCallback: async (event) => {
|
|
3927
|
-
context.progressEvents.push(event);
|
|
3928
|
-
context.statistics.totalProgressEvents++;
|
|
3929
|
-
await this.processProgressEvent(context, event);
|
|
3930
|
-
}
|
|
3931
|
-
};
|
|
3932
|
-
try {
|
|
4211
|
+
progressCallback: async (event) => {
|
|
4212
|
+
context.progressEvents.push(event);
|
|
4213
|
+
context.statistics.totalProgressEvents++;
|
|
4214
|
+
await this.processProgressEvent(context, event);
|
|
4215
|
+
}
|
|
4216
|
+
};
|
|
3933
4217
|
if (!this.currentBackend) {
|
|
3934
4218
|
throw new Error("No backend initialized. Call initializeBackend() first.");
|
|
3935
4219
|
}
|
|
@@ -3998,7 +4282,10 @@ var init_engine = __esm({
|
|
|
3998
4282
|
duration,
|
|
3999
4283
|
error: mcpError,
|
|
4000
4284
|
progressEvents: [],
|
|
4001
|
-
request: toolRequest
|
|
4285
|
+
request: toolRequest ?? {
|
|
4286
|
+
toolName: this.getToolNameForSubagent(context.request.subagent),
|
|
4287
|
+
arguments: {}
|
|
4288
|
+
}
|
|
4002
4289
|
},
|
|
4003
4290
|
progressEvents: [],
|
|
4004
4291
|
error: mcpError
|
|
@@ -5070,10 +5357,13 @@ var init_terminal_progress_writer = __esm({
|
|
|
5070
5357
|
// src/cli/commands/main.ts
|
|
5071
5358
|
var main_exports = {};
|
|
5072
5359
|
__export(main_exports, {
|
|
5360
|
+
expandKanbanTaskReferencesInPrompt: () => expandKanbanTaskReferencesInPrompt,
|
|
5073
5361
|
getActiveSessionId: () => getActiveSessionId,
|
|
5074
5362
|
getDefaultModelForSubagent: () => getDefaultModelForSubagent,
|
|
5075
5363
|
isModelCompatibleWithSubagent: () => isModelCompatibleWithSubagent,
|
|
5076
|
-
mainCommandHandler: () => mainCommandHandler
|
|
5364
|
+
mainCommandHandler: () => mainCommandHandler,
|
|
5365
|
+
normalizeLeadingPromptDirectiveArtifacts: () => normalizeLeadingPromptDirectiveArtifacts,
|
|
5366
|
+
rewriteLeadingPromptShortcut: () => rewriteLeadingPromptShortcut
|
|
5077
5367
|
});
|
|
5078
5368
|
function normalizeVerboseLevel(verbose, quiet) {
|
|
5079
5369
|
if (quiet) return 0;
|
|
@@ -5140,6 +5430,169 @@ function toStringArray(value) {
|
|
|
5140
5430
|
const normalized = value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0);
|
|
5141
5431
|
return normalized.length > 0 ? normalized : void 0;
|
|
5142
5432
|
}
|
|
5433
|
+
function extractReferencedKanbanTaskIds(prompt) {
|
|
5434
|
+
const taskIds = [];
|
|
5435
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5436
|
+
for (const match of prompt.matchAll(KANBAN_TASK_REFERENCE_REGEX)) {
|
|
5437
|
+
const taskId = match[1];
|
|
5438
|
+
if (!taskId || seen.has(taskId)) {
|
|
5439
|
+
continue;
|
|
5440
|
+
}
|
|
5441
|
+
seen.add(taskId);
|
|
5442
|
+
taskIds.push(taskId);
|
|
5443
|
+
}
|
|
5444
|
+
return taskIds;
|
|
5445
|
+
}
|
|
5446
|
+
function normalizeKanbanTaskArray(payload) {
|
|
5447
|
+
if (Array.isArray(payload)) {
|
|
5448
|
+
return payload.filter((entry) => Boolean(entry) && typeof entry === "object");
|
|
5449
|
+
}
|
|
5450
|
+
if (payload && typeof payload === "object") {
|
|
5451
|
+
return [payload];
|
|
5452
|
+
}
|
|
5453
|
+
return [];
|
|
5454
|
+
}
|
|
5455
|
+
async function runKanbanGetCommand(command, args, workingDirectory) {
|
|
5456
|
+
try {
|
|
5457
|
+
const execFile3 = promisify(childProcess.execFile);
|
|
5458
|
+
const result = await execFile3(command, args, {
|
|
5459
|
+
cwd: workingDirectory,
|
|
5460
|
+
env: {
|
|
5461
|
+
...process.env,
|
|
5462
|
+
JUNO_TASK_ROOT: process.env.JUNO_TASK_ROOT || workingDirectory
|
|
5463
|
+
},
|
|
5464
|
+
maxBuffer: 1024 * 1024
|
|
5465
|
+
});
|
|
5466
|
+
const stdout2 = typeof result === "string" || Buffer.isBuffer(result) ? String(result) : String(result.stdout ?? "");
|
|
5467
|
+
const parsed = JSON.parse(stdout2);
|
|
5468
|
+
return normalizeKanbanTaskArray(parsed);
|
|
5469
|
+
} catch {
|
|
5470
|
+
return null;
|
|
5471
|
+
}
|
|
5472
|
+
}
|
|
5473
|
+
async function fetchKanbanTasksForCommand(command, taskIds, workingDirectory) {
|
|
5474
|
+
const tasksById = /* @__PURE__ */ new Map();
|
|
5475
|
+
if (taskIds.length === 0) {
|
|
5476
|
+
return tasksById;
|
|
5477
|
+
}
|
|
5478
|
+
const requestedTaskIds = new Set(taskIds);
|
|
5479
|
+
const addFetchedTasks = (fetchedTasks) => {
|
|
5480
|
+
if (!fetchedTasks) {
|
|
5481
|
+
return;
|
|
5482
|
+
}
|
|
5483
|
+
for (const task of fetchedTasks) {
|
|
5484
|
+
const taskId = typeof task.id === "string" ? task.id : void 0;
|
|
5485
|
+
if (!taskId || !requestedTaskIds.has(taskId)) {
|
|
5486
|
+
continue;
|
|
5487
|
+
}
|
|
5488
|
+
tasksById.set(taskId, task);
|
|
5489
|
+
}
|
|
5490
|
+
};
|
|
5491
|
+
addFetchedTasks(await runKanbanGetCommand(command, ["get", ...taskIds], workingDirectory));
|
|
5492
|
+
const unresolvedTaskIds = taskIds.filter((taskId) => !tasksById.has(taskId));
|
|
5493
|
+
for (const taskId of unresolvedTaskIds) {
|
|
5494
|
+
addFetchedTasks(await runKanbanGetCommand(command, ["get", taskId], workingDirectory));
|
|
5495
|
+
}
|
|
5496
|
+
return tasksById;
|
|
5497
|
+
}
|
|
5498
|
+
async function fetchReferencedKanbanTasks(taskIds, workingDirectory) {
|
|
5499
|
+
const tasksById = /* @__PURE__ */ new Map();
|
|
5500
|
+
if (taskIds.length === 0) {
|
|
5501
|
+
return tasksById;
|
|
5502
|
+
}
|
|
5503
|
+
const kanbanScriptPath = path15.join(workingDirectory, KANBAN_TASK_SCRIPT_RELATIVE_PATH);
|
|
5504
|
+
const hasKanbanScript = await fs16.pathExists(kanbanScriptPath);
|
|
5505
|
+
const commandAttempts = [];
|
|
5506
|
+
if (hasKanbanScript) {
|
|
5507
|
+
commandAttempts.push(kanbanScriptPath);
|
|
5508
|
+
}
|
|
5509
|
+
commandAttempts.push("juno-kanban");
|
|
5510
|
+
let unresolvedTaskIds = [...taskIds];
|
|
5511
|
+
for (const command of commandAttempts) {
|
|
5512
|
+
if (unresolvedTaskIds.length === 0) {
|
|
5513
|
+
break;
|
|
5514
|
+
}
|
|
5515
|
+
const fetchedTasks = await fetchKanbanTasksForCommand(command, unresolvedTaskIds, workingDirectory);
|
|
5516
|
+
if (fetchedTasks.size === 0) {
|
|
5517
|
+
continue;
|
|
5518
|
+
}
|
|
5519
|
+
for (const [taskId, task] of fetchedTasks.entries()) {
|
|
5520
|
+
tasksById.set(taskId, task);
|
|
5521
|
+
}
|
|
5522
|
+
unresolvedTaskIds = unresolvedTaskIds.filter((taskId) => !tasksById.has(taskId));
|
|
5523
|
+
}
|
|
5524
|
+
return tasksById;
|
|
5525
|
+
}
|
|
5526
|
+
async function expandKanbanTaskReferencesInPrompt(prompt, workingDirectory) {
|
|
5527
|
+
const referencedTaskIds = extractReferencedKanbanTaskIds(prompt);
|
|
5528
|
+
if (referencedTaskIds.length === 0) {
|
|
5529
|
+
return prompt;
|
|
5530
|
+
}
|
|
5531
|
+
const tasksById = await fetchReferencedKanbanTasks(referencedTaskIds, workingDirectory);
|
|
5532
|
+
if (tasksById.size === 0) {
|
|
5533
|
+
return prompt;
|
|
5534
|
+
}
|
|
5535
|
+
return prompt.replace(KANBAN_TASK_REFERENCE_REGEX, (fullMatch, taskId) => {
|
|
5536
|
+
const task = tasksById.get(taskId);
|
|
5537
|
+
if (!task) {
|
|
5538
|
+
return fullMatch;
|
|
5539
|
+
}
|
|
5540
|
+
return `
|
|
5541
|
+
[kanban_task:${taskId}]
|
|
5542
|
+
${JSON.stringify(task, null, 2)}
|
|
5543
|
+
[/kanban_task]`;
|
|
5544
|
+
});
|
|
5545
|
+
}
|
|
5546
|
+
function normalizeLeadingPromptDirectiveArtifacts(prompt) {
|
|
5547
|
+
const lines = prompt.split(/\r?\n/);
|
|
5548
|
+
if (lines.length === 0) {
|
|
5549
|
+
return prompt;
|
|
5550
|
+
}
|
|
5551
|
+
let index = 0;
|
|
5552
|
+
while (index < lines.length && lines[index].trim() === "") {
|
|
5553
|
+
index += 1;
|
|
5554
|
+
}
|
|
5555
|
+
if (index >= lines.length) {
|
|
5556
|
+
return prompt;
|
|
5557
|
+
}
|
|
5558
|
+
const firstMeaningfulLine = lines[index].trim();
|
|
5559
|
+
if (!LEADING_PROMPT_DELIMITER_MARKERS.has(firstMeaningfulLine)) {
|
|
5560
|
+
return prompt;
|
|
5561
|
+
}
|
|
5562
|
+
let directiveIndex = index + 1;
|
|
5563
|
+
while (directiveIndex < lines.length && lines[directiveIndex].trim() === "") {
|
|
5564
|
+
directiveIndex += 1;
|
|
5565
|
+
}
|
|
5566
|
+
if (directiveIndex >= lines.length) {
|
|
5567
|
+
return prompt;
|
|
5568
|
+
}
|
|
5569
|
+
const directiveCandidate = lines[directiveIndex].trimStart();
|
|
5570
|
+
if (!LEADING_DIRECTIVE_LINE_REGEX.test(directiveCandidate)) {
|
|
5571
|
+
return prompt;
|
|
5572
|
+
}
|
|
5573
|
+
return lines.slice(directiveIndex).join("\n");
|
|
5574
|
+
}
|
|
5575
|
+
function rewriteLeadingPromptShortcut(prompt, subagent) {
|
|
5576
|
+
const match = prompt.match(LEADING_PROMPT_SHORTCUT_REGEX);
|
|
5577
|
+
if (!match) {
|
|
5578
|
+
return prompt;
|
|
5579
|
+
}
|
|
5580
|
+
const shortcut = match[1] ?? match[2];
|
|
5581
|
+
if (!shortcut) {
|
|
5582
|
+
return prompt;
|
|
5583
|
+
}
|
|
5584
|
+
const remaining = match[3] ?? "";
|
|
5585
|
+
switch (subagent) {
|
|
5586
|
+
case "claude":
|
|
5587
|
+
return `/${shortcut}${remaining}`;
|
|
5588
|
+
case "pi":
|
|
5589
|
+
return `/skill:${shortcut}${remaining}`;
|
|
5590
|
+
case "codex":
|
|
5591
|
+
return `$${shortcut}${remaining}`;
|
|
5592
|
+
default:
|
|
5593
|
+
return prompt;
|
|
5594
|
+
}
|
|
5595
|
+
}
|
|
5143
5596
|
function resolveContinueEnvFilePath(workingDirectory, configuredPath) {
|
|
5144
5597
|
const candidate = configuredPath && configuredPath.trim() ? configuredPath.trim() : DEFAULT_ENV_FILE_NAME;
|
|
5145
5598
|
return path15.isAbsolute(candidate) ? candidate : path15.join(workingDirectory, candidate);
|
|
@@ -5542,7 +5995,13 @@ async function mainCommandHandler(_args, options, _command) {
|
|
|
5542
5995
|
]);
|
|
5543
5996
|
}
|
|
5544
5997
|
const promptProcessor = new PromptProcessor(options);
|
|
5545
|
-
const
|
|
5998
|
+
const rawInstruction = await promptProcessor.processPrompt();
|
|
5999
|
+
const normalizedInstruction = normalizeLeadingPromptDirectiveArtifacts(rawInstruction);
|
|
6000
|
+
const rewrittenInstruction = rewriteLeadingPromptShortcut(normalizedInstruction, options.subagent);
|
|
6001
|
+
const instruction = await expandKanbanTaskReferencesInPrompt(
|
|
6002
|
+
rewrittenInstruction,
|
|
6003
|
+
config.workingDirectory
|
|
6004
|
+
);
|
|
5546
6005
|
const selectedBackend = "shell";
|
|
5547
6006
|
if (options.allowedTools && options.appendAllowedTools) {
|
|
5548
6007
|
console.error(
|
|
@@ -5561,6 +6020,7 @@ async function mainCommandHandler(_args, options, _command) {
|
|
|
5561
6020
|
}
|
|
5562
6021
|
const configuredModel = getConfiguredDefaultModelForSubagent(config, options.subagent);
|
|
5563
6022
|
const resolvedModel = options.model || configuredModel || getDefaultModelForSubagent(options.subagent);
|
|
6023
|
+
const liveInteractiveSession = options.continueFromLatest === true && options.subagent === "pi" && options.live === true && instruction.length === 0 && typeof options.resume === "string" && options.resume.trim().length > 0;
|
|
5564
6024
|
const executionRequest = createExecutionRequest({
|
|
5565
6025
|
instruction,
|
|
5566
6026
|
subagent: options.subagent,
|
|
@@ -5576,7 +6036,8 @@ async function mainCommandHandler(_args, options, _command) {
|
|
|
5576
6036
|
...options.resume !== void 0 ? { resume: options.resume } : {},
|
|
5577
6037
|
...options.continue !== void 0 ? { continueConversation: options.continue } : {},
|
|
5578
6038
|
...options.thinking !== void 0 ? { thinking: options.thinking } : {},
|
|
5579
|
-
...options.live !== void 0 ? { live: options.live } : {}
|
|
6039
|
+
...options.live !== void 0 ? { live: options.live } : {},
|
|
6040
|
+
...liveInteractiveSession ? { liveInteractiveSession: true } : {}
|
|
5580
6041
|
});
|
|
5581
6042
|
const coordinator = new MainExecutionCoordinator(
|
|
5582
6043
|
config,
|
|
@@ -5654,7 +6115,7 @@ async function mainCommandHandler(_args, options, _command) {
|
|
|
5654
6115
|
}
|
|
5655
6116
|
}
|
|
5656
6117
|
}
|
|
5657
|
-
var SESSION_HISTORY_VERSION, SESSION_HISTORY_FILE_NAME, CONTINUE_SETTINGS_VERSION, DEFAULT_ENV_FILE_NAME, PromptProcessor, _activeSessionId, MainProgressDisplay, MainExecutionCoordinator;
|
|
6118
|
+
var SESSION_HISTORY_VERSION, SESSION_HISTORY_FILE_NAME, CONTINUE_SETTINGS_VERSION, DEFAULT_ENV_FILE_NAME, LEADING_PROMPT_SHORTCUT_REGEX, LEADING_PROMPT_DELIMITER_MARKERS, LEADING_DIRECTIVE_LINE_REGEX, KANBAN_TASK_REFERENCE_REGEX, KANBAN_TASK_SCRIPT_RELATIVE_PATH, PromptProcessor, _activeSessionId, MainProgressDisplay, MainExecutionCoordinator;
|
|
5658
6119
|
var init_main = __esm({
|
|
5659
6120
|
"src/cli/commands/main.ts"() {
|
|
5660
6121
|
init_version();
|
|
@@ -5671,6 +6132,11 @@ var init_main = __esm({
|
|
|
5671
6132
|
SESSION_HISTORY_FILE_NAME = "session_history.json";
|
|
5672
6133
|
CONTINUE_SETTINGS_VERSION = 1;
|
|
5673
6134
|
DEFAULT_ENV_FILE_NAME = ".env.juno";
|
|
6135
|
+
LEADING_PROMPT_SHORTCUT_REGEX = /^%(?:\{([^\s{}]+)\}|([^\s%][^\s]*))(.*)$/s;
|
|
6136
|
+
LEADING_PROMPT_DELIMITER_MARKERS = /* @__PURE__ */ new Set(["---", "***", "___"]);
|
|
6137
|
+
LEADING_DIRECTIVE_LINE_REGEX = /^(?:%(?:\{[^\s{}]+\}|[^\s%][^\s]*)|\/skill:[^\s]+|\/[^\s]+|\$[^\s]+)/;
|
|
6138
|
+
KANBAN_TASK_REFERENCE_REGEX = /(?<!#)##\s*\{?([A-Za-z0-9]{6})\}?(?![A-Za-z0-9])/g;
|
|
6139
|
+
KANBAN_TASK_SCRIPT_RELATIVE_PATH = path15.join(".juno_task", "scripts", "kanban.sh");
|
|
5674
6140
|
PromptProcessor = class {
|
|
5675
6141
|
constructor(options) {
|
|
5676
6142
|
this.options = options;
|
|
@@ -5688,6 +6154,9 @@ var init_main = __esm({
|
|
|
5688
6154
|
if (this.hasRedirectedStdin()) {
|
|
5689
6155
|
return await this.readPipedStdin();
|
|
5690
6156
|
}
|
|
6157
|
+
if (this.shouldOpenLiveContinueSessionWithoutPrompt()) {
|
|
6158
|
+
return "";
|
|
6159
|
+
}
|
|
5691
6160
|
if (this.options.interactive) {
|
|
5692
6161
|
return await this.collectInteractivePrompt();
|
|
5693
6162
|
} else {
|
|
@@ -5726,6 +6195,9 @@ var init_main = __esm({
|
|
|
5726
6195
|
return false;
|
|
5727
6196
|
}
|
|
5728
6197
|
}
|
|
6198
|
+
shouldOpenLiveContinueSessionWithoutPrompt() {
|
|
6199
|
+
return this.options.continueFromLatest === true && this.options.subagent === "pi" && this.options.live === true && !this.options.promptFile && this.options.prompt !== true && !this.options.interactive && !this.options.interactivePrompt;
|
|
6200
|
+
}
|
|
5729
6201
|
async isFilePath(prompt) {
|
|
5730
6202
|
if (prompt.includes("\n") || prompt.length > 500) {
|
|
5731
6203
|
return false;
|
|
@@ -5834,6 +6306,7 @@ var init_main = __esm({
|
|
|
5834
6306
|
// iteration# → sub-agent session_id
|
|
5835
6307
|
latestSessionId = null;
|
|
5836
6308
|
// most recent session_id seen
|
|
6309
|
+
lastResolvedInstructionByIteration = /* @__PURE__ */ new Map();
|
|
5837
6310
|
constructor(verboseLevel = 1) {
|
|
5838
6311
|
this.verboseLevel = verboseLevel;
|
|
5839
6312
|
}
|
|
@@ -5860,9 +6333,18 @@ var init_main = __esm({
|
|
|
5860
6333
|
console.error(chalk21.gray(` Request ID: ${request.requestId}`));
|
|
5861
6334
|
console.error(chalk21.gray(` Working Directory: ${request.workingDirectory}`));
|
|
5862
6335
|
}
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
6336
|
+
const hasPromptSubstitutionSyntax = this.hasPromptCommandSubstitutionSyntax(request.instruction);
|
|
6337
|
+
if (hasPromptSubstitutionSyntax) {
|
|
6338
|
+
console.error(chalk21.blue("\n\u{1F4CB} Task Template:"));
|
|
6339
|
+
} else {
|
|
6340
|
+
console.error(chalk21.blue("\n\u{1F4CB} Task:"));
|
|
6341
|
+
}
|
|
6342
|
+
console.error(chalk21.white(` ${this.buildInstructionPreview(request.instruction)}`));
|
|
6343
|
+
if (hasPromptSubstitutionSyntax) {
|
|
6344
|
+
console.error(
|
|
6345
|
+
chalk21.gray(" Prompt-time substitutions are resolved immediately before each subagent call.")
|
|
6346
|
+
);
|
|
6347
|
+
}
|
|
5866
6348
|
console.error("");
|
|
5867
6349
|
}
|
|
5868
6350
|
getSelectedExecutionOptions(request) {
|
|
@@ -5896,6 +6378,32 @@ var init_main = __esm({
|
|
|
5896
6378
|
if (value.length <= maxLength) return value;
|
|
5897
6379
|
return `${value.substring(0, maxLength - 3)}...`;
|
|
5898
6380
|
}
|
|
6381
|
+
buildInstructionPreview(instruction, maxLength = 200) {
|
|
6382
|
+
if (instruction.length <= maxLength) {
|
|
6383
|
+
return instruction;
|
|
6384
|
+
}
|
|
6385
|
+
return `${instruction.substring(0, maxLength)}...`;
|
|
6386
|
+
}
|
|
6387
|
+
hasPromptCommandSubstitutionSyntax(instruction) {
|
|
6388
|
+
return instruction.includes("!'") || instruction.includes("!```");
|
|
6389
|
+
}
|
|
6390
|
+
onInstructionResolved(iteration, resolvedInstruction, templateInstruction) {
|
|
6391
|
+
const previousInstruction = this.lastResolvedInstructionByIteration.get(iteration);
|
|
6392
|
+
if (previousInstruction === resolvedInstruction) {
|
|
6393
|
+
return;
|
|
6394
|
+
}
|
|
6395
|
+
this.lastResolvedInstructionByIteration.set(iteration, resolvedInstruction);
|
|
6396
|
+
if (this.verboseLevel === 0) {
|
|
6397
|
+
return;
|
|
6398
|
+
}
|
|
6399
|
+
if (templateInstruction !== void 0 && resolvedInstruction === templateInstruction) {
|
|
6400
|
+
return;
|
|
6401
|
+
}
|
|
6402
|
+
const heading = iteration === 1 ? "\n\u{1F9E9} Resolved Task (iteration 1):" : `
|
|
6403
|
+
\u{1F9E9} Resolved Task (iteration ${iteration}):`;
|
|
6404
|
+
console.error(chalk21.blue(heading));
|
|
6405
|
+
console.error(chalk21.white(` ${this.buildInstructionPreview(resolvedInstruction)}`));
|
|
6406
|
+
}
|
|
5899
6407
|
onProgress(event) {
|
|
5900
6408
|
const timestamp = event.timestamp.toLocaleTimeString();
|
|
5901
6409
|
if (event.metadata?.sessionId && typeof event.metadata.sessionId === "string") {
|
|
@@ -5973,7 +6481,10 @@ var init_main = __esm({
|
|
|
5973
6481
|
if (this.verboseLevel === 0) {
|
|
5974
6482
|
const lastIteration2 = result.iterations[result.iterations.length - 1];
|
|
5975
6483
|
if (lastIteration2?.toolResult.content && !this.hasStreamedJsonOutput) {
|
|
5976
|
-
|
|
6484
|
+
const displayContent = this.getDisplayResultContent(lastIteration2.toolResult.content);
|
|
6485
|
+
if (displayContent.trim().length > 0) {
|
|
6486
|
+
console.log(displayContent);
|
|
6487
|
+
}
|
|
5977
6488
|
}
|
|
5978
6489
|
return;
|
|
5979
6490
|
}
|
|
@@ -5986,12 +6497,14 @@ var init_main = __esm({
|
|
|
5986
6497
|
}
|
|
5987
6498
|
const lastIteration = result.iterations[result.iterations.length - 1];
|
|
5988
6499
|
const structuredOutput = lastIteration?.toolResult.metadata?.structuredOutput === true;
|
|
6500
|
+
const rawResultContent = lastIteration?.toolResult.content || "";
|
|
6501
|
+
const displayResultContent = rawResultContent ? this.getDisplayResultContent(rawResultContent) : "";
|
|
5989
6502
|
const shouldPrintResult = Boolean(
|
|
5990
|
-
lastIteration &&
|
|
6503
|
+
lastIteration && displayResultContent && (!this.hasStreamedJsonOutput || structuredOutput)
|
|
5991
6504
|
);
|
|
5992
6505
|
if (shouldPrintResult) {
|
|
5993
6506
|
console.error(chalk21.blue("\n\u{1F4C4} Result:"));
|
|
5994
|
-
console.log(
|
|
6507
|
+
console.log(displayResultContent);
|
|
5995
6508
|
}
|
|
5996
6509
|
const iterationCosts = this.extractIterationCosts(result);
|
|
5997
6510
|
const totalCostUsd = [...iterationCosts.values()].reduce((sum, cost) => sum + cost, 0);
|
|
@@ -6061,6 +6574,26 @@ var init_main = __esm({
|
|
|
6061
6574
|
console.error(chalk21.gray("\n\u{1F511} Session ID: could not be extracted"));
|
|
6062
6575
|
}
|
|
6063
6576
|
}
|
|
6577
|
+
getDisplayResultContent(content) {
|
|
6578
|
+
if (this.verboseLevel >= 2) {
|
|
6579
|
+
return content;
|
|
6580
|
+
}
|
|
6581
|
+
try {
|
|
6582
|
+
const payload = JSON.parse(content);
|
|
6583
|
+
if (payload?.type === "result" && Object.prototype.hasOwnProperty.call(payload, "result")) {
|
|
6584
|
+
const resultValue = payload.result;
|
|
6585
|
+
if (typeof resultValue === "string") {
|
|
6586
|
+
return resultValue;
|
|
6587
|
+
}
|
|
6588
|
+
if (resultValue === null || resultValue === void 0) {
|
|
6589
|
+
return "";
|
|
6590
|
+
}
|
|
6591
|
+
return JSON.stringify(resultValue, null, 2);
|
|
6592
|
+
}
|
|
6593
|
+
} catch {
|
|
6594
|
+
}
|
|
6595
|
+
return content;
|
|
6596
|
+
}
|
|
6064
6597
|
/**
|
|
6065
6598
|
* Extract session IDs from iteration results' structured payloads
|
|
6066
6599
|
*/
|
|
@@ -6209,6 +6742,13 @@ var init_main = __esm({
|
|
|
6209
6742
|
engine.on("iteration:start", ({ iterationNumber }) => {
|
|
6210
6743
|
this.progressDisplay.onIterationStart(iterationNumber);
|
|
6211
6744
|
});
|
|
6745
|
+
engine.on("iteration:instruction-resolved", ({ iterationNumber, instruction, templateInstruction }) => {
|
|
6746
|
+
this.progressDisplay.onInstructionResolved(
|
|
6747
|
+
iterationNumber,
|
|
6748
|
+
typeof instruction === "string" ? instruction : "",
|
|
6749
|
+
typeof templateInstruction === "string" ? templateInstruction : void 0
|
|
6750
|
+
);
|
|
6751
|
+
});
|
|
6212
6752
|
engine.on("iteration:complete", ({ iterationResult }) => {
|
|
6213
6753
|
this.progressDisplay.onIterationComplete(iterationResult.success, iterationResult.duration);
|
|
6214
6754
|
});
|
|
@@ -14774,6 +15314,26 @@ function normalizeVerbose(value) {
|
|
|
14774
15314
|
if (!isNaN(num) && num >= 0 && num <= 2) return Math.floor(num);
|
|
14775
15315
|
return 1;
|
|
14776
15316
|
}
|
|
15317
|
+
function extractOptionValueFromArgv(argv2, longOption, shortOption) {
|
|
15318
|
+
for (let i = 0; i < argv2.length; i++) {
|
|
15319
|
+
const token = argv2[i];
|
|
15320
|
+
if (!token) continue;
|
|
15321
|
+
if (token === longOption || token === shortOption) {
|
|
15322
|
+
const next = argv2[i + 1];
|
|
15323
|
+
if (next && !next.startsWith("-")) {
|
|
15324
|
+
return next;
|
|
15325
|
+
}
|
|
15326
|
+
continue;
|
|
15327
|
+
}
|
|
15328
|
+
if (token.startsWith(`${longOption}=`)) {
|
|
15329
|
+
return token.slice(longOption.length + 1);
|
|
15330
|
+
}
|
|
15331
|
+
if (token.startsWith(`${shortOption}=`)) {
|
|
15332
|
+
return token.slice(shortOption.length + 1);
|
|
15333
|
+
}
|
|
15334
|
+
}
|
|
15335
|
+
return void 0;
|
|
15336
|
+
}
|
|
14777
15337
|
function isConnectionLikeError(err) {
|
|
14778
15338
|
const msg = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
|
|
14779
15339
|
const lower = msg.toLowerCase();
|
|
@@ -14904,6 +15464,15 @@ function getForwardedUntilCompletionArgs() {
|
|
|
14904
15464
|
if (arg.startsWith("--pre-run-hook=")) {
|
|
14905
15465
|
continue;
|
|
14906
15466
|
}
|
|
15467
|
+
if (arg === "--cwd" || arg === "-w") {
|
|
15468
|
+
if (i + 1 < args.length && args[i + 1] && !args[i + 1].startsWith("-")) {
|
|
15469
|
+
i += 1;
|
|
15470
|
+
}
|
|
15471
|
+
continue;
|
|
15472
|
+
}
|
|
15473
|
+
if (arg.startsWith("--cwd=") || arg.startsWith("-w=")) {
|
|
15474
|
+
continue;
|
|
15475
|
+
}
|
|
14907
15476
|
forwardedArgs.push(arg);
|
|
14908
15477
|
}
|
|
14909
15478
|
return forwardedArgs;
|
|
@@ -14915,7 +15484,9 @@ async function runUntilCompletionScriptIfRequested(options) {
|
|
|
14915
15484
|
const { spawn: spawn3 } = await import('child_process');
|
|
14916
15485
|
const path21 = await import('path');
|
|
14917
15486
|
const fs22 = await import('fs-extra');
|
|
14918
|
-
const
|
|
15487
|
+
const optionCwd = typeof options.cwd === "string" && options.cwd.trim().length > 0 ? options.cwd.trim() : extractOptionValueFromArgv(process.argv.slice(2), "--cwd", "-w");
|
|
15488
|
+
const invocationCwd = typeof optionCwd === "string" && optionCwd.trim().length > 0 ? path21.resolve(process.cwd(), optionCwd) : process.cwd();
|
|
15489
|
+
const scriptPath = path21.join(invocationCwd, ".juno_task", "scripts", "run_until_completion.sh");
|
|
14919
15490
|
if (!await fs22.pathExists(scriptPath)) {
|
|
14920
15491
|
console.error(chalk21.red.bold("\n\u274C Error: run_until_completion.sh not found"));
|
|
14921
15492
|
console.error(chalk21.red(` Expected location: ${scriptPath}`));
|
|
@@ -14932,7 +15503,7 @@ async function runUntilCompletionScriptIfRequested(options) {
|
|
|
14932
15503
|
scriptArgs.push(...getForwardedUntilCompletionArgs());
|
|
14933
15504
|
const child = spawn3(scriptPath, scriptArgs, {
|
|
14934
15505
|
stdio: "inherit",
|
|
14935
|
-
cwd:
|
|
15506
|
+
cwd: invocationCwd
|
|
14936
15507
|
});
|
|
14937
15508
|
process.removeAllListeners("SIGINT");
|
|
14938
15509
|
process.removeAllListeners("SIGTERM");
|
|
@@ -14964,9 +15535,9 @@ async function runUntilCompletionScriptIfRequested(options) {
|
|
|
14964
15535
|
return true;
|
|
14965
15536
|
}
|
|
14966
15537
|
function setupContinueCommand(program) {
|
|
14967
|
-
const continueCommand = program.command("continue").description("Continue the most recent juno-code session with saved settings").argument("[prompt_text...]", "Prompt text (positional, alternative to -p)").option(
|
|
15538
|
+
const continueCommand = program.command("continue").alias("contiue").description("Continue the most recent juno-code session with saved settings").argument("[prompt_text...]", "Prompt text (positional, alternative to -p)").option(
|
|
14968
15539
|
"-p, --prompt [text]",
|
|
14969
|
-
"Prompt input (inline text, file path, or
|
|
15540
|
+
"Prompt input (inline text, file path, or heredoc/stdin; supports !'cmd' and !```cmd``` substitutions, prefer single quotes for shell metacharacters)"
|
|
14970
15541
|
).option("-f, --prompt-file <path>", "Read prompt from a file (shell-safe for backticks/$())").option("-w, --cwd <path>", "Working directory").option("-i, --max-iterations <number>", "Override max iterations for this continue run", parseInt).option("-m, --model <name>", "Override model for this continue run").option("-s, --subagent <name>", "Override subagent for this continue run").option("-I, --interactive", "Interactive mode for typing prompts").option("--live", "Run Pi subagent in interactive live TUI mode (pi only)").option("--thinking <level>", "Override thinking level for this continue run").action(async (promptArgs, options, command) => {
|
|
14971
15542
|
if (promptArgs.length > 0 && options.prompt === void 0) {
|
|
14972
15543
|
options.prompt = promptArgs.join(" ");
|
|
@@ -15041,7 +15612,7 @@ function setupContinueScopeCommand(program) {
|
|
|
15041
15612
|
function setupMainCommand(program) {
|
|
15042
15613
|
program.argument("[prompt_text...]", "Prompt text (positional, alternative to -p)").option(
|
|
15043
15614
|
"-p, --prompt [text]",
|
|
15044
|
-
"Prompt input (inline text, file path, or
|
|
15615
|
+
"Prompt input (inline text, file path, or heredoc/stdin; supports !'cmd' and !```cmd``` substitutions, prefer single quotes for shell metacharacters)"
|
|
15045
15616
|
).option("-f, --prompt-file <path>", "Read prompt from a file (shell-safe for backticks/$())").option("-w, --cwd <path>", "Working directory").option("-i, --max-iterations <number>", "Maximum iterations (-1 for unlimited)", parseInt).option("-I, --interactive", "Interactive mode for typing prompts").option("--live", "Run Pi subagent in interactive live TUI mode (pi only)").option("-ip, --interactive-prompt", "Launch interactive prompt editor").action(async (promptArgs, options, command) => {
|
|
15046
15617
|
if (promptArgs.length > 0 && options.prompt === void 0) {
|
|
15047
15618
|
options.prompt = promptArgs.join(" ");
|
|
@@ -15215,6 +15786,11 @@ ${chalk21.blue("Examples:")}
|
|
|
15215
15786
|
|
|
15216
15787
|
${chalk21.gray("# Shell safety")}
|
|
15217
15788
|
${chalk21.gray("Use single quotes (or -f/stdin) when prompts contain backticks or $()")}
|
|
15789
|
+
|
|
15790
|
+
${chalk21.gray("# Prompt-time substitutions (refreshed each iteration)")}
|
|
15791
|
+
juno-code claude -p "Status: !'git status --short'"
|
|
15792
|
+
juno-code claude -i 3 -p "Recent commits:
|
|
15793
|
+
!\`\`\`git log -n 5 --oneline\`\`\`"
|
|
15218
15794
|
`
|
|
15219
15795
|
},
|
|
15220
15796
|
pi: {
|
|
@@ -15403,7 +15979,7 @@ function setupAliases(program) {
|
|
|
15403
15979
|
if (!help) continue;
|
|
15404
15980
|
const cmd = program.command(subagent).description(help.description).argument("[prompt...]", "Prompt text or file path").option(
|
|
15405
15981
|
"-p, --prompt [text]",
|
|
15406
|
-
"Prompt input (inline text, or
|
|
15982
|
+
"Prompt input (inline text, or heredoc/stdin; supports !'cmd' and !```cmd``` substitutions, prefer single quotes for shell metacharacters)"
|
|
15407
15983
|
).option("-f, --prompt-file <path>", "Read prompt from a file (shell-safe for backticks/$())").option("-w, --cwd <path>", "Working directory").option("-i, --max-iterations <number>", "Maximum iterations (-1 for unlimited)", parseInt).option("-m, --model <name>", "Model to use (see model shorthands below)").option("-r, --resume <sessionId>", "Resume a conversation by session ID").option("--continue", "Continue the most recent conversation").option("-I, --interactive", "Interactive mode for typing prompts").option("--live", "Run Pi subagent in interactive live TUI mode (pi only)").addHelpText("after", help.helpText).action(async (promptArgs, options, command) => {
|
|
15408
15984
|
if (promptArgs.length > 0 && options.prompt === void 0) {
|
|
15409
15985
|
options.prompt = promptArgs.join(" ");
|
|
@@ -15428,9 +16004,24 @@ function setupAliases(program) {
|
|
|
15428
16004
|
handleCLIError(error, normalizeVerbose(options.verbose));
|
|
15429
16005
|
}
|
|
15430
16006
|
});
|
|
15431
|
-
cmd.command("set-default-model <model>").description(`Set default model for the ${subagent} subagent in .juno_task/config.json`).option("-w, --cwd <path>", "Working directory").action(async (model, commandOptions) => {
|
|
16007
|
+
cmd.command("set-default-model <model>").description(`Set default model for the ${subagent} subagent in .juno_task/config.json`).option("-w, --cwd <path>", "Working directory").action(async (model, commandOptions, command) => {
|
|
16008
|
+
const mergedOptions = (() => {
|
|
16009
|
+
const commandWithGlobals = command;
|
|
16010
|
+
if (typeof commandWithGlobals.optsWithGlobals === "function") {
|
|
16011
|
+
return {
|
|
16012
|
+
...commandWithGlobals.optsWithGlobals(),
|
|
16013
|
+
...commandOptions
|
|
16014
|
+
};
|
|
16015
|
+
}
|
|
16016
|
+
const parentOptions = command.parent?.opts ? command.parent.opts() : {};
|
|
16017
|
+
return {
|
|
16018
|
+
...parentOptions,
|
|
16019
|
+
...commandOptions
|
|
16020
|
+
};
|
|
16021
|
+
})();
|
|
15432
16022
|
try {
|
|
15433
|
-
const
|
|
16023
|
+
const optionCwd = typeof mergedOptions.cwd === "string" && mergedOptions.cwd.trim().length > 0 ? mergedOptions.cwd.trim() : extractOptionValueFromArgv(process.argv.slice(2), "--cwd", "-w");
|
|
16024
|
+
const workingDirectory = typeof optionCwd === "string" && optionCwd.trim().length > 0 ? optionCwd.trim() : process.cwd();
|
|
15434
16025
|
const [{ loadConfig: loadConfig2 }, subagentModels, fsExtra2, nodePath] = await Promise.all([
|
|
15435
16026
|
Promise.resolve().then(() => (init_config(), config_exports)),
|
|
15436
16027
|
Promise.resolve().then(() => (init_subagent_models(), subagent_models_exports)),
|
|
@@ -15471,7 +16062,7 @@ function setupAliases(program) {
|
|
|
15471
16062
|
)
|
|
15472
16063
|
);
|
|
15473
16064
|
} catch (error) {
|
|
15474
|
-
handleCLIError(error, normalizeVerbose(
|
|
16065
|
+
handleCLIError(error, normalizeVerbose(mergedOptions.verbose));
|
|
15475
16066
|
}
|
|
15476
16067
|
});
|
|
15477
16068
|
cmd.allowUnknownOption(true);
|
|
@@ -15668,6 +16259,11 @@ ${chalk21.blue.bold("Examples:")}
|
|
|
15668
16259
|
${chalk21.gray("# Shell safety")}
|
|
15669
16260
|
${chalk21.gray("Use single quotes or -f/stdin when prompts include backticks or $()")}
|
|
15670
16261
|
|
|
16262
|
+
${chalk21.gray("# Prompt-time command substitution (per iteration)")}
|
|
16263
|
+
juno-code claude -p "Status: !'git status --short'"
|
|
16264
|
+
juno-code claude -i 3 -p "Recent commits:
|
|
16265
|
+
!\`\`\`git log -n 5 --oneline\`\`\`"
|
|
16266
|
+
|
|
15671
16267
|
${chalk21.gray("# Interactive project setup")}
|
|
15672
16268
|
juno-code init --interactive
|
|
15673
16269
|
|