ework-web 0.1.3 → 0.1.4
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/package.json +1 -1
- package/src/opencode.ts +38 -3
package/package.json
CHANGED
package/src/opencode.ts
CHANGED
|
@@ -170,11 +170,16 @@ export class OpencodeClient {
|
|
|
170
170
|
}
|
|
171
171
|
const text = stdout.trim();
|
|
172
172
|
if (!text) return null;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
} catch {
|
|
173
|
+
const jsonText = stripNonJsonPreamble(text);
|
|
174
|
+
if (jsonText === null) {
|
|
176
175
|
throw new OpencodeError(`opencode ${args.join(" ")}: non-JSON output`, 502);
|
|
177
176
|
}
|
|
177
|
+
try {
|
|
178
|
+
return JSON.parse(jsonText);
|
|
179
|
+
} catch (e) {
|
|
180
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
181
|
+
throw new OpencodeError(`opencode ${args.join(" ")}: malformed JSON (${msg})`, 502);
|
|
182
|
+
}
|
|
178
183
|
}
|
|
179
184
|
|
|
180
185
|
private async run(args: string[]): Promise<{ stdout: string; stderr: string; code: number | null }> {
|
|
@@ -239,6 +244,36 @@ function asString(v: unknown): string {
|
|
|
239
244
|
return typeof v === "string" ? v : "";
|
|
240
245
|
}
|
|
241
246
|
|
|
247
|
+
// `opencode export` (and other opencode subcommands that emit JSON) write
|
|
248
|
+
// status lines to stdout BEFORE the JSON payload:
|
|
249
|
+
// • plugin banners via console.log: "[omo-stable] Downloading comment-checker binary..."
|
|
250
|
+
// • plugin registration via console.log: "[omo-stable] ast-grep binary ready."
|
|
251
|
+
// • CLI status: "Exporting session: ses_..."
|
|
252
|
+
// • any other stdout-side logging from plugins
|
|
253
|
+
// These break JSON.parse(). Find the first line that starts a JSON object
|
|
254
|
+
// or array and slice from there. Returns null if no JSON-looking content.
|
|
255
|
+
//
|
|
256
|
+
// We try JSON.parse at each candidate (line starting with '{' or '[') and
|
|
257
|
+
// return the first one that parses — necessary because plugin banners like
|
|
258
|
+
// "[omo-stable] ..." also start with '[' but aren't JSON.
|
|
259
|
+
export function stripNonJsonPreamble(s: string): string | null {
|
|
260
|
+
const lines = s.split(/\r?\n/);
|
|
261
|
+
for (let i = 0; i < lines.length; i++) {
|
|
262
|
+
const line = lines[i];
|
|
263
|
+
if (!line) continue;
|
|
264
|
+
const trimmed = line.trimStart();
|
|
265
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) continue;
|
|
266
|
+
const candidate = lines.slice(i).join("\n");
|
|
267
|
+
try {
|
|
268
|
+
JSON.parse(candidate);
|
|
269
|
+
return candidate;
|
|
270
|
+
} catch {
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
|
|
242
277
|
function parseSessionExport(v: unknown): SessionExport | null {
|
|
243
278
|
if (!v || typeof v !== "object") return null;
|
|
244
279
|
const o = v as Record<string, unknown>;
|