mcp-server-opencode 1.1.5 → 1.3.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 +127 -0
- package/README.md +34 -5
- package/build/src/index.js +32 -15
- package/build/src/index.js.map +1 -1
- package/build/src/modules/shared/execution-report.d.ts +66 -0
- package/build/src/modules/shared/execution-report.d.ts.map +1 -0
- package/build/src/modules/shared/execution-report.js +407 -0
- package/build/src/modules/shared/execution-report.js.map +1 -0
- package/build/src/modules/shared/execution-usage.d.ts +50 -0
- package/build/src/modules/shared/execution-usage.d.ts.map +1 -0
- package/build/src/modules/shared/execution-usage.js +89 -0
- package/build/src/modules/shared/execution-usage.js.map +1 -0
- package/build/src/modules/shared/git-workspace.d.ts +34 -0
- package/build/src/modules/shared/git-workspace.d.ts.map +1 -0
- package/build/src/modules/shared/git-workspace.js +193 -0
- package/build/src/modules/shared/git-workspace.js.map +1 -0
- package/build/src/modules/shared/instructions.d.ts +8 -1
- package/build/src/modules/shared/instructions.d.ts.map +1 -1
- package/build/src/modules/shared/instructions.js +32 -27
- package/build/src/modules/shared/instructions.js.map +1 -1
- package/build/src/modules/shared/message-id.d.ts +3 -0
- package/build/src/modules/shared/message-id.d.ts.map +1 -0
- package/build/src/modules/shared/message-id.js +6 -0
- package/build/src/modules/shared/message-id.js.map +1 -0
- package/build/src/modules/shared/opencode-client.d.ts +42 -4
- package/build/src/modules/shared/opencode-client.d.ts.map +1 -1
- package/build/src/modules/shared/opencode-client.js +214 -38
- package/build/src/modules/shared/opencode-client.js.map +1 -1
- package/build/src/modules/shared/permission-scopes.d.ts +6 -0
- package/build/src/modules/shared/permission-scopes.d.ts.map +1 -0
- package/build/src/modules/shared/permission-scopes.js +60 -0
- package/build/src/modules/shared/permission-scopes.js.map +1 -0
- package/build/src/modules/shared/permissions.d.ts +110 -0
- package/build/src/modules/shared/permissions.d.ts.map +1 -0
- package/build/src/modules/shared/permissions.js +214 -0
- package/build/src/modules/shared/permissions.js.map +1 -0
- package/build/src/modules/shared/prompt-dispatch.d.ts +13 -0
- package/build/src/modules/shared/prompt-dispatch.d.ts.map +1 -0
- package/build/src/modules/shared/prompt-dispatch.js +34 -0
- package/build/src/modules/shared/prompt-dispatch.js.map +1 -0
- package/build/src/modules/shared/run-observer.d.ts +5 -0
- package/build/src/modules/shared/run-observer.d.ts.map +1 -0
- package/build/src/modules/shared/run-observer.js +421 -0
- package/build/src/modules/shared/run-observer.js.map +1 -0
- package/build/src/modules/shared/server-registry.d.ts +4 -0
- package/build/src/modules/shared/server-registry.d.ts.map +1 -1
- package/build/src/modules/shared/server-registry.js.map +1 -1
- package/build/src/modules/shared/task-registry.d.ts +75 -0
- package/build/src/modules/shared/task-registry.d.ts.map +1 -1
- package/build/src/modules/shared/task-registry.js +85 -0
- package/build/src/modules/shared/task-registry.js.map +1 -1
- package/build/src/modules/shared/usage-limits.d.ts +70 -0
- package/build/src/modules/shared/usage-limits.d.ts.map +1 -0
- package/build/src/modules/shared/usage-limits.js +296 -0
- package/build/src/modules/shared/usage-limits.js.map +1 -0
- package/build/src/modules/shared/workspace-manager.d.ts +25 -0
- package/build/src/modules/shared/workspace-manager.d.ts.map +1 -0
- package/build/src/modules/shared/workspace-manager.js +105 -0
- package/build/src/modules/shared/workspace-manager.js.map +1 -0
- package/build/src/modules/tools/cancel_task.d.ts.map +1 -1
- package/build/src/modules/tools/cancel_task.js +30 -1
- package/build/src/modules/tools/cancel_task.js.map +1 -1
- package/build/src/modules/tools/cleanup_workspace.d.ts +3 -0
- package/build/src/modules/tools/cleanup_workspace.d.ts.map +1 -0
- package/build/src/modules/tools/cleanup_workspace.js +82 -0
- package/build/src/modules/tools/cleanup_workspace.js.map +1 -0
- package/build/src/modules/tools/continue_task.d.ts.map +1 -1
- package/build/src/modules/tools/continue_task.js +116 -6
- package/build/src/modules/tools/continue_task.js.map +1 -1
- package/build/src/modules/tools/get_task_result.d.ts.map +1 -1
- package/build/src/modules/tools/get_task_result.js +125 -22
- package/build/src/modules/tools/get_task_result.js.map +1 -1
- package/build/src/modules/tools/get_task_status.d.ts.map +1 -1
- package/build/src/modules/tools/get_task_status.js +69 -6
- package/build/src/modules/tools/get_task_status.js.map +1 -1
- package/build/src/modules/tools/index.d.ts.map +1 -1
- package/build/src/modules/tools/index.js +2 -0
- package/build/src/modules/tools/index.js.map +1 -1
- package/build/src/modules/tools/list_agents.d.ts.map +1 -1
- package/build/src/modules/tools/list_agents.js +48 -7
- package/build/src/modules/tools/list_agents.js.map +1 -1
- package/build/src/modules/tools/start_server.d.ts.map +1 -1
- package/build/src/modules/tools/start_server.js +21 -1
- package/build/src/modules/tools/start_server.js.map +1 -1
- package/build/src/modules/tools/start_task.d.ts.map +1 -1
- package/build/src/modules/tools/start_task.js +218 -13
- package/build/src/modules/tools/start_task.js.map +1 -1
- package/build/src/modules/tools/stop_server.d.ts.map +1 -1
- package/build/src/modules/tools/stop_server.js +17 -0
- package/build/src/modules/tools/stop_server.js.map +1 -1
- package/build/src/modules/tools/wait_for_task.d.ts.map +1 -1
- package/build/src/modules/tools/wait_for_task.js +110 -24
- package/build/src/modules/tools/wait_for_task.js.map +1 -1
- package/package.json +4 -2
|
@@ -1,69 +1,209 @@
|
|
|
1
1
|
import { createOpencodeClient, } from "@opencode-ai/sdk";
|
|
2
|
+
import { buildExecutionUsage } from "./execution-usage.js";
|
|
2
3
|
import { getServer } from "./server-registry.js";
|
|
3
4
|
import { getTask } from "./task-registry.js";
|
|
5
|
+
const SDK_REQUEST_TIMEOUT_MS = 30_000;
|
|
6
|
+
export async function fetchWithDeadline(request) {
|
|
7
|
+
const controller = new AbortController();
|
|
8
|
+
const abortFromRequest = () => controller.abort(request.signal.reason);
|
|
9
|
+
request.signal.addEventListener("abort", abortFromRequest, { once: true });
|
|
10
|
+
const timer = setTimeout(() => controller.abort(new Error("OpenCode request deadline exceeded")), SDK_REQUEST_TIMEOUT_MS);
|
|
11
|
+
timer.unref?.();
|
|
12
|
+
try {
|
|
13
|
+
return await fetch(new Request(request, { signal: controller.signal }));
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
clearTimeout(timer);
|
|
17
|
+
request.signal.removeEventListener("abort", abortFromRequest);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
4
20
|
/** Build an HTTP client for a tracked server, or undefined if the id is unknown. */
|
|
5
|
-
export function clientForServer(serverId) {
|
|
21
|
+
export function clientForServer(serverId, directory) {
|
|
6
22
|
const server = getServer(serverId);
|
|
7
23
|
if (!server)
|
|
8
24
|
return undefined;
|
|
9
|
-
|
|
25
|
+
const selectedDirectory = directory ?? server.directory;
|
|
26
|
+
return createOpencodeClient({
|
|
27
|
+
baseUrl: server.baseUrl,
|
|
28
|
+
fetch: fetchWithDeadline,
|
|
29
|
+
...(selectedDirectory ? { directory: selectedDirectory } : {}),
|
|
30
|
+
});
|
|
10
31
|
}
|
|
11
32
|
/** Resolve a task to its server client and session id, or undefined if unknown. */
|
|
12
33
|
export function clientForTask(taskId) {
|
|
13
34
|
const task = getTask(taskId);
|
|
14
35
|
if (!task)
|
|
15
36
|
return undefined;
|
|
16
|
-
const client = clientForServer(task.serverId);
|
|
37
|
+
const client = clientForServer(task.serverId, task.directory);
|
|
17
38
|
if (!client)
|
|
18
39
|
return undefined;
|
|
19
40
|
return { client, sessionId: task.sessionId };
|
|
20
41
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
42
|
+
export function isTerminalTaskStatus(status) {
|
|
43
|
+
return ["completed", "failed", "empty", "cancelled", "error"].includes(status);
|
|
44
|
+
}
|
|
45
|
+
export function sdkResponseError(response) {
|
|
46
|
+
return typeof response === "object" && response !== null && "error" in response
|
|
47
|
+
? response.error
|
|
48
|
+
: undefined;
|
|
49
|
+
}
|
|
50
|
+
/** Fetch every assistant message (with its parts) for a session, oldest first. */
|
|
51
|
+
export async function assistantEntries(client, sessionId, signal) {
|
|
52
|
+
const res = await client.session.messages({ path: { id: sessionId }, signal });
|
|
53
|
+
if (sdkResponseError(res))
|
|
54
|
+
throw sdkResponseError(res);
|
|
55
|
+
const entries = [];
|
|
56
|
+
for (const message of res.data ?? []) {
|
|
57
|
+
if (message.info.role === "assistant") {
|
|
58
|
+
entries.push({ info: message.info, parts: message.parts });
|
|
29
59
|
}
|
|
30
60
|
}
|
|
31
|
-
return
|
|
61
|
+
return entries;
|
|
62
|
+
}
|
|
63
|
+
function entriesForCurrentRun(entries, taskId) {
|
|
64
|
+
const task = getTask(taskId);
|
|
65
|
+
const run = task?.runs?.find((item) => item.run_id === task.currentRunId);
|
|
66
|
+
if (!run)
|
|
67
|
+
return entries;
|
|
68
|
+
return entries.filter((entry) => entry.info.parentID === run.message_id);
|
|
69
|
+
}
|
|
70
|
+
export async function currentRunEntries(client, sessionId, taskId) {
|
|
71
|
+
return entriesForCurrentRun(await assistantEntries(client, sessionId), taskId);
|
|
72
|
+
}
|
|
73
|
+
/** Every part the assistant emitted across the whole session, oldest first. */
|
|
74
|
+
export function sessionParts(entries) {
|
|
75
|
+
return entries.flatMap((entry) => entry.parts);
|
|
76
|
+
}
|
|
77
|
+
/** Fetch the most recent assistant message (with its parts) for a session. */
|
|
78
|
+
export async function lastAssistantEntry(client, sessionId) {
|
|
79
|
+
return (await assistantEntries(client, sessionId)).at(-1);
|
|
32
80
|
}
|
|
33
81
|
const TEXT_SNIPPET_MAX_LENGTH = 500;
|
|
82
|
+
/**
|
|
83
|
+
* Tools that can change the workspace. Verified against the live tool catalog
|
|
84
|
+
* (`client.tool.ids()` on opencode 1.18.18): the patch tool is `apply_patch`,
|
|
85
|
+
* and there is no `list` tool. `task` delegates to a subagent, which can write
|
|
86
|
+
* through any of the others.
|
|
87
|
+
*/
|
|
88
|
+
const MUTATING_TOOLS = new Set(["write", "edit", "apply_patch", "bash", "task"]);
|
|
89
|
+
/**
|
|
90
|
+
* Whether an assistant turn actually produced anything.
|
|
91
|
+
*
|
|
92
|
+
* A completed timestamp only says the turn ended, not that it did work: an
|
|
93
|
+
* aborted or rejected turn carries a completed timestamp with no parts at all,
|
|
94
|
+
* which is byte-for-byte indistinguishable from a task that succeeded quietly.
|
|
95
|
+
*/
|
|
96
|
+
export function hasWork(parts) {
|
|
97
|
+
for (const part of parts) {
|
|
98
|
+
if (part.type === "text" && part.text.trim() !== "")
|
|
99
|
+
return true;
|
|
100
|
+
if (part.type === "tool")
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
34
105
|
/**
|
|
35
106
|
* How long an idle session may stay without any assistant message before the
|
|
36
107
|
* task is considered dead (e.g. the fire-and-forget prompt was rejected).
|
|
37
108
|
*/
|
|
38
109
|
export const PENDING_STALL_MS = 15_000;
|
|
39
|
-
/**
|
|
40
|
-
|
|
110
|
+
/**
|
|
111
|
+
* The workspace path a completed tool call wrote to, if it names one.
|
|
112
|
+
*
|
|
113
|
+
* Verified against a live server: `write` and `edit` carry the path as
|
|
114
|
+
* `state.input.filePath`; `bash` carries only `command`, so it counts as
|
|
115
|
+
* mutating without contributing a path.
|
|
116
|
+
*/
|
|
117
|
+
function touchedFilePath(input) {
|
|
118
|
+
const filePath = input.filePath;
|
|
119
|
+
return typeof filePath === "string" && filePath !== "" ? filePath : undefined;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Build a TaskProgress summary.
|
|
123
|
+
*
|
|
124
|
+
* `latest` is the current assistant turn — it drives the text snippet and the
|
|
125
|
+
* in-flight tool. `whole` is every assistant part in the session and drives the
|
|
126
|
+
* side-effect evidence, because an agent's edits land in earlier turns while
|
|
127
|
+
* the final turn is usually just "DONE". Reading evidence off the last message
|
|
128
|
+
* alone reports `files_touched: []` for a task that rewrote the workspace.
|
|
129
|
+
*/
|
|
130
|
+
export function buildProgress(latest, whole = latest) {
|
|
41
131
|
let text = "";
|
|
42
|
-
let toolCallsCompleted = 0;
|
|
43
132
|
let currentTool;
|
|
44
133
|
let currentToolStatus;
|
|
45
|
-
for (const part of
|
|
134
|
+
for (const part of latest) {
|
|
46
135
|
if (part.type === "text") {
|
|
47
136
|
text += part.text;
|
|
48
137
|
continue;
|
|
49
138
|
}
|
|
50
|
-
if (part.type === "tool"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
else if (part.state.status === "running" || part.state.status === "pending") {
|
|
55
|
-
currentTool = part.tool;
|
|
56
|
-
currentToolStatus = part.state.status;
|
|
57
|
-
}
|
|
139
|
+
if (part.type === "tool" &&
|
|
140
|
+
(part.state.status === "running" || part.state.status === "pending")) {
|
|
141
|
+
currentTool = part.tool;
|
|
142
|
+
currentToolStatus = part.state.status;
|
|
58
143
|
}
|
|
59
144
|
}
|
|
145
|
+
let toolCallsCompleted = 0;
|
|
146
|
+
let mutatingToolCalls = 0;
|
|
147
|
+
const filesTouched = new Set();
|
|
148
|
+
for (const part of whole) {
|
|
149
|
+
if (part.type !== "tool" || part.state.status !== "completed")
|
|
150
|
+
continue;
|
|
151
|
+
toolCallsCompleted++;
|
|
152
|
+
if (!MUTATING_TOOLS.has(part.tool))
|
|
153
|
+
continue;
|
|
154
|
+
mutatingToolCalls++;
|
|
155
|
+
const filePath = touchedFilePath(part.state.input);
|
|
156
|
+
if (filePath !== undefined)
|
|
157
|
+
filesTouched.add(filePath);
|
|
158
|
+
}
|
|
60
159
|
return {
|
|
61
160
|
text_snippet: text.slice(-TEXT_SNIPPET_MAX_LENGTH),
|
|
62
161
|
tool_calls_completed: toolCallsCompleted,
|
|
162
|
+
mutating_tool_calls: mutatingToolCalls,
|
|
163
|
+
files_touched: [...filesTouched],
|
|
63
164
|
current_tool: currentTool,
|
|
64
165
|
current_tool_status: currentToolStatus,
|
|
65
166
|
};
|
|
66
167
|
}
|
|
168
|
+
/** Message returned alongside the `cancelled` status, shared by status and result. */
|
|
169
|
+
export const CANCELLED_TASK_MESSAGE = "the task was cancelled via opencode_cancel_task; any output below is whatever the agent produced before the abort";
|
|
170
|
+
/** Message returned alongside the `empty` status, shared by status and result. */
|
|
171
|
+
export const EMPTY_TURN_MESSAGE = "the session finished without producing any text or tool calls; the prompt was likely rejected or the turn was aborted";
|
|
172
|
+
function usageSnapshot(entries, currentMessageID, diagnostic) {
|
|
173
|
+
return {
|
|
174
|
+
captured_at: new Date().toISOString(),
|
|
175
|
+
snapshot_kind: "live_observation",
|
|
176
|
+
report: entries ? buildExecutionUsage(entries, currentMessageID) : null,
|
|
177
|
+
...(diagnostic ? { diagnostic } : {}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async function readObservedEntries(client, sessionId, signal, includeUsage) {
|
|
181
|
+
try {
|
|
182
|
+
return { entries: await assistantEntries(client, sessionId, signal) };
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (!includeUsage)
|
|
186
|
+
throw error;
|
|
187
|
+
return {
|
|
188
|
+
entries: [],
|
|
189
|
+
diagnostic: `usage unavailable: ${error instanceof Error ? error.message : String(error)}`,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export function deriveAssistantTurnStatus(entry) {
|
|
194
|
+
if (!entry)
|
|
195
|
+
return { status: "pending" };
|
|
196
|
+
if (entry.info.error)
|
|
197
|
+
return { status: "failed", error: entry.info.error.name };
|
|
198
|
+
if (!entry.info.time.completed)
|
|
199
|
+
return { status: "running" };
|
|
200
|
+
const failedTool = entry.parts.find((part) => part.type === "tool" && part.state.status === "error");
|
|
201
|
+
if (failedTool?.type === "tool" && failedTool.state.status === "error")
|
|
202
|
+
return { status: "failed", error: `${failedTool.tool} failed: ${failedTool.state.error}` };
|
|
203
|
+
if (!hasWork(entry.parts))
|
|
204
|
+
return { status: "empty", error: EMPTY_TURN_MESSAGE };
|
|
205
|
+
return { status: "completed" };
|
|
206
|
+
}
|
|
67
207
|
/**
|
|
68
208
|
* Derive the current status of a task by inspecting session busy state and
|
|
69
209
|
* the last assistant message. Shared by opencode_get_task_status and
|
|
@@ -71,22 +211,61 @@ export function buildProgress(parts) {
|
|
|
71
211
|
*/
|
|
72
212
|
export async function deriveTaskStatus(client, sessionId, taskId, options) {
|
|
73
213
|
const includeProgress = options?.includeProgress ?? false;
|
|
214
|
+
const includeUsage = options?.includeUsage ?? false;
|
|
215
|
+
const signal = options?.signal;
|
|
216
|
+
// Cancellation wins over everything else: an aborted session keeps its
|
|
217
|
+
// completed timestamp, so any later check would call it `completed`.
|
|
218
|
+
const task = getTask(taskId);
|
|
219
|
+
const currentRun = task?.runs?.find((item) => item.run_id === task.currentRunId);
|
|
220
|
+
const usageMessageID = options?.usageMessageID ?? currentRun?.message_id;
|
|
221
|
+
if (task?.cancelledAt !== undefined || currentRun?.cancelledAt !== undefined) {
|
|
222
|
+
const observed = includeProgress || includeUsage
|
|
223
|
+
? await readObservedEntries(client, sessionId, signal, includeUsage)
|
|
224
|
+
: { entries: [] };
|
|
225
|
+
const allEntries = observed.entries;
|
|
226
|
+
const entries = includeProgress ? entriesForCurrentRun(allEntries, taskId) : [];
|
|
227
|
+
const latest = entries.at(-1);
|
|
228
|
+
return {
|
|
229
|
+
task_id: taskId,
|
|
230
|
+
status: "cancelled",
|
|
231
|
+
error: CANCELLED_TASK_MESSAGE,
|
|
232
|
+
progress: latest ? buildProgress(latest.parts, sessionParts(entries)) : undefined,
|
|
233
|
+
...(includeUsage
|
|
234
|
+
? {
|
|
235
|
+
usage: usageSnapshot(observed.diagnostic ? null : allEntries, usageMessageID, observed.diagnostic),
|
|
236
|
+
}
|
|
237
|
+
: {}),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
74
240
|
// The status map only lists sessions that are actively working.
|
|
75
|
-
const statusRes = await client.session.status();
|
|
241
|
+
const statusRes = await client.session.status({ signal });
|
|
242
|
+
if (sdkResponseError(statusRes))
|
|
243
|
+
throw sdkResponseError(statusRes);
|
|
76
244
|
const sessionStatus = statusRes.data?.[sessionId];
|
|
77
245
|
if (sessionStatus?.type === "busy" || sessionStatus?.type === "retry") {
|
|
78
|
-
if (includeProgress) {
|
|
79
|
-
const
|
|
246
|
+
if (includeProgress || includeUsage) {
|
|
247
|
+
const observed = await readObservedEntries(client, sessionId, signal, includeUsage);
|
|
248
|
+
const allEntries = observed.entries;
|
|
249
|
+
const entries = includeProgress ? entriesForCurrentRun(allEntries, taskId) : [];
|
|
250
|
+
const latest = entries.at(-1);
|
|
80
251
|
return {
|
|
81
252
|
task_id: taskId,
|
|
82
253
|
status: "running",
|
|
83
|
-
progress:
|
|
254
|
+
progress: latest ? buildProgress(latest.parts, sessionParts(entries)) : undefined,
|
|
255
|
+
...(includeUsage
|
|
256
|
+
? {
|
|
257
|
+
usage: usageSnapshot(observed.diagnostic ? null : allEntries, usageMessageID, observed.diagnostic),
|
|
258
|
+
}
|
|
259
|
+
: {}),
|
|
84
260
|
};
|
|
85
261
|
}
|
|
86
262
|
return { task_id: taskId, status: "running" };
|
|
87
263
|
}
|
|
88
264
|
// Not busy: inspect the last assistant message to tell pending from done.
|
|
89
|
-
const
|
|
265
|
+
const allEntries = await assistantEntries(client, sessionId, signal);
|
|
266
|
+
const entries = entriesForCurrentRun(allEntries, taskId);
|
|
267
|
+
const usage = includeUsage ? usageSnapshot(allEntries, usageMessageID) : undefined;
|
|
268
|
+
const entry = entries.at(-1);
|
|
90
269
|
if (!entry) {
|
|
91
270
|
// Idle session with no assistant output: either the prompt was just accepted,
|
|
92
271
|
// or it was silently rejected (fire-and-forget) and will never run. Past the
|
|
@@ -97,20 +276,17 @@ export async function deriveTaskStatus(client, sessionId, taskId, options) {
|
|
|
97
276
|
task_id: taskId,
|
|
98
277
|
status: "failed",
|
|
99
278
|
error: "task produced no output after starting; the prompt was likely rejected (e.g. invalid model or agent)",
|
|
279
|
+
...(usage ? { usage } : {}),
|
|
100
280
|
};
|
|
101
281
|
}
|
|
102
|
-
return { task_id: taskId, status: "pending" };
|
|
103
|
-
}
|
|
104
|
-
if (entry.info.error) {
|
|
105
|
-
return { task_id: taskId, status: "failed", error: entry.info.error.name };
|
|
106
|
-
}
|
|
107
|
-
if (entry.info.time.completed) {
|
|
108
|
-
return { task_id: taskId, status: "completed" };
|
|
282
|
+
return { task_id: taskId, status: "pending", ...(usage ? { usage } : {}) };
|
|
109
283
|
}
|
|
284
|
+
const turn = deriveAssistantTurnStatus(entry);
|
|
110
285
|
return {
|
|
111
286
|
task_id: taskId,
|
|
112
|
-
|
|
113
|
-
progress: includeProgress ? buildProgress(entry.parts) : undefined,
|
|
287
|
+
...turn,
|
|
288
|
+
progress: includeProgress ? buildProgress(entry.parts, sessionParts(entries)) : undefined,
|
|
289
|
+
...(usage ? { usage } : {}),
|
|
114
290
|
};
|
|
115
291
|
}
|
|
116
292
|
//# sourceMappingURL=opencode-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode-client.js","sourceRoot":"","sources":["../../../../src/modules/shared/opencode-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"opencode-client.js","sourceRoot":"","sources":["../../../../src/modules/shared/opencode-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ExternalDirectoryPolicy } from "./permissions.js";
|
|
2
|
+
export declare function registerPermissionSession(serverId: string, directory: string, sessionId: string, policy?: ExternalDirectoryPolicy): void;
|
|
3
|
+
export declare function unregisterPermissionSession(serverId: string, directory: string, sessionId: string): void;
|
|
4
|
+
export declare function stopPermissionScope(serverId: string, directory: string): void;
|
|
5
|
+
export declare function stopPermissionScopesForServer(serverId: string): void;
|
|
6
|
+
//# sourceMappingURL=permission-scopes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-scopes.d.ts","sourceRoot":"","sources":["../../../../src/modules/shared/permission-scopes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,uBAAuB,EAA4B,MAAM,kBAAkB,CAAC;AAc1F,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,uBAAuB,GAC/B,IAAI,CAwBN;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,IAAI,CASN;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAM7E;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAMpE"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createOpencodeClient } from "@opencode-ai/sdk";
|
|
2
|
+
import { fetchWithDeadline } from "./opencode-client.js";
|
|
3
|
+
import { startPermissionResponder } from "./permissions.js";
|
|
4
|
+
import { getServer } from "./server-registry.js";
|
|
5
|
+
const scopes = new Map();
|
|
6
|
+
function scopeKey(serverId, directory) {
|
|
7
|
+
return `${serverId}\0${directory}`;
|
|
8
|
+
}
|
|
9
|
+
export function registerPermissionSession(serverId, directory, sessionId, policy) {
|
|
10
|
+
const key = scopeKey(serverId, directory);
|
|
11
|
+
let scope = scopes.get(key);
|
|
12
|
+
if (!scope) {
|
|
13
|
+
const server = getServer(serverId);
|
|
14
|
+
if (!server)
|
|
15
|
+
throw new Error(`OpenCode server is not registered: ${serverId}`);
|
|
16
|
+
if (!server.permissionScopesEnabled)
|
|
17
|
+
return;
|
|
18
|
+
const sessionIDs = new Set();
|
|
19
|
+
const responder = startPermissionResponder(createOpencodeClient({
|
|
20
|
+
baseUrl: server.baseUrl,
|
|
21
|
+
fetch: fetchWithDeadline,
|
|
22
|
+
directory,
|
|
23
|
+
}), {
|
|
24
|
+
policy: policy ?? server.permissionPolicy,
|
|
25
|
+
allowedSessionIDs: () => sessionIDs,
|
|
26
|
+
onError: (error) => console.error("OpenCode permission responder error:", error),
|
|
27
|
+
});
|
|
28
|
+
scope = { sessionIDs, stop: responder.stop };
|
|
29
|
+
scopes.set(key, scope);
|
|
30
|
+
}
|
|
31
|
+
scope.sessionIDs.add(sessionId);
|
|
32
|
+
}
|
|
33
|
+
export function unregisterPermissionSession(serverId, directory, sessionId) {
|
|
34
|
+
const key = scopeKey(serverId, directory);
|
|
35
|
+
const scope = scopes.get(key);
|
|
36
|
+
if (!scope)
|
|
37
|
+
return;
|
|
38
|
+
scope.sessionIDs.delete(sessionId);
|
|
39
|
+
if (scope.sessionIDs.size === 0) {
|
|
40
|
+
scope.stop();
|
|
41
|
+
scopes.delete(key);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function stopPermissionScope(serverId, directory) {
|
|
45
|
+
const key = scopeKey(serverId, directory);
|
|
46
|
+
const scope = scopes.get(key);
|
|
47
|
+
if (!scope)
|
|
48
|
+
return;
|
|
49
|
+
scope.stop();
|
|
50
|
+
scopes.delete(key);
|
|
51
|
+
}
|
|
52
|
+
export function stopPermissionScopesForServer(serverId) {
|
|
53
|
+
for (const [key, scope] of scopes) {
|
|
54
|
+
if (!key.startsWith(`${serverId}\0`))
|
|
55
|
+
continue;
|
|
56
|
+
scope.stop();
|
|
57
|
+
scopes.delete(key);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=permission-scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-scopes.js","sourceRoot":"","sources":["../../../../src/modules/shared/permission-scopes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { Config, OpencodeClient } from "@opencode-ai/sdk";
|
|
2
|
+
/**
|
|
3
|
+
* A pending permission request, as the OpenCode server actually emits it.
|
|
4
|
+
*
|
|
5
|
+
* The SDK's generated `Permission` type is stale relative to the running
|
|
6
|
+
* binary (verified against opencode 1.18.18 / `@opencode-ai/sdk` 1.17.20):
|
|
7
|
+
* the live event is `permission.asked` rather than `permission.updated`, the
|
|
8
|
+
* permission kind arrives as `permission` rather than `type`, and the call id
|
|
9
|
+
* is nested under `tool`. Both spellings are accepted so this keeps working
|
|
10
|
+
* whichever side moves first.
|
|
11
|
+
*/
|
|
12
|
+
export interface PermissionAsk {
|
|
13
|
+
id: string;
|
|
14
|
+
sessionID: string;
|
|
15
|
+
/** Live server field. */
|
|
16
|
+
permission?: string;
|
|
17
|
+
/** Generated-SDK field. */
|
|
18
|
+
type?: string;
|
|
19
|
+
patterns?: string[];
|
|
20
|
+
always?: string[];
|
|
21
|
+
metadata?: Record<string, unknown>;
|
|
22
|
+
/** Live server nests the originating call here. */
|
|
23
|
+
tool?: {
|
|
24
|
+
messageID?: string;
|
|
25
|
+
callID?: string;
|
|
26
|
+
};
|
|
27
|
+
/** Generated-SDK field. */
|
|
28
|
+
callID?: string;
|
|
29
|
+
}
|
|
30
|
+
/** The permission kind, reading whichever field this server version emits. */
|
|
31
|
+
export declare function permissionKind(ask: PermissionAsk): string | undefined;
|
|
32
|
+
/** The originating tool call id, reading whichever field this server emits. */
|
|
33
|
+
export declare function permissionCallID(ask: PermissionAsk): string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* How the delegated agent may touch paths outside the directory the server was
|
|
36
|
+
* launched in.
|
|
37
|
+
*
|
|
38
|
+
* - `read-only` (default): reads outside the cwd are approved, writes are rejected.
|
|
39
|
+
* - `allow`: no boundary at all — anything outside the cwd is approved.
|
|
40
|
+
* - `deny`: nothing outside the cwd is reachable.
|
|
41
|
+
*/
|
|
42
|
+
export type ExternalDirectoryPolicy = "read-only" | "allow" | "deny";
|
|
43
|
+
export declare const DEFAULT_EXTERNAL_DIRECTORY_POLICY: ExternalDirectoryPolicy;
|
|
44
|
+
/** The permission type OpenCode raises for any path outside the server cwd. */
|
|
45
|
+
export declare const EXTERNAL_DIRECTORY = "external_directory";
|
|
46
|
+
/**
|
|
47
|
+
* Resolve the external-directory policy.
|
|
48
|
+
*
|
|
49
|
+
* Precedence: the `OPENCODE_MCP_EXTERNAL_DIR` environment variable wins over an
|
|
50
|
+
* `OPENCODE_MCP_EXTERNAL_DIR=<policy>` CLI arg, which wins over `read-only`.
|
|
51
|
+
* Unrecognised values fall back to the default.
|
|
52
|
+
*
|
|
53
|
+
* Reads `process.env` / `process.argv` lazily on each call so tests can vary
|
|
54
|
+
* them between invocations without module re-import tricks.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getExternalDirectoryPolicy(): ExternalDirectoryPolicy;
|
|
57
|
+
/**
|
|
58
|
+
* Build the config handed to `createOpencodeServer`.
|
|
59
|
+
*
|
|
60
|
+
* OpenCode deep-merges this over the user's global config per permission key,
|
|
61
|
+
* so only `external_directory` is touched — existing `read` / `edit` / `bash`
|
|
62
|
+
* rules (including deny globs for secrets) survive untouched.
|
|
63
|
+
*
|
|
64
|
+
* `read-only` keeps the key on `ask` on purpose: the permission responder is
|
|
65
|
+
* what applies the read/write split, and it can only do that if OpenCode still
|
|
66
|
+
* raises the request.
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildServerConfig(policy: ExternalDirectoryPolicy): Config;
|
|
69
|
+
export type PermissionResponse = "once" | "always" | "reject";
|
|
70
|
+
export interface PermissionDecision {
|
|
71
|
+
response: PermissionResponse;
|
|
72
|
+
reason: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Decide how to answer a pending permission request.
|
|
76
|
+
*
|
|
77
|
+
* Anything that is not `external_directory` targets the directory the server
|
|
78
|
+
* was launched in, which the caller already owns — approved with `always` so
|
|
79
|
+
* repeat calls stop round-tripping.
|
|
80
|
+
*
|
|
81
|
+
* External reads are approved with `once` rather than `always` on purpose: an
|
|
82
|
+
* `always` reply persists the approval keyed by directory pattern, not by
|
|
83
|
+
* operation, which would silently let a later write into that same directory
|
|
84
|
+
* through and defeat the read-only boundary.
|
|
85
|
+
*/
|
|
86
|
+
export declare function decidePermission(client: OpencodeClient, ask: PermissionAsk, policy: ExternalDirectoryPolicy, sleep?: (ms: number) => Promise<void>): Promise<PermissionDecision>;
|
|
87
|
+
export interface PermissionResponderOptions {
|
|
88
|
+
policy?: ExternalDirectoryPolicy;
|
|
89
|
+
/** Called on stream/reply failures so they never bubble into the MCP server. */
|
|
90
|
+
onError?: (error: unknown) => void;
|
|
91
|
+
/** Called after each answered request; useful for diagnostics and tests. */
|
|
92
|
+
onDecision?: (ask: PermissionAsk, decision: PermissionDecision) => void;
|
|
93
|
+
sleep?: (ms: number) => Promise<void>;
|
|
94
|
+
/** Dynamic allow-list; the root responder must not answer unrelated sessions. */
|
|
95
|
+
allowedSessionIDs?: () => ReadonlySet<string>;
|
|
96
|
+
}
|
|
97
|
+
export interface PermissionResponder {
|
|
98
|
+
stop: () => void;
|
|
99
|
+
/** Resolves once the responder loop has exited. */
|
|
100
|
+
done: Promise<void>;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Answer permission requests for a headless server.
|
|
104
|
+
*
|
|
105
|
+
* Without this, any request configured as `ask` blocks the agent forever: there
|
|
106
|
+
* is no interactive approver behind an MCP-spawned server, so the session stays
|
|
107
|
+
* genuinely busy and the task never completes or fails.
|
|
108
|
+
*/
|
|
109
|
+
export declare function startPermissionResponder(client: OpencodeClient, options?: PermissionResponderOptions): PermissionResponder;
|
|
110
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../src/modules/shared/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,mDAAmD;IACnD,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAErE;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAErE,eAAO,MAAM,iCAAiC,EAAE,uBAAqC,CAAC;AAEtF,+EAA+E;AAC/E,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAyBvD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,IAAI,uBAAuB,CAYpE;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAGzE;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAsCD;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,uBAAuB,EAC/B,KAAK,GAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAgB,GAClD,OAAO,CAAC,kBAAkB,CAAC,CAyB7B;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,gFAAgF;IAChF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,4EAA4E;IAC5E,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACxE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,mDAAmD;IACnD,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACrB;AAMD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,0BAA+B,GACvC,mBAAmB,CAsDrB"}
|