opencode-orchestrator 1.0.78 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/dist/core/loop/mission-loop.d.ts +8 -0
- package/dist/index.js +58 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,13 +59,17 @@ OpenCode Orchestrator utilizes a **Hub-and-Spoke Topology** to execute complex e
|
|
|
59
59
|
|
|
60
60
|
## 🛠️ Technical Excellence
|
|
61
61
|
|
|
62
|
-
###
|
|
62
|
+
### ️ Atomic MVCC State Synchronization
|
|
63
63
|
The engine solves the "Concurrent TODO Update" problem using **Multi-Version Concurrency Control (MVCC) + Mutex**. Agents can safely mark tasks as complete in parallel without data loss or race conditions. Every state change is kryptographically hashed and logged for a complete audit trail.
|
|
64
64
|
|
|
65
65
|
### 🧩 Advanced Hook Orchestration
|
|
66
66
|
Execution flows are governed by a **Priority-Phase Hook Registry**. Hooks (Safety, UI, Protocol) are grouped into phases (`early`, `normal`, `late`) and executed using a **Topological Sort** to handle complex dependencies automatically, ensuring a predictable and stable environment.
|
|
67
67
|
|
|
68
|
-
###
|
|
68
|
+
### ️ Autonomous Recovery
|
|
69
|
+
- **Self-healing loops** with adaptive stagnation detection.
|
|
70
|
+
- **Proactive Agency**: Smart monitoring that audits logs and plans ahead during background tasks.
|
|
71
|
+
|
|
72
|
+
### ️ State-Level Session Isolation
|
|
69
73
|
Reused sessions in the **SessionPool** are explicitly reset using server-side compaction triggered by health monitors. This ensures that previous task context (old error messages, stale file references) never leaks into new tasks, maintaining 100% implementation integrity.
|
|
70
74
|
|
|
71
75
|
### 🚀 Zero-Payload Turbo Mode
|
|
@@ -78,12 +82,17 @@ Leverages `system.transform` to unshift massive agent instruction sets on the se
|
|
|
78
82
|
### 🧠 Hierarchical Memory System
|
|
79
83
|
Maintains focus across thousands of conversation turns using a 4-tier memory structure and **EMA-based Context Gating** to preserve "Architectural Truth" while pruning operational noise.
|
|
80
84
|
|
|
81
|
-
###
|
|
85
|
+
### Dynamic Concurrency Auto-Scaling
|
|
82
86
|
Slots for parallel implementation scale up automatically after a **3-success streak** and scale down aggressively upon detection of API instability or implementation failures.
|
|
83
87
|
|
|
84
88
|
### 🛡️ Neuro-Symbolic Safety
|
|
85
89
|
Combines LLM reasoning with deterministic **AST/LSP verification**. Every code change is verified by native system tools before being accepted into the master roadmap.
|
|
86
90
|
|
|
91
|
+
### 🔄 Adaptive Intelligence Loop
|
|
92
|
+
- **Stagnation Detection**: Automatically senses when no progress is made across multiple iterations.
|
|
93
|
+
- **Diagnostic Intervention**: Forces the agent into a "Diagnostic Mode" when stagnation is detected, mandating log audits and strategy pivots.
|
|
94
|
+
- **Proactive Agency**: Mandates Speculative Planning and Parallel Thinking during background task execution.
|
|
95
|
+
|
|
87
96
|
### 📊 Real-time TUI Monitor
|
|
88
97
|
A live dashboard directly in your TUI. Monitor **Mission Progress**, active **Agent Sub-sessions**, and **Technical Metrics** through optimized, protocol-safe channels.
|
|
89
98
|
|
|
@@ -20,6 +20,10 @@ export interface MissionLoopState {
|
|
|
20
20
|
startedAt: string;
|
|
21
21
|
/** Last activity timestamp */
|
|
22
22
|
lastActivity?: string;
|
|
23
|
+
/** Last known progress string (e.g., "3/10") */
|
|
24
|
+
lastProgress?: string;
|
|
25
|
+
/** Number of iterations without progress */
|
|
26
|
+
stagnationCount?: number;
|
|
23
27
|
}
|
|
24
28
|
export interface MissionLoopOptions {
|
|
25
29
|
/** Maximum iterations before stopping (default: 1000) */
|
|
@@ -67,3 +71,7 @@ export declare function generateCompletionNotification(state: MissionLoopState):
|
|
|
67
71
|
* Generate max iterations reached notification
|
|
68
72
|
*/
|
|
69
73
|
export declare function generateMaxIterationsNotification(state: MissionLoopState): string;
|
|
74
|
+
/**
|
|
75
|
+
* Stagnation intervention prompt
|
|
76
|
+
*/
|
|
77
|
+
export declare const STAGNATION_INTERVENTION = "\n<system_intervention type=\"stagnation_detected\">\n\u26A0\uFE0F **\uACBD\uACE0: \uC9C4\uD589 \uC815\uCCB4 \uAC10\uC9C0 (STAGNATION DETECTED)**\n\uCD5C\uADFC \uC5EC\uB7EC \uD134 \uB3D9\uC548 \uC2E4\uC9C8\uC801\uC778 \uC9C4\uC804\uC774 \uAC10\uC9C0\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uB2E8\uC21C \"\uBAA8\uB2C8\uD130\uB9C1\"\uC774\uB098 \uAC19\uC740 \uD589\uB3D9\uC744 \uBC18\uBCF5\uD558\uB294 \uAC83\uC740 \uAE08\uC9C0\uB429\uB2C8\uB2E4.\n\n**\uC790\uC728\uC801 \uC9C4\uB2E8 \uBC0F \uD574\uACB0 \uC9C0\uCE68:**\n1. **\uC2E4\uC2DC\uAC04 \uB85C\uADF8 \uD655\uC778**: `check_background_task` \uB610\uB294 `read_file`\uC744 \uC0AC\uC6A9\uD558\uC5EC \uC9C4\uD589 \uC911\uC778 \uC791\uC5C5\uC758 \uCD9C\uB825 \uB85C\uADF8\uB97C \uC9C1\uC811 \uD655\uC778\uD558\uC2ED\uC2DC\uC624.\n2. **\uD504\uB85C\uC138\uC2A4 \uC0DD\uC874 \uC9C4\uB2E8**: \uC791\uC5C5\uC774 \uC880\uBE44 \uC0C1\uD0DC\uC774\uAC70\uB098 \uBA48\uCD98 \uAC83 \uAC19\uB2E4\uBA74 \uACFC\uAC10\uD558\uAC8C `kill`\uD558\uACE0 \uB2E8\uACC4\uB97C \uC138\uBD84\uD654\uD558\uC5EC \uB2E4\uC2DC \uC2E4\uD589\uD558\uC2ED\uC2DC\uC624.\n3. **\uC804\uB7B5 \uC804\uD658**: \uB3D9\uC77C\uD55C \uC811\uADFC \uBC29\uC2DD\uC774 \uC2E4\uD328\uD558\uACE0 \uC788\uB2E4\uBA74, \uB2E4\uB978 \uB3C4\uAD6C\uB098 \uBC29\uBC95\uC744 \uC0AC\uC6A9\uD558\uC5EC \uBAA9\uD45C\uC5D0 \uB3C4\uB2EC\uD558\uC2ED\uC2DC\uC624.\n\n**\uC9C0\uAE08 \uBC14\uB85C \uB2A5\uB3D9\uC801\uC73C\uB85C \uAC1C\uC785\uD558\uC2ED\uC2DC\uC624. \uB300\uAE30\uD558\uC9C0 \uB9C8\uC2ED\uC2DC\uC624.**\n</system_intervention>";
|
package/dist/index.js
CHANGED
|
@@ -22652,8 +22652,11 @@ var CONTINUE_INSTRUCTION = `<auto_continue>
|
|
|
22652
22652
|
<rules>
|
|
22653
22653
|
1. DO NOT stop - mission is incomplete
|
|
22654
22654
|
2. DO NOT wait for user input
|
|
22655
|
-
3. If
|
|
22656
|
-
|
|
22655
|
+
3. **PROACTIVE THINKING MANDATORY**: If background tasks are running, use the time to:
|
|
22656
|
+
- Run \`check_background_task\` to audit logs and ensure no deadlocks.
|
|
22657
|
+
- speculatively plan the next steps or prepare necessary code templates.
|
|
22658
|
+
- execute independent sub-tasks from the TODO list.
|
|
22659
|
+
4. If previous action failed, try different approach
|
|
22657
22660
|
5. Breakdown abstract tasks into Grade 3 sub-tasks before execution
|
|
22658
22661
|
</rules>
|
|
22659
22662
|
|
|
@@ -22779,6 +22782,18 @@ ${state2.prompt}
|
|
|
22779
22782
|
**NOW**: Continue executing!
|
|
22780
22783
|
</mission_loop>`;
|
|
22781
22784
|
}
|
|
22785
|
+
var STAGNATION_INTERVENTION = `
|
|
22786
|
+
<system_intervention type="stagnation_detected">
|
|
22787
|
+
\u26A0\uFE0F **\uACBD\uACE0: \uC9C4\uD589 \uC815\uCCB4 \uAC10\uC9C0 (STAGNATION DETECTED)**
|
|
22788
|
+
\uCD5C\uADFC \uC5EC\uB7EC \uD134 \uB3D9\uC548 \uC2E4\uC9C8\uC801\uC778 \uC9C4\uC804\uC774 \uAC10\uC9C0\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uB2E8\uC21C "\uBAA8\uB2C8\uD130\uB9C1"\uC774\uB098 \uAC19\uC740 \uD589\uB3D9\uC744 \uBC18\uBCF5\uD558\uB294 \uAC83\uC740 \uAE08\uC9C0\uB429\uB2C8\uB2E4.
|
|
22789
|
+
|
|
22790
|
+
**\uC790\uC728\uC801 \uC9C4\uB2E8 \uBC0F \uD574\uACB0 \uC9C0\uCE68:**
|
|
22791
|
+
1. **\uC2E4\uC2DC\uAC04 \uB85C\uADF8 \uD655\uC778**: \`check_background_task\` \uB610\uB294 \`read_file\`\uC744 \uC0AC\uC6A9\uD558\uC5EC \uC9C4\uD589 \uC911\uC778 \uC791\uC5C5\uC758 \uCD9C\uB825 \uB85C\uADF8\uB97C \uC9C1\uC811 \uD655\uC778\uD558\uC2ED\uC2DC\uC624.
|
|
22792
|
+
2. **\uD504\uB85C\uC138\uC2A4 \uC0DD\uC874 \uC9C4\uB2E8**: \uC791\uC5C5\uC774 \uC880\uBE44 \uC0C1\uD0DC\uC774\uAC70\uB098 \uBA48\uCD98 \uAC83 \uAC19\uB2E4\uBA74 \uACFC\uAC10\uD558\uAC8C \`kill\`\uD558\uACE0 \uB2E8\uACC4\uB97C \uC138\uBD84\uD654\uD558\uC5EC \uB2E4\uC2DC \uC2E4\uD589\uD558\uC2ED\uC2DC\uC624.
|
|
22793
|
+
3. **\uC804\uB7B5 \uC804\uD658**: \uB3D9\uC77C\uD55C \uC811\uADFC \uBC29\uC2DD\uC774 \uC2E4\uD328\uD558\uACE0 \uC788\uB2E4\uBA74, \uB2E4\uB978 \uB3C4\uAD6C\uB098 \uBC29\uBC95\uC744 \uC0AC\uC6A9\uD558\uC5EC \uBAA9\uD45C\uC5D0 \uB3C4\uB2EC\uD558\uC2ED\uC2DC\uC624.
|
|
22794
|
+
|
|
22795
|
+
**\uC9C0\uAE08 \uBC14\uB85C \uB2A5\uB3D9\uC801\uC73C\uB85C \uAC1C\uC785\uD558\uC2ED\uC2DC\uC624. \uB300\uAE30\uD558\uC9C0 \uB9C8\uC2ED\uC2DC\uC624.**
|
|
22796
|
+
</system_intervention>`;
|
|
22782
22797
|
|
|
22783
22798
|
// src/core/orchestrator/session-manager.ts
|
|
22784
22799
|
function ensureSessionInitialized(sessions, sessionID, directory) {
|
|
@@ -23523,13 +23538,27 @@ var MissionControlHook = class {
|
|
|
23523
23538
|
if (verification.passed) {
|
|
23524
23539
|
return this.handleMissionComplete(directory, verification);
|
|
23525
23540
|
}
|
|
23526
|
-
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23541
|
+
const loopState = readLoopState(directory);
|
|
23542
|
+
let isStagnant = false;
|
|
23543
|
+
if (loopState && loopState.active && loopState.sessionID === sessionID) {
|
|
23544
|
+
const currentProgress = verification.todoProgress;
|
|
23545
|
+
if (loopState.lastProgress === currentProgress) {
|
|
23546
|
+
loopState.stagnationCount = (loopState.stagnationCount || 0) + 1;
|
|
23547
|
+
if (loopState.stagnationCount >= 2) {
|
|
23548
|
+
isStagnant = true;
|
|
23549
|
+
}
|
|
23550
|
+
} else {
|
|
23551
|
+
loopState.stagnationCount = 0;
|
|
23552
|
+
}
|
|
23553
|
+
loopState.lastProgress = currentProgress;
|
|
23554
|
+
writeLoopState(directory, loopState);
|
|
23555
|
+
}
|
|
23530
23556
|
const failurePrompt = verification.checklistProgress !== "0/0" ? buildVerificationFailurePrompt(verification) : buildTodoIncompletePrompt(verification);
|
|
23531
23557
|
const continuation = this.buildContinuationResponse(session, sessionID);
|
|
23532
23558
|
const prompts = [failurePrompt];
|
|
23559
|
+
if (isStagnant) {
|
|
23560
|
+
prompts.push(STAGNATION_INTERVENTION);
|
|
23561
|
+
}
|
|
23533
23562
|
if (continuation.action === HOOK_ACTIONS.INJECT) {
|
|
23534
23563
|
prompts.push(...continuation.prompts);
|
|
23535
23564
|
}
|
|
@@ -24755,22 +24784,6 @@ function hasRunningBackgroundTasks2(parentSessionID) {
|
|
|
24755
24784
|
return false;
|
|
24756
24785
|
}
|
|
24757
24786
|
}
|
|
24758
|
-
async function showCountdownToast2(client, seconds, iteration, maxIterations) {
|
|
24759
|
-
try {
|
|
24760
|
-
const tuiClient2 = client;
|
|
24761
|
-
if (tuiClient2.tui?.showToast) {
|
|
24762
|
-
await tuiClient2.tui.showToast({
|
|
24763
|
-
body: {
|
|
24764
|
-
title: "\u{1F504} Mission Loop",
|
|
24765
|
-
message: `Continuing in ${seconds}s... (iteration ${iteration}/${maxIterations})`,
|
|
24766
|
-
variant: TOAST_VARIANTS.WARNING,
|
|
24767
|
-
duration: TOAST_DURATION.EXTRA_SHORT
|
|
24768
|
-
}
|
|
24769
|
-
});
|
|
24770
|
-
}
|
|
24771
|
-
} catch {
|
|
24772
|
-
}
|
|
24773
|
-
}
|
|
24774
24787
|
async function showCompletedToast(client, state2) {
|
|
24775
24788
|
try {
|
|
24776
24789
|
const tuiClient2 = client;
|
|
@@ -24787,7 +24800,7 @@ async function showCompletedToast(client, state2) {
|
|
|
24787
24800
|
} catch {
|
|
24788
24801
|
}
|
|
24789
24802
|
}
|
|
24790
|
-
async function injectContinuation2(client, directory, sessionID, loopState) {
|
|
24803
|
+
async function injectContinuation2(client, directory, sessionID, loopState, customPrompt) {
|
|
24791
24804
|
const handlerState = getState4(sessionID);
|
|
24792
24805
|
if (handlerState.isAborting) return;
|
|
24793
24806
|
if (hasRunningBackgroundTasks2(sessionID)) return;
|
|
@@ -24798,7 +24811,12 @@ async function injectContinuation2(client, directory, sessionID, loopState) {
|
|
|
24798
24811
|
return;
|
|
24799
24812
|
}
|
|
24800
24813
|
const summary = buildVerificationSummary(verification);
|
|
24801
|
-
|
|
24814
|
+
let prompt = generateMissionContinuationPrompt(loopState, summary);
|
|
24815
|
+
if (customPrompt) {
|
|
24816
|
+
prompt = `${customPrompt}
|
|
24817
|
+
|
|
24818
|
+
${prompt}`;
|
|
24819
|
+
}
|
|
24802
24820
|
try {
|
|
24803
24821
|
client.session.prompt({
|
|
24804
24822
|
path: { id: sessionID },
|
|
@@ -24859,19 +24877,27 @@ async function handleMissionIdle(client, directory, sessionID, mainSessionID) {
|
|
|
24859
24877
|
await handleMissionComplete(client, directory, loopState);
|
|
24860
24878
|
return;
|
|
24861
24879
|
}
|
|
24862
|
-
|
|
24863
|
-
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24880
|
+
const currentProgress = verification.todoProgress;
|
|
24881
|
+
let isStagnant = false;
|
|
24882
|
+
if (loopState.lastProgress === currentProgress) {
|
|
24883
|
+
loopState.stagnationCount = (loopState.stagnationCount || 0) + 1;
|
|
24884
|
+
if (loopState.stagnationCount >= 2) {
|
|
24885
|
+
isStagnant = true;
|
|
24886
|
+
log(`[${MISSION_CONTROL.LOG_SOURCE}-handler] Stagnation detected for ${sessionID} (${currentProgress}). Intervention ready.`);
|
|
24887
|
+
}
|
|
24888
|
+
} else {
|
|
24889
|
+
loopState.stagnationCount = 0;
|
|
24868
24890
|
}
|
|
24891
|
+
loopState.lastProgress = currentProgress;
|
|
24869
24892
|
const newState = incrementIteration(directory);
|
|
24870
24893
|
if (!newState) return;
|
|
24871
|
-
|
|
24894
|
+
newState.lastProgress = currentProgress;
|
|
24895
|
+
newState.stagnationCount = loopState.stagnationCount;
|
|
24896
|
+
writeLoopState(directory, newState);
|
|
24897
|
+
const countdownMsg = isStagnant ? "Stagnation Detected! Intervening..." : `Continuing in ${MISSION_CONTROL.DEFAULT_COUNTDOWN_SECONDS}s... (iteration ${newState.iteration}/${newState.maxIterations})`;
|
|
24872
24898
|
handlerState.countdownTimer = setTimeout(async () => {
|
|
24873
24899
|
cancelCountdown2(sessionID);
|
|
24874
|
-
await injectContinuation2(client, directory, sessionID, newState);
|
|
24900
|
+
await injectContinuation2(client, directory, sessionID, newState, isStagnant ? STAGNATION_INTERVENTION : void 0);
|
|
24875
24901
|
}, MISSION_CONTROL.DEFAULT_COUNTDOWN_SECONDS * 1e3);
|
|
24876
24902
|
}
|
|
24877
24903
|
function handleUserMessage2(sessionID) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "opencode-orchestrator",
|
|
3
3
|
"displayName": "OpenCode Orchestrator",
|
|
4
4
|
"description": "Distributed Cognitive Architecture for OpenCode. Turns simple prompts into specialized multi-agent workflows (Planner, Coder, Reviewer).",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.2.1",
|
|
6
6
|
"author": "agnusdei1207",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|