oh-my-opencode 3.12.1 → 3.12.2

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/cli/index.js CHANGED
@@ -4920,17 +4920,40 @@ var init_file_reference_resolver = () => {};
4920
4920
  import * as fs from "fs";
4921
4921
  import * as os from "os";
4922
4922
  import * as path from "path";
4923
+ function flush() {
4924
+ if (buffer.length === 0)
4925
+ return;
4926
+ const data = buffer.join("");
4927
+ buffer = [];
4928
+ try {
4929
+ fs.appendFileSync(logFile, data);
4930
+ } catch {}
4931
+ }
4932
+ function scheduleFlush() {
4933
+ if (flushTimer)
4934
+ return;
4935
+ flushTimer = setTimeout(() => {
4936
+ flushTimer = null;
4937
+ flush();
4938
+ }, FLUSH_INTERVAL_MS);
4939
+ }
4923
4940
  function log(message, data) {
4924
4941
  try {
4925
4942
  const timestamp2 = new Date().toISOString();
4926
4943
  const logEntry = `[${timestamp2}] ${message} ${data ? JSON.stringify(data) : ""}
4927
4944
  `;
4928
- fs.appendFileSync(logFile, logEntry);
4945
+ buffer.push(logEntry);
4946
+ if (buffer.length >= BUFFER_SIZE_LIMIT) {
4947
+ flush();
4948
+ } else {
4949
+ scheduleFlush();
4950
+ }
4929
4951
  } catch {}
4930
4952
  }
4931
- var logFile;
4953
+ var logFile, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50;
4932
4954
  var init_logger = __esm(() => {
4933
4955
  logFile = path.join(os.tmpdir(), "oh-my-opencode.log");
4956
+ buffer = [];
4934
4957
  });
4935
4958
 
4936
4959
  // src/shared/deep-merge.ts
@@ -4974,6 +4997,12 @@ var init_snake_case = __esm(() => {
4974
4997
 
4975
4998
  // src/shared/tool-name.ts
4976
4999
  var init_tool_name = () => {};
5000
+
5001
+ // src/shared/pattern-matcher.ts
5002
+ var regexCache;
5003
+ var init_pattern_matcher = __esm(() => {
5004
+ regexCache = new Map;
5005
+ });
4977
5006
  // src/shared/file-utils.ts
4978
5007
  var init_file_utils = () => {};
4979
5008
 
@@ -6623,6 +6652,8 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
6623
6652
  function getCacheFilePath(filename) {
6624
6653
  return join4(getCacheDir2(), filename);
6625
6654
  }
6655
+ let memConnected;
6656
+ let memProviderModels;
6626
6657
  function ensureCacheDir() {
6627
6658
  const cacheDir = getCacheDir2();
6628
6659
  if (!existsSync3(cacheDir)) {
@@ -6630,18 +6661,23 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
6630
6661
  }
6631
6662
  }
6632
6663
  function readConnectedProvidersCache() {
6664
+ if (memConnected !== undefined)
6665
+ return memConnected;
6633
6666
  const cacheFile = getCacheFilePath(CONNECTED_PROVIDERS_CACHE_FILE);
6634
6667
  if (!existsSync3(cacheFile)) {
6635
6668
  log("[connected-providers-cache] Cache file not found", { cacheFile });
6669
+ memConnected = null;
6636
6670
  return null;
6637
6671
  }
6638
6672
  try {
6639
6673
  const content = readFileSync2(cacheFile, "utf-8");
6640
6674
  const data = JSON.parse(content);
6641
6675
  log("[connected-providers-cache] Read cache", { count: data.connected.length, updatedAt: data.updatedAt });
6676
+ memConnected = data.connected;
6642
6677
  return data.connected;
6643
6678
  } catch (err) {
6644
6679
  log("[connected-providers-cache] Error reading cache", { error: String(err) });
6680
+ memConnected = null;
6645
6681
  return null;
6646
6682
  }
6647
6683
  }
@@ -6658,15 +6694,19 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
6658
6694
  };
6659
6695
  try {
6660
6696
  writeFileSync2(cacheFile, JSON.stringify(data, null, 2));
6697
+ memConnected = connected;
6661
6698
  log("[connected-providers-cache] Cache written", { count: connected.length });
6662
6699
  } catch (err) {
6663
6700
  log("[connected-providers-cache] Error writing cache", { error: String(err) });
6664
6701
  }
6665
6702
  }
