oh-my-opencode 5.0.0-beta.51 → 5.0.0-beta.52
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/doctor/checks/index.d.ts +2 -0
- package/dist/cli/doctor/checks/latest-version.d.ts +11 -0
- package/dist/cli/doctor/framework/constants.d.ts +5 -0
- package/dist/cli/doctor/framework/types.d.ts +2 -0
- package/dist/cli/index.js +88 -37
- package/dist/cli-node/index.js +88 -37
- package/dist/features/background-agent/manager.d.ts +7 -0
- package/dist/features/background-agent/types.d.ts +4 -0
- package/dist/features/claude-tasks/storage.d.ts +7 -2
- package/dist/features/hook-message-injector/index.d.ts +1 -0
- package/dist/features/hook-message-injector/sdk-message-lookup.d.ts +1 -0
- package/dist/hooks/keyword-detector/hook.d.ts +2 -0
- package/dist/hooks/keyword-detector/ultrawork/index.d.ts +2 -0
- package/dist/hooks/unstable-agent-babysitter/task-message-analyzer.d.ts +1 -0
- package/dist/index.js +286 -109
- package/dist/plugin/chat-message/types.d.ts +3 -1
- package/dist/plugin/stop-continuation.d.ts +3 -0
- package/dist/plugin/system-transform.d.ts +5 -1
- package/dist/skills/frontend/ATTRIBUTION.md +10 -0
- package/dist/skills/frontend/SKILL.md +3 -0
- package/dist/skills/frontend/references/design/README.md +10 -2
- package/dist/skills/frontend/references/design/_INDEX.md +1 -0
- package/dist/skills/frontend/references/design/ambience-skill.md +145 -0
- package/dist/skills/frontend/references/design/interaction-skill.md +2 -0
- package/dist/tui.js +16 -7
- package/package.json +14 -14
- package/packages/lsp-daemon/dist/cli.js +1 -2
- package/packages/lsp-daemon/dist/ownership.js +2 -2
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/dist/cli.js +1 -1
- package/packages/omo-codex/plugin/components/git-bash/dist/codex-hook.js +2 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/src/codex-hook.ts +2 -1
- package/packages/omo-codex/plugin/components/git-bash/test/codex-hook.test.ts +6 -7
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +10 -0
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +3 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +10 -2
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/ambience-skill.md +145 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/interaction-skill.md +2 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
- package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +10 -0
- package/packages/shared-skills/skills/frontend/SKILL.md +3 -0
- package/packages/shared-skills/skills/frontend/references/design/README.md +10 -2
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/shared-skills/skills/frontend/references/design/ambience-skill.md +145 -0
- package/packages/shared-skills/skills/frontend/references/design/interaction-skill.md +2 -0
package/dist/index.js
CHANGED
|
@@ -23340,10 +23340,8 @@ function validationDiagnostic(path, issues) {
|
|
|
23340
23340
|
function unrecognizedKeyIssues(issues) {
|
|
23341
23341
|
return issues.flatMap((issue) => issue.code === "unrecognized_keys" ? [{ keys: issue.keys, path: issue.path.map((segment) => String(segment)) }] : []);
|
|
23342
23342
|
}
|
|
23343
|
-
function hasUnsafeUnrecognizedKey(
|
|
23344
|
-
|
|
23345
|
-
return true;
|
|
23346
|
-
return hasTamperedPrototype(parsed);
|
|
23343
|
+
function hasUnsafeUnrecognizedKey(issues) {
|
|
23344
|
+
return issues.some((issue) => issue.keys.some((key) => isUnsafeObjectKey2(key)));
|
|
23347
23345
|
}
|
|
23348
23346
|
function hasTamperedPrototype(value) {
|
|
23349
23347
|
if (Array.isArray(value))
|
|
@@ -23416,11 +23414,17 @@ function readConfigSource(path, scope, fileSystem) {
|
|
|
23416
23414
|
source: { exists: true, loaded: false, path, scope }
|
|
23417
23415
|
};
|
|
23418
23416
|
}
|
|
23417
|
+
if (hasTamperedPrototype(parsed.data)) {
|
|
23418
|
+
return {
|
|
23419
|
+
diagnostic: { kind: "validation", message: `Invalid omo config at ${path}: "__proto__" member is not allowed`, path },
|
|
23420
|
+
source: { exists: true, loaded: false, path, scope }
|
|
23421
|
+
};
|
|
23422
|
+
}
|
|
23419
23423
|
const parsedRecord = toRecord2(parsed.data);
|
|
23420
23424
|
const validation = OmoConfigLayerSchema.safeParse(parsed.data);
|
|
23421
23425
|
if (!validation.success) {
|
|
23422
23426
|
const unrecognized = unrecognizedKeyIssues(validation.error.issues);
|
|
23423
|
-
if (
|
|
23427
|
+
if (hasUnsafeUnrecognizedKey(unrecognized)) {
|
|
23424
23428
|
return {
|
|
23425
23429
|
diagnostic: validationDiagnostic(path, validation.error.issues),
|
|
23426
23430
|
source: { exists: true, loaded: false, path, scope }
|
|
@@ -82598,7 +82602,7 @@ function convertSDKMessageToStoredMessage(msg) {
|
|
|
82598
82602
|
return null;
|
|
82599
82603
|
const providerID = info.model?.providerID ?? info.providerID;
|
|
82600
82604
|
const modelID = info.model?.modelID ?? info.modelID;
|
|
82601
|
-
const variant = info.model?.variant;
|
|
82605
|
+
const variant = info.model?.variant ?? info.variant;
|
|
82602
82606
|
if (!info.agent && !providerID && !modelID) {
|
|
82603
82607
|
return null;
|
|
82604
82608
|
}
|
|
@@ -82695,6 +82699,10 @@ async function resolveMessageContext(sessionID, client, messageDir) {
|
|
|
82695
82699
|
// packages/omo-opencode/src/features/hook-message-injector/id-generation.ts
|
|
82696
82700
|
import { randomBytes } from "crypto";
|
|
82697
82701
|
var processPrefix = randomBytes(4).toString("hex");
|
|
82702
|
+
var partCounter = 0;
|
|
82703
|
+
function generatePartId() {
|
|
82704
|
+
return `prt_${processPrefix}_${String(++partCounter).padStart(6, "0")}`;
|
|
82705
|
+
}
|
|
82698
82706
|
// packages/omo-opencode/src/shared/internal-initiator-marker.ts
|
|
82699
82707
|
init_internal_initiator_marker();
|
|
82700
82708
|
|
|
@@ -86537,6 +86545,10 @@ var CHECK_NAMES = {
|
|
|
86537
86545
|
[CHECK_IDS.TEAM_MODE]: "Team Mode",
|
|
86538
86546
|
[CHECK_IDS.CODEX]: "Codex"
|
|
86539
86547
|
};
|
|
86548
|
+
var UPDATE_COMMANDS = {
|
|
86549
|
+
opencode: `bunx ${PUBLISHED_PACKAGE_NAME} install`,
|
|
86550
|
+
codex: "npx lazycodex-ai install --no-tui --codex-autonomous"
|
|
86551
|
+
};
|
|
86540
86552
|
|
|
86541
86553
|
// packages/omo-opencode/src/cli/doctor/checks/tui-plugin-config.ts
|
|
86542
86554
|
var TUI_SUBPATH = "tui";
|
|
@@ -96387,7 +96399,7 @@ function getCachedVersion(options = {}) {
|
|
|
96387
96399
|
// package.json
|
|
96388
96400
|
var package_default = {
|
|
96389
96401
|
name: "oh-my-opencode",
|
|
96390
|
-
version: "5.0.0-beta.
|
|
96402
|
+
version: "5.0.0-beta.52",
|
|
96391
96403
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
96392
96404
|
main: "./dist/index.js",
|
|
96393
96405
|
types: "dist/index.d.ts",
|
|
@@ -96571,7 +96583,7 @@ var package_default = {
|
|
|
96571
96583
|
zod: "^4.4.3"
|
|
96572
96584
|
},
|
|
96573
96585
|
devDependencies: {
|
|
96574
|
-
"@code-yeongyu/senpi": "2026.9.
|
|
96586
|
+
"@code-yeongyu/senpi": "2026.9.10",
|
|
96575
96587
|
"@oh-my-opencode/agents-md-core": "workspace:*",
|
|
96576
96588
|
"@oh-my-opencode/ast-grep-mcp": "workspace:*",
|
|
96577
96589
|
"@oh-my-opencode/boulder-state": "workspace:*",
|
|
@@ -96612,18 +96624,18 @@ var package_default = {
|
|
|
96612
96624
|
typescript: "^7.0.2"
|
|
96613
96625
|
},
|
|
96614
96626
|
optionalDependencies: {
|
|
96615
|
-
"oh-my-opencode-darwin-arm64": "5.0.0-beta.
|
|
96616
|
-
"oh-my-opencode-darwin-x64": "5.0.0-beta.
|
|
96617
|
-
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.
|
|
96618
|
-
"oh-my-opencode-linux-arm64": "5.0.0-beta.
|
|
96619
|
-
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.
|
|
96620
|
-
"oh-my-opencode-linux-x64": "5.0.0-beta.
|
|
96621
|
-
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.
|
|
96622
|
-
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.
|
|
96623
|
-
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.
|
|
96624
|
-
"oh-my-opencode-windows-arm64": "5.0.0-beta.
|
|
96625
|
-
"oh-my-opencode-windows-x64": "5.0.0-beta.
|
|
96626
|
-
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.
|
|
96627
|
+
"oh-my-opencode-darwin-arm64": "5.0.0-beta.52",
|
|
96628
|
+
"oh-my-opencode-darwin-x64": "5.0.0-beta.52",
|
|
96629
|
+
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.52",
|
|
96630
|
+
"oh-my-opencode-linux-arm64": "5.0.0-beta.52",
|
|
96631
|
+
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.52",
|
|
96632
|
+
"oh-my-opencode-linux-x64": "5.0.0-beta.52",
|
|
96633
|
+
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.52",
|
|
96634
|
+
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.52",
|
|
96635
|
+
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.52",
|
|
96636
|
+
"oh-my-opencode-windows-arm64": "5.0.0-beta.52",
|
|
96637
|
+
"oh-my-opencode-windows-x64": "5.0.0-beta.52",
|
|
96638
|
+
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.52"
|
|
96627
96639
|
},
|
|
96628
96640
|
overrides: {
|
|
96629
96641
|
"@earendil-works/pi-agent-core": "0.84.2",
|
|
@@ -103400,8 +103412,7 @@ function getDefaultUltraworkMessage() {
|
|
|
103400
103412
|
return ULTRAWORK_DEFAULT_MESSAGE;
|
|
103401
103413
|
}
|
|
103402
103414
|
// packages/omo-opencode/src/hooks/keyword-detector/ultrawork/index.ts
|
|
103403
|
-
function
|
|
103404
|
-
const source = getUltraworkSource(agentName, modelID);
|
|
103415
|
+
function getUltraworkMessageForSource(source) {
|
|
103405
103416
|
switch (source) {
|
|
103406
103417
|
case "planner":
|
|
103407
103418
|
return getPlannerUltraworkMessage();
|
|
@@ -103416,6 +103427,9 @@ function getUltraworkMessage(agentName, modelID) {
|
|
|
103416
103427
|
return getDefaultUltraworkMessage();
|
|
103417
103428
|
}
|
|
103418
103429
|
}
|
|
103430
|
+
function getUltraworkMessage(agentName, modelID) {
|
|
103431
|
+
return getUltraworkMessageForSource(getUltraworkSource(agentName, modelID));
|
|
103432
|
+
}
|
|
103419
103433
|
|
|
103420
103434
|
// packages/omo-opencode/src/hooks/keyword-detector/team/default.ts
|
|
103421
103435
|
var TEAM_PATTERN = /\bteam[\s_-]?mode\b/i;
|
|
@@ -103498,6 +103512,7 @@ function extractPromptText2(parts) {
|
|
|
103498
103512
|
// packages/omo-opencode/src/hooks/keyword-detector/hook.ts
|
|
103499
103513
|
var defaultModeUltraworkInjectedSessions = new Set;
|
|
103500
103514
|
var DEFAULT_MODE_ULTRAWORK_SESSION_CAP = 256;
|
|
103515
|
+
var ULTRAWORK_CONTINUATION_MARKER = "<ultrawork-mode>active</ultrawork-mode>";
|
|
103501
103516
|
function rememberDefaultModeUltraworkInjectedSession(sessionID) {
|
|
103502
103517
|
if (defaultModeUltraworkInjectedSessions.has(sessionID))
|
|
103503
103518
|
return;
|
|
@@ -103526,6 +103541,7 @@ function filterAlreadyInjectedKeywords(detected, text) {
|
|
|
103526
103541
|
function createKeywordDetectorHook(ctx, _collector, _ralphLoop, config, defaultMode) {
|
|
103527
103542
|
const disabledKeywords = config?.disabled_keywords;
|
|
103528
103543
|
const enabledExpansions = config?.enabled_expansions;
|
|
103544
|
+
const explicitUltraworkSessions = new Map;
|
|
103529
103545
|
function getRuntimeVariant(input, message) {
|
|
103530
103546
|
if (typeof message.variant === "string") {
|
|
103531
103547
|
return message.variant;
|
|
@@ -103538,12 +103554,15 @@ function createKeywordDetectorHook(ctx, _collector, _ralphLoop, config, defaultM
|
|
|
103538
103554
|
log2(`[keyword-detector] Skipping synthetic/internal text message`, { sessionID: input.sessionID });
|
|
103539
103555
|
return;
|
|
103540
103556
|
}
|
|
103541
|
-
const promptText = extractPromptText2(output.parts);
|
|
103557
|
+
const promptText = extractPromptText2(output.parts.filter(isRealUserTextPart));
|
|
103542
103558
|
if (isSystemDirective(promptText)) {
|
|
103543
103559
|
log2(`[keyword-detector] Skipping system directive message`, { sessionID: input.sessionID });
|
|
103544
103560
|
return;
|
|
103545
103561
|
}
|
|
103546
103562
|
if (looksLikeSlashCommand(promptText)) {
|
|
103563
|
+
if (/^\s*\/stop-continuation(?:\s|$)/i.test(promptText)) {
|
|
103564
|
+
explicitUltraworkSessions.delete(input.sessionID);
|
|
103565
|
+
}
|
|
103547
103566
|
log2(`[keyword-detector] Skipping slash command invocation`, { sessionID: input.sessionID });
|
|
103548
103567
|
return;
|
|
103549
103568
|
}
|
|
@@ -103553,8 +103572,17 @@ function createKeywordDetectorHook(ctx, _collector, _ralphLoop, config, defaultM
|
|
|
103553
103572
|
return;
|
|
103554
103573
|
}
|
|
103555
103574
|
const cleanText = removeSystemReminders(promptText);
|
|
103556
|
-
const
|
|
103575
|
+
const selectedModel = output.message.model;
|
|
103576
|
+
const modelID = selectedModel !== null && typeof selectedModel === "object" && "modelID" in selectedModel && typeof selectedModel.modelID === "string" ? selectedModel.modelID : input.model?.modelID;
|
|
103577
|
+
const promptSource = getUltraworkSource(currentAgent, modelID);
|
|
103557
103578
|
let detectedKeywords = detectKeywordsWithType(cleanText, currentAgent, modelID, disabledKeywords, enabledExpansions);
|
|
103579
|
+
const explicitUltrawork = detectedKeywords.some((k) => k.type === "ultrawork" || k.type === "hyperplan-ultrawork");
|
|
103580
|
+
const activeUltrawork = explicitUltraworkSessions.get(input.sessionID);
|
|
103581
|
+
const replayUltrawork = !explicitUltrawork && activeUltrawork !== undefined;
|
|
103582
|
+
const compactUltrawork = activeUltrawork !== undefined && !activeUltrawork.needsRestoration && activeUltrawork.source === promptSource;
|
|
103583
|
+
if (replayUltrawork) {
|
|
103584
|
+
detectedKeywords.push({ type: "ultrawork", message: getUltraworkMessageForSource(promptSource) });
|
|
103585
|
+
}
|
|
103558
103586
|
detectedKeywords = suppressComboStandalones(detectedKeywords);
|
|
103559
103587
|
if (isPlannerAgent(currentAgent)) {
|
|
103560
103588
|
const preFilterCount = detectedKeywords.length;
|
|
@@ -103606,7 +103634,7 @@ function createKeywordDetectorHook(ctx, _collector, _ralphLoop, config, defaultM
|
|
|
103606
103634
|
return;
|
|
103607
103635
|
}
|
|
103608
103636
|
const hasUltrawork = detectedKeywords.some((k) => k.type === "ultrawork");
|
|
103609
|
-
if (hasUltrawork) {
|
|
103637
|
+
if (hasUltrawork && explicitUltrawork) {
|
|
103610
103638
|
const runtimeVariant = getRuntimeVariant(input, output.message);
|
|
103611
103639
|
const isRuntimeMax = runtimeVariant === "max";
|
|
103612
103640
|
log2(`[keyword-detector] Ultrawork mode activated`, {
|
|
@@ -103654,34 +103682,83 @@ function createKeywordDetectorHook(ctx, _collector, _ralphLoop, config, defaultM
|
|
|
103654
103682
|
}
|
|
103655
103683
|
}).catch((err) => log2(`[keyword-detector] Failed to show toast`, { error: err, sessionID: input.sessionID }));
|
|
103656
103684
|
}
|
|
103657
|
-
const
|
|
103658
|
-
if (textPartIndex === -1) {
|
|
103659
|
-
log2(`[keyword-detector] No text part found, skipping injection`, { sessionID: input.sessionID });
|
|
103660
|
-
return;
|
|
103661
|
-
}
|
|
103662
|
-
const allMessages = detectedKeywords.map((k) => k.message).join(`
|
|
103685
|
+
const allMessages = detectedKeywords.filter((k) => !(compactUltrawork && k.type === "ultrawork")).map((k) => k.message).join(`
|
|
103663
103686
|
|
|
103664
103687
|
`);
|
|
103665
|
-
const
|
|
103666
|
-
|
|
103688
|
+
const textPart = output.parts.find(isRealUserTextPart);
|
|
103689
|
+
const requiresFullGuidance = (hasUltrawork || hasHyperplanUltrawork) && !compactUltrawork && allMessages.length > 0;
|
|
103690
|
+
const messageID = input.messageID ?? (typeof output.message.id === "string" ? output.message.id : undefined);
|
|
103691
|
+
let fullGuidanceDurablyAdded = textPart !== undefined && requiresFullGuidance;
|
|
103692
|
+
if (textPart && allMessages) {
|
|
103693
|
+
textPart.text = `${textPart.text}
|
|
103667
103694
|
|
|
103668
103695
|
---
|
|
103669
103696
|
|
|
103670
103697
|
${allMessages}`;
|
|
103698
|
+
}
|
|
103699
|
+
if (!textPart && requiresFullGuidance && messageID) {
|
|
103700
|
+
output.parts.push({
|
|
103701
|
+
id: generatePartId(),
|
|
103702
|
+
sessionID: input.sessionID,
|
|
103703
|
+
messageID,
|
|
103704
|
+
type: "text",
|
|
103705
|
+
text: allMessages,
|
|
103706
|
+
synthetic: true
|
|
103707
|
+
});
|
|
103708
|
+
fullGuidanceDurablyAdded = true;
|
|
103709
|
+
}
|
|
103710
|
+
if (hasUltrawork && compactUltrawork && !output.parts.some((part) => part.synthetic === true && part.text === ULTRAWORK_CONTINUATION_MARKER) && messageID) {
|
|
103711
|
+
output.parts.push({
|
|
103712
|
+
id: generatePartId(),
|
|
103713
|
+
sessionID: input.sessionID,
|
|
103714
|
+
messageID,
|
|
103715
|
+
type: "text",
|
|
103716
|
+
text: ULTRAWORK_CONTINUATION_MARKER,
|
|
103717
|
+
synthetic: true
|
|
103718
|
+
});
|
|
103719
|
+
}
|
|
103720
|
+
if ((explicitUltrawork || replayUltrawork) && (hasUltrawork || hasHyperplanUltrawork) && (!requiresFullGuidance || fullGuidanceDurablyAdded)) {
|
|
103721
|
+
if (!explicitUltraworkSessions.has(input.sessionID) && explicitUltraworkSessions.size >= DEFAULT_MODE_ULTRAWORK_SESSION_CAP) {
|
|
103722
|
+
const oldest = explicitUltraworkSessions.keys().next().value;
|
|
103723
|
+
if (oldest !== undefined)
|
|
103724
|
+
explicitUltraworkSessions.delete(oldest);
|
|
103725
|
+
}
|
|
103726
|
+
explicitUltraworkSessions.set(input.sessionID, { source: promptSource, needsRestoration: false });
|
|
103727
|
+
}
|
|
103671
103728
|
log2(`[keyword-detector] Detected ${detectedKeywords.length} keywords`, {
|
|
103672
103729
|
sessionID: input.sessionID,
|
|
103673
103730
|
types: detectedKeywords.map((k) => k.type)
|
|
103674
103731
|
});
|
|
103675
103732
|
},
|
|
103733
|
+
clearSession: (sessionID) => {
|
|
103734
|
+
explicitUltraworkSessions.delete(sessionID);
|
|
103735
|
+
},
|
|
103736
|
+
getSystemTransformGuidance: (sessionID, modelID) => {
|
|
103737
|
+
const activeUltrawork = explicitUltraworkSessions.get(sessionID);
|
|
103738
|
+
const agent = getSessionAgent(sessionID);
|
|
103739
|
+
if (!activeUltrawork?.needsRestoration || isPlannerAgent(agent) || isNonOmoAgent(agent) || subagentSessions.has(sessionID))
|
|
103740
|
+
return;
|
|
103741
|
+
return getUltraworkMessageForSource(modelID === undefined ? activeUltrawork.source : getUltraworkSource(agent, modelID));
|
|
103742
|
+
},
|
|
103676
103743
|
event: ({ event }) => {
|
|
103677
|
-
if (event.type !== "session.deleted")
|
|
103744
|
+
if (event.type !== "session.deleted" && event.type !== "session.compacted")
|
|
103678
103745
|
return;
|
|
103679
103746
|
const sessionID = resolveSessionEventID(event.properties);
|
|
103680
|
-
if (sessionID)
|
|
103747
|
+
if (sessionID) {
|
|
103748
|
+
if (event.type === "session.compacted") {
|
|
103749
|
+
const activeUltrawork = explicitUltraworkSessions.get(sessionID);
|
|
103750
|
+
if (activeUltrawork) {
|
|
103751
|
+
explicitUltraworkSessions.set(sessionID, { ...activeUltrawork, needsRestoration: true });
|
|
103752
|
+
}
|
|
103753
|
+
return;
|
|
103754
|
+
}
|
|
103681
103755
|
clearDefaultModeUltraworkInjectedSession(sessionID);
|
|
103756
|
+
explicitUltraworkSessions.delete(sessionID);
|
|
103757
|
+
}
|
|
103682
103758
|
},
|
|
103683
103759
|
dispose: () => {
|
|
103684
103760
|
clearAllDefaultModeUltraworkInjectedSessions();
|
|
103761
|
+
explicitUltraworkSessions.clear();
|
|
103685
103762
|
}
|
|
103686
103763
|
};
|
|
103687
103764
|
}
|
|
@@ -113354,7 +113431,14 @@ async function resolveRecentPromptContextForSession(ctx, sessionID, deps = defau
|
|
|
113354
113431
|
};
|
|
113355
113432
|
}
|
|
113356
113433
|
if (info?.providerID && info?.modelID) {
|
|
113357
|
-
return {
|
|
113434
|
+
return {
|
|
113435
|
+
model: {
|
|
113436
|
+
providerID: info.providerID,
|
|
113437
|
+
modelID: info.modelID,
|
|
113438
|
+
...info.variant ? { variant: info.variant } : {}
|
|
113439
|
+
},
|
|
113440
|
+
tools
|
|
113441
|
+
};
|
|
113358
113442
|
}
|
|
113359
113443
|
}
|
|
113360
113444
|
} catch (error) {
|
|
@@ -116577,6 +116661,7 @@ function getMessageInfo(value) {
|
|
|
116577
116661
|
model,
|
|
116578
116662
|
providerID: typeof info.providerID === "string" ? info.providerID : undefined,
|
|
116579
116663
|
modelID: typeof info.modelID === "string" ? info.modelID : undefined,
|
|
116664
|
+
variant: typeof info.variant === "string" ? info.variant : undefined,
|
|
116580
116665
|
tools: isRecord(info.tools) ? Object.entries(info.tools).reduce((acc, [key, value]) => {
|
|
116581
116666
|
if (value === true || value === false || value === "allow" || value === "deny" || value === "ask") {
|
|
116582
116667
|
acc[key] = value;
|
|
@@ -116672,7 +116757,11 @@ async function resolveMainSessionTarget(ctx, sessionID) {
|
|
|
116672
116757
|
const info = getMessageInfo(messages[i]);
|
|
116673
116758
|
if (info?.agent || info?.model || info?.providerID && info?.modelID) {
|
|
116674
116759
|
agent = agent ?? info?.agent;
|
|
116675
|
-
model = info?.model ?? (info?.providerID && info?.modelID ? {
|
|
116760
|
+
model = info?.model ?? (info?.providerID && info?.modelID ? {
|
|
116761
|
+
providerID: info.providerID,
|
|
116762
|
+
modelID: info.modelID,
|
|
116763
|
+
...info.variant ? { variant: info.variant } : {}
|
|
116764
|
+
} : undefined);
|
|
116676
116765
|
tools = resolveInheritedPromptTools(sessionID, info?.tools) ?? tools;
|
|
116677
116766
|
break;
|
|
116678
116767
|
}
|
|
@@ -129573,6 +129662,7 @@ async function executeSyncContinuation(args, ctx, executorCtx, parentContext, de
|
|
|
129573
129662
|
throw new Error("task_id is required to continue a sync task");
|
|
129574
129663
|
}
|
|
129575
129664
|
cancelSyncSessionDeletion(continuationID);
|
|
129665
|
+
const detachFromManager = executorCtx.manager?.attachSyncContinuation?.(continuationID);
|
|
129576
129666
|
const taskId = `resume_sync_${continuationID.slice(0, 8)}`;
|
|
129577
129667
|
const startTime = new Date;
|
|
129578
129668
|
if (toastManager) {
|
|
@@ -129644,6 +129734,7 @@ async function executeSyncContinuation(args, ctx, executorCtx, parentContext, de
|
|
|
129644
129734
|
toastManager.removeTask(taskId);
|
|
129645
129735
|
}
|
|
129646
129736
|
const errorMessage = promptError instanceof Error ? promptError.message : String(promptError);
|
|
129737
|
+
detachFromManager?.();
|
|
129647
129738
|
scheduleSyncSessionDeletion(client, continuationID);
|
|
129648
129739
|
return `Failed to send continuation prompt: ${errorMessage}
|
|
129649
129740
|
|
|
@@ -129718,6 +129809,7 @@ ${buildTaskMetadataBlock({
|
|
|
129718
129809
|
});
|
|
129719
129810
|
}
|
|
129720
129811
|
}
|
|
129812
|
+
detachFromManager?.();
|
|
129721
129813
|
scheduleSyncSessionDeletion(client, continuationID);
|
|
129722
129814
|
}
|
|
129723
129815
|
}
|
|
@@ -131857,21 +131949,39 @@ function writeJsonAtomic(filePath, data) {
|
|
|
131857
131949
|
}
|
|
131858
131950
|
}
|
|
131859
131951
|
var STALE_LOCK_THRESHOLD_MS = 30000;
|
|
131952
|
+
var DEFAULT_LOCK_WAIT_TIMEOUT_MS = 5000;
|
|
131953
|
+
var DEFAULT_LOCK_RETRY_DELAY_MS = 10;
|
|
131954
|
+
var MAX_LOCK_RETRY_DELAY_MS = 50;
|
|
131955
|
+
function resolveLockWaitTimeoutMs() {
|
|
131956
|
+
const raw = process.env.OMO_TASK_LOCK_WAIT_TIMEOUT_MS?.trim();
|
|
131957
|
+
if (!raw)
|
|
131958
|
+
return DEFAULT_LOCK_WAIT_TIMEOUT_MS;
|
|
131959
|
+
const parsed = Number(raw);
|
|
131960
|
+
if (!Number.isFinite(parsed) || parsed < 0)
|
|
131961
|
+
return DEFAULT_LOCK_WAIT_TIMEOUT_MS;
|
|
131962
|
+
return parsed;
|
|
131963
|
+
}
|
|
131964
|
+
function delay5(ms) {
|
|
131965
|
+
return new Promise((resolve) => {
|
|
131966
|
+
setTimeout(resolve, ms);
|
|
131967
|
+
});
|
|
131968
|
+
}
|
|
131860
131969
|
function generateTaskId() {
|
|
131861
131970
|
return `T-${randomUUID9()}`;
|
|
131862
131971
|
}
|
|
131863
|
-
function acquireLock2(dirPath) {
|
|
131972
|
+
async function acquireLock2(dirPath, options = {}) {
|
|
131864
131973
|
const lockPath = join113(dirPath, ".lock");
|
|
131865
131974
|
const lockId = randomUUID9();
|
|
131975
|
+
const waitTimeoutMs = options.waitTimeoutMs ?? resolveLockWaitTimeoutMs();
|
|
131976
|
+
const baseRetryDelayMs = options.retryDelayMs ?? DEFAULT_LOCK_RETRY_DELAY_MS;
|
|
131866
131977
|
const createLock = (timestamp) => {
|
|
131867
131978
|
writeFileSync22(lockPath, JSON.stringify({ id: lockId, timestamp }), {
|
|
131868
131979
|
encoding: "utf-8",
|
|
131869
131980
|
flag: "wx"
|
|
131870
131981
|
});
|
|
131871
131982
|
};
|
|
131872
|
-
const isStale = () => {
|
|
131983
|
+
const isStale = (lockContent) => {
|
|
131873
131984
|
try {
|
|
131874
|
-
const lockContent = readFileSync62(lockPath, "utf-8");
|
|
131875
131985
|
const lockData = JSON.parse(lockContent);
|
|
131876
131986
|
const lockAge = Date.now() - lockData.timestamp;
|
|
131877
131987
|
return lockAge > STALE_LOCK_THRESHOLD_MS;
|
|
@@ -131880,6 +131990,25 @@ function acquireLock2(dirPath) {
|
|
|
131880
131990
|
return true;
|
|
131881
131991
|
}
|
|
131882
131992
|
};
|
|
131993
|
+
const reclaimStaleLock = () => {
|
|
131994
|
+
let snapshot;
|
|
131995
|
+
try {
|
|
131996
|
+
snapshot = readFileSync62(lockPath, "utf-8");
|
|
131997
|
+
} catch (error) {
|
|
131998
|
+
ignoreClaudeTaskStorageError(error);
|
|
131999
|
+
return true;
|
|
132000
|
+
}
|
|
132001
|
+
if (!isStale(snapshot))
|
|
132002
|
+
return false;
|
|
132003
|
+
try {
|
|
132004
|
+
if (readFileSync62(lockPath, "utf-8") !== snapshot)
|
|
132005
|
+
return false;
|
|
132006
|
+
unlinkSync16(lockPath);
|
|
132007
|
+
} catch (error) {
|
|
132008
|
+
ignoreClaudeTaskStorageError(error);
|
|
132009
|
+
}
|
|
132010
|
+
return true;
|
|
132011
|
+
};
|
|
131883
132012
|
const tryAcquire = () => {
|
|
131884
132013
|
const now = Date.now();
|
|
131885
132014
|
try {
|
|
@@ -131892,15 +132021,27 @@ function acquireLock2(dirPath) {
|
|
|
131892
132021
|
throw error;
|
|
131893
132022
|
}
|
|
131894
132023
|
};
|
|
132024
|
+
const nextDelayMs = (attempt, deadline) => {
|
|
132025
|
+
const cap = Math.max(MAX_LOCK_RETRY_DELAY_MS, baseRetryDelayMs);
|
|
132026
|
+
const step = Math.min(baseRetryDelayMs * 2 ** attempt, cap);
|
|
132027
|
+
const jittered = step / 2 + Math.random() * (step / 2);
|
|
132028
|
+
return Math.max(1, Math.min(jittered, deadline - Date.now()));
|
|
132029
|
+
};
|
|
131895
132030
|
ensureDir(dirPath);
|
|
131896
|
-
|
|
131897
|
-
|
|
131898
|
-
|
|
131899
|
-
|
|
131900
|
-
|
|
131901
|
-
|
|
132031
|
+
const deadline = Date.now() + waitTimeoutMs;
|
|
132032
|
+
let acquired = false;
|
|
132033
|
+
for (let attempt = 0;; attempt++) {
|
|
132034
|
+
if (tryAcquire()) {
|
|
132035
|
+
acquired = true;
|
|
132036
|
+
break;
|
|
132037
|
+
}
|
|
132038
|
+
if (reclaimStaleLock() && tryAcquire()) {
|
|
132039
|
+
acquired = true;
|
|
132040
|
+
break;
|
|
131902
132041
|
}
|
|
131903
|
-
|
|
132042
|
+
if (Date.now() >= deadline)
|
|
132043
|
+
break;
|
|
132044
|
+
await delay5(nextDelayMs(attempt, deadline));
|
|
131904
132045
|
}
|
|
131905
132046
|
if (!acquired) {
|
|
131906
132047
|
return {
|
|
@@ -132059,10 +132200,11 @@ async function handleCreate(args, config, ctx, context) {
|
|
|
132059
132200
|
try {
|
|
132060
132201
|
const validatedArgs = TaskCreateInputSchema.parse(args);
|
|
132061
132202
|
const taskDir = getTaskDir(config);
|
|
132062
|
-
const lock = acquireLock2(taskDir);
|
|
132203
|
+
const lock = await acquireLock2(taskDir);
|
|
132063
132204
|
if (!lock.acquired) {
|
|
132064
|
-
return JSON.stringify({ error: "task_lock_unavailable" });
|
|
132205
|
+
return JSON.stringify({ error: "task_lock_unavailable", retryable: true });
|
|
132065
132206
|
}
|
|
132207
|
+
let validatedTask;
|
|
132066
132208
|
try {
|
|
132067
132209
|
const taskId = generateTaskId();
|
|
132068
132210
|
const task = {
|
|
@@ -132078,18 +132220,18 @@ async function handleCreate(args, config, ctx, context) {
|
|
|
132078
132220
|
parentID: validatedArgs.parentID,
|
|
132079
132221
|
threadID: context.sessionID
|
|
132080
132222
|
};
|
|
132081
|
-
|
|
132223
|
+
validatedTask = TaskObjectSchema.parse(task);
|
|
132082
132224
|
writeJsonAtomic(join114(taskDir, `${taskId}.json`), validatedTask);
|
|
132083
|
-
await syncTaskTodoUpdate(ctx, validatedTask, context.sessionID);
|
|
132084
|
-
return JSON.stringify({
|
|
132085
|
-
task: {
|
|
132086
|
-
id: validatedTask.id,
|
|
132087
|
-
subject: validatedTask.subject
|
|
132088
|
-
}
|
|
132089
|
-
});
|
|
132090
132225
|
} finally {
|
|
132091
132226
|
lock.release();
|
|
132092
132227
|
}
|
|
132228
|
+
await syncTaskTodoUpdate(ctx, validatedTask, context.sessionID);
|
|
132229
|
+
return JSON.stringify({
|
|
132230
|
+
task: {
|
|
132231
|
+
id: validatedTask.id,
|
|
132232
|
+
subject: validatedTask.subject
|
|
132233
|
+
}
|
|
132234
|
+
});
|
|
132093
132235
|
} catch (error) {
|
|
132094
132236
|
if (error instanceof Error && error.message.includes("Required")) {
|
|
132095
132237
|
return JSON.stringify({
|
|
@@ -132223,6 +132365,44 @@ Properly managed dependencies enable maximum parallel execution.`,
|
|
|
132223
132365
|
}
|
|
132224
132366
|
});
|
|
132225
132367
|
}
|
|
132368
|
+
function applyTaskUpdate(taskPath, input) {
|
|
132369
|
+
const task = readJsonSafe(taskPath, TaskObjectSchema);
|
|
132370
|
+
if (!task) {
|
|
132371
|
+
return null;
|
|
132372
|
+
}
|
|
132373
|
+
if (input.subject !== undefined) {
|
|
132374
|
+
task.subject = input.subject;
|
|
132375
|
+
}
|
|
132376
|
+
if (input.description !== undefined) {
|
|
132377
|
+
task.description = input.description;
|
|
132378
|
+
}
|
|
132379
|
+
if (input.status !== undefined) {
|
|
132380
|
+
task.status = input.status;
|
|
132381
|
+
}
|
|
132382
|
+
if (input.activeForm !== undefined) {
|
|
132383
|
+
task.activeForm = input.activeForm;
|
|
132384
|
+
}
|
|
132385
|
+
if (input.owner !== undefined) {
|
|
132386
|
+
task.owner = input.owner;
|
|
132387
|
+
}
|
|
132388
|
+
if (input.addBlocks) {
|
|
132389
|
+
task.blocks = [...new Set([...task.blocks, ...input.addBlocks])];
|
|
132390
|
+
}
|
|
132391
|
+
if (input.addBlockedBy) {
|
|
132392
|
+
task.blockedBy = [...new Set([...task.blockedBy, ...input.addBlockedBy])];
|
|
132393
|
+
}
|
|
132394
|
+
if (input.metadata !== undefined) {
|
|
132395
|
+
task.metadata = { ...task.metadata, ...input.metadata };
|
|
132396
|
+
Object.keys(task.metadata).forEach((key) => {
|
|
132397
|
+
if (task.metadata?.[key] === null) {
|
|
132398
|
+
delete task.metadata[key];
|
|
132399
|
+
}
|
|
132400
|
+
});
|
|
132401
|
+
}
|
|
132402
|
+
const updatedTask = TaskObjectSchema.parse(task);
|
|
132403
|
+
writeJsonAtomic(taskPath, updatedTask);
|
|
132404
|
+
return updatedTask;
|
|
132405
|
+
}
|
|
132226
132406
|
async function handleUpdate(args, config, ctx, context) {
|
|
132227
132407
|
try {
|
|
132228
132408
|
const validatedArgs = TaskUpdateInputSchema.parse(args);
|
|
@@ -132231,54 +132411,21 @@ async function handleUpdate(args, config, ctx, context) {
|
|
|
132231
132411
|
return JSON.stringify({ error: "invalid_task_id" });
|
|
132232
132412
|
}
|
|
132233
132413
|
const taskDir = getTaskDir(config);
|
|
132234
|
-
const lock = acquireLock2(taskDir);
|
|
132414
|
+
const lock = await acquireLock2(taskDir);
|
|
132235
132415
|
if (!lock.acquired) {
|
|
132236
|
-
return JSON.stringify({ error: "task_lock_unavailable" });
|
|
132416
|
+
return JSON.stringify({ error: "task_lock_unavailable", retryable: true });
|
|
132237
132417
|
}
|
|
132418
|
+
let updatedTask = null;
|
|
132238
132419
|
try {
|
|
132239
|
-
|
|
132240
|
-
const task = readJsonSafe(taskPath, TaskObjectSchema);
|
|
132241
|
-
if (!task) {
|
|
132242
|
-
return JSON.stringify({ error: "task_not_found" });
|
|
132243
|
-
}
|
|
132244
|
-
if (validatedArgs.subject !== undefined) {
|
|
132245
|
-
task.subject = validatedArgs.subject;
|
|
132246
|
-
}
|
|
132247
|
-
if (validatedArgs.description !== undefined) {
|
|
132248
|
-
task.description = validatedArgs.description;
|
|
132249
|
-
}
|
|
132250
|
-
if (validatedArgs.status !== undefined) {
|
|
132251
|
-
task.status = validatedArgs.status;
|
|
132252
|
-
}
|
|
132253
|
-
if (validatedArgs.activeForm !== undefined) {
|
|
132254
|
-
task.activeForm = validatedArgs.activeForm;
|
|
132255
|
-
}
|
|
132256
|
-
if (validatedArgs.owner !== undefined) {
|
|
132257
|
-
task.owner = validatedArgs.owner;
|
|
132258
|
-
}
|
|
132259
|
-
const addBlocks = args.addBlocks;
|
|
132260
|
-
if (addBlocks) {
|
|
132261
|
-
task.blocks = [...new Set([...task.blocks, ...addBlocks])];
|
|
132262
|
-
}
|
|
132263
|
-
const addBlockedBy = args.addBlockedBy;
|
|
132264
|
-
if (addBlockedBy) {
|
|
132265
|
-
task.blockedBy = [...new Set([...task.blockedBy, ...addBlockedBy])];
|
|
132266
|
-
}
|
|
132267
|
-
if (validatedArgs.metadata !== undefined) {
|
|
132268
|
-
task.metadata = { ...task.metadata, ...validatedArgs.metadata };
|
|
132269
|
-
Object.keys(task.metadata).forEach((key) => {
|
|
132270
|
-
if (task.metadata?.[key] === null) {
|
|
132271
|
-
delete task.metadata[key];
|
|
132272
|
-
}
|
|
132273
|
-
});
|
|
132274
|
-
}
|
|
132275
|
-
const validatedTask = TaskObjectSchema.parse(task);
|
|
132276
|
-
writeJsonAtomic(taskPath, validatedTask);
|
|
132277
|
-
await syncTaskTodoUpdate(ctx, validatedTask, context.sessionID);
|
|
132278
|
-
return JSON.stringify({ task: validatedTask });
|
|
132420
|
+
updatedTask = applyTaskUpdate(join117(taskDir, `${taskId}.json`), validatedArgs);
|
|
132279
132421
|
} finally {
|
|
132280
132422
|
lock.release();
|
|
132281
132423
|
}
|
|
132424
|
+
if (!updatedTask) {
|
|
132425
|
+
return JSON.stringify({ error: "task_not_found" });
|
|
132426
|
+
}
|
|
132427
|
+
await syncTaskTodoUpdate(ctx, updatedTask, context.sessionID);
|
|
132428
|
+
return JSON.stringify({ task: updatedTask });
|
|
132282
132429
|
} catch (error) {
|
|
132283
132430
|
if (error instanceof Error && error.message.includes("Required")) {
|
|
132284
132431
|
return JSON.stringify({
|
|
@@ -134858,6 +135005,7 @@ async function tryFallbackRetry(args) {
|
|
|
134858
135005
|
sessionPermission: task.sessionPermission,
|
|
134859
135006
|
category: task.category,
|
|
134860
135007
|
isUnstableAgent: task.isUnstableAgent,
|
|
135008
|
+
cwd: task.cwd,
|
|
134861
135009
|
onSessionCreated: task.onSessionCreated
|
|
134862
135010
|
};
|
|
134863
135011
|
if (previousSessionID) {
|
|
@@ -137330,6 +137478,7 @@ class BackgroundManager {
|
|
|
137330
137478
|
queuesByKey = new Map;
|
|
137331
137479
|
processingKeys = new Set;
|
|
137332
137480
|
completionTimers = new Map;
|
|
137481
|
+
syncAttachedSessions = new Set;
|
|
137333
137482
|
completedTaskArchive = new Map;
|
|
137334
137483
|
completedTaskSummaries = new Map;
|
|
137335
137484
|
idleDeferralTimers = new Map;
|
|
@@ -137636,6 +137785,7 @@ class BackgroundManager {
|
|
|
137636
137785
|
sessionPermission: input.sessionPermission,
|
|
137637
137786
|
attemptCount: 0,
|
|
137638
137787
|
category: input.category,
|
|
137788
|
+
cwd: input.cwd,
|
|
137639
137789
|
onSessionCreated: input.onSessionCreated
|
|
137640
137790
|
};
|
|
137641
137791
|
const firstAttempt = startAttempt(task, input.model);
|
|
@@ -137750,7 +137900,8 @@ class BackgroundManager {
|
|
|
137750
137900
|
return null;
|
|
137751
137901
|
});
|
|
137752
137902
|
const parentDirectory = parentSession?.data?.directory ?? this.directory;
|
|
137753
|
-
|
|
137903
|
+
const childDirectory = input.cwd ?? parentDirectory;
|
|
137904
|
+
log2(`[background-agent] Parent dir: ${parentSession?.data?.directory}, using: ${childDirectory}`);
|
|
137754
137905
|
const createResult = await this.client.session.create({
|
|
137755
137906
|
body: {
|
|
137756
137907
|
parentID: input.parentSessionId,
|
|
@@ -137765,7 +137916,7 @@ class BackgroundManager {
|
|
|
137765
137916
|
} : {}
|
|
137766
137917
|
},
|
|
137767
137918
|
query: {
|
|
137768
|
-
directory:
|
|
137919
|
+
directory: childDirectory
|
|
137769
137920
|
}
|
|
137770
137921
|
});
|
|
137771
137922
|
if (createResult.error) {
|
|
@@ -137816,7 +137967,7 @@ class BackgroundManager {
|
|
|
137816
137967
|
task.concurrencyGroup = concurrencyKey;
|
|
137817
137968
|
if (task.retryNotification) {
|
|
137818
137969
|
const attemptNumber = boundAttempt.attemptNumber;
|
|
137819
|
-
const retrySessionUrl = buildLocalSessionUrl(
|
|
137970
|
+
const retrySessionUrl = buildLocalSessionUrl(childDirectory, sessionID);
|
|
137820
137971
|
const previousAttempt = getPreviousAttempt(task, boundAttempt.attemptId);
|
|
137821
137972
|
const failedSessionID = previousAttempt?.sessionId ?? task.retryNotification.previousSessionID;
|
|
137822
137973
|
const failedSessionLine = failedSessionID ? `
|
|
@@ -137901,7 +138052,7 @@ The fallback retry session is now created and can be inspected directly.
|
|
|
137901
138052
|
promptWithRetryInDirectory(this.client, {
|
|
137902
138053
|
path: { id: sessionID },
|
|
137903
138054
|
body: promptBody
|
|
137904
|
-
},
|
|
138055
|
+
}, childDirectory).catch(async (error) => {
|
|
137905
138056
|
if (isAgentNotFoundError(error) && input.agent !== FALLBACK_AGENT) {
|
|
137906
138057
|
log2("[background-agent] Agent not found, retrying with fallback agent", {
|
|
137907
138058
|
original: input.agent,
|
|
@@ -137927,7 +138078,7 @@ The fallback retry session is now created and can be inspected directly.
|
|
|
137927
138078
|
await promptWithRetryInDirectory(this.client, {
|
|
137928
138079
|
path: { id: sessionID },
|
|
137929
138080
|
body: fallbackBody
|
|
137930
|
-
},
|
|
138081
|
+
}, childDirectory);
|
|
137931
138082
|
task.agent = FALLBACK_AGENT;
|
|
137932
138083
|
return;
|
|
137933
138084
|
} catch (retryError) {
|
|
@@ -138057,6 +138208,19 @@ The fallback retry session is now created and can be inspected directly.
|
|
|
138057
138208
|
}
|
|
138058
138209
|
return;
|
|
138059
138210
|
}
|
|
138211
|
+
attachSyncContinuation(sessionID) {
|
|
138212
|
+
this.syncAttachedSessions.add(sessionID);
|
|
138213
|
+
return () => {
|
|
138214
|
+
if (!this.syncAttachedSessions.delete(sessionID))
|
|
138215
|
+
return;
|
|
138216
|
+
const task = this.findBySession(sessionID);
|
|
138217
|
+
if (!task || !TERMINAL_BACKGROUND_TASK_STATUSES.has(task.status))
|
|
138218
|
+
return;
|
|
138219
|
+
if (this.completionTimers.has(task.id))
|
|
138220
|
+
return;
|
|
138221
|
+
this.scheduleTaskRemoval(task.id);
|
|
138222
|
+
};
|
|
138223
|
+
}
|
|
138060
138224
|
resolveTaskAttemptBySession(sessionID) {
|
|
138061
138225
|
const task = this.findBySession(sessionID);
|
|
138062
138226
|
if (!task) {
|
|
@@ -138247,7 +138411,7 @@ The fallback retry session is now created and can be inspected directly.
|
|
|
138247
138411
|
})(),
|
|
138248
138412
|
parts: [createInternalAgentTextPart(input.prompt)]
|
|
138249
138413
|
},
|
|
138250
|
-
query: { directory: this.directory }
|
|
138414
|
+
query: { directory: existingTask.cwd ?? this.directory }
|
|
138251
138415
|
}
|
|
138252
138416
|
}).then((promptResult) => {
|
|
138253
138417
|
if (promptResult.status === "failed") {
|
|
@@ -138984,6 +139148,8 @@ The task was re-queued on a fallback model after a retryable failure.
|
|
|
138984
139148
|
const task = this.tasks.get(taskId);
|
|
138985
139149
|
if (!task)
|
|
138986
139150
|
return;
|
|
139151
|
+
if (task.sessionId && this.syncAttachedSessions.has(task.sessionId))
|
|
139152
|
+
return;
|
|
138987
139153
|
if (task.parentSessionId) {
|
|
138988
139154
|
const siblings = this.getTasksByParentSession(task.parentSessionId);
|
|
138989
139155
|
const runningOrPendingSiblings = siblings.filter((sibling) => sibling.id !== taskId && (sibling.status === "running" || sibling.status === "pending"));
|
|
@@ -139622,6 +139788,7 @@ The task was re-queued on a fallback model after a retryable failure.
|
|
|
139622
139788
|
clearTimeout(timer);
|
|
139623
139789
|
}
|
|
139624
139790
|
this.completionTimers.clear();
|
|
139791
|
+
this.syncAttachedSessions.clear();
|
|
139625
139792
|
for (const timer of this.idleDeferralTimers.values()) {
|
|
139626
139793
|
clearTimeout(timer);
|
|
139627
139794
|
}
|
|
@@ -169753,6 +169920,7 @@ async function createTeamRun(spec, leadSessionId, ctx, config, bgMgr, tmuxMgr, o
|
|
|
169753
169920
|
skillContent: resolvedMember.systemContent,
|
|
169754
169921
|
category: member.kind === "category" ? member.category : undefined,
|
|
169755
169922
|
sessionPermission: QUESTION_DENIED_SESSION_PERMISSION,
|
|
169923
|
+
...resource.worktreePath ? { cwd: resource.worktreePath } : {},
|
|
169756
169924
|
onSessionCreated: async (sessionId) => {
|
|
169757
169925
|
registerTeamSession(sessionId, {
|
|
169758
169926
|
teamRunId: runtimeState.teamRunId,
|
|
@@ -171589,6 +171757,7 @@ init_logger2();
|
|
|
171589
171757
|
// packages/omo-opencode/src/plugin/stop-continuation.ts
|
|
171590
171758
|
function stopContinuation(args) {
|
|
171591
171759
|
const { directory, hooks, sessionID } = args;
|
|
171760
|
+
hooks.keywordDetector?.clearSession?.(sessionID);
|
|
171592
171761
|
hooks.stopContinuationGuard?.stop?.(sessionID);
|
|
171593
171762
|
hooks.todoContinuationEnforcer?.cancelAllCountdowns();
|
|
171594
171763
|
hooks.goal?.clearGoal(sessionID);
|
|
@@ -171928,9 +172097,16 @@ function toCanonicalModel(model) {
|
|
|
171928
172097
|
return model.id;
|
|
171929
172098
|
return `${model.providerID}/${model.id}`;
|
|
171930
172099
|
}
|
|
171931
|
-
function createSystemTransformHandler(defaultMode, getUltraworkMessage) {
|
|
172100
|
+
function createSystemTransformHandler(defaultMode, getUltraworkMessage, ultraworkRestoration) {
|
|
171932
172101
|
return async (input, output) => {
|
|
171933
172102
|
reconcileSisyphusRuntimePrompt(output.system, toCanonicalModel(input.model));
|
|
172103
|
+
const restoredGuidance = input.sessionID ? ultraworkRestoration?.getSystemTransformGuidance?.(input.sessionID, input.model?.id) : undefined;
|
|
172104
|
+
if (restoredGuidance) {
|
|
172105
|
+
if (!output.system.some((part) => part.includes(ULTRAWORK_MODE_TAG))) {
|
|
172106
|
+
output.system.push(restoredGuidance);
|
|
172107
|
+
}
|
|
172108
|
+
return;
|
|
172109
|
+
}
|
|
171934
172110
|
if (!defaultMode?.ultrawork || !getUltraworkMessage)
|
|
171935
172111
|
return;
|
|
171936
172112
|
if (output.system.some((part) => part.includes(ULTRAWORK_MODE_TAG)))
|
|
@@ -172103,6 +172279,7 @@ function createEventHookDispatcher(hooks, runEventHookSafely) {
|
|
|
172103
172279
|
await runEventHookSafely("directoryAgentsInjector", hooks.directoryAgentsInjector?.event, input);
|
|
172104
172280
|
await runEventHookSafely("directoryReadmeInjector", hooks.directoryReadmeInjector?.event, input);
|
|
172105
172281
|
await runEventHookSafely("rulesInjector", hooks.rulesInjector?.event, input);
|
|
172282
|
+
await runEventHookSafely("keywordDetector", hooks.keywordDetector?.event, input);
|
|
172106
172283
|
await runEventHookSafely("hephaestusAgentsMdInjector", hooks.hephaestusAgentsMdInjector?.event, input);
|
|
172107
172284
|
await runEventHookSafely("thinkMode", hooks.thinkMode?.event, input);
|
|
172108
172285
|
await runEventHookSafely("anthropicContextWindowLimitRecovery", hooks.anthropicContextWindowLimitRecovery?.event, input);
|
|
@@ -173663,7 +173840,7 @@ function createPluginInterface(args) {
|
|
|
173663
173840
|
"experimental.chat.messages.transform": createMessagesTransformHandler({
|
|
173664
173841
|
hooks
|
|
173665
173842
|
}),
|
|
173666
|
-
"experimental.chat.system.transform": createSystemTransformHandler(pluginConfig.default_mode, getUltraworkMessage),
|
|
173843
|
+
"experimental.chat.system.transform": createSystemTransformHandler(pluginConfig.default_mode, getUltraworkMessage, hooks.keywordDetector),
|
|
173667
173844
|
config: managers.configHandler,
|
|
173668
173845
|
event: createEventHandler2({
|
|
173669
173846
|
ctx,
|
|
@@ -174410,7 +174587,7 @@ async function killTargets(targets, options, config) {
|
|
|
174410
174587
|
const terminated = await safelyTerminate(target.pid, context);
|
|
174411
174588
|
if (!terminated)
|
|
174412
174589
|
continue;
|
|
174413
|
-
await
|
|
174590
|
+
await delay6(options.graceMs ?? DEFAULT_GRACE_MS);
|
|
174414
174591
|
if (!await context.killer.isAlive(target.pid)) {
|
|
174415
174592
|
killed.push(target);
|
|
174416
174593
|
continue;
|
|
@@ -174469,7 +174646,7 @@ function writeSweepStamp(stampFile, nowMs) {
|
|
|
174469
174646
|
const stampDate = new Date(nowMs);
|
|
174470
174647
|
utimesSync(stampFile, stampDate, stampDate);
|
|
174471
174648
|
}
|
|
174472
|
-
function
|
|
174649
|
+
function delay6(ms) {
|
|
174473
174650
|
if (ms <= 0)
|
|
174474
174651
|
return Promise.resolve();
|
|
174475
174652
|
return new Promise((resolvePromise) => {
|