oh-my-opencode 3.7.1 → 3.7.2

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.2",
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.2",
9131
+ "oh-my-opencode-darwin-x64": "3.7.2",
9132
+ "oh-my-opencode-linux-arm64": "3.7.2",
9133
+ "oh-my-opencode-linux-arm64-musl": "3.7.2",
9134
+ "oh-my-opencode-linux-x64": "3.7.2",
9135
+ "oh-my-opencode-linux-x64-musl": "3.7.2",
9136
+ "oh-my-opencode-windows-x64": "3.7.2"
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";
@@ -24835,7 +25217,7 @@ async function createServerConnection(options) {
24835
25217
  prependResolvedOpencodeBinToPath();
24836
25218
  const { port, attach, signal } = options;
24837
25219
  if (attach !== undefined) {
24838
- console.log(import_picocolors8.default.dim("Attaching to existing server at"), import_picocolors8.default.cyan(attach));
25220
+ console.log(import_picocolors9.default.dim("Attaching to existing server at"), import_picocolors9.default.cyan(attach));
24839
25221
  const client4 = createOpencodeClient({ baseUrl: attach });
24840
25222
  return { client: client4, cleanup: () => {} };
24841
25223
  }
@@ -24845,28 +25227,28 @@ async function createServerConnection(options) {
24845
25227
  }
24846
25228
  const available = await isPortAvailable(port, "127.0.0.1");
24847
25229
  if (available) {
24848
- console.log(import_picocolors8.default.dim("Starting server on port"), import_picocolors8.default.cyan(port.toString()));
25230
+ console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(port.toString()));
24849
25231
  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));
25232
+ console.log(import_picocolors9.default.dim("Server listening at"), import_picocolors9.default.cyan(server3.url));
24851
25233
  return { client: client5, cleanup: () => server3.close() };
24852
25234
  }
24853
- console.log(import_picocolors8.default.dim("Port"), import_picocolors8.default.cyan(port.toString()), import_picocolors8.default.dim("is occupied, attaching to existing server"));
25235
+ console.log(import_picocolors9.default.dim("Port"), import_picocolors9.default.cyan(port.toString()), import_picocolors9.default.dim("is occupied, attaching to existing server"));
24854
25236
  const client4 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
24855
25237
  return { client: client4, cleanup: () => {} };
24856
25238
  }
24857
25239
  const { port: selectedPort, wasAutoSelected } = await getAvailableServerPort(DEFAULT_SERVER_PORT, "127.0.0.1");
24858
25240
  if (wasAutoSelected) {
24859
- console.log(import_picocolors8.default.dim("Auto-selected port"), import_picocolors8.default.cyan(selectedPort.toString()));
25241
+ console.log(import_picocolors9.default.dim("Auto-selected port"), import_picocolors9.default.cyan(selectedPort.toString()));
24860
25242
  } else {
24861
- console.log(import_picocolors8.default.dim("Starting server on port"), import_picocolors8.default.cyan(selectedPort.toString()));
25243
+ console.log(import_picocolors9.default.dim("Starting server on port"), import_picocolors9.default.cyan(selectedPort.toString()));
24862
25244
  }
24863
25245
  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));
25246
+ console.log(import_picocolors9.default.dim("Server listening at"), import_picocolors9.default.cyan(server2.url));
24865
25247
  return { client: client3, cleanup: () => server2.close() };
24866
25248
  }
24867
25249
 
24868
25250
  // src/cli/run/session-resolver.ts
24869
- var import_picocolors9 = __toESM(require_picocolors(), 1);
25251
+ var import_picocolors10 = __toESM(require_picocolors(), 1);
24870
25252
  var SESSION_CREATE_MAX_RETRIES = 3;
24871
25253
  var SESSION_CREATE_RETRY_DELAY_MS = 1000;
24872
25254
  async function resolveSession(options) {
@@ -24892,11 +25274,11 @@ async function resolveSession(options) {
24892
25274
  query: { directory }
24893
25275
  });
24894
25276
  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)}`));
25277
+ console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES} failed:`));
25278
+ console.error(import_picocolors10.default.dim(` Error: ${serializeError(res.error)}`));
24897
25279
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
24898
25280
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
24899
- console.log(import_picocolors9.default.dim(` Retrying in ${delay}ms...`));
25281
+ console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
24900
25282
  await new Promise((resolve2) => setTimeout(resolve2, delay));
24901
25283
  }
24902
25284
  continue;
