oh-my-opencode 5.1.27 → 5.1.29

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.
Files changed (56) hide show
  1. package/dist/cli/index.js +501 -47
  2. package/dist/cli-node/index.js +501 -47
  3. package/dist/index.js +523 -55
  4. package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
  5. package/dist/tui.js +256 -27
  6. package/package.json +14 -14
  7. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  8. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  9. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  10. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  11. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  12. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  13. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  14. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  15. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  16. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  17. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  18. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  19. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  20. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  21. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  22. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  23. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  24. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  25. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  26. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  27. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  28. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  29. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  30. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  31. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  32. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  33. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  34. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  35. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  36. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  37. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  38. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  39. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  40. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  41. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  42. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  43. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  44. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  45. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  46. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  47. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  48. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  51. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  52. package/packages/omo-codex/plugin/package-lock.json +12 -12
  53. package/packages/omo-codex/plugin/package.json +1 -1
  54. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
  55. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
  56. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
package/dist/cli/index.js CHANGED
@@ -64,7 +64,7 @@ var package_default;
64
64
  var init_package = __esm(() => {
65
65
  package_default = {
66
66
  name: "oh-my-opencode",
67
- version: "5.1.27",
67
+ version: "5.1.29",
68
68
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
69
69
  main: "./dist/index.js",
70
70
  types: "dist/index.d.ts",
@@ -241,7 +241,7 @@ var init_package = __esm(() => {
241
241
  },
242
242
  devDependencies: {
243
243
  "@clack/prompts": "^1.8.1",
244
- "@code-yeongyu/senpi": "2026.10.10-9",
244
+ "@code-yeongyu/senpi": "2026.10.10-11",
245
245
  "@modelcontextprotocol/sdk": "^1.30.0",
246
246
  "@oh-my-opencode/agents-md-core": "workspace:*",
247
247
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
@@ -299,18 +299,18 @@ var init_package = __esm(() => {
299
299
  typescript: "^7.0.2"
300
300
  },
301
301
  optionalDependencies: {
302
- "oh-my-opencode-darwin-arm64": "5.1.27",
303
- "oh-my-opencode-darwin-x64": "5.1.27",
304
- "oh-my-opencode-darwin-x64-baseline": "5.1.27",
305
- "oh-my-opencode-linux-arm64": "5.1.27",
306
- "oh-my-opencode-linux-arm64-musl": "5.1.27",
307
- "oh-my-opencode-linux-x64": "5.1.27",
308
- "oh-my-opencode-linux-x64-baseline": "5.1.27",
309
- "oh-my-opencode-linux-x64-musl": "5.1.27",
310
- "oh-my-opencode-linux-x64-musl-baseline": "5.1.27",
311
- "oh-my-opencode-windows-arm64": "5.1.27",
312
- "oh-my-opencode-windows-x64": "5.1.27",
313
- "oh-my-opencode-windows-x64-baseline": "5.1.27"
302
+ "oh-my-opencode-darwin-arm64": "5.1.29",
303
+ "oh-my-opencode-darwin-x64": "5.1.29",
304
+ "oh-my-opencode-darwin-x64-baseline": "5.1.29",
305
+ "oh-my-opencode-linux-arm64": "5.1.29",
306
+ "oh-my-opencode-linux-arm64-musl": "5.1.29",
307
+ "oh-my-opencode-linux-x64": "5.1.29",
308
+ "oh-my-opencode-linux-x64-baseline": "5.1.29",
309
+ "oh-my-opencode-linux-x64-musl": "5.1.29",
310
+ "oh-my-opencode-linux-x64-musl-baseline": "5.1.29",
311
+ "oh-my-opencode-windows-arm64": "5.1.29",
312
+ "oh-my-opencode-windows-x64": "5.1.29",
313
+ "oh-my-opencode-windows-x64-baseline": "5.1.29"
314
314
  },
315
315
  overrides: {
316
316
  hono: "^4.13.8",
@@ -4851,7 +4851,7 @@ function applyEdits(text, edits) {
4851
4851
  }
4852
4852
  return text;
4853
4853
  }
4854
- var ScanError, SyntaxKind, parse2, ParseErrorCode;
4854
+ var ScanError, SyntaxKind, parse2, parseTree2, findNodeAtLocation2, ParseErrorCode;
4855
4855
  var init_main = __esm(() => {
4856
4856
  init_format();
4857
4857
  init_edit();
@@ -4886,6 +4886,8 @@ var init_main = __esm(() => {
4886
4886
  SyntaxKind[SyntaxKind["EOF"] = 17] = "EOF";
4887
4887
  })(SyntaxKind || (SyntaxKind = {}));
4888
4888
  parse2 = parse;
4889
+ parseTree2 = parseTree;
4890
+ findNodeAtLocation2 = findNodeAtLocation;
4889
4891
  (function(ParseErrorCode) {
4890
4892
  ParseErrorCode[ParseErrorCode["InvalidSymbol"] = 1] = "InvalidSymbol";
4891
4893
  ParseErrorCode[ParseErrorCode["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
@@ -7245,20 +7247,20 @@ var init_agent_model_requirements = __esm(() => {
7245
7247
  fallbackChain: [
7246
7248
  { providers: ["kimi-for-coding"], model: "kimi-for-coding-highspeed", variant: "off" },
7247
7249
  { providers: ["openai", "chatgpt-subscription"], model: "gpt-6-luna-fast", variant: "low" },
7250
+ { providers: ["anthropic", "github-copilot"], model: "claude-haiku-5-5", variant: "medium" },
7248
7251
  { providers: ["deepseek"], model: "deepseek-flash", variant: "max" },
7249
7252
  { providers: ["opencode-go", "bailian-coding-plan"], model: "qwen3.7-plus" },
7250
- { providers: ["opencode-go"], model: "minimax-m2.7" },
7251
- { providers: ["anthropic", "github-copilot"], model: "claude-haiku-4-5" }
7253
+ { providers: ["opencode-go"], model: "minimax-m2.7" }
7252
7254
  ]
7253
7255
  },
7254
7256
  explore: {
7255
7257
  fallbackChain: [
7256
7258
  { providers: ["kimi-for-coding"], model: "kimi-for-coding-highspeed", variant: "off" },
7257
7259
  { providers: ["openai", "chatgpt-subscription"], model: "gpt-6-luna-fast", variant: "low" },
7260
+ { providers: ["anthropic", "github-copilot"], model: "claude-haiku-5-5", variant: "medium" },
7258
7261
  { providers: ["deepseek"], model: "deepseek-flash", variant: "max" },
7259
7262
  { providers: ["opencode-go", "bailian-coding-plan"], model: "qwen3.7-plus" },
7260
- { providers: ["opencode-go"], model: "minimax-m2.7" },
7261
- { providers: ["anthropic", "github-copilot"], model: "claude-haiku-4-5" }
7263
+ { providers: ["opencode-go"], model: "minimax-m2.7" }
7262
7264
  ]
7263
7265
  },
7264
7266
  "multimodal-looker": {
@@ -7433,6 +7435,11 @@ var init_category_model_requirements = __esm(() => {
7433
7435
  quick: {
7434
7436
  fallbackChain: [
7435
7437
  { providers: ["openai", "chatgpt-subscription"], model: "gpt-6-luna-fast", variant: "low" },
7438
+ {
7439
+ providers: ["anthropic", "anthropic-api", "github-copilot"],
7440
+ model: "claude-haiku-5-5",
7441
+ variant: "medium"
7442
+ },
7436
7443
  { providers: ["deepseek"], model: "deepseek-flash", variant: "off" },
7437
7444
  {
7438
7445
  providers: ["qwen-token-plan", "alibaba-token-plan", "bailian-coding-plan"],
@@ -7442,11 +7449,6 @@ var init_category_model_requirements = __esm(() => {
7442
7449
  { providers: ["opencode-go"], model: "minimax-m3", variant: "max" },
7443
7450
  { providers: ["opencode-go"], model: "minimax-m2.7", variant: "max" },
7444
7451
  { providers: ["xai"], model: "grok-4.20-0309-non-reasoning" },
7445
- {
7446
- providers: ["anthropic", "anthropic-api", "github-copilot"],
7447
- model: "claude-haiku-4-5",
7448
- variant: "off"
7449
- },
7450
7452
  { providers: ["zai-coding-plan"], model: "glm-5.3-flash", variant: "low" },
7451
7453
  { providers: ["xiaomi"], model: "mimo-v2.6-flash", variant: "low" }
7452
7454
  ]
@@ -64909,6 +64911,237 @@ var init_model_capabilities_generated = __esm(() => {
64909
64911
  input: 1048576,
64910
64912
  output: 131072
64911
64913
  }
64914
+ },
64915
+ "claude-haiku-5-5": {
64916
+ id: "claude-haiku-5-5",
64917
+ family: "claude-haiku",
64918
+ reasoning: true,
64919
+ temperature: false,
64920
+ toolCall: true,
64921
+ modalities: {
64922
+ input: [
64923
+ "text",
64924
+ "image",
64925
+ "pdf"
64926
+ ],
64927
+ output: [
64928
+ "text"
64929
+ ]
64930
+ },
64931
+ limit: {
64932
+ context: 1e6,
64933
+ output: 128000
64934
+ }
64935
+ },
64936
+ "claude-haiku-5-5@default": {
64937
+ id: "claude-haiku-5-5@default",
64938
+ family: "claude-haiku",
64939
+ reasoning: true,
64940
+ temperature: false,
64941
+ toolCall: true,
64942
+ modalities: {
64943
+ input: [
64944
+ "text",
64945
+ "image",
64946
+ "pdf"
64947
+ ],
64948
+ output: [
64949
+ "text"
64950
+ ]
64951
+ },
64952
+ limit: {
64953
+ context: 1e6,
64954
+ output: 128000
64955
+ }
64956
+ },
64957
+ "au.anthropic.claude-haiku-5-5": {
64958
+ id: "au.anthropic.claude-haiku-5-5",
64959
+ family: "claude-haiku",
64960
+ reasoning: true,
64961
+ temperature: false,
64962
+ toolCall: true,
64963
+ modalities: {
64964
+ input: [
64965
+ "text",
64966
+ "image",
64967
+ "pdf"
64968
+ ],
64969
+ output: [
64970
+ "text"
64971
+ ]
64972
+ },
64973
+ limit: {
64974
+ context: 1e6,
64975
+ output: 128000
64976
+ }
64977
+ },
64978
+ "anthropic.claude-haiku-5-5": {
64979
+ id: "anthropic.claude-haiku-5-5",
64980
+ family: "claude-haiku",
64981
+ reasoning: true,
64982
+ temperature: false,
64983
+ toolCall: true,
64984
+ modalities: {
64985
+ input: [
64986
+ "text",
64987
+ "image",
64988
+ "pdf"
64989
+ ],
64990
+ output: [
64991
+ "text"
64992
+ ]
64993
+ },
64994
+ limit: {
64995
+ context: 1e6,
64996
+ output: 128000
64997
+ }
64998
+ },
64999
+ "eu.anthropic.claude-haiku-5-5": {
65000
+ id: "eu.anthropic.claude-haiku-5-5",
65001
+ family: "claude-haiku",
65002
+ reasoning: true,
65003
+ temperature: false,
65004
+ toolCall: true,
65005
+ modalities: {
65006
+ input: [
65007
+ "text",
65008
+ "image",
65009
+ "pdf"
65010
+ ],
65011
+ output: [
65012
+ "text"
65013
+ ]
65014
+ },
65015
+ limit: {
65016
+ context: 1e6,
65017
+ output: 128000
65018
+ }
65019
+ },
65020
+ "global.anthropic.claude-haiku-5-5": {
65021
+ id: "global.anthropic.claude-haiku-5-5",
65022
+ family: "claude-haiku",
65023
+ reasoning: true,
65024
+ temperature: false,
65025
+ toolCall: true,
65026
+ modalities: {
65027
+ input: [
65028
+ "text",
65029
+ "image",
65030
+ "pdf"
65031
+ ],
65032
+ output: [
65033
+ "text"
65034
+ ]
65035
+ },
65036
+ limit: {
65037
+ context: 1e6,
65038
+ output: 128000
65039
+ }
65040
+ },
65041
+ "jp.anthropic.claude-haiku-5-5": {
65042
+ id: "jp.anthropic.claude-haiku-5-5",
65043
+ family: "claude-haiku",
65044
+ reasoning: true,
65045
+ temperature: false,
65046
+ toolCall: true,
65047
+ modalities: {
65048
+ input: [
65049
+ "text",
65050
+ "image",
65051
+ "pdf"
65052
+ ],
65053
+ output: [
65054
+ "text"
65055
+ ]
65056
+ },
65057
+ limit: {
65058
+ context: 1e6,
65059
+ output: 128000
65060
+ }
65061
+ },
65062
+ "us.anthropic.claude-haiku-5-5": {
65063
+ id: "us.anthropic.claude-haiku-5-5",
65064
+ family: "claude-haiku",
65065
+ reasoning: true,
65066
+ temperature: false,
65067
+ toolCall: true,
65068
+ modalities: {
65069
+ input: [
65070
+ "text",
65071
+ "image",
65072
+ "pdf"
65073
+ ],
65074
+ output: [
65075
+ "text"
65076
+ ]
65077
+ },
65078
+ limit: {
65079
+ context: 1e6,
65080
+ output: 128000
65081
+ }
65082
+ },
65083
+ "anthropic/claude-haiku-5-5": {
65084
+ id: "anthropic/claude-haiku-5-5",
65085
+ family: "claude-haiku",
65086
+ reasoning: true,
65087
+ temperature: false,
65088
+ toolCall: true,
65089
+ modalities: {
65090
+ input: [
65091
+ "text",
65092
+ "image"
65093
+ ],
65094
+ output: [
65095
+ "text"
65096
+ ]
65097
+ },
65098
+ limit: {
65099
+ context: 1e6,
65100
+ output: 128000
65101
+ }
65102
+ },
65103
+ "claude-haiku-5.5": {
65104
+ id: "claude-haiku-5.5",
65105
+ family: "claude-haiku",
65106
+ reasoning: true,
65107
+ temperature: false,
65108
+ toolCall: true,
65109
+ modalities: {
65110
+ input: [
65111
+ "text",
65112
+ "image",
65113
+ "pdf"
65114
+ ],
65115
+ output: [
65116
+ "text"
65117
+ ]
65118
+ },
65119
+ limit: {
65120
+ context: 1e6,
65121
+ output: 128000
65122
+ }
65123
+ },
65124
+ "anthropic/claude-haiku-5.5": {
65125
+ id: "anthropic/claude-haiku-5.5",
65126
+ family: "claude-haiku",
65127
+ reasoning: true,
65128
+ temperature: false,
65129
+ toolCall: true,
65130
+ modalities: {
65131
+ input: [
65132
+ "text",
65133
+ "image",
65134
+ "pdf"
65135
+ ],
65136
+ output: [
65137
+ "text"
65138
+ ]
65139
+ },
65140
+ limit: {
65141
+ context: 1e6,
65142
+ input: 1e6,
65143
+ output: 128000
65144
+ }
64912
65145
  }
64913
65146
  }
64914
65147
  };
@@ -68051,7 +68284,7 @@ var init_claude_model_mapper = __esm(() => {
68051
68284
  CLAUDE_CODE_ALIAS_MAP = new Map([
68052
68285
  ["sonnet", `${ANTHROPIC_PREFIX}claude-sonnet-4-6`],
68053
68286
  ["opus", `${ANTHROPIC_PREFIX}claude-opus-4-8`],
68054
- ["haiku", `${ANTHROPIC_PREFIX}claude-haiku-4-5`]
68287
+ ["haiku", `${ANTHROPIC_PREFIX}claude-haiku-5-5`]
68055
68288
  ]);
68056
68289
  });
68057
68290
 
@@ -76161,6 +76394,187 @@ var init_jsonc_parse = __esm(() => {
76161
76394
  init_main();
76162
76395
  });
76163
76396
 
76397
+ // packages/omo-config-core/src/writer/surgical-edit.ts
76398
+ function applyOmoConfigEdit(content, edit) {
76399
+ const fallback = formattedModify(content, edit);
76400
+ const surgical = surgicalEditPreservingEol(content, edit);
76401
+ if (surgical === undefined)
76402
+ return fallback;
76403
+ if (parses(fallback))
76404
+ return sameData(surgical, fallback) ? surgical : fallback;
76405
+ return parses(surgical) ? surgical : fallback;
76406
+ }
76407
+ function surgicalEditPreservingEol(content, edit) {
76408
+ const crlf = content.includes(`\r
76409
+ `);
76410
+ if (crlf && /(?<!\r)\n/.test(content))
76411
+ return;
76412
+ const text = crlf ? content.replaceAll(`\r
76413
+ `, `
76414
+ `) : content;
76415
+ const edited = surgicalEdit(text, edit);
76416
+ if (edited === undefined)
76417
+ return;
76418
+ return crlf ? edited.replaceAll(`
76419
+ `, `\r
76420
+ `) : edited;
76421
+ }
76422
+ function parses(content) {
76423
+ return parseJsoncSafe3(content).errors.length === 0;
76424
+ }
76425
+ function surgicalEdit(content, edit) {
76426
+ const root = parseTree2(content);
76427
+ if (root === undefined)
76428
+ return;
76429
+ const target = findNodeAtLocation2(root, [...edit.path]);
76430
+ if (target !== undefined)
76431
+ return edit.value === undefined ? removeMember(content, target) : undefined;
76432
+ if (edit.value === undefined)
76433
+ return content;
76434
+ return insertMember(content, root, edit);
76435
+ }
76436
+ function sameData(surgical, fallback) {
76437
+ const left = parseJsoncSafe3(surgical);
76438
+ const right = parseJsoncSafe3(fallback);
76439
+ if (left.errors.length > 0 || right.errors.length > 0)
76440
+ return false;
76441
+ return JSON.stringify(left.data) === JSON.stringify(right.data);
76442
+ }
76443
+ function formattedModify(content, edit) {
76444
+ return applyEdits(content, modify(content, [...edit.path], edit.value, { formattingOptions: FORMATTING_OPTIONS }));
76445
+ }
76446
+ function lineStart(content, offset) {
76447
+ return content.lastIndexOf(`
76448
+ `, offset - 1) + 1;
76449
+ }
76450
+ function lineEnd(content, offset) {
76451
+ const end = content.indexOf(`
76452
+ `, offset);
76453
+ return end === -1 ? content.length : end;
76454
+ }
76455
+ function leadingWhitespace(content, offset) {
76456
+ const start = lineStart(content, offset);
76457
+ return /^[ \t]*/.exec(content.slice(start))?.[0] ?? "";
76458
+ }
76459
+ function onlyWhitespaceBefore(content, offset) {
76460
+ return /^[ \t]*$/.test(content.slice(lineStart(content, offset), offset));
76461
+ }
76462
+ function commaAfter(content, offset) {
76463
+ const match = /^[ \t]*,/.exec(content.slice(offset));
76464
+ return match === null ? undefined : offset + match[0].length - 1;
76465
+ }
76466
+ function lineRestIsTrivia(content, offset) {
76467
+ const rest = content.slice(offset, lineEnd(content, offset));
76468
+ return /^[ \t]*,?[ \t]*(?:\/\/.*|\/\*(?:(?!\*\/).)*\*\/[ \t]*)?$/.test(rest);
76469
+ }
76470
+ function memberNodes(objectNode) {
76471
+ return (objectNode.children ?? []).filter((child) => child.type === "property");
76472
+ }
76473
+ function fileIndentUnit(content) {
76474
+ const indents = [...content.matchAll(/\n([ \t]+)\S/g)].map((match) => match[1] ?? "");
76475
+ if (indents.some((indent) => indent.startsWith("\t")))
76476
+ return "\t";
76477
+ const widths = indents.map((indent) => indent.length).filter((width) => width > 0);
76478
+ return " ".repeat(widths.length === 0 ? 2 : Math.min(...widths));
76479
+ }
76480
+ function indentUnit(content, memberIndent, objectIndent) {
76481
+ if (memberIndent.startsWith(objectIndent) && memberIndent.length > objectIndent.length) {
76482
+ return memberIndent.slice(objectIndent.length);
76483
+ }
76484
+ return fileIndentUnit(content);
76485
+ }
76486
+ function renderMember(key, value, memberIndent, unit) {
76487
+ const rendered = JSON.stringify(value, null, unit).split(`
76488
+ `).join(`
76489
+ ${memberIndent}`);
76490
+ return `${JSON.stringify(key)}: ${rendered}`;
76491
+ }
76492
+ function nestedValue(path, value) {
76493
+ return path.reduceRight((inner, segment) => ({ [String(segment)]: inner }), value);
76494
+ }
76495
+ function insertMember(content, root, edit) {
76496
+ let depth = edit.path.length - 1;
76497
+ let parent;
76498
+ while (depth >= 0) {
76499
+ parent = depth === 0 ? root : findNodeAtLocation2(root, [...edit.path.slice(0, depth)]);
76500
+ if (parent !== undefined)
76501
+ break;
76502
+ depth -= 1;
76503
+ }
76504
+ if (parent === undefined || parent.type !== "object")
76505
+ return;
76506
+ const key = edit.path[depth];
76507
+ if (typeof key !== "string")
76508
+ return;
76509
+ const value = nestedValue(edit.path.slice(depth + 1), edit.value);
76510
+ const objectIndent = leadingWhitespace(content, parent.offset);
76511
+ const closeBrace = parent.offset + parent.length - 1;
76512
+ const members = memberNodes(parent);
76513
+ const last = members.at(-1);
76514
+ if (last === undefined) {
76515
+ if (!/^\{\s*\}$/.test(content.slice(parent.offset, closeBrace + 1)))
76516
+ return;
76517
+ const unit = fileIndentUnit(content);
76518
+ const memberIndent = `${objectIndent}${unit}`;
76519
+ const member = renderMember(key, value, memberIndent, unit);
76520
+ return `${content.slice(0, parent.offset)}{
76521
+ ${memberIndent}${member}
76522
+ ${objectIndent}}${content.slice(closeBrace + 1)}`;
76523
+ }
76524
+ if (!onlyWhitespaceBefore(content, last.offset))
76525
+ return;
76526
+ const lastEnd = last.offset + last.length;
76527
+ if (!lineRestIsTrivia(content, lastEnd))
76528
+ return;
76529
+ const insertAt = lineEnd(content, lastEnd);
76530
+ if (insertAt >= closeBrace)
76531
+ return;
76532
+ const memberIndent = leadingWhitespace(content, last.offset);
76533
+ const unit = indentUnit(content, memberIndent, objectIndent);
76534
+ const trailingComma = commaAfter(content, lastEnd);
76535
+ const member = renderMember(key, value, memberIndent, unit);
76536
+ const head = trailingComma === undefined ? `${content.slice(0, lastEnd)},${content.slice(lastEnd, insertAt)}` : content.slice(0, insertAt);
76537
+ return `${head}
76538
+ ${memberIndent}${member}${trailingComma === undefined ? "" : ","}${content.slice(insertAt)}`;
76539
+ }
76540
+ function removeMember(content, valueNode) {
76541
+ const property = valueNode.parent;
76542
+ if (property?.type !== "property" || property.parent?.type !== "object")
76543
+ return;
76544
+ if (!onlyWhitespaceBefore(content, property.offset))
76545
+ return;
76546
+ const end = property.offset + property.length;
76547
+ if (!lineRestIsTrivia(content, end))
76548
+ return;
76549
+ const members = memberNodes(property.parent);
76550
+ const index = members.indexOf(property);
76551
+ const isLast = index === members.length - 1;
76552
+ const removeFrom = lineStart(content, property.offset);
76553
+ const lineAfter = lineEnd(content, end);
76554
+ const removeTo = lineAfter < content.length ? lineAfter + 1 : lineAfter;
76555
+ const removed = `${content.slice(0, removeFrom)}${content.slice(removeTo)}`;
76556
+ if (!isLast || commaAfter(content, end) !== undefined || index === 0)
76557
+ return removed;
76558
+ const previous = members[index - 1];
76559
+ if (previous === undefined)
76560
+ return removed;
76561
+ const previousComma = commaAfter(content, previous.offset + previous.length);
76562
+ if (previousComma === undefined)
76563
+ return removed;
76564
+ return `${removed.slice(0, previousComma)}${removed.slice(previousComma + 1)}`;
76565
+ }
76566
+ var FORMATTING_OPTIONS;
76567
+ var init_surgical_edit = __esm(() => {
76568
+ init_main();
76569
+ init_jsonc_parse();
76570
+ FORMATTING_OPTIONS = {
76571
+ eol: `
76572
+ `,
76573
+ insertSpaces: true,
76574
+ tabSize: 2
76575
+ };
76576
+ });
76577
+
76164
76578
  // packages/omo-config-core/src/writer/writer.ts
76165
76579
  import { randomUUID as randomUUID2 } from "crypto";
76166
76580
  import { dirname as dirname5, join as join16, posix as posix3 } from "path";
@@ -76288,7 +76702,7 @@ function updateOmoConfig(options) {
76288
76702
  }
76289
76703
  let nextContent = content;
76290
76704
  for (const edit of options.edits) {
76291
- nextContent = applyEdits(nextContent, modify(nextContent, [...edit.path], edit.value, { formattingOptions: FORMATTING_OPTIONS }));
76705
+ nextContent = applyOmoConfigEdit(nextContent, edit);
76292
76706
  }
76293
76707
  writeAtomically(path, nextContent, fileSystem);
76294
76708
  return backupPath === undefined ? { path } : { backupPath, path };
@@ -76296,18 +76710,12 @@ function updateOmoConfig(options) {
76296
76710
  var EMPTY_OMO_CONFIG = `// OMO configuration
76297
76711
  {
76298
76712
  }
76299
- `, FORMATTING_OPTIONS;
76713
+ `;
76300
76714
  var init_writer = __esm(() => {
76301
76715
  init_jsonc_parse();
76302
- init_main();
76303
76716
  init_loader3();
76717
+ init_surgical_edit();
76304
76718
  init_types4();
76305
- FORMATTING_OPTIONS = {
76306
- eol: `
76307
- `,
76308
- insertSpaces: true,
76309
- tabSize: 2
76310
- };
76311
76719
  });
76312
76720
 
76313
76721
  // packages/omo-config-core/src/writer/index.ts
@@ -76343,6 +76751,57 @@ function moveMigrationBackup(fileSystem, sourcePath, backupPath) {
76343
76751
  }
76344
76752
  }
76345
76753
 
76754
+ // packages/omo-config-core/src/migration/diff-edits.ts
76755
+ function deepEqual(left, right) {
76756
+ if (left === right)
76757
+ return true;
76758
+ if (Array.isArray(left) || Array.isArray(right)) {
76759
+ if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length)
76760
+ return false;
76761
+ return left.every((entry, index) => deepEqual(entry, right[index]));
76762
+ }
76763
+ if (!isPlainObject5(left) || !isPlainObject5(right))
76764
+ return false;
76765
+ const leftKeys = Object.keys(left);
76766
+ if (leftKeys.length !== Object.keys(right).length)
76767
+ return false;
76768
+ return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key]));
76769
+ }
76770
+ function withoutMarker(document) {
76771
+ const { _migrations: _marker, ...rest } = document;
76772
+ return rest;
76773
+ }
76774
+ function diffEdits(before, after, path = []) {
76775
+ const edits = [];
76776
+ for (const key of Object.keys(before)) {
76777
+ if (isUnsafeObjectKey3(key))
76778
+ continue;
76779
+ if (!Object.prototype.hasOwnProperty.call(after, key))
76780
+ edits.push({ path: [...path, key], value: undefined });
76781
+ }
76782
+ for (const [key, value] of Object.entries(after)) {
76783
+ if (isUnsafeObjectKey3(key))
76784
+ continue;
76785
+ const nextPath = [...path, key];
76786
+ if (!Object.prototype.hasOwnProperty.call(before, key)) {
76787
+ edits.push({ path: nextPath, value });
76788
+ continue;
76789
+ }
76790
+ const previous = before[key];
76791
+ if (deepEqual(previous, value))
76792
+ continue;
76793
+ if (isPlainObject5(previous) && isPlainObject5(value)) {
76794
+ edits.push(...diffEdits(previous, value, nextPath));
76795
+ continue;
76796
+ }
76797
+ edits.push({ path: nextPath, value });
76798
+ }
76799
+ return edits;
76800
+ }
76801
+ var init_diff_edits = __esm(() => {
76802
+ init_plain_object();
76803
+ });
76804
+
76346
76805
  // packages/omo-config-core/src/migration/merge.ts
76347
76806
  function displayValue(value) {
76348
76807
  const encoded = JSON.stringify(value);
@@ -76593,17 +77052,11 @@ function prepareTargetReplacement(input) {
76593
77052
  const marker = markerValue(input.target, input.migrationId, input.targetPath);
76594
77053
  const document = { ...documentCleanup.document, _migrations: marker };
76595
77054
  validateTarget(input.targetPath, document);
76596
- const edits = [...targetCleanup.edits];
76597
- for (const key of Object.keys(targetCleanup.document)) {
76598
- if (key !== "_migrations" && !Object.prototype.hasOwnProperty.call(documentCleanup.document, key)) {
76599
- edits.push({ path: [key], value: undefined });
76600
- }
76601
- }
76602
- for (const [key, value] of Object.entries(documentCleanup.document)) {
76603
- if (key !== "_migrations")
76604
- edits.push({ path: [key], value });
76605
- }
76606
- edits.push({ path: ["_migrations"], value: marker });
77055
+ const edits = [
77056
+ ...targetCleanup.edits,
77057
+ ...diffEdits(withoutMarker(targetCleanup.document), withoutMarker(documentCleanup.document)),
77058
+ { path: ["_migrations"], value: marker }
77059
+ ];
76607
77060
  return {
76608
77061
  diagnostics: uniqueDiagnostics([...targetCleanup.diagnostics, ...documentCleanup.diagnostics]),
76609
77062
  document,
@@ -76638,6 +77091,7 @@ var init_commit = __esm(() => {
76638
77091
  init_loader3();
76639
77092
  init_schema();
76640
77093
  init_writer2();
77094
+ init_diff_edits();
76641
77095
  init_merge2();
76642
77096
  init_types5();
76643
77097
  OMO_HARNESS_BLOCKS = [...OMO_CONFIG_HARNESS_IDS, ...OMO_CONFIG_LEGACY_HARNESS_IDS].map(harnessBlockKey);
@@ -77936,7 +78390,7 @@ function generateModelConfig(config) {
77936
78390
  if (avail.native.openai) {
77937
78391
  agentConfig = { model: "openai/gpt-6-luna-fast", variant: "low" };
77938
78392
  } else if (avail.native.claude) {
77939
- agentConfig = { model: "anthropic/claude-haiku-4-5" };
78393
+ agentConfig = { model: "anthropic/claude-haiku-5-5", variant: "medium" };
77940
78394
  } else if (avail.opencodeZen) {
77941
78395
  agentConfig = { model: "opencode/gpt-5-nano" };
77942
78396
  } else if (avail.opencodeGo) {
@@ -89440,7 +89894,7 @@ var package_default2;
89440
89894
  var init_package2 = __esm(() => {
89441
89895
  package_default2 = {
89442
89896
  name: "@oh-my-opencode/omo-codex",
89443
- version: "5.1.27",
89897
+ version: "5.1.29",
89444
89898
  type: "module",
89445
89899
  private: true,
89446
89900
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",