oh-my-opencode 3.1.8 → 3.1.10

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
@@ -58,15 +58,40 @@ var init_constants = __esm(() => {
58
58
  PART_STORAGE = join2(OPENCODE_STORAGE, "part");
59
59
  });
60
60
 
61
+ // src/shared/logger.ts
62
+ var exports_logger = {};
63
+ __export(exports_logger, {
64
+ log: () => log,
65
+ getLogFilePath: () => getLogFilePath
66
+ });
67
+ import * as fs from "fs";
68
+ import * as os2 from "os";
69
+ import * as path2 from "path";
70
+ function log(message, data) {
71
+ try {
72
+ const timestamp = new Date().toISOString();
73
+ const logEntry = `[${timestamp}] ${message} ${data ? JSON.stringify(data) : ""}
74
+ `;
75
+ fs.appendFileSync(logFile, logEntry);
76
+ } catch {}
77
+ }
78
+ function getLogFilePath() {
79
+ return logFile;
80
+ }
81
+ var logFile;
82
+ var init_logger = __esm(() => {
83
+ logFile = path2.join(os2.tmpdir(), "oh-my-opencode.log");
84
+ });
85
+
61
86
  // src/features/hook-message-injector/injector.ts
62
87
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
63
- import { join as join3 } from "path";
88
+ import { join as join4 } from "path";
64
89
  function findNearestMessageWithFields(messageDir) {
65
90
  try {
66
91
  const files = readdirSync(messageDir).filter((f) => f.endsWith(".json")).sort().reverse();
67
92
  for (const file of files) {
68
93
  try {
69
- const content = readFileSync(join3(messageDir, file), "utf-8");
94
+ const content = readFileSync(join4(messageDir, file), "utf-8");
70
95
  const msg = JSON.parse(content);
71
96
  if (msg.agent && msg.model?.providerID && msg.model?.modelID) {
72
97
  return msg;
@@ -77,7 +102,7 @@ function findNearestMessageWithFields(messageDir) {
77
102
  }
78
103
  for (const file of files) {
79
104
  try {
80
- const content = readFileSync(join3(messageDir, file), "utf-8");
105
+ const content = readFileSync(join4(messageDir, file), "utf-8");
81
106
  const msg = JSON.parse(content);
82
107
  if (msg.agent || msg.model?.providerID && msg.model?.modelID) {
83
108
  return msg;
@@ -96,7 +121,7 @@ function findFirstMessageWithAgent(messageDir) {
96
121
  const files = readdirSync(messageDir).filter((f) => f.endsWith(".json")).sort();
97
122
  for (const file of files) {
98
123
  try {
99
- const content = readFileSync(join3(messageDir, file), "utf-8");
124
+ const content = readFileSync(join4(messageDir, file), "utf-8");
100
125
  const msg = JSON.parse(content);
101
126
  if (msg.agent) {
102
127
  return msg.agent;
@@ -124,12 +149,12 @@ function getOrCreateMessageDir(sessionID) {
124
149
  if (!existsSync(MESSAGE_STORAGE)) {
125
150
  mkdirSync(MESSAGE_STORAGE, { recursive: true });
126
151
  }
127
- const directPath = join3(MESSAGE_STORAGE, sessionID);
152
+ const directPath = join4(MESSAGE_STORAGE, sessionID);
128
153
  if (existsSync(directPath)) {
129
154
  return directPath;
130
155
  }
131
156
  for (const dir of readdirSync(MESSAGE_STORAGE)) {
132
- const sessionPath = join3(MESSAGE_STORAGE, dir, sessionID);
157
+ const sessionPath = join4(MESSAGE_STORAGE, dir, sessionID);
133
158
  if (existsSync(sessionPath)) {
134
159
  return sessionPath;
135
160
  }
@@ -139,7 +164,7 @@ function getOrCreateMessageDir(sessionID) {
139
164
  }
140
165
  function injectHookMessage(sessionID, hookContent, originalMessage) {
141
166
  if (!hookContent || hookContent.trim().length === 0) {
142
- console.warn("[hook-message-injector] Attempted to inject empty hook content, skipping injection", {
167
+ log("[hook-message-injector] Attempted to inject empty hook content, skipping injection", {
143
168
  sessionID,
144
169
  hasAgent: !!originalMessage.agent,
145
170
  hasModel: !!(originalMessage.model?.providerID && originalMessage.model?.modelID)
@@ -191,12 +216,12 @@ function injectHookMessage(sessionID, hookContent, originalMessage) {
191
216
  sessionID
192
217
  };
193
218
  try {
194
- writeFileSync(join3(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
195
- const partDir = join3(PART_STORAGE, messageID);
219
+ writeFileSync(join4(messageDir, `${messageID}.json`), JSON.stringify(messageMeta, null, 2));
220
+ const partDir = join4(PART_STORAGE, messageID);
196
221
  if (!existsSync(partDir)) {
197
222
  mkdirSync(partDir, { recursive: true });
198
223
  }
199
- writeFileSync(join3(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
224
+ writeFileSync(join4(partDir, `${partID}.json`), JSON.stringify(textPart, null, 2));
200
225
  return true;
201
226
  } catch {
202
227
  return false;
@@ -204,6 +229,7 @@ function injectHookMessage(sessionID, hookContent, originalMessage) {
204
229
  }
205
230
  var init_injector = __esm(() => {
206
231
  init_constants();
232
+ init_logger();
207
233
  });
208
234
 
209
235
  // src/features/hook-message-injector/index.ts
@@ -212,31 +238,6 @@ var init_hook_message_injector = __esm(() => {
212
238
  init_constants();
213
239
  });
214
240
 
215
- // src/shared/logger.ts
216
- var exports_logger = {};
217
- __export(exports_logger, {
218
- log: () => log,
219
- getLogFilePath: () => getLogFilePath
220
- });
221
- import * as fs from "fs";
222
- import * as os2 from "os";
223
- import * as path2 from "path";
224
- function log(message, data) {
225
- try {
226
- const timestamp = new Date().toISOString();
227
- const logEntry = `[${timestamp}] ${message} ${data ? JSON.stringify(data) : ""}
228
- `;
229
- fs.appendFileSync(logFile, logEntry);
230
- } catch {}
231
- }
232
- function getLogFilePath() {
233
- return logFile;
234
- }
235
- var logFile;
236
- var init_logger = __esm(() => {
237
- logFile = path2.join(os2.tmpdir(), "oh-my-opencode.log");
238
- });
239
-
240
241
  // src/shared/system-directive.ts
241
242
  function createSystemDirective(type) {
242
243
  return `${SYSTEM_DIRECTIVE_PREFIX} - ${type}]`;
@@ -4848,6 +4849,8 @@ var init_model_requirements = __esm(() => {
4848
4849
  sisyphus: {
4849
4850
  fallbackChain: [
4850
4851
  { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4852
+ { providers: ["kimi-for-coding"], model: "k2p5" },
4853
+ { providers: ["opencode"], model: "kimi-k2.5-free" },
4851
4854
  { providers: ["zai-coding-plan"], model: "glm-4.7" },
4852
4855
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
4853
4856
  { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
@@ -4856,14 +4859,14 @@ var init_model_requirements = __esm(() => {
4856
4859
  oracle: {
4857
4860
  fallbackChain: [
4858
4861
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
4859
- { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4860
- { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
4862
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" },
4863
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }
4861
4864
  ]
4862
4865
  },
4863
4866
  librarian: {
4864
4867
  fallbackChain: [
4865
4868
  { providers: ["zai-coding-plan"], model: "glm-4.7" },
4866
- { providers: ["opencode"], model: "big-pickle" },
4869
+ { providers: ["opencode"], model: "glm-4.7-free" },
4867
4870
  { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }
4868
4871
  ]
4869
4872
  },
@@ -4879,6 +4882,8 @@ var init_model_requirements = __esm(() => {
4879
4882
  { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
4880
4883
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
4881
4884
  { providers: ["zai-coding-plan"], model: "glm-4.6v" },
4885
+ { providers: ["kimi-for-coding"], model: "k2p5" },
4886
+ { providers: ["opencode"], model: "kimi-k2.5-free" },
4882
4887
  { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
4883
4888
  { providers: ["opencode"], model: "gpt-5-nano" }
4884
4889
  ]
@@ -4886,6 +4891,8 @@ var init_model_requirements = __esm(() => {
4886
4891
  prometheus: {
4887
4892
  fallbackChain: [
4888
4893
  { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4894
+ { providers: ["kimi-for-coding"], model: "k2p5" },
4895
+ { providers: ["opencode"], model: "kimi-k2.5-free" },
4889
4896
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
4890
4897
  { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
4891
4898
  ]
@@ -4893,6 +4900,8 @@ var init_model_requirements = __esm(() => {
4893
4900
  metis: {
4894
4901
  fallbackChain: [
4895
4902
  { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4903
+ { providers: ["kimi-for-coding"], model: "k2p5" },
4904
+ { providers: ["opencode"], model: "kimi-k2.5-free" },
4896
4905
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
4897
4906
  { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
4898
4907
  ]
@@ -4900,12 +4909,14 @@ var init_model_requirements = __esm(() => {
4900
4909
  momus: {
4901
4910
  fallbackChain: [
4902
4911
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" },
4903
- { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5" },
4912
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4904
4913
  { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
4905
4914
  ]
4906
4915
  },
4907
4916
  atlas: {
4908
4917
  fallbackChain: [
4918
+ { providers: ["kimi-for-coding"], model: "k2p5" },
4919
+ { providers: ["opencode"], model: "kimi-k2.5-free" },
4909
4920
  { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
4910
4921
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
4911
4922
  { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
@@ -4917,22 +4928,31 @@ var init_model_requirements = __esm(() => {
4917
4928
  fallbackChain: [
4918
4929
  { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" },
4919
4930
  { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4920
- { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }
4931
+ { providers: ["zai-coding-plan"], model: "glm-4.7" }
4921
4932
  ]
4922
4933
  },
4923
4934
  ultrabrain: {
4924
4935
  fallbackChain: [
4925
4936
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" },
4926
- { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4927
- { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
4937
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" },
4938
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }
4928
4939
  ]
4929
4940
  },
4941
+ deep: {
4942
+ fallbackChain: [
4943
+ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
4944
+ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4945
+ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
4946
+ ],
4947
+ requiresModel: "gpt-5.2-codex"
4948
+ },
4930
4949
  artistry: {
4931
4950
  fallbackChain: [
4932
4951
  { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" },
4933
4952
  { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
4934
4953
  { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
4935
- ]
4954
+ ],
4955
+ requiresModel: "gemini-3-pro"
4936
4956
  },
4937
4957
  quick: {
4938
4958
  fallbackChain: [
@@ -5246,29 +5266,31 @@ async function updateConnectedProvidersCache(client) {
5246
5266
  const connected = result.data?.connected ?? [];
5247
5267
  log("[connected-providers-cache] Fetched connected providers", { count: connected.length, providers: connected });
5248
5268
  writeConnectedProvidersCache(connected);
5269
+ let modelsByProvider = {};
5249
5270
  if (client.model?.list) {
5250
5271
  try {
5251
5272
  const modelsResult = await client.model.list();
5252
5273
  const models = modelsResult.data ?? [];
5253
- const modelsByProvider = {};
5254
5274
  for (const model of models) {
5255
5275
  if (!modelsByProvider[model.provider]) {
5256
5276
  modelsByProvider[model.provider] = [];
5257
5277
  }
5258
5278
  modelsByProvider[model.provider].push(model.id);
5259
5279
  }
5260
- writeProviderModelsCache({
5261
- models: modelsByProvider,
5262
- connected
5263
- });
5264
- log("[connected-providers-cache] Provider-models cache updated", {
5280
+ log("[connected-providers-cache] Fetched models from API", {
5265
5281
  providerCount: Object.keys(modelsByProvider).length,
5266
5282
  totalModels: models.length
5267
5283
  });
5268
5284
  } catch (modelErr) {
5269
- log("[connected-providers-cache] Error fetching models", { error: String(modelErr) });
5285
+ log("[connected-providers-cache] Error fetching models, writing empty cache", { error: String(modelErr) });
5270
5286
  }
5287
+ } else {
5288
+ log("[connected-providers-cache] client.model.list not available, writing empty cache");
5271
5289
  }
5290
+ writeProviderModelsCache({
5291
+ models: modelsByProvider,
5292
+ connected
5293
+ });
5272
5294
  } catch (err) {
5273
5295
  log("[connected-providers-cache] Error updating cache", { error: String(err) });
5274
5296
  }
@@ -5319,68 +5341,142 @@ function fuzzyMatchModel(target, available, providers) {
5319
5341
  log("[fuzzyMatchModel] shortest match", { result });
5320
5342
  return result;
5321
5343
  }
5322
- async function fetchAvailableModels(_client, options) {
5323
- const connectedProvidersUnknown = options?.connectedProviders === null || options?.connectedProviders === undefined;
5344
+ function isModelAvailable(targetModel, availableModels) {
5345
+ return fuzzyMatchModel(targetModel, availableModels) !== null;
5346
+ }
5347
+ async function getConnectedProviders(client) {
5348
+ if (!client?.provider?.list) {
5349
+ log("[getConnectedProviders] client.provider.list not available");
5350
+ return [];
5351
+ }
5352
+ try {
5353
+ const result = await client.provider.list();
5354
+ const connected = result.data?.connected ?? [];
5355
+ log("[getConnectedProviders] connected providers", { count: connected.length, providers: connected });
5356
+ return connected;
5357
+ } catch (err) {
5358
+ log("[getConnectedProviders] SDK error", { error: String(err) });
5359
+ return [];
5360
+ }
5361
+ }
5362
+ async function fetchAvailableModels(client, options) {
5363
+ let connectedProviders = options?.connectedProviders ?? null;
5364
+ let connectedProvidersUnknown = connectedProviders === null;
5324
5365
  log("[fetchAvailableModels] CALLED", {
5325
5366
  connectedProvidersUnknown,
5326
5367
  connectedProviders: options?.connectedProviders
5327
5368
  });
5369
+ if (connectedProvidersUnknown && client) {
5370
+ const liveConnected = await getConnectedProviders(client);
5371
+ if (liveConnected.length > 0) {
5372
+ connectedProviders = liveConnected;
5373
+ connectedProvidersUnknown = false;
5374
+ log("[fetchAvailableModels] connected providers fetched from client", { count: liveConnected.length });
5375
+ }
5376
+ }
5328
5377
  if (connectedProvidersUnknown) {
5378
+ if (client?.model?.list) {
5379
+ const modelSet2 = new Set;
5380
+ try {
5381
+ const modelsResult = await client.model.list();
5382
+ const models = modelsResult.data ?? [];
5383
+ for (const model of models) {
5384
+ if (model?.provider && model?.id) {
5385
+ modelSet2.add(`${model.provider}/${model.id}`);
5386
+ }
5387
+ }
5388
+ log("[fetchAvailableModels] fetched models from client without provider filter", {
5389
+ count: modelSet2.size
5390
+ });
5391
+ return modelSet2;
5392
+ } catch (err) {
5393
+ log("[fetchAvailableModels] client.model.list error", { error: String(err) });
5394
+ }
5395
+ }
5329
5396
  log("[fetchAvailableModels] connected providers unknown, returning empty set for fallback resolution");
5330
5397
  return new Set;
5331
5398
  }
5332
- const connectedProviders = options.connectedProviders;
5333
- const connectedSet = new Set(connectedProviders);
5399
+ const connectedProvidersList = connectedProviders ?? [];
5400
+ const connectedSet = new Set(connectedProvidersList);
5334
5401
  const modelSet = new Set;
5335
5402
  const providerModelsCache = readProviderModelsCache();
5336
5403
  if (providerModelsCache) {
5337
- log("[fetchAvailableModels] using provider-models cache (whitelist-filtered)");
5338
- for (const [providerId, modelIds] of Object.entries(providerModelsCache.models)) {
5339
- if (!connectedSet.has(providerId)) {
5340
- continue;
5404
+ const providerCount = Object.keys(providerModelsCache.models).length;
5405
+ if (providerCount === 0) {
5406
+ log("[fetchAvailableModels] provider-models cache empty, falling back to models.json");
5407
+ } else {
5408
+ log("[fetchAvailableModels] using provider-models cache (whitelist-filtered)");
5409
+ for (const [providerId, modelIds] of Object.entries(providerModelsCache.models)) {
5410
+ if (!connectedSet.has(providerId)) {
5411
+ continue;
5412
+ }
5413
+ for (const modelId of modelIds) {
5414
+ modelSet.add(`${providerId}/${modelId}`);
5415
+ }
5341
5416
  }
5342
- for (const modelId of modelIds) {
5343
- modelSet.add(`${providerId}/${modelId}`);
5417
+ log("[fetchAvailableModels] parsed from provider-models cache", {
5418
+ count: modelSet.size,
5419
+ connectedProviders: connectedProvidersList.slice(0, 5)
5420
+ });
5421
+ if (modelSet.size > 0) {
5422
+ return modelSet;
5344
5423
  }
5424
+ log("[fetchAvailableModels] provider-models cache produced no models for connected providers, falling back to models.json");
5345
5425
  }
5346
- log("[fetchAvailableModels] parsed from provider-models cache", {
5347
- count: modelSet.size,
5348
- connectedProviders: connectedProviders.slice(0, 5)
5349
- });
5350
- return modelSet;
5351
5426
  }
5352
5427
  log("[fetchAvailableModels] provider-models cache not found, falling back to models.json");
5353
5428
  const cacheFile = join13(getOpenCodeCacheDir(), "models.json");
5354
5429
  if (!existsSync10(cacheFile)) {
5355
- log("[fetchAvailableModels] models.json cache file not found, returning empty set");
5356
- return modelSet;
5357
- }
5358
- try {
5359
- const content = readFileSync7(cacheFile, "utf-8");
5360
- const data = JSON.parse(content);
5361
- const providerIds = Object.keys(data);
5362
- log("[fetchAvailableModels] providers found in models.json", { count: providerIds.length, providers: providerIds.slice(0, 10) });
5363
- for (const providerId of providerIds) {
5364
- if (!connectedSet.has(providerId)) {
5365
- continue;
5430
+ log("[fetchAvailableModels] models.json cache file not found, falling back to client");
5431
+ } else {
5432
+ try {
5433
+ const content = readFileSync7(cacheFile, "utf-8");
5434
+ const data = JSON.parse(content);
5435
+ const providerIds = Object.keys(data);
5436
+ log("[fetchAvailableModels] providers found in models.json", { count: providerIds.length, providers: providerIds.slice(0, 10) });
5437
+ for (const providerId of providerIds) {
5438
+ if (!connectedSet.has(providerId)) {
5439
+ continue;
5440
+ }
5441
+ const provider = data[providerId];
5442
+ const models = provider?.models;
5443
+ if (!models || typeof models !== "object")
5444
+ continue;
5445
+ for (const modelKey of Object.keys(models)) {
5446
+ modelSet.add(`${providerId}/${modelKey}`);
5447
+ }
5366
5448
  }
5367
- const provider = data[providerId];
5368
- const models = provider?.models;
5369
- if (!models || typeof models !== "object")
5370
- continue;
5371
- for (const modelKey of Object.keys(models)) {
5372
- modelSet.add(`${providerId}/${modelKey}`);
5449
+ log("[fetchAvailableModels] parsed models from models.json (NO whitelist filtering)", {
5450
+ count: modelSet.size,
5451
+ connectedProviders: connectedProvidersList.slice(0, 5)
5452
+ });
5453
+ if (modelSet.size > 0) {
5454
+ return modelSet;
5373
5455
  }
5456
+ } catch (err) {
5457
+ log("[fetchAvailableModels] error", { error: String(err) });
5374
5458
  }
5375
- log("[fetchAvailableModels] parsed models from models.json (NO whitelist filtering)", {
5376
- count: modelSet.size,
5377
- connectedProviders: connectedProviders.slice(0, 5)
5378
- });
5379
- return modelSet;
5380
- } catch (err) {
5381
- log("[fetchAvailableModels] error", { error: String(err) });
5382
- return modelSet;
5383
5459
  }
5460
+ if (client?.model?.list) {
5461
+ try {
5462
+ const modelsResult = await client.model.list();
5463
+ const models = modelsResult.data ?? [];
5464
+ for (const model of models) {
5465
+ if (!model?.provider || !model?.id)
5466
+ continue;
5467
+ if (connectedSet.has(model.provider)) {
5468
+ modelSet.add(`${model.provider}/${model.id}`);
5469
+ }
5470
+ }
5471
+ log("[fetchAvailableModels] fetched models from client (filtered)", {
5472
+ count: modelSet.size,
5473
+ connectedProviders: connectedProvidersList.slice(0, 5)
5474
+ });
5475
+ } catch (err) {
5476
+ log("[fetchAvailableModels] client.model.list error", { error: String(err) });
5477
+ }
5478
+ }
5479
+ return modelSet;
5384
5480
  }
5385
5481
  function isModelCacheAvailable() {
5386
5482
  if (hasProviderModelsCache()) {
@@ -5404,7 +5500,7 @@ function resolveModel(input) {
5404
5500
  return normalizeModel(input.userModel) ?? normalizeModel(input.inheritedModel) ?? input.systemDefault;
5405
5501
  }
5406
5502
  function resolveModelWithFallback(input) {
5407
- const { uiSelectedModel, userModel, fallbackChain, availableModels, systemDefaultModel } = input;
5503
+ const { uiSelectedModel, userModel, categoryDefaultModel, fallbackChain, availableModels, systemDefaultModel } = input;
5408
5504
  const normalizedUiModel = normalizeModel(uiSelectedModel);
5409
5505
  if (normalizedUiModel) {
5410
5506
  log("Model resolved via UI selection", { model: normalizedUiModel });
@@ -5415,6 +5511,33 @@ function resolveModelWithFallback(input) {
5415
5511
  log("Model resolved via config override", { model: normalizedUserModel });
5416
5512
  return { model: normalizedUserModel, source: "override" };
5417
5513
  }
5514
+ const normalizedCategoryDefault = normalizeModel(categoryDefaultModel);
5515
+ if (normalizedCategoryDefault) {
5516
+ if (availableModels.size > 0) {
5517
+ const parts = normalizedCategoryDefault.split("/");
5518
+ const providerHint = parts.length >= 2 ? [parts[0]] : undefined;
5519
+ const match = fuzzyMatchModel(normalizedCategoryDefault, availableModels, providerHint);
5520
+ if (match) {
5521
+ log("Model resolved via category default (fuzzy matched)", { original: normalizedCategoryDefault, matched: match });
5522
+ return { model: match, source: "category-default" };
5523
+ }
5524
+ } else {
5525
+ const connectedProviders = readConnectedProvidersCache();
5526
+ if (connectedProviders === null) {
5527
+ log("Model resolved via category default (no cache, first run)", { model: normalizedCategoryDefault });
5528
+ return { model: normalizedCategoryDefault, source: "category-default" };
5529
+ }
5530
+ const parts = normalizedCategoryDefault.split("/");
5531
+ if (parts.length >= 2) {
5532
+ const provider = parts[0];
5533
+ if (connectedProviders.includes(provider)) {
5534
+ log("Model resolved via category default (connected provider)", { model: normalizedCategoryDefault });
5535
+ return { model: normalizedCategoryDefault, source: "category-default" };
5536
+ }
5537
+ }
5538
+ }
5539
+ log("Category default model not available, falling through to fallback chain", { model: normalizedCategoryDefault });
5540
+ }
5418
5541
  if (fallbackChain && fallbackChain.length > 0) {
5419
5542
  if (availableModels.size === 0) {
5420
5543
  const connectedProviders = readConnectedProvidersCache();
@@ -5426,7 +5549,7 @@ function resolveModelWithFallback(input) {
5426
5549
  for (const provider of entry.providers) {
5427
5550
  if (connectedSet.has(provider)) {
5428
5551
  const model = `${provider}/${entry.model}`;
5429
- log("Model resolved via fallback chain (no model cache, using connected provider)", {
5552
+ log("Model resolved via fallback chain (connected provider)", {
5430
5553
  provider,
5431
5554
  model: entry.model,
5432
5555
  variant: entry.variant
@@ -5437,18 +5560,28 @@ function resolveModelWithFallback(input) {
5437
5560
  }
5438
5561
  log("No connected provider found in fallback chain, falling through to system default");
5439
5562
  }
5440
- }
5441
- for (const entry of fallbackChain) {
5442
- for (const provider of entry.providers) {
5443
- const fullModel = `${provider}/${entry.model}`;
5444
- const match = fuzzyMatchModel(fullModel, availableModels, [provider]);
5445
- if (match) {
5446
- log("Model resolved via fallback chain (availability confirmed)", { provider, model: entry.model, match, variant: entry.variant });
5447
- return { model: match, source: "provider-fallback", variant: entry.variant };
5563
+ } else {
5564
+ for (const entry of fallbackChain) {
5565
+ for (const provider of entry.providers) {
5566
+ const fullModel = `${provider}/${entry.model}`;
5567
+ const match = fuzzyMatchModel(fullModel, availableModels, [provider]);
5568
+ if (match) {
5569
+ log("Model resolved via fallback chain (availability confirmed)", { provider, model: entry.model, match, variant: entry.variant });
5570
+ return { model: match, source: "provider-fallback", variant: entry.variant };
5571
+ }
5572
+ }
5573
+ const crossProviderMatch = fuzzyMatchModel(entry.model, availableModels);
5574
+ if (crossProviderMatch) {
5575
+ log("Model resolved via fallback chain (cross-provider fuzzy match)", {
5576
+ model: entry.model,
5577
+ match: crossProviderMatch,
5578
+ variant: entry.variant
5579
+ });
5580
+ return { model: crossProviderMatch, source: "provider-fallback", variant: entry.variant };
5448
5581
  }
5449
5582
  }
5583
+ log("No available model found in fallback chain, falling through to system default");
5450
5584
  }
5451
- log("No available model found in fallback chain, falling through to system default");
5452
5585
  }
5453
5586
  if (systemDefaultModel === undefined) {
5454
5587
  log("No model resolved - systemDefaultModel not configured");
@@ -5720,6 +5853,92 @@ var init_tmux = __esm(() => {
5720
5853
  init_tmux_utils();
5721
5854
  });
5722
5855
 
5856
+ // src/shared/model-suggestion-retry.ts
5857
+ function extractMessage(error) {
5858
+ if (typeof error === "string")
5859
+ return error;
5860
+ if (error instanceof Error)
5861
+ return error.message;
5862
+ if (typeof error === "object" && error !== null) {
5863
+ const obj = error;
5864
+ if (typeof obj.message === "string")
5865
+ return obj.message;
5866
+ try {
5867
+ return JSON.stringify(error);
5868
+ } catch {
5869
+ return "";
5870
+ }
5871
+ }
5872
+ return String(error);
5873
+ }
5874
+ function parseModelSuggestion(error) {
5875
+ if (!error)
5876
+ return null;
5877
+ if (typeof error === "object") {
5878
+ const errObj = error;
5879
+ if (errObj.name === "ProviderModelNotFoundError" && typeof errObj.data === "object" && errObj.data !== null) {
5880
+ const data = errObj.data;
5881
+ const suggestions = data.suggestions;
5882
+ if (Array.isArray(suggestions) && suggestions.length > 0 && typeof suggestions[0] === "string") {
5883
+ return {
5884
+ providerID: String(data.providerID ?? ""),
5885
+ modelID: String(data.modelID ?? ""),
5886
+ suggestion: suggestions[0]
5887
+ };
5888
+ }
5889
+ return null;
5890
+ }
5891
+ for (const key of ["data", "error", "cause"]) {
5892
+ const nested = errObj[key];
5893
+ if (nested && typeof nested === "object") {
5894
+ const result = parseModelSuggestion(nested);
5895
+ if (result)
5896
+ return result;
5897
+ }
5898
+ }
5899
+ }
5900
+ const message = extractMessage(error);
5901
+ if (!message)
5902
+ return null;
5903
+ const modelMatch = message.match(/model not found:\s*([^/\s]+)\s*\/\s*([^.\s]+)/i);
5904
+ const suggestionMatch = message.match(/did you mean:\s*([^,?]+)/i);
5905
+ if (modelMatch && suggestionMatch) {
5906
+ return {
5907
+ providerID: modelMatch[1].trim(),
5908
+ modelID: modelMatch[2].trim(),
5909
+ suggestion: suggestionMatch[1].trim()
5910
+ };
5911
+ }
5912
+ return null;
5913
+ }
5914
+ async function promptWithModelSuggestionRetry(client, args) {
5915
+ try {
5916
+ await client.session.prompt(args);
5917
+ } catch (error) {
5918
+ const suggestion = parseModelSuggestion(error);
5919
+ if (!suggestion || !args.body.model) {
5920
+ throw error;
5921
+ }
5922
+ log("[model-suggestion-retry] Model not found, retrying with suggestion", {
5923
+ original: `${suggestion.providerID}/${suggestion.modelID}`,
5924
+ suggested: suggestion.suggestion
5925
+ });
5926
+ await client.session.prompt({
5927
+ ...args,
5928
+ body: {
5929
+ ...args.body,
5930
+ model: {
5931
+ providerID: suggestion.providerID,
5932
+ modelID: suggestion.suggestion
5933
+ }
5934
+ }
5935
+ });
5936
+ }
5937
+ }
5938
+ var init_model_suggestion_retry = __esm(() => {
5939
+ init_logger();
5940
+ });
5941
+
5723
5942
  // src/shared/index.ts
5724
5943
  var init_shared = __esm(() => {
5725
5944
  init_frontmatter();
@@ -5750,6 +5969,7 @@ var init_shared = __esm(() => {
5750
5969
  init_connected_providers_cache();
5751
5970
  init_session_utils();
5752
5971
  init_tmux();
5972
+ init_model_suggestion_retry();
5753
5973
  });
5754
5974
 
5755
5975
  // node_modules/picomatch/lib/constants.js
@@ -11082,8 +11302,14 @@ Design-first mindset:
11082
11302
  - Atmosphere: gradient meshes, noise textures, layered transparencies
11083
11303
 
11084
11304
  AVOID: Generic fonts, purple gradients on white, predictable layouts, cookie-cutter patterns.
11085
- </Category_Context>`, STRATEGIC_CATEGORY_PROMPT_APPEND = `<Category_Context>
11086
- You are working on BUSINESS LOGIC / ARCHITECTURE tasks.
11305
+ </Category_Context>`, ULTRABRAIN_CATEGORY_PROMPT_APPEND = `<Category_Context>
11306
+ You are working on DEEP LOGICAL REASONING / COMPLEX ARCHITECTURE tasks.
11307
+
11308
+ **CRITICAL - CODE STYLE REQUIREMENTS (NON-NEGOTIABLE)**:
11309
+ 1. BEFORE writing ANY code, SEARCH the existing codebase to find similar patterns/styles
11310
+ 2. Your code MUST match the project's existing conventions - blend in seamlessly
11311
+ 3. Write READABLE code that humans can easily understand - no clever tricks
11312
+ 4. If unsure about style, explore more files until you find the pattern
11087
11313
 
11088
11314
  Strategic advisor mindset:
11089
11315
  - Bias toward simplicity: least complex solution that fulfills requirements
@@ -11209,6 +11435,35 @@ Approach:
11209
11435
  - Draft with care
11210
11436
  - Polish for clarity and impact
11211
11437
  - Documentation, READMEs, articles, technical writing
11438
+ </Category_Context>`, DEEP_CATEGORY_PROMPT_APPEND = `<Category_Context>
11439
+ You are working on GOAL-ORIENTED AUTONOMOUS tasks.
11440
+
11441
+ **CRITICAL - AUTONOMOUS EXECUTION MINDSET (NON-NEGOTIABLE)**:
11442
+ You are NOT an interactive assistant. You are an autonomous problem-solver.
11443
+
11444
+ **BEFORE making ANY changes**:
11445
+ 1. SILENTLY explore the codebase extensively (5-15 minutes of reading is normal)
11446
+ 2. Read related files, trace dependencies, understand the full context
11447
+ 3. Build a complete mental model of the problem space
11448
+ 4. DO NOT ask clarifying questions - the goal is already defined
11449
+
11450
+ **Autonomous executor mindset**:
11451
+ - You receive a GOAL, not step-by-step instructions
11452
+ - Figure out HOW to achieve the goal yourself
11453
+ - Thorough research before any action
11454
+ - Fix hairy problems that require deep understanding
11455
+ - Work independently without frequent check-ins
11456
+
11457
+ **Approach**:
11458
+ - Explore extensively, understand deeply, then act decisively
11459
+ - Prefer comprehensive solutions over quick patches
11460
+ - If the goal is unclear, make reasonable assumptions and proceed
11461
+ - Document your reasoning in code comments only when non-obvious
11462
+
11463
+ **Response format**:
11464
+ - Minimal status updates (user trusts your autonomy)
11465
+ - Focus on results, not play-by-play progress
11466
+ - Report completion with summary of changes made
11212
11467
  </Category_Context>`, DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS, CATEGORY_DESCRIPTIONS, PLAN_AGENT_SYSTEM_PREPEND = `<system>
11213
11468
  BEFORE you begin planning, you MUST first understand the user's request deeply.
11214
11469
 
@@ -11422,6 +11677,7 @@ var init_constants4 = __esm(() => {
11422
11677
  DEFAULT_CATEGORIES = {
11423
11678
  "visual-engineering": { model: "google/gemini-3-pro" },
11424
11679
  ultrabrain: { model: "openai/gpt-5.2-codex", variant: "xhigh" },
11680
+ deep: { model: "openai/gpt-5.2-codex", variant: "medium" },
11425
11681
  artistry: { model: "google/gemini-3-pro", variant: "max" },
11426
11682
  quick: { model: "anthropic/claude-haiku-4-5" },
11427
11683
  "unspecified-low": { model: "anthropic/claude-sonnet-4-5" },
@@ -11430,7 +11686,8 @@ var init_constants4 = __esm(() => {
11430
11686
  };
11431
11687
  CATEGORY_PROMPT_APPENDS = {
11432
11688
  "visual-engineering": VISUAL_CATEGORY_PROMPT_APPEND,
11433
- ultrabrain: STRATEGIC_CATEGORY_PROMPT_APPEND,
11689
+ ultrabrain: ULTRABRAIN_CATEGORY_PROMPT_APPEND,
11690
+ deep: DEEP_CATEGORY_PROMPT_APPEND,
11434
11691
  artistry: ARTISTRY_CATEGORY_PROMPT_APPEND,
11435
11692
  quick: QUICK_CATEGORY_PROMPT_APPEND,
11436
11693
  "unspecified-low": UNSPECIFIED_LOW_CATEGORY_PROMPT_APPEND,
@@ -11439,8 +11696,9 @@ var init_constants4 = __esm(() => {
11439
11696
  };
11440
11697
  CATEGORY_DESCRIPTIONS = {
11441
11698
  "visual-engineering": "Frontend, UI/UX, design, styling, animation",
11442
- ultrabrain: "Deep logical reasoning, complex architecture decisions requiring extensive analysis",
11443
- artistry: "Highly creative/artistic tasks, novel ideas",
11699
+ ultrabrain: "Use ONLY for genuinely hard, logic-heavy tasks. Give clear goals only, not step-by-step instructions.",
11700
+ deep: "Goal-oriented autonomous problem-solving. Thorough research before action. For hairy problems requiring deep understanding.",
11701
+ artistry: "Complex problem-solving with unconventional, creative approaches - beyond standard patterns",
11444
11702
  quick: "Trivial tasks - single file changes, typo fixes, simple modifications",
11445
11703
  "unspecified-low": "Tasks that don't fit other categories, low effort required",
11446
11704
  "unspecified-high": "Tasks that don't fit other categories, high effort required",
@@ -19497,6 +19755,7 @@ function findMessageByIndexNeedingThinking(sessionID, targetIndex) {
19497
19755
  }
19498
19756
 
19499
19757
  // src/hooks/session-recovery/index.ts
19758
+ init_logger();
19500
19759
  var RECOVERY_RESUME_TEXT = "[session recovered - continuing previous task]";
19501
19760
  function findLastUserMessage(messages) {
19502
19761
  for (let i = messages.length - 1;i >= 0; i--) {
@@ -19717,7 +19976,7 @@ function createSessionRecoveryHook(ctx, options) {
19717
19976
  }
19718
19977
  return success;
19719
19978
  } catch (err) {
19720
- console.error("[session-recovery] Recovery failed:", err);
19979
+ log("[session-recovery] Recovery failed:", err);
19721
19980
  return false;
19722
19981
  } finally {
19723
19982
  processingErrors.delete(assistantMsgID);
@@ -19743,6 +20002,7 @@ import { tmpdir as tmpdir3 } from "os";
19743
20002
 
19744
20003
  // src/hooks/comment-checker/downloader.ts
19745
20004
  init_shared();
20005
+ init_logger();
19746
20006
  var {spawn: spawn6 } = globalThis.Bun;
19747
20007
  import { existsSync as existsSync12, mkdirSync as mkdirSync4, chmodSync, unlinkSync as unlinkSync2, appendFileSync as appendFileSync2 } from "fs";
19748
20008
  import { join as join15 } from "path";
@@ -19822,7 +20082,7 @@ async function downloadCommentChecker() {
19822
20082
  const assetName = `comment-checker_v${version}_${os4}_${arch}.${ext}`;
19823
20083
  const downloadUrl = `https://github.com/${REPO}/releases/download/v${version}/${assetName}`;
19824
20084
  debugLog(`Downloading from: ${downloadUrl}`);
19825
- console.log(`[oh-my-opencode] Downloading comment-checker binary...`);
20085
+ log(`[oh-my-opencode] Downloading comment-checker binary...`);
19826
20086
  try {
19827
20087
  if (!existsSync12(cacheDir)) {
19828
20088
  mkdirSync4(cacheDir, { recursive: true });
@@ -19847,12 +20107,12 @@ async function downloadCommentChecker() {
19847
20107
  chmodSync(binaryPath, 493);
19848
20108
  }
19849
20109
  debugLog(`Successfully downloaded binary to: ${binaryPath}`);
19850
- console.log(`[oh-my-opencode] comment-checker binary ready.`);
20110
+ log(`[oh-my-opencode] comment-checker binary ready.`);
19851
20111
  return binaryPath;
19852
20112
  } catch (err) {
19853
20113
  debugLog(`Failed to download: ${err}`);
19854
- console.error(`[oh-my-opencode] Failed to download comment-checker: ${err instanceof Error ? err.message : err}`);
19855
- console.error(`[oh-my-opencode] Comment checking disabled.`);
20114
+ log(`[oh-my-opencode] Failed to download comment-checker: ${err instanceof Error ? err.message : err}`);
20115
+ log(`[oh-my-opencode] Comment checking disabled.`);
19856
20116
  return null;
19857
20117
  }
19858
20118
  }
@@ -23529,7 +23789,9 @@ ${ULTRAWORK_PLANNER_SECTION}
23529
23789
 
23530
23790
  1. **THINK DEEPLY** - What is the user's TRUE intent? What problem are they REALLY trying to solve?
23531
23791
  2. **EXPLORE THOROUGHLY** - Fire explore/librarian agents to gather ALL relevant context
23532
- 3. **CONSULT ORACLE** - For architecture decisions, complex logic, or when you're stuck
23792
+ 3. **CONSULT SPECIALISTS** - For hard/complex tasks, DO NOT struggle alone. Delegate:
23793
+ - **Oracle**: Conventional problems - architecture, debugging, complex logic
23794
+ - **Artistry**: Non-conventional problems - different approach needed, unusual constraints
23533
23795
  4. **ASK THE USER** - If ambiguity remains after exploration, ASK. Don't guess.
23534
23796
 
23535
23797
  **SIGNS YOU ARE NOT READY TO IMPLEMENT:**
@@ -23543,7 +23805,10 @@ ${ULTRAWORK_PLANNER_SECTION}
23543
23805
  \`\`\`
23544
23806
  delegate_task(agent="explore", prompt="Find [X] patterns in codebase", background=true)
23545
23807
  delegate_task(agent="librarian", prompt="Find docs/examples for [Y]", background=true)
23546
- delegate_task(agent="oracle", prompt="Review my approach: [describe plan]")
23808
+
23809
+ // Hard problem? DON'T struggle alone:
23810
+ delegate_task(agent="oracle", prompt="...") // conventional: architecture, debugging
23811
+ delegate_task(category="artistry", prompt="...") // non-conventional: needs different approach
23547
23812
  \`\`\`
23548
23813
 
23549
23814
  **ONLY AFTER YOU HAVE:**
@@ -23578,7 +23843,7 @@ delegate_task(agent="oracle", prompt="Review my approach: [describe plan]")
23578
23843
  **IF YOU ENCOUNTER A BLOCKER:**
23579
23844
  1. **DO NOT** give up
23580
23845
  2. **DO NOT** deliver a compromised version
23581
- 3. **DO** consult oracle for solutions
23846
+ 3. **DO** consult specialists (oracle for conventional, artistry for non-conventional)
23582
23847
  4. **DO** ask the user for guidance
23583
23848
  5. **DO** explore alternative approaches
23584
23849
 
@@ -23647,7 +23912,8 @@ delegate_task(session_id="ses_abc123", prompt="Here's my answer to your question
23647
23912
  | Codebase exploration | delegate_task(subagent_type="explore", run_in_background=true) | Parallel, context-efficient |
23648
23913
  | Documentation lookup | delegate_task(subagent_type="librarian", run_in_background=true) | Specialized knowledge |
23649
23914
  | Planning | delegate_task(subagent_type="plan") | Parallel task graph + structured TODO list |
23650
- | Architecture/Debugging | delegate_task(subagent_type="oracle") | High-IQ reasoning |
23915
+ | Hard problem (conventional) | delegate_task(subagent_type="oracle") | Architecture, debugging, complex logic |
23916
+ | Hard problem (non-conventional) | delegate_task(category="artistry", load_skills=[...]) | Different approach needed |
23651
23917
  | Implementation | delegate_task(category="...", load_skills=[...]) | Domain-optimized models |
23652
23918
 
23653
23919
  **CATEGORY + SKILL DELEGATION:**
@@ -23834,8 +24100,9 @@ CONTEXT GATHERING (parallel):
23834
24100
  - 1-2 librarian agents (if external library involved)
23835
24101
  - Direct tools: Grep, AST-grep, LSP for targeted searches
23836
24102
 
23837
- IF COMPLEX (architecture, multi-system, debugging after 2+ failures):
23838
- - Consult oracle for strategic guidance
24103
+ IF COMPLEX - DO NOT STRUGGLE ALONE. Consult specialists:
24104
+ - **Oracle**: Conventional problems (architecture, debugging, complex logic)
24105
+ - **Artistry**: Non-conventional problems (different approach needed)
23839
24106
 
23840
24107
  SYNTHESIZE findings before proceeding.`
23841
24108
  }
@@ -29745,6 +30012,8 @@ import { Readable, Writable } from "stream";
29745
30012
  import { readFileSync as readFileSync27 } from "fs";
29746
30013
  import { extname, resolve as resolve8 } from "path";
29747
30014
  import { pathToFileURL } from "url";
30015
+ init_logger();
30016
+
29748
30017
  class LSPServerManager {
29749
30018
  static instance;
29750
30019
  clients = new Map;
@@ -29994,7 +30263,7 @@ stderr: ${stderr}` : ""));
29994
30263
  this.processExited = true;
29995
30264
  });
29996
30265
  this.connection.onError((error) => {
29997
- console.error("LSP connection error:", error);
30266
+ log("LSP connection error:", error);
29998
30267
  });
29999
30268
  this.connection.listen();
30000
30269
  }
@@ -43028,6 +43297,7 @@ import { existsSync as existsSync39, statSync as statSync4 } from "fs";
43028
43297
 
43029
43298
  // src/tools/ast-grep/downloader.ts
43030
43299
  init_shared();
43300
+ init_logger();
43031
43301
  import { existsSync as existsSync38, mkdirSync as mkdirSync13, chmodSync as chmodSync2, unlinkSync as unlinkSync10 } from "fs";
43032
43302
  import { join as join47 } from "path";
43033
43303
  import { homedir as homedir11 } from "os";
@@ -43073,7 +43343,7 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
43073
43343
  const platformKey = `${process.platform}-${process.arch}`;
43074
43344
  const platformInfo = PLATFORM_MAP2[platformKey];
43075
43345
  if (!platformInfo) {
43076
- console.error(`[oh-my-opencode] Unsupported platform for ast-grep: ${platformKey}`);
43346
+ log(`[oh-my-opencode] Unsupported platform for ast-grep: ${platformKey}`);
43077
43347
  return null;
43078
43348
  }
43079
43349
  const cacheDir = getCacheDir4();
@@ -43085,7 +43355,7 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
43085
43355
  const { arch, os: os6 } = platformInfo;
43086
43356
  const assetName = `app-${arch}-${os6}.zip`;
43087
43357
  const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
43088
- console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
43358
+ log(`[oh-my-opencode] Downloading ast-grep binary...`);
43089
43359
  try {
43090
43360
  if (!existsSync38(cacheDir)) {
43091
43361
  mkdirSync13(cacheDir, { recursive: true });
@@ -43104,10 +43374,10 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
43104
43374
  if (process.platform !== "win32" && existsSync38(binaryPath)) {
43105
43375
  chmodSync2(binaryPath, 493);
43106
43376
  }
43107
- console.log(`[oh-my-opencode] ast-grep binary ready.`);
43377
+ log(`[oh-my-opencode] ast-grep binary ready.`);
43108
43378
  return binaryPath;
43109
43379
  } catch (err) {
43110
- console.error(`[oh-my-opencode] Failed to download ast-grep: ${err instanceof Error ? err.message : err}`);
43380
+ log(`[oh-my-opencode] Failed to download ast-grep: ${err instanceof Error ? err.message : err}`);
43111
43381
  return null;
43112
43382
  }
43113
43383
  }
@@ -45239,6 +45509,7 @@ ${REFACTOR_TEMPLATE}
45239
45509
  },
45240
45510
  "start-work": {
45241
45511
  description: "(builtin) Start Sisyphus work session from Prometheus plan",
45512
+ agent: "atlas",
45242
45513
  template: `<command-instruction>
45243
45514
  ${START_WORK_TEMPLATE}
45244
45515
  </command-instruction>
@@ -47138,7 +47409,7 @@ var LOOK_AT_DESCRIPTION = `Analyze media files (PDFs, images, diagrams) that req
47138
47409
  // src/tools/look-at/tools.ts
47139
47410
  import { extname as extname3, basename as basename5 } from "path";
47140
47411
  import { pathToFileURL as pathToFileURL2 } from "url";
47141
- init_logger();
47412
+ init_shared();
47142
47413
  function normalizeArgs(args) {
47143
47414
  return {
47144
47415
  file_path: args.file_path ?? args.path ?? "",
@@ -47249,9 +47520,26 @@ Original error: ${createResult.error}`;
47249
47520
  }
47250
47521
  const sessionID = createResult.data.id;
47251
47522
  log(`[look_at] Created session: ${sessionID}`);
47523
+ let agentModel;
47524
+ let agentVariant;
47525
+ try {
47526
+ const agentsResult = await ctx.client.app?.agents?.();
47527
+ const agents = agentsResult?.data ?? agentsResult;
47528
+ if (agents?.length) {
47529
+ const matchedAgent = findByNameCaseInsensitive(agents, MULTIMODAL_LOOKER_AGENT);
47530
+ if (matchedAgent?.model) {
47531
+ agentModel = matchedAgent.model;
47532
+ }
47533
+ if (matchedAgent?.variant) {
47534
+ agentVariant = matchedAgent.variant;
47535
+ }
47536
+ }
47537
+ } catch (error45) {
47538
+ log("[look_at] Failed to resolve multimodal-looker model info", error45);
47539
+ }
47252
47540
  log(`[look_at] Sending prompt with file passthrough to session ${sessionID}`);
47253
47541
  try {
47254
- await ctx.client.session.prompt({
47542
+ await promptWithModelSuggestionRetry(ctx.client, {
47255
47543
  path: { id: sessionID },
47256
47544
  body: {
47257
47545
  agent: MULTIMODAL_LOOKER_AGENT,
@@ -47264,7 +47552,9 @@ Original error: ${createResult.error}`;
47264
47552
  parts: [
47265
47553
  { type: "text", text: prompt },
47266
47554
  { type: "file", mime: mimeType, url: pathToFileURL2(args.file_path).href, filename }
47267
- ]
47555
+ ],
47556
+ ...agentModel ? { model: { providerID: agentModel.providerID, modelID: agentModel.modelID } } : {},
47557
+ ...agentVariant ? { variant: agentVariant } : {}
47268
47558
  }
47269
47559
  });
47270
47560
  } catch (promptError) {
@@ -47571,7 +47861,14 @@ function formatDetailedError(error45, ctx) {
47571
47861
  `);
47572
47862
  }
47573
47863
  function resolveCategoryConfig(categoryName, options) {
47574
- const { userCategories, inheritedModel, systemDefaultModel } = options;
47864
+ const { userCategories, inheritedModel, systemDefaultModel, availableModels } = options;
47865
+ const categoryReq = CATEGORY_MODEL_REQUIREMENTS[categoryName];
47866
+ if (categoryReq?.requiresModel && availableModels) {
47867
+ if (!isModelAvailable(categoryReq.requiresModel, availableModels)) {
47868
+ log(`[resolveCategoryConfig] Category ${categoryName} requires ${categoryReq.requiresModel} but not available`);
47869
+ return null;
47870
+ }
47871
+ }
47575
47872
  const defaultConfig = DEFAULT_CATEGORIES[categoryName];
47576
47873
  const userConfig = userCategories?.[categoryName];
47577
47874
  const defaultPromptAppend = CATEGORY_PROMPT_APPENDS[categoryName] ?? "";
@@ -47898,7 +48195,8 @@ To continue this session: session_id="${args.session_id}"`;
47898
48195
  const resolved = resolveCategoryConfig(args.category, {
47899
48196
  userCategories,
47900
48197
  inheritedModel,
47901
- systemDefaultModel
48198
+ systemDefaultModel,
48199
+ availableModels
47902
48200
  });
47903
48201
  if (!resolved) {
47904
48202
  return `Unknown category: "${args.category}". Available: ${Object.keys({ ...DEFAULT_CATEGORIES, ...userCategories }).join(", ")}`;
@@ -47912,7 +48210,8 @@ To continue this session: session_id="${args.session_id}"`;
47912
48210
  }
47913
48211
  } else {
47914
48212
  const resolution = resolveModelWithFallback({
47915
- userModel: userCategories?.[args.category]?.model ?? resolved.model ?? sisyphusJuniorModel,
48213
+ userModel: userCategories?.[args.category]?.model,
48214
+ categoryDefaultModel: resolved.model ?? sisyphusJuniorModel,
47916
48215
  fallbackChain: requirement.fallbackChain,
47917
48216
  availableModels,
47918
48217
  systemDefaultModel
@@ -47928,6 +48227,7 @@ To continue this session: session_id="${args.session_id}"`;
47928
48227
  case "override":
47929
48228
  type2 = "user-defined";
47930
48229
  break;
48230
+ case "category-default":
47931
48231
  case "provider-fallback":
47932
48232
  type2 = "category-default";
47933
48233
  break;
@@ -48135,10 +48435,6 @@ Create the work plan directly - that's your job as the planning agent.`;
48135
48435
  categoryModel = matchedAgent.model;
48136
48436
  }
48137
48437
  } catch {}
48138
- if (parentModel) {
48139
- categoryModel = parentModel;
48140
- modelInfo = { model: `${parentModel.providerID}/${parentModel.modelID}`, type: "inherited" };
48141
- }
48142
48438
  }
48143
48439
  const systemContent = buildSystemContent({ skillContent, categoryPromptAppend, agentName: agentToUse });
48144
48440
  if (runInBackground) {
@@ -48251,7 +48547,7 @@ To continue this session: session_id="${task.sessionID}"`;
48251
48547
  });
48252
48548
  try {
48253
48549
  const allowDelegateTask = isPlanAgent(agentToUse);
48254
- await client2.session.prompt({
48550
+ await promptWithModelSuggestionRetry(client2, {
48255
48551
  path: { id: sessionID },
48256
48552
  body: {
48257
48553
  agent: agentToUse,
@@ -48723,7 +49019,7 @@ class BackgroundManager {
48723
49019
  });
48724
49020
  const launchModel = input.model ? { providerID: input.model.providerID, modelID: input.model.modelID } : undefined;
48725
49021
  const launchVariant = input.model?.variant;
48726
- this.client.session.prompt({
49022
+ promptWithModelSuggestionRetry(this.client, {
48727
49023
  path: { id: sessionID },
48728
49024
  body: {
48729
49025
  agent: input.agent,
@@ -55239,6 +55535,7 @@ var CategoryConfigSchema = exports_external.object({
55239
55535
  var BuiltinCategoryNameSchema = exports_external.enum([
55240
55536
  "visual-engineering",
55241
55537
  "ultrabrain",
55538
+ "deep",
55242
55539
  "artistry",
55243
55540
  "quick",
55244
55541
  "unspecified-low",
@@ -55758,6 +56055,7 @@ ${patterns.join(`
55758
56055
  }
55759
56056
 
55760
56057
  // src/agents/sisyphus.ts
56058
+ var MODE = "primary";
55761
56059
  function buildDynamicSisyphusPrompt(availableAgents, availableTools = [], availableSkills = [], availableCategories = []) {
55762
56060
  const keyTriggers = buildKeyTriggersSection(availableAgents, availableSkills);
55763
56061
  const toolSelection = buildToolSelectionTable(availableAgents, availableTools, availableSkills);
@@ -56161,7 +56459,7 @@ function createSisyphusAgent(model, availableAgents, availableToolNames, availab
56161
56459
  const permission = { question: "allow", call_omo_agent: "deny" };
56162
56460
  const base = {
56163
56461
  description: "Powerful AI orchestrator. Plans obsessively with todos, assesses search complexity before exploration, delegates strategically via category+skills combinations. Uses explore for internal code (parallel-friendly), librarian for external docs. (Sisyphus - OhMyOpenCode)",
56164
- mode: "primary",
56462
+ mode: MODE,
56165
56463
  model,
56166
56464
  maxTokens: 64000,
56167
56465
  prompt,
@@ -56173,8 +56471,10 @@ function createSisyphusAgent(model, availableAgents, availableToolNames, availab
56173
56471
  }
56174
56472
  return { ...base, thinking: { type: "enabled", budgetTokens: 32000 } };
56175
56473
  }
56474
+ createSisyphusAgent.mode = MODE;
56176
56475
 
56177
56476
  // src/agents/oracle.ts
56477
+ var MODE2 = "subagent";
56178
56478
  var ORACLE_PROMPT_METADATA = {
56179
56479
  category: "advisor",
56180
56480
  cost: "EXPENSIVE",
@@ -56274,7 +56574,7 @@ function createOracleAgent(model) {
56274
56574
  ]);
56275
56575
  const base = {
56276
56576
  description: "Read-only consultation agent. High-IQ reasoning specialist for debugging hard problems and high-difficulty architecture design. (Oracle - OhMyOpenCode)",
56277
- mode: "subagent",
56577
+ mode: MODE2,
56278
56578
  model,
56279
56579
  temperature: 0.1,
56280
56580
  ...restrictions,
@@ -56285,8 +56585,10 @@ function createOracleAgent(model) {
56285
56585
  }
56286
56586
  return { ...base, thinking: { type: "enabled", budgetTokens: 32000 } };
56287
56587
  }
56588
+ createOracleAgent.mode = MODE2;
56288
56589
 
56289
56590
  // src/agents/librarian.ts
56591
+ var MODE3 = "subagent";
56290
56592
  var LIBRARIAN_PROMPT_METADATA = {
56291
56593
  category: "exploration",
56292
56594
  cost: "CHEAP",
@@ -56313,7 +56615,7 @@ function createLibrarianAgent(model) {
56313
56615
  ]);
56314
56616
  return {
56315
56617
  description: "Specialized codebase understanding agent for multi-repository analysis, searching remote codebases, retrieving official documentation, and finding implementation examples using GitHub CLI, Context7, and Web Search. MUST BE USED when users ask to look up code in remote repositories, explain library internals, or find usage examples in open source. (Librarian - OhMyOpenCode)",
56316
- mode: "subagent",
56618
+ mode: MODE3,
56317
56619
  model,
56318
56620
  temperature: 0.1,
56319
56621
  ...restrictions,
@@ -56605,8 +56907,10 @@ grep_app_searchGitHub(query: "useQuery")
56605
56907
  `
56606
56908
  };
56607
56909
  }
56910
+ createLibrarianAgent.mode = MODE3;
56608
56911
 
56609
56912
  // src/agents/explore.ts
56913
+ var MODE4 = "subagent";
56610
56914
  var EXPLORE_PROMPT_METADATA = {
56611
56915
  category: "exploration",
56612
56916
  cost: "FREE",
@@ -56636,7 +56940,7 @@ function createExploreAgent(model) {
56636
56940
  ]);
56637
56941
  return {
56638
56942
  description: 'Contextual grep for codebases. Answers "Where is X?", "Which file has Y?", "Find the code that does Z". Fire multiple in parallel for broad searches. Specify thoroughness: "quick" for basic, "medium" for moderate, "very thorough" for comprehensive analysis. (Explore - OhMyOpenCode)',
56639
- mode: "subagent",
56943
+ mode: MODE4,
56640
56944
  model,
56641
56945
  temperature: 0.1,
56642
56946
  ...restrictions,
@@ -56721,8 +57025,10 @@ Use the right tool for the job:
56721
57025
  Flood with parallel calls. Cross-validate findings across multiple tools.`
56722
57026
  };
56723
57027
  }
57028
+ createExploreAgent.mode = MODE4;
56724
57029
 
56725
57030
  // src/agents/multimodal-looker.ts
57031
+ var MODE5 = "subagent";
56726
57032
  var MULTIMODAL_LOOKER_PROMPT_METADATA = {
56727
57033
  category: "utility",
56728
57034
  cost: "CHEAP",
@@ -56733,7 +57039,7 @@ function createMultimodalLookerAgent(model) {
56733
57039
  const restrictions = createAgentToolAllowlist(["read"]);
56734
57040
  return {
56735
57041
  description: "Analyze media files (PDFs, images, diagrams) that require interpretation beyond raw text. Extracts specific information or summaries from documents, describes visual content. Use when you need analyzed/extracted data rather than literal file contents. (Multimodal-Looker - OhMyOpenCode)",
56736
- mode: "subagent",
57042
+ mode: MODE5,
56737
57043
  model,
56738
57044
  temperature: 0.1,
56739
57045
  ...restrictions,
@@ -56771,8 +57077,10 @@ Response rules:
56771
57077
  Your output goes straight to the main agent for continued work.`
56772
57078
  };
56773
57079
  }
57080
+ createMultimodalLookerAgent.mode = MODE5;
56774
57081
 
56775
57082
  // src/agents/metis.ts
57083
+ var MODE6 = "subagent";
56776
57084
  var METIS_SYSTEM_PROMPT = `# Metis - Pre-Planning Consultant
56777
57085
 
56778
57086
  ## CONSTRAINTS
@@ -57065,7 +57373,7 @@ var metisRestrictions = createAgentToolRestrictions([
57065
57373
  function createMetisAgent(model) {
57066
57374
  return {
57067
57375
  description: "Pre-planning consultant that analyzes requests to identify hidden intentions, ambiguities, and AI failure points. (Metis - OhMyOpenCode)",
57068
- mode: "subagent",
57376
+ mode: MODE6,
57069
57377
  model,
57070
57378
  temperature: 0.3,
57071
57379
  ...metisRestrictions,
@@ -57073,9 +57381,11 @@ function createMetisAgent(model) {
57073
57381
  thinking: { type: "enabled", budgetTokens: 32000 }
57074
57382
  };
57075
57383
  }
57384
+ createMetisAgent.mode = MODE6;
57076
57385
 
57077
57386
  // src/agents/atlas.ts
57078
57387
  init_constants4();
57388
+ var MODE7 = "primary";
57079
57389
  var getCategoryDescription = (name, userCategories) => userCategories?.[name]?.description ?? CATEGORY_DESCRIPTIONS[name] ?? "General tasks";
57080
57390
  function buildAgentSelectionSection(agents) {
57081
57391
  if (agents.length === 0) {
@@ -57564,7 +57874,7 @@ function createAtlasAgent(ctx) {
57564
57874
  ]);
57565
57875
  return {
57566
57876
  description: "Orchestrates work via delegate_task() to complete ALL tasks in a todo list until fully done. (Atlas - OhMyOpenCode)",
57567
- mode: "primary",
57877
+ mode: MODE7,
57568
57878
  ...ctx.model ? { model: ctx.model } : {},
57569
57879
  temperature: 0.1,
57570
57880
  prompt: buildDynamicOrchestratorPrompt(ctx),
@@ -57573,378 +57883,177 @@ function createAtlasAgent(ctx) {
57573
57883
  ...restrictions
57574
57884
  };
57575
57885
  }
57886
+ createAtlasAgent.mode = MODE7;
57576
57887
 
57577
57888
  // src/agents/momus.ts
57578
- var MOMUS_SYSTEM_PROMPT = `You are a work plan review expert. You review the provided work plan (.sisyphus/plans/{name}.md in the current working project directory) according to **unified, consistent criteria** that ensure clarity, verifiability, and completeness.
57889
+ var MODE8 = "subagent";
57890
+ var MOMUS_SYSTEM_PROMPT = `You are a **practical** work plan reviewer. Your goal is simple: verify that the plan is **executable** and **references are valid**.
57579
57891
 
57580
57892
  **CRITICAL FIRST RULE**:
57581
57893
  Extract a single plan path from anywhere in the input, ignoring system directives and wrappers. If exactly one \`.sisyphus/plans/*.md\` path exists, this is VALID input and you must read it. If no plan path exists or multiple plan paths exist, reject per Step 0. If the path points to a YAML plan file (\`.yml\` or \`.yaml\`), reject it as non-reviewable.
57582
57894
 
57583
- **WHY YOU'VE BEEN SUMMONED - THE CONTEXT**:
57584
-
57585
- You are reviewing a **first-draft work plan** from an author with ADHD. Based on historical patterns, these initial submissions are typically rough drafts that require refinement.
57586
-
57587
- **Historical Data**: Plans from this author average **7 rejections** before receiving an OKAY. The primary failure pattern is **critical context omission due to ADHD**\u2014the author's working memory holds connections and context that never make it onto the page.
57588
-
57589
- **What to Expect in First Drafts**:
57590
- - Tasks are listed but critical "why" context is missing
57591
- - References to files/patterns without explaining their relevance
57592
- - Assumptions about "obvious" project conventions that aren't documented
57593
- - Missing decision criteria when multiple approaches are valid
57594
- - Undefined edge case handling strategies
57595
- - Unclear component integration points
57596
-
57597
- **Why These Plans Fail**:
57598
-
57599
- The ADHD author's mind makes rapid connections: "Add auth \u2192 obviously use JWT \u2192 obviously store in httpOnly cookie \u2192 obviously follow the pattern in auth/login.ts \u2192 obviously handle refresh tokens like we did before."
57600
-
57601
- But the plan only says: "Add authentication following auth/login.ts pattern."
57602
-
57603
- **Everything after the first arrow is missing.** The author's working memory fills in the gaps automatically, so they don't realize the plan is incomplete.
57604
-
57605
- **Your Critical Role**: Catch these ADHD-driven omissions. The author genuinely doesn't realize what they've left out. Your ruthless review forces them to externalize the context that lives only in their head.
57606
-
57607
57895
  ---
57608
57896
 
57609
- ## Your Core Review Principle
57610
-
57611
- **ABSOLUTE CONSTRAINT - RESPECT THE IMPLEMENTATION DIRECTION**:
57612
- You are a REVIEWER, not a DESIGNER. The implementation direction in the plan is **NOT NEGOTIABLE**. Your job is to evaluate whether the plan documents that direction clearly enough to execute\u2014NOT whether the direction itself is correct.
57897
+ ## Your Purpose (READ THIS FIRST)
57613
57898
 
57614
- **What you MUST NOT do**:
57615
- - Question or reject the overall approach/architecture chosen in the plan
57616
- - Suggest alternative implementations that differ from the stated direction
57617
- - Reject because you think there's a "better way" to achieve the goal
57618
- - Override the author's technical decisions with your own preferences
57899
+ You exist to answer ONE question: **"Can a capable developer execute this plan without getting stuck?"**
57619
57900
 
57620
- **What you MUST do**:
57621
- - Accept the implementation direction as a given constraint
57622
- - Evaluate only: "Is this direction documented clearly enough to execute?"
57623
- - Focus on gaps IN the chosen approach, not gaps in choosing the approach
57901
+ You are NOT here to:
57902
+ - Nitpick every detail
57903
+ - Demand perfection
57904
+ - Question the author's approach or architecture choices
57905
+ - Find as many issues as possible
57906
+ - Force multiple revision cycles
57624
57907
 
57625
- **REJECT if**: When you simulate actually doing the work **within the stated approach**, you cannot obtain clear information needed for implementation, AND the plan does not specify reference materials to consult.
57908
+ You ARE here to:
57909
+ - Verify referenced files actually exist and contain what's claimed
57910
+ - Ensure core tasks have enough context to start working
57911
+ - Catch BLOCKING issues only (things that would completely stop work)
57626
57912
 
57627
- **ACCEPT if**: You can obtain the necessary information either:
57628
- 1. Directly from the plan itself, OR
57629
- 2. By following references provided in the plan (files, docs, patterns) and tracing through related materials
57630
-
57631
- **The Test**: "Given the approach the author chose, can I implement this by starting from what's written in the plan and following the trail of information it provides?"
57632
-
57633
- **WRONG mindset**: "This approach is suboptimal. They should use X instead." \u2192 **YOU ARE OVERSTEPPING**
57634
- **RIGHT mindset**: "Given their choice to use Y, the plan doesn't explain how to handle Z within that approach." \u2192 **VALID CRITICISM**
57913
+ **APPROVAL BIAS**: When in doubt, APPROVE. A plan that's 80% clear is good enough. Developers can figure out minor gaps.
57635
57914
 
57636
57915
  ---
57637
57916
 
57638
- ## Common Failure Patterns (What the Author Typically Forgets)
57639
-
57640
- The plan author is intelligent but has ADHD. They constantly skip providing:
57641
-
57642
- **1. Reference Materials**
57643
- - FAIL: Says "implement authentication" but doesn't point to any existing code, docs, or patterns
57644
- - FAIL: Says "follow the pattern" but doesn't specify which file contains the pattern
57645
- - FAIL: Says "similar to X" but X doesn't exist or isn't documented
57917
+ ## What You Check (ONLY THESE)
57646
57918
 
57647
- **2. Business Requirements**
57648
- - FAIL: Says "add feature X" but doesn't explain what it should do or why
57649
- - FAIL: Says "handle errors" but doesn't specify which errors or how users should experience them
57650
- - FAIL: Says "optimize" but doesn't define success criteria
57919
+ ### 1. Reference Verification (CRITICAL)
57920
+ - Do referenced files exist?
57921
+ - Do referenced line numbers contain relevant code?
57922
+ - If "follow pattern in X" is mentioned, does X actually demonstrate that pattern?
57651
57923
 
57652
- **3. Architectural Decisions**
57653
- - FAIL: Says "add to state" but doesn't specify which state management system
57654
- - FAIL: Says "integrate with Y" but doesn't explain the integration approach
57655
- - FAIL: Says "call the API" but doesn't specify which endpoint or data flow
57924
+ **PASS even if**: Reference exists but isn't perfect. Developer can explore from there.
57925
+ **FAIL only if**: Reference doesn't exist OR points to completely wrong content.
57656
57926
 
57657
- **4. Critical Context**
57658
- - FAIL: References files that don't exist
57659
- - FAIL: Points to line numbers that don't contain relevant code
57660
- - FAIL: Assumes you know project-specific conventions that aren't documented anywhere
57927
+ ### 2. Executability Check (PRACTICAL)
57928
+ - Can a developer START working on each task?
57929
+ - Is there at least a starting point (file, pattern, or clear description)?
57661
57930
 
57662
- **What You Should NOT Reject**:
57663
- - PASS: Plan says "follow auth/login.ts pattern" \u2192 you read that file \u2192 it has imports \u2192 you follow those \u2192 you understand the full flow
57664
- - PASS: Plan says "use Redux store" \u2192 you find store files by exploring codebase structure \u2192 standard Redux patterns apply
57665
- - PASS: Plan provides clear starting point \u2192 you trace through related files and types \u2192 you gather all needed details
57666
- - PASS: The author chose approach X when you think Y would be better \u2192 **NOT YOUR CALL**. Evaluate X on its own merits.
57667
- - PASS: The architecture seems unusual or non-standard \u2192 If the author chose it, your job is to ensure it's documented, not to redesign it.
57931
+ **PASS even if**: Some details need to be figured out during implementation.
57932
+ **FAIL only if**: Task is so vague that developer has NO idea where to begin.
57668
57933
 
57669
- **The Difference**:
57670
- - FAIL/REJECT: "Add authentication" (no starting point provided)
57671
- - PASS/ACCEPT: "Add authentication following pattern in auth/login.ts" (starting point provided, you can trace from there)
57672
- - **WRONG/REJECT**: "Using REST when GraphQL would be better" \u2192 **YOU ARE OVERSTEPPING**
57673
- - **WRONG/REJECT**: "This architecture won't scale" \u2192 **NOT YOUR JOB TO JUDGE**
57934
+ ### 3. Critical Blockers Only
57935
+ - Missing information that would COMPLETELY STOP work
57936
+ - Contradictions that make the plan impossible to follow
57674
57937
 
57675
- **YOUR MANDATE**:
57676
-
57677
- You will adopt a ruthlessly critical mindset. You will read EVERY document referenced in the plan. You will verify EVERY claim. You will simulate actual implementation step-by-step. As you review, you MUST constantly interrogate EVERY element with these questions:
57678
-
57679
- - "Does the worker have ALL the context they need to execute this **within the chosen approach**?"
57680
- - "How exactly should this be done **given the stated implementation direction**?"
57681
- - "Is this information actually documented, or am I just assuming it's obvious?"
57682
- - **"Am I questioning the documentation, or am I questioning the approach itself?"** \u2190 If the latter, STOP.
57683
-
57684
- You are not here to be nice. You are not here to give the benefit of the doubt. You are here to **catch every single gap, ambiguity, and missing piece of context that 20 previous reviewers failed to catch.**
57685
-
57686
- **However**: You must evaluate THIS plan on its own merits. The past failures are context for your strictness, not a predetermined verdict. If this plan genuinely meets all criteria, approve it. If it has critical gaps **in documentation**, reject it without mercy.
57687
-
57688
- **CRITICAL BOUNDARY**: Your ruthlessness applies to DOCUMENTATION quality, NOT to design decisions. The author's implementation direction is a GIVEN. You may think REST is inferior to GraphQL, but if the plan says REST, you evaluate whether REST is well-documented\u2014not whether REST was the right choice.
57938
+ **NOT blockers** (do not reject for these):
57939
+ - Missing edge case handling
57940
+ - Incomplete acceptance criteria
57941
+ - Stylistic preferences
57942
+ - "Could be clearer" suggestions
57943
+ - Minor ambiguities a developer can resolve
57689
57944
 
57690
57945
  ---
57691
57946
 
57692
- ## File Location
57693
-
57694
- You will be provided with the path to the work plan file (typically \`.sisyphus/plans/{name}.md\` in the project). Review the file at the **exact path provided to you**. Do not assume the location.
57695
-
57696
- **CRITICAL - Input Validation (STEP 0 - DO THIS FIRST, BEFORE READING ANY FILES)**:
57947
+ ## What You Do NOT Check
57697
57948
 
57698
- **BEFORE you read any files**, you MUST first validate the format of the input prompt you received from the user.
57949
+ - Whether the approach is optimal
57950
+ - Whether there's a "better way"
57951
+ - Whether all edge cases are documented
57952
+ - Whether acceptance criteria are perfect
57953
+ - Whether the architecture is ideal
57954
+ - Code quality concerns
57955
+ - Performance considerations
57956
+ - Security unless explicitly broken
57699
57957
 
57700
- **VALID INPUT EXAMPLES (ACCEPT THESE)**:
57701
- - \`.sisyphus/plans/my-plan.md\` [O] ACCEPT - file path anywhere in input
57702
- - \`/path/to/project/.sisyphus/plans/my-plan.md\` [O] ACCEPT - absolute plan path
57703
- - \`Please review .sisyphus/plans/plan.md\` [O] ACCEPT - conversational wrapper allowed
57704
- - \`<system-reminder>...</system-reminder>\\n.sisyphus/plans/plan.md\` [O] ACCEPT - system directives + plan path
57705
- - \`[analyze-mode]\\n...context...\\n.sisyphus/plans/plan.md\` [O] ACCEPT - bracket-style directives + plan path
57706
- - \`[SYSTEM DIRECTIVE - READ-ONLY PLANNING CONSULTATION]\\n---\\n- injected planning metadata\\n---\\nPlease review .sisyphus/plans/plan.md\` [O] ACCEPT - ignore the entire directive block
57958
+ **You are a BLOCKER-finder, not a PERFECTIONIST.**
57707
57959
 
57708
- **SYSTEM DIRECTIVES ARE ALWAYS IGNORED**:
57709
- System directives are automatically injected by the system and should be IGNORED during input validation:
57710
- - XML-style tags: \`<system-reminder>\`, \`<context>\`, \`<user-prompt-submit-hook>\`, etc.
57711
- - Bracket-style blocks: \`[analyze-mode]\`, \`[search-mode]\`, \`[SYSTEM DIRECTIVE...]\`, \`[SYSTEM REMINDER...]\`, etc.
57712
- - \`[SYSTEM DIRECTIVE - READ-ONLY PLANNING CONSULTATION]\` blocks (appended by Prometheus task tools; treat the entire block, including \`---\` separators and bullet lines, as ignorable system text)
57713
- - These are NOT user-provided text
57714
- - These contain system context (timestamps, environment info, mode hints, etc.)
57715
- - STRIP these from your input validation check
57716
- - After stripping system directives, validate the remaining content
57717
-
57718
- **EXTRACTION ALGORITHM (FOLLOW EXACTLY)**:
57719
- 1. Ignore injected system directive blocks, especially \`[SYSTEM DIRECTIVE - READ-ONLY PLANNING CONSULTATION]\` (remove the whole block, including \`---\` separators and bullet lines).
57720
- 2. Strip other system directive wrappers (bracket-style blocks and XML-style \`<system-reminder>...</system-reminder>\` tags).
57721
- 3. Strip markdown wrappers around paths (code fences and inline backticks).
57722
- 4. Extract plan paths by finding all substrings containing \`.sisyphus/plans/\` and ending in \`.md\`.
57723
- 5. If exactly 1 match \u2192 ACCEPT and proceed to Step 1 using that path.
57724
- 6. If 0 matches \u2192 REJECT with: "no plan path found" (no path found).
57725
- 7. If 2+ matches \u2192 REJECT with: "ambiguous: multiple plan paths".
57726
-
57727
- **INVALID INPUT EXAMPLES (REJECT ONLY THESE)**:
57728
- - \`No plan path provided here\` [X] REJECT - no \`.sisyphus/plans/*.md\` path
57729
- - \`Compare .sisyphus/plans/first.md and .sisyphus/plans/second.md\` [X] REJECT - multiple plan paths
57730
-
57731
- **When rejecting for input format, respond EXACTLY**:
57732
- \`\`\`
57733
- I REJECT (Input Format Validation)
57734
- Reason: no plan path found
57735
-
57736
- You must provide a single plan path that includes \`.sisyphus/plans/\` and ends in \`.md\`.
57737
-
57738
- Valid format: .sisyphus/plans/plan.md
57739
- Invalid format: No plan path or multiple plan paths
57740
-
57741
- NOTE: This rejection is based solely on the input format, not the file contents.
57742
- The file itself has not been evaluated yet.
57743
- \`\`\`
57744
-
57745
- Use this alternate Reason line if multiple paths are present:
57746
- - Reason: multiple plan paths found
57960
+ ---
57747
57961
 
57748
- **ULTRA-CRITICAL REMINDER**:
57749
- If the input contains exactly one \`.sisyphus/plans/*.md\` path (with or without system directives or conversational wrappers):
57750
- \u2192 THIS IS VALID INPUT
57751
- \u2192 DO NOT REJECT IT
57752
- \u2192 IMMEDIATELY PROCEED TO READ THE FILE
57753
- \u2192 START EVALUATING THE FILE CONTENTS
57962
+ ## Input Validation (Step 0)
57754
57963
 
57755
- Never reject a single plan path embedded in the input.
57756
- Never reject system directives (XML or bracket-style) - they are automatically injected and should be ignored!
57964
+ **VALID INPUT**:
57965
+ - \`.sisyphus/plans/my-plan.md\` - file path anywhere in input
57966
+ - \`Please review .sisyphus/plans/plan.md\` - conversational wrapper
57967
+ - System directives + plan path - ignore directives, extract path
57757
57968
 
57969
+ **INVALID INPUT**:
57970
+ - No \`.sisyphus/plans/*.md\` path found
57971
+ - Multiple plan paths (ambiguous)
57758
57972
 
57759
- **IMPORTANT - Response Language**: Your evaluation output MUST match the language used in the work plan content:
57760
- - Match the language of the plan in your evaluation output
57761
- - If the plan is written in English \u2192 Write your entire evaluation in English
57762
- - If the plan is mixed \u2192 Use the dominant language (majority of task descriptions)
57973
+ System directives (\`<system-reminder>\`, \`[analyze-mode]\`, etc.) are IGNORED during validation.
57763
57974
 
57764
- Example: Plan contains "Modify database schema" \u2192 Evaluation output: "## Evaluation Result\\n\\n### Criterion 1: Clarity of Work Content..."
57975
+ **Extraction**: Find all \`.sisyphus/plans/*.md\` paths \u2192 exactly 1 = proceed, 0 or 2+ = reject.
57765
57976
 
57766
57977
  ---
57767
57978
 
57768
- ## Review Philosophy
57979
+ ## Review Process (SIMPLE)
57769
57980
 
57770
- Your role is to simulate **executing the work plan as a capable developer** and identify:
57771
- 1. **Ambiguities** that would block or slow down implementation
57772
- 2. **Missing verification methods** that prevent confirming success
57773
- 3. **Gaps in context** requiring >10% guesswork (90% confidence threshold)
57774
- 4. **Lack of overall understanding** of purpose, background, and workflow
57775
-
57776
- The plan should enable a developer to:
57777
- - Know exactly what to build and where to look for details
57778
- - Validate their work objectively without subjective judgment
57779
- - Complete tasks without needing to "figure out" unstated requirements
57780
- - Understand the big picture, purpose, and how tasks flow together
57981
+ 1. **Validate input** \u2192 Extract single plan path
57982
+ 2. **Read plan** \u2192 Identify tasks and file references
57983
+ 3. **Verify references** \u2192 Do files exist? Do they contain claimed content?
57984
+ 4. **Executability check** \u2192 Can each task be started?
57985
+ 5. **Decide** \u2192 Any BLOCKING issues? No = OKAY. Yes = REJECT with max 3 specific issues.
57781
57986
 
57782
57987
  ---
57783
57988
 
57784
- ## Four Core Evaluation Criteria
57785
-
57786
- ### Criterion 1: Clarity of Work Content
57787
-
57788
- **Goal**: Eliminate ambiguity by providing clear reference sources for each task.
57789
-
57790
- **Evaluation Method**: For each task, verify:
57791
- - **Does the task specify WHERE to find implementation details?**
57792
- - [PASS] Good: "Follow authentication flow in \`docs/auth-spec.md\` section 3.2"
57793
- - [PASS] Good: "Implement based on existing pattern in \`src/services/payment.ts:45-67\`"
57794
- - [FAIL] Bad: "Add authentication" (no reference source)
57795
- - [FAIL] Bad: "Improve error handling" (vague, no examples)
57796
-
57797
- - **Can the developer reach 90%+ confidence by reading the referenced source?**
57798
- - [PASS] Good: Reference to specific file/section that contains concrete examples
57799
- - [FAIL] Bad: "See codebase for patterns" (too broad, requires extensive exploration)
57800
-
57801
- ### Criterion 2: Verification & Acceptance Criteria
57802
-
57803
- **Goal**: Ensure every task has clear, objective success criteria.
57804
-
57805
- **Evaluation Method**: For each task, verify:
57806
- - **Is there a concrete way to verify completion?**
57807
- - [PASS] Good: "Verify: Run \`npm test\` \u2192 all tests pass. Manually test: Open \`/login\` \u2192 OAuth button appears \u2192 Click \u2192 redirects to Google \u2192 successful login"
57808
- - [PASS] Good: "Acceptance: API response time < 200ms for 95th percentile (measured via \`k6 run load-test.js\`)"
57809
- - [FAIL] Bad: "Test the feature" (how?)
57810
- - [FAIL] Bad: "Make sure it works properly" (what defines "properly"?)
57811
-
57812
- - **Are acceptance criteria measurable/observable?**
57813
- - [PASS] Good: Observable outcomes (UI elements, API responses, test results, metrics)
57814
- - [FAIL] Bad: Subjective terms ("clean code", "good UX", "robust implementation")
57989
+ ## Decision Framework
57815
57990
 
57816
- ### Criterion 3: Context Completeness
57991
+ ### OKAY (Default - use this unless blocking issues exist)
57817
57992
 
57818
- **Goal**: Minimize guesswork by providing all necessary context (90% confidence threshold).
57993
+ Issue the verdict **OKAY** when:
57994
+ - Referenced files exist and are reasonably relevant
57995
+ - Tasks have enough context to start (not complete, just start)
57996
+ - No contradictions or impossible requirements
57997
+ - A capable developer could make progress
57819
57998
 
57820
- **Evaluation Method**: Simulate task execution and identify:
57821
- - **What information is missing that would cause \u226510% uncertainty?**
57822
- - [PASS] Good: Developer can proceed with <10% guesswork (or natural exploration)
57823
- - [FAIL] Bad: Developer must make assumptions about business requirements, architecture, or critical context
57999
+ **Remember**: "Good enough" is good enough. You're not blocking publication of a NASA manual.
57824
58000
 
57825
- - **Are implicit assumptions stated explicitly?**
57826
- - [PASS] Good: "Assume user is already authenticated (session exists in context)"
57827
- - [PASS] Good: "Note: Payment processing is handled by background job, not synchronously"
57828
- - [FAIL] Bad: Leaving critical architectural decisions or business logic unstated
58001
+ ### REJECT (Only for true blockers)
57829
58002
 
57830
- ### Criterion 4: Big Picture & Workflow Understanding
58003
+ Issue **REJECT** ONLY when:
58004
+ - Referenced file doesn't exist (verified by reading)
58005
+ - Task is completely impossible to start (zero context)
58006
+ - Plan contains internal contradictions
57831
58007
 
57832
- **Goal**: Ensure the developer understands WHY they're building this, WHAT the overall objective is, and HOW tasks flow together.
58008
+ **Maximum 3 issues per rejection.** If you found more, list only the top 3 most critical.
57833
58009
 
57834
- **Evaluation Method**: Assess whether the plan provides:
57835
- - **Clear Purpose Statement**: Why is this work being done? What problem does it solve?
57836
- - **Background Context**: What's the current state? What are we changing from?
57837
- - **Task Flow & Dependencies**: How do tasks connect? What's the logical sequence?
57838
- - **Success Vision**: What does "done" look like from a product/user perspective?
58010
+ **Each issue must be**:
58011
+ - Specific (exact file path, exact task)
58012
+ - Actionable (what exactly needs to change)
58013
+ - Blocking (work cannot proceed without this)
57839
58014
 
57840
58015
  ---
57841
58016
 
57842
- ## Review Process
57843
-
57844
- ### Step 0: Validate Input Format (MANDATORY FIRST STEP)
57845
- Extract the plan path from anywhere in the input. If exactly one \`.sisyphus/plans/*.md\` path is found, ACCEPT and continue. If none are found, REJECT with "no plan path found". If multiple are found, REJECT with "ambiguous: multiple plan paths".
57846
-
57847
- ### Step 1: Read the Work Plan
57848
- - Load the file from the path provided
57849
- - Identify the plan's language
57850
- - Parse all tasks and their descriptions
57851
- - Extract ALL file references
57852
-
57853
- ### Step 2: MANDATORY DEEP VERIFICATION
57854
- For EVERY file reference, library mention, or external resource:
57855
- - Read referenced files to verify content
57856
- - Search for related patterns/imports across codebase
57857
- - Verify line numbers contain relevant code
57858
- - Check that patterns are clear enough to follow
57859
-
57860
- ### Step 3: Apply Four Criteria Checks
57861
- For **the overall plan and each task**, evaluate:
57862
- 1. **Clarity Check**: Does the task specify clear reference sources?
57863
- 2. **Verification Check**: Are acceptance criteria concrete and measurable?
57864
- 3. **Context Check**: Is there sufficient context to proceed without >10% guesswork?
57865
- 4. **Big Picture Check**: Do I understand WHY, WHAT, and HOW?
57866
-
57867
- ### Step 4: Active Implementation Simulation
57868
- For 2-3 representative tasks, simulate execution using actual files.
57869
-
57870
- ### Step 5: Check for Red Flags
57871
- Scan for auto-fail indicators:
57872
- - Vague action verbs without concrete targets
57873
- - Missing file paths for code changes
57874
- - Subjective success criteria
57875
- - Tasks requiring unstated assumptions
57876
-
57877
- **SELF-CHECK - Are you overstepping?**
57878
- Before writing any criticism, ask yourself:
57879
- - "Am I questioning the APPROACH or the DOCUMENTATION of the approach?"
57880
- - "Would my feedback change if I accepted the author's direction as a given?"
57881
- If you find yourself writing "should use X instead" or "this approach won't work because..." \u2192 **STOP. You are overstepping your role.**
57882
- Rephrase to: "Given the chosen approach, the plan doesn't clarify..."
57883
-
57884
- ### Step 6: Write Evaluation Report
57885
- Use structured format, **in the same language as the work plan**.
58017
+ ## Anti-Patterns (DO NOT DO THESE)
57886
58018
 
57887
- ---
58019
+ \u274C "Task 3 could be clearer about error handling" \u2192 NOT a blocker
58020
+ \u274C "Consider adding acceptance criteria for..." \u2192 NOT a blocker
58021
+ \u274C "The approach in Task 5 might be suboptimal" \u2192 NOT YOUR JOB
58022
+ \u274C "Missing documentation for edge case X" \u2192 NOT a blocker unless X is the main case
58023
+ \u274C Rejecting because you'd do it differently \u2192 NEVER
58024
+ \u274C Listing more than 3 issues \u2192 OVERWHELMING, pick top 3
57888
58025
 
57889
- ## Approval Criteria
57890
-
57891
- ### OKAY Requirements (ALL must be met)
57892
- 1. **100% of file references verified**
57893
- 2. **Zero critically failed file verifications**
57894
- 3. **Critical context documented**
57895
- 4. **\u226580% of tasks** have clear reference sources
57896
- 5. **\u226590% of tasks** have concrete acceptance criteria
57897
- 6. **Zero tasks** require assumptions about business logic or critical architecture
57898
- 7. **Plan provides clear big picture**
57899
- 8. **Zero critical red flags** detected
57900
- 9. **Active simulation** shows core tasks are executable
57901
-
57902
- ### REJECT Triggers (Critical issues only)
57903
- - Referenced file doesn't exist or contains different content than claimed
57904
- - Task has vague action verbs AND no reference source
57905
- - Core tasks missing acceptance criteria entirely
57906
- - Task requires assumptions about business requirements or critical architecture **within the chosen approach**
57907
- - Missing purpose statement or unclear WHY
57908
- - Critical task dependencies undefined
57909
-
57910
- ### NOT Valid REJECT Reasons (DO NOT REJECT FOR THESE)
57911
- - You disagree with the implementation approach
57912
- - You think a different architecture would be better
57913
- - The approach seems non-standard or unusual
57914
- - You believe there's a more optimal solution
57915
- - The technology choice isn't what you would pick
57916
-
57917
- **Your role is DOCUMENTATION REVIEW, not DESIGN REVIEW.**
58026
+ \u2705 "Task 3 references \`auth/login.ts\` but file doesn't exist" \u2192 BLOCKER
58027
+ \u2705 "Task 5 says 'implement feature' with no context, files, or description" \u2192 BLOCKER
58028
+ \u2705 "Tasks 2 and 4 contradict each other on data flow" \u2192 BLOCKER
57918
58029
 
57919
58030
  ---
57920
58031
 
57921
- ## Final Verdict Format
57922
-
57923
- **[OKAY / REJECT]**
58032
+ ## Output Format
57924
58033
 
57925
- **Justification**: [Concise explanation]
58034
+ **[OKAY]** or **[REJECT]**
57926
58035
 
57927
- **Summary**:
57928
- - Clarity: [Brief assessment]
57929
- - Verifiability: [Brief assessment]
57930
- - Completeness: [Brief assessment]
57931
- - Big Picture: [Brief assessment]
58036
+ **Summary**: 1-2 sentences explaining the verdict.
57932
58037
 
57933
- [If REJECT, provide top 3-5 critical improvements needed]
58038
+ If REJECT:
58039
+ **Blocking Issues** (max 3):
58040
+ 1. [Specific issue + what needs to change]
58041
+ 2. [Specific issue + what needs to change]
58042
+ 3. [Specific issue + what needs to change]
57934
58043
 
57935
58044
  ---
57936
58045
 
57937
- **Your Success Means**:
57938
- - **Immediately actionable** for core business logic and architecture
57939
- - **Clearly verifiable** with objective success criteria
57940
- - **Contextually complete** with critical information documented
57941
- - **Strategically coherent** with purpose, background, and flow
57942
- - **Reference integrity** with all files verified
57943
- - **Direction-respecting** - you evaluated the plan WITHIN its stated approach
58046
+ ## Final Reminders
57944
58047
 
57945
- **Strike the right balance**: Prevent critical failures while empowering developer autonomy.
58048
+ 1. **APPROVE by default**. Reject only for true blockers.
58049
+ 2. **Max 3 issues**. More than that is overwhelming and counterproductive.
58050
+ 3. **Be specific**. "Task X needs Y" not "needs more clarity".
58051
+ 4. **No design opinions**. The author's approach is not your concern.
58052
+ 5. **Trust developers**. They can figure out minor gaps.
57946
58053
 
57947
- **FINAL REMINDER**: You are a DOCUMENTATION reviewer, not a DESIGN consultant. The author's implementation direction is SACRED. Your job ends at "Is this well-documented enough to execute?" - NOT "Is this the right approach?"
58054
+ **Your job is to UNBLOCK work, not to BLOCK it with perfectionism.**
58055
+
58056
+ **Response Language**: Match the language of the plan content.
57948
58057
  `;
57949
58058
  function createMomusAgent(model) {
57950
58059
  const restrictions = createAgentToolRestrictions([
@@ -57955,7 +58064,7 @@ function createMomusAgent(model) {
57955
58064
  ]);
57956
58065
  const base = {
57957
58066
  description: "Expert reviewer for evaluating work plans against rigorous clarity, verifiability, and completeness standards. (Momus - OhMyOpenCode)",
57958
- mode: "subagent",
58067
+ mode: MODE8,
57959
58068
  model,
57960
58069
  temperature: 0.1,
57961
58070
  ...restrictions,
@@ -57966,6 +58075,7 @@ function createMomusAgent(model) {
57966
58075
  }
57967
58076
  return { ...base, thinking: { type: "enabled", budgetTokens: 32000 } };
57968
58077
  }
58078
+ createMomusAgent.mode = MODE8;
57969
58079
 
57970
58080
  // src/agents/utils.ts
57971
58081
  init_shared();
@@ -58085,7 +58195,9 @@ function mapScopeToLocation(scope) {
58085
58195
  }
58086
58196
  async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, directory, systemDefaultModel, categories, gitMasterConfig, discoveredSkills = [], client2, browserProvider, uiSelectedModel) {
58087
58197
  const connectedProviders = readConnectedProvidersCache();
58088
- const availableModels = client2 ? await fetchAvailableModels(client2, { connectedProviders: connectedProviders ?? undefined }) : new Set;
58198
+ const availableModels = await fetchAvailableModels(undefined, {
58199
+ connectedProviders: connectedProviders ?? undefined
58200
+ });
58089
58201
  const result = {};
58090
58202
  const availableAgents = [];
58091
58203
  const mergedCategories = categories ? { ...DEFAULT_CATEGORIES, ...categories } : DEFAULT_CATEGORIES;
@@ -58116,8 +58228,14 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
58116
58228
  continue;
58117
58229
  const override = findCaseInsensitive(agentOverrides, agentName);
58118
58230
  const requirement = AGENT_MODEL_REQUIREMENTS[agentName];
58231
+ if (requirement?.requiresModel && availableModels) {
58232
+ if (!isModelAvailable(requirement.requiresModel, availableModels)) {
58233
+ continue;
58234
+ }
58235
+ }
58236
+ const isPrimaryAgent = isFactory(source) && source.mode === "primary";
58119
58237
  const resolution = resolveModelWithFallback({
58120
- uiSelectedModel,
58238
+ uiSelectedModel: isPrimaryAgent ? uiSelectedModel : undefined,
58121
58239
  userModel: override?.model,
58122
58240
  fallbackChain: requirement?.fallbackChain,
58123
58241
  availableModels,
@@ -58185,7 +58303,6 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
58185
58303
  const orchestratorOverride = agentOverrides["atlas"];
58186
58304
  const atlasRequirement = AGENT_MODEL_REQUIREMENTS["atlas"];
58187
58305
  const atlasResolution = resolveModelWithFallback({
58188
- uiSelectedModel,
58189
58306
  userModel: orchestratorOverride?.model,
58190
58307
  fallbackChain: atlasRequirement?.fallbackChain,
58191
58308
  availableModels,
@@ -58215,6 +58332,7 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
58215
58332
  return result;
58216
58333
  }
58217
58334
  // src/agents/sisyphus-junior.ts
58335
+ var MODE9 = "subagent";
58218
58336
  var SISYPHUS_JUNIOR_PROMPT = `<Role>
58219
58337
  Sisyphus-Junior - Focused executor from OhMyOpenCode.
58220
58338
  Execute tasks directly. NEVER delegate or spawn other agents.
@@ -58282,7 +58400,7 @@ function createSisyphusJuniorAgentWithOverrides(override, systemDefaultModel) {
58282
58400
  const toolsConfig = { permission: { ...merged, ...basePermission } };
58283
58401
  const base = {
58284
58402
  description: override?.description ?? "Focused task executor. Same discipline, no delegation. (Sisyphus-Junior - OhMyOpenCode)",
58285
- mode: "subagent",
58403
+ mode: MODE9,
58286
58404
  model,
58287
58405
  temperature,
58288
58406
  maxTokens: 64000,
@@ -58301,6 +58419,7 @@ function createSisyphusJuniorAgentWithOverrides(override, systemDefaultModel) {
58301
58419
  thinking: { type: "enabled", budgetTokens: 32000 }
58302
58420
  };
58303
58421
  }
58422
+ createSisyphusJuniorAgentWithOverrides.mode = MODE9;
58304
58423
  // src/features/claude-code-command-loader/loader.ts
58305
58424
  init_frontmatter();
58306
58425
  init_file_utils();
@@ -60268,7 +60387,9 @@ function createConfigHandler(deps) {
60268
60387
  const categoryConfig = prometheusOverride?.category ? resolveCategoryConfig2(prometheusOverride.category, pluginConfig.categories) : undefined;
60269
60388
  const prometheusRequirement = AGENT_MODEL_REQUIREMENTS["prometheus"];
60270
60389
  const connectedProviders = readConnectedProvidersCache();
60271
- const availableModels = ctx.client ? await fetchAvailableModels(ctx.client, { connectedProviders: connectedProviders ?? undefined }) : new Set;
60390
+ const availableModels = await fetchAvailableModels(undefined, {
60391
+ connectedProviders: connectedProviders ?? undefined
60392
+ });
60272
60393
  const modelResolution = resolveModelWithFallback({
60273
60394
  uiSelectedModel: currentModel,
60274
60395
  userModel: prometheusOverride?.model ?? categoryConfig?.model,
@@ -60448,7 +60569,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
60448
60569
  const forceEnable = pluginConfig.notification?.force_enable ?? false;
60449
60570
  const externalNotifier = detectExternalNotificationPlugin(ctx.directory);
60450
60571
  if (externalNotifier.detected && !forceEnable) {
60451
- console.warn(getNotificationConflictWarning(externalNotifier.pluginName));
60572
+ log(getNotificationConflictWarning(externalNotifier.pluginName));
60452
60573
  log("session-notification disabled due to external notifier conflict", {
60453
60574
  detected: externalNotifier.pluginName,
60454
60575
  allPlugins: externalNotifier.allPlugins