opencode-orchestrator 1.3.6 → 1.3.7
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 +3 -1
- package/dist/core/memory/interfaces.d.ts +1 -1
- package/dist/core/memory/memory-manager.d.ts +1 -1
- package/dist/core/orchestrator/session-manager.d.ts +19 -2
- package/dist/core/queue/async-utils.d.ts +1 -1
- package/dist/hooks/compatibility/external-plugin.d.ts +3 -3
- package/dist/hooks/custom/agent-ui.d.ts +2 -10
- package/dist/hooks/custom/memory-gate.d.ts +3 -6
- package/dist/hooks/custom/metrics.d.ts +4 -6
- package/dist/hooks/custom/resource-control.d.ts +3 -2
- package/dist/hooks/custom/secret-scanner.d.ts +2 -10
- package/dist/hooks/custom/strict-role-guard.d.ts +2 -11
- package/dist/hooks/custom/user-activity.d.ts +2 -2
- package/dist/hooks/features/mission-loop.d.ts +3 -2
- package/dist/hooks/features/sanity-check.d.ts +3 -6
- package/dist/hooks/registry.d.ts +4 -16
- package/dist/hooks/types.d.ts +21 -16
- package/dist/index.js +103 -60
- package/dist/tools/lsp/diagnostics-cache.d.ts +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://www.npmjs.com/package/opencode-orchestrator)
|
|
8
8
|
<!-- VERSION:START -->
|
|
9
|
-
**Version:** `1.3.
|
|
9
|
+
**Version:** `1.3.7`
|
|
10
10
|
<!-- VERSION:END -->
|
|
11
11
|
</div>
|
|
12
12
|
|
|
@@ -139,6 +139,8 @@ Useful references:
|
|
|
139
139
|
3. OpenCode keybinds: https://opencode.ai/docs/keybinds/
|
|
140
140
|
4. Project issues: https://github.com/agnusdei1207/opencode-orchestrator/issues
|
|
141
141
|
|
|
142
|
+
Contributions are welcome: open an issue or pull request when you find a bug, compatibility gap, or focused improvement.
|
|
143
|
+
|
|
142
144
|
Config logs:
|
|
143
145
|
|
|
144
146
|
| Platform | Path |
|
|
@@ -12,7 +12,7 @@ export declare class MemoryManager {
|
|
|
12
12
|
/**
|
|
13
13
|
* Add a memory entry
|
|
14
14
|
*/
|
|
15
|
-
add(level: MemoryLevel, content: string, importance?: number, metadata?: Record<string,
|
|
15
|
+
add(level: MemoryLevel, content: string, importance?: number, metadata?: Record<string, unknown>): string;
|
|
16
16
|
/**
|
|
17
17
|
* Retrieve memory for prompt construction
|
|
18
18
|
*/
|
|
@@ -1,8 +1,24 @@
|
|
|
1
|
+
interface ManagedSessionState {
|
|
2
|
+
active: boolean;
|
|
3
|
+
step: number;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
startTime: number;
|
|
6
|
+
lastStepTime: number;
|
|
7
|
+
lastCompletedMessageID?: string;
|
|
8
|
+
lastUserMessageAt?: number;
|
|
9
|
+
lastAssistantCompletedAt?: number;
|
|
10
|
+
lastAbortAt?: number;
|
|
11
|
+
tokens: {
|
|
12
|
+
totalInput: number;
|
|
13
|
+
totalOutput: number;
|
|
14
|
+
estimatedCost: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
1
17
|
/**
|
|
2
18
|
* Ensures a local session object exists in the plugin context map.
|
|
3
19
|
* Now WITH disk-based rehydration for robustness.
|
|
4
20
|
*/
|
|
5
|
-
export declare function ensureSessionInitialized(sessions: Map<string,
|
|
21
|
+
export declare function ensureSessionInitialized(sessions: Map<string, unknown>, sessionID: string, directory?: string): ManagedSessionState;
|
|
6
22
|
/**
|
|
7
23
|
* Activates the global mission state for a specific session.
|
|
8
24
|
*/
|
|
@@ -19,7 +35,7 @@ export declare function deactivateMissionState(sessionID: string): void;
|
|
|
19
35
|
/**
|
|
20
36
|
* Updates token usage and estimated cost for a session.
|
|
21
37
|
*/
|
|
22
|
-
export declare function updateSessionTokens(sessions: Map<string,
|
|
38
|
+
export declare function updateSessionTokens(sessions: Map<string, unknown>, sessionID: string, inputLen: number, outputLen: number): void;
|
|
23
39
|
/**
|
|
24
40
|
* Anomaly Management
|
|
25
41
|
*/
|
|
@@ -29,3 +45,4 @@ export declare function resetAnomaly(sessionID: string): void;
|
|
|
29
45
|
* Task Tracking
|
|
30
46
|
*/
|
|
31
47
|
export declare function updateCurrentTask(sessionID: string, taskID: string): void;
|
|
48
|
+
export {};
|
|
@@ -17,4 +17,4 @@ export declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number, e
|
|
|
17
17
|
/**
|
|
18
18
|
* Debounce async function
|
|
19
19
|
*/
|
|
20
|
-
export declare function debounceAsync<
|
|
20
|
+
export declare function debounceAsync<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => Promise<TResult>, delayMs: number): (...args: TArgs) => Promise<TResult>;
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Detects if other major plugins are present and ensures orchestrator plays nicely.
|
|
5
5
|
*/
|
|
6
|
-
import type { ChatMessageHook,
|
|
7
|
-
export declare class ExternalPluginCompatHook implements ChatMessageHook
|
|
6
|
+
import type { ChatMessageHook, ChatMessageResult, HookContext } from "../types.js";
|
|
7
|
+
export declare class ExternalPluginCompatHook implements ChatMessageHook {
|
|
8
8
|
name: string;
|
|
9
|
-
execute(ctx: HookContext, input:
|
|
9
|
+
execute(ctx: HookContext, input: string): Promise<ChatMessageResult>;
|
|
10
10
|
}
|
|
@@ -5,16 +5,8 @@
|
|
|
5
5
|
* - Agent headers (e.g. [P] PLANNER Working...)
|
|
6
6
|
* - Task ID tracking
|
|
7
7
|
*/
|
|
8
|
-
import type { PostToolUseHook, HookContext } from "../types.js";
|
|
8
|
+
import type { PostToolUseHook, HookContext, PostToolResult, ToolInput, ToolOutput } from "../types.js";
|
|
9
9
|
export declare class AgentUIHook implements PostToolUseHook {
|
|
10
10
|
name: "AgentUI";
|
|
11
|
-
execute(ctx: HookContext, tool: string, input:
|
|
12
|
-
title: string;
|
|
13
|
-
output: string;
|
|
14
|
-
metadata: any;
|
|
15
|
-
}): Promise<{
|
|
16
|
-
output?: undefined;
|
|
17
|
-
} | {
|
|
18
|
-
output: string;
|
|
19
|
-
}>;
|
|
11
|
+
execute(ctx: HookContext, tool: string, input: ToolInput, output: ToolOutput): Promise<PostToolResult>;
|
|
20
12
|
}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MemoryGate Hook - Intercepts tool usage and turn completion to maintain memory.
|
|
3
3
|
*/
|
|
4
|
-
import { PostToolUseHook, AssistantDoneHook, HookContext } from "../types.js";
|
|
4
|
+
import type { PostToolUseHook, AssistantDoneHook, HookContext, HookResult, PostToolResult, ToolInput, ToolOutput } from "../types.js";
|
|
5
5
|
export declare class MemoryGateHook implements PostToolUseHook, AssistantDoneHook {
|
|
6
6
|
name: "MemoryGate";
|
|
7
7
|
private memoryManager;
|
|
8
|
-
execute(context: HookContext,
|
|
9
|
-
|
|
10
|
-
output: string;
|
|
11
|
-
metadata: any;
|
|
12
|
-
}): Promise<any>;
|
|
8
|
+
execute(context: HookContext, tool: string, input: ToolInput, output: ToolOutput): Promise<PostToolResult>;
|
|
9
|
+
execute(context: HookContext, finalText: string): Promise<HookResult>;
|
|
13
10
|
/**
|
|
14
11
|
* Post-Tool: Capture tool outputs to TASK memory
|
|
15
12
|
*/
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MetricsHook - Collects telemetry during mission execution
|
|
3
3
|
*/
|
|
4
|
-
import { PreToolUseHook, PostToolUseHook, AssistantDoneHook, HookContext } from "../types.js";
|
|
4
|
+
import type { PreToolUseHook, PostToolUseHook, AssistantDoneHook, HookContext, HookResult, PostToolResult, PreToolResult, ToolInput, ToolOutput } from "../types.js";
|
|
5
5
|
export declare class MetricsHook implements PreToolUseHook, PostToolUseHook, AssistantDoneHook {
|
|
6
6
|
name: "MetricsTelemetry";
|
|
7
7
|
private startTimes;
|
|
8
8
|
private metrics;
|
|
9
|
-
execute(context: HookContext,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
metadata: any;
|
|
13
|
-
}): Promise<any>;
|
|
9
|
+
execute(context: HookContext, tool: string, input: ToolInput): Promise<PreToolResult>;
|
|
10
|
+
execute(context: HookContext, tool: string, input: ToolInput, output: ToolOutput): Promise<PostToolResult>;
|
|
11
|
+
execute(context: HookContext, finalText: string): Promise<HookResult>;
|
|
14
12
|
}
|
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* Unifies resource tracking, monitoring, and active memory compaction.
|
|
5
5
|
* Replaces separate ResourceUsageHook and MemoryCompactionHook.
|
|
6
6
|
*/
|
|
7
|
-
import type { PostToolUseHook, AssistantDoneHook, HookContext } from "../types.js";
|
|
7
|
+
import type { PostToolUseHook, AssistantDoneHook, HookContext, HookResult, PostToolResult, ToolInput, ToolOutput } from "../types.js";
|
|
8
8
|
export declare class ResourceControlHook implements PostToolUseHook, AssistantDoneHook {
|
|
9
9
|
name: "ResourceControl";
|
|
10
10
|
private lastCompactionTime;
|
|
11
|
-
execute(ctx: HookContext,
|
|
11
|
+
execute(ctx: HookContext, tool: string, input: ToolInput, output: ToolOutput): Promise<PostToolResult>;
|
|
12
|
+
execute(ctx: HookContext, finalText: string): Promise<HookResult>;
|
|
12
13
|
private checkMemoryHealth;
|
|
13
14
|
}
|
|
@@ -4,16 +4,8 @@
|
|
|
4
4
|
* Scans tool outputs for potential secrets (API Keys, etc) and masks them.
|
|
5
5
|
* This prevents leaking secrets into the context window or logs.
|
|
6
6
|
*/
|
|
7
|
-
import type { PostToolUseHook, HookContext } from "../types.js";
|
|
7
|
+
import type { PostToolUseHook, HookContext, PostToolResult, ToolInput, ToolOutput } from "../types.js";
|
|
8
8
|
export declare class SecretScannerHook implements PostToolUseHook {
|
|
9
9
|
name: "SecretScanner";
|
|
10
|
-
execute(ctx: HookContext, tool: string, input:
|
|
11
|
-
title: string;
|
|
12
|
-
output: string;
|
|
13
|
-
metadata: any;
|
|
14
|
-
}): Promise<{
|
|
15
|
-
output: string;
|
|
16
|
-
} | {
|
|
17
|
-
output?: undefined;
|
|
18
|
-
}>;
|
|
10
|
+
execute(ctx: HookContext, tool: string, input: ToolInput, output: ToolOutput): Promise<PostToolResult>;
|
|
19
11
|
}
|
|
@@ -5,17 +5,8 @@
|
|
|
5
5
|
* - Planner: Cannot write code or run commands.
|
|
6
6
|
* - Reviewer: Cannot write code (only review).
|
|
7
7
|
*/
|
|
8
|
-
import type { PreToolUseHook, HookContext } from "../types.js";
|
|
8
|
+
import type { PreToolUseHook, HookContext, PreToolResult, ToolInput } from "../types.js";
|
|
9
9
|
export declare class StrictRoleGuardHook implements PreToolUseHook {
|
|
10
10
|
name: "StrictRoleGuard";
|
|
11
|
-
execute(ctx: HookContext, tool: string, args:
|
|
12
|
-
action: "block";
|
|
13
|
-
reason: "Fork bomb detected.";
|
|
14
|
-
} | {
|
|
15
|
-
action: "block";
|
|
16
|
-
reason: "Root deletion blocked.";
|
|
17
|
-
} | {
|
|
18
|
-
action: "allow";
|
|
19
|
-
reason?: undefined;
|
|
20
|
-
}>;
|
|
11
|
+
execute(ctx: HookContext, tool: string, args: ToolInput): Promise<PreToolResult>;
|
|
21
12
|
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Tracks user interaction (chat messages) to pause auto-continuation/loops
|
|
5
5
|
* and update activity timestamps.
|
|
6
6
|
*/
|
|
7
|
-
import type { ChatMessageHook, HookContext } from "../types.js";
|
|
7
|
+
import type { ChatMessageHook, ChatMessageResult, HookContext } from "../types.js";
|
|
8
8
|
export declare class UserActivityHook implements ChatMessageHook {
|
|
9
9
|
name: "UserActivity";
|
|
10
|
-
execute(ctx: HookContext, message: string): Promise<
|
|
10
|
+
execute(ctx: HookContext, message: string): Promise<ChatMessageResult>;
|
|
11
11
|
}
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
* - Auto-continuation injection (Loop)
|
|
7
7
|
* - User cancellation detection
|
|
8
8
|
*/
|
|
9
|
-
import type { AssistantDoneHook, ChatMessageHook, HookContext } from "../types.js";
|
|
9
|
+
import type { AssistantDoneHook, ChatMessageHook, ChatMessageResult, HookContext, HookResult } from "../types.js";
|
|
10
10
|
export declare class MissionControlHook implements AssistantDoneHook, ChatMessageHook {
|
|
11
11
|
name: "MissionLoop";
|
|
12
|
-
execute(ctx: HookContext, text: string): Promise<
|
|
12
|
+
execute(ctx: HookContext, text: string): Promise<ChatMessageResult>;
|
|
13
|
+
execute(ctx: HookContext, text: string): Promise<HookResult>;
|
|
13
14
|
private handleChatCommand;
|
|
14
15
|
private cancelMission;
|
|
15
16
|
private handleMissionProgress;
|
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
* Sanity Check Hook
|
|
3
3
|
* Implements output anomaly detection.
|
|
4
4
|
*/
|
|
5
|
-
import type { PostToolUseHook, AssistantDoneHook, HookContext } from "../types.js";
|
|
5
|
+
import type { PostToolUseHook, AssistantDoneHook, HookContext, HookResult, PostToolResult, ToolInput, ToolOutput } from "../types.js";
|
|
6
6
|
export declare class SanityCheckHook implements PostToolUseHook, AssistantDoneHook {
|
|
7
7
|
name: "SanityCheck";
|
|
8
|
-
execute(ctx: HookContext,
|
|
9
|
-
|
|
10
|
-
output: string;
|
|
11
|
-
metadata: any;
|
|
12
|
-
}): Promise<any>;
|
|
8
|
+
execute(ctx: HookContext, tool: string, input: ToolInput, output: ToolOutput): Promise<PostToolResult>;
|
|
9
|
+
execute(ctx: HookContext, finalText: string): Promise<HookResult>;
|
|
13
10
|
private checkToolOutput;
|
|
14
11
|
private checkFinalText;
|
|
15
12
|
}
|
package/dist/hooks/registry.d.ts
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* Hook Registry
|
|
3
3
|
* Manages registration and execution of hooks with priority and dependency support.
|
|
4
4
|
*/
|
|
5
|
-
import type { PreToolUseHook, PostToolUseHook, ChatMessageHook, AssistantDoneHook, HookContext, HookResult, HookMetadata } from "./types.js";
|
|
6
|
-
import { HOOK_ACTIONS } from "./constants.js";
|
|
5
|
+
import type { PreToolUseHook, PostToolUseHook, ChatMessageHook, AssistantDoneHook, HookContext, HookResult, HookMetadata, ChatMessageResult, PreToolResult, ToolInput, ToolOutput } from "./types.js";
|
|
7
6
|
export declare class HookRegistry {
|
|
8
7
|
private static instance;
|
|
9
8
|
private preToolHooks;
|
|
@@ -19,19 +18,8 @@ export declare class HookRegistry {
|
|
|
19
18
|
private prepareMetadata;
|
|
20
19
|
private sortHooks;
|
|
21
20
|
private topologicalSort;
|
|
22
|
-
executePreTool(ctx: HookContext, tool: string, args:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
reason?: string;
|
|
26
|
-
}>;
|
|
27
|
-
executePostTool(ctx: HookContext, tool: string, input: Record<string, unknown>, output: {
|
|
28
|
-
title: string;
|
|
29
|
-
output: string;
|
|
30
|
-
metadata: Record<string, unknown>;
|
|
31
|
-
}): Promise<void>;
|
|
32
|
-
executeChat(ctx: HookContext, message: string): Promise<{
|
|
33
|
-
action: typeof HOOK_ACTIONS.PROCESS | typeof HOOK_ACTIONS.INTERCEPT;
|
|
34
|
-
modifiedMessage?: string;
|
|
35
|
-
}>;
|
|
21
|
+
executePreTool(ctx: HookContext, tool: string, args: ToolInput): Promise<PreToolResult>;
|
|
22
|
+
executePostTool(ctx: HookContext, tool: string, input: ToolInput, output: ToolOutput): Promise<void>;
|
|
23
|
+
executeChat(ctx: HookContext, message: string): Promise<ChatMessageResult>;
|
|
36
24
|
executeDone(ctx: HookContext, finalText: string): Promise<HookResult>;
|
|
37
25
|
}
|
package/dist/hooks/types.d.ts
CHANGED
|
@@ -25,17 +25,31 @@ export type HookResult = {
|
|
|
25
25
|
action: typeof HOOK_ACTIONS.INJECT;
|
|
26
26
|
prompts: string[];
|
|
27
27
|
};
|
|
28
|
+
export type ToolInput = Record<string, unknown>;
|
|
29
|
+
export interface ToolOutput {
|
|
30
|
+
title: string;
|
|
31
|
+
output: string;
|
|
32
|
+
metadata: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
export type PreToolResult = {
|
|
35
|
+
action: typeof HOOK_ACTIONS.ALLOW | typeof HOOK_ACTIONS.BLOCK | typeof HOOK_ACTIONS.MODIFY;
|
|
36
|
+
modifiedArgs?: ToolInput;
|
|
37
|
+
reason?: string;
|
|
38
|
+
};
|
|
39
|
+
export type PostToolResult = {
|
|
40
|
+
output?: string;
|
|
41
|
+
};
|
|
42
|
+
export type ChatMessageResult = {
|
|
43
|
+
action: typeof HOOK_ACTIONS.PROCESS | typeof HOOK_ACTIONS.INTERCEPT;
|
|
44
|
+
modifiedMessage?: string;
|
|
45
|
+
};
|
|
28
46
|
/**
|
|
29
47
|
* Pre-Tool Execution Hook
|
|
30
48
|
* Runs before a tool is executed. Can block execution or modify arguments.
|
|
31
49
|
*/
|
|
32
50
|
export interface PreToolUseHook {
|
|
33
51
|
name: string;
|
|
34
|
-
execute(context: HookContext, tool: string, args:
|
|
35
|
-
action: typeof HOOK_ACTIONS.ALLOW | typeof HOOK_ACTIONS.BLOCK | typeof HOOK_ACTIONS.MODIFY;
|
|
36
|
-
modifiedArgs?: Record<string, unknown>;
|
|
37
|
-
reason?: string;
|
|
38
|
-
}>;
|
|
52
|
+
execute(context: HookContext, tool: string, args: ToolInput): Promise<PreToolResult>;
|
|
39
53
|
}
|
|
40
54
|
/**
|
|
41
55
|
* Post-Tool Execution Hook
|
|
@@ -43,13 +57,7 @@ export interface PreToolUseHook {
|
|
|
43
57
|
*/
|
|
44
58
|
export interface PostToolUseHook {
|
|
45
59
|
name: string;
|
|
46
|
-
execute(context: HookContext, tool: string, input:
|
|
47
|
-
title: string;
|
|
48
|
-
output: string;
|
|
49
|
-
metadata: Record<string, unknown>;
|
|
50
|
-
}): Promise<{
|
|
51
|
-
output?: string;
|
|
52
|
-
}>;
|
|
60
|
+
execute(context: HookContext, tool: string, input: ToolInput, output: ToolOutput): Promise<PostToolResult>;
|
|
53
61
|
}
|
|
54
62
|
/**
|
|
55
63
|
* Chat Message Hook
|
|
@@ -57,10 +65,7 @@ export interface PostToolUseHook {
|
|
|
57
65
|
*/
|
|
58
66
|
export interface ChatMessageHook {
|
|
59
67
|
name: string;
|
|
60
|
-
execute(context: HookContext, message: string): Promise<
|
|
61
|
-
action: typeof HOOK_ACTIONS.PROCESS | typeof HOOK_ACTIONS.INTERCEPT;
|
|
62
|
-
modifiedMessage?: string;
|
|
63
|
-
}>;
|
|
68
|
+
execute(context: HookContext, message: string): Promise<ChatMessageResult>;
|
|
64
69
|
}
|
|
65
70
|
/**
|
|
66
71
|
* Assistant Done Hook
|
package/dist/index.js
CHANGED
|
@@ -1037,7 +1037,7 @@ function show(options) {
|
|
|
1037
1037
|
} catch {
|
|
1038
1038
|
}
|
|
1039
1039
|
}, timeoutMs);
|
|
1040
|
-
const
|
|
1040
|
+
const payload = {
|
|
1041
1041
|
body: {
|
|
1042
1042
|
title: toast.title,
|
|
1043
1043
|
message: toast.message,
|
|
@@ -1045,15 +1045,11 @@ function show(options) {
|
|
|
1045
1045
|
duration: toast.duration
|
|
1046
1046
|
},
|
|
1047
1047
|
signal: ac.signal
|
|
1048
|
+
};
|
|
1049
|
+
Promise.resolve(client.tui.showToast(payload)).finally(() => {
|
|
1050
|
+
clearTimeout(timer);
|
|
1051
|
+
}).catch(() => {
|
|
1048
1052
|
});
|
|
1049
|
-
if (promise3 && typeof promise3.then === "function") {
|
|
1050
|
-
Promise.resolve(promise3).finally(() => {
|
|
1051
|
-
if (timer) {
|
|
1052
|
-
clearTimeout(timer);
|
|
1053
|
-
}
|
|
1054
|
-
}).catch(() => {
|
|
1055
|
-
});
|
|
1056
|
-
}
|
|
1057
1053
|
} catch {
|
|
1058
1054
|
}
|
|
1059
1055
|
}
|
|
@@ -36891,30 +36887,26 @@ function normalizeContinuationContext(state2, input) {
|
|
|
36891
36887
|
// src/core/orchestrator/session-manager.ts
|
|
36892
36888
|
function ensureSessionInitialized(sessions, sessionID, directory) {
|
|
36893
36889
|
if (!sessions.has(sessionID)) {
|
|
36894
|
-
const
|
|
36895
|
-
const newSession = {
|
|
36896
|
-
active: true,
|
|
36897
|
-
step: 0,
|
|
36898
|
-
timestamp: now,
|
|
36899
|
-
startTime: now,
|
|
36900
|
-
lastStepTime: now,
|
|
36901
|
-
lastCompletedMessageID: void 0,
|
|
36902
|
-
lastUserMessageAt: void 0,
|
|
36903
|
-
lastAssistantCompletedAt: void 0,
|
|
36904
|
-
lastAbortAt: void 0,
|
|
36905
|
-
tokens: { totalInput: 0, totalOutput: 0, estimatedCost: 0 }
|
|
36906
|
-
};
|
|
36890
|
+
const newSession2 = createManagedSession();
|
|
36907
36891
|
if (directory) {
|
|
36908
36892
|
const diskState = readLoopState(directory);
|
|
36909
36893
|
if (diskState && diskState.sessionID === sessionID) {
|
|
36910
|
-
|
|
36911
|
-
|
|
36894
|
+
newSession2.step = diskState.iteration;
|
|
36895
|
+
newSession2.startTime = new Date(diskState.startedAt).getTime();
|
|
36912
36896
|
log(`[SessionManager] Rehydrated session from disk: ${sessionID}`);
|
|
36913
36897
|
}
|
|
36914
36898
|
}
|
|
36915
|
-
sessions.set(sessionID,
|
|
36899
|
+
sessions.set(sessionID, newSession2);
|
|
36900
|
+
return newSession2;
|
|
36916
36901
|
}
|
|
36917
|
-
|
|
36902
|
+
const session = sessions.get(sessionID);
|
|
36903
|
+
if (isManagedSessionState(session)) return session;
|
|
36904
|
+
if (isRecord(session)) {
|
|
36905
|
+
return normalizeManagedSession(session);
|
|
36906
|
+
}
|
|
36907
|
+
const newSession = createManagedSession();
|
|
36908
|
+
sessions.set(sessionID, newSession);
|
|
36909
|
+
return newSession;
|
|
36918
36910
|
}
|
|
36919
36911
|
function ensureGlobalState(sessionID, directory) {
|
|
36920
36912
|
let stateSession = state.sessions.get(sessionID);
|
|
@@ -36978,6 +36970,43 @@ function updateSessionTokens(sessions, sessionID, inputLen, outputLen) {
|
|
|
36978
36970
|
const cost = session.tokens.totalInput / 1e3 * COST_PER_1K_INPUT + session.tokens.totalOutput / 1e3 * COST_PER_1K_OUTPUT;
|
|
36979
36971
|
session.tokens.estimatedCost = Number(cost.toFixed(4));
|
|
36980
36972
|
}
|
|
36973
|
+
function createManagedSession() {
|
|
36974
|
+
const now = Date.now();
|
|
36975
|
+
return {
|
|
36976
|
+
active: true,
|
|
36977
|
+
step: 0,
|
|
36978
|
+
timestamp: now,
|
|
36979
|
+
startTime: now,
|
|
36980
|
+
lastStepTime: now,
|
|
36981
|
+
lastCompletedMessageID: void 0,
|
|
36982
|
+
lastUserMessageAt: void 0,
|
|
36983
|
+
lastAssistantCompletedAt: void 0,
|
|
36984
|
+
lastAbortAt: void 0,
|
|
36985
|
+
tokens: { totalInput: 0, totalOutput: 0, estimatedCost: 0 }
|
|
36986
|
+
};
|
|
36987
|
+
}
|
|
36988
|
+
function normalizeManagedSession(session) {
|
|
36989
|
+
const now = Date.now();
|
|
36990
|
+
if (typeof session.active !== "boolean") session.active = true;
|
|
36991
|
+
if (typeof session.step !== "number") session.step = 0;
|
|
36992
|
+
if (typeof session.timestamp !== "number") session.timestamp = now;
|
|
36993
|
+
if (typeof session.startTime !== "number") session.startTime = now;
|
|
36994
|
+
if (typeof session.lastStepTime !== "number") session.lastStepTime = now;
|
|
36995
|
+
if (!isTokenUsage(session.tokens)) {
|
|
36996
|
+
session.tokens = { totalInput: 0, totalOutput: 0, estimatedCost: 0 };
|
|
36997
|
+
}
|
|
36998
|
+
return session;
|
|
36999
|
+
}
|
|
37000
|
+
function isManagedSessionState(value) {
|
|
37001
|
+
return isRecord(value) && typeof value.active === "boolean" && typeof value.step === "number" && typeof value.timestamp === "number" && typeof value.startTime === "number" && typeof value.lastStepTime === "number" && isTokenUsage(value.tokens);
|
|
37002
|
+
}
|
|
37003
|
+
function isRecord(value) {
|
|
37004
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37005
|
+
}
|
|
37006
|
+
function isTokenUsage(value) {
|
|
37007
|
+
if (!isRecord(value)) return false;
|
|
37008
|
+
return typeof value.totalInput === "number" && typeof value.totalOutput === "number" && typeof value.estimatedCost === "number";
|
|
37009
|
+
}
|
|
36981
37010
|
function recordAnomaly(sessionID) {
|
|
36982
37011
|
const session = ensureGlobalState(sessionID);
|
|
36983
37012
|
session.anomalyCount = (session.anomalyCount || 0) + 1;
|
|
@@ -37000,6 +37029,7 @@ var SanityCheckHook = class {
|
|
|
37000
37029
|
if (toolOrText === TOOL_NAMES.CALL_AGENT) {
|
|
37001
37030
|
return this.checkToolOutput(ctx, input, output);
|
|
37002
37031
|
}
|
|
37032
|
+
return {};
|
|
37003
37033
|
} else {
|
|
37004
37034
|
return this.checkFinalText(ctx, toolOrText);
|
|
37005
37035
|
}
|
|
@@ -37008,7 +37038,7 @@ var SanityCheckHook = class {
|
|
|
37008
37038
|
const sanityResult = checkOutputSanity(toolOutput.output);
|
|
37009
37039
|
if (!sanityResult.isHealthy) {
|
|
37010
37040
|
const count = recordAnomaly(ctx.sessionID);
|
|
37011
|
-
const agentName = toolInput?.agent
|
|
37041
|
+
const agentName = typeof toolInput?.agent === "string" ? toolInput.agent : "unknown";
|
|
37012
37042
|
const recoveryText = count >= 2 ? ESCALATION_PROMPT : RECOVERY_PROMPT;
|
|
37013
37043
|
const errorMsg = MISSION_MESSAGES.ANOMALY_DETECTED_TITLE(agentName.toUpperCase()) + "\n\n" + MISSION_MESSAGES.ANOMALY_DETECTED_BODY(sanityResult.reason || "Unknown anomaly", count, recoveryText);
|
|
37014
37044
|
return { output: errorMsg };
|
|
@@ -37756,7 +37786,7 @@ var MissionControlHook = class {
|
|
|
37756
37786
|
deactivateMissionState(sessionID);
|
|
37757
37787
|
clearSession2(sessionID);
|
|
37758
37788
|
const session = sessions.get(sessionID);
|
|
37759
|
-
if (
|
|
37789
|
+
if (isRecord2(session)) {
|
|
37760
37790
|
session.active = false;
|
|
37761
37791
|
}
|
|
37762
37792
|
}
|
|
@@ -37872,11 +37902,11 @@ var MissionControlHook = class {
|
|
|
37872
37902
|
}
|
|
37873
37903
|
}
|
|
37874
37904
|
};
|
|
37875
|
-
function
|
|
37905
|
+
function isRecord2(value) {
|
|
37876
37906
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37877
37907
|
}
|
|
37878
37908
|
function isMissionSessionState(value) {
|
|
37879
|
-
return
|
|
37909
|
+
return isRecord2(value) && typeof value.step === "number" && typeof value.startTime === "number" && typeof value.lastStepTime === "number";
|
|
37880
37910
|
}
|
|
37881
37911
|
|
|
37882
37912
|
// src/hooks/custom/strict-role-guard.ts
|
|
@@ -37909,7 +37939,7 @@ var StrictRoleGuardHook = class {
|
|
|
37909
37939
|
name = HOOK_NAMES2.STRICT_ROLE_GUARD;
|
|
37910
37940
|
async execute(ctx, tool2, args) {
|
|
37911
37941
|
if (tool2 === TOOL_NAMES.RUN_COMMAND || tool2 === TOOL_NAMES.RUN_BACKGROUND) {
|
|
37912
|
-
const cmd = args
|
|
37942
|
+
const cmd = typeof args.command === "string" ? args.command : void 0;
|
|
37913
37943
|
if (cmd) {
|
|
37914
37944
|
if (cmd.includes(SECURITY_PATTERNS.FORK_BOMB)) {
|
|
37915
37945
|
return { action: HOOK_ACTIONS.BLOCK, reason: MISSION_MESSAGES.BLOCK_REASON_FORK_BOMB };
|
|
@@ -37948,14 +37978,15 @@ var AgentUIHook = class {
|
|
|
37948
37978
|
name = HOOK_NAMES2.AGENT_UI;
|
|
37949
37979
|
async execute(ctx, tool2, input, output) {
|
|
37950
37980
|
if (tool2 !== TOOL_NAMES.CALL_AGENT) return {};
|
|
37951
|
-
|
|
37952
|
-
|
|
37981
|
+
const task = typeof input.task === "string" ? input.task : void 0;
|
|
37982
|
+
if (task) {
|
|
37983
|
+
const taskIdMatch = task.match(UI_PATTERNS.TASK_ID);
|
|
37953
37984
|
if (taskIdMatch) {
|
|
37954
37985
|
updateCurrentTask(ctx.sessionID, taskIdMatch[1].toUpperCase());
|
|
37955
37986
|
}
|
|
37956
37987
|
}
|
|
37957
|
-
|
|
37958
|
-
|
|
37988
|
+
const agentName = typeof input.agent === "string" ? input.agent : void 0;
|
|
37989
|
+
if (agentName) {
|
|
37959
37990
|
const indicator = agentName[0].toUpperCase();
|
|
37960
37991
|
const header = MISSION_MESSAGES.AGENT_HEADER_FORMAT(indicator, agentName.toUpperCase());
|
|
37961
37992
|
if (!output.output.startsWith("[" + indicator + "]")) {
|
|
@@ -38072,25 +38103,21 @@ var ResourceControlHook = class {
|
|
|
38072
38103
|
name = HOOK_NAMES2.RESOURCE_CONTROL;
|
|
38073
38104
|
lastCompactionTime = /* @__PURE__ */ new Map();
|
|
38074
38105
|
async execute(ctx, toolOrText, input, output) {
|
|
38075
|
-
|
|
38076
|
-
|
|
38077
|
-
|
|
38078
|
-
|
|
38079
|
-
inputLen = inputStr.length;
|
|
38080
|
-
}
|
|
38081
|
-
if (output) {
|
|
38082
|
-
const outputStr = typeof output === "string" ? output : JSON.stringify(output);
|
|
38083
|
-
outputLen = outputStr.length;
|
|
38084
|
-
}
|
|
38085
|
-
if (arguments.length === 2 && typeof toolOrText === "string") {
|
|
38106
|
+
const isAssistantDone = input === void 0 && output === void 0;
|
|
38107
|
+
const inputLen = isAssistantDone ? 0 : getSerializedLength(input);
|
|
38108
|
+
let outputLen = getSerializedLength(output);
|
|
38109
|
+
if (isAssistantDone) {
|
|
38086
38110
|
outputLen = toolOrText.length;
|
|
38087
38111
|
}
|
|
38088
38112
|
updateSessionTokens(ctx.sessions, ctx.sessionID, inputLen, outputLen);
|
|
38113
|
+
if (!isAssistantDone) {
|
|
38114
|
+
return {};
|
|
38115
|
+
}
|
|
38089
38116
|
const session = ctx.sessions.get(ctx.sessionID);
|
|
38090
38117
|
return this.checkMemoryHealth(ctx, session);
|
|
38091
38118
|
}
|
|
38092
38119
|
async checkMemoryHealth(ctx, session) {
|
|
38093
|
-
if (!session
|
|
38120
|
+
if (!hasTokenUsage(session)) return { action: HOOK_ACTIONS.CONTINUE };
|
|
38094
38121
|
const totalUsed = session.tokens.totalInput + session.tokens.totalOutput;
|
|
38095
38122
|
const maxTokens = CONTEXT_MONITOR_CONFIG.DEFAULT_MAX_TOKENS;
|
|
38096
38123
|
const usage = calculateUsage(totalUsed, maxTokens);
|
|
@@ -38112,6 +38139,22 @@ var ResourceControlHook = class {
|
|
|
38112
38139
|
};
|
|
38113
38140
|
}
|
|
38114
38141
|
};
|
|
38142
|
+
function getSerializedLength(value) {
|
|
38143
|
+
if (value === void 0 || value === null) return 0;
|
|
38144
|
+
if (typeof value === "string") return value.length;
|
|
38145
|
+
try {
|
|
38146
|
+
return JSON.stringify(value)?.length ?? 0;
|
|
38147
|
+
} catch {
|
|
38148
|
+
return String(value).length;
|
|
38149
|
+
}
|
|
38150
|
+
}
|
|
38151
|
+
function hasTokenUsage(session) {
|
|
38152
|
+
if (typeof session !== "object" || session === null || Array.isArray(session)) return false;
|
|
38153
|
+
const tokens = session.tokens;
|
|
38154
|
+
if (typeof tokens !== "object" || tokens === null || Array.isArray(tokens)) return false;
|
|
38155
|
+
const candidate = tokens;
|
|
38156
|
+
return typeof candidate.totalInput === "number" && typeof candidate.totalOutput === "number";
|
|
38157
|
+
}
|
|
38115
38158
|
|
|
38116
38159
|
// src/core/loop/todo-continuation.ts
|
|
38117
38160
|
init_shared();
|
|
@@ -41183,11 +41226,11 @@ var CONCURRENCY_KEYS = [
|
|
|
41183
41226
|
"providerConcurrency",
|
|
41184
41227
|
"modelConcurrency"
|
|
41185
41228
|
];
|
|
41186
|
-
function
|
|
41229
|
+
function isRecord3(value) {
|
|
41187
41230
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41188
41231
|
}
|
|
41189
41232
|
function readLimitMap(value) {
|
|
41190
|
-
if (!
|
|
41233
|
+
if (!isRecord3(value)) return void 0;
|
|
41191
41234
|
const result = {};
|
|
41192
41235
|
for (const [key, limit] of Object.entries(value)) {
|
|
41193
41236
|
if (typeof limit === "number" && Number.isFinite(limit) && limit >= 0) {
|
|
@@ -41197,7 +41240,7 @@ function readLimitMap(value) {
|
|
|
41197
41240
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
41198
41241
|
}
|
|
41199
41242
|
function extractConcurrencyConfig(source) {
|
|
41200
|
-
if (!
|
|
41243
|
+
if (!isRecord3(source)) return {};
|
|
41201
41244
|
const config3 = {};
|
|
41202
41245
|
if (typeof source.defaultConcurrency === "number" && source.defaultConcurrency >= 0) {
|
|
41203
41246
|
config3.defaultConcurrency = source.defaultConcurrency;
|
|
@@ -41211,7 +41254,7 @@ function extractConcurrencyConfig(source) {
|
|
|
41211
41254
|
return config3;
|
|
41212
41255
|
}
|
|
41213
41256
|
function hasConcurrencyConfig(source) {
|
|
41214
|
-
if (!
|
|
41257
|
+
if (!isRecord3(source)) return false;
|
|
41215
41258
|
return CONCURRENCY_KEYS.some((key) => source[key] !== void 0);
|
|
41216
41259
|
}
|
|
41217
41260
|
function mergeConcurrencyConfig(base, override) {
|
|
@@ -41235,14 +41278,14 @@ function mergeConcurrencyConfig(base, override) {
|
|
|
41235
41278
|
|
|
41236
41279
|
// src/core/config/plugin-options.ts
|
|
41237
41280
|
function parseOrchestratorPluginOptions(options) {
|
|
41238
|
-
const source =
|
|
41281
|
+
const source = isRecord4(options) ? options : {};
|
|
41239
41282
|
return {
|
|
41240
41283
|
concurrency: extractConcurrencyConfig(source),
|
|
41241
41284
|
missionLoop: readMissionLoopOptions(source.missionLoop)
|
|
41242
41285
|
};
|
|
41243
41286
|
}
|
|
41244
41287
|
function readMissionLoopOptions(value) {
|
|
41245
|
-
if (!
|
|
41288
|
+
if (!isRecord4(value)) return DEFAULT_MISSION_RUNTIME_OPTIONS;
|
|
41246
41289
|
return {
|
|
41247
41290
|
ledger: readBoolean(value.ledger, DEFAULT_MISSION_RUNTIME_OPTIONS.ledger),
|
|
41248
41291
|
markdownMemory: readBoolean(value.markdownMemory, DEFAULT_MISSION_RUNTIME_OPTIONS.markdownMemory),
|
|
@@ -41258,7 +41301,7 @@ function readBoolean(value, fallback) {
|
|
|
41258
41301
|
function readPositiveInteger(value, fallback) {
|
|
41259
41302
|
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : fallback;
|
|
41260
41303
|
}
|
|
41261
|
-
function
|
|
41304
|
+
function isRecord4(value) {
|
|
41262
41305
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41263
41306
|
}
|
|
41264
41307
|
|
|
@@ -41380,7 +41423,7 @@ This plugin runs in "Claude Code Compatibility Mode".
|
|
|
41380
41423
|
}
|
|
41381
41424
|
|
|
41382
41425
|
// src/plugin-handlers/config-handler.ts
|
|
41383
|
-
function
|
|
41426
|
+
function isRecord5(value) {
|
|
41384
41427
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41385
41428
|
}
|
|
41386
41429
|
function isPermissionAction(value) {
|
|
@@ -41390,10 +41433,10 @@ function mergePermission(globalPermission, agentPermission) {
|
|
|
41390
41433
|
if (agentPermission === void 0) {
|
|
41391
41434
|
return globalPermission;
|
|
41392
41435
|
}
|
|
41393
|
-
if (
|
|
41436
|
+
if (isRecord5(globalPermission) && isRecord5(agentPermission)) {
|
|
41394
41437
|
return { ...globalPermission, ...agentPermission };
|
|
41395
41438
|
}
|
|
41396
|
-
if (isPermissionAction(globalPermission) &&
|
|
41439
|
+
if (isPermissionAction(globalPermission) && isRecord5(agentPermission)) {
|
|
41397
41440
|
return { "*": globalPermission, ...agentPermission };
|
|
41398
41441
|
}
|
|
41399
41442
|
return agentPermission;
|
|
@@ -43081,7 +43124,7 @@ Use \`delegate_task\` with background=true for parallel work.
|
|
|
43081
43124
|
// src/index.ts
|
|
43082
43125
|
var require2 = createRequire(import.meta.url);
|
|
43083
43126
|
var { version: PLUGIN_VERSION } = require2("../package.json");
|
|
43084
|
-
function
|
|
43127
|
+
function isRecord6(value) {
|
|
43085
43128
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
43086
43129
|
}
|
|
43087
43130
|
function readStringField(source, key) {
|
|
@@ -43089,11 +43132,11 @@ function readStringField(source, key) {
|
|
|
43089
43132
|
return typeof value === "string" ? value : void 0;
|
|
43090
43133
|
}
|
|
43091
43134
|
function readCreatedSessionID(properties) {
|
|
43092
|
-
if (!
|
|
43135
|
+
if (!isRecord6(properties)) return void 0;
|
|
43093
43136
|
const directID = readStringField(properties, "sessionID") ?? readStringField(properties, "id");
|
|
43094
43137
|
if (directID) return directID;
|
|
43095
43138
|
const info = properties.info;
|
|
43096
|
-
return
|
|
43139
|
+
return isRecord6(info) ? readStringField(info, "sessionID") : void 0;
|
|
43097
43140
|
}
|
|
43098
43141
|
var OrchestratorPlugin = async (input, options) => {
|
|
43099
43142
|
const { directory, client } = input;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export interface CachedDiagnostics {
|
|
2
|
-
diagnostics:
|
|
2
|
+
diagnostics: string;
|
|
3
3
|
timestamp: number;
|
|
4
4
|
filesMtime: number;
|
|
5
5
|
}
|
|
6
6
|
export declare class DiagnosticsCache {
|
|
7
7
|
private cache;
|
|
8
8
|
private defaultTTL;
|
|
9
|
-
get(directory: string, file?: string): Promise<
|
|
10
|
-
set(directory: string, file: string | undefined, diagnostics:
|
|
9
|
+
get(directory: string, file?: string): Promise<string | null>;
|
|
10
|
+
set(directory: string, file: string | undefined, diagnostics: string): Promise<void>;
|
|
11
11
|
private getCacheKey;
|
|
12
12
|
private getFilesMtime;
|
|
13
13
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "opencode-orchestrator",
|
|
3
3
|
"displayName": "OpenCode Orchestrator",
|
|
4
4
|
"description": "Multi-agent mission control for OpenCode with Commander, Planner, Worker, and Reviewer workflows.",
|
|
5
|
-
"version": "1.3.
|
|
5
|
+
"version": "1.3.7",
|
|
6
6
|
"author": "agnusdei1207",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|