@bohuyeshan/openagent-labforge-core 3.11.3 → 3.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/README.zh-cn.md +4 -4
- package/dist/cli/index.js +1 -1
- package/dist/index.js +74 -12
- package/dist/plugin/ultrawork-model-override.d.ts +1 -1
- package/dist/shared/session-model-state.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -272,10 +272,10 @@ Keep reasoning depth in the OpenCode UI instead of hardcoding separate `low` / `
|
|
|
272
272
|
|
|
273
273
|
Copy and paste this prompt to your LLM agent (Claude Code, AmpCode, Cursor, etc.):
|
|
274
274
|
|
|
275
|
-
```
|
|
276
|
-
Install and configure @bohuyeshan/openagent-labforge-core by following the instructions here:
|
|
277
|
-
https://raw.githubusercontent.com/code-yeongyu/openagent-labforge/refs/heads/dev/docs/guide/installation.md
|
|
278
|
-
```
|
|
275
|
+
```
|
|
276
|
+
Install and configure @bohuyeshan/openagent-labforge-core by following the instructions here:
|
|
277
|
+
https://raw.githubusercontent.com/code-yeongyu/openagent-labforge/refs/heads/dev/docs/guide/installation.md
|
|
278
|
+
```
|
|
279
279
|
|
|
280
280
|
Or read the [Installation Guide](docs/guide/installation.md), but seriously, let an agent do it. Humans fat-finger configs.
|
|
281
281
|
|
package/README.zh-cn.md
CHANGED
|
@@ -273,10 +273,10 @@ npm install --prefix ~/.config/opencode /absolute/path/to/openagent-labforge-cor
|
|
|
273
273
|
|
|
274
274
|
复制并粘贴以下提示词到你的 LLM Agent (Claude Code, AmpCode, Cursor 等):
|
|
275
275
|
|
|
276
|
-
```
|
|
277
|
-
Install and configure @bohuyeshan/openagent-labforge-core by following the instructions here:
|
|
278
|
-
https://raw.githubusercontent.com/code-yeongyu/openagent-labforge/refs/heads/dev/docs/guide/installation.md
|
|
279
|
-
```
|
|
276
|
+
```
|
|
277
|
+
Install and configure @bohuyeshan/openagent-labforge-core by following the instructions here:
|
|
278
|
+
https://raw.githubusercontent.com/code-yeongyu/openagent-labforge/refs/heads/dev/docs/guide/installation.md
|
|
279
|
+
```
|
|
280
280
|
|
|
281
281
|
或者你可以直接去读 [安装指南](docs/guide/installation.md),但说真的,让 Agent 去干吧。人类配环境总是容易敲错字母。
|
|
282
282
|
|
package/dist/cli/index.js
CHANGED
|
@@ -9195,7 +9195,7 @@ var {
|
|
|
9195
9195
|
// package.json
|
|
9196
9196
|
var package_default = {
|
|
9197
9197
|
name: "@bohuyeshan/openagent-labforge-core",
|
|
9198
|
-
version: "3.11.
|
|
9198
|
+
version: "3.11.4",
|
|
9199
9199
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
9200
9200
|
main: "dist/index.js",
|
|
9201
9201
|
types: "dist/index.d.ts",
|
package/dist/index.js
CHANGED
|
@@ -20225,9 +20225,32 @@ function hasUnansweredQuestion(messages) {
|
|
|
20225
20225
|
/\u662F\u5426\u8981/u,
|
|
20226
20226
|
/\u4F60\u5E0C\u671B/u,
|
|
20227
20227
|
/\u4F60\u60F3\u8981/u,
|
|
20228
|
+
/\u4F60\u89C9\u5F97/u,
|
|
20229
|
+
/\u4F60\u600E\u4E48\u770B/u,
|
|
20230
|
+
/\u8BF7\u7ED9(?:\u6211)?\u610F\u89C1/u,
|
|
20231
|
+
/\u8BF7\u53CD\u9988/u,
|
|
20232
|
+
/\u6D4B\u8BD5\u540E(?:\u544A\u8BC9\u6211|\u53CD\u9988)/u,
|
|
20233
|
+
/\u8DD1\u5B8C\u6D4B\u8BD5(?:\u544A\u8BC9\u6211|\u53CD\u9988)/u,
|
|
20234
|
+
/\u786E\u8BA4\u540E(?:\u544A\u8BC9\u6211|\u56DE\u590D\u6211|\u6211\u518D\u7EE7\u7EED)/u,
|
|
20235
|
+
/\u4F60\u6765\u51B3\u5B9A/u,
|
|
20236
|
+
/\u4F60\u51B3\u5B9A/u,
|
|
20237
|
+
/\u8BF7(?:\u9009\u62E9|\u9009\u4E00\u4E2A)/u,
|
|
20228
20238
|
/\u5B8C\u6210\u540E\u56DE\u6211/u,
|
|
20229
20239
|
/\u91CD\u542F\u540E\u544A\u8BC9\u6211/u,
|
|
20230
20240
|
/\u56DE\u6211\u4E00\u53E5/u,
|
|
20241
|
+
/\u9700\u8981\u4F60\u786E\u8BA4/u,
|
|
20242
|
+
/\u7B49\u5F85(?:\u4F60\u7684|\u7528\u6237)(?:\u786E\u8BA4|\u53CD\u9988|\u51B3\u5B9A|\u56DE\u590D|\u610F\u89C1)/u,
|
|
20243
|
+
/what do you think/iu,
|
|
20244
|
+
/any preference/iu,
|
|
20245
|
+
/your (?:feedback|input|decision|opinion)/iu,
|
|
20246
|
+
/after you (?:test|review)/iu,
|
|
20247
|
+
/once you (?:test|review)/iu,
|
|
20248
|
+
/please review/iu,
|
|
20249
|
+
/review and confirm/iu,
|
|
20250
|
+
/should i proceed/iu,
|
|
20251
|
+
/would you like me to continue/iu,
|
|
20252
|
+
/do you want me to continue/iu,
|
|
20253
|
+
/let me know when/iu,
|
|
20231
20254
|
/which (one|option|path|approach)/iu,
|
|
20232
20255
|
/would you like/iu,
|
|
20233
20256
|
/please provide/iu,
|
|
@@ -20249,7 +20272,7 @@ function hasUnansweredQuestion(messages) {
|
|
|
20249
20272
|
`);
|
|
20250
20273
|
if (combinedText.length > 0) {
|
|
20251
20274
|
const normalized = combinedText.trim();
|
|
20252
|
-
const looksLikeQuestion = /[?\uFF1F]
|
|
20275
|
+
const looksLikeQuestion = /[?\uFF1F]/.test(normalized) || waitPatterns.some((pattern) => pattern.test(normalized));
|
|
20253
20276
|
if (looksLikeQuestion) {
|
|
20254
20277
|
log(`[${HOOK_NAME}] Detected textual prompt awaiting user response`);
|
|
20255
20278
|
return true;
|
|
@@ -52474,6 +52497,7 @@ init_logger();
|
|
|
52474
52497
|
var sessionModels = new Map;
|
|
52475
52498
|
var sessionModelLocks = new Map;
|
|
52476
52499
|
var sessionForcedModels = new Map;
|
|
52500
|
+
var sessionAutoModelRouting = new Map;
|
|
52477
52501
|
function setSessionModel(sessionID, model) {
|
|
52478
52502
|
sessionModels.set(sessionID, model);
|
|
52479
52503
|
}
|
|
@@ -52484,6 +52508,7 @@ function clearSessionModel(sessionID) {
|
|
|
52484
52508
|
sessionModels.delete(sessionID);
|
|
52485
52509
|
sessionModelLocks.delete(sessionID);
|
|
52486
52510
|
sessionForcedModels.delete(sessionID);
|
|
52511
|
+
sessionAutoModelRouting.delete(sessionID);
|
|
52487
52512
|
}
|
|
52488
52513
|
function setSessionModelLock(sessionID, model) {
|
|
52489
52514
|
sessionModelLocks.set(sessionID, model);
|
|
@@ -52503,6 +52528,12 @@ function getSessionForcedModel(sessionID) {
|
|
|
52503
52528
|
function clearSessionForcedModel(sessionID) {
|
|
52504
52529
|
sessionForcedModels.delete(sessionID);
|
|
52505
52530
|
}
|
|
52531
|
+
function setSessionAutoModelRouting(sessionID, enabled) {
|
|
52532
|
+
sessionAutoModelRouting.set(sessionID, enabled);
|
|
52533
|
+
}
|
|
52534
|
+
function isSessionAutoModelRoutingEnabled(sessionID) {
|
|
52535
|
+
return sessionAutoModelRouting.get(sessionID) === true;
|
|
52536
|
+
}
|
|
52506
52537
|
|
|
52507
52538
|
// src/hooks/compaction-context-injector/session-id.ts
|
|
52508
52539
|
function isCompactionAgent(agent) {
|
|
@@ -54181,6 +54212,8 @@ function createSessionStatusHandler(deps, helpers, sessionStatusRetryKeys) {
|
|
|
54181
54212
|
const model = props?.model;
|
|
54182
54213
|
if (!sessionID || status?.type !== "retry")
|
|
54183
54214
|
return;
|
|
54215
|
+
if (!isSessionAutoModelRoutingEnabled(sessionID))
|
|
54216
|
+
return;
|
|
54184
54217
|
const retryMessage = typeof status.message === "string" ? status.message : "";
|
|
54185
54218
|
const retrySignal = extractAutoRetrySignal({ status: retryMessage, message: retryMessage });
|
|
54186
54219
|
if (!retrySignal)
|
|
@@ -54316,6 +54349,10 @@ function createEventHandler(deps, helpers) {
|
|
|
54316
54349
|
log(`[${HOOK_NAME12}] session.error without sessionID, skipping`);
|
|
54317
54350
|
return;
|
|
54318
54351
|
}
|
|
54352
|
+
if (!isSessionAutoModelRoutingEnabled(sessionID)) {
|
|
54353
|
+
log(`[${HOOK_NAME12}] session.error fallback skipped - auto model routing disabled`, { sessionID });
|
|
54354
|
+
return;
|
|
54355
|
+
}
|
|
54319
54356
|
const resolvedAgent = await helpers.resolveAgentForSessionFromContext(sessionID, agent);
|
|
54320
54357
|
if (sessionRetryInFlight.has(sessionID)) {
|
|
54321
54358
|
log(`[${HOOK_NAME12}] session.error skipped \u2014 retry in flight`, {
|
|
@@ -54516,6 +54553,9 @@ function createMessageUpdateHandler(deps, helpers) {
|
|
|
54516
54553
|
return;
|
|
54517
54554
|
}
|
|
54518
54555
|
if (sessionID && role === "assistant" && error48) {
|
|
54556
|
+
if (!isSessionAutoModelRoutingEnabled(sessionID)) {
|
|
54557
|
+
return;
|
|
54558
|
+
}
|
|
54519
54559
|
sessionAwaitingFallbackResult.delete(sessionID);
|
|
54520
54560
|
if (sessionRetryInFlight.has(sessionID) && !retrySignal) {
|
|
54521
54561
|
log(`[${HOOK_NAME12}] message.updated fallback skipped (retry in flight)`, { sessionID });
|
|
@@ -54617,6 +54657,8 @@ function createChatMessageHandler2(deps) {
|
|
|
54617
54657
|
let state3 = sessionStates.get(sessionID);
|
|
54618
54658
|
if (!state3)
|
|
54619
54659
|
return;
|
|
54660
|
+
if (!isSessionAutoModelRoutingEnabled(sessionID))
|
|
54661
|
+
return;
|
|
54620
54662
|
sessionLastAccess.set(sessionID, Date.now());
|
|
54621
54663
|
const requestedModel = input.model ? `${input.model.providerID}/${input.model.modelID}` : undefined;
|
|
54622
54664
|
if (requestedModel && requestedModel !== state3.currentModel) {
|
|
@@ -77872,7 +77914,7 @@ function createSessionHooks(args) {
|
|
|
77872
77914
|
fallbackTitleState.delete(oldestKey);
|
|
77873
77915
|
}
|
|
77874
77916
|
};
|
|
77875
|
-
const isModelFallbackConfigEnabled = pluginConfig.model_fallback ??
|
|
77917
|
+
const isModelFallbackConfigEnabled = pluginConfig.model_fallback ?? false;
|
|
77876
77918
|
const modelFallback = isModelFallbackConfigEnabled && isHookEnabled("model-fallback") ? safeHook("model-fallback", () => createModelFallbackHook({
|
|
77877
77919
|
toast: async ({ title, message, variant, duration: duration5 }) => {
|
|
77878
77920
|
await ctx.client.tui.showToast({
|
|
@@ -97821,7 +97863,18 @@ function applyResolvedUltraworkOverride(args) {
|
|
|
97821
97863
|
});
|
|
97822
97864
|
showToast3(tui, "Ultrawork Model Override", `${fromModel} \u2192 ${override.modelID}. Maximum precision engaged.`);
|
|
97823
97865
|
}
|
|
97824
|
-
function applyUltraworkModelOverrideOnMessage(pluginConfig, inputAgentName, output, tui, sessionID,
|
|
97866
|
+
function applyUltraworkModelOverrideOnMessage(pluginConfig, inputAgentName, output, tui, sessionID, manualModelChangeDetectedOrClient = false, client2, allowAutomaticModelOverride = true) {
|
|
97867
|
+
let manualModelChangeDetected = false;
|
|
97868
|
+
let resolvedClient = client2;
|
|
97869
|
+
if (typeof manualModelChangeDetectedOrClient === "boolean") {
|
|
97870
|
+
manualModelChangeDetected = manualModelChangeDetectedOrClient;
|
|
97871
|
+
} else if (manualModelChangeDetectedOrClient !== undefined && manualModelChangeDetectedOrClient !== null) {
|
|
97872
|
+
resolvedClient = manualModelChangeDetectedOrClient;
|
|
97873
|
+
}
|
|
97874
|
+
if (!allowAutomaticModelOverride) {
|
|
97875
|
+
log("[ultrawork-model-override] Skip override; auto model routing disabled for session");
|
|
97876
|
+
return;
|
|
97877
|
+
}
|
|
97825
97878
|
if (manualModelChangeDetected) {
|
|
97826
97879
|
log("[ultrawork-model-override] Skip override; manual model change detected");
|
|
97827
97880
|
return;
|
|
@@ -97831,7 +97884,7 @@ function applyUltraworkModelOverrideOnMessage(pluginConfig, inputAgentName, outp
|
|
|
97831
97884
|
return;
|
|
97832
97885
|
const currentModel = getMessageModel(output.message.model);
|
|
97833
97886
|
const variantTargetModel = override.providerID && override.modelID ? { providerID: override.providerID, modelID: override.modelID } : currentModel;
|
|
97834
|
-
if (!
|
|
97887
|
+
if (!resolvedClient || typeof resolvedClient.provider?.list !== "function") {
|
|
97835
97888
|
if (override.variant) {
|
|
97836
97889
|
log("[ultrawork-model-override] SDK validation unavailable, skipping variant override", {
|
|
97837
97890
|
variant: override.variant
|
|
@@ -97840,7 +97893,7 @@ function applyUltraworkModelOverrideOnMessage(pluginConfig, inputAgentName, outp
|
|
|
97840
97893
|
applyResolvedUltraworkOverride({ override, validatedVariant: undefined, output, inputAgentName, tui });
|
|
97841
97894
|
return;
|
|
97842
97895
|
}
|
|
97843
|
-
return resolveValidUltraworkVariant(
|
|
97896
|
+
return resolveValidUltraworkVariant(resolvedClient, variantTargetModel, override.variant).then((validatedVariant) => {
|
|
97844
97897
|
if (override.variant && !validatedVariant) {
|
|
97845
97898
|
log("[ultrawork-model-override] Skip invalid ultrawork variant override", {
|
|
97846
97899
|
variant: override.variant,
|
|
@@ -97913,6 +97966,10 @@ function createChatMessageHandler3(args) {
|
|
|
97913
97966
|
const forcedModel = getSessionForcedModel(input.sessionID);
|
|
97914
97967
|
const rawInputModel = input.model;
|
|
97915
97968
|
const rawInputModelId = modelToString(rawInputModel);
|
|
97969
|
+
if (rawInputModel !== undefined) {
|
|
97970
|
+
setSessionAutoModelRouting(input.sessionID, isAutoModelSelection(rawInputModelId));
|
|
97971
|
+
}
|
|
97972
|
+
const autoModelRoutingEnabled = isSessionAutoModelRoutingEnabled(input.sessionID);
|
|
97916
97973
|
if (strictUserModelPriority && lockedModel) {
|
|
97917
97974
|
if (!rawInputModel) {
|
|
97918
97975
|
input.model = lockedModel;
|
|
@@ -97925,7 +97982,10 @@ function createChatMessageHandler3(args) {
|
|
|
97925
97982
|
}
|
|
97926
97983
|
}
|
|
97927
97984
|
}
|
|
97928
|
-
const soulRules = loadSoulRules({
|
|
97985
|
+
const soulRules = loadSoulRules({
|
|
97986
|
+
directory: typeof ctx.directory === "string" ? ctx.directory : "",
|
|
97987
|
+
pluginConfig
|
|
97988
|
+
});
|
|
97929
97989
|
const injectOnce = pluginConfig.soul?.inject_once ?? true;
|
|
97930
97990
|
const alreadyInjected = soulInjectedSessions.has(input.sessionID);
|
|
97931
97991
|
if (soulRules.content && (!injectOnce || !alreadyInjected)) {
|
|
@@ -97960,12 +98020,14 @@ function createChatMessageHandler3(args) {
|
|
|
97960
98020
|
if (firstMessageVariantGate.shouldOverride(input.sessionID)) {
|
|
97961
98021
|
firstMessageVariantGate.markApplied(input.sessionID);
|
|
97962
98022
|
}
|
|
97963
|
-
if (!isRuntimeFallbackEnabled) {
|
|
98023
|
+
if (!isRuntimeFallbackEnabled && autoModelRoutingEnabled) {
|
|
97964
98024
|
await hooks2.modelFallback?.["chat.message"]?.(input, output);
|
|
97965
98025
|
}
|
|
97966
98026
|
await hooks2.stopContinuationGuard?.["chat.message"]?.(input);
|
|
97967
98027
|
await hooks2.backgroundNotificationHook?.["chat.message"]?.(input, output);
|
|
97968
|
-
|
|
98028
|
+
if (autoModelRoutingEnabled) {
|
|
98029
|
+
await hooks2.runtimeFallback?.["chat.message"]?.(input, output);
|
|
98030
|
+
}
|
|
97969
98031
|
await hooks2.keywordDetector?.["chat.message"]?.(input, output);
|
|
97970
98032
|
await hooks2.thinkMode?.["chat.message"]?.(input, output);
|
|
97971
98033
|
await hooks2.claudeCodeHooks?.["chat.message"]?.(input, output);
|
|
@@ -98008,7 +98070,7 @@ function createChatMessageHandler3(args) {
|
|
|
98008
98070
|
hooks2.ralphLoop.cancelLoop(input.sessionID);
|
|
98009
98071
|
}
|
|
98010
98072
|
}
|
|
98011
|
-
await applyUltraworkModelOverrideOnMessage(pluginConfig, input.agent, output, pluginContext.client.tui, input.sessionID, manualModelChangeDetected, pluginContext.client);
|
|
98073
|
+
await applyUltraworkModelOverrideOnMessage(pluginConfig, input.agent, output, pluginContext.client.tui, input.sessionID, manualModelChangeDetected, pluginContext.client, autoModelRoutingEnabled);
|
|
98012
98074
|
const requestedModel = input.model;
|
|
98013
98075
|
const requestedModelId = modelToString(requestedModel);
|
|
98014
98076
|
const shouldLockToRequestedModel = strictUserModelPriority && requestedModel !== undefined && !isAutoModelSelection(requestedModelId);
|
|
@@ -98346,7 +98408,7 @@ function createEventHandler2(args) {
|
|
|
98346
98408
|
setSessionModel(sessionID, { providerID, modelID });
|
|
98347
98409
|
}
|
|
98348
98410
|
}
|
|
98349
|
-
if (sessionID && role === "assistant" && !isRuntimeFallbackEnabled && isModelFallbackEnabled) {
|
|
98411
|
+
if (sessionID && role === "assistant" && !isRuntimeFallbackEnabled && isModelFallbackEnabled && isSessionAutoModelRoutingEnabled(sessionID)) {
|
|
98350
98412
|
try {
|
|
98351
98413
|
const assistantMessageID = info?.id;
|
|
98352
98414
|
const assistantError = info?.error;
|
|
@@ -98390,7 +98452,7 @@ function createEventHandler2(args) {
|
|
|
98390
98452
|
if (event.type === "session.status") {
|
|
98391
98453
|
const sessionID = props?.sessionID;
|
|
98392
98454
|
const status = props?.status;
|
|
98393
|
-
if (sessionID && status?.type === "retry" && isModelFallbackEnabled && !isRuntimeFallbackEnabled) {
|
|
98455
|
+
if (sessionID && status?.type === "retry" && isModelFallbackEnabled && !isRuntimeFallbackEnabled && isSessionAutoModelRoutingEnabled(sessionID)) {
|
|
98394
98456
|
try {
|
|
98395
98457
|
const retryMessage = typeof status.message === "string" ? status.message : "";
|
|
98396
98458
|
const parsedForKey = extractProviderModelFromErrorMessage(retryMessage);
|
|
@@ -98452,7 +98514,7 @@ function createEventHandler2(args) {
|
|
|
98452
98514
|
query: { directory: pluginContext.directory }
|
|
98453
98515
|
}).catch(() => {});
|
|
98454
98516
|
}
|
|
98455
|
-
} else if (sessionID && shouldRetryError(errorInfo) && !isRuntimeFallbackEnabled && isModelFallbackEnabled) {
|
|
98517
|
+
} else if (sessionID && shouldRetryError(errorInfo) && !isRuntimeFallbackEnabled && isModelFallbackEnabled && isSessionAutoModelRoutingEnabled(sessionID)) {
|
|
98456
98518
|
let agentName = getSessionAgent(sessionID);
|
|
98457
98519
|
if (!agentName && sessionID === getMainSessionID()) {
|
|
98458
98520
|
if (errorMessage.includes("claude-opus") || errorMessage.includes("opus")) {
|
|
@@ -20,4 +20,4 @@ export declare function applyUltraworkModelOverrideOnMessage(pluginConfig: OhMyO
|
|
|
20
20
|
text?: string;
|
|
21
21
|
[key: string]: unknown;
|
|
22
22
|
}>;
|
|
23
|
-
}, tui: unknown, sessionID?: string,
|
|
23
|
+
}, tui: unknown, sessionID?: string, manualModelChangeDetectedOrClient?: unknown, client?: unknown, allowAutomaticModelOverride?: boolean): void | Promise<void>;
|
|
@@ -11,3 +11,7 @@ export declare function clearSessionModelLock(sessionID: string): void;
|
|
|
11
11
|
export declare function setSessionForcedModel(sessionID: string, model: SessionModel): void;
|
|
12
12
|
export declare function getSessionForcedModel(sessionID: string): SessionModel | undefined;
|
|
13
13
|
export declare function clearSessionForcedModel(sessionID: string): void;
|
|
14
|
+
export declare function setSessionAutoModelRouting(sessionID: string, enabled: boolean): void;
|
|
15
|
+
export declare function getSessionAutoModelRouting(sessionID: string): boolean | undefined;
|
|
16
|
+
export declare function isSessionAutoModelRoutingEnabled(sessionID: string): boolean;
|
|
17
|
+
export declare function clearSessionAutoModelRouting(sessionID: string): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bohuyeshan/openagent-labforge-core",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.4",
|
|
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",
|