oh-my-opencode 4.1.1 → 4.1.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/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.ru.md +1 -1
- package/README.zh-cn.md +1 -1
- package/dist/cli/index.js +2261 -867
- package/dist/hooks/ralph-loop/iteration-continuation.d.ts +1 -0
- package/dist/hooks/ralph-loop/loop-state-controller.d.ts +3 -3
- package/dist/hooks/ralph-loop/pending-verification-handler.d.ts +2 -1
- package/dist/hooks/ralph-loop/ralph-loop-event-handler.d.ts +2 -2
- package/dist/hooks/ralph-loop/storage.d.ts +2 -2
- package/dist/hooks/ralph-loop/types.d.ts +4 -0
- package/dist/hooks/ralph-loop/verification-failure-handler.d.ts +2 -2
- package/dist/index.js +129 -27
- package/dist/tools/delegate-task/subagent-discovery.d.ts +1 -0
- package/package.json +23 -21
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RalphLoopOptions, RalphLoopState } from "./types";
|
|
1
|
+
import type { IterationCommitExpectation, RalphLoopOptions, RalphLoopState } from "./types";
|
|
2
2
|
export declare function createLoopStateController(options: {
|
|
3
3
|
directory: string;
|
|
4
4
|
stateDir: string | undefined;
|
|
@@ -14,9 +14,9 @@ export declare function createLoopStateController(options: {
|
|
|
14
14
|
cancelLoop(sessionID: string): boolean;
|
|
15
15
|
getState(): RalphLoopState | null;
|
|
16
16
|
clear(): boolean;
|
|
17
|
-
incrementIteration(): RalphLoopState | null;
|
|
17
|
+
incrementIteration(expected?: IterationCommitExpectation): RalphLoopState | null;
|
|
18
18
|
setSessionID(sessionID: string): RalphLoopState | null;
|
|
19
|
-
setMessageCountAtStart(sessionID: string, messageCountAtStart: number): RalphLoopState | null;
|
|
19
|
+
setMessageCountAtStart(sessionID: string, messageCountAtStart: number, expectedStartedAt?: string): RalphLoopState | null;
|
|
20
20
|
markVerificationPending(sessionID: string): RalphLoopState | null;
|
|
21
21
|
setVerificationSessionID(sessionID: string, verificationSessionID: string): RalphLoopState | null;
|
|
22
22
|
restartAfterFailedVerification(sessionID: string, messageCountAtStart?: number): RalphLoopState | null;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
2
|
import type { RalphLoopState } from "./types";
|
|
3
|
+
import type { IterationCommitExpectation } from "./types";
|
|
3
4
|
type LoopStateController = {
|
|
4
5
|
restartAfterFailedVerification: (sessionID: string, messageCountAtStart?: number) => RalphLoopState | null;
|
|
5
6
|
clearVerificationState: (sessionID: string, messageCountAtStart?: number) => RalphLoopState | null;
|
|
6
|
-
incrementIteration: () => RalphLoopState | null;
|
|
7
|
+
incrementIteration: (expected?: IterationCommitExpectation) => RalphLoopState | null;
|
|
7
8
|
clear: () => boolean;
|
|
8
9
|
setVerificationSessionID: (sessionID: string, verificationSessionID: string) => RalphLoopState | null;
|
|
9
10
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
-
import type { RalphLoopOptions, RalphLoopState } from "./types";
|
|
2
|
+
import type { IterationCommitExpectation, RalphLoopOptions, RalphLoopState } from "./types";
|
|
3
3
|
type LoopStateController = {
|
|
4
4
|
getState: () => RalphLoopState | null;
|
|
5
5
|
clear: () => boolean;
|
|
6
|
-
incrementIteration: () => RalphLoopState | null;
|
|
6
|
+
incrementIteration: (expected?: IterationCommitExpectation) => RalphLoopState | null;
|
|
7
7
|
setSessionID: (sessionID: string) => RalphLoopState | null;
|
|
8
8
|
markVerificationPending: (sessionID: string) => RalphLoopState | null;
|
|
9
9
|
setVerificationSessionID: (sessionID: string, verificationSessionID: string) => RalphLoopState | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { RalphLoopState } from "./types";
|
|
1
|
+
import type { IterationCommitExpectation, RalphLoopState } from "./types";
|
|
2
2
|
export declare function getStateFilePath(directory: string, customPath?: string): string;
|
|
3
3
|
export declare function readState(directory: string, customPath?: string): RalphLoopState | null;
|
|
4
4
|
export declare function writeState(directory: string, state: RalphLoopState, customPath?: string): boolean;
|
|
5
5
|
export declare function clearState(directory: string, customPath?: string): boolean;
|
|
6
|
-
export declare function incrementIteration(directory: string, customPath?: string): RalphLoopState | null;
|
|
6
|
+
export declare function incrementIteration(directory: string, customPath?: string, expected?: IterationCommitExpectation): RalphLoopState | null;
|
|
@@ -15,6 +15,10 @@ export interface RalphLoopState {
|
|
|
15
15
|
verification_pending?: boolean;
|
|
16
16
|
strategy?: "reset" | "continue";
|
|
17
17
|
}
|
|
18
|
+
export interface IterationCommitExpectation {
|
|
19
|
+
iteration: number;
|
|
20
|
+
sessionID: string;
|
|
21
|
+
}
|
|
18
22
|
export interface RalphLoopOptions {
|
|
19
23
|
config?: RalphLoopConfig;
|
|
20
24
|
getTranscriptPath?: (sessionId: string) => string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
-
import type { RalphLoopState } from "./types";
|
|
2
|
+
import type { IterationCommitExpectation, RalphLoopState } from "./types";
|
|
3
3
|
type LoopStateController = {
|
|
4
4
|
clearVerificationState: (sessionID: string, messageCountAtStart?: number) => RalphLoopState | null;
|
|
5
|
-
incrementIteration: () => RalphLoopState | null;
|
|
5
|
+
incrementIteration: (expected?: IterationCommitExpectation) => RalphLoopState | null;
|
|
6
6
|
clear: () => boolean;
|
|
7
7
|
};
|
|
8
8
|
export declare function handleFailedVerification(ctx: PluginInput, input: {
|
package/dist/index.js
CHANGED
|
@@ -58612,10 +58612,13 @@ function clearState(directory, customPath) {
|
|
|
58612
58612
|
return false;
|
|
58613
58613
|
}
|
|
58614
58614
|
}
|
|
58615
|
-
function incrementIteration(directory, customPath) {
|
|
58615
|
+
function incrementIteration(directory, customPath, expected) {
|
|
58616
58616
|
const state3 = readState(directory, customPath);
|
|
58617
58617
|
if (!state3)
|
|
58618
58618
|
return null;
|
|
58619
|
+
if (expected && (state3.iteration !== expected.iteration || state3.session_id !== expected.sessionID)) {
|
|
58620
|
+
return null;
|
|
58621
|
+
}
|
|
58619
58622
|
state3.iteration += 1;
|
|
58620
58623
|
if (writeState(directory, state3, customPath)) {
|
|
58621
58624
|
return state3;
|
|
@@ -74093,6 +74096,12 @@ async function runAggressiveTruncationStrategy(params) {
|
|
|
74093
74096
|
clearSessionState(params.autoCompactState, params.sessionID);
|
|
74094
74097
|
setTimeout(async () => {
|
|
74095
74098
|
try {
|
|
74099
|
+
if (await isSessionActive(params.client, params.sessionID)) {
|
|
74100
|
+
log("[auto-compact] skipped delayed auto prompt because session became active", {
|
|
74101
|
+
sessionID: params.sessionID
|
|
74102
|
+
});
|
|
74103
|
+
return;
|
|
74104
|
+
}
|
|
74096
74105
|
const sdkMessage = await findNearestMessageWithFieldsFromSDK(params.client, params.sessionID);
|
|
74097
74106
|
const previousMessage = sdkMessage ?? (() => {
|
|
74098
74107
|
const messageDir = getMessageDir(params.sessionID);
|
|
@@ -74114,7 +74123,12 @@ async function runAggressiveTruncationStrategy(params) {
|
|
|
74114
74123
|
},
|
|
74115
74124
|
query: { directory: params.directory }
|
|
74116
74125
|
});
|
|
74117
|
-
} catch {
|
|
74126
|
+
} catch (error) {
|
|
74127
|
+
log("[auto-compact] delayed auto prompt failed", {
|
|
74128
|
+
sessionID: params.sessionID,
|
|
74129
|
+
error: String(error)
|
|
74130
|
+
});
|
|
74131
|
+
}
|
|
74118
74132
|
}, 500);
|
|
74119
74133
|
return { handled: true, nextTruncateAttempt };
|
|
74120
74134
|
}
|
|
@@ -75462,6 +75476,12 @@ function getNextReachableFallback(sessionID, state3) {
|
|
|
75462
75476
|
}
|
|
75463
75477
|
|
|
75464
75478
|
// src/hooks/model-fallback/fallback-state-controller.ts
|
|
75479
|
+
function canonicalizeModelIDForDuplicateCheck(modelID) {
|
|
75480
|
+
return modelID.toLowerCase().replace(/\./g, "-");
|
|
75481
|
+
}
|
|
75482
|
+
function isSameFailedModel(state3, providerID, modelID) {
|
|
75483
|
+
return state3.providerID.toLowerCase() === providerID.toLowerCase() && canonicalizeModelIDForDuplicateCheck(state3.modelID) === canonicalizeModelIDForDuplicateCheck(modelID);
|
|
75484
|
+
}
|
|
75465
75485
|
function createModelFallbackStateController(input) {
|
|
75466
75486
|
const { pendingModelFallbacks, lastToastKey, sessionFallbackChains } = input;
|
|
75467
75487
|
function setSessionFallbackChain(sessionID, fallbackChain) {
|
|
@@ -75500,6 +75520,10 @@ function createModelFallbackStateController(input) {
|
|
|
75500
75520
|
log(`[model-fallback] Pending fallback already armed for session: ${sessionID}`);
|
|
75501
75521
|
return false;
|
|
75502
75522
|
}
|
|
75523
|
+
if (existing.attemptCount > 0 && isSameFailedModel(existing, currentProviderID, currentModelID)) {
|
|
75524
|
+
log(`[model-fallback] Ignoring duplicate fallback arm for already handled model in session: ${sessionID}`);
|
|
75525
|
+
return false;
|
|
75526
|
+
}
|
|
75503
75527
|
existing.providerID = currentProviderID;
|
|
75504
75528
|
existing.modelID = currentModelID;
|
|
75505
75529
|
existing.pending = true;
|
|
@@ -80225,6 +80249,31 @@ function detectBannedCommand(command) {
|
|
|
80225
80249
|
}
|
|
80226
80250
|
return;
|
|
80227
80251
|
}
|
|
80252
|
+
function detectWindowsShellType(shellPath) {
|
|
80253
|
+
if (!shellPath) {
|
|
80254
|
+
return;
|
|
80255
|
+
}
|
|
80256
|
+
const shellName = shellPath.replace(/\\/g, "/").split("/").pop()?.toLowerCase();
|
|
80257
|
+
if (shellName === "cmd" || shellName === "cmd.exe") {
|
|
80258
|
+
return "cmd";
|
|
80259
|
+
}
|
|
80260
|
+
if (shellName === "powershell" || shellName === "powershell.exe" || shellName === "pwsh" || shellName === "pwsh.exe") {
|
|
80261
|
+
return "powershell";
|
|
80262
|
+
}
|
|
80263
|
+
return;
|
|
80264
|
+
}
|
|
80265
|
+
function detectCommandShellType() {
|
|
80266
|
+
if (process.platform === "win32" && process.env.SHELL) {
|
|
80267
|
+
const shellType = detectWindowsShellType(process.env.SHELL);
|
|
80268
|
+
if (shellType) {
|
|
80269
|
+
return shellType;
|
|
80270
|
+
}
|
|
80271
|
+
}
|
|
80272
|
+
if (process.platform === "win32" && !process.env.SHELL && !process.env.MSYSTEM) {
|
|
80273
|
+
return detectWindowsShellType(process.env.ComSpec) ?? "cmd";
|
|
80274
|
+
}
|
|
80275
|
+
return detectShellType();
|
|
80276
|
+
}
|
|
80228
80277
|
function createNonInteractiveEnvHook(_ctx) {
|
|
80229
80278
|
return {
|
|
80230
80279
|
"tool.execute.before": async (input, output) => {
|
|
@@ -80243,7 +80292,7 @@ function createNonInteractiveEnvHook(_ctx) {
|
|
|
80243
80292
|
if (!isGitCommand) {
|
|
80244
80293
|
return;
|
|
80245
80294
|
}
|
|
80246
|
-
const shellType =
|
|
80295
|
+
const shellType = detectCommandShellType();
|
|
80247
80296
|
const envPrefix = buildEnvPrefix(NON_INTERACTIVE_ENV, shellType);
|
|
80248
80297
|
if (command.trim().startsWith(envPrefix.trim())) {
|
|
80249
80298
|
return;
|
|
@@ -81165,8 +81214,8 @@ function createLoopStateController(options) {
|
|
|
81165
81214
|
clear() {
|
|
81166
81215
|
return clearState(directory, stateDir);
|
|
81167
81216
|
},
|
|
81168
|
-
incrementIteration() {
|
|
81169
|
-
return incrementIteration(directory, stateDir);
|
|
81217
|
+
incrementIteration(expected) {
|
|
81218
|
+
return incrementIteration(directory, stateDir, expected);
|
|
81170
81219
|
},
|
|
81171
81220
|
setSessionID(sessionID) {
|
|
81172
81221
|
const state3 = readState(directory, stateDir);
|
|
@@ -81179,11 +81228,14 @@ function createLoopStateController(options) {
|
|
|
81179
81228
|
}
|
|
81180
81229
|
return state3;
|
|
81181
81230
|
},
|
|
81182
|
-
setMessageCountAtStart(sessionID, messageCountAtStart) {
|
|
81231
|
+
setMessageCountAtStart(sessionID, messageCountAtStart, expectedStartedAt) {
|
|
81183
81232
|
const state3 = readState(directory, stateDir);
|
|
81184
81233
|
if (!state3 || state3.session_id !== sessionID) {
|
|
81185
81234
|
return null;
|
|
81186
81235
|
}
|
|
81236
|
+
if (state3.iteration !== 1 || state3.verification_pending || state3.message_count_at_start !== undefined || expectedStartedAt !== undefined && state3.started_at !== expectedStartedAt) {
|
|
81237
|
+
return null;
|
|
81238
|
+
}
|
|
81187
81239
|
state3.message_count_at_start = messageCountAtStart;
|
|
81188
81240
|
if (!writeState(directory, state3, stateDir)) {
|
|
81189
81241
|
return null;
|
|
@@ -81933,9 +81985,9 @@ async function continueIteration(ctx, state3, options) {
|
|
|
81933
81985
|
previousSessionID: options.previousSessionID,
|
|
81934
81986
|
newSessionID
|
|
81935
81987
|
});
|
|
81936
|
-
return { status: "
|
|
81988
|
+
return { status: "dispatch_rejected", error: "state commit failed after reset dispatch" };
|
|
81937
81989
|
}
|
|
81938
|
-
return { status: "dispatched" };
|
|
81990
|
+
return { status: "dispatched", sessionID: newSessionID };
|
|
81939
81991
|
}
|
|
81940
81992
|
try {
|
|
81941
81993
|
const promptResult = await injectContinuationPrompt(ctx, {
|
|
@@ -81950,7 +82002,7 @@ async function continueIteration(ctx, state3, options) {
|
|
|
81950
82002
|
} catch (error) {
|
|
81951
82003
|
return { status: "dispatch_rejected", error };
|
|
81952
82004
|
}
|
|
81953
|
-
return { status: "dispatched" };
|
|
82005
|
+
return { status: "dispatched", sessionID: options.previousSessionID };
|
|
81954
82006
|
}
|
|
81955
82007
|
|
|
81956
82008
|
// src/hooks/ralph-loop/pending-verification-handler.ts
|
|
@@ -82448,11 +82500,21 @@ function createRalphLoopEventHandler(ctx, options) {
|
|
|
82448
82500
|
})) {
|
|
82449
82501
|
return;
|
|
82450
82502
|
}
|
|
82451
|
-
const committed = options.loopState.incrementIteration(
|
|
82503
|
+
const committed = options.loopState.incrementIteration({
|
|
82504
|
+
iteration: stateBeforeCommit.iteration,
|
|
82505
|
+
sessionID: result.sessionID
|
|
82506
|
+
});
|
|
82452
82507
|
if (committed) {
|
|
82453
82508
|
showIterationToast(ctx, committed);
|
|
82454
82509
|
} else {
|
|
82455
82510
|
log(`[${HOOK_NAME3}] Dispatch succeeded but iteration commit failed`, { sessionID });
|
|
82511
|
+
options.loopState.clear();
|
|
82512
|
+
showToastBestEffort3(ctx, {
|
|
82513
|
+
title: "Ralph Loop Failed",
|
|
82514
|
+
message: "Dispatch succeeded but iteration commit failed",
|
|
82515
|
+
variant: "warning",
|
|
82516
|
+
duration: 5000
|
|
82517
|
+
});
|
|
82456
82518
|
}
|
|
82457
82519
|
return;
|
|
82458
82520
|
}
|
|
@@ -82580,12 +82642,22 @@ function createRalphLoopEventHandler(ctx, options) {
|
|
|
82580
82642
|
})) {
|
|
82581
82643
|
return;
|
|
82582
82644
|
}
|
|
82583
|
-
const committed = options.loopState.incrementIteration(
|
|
82645
|
+
const committed = options.loopState.incrementIteration({
|
|
82646
|
+
iteration: stateBeforeCommit.iteration,
|
|
82647
|
+
sessionID: result.sessionID
|
|
82648
|
+
});
|
|
82584
82649
|
if (committed) {
|
|
82585
82650
|
showIterationToast(ctx, committed);
|
|
82586
82651
|
runtimeErrorRetriedSessions.set(sessionID, committed.iteration);
|
|
82587
82652
|
} else {
|
|
82588
82653
|
log(`[${HOOK_NAME3}] Dispatch succeeded but iteration commit failed after runtime error`, { sessionID });
|
|
82654
|
+
options.loopState.clear();
|
|
82655
|
+
showToastBestEffort3(ctx, {
|
|
82656
|
+
title: "Ralph Loop Failed",
|
|
82657
|
+
message: "Dispatch succeeded but iteration commit failed",
|
|
82658
|
+
variant: "warning",
|
|
82659
|
+
duration: 5000
|
|
82660
|
+
});
|
|
82589
82661
|
}
|
|
82590
82662
|
return;
|
|
82591
82663
|
}
|
|
@@ -82646,12 +82718,14 @@ function createRalphLoopHook(ctx, options) {
|
|
|
82646
82718
|
if (!startSuccess || typeof loopOptions?.messageCountAtStart === "number") {
|
|
82647
82719
|
return startSuccess;
|
|
82648
82720
|
}
|
|
82721
|
+
const startedState = loopState.getState();
|
|
82722
|
+
const expectedStartedAt = startedState?.session_id === sessionID ? startedState.started_at : undefined;
|
|
82649
82723
|
ctx.client.session.messages({
|
|
82650
82724
|
path: { id: sessionID },
|
|
82651
82725
|
query: { directory: ctx.directory }
|
|
82652
82726
|
}).then((messagesResponse) => {
|
|
82653
82727
|
const messageCountAtStart = getMessageCountFromResponse2(messagesResponse);
|
|
82654
|
-
loopState.setMessageCountAtStart(sessionID, messageCountAtStart);
|
|
82728
|
+
loopState.setMessageCountAtStart(sessionID, messageCountAtStart, expectedStartedAt);
|
|
82655
82729
|
}).catch(() => {});
|
|
82656
82730
|
return startSuccess;
|
|
82657
82731
|
},
|
|
@@ -93550,7 +93624,7 @@ function createRecoveryLogic(ctx, getTailState) {
|
|
|
93550
93624
|
agent: launchAgent ?? expectedPromptConfig.agent,
|
|
93551
93625
|
...model ? { model } : {},
|
|
93552
93626
|
...tools ? { tools } : {},
|
|
93553
|
-
parts: [
|
|
93627
|
+
parts: [createInternalAgentContinuationTextPart(AGENT_RECOVERY_PROMPT)]
|
|
93554
93628
|
},
|
|
93555
93629
|
query: { directory: ctx.directory }
|
|
93556
93630
|
});
|
|
@@ -95371,6 +95445,18 @@ function createSessionStatusHandler(deps, helpers, sessionStatusRetryKeys) {
|
|
|
95371
95445
|
|
|
95372
95446
|
// src/hooks/runtime-fallback/event-handler.ts
|
|
95373
95447
|
init_event_session_id();
|
|
95448
|
+
function resolveEventModel(props) {
|
|
95449
|
+
const model = props?.model;
|
|
95450
|
+
if (typeof model === "string") {
|
|
95451
|
+
return model;
|
|
95452
|
+
}
|
|
95453
|
+
const providerID = props?.providerID;
|
|
95454
|
+
const modelID = props?.modelID;
|
|
95455
|
+
if (typeof providerID === "string" && typeof modelID === "string") {
|
|
95456
|
+
return `${providerID}/${modelID}`;
|
|
95457
|
+
}
|
|
95458
|
+
return;
|
|
95459
|
+
}
|
|
95374
95460
|
function createEventHandler(deps, helpers) {
|
|
95375
95461
|
const { config, pluginConfig, sessionStates, sessionLastAccess, sessionRetryInFlight, sessionAwaitingFallbackResult, sessionFallbackTimeouts, sessionStatusRetryKeys } = deps;
|
|
95376
95462
|
const sessionStatusHandler = createSessionStatusHandler(deps, helpers, sessionStatusRetryKeys);
|
|
@@ -95475,6 +95561,18 @@ function createEventHandler(deps, helpers) {
|
|
|
95475
95561
|
});
|
|
95476
95562
|
return;
|
|
95477
95563
|
}
|
|
95564
|
+
if (sessionAwaitingFallbackResult.has(sessionID)) {
|
|
95565
|
+
const pendingFallbackModel = sessionStates.get(sessionID)?.pendingFallbackModel;
|
|
95566
|
+
const eventModel = resolveEventModel(props);
|
|
95567
|
+
if (!pendingFallbackModel || eventModel !== pendingFallbackModel) {
|
|
95568
|
+
log(`[${HOOK_NAME11}] session.error skipped - awaiting fallback result`, {
|
|
95569
|
+
sessionID,
|
|
95570
|
+
pendingFallbackModel,
|
|
95571
|
+
eventModel
|
|
95572
|
+
});
|
|
95573
|
+
return;
|
|
95574
|
+
}
|
|
95575
|
+
}
|
|
95478
95576
|
sessionAwaitingFallbackResult.delete(sessionID);
|
|
95479
95577
|
helpers.clearSessionFallbackTimeout(sessionID);
|
|
95480
95578
|
log(`[${HOOK_NAME11}] session.error received`, {
|
|
@@ -103868,11 +103966,12 @@ function mergeWithClaudeCodeAgents(serverAgents, directory) {
|
|
|
103868
103966
|
const toAgentInfoList = (record) => Object.entries(record).map(([name, config2]) => ({
|
|
103869
103967
|
name,
|
|
103870
103968
|
mode: config2.mode,
|
|
103969
|
+
hidden: config2.hidden,
|
|
103871
103970
|
model: config2.model
|
|
103872
103971
|
}));
|
|
103873
103972
|
const mergedAgentMap = new Map;
|
|
103874
103973
|
const addIfAbsent = (agent) => {
|
|
103875
|
-
const key = agent.name.toLowerCase();
|
|
103974
|
+
const key = stripAgentListSortPrefix(agent.name).trim().toLowerCase();
|
|
103876
103975
|
if (!mergedAgentMap.has(key)) {
|
|
103877
103976
|
mergedAgentMap.set(key, agent);
|
|
103878
103977
|
}
|
|
@@ -103905,10 +104004,10 @@ function findPrimaryAgentMatch(agents, requestedAgentName) {
|
|
|
103905
104004
|
return agents.find((agent) => agent.mode === "primary" && matchesRequestedAgent(agent, requestedAgentName));
|
|
103906
104005
|
}
|
|
103907
104006
|
function findCallableAgentMatch(agents, requestedAgentName) {
|
|
103908
|
-
return agents.find((agent) => isTaskCallableAgentMode(agent.mode) && matchesRequestedAgent(agent, requestedAgentName));
|
|
104007
|
+
return agents.find((agent) => isTaskCallableAgentMode(agent.mode) && agent.hidden !== true && matchesRequestedAgent(agent, requestedAgentName));
|
|
103909
104008
|
}
|
|
103910
104009
|
function listCallableAgentNames(agents) {
|
|
103911
|
-
return agents.filter((agent) => isTaskCallableAgentMode(agent.mode)).map((agent) => stripAgentListSortPrefix(agent.name)).sort().join(", ");
|
|
104010
|
+
return agents.filter((agent) => isTaskCallableAgentMode(agent.mode) && agent.hidden !== true).map((agent) => stripAgentListSortPrefix(agent.name)).sort().join(", ");
|
|
103912
104011
|
}
|
|
103913
104012
|
|
|
103914
104013
|
// src/tools/call-omo-agent/background-executor.ts
|
|
@@ -113776,13 +113875,14 @@ ${originalText}`;
|
|
|
113776
113875
|
...variant !== undefined ? { variant } : {},
|
|
113777
113876
|
...resolvedTools ? { tools: resolvedTools } : {}
|
|
113778
113877
|
};
|
|
113779
|
-
const
|
|
113780
|
-
if (
|
|
113781
|
-
this.queuePendingParentWake(task.parentSessionId, notification2, parentPromptContext);
|
|
113878
|
+
const shouldDeferNotification = await this.isSessionActive(task.parentSessionId);
|
|
113879
|
+
if (shouldDeferNotification) {
|
|
113880
|
+
this.queuePendingParentWake(task.parentSessionId, notification2, parentPromptContext, shouldReply);
|
|
113782
113881
|
log("[background-agent] Deferred notification until parent session is idle:", {
|
|
113783
113882
|
taskId: task.id,
|
|
113784
113883
|
allComplete,
|
|
113785
|
-
isTaskFailure
|
|
113884
|
+
isTaskFailure,
|
|
113885
|
+
shouldReply
|
|
113786
113886
|
});
|
|
113787
113887
|
} else {
|
|
113788
113888
|
try {
|
|
@@ -113825,15 +113925,17 @@ ${originalText}`;
|
|
|
113825
113925
|
async isSessionActive(sessionID) {
|
|
113826
113926
|
return isSessionActive(this.client, sessionID);
|
|
113827
113927
|
}
|
|
113828
|
-
queuePendingParentWake(sessionID, notification2, promptContext) {
|
|
113928
|
+
queuePendingParentWake(sessionID, notification2, promptContext, shouldReply) {
|
|
113829
113929
|
const pendingWake = this.pendingParentWakes.get(sessionID);
|
|
113830
113930
|
if (pendingWake) {
|
|
113831
113931
|
pendingWake.notifications.push(notification2);
|
|
113832
113932
|
pendingWake.promptContext = promptContext;
|
|
113933
|
+
pendingWake.shouldReply = pendingWake.shouldReply || shouldReply;
|
|
113833
113934
|
} else {
|
|
113834
113935
|
this.pendingParentWakes.set(sessionID, {
|
|
113835
113936
|
promptContext,
|
|
113836
|
-
notifications: [notification2]
|
|
113937
|
+
notifications: [notification2],
|
|
113938
|
+
shouldReply
|
|
113837
113939
|
});
|
|
113838
113940
|
}
|
|
113839
113941
|
this.schedulePendingParentWakeFlush(sessionID);
|
|
@@ -113863,7 +113965,7 @@ ${originalText}`;
|
|
|
113863
113965
|
await promptAsyncInDirectory(this.client, {
|
|
113864
113966
|
path: { id: sessionID },
|
|
113865
113967
|
body: {
|
|
113866
|
-
noReply:
|
|
113968
|
+
noReply: !pendingWake.shouldReply,
|
|
113867
113969
|
...pendingWake.promptContext,
|
|
113868
113970
|
parts: [createInternalAgentTextPart(notificationContent)]
|
|
113869
113971
|
}
|
|
@@ -138840,6 +138942,10 @@ function createEventHandler2(args) {
|
|
|
138840
138942
|
const lastHandledRetryStatusKey = new Map;
|
|
138841
138943
|
const lastKnownModelBySession = new Map;
|
|
138842
138944
|
const resolveFallbackProviderID = (sessionID, providerHint) => {
|
|
138945
|
+
const normalizedProviderHint = providerHint?.trim();
|
|
138946
|
+
if (normalizedProviderHint) {
|
|
138947
|
+
return normalizedProviderHint;
|
|
138948
|
+
}
|
|
138843
138949
|
const sessionModel = getSessionModel(sessionID);
|
|
138844
138950
|
if (sessionModel?.providerID) {
|
|
138845
138951
|
return sessionModel.providerID;
|
|
@@ -138848,10 +138954,6 @@ function createEventHandler2(args) {
|
|
|
138848
138954
|
if (lastKnownModel?.providerID) {
|
|
138849
138955
|
return lastKnownModel.providerID;
|
|
138850
138956
|
}
|
|
138851
|
-
const normalizedProviderHint = providerHint?.trim();
|
|
138852
|
-
if (normalizedProviderHint) {
|
|
138853
|
-
return normalizedProviderHint;
|
|
138854
|
-
}
|
|
138855
138957
|
const connectedProvider = readConnectedProvidersCache()?.[0];
|
|
138856
138958
|
if (connectedProvider) {
|
|
138857
138959
|
return connectedProvider;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oh-my-opencode",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.2",
|
|
4
4
|
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"postinstall": "node postinstall.mjs",
|
|
34
34
|
"prepublishOnly": "bun run clean && bun run build",
|
|
35
35
|
"test:model-capabilities": "bun test src/shared/model-capability-aliases.test.ts src/shared/model-capability-guardrails.test.ts src/shared/model-capabilities.test.ts src/cli/doctor/checks/model-resolution.test.ts --bail",
|
|
36
|
-
"typecheck": "
|
|
36
|
+
"typecheck": "tsgo --noEmit",
|
|
37
|
+
"typecheck:script": "tsgo --noEmit -p script/tsconfig.json",
|
|
37
38
|
"test": "bun run script/run-ci-tests.ts"
|
|
38
39
|
},
|
|
39
40
|
"keywords": [
|
|
@@ -63,35 +64,36 @@
|
|
|
63
64
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
64
65
|
"@opencode-ai/plugin": "^1.4.0",
|
|
65
66
|
"@opencode-ai/sdk": "^1.4.0",
|
|
66
|
-
"commander": "^14.0.
|
|
67
|
-
"detect-libc": "^2.
|
|
68
|
-
"diff": "^8.0.
|
|
67
|
+
"commander": "^14.0.3",
|
|
68
|
+
"detect-libc": "^2.1.2",
|
|
69
|
+
"diff": "^8.0.4",
|
|
69
70
|
"js-yaml": "^4.1.1",
|
|
70
71
|
"jsonc-parser": "^3.3.1",
|
|
71
72
|
"picocolors": "^1.1.1",
|
|
72
73
|
"picomatch": "^4.0.4",
|
|
73
|
-
"posthog-node": "^5.
|
|
74
|
-
"vscode-jsonrpc": "^8.2.
|
|
74
|
+
"posthog-node": "^5.34.1",
|
|
75
|
+
"vscode-jsonrpc": "^8.2.1"
|
|
75
76
|
},
|
|
76
77
|
"devDependencies": {
|
|
78
|
+
"@typescript/native-preview": "7.0.0-dev.20260513.1",
|
|
77
79
|
"@types/js-yaml": "^4.0.9",
|
|
78
80
|
"@types/picomatch": "^3.0.2",
|
|
79
|
-
"bun-types": "1.3.
|
|
80
|
-
"typescript": "^5.
|
|
81
|
-
"zod": "^4.3
|
|
81
|
+
"bun-types": "1.3.12",
|
|
82
|
+
"typescript": "^5.9.3",
|
|
83
|
+
"zod": "^4.4.3"
|
|
82
84
|
},
|
|
83
85
|
"optionalDependencies": {
|
|
84
|
-
"oh-my-opencode-darwin-arm64": "4.1.
|
|
85
|
-
"oh-my-opencode-darwin-x64": "4.1.
|
|
86
|
-
"oh-my-opencode-darwin-x64-baseline": "4.1.
|
|
87
|
-
"oh-my-opencode-linux-arm64": "4.1.
|
|
88
|
-
"oh-my-opencode-linux-arm64-musl": "4.1.
|
|
89
|
-
"oh-my-opencode-linux-x64": "4.1.
|
|
90
|
-
"oh-my-opencode-linux-x64-baseline": "4.1.
|
|
91
|
-
"oh-my-opencode-linux-x64-musl": "4.1.
|
|
92
|
-
"oh-my-opencode-linux-x64-musl-baseline": "4.1.
|
|
93
|
-
"oh-my-opencode-windows-x64": "4.1.
|
|
94
|
-
"oh-my-opencode-windows-x64-baseline": "4.1.
|
|
86
|
+
"oh-my-opencode-darwin-arm64": "4.1.2",
|
|
87
|
+
"oh-my-opencode-darwin-x64": "4.1.2",
|
|
88
|
+
"oh-my-opencode-darwin-x64-baseline": "4.1.2",
|
|
89
|
+
"oh-my-opencode-linux-arm64": "4.1.2",
|
|
90
|
+
"oh-my-opencode-linux-arm64-musl": "4.1.2",
|
|
91
|
+
"oh-my-opencode-linux-x64": "4.1.2",
|
|
92
|
+
"oh-my-opencode-linux-x64-baseline": "4.1.2",
|
|
93
|
+
"oh-my-opencode-linux-x64-musl": "4.1.2",
|
|
94
|
+
"oh-my-opencode-linux-x64-musl-baseline": "4.1.2",
|
|
95
|
+
"oh-my-opencode-windows-x64": "4.1.2",
|
|
96
|
+
"oh-my-opencode-windows-x64-baseline": "4.1.2"
|
|
95
97
|
},
|
|
96
98
|
"overrides": {
|
|
97
99
|
"hono": "^4.12.18",
|