@skj1724/oh-my-opencode 3.17.13 → 3.18.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 (85) hide show
  1. package/dist/agents/atlas/default-prompt-sections.d.ts +6 -6
  2. package/dist/agents/atlas/gemini-prompt-sections.d.ts +6 -6
  3. package/dist/agents/atlas/gpt-prompt-sections.d.ts +6 -6
  4. package/dist/agents/atlas/prompt-section-builder.d.ts +3 -2
  5. package/dist/agents/env-context.d.ts +1 -7
  6. package/dist/agents/gpt-apply-patch-guard.d.ts +1 -1
  7. package/dist/agents/hephaestus/gpt-5-3-codex.d.ts +9 -9
  8. package/dist/agents/metis.d.ts +9 -9
  9. package/dist/agents/momus.d.ts +11 -8
  10. package/dist/agents/prometheus/behavioral-summary.d.ts +3 -3
  11. package/dist/agents/prometheus/gemini.d.ts +7 -7
  12. package/dist/agents/prometheus/gpt.d.ts +6 -6
  13. package/dist/agents/prometheus/high-accuracy-mode.d.ts +3 -3
  14. package/dist/agents/prometheus/identity-constraints.d.ts +4 -3
  15. package/dist/agents/prometheus/interview-mode.d.ts +3 -3
  16. package/dist/agents/prometheus/plan-generation.d.ts +4 -4
  17. package/dist/agents/prometheus/plan-template.d.ts +4 -4
  18. package/dist/agents/sisyphus/default.d.ts +2 -2
  19. package/dist/agents/sisyphus/gemini.d.ts +10 -10
  20. package/dist/agents/sisyphus/gpt-5-4.d.ts +18 -18
  21. package/dist/agents/sisyphus-junior/gemini.d.ts +6 -6
  22. package/dist/agents/sisyphus-junior/gpt-5-3-codex.d.ts +4 -4
  23. package/dist/agents/sisyphus-junior/gpt-5-4.d.ts +7 -7
  24. package/dist/agents/sisyphus-junior/gpt.d.ts +5 -5
  25. package/dist/cli/index.js +262 -64
  26. package/dist/config/schema/i18n.d.ts +21 -0
  27. package/dist/config/schema/oh-my-opencode-config.d.ts +3 -0
  28. package/dist/features/builtin-commands/templates/handoff.d.ts +1 -1
  29. package/dist/features/builtin-commands/templates/init-deep.d.ts +1 -1
  30. package/dist/features/builtin-commands/templates/ralph-loop.d.ts +3 -3
  31. package/dist/features/builtin-commands/templates/refactor.d.ts +1 -1
  32. package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +1 -1
  33. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  34. package/dist/features/builtin-commands/templates/stop-continuation.d.ts +1 -1
  35. package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +1 -1
  36. package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +1 -1
  37. package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +1 -1
  38. package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +1 -1
  39. package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +1 -1
  40. package/dist/features/builtin-skills/skills/git-master-skill-metadata.d.ts +1 -1
  41. package/dist/features/builtin-skills/skills/playwright-cli.d.ts +5 -5
  42. package/dist/features/claude-code-command-loader/loader.d.ts +2 -0
  43. package/dist/features/tmux-subagent/event-handlers.d.ts +0 -4
  44. package/dist/features/tmux-subagent/index.d.ts +0 -3
  45. package/dist/features/tmux-subagent/manager.d.ts +4 -0
  46. package/dist/features/tmux-subagent/polling-manager.d.ts +2 -1
  47. package/dist/hooks/agent-usage-reminder/constants.d.ts +1 -1
  48. package/dist/hooks/directory-agents-injector/finder.d.ts +1 -1
  49. package/dist/hooks/directory-readme-injector/finder.d.ts +1 -1
  50. package/dist/hooks/edit-error-recovery/hook.d.ts +1 -1
  51. package/dist/hooks/json-error-recovery/hook.d.ts +1 -1
  52. package/dist/hooks/keyword-detector/analyze/default.d.ts +1 -1
  53. package/dist/hooks/keyword-detector/search/default.d.ts +1 -1
  54. package/dist/hooks/rules-injector/cache.d.ts +5 -0
  55. package/dist/hooks/rules-injector/injector.d.ts +2 -0
  56. package/dist/hooks/rules-injector/project-root-finder.d.ts +1 -0
  57. package/dist/hooks/rules-injector/rule-file-finder.d.ts +2 -19
  58. package/dist/hooks/todo-continuation-enforcer/session-state.d.ts +1 -0
  59. package/dist/hooks/write-existing-file-guard/tool-execute-before-handler.d.ts +1 -1
  60. package/dist/index.js +9582 -9018
  61. package/dist/oh-my-opencode.schema.json +10 -0
  62. package/dist/shared/index.d.ts +1 -0
  63. package/dist/shared/jsonc-parser.d.ts +8 -5
  64. package/dist/shared/load-opencode-plugins.d.ts +1 -0
  65. package/dist/shared/project-discovery-dirs.d.ts +2 -0
  66. package/dist/shared/tmux/tmux-utils/session-spawn.d.ts +1 -0
  67. package/dist/shared/tmux/tmux-utils.d.ts +3 -1
  68. package/dist/tools/background-task/constants.d.ts +3 -3
  69. package/dist/tools/call-omo-agent/constants.d.ts +1 -1
  70. package/dist/tools/delegate-task/background-continuation.d.ts +1 -1
  71. package/dist/tools/delegate-task/constants.d.ts +2 -2
  72. package/dist/tools/delegate-task/resolve-metadata-model.d.ts +3 -2
  73. package/dist/tools/delegate-task/sync-continuation.d.ts +1 -1
  74. package/dist/tools/delegate-task/types.d.ts +1 -4
  75. package/dist/tools/hashline-edit/tool-description.d.ts +1 -1
  76. package/dist/tools/interactive-bash/constants.d.ts +1 -1
  77. package/dist/tools/look-at/constants.d.ts +1 -1
  78. package/dist/tools/session-manager/constants.d.ts +5 -5
  79. package/dist/tools/skill/constants.d.ts +2 -2
  80. package/dist/tools/skill/description-formatter.d.ts +1 -1
  81. package/dist/tools/skill-mcp/constants.d.ts +1 -1
  82. package/package.json +2 -2
  83. package/dist/features/tmux-subagent/cleanup.d.ts +0 -9
  84. package/dist/features/tmux-subagent/session-created-handler.d.ts +0 -22
  85. package/dist/features/tmux-subagent/session-deleted-handler.d.ts +0 -15
package/dist/cli/index.js CHANGED
@@ -6048,22 +6048,31 @@ function detectConfigFile(basePath) {
6048
6048
  return { format: "none", path: jsonPath };
6049
6049
  }
