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 +69 -26
- package/dist/config/schema/background-task.d.ts +1 -2
- package/dist/config/schema/oh-my-opencode-config.d.ts +1 -2
- package/dist/features/background-agent/constants.d.ts +1 -2
- package/dist/features/background-agent/loop-detector.d.ts +1 -4
- package/dist/features/background-agent/manager.d.ts +1 -0
- package/dist/features/background-agent/session-status-classifier.d.ts +2 -0
- package/dist/features/background-agent/types.d.ts +4 -4
- package/dist/index.js +264 -202
- package/dist/oh-my-opencode.schema.json +1 -6
- package/package.json +12 -12
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
|
-
|
|
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.
|
|
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.
|
|
8977
|
-
"oh-my-opencode-darwin-x64": "3.12.
|
|
8978
|
-
"oh-my-opencode-darwin-x64-baseline": "3.12.
|
|
8979
|
-
"oh-my-opencode-linux-arm64": "3.12.
|
|
8980
|
-
"oh-my-opencode-linux-arm64-musl": "3.12.
|
|
8981
|
-
"oh-my-opencode-linux-x64": "3.12.
|
|
8982
|
-
"oh-my-opencode-linux-x64-baseline": "3.12.
|
|
8983
|
-
"oh-my-opencode-linux-x64-musl": "3.12.
|
|
8984
|
-
"oh-my-opencode-linux-x64-musl-baseline": "3.12.
|
|
8985
|
-
"oh-my-opencode-windows-x64": "3.12.
|
|
8986
|
-
"oh-my-opencode-windows-x64-baseline": "3.12.
|
|
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
|
-
|
|
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
|
-
|
|
10404
|
+
parts.push(" ");
|
|
10361
10405
|
lineStart = false;
|
|
10362
10406
|
}
|
|
10363
10407
|
if (ch === `
|
|
10364
10408
|
`) {
|
|
10365
|
-
|
|
10366
|
-
|
|
10409
|
+
parts.push(`
|
|
10410
|
+
`);
|
|
10367
10411
|
lineStart = true;
|
|
10368
10412
|
continue;
|
|
10369
10413
|
}
|
|
10370
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
24879
|
-
const chunks =
|
|
24921
|
+
buffer2 += value;
|
|
24922
|
+
const chunks = buffer2.split(`
|
|
24880
24923
|
|
|
24881
24924
|
`);
|
|
24882
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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;
|
|
@@ -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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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;
|