juno-code 1.0.33 → 1.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +207 -79
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/cli.mjs +170 -42
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/index.js +3 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -7
- package/dist/index.mjs.map +1 -1
- package/dist/templates/services/__pycache__/codex.cpython-38.pyc +0 -0
- package/dist/templates/services/claude.py +31 -1
- package/dist/templates/services/codex.py +338 -150
- package/package.json +1 -1
package/dist/bin/cli.mjs
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import fs2 from 'fs-extra';
|
|
3
3
|
import * as path3 from 'path';
|
|
4
4
|
import path3__default, { dirname, join } from 'path';
|
|
5
|
-
import * as
|
|
6
|
-
import
|
|
5
|
+
import * as os4 from 'os';
|
|
6
|
+
import os4__default, { homedir, EOL } from 'os';
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import { createRequire } from 'module';
|
|
9
9
|
import semver from 'semver';
|
|
@@ -3295,13 +3295,9 @@ var init_advanced_logger = __esm({
|
|
|
3295
3295
|
/**
|
|
3296
3296
|
* Output formatted log
|
|
3297
3297
|
*/
|
|
3298
|
-
output(formatted,
|
|
3298
|
+
output(formatted, _level) {
|
|
3299
3299
|
if (this.options.output === "console" || this.options.output === "both") {
|
|
3300
|
-
|
|
3301
|
-
console.error(formatted);
|
|
3302
|
-
} else {
|
|
3303
|
-
console.log(formatted);
|
|
3304
|
-
}
|
|
3300
|
+
console.error(formatted);
|
|
3305
3301
|
}
|
|
3306
3302
|
if (this.options.output === "file" || this.options.output === "both") {
|
|
3307
3303
|
this.writeToFile(formatted);
|
|
@@ -5997,7 +5993,7 @@ var init_client = __esm({
|
|
|
5997
5993
|
`${serverName}`,
|
|
5998
5994
|
// Assume it's in PATH
|
|
5999
5995
|
`/usr/local/bin/${serverName}`,
|
|
6000
|
-
path3__default.resolve(
|
|
5996
|
+
path3__default.resolve(os4__default.homedir(), `.local/bin/${serverName}`),
|
|
6001
5997
|
path3__default.resolve(this.options.workingDirectory || process.cwd(), `${serverName}`)
|
|
6002
5998
|
];
|
|
6003
5999
|
for (const serverPath of possiblePaths) {
|
|
@@ -7006,7 +7002,7 @@ var init_shell_backend = __esm({
|
|
|
7006
7002
|
});
|
|
7007
7003
|
try {
|
|
7008
7004
|
const scriptPath = await this.findScriptForSubagent(subagentType);
|
|
7009
|
-
const result = await this.executeScript(scriptPath, request, toolId);
|
|
7005
|
+
const result = await this.executeScript(scriptPath, request, toolId, subagentType);
|
|
7010
7006
|
const duration = Date.now() - startTime;
|
|
7011
7007
|
await this.emitProgressEvent({
|
|
7012
7008
|
sessionId: request.metadata?.sessionId || "unknown",
|
|
@@ -7023,8 +7019,9 @@ var init_shell_backend = __esm({
|
|
|
7023
7019
|
phase: "completion"
|
|
7024
7020
|
}
|
|
7025
7021
|
});
|
|
7022
|
+
const structuredResult = this.buildStructuredOutput(subagentType, result);
|
|
7026
7023
|
return {
|
|
7027
|
-
content:
|
|
7024
|
+
content: structuredResult.content,
|
|
7028
7025
|
status: result.success ? "completed" : "failed",
|
|
7029
7026
|
startTime: new Date(startTime),
|
|
7030
7027
|
endTime: /* @__PURE__ */ new Date(),
|
|
@@ -7032,6 +7029,7 @@ var init_shell_backend = __esm({
|
|
|
7032
7029
|
error: result.error ? { type: "shell_execution", message: result.error, timestamp: /* @__PURE__ */ new Date() } : void 0,
|
|
7033
7030
|
progressEvents: [],
|
|
7034
7031
|
// Progress events are handled via callbacks
|
|
7032
|
+
...structuredResult.metadata ? { metadata: structuredResult.metadata } : void 0,
|
|
7035
7033
|
request
|
|
7036
7034
|
};
|
|
7037
7035
|
} catch (error) {
|
|
@@ -7197,8 +7195,8 @@ var init_shell_backend = __esm({
|
|
|
7197
7195
|
/**
|
|
7198
7196
|
* Execute a shell script
|
|
7199
7197
|
*/
|
|
7200
|
-
async executeScript(scriptPath, request, toolId) {
|
|
7201
|
-
return new Promise((resolve9, reject) => {
|
|
7198
|
+
async executeScript(scriptPath, request, toolId, subagentType) {
|
|
7199
|
+
return new Promise(async (resolve9, reject) => {
|
|
7202
7200
|
const startTime = Date.now();
|
|
7203
7201
|
const isPython = scriptPath.endsWith(".py");
|
|
7204
7202
|
const env2 = {
|
|
@@ -7211,6 +7209,19 @@ var init_shell_backend = __esm({
|
|
|
7211
7209
|
JUNO_ITERATION: String(request.arguments?.iteration || 1),
|
|
7212
7210
|
JUNO_TOOL_ID: toolId
|
|
7213
7211
|
};
|
|
7212
|
+
let captureDir = null;
|
|
7213
|
+
let capturePath = null;
|
|
7214
|
+
if (subagentType === "claude") {
|
|
7215
|
+
try {
|
|
7216
|
+
captureDir = await promises.mkdtemp(path3.join(os4__default.tmpdir(), "juno-shell-"));
|
|
7217
|
+
capturePath = path3.join(captureDir, `subagent_${toolId}.json`);
|
|
7218
|
+
env2.JUNO_SUBAGENT_CAPTURE_PATH = capturePath;
|
|
7219
|
+
} catch (error) {
|
|
7220
|
+
if (this.config?.debug) {
|
|
7221
|
+
engineLogger.warn(`Failed to prepare subagent capture path: ${error instanceof Error ? error.message : String(error)}`);
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
}
|
|
7214
7225
|
const command = isPython ? "python3" : "bash";
|
|
7215
7226
|
const args = [scriptPath];
|
|
7216
7227
|
if (isPython && request.arguments?.instruction) {
|
|
@@ -7285,20 +7296,46 @@ var init_shell_backend = __esm({
|
|
|
7285
7296
|
}
|
|
7286
7297
|
});
|
|
7287
7298
|
child.on("close", (exitCode) => {
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7299
|
+
void (async () => {
|
|
7300
|
+
if (isProcessKilled) return;
|
|
7301
|
+
const duration = Date.now() - startTime;
|
|
7302
|
+
const success = exitCode === 0;
|
|
7303
|
+
let subAgentResponse;
|
|
7304
|
+
if (capturePath) {
|
|
7305
|
+
try {
|
|
7306
|
+
const captured = await promises.readFile(capturePath, "utf-8");
|
|
7307
|
+
if (captured.trim()) {
|
|
7308
|
+
subAgentResponse = JSON.parse(captured);
|
|
7309
|
+
}
|
|
7310
|
+
} catch (error) {
|
|
7311
|
+
if (this.config?.debug) {
|
|
7312
|
+
engineLogger.warn(`Failed to read subagent capture: ${error instanceof Error ? error.message : String(error)}`);
|
|
7313
|
+
}
|
|
7314
|
+
} finally {
|
|
7315
|
+
if (captureDir) {
|
|
7316
|
+
try {
|
|
7317
|
+
await promises.rm(captureDir, { recursive: true, force: true });
|
|
7318
|
+
} catch (cleanupError) {
|
|
7319
|
+
if (this.config?.debug) {
|
|
7320
|
+
engineLogger.warn(`Failed to clean capture directory: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`);
|
|
7321
|
+
}
|
|
7322
|
+
}
|
|
7323
|
+
}
|
|
7324
|
+
}
|
|
7325
|
+
}
|
|
7326
|
+
if (this.config.debug) {
|
|
7327
|
+
engineLogger.debug(`Script execution completed with exit code: ${exitCode}, duration: ${duration}ms`);
|
|
7328
|
+
engineLogger.debug(`Stdout length: ${stdout2.length}, Stderr length: ${stderr.length}`);
|
|
7329
|
+
}
|
|
7330
|
+
resolve9({
|
|
7331
|
+
success,
|
|
7332
|
+
output: stdout2,
|
|
7333
|
+
error: stderr || void 0,
|
|
7334
|
+
exitCode: exitCode || 0,
|
|
7335
|
+
duration,
|
|
7336
|
+
...subAgentResponse ? { subAgentResponse } : void 0
|
|
7337
|
+
});
|
|
7338
|
+
})();
|
|
7302
7339
|
});
|
|
7303
7340
|
child.on("error", (error) => {
|
|
7304
7341
|
if (isProcessKilled) return;
|
|
@@ -7330,6 +7367,66 @@ var init_shell_backend = __esm({
|
|
|
7330
7367
|
});
|
|
7331
7368
|
});
|
|
7332
7369
|
}
|
|
7370
|
+
/**
|
|
7371
|
+
* Build a structured, JSON-parsable result payload for programmatic capture while
|
|
7372
|
+
* preserving the shell backend's existing on-screen streaming behavior.
|
|
7373
|
+
*/
|
|
7374
|
+
buildStructuredOutput(subagentType, result) {
|
|
7375
|
+
if (subagentType === "claude") {
|
|
7376
|
+
const claudeEvent = result.subAgentResponse ?? this.extractLastJsonEvent(result.output);
|
|
7377
|
+
const isError = claudeEvent?.is_error ?? claudeEvent?.subtype === "error" ?? !result.success;
|
|
7378
|
+
const structuredPayload = {
|
|
7379
|
+
type: "result",
|
|
7380
|
+
subtype: claudeEvent?.subtype || (isError ? "error" : "success"),
|
|
7381
|
+
is_error: isError,
|
|
7382
|
+
result: claudeEvent?.result ?? claudeEvent?.error ?? claudeEvent?.content ?? result.output,
|
|
7383
|
+
error: claudeEvent?.error,
|
|
7384
|
+
stderr: result.error,
|
|
7385
|
+
datetime: claudeEvent?.datetime,
|
|
7386
|
+
counter: claudeEvent?.counter,
|
|
7387
|
+
session_id: claudeEvent?.session_id,
|
|
7388
|
+
num_turns: claudeEvent?.num_turns,
|
|
7389
|
+
duration_ms: claudeEvent?.duration_ms ?? result.duration,
|
|
7390
|
+
exit_code: result.exitCode,
|
|
7391
|
+
total_cost_usd: claudeEvent?.total_cost_usd,
|
|
7392
|
+
usage: claudeEvent?.usage,
|
|
7393
|
+
modelUsage: claudeEvent?.modelUsage || claudeEvent?.model_usage || {},
|
|
7394
|
+
permission_denials: claudeEvent?.permission_denials || [],
|
|
7395
|
+
uuid: claudeEvent?.uuid,
|
|
7396
|
+
sub_agent_response: claudeEvent
|
|
7397
|
+
};
|
|
7398
|
+
const metadata = {
|
|
7399
|
+
...claudeEvent ? { subAgentResponse: claudeEvent } : void 0,
|
|
7400
|
+
structuredOutput: true,
|
|
7401
|
+
contentType: "application/json",
|
|
7402
|
+
rawOutput: result.output
|
|
7403
|
+
};
|
|
7404
|
+
return {
|
|
7405
|
+
content: JSON.stringify(structuredPayload),
|
|
7406
|
+
metadata
|
|
7407
|
+
};
|
|
7408
|
+
}
|
|
7409
|
+
return { content: result.output, metadata: result.metadata };
|
|
7410
|
+
}
|
|
7411
|
+
/**
|
|
7412
|
+
* Extract the last valid JSON object from a script's stdout to use as a structured payload fallback.
|
|
7413
|
+
*/
|
|
7414
|
+
extractLastJsonEvent(output) {
|
|
7415
|
+
if (!output) {
|
|
7416
|
+
return null;
|
|
7417
|
+
}
|
|
7418
|
+
const lines = output.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
7419
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
7420
|
+
try {
|
|
7421
|
+
const parsed = JSON.parse(lines[i]);
|
|
7422
|
+
if (parsed && typeof parsed === "object") {
|
|
7423
|
+
return parsed;
|
|
7424
|
+
}
|
|
7425
|
+
} catch {
|
|
7426
|
+
}
|
|
7427
|
+
}
|
|
7428
|
+
return null;
|
|
7429
|
+
}
|
|
7333
7430
|
/**
|
|
7334
7431
|
* Parse streaming events from script output
|
|
7335
7432
|
* Handles both JSON format (Claude) and TEXT format (Codex)
|
|
@@ -7337,7 +7434,7 @@ var init_shell_backend = __esm({
|
|
|
7337
7434
|
* Strategy:
|
|
7338
7435
|
* 1. Try to parse each line as JSON first (for Claude)
|
|
7339
7436
|
* 2. If JSON parsing fails, treat as TEXT streaming (for Codex and other text-based subagents)
|
|
7340
|
-
* 3. Emit all
|
|
7437
|
+
* 3. Emit all text lines (including whitespace-only) as progress events for real-time display
|
|
7341
7438
|
*/
|
|
7342
7439
|
parseAndEmitStreamingEvents(data, sessionId) {
|
|
7343
7440
|
if (!this.jsonBuffer) {
|
|
@@ -7347,14 +7444,35 @@ var init_shell_backend = __esm({
|
|
|
7347
7444
|
const lines = this.jsonBuffer.split("\n");
|
|
7348
7445
|
this.jsonBuffer = lines.pop() || "";
|
|
7349
7446
|
for (const line of lines) {
|
|
7350
|
-
const
|
|
7351
|
-
if (!
|
|
7447
|
+
const rawLine = line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
7448
|
+
if (!rawLine) continue;
|
|
7449
|
+
const hasNonWhitespace = rawLine.trim().length > 0;
|
|
7450
|
+
if (!hasNonWhitespace) {
|
|
7451
|
+
this.emitProgressEvent({
|
|
7452
|
+
sessionId,
|
|
7453
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
7454
|
+
backend: "shell",
|
|
7455
|
+
count: ++this.eventCounter,
|
|
7456
|
+
type: "thinking",
|
|
7457
|
+
content: rawLine,
|
|
7458
|
+
metadata: {
|
|
7459
|
+
format: "text",
|
|
7460
|
+
raw: true
|
|
7461
|
+
}
|
|
7462
|
+
}).catch((error) => {
|
|
7463
|
+
if (this.config?.debug) {
|
|
7464
|
+
engineLogger.warn(`Failed to emit whitespace-only streaming event: ${error instanceof Error ? error.message : String(error)}`);
|
|
7465
|
+
}
|
|
7466
|
+
});
|
|
7467
|
+
continue;
|
|
7468
|
+
}
|
|
7469
|
+
const trimmedLine = rawLine.trim();
|
|
7352
7470
|
let isJsonParsed = false;
|
|
7353
7471
|
try {
|
|
7354
7472
|
const jsonEvent = JSON.parse(trimmedLine);
|
|
7355
7473
|
let progressEvent;
|
|
7356
7474
|
if (this.isClaudeCliEvent(jsonEvent)) {
|
|
7357
|
-
progressEvent = this.convertClaudeEventToProgress(jsonEvent, sessionId,
|
|
7475
|
+
progressEvent = this.convertClaudeEventToProgress(jsonEvent, sessionId, rawLine);
|
|
7358
7476
|
isJsonParsed = true;
|
|
7359
7477
|
} else if (this.isGenericStreamingEvent(jsonEvent)) {
|
|
7360
7478
|
progressEvent = {
|
|
@@ -7389,7 +7507,7 @@ var init_shell_backend = __esm({
|
|
|
7389
7507
|
backend: "shell",
|
|
7390
7508
|
count: ++this.eventCounter,
|
|
7391
7509
|
type: "thinking",
|
|
7392
|
-
content:
|
|
7510
|
+
content: rawLine,
|
|
7393
7511
|
metadata: {
|
|
7394
7512
|
format: "text",
|
|
7395
7513
|
raw: true
|
|
@@ -13069,7 +13187,11 @@ var init_main = __esm({
|
|
|
13069
13187
|
\u274C Execution failed (${elapsed})`));
|
|
13070
13188
|
}
|
|
13071
13189
|
const lastIteration = result.iterations[result.iterations.length - 1];
|
|
13072
|
-
|
|
13190
|
+
const structuredOutput = lastIteration?.toolResult.metadata?.structuredOutput === true;
|
|
13191
|
+
const shouldPrintResult = Boolean(
|
|
13192
|
+
lastIteration && lastIteration.toolResult.content && (!this.hasStreamedJsonOutput || structuredOutput)
|
|
13193
|
+
);
|
|
13194
|
+
if (shouldPrintResult) {
|
|
13073
13195
|
console.error(chalk15.blue("\n\u{1F4C4} Result:"));
|
|
13074
13196
|
console.log(lastIteration.toolResult.content);
|
|
13075
13197
|
}
|
|
@@ -13407,7 +13529,7 @@ async function validateJSONConfigs(baseDir = process.cwd(), backendType = "mcp")
|
|
|
13407
13529
|
}
|
|
13408
13530
|
function displayValidationResults(result) {
|
|
13409
13531
|
if (result.isValid && result.warnings.length === 0) {
|
|
13410
|
-
console.
|
|
13532
|
+
console.error(chalk15.green("\u2705 All configuration files are valid\n"));
|
|
13411
13533
|
return;
|
|
13412
13534
|
}
|
|
13413
13535
|
if (result.errors.length > 0) {
|
|
@@ -21833,6 +21955,11 @@ var QUICK_REFERENCE = [
|
|
|
21833
21955
|
description: "Shell completion setup",
|
|
21834
21956
|
usage: "juno-code completion <install|uninstall>"
|
|
21835
21957
|
},
|
|
21958
|
+
{
|
|
21959
|
+
name: "services",
|
|
21960
|
+
description: "Manage service scripts (use --force to refresh codex.py/claude.py)",
|
|
21961
|
+
usage: "juno-code services install --force"
|
|
21962
|
+
},
|
|
21836
21963
|
{
|
|
21837
21964
|
name: "help",
|
|
21838
21965
|
description: "Show help information",
|
|
@@ -22401,11 +22528,12 @@ init_service_installer();
|
|
|
22401
22528
|
function createServicesCommand() {
|
|
22402
22529
|
const servicesCmd = new Command("services").description("Manage juno-code service scripts").addHelpText("after", `
|
|
22403
22530
|
Examples:
|
|
22404
|
-
$ juno-code services install
|
|
22405
|
-
$ juno-code services
|
|
22406
|
-
$ juno-code services
|
|
22407
|
-
$ juno-code services
|
|
22408
|
-
$ juno-code services
|
|
22531
|
+
$ juno-code services install Install service scripts to ~/.juno_code/services/
|
|
22532
|
+
$ juno-code services install --force Reinstall/refresh service scripts (codex.py/claude.py)
|
|
22533
|
+
$ juno-code services list List installed service scripts
|
|
22534
|
+
$ juno-code services status Check installation status
|
|
22535
|
+
$ juno-code services uninstall Remove all service scripts
|
|
22536
|
+
$ juno-code services path Show services directory path
|
|
22409
22537
|
|
|
22410
22538
|
Service scripts are Python/shell scripts that provide additional functionality
|
|
22411
22539
|
and can be customized by users. They are installed to ~/.juno_code/services/
|
|
@@ -22579,7 +22707,7 @@ var ShellDetector = class _ShellDetector {
|
|
|
22579
22707
|
* Get shell configuration file path
|
|
22580
22708
|
*/
|
|
22581
22709
|
getConfigPath(shell) {
|
|
22582
|
-
const homeDir =
|
|
22710
|
+
const homeDir = os4.homedir();
|
|
22583
22711
|
switch (shell) {
|
|
22584
22712
|
case "bash":
|
|
22585
22713
|
if (process.platform === "darwin") {
|
|
@@ -22603,7 +22731,7 @@ var ShellDetector = class _ShellDetector {
|
|
|
22603
22731
|
* Get shell completion script installation path
|
|
22604
22732
|
*/
|
|
22605
22733
|
getCompletionPath(shell) {
|
|
22606
|
-
const homeDir =
|
|
22734
|
+
const homeDir = os4.homedir();
|
|
22607
22735
|
switch (shell) {
|
|
22608
22736
|
case "bash":
|
|
22609
22737
|
if (process.platform === "darwin") {
|
|
@@ -22881,7 +23009,7 @@ var ContextAwareCompletion = class {
|
|
|
22881
23009
|
*/
|
|
22882
23010
|
expandPath(inputPath) {
|
|
22883
23011
|
if (inputPath.startsWith("~/")) {
|
|
22884
|
-
return path3.join(
|
|
23012
|
+
return path3.join(os4.homedir(), inputPath.slice(2));
|
|
22885
23013
|
}
|
|
22886
23014
|
if (inputPath.startsWith("./") || inputPath.startsWith("../")) {
|
|
22887
23015
|
return path3.resolve(inputPath);
|