oh-my-opencode 3.7.1 → 3.7.3

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/cli/index.js CHANGED
@@ -4440,7 +4440,7 @@ function renamed(from, to) {
4440
4440
  };
4441
4441
  }
4442
4442
  var isNothing_1, isObject_1, toArray_1, repeat_1, isNegativeZero_1, extend_1, common, exception, snippet, TYPE_CONSTRUCTOR_OPTIONS, YAML_NODE_KINDS, type, schema, str, seq, map, failsafe, _null, bool, int, YAML_FLOAT_PATTERN, SCIENTIFIC_WITHOUT_DOT, float, json, core, YAML_DATE_REGEXP, YAML_TIMESTAMP_REGEXP, timestamp, merge, BASE64_MAP = `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
4443
- \r`, binary, _hasOwnProperty$3, _toString$2, omap, _toString$1, pairs, _hasOwnProperty$2, set, _default, _hasOwnProperty$1, CONTEXT_FLOW_IN = 1, CONTEXT_FLOW_OUT = 2, CONTEXT_BLOCK_IN = 3, CONTEXT_BLOCK_OUT = 4, CHOMPING_CLIP = 1, CHOMPING_STRIP = 2, CHOMPING_KEEP = 3, PATTERN_NON_PRINTABLE, PATTERN_NON_ASCII_LINE_BREAKS, PATTERN_FLOW_INDICATORS, PATTERN_TAG_HANDLE, PATTERN_TAG_URI, simpleEscapeCheck, simpleEscapeMap, i, directiveHandlers, loadAll_1, load_1, loader, _toString, _hasOwnProperty, CHAR_BOM = 65279, CHAR_TAB = 9, CHAR_LINE_FEED = 10, CHAR_CARRIAGE_RETURN = 13, CHAR_SPACE = 32, CHAR_EXCLAMATION = 33, CHAR_DOUBLE_QUOTE = 34, CHAR_SHARP = 35, CHAR_PERCENT = 37, CHAR_AMPERSAND = 38, CHAR_SINGLE_QUOTE = 39, CHAR_ASTERISK = 42, CHAR_COMMA = 44, CHAR_MINUS = 45, CHAR_COLON = 58, CHAR_EQUALS = 61, CHAR_GREATER_THAN = 62, CHAR_QUESTION = 63, CHAR_COMMERCIAL_AT = 64, CHAR_LEFT_SQUARE_BRACKET = 91, CHAR_RIGHT_SQUARE_BRACKET = 93, CHAR_GRAVE_ACCENT = 96, CHAR_LEFT_CURLY_BRACKET = 123, CHAR_VERTICAL_LINE = 124, CHAR_RIGHT_CURLY_BRACKET = 125, ESCAPE_SEQUENCES, DEPRECATED_BOOLEANS_SYNTAX, DEPRECATED_BASE60_SYNTAX, QUOTING_TYPE_SINGLE = 1, QUOTING_TYPE_DOUBLE = 2, STYLE_PLAIN = 1, STYLE_SINGLE = 2, STYLE_LITERAL = 3, STYLE_FOLDED = 4, STYLE_DOUBLE = 5, dump_1, dumper, load, loadAll, dump, safeLoad, safeLoadAll, safeDump;
4443
+ \r`, binary, _hasOwnProperty$3, _toString$2, omap, _toString$1, pairs, _hasOwnProperty$2, set, _default, _hasOwnProperty$1, CONTEXT_FLOW_IN = 1, CONTEXT_FLOW_OUT = 2, CONTEXT_BLOCK_IN = 3, CONTEXT_BLOCK_OUT = 4, CHOMPING_CLIP = 1, CHOMPING_STRIP = 2, CHOMPING_KEEP = 3, PATTERN_NON_PRINTABLE, PATTERN_NON_ASCII_LINE_BREAKS, PATTERN_FLOW_INDICATORS, PATTERN_TAG_HANDLE, PATTERN_TAG_URI, simpleEscapeCheck, simpleEscapeMap, i, directiveHandlers, loadAll_1, load_1, loader, _toString, _hasOwnProperty, CHAR_BOM = 65279, CHAR_TAB = 9, CHAR_LINE_FEED = 10, CHAR_CARRIAGE_RETURN = 13, CHAR_SPACE = 32, CHAR_EXCLAMATION = 33, CHAR_DOUBLE_QUOTE = 34, CHAR_SHARP = 35, CHAR_PERCENT = 37, CHAR_AMPERSAND = 38, CHAR_SINGLE_QUOTE = 39, CHAR_ASTERISK = 42, CHAR_COMMA = 44, CHAR_MINUS = 45, CHAR_COLON = 58, CHAR_EQUALS = 61, CHAR_GREATER_THAN = 62, CHAR_QUESTION = 63, CHAR_COMMERCIAL_AT = 64, CHAR_LEFT_SQUARE_BRACKET = 91, CHAR_RIGHT_SQUARE_BRACKET = 93, CHAR_GRAVE_ACCENT = 96, CHAR_LEFT_CURLY_BRACKET = 123, CHAR_VERTICAL_LINE = 124, CHAR_RIGHT_CURLY_BRACKET = 125, ESCAPE_SEQUENCES, DEPRECATED_BOOLEANS_SYNTAX, DEPRECATED_BASE60_SYNTAX, QUOTING_TYPE_SINGLE = 1, QUOTING_TYPE_DOUBLE = 2, STYLE_PLAIN = 1, STYLE_SINGLE = 2, STYLE_LITERAL = 3, STYLE_FOLDED = 4, STYLE_DOUBLE = 5, dump_1, dumper, Type, Schema, FAILSAFE_SCHEMA, JSON_SCHEMA, CORE_SCHEMA, DEFAULT_SCHEMA, load, loadAll, dump, YAMLException, types, safeLoad, safeLoadAll, safeDump, jsYaml;
4444
4444
  var init_js_yaml = __esm(() => {
4445
4445
  /*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT */
4446
4446
  isNothing_1 = isNothing;
@@ -4793,15 +4793,69 @@ var init_js_yaml = __esm(() => {
4793
4793
  dumper = {
4794
4794
  dump: dump_1
4795
4795
  };
4796
+ Type = type;
4797
+ Schema = schema;
4798
+ FAILSAFE_SCHEMA = failsafe;
4799
+ JSON_SCHEMA = json;
4800
+ CORE_SCHEMA = core;
4801
+ DEFAULT_SCHEMA = _default;
4796
4802
  load = loader.load;
4797
4803
  loadAll = loader.loadAll;
4798
4804
  dump = dumper.dump;
4805
+ YAMLException = exception;
4806
+ types = {
4807
+ binary,
4808
+ float,
4809
+ map,
4810
+ null: _null,
4811
+ pairs,
4812
+ set,
4813
+ timestamp,
4814
+ bool,
4815
+ int,
4816
+ merge,
4817
+ omap,
4818
+ seq,
4819
+ str
4820
+ };
4799
4821
  safeLoad = renamed("safeLoad", "load");
4800
4822
  safeLoadAll = renamed("safeLoadAll", "loadAll");
4801
4823
  safeDump = renamed("safeDump", "dump");
4824
+ jsYaml = {
4825
+ Type,
4826
+ Schema,
4827
+ FAILSAFE_SCHEMA,
4828
+ JSON_SCHEMA,
4829
+ CORE_SCHEMA,
4830
+ DEFAULT_SCHEMA,
4831
+ load,
4832
+ loadAll,
4833
+ dump,
4834
+ YAMLException,
4835
+ types,
4836
+ safeLoad,
4837
+ safeLoadAll,
4838
+ safeDump
4839
+ };
4802
4840
  });
4803
4841
 
4804
4842
  // src/shared/frontmatter.ts
4843
+ function parseFrontmatter(content) {
4844
+ const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n?---\r?\n([\s\S]*)$/;
4845
+ const match = content.match(frontmatterRegex);
4846
+ if (!match) {
4847
+ return { data: {}, body: content, hadFrontmatter: false, parseError: false };
4848
+ }
4849
+ const yamlContent = match[1];
4850
+ const body = match[2];
4851
+ try {
4852
+ const parsed = jsYaml.load(yamlContent, { schema: jsYaml.JSON_SCHEMA });
4853
+ const data = parsed ?? {};
4854
+ return { data, body, hadFrontmatter: true, parseError: false };
4855
+ } catch {
4856
+ return { data: {}, body, hadFrontmatter: true, parseError: true };
4857
+ }
4858
+ }
4805
4859
  var init_frontmatter = __esm(() => {
4806
4860
  init_js_yaml();
4807
4861
  });
@@ -8999,7 +9053,7 @@ var {
8999
9053
  // package.json
9000
9054
  var package_default = {
9001
9055
  name: "oh-my-opencode",
9002
- version: "3.7.1",
9056
+ version: "3.7.3",
9003
9057
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
9004
9058
  main: "dist/index.js",
9005
9059
  types: "dist/index.d.ts",
@@ -9073,13 +9127,13 @@ var package_default = {
9073
9127
  typescript: "^5.7.3"
9074
9128
  },
9075
9129
  optionalDependencies: {
9076
- "oh-my-opencode-darwin-arm64": "3.7.1",
9077
- "oh-my-opencode-darwin-x64": "3.7.1",
9078
- "oh-my-opencode-linux-arm64": "3.7.1",
9079
- "oh-my-opencode-linux-arm64-musl": "3.7.1",
9080
- "oh-my-opencode-linux-x64": "3.7.1",
9081
- "oh-my-opencode-linux-x64-musl": "3.7.1",
9082
- "oh-my-opencode-windows-x64": "3.7.1"
9130
+ "oh-my-opencode-darwin-arm64": "3.7.3",
9131
+ "oh-my-opencode-darwin-x64": "3.7.3",
9132
+ "oh-my-opencode-linux-arm64": "3.7.3",
9133
+ "oh-my-opencode-linux-arm64-musl": "3.7.3",
9134
+ "oh-my-opencode-linux-x64": "3.7.3",
9135
+ "oh-my-opencode-linux-x64-musl": "3.7.3",
9136
+ "oh-my-opencode-windows-x64": "3.7.3"
9083
9137
  },
9084
9138
  trustedDependencies: [
9085
9139
  "@ast-grep/cli",
@@ -10131,7 +10185,7 @@ async function install(args) {
10131
10185
  }
10132
10186
 
10133
10187
  // src/cli/run/runner.ts
10134
- var import_picocolors14 = __toESM(require_picocolors(), 1);
10188
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
10135
10189
 
10136
10190
  // src/cli/run/event-state.ts
10137
10191
  function createEventState() {
@@ -10143,7 +10197,22 @@ function createEventState() {
10143
10197
  lastPartText: "",
10144
10198
  currentTool: null,
10145
10199
  hasReceivedMeaningfulWork: false,
10146
- messageCount: 0
10200
+ messageCount: 0,
10201
+ currentAgent: null,
10202
+ currentModel: null,
10203
+ currentVariant: null,
10204
+ currentMessageRole: null,
10205
+ agentColorsByName: {},
10206
+ partTypesById: {},
10207
+ inThinkBlock: false,
10208
+ lastReasoningText: "",
10209
+ hasPrintedThinkingLine: false,
10210
+ lastThinkingLineWidth: 0,
10211
+ messageRoleById: {},
10212
+ lastThinkingSummary: "",
10213
+ textAtLineStart: true,
10214
+ thinkingAtLineStart: false,
10215
+ currentMessageId: null
10147
10216
  };
10148
10217
  }
10149
10218
  // src/cli/run/event-formatting.ts
@@ -10218,6 +10287,14 @@ function logEventVerbose(ctx, payload) {
10218
10287
  }
10219
10288
  break;
10220
10289
  }
10290
+ case "message.part.delta": {
10291
+ const deltaProps = props;
10292
+ const field = deltaProps?.field ?? "unknown";
10293
+ const delta = deltaProps?.delta ?? "";
10294
+ const preview = delta.slice(0, 80).replace(/\n/g, "\\n");
10295
+ console.error(import_picocolors5.default.dim(`${sessionTag} message.part.delta (${field}): "${preview}${delta.length > 80 ? "..." : ""}"`));
10296
+ break;
10297
+ }
10221
10298
  case "message.updated": {
10222
10299
  const msgProps = props;
10223
10300
  const role = msgProps?.info?.role ?? "unknown";
@@ -10264,10 +10341,222 @@ function logEventVerbose(ctx, payload) {
10264
10341
  }
10265
10342
  }
10266
10343
  // src/cli/run/event-stream-processor.ts
10267
- var import_picocolors7 = __toESM(require_picocolors(), 1);
10344
+ var import_picocolors8 = __toESM(require_picocolors(), 1);
10268
10345
 
10269
10346
  // src/cli/run/event-handlers.ts
10347
+ var import_picocolors7 = __toESM(require_picocolors(), 1);
10348
+
10349
+ // src/cli/run/tool-input-preview.ts
10350
+ function formatToolHeader(toolName, input) {
10351
+ if (toolName === "glob") {
10352
+ const pattern = str2(input.pattern);
10353
+ const root = str2(input.path);
10354
+ return {
10355
+ icon: "\u2731",
10356
+ title: pattern ? `Glob "${pattern}"` : "Glob",
10357
+ description: root ? `in ${root}` : undefined
10358
+ };
10359
+ }
10360
+ if (toolName === "grep") {
10361
+ const pattern = str2(input.pattern);
10362
+ const root = str2(input.path);
10363
+ return {
10364
+ icon: "\u2731",
10365
+ title: pattern ? `Grep "${pattern}"` : "Grep",
10366
+ description: root ? `in ${root}` : undefined
10367
+ };
10368
+ }
10369
+ if (toolName === "list") {
10370
+ const path3 = str2(input.path);
10371
+ return {
10372
+ icon: "\u2192",
10373
+ title: path3 ? `List ${path3}` : "List"
10374
+ };
10375
+ }
10376
+ if (toolName === "read") {
10377
+ const filePath = str2(input.filePath);
10378
+ return {
10379
+ icon: "\u2192",
10380
+ title: filePath ? `Read ${filePath}` : "Read",
10381
+ description: formatKeyValues(input, ["filePath"])
10382
+ };
10383
+ }
10384
+ if (toolName === "write") {
10385
+ const filePath = str2(input.filePath);
10386
+ return {
10387
+ icon: "\u2190",
10388
+ title: filePath ? `Write ${filePath}` : "Write"
10389
+ };
10390
+ }
10391
+ if (toolName === "edit") {
10392
+ const filePath = str2(input.filePath);
10393
+ return {
10394
+ icon: "\u2190",
10395
+ title: filePath ? `Edit ${filePath}` : "Edit",
10396
+ description: formatKeyValues(input, ["filePath", "oldString", "newString"])
10397
+ };
10398
+ }
10399
+ if (toolName === "webfetch") {
10400
+ const url = str2(input.url);
10401
+ return {
10402
+ icon: "%",
10403
+ title: url ? `WebFetch ${url}` : "WebFetch",
10404
+ description: formatKeyValues(input, ["url"])
10405
+ };
10406
+ }
10407
+ if (toolName === "websearch_web_search_exa") {
10408
+ const query = str2(input.query);
10409
+ return {
10410
+ icon: "\u25C8",
10411
+ title: query ? `Web Search "${query}"` : "Web Search"
10412
+ };
10413
+ }
10414
+ if (toolName === "grep_app_searchGitHub") {
10415
+ const query = str2(input.query);
10416
+ return {
10417
+ icon: "\u25C7",
10418
+ title: query ? `Code Search "${query}"` : "Code Search"
10419
+ };
10420
+ }
10421
+ if (toolName === "task") {
10422
+ const desc = str2(input.description);
10423
+ const subagent = str2(input.subagent_type);
10424
+ return {
10425
+ icon: "#",
10426
+ title: desc || (subagent ? `${subagent} Task` : "Task"),
10427
+ description: subagent ? `agent=${subagent}` : undefined
10428
+ };
10429
+ }
10430
+ if (toolName === "bash") {
10431
+ const command = str2(input.command);
10432
+ return {
10433
+ icon: "$",
10434
+ title: command || "bash",
10435
+ description: formatKeyValues(input, ["command"])
10436
+ };
10437
+ }
10438
+ if (toolName === "skill") {
10439
+ const name = str2(input.name);
10440
+ return {
10441
+ icon: "\u2192",
10442
+ title: name ? `Skill "${name}"` : "Skill"
10443
+ };
10444
+ }
10445
+ if (toolName === "todowrite") {
10446
+ return {
10447
+ icon: "#",
10448
+ title: "Todos"
10449
+ };
10450
+ }
10451
+ return {
10452
+ icon: "\u2699",
10453
+ title: toolName,
10454
+ description: formatKeyValues(input, [])
10455
+ };
10456
+ }
10457
+ function formatKeyValues(input, exclude) {
10458
+ const entries = Object.entries(input).filter(([key, value]) => {
10459
+ if (exclude.includes(key))
10460
+ return false;
10461
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
10462
+ });
10463
+ if (!entries.length)
10464
+ return;
10465
+ return entries.map(([key, value]) => `${key}=${String(value)}`).join(" ");
10466
+ }
10467
+ function str2(value) {
10468
+ if (typeof value !== "string")
10469
+ return;
10470
+ const trimmed = value.trim();
10471
+ return trimmed.length ? trimmed : undefined;
10472
+ }
10473
+
10474
+ // src/cli/run/display-chars.ts
10475
+ var isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS);
10476
+ var displayChars = {
10477
+ treeEnd: isCI ? "`-" : "\u2514\u2500",
10478
+ treeIndent: " ",
10479
+ treeJoin: isCI ? " " : " "
10480
+ };
10481
+
10482
+ // src/cli/run/output-renderer.ts
10270
10483
  var import_picocolors6 = __toESM(require_picocolors(), 1);
