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.
Files changed (121) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/LICENSE +21 -0
  3. package/README.md +514 -0
  4. package/SECURITY.md +80 -0
  5. package/agents/deepseek-coder.md +32 -0
  6. package/agents/deepseek-researcher.md +36 -0
  7. package/agents/deepseek-reviewer.md +31 -0
  8. package/agents/deepseek-tester.md +31 -0
  9. package/dist/cli/init.d.ts +6 -0
  10. package/dist/cli/init.js +208 -0
  11. package/dist/cli/init.js.map +1 -0
  12. package/dist/config/config.d.ts +109 -0
  13. package/dist/config/config.js +163 -0
  14. package/dist/config/config.js.map +1 -0
  15. package/dist/errors.d.ts +29 -0
  16. package/dist/errors.js +68 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +116 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/mcp/execute.d.ts +30 -0
  22. package/dist/mcp/execute.js +128 -0
  23. package/dist/mcp/execute.js.map +1 -0
  24. package/dist/mcp/server.d.ts +19 -0
  25. package/dist/mcp/server.js +38 -0
  26. package/dist/mcp/server.js.map +1 -0
  27. package/dist/mcp/session-utils.d.ts +5 -0
  28. package/dist/mcp/session-utils.js +55 -0
  29. package/dist/mcp/session-utils.js.map +1 -0
  30. package/dist/mcp/tool-utils.d.ts +11 -0
  31. package/dist/mcp/tool-utils.js +44 -0
  32. package/dist/mcp/tool-utils.js.map +1 -0
  33. package/dist/mcp/tools/abort-session.d.ts +3 -0
  34. package/dist/mcp/tools/abort-session.js +48 -0
  35. package/dist/mcp/tools/abort-session.js.map +1 -0
  36. package/dist/mcp/tools/create-session.d.ts +3 -0
  37. package/dist/mcp/tools/create-session.js +53 -0
  38. package/dist/mcp/tools/create-session.js.map +1 -0
  39. package/dist/mcp/tools/delegate-task.d.ts +4 -0
  40. package/dist/mcp/tools/delegate-task.js +98 -0
  41. package/dist/mcp/tools/delegate-task.js.map +1 -0
  42. package/dist/mcp/tools/get-diff.d.ts +3 -0
  43. package/dist/mcp/tools/get-diff.js +97 -0
  44. package/dist/mcp/tools/get-diff.js.map +1 -0
  45. package/dist/mcp/tools/get-session.d.ts +3 -0
  46. package/dist/mcp/tools/get-session.js +79 -0
  47. package/dist/mcp/tools/get-session.js.map +1 -0
  48. package/dist/mcp/tools/list-agents.d.ts +3 -0
  49. package/dist/mcp/tools/list-agents.js +72 -0
  50. package/dist/mcp/tools/list-agents.js.map +1 -0
  51. package/dist/mcp/tools/send-message.d.ts +3 -0
  52. package/dist/mcp/tools/send-message.js +59 -0
  53. package/dist/mcp/tools/send-message.js.map +1 -0
  54. package/dist/opencode/agents.d.ts +46 -0
  55. package/dist/opencode/agents.js +239 -0
  56. package/dist/opencode/agents.js.map +1 -0
  57. package/dist/opencode/binary.d.ts +19 -0
  58. package/dist/opencode/binary.js +129 -0
  59. package/dist/opencode/binary.js.map +1 -0
  60. package/dist/opencode/client.d.ts +32 -0
  61. package/dist/opencode/client.js +55 -0
  62. package/dist/opencode/client.js.map +1 -0
  63. package/dist/opencode/manager.d.ts +66 -0
  64. package/dist/opencode/manager.js +492 -0
  65. package/dist/opencode/manager.js.map +1 -0
  66. package/dist/opencode/permission-watcher.d.ts +26 -0
  67. package/dist/opencode/permission-watcher.js +144 -0
  68. package/dist/opencode/permission-watcher.js.map +1 -0
  69. package/dist/opencode/run.d.ts +39 -0
  70. package/dist/opencode/run.js +318 -0
  71. package/dist/opencode/run.js.map +1 -0
  72. package/dist/opencode/sessions.d.ts +26 -0
  73. package/dist/opencode/sessions.js +105 -0
  74. package/dist/opencode/sessions.js.map +1 -0
  75. package/dist/opencode/setup.d.ts +38 -0
  76. package/dist/opencode/setup.js +109 -0
  77. package/dist/opencode/setup.js.map +1 -0
  78. package/dist/security/paths.d.ts +20 -0
  79. package/dist/security/paths.js +93 -0
  80. package/dist/security/paths.js.map +1 -0
  81. package/dist/security/policy.d.ts +17 -0
  82. package/dist/security/policy.js +86 -0
  83. package/dist/security/policy.js.map +1 -0
  84. package/dist/types/index.d.ts +131 -0
  85. package/dist/types/index.js +2 -0
  86. package/dist/types/index.js.map +1 -0
  87. package/dist/util/fs.d.ts +12 -0
  88. package/dist/util/fs.js +73 -0
  89. package/dist/util/fs.js.map +1 -0
  90. package/dist/util/git.d.ts +54 -0
  91. package/dist/util/git.js +202 -0
  92. package/dist/util/git.js.map +1 -0
  93. package/dist/util/logger.d.ts +21 -0
  94. package/dist/util/logger.js +129 -0
  95. package/dist/util/logger.js.map +1 -0
  96. package/dist/util/text.d.ts +11 -0
  97. package/dist/util/text.js +126 -0
  98. package/dist/util/text.js.map +1 -0
  99. package/dist/workspace/context.d.ts +12 -0
  100. package/dist/workspace/context.js +67 -0
  101. package/dist/workspace/context.js.map +1 -0
  102. package/dist/workspace/resolver.d.ts +35 -0
  103. package/dist/workspace/resolver.js +112 -0
  104. package/dist/workspace/resolver.js.map +1 -0
  105. package/dist/workspace/validator.d.ts +13 -0
  106. package/dist/workspace/validator.js +102 -0
  107. package/dist/workspace/validator.js.map +1 -0
  108. package/docs/agent-configuration.md +100 -0
  109. package/docs/architecture.md +115 -0
  110. package/docs/claude-code-setup.md +116 -0
  111. package/docs/configuration.md +184 -0
  112. package/docs/contributing.md +71 -0
  113. package/docs/deepseek-setup.md +84 -0
  114. package/docs/development.md +146 -0
  115. package/docs/installation.md +88 -0
  116. package/docs/opencode-setup.md +97 -0
  117. package/docs/security-audit.md +80 -0
  118. package/docs/security.md +128 -0
  119. package/docs/troubleshooting.md +126 -0
  120. package/docs/workspace-model.md +126 -0
  121. 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":"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"}