oh-my-opencode 4.11.1 → 4.12.1

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 (170) hide show
  1. package/.agents/skills/codex-qa/scripts/lib/app-server-client.mjs +132 -82
  2. package/.agents/skills/codex-qa/scripts/lib/app-server-client.test.js +48 -0
  3. package/.agents/skills/opencode-qa/scripts/serve-wake-split-probe.sh +361 -84
  4. package/.agents/skills/work-with-pr/SKILL.md +19 -5
  5. package/.opencode/skills/work-with-pr/SKILL.md +19 -5
  6. package/dist/agents/types.d.ts +7 -6
  7. package/dist/cli/index.js +460 -309
  8. package/dist/cli-node/index.js +460 -309
  9. package/dist/features/background-agent/parent-wake-flush-runner.d.ts +1 -0
  10. package/dist/features/background-agent/parent-wake-history-state.d.ts +1 -0
  11. package/dist/features/background-agent/parent-wake-session-history.d.ts +1 -47
  12. package/dist/features/background-agent/parent-wake-session-message.d.ts +47 -0
  13. package/dist/index.js +593 -310
  14. package/dist/plugin/tool-execute-before.d.ts +2 -0
  15. package/dist/plugin-handlers/plugin-components-loader.d.ts +1 -0
  16. package/dist/skills/ultraresearch/SKILL.md +11 -2
  17. package/dist/skills/ulw-plan/SKILL.md +2 -1
  18. package/dist/skills/ulw-plan/references/full-workflow.md +1 -1
  19. package/dist/skills/ulw-plan/references/intent-clear.md +2 -2
  20. package/dist/tools/background-task/constants.d.ts +1 -1
  21. package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -2
  22. package/dist/tools/delegate-task/sync-session-turns.d.ts +3 -0
  23. package/dist/tui.js +25 -10
  24. package/package.json +13 -13
  25. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +24 -2
  26. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +25 -9
  27. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  28. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  29. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +336 -173
  30. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +284 -33
  31. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  32. package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +11 -0
  33. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +12 -0
  34. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +34 -0
  35. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +47 -5
  36. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +7 -5
  37. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +58 -96
  38. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +94 -0
  39. package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +33 -0
  40. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +48 -0
  41. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +1 -0
  42. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +142 -0
  43. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  44. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  45. package/packages/omo-codex/plugin/components/comment-checker/test/package-smoke.test.ts +2 -71
  46. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  47. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  48. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  49. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  50. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  51. package/packages/omo-codex/plugin/components/lsp/package.json +2 -2
  52. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +26 -104
  53. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  54. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  55. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +12 -92
  56. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +157 -234
  57. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  58. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -2
  59. package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +227 -15
  60. package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +62 -2
  61. package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +34 -3
  62. package/packages/omo-codex/plugin/components/teammode/dist/cli.js +94 -0
  63. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +17 -0
  64. package/packages/omo-codex/plugin/components/teammode/package.json +26 -0
  65. package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +139 -0
  66. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +111 -0
  67. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-state.mjs +250 -0
  68. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +220 -0
  69. package/packages/omo-codex/plugin/components/teammode/src/cli.ts +12 -0
  70. package/packages/omo-codex/plugin/components/teammode/src/codex-hook.ts +125 -0
  71. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +116 -0
  72. package/packages/omo-codex/plugin/components/teammode/tsconfig.json +25 -0
  73. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  74. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  75. package/packages/omo-codex/plugin/components/test-support/package-smoke-fixture.ts +158 -0
  76. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  77. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  78. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +2 -1
  79. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/agents/openai.yaml +1 -1
  80. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
  81. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -2
  82. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +76 -49
  83. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
  84. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  85. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/agents/openai.yaml +1 -1
  86. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +1 -1
  87. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +17 -0
  88. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +17 -0
  89. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +17 -0
  90. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +17 -0
  91. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +17 -0
  92. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +17 -0
  93. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +17 -0
  94. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +17 -0
  95. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +17 -0
  96. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +17 -0
  97. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +17 -0
  98. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +17 -0
  99. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +16 -0
  100. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +16 -0
  101. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +16 -0
  102. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +16 -0
  103. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +16 -0
  104. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +17 -0
  105. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +16 -0
  106. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +16 -0
  107. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +16 -0
  108. package/packages/omo-codex/plugin/package-lock.json +30 -22
  109. package/packages/omo-codex/plugin/package.json +2 -1
  110. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +15 -11
  111. package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +15 -4
  112. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +37 -0
  113. package/packages/omo-codex/plugin/skills/ast-grep/agents/openai.yaml +2 -0
  114. package/packages/omo-codex/plugin/skills/comment-checker/agents/openai.yaml +2 -0
  115. package/packages/omo-codex/plugin/skills/debugging/agents/openai.yaml +2 -0
  116. package/packages/omo-codex/plugin/skills/frontend/agents/openai.yaml +2 -0
  117. package/packages/omo-codex/plugin/skills/git-master/agents/openai.yaml +1 -1
  118. package/packages/omo-codex/plugin/skills/init-deep/agents/openai.yaml +2 -0
  119. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
  120. package/packages/omo-codex/plugin/skills/lcx-doctor/agents/openai.yaml +1 -1
  121. package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
  122. package/packages/omo-codex/plugin/skills/lsp/agents/openai.yaml +2 -0
  123. package/packages/omo-codex/plugin/skills/lsp-setup/agents/openai.yaml +2 -0
  124. package/packages/omo-codex/plugin/skills/programming/agents/openai.yaml +2 -0
  125. package/packages/omo-codex/plugin/skills/refactor/agents/openai.yaml +2 -0
  126. package/packages/omo-codex/plugin/skills/remove-ai-slops/agents/openai.yaml +2 -0
  127. package/packages/omo-codex/plugin/skills/review-work/agents/openai.yaml +2 -0
  128. package/packages/omo-codex/plugin/skills/rules/agents/openai.yaml +2 -0
  129. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +2 -0
  130. package/packages/omo-codex/plugin/skills/teammode/SKILL.md +139 -0
  131. package/packages/omo-codex/plugin/skills/teammode/agents/openai.yaml +2 -0
  132. package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +111 -0
  133. package/packages/omo-codex/plugin/skills/teammode/scripts/team-state.mjs +250 -0
  134. package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +220 -0
  135. package/packages/omo-codex/plugin/skills/ultraresearch/SKILL.md +11 -2
  136. package/packages/omo-codex/plugin/skills/ultraresearch/agents/openai.yaml +2 -0
  137. package/packages/omo-codex/plugin/skills/ulw-loop/agents/openai.yaml +1 -1
  138. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -1
  139. package/packages/omo-codex/plugin/skills/ulw-plan/agents/openai.yaml +1 -1
  140. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
  141. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -2
  142. package/packages/omo-codex/plugin/skills/visual-qa/agents/openai.yaml +2 -0
  143. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +70 -33
  144. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +6 -2
  145. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +14 -1
  146. package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +1 -1
  147. package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +14 -6
  148. package/packages/omo-codex/plugin/test/bootstrap-ps-guard.test.mjs +7 -3
  149. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +4 -3
  150. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +24 -0
  151. package/packages/omo-codex/plugin/test/display-metadata.test.mjs +83 -0
  152. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +31 -19
  153. package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +3 -3
  154. package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +6 -6
  155. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -0
  156. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +9 -4
  157. package/packages/omo-codex/plugin/test/teammode-safety-fixture.mjs +88 -0
  158. package/packages/omo-codex/plugin/test/teammode-safety.test.mjs +240 -0
  159. package/packages/omo-codex/plugin/test/ultraresearch-skill-contract.test.mjs +48 -0
  160. package/packages/omo-codex/scripts/install-dist/install-local.mjs +398 -206
  161. package/packages/omo-codex/scripts/install-hook-targets.test.mjs +93 -0
  162. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +2 -2
  163. package/packages/omo-codex/scripts/install-local-bun-global-update.test.mjs +63 -0
  164. package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +109 -1
  165. package/packages/omo-codex/scripts/install-local.mjs +1 -0
  166. package/packages/shared-skills/skills/ultraresearch/SKILL.md +11 -2
  167. package/packages/shared-skills/skills/ulw-plan/SKILL.md +2 -1
  168. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
  169. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -2
  170. package/packages/omo-codex/plugin/hooks/hooks.json +0 -214