6666
6703
  function readProviderModelsCache() {
6704
+ if (memProviderModels !== undefined)
6705
+ return memProviderModels;
6667
6706
  const cacheFile = getCacheFilePath(PROVIDER_MODELS_CACHE_FILE);
6668
6707
  if (!existsSync3(cacheFile)) {
6669
6708
  log("[connected-providers-cache] Provider-models cache file not found", { cacheFile });
6709
+ memProviderModels = null;
6670
6710
  return null;
6671
6711
  }
6672
6712
  try {
@@ -6676,9 +6716,11 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
6676
6716
  providerCount: Object.keys(data.models).length,
6677
6717
  updatedAt: data.updatedAt
6678
6718
  });
6719
+ memProviderModels = data;
6679
6720
  return data;
6680
6721
  } catch (err) {
6681
6722
  log("[connected-providers-cache] Error reading provider-models cache", { error: String(err) });
6723
+ memProviderModels = null;
6682
6724
  return null;
6683
6725
  }
6684
6726
  }
@@ -6695,6 +6737,7 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
6695
6737
  };
6696
6738
  try {
6697
6739
  writeFileSync2(cacheFile, JSON.stringify(cacheData, null, 2));
6740
+ memProviderModels = cacheData;
6698
6741
  log("[connected-providers-cache] Provider-models cache written", {
6699
6742
  providerCount: Object.keys(data.models).length
6700
6743
  });
@@ -7127,6 +7170,7 @@ var init_shared = __esm(() => {
7127
7170
  init_logger();
7128
7171
  init_snake_case();
7129
7172
  init_tool_name();
7173
+ init_pattern_matcher();
7130
7174
  init_deep_merge();
7131
7175
  init_file_utils();
7132
7176
  init_dynamic_truncator();
@@ -8897,7 +8941,7 @@ var {
8897
8941
  // package.json
8898
8942
  var package_default = {
8899
8943
  name: "oh-my-opencode",
8900
- version: "3.12.1",
8944
+ version: "3.12.2",
8901
8945
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
8902
8946
  main: "dist/index.js",
8903
8947
  types: "dist/index.d.ts",
@@ -8973,17 +9017,17 @@ var package_default = {
8973
9017
  typescript: "^5.7.3"
8974
9018
  },
8975
9019
  optionalDependencies: {
8976
- "oh-my-opencode-darwin-arm64": "3.12.1",
8977
- "oh-my-opencode-darwin-x64": "3.12.1",
8978
- "oh-my-opencode-darwin-x64-baseline": "3.12.1",
8979
- "oh-my-opencode-linux-arm64": "3.12.1",
8980
- "oh-my-opencode-linux-arm64-musl": "3.12.1",
8981
- "oh-my-opencode-linux-x64": "3.12.1",
8982
- "oh-my-opencode-linux-x64-baseline": "3.12.1",
8983
- "oh-my-opencode-linux-x64-musl": "3.12.1",
8984
- "oh-my-opencode-linux-x64-musl-baseline": "3.12.1",
8985
- "oh-my-opencode-windows-x64": "3.12.1",
8986
- "oh-my-opencode-windows-x64-baseline": "3.12.1"
9020
+ "oh-my-opencode-darwin-arm64": "3.12.2",
9021
+ "oh-my-opencode-darwin-x64": "3.12.2",
9022
+ "oh-my-opencode-darwin-x64-baseline": "3.12.2",
9023
+ "oh-my-opencode-linux-arm64": "3.12.2",
9024
+ "oh-my-opencode-linux-arm64-musl": "3.12.2",
9025
+ "oh-my-opencode-linux-x64": "3.12.2",
9026
+ "oh-my-opencode-linux-x64-baseline": "3.12.2",
9027
+ "oh-my-opencode-linux-x64-musl": "3.12.2",
9028
+ "oh-my-opencode-linux-x64-musl-baseline": "3.12.2",
9029
+ "oh-my-opencode-windows-x64": "3.12.2",
9030
+ "oh-my-opencode-windows-x64-baseline": "3.12.2"
8987
9031
  },
8988
9032
  overrides: {
8989
9033
  "@opencode-ai/sdk": "^1.2.24"
@@ -10352,24 +10396,24 @@ function writePaddedText(text, atLineStart) {
10352
10396
  return { output: text, atLineStart: text.endsWith(`
10353
10397
  `) };
10354
10398
  }
10355
- let output = "";
10399
+ const parts = [];
10356
10400
  let lineStart = atLineStart;
10357
10401
  for (let i2 = 0;i2 < text.length; i2++) {
10358
10402
  const ch = text[i2];
10359
10403
  if (lineStart) {
10360
- output += " ";
10404
+ parts.push(" ");
10361
10405
  lineStart = false;
10362
10406
  }
10363
10407
  if (ch === `
10364
10408
  `) {
10365
- output += `
10366
- `;
10409
+ parts.push(`
10410
+ `);
10367
10411
  lineStart = true;
10368
10412
  continue;
10369
10413
  }
10370
- output += ch;
10414
+ parts.push(ch);
10371
10415
  }
10372
- return { output, atLineStart: lineStart };
10416
+ return { output: parts.join(""), atLineStart: lineStart };
10373
10417
  }
10374
10418
  function colorizeWithProfileColor(text, hexColor) {
10375
10419
  if (!hexColor)
@@ -24364,8 +24408,7 @@ var BabysittingConfigSchema = exports_external.object({
24364
24408
  var CircuitBreakerConfigSchema = exports_external.object({
24365
24409
  enabled: exports_external.boolean().optional(),
24366
24410
  maxToolCalls: exports_external.number().int().min(10).optional(),
24367
- windowSize: exports_external.number().int().min(5).optional(),
24368
- repetitionThresholdPercent: exports_external.number().gt(0).max(100).optional()
24411
+ consecutiveThreshold: exports_external.number().int().min(5).optional()
24369
24412
  });
24370
24413
  var BackgroundTaskConfigSchema = exports_external.object({
24371
24414
  defaultConcurrency: exports_external.number().min(1).optional(),
@@ -24863,7 +24906,7 @@ var createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseVa
24863
24906
  if (!response.body)
24864
24907
  throw new Error("No body in SSE response");
24865
24908
  const reader = response.body.pipeThrough(new TextDecoderStream).getReader();
24866
- let buffer = "";
24909
+ let buffer2 = "";
24867
24910
  const abortHandler = () => {
24868
24911
  try {
24869
24912
  reader.cancel();
@@ -24875,11 +24918,11 @@ var createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseVa
24875
24918
  const { done, value } = await reader.read();
24876
24919
  if (done)
24877
24920
  break;
24878
- buffer += value;
24879
- const chunks = buffer.split(`
24921
+ buffer2 += value;
24922
+ const chunks = buffer2.split(`
24880
24923
 
24881
24924
  `);
24882
- buffer = chunks.pop() ?? "";
24925
+ buffer2 = chunks.pop() ?? "";
24883
24926
  for (const chunk of chunks) {
24884
24927
  const lines = chunk.split(`
24885
24928
  `);
@@ -12,8 +12,7 @@ export declare const BackgroundTaskConfigSchema: z.ZodObject<{
12
12
  circuitBreaker: z.ZodOptional<z.ZodObject<{
13
13
  enabled: z.ZodOptional<z.ZodBoolean>;
14
14
  maxToolCalls: z.ZodOptional<z.ZodNumber>;
15
- windowSize: z.ZodOptional<z.ZodNumber>;
16
- repetitionThresholdPercent: z.ZodOptional<z.ZodNumber>;
15
+ consecutiveThreshold: z.ZodOptional<z.ZodNumber>;
17
16
  }, z.core.$strip>>;
18
17
  }, z.core.$strip>;
19
18
  export type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>;
@@ -1345,8 +1345,7 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
1345
1345
  circuitBreaker: z.ZodOptional<z.ZodObject<{
1346
1346
  enabled: z.ZodOptional<z.ZodBoolean>;
1347
1347
  maxToolCalls: z.ZodOptional<z.ZodNumber>;
1348
- windowSize: z.ZodOptional<z.ZodNumber>;
1349
- repetitionThresholdPercent: z.ZodOptional<z.ZodNumber>;
1348
+ consecutiveThreshold: z.ZodOptional<z.ZodNumber>;
1350
1349
  }, z.core.$strip>>;
1351
1350
  }, z.core.$strip>>;
1352
1351
  notification: z.ZodOptional<z.ZodObject<{
@@ -6,8 +6,7 @@ export declare const MIN_STABILITY_TIME_MS: number;
6
6
  export declare const DEFAULT_STALE_TIMEOUT_MS = 1200000;
7
7
  export declare const DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 1800000;
8
8
  export declare const DEFAULT_MAX_TOOL_CALLS = 200;
9
- export declare const DEFAULT_CIRCUIT_BREAKER_WINDOW_SIZE = 20;
10
- export declare const DEFAULT_CIRCUIT_BREAKER_REPETITION_THRESHOLD_PERCENT = 80;
9
+ export declare const DEFAULT_CIRCUIT_BREAKER_CONSECUTIVE_THRESHOLD = 20;
11
10
  export declare const DEFAULT_CIRCUIT_BREAKER_ENABLED = true;
12
11
  export declare const MIN_RUNTIME_BEFORE_STALE_MS = 30000;
13
12
  export declare const MIN_IDLE_TIME_MS = 5000;
@@ -3,15 +3,12 @@ import type { ToolCallWindow } from "./types";
3
3
  export interface CircuitBreakerSettings {
4
4
  enabled: boolean;
5
5
  maxToolCalls: number;
6
- windowSize: number;
7
- repetitionThresholdPercent: number;
6
+ consecutiveThreshold: number;
8
7
  }
9
8
  export interface ToolLoopDetectionResult {
10
9
  triggered: boolean;
11
10
  toolName?: string;
12
11
  repeatedCount?: number;
13
- sampleSize?: number;
14
- thresholdPercent?: number;
15
12
  }
16
13
  export declare function resolveCircuitBreakerSettings(config?: BackgroundTaskConfig): CircuitBreakerSettings;
17
14
  export declare function recordToolCall(window: ToolCallWindow | undefined, toolName: string, settings: CircuitBreakerSettings, toolInput?: Record<string, unknown> | null): ToolCallWindow;
@@ -45,6 +45,7 @@ export declare class BackgroundManager {
45
45
  private preStartDescendantReservations;
46
46
  private enableParentSessionNotifications;
47
47
  readonly taskHistory: TaskHistory;
48
+ private cachedCircuitBreakerSettings?;
48
49
  constructor(ctx: PluginInput, config?: BackgroundTaskConfig, options?: {
49
50
  tmuxConfig?: TmuxConfig;
50
51
  onSubagentSessionCreated?: OnSubagentSessionCreated;
@@ -0,0 +1,2 @@
1
+ export declare function isActiveSessionStatus(type: string): boolean;
2
+ export declare function isTerminalSessionStatus(type: string): boolean;
@@ -2,15 +2,15 @@ import type { FallbackEntry } from "../../shared/model-requirements";
2
2
  import type { SessionPermissionRule } from "../../shared/question-denied-session-permission";
3
3
  export type BackgroundTaskStatus = "pending" | "running" | "completed" | "error" | "cancelled" | "interrupt";
4
4
  export interface ToolCallWindow {
5
- toolSignatures: string[];
6
- windowSize: number;
7
- thresholdPercent: number;
5
+ lastSignature: string;
6
+ consecutiveCount: number;
7
+ threshold: number;
8
8
  }
9
9
  export interface TaskProgress {
10
10
  toolCalls: number;
11
11
  lastTool?: string;
12
12
  toolCallWindow?: ToolCallWindow;
13
- countedToolPartIDs?: string[];
13
+ countedToolPartIDs?: Set<string>;
14
14
  lastUpdate: Date;
15
15
  lastMessage?: string;
16
16
  lastMessageAt?: Date;