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.js
CHANGED
|
@@ -13,9 +13,9 @@ var yaml = require('js-yaml');
|
|
|
13
13
|
var crypto = require('crypto');
|
|
14
14
|
var chalk21 = require('chalk');
|
|
15
15
|
var execa = require('execa');
|
|
16
|
-
var
|
|
17
|
-
var events = require('events');
|
|
16
|
+
var childProcess = require('child_process');
|
|
18
17
|
var util = require('util');
|
|
18
|
+
var events = require('events');
|
|
19
19
|
var commander = require('commander');
|
|
20
20
|
var readline = require('readline');
|
|
21
21
|
var uuid = require('uuid');
|
|
@@ -54,6 +54,7 @@ var semver__default = /*#__PURE__*/_interopDefault(semver);
|
|
|
54
54
|
var fs8__namespace = /*#__PURE__*/_interopNamespace(fs8);
|
|
55
55
|
var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
|
|
56
56
|
var chalk21__default = /*#__PURE__*/_interopDefault(chalk21);
|
|
57
|
+
var childProcess__namespace = /*#__PURE__*/_interopNamespace(childProcess);
|
|
57
58
|
var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
|
|
58
59
|
var process2__namespace = /*#__PURE__*/_interopNamespace(process2);
|
|
59
60
|
var Table__default = /*#__PURE__*/_interopDefault(Table);
|
|
@@ -292,14 +293,14 @@ function isModelCompatibleWithSubagent(model, subagent) {
|
|
|
292
293
|
}
|
|
293
294
|
}
|
|
294
295
|
function getConfiguredDefaultModelForSubagent(config, subagent) {
|
|
295
|
-
const legacyDefaultModel = config.defaultSubagent === subagent && typeof config.defaultModel === "string" && isModelCompatibleWithSubagent(config.defaultModel, subagent) ? config.defaultModel : void 0;
|
|
296
|
-
if (legacyDefaultModel) {
|
|
297
|
-
return legacyDefaultModel;
|
|
298
|
-
}
|
|
299
296
|
const modelFromMap = config.defaultModels?.[subagent];
|
|
300
297
|
if (typeof modelFromMap === "string" && isModelCompatibleWithSubagent(modelFromMap, subagent)) {
|
|
301
298
|
return modelFromMap;
|
|
302
299
|
}
|
|
300
|
+
const legacyDefaultModel = config.defaultSubagent === subagent && typeof config.defaultModel === "string" && isModelCompatibleWithSubagent(config.defaultModel, subagent) ? config.defaultModel : void 0;
|
|
301
|
+
if (legacyDefaultModel) {
|
|
302
|
+
return legacyDefaultModel;
|
|
303
|
+
}
|
|
303
304
|
return void 0;
|
|
304
305
|
}
|
|
305
306
|
var SUBAGENT_DEFAULT_MODELS;
|
|
@@ -867,6 +868,13 @@ async function ensureHooksConfig(baseDir) {
|
|
|
867
868
|
existingConfig.defaultModels = baseDefaults;
|
|
868
869
|
needsUpdate = true;
|
|
869
870
|
}
|
|
871
|
+
const selectedSubagentRaw = typeof existingConfig.defaultSubagent === "string" ? existingConfig.defaultSubagent : "claude";
|
|
872
|
+
const selectedSubagent = selectedSubagentRaw in SUBAGENT_DEFAULT_MODELS ? selectedSubagentRaw : "claude";
|
|
873
|
+
const selectedMapModel = existingConfig.defaultModels && typeof existingConfig.defaultModels === "object" ? existingConfig.defaultModels[selectedSubagent] : void 0;
|
|
874
|
+
if (typeof selectedMapModel === "string" && isModelCompatibleWithSubagent(selectedMapModel, selectedSubagent) && existingConfig.defaultModel !== selectedMapModel) {
|
|
875
|
+
existingConfig.defaultModel = selectedMapModel;
|
|
876
|
+
needsUpdate = true;
|
|
877
|
+
}
|
|
870
878
|
if (existingConfig.defaultMaxIterations === 50) {
|
|
871
879
|
existingConfig.defaultMaxIterations = DEFAULT_CONFIG.defaultMaxIterations;
|
|
872
880
|
needsUpdate = true;
|
|
@@ -2391,25 +2399,28 @@ var init_shell_backend = __esm({
|
|
|
2391
2399
|
const scriptPath = await this.findScriptForSubagent(subagentType);
|
|
2392
2400
|
const result = await this.executeScript(scriptPath, request, toolId, subagentType);
|
|
2393
2401
|
const duration = Date.now() - startTime;
|
|
2402
|
+
const structuredResult = this.buildStructuredOutput(subagentType, result);
|
|
2403
|
+
const structuredPayload = this.parseStructuredResultPayload(structuredResult.content);
|
|
2404
|
+
const structuredIndicatesError = structuredPayload?.is_error === true || structuredPayload?.subtype === "error";
|
|
2405
|
+
const executionSucceeded = result.success && !structuredIndicatesError;
|
|
2394
2406
|
await this.emitProgressEvent({
|
|
2395
2407
|
sessionId: request.metadata?.sessionId || "unknown",
|
|
2396
2408
|
timestamp: /* @__PURE__ */ new Date(),
|
|
2397
2409
|
backend: "shell",
|
|
2398
2410
|
count: ++this.eventCounter,
|
|
2399
2411
|
type: "tool_result" /* TOOL_RESULT */,
|
|
2400
|
-
content: `${request.toolName} completed successfully (${duration}ms)`,
|
|
2412
|
+
content: executionSucceeded ? `${request.toolName} completed successfully (${duration}ms)` : `${request.toolName} completed with error (${duration}ms)`,
|
|
2401
2413
|
toolId,
|
|
2402
2414
|
metadata: {
|
|
2403
2415
|
toolName: request.toolName,
|
|
2404
2416
|
duration,
|
|
2405
|
-
success:
|
|
2417
|
+
success: executionSucceeded,
|
|
2406
2418
|
phase: "completion"
|
|
2407
2419
|
}
|
|
2408
2420
|
});
|
|
2409
|
-
const structuredResult = this.buildStructuredOutput(subagentType, result);
|
|
2410
2421
|
const toolResult = {
|
|
2411
2422
|
content: structuredResult.content,
|
|
2412
|
-
status:
|
|
2423
|
+
status: executionSucceeded ? "completed" /* COMPLETED */ : "failed" /* FAILED */,
|
|
2413
2424
|
startTime: new Date(startTime),
|
|
2414
2425
|
endTime: /* @__PURE__ */ new Date(),
|
|
2415
2426
|
duration,
|
|
@@ -2418,6 +2429,9 @@ var init_shell_backend = __esm({
|
|
|
2418
2429
|
};
|
|
2419
2430
|
if (result.error) {
|
|
2420
2431
|
toolResult.error = new Error(result.error);
|
|
2432
|
+
} else if (!executionSucceeded) {
|
|
2433
|
+
const structuredErrorMessage = typeof structuredPayload?.error === "string" && structuredPayload.error || typeof structuredPayload?.result === "string" && structuredPayload.result || `${request.toolName} reported a structured error`;
|
|
2434
|
+
toolResult.error = new Error(structuredErrorMessage);
|
|
2421
2435
|
}
|
|
2422
2436
|
if (structuredResult.metadata) {
|
|
2423
2437
|
toolResult.metadata = structuredResult.metadata;
|
|
@@ -2669,6 +2683,9 @@ var init_shell_backend = __esm({
|
|
|
2669
2683
|
if (isPython && subagentType === "pi" && request.arguments?.live === true) {
|
|
2670
2684
|
args.push("--live");
|
|
2671
2685
|
}
|
|
2686
|
+
if (isPython && subagentType === "pi" && request.arguments?.liveInteractiveSession === true) {
|
|
2687
|
+
args.push("--live-manual");
|
|
2688
|
+
}
|
|
2672
2689
|
if (isPython && this.config.debug) {
|
|
2673
2690
|
args.push("--verbose");
|
|
2674
2691
|
}
|
|
@@ -2693,7 +2710,7 @@ var init_shell_backend = __esm({
|
|
|
2693
2710
|
`Pi live mode stdio: ${shouldAttachLiveTerminal ? "inherit (interactive TTY or stdout-tty fallback)" : "pipe (headless/non-TTY)"}`
|
|
2694
2711
|
);
|
|
2695
2712
|
}
|
|
2696
|
-
const child =
|
|
2713
|
+
const child = childProcess.spawn(command, args, {
|
|
2697
2714
|
env: env2,
|
|
2698
2715
|
cwd: this.config.workingDirectory,
|
|
2699
2716
|
stdio: shouldAttachLiveTerminal ? "inherit" : ["pipe", "pipe", "pipe"]
|
|
@@ -2951,8 +2968,19 @@ var init_shell_backend = __esm({
|
|
|
2951
2968
|
if (subagentType === "pi") {
|
|
2952
2969
|
const piEvent = result.subAgentResponse ?? this.extractLastJsonEvent(result.output);
|
|
2953
2970
|
if (piEvent) {
|
|
2954
|
-
|
|
2955
|
-
|
|
2971
|
+
const piNestedEvent = typeof piEvent.sub_agent_response === "object" && piEvent.sub_agent_response ? piEvent.sub_agent_response : void 0;
|
|
2972
|
+
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;
|
|
2973
|
+
const sanitizedPiEvent = { ...piEvent };
|
|
2974
|
+
delete sanitizedPiEvent.messages;
|
|
2975
|
+
if (sanitizedPiEvent.sub_agent_response && typeof sanitizedPiEvent.sub_agent_response === "object") {
|
|
2976
|
+
const inner = { ...sanitizedPiEvent.sub_agent_response };
|
|
2977
|
+
delete inner.messages;
|
|
2978
|
+
delete inner.type;
|
|
2979
|
+
sanitizedPiEvent.sub_agent_response = inner;
|
|
2980
|
+
}
|
|
2981
|
+
const hasDirectResultText = typeof piEvent.result === "string";
|
|
2982
|
+
let resultText = hasDirectResultText ? piEvent.result : void 0;
|
|
2983
|
+
if (resultText === void 0 && Array.isArray(piEvent.messages)) {
|
|
2956
2984
|
for (let i = piEvent.messages.length - 1; i >= 0; i--) {
|
|
2957
2985
|
const msg = piEvent.messages[i];
|
|
2958
2986
|
if (msg?.role === "assistant") {
|
|
@@ -2972,16 +3000,11 @@ var init_shell_backend = __esm({
|
|
|
2972
3000
|
}
|
|
2973
3001
|
}
|
|
2974
3002
|
}
|
|
2975
|
-
if (resultText) {
|
|
3003
|
+
if (resultText === void 0 && typeof piEvent.error === "string") {
|
|
3004
|
+
resultText = piEvent.error;
|
|
3005
|
+
}
|
|
3006
|
+
if (resultText !== void 0) {
|
|
2976
3007
|
const isError = piEvent.is_error ?? !result.success;
|
|
2977
|
-
const sanitizedPiEvent = { ...piEvent };
|
|
2978
|
-
delete sanitizedPiEvent.messages;
|
|
2979
|
-
if (sanitizedPiEvent.sub_agent_response && typeof sanitizedPiEvent.sub_agent_response === "object") {
|
|
2980
|
-
const inner = { ...sanitizedPiEvent.sub_agent_response };
|
|
2981
|
-
delete inner.messages;
|
|
2982
|
-
delete inner.type;
|
|
2983
|
-
sanitizedPiEvent.sub_agent_response = inner;
|
|
2984
|
-
}
|
|
2985
3008
|
const usage = piEvent.usage;
|
|
2986
3009
|
const totalCostUsd = typeof piEvent.total_cost_usd === "number" ? piEvent.total_cost_usd : typeof usage?.cost?.total === "number" ? usage.cost.total : void 0;
|
|
2987
3010
|
const structuredPayload = {
|
|
@@ -2989,9 +3012,9 @@ var init_shell_backend = __esm({
|
|
|
2989
3012
|
subtype: piEvent.subtype || (isError ? "error" : "success"),
|
|
2990
3013
|
is_error: isError,
|
|
2991
3014
|
result: resultText,
|
|
2992
|
-
error: piEvent.error,
|
|
3015
|
+
error: isError ? piEvent.error ?? result.error ?? resultText : piEvent.error,
|
|
2993
3016
|
stderr: result.error,
|
|
2994
|
-
session_id:
|
|
3017
|
+
session_id: piSessionId,
|
|
2995
3018
|
exit_code: result.exitCode,
|
|
2996
3019
|
duration_ms: piEvent.duration_ms ?? result.duration,
|
|
2997
3020
|
total_cost_usd: totalCostUsd,
|
|
@@ -3009,6 +3032,57 @@ var init_shell_backend = __esm({
|
|
|
3009
3032
|
metadata
|
|
3010
3033
|
};
|
|
3011
3034
|
}
|
|
3035
|
+
const isSessionSnapshotOnly = piEvent.type === "session" || piEvent.subtype === "session";
|
|
3036
|
+
if (isSessionSnapshotOnly) {
|
|
3037
|
+
const errorMessage = result.error?.trim() || "Pi exited before emitting a terminal result event (session snapshot only).";
|
|
3038
|
+
const structuredPayload = {
|
|
3039
|
+
type: "result",
|
|
3040
|
+
subtype: "error",
|
|
3041
|
+
is_error: true,
|
|
3042
|
+
result: errorMessage,
|
|
3043
|
+
error: errorMessage,
|
|
3044
|
+
stderr: result.error,
|
|
3045
|
+
session_id: piSessionId,
|
|
3046
|
+
exit_code: result.exitCode,
|
|
3047
|
+
duration_ms: result.duration,
|
|
3048
|
+
sub_agent_response: sanitizedPiEvent
|
|
3049
|
+
};
|
|
3050
|
+
const metadata = {
|
|
3051
|
+
...piEvent ? { subAgentResponse: piEvent } : void 0,
|
|
3052
|
+
structuredOutput: true,
|
|
3053
|
+
contentType: "application/json",
|
|
3054
|
+
rawOutput: result.output
|
|
3055
|
+
};
|
|
3056
|
+
return {
|
|
3057
|
+
content: JSON.stringify(structuredPayload),
|
|
3058
|
+
metadata
|
|
3059
|
+
};
|
|
3060
|
+
}
|
|
3061
|
+
if (!result.success) {
|
|
3062
|
+
const errorMessage = result.error?.trim() || result.output?.trim() || "Unknown error";
|
|
3063
|
+
const structuredPayload = {
|
|
3064
|
+
type: "result",
|
|
3065
|
+
subtype: "error",
|
|
3066
|
+
is_error: true,
|
|
3067
|
+
result: errorMessage,
|
|
3068
|
+
error: errorMessage,
|
|
3069
|
+
stderr: result.error,
|
|
3070
|
+
session_id: piSessionId,
|
|
3071
|
+
exit_code: result.exitCode,
|
|
3072
|
+
duration_ms: result.duration,
|
|
3073
|
+
sub_agent_response: sanitizedPiEvent
|
|
3074
|
+
};
|
|
3075
|
+
const metadata = {
|
|
3076
|
+
...piEvent ? { subAgentResponse: piEvent } : void 0,
|
|
3077
|
+
structuredOutput: true,
|
|
3078
|
+
contentType: "application/json",
|
|
3079
|
+
rawOutput: result.output
|
|
3080
|
+
};
|
|
3081
|
+
return {
|
|
3082
|
+
content: JSON.stringify(structuredPayload),
|
|
3083
|
+
metadata
|
|
3084
|
+
};
|
|
3085
|
+
}
|
|
3012
3086
|
}
|
|
3013
3087
|
}
|
|
3014
3088
|
if (!result.success) {
|
|
@@ -3073,6 +3147,20 @@ var init_shell_backend = __esm({
|
|
|
3073
3147
|
}
|
|
3074
3148
|
return null;
|
|
3075
3149
|
}
|
|
3150
|
+
/**
|
|
3151
|
+
* Parse JSON structured output payload emitted by shell service wrappers.
|
|
3152
|
+
*/
|
|
3153
|
+
parseStructuredResultPayload(content) {
|
|
3154
|
+
try {
|
|
3155
|
+
const parsed = JSON.parse(content);
|
|
3156
|
+
if (!parsed || typeof parsed !== "object") {
|
|
3157
|
+
return null;
|
|
3158
|
+
}
|
|
3159
|
+
return parsed;
|
|
3160
|
+
} catch {
|
|
3161
|
+
return null;
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3076
3164
|
/**
|
|
3077
3165
|
* Extract the last valid JSON object from a script's stdout to use as a structured payload fallback.
|
|
3078
3166
|
*/
|
|
@@ -3331,6 +3419,179 @@ var init_shell_backend = __esm({
|
|
|
3331
3419
|
};
|
|
3332
3420
|
}
|
|
3333
3421
|
});
|
|
3422
|
+
function findPromptCommandSubstitutions(prompt) {
|
|
3423
|
+
const matches = [];
|
|
3424
|
+
let cursor = 0;
|
|
3425
|
+
while (cursor < prompt.length) {
|
|
3426
|
+
const singleQuotedStart = prompt.indexOf(SINGLE_QUOTED_MARKER, cursor);
|
|
3427
|
+
const tripleBacktickStart = prompt.indexOf(TRIPLE_BACKTICK_MARKER, cursor);
|
|
3428
|
+
const markerStart = chooseNearestMarker(singleQuotedStart, tripleBacktickStart);
|
|
3429
|
+
if (markerStart === null) {
|
|
3430
|
+
break;
|
|
3431
|
+
}
|
|
3432
|
+
if (markerStart === singleQuotedStart) {
|
|
3433
|
+
const parsedSingleQuoted = parseSingleQuotedSubstitution(prompt, markerStart);
|
|
3434
|
+
if (!parsedSingleQuoted) {
|
|
3435
|
+
cursor = markerStart + SINGLE_QUOTED_MARKER.length;
|
|
3436
|
+
continue;
|
|
3437
|
+
}
|
|
3438
|
+
matches.push(parsedSingleQuoted);
|
|
3439
|
+
cursor = parsedSingleQuoted.endIndex;
|
|
3440
|
+
continue;
|
|
3441
|
+
}
|
|
3442
|
+
const parsedTripleBacktick = parseTripleBacktickSubstitution(prompt, markerStart);
|
|
3443
|
+
if (!parsedTripleBacktick) {
|
|
3444
|
+
cursor = markerStart + TRIPLE_BACKTICK_MARKER.length;
|
|
3445
|
+
continue;
|
|
3446
|
+
}
|
|
3447
|
+
matches.push(parsedTripleBacktick);
|
|
3448
|
+
cursor = parsedTripleBacktick.endIndex;
|
|
3449
|
+
}
|
|
3450
|
+
return matches;
|
|
3451
|
+
}
|
|
3452
|
+
async function resolvePromptCommandSubstitutions(prompt, options) {
|
|
3453
|
+
const matches = findPromptCommandSubstitutions(prompt);
|
|
3454
|
+
if (matches.length === 0) {
|
|
3455
|
+
return prompt;
|
|
3456
|
+
}
|
|
3457
|
+
const executor = options.executor ?? createDefaultPromptCommandExecutor(options);
|
|
3458
|
+
let result = "";
|
|
3459
|
+
let cursor = 0;
|
|
3460
|
+
for (const match of matches) {
|
|
3461
|
+
result += prompt.slice(cursor, match.startIndex);
|
|
3462
|
+
const commandOutput = await executor(match.command);
|
|
3463
|
+
result += normalizeCommandOutput(commandOutput);
|
|
3464
|
+
cursor = match.endIndex;
|
|
3465
|
+
}
|
|
3466
|
+
result += prompt.slice(cursor);
|
|
3467
|
+
return result;
|
|
3468
|
+
}
|
|
3469
|
+
function chooseNearestMarker(singleQuotedStart, tripleBacktickStart) {
|
|
3470
|
+
const singleExists = singleQuotedStart >= 0;
|
|
3471
|
+
const tripleExists = tripleBacktickStart >= 0;
|
|
3472
|
+
if (!singleExists && !tripleExists) {
|
|
3473
|
+
return null;
|
|
3474
|
+
}
|
|
3475
|
+
if (!singleExists) {
|
|
3476
|
+
return tripleBacktickStart;
|
|
3477
|
+
}
|
|
3478
|
+
if (!tripleExists) {
|
|
3479
|
+
return singleQuotedStart;
|
|
3480
|
+
}
|
|
3481
|
+
return Math.min(singleQuotedStart, tripleBacktickStart);
|
|
3482
|
+
}
|
|
3483
|
+
function parseSingleQuotedSubstitution(prompt, markerStart) {
|
|
3484
|
+
const contentStart = markerStart + SINGLE_QUOTED_MARKER.length;
|
|
3485
|
+
const closingQuote = findClosingSingleQuote(prompt, contentStart);
|
|
3486
|
+
if (closingQuote < 0) {
|
|
3487
|
+
return null;
|
|
3488
|
+
}
|
|
3489
|
+
const raw = prompt.slice(markerStart, closingQuote + 1);
|
|
3490
|
+
const command = prompt.slice(contentStart, closingQuote);
|
|
3491
|
+
return {
|
|
3492
|
+
syntax: "single-quoted",
|
|
3493
|
+
startIndex: markerStart,
|
|
3494
|
+
endIndex: closingQuote + 1,
|
|
3495
|
+
command,
|
|
3496
|
+
raw
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
function findClosingSingleQuote(prompt, startIndex) {
|
|
3500
|
+
let escaped = false;
|
|
3501
|
+
for (let index = startIndex; index < prompt.length; index++) {
|
|
3502
|
+
const char = prompt[index];
|
|
3503
|
+
if (char === "'" && !escaped) {
|
|
3504
|
+
return index;
|
|
3505
|
+
}
|
|
3506
|
+
if (char === "\\" && !escaped) {
|
|
3507
|
+
escaped = true;
|
|
3508
|
+
continue;
|
|
3509
|
+
}
|
|
3510
|
+
escaped = false;
|
|
3511
|
+
}
|
|
3512
|
+
return -1;
|
|
3513
|
+
}
|
|
3514
|
+
function parseTripleBacktickSubstitution(prompt, markerStart) {
|
|
3515
|
+
const contentStart = markerStart + TRIPLE_BACKTICK_MARKER.length;
|
|
3516
|
+
const closingBackticks = prompt.indexOf(TRIPLE_BACKTICK_CLOSER, contentStart);
|
|
3517
|
+
if (closingBackticks < 0) {
|
|
3518
|
+
return null;
|
|
3519
|
+
}
|
|
3520
|
+
const raw = prompt.slice(markerStart, closingBackticks + TRIPLE_BACKTICK_CLOSER.length);
|
|
3521
|
+
const command = prompt.slice(contentStart, closingBackticks);
|
|
3522
|
+
return {
|
|
3523
|
+
syntax: "triple-backtick",
|
|
3524
|
+
startIndex: markerStart,
|
|
3525
|
+
endIndex: closingBackticks + TRIPLE_BACKTICK_CLOSER.length,
|
|
3526
|
+
command,
|
|
3527
|
+
raw
|
|
3528
|
+
};
|
|
3529
|
+
}
|
|
3530
|
+
function createDefaultPromptCommandExecutor(options) {
|
|
3531
|
+
const execFile3 = util.promisify(childProcess__namespace.execFile);
|
|
3532
|
+
const maxBufferBytes = options.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES;
|
|
3533
|
+
const commandTimeoutMs = resolvePromptCommandTimeoutMs(options.commandTimeoutMs);
|
|
3534
|
+
const shell = process.env.SHELL || "/bin/bash";
|
|
3535
|
+
return async (command) => {
|
|
3536
|
+
const normalizedCommand = command.trim();
|
|
3537
|
+
if (!normalizedCommand) {
|
|
3538
|
+
return "";
|
|
3539
|
+
}
|
|
3540
|
+
const commandForExecution = wrapCommandForNonInteractiveExecution(normalizedCommand);
|
|
3541
|
+
try {
|
|
3542
|
+
const result = await execFile3(shell, ["-lc", commandForExecution], {
|
|
3543
|
+
cwd: options.workingDirectory,
|
|
3544
|
+
env: options.environment ?? process.env,
|
|
3545
|
+
maxBuffer: maxBufferBytes,
|
|
3546
|
+
timeout: commandTimeoutMs
|
|
3547
|
+
});
|
|
3548
|
+
const stdout2 = typeof result === "string" || Buffer.isBuffer(result) ? String(result) : String(result.stdout ?? "");
|
|
3549
|
+
return stdout2;
|
|
3550
|
+
} catch (error) {
|
|
3551
|
+
const failedCommand = normalizedCommand.replace(/\s+/g, " ").trim();
|
|
3552
|
+
const details = error && typeof error === "object" && "stderr" in error ? String(error.stderr ?? "").trim() : "";
|
|
3553
|
+
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 ?? "")));
|
|
3554
|
+
if (timeoutDetected) {
|
|
3555
|
+
throw new Error(
|
|
3556
|
+
`Prompt command substitution timed out after ${commandTimeoutMs}ms for \`${failedCommand}\``
|
|
3557
|
+
);
|
|
3558
|
+
}
|
|
3559
|
+
const suffix = details ? `: ${details}` : "";
|
|
3560
|
+
throw new Error(`Prompt command substitution failed for \`${failedCommand}\`${suffix}`);
|
|
3561
|
+
}
|
|
3562
|
+
};
|
|
3563
|
+
}
|
|
3564
|
+
function resolvePromptCommandTimeoutMs(explicitTimeoutMs) {
|
|
3565
|
+
if (typeof explicitTimeoutMs === "number" && Number.isFinite(explicitTimeoutMs) && explicitTimeoutMs > 0) {
|
|
3566
|
+
return explicitTimeoutMs;
|
|
3567
|
+
}
|
|
3568
|
+
const envValue = process.env[COMMAND_TIMEOUT_ENV_KEY];
|
|
3569
|
+
if (envValue !== void 0) {
|
|
3570
|
+
const parsed = Number(envValue);
|
|
3571
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
3572
|
+
return parsed;
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
return DEFAULT_COMMAND_TIMEOUT_MS;
|
|
3576
|
+
}
|
|
3577
|
+
function wrapCommandForNonInteractiveExecution(command) {
|
|
3578
|
+
return `(${command}) </dev/null`;
|
|
3579
|
+
}
|
|
3580
|
+
function normalizeCommandOutput(output) {
|
|
3581
|
+
return output.replace(/\r?\n$/, "");
|
|
3582
|
+
}
|
|
3583
|
+
var SINGLE_QUOTED_MARKER, TRIPLE_BACKTICK_MARKER, TRIPLE_BACKTICK_CLOSER, DEFAULT_MAX_BUFFER_BYTES, DEFAULT_COMMAND_TIMEOUT_MS, COMMAND_TIMEOUT_ENV_KEY;
|
|
3584
|
+
var init_prompt_command_substitution = __esm({
|
|
3585
|
+
"src/core/prompt-command-substitution.ts"() {
|
|
3586
|
+
init_version();
|
|
3587
|
+
SINGLE_QUOTED_MARKER = "!'";
|
|
3588
|
+
TRIPLE_BACKTICK_MARKER = "!```";
|
|
3589
|
+
TRIPLE_BACKTICK_CLOSER = "```";
|
|
3590
|
+
DEFAULT_MAX_BUFFER_BYTES = 1024 * 1024;
|
|
3591
|
+
DEFAULT_COMMAND_TIMEOUT_MS = 3e4;
|
|
3592
|
+
COMMAND_TIMEOUT_ENV_KEY = "JUNO_CODE_PROMPT_SUBSTITUTION_TIMEOUT_MS";
|
|
3593
|
+
}
|
|
3594
|
+
});
|
|
3334
3595
|
function createExecutionEngine(config) {
|
|
3335
3596
|
return new ExecutionEngine({
|
|
3336
3597
|
config,
|
|
@@ -3381,6 +3642,9 @@ function createExecutionRequest(options) {
|
|
|
3381
3642
|
if (options.live !== void 0) {
|
|
3382
3643
|
result.live = options.live;
|
|
3383
3644
|
}
|
|
3645
|
+
if (options.liveInteractiveSession !== void 0) {
|
|
3646
|
+
result.liveInteractiveSession = options.liveInteractiveSession;
|
|
3647
|
+
}
|
|
3384
3648
|
return result;
|
|
3385
3649
|
}
|
|
3386
3650
|
var DEFAULT_ERROR_RECOVERY_CONFIG, DEFAULT_RATE_LIMIT_CONFIG, DEFAULT_PROGRESS_CONFIG, ExecutionEngine;
|
|
@@ -3391,6 +3655,7 @@ var init_engine = __esm({
|
|
|
3391
3655
|
init_hooks();
|
|
3392
3656
|
init_advanced_logger();
|
|
3393
3657
|
init_shell_backend();
|
|
3658
|
+
init_prompt_command_substitution();
|
|
3394
3659
|
DEFAULT_ERROR_RECOVERY_CONFIG = {
|
|
3395
3660
|
maxAttempts: {
|
|
3396
3661
|
connection: 3,
|
|
@@ -3687,7 +3952,8 @@ var init_engine = __esm({
|
|
|
3687
3952
|
if (!request.requestId?.trim()) {
|
|
3688
3953
|
throw new Error("Request ID is required");
|
|
3689
3954
|
}
|
|
3690
|
-
|
|
3955
|
+
const allowEmptyInstructionForPiLiveInteractiveSession = request.subagent === "pi" && request.live === true && request.liveInteractiveSession === true && typeof request.resume === "string" && request.resume.trim().length > 0;
|
|
3956
|
+
if (!request.instruction?.trim() && !allowEmptyInstructionForPiLiveInteractiveSession) {
|
|
3691
3957
|
throw new Error("Instruction is required");
|
|
3692
3958
|
}
|
|
3693
3959
|
if (!request.subagent?.trim()) {
|
|
@@ -3925,44 +4191,62 @@ var init_engine = __esm({
|
|
|
3925
4191
|
engineLogger.warn("Hook START_ITERATION failed", { error, iterationNumber });
|
|
3926
4192
|
}
|
|
3927
4193
|
this.emit("iteration:start", { context, iterationNumber });
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
4194
|
+
let toolRequest = null;
|
|
4195
|
+
try {
|
|
4196
|
+
const instructionTemplate = context.request.instruction;
|
|
4197
|
+
const resolvedInstruction = await resolvePromptCommandSubstitutions(instructionTemplate, {
|
|
4198
|
+
workingDirectory: context.request.workingDirectory,
|
|
4199
|
+
environment: {
|
|
4200
|
+
...process.env,
|
|
4201
|
+
JUNO_TASK_ROOT: process.env.JUNO_TASK_ROOT || context.request.workingDirectory
|
|
4202
|
+
}
|
|
4203
|
+
});
|
|
4204
|
+
this.emit("iteration:instruction-resolved", {
|
|
4205
|
+
context,
|
|
4206
|
+
iterationNumber,
|
|
4207
|
+
instruction: resolvedInstruction,
|
|
4208
|
+
templateInstruction: instructionTemplate
|
|
4209
|
+
});
|
|
4210
|
+
toolRequest = {
|
|
4211
|
+
toolName: this.getToolNameForSubagent(context.request.subagent),
|
|
4212
|
+
arguments: {
|
|
4213
|
+
instruction: resolvedInstruction,
|
|
4214
|
+
project_path: context.request.workingDirectory,
|
|
4215
|
+
...context.request.model !== void 0 && { model: context.request.model },
|
|
4216
|
+
...context.request.agents !== void 0 && { agents: context.request.agents },
|
|
4217
|
+
...context.request.tools !== void 0 && { tools: context.request.tools },
|
|
4218
|
+
...context.request.allowedTools !== void 0 && {
|
|
4219
|
+
allowedTools: context.request.allowedTools
|
|
4220
|
+
},
|
|
4221
|
+
...context.request.appendAllowedTools !== void 0 && {
|
|
4222
|
+
appendAllowedTools: context.request.appendAllowedTools
|
|
4223
|
+
},
|
|
4224
|
+
...context.request.disallowedTools !== void 0 && {
|
|
4225
|
+
disallowedTools: context.request.disallowedTools
|
|
4226
|
+
},
|
|
4227
|
+
...context.request.resume !== void 0 && { resume: context.request.resume },
|
|
4228
|
+
...context.request.continueConversation !== void 0 && {
|
|
4229
|
+
continueConversation: context.request.continueConversation
|
|
4230
|
+
},
|
|
4231
|
+
...context.request.thinking !== void 0 && { thinking: context.request.thinking },
|
|
4232
|
+
...context.request.live !== void 0 && { live: context.request.live },
|
|
4233
|
+
...context.request.liveInteractiveSession !== void 0 && {
|
|
4234
|
+
liveInteractiveSession: context.request.liveInteractiveSession
|
|
4235
|
+
},
|
|
4236
|
+
iteration: iterationNumber
|
|
3944
4237
|
},
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
4238
|
+
timeout: context.request.timeoutMs || this.engineConfig.config.mcpTimeout,
|
|
4239
|
+
priority: context.request.priority || "normal",
|
|
4240
|
+
metadata: {
|
|
4241
|
+
sessionId: context.sessionContext.sessionId,
|
|
4242
|
+
iterationNumber
|
|
3948
4243
|
},
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
metadata: {
|
|
3956
|
-
sessionId: context.sessionContext.sessionId,
|
|
3957
|
-
iterationNumber
|
|
3958
|
-
},
|
|
3959
|
-
progressCallback: async (event) => {
|
|
3960
|
-
context.progressEvents.push(event);
|
|
3961
|
-
context.statistics.totalProgressEvents++;
|
|
3962
|
-
await this.processProgressEvent(context, event);
|
|
3963
|
-
}
|
|
3964
|
-
};
|
|
3965
|
-
try {
|
|
4244
|
+
progressCallback: async (event) => {
|
|
4245
|
+
context.progressEvents.push(event);
|
|
4246
|
+
context.statistics.totalProgressEvents++;
|
|
4247
|
+
await this.processProgressEvent(context, event);
|
|
4248
|
+
}
|
|
4249
|
+
};
|
|
3966
4250
|
if (!this.currentBackend) {
|
|
3967
4251
|
throw new Error("No backend initialized. Call initializeBackend() first.");
|
|
3968
4252
|
}
|
|
@@ -4031,7 +4315,10 @@ var init_engine = __esm({
|
|
|
4031
4315
|
duration,
|
|
4032
4316
|
error: mcpError,
|
|
4033
4317
|
progressEvents: [],
|
|
4034
|
-
request: toolRequest
|
|
4318
|
+
request: toolRequest ?? {
|
|
4319
|
+
toolName: this.getToolNameForSubagent(context.request.subagent),
|
|
4320
|
+
arguments: {}
|
|
4321
|
+
}
|
|
4035
4322
|
},
|
|
4036
4323
|
progressEvents: [],
|
|
4037
4324
|
error: mcpError
|
|
@@ -4970,7 +5257,7 @@ var init_concurrent_feedback_collector = __esm({
|
|
|
4970
5257
|
);
|
|
4971
5258
|
}
|
|
4972
5259
|
return new Promise((resolve7) => {
|
|
4973
|
-
const child =
|
|
5260
|
+
const child = childProcess.spawn(this.options.command, this.options.commandArgs, {
|
|
4974
5261
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4975
5262
|
});
|
|
4976
5263
|
child.stdout?.on("data", (d) => {
|
|
@@ -5103,10 +5390,13 @@ var init_terminal_progress_writer = __esm({
|
|
|
5103
5390
|
// src/cli/commands/main.ts
|
|
5104
5391
|
var main_exports = {};
|
|
5105
5392
|
__export(main_exports, {
|
|
5393
|
+
expandKanbanTaskReferencesInPrompt: () => expandKanbanTaskReferencesInPrompt,
|
|
5106
5394
|
getActiveSessionId: () => getActiveSessionId,
|
|
5107
5395
|
getDefaultModelForSubagent: () => getDefaultModelForSubagent,
|
|
5108
5396
|
isModelCompatibleWithSubagent: () => isModelCompatibleWithSubagent,
|
|
5109
|
-
mainCommandHandler: () => mainCommandHandler
|
|
5397
|
+
mainCommandHandler: () => mainCommandHandler,
|
|
5398
|
+
normalizeLeadingPromptDirectiveArtifacts: () => normalizeLeadingPromptDirectiveArtifacts,
|
|
5399
|
+
rewriteLeadingPromptShortcut: () => rewriteLeadingPromptShortcut
|
|
5110
5400
|
});
|
|
5111
5401
|
function normalizeVerboseLevel(verbose, quiet) {
|
|
5112
5402
|
if (quiet) return 0;
|
|
@@ -5173,6 +5463,169 @@ function toStringArray(value) {
|
|
|
5173
5463
|
const normalized = value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0);
|
|
5174
5464
|
return normalized.length > 0 ? normalized : void 0;
|
|
5175
5465
|
}
|
|
5466
|
+
function extractReferencedKanbanTaskIds(prompt) {
|
|
5467
|
+
const taskIds = [];
|
|
5468
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5469
|
+
for (const match of prompt.matchAll(KANBAN_TASK_REFERENCE_REGEX)) {
|
|
5470
|
+
const taskId = match[1];
|
|
5471
|
+
if (!taskId || seen.has(taskId)) {
|
|
5472
|
+
continue;
|
|
5473
|
+
}
|
|
5474
|
+
seen.add(taskId);
|
|
5475
|
+
taskIds.push(taskId);
|
|
5476
|
+
}
|
|
5477
|
+
return taskIds;
|
|
5478
|
+
}
|
|
5479
|
+
function normalizeKanbanTaskArray(payload) {
|
|
5480
|
+
if (Array.isArray(payload)) {
|
|
5481
|
+
return payload.filter((entry) => Boolean(entry) && typeof entry === "object");
|
|
5482
|
+
}
|
|
5483
|
+
if (payload && typeof payload === "object") {
|
|
5484
|
+
return [payload];
|
|
5485
|
+
}
|
|
5486
|
+
return [];
|
|
5487
|
+
}
|
|
5488
|
+
async function runKanbanGetCommand(command, args, workingDirectory) {
|
|
5489
|
+
try {
|
|
5490
|
+
const execFile3 = util.promisify(childProcess__namespace.execFile);
|
|
5491
|
+
const result = await execFile3(command, args, {
|
|
5492
|
+
cwd: workingDirectory,
|
|
5493
|
+
env: {
|
|
5494
|
+
...process.env,
|
|
5495
|
+
JUNO_TASK_ROOT: process.env.JUNO_TASK_ROOT || workingDirectory
|
|
5496
|
+
},
|
|
5497
|
+
maxBuffer: 1024 * 1024
|
|
5498
|
+
});
|
|
5499
|
+
const stdout2 = typeof result === "string" || Buffer.isBuffer(result) ? String(result) : String(result.stdout ?? "");
|
|
5500
|
+
const parsed = JSON.parse(stdout2);
|
|
5501
|
+
return normalizeKanbanTaskArray(parsed);
|
|
5502
|
+
} catch {
|
|
5503
|
+
return null;
|
|
5504
|
+
}
|
|
5505
|
+
}
|
|
5506
|
+
async function fetchKanbanTasksForCommand(command, taskIds, workingDirectory) {
|
|
5507
|
+
const tasksById = /* @__PURE__ */ new Map();
|
|
5508
|
+
if (taskIds.length === 0) {
|
|
5509
|
+
return tasksById;
|
|
5510
|
+
}
|
|
5511
|
+
const requestedTaskIds = new Set(taskIds);
|
|
5512
|
+
const addFetchedTasks = (fetchedTasks) => {
|
|
5513
|
+
if (!fetchedTasks) {
|
|
5514
|
+
return;
|
|
5515
|
+
}
|
|
5516
|
+
for (const task of fetchedTasks) {
|
|
5517
|
+
const taskId = typeof task.id === "string" ? task.id : void 0;
|
|
5518
|
+
if (!taskId || !requestedTaskIds.has(taskId)) {
|
|
5519
|
+
continue;
|
|
5520
|
+
}
|
|
5521
|
+
tasksById.set(taskId, task);
|
|
5522
|
+
}
|
|
5523
|
+
};
|
|
5524
|
+
addFetchedTasks(await runKanbanGetCommand(command, ["get", ...taskIds], workingDirectory));
|
|
5525
|
+
const unresolvedTaskIds = taskIds.filter((taskId) => !tasksById.has(taskId));
|
|
5526
|
+
for (const taskId of unresolvedTaskIds) {
|
|
5527
|
+
addFetchedTasks(await runKanbanGetCommand(command, ["get", taskId], workingDirectory));
|
|
5528
|
+
}
|
|
5529
|
+
return tasksById;
|
|
5530
|
+
}
|
|
5531
|
+
async function fetchReferencedKanbanTasks(taskIds, workingDirectory) {
|
|
5532
|
+
const tasksById = /* @__PURE__ */ new Map();
|
|
5533
|
+
if (taskIds.length === 0) {
|
|
5534
|
+
return tasksById;
|
|
5535
|
+
}
|
|
5536
|
+
const kanbanScriptPath = path15__namespace.join(workingDirectory, KANBAN_TASK_SCRIPT_RELATIVE_PATH);
|
|
5537
|
+
const hasKanbanScript = await fs16__default.default.pathExists(kanbanScriptPath);
|
|
5538
|
+
const commandAttempts = [];
|
|
5539
|
+
if (hasKanbanScript) {
|
|
5540
|
+
commandAttempts.push(kanbanScriptPath);
|
|
5541
|
+
}
|
|
5542
|
+
commandAttempts.push("juno-kanban");
|
|
5543
|
+
let unresolvedTaskIds = [...taskIds];
|
|
5544
|
+
for (const command of commandAttempts) {
|
|
5545
|
+
if (unresolvedTaskIds.length === 0) {
|
|
5546
|
+
break;
|
|
5547
|
+
}
|
|
5548
|
+
const fetchedTasks = await fetchKanbanTasksForCommand(command, unresolvedTaskIds, workingDirectory);
|
|
5549
|
+
if (fetchedTasks.size === 0) {
|
|
5550
|
+
continue;
|
|
5551
|
+
}
|
|
5552
|
+
for (const [taskId, task] of fetchedTasks.entries()) {
|
|
5553
|
+
tasksById.set(taskId, task);
|
|
5554
|
+
}
|
|
5555
|
+
unresolvedTaskIds = unresolvedTaskIds.filter((taskId) => !tasksById.has(taskId));
|
|
5556
|
+
}
|
|
5557
|
+
return tasksById;
|
|
5558
|
+
}
|
|
5559
|
+
async function expandKanbanTaskReferencesInPrompt(prompt, workingDirectory) {
|
|
5560
|
+
const referencedTaskIds = extractReferencedKanbanTaskIds(prompt);
|
|
5561
|
+
if (referencedTaskIds.length === 0) {
|
|
5562
|
+
return prompt;
|
|
5563
|
+
}
|
|
5564
|
+
const tasksById = await fetchReferencedKanbanTasks(referencedTaskIds, workingDirectory);
|
|
5565
|
+
if (tasksById.size === 0) {
|
|
5566
|
+
return prompt;
|
|
5567
|
+
}
|
|
5568
|
+
return prompt.replace(KANBAN_TASK_REFERENCE_REGEX, (fullMatch, taskId) => {
|
|
5569
|
+
const task = tasksById.get(taskId);
|
|
5570
|
+
if (!task) {
|
|
5571
|
+
return fullMatch;
|
|
5572
|
+
}
|
|
5573
|
+
return `
|
|
5574
|
+
[kanban_task:${taskId}]
|
|
5575
|
+
${JSON.stringify(task, null, 2)}
|
|
5576
|
+
[/kanban_task]`;
|
|
5577
|
+
});
|
|
5578
|
+
}
|
|
5579
|
+
function normalizeLeadingPromptDirectiveArtifacts(prompt) {
|
|
5580
|
+
const lines = prompt.split(/\r?\n/);
|
|
5581
|
+
if (lines.length === 0) {
|
|
5582
|
+
return prompt;
|
|
5583
|
+
}
|
|
5584
|
+
let index = 0;
|
|
5585
|
+
while (index < lines.length && lines[index].trim() === "") {
|
|
5586
|
+
index += 1;
|
|
5587
|
+
}
|
|
5588
|
+
if (index >= lines.length) {
|
|
5589
|
+
return prompt;
|
|
5590
|
+
}
|
|
5591
|
+
const firstMeaningfulLine = lines[index].trim();
|
|
5592
|
+
if (!LEADING_PROMPT_DELIMITER_MARKERS.has(firstMeaningfulLine)) {
|
|
5593
|
+
return prompt;
|
|
5594
|
+
}
|
|
5595
|
+
let directiveIndex = index + 1;
|
|
5596
|
+
while (directiveIndex < lines.length && lines[directiveIndex].trim() === "") {
|
|
5597
|
+
directiveIndex += 1;
|
|
5598
|
+
}
|
|
5599
|
+
if (directiveIndex >= lines.length) {
|
|
5600
|
+
return prompt;
|
|
5601
|
+
}
|
|
5602
|
+
const directiveCandidate = lines[directiveIndex].trimStart();
|
|
5603
|
+
if (!LEADING_DIRECTIVE_LINE_REGEX.test(directiveCandidate)) {
|
|
5604
|
+
return prompt;
|
|
5605
|
+
}
|
|
5606
|
+
return lines.slice(directiveIndex).join("\n");
|
|
5607
|
+
}
|
|
5608
|
+
function rewriteLeadingPromptShortcut(prompt, subagent) {
|
|
5609
|
+
const match = prompt.match(LEADING_PROMPT_SHORTCUT_REGEX);
|
|
5610
|
+
if (!match) {
|
|
5611
|
+
return prompt;
|
|
5612
|
+
}
|
|
5613
|
+
const shortcut = match[1] ?? match[2];
|
|
5614
|
+
if (!shortcut) {
|
|
5615
|
+
return prompt;
|
|
5616
|
+
}
|
|
5617
|
+
const remaining = match[3] ?? "";
|
|
5618
|
+
switch (subagent) {
|
|
5619
|
+
case "claude":
|
|
5620
|
+
return `/${shortcut}${remaining}`;
|
|
5621
|
+
case "pi":
|
|
5622
|
+
return `/skill:${shortcut}${remaining}`;
|
|
5623
|
+
case "codex":
|
|
5624
|
+
return `$${shortcut}${remaining}`;
|
|
5625
|
+
default:
|
|
5626
|
+
return prompt;
|
|
5627
|
+
}
|
|
5628
|
+
}
|
|
5176
5629
|
function resolveContinueEnvFilePath(workingDirectory, configuredPath) {
|
|
5177
5630
|
const candidate = configuredPath && configuredPath.trim() ? configuredPath.trim() : DEFAULT_ENV_FILE_NAME;
|
|
5178
5631
|
return path15__namespace.isAbsolute(candidate) ? candidate : path15__namespace.join(workingDirectory, candidate);
|
|
@@ -5575,7 +6028,13 @@ async function mainCommandHandler(_args, options, _command) {
|
|
|
5575
6028
|
]);
|
|
5576
6029
|
}
|
|
5577
6030
|
const promptProcessor = new PromptProcessor(options);
|
|
5578
|
-
const
|
|
6031
|
+
const rawInstruction = await promptProcessor.processPrompt();
|
|
6032
|
+
const normalizedInstruction = normalizeLeadingPromptDirectiveArtifacts(rawInstruction);
|
|
6033
|
+
const rewrittenInstruction = rewriteLeadingPromptShortcut(normalizedInstruction, options.subagent);
|
|
6034
|
+
const instruction = await expandKanbanTaskReferencesInPrompt(
|
|
6035
|
+
rewrittenInstruction,
|
|
6036
|
+
config.workingDirectory
|
|
6037
|
+
);
|
|
5579
6038
|
const selectedBackend = "shell";
|
|
5580
6039
|
if (options.allowedTools && options.appendAllowedTools) {
|
|
5581
6040
|
console.error(
|
|
@@ -5594,6 +6053,7 @@ async function mainCommandHandler(_args, options, _command) {
|
|
|
5594
6053
|
}
|
|
5595
6054
|
const configuredModel = getConfiguredDefaultModelForSubagent(config, options.subagent);
|
|
5596
6055
|
const resolvedModel = options.model || configuredModel || getDefaultModelForSubagent(options.subagent);
|
|
6056
|
+
const liveInteractiveSession = options.continueFromLatest === true && options.subagent === "pi" && options.live === true && instruction.length === 0 && typeof options.resume === "string" && options.resume.trim().length > 0;
|
|
5597
6057
|
const executionRequest = createExecutionRequest({
|
|
5598
6058
|
instruction,
|
|
5599
6059
|
subagent: options.subagent,
|
|
@@ -5609,7 +6069,8 @@ async function mainCommandHandler(_args, options, _command) {
|
|
|
5609
6069
|
...options.resume !== void 0 ? { resume: options.resume } : {},
|
|
5610
6070
|
...options.continue !== void 0 ? { continueConversation: options.continue } : {},
|
|
5611
6071
|
...options.thinking !== void 0 ? { thinking: options.thinking } : {},
|
|
5612
|
-
...options.live !== void 0 ? { live: options.live } : {}
|
|
6072
|
+
...options.live !== void 0 ? { live: options.live } : {},
|
|
6073
|
+
...liveInteractiveSession ? { liveInteractiveSession: true } : {}
|
|
5613
6074
|
});
|
|
5614
6075
|
const coordinator = new MainExecutionCoordinator(
|
|
5615
6076
|
config,
|
|
@@ -5687,7 +6148,7 @@ async function mainCommandHandler(_args, options, _command) {
|
|
|
5687
6148
|
}
|
|
5688
6149
|
}
|
|
5689
6150
|
}
|
|
5690
|
-
var SESSION_HISTORY_VERSION, SESSION_HISTORY_FILE_NAME, CONTINUE_SETTINGS_VERSION, DEFAULT_ENV_FILE_NAME, PromptProcessor, _activeSessionId, MainProgressDisplay, MainExecutionCoordinator;
|
|
6151
|
+
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;
|
|
5691
6152
|
var init_main = __esm({
|
|
5692
6153
|
"src/cli/commands/main.ts"() {
|
|
5693
6154
|
init_version();
|
|
@@ -5704,6 +6165,11 @@ var init_main = __esm({
|
|
|
5704
6165
|
SESSION_HISTORY_FILE_NAME = "session_history.json";
|
|
5705
6166
|
CONTINUE_SETTINGS_VERSION = 1;
|
|
5706
6167
|
DEFAULT_ENV_FILE_NAME = ".env.juno";
|
|
6168
|
+
LEADING_PROMPT_SHORTCUT_REGEX = /^%(?:\{([^\s{}]+)\}|([^\s%][^\s]*))(.*)$/s;
|
|
6169
|
+
LEADING_PROMPT_DELIMITER_MARKERS = /* @__PURE__ */ new Set(["---", "***", "___"]);
|
|
6170
|
+
LEADING_DIRECTIVE_LINE_REGEX = /^(?:%(?:\{[^\s{}]+\}|[^\s%][^\s]*)|\/skill:[^\s]+|\/[^\s]+|\$[^\s]+)/;
|
|
6171
|
+
KANBAN_TASK_REFERENCE_REGEX = /(?<!#)##\s*\{?([A-Za-z0-9]{6})\}?(?![A-Za-z0-9])/g;
|
|
6172
|
+
KANBAN_TASK_SCRIPT_RELATIVE_PATH = path15__namespace.join(".juno_task", "scripts", "kanban.sh");
|
|
5707
6173
|
PromptProcessor = class {
|
|
5708
6174
|
constructor(options) {
|
|
5709
6175
|
this.options = options;
|
|
@@ -5721,6 +6187,9 @@ var init_main = __esm({
|
|
|
5721
6187
|
if (this.hasRedirectedStdin()) {
|
|
5722
6188
|
return await this.readPipedStdin();
|
|
5723
6189
|
}
|
|
6190
|
+
if (this.shouldOpenLiveContinueSessionWithoutPrompt()) {
|
|
6191
|
+
return "";
|
|
6192
|
+
}
|
|
5724
6193
|
if (this.options.interactive) {
|
|
5725
6194
|
return await this.collectInteractivePrompt();
|
|
5726
6195
|
} else {
|
|
@@ -5759,6 +6228,9 @@ var init_main = __esm({
|
|
|
5759
6228
|
return false;
|
|
5760
6229
|
}
|
|
5761
6230
|
}
|
|
6231
|
+
shouldOpenLiveContinueSessionWithoutPrompt() {
|
|
6232
|
+
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;
|
|
6233
|
+
}
|
|
5762
6234
|
async isFilePath(prompt) {
|
|
5763
6235
|
if (prompt.includes("\n") || prompt.length > 500) {
|
|
5764
6236
|
return false;
|
|
@@ -5867,6 +6339,7 @@ var init_main = __esm({
|
|
|
5867
6339
|
// iteration# → sub-agent session_id
|
|
5868
6340
|
latestSessionId = null;
|
|
5869
6341
|
// most recent session_id seen
|
|
6342
|
+
lastResolvedInstructionByIteration = /* @__PURE__ */ new Map();
|
|
5870
6343
|
constructor(verboseLevel = 1) {
|
|
5871
6344
|
this.verboseLevel = verboseLevel;
|
|
5872
6345
|
}
|
|
@@ -5893,9 +6366,18 @@ var init_main = __esm({
|
|
|
5893
6366
|
console.error(chalk21__default.default.gray(` Request ID: ${request.requestId}`));
|
|
5894
6367
|
console.error(chalk21__default.default.gray(` Working Directory: ${request.workingDirectory}`));
|
|
5895
6368
|
}
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
6369
|
+
const hasPromptSubstitutionSyntax = this.hasPromptCommandSubstitutionSyntax(request.instruction);
|
|
6370
|
+
if (hasPromptSubstitutionSyntax) {
|
|
6371
|
+
console.error(chalk21__default.default.blue("\n\u{1F4CB} Task Template:"));
|
|
6372
|
+
} else {
|
|
6373
|
+
console.error(chalk21__default.default.blue("\n\u{1F4CB} Task:"));
|
|
6374
|
+
}
|
|
6375
|
+
console.error(chalk21__default.default.white(` ${this.buildInstructionPreview(request.instruction)}`));
|
|
6376
|
+
if (hasPromptSubstitutionSyntax) {
|
|
6377
|
+
console.error(
|
|
6378
|
+
chalk21__default.default.gray(" Prompt-time substitutions are resolved immediately before each subagent call.")
|
|
6379
|
+
);
|
|
6380
|
+
}
|
|
5899
6381
|
console.error("");
|
|
5900
6382
|
}
|
|
5901
6383
|
getSelectedExecutionOptions(request) {
|
|
@@ -5929,6 +6411,32 @@ var init_main = __esm({
|
|
|
5929
6411
|
if (value.length <= maxLength) return value;
|
|
5930
6412
|
return `${value.substring(0, maxLength - 3)}...`;
|
|
5931
6413
|
}
|
|
6414
|
+
buildInstructionPreview(instruction, maxLength = 200) {
|
|
6415
|
+
if (instruction.length <= maxLength) {
|
|
6416
|
+
return instruction;
|
|
6417
|
+
}
|
|
6418
|
+
return `${instruction.substring(0, maxLength)}...`;
|
|
6419
|
+
}
|
|
6420
|
+
hasPromptCommandSubstitutionSyntax(instruction) {
|
|
6421
|
+
return instruction.includes("!'") || instruction.includes("!```");
|
|
6422
|
+
}
|
|
6423
|
+
onInstructionResolved(iteration, resolvedInstruction, templateInstruction) {
|
|
6424
|
+
const previousInstruction = this.lastResolvedInstructionByIteration.get(iteration);
|
|
6425
|
+
if (previousInstruction === resolvedInstruction) {
|
|
6426
|
+
return;
|
|
6427
|
+
}
|
|
6428
|
+
this.lastResolvedInstructionByIteration.set(iteration, resolvedInstruction);
|
|
6429
|
+
if (this.verboseLevel === 0) {
|
|
6430
|
+
return;
|
|
6431
|
+
}
|
|
6432
|
+
if (templateInstruction !== void 0 && resolvedInstruction === templateInstruction) {
|
|
6433
|
+
return;
|
|
6434
|
+
}
|
|
6435
|
+
const heading = iteration === 1 ? "\n\u{1F9E9} Resolved Task (iteration 1):" : `
|
|
6436
|
+
\u{1F9E9} Resolved Task (iteration ${iteration}):`;
|
|
6437
|
+
console.error(chalk21__default.default.blue(heading));
|
|
6438
|
+
console.error(chalk21__default.default.white(` ${this.buildInstructionPreview(resolvedInstruction)}`));
|
|
6439
|
+
}
|
|
5932
6440
|
onProgress(event) {
|
|
5933
6441
|
const timestamp = event.timestamp.toLocaleTimeString();
|
|
5934
6442
|
if (event.metadata?.sessionId && typeof event.metadata.sessionId === "string") {
|
|
@@ -6006,7 +6514,10 @@ var init_main = __esm({
|
|
|
6006
6514
|
if (this.verboseLevel === 0) {
|
|
6007
6515
|
const lastIteration2 = result.iterations[result.iterations.length - 1];
|
|
6008
6516
|
if (lastIteration2?.toolResult.content && !this.hasStreamedJsonOutput) {
|
|
6009
|
-
|
|
6517
|
+
const displayContent = this.getDisplayResultContent(lastIteration2.toolResult.content);
|
|
6518
|
+
if (displayContent.trim().length > 0) {
|
|
6519
|
+
console.log(displayContent);
|
|
6520
|
+
}
|
|
6010
6521
|
}
|
|
6011
6522
|
return;
|
|
6012
6523
|
}
|
|
@@ -6019,12 +6530,14 @@ var init_main = __esm({
|
|
|
6019
6530
|
}
|
|
6020
6531
|
const lastIteration = result.iterations[result.iterations.length - 1];
|
|
6021
6532
|
const structuredOutput = lastIteration?.toolResult.metadata?.structuredOutput === true;
|
|
6533
|
+
const rawResultContent = lastIteration?.toolResult.content || "";
|
|
6534
|
+
const displayResultContent = rawResultContent ? this.getDisplayResultContent(rawResultContent) : "";
|
|
6022
6535
|
const shouldPrintResult = Boolean(
|
|
6023
|
-
lastIteration &&
|
|
6536
|
+
lastIteration && displayResultContent && (!this.hasStreamedJsonOutput || structuredOutput)
|
|
6024
6537
|
);
|
|
6025
6538
|
if (shouldPrintResult) {
|
|
6026
6539
|
console.error(chalk21__default.default.blue("\n\u{1F4C4} Result:"));
|
|
6027
|
-
console.log(
|
|
6540
|
+
console.log(displayResultContent);
|
|
6028
6541
|
}
|
|
6029
6542
|
const iterationCosts = this.extractIterationCosts(result);
|
|
6030
6543
|
const totalCostUsd = [...iterationCosts.values()].reduce((sum, cost) => sum + cost, 0);
|
|
@@ -6094,6 +6607,26 @@ var init_main = __esm({
|
|
|
6094
6607
|
console.error(chalk21__default.default.gray("\n\u{1F511} Session ID: could not be extracted"));
|
|
6095
6608
|
}
|
|
6096
6609
|
}
|
|
6610
|
+
getDisplayResultContent(content) {
|
|
6611
|
+
if (this.verboseLevel >= 2) {
|
|
6612
|
+
return content;
|
|
6613
|
+
}
|
|
6614
|
+
try {
|
|
6615
|
+
const payload = JSON.parse(content);
|
|
6616
|
+
if (payload?.type === "result" && Object.prototype.hasOwnProperty.call(payload, "result")) {
|
|
6617
|
+
const resultValue = payload.result;
|
|
6618
|
+
if (typeof resultValue === "string") {
|
|
6619
|
+
return resultValue;
|
|
6620
|
+
}
|
|
6621
|
+
if (resultValue === null || resultValue === void 0) {
|
|
6622
|
+
return "";
|
|
6623
|
+
}
|
|
6624
|
+
return JSON.stringify(resultValue, null, 2);
|
|
6625
|
+
}
|
|
6626
|
+
} catch {
|
|
6627
|
+
}
|
|
6628
|
+
return content;
|
|
6629
|
+
}
|
|
6097
6630
|
/**
|
|
6098
6631
|
* Extract session IDs from iteration results' structured payloads
|
|
6099
6632
|
*/
|
|
@@ -6242,6 +6775,13 @@ var init_main = __esm({
|
|
|
6242
6775
|
engine.on("iteration:start", ({ iterationNumber }) => {
|
|
6243
6776
|
this.progressDisplay.onIterationStart(iterationNumber);
|
|
6244
6777
|
});
|
|
6778
|
+
engine.on("iteration:instruction-resolved", ({ iterationNumber, instruction, templateInstruction }) => {
|
|
6779
|
+
this.progressDisplay.onInstructionResolved(
|
|
6780
|
+
iterationNumber,
|
|
6781
|
+
typeof instruction === "string" ? instruction : "",
|
|
6782
|
+
typeof templateInstruction === "string" ? templateInstruction : void 0
|
|
6783
|
+
);
|
|
6784
|
+
});
|
|
6245
6785
|
engine.on("iteration:complete", ({ iterationResult }) => {
|
|
6246
6786
|
this.progressDisplay.onIterationComplete(iterationResult.success, iterationResult.duration);
|
|
6247
6787
|
});
|
|
@@ -14807,6 +15347,26 @@ function normalizeVerbose(value) {
|
|
|
14807
15347
|
if (!isNaN(num) && num >= 0 && num <= 2) return Math.floor(num);
|
|
14808
15348
|
return 1;
|
|
14809
15349
|
}
|
|
15350
|
+
function extractOptionValueFromArgv(argv2, longOption, shortOption) {
|
|
15351
|
+
for (let i = 0; i < argv2.length; i++) {
|
|
15352
|
+
const token = argv2[i];
|
|
15353
|
+
if (!token) continue;
|
|
15354
|
+
if (token === longOption || token === shortOption) {
|
|
15355
|
+
const next = argv2[i + 1];
|
|
15356
|
+
if (next && !next.startsWith("-")) {
|
|
15357
|
+
return next;
|
|
15358
|
+
}
|
|
15359
|
+
continue;
|
|
15360
|
+
}
|
|
15361
|
+
if (token.startsWith(`${longOption}=`)) {
|
|
15362
|
+
return token.slice(longOption.length + 1);
|
|
15363
|
+
}
|
|
15364
|
+
if (token.startsWith(`${shortOption}=`)) {
|
|
15365
|
+
return token.slice(shortOption.length + 1);
|
|
15366
|
+
}
|
|
15367
|
+
}
|
|
15368
|
+
return void 0;
|
|
15369
|
+
}
|
|
14810
15370
|
function isConnectionLikeError(err) {
|
|
14811
15371
|
const msg = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
|
|
14812
15372
|
const lower = msg.toLowerCase();
|
|
@@ -14937,6 +15497,15 @@ function getForwardedUntilCompletionArgs() {
|
|
|
14937
15497
|
if (arg.startsWith("--pre-run-hook=")) {
|
|
14938
15498
|
continue;
|
|
14939
15499
|
}
|
|
15500
|
+
if (arg === "--cwd" || arg === "-w") {
|
|
15501
|
+
if (i + 1 < args.length && args[i + 1] && !args[i + 1].startsWith("-")) {
|
|
15502
|
+
i += 1;
|
|
15503
|
+
}
|
|
15504
|
+
continue;
|
|
15505
|
+
}
|
|
15506
|
+
if (arg.startsWith("--cwd=") || arg.startsWith("-w=")) {
|
|
15507
|
+
continue;
|
|
15508
|
+
}
|
|
14940
15509
|
forwardedArgs.push(arg);
|
|
14941
15510
|
}
|
|
14942
15511
|
return forwardedArgs;
|
|
@@ -14948,7 +15517,9 @@ async function runUntilCompletionScriptIfRequested(options) {
|
|
|
14948
15517
|
const { spawn: spawn3 } = await import('child_process');
|
|
14949
15518
|
const path21 = await import('path');
|
|
14950
15519
|
const fs22 = await import('fs-extra');
|
|
14951
|
-
const
|
|
15520
|
+
const optionCwd = typeof options.cwd === "string" && options.cwd.trim().length > 0 ? options.cwd.trim() : extractOptionValueFromArgv(process.argv.slice(2), "--cwd", "-w");
|
|
15521
|
+
const invocationCwd = typeof optionCwd === "string" && optionCwd.trim().length > 0 ? path21.resolve(process.cwd(), optionCwd) : process.cwd();
|
|
15522
|
+
const scriptPath = path21.join(invocationCwd, ".juno_task", "scripts", "run_until_completion.sh");
|
|
14952
15523
|
if (!await fs22.pathExists(scriptPath)) {
|
|
14953
15524
|
console.error(chalk21__default.default.red.bold("\n\u274C Error: run_until_completion.sh not found"));
|
|
14954
15525
|
console.error(chalk21__default.default.red(` Expected location: ${scriptPath}`));
|
|
@@ -14965,7 +15536,7 @@ async function runUntilCompletionScriptIfRequested(options) {
|
|
|
14965
15536
|
scriptArgs.push(...getForwardedUntilCompletionArgs());
|
|
14966
15537
|
const child = spawn3(scriptPath, scriptArgs, {
|
|
14967
15538
|
stdio: "inherit",
|
|
14968
|
-
cwd:
|
|
15539
|
+
cwd: invocationCwd
|
|
14969
15540
|
});
|
|
14970
15541
|
process.removeAllListeners("SIGINT");
|
|
14971
15542
|
process.removeAllListeners("SIGTERM");
|
|
@@ -14997,9 +15568,9 @@ async function runUntilCompletionScriptIfRequested(options) {
|
|
|
14997
15568
|
return true;
|
|
14998
15569
|
}
|
|
14999
15570
|
function setupContinueCommand(program) {
|
|
15000
|
-
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(
|
|
15571
|
+
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(
|
|
15001
15572
|
"-p, --prompt [text]",
|
|
15002
|
-
"Prompt input (inline text, file path, or
|
|
15573
|
+
"Prompt input (inline text, file path, or heredoc/stdin; supports !'cmd' and !```cmd``` substitutions, prefer single quotes for shell metacharacters)"
|
|
15003
15574
|
).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) => {
|
|
15004
15575
|
if (promptArgs.length > 0 && options.prompt === void 0) {
|
|
15005
15576
|
options.prompt = promptArgs.join(" ");
|
|
@@ -15074,7 +15645,7 @@ function setupContinueScopeCommand(program) {
|
|
|
15074
15645
|
function setupMainCommand(program) {
|
|
15075
15646
|
program.argument("[prompt_text...]", "Prompt text (positional, alternative to -p)").option(
|
|
15076
15647
|
"-p, --prompt [text]",
|
|
15077
|
-
"Prompt input (inline text, file path, or
|
|
15648
|
+
"Prompt input (inline text, file path, or heredoc/stdin; supports !'cmd' and !```cmd``` substitutions, prefer single quotes for shell metacharacters)"
|
|
15078
15649
|
).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) => {
|
|
15079
15650
|
if (promptArgs.length > 0 && options.prompt === void 0) {
|
|
15080
15651
|
options.prompt = promptArgs.join(" ");
|
|
@@ -15248,6 +15819,11 @@ ${chalk21__default.default.blue("Examples:")}
|
|
|
15248
15819
|
|
|
15249
15820
|
${chalk21__default.default.gray("# Shell safety")}
|
|
15250
15821
|
${chalk21__default.default.gray("Use single quotes (or -f/stdin) when prompts contain backticks or $()")}
|
|
15822
|
+
|
|
15823
|
+
${chalk21__default.default.gray("# Prompt-time substitutions (refreshed each iteration)")}
|
|
15824
|
+
juno-code claude -p "Status: !'git status --short'"
|
|
15825
|
+
juno-code claude -i 3 -p "Recent commits:
|
|
15826
|
+
!\`\`\`git log -n 5 --oneline\`\`\`"
|
|
15251
15827
|
`
|
|
15252
15828
|
},
|
|
15253
15829
|
pi: {
|
|
@@ -15436,7 +16012,7 @@ function setupAliases(program) {
|
|
|
15436
16012
|
if (!help) continue;
|
|
15437
16013
|
const cmd = program.command(subagent).description(help.description).argument("[prompt...]", "Prompt text or file path").option(
|
|
15438
16014
|
"-p, --prompt [text]",
|
|
15439
|
-
"Prompt input (inline text, or
|
|
16015
|
+
"Prompt input (inline text, or heredoc/stdin; supports !'cmd' and !```cmd``` substitutions, prefer single quotes for shell metacharacters)"
|
|
15440
16016
|
).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) => {
|
|
15441
16017
|
if (promptArgs.length > 0 && options.prompt === void 0) {
|
|
15442
16018
|
options.prompt = promptArgs.join(" ");
|
|
@@ -15461,9 +16037,24 @@ function setupAliases(program) {
|
|
|
15461
16037
|
handleCLIError(error, normalizeVerbose(options.verbose));
|
|
15462
16038
|
}
|
|
15463
16039
|
});
|
|
15464
|
-
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) => {
|
|
16040
|
+
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) => {
|
|
16041
|
+
const mergedOptions = (() => {
|
|
16042
|
+
const commandWithGlobals = command;
|
|
16043
|
+
if (typeof commandWithGlobals.optsWithGlobals === "function") {
|
|
16044
|
+
return {
|
|
16045
|
+
...commandWithGlobals.optsWithGlobals(),
|
|
16046
|
+
...commandOptions
|
|
16047
|
+
};
|
|
16048
|
+
}
|
|
16049
|
+
const parentOptions = command.parent?.opts ? command.parent.opts() : {};
|
|
16050
|
+
return {
|
|
16051
|
+
...parentOptions,
|
|
16052
|
+
...commandOptions
|
|
16053
|
+
};
|
|
16054
|
+
})();
|
|
15465
16055
|
try {
|
|
15466
|
-
const
|
|
16056
|
+
const optionCwd = typeof mergedOptions.cwd === "string" && mergedOptions.cwd.trim().length > 0 ? mergedOptions.cwd.trim() : extractOptionValueFromArgv(process.argv.slice(2), "--cwd", "-w");
|
|
16057
|
+
const workingDirectory = typeof optionCwd === "string" && optionCwd.trim().length > 0 ? optionCwd.trim() : process.cwd();
|
|
15467
16058
|
const [{ loadConfig: loadConfig2 }, subagentModels, fsExtra2, nodePath] = await Promise.all([
|
|
15468
16059
|
Promise.resolve().then(() => (init_config(), config_exports)),
|
|
15469
16060
|
Promise.resolve().then(() => (init_subagent_models(), subagent_models_exports)),
|
|
@@ -15504,7 +16095,7 @@ function setupAliases(program) {
|
|
|
15504
16095
|
)
|
|
15505
16096
|
);
|
|
15506
16097
|
} catch (error) {
|
|
15507
|
-
handleCLIError(error, normalizeVerbose(
|
|
16098
|
+
handleCLIError(error, normalizeVerbose(mergedOptions.verbose));
|
|
15508
16099
|
}
|
|
15509
16100
|
});
|
|
15510
16101
|
cmd.allowUnknownOption(true);
|
|
@@ -15701,6 +16292,11 @@ ${chalk21__default.default.blue.bold("Examples:")}
|
|
|
15701
16292
|
${chalk21__default.default.gray("# Shell safety")}
|
|
15702
16293
|
${chalk21__default.default.gray("Use single quotes or -f/stdin when prompts include backticks or $()")}
|
|
15703
16294
|
|
|
16295
|
+
${chalk21__default.default.gray("# Prompt-time command substitution (per iteration)")}
|
|
16296
|
+
juno-code claude -p "Status: !'git status --short'"
|
|
16297
|
+
juno-code claude -i 3 -p "Recent commits:
|
|
16298
|
+
!\`\`\`git log -n 5 --oneline\`\`\`"
|
|
16299
|
+
|
|
15704
16300
|
${chalk21__default.default.gray("# Interactive project setup")}
|
|
15705
16301
|
juno-code init --interactive
|
|
15706
16302
|
|