package/dist/index.js CHANGED
@@ -5798,6 +5798,201 @@ function buildCodegraphEnv(options = {}) {
5798
5798
  var CODEGRAPH_INSTALL_DIR_ENV = "CODEGRAPH_INSTALL_DIR", CODEGRAPH_NO_DOWNLOAD_ENV = "CODEGRAPH_NO_DOWNLOAD", CODEGRAPH_TELEMETRY_ENV = "CODEGRAPH_TELEMETRY", DO_NOT_TRACK_ENV = "DO_NOT_TRACK";
5799
5799
  var init_env = () => {};
5800
5800
 
5801
+ // packages/utils/src/codegraph/workspace.ts
5802
+ import { createHash as createHash2 } from "crypto";
5803
+ import {
5804
+ appendFileSync as appendFileSync2,
5805
+ existsSync as existsSync5,
5806
+ lstatSync as lstatSync2,
5807
+ mkdirSync as mkdirSync2,
5808
+ readFileSync as readFileSync2,
5809
+ readdirSync,
5810
+ realpathSync as realpathSync3,
5811
+ rmSync,
5812
+ statSync as statSync3,
5813
+ symlinkSync
5814
+ } from "fs";
5815
+ import { homedir as homedir3 } from "os";
5816
+ import { basename as basename3, join as join9, resolve as resolve4 } from "path";
5817
+ function sanitizeBase(value) {
5818
+ const sanitized = value.replace(/[^A-Za-z0-9._-]/g, "-").replace(/-+/g, "-");
5819
+ return sanitized.length > 0 ? sanitized : "workspace";
5820
+ }
5821
+ function codegraphDataRoot(homeDir) {
5822
+ return join9(homeDir, ".omo", "codegraph");
5823
+ }
5824
+ function workspaceStorageName(workspace) {
5825
+ const resolved = resolve4(workspace);
5826
+ const hash = createHash2("sha256").update(resolved).digest("hex").slice(0, 16);
5827
+ return `${sanitizeBase(basename3(resolved))}-${hash}`;
5828
+ }
5829
+ function resolveCodegraphWorkspacePaths(workspace, options = {}) {
5830
+ const resolvedWorkspace = resolve4(workspace);
5831
+ const dataRoot = codegraphDataRoot(options.homeDir ?? homedir3());
5832
+ return {
5833
+ dataDir: join9(dataRoot, "projects", workspaceStorageName(resolvedWorkspace)),
5834
+ dataRoot,
5835
+ projectLink: join9(resolvedWorkspace, ".codegraph")
5836
+ };
5837
+ }
5838
+ function fallbackResult(dataRoot, projectLink, reason) {
5839
+ return { dataDir: projectLink, dataRoot, linked: false, mode: "in-place-fallback", projectLink, reason };
5840
+ }
5841
+ function isSameFilesystem(workspace, dataRoot, override) {
5842
+ if (override !== undefined)
5843
+ return override;
5844
+ return statSync3(workspace).dev === statSync3(dataRoot).dev;
5845
+ }
5846
+ function ensureInPlaceFallback(projectLink) {
5847
+ if (!existsSync5(projectLink))
5848
+ mkdirSync2(projectLink, { recursive: true });
5849
+ }
5850
+ function prepareCodegraphWorkspace(workspace, options = {}) {
5851
+ const resolvedWorkspace = resolve4(workspace);
5852
+ const { dataDir, dataRoot, projectLink } = resolveCodegraphWorkspacePaths(resolvedWorkspace, options);
5853
+ try {
5854
+ mkdirSync2(dataDir, { recursive: true });
5855
+ if (existsSync5(projectLink)) {
5856
+ const linkStat = lstatSync2(projectLink);
5857
+ if (!linkStat.isSymbolicLink()) {
5858
+ return { dataDir: projectLink, dataRoot, linked: false, mode: "in-project", projectLink };
5859
+ }
5860
+ if (realpathSync3(projectLink) === realpathSync3(dataDir)) {
5861
+ return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
5862
+ }
5863
+ return fallbackResult(dataRoot, projectLink, "existing .codegraph symlink points outside OMO store");
5864
+ }
5865
+ if (!isSameFilesystem(resolvedWorkspace, dataRoot, options.sameFilesystem)) {
5866
+ ensureInPlaceFallback(projectLink);
5867
+ return fallbackResult(dataRoot, projectLink, "workspace and OMO store are on different filesystems");
5868
+ }
5869
+ const symlink = options.symlink ?? symlinkSync;
5870
+ symlink(dataDir, projectLink, (options.platform ?? process.platform) === "win32" ? "junction" : "dir");
5871
+ return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
5872
+ } catch (error) {
5873
+ const reason = error instanceof Error ? error.message : String(error);
5874
+ try {
5875
+ ensureInPlaceFallback(projectLink);
5876
+ } catch (fallbackError) {
5877
+ return fallbackResult(dataRoot, projectLink, `${reason}; fallback failed: ${String(fallbackError)}`);
5878
+ }
5879
+ return fallbackResult(dataRoot, projectLink, reason);
5880
+ }
5881
+ }
5882
+ function ensureCodegraphGitignored(workspace) {
5883
+ const gitDir = join9(workspace, ".git");
5884
+ if (!existsSync5(gitDir))
5885
+ return false;
5886
+ const excludePath = join9(gitDir, "info", "exclude");
5887
+ try {
5888
+ mkdirSync2(join9(gitDir, "info"), { recursive: true });
5889
+ const existing = existsSync5(excludePath) ? readFileSync2(excludePath, "utf8") : "";
5890
+ if (existing.split(/\r?\n/).includes(".codegraph"))
5891
+ return true;
5892
+ appendFileSync2(excludePath, `${existing.endsWith(`
5893
+ `) || existing.length === 0 ? "" : `
5894
+ `}.codegraph
5895
+ `);
5896
+ return true;
5897
+ } catch (error) {
5898
+ if (error instanceof Error)
5899
+ return false;
5900
+ throw error;
5901
+ }
5902
+ }
5903
+ var init_workspace = () => {};
5904
+
5905
+ // packages/utils/src/codegraph/guidance.ts
5906
+ import { homedir as homedir4 } from "os";
5907
+ function getCodegraphUninitializedProject(input) {
5908
+ const output = textFromUnknown(input.toolOutput);
5909
+ if (!isCodegraphTool(input.toolName))
5910
+ return null;
5911
+ const projectPath = extractProjectPath(output);
5912
+ if (projectPath !== null)
5913
+ return projectPath;
5914
+ if (!looksLikeCodegraphUninitializedOutput(output))
5915
+ return null;
5916
+ return typeof input.cwd === "string" && input.cwd.trim().length > 0 ? input.cwd.trim() : null;
5917
+ }
5918
+ function buildCodegraphInitGuidance(projectPath, options = {}) {
5919
+ const { dataDir, dataRoot, projectLink } = resolveCodegraphWorkspacePaths(projectPath, {
5920
+ homeDir: options.homeDir ?? homedir4()
5921
+ });
5922
+ const displayProjectPath = formatDisplayPath(projectPath);
5923
+ const displayProjectLink = formatDisplayPath(projectLink);
5924
+ const displayDataDir = formatDisplayPath(dataDir);
5925
+ const displayDataRoot = formatDisplayPath(dataRoot);
5926
+ return [
5927
+ "OMO CodeGraph initialization guidance:",
5928
+ "",
5929
+ `CodeGraph is not initialized for ${displayProjectPath}. Initialize it through OMO's global local store instead of leaving a standalone project-local index.`,
5930
+ "",
5931
+ `- Link or create ${displayProjectLink} so it points at ${displayDataDir} under the OMO store ${displayDataRoot}.`,
5932
+ `- Then run \`codegraph init\` from ${displayProjectPath} and retry the CodeGraph tool.`,
5933
+ "- OMO's CodeGraph bootstrap does this automatically on session start; if bootstrap just ran, wait for it to finish and retry."
5934
+ ].join(`
5935
+ `);
5936
+ }
5937
+ function buildCodegraphInitGuidanceForToolResult(input, options = {}) {
5938
+ const projectPath = getCodegraphUninitializedProject(input);
5939
+ return projectPath === null ? null : buildCodegraphInitGuidance(projectPath, options);
5940
+ }
5941
+ function extractProjectPath(output) {
5942
+ const normalizedOutput = normalizeCodegraphOutput(output);
5943
+ const uninitializedMatch = normalizedOutput.match(CODEGRAPH_UNINITIALIZED_PATTERN);
5944
+ const uninitializedProject = uninitializedMatch?.[1]?.trim();
5945
+ if (uninitializedProject && uninitializedProject.length > 0)
5946
+ return uninitializedProject;
5947
+ if (!looksLikeCodegraphUninitializedOutput(normalizedOutput))
5948
+ return null;
5949
+ const statusMatch = normalizedOutput.match(CODEGRAPH_STATUS_PROJECT_PATTERN);
5950
+ const statusProject = statusMatch?.[1]?.trim();
5951
+ return statusProject && statusProject.length > 0 ? statusProject : null;
5952
+ }
5953
+ function looksLikeCodegraphUninitializedOutput(output) {
5954
+ const normalizedOutput = normalizeCodegraphOutput(output);
5955
+ if (normalizedOutput.match(CODEGRAPH_UNINITIALIZED_PATTERN) !== null)
5956
+ return true;
5957
+ return CODEGRAPH_STATUS_UNINITIALIZED_PATTERN.test(normalizedOutput) && CODEGRAPH_INIT_HINT_PATTERN.test(normalizedOutput);
5958
+ }
5959
+ function normalizeCodegraphOutput(output) {
5960
+ return output.replace(ANSI_ESCAPE_PATTERN, "");
5961
+ }
5962
+ function isCodegraphTool(toolName) {
5963
+ if (typeof toolName !== "string")
5964
+ return false;
5965
+ return toolName.startsWith("codegraph.") || toolName.startsWith("codegraph_") || toolName.startsWith("mcp__codegraph__");
5966
+ }
5967
+ function formatDisplayPath(value) {
5968
+ return JSON.stringify(value);
5969
+ }
5970
+ function textFromUnknown(value) {
5971
+ if (typeof value === "string")
5972
+ return value;
5973
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint")
5974
+ return String(value);
5975
+ if (Array.isArray(value))
5976
+ return value.map(textFromUnknown).filter(Boolean).join(`
5977
+ `);
5978
+ if (!isRecord2(value))
5979
+ return "";
5980
+ return Object.entries(value).map(([key, nested]) => `${key}: ${textFromUnknown(nested)}`).filter((line) => line.trim().length > 0).join(`
5981
+ `);
5982
+ }
5983
+ function isRecord2(value) {
5984
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5985
+ }
5986
+ var CODEGRAPH_UNINITIALIZED_PATTERN, ANSI_ESCAPE_PATTERN, CODEGRAPH_STATUS_PROJECT_PATTERN, CODEGRAPH_STATUS_UNINITIALIZED_PATTERN, CODEGRAPH_INIT_HINT_PATTERN;
5987
+ var init_guidance = __esm(() => {
5988
+ init_workspace();
5989
+ CODEGRAPH_UNINITIALIZED_PATTERN = /CodeGraph not initialized in ([\s\S]*?)\.\s*Run ['`]codegraph init['`] in that project first\./i;
5990
+ ANSI_ESCAPE_PATTERN = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
5991
+ CODEGRAPH_STATUS_PROJECT_PATTERN = /^.*?\bProject:\s*(.+?)\s*$/im;
5992
+ CODEGRAPH_STATUS_UNINITIALIZED_PATTERN = /^.*?\bNot initialized\s*$/im;
5993
+ CODEGRAPH_INIT_HINT_PATTERN = /Run\s+["'`]codegraph init["'`]\s+(?:in that project first|to initialize)\.?/i;
5994
+ });
5995
+
5801
5996
  // packages/utils/src/codegraph/node-support.ts
5802
5997
  function evaluateCodegraphNodeSupport(options = {}) {
5803
5998
  const nodeVersion = options.nodeVersion ?? process.versions.node;
@@ -5860,24 +6055,24 @@ var init_manifest = __esm(() => {
5860
6055
  });
5861
6056
 
5862
6057
  // packages/utils/src/codegraph/provision.ts
5863
- import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
6058
+ import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
5864
6059
  import { execFile } from "child_process";
5865
6060
  import { chmod as chmod2, mkdir as mkdir2, readdir, readFile as readFile2, rename as rename2, rm as rm2, rmdir, stat, writeFile as writeFile3 } from "fs/promises";
5866
- import { existsSync as existsSync5 } from "fs";
5867
- import { homedir as homedir3, hostname } from "os";
5868
- import { basename as basename3, join as join9 } from "path";
6061
+ import { existsSync as existsSync6 } from "fs";
6062
+ import { homedir as homedir5, hostname } from "os";
6063
+ import { basename as basename4, join as join10 } from "path";
5869
6064
  import { promisify } from "util";
5870
6065
  function platformKey() {
5871
6066
  return `${process.platform}-${process.arch}`;
5872
6067
  }
5873
6068
  function markerPath(installDir, version) {
5874
- return join9(installDir, ".provisioned", `codegraph-${version}.json`);
6069
+ return join10(installDir, ".provisioned", `codegraph-${version}.json`);
5875
6070
  }
5876
6071
  function defaultInstallDir() {
5877
- return join9(homedir3(), ".omo", "codegraph");
6072
+ return join10(homedir5(), ".omo", "codegraph");
5878
6073
  }
5879
6074
  function sha2562(bytes) {
5880
- return createHash2("sha256").update(bytes).digest("hex");
6075
+ return createHash3("sha256").update(bytes).digest("hex");
5881
6076
  }
5882
6077
  function isErrnoException(error) {
5883
6078
  return error instanceof Error && "code" in error;
@@ -5894,7 +6089,7 @@ async function removeEmptyDirectory(path4) {
5894
6089
  }
5895
6090
  }
5896
6091
  function sleep(ms) {
5897
- return new Promise((resolve4) => setTimeout(resolve4, ms));
6092
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
5898
6093
  }
5899
6094
  async function defaultDownloader(asset, timeoutMs = DEFAULT_DOWNLOAD_TIMEOUT_MS2) {
5900
6095
  const response = await fetch(asset.url, { signal: AbortSignal.timeout(timeoutMs) });
@@ -5908,7 +6103,7 @@ function forcedBadChecksumOptions(options) {
5908
6103
  const key = options.platformKey ?? platformKey();
5909
6104
  return {
5910
6105
  downloader: async () => new TextEncoder().encode("checksum mismatch"),
5911
- installDir: options.installDir ?? join9(options.lockDir, "codegraph-force-bad-checksum"),
6106
+ installDir: options.installDir ?? join10(options.lockDir, "codegraph-force-bad-checksum"),
5912
6107
  manifest: {
5913
6108
  assets: {
5914
6109
  [key]: { executableName: process.platform === "win32" ? "codegraph.cmd" : "codegraph", sha256: "0000", url: "memory://bad" }
@@ -5919,13 +6114,13 @@ function forcedBadChecksumOptions(options) {
5919
6114
  };
5920
6115
  }
5921
6116
  async function readMarker(path4) {
5922
- if (!existsSync5(path4))
6117
+ if (!existsSync6(path4))
5923
6118
  return null;
5924
6119
  try {
5925
6120
  const raw = JSON.parse(await readFile2(path4, "utf8"));
5926
6121
  if (typeof raw === "object" && raw !== null && "binPath" in raw) {
5927
6122
  const value = raw.binPath;
5928
- return typeof value === "string" && existsSync5(value) ? value : null;
6123
+ return typeof value === "string" && existsSync6(value) ? value : null;
5929
6124
  }
5930
6125
  return null;
5931
6126
  } catch (error) {
@@ -5936,7 +6131,7 @@ async function readMarker(path4) {
5936
6131
  }
5937
6132
  async function acquireLock(lockPath, waitMs, staleMs) {
5938
6133
  const startedAt = Date.now();
5939
- await mkdir2(join9(lockPath, ".."), { recursive: true });
6134
+ await mkdir2(join10(lockPath, ".."), { recursive: true });
5940
6135
  while (Date.now() - startedAt <= waitMs) {
5941
6136
  try {
5942
6137
  await mkdir2(lockPath);
@@ -5961,44 +6156,44 @@ async function installExtractedBundle(extractDir, installDir, executableName) {
5961
6156
  const roots = await readdir(extractDir);
5962
6157
  if (roots.length !== 1)
5963
6158
  throw new Error(`CodeGraph archive should contain one root directory, found ${roots.length}`);
5964
- const bundleDir = join9(extractDir, roots[0] ?? "");
6159
+ const bundleDir = join10(extractDir, roots[0] ?? "");
5965
6160
  const bundleEntries = await readdir(bundleDir);
5966
6161
  await mkdir2(installDir, { recursive: true });
5967
6162
  for (const entry of bundleEntries) {
5968
- await rm2(join9(installDir, entry), { force: true, recursive: true });
5969
- await rename2(join9(bundleDir, entry), join9(installDir, entry));
6163
+ await rm2(join10(installDir, entry), { force: true, recursive: true });
6164
+ await rename2(join10(bundleDir, entry), join10(installDir, entry));
5970
6165
  }
5971
- const destination = join9(installDir, "bin", executableName);
5972
- if (!existsSync5(destination))
6166
+ const destination = join10(installDir, "bin", executableName);
6167
+ if (!existsSync6(destination))
5973
6168
  throw new Error(`CodeGraph archive did not contain bin/${executableName}`);
5974
6169
  await chmod2(destination, 493);
5975
6170
  return destination;
5976
6171
  }
5977
6172
  async function installAsset(layout) {
5978
6173
  const { asset, downloader, installDir, version } = layout;
5979
- const stagingDir = join9(installDir, ".staging", randomUUID2());
5980
- const archivePath = join9(stagingDir, basename3(asset.url));
5981
- const extractDir = join9(stagingDir, "extract");
6174
+ const stagingDir = join10(installDir, ".staging", randomUUID2());
6175
+ const archivePath = join10(stagingDir, basename4(asset.url));
6176
+ const extractDir = join10(stagingDir, "extract");
5982
6177
  try {
5983
6178
  await mkdir2(extractDir, { recursive: true });
5984
6179
  const bytes = await downloader(asset);
5985
6180
  const actualChecksum = sha2562(bytes);
5986
6181
  if (actualChecksum !== asset.sha256) {
5987
- throw new Error(`checksum mismatch for ${basename3(asset.url)}: expected ${asset.sha256}, got ${actualChecksum}`);
6182
+ throw new Error(`checksum mismatch for ${basename4(asset.url)}: expected ${asset.sha256}, got ${actualChecksum}`);
5988
6183
  }
5989
6184
  if (!asset.url.endsWith(".tar.gz") && !asset.url.endsWith(".tgz")) {
5990
- throw new Error(`unsupported CodeGraph archive type for ${basename3(asset.url)}`);
6185
+ throw new Error(`unsupported CodeGraph archive type for ${basename4(asset.url)}`);
5991
6186
  }
5992
6187
  await writeFile3(archivePath, bytes);
5993
6188
  await extractTarGz(archivePath, extractDir);
5994
6189
  const destination = await installExtractedBundle(extractDir, installDir, asset.executableName);
5995
- await mkdir2(join9(installDir, ".provisioned"), { recursive: true });
6190
+ await mkdir2(join10(installDir, ".provisioned"), { recursive: true });
5996
6191
  await writeFile3(markerPath(installDir, version), `${JSON.stringify({ binPath: destination, version })}
5997
6192
  `);
5998
6193
  return destination;
5999
6194
  } finally {
6000
6195
  await rm2(stagingDir, { force: true, recursive: true });
6001
- await removeEmptyDirectory(join9(installDir, ".staging"));
6196
+ await removeEmptyDirectory(join10(installDir, ".staging"));
6002
6197
  }
6003
6198
  }
6004
6199
  async function ensureCodegraphProvisioned(options) {
@@ -6011,7 +6206,7 @@ async function ensureCodegraphProvisioned(options) {
6011
6206
  const existing = await readMarker(marker);
6012
6207
  if (existing !== null)
6013
6208
  return { binPath: existing, provisioned: true };
6014
- const lockPath = join9(options.lockDir, `codegraph-${hostname()}.lock`);
6209
+ const lockPath = join10(options.lockDir, `codegraph-${hostname()}.lock`);
6015
6210
  const release = await acquireLock(lockPath, options.lockWaitMs ?? DEFAULT_LOCK_WAIT_MS, options.lockStaleMs ?? DEFAULT_LOCK_STALE_MS);
6016
6211
  if (release === null)
6017
6212
  return { error: "timed out waiting for codegraph provisioning lock", provisioned: false };
@@ -6041,10 +6236,10 @@ var init_provision = __esm(() => {
6041
6236
  });
6042
6237
 
6043
6238
  // packages/utils/src/codegraph/resolve.ts
6044
- import { existsSync as existsSync6 } from "fs";
6045
- import { homedir as homedir4 } from "os";
6239
+ import { existsSync as existsSync7 } from "fs";
6240
+ import { homedir as homedir6 } from "os";
6046
6241
  import { spawnSync as spawnSync2 } from "child_process";
6047
- import { basename as basename4, dirname as dirname3, join as join10 } from "path";
6242
+ import { basename as basename5, dirname as dirname3, join as join11 } from "path";
6048
6243
  import { createRequire } from "module";
6049
6244
  function defaultRequireResolve(specifier) {
6050
6245
  return requireFromHere.resolve(specifier);
@@ -6070,7 +6265,7 @@ ${result.stderr}`.trim().split(/\s+/)[0];
6070
6265
  }
6071
6266
  }
6072
6267
  function isNodeExecutableName(filePath) {
6073
- const executable = basename4(filePath).toLowerCase();
6268
+ const executable = basename5(filePath).toLowerCase();
6074
6269
  return executable === "node" || executable === "node.exe" || /^node\d+(\.exe)?$/.test(executable);
6075
6270
  }
6076
6271
  function looksLikePath(command) {
@@ -6109,7 +6304,7 @@ function defaultNodeRuntime(env, fileExists, which2, nodeVersion) {
6109
6304
  }
6110
6305
  function resolveCodegraphNodeRuntime(options = {}) {
6111
6306
  const env = options.env ?? process.env;
6112
- return defaultNodeRuntime(env, options.fileExists ?? existsSync6, options.which ?? bunWhich, options.nodeVersion ?? defaultNodeVersion);
6307
+ return defaultNodeRuntime(env, options.fileExists ?? existsSync7, options.which ?? bunWhich, options.nodeVersion ?? defaultNodeVersion);
6113
6308
  }
6114
6309
  function resolveCodegraphNodeSupport(options = {}) {
6115
6310
  const env = options.env ?? process.env;
@@ -6123,8 +6318,8 @@ function resolveCodegraphNodeSupport(options = {}) {
6123
6318
  function defaultProvisionedBin(homeDir, fileExists) {
6124
6319
  const binaryName = process.platform === "win32" ? "codegraph.cmd" : "codegraph";
6125
6320
  const candidates = [
6126
- join10(homeDir, ".omo", "codegraph", "bin", binaryName),
6127
- join10(homeDir, ".omo", "codegraph", "node-servers", "node_modules", ".bin", binaryName)
6321
+ join11(homeDir, ".omo", "codegraph", "bin", binaryName),
6322
+ join11(homeDir, ".omo", "codegraph", "node-servers", "node_modules", ".bin", binaryName)
6128
6323
  ];
6129
6324
  return candidates.find((candidate) => fileExists(candidate)) ?? null;
6130
6325
  }
@@ -6132,7 +6327,7 @@ function resolveBundledShim(requireResolve, fileExists) {
6132
6327
  try {
6133
6328
  const packageJson = requireResolve(`${CODEGRAPH_PACKAGE}/package.json`);
6134
6329
  const packageRoot = dirname3(packageJson);
6135
- const candidates = [join10(packageRoot, "bin", "codegraph.js"), join10(packageRoot, "npm-shim.js")];
6330
+ const candidates = [join11(packageRoot, "bin", "codegraph.js"), join11(packageRoot, "npm-shim.js")];
6136
6331
  return candidates.find((candidate) => fileExists(candidate)) ?? null;
6137
6332
  } catch (error) {
6138
6333
  if (error instanceof Error)
@@ -6148,7 +6343,7 @@ function resolveBundledShim(requireResolve, fileExists) {
6148
6343
  }
6149
6344
  function resolveCodegraphCommand(options = {}) {
6150
6345
  const env = options.env ?? process.env;
6151
- const fileExists = options.fileExists ?? existsSync6;
6346
+ const fileExists = options.fileExists ?? existsSync7;
6152
6347
  const configuredBin = env[CODEGRAPH_ENV_BIN]?.trim() || env[CODEGRAPH_LEGACY_ENV_BIN]?.trim();
6153
6348
  if (configuredBin !== undefined && configuredBin.length > 0) {
6154
6349
  return { argsPrefix: [], command: configuredBin, exists: fileExists(configuredBin), source: "env" };
@@ -6160,7 +6355,7 @@ function resolveCodegraphCommand(options = {}) {
6160
6355
  if (bundled !== null && runtime4 !== null) {
6161
6356
  return { argsPrefix: [bundled], command: runtime4, exists: true, source: "bundled" };
6162
6357
  }
6163
- const provisioned = options.provisioned?.() ?? defaultProvisionedBin(options.homeDir ?? homedir4(), fileExists);
6358
+ const provisioned = options.provisioned?.() ?? defaultProvisionedBin(options.homeDir ?? homedir6(), fileExists);
6164
6359
  if (provisioned !== null && fileExists(provisioned)) {
6165
6360
  return { argsPrefix: [], command: provisioned, exists: true, source: "provisioned" };
6166
6361
  }
@@ -6179,115 +6374,19 @@ var init_resolve2 = __esm(() => {
6179
6374
  requireFromHere = createRequire(import.meta.url);
6180
6375
  });
6181
6376
 
6182
- // packages/utils/src/codegraph/workspace.ts
6183
- import { createHash as createHash3 } from "crypto";
6184
- import {
6185
- appendFileSync as appendFileSync2,
6186
- existsSync as existsSync7,
6187
- lstatSync as lstatSync2,
6188
- mkdirSync as mkdirSync2,
6189
- readFileSync as readFileSync2,
6190
- readdirSync,
6191
- realpathSync as realpathSync3,
6192
- rmSync,
6193
- statSync as statSync3,
6194
- symlinkSync
6195
- } from "fs";
6196
- import { homedir as homedir5 } from "os";
6197
- import { basename as basename5, join as join11, resolve as resolve4 } from "path";
6198
- function sanitizeBase(value) {
6199
- const sanitized = value.replace(/[^A-Za-z0-9._-]/g, "-").replace(/-+/g, "-");
6200
- return sanitized.length > 0 ? sanitized : "workspace";
6201
- }
6202
- function codegraphDataRoot(homeDir) {
6203
- return join11(homeDir, ".omo", "codegraph");
6204
- }
6205
- function workspaceStorageName(workspace) {
6206
- const resolved = resolve4(workspace);
6207
- const hash = createHash3("sha256").update(resolved).digest("hex").slice(0, 16);
6208
- return `${sanitizeBase(basename5(resolved))}-${hash}`;
6209
- }
6210
- function fallbackResult(dataRoot, projectLink, reason) {
6211
- return { dataDir: projectLink, dataRoot, linked: false, mode: "in-place-fallback", projectLink, reason };
6212
- }
6213
- function isSameFilesystem(workspace, dataRoot, override) {
6214
- if (override !== undefined)
6215
- return override;
6216
- return statSync3(workspace).dev === statSync3(dataRoot).dev;
6217
- }
6218
- function ensureInPlaceFallback(projectLink) {
6219
- if (!existsSync7(projectLink))
6220
- mkdirSync2(projectLink, { recursive: true });
6221
- }
6222
- function prepareCodegraphWorkspace(workspace, options = {}) {
6223
- const resolvedWorkspace = resolve4(workspace);
6224
- const dataRoot = codegraphDataRoot(options.homeDir ?? homedir5());
6225
- const dataDir = join11(dataRoot, "projects", workspaceStorageName(resolvedWorkspace));
6226
- const projectLink = join11(resolvedWorkspace, ".codegraph");
6227
- try {
6228
- mkdirSync2(dataDir, { recursive: true });
6229
- if (existsSync7(projectLink)) {
6230
- const linkStat = lstatSync2(projectLink);
6231
- if (!linkStat.isSymbolicLink()) {
6232
- return { dataDir: projectLink, dataRoot, linked: false, mode: "in-project", projectLink };
6233
- }
6234
- if (realpathSync3(projectLink) === realpathSync3(dataDir)) {
6235
- return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
6236
- }
6237
- return fallbackResult(dataRoot, projectLink, "existing .codegraph symlink points outside OMO store");
6238
- }
6239
- if (!isSameFilesystem(resolvedWorkspace, dataRoot, options.sameFilesystem)) {
6240
- ensureInPlaceFallback(projectLink);
6241
- return fallbackResult(dataRoot, projectLink, "workspace and OMO store are on different filesystems");
6242
- }
6243
- const symlink = options.symlink ?? symlinkSync;
6244
- symlink(dataDir, projectLink, (options.platform ?? process.platform) === "win32" ? "junction" : "dir");
6245
- return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
6246
- } catch (error) {
6247
- const reason = error instanceof Error ? error.message : String(error);
6248
- try {
6249
- ensureInPlaceFallback(projectLink);
6250
- } catch (fallbackError) {
6251
- return fallbackResult(dataRoot, projectLink, `${reason}; fallback failed: ${String(fallbackError)}`);
6252
- }
6253
- return fallbackResult(dataRoot, projectLink, reason);
6254
- }
6255
- }
6256
- function ensureCodegraphGitignored(workspace) {
6257
- const gitDir = join11(workspace, ".git");
6258
- if (!existsSync7(gitDir))
6259
- return false;
6260
- const excludePath = join11(gitDir, "info", "exclude");
6261
- try {
6262
- mkdirSync2(join11(gitDir, "info"), { recursive: true });
6263
- const existing = existsSync7(excludePath) ? readFileSync2(excludePath, "utf8") : "";
6264
- if (existing.split(/\r?\n/).includes(".codegraph"))
6265
- return true;
6266
- appendFileSync2(excludePath, `${existing.endsWith(`
6267
- `) || existing.length === 0 ? "" : `
6268
- `}.codegraph
6269
- `);
6270
- return true;
6271
- } catch (error) {
6272
- if (error instanceof Error)
6273
- return false;
6274
- throw error;
6275
- }
6276
- }
6277
- var init_workspace = () => {};
6278
-
6279
6377
  // packages/utils/src/codegraph/index.ts
6280
6378
  var init_codegraph = __esm(() => {
6281
6379
  init_env();
6380
+ init_guidance();
6282
6381
  init_provision();
6283
6382
  init_resolve2();
6284
6383
  init_workspace();
6285
6384
  });
6286
6385
 
6287
6386
  // packages/utils/src/command-executor/home-directory.ts
6288
- import { homedir as homedir6 } from "os";
6387
+ import { homedir as homedir7 } from "os";
6289
6388
  function getHomeDirectory() {
6290
- return process.env.HOME || process.env.USERPROFILE || homedir6();
6389
+ return process.env.HOME || process.env.USERPROFILE || homedir7();
6291
6390
  }
6292
6391
  var init_home_directory = () => {};
6293
6392
 
@@ -12779,7 +12878,7 @@ var init_types2 = __esm(() => {
12779
12878
 
12780
12879
  // packages/team-core/src/team-registry/paths.ts
12781
12880
  import { mkdir as mkdir3, readdir as readdir2, stat as stat2, chmod as chmod3 } from "fs/promises";
12782
- import { homedir as homedir22 } from "os";
12881
+ import { homedir as homedir23 } from "os";
12783
12882
  import path14 from "path";
12784
12883
  function getTeamDirectory(baseDir, teamName, scope, projectRoot) {
12785
12884
  if (scope === "project") {
@@ -12802,7 +12901,7 @@ function resolveContainedPath2(baseDir, pathSegments) {
12802
12901
  return resolvedPath;
12803
12902
  }
12804
12903
  function resolveBaseDir(config) {
12805
- return config.base_dir ?? path14.join(homedir22(), ".omo");
12904
+ return config.base_dir ?? path14.join(homedir23(), ".omo");
12806
12905
  }
12807
12906
  function getTeamSpecPath(baseDir, teamName, scope, projectRoot) {
12808
12907
  return path14.join(getTeamDirectory(baseDir, teamName, scope, projectRoot), "config.json");
@@ -20506,7 +20605,7 @@ init_command_executor();
20506
20605
  init_src();
20507
20606
  // packages/omo-opencode/src/shared/file-reference-resolver.ts
20508
20607
  import { existsSync as existsSync10, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
20509
- import { homedir as homedir7 } from "os";
20608
+ import { homedir as homedir8 } from "os";
20510
20609
  import { isAbsolute as isAbsolute4, posix, resolve as resolve7, win32 } from "path";
20511
20610
  init_logger2();
20512
20611
  var FILE_REFERENCE_PATTERN = /@([^\s@]+)/g;
@@ -20525,7 +20624,7 @@ function expandEnvironmentVariable(match, variableName) {
20525
20624
  return value;
20526
20625
  }
20527
20626
  if (variableName === "HOME") {
20528
- return homedir7();
20627
+ return homedir8();
20529
20628
  }
20530
20629
  return match;
20531
20630
  }
@@ -20989,6 +21088,11 @@ function isClaudeOpus47OrLaterModel(model) {
20989
21088
  return false;
20990
21089
  return major > 4 || major === 4 && minor >= 7;
20991
21090
  }
21091
+ var CLAUDE_FABLE_OR_MYTHOS_RE = /claude-(?:fable|mythos)-(?:\d+|preview)/;
21092
+ function isClaudeFableOrMythosModel(model) {
21093
+ const modelName = extractModelName(model).toLowerCase().replaceAll(".", "-");
21094
+ return CLAUDE_FABLE_OR_MYTHOS_RE.test(modelName);
21095
+ }
20992
21096
  function isKimiK2Model(model) {
20993
21097
  const modelName = extractModelName(model).toLowerCase();
20994
21098
  if (modelName.includes("kimi"))
@@ -22020,7 +22124,7 @@ function extractRuntimeFallbackAutoRetrySignal(info) {
22020
22124
  }
22021
22125
  // packages/model-core/src/runtime-fallback-error-shape.ts
22022
22126
  var DEFAULT_RETRY_ON_ERRORS = [429, 500, 502, 503, 504];
22023
- function isRecord2(value) {
22127
+ function isRecord3(value) {
22024
22128
  return typeof value === "object" && value !== null;
22025
22129
  }
22026
22130
  function getRecordValue(record, key) {
@@ -22028,14 +22132,14 @@ function getRecordValue(record, key) {
22028
22132
  }
22029
22133
  function getNestedRecord(record, key) {
22030
22134
  const value = getRecordValue(record, key);
22031
- return isRecord2(value) ? value : undefined;
22135
+ return isRecord3(value) ? value : undefined;
22032
22136
  }
22033
22137
  function getRuntimeFallbackErrorMessage(error) {
22034
22138
  if (!error)
22035
22139
  return "";
22036
22140
  if (typeof error === "string")
22037
22141
  return error.toLowerCase();
22038
- if (!isRecord2(error)) {
22142
+ if (!isRecord3(error)) {
22039
22143
  try {
22040
22144
  return JSON.stringify(error).toLowerCase();
22041
22145
  } catch (error2) {
@@ -22071,7 +22175,7 @@ function getRuntimeFallbackErrorMessage(error) {
22071
22175
  }
22072
22176
  }
22073
22177
  function getRuntimeFallbackStatusCode(error, retryOnErrors) {
22074
- if (isRecord2(error)) {
22178
+ if (isRecord3(error)) {
22075
22179
  const topLevelStatusCode = getRecordValue(error, "statusCode");
22076
22180
  if (typeof topLevelStatusCode === "number")
22077
22181
  return topLevelStatusCode;
@@ -22079,7 +22183,7 @@ function getRuntimeFallbackStatusCode(error, retryOnErrors) {
22079
22183
  if (typeof topLevelStatus === "number")
22080
22184
  return topLevelStatus;
22081
22185
  }
22082
- const root = isRecord2(error) ? error : undefined;
22186
+ const root = isRecord3(error) ? error : undefined;
22083
22187
  const data = getNestedRecord(root, "data");
22084
22188
  const nestedError = getNestedRecord(root, "error");
22085
22189
  const cause = getNestedRecord(root, "cause");
@@ -22098,7 +22202,7 @@ function getRuntimeFallbackStatusCode(error, retryOnErrors) {
22098
22202
  return;
22099
22203
  }
22100
22204
  function getRuntimeFallbackErrorName(error) {
22101
- if (!isRecord2(error))
22205
+ if (!isRecord3(error))
22102
22206
  return;
22103
22207
  const data = getNestedRecord(error, "data");
22104
22208
  const nestedError = getNestedRecord(error, "error");
@@ -22113,7 +22217,7 @@ function getRuntimeFallbackErrorName(error) {
22113
22217
  return;
22114
22218
  }
22115
22219
  function getRuntimeFallbackRetryableSignal(error) {
22116
- if (!isRecord2(error))
22220
+ if (!isRecord3(error))
22117
22221
  return;
22118
22222
  const data = getNestedRecord(error, "data");
22119
22223
  const nestedError = getNestedRecord(error, "error");
@@ -22319,7 +22423,7 @@ function getBundledModelCapabilitiesSnapshot(snapshotJson) {
22319
22423
  };
22320
22424
  }
22321
22425
  // packages/model-core/src/model-capabilities/runtime-model-readers.ts
22322
- function isRecord3(value) {
22426
+ function isRecord4(value) {
22323
22427
  return typeof value === "object" && value !== null && !Array.isArray(value);
22324
22428
  }
22325
22429
  function readNumber(value) {
@@ -22337,7 +22441,7 @@ function normalizeVariantKeys(value) {
22337
22441
  if (arrayVariants) {
22338
22442
  return arrayVariants.filter((v) => typeof v === "string").map((variant) => variant.toLowerCase());
22339
22443
  }
22340
- if (!isRecord3(value)) {
22444
+ if (!isRecord4(value)) {
22341
22445
  return;
22342
22446
  }
22343
22447
  const variants = Object.keys(value).map((variant) => variant.toLowerCase());
@@ -22348,7 +22452,7 @@ function readModalityKeys(value) {
22348
22452
  if (stringArray) {
22349
22453
  return stringArray.filter((entry) => typeof entry === "string").map((entry) => entry.toLowerCase());
22350
22454
  }
22351
- if (!isRecord3(value)) {
22455
+ if (!isRecord4(value)) {
22352
22456
  return;
22353
22457
  }
22354
22458
  const fromNested = Object.values(value).filter((v) => Array.isArray(v)).flat().filter((item) => typeof item === "string");
@@ -22359,7 +22463,7 @@ function readModalityKeys(value) {
22359
22463
  return enabled.length > 0 ? enabled : undefined;
22360
22464
  }
22361
22465
  function normalizeModalities(value) {
22362
- if (!isRecord3(value)) {
22466
+ if (!isRecord4(value)) {
22363
22467
  return;
22364
22468
  }
22365
22469
  const input = readModalityKeys(value.input);
@@ -22373,7 +22477,7 @@ function normalizeModalities(value) {
22373
22477
  };
22374
22478
  }
22375
22479
  function readRuntimeModelCapabilities(runtimeModel) {
22376
- return isRecord3(runtimeModel?.capabilities) ? runtimeModel.capabilities : undefined;
22480
+ return isRecord4(runtimeModel?.capabilities) ? runtimeModel.capabilities : undefined;
22377
22481
  }
22378
22482
  function readRuntimeModelBoolean(runtimeModel, keys) {
22379
22483
  const runtimeCapabilities = readRuntimeModelCapabilities(runtimeModel);
@@ -22390,7 +22494,7 @@ function readRuntimeModelBoolean(runtimeModel, keys) {
22390
22494
  return;
22391
22495
  }
22392
22496
  function readRuntimeModel(runtimeModel) {
22393
- return isRecord3(runtimeModel) ? runtimeModel : undefined;
22497
+ return isRecord4(runtimeModel) ? runtimeModel : undefined;
22394
22498
  }
22395
22499
  function readRuntimeModelVariants(runtimeModel) {
22396
22500
  const rootVariants = normalizeVariantKeys(runtimeModel?.variants);
@@ -22438,8 +22542,8 @@ function readRuntimeModelToolCallSupport(runtimeModel) {
22438
22542
  return readRuntimeModelBoolean(runtimeModel, ["toolCall", "tool_call", "toolcall"]);
22439
22543
  }
22440
22544
  function readRuntimeModelLimitOutput(runtimeModel) {
22441
- const limit = isRecord3(runtimeModel?.limit) ? runtimeModel.limit : readRuntimeModelCapabilities(runtimeModel)?.limit;
22442
- if (!isRecord3(limit)) {
22545
+ const limit = isRecord4(runtimeModel?.limit) ? runtimeModel.limit : readRuntimeModelCapabilities(runtimeModel)?.limit;
22546
+ if (!isRecord4(limit)) {
22443
22547
  return;
22444
22548
  }
22445
22549
  const output = readNumber(limit.output);
@@ -22556,7 +22660,7 @@ function resolveActualContextLimit(providerID, modelID, modelCacheState) {
22556
22660
  }
22557
22661
  // packages/model-core/src/model-capabilities-snapshot.ts
22558
22662
  var MODELS_DEV_SOURCE_URL = "https://models.dev/api.json";
22559
- function isRecord4(value) {
22663
+ function isRecord5(value) {
22560
22664
  return typeof value === "object" && value !== null && !Array.isArray(value);
22561
22665
  }
22562
22666
  function readBoolean(value) {
@@ -22576,7 +22680,7 @@ function readStringArray2(value) {
22576
22680
  return result.length > 0 ? result : undefined;
22577
22681
  }
22578
22682
  function normalizeSnapshotEntry(rawModelID, rawModel) {
22579
- if (!isRecord4(rawModel)) {
22683
+ if (!isRecord5(rawModel)) {
22580
22684
  return;
22581
22685
  }
22582
22686
  const id = readString(rawModel.id) ?? rawModelID;
@@ -22584,14 +22688,14 @@ function normalizeSnapshotEntry(rawModelID, rawModel) {
22584
22688
  const reasoning = readBoolean(rawModel.reasoning);
22585
22689
  const temperature = readBoolean(rawModel.temperature);
22586
22690
  const toolCall = readBoolean(rawModel.tool_call);
22587
- const rawModalities = isRecord4(rawModel.modalities) ? rawModel.modalities : undefined;
22691
+ const rawModalities = isRecord5(rawModel.modalities) ? rawModel.modalities : undefined;
22588
22692
  const modalitiesInput = readStringArray2(rawModalities?.input);
22589
22693
  const modalitiesOutput = readStringArray2(rawModalities?.output);
22590
22694
  const modalities = modalitiesInput || modalitiesOutput ? {
22591
22695
  ...modalitiesInput ? { input: modalitiesInput } : {},
22592
22696
  ...modalitiesOutput ? { output: modalitiesOutput } : {}
22593
22697
  } : undefined;
22594
- const rawLimit = isRecord4(rawModel.limit) ? rawModel.limit : undefined;
22698
+ const rawLimit = isRecord5(rawModel.limit) ? rawModel.limit : undefined;
22595
22699
  const limitContext = readNumber2(rawLimit?.context);
22596
22700
  const limitInput = readNumber2(rawLimit?.input);
22597
22701
  const limitOutput = readNumber2(rawLimit?.output);
@@ -22631,13 +22735,13 @@ function mergeSnapshotEntries(existing, incoming) {
22631
22735
  }
22632
22736
  function buildModelCapabilitiesSnapshotFromModelsDev(raw) {
22633
22737
  const models = {};
22634
- const providers = isRecord4(raw) ? raw : {};
22738
+ const providers = isRecord5(raw) ? raw : {};
22635
22739
  for (const providerValue of Object.values(providers)) {
22636
- if (!isRecord4(providerValue)) {
22740
+ if (!isRecord5(providerValue)) {
22637
22741
  continue;
22638
22742
  }
22639
22743
  const providerModels = providerValue.models;
22640
- if (!isRecord4(providerModels)) {
22744
+ if (!isRecord5(providerModels)) {
22641
22745
  continue;
22642
22746
  }
22643
22747
  for (const [rawModelID, rawModel] of Object.entries(providerModels)) {
@@ -23054,14 +23158,14 @@ function addConfigLoadError(error) {
23054
23158
  configLoadErrors.push(error);
23055
23159
  }
23056
23160
  // packages/omo-opencode/src/shared/claude-config-dir.ts
23057
- import { homedir as homedir9 } from "os";
23161
+ import { homedir as homedir10 } from "os";
23058
23162
  import { join as join14 } from "path";
23059
23163
  function getClaudeConfigDir() {
23060
23164
  const envConfigDir = process.env.CLAUDE_CONFIG_DIR;
23061
23165
  if (envConfigDir) {
23062
23166
  return envConfigDir;
23063
23167
  }
23064
- return join14(homedir9(), ".claude");
23168
+ return join14(homedir10(), ".claude");
23065
23169
  }
23066
23170
  // packages/omo-opencode/src/shared/jsonc-parser.ts
23067
23171
  init_src();
@@ -23386,7 +23490,7 @@ var KIMI_CATEGORIES = [
23386
23490
  // packages/omo-opencode/src/agents/types.ts
23387
23491
  var CLAUDE_THINKING_BUDGET_TOKENS = 32000;
23388
23492
  function buildClaudeThinkingConfig(model) {
23389
- if (isClaudeOpus47OrLaterModel(model)) {
23493
+ if (isClaudeOpus47OrLaterModel(model) || isClaudeFableOrMythosModel(model)) {
23390
23494
  return {};
23391
23495
  }
23392
23496
  return { thinking: { type: "enabled", budgetTokens: CLAUDE_THINKING_BUDGET_TOKENS } };
@@ -23906,7 +24010,7 @@ configureMigrationCategoryDefaults(DEFAULT_CATEGORIES);
23906
24010
  // packages/omo-opencode/src/shared/opencode-config-dir.ts
23907
24011
  init_plugin_identity();
23908
24012
  import { existsSync as existsSync11, realpathSync as realpathSync4 } from "fs";
23909
- import { homedir as homedir10 } from "os";
24013
+ import { homedir as homedir11 } from "os";
23910
24014
  import { join as join15, posix as posix2, resolve as resolve8, win32 as win322 } from "path";
23911
24015
  var TAURI_APP_IDENTIFIER = "ai.opencode.desktop";
23912
24016
  var TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
@@ -23919,14 +24023,14 @@ function getTauriConfigDir(identifier) {
23919
24023
  const platform = process.platform;
23920
24024
  switch (platform) {
23921
24025
  case "darwin":
23922
- return join15(homedir10(), "Library", "Application Support", identifier);
24026
+ return join15(homedir11(), "Library", "Application Support", identifier);
23923
24027
  case "win32": {
23924
- const appData = process.env.APPDATA || join15(homedir10(), "AppData", "Roaming");
24028
+ const appData = process.env.APPDATA || join15(homedir11(), "AppData", "Roaming");
23925
24029
  return win322.join(appData, identifier);
23926
24030
  }
23927
24031
  case "linux":
23928
24032
  default: {
23929
- const xdgConfig = process.env.XDG_CONFIG_HOME || join15(homedir10(), ".config");
24033
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join15(homedir11(), ".config");
23930
24034
  return join15(xdgConfig, identifier);
23931
24035
  }
23932
24036
  }
@@ -23970,7 +24074,7 @@ function getWslLinuxHomeDir(windowsConfigRoot) {
23970
24074
  function getCliDefaultConfigDir() {
23971
24075
  const envXdgConfig = process.env.XDG_CONFIG_HOME?.trim();
23972
24076
  const shouldIgnoreWindowsXdg = envXdgConfig !== undefined && envXdgConfig.length > 0 && isWslEnvironment() && isWindowsUserConfigRoot(envXdgConfig);
23973
- const xdgConfig = shouldIgnoreWindowsXdg ? posix2.join(getWslLinuxHomeDir(envXdgConfig) ?? "/home", ".config") : envXdgConfig || join15(homedir10(), ".config");
24077
+ const xdgConfig = shouldIgnoreWindowsXdg ? posix2.join(getWslLinuxHomeDir(envXdgConfig) ?? "/home", ".config") : envXdgConfig || join15(homedir11(), ".config");
23974
24078
  const configDir = isWslEnvironment() ? posix2.join(xdgConfig, "opencode") : join15(xdgConfig, "opencode");
23975
24079
  return resolveConfigPath(configDir);
23976
24080
  }
@@ -24023,12 +24127,12 @@ function getOpenCodeConfigPaths(options) {
24023
24127
  };
24024
24128
  }
24025
24129
  // packages/omo-opencode/src/shared/resolve-agent-definition-paths.ts
24026
- import { homedir as homedir11 } from "os";
24130
+ import { homedir as homedir12 } from "os";
24027
24131
  import { isAbsolute as isAbsolute5, join as join16, resolve as resolve9 } from "path";
24028
24132
  init_logger2();
24029
24133
  function resolveAgentDefinitionPaths(paths, baseDir, containmentDir) {
24030
24134
  return paths.flatMap((p) => {
24031
- const expanded = p.startsWith("~/") ? join16(homedir11(), p.slice(2)) : p;
24135
+ const expanded = p.startsWith("~/") ? join16(homedir12(), p.slice(2)) : p;
24032
24136
  const resolved = isAbsolute5(expanded) ? expanded : resolve9(baseDir, expanded);
24033
24137
  if (containmentDir !== null && !isWithinProject(resolved, containmentDir)) {
24034
24138
  log2(`agent_definitions path rejected (outside project boundary): ${p} -> ${resolved}`);
@@ -69992,7 +70096,7 @@ async function probe(registration) {
69992
70096
  registration.available = false;
69993
70097
  return false;
69994
70098
  }
69995
- const probeUrl = new URL("/session", registration.serverUrl);
70099
+ const probeUrl = new URL("/global/health", registration.serverUrl);
69996
70100
  const authHeader = getServerBasicAuthHeader();
69997
70101
  const headers = authHeader ? { Authorization: authHeader } : {};
69998
70102
  try {
@@ -70026,12 +70130,17 @@ async function probe(registration) {
70026
70130
  return false;
70027
70131
  }
70028
70132
  }
70029
- function hasFreshProbe(registration) {
70030
- return registration.available !== undefined && Date.now() - registration.probeTimestamp < PROBE_TTL_MS;
70133
+ function getFreshProbeAvailability(registration) {
70134
+ const available = registration.available;
70135
+ if (available === undefined || Date.now() - registration.probeTimestamp >= PROBE_TTL_MS) {
70136
+ return;
70137
+ }
70138
+ return available;
70031
70139
  }
70032
70140
  async function resolveAvailability(registration) {
70033
- if (hasFreshProbe(registration)) {
70034
- return registration.available;
70141
+ const freshAvailability = getFreshProbeAvailability(registration);
70142
+ if (freshAvailability !== undefined) {
70143
+ return freshAvailability;
70035
70144
  }
70036
70145
  if (!registration.inFlightProbe) {
70037
70146
  registration.inFlightProbe = probe(registration).finally(() => {
@@ -70066,10 +70175,11 @@ function tryResolveDispatchClientSync2(client3, sessionID) {
70066
70175
  if (!registration.serverUrl) {
70067
70176
  return { client: client3, route: "in-process", reason: "unavailable" };
70068
70177
  }
70069
- if (!hasFreshProbe(registration)) {
70178
+ const freshAvailability = getFreshProbeAvailability(registration);
70179
+ if (freshAvailability === undefined) {
70070
70180
  return;
70071
70181
  }
70072
- if (!registration.available) {
70182
+ if (!freshAvailability) {
70073
70183
  return { client: client3, route: "in-process", reason: "unavailable" };
70074
70184
  }
70075
70185
  const resolvedLiveClient = getOrBuildLiveClient(registration);
@@ -70084,6 +70194,9 @@ async function resolveDispatchClient2(client3, sessionID) {
70084
70194
  return syncResult;
70085
70195
  }
70086
70196
  const registration = registrations.get(client3);
70197
+ if (!registration) {
70198
+ return { client: client3, route: "in-process", reason: "identity" };
70199
+ }
70087
70200
  const isAvailable = await resolveAvailability(registration);
70088
70201
  if (!isAvailable) {
70089
70202
  return { client: client3, route: "in-process", reason: "unavailable" };
@@ -70652,7 +70765,7 @@ var log4 = logger4.log;
70652
70765
  var getLogFilePath2 = logger4.getLogFilePath;
70653
70766
 
70654
70767
  // packages/claude-code-compat-core/src/features/claude-code-plugin-loader/scope-filter.ts
70655
- import { homedir as homedir13 } from "os";
70768
+ import { homedir as homedir14 } from "os";
70656
70769
  import { join as join29 } from "path";
70657
70770
 
70658
70771
  // packages/claude-code-compat-core/src/shared/contains-path.ts
@@ -70661,10 +70774,10 @@ init_src();
70661
70774
  // packages/claude-code-compat-core/src/features/claude-code-plugin-loader/scope-filter.ts
70662
70775
  function expandTilde(inputPath) {
70663
70776
  if (inputPath === "~") {
70664
- return homedir13();
70777
+ return homedir14();
70665
70778
  }
70666
70779
  if (inputPath.startsWith("~/") || inputPath.startsWith("~\\")) {
70667
- return join29(homedir13(), inputPath.slice(2));
70780
+ return join29(homedir14(), inputPath.slice(2));
70668
70781
  }
70669
70782
  return inputPath;
70670
70783
  }
@@ -70679,13 +70792,13 @@ function shouldLoadPluginForCwd(installation, cwd = process.cwd()) {
70679
70792
  }
70680
70793
 
70681
70794
  // packages/claude-code-compat-core/src/features/claude-code-plugin-loader/discovery-paths.ts
70682
- import { homedir as homedir14 } from "os";
70795
+ import { homedir as homedir15 } from "os";
70683
70796
  import { join as join30 } from "path";
70684
70797
  function getPluginsBaseDir() {
70685
70798
  if (process.env.CLAUDE_PLUGINS_HOME) {
70686
70799
  return process.env.CLAUDE_PLUGINS_HOME;
70687
70800
  }
70688
- return join30(homedir14(), ".claude", "plugins");
70801
+ return join30(homedir15(), ".claude", "plugins");
70689
70802
  }
70690
70803
  function getInstalledPluginsPath(pluginsBaseDir) {
70691
70804
  return join30(pluginsBaseDir ?? getPluginsBaseDir(), "installed_plugins.json");
@@ -70694,7 +70807,7 @@ function getClaudeSettingsPath() {
70694
70807
  if (process.env.CLAUDE_SETTINGS_PATH) {
70695
70808
  return process.env.CLAUDE_SETTINGS_PATH;
70696
70809
  }
70697
- return join30(homedir14(), ".claude", "settings.json");
70810
+ return join30(homedir15(), ".claude", "settings.json");
70698
70811
  }
70699
70812
 
70700
70813
  // packages/claude-code-compat-core/src/features/claude-code-plugin-loader/installed-plugin-database.ts
@@ -74169,7 +74282,7 @@ async function runCommentChecker(input, options) {
74169
74282
  // packages/omo-opencode/src/hooks/comment-checker/downloader.ts
74170
74283
  import { existsSync as existsSync37, appendFileSync as appendFileSync3 } from "fs";
74171
74284
  import { join as join43 } from "path";
74172
- import { homedir as homedir15, tmpdir as tmpdir3 } from "os";
74285
+ import { homedir as homedir16, tmpdir as tmpdir3 } from "os";
74173
74286
  import { createRequire as createRequire3 } from "module";
74174
74287
  init_logger2();
74175
74288
  init_plugin_identity();
@@ -74193,11 +74306,11 @@ var PLATFORM_MAP = {
74193
74306
  function getCacheDir2() {
74194
74307
  if (process.platform === "win32") {
74195
74308
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
74196
- const base2 = localAppData || join43(homedir15(), "AppData", "Local");
74309
+ const base2 = localAppData || join43(homedir16(), "AppData", "Local");
74197
74310
  return join43(base2, CACHE_DIR_NAME, "bin");
74198
74311
  }
74199
74312
  const xdgCache = process.env.XDG_CACHE_HOME;
74200
- const base = xdgCache || join43(homedir15(), ".cache");
74313
+ const base = xdgCache || join43(homedir16(), ".cache");
74201
74314
  return join43(base, CACHE_DIR_NAME, "bin");
74202
74315
  }
74203
74316
  function getBinaryName() {
@@ -74809,7 +74922,7 @@ function isSameOrChildPath(childPath, parentPath) {
74809
74922
  }
74810
74923
  // packages/rules-engine/src/finder.ts
74811
74924
  import { existsSync as existsSync42, statSync as statSync6 } from "fs";
74812
- import { homedir as homedir16 } from "os";
74925
+ import { homedir as homedir17 } from "os";
74813
74926
  import { dirname as dirname13, isAbsolute as isAbsolute9, join as join48, relative as relative8, resolve as resolve14 } from "path";
74814
74927
 
74815
74928
  // packages/rules-engine/src/ordering.ts
@@ -74908,7 +75021,7 @@ function findRuleFiles(projectRoot, homeDir, currentFile, options, cache) {
74908
75021
  const seenRealPaths = new Set;
74909
75022
  addProjectRuleCandidates(effectiveProjectRoot, startDir, candidates, seenRealPaths, cache);
74910
75023
  addProjectSingleFileCandidates(effectiveProjectRoot, candidates, seenRealPaths);
74911
- addUserRuleCandidates(homeDir || homedir16(), skipClaudeUserRules, candidates, seenRealPaths, cache);
75024
+ addUserRuleCandidates(homeDir || homedir17(), skipClaudeUserRules, candidates, seenRealPaths, cache);
74912
75025
  const sorted = sortCandidates(candidates);
74913
75026
  cache?.set(cacheKey, sorted);
74914
75027
  return sorted;
@@ -79997,7 +80110,7 @@ function createSessionRuleScanCacheStore() {
79997
80110
  }
79998
80111
 
79999
80112
  // packages/omo-opencode/src/hooks/rules-injector/injection-processor.ts
80000
- import { homedir as homedir17 } from "os";
80113
+ import { homedir as homedir18 } from "os";
80001
80114
  // packages/omo-opencode/src/hooks/rules-injector/rule-file-finder.ts
80002
80115
  init_logger2();
80003
80116
  setSisyphusRuleDeprecationLogger(log2);
@@ -80143,7 +80256,7 @@ function createRuleInjectionProcessor(deps) {
80143
80256
  getSessionCache: getSessionCache3,
80144
80257
  getSessionRuleScanCache,
80145
80258
  ruleFinderOptions,
80146
- homedir: getHomeDir = homedir17,
80259
+ homedir: getHomeDir = homedir18,
80147
80260
  shouldApplyRule: shouldApplyRuleImpl = shouldApplyRule,
80148
80261
  isDuplicateByRealPath: isDuplicateByRealPathImpl = isDuplicateByRealPath,
80149
80262
  createContentHash: createContentHashImpl = createContentHash,
@@ -80669,7 +80782,7 @@ function getCachedVersion(options = {}) {
80669
80782
  // package.json
80670
80783
  var package_default = {
80671
80784
  name: "oh-my-opencode",
80672
- version: "4.11.1",
80785
+ version: "4.12.1",
80673
80786
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
80674
80787
  main: "./dist/index.js",
80675
80788
  types: "dist/index.d.ts",
@@ -80839,18 +80952,18 @@ var package_default = {
80839
80952
  typescript: "^6.0.3"
80840
80953
  },
80841
80954
  optionalDependencies: {
80842
- "oh-my-opencode-darwin-arm64": "4.11.1",
80843
- "oh-my-opencode-darwin-x64": "4.11.1",
80844
- "oh-my-opencode-darwin-x64-baseline": "4.11.1",
80845
- "oh-my-opencode-linux-arm64": "4.11.1",
80846
- "oh-my-opencode-linux-arm64-musl": "4.11.1",
80847
- "oh-my-opencode-linux-x64": "4.11.1",
80848
- "oh-my-opencode-linux-x64-baseline": "4.11.1",
80849
- "oh-my-opencode-linux-x64-musl": "4.11.1",
80850
- "oh-my-opencode-linux-x64-musl-baseline": "4.11.1",
80851
- "oh-my-opencode-windows-arm64": "4.11.1",
80852
- "oh-my-opencode-windows-x64": "4.11.1",
80853
- "oh-my-opencode-windows-x64-baseline": "4.11.1"
80955
+ "oh-my-opencode-darwin-arm64": "4.12.1",
80956
+ "oh-my-opencode-darwin-x64": "4.12.1",
80957
+ "oh-my-opencode-darwin-x64-baseline": "4.12.1",
80958
+ "oh-my-opencode-linux-arm64": "4.12.1",
80959
+ "oh-my-opencode-linux-arm64-musl": "4.12.1",
80960
+ "oh-my-opencode-linux-x64": "4.12.1",
80961
+ "oh-my-opencode-linux-x64-baseline": "4.12.1",
80962
+ "oh-my-opencode-linux-x64-musl": "4.12.1",
80963
+ "oh-my-opencode-linux-x64-musl-baseline": "4.12.1",
80964
+ "oh-my-opencode-windows-arm64": "4.12.1",
80965
+ "oh-my-opencode-windows-x64": "4.12.1",
80966
+ "oh-my-opencode-windows-x64-baseline": "4.12.1"
80854
80967
  },
80855
80968
  overrides: {
80856
80969
  hono: "^4.12.18",
@@ -81841,7 +81954,7 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
81841
81954
  // packages/omo-opencode/src/hooks/codegraph-bootstrap/hook.ts
81842
81955
  init_src();
81843
81956
  import { existsSync as existsSync65 } from "fs";
81844
- import { homedir as homedir20 } from "os";
81957
+ import { homedir as homedir21 } from "os";
81845
81958
  import { join as join75 } from "path";
81846
81959
 
81847
81960
  // packages/omo-opencode/src/hooks/codegraph-bootstrap/command-runner.ts
@@ -81989,7 +82102,7 @@ function defaultSchedule(task) {
81989
82102
  timer.unref?.();
81990
82103
  }
81991
82104
  function defaultInstallDir2() {
81992
- return join75(homedir20(), ".omo", "codegraph");
82105
+ return join75(homedir21(), ".omo", "codegraph");
81993
82106
  }
81994
82107
  function provisionedBinFromInstallDir(installDir) {
81995
82108
  if (installDir === undefined)
@@ -82120,7 +82233,7 @@ function createCodegraphBootstrapHook(ctx, config, depsOverride = {}) {
82120
82233
  }
82121
82234
  // packages/omo-opencode/src/hooks/ast-grep-sg-provision/hook.ts
82122
82235
  init_src();
82123
- import { homedir as homedir21 } from "os";
82236
+ import { homedir as homedir22 } from "os";
82124
82237
  import { join as join76 } from "path";
82125
82238
  var provisionedTargets = new Set;
82126
82239
  function defaultSchedule2(task) {
@@ -82140,7 +82253,7 @@ async function runProvision(targetDir, deps) {
82140
82253
  }
82141
82254
  var defaultDeps5 = {
82142
82255
  findSgBinary: findSgBinarySync,
82143
- homeDir: homedir21,
82256
+ homeDir: homedir22,
82144
82257
  log: log2,
82145
82258
  provisionSgBinary,
82146
82259
  schedule: defaultSchedule2
@@ -90342,7 +90455,7 @@ import { dirname as dirname28 } from "path";
90342
90455
  init_resolve_commands_in_text();
90343
90456
  // packages/skills-loader-core/src/features/opencode-skill-loader/loader.ts
90344
90457
  import { join as join88 } from "path";
90345
- import { homedir as homedir25 } from "os";
90458
+ import { homedir as homedir26 } from "os";
90346
90459
 
90347
90460
  // packages/shared-skills/index.mjs
90348
90461
  import { fileURLToPath as fileURLToPath5 } from "url";
@@ -90351,21 +90464,21 @@ function sharedSkillsRootPath() {
90351
90464
  }
90352
90465
 
90353
90466
  // packages/skills-loader-core/src/shared/claude-config-dir.ts
90354
- import { homedir as homedir23 } from "os";
90467
+ import { homedir as homedir24 } from "os";
90355
90468
  import { join as join82 } from "path";
90356
90469
  function getClaudeConfigDir2() {
90357
90470
  const envConfigDir = process.env.CLAUDE_CONFIG_DIR;
90358
90471
  if (envConfigDir) {
90359
90472
  return envConfigDir;
90360
90473
  }
90361
- return join82(homedir23(), ".claude");
90474
+ return join82(homedir24(), ".claude");
90362
90475
  }
90363
90476
  // packages/skills-loader-core/src/shared/opencode-command-dirs.ts
90364
90477
  import { basename as basename13, dirname as dirname24, join as join84 } from "path";
90365
90478
 
90366
90479
  // packages/skills-loader-core/src/shared/opencode-config-dir.ts
90367
90480
  import { existsSync as existsSync70, realpathSync as realpathSync11 } from "fs";
90368
- import { homedir as homedir24 } from "os";
90481
+ import { homedir as homedir25 } from "os";
90369
90482
  import { join as join83, posix as posix4, resolve as resolve19, win32 as win325 } from "path";
90370
90483
 
90371
90484
  // packages/skills-loader-core/src/shared/plugin-identity.ts
@@ -90399,14 +90512,14 @@ function getTauriConfigDir2(identifier) {
90399
90512
  const platform2 = process.platform;
90400
90513
  switch (platform2) {
90401
90514
  case "darwin":
90402
- return join83(homedir24(), "Library", "Application Support", identifier);
90515
+ return join83(homedir25(), "Library", "Application Support", identifier);
90403
90516
  case "win32": {
90404
- const appData = process.env.APPDATA || join83(homedir24(), "AppData", "Roaming");
90517
+ const appData = process.env.APPDATA || join83(homedir25(), "AppData", "Roaming");
90405
90518
  return win325.join(appData, identifier);
90406
90519
  }
90407
90520
  case "linux":
90408
90521
  default: {
90409
- const xdgConfig = process.env.XDG_CONFIG_HOME || join83(homedir24(), ".config");
90522
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join83(homedir25(), ".config");
90410
90523
  return join83(xdgConfig, identifier);
90411
90524
  }
90412
90525
  }
@@ -90450,7 +90563,7 @@ function getWslLinuxHomeDir2(windowsConfigRoot) {
90450
90563
  function getCliDefaultConfigDir2() {
90451
90564
  const envXdgConfig = process.env.XDG_CONFIG_HOME?.trim();
90452
90565
  const shouldIgnoreWindowsXdg = envXdgConfig !== undefined && envXdgConfig.length > 0 && isWslEnvironment2() && isWindowsUserConfigRoot2(envXdgConfig);
90453
- const xdgConfig = shouldIgnoreWindowsXdg ? posix4.join(getWslLinuxHomeDir2(envXdgConfig) ?? "/home", ".config") : envXdgConfig || join83(homedir24(), ".config");
90566
+ const xdgConfig = shouldIgnoreWindowsXdg ? posix4.join(getWslLinuxHomeDir2(envXdgConfig) ?? "/home", ".config") : envXdgConfig || join83(homedir25(), ".config");
90454
90567
  const configDir = isWslEnvironment2() ? posix4.join(xdgConfig, "opencode") : join83(xdgConfig, "opencode");
90455
90568
  return resolveConfigPath2(configDir);
90456
90569
  }
@@ -91025,7 +91138,7 @@ async function loadProjectAgentsSkills(directory) {
91025
91138
  const allSkills = await Promise.all(agentsProjectSkillDirs.map((skillsDir) => loadSkillsFromDir({ skillsDir, scope: "project" })));
91026
91139
  return skillsToCommandDefinitionRecord(deduplicateSkillsByName(allSkills.flat()));
91027
91140
  }
91028
- async function loadGlobalAgentsSkills(homeDirectory = homedir25()) {
91141
+ async function loadGlobalAgentsSkills(homeDirectory = homedir26()) {
91029
91142
  const agentsGlobalDir = join88(homeDirectory, ".agents", "skills");
91030
91143
  const skills = await loadSkillsFromDir({ skillsDir: agentsGlobalDir, scope: "user" });
91031
91144
  return skillsToCommandDefinitionRecord(skills);
@@ -91123,7 +91236,7 @@ async function discoverProjectAgentsSkills(directory) {
91123
91236
  const allSkills = await Promise.all(agentsProjectSkillDirs.map((skillsDir) => loadSkillsFromDir({ skillsDir, scope: "project" })));
91124
91237
  return deduplicateSkillsByName(allSkills.flat());
91125
91238
  }
91126
- async function discoverGlobalAgentsSkills(homeDirectory = homedir25()) {
91239
+ async function discoverGlobalAgentsSkills(homeDirectory = homedir26()) {
91127
91240
  const agentsGlobalDir = join88(homeDirectory, ".agents", "skills");
91128
91241
  return loadSkillsFromDir({ skillsDir: agentsGlobalDir, scope: "user" });
91129
91242
  }
@@ -91154,14 +91267,14 @@ function builtinToLoadedSkill(builtin) {
91154
91267
  init_src();
91155
91268
  import { existsSync as existsSync72, readFileSync as readFileSync46 } from "fs";
91156
91269
  import { dirname as dirname26, isAbsolute as isAbsolute13, resolve as resolve22 } from "path";
91157
- import { homedir as homedir26 } from "os";
91270
+ import { homedir as homedir27 } from "os";
91158
91271
  function resolveFilePath5(from, configDir) {
91159
91272
  let filePath = from;
91160
91273
  if (filePath.startsWith("{file:") && filePath.endsWith("}")) {
91161
91274
  filePath = filePath.slice(6, -1);
91162
91275
  }
91163
91276
  if (filePath.startsWith("~/")) {
91164
- return resolve22(homedir26(), filePath.slice(2));
91277
+ return resolve22(homedir27(), filePath.slice(2));
91165
91278
  }
91166
91279
  if (isAbsolute13(filePath)) {
91167
91280
  return filePath;
@@ -94402,7 +94515,7 @@ function isDisabledSkillName(name, disabledSkills) {
94402
94515
  init_src();
94403
94516
  var import_picomatch2 = __toESM(require_picomatch2(), 1);
94404
94517
  import * as fs20 from "fs/promises";
94405
- import { homedir as homedir27 } from "os";
94518
+ import { homedir as homedir28 } from "os";
94406
94519
  import { dirname as dirname27, extname as extname2, isAbsolute as isAbsolute14, join as join90, relative as relative12 } from "path";
94407
94520
  var MAX_RECURSIVE_DEPTH = 10;
94408
94521
  function isHttpUrl(path17) {
@@ -94410,10 +94523,10 @@ function isHttpUrl(path17) {
94410
94523
  }
94411
94524
  function toAbsolutePath(path17, configDir) {
94412
94525
  if (path17 === "~") {
94413
- return homedir27();
94526
+ return homedir28();
94414
94527
  }
94415
94528
  if (path17.startsWith("~/")) {
94416
- return join90(homedir27(), path17.slice(2));
94529
+ return join90(homedir28(), path17.slice(2));
94417
94530
  }
94418
94531
  if (isAbsolute14(path17)) {
94419
94532
  return path17;
@@ -100740,7 +100853,7 @@ function buildRetryGuidance(errorInfo) {
100740
100853
  if (!pattern) {
100741
100854
  return `[task ERROR] Fix the error and retry with correct parameters.`;
100742
100855
  }
100743
- let guidance = `
100856
+ let guidance2 = `
100744
100857
  [task CALL FAILED - IMMEDIATE RETRY REQUIRED]
100745
100858
 
100746
100859
  **Error Type**: ${errorInfo.errorType}
@@ -100748,11 +100861,11 @@ function buildRetryGuidance(errorInfo) {
100748
100861
  `;
100749
100862
  const availableList = extractAvailableList(errorInfo.originalOutput);
100750
100863
  if (availableList) {
100751
- guidance += `
100864
+ guidance2 += `
100752
100865
  **Available Options**: ${availableList}
100753
100866
  `;
100754
100867
  }
100755
- guidance += `
100868
+ guidance2 += `
100756
100869
  **Action**: Retry task NOW with corrected parameters.
100757
100870
 
100758
100871
  Example of CORRECT call:
@@ -100766,7 +100879,7 @@ function buildRetryGuidance(errorInfo) {
100766
100879
  )
100767
100880
  \`\`\`
100768
100881
  `;
100769
- return guidance;
100882
+ return guidance2;
100770
100883
  }
100771
100884
  // packages/omo-opencode/src/hooks/delegate-task-retry/hook.ts
100772
100885
  function createDelegateTaskRetryHook(_ctx) {
@@ -100778,9 +100891,9 @@ function createDelegateTaskRetryHook(_ctx) {
100778
100891
  return;
100779
100892
  const errorInfo = detectDelegateTaskError(output.output);
100780
100893
  if (errorInfo) {
100781
- const guidance = buildRetryGuidance(errorInfo);
100894
+ const guidance2 = buildRetryGuidance(errorInfo);
100782
100895
  output.output += `
100783
- ${guidance}`;
100896
+ ${guidance2}`;
100784
100897
  }
100785
100898
  }
100786
100899
  };
@@ -110801,18 +110914,18 @@ import { existsSync as existsSync95, readdirSync as readdirSync23 } from "fs";
110801
110914
  import { join as join108 } from "path";
110802
110915
 
110803
110916
  // packages/claude-code-compat-core/src/shared/claude-config-dir.ts
110804
- import { homedir as homedir28 } from "os";
110917
+ import { homedir as homedir29 } from "os";
110805
110918
  import { join as join103 } from "path";
110806
110919
  function getClaudeConfigDir3() {
110807
110920
  const envConfigDir = process.env.CLAUDE_CONFIG_DIR;
110808
110921
  if (envConfigDir) {
110809
110922
  return envConfigDir;
110810
110923
  }
110811
- return join103(process.env.HOME || process.env.USERPROFILE || homedir28(), ".claude");
110924
+ return join103(process.env.HOME || process.env.USERPROFILE || homedir29(), ".claude");
110812
110925
  }
110813
110926
  // packages/claude-code-compat-core/src/shared/opencode-config-dir.ts
110814
110927
  import { existsSync as existsSync91, realpathSync as realpathSync15 } from "fs";
110815
- import { homedir as homedir29 } from "os";
110928
+ import { homedir as homedir30 } from "os";
110816
110929
  import { join as join104, posix as posix7, resolve as resolve33, win32 as win3210 } from "path";
110817
110930
  var TAURI_APP_IDENTIFIER3 = "ai.opencode.desktop";
110818
110931
  var TAURI_APP_IDENTIFIER_DEV3 = "ai.opencode.desktop.dev";
@@ -110825,14 +110938,14 @@ function getTauriConfigDir3(identifier) {
110825
110938
  const platform2 = process.platform;
110826
110939
  switch (platform2) {
110827
110940
  case "darwin":
110828
- return join104(homedir29(), "Library", "Application Support", identifier);
110941
+ return join104(homedir30(), "Library", "Application Support", identifier);
110829
110942
  case "win32": {
110830
- const appData = process.env.APPDATA || join104(homedir29(), "AppData", "Roaming");
110943
+ const appData = process.env.APPDATA || join104(homedir30(), "AppData", "Roaming");
110831
110944
  return win3210.join(appData, identifier);
110832
110945
  }
110833
110946
  case "linux":
110834
110947
  default: {
110835
- const xdgConfig = process.env.XDG_CONFIG_HOME || join104(homedir29(), ".config");
110948
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join104(homedir30(), ".config");
110836
110949
  return join104(xdgConfig, identifier);
110837
110950
  }
110838
110951
  }
@@ -110876,7 +110989,7 @@ function getWslLinuxHomeDir3(windowsConfigRoot) {
110876
110989
  function getCliDefaultConfigDir3() {
110877
110990
  const envXdgConfig = process.env.XDG_CONFIG_HOME?.trim();
110878
110991
  const shouldIgnoreWindowsXdg = envXdgConfig !== undefined && envXdgConfig.length > 0 && isWslEnvironment3() && isWindowsUserConfigRoot3(envXdgConfig);
110879
- const xdgConfig = shouldIgnoreWindowsXdg ? posix7.join(getWslLinuxHomeDir3(envXdgConfig) ?? "/home", ".config") : envXdgConfig || join104(homedir29(), ".config");
110992
+ const xdgConfig = shouldIgnoreWindowsXdg ? posix7.join(getWslLinuxHomeDir3(envXdgConfig) ?? "/home", ".config") : envXdgConfig || join104(homedir30(), ".config");
110880
110993
  const configDir = isWslEnvironment3() ? posix7.join(xdgConfig, "opencode") : join104(xdgConfig, "opencode");
110881
110994
  return resolveConfigPath3(configDir);
110882
110995
  }
@@ -110921,11 +111034,11 @@ function getOpenCodeConfigDir3(options) {
110921
111034
  // packages/claude-code-compat-core/src/shared/jsonc-parser.ts
110922
111035
  init_src();
110923
111036
  // packages/claude-code-compat-core/src/shared/resolve-agent-definition-paths.ts
110924
- import { homedir as homedir30 } from "os";
111037
+ import { homedir as homedir31 } from "os";
110925
111038
  import { isAbsolute as isAbsolute18, join as join105, resolve as resolve34 } from "path";
110926
111039
  function resolveAgentDefinitionPaths2(paths, baseDir, containmentDir) {
110927
111040
  return paths.flatMap((p) => {
110928
- const expanded = p.startsWith("~/") ? join105(homedir30(), p.slice(2)) : p;
111041
+ const expanded = p.startsWith("~/") ? join105(homedir31(), p.slice(2)) : p;
110929
111042
  const resolved = isAbsolute18(expanded) ? expanded : resolve34(baseDir, expanded);
110930
111043
  if (containmentDir !== null && !isWithinProject(resolved, containmentDir)) {
110931
111044
  log4(`agent_definitions path rejected (outside project boundary): ${p} -> ${resolved}`);
@@ -111456,9 +111569,7 @@ Description: ${task.description}
111456
111569
  Agent: ${task.agent} (subagent)
111457
111570
  Status: ${task.status}
111458
111571
 
111459
- System notifies on completion. Use \`background_output\` with task_id="${task.id}" to check.
111460
-
111461
- Do NOT call background_output now. Wait for <system-reminder> notification first.`;
111572
+ Do NOT call background_output now. Wait for <system-reminder> notification first. The system will deliver the result when the task completes; you do not need to poll for it.`;
111462
111573
  } catch (error) {
111463
111574
  const message = error instanceof Error ? error.message : String(error);
111464
111575
  return `Failed to launch background agent task: ${message}`;
@@ -113708,9 +113819,7 @@ Agent: ${task.agent}
113708
113819
  Status: ${task.status}
113709
113820
 
113710
113821
  Agent continues with full previous context preserved.
113711
- System notifies on completion. Use \`background_output\` with task_id="${backgroundTaskId}" to check.
113712
-
113713
- Do NOT call background_output now. Wait for <system-reminder> notification first.
113822
+ Do NOT call background_output now. Wait for <system-reminder> notification first. The system will deliver the result when the task completes; you do not need to poll for it.
113714
113823
 
113715
113824
  ${buildTaskMetadataBlock({
113716
113825
  sessionId,
@@ -113764,10 +113873,60 @@ function getTimingConfig() {
113764
113873
  };
113765
113874
  }
113766
113875
 
113767
- // packages/omo-opencode/src/tools/delegate-task/sync-session-poller.ts
113768
- init_logger2();
113876
+ // packages/omo-opencode/src/tools/delegate-task/sync-session-turns.ts
113769
113877
  var NON_TERMINAL_FINISH_REASONS = new Set(["tool-calls", "unknown"]);
113770
113878
  var PENDING_TOOL_PART_TYPES = new Set(["tool", "tool_use", "tool-call"]);
113879
+ var ALL_BACKGROUND_TASKS_COMPLETE_MARKER = "[ALL BACKGROUND TASKS COMPLETE]";
113880
+ function getTextParts2(message) {
113881
+ return (message.parts ?? []).filter((part) => part.type === "text").map((part) => part.text ?? "").join(`
113882
+ `);
113883
+ }
113884
+ function isInternalAllCompleteWake(message) {
113885
+ return isTerminalNoReplyUserMessage(message) && getTextParts2(message).includes(ALL_BACKGROUND_TASKS_COMPLETE_MARKER);
113886
+ }
113887
+ function getLastSessionTurns(messages) {
113888
+ let lastRelevantUser;
113889
+ let lastAssistant;
113890
+ for (let i = messages.length - 1;i >= 0; i--) {
113891
+ const msg = messages[i];
113892
+ if (msg === undefined)
113893
+ continue;
113894
+ if (!lastAssistant && msg.info?.role === "assistant")
113895
+ lastAssistant = msg;
113896
+ if (!lastRelevantUser && msg.info?.role === "user" && !isInternalAllCompleteWake(msg)) {
113897
+ lastRelevantUser = msg;
113898
+ }
113899
+ if (lastRelevantUser && lastAssistant)
113900
+ break;
113901
+ }
113902
+ return { lastAssistant, lastRelevantUser };
113903
+ }
113904
+ function isSessionComplete(messages) {
113905
+ const { lastAssistant, lastRelevantUser } = getLastSessionTurns(messages);
113906
+ if (!lastAssistant?.info?.finish)
113907
+ return false;
113908
+ if (NON_TERMINAL_FINISH_REASONS.has(lastAssistant.info.finish))
113909
+ return false;
113910
+ if (lastAssistant.parts?.some((part) => part.type && PENDING_TOOL_PART_TYPES.has(part.type)))
113911
+ return false;
113912
+ if (!lastRelevantUser?.info?.id || !lastAssistant?.info?.id)
113913
+ return false;
113914
+ return lastRelevantUser.info.id < lastAssistant.info.id;
113915
+ }
113916
+ function getTerminalSessionError(messages) {
113917
+ const { lastAssistant, lastRelevantUser } = getLastSessionTurns(messages);
113918
+ if (lastRelevantUser?.info?.id && lastAssistant?.info?.id && lastAssistant.info.id <= lastRelevantUser.info.id) {
113919
+ return null;
113920
+ }
113921
+ if (!lastAssistant?.info || !("error" in lastAssistant.info)) {
113922
+ return null;
113923
+ }
113924
+ const errorMessage = extractErrorMessage(lastAssistant.info.error);
113925
+ return errorMessage && errorMessage.length > 0 ? errorMessage : "Session error";
113926
+ }
113927
+
113928
+ // packages/omo-opencode/src/tools/delegate-task/sync-session-poller.ts
113929
+ init_logger2();
113771
113930
  var ACTIVE_SESSION_STATUSES2 = new Set(["busy", "retry", "running"]);
113772
113931
  var CHILD_WAKE_GRACE_MS = 5000;
113773
113932
  function wait(milliseconds) {
@@ -113794,40 +113953,6 @@ async function fetchSessionMessages(client3, sessionID) {
113794
113953
  const rawData = messagesResult?.data ?? messagesResult;
113795
113954
  return Array.isArray(rawData) ? rawData : [];
113796
113955
  }
113797
- function getTerminalSessionError(messages) {
113798
- const lastAssistant = [...messages].reverse().find((msg) => msg.info?.role === "assistant");
113799
- const lastUser = [...messages].reverse().find((msg) => msg.info?.role === "user");
113800
- if (lastUser?.info?.id && lastAssistant?.info?.id && lastAssistant.info.id <= lastUser.info.id) {
113801
- return null;
113802
- }
113803
- if (!lastAssistant?.info || !("error" in lastAssistant.info)) {
113804
- return null;
113805
- }
113806
- const errorMessage = extractErrorMessage(lastAssistant.info.error);
113807
- return errorMessage && errorMessage.length > 0 ? errorMessage : "Session error";
113808
- }
113809
- function isSessionComplete(messages) {
113810
- let lastUser;
113811
- let lastAssistant;
113812
- for (let i = messages.length - 1;i >= 0; i--) {
113813
- const msg = messages[i];
113814
- if (!lastAssistant && msg.info?.role === "assistant")
113815
- lastAssistant = msg;
113816
- if (!lastUser && msg.info?.role === "user")
113817
- lastUser = msg;
113818
- if (lastUser && lastAssistant)
113819
- break;
113820
- }
113821
- if (!lastAssistant?.info?.finish)
113822
- return false;
113823
- if (NON_TERMINAL_FINISH_REASONS.has(lastAssistant.info.finish))
113824
- return false;
113825
- if (lastAssistant.parts?.some((part) => part.type && PENDING_TOOL_PART_TYPES.has(part.type)))
113826
- return false;
113827
- if (!lastUser?.info?.id || !lastAssistant?.info?.id)
113828
- return false;
113829
- return lastUser.info.id < lastAssistant.info.id;
113830
- }
113831
113956
  var DEFAULT_MAX_ASSISTANT_TURNS = 300;
113832
113957
  async function pollSyncSession(ctx, client3, input, timeoutMs) {
113833
113958
  const syncTiming = getTimingConfig();
@@ -113870,11 +113995,12 @@ async function pollSyncSession(ctx, client3, input, timeoutMs) {
113870
113995
  finalMessages = await fetchSessionMessages(client3, input.sessionID);
113871
113996
  break;
113872
113997
  } catch (error) {
113998
+ const errorMessage = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
113873
113999
  log2("[task] Final messages fetch failed after abort, retrying", {
113874
114000
  sessionID: input.sessionID,
113875
114001
  attempt,
113876
114002
  maxAttempts: abortFetchAttempts,
113877
- error: String(error)
114003
+ error: errorMessage
113878
114004
  });
113879
114005
  if (attempt < abortFetchAttempts) {
113880
114006
  await wait(syncTiming.POLL_INTERVAL_MS);
@@ -113924,7 +114050,8 @@ Session ID: ${input.sessionID}`;
113924
114050
  try {
113925
114051
  messages = await fetchSessionMessages(client3, input.sessionID);
113926
114052
  } catch (error) {
113927
- log2("[task] Poll messages fetch failed, retrying", { sessionID: input.sessionID, error: String(error) });
114053
+ const errorMessage = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
114054
+ log2("[task] Poll messages fetch failed, retrying", { sessionID: input.sessionID, error: errorMessage });
113928
114055
  continue;
113929
114056
  }
113930
114057
  if (input.anchorMessageCount !== undefined && messages.length <= input.anchorMessageCount) {
@@ -114706,9 +114833,7 @@ Description: ${task.description}
114706
114833
  Agent: ${task.agent}${args.category ? ` (category: ${args.category})` : ""}
114707
114834
  Status: ${task.status}
114708
114835
 
114709
- System notifies on completion. Use \`background_output\` with task_id="${task.id}" to check.
114710
-
114711
- Do NOT call background_output now. Wait for <system-reminder> notification first.${taskMetadataBlock}`;
114836
+ Do NOT call background_output now. Wait for <system-reminder> notification first. The system will deliver the result when the task completes; you do not need to poll for it.${taskMetadataBlock}`;
114712
114837
  } catch (error) {
114713
114838
  return formatDetailedError(error, {
114714
114839
  operation: "Launch background task",
@@ -119356,9 +119481,38 @@ function timestampFromUnknown(value) {
119356
119481
  }
119357
119482
  return;
119358
119483
  }
119484
+ function latestTimestamp(...values) {
119485
+ let latest;
119486
+ for (const value of values) {
119487
+ const timestamp = timestampFromUnknown(value);
119488
+ if (timestamp === undefined) {
119489
+ continue;
119490
+ }
119491
+ if (latest === undefined || timestamp > latest) {
119492
+ latest = timestamp;
119493
+ }
119494
+ }
119495
+ return latest;
119496
+ }
119497
+ function latestTimeActivity(time) {
119498
+ if (!time) {
119499
+ return;
119500
+ }
119501
+ return latestTimestamp(time.created, time.updated, time.completed, time.start, time.end);
119502
+ }
119359
119503
  function getParentWakeMessageCreatedAt(message) {
119360
119504
  return timestampFromUnknown(message.info?.time?.created ?? message.time?.created);
119361
119505
  }
119506
+ function getParentWakeMessageActivityAt(message) {
119507
+ let latest = latestTimestamp(latestTimeActivity(message.info?.time), latestTimeActivity(message.time));
119508
+ for (const part of message.parts ?? []) {
119509
+ const partActivity = latestTimestamp(latestTimeActivity(part.time), latestTimeActivity(part.state?.time));
119510
+ if (partActivity !== undefined && (latest === undefined || partActivity > latest)) {
119511
+ latest = partActivity;
119512
+ }
119513
+ }
119514
+ return latest;
119515
+ }
119362
119516
 
119363
119517
  // packages/omo-opencode/src/features/background-agent/parent-wake-history-state.ts
119364
119518
  function latestAssistantTurnIsCompletedEmptyNoProgress(messages) {
@@ -119408,6 +119562,20 @@ function latestAssistantTurnHasFreshToolActivity(messages, now, maxAgeMs) {
119408
119562
  }
119409
119563
  return false;
119410
119564
  }
119565
+ function latestAssistantTurnHasStaleUnknownSubstantiveOutput(messages, now, maxAgeMs) {
119566
+ for (let index = messages.length - 1;index >= 0; index--) {
119567
+ const message = messages[index];
119568
+ const role = messageRole(message);
119569
+ if (role === "assistant") {
119570
+ const finish = messageFinish(message);
119571
+ return (finish === undefined || finish === "unknown") && !messageCompleted(message) && messageHasSubstantiveAssistantOutput(message) && !messageHasFreshActivity(message, now, maxAgeMs);
119572
+ }
119573
+ if (role === "user" && !messageIsSyntheticOrInternalUser(message)) {
119574
+ return false;
119575
+ }
119576
+ }
119577
+ return false;
119578
+ }
119411
119579
  function createEmptyAssistantTurnRetryDedupeKey(wake) {
119412
119580
  return [
119413
119581
  "background-agent-parent-wake-empty-retry",
@@ -119422,6 +119590,13 @@ function partHasFreshToolActivity(part, now, maxAgeMs) {
119422
119590
  }
119423
119591
  return timeHasFreshActivity(part.time, now, maxAgeMs) || timeHasFreshActivity(isRecord(part.state) ? part.state.time : undefined, now, maxAgeMs);
119424
119592
  }
119593
+ function messageHasFreshActivity(message, now, maxAgeMs) {
119594
+ if (!isRecord(message)) {
119595
+ return false;
119596
+ }
119597
+ const activityAt = getParentWakeMessageActivityAt(message);
119598
+ return activityAt !== undefined && now - activityAt <= maxAgeMs;
119599
+ }
119425
119600
  function timeHasFreshActivity(time, now, maxAgeMs) {
119426
119601
  if (!isRecord(time)) {
119427
119602
  return false;
@@ -119612,6 +119787,22 @@ class ParentWakeFlushRunner {
119612
119787
  });
119613
119788
  return;
119614
119789
  }
119790
+ const finalToolWaitDecision = await this.confirmParentWakeStillSafeForReply(sessionID, latestWake, toolWaitDecision);
119791
+ if (finalToolWaitDecision.defer) {
119792
+ if (this.deferReplyWakeWhileUnsafe(sessionID, latestWake)) {
119793
+ return;
119794
+ }
119795
+ await this.sendParentWakePrompt(sessionID, latestWake, {
119796
+ emptyAssistantTurnRetry,
119797
+ toolWaitDecision: { ...finalToolWaitDecision, skipPromptGateToolStateCheck: true },
119798
+ forceNoReply: true,
119799
+ retainPendingWake: latestWake.shouldReply
119800
+ });
119801
+ log2("[background-agent] Recorded admit-only parent wake because parent session history became unsafe:", {
119802
+ sessionID
119803
+ });
119804
+ return;
119805
+ }
119615
119806
  const dispatchedWake = this.deps.dispatchedTracker.getWake(sessionID);
119616
119807
  if (dispatchedWake && isRedundantParentWake(latestWake, dispatchedWake)) {
119617
119808
  this.deps.pendingQueue.deleteWake(sessionID);
@@ -119620,7 +119811,7 @@ class ParentWakeFlushRunner {
119620
119811
  }
119621
119812
  await this.sendParentWakePrompt(sessionID, latestWake, {
119622
119813
  emptyAssistantTurnRetry,
119623
- toolWaitDecision
119814
+ toolWaitDecision: finalToolWaitDecision
119624
119815
  });
119625
119816
  }
119626
119817
  schedulePendingParentWakeFlush(sessionID, delayMs) {
@@ -119691,6 +119882,12 @@ class ParentWakeFlushRunner {
119691
119882
  async shouldDeferParentWakeForSessionHistory(sessionID, wake) {
119692
119883
  return this.deps.sessionInspector.shouldDeferForHistory(sessionID, wake);
119693
119884
  }
119885
+ async confirmParentWakeStillSafeForReply(sessionID, wake, decision) {
119886
+ if (!decision.skipPromptGateToolStateCheck) {
119887
+ return decision;
119888
+ }
119889
+ return this.deps.sessionInspector.shouldDeferForHistory(sessionID, wake);
119890
+ }
119694
119891
  requeueWake(sessionID, latestWake) {
119695
119892
  this.deps.pendingQueue.requeueWake(sessionID, latestWake);
119696
119893
  }
@@ -119858,6 +120055,12 @@ function getParentWakeSessionHistoryDeferralDecision(input) {
119858
120055
  log2("[background-agent] Holding parent wake during stale tool-call deferral:", { sessionID: input.sessionID });
119859
120056
  return { defer: true, skipPromptGateToolStateCheck: true };
119860
120057
  }
120058
+ if (now - input.wake.toolCallDeferralStartedAt >= input.toolCallDeferMaxMs && latestAssistantTurnHasStaleUnknownSubstantiveOutput(messages, now, input.toolCallDeferMaxMs)) {
120059
+ log2("[background-agent] Retrying parent wake after stale unknown-finish assistant output:", {
120060
+ sessionID: input.sessionID
120061
+ });
120062
+ return { defer: false, skipPromptGateToolStateCheck: true };
120063
+ }
119861
120064
  log2("[background-agent] Deferred parent wake because latest assistant turn blocks internal prompts:", {
119862
120065
  sessionID: input.sessionID
119863
120066
  });
@@ -124894,7 +125097,7 @@ import { basename as basename22, dirname as dirname39, join as join120 } from "p
124894
125097
 
124895
125098
  // packages/mcp-client-core/src/config-dir.ts
124896
125099
  import { existsSync as existsSync100, realpathSync as realpathSync17 } from "fs";
124897
- import { homedir as homedir31 } from "os";
125100
+ import { homedir as homedir32 } from "os";
124898
125101
  import { join as join118, resolve as resolve36 } from "path";
124899
125102
  function resolveConfigPath4(pathValue) {
124900
125103
  const resolvedPath = resolve36(pathValue);
@@ -124913,7 +125116,7 @@ function getOpenCodeCliConfigDir(env2 = process.env) {
124913
125116
  if (customConfigDir) {
124914
125117
  return resolveConfigPath4(customConfigDir);
124915
125118
  }
124916
- const xdgConfigDir = env2["XDG_CONFIG_HOME"]?.trim() || join118(homedir31(), ".config");
125119
+ const xdgConfigDir = env2["XDG_CONFIG_HOME"]?.trim() || join118(homedir32(), ".config");
124917
125120
  return resolveConfigPath4(join118(xdgConfigDir, "opencode"));
124918
125121
  }
124919
125122
 
@@ -130466,10 +130669,10 @@ import { dirname as dirname40 } from "path";
130466
130669
  // packages/omo-opencode/src/features/tui-sidebar/mirror-path.ts
130467
130670
  import { createHash as createHash8 } from "crypto";
130468
130671
  import { realpathSync as realpathSync18 } from "fs";
130469
- import { homedir as homedir32 } from "os";
130672
+ import { homedir as homedir33 } from "os";
130470
130673
  import { join as join121, resolve as resolve37 } from "path";
130471
130674
  function mirrorStorageDir() {
130472
- return join121(process.env.XDG_DATA_HOME ?? join121(homedir32(), ".local", "share"), "opencode", "storage", "oh-my-openagent", MIRROR_DIR_NAME);
130675
+ return join121(process.env.XDG_DATA_HOME ?? join121(homedir33(), ".local", "share"), "opencode", "storage", "oh-my-openagent", MIRROR_DIR_NAME);
130473
130676
  }
130474
130677
  function canonicalProjectDir(projectDir) {
130475
130678
  try {
@@ -133344,11 +133547,11 @@ import {
133344
133547
 
133345
133548
  // packages/openclaw-core/src/reply-listener-paths.ts
133346
133549
  import { existsSync as existsSync103, mkdirSync as mkdirSync22 } from "fs";
133347
- import { homedir as homedir33 } from "os";
133550
+ import { homedir as homedir34 } from "os";
133348
133551
  import { join as join123 } from "path";
133349
133552
  var REPLY_LISTENER_SECURE_FILE_MODE = 384;
133350
133553
  function resolveReplyListenerHomeDir() {
133351
- return process.env.HOME ?? process.env.USERPROFILE ?? homedir33();
133554
+ return process.env.HOME ?? process.env.USERPROFILE ?? homedir34();
133352
133555
  }
133353
133556
  function getReplyListenerStateDir() {
133354
133557
  return join123(resolveReplyListenerHomeDir(), ".omo", "openclaw", "state");
@@ -134551,7 +134754,7 @@ async function createRuntimeSkillSourceServer(options, runtimeEnv = runtime6) {
134551
134754
  // packages/claude-code-compat-core/src/features/claude-code-mcp-loader/loader.ts
134552
134755
  import { existsSync as existsSync108, readFileSync as readFileSync75 } from "fs";
134553
134756
  import { join as join126 } from "path";
134554
- import { homedir as homedir34 } from "os";
134757
+ import { homedir as homedir35 } from "os";
134555
134758
  function getMcpConfigPaths() {
134556
134759
  const claudeConfigDir = getClaudeConfigDir3();
134557
134760
  const homeDir = getHomeDir();
@@ -134564,7 +134767,7 @@ function getMcpConfigPaths() {
134564
134767
  ];
134565
134768
  }
134566
134769
  function getHomeDir() {
134567
- return process.env.HOME || process.env.USERPROFILE || homedir34();
134770
+ return process.env.HOME || process.env.USERPROFILE || homedir35();
134568
134771
  }
134569
134772
  async function loadMcpConfigFile(filePath) {
134570
134773
  if (!existsSync108(filePath)) {
@@ -141493,14 +141696,14 @@ function createHephaestusAgent(model, availableAgents, availableToolNames, avail
141493
141696
  createHephaestusAgent.mode = MODE9;
141494
141697
  // packages/omo-opencode/src/agents/builtin-agents/resolve-file-uri.ts
141495
141698
  import { existsSync as existsSync109, readFileSync as readFileSync76 } from "fs";
141496
- import { homedir as homedir35 } from "os";
141699
+ import { homedir as homedir36 } from "os";
141497
141700
  import { isAbsolute as isAbsolute20, join as join127, resolve as resolve38 } from "path";
141498
141701
  init_logger2();
141499
141702
  var ALLOWED_HOME_SUBDIRS = [
141500
- join127(homedir35(), ".config", "opencode"),
141501
- join127(homedir35(), ".config", "oh-my-openagent"),
141502
- join127(homedir35(), ".omo"),
141503
- join127(homedir35(), ".opencode")
141703
+ join127(homedir36(), ".config", "opencode"),
141704
+ join127(homedir36(), ".config", "oh-my-openagent"),
141705
+ join127(homedir36(), ".omo"),
141706
+ join127(homedir36(), ".opencode")
141504
141707
  ];
141505
141708
  function isWithinAllowedPaths(filePath, projectRoot) {
141506
141709
  if (isWithinProject(filePath, projectRoot))
@@ -141518,7 +141721,7 @@ function resolvePromptAppend(promptAppend, configDir) {
141518
141721
  let filePath;
141519
141722
  try {
141520
141723
  const decoded = decodeURIComponent(encoded);
141521
- const expanded = decoded.startsWith("~/") ? decoded.replace(/^~\//, `${homedir35()}/`) : decoded;
141724
+ const expanded = decoded.startsWith("~/") ? decoded.replace(/^~\//, `${homedir36()}/`) : decoded;
141522
141725
  filePath = isAbsolute20(expanded) ? expanded : resolve38(configDir ?? process.cwd(), expanded);
141523
141726
  } catch (error) {
141524
141727
  if (!(error instanceof Error)) {
@@ -144898,7 +145101,7 @@ async function loadPluginComponents(params) {
144898
145101
  const errorMessage = error instanceof Error ? error.message : String(error);
144899
145102
  log2("[config-handler] Plugin loading failed", { error: errorMessage });
144900
145103
  addConfigLoadError({ path: "plugin-loading", error: errorMessage });
144901
- return EMPTY_PLUGIN_COMPONENTS;
145104
+ return { ...EMPTY_PLUGIN_COMPONENTS, retryableLoadFailure: true };
144902
145105
  }
144903
145106
  }
144904
145107
 
@@ -145037,8 +145240,38 @@ function collectTrustedVisionCapableModels(pluginConfig) {
145037
145240
  }
145038
145241
  return trusted;
145039
145242
  }
145243
+ function cloneConfigValue(value) {
145244
+ if (Array.isArray(value)) {
145245
+ return value.map(cloneConfigValue);
145246
+ }
145247
+ if (typeof value === "object" && value !== null) {
145248
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, cloneConfigValue(entry)]));
145249
+ }
145250
+ return value;
145251
+ }
145252
+ function cloneAgentConfig(agents) {
145253
+ return cloneConfigValue(agents);
145254
+ }
145255
+ function createAgentConfigCacheKey(config) {
145256
+ return JSON.stringify({
145257
+ agent: config.agent,
145258
+ default_agent: config.default_agent,
145259
+ model: config.model,
145260
+ skills: config.skills
145261
+ });
145262
+ }
145263
+ function replayAgentConfigSideEffects(params) {
145264
+ if (params.configuredDefaultAgent && typeof params.defaultAgent === "string") {
145265
+ setDefaultAgentForSort(params.defaultAgent);
145266
+ }
145267
+ clearRegisteredAgentNames();
145268
+ for (const name of Object.keys(params.agentResult)) {
145269
+ registerAgentName(name);
145270
+ }
145271
+ }
145040
145272
  function createConfigHandler(deps) {
145041
145273
  const { ctx, pluginConfig, modelCacheState, runtimeSkillSourceUrl } = deps;
145274
+ let agentConfigSnapshot;
145042
145275
  return async (config) => {
145043
145276
  const formatterConfig = config.formatter;
145044
145277
  setAdditionalAllowedMcpEnvVars(pluginConfig.mcp_env_allowlist ?? []);
@@ -145049,13 +145282,36 @@ function createConfigHandler(deps) {
145049
145282
  });
145050
145283
  clearFormatterCache();
145051
145284
  const pluginComponents = await loadPluginComponents({ pluginConfig });
145285
+ const pluginComponentsLoadFailed = pluginComponents.retryableLoadFailure === true;
145052
145286
  applyHookConfig({ pluginComponents });
145053
- const agentResult = await applyAgentConfig({
145054
- config,
145055
- pluginConfig,
145056
- ctx,
145057
- pluginComponents
145058
- });
145287
+ const agentCacheKey = createAgentConfigCacheKey(config);
145288
+ let agentResult;
145289
+ if (!pluginComponentsLoadFailed && agentConfigSnapshot?.cacheKey === agentCacheKey) {
145290
+ config.agent = cloneAgentConfig(agentConfigSnapshot.agents);
145291
+ if (agentConfigSnapshot.defaultAgent !== undefined) {
145292
+ config.default_agent = agentConfigSnapshot.defaultAgent;
145293
+ }
145294
+ agentResult = config.agent;
145295
+ replayAgentConfigSideEffects({
145296
+ agentResult,
145297
+ configuredDefaultAgent: agentConfigSnapshot.configuredDefaultAgent,
145298
+ defaultAgent: config.default_agent
145299
+ });
145300
+ } else {
145301
+ const configuredDefaultAgent = getConfiguredDefaultAgent(config);
145302
+ agentResult = await applyAgentConfig({
145303
+ config,
145304
+ pluginConfig,
145305
+ ctx,
145306
+ pluginComponents
145307
+ });
145308
+ agentConfigSnapshot = pluginComponentsLoadFailed ? undefined : {
145309
+ cacheKey: agentCacheKey,
145310
+ configuredDefaultAgent,
145311
+ defaultAgent: config.default_agent,
145312
+ agents: cloneAgentConfig(agentResult)
145313
+ };
145314
+ }
145059
145315
  applyToolConfig({ config, pluginConfig, agentResult });
145060
145316
  await applyMcpConfig({ config, pluginConfig, ctx, pluginComponents });
145061
145317
  await applyCommandConfig({ config, pluginConfig, ctx, pluginComponents });
@@ -149790,6 +150046,7 @@ function createToolDefinitionHandler(args) {
149790
150046
  }
149791
150047
 
149792
150048
  // packages/omo-opencode/src/plugin/tool-execute-after.ts
150049
+ init_src();
149793
150050
  init_logger2();
149794
150051
  var VERIFICATION_ATTEMPT_PATTERN = /<ulw_verification_attempt_id>(.*?)<\/ulw_verification_attempt_id>/i;
149795
150052
  var METADATA_LINKED_TOOLS = new Set([
@@ -149815,12 +150072,25 @@ function getPluginDirectory(ctx) {
149815
150072
  function expectsRecoverableMetadata(tool3) {
149816
150073
  return METADATA_LINKED_TOOLS.has(tool3);
149817
150074
  }
150075
+ function appendCodegraphInitGuidance(input, output, cwd) {
150076
+ const guidance2 = buildCodegraphInitGuidanceForToolResult({
150077
+ cwd: cwd ?? undefined,
150078
+ toolName: input.tool,
150079
+ toolOutput: output.output
150080
+ });
150081
+ if (guidance2 === null || output.output.includes(guidance2))
150082
+ return;
150083
+ output.output = `${output.output}
150084
+
150085
+ ${guidance2}`;
150086
+ }
149818
150087
  function createToolExecuteAfterHandler3(args) {
149819
150088
  const { ctx, hooks } = args;
149820
150089
  const log8 = args.log ?? log2;
149821
150090
  return async (input, output) => {
149822
150091
  if (!output)
149823
150092
  return;
150093
+ appendCodegraphInitGuidance(input, output, getPluginDirectory(ctx));
149824
150094
  const hookInput = {
149825
150095
  tool: input.tool,
149826
150096
  sessionID: input.sessionID,
@@ -149975,6 +150245,15 @@ async function resolveSessionAgent(client3, sessionId) {
149975
150245
  // packages/omo-opencode/src/plugin/tool-execute-before.ts
149976
150246
  init_constants3();
149977
150247
  init_storage();
150248
+ var BACKGROUND_WAIT_BLOCK_MESSAGE = [
150249
+ "Background task wait is already managed by the plugin.",
150250
+ "End this response now and wait for the <system-reminder> completion notification.",
150251
+ "After that reminder arrives, call background_output with the task_id from the launch result."
150252
+ ].join(" ");
150253
+ function isPureSleepCommand(command) {
150254
+ const commandLines = command.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
150255
+ return commandLines.length > 0 && commandLines.every((line) => /^sleep\s+\d+(?:\.\d+)?[smhd]?\s*$/i.test(line));
150256
+ }
149978
150257
  function getLoopCommandArguments(args, command) {
149979
150258
  const rawUserMessage = typeof args.user_message === "string" ? args.user_message.trim() : "";
149980
150259
  if (rawUserMessage) {
@@ -149984,7 +150263,7 @@ function getLoopCommandArguments(args, command) {
149984
150263
  return rawName.replace(new RegExp(`^/?(${command})\\s*`, "i"), "");
149985
150264
  }
149986
150265
  function createToolExecuteBeforeHandler3(args) {
149987
- const { ctx, hooks } = args;
150266
+ const { ctx, hooks, backgroundManager } = args;
149988
150267
  function buildUltraworkOracleVerificationPrompt(prompt, originalTask, verificationAttemptId) {
149989
150268
  const verificationPrompt = [
149990
150269
  "You are verifying the active ULTRAWORK loop result for this session.",
@@ -150025,6 +150304,9 @@ function createToolExecuteBeforeHandler3(args) {
150025
150304
  callID: input.callID
150026
150305
  });
150027
150306
  }
150307
+ if (isPureSleepCommand(output.args.command) && (backgroundManager?.hasActiveChildTasks(input.sessionID) === true || backgroundManager?.hasPendingParentWake(input.sessionID) === true)) {
150308
+ throw new Error(BACKGROUND_WAIT_BLOCK_MESSAGE);
150309
+ }
150028
150310
  }
150029
150311
  await hooks.writeExistingFileGuard?.["tool.execute.before"]?.(input, output);
150030
150312
  await hooks.notepadWriteGuard?.["tool.execute.before"]?.(input, output);
@@ -150192,7 +150474,8 @@ function createPluginInterface(args) {
150192
150474
  }),
150193
150475
  "tool.execute.before": createToolExecuteBeforeHandler3({
150194
150476
  ctx,
150195
- hooks
150477
+ hooks,
150478
+ backgroundManager: managers.backgroundManager
150196
150479
  }),
150197
150480
  "tool.execute.after": createToolExecuteAfterHandler3({
150198
150481
  ctx,
@@ -150203,7 +150486,7 @@ function createPluginInterface(args) {
150203
150486
 
150204
150487
  // packages/omo-opencode/src/plugin-config/layered-config-loader.ts
150205
150488
  import * as fs25 from "fs";
150206
- import { homedir as homedir36 } from "os";
150489
+ import { homedir as homedir37 } from "os";
150207
150490
  import * as path27 from "path";
150208
150491
 
150209
150492
  // packages/omo-opencode/src/config/schema/agent-names.ts
@@ -151045,7 +151328,7 @@ function loadConfigFromPath2(configPath, _ctx) {
151045
151328
 
151046
151329
  // packages/omo-opencode/src/plugin-config/layered-config-loader.ts
151047
151330
  function resolveHomeDirectory() {
151048
- return process.env.HOME ?? process.env.USERPROFILE ?? homedir36();
151331
+ return process.env.HOME ?? process.env.USERPROFILE ?? homedir37();
151049
151332
  }
151050
151333
  function resolveConfigPathAfterLegacyMigration(detectedPath) {
151051
151334
  if (!path27.basename(detectedPath).startsWith(LEGACY_CONFIG_BASENAME)) {