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 CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  var fs2 = require('fs-extra');
5
5
  var path3 = require('path');
6
- var os3 = require('os');
6
+ var os4 = require('os');
7
7
  var url = require('url');
8
8
  var module$1 = require('module');
9
9
  var semver = require('semver');
@@ -54,7 +54,7 @@ function _interopNamespace(e) {
54
54
 
55
55
  var fs2__default = /*#__PURE__*/_interopDefault(fs2);
56
56
  var path3__namespace = /*#__PURE__*/_interopNamespace(path3);
57
- var os3__namespace = /*#__PURE__*/_interopNamespace(os3);
57
+ var os4__namespace = /*#__PURE__*/_interopNamespace(os4);
58
58
  var semver__default = /*#__PURE__*/_interopDefault(semver);
59
59
  var nodeFs__namespace = /*#__PURE__*/_interopNamespace(nodeFs);
60
60
  var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
@@ -341,8 +341,8 @@ var init_service_installer = __esm({
341
341
  "src/utils/service-installer.ts"() {
342
342
  init_version();
343
343
  ServiceInstaller = class {
344
- static SERVICES_DIR = path3__namespace.join(os3.homedir(), ".juno_code", "services");
345
- static VERSION_FILE = path3__namespace.join(os3.homedir(), ".juno_code", "services", ".version");
344
+ static SERVICES_DIR = path3__namespace.join(os4.homedir(), ".juno_code", "services");
345
+ static VERSION_FILE = path3__namespace.join(os4.homedir(), ".juno_code", "services", ".version");
346
346
  /**
347
347
  * Get the current package version
348
348
  */
@@ -3331,13 +3331,9 @@ var init_advanced_logger = __esm({
3331
3331
  /**
3332
3332
  * Output formatted log
3333
3333
  */
3334
- output(formatted, level) {
3334
+ output(formatted, _level) {
3335
3335
  if (this.options.output === "console" || this.options.output === "both") {
3336
- if (level >= 3 /* WARN */) {
3337
- console.error(formatted);
3338
- } else {
3339
- console.log(formatted);
3340
- }
3336
+ console.error(formatted);
3341
3337
  }
3342
3338
  if (this.options.output === "file" || this.options.output === "both") {
3343
3339
  this.writeToFile(formatted);
@@ -5415,8 +5411,8 @@ var init_terminal_progress_writer = __esm({
5415
5411
  this.options.stream.write("\r\x1B[K");
5416
5412
  if (typeof content === "string") {
5417
5413
  this.options.stream.write(content);
5418
- if (!content.endsWith("\n") && !content.endsWith(os3.EOL)) {
5419
- this.options.stream.write(os3.EOL);
5414
+ if (!content.endsWith("\n") && !content.endsWith(os4.EOL)) {
5415
+ this.options.stream.write(os4.EOL);
5420
5416
  }
5421
5417
  } else {
5422
5418
  console.error(content);
@@ -5424,8 +5420,8 @@ var init_terminal_progress_writer = __esm({
5424
5420
  } else {
5425
5421
  if (typeof content === "string") {
5426
5422
  this.options.stream.write(content);
5427
- if (!content.endsWith("\n") && !content.endsWith(os3.EOL)) {
5428
- this.options.stream.write(os3.EOL);
5423
+ if (!content.endsWith("\n") && !content.endsWith(os4.EOL)) {
5424
+ this.options.stream.write(os4.EOL);
5429
5425
  }
5430
5426
  } else {
5431
5427
  console.error(content);
@@ -6033,7 +6029,7 @@ var init_client = __esm({
6033
6029
  `${serverName}`,
6034
6030
  // Assume it's in PATH
6035
6031
  `/usr/local/bin/${serverName}`,
6036
- path3__namespace.default.resolve(os3__namespace.default.homedir(), `.local/bin/${serverName}`),
6032
+ path3__namespace.default.resolve(os4__namespace.default.homedir(), `.local/bin/${serverName}`),
6037
6033
  path3__namespace.default.resolve(this.options.workingDirectory || process.cwd(), `${serverName}`)
6038
6034
  ];
6039
6035
  for (const serverPath of possiblePaths) {
@@ -7042,7 +7038,7 @@ var init_shell_backend = __esm({
7042
7038
  });
7043
7039
  try {
7044
7040
  const scriptPath = await this.findScriptForSubagent(subagentType);
7045
- const result = await this.executeScript(scriptPath, request, toolId);
7041
+ const result = await this.executeScript(scriptPath, request, toolId, subagentType);
7046
7042
  const duration = Date.now() - startTime;
7047
7043
  await this.emitProgressEvent({
7048
7044
  sessionId: request.metadata?.sessionId || "unknown",
@@ -7059,8 +7055,9 @@ var init_shell_backend = __esm({
7059
7055
  phase: "completion"
7060
7056
  }
7061
7057
  });
7058
+ const structuredResult = this.buildStructuredOutput(subagentType, result);
7062
7059
  return {
7063
- content: result.output,
7060
+ content: structuredResult.content,
7064
7061
  status: result.success ? "completed" : "failed",
7065
7062
  startTime: new Date(startTime),
7066
7063
  endTime: /* @__PURE__ */ new Date(),
@@ -7068,6 +7065,7 @@ var init_shell_backend = __esm({
7068
7065
  error: result.error ? { type: "shell_execution", message: result.error, timestamp: /* @__PURE__ */ new Date() } : void 0,
7069
7066
  progressEvents: [],
7070
7067
  // Progress events are handled via callbacks
7068
+ ...structuredResult.metadata ? { metadata: structuredResult.metadata } : void 0,
7071
7069
  request
7072
7070
  };
7073
7071
  } catch (error) {
@@ -7233,8 +7231,8 @@ var init_shell_backend = __esm({
7233
7231
  /**
7234
7232
  * Execute a shell script
7235
7233
  */
7236
- async executeScript(scriptPath, request, toolId) {
7237
- return new Promise((resolve9, reject) => {
7234
+ async executeScript(scriptPath, request, toolId, subagentType) {
7235
+ return new Promise(async (resolve9, reject) => {
7238
7236
  const startTime = Date.now();
7239
7237
  const isPython = scriptPath.endsWith(".py");
7240
7238
  const env2 = {
@@ -7247,6 +7245,19 @@ var init_shell_backend = __esm({
7247
7245
  JUNO_ITERATION: String(request.arguments?.iteration || 1),
7248
7246
  JUNO_TOOL_ID: toolId
7249
7247
  };
7248
+ let captureDir = null;
7249
+ let capturePath = null;
7250
+ if (subagentType === "claude") {
7251
+ try {
7252
+ captureDir = await nodeFs.promises.mkdtemp(path3__namespace.join(os4__namespace.default.tmpdir(), "juno-shell-"));
7253
+ capturePath = path3__namespace.join(captureDir, `subagent_${toolId}.json`);
7254
+ env2.JUNO_SUBAGENT_CAPTURE_PATH = capturePath;
7255
+ } catch (error) {
7256
+ if (this.config?.debug) {
7257
+ engineLogger.warn(`Failed to prepare subagent capture path: ${error instanceof Error ? error.message : String(error)}`);
7258
+ }
7259
+ }
7260
+ }
7250
7261
  const command = isPython ? "python3" : "bash";
7251
7262
  const args = [scriptPath];
7252
7263
  if (isPython && request.arguments?.instruction) {
@@ -7321,20 +7332,46 @@ var init_shell_backend = __esm({
7321
7332
  }
7322
7333
  });
7323
7334
  child.on("close", (exitCode) => {
7324
- if (isProcessKilled) return;
7325
- const duration = Date.now() - startTime;
7326
- const success = exitCode === 0;
7327
- if (this.config.debug) {
7328
- engineLogger.debug(`Script execution completed with exit code: ${exitCode}, duration: ${duration}ms`);
7329
- engineLogger.debug(`Stdout length: ${stdout2.length}, Stderr length: ${stderr.length}`);
7330
- }
7331
- resolve9({
7332
- success,
7333
- output: stdout2,
7334
- error: stderr || void 0,
7335
- exitCode: exitCode || 0,
7336
- duration
7337
- });
7335
+ void (async () => {
7336
+ if (isProcessKilled) return;
7337
+ const duration = Date.now() - startTime;
7338
+ const success = exitCode === 0;
7339
+ let subAgentResponse;
7340
+ if (capturePath) {
7341
+ try {
7342
+ const captured = await nodeFs.promises.readFile(capturePath, "utf-8");
7343
+ if (captured.trim()) {
7344
+ subAgentResponse = JSON.parse(captured);
7345
+ }
7346
+ } catch (error) {
7347
+ if (this.config?.debug) {
7348
+ engineLogger.warn(`Failed to read subagent capture: ${error instanceof Error ? error.message : String(error)}`);
7349
+ }
7350
+ } finally {
7351
+ if (captureDir) {
7352
+ try {
7353
+ await nodeFs.promises.rm(captureDir, { recursive: true, force: true });
7354
+ } catch (cleanupError) {
7355
+ if (this.config?.debug) {
7356
+ engineLogger.warn(`Failed to clean capture directory: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`);
7357
+ }
7358
+ }
7359
+ }
7360
+ }
7361
+ }
7362
+ if (this.config.debug) {
7363
+ engineLogger.debug(`Script execution completed with exit code: ${exitCode}, duration: ${duration}ms`);
7364
+ engineLogger.debug(`Stdout length: ${stdout2.length}, Stderr length: ${stderr.length}`);
7365
+ }
7366
+ resolve9({
7367
+ success,
7368
+ output: stdout2,
7369
+ error: stderr || void 0,
7370
+ exitCode: exitCode || 0,
7371
+ duration,
7372
+ ...subAgentResponse ? { subAgentResponse } : void 0
7373
+ });
7374
+ })();
7338
7375
  });
7339
7376
  child.on("error", (error) => {
7340
7377
  if (isProcessKilled) return;
@@ -7366,6 +7403,66 @@ var init_shell_backend = __esm({
7366
7403
  });
7367
7404
  });
7368
7405
  }
7406
+ /**
7407
+ * Build a structured, JSON-parsable result payload for programmatic capture while
7408
+ * preserving the shell backend's existing on-screen streaming behavior.
7409
+ */
7410
+ buildStructuredOutput(subagentType, result) {
7411
+ if (subagentType === "claude") {
7412
+ const claudeEvent = result.subAgentResponse ?? this.extractLastJsonEvent(result.output);
7413
+ const isError = claudeEvent?.is_error ?? claudeEvent?.subtype === "error" ?? !result.success;
7414
+ const structuredPayload = {
7415
+ type: "result",
7416
+ subtype: claudeEvent?.subtype || (isError ? "error" : "success"),
7417
+ is_error: isError,
7418
+ result: claudeEvent?.result ?? claudeEvent?.error ?? claudeEvent?.content ?? result.output,
7419
+ error: claudeEvent?.error,
7420
+ stderr: result.error,
7421
+ datetime: claudeEvent?.datetime,
7422
+ counter: claudeEvent?.counter,
7423
+ session_id: claudeEvent?.session_id,
7424
+ num_turns: claudeEvent?.num_turns,
7425
+ duration_ms: claudeEvent?.duration_ms ?? result.duration,
7426
+ exit_code: result.exitCode,
7427
+ total_cost_usd: claudeEvent?.total_cost_usd,
7428
+ usage: claudeEvent?.usage,
7429
+ modelUsage: claudeEvent?.modelUsage || claudeEvent?.model_usage || {},
7430
+ permission_denials: claudeEvent?.permission_denials || [],
7431
+ uuid: claudeEvent?.uuid,
7432
+ sub_agent_response: claudeEvent
7433
+ };
7434
+ const metadata = {
7435
+ ...claudeEvent ? { subAgentResponse: claudeEvent } : void 0,
7436
+ structuredOutput: true,
7437
+ contentType: "application/json",
7438
+ rawOutput: result.output
7439
+ };
7440
+ return {
7441
+ content: JSON.stringify(structuredPayload),
7442
+ metadata
7443
+ };
7444
+ }
7445
+ return { content: result.output, metadata: result.metadata };
7446
+ }
7447
+ /**
7448
+ * Extract the last valid JSON object from a script's stdout to use as a structured payload fallback.
7449
+ */
7450
+ extractLastJsonEvent(output) {
7451
+ if (!output) {
7452
+ return null;
7453
+ }
7454
+ const lines = output.split("\n").map((line) => line.trim()).filter(Boolean);
7455
+ for (let i = lines.length - 1; i >= 0; i--) {
7456
+ try {
7457
+ const parsed = JSON.parse(lines[i]);
7458
+ if (parsed && typeof parsed === "object") {
7459
+ return parsed;
7460
+ }
7461
+ } catch {
7462
+ }
7463
+ }
7464
+ return null;
7465
+ }
7369
7466
  /**
7370
7467
  * Parse streaming events from script output
7371
7468
  * Handles both JSON format (Claude) and TEXT format (Codex)
@@ -7373,7 +7470,7 @@ var init_shell_backend = __esm({
7373
7470
  * Strategy:
7374
7471
  * 1. Try to parse each line as JSON first (for Claude)
7375
7472
  * 2. If JSON parsing fails, treat as TEXT streaming (for Codex and other text-based subagents)
7376
- * 3. Emit all non-empty lines as progress events for real-time display
7473
+ * 3. Emit all text lines (including whitespace-only) as progress events for real-time display
7377
7474
  */
7378
7475
  parseAndEmitStreamingEvents(data, sessionId) {
7379
7476
  if (!this.jsonBuffer) {
@@ -7383,14 +7480,35 @@ var init_shell_backend = __esm({
7383
7480
  const lines = this.jsonBuffer.split("\n");
7384
7481
  this.jsonBuffer = lines.pop() || "";
7385
7482
  for (const line of lines) {
7386
- const trimmedLine = line.trim();
7387
- if (!trimmedLine) continue;
7483
+ const rawLine = line.endsWith("\r") ? line.slice(0, -1) : line;
7484
+ if (!rawLine) continue;
7485
+ const hasNonWhitespace = rawLine.trim().length > 0;
7486
+ if (!hasNonWhitespace) {
7487
+ this.emitProgressEvent({
7488
+ sessionId,
7489
+ timestamp: /* @__PURE__ */ new Date(),
7490
+ backend: "shell",
7491
+ count: ++this.eventCounter,
7492
+ type: "thinking",
7493
+ content: rawLine,
7494
+ metadata: {
7495
+ format: "text",
7496
+ raw: true
7497
+ }
7498
+ }).catch((error) => {
7499
+ if (this.config?.debug) {
7500
+ engineLogger.warn(`Failed to emit whitespace-only streaming event: ${error instanceof Error ? error.message : String(error)}`);
7501
+ }
7502
+ });
7503
+ continue;
7504
+ }
7505
+ const trimmedLine = rawLine.trim();
7388
7506
  let isJsonParsed = false;
7389
7507
  try {
7390
7508
  const jsonEvent = JSON.parse(trimmedLine);
7391
7509
  let progressEvent;
7392
7510
  if (this.isClaudeCliEvent(jsonEvent)) {
7393
- progressEvent = this.convertClaudeEventToProgress(jsonEvent, sessionId, trimmedLine);
7511
+ progressEvent = this.convertClaudeEventToProgress(jsonEvent, sessionId, rawLine);
7394
7512
  isJsonParsed = true;
7395
7513
  } else if (this.isGenericStreamingEvent(jsonEvent)) {
7396
7514
  progressEvent = {
@@ -7425,7 +7543,7 @@ var init_shell_backend = __esm({
7425
7543
  backend: "shell",
7426
7544
  count: ++this.eventCounter,
7427
7545
  type: "thinking",
7428
- content: trimmedLine,
7546
+ content: rawLine,
7429
7547
  metadata: {
7430
7548
  format: "text",
7431
7549
  raw: true
@@ -7890,7 +8008,7 @@ var init_concurrent_feedback_collector = __esm({
7890
8008
  process.stdin.removeAllListeners("data");
7891
8009
  process.stdin.removeAllListeners("end");
7892
8010
  if (this.options.verbose) {
7893
- process.stderr.write(`${os3.EOL}[feedback-collector] Stopped. Total submissions: ${this.submissionCount}${os3.EOL}`);
8011
+ process.stderr.write(`${os4.EOL}[feedback-collector] Stopped. Total submissions: ${this.submissionCount}${os4.EOL}`);
7894
8012
  }
7895
8013
  }
7896
8014
  /**
@@ -7953,7 +8071,7 @@ var init_concurrent_feedback_collector = __esm({
7953
8071
  chalk15__default.default.blue.bold("\u2551") + chalk15__default.default.gray(" Exit: Press Ctrl-D (or Ctrl-Z on Windows)") + " ".repeat(16) + chalk15__default.default.blue.bold("\u2551"),
7954
8072
  chalk15__default.default.blue.bold("\u255A" + border + "\u255D"),
7955
8073
  chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Type F+Enter to start giving feedback)")
7956
- ].join(os3.EOL) + os3.EOL
8074
+ ].join(os4.EOL) + os4.EOL
7957
8075
  );
7958
8076
  }
7959
8077
  /**
@@ -7963,7 +8081,7 @@ var init_concurrent_feedback_collector = __esm({
7963
8081
  this.progressTimer = setInterval(() => {
7964
8082
  this.progressTick += 1;
7965
8083
  const elapsed = ((Date.now() - this.startTime.getTime()) / 1e3).toFixed(1);
7966
- process.stderr.write(`[progress] tick=${this.progressTick} elapsed=${elapsed}s${os3.EOL}`);
8084
+ process.stderr.write(`[progress] tick=${this.progressTick} elapsed=${elapsed}s${os4.EOL}`);
7967
8085
  }, this.options.progressInterval);
7968
8086
  }
7969
8087
  /**
@@ -7973,10 +8091,10 @@ var init_concurrent_feedback_collector = __esm({
7973
8091
  this.feedbackMode = "feedback" /* FEEDBACK */;
7974
8092
  setFeedbackActive(true);
7975
8093
  this.buffer = "";
7976
- process.stdout.write(os3.EOL + chalk15__default.default.yellow.bold("\u{1F4DD} FEEDBACK MODE") + chalk15__default.default.gray(" - Type feedback (multiline ok), then Q+Enter to submit | MCP progress paused") + os3.EOL);
8094
+ process.stdout.write(os4.EOL + chalk15__default.default.yellow.bold("\u{1F4DD} FEEDBACK MODE") + chalk15__default.default.gray(" - Type feedback (multiline ok), then Q+Enter to submit | MCP progress paused") + os4.EOL);
7977
8095
  process.stdout.write(chalk15__default.default.cyan.bold("> "));
7978
8096
  if (this.options.verbose) {
7979
- process.stderr.write(`[feedback-collector] Entered FEEDBACK mode - MCP progress buffering activated${os3.EOL}`);
8097
+ process.stderr.write(`[feedback-collector] Entered FEEDBACK mode - MCP progress buffering activated${os4.EOL}`);
7980
8098
  }
7981
8099
  }
7982
8100
  /**
@@ -7986,7 +8104,7 @@ var init_concurrent_feedback_collector = __esm({
7986
8104
  this.feedbackMode = "normal" /* NORMAL */;
7987
8105
  setFeedbackActive(false);
7988
8106
  if (this.options.verbose) {
7989
- process.stderr.write(`[feedback-collector] Exited FEEDBACK mode - MCP progress restored${os3.EOL}`);
8107
+ process.stderr.write(`[feedback-collector] Exited FEEDBACK mode - MCP progress restored${os4.EOL}`);
7990
8108
  }
7991
8109
  }
7992
8110
  /**
@@ -8029,7 +8147,7 @@ var init_concurrent_feedback_collector = __esm({
8029
8147
  clearInterval(this.progressTimer);
8030
8148
  }
8031
8149
  if (this.options.verbose) {
8032
- process.stderr.write(`${os3.EOL}[feedback-collector] EOF received. Total submissions: ${this.submissionCount}${os3.EOL}`);
8150
+ process.stderr.write(`${os4.EOL}[feedback-collector] EOF received. Total submissions: ${this.submissionCount}${os4.EOL}`);
8033
8151
  }
8034
8152
  });
8035
8153
  }
@@ -8044,7 +8162,7 @@ var init_concurrent_feedback_collector = __esm({
8044
8162
  return;
8045
8163
  }
8046
8164
  if (trimmed.length > 0) {
8047
- process.stdout.write(chalk15__default.default.gray("Type F+Enter to enter feedback mode, or Ctrl-D to exit") + os3.EOL);
8165
+ process.stdout.write(chalk15__default.default.gray("Type F+Enter to enter feedback mode, or Ctrl-D to exit") + os4.EOL);
8048
8166
  process.stdout.write(chalk15__default.default.cyan.bold("> "));
8049
8167
  }
8050
8168
  return;
@@ -8053,10 +8171,10 @@ var init_concurrent_feedback_collector = __esm({
8053
8171
  if (trimmed === "q") {
8054
8172
  this.submitFeedback();
8055
8173
  this.exitFeedbackMode();
8056
- process.stdout.write(os3.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Type F+Enter for another feedback, or Ctrl-D to exit)") + os3.EOL);
8174
+ process.stdout.write(os4.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Type F+Enter for another feedback, or Ctrl-D to exit)") + os4.EOL);
8057
8175
  return;
8058
8176
  }
8059
- this.buffer += line + os3.EOL;
8177
+ this.buffer += line + os4.EOL;
8060
8178
  }
8061
8179
  }
8062
8180
  /**
@@ -8066,18 +8184,18 @@ var init_concurrent_feedback_collector = __esm({
8066
8184
  const content = this.buffer.trimEnd();
8067
8185
  this.buffer = "";
8068
8186
  if (content.length === 0) {
8069
- process.stdout.write(os3.EOL + chalk15__default.default.yellow("\u26A0\uFE0F No feedback content to submit") + os3.EOL);
8187
+ process.stdout.write(os4.EOL + chalk15__default.default.yellow("\u26A0\uFE0F No feedback content to submit") + os4.EOL);
8070
8188
  return;
8071
8189
  }
8072
- process.stdout.write(os3.EOL + chalk15__default.default.green.bold("\u2705 Feedback registered and being processed...") + os3.EOL);
8190
+ process.stdout.write(os4.EOL + chalk15__default.default.green.bold("\u2705 Feedback registered and being processed...") + os4.EOL);
8073
8191
  if (this.options.verbose) {
8074
- process.stdout.write(chalk15__default.default.gray("Feedback content:") + os3.EOL);
8075
- process.stdout.write(content + os3.EOL);
8076
- process.stdout.write(chalk15__default.default.cyan("===== END BLOCK =====") + os3.EOL);
8192
+ process.stdout.write(chalk15__default.default.gray("Feedback content:") + os4.EOL);
8193
+ process.stdout.write(content + os4.EOL);
8194
+ process.stdout.write(chalk15__default.default.cyan("===== END BLOCK =====") + os4.EOL);
8077
8195
  }
8078
8196
  flushBufferedProgress();
8079
8197
  this.enqueueSubmission(content).catch((err) => {
8080
- process.stderr.write(`${os3.EOL}[feedback-collector] Error submitting feedback: ${err}${os3.EOL}`);
8198
+ process.stderr.write(`${os4.EOL}[feedback-collector] Error submitting feedback: ${err}${os4.EOL}`);
8081
8199
  });
8082
8200
  }
8083
8201
  /**
@@ -8103,18 +8221,18 @@ var init_concurrent_feedback_collector = __esm({
8103
8221
  this.submissions.push(submission);
8104
8222
  if (this.options.onSubmit) {
8105
8223
  if (this.options.verbose) {
8106
- process.stderr.write(`${os3.EOL}[feedback-collector ${n}] Using custom submission handler${os3.EOL}`);
8224
+ process.stderr.write(`${os4.EOL}[feedback-collector ${n}] Using custom submission handler${os4.EOL}`);
8107
8225
  }
8108
8226
  try {
8109
8227
  await this.options.onSubmit(input);
8110
8228
  if (this.options.verbose) {
8111
- process.stderr.write(`[feedback-collector ${n}] Custom handler completed${os3.EOL}`);
8229
+ process.stderr.write(`[feedback-collector ${n}] Custom handler completed${os4.EOL}`);
8112
8230
  }
8113
- process.stdout.write(os3.EOL + chalk15__default.default.green("\u2705 Feedback submitted successfully. You can type another block.") + os3.EOL);
8114
- process.stdout.write(os3.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Ready for next feedback)") + os3.EOL);
8231
+ process.stdout.write(os4.EOL + chalk15__default.default.green("\u2705 Feedback submitted successfully. You can type another block.") + os4.EOL);
8232
+ process.stdout.write(os4.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Ready for next feedback)") + os4.EOL);
8115
8233
  } catch (error) {
8116
- process.stderr.write(`[feedback-collector ${n}] Custom handler error: ${error}${os3.EOL}`);
8117
- process.stdout.write(os3.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os3.EOL);
8234
+ process.stderr.write(`[feedback-collector ${n}] Custom handler error: ${error}${os4.EOL}`);
8235
+ process.stdout.write(os4.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os4.EOL);
8118
8236
  }
8119
8237
  } else {
8120
8238
  await this.runCommandWithInput(n, input);
@@ -8125,7 +8243,7 @@ var init_concurrent_feedback_collector = __esm({
8125
8243
  */
8126
8244
  async runCommandWithInput(n, input) {
8127
8245
  if (this.options.verbose) {
8128
- process.stderr.write(`${os3.EOL}[feedback-collector ${n}] Launching "${this.options.command}" ${this.options.commandArgs.join(" ")}${os3.EOL}`);
8246
+ process.stderr.write(`${os4.EOL}[feedback-collector ${n}] Launching "${this.options.command}" ${this.options.commandArgs.join(" ")}${os4.EOL}`);
8129
8247
  }
8130
8248
  return new Promise((resolve9) => {
8131
8249
  const child = child_process.spawn(this.options.command, this.options.commandArgs, {
@@ -8143,25 +8261,25 @@ var init_concurrent_feedback_collector = __esm({
8143
8261
  });
8144
8262
  child.on("close", (code) => {
8145
8263
  if (this.options.verbose) {
8146
- process.stderr.write(`[feedback-collector ${n}] exit code ${code ?? 0}${os3.EOL}`);
8264
+ process.stderr.write(`[feedback-collector ${n}] exit code ${code ?? 0}${os4.EOL}`);
8147
8265
  }
8148
8266
  if (code === 0) {
8149
- process.stdout.write(os3.EOL + chalk15__default.default.green("\u2705 Feedback submitted successfully. You can type another block.") + os3.EOL);
8150
- process.stdout.write(os3.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Ready for next feedback)") + os3.EOL);
8267
+ process.stdout.write(os4.EOL + chalk15__default.default.green("\u2705 Feedback submitted successfully. You can type another block.") + os4.EOL);
8268
+ process.stdout.write(os4.EOL + chalk15__default.default.cyan.bold("> ") + chalk15__default.default.gray("(Ready for next feedback)") + os4.EOL);
8151
8269
  } else {
8152
- process.stdout.write(os3.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os3.EOL);
8270
+ process.stdout.write(os4.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os4.EOL);
8153
8271
  }
8154
8272
  resolve9();
8155
8273
  });
8156
8274
  child.on("error", (err) => {
8157
- process.stderr.write(`[feedback-collector ${n}] error: ${err.message}${os3.EOL}`);
8158
- process.stdout.write(os3.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os3.EOL);
8275
+ process.stderr.write(`[feedback-collector ${n}] error: ${err.message}${os4.EOL}`);
8276
+ process.stdout.write(os4.EOL + chalk15__default.default.red("\u274C Feedback submission failed. Please try again.") + os4.EOL);
8159
8277
  resolve9();
8160
8278
  });
8161
8279
  if (child.stdin) {
8162
8280
  child.stdin.write(input);
8163
- if (!input.endsWith(os3.EOL)) {
8164
- child.stdin.write(os3.EOL);
8281
+ if (!input.endsWith(os4.EOL)) {
8282
+ child.stdin.write(os4.EOL);
8165
8283
  }
8166
8284
  child.stdin.end();
8167
8285
  }
@@ -13105,7 +13223,11 @@ var init_main = __esm({
13105
13223
  \u274C Execution failed (${elapsed})`));
13106
13224
  }
13107
13225
  const lastIteration = result.iterations[result.iterations.length - 1];
13108
- if (lastIteration && lastIteration.toolResult.content && !this.hasStreamedJsonOutput) {
13226
+ const structuredOutput = lastIteration?.toolResult.metadata?.structuredOutput === true;
13227
+ const shouldPrintResult = Boolean(
13228
+ lastIteration && lastIteration.toolResult.content && (!this.hasStreamedJsonOutput || structuredOutput)
13229
+ );
13230
+ if (shouldPrintResult) {
13109
13231
  console.error(chalk15__default.default.blue("\n\u{1F4C4} Result:"));
13110
13232
  console.log(lastIteration.toolResult.content);
13111
13233
  }
@@ -13443,7 +13565,7 @@ async function validateJSONConfigs(baseDir = process.cwd(), backendType = "mcp")
13443
13565
  }
13444
13566
  function displayValidationResults(result) {
13445
13567
  if (result.isValid && result.warnings.length === 0) {
13446
- console.log(chalk15__default.default.green("\u2705 All configuration files are valid\n"));
13568
+ console.error(chalk15__default.default.green("\u2705 All configuration files are valid\n"));
13447
13569
  return;
13448
13570
  }
13449
13571
  if (result.errors.length > 0) {
@@ -21869,6 +21991,11 @@ var QUICK_REFERENCE = [
21869
21991
  description: "Shell completion setup",
21870
21992
  usage: "juno-code completion <install|uninstall>"
21871
21993
  },
21994
+ {
21995
+ name: "services",
21996
+ description: "Manage service scripts (use --force to refresh codex.py/claude.py)",
21997
+ usage: "juno-code services install --force"
21998
+ },
21872
21999
  {
21873
22000
  name: "help",
21874
22001
  description: "Show help information",
@@ -22437,11 +22564,12 @@ init_service_installer();
22437
22564
  function createServicesCommand() {
22438
22565
  const servicesCmd = new commander.Command("services").description("Manage juno-code service scripts").addHelpText("after", `
22439
22566
  Examples:
22440
- $ juno-code services install Install service scripts to ~/.juno_code/services/
22441
- $ juno-code services list List installed service scripts
22442
- $ juno-code services status Check installation status
22443
- $ juno-code services uninstall Remove all service scripts
22444
- $ juno-code services path Show services directory path
22567
+ $ juno-code services install Install service scripts to ~/.juno_code/services/
22568
+ $ juno-code services install --force Reinstall/refresh service scripts (codex.py/claude.py)
22569
+ $ juno-code services list List installed service scripts
22570
+ $ juno-code services status Check installation status
22571
+ $ juno-code services uninstall Remove all service scripts
22572
+ $ juno-code services path Show services directory path
22445
22573
 
22446
22574
  Service scripts are Python/shell scripts that provide additional functionality
22447
22575
  and can be customized by users. They are installed to ~/.juno_code/services/
@@ -22615,7 +22743,7 @@ var ShellDetector = class _ShellDetector {
22615
22743
  * Get shell configuration file path
22616
22744
  */
22617
22745
  getConfigPath(shell) {
22618
- const homeDir = os3__namespace.homedir();
22746
+ const homeDir = os4__namespace.homedir();
22619
22747
  switch (shell) {
22620
22748
  case "bash":
22621
22749
  if (process.platform === "darwin") {
@@ -22639,7 +22767,7 @@ var ShellDetector = class _ShellDetector {
22639
22767
  * Get shell completion script installation path
22640
22768
  */
22641
22769
  getCompletionPath(shell) {
22642
- const homeDir = os3__namespace.homedir();
22770
+ const homeDir = os4__namespace.homedir();
22643
22771
  switch (shell) {
22644
22772
  case "bash":
22645
22773
  if (process.platform === "darwin") {
@@ -22917,7 +23045,7 @@ var ContextAwareCompletion = class {
22917
23045
  */
22918
23046
  expandPath(inputPath) {
22919
23047
  if (inputPath.startsWith("~/")) {
22920
- return path3__namespace.join(os3__namespace.homedir(), inputPath.slice(2));
23048
+ return path3__namespace.join(os4__namespace.homedir(), inputPath.slice(2));
22921
23049
  }
22922
23050
  if (inputPath.startsWith("./") || inputPath.startsWith("../")) {
22923
23051
  return path3__namespace.resolve(inputPath);