@flue/cli 0.0.11 → 0.0.13

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.
@@ -1,2406 +0,0 @@
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 };