@flue/cli 0.0.9 → 0.0.11
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/dist/dist-C2CPKdvn.mjs +2406 -0
- package/dist/flue.js +8 -4
- package/package.json +2 -4
|
@@ -0,0 +1,2406 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/core/serverSentEvents.gen.js
|
|
4
|
+
const createSseClient = ({ onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url, ...options }) => {
|
|
5
|
+
let lastEventId;
|
|
6
|
+
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
7
|
+
const createStream = async function* () {
|
|
8
|
+
let retryDelay = sseDefaultRetryDelay ?? 3e3;
|
|
9
|
+
let attempt = 0;
|
|
10
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
11
|
+
while (true) {
|
|
12
|
+
if (signal.aborted) break;
|
|
13
|
+
attempt++;
|
|
14
|
+
const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
|
|
15
|
+
if (lastEventId !== void 0) headers.set("Last-Event-ID", lastEventId);
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetch(url, {
|
|
18
|
+
...options,
|
|
19
|
+
headers,
|
|
20
|
+
signal
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
|
|
23
|
+
if (!response.body) throw new Error("No body in SSE response");
|
|
24
|
+
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
25
|
+
let buffer = "";
|
|
26
|
+
const abortHandler = () => {
|
|
27
|
+
try {
|
|
28
|
+
reader.cancel();
|
|
29
|
+
} catch {}
|
|
30
|
+
};
|
|
31
|
+
signal.addEventListener("abort", abortHandler);
|
|
32
|
+
try {
|
|
33
|
+
while (true) {
|
|
34
|
+
const { done, value } = await reader.read();
|
|
35
|
+
if (done) break;
|
|
36
|
+
buffer += value;
|
|
37
|
+
const chunks = buffer.split("\n\n");
|
|
38
|
+
buffer = chunks.pop() ?? "";
|
|
39
|
+
for (const chunk of chunks) {
|
|
40
|
+
const lines = chunk.split("\n");
|
|
41
|
+
const dataLines = [];
|
|
42
|
+
let eventName;
|
|
43
|
+
for (const line of lines) if (line.startsWith("data:")) dataLines.push(line.replace(/^data:\s*/, ""));
|
|
44
|
+
else if (line.startsWith("event:")) eventName = line.replace(/^event:\s*/, "");
|
|
45
|
+
else if (line.startsWith("id:")) lastEventId = line.replace(/^id:\s*/, "");
|
|
46
|
+
else if (line.startsWith("retry:")) {
|
|
47
|
+
const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
|
|
48
|
+
if (!Number.isNaN(parsed)) retryDelay = parsed;
|
|
49
|
+
}
|
|
50
|
+
let data;
|
|
51
|
+
let parsedJson = false;
|
|
52
|
+
if (dataLines.length) {
|
|
53
|
+
const rawData = dataLines.join("\n");
|
|
54
|
+
try {
|
|
55
|
+
data = JSON.parse(rawData);
|
|
56
|
+
parsedJson = true;
|
|
57
|
+
} catch {
|
|
58
|
+
data = rawData;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (parsedJson) {
|
|
62
|
+
if (responseValidator) await responseValidator(data);
|
|
63
|
+
if (responseTransformer) data = await responseTransformer(data);
|
|
64
|
+
}
|
|
65
|
+
onSseEvent?.({
|
|
66
|
+
data,
|
|
67
|
+
event: eventName,
|
|
68
|
+
id: lastEventId,
|
|
69
|
+
retry: retryDelay
|
|
70
|
+
});
|
|
71
|
+
if (dataLines.length) yield data;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} finally {
|
|
75
|
+
signal.removeEventListener("abort", abortHandler);
|
|
76
|
+
reader.releaseLock();
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
onSseError?.(error);
|
|
81
|
+
if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) break;
|
|
82
|
+
await sleep(Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
return { stream: createStream() };
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/core/auth.gen.js
|
|
91
|
+
const getAuthToken = async (auth, callback) => {
|
|
92
|
+
const token = typeof callback === "function" ? await callback(auth) : callback;
|
|
93
|
+
if (!token) return;
|
|
94
|
+
if (auth.scheme === "bearer") return `Bearer ${token}`;
|
|
95
|
+
if (auth.scheme === "basic") return `Basic ${btoa(token)}`;
|
|
96
|
+
return token;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/core/bodySerializer.gen.js
|
|
101
|
+
const jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
|
|
102
|
+
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/core/pathSerializer.gen.js
|
|
105
|
+
const separatorArrayExplode = (style) => {
|
|
106
|
+
switch (style) {
|
|
107
|
+
case "label": return ".";
|
|
108
|
+
case "matrix": return ";";
|
|
109
|
+
case "simple": return ",";
|
|
110
|
+
default: return "&";
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
const separatorArrayNoExplode = (style) => {
|
|
114
|
+
switch (style) {
|
|
115
|
+
case "form": return ",";
|
|
116
|
+
case "pipeDelimited": return "|";
|
|
117
|
+
case "spaceDelimited": return "%20";
|
|
118
|
+
default: return ",";
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const separatorObjectExplode = (style) => {
|
|
122
|
+
switch (style) {
|
|
123
|
+
case "label": return ".";
|
|
124
|
+
case "matrix": return ";";
|
|
125
|
+
case "simple": return ",";
|
|
126
|
+
default: return "&";
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const serializeArrayParam = ({ allowReserved, explode, name, style, value }) => {
|
|
130
|
+
if (!explode) {
|
|
131
|
+
const joinedValues = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
|
|
132
|
+
switch (style) {
|
|
133
|
+
case "label": return `.${joinedValues}`;
|
|
134
|
+
case "matrix": return `;${name}=${joinedValues}`;
|
|
135
|
+
case "simple": return joinedValues;
|
|
136
|
+
default: return `${name}=${joinedValues}`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const separator = separatorArrayExplode(style);
|
|
140
|
+
const joinedValues = value.map((v) => {
|
|
141
|
+
if (style === "label" || style === "simple") return allowReserved ? v : encodeURIComponent(v);
|
|
142
|
+
return serializePrimitiveParam({
|
|
143
|
+
allowReserved,
|
|
144
|
+
name,
|
|
145
|
+
value: v
|
|
146
|
+
});
|
|
147
|
+
}).join(separator);
|
|
148
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
149
|
+
};
|
|
150
|
+
const serializePrimitiveParam = ({ allowReserved, name, value }) => {
|
|
151
|
+
if (value === void 0 || value === null) return "";
|
|
152
|
+
if (typeof value === "object") throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
|
|
153
|
+
return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
|
|
154
|
+
};
|
|
155
|
+
const serializeObjectParam = ({ allowReserved, explode, name, style, value, valueOnly }) => {
|
|
156
|
+
if (value instanceof Date) return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
|
157
|
+
if (style !== "deepObject" && !explode) {
|
|
158
|
+
let values = [];
|
|
159
|
+
Object.entries(value).forEach(([key, v]) => {
|
|
160
|
+
values = [
|
|
161
|
+
...values,
|
|
162
|
+
key,
|
|
163
|
+
allowReserved ? v : encodeURIComponent(v)
|
|
164
|
+
];
|
|
165
|
+
});
|
|
166
|
+
const joinedValues = values.join(",");
|
|
167
|
+
switch (style) {
|
|
168
|
+
case "form": return `${name}=${joinedValues}`;
|
|
169
|
+
case "label": return `.${joinedValues}`;
|
|
170
|
+
case "matrix": return `;${name}=${joinedValues}`;
|
|
171
|
+
default: return joinedValues;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const separator = separatorObjectExplode(style);
|
|
175
|
+
const joinedValues = Object.entries(value).map(([key, v]) => serializePrimitiveParam({
|
|
176
|
+
allowReserved,
|
|
177
|
+
name: style === "deepObject" ? `${name}[${key}]` : key,
|
|
178
|
+
value: v
|
|
179
|
+
})).join(separator);
|
|
180
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/core/utils.gen.js
|
|
185
|
+
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
186
|
+
const defaultPathSerializer = ({ path, url: _url }) => {
|
|
187
|
+
let url = _url;
|
|
188
|
+
const matches = _url.match(PATH_PARAM_RE);
|
|
189
|
+
if (matches) for (const match of matches) {
|
|
190
|
+
let explode = false;
|
|
191
|
+
let name = match.substring(1, match.length - 1);
|
|
192
|
+
let style = "simple";
|
|
193
|
+
if (name.endsWith("*")) {
|
|
194
|
+
explode = true;
|
|
195
|
+
name = name.substring(0, name.length - 1);
|
|
196
|
+
}
|
|
197
|
+
if (name.startsWith(".")) {
|
|
198
|
+
name = name.substring(1);
|
|
199
|
+
style = "label";
|
|
200
|
+
} else if (name.startsWith(";")) {
|
|
201
|
+
name = name.substring(1);
|
|
202
|
+
style = "matrix";
|
|
203
|
+
}
|
|
204
|
+
const value = path[name];
|
|
205
|
+
if (value === void 0 || value === null) continue;
|
|
206
|
+
if (Array.isArray(value)) {
|
|
207
|
+
url = url.replace(match, serializeArrayParam({
|
|
208
|
+
explode,
|
|
209
|
+
name,
|
|
210
|
+
style,
|
|
211
|
+
value
|
|
212
|
+
}));
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (typeof value === "object") {
|
|
216
|
+
url = url.replace(match, serializeObjectParam({
|
|
217
|
+
explode,
|
|
218
|
+
name,
|
|
219
|
+
style,
|
|
220
|
+
value,
|
|
221
|
+
valueOnly: true
|
|
222
|
+
}));
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (style === "matrix") {
|
|
226
|
+
url = url.replace(match, `;${serializePrimitiveParam({
|
|
227
|
+
name,
|
|
228
|
+
value
|
|
229
|
+
})}`);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
|
|
233
|
+
url = url.replace(match, replaceValue);
|
|
234
|
+
}
|
|
235
|
+
return url;
|
|
236
|
+
};
|
|
237
|
+
const getUrl = ({ baseUrl, path, query, querySerializer, url: _url }) => {
|
|
238
|
+
const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
|
|
239
|
+
let url = (baseUrl ?? "") + pathUrl;
|
|
240
|
+
if (path) url = defaultPathSerializer({
|
|
241
|
+
path,
|
|
242
|
+
url
|
|
243
|
+
});
|
|
244
|
+
let search = query ? querySerializer(query) : "";
|
|
245
|
+
if (search.startsWith("?")) search = search.substring(1);
|
|
246
|
+
if (search) url += `?${search}`;
|
|
247
|
+
return url;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/client/utils.gen.js
|
|
252
|
+
const createQuerySerializer = ({ allowReserved, array, object } = {}) => {
|
|
253
|
+
const querySerializer = (queryParams) => {
|
|
254
|
+
const search = [];
|
|
255
|
+
if (queryParams && typeof queryParams === "object") for (const name in queryParams) {
|
|
256
|
+
const value = queryParams[name];
|
|
257
|
+
if (value === void 0 || value === null) continue;
|
|
258
|
+
if (Array.isArray(value)) {
|
|
259
|
+
const serializedArray = serializeArrayParam({
|
|
260
|
+
allowReserved,
|
|
261
|
+
explode: true,
|
|
262
|
+
name,
|
|
263
|
+
style: "form",
|
|
264
|
+
value,
|
|
265
|
+
...array
|
|
266
|
+
});
|
|
267
|
+
if (serializedArray) search.push(serializedArray);
|
|
268
|
+
} else if (typeof value === "object") {
|
|
269
|
+
const serializedObject = serializeObjectParam({
|
|
270
|
+
allowReserved,
|
|
271
|
+
explode: true,
|
|
272
|
+
name,
|
|
273
|
+
style: "deepObject",
|
|
274
|
+
value,
|
|
275
|
+
...object
|
|
276
|
+
});
|
|
277
|
+
if (serializedObject) search.push(serializedObject);
|
|
278
|
+
} else {
|
|
279
|
+
const serializedPrimitive = serializePrimitiveParam({
|
|
280
|
+
allowReserved,
|
|
281
|
+
name,
|
|
282
|
+
value
|
|
283
|
+
});
|
|
284
|
+
if (serializedPrimitive) search.push(serializedPrimitive);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return search.join("&");
|
|
288
|
+
};
|
|
289
|
+
return querySerializer;
|
|
290
|
+
};
|
|
291
|
+
/**
|
|
292
|
+
* Infers parseAs value from provided Content-Type header.
|
|
293
|
+
*/
|
|
294
|
+
const getParseAs = (contentType) => {
|
|
295
|
+
if (!contentType) return "stream";
|
|
296
|
+
const cleanContent = contentType.split(";")[0]?.trim();
|
|
297
|
+
if (!cleanContent) return;
|
|
298
|
+
if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) return "json";
|
|
299
|
+
if (cleanContent === "multipart/form-data") return "formData";
|
|
300
|
+
if ([
|
|
301
|
+
"application/",
|
|
302
|
+
"audio/",
|
|
303
|
+
"image/",
|
|
304
|
+
"video/"
|
|
305
|
+
].some((type) => cleanContent.startsWith(type))) return "blob";
|
|
306
|
+
if (cleanContent.startsWith("text/")) return "text";
|
|
307
|
+
};
|
|
308
|
+
const checkForExistence = (options, name) => {
|
|
309
|
+
if (!name) return false;
|
|
310
|
+
if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) return true;
|
|
311
|
+
return false;
|
|
312
|
+
};
|
|
313
|
+
const setAuthParams = async ({ security, ...options }) => {
|
|
314
|
+
for (const auth of security) {
|
|
315
|
+
if (checkForExistence(options, auth.name)) continue;
|
|
316
|
+
const token = await getAuthToken(auth, options.auth);
|
|
317
|
+
if (!token) continue;
|
|
318
|
+
const name = auth.name ?? "Authorization";
|
|
319
|
+
switch (auth.in) {
|
|
320
|
+
case "query":
|
|
321
|
+
if (!options.query) options.query = {};
|
|
322
|
+
options.query[name] = token;
|
|
323
|
+
break;
|
|
324
|
+
case "cookie":
|
|
325
|
+
options.headers.append("Cookie", `${name}=${token}`);
|
|
326
|
+
break;
|
|
327
|
+
default:
|
|
328
|
+
options.headers.set(name, token);
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
const buildUrl = (options) => getUrl({
|
|
334
|
+
baseUrl: options.baseUrl,
|
|
335
|
+
path: options.path,
|
|
336
|
+
query: options.query,
|
|
337
|
+
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
|
|
338
|
+
url: options.url
|
|
339
|
+
});
|
|
340
|
+
const mergeConfigs = (a, b) => {
|
|
341
|
+
const config = {
|
|
342
|
+
...a,
|
|
343
|
+
...b
|
|
344
|
+
};
|
|
345
|
+
if (config.baseUrl?.endsWith("/")) config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
|
346
|
+
config.headers = mergeHeaders(a.headers, b.headers);
|
|
347
|
+
return config;
|
|
348
|
+
};
|
|
349
|
+
const mergeHeaders = (...headers) => {
|
|
350
|
+
const mergedHeaders = new Headers();
|
|
351
|
+
for (const header of headers) {
|
|
352
|
+
if (!header || typeof header !== "object") continue;
|
|
353
|
+
const iterator = header instanceof Headers ? header.entries() : Object.entries(header);
|
|
354
|
+
for (const [key, value] of iterator) if (value === null) mergedHeaders.delete(key);
|
|
355
|
+
else if (Array.isArray(value)) for (const v of value) mergedHeaders.append(key, v);
|
|
356
|
+
else if (value !== void 0) mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
|
|
357
|
+
}
|
|
358
|
+
return mergedHeaders;
|
|
359
|
+
};
|
|
360
|
+
var Interceptors = class {
|
|
361
|
+
_fns;
|
|
362
|
+
constructor() {
|
|
363
|
+
this._fns = [];
|
|
364
|
+
}
|
|
365
|
+
clear() {
|
|
366
|
+
this._fns = [];
|
|
367
|
+
}
|
|
368
|
+
getInterceptorIndex(id) {
|
|
369
|
+
if (typeof id === "number") return this._fns[id] ? id : -1;
|
|
370
|
+
else return this._fns.indexOf(id);
|
|
371
|
+
}
|
|
372
|
+
exists(id) {
|
|
373
|
+
const index = this.getInterceptorIndex(id);
|
|
374
|
+
return !!this._fns[index];
|
|
375
|
+
}
|
|
376
|
+
eject(id) {
|
|
377
|
+
const index = this.getInterceptorIndex(id);
|
|
378
|
+
if (this._fns[index]) this._fns[index] = null;
|
|
379
|
+
}
|
|
380
|
+
update(id, fn) {
|
|
381
|
+
const index = this.getInterceptorIndex(id);
|
|
382
|
+
if (this._fns[index]) {
|
|
383
|
+
this._fns[index] = fn;
|
|
384
|
+
return id;
|
|
385
|
+
} else return false;
|
|
386
|
+
}
|
|
387
|
+
use(fn) {
|
|
388
|
+
this._fns = [...this._fns, fn];
|
|
389
|
+
return this._fns.length - 1;
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
const createInterceptors = () => ({
|
|
393
|
+
error: new Interceptors(),
|
|
394
|
+
request: new Interceptors(),
|
|
395
|
+
response: new Interceptors()
|
|
396
|
+
});
|
|
397
|
+
const defaultQuerySerializer = createQuerySerializer({
|
|
398
|
+
allowReserved: false,
|
|
399
|
+
array: {
|
|
400
|
+
explode: true,
|
|
401
|
+
style: "form"
|
|
402
|
+
},
|
|
403
|
+
object: {
|
|
404
|
+
explode: true,
|
|
405
|
+
style: "deepObject"
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
const defaultHeaders = { "Content-Type": "application/json" };
|
|
409
|
+
const createConfig = (override = {}) => ({
|
|
410
|
+
...jsonBodySerializer,
|
|
411
|
+
headers: defaultHeaders,
|
|
412
|
+
parseAs: "auto",
|
|
413
|
+
querySerializer: defaultQuerySerializer,
|
|
414
|
+
...override
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
//#endregion
|
|
418
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/client/client.gen.js
|
|
419
|
+
const createClient = (config = {}) => {
|
|
420
|
+
let _config = mergeConfigs(createConfig(), config);
|
|
421
|
+
const getConfig = () => ({ ..._config });
|
|
422
|
+
const setConfig = (config) => {
|
|
423
|
+
_config = mergeConfigs(_config, config);
|
|
424
|
+
return getConfig();
|
|
425
|
+
};
|
|
426
|
+
const interceptors = createInterceptors();
|
|
427
|
+
const beforeRequest = async (options) => {
|
|
428
|
+
const opts = {
|
|
429
|
+
..._config,
|
|
430
|
+
...options,
|
|
431
|
+
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
|
432
|
+
headers: mergeHeaders(_config.headers, options.headers),
|
|
433
|
+
serializedBody: void 0
|
|
434
|
+
};
|
|
435
|
+
if (opts.security) await setAuthParams({
|
|
436
|
+
...opts,
|
|
437
|
+
security: opts.security
|
|
438
|
+
});
|
|
439
|
+
if (opts.requestValidator) await opts.requestValidator(opts);
|
|
440
|
+
if (opts.body && opts.bodySerializer) opts.serializedBody = opts.bodySerializer(opts.body);
|
|
441
|
+
if (opts.serializedBody === void 0 || opts.serializedBody === "") opts.headers.delete("Content-Type");
|
|
442
|
+
return {
|
|
443
|
+
opts,
|
|
444
|
+
url: buildUrl(opts)
|
|
445
|
+
};
|
|
446
|
+
};
|
|
447
|
+
const request = async (options) => {
|
|
448
|
+
const { opts, url } = await beforeRequest(options);
|
|
449
|
+
const requestInit = {
|
|
450
|
+
redirect: "follow",
|
|
451
|
+
...opts,
|
|
452
|
+
body: opts.serializedBody
|
|
453
|
+
};
|
|
454
|
+
let request = new Request(url, requestInit);
|
|
455
|
+
for (const fn of interceptors.request._fns) if (fn) request = await fn(request, opts);
|
|
456
|
+
const _fetch = opts.fetch;
|
|
457
|
+
let response = await _fetch(request);
|
|
458
|
+
for (const fn of interceptors.response._fns) if (fn) response = await fn(response, request, opts);
|
|
459
|
+
const result = {
|
|
460
|
+
request,
|
|
461
|
+
response
|
|
462
|
+
};
|
|
463
|
+
if (response.ok) {
|
|
464
|
+
if (response.status === 204 || response.headers.get("Content-Length") === "0") return opts.responseStyle === "data" ? {} : {
|
|
465
|
+
data: {},
|
|
466
|
+
...result
|
|
467
|
+
};
|
|
468
|
+
const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
469
|
+
let data;
|
|
470
|
+
switch (parseAs) {
|
|
471
|
+
case "arrayBuffer":
|
|
472
|
+
case "blob":
|
|
473
|
+
case "formData":
|
|
474
|
+
case "json":
|
|
475
|
+
case "text":
|
|
476
|
+
data = await response[parseAs]();
|
|
477
|
+
break;
|
|
478
|
+
case "stream": return opts.responseStyle === "data" ? response.body : {
|
|
479
|
+
data: response.body,
|
|
480
|
+
...result
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
if (parseAs === "json") {
|
|
484
|
+
if (opts.responseValidator) await opts.responseValidator(data);
|
|
485
|
+
if (opts.responseTransformer) data = await opts.responseTransformer(data);
|
|
486
|
+
}
|
|
487
|
+
return opts.responseStyle === "data" ? data : {
|
|
488
|
+
data,
|
|
489
|
+
...result
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
const textError = await response.text();
|
|
493
|
+
let jsonError;
|
|
494
|
+
try {
|
|
495
|
+
jsonError = JSON.parse(textError);
|
|
496
|
+
} catch {}
|
|
497
|
+
const error = jsonError ?? textError;
|
|
498
|
+
let finalError = error;
|
|
499
|
+
for (const fn of interceptors.error._fns) if (fn) finalError = await fn(error, response, request, opts);
|
|
500
|
+
finalError = finalError || {};
|
|
501
|
+
if (opts.throwOnError) throw finalError;
|
|
502
|
+
return opts.responseStyle === "data" ? void 0 : {
|
|
503
|
+
error: finalError,
|
|
504
|
+
...result
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
const makeMethod = (method) => {
|
|
508
|
+
const fn = (options) => request({
|
|
509
|
+
...options,
|
|
510
|
+
method
|
|
511
|
+
});
|
|
512
|
+
fn.sse = async (options) => {
|
|
513
|
+
const { opts, url } = await beforeRequest(options);
|
|
514
|
+
return createSseClient({
|
|
515
|
+
...opts,
|
|
516
|
+
body: opts.body,
|
|
517
|
+
headers: opts.headers,
|
|
518
|
+
method,
|
|
519
|
+
url
|
|
520
|
+
});
|
|
521
|
+
};
|
|
522
|
+
return fn;
|
|
523
|
+
};
|
|
524
|
+
return {
|
|
525
|
+
buildUrl,
|
|
526
|
+
connect: makeMethod("CONNECT"),
|
|
527
|
+
delete: makeMethod("DELETE"),
|
|
528
|
+
get: makeMethod("GET"),
|
|
529
|
+
getConfig,
|
|
530
|
+
head: makeMethod("HEAD"),
|
|
531
|
+
interceptors,
|
|
532
|
+
options: makeMethod("OPTIONS"),
|
|
533
|
+
patch: makeMethod("PATCH"),
|
|
534
|
+
post: makeMethod("POST"),
|
|
535
|
+
put: makeMethod("PUT"),
|
|
536
|
+
request,
|
|
537
|
+
setConfig,
|
|
538
|
+
trace: makeMethod("TRACE")
|
|
539
|
+
};
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
//#endregion
|
|
543
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/core/params.gen.js
|
|
544
|
+
const extraPrefixes = Object.entries({
|
|
545
|
+
$body_: "body",
|
|
546
|
+
$headers_: "headers",
|
|
547
|
+
$path_: "path",
|
|
548
|
+
$query_: "query"
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
//#endregion
|
|
552
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/client.gen.js
|
|
553
|
+
const client = createClient(createConfig({ baseUrl: "http://localhost:4096" }));
|
|
554
|
+
|
|
555
|
+
//#endregion
|
|
556
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/gen/sdk.gen.js
|
|
557
|
+
var _HeyApiClient = class {
|
|
558
|
+
_client = client;
|
|
559
|
+
constructor(args) {
|
|
560
|
+
if (args?.client) this._client = args.client;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
var Global = class extends _HeyApiClient {
|
|
564
|
+
/**
|
|
565
|
+
* Get events
|
|
566
|
+
*/
|
|
567
|
+
event(options) {
|
|
568
|
+
return (options?.client ?? this._client).get.sse({
|
|
569
|
+
url: "/global/event",
|
|
570
|
+
...options
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
var Project = class extends _HeyApiClient {
|
|
575
|
+
/**
|
|
576
|
+
* List all projects
|
|
577
|
+
*/
|
|
578
|
+
list(options) {
|
|
579
|
+
return (options?.client ?? this._client).get({
|
|
580
|
+
url: "/project",
|
|
581
|
+
...options
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Get the current project
|
|
586
|
+
*/
|
|
587
|
+
current(options) {
|
|
588
|
+
return (options?.client ?? this._client).get({
|
|
589
|
+
url: "/project/current",
|
|
590
|
+
...options
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
var Pty = class extends _HeyApiClient {
|
|
595
|
+
/**
|
|
596
|
+
* List all PTY sessions
|
|
597
|
+
*/
|
|
598
|
+
list(options) {
|
|
599
|
+
return (options?.client ?? this._client).get({
|
|
600
|
+
url: "/pty",
|
|
601
|
+
...options
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Create a new PTY session
|
|
606
|
+
*/
|
|
607
|
+
create(options) {
|
|
608
|
+
return (options?.client ?? this._client).post({
|
|
609
|
+
url: "/pty",
|
|
610
|
+
...options,
|
|
611
|
+
headers: {
|
|
612
|
+
"Content-Type": "application/json",
|
|
613
|
+
...options?.headers
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Remove a PTY session
|
|
619
|
+
*/
|
|
620
|
+
remove(options) {
|
|
621
|
+
return (options.client ?? this._client).delete({
|
|
622
|
+
url: "/pty/{id}",
|
|
623
|
+
...options
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Get PTY session info
|
|
628
|
+
*/
|
|
629
|
+
get(options) {
|
|
630
|
+
return (options.client ?? this._client).get({
|
|
631
|
+
url: "/pty/{id}",
|
|
632
|
+
...options
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Update PTY session
|
|
637
|
+
*/
|
|
638
|
+
update(options) {
|
|
639
|
+
return (options.client ?? this._client).put({
|
|
640
|
+
url: "/pty/{id}",
|
|
641
|
+
...options,
|
|
642
|
+
headers: {
|
|
643
|
+
"Content-Type": "application/json",
|
|
644
|
+
...options.headers
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Connect to a PTY session
|
|
650
|
+
*/
|
|
651
|
+
connect(options) {
|
|
652
|
+
return (options.client ?? this._client).get({
|
|
653
|
+
url: "/pty/{id}/connect",
|
|
654
|
+
...options
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
var Config = class extends _HeyApiClient {
|
|
659
|
+
/**
|
|
660
|
+
* Get config info
|
|
661
|
+
*/
|
|
662
|
+
get(options) {
|
|
663
|
+
return (options?.client ?? this._client).get({
|
|
664
|
+
url: "/config",
|
|
665
|
+
...options
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Update config
|
|
670
|
+
*/
|
|
671
|
+
update(options) {
|
|
672
|
+
return (options?.client ?? this._client).patch({
|
|
673
|
+
url: "/config",
|
|
674
|
+
...options,
|
|
675
|
+
headers: {
|
|
676
|
+
"Content-Type": "application/json",
|
|
677
|
+
...options?.headers
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* List all providers
|
|
683
|
+
*/
|
|
684
|
+
providers(options) {
|
|
685
|
+
return (options?.client ?? this._client).get({
|
|
686
|
+
url: "/config/providers",
|
|
687
|
+
...options
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
var Tool = class extends _HeyApiClient {
|
|
692
|
+
/**
|
|
693
|
+
* List all tool IDs (including built-in and dynamically registered)
|
|
694
|
+
*/
|
|
695
|
+
ids(options) {
|
|
696
|
+
return (options?.client ?? this._client).get({
|
|
697
|
+
url: "/experimental/tool/ids",
|
|
698
|
+
...options
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* List tools with JSON schema parameters for a provider/model
|
|
703
|
+
*/
|
|
704
|
+
list(options) {
|
|
705
|
+
return (options.client ?? this._client).get({
|
|
706
|
+
url: "/experimental/tool",
|
|
707
|
+
...options
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
var Instance = class extends _HeyApiClient {
|
|
712
|
+
/**
|
|
713
|
+
* Dispose the current instance
|
|
714
|
+
*/
|
|
715
|
+
dispose(options) {
|
|
716
|
+
return (options?.client ?? this._client).post({
|
|
717
|
+
url: "/instance/dispose",
|
|
718
|
+
...options
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
var Path = class extends _HeyApiClient {
|
|
723
|
+
/**
|
|
724
|
+
* Get the current path
|
|
725
|
+
*/
|
|
726
|
+
get(options) {
|
|
727
|
+
return (options?.client ?? this._client).get({
|
|
728
|
+
url: "/path",
|
|
729
|
+
...options
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
var Vcs = class extends _HeyApiClient {
|
|
734
|
+
/**
|
|
735
|
+
* Get VCS info for the current instance
|
|
736
|
+
*/
|
|
737
|
+
get(options) {
|
|
738
|
+
return (options?.client ?? this._client).get({
|
|
739
|
+
url: "/vcs",
|
|
740
|
+
...options
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
var Session = class extends _HeyApiClient {
|
|
745
|
+
/**
|
|
746
|
+
* List all sessions
|
|
747
|
+
*/
|
|
748
|
+
list(options) {
|
|
749
|
+
return (options?.client ?? this._client).get({
|
|
750
|
+
url: "/session",
|
|
751
|
+
...options
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Create a new session
|
|
756
|
+
*/
|
|
757
|
+
create(options) {
|
|
758
|
+
return (options?.client ?? this._client).post({
|
|
759
|
+
url: "/session",
|
|
760
|
+
...options,
|
|
761
|
+
headers: {
|
|
762
|
+
"Content-Type": "application/json",
|
|
763
|
+
...options?.headers
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Get session status
|
|
769
|
+
*/
|
|
770
|
+
status(options) {
|
|
771
|
+
return (options?.client ?? this._client).get({
|
|
772
|
+
url: "/session/status",
|
|
773
|
+
...options
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Delete a session and all its data
|
|
778
|
+
*/
|
|
779
|
+
delete(options) {
|
|
780
|
+
return (options.client ?? this._client).delete({
|
|
781
|
+
url: "/session/{id}",
|
|
782
|
+
...options
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Get session
|
|
787
|
+
*/
|
|
788
|
+
get(options) {
|
|
789
|
+
return (options.client ?? this._client).get({
|
|
790
|
+
url: "/session/{id}",
|
|
791
|
+
...options
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Update session properties
|
|
796
|
+
*/
|
|
797
|
+
update(options) {
|
|
798
|
+
return (options.client ?? this._client).patch({
|
|
799
|
+
url: "/session/{id}",
|
|
800
|
+
...options,
|
|
801
|
+
headers: {
|
|
802
|
+
"Content-Type": "application/json",
|
|
803
|
+
...options.headers
|
|
804
|
+
}
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Get a session's children
|
|
809
|
+
*/
|
|
810
|
+
children(options) {
|
|
811
|
+
return (options.client ?? this._client).get({
|
|
812
|
+
url: "/session/{id}/children",
|
|
813
|
+
...options
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Get the todo list for a session
|
|
818
|
+
*/
|
|
819
|
+
todo(options) {
|
|
820
|
+
return (options.client ?? this._client).get({
|
|
821
|
+
url: "/session/{id}/todo",
|
|
822
|
+
...options
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Analyze the app and create an AGENTS.md file
|
|
827
|
+
*/
|
|
828
|
+
init(options) {
|
|
829
|
+
return (options.client ?? this._client).post({
|
|
830
|
+
url: "/session/{id}/init",
|
|
831
|
+
...options,
|
|
832
|
+
headers: {
|
|
833
|
+
"Content-Type": "application/json",
|
|
834
|
+
...options.headers
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Fork an existing session at a specific message
|
|
840
|
+
*/
|
|
841
|
+
fork(options) {
|
|
842
|
+
return (options.client ?? this._client).post({
|
|
843
|
+
url: "/session/{id}/fork",
|
|
844
|
+
...options,
|
|
845
|
+
headers: {
|
|
846
|
+
"Content-Type": "application/json",
|
|
847
|
+
...options.headers
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Abort a session
|
|
853
|
+
*/
|
|
854
|
+
abort(options) {
|
|
855
|
+
return (options.client ?? this._client).post({
|
|
856
|
+
url: "/session/{id}/abort",
|
|
857
|
+
...options
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Unshare the session
|
|
862
|
+
*/
|
|
863
|
+
unshare(options) {
|
|
864
|
+
return (options.client ?? this._client).delete({
|
|
865
|
+
url: "/session/{id}/share",
|
|
866
|
+
...options
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Share a session
|
|
871
|
+
*/
|
|
872
|
+
share(options) {
|
|
873
|
+
return (options.client ?? this._client).post({
|
|
874
|
+
url: "/session/{id}/share",
|
|
875
|
+
...options
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Get the diff for this session
|
|
880
|
+
*/
|
|
881
|
+
diff(options) {
|
|
882
|
+
return (options.client ?? this._client).get({
|
|
883
|
+
url: "/session/{id}/diff",
|
|
884
|
+
...options
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Summarize the session
|
|
889
|
+
*/
|
|
890
|
+
summarize(options) {
|
|
891
|
+
return (options.client ?? this._client).post({
|
|
892
|
+
url: "/session/{id}/summarize",
|
|
893
|
+
...options,
|
|
894
|
+
headers: {
|
|
895
|
+
"Content-Type": "application/json",
|
|
896
|
+
...options.headers
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* List messages for a session
|
|
902
|
+
*/
|
|
903
|
+
messages(options) {
|
|
904
|
+
return (options.client ?? this._client).get({
|
|
905
|
+
url: "/session/{id}/message",
|
|
906
|
+
...options
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* Create and send a new message to a session
|
|
911
|
+
*/
|
|
912
|
+
prompt(options) {
|
|
913
|
+
return (options.client ?? this._client).post({
|
|
914
|
+
url: "/session/{id}/message",
|
|
915
|
+
...options,
|
|
916
|
+
headers: {
|
|
917
|
+
"Content-Type": "application/json",
|
|
918
|
+
...options.headers
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Get a message from a session
|
|
924
|
+
*/
|
|
925
|
+
message(options) {
|
|
926
|
+
return (options.client ?? this._client).get({
|
|
927
|
+
url: "/session/{id}/message/{messageID}",
|
|
928
|
+
...options
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Create and send a new message to a session, start if needed and return immediately
|
|
933
|
+
*/
|
|
934
|
+
promptAsync(options) {
|
|
935
|
+
return (options.client ?? this._client).post({
|
|
936
|
+
url: "/session/{id}/prompt_async",
|
|
937
|
+
...options,
|
|
938
|
+
headers: {
|
|
939
|
+
"Content-Type": "application/json",
|
|
940
|
+
...options.headers
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Send a new command to a session
|
|
946
|
+
*/
|
|
947
|
+
command(options) {
|
|
948
|
+
return (options.client ?? this._client).post({
|
|
949
|
+
url: "/session/{id}/command",
|
|
950
|
+
...options,
|
|
951
|
+
headers: {
|
|
952
|
+
"Content-Type": "application/json",
|
|
953
|
+
...options.headers
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Run a shell command
|
|
959
|
+
*/
|
|
960
|
+
shell(options) {
|
|
961
|
+
return (options.client ?? this._client).post({
|
|
962
|
+
url: "/session/{id}/shell",
|
|
963
|
+
...options,
|
|
964
|
+
headers: {
|
|
965
|
+
"Content-Type": "application/json",
|
|
966
|
+
...options.headers
|
|
967
|
+
}
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* Revert a message
|
|
972
|
+
*/
|
|
973
|
+
revert(options) {
|
|
974
|
+
return (options.client ?? this._client).post({
|
|
975
|
+
url: "/session/{id}/revert",
|
|
976
|
+
...options,
|
|
977
|
+
headers: {
|
|
978
|
+
"Content-Type": "application/json",
|
|
979
|
+
...options.headers
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Restore all reverted messages
|
|
985
|
+
*/
|
|
986
|
+
unrevert(options) {
|
|
987
|
+
return (options.client ?? this._client).post({
|
|
988
|
+
url: "/session/{id}/unrevert",
|
|
989
|
+
...options
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
var Command = class extends _HeyApiClient {
|
|
994
|
+
/**
|
|
995
|
+
* List all commands
|
|
996
|
+
*/
|
|
997
|
+
list(options) {
|
|
998
|
+
return (options?.client ?? this._client).get({
|
|
999
|
+
url: "/command",
|
|
1000
|
+
...options
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
var Oauth = class extends _HeyApiClient {
|
|
1005
|
+
/**
|
|
1006
|
+
* Authorize a provider using OAuth
|
|
1007
|
+
*/
|
|
1008
|
+
authorize(options) {
|
|
1009
|
+
return (options.client ?? this._client).post({
|
|
1010
|
+
url: "/provider/{id}/oauth/authorize",
|
|
1011
|
+
...options,
|
|
1012
|
+
headers: {
|
|
1013
|
+
"Content-Type": "application/json",
|
|
1014
|
+
...options.headers
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Handle OAuth callback for a provider
|
|
1020
|
+
*/
|
|
1021
|
+
callback(options) {
|
|
1022
|
+
return (options.client ?? this._client).post({
|
|
1023
|
+
url: "/provider/{id}/oauth/callback",
|
|
1024
|
+
...options,
|
|
1025
|
+
headers: {
|
|
1026
|
+
"Content-Type": "application/json",
|
|
1027
|
+
...options.headers
|
|
1028
|
+
}
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
var Provider = class extends _HeyApiClient {
|
|
1033
|
+
/**
|
|
1034
|
+
* List all providers
|
|
1035
|
+
*/
|
|
1036
|
+
list(options) {
|
|
1037
|
+
return (options?.client ?? this._client).get({
|
|
1038
|
+
url: "/provider",
|
|
1039
|
+
...options
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Get provider authentication methods
|
|
1044
|
+
*/
|
|
1045
|
+
auth(options) {
|
|
1046
|
+
return (options?.client ?? this._client).get({
|
|
1047
|
+
url: "/provider/auth",
|
|
1048
|
+
...options
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
oauth = new Oauth({ client: this._client });
|
|
1052
|
+
};
|
|
1053
|
+
var Find = class extends _HeyApiClient {
|
|
1054
|
+
/**
|
|
1055
|
+
* Find text in files
|
|
1056
|
+
*/
|
|
1057
|
+
text(options) {
|
|
1058
|
+
return (options.client ?? this._client).get({
|
|
1059
|
+
url: "/find",
|
|
1060
|
+
...options
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Find files
|
|
1065
|
+
*/
|
|
1066
|
+
files(options) {
|
|
1067
|
+
return (options.client ?? this._client).get({
|
|
1068
|
+
url: "/find/file",
|
|
1069
|
+
...options
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Find workspace symbols
|
|
1074
|
+
*/
|
|
1075
|
+
symbols(options) {
|
|
1076
|
+
return (options.client ?? this._client).get({
|
|
1077
|
+
url: "/find/symbol",
|
|
1078
|
+
...options
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
var File$1 = class extends _HeyApiClient {
|
|
1083
|
+
/**
|
|
1084
|
+
* List files and directories
|
|
1085
|
+
*/
|
|
1086
|
+
list(options) {
|
|
1087
|
+
return (options.client ?? this._client).get({
|
|
1088
|
+
url: "/file",
|
|
1089
|
+
...options
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Read a file
|
|
1094
|
+
*/
|
|
1095
|
+
read(options) {
|
|
1096
|
+
return (options.client ?? this._client).get({
|
|
1097
|
+
url: "/file/content",
|
|
1098
|
+
...options
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Get file status
|
|
1103
|
+
*/
|
|
1104
|
+
status(options) {
|
|
1105
|
+
return (options?.client ?? this._client).get({
|
|
1106
|
+
url: "/file/status",
|
|
1107
|
+
...options
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
};
|
|
1111
|
+
var App = class extends _HeyApiClient {
|
|
1112
|
+
/**
|
|
1113
|
+
* Write a log entry to the server logs
|
|
1114
|
+
*/
|
|
1115
|
+
log(options) {
|
|
1116
|
+
return (options?.client ?? this._client).post({
|
|
1117
|
+
url: "/log",
|
|
1118
|
+
...options,
|
|
1119
|
+
headers: {
|
|
1120
|
+
"Content-Type": "application/json",
|
|
1121
|
+
...options?.headers
|
|
1122
|
+
}
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* List all agents
|
|
1127
|
+
*/
|
|
1128
|
+
agents(options) {
|
|
1129
|
+
return (options?.client ?? this._client).get({
|
|
1130
|
+
url: "/agent",
|
|
1131
|
+
...options
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
var Auth = class extends _HeyApiClient {
|
|
1136
|
+
/**
|
|
1137
|
+
* Remove OAuth credentials for an MCP server
|
|
1138
|
+
*/
|
|
1139
|
+
remove(options) {
|
|
1140
|
+
return (options.client ?? this._client).delete({
|
|
1141
|
+
url: "/mcp/{name}/auth",
|
|
1142
|
+
...options
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Start OAuth authentication flow for an MCP server
|
|
1147
|
+
*/
|
|
1148
|
+
start(options) {
|
|
1149
|
+
return (options.client ?? this._client).post({
|
|
1150
|
+
url: "/mcp/{name}/auth",
|
|
1151
|
+
...options
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Complete OAuth authentication with authorization code
|
|
1156
|
+
*/
|
|
1157
|
+
callback(options) {
|
|
1158
|
+
return (options.client ?? this._client).post({
|
|
1159
|
+
url: "/mcp/{name}/auth/callback",
|
|
1160
|
+
...options,
|
|
1161
|
+
headers: {
|
|
1162
|
+
"Content-Type": "application/json",
|
|
1163
|
+
...options.headers
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Start OAuth flow and wait for callback (opens browser)
|
|
1169
|
+
*/
|
|
1170
|
+
authenticate(options) {
|
|
1171
|
+
return (options.client ?? this._client).post({
|
|
1172
|
+
url: "/mcp/{name}/auth/authenticate",
|
|
1173
|
+
...options
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
/**
|
|
1177
|
+
* Set authentication credentials
|
|
1178
|
+
*/
|
|
1179
|
+
set(options) {
|
|
1180
|
+
return (options.client ?? this._client).put({
|
|
1181
|
+
url: "/auth/{id}",
|
|
1182
|
+
...options,
|
|
1183
|
+
headers: {
|
|
1184
|
+
"Content-Type": "application/json",
|
|
1185
|
+
...options.headers
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
var Mcp = class extends _HeyApiClient {
|
|
1191
|
+
/**
|
|
1192
|
+
* Get MCP server status
|
|
1193
|
+
*/
|
|
1194
|
+
status(options) {
|
|
1195
|
+
return (options?.client ?? this._client).get({
|
|
1196
|
+
url: "/mcp",
|
|
1197
|
+
...options
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* Add MCP server dynamically
|
|
1202
|
+
*/
|
|
1203
|
+
add(options) {
|
|
1204
|
+
return (options?.client ?? this._client).post({
|
|
1205
|
+
url: "/mcp",
|
|
1206
|
+
...options,
|
|
1207
|
+
headers: {
|
|
1208
|
+
"Content-Type": "application/json",
|
|
1209
|
+
...options?.headers
|
|
1210
|
+
}
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Connect an MCP server
|
|
1215
|
+
*/
|
|
1216
|
+
connect(options) {
|
|
1217
|
+
return (options.client ?? this._client).post({
|
|
1218
|
+
url: "/mcp/{name}/connect",
|
|
1219
|
+
...options
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Disconnect an MCP server
|
|
1224
|
+
*/
|
|
1225
|
+
disconnect(options) {
|
|
1226
|
+
return (options.client ?? this._client).post({
|
|
1227
|
+
url: "/mcp/{name}/disconnect",
|
|
1228
|
+
...options
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
auth = new Auth({ client: this._client });
|
|
1232
|
+
};
|
|
1233
|
+
var Lsp = class extends _HeyApiClient {
|
|
1234
|
+
/**
|
|
1235
|
+
* Get LSP server status
|
|
1236
|
+
*/
|
|
1237
|
+
status(options) {
|
|
1238
|
+
return (options?.client ?? this._client).get({
|
|
1239
|
+
url: "/lsp",
|
|
1240
|
+
...options
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
var Formatter = class extends _HeyApiClient {
|
|
1245
|
+
/**
|
|
1246
|
+
* Get formatter status
|
|
1247
|
+
*/
|
|
1248
|
+
status(options) {
|
|
1249
|
+
return (options?.client ?? this._client).get({
|
|
1250
|
+
url: "/formatter",
|
|
1251
|
+
...options
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
};
|
|
1255
|
+
var Control = class extends _HeyApiClient {
|
|
1256
|
+
/**
|
|
1257
|
+
* Get the next TUI request from the queue
|
|
1258
|
+
*/
|
|
1259
|
+
next(options) {
|
|
1260
|
+
return (options?.client ?? this._client).get({
|
|
1261
|
+
url: "/tui/control/next",
|
|
1262
|
+
...options
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Submit a response to the TUI request queue
|
|
1267
|
+
*/
|
|
1268
|
+
response(options) {
|
|
1269
|
+
return (options?.client ?? this._client).post({
|
|
1270
|
+
url: "/tui/control/response",
|
|
1271
|
+
...options,
|
|
1272
|
+
headers: {
|
|
1273
|
+
"Content-Type": "application/json",
|
|
1274
|
+
...options?.headers
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
var Tui = class extends _HeyApiClient {
|
|
1280
|
+
/**
|
|
1281
|
+
* Append prompt to the TUI
|
|
1282
|
+
*/
|
|
1283
|
+
appendPrompt(options) {
|
|
1284
|
+
return (options?.client ?? this._client).post({
|
|
1285
|
+
url: "/tui/append-prompt",
|
|
1286
|
+
...options,
|
|
1287
|
+
headers: {
|
|
1288
|
+
"Content-Type": "application/json",
|
|
1289
|
+
...options?.headers
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Open the help dialog
|
|
1295
|
+
*/
|
|
1296
|
+
openHelp(options) {
|
|
1297
|
+
return (options?.client ?? this._client).post({
|
|
1298
|
+
url: "/tui/open-help",
|
|
1299
|
+
...options
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Open the session dialog
|
|
1304
|
+
*/
|
|
1305
|
+
openSessions(options) {
|
|
1306
|
+
return (options?.client ?? this._client).post({
|
|
1307
|
+
url: "/tui/open-sessions",
|
|
1308
|
+
...options
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Open the theme dialog
|
|
1313
|
+
*/
|
|
1314
|
+
openThemes(options) {
|
|
1315
|
+
return (options?.client ?? this._client).post({
|
|
1316
|
+
url: "/tui/open-themes",
|
|
1317
|
+
...options
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Open the model dialog
|
|
1322
|
+
*/
|
|
1323
|
+
openModels(options) {
|
|
1324
|
+
return (options?.client ?? this._client).post({
|
|
1325
|
+
url: "/tui/open-models",
|
|
1326
|
+
...options
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* Submit the prompt
|
|
1331
|
+
*/
|
|
1332
|
+
submitPrompt(options) {
|
|
1333
|
+
return (options?.client ?? this._client).post({
|
|
1334
|
+
url: "/tui/submit-prompt",
|
|
1335
|
+
...options
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Clear the prompt
|
|
1340
|
+
*/
|
|
1341
|
+
clearPrompt(options) {
|
|
1342
|
+
return (options?.client ?? this._client).post({
|
|
1343
|
+
url: "/tui/clear-prompt",
|
|
1344
|
+
...options
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
* Execute a TUI command (e.g. agent_cycle)
|
|
1349
|
+
*/
|
|
1350
|
+
executeCommand(options) {
|
|
1351
|
+
return (options?.client ?? this._client).post({
|
|
1352
|
+
url: "/tui/execute-command",
|
|
1353
|
+
...options,
|
|
1354
|
+
headers: {
|
|
1355
|
+
"Content-Type": "application/json",
|
|
1356
|
+
...options?.headers
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
/**
|
|
1361
|
+
* Show a toast notification in the TUI
|
|
1362
|
+
*/
|
|
1363
|
+
showToast(options) {
|
|
1364
|
+
return (options?.client ?? this._client).post({
|
|
1365
|
+
url: "/tui/show-toast",
|
|
1366
|
+
...options,
|
|
1367
|
+
headers: {
|
|
1368
|
+
"Content-Type": "application/json",
|
|
1369
|
+
...options?.headers
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Publish a TUI event
|
|
1375
|
+
*/
|
|
1376
|
+
publish(options) {
|
|
1377
|
+
return (options?.client ?? this._client).post({
|
|
1378
|
+
url: "/tui/publish",
|
|
1379
|
+
...options,
|
|
1380
|
+
headers: {
|
|
1381
|
+
"Content-Type": "application/json",
|
|
1382
|
+
...options?.headers
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
control = new Control({ client: this._client });
|
|
1387
|
+
};
|
|
1388
|
+
var Event = class extends _HeyApiClient {
|
|
1389
|
+
/**
|
|
1390
|
+
* Get events
|
|
1391
|
+
*/
|
|
1392
|
+
subscribe(options) {
|
|
1393
|
+
return (options?.client ?? this._client).get.sse({
|
|
1394
|
+
url: "/event",
|
|
1395
|
+
...options
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
};
|
|
1399
|
+
var OpencodeClient = class extends _HeyApiClient {
|
|
1400
|
+
/**
|
|
1401
|
+
* Respond to a permission request
|
|
1402
|
+
*/
|
|
1403
|
+
postSessionIdPermissionsPermissionId(options) {
|
|
1404
|
+
return (options.client ?? this._client).post({
|
|
1405
|
+
url: "/session/{id}/permissions/{permissionID}",
|
|
1406
|
+
...options,
|
|
1407
|
+
headers: {
|
|
1408
|
+
"Content-Type": "application/json",
|
|
1409
|
+
...options.headers
|
|
1410
|
+
}
|
|
1411
|
+
});
|
|
1412
|
+
}
|
|
1413
|
+
global = new Global({ client: this._client });
|
|
1414
|
+
project = new Project({ client: this._client });
|
|
1415
|
+
pty = new Pty({ client: this._client });
|
|
1416
|
+
config = new Config({ client: this._client });
|
|
1417
|
+
tool = new Tool({ client: this._client });
|
|
1418
|
+
instance = new Instance({ client: this._client });
|
|
1419
|
+
path = new Path({ client: this._client });
|
|
1420
|
+
vcs = new Vcs({ client: this._client });
|
|
1421
|
+
session = new Session({ client: this._client });
|
|
1422
|
+
command = new Command({ client: this._client });
|
|
1423
|
+
provider = new Provider({ client: this._client });
|
|
1424
|
+
find = new Find({ client: this._client });
|
|
1425
|
+
file = new File$1({ client: this._client });
|
|
1426
|
+
app = new App({ client: this._client });
|
|
1427
|
+
mcp = new Mcp({ client: this._client });
|
|
1428
|
+
lsp = new Lsp({ client: this._client });
|
|
1429
|
+
formatter = new Formatter({ client: this._client });
|
|
1430
|
+
tui = new Tui({ client: this._client });
|
|
1431
|
+
auth = new Auth({ client: this._client });
|
|
1432
|
+
event = new Event({ client: this._client });
|
|
1433
|
+
};
|
|
1434
|
+
|
|
1435
|
+
//#endregion
|
|
1436
|
+
//#region ../../node_modules/.pnpm/@opencode-ai+sdk@1.1.55/node_modules/@opencode-ai/sdk/dist/client.js
|
|
1437
|
+
function createOpencodeClient(config) {
|
|
1438
|
+
if (!config?.fetch) {
|
|
1439
|
+
const customFetch = (req) => {
|
|
1440
|
+
req.timeout = false;
|
|
1441
|
+
return fetch(req);
|
|
1442
|
+
};
|
|
1443
|
+
config = {
|
|
1444
|
+
...config,
|
|
1445
|
+
fetch: customFetch
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
if (config?.directory) config.headers = {
|
|
1449
|
+
...config.headers,
|
|
1450
|
+
"x-opencode-directory": config.directory
|
|
1451
|
+
};
|
|
1452
|
+
return new OpencodeClient({ client: createClient(config) });
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
//#endregion
|
|
1456
|
+
//#region ../../node_modules/.pnpm/valibot@1.2.0_typescript@5.9.3/node_modules/valibot/dist/index.mjs
|
|
1457
|
+
let store$4;
|
|
1458
|
+
/**
|
|
1459
|
+
* Returns the global configuration.
|
|
1460
|
+
*
|
|
1461
|
+
* @param config The config to merge.
|
|
1462
|
+
*
|
|
1463
|
+
* @returns The configuration.
|
|
1464
|
+
*/
|
|
1465
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
1466
|
+
function getGlobalConfig(config$1) {
|
|
1467
|
+
return {
|
|
1468
|
+
lang: config$1?.lang ?? store$4?.lang,
|
|
1469
|
+
message: config$1?.message,
|
|
1470
|
+
abortEarly: config$1?.abortEarly ?? store$4?.abortEarly,
|
|
1471
|
+
abortPipeEarly: config$1?.abortPipeEarly ?? store$4?.abortPipeEarly
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Returns the default value of the schema.
|
|
1476
|
+
*
|
|
1477
|
+
* @param schema The schema to get it from.
|
|
1478
|
+
* @param dataset The input dataset if available.
|
|
1479
|
+
* @param config The config if available.
|
|
1480
|
+
*
|
|
1481
|
+
* @returns The default value.
|
|
1482
|
+
*/
|
|
1483
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
1484
|
+
function getDefault(schema, dataset, config$1) {
|
|
1485
|
+
return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
|
|
1486
|
+
}
|
|
1487
|
+
/**
|
|
1488
|
+
* Parses an unknown input based on a schema.
|
|
1489
|
+
*
|
|
1490
|
+
* @param schema The schema to be used.
|
|
1491
|
+
* @param input The input to be parsed.
|
|
1492
|
+
* @param config The parse configuration.
|
|
1493
|
+
*
|
|
1494
|
+
* @returns The parse result.
|
|
1495
|
+
*/
|
|
1496
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
1497
|
+
function safeParse(schema, input, config$1) {
|
|
1498
|
+
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config$1));
|
|
1499
|
+
return {
|
|
1500
|
+
typed: dataset.typed,
|
|
1501
|
+
success: !dataset.issues,
|
|
1502
|
+
output: dataset.value,
|
|
1503
|
+
issues: dataset.issues
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
//#endregion
|
|
1508
|
+
//#region ../../node_modules/.pnpm/@valibot+to-json-schema@1.5.0_valibot@1.2.0_typescript@5.9.3_/node_modules/@valibot/to-json-schema/dist/index.mjs
|
|
1509
|
+
/**
|
|
1510
|
+
* Adds an error message to the errors array.
|
|
1511
|
+
*
|
|
1512
|
+
* @param errors The array of error messages.
|
|
1513
|
+
* @param message The error message to add.
|
|
1514
|
+
*
|
|
1515
|
+
* @returns The new errors.
|
|
1516
|
+
*/
|
|
1517
|
+
function addError(errors, message) {
|
|
1518
|
+
if (errors) {
|
|
1519
|
+
errors.push(message);
|
|
1520
|
+
return errors;
|
|
1521
|
+
}
|
|
1522
|
+
return [message];
|
|
1523
|
+
}
|
|
1524
|
+
/**
|
|
1525
|
+
* Throws an error or logs a warning based on the configuration.
|
|
1526
|
+
*
|
|
1527
|
+
* @param message The message to throw or log.
|
|
1528
|
+
* @param config The conversion configuration.
|
|
1529
|
+
*/
|
|
1530
|
+
function handleError(message, config) {
|
|
1531
|
+
switch (config?.errorMode) {
|
|
1532
|
+
case "ignore": break;
|
|
1533
|
+
case "warn":
|
|
1534
|
+
console.warn(message);
|
|
1535
|
+
break;
|
|
1536
|
+
default: throw new Error(message);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
/**
|
|
1540
|
+
* Converts any supported Valibot action to the JSON Schema format.
|
|
1541
|
+
*
|
|
1542
|
+
* @param jsonSchema The JSON Schema object.
|
|
1543
|
+
* @param valibotAction The Valibot action object.
|
|
1544
|
+
* @param config The conversion configuration.
|
|
1545
|
+
*
|
|
1546
|
+
* @returns The converted JSON Schema.
|
|
1547
|
+
*/
|
|
1548
|
+
function convertAction(jsonSchema, valibotAction, config) {
|
|
1549
|
+
if (config?.ignoreActions?.includes(valibotAction.type)) return jsonSchema;
|
|
1550
|
+
let errors;
|
|
1551
|
+
switch (valibotAction.type) {
|
|
1552
|
+
case "base64":
|
|
1553
|
+
jsonSchema.contentEncoding = "base64";
|
|
1554
|
+
break;
|
|
1555
|
+
case "bic":
|
|
1556
|
+
case "cuid2":
|
|
1557
|
+
case "decimal":
|
|
1558
|
+
case "digits":
|
|
1559
|
+
case "emoji":
|
|
1560
|
+
case "hexadecimal":
|
|
1561
|
+
case "hex_color":
|
|
1562
|
+
case "nanoid":
|
|
1563
|
+
case "octal":
|
|
1564
|
+
case "ulid":
|
|
1565
|
+
jsonSchema.pattern = valibotAction.requirement.source;
|
|
1566
|
+
break;
|
|
1567
|
+
case "description":
|
|
1568
|
+
jsonSchema.description = valibotAction.description;
|
|
1569
|
+
break;
|
|
1570
|
+
case "email":
|
|
1571
|
+
jsonSchema.format = "email";
|
|
1572
|
+
break;
|
|
1573
|
+
case "empty":
|
|
1574
|
+
if (jsonSchema.type === "array") jsonSchema.maxItems = 0;
|
|
1575
|
+
else {
|
|
1576
|
+
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
|
|
1577
|
+
jsonSchema.maxLength = 0;
|
|
1578
|
+
}
|
|
1579
|
+
break;
|
|
1580
|
+
case "entries":
|
|
1581
|
+
jsonSchema.minProperties = valibotAction.requirement;
|
|
1582
|
+
jsonSchema.maxProperties = valibotAction.requirement;
|
|
1583
|
+
break;
|
|
1584
|
+
case "examples":
|
|
1585
|
+
if (Array.isArray(jsonSchema.examples)) jsonSchema.examples = [...jsonSchema.examples, ...valibotAction.examples];
|
|
1586
|
+
else jsonSchema.examples = valibotAction.examples;
|
|
1587
|
+
break;
|
|
1588
|
+
case "integer":
|
|
1589
|
+
jsonSchema.type = "integer";
|
|
1590
|
+
break;
|
|
1591
|
+
case "ipv4":
|
|
1592
|
+
jsonSchema.format = "ipv4";
|
|
1593
|
+
break;
|
|
1594
|
+
case "ipv6":
|
|
1595
|
+
jsonSchema.format = "ipv6";
|
|
1596
|
+
break;
|
|
1597
|
+
case "iso_date":
|
|
1598
|
+
jsonSchema.format = "date";
|
|
1599
|
+
break;
|
|
1600
|
+
case "iso_date_time":
|
|
1601
|
+
case "iso_timestamp":
|
|
1602
|
+
jsonSchema.format = "date-time";
|
|
1603
|
+
break;
|
|
1604
|
+
case "iso_time":
|
|
1605
|
+
jsonSchema.format = "time";
|
|
1606
|
+
break;
|
|
1607
|
+
case "length":
|
|
1608
|
+
if (jsonSchema.type === "array") {
|
|
1609
|
+
jsonSchema.minItems = valibotAction.requirement;
|
|
1610
|
+
jsonSchema.maxItems = valibotAction.requirement;
|
|
1611
|
+
} else {
|
|
1612
|
+
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
|
|
1613
|
+
jsonSchema.minLength = valibotAction.requirement;
|
|
1614
|
+
jsonSchema.maxLength = valibotAction.requirement;
|
|
1615
|
+
}
|
|
1616
|
+
break;
|
|
1617
|
+
case "max_entries":
|
|
1618
|
+
jsonSchema.maxProperties = valibotAction.requirement;
|
|
1619
|
+
break;
|
|
1620
|
+
case "max_length":
|
|
1621
|
+
if (jsonSchema.type === "array") jsonSchema.maxItems = valibotAction.requirement;
|
|
1622
|
+
else {
|
|
1623
|
+
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
|
|
1624
|
+
jsonSchema.maxLength = valibotAction.requirement;
|
|
1625
|
+
}
|
|
1626
|
+
break;
|
|
1627
|
+
case "max_value":
|
|
1628
|
+
if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "max_value" action is not supported on type "${jsonSchema.type}".`);
|
|
1629
|
+
jsonSchema.maximum = valibotAction.requirement;
|
|
1630
|
+
break;
|
|
1631
|
+
case "metadata":
|
|
1632
|
+
if (typeof valibotAction.metadata.title === "string") jsonSchema.title = valibotAction.metadata.title;
|
|
1633
|
+
if (typeof valibotAction.metadata.description === "string") jsonSchema.description = valibotAction.metadata.description;
|
|
1634
|
+
if (Array.isArray(valibotAction.metadata.examples)) if (Array.isArray(jsonSchema.examples)) jsonSchema.examples = [...jsonSchema.examples, ...valibotAction.metadata.examples];
|
|
1635
|
+
else jsonSchema.examples = valibotAction.metadata.examples;
|
|
1636
|
+
break;
|
|
1637
|
+
case "min_entries":
|
|
1638
|
+
jsonSchema.minProperties = valibotAction.requirement;
|
|
1639
|
+
break;
|
|
1640
|
+
case "min_length":
|
|
1641
|
+
if (jsonSchema.type === "array") jsonSchema.minItems = valibotAction.requirement;
|
|
1642
|
+
else {
|
|
1643
|
+
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
|
|
1644
|
+
jsonSchema.minLength = valibotAction.requirement;
|
|
1645
|
+
}
|
|
1646
|
+
break;
|
|
1647
|
+
case "min_value":
|
|
1648
|
+
if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "min_value" action is not supported on type "${jsonSchema.type}".`);
|
|
1649
|
+
jsonSchema.minimum = valibotAction.requirement;
|
|
1650
|
+
break;
|
|
1651
|
+
case "multiple_of":
|
|
1652
|
+
jsonSchema.multipleOf = valibotAction.requirement;
|
|
1653
|
+
break;
|
|
1654
|
+
case "non_empty":
|
|
1655
|
+
if (jsonSchema.type === "array") jsonSchema.minItems = 1;
|
|
1656
|
+
else {
|
|
1657
|
+
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
|
|
1658
|
+
jsonSchema.minLength = 1;
|
|
1659
|
+
}
|
|
1660
|
+
break;
|
|
1661
|
+
case "regex":
|
|
1662
|
+
if (valibotAction.requirement.flags) errors = addError(errors, "RegExp flags are not supported by JSON Schema.");
|
|
1663
|
+
jsonSchema.pattern = valibotAction.requirement.source;
|
|
1664
|
+
break;
|
|
1665
|
+
case "title":
|
|
1666
|
+
jsonSchema.title = valibotAction.title;
|
|
1667
|
+
break;
|
|
1668
|
+
case "url":
|
|
1669
|
+
jsonSchema.format = "uri";
|
|
1670
|
+
break;
|
|
1671
|
+
case "uuid":
|
|
1672
|
+
jsonSchema.format = "uuid";
|
|
1673
|
+
break;
|
|
1674
|
+
case "value":
|
|
1675
|
+
jsonSchema.const = valibotAction.requirement;
|
|
1676
|
+
break;
|
|
1677
|
+
default: errors = addError(errors, `The "${valibotAction.type}" action cannot be converted to JSON Schema.`);
|
|
1678
|
+
}
|
|
1679
|
+
if (config?.overrideAction) {
|
|
1680
|
+
const actionOverride = config.overrideAction({
|
|
1681
|
+
valibotAction,
|
|
1682
|
+
jsonSchema,
|
|
1683
|
+
errors
|
|
1684
|
+
});
|
|
1685
|
+
if (actionOverride) return { ...actionOverride };
|
|
1686
|
+
}
|
|
1687
|
+
if (errors) for (const message of errors) handleError(message, config);
|
|
1688
|
+
return jsonSchema;
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Flattens a Valibot pipe by recursively expanding nested pipes.
|
|
1692
|
+
*
|
|
1693
|
+
* @param pipe The pipeline to flatten.
|
|
1694
|
+
*
|
|
1695
|
+
* @returns A flat pipeline.
|
|
1696
|
+
*/
|
|
1697
|
+
function flattenPipe(pipe) {
|
|
1698
|
+
return pipe.flatMap((item) => "pipe" in item ? flattenPipe(item.pipe) : item);
|
|
1699
|
+
}
|
|
1700
|
+
let refCount = 0;
|
|
1701
|
+
/**
|
|
1702
|
+
* Converts any supported Valibot schema to the JSON Schema format.
|
|
1703
|
+
*
|
|
1704
|
+
* @param jsonSchema The JSON Schema object.
|
|
1705
|
+
* @param valibotSchema The Valibot schema object.
|
|
1706
|
+
* @param config The conversion configuration.
|
|
1707
|
+
* @param context The conversion context.
|
|
1708
|
+
* @param skipRef Whether to skip using a reference.
|
|
1709
|
+
*
|
|
1710
|
+
* @returns The converted JSON Schema.
|
|
1711
|
+
*/
|
|
1712
|
+
function convertSchema(jsonSchema, valibotSchema, config, context, skipRef = false) {
|
|
1713
|
+
if (!skipRef) {
|
|
1714
|
+
const referenceId = context.referenceMap.get(valibotSchema);
|
|
1715
|
+
if (referenceId) {
|
|
1716
|
+
jsonSchema.$ref = `#/$defs/${referenceId}`;
|
|
1717
|
+
if (config?.overrideRef) {
|
|
1718
|
+
const refOverride = config.overrideRef({
|
|
1719
|
+
...context,
|
|
1720
|
+
referenceId,
|
|
1721
|
+
valibotSchema,
|
|
1722
|
+
jsonSchema
|
|
1723
|
+
});
|
|
1724
|
+
if (refOverride) jsonSchema.$ref = refOverride;
|
|
1725
|
+
}
|
|
1726
|
+
return jsonSchema;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
if ("pipe" in valibotSchema) {
|
|
1730
|
+
const flatPipe = flattenPipe(valibotSchema.pipe);
|
|
1731
|
+
let startIndex = 0;
|
|
1732
|
+
let stopIndex = flatPipe.length - 1;
|
|
1733
|
+
if (config?.typeMode === "input") {
|
|
1734
|
+
const inputStopIndex = flatPipe.slice(1).findIndex((item) => item.kind === "schema" || item.kind === "transformation" && (item.type === "find_item" || item.type === "parse_json" || item.type === "raw_transform" || item.type === "reduce_items" || item.type === "stringify_json" || item.type === "to_bigint" || item.type === "to_boolean" || item.type === "to_date" || item.type === "to_number" || item.type === "to_string" || item.type === "transform"));
|
|
1735
|
+
if (inputStopIndex !== -1) stopIndex = inputStopIndex;
|
|
1736
|
+
} else if (config?.typeMode === "output") {
|
|
1737
|
+
const outputStartIndex = flatPipe.findLastIndex((item) => item.kind === "schema");
|
|
1738
|
+
if (outputStartIndex !== -1) startIndex = outputStartIndex;
|
|
1739
|
+
}
|
|
1740
|
+
for (let index = startIndex; index <= stopIndex; index++) {
|
|
1741
|
+
const valibotPipeItem = flatPipe[index];
|
|
1742
|
+
if (valibotPipeItem.kind === "schema") {
|
|
1743
|
+
if (index > startIndex) handleError("Set the \"typeMode\" config to \"input\" or \"output\" to convert pipelines with multiple schemas.", config);
|
|
1744
|
+
jsonSchema = convertSchema(jsonSchema, valibotPipeItem, config, context, true);
|
|
1745
|
+
} else jsonSchema = convertAction(jsonSchema, valibotPipeItem, config);
|
|
1746
|
+
}
|
|
1747
|
+
return jsonSchema;
|
|
1748
|
+
}
|
|
1749
|
+
let errors;
|
|
1750
|
+
switch (valibotSchema.type) {
|
|
1751
|
+
case "boolean":
|
|
1752
|
+
jsonSchema.type = "boolean";
|
|
1753
|
+
break;
|
|
1754
|
+
case "null":
|
|
1755
|
+
if (config?.target === "openapi-3.0") jsonSchema.enum = [null];
|
|
1756
|
+
else jsonSchema.type = "null";
|
|
1757
|
+
break;
|
|
1758
|
+
case "number":
|
|
1759
|
+
jsonSchema.type = "number";
|
|
1760
|
+
break;
|
|
1761
|
+
case "string":
|
|
1762
|
+
jsonSchema.type = "string";
|
|
1763
|
+
break;
|
|
1764
|
+
case "array":
|
|
1765
|
+
jsonSchema.type = "array";
|
|
1766
|
+
jsonSchema.items = convertSchema({}, valibotSchema.item, config, context);
|
|
1767
|
+
break;
|
|
1768
|
+
case "tuple":
|
|
1769
|
+
case "tuple_with_rest":
|
|
1770
|
+
case "loose_tuple":
|
|
1771
|
+
case "strict_tuple":
|
|
1772
|
+
jsonSchema.type = "array";
|
|
1773
|
+
if (config?.target === "openapi-3.0") {
|
|
1774
|
+
jsonSchema.items = { anyOf: [] };
|
|
1775
|
+
jsonSchema.minItems = valibotSchema.items.length;
|
|
1776
|
+
for (const item of valibotSchema.items) jsonSchema.items.anyOf.push(convertSchema({}, item, config, context));
|
|
1777
|
+
if (valibotSchema.type === "tuple_with_rest") jsonSchema.items.anyOf.push(convertSchema({}, valibotSchema.rest, config, context));
|
|
1778
|
+
else if (valibotSchema.type === "strict_tuple" || valibotSchema.type === "tuple") jsonSchema.maxItems = valibotSchema.items.length;
|
|
1779
|
+
} else if (config?.target === "draft-2020-12") {
|
|
1780
|
+
jsonSchema.prefixItems = [];
|
|
1781
|
+
jsonSchema.minItems = valibotSchema.items.length;
|
|
1782
|
+
for (const item of valibotSchema.items) jsonSchema.prefixItems.push(convertSchema({}, item, config, context));
|
|
1783
|
+
if (valibotSchema.type === "tuple_with_rest") jsonSchema.items = convertSchema({}, valibotSchema.rest, config, context);
|
|
1784
|
+
else if (valibotSchema.type === "strict_tuple") jsonSchema.items = false;
|
|
1785
|
+
} else {
|
|
1786
|
+
jsonSchema.items = [];
|
|
1787
|
+
jsonSchema.minItems = valibotSchema.items.length;
|
|
1788
|
+
for (const item of valibotSchema.items) jsonSchema.items.push(convertSchema({}, item, config, context));
|
|
1789
|
+
if (valibotSchema.type === "tuple_with_rest") jsonSchema.additionalItems = convertSchema({}, valibotSchema.rest, config, context);
|
|
1790
|
+
else if (valibotSchema.type === "strict_tuple") jsonSchema.additionalItems = false;
|
|
1791
|
+
}
|
|
1792
|
+
break;
|
|
1793
|
+
case "object":
|
|
1794
|
+
case "object_with_rest":
|
|
1795
|
+
case "loose_object":
|
|
1796
|
+
case "strict_object":
|
|
1797
|
+
jsonSchema.type = "object";
|
|
1798
|
+
jsonSchema.properties = {};
|
|
1799
|
+
jsonSchema.required = [];
|
|
1800
|
+
for (const key in valibotSchema.entries) {
|
|
1801
|
+
const entry = valibotSchema.entries[key];
|
|
1802
|
+
jsonSchema.properties[key] = convertSchema({}, entry, config, context);
|
|
1803
|
+
if (entry.type !== "exact_optional" && entry.type !== "nullish" && entry.type !== "optional") jsonSchema.required.push(key);
|
|
1804
|
+
}
|
|
1805
|
+
if (valibotSchema.type === "object_with_rest") jsonSchema.additionalProperties = convertSchema({}, valibotSchema.rest, config, context);
|
|
1806
|
+
else if (valibotSchema.type === "strict_object") jsonSchema.additionalProperties = false;
|
|
1807
|
+
break;
|
|
1808
|
+
case "record":
|
|
1809
|
+
if (config?.target === "openapi-3.0" && "pipe" in valibotSchema.key) errors = addError(errors, "The \"record\" schema with a schema for the key that contains a \"pipe\" cannot be converted to JSON Schema.");
|
|
1810
|
+
if (valibotSchema.key.type !== "string") errors = addError(errors, `The "record" schema with the "${valibotSchema.key.type}" schema for the key cannot be converted to JSON Schema.`);
|
|
1811
|
+
jsonSchema.type = "object";
|
|
1812
|
+
if (config?.target !== "openapi-3.0") jsonSchema.propertyNames = convertSchema({}, valibotSchema.key, config, context);
|
|
1813
|
+
jsonSchema.additionalProperties = convertSchema({}, valibotSchema.value, config, context);
|
|
1814
|
+
break;
|
|
1815
|
+
case "any":
|
|
1816
|
+
case "unknown": break;
|
|
1817
|
+
case "nullable":
|
|
1818
|
+
case "nullish":
|
|
1819
|
+
if (config?.target === "openapi-3.0") {
|
|
1820
|
+
const innerSchema = convertSchema({}, valibotSchema.wrapped, config, context);
|
|
1821
|
+
Object.assign(jsonSchema, innerSchema);
|
|
1822
|
+
jsonSchema.nullable = true;
|
|
1823
|
+
} else jsonSchema.anyOf = [convertSchema({}, valibotSchema.wrapped, config, context), { type: "null" }];
|
|
1824
|
+
if (valibotSchema.default !== void 0) jsonSchema.default = getDefault(valibotSchema);
|
|
1825
|
+
break;
|
|
1826
|
+
case "exact_optional":
|
|
1827
|
+
case "optional":
|
|
1828
|
+
case "undefinedable":
|
|
1829
|
+
jsonSchema = convertSchema(jsonSchema, valibotSchema.wrapped, config, context);
|
|
1830
|
+
if (valibotSchema.default !== void 0) jsonSchema.default = getDefault(valibotSchema);
|
|
1831
|
+
break;
|
|
1832
|
+
case "literal":
|
|
1833
|
+
if (typeof valibotSchema.literal !== "boolean" && typeof valibotSchema.literal !== "number" && typeof valibotSchema.literal !== "string") errors = addError(errors, "The value of the \"literal\" schema is not JSON compatible.");
|
|
1834
|
+
if (config?.target === "openapi-3.0") jsonSchema.enum = [valibotSchema.literal];
|
|
1835
|
+
else jsonSchema.const = valibotSchema.literal;
|
|
1836
|
+
break;
|
|
1837
|
+
case "enum":
|
|
1838
|
+
jsonSchema.enum = valibotSchema.options;
|
|
1839
|
+
break;
|
|
1840
|
+
case "picklist":
|
|
1841
|
+
if (valibotSchema.options.some((option) => typeof option !== "number" && typeof option !== "string")) errors = addError(errors, "An option of the \"picklist\" schema is not JSON compatible.");
|
|
1842
|
+
jsonSchema.enum = valibotSchema.options;
|
|
1843
|
+
break;
|
|
1844
|
+
case "union":
|
|
1845
|
+
jsonSchema.anyOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
|
|
1846
|
+
break;
|
|
1847
|
+
case "variant":
|
|
1848
|
+
jsonSchema.oneOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
|
|
1849
|
+
break;
|
|
1850
|
+
case "intersect":
|
|
1851
|
+
jsonSchema.allOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
|
|
1852
|
+
break;
|
|
1853
|
+
case "lazy": {
|
|
1854
|
+
let wrappedValibotSchema = context.getterMap.get(valibotSchema.getter);
|
|
1855
|
+
if (!wrappedValibotSchema) {
|
|
1856
|
+
wrappedValibotSchema = valibotSchema.getter(void 0);
|
|
1857
|
+
context.getterMap.set(valibotSchema.getter, wrappedValibotSchema);
|
|
1858
|
+
}
|
|
1859
|
+
let referenceId = context.referenceMap.get(wrappedValibotSchema);
|
|
1860
|
+
if (!referenceId) {
|
|
1861
|
+
referenceId = `${refCount++}`;
|
|
1862
|
+
context.referenceMap.set(wrappedValibotSchema, referenceId);
|
|
1863
|
+
context.definitions[referenceId] = convertSchema({}, wrappedValibotSchema, config, context, true);
|
|
1864
|
+
}
|
|
1865
|
+
jsonSchema.$ref = `#/$defs/${referenceId}`;
|
|
1866
|
+
if (config?.overrideRef) {
|
|
1867
|
+
const refOverride = config.overrideRef({
|
|
1868
|
+
...context,
|
|
1869
|
+
referenceId,
|
|
1870
|
+
valibotSchema: wrappedValibotSchema,
|
|
1871
|
+
jsonSchema
|
|
1872
|
+
});
|
|
1873
|
+
if (refOverride) jsonSchema.$ref = refOverride;
|
|
1874
|
+
}
|
|
1875
|
+
break;
|
|
1876
|
+
}
|
|
1877
|
+
default: errors = addError(errors, `The "${valibotSchema.type}" schema cannot be converted to JSON Schema.`);
|
|
1878
|
+
}
|
|
1879
|
+
if (config?.overrideSchema) {
|
|
1880
|
+
const schemaOverride = config.overrideSchema({
|
|
1881
|
+
...context,
|
|
1882
|
+
referenceId: context.referenceMap.get(valibotSchema),
|
|
1883
|
+
valibotSchema,
|
|
1884
|
+
jsonSchema,
|
|
1885
|
+
errors
|
|
1886
|
+
});
|
|
1887
|
+
if (schemaOverride) return { ...schemaOverride };
|
|
1888
|
+
}
|
|
1889
|
+
if (errors) for (const message of errors) handleError(message, config);
|
|
1890
|
+
return jsonSchema;
|
|
1891
|
+
}
|
|
1892
|
+
let store;
|
|
1893
|
+
/**
|
|
1894
|
+
* Returns the current global schema definitions.
|
|
1895
|
+
*
|
|
1896
|
+
* @returns The schema definitions.
|
|
1897
|
+
*
|
|
1898
|
+
* @beta
|
|
1899
|
+
*/
|
|
1900
|
+
function getGlobalDefs() {
|
|
1901
|
+
return store;
|
|
1902
|
+
}
|
|
1903
|
+
/**
|
|
1904
|
+
* Converts a Valibot schema to the JSON Schema format.
|
|
1905
|
+
*
|
|
1906
|
+
* @param schema The Valibot schema object.
|
|
1907
|
+
* @param config The JSON Schema configuration.
|
|
1908
|
+
*
|
|
1909
|
+
* @returns The converted JSON Schema.
|
|
1910
|
+
*/
|
|
1911
|
+
function toJsonSchema(schema, config) {
|
|
1912
|
+
const context = {
|
|
1913
|
+
definitions: {},
|
|
1914
|
+
referenceMap: /* @__PURE__ */ new Map(),
|
|
1915
|
+
getterMap: /* @__PURE__ */ new Map()
|
|
1916
|
+
};
|
|
1917
|
+
const definitions = config?.definitions ?? getGlobalDefs();
|
|
1918
|
+
if (definitions) {
|
|
1919
|
+
for (const key in definitions) context.referenceMap.set(definitions[key], key);
|
|
1920
|
+
for (const key in definitions) context.definitions[key] = convertSchema({}, definitions[key], config, context, true);
|
|
1921
|
+
}
|
|
1922
|
+
const jsonSchema = convertSchema({}, schema, config, context);
|
|
1923
|
+
const target = config?.target ?? "draft-07";
|
|
1924
|
+
if (target === "draft-2020-12") jsonSchema.$schema = "https://json-schema.org/draft/2020-12/schema";
|
|
1925
|
+
else if (target === "draft-07") jsonSchema.$schema = "http://json-schema.org/draft-07/schema#";
|
|
1926
|
+
if (context.referenceMap.size) jsonSchema.$defs = context.definitions;
|
|
1927
|
+
return jsonSchema;
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
//#endregion
|
|
1931
|
+
//#region ../client/dist/index.mjs
|
|
1932
|
+
/**
|
|
1933
|
+
* Error thrown when skill result extraction or validation fails.
|
|
1934
|
+
*/
|
|
1935
|
+
var SkillOutputError = class extends Error {
|
|
1936
|
+
sessionId;
|
|
1937
|
+
rawOutput;
|
|
1938
|
+
validationErrors;
|
|
1939
|
+
constructor(message, opts) {
|
|
1940
|
+
super(message);
|
|
1941
|
+
this.name = "SkillOutputError";
|
|
1942
|
+
this.sessionId = opts.sessionId;
|
|
1943
|
+
this.rawOutput = opts.rawOutput;
|
|
1944
|
+
this.validationErrors = opts.validationErrors;
|
|
1945
|
+
}
|
|
1946
|
+
};
|
|
1947
|
+
/**
|
|
1948
|
+
* Summarize tool input into a short human-readable string.
|
|
1949
|
+
*/
|
|
1950
|
+
function summarizeInput(tool, input) {
|
|
1951
|
+
if (input.command) return String(input.command).slice(0, 500);
|
|
1952
|
+
if (input.filePath) return String(input.filePath);
|
|
1953
|
+
if (input.pattern) return String(input.pattern);
|
|
1954
|
+
if (input.url) return String(input.url);
|
|
1955
|
+
if (input.name) return String(input.name);
|
|
1956
|
+
return tool;
|
|
1957
|
+
}
|
|
1958
|
+
/**
|
|
1959
|
+
* Attempt to parse a raw OpenCode SSE event and convert it to a FlueEvent.
|
|
1960
|
+
* Returns null if the event should be filtered out (not relevant for logs).
|
|
1961
|
+
*/
|
|
1962
|
+
function transformEvent(raw) {
|
|
1963
|
+
const type = raw?.type;
|
|
1964
|
+
if (!type) return null;
|
|
1965
|
+
const now = Date.now();
|
|
1966
|
+
if (type === "message.part.updated") {
|
|
1967
|
+
const part = raw.properties?.part;
|
|
1968
|
+
if (!part) return null;
|
|
1969
|
+
const sessionId = part.sessionID ?? "";
|
|
1970
|
+
if (part.type === "tool") {
|
|
1971
|
+
const tool = part.tool ?? "?";
|
|
1972
|
+
const state = part.state;
|
|
1973
|
+
if (!state) return null;
|
|
1974
|
+
const input = summarizeInput(tool, state.input ?? {});
|
|
1975
|
+
switch (state.status) {
|
|
1976
|
+
case "pending": return {
|
|
1977
|
+
timestamp: now,
|
|
1978
|
+
sessionId,
|
|
1979
|
+
type: "tool.pending",
|
|
1980
|
+
tool,
|
|
1981
|
+
input
|
|
1982
|
+
};
|
|
1983
|
+
case "running": return {
|
|
1984
|
+
timestamp: now,
|
|
1985
|
+
sessionId,
|
|
1986
|
+
type: "tool.running",
|
|
1987
|
+
tool,
|
|
1988
|
+
input
|
|
1989
|
+
};
|
|
1990
|
+
case "completed": return {
|
|
1991
|
+
timestamp: now,
|
|
1992
|
+
sessionId,
|
|
1993
|
+
type: "tool.complete",
|
|
1994
|
+
tool,
|
|
1995
|
+
input,
|
|
1996
|
+
output: (state.output ?? "").slice(0, 1e3),
|
|
1997
|
+
duration: state.time?.end && state.time?.start ? state.time.end - state.time.start : 0
|
|
1998
|
+
};
|
|
1999
|
+
case "error": {
|
|
2000
|
+
const duration = state.time?.end && state.time?.start ? state.time.end - state.time.start : 0;
|
|
2001
|
+
return {
|
|
2002
|
+
timestamp: now,
|
|
2003
|
+
sessionId,
|
|
2004
|
+
type: "tool.error",
|
|
2005
|
+
tool,
|
|
2006
|
+
input,
|
|
2007
|
+
error: state.error ?? "unknown error",
|
|
2008
|
+
duration
|
|
2009
|
+
};
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
return null;
|
|
2013
|
+
}
|
|
2014
|
+
if (part.type === "text") {
|
|
2015
|
+
const delta = raw.properties?.delta;
|
|
2016
|
+
if (delta) return {
|
|
2017
|
+
timestamp: now,
|
|
2018
|
+
sessionId,
|
|
2019
|
+
type: "text",
|
|
2020
|
+
text: delta
|
|
2021
|
+
};
|
|
2022
|
+
return null;
|
|
2023
|
+
}
|
|
2024
|
+
if (part.type === "step-start") return {
|
|
2025
|
+
timestamp: now,
|
|
2026
|
+
sessionId: part.sessionID ?? "",
|
|
2027
|
+
type: "step.start"
|
|
2028
|
+
};
|
|
2029
|
+
if (part.type === "step-finish") return {
|
|
2030
|
+
timestamp: now,
|
|
2031
|
+
sessionId: part.sessionID ?? "",
|
|
2032
|
+
type: "step.finish",
|
|
2033
|
+
reason: part.reason ?? "",
|
|
2034
|
+
tokens: {
|
|
2035
|
+
input: part.tokens?.input ?? 0,
|
|
2036
|
+
output: part.tokens?.output ?? 0
|
|
2037
|
+
},
|
|
2038
|
+
cost: part.cost ?? 0
|
|
2039
|
+
};
|
|
2040
|
+
return null;
|
|
2041
|
+
}
|
|
2042
|
+
if (type === "session.status") {
|
|
2043
|
+
const sessionId = raw.properties?.sessionID ?? "";
|
|
2044
|
+
const status = raw.properties?.status;
|
|
2045
|
+
if (status?.type === "busy") return {
|
|
2046
|
+
timestamp: now,
|
|
2047
|
+
sessionId,
|
|
2048
|
+
type: "status",
|
|
2049
|
+
status: "busy"
|
|
2050
|
+
};
|
|
2051
|
+
if (status?.type === "idle") return {
|
|
2052
|
+
timestamp: now,
|
|
2053
|
+
sessionId,
|
|
2054
|
+
type: "status",
|
|
2055
|
+
status: "idle"
|
|
2056
|
+
};
|
|
2057
|
+
if (status?.type === "retry") return {
|
|
2058
|
+
timestamp: now,
|
|
2059
|
+
sessionId,
|
|
2060
|
+
type: "status",
|
|
2061
|
+
status: "retry",
|
|
2062
|
+
message: status.message
|
|
2063
|
+
};
|
|
2064
|
+
return null;
|
|
2065
|
+
}
|
|
2066
|
+
if (type === "session.idle") return {
|
|
2067
|
+
timestamp: now,
|
|
2068
|
+
sessionId: raw.properties?.sessionID ?? "",
|
|
2069
|
+
type: "status",
|
|
2070
|
+
status: "idle"
|
|
2071
|
+
};
|
|
2072
|
+
if (type === "session.compacted") return {
|
|
2073
|
+
timestamp: now,
|
|
2074
|
+
sessionId: raw.properties?.sessionID ?? "",
|
|
2075
|
+
type: "status",
|
|
2076
|
+
status: "compacted"
|
|
2077
|
+
};
|
|
2078
|
+
if (type === "session.error") return {
|
|
2079
|
+
timestamp: now,
|
|
2080
|
+
sessionId: raw.properties?.sessionID ?? "",
|
|
2081
|
+
type: "error",
|
|
2082
|
+
message: raw.properties?.error ?? "unknown error"
|
|
2083
|
+
};
|
|
2084
|
+
return null;
|
|
2085
|
+
}
|
|
2086
|
+
async function runShell(command, options) {
|
|
2087
|
+
return new Promise((resolve) => {
|
|
2088
|
+
const child = exec(command, {
|
|
2089
|
+
cwd: options?.cwd,
|
|
2090
|
+
env: options?.env ? {
|
|
2091
|
+
...process.env,
|
|
2092
|
+
...options.env
|
|
2093
|
+
} : process.env,
|
|
2094
|
+
timeout: options?.timeout
|
|
2095
|
+
}, (error, stdout, stderr) => {
|
|
2096
|
+
const rawCode = error && typeof error.code === "number" ? error.code : 0;
|
|
2097
|
+
resolve({
|
|
2098
|
+
stdout: stdout ?? "",
|
|
2099
|
+
stderr: stderr ?? "",
|
|
2100
|
+
exitCode: error ? rawCode || 1 : 0
|
|
2101
|
+
});
|
|
2102
|
+
});
|
|
2103
|
+
if (options?.stdin) {
|
|
2104
|
+
child.stdin?.write(options.stdin);
|
|
2105
|
+
child.stdin?.end();
|
|
2106
|
+
}
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
/**
|
|
2110
|
+
* Checks if a Valibot schema represents a plain string type.
|
|
2111
|
+
*/
|
|
2112
|
+
function isStringSchema(schema) {
|
|
2113
|
+
return schema.type === "string";
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* Checks if a skill name is a file path (contains '/' or ends with '.md').
|
|
2117
|
+
*/
|
|
2118
|
+
function isFilePath(name) {
|
|
2119
|
+
return name.includes("/") || name.endsWith(".md");
|
|
2120
|
+
}
|
|
2121
|
+
/**
|
|
2122
|
+
* Build the prompt text for a skill invocation.
|
|
2123
|
+
*
|
|
2124
|
+
* If `name` looks like a file path (contains '/' or ends with '.md'), the
|
|
2125
|
+
* prompt instructs the agent to read and follow that file under
|
|
2126
|
+
* `.opencode/skills/`. Otherwise, it instructs the agent to use the named
|
|
2127
|
+
* skill.
|
|
2128
|
+
*
|
|
2129
|
+
* @param name - A skill name or a file path relative to .opencode/skills/.
|
|
2130
|
+
* @param args - Key-value arguments to include in the prompt.
|
|
2131
|
+
* @param schema - Optional Valibot schema for result extraction.
|
|
2132
|
+
* @returns The complete prompt string.
|
|
2133
|
+
*/
|
|
2134
|
+
function buildSkillPrompt(name, args, schema) {
|
|
2135
|
+
const parts = [
|
|
2136
|
+
"You are running in headless mode with no human operator. Work autonomously — never ask questions, never wait for user input, never use the question tool. Make your best judgment and proceed independently.",
|
|
2137
|
+
"",
|
|
2138
|
+
isFilePath(name) ? `Read and use the .opencode/skills/${name} skill.` : `Use the ${name} skill.`
|
|
2139
|
+
];
|
|
2140
|
+
if (args && Object.keys(args).length > 0) parts.push(`\nArguments:\n${JSON.stringify(args, null, 2)}`);
|
|
2141
|
+
if (schema) if (isStringSchema(schema)) parts.push("\nWhen complete, output your result between these exact delimiters (the result can contain any content including code blocks):", "---RESULT_START---", "Your text output here", "---RESULT_END---");
|
|
2142
|
+
else {
|
|
2143
|
+
const { $schema: _, ...schemaWithoutMeta } = toJsonSchema(schema, { errorMode: "ignore" });
|
|
2144
|
+
parts.push("\nWhen complete, output your result between these exact delimiters as JSON conforming to this schema:", "```json", JSON.stringify(schemaWithoutMeta, null, 2), "```", "", "Format:", "---RESULT_START---", "{\"key\": \"value\"}", "---RESULT_END---");
|
|
2145
|
+
}
|
|
2146
|
+
return parts.join("\n");
|
|
2147
|
+
}
|
|
2148
|
+
/**
|
|
2149
|
+
* Extracts and validates a structured result from OpenCode response parts.
|
|
2150
|
+
*
|
|
2151
|
+
* Scans TextParts for the last ---RESULT_START--- / ---RESULT_END--- block,
|
|
2152
|
+
* parses the content, and validates it against the provided Valibot schema.
|
|
2153
|
+
*
|
|
2154
|
+
* @param parts - The response parts from OpenCode's session.prompt().
|
|
2155
|
+
* @param schema - The Valibot schema to validate against.
|
|
2156
|
+
* @param sessionId - The session ID (for error reporting).
|
|
2157
|
+
* @returns The validated, typed result.
|
|
2158
|
+
* @throws {SkillOutputError} If no result block is found or validation fails.
|
|
2159
|
+
*/
|
|
2160
|
+
function extractResult(parts, schema, sessionId) {
|
|
2161
|
+
const allText = parts.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
2162
|
+
const resultBlock = extractLastResultBlock(allText);
|
|
2163
|
+
if (resultBlock === null) {
|
|
2164
|
+
console.error(`[flue] extractResult: no RESULT_START/RESULT_END block found (session: ${sessionId}, text length: ${allText.length} chars)`);
|
|
2165
|
+
console.error(`[flue] extractResult: response tail (last 500 chars): ${allText.slice(-500)}`);
|
|
2166
|
+
throw new SkillOutputError("No ---RESULT_START--- / ---RESULT_END--- block found in the assistant response.", {
|
|
2167
|
+
sessionId,
|
|
2168
|
+
rawOutput: allText
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
console.log(`[flue] extractResult: found result block (${resultBlock.length} chars, session: ${sessionId})`);
|
|
2172
|
+
if (schema.type === "string") {
|
|
2173
|
+
const parseResult = safeParse(schema, resultBlock);
|
|
2174
|
+
if (!parseResult.success) {
|
|
2175
|
+
console.error("[flue] extractResult: string validation failed", parseResult.issues);
|
|
2176
|
+
throw new SkillOutputError("Result validation failed for string schema.", {
|
|
2177
|
+
sessionId,
|
|
2178
|
+
rawOutput: resultBlock,
|
|
2179
|
+
validationErrors: parseResult.issues
|
|
2180
|
+
});
|
|
2181
|
+
}
|
|
2182
|
+
console.log(`[flue] extractResult: validated string result (${resultBlock.length} chars)`);
|
|
2183
|
+
return parseResult.output;
|
|
2184
|
+
}
|
|
2185
|
+
let parsed;
|
|
2186
|
+
try {
|
|
2187
|
+
parsed = JSON.parse(resultBlock);
|
|
2188
|
+
} catch (err) {
|
|
2189
|
+
console.error(`[flue] extractResult: JSON parse failed for block: ${resultBlock.slice(0, 200)}`);
|
|
2190
|
+
throw new SkillOutputError("Failed to parse result block as JSON.", {
|
|
2191
|
+
sessionId,
|
|
2192
|
+
rawOutput: resultBlock,
|
|
2193
|
+
validationErrors: err
|
|
2194
|
+
});
|
|
2195
|
+
}
|
|
2196
|
+
const parseResult = safeParse(schema, parsed);
|
|
2197
|
+
if (!parseResult.success) {
|
|
2198
|
+
console.error("[flue] extractResult: schema validation failed", parseResult.issues);
|
|
2199
|
+
console.error("[flue] extractResult: parsed value was:", JSON.stringify(parsed));
|
|
2200
|
+
throw new SkillOutputError("Result does not match the expected schema.", {
|
|
2201
|
+
sessionId,
|
|
2202
|
+
rawOutput: resultBlock,
|
|
2203
|
+
validationErrors: parseResult.issues
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
console.log("[flue] extractResult: validated result:", JSON.stringify(parseResult.output));
|
|
2207
|
+
return parseResult.output;
|
|
2208
|
+
}
|
|
2209
|
+
/**
|
|
2210
|
+
* Extracts the content of the last ---RESULT_START--- / ---RESULT_END--- block from text.
|
|
2211
|
+
* Returns null if no result block is found.
|
|
2212
|
+
*/
|
|
2213
|
+
function extractLastResultBlock(text) {
|
|
2214
|
+
const matches = text.matchAll(/---RESULT_START---\s*\n([\s\S]*?)---RESULT_END---/g);
|
|
2215
|
+
let lastMatch = null;
|
|
2216
|
+
for (const match of matches) lastMatch = match[1]?.trim() ?? null;
|
|
2217
|
+
return lastMatch;
|
|
2218
|
+
}
|
|
2219
|
+
/** How often to poll and log progress (ms). */
|
|
2220
|
+
const POLL_INTERVAL = 5e3;
|
|
2221
|
+
/** Max times we'll see 0 assistant messages before giving up. */
|
|
2222
|
+
const MAX_EMPTY_POLLS = 60;
|
|
2223
|
+
/** Max time to poll before timing out (ms) - 45 minutes. */
|
|
2224
|
+
const MAX_POLL_TIME = 2700 * 1e3;
|
|
2225
|
+
/**
|
|
2226
|
+
* Run a named skill via the OpenCode client and optionally extract a typed result.
|
|
2227
|
+
*/
|
|
2228
|
+
async function runSkill(client, workdir, name, options) {
|
|
2229
|
+
const { args, result: schema, model, prompt: promptOverride } = options ?? {};
|
|
2230
|
+
const prompt = promptOverride ?? buildSkillPrompt(name, args, schema);
|
|
2231
|
+
console.log(`[flue] skill("${name}"): starting`);
|
|
2232
|
+
console.log(`[flue] skill("${name}"): creating session`);
|
|
2233
|
+
const session = await client.session.create({
|
|
2234
|
+
body: { title: name },
|
|
2235
|
+
query: { directory: workdir }
|
|
2236
|
+
});
|
|
2237
|
+
console.log(`[flue] skill("${name}"): session created`, {
|
|
2238
|
+
hasData: !!session.data,
|
|
2239
|
+
sessionId: session.data?.id,
|
|
2240
|
+
error: session.error
|
|
2241
|
+
});
|
|
2242
|
+
if (!session.data) throw new Error(`Failed to create OpenCode session for skill "${name}".`);
|
|
2243
|
+
const sessionId = session.data.id;
|
|
2244
|
+
const promptStart = Date.now();
|
|
2245
|
+
console.log(`[flue] skill("${name}"): sending prompt async`);
|
|
2246
|
+
const asyncResult = await client.session.promptAsync({
|
|
2247
|
+
path: { id: sessionId },
|
|
2248
|
+
query: { directory: workdir },
|
|
2249
|
+
body: {
|
|
2250
|
+
...model ? { model } : {},
|
|
2251
|
+
parts: [{
|
|
2252
|
+
type: "text",
|
|
2253
|
+
text: prompt
|
|
2254
|
+
}]
|
|
2255
|
+
}
|
|
2256
|
+
});
|
|
2257
|
+
console.log(`[flue] skill("${name}"): prompt sent`, {
|
|
2258
|
+
hasError: !!asyncResult.error,
|
|
2259
|
+
error: asyncResult.error,
|
|
2260
|
+
data: asyncResult.data
|
|
2261
|
+
});
|
|
2262
|
+
if (asyncResult.error) throw new Error(`Failed to send prompt for skill "${name}" (session ${sessionId}): ${JSON.stringify(asyncResult.error)}`);
|
|
2263
|
+
await confirmSessionStarted(client, sessionId, workdir, name);
|
|
2264
|
+
console.log(`[flue] skill("${name}"): starting polling`);
|
|
2265
|
+
const parts = await pollUntilIdle(client, sessionId, workdir, name, promptStart);
|
|
2266
|
+
const promptElapsed = ((Date.now() - promptStart) / 1e3).toFixed(1);
|
|
2267
|
+
console.log(`[flue] skill("${name}"): completed (${promptElapsed}s)`);
|
|
2268
|
+
if (!schema) return;
|
|
2269
|
+
return extractResult(parts, schema, sessionId);
|
|
2270
|
+
}
|
|
2271
|
+
/**
|
|
2272
|
+
* After promptAsync, confirm that OpenCode actually started processing the session.
|
|
2273
|
+
* Polls quickly (1s) to detect the session appearing as "busy" or a user message being recorded.
|
|
2274
|
+
* Fails fast (~15s) instead of letting the poll loop run for 5 minutes.
|
|
2275
|
+
*/
|
|
2276
|
+
async function confirmSessionStarted(client, sessionId, workdir, skillName) {
|
|
2277
|
+
const maxAttempts = 15;
|
|
2278
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
2279
|
+
await sleep(1e3);
|
|
2280
|
+
if (((await client.session.status({ query: { directory: workdir } })).data?.[sessionId])?.type === "busy") {
|
|
2281
|
+
console.log(`[flue] skill("${skillName}"): session confirmed running`);
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
const messages = (await client.session.messages({
|
|
2285
|
+
path: { id: sessionId },
|
|
2286
|
+
query: { directory: workdir }
|
|
2287
|
+
})).data;
|
|
2288
|
+
if (messages && messages.length > 0) {
|
|
2289
|
+
console.log(`[flue] skill("${skillName}"): session confirmed (${messages.length} messages)`);
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
throw new Error(`Skill "${skillName}" failed to start: session ${sessionId} has no messages after 15s.\nThe prompt was accepted but OpenCode never began processing it.\nThis usually means no model is configured. Pass --model to the flue CLI or set "model" in opencode.json.`);
|
|
2294
|
+
}
|
|
2295
|
+
async function pollUntilIdle(client, sessionId, workdir, skillName, startTime) {
|
|
2296
|
+
let emptyPolls = 0;
|
|
2297
|
+
let pollCount = 0;
|
|
2298
|
+
for (;;) {
|
|
2299
|
+
await sleep(POLL_INTERVAL);
|
|
2300
|
+
pollCount++;
|
|
2301
|
+
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(0);
|
|
2302
|
+
if (Date.now() - startTime > MAX_POLL_TIME) throw new Error(`Skill "${skillName}" timed out after ${elapsed}s. Session never went idle. This may indicate a stuck session or OpenCode bug.`);
|
|
2303
|
+
const statusResult = await client.session.status({ query: { directory: workdir } });
|
|
2304
|
+
const sessionStatus = statusResult.data?.[sessionId];
|
|
2305
|
+
if (!sessionStatus || sessionStatus.type === "idle") {
|
|
2306
|
+
const parts = await fetchAllAssistantParts(client, sessionId, workdir);
|
|
2307
|
+
if (parts.length === 0) {
|
|
2308
|
+
emptyPolls++;
|
|
2309
|
+
if (emptyPolls % 12 === 0) {
|
|
2310
|
+
console.log(`[flue] skill("${skillName}"): status result: ${JSON.stringify({
|
|
2311
|
+
hasData: !!statusResult.data,
|
|
2312
|
+
sessionIds: statusResult.data ? Object.keys(statusResult.data) : [],
|
|
2313
|
+
error: statusResult.error
|
|
2314
|
+
})}`);
|
|
2315
|
+
console.log(`[flue] skill("${skillName}"): sessionStatus for ${sessionId}: ${JSON.stringify(sessionStatus)}`);
|
|
2316
|
+
}
|
|
2317
|
+
if (emptyPolls >= MAX_EMPTY_POLLS) {
|
|
2318
|
+
const allMessages = await client.session.messages({
|
|
2319
|
+
path: { id: sessionId },
|
|
2320
|
+
query: { directory: workdir }
|
|
2321
|
+
});
|
|
2322
|
+
console.error(`[flue] skill("${skillName}"): TIMEOUT DIAGNOSTICS`, JSON.stringify({
|
|
2323
|
+
sessionId,
|
|
2324
|
+
statusData: statusResult.data,
|
|
2325
|
+
messageCount: Array.isArray(allMessages.data) ? allMessages.data.length : 0,
|
|
2326
|
+
messages: allMessages.data
|
|
2327
|
+
}, null, 2));
|
|
2328
|
+
throw new Error(`Skill "${skillName}" produced no output after ${elapsed}s and ${emptyPolls} empty polls. The agent may have failed to start — check model ID and API key.`);
|
|
2329
|
+
}
|
|
2330
|
+
continue;
|
|
2331
|
+
}
|
|
2332
|
+
return parts;
|
|
2333
|
+
}
|
|
2334
|
+
if (pollCount % 12 === 0) console.log(`[flue] skill("${skillName}"): running (${elapsed}s)`);
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
/**
|
|
2338
|
+
* Fetch ALL parts from every assistant message in the session.
|
|
2339
|
+
*/
|
|
2340
|
+
async function fetchAllAssistantParts(client, sessionId, workdir) {
|
|
2341
|
+
const messagesResult = await client.session.messages({
|
|
2342
|
+
path: { id: sessionId },
|
|
2343
|
+
query: { directory: workdir }
|
|
2344
|
+
});
|
|
2345
|
+
if (!messagesResult.data) throw new Error(`Failed to fetch messages for session ${sessionId}.`);
|
|
2346
|
+
const assistantMessages = messagesResult.data.filter((m) => m.info.role === "assistant");
|
|
2347
|
+
const allParts = [];
|
|
2348
|
+
for (const msg of assistantMessages) allParts.push(...msg.parts ?? []);
|
|
2349
|
+
return allParts;
|
|
2350
|
+
}
|
|
2351
|
+
function sleep(ms) {
|
|
2352
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2353
|
+
}
|
|
2354
|
+
var Flue = class {
|
|
2355
|
+
/** Working branch for commits. */
|
|
2356
|
+
branch;
|
|
2357
|
+
/** Workflow arguments passed by the runner. */
|
|
2358
|
+
args;
|
|
2359
|
+
/** Scoped secrets passed by the runner. */
|
|
2360
|
+
secrets;
|
|
2361
|
+
workdir;
|
|
2362
|
+
model;
|
|
2363
|
+
client;
|
|
2364
|
+
constructor(options) {
|
|
2365
|
+
this.branch = options.branch ?? "main";
|
|
2366
|
+
this.args = options.args ?? {};
|
|
2367
|
+
this.secrets = options.secrets ?? {};
|
|
2368
|
+
this.workdir = options.workdir;
|
|
2369
|
+
this.model = options.model;
|
|
2370
|
+
this.client = createOpencodeClient({
|
|
2371
|
+
baseUrl: options.opencodeUrl ?? "http://localhost:48765",
|
|
2372
|
+
directory: options.workdir
|
|
2373
|
+
});
|
|
2374
|
+
}
|
|
2375
|
+
async skill(name, options) {
|
|
2376
|
+
const mergedOptions = {
|
|
2377
|
+
...options,
|
|
2378
|
+
args: this.args || options?.args ? {
|
|
2379
|
+
...this.args,
|
|
2380
|
+
...options?.args
|
|
2381
|
+
} : void 0,
|
|
2382
|
+
model: options?.model ?? this.model
|
|
2383
|
+
};
|
|
2384
|
+
return runSkill(this.client, this.workdir, name, mergedOptions);
|
|
2385
|
+
}
|
|
2386
|
+
async prompt(promptText, options) {
|
|
2387
|
+
const mergedOptions = {
|
|
2388
|
+
result: options?.result,
|
|
2389
|
+
model: options?.model ?? this.model,
|
|
2390
|
+
prompt: promptText
|
|
2391
|
+
};
|
|
2392
|
+
return runSkill(this.client, this.workdir, "__inline__", mergedOptions);
|
|
2393
|
+
}
|
|
2394
|
+
/** Execute a shell command with scoped environment variables. */
|
|
2395
|
+
async shell(command, options) {
|
|
2396
|
+
return runShell(command, {
|
|
2397
|
+
...options,
|
|
2398
|
+
cwd: options?.cwd ?? this.workdir
|
|
2399
|
+
});
|
|
2400
|
+
}
|
|
2401
|
+
/** Close the OpenCode client connection. */
|
|
2402
|
+
async close() {}
|
|
2403
|
+
};
|
|
2404
|
+
|
|
2405
|
+
//#endregion
|
|
2406
|
+
export { Flue, transformEvent };
|