oh-my-opencode 4.11.1 → 4.12.0
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/.agents/skills/codex-qa/scripts/lib/app-server-client.mjs +132 -82
- package/.agents/skills/codex-qa/scripts/lib/app-server-client.test.js +48 -0
- package/.agents/skills/opencode-qa/scripts/serve-wake-split-probe.sh +361 -84
- package/.agents/skills/work-with-pr/SKILL.md +19 -5
- package/.opencode/skills/work-with-pr/SKILL.md +19 -5
- package/dist/agents/types.d.ts +7 -6
- package/dist/cli/index.js +438 -306
- package/dist/cli-node/index.js +438 -306
- package/dist/features/background-agent/parent-wake-flush-runner.d.ts +1 -0
- package/dist/features/background-agent/parent-wake-history-state.d.ts +1 -0
- package/dist/features/background-agent/parent-wake-session-history.d.ts +1 -47
- package/dist/features/background-agent/parent-wake-session-message.d.ts +47 -0
- package/dist/index.js +245 -69
- package/dist/plugin/tool-execute-before.d.ts +2 -0
- package/dist/plugin-handlers/plugin-components-loader.d.ts +1 -0
- package/dist/skills/ulw-plan/SKILL.md +2 -1
- package/dist/skills/ulw-plan/references/full-workflow.md +1 -1
- package/dist/skills/ulw-plan/references/intent-clear.md +2 -2
- package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -2
- package/dist/tools/delegate-task/sync-session-turns.d.ts +3 -0
- package/dist/tui.js +16 -7
- package/package.json +13 -13
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +22 -2
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +25 -9
- 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/codegraph/dist/cli.js +10 -3
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +9 -2
- package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +7 -2
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +2 -1
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +9 -9
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +94 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +33 -0
- 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/comment-checker/test/package-smoke.test.ts +2 -71
- 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/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/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +26 -104
- 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/rules/test/package-smoke.test.ts +12 -92
- package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +157 -234
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +227 -15
- package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +62 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +34 -3
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +139 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +111 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-state.mjs +250 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +220 -0
- 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/test-support/package-smoke-fixture.ts +158 -0
- 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/ultrawork/skills/ulw-plan/SKILL.md +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +76 -49
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +17 -0
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +17 -0
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +17 -0
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +17 -0
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +17 -0
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +16 -0
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +16 -0
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +16 -0
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +16 -0
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +16 -0
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +17 -0
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +16 -0
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +16 -0
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +16 -0
- package/packages/omo-codex/plugin/package-lock.json +12 -22
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +14 -11
- package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +15 -4
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +37 -0
- package/packages/omo-codex/plugin/skills/ast-grep/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/comment-checker/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/debugging/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/frontend/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/git-master/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/init-deep/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/lcx-doctor/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/lsp/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/lsp-setup/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/programming/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/refactor/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/remove-ai-slops/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/review-work/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/rules/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/teammode/SKILL.md +139 -0
- package/packages/omo-codex/plugin/skills/teammode/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +111 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-state.mjs +250 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +220 -0
- package/packages/omo-codex/plugin/skills/ultraresearch/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -2
- package/packages/omo-codex/plugin/skills/visual-qa/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +34 -33
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +5 -2
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +13 -0
- package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +14 -6
- package/packages/omo-codex/plugin/test/bootstrap-ps-guard.test.mjs +7 -3
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +3 -3
- package/packages/omo-codex/plugin/test/display-metadata.test.mjs +83 -0
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +30 -19
- package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +3 -3
- package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +6 -6
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -0
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +9 -4
- package/packages/omo-codex/plugin/test/teammode-safety-fixture.mjs +88 -0
- package/packages/omo-codex/plugin/test/teammode-safety.test.mjs +240 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +385 -206
- package/packages/omo-codex/scripts/install-hook-targets.test.mjs +93 -0
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +2 -2
- package/packages/omo-codex/scripts/install-local-bun-global-update.test.mjs +63 -0
- package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +109 -1
- package/packages/omo-codex/scripts/install-local.mjs +1 -0
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -2
- package/packages/omo-codex/plugin/hooks/hooks.json +0 -214
|
@@ -21,6 +21,7 @@ export declare class ParentWakeFlushRunner {
|
|
|
21
21
|
private hasRecentParentSessionActivity;
|
|
22
22
|
private isUserMessageInProgress;
|
|
23
23
|
private shouldDeferParentWakeForSessionHistory;
|
|
24
|
+
private confirmParentWakeStillSafeForReply;
|
|
24
25
|
private requeueWake;
|
|
25
26
|
}
|
|
26
27
|
export {};
|
|
@@ -2,4 +2,5 @@ import type { PendingParentWake } from "./parent-wake-dedupe";
|
|
|
2
2
|
export declare function latestAssistantTurnIsCompletedEmptyNoProgress(messages: readonly unknown[]): boolean;
|
|
3
3
|
export declare function latestAssistantTurnHasToolBlock(messages: readonly unknown[]): boolean;
|
|
4
4
|
export declare function latestAssistantTurnHasFreshToolActivity(messages: readonly unknown[], now: number, maxAgeMs: number): boolean;
|
|
5
|
+
export declare function latestAssistantTurnHasStaleUnknownSubstantiveOutput(messages: readonly unknown[], now: number, maxAgeMs: number): boolean;
|
|
5
6
|
export declare function createEmptyAssistantTurnRetryDedupeKey(wake: PendingParentWake): string;
|
|
@@ -1,51 +1,5 @@
|
|
|
1
1
|
import type { PendingParentWake } from "./parent-wake-dedupe";
|
|
2
|
-
|
|
3
|
-
readonly info?: {
|
|
4
|
-
readonly role?: string;
|
|
5
|
-
readonly finish?: string;
|
|
6
|
-
readonly error?: unknown;
|
|
7
|
-
readonly time?: {
|
|
8
|
-
readonly created?: unknown;
|
|
9
|
-
readonly updated?: unknown;
|
|
10
|
-
readonly completed?: unknown;
|
|
11
|
-
readonly start?: unknown;
|
|
12
|
-
readonly end?: unknown;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
readonly role?: string;
|
|
16
|
-
readonly finish?: string;
|
|
17
|
-
readonly error?: unknown;
|
|
18
|
-
readonly time?: {
|
|
19
|
-
readonly created?: unknown;
|
|
20
|
-
readonly updated?: unknown;
|
|
21
|
-
readonly completed?: unknown;
|
|
22
|
-
readonly start?: unknown;
|
|
23
|
-
readonly end?: unknown;
|
|
24
|
-
};
|
|
25
|
-
readonly parts?: readonly {
|
|
26
|
-
readonly type?: string;
|
|
27
|
-
readonly text?: string;
|
|
28
|
-
readonly synthetic?: boolean;
|
|
29
|
-
readonly content?: unknown;
|
|
30
|
-
readonly time?: {
|
|
31
|
-
readonly created?: unknown;
|
|
32
|
-
readonly updated?: unknown;
|
|
33
|
-
readonly completed?: unknown;
|
|
34
|
-
readonly start?: unknown;
|
|
35
|
-
readonly end?: unknown;
|
|
36
|
-
};
|
|
37
|
-
readonly state?: {
|
|
38
|
-
readonly status?: unknown;
|
|
39
|
-
readonly time?: {
|
|
40
|
-
readonly created?: unknown;
|
|
41
|
-
readonly updated?: unknown;
|
|
42
|
-
readonly completed?: unknown;
|
|
43
|
-
readonly start?: unknown;
|
|
44
|
-
readonly end?: unknown;
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
}[];
|
|
48
|
-
};
|
|
2
|
+
import type { ParentWakeSessionMessage } from "./parent-wake-session-message";
|
|
49
3
|
export type ToolWaitDeferralDecision = {
|
|
50
4
|
readonly defer: boolean;
|
|
51
5
|
readonly skipPromptGateToolStateCheck: boolean;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type ParentWakeSessionMessage = {
|
|
2
|
+
readonly info?: {
|
|
3
|
+
readonly role?: string;
|
|
4
|
+
readonly finish?: string;
|
|
5
|
+
readonly error?: unknown;
|
|
6
|
+
readonly time?: {
|
|
7
|
+
readonly created?: unknown;
|
|
8
|
+
readonly updated?: unknown;
|
|
9
|
+
readonly completed?: unknown;
|
|
10
|
+
readonly start?: unknown;
|
|
11
|
+
readonly end?: unknown;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
readonly role?: string;
|
|
15
|
+
readonly finish?: string;
|
|
16
|
+
readonly error?: unknown;
|
|
17
|
+
readonly time?: {
|
|
18
|
+
readonly created?: unknown;
|
|
19
|
+
readonly updated?: unknown;
|
|
20
|
+
readonly completed?: unknown;
|
|
21
|
+
readonly start?: unknown;
|
|
22
|
+
readonly end?: unknown;
|
|
23
|
+
};
|
|
24
|
+
readonly parts?: readonly {
|
|
25
|
+
readonly type?: string;
|
|
26
|
+
readonly text?: string;
|
|
27
|
+
readonly synthetic?: boolean;
|
|
28
|
+
readonly content?: unknown;
|
|
29
|
+
readonly time?: {
|
|
30
|
+
readonly created?: unknown;
|
|
31
|
+
readonly updated?: unknown;
|
|
32
|
+
readonly completed?: unknown;
|
|
33
|
+
readonly start?: unknown;
|
|
34
|
+
readonly end?: unknown;
|
|
35
|
+
};
|
|
36
|
+
readonly state?: {
|
|
37
|
+
readonly status?: unknown;
|
|
38
|
+
readonly time?: {
|
|
39
|
+
readonly created?: unknown;
|
|
40
|
+
readonly updated?: unknown;
|
|
41
|
+
readonly completed?: unknown;
|
|
42
|
+
readonly start?: unknown;
|
|
43
|
+
readonly end?: unknown;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}[];
|
|
47
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -20989,6 +20989,11 @@ function isClaudeOpus47OrLaterModel(model) {
|
|
|
20989
20989
|
return false;
|
|
20990
20990
|
return major > 4 || major === 4 && minor >= 7;
|
|
20991
20991
|
}
|
|
20992
|
+
var CLAUDE_FABLE_OR_MYTHOS_RE = /claude-(?:fable|mythos)-(?:\d+|preview)/;
|
|
20993
|
+
function isClaudeFableOrMythosModel(model) {
|
|
20994
|
+
const modelName = extractModelName(model).toLowerCase().replaceAll(".", "-");
|
|
20995
|
+
return CLAUDE_FABLE_OR_MYTHOS_RE.test(modelName);
|
|
20996
|
+
}
|
|
20992
20997
|
function isKimiK2Model(model) {
|
|
20993
20998
|
const modelName = extractModelName(model).toLowerCase();
|
|
20994
20999
|
if (modelName.includes("kimi"))
|
|
@@ -23386,7 +23391,7 @@ var KIMI_CATEGORIES = [
|
|
|
23386
23391
|
// packages/omo-opencode/src/agents/types.ts
|
|
23387
23392
|
var CLAUDE_THINKING_BUDGET_TOKENS = 32000;
|
|
23388
23393
|
function buildClaudeThinkingConfig(model) {
|
|
23389
|
-
if (isClaudeOpus47OrLaterModel(model)) {
|
|
23394
|
+
if (isClaudeOpus47OrLaterModel(model) || isClaudeFableOrMythosModel(model)) {
|
|
23390
23395
|
return {};
|
|
23391
23396
|
}
|
|
23392
23397
|
return { thinking: { type: "enabled", budgetTokens: CLAUDE_THINKING_BUDGET_TOKENS } };
|
|
@@ -69992,7 +69997,7 @@ async function probe(registration) {
|
|
|
69992
69997
|
registration.available = false;
|
|
69993
69998
|
return false;
|
|
69994
69999
|
}
|
|
69995
|
-
const probeUrl = new URL("/
|
|
70000
|
+
const probeUrl = new URL("/global/health", registration.serverUrl);
|
|
69996
70001
|
const authHeader = getServerBasicAuthHeader();
|
|
69997
70002
|
const headers = authHeader ? { Authorization: authHeader } : {};
|
|
69998
70003
|
try {
|
|
@@ -70026,12 +70031,17 @@ async function probe(registration) {
|
|
|
70026
70031
|
return false;
|
|
70027
70032
|
}
|
|
70028
70033
|
}
|
|
70029
|
-
function
|
|
70030
|
-
|
|
70034
|
+
function getFreshProbeAvailability(registration) {
|
|
70035
|
+
const available = registration.available;
|
|
70036
|
+
if (available === undefined || Date.now() - registration.probeTimestamp >= PROBE_TTL_MS) {
|
|
70037
|
+
return;
|
|
70038
|
+
}
|
|
70039
|
+
return available;
|
|
70031
70040
|
}
|
|
70032
70041
|
async function resolveAvailability(registration) {
|
|
70033
|
-
|
|
70034
|
-
|
|
70042
|
+
const freshAvailability = getFreshProbeAvailability(registration);
|
|
70043
|
+
if (freshAvailability !== undefined) {
|
|
70044
|
+
return freshAvailability;
|
|
70035
70045
|
}
|
|
70036
70046
|
if (!registration.inFlightProbe) {
|
|
70037
70047
|
registration.inFlightProbe = probe(registration).finally(() => {
|
|
@@ -70066,10 +70076,11 @@ function tryResolveDispatchClientSync2(client3, sessionID) {
|
|
|
70066
70076
|
if (!registration.serverUrl) {
|
|
70067
70077
|
return { client: client3, route: "in-process", reason: "unavailable" };
|
|
70068
70078
|
}
|
|
70069
|
-
|
|
70079
|
+
const freshAvailability = getFreshProbeAvailability(registration);
|
|
70080
|
+
if (freshAvailability === undefined) {
|
|
70070
70081
|
return;
|
|
70071
70082
|
}
|
|
70072
|
-
if (!
|
|
70083
|
+
if (!freshAvailability) {
|
|
70073
70084
|
return { client: client3, route: "in-process", reason: "unavailable" };
|
|
70074
70085
|
}
|
|
70075
70086
|
const resolvedLiveClient = getOrBuildLiveClient(registration);
|
|
@@ -70084,6 +70095,9 @@ async function resolveDispatchClient2(client3, sessionID) {
|
|
|
70084
70095
|
return syncResult;
|
|
70085
70096
|
}
|
|
70086
70097
|
const registration = registrations.get(client3);
|
|
70098
|
+
if (!registration) {
|
|
70099
|
+
return { client: client3, route: "in-process", reason: "identity" };
|
|
70100
|
+
}
|
|
70087
70101
|
const isAvailable = await resolveAvailability(registration);
|
|
70088
70102
|
if (!isAvailable) {
|
|
70089
70103
|
return { client: client3, route: "in-process", reason: "unavailable" };
|
|
@@ -80669,7 +80683,7 @@ function getCachedVersion(options = {}) {
|
|
|
80669
80683
|
// package.json
|
|
80670
80684
|
var package_default = {
|
|
80671
80685
|
name: "oh-my-opencode",
|
|
80672
|
-
version: "4.
|
|
80686
|
+
version: "4.12.0",
|
|
80673
80687
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
80674
80688
|
main: "./dist/index.js",
|
|
80675
80689
|
types: "dist/index.d.ts",
|
|
@@ -80839,18 +80853,18 @@ var package_default = {
|
|
|
80839
80853
|
typescript: "^6.0.3"
|
|
80840
80854
|
},
|
|
80841
80855
|
optionalDependencies: {
|
|
80842
|
-
"oh-my-opencode-darwin-arm64": "4.
|
|
80843
|
-
"oh-my-opencode-darwin-x64": "4.
|
|
80844
|
-
"oh-my-opencode-darwin-x64-baseline": "4.
|
|
80845
|
-
"oh-my-opencode-linux-arm64": "4.
|
|
80846
|
-
"oh-my-opencode-linux-arm64-musl": "4.
|
|
80847
|
-
"oh-my-opencode-linux-x64": "4.
|
|
80848
|
-
"oh-my-opencode-linux-x64-baseline": "4.
|
|
80849
|
-
"oh-my-opencode-linux-x64-musl": "4.
|
|
80850
|
-
"oh-my-opencode-linux-x64-musl-baseline": "4.
|
|
80851
|
-
"oh-my-opencode-windows-arm64": "4.
|
|
80852
|
-
"oh-my-opencode-windows-x64": "4.
|
|
80853
|
-
"oh-my-opencode-windows-x64-baseline": "4.
|
|
80856
|
+
"oh-my-opencode-darwin-arm64": "4.12.0",
|
|
80857
|
+
"oh-my-opencode-darwin-x64": "4.12.0",
|
|
80858
|
+
"oh-my-opencode-darwin-x64-baseline": "4.12.0",
|
|
80859
|
+
"oh-my-opencode-linux-arm64": "4.12.0",
|
|
80860
|
+
"oh-my-opencode-linux-arm64-musl": "4.12.0",
|
|
80861
|
+
"oh-my-opencode-linux-x64": "4.12.0",
|
|
80862
|
+
"oh-my-opencode-linux-x64-baseline": "4.12.0",
|
|
80863
|
+
"oh-my-opencode-linux-x64-musl": "4.12.0",
|
|
80864
|
+
"oh-my-opencode-linux-x64-musl-baseline": "4.12.0",
|
|
80865
|
+
"oh-my-opencode-windows-arm64": "4.12.0",
|
|
80866
|
+
"oh-my-opencode-windows-x64": "4.12.0",
|
|
80867
|
+
"oh-my-opencode-windows-x64-baseline": "4.12.0"
|
|
80854
80868
|
},
|
|
80855
80869
|
overrides: {
|
|
80856
80870
|
hono: "^4.12.18",
|
|
@@ -113764,10 +113778,60 @@ function getTimingConfig() {
|
|
|
113764
113778
|
};
|
|
113765
113779
|
}
|
|
113766
113780
|
|
|
113767
|
-
// packages/omo-opencode/src/tools/delegate-task/sync-session-
|
|
113768
|
-
init_logger2();
|
|
113781
|
+
// packages/omo-opencode/src/tools/delegate-task/sync-session-turns.ts
|
|
113769
113782
|
var NON_TERMINAL_FINISH_REASONS = new Set(["tool-calls", "unknown"]);
|
|
113770
113783
|
var PENDING_TOOL_PART_TYPES = new Set(["tool", "tool_use", "tool-call"]);
|
|
113784
|
+
var ALL_BACKGROUND_TASKS_COMPLETE_MARKER = "[ALL BACKGROUND TASKS COMPLETE]";
|
|
113785
|
+
function getTextParts2(message) {
|
|
113786
|
+
return (message.parts ?? []).filter((part) => part.type === "text").map((part) => part.text ?? "").join(`
|
|
113787
|
+
`);
|
|
113788
|
+
}
|
|
113789
|
+
function isInternalAllCompleteWake(message) {
|
|
113790
|
+
return isTerminalNoReplyUserMessage(message) && getTextParts2(message).includes(ALL_BACKGROUND_TASKS_COMPLETE_MARKER);
|
|
113791
|
+
}
|
|
113792
|
+
function getLastSessionTurns(messages) {
|
|
113793
|
+
let lastRelevantUser;
|
|
113794
|
+
let lastAssistant;
|
|
113795
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
113796
|
+
const msg = messages[i];
|
|
113797
|
+
if (msg === undefined)
|
|
113798
|
+
continue;
|
|
113799
|
+
if (!lastAssistant && msg.info?.role === "assistant")
|
|
113800
|
+
lastAssistant = msg;
|
|
113801
|
+
if (!lastRelevantUser && msg.info?.role === "user" && !isInternalAllCompleteWake(msg)) {
|
|
113802
|
+
lastRelevantUser = msg;
|
|
113803
|
+
}
|
|
113804
|
+
if (lastRelevantUser && lastAssistant)
|
|
113805
|
+
break;
|
|
113806
|
+
}
|
|
113807
|
+
return { lastAssistant, lastRelevantUser };
|
|
113808
|
+
}
|
|
113809
|
+
function isSessionComplete(messages) {
|
|
113810
|
+
const { lastAssistant, lastRelevantUser } = getLastSessionTurns(messages);
|
|
113811
|
+
if (!lastAssistant?.info?.finish)
|
|
113812
|
+
return false;
|
|
113813
|
+
if (NON_TERMINAL_FINISH_REASONS.has(lastAssistant.info.finish))
|
|
113814
|
+
return false;
|
|
113815
|
+
if (lastAssistant.parts?.some((part) => part.type && PENDING_TOOL_PART_TYPES.has(part.type)))
|
|
113816
|
+
return false;
|
|
113817
|
+
if (!lastRelevantUser?.info?.id || !lastAssistant?.info?.id)
|
|
113818
|
+
return false;
|
|
113819
|
+
return lastRelevantUser.info.id < lastAssistant.info.id;
|
|
113820
|
+
}
|
|
113821
|
+
function getTerminalSessionError(messages) {
|
|
113822
|
+
const { lastAssistant, lastRelevantUser } = getLastSessionTurns(messages);
|
|
113823
|
+
if (lastRelevantUser?.info?.id && lastAssistant?.info?.id && lastAssistant.info.id <= lastRelevantUser.info.id) {
|
|
113824
|
+
return null;
|
|
113825
|
+
}
|
|
113826
|
+
if (!lastAssistant?.info || !("error" in lastAssistant.info)) {
|
|
113827
|
+
return null;
|
|
113828
|
+
}
|
|
113829
|
+
const errorMessage = extractErrorMessage(lastAssistant.info.error);
|
|
113830
|
+
return errorMessage && errorMessage.length > 0 ? errorMessage : "Session error";
|
|
113831
|
+
}
|
|
113832
|
+
|
|
113833
|
+
// packages/omo-opencode/src/tools/delegate-task/sync-session-poller.ts
|
|
113834
|
+
init_logger2();
|
|
113771
113835
|
var ACTIVE_SESSION_STATUSES2 = new Set(["busy", "retry", "running"]);
|
|
113772
113836
|
var CHILD_WAKE_GRACE_MS = 5000;
|
|
113773
113837
|
function wait(milliseconds) {
|
|
@@ -113794,40 +113858,6 @@ async function fetchSessionMessages(client3, sessionID) {
|
|
|
113794
113858
|
const rawData = messagesResult?.data ?? messagesResult;
|
|
113795
113859
|
return Array.isArray(rawData) ? rawData : [];
|
|
113796
113860
|
}
|
|
113797
|
-
function getTerminalSessionError(messages) {
|
|
113798
|
-
const lastAssistant = [...messages].reverse().find((msg) => msg.info?.role === "assistant");
|
|
113799
|
-
const lastUser = [...messages].reverse().find((msg) => msg.info?.role === "user");
|
|
113800
|
-
if (lastUser?.info?.id && lastAssistant?.info?.id && lastAssistant.info.id <= lastUser.info.id) {
|
|
113801
|
-
return null;
|
|
113802
|
-
}
|
|
113803
|
-
if (!lastAssistant?.info || !("error" in lastAssistant.info)) {
|
|
113804
|
-
return null;
|
|
113805
|
-
}
|
|
113806
|
-
const errorMessage = extractErrorMessage(lastAssistant.info.error);
|
|
113807
|
-
return errorMessage && errorMessage.length > 0 ? errorMessage : "Session error";
|
|
113808
|
-
}
|
|
113809
|
-
function isSessionComplete(messages) {
|
|
113810
|
-
let lastUser;
|
|
113811
|
-
let lastAssistant;
|
|
113812
|
-
for (let i = messages.length - 1;i >= 0; i--) {
|
|
113813
|
-
const msg = messages[i];
|
|
113814
|
-
if (!lastAssistant && msg.info?.role === "assistant")
|
|
113815
|
-
lastAssistant = msg;
|
|
113816
|
-
if (!lastUser && msg.info?.role === "user")
|
|
113817
|
-
lastUser = msg;
|
|
113818
|
-
if (lastUser && lastAssistant)
|
|
113819
|
-
break;
|
|
113820
|
-
}
|
|
113821
|
-
if (!lastAssistant?.info?.finish)
|
|
113822
|
-
return false;
|
|
113823
|
-
if (NON_TERMINAL_FINISH_REASONS.has(lastAssistant.info.finish))
|
|
113824
|
-
return false;
|
|
113825
|
-
if (lastAssistant.parts?.some((part) => part.type && PENDING_TOOL_PART_TYPES.has(part.type)))
|
|
113826
|
-
return false;
|
|
113827
|
-
if (!lastUser?.info?.id || !lastAssistant?.info?.id)
|
|
113828
|
-
return false;
|
|
113829
|
-
return lastUser.info.id < lastAssistant.info.id;
|
|
113830
|
-
}
|
|
113831
113861
|
var DEFAULT_MAX_ASSISTANT_TURNS = 300;
|
|
113832
113862
|
async function pollSyncSession(ctx, client3, input, timeoutMs) {
|
|
113833
113863
|
const syncTiming = getTimingConfig();
|
|
@@ -113870,11 +113900,12 @@ async function pollSyncSession(ctx, client3, input, timeoutMs) {
|
|
|
113870
113900
|
finalMessages = await fetchSessionMessages(client3, input.sessionID);
|
|
113871
113901
|
break;
|
|
113872
113902
|
} catch (error) {
|
|
113903
|
+
const errorMessage = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
113873
113904
|
log2("[task] Final messages fetch failed after abort, retrying", {
|
|
113874
113905
|
sessionID: input.sessionID,
|
|
113875
113906
|
attempt,
|
|
113876
113907
|
maxAttempts: abortFetchAttempts,
|
|
113877
|
-
error:
|
|
113908
|
+
error: errorMessage
|
|
113878
113909
|
});
|
|
113879
113910
|
if (attempt < abortFetchAttempts) {
|
|
113880
113911
|
await wait(syncTiming.POLL_INTERVAL_MS);
|
|
@@ -113924,7 +113955,8 @@ Session ID: ${input.sessionID}`;
|
|
|
113924
113955
|
try {
|
|
113925
113956
|
messages = await fetchSessionMessages(client3, input.sessionID);
|
|
113926
113957
|
} catch (error) {
|
|
113927
|
-
|
|
113958
|
+
const errorMessage = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
113959
|
+
log2("[task] Poll messages fetch failed, retrying", { sessionID: input.sessionID, error: errorMessage });
|
|
113928
113960
|
continue;
|
|
113929
113961
|
}
|
|
113930
113962
|
if (input.anchorMessageCount !== undefined && messages.length <= input.anchorMessageCount) {
|
|
@@ -119356,9 +119388,38 @@ function timestampFromUnknown(value) {
|
|
|
119356
119388
|
}
|
|
119357
119389
|
return;
|
|
119358
119390
|
}
|
|
119391
|
+
function latestTimestamp(...values) {
|
|
119392
|
+
let latest;
|
|
119393
|
+
for (const value of values) {
|
|
119394
|
+
const timestamp = timestampFromUnknown(value);
|
|
119395
|
+
if (timestamp === undefined) {
|
|
119396
|
+
continue;
|
|
119397
|
+
}
|
|
119398
|
+
if (latest === undefined || timestamp > latest) {
|
|
119399
|
+
latest = timestamp;
|
|
119400
|
+
}
|
|
119401
|
+
}
|
|
119402
|
+
return latest;
|
|
119403
|
+
}
|
|
119404
|
+
function latestTimeActivity(time) {
|
|
119405
|
+
if (!time) {
|
|
119406
|
+
return;
|
|
119407
|
+
}
|
|
119408
|
+
return latestTimestamp(time.created, time.updated, time.completed, time.start, time.end);
|
|
119409
|
+
}
|
|
119359
119410
|
function getParentWakeMessageCreatedAt(message) {
|
|
119360
119411
|
return timestampFromUnknown(message.info?.time?.created ?? message.time?.created);
|
|
119361
119412
|
}
|
|
119413
|
+
function getParentWakeMessageActivityAt(message) {
|
|
119414
|
+
let latest = latestTimestamp(latestTimeActivity(message.info?.time), latestTimeActivity(message.time));
|
|
119415
|
+
for (const part of message.parts ?? []) {
|
|
119416
|
+
const partActivity = latestTimestamp(latestTimeActivity(part.time), latestTimeActivity(part.state?.time));
|
|
119417
|
+
if (partActivity !== undefined && (latest === undefined || partActivity > latest)) {
|
|
119418
|
+
latest = partActivity;
|
|
119419
|
+
}
|
|
119420
|
+
}
|
|
119421
|
+
return latest;
|
|
119422
|
+
}
|
|
119362
119423
|
|
|
119363
119424
|
// packages/omo-opencode/src/features/background-agent/parent-wake-history-state.ts
|
|
119364
119425
|
function latestAssistantTurnIsCompletedEmptyNoProgress(messages) {
|
|
@@ -119408,6 +119469,20 @@ function latestAssistantTurnHasFreshToolActivity(messages, now, maxAgeMs) {
|
|
|
119408
119469
|
}
|
|
119409
119470
|
return false;
|
|
119410
119471
|
}
|
|
119472
|
+
function latestAssistantTurnHasStaleUnknownSubstantiveOutput(messages, now, maxAgeMs) {
|
|
119473
|
+
for (let index = messages.length - 1;index >= 0; index--) {
|
|
119474
|
+
const message = messages[index];
|
|
119475
|
+
const role = messageRole(message);
|
|
119476
|
+
if (role === "assistant") {
|
|
119477
|
+
const finish = messageFinish(message);
|
|
119478
|
+
return (finish === undefined || finish === "unknown") && !messageCompleted(message) && messageHasSubstantiveAssistantOutput(message) && !messageHasFreshActivity(message, now, maxAgeMs);
|
|
119479
|
+
}
|
|
119480
|
+
if (role === "user" && !messageIsSyntheticOrInternalUser(message)) {
|
|
119481
|
+
return false;
|
|
119482
|
+
}
|
|
119483
|
+
}
|
|
119484
|
+
return false;
|
|
119485
|
+
}
|
|
119411
119486
|
function createEmptyAssistantTurnRetryDedupeKey(wake) {
|
|
119412
119487
|
return [
|
|
119413
119488
|
"background-agent-parent-wake-empty-retry",
|
|
@@ -119422,6 +119497,13 @@ function partHasFreshToolActivity(part, now, maxAgeMs) {
|
|
|
119422
119497
|
}
|
|
119423
119498
|
return timeHasFreshActivity(part.time, now, maxAgeMs) || timeHasFreshActivity(isRecord(part.state) ? part.state.time : undefined, now, maxAgeMs);
|
|
119424
119499
|
}
|
|
119500
|
+
function messageHasFreshActivity(message, now, maxAgeMs) {
|
|
119501
|
+
if (!isRecord(message)) {
|
|
119502
|
+
return false;
|
|
119503
|
+
}
|
|
119504
|
+
const activityAt = getParentWakeMessageActivityAt(message);
|
|
119505
|
+
return activityAt !== undefined && now - activityAt <= maxAgeMs;
|
|
119506
|
+
}
|
|
119425
119507
|
function timeHasFreshActivity(time, now, maxAgeMs) {
|
|
119426
119508
|
if (!isRecord(time)) {
|
|
119427
119509
|
return false;
|
|
@@ -119612,6 +119694,22 @@ class ParentWakeFlushRunner {
|
|
|
119612
119694
|
});
|
|
119613
119695
|
return;
|
|
119614
119696
|
}
|
|
119697
|
+
const finalToolWaitDecision = await this.confirmParentWakeStillSafeForReply(sessionID, latestWake, toolWaitDecision);
|
|
119698
|
+
if (finalToolWaitDecision.defer) {
|
|
119699
|
+
if (this.deferReplyWakeWhileUnsafe(sessionID, latestWake)) {
|
|
119700
|
+
return;
|
|
119701
|
+
}
|
|
119702
|
+
await this.sendParentWakePrompt(sessionID, latestWake, {
|
|
119703
|
+
emptyAssistantTurnRetry,
|
|
119704
|
+
toolWaitDecision: { ...finalToolWaitDecision, skipPromptGateToolStateCheck: true },
|
|
119705
|
+
forceNoReply: true,
|
|
119706
|
+
retainPendingWake: latestWake.shouldReply
|
|
119707
|
+
});
|
|
119708
|
+
log2("[background-agent] Recorded admit-only parent wake because parent session history became unsafe:", {
|
|
119709
|
+
sessionID
|
|
119710
|
+
});
|
|
119711
|
+
return;
|
|
119712
|
+
}
|
|
119615
119713
|
const dispatchedWake = this.deps.dispatchedTracker.getWake(sessionID);
|
|
119616
119714
|
if (dispatchedWake && isRedundantParentWake(latestWake, dispatchedWake)) {
|
|
119617
119715
|
this.deps.pendingQueue.deleteWake(sessionID);
|
|
@@ -119620,7 +119718,7 @@ class ParentWakeFlushRunner {
|
|
|
119620
119718
|
}
|
|
119621
119719
|
await this.sendParentWakePrompt(sessionID, latestWake, {
|
|
119622
119720
|
emptyAssistantTurnRetry,
|
|
119623
|
-
toolWaitDecision
|
|
119721
|
+
toolWaitDecision: finalToolWaitDecision
|
|
119624
119722
|
});
|
|
119625
119723
|
}
|
|
119626
119724
|
schedulePendingParentWakeFlush(sessionID, delayMs) {
|
|
@@ -119691,6 +119789,12 @@ class ParentWakeFlushRunner {
|
|
|
119691
119789
|
async shouldDeferParentWakeForSessionHistory(sessionID, wake) {
|
|
119692
119790
|
return this.deps.sessionInspector.shouldDeferForHistory(sessionID, wake);
|
|
119693
119791
|
}
|
|
119792
|
+
async confirmParentWakeStillSafeForReply(sessionID, wake, decision) {
|
|
119793
|
+
if (!decision.skipPromptGateToolStateCheck) {
|
|
119794
|
+
return decision;
|
|
119795
|
+
}
|
|
119796
|
+
return this.deps.sessionInspector.shouldDeferForHistory(sessionID, wake);
|
|
119797
|
+
}
|
|
119694
119798
|
requeueWake(sessionID, latestWake) {
|
|
119695
119799
|
this.deps.pendingQueue.requeueWake(sessionID, latestWake);
|
|
119696
119800
|
}
|
|
@@ -119858,6 +119962,12 @@ function getParentWakeSessionHistoryDeferralDecision(input) {
|
|
|
119858
119962
|
log2("[background-agent] Holding parent wake during stale tool-call deferral:", { sessionID: input.sessionID });
|
|
119859
119963
|
return { defer: true, skipPromptGateToolStateCheck: true };
|
|
119860
119964
|
}
|
|
119965
|
+
if (now - input.wake.toolCallDeferralStartedAt >= input.toolCallDeferMaxMs && latestAssistantTurnHasStaleUnknownSubstantiveOutput(messages, now, input.toolCallDeferMaxMs)) {
|
|
119966
|
+
log2("[background-agent] Retrying parent wake after stale unknown-finish assistant output:", {
|
|
119967
|
+
sessionID: input.sessionID
|
|
119968
|
+
});
|
|
119969
|
+
return { defer: false, skipPromptGateToolStateCheck: true };
|
|
119970
|
+
}
|
|
119861
119971
|
log2("[background-agent] Deferred parent wake because latest assistant turn blocks internal prompts:", {
|
|
119862
119972
|
sessionID: input.sessionID
|
|
119863
119973
|
});
|
|
@@ -144898,7 +145008,7 @@ async function loadPluginComponents(params) {
|
|
|
144898
145008
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
144899
145009
|
log2("[config-handler] Plugin loading failed", { error: errorMessage });
|
|
144900
145010
|
addConfigLoadError({ path: "plugin-loading", error: errorMessage });
|
|
144901
|
-
return EMPTY_PLUGIN_COMPONENTS;
|
|
145011
|
+
return { ...EMPTY_PLUGIN_COMPONENTS, retryableLoadFailure: true };
|
|
144902
145012
|
}
|
|
144903
145013
|
}
|
|
144904
145014
|
|
|
@@ -145037,8 +145147,38 @@ function collectTrustedVisionCapableModels(pluginConfig) {
|
|
|
145037
145147
|
}
|
|
145038
145148
|
return trusted;
|
|
145039
145149
|
}
|
|
145150
|
+
function cloneConfigValue(value) {
|
|
145151
|
+
if (Array.isArray(value)) {
|
|
145152
|
+
return value.map(cloneConfigValue);
|
|
145153
|
+
}
|
|
145154
|
+
if (typeof value === "object" && value !== null) {
|
|
145155
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, cloneConfigValue(entry)]));
|
|
145156
|
+
}
|
|
145157
|
+
return value;
|
|
145158
|
+
}
|
|
145159
|
+
function cloneAgentConfig(agents) {
|
|
145160
|
+
return cloneConfigValue(agents);
|
|
145161
|
+
}
|
|
145162
|
+
function createAgentConfigCacheKey(config) {
|
|
145163
|
+
return JSON.stringify({
|
|
145164
|
+
agent: config.agent,
|
|
145165
|
+
default_agent: config.default_agent,
|
|
145166
|
+
model: config.model,
|
|
145167
|
+
skills: config.skills
|
|
145168
|
+
});
|
|
145169
|
+
}
|
|
145170
|
+
function replayAgentConfigSideEffects(params) {
|
|
145171
|
+
if (params.configuredDefaultAgent && typeof params.defaultAgent === "string") {
|
|
145172
|
+
setDefaultAgentForSort(params.defaultAgent);
|
|
145173
|
+
}
|
|
145174
|
+
clearRegisteredAgentNames();
|
|
145175
|
+
for (const name of Object.keys(params.agentResult)) {
|
|
145176
|
+
registerAgentName(name);
|
|
145177
|
+
}
|
|
145178
|
+
}
|
|
145040
145179
|
function createConfigHandler(deps) {
|
|
145041
145180
|
const { ctx, pluginConfig, modelCacheState, runtimeSkillSourceUrl } = deps;
|
|
145181
|
+
let agentConfigSnapshot;
|
|
145042
145182
|
return async (config) => {
|
|
145043
145183
|
const formatterConfig = config.formatter;
|
|
145044
145184
|
setAdditionalAllowedMcpEnvVars(pluginConfig.mcp_env_allowlist ?? []);
|
|
@@ -145049,13 +145189,36 @@ function createConfigHandler(deps) {
|
|
|
145049
145189
|
});
|
|
145050
145190
|
clearFormatterCache();
|
|
145051
145191
|
const pluginComponents = await loadPluginComponents({ pluginConfig });
|
|
145192
|
+
const pluginComponentsLoadFailed = pluginComponents.retryableLoadFailure === true;
|
|
145052
145193
|
applyHookConfig({ pluginComponents });
|
|
145053
|
-
const
|
|
145054
|
-
|
|
145055
|
-
|
|
145056
|
-
|
|
145057
|
-
|
|
145058
|
-
|
|
145194
|
+
const agentCacheKey = createAgentConfigCacheKey(config);
|
|
145195
|
+
let agentResult;
|
|
145196
|
+
if (!pluginComponentsLoadFailed && agentConfigSnapshot?.cacheKey === agentCacheKey) {
|
|
145197
|
+
config.agent = cloneAgentConfig(agentConfigSnapshot.agents);
|
|
145198
|
+
if (agentConfigSnapshot.defaultAgent !== undefined) {
|
|
145199
|
+
config.default_agent = agentConfigSnapshot.defaultAgent;
|
|
145200
|
+
}
|
|
145201
|
+
agentResult = config.agent;
|
|
145202
|
+
replayAgentConfigSideEffects({
|
|
145203
|
+
agentResult,
|
|
145204
|
+
configuredDefaultAgent: agentConfigSnapshot.configuredDefaultAgent,
|
|
145205
|
+
defaultAgent: config.default_agent
|
|
145206
|
+
});
|
|
145207
|
+
} else {
|
|
145208
|
+
const configuredDefaultAgent = getConfiguredDefaultAgent(config);
|
|
145209
|
+
agentResult = await applyAgentConfig({
|
|
145210
|
+
config,
|
|
145211
|
+
pluginConfig,
|
|
145212
|
+
ctx,
|
|
145213
|
+
pluginComponents
|
|
145214
|
+
});
|
|
145215
|
+
agentConfigSnapshot = pluginComponentsLoadFailed ? undefined : {
|
|
145216
|
+
cacheKey: agentCacheKey,
|
|
145217
|
+
configuredDefaultAgent,
|
|
145218
|
+
defaultAgent: config.default_agent,
|
|
145219
|
+
agents: cloneAgentConfig(agentResult)
|
|
145220
|
+
};
|
|
145221
|
+
}
|
|
145059
145222
|
applyToolConfig({ config, pluginConfig, agentResult });
|
|
145060
145223
|
await applyMcpConfig({ config, pluginConfig, ctx, pluginComponents });
|
|
145061
145224
|
await applyCommandConfig({ config, pluginConfig, ctx, pluginComponents });
|
|
@@ -149975,6 +150138,15 @@ async function resolveSessionAgent(client3, sessionId) {
|
|
|
149975
150138
|
// packages/omo-opencode/src/plugin/tool-execute-before.ts
|
|
149976
150139
|
init_constants3();
|
|
149977
150140
|
init_storage();
|
|
150141
|
+
var BACKGROUND_WAIT_BLOCK_MESSAGE = [
|
|
150142
|
+
"Background task wait is already managed by the plugin.",
|
|
150143
|
+
"End this response now and wait for the <system-reminder> completion notification.",
|
|
150144
|
+
"After that reminder arrives, call background_output with the task_id from the launch result."
|
|
150145
|
+
].join(" ");
|
|
150146
|
+
function isPureSleepCommand(command) {
|
|
150147
|
+
const commandLines = command.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
150148
|
+
return commandLines.length > 0 && commandLines.every((line) => /^sleep\s+\d+(?:\.\d+)?[smhd]?\s*$/i.test(line));
|
|
150149
|
+
}
|
|
149978
150150
|
function getLoopCommandArguments(args, command) {
|
|
149979
150151
|
const rawUserMessage = typeof args.user_message === "string" ? args.user_message.trim() : "";
|
|
149980
150152
|
if (rawUserMessage) {
|
|
@@ -149984,7 +150156,7 @@ function getLoopCommandArguments(args, command) {
|
|
|
149984
150156
|
return rawName.replace(new RegExp(`^/?(${command})\\s*`, "i"), "");
|
|
149985
150157
|
}
|
|
149986
150158
|
function createToolExecuteBeforeHandler3(args) {
|
|
149987
|
-
const { ctx, hooks } = args;
|
|
150159
|
+
const { ctx, hooks, backgroundManager } = args;
|
|
149988
150160
|
function buildUltraworkOracleVerificationPrompt(prompt, originalTask, verificationAttemptId) {
|
|
149989
150161
|
const verificationPrompt = [
|
|
149990
150162
|
"You are verifying the active ULTRAWORK loop result for this session.",
|
|
@@ -150025,6 +150197,9 @@ function createToolExecuteBeforeHandler3(args) {
|
|
|
150025
150197
|
callID: input.callID
|
|
150026
150198
|
});
|
|
150027
150199
|
}
|
|
150200
|
+
if (isPureSleepCommand(output.args.command) && (backgroundManager?.hasActiveChildTasks(input.sessionID) === true || backgroundManager?.hasPendingParentWake(input.sessionID) === true)) {
|
|
150201
|
+
throw new Error(BACKGROUND_WAIT_BLOCK_MESSAGE);
|
|
150202
|
+
}
|
|
150028
150203
|
}
|
|
150029
150204
|
await hooks.writeExistingFileGuard?.["tool.execute.before"]?.(input, output);
|
|
150030
150205
|
await hooks.notepadWriteGuard?.["tool.execute.before"]?.(input, output);
|
|
@@ -150192,7 +150367,8 @@ function createPluginInterface(args) {
|
|
|
150192
150367
|
}),
|
|
150193
150368
|
"tool.execute.before": createToolExecuteBeforeHandler3({
|
|
150194
150369
|
ctx,
|
|
150195
|
-
hooks
|
|
150370
|
+
hooks,
|
|
150371
|
+
backgroundManager: managers.backgroundManager
|
|
150196
150372
|
}),
|
|
150197
150373
|
"tool.execute.after": createToolExecuteAfterHandler3({
|
|
150198
150374
|
ctx,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { PluginContext } from "./types";
|
|
2
2
|
import type { CreatedHooks } from "../create-hooks";
|
|
3
|
+
import type { BackgroundManager } from "../features/background-agent";
|
|
3
4
|
export declare function createToolExecuteBeforeHandler(args: {
|
|
4
5
|
ctx: PluginContext;
|
|
5
6
|
hooks: CreatedHooks;
|
|
7
|
+
backgroundManager?: Pick<BackgroundManager, "hasActiveChildTasks" | "hasPendingParentWake">;
|
|
6
8
|
}): (input: {
|
|
7
9
|
tool: string;
|
|
8
10
|
sessionID: string;
|
|
@@ -17,6 +17,7 @@ Outcome-first: explore a lot, ask few sharp questions - or none, when the intent
|
|
|
17
17
|
|
|
18
18
|
After grounding, make ONE judgment and load ONE intent reference (you ALSO read `references/full-workflow.md` for the shared mechanics - see below). The test keys on whether the desired **OUTCOME** is clear, NOT on request length.
|
|
19
19
|
|
|
20
|
+
- **OVERRIDE - explicit ask wins:** if the user explicitly asks to be questioned or interviewed ("ask me", "interview me", "why aren't you asking me" - in any language), route **CLEAR**, run the interview, and turn the adopt-default filter OFF: the user has claimed the forks, so every surviving one is ASKED, not defaulted. This beats the OUTCOME test below, even on a fuzzy brief.
|
|
20
21
|
- **CLEAR** - the user knows the outcome; the only open items are preferences/tradeoffs the repo cannot answer (genuine owner-decisions). Read **`references/intent-clear.md`**: ask the surviving forks with WHY, run the normal approval gate, high-accuracy review is OPTIONAL (offered as one question).
|
|
21
22
|
- **UNCLEAR** - the outcome itself is fuzzy (a vague brief, a bootstrap, `$start-work` with no selectable plan, a goal the user cannot yet articulate). Asking would offload your own job onto the user. Read **`references/intent-unclear.md`**: research maximally, adopt and ANNOUNCE best-practice defaults, do NOT ask the user extra questions, and run high-accuracy review AUTOMATICALLY (unless Classify sized the work Trivial).
|
|
22
23
|
- **ON THE FENCE** - when CLEAR vs UNCLEAR is genuinely ambiguous, treat it as CLEAR and ask exactly ONE question. A user wrongly silenced is worse than one extra question. The dominant failure to guard against is mis-routing a CLEAR request to UNCLEAR, which silently applies defaults and overrides forks the user wanted to own.
|
|
@@ -42,7 +43,7 @@ Run it ONCE at plan generation. A plain re-run on an existing plan is a safe no-
|
|
|
42
43
|
- **Decision-complete is the north star.** The executor has NO interview context - spell out exact paths, "every X in Y", and an explicit Must-NOT-Have. Leave the implementer ZERO judgment calls.
|
|
43
44
|
- **Explore before asking.** Discoverable facts (repo/system/docs truth) -> research and cite, never ask. Preferences/tradeoffs -> the only things you bring to the user. When unsure which, treat it as a user-decision.
|
|
44
45
|
- **CodeGraph first when present.** Use `codegraph_explore` for repo how/where/what/flow questions before wider reads; if codegraph_* tools are absent, inactive/uninitialized, or cold-start unavailable, continue with Read/Grep/Glob/LSP and the ast-grep skill.
|
|
45
|
-
- **Two filters** on every candidate question, in order: (1) Could collected evidence answer it? -> explore instead. (2) Could the user's stated intent plus a defensible default answer it? -> adopt the default, record it, do not ask
|
|
46
|
+
- **Two filters** on every candidate question, in order: (1) Could collected evidence answer it? -> explore instead. (2) Could the user's stated intent plus a defensible default answer it? -> adopt the default, record it, do not ask - UNLESS it is an owner-decision, which always survives as a question even when a default exists: anything irreversible / destructive / safety-critical, or a cross-cutting product choice the user lives with (public config surface, distribution / packaging, external dependency or pinned SHA, data / schema shape). Default the reversible internals; surface the owner-decisions.
|
|
46
47
|
- **Explore to sufficiency, then STOP.** One research wave per open question; stop when the clearance check is answerable; never re-explore to double-check.
|
|
47
48
|
- **Parallel-dispatch** independent research in ONE turn and keep working while it runs. Subagent outputs are CLAIMS until you independently verify them.
|
|
48
49
|
- **Approval is not execution.** Approval authorizes writing the plan ONLY, never implementation. ONE request -> ONE plan, however large.
|