@@ -24904,10 +25286,10 @@ async function resolveSession(options) {
24904
25286
  if (res.data?.id) {
24905
25287
  return res.data.id;
24906
25288
  }
24907
- console.error(import_picocolors9.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
25289
+ console.error(import_picocolors10.default.yellow(`Session create attempt ${attempt}/${SESSION_CREATE_MAX_RETRIES}: No session ID returned`));
24908
25290
  if (attempt < SESSION_CREATE_MAX_RETRIES) {
24909
25291
  const delay = SESSION_CREATE_RETRY_DELAY_MS * attempt;
24910
- console.log(import_picocolors9.default.dim(` Retrying in ${delay}ms...`));
25292
+ console.log(import_picocolors10.default.dim(` Retrying in ${delay}ms...`));
24911
25293
  await new Promise((resolve2) => setTimeout(resolve2, delay));
24912
25294
  }
24913
25295
  }
@@ -24946,14 +25328,14 @@ function createJsonOutputManager(options = {}) {
24946
25328
  }
24947
25329
 
24948
25330
  // src/cli/run/on-complete-hook.ts
24949
- var import_picocolors10 = __toESM(require_picocolors(), 1);
25331
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
24950
25332
  async function executeOnCompleteHook(options) {
24951
25333
  const { command, sessionId, exitCode, durationMs, messageCount } = options;
24952
25334
  const trimmedCommand = command.trim();
24953
25335
  if (!trimmedCommand) {
24954
25336
  return;
24955
25337
  }
24956
- console.error(import_picocolors10.default.dim(`Running on-complete hook: ${trimmedCommand}`));
25338
+ console.error(import_picocolors11.default.dim(`Running on-complete hook: ${trimmedCommand}`));
24957
25339
  try {
24958
25340
  const proc = Bun.spawn(["sh", "-c", trimmedCommand], {
24959
25341
  env: {
@@ -24968,16 +25350,16 @@ async function executeOnCompleteHook(options) {
24968
25350
  });
24969
25351
  const hookExitCode = await proc.exited;
24970
25352
  if (hookExitCode !== 0) {
24971
- console.error(import_picocolors10.default.yellow(`Warning: on-complete hook exited with code ${hookExitCode}`));
25353
+ console.error(import_picocolors11.default.yellow(`Warning: on-complete hook exited with code ${hookExitCode}`));
24972
25354
  }
24973
25355
  } catch (error45) {
24974
- console.error(import_picocolors10.default.yellow(`Warning: Failed to execute on-complete hook: ${error45 instanceof Error ? error45.message : String(error45)}`));
25356
+ console.error(import_picocolors11.default.yellow(`Warning: Failed to execute on-complete hook: ${error45 instanceof Error ? error45.message : String(error45)}`));
24975
25357
  }
24976
25358
  }
24977
25359
 
24978
25360
  // src/cli/run/agent-resolver.ts
24979
25361
  init_agent_display_names();
24980
- var import_picocolors11 = __toESM(require_picocolors(), 1);
25362
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
24981
25363
  var CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas"];
24982
25364
  var DEFAULT_AGENT = "sisyphus";
24983
25365
  var normalizeAgentName = (agent) => {
@@ -25022,35 +25404,224 @@ var resolveRunAgent = (options, pluginConfig, env = process.env) => {
25022
25404
  const fallbackName = getAgentDisplayName(fallback);
25023
25405
  const fallbackDisabled = isAgentDisabled(fallback, pluginConfig);
25024
25406
  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}".`));
25407
+ console.log(import_picocolors12.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackName}".`));
25026
25408
  return fallbackName;
25027
25409
  }
25028
- console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
25410
+ console.log(import_picocolors12.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackName}".`));
25029
25411
  return fallbackName;
25030
25412
  }
25031
25413
  return resolved.resolvedName;
25032
25414
  };
25033
25415
 
25034
25416
  // src/cli/run/poll-for-completion.ts
25035
- var import_picocolors13 = __toESM(require_picocolors(), 1);
25417
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
25036
25418
 
25037
25419
  // src/cli/run/completion.ts
25038
25420
  init_shared();
25039
- var import_picocolors12 = __toESM(require_picocolors(), 1);
25421
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
25422
+ // src/features/boulder-state/constants.ts
25423
+ var BOULDER_DIR = ".sisyphus";
25424
+ var BOULDER_FILE = "boulder.json";
25425
+ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
25426
+ var NOTEPAD_DIR = "notepads";
25427
+ var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
25428
+ // src/features/boulder-state/storage.ts
25429
+ import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync3, readdirSync } from "fs";
25430
+ import { dirname as dirname3, join as join9, basename } from "path";
25431
+ function getBoulderFilePath(directory) {
25432
+ return join9(directory, BOULDER_DIR, BOULDER_FILE);
25433
+ }
25434
+ function readBoulderState(directory) {
25435
+ const filePath = getBoulderFilePath(directory);
25436
+ if (!existsSync11(filePath)) {
25437
+ return null;
25438
+ }
25439
+ try {
25440
+ const content = readFileSync11(filePath, "utf-8");
25441
+ const parsed = JSON.parse(content);
25442
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
25443
+ return null;
25444
+ }
25445
+ if (!Array.isArray(parsed.session_ids)) {
25446
+ parsed.session_ids = [];
25447
+ }
25448
+ return parsed;
25449
+ } catch {
25450
+ return null;
25451
+ }
25452
+ }
25453
+ function getPlanProgress(planPath) {
25454
+ if (!existsSync11(planPath)) {
25455
+ return { total: 0, completed: 0, isComplete: true };
25456
+ }
25457
+ try {
25458
+ const content = readFileSync11(planPath, "utf-8");
25459
+ const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) || [];
25460
+ const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) || [];
25461
+ const total = uncheckedMatches.length + checkedMatches.length;
25462
+ const completed = checkedMatches.length;
25463
+ return {
25464
+ total,
25465
+ completed,
25466
+ isComplete: total === 0 || completed === total
25467
+ };
25468
+ } catch {
25469
+ return { total: 0, completed: 0, isComplete: true };
25470
+ }
25471
+ }
25472
+ // src/features/run-continuation-state/constants.ts
25473
+ var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
25474
+ // src/features/run-continuation-state/storage.ts
25475
+ import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync12, rmSync, writeFileSync as writeFileSync8 } from "fs";
25476
+ import { join as join10 } from "path";
25477
+ function getMarkerPath(directory, sessionID) {
25478
+ return join10(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
25479
+ }
25480
+ function readContinuationMarker(directory, sessionID) {
25481
+ const markerPath = getMarkerPath(directory, sessionID);
25482
+ if (!existsSync12(markerPath))
25483
+ return null;
25484
+ try {
25485
+ const raw = readFileSync12(markerPath, "utf-8");
25486
+ const parsed = JSON.parse(raw);
25487
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
25488
+ return null;
25489
+ return parsed;
25490
+ } catch {
25491
+ return null;
25492
+ }
25493
+ }
25494
+ function isContinuationMarkerActive(marker) {
25495
+ if (!marker)
25496
+ return false;
25497
+ return Object.values(marker.sources).some((entry) => entry?.state === "active");
25498
+ }
25499
+ function getActiveContinuationMarkerReason(marker) {
25500
+ if (!marker)
25501
+ return null;
25502
+ const active = Object.entries(marker.sources).find(([, entry2]) => entry2?.state === "active");
25503
+ if (!active || !active[1])
25504
+ return null;
25505
+ const [source, entry] = active;
25506
+ return entry.reason ?? `${source} continuation is active`;
25507
+ }
25508
+ // src/hooks/ralph-loop/storage.ts
25509
+ init_frontmatter();
25510
+ import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync9, unlinkSync, mkdirSync as mkdirSync5 } from "fs";
25511
+ import { dirname as dirname4, join as join11 } from "path";
25512
+
25513
+ // src/hooks/ralph-loop/constants.ts
25514
+ var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
25515
+ var DEFAULT_MAX_ITERATIONS = 100;
25516
+ var DEFAULT_COMPLETION_PROMISE = "DONE";
25517
+
25518
+ // src/hooks/ralph-loop/storage.ts
25519
+ function getStateFilePath(directory, customPath) {
25520
+ return customPath ? join11(directory, customPath) : join11(directory, DEFAULT_STATE_FILE);
25521
+ }
25522
+ function readState(directory, customPath) {
25523
+ const filePath = getStateFilePath(directory, customPath);
25524
+ if (!existsSync13(filePath)) {
25525
+ return null;
25526
+ }
25527
+ try {
25528
+ const content = readFileSync13(filePath, "utf-8");
25529
+ const { data, body } = parseFrontmatter(content);
25530
+ const active = data.active;
25531
+ const iteration = data.iteration;
25532
+ if (active === undefined || iteration === undefined) {
25533
+ return null;
25534
+ }
25535
+ const isActive = active === true || active === "true";
25536
+ const iterationNum = typeof iteration === "number" ? iteration : Number(iteration);
25537
+ if (isNaN(iterationNum)) {
25538
+ return null;
25539
+ }
25540
+ const stripQuotes = (val) => {
25541
+ const str3 = String(val ?? "");
25542
+ return str3.replace(/^["']|["']$/g, "");
25543
+ };
25544
+ return {
25545
+ active: isActive,
25546
+ iteration: iterationNum,
25547
+ max_iterations: Number(data.max_iterations) || DEFAULT_MAX_ITERATIONS,
25548
+ completion_promise: stripQuotes(data.completion_promise) || DEFAULT_COMPLETION_PROMISE,
25549
+ started_at: stripQuotes(data.started_at) || new Date().toISOString(),
25550
+ prompt: body.trim(),
25551
+ session_id: data.session_id ? stripQuotes(data.session_id) : undefined,
25552
+ ultrawork: data.ultrawork === true || data.ultrawork === "true" ? true : undefined
25553
+ };
25554
+ } catch {
25555
+ return null;
25556
+ }
25557
+ }
25558
+
25559
+ // src/cli/run/continuation-state.ts
25560
+ function getContinuationState(directory, sessionID) {
25561
+ const marker = readContinuationMarker(directory, sessionID);
25562
+ return {
25563
+ hasActiveBoulder: hasActiveBoulderContinuation(directory, sessionID),
25564
+ hasActiveRalphLoop: hasActiveRalphLoopContinuation(directory, sessionID),
25565
+ hasHookMarker: marker !== null,
25566
+ hasTodoHookMarker: marker?.sources.todo !== undefined,
25567
+ hasActiveHookMarker: isContinuationMarkerActive(marker),
25568
+ activeHookMarkerReason: getActiveContinuationMarkerReason(marker)
25569
+ };
25570
+ }
25571
+ function hasActiveBoulderContinuation(directory, sessionID) {
25572
+ const boulder = readBoulderState(directory);
25573
+ if (!boulder)
25574
+ return false;
25575
+ if (!boulder.session_ids.includes(sessionID))
25576
+ return false;
25577
+ const progress = getPlanProgress(boulder.active_plan);
25578
+ return !progress.isComplete;
25579
+ }
25580
+ function hasActiveRalphLoopContinuation(directory, sessionID) {
25581
+ const state = readState(directory);
25582
+ if (!state || !state.active)
25583
+ return false;
25584
+ if (state.session_id && state.session_id !== sessionID) {
25585
+ return false;
25586
+ }
25587
+ return true;
25588
+ }
25589
+
25590
+ // src/cli/run/completion.ts
25040
25591
  async function checkCompletionConditions(ctx) {
25041
25592
  try {
25042
- if (!await areAllTodosComplete(ctx)) {
25593
+ const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
25594
+ if (continuationState.hasActiveHookMarker) {
25595
+ const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
25596
+ console.log(import_picocolors13.default.dim(` Waiting: ${reason}`));
25597
+ return false;
25598
+ }
25599
+ if (!continuationState.hasTodoHookMarker && !await areAllTodosComplete(ctx)) {
25043
25600
  return false;
25044
25601
  }
25045
25602
  if (!await areAllChildrenIdle(ctx)) {
25046
25603
  return false;
25047
25604
  }
25605
+ if (!areContinuationHooksIdle(continuationState)) {
25606
+ return false;
25607
+ }
25048
25608
  return true;
25049
25609
  } catch (err) {
25050
- console.error(import_picocolors12.default.red(`[completion] API error: ${err}`));
25610
+ console.error(import_picocolors13.default.red(`[completion] API error: ${err}`));
25051
25611
  return false;
25052
25612
  }
25053
25613
  }
25614
+ function areContinuationHooksIdle(continuationState) {
25615
+ if (continuationState.hasActiveBoulder) {
25616
+ console.log(import_picocolors13.default.dim(" Waiting: boulder continuation is active"));
25617
+ return false;
25618
+ }
25619
+ if (continuationState.hasActiveRalphLoop) {
25620
+ console.log(import_picocolors13.default.dim(" Waiting: ralph-loop continuation is active"));
25621
+ return false;
25622
+ }
25623
+ return true;
25624
+ }
25054
25625
  async function areAllTodosComplete(ctx) {
25055
25626
  const todosRes = await ctx.client.session.todo({
25056
25627
  path: { id: ctx.sessionID },
@@ -25059,7 +25630,7 @@ async function areAllTodosComplete(ctx) {
25059
25630
  const todos = normalizeSDKResponse(todosRes, []);
25060
25631
  const incompleteTodos = todos.filter((t) => t.status !== "completed" && t.status !== "cancelled");
25061
25632
  if (incompleteTodos.length > 0) {
25062
- console.log(import_picocolors12.default.dim(` Waiting: ${incompleteTodos.length} todos remaining`));
25633
+ console.log(import_picocolors13.default.dim(` Waiting: ${incompleteTodos.length} todos remaining`));
25063
25634
  return false;
25064
25635
  }
25065
25636
  return true;
@@ -25083,7 +25654,7 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
25083
25654
  for (const child of children) {
25084
25655
  const status = allStatuses[child.id];
25085
25656
  if (status && status.type !== "idle") {
25086
- console.log(import_picocolors12.default.dim(` Waiting: session ${child.id.slice(0, 8)}... is ${status.type}`));
25657
+ console.log(import_picocolors13.default.dim(` Waiting: session ${child.id.slice(0, 8)}... is ${status.type}`));
25087
25658
  return false;
25088
25659
  }
25089
25660
  const descendantsIdle = await areAllDescendantsIdle(ctx, child.id, allStatuses);
@@ -25097,9 +25668,9 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
25097
25668
  // src/cli/run/poll-for-completion.ts
25098
25669
  init_shared();
25099
25670
  var DEFAULT_POLL_INTERVAL_MS = 500;
25100
- var DEFAULT_REQUIRED_CONSECUTIVE = 3;
25671
+ var DEFAULT_REQUIRED_CONSECUTIVE = 1;
25101
25672
  var ERROR_GRACE_CYCLES = 3;
25102
- var MIN_STABILIZATION_MS = 1e4;
25673
+ var MIN_STABILIZATION_MS = 0;
25103
25674
  async function pollForCompletion(ctx, eventState, abortController, options = {}) {
25104
25675
  const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
25105
25676
  const requiredConsecutive = options.requiredConsecutive ?? DEFAULT_REQUIRED_CONSECUTIVE;
@@ -25110,13 +25681,16 @@ async function pollForCompletion(ctx, eventState, abortController, options = {})
25110
25681
  const pollStartTimestamp = Date.now();
25111
25682
  while (!abortController.signal.aborted) {
25112
25683
  await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
25684
+ if (abortController.signal.aborted) {
25685
+ return 130;
25686
+ }
25113
25687
  if (eventState.mainSessionError) {
25114
25688
  errorCycleCount++;
25115
25689
  if (errorCycleCount >= ERROR_GRACE_CYCLES) {
25116
- console.error(import_picocolors13.default.red(`
25690
+ console.error(import_picocolors14.default.red(`
25117
25691
 
25118
25692
  Session ended with error: ${eventState.lastError}`));
25119
- console.error(import_picocolors13.default.yellow("Check if todos were completed before the error."));
25693
+ console.error(import_picocolors14.default.yellow("Check if todos were completed before the error."));
25120
25694
  return 1;
25121
25695
  }
25122
25696
  continue;
@@ -25138,6 +25712,10 @@ Session ended with error: ${eventState.lastError}`));
25138
25712
  continue;
25139
25713
  }
25140
25714
  if (!eventState.hasReceivedMeaningfulWork) {
25715
+ if (minStabilizationMs <= 0) {
25716
+ consecutiveCompleteChecks = 0;
25717
+ continue;
25718
+ }
25141
25719
  if (Date.now() - pollStartTimestamp < minStabilizationMs) {
25142
25720
  consecutiveCompleteChecks = 0;
25143
25721
  continue;
@@ -25153,9 +25731,12 @@ Session ended with error: ${eventState.lastError}`));
25153
25731
  }
25154
25732
  const shouldExit = await checkCompletionConditions(ctx);
25155
25733
  if (shouldExit) {
25734
+ if (abortController.signal.aborted) {
25735
+ return 130;
25736
+ }
25156
25737
  consecutiveCompleteChecks++;
25157
25738
  if (consecutiveCompleteChecks >= requiredConsecutive) {
25158
- console.log(import_picocolors13.default.green(`
25739
+ console.log(import_picocolors14.default.green(`
25159
25740
 
25160
25741
  All tasks completed.`));
25161
25742
  return 0;
@@ -25182,25 +25763,40 @@ async function getMainSessionStatus(ctx) {
25182
25763
  }
25183
25764
  }
25184
25765
 
25766
+ // src/cli/run/agent-profile-colors.ts
25767
+ init_shared();
25768
+ async function loadAgentProfileColors(client3) {
25769
+ try {
25770
+ const agentsRes = await client3.app.agents();
25771
+ const agents = normalizeSDKResponse(agentsRes, [], {
25772
+ preferResponseOnMissingData: true
25773
+ });
25774
+ const colors = {};
25775
+ for (const agent of agents) {
25776
+ if (!agent.name || !agent.color)
25777
+ continue;
25778
+ colors[agent.name] = agent.color;
25779
+ }
25780
+ return colors;
25781
+ } catch {
25782
+ return {};
25783
+ }
25784
+ }
25785
+
25185
25786
  // src/cli/run/runner.ts
25186
- var DEFAULT_TIMEOUT_MS = 600000;
25187
25787
  var EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS = 2000;
25188
25788
  async function waitForEventProcessorShutdown(eventProcessor, timeoutMs = EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS) {
25189
25789
  const completed = await Promise.race([
25190
25790
  eventProcessor.then(() => true),
25191
25791
  new Promise((resolve2) => setTimeout(() => resolve2(false), timeoutMs))
25192
25792
  ]);
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
25793
  }
25197
25794
  async function run(options) {
25198
25795
  process.env.OPENCODE_CLI_RUN_MODE = "true";
25199
25796
  const startTime = Date.now();
25200
25797
  const {
25201
25798
  message,
25202
- directory = process.cwd(),
25203
- timeout = DEFAULT_TIMEOUT_MS
25799
+ directory = process.cwd()
25204
25800
  } = options;
25205
25801
  const jsonManager = options.json ? createJsonOutputManager() : null;
25206
25802
  if (jsonManager)
@@ -25208,14 +25804,6 @@ async function run(options) {
25208
25804
  const pluginConfig = loadPluginConfig(directory, { command: "run" });
25209
25805
  const resolvedAgent = resolveRunAgent(options, pluginConfig);
25210
25806
  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
25807
  try {
25220
25808
  const { client: client3, cleanup: serverCleanup } = await createServerConnection({
25221
25809
  port: options.port,
@@ -25223,12 +25811,10 @@ Timeout reached. Aborting...`));
25223
25811
  signal: abortController.signal
25224
25812
  });
25225
25813
  const cleanup = () => {
25226
- if (timeoutId)
25227
- clearTimeout(timeoutId);
25228
25814
  serverCleanup();
25229
25815
  };
25230
25816
  process.on("SIGINT", () => {
25231
- console.log(import_picocolors14.default.yellow(`
25817
+ console.log(import_picocolors15.default.yellow(`
25232
25818
  Interrupted. Shutting down...`));
25233
25819
  cleanup();
25234
25820
  process.exit(130);
@@ -25239,13 +25825,18 @@ Interrupted. Shutting down...`));
25239
25825
  sessionId: options.sessionId,
25240
25826
  directory
25241
25827
  });
25242
- console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
25243
- const ctx = { client: client3, sessionID, directory, abortController };
25828
+ console.log(import_picocolors15.default.dim(`Session: ${sessionID}`));
25829
+ const ctx = {
25830
+ client: client3,
25831
+ sessionID,
25832
+ directory,
25833
+ abortController,
25834
+ verbose: options.verbose ?? false
25835
+ };
25244
25836
  const events = await client3.event.subscribe({ query: { directory } });
25245
25837
  const eventState = createEventState();
25838
+ eventState.agentColorsByName = await loadAgentProfileColors(client3);
25246
25839
  const eventProcessor = processEvents(ctx, events.stream, eventState).catch(() => {});
25247
- console.log(import_picocolors14.default.dim(`
25248
- Sending prompt...`));
25249
25840
  await client3.session.promptAsync({
25250
25841
  path: { id: sessionID },
25251
25842
  body: {
@@ -25254,8 +25845,6 @@ Sending prompt...`));
25254
25845
  },
25255
25846
  query: { directory }
25256
25847
  });
25257
- console.log(import_picocolors14.default.dim(`Waiting for completion...
25258
- `));
25259
25848
  const exitCode = await pollForCompletion(ctx, eventState, abortController);
25260
25849
  abortController.abort();
25261
25850
  await waitForEventProcessorShutdown(eventProcessor);
@@ -25285,14 +25874,12 @@ Sending prompt...`));
25285
25874
  throw err;
25286
25875
  }
25287
25876
  } catch (err) {
25288
- if (timeoutId)
25289
- clearTimeout(timeoutId);
25290
25877
  if (jsonManager)
25291
25878
  jsonManager.restore();
25292
25879
  if (err instanceof Error && err.name === "AbortError") {
25293
25880
  return 130;
25294
25881
  }
25295
- console.error(import_picocolors14.default.red(`Error: ${serializeError(err)}`));
25882
+ console.error(import_picocolors15.default.red(`Error: ${serializeError(err)}`));
25296
25883
  return 1;
25297
25884
  }
25298
25885
  }
@@ -25300,53 +25887,53 @@ Sending prompt...`));
25300
25887
  init_checker();
25301
25888
 
25302
25889
  // src/cli/get-local-version/formatter.ts
25303
- var import_picocolors15 = __toESM(require_picocolors(), 1);
25890
+ var import_picocolors16 = __toESM(require_picocolors(), 1);
25304
25891
  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]")
25892
+ check: import_picocolors16.default.green("[OK]"),
25893
+ cross: import_picocolors16.default.red("[X]"),
25894
+ arrow: import_picocolors16.default.cyan("->"),
25895
+ info: import_picocolors16.default.blue("[i]"),
25896
+ warn: import_picocolors16.default.yellow("[!]"),
25897
+ pin: import_picocolors16.default.magenta("[PINNED]"),
25898
+ dev: import_picocolors16.default.cyan("[DEV]")
25312
25899
  };
25313
25900
  function formatVersionOutput(info) {
25314
25901
  const lines = [];
25315
25902
  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)));
25903
+ lines.push(import_picocolors16.default.bold(import_picocolors16.default.white("oh-my-opencode Version Information")));
25904
+ lines.push(import_picocolors16.default.dim("\u2500".repeat(50)));
25318
25905
  lines.push("");
25319
25906
  if (info.currentVersion) {
25320
- lines.push(` Current Version: ${import_picocolors15.default.cyan(info.currentVersion)}`);
25907
+ lines.push(` Current Version: ${import_picocolors16.default.cyan(info.currentVersion)}`);
25321
25908
  } else {
25322
- lines.push(` Current Version: ${import_picocolors15.default.dim("unknown")}`);
25909
+ lines.push(` Current Version: ${import_picocolors16.default.dim("unknown")}`);
25323
25910
  }
25324
25911
  if (!info.isLocalDev && info.latestVersion) {
25325
- lines.push(` Latest Version: ${import_picocolors15.default.cyan(info.latestVersion)}`);
25912
+ lines.push(` Latest Version: ${import_picocolors16.default.cyan(info.latestVersion)}`);
25326
25913
  }
25327
25914
  lines.push("");
25328
25915
  switch (info.status) {
25329
25916
  case "up-to-date":
25330
- lines.push(` ${SYMBOLS2.check} ${import_picocolors15.default.green("You're up to date!")}`);
25917
+ lines.push(` ${SYMBOLS2.check} ${import_picocolors16.default.green("You're up to date!")}`);
25331
25918
  break;
25332
25919
  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")}`);
25920
+ lines.push(` ${SYMBOLS2.warn} ${import_picocolors16.default.yellow("Update available")}`);
25921
+ lines.push(` ${import_picocolors16.default.dim("Run:")} ${import_picocolors16.default.cyan("cd ~/.config/opencode && bun update oh-my-opencode")}`);
25335
25922
  break;
25336
25923
  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")}`);
25924
+ lines.push(` ${SYMBOLS2.dev} ${import_picocolors16.default.cyan("Running in local development mode")}`);
25925
+ lines.push(` ${import_picocolors16.default.dim("Using file:// protocol from config")}`);
25339
25926
  break;
25340
25927
  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")}`);
25928
+ lines.push(` ${SYMBOLS2.pin} ${import_picocolors16.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
25929
+ lines.push(` ${import_picocolors16.default.dim("Update check skipped for pinned versions")}`);
25343
25930
  break;
25344
25931
  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")}`);
25932
+ lines.push(` ${SYMBOLS2.cross} ${import_picocolors16.default.red("Unable to check for updates")}`);
25933
+ lines.push(` ${import_picocolors16.default.dim("Network error or npm registry unavailable")}`);
25347
25934
  break;
25348
25935
  case "unknown":
25349
- lines.push(` ${SYMBOLS2.info} ${import_picocolors15.default.yellow("Version information unavailable")}`);
25936
+ lines.push(` ${SYMBOLS2.info} ${import_picocolors16.default.yellow("Version information unavailable")}`);
25350
25937
  break;
25351
25938
  }
25352
25939
  lines.push("");
@@ -25446,21 +26033,21 @@ async function getLocalVersion(options = {}) {
25446
26033
  }
25447
26034
  }
25448
26035
  // src/cli/doctor/constants.ts
25449
- var import_picocolors16 = __toESM(require_picocolors(), 1);
26036
+ var import_picocolors17 = __toESM(require_picocolors(), 1);
25450
26037
  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")
26038
+ check: import_picocolors17.default.green("\u2713"),
26039
+ cross: import_picocolors17.default.red("\u2717"),
26040
+ warn: import_picocolors17.default.yellow("\u26A0"),
26041
+ info: import_picocolors17.default.blue("\u2139"),
26042
+ arrow: import_picocolors17.default.cyan("\u2192"),
26043
+ bullet: import_picocolors17.default.dim("\u2022"),
26044
+ skip: import_picocolors17.default.dim("\u25CB")
25458
26045
  };
25459
26046
  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
26047
+ pass: import_picocolors17.default.green,
26048
+ fail: import_picocolors17.default.red,
26049
+ warn: import_picocolors17.default.yellow,
26050
+ skip: import_picocolors17.default.dim
25464
26051
  };
25465
26052
  var CHECK_IDS = {
25466
26053
  SYSTEM: "system",
@@ -25483,29 +26070,29 @@ var PACKAGE_NAME4 = "oh-my-opencode";
25483
26070
  var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
25484
26071
 
25485
26072
  // src/cli/doctor/checks/system.ts
25486
- import { existsSync as existsSync19, readFileSync as readFileSync20 } from "fs";
26073
+ import { existsSync as existsSync22, readFileSync as readFileSync23 } from "fs";
25487
26074
 
25488
26075
  // src/cli/doctor/checks/system-binary.ts
25489
- import { existsSync as existsSync16 } from "fs";
26076
+ import { existsSync as existsSync19 } from "fs";
25490
26077
  import { homedir as homedir5 } from "os";
25491
- import { join as join13 } from "path";
26078
+ import { join as join16 } from "path";
25492
26079
  function getDesktopAppPaths(platform) {
25493
26080
  const home = homedir5();
25494
26081
  switch (platform) {
25495
26082
  case "darwin":
25496
26083
  return [
25497
26084
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
25498
- join13(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
26085
+ join16(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
25499
26086
  ];
25500
26087
  case "win32": {
25501
26088
  const programFiles = process.env.ProgramFiles;
25502
26089
  const localAppData = process.env.LOCALAPPDATA;
25503
26090
  const paths = [];
25504
26091
  if (programFiles) {
25505
- paths.push(join13(programFiles, "OpenCode", "OpenCode.exe"));
26092
+ paths.push(join16(programFiles, "OpenCode", "OpenCode.exe"));
25506
26093
  }
25507
26094
  if (localAppData) {
25508
- paths.push(join13(localAppData, "OpenCode", "OpenCode.exe"));
26095
+ paths.push(join16(localAppData, "OpenCode", "OpenCode.exe"));
25509
26096
  }
25510
26097
  return paths;
25511
26098
  }
@@ -25513,8 +26100,8 @@ function getDesktopAppPaths(platform) {
25513
26100
  return [
25514
26101
  "/usr/bin/opencode",
25515
26102
  "/usr/lib/opencode/opencode",
25516
- join13(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
25517
- join13(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
26103
+ join16(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
26104
+ join16(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
25518
26105
  ];
25519
26106
  default:
25520
26107
  return [];
@@ -25526,7 +26113,7 @@ function buildVersionCommand(binaryPath, platform) {
25526
26113
  }
25527
26114
  return [binaryPath, "--version"];
25528
26115
  }
25529
- function findDesktopBinary(platform = process.platform, checkExists = existsSync16) {
26116
+ function findDesktopBinary(platform = process.platform, checkExists = existsSync19) {
25530
26117
  for (const desktopPath of getDesktopAppPaths(platform)) {
25531
26118
  if (checkExists(desktopPath)) {
25532
26119
  return { binary: "opencode", path: desktopPath };
@@ -25573,13 +26160,13 @@ function compareVersions(current, minimum) {
25573
26160
  }
25574
26161
 
25575
26162
  // src/cli/doctor/checks/system-plugin.ts
25576
- import { existsSync as existsSync17, readFileSync as readFileSync18 } from "fs";
26163
+ import { existsSync as existsSync20, readFileSync as readFileSync21 } from "fs";
25577
26164
  init_shared();
25578
26165
  function detectConfigPath() {
25579
26166
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
25580
- if (existsSync17(paths.configJsonc))
26167
+ if (existsSync20(paths.configJsonc))
25581
26168
  return paths.configJsonc;
25582
- if (existsSync17(paths.configJson))
26169
+ if (existsSync20(paths.configJson))
25583
26170
  return paths.configJson;
25584
26171
  return null;
25585
26172
  }
@@ -25615,7 +26202,7 @@ function getPluginInfo() {
25615
26202
  };
25616
26203
  }
25617
26204
  try {
25618
- const content = readFileSync18(configPath, "utf-8");
26205
+ const content = readFileSync21(configPath, "utf-8");
25619
26206
  const parsedConfig = parseJsonc(content);
25620
26207
  const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
25621
26208
  if (!pluginEntry) {
@@ -25652,32 +26239,32 @@ function getPluginInfo() {
25652
26239
  // src/cli/doctor/checks/system-loaded-version.ts
25653
26240
  init_checker();
25654
26241
  init_auto_update_checker();
25655
- import { existsSync as existsSync18, readFileSync as readFileSync19 } from "fs";
26242
+ import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
25656
26243
  import { homedir as homedir6 } from "os";
25657
- import { join as join14 } from "path";
26244
+ import { join as join17 } from "path";
25658
26245
  init_shared();
25659
26246
  function getPlatformDefaultCacheDir(platform = process.platform) {
25660
26247
  if (platform === "darwin")
25661
- return join14(homedir6(), "Library", "Caches");
26248
+ return join17(homedir6(), "Library", "Caches");
25662
26249
  if (platform === "win32")
25663
- return process.env.LOCALAPPDATA ?? join14(homedir6(), "AppData", "Local");
25664
- return join14(homedir6(), ".cache");
26250
+ return process.env.LOCALAPPDATA ?? join17(homedir6(), "AppData", "Local");
26251
+ return join17(homedir6(), ".cache");
25665
26252
  }
25666
26253
  function resolveOpenCodeCacheDir() {
25667
26254
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
25668
26255
  if (xdgCacheHome)
25669
- return join14(xdgCacheHome, "opencode");
26256
+ return join17(xdgCacheHome, "opencode");
25670
26257
  const fromShared = getOpenCodeCacheDir();
25671
- const platformDefault = join14(getPlatformDefaultCacheDir(), "opencode");
25672
- if (existsSync18(fromShared) || !existsSync18(platformDefault))
26258
+ const platformDefault = join17(getPlatformDefaultCacheDir(), "opencode");
26259
+ if (existsSync21(fromShared) || !existsSync21(platformDefault))
25673
26260
  return fromShared;
25674
26261
  return platformDefault;
25675
26262
  }
25676
26263
  function readPackageJson(filePath) {
25677
- if (!existsSync18(filePath))
26264
+ if (!existsSync21(filePath))
25678
26265
  return null;
25679
26266
  try {
25680
- const content = readFileSync19(filePath, "utf-8");
26267
+ const content = readFileSync22(filePath, "utf-8");
25681
26268
  return parseJsonc(content);
25682
26269
  } catch {
25683
26270
  return null;
@@ -25691,8 +26278,8 @@ function normalizeVersion(value) {
25691
26278
  }
25692
26279
  function getLoadedPluginVersion() {
25693
26280
  const cacheDir = resolveOpenCodeCacheDir();
25694
- const cachePackagePath = join14(cacheDir, "package.json");
25695
- const installedPackagePath = join14(cacheDir, "node_modules", PACKAGE_NAME4, "package.json");
26281
+ const cachePackagePath = join17(cacheDir, "package.json");
26282
+ const installedPackagePath = join17(cacheDir, "node_modules", PACKAGE_NAME4, "package.json");
25696
26283
  const cachePackage = readPackageJson(cachePackagePath);
25697
26284
  const installedPackage = readPackageJson(installedPackagePath);
25698
26285
  const expectedVersion = normalizeVersion(cachePackage?.dependencies?.[PACKAGE_NAME4]);
@@ -25715,10 +26302,10 @@ init_shared();
25715
26302
  function isConfigValid(configPath) {
25716
26303
  if (!configPath)
25717
26304
  return true;
25718
- if (!existsSync19(configPath))
26305
+ if (!existsSync22(configPath))
25719
26306
  return false;
25720
26307
  try {
25721
- parseJsonc(readFileSync20(configPath, "utf-8"));
26308
+ parseJsonc(readFileSync23(configPath, "utf-8"));
25722
26309
  return true;
25723
26310
  } catch {
25724
26311
  return false;
@@ -25820,28 +26407,28 @@ async function checkSystem() {
25820
26407
  }
25821
26408
 
25822
26409
  // src/cli/doctor/checks/config.ts
25823
- import { readFileSync as readFileSync23 } from "fs";
25824
- import { join as join18 } from "path";
26410
+ import { readFileSync as readFileSync26 } from "fs";
26411
+ import { join as join21 } from "path";
25825
26412
  init_shared();
25826
26413
 
25827
26414
  // src/cli/doctor/checks/model-resolution-cache.ts
25828
26415
  init_shared();
25829
- import { existsSync as existsSync20, readFileSync as readFileSync21 } from "fs";
26416
+ import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
25830
26417
  import { homedir as homedir7 } from "os";
25831
- import { join as join15 } from "path";
26418
+ import { join as join18 } from "path";
25832
26419
  function getOpenCodeCacheDir2() {
25833
26420
  const xdgCache = process.env.XDG_CACHE_HOME;
25834
26421
  if (xdgCache)
25835
- return join15(xdgCache, "opencode");
25836
- return join15(homedir7(), ".cache", "opencode");
26422
+ return join18(xdgCache, "opencode");
26423
+ return join18(homedir7(), ".cache", "opencode");
25837
26424
  }
25838
26425
  function loadAvailableModelsFromCache() {
25839
- const cacheFile = join15(getOpenCodeCacheDir2(), "models.json");
25840
- if (!existsSync20(cacheFile)) {
26426
+ const cacheFile = join18(getOpenCodeCacheDir2(), "models.json");
26427
+ if (!existsSync23(cacheFile)) {
25841
26428
  return { providers: [], modelCount: 0, cacheExists: false };
25842
26429
  }
25843
26430
  try {
25844
- const content = readFileSync21(cacheFile, "utf-8");
26431
+ const content = readFileSync24(cacheFile, "utf-8");
25845
26432
  const data = parseJsonc(content);
25846
26433
  const providers = Object.keys(data);
25847
26434
  let modelCount = 0;
@@ -25862,16 +26449,16 @@ init_model_requirements();
25862
26449
 
25863
26450
  // src/cli/doctor/checks/model-resolution-config.ts
25864
26451
  init_shared();
25865
- import { readFileSync as readFileSync22 } from "fs";
25866
- import { join as join16 } from "path";
26452
+ import { readFileSync as readFileSync25 } from "fs";
26453
+ import { join as join19 } from "path";
25867
26454
  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);
26455
+ var USER_CONFIG_BASE = join19(getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir, PACKAGE_NAME5);
26456
+ var PROJECT_CONFIG_BASE = join19(process.cwd(), ".opencode", PACKAGE_NAME5);
25870
26457
  function loadOmoConfig() {
25871
26458
  const projectDetected = detectConfigFile(PROJECT_CONFIG_BASE);
25872
26459
  if (projectDetected.format !== "none") {
25873
26460
  try {
25874
- const content = readFileSync22(projectDetected.path, "utf-8");
26461
+ const content = readFileSync25(projectDetected.path, "utf-8");
25875
26462
  return parseJsonc(content);
25876
26463
  } catch {
25877
26464
  return null;
@@ -25880,7 +26467,7 @@ function loadOmoConfig() {
25880
26467
  const userDetected = detectConfigFile(USER_CONFIG_BASE);
25881
26468
  if (userDetected.format !== "none") {
25882
26469
  try {
25883
- const content = readFileSync22(userDetected.path, "utf-8");
26470
+ const content = readFileSync25(userDetected.path, "utf-8");
25884
26471
  return parseJsonc(content);
25885
26472
  } catch {
25886
26473
  return null;
@@ -25891,7 +26478,7 @@ function loadOmoConfig() {
25891
26478
 
25892
26479
  // src/cli/doctor/checks/model-resolution-details.ts
25893
26480
  init_shared();
25894
- import { join as join17 } from "path";
26481
+ import { join as join20 } from "path";
25895
26482
 
25896
26483
  // src/cli/doctor/checks/model-resolution-variant.ts
25897
26484
  function formatModelWithVariant(model, variant) {
@@ -25930,7 +26517,7 @@ function getCategoryEffectiveVariant(categoryName, requirement, config2) {
25930
26517
  // src/cli/doctor/checks/model-resolution-details.ts
25931
26518
  function buildModelResolutionDetails(options) {
25932
26519
  const details = [];
25933
- const cacheFile = join17(getOpenCodeCacheDir(), "models.json");
26520
+ const cacheFile = join20(getOpenCodeCacheDir(), "models.json");
25934
26521
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
25935
26522
  details.push("");
25936
26523
  if (options.available.cacheExists) {
@@ -26042,8 +26629,8 @@ async function checkModels() {
26042
26629
  }
26043
26630
 
26044
26631
  // 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);
26632
+ var USER_CONFIG_BASE2 = join21(getOpenCodeConfigDir({ binary: "opencode" }), PACKAGE_NAME4);
26633
+ var PROJECT_CONFIG_BASE2 = join21(process.cwd(), ".opencode", PACKAGE_NAME4);
26047
26634
  function findConfigPath() {
26048
26635
  const projectConfig = detectConfigFile(PROJECT_CONFIG_BASE2);
26049
26636
  if (projectConfig.format !== "none")
@@ -26059,7 +26646,7 @@ function validateConfig() {
26059
26646
  return { exists: false, path: null, valid: true, config: null, errors: [] };
26060
26647
  }
26061
26648
  try {
26062
- const content = readFileSync23(configPath, "utf-8");
26649
+ const content = readFileSync26(configPath, "utf-8");
26063
26650
  const rawConfig = parseJsonc(content);
26064
26651
  const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
26065
26652
  if (!schemaResult.success) {
@@ -26162,9 +26749,9 @@ async function checkConfig() {
26162
26749
  }
26163
26750
 
26164
26751
  // src/cli/doctor/checks/dependencies.ts
26165
- import { existsSync as existsSync21 } from "fs";
26752
+ import { existsSync as existsSync24 } from "fs";
26166
26753
  import { createRequire as createRequire2 } from "module";
26167
- import { dirname as dirname5, join as join19 } from "path";
26754
+ import { dirname as dirname7, join as join22 } from "path";
26168
26755
  async function checkBinaryExists(binary2) {
26169
26756
  try {
26170
26757
  const path9 = Bun.which(binary2);
@@ -26220,15 +26807,15 @@ async function checkAstGrepNapi() {
26220
26807
  path: null
26221
26808
  };
26222
26809
  } catch {
26223
- const { existsSync: existsSync22 } = await import("fs");
26224
- const { join: join20 } = await import("path");
26810
+ const { existsSync: existsSync25 } = await import("fs");
26811
+ const { join: join23 } = await import("path");
26225
26812
  const { homedir: homedir8 } = await import("os");
26226
26813
  const pathsToCheck = [
26227
- join20(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
26228
- join20(process.cwd(), "node_modules", "@ast-grep", "napi")
26814
+ join23(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
26815
+ join23(process.cwd(), "node_modules", "@ast-grep", "napi")
26229
26816
  ];
26230
26817
  for (const napiPath of pathsToCheck) {
26231
- if (existsSync22(napiPath)) {
26818
+ if (existsSync25(napiPath)) {
26232
26819
  return {
26233
26820
  name: "AST-Grep NAPI",
26234
26821
  required: false,
@@ -26253,8 +26840,8 @@ function findCommentCheckerPackageBinary() {
26253
26840
  try {
26254
26841
  const require2 = createRequire2(import.meta.url);
26255
26842
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
26256
- const binaryPath = join19(dirname5(pkgPath), "bin", binaryName);
26257
- if (existsSync21(binaryPath))
26843
+ const binaryPath = join22(dirname7(pkgPath), "bin", binaryName);
26844
+ if (existsSync24(binaryPath))
26258
26845
  return binaryPath;
26259
26846
  } catch {}
26260
26847
  return null;
@@ -26372,14 +26959,14 @@ init_jsonc_parser();
26372
26959
 
26373
26960
  // src/tools/lsp/server-installation.ts
26374
26961
  init_shared();
26375
- import { existsSync as existsSync22 } from "fs";
26376
- import { join as join20 } from "path";
26962
+ import { existsSync as existsSync25 } from "fs";
26963
+ import { join as join23 } from "path";
26377
26964
  function isServerInstalled(command) {
26378
26965
  if (command.length === 0)
26379
26966
  return false;
26380
26967
  const cmd = command[0];
26381
26968
  if (cmd.includes("/") || cmd.includes("\\")) {
26382
- if (existsSync22(cmd))
26969
+ if (existsSync25(cmd))
26383
26970
  return true;
26384
26971
  }
26385
26972
  const isWindows = process.platform === "win32";
@@ -26401,23 +26988,23 @@ function isServerInstalled(command) {
26401
26988
  const paths = pathEnv.split(pathSeparator);
26402
26989
  for (const p2 of paths) {
26403
26990
  for (const suffix of exts) {
26404
- if (existsSync22(join20(p2, cmd + suffix))) {
26991
+ if (existsSync25(join23(p2, cmd + suffix))) {
26405
26992
  return true;
26406
26993
  }
26407
26994
  }
26408
26995
  }
26409
26996
  const cwd = process.cwd();
26410
26997
  const configDir = getOpenCodeConfigDir({ binary: "opencode" });
26411
- const dataDir = join20(getDataDir(), "opencode");
26998
+ const dataDir = join23(getDataDir(), "opencode");
26412
26999
  const additionalBases = [
26413
- join20(cwd, "node_modules", ".bin"),
26414
- join20(configDir, "bin"),
26415
- join20(configDir, "node_modules", ".bin"),
26416
- join20(dataDir, "bin")
27000
+ join23(cwd, "node_modules", ".bin"),
27001
+ join23(configDir, "bin"),
27002
+ join23(configDir, "node_modules", ".bin"),
27003
+ join23(dataDir, "bin")
26417
27004
  ];
26418
27005
  for (const base of additionalBases) {
26419
27006
  for (const suffix of exts) {
26420
- if (existsSync22(join20(base, cmd + suffix))) {
27007
+ if (existsSync25(join23(base, cmd + suffix))) {
26421
27008
  return true;
26422
27009
  }
26423
27010
  }
@@ -26451,24 +27038,24 @@ function getLspServerStats(servers) {
26451
27038
 
26452
27039
  // src/cli/doctor/checks/tools-mcp.ts
26453
27040
  init_shared();
26454
- import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
27041
+ import { existsSync as existsSync26, readFileSync as readFileSync27 } from "fs";
26455
27042
  import { homedir as homedir8 } from "os";
26456
- import { join as join21 } from "path";
27043
+ import { join as join24 } from "path";
26457
27044
  var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
26458
27045
  function getMcpConfigPaths() {
26459
27046
  return [
26460
- join21(homedir8(), ".claude", ".mcp.json"),
26461
- join21(process.cwd(), ".mcp.json"),
26462
- join21(process.cwd(), ".claude", ".mcp.json")
27047
+ join24(homedir8(), ".claude", ".mcp.json"),
27048
+ join24(process.cwd(), ".mcp.json"),
27049
+ join24(process.cwd(), ".claude", ".mcp.json")
26463
27050
  ];
26464
27051
  }
26465
27052
  function loadUserMcpConfig() {
26466
27053
  const servers = {};
26467
27054
  for (const configPath of getMcpConfigPaths()) {
26468
- if (!existsSync23(configPath))
27055
+ if (!existsSync26(configPath))
26469
27056
  continue;
26470
27057
  try {
26471
- const content = readFileSync24(configPath, "utf-8");
27058
+ const content = readFileSync27(configPath, "utf-8");
26472
27059
  const config2 = parseJsonc(content);
26473
27060
  if (config2.mcpServers) {
26474
27061
  Object.assign(servers, config2.mcpServers);
@@ -26629,10 +27216,10 @@ function getAllCheckDefinitions() {
26629
27216
  }
26630
27217
 
26631
27218
  // src/cli/doctor/format-default.ts
26632
- var import_picocolors18 = __toESM(require_picocolors(), 1);
27219
+ var import_picocolors19 = __toESM(require_picocolors(), 1);
26633
27220
 
26634
27221
  // src/cli/doctor/format-shared.ts
26635
- var import_picocolors17 = __toESM(require_picocolors(), 1);
27222
+ var import_picocolors18 = __toESM(require_picocolors(), 1);
26636
27223
  function formatStatusSymbol(status) {
26637
27224
  const colorFn = STATUS_COLORS[status];
26638
27225
  switch (status) {
@@ -26647,23 +27234,23 @@ function formatStatusSymbol(status) {
26647
27234
  }
26648
27235
  }
26649
27236
  function formatStatusMark(available) {
26650
- return available ? import_picocolors17.default.green(SYMBOLS3.check) : import_picocolors17.default.red(SYMBOLS3.cross);
27237
+ return available ? import_picocolors18.default.green(SYMBOLS3.check) : import_picocolors18.default.red(SYMBOLS3.cross);
26651
27238
  }
26652
27239
  function formatHeader() {
26653
27240
  return `
26654
- ${import_picocolors17.default.bgMagenta(import_picocolors17.default.white(" oMoMoMoMo Doctor "))}
27241
+ ${import_picocolors18.default.bgMagenta(import_picocolors18.default.white(" oMoMoMoMo Doctor "))}
26655
27242
  `;
26656
27243
  }
26657
27244
  function formatIssue(issue2, index) {
26658
27245
  const lines = [];
26659
- const severityColor = issue2.severity === "error" ? import_picocolors17.default.red : import_picocolors17.default.yellow;
27246
+ const severityColor = issue2.severity === "error" ? import_picocolors18.default.red : import_picocolors18.default.yellow;
26660
27247
  lines.push(`${index}. ${severityColor(issue2.title)}`);
26661
- lines.push(` ${import_picocolors17.default.dim(issue2.description)}`);
27248
+ lines.push(` ${import_picocolors18.default.dim(issue2.description)}`);
26662
27249
  if (issue2.fix) {
26663
- lines.push(` ${import_picocolors17.default.cyan("Fix:")} ${import_picocolors17.default.dim(issue2.fix)}`);
27250
+ lines.push(` ${import_picocolors18.default.cyan("Fix:")} ${import_picocolors18.default.dim(issue2.fix)}`);
26664
27251
  }
26665
27252
  if (issue2.affects && issue2.affects.length > 0) {
26666
- lines.push(` ${import_picocolors17.default.cyan("Affects:")} ${import_picocolors17.default.dim(issue2.affects.join(", "))}`);
27253
+ lines.push(` ${import_picocolors18.default.cyan("Affects:")} ${import_picocolors18.default.dim(issue2.affects.join(", "))}`);
26667
27254
  }
26668
27255
  return lines.join(`
26669
27256
  `);
@@ -26677,12 +27264,12 @@ function formatDefault(result) {
26677
27264
  if (allIssues.length === 0) {
26678
27265
  const opencodeVer = result.systemInfo.opencodeVersion ?? "unknown";
26679
27266
  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})`)}`);
27267
+ lines.push(` ${import_picocolors19.default.green(SYMBOLS3.check)} ${import_picocolors19.default.green(`System OK (opencode ${opencodeVer} \xB7 oh-my-opencode ${pluginVer})`)}`);
26681
27268
  } else {
26682
27269
  const issueCount = allIssues.filter((i2) => i2.severity === "error").length;
26683
27270
  const warnCount = allIssues.filter((i2) => i2.severity === "warning").length;
26684
27271
  const totalStr = `${issueCount + warnCount} ${issueCount + warnCount === 1 ? "issue" : "issues"}`;
26685
- lines.push(` ${import_picocolors18.default.yellow(SYMBOLS3.warn)} ${totalStr} found:
27272
+ lines.push(` ${import_picocolors19.default.yellow(SYMBOLS3.warn)} ${totalStr} found:
26686
27273
  `);
26687
27274
  allIssues.forEach((issue2, index) => {
26688
27275
  lines.push(formatIssue(issue2, index + 1));
@@ -26694,7 +27281,7 @@ function formatDefault(result) {
26694
27281
  }
26695
27282
 
26696
27283
  // src/cli/doctor/format-status.ts
26697
- var import_picocolors19 = __toESM(require_picocolors(), 1);
27284
+ var import_picocolors20 = __toESM(require_picocolors(), 1);
26698
27285
  function formatStatus(result) {
26699
27286
  const lines = [];
26700
27287
  lines.push(formatHeader());
@@ -26705,7 +27292,7 @@ function formatStatus(result) {
26705
27292
  const bunVer = systemInfo.bunVersion ?? "unknown";
26706
27293
  lines.push(` ${padding}System ${opencodeVer} \xB7 ${pluginVer} \xB7 Bun ${bunVer}`);
26707
27294
  const configPath = systemInfo.configPath ?? "unknown";
26708
- const configStatus = systemInfo.configValid ? import_picocolors19.default.green("(valid)") : import_picocolors19.default.red("(invalid)");
27295
+ const configStatus = systemInfo.configValid ? import_picocolors20.default.green("(valid)") : import_picocolors20.default.red("(invalid)");
26709
27296
  lines.push(` ${padding}Config ${configPath} ${configStatus}`);
26710
27297
  const lspText = `LSP ${tools.lspInstalled}/${tools.lspTotal}`;
26711
27298
  const astGrepMark = formatStatusMark(tools.astGrepCli);
@@ -26722,13 +27309,13 @@ function formatStatus(result) {
26722
27309
  }
26723
27310
 
26724
27311
  // src/cli/doctor/format-verbose.ts
26725
- var import_picocolors20 = __toESM(require_picocolors(), 1);
27312
+ var import_picocolors21 = __toESM(require_picocolors(), 1);
26726
27313
  function formatVerbose(result) {
26727
27314
  const lines = [];
26728
27315
  lines.push(formatHeader());
26729
27316
  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))}`);
27317
+ lines.push(`${import_picocolors21.default.bold("System Information")}`);
27318
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
26732
27319
  lines.push(` ${formatStatusSymbol("pass")} opencode ${systemInfo.opencodeVersion ?? "unknown"}`);
26733
27320
  lines.push(` ${formatStatusSymbol("pass")} oh-my-opencode ${systemInfo.pluginVersion ?? "unknown"}`);
26734
27321
  if (systemInfo.loadedVersion) {
@@ -26739,33 +27326,33 @@ function formatVerbose(result) {
26739
27326
  }
26740
27327
  lines.push(` ${formatStatusSymbol("pass")} path ${systemInfo.opencodePath ?? "unknown"}`);
26741
27328
  if (systemInfo.isLocalDev) {
26742
- lines.push(` ${import_picocolors20.default.yellow("*")} ${import_picocolors20.default.dim("(local development mode)")}`);
27329
+ lines.push(` ${import_picocolors21.default.yellow("*")} ${import_picocolors21.default.dim("(local development mode)")}`);
26743
27330
  }
26744
27331
  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");
27332
+ lines.push(`${import_picocolors21.default.bold("Configuration")}`);
27333
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
27334
+ const configStatus = systemInfo.configValid ? import_picocolors21.default.green("valid") : import_picocolors21.default.red("invalid");
26748
27335
  lines.push(` ${formatStatusSymbol(systemInfo.configValid ? "pass" : "fail")} ${systemInfo.configPath ?? "unknown"} (${configStatus})`);
26749
27336
  lines.push("");
26750
- lines.push(`${import_picocolors20.default.bold("Tools")}`);
26751
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
27337
+ lines.push(`${import_picocolors21.default.bold("Tools")}`);
27338
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
26752
27339
  lines.push(` ${formatStatusSymbol("pass")} LSP ${tools.lspInstalled}/${tools.lspTotal} installed`);
26753
27340
  lines.push(` ${formatStatusSymbol(tools.astGrepCli ? "pass" : "fail")} ast-grep CLI ${tools.astGrepCli ? "installed" : "not found"}`);
26754
27341
  lines.push(` ${formatStatusSymbol(tools.astGrepNapi ? "pass" : "fail")} ast-grep napi ${tools.astGrepNapi ? "installed" : "not found"}`);
26755
27342
  lines.push(` ${formatStatusSymbol(tools.commentChecker ? "pass" : "fail")} comment-checker ${tools.commentChecker ? "installed" : "not found"}`);
26756
27343
  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
27344
  lines.push("");
26758
- lines.push(`${import_picocolors20.default.bold("MCPs")}`);
26759
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
27345
+ lines.push(`${import_picocolors21.default.bold("MCPs")}`);
27346
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
26760
27347
  if (tools.mcpBuiltin.length === 0) {
26761
- lines.push(` ${import_picocolors20.default.dim("No built-in MCPs")}`);
27348
+ lines.push(` ${import_picocolors21.default.dim("No built-in MCPs")}`);
26762
27349
  } else {
26763
27350
  for (const mcp of tools.mcpBuiltin) {
26764
27351
  lines.push(` ${formatStatusSymbol("pass")} ${mcp}`);
26765
27352
  }
26766
27353
  }
26767
27354
  if (tools.mcpUser.length > 0) {
26768
- lines.push(` ${import_picocolors20.default.cyan("+")} ${tools.mcpUser.length} user MCP(s):`);
27355
+ lines.push(` ${import_picocolors21.default.cyan("+")} ${tools.mcpUser.length} user MCP(s):`);
26769
27356
  for (const mcp of tools.mcpUser) {
26770
27357
  lines.push(` ${formatStatusSymbol("pass")} ${mcp}`);
26771
27358
  }
@@ -26773,20 +27360,20 @@ function formatVerbose(result) {
26773
27360
  lines.push("");
26774
27361
  const allIssues = results.flatMap((r2) => r2.issues);
26775
27362
  if (allIssues.length > 0) {
26776
- lines.push(`${import_picocolors20.default.bold("Issues")}`);
26777
- lines.push(`${import_picocolors20.default.dim("\u2500".repeat(40))}`);
27363
+ lines.push(`${import_picocolors21.default.bold("Issues")}`);
27364
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
26778
27365
  allIssues.forEach((issue2, index) => {
26779
27366
  lines.push(formatIssue(issue2, index + 1));
26780
27367
  lines.push("");
26781
27368
  });
26782
27369
  }
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`;
27370
+ lines.push(`${import_picocolors21.default.bold("Summary")}`);
27371
+ lines.push(`${import_picocolors21.default.dim("\u2500".repeat(40))}`);
27372
+ const passText = summary.passed > 0 ? import_picocolors21.default.green(`${summary.passed} passed`) : `${summary.passed} passed`;
27373
+ const failText = summary.failed > 0 ? import_picocolors21.default.red(`${summary.failed} failed`) : `${summary.failed} failed`;
27374
+ const warnText = summary.warnings > 0 ? import_picocolors21.default.yellow(`${summary.warnings} warnings`) : `${summary.warnings} warnings`;
26788
27375
  lines.push(` ${passText}, ${failText}, ${warnText}`);
26789
- lines.push(` ${import_picocolors20.default.dim(`Total: ${summary.total} checks in ${summary.duration}ms`)}`);
27376
+ lines.push(` ${import_picocolors21.default.dim(`Total: ${summary.total} checks in ${summary.duration}ms`)}`);
26790
27377
  return lines.join(`
26791
27378
  `);
26792
27379
  }
@@ -26870,11 +27457,11 @@ async function doctor(options = { mode: "default" }) {
26870
27457
 
26871
27458
  // src/features/mcp-oauth/storage.ts
26872
27459
  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";
27460
+ import { chmodSync, existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as readFileSync28, unlinkSync as unlinkSync2, writeFileSync as writeFileSync12 } from "fs";
27461
+ import { dirname as dirname8, join as join25 } from "path";
26875
27462
  var STORAGE_FILE_NAME = "mcp-oauth.json";
26876
27463
  function getMcpOauthStoragePath() {
26877
- return join22(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
27464
+ return join25(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
26878
27465
  }
26879
27466
  function normalizeHost(serverHost) {
26880
27467
  let host = serverHost.trim();
@@ -26911,11 +27498,11 @@ function buildKey(serverHost, resource) {
26911
27498
  }
26912
27499
  function readStore() {
26913
27500
  const filePath = getMcpOauthStoragePath();
26914
- if (!existsSync24(filePath)) {
27501
+ if (!existsSync27(filePath)) {
26915
27502
  return null;
26916
27503
  }
26917
27504
  try {
26918
- const content = readFileSync25(filePath, "utf-8");
27505
+ const content = readFileSync28(filePath, "utf-8");
26919
27506
  return JSON.parse(content);
26920
27507
  } catch {
26921
27508
  return null;
@@ -26924,11 +27511,11 @@ function readStore() {
26924
27511
  function writeStore(store) {
26925
27512
  const filePath = getMcpOauthStoragePath();
26926
27513
  try {
26927
- const dir = dirname6(filePath);
26928
- if (!existsSync24(dir)) {
26929
- mkdirSync3(dir, { recursive: true });
27514
+ const dir = dirname8(filePath);
27515
+ if (!existsSync27(dir)) {
27516
+ mkdirSync6(dir, { recursive: true });
26930
27517
  }
26931
- writeFileSync9(filePath, JSON.stringify(store, null, 2), { encoding: "utf-8", mode: 384 });
27518
+ writeFileSync12(filePath, JSON.stringify(store, null, 2), { encoding: "utf-8", mode: 384 });
26932
27519
  chmodSync(filePath, 384);
26933
27520
  return true;
26934
27521
  } catch {
@@ -26960,8 +27547,8 @@ function deleteToken(serverHost, resource) {
26960
27547
  if (Object.keys(store).length === 0) {
26961
27548
  try {
26962
27549
  const filePath = getMcpOauthStoragePath();
26963
- if (existsSync24(filePath)) {
26964
- unlinkSync(filePath);
27550
+ if (existsSync27(filePath)) {
27551
+ unlinkSync2(filePath);
26965
27552
  }
26966
27553
  return true;
26967
27554
  } catch {
@@ -27132,30 +27719,11 @@ function isRecord2(value) {
27132
27719
  }
27133
27720
 
27134
27721
  // src/features/mcp-oauth/callback-server.ts
27722
+ init_port_utils();
27135
27723
  var DEFAULT_PORT = 19877;
27136
- var MAX_PORT_ATTEMPTS2 = 20;
27137
27724
  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
27725
  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}`);
27726
+ return findAvailablePort(startPort);
27159
27727
  }
27160
27728
 
27161
27729
  // src/features/mcp-oauth/oauth-authorization-flow.ts
@@ -27542,11 +28110,10 @@ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi):
27542
28110
  const exitCode = await install(args);
27543
28111
  process.exit(exitCode);
27544
28112
  });
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", `
28113
+ 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
28114
  Examples:
27547
28115
  $ bunx oh-my-opencode run "Fix the bug in index.ts"
27548
28116
  $ bunx oh-my-opencode run --agent Sisyphus "Implement feature X"
27549
- $ bunx oh-my-opencode run --timeout 3600000 "Large refactoring task"
27550
28117
  $ bunx oh-my-opencode run --port 4321 "Fix the bug"
27551
28118
  $ bunx oh-my-opencode run --attach http://127.0.0.1:4321 "Fix the bug"
27552
28119
  $ bunx oh-my-opencode run --json "Fix the bug" | jq .sessionId
@@ -27574,11 +28141,11 @@ Unlike 'opencode run', this command waits until:
27574
28141
  message,
27575
28142
  agent: options.agent,
27576
28143
  directory: options.directory,
27577
- timeout: options.timeout,
27578
28144
  port: options.port,
27579
28145
  attach: options.attach,
27580
28146
  onComplete: options.onComplete,
27581
28147
  json: options.json ?? false,
28148
+ verbose: options.verbose ?? false,
27582
28149
  sessionId: options.sessionId
27583
28150
  };
27584
28151
  const exitCode = await run(runOptions);