10484
+ function renderAgentHeader(agent, model, variant, agentColorsByName) {
10485
+ if (!agent && !model)
10486
+ return;
10487
+ const agentLabel = agent ? import_picocolors6.default.bold(colorizeWithProfileColor(agent, agentColorsByName[agent])) : "";
10488
+ const modelBase = model ?? "";
10489
+ const variantSuffix = variant ? ` (${variant})` : "";
10490
+ const modelLabel = model ? import_picocolors6.default.dim(`${modelBase}${variantSuffix}`) : "";
10491
+ process.stdout.write(`
10492
+ `);
10493
+ if (modelLabel) {
10494
+ process.stdout.write(` ${modelLabel}
10495
+ `);
10496
+ }
10497
+ if (agentLabel) {
10498
+ process.stdout.write(` ${import_picocolors6.default.dim("\u2514\u2500")} ${agentLabel}
10499
+ `);
10500
+ }
10501
+ process.stdout.write(`
10502
+ `);
10503
+ }
10504
+ function openThinkBlock() {
10505
+ process.stdout.write(`
10506
+ ${import_picocolors6.default.dim("\u2503 Thinking:")} `);
10507
+ }
10508
+ function closeThinkBlock() {
10509
+ process.stdout.write(`
10510
+
10511
+ `);
10512
+ }
10513
+ function writePaddedText(text, atLineStart) {
10514
+ const isGitHubActions = process.env.GITHUB_ACTIONS === "true";
10515
+ if (isGitHubActions) {
10516
+ return { output: text, atLineStart: text.endsWith(`
10517
+ `) };
10518
+ }
10519
+ let output = "";
10520
+ let lineStart = atLineStart;
10521
+ for (let i2 = 0;i2 < text.length; i2++) {
10522
+ const ch = text[i2];
10523
+ if (lineStart) {
10524
+ output += " ";
10525
+ lineStart = false;
10526
+ }
10527
+ if (ch === `
10528
+ `) {
10529
+ output += `
10530
+ `;
10531
+ lineStart = true;
10532
+ continue;
10533
+ }
10534
+ output += ch;
10535
+ }
10536
+ return { output, atLineStart: lineStart };
10537
+ }
10538
+ function colorizeWithProfileColor(text, hexColor) {
10539
+ if (!hexColor)
10540
+ return import_picocolors6.default.magenta(text);
10541
+ const rgb = parseHexColor(hexColor);
10542
+ if (!rgb)
10543
+ return import_picocolors6.default.magenta(text);
10544
+ const [r2, g2, b3] = rgb;
10545
+ return `\x1B[38;2;${r2};${g2};${b3}m${text}\x1B[39m`;
10546
+ }
10547
+ function parseHexColor(hexColor) {
10548
+ const cleaned = hexColor.trim();
10549
+ const match = cleaned.match(/^#?([A-Fa-f0-9]{6})$/);
10550
+ if (!match)
10551
+ return null;
10552
+ const hex = match[1];
10553
+ const r2 = Number.parseInt(hex.slice(0, 2), 16);
10554
+ const g2 = Number.parseInt(hex.slice(2, 4), 16);
10555
+ const b3 = Number.parseInt(hex.slice(4, 6), 16);
10556
+ return [r2, g2, b3];
10557
+ }
10558
+
10559
+ // src/cli/run/event-handlers.ts
10271
10560
  function getSessionId(props) {
10272
10561
  return props?.sessionID ?? props?.sessionId;
10273
10562
  }
@@ -10277,6 +10566,12 @@ function getInfoSessionId(props) {
10277
10566
  function getPartSessionId(props) {
10278
10567
  return props?.part?.sessionID ?? props?.part?.sessionId;
10279
10568
  }
10569
+ function getPartMessageId(props) {
10570
+ return props?.part?.messageID;
10571
+ }
10572
+ function getDeltaMessageId(props) {
10573
+ return props?.messageID;
10574
+ }
10280
10575
  function handleSessionIdle(ctx, payload, state) {
10281
10576
  if (payload.type !== "session.idle")
10282
10577
  return;
@@ -10306,7 +10601,7 @@ function handleSessionError(ctx, payload, state) {
10306
10601
  if (getSessionId(props) === ctx.sessionID) {
10307
10602
  state.mainSessionError = true;
10308
10603
  state.lastError = serializeError(props?.error);
10309
- console.error(import_picocolors6.default.red(`
10604
+ console.error(import_picocolors7.default.red(`
10310
10605
  [session.error] ${state.lastError}`));
10311
10606
  }
10312
10607
  }
@@ -10318,13 +10613,36 @@ function handleMessagePartUpdated(ctx, payload, state) {
10318
10613
  const infoSid = getInfoSessionId(props);
10319
10614
  if ((partSid ?? infoSid) !== ctx.sessionID)
10320
10615
  return;
10616
+ const role = props?.info?.role;
10617
+ const mappedRole = getPartMessageId(props) ? state.messageRoleById[getPartMessageId(props) ?? ""] : undefined;
10618
+ if ((role ?? mappedRole) === "user")
10619
+ return;
10321
10620
  const part = props?.part;
10322
10621
  if (!part)
10323
10622
  return;
10623
+ if (part.id && part.type) {
10624
+ state.partTypesById[part.id] = part.type;
10625
+ }
10626
+ if (part.type === "reasoning") {
10627
+ ensureThinkBlockOpen(state);
10628
+ const reasoningText = part.text ?? "";
10629
+ const newText = reasoningText.slice(state.lastReasoningText.length);
10630
+ if (newText) {
10631
+ const padded = writePaddedText(newText, state.thinkingAtLineStart);
10632
+ process.stdout.write(import_picocolors7.default.dim(padded.output));
10633
+ state.thinkingAtLineStart = padded.atLineStart;
10634
+ state.hasReceivedMeaningfulWork = true;
10635
+ }
10636
+ state.lastReasoningText = reasoningText;
10637
+ return;
10638
+ }
10639
+ closeThinkBlockIfNeeded(state);
10324
10640
  if (part.type === "text" && part.text) {
10325
10641
  const newText = part.text.slice(state.lastPartText.length);
10326
10642
  if (newText) {
10327
- process.stdout.write(newText);
10643
+ const padded = writePaddedText(newText, state.textAtLineStart);
10644
+ process.stdout.write(padded.output);
10645
+ state.textAtLineStart = padded.atLineStart;
10328
10646
  state.hasReceivedMeaningfulWork = true;
10329
10647
  }
10330
10648
  state.lastPartText = part.text;
@@ -10333,42 +10651,67 @@ function handleMessagePartUpdated(ctx, payload, state) {
10333
10651
  handleToolPart(ctx, part, state);
10334
10652
  }
10335
10653
  }
10654
+ function handleMessagePartDelta(ctx, payload, state) {
10655
+ if (payload.type !== "message.part.delta")
10656
+ return;
10657
+ const props = payload.properties;
10658
+ const sessionID = props?.sessionID ?? props?.sessionId;
10659
+ if (sessionID !== ctx.sessionID)
10660
+ return;
10661
+ const role = getDeltaMessageId(props) ? state.messageRoleById[getDeltaMessageId(props) ?? ""] : undefined;
10662
+ if (role === "user")
10663
+ return;
10664
+ if (props?.field !== "text")
10665
+ return;
10666
+ const partType = props?.partID ? state.partTypesById[props.partID] : undefined;
10667
+ const delta = props.delta ?? "";
10668
+ if (!delta)
10669
+ return;
10670
+ if (partType === "reasoning") {
10671
+ ensureThinkBlockOpen(state);
10672
+ const padded2 = writePaddedText(delta, state.thinkingAtLineStart);
10673
+ process.stdout.write(import_picocolors7.default.dim(padded2.output));
10674
+ state.thinkingAtLineStart = padded2.atLineStart;
10675
+ state.lastReasoningText += delta;
10676
+ state.hasReceivedMeaningfulWork = true;
10677
+ return;
10678
+ }
10679
+ closeThinkBlockIfNeeded(state);
10680
+ const padded = writePaddedText(delta, state.textAtLineStart);
10681
+ process.stdout.write(padded.output);
10682
+ state.textAtLineStart = padded.atLineStart;
10683
+ state.lastPartText += delta;
10684
+ state.hasReceivedMeaningfulWork = true;
10685
+ }
10336
10686
  function handleToolPart(_ctx, part, state) {
10337
10687
  const toolName = part.tool || part.name || "unknown";
10338
10688
  const status = part.state?.status;
10339
10689
  if (status === "running") {
10690
+ if (state.currentTool !== null)
10691
+ return;
10340
10692
  state.currentTool = toolName;
10341
- let inputPreview = "";
10342
- const input = part.state?.input;
10343
- if (input) {
10344
- if (input.command) {
10345
- inputPreview = ` ${import_picocolors6.default.dim(String(input.command).slice(0, 60))}`;
10346
- } else if (input.pattern) {
10347
- inputPreview = ` ${import_picocolors6.default.dim(String(input.pattern).slice(0, 40))}`;
10348
- } else if (input.filePath) {
10349
- inputPreview = ` ${import_picocolors6.default.dim(String(input.filePath))}`;
10350
- } else if (input.query) {
10351
- inputPreview = ` ${import_picocolors6.default.dim(String(input.query).slice(0, 40))}`;
10352
- }
10353
- }
10693
+ const header = formatToolHeader(toolName, part.state?.input ?? {});
10694
+ const suffix = header.description ? ` ${import_picocolors7.default.dim(header.description)}` : "";
10354
10695
  state.hasReceivedMeaningfulWork = true;
10355
10696
  process.stdout.write(`
10356
- ${import_picocolors6.default.cyan(">")} ${import_picocolors6.default.bold(toolName)}${inputPreview}
10697
+ ${import_picocolors7.default.cyan(header.icon)} ${import_picocolors7.default.bold(header.title)}${suffix}
10357
10698
  `);
10358
10699
  }
10359
10700
  if (status === "completed" || status === "error") {
10701
+ if (state.currentTool === null)
10702
+ return;
10360
10703
  const output = part.state?.output || "";
10361
- const maxLen = 200;
10362
- const preview = output.length > maxLen ? output.slice(0, maxLen) + "..." : output;
10363
- if (preview.trim()) {
10364
- const lines = preview.split(`
10365
- `).slice(0, 3);
10366
- process.stdout.write(import_picocolors6.default.dim(` \u2514\u2500 ${lines.join(`
10367
- `)}
10704
+ if (output.trim()) {
10705
+ process.stdout.write(import_picocolors7.default.dim(` ${displayChars.treeEnd} output
10368
10706
  `));
10707
+ const padded = writePaddedText(output, true);
10708
+ process.stdout.write(import_picocolors7.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
10709
+ process.stdout.write(`
10710
+ `);
10369
10711
  }
10370
10712
  state.currentTool = null;
10371
10713
  state.lastPartText = "";
10714
+ state.textAtLineStart = true;
10372
10715
  }
10373
10716
  }
10374
10717
  function handleMessageUpdated(ctx, payload, state) {
@@ -10377,11 +10720,36 @@ function handleMessageUpdated(ctx, payload, state) {
10377
10720
  const props = payload.properties;
10378
10721
  if (getInfoSessionId(props) !== ctx.sessionID)
10379
10722
  return;
10723
+ state.currentMessageRole = props?.info?.role ?? null;
10724
+ const messageID = props?.info?.id ?? null;
10725
+ const role = props?.info?.role;
10726
+ if (messageID && role) {
10727
+ state.messageRoleById[messageID] = role;
10728
+ }
10380
10729
  if (props?.info?.role !== "assistant")
10381
10730
  return;
10382
- state.hasReceivedMeaningfulWork = true;
10383
- state.messageCount++;
10384
- state.lastPartText = "";
10731
+ const isNewMessage = !messageID || messageID !== state.currentMessageId;
10732
+ if (isNewMessage) {
10733
+ state.currentMessageId = messageID;
10734
+ state.hasReceivedMeaningfulWork = true;
10735
+ state.messageCount++;
10736
+ state.lastPartText = "";
10737
+ state.lastReasoningText = "";
10738
+ state.hasPrintedThinkingLine = false;
10739
+ state.lastThinkingSummary = "";
10740
+ state.textAtLineStart = true;
10741
+ state.thinkingAtLineStart = false;
10742
+ closeThinkBlockIfNeeded(state);
10743
+ }
10744
+ const agent = props?.info?.agent ?? null;
10745
+ const model = props?.info?.modelID ?? null;
10746
+ const variant = props?.info?.variant ?? null;
10747
+ if (agent !== state.currentAgent || model !== state.currentModel || variant !== state.currentVariant) {
10748
+ state.currentAgent = agent;
10749
+ state.currentModel = model;
10750
+ state.currentVariant = variant;
10751
+ renderAgentHeader(agent, model, variant, state.agentColorsByName);
10752
+ }
10385
10753
  }
10386
10754
  function handleToolExecute(ctx, payload, state) {
10387
10755
  if (payload.type !== "tool.execute")
@@ -10389,24 +10757,16 @@ function handleToolExecute(ctx, payload, state) {
10389
10757
  const props = payload.properties;
10390
10758
  if (getSessionId(props) !== ctx.sessionID)
10391
10759
  return;
10760
+ closeThinkBlockIfNeeded(state);
10761
+ if (state.currentTool !== null)
10762
+ return;
10392
10763
  const toolName = props?.name || "unknown";
10393
10764
  state.currentTool = toolName;
10394
- let inputPreview = "";
10395
- if (props?.input) {
10396
- const input = props.input;
10397
- if (input.command) {
10398
- inputPreview = ` ${import_picocolors6.default.dim(String(input.command).slice(0, 60))}`;
10399
- } else if (input.pattern) {
10400
- inputPreview = ` ${import_picocolors6.default.dim(String(input.pattern).slice(0, 40))}`;
10401
- } else if (input.filePath) {
10402
- inputPreview = ` ${import_picocolors6.default.dim(String(input.filePath))}`;
10403
- } else if (input.query) {
10404
- inputPreview = ` ${import_picocolors6.default.dim(String(input.query).slice(0, 40))}`;
10405
- }
10406
- }
10765
+ const header = formatToolHeader(toolName, props?.input ?? {});
10766
+ const suffix = header.description ? ` ${import_picocolors7.default.dim(header.description)}` : "";
10407
10767
  state.hasReceivedMeaningfulWork = true;
10408
10768
  process.stdout.write(`
10409
- ${import_picocolors6.default.cyan(">")} ${import_picocolors6.default.bold(toolName)}${inputPreview}
10769
+ ${import_picocolors7.default.cyan(header.icon)} ${import_picocolors7.default.bold(header.title)}${suffix}
10410
10770
  `);
10411
10771
  }
10412
10772
  function handleToolResult(ctx, payload, state) {
@@ -10415,37 +10775,52 @@ function handleToolResult(ctx, payload, state) {
10415
10775
  const props = payload.properties;
10416
10776
  if (getSessionId(props) !== ctx.sessionID)
10417
10777
  return;
10778
+ closeThinkBlockIfNeeded(state);
10779
+ if (state.currentTool === null)
10780
+ return;
10418
10781
  const output = props?.output || "";
10419
- const maxLen = 200;
10420
- const preview = output.length > maxLen ? output.slice(0, maxLen) + "..." : output;
10421
- if (preview.trim()) {
10422
- const lines = preview.split(`
10423
- `).slice(0, 3);
10424
- process.stdout.write(import_picocolors6.default.dim(` \u2514\u2500 ${lines.join(`
10425
- `)}
10782
+ if (output.trim()) {
10783
+ process.stdout.write(import_picocolors7.default.dim(` ${displayChars.treeEnd} output
10426
10784
  `));
10785
+ const padded = writePaddedText(output, true);
10786
+ process.stdout.write(import_picocolors7.default.dim(padded.output + (padded.atLineStart ? "" : " ")));
10787
+ process.stdout.write(`
10788
+ `);
10427
10789
  }
10428
10790
  state.currentTool = null;
10429
10791
  state.lastPartText = "";
10792
+ state.textAtLineStart = true;
10430
10793
  }
10431
10794
  function handleTuiToast(_ctx, payload, state) {
10432
10795
  if (payload.type !== "tui.toast.show")
10433
10796
  return;
10434
10797
  const props = payload.properties;
10435
- const title = props?.title ? `${props.title}: ` : "";
10436
- const message = props?.message?.trim();
10437
10798
  const variant = props?.variant ?? "info";
10438
- if (!message)
10439
- return;
10440
10799
  if (variant === "error") {
10441
- state.mainSessionError = true;
10442
- state.lastError = `${title}${message}`;
10443
- console.error(import_picocolors6.default.red(`
10444
- [tui.toast.error] ${state.lastError}`));
10445
- return;
10800
+ const title = props?.title ? `${props.title}: ` : "";
10801
+ const message = props?.message?.trim();
10802
+ if (message) {
10803
+ state.mainSessionError = true;
10804
+ state.lastError = `${title}${message}`;
10805
+ }
10446
10806
  }
10447
- const colorize = variant === "warning" ? import_picocolors6.default.yellow : import_picocolors6.default.dim;
10448
- console.log(colorize(`[toast:${variant}] ${title}${message}`));
10807
+ }
10808
+ function ensureThinkBlockOpen(state) {
10809
+ if (state.inThinkBlock)
10810
+ return;
10811
+ openThinkBlock();
10812
+ state.inThinkBlock = true;
10813
+ state.hasPrintedThinkingLine = false;
10814
+ state.thinkingAtLineStart = false;
10815
+ }
10816
+ function closeThinkBlockIfNeeded(state) {
10817
+ if (!state.inThinkBlock)
10818
+ return;
10819
+ closeThinkBlock();
10820
+ state.inThinkBlock = false;
10821
+ state.lastThinkingLineWidth = 0;
10822
+ state.lastThinkingSummary = "";
10823
+ state.thinkingAtLineStart = false;
10449
10824
  }
10450
10825
 
10451
10826
  // src/cli/run/event-stream-processor.ts
@@ -10456,20 +10831,25 @@ async function processEvents(ctx, stream, state) {
10456
10831
  try {
10457
10832
  const payload = event;
10458
10833
  if (!payload?.type) {
10459
- console.error(import_picocolors7.default.dim(`[event] no type: ${JSON.stringify(event)}`));
10834
+ if (ctx.verbose) {
10835
+ console.error(import_picocolors8.default.dim(`[event] no type: ${JSON.stringify(event)}`));
10836
+ }
10460
10837
  continue;
10461
10838
  }
10462
- logEventVerbose(ctx, payload);
10839
+ if (ctx.verbose) {
10840
+ logEventVerbose(ctx, payload);
10841
+ }
10463
10842
  handleSessionError(ctx, payload, state);
10464
10843
  handleSessionIdle(ctx, payload, state);
10465
10844
  handleSessionStatus(ctx, payload, state);
10466
10845
  handleMessagePartUpdated(ctx, payload, state);
10846
+ handleMessagePartDelta(ctx, payload, state);
10467
10847
  handleMessageUpdated(ctx, payload, state);
10468
10848
  handleToolExecute(ctx, payload, state);
10469
10849
  handleToolResult(ctx, payload, state);
10470
10850
  handleTuiToast(ctx, payload, state);
10471
10851
  } catch (err) {
10472
- console.error(import_picocolors7.default.red(`[event error] ${err}`));
10852
+ console.error(import_picocolors8.default.red(`[event error] ${err}`));
10473
10853
  }
10474
10854
  }
10475
10855
  }
@@ -11224,14 +11604,14 @@ function promiseAllObject(promisesObj) {
11224
11604
  }
11225
11605
  function randomString(length = 10) {
11226
11606
  const chars = "abcdefghijklmnopqrstuvwxyz";
11227
- let str2 = "";
11607
+ let str3 = "";
11228
11608
  for (let i2 = 0;i2 < length; i2++) {
11229
- str2 += chars[Math.floor(Math.random() * chars.length)];
11609
+ str3 += chars[Math.floor(Math.random() * chars.length)];
11230
11610
  }
11231
- return str2;
11611
+ return str3;
11232
11612
  }
11233
- function esc(str2) {
11234
- return JSON.stringify(str2);
11613
+ function esc(str3) {
11614
+ return JSON.stringify(str3);
11235
11615
  }
11236
11616
  var captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {};
11237
11617
  function isObject2(data) {
@@ -11325,8 +11705,8 @@ var getParsedType = (data) => {
11325
11705
  };
11326
11706
  var propertyKeyTypes = new Set(["string", "number", "symbol"]);
11327
11707
  var primitiveTypes = new Set(["string", "number", "bigint", "boolean", "symbol", "undefined"]);
11328
- function escapeRegex(str2) {
11329
- return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11708
+ function escapeRegex(str3) {
11709
+ return str3.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11330
11710
  }
11331
11711
  function clone(inst, def, params) {
11332
11712
  const cl = new inst._zod.constr(def ?? inst._zod.def);
@@ -20561,10 +20941,10 @@ function _property(property, schema2, params) {
20561
20941
  ...normalizeParams(params)
20562
20942
  });
20563
20943
  }
20564
- function _mime(types2, params) {
20944
+ function _mime(types3, params) {
20565
20945
  return new $ZodCheckMimeType({
20566
20946
  check: "mime_type",
20567
- mime: types2,
20947
+ mime: types3,
20568
20948
  ...normalizeParams(params)
20569
20949
  });
20570
20950
  }
@@ -22474,7 +22854,7 @@ var ZodFile = /* @__PURE__ */ $constructor("ZodFile", (inst, def) => {
22474
22854
  ZodType.init(inst, def);
22475
22855
  inst.min = (size, params) => inst.check(_minSize(size, params));
22476
22856
  inst.max = (size, params) => inst.check(_maxSize(size, params));
22477
- inst.mime = (types2, params) => inst.check(_mime(Array.isArray(types2) ? types2 : [types2], params));
22857
+ inst.mime = (types3, params) => inst.check(_mime(Array.isArray(types3) ? types3 : [types3], params));
22478
22858
  });
22479
22859
  function file(params) {
22480
22860
  return _file(ZodFile, params);
@@ -23040,9 +23420,11 @@ var HookNameSchema = exports_external.enum([
23040
23420
  "claude-code-hooks",
23041
23421
  "auto-slash-command",
23042
23422
  "edit-error-recovery",
23423
+ "json-error-recovery",
23043
23424
  "delegate-task-retry",
23044
23425
  "prometheus-md-only",
23045
23426
  "sisyphus-junior-notepad",
23427
+ "sisyphus-gpt-hephaestus-reminder",
23046
23428
  "start-work",
23047
23429
  "atlas",
23048
23430
  "unstable-agent-babysitter",
@@ -24739,7 +25121,7 @@ async function createOpencode(options) {
24739
25121
 
24740
25122
  // src/cli/run/server-connection.ts
24741
25123
  init_port_utils();
24742
- var import_picocolors8 = __toESM(require_picocolors(), 1);
25124
+ var import_picocolors9 = __toESM(require_picocolors(), 1);
24743
25125
 
24744
25126
  // src/cli/run/opencode-binary-resolver.ts
24745
25127
  import { delimiter, dirname, join as join8 } from "path";
@@ -24831,13 +25213,25 @@ function prependResolvedOpencodeBinToPath(env = process.env, resolve2 = resolveF
24831
25213
  }
24832
25214
 
24833
25215
  // src/cli/run/server-connection.ts
25216
+ function isPortStartFailure(error45, port) {
25217
+ if (!(error45 instanceof Error)) {
25218
+ return false;
25219
+ }
25220
+ return error45.message.includes(`Failed to start server on port ${port}`);
25221
+ }
25222
+ async function startServer(options) {
25223
+ const { signal, port } = options;
25224
+ const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
25225
+ console.log(import_picocolors9.default.dim("Server listening at"), import_picocolors9.default.cyan(server2.url));
25226
+ return { client: client3, cleanup: () => server2.close() };
25227
+ }
24834
25228
  async function createServerConnection(options) {
24835
25229
  prependResolvedOpencodeBinToPath();
24836
25230
  const { port, attach, signal } = options;
24837
25231
  if (attach !== undefined) {
24838
- console.log(import_picocolors8.default.dim("Attaching to existing server at"), import_picocolors8.default.cyan(attach));
24839
- const client4 = createOpencodeClient({ baseUrl: attach });
24840
- return { client: client4, cleanup: () => {} };
25232
+ console.log(import_picocolors9.default.dim("Attaching to existing server at"), import_picocolors9.default.cyan(attach));
25233
+ const client3 = createOpencodeClient({ baseUrl: attach });
25234
+ return { client: client3, cleanup: () => {} };
24841
25235
  }
24842
25236
  if (port !== undefined) {
24843
25237
  if (port < 1 || port > 65535) {
@@ -24845,28 +25239,46 @@ async function createServerConnection(options) {
24845
25239
  }
24846
25240
  const available = await isPortAvailable(port, "127.0.0.1");
24847
25241
  if (available) {
24848
- console.log(import_picocolors8.default.dim("Starting server on port"), import_picocolors8.default.cyan(port.toString()));
24849
- const { client: client5, server: server3 } = await withWorkingOpencodePath(() => createOpencode({ signal, port, hostname: "127.0.0.1" }));
24850
- console.log(import_picocolors8.default.dim("Server listening at"), import_picocolors8.default.cyan(server3.url));
24851
- return { client: client5, cleanup: () => server3.close() };
25242
+ console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(port.toString()));
25243
+ try {
25244
+ return await startServer({ signal, port });
25245
+ } catch (error45) {
25246
+ if (!isPortStartFailure(error45, port)) {
25247
+ throw error45;
25248
+ }
25249
+ const stillAvailable = await isPortAvailable(port, "127.0.0.1");
25250
+ if (stillAvailable) {
25251
+ throw error45;
25252
+ }
25253
+ console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("became occupied, attaching to existing server"));
25254
+ const client4 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
25255
+ return { client: client4, cleanup: () => {} };
25256
+ }
24852
25257
  }
24853
- console.log(import_picocolors8.default.dim("Port"), import_picocolors8.default.cyan(port.toString()), import_picocolors8.default.dim("is occupied, attaching to existing server"));
24854
- const client4 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
24855
- return { client: client4, cleanup: () => {} };
25258
+ console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("is occupied, attaching to existing server"));
25259
+ const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
25260
+ return { client: client3, cleanup: () => {} };
24856
25261
  }
24857
25262
  const { port: selectedPort, wasAutoSelected } = await getAvailableServerPort(DEFAULT_SERVER_PORT, "127.0.0.1");
24858
25263
  if (wasAutoSelected) {
24859
- console.log(import_picocolors8.default.dim("Auto-selected port"), import_picocolors8.default.cyan(selectedPort.toString()));
25264
+ console.log(import_picocolors9.default.dim("Auto-selected port"), import_picocolors9.default.cyan(selectedPort.toString()));
24860
25265
  } else {
24861
- console.log(import_picocolors8.default.dim("Starting server on port"), import_picocolors8.default.cyan(selectedPort.toString()));
25266
+ console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(selectedPort.toString()));
25267
+ }
25268
+ try {
25269
+ return await startServer({ signal, port: selectedPort });
25270
+ } catch (error45) {
25271
+ if (!isPortStartFailure(error45, selectedPort)) {
25272
+ throw error45;
25273
+ }
25274
+ const { port: retryPort } = await getAvailableServerPort(selectedPort + 1, "127.0.0.1");
25275
+ console.log(import_picocolors9.default.dim("Retrying server start on port"), import_picocolors9.default.cyan(retryPort.toString()));
25276
+ return await startServer({ signal, port: retryPort });
24862
25277
  }
24863
- const { client: client3, server: server2 } = await withWorkingOpencodePath(() => createOpencode({ signal, port: selectedPort, hostname: "127.0.0.1" }));
24864
- console.log(import_picocolors8.default.dim("Server listening at"), import_picocolors8.default.cyan(server2.url));
24865
- return { client: client3, cleanup: () => server2.close() };
24866
25278
  }
24867
25279
 
24868
25280
  // src/cli/run/session-resolver.ts
24869
- var import_picocolors9 = __toESM(require_picocolors(), 1);
25281
+ var import_picocolors10 = __toESM(require_picocolors(), 1);
24870
25282
  var SESSION_CREATE_MAX_RETRIES = 3;
24871
25283
  var SESSION_CREATE_RETRY_DELAY_MS = 1000;
24872
25284
  async function resolveSession(options) {
@@ -24892,11 +25304,11 @@ async function resolveSession(options) {
24892
25304
  query: { directory }
24893
25305
  });
24894
25306
  if (res.error) {
24895
- console.error(import_picocolors9.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
24896
- console.error(import_picocolors9.default.dim(` Error: ${serializeError(res.error)}`));
25307
+ console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
25308
+ console.error(import_picocolors10.default.dim(` Error: ${serializeError(res.error)}`));
24897
25309
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
24898
25310
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
24899
- console.log(import_picocolors9.default.dim(` Retrying in ${delay}ms...`));
25311
+ console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
24900
25312
  await new Promise((resolve2) => setTimeout(resolve2, delay));
24901
25313
  }
24902
25314
  continue;
@@ -24904,10 +25316,10 @@ async function resolveSession(options) {
24904
25316
  if (res.data?.id) {
24905
25317
  return res.data.id;
24906
25318
  }
24907
- console.error(import_picocolors9.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
25319
+ console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
24908
25320
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
24909
25321
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
24910
- console.log(import_picocolors9.default.dim(` Retrying in ${delay}ms...`));
25322
+ console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
24911
25323
  await new Promise((resolve2) => setTimeout(resolve2, delay));
24912
25324
  }
24913
25325
  }
@@ -24946,14 +25358,14 @@ function createJsonOutputManager(options = {}) {
24946
25358
  }
24947
25359
 
24948
25360
  // src/cli/run/on-complete-hook.ts
24949
- var import_picocolors10 = __toESM(require_picocolors(), 1);
25361
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
24950
25362
  async function executeOnCompleteHook(options) {
24951
25363
  const { command, sessionId, exitCode, durationMs, messageCount } = options;
24952
25364
  const trimmedCommand = command.trim();
24953
25365
  if (!trimmedCommand) {
24954
25366
  return;
24955
25367
  }
24956
- console.error(import_picocolors10.default.dim(`Running on-complete hook: ${trimmedCommand}`));
25368
+ console.error(import_picocolors11.default.dim(`Running on-complete hook: ${trimmedCommand}`));
24957
25369
  try {
24958
25370
  const proc = Bun.spawn(["sh", "-c", trimmedCommand], {
24959
25371
  env: {
@@ -24968,16 +25380,16 @@ async function executeOnCompleteHook(options) {
24968
25380
  });
24969
25381
  const hookExitCode = await proc.exited;
24970
25382
  if (hookExitCode !== 0) {
24971
- console.error(import_picocolors10.default.yellow(`Warning: on-complete hook exited with code ${hookExitCode}`));
25383
+ console.error(import_picocolors11.default.yellow(`Warning: on-complete hook exited with code ${hookExitCode}`));
24972
25384
  }
24973
25385
  } catch (error45) {
24974
- console.error(import_picocolors10.default.yellow(`Warning: Failed to execute on-complete hook: ${error45 instanceof Error ? error45.message : String(error45)}`));
25386
+ console.error(import_picocolors11.default.yellow(`Warning: Failed to execute on-complete hook: ${error45 instanceof Error ? error45.message : String(error45)}`));
24975
25387
  }
24976
25388
  }
24977
25389
 
24978
25390
  // src/cli/run/agent-resolver.ts
24979
25391
  init_agent_display_names();
24980
- var import_picocolors11 = __toESM(require_picocolors(), 1);
25392
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
24981
25393
  var CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas"];
24982
25394
  var DEFAULT_AGENT = "sisyphus";
24983
25395
  var normalizeAgentName = (agent) => {
@@ -25022,35 +25434,224 @@ var resolveRunAgent = (options, pluginConfig, env = process.env) => {
25022
25434
  const fallbackName = getAgentDisplayName(fallback);
25023
25435
  const fallbackDisabled = isAgentDisabled(fallback, pluginConfig);
25024
25436
  if (fallbackDisabled) {
25025
- console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
25437
+ console.log(import_picocolors12.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
25026
25438
  return fallbackName;
25027
25439
  }
25028
- console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
25440
+ console.log(import_picocolors12.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
25029
25441
  return fallbackName;
25030
25442
  }
25031
25443
  return resolved.resolvedName;
25032
25444
  };
25033
25445
 
25034
25446
  // src/cli/run/poll-for-completion.ts
25035
- var import_picocolors13 = __toESM(require_picocolors(), 1);
25447
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
25036
25448
 
25037
25449
  // src/cli/run/completion.ts
25038
25450
  init_shared();
25039
- var import_picocolors12 = __toESM(require_picocolors(), 1);
25451
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
25452
+ // src/features/boulder-state/constants.ts
25453
+ var BOULDER_DIR = ".sisyphus";
25454
+ var BOULDER_FILE = "boulder.json";
25455
+ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
25456
+ var NOTEPAD_DIR = "notepads";
25457
+ var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
25458
+ // src/features/boulder-state/storage.ts
25459
+ import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync3, readdirSync } from "fs";
25460
+ import { dirname as dirname3, join as join9, basename } from "path";
25461
+ function getBoulderFilePath(directory) {
25462
+ return join9(directory, BOULDER_DIR, BOULDER_FILE);
25463
+ }
25464
+ function readBoulderState(directory) {
25465
+ const filePath = getBoulderFilePath(directory);
25466
+ if (!existsSync11(filePath)) {
25467
+ return null;
25468
+ }
25469
+ try {
25470
+ const content = readFileSync11(filePath, "utf-8");
25471
+ const parsed = JSON.parse(content);
25472
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
25473
+ return null;
25474
+ }
25475
+ if (!Array.isArray(parsed.session_ids)) {
25476
+ parsed.session_ids = [];
25477
+ }
25478
+ return parsed;
25479
+ } catch {
25480
+ return null;
25481
+ }
25482
+ }
25483
+ function getPlanProgress(planPath) {
25484
+ if (!existsSync11(planPath)) {
25485
+ return { total: 0, completed: 0, isComplete: true };
25486
+ }
25487
+ try {
25488
+ const content = readFileSync11(planPath, "utf-8");
25489
+ const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) || [];
25490
+ const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) || [];
25491
+ const total = uncheckedMatches.length + checkedMatches.length;
25492
+ const completed = checkedMatches.length;
25493
+ return {
25494
+ total,
25495
+ completed,
25496
+ isComplete: total === 0 || completed === total
25497
+ };
25498
+ } catch {
25499
+ return { total: 0, completed: 0, isComplete: true };
25500
+ }
25501
+ }
25502
+ // src/features/run-continuation-state/constants.ts
25503
+ var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
25504
+ // src/features/run-continuation-state/storage.ts
25505
+ import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync12, rmSync, writeFileSync as writeFileSync8 } from "fs";
25506
+ import { join as join10 } from "path";
25507
+ function getMarkerPath(directory, sessionID) {
25508
+ return join10(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
25509
+ }
25510
+ function readContinuationMarker(directory, sessionID) {
25511
+ const markerPath = getMarkerPath(directory, sessionID);
25512
+ if (!existsSync12(markerPath))
25513
+ return null;
25514
+ try {
25515
+ const raw = readFileSync12(markerPath, "utf-8");
25516
+ const parsed = JSON.parse(raw);
25517
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
25518
+ return null;
25519
+ return parsed;
25520
+ } catch {
25521
+ return null;
25522
+ }
25523
+ }
25524
+ function isContinuationMarkerActive(marker) {
25525
+ if (!marker)
25526
+ return false;
25527
+ return Object.values(marker.sources).some((entry) => entry?.state === "active");
25528
+ }
25529
+ function getActiveContinuationMarkerReason(marker) {
25530
+ if (!marker)
25531
+ return null;
25532
+ const active = Object.entries(marker.sources).find(([, entry2]) => entry2?.state === "active");
25533
+ if (!active || !active[1])
25534
+ return null;
25535
+ const [source, entry] = active;
25536
+ return entry.reason ?? `${source} continuation is active`;
25537
+ }
25538
+ // src/hooks/ralph-loop/storage.ts
25539
+ init_frontmatter();
25540
+ import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync9, unlinkSync, mkdirSync as mkdirSync5 } from "fs";
25541
+ import { dirname as dirname4, join as join11 } from "path";
25542
+
25543
+ // src/hooks/ralph-loop/constants.ts
25544
+ var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
25545
+ var DEFAULT_MAX_ITERATIONS = 100;
25546
+ var DEFAULT_COMPLETION_PROMISE = "DONE";
25547
+
25548
+ // src/hooks/ralph-loop/storage.ts
25549
+ function getStateFilePath(directory, customPath) {
25550
+ return customPath ? join11(directory, customPath) : join11(directory, DEFAULT_STATE_FILE);
25551
+ }
25552
+ function readState(directory, customPath) {
25553
+ const filePath = getStateFilePath(directory, customPath);
25554
+ if (!existsSync13(filePath)) {
25555
+ return null;
25556
+ }
25557
+ try {
25558
+ const content = readFileSync13(filePath, "utf-8");
25559
+ const { data, body } = parseFrontmatter(content);
25560
+ const active = data.active;
25561
+ const iteration = data.iteration;
25562
+ if (active === undefined || iteration === undefined) {
25563
+ return null;
25564
+ }
25565
+ const isActive = active === true || active === "true";
25566
+ const iterationNum = typeof iteration === "number" ? iteration : Number(iteration);
25567
+ if (isNaN(iterationNum)) {
25568
+ return null;
25569
+ }
25570
+ const stripQuotes = (val) => {
25571
+ const str3 = String(val ?? "");
25572
+ return str3.replace(/^["']|["']$/g, "");
25573
+ };
25574
+ return {
25575
+ active: isActive,
25576
+ iteration: iterationNum,
25577
+ max_iterations: Number(data.max_iterations) || DEFAULT_MAX_ITERATIONS,
25578
+ completion_promise: stripQuotes(data.completion_promise) || DEFAULT_COMPLETION_PROMISE,
25579
+ started_at: stripQuotes(data.started_at) || new Date().toISOString(),
25580
+ prompt: body.trim(),
25581
+ session_id: data.session_id ? stripQuotes(data.session_id) : undefined,
25582
+ ultrawork: data.ultrawork === true || data.ultrawork === "true" ? true : undefined
25583
+ };
25584
+ } catch {
25585
+ return null;
25586
+ }
25587
+ }
25588
+
25589
+ // src/cli/run/continuation-state.ts
25590
+ function getContinuationState(directory, sessionID) {
25591
+ const marker = readContinuationMarker(directory, sessionID);
25592
+ return {
25593
+ hasActiveBoulder: hasActiveBoulderContinuation(directory, sessionID),
25594
+ hasActiveRalphLoop: hasActiveRalphLoopContinuation(directory, sessionID),
25595
+ hasHookMarker: marker !== null,
25596
+ hasTodoHookMarker: marker?.sources.todo !== undefined,
25597
+ hasActiveHookMarker: isContinuationMarkerActive(marker),
25598
+ activeHookMarkerReason: getActiveContinuationMarkerReason(marker)
25599
+ };
25600
+ }
25601
+ function hasActiveBoulderContinuation(directory, sessionID) {
25602
+ const boulder = readBoulderState(directory);
25603
+ if (!boulder)
25604
+ return false;
25605
+ if (!boulder.session_ids.includes(sessionID))
25606
+ return false;
25607
+ const progress = getPlanProgress(boulder.active_plan);
25608
+ return !progress.isComplete;
25609
+ }
25610
+ function hasActiveRalphLoopContinuation(directory, sessionID) {
25611
+ const state = readState(directory);
25612
+ if (!state || !state.active)
25613
+ return false;
25614
+ if (state.session_id && state.session_id !== sessionID) {
25615
+ return false;
25616
+ }
25617
+ return true;
25618
+ }
25619
+
25620
+ // src/cli/run/completion.ts
25040
25621
  async function checkCompletionConditions(ctx) {
25041
25622
  try {
25042
- if (!await areAllTodosComplete(ctx)) {
25623
+ const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
25624
+ if (continuationState.hasActiveHookMarker) {
25625
+ const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
25626
+ console.log(import_picocolors13.default.dim(` Waiting: ${reason}`));
25627
+ return false;
25628
+ }
25629
+ if (!continuationState.hasTodoHookMarker && !await areAllTodosComplete(ctx)) {
25043
25630
  return false;
25044
25631
  }
25045
25632
  if (!await areAllChildrenIdle(ctx)) {
25046
25633
  return false;
25047
25634
  }
25635
+ if (!areContinuationHooksIdle(continuationState)) {
25636
+ return false;
25637
+ }
25048
25638
  return true;
25049
25639
  } catch (err) {
25050
- console.error(import_picocolors12.default.red(`[completion] API error: ${err}`));
25640
+ console.error(import_picocolors13.default.red(`[completion] API error: ${err}`));
25051
25641
  return false;
25052
25642
  }
25053
25643
  }
25644
+ function areContinuationHooksIdle(continuationState) {
25645
+ if (continuationState.hasActiveBoulder) {
25646
+ console.log(import_picocolors13.default.dim(" Waiting: boulder continuation is active"));
25647
+ return false;
25648
+ }
25649
+ if (continuationState.hasActiveRalphLoop) {
25650
+ console.log(import_picocolors13.default.dim(" Waiting: ralph-loop continuation is active"));
25651
+ return false;
25652
+ }
25653
+ return true;
25654
+ }
25054
25655
  async function areAllTodosComplete(ctx) {
25055
25656
  const todosRes = await ctx.client.session.todo({
25056
25657
  path: { id: ctx.sessionID },
@@ -25059,7 +25660,7 @@ async function areAllTodosComplete(ctx) {
25059
25660
  const todos = normalizeSDKResponse(todosRes, []);
25060
25661
  const incompleteTodos = todos.filter((t) => t.status !== "completed" && t.status !== "cancelled");
25061
25662
  if (incompleteTodos.length > 0) {
25062
- console.log(import_picocolors12.default.dim(` Waiting: ${incompleteTodos.length} todos remaining`));
25663
+ console.log(import_picocolors13.default.dim(` Waiting: ${incompleteTodos.length} todos remaining`));
25063
25664
  return false;
25064
25665
  }
25065
25666
  return true;
@@ -25083,7 +25684,7 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
25083
25684
  for (const child of children) {
25084
25685
  const status = allStatuses[child.id];
25085
25686
  if (status && status.type !== "idle") {
25086
- console.log(import_picocolors12.default.dim(` Waiting: session ${child.id.slice(0, 8)}... is ${status.type}`));
25687
+ console.log(import_picocolors13.default.dim(` Waiting: session ${child.id.slice(0, 8)}... is ${status.type}`));
25087
25688
  return false;
25088
25689
  }
25089
25690
  const descendantsIdle = await areAllDescendantsIdle(ctx, child.id, allStatuses);
@@ -25097,9 +25698,9 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
25097
25698
  // src/cli/run/poll-for-completion.ts
25098
25699
  init_shared();
25099
25700
  var DEFAULT_POLL_INTERVAL_MS = 500;
25100
- var DEFAULT_REQUIRED_CONSECUTIVE = 3;
25701
+ var DEFAULT_REQUIRED_CONSECUTIVE = 1;
25101
25702
  var ERROR_GRACE_CYCLES = 3;
25102
- var MIN_STABILIZATION_MS = 1e4;
25703
+ var MIN_STABILIZATION_MS = 0;
25103
25704
  async function pollForCompletion(ctx, eventState, abortController, options = {}) {
25104
25705
  const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
25105
25706
  const requiredConsecutive = options.requiredConsecutive ?? DEFAULT_REQUIRED_CONSECUTIVE;
@@ -25110,13 +25711,16 @@ async function pollForCompletion(ctx, eventState, abortController, options = {})
25110
25711
  const pollStartTimestamp = Date.now();
25111
25712
  while (!abortController.signal.aborted) {
25112
25713
  await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
25714
+ if (abortController.signal.aborted) {
25715
+ return 130;
25716
+ }
25113
25717
  if (eventState.mainSessionError) {
25114
25718
  errorCycleCount++;
25115
25719
  if (errorCycleCount >= ERROR_GRACE_CYCLES) {
25116
- console.error(import_picocolors13.default.red(`
25720
+ console.error(import_picocolors14.default.red(`
25117
25721
 
25118
25722
  Session ended with error: ${eventState.lastError}`));
25119
- console.error(import_picocolors13.default.yellow("Check if todos were completed before the error."));
25723
+ console.error(import_picocolors14.default.yellow("Check if todos were completed before the error."));
25120
25724
  return 1;
25121
25725
  }
25122
25726
  continue;
@@ -25138,6 +25742,10 @@ Session ended with error: ${eventState.lastError}`));
25138
25742
  continue;
25139
25743
  }
25140
25744
  if (!eventState.hasReceivedMeaningfulWork) {
25745
+ if (minStabilizationMs <= 0) {
25746
+ consecutiveCompleteChecks = 0;
25747
+ continue;
25748
+ }
25141
25749
  if (Date.now() - pollStartTimestamp < minStabilizationMs) {
25142
25750
  consecutiveCompleteChecks = 0;
25143
25751
  continue;
@@ -25153,9 +25761,12 @@ Session ended with error: ${eventState.lastError}`));
25153
25761
  }
25154
25762
  const shouldExit = await checkCompletionConditions(ctx);
25155
25763
  if (shouldExit) {
25764
+ if (abortController.signal.aborted) {
25765
+ return 130;
25766
+ }
25156
25767
  consecutiveCompleteChecks++;
25157
25768
  if (consecutiveCompleteChecks >= requiredConsecutive) {
25158
- console.log(import_picocolors13.default.green(`
25769
+ console.log(import_picocolors14.default.green(`
25159
25770
 
25160
25771
  All tasks completed.`));
25161
25772
  return 0;
@@ -25182,25 +25793,40 @@ async function getMainSessionStatus(ctx) {
25182
25793
  }
25183
25794
  }
25184
25795
 
25796
+ // src/cli/run/agent-profile-colors.ts
25797
+ init_shared();
25798
+ async function loadAgentProfileColors(client3) {
25799
+ try {
25800
+ const agentsRes = await client3.app.agents();
25801
+ const agents = normalizeSDKResponse(agentsRes, [], {
25802
+ preferResponseOnMissingData: true
25803
+ });
25804
+ const colors = {};
25805
+ for (const agent of agents) {
25806
+ if (!agent.name || !agent.color)
25807
+ continue;
25808
+ colors[agent.name] = agent.color;
25809
+ }
25810
+ return colors;
25811
+ } catch {
25812
+ return {};
25813
+ }
25814
+ }
25815
+
25185
25816
  // src/cli/run/runner.ts
25186
- var DEFAULT_TIMEOUT_MS = 600000;
25187
25817
  var EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS = 2000;
25188
25818
  async function waitForEventProcessorShutdown(eventProcessor, timeoutMs = EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS) {
25189
25819
  const completed = await Promise.race([
25190
25820
  eventProcessor.then(() => true),
25191
25821
  new Promise((resolve2) => setTimeout(() => resolve2(false), timeoutMs))
25192
25822
  ]);
25193
- if (!completed) {
25194
- console.log(import_picocolors14.default.dim(`[run] Event stream did not close within ${timeoutMs}ms after abort; continuing shutdown.`));
25195
- }
25196
25823
  }
25197
25824
  async function run(options) {
25198
25825
  process.env.OPENCODE_CLI_RUN_MODE = "true";
25199
25826
  const startTime = Date.now();
25200
25827
  const {
25201
25828
  message,
25202
- directory = process.cwd(),
25203
- timeout = DEFAULT_TIMEOUT_MS
25829
+ directory = process.cwd()
25204
25830
  } = options;
25205
25831
  const jsonManager = options.json ? createJsonOutputManager() : null;
25206
25832
  if (jsonManager)
@@ -25208,14 +25834,6 @@ async function run(options) {
25208
25834
  const pluginConfig = loadPluginConfig(directory, { command: "run" });
25209
25835
  const resolvedAgent = resolveRunAgent(options, pluginConfig);
25210
25836
  const abortController = new AbortController;
25211
- let timeoutId = null;
25212
- if (timeout > 0) {
25213
- timeoutId = setTimeout(() => {
25214
- console.log(import_picocolors14.default.yellow(`
25215
- Timeout reached. Aborting...`));
25216
- abortController.abort();
25217
- }, timeout);
25218
- }
25219
25837
  try {
25220
25838
  const { client: client3, cleanup: serverCleanup } = await createServerConnection({
25221
25839
  port: options.port,
@@ -25223,12 +25841,10 @@ Timeout reached. Aborting...`));
25223
25841
  signal: abortController.signal
25224
25842
  });
25225
25843
  const cleanup = () => {
25226
- if (timeoutId)
25227
- clearTimeout(timeoutId);
25228
25844
  serverCleanup();
25229
25845
  };
25230
25846
  process.on("SIGINT", () => {
25231
- console.log(import_picocolors14.default.yellow(`
25847
+ console.log(import_picocolors15.default.yellow(`
25232
25848
  Interrupted. Shutting down...`));
25233
25849
  cleanup();
25234
25850
  process.exit(130);
@@ -25239,13 +25855,18 @@ Interrupted. Shutting down...`));
25239
25855
  sessionId: options.sessionId,
25240
25856
  directory
25241
25857
  });
25242
- console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
25243
- const ctx = { client: client3, sessionID, directory, abortController };
25858
+ console.log(import_picocolors15.default.dim(`Session: ${sessionID}`));
25859
+ const ctx = {
25860
+ client: client3,
25861
+ sessionID,
25862
+ directory,
25863
+ abortController,
25864
+ verbose: options.verbose ?? false
25865
+ };
25244
25866
  const events = await client3.event.subscribe({ query: { directory } });
25245
25867
  const eventState = createEventState();
25868
+ eventState.agentColorsByName = await loadAgentProfileColors(client3);
25246
25869
  const eventProcessor = processEvents(ctx, events.stream, eventState).catch(() => {});
25247
- console.log(import_picocolors14.default.dim(`
25248
- Sending prompt...`));
25249
25870
  await client3.session.promptAsync({
25250
25871
  path: { id: sessionID },
25251
25872
  body: {
@@ -25254,8 +25875,6 @@ Sending prompt...`));
25254
25875
  },
25255
25876
  query: { directory }
25256
25877
  });
25257
- console.log(import_picocolors14.default.dim(`Waiting for completion...
25258
- `));
25259
25878
  const exitCode = await pollForCompletion(ctx, eventState, abortController);
25260
25879
  abortController.abort();
25261
25880
  await waitForEventProcessorShutdown(eventProcessor);
@@ -25285,14 +25904,12 @@ Sending prompt...`));
25285
25904
  throw err;
25286
25905
  }
25287
25906
  } catch (err) {
25288
- if (timeoutId)
25289
- clearTimeout(timeoutId);
25290
25907
  if (jsonManager)
25291
25908
  jsonManager.restore();
25292
25909
  if (err instanceof Error && err.name === "AbortError") {
25293
25910
  return 130;
25294
25911
  }
25295
- console.error(import_picocolors14.default.red(`Error: ${serializeError(err)}`));
25912
+ console.error(import_picocolors15.default.red(`Error: ${serializeError(err)}`));
25296
25913
  return 1;
25297
25914
  }
25298
25915
  }
@@ -25300,53 +25917,53 @@ Sending prompt...`));
25300
25917
  init_checker();
25301
25918
 
25302
25919
  // src/cli/get-local-version/formatter.ts
25303
- var import_picocolors15 = __toESM(require_picocolors(), 1);
25920
+ var import_picocolors16 = __toESM(require_picocolors(), 1);
25304
25921
  var SYMBOLS2 = {
25305
- check: import_picocolors15.default.green("[OK]"),
25306
- cross: import_picocolors15.default.red("[X]"),
25307
- arrow: import_picocolors15.default.cyan("->"),
25308
- info: import_picocolors15.default.blue("[i]"),
25309
- warn: import_picocolors15.default.yellow("[!]"),
25310
- pin: import_picocolors15.default.magenta("[PINNED]"),
25311
- dev: import_picocolors15.default.cyan("[DEV]")
25922
+ check: import_picocolors16.default.green("[OK]"),
25923
+ cross: import_picocolors16.default.red("[X]"),
25924
+ arrow: import_picocolors16.default.cyan("->"),
25925
+ info: import_picocolors16.default.blue("[i]"),
25926
+ warn: import_picocolors16.default.yellow("[!]"),
25927
+ pin: import_picocolors16.default.magenta("[PINNED]"),
25928
+ dev: import_picocolors16.default.cyan("[DEV]")
25312
25929
  };
25313
25930
  function formatVersionOutput(info) {
25314
25931
  const lines = [];
25315
25932
  lines.push("");
25316
- lines.push(import_picocolors15.default.bold(import_picocolors15.default.white("oh-my-opencode Version Information")));
25317
- lines.push(import_picocolors15.default.dim("\u2500".repeat(50)));
25933
+ lines.push(import_picocolors16.default.bold(import_picocolors16.default.white("oh-my-opencode Version Information")));
25934
+ lines.push(import_picocolors16.default.dim("\u2500".repeat(50)));
25318
25935
  lines.push("");
25319
25936
  if (info.currentVersion) {
25320
- lines.push(` Current Version: ${import_picocolors15.default.cyan(info.currentVersion)}`);
25937
+ lines.push(` Current Version: ${import_picocolors16.default.cyan(info.currentVersion)}`);
25321
25938
  } else {
25322
- lines.push(` Current Version: ${import_picocolors15.default.dim("unknown")}`);
25939
+ lines.push(` Current Version: ${import_picocolors16.default.dim("unknown")}`);
25323
25940
  }
25324
25941
  if (!info.isLocalDev && info.latestVersion) {
25325
- lines.push(` Latest Version: ${import_picocolors15.default.cyan(info.latestVersion)}`);
25942
+ lines.push(` Latest Version: ${import_picocolors16.default.cyan(info.latestVersion)}`);
25326
25943
  }
25327
25944
  lines.push("");
25328
25945
  switch (info.status) {
25329
25946
  case "up-to-date":
25330
- lines.push(` ${SYMBOLS2.check} ${import_picocolors15.default.green("You're up to date!")}`);
25947
+ lines.push(` ${SYMBOLS2.check} ${import_picocolors16.default.green("You're up to date!")}`);
25331
25948
  break;
25332
25949
  case "outdated":
25333
- lines.push(` ${SYMBOLS2.warn} ${import_picocolors15.default.yellow("Update available")}`);
25334
- lines.push(` ${import_picocolors15.default.dim("Run:")} ${import_picocolors15.default.cyan("cd ~/.config/opencode && bun update oh-my-opencode")}`);
25950
+ lines.push(` ${SYMBOLS2.warn} ${import_picocolors16.default.yellow("Update available")}`);
25951
+ lines.push(` ${import_picocolors16.default.dim("Run:")} ${import_picocolors16.default.cyan("cd ~/.config/opencode && bun update oh-my-opencode")}`);
25335
25952
  break;
25336
25953
  case "local-dev":
25337
- lines.push(` ${SYMBOLS2.dev} ${import_picocolors15.default.cyan("Running in local development mode")}`);
25338
- lines.push(` ${import_picocolors15.default.dim("Using file:// protocol from config")}`);
25954
+ lines.push(` ${SYMBOLS2.dev} ${import_picocolors16.default.cyan("Running in local development mode")}`);
25955
+ lines.push(` ${import_picocolors16.default.dim("Using file:// protocol from config")}`);
25339
25956
  break;
25340
25957
  case "pinned":
25341
- lines.push(` ${SYMBOLS2.pin} ${import_picocolors15.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
25342
- lines.push(` ${import_picocolors15.default.dim("Update check skipped for pinned versions")}`);
25958
+ lines.push(` ${SYMBOLS2.pin} ${import_picocolors16.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
25959
+ lines.push(` ${import_picocolors16.default.dim("Update check skipped for pinned versions")}`);
25343
25960
  break;
25344
25961
  case "error":
25345
- lines.push(` ${SYMBOLS2.cross} ${import_picocolors15.default.red("Unable to check for updates")}`);
25346
- lines.push(` ${import_picocolors15.default.dim("Network error or npm registry unavailable")}`);
25962
+ lines.push(` ${SYMBOLS2.cross} ${import_picocolors16.default.red("Unable to check for updates")}`);
25963
+ lines.push(` ${import_picocolors16.default.dim("Network error or npm registry unavailable")}`);
25347
25964
  break;
25348
25965
  case "unknown":
25349
- lines.push(` ${SYMBOLS2.info} ${import_picocolors15.default.yellow("Version information unavailable")}`);
25966
+ lines.push(` ${SYMBOLS2.info} ${import_picocolors16.default.yellow("Version information unavailable")}`);
25350
25967
  break;
25351
25968
  }
25352
25969
  lines.push("");
@@ -25446,21 +26063,21 @@ async function getLocalVersion(options = {}) {
25446
26063
  }
25447
26064
  }
25448
26065
  // src/cli/doctor/constants.ts
25449
- var import_picocolors16 = __toESM(require_picocolors(), 1);
26066
+ var import_picocolors17 = __toESM(require_picocolors(), 1);
25450
26067
  var SYMBOLS3 = {
25451
- check: import_picocolors16.default.green("\u2713"),
25452
- cross: import_picocolors16.default.red("\u2717"),
25453
- warn: import_picocolors16.default.yellow("\u26A0"),
25454
- info: import_picocolors16.default.blue("\u2139"),
25455
- arrow: import_picocolors16.default.cyan("\u2192"),
25456
- bullet: import_picocolors16.default.dim("\u2022"),
25457
- skip: import_picocolors16.default.dim("\u25CB")
26068
+ check: import_picocolors17.default.green("\u2713"),
26069
+ cross: import_picocolors17.default.red("\u2717"),
26070
+ warn: import_picocolors17.default.yellow("\u26A0"),
26071
+ info: import_picocolors17.default.blue("\u2139"),
26072
+ arrow: import_picocolors17.default.cyan("\u2192"),
26073
+ bullet: import_picocolors17.default.dim("\u2022"),
26074
+ skip: import_picocolors17.default.dim("\u25CB")
25458
26075
  };
25459
26076
  var STATUS_COLORS = {
25460
- pass: import_picocolors16.default.green,
25461
- fail: import_picocolors16.default.red,
25462
- warn: import_picocolors16.default.yellow,
25463
- skip: import_picocolors16.default.dim
26077
+ pass: import_picocolors17.default.green,
26078
+ fail: import_picocolors17.default.red,
26079
+ warn: import_picocolors17.default.yellow,
26080
+ skip: import_picocolors17.default.dim
25464
26081
  };
25465
26082
  var CHECK_IDS = {
25466
26083
  SYSTEM: "system",
@@ -25483,29 +26100,29 @@ var PACKAGE_NAME4 = "oh-my-opencode";
25483
26100
  var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
25484
26101
 
25485
26102
  // src/cli/doctor/checks/system.ts
25486
- import { existsSync as existsSync19, readFileSync as readFileSync20 } from "fs";
26103
+ import { existsSync as existsSync22, readFileSync as readFileSync23 } from "fs";
25487
26104
 
25488
26105
  // src/cli/doctor/checks/system-binary.ts
25489
- import { existsSync as existsSync16 } from "fs";
26106
+ import { existsSync as existsSync19 } from "fs";
25490
26107
  import { homedir as homedir5 } from "os";
25491
- import { join as join13 } from "path";
26108
+ import { join as join16 } from "path";
25492
26109
  function getDesktopAppPaths(platform) {
25493
26110
  const home = homedir5();
25494
26111
  switch (platform) {
25495
26112
  case "darwin":
25496
26113
  return [
25497
26114
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
25498
- join13(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
26115
+ join16(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
25499
26116
  ];
25500
26117
  case "win32": {
25501
26118
  const programFiles = process.env.ProgramFiles;
25502
26119
  const localAppData = process.env.LOCALAPPDATA;
25503
26120
  const paths = [];
25504
26121
  if (programFiles) {
25505
- paths.push(join13(programFiles, "OpenCode", "OpenCode.exe"));
26122
+ paths.push(join16(programFiles, "OpenCode", "OpenCode.exe"));
25506
26123
  }
25507
26124
  if (localAppData) {
25508
- paths.push(join13(localAppData, "OpenCode", "OpenCode.exe"));
26125
+ paths.push(join16(localAppData, "OpenCode", "OpenCode.exe"));
25509
26126
  }
25510
26127
  return paths;
25511
26128
  }
@@ -25513,8 +26130,8 @@ function getDesktopAppPaths(platform) {
25513
26130
  return [
25514
26131
  "/usr/bin/opencode",
25515
26132
  "/usr/lib/opencode/opencode",
25516
- join13(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
25517
- join13(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
26133
+ join16(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
26134
+ join16(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
25518
26135
  ];
25519
26136
  default:
25520
26137
  return [];
@@ -25526,7 +26143,7 @@ function buildVersionCommand(binaryPath, platform) {
25526
26143
  }
25527
26144
  return [binaryPath, "--version"];
25528
26145
  }
25529
- function findDesktopBinary(platform = process.platform, checkExists = existsSync16) {
26146
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync19) {
25530
26147
  for (const desktopPath of getDesktopAppPaths(platform)) {
25531
26148
  if (checkExists(desktopPath)) {
25532
26149
  return { binary: "opencode", path: desktopPath };
@@ -25573,13 +26190,13 @@ function compareVersions(current, minimum) {
25573
26190
  }
25574
26191
 
25575
26192
  // src/cli/doctor/checks/system-plugin.ts
25576
- import { existsSync as existsSync17, readFileSync as readFileSync18 } from "fs";
26193
+ import { existsSync as existsSync20, readFileSync as readFileSync21 } from "fs";
25577
26194
  init_shared();
25578
26195
  function detectConfigPath() {
25579
26196
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
25580
- if (existsSync17(paths.configJsonc))
26197
+ if (existsSync20(paths.configJsonc))
25581
26198
  return paths.configJsonc;
25582
- if (existsSync17(paths.configJson))
26199
+ if (existsSync20(paths.configJson))
25583
26200
  return paths.configJson;
25584
26201
  return null;
25585
26202
  }
@@ -25615,7 +26232,7 @@ function getPluginInfo() {
25615
26232
  };
25616
26233
  }
25617
26234
  try {
25618
- const content = readFileSync18(configPath, "utf-8");
26235
+ const content = readFileSync21(configPath, "utf-8");
25619
26236
  const parsedConfig = parseJsonc(content);
25620
26237
  const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
25621
26238
  if (!pluginEntry) {
@@ -25652,32 +26269,32 @@ function getPluginInfo() {
25652
26269
  // src/cli/doctor/checks/system-loaded-version.ts
25653
26270
  init_checker();
25654
26271
  init_auto_update_checker();
25655
- import { existsSync as existsSync18, readFileSync as readFileSync19 } from "fs";
26272
+ import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
25656
26273
  import { homedir as homedir6 } from "os";
25657
- import { join as join14 } from "path";
26274
+ import { join as join17 } from "path";
25658
26275
  init_shared();
25659
26276
  function getPlatformDefaultCacheDir(platform = process.platform) {
25660
26277
  if (platform === "darwin")
25661
- return join14(homedir6(), "Library", "Caches");
26278
+ return join17(homedir6(), "Library", "Caches");
25662
26279
  if (platform === "win32")
25663
- return process.env.LOCALAPPDATA ?? join14(homedir6(), "AppData", "Local");
25664
- return join14(homedir6(), ".cache");
26280
+ return process.env.LOCALAPPDATA ?? join17(homedir6(), "AppData", "Local");
26281
+ return join17(homedir6(), ".cache");
25665
26282
  }
25666
26283
  function resolveOpenCodeCacheDir() {
25667
26284
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
25668
26285
  if (xdgCacheHome)
25669
- return join14(xdgCacheHome, "opencode");
26286
+ return join17(xdgCacheHome, "opencode");
25670
26287
  const fromShared = getOpenCodeCacheDir();
25671
- const platformDefault = join14(getPlatformDefaultCacheDir(), "opencode");
25672
- if (existsSync18(fromShared) || !existsSync18(platformDefault))
26288
+ const platformDefault = join17(getPlatformDefaultCacheDir(), "opencode");
26289
+ if (existsSync21(fromShared) || !existsSync21(platformDefault))
25673
26290
  return fromShared;
25674
26291
  return platformDefault;
25675
26292
  }
25676
26293
  function readPackageJson(filePath) {
25677
- if (!existsSync18(filePath))
26294
+ if (!existsSync21(filePath))
25678
26295
  return null;
25679
26296
  try {
25680
- const content = readFileSync19(filePath, "utf-8");
26297
+ const content = readFileSync22(filePath, "utf-8");
25681
26298
  return parseJsonc(content);
25682
26299
  } catch {
25683
26300
  return null;
@@ -25691,8 +26308,8 @@ function normalizeVersion(value) {
25691
26308
  }
25692
26309
  function getLoadedPluginVersion() {
25693
26310
  const cacheDir = resolveOpenCodeCacheDir();
25694
- const cachePackagePath = join14(cacheDir, "package.json");
25695
- const installedPackagePath = join14(cacheDir, "node_modules", PACKAGE_NAME4, "package.json");
26311
+ const cachePackagePath = join17(cacheDir, "package.json");
26312
+ const installedPackagePath = join17(cacheDir, "node_modules", PACKAGE_NAME4, "package.json");
25696
26313
  const cachePackage = readPackageJson(cachePackagePath);
25697
26314
  const installedPackage = readPackageJson(installedPackagePath);
25698
26315
  const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME4]);
@@ -25715,10 +26332,10 @@ init_shared();
25715
26332
  function isConfigValid(configPath) {
25716
26333
  if (!configPath)
25717
26334
  return true;
25718
- if (!existsSync19(configPath))
26335
+ if (!existsSync22(configPath))
25719
26336
  return false;
25720
26337
  try {
25721
- parseJsonc(readFileSync20(configPath, "utf-8"));
26338
+ parseJsonc(readFileSync23(configPath, "utf-8"));
25722
26339
  return true;
25723
26340
  } catch {
25724
26341
  return false;
@@ -25820,28 +26437,28 @@ async function checkSystem() {
25820
26437
  }
25821
26438
 
25822
26439
  // src/cli/doctor/checks/config.ts
25823
- import { readFileSync as readFileSync23 } from "fs";
25824
- import { join as join18 } from "path";
26440
+ import { readFileSync as readFileSync26 } from "fs";
26441
+ import { join as join21 } from "path";
25825
26442
  init_shared();
25826
26443
 
25827
26444
  // src/cli/doctor/checks/model-resolution-cache.ts
25828
26445
  init_shared();
25829
- import { existsSync as existsSync20, readFileSync as readFileSync21 } from "fs";
26446
+ import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
25830
26447
  import { homedir as homedir7 } from "os";
25831
- import { join as join15 } from "path";
26448
+ import { join as join18 } from "path";
25832
26449
  function getOpenCodeCacheDir2() {
25833
26450
  const xdgCache = process.env.XDG_CACHE_HOME;
25834
26451
  if (xdgCache)
25835
- return join15(xdgCache, "opencode");
25836
- return join15(homedir7(), ".cache", "opencode");
26452
+ return join18(xdgCache, "opencode");
26453
+ return join18(homedir7(), ".cache", "opencode");
25837
26454
  }
25838
26455
  function loadAvailableModelsFromCache() {
25839
- const cacheFile = join15(getOpenCodeCacheDir2(), "models.json");
25840
- if (!existsSync20(cacheFile)) {
26456
+ const cacheFile = join18(getOpenCodeCacheDir2(), "models.json");
26457
+ if (!existsSync23(cacheFile)) {
25841
26458
  return { providers: [], modelCount: 0, cacheExists: false };
25842
26459
  }
25843
26460
  try {
25844
- const content = readFileSync21(cacheFile, "utf-8");
26461
+ const content = readFileSync24(cacheFile, "utf-8");
25845
26462
  const data = parseJsonc(content);
25846
26463
  const providers = Object.keys(data);
25847
26464
  let modelCount = 0;
@@ -25862,16 +26479,16 @@ init_model_requirements();
25862
26479
 
25863
26480
  // src/cli/doctor/checks/model-resolution-config.ts
25864
26481
  init_shared();
25865
- import { readFileSync as readFileSync22 } from "fs";
25866
- import { join as join16 } from "path";
26482
+ import { readFileSync as readFileSync25 } from "fs";
26483
+ import { join as join19 } from "path";
25867
26484
  var PACKAGE_NAME5 = "oh-my-opencode";
25868
- var USER_CONFIG_BASE = join16(getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir, PACKAGE_NAME5);
25869
- var PROJECT_CONFIG_BASE = join16(process.cwd(), ".opencode", PACKAGE_NAME5);
26485
+ var USER_CONFIG_BASE = join19(getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir, PACKAGE_NAME5);
26486
+ var PROJECT_CONFIG_BASE = join19(process.cwd(), ".opencode", PACKAGE_NAME5);
25870
26487
  function loadOmoConfig() {
25871
26488
  const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
25872
26489
  if (projectDetected.format !== "none") {
25873
26490
  try {
25874
- const content = readFileSync22(projectDetected.path, "utf-8");
26491
+ const content = readFileSync25(projectDetected.path, "utf-8");
25875
26492
  return parseJsonc(content);
25876
26493
  } catch {
25877
26494
  return null;
@@ -25880,7 +26497,7 @@ function loadOmoConfig() {
25880
26497
  const userDetected = detectConfigFile(USER_CONFIG_BASE);
25881
26498
  if (userDetected.format !== "none") {
25882
26499
  try {
25883
- const content = readFileSync22(userDetected.path, "utf-8");
26500
+ const content = readFileSync25(userDetected.path, "utf-8");
25884
26501
  return parseJsonc(content);
25885
26502
  } catch {
25886
26503
  return null;
@@ -25891,7 +26508,7 @@ function loadOmoConfig() {
25891
26508
 
25892
26509
  // src/cli/doctor/checks/model-resolution-details.ts
25893
26510
  init_shared();
25894
- import { join as join17 } from "path";
26511
+ import { join as join20 } from "path";
25895
26512
 
25896
26513
  // src/cli/doctor/checks/model-resolution-variant.ts
25897
26514
  function formatModelWithVariant(model, variant) {
@@ -25930,7 +26547,7 @@ function getCategoryEffectiveVariant(categoryName, requirement, config2) {
25930
26547
  // src/cli/doctor/checks/model-resolution-details.ts
25931
26548
  function buildModelResolutionDetails(options) {
25932
26549
  const details = [];
25933
- const cacheFile = join17(getOpenCodeCacheDir(), "models.json");
26550
+ const cacheFile = join20(getOpenCodeCacheDir(), "models.json");
25934
26551
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
25935
26552
  details.push("");
25936
26553
  if (options.available.cacheExists) {
@@ -26042,8 +26659,8 @@ async function checkModels() {
26042
26659
  }
26043
26660
 
26044
26661
  // src/cli/doctor/checks/config.ts
26045
- var USER_CONFIG_BASE2 = join18(getOpenCodeConfigDir({ binary: "opencode" }), PACKAGE_NAME4);
26046
- var PROJECT_CONFIG_BASE2 = join18(process.cwd(), ".opencode", PACKAGE_NAME4);
26662
+ var USER_CONFIG_BASE2 = join21(getOpenCodeConfigDir({ binary: "opencode" }), PACKAGE_NAME4);
26663
+ var PROJECT_CONFIG_BASE2 = join21(process.cwd(), ".opencode", PACKAGE_NAME4);
26047
26664
  function findConfigPath() {
26048
26665
  const projectConfig = detectConfigFile(PROJECT_CONFIG_BASE2);
26049
26666
  if (projectConfig.format !== "none")
@@ -26059,7 +26676,7 @@ function validateConfig() {
26059
26676
  return { exists: false, path: null, valid: true, config: null, errors: [] };
26060
26677
  }
26061
26678
  try {
26062
- const content = readFileSync23(configPath, "utf-8");
26679
+ const content = readFileSync26(configPath, "utf-8");
26063
26680
  const rawConfig = parseJsonc(content);
26064
26681
  const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
26065
26682
  if (!schemaResult.success) {
@@ -26162,9 +26779,9 @@ async function checkConfig() {
26162
26779
  }
26163
26780
 
26164
26781
  // src/cli/doctor/checks/dependencies.ts
26165
- import { existsSync as existsSync21 } from "fs";
26782
+ import { existsSync as existsSync24 } from "fs";
26166
26783
  import { createRequire as createRequire2 } from "module";
26167
- import { dirname as dirname5, join as join19 } from "path";
26784
+ import { dirname as dirname7, join as join22 } from "path";
26168
26785
  async function checkBinaryExists(binary2) {
26169
26786
  try {
26170
26787
  const path9 = Bun.which(binary2);
@@ -26220,15 +26837,15 @@ async function checkAstGrepNapi() {
26220
26837
  path: null
26221
26838
  };
26222
26839
  } catch {
26223
- const { existsSync: existsSync22 } = await import("fs");
26224
- const { join: join20 } = await import("path");
26840
+ const { existsSync: existsSync25 } = await import("fs");
26841
+ const { join: join23 } = await import("path");
26225
26842
  const { homedir: homedir8 } = await import("os");
26226
26843
  const pathsToCheck = [
26227
- join20(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
26228
- join20(process.cwd(), "node_modules", "@ast-grep", "napi")
26844
+ join23(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
26845
+ join23(process.cwd(), "node_modules", "@ast-grep", "napi")
26229
26846
  ];
26230
26847
  for (const napiPath of pathsToCheck) {
26231
- if (existsSync22(napiPath)) {
26848
+ if (existsSync25(napiPath)) {
26232
26849
  return {
26233
26850
  name: "AST-Grep NAPI",
26234
26851
  required: false,
@@ -26253,8 +26870,8 @@ function findCommentCheckerPackageBinary() {
26253
26870
  try {
26254
26871
  const require2 = createRequire2(import.meta.url);
26255
26872
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
26256
- const binaryPath = join19(dirname5(pkgPath), "bin", binaryName);
26257
- if (existsSync21(binaryPath))
26873
+ const binaryPath = join22(dirname7(pkgPath), "bin", binaryName);
26874
+ if (existsSync24(binaryPath))
26258
26875
  return binaryPath;
26259
26876
  } catch {}
26260
26877
  return null;
@@ -26372,14 +26989,14 @@ init_jsonc_parser();
26372
26989
 
26373
26990
  // src/tools/lsp/server-installation.ts
26374
26991
  init_shared();
26375
- import { existsSync as existsSync22 } from "fs";
26376
- import { join as join20 } from "path";
26992
+ import { existsSync as existsSync25 } from "fs";
26993
+ import { join as join23 } from "path";
26377
26994
  function isServerInstalled(command) {
26378
26995
  if (command.length === 0)
26379
26996
  return false;
26380
26997
  const cmd = command[0];
26381
26998
  if (cmd.includes("/") || cmd.includes("\\")) {
26382
- if (existsSync22(cmd))
26999
+ if (existsSync25(cmd))
26383
27000
  return true;
26384
27001
  }
26385
27002
  const isWindows = process.platform === "win32";
@@ -26401,23 +27018,23 @@ function isServerInstalled(command) {
26401
27018
  const paths = pathEnv.split(pathSeparator);
26402
27019
  for (const p2 of paths) {
26403
27020
  for (const suffix of exts) {
26404
- if (existsSync22(join20(p2, cmd + suffix))) {
27021
+ if (existsSync25(join23(p2, cmd + suffix))) {
26405
27022
  return true;
26406
27023
  }
26407
27024
  }
26408
27025
  }
26409
27026
  const cwd = process.cwd();
26410
27027
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
26411
- const dataDir = join20(getDataDir(), "opencode");
27028
+ const dataDir = join23(getDataDir(), "opencode");
26412
27029
  const additionalBases = [
26413
- join20(cwd, "node_modules", ".bin"),
26414
- join20(configDir, "bin"),
26415
- join20(configDir, "node_modules", ".bin"),
26416
- join20(dataDir, "bin")
27030
+ join23(cwd, "node_modules", ".bin"),
27031
+ join23(configDir, "bin"),
27032
+ join23(configDir, "node_modules", ".bin"),
27033
+ join23(dataDir, "bin")
26417
27034
  ];
26418
27035
  for (const base of additionalBases) {
26419
27036
  for (const suffix of exts) {
26420
- if (existsSync22(join20(base, cmd + suffix))) {
27037
+ if (existsSync25(join23(base, cmd + suffix))) {
26421
27038
  return true;
26422
27039
  }
26423
27040
  }
@@ -26451,24 +27068,24 @@ function getLspServerStats(servers) {
26451
27068
 
26452
27069
  // src/cli/doctor/checks/tools-mcp.ts
26453
27070
  init_shared();
26454
- import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
27071
+ import { existsSync as existsSync26, readFileSync as readFileSync27 } from "fs";
26455
27072
  import { homedir as homedir8 } from "os";
26456
- import { join as join21 } from "path";
27073
+ import { join as join24 } from "path";
26457
27074
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
26458
27075
  function getMcpConfigPaths() {
26459
27076
  return [
26460
- join21(homedir8(), ".claude", ".mcp.json"),
26461
- join21(process.cwd(), ".mcp.json"),
26462
- join21(process.cwd(), ".claude", ".mcp.json")
27077
+ join24(homedir8(), ".claude", ".mcp.json"),
27078
+ join24(process.cwd(), ".mcp.json"),
27079
+ join24(process.cwd(), ".claude", ".mcp.json")
26463
27080
  ];
26464
27081
  }
26465
27082
  function loadUserMcpConfig() {
26466
27083
  const servers = {};
26467
27084
  for (const configPath of getMcpConfigPaths()) {
26468
- if (!existsSync23(configPath))
27085
+ if (!existsSync26(configPath))
26469
27086
  continue;
26470
27087
  try {
26471
- const content = readFileSync24(configPath, "utf-8");
27088
+ const content = readFileSync27(configPath, "utf-8");
26472
27089
  const config2 = parseJsonc(content);
26473
27090
  if (config2.mcpServers) {
26474
27091
  Object.assign(servers, config2.mcpServers);
@@ -26629,10 +27246,10 @@ function getAllCheckDefinitions() {
26629
27246
  }
26630
27247
 
26631
27248
  // src/cli/doctor/format-default.ts
26632
- var import_picocolors18 = __toESM(require_picocolors(), 1);
27249
+ var import_picocolors19 = __toESM(require_picocolors(), 1);
26633
27250
 
26634
27251
  // src/cli/doctor/format-shared.ts
26635
- var import_picocolors17 = __toESM(require_picocolors(), 1);
27252
+ var import_picocolors18 = __toESM(require_picocolors(), 1);
26636
27253
  function formatStatusSymbol(status) {
26637
27254
  const colorFn = STATUS_COLORS[status];
26638
27255
  switch (status) {
@@ -26647,23 +27264,23 @@ function formatStatusSymbol(status) {
26647
27264
  }
26648
27265
  }
26649
27266
  function formatStatusMark(available) {
26650
- return available ? import_picocolors17.default.green(SYMBOLS3.check) : import_picocolors17.default.red(SYMBOLS3.cross);
27267
+ return available ? import_picocolors18.default.green(SYMBOLS3.check) : import_picocolors18.default.red(SYMBOLS3.cross);
26651
27268
  }
26652
27269
  function formatHeader() {
26653
27270
  return `
26654
- ${import_picocolors17.default.bgMagenta(import_picocolors17.default.white(" oMoMoMoMo Doctor "))}
27271
+ ${import_picocolors18.default.bgMagenta(import_picocolors18.default.white(" oMoMoMoMo Doctor "))}
26655
27272
  `;
26656
27273
  }
26657
27274
  function formatIssue(issue2, index) {
26658
27275
  const lines = [];
26659
- const severityColor = issue2.severity === "error" ? import_picocolors17.default.red : import_picocolors17.default.yellow;
27276
+ const severityColor = issue2.severity === "error" ? import_picocolors18.default.red : import_picocolors18.default.yellow;
26660
27277
  lines.push(`${index}. ${severityColor(issue2.title)}`);
26661
- lines.push(` ${import_picocolors17.default.dim(issue2.description)}`);
27278
+ lines.push(` ${import_picocolors18.default.dim(issue2.description)}`);
26662
27279
  if (issue2.fix) {
26663
- lines.push(` ${import_picocolors17.default.cyan("Fix:")} ${import_picocolors17.default.dim(issue2.fix)}`);
27280
+ lines.push(` ${import_picocolors18.default.cyan("Fix:")} ${import_picocolors18.default.dim(issue2.fix)}`);
26664
27281
  }
26665
27282
  if (issue2.affects && issue2.affects.length > 0) {
26666
- lines.push(` ${import_picocolors17.default.cyan("Affects:")} ${import_picocolors17.default.dim(issue2.affects.join(", "))}`);
27283
+ lines.push(` ${import_picocolors18.default.cyan("Affects:")} ${import_picocolors18.default.dim(issue2.affects.join(", "))}`);
26667
27284
  }
26668
27285
  return lines.join(`
26669
27286
  `);
@@ -26677,12 +27294,12 @@ function formatDefault(result) {
26677
27294
  if (allIssues.length === 0) {
26678
27295
  const opencodeVer = result.systemInfo.opencodeVersion ?? "unknown";
26679
27296
  const pluginVer = result.systemInfo.pluginVersion ?? "unknown";
26680
- lines.push(` ${import_picocolors18.default.green(SYMBOLS3.check)} ${import_picocolors18.default.green(`System OK (opencode ${opencodeVer} \xB7 oh-my-opencode ${pluginVer})`)}`);
27297
+ lines.push(` ${import_picocolors19.default.green(SYMBOLS3.check)} ${import_picocolors19.default.green(`System OK (opencode ${opencodeVer} \xB7 oh-my-opencode ${pluginVer})`)}`);
26681
27298
  } else {
26682
27299
  const issueCount = allIssues.filter((i2) => i2.severity === "error").length;
26683
27300
  const warnCount = allIssues.filter((i2) => i2.severity === "warning").length;
26684
27301
  const totalStr = `${issueCount + warnCount} ${issueCount + warnCount === 1 ? "issue" : "issues"}`;
26685
- lines.push(` ${import_picocolors18.default.yellow(SYMBOLS3.warn)} ${totalStr} found:
27302
+ lines.push(` ${import_picocolors19.default.yellow(SYMBOLS3.warn)} ${totalStr} found:
26686
27303
  `);
26687
27304
  allIssues.forEach((issue2, index) => {
26688
27305
  lines.push(formatIssue(issue2, index + 1));
@@ -26694,7 +27311,7 @@ function formatDefault(result) {
26694
27311
  }
26695
27312
 
26696
27313
  // src/cli/doctor/format-status.ts
26697
- var import_picocolors19 = __toESM(require_picocolors(), 1);
27314
+ var import_picocolors20 = __toESM(require_picocolors(), 1);
26698
27315
  function formatStatus(result) {
26699
27316
  const lines = [];
26700
27317
  lines.push(formatHeader());
@@ -26705,7 +27322,7 @@ function formatStatus(result) {
26705
27322
  const bunVer = systemInfo.bunVersion ?? "unknown";
26706
27323
  lines.push(` ${padding}System ${opencodeVer} \xB7 ${pluginVer} \xB7 Bun ${bunVer}`);
26707
27324
  const configPath = systemInfo.configPath ?? "unknown";
26708
- const configStatus = systemInfo.configValid ? import_picocolors19.default.green("(valid)") : import_picocolors19.default.red("(invalid)");
27325
+ const configStatus = systemInfo.configValid ? import_picocolors20.default.green("(valid)") : import_picocolors20.default.red("(invalid)");
26709
27326
  lines.push(` ${padding}Config ${configPath} ${configStatus}`);
26710
27327
  const lspText = `LSP ${tools.lspInstalled}/${tools.lspTotal}`;
26711
27328
  const astGrepMark = formatStatusMark(tools.astGrepCli);
@@ -26722,13 +27339,13 @@ function formatStatus(result) {
26722
27339
  }
26723
27340
 
26724
27341
  // src/cli/doctor/format-verbose.ts
26725
- var import_picocolors20 = __toESM(require_picocolors(), 1);
27342
+ var import_picocolors21 = __toESM(require_picocolors(), 1);
26726
27343
  function formatVerbose(result) {
26727
27344
  const lines = [];
26728
27345
  lines.push(formatHeader());
26729
27346
  const { systemInfo, tools, results, summary } = result;
26730
- lines.push(`${import_picocolors20.default.bold("System Information")}`);
26731
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
27347
+ lines.push(`${import_picocolors21.default.bold("System Information")}`);
27348
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
26732
27349
  lines.push(` ${formatStatusSymbol("pass")} opencode ${systemInfo.opencodeVersion ?? "unknown"}`);
26733
27350
  lines.push(` ${formatStatusSymbol("pass")} oh-my-opencode ${systemInfo.pluginVersion ?? "unknown"}`);
26734
27351
  if (systemInfo.loadedVersion) {
@@ -26739,33 +27356,33 @@ function formatVerbose(result) {
26739
27356
  }
26740
27357
  lines.push(` ${formatStatusSymbol("pass")} path ${systemInfo.opencodePath ?? "unknown"}`);
26741
27358
  if (systemInfo.isLocalDev) {
26742
- lines.push(` ${import_picocolors20.default.yellow("*")} ${import_picocolors20.default.dim("(local development mode)")}`);
27359
+ lines.push(` ${import_picocolors21.default.yellow("*")} ${import_picocolors21.default.dim("(local development mode)")}`);
26743
27360
  }
26744
27361
  lines.push("");
26745
- lines.push(`${import_picocolors20.default.bold("Configuration")}`);
26746
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
26747
- const configStatus = systemInfo.configValid ? import_picocolors20.default.green("valid") : import_picocolors20.default.red("invalid");
27362
+ lines.push(`${import_picocolors21.default.bold("Configuration")}`);
27363
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
27364
+ const configStatus = systemInfo.configValid ? import_picocolors21.default.green("valid") : import_picocolors21.default.red("invalid");
26748
27365
  lines.push(` ${formatStatusSymbol(systemInfo.configValid ? "pass" : "fail")} ${systemInfo.configPath ?? "unknown"} (${configStatus})`);
26749
27366
  lines.push("");
26750
- lines.push(`${import_picocolors20.default.bold("Tools")}`);
26751
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
27367
+ lines.push(`${import_picocolors21.default.bold("Tools")}`);
27368
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
26752
27369
  lines.push(` ${formatStatusSymbol("pass")} LSP ${tools.lspInstalled}/${tools.lspTotal} installed`);
26753
27370
  lines.push(` ${formatStatusSymbol(tools.astGrepCli ? "pass" : "fail")} ast-grep CLI ${tools.astGrepCli ? "installed" : "not found"}`);
26754
27371
  lines.push(` ${formatStatusSymbol(tools.astGrepNapi ? "pass" : "fail")} ast-grep napi ${tools.astGrepNapi ? "installed" : "not found"}`);
26755
27372
  lines.push(` ${formatStatusSymbol(tools.commentChecker ? "pass" : "fail")} comment-checker ${tools.commentChecker ? "installed" : "not found"}`);
26756
27373
  lines.push(` ${formatStatusSymbol(tools.ghCli.installed && tools.ghCli.authenticated ? "pass" : "fail")} gh CLI ${tools.ghCli.installed ? "installed" : "not found"}${tools.ghCli.authenticated && tools.ghCli.username ? ` (${tools.ghCli.username})` : ""}`);
26757
27374
  lines.push("");
26758
- lines.push(`${import_picocolors20.default.bold("MCPs")}`);
26759
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
27375
+ lines.push(`${import_picocolors21.default.bold("MCPs")}`);
27376
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
26760
27377
  if (tools.mcpBuiltin.length === 0) {
26761
- lines.push(` ${import_picocolors20.default.dim("No built-in MCPs")}`);
27378
+ lines.push(` ${import_picocolors21.default.dim("No built-in MCPs")}`);
26762
27379
  } else {
26763
27380
  for (const mcp of tools.mcpBuiltin) {
26764
27381
  lines.push(` ${formatStatusSymbol("pass")} ${mcp}`);
26765
27382
  }
26766
27383
  }
26767
27384
  if (tools.mcpUser.length > 0) {
26768
- lines.push(` ${import_picocolors20.default.cyan("+")} ${tools.mcpUser.length} user MCP(s):`);
27385
+ lines.push(` ${import_picocolors21.default.cyan("+")} ${tools.mcpUser.length} user MCP(s):`);
26769
27386
  for (const mcp of tools.mcpUser) {
26770
27387
  lines.push(` ${formatStatusSymbol("pass")} ${mcp}`);
26771
27388
  }
@@ -26773,20 +27390,20 @@ function formatVerbose(result) {
26773
27390
  lines.push("");
26774
27391
  const allIssues = results.flatMap((r2) => r2.issues);
26775
27392
  if (allIssues.length > 0) {
26776
- lines.push(`${import_picocolors20.default.bold("Issues")}`);
26777
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
27393
+ lines.push(`${import_picocolors21.default.bold("Issues")}`);
27394
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
26778
27395
  allIssues.forEach((issue2, index) => {
26779
27396
  lines.push(formatIssue(issue2, index + 1));
26780
27397
  lines.push("");
26781
27398
  });
26782
27399
  }
26783
- lines.push(`${import_picocolors20.default.bold("Summary")}`);
26784
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
26785
- const passText = summary.passed > 0 ? import_picocolors20.default.green(`${summary.passed} passed`) : `${summary.passed} passed`;
26786
- const failText = summary.failed > 0 ? import_picocolors20.default.red(`${summary.failed} failed`) : `${summary.failed} failed`;
26787
- const warnText = summary.warnings > 0 ? import_picocolors20.default.yellow(`${summary.warnings} warnings`) : `${summary.warnings} warnings`;
27400
+ lines.push(`${import_picocolors21.default.bold("Summary")}`);
27401
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
27402
+ const passText = summary.passed > 0 ? import_picocolors21.default.green(`${summary.passed} passed`) : `${summary.passed} passed`;
27403
+ const failText = summary.failed > 0 ? import_picocolors21.default.red(`${summary.failed} failed`) : `${summary.failed} failed`;
27404
+ const warnText = summary.warnings > 0 ? import_picocolors21.default.yellow(`${summary.warnings} warnings`) : `${summary.warnings} warnings`;
26788
27405
  lines.push(` ${passText}, ${failText}, ${warnText}`);
26789
- lines.push(` ${import_picocolors20.default.dim(`Total: ${summary.total} checks in ${summary.duration}ms`)}`);
27406
+ lines.push(` ${import_picocolors21.default.dim(`Total: ${summary.total} checks in ${summary.duration}ms`)}`);
26790
27407
  return lines.join(`
26791
27408
  `);
26792
27409
  }
@@ -26870,11 +27487,11 @@ async function doctor(options = { mode: "default" }) {
26870
27487
 
26871
27488
  // src/features/mcp-oauth/storage.ts
26872
27489
  init_shared();
26873
- import { chmodSync, existsSync as existsSync24, mkdirSync as mkdirSync3, readFileSync as readFileSync25, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
26874
- import { dirname as dirname6, join as join22 } from "path";
27490
+ import { chmodSync, existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as readFileSync28, unlinkSync as unlinkSync2, writeFileSync as writeFileSync12 } from "fs";
27491
+ import { dirname as dirname8, join as join25 } from "path";
26875
27492
  var STORAGE_FILE_NAME = "mcp-oauth.json";
26876
27493
  function getMcpOauthStoragePath() {
26877
- return join22(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
27494
+ return join25(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
26878
27495
  }
26879
27496
  function normalizeHost(serverHost) {
26880
27497
  let host = serverHost.trim();
@@ -26911,11 +27528,11 @@ function buildKey(serverHost, resource) {
26911
27528
  }
26912
27529
  function readStore() {
26913
27530
  const filePath = getMcpOauthStoragePath();
26914
- if (!existsSync24(filePath)) {
27531
+ if (!existsSync27(filePath)) {
26915
27532
  return null;
26916
27533
  }
26917
27534
  try {
26918
- const content = readFileSync25(filePath, "utf-8");
27535
+ const content = readFileSync28(filePath, "utf-8");
26919
27536
  return JSON.parse(content);
26920
27537
  } catch {
26921
27538
  return null;
@@ -26924,11 +27541,11 @@ function readStore() {
26924
27541
  function writeStore(store) {
26925
27542
  const filePath = getMcpOauthStoragePath();
26926
27543
  try {
26927
- const dir = dirname6(filePath);
26928
- if (!existsSync24(dir)) {
26929
- mkdirSync3(dir, { recursive: true });
27544
+ const dir = dirname8(filePath);
27545
+ if (!existsSync27(dir)) {
27546
+ mkdirSync6(dir, { recursive: true });
26930
27547
  }
26931
- writeFileSync9(filePath, JSON.stringify(store, null, 2), { encoding: "utf-8", mode: 384 });
27548
+ writeFileSync12(filePath, JSON.stringify(store, null, 2), { encoding: "utf-8", mode: 384 });
26932
27549
  chmodSync(filePath, 384);
26933
27550
  return true;
26934
27551
  } catch {
@@ -26960,8 +27577,8 @@ function deleteToken(serverHost, resource) {
26960
27577
  if (Object.keys(store).length === 0) {
26961
27578
  try {
26962
27579
  const filePath = getMcpOauthStoragePath();
26963
- if (existsSync24(filePath)) {
26964
- unlinkSync(filePath);
27580
+ if (existsSync27(filePath)) {
27581
+ unlinkSync2(filePath);
26965
27582
  }
26966
27583
  return true;
26967
27584
  } catch {
@@ -27132,30 +27749,11 @@ function isRecord2(value) {
27132
27749
  }
27133
27750
 
27134
27751
  // src/features/mcp-oauth/callback-server.ts
27752
+ init_port_utils();
27135
27753
  var DEFAULT_PORT = 19877;
27136
- var MAX_PORT_ATTEMPTS2 = 20;
27137
27754
  var TIMEOUT_MS = 5 * 60 * 1000;
27138
- async function isPortAvailable2(port) {
27139
- try {
27140
- const server2 = Bun.serve({
27141
- port,
27142
- hostname: "127.0.0.1",
27143
- fetch: () => new Response
27144
- });
27145
- server2.stop(true);
27146
- return true;
27147
- } catch {
27148
- return false;
27149
- }
27150
- }
27151
27755
  async function findAvailablePort2(startPort = DEFAULT_PORT) {
27152
- for (let attempt = 0;attempt < MAX_PORT_ATTEMPTS2; attempt++) {
27153
- const port = startPort + attempt;
27154
- if (await isPortAvailable2(port)) {
27155
- return port;
27156
- }
27157
- }
27158
- throw new Error(`No available port found in range ${startPort}-${startPort + MAX_PORT_ATTEMPTS2 - 1}`);
27756
+ return findAvailablePort(startPort);
27159
27757
  }
27160
27758
 
27161
27759
  // src/features/mcp-oauth/oauth-authorization-flow.ts
@@ -27542,11 +28140,10 @@ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi):
27542
28140
  const exitCode = await install(args);
27543
28141
  process.exit(exitCode);
27544
28142
  });
27545
- program2.command("run <message>").allowUnknownOption().passThroughOptions().description("Run opencode with todo/background task completion enforcement").option("-a, --agent <name>", "Agent to use (default: from CLI/env/config, fallback: Sisyphus)").option("-d, --directory <path>", "Working directory").option("-t, --timeout <ms>", "Timeout in milliseconds (default: 30 minutes)", parseInt).option("-p, --port <port>", "Server port (attaches if port already in use)", parseInt).option("--attach <url>", "Attach to existing opencode server URL").option("--on-complete <command>", "Shell command to run after completion").option("--json", "Output structured JSON result to stdout").option("--session-id <id>", "Resume existing session instead of creating new one").addHelpText("after", `
28143
+ program2.command("run <message>").allowUnknownOption().passThroughOptions().description("Run opencode with todo/background task completion enforcement").option("-a, --agent <name>", "Agent to use (default: from CLI/env/config, fallback: Sisyphus)").option("-d, --directory <path>", "Working directory").option("-p, --port <port>", "Server port (attaches if port already in use)", parseInt).option("--attach <url>", "Attach to existing opencode server URL").option("--on-complete <command>", "Shell command to run after completion").option("--json", "Output structured JSON result to stdout").option("--verbose", "Show full event stream (default: messages/tools only)").option("--session-id <id>", "Resume existing session instead of creating new one").addHelpText("after", `
27546
28144
  Examples:
27547
28145
  $ bunx oh-my-opencode run "Fix the bug in index.ts"
27548
28146
  $ bunx oh-my-opencode run --agent Sisyphus "Implement feature X"
27549
- $ bunx oh-my-opencode run --timeout 3600000 "Large refactoring task"
27550
28147
  $ bunx oh-my-opencode run --port 4321 "Fix the bug"
27551
28148
  $ bunx oh-my-opencode run --attach http://127.0.0.1:4321 "Fix the bug"
27552
28149
  $ bunx oh-my-opencode run --json "Fix the bug" | jq .sessionId
@@ -27574,11 +28171,11 @@ Unlike 'opencode run', this command waits until:
27574
28171
  message,
27575
28172
  agent: options.agent,
27576
28173
  directory: options.directory,
27577
- timeout: options.timeout,
27578
28174
  port: options.port,
27579
28175
  attach: options.attach,
27580
28176
  onComplete: options.onComplete,
27581
28177
  json: options.json ?? false,
28178
+ verbose: options.verbose ?? false,
27582
28179
  sessionId: options.sessionId
27583
28180
  };
27584
28181
  const exitCode = await run(runOptions);