@skj1724/oh-my-opencode 4.0.1 → 4.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5075,47 +5075,215 @@ var sessionCursors;
5075
5075
  var init_session_cursor = __esm(() => {
5076
5076
  sessionCursors = new Map;
5077
5077
  });
5078
- // src/shared/agent-tool-restrictions.ts
5079
- function getAgentToolRestrictions(agentName) {
5080
- return findCaseInsensitive(AGENT_RESTRICTIONS, resolveAgentName(agentName)) ?? {};
5078
+ // src/shared/agent-permissions.ts
5079
+ function getAgentPermission(agentName) {
5080
+ const exact = DEFAULT_AGENT_PERMISSIONS[agentName];
5081
+ if (exact !== undefined)
5082
+ return { ...exact };
5083
+ const lower = agentName.toLowerCase();
5084
+ for (const [key, perm] of Object.entries(DEFAULT_AGENT_PERMISSIONS)) {
5085
+ if (key.toLowerCase() === lower)
5086
+ return { ...perm };
5087
+ }
5088
+ return { ...NEW_AGENT_DEFAULT };
5081
5089
  }
5082
- var EXPLORATION_AGENT_DENYLIST, AGENT_RESTRICTIONS;
5083
- var init_agent_tool_restrictions = __esm(() => {
5084
- init_case_insensitive();
5085
- init_agent_display_names();
5086
- EXPLORATION_AGENT_DENYLIST = {
5087
- write: false,
5088
- edit: false,
5089
- task: false,
5090
- delegate_task: false,
5091
- call_omo_agent: false
5092
- };
5093
- AGENT_RESTRICTIONS = {
5094
- "\u6DF1\u5EA6\u63A2\u7D22": EXPLORATION_AGENT_DENYLIST,
5095
- "\u77E5\u8BC6\u5178\u85CF": EXPLORATION_AGENT_DENYLIST,
5090
+ function deriveToolRestrictions(agentName) {
5091
+ const cached = toolRestrictionsCache.get(agentName);
5092
+ if (cached !== undefined)
5093
+ return cached;
5094
+ const perm = getAgentPermission(agentName);
5095
+ let restrictions;
5096
+ if (perm.toolMode === "whitelist") {
5097
+ restrictions = { ...perm.toolOverrides };
5098
+ } else {
5099
+ restrictions = {};
5100
+ if (!perm.canWriteFiles) {
5101
+ restrictions.write = false;
5102
+ restrictions.edit = false;
5103
+ restrictions.ast_grep_replace = false;
5104
+ restrictions.lsp_rename = false;
5105
+ }
5106
+ if (!perm.canExecuteCommands) {
5107
+ restrictions.bash = false;
5108
+ }
5109
+ if (!perm.canDelegateTasks) {
5110
+ restrictions.delegate_task = false;
5111
+ restrictions.task = false;
5112
+ restrictions.call_omo_agent = false;
5113
+ }
5114
+ if (perm.toolOverrides) {
5115
+ for (const [key, value] of Object.entries(perm.toolOverrides)) {
5116
+ restrictions[key] = value;
5117
+ }
5118
+ }
5119
+ }
5120
+ toolRestrictionsCache.set(agentName, restrictions);
5121
+ return restrictions;
5122
+ }
5123
+ function canDelegateTo(parentAgent, targetAgent, category) {
5124
+ const parent = getAgentPermission(parentAgent);
5125
+ const target = getAgentPermission(targetAgent);
5126
+ if (!parent.canDelegateTasks)
5127
+ return false;
5128
+ if (!parent.canWriteFiles) {
5129
+ if (category !== undefined) {
5130
+ const allowed = parent.allowedCategories.map((c) => c.toLowerCase());
5131
+ if (!allowed.includes(category.toLowerCase()))
5132
+ return false;
5133
+ }
5134
+ if (target.canWriteFiles)
5135
+ return false;
5136
+ }
5137
+ return true;
5138
+ }
5139
+ function deriveSdkPermission(agentName) {
5140
+ const cached = sdkPermissionCache.get(agentName);
5141
+ if (cached !== undefined)
5142
+ return cached;
5143
+ const perm = getAgentPermission(agentName);
5144
+ const permission = {};
5145
+ if (!perm.canWriteFiles) {
5146
+ permission.write = "deny";
5147
+ permission.edit = "deny";
5148
+ }
5149
+ if (!perm.canExecuteCommands) {
5150
+ permission.bash = "deny";
5151
+ }
5152
+ if (perm.canDelegateTasks) {
5153
+ permission.delegate_task = "allow";
5154
+ }
5155
+ if (perm.sdkPermissionOverrides) {
5156
+ for (const [key, value] of Object.entries(perm.sdkPermissionOverrides)) {
5157
+ permission[key] = value;
5158
+ }
5159
+ }
5160
+ sdkPermissionCache.set(agentName, permission);
5161
+ return permission;
5162
+ }
5163
+ var DEFAULT_AGENT_PERMISSIONS, ALL_DEFINED_AGENTS, NEW_AGENT_DEFAULT, toolRestrictionsCache, sdkPermissionCache;
5164
+ var init_agent_permissions = __esm(() => {
5165
+ DEFAULT_AGENT_PERMISSIONS = {
5166
+ "\u6218\u7565\u53C2\u8C0B": {
5167
+ canReadFiles: true,
5168
+ canWriteFiles: false,
5169
+ canExecuteCommands: true,
5170
+ canDelegateTasks: true,
5171
+ allowedCategories: ["quick"],
5172
+ sdkPermissionOverrides: { call_omo_agent: "deny", question: "allow" }
5173
+ },
5174
+ "\u6DF1\u5EA6\u63A2\u7D22": {
5175
+ canReadFiles: true,
5176
+ canWriteFiles: false,
5177
+ canExecuteCommands: false,
5178
+ canDelegateTasks: false,
5179
+ allowedCategories: []
5180
+ },
5181
+ "\u77E5\u8BC6\u5178\u85CF": {
5182
+ canReadFiles: true,
5183
+ canWriteFiles: false,
5184
+ canExecuteCommands: false,
5185
+ canDelegateTasks: false,
5186
+ allowedCategories: [],
5187
+ sdkPermissionOverrides: { "grep_app_*": "allow" }
5188
+ },
5096
5189
  "\u6280\u672F\u53C2\u8C0B": {
5097
- write: false,
5098
- edit: false,
5099
- task: false,
5100
- delegate_task: false
5190
+ canReadFiles: true,
5191
+ canWriteFiles: false,
5192
+ canExecuteCommands: false,
5193
+ canDelegateTasks: false,
5194
+ allowedCategories: []
5101
5195
  },
5102
- "\u5A92\u4F53\u89E3\u6790": {
5103
- read: true
5196
+ "\u9884\u5BA1\u987E\u95EE": {
5197
+ canReadFiles: true,
5198
+ canWriteFiles: false,
5199
+ canExecuteCommands: false,
5200
+ canDelegateTasks: false,
5201
+ allowedCategories: []
5104
5202
  },
5105
- "\u6267\u884C\u52A9\u7406": {
5106
- task: false,
5107
- delegate_task: false
5203
+ "\u8BA1\u5212\u5BA1\u67E5": {
5204
+ canReadFiles: true,
5205
+ canWriteFiles: false,
5206
+ canExecuteCommands: false,
5207
+ canDelegateTasks: false,
5208
+ allowedCategories: []
5209
+ },
5210
+ "\u5A92\u4F53\u89E3\u6790": {
5211
+ canReadFiles: true,
5212
+ canWriteFiles: false,
5213
+ canExecuteCommands: false,
5214
+ canDelegateTasks: false,
5215
+ allowedCategories: [],
5216
+ toolMode: "whitelist",
5217
+ toolOverrides: { read: true },
5218
+ sdkPermissionOverrides: { task: "deny", look_at: "deny" }
5108
5219
  },
5109
5220
  "BTW \u987E\u95EE": {
5110
- write: false,
5111
- edit: false,
5112
- bash: false,
5113
- task: false,
5114
- delegate_task: false,
5115
- call_omo_agent: false,
5116
- slashcommand: false
5221
+ canReadFiles: true,
5222
+ canWriteFiles: false,
5223
+ canExecuteCommands: false,
5224
+ canDelegateTasks: false,
5225
+ allowedCategories: [],
5226
+ toolOverrides: { slashcommand: false }
5227
+ },
5228
+ "\u4E3B\u6267\u884C\u5B98": {
5229
+ canReadFiles: true,
5230
+ canWriteFiles: true,
5231
+ canExecuteCommands: true,
5232
+ canDelegateTasks: true,
5233
+ allowedCategories: [
5234
+ "visual-engineering",
5235
+ "ultrabrain",
5236
+ "artistry",
5237
+ "quick",
5238
+ "unspecified-low",
5239
+ "unspecified-high",
5240
+ "writing"
5241
+ ],
5242
+ sdkPermissionOverrides: { call_omo_agent: "deny", question: "allow" }
5243
+ },
5244
+ "\u4EFB\u52A1\u7F16\u6392": {
5245
+ canReadFiles: true,
5246
+ canWriteFiles: true,
5247
+ canExecuteCommands: true,
5248
+ canDelegateTasks: true,
5249
+ allowedCategories: [
5250
+ "visual-engineering",
5251
+ "ultrabrain",
5252
+ "artistry",
5253
+ "quick",
5254
+ "unspecified-low",
5255
+ "unspecified-high",
5256
+ "writing"
5257
+ ],
5258
+ sdkPermissionOverrides: { task: "deny", call_omo_agent: "deny" }
5259
+ },
5260
+ "\u6267\u884C\u52A9\u7406": {
5261
+ canReadFiles: true,
5262
+ canWriteFiles: true,
5263
+ canExecuteCommands: true,
5264
+ canDelegateTasks: false,
5265
+ allowedCategories: [],
5266
+ sdkPermissionOverrides: { delegate_task: "allow" }
5117
5267
  }
5118
5268
  };
5269
+ ALL_DEFINED_AGENTS = Object.freeze(Object.keys(DEFAULT_AGENT_PERMISSIONS));
5270
+ NEW_AGENT_DEFAULT = {
5271
+ canReadFiles: true,
5272
+ canWriteFiles: false,
5273
+ canExecuteCommands: false,
5274
+ canDelegateTasks: false,
5275
+ allowedCategories: []
5276
+ };
5277
+ toolRestrictionsCache = new Map;
5278
+ sdkPermissionCache = new Map;
5279
+ });
5280
+
5281
+ // src/shared/agent-tool-restrictions.ts
5282
+ function getAgentToolRestrictions(agentName) {
5283
+ return deriveToolRestrictions(agentName);
5284
+ }
5285
+ var init_agent_tool_restrictions = __esm(() => {
5286
+ init_agent_permissions();
5119
5287
  });
5120
5288
 
5121
5289
  // src/shared/model-requirements.ts
@@ -6292,6 +6460,7 @@ var init_shared = __esm(() => {
6292
6460
  init_agent_variant();
6293
6461
  init_session_cursor();
6294
6462
  init_system_directive();
6463
+ init_agent_permissions();
6295
6464
  init_agent_tool_restrictions();
6296
6465
  init_model_requirements();
6297
6466
  init_model_resolver();
@@ -27218,11 +27387,12 @@ import { resolve as resolve7, relative as relative5, isAbsolute as isAbsolute3 }
27218
27387
  // src/hooks/prometheus-md-only/constants.ts
27219
27388
  init_system_directive();
27220
27389
  init_agent_display_names();
27390
+ init_agent_permissions();
27221
27391
  var HOOK_NAME4 = "prometheus-md-only";
27222
27392
  var PROMETHEUS_AGENTS = ["\u6218\u7565\u53C2\u8C0B"];
27223
- var AGENT_CATEGORY_WHITELIST = {
27224
- "\u6218\u7565\u53C2\u8C0B": ["quick"]
27225
- };
27393
+ function getAllowedCategoriesForAgent(agentName) {
27394
+ return getAgentPermission(agentName).allowedCategories;
27395
+ }
27226
27396
  var ALLOWED_EXTENSIONS = [".md"];
27227
27397
  var BLOCKED_TOOLS = ["Write", "Edit", "write", "edit", "ast_grep_replace", "lsp_rename"];
27228
27398
  var BASH_WRITE_COMMANDS = [
@@ -27419,7 +27589,7 @@ function createPrometheusMdOnlyHook(ctx) {
27419
27589
  const category = output.args.category;
27420
27590
  const subagent_type = output.args.subagent_type;
27421
27591
  const matchedAgent = PROMETHEUS_AGENTS.find((a) => agentNameMatches(agentName, a));
27422
- const whitelist = matchedAgent ? AGENT_CATEGORY_WHITELIST[matchedAgent] ?? [] : [];
27592
+ const whitelist = matchedAgent ? getAllowedCategoriesForAgent(matchedAgent) : [];
27423
27593
  if (!subagent_type && (!category || !whitelist.includes(category))) {
27424
27594
  log(`[${HOOK_NAME4}] Blocked: Prometheus attempted delegate_task with non-allowed category`, {
27425
27595
  sessionID: input.sessionID,
@@ -28718,6 +28888,7 @@ function isActiveContinuationTrigger(sessionID, directory) {
28718
28888
  return false;
28719
28889
  }
28720
28890
  var CONTINUATION_COOLDOWN_MS = 5000;
28891
+ var CONTINUATION_CYCLE_THRESHOLD = 5;
28721
28892
  function isAbortError(error) {
28722
28893
  if (!error)
28723
28894
  return false;
@@ -28908,6 +29079,28 @@ function createAtlasHook(ctx, options) {
28908
29079
  log(`[${HOOK_NAME6}] Skipped: continuation cooldown active`, { sessionID, cooldownRemaining: CONTINUATION_COOLDOWN_MS - (now - state2.lastContinuationInjectedAt) });
28909
29080
  return;
28910
29081
  }
29082
+ const progressKey = `${progress.completed}/${progress.total}`;
29083
+ if (state2.lastContinuationProgress === progressKey) {
29084
+ state2.continuationCycleCount = (state2.continuationCycleCount ?? 0) + 1;
29085
+ } else {
29086
+ state2.continuationCycleCount = 0;
29087
+ }
29088
+ state2.lastContinuationProgress = progressKey;
29089
+ if ((state2.continuationCycleCount ?? 0) >= CONTINUATION_CYCLE_THRESHOLD) {
29090
+ if (!state2.isBlocked) {
29091
+ state2.isBlocked = true;
29092
+ await ctx.client.tui.showToast({
29093
+ body: {
29094
+ title: "\u26A0\uFE0F \u5DE5\u4F5C\u53EF\u80FD\u88AB\u963B\u585E",
29095
+ message: `\u8BA1\u5212 "${boulderState.plan_name}" \u5728 ${progressKey} \u5904\u8FDE\u7EED ${state2.continuationCycleCount} \u6B21\u65E0\u8FDB\u5C55\u3002\u8BF7\u68C0\u67E5\u662F\u5426\u9700\u8981\u4F60\u7684\u8F93\u5165\u3002`,
29096
+ variant: "warning",
29097
+ duration: 5000
29098
+ }
29099
+ }).catch(() => {});
29100
+ }
29101
+ log(`[${HOOK_NAME6}] Skipped: blocked detection`, { sessionID, count: state2.continuationCycleCount, progress: progressKey });
29102
+ return;
29103
+ }
28911
29104
  state2.lastContinuationInjectedAt = now;
28912
29105
  const remaining = progress.total - progress.completed;
28913
29106
  injectContinuation(sessionID, boulderState.plan_name, remaining, progress.total);
@@ -28922,6 +29115,15 @@ function createAtlasHook(ctx, options) {
28922
29115
  if (state2) {
28923
29116
  state2.lastEventWasAbortError = false;
28924
29117
  }
29118
+ if (info?.role === "user" && state2) {
29119
+ state2.lastEventWasAbortError = false;
29120
+ if (state2.isBlocked) {
29121
+ state2.isBlocked = false;
29122
+ state2.continuationCycleCount = 0;
29123
+ state2.lastContinuationProgress = undefined;
29124
+ log(`[${HOOK_NAME6}] Blocked state reset by user message`, { sessionID });
29125
+ }
29126
+ }
28925
29127
  return;
28926
29128
  }
28927
29129
  if (event.type === "message.part.updated") {
@@ -29043,6 +29245,15 @@ function createAtlasHook(ctx, options) {
29043
29245
  if (isBackgroundLaunch) {
29044
29246
  return;
29045
29247
  }
29248
+ if (input.sessionID) {
29249
+ const toolState = sessions.get(input.sessionID);
29250
+ if (toolState?.isBlocked) {
29251
+ toolState.isBlocked = false;
29252
+ toolState.continuationCycleCount = 0;
29253
+ toolState.lastContinuationProgress = undefined;
29254
+ log(`[${HOOK_NAME6}] Blocked state reset by delegate_task completion`, { sessionID: input.sessionID });
29255
+ }
29256
+ }
29046
29257
  if (output.output && typeof output.output === "string") {
29047
29258
  const gitStats = getGitDiffStats(ctx.directory);
29048
29259
  const fileChanges = formatFileChanges(gitStats);
@@ -30562,138 +30773,8 @@ function createToolDefinitionOptimizerHook(_ctx) {
30562
30773
  }
30563
30774
  };
30564
30775
  }
30565
- // src/shared/agent-permissions.ts
30566
- var DEFAULT_AGENT_PERMISSIONS = {
30567
- "\u6218\u7565\u53C2\u8C0B": {
30568
- canReadFiles: true,
30569
- canWriteFiles: false,
30570
- canExecuteCommands: true,
30571
- canDelegateTasks: true,
30572
- allowedCategories: ["quick"]
30573
- },
30574
- "\u6DF1\u5EA6\u63A2\u7D22": {
30575
- canReadFiles: true,
30576
- canWriteFiles: false,
30577
- canExecuteCommands: false,
30578
- canDelegateTasks: false,
30579
- allowedCategories: []
30580
- },
30581
- "\u77E5\u8BC6\u5178\u85CF": {
30582
- canReadFiles: true,
30583
- canWriteFiles: false,
30584
- canExecuteCommands: false,
30585
- canDelegateTasks: false,
30586
- allowedCategories: []
30587
- },
30588
- "\u6280\u672F\u53C2\u8C0B": {
30589
- canReadFiles: true,
30590
- canWriteFiles: false,
30591
- canExecuteCommands: false,
30592
- canDelegateTasks: false,
30593
- allowedCategories: []
30594
- },
30595
- "\u9884\u5BA1\u987E\u95EE": {
30596
- canReadFiles: true,
30597
- canWriteFiles: false,
30598
- canExecuteCommands: false,
30599
- canDelegateTasks: false,
30600
- allowedCategories: []
30601
- },
30602
- "\u8BA1\u5212\u5BA1\u67E5": {
30603
- canReadFiles: true,
30604
- canWriteFiles: false,
30605
- canExecuteCommands: false,
30606
- canDelegateTasks: false,
30607
- allowedCategories: []
30608
- },
30609
- "\u5A92\u4F53\u89E3\u6790": {
30610
- canReadFiles: true,
30611
- canWriteFiles: false,
30612
- canExecuteCommands: false,
30613
- canDelegateTasks: false,
30614
- allowedCategories: []
30615
- },
30616
- "BTW \u987E\u95EE": {
30617
- canReadFiles: true,
30618
- canWriteFiles: false,
30619
- canExecuteCommands: false,
30620
- canDelegateTasks: false,
30621
- allowedCategories: []
30622
- },
30623
- "\u4E3B\u6267\u884C\u5B98": {
30624
- canReadFiles: true,
30625
- canWriteFiles: true,
30626
- canExecuteCommands: true,
30627
- canDelegateTasks: true,
30628
- allowedCategories: [
30629
- "visual-engineering",
30630
- "ultrabrain",
30631
- "artistry",
30632
- "quick",
30633
- "unspecified-low",
30634
- "unspecified-high",
30635
- "writing"
30636
- ]
30637
- },
30638
- "\u4EFB\u52A1\u7F16\u6392": {
30639
- canReadFiles: true,
30640
- canWriteFiles: true,
30641
- canExecuteCommands: true,
30642
- canDelegateTasks: true,
30643
- allowedCategories: [
30644
- "visual-engineering",
30645
- "ultrabrain",
30646
- "artistry",
30647
- "quick",
30648
- "unspecified-low",
30649
- "unspecified-high",
30650
- "writing"
30651
- ]
30652
- },
30653
- "\u6267\u884C\u52A9\u7406": {
30654
- canReadFiles: true,
30655
- canWriteFiles: true,
30656
- canExecuteCommands: true,
30657
- canDelegateTasks: false,
30658
- allowedCategories: []
30659
- }
30660
- };
30661
- var NEW_AGENT_DEFAULT = {
30662
- canReadFiles: true,
30663
- canWriteFiles: false,
30664
- canExecuteCommands: false,
30665
- canDelegateTasks: false,
30666
- allowedCategories: []
30667
- };
30668
- function getAgentPermission(agentName) {
30669
- const exact = DEFAULT_AGENT_PERMISSIONS[agentName];
30670
- if (exact !== undefined)
30671
- return { ...exact };
30672
- const lower = agentName.toLowerCase();
30673
- for (const [key, perm] of Object.entries(DEFAULT_AGENT_PERMISSIONS)) {
30674
- if (key.toLowerCase() === lower)
30675
- return { ...perm };
30676
- }
30677
- return { ...NEW_AGENT_DEFAULT };
30678
- }
30679
- function canDelegateTo(parentAgent, targetAgent, category) {
30680
- const parent = getAgentPermission(parentAgent);
30681
- const target = getAgentPermission(targetAgent);
30682
- if (!parent.canDelegateTasks)
30683
- return false;
30684
- if (!parent.canWriteFiles) {
30685
- if (category !== undefined) {
30686
- const allowed = parent.allowedCategories.map((c) => c.toLowerCase());
30687
- if (!allowed.includes(category.toLowerCase()))
30688
- return false;
30689
- }
30690
- if (target.canWriteFiles)
30691
- return false;
30692
- }
30693
- return true;
30694
- }
30695
-
30696
30776
  // src/shared/permission-bridge.ts
30777
+ init_agent_permissions();
30697
30778
  var SISYPHUS_PATTERN = /\.sisyphus[/\\]/i;
30698
30779
  var MD_EXTENSION = /\.md$/i;
30699
30780
  function isPrometheusAllowedPath(filePath) {
@@ -30722,6 +30803,11 @@ function evaluatePermission(input, agentName) {
30722
30803
  }
30723
30804
  return { status: "allow", reason: `${agentName} \u6709\u547D\u4EE4\u6267\u884C\u6743\u9650` };
30724
30805
  }
30806
+ case "read":
30807
+ if (!perm.canReadFiles) {
30808
+ return { status: "ask", reason: `${agentName} \u65E0\u6587\u4EF6\u8BFB\u53D6\u6743\u9650` };
30809
+ }
30810
+ return { status: "allow", reason: `${agentName} \u6709\u6587\u4EF6\u8BFB\u53D6\u6743\u9650` };
30725
30811
  case "webfetch":
30726
30812
  case "doom_loop":
30727
30813
  case "external_directory":
@@ -31037,10 +31123,11 @@ init_logger();
31037
31123
  init_agent_display_names();
31038
31124
  var THROTTLE_MS = 30000;
31039
31125
  var TIMEOUT_MS = 15000;
31040
- var MAX_TITLE_LENGTH = 40;
31126
+ var MAX_TITLE_LENGTH = 30;
31041
31127
  var namingInProgress = new Map;
31042
31128
  var lastNamedTime = new Map;
31043
31129
  var activeSubSessions = new Map;
31130
+ var sessionMessageCache = new Map;
31044
31131
  function extractTextFromResponse(response) {
31045
31132
  try {
31046
31133
  const data = response?.data;
@@ -31054,7 +31141,7 @@ function extractTextFromResponse(response) {
31054
31141
  }
31055
31142
  }
31056
31143
  function extractConversationText(messages) {
31057
- const recent = messages.slice(-4);
31144
+ const recent = messages.slice(-2);
31058
31145
  return recent.map((m) => {
31059
31146
  const role = m?.info ? m.info?.role : m?.role;
31060
31147
  const parts = m?.parts ?? [];
@@ -31067,6 +31154,17 @@ function extractConversationText(messages) {
31067
31154
 
31068
31155
  `);
31069
31156
  }
31157
+ function normalizeTitle(title) {
31158
+ let result = title.trim();
31159
+ result = result.replace(/\[/g, "\u3010").replace(/\]/g, "\u3011");
31160
+ if (!result)
31161
+ return "";
31162
+ if (!/^\u3010[^\u3011]+\u3011/.test(result)) {
31163
+ result = `\u3010\u6742\u9879\u3011${result}`;
31164
+ }
31165
+ result = Array.from(result).slice(0, MAX_TITLE_LENGTH).join("");
31166
+ return result;
31167
+ }
31070
31168
  function withTimeout3(promise, ms) {
31071
31169
  return Promise.race([
31072
31170
  promise,
@@ -31100,7 +31198,12 @@ function createSessionNamingHook(_ctx) {
31100
31198
  const sessionData = sessionInfo.data;
31101
31199
  const currentModel = sessionData.model;
31102
31200
  const currentAgent = sessionData.agent;
31103
- const messagesResp = await ctx.client.session.messages({ path: { id: sessionID }, query: { limit: 4 } }).catch(() => null);
31201
+ const existingTitle = sessionData.title;
31202
+ if (existingTitle && !/^\u3010[^\u3011]+\u3011/.test(existingTitle)) {
31203
+ log("[session-naming] Manual title detected, skipping idle update", { sessionID, existingTitle });
31204
+ return;
31205
+ }
31206
+ const messagesResp = await ctx.client.session.messages({ path: { id: sessionID }, query: { limit: 2 } }).catch(() => null);
31104
31207
  if (!messagesResp) {
31105
31208
  log("[session-naming] Failed to get messages", { sessionID });
31106
31209
  return;
@@ -31110,6 +31213,9 @@ function createSessionNamingHook(_ctx) {
31110
31213
  log("[session-naming] No messages to name from", { sessionID });
31111
31214
  return;
31112
31215
  }
31216
+ const existingCache = sessionMessageCache.get(sessionID) ?? [];
31217
+ const merged = [...existingCache, ...messages];
31218
+ sessionMessageCache.set(sessionID, merged.slice(-20));
31113
31219
  const conversationText = extractConversationText(messages);
31114
31220
  if (!conversationText) {
31115
31221
  log("[session-naming] Empty conversation text", { sessionID });
@@ -31124,17 +31230,25 @@ function createSessionNamingHook(_ctx) {
31124
31230
  activeSubSessions.set(sessionID, subSessionID);
31125
31231
  subagentSessions.add(subSessionID);
31126
31232
  const resolvedAgent = currentAgent ? resolveAgentName(currentAgent) : undefined;
31233
+ const existingTitleLine = existingTitle ? `
31234
+ - \u73B0\u6709\u6807\u9898\uFF1A${existingTitle}` : "";
31127
31235
  const promptResult = await withTimeout3(ctx.client.session.prompt({
31128
31236
  path: { id: subSessionID },
31129
31237
  body: {
31130
31238
  parts: [
31131
31239
  {
31132
31240
  type: "text",
31133
- text: `\u6839\u636E\u4EE5\u4E0B\u5BF9\u8BDD\u5185\u5BB9\u751F\u6210\u4E00\u4E2A\u7B80\u77ED\u7684\u4E2D\u6587\u4F1A\u8BDD\u6807\u9898\uFF08\u4E0D\u8D85\u8FC7 20 \u4E2A\u5B57\uFF09\u3002
31134
- \u53EA\u8F93\u51FA\u6807\u9898\u672C\u8EAB\uFF0C\u4E0D\u8981\u989D\u5916\u8BF4\u660E\uFF0C\u4E0D\u8981\u52A0\u5F15\u53F7\uFF0C\u4E0D\u8981\u52A0\u6807\u70B9\u3002
31241
+ text: `\u4F60\u6B63\u5728\u4E3A\u4E00\u4E2A AI \u7F16\u7A0B\u4F1A\u8BDD\u66F4\u65B0\u6807\u9898\u3002${existingTitleLine}
31242
+
31243
+ - \u6700\u65B0\u5BF9\u8BDD\uFF1A${conversationText}
31135
31244
 
31136
- \u5BF9\u8BDD\uFF1A
31137
- ${conversationText}`
31245
+ \u8BF7\u5224\u65AD\uFF1A
31246
+ 1. \u5982\u679C\u6700\u65B0\u5BF9\u8BDD\u4E0E\u539F\u6807\u9898\u63CF\u8FF0\u7684\u4E3B\u9898\u4E00\u81F4 \u2192 \u56DE\u590D\u300C\u65E0\u9700\u66F4\u65B0\u300D
31247
+ 2. \u5982\u679C\u6700\u65B0\u5BF9\u8BDD\u8F6C\u5411\u4E86\u65B0\u4E3B\u9898\u6216\u539F\u6807\u9898\u4E0D\u591F\u51C6\u786E \u2192 \u751F\u6210\u66F4\u51C6\u786E\u7684\u6807\u9898
31248
+
31249
+ \u6807\u9898\u683C\u5F0F\u4E3A\uFF1A\u3010\u7C7B\u578B\u524D\u7F00\u3011\u7B80\u77ED\u63CF\u8FF0
31250
+ \u4F8B\u5982\uFF1A\u3010\u529F\u80FD\u3011\u6DFB\u52A0\u767B\u5F55\u9875\u9762 \u6216 \u3010\u4FEE\u590D\u3011\u4FEE\u590D\u7A7A\u6307\u9488\u5F02\u5E38
31251
+ \u53EA\u8F93\u51FA\u6807\u9898\u6216\u300C\u65E0\u9700\u66F4\u65B0\u300D\uFF0C\u4E0D\u8981\u989D\u5916\u8BF4\u660E\u3002`
31138
31252
  }
31139
31253
  ],
31140
31254
  ...currentModel ? { model: { providerID: currentModel.providerID, modelID: currentModel.modelID } } : {},
@@ -31148,12 +31262,31 @@ ${conversationText}`
31148
31262
  }
31149
31263
  await ctx.client.session.abort({ path: { id: subSessionID } }).catch(() => {});
31150
31264
  activeSubSessions.delete(sessionID);
31151
- if (!title) {
31152
- log("[session-naming] No title extracted from sub-session response", { sessionID });
31265
+ if (title && (title.includes("\u65E0\u9700\u66F4\u65B0") || title.includes("\u4E0D\u9700\u8981\u66F4\u65B0"))) {
31266
+ log("[session-naming] AI judged no update needed", { sessionID, existingTitle });
31153
31267
  return;
31154
31268
  }
31155
- if (title.length > MAX_TITLE_LENGTH) {
31156
- title = title.slice(0, MAX_TITLE_LENGTH);
31269
+ if (!title) {
31270
+ log("[session-naming] No title from AI, falling back to first message", { sessionID });
31271
+ const firstMsg = messages[0];
31272
+ const firstParts = firstMsg?.parts ?? [];
31273
+ const fallbackText = firstParts.filter((p) => p?.type === "text").map((p) => String(p?.text ?? "")).join("").trim();
31274
+ if (fallbackText) {
31275
+ title = fallbackText;
31276
+ } else {
31277
+ const now = new Date;
31278
+ const yyyy = now.getFullYear();
31279
+ const mm = String(now.getMonth() + 1).padStart(2, "0");
31280
+ const dd = String(now.getDate()).padStart(2, "0");
31281
+ const hh = String(now.getHours()).padStart(2, "0");
31282
+ const min = String(now.getMinutes()).padStart(2, "0");
31283
+ title = `\u3010\u65B0\u4F1A\u8BDD\u3011 - ${yyyy}-${mm}-${dd} ${hh}:${min}`;
31284
+ }
31285
+ }
31286
+ title = normalizeTitle(title);
31287
+ if (existingTitle && title === existingTitle) {
31288
+ log("[session-naming] Title unchanged, skipping update", { sessionID, title });
31289
+ return;
31157
31290
  }
31158
31291
  await ctx.client.session.update({ path: { id: sessionID }, body: { title } }).catch(() => {
31159
31292
  log("[session-naming] Failed to update session title", { sessionID, title });
@@ -31166,16 +31299,66 @@ ${conversationText}`
31166
31299
  namingInProgress.delete(sessionID);
31167
31300
  }
31168
31301
  }
31169
- function handleSessionDeleted(props) {
31302
+ async function handleSessionDeleted(props) {
31170
31303
  const sessionInfo = props?.info;
31171
31304
  if (!sessionInfo?.id)
31172
31305
  return;
31173
- namingInProgress.delete(sessionInfo.id);
31174
- lastNamedTime.delete(sessionInfo.id);
31175
- const subSessionID = activeSubSessions.get(sessionInfo.id);
31306
+ const sessionID = sessionInfo.id;
31307
+ const existingTitle = sessionInfo.title ?? "";
31308
+ try {
31309
+ const cachedMessages = sessionMessageCache.get(sessionID) ?? [];
31310
+ if (cachedMessages.length > 0) {
31311
+ const conversationText = extractConversationText(cachedMessages);
31312
+ if (conversationText) {
31313
+ const subSession = await ctx.client.session.create({ body: { parentID: sessionID } }).catch(() => null);
31314
+ if (subSession?.data?.id) {
31315
+ const subSessionID2 = subSession.data.id;
31316
+ subagentSessions.add(subSessionID2);
31317
+ const fallbackModel = { providerID: "anthropic", modelID: "claude-haiku-4-5" };
31318
+ const titleLine = existingTitle ? `
31319
+ \u539F\u6807\u9898\uFF1A${existingTitle}` : "";
31320
+ const promptResult = await withTimeout3(ctx.client.session.prompt({
31321
+ path: { id: subSessionID2 },
31322
+ body: {
31323
+ parts: [
31324
+ {
31325
+ type: "text",
31326
+ text: `\u8BF7\u4E3A\u4EE5\u4E0B AI \u7F16\u7A0B\u4F1A\u8BDD\u751F\u6210\u4E00\u4E2A\u6982\u62EC\u6027\u7684\u4E2D\u6587\u6807\u9898\uFF08\u4E0D\u8D85\u8FC7 30 \u5B57\uFF09\u3002
31327
+ \u6807\u9898\u5E94\u8986\u76D6\u6574\u4E2A\u4F1A\u8BDD\u7684\u6838\u5FC3\u4E3B\u65E8\uFF0C\u800C\u4E0D\u4EC5\u4EC5\u662F\u6700\u8FD1\u7684\u5185\u5BB9\u3002${titleLine}
31328
+
31329
+ \u4F1A\u8BDD\u5185\u5BB9\uFF1A
31330
+ ${conversationText}
31331
+
31332
+ \u6807\u9898\u683C\u5F0F\u4E3A\uFF1A\u3010\u7C7B\u578B\u524D\u7F00\u3011\u7B80\u77ED\u63CF\u8FF0
31333
+ \u4F8B\u5982\uFF1A\u3010\u529F\u80FD\u3011\u6DFB\u52A0\u767B\u5F55\u9875\u9762 \u6216 \u3010\u91CD\u6784\u3011\u91CD\u6784\u8BA4\u8BC1\u6A21\u5757
31334
+ \u53EA\u8F93\u51FA\u6807\u9898\u672C\u8EAB\uFF0C\u4E0D\u8981\u989D\u5916\u8BF4\u660E\u3002`
31335
+ }
31336
+ ],
31337
+ model: fallbackModel,
31338
+ tools: { bash: false, task: false, delegate_task: false, question: false }
31339
+ }
31340
+ }), TIMEOUT_MS).catch(() => null);
31341
+ const title = promptResult ? extractTextFromResponse(promptResult) : null;
31342
+ if (title) {
31343
+ const finalTitle = normalizeTitle(title);
31344
+ await ctx.client.session.update({ path: { id: sessionID }, body: { title: finalTitle } }).catch(() => {
31345
+ log("[session-naming] Failed to update session title on delete", { sessionID, title: finalTitle });
31346
+ });
31347
+ log("[session-naming] Final naming on delete", { sessionID, title: finalTitle });
31348
+ }
31349
+ }
31350
+ }
31351
+ }
31352
+ } catch (err) {
31353
+ log("[session-naming] Error in final naming on delete", { sessionID, error: String(err) });
31354
+ }
31355
+ namingInProgress.delete(sessionID);
31356
+ lastNamedTime.delete(sessionID);
31357
+ sessionMessageCache.delete(sessionID);
31358
+ const subSessionID = activeSubSessions.get(sessionID);
31176
31359
  if (subSessionID) {
31177
31360
  ctx.client.session.abort({ path: { id: subSessionID } }).catch(() => {});
31178
- activeSubSessions.delete(sessionInfo.id);
31361
+ activeSubSessions.delete(sessionID);
31179
31362
  }
31180
31363
  }
31181
31364
  const eventHandler = async ({ event }) => {
@@ -31187,7 +31370,7 @@ ${conversationText}`
31187
31370
  await handleSessionIdle(props);
31188
31371
  break;
31189
31372
  case "session.deleted":
31190
- handleSessionDeleted(props);
31373
+ await handleSessionDeleted(props);
31191
31374
  break;
31192
31375
  }
31193
31376
  };
@@ -31202,6 +31385,7 @@ ${conversationText}`
31202
31385
  activeSubSessions.clear();
31203
31386
  namingInProgress.clear();
31204
31387
  lastNamedTime.clear();
31388
+ sessionMessageCache.clear();
31205
31389
  }
31206
31390
  };
31207
31391
  }
@@ -48085,10 +48269,10 @@ var SESSION_LIST_DESCRIPTION = `\u5217\u51FA\u6240\u6709 OpenCode session\uFF0C\
48085
48269
  - to_date\uFF08\u53EF\u9009\uFF09\uFF1A\u8FC7\u6EE4\u6B64\u65E5\u671F\u4E4B\u524D\u7684 session\uFF08ISO 8601 \u683C\u5F0F\uFF09
48086
48270
 
48087
48271
  \u8F93\u51FA\u793A\u4F8B\uFF1A
48088
- | Session ID | Messages | First | Last | Agents |
48089
- |------------|----------|-------|------|--------|
48090
- | ses_abc123 | 45 | 2025-12-20 | 2025-12-24 | build, \u6280\u672F\u53C2\u8C0B |
48091
- | ses_def456 | 12 | 2025-12-19 | 2025-12-19 | build |`;
48272
+ | Session ID | \u6807\u9898 | Messages | First | Last | Agents |
48273
+ |------------|------|----------|-------|------|--------|
48274
+ | ses_abc123 | \u9879\u76EE\u91CD\u6784 | 45 | 2025-12-20 | 2025-12-24 | build, \u6280\u672F\u53C2\u8C0B |
48275
+ | ses_def456 | | 12 | 2025-12-19 | 2025-12-19 | build |`;
48092
48276
  var SESSION_READ_DESCRIPTION = `\u8BFB\u53D6 OpenCode session \u4E2D\u7684\u6D88\u606F\u548C\u5386\u53F2\u8BB0\u5F55\u3002
48093
48277
 
48094
48278
  \u8FD4\u56DE\u683C\u5F0F\u5316\u7684 session \u6D88\u606F\u89C6\u56FE\uFF0C\u5305\u542B\u89D2\u8272\u3001\u65F6\u95F4\u6233\u548C\u5185\u5BB9\u3002\u53EF\u9009\u62E9\u5305\u542B todo \u548C transcript \u6570\u636E\u3002
@@ -48139,6 +48323,7 @@ var SESSION_INFO_DESCRIPTION = `\u83B7\u53D6 OpenCode session \u7684\u5143\u6570
48139
48323
 
48140
48324
  \u8F93\u51FA\u793A\u4F8B\uFF1A
48141
48325
  Session ID: ses_abc123
48326
+ Title: \u9879\u76EE\u91CD\u6784
48142
48327
  Messages: 45
48143
48328
  Date Range: 2025-12-20 10:30:00 to 2025-12-24 15:45:30
48144
48329
  Duration: 4 days, 5 hours
@@ -48328,6 +48513,26 @@ async function readSessionTranscript(sessionID) {
48328
48513
  return 0;
48329
48514
  }
48330
48515
  }
48516
+ async function findSessionMetadata(sessionID) {
48517
+ if (!existsSync49(SESSION_STORAGE))
48518
+ return null;
48519
+ try {
48520
+ const projectDirs = await readdir(SESSION_STORAGE, { withFileTypes: true });
48521
+ for (const projectDir of projectDirs) {
48522
+ if (!projectDir.isDirectory())
48523
+ continue;
48524
+ const projectPath = join59(SESSION_STORAGE, projectDir.name);
48525
+ const filePath = join59(projectPath, `${sessionID}.json`);
48526
+ if (!existsSync49(filePath))
48527
+ continue;
48528
+ const content = await readFile(filePath, "utf-8");
48529
+ return JSON.parse(content);
48530
+ }
48531
+ } catch {
48532
+ return null;
48533
+ }
48534
+ return null;
48535
+ }
48331
48536
  async function getSessionInfo(sessionID) {
48332
48537
  const messages = await readSessionMessages(sessionID);
48333
48538
  if (messages.length === 0)
@@ -48348,6 +48553,7 @@ async function getSessionInfo(sessionID) {
48348
48553
  }
48349
48554
  const todos = await readSessionTodos(sessionID);
48350
48555
  const transcriptEntries = await readSessionTranscript(sessionID);
48556
+ const metadata = await findSessionMetadata(sessionID);
48351
48557
  return {
48352
48558
  id: sessionID,
48353
48559
  message_count: messages.length,
@@ -48357,27 +48563,34 @@ async function getSessionInfo(sessionID) {
48357
48563
  has_todos: todos.length > 0,
48358
48564
  has_transcript: transcriptEntries > 0,
48359
48565
  todos,
48360
- transcript_entries: transcriptEntries
48566
+ transcript_entries: transcriptEntries,
48567
+ title: metadata?.title
48361
48568
  };
48362
48569
  }
48363
48570
 
48364
48571
  // src/tools/session-manager/utils.ts
48365
- async function formatSessionList(sessionIDs) {
48366
- if (sessionIDs.length === 0) {
48572
+ async function formatSessionList(sessions) {
48573
+ if (sessions.length === 0) {
48367
48574
  return "\u672A\u627E\u5230\u4F1A\u8BDD\u3002";
48368
48575
  }
48369
- const infos = (await Promise.all(sessionIDs.map((id) => getSessionInfo(id)))).filter((info) => info !== null);
48576
+ const titleMap = new Map(sessions.map((s) => [s.id, s.title]));
48577
+ const infos = (await Promise.all(sessions.map((s) => getSessionInfo(s.id)))).filter((info) => info !== null);
48370
48578
  if (infos.length === 0) {
48371
48579
  return "\u672A\u627E\u5230\u6709\u6548\u4F1A\u8BDD\u3002";
48372
48580
  }
48373
- const headers = ["\u4F1A\u8BDDID", "\u6D88\u606F\u6570", "\u9996\u6761", "\u672B\u6761", "\u4EE3\u7406"];
48374
- const rows = infos.map((info) => [
48375
- info.id,
48376
- info.message_count.toString(),
48377
- info.first_message?.toISOString().split("T")[0] ?? "\u65E0",
48378
- info.last_message?.toISOString().split("T")[0] ?? "\u65E0",
48379
- info.agents_used.join(", ") || "\u65E0"
48380
- ]);
48581
+ const headers = ["\u4F1A\u8BDDID", "\u6807\u9898", "\u6D88\u606F\u6570", "\u9996\u6761", "\u672B\u6761", "\u4EE3\u7406"];
48582
+ const rows = infos.map((info) => {
48583
+ const title = titleMap.get(info.id) ?? "";
48584
+ const displayTitle = title.length > 30 ? title.slice(0, 30) + "..." : title;
48585
+ return [
48586
+ info.id,
48587
+ displayTitle,
48588
+ info.message_count.toString(),
48589
+ info.first_message?.toISOString().split("T")[0] ?? "\u65E0",
48590
+ info.last_message?.toISOString().split("T")[0] ?? "\u65E0",
48591
+ info.agents_used.join(", ") || "\u65E0"
48592
+ ];
48593
+ });
48381
48594
  const colWidths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
48382
48595
  const formatRow = (cells) => {
48383
48596
  return "| " + cells.map((cell, i) => cell.padEnd(colWidths[i])).join(" | ").trim() + " |";
@@ -48425,6 +48638,7 @@ function formatSessionMessages(messages, includeTodos, todos) {
48425
48638
  function formatSessionInfo(info) {
48426
48639
  const lines = [
48427
48640
  `\u4F1A\u8BDDID\uFF1A${info.id}`,
48641
+ `\u6807\u9898\uFF1A${info.title ?? ""}`,
48428
48642
  `\u6D88\u606F\u6570\uFF1A${info.message_count}`,
48429
48643
  `\u65E5\u671F\u8303\u56F4\uFF1A${info.first_message?.toISOString() ?? "\u65E0"} \u81F3 ${info.last_message?.toISOString() ?? "\u65E0"}`,
48430
48644
  `\u4F7F\u7528\u7684\u4EE3\u7406\uFF1A${info.agents_used.join(", ") || "\u65E0"}`,
@@ -48540,14 +48754,15 @@ var session_list = tool({
48540
48754
  try {
48541
48755
  const directory = args.project_path ?? process.cwd();
48542
48756
  let sessions = await getMainSessions({ directory });
48543
- let sessionIDs = sessions.map((s) => s.id);
48544
48757
  if (args.from_date || args.to_date) {
48545
- sessionIDs = await filterSessionsByDate(sessionIDs, args.from_date, args.to_date);
48758
+ const filteredIDs = await filterSessionsByDate(sessions.map((s) => s.id), args.from_date, args.to_date);
48759
+ const idSet = new Set(filteredIDs);
48760
+ sessions = sessions.filter((s) => idSet.has(s.id));
48546
48761
  }
48547
48762
  if (args.limit && args.limit > 0) {
48548
- sessionIDs = sessionIDs.slice(0, args.limit);
48763
+ sessions = sessions.slice(0, args.limit);
48549
48764
  }
48550
- return await formatSessionList(sessionIDs);
48765
+ return await formatSessionList(sessions);
48551
48766
  } catch (e) {
48552
48767
  return `\u9519\u8BEF\uFF1A${e instanceof Error ? e.message : String(e)}`;
48553
48768
  }
@@ -49529,6 +49744,7 @@ var CALL_OMO_AGENT_DESCRIPTION = `\u542F\u52A8\u6DF1\u5EA6\u63A2\u7D22/\u77E5\u8
49529
49744
  import { existsSync as existsSync50, readdirSync as readdirSync17 } from "fs";
49530
49745
  import { join as join60 } from "path";
49531
49746
  init_shared();
49747
+ init_agent_permissions();
49532
49748
  init_agent_display_names();
49533
49749
  init_session_cursor();
49534
49750
  init_claude_code_session_state();
@@ -50148,6 +50364,7 @@ init_shared();
50148
50364
  init_agent_display_names();
50149
50365
  init_runtime_fallback();
50150
50366
  init_model_health_registry();
50367
+ init_agent_permissions();
50151
50368
  init_agent_identity_resolver();
50152
50369
  var SISYPHUS_JUNIOR_AGENT = "\u6267\u884C\u52A9\u7406";
50153
50370
  var MAX_LOOP_ATTEMPTS = 10;
@@ -50729,6 +50946,7 @@ ${supervisedResult}`;
50729
50946
  const sessionID = createResult.data.id;
50730
50947
  syncSessionID = sessionID;
50731
50948
  subagentSessions.add(sessionID);
50949
+ updateSessionAgent(sessionID, agentToUse, "delegate-task");
50732
50950
  taskId = `sync_${sessionID.slice(0, 8)}`;
50733
50951
  const startTime = new Date;
50734
50952
  if (toastManager) {
@@ -51445,6 +51663,7 @@ class BackgroundManager {
51445
51663
  }
51446
51664
  const sessionID = createResult.data.id;
51447
51665
  subagentSessions.add(sessionID);
51666
+ updateSessionAgent(sessionID, input.agent, "background-agent");
51448
51667
  task.status = "running";
51449
51668
  task.startedAt = new Date;
51450
51669
  task.sessionID = sessionID;
@@ -72368,6 +72587,7 @@ var PROMETHEUS_SYSTEM_PROMPT = `<system-reminder>
72368
72587
  \u25A1 \u6280\u672F\u65B9\u6848\u662F\u5426\u5DF2\u7ECF\u786E\u5B9A\uFF1F
72369
72588
  \u25A1 \u6D4B\u8BD5\u7B56\u7565\u662F\u5426\u5DF2\u7ECF\u786E\u8BA4\uFF08TDD / \u4E8B\u540E\u6D4B\u8BD5 / \u4EC5\u624B\u52A8\uFF09\uFF1F
72370
72589
  \u25A1 \u662F\u5426\u6709\u672A\u89E3\u51B3\u7684\u963B\u585E\u6027\u95EE\u9898\uFF1F
72590
+ \u25A1 \u9884\u5BA1\u987E\u95EE\u662F\u5426\u5DF2\u5B8C\u6210\u5DEE\u8DDD\u5206\u6790\uFF1F\uFF08\u6B64\u68C0\u67E5\u4EC5\u5728\u9884\u5BA1\u987E\u95EE\u54A8\u8BE2\u9636\u6BB5\u540E\u8FDB\u884C\uFF0C\u5176\u4ED6\u9636\u6BB5\u4E0D\u9002\u7528\uFF09
72371
72591
 
72372
72592
  \u2192 \u5168\u90E8\u6EE1\u8DB3\uFF1A\u6211\u4F1A\u8BF4"\u6240\u6709\u9700\u6C42\u660E\u786E\uFF0C\u5F00\u59CB\u751F\u6210\u8BA1\u5212\u3002"\u7136\u540E\u63A8\u8FDB\u3002
72373
72593
  \u2192 \u4EFB\u4F55\u4E00\u9879\u4E0D\u6EE1\u8DB3\uFF1A\u6211\u4F1A\u9488\u5BF9\u6027\u5730\u63D0\u51FA\u6F84\u6E05\u95EE\u9898\uFF0C\u7EE7\u7EED\u8BBF\u8C08\u3002
@@ -72447,6 +72667,25 @@ var PROMETHEUS_SYSTEM_PROMPT = `<system-reminder>
72447
72667
 
72448
72668
  **\u6211\u7EDD\u4E0D\u4F1A\u8DF3\u8FC7\u8349\u7A3F\u66F4\u65B0\u3002\u6211\u7684\u8BB0\u5FC6\u662F\u6709\u9650\u7684\u3002\u8349\u7A3F\u662F\u6211\u7684\u5907\u4EFD\u5927\u8111\u3002**
72449
72669
 
72670
+ ### \u94C1\u5F8B\u4E03\uFF1A\u6D41\u7A0B\u987A\u5E8F\u4E0D\u53EF\u8FDD\u53CD
72671
+
72672
+ \u6211\u7684\u5DE5\u4F5C\u9636\u6BB5\u6709\u4E25\u683C\u7684\u524D\u540E\u4F9D\u8D56\u5173\u7CFB\uFF1A**\u8BBF\u8C08 \u2192 \u9884\u5BA1\u987E\u95EE\u54A8\u8BE2 \u2192 \u8BA1\u5212\u751F\u6210 \u2192 \u81EA\u6211\u5BA1\u67E5 \u2192 \u5448\u73B0\u6458\u8981 \u2192 \u9AD8\u7CBE\u5EA6\u5BA1\u67E5\uFF08\u53EF\u9009\uFF09\u2192 \u4EA4\u63A5\u3002**
72673
+
72674
+ \u8FD9\u4E9B\u9636\u6BB5\u7684\u987A\u5E8F\u662F\u94C1\u5F8B\u3002\u5177\u4F53\u6765\u8BF4\uFF1A
72675
+
72676
+ **\u5173\u952E\u7981\u4EE4**\uFF08\u4E0D\u53EF\u8FDD\u53CD\uFF09\uFF1A
72677
+ - \u274C \u9884\u5BA1\u987E\u95EE\uFF08plan-1\uFF09\u5C1A\u672A\u5B8C\u6210\u65F6\uFF0C**\u4E0D\u5F97**\u5F00\u59CB\u751F\u6210\u8BA1\u5212\uFF08plan-2\uFF09
72678
+ - \u274C \u9884\u5BA1\u987E\u95EE\u5C1A\u672A\u5B8C\u6210\u65F6\uFF0C**\u4E0D\u5F97**\u5F00\u59CB\u81EA\u6211\u5BA1\u67E5\uFF08plan-3\uFF09
72679
+ - \u274C \u9884\u5BA1\u987E\u95EE\u5C1A\u672A\u5B8C\u6210\u65F6\uFF0C**\u4E0D\u5F97**\u63D0\u4EA4\u7ED9\u8BA1\u5212\u5BA1\u67E5\uFF08plan-7\uFF09
72680
+ - \u274C \u4EFB\u4F55\u60C5\u51B5\u4E0B\u90FD\u4E0D\u5F97"\u4E0D\u7B49\u9884\u5BA1\u987E\u95EE\u4E86\uFF0C\u5148\u7EE7\u7EED"
72681
+
72682
+ **\u6B63\u786E\u7684\u884C\u4E3A**\uFF1A
72683
+ 1. \u8C03\u7528\u9884\u5BA1\u987E\u95EE\u540E\uFF0C\u5982\u679C\u5B83\u8FD8\u5728\u8FD0\u884C\uFF08\u72B6\u6001\u4E3A \`running\`\uFF09\uFF0C\u6211\u5FC5\u987B\u4F7F\u7528 \`background_output\` \u540C\u6B65\u7B49\u5F85\u5B83\u5B8C\u6210
72684
+ 2. \u53EA\u6709\u9884\u5BA1\u987E\u95EE\u8FD4\u56DE\u7ED3\u679C\u540E\uFF0C\u6211\u624D\u80FD\u7EE7\u7EED\u5230 plan-2\uFF08\u751F\u6210\u8BA1\u5212\uFF09
72685
+ 3. \u5982\u679C\u9884\u5BA1\u987E\u95EE\u957F\u65F6\u95F4\u672A\u8FD4\u56DE\uFF0C\u6211\u5E94\u5F53\u544A\u77E5\u4F60\u5E76\u8BE2\u95EE\u5982\u4F55\u5904\u7406\u2014\u2014\u800C\u4E0D\u662F\u81EA\u884C\u8DF3\u8FC7
72686
+
72687
+ **\u4E3A\u4EC0\u4E48**\uFF1A\u9884\u5BA1\u987E\u95EE\u53D1\u73B0\u7684\u5DEE\u8DDD\u76F4\u63A5\u51B3\u5B9A\u8BA1\u5212\u8D28\u91CF\u3002\u8DF3\u8FC7\u9884\u5BA1\u987E\u95EE\u7B49\u4E8E\u5728\u4E0D\u77E5\u9053\u7F3A\u53E3\u7684\u60C5\u51B5\u4E0B\u5EFA\u9020\u2014\u2014\u8FD9\u662F\u5EFA\u9020\uFF0C\u4E0D\u662F\u89C4\u5212\u3002\u4F5C\u4E3A\u6218\u7565\u53C2\u8C0B\uFF0C\u6211\u7684\u6838\u5FC3\u4EF7\u503C\u5C31\u662F\u5728\u6267\u884C\u4E4B\u524D\u53D1\u73B0\u6240\u6709\u53EF\u80FD\u7684\u95EE\u9898\u3002
72688
+
72450
72689
  ---
72451
72690
 
72452
72691
  ## \u6BCF\u6B21\u56DE\u590D\u524D\u7684\u6B62\u6B65\u68C0\u67E5
@@ -72849,10 +73088,12 @@ todoWrite([
72849
73088
 
72850
73089
  \u8FD9\u4E2A\u4EFB\u52A1\u5217\u8868\u8BA9\u4F60\u80FD\u51C6\u786E\u770B\u5230\u8FD8\u6709\u54EA\u4E9B\u6B65\u9AA4\uFF0C\u9632\u6B62\u4EFB\u4F55\u5173\u952E\u6B65\u9AA4\u88AB\u9057\u6F0F\uFF0C\u4E3A\u6BCF\u4E2A\u9636\u6BB5\u5EFA\u7ACB\u8D23\u4EFB\u5236\uFF0C\u5E76\u5728\u4F1A\u8BDD\u4E2D\u65AD\u65F6\u652F\u6301\u6062\u590D\u3002
72851
73090
 
72852
- **\u6211\u7684\u5DE5\u4F5C\u6D41**\uFF1A
73091
+ **\u6211\u7684\u5DE5\u4F5C\u6D41\uFF08\u4E25\u683C\u987A\u5E8F\u6267\u884C\uFF0C\u6BCF\u4E00\u6B65\u4F9D\u8D56\u524D\u4E00\u6B65\u5B8C\u6210\uFF09**\uFF1A
72853
73092
  1. \u68C0\u6D4B\u5230\u89E6\u53D1 \u2192 **\u7ACB\u5373** TodoWrite\uFF08plan-1 \u5230 plan-8\uFF09
72854
73093
  2. \u6807\u8BB0 plan-1 \u4E3A \`in_progress\` \u2192 \u54A8\u8BE2 \u9884\u5BA1\u987E\u95EE\uFF08\u81EA\u52A8\u8FDB\u884C\uFF0C\u65E0\u9700\u989D\u5916\u63D0\u95EE\uFF09
72855
- 3. \u6807\u8BB0 plan-2 \u4E3A \`in_progress\` \u2192 \u7ACB\u5373\u751F\u6210\u8BA1\u5212
73094
+ \u26A0\uFE0F **\u5173\u952E\u7B49\u5F85\u70B9**\uFF1A\u6B64\u65F6\u5FC5\u987B\u540C\u6B65\u7B49\u5F85 preaudit \u8FD4\u56DE\u7ED3\u679C\uFF0Cplan-1 \u5B8C\u6210\u540E\u624D\u80FD\u7EE7\u7EED
73095
+ 3. \u786E\u8BA4 plan-1\uFF08\u9884\u5BA1\u987E\u95EE\uFF09\u5DF2\u5B8C\u6210 \u2192 \u6807\u8BB0 plan-2 \u4E3A \`in_progress\` \u2192 \u7ACB\u5373\u751F\u6210\u8BA1\u5212
73096
+ \uFF08plan-2 \u4F9D\u8D56 plan-1 \u5B8C\u6210\uFF0C\u7EDD\u4E0D\u53EF\u5E76\u884C\u6216\u63D0\u524D\u6267\u884C\uFF09
72856
73097
  4. \u6807\u8BB0 plan-3 \u4E3A \`in_progress\` \u2192 \u81EA\u6211\u5BA1\u67E5\u5E76\u5206\u7C7B\u5DEE\u8DDD
72857
73098
  5. \u6807\u8BB0 plan-4 \u4E3A \`in_progress\` \u2192 \u5448\u73B0\u6458\u8981\uFF08\u5305\u542B\u81EA\u52A8\u89E3\u51B3/\u9ED8\u8BA4/\u51B3\u7B56\uFF09
72858
73099
  6. \u6807\u8BB0 plan-5 \u4E3A \`in_progress\` \u2192 \u5982\u679C\u9700\u8981\u51B3\u7B56\uFF0C\u7B49\u5F85\u4F60\u5E76\u66F4\u65B0\u8BA1\u5212
@@ -72892,8 +73133,27 @@ delegate_task(
72892
73133
  )
72893
73134
  \`\`\`
72894
73135
 
73136
+ > **\u26A0\uFE0F \u7EDD\u5BF9\u7981\u4EE4\uFF1A\u6B64\u8C03\u7528\u5FC5\u987B\u540C\u6B65\u963B\u585E\uFF08run_in_background=false\uFF09**
73137
+ >
73138
+ > \`run_in_background=false\` \u662F**\u4E0D\u53EF\u66F4\u6539\u7684**\u3002\u7406\u7531\uFF1A
73139
+ > 1. \u9884\u5BA1\u987E\u95EE\u7684\u5206\u6790\u7ED3\u679C\u662F\u8BA1\u5212\u751F\u6210\u7684\u524D\u63D0\u6761\u4EF6\uFF0C\u6CA1\u6709\u5B83\u6211\u65E0\u6CD5\u5199\u51FA\u6B63\u786E\u7684\u8BA1\u5212
73140
+ > 2. \u5982\u679C\u6211\u6539\u7528 \`run_in_background=true\`\uFF0C\u7CFB\u7EDF\u4E0D\u4F1A\u963B\u6B62\u6211\u2014\u2014\u4F46\u6211\u4F1A\u56E0\u6B64\u5931\u804C
73141
+ > 3. \u8BA1\u5212\u5BA1\u67E5\uFF08Momus\uFF09\u4F1A\u53D1\u73B0\u6240\u6709\u672C\u5E94\u88AB\u9884\u5BA1\u987E\u95EE\u63D0\u524D\u53D1\u73B0\u7684\u7F3A\u53E3\uFF0C\u9020\u6210\u989D\u5916\u7684\u4FEE\u590D\u5FAA\u73AF
73142
+ > 4. \u7528\u6237\u9009\u62E9\u9AD8\u7CBE\u5EA6\u6A21\u5F0F\u65F6\uFF0C\u8BA1\u5212\u5BA1\u67E5\u4F1A\u53D1\u73B0\u66F4\u591A\u95EE\u9898\uFF0C\u9020\u6210\u4FE1\u4EFB\u635F\u5931
73143
+ >
73144
+ > **\u5982\u679C\u4F60\u53D1\u73B0\u81EA\u5DF1\u5728\u601D\u8003"\u4E0D\u7B49\u9884\u5BA1\u987E\u95EE\u4E86\uFF0C\u5148\u5F00\u59CB\u751F\u6210\u8BA1\u5212"\uFF0C\u505C\u4E0B\u6765\u3002**
73145
+ > \u8FD9\u662F\u6D41\u7A0B\u8FDD\u89C4\u7684\u524D\u5146\u3002\u6B63\u786E\u7684\u505A\u6CD5\u662F\uFF1A
73146
+ > 1. \u4F7F\u7528 \`background_output(task_id)\` \u540C\u6B65\u7B49\u5F85\u9884\u5BA1\u987E\u95EE\u5B8C\u6210
73147
+ > 2. \u5982\u679C\u8D85\u65F6\uFF0C\u544A\u77E5\u7528\u6237\u5E76\u8BE2\u95EE\u5982\u4F55\u5904\u7406
73148
+ > 3. \u53EA\u6709\u5728\u9884\u5BA1\u987E\u95EE\u8FD4\u56DE\u7ED3\u679C\u540E\uFF0C\u624D\u80FD\u7EE7\u7EED\u5230 plan-2
73149
+
72895
73150
  ## \u6536\u5230 \u9884\u5BA1\u987E\u95EE \u5206\u6790\u540E\uFF1A\u81EA\u52A8\u751F\u6210\u8BA1\u5212\u548C\u603B\u7ED3
72896
73151
 
73152
+ **\u5148\u786E\u8BA4\uFF1A\u9884\u5BA1\u987E\u95EE\u7684\u5206\u6790\u662F\u5426\u5DF2\u8FD4\u56DE\uFF1F**
73153
+ - \u5982\u679C\u9884\u5BA1\u987E\u95EE\u4ECD\u5728\u8FD0\u884C\uFF08\u72B6\u6001\u4E3A \`running\`\uFF09\uFF1A\u4F7F\u7528 \`background_output\` **\u540C\u6B65\u7B49\u5F85**\u5B83\u5B8C\u6210
73154
+ - \u5982\u679C\u9884\u5BA1\u987E\u95EE\u5DF2\u8FD4\u56DE\u7ED3\u679C\uFF1A\u7EE7\u7EED\u4E0B\u4E00\u6B65
73155
+ - **\u7EDD\u4E0D**\u5728\u9884\u5BA1\u987E\u95EE\u672A\u5B8C\u6210\u65F6\u7EE7\u7EED
73156
+
72897
73157
  \u6536\u5230 \u9884\u5BA1\u987E\u95EE \u7684\u5206\u6790\u540E\uFF0C\u6211**\u4E0D\u4F1A\u63D0\u51FA\u989D\u5916\u7684\u95EE\u9898**\u3002\u800C\u662F\uFF1A
72898
73158
 
72899
73159
  1. **\u5C06 \u9884\u5BA1\u987E\u95EE \u7684\u53D1\u73B0**\u9759\u9ED8\u878D\u5165\u6211\u7684\u7406\u89E3
@@ -73024,6 +73284,17 @@ Question({
73024
73284
 
73025
73285
  ## \u9AD8\u7CBE\u5EA6\u6A21\u5F0F\u2014\u2014\u5F3A\u5236\u5FAA\u73AF
73026
73286
 
73287
+ ### \u8FDB\u5165\u9AD8\u7CBE\u5EA6\u6A21\u5F0F\u7684\u524D\u7F6E\u6761\u4EF6
73288
+
73289
+ \u5728\u8FDB\u5165\u9AD8\u7CBE\u5EA6\u5BA1\u67E5\u5FAA\u73AF\u4E4B\u524D\uFF0C\u6211\u5FC5\u987B\u5148\u786E\u8BA4\uFF1A
73290
+
73291
+ - [ ] \u9884\u5BA1\u987E\u95EE\u7684\u5DEE\u8DDD\u5206\u6790\u5DF2\u5B8C\u6210\u5E76\u6574\u5408\u5230\u8BA1\u5212\u4E2D
73292
+ - [ ] \u8BA1\u5212\u6587\u4EF6\u4E2D\u7684"\u9884\u5BA1\u987E\u95EE \u5BA1\u67E5"\u7AE0\u8282\u5DF2\u586B\u5199\u5B8C\u6574
73293
+ - [ ] \u81EA\u6211\u5BA1\u67E5\u5DF2\u5B8C\u6210
73294
+
73295
+ **\u5982\u679C\u9884\u5BA1\u987E\u95EE\u7684\u53D1\u73B0\u5C1A\u672A\u88AB\u6574\u5408\u5230\u8BA1\u5212\u4E2D\uFF0C\u6211\u4E0D\u5F97\u63D0\u4EA4\u7ED9\u8BA1\u5212\u5BA1\u67E5\u3002**
73296
+ \u5FC5\u987B\u5148\u9000\u51FA\u9AD8\u7CBE\u5EA6\u6A21\u5F0F\uFF0C\u6574\u5408\u9884\u5BA1\u987E\u95EE\u7684\u53D1\u73B0\uFF0C\u66F4\u65B0\u8BA1\u5212\u6587\u4EF6\uFF0C\u7136\u540E\u91CD\u65B0\u5F00\u59CB\u9AD8\u7CBE\u5EA6\u5BA1\u67E5\u3002
73297
+
73027
73298
  \u5F53\u4F60\u8981\u6C42\u9AD8\u7CBE\u5EA6\u65F6\uFF0C\u8FD9\u5BF9\u6211\u6765\u8BF4\u662F\u4E00\u4E2A\u4E0D\u53EF\u534F\u5546\u7684\u627F\u8BFA\u3002
73028
73299
 
73029
73300
  ### \u8BA1\u5212\u5BA1\u67E5 \u5BA1\u67E5\u5FAA\u73AF\uFF08\u7EDD\u5BF9\u8981\u6C42\uFF09
@@ -73632,29 +73903,14 @@ function createConfigHandler(deps) {
73632
73903
  LspCodeActions: false,
73633
73904
  LspCodeActionResolve: false
73634
73905
  };
73635
- if (agentResult["\u77E5\u8BC6\u5178\u85CF"]) {
73636
- const agent = agentResult["\u77E5\u8BC6\u5178\u85CF"];
73637
- agent.permission = { ...agent.permission, "grep_app_*": "allow" };
73638
- }
73639
- if (agentResult["\u5A92\u4F53\u89E3\u6790"]) {
73640
- const agent = agentResult["\u5A92\u4F53\u89E3\u6790"];
73641
- agent.permission = { ...agent.permission, task: "deny", look_at: "deny" };
73642
- }
73643
- if (agentResult["\u4EFB\u52A1\u7F16\u6392"]) {
73644
- const agent = agentResult["\u4EFB\u52A1\u7F16\u6392"];
73645
- agent.permission = { ...agent.permission, task: "deny", call_omo_agent: "deny", delegate_task: "allow" };
73646
- }
73647
- if (agentResult["\u4E3B\u6267\u884C\u5B98"]) {
73648
- const agent = agentResult["\u4E3B\u6267\u884C\u5B98"];
73649
- agent.permission = { ...agent.permission, call_omo_agent: "deny", delegate_task: "allow", question: "allow" };
73650
- }
73651
- if (agentResult["\u6218\u7565\u53C2\u8C0B"]) {
73652
- const agent = agentResult["\u6218\u7565\u53C2\u8C0B"];
73653
- agent.permission = { ...agent.permission, call_omo_agent: "deny", delegate_task: "allow", question: "allow" };
73654
- }
73655
- if (agentResult["\u6267\u884C\u52A9\u7406"]) {
73656
- const agent = agentResult["\u6267\u884C\u52A9\u7406"];
73657
- agent.permission = { ...agent.permission, delegate_task: "allow" };
73906
+ for (const [agentName, agent] of Object.entries(agentResult)) {
73907
+ if (!agent)
73908
+ continue;
73909
+ const typedAgent = agent;
73910
+ const sdkPermission = deriveSdkPermission(agentName);
73911
+ if (Object.keys(sdkPermission).length > 0) {
73912
+ typedAgent.permission = { ...typedAgent.permission, ...sdkPermission };
73913
+ }
73658
73914
  }
73659
73915
  config4.permission = {
73660
73916
  ...config4.permission,