claude-opencode-mcp 1.0.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/CHANGELOG.md +56 -0
- package/LICENSE +21 -0
- package/README.md +514 -0
- package/SECURITY.md +80 -0
- package/agents/deepseek-coder.md +32 -0
- package/agents/deepseek-researcher.md +36 -0
- package/agents/deepseek-reviewer.md +31 -0
- package/agents/deepseek-tester.md +31 -0
- package/dist/cli/init.d.ts +6 -0
- package/dist/cli/init.js +208 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/config/config.d.ts +109 -0
- package/dist/config/config.js +163 -0
- package/dist/config/config.js.map +1 -0
- package/dist/errors.d.ts +29 -0
- package/dist/errors.js +68 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/execute.d.ts +30 -0
- package/dist/mcp/execute.js +128 -0
- package/dist/mcp/execute.js.map +1 -0
- package/dist/mcp/server.d.ts +19 -0
- package/dist/mcp/server.js +38 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/session-utils.d.ts +5 -0
- package/dist/mcp/session-utils.js +55 -0
- package/dist/mcp/session-utils.js.map +1 -0
- package/dist/mcp/tool-utils.d.ts +11 -0
- package/dist/mcp/tool-utils.js +44 -0
- package/dist/mcp/tool-utils.js.map +1 -0
- package/dist/mcp/tools/abort-session.d.ts +3 -0
- package/dist/mcp/tools/abort-session.js +48 -0
- package/dist/mcp/tools/abort-session.js.map +1 -0
- package/dist/mcp/tools/create-session.d.ts +3 -0
- package/dist/mcp/tools/create-session.js +53 -0
- package/dist/mcp/tools/create-session.js.map +1 -0
- package/dist/mcp/tools/delegate-task.d.ts +4 -0
- package/dist/mcp/tools/delegate-task.js +98 -0
- package/dist/mcp/tools/delegate-task.js.map +1 -0
- package/dist/mcp/tools/get-diff.d.ts +3 -0
- package/dist/mcp/tools/get-diff.js +97 -0
- package/dist/mcp/tools/get-diff.js.map +1 -0
- package/dist/mcp/tools/get-session.d.ts +3 -0
- package/dist/mcp/tools/get-session.js +79 -0
- package/dist/mcp/tools/get-session.js.map +1 -0
- package/dist/mcp/tools/list-agents.d.ts +3 -0
- package/dist/mcp/tools/list-agents.js +72 -0
- package/dist/mcp/tools/list-agents.js.map +1 -0
- package/dist/mcp/tools/send-message.d.ts +3 -0
- package/dist/mcp/tools/send-message.js +59 -0
- package/dist/mcp/tools/send-message.js.map +1 -0
- package/dist/opencode/agents.d.ts +46 -0
- package/dist/opencode/agents.js +239 -0
- package/dist/opencode/agents.js.map +1 -0
- package/dist/opencode/binary.d.ts +19 -0
- package/dist/opencode/binary.js +129 -0
- package/dist/opencode/binary.js.map +1 -0
- package/dist/opencode/client.d.ts +32 -0
- package/dist/opencode/client.js +55 -0
- package/dist/opencode/client.js.map +1 -0
- package/dist/opencode/manager.d.ts +66 -0
- package/dist/opencode/manager.js +492 -0
- package/dist/opencode/manager.js.map +1 -0
- package/dist/opencode/permission-watcher.d.ts +26 -0
- package/dist/opencode/permission-watcher.js +144 -0
- package/dist/opencode/permission-watcher.js.map +1 -0
- package/dist/opencode/run.d.ts +39 -0
- package/dist/opencode/run.js +318 -0
- package/dist/opencode/run.js.map +1 -0
- package/dist/opencode/sessions.d.ts +26 -0
- package/dist/opencode/sessions.js +105 -0
- package/dist/opencode/sessions.js.map +1 -0
- package/dist/opencode/setup.d.ts +38 -0
- package/dist/opencode/setup.js +109 -0
- package/dist/opencode/setup.js.map +1 -0
- package/dist/security/paths.d.ts +20 -0
- package/dist/security/paths.js +93 -0
- package/dist/security/paths.js.map +1 -0
- package/dist/security/policy.d.ts +17 -0
- package/dist/security/policy.js +86 -0
- package/dist/security/policy.js.map +1 -0
- package/dist/types/index.d.ts +131 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/util/fs.d.ts +12 -0
- package/dist/util/fs.js +73 -0
- package/dist/util/fs.js.map +1 -0
- package/dist/util/git.d.ts +54 -0
- package/dist/util/git.js +202 -0
- package/dist/util/git.js.map +1 -0
- package/dist/util/logger.d.ts +21 -0
- package/dist/util/logger.js +129 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/text.d.ts +11 -0
- package/dist/util/text.js +126 -0
- package/dist/util/text.js.map +1 -0
- package/dist/workspace/context.d.ts +12 -0
- package/dist/workspace/context.js +67 -0
- package/dist/workspace/context.js.map +1 -0
- package/dist/workspace/resolver.d.ts +35 -0
- package/dist/workspace/resolver.js +112 -0
- package/dist/workspace/resolver.js.map +1 -0
- package/dist/workspace/validator.d.ts +13 -0
- package/dist/workspace/validator.js +102 -0
- package/dist/workspace/validator.js.map +1 -0
- package/docs/agent-configuration.md +100 -0
- package/docs/architecture.md +115 -0
- package/docs/claude-code-setup.md +116 -0
- package/docs/configuration.md +184 -0
- package/docs/contributing.md +71 -0
- package/docs/deepseek-setup.md +84 -0
- package/docs/development.md +146 -0
- package/docs/installation.md +88 -0
- package/docs/opencode-setup.md +97 -0
- package/docs/security-audit.md +80 -0
- package/docs/security.md +128 -0
- package/docs/troubleshooting.md +126 -0
- package/docs/workspace-model.md +126 -0
- package/package.json +79 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { basicAuthHeader } from "./client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Listens to the OpenCode event stream and rejects permission requests that
|
|
4
|
+
* would otherwise wait forever (the bridge is headless: there is no human to
|
|
5
|
+
* answer an `ask` rule). The bridge's own agents never emit `ask` rules, but a
|
|
6
|
+
* user's global OpenCode configuration might.
|
|
7
|
+
*/
|
|
8
|
+
export class PermissionWatcher {
|
|
9
|
+
baseUrl;
|
|
10
|
+
auth;
|
|
11
|
+
logger;
|
|
12
|
+
active = new Set();
|
|
13
|
+
controller = null;
|
|
14
|
+
loopPromise = null;
|
|
15
|
+
stopped = false;
|
|
16
|
+
constructor(baseUrl, auth, logger) {
|
|
17
|
+
this.baseUrl = baseUrl;
|
|
18
|
+
this.auth = auth;
|
|
19
|
+
this.logger = logger;
|
|
20
|
+
}
|
|
21
|
+
activate(sessionId) {
|
|
22
|
+
this.active.add(sessionId);
|
|
23
|
+
this.ensureStarted();
|
|
24
|
+
}
|
|
25
|
+
deactivate(sessionId) {
|
|
26
|
+
this.active.delete(sessionId);
|
|
27
|
+
}
|
|
28
|
+
ensureStarted() {
|
|
29
|
+
if (this.stopped || this.loopPromise)
|
|
30
|
+
return;
|
|
31
|
+
this.controller = new AbortController();
|
|
32
|
+
this.loopPromise = this.loop(this.controller.signal).finally(() => {
|
|
33
|
+
this.loopPromise = null;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async stop() {
|
|
37
|
+
this.stopped = true;
|
|
38
|
+
this.controller?.abort();
|
|
39
|
+
try {
|
|
40
|
+
await this.loopPromise;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// ignore
|
|
44
|
+
}
|
|
45
|
+
this.loopPromise = null;
|
|
46
|
+
}
|
|
47
|
+
async loop(signal) {
|
|
48
|
+
let delay = 1000;
|
|
49
|
+
while (!signal.aborted) {
|
|
50
|
+
try {
|
|
51
|
+
await this.consume(signal);
|
|
52
|
+
delay = 1000;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (signal.aborted)
|
|
56
|
+
return;
|
|
57
|
+
this.logger.debug("permission watcher stream disconnected; retrying", {
|
|
58
|
+
delayMs: delay,
|
|
59
|
+
error: error instanceof Error ? error.message : String(error),
|
|
60
|
+
});
|
|
61
|
+
await sleep(delay, signal);
|
|
62
|
+
delay = Math.min(delay * 2, 10_000);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async consume(signal) {
|
|
67
|
+
const headers = { accept: "text/event-stream" };
|
|
68
|
+
if (this.auth)
|
|
69
|
+
headers.Authorization = basicAuthHeader(this.auth);
|
|
70
|
+
const response = await fetch(`${this.baseUrl}/event`, { headers, signal });
|
|
71
|
+
if (!response.ok || !response.body) {
|
|
72
|
+
throw new Error(`event stream responded with ${response.status}`);
|
|
73
|
+
}
|
|
74
|
+
const reader = response.body.getReader();
|
|
75
|
+
const decoder = new TextDecoder();
|
|
76
|
+
let buffer = "";
|
|
77
|
+
while (!signal.aborted) {
|
|
78
|
+
const { value, done } = await reader.read();
|
|
79
|
+
if (done)
|
|
80
|
+
break;
|
|
81
|
+
buffer += decoder.decode(value, { stream: true });
|
|
82
|
+
let index = buffer.indexOf("\n");
|
|
83
|
+
while (index !== -1) {
|
|
84
|
+
const line = buffer.slice(0, index);
|
|
85
|
+
buffer = buffer.slice(index + 1);
|
|
86
|
+
this.handleLine(line);
|
|
87
|
+
index = buffer.indexOf("\n");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
handleLine(line) {
|
|
92
|
+
const trimmed = line.trim();
|
|
93
|
+
if (!trimmed.startsWith("data:"))
|
|
94
|
+
return;
|
|
95
|
+
const payload = trimmed.slice("data:".length).trim();
|
|
96
|
+
if (!payload || payload === "[DONE]")
|
|
97
|
+
return;
|
|
98
|
+
let event;
|
|
99
|
+
try {
|
|
100
|
+
event = JSON.parse(payload);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (event.type !== "permission.updated")
|
|
106
|
+
return;
|
|
107
|
+
const permission = event.properties;
|
|
108
|
+
if (!permission?.id || !permission.sessionID)
|
|
109
|
+
return;
|
|
110
|
+
if (!this.active.has(permission.sessionID))
|
|
111
|
+
return;
|
|
112
|
+
void this.reject(permission);
|
|
113
|
+
}
|
|
114
|
+
async reject(permission) {
|
|
115
|
+
this.logger.warn("auto-rejecting OpenCode permission request (headless bridge)", {
|
|
116
|
+
sessionID: permission.sessionID,
|
|
117
|
+
permissionID: permission.id,
|
|
118
|
+
type: permission.type,
|
|
119
|
+
title: permission.title,
|
|
120
|
+
});
|
|
121
|
+
const headers = { "content-type": "application/json" };
|
|
122
|
+
if (this.auth)
|
|
123
|
+
headers.Authorization = basicAuthHeader(this.auth);
|
|
124
|
+
try {
|
|
125
|
+
await fetch(`${this.baseUrl}/session/${encodeURIComponent(permission.sessionID)}/permissions/${encodeURIComponent(permission.id)}`, { method: "POST", headers, body: JSON.stringify({ response: "reject" }) });
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
this.logger.warn("failed to reject permission request", {
|
|
129
|
+
permissionID: permission.id,
|
|
130
|
+
error: error instanceof Error ? error.message : String(error),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function sleep(ms, signal) {
|
|
136
|
+
return new Promise((resolve) => {
|
|
137
|
+
const timer = setTimeout(resolve, ms);
|
|
138
|
+
signal?.addEventListener("abort", () => {
|
|
139
|
+
clearTimeout(timer);
|
|
140
|
+
resolve();
|
|
141
|
+
}, { once: true });
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=permission-watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-watcher.js","sourceRoot":"","sources":["../../src/opencode/permission-watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { OpencodeClient, Part } from "@opencode-ai/sdk";
|
|
2
|
+
import type { ResolvedConfig } from "../config/config.js";
|
|
3
|
+
import type { RunProgress, RunResult } from "../types/index.js";
|
|
4
|
+
import type { Logger } from "../util/logger.js";
|
|
5
|
+
export interface ModelRef {
|
|
6
|
+
providerID: string;
|
|
7
|
+
modelID: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseModelRef(model: string, defaultProvider: string): ModelRef;
|
|
10
|
+
export declare function formatModelRef(ref: ModelRef | null): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve which model a delegated run should use.
|
|
13
|
+
*
|
|
14
|
+
* Priority: explicit request > bridge configuration > provider default from
|
|
15
|
+
* the running OpenCode instance. Nothing is hard-coded to DeepSeek: the
|
|
16
|
+
* provider comes from `defaults.provider`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveModel(client: OpencodeClient, config: ResolvedConfig, requested?: string | null): Promise<ModelRef | null>;
|
|
19
|
+
export declare function assistantText(parts: Part[] | undefined): string;
|
|
20
|
+
interface RunErrorInfo {
|
|
21
|
+
code: string;
|
|
22
|
+
message: string;
|
|
23
|
+
details?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
export declare function describeError(error: unknown): RunErrorInfo;
|
|
26
|
+
export interface RunPromptInput {
|
|
27
|
+
client: OpencodeClient;
|
|
28
|
+
sessionId: string;
|
|
29
|
+
agent: string;
|
|
30
|
+
model: ModelRef | null;
|
|
31
|
+
text: string;
|
|
32
|
+
timeoutMs: number;
|
|
33
|
+
disableEdits?: boolean;
|
|
34
|
+
onProgress?: (progress: RunProgress) => void | Promise<void>;
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
logger: Logger;
|
|
37
|
+
}
|
|
38
|
+
export declare function runPrompt(input: RunPromptInput): Promise<RunResult>;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { BridgeError } from "../errors.js";
|
|
2
|
+
import { extractFindings, stripAnsi } from "../util/text.js";
|
|
3
|
+
export function parseModelRef(model, defaultProvider) {
|
|
4
|
+
const trimmed = model.trim();
|
|
5
|
+
if (!trimmed) {
|
|
6
|
+
throw new BridgeError("INVALID_ARGUMENT", "model must not be empty");
|
|
7
|
+
}
|
|
8
|
+
const slash = trimmed.indexOf("/");
|
|
9
|
+
if (slash > 0 && slash < trimmed.length - 1) {
|
|
10
|
+
return { providerID: trimmed.slice(0, slash), modelID: trimmed.slice(slash + 1) };
|
|
11
|
+
}
|
|
12
|
+
return { providerID: defaultProvider, modelID: trimmed };
|
|
13
|
+
}
|
|
14
|
+
export function formatModelRef(ref) {
|
|
15
|
+
return ref ? `${ref.providerID}/${ref.modelID}` : null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolve which model a delegated run should use.
|
|
19
|
+
*
|
|
20
|
+
* Priority: explicit request > bridge configuration > provider default from
|
|
21
|
+
* the running OpenCode instance. Nothing is hard-coded to DeepSeek: the
|
|
22
|
+
* provider comes from `defaults.provider`.
|
|
23
|
+
*/
|
|
24
|
+
export async function resolveModel(client, config, requested) {
|
|
25
|
+
const raw = requested?.trim() ? requested.trim() : config.defaults.model;
|
|
26
|
+
if (raw)
|
|
27
|
+
return parseModelRef(raw, config.defaults.provider);
|
|
28
|
+
let defaults = {};
|
|
29
|
+
try {
|
|
30
|
+
const result = await client.config.providers();
|
|
31
|
+
defaults = result.data?.default ?? {};
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
defaults = {};
|
|
35
|
+
}
|
|
36
|
+
const modelID = defaults[config.defaults.provider];
|
|
37
|
+
if (modelID) {
|
|
38
|
+
return { providerID: config.defaults.provider, modelID };
|
|
39
|
+
}
|
|
40
|
+
throw new BridgeError("MODEL_NOT_AVAILABLE", [
|
|
41
|
+
`No default model is available for provider "${config.defaults.provider}".`,
|
|
42
|
+
'Set `defaults.model` (for example "deepseek/deepseek-v4-pro") in the bridge config,',
|
|
43
|
+
"or configure a default model in OpenCode, or pass `model` to delegate_task.",
|
|
44
|
+
].join(" "), { details: { provider: config.defaults.provider, availableDefaults: defaults } });
|
|
45
|
+
}
|
|
46
|
+
export function assistantText(parts) {
|
|
47
|
+
if (!parts)
|
|
48
|
+
return "";
|
|
49
|
+
return parts
|
|
50
|
+
.filter((part) => part.type === "text")
|
|
51
|
+
.filter((part) => !part.synthetic && !part.ignored)
|
|
52
|
+
.map((part) => part.text)
|
|
53
|
+
.join("\n\n")
|
|
54
|
+
.trim();
|
|
55
|
+
}
|
|
56
|
+
export function describeError(error) {
|
|
57
|
+
const record = error;
|
|
58
|
+
const name = record?.name ?? "UnknownError";
|
|
59
|
+
const data = record?.data ?? {};
|
|
60
|
+
switch (name) {
|
|
61
|
+
case "ProviderAuthError":
|
|
62
|
+
return {
|
|
63
|
+
code: "OPENCODE_ERROR",
|
|
64
|
+
message: `Provider authentication failed for ${String(data.providerID ?? "provider")}: ${String(data.message ?? "unknown error")}`,
|
|
65
|
+
details: { providerID: data.providerID },
|
|
66
|
+
};
|
|
67
|
+
case "MessageAbortedError":
|
|
68
|
+
return { code: "AGENT_ABORTED", message: "The delegated run was aborted." };
|
|
69
|
+
case "MessageOutputLengthError":
|
|
70
|
+
return {
|
|
71
|
+
code: "AGENT_EXECUTION_FAILED",
|
|
72
|
+
message: "The model hit its output length limit before finishing.",
|
|
73
|
+
};
|
|
74
|
+
case "APIError":
|
|
75
|
+
case "ApiError":
|
|
76
|
+
return {
|
|
77
|
+
code: "AGENT_EXECUTION_FAILED",
|
|
78
|
+
message: String(data.message ?? "The model provider returned an error."),
|
|
79
|
+
details: {
|
|
80
|
+
statusCode: data.statusCode,
|
|
81
|
+
responseBody: typeof data.responseBody === "string" ? data.responseBody.slice(0, 2000) : undefined,
|
|
82
|
+
isRetryable: data.isRetryable,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
default:
|
|
86
|
+
return {
|
|
87
|
+
code: "AGENT_EXECUTION_FAILED",
|
|
88
|
+
message: String(data.message ?? "The delegated run failed."),
|
|
89
|
+
details: { name },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function latestActivity(client, sessionId) {
|
|
94
|
+
try {
|
|
95
|
+
const result = await client.session.messages({ path: { id: sessionId }, query: { limit: 5 } });
|
|
96
|
+
const messages = result.data ?? [];
|
|
97
|
+
const last = messages[messages.length - 1];
|
|
98
|
+
if (!last)
|
|
99
|
+
return null;
|
|
100
|
+
const parts = last.parts ?? [];
|
|
101
|
+
for (let index = parts.length - 1; index >= 0; index -= 1) {
|
|
102
|
+
const part = parts[index];
|
|
103
|
+
if (!part)
|
|
104
|
+
continue;
|
|
105
|
+
if (part.type === "tool") {
|
|
106
|
+
const status = part.state && "status" in part.state ? part.state.status : "running";
|
|
107
|
+
return `${status === "running" ? "running" : status} ${part.tool}`;
|
|
108
|
+
}
|
|
109
|
+
if (part.type === "reasoning")
|
|
110
|
+
return "reasoning";
|
|
111
|
+
if (part.type === "text")
|
|
112
|
+
return "writing response";
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const POLL_INTERVAL_MS = 1500;
|
|
121
|
+
export async function runPrompt(input) {
|
|
122
|
+
const startedAt = Date.now();
|
|
123
|
+
let abortedByCaller = false;
|
|
124
|
+
let pollTimer = null;
|
|
125
|
+
let timeoutTimer = null;
|
|
126
|
+
const abortSession = async () => {
|
|
127
|
+
try {
|
|
128
|
+
await input.client.session.abort({ path: { id: input.sessionId } });
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// best effort
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const onSignalAbort = () => {
|
|
135
|
+
abortedByCaller = true;
|
|
136
|
+
void abortSession();
|
|
137
|
+
};
|
|
138
|
+
if (input.signal) {
|
|
139
|
+
if (input.signal.aborted) {
|
|
140
|
+
throw new BridgeError("AGENT_ABORTED", "Delegated run was cancelled before it started.");
|
|
141
|
+
}
|
|
142
|
+
input.signal.addEventListener("abort", onSignalAbort, { once: true });
|
|
143
|
+
}
|
|
144
|
+
const emit = async (progress) => {
|
|
145
|
+
if (!input.onProgress)
|
|
146
|
+
return;
|
|
147
|
+
try {
|
|
148
|
+
await input.onProgress(progress);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// progress reporting must never break the run
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const startPolling = () => {
|
|
155
|
+
if (!input.onProgress)
|
|
156
|
+
return;
|
|
157
|
+
const tick = async () => {
|
|
158
|
+
const elapsed = Date.now() - startedAt;
|
|
159
|
+
let message = "working…";
|
|
160
|
+
try {
|
|
161
|
+
const statusResult = await input.client.session.status();
|
|
162
|
+
const status = statusResult.data?.[input.sessionId];
|
|
163
|
+
if (status?.type === "retry") {
|
|
164
|
+
message = `retrying after provider error (attempt ${status.attempt})`;
|
|
165
|
+
}
|
|
166
|
+
else if (status?.type === "busy") {
|
|
167
|
+
message = "working…";
|
|
168
|
+
}
|
|
169
|
+
const activity = await latestActivity(input.client, input.sessionId);
|
|
170
|
+
if (activity)
|
|
171
|
+
message = activity;
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// keep the previous message
|
|
175
|
+
}
|
|
176
|
+
await emit({ progress: Math.min(90, 5 + Math.floor(elapsed / 1000)), message });
|
|
177
|
+
};
|
|
178
|
+
void tick();
|
|
179
|
+
pollTimer = setInterval(() => void tick(), POLL_INTERVAL_MS);
|
|
180
|
+
pollTimer.unref?.();
|
|
181
|
+
};
|
|
182
|
+
const stopPolling = () => {
|
|
183
|
+
if (pollTimer)
|
|
184
|
+
clearInterval(pollTimer);
|
|
185
|
+
pollTimer = null;
|
|
186
|
+
if (timeoutTimer)
|
|
187
|
+
clearTimeout(timeoutTimer);
|
|
188
|
+
timeoutTimer = null;
|
|
189
|
+
input.signal?.removeEventListener("abort", onSignalAbort);
|
|
190
|
+
};
|
|
191
|
+
const body = {
|
|
192
|
+
agent: input.agent,
|
|
193
|
+
parts: [{ type: "text", text: input.text }],
|
|
194
|
+
...(input.model ? { model: input.model } : {}),
|
|
195
|
+
...(input.disableEdits ? { tools: { edit: false, write: false, apply_patch: false } } : {}),
|
|
196
|
+
};
|
|
197
|
+
startPolling();
|
|
198
|
+
const promptPromise = input.client.session
|
|
199
|
+
.prompt({ path: { id: input.sessionId }, body })
|
|
200
|
+
.then((result) => ({ kind: "result", result }))
|
|
201
|
+
.catch((error) => ({ kind: "thrown", error }));
|
|
202
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
203
|
+
timeoutTimer = setTimeout(() => {
|
|
204
|
+
void abortSession();
|
|
205
|
+
resolve({ kind: "timeout" });
|
|
206
|
+
}, input.timeoutMs);
|
|
207
|
+
timeoutTimer.unref?.();
|
|
208
|
+
});
|
|
209
|
+
const outcome = await Promise.race([promptPromise, timeoutPromise]);
|
|
210
|
+
stopPolling();
|
|
211
|
+
const durationMs = Date.now() - startedAt;
|
|
212
|
+
if (outcome.kind === "timeout") {
|
|
213
|
+
await emit({ progress: 95, message: "timed out; aborting session" });
|
|
214
|
+
return {
|
|
215
|
+
status: "timeout",
|
|
216
|
+
summary: "",
|
|
217
|
+
findings: [],
|
|
218
|
+
error: {
|
|
219
|
+
code: "AGENT_TIMEOUT",
|
|
220
|
+
message: `Delegated run exceeded ${input.timeoutMs}ms and was aborted.`,
|
|
221
|
+
details: { timeout_ms: input.timeoutMs },
|
|
222
|
+
},
|
|
223
|
+
durationMs,
|
|
224
|
+
truncated: false,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
if (abortedByCaller) {
|
|
228
|
+
throw new BridgeError("AGENT_ABORTED", "Delegated run was cancelled by the caller.");
|
|
229
|
+
}
|
|
230
|
+
if (outcome.kind === "thrown") {
|
|
231
|
+
const error = outcome.error;
|
|
232
|
+
if (error instanceof BridgeError)
|
|
233
|
+
throw error;
|
|
234
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
235
|
+
throw new BridgeError("OPENCODE_UNAVAILABLE", `OpenCode request failed: ${message}`, {
|
|
236
|
+
cause: error,
|
|
237
|
+
retryable: true,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const { data, error } = outcome.result;
|
|
241
|
+
if (error) {
|
|
242
|
+
const mapped = describeError(error);
|
|
243
|
+
return {
|
|
244
|
+
status: "failed",
|
|
245
|
+
summary: "",
|
|
246
|
+
findings: [],
|
|
247
|
+
error: {
|
|
248
|
+
code: mapped.code,
|
|
249
|
+
message: mapped.message,
|
|
250
|
+
...(mapped.details ? { details: mapped.details } : {}),
|
|
251
|
+
},
|
|
252
|
+
durationMs,
|
|
253
|
+
truncated: false,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
const info = data?.info;
|
|
257
|
+
if (!info) {
|
|
258
|
+
return {
|
|
259
|
+
status: "failed",
|
|
260
|
+
summary: "",
|
|
261
|
+
findings: [],
|
|
262
|
+
error: { code: "OPENCODE_ERROR", message: "OpenCode returned an empty assistant message." },
|
|
263
|
+
durationMs,
|
|
264
|
+
truncated: false,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (info.error) {
|
|
268
|
+
const mapped = describeError(info.error);
|
|
269
|
+
if (mapped.code === "AGENT_ABORTED" && abortedByCaller) {
|
|
270
|
+
throw new BridgeError("AGENT_ABORTED", "Delegated run was cancelled by the caller.");
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
status: "failed",
|
|
274
|
+
summary: "",
|
|
275
|
+
findings: [],
|
|
276
|
+
error: {
|
|
277
|
+
code: mapped.code,
|
|
278
|
+
message: mapped.message,
|
|
279
|
+
...(mapped.details ? { details: mapped.details } : {}),
|
|
280
|
+
},
|
|
281
|
+
durationMs,
|
|
282
|
+
...(info.id ? { messageID: info.id } : {}),
|
|
283
|
+
truncated: false,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
let summary = stripAnsi(assistantText(data?.parts));
|
|
287
|
+
if (!summary) {
|
|
288
|
+
summary = await fallbackLatestText(input.client, input.sessionId);
|
|
289
|
+
}
|
|
290
|
+
await emit({ progress: 100, message: "completed" });
|
|
291
|
+
return {
|
|
292
|
+
status: "completed",
|
|
293
|
+
summary,
|
|
294
|
+
findings: extractFindings(summary),
|
|
295
|
+
durationMs,
|
|
296
|
+
...(info.id ? { messageID: info.id } : {}),
|
|
297
|
+
truncated: false,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
async function fallbackLatestText(client, sessionId) {
|
|
301
|
+
try {
|
|
302
|
+
const result = await client.session.messages({ path: { id: sessionId }, query: { limit: 10 } });
|
|
303
|
+
const messages = result.data ?? [];
|
|
304
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
305
|
+
const message = messages[index];
|
|
306
|
+
if (message?.info.role !== "assistant")
|
|
307
|
+
continue;
|
|
308
|
+
const text = assistantText(message.parts);
|
|
309
|
+
if (text)
|
|
310
|
+
return stripAnsi(text);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
// ignored
|
|
315
|
+
}
|
|
316
|
+
return "";
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/opencode/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AgentSession, SessionStatus } from "../types/index.js";
|
|
2
|
+
import type { Logger } from "../util/logger.js";
|
|
3
|
+
export declare class SessionRegistry {
|
|
4
|
+
private readonly sessions;
|
|
5
|
+
private readonly file;
|
|
6
|
+
private readonly logger;
|
|
7
|
+
constructor(file: string | null, logger: Logger);
|
|
8
|
+
private load;
|
|
9
|
+
private persist;
|
|
10
|
+
get(id: string): AgentSession | null;
|
|
11
|
+
upsert(session: AgentSession): AgentSession;
|
|
12
|
+
update(id: string, patch: Partial<AgentSession>): AgentSession | null;
|
|
13
|
+
setStatus(id: string, status: SessionStatus): AgentSession | null;
|
|
14
|
+
delete(id: string): boolean;
|
|
15
|
+
list(): AgentSession[];
|
|
16
|
+
findByDirectory(cwd: string): AgentSession[];
|
|
17
|
+
}
|
|
18
|
+
export declare function createSessionRecord(input: {
|
|
19
|
+
id: string;
|
|
20
|
+
cwd: string;
|
|
21
|
+
agent: string;
|
|
22
|
+
provider: string | null;
|
|
23
|
+
model: string | null;
|
|
24
|
+
title: string | null;
|
|
25
|
+
baseline?: AgentSession["baseline"];
|
|
26
|
+
}): AgentSession;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { readJsonFileSync, writeFileAtomicSync } from "../util/fs.js";
|
|
2
|
+
const MAX_SESSION_AGE_MS = 14 * 24 * 60 * 60 * 1000;
|
|
3
|
+
export class SessionRegistry {
|
|
4
|
+
sessions = new Map();
|
|
5
|
+
file;
|
|
6
|
+
logger;
|
|
7
|
+
constructor(file, logger) {
|
|
8
|
+
this.file = file;
|
|
9
|
+
this.logger = logger;
|
|
10
|
+
this.load();
|
|
11
|
+
}
|
|
12
|
+
load() {
|
|
13
|
+
if (!this.file)
|
|
14
|
+
return;
|
|
15
|
+
let data = null;
|
|
16
|
+
try {
|
|
17
|
+
data = readJsonFileSync(this.file);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
this.logger.warn("failed to read session registry; starting empty", {
|
|
21
|
+
file: this.file,
|
|
22
|
+
error: error instanceof Error ? error.message : String(error),
|
|
23
|
+
});
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (data?.version !== 1 || !Array.isArray(data.sessions))
|
|
27
|
+
return;
|
|
28
|
+
const cutoff = Date.now() - MAX_SESSION_AGE_MS;
|
|
29
|
+
for (const session of data.sessions) {
|
|
30
|
+
if (!session?.id)
|
|
31
|
+
continue;
|
|
32
|
+
const updated = Date.parse(session.updatedAt ?? session.createdAt ?? "");
|
|
33
|
+
if (Number.isFinite(updated) && updated < cutoff)
|
|
34
|
+
continue;
|
|
35
|
+
this.sessions.set(session.id, session);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
persist() {
|
|
39
|
+
if (!this.file)
|
|
40
|
+
return;
|
|
41
|
+
const payload = { version: 1, sessions: [...this.sessions.values()] };
|
|
42
|
+
try {
|
|
43
|
+
// 0o600: the registry contains agent output summaries and workspace paths.
|
|
44
|
+
writeFileAtomicSync(this.file, `${JSON.stringify(payload, null, 2)}\n`, { mode: 0o600 });
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
this.logger.warn("failed to persist session registry", {
|
|
48
|
+
file: this.file,
|
|
49
|
+
error: error instanceof Error ? error.message : String(error),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
get(id) {
|
|
54
|
+
return this.sessions.get(id) ?? null;
|
|
55
|
+
}
|
|
56
|
+
upsert(session) {
|
|
57
|
+
this.sessions.set(session.id, session);
|
|
58
|
+
this.persist();
|
|
59
|
+
return session;
|
|
60
|
+
}
|
|
61
|
+
update(id, patch) {
|
|
62
|
+
const existing = this.sessions.get(id);
|
|
63
|
+
if (!existing)
|
|
64
|
+
return null;
|
|
65
|
+
const updated = {
|
|
66
|
+
...existing,
|
|
67
|
+
...patch,
|
|
68
|
+
updatedAt: new Date().toISOString(),
|
|
69
|
+
};
|
|
70
|
+
this.sessions.set(id, updated);
|
|
71
|
+
this.persist();
|
|
72
|
+
return updated;
|
|
73
|
+
}
|
|
74
|
+
setStatus(id, status) {
|
|
75
|
+
return this.update(id, { status });
|
|
76
|
+
}
|
|
77
|
+
delete(id) {
|
|
78
|
+
const deleted = this.sessions.delete(id);
|
|
79
|
+
if (deleted)
|
|
80
|
+
this.persist();
|
|
81
|
+
return deleted;
|
|
82
|
+
}
|
|
83
|
+
list() {
|
|
84
|
+
return [...this.sessions.values()].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
85
|
+
}
|
|
86
|
+
findByDirectory(cwd) {
|
|
87
|
+
return this.list().filter((session) => session.cwd === cwd);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export function createSessionRecord(input) {
|
|
91
|
+
const now = new Date().toISOString();
|
|
92
|
+
return {
|
|
93
|
+
id: input.id,
|
|
94
|
+
cwd: input.cwd,
|
|
95
|
+
agent: input.agent,
|
|
96
|
+
provider: input.provider,
|
|
97
|
+
model: input.model,
|
|
98
|
+
title: input.title,
|
|
99
|
+
status: "pending",
|
|
100
|
+
createdAt: now,
|
|
101
|
+
updatedAt: now,
|
|
102
|
+
...(input.baseline ? { baseline: input.baseline } : {}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/opencode/sessions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAQtE,MAAM,kBAAkB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEpD,MAAM,OAAO,eAAe;IACT,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC3C,IAAI,CAAgB;IACpB,MAAM,CAAS;IAEhC,YAAY,IAAmB,EAAE,MAAc;QAC7C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO;QACvB,IAAI,IAAI,GAAwB,IAAI,CAAC;QACrC,IAAI,CAAC;YACH,IAAI,GAAG,gBAAgB,CAAe,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iDAAiD,EAAE;gBAClE,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,IAAI,IAAI,EAAE,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO;QACjE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,CAAC;QAC/C,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,CAAC,OAAO,EAAE,EAAE;gBAAE,SAAS;YAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;YACzE,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,MAAM;gBAAE,SAAS;YAC3D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO;QACvB,MAAM,OAAO,GAAiB,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QACpF,IAAI,CAAC;YACH,2EAA2E;YAC3E,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE;gBACrD,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;IACvC,CAAC;IAED,MAAM,CAAC,OAAqB;QAC1B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,EAAU,EAAE,KAA4B;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC3B,MAAM,OAAO,GAAiB;YAC5B,GAAG,QAAQ;YACX,GAAG,KAAK;YACR,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,SAAS,CAAC,EAAU,EAAE,MAAqB;QACzC,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,EAAU;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzC,IAAI,OAAO;YAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5F,CAAC;IAED,eAAe,CAAC,GAAW;QACzB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IAC9D,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,KAQnC;IACC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;QACd,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxD,CAAC;AACJ,CAAC"}
|