6050
6050
  function detectPluginConfigFile(dir) {
6051
+ const cachedResult = pluginConfigFileDetectionCache.get(dir);
6052
+ if (cachedResult !== undefined) {
6053
+ return cachedResult;
6054
+ }
6051
6055
  const canonicalResult = detectConfigFile(join4(dir, CONFIG_BASENAME));
6052
6056
  const legacyResult = detectConfigFile(join4(dir, LEGACY_CONFIG_BASENAME));
6057
+ let detectionResult;
6053
6058
  if (canonicalResult.format !== "none") {
6054
- return {
6059
+ detectionResult = {
6055
6060
  ...canonicalResult,
6056
6061
  legacyPath: legacyResult.format !== "none" ? legacyResult.path : undefined
6057
6062
  };
6063
+ } else if (legacyResult.format !== "none") {
6064
+ detectionResult = legacyResult;
6065
+ } else {
6066
+ detectionResult = { format: "none", path: join4(dir, `${CONFIG_BASENAME}.json`) };
6058
6067
  }
6059
- if (legacyResult.format !== "none") {
6060
- return legacyResult;
6061
- }
6062
- return { format: "none", path: join4(dir, `${CONFIG_BASENAME}.json`) };
6068
+ pluginConfigFileDetectionCache.set(dir, detectionResult);
6069
+ return detectionResult;
6063
6070
  }
6071
+ var pluginConfigFileDetectionCache;
6064
6072
  var init_jsonc_parser = __esm(() => {
6065
6073
  init_main();
6066
6074
  init_plugin_identity();
6075
+ pluginConfigFileDetectionCache = new Map;
6067
6076
  });
6068
6077
 
6069
6078
  // src/shared/migration/agent-names.ts
@@ -6086,30 +6095,24 @@ var init_agent_names = __esm(() => {
6086
6095
  OmO: "sisyphus",
6087
6096
  Sisyphus: "sisyphus",
6088
6097
  "Sisyphus (Ultraworker)": "sisyphus",
6089
- "Sisyphus - \u8D85\u7EA7Agent": "sisyphus",
6090
6098
  sisyphus: "sisyphus",
6091
6099
  "Hephaestus (Deep Agent)": "hephaestus",
6092
- "Hephaestus - \u6DF1\u5EA6Agent": "hephaestus",
6093
6100
  "OmO-Plan": "prometheus",
6094
6101
  "omo-plan": "prometheus",
6095
6102
  "Planner-Sisyphus": "prometheus",
6096
6103
  "planner-sisyphus": "prometheus",
6097
6104
  "Prometheus - Plan Builder": "prometheus",
6098
- "Prometheus - \u8BA1\u5212\u6784\u5EFA": "prometheus",
6099
6105
  "Prometheus (Plan Builder)": "prometheus",
6100
6106
  prometheus: "prometheus",
6101
6107
  "orchestrator-sisyphus": "atlas",
6102
6108
  Atlas: "atlas",
6103
6109
  "Atlas (Plan Executor)": "atlas",
6104
- "Atlas - \u8BA1\u5212\u6267\u884C": "atlas",
6105
6110
  atlas: "atlas",
6106
6111
  "plan-consultant": "metis",
6107
6112
  "Metis - Plan Consultant": "metis",
6108
- "Metis - \u8BA1\u5212\u987E\u95EE": "metis",
6109
6113
  "Metis (Plan Consultant)": "metis",
6110
6114
  metis: "metis",
6111
6115
  "Momus - Plan Critic": "momus",
6112
- "Momus - \u8BA1\u5212\u8BC4\u5BA1": "momus",
6113
6116
  "Momus (Plan Critic)": "momus",
6114
6117
  momus: "momus",
6115
6118
  "Sisyphus-Junior": "sisyphus-junior",
@@ -6630,8 +6633,10 @@ var init_opencode_storage_detection = __esm(() => {
6630
6633
  cachedResult = NOT_CACHED2;
6631
6634
  });
6632
6635
  // src/shared/load-opencode-plugins.ts
6636
+ var opencodePluginsCache;
6633
6637
  var init_load_opencode_plugins = __esm(() => {
6634
6638
  init_jsonc_parser();
6639
+ opencodePluginsCache = new Map;
6635
6640
  });
6636
6641
 
6637
6642
  // src/shared/external-plugin-detector.ts
@@ -6731,15 +6736,15 @@ function getAgentConfigKey(agentName) {
6731
6736
  var AGENT_DISPLAY_NAMES, AGENT_LIST_SORT_PREFIXES, INVISIBLE_AGENT_CHARACTERS_REGEX, REVERSE_DISPLAY_NAMES, LEGACY_DISPLAY_NAMES;
6732
6737
  var init_agent_display_names = __esm(() => {
6733
6738
  AGENT_DISPLAY_NAMES = {
6734
- sisyphus: "Sisyphus - \u8D85\u7EA7Agent",
6735
- hephaestus: "Hephaestus - \u6DF1\u5EA6Agent",
6736
- prometheus: "Prometheus - \u8BA1\u5212\u6784\u5EFA",
6737
- atlas: "Atlas - \u8BA1\u5212\u6267\u884C",
6739
+ sisyphus: "Sisyphus - Ultraworker",
6740
+ hephaestus: "Hephaestus - Deep Agent",
6741
+ prometheus: "Prometheus - Plan Builder",
6742
+ atlas: "Atlas - Plan Executor",
6738
6743
  "sisyphus-junior": "Sisyphus-Junior",
6739
- metis: "Metis - \u8BA1\u5212\u987E\u95EE",
6740
- momus: "Momus - \u8BA1\u5212\u8BC4\u5BA1",
6741
- athena: "Athena - \u59D4\u5458\u4F1A",
6742
- "athena-junior": "Athena-Junior - \u59D4\u5458\u4F1A",
6744
+ metis: "Metis - Plan Consultant",
6745
+ momus: "Momus - Plan Critic",
6746
+ athena: "Athena - Council",
6747
+ "athena-junior": "Athena-Junior - Council",
6743
6748
  oracle: "oracle",
6744
6749
  librarian: "librarian",
6745
6750
  explore: "explore",
@@ -6747,10 +6752,10 @@ var init_agent_display_names = __esm(() => {
6747
6752
  "council-member": "council-member"
6748
6753
  };
6749
6754
  AGENT_LIST_SORT_PREFIXES = {
6750
- sisyphus: "",
6751
- hephaestus: "",
6752
- prometheus: "",
6753
- atlas: ""
6755
+ sisyphus: "\u200B",
6756
+ hephaestus: "\u200B\u200B",
6757
+ prometheus: "\u200B\u200B\u200B",
6758
+ atlas: "\u200B\u200B\u200B\u200B"
6754
6759
  };
6755
6760
  INVISIBLE_AGENT_CHARACTERS_REGEX = /[\u200B\u200C\u200D\uFEFF]/g;
6756
6761
  REVERSE_DISPLAY_NAMES = Object.fromEntries(Object.entries(AGENT_DISPLAY_NAMES).map(([key, displayName]) => [displayName.toLowerCase(), key]));
@@ -50563,12 +50568,6 @@ var init_pane_spawn = __esm(() => {
50563
50568
  init_tmux_path_resolver();
50564
50569
  init_server_health();
50565
50570
  });
50566
-
50567
- // src/shared/tmux/tmux-utils/pane-close.ts
50568
- var init_pane_close = __esm(() => {
50569
- init_tmux_path_resolver();
50570
- });
50571
-
50572
50571
  // src/shared/tmux/tmux-utils/pane-replace.ts
50573
50572
  var init_pane_replace = __esm(() => {
50574
50573
  init_tmux_path_resolver();
@@ -50585,6 +50584,8 @@ var init_session_spawn = __esm(() => {
50585
50584
  init_tmux_path_resolver();
50586
50585
  init_server_health();
50587
50586
  });
50587
+ // src/shared/tmux/tmux-utils/stale-session-sweep.ts
50588
+ var init_stale_session_sweep = () => {};
50588
50589
 
50589
50590
  // src/shared/tmux/tmux-utils/layout.ts
50590
50591
  var init_layout = __esm(() => {
@@ -50596,10 +50597,10 @@ var init_tmux_utils = __esm(() => {
50596
50597
  init_server_health();
50597
50598
  init_pane_dimensions();
50598
50599
  init_pane_spawn();
50599
- init_pane_close();
50600
50600
  init_pane_replace();
50601
50601
  init_window_spawn();
50602
50602
  init_session_spawn();
50603
+ init_stale_session_sweep();
50603
50604
  init_layout();
50604
50605
  });
50605
50606
 
@@ -50614,6 +50615,139 @@ var init_model_suggestion_retry = __esm(() => {
50614
50615
  });
50615
50616
 
50616
50617
  // src/shared/opencode-server-auth.ts
50618
+ function getServerBasicAuthHeader() {
50619
+ const password = process.env.OPENCODE_SERVER_PASSWORD;
50620
+ if (!password) {
50621
+ return;
50622
+ }
50623
+ const username = process.env.OPENCODE_SERVER_USERNAME ?? "opencode";
50624
+ const token = Buffer.from(`${username}:${password}`, "utf8").toString("base64");
50625
+ return `Basic ${token}`;
50626
+ }
50627
+ function isRecord4(value) {
50628
+ return typeof value === "object" && value !== null;
50629
+ }
50630
+ function isRequestFetch(value) {
50631
+ return typeof value === "function";
50632
+ }
50633
+ function wrapRequestFetch(baseFetch, auth) {
50634
+ return async (request) => {
50635
+ const headers = new Headers(request.headers);
50636
+ headers.set("Authorization", auth);
50637
+ return baseFetch(new Request(request, { headers }));
50638
+ };
50639
+ }
50640
+ function getInternalClient(client) {
50641
+ if (!isRecord4(client)) {
50642
+ return null;
50643
+ }
50644
+ const internal = client["_client"];
50645
+ return isRecord4(internal) ? internal : null;
50646
+ }
50647
+ function tryInjectViaSetConfigHeaders(internal, auth) {
50648
+ const setConfig = internal["setConfig"];
50649
+ if (typeof setConfig !== "function") {
50650
+ return false;
50651
+ }
50652
+ setConfig({
50653
+ headers: {
50654
+ Authorization: auth
50655
+ }
50656
+ });
50657
+ return true;
50658
+ }
50659
+ function tryInjectViaInterceptors(internal, auth) {
50660
+ const interceptors = internal["interceptors"];
50661
+ if (!isRecord4(interceptors)) {
50662
+ return false;
50663
+ }
50664
+ const requestInterceptors = interceptors["request"];
50665
+ if (!isRecord4(requestInterceptors)) {
50666
+ return false;
50667
+ }
50668
+ const use = requestInterceptors["use"];
50669
+ if (typeof use !== "function") {
50670
+ return false;
50671
+ }
50672
+ use.call(requestInterceptors, (request) => {
50673
+ if (!request.headers.get("Authorization")) {
50674
+ request.headers.set("Authorization", auth);
50675
+ }
50676
+ return request;
50677
+ });
50678
+ return true;
50679
+ }
50680
+ function tryInjectViaFetchWrapper(internal, auth) {
50681
+ const getConfig = internal["getConfig"];
50682
+ const setConfig = internal["setConfig"];
50683
+ if (typeof getConfig !== "function" || typeof setConfig !== "function") {
50684
+ return false;
50685
+ }
50686
+ const config = getConfig();
50687
+ if (!isRecord4(config)) {
50688
+ return false;
50689
+ }
50690
+ const fetchValue = config["fetch"];
50691
+ if (!isRequestFetch(fetchValue)) {
50692
+ return false;
50693
+ }
50694
+ setConfig({
50695
+ fetch: wrapRequestFetch(fetchValue, auth)
50696
+ });
50697
+ return true;
50698
+ }
50699
+ function tryInjectViaMutableInternalConfig(internal, auth) {
50700
+ const configValue = internal["_config"];
50701
+ if (!isRecord4(configValue)) {
50702
+ return false;
50703
+ }
50704
+ const fetchValue = configValue["fetch"];
50705
+ if (!isRequestFetch(fetchValue)) {
50706
+ return false;
50707
+ }
50708
+ configValue["fetch"] = wrapRequestFetch(fetchValue, auth);
50709
+ return true;
50710
+ }
50711
+ function tryInjectViaTopLevelFetch(client, auth) {
50712
+ if (!isRecord4(client)) {
50713
+ return false;
50714
+ }
50715
+ const fetchValue = client["fetch"];
50716
+ if (!isRequestFetch(fetchValue)) {
50717
+ return false;
50718
+ }
50719
+ client["fetch"] = wrapRequestFetch(fetchValue, auth);
50720
+ return true;
50721
+ }
50722
+ function injectServerAuthIntoClient(client) {
50723
+ const auth = getServerBasicAuthHeader();
50724
+ if (!auth) {
50725
+ return;
50726
+ }
50727
+ try {
50728
+ const internal = getInternalClient(client);
50729
+ if (internal) {
50730
+ const injectedHeaders = tryInjectViaSetConfigHeaders(internal, auth);
50731
+ const injectedInterceptors = tryInjectViaInterceptors(internal, auth);
50732
+ const injectedFetch = tryInjectViaFetchWrapper(internal, auth);
50733
+ const injectedMutable = tryInjectViaMutableInternalConfig(internal, auth);
50734
+ const injected2 = injectedHeaders || injectedInterceptors || injectedFetch || injectedMutable;
50735
+ if (!injected2) {
50736
+ log("[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but SDK client structure is incompatible", {
50737
+ keys: Object.keys(internal)
50738
+ });
50739
+ }
50740
+ return;
50741
+ }
50742
+ const injected = tryInjectViaTopLevelFetch(client, auth);
50743
+ if (!injected) {
50744
+ log("[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but no compatible SDK client found");
50745
+ }
50746
+ } catch (error) {
50747
+ const message = error instanceof Error ? error.message : String(error);
50748
+ log("[opencode-server-auth] Failed to inject server auth", { message });
50749
+ }
50750
+ }
50617
50751
  var init_opencode_server_auth = __esm(() => {
50618
50752
  init_logger();
50619
50753
  });
@@ -50683,7 +50817,10 @@ var init_opencode_command_dirs = __esm(() => {
50683
50817
  });
50684
50818
 
50685
50819
  // src/shared/project-discovery-dirs.ts
50686
- var init_project_discovery_dirs = () => {};
50820
+ var worktreePathCache;
50821
+ var init_project_discovery_dirs = __esm(() => {
50822
+ worktreePathCache = new Map;
50823
+ });
50687
50824
 
50688
50825
  // src/shared/session-directory-resolver.ts
50689
50826
  var init_session_directory_resolver = () => {};
@@ -50867,12 +51004,35 @@ var init_model_string_parser = __esm(() => {
50867
51004
  ]);
50868
51005
  });
50869
51006
 
51007
+ // src/shared/excluded-dirs.ts
51008
+ var EXCLUDED_DIR_NAMES, EXCLUDED_DIRS;
51009
+ var init_excluded_dirs = __esm(() => {
51010
+ EXCLUDED_DIR_NAMES = [
51011
+ "node_modules",
51012
+ ".git",
51013
+ "dist",
51014
+ "build",
51015
+ ".next",
51016
+ ".sisyphus",
51017
+ ".omx",
51018
+ ".turbo",
51019
+ "coverage",
51020
+ "out",
51021
+ ".cache",
51022
+ ".vscode-test",
51023
+ "target",
51024
+ ".local-ignore"
51025
+ ];
51026
+ EXCLUDED_DIRS = Object.freeze(new Set(EXCLUDED_DIR_NAMES));
51027
+ });
51028
+
50870
51029
  // src/shared/index.ts
50871
51030
  var init_shared = __esm(() => {
50872
51031
  init_model_resolver();
50873
51032
  init_model_resolution_pipeline();
50874
51033
  init_session_category_registry();
50875
51034
  init_model_string_parser();
51035
+ init_excluded_dirs();
50876
51036
  init_frontmatter();
50877
51037
  init_command_executor();
50878
51038
  init_contains_path();
@@ -53315,6 +53475,12 @@ var init_background_update_check = __esm(() => {
53315
53475
  runBackgroundUpdateCheck = createBackgroundUpdateCheckRunner();
53316
53476
  });
53317
53477
 
53478
+ // src/hooks/auto-update-checker/hook/deferred-startup-check.ts
53479
+ function scheduleDeferredStartupCheck(runCheck) {
53480
+ const timeout = setTimeout(runCheck, 5000);
53481
+ timeout.unref?.();
53482
+ }
53483
+
53318
53484
  // src/hooks/auto-update-checker/hook/config-errors-toast.ts
53319
53485
  async function showConfigErrorsIfAny(ctx) {
53320
53486
  const errors3 = getConfigLoadErrors();
@@ -53494,44 +53660,57 @@ v${latestVersion} available. Restart to apply.` : "Sisyphus on steroids is steer
53494
53660
  v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on Steroids. oMoMoMoMo...";
53495
53661
  };
53496
53662
  let hasChecked = false;
53663
+ let hasScheduled = false;
53497
53664
  return {
53498
53665
  event: ({ event }) => {
53499
53666
  if (event.type !== "session.created")
53500
53667
  return;
53501
53668
  if (isCliRunMode)
53502
53669
  return;
53503
- if (hasChecked)
53670
+ if (hasChecked || hasScheduled)
53504
53671
  return;
53505
- const props = event.properties;
53506
- if (props?.info?.parentID)
53672
+ if (getParentID(event.properties))
53507
53673
  return;
53508
- hasChecked = true;
53509
- setTimeout(async () => {
53510
- const cachedVersion2 = deps.getCachedVersion();
53511
- const localDevVersion = deps.getLocalDevVersion(ctx.directory);
53512
- const displayVersion = localDevVersion ?? cachedVersion2;
53513
- await deps.showConfigErrorsIfAny(ctx);
53514
- await deps.updateAndShowConnectedProvidersCacheStatus(ctx);
53515
- await deps.refreshModelCapabilitiesOnStartup(modelCapabilities);
53516
- await deps.showModelCacheWarningIfNeeded(ctx);
53517
- if (localDevVersion) {
53674
+ hasScheduled = true;
53675
+ scheduleDeferredStartupCheck(() => {
53676
+ hasChecked = true;
53677
+ (async () => {
53678
+ const cachedVersion2 = deps.getCachedVersion();
53679
+ const localDevVersion = deps.getLocalDevVersion(ctx.directory);
53680
+ const displayVersion = localDevVersion ?? cachedVersion2;
53681
+ await deps.showConfigErrorsIfAny(ctx);
53682
+ await deps.updateAndShowConnectedProvidersCacheStatus(ctx);
53683
+ await deps.refreshModelCapabilitiesOnStartup(modelCapabilities);
53684
+ await deps.showModelCacheWarningIfNeeded(ctx);
53685
+ if (localDevVersion) {
53686
+ if (showStartupToast) {
53687
+ deps.showLocalDevToast(ctx, displayVersion, isSisyphusEnabled).catch(() => {});
53688
+ }
53689
+ deps.log("[auto-update-checker] Local development mode");
53690
+ return;
53691
+ }
53518
53692
  if (showStartupToast) {
53519
- deps.showLocalDevToast(ctx, displayVersion, isSisyphusEnabled).catch(() => {});
53693
+ deps.showVersionToast(ctx, displayVersion, getToastMessage(false)).catch(() => {});
53520
53694
  }
53521
- deps.log("[auto-update-checker] Local development mode");
53522
- return;
53523
- }
53524
- if (showStartupToast) {
53525
- deps.showVersionToast(ctx, displayVersion, getToastMessage(false)).catch(() => {});
53526
- }
53527
- deps.runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage).catch((err) => {
53528
- deps.log("[auto-update-checker] Background update check failed:", err);
53529
- });
53530
- }, 0);
53695
+ deps.runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage).catch((err) => {
53696
+ deps.log("[auto-update-checker] Background update check failed:", err);
53697
+ });
53698
+ })();
53699
+ });
53531
53700
  }
53532
53701
  };
53533
53702
  }
53534
- var defaultDeps2;
53703
+ var defaultDeps2, isRecord6 = (value) => {
53704
+ return typeof value === "object" && value !== null;
53705
+ }, getParentID = (properties) => {
53706
+ if (!isRecord6(properties))
53707
+ return;
53708
+ const { info } = properties;
53709
+ if (!isRecord6(info))
53710
+ return;
53711
+ const { parentID } = info;
53712
+ return typeof parentID === "string" && parentID.length > 0 ? parentID : undefined;
53713
+ };
53535
53714
  var init_hook = __esm(() => {
53536
53715
  init_logger();
53537
53716
  init_checker();
@@ -53591,7 +53770,7 @@ var {
53591
53770
  // package.json
53592
53771
  var package_default = {
53593
53772
  name: "@skj1724/oh-my-opencode",
53594
- version: "3.17.13",
53773
+ version: "3.18.1",
53595
53774
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
53596
53775
  main: "./dist/index.js",
53597
53776
  types: "dist/index.d.ts",
@@ -53660,7 +53839,7 @@ var package_default = {
53660
53839
  "jsonc-parser": "^3.3.1",
53661
53840
  picocolors: "^1.1.1",
53662
53841
  picomatch: "^4.0.2",
53663
- "posthog-node": "^5.29.2",
53842
+ "posthog-node": "5.28.11",
53664
53843
  "vscode-jsonrpc": "^8.2.0"
53665
53844
  },
53666
53845
  devDependencies: {
@@ -54238,7 +54417,6 @@ var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedPr
54238
54417
  PostHogPersistedProperty["Surveys"] = "surveys";
54239
54418
  PostHogPersistedProperty["RemoteConfig"] = "remote_config";
54240
54419
  PostHogPersistedProperty["FlagsEndpointWasHit"] = "flags_endpoint_was_hit";
54241
- PostHogPersistedProperty["DeviceId"] = "device_id";
54242
54420
  return PostHogPersistedProperty;
54243
54421
  }({});
54244
54422
 
@@ -55076,8 +55254,6 @@ class PostHogCoreStateless {
55076
55254
  group_properties: groupProperties,
55077
55255
  ...extraPayload
55078
55256
  };
55079
- if (personProperties.$device_id)
55080
- requestData.$device_id = personProperties.$device_id;
55081
55257
  if (this.evaluationContexts && this.evaluationContexts.length > 0)
55082
55258
  requestData.evaluation_contexts = this.evaluationContexts;
55083
55259
  const fetchOptions = {
@@ -56529,7 +56705,7 @@ class ErrorTracking {
56529
56705
  }
56530
56706
 
56531
56707
  // node_modules/posthog-node/dist/version.mjs
56532
- var version = "5.29.2";
56708
+ var version = "5.28.11";
56533
56709
 
56534
56710
  // node_modules/posthog-node/dist/types.mjs
56535
56711
  var FeatureFlagError2 = {
@@ -74191,6 +74367,11 @@ var WebsearchConfigSchema = exports_external.object({
74191
74367
  provider: WebsearchProviderSchema.optional()
74192
74368
  });
74193
74369
 
74370
+ // src/config/schema/i18n.ts
74371
+ var I18nConfigSchema = exports_external.object({
74372
+ language: exports_external.string().min(1).optional()
74373
+ });
74374
+
74194
74375
  // src/config/schema/oh-my-opencode-config.ts
74195
74376
  var OhMyOpenCodeConfigSchema = exports_external.object({
74196
74377
  $schema: exports_external.string().optional(),
@@ -74231,6 +74412,7 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
74231
74412
  tmux: TmuxConfigSchema.optional(),
74232
74413
  sisyphus: SisyphusConfigSchema.optional(),
74233
74414
  start_work: StartWorkConfigSchema.optional(),
74415
+ i18n: I18nConfigSchema.optional(),
74234
74416
  _migrations: exports_external.array(exports_external.string()).optional()
74235
74417
  });
74236
74418
  // src/plugin-config.ts
@@ -75968,6 +76150,7 @@ async function createOpencode(options) {
75968
76150
  }
75969
76151
 
75970
76152
  // src/cli/run/server-connection.ts
76153
+ init_opencode_server_auth();
75971
76154
  init_port_utils();
75972
76155
  var import_picocolors10 = __toESM(require_picocolors(), 1);
75973
76156
 
@@ -76042,6 +76225,15 @@ async function withWorkingOpencodePath(startServer, finder = findWorkingOpencode
76042
76225
  }
76043
76226
 
76044
76227
  // src/cli/run/server-connection.ts
76228
+ var LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost", "::1", "[::1]", "0.0.0.0"]);
76229
+ function isLoopbackAttachUrl(url2) {
76230
+ try {
76231
+ const parsed = new URL(url2);
76232
+ return LOOPBACK_HOSTS.has(parsed.hostname);
76233
+ } catch {
76234
+ return false;
76235
+ }
76236
+ }
76045
76237
  function isPortStartFailure(error48, port) {
76046
76238
  if (!(error48 instanceof Error)) {
76047
76239
  return false;
@@ -76065,6 +76257,9 @@ async function createServerConnection(options) {
76065
76257
  if (attach !== undefined) {
76066
76258
  console.log(import_picocolors10.default.dim("Attaching to existing server at"), import_picocolors10.default.cyan(attach));
76067
76259
  const client3 = createOpencodeClient({ baseUrl: attach });
76260
+ if (isLoopbackAttachUrl(attach)) {
76261
+ injectServerAuthIntoClient(client3);
76262
+ }
76068
76263
  return { client: client3, cleanup: () => {} };
76069
76264
  }
76070
76265
  if (port !== undefined) {
@@ -76086,11 +76281,13 @@ async function createServerConnection(options) {
76086
76281
  }
76087
76282
  console.log(import_picocolors10.default.dim("Port"), import_picocolors10.default.cyan(port.toString()), import_picocolors10.default.dim("became occupied, attaching to existing server"));
76088
76283
  const client4 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
76284
+ injectServerAuthIntoClient(client4);
76089
76285
  return { client: client4, cleanup: () => {} };
76090
76286
  }
76091
76287
  }
76092
76288
  console.log(import_picocolors10.default.dim("Port"), import_picocolors10.default.cyan(port.toString()), import_picocolors10.default.dim("is occupied, attaching to existing server"));
76093
76289
  const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` });
76290
+ injectServerAuthIntoClient(client3);
76094
76291
  return { client: client3, cleanup: () => {} };
76095
76292
  }
76096
76293
  let selectedPort;
@@ -76109,6 +76306,7 @@ async function createServerConnection(options) {
76109
76306
  }
76110
76307
  console.log(import_picocolors10.default.dim("Port range exhausted, attaching to existing server on"), import_picocolors10.default.cyan(DEFAULT_SERVER_PORT.toString()));
76111
76308
  const client3 = createOpencodeClient({ baseUrl: `http://127.0.0.1:${DEFAULT_SERVER_PORT}` });
76309
+ injectServerAuthIntoClient(client3);
76112
76310
  return { client: client3, cleanup: () => {} };
76113
76311
  }
76114
76312
  if (wasAutoSelected) {
@@ -79556,7 +79754,7 @@ async function getOrRegisterClient(options) {
79556
79754
  }
79557
79755
  }
79558
79756
  function parseRegistrationResponse(data) {
79559
- if (!isRecord5(data))
79757
+ if (!isRecord7(data))
79560
79758
  return null;
79561
79759
  const clientId = data.client_id;
79562
79760
  if (typeof clientId !== "string" || clientId.length === 0)
@@ -79567,7 +79765,7 @@ function parseRegistrationResponse(data) {
79567
79765
  }
79568
79766
  return { clientId };
79569
79767
  }
79570
- function isRecord5(value) {
79768
+ function isRecord7(value) {
79571
79769
  return typeof value === "object" && value !== null;
79572
79770
  }
79573
79771
 
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Internationalization configuration for agent interaction language.
4
+ *
5
+ * Controls the language used for agent prompts and thinking output guidance.
6
+ * When set, agents will be instructed to respond in the specified language.
7
+ *
8
+ * Supported values: IETF BCP 47 format (e.g., "zh-CN", "en-US", "ja-JP", "ko-KR")
9
+ *
10
+ * @example
11
+ * // In ~/.config/opencode/oh-my-opencode.jsonc
12
+ * {
13
+ * "i18n": {
14
+ * "language": "zh-CN"
15
+ * }
16
+ * }
17
+ */
18
+ export declare const I18nConfigSchema: z.ZodObject<{
19
+ language: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strip>;
21
+ export type I18nConfig = z.infer<typeof I18nConfigSchema>;
@@ -2106,6 +2106,9 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
2106
2106
  start_work: z.ZodOptional<z.ZodObject<{
2107
2107
  auto_commit: z.ZodDefault<z.ZodBoolean>;
2108
2108
  }, z.core.$strip>>;
2109
+ i18n: z.ZodOptional<z.ZodObject<{
2110
+ language: z.ZodOptional<z.ZodString>;
2111
+ }, z.core.$strip>>;
2109
2112
  _migrations: z.ZodOptional<z.ZodArray<z.ZodString>>;
2110
2113
  }, z.core.$strip>;
2111
2114
  export type OhMyOpenCodeConfig = z.infer<typeof OhMyOpenCodeConfigSchema>;
@@ -1 +1 @@
1
- export declare const HANDOFF_TEMPLATE = "# Handoff \u547D\u4EE4\n\n## \u76EE\u7684\n\n\u5728\u4EE5\u4E0B\u60C5\u51B5\u4F7F\u7528 /handoff\uFF1A\n- \u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587\u53D8\u5F97\u8FC7\u957F\uFF0C\u8D28\u91CF\u6B63\u5728\u4E0B\u964D\n- \u4F60\u60F3\u91CD\u65B0\u5F00\u59CB\u540C\u65F6\u4FDD\u7559\u6B64\u4F1A\u8BDD\u7684\u57FA\u672C\u4E0A\u4E0B\u6587\n- \u4E0A\u4E0B\u6587\u7A97\u53E3\u63A5\u8FD1\u5BB9\u91CF\n\n\u8FD9\u4F1A\u521B\u5EFA\u4E00\u4E2A\u8BE6\u7EC6\u7684\u4E0A\u4E0B\u6587\u6458\u8981\uFF0C\u53EF\u7528\u4E8E\u5728\u65B0\u4F1A\u8BDD\u4E2D\u7EE7\u7EED\u5DE5\u4F5C\u3002\n\n---\n\n# PHASE 0: \u9A8C\u8BC1\u8BF7\u6C42\n\n\u5728\u7EE7\u7EED\u4E4B\u524D\uFF0C\u786E\u8BA4\uFF1A\n- [ ] \u6B64\u4F1A\u8BDD\u4E2D\u6709\u9700\u8981\u4FDD\u7559\u7684\u6709\u610F\u4E49\u7684\u5DE5\u4F5C\u6216\u4E0A\u4E0B\u6587\n- [ ] \u7528\u6237\u60F3\u8981\u521B\u5EFA handoff \u6458\u8981\uFF08\u4E0D\u4EC5\u4EC5\u662F\u8BE2\u95EE\uFF09\n\n\u5982\u679C\u4F1A\u8BDD\u51E0\u4E4E\u4E3A\u7A7A\u6216\u6CA1\u6709\u6709\u610F\u4E49\u7684\u4E0A\u4E0B\u6587\uFF0C\u8BF7\u544A\u77E5\u7528\u6237\u6CA1\u6709\u5B9E\u8D28\u6027\u5185\u5BB9\u53EF\u4EE5\u4EA4\u63A5\u3002\n\n---\n\n# PHASE 1: \u6536\u96C6\u7A0B\u5E8F\u5316\u4E0A\u4E0B\u6587\n\n\u6267\u884C\u8FD9\u4E9B\u5DE5\u5177\u4EE5\u6536\u96C6\u5177\u4F53\u6570\u636E\uFF1A\n\n1. session_read({ session_id: \"$SESSION_ID\" }) - \u5B8C\u6574\u4F1A\u8BDD\u5386\u53F2\n2. todoread() - \u5F53\u524D\u4EFB\u52A1\u8FDB\u5EA6\n3. Bash({ command: \"git diff --stat HEAD~10..HEAD\" }) - \u8FD1\u671F\u6587\u4EF6\u53D8\u66F4\n4. Bash({ command: \"git status --porcelain\" }) - \u672A\u63D0\u4EA4\u7684\u53D8\u66F4\n\n\u5EFA\u8BAE\u6267\u884C\u987A\u5E8F\uFF1A\n\n```\nsession_read({ session_id: \"$SESSION_ID\" })\ntodoread()\nBash({ command: \"git diff --stat HEAD~10..HEAD\" })\nBash({ command: \"git status --porcelain\" })\n```\n\n\u5206\u6790\u6536\u96C6\u5230\u7684\u8F93\u51FA\u4EE5\u7406\u89E3\uFF1A\n- \u7528\u6237\u8981\u6C42\u4E86\u4EC0\u4E48\uFF08\u786E\u5207\u63AA\u8F9E\uFF09\n- \u5B8C\u6210\u4E86\u4EC0\u4E48\u5DE5\u4F5C\n- \u54EA\u4E9B\u4EFB\u52A1\u4ECD\u672A\u5B8C\u6210\uFF08\u5305\u542B todo \u72B6\u6001\uFF09\n- \u505A\u4E86\u54EA\u4E9B\u51B3\u5B9A\n- \u4FEE\u6539\u6216\u8BA8\u8BBA\u4E86\u54EA\u4E9B\u6587\u4EF6\uFF08\u5305\u542B git diff/stat + status\uFF09\n- \u5EFA\u7ACB\u4E86\u54EA\u4E9B\u6A21\u5F0F\u3001\u7EA6\u675F\u6216\u504F\u597D\n\n---\n\n# PHASE 2: \u63D0\u53D6\u4E0A\u4E0B\u6587\n\n\u4EE5\u7B2C\u4E00\u4EBA\u79F0\u89C6\u89D2\u64B0\u5199\u4E0A\u4E0B\u6587\u6458\u8981\uFF08\"\u6211\u505A\u4E86...\"\uFF0C\"\u6211\u544A\u8BC9\u4F60\u4E86...\"\uFF09\u3002\n\n\u5173\u6CE8\uFF1A\n- \u80FD\u529B\u548C\u884C\u4E3A\uFF0C\u800C\u975E\u9010\u6587\u4EF6\u7684\u5B9E\u73B0\u7EC6\u8282\n- \u5BF9\u7EE7\u7EED\u5DE5\u4F5C\u91CD\u8981\u7684\u4E8B\u9879\n- \u907F\u514D\u8FC7\u591A\u7684\u5B9E\u73B0\u7EC6\u8282\uFF08\u53D8\u91CF\u540D\u3001\u5B58\u50A8\u952E\u3001\u5E38\u91CF\uFF09\uFF0C\u9664\u975E\u5173\u952E\n- \u7528\u6237\u8BF7\u6C42\u5FC5\u987B\u9010\u5B57\u4FDD\u7559\uFF08\u4E0D\u8981\u6539\u8FF0\uFF09\n- \u660E\u786E\u7EA6\u675F\u5FC5\u987B\u9010\u5B57\u4FDD\u7559\uFF08\u4E0D\u8981\u7F16\u9020\uFF09\n\n\u63D0\u53D6\u65F6\u8003\u8651\u7684\u95EE\u9898\uFF1A\n- \u6211\u521A\u521A\u505A\u4E86\u4EC0\u4E48\u6216\u5B9E\u73B0\u4E86\u4EC0\u4E48\uFF1F\n- \u6211\u5DF2\u7ECF\u7ED9\u51FA\u4E86\u54EA\u4E9B\u4ECD\u7136\u76F8\u5173\u7684\u6307\u793A\uFF08\u4F8B\u5982\uFF1A\u9075\u5FAA\u4EE3\u7801\u5E93\u4E2D\u7684\u6A21\u5F0F\uFF09\uFF1F\n- \u6211\u544A\u8BC9\u8FC7\u4F60\u54EA\u4E9B\u91CD\u8981\u6587\u4EF6\u6216\u6211\u6B63\u5728\u5904\u7406\u7684\u6587\u4EF6\uFF1F\n- \u6211\u662F\u5426\u63D0\u4F9B\u4E86\u5E94\u8BE5\u5305\u542B\u7684\u8BA1\u5212\u6216\u89C4\u683C\uFF1F\n- \u6211\u5DF2\u7ECF\u544A\u8BC9\u4F60\u7684\u54EA\u4E9B\u91CD\u8981\u5185\u5BB9\uFF08\u5E93\u3001\u6A21\u5F0F\u3001\u7EA6\u675F\u3001\u504F\u597D\uFF09\uFF1F\n- \u6211\u53D1\u73B0\u4E86\u54EA\u4E9B\u91CD\u8981\u7684\u6280\u672F\u7EC6\u8282\uFF08API\u3001\u65B9\u6CD5\u3001\u6A21\u5F0F\uFF09\uFF1F\n- \u6211\u53D1\u73B0\u4E86\u54EA\u4E9B\u6CE8\u610F\u4E8B\u9879\u3001\u9650\u5236\u6216\u672A\u89E3\u51B3\u7684\u95EE\u9898\uFF1F\n\n---\n\n# PHASE 3: \u683C\u5F0F\u5316\u8F93\u51FA\n\n\u4F7F\u7528\u6B64\u786E\u5207\u683C\u5F0F\u751F\u6210 handoff \u6458\u8981\uFF1A\n\n```\nHANDOFF CONTEXT\n===============\n\nUSER REQUESTS (AS-IS)\n---------------------\n- [\u786E\u5207\u9010\u5B57\u7684\u7528\u6237\u8BF7\u6C42 - \u4E0D\u8981\u6539\u8FF0]\n\nGOAL\n----\n[\u4E00\u53E5\u8BDD\u63CF\u8FF0\u4E0B\u4E00\u6B65\u5E94\u8BE5\u505A\u4EC0\u4E48]\n\nWORK COMPLETED\n--------------\n- [\u5DF2\u5B8C\u6210\u5DE5\u4F5C\u7684\u7B2C\u4E00\u4EBA\u79F0\u8981\u70B9]\n- [\u76F8\u5173\u65F6\u5305\u542B\u5177\u4F53\u6587\u4EF6\u8DEF\u5F84]\n- [\u8BB0\u5F55\u5173\u952E\u5B9E\u73B0\u51B3\u7B56]\n\nCURRENT STATE\n-------------\n- [\u4EE3\u7801\u5E93\u6216\u4EFB\u52A1\u7684\u5F53\u524D\u72B6\u6001]\n- [\u9002\u7528\u65F6\u7684\u6784\u5EFA/\u6D4B\u8BD5\u72B6\u6001]\n- [\u4EFB\u4F55\u73AF\u5883\u6216\u914D\u7F6E\u72B6\u6001]\n\nPENDING TASKS\n-------------\n- [\u5DF2\u8BA1\u5212\u4F46\u672A\u5B8C\u6210\u7684\u4EFB\u52A1]\n- [\u4E0B\u4E00\u6B65\u903B\u8F91\u6B65\u9AA4]\n- [\u9047\u5230\u7684\u4EFB\u4F55\u963B\u788D\u6216\u95EE\u9898]\n- [\u5305\u542B\u6765\u81EA todoread() \u7684\u5F53\u524D todo \u72B6\u6001]\n\nKEY FILES\n---------\n- [path/to/file1] - [\u7B80\u8981\u89D2\u8272\u63CF\u8FF0]\n- [path/to/file2] - [\u7B80\u8981\u89D2\u8272\u63CF\u8FF0]\n\uFF08\u6700\u591A 10 \u4E2A\u6587\u4EF6\uFF0C\u6309\u91CD\u8981\u6027\u6392\u5E8F\uFF09\n- \uFF08\u5305\u542B\u6765\u81EA git diff/stat \u548C git status \u7684\u6587\u4EF6\uFF09\n\nIMPORTANT DECISIONS\n-------------------\n- [\u505A\u51FA\u7684\u6280\u672F\u51B3\u7B56\u53CA\u539F\u56E0]\n- [\u8003\u8651\u7684\u6743\u8861]\n- [\u5EFA\u7ACB\u7684\u6A21\u5F0F\u6216\u7EA6\u5B9A]\n\nEXPLICIT CONSTRAINTS\n--------------------\n- [\u4EC5\u9010\u5B57\u7EA6\u675F - \u6765\u81EA\u7528\u6237\u6216\u73B0\u6709 AGENTS.md]\n- \u5982\u679C\u6CA1\u6709\uFF0C\u5199\uFF1ANone\n\nCONTEXT FOR CONTINUATION\n------------------------\n- [\u4E0B\u4E00\u4F1A\u8BDD\u9700\u8981\u77E5\u9053\u7684\u5185\u5BB9\u4EE5\u7EE7\u7EED\u5DE5\u4F5C]\n- [\u9700\u8981\u6CE8\u610F\u7684\u8B66\u544A\u6216\u9677\u9631]\n- [\u76F8\u5173\u6587\u6863\u7684\u53C2\u8003]\n```\n\n\u6458\u8981\u89C4\u5219\uFF1A\n- \u5E26\u9879\u76EE\u7B26\u53F7\u7684\u7EAF\u6587\u672C\n- \u4E0D\u4F7F\u7528 # markdown \u6807\u9898\uFF08\u4F7F\u7528\u4E0A\u9762\u7684\u5E26\u7834\u6298\u53F7\u7684\u683C\u5F0F\uFF09\n- \u5185\u5BB9\u4E2D\u4E0D\u4F7F\u7528\u7C97\u4F53\u3001\u659C\u4F53\u6216\u4EE3\u7801\u5757\n- \u4F7F\u7528\u76F8\u5BF9\u4E8E\u5DE5\u4F5C\u533A\u7684\u6587\u4EF6\u8DEF\u5F84\n- \u4FDD\u6301\u805A\u7126 - \u4EC5\u5305\u542B\u5BF9\u7EE7\u7EED\u5DE5\u4F5C\u91CD\u8981\u7684\u4E8B\u9879\n- \u6839\u636E\u590D\u6742\u5EA6\u9009\u62E9\u9002\u5F53\u957F\u5EA6\n- \u7528\u6237\u8BF7\u6C42\u5FC5\u987B\u9010\u5B57\u4FDD\u7559\n\n---\n\n# PHASE 4: \u63D0\u4F9B\u8BF4\u660E\n\n\u751F\u6210\u6458\u8981\u540E\uFF0C\u6307\u5BFC\u7528\u6237\uFF1A\n\n```\n---\n\nTO CONTINUE IN A NEW SESSION:\n\n1. \u5728 OpenCode TUI \u4E2D\u6309 'n' \u6253\u5F00\u65B0\u4F1A\u8BDD\uFF0C\u6216\u5728\u65B0\u7EC8\u7AEF\u4E2D\u8FD0\u884C 'opencode'\n2. \u5C06\u4E0A\u9762\u7684 HANDOFF CONTEXT \u4F5C\u4E3A\u7B2C\u4E00\u6761\u6D88\u606F\u7C98\u8D34\n3. \u6DFB\u52A0\u4F60\u7684\u8BF7\u6C42\uFF1A\"\u4ECE\u4E0A\u9762\u7684 handoff context \u7EE7\u7EED\u3002[\u4F60\u7684\u4E0B\u4E00\u4E2A\u4EFB\u52A1]\"\n\n\u65B0\u4F1A\u8BDD\u5C06\u62E5\u6709\u7EE7\u7EED\u5DE5\u4F5C\u6240\u9700\u7684\u6240\u6709\u4E0A\u4E0B\u6587\u3002\n```\n\n---\n\n# \u91CD\u8981\u7EA6\u675F\n\n- \u4E0D\u8981\u5C1D\u8BD5\u4EE5\u7F16\u7A0B\u65B9\u5F0F\u521B\u5EFA\u65B0\u4F1A\u8BDD\uFF08\u4EE3\u7406\u65E0\u6CD5\u4F7F\u7528 API\uFF09\n- \u63D0\u4F9B\u4E0D\u4F9D\u8D56\u6B64\u4F1A\u8BDD\u8BBF\u95EE\u7684\u72EC\u7ACB\u6458\u8981\n- \u5305\u542B\u76F8\u5BF9\u4E8E\u5DE5\u4F5C\u533A\u7684\u6587\u4EF6\u8DEF\u5F84\n- \u4E0D\u8981\u5305\u542B\u654F\u611F\u4FE1\u606F\uFF08API \u5BC6\u94A5\u3001\u51ED\u8BC1\u3001\u5BC6\u94A5\uFF09\n- KEY FILES \u90E8\u5206\u4E0D\u8D85\u8FC7 10 \u4E2A\u6587\u4EF6\n- \u5C06 GOAL \u90E8\u5206\u4FDD\u6301\u5728\u4E00\u53E5\u8BDD\u6216\u77ED\u6BB5\u843D\n\n---\n\n# \u7ACB\u5373\u6267\u884C\n\n\u9996\u5148\u6536\u96C6\u7A0B\u5E8F\u5316\u4E0A\u4E0B\u6587\uFF0C\u7136\u540E\u7EFC\u5408 handoff \u6458\u8981\u3002\n";
1
+ export declare const HANDOFF_TEMPLATE = "# Handoff Command\n\n## Purpose\n\nUse /handoff when:\n- The current session context is getting too long and quality is degrading\n- You want to start fresh while preserving essential context from this session\n- The context window is approaching capacity\n\nThis creates a detailed context summary that can be used to continue work in a new session.\n\n---\n\n# PHASE 0: VALIDATE REQUEST\n\nBefore proceeding, confirm:\n- [ ] There is meaningful work or context in this session to preserve\n- [ ] The user wants to create a handoff summary (not just asking about it)\n\nIf the session is nearly empty or has no meaningful context, inform the user there is nothing substantial to hand off.\n\n---\n\n# PHASE 1: GATHER PROGRAMMATIC CONTEXT\n\nExecute these tools to gather concrete data:\n\n1. session_read({ session_id: \"$SESSION_ID\" }) - full session history\n2. todoread() - current task progress\n3. Bash({ command: \"git diff --stat HEAD~10..HEAD\" }) - recent file changes\n4. Bash({ command: \"git status --porcelain\" }) - uncommitted changes\n\nSuggested execution order:\n\n```\nsession_read({ session_id: \"$SESSION_ID\" })\ntodoread()\nBash({ command: \"git diff --stat HEAD~10..HEAD\" })\nBash({ command: \"git status --porcelain\" })\n```\n\nAnalyze the gathered outputs to understand:\n- What the user asked for (exact wording)\n- What work was completed\n- What tasks remain incomplete (include todo state)\n- What decisions were made\n- What files were modified or discussed (include git diff/stat + status)\n- What patterns, constraints, or preferences were established\n\n---\n\n# PHASE 2: EXTRACT CONTEXT\n\nWrite the context summary from first person perspective (\"I did...\", \"I told you...\").\n\nFocus on:\n- Capabilities and behavior, not file-by-file implementation details\n- What matters for continuing the work\n- Avoiding excessive implementation details (variable names, storage keys, constants) unless critical\n- USER REQUESTS (AS-IS) must be verbatim (do not paraphrase)\n- EXPLICIT CONSTRAINTS must be verbatim only (do not invent)\n\nQuestions to consider when extracting:\n- What did I just do or implement?\n- What instructions did I already give which are still relevant (e.g. follow patterns in the codebase)?\n- What files did I tell you are important or that I am working on?\n- Did I provide a plan or spec that should be included?\n- What did I already tell you that is important (libraries, patterns, constraints, preferences)?\n- What important technical details did I discover (APIs, methods, patterns)?\n- What caveats, limitations, or open questions did I find?\n\n---\n\n# PHASE 3: FORMAT OUTPUT\n\nGenerate a handoff summary using this exact format:\n\n```\nHANDOFF CONTEXT\n===============\n\nUSER REQUESTS (AS-IS)\n---------------------\n- [Exact verbatim user requests - NOT paraphrased]\n\nGOAL\n----\n[One sentence describing what should be done next]\n\nWORK COMPLETED\n--------------\n- [First person bullet points of what was done]\n- [Include specific file paths when relevant]\n- [Note key implementation decisions]\n\nCURRENT STATE\n-------------\n- [Current state of the codebase or task]\n- [Build/test status if applicable]\n- [Any environment or configuration state]\n\nPENDING TASKS\n-------------\n- [Tasks that were planned but not completed]\n- [Next logical steps to take]\n- [Any blockers or issues encountered]\n- [Include current todo state from todoread()]\n\nKEY FILES\n---------\n- [path/to/file1] - [brief role description]\n- [path/to/file2] - [brief role description]\n(Maximum 10 files, prioritized by importance)\n- (Include files from git diff/stat and git status)\n\nIMPORTANT DECISIONS\n-------------------\n- [Technical decisions that were made and why]\n- [Trade-offs that were considered]\n- [Patterns or conventions established]\n\nEXPLICIT CONSTRAINTS\n--------------------\n- [Verbatim constraints only - from user or existing AGENTS.md]\n- If none, write: None\n\nCONTEXT FOR CONTINUATION\n------------------------\n- [What the next session needs to know to continue]\n- [Warnings or gotchas to be aware of]\n- [References to documentation if relevant]\n```\n\nRules for the summary:\n- Plain text with bullets\n- No markdown headers with # (use the format above with dashes)\n- No bold, italic, or code fences within content\n- Use workspace-relative paths for files\n- Keep it focused - only include what matters for continuation\n- Pick an appropriate length based on complexity\n- USER REQUESTS (AS-IS) and EXPLICIT CONSTRAINTS must be verbatim only\n\n---\n\n# PHASE 4: PROVIDE INSTRUCTIONS\n\nAfter generating the summary, instruct the user:\n\n```\n---\n\nTO CONTINUE IN A NEW SESSION:\n\n1. Press 'n' in OpenCode TUI to open a new session, or run 'opencode' in a new terminal\n2. Paste the HANDOFF CONTEXT above as your first message\n3. Add your request: \"Continue from the handoff context above. [Your next task]\"\n\nThe new session will have all context needed to continue seamlessly.\n```\n\n---\n\n# IMPORTANT CONSTRAINTS\n\n- DO NOT attempt to programmatically create new sessions (no API available to agents)\n- DO provide a self-contained summary that works without access to this session\n- DO include workspace-relative file paths\n- DO NOT include sensitive information (API keys, credentials, secrets)\n- DO NOT exceed 10 files in the KEY FILES section\n- DO keep the GOAL section to a single sentence or short paragraph\n\n---\n\n# EXECUTE NOW\n\nBegin by gathering programmatic context, then synthesize the handoff summary.\n";