@nuucognition/flint-cli 0.5.0-alpha.0 → 0.5.1
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/README.md +9 -2
- package/dist/{chunk-O7OVKLLV.js → chunk-C66KJDI7.js} +1 -1
- package/dist/{chunk-XCVQLFHY.js → chunk-CBGQBE6C.js} +0 -1
- package/dist/{chunk-PONDZIXS.js → chunk-M3NSYVYR.js} +1 -1
- package/dist/{chunk-ZP5A4PAH.js → chunk-VAJMJ47E.js} +16 -10
- package/dist/{chunk-HZD727IL.js → chunk-XWUP7WHQ.js} +425 -60
- package/dist/{dist-UIVVEOGP.js → dist-RGQKIZQW.js} +7 -5
- package/dist/{exports-E3262H6I-A4GXPTSR.js → exports-FO5IMLM7-EN6H3N2A.js} +2 -2
- package/dist/index.js +2951 -460
- package/dist/{mesh-config-BAIYF4KD-QNNQOBSL.js → mesh-config-BAIYF4KD-W2RGZQ2V.js} +1 -1
- package/dist/{metadata-SJT4H53O-EXBS6PS4.js → metadata-SJT4H53O-7W2752ZT.js} +2 -2
- package/dist/{registry-YN5W7EY7-2W767O74.js → registry-YN5W7EY7-SZNXPBV5.js} +1 -1
- package/package.json +15 -8
package/dist/index.js
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
getGitStatus,
|
|
35
35
|
getIdentity,
|
|
36
36
|
getInstalledShardsWithVersions,
|
|
37
|
+
getMigrationsForVersion,
|
|
37
38
|
getPendingQuestion,
|
|
38
39
|
getPlate,
|
|
39
40
|
getPreset,
|
|
@@ -46,6 +47,7 @@ import {
|
|
|
46
47
|
getStatus,
|
|
47
48
|
getTinderboxStatus,
|
|
48
49
|
getUnfulfilledCodebases,
|
|
50
|
+
getVersionSteps,
|
|
49
51
|
hasConflictMarkers,
|
|
50
52
|
hasUncommittedChanges,
|
|
51
53
|
hasUnpushedCommits,
|
|
@@ -60,6 +62,7 @@ import {
|
|
|
60
62
|
isOwnerRepo,
|
|
61
63
|
isRebaseInProgress,
|
|
62
64
|
isValidStatus,
|
|
65
|
+
isVersionStepSealed,
|
|
63
66
|
listPlateTools,
|
|
64
67
|
listPlates,
|
|
65
68
|
listPresets,
|
|
@@ -89,6 +92,7 @@ import {
|
|
|
89
92
|
runMigrations,
|
|
90
93
|
runPlateTool,
|
|
91
94
|
runShardScript,
|
|
95
|
+
runSingleMigration,
|
|
92
96
|
scaffoldNewShard,
|
|
93
97
|
scanTinderboxFlints,
|
|
94
98
|
setCurrentRunResult,
|
|
@@ -107,7 +111,7 @@ import {
|
|
|
107
111
|
updateSession,
|
|
108
112
|
updateShards,
|
|
109
113
|
updateSourceRepository
|
|
110
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-XWUP7WHQ.js";
|
|
111
115
|
import {
|
|
112
116
|
cleanRegistryFile,
|
|
113
117
|
findFlintByName,
|
|
@@ -118,7 +122,7 @@ import {
|
|
|
118
122
|
registerFlintByPath,
|
|
119
123
|
unregisterFlint,
|
|
120
124
|
upsertFlintEntry
|
|
121
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-C66KJDI7.js";
|
|
122
126
|
import "./chunk-V7YA5RXL.js";
|
|
123
127
|
import {
|
|
124
128
|
generateSourceMeshExportMetadata,
|
|
@@ -126,14 +130,14 @@ import {
|
|
|
126
130
|
removeSourceMeshExportMetadata,
|
|
127
131
|
removeSourceRepoMetadata,
|
|
128
132
|
resolveSource
|
|
129
|
-
} from "./chunk-
|
|
133
|
+
} from "./chunk-M3NSYVYR.js";
|
|
130
134
|
import {
|
|
131
135
|
buildExport,
|
|
132
136
|
buildExportByName,
|
|
133
137
|
cleanupStaleExports,
|
|
134
138
|
scanExportEligible,
|
|
135
139
|
scanExports
|
|
136
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-VAJMJ47E.js";
|
|
137
141
|
import {
|
|
138
142
|
addExportToConfig,
|
|
139
143
|
addLatticeDeclaration,
|
|
@@ -155,7 +159,6 @@ import {
|
|
|
155
159
|
hasFlintJson,
|
|
156
160
|
hasFlintToml,
|
|
157
161
|
isLocalShard,
|
|
158
|
-
parse,
|
|
159
162
|
readFlintToml,
|
|
160
163
|
readLatticesState,
|
|
161
164
|
removeExportFromConfig,
|
|
@@ -165,26 +168,853 @@ import {
|
|
|
165
168
|
removeSourceRepository,
|
|
166
169
|
removeWorkspaceRepository,
|
|
167
170
|
resolveShardMode,
|
|
168
|
-
stringify,
|
|
169
171
|
toKebabCase,
|
|
170
172
|
writeFlintJson,
|
|
171
173
|
writeFlintToml
|
|
172
|
-
} from "./chunk-
|
|
174
|
+
} from "./chunk-CBGQBE6C.js";
|
|
173
175
|
|
|
174
176
|
// src/index.ts
|
|
175
177
|
import { Command as Command37 } from "commander";
|
|
176
|
-
import { readFileSync as
|
|
178
|
+
import { readFileSync as readFileSync10, existsSync as existsSync13, cpSync, mkdirSync as mkdirSync5, readdirSync as readdirSync7 } from "fs";
|
|
177
179
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
178
180
|
import { dirname as dirname4, join as join18 } from "path";
|
|
179
|
-
import { homedir as
|
|
181
|
+
import { homedir as homedir10 } from "os";
|
|
180
182
|
import pc42 from "picocolors";
|
|
181
183
|
|
|
182
|
-
//
|
|
184
|
+
// ../../../main/packages/cli-core/dist/index.js
|
|
183
185
|
import { homedir } from "os";
|
|
184
186
|
import { join } from "path";
|
|
185
187
|
import { mkdir, readFile as fsReadFile, writeFile as fsWriteFile } from "fs/promises";
|
|
186
188
|
import { readFileSync as fsReadFileSync } from "fs";
|
|
187
189
|
import { dirname } from "path";
|
|
190
|
+
|
|
191
|
+
// ../../../main/node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
|
|
192
|
+
function getLineColFromPtr(string, ptr) {
|
|
193
|
+
let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
|
|
194
|
+
return [lines.length, lines.pop().length + 1];
|
|
195
|
+
}
|
|
196
|
+
function makeCodeBlock(string, line, column) {
|
|
197
|
+
let lines = string.split(/\r\n|\n|\r/g);
|
|
198
|
+
let codeblock = "";
|
|
199
|
+
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
200
|
+
for (let i = line - 1; i <= line + 1; i++) {
|
|
201
|
+
let l = lines[i - 1];
|
|
202
|
+
if (!l)
|
|
203
|
+
continue;
|
|
204
|
+
codeblock += i.toString().padEnd(numberLen, " ");
|
|
205
|
+
codeblock += ": ";
|
|
206
|
+
codeblock += l;
|
|
207
|
+
codeblock += "\n";
|
|
208
|
+
if (i === line) {
|
|
209
|
+
codeblock += " ".repeat(numberLen + column + 2);
|
|
210
|
+
codeblock += "^\n";
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return codeblock;
|
|
214
|
+
}
|
|
215
|
+
var TomlError = class extends Error {
|
|
216
|
+
line;
|
|
217
|
+
column;
|
|
218
|
+
codeblock;
|
|
219
|
+
constructor(message, options) {
|
|
220
|
+
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
|
221
|
+
const codeblock = makeCodeBlock(options.toml, line, column);
|
|
222
|
+
super(`Invalid TOML document: ${message}
|
|
223
|
+
|
|
224
|
+
${codeblock}`, options);
|
|
225
|
+
this.line = line;
|
|
226
|
+
this.column = column;
|
|
227
|
+
this.codeblock = codeblock;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// ../../../main/node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/util.js
|
|
232
|
+
function isEscaped(str, ptr) {
|
|
233
|
+
let i = 0;
|
|
234
|
+
while (str[ptr - ++i] === "\\")
|
|
235
|
+
;
|
|
236
|
+
return --i && i % 2;
|
|
237
|
+
}
|
|
238
|
+
function indexOfNewline(str, start = 0, end = str.length) {
|
|
239
|
+
let idx = str.indexOf("\n", start);
|
|
240
|
+
if (str[idx - 1] === "\r")
|
|
241
|
+
idx--;
|
|
242
|
+
return idx <= end ? idx : -1;
|
|
243
|
+
}
|
|
244
|
+
function skipComment(str, ptr) {
|
|
245
|
+
for (let i = ptr; i < str.length; i++) {
|
|
246
|
+
let c = str[i];
|
|
247
|
+
if (c === "\n")
|
|
248
|
+
return i;
|
|
249
|
+
if (c === "\r" && str[i + 1] === "\n")
|
|
250
|
+
return i + 1;
|
|
251
|
+
if (c < " " && c !== " " || c === "\x7F") {
|
|
252
|
+
throw new TomlError("control characters are not allowed in comments", {
|
|
253
|
+
toml: str,
|
|
254
|
+
ptr
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return str.length;
|
|
259
|
+
}
|
|
260
|
+
function skipVoid(str, ptr, banNewLines, banComments) {
|
|
261
|
+
let c;
|
|
262
|
+
while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n"))
|
|
263
|
+
ptr++;
|
|
264
|
+
return banComments || c !== "#" ? ptr : skipVoid(str, skipComment(str, ptr), banNewLines);
|
|
265
|
+
}
|
|
266
|
+
function skipUntil(str, ptr, sep, end, banNewLines = false) {
|
|
267
|
+
if (!end) {
|
|
268
|
+
ptr = indexOfNewline(str, ptr);
|
|
269
|
+
return ptr < 0 ? str.length : ptr;
|
|
270
|
+
}
|
|
271
|
+
for (let i = ptr; i < str.length; i++) {
|
|
272
|
+
let c = str[i];
|
|
273
|
+
if (c === "#") {
|
|
274
|
+
i = indexOfNewline(str, i);
|
|
275
|
+
} else if (c === sep) {
|
|
276
|
+
return i + 1;
|
|
277
|
+
} else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i + 1] === "\n")) {
|
|
278
|
+
return i;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
throw new TomlError("cannot find end of structure", {
|
|
282
|
+
toml: str,
|
|
283
|
+
ptr
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function getStringEnd(str, seek) {
|
|
287
|
+
let first = str[seek];
|
|
288
|
+
let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2] ? str.slice(seek, seek + 3) : first;
|
|
289
|
+
seek += target.length - 1;
|
|
290
|
+
do
|
|
291
|
+
seek = str.indexOf(target, ++seek);
|
|
292
|
+
while (seek > -1 && first !== "'" && isEscaped(str, seek));
|
|
293
|
+
if (seek > -1) {
|
|
294
|
+
seek += target.length;
|
|
295
|
+
if (target.length > 1) {
|
|
296
|
+
if (str[seek] === first)
|
|
297
|
+
seek++;
|
|
298
|
+
if (str[seek] === first)
|
|
299
|
+
seek++;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return seek;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ../../../main/node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/date.js
|
|
306
|
+
var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
307
|
+
var TomlDate = class _TomlDate extends Date {
|
|
308
|
+
#hasDate = false;
|
|
309
|
+
#hasTime = false;
|
|
310
|
+
#offset = null;
|
|
311
|
+
constructor(date) {
|
|
312
|
+
let hasDate = true;
|
|
313
|
+
let hasTime = true;
|
|
314
|
+
let offset = "Z";
|
|
315
|
+
if (typeof date === "string") {
|
|
316
|
+
let match = date.match(DATE_TIME_RE);
|
|
317
|
+
if (match) {
|
|
318
|
+
if (!match[1]) {
|
|
319
|
+
hasDate = false;
|
|
320
|
+
date = `0000-01-01T${date}`;
|
|
321
|
+
}
|
|
322
|
+
hasTime = !!match[2];
|
|
323
|
+
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
324
|
+
if (match[2] && +match[2] > 23) {
|
|
325
|
+
date = "";
|
|
326
|
+
} else {
|
|
327
|
+
offset = match[3] || null;
|
|
328
|
+
date = date.toUpperCase();
|
|
329
|
+
if (!offset && hasTime)
|
|
330
|
+
date += "Z";
|
|
331
|
+
}
|
|
332
|
+
} else {
|
|
333
|
+
date = "";
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
super(date);
|
|
337
|
+
if (!isNaN(this.getTime())) {
|
|
338
|
+
this.#hasDate = hasDate;
|
|
339
|
+
this.#hasTime = hasTime;
|
|
340
|
+
this.#offset = offset;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
isDateTime() {
|
|
344
|
+
return this.#hasDate && this.#hasTime;
|
|
345
|
+
}
|
|
346
|
+
isLocal() {
|
|
347
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
348
|
+
}
|
|
349
|
+
isDate() {
|
|
350
|
+
return this.#hasDate && !this.#hasTime;
|
|
351
|
+
}
|
|
352
|
+
isTime() {
|
|
353
|
+
return this.#hasTime && !this.#hasDate;
|
|
354
|
+
}
|
|
355
|
+
isValid() {
|
|
356
|
+
return this.#hasDate || this.#hasTime;
|
|
357
|
+
}
|
|
358
|
+
toISOString() {
|
|
359
|
+
let iso = super.toISOString();
|
|
360
|
+
if (this.isDate())
|
|
361
|
+
return iso.slice(0, 10);
|
|
362
|
+
if (this.isTime())
|
|
363
|
+
return iso.slice(11, 23);
|
|
364
|
+
if (this.#offset === null)
|
|
365
|
+
return iso.slice(0, -1);
|
|
366
|
+
if (this.#offset === "Z")
|
|
367
|
+
return iso;
|
|
368
|
+
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
369
|
+
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
370
|
+
let offsetDate = new Date(this.getTime() - offset * 6e4);
|
|
371
|
+
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
372
|
+
}
|
|
373
|
+
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
374
|
+
let date = new _TomlDate(jsDate);
|
|
375
|
+
date.#offset = offset;
|
|
376
|
+
return date;
|
|
377
|
+
}
|
|
378
|
+
static wrapAsLocalDateTime(jsDate) {
|
|
379
|
+
let date = new _TomlDate(jsDate);
|
|
380
|
+
date.#offset = null;
|
|
381
|
+
return date;
|
|
382
|
+
}
|
|
383
|
+
static wrapAsLocalDate(jsDate) {
|
|
384
|
+
let date = new _TomlDate(jsDate);
|
|
385
|
+
date.#hasTime = false;
|
|
386
|
+
date.#offset = null;
|
|
387
|
+
return date;
|
|
388
|
+
}
|
|
389
|
+
static wrapAsLocalTime(jsDate) {
|
|
390
|
+
let date = new _TomlDate(jsDate);
|
|
391
|
+
date.#hasDate = false;
|
|
392
|
+
date.#offset = null;
|
|
393
|
+
return date;
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
// ../../../main/node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/primitive.js
|
|
398
|
+
var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
|
|
399
|
+
var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
|
|
400
|
+
var LEADING_ZERO = /^[+-]?0[0-9_]/;
|
|
401
|
+
var ESCAPE_REGEX = /^[0-9a-f]{2,8}$/i;
|
|
402
|
+
var ESC_MAP = {
|
|
403
|
+
b: "\b",
|
|
404
|
+
t: " ",
|
|
405
|
+
n: "\n",
|
|
406
|
+
f: "\f",
|
|
407
|
+
r: "\r",
|
|
408
|
+
e: "\x1B",
|
|
409
|
+
'"': '"',
|
|
410
|
+
"\\": "\\"
|
|
411
|
+
};
|
|
412
|
+
function parseString(str, ptr = 0, endPtr = str.length) {
|
|
413
|
+
let isLiteral = str[ptr] === "'";
|
|
414
|
+
let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1];
|
|
415
|
+
if (isMultiline) {
|
|
416
|
+
endPtr -= 2;
|
|
417
|
+
if (str[ptr += 2] === "\r")
|
|
418
|
+
ptr++;
|
|
419
|
+
if (str[ptr] === "\n")
|
|
420
|
+
ptr++;
|
|
421
|
+
}
|
|
422
|
+
let tmp = 0;
|
|
423
|
+
let isEscape;
|
|
424
|
+
let parsed = "";
|
|
425
|
+
let sliceStart = ptr;
|
|
426
|
+
while (ptr < endPtr - 1) {
|
|
427
|
+
let c = str[ptr++];
|
|
428
|
+
if (c === "\n" || c === "\r" && str[ptr] === "\n") {
|
|
429
|
+
if (!isMultiline) {
|
|
430
|
+
throw new TomlError("newlines are not allowed in strings", {
|
|
431
|
+
toml: str,
|
|
432
|
+
ptr: ptr - 1
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
} else if (c < " " && c !== " " || c === "\x7F") {
|
|
436
|
+
throw new TomlError("control characters are not allowed in strings", {
|
|
437
|
+
toml: str,
|
|
438
|
+
ptr: ptr - 1
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
if (isEscape) {
|
|
442
|
+
isEscape = false;
|
|
443
|
+
if (c === "x" || c === "u" || c === "U") {
|
|
444
|
+
let code = str.slice(ptr, ptr += c === "x" ? 2 : c === "u" ? 4 : 8);
|
|
445
|
+
if (!ESCAPE_REGEX.test(code)) {
|
|
446
|
+
throw new TomlError("invalid unicode escape", {
|
|
447
|
+
toml: str,
|
|
448
|
+
ptr: tmp
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
try {
|
|
452
|
+
parsed += String.fromCodePoint(parseInt(code, 16));
|
|
453
|
+
} catch {
|
|
454
|
+
throw new TomlError("invalid unicode escape", {
|
|
455
|
+
toml: str,
|
|
456
|
+
ptr: tmp
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
} else if (isMultiline && (c === "\n" || c === " " || c === " " || c === "\r")) {
|
|
460
|
+
ptr = skipVoid(str, ptr - 1, true);
|
|
461
|
+
if (str[ptr] !== "\n" && str[ptr] !== "\r") {
|
|
462
|
+
throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
|
|
463
|
+
toml: str,
|
|
464
|
+
ptr: tmp
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
ptr = skipVoid(str, ptr);
|
|
468
|
+
} else if (c in ESC_MAP) {
|
|
469
|
+
parsed += ESC_MAP[c];
|
|
470
|
+
} else {
|
|
471
|
+
throw new TomlError("unrecognized escape sequence", {
|
|
472
|
+
toml: str,
|
|
473
|
+
ptr: tmp
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
sliceStart = ptr;
|
|
477
|
+
} else if (!isLiteral && c === "\\") {
|
|
478
|
+
tmp = ptr - 1;
|
|
479
|
+
isEscape = true;
|
|
480
|
+
parsed += str.slice(sliceStart, tmp);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return parsed + str.slice(sliceStart, endPtr - 1);
|
|
484
|
+
}
|
|
485
|
+
function parseValue(value, toml, ptr, integersAsBigInt) {
|
|
486
|
+
if (value === "true")
|
|
487
|
+
return true;
|
|
488
|
+
if (value === "false")
|
|
489
|
+
return false;
|
|
490
|
+
if (value === "-inf")
|
|
491
|
+
return -Infinity;
|
|
492
|
+
if (value === "inf" || value === "+inf")
|
|
493
|
+
return Infinity;
|
|
494
|
+
if (value === "nan" || value === "+nan" || value === "-nan")
|
|
495
|
+
return NaN;
|
|
496
|
+
if (value === "-0")
|
|
497
|
+
return integersAsBigInt ? 0n : 0;
|
|
498
|
+
let isInt = INT_REGEX.test(value);
|
|
499
|
+
if (isInt || FLOAT_REGEX.test(value)) {
|
|
500
|
+
if (LEADING_ZERO.test(value)) {
|
|
501
|
+
throw new TomlError("leading zeroes are not allowed", {
|
|
502
|
+
toml,
|
|
503
|
+
ptr
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
value = value.replace(/_/g, "");
|
|
507
|
+
let numeric = +value;
|
|
508
|
+
if (isNaN(numeric)) {
|
|
509
|
+
throw new TomlError("invalid number", {
|
|
510
|
+
toml,
|
|
511
|
+
ptr
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
if (isInt) {
|
|
515
|
+
if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
|
|
516
|
+
throw new TomlError("integer value cannot be represented losslessly", {
|
|
517
|
+
toml,
|
|
518
|
+
ptr
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
if (isInt || integersAsBigInt === true)
|
|
522
|
+
numeric = BigInt(value);
|
|
523
|
+
}
|
|
524
|
+
return numeric;
|
|
525
|
+
}
|
|
526
|
+
const date = new TomlDate(value);
|
|
527
|
+
if (!date.isValid()) {
|
|
528
|
+
throw new TomlError("invalid value", {
|
|
529
|
+
toml,
|
|
530
|
+
ptr
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
return date;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// ../../../main/node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/extract.js
|
|
537
|
+
function sliceAndTrimEndOf(str, startPtr, endPtr) {
|
|
538
|
+
let value = str.slice(startPtr, endPtr);
|
|
539
|
+
let commentIdx = value.indexOf("#");
|
|
540
|
+
if (commentIdx > -1) {
|
|
541
|
+
skipComment(str, commentIdx);
|
|
542
|
+
value = value.slice(0, commentIdx);
|
|
543
|
+
}
|
|
544
|
+
return [value.trimEnd(), commentIdx];
|
|
545
|
+
}
|
|
546
|
+
function extractValue(str, ptr, end, depth, integersAsBigInt) {
|
|
547
|
+
if (depth === 0) {
|
|
548
|
+
throw new TomlError("document contains excessively nested structures. aborting.", {
|
|
549
|
+
toml: str,
|
|
550
|
+
ptr
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
let c = str[ptr];
|
|
554
|
+
if (c === "[" || c === "{") {
|
|
555
|
+
let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt);
|
|
556
|
+
if (end) {
|
|
557
|
+
endPtr2 = skipVoid(str, endPtr2);
|
|
558
|
+
if (str[endPtr2] === ",")
|
|
559
|
+
endPtr2++;
|
|
560
|
+
else if (str[endPtr2] !== end) {
|
|
561
|
+
throw new TomlError("expected comma or end of structure", {
|
|
562
|
+
toml: str,
|
|
563
|
+
ptr: endPtr2
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return [value, endPtr2];
|
|
568
|
+
}
|
|
569
|
+
let endPtr;
|
|
570
|
+
if (c === '"' || c === "'") {
|
|
571
|
+
endPtr = getStringEnd(str, ptr);
|
|
572
|
+
let parsed = parseString(str, ptr, endPtr);
|
|
573
|
+
if (end) {
|
|
574
|
+
endPtr = skipVoid(str, endPtr);
|
|
575
|
+
if (str[endPtr] && str[endPtr] !== "," && str[endPtr] !== end && str[endPtr] !== "\n" && str[endPtr] !== "\r") {
|
|
576
|
+
throw new TomlError("unexpected character encountered", {
|
|
577
|
+
toml: str,
|
|
578
|
+
ptr: endPtr
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
endPtr += +(str[endPtr] === ",");
|
|
582
|
+
}
|
|
583
|
+
return [parsed, endPtr];
|
|
584
|
+
}
|
|
585
|
+
endPtr = skipUntil(str, ptr, ",", end);
|
|
586
|
+
let slice = sliceAndTrimEndOf(str, ptr, endPtr - +(str[endPtr - 1] === ","));
|
|
587
|
+
if (!slice[0]) {
|
|
588
|
+
throw new TomlError("incomplete key-value declaration: no value specified", {
|
|
589
|
+
toml: str,
|
|
590
|
+
ptr
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
if (end && slice[1] > -1) {
|
|
594
|
+
endPtr = skipVoid(str, ptr + slice[1]);
|
|
595
|
+
endPtr += +(str[endPtr] === ",");
|
|
596
|
+
}
|
|
597
|
+
return [
|
|
598
|
+
parseValue(slice[0], str, ptr, integersAsBigInt),
|
|
599
|
+
endPtr
|
|
600
|
+
];
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// ../../../main/node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/struct.js
|
|
604
|
+
var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
|
|
605
|
+
function parseKey(str, ptr, end = "=") {
|
|
606
|
+
let dot = ptr - 1;
|
|
607
|
+
let parsed = [];
|
|
608
|
+
let endPtr = str.indexOf(end, ptr);
|
|
609
|
+
if (endPtr < 0) {
|
|
610
|
+
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
611
|
+
toml: str,
|
|
612
|
+
ptr
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
do {
|
|
616
|
+
let c = str[ptr = ++dot];
|
|
617
|
+
if (c !== " " && c !== " ") {
|
|
618
|
+
if (c === '"' || c === "'") {
|
|
619
|
+
if (c === str[ptr + 1] && c === str[ptr + 2]) {
|
|
620
|
+
throw new TomlError("multiline strings are not allowed in keys", {
|
|
621
|
+
toml: str,
|
|
622
|
+
ptr
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
let eos = getStringEnd(str, ptr);
|
|
626
|
+
if (eos < 0) {
|
|
627
|
+
throw new TomlError("unfinished string encountered", {
|
|
628
|
+
toml: str,
|
|
629
|
+
ptr
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
dot = str.indexOf(".", eos);
|
|
633
|
+
let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
634
|
+
let newLine = indexOfNewline(strEnd);
|
|
635
|
+
if (newLine > -1) {
|
|
636
|
+
throw new TomlError("newlines are not allowed in keys", {
|
|
637
|
+
toml: str,
|
|
638
|
+
ptr: ptr + dot + newLine
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
if (strEnd.trimStart()) {
|
|
642
|
+
throw new TomlError("found extra tokens after the string part", {
|
|
643
|
+
toml: str,
|
|
644
|
+
ptr: eos
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
if (endPtr < eos) {
|
|
648
|
+
endPtr = str.indexOf(end, eos);
|
|
649
|
+
if (endPtr < 0) {
|
|
650
|
+
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
651
|
+
toml: str,
|
|
652
|
+
ptr
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
parsed.push(parseString(str, ptr, eos));
|
|
657
|
+
} else {
|
|
658
|
+
dot = str.indexOf(".", ptr);
|
|
659
|
+
let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
660
|
+
if (!KEY_PART_RE.test(part)) {
|
|
661
|
+
throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
|
|
662
|
+
toml: str,
|
|
663
|
+
ptr
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
parsed.push(part.trimEnd());
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
} while (dot + 1 && dot < endPtr);
|
|
670
|
+
return [parsed, skipVoid(str, endPtr + 1, true, true)];
|
|
671
|
+
}
|
|
672
|
+
function parseInlineTable(str, ptr, depth, integersAsBigInt) {
|
|
673
|
+
let res = {};
|
|
674
|
+
let seen = /* @__PURE__ */ new Set();
|
|
675
|
+
let c;
|
|
676
|
+
ptr++;
|
|
677
|
+
while ((c = str[ptr++]) !== "}" && c) {
|
|
678
|
+
if (c === ",") {
|
|
679
|
+
throw new TomlError("expected value, found comma", {
|
|
680
|
+
toml: str,
|
|
681
|
+
ptr: ptr - 1
|
|
682
|
+
});
|
|
683
|
+
} else if (c === "#")
|
|
684
|
+
ptr = skipComment(str, ptr);
|
|
685
|
+
else if (c !== " " && c !== " " && c !== "\n" && c !== "\r") {
|
|
686
|
+
let k;
|
|
687
|
+
let t = res;
|
|
688
|
+
let hasOwn = false;
|
|
689
|
+
let [key, keyEndPtr] = parseKey(str, ptr - 1);
|
|
690
|
+
for (let i = 0; i < key.length; i++) {
|
|
691
|
+
if (i)
|
|
692
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
693
|
+
k = key[i];
|
|
694
|
+
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
|
|
695
|
+
throw new TomlError("trying to redefine an already defined value", {
|
|
696
|
+
toml: str,
|
|
697
|
+
ptr
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
if (!hasOwn && k === "__proto__") {
|
|
701
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
if (hasOwn) {
|
|
705
|
+
throw new TomlError("trying to redefine an already defined value", {
|
|
706
|
+
toml: str,
|
|
707
|
+
ptr
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt);
|
|
711
|
+
seen.add(value);
|
|
712
|
+
t[k] = value;
|
|
713
|
+
ptr = valueEndPtr;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
if (!c) {
|
|
717
|
+
throw new TomlError("unfinished table encountered", {
|
|
718
|
+
toml: str,
|
|
719
|
+
ptr
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
return [res, ptr];
|
|
723
|
+
}
|
|
724
|
+
function parseArray(str, ptr, depth, integersAsBigInt) {
|
|
725
|
+
let res = [];
|
|
726
|
+
let c;
|
|
727
|
+
ptr++;
|
|
728
|
+
while ((c = str[ptr++]) !== "]" && c) {
|
|
729
|
+
if (c === ",") {
|
|
730
|
+
throw new TomlError("expected value, found comma", {
|
|
731
|
+
toml: str,
|
|
732
|
+
ptr: ptr - 1
|
|
733
|
+
});
|
|
734
|
+
} else if (c === "#")
|
|
735
|
+
ptr = skipComment(str, ptr);
|
|
736
|
+
else if (c !== " " && c !== " " && c !== "\n" && c !== "\r") {
|
|
737
|
+
let e = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt);
|
|
738
|
+
res.push(e[0]);
|
|
739
|
+
ptr = e[1];
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (!c) {
|
|
743
|
+
throw new TomlError("unfinished array encountered", {
|
|
744
|
+
toml: str,
|
|
745
|
+
ptr
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
return [res, ptr];
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// ../../../main/node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/parse.js
|
|
752
|
+
function peekTable(key, table, meta, type) {
|
|
753
|
+
let t = table;
|
|
754
|
+
let m = meta;
|
|
755
|
+
let k;
|
|
756
|
+
let hasOwn = false;
|
|
757
|
+
let state;
|
|
758
|
+
for (let i = 0; i < key.length; i++) {
|
|
759
|
+
if (i) {
|
|
760
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
761
|
+
m = (state = m[k]).c;
|
|
762
|
+
if (type === 0 && (state.t === 1 || state.t === 2)) {
|
|
763
|
+
return null;
|
|
764
|
+
}
|
|
765
|
+
if (state.t === 2) {
|
|
766
|
+
let l = t.length - 1;
|
|
767
|
+
t = t[l];
|
|
768
|
+
m = m[l].c;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
k = key[i];
|
|
772
|
+
if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
if (!hasOwn) {
|
|
776
|
+
if (k === "__proto__") {
|
|
777
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
778
|
+
Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
|
|
779
|
+
}
|
|
780
|
+
m[k] = {
|
|
781
|
+
t: i < key.length - 1 && type === 2 ? 3 : type,
|
|
782
|
+
d: false,
|
|
783
|
+
i: 0,
|
|
784
|
+
c: {}
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
state = m[k];
|
|
789
|
+
if (state.t !== type && !(type === 1 && state.t === 3)) {
|
|
790
|
+
return null;
|
|
791
|
+
}
|
|
792
|
+
if (type === 2) {
|
|
793
|
+
if (!state.d) {
|
|
794
|
+
state.d = true;
|
|
795
|
+
t[k] = [];
|
|
796
|
+
}
|
|
797
|
+
t[k].push(t = {});
|
|
798
|
+
state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} };
|
|
799
|
+
}
|
|
800
|
+
if (state.d) {
|
|
801
|
+
return null;
|
|
802
|
+
}
|
|
803
|
+
state.d = true;
|
|
804
|
+
if (type === 1) {
|
|
805
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
806
|
+
} else if (type === 0 && hasOwn) {
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
return [k, t, state.c];
|
|
810
|
+
}
|
|
811
|
+
function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
812
|
+
let res = {};
|
|
813
|
+
let meta = {};
|
|
814
|
+
let tbl = res;
|
|
815
|
+
let m = meta;
|
|
816
|
+
for (let ptr = skipVoid(toml, 0); ptr < toml.length; ) {
|
|
817
|
+
if (toml[ptr] === "[") {
|
|
818
|
+
let isTableArray = toml[++ptr] === "[";
|
|
819
|
+
let k = parseKey(toml, ptr += +isTableArray, "]");
|
|
820
|
+
if (isTableArray) {
|
|
821
|
+
if (toml[k[1] - 1] !== "]") {
|
|
822
|
+
throw new TomlError("expected end of table declaration", {
|
|
823
|
+
toml,
|
|
824
|
+
ptr: k[1] - 1
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
k[1]++;
|
|
828
|
+
}
|
|
829
|
+
let p = peekTable(
|
|
830
|
+
k[0],
|
|
831
|
+
res,
|
|
832
|
+
meta,
|
|
833
|
+
isTableArray ? 2 : 1
|
|
834
|
+
/* Type.EXPLICIT */
|
|
835
|
+
);
|
|
836
|
+
if (!p) {
|
|
837
|
+
throw new TomlError("trying to redefine an already defined table or value", {
|
|
838
|
+
toml,
|
|
839
|
+
ptr
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
m = p[2];
|
|
843
|
+
tbl = p[1];
|
|
844
|
+
ptr = k[1];
|
|
845
|
+
} else {
|
|
846
|
+
let k = parseKey(toml, ptr);
|
|
847
|
+
let p = peekTable(
|
|
848
|
+
k[0],
|
|
849
|
+
tbl,
|
|
850
|
+
m,
|
|
851
|
+
0
|
|
852
|
+
/* Type.DOTTED */
|
|
853
|
+
);
|
|
854
|
+
if (!p) {
|
|
855
|
+
throw new TomlError("trying to redefine an already defined table or value", {
|
|
856
|
+
toml,
|
|
857
|
+
ptr
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
let v = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt);
|
|
861
|
+
p[1][p[0]] = v[0];
|
|
862
|
+
ptr = v[1];
|
|
863
|
+
}
|
|
864
|
+
ptr = skipVoid(toml, ptr, true);
|
|
865
|
+
if (toml[ptr] && toml[ptr] !== "\n" && toml[ptr] !== "\r") {
|
|
866
|
+
throw new TomlError("each key-value declaration must be followed by an end-of-line", {
|
|
867
|
+
toml,
|
|
868
|
+
ptr
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
ptr = skipVoid(toml, ptr);
|
|
872
|
+
}
|
|
873
|
+
return res;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// ../../../main/node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/stringify.js
|
|
877
|
+
var BARE_KEY = /^[a-z0-9-_]+$/i;
|
|
878
|
+
function extendedTypeOf(obj) {
|
|
879
|
+
let type = typeof obj;
|
|
880
|
+
if (type === "object") {
|
|
881
|
+
if (Array.isArray(obj))
|
|
882
|
+
return "array";
|
|
883
|
+
if (obj instanceof Date)
|
|
884
|
+
return "date";
|
|
885
|
+
}
|
|
886
|
+
return type;
|
|
887
|
+
}
|
|
888
|
+
function isArrayOfTables(obj) {
|
|
889
|
+
for (let i = 0; i < obj.length; i++) {
|
|
890
|
+
if (extendedTypeOf(obj[i]) !== "object")
|
|
891
|
+
return false;
|
|
892
|
+
}
|
|
893
|
+
return obj.length != 0;
|
|
894
|
+
}
|
|
895
|
+
function formatString(s) {
|
|
896
|
+
return JSON.stringify(s).replace(/\x7f/g, "\\u007f");
|
|
897
|
+
}
|
|
898
|
+
function stringifyValue(val, type, depth, numberAsFloat) {
|
|
899
|
+
if (depth === 0) {
|
|
900
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
901
|
+
}
|
|
902
|
+
if (type === "number") {
|
|
903
|
+
if (isNaN(val))
|
|
904
|
+
return "nan";
|
|
905
|
+
if (val === Infinity)
|
|
906
|
+
return "inf";
|
|
907
|
+
if (val === -Infinity)
|
|
908
|
+
return "-inf";
|
|
909
|
+
if (numberAsFloat && Number.isInteger(val))
|
|
910
|
+
return val.toFixed(1);
|
|
911
|
+
return val.toString();
|
|
912
|
+
}
|
|
913
|
+
if (type === "bigint" || type === "boolean") {
|
|
914
|
+
return val.toString();
|
|
915
|
+
}
|
|
916
|
+
if (type === "string") {
|
|
917
|
+
return formatString(val);
|
|
918
|
+
}
|
|
919
|
+
if (type === "date") {
|
|
920
|
+
if (isNaN(val.getTime())) {
|
|
921
|
+
throw new TypeError("cannot serialize invalid date");
|
|
922
|
+
}
|
|
923
|
+
return val.toISOString();
|
|
924
|
+
}
|
|
925
|
+
if (type === "object") {
|
|
926
|
+
return stringifyInlineTable(val, depth, numberAsFloat);
|
|
927
|
+
}
|
|
928
|
+
if (type === "array") {
|
|
929
|
+
return stringifyArray(val, depth, numberAsFloat);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
function stringifyInlineTable(obj, depth, numberAsFloat) {
|
|
933
|
+
let keys = Object.keys(obj);
|
|
934
|
+
if (keys.length === 0)
|
|
935
|
+
return "{}";
|
|
936
|
+
let res = "{ ";
|
|
937
|
+
for (let i = 0; i < keys.length; i++) {
|
|
938
|
+
let k = keys[i];
|
|
939
|
+
if (i)
|
|
940
|
+
res += ", ";
|
|
941
|
+
res += BARE_KEY.test(k) ? k : formatString(k);
|
|
942
|
+
res += " = ";
|
|
943
|
+
res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
|
|
944
|
+
}
|
|
945
|
+
return res + " }";
|
|
946
|
+
}
|
|
947
|
+
function stringifyArray(array, depth, numberAsFloat) {
|
|
948
|
+
if (array.length === 0)
|
|
949
|
+
return "[]";
|
|
950
|
+
let res = "[ ";
|
|
951
|
+
for (let i = 0; i < array.length; i++) {
|
|
952
|
+
if (i)
|
|
953
|
+
res += ", ";
|
|
954
|
+
if (array[i] === null || array[i] === void 0) {
|
|
955
|
+
throw new TypeError("arrays cannot contain null or undefined values");
|
|
956
|
+
}
|
|
957
|
+
res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat);
|
|
958
|
+
}
|
|
959
|
+
return res + " ]";
|
|
960
|
+
}
|
|
961
|
+
function stringifyArrayTable(array, key, depth, numberAsFloat) {
|
|
962
|
+
if (depth === 0) {
|
|
963
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
964
|
+
}
|
|
965
|
+
let res = "";
|
|
966
|
+
for (let i = 0; i < array.length; i++) {
|
|
967
|
+
res += `${res && "\n"}[[${key}]]
|
|
968
|
+
`;
|
|
969
|
+
res += stringifyTable(0, array[i], key, depth, numberAsFloat);
|
|
970
|
+
}
|
|
971
|
+
return res;
|
|
972
|
+
}
|
|
973
|
+
function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
|
|
974
|
+
if (depth === 0) {
|
|
975
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
976
|
+
}
|
|
977
|
+
let preamble = "";
|
|
978
|
+
let tables = "";
|
|
979
|
+
let keys = Object.keys(obj);
|
|
980
|
+
for (let i = 0; i < keys.length; i++) {
|
|
981
|
+
let k = keys[i];
|
|
982
|
+
if (obj[k] !== null && obj[k] !== void 0) {
|
|
983
|
+
let type = extendedTypeOf(obj[k]);
|
|
984
|
+
if (type === "symbol" || type === "function") {
|
|
985
|
+
throw new TypeError(`cannot serialize values of type '${type}'`);
|
|
986
|
+
}
|
|
987
|
+
let key = BARE_KEY.test(k) ? k : formatString(k);
|
|
988
|
+
if (type === "array" && isArrayOfTables(obj[k])) {
|
|
989
|
+
tables += (tables && "\n") + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
|
|
990
|
+
} else if (type === "object") {
|
|
991
|
+
let tblKey = prefix ? `${prefix}.${key}` : key;
|
|
992
|
+
tables += (tables && "\n") + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat);
|
|
993
|
+
} else {
|
|
994
|
+
preamble += key;
|
|
995
|
+
preamble += " = ";
|
|
996
|
+
preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
|
|
997
|
+
preamble += "\n";
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
if (tableKey && (preamble || !tables))
|
|
1002
|
+
preamble = preamble ? `[${tableKey}]
|
|
1003
|
+
${preamble}` : `[${tableKey}]`;
|
|
1004
|
+
return preamble && tables ? `${preamble}
|
|
1005
|
+
${tables}` : preamble || tables;
|
|
1006
|
+
}
|
|
1007
|
+
function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
|
|
1008
|
+
if (extendedTypeOf(obj) !== "object") {
|
|
1009
|
+
throw new TypeError("stringify can only be called with an object");
|
|
1010
|
+
}
|
|
1011
|
+
let str = stringifyTable(0, obj, "", maxDepth, numbersAsFloat);
|
|
1012
|
+
if (str[str.length - 1] !== "\n")
|
|
1013
|
+
return str + "\n";
|
|
1014
|
+
return str;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// ../../../main/packages/cli-core/dist/index.js
|
|
188
1018
|
import { createHash, randomBytes } from "crypto";
|
|
189
1019
|
import { createServer } from "http";
|
|
190
1020
|
import { existsSync, mkdirSync as mkdirSync2, readFileSync } from "fs";
|
|
@@ -193,7 +1023,7 @@ import { homedir as homedir2 } from "os";
|
|
|
193
1023
|
import { join as join2 } from "path";
|
|
194
1024
|
import pc from "picocolors";
|
|
195
1025
|
|
|
196
|
-
//
|
|
1026
|
+
// ../../../main/node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
|
|
197
1027
|
import process7 from "process";
|
|
198
1028
|
import { Buffer as Buffer2 } from "buffer";
|
|
199
1029
|
import path from "path";
|
|
@@ -202,19 +1032,19 @@ import { promisify as promisify5 } from "util";
|
|
|
202
1032
|
import childProcess from "child_process";
|
|
203
1033
|
import fs5, { constants as fsConstants2 } from "fs/promises";
|
|
204
1034
|
|
|
205
|
-
//
|
|
1035
|
+
// ../../../main/node_modules/.pnpm/wsl-utils@0.1.0/node_modules/wsl-utils/index.js
|
|
206
1036
|
import process3 from "process";
|
|
207
1037
|
import fs4, { constants as fsConstants } from "fs/promises";
|
|
208
1038
|
|
|
209
|
-
//
|
|
1039
|
+
// ../../../main/node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js
|
|
210
1040
|
import process2 from "process";
|
|
211
1041
|
import os from "os";
|
|
212
1042
|
import fs3 from "fs";
|
|
213
1043
|
|
|
214
|
-
//
|
|
1044
|
+
// ../../../main/node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
215
1045
|
import fs2 from "fs";
|
|
216
1046
|
|
|
217
|
-
//
|
|
1047
|
+
// ../../../main/node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
|
|
218
1048
|
import fs from "fs";
|
|
219
1049
|
var isDockerCached;
|
|
220
1050
|
function hasDockerEnv() {
|
|
@@ -239,7 +1069,7 @@ function isDocker() {
|
|
|
239
1069
|
return isDockerCached;
|
|
240
1070
|
}
|
|
241
1071
|
|
|
242
|
-
//
|
|
1072
|
+
// ../../../main/node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
243
1073
|
var cachedResult;
|
|
244
1074
|
var hasContainerEnv = () => {
|
|
245
1075
|
try {
|
|
@@ -256,7 +1086,7 @@ function isInsideContainer() {
|
|
|
256
1086
|
return cachedResult;
|
|
257
1087
|
}
|
|
258
1088
|
|
|
259
|
-
//
|
|
1089
|
+
// ../../../main/node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js
|
|
260
1090
|
var isWsl = () => {
|
|
261
1091
|
if (process2.platform !== "linux") {
|
|
262
1092
|
return false;
|
|
@@ -268,19 +1098,14 @@ var isWsl = () => {
|
|
|
268
1098
|
return true;
|
|
269
1099
|
}
|
|
270
1100
|
try {
|
|
271
|
-
|
|
272
|
-
return !isInsideContainer();
|
|
273
|
-
}
|
|
1101
|
+
return fs3.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
|
|
274
1102
|
} catch {
|
|
1103
|
+
return false;
|
|
275
1104
|
}
|
|
276
|
-
if (fs3.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop") || fs3.existsSync("/run/WSL")) {
|
|
277
|
-
return !isInsideContainer();
|
|
278
|
-
}
|
|
279
|
-
return false;
|
|
280
1105
|
};
|
|
281
1106
|
var is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
282
1107
|
|
|
283
|
-
//
|
|
1108
|
+
// ../../../main/node_modules/.pnpm/wsl-utils@0.1.0/node_modules/wsl-utils/index.js
|
|
284
1109
|
var wslDrivesMountPoint = /* @__PURE__ */ (() => {
|
|
285
1110
|
const defaultMountPoint = "/mnt/";
|
|
286
1111
|
let mountPoint;
|
|
@@ -319,7 +1144,7 @@ var powerShellPath = async () => {
|
|
|
319
1144
|
return `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
320
1145
|
};
|
|
321
1146
|
|
|
322
|
-
//
|
|
1147
|
+
// ../../../main/node_modules/.pnpm/define-lazy-prop@3.0.0/node_modules/define-lazy-prop/index.js
|
|
323
1148
|
function defineLazyProperty(object, propertyName, valueGetter) {
|
|
324
1149
|
const define = (value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true });
|
|
325
1150
|
Object.defineProperty(object, propertyName, {
|
|
@@ -337,12 +1162,12 @@ function defineLazyProperty(object, propertyName, valueGetter) {
|
|
|
337
1162
|
return object;
|
|
338
1163
|
}
|
|
339
1164
|
|
|
340
|
-
//
|
|
1165
|
+
// ../../../main/node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/index.js
|
|
341
1166
|
import { promisify as promisify4 } from "util";
|
|
342
1167
|
import process6 from "process";
|
|
343
1168
|
import { execFile as execFile4 } from "child_process";
|
|
344
1169
|
|
|
345
|
-
//
|
|
1170
|
+
// ../../../main/node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js
|
|
346
1171
|
import { promisify } from "util";
|
|
347
1172
|
import process4 from "process";
|
|
348
1173
|
import { execFile } from "child_process";
|
|
@@ -360,7 +1185,7 @@ async function defaultBrowserId() {
|
|
|
360
1185
|
return browserId;
|
|
361
1186
|
}
|
|
362
1187
|
|
|
363
|
-
//
|
|
1188
|
+
// ../../../main/node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js
|
|
364
1189
|
import process5 from "process";
|
|
365
1190
|
import { promisify as promisify2 } from "util";
|
|
366
1191
|
import { execFile as execFile2, execFileSync } from "child_process";
|
|
@@ -378,13 +1203,13 @@ async function runAppleScript(script, { humanReadableOutput = true, signal } = {
|
|
|
378
1203
|
return stdout.trim();
|
|
379
1204
|
}
|
|
380
1205
|
|
|
381
|
-
//
|
|
1206
|
+
// ../../../main/node_modules/.pnpm/bundle-name@4.1.0/node_modules/bundle-name/index.js
|
|
382
1207
|
async function bundleName(bundleId) {
|
|
383
1208
|
return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
|
|
384
1209
|
tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
|
|
385
1210
|
}
|
|
386
1211
|
|
|
387
|
-
//
|
|
1212
|
+
// ../../../main/node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/windows.js
|
|
388
1213
|
import { promisify as promisify3 } from "util";
|
|
389
1214
|
import { execFile as execFile3 } from "child_process";
|
|
390
1215
|
var execFileAsync3 = promisify3(execFile3);
|
|
@@ -422,14 +1247,14 @@ async function defaultBrowser(_execFileAsync = execFileAsync3) {
|
|
|
422
1247
|
throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
|
|
423
1248
|
}
|
|
424
1249
|
const { id } = match.groups;
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
return
|
|
1250
|
+
const browser = windowsBrowserProgIds[id];
|
|
1251
|
+
if (!browser) {
|
|
1252
|
+
throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
|
|
1253
|
+
}
|
|
1254
|
+
return browser;
|
|
430
1255
|
}
|
|
431
1256
|
|
|
432
|
-
//
|
|
1257
|
+
// ../../../main/node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/index.js
|
|
433
1258
|
var execFileAsync4 = promisify4(execFile4);
|
|
434
1259
|
var titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
|
|
435
1260
|
async function defaultBrowser2() {
|
|
@@ -450,7 +1275,7 @@ async function defaultBrowser2() {
|
|
|
450
1275
|
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
451
1276
|
}
|
|
452
1277
|
|
|
453
|
-
//
|
|
1278
|
+
// ../../../main/node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
|
|
454
1279
|
var execFile5 = promisify5(childProcess.execFile);
|
|
455
1280
|
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
456
1281
|
var localXdgOpenPath = path.join(__dirname, "xdg-open");
|
|
@@ -707,7 +1532,7 @@ defineLazyProperty(apps, "browser", () => "browser");
|
|
|
707
1532
|
defineLazyProperty(apps, "browserPrivate", () => "browserPrivate");
|
|
708
1533
|
var open_default = open;
|
|
709
1534
|
|
|
710
|
-
//
|
|
1535
|
+
// ../../../main/packages/cli-core/dist/index.js
|
|
711
1536
|
import { Command } from "commander";
|
|
712
1537
|
import cfonts from "cfonts";
|
|
713
1538
|
import pc3 from "picocolors";
|
|
@@ -729,9 +1554,9 @@ function normalizeRuntimeMode(input) {
|
|
|
729
1554
|
function authEnvForMode(mode) {
|
|
730
1555
|
return mode === "dev" ? "dev" : "prod";
|
|
731
1556
|
}
|
|
732
|
-
async function readConfigFile(
|
|
1557
|
+
async function readConfigFile(path5) {
|
|
733
1558
|
try {
|
|
734
|
-
const content = await fsReadFile(
|
|
1559
|
+
const content = await fsReadFile(path5, "utf-8");
|
|
735
1560
|
return parse(content);
|
|
736
1561
|
} catch (error22) {
|
|
737
1562
|
if (error22.code === "ENOENT") {
|
|
@@ -740,9 +1565,9 @@ async function readConfigFile(path4) {
|
|
|
740
1565
|
throw error22;
|
|
741
1566
|
}
|
|
742
1567
|
}
|
|
743
|
-
function readConfigFileSync(
|
|
1568
|
+
function readConfigFileSync(path5) {
|
|
744
1569
|
try {
|
|
745
|
-
const content = fsReadFileSync(
|
|
1570
|
+
const content = fsReadFileSync(path5, "utf-8");
|
|
746
1571
|
return parse(content);
|
|
747
1572
|
} catch (error22) {
|
|
748
1573
|
if (error22.code === "ENOENT") {
|
|
@@ -751,25 +1576,25 @@ function readConfigFileSync(path4) {
|
|
|
751
1576
|
throw error22;
|
|
752
1577
|
}
|
|
753
1578
|
}
|
|
754
|
-
async function writeConfigFile(
|
|
755
|
-
await mkdir(dirname(
|
|
756
|
-
await fsWriteFile(
|
|
1579
|
+
async function writeConfigFile(path5, data) {
|
|
1580
|
+
await mkdir(dirname(path5), { recursive: true });
|
|
1581
|
+
await fsWriteFile(path5, `${stringify(data)}
|
|
757
1582
|
`, "utf-8");
|
|
758
1583
|
}
|
|
759
|
-
async function setConfigField(
|
|
760
|
-
const existing = await readConfigFile(
|
|
1584
|
+
async function setConfigField(path5, key, value) {
|
|
1585
|
+
const existing = await readConfigFile(path5) ?? {};
|
|
761
1586
|
existing[key] = value;
|
|
762
|
-
await writeConfigFile(
|
|
1587
|
+
await writeConfigFile(path5, existing);
|
|
763
1588
|
}
|
|
764
|
-
async function setFeatureOverride(
|
|
765
|
-
const existing = await readConfigFile(
|
|
1589
|
+
async function setFeatureOverride(path5, featureId, enabled) {
|
|
1590
|
+
const existing = await readConfigFile(path5) ?? {};
|
|
766
1591
|
const features = existing.features && typeof existing.features === "object" && !Array.isArray(existing.features) ? { ...existing.features } : {};
|
|
767
1592
|
features[featureId] = enabled;
|
|
768
1593
|
existing.features = features;
|
|
769
|
-
await writeConfigFile(
|
|
1594
|
+
await writeConfigFile(path5, existing);
|
|
770
1595
|
}
|
|
771
|
-
async function removeFeatureOverride(
|
|
772
|
-
const existing = await readConfigFile(
|
|
1596
|
+
async function removeFeatureOverride(path5, featureId) {
|
|
1597
|
+
const existing = await readConfigFile(path5);
|
|
773
1598
|
if (!existing) return;
|
|
774
1599
|
const features = existing.features;
|
|
775
1600
|
if (!features || typeof features !== "object" || Array.isArray(features)) {
|
|
@@ -782,7 +1607,7 @@ async function removeFeatureOverride(path4, featureId) {
|
|
|
782
1607
|
} else {
|
|
783
1608
|
existing.features = next;
|
|
784
1609
|
}
|
|
785
|
-
await writeConfigFile(
|
|
1610
|
+
await writeConfigFile(path5, existing);
|
|
786
1611
|
}
|
|
787
1612
|
var CONFIG_FILENAME = "config.toml";
|
|
788
1613
|
function getConfigDir(cliname) {
|
|
@@ -991,9 +1816,9 @@ async function loadAuth(env = "prod") {
|
|
|
991
1816
|
function loadAuthSync(env = "prod") {
|
|
992
1817
|
try {
|
|
993
1818
|
ensureNuuDirSync();
|
|
994
|
-
const
|
|
995
|
-
if (!existsSync(
|
|
996
|
-
return normalizeCredentials(JSON.parse(readFileSync(
|
|
1819
|
+
const path5 = authPath(env);
|
|
1820
|
+
if (!existsSync(path5)) return null;
|
|
1821
|
+
return normalizeCredentials(JSON.parse(readFileSync(path5, "utf-8")));
|
|
997
1822
|
} catch {
|
|
998
1823
|
return null;
|
|
999
1824
|
}
|
|
@@ -1480,7 +2305,7 @@ var FEATURES = createFeatureRegistry([
|
|
|
1480
2305
|
{ id: "agent", tier: "prod", type: "command", description: "Headless agent management", requiresAuth: false },
|
|
1481
2306
|
{ id: "tinderbox", tier: "prod", type: "command", description: "Orchestrate operations across multiple Flints", requiresAuth: false },
|
|
1482
2307
|
{ id: "code", tier: "prod", type: "command", description: "Launch AI coding agents", requiresAuth: false },
|
|
1483
|
-
{ id: "orb", tier: "prod", type: "command", description: "
|
|
2308
|
+
{ id: "orb", tier: "prod", type: "command", description: "Orbh meta-harness agent management", requiresAuth: false },
|
|
1484
2309
|
{ id: "server", tier: "prod", type: "command", description: "Flint runtime server", requiresAuth: false },
|
|
1485
2310
|
{ id: "runtime", tier: "dev", type: "command", description: "Flint runtime management", requiresAuth: false },
|
|
1486
2311
|
{ id: "obsidian.push", tier: "dev", type: "function", description: "Push obsidian config changes to remote", requiresAuth: false },
|
|
@@ -1558,25 +2383,25 @@ function createProgressDisplay(label, total) {
|
|
|
1558
2383
|
import { homedir as homedir3 } from "os";
|
|
1559
2384
|
import { access } from "fs/promises";
|
|
1560
2385
|
import { createInterface } from "readline";
|
|
1561
|
-
function abbreviatePath(
|
|
2386
|
+
function abbreviatePath(path5) {
|
|
1562
2387
|
const home = homedir3();
|
|
1563
|
-
if (
|
|
1564
|
-
return
|
|
2388
|
+
if (path5.startsWith(home)) {
|
|
2389
|
+
return path5.replace(home, "~");
|
|
1565
2390
|
}
|
|
1566
|
-
return
|
|
2391
|
+
return path5;
|
|
1567
2392
|
}
|
|
1568
|
-
function expandPath(
|
|
1569
|
-
if (
|
|
1570
|
-
return
|
|
2393
|
+
function expandPath(path5) {
|
|
2394
|
+
if (path5.startsWith("~/")) {
|
|
2395
|
+
return path5.replace("~", homedir3());
|
|
1571
2396
|
}
|
|
1572
|
-
return
|
|
2397
|
+
return path5;
|
|
1573
2398
|
}
|
|
1574
2399
|
function padEnd(str, length) {
|
|
1575
2400
|
return str.padEnd(length);
|
|
1576
2401
|
}
|
|
1577
|
-
async function checkPathExists(
|
|
2402
|
+
async function checkPathExists(path5) {
|
|
1578
2403
|
try {
|
|
1579
|
-
await access(
|
|
2404
|
+
await access(path5);
|
|
1580
2405
|
return true;
|
|
1581
2406
|
} catch {
|
|
1582
2407
|
return false;
|
|
@@ -1827,12 +2652,12 @@ function resolvePath(flint, fullPath) {
|
|
|
1827
2652
|
}
|
|
1828
2653
|
function printFlint(flint, opts) {
|
|
1829
2654
|
const { nameColWidth, showStatus, fullPath, indent = " " } = opts;
|
|
1830
|
-
const
|
|
2655
|
+
const path5 = resolvePath(flint, fullPath);
|
|
1831
2656
|
const isBroken = showStatus && !flint.valid;
|
|
1832
2657
|
const tags = formatTags(flint.tags);
|
|
1833
2658
|
const nameCell = tags ? `${pc7.bold(flint.name)} ${tags}` : pc7.bold(flint.name);
|
|
1834
2659
|
const status = showStatus ? statusBadge(flint) + " " : "";
|
|
1835
|
-
const pathColor = isBroken ? pc7.red(
|
|
2660
|
+
const pathColor = isBroken ? pc7.red(path5) : pc7.dim(path5);
|
|
1836
2661
|
console.log(`${indent}${pad(nameCell, nameColWidth)}${status}${pathColor}`);
|
|
1837
2662
|
if (flint.description) {
|
|
1838
2663
|
console.log(`${indent} ${pc7.dim(truncate(flint.description, 65))}`);
|
|
@@ -1840,10 +2665,10 @@ function printFlint(flint, opts) {
|
|
|
1840
2665
|
}
|
|
1841
2666
|
function printGroupRow(flint, opts) {
|
|
1842
2667
|
const { nameColWidth, showStatus, fullPath } = opts;
|
|
1843
|
-
const
|
|
2668
|
+
const path5 = resolvePath(flint, fullPath);
|
|
1844
2669
|
const isBroken = showStatus && !flint.valid;
|
|
1845
2670
|
const status = showStatus ? statusBadge(flint) + " " : "";
|
|
1846
|
-
const pathColor = isBroken ? pc7.red(
|
|
2671
|
+
const pathColor = isBroken ? pc7.red(path5) : pc7.dim(path5);
|
|
1847
2672
|
console.log(` ${pad(flint.name, nameColWidth)}${status}${pathColor}`);
|
|
1848
2673
|
}
|
|
1849
2674
|
function measureNameCol(flints) {
|
|
@@ -3637,9 +4462,23 @@ var syncCommand = new Command6("sync").description("Sync shards from flint.toml"
|
|
|
3637
4462
|
if (result.migrations.pending.length > 0) {
|
|
3638
4463
|
console.log(pc9.bold("Migrations:"));
|
|
3639
4464
|
console.log(pc9.yellow(` ${result.migrations.pending.length} migration(s) available:`));
|
|
4465
|
+
const migrationsByVersion = /* @__PURE__ */ new Map();
|
|
3640
4466
|
for (const m of result.migrations.pending) {
|
|
3641
|
-
|
|
3642
|
-
|
|
4467
|
+
const existing = migrationsByVersion.get(m.to) || [];
|
|
4468
|
+
existing.push(m);
|
|
4469
|
+
migrationsByVersion.set(m.to, existing);
|
|
4470
|
+
}
|
|
4471
|
+
for (const [version, items] of migrationsByVersion) {
|
|
4472
|
+
const sealed = isVersionStepSealed(version);
|
|
4473
|
+
if (!sealed) {
|
|
4474
|
+
console.log(` ${pc9.yellow("\u2192")} ${pc9.bold(version)} ${pc9.yellow("(unsealed \u2014 version will not advance)")}`);
|
|
4475
|
+
} else {
|
|
4476
|
+
console.log(` ${pc9.yellow("\u2192")} ${pc9.bold(version)}`);
|
|
4477
|
+
}
|
|
4478
|
+
for (const m of items) {
|
|
4479
|
+
console.log(` ${m.name} ${pc9.dim(`(${m.from} \u2192 ${m.to})`)}`);
|
|
4480
|
+
console.log(` ${pc9.dim(m.description)}`);
|
|
4481
|
+
}
|
|
3643
4482
|
}
|
|
3644
4483
|
console.log(pc9.dim(`
|
|
3645
4484
|
Run \`flint migrate\` to apply.
|
|
@@ -4120,9 +4959,9 @@ var REQUIRED_DIRS = [
|
|
|
4120
4959
|
"Workspace/Bench",
|
|
4121
4960
|
".flint"
|
|
4122
4961
|
];
|
|
4123
|
-
async function exists(
|
|
4962
|
+
async function exists(path5) {
|
|
4124
4963
|
try {
|
|
4125
|
-
await access2(
|
|
4964
|
+
await access2(path5);
|
|
4126
4965
|
return true;
|
|
4127
4966
|
} catch {
|
|
4128
4967
|
return false;
|
|
@@ -4347,9 +5186,9 @@ import pc12 from "picocolors";
|
|
|
4347
5186
|
import { readFile as readFile4, stat } from "fs/promises";
|
|
4348
5187
|
import { join as join7, basename as basename2 } from "path";
|
|
4349
5188
|
import { createInterface as createInterface2 } from "readline";
|
|
4350
|
-
async function exists2(
|
|
5189
|
+
async function exists2(path5) {
|
|
4351
5190
|
try {
|
|
4352
|
-
await stat(
|
|
5191
|
+
await stat(path5);
|
|
4353
5192
|
return true;
|
|
4354
5193
|
} catch {
|
|
4355
5194
|
return false;
|
|
@@ -4643,17 +5482,17 @@ import { resolve as resolve2 } from "path";
|
|
|
4643
5482
|
import { platform as platform3 } from "os";
|
|
4644
5483
|
import pc13 from "picocolors";
|
|
4645
5484
|
var execAsync2 = promisify7(exec2);
|
|
4646
|
-
async function openInObsidian(
|
|
5485
|
+
async function openInObsidian(path5) {
|
|
4647
5486
|
const os2 = platform3();
|
|
4648
5487
|
if (os2 === "darwin") {
|
|
4649
|
-
await execAsync2(`open -a "Obsidian" "${
|
|
5488
|
+
await execAsync2(`open -a "Obsidian" "${path5}"`);
|
|
4650
5489
|
} else if (os2 === "win32") {
|
|
4651
|
-
await execAsync2(`start "" "Obsidian" "${
|
|
5490
|
+
await execAsync2(`start "" "Obsidian" "${path5}"`);
|
|
4652
5491
|
} else {
|
|
4653
5492
|
try {
|
|
4654
|
-
await execAsync2(`obsidian "${
|
|
5493
|
+
await execAsync2(`obsidian "${path5}"`);
|
|
4655
5494
|
} catch {
|
|
4656
|
-
await execAsync2(`xdg-open "${
|
|
5495
|
+
await execAsync2(`xdg-open "${path5}"`);
|
|
4657
5496
|
}
|
|
4658
5497
|
}
|
|
4659
5498
|
}
|
|
@@ -4745,7 +5584,7 @@ if (!configJson) {
|
|
|
4745
5584
|
}
|
|
4746
5585
|
|
|
4747
5586
|
const { sessionPath, flintPath, prompt, claudeArgs, sessionId, runId } = JSON.parse(configJson);
|
|
4748
|
-
const dashboardUrl = 'http://localhost:
|
|
5587
|
+
const dashboardUrl = 'http://localhost:13040/agent#session-' + sessionId;
|
|
4749
5588
|
|
|
4750
5589
|
function readSession() {
|
|
4751
5590
|
try {
|
|
@@ -6100,7 +6939,7 @@ plateCommand.command("create").description("Scaffold a new Plate").argument("<na
|
|
|
6100
6939
|
const flintPath = await resolveFlintPath2(options.path);
|
|
6101
6940
|
const plate = await createPlate(flintPath, name, { shard: options.shard });
|
|
6102
6941
|
console.log(pc22.green(`
|
|
6103
|
-
Created Plate ${pc22.bold(plate.manifest.
|
|
6942
|
+
Created Plate ${pc22.bold(plate.manifest.title)}`));
|
|
6104
6943
|
console.log(` Name: ${pc22.cyan(plate.manifest.name)}`);
|
|
6105
6944
|
console.log(` Path: ${pc22.dim(plate.path)}`);
|
|
6106
6945
|
if (plate.manifest.shard) {
|
|
@@ -6130,15 +6969,15 @@ plateCommand.command("list").description("List installed Plates").option("-p, --
|
|
|
6130
6969
|
return;
|
|
6131
6970
|
}
|
|
6132
6971
|
const nameWidth = Math.max(4, ...plates.map((plate) => plate.manifest.name.length)) + 2;
|
|
6133
|
-
const
|
|
6972
|
+
const titleWidth = Math.max(5, ...plates.map((plate) => plate.manifest.title.length)) + 2;
|
|
6134
6973
|
const shardWidth = Math.max(5, ...plates.map((plate) => (plate.manifest.shard ?? "\u2014").length)) + 2;
|
|
6135
6974
|
console.log();
|
|
6136
6975
|
console.log(
|
|
6137
|
-
` ${pad2(pc22.bold("Name"), nameWidth)}${pad2(pc22.bold("
|
|
6976
|
+
` ${pad2(pc22.bold("Name"), nameWidth)}${pad2(pc22.bold("Title"), titleWidth)}${pad2(pc22.bold("Shard"), shardWidth)}${pc22.bold("Built")}`
|
|
6138
6977
|
);
|
|
6139
6978
|
for (const plate of plates) {
|
|
6140
6979
|
console.log(
|
|
6141
|
-
` ${pad2(plate.manifest.name, nameWidth)}${pad2(plate.manifest.
|
|
6980
|
+
` ${pad2(plate.manifest.name, nameWidth)}${pad2(plate.manifest.title, titleWidth)}${pad2(plate.manifest.shard ?? "\u2014", shardWidth)}${plate.built ? pc22.green("yes") : pc22.yellow("no")}`
|
|
6142
6981
|
);
|
|
6143
6982
|
}
|
|
6144
6983
|
console.log();
|
|
@@ -6158,7 +6997,7 @@ repoCommand.command("add").description("Add a plate from a git repo").argument("
|
|
|
6158
6997
|
getPlateDeclaration,
|
|
6159
6998
|
nameFormats,
|
|
6160
6999
|
updateGitignore: updateGitignore2
|
|
6161
|
-
} = await import("./dist-
|
|
7000
|
+
} = await import("./dist-RGQKIZQW.js");
|
|
6162
7001
|
const { proper, slug } = nameFormats(name);
|
|
6163
7002
|
const existing = await getPlateDeclaration(flintPath, slug);
|
|
6164
7003
|
if (existing) {
|
|
@@ -6170,7 +7009,7 @@ repoCommand.command("add").description("Add a plate from a git repo").argument("
|
|
|
6170
7009
|
Cloning ${url}...`));
|
|
6171
7010
|
await clonePlateFromRepo(flintPath, slug, url, platePath);
|
|
6172
7011
|
await addPlateDeclaration(flintPath, slug, platePath, { title: proper });
|
|
6173
|
-
const { setPlateRepo } = await import("./dist-
|
|
7012
|
+
const { setPlateRepo } = await import("./dist-RGQKIZQW.js");
|
|
6174
7013
|
await setPlateRepo(flintPath, slug, url);
|
|
6175
7014
|
await updateGitignore2(flintPath);
|
|
6176
7015
|
console.log(pc22.green(`
|
|
@@ -6188,8 +7027,8 @@ Added plate: ${pc22.bold(proper)}`));
|
|
|
6188
7027
|
repoCommand.command("remove").description("Remove a repo-sourced plate").argument("<name>", "Plate declaration name or slug").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, options) => {
|
|
6189
7028
|
try {
|
|
6190
7029
|
const flintPath = await resolveFlintPath2(options.path);
|
|
6191
|
-
const { removePlateDeclaration, updateGitignore: updateGitignore2 } = await import("./dist-
|
|
6192
|
-
const { rm: rm5, stat:
|
|
7030
|
+
const { removePlateDeclaration, updateGitignore: updateGitignore2 } = await import("./dist-RGQKIZQW.js");
|
|
7031
|
+
const { rm: rm5, stat: stat9 } = await import("fs/promises");
|
|
6193
7032
|
const { join: join19 } = await import("path");
|
|
6194
7033
|
const plate = await getPlate(flintPath, name);
|
|
6195
7034
|
if (!plate) {
|
|
@@ -6197,14 +7036,14 @@ repoCommand.command("remove").description("Remove a repo-sourced plate").argumen
|
|
|
6197
7036
|
process.exit(1);
|
|
6198
7037
|
}
|
|
6199
7038
|
try {
|
|
6200
|
-
await
|
|
7039
|
+
await stat9(plate.path);
|
|
6201
7040
|
await rm5(plate.path, { recursive: true, force: true });
|
|
6202
7041
|
} catch {
|
|
6203
7042
|
}
|
|
6204
7043
|
await removePlateDeclaration(flintPath, plate.declarationName);
|
|
6205
7044
|
await updateGitignore2(flintPath);
|
|
6206
7045
|
console.log(pc22.green(`
|
|
6207
|
-
Removed plate: ${pc22.bold(plate.manifest.
|
|
7046
|
+
Removed plate: ${pc22.bold(plate.manifest.title)}
|
|
6208
7047
|
`));
|
|
6209
7048
|
} catch (err) {
|
|
6210
7049
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -6213,10 +7052,65 @@ Removed plate: ${pc22.bold(plate.manifest.display)}
|
|
|
6213
7052
|
}
|
|
6214
7053
|
});
|
|
6215
7054
|
plateCommand.addCommand(repoCommand);
|
|
7055
|
+
plateCommand.command("install").description("Install a Plate from a git repo URL").argument("<url>", "Git repo URL to clone").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (url, options) => {
|
|
7056
|
+
try {
|
|
7057
|
+
const flintPath = await resolveFlintPath2(options.path);
|
|
7058
|
+
const {
|
|
7059
|
+
addPlateDeclaration,
|
|
7060
|
+
clonePlateFromRepo,
|
|
7061
|
+
readPlateManifest,
|
|
7062
|
+
setPlateRepo,
|
|
7063
|
+
updateGitignore: updateGitignore2
|
|
7064
|
+
} = await import("./dist-RGQKIZQW.js");
|
|
7065
|
+
const { join: join19 } = await import("path");
|
|
7066
|
+
const { mkdtemp: mkdtemp2, rm: rm5, rename: rename2 } = await import("fs/promises");
|
|
7067
|
+
const { tmpdir: tmpdir2 } = await import("os");
|
|
7068
|
+
const tmpDir = await mkdtemp2(join19(tmpdir2(), "flint-plate-"));
|
|
7069
|
+
console.log(pc22.dim(`
|
|
7070
|
+
Cloning ${url}...`));
|
|
7071
|
+
try {
|
|
7072
|
+
await clonePlateFromRepo(flintPath, "temp", url, tmpDir);
|
|
7073
|
+
} catch {
|
|
7074
|
+
const { execSync: execSync6 } = await import("child_process");
|
|
7075
|
+
execSync6(`git clone --depth 1 "${url}" "${tmpDir}"`, { timeout: 6e4, stdio: "ignore" });
|
|
7076
|
+
await rm5(join19(tmpDir, ".git"), { recursive: true, force: true }).catch(() => {
|
|
7077
|
+
});
|
|
7078
|
+
}
|
|
7079
|
+
const manifest = await readPlateManifest(tmpDir);
|
|
7080
|
+
const slug = manifest.name;
|
|
7081
|
+
const title = manifest.title;
|
|
7082
|
+
const existing = await getPlate(flintPath, slug);
|
|
7083
|
+
if (existing) {
|
|
7084
|
+
await rm5(tmpDir, { recursive: true, force: true });
|
|
7085
|
+
console.error(pc22.red(`Error: Plate "${slug}" already exists.`));
|
|
7086
|
+
process.exit(1);
|
|
7087
|
+
}
|
|
7088
|
+
const { mkdir: mkdir8 } = await import("fs/promises");
|
|
7089
|
+
const platePath = `Plates/${title}`;
|
|
7090
|
+
const absolutePlatePath = join19(flintPath, platePath);
|
|
7091
|
+
await mkdir8(join19(flintPath, "Plates"), { recursive: true });
|
|
7092
|
+
await rename2(tmpDir, absolutePlatePath);
|
|
7093
|
+
await addPlateDeclaration(flintPath, slug, platePath, { title });
|
|
7094
|
+
await setPlateRepo(flintPath, slug, url);
|
|
7095
|
+
await updateGitignore2(flintPath);
|
|
7096
|
+
console.log(pc22.green(`
|
|
7097
|
+
Installed plate: ${pc22.bold(title)}`));
|
|
7098
|
+
console.log(` Slug: ${pc22.cyan(slug)}`);
|
|
7099
|
+
console.log(` Title: ${title}`);
|
|
7100
|
+
console.log(` Path: ${pc22.dim(platePath)}`);
|
|
7101
|
+
console.log(` URL: ${pc22.dim(url)}`);
|
|
7102
|
+
console.log(pc22.dim("\nThe server will auto-build this plate on next startup."));
|
|
7103
|
+
console.log();
|
|
7104
|
+
} catch (err) {
|
|
7105
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7106
|
+
console.error(pc22.red(`Error: ${message}`));
|
|
7107
|
+
process.exit(1);
|
|
7108
|
+
}
|
|
7109
|
+
});
|
|
6216
7110
|
plateCommand.command("push").description("Initialize a plate as a git repo, set remote, and push").argument("<name>", "Plate name").argument("<url>", "Git remote URL").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, url, options) => {
|
|
6217
7111
|
try {
|
|
6218
7112
|
const flintPath = await resolveFlintPath2(options.path);
|
|
6219
|
-
const { setPlateRepo } = await import("./dist-
|
|
7113
|
+
const { setPlateRepo } = await import("./dist-RGQKIZQW.js");
|
|
6220
7114
|
console.log(pc22.dim(`
|
|
6221
7115
|
Pushing plate "${name}"...`));
|
|
6222
7116
|
const result = await initPlateRepo(flintPath, name, url);
|
|
@@ -6242,7 +7136,7 @@ Pushing plate "${name}"...`));
|
|
|
6242
7136
|
plateCommand.command("sync").description("Sync plates that have a repo configured").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
6243
7137
|
try {
|
|
6244
7138
|
const flintPath = await resolveFlintPath2(options.path);
|
|
6245
|
-
const { getPlateDeclarations, syncPlateRepos } = await import("./dist-
|
|
7139
|
+
const { getPlateDeclarations, syncPlateRepos } = await import("./dist-RGQKIZQW.js");
|
|
6246
7140
|
const declarations = await getPlateDeclarations(flintPath);
|
|
6247
7141
|
const hasRepos = Object.values(declarations).some((d) => d.repo);
|
|
6248
7142
|
if (!hasRepos) {
|
|
@@ -6261,6 +7155,8 @@ plateCommand.command("sync").description("Sync plates that have a repo configure
|
|
|
6261
7155
|
console.log(` ${pc22.green("+")} ${pr.name} ${pc22.dim("(cloned)")}`);
|
|
6262
7156
|
} else if (pr.status === "updated") {
|
|
6263
7157
|
console.log(` ${pc22.green("\u2713")} ${pr.name} ${pc22.dim("(updated)")}`);
|
|
7158
|
+
} else if (pr.status === "skipped") {
|
|
7159
|
+
console.log(` ${pc22.dim("\u25CB")} ${pr.name} ${pc22.dim("(exists, skipped)")}`);
|
|
6264
7160
|
} else if (pr.status === "error") {
|
|
6265
7161
|
console.log(` ${pc22.red("\u2717")} ${pr.name} \u2014 ${pr.error}`);
|
|
6266
7162
|
}
|
|
@@ -6281,7 +7177,7 @@ plateCommand.command("info").description("Show Plate details").argument("<name>"
|
|
|
6281
7177
|
}
|
|
6282
7178
|
console.log();
|
|
6283
7179
|
console.log(`${pc22.bold("Name:")} ${pc22.cyan(plate.manifest.name)}`);
|
|
6284
|
-
console.log(`${pc22.bold("
|
|
7180
|
+
console.log(`${pc22.bold("Title:")} ${plate.manifest.title}`);
|
|
6285
7181
|
console.log(`${pc22.bold("Version:")} ${plate.manifest.version ?? "0.1.0"}`);
|
|
6286
7182
|
console.log(`${pc22.bold("Shard:")} ${plate.manifest.shard ?? "\u2014"}`);
|
|
6287
7183
|
console.log(`${pc22.bold("Entry:")} ${plate.manifest.entry}`);
|
|
@@ -6316,7 +7212,7 @@ plateCommand.command("dev").description("Start a Plate dev server").argument("<n
|
|
|
6316
7212
|
if (!plate) {
|
|
6317
7213
|
throw new Error(`Plate not found: ${name}`);
|
|
6318
7214
|
}
|
|
6319
|
-
console.log(pc22.dim(`Starting dev server for ${plate.manifest.
|
|
7215
|
+
console.log(pc22.dim(`Starting dev server for ${plate.manifest.title}...
|
|
6320
7216
|
`));
|
|
6321
7217
|
const child = spawnPlateDevServer(flintPath, plate);
|
|
6322
7218
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
@@ -6516,9 +7412,9 @@ repoCommand2.addCommand(
|
|
|
6516
7412
|
}
|
|
6517
7413
|
})
|
|
6518
7414
|
);
|
|
6519
|
-
async function fileExists(
|
|
7415
|
+
async function fileExists(path5) {
|
|
6520
7416
|
try {
|
|
6521
|
-
await stat3(
|
|
7417
|
+
await stat3(path5);
|
|
6522
7418
|
return true;
|
|
6523
7419
|
} catch {
|
|
6524
7420
|
return false;
|
|
@@ -7136,11 +8032,33 @@ var latticeCommand = new Command21("lattice").description("Manage lattice connec
|
|
|
7136
8032
|
|
|
7137
8033
|
// src/commands/server.ts
|
|
7138
8034
|
import { Command as Command22 } from "commander";
|
|
8035
|
+
import { createRequire } from "module";
|
|
8036
|
+
import path3 from "path";
|
|
8037
|
+
import { spawn as spawn4 } from "child_process";
|
|
8038
|
+
import { stat as stat4 } from "fs/promises";
|
|
7139
8039
|
import pc25 from "picocolors";
|
|
8040
|
+
var SERVER_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
8041
|
+
var FLINT_SERVER_PACKAGE = "@nuucognition/flint-server";
|
|
8042
|
+
var SHUTDOWN_HEADER_NAME = "x-flint-shutdown";
|
|
8043
|
+
var SHUTDOWN_HEADER_VALUE = "true";
|
|
8044
|
+
async function importFlintServer() {
|
|
8045
|
+
const require2 = createRequire(import.meta.url);
|
|
8046
|
+
try {
|
|
8047
|
+
const resolved = require2.resolve(FLINT_SERVER_PACKAGE);
|
|
8048
|
+
return await import(resolved);
|
|
8049
|
+
} catch (error3) {
|
|
8050
|
+
if (error3 instanceof Error && (error3.code === "ERR_MODULE_NOT_FOUND" || error3.code === "MODULE_NOT_FOUND" || error3.message.includes(`Cannot find package '${FLINT_SERVER_PACKAGE}'`) || error3.message.includes(`Cannot find module '${FLINT_SERVER_PACKAGE}'`))) {
|
|
8051
|
+
console.error(pc25.red(`Error: ${FLINT_SERVER_PACKAGE} is not installed.`));
|
|
8052
|
+
console.log(pc25.dim("The server module is in development. Install it locally to use this command."));
|
|
8053
|
+
process.exit(1);
|
|
8054
|
+
}
|
|
8055
|
+
throw error3;
|
|
8056
|
+
}
|
|
8057
|
+
}
|
|
7140
8058
|
var serverCommand = new Command22("server").description("Manage the local Flint server");
|
|
7141
|
-
serverCommand.command("start").description("Start the Flint server").option("-p, --port <port>", "Port to bind").option("--path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
8059
|
+
serverCommand.command("start").description("Start the Flint server").option("-p, --port <port>", "Port to bind").option("--path <dir>", "Path to flint (default: auto-detect)").option("--steel-url <url>", "Paired Steel host URL for cascading shutdown").action(async (options) => {
|
|
7142
8060
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
7143
|
-
let configPort =
|
|
8061
|
+
let configPort = 13040;
|
|
7144
8062
|
if (flintPath) {
|
|
7145
8063
|
try {
|
|
7146
8064
|
const config = await readFlintToml(flintPath);
|
|
@@ -7149,15 +8067,9 @@ serverCommand.command("start").description("Start the Flint server").option("-p,
|
|
|
7149
8067
|
}
|
|
7150
8068
|
}
|
|
7151
8069
|
const port = options.port ? Number(options.port) : configPort;
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
} catch {
|
|
7156
|
-
console.error(pc25.red("Error: @nuucognition/flint-server is not installed."));
|
|
7157
|
-
console.log(pc25.dim("The server module is in development. Install it locally to use this command."));
|
|
7158
|
-
process.exit(1);
|
|
7159
|
-
}
|
|
7160
|
-
const server = await startFlintServer({ port, flintPath });
|
|
8070
|
+
const steelUrl = typeof options.steelUrl === "string" ? options.steelUrl.trim() : void 0;
|
|
8071
|
+
const { startFlintServer } = await importFlintServer();
|
|
8072
|
+
const server = await startFlintServer({ port, flintPath, steelUrl });
|
|
7161
8073
|
console.log(`
|
|
7162
8074
|
${pc25.bold(pc25.blue("Flint Server"))}`);
|
|
7163
8075
|
console.log(` URL: ${pc25.cyan(server.address)}`);
|
|
@@ -7169,14 +8081,76 @@ ${pc25.bold(pc25.blue("Flint Server"))}`);
|
|
|
7169
8081
|
console.log(`
|
|
7170
8082
|
${pc25.dim('Session endpoint: POST /sessions { "prompt": "..." }')}
|
|
7171
8083
|
`);
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
8084
|
+
let shutdownPromise = null;
|
|
8085
|
+
let shutdownTimer = null;
|
|
8086
|
+
const handleShutdown = (signal) => {
|
|
8087
|
+
if (shutdownPromise) {
|
|
8088
|
+
console.error(pc25.red(`Received ${signal} during shutdown. Forcing Flint server exit.`));
|
|
8089
|
+
process.exit(1);
|
|
8090
|
+
}
|
|
8091
|
+
console.log(pc25.dim(`Received ${signal}. Shutting down Flint server...`));
|
|
8092
|
+
shutdownTimer = setTimeout(() => {
|
|
8093
|
+
console.error(pc25.red(`Flint server did not shut down within ${SERVER_SHUTDOWN_TIMEOUT_MS}ms. Forcing exit.`));
|
|
8094
|
+
process.exit(1);
|
|
8095
|
+
}, SERVER_SHUTDOWN_TIMEOUT_MS);
|
|
8096
|
+
shutdownTimer.unref?.();
|
|
8097
|
+
shutdownPromise = (async () => {
|
|
8098
|
+
try {
|
|
8099
|
+
await server.close();
|
|
8100
|
+
process.exit(0);
|
|
8101
|
+
} catch (error3) {
|
|
8102
|
+
const message = error3 instanceof Error ? error3.message : String(error3);
|
|
8103
|
+
console.error(pc25.red(`Flint server shutdown failed: ${message}`));
|
|
8104
|
+
process.exit(1);
|
|
8105
|
+
} finally {
|
|
8106
|
+
if (shutdownTimer) {
|
|
8107
|
+
clearTimeout(shutdownTimer);
|
|
8108
|
+
shutdownTimer = null;
|
|
8109
|
+
}
|
|
8110
|
+
}
|
|
8111
|
+
})();
|
|
7175
8112
|
};
|
|
7176
|
-
process.on("SIGINT", handleShutdown);
|
|
7177
|
-
process.on("SIGTERM", handleShutdown);
|
|
8113
|
+
process.on("SIGINT", () => handleShutdown("SIGINT"));
|
|
8114
|
+
process.on("SIGTERM", () => handleShutdown("SIGTERM"));
|
|
8115
|
+
});
|
|
8116
|
+
serverCommand.command("dev").description("Start the server in dev mode with auto-reload on source changes").option("-p, --port <port>", "Port to bind").option("--path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
8117
|
+
const require2 = createRequire(import.meta.url);
|
|
8118
|
+
let serverPkgDir;
|
|
8119
|
+
try {
|
|
8120
|
+
const serverPkgJson = require2.resolve(`${FLINT_SERVER_PACKAGE}/package.json`);
|
|
8121
|
+
serverPkgDir = path3.dirname(serverPkgJson);
|
|
8122
|
+
} catch {
|
|
8123
|
+
console.error(pc25.red("Error: flint-server package not found."));
|
|
8124
|
+
process.exit(1);
|
|
8125
|
+
}
|
|
8126
|
+
const devEntry = path3.join(serverPkgDir, "src", "dev.ts");
|
|
8127
|
+
try {
|
|
8128
|
+
await stat4(devEntry);
|
|
8129
|
+
} catch {
|
|
8130
|
+
console.error(pc25.red("Dev mode requires the server source directory."));
|
|
8131
|
+
console.log(pc25.dim("This command only works from the monorepo development environment."));
|
|
8132
|
+
process.exit(1);
|
|
8133
|
+
}
|
|
8134
|
+
const env = { ...process.env };
|
|
8135
|
+
if (options.port) env.FLINT_SERVER_PORT = String(options.port);
|
|
8136
|
+
if (options.path) {
|
|
8137
|
+
env.FLINT_PATH = options.path;
|
|
8138
|
+
} else {
|
|
8139
|
+
const detected = await findFlintRoot(process.cwd());
|
|
8140
|
+
if (detected) env.FLINT_PATH = detected;
|
|
8141
|
+
}
|
|
8142
|
+
console.log(`${pc25.bold(pc25.blue("Flint Server"))} ${pc25.dim("dev mode \u2014 watching for changes")}
|
|
8143
|
+
`);
|
|
8144
|
+
const child = spawn4("tsx", ["watch", devEntry], {
|
|
8145
|
+
env,
|
|
8146
|
+
stdio: "inherit",
|
|
8147
|
+
cwd: serverPkgDir
|
|
8148
|
+
});
|
|
8149
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
8150
|
+
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
|
8151
|
+
process.on("SIGINT", () => child.kill("SIGINT"));
|
|
7178
8152
|
});
|
|
7179
|
-
serverCommand.command("status").description("Check server status").option("--server <url>", "Server URL", "http://127.0.0.1:
|
|
8153
|
+
serverCommand.command("status").description("Check server status").option("--server <url>", "Server URL", "http://127.0.0.1:13040").action(async (options) => {
|
|
7180
8154
|
const serverUrl = options.server;
|
|
7181
8155
|
try {
|
|
7182
8156
|
const response = await fetch(`${serverUrl}/health`);
|
|
@@ -7223,10 +8197,15 @@ ${pc25.bold("Sessions")}`);
|
|
|
7223
8197
|
console.log(pc25.yellow("Server not running. Start with: flint server start"));
|
|
7224
8198
|
}
|
|
7225
8199
|
});
|
|
7226
|
-
serverCommand.command("stop").description("Stop the Flint server").option("--server <url>", "Server URL", "http://127.0.0.1:
|
|
8200
|
+
serverCommand.command("stop").description("Stop the Flint server").option("--server <url>", "Server URL", "http://127.0.0.1:13040").action(async (options) => {
|
|
7227
8201
|
const serverUrl = options.server;
|
|
7228
8202
|
try {
|
|
7229
|
-
const response = await fetch(`${serverUrl}/shutdown`, {
|
|
8203
|
+
const response = await fetch(`${serverUrl}/shutdown`, {
|
|
8204
|
+
method: "POST",
|
|
8205
|
+
headers: {
|
|
8206
|
+
[SHUTDOWN_HEADER_NAME]: SHUTDOWN_HEADER_VALUE
|
|
8207
|
+
}
|
|
8208
|
+
});
|
|
7230
8209
|
if (!response.ok) {
|
|
7231
8210
|
console.log(pc25.yellow("Server not running."));
|
|
7232
8211
|
return;
|
|
@@ -7236,15 +8215,38 @@ serverCommand.command("stop").description("Stop the Flint server").option("--ser
|
|
|
7236
8215
|
console.log(pc25.yellow("Server not running."));
|
|
7237
8216
|
}
|
|
7238
8217
|
});
|
|
8218
|
+
serverCommand.command("list").description("List all running Flint servers from the shared registry").action(async () => {
|
|
8219
|
+
const { readAndValidateRegistry, getServerRegistryPath } = await importFlintServer();
|
|
8220
|
+
const servers = await readAndValidateRegistry();
|
|
8221
|
+
console.log(pc25.dim(`Registry: ${getServerRegistryPath()}
|
|
8222
|
+
`));
|
|
8223
|
+
if (servers.length === 0) {
|
|
8224
|
+
console.log(pc25.yellow("No running Flint servers found."));
|
|
8225
|
+
return;
|
|
8226
|
+
}
|
|
8227
|
+
console.log(`${pc25.bold("Running Flint Servers")} (${servers.length})
|
|
8228
|
+
`);
|
|
8229
|
+
for (const server of servers) {
|
|
8230
|
+
console.log(` ${pc25.bold(pc25.blue(server.name))}`);
|
|
8231
|
+
console.log(` URL: ${pc25.cyan(server.url)}`);
|
|
8232
|
+
console.log(` Path: ${pc25.dim(server.flintPath)}`);
|
|
8233
|
+
console.log(` PID: ${server.pid}`);
|
|
8234
|
+
console.log(` Since: ${pc25.dim(server.started)}`);
|
|
8235
|
+
if (server.flintId) {
|
|
8236
|
+
console.log(` ID: ${pc25.dim(server.flintId)}`);
|
|
8237
|
+
}
|
|
8238
|
+
console.log();
|
|
8239
|
+
}
|
|
8240
|
+
});
|
|
7239
8241
|
|
|
7240
8242
|
// src/commands/runtime.ts
|
|
7241
8243
|
import { Command as Command23 } from "commander";
|
|
7242
8244
|
import pc26 from "picocolors";
|
|
7243
|
-
import
|
|
8245
|
+
import path4 from "path";
|
|
7244
8246
|
var runtimeCommand = new Command23("runtime").description("Manage Flint runtimes");
|
|
7245
|
-
runtimeCommand.command("start [flintPath]").description("Start runtime for a Flint").option("--server <url>", "Server URL", "http://127.0.0.1:
|
|
8247
|
+
runtimeCommand.command("start [flintPath]").description("Start runtime for a Flint").option("--server <url>", "Server URL", "http://127.0.0.1:13040").action(async (flintPath, options) => {
|
|
7246
8248
|
const serverUrl = options.server;
|
|
7247
|
-
const resolvedPath = flintPath ?
|
|
8249
|
+
const resolvedPath = flintPath ? path4.resolve(flintPath) : await findFlintRoot(process.cwd());
|
|
7248
8250
|
if (!resolvedPath) {
|
|
7249
8251
|
console.error(pc26.red("Error: Not inside a Flint workspace. Provide a path or cd into one."));
|
|
7250
8252
|
process.exit(1);
|
|
@@ -7271,12 +8273,12 @@ ${pc26.bold("Runtime Started")}`);
|
|
|
7271
8273
|
process.exit(1);
|
|
7272
8274
|
}
|
|
7273
8275
|
});
|
|
7274
|
-
runtimeCommand.command("stop [runtimeId]").description("Stop a running runtime").option("--path <dir>", "Path to Flint").option("--server <url>", "Server URL", "http://127.0.0.1:
|
|
8276
|
+
runtimeCommand.command("stop [runtimeId]").description("Stop a running runtime").option("--path <dir>", "Path to Flint").option("--server <url>", "Server URL", "http://127.0.0.1:13040").action(async (runtimeId, options) => {
|
|
7275
8277
|
const serverUrl = options.server;
|
|
7276
8278
|
let id = runtimeId;
|
|
7277
8279
|
try {
|
|
7278
8280
|
if (!id) {
|
|
7279
|
-
const lookupPath = options.path ?
|
|
8281
|
+
const lookupPath = options.path ? path4.resolve(options.path) : await findFlintRoot(process.cwd());
|
|
7280
8282
|
if (!lookupPath) {
|
|
7281
8283
|
console.error(pc26.red("Error: Provide a runtime ID or Flint path."));
|
|
7282
8284
|
process.exit(1);
|
|
@@ -7307,7 +8309,7 @@ runtimeCommand.command("stop [runtimeId]").description("Stop a running runtime")
|
|
|
7307
8309
|
process.exit(1);
|
|
7308
8310
|
}
|
|
7309
8311
|
});
|
|
7310
|
-
runtimeCommand.command("list").description("List active runtimes").option("--server <url>", "Server URL", "http://127.0.0.1:
|
|
8312
|
+
runtimeCommand.command("list").description("List active runtimes").option("--server <url>", "Server URL", "http://127.0.0.1:13040").action(async (options) => {
|
|
7311
8313
|
const serverUrl = options.server;
|
|
7312
8314
|
try {
|
|
7313
8315
|
const response = await fetch(`${serverUrl}/runtimes`);
|
|
@@ -7337,34 +8339,38 @@ ${pc26.bold("Active Runtimes")}
|
|
|
7337
8339
|
// src/commands/code.ts
|
|
7338
8340
|
import { Command as Command24 } from "commander";
|
|
7339
8341
|
import pc29 from "picocolors";
|
|
7340
|
-
import { spawn as
|
|
8342
|
+
import { spawn as spawn5, execSync as execSync3 } from "child_process";
|
|
7341
8343
|
import { createInterface as createInterface5 } from "readline";
|
|
7342
|
-
import { existsSync as
|
|
8344
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync2 } from "fs";
|
|
7343
8345
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
7344
8346
|
import { join as join13 } from "path";
|
|
7345
8347
|
|
|
7346
|
-
// src/commands/export-session.ts
|
|
7347
|
-
import { writeFile as writeFile3, mkdir as mkdir5, stat as stat4, readFile as readFile6 } from "fs/promises";
|
|
7348
|
-
import { join as join11 } from "path";
|
|
7349
|
-
import { homedir as homedir6 } from "os";
|
|
7350
|
-
import pc27 from "picocolors";
|
|
7351
|
-
|
|
7352
8348
|
// ../../packages/orbh/dist/index.js
|
|
7353
8349
|
import { randomUUID } from "crypto";
|
|
7354
8350
|
import { mkdirSync, readdirSync, readFileSync as readFileSync2, renameSync, writeFileSync } from "fs";
|
|
7355
8351
|
import { existsSync as existsSync5 } from "fs";
|
|
7356
8352
|
import { join as join10 } from "path";
|
|
7357
8353
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
7358
|
-
import {
|
|
7359
|
-
import { existsSync as existsSync32 } from "fs";
|
|
8354
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22 } from "fs";
|
|
8355
|
+
import { closeSync, existsSync as existsSync32, openSync, readSync, statSync, unwatchFile, watch, watchFile } from "fs";
|
|
8356
|
+
import { existsSync as existsSync42, readFileSync as readFileSync3, unwatchFile as unwatchFile2, watch as watch2, watchFile as watchFile2 } from "fs";
|
|
8357
|
+
import { existsSync as existsSync52 } from "fs";
|
|
7360
8358
|
import { join as join22 } from "path";
|
|
7361
8359
|
import { homedir as homedir5 } from "os";
|
|
7362
8360
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
7363
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
7364
|
-
import { existsSync as
|
|
8361
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
|
|
8362
|
+
import { existsSync as existsSync6 } from "fs";
|
|
7365
8363
|
import { join as join32 } from "path";
|
|
7366
8364
|
import { homedir as homedir22 } from "os";
|
|
7367
8365
|
import { spawnSync as spawnSync22 } from "child_process";
|
|
8366
|
+
import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
8367
|
+
import { spawnSync as spawnSync32 } from "child_process";
|
|
8368
|
+
import { basename as basename4, join as join42 } from "path";
|
|
8369
|
+
import { homedir as homedir32 } from "os";
|
|
8370
|
+
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync3 } from "fs";
|
|
8371
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
8372
|
+
import { homedir as homedir42 } from "os";
|
|
8373
|
+
import { basename as basename22, join as join52 } from "path";
|
|
7368
8374
|
var RUN_TRANSITIONS = {
|
|
7369
8375
|
running: ["completed", "failed", "cancelled", "suspended"],
|
|
7370
8376
|
completed: [],
|
|
@@ -7424,26 +8430,84 @@ function addRequest(session, request) {
|
|
|
7424
8430
|
function answerRequest(session, requestId, response) {
|
|
7425
8431
|
const terminalRunStatuses = ["completed", "failed", "cancelled"];
|
|
7426
8432
|
const currentRun = getCurrentRun2(session);
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
8433
|
+
for (let i = session.runs.length - 1; i >= 0; i--) {
|
|
8434
|
+
const run = session.runs[i];
|
|
8435
|
+
if (!run) {
|
|
8436
|
+
continue;
|
|
8437
|
+
}
|
|
8438
|
+
const request = run.requests.find((entry) => entry.id === requestId);
|
|
8439
|
+
if (!request) {
|
|
8440
|
+
continue;
|
|
8441
|
+
}
|
|
8442
|
+
if (request.type !== "deferred") {
|
|
8443
|
+
if (run !== currentRun || terminalRunStatuses.includes(run.status)) {
|
|
8444
|
+
return void 0;
|
|
8445
|
+
}
|
|
8446
|
+
}
|
|
8447
|
+
request.response = response ?? null;
|
|
8448
|
+
request.answered = (/* @__PURE__ */ new Date()).toISOString();
|
|
8449
|
+
return request;
|
|
7436
8450
|
}
|
|
7437
|
-
|
|
7438
|
-
request.answered = (/* @__PURE__ */ new Date()).toISOString();
|
|
7439
|
-
return request;
|
|
8451
|
+
return void 0;
|
|
7440
8452
|
}
|
|
7441
8453
|
function getPendingRequest(session) {
|
|
8454
|
+
for (let i = session.runs.length - 1; i >= 0; i--) {
|
|
8455
|
+
const run = session.runs[i];
|
|
8456
|
+
if (!run) {
|
|
8457
|
+
continue;
|
|
8458
|
+
}
|
|
8459
|
+
for (let j = run.requests.length - 1; j >= 0; j--) {
|
|
8460
|
+
const request = run.requests[j];
|
|
8461
|
+
if (request && request.answered === null) {
|
|
8462
|
+
return request;
|
|
8463
|
+
}
|
|
8464
|
+
}
|
|
8465
|
+
}
|
|
8466
|
+
return void 0;
|
|
8467
|
+
}
|
|
8468
|
+
var TERMINAL_SESSION_STATUSES = ["finished", "failed", "cancelled"];
|
|
8469
|
+
function isTerminalSessionStatus(status) {
|
|
8470
|
+
return TERMINAL_SESSION_STATUSES.includes(status);
|
|
8471
|
+
}
|
|
8472
|
+
function isProcessAlive(pid) {
|
|
8473
|
+
try {
|
|
8474
|
+
process.kill(pid, 0);
|
|
8475
|
+
return true;
|
|
8476
|
+
} catch {
|
|
8477
|
+
return false;
|
|
8478
|
+
}
|
|
8479
|
+
}
|
|
8480
|
+
function healSession(session) {
|
|
8481
|
+
if (isTerminalSessionStatus(session.status)) return false;
|
|
7442
8482
|
const currentRun = getCurrentRun2(session);
|
|
7443
8483
|
if (!currentRun) {
|
|
7444
|
-
|
|
8484
|
+
session.status = "failed";
|
|
8485
|
+
return true;
|
|
8486
|
+
}
|
|
8487
|
+
if (currentRun.status !== "running") return false;
|
|
8488
|
+
const alive = currentRun.pid ? isProcessAlive(currentRun.pid) : false;
|
|
8489
|
+
if (alive) return false;
|
|
8490
|
+
const hasResult = currentRun.result !== null;
|
|
8491
|
+
updateCurrentRun2(session, {
|
|
8492
|
+
status: hasResult ? "completed" : "suspended",
|
|
8493
|
+
ended: currentRun.ended ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
8494
|
+
});
|
|
8495
|
+
const pending = getPendingRequest(session);
|
|
8496
|
+
if (pending?.type === "deferred") {
|
|
8497
|
+
session.status = "deferred";
|
|
8498
|
+
} else {
|
|
8499
|
+
session.status = "finished";
|
|
7445
8500
|
}
|
|
7446
|
-
return
|
|
8501
|
+
return true;
|
|
8502
|
+
}
|
|
8503
|
+
function isRecord(value) {
|
|
8504
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8505
|
+
}
|
|
8506
|
+
function normalizeSession(session) {
|
|
8507
|
+
return {
|
|
8508
|
+
...session,
|
|
8509
|
+
metadata: isRecord(session.metadata) ? session.metadata : {}
|
|
8510
|
+
};
|
|
7447
8511
|
}
|
|
7448
8512
|
function ensureSessionsDir(sessionsDir) {
|
|
7449
8513
|
if (!existsSync5(sessionsDir)) {
|
|
@@ -7463,6 +8527,7 @@ function createSession2(sessionsDir, runtime2, prompt6, options) {
|
|
|
7463
8527
|
prompt: prompt6,
|
|
7464
8528
|
title: options?.title ?? "",
|
|
7465
8529
|
description: options?.description ?? "",
|
|
8530
|
+
metadata: options?.metadata ?? {},
|
|
7466
8531
|
continues: options?.continues ?? null,
|
|
7467
8532
|
started: timestamp,
|
|
7468
8533
|
updated: timestamp,
|
|
@@ -7478,7 +8543,7 @@ function readSession2(sessionsDir, sessionId) {
|
|
|
7478
8543
|
return null;
|
|
7479
8544
|
}
|
|
7480
8545
|
try {
|
|
7481
|
-
return JSON.parse(readFileSync2(sessionPath, "utf-8"));
|
|
8546
|
+
return normalizeSession(JSON.parse(readFileSync2(sessionPath, "utf-8")));
|
|
7482
8547
|
} catch {
|
|
7483
8548
|
return null;
|
|
7484
8549
|
}
|
|
@@ -7486,7 +8551,7 @@ function readSession2(sessionsDir, sessionId) {
|
|
|
7486
8551
|
function writeSession(sessionsDir, session) {
|
|
7487
8552
|
ensureSessionsDir(sessionsDir);
|
|
7488
8553
|
const nextSession = {
|
|
7489
|
-
...session,
|
|
8554
|
+
...normalizeSession(session),
|
|
7490
8555
|
updated: (/* @__PURE__ */ new Date()).toISOString()
|
|
7491
8556
|
};
|
|
7492
8557
|
const sessionPath = getSessionPath2(sessionsDir, nextSession.id);
|
|
@@ -7501,12 +8566,12 @@ function updateSession2(sessionsDir, sessionId, update) {
|
|
|
7501
8566
|
return null;
|
|
7502
8567
|
}
|
|
7503
8568
|
const { id: _ignoredId, started: _ignoredStarted, ...safeUpdate } = update;
|
|
7504
|
-
const nextSession = {
|
|
8569
|
+
const nextSession = normalizeSession({
|
|
7505
8570
|
...session,
|
|
7506
8571
|
...safeUpdate,
|
|
7507
8572
|
id: session.id,
|
|
7508
8573
|
started: session.started
|
|
7509
|
-
};
|
|
8574
|
+
});
|
|
7510
8575
|
writeSession(sessionsDir, nextSession);
|
|
7511
8576
|
return nextSession;
|
|
7512
8577
|
}
|
|
@@ -7751,7 +8816,7 @@ function formatSubagent(agentId, agentType, prompt6, transcript, opts, depth) {
|
|
|
7751
8816
|
function formatTurnContent(content, opts, depth) {
|
|
7752
8817
|
switch (content.type) {
|
|
7753
8818
|
case "text":
|
|
7754
|
-
return [content.text, ""];
|
|
8819
|
+
return ["````", content.text, "````", ""];
|
|
7755
8820
|
case "thinking": {
|
|
7756
8821
|
if (!opts.includeThinking) return [];
|
|
7757
8822
|
if (content.encrypted) {
|
|
@@ -7831,11 +8896,11 @@ function createClaudeMapperContext(toolIdMap = /* @__PURE__ */ new Map()) {
|
|
|
7831
8896
|
activeSubagents: /* @__PURE__ */ new Map()
|
|
7832
8897
|
};
|
|
7833
8898
|
}
|
|
7834
|
-
function
|
|
8899
|
+
function isRecord2(value) {
|
|
7835
8900
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7836
8901
|
}
|
|
7837
8902
|
function isClaudeContentBlockArray(value) {
|
|
7838
|
-
return Array.isArray(value) && value.every((item) =>
|
|
8903
|
+
return Array.isArray(value) && value.every((item) => isRecord2(item));
|
|
7839
8904
|
}
|
|
7840
8905
|
function stringifyContent(value) {
|
|
7841
8906
|
if (typeof value === "string") {
|
|
@@ -7844,7 +8909,7 @@ function stringifyContent(value) {
|
|
|
7844
8909
|
if (Array.isArray(value)) {
|
|
7845
8910
|
return value.map((item) => stringifyContent(item)).join("\n");
|
|
7846
8911
|
}
|
|
7847
|
-
if (
|
|
8912
|
+
if (isRecord2(value)) {
|
|
7848
8913
|
return JSON.stringify(value);
|
|
7849
8914
|
}
|
|
7850
8915
|
if (value === null || value === void 0) {
|
|
@@ -7856,7 +8921,7 @@ function toTimestamp(entry) {
|
|
|
7856
8921
|
return typeof entry.timestamp === "string" ? entry.timestamp : (/* @__PURE__ */ new Date(0)).toISOString();
|
|
7857
8922
|
}
|
|
7858
8923
|
function mapUserEntry(entry, context) {
|
|
7859
|
-
const message =
|
|
8924
|
+
const message = isRecord2(entry.message) ? entry.message : null;
|
|
7860
8925
|
if (!message) {
|
|
7861
8926
|
return [];
|
|
7862
8927
|
}
|
|
@@ -7917,7 +8982,7 @@ function mapUserEntry(entry, context) {
|
|
|
7917
8982
|
return mappedEntries;
|
|
7918
8983
|
}
|
|
7919
8984
|
function mapAssistantEntry(entry, context) {
|
|
7920
|
-
const message =
|
|
8985
|
+
const message = isRecord2(entry.message) ? entry.message : null;
|
|
7921
8986
|
if (!message || !isClaudeContentBlockArray(message.content)) {
|
|
7922
8987
|
return [];
|
|
7923
8988
|
}
|
|
@@ -7947,12 +9012,12 @@ function mapAssistantEntry(entry, context) {
|
|
|
7947
9012
|
type: "tool-call",
|
|
7948
9013
|
id: block.id,
|
|
7949
9014
|
tool: block.name,
|
|
7950
|
-
input:
|
|
9015
|
+
input: isRecord2(block.input) ? block.input : {},
|
|
7951
9016
|
timestamp
|
|
7952
9017
|
});
|
|
7953
9018
|
}
|
|
7954
9019
|
}
|
|
7955
|
-
const usage =
|
|
9020
|
+
const usage = isRecord2(message.usage) ? message.usage : null;
|
|
7956
9021
|
if (usage) {
|
|
7957
9022
|
const usageEntry = {
|
|
7958
9023
|
type: "usage",
|
|
@@ -7968,7 +9033,7 @@ function mapAssistantEntry(entry, context) {
|
|
|
7968
9033
|
return mappedEntries;
|
|
7969
9034
|
}
|
|
7970
9035
|
function mapAgentProgressEntry(entry, context) {
|
|
7971
|
-
const data =
|
|
9036
|
+
const data = isRecord2(entry.data) ? entry.data : null;
|
|
7972
9037
|
if (!data || typeof data.agentId !== "string") {
|
|
7973
9038
|
return [];
|
|
7974
9039
|
}
|
|
@@ -7977,7 +9042,7 @@ function mapAgentProgressEntry(entry, context) {
|
|
|
7977
9042
|
const parentToolCallId = typeof entry.parentToolUseID === "string" ? entry.parentToolUseID : "";
|
|
7978
9043
|
const prompt6 = typeof data.prompt === "string" ? data.prompt : void 0;
|
|
7979
9044
|
const agentType = typeof data.agentType === "string" ? data.agentType : void 0;
|
|
7980
|
-
const nestedMessage =
|
|
9045
|
+
const nestedMessage = isRecord2(data.message) ? data.message : null;
|
|
7981
9046
|
const mappedEntries = [];
|
|
7982
9047
|
if (!context.activeSubagents.has(agentId)) {
|
|
7983
9048
|
context.activeSubagents.set(agentId, {
|
|
@@ -8010,7 +9075,7 @@ function mapAgentProgressEntry(entry, context) {
|
|
|
8010
9075
|
return mappedEntries;
|
|
8011
9076
|
}
|
|
8012
9077
|
function mapProgressEntry(entry, context) {
|
|
8013
|
-
const data =
|
|
9078
|
+
const data = isRecord2(entry.data) ? entry.data : null;
|
|
8014
9079
|
if (!data || typeof data.type !== "string") {
|
|
8015
9080
|
return [];
|
|
8016
9081
|
}
|
|
@@ -8057,7 +9122,7 @@ function buildClaudeToolIdMap(entries) {
|
|
|
8057
9122
|
if (entry.type !== "assistant") {
|
|
8058
9123
|
continue;
|
|
8059
9124
|
}
|
|
8060
|
-
const message =
|
|
9125
|
+
const message = isRecord2(entry.message) ? entry.message : null;
|
|
8061
9126
|
if (!message || !isClaudeContentBlockArray(message.content)) {
|
|
8062
9127
|
continue;
|
|
8063
9128
|
}
|
|
@@ -8100,17 +9165,17 @@ function createCodexMapperContext(toolIdMap = /* @__PURE__ */ new Map()) {
|
|
|
8100
9165
|
activeSubagents: /* @__PURE__ */ new Map()
|
|
8101
9166
|
};
|
|
8102
9167
|
}
|
|
8103
|
-
function
|
|
9168
|
+
function isRecord3(value) {
|
|
8104
9169
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8105
9170
|
}
|
|
8106
|
-
function
|
|
9171
|
+
function stringifyValue2(value) {
|
|
8107
9172
|
if (typeof value === "string") {
|
|
8108
9173
|
return value;
|
|
8109
9174
|
}
|
|
8110
9175
|
if (Array.isArray(value)) {
|
|
8111
|
-
return value.map((item) =>
|
|
9176
|
+
return value.map((item) => stringifyValue2(item)).join("\n");
|
|
8112
9177
|
}
|
|
8113
|
-
if (
|
|
9178
|
+
if (isRecord3(value)) {
|
|
8114
9179
|
return JSON.stringify(value);
|
|
8115
9180
|
}
|
|
8116
9181
|
if (value === null || value === void 0) {
|
|
@@ -8119,13 +9184,13 @@ function stringifyValue(value) {
|
|
|
8119
9184
|
return String(value);
|
|
8120
9185
|
}
|
|
8121
9186
|
function parseObjectInput(value) {
|
|
8122
|
-
if (
|
|
9187
|
+
if (isRecord3(value)) {
|
|
8123
9188
|
return value;
|
|
8124
9189
|
}
|
|
8125
9190
|
if (typeof value === "string") {
|
|
8126
9191
|
try {
|
|
8127
9192
|
const parsed = JSON.parse(value);
|
|
8128
|
-
return
|
|
9193
|
+
return isRecord3(parsed) ? parsed : {};
|
|
8129
9194
|
} catch {
|
|
8130
9195
|
return {};
|
|
8131
9196
|
}
|
|
@@ -8137,7 +9202,7 @@ function extractTextContent(content) {
|
|
|
8137
9202
|
return "";
|
|
8138
9203
|
}
|
|
8139
9204
|
return content.map((block) => {
|
|
8140
|
-
if (!
|
|
9205
|
+
if (!isRecord3(block)) {
|
|
8141
9206
|
return "";
|
|
8142
9207
|
}
|
|
8143
9208
|
const text = block.text;
|
|
@@ -8149,7 +9214,7 @@ function extractReasoningSummary(summary) {
|
|
|
8149
9214
|
return "";
|
|
8150
9215
|
}
|
|
8151
9216
|
return summary.map((item) => {
|
|
8152
|
-
if (!
|
|
9217
|
+
if (!isRecord3(item)) {
|
|
8153
9218
|
return "";
|
|
8154
9219
|
}
|
|
8155
9220
|
const text = item.text;
|
|
@@ -8157,14 +9222,14 @@ function extractReasoningSummary(summary) {
|
|
|
8157
9222
|
}).filter((text) => text.length > 0).join("\n");
|
|
8158
9223
|
}
|
|
8159
9224
|
function inferToolResultError(output) {
|
|
8160
|
-
if (
|
|
8161
|
-
const metadata =
|
|
9225
|
+
if (isRecord3(output)) {
|
|
9226
|
+
const metadata = isRecord3(output.metadata) ? output.metadata : null;
|
|
8162
9227
|
return metadata?.exit_code !== void 0 && typeof metadata.exit_code === "number" && metadata.exit_code !== 0;
|
|
8163
9228
|
}
|
|
8164
9229
|
if (typeof output === "string") {
|
|
8165
9230
|
try {
|
|
8166
9231
|
const parsed = JSON.parse(output);
|
|
8167
|
-
if (
|
|
9232
|
+
if (isRecord3(parsed)) {
|
|
8168
9233
|
return inferToolResultError(parsed);
|
|
8169
9234
|
}
|
|
8170
9235
|
} catch {
|
|
@@ -8222,14 +9287,14 @@ function mapFunctionCallOutputPayload(payload, timestamp, context) {
|
|
|
8222
9287
|
type: "tool-result",
|
|
8223
9288
|
id: payload.call_id,
|
|
8224
9289
|
tool: context.toolIdMap.get(payload.call_id) ?? "unknown",
|
|
8225
|
-
output:
|
|
9290
|
+
output: stringifyValue2(output),
|
|
8226
9291
|
error: inferToolResultError(output),
|
|
8227
9292
|
timestamp
|
|
8228
9293
|
}
|
|
8229
9294
|
];
|
|
8230
9295
|
}
|
|
8231
9296
|
function mapWebSearchCallPayload(payload, timestamp) {
|
|
8232
|
-
const action =
|
|
9297
|
+
const action = isRecord3(payload.action) ? payload.action : null;
|
|
8233
9298
|
const query = typeof action?.query === "string" ? action.query : "web_search";
|
|
8234
9299
|
return [
|
|
8235
9300
|
{
|
|
@@ -8253,8 +9318,8 @@ function getSubagentId(payload) {
|
|
|
8253
9318
|
}
|
|
8254
9319
|
}
|
|
8255
9320
|
const nestedIds = [
|
|
8256
|
-
|
|
8257
|
-
|
|
9321
|
+
isRecord3(payload.new_thread_id) ? payload.new_thread_id.id : void 0,
|
|
9322
|
+
isRecord3(payload.receiver_thread_id) ? payload.receiver_thread_id.id : void 0
|
|
8258
9323
|
];
|
|
8259
9324
|
for (const nestedId of nestedIds) {
|
|
8260
9325
|
if (typeof nestedId === "string" && nestedId.length > 0) {
|
|
@@ -8266,8 +9331,8 @@ function getSubagentId(payload) {
|
|
|
8266
9331
|
function mapEventPayload(payload, timestamp, context) {
|
|
8267
9332
|
switch (payload.type) {
|
|
8268
9333
|
case "token_count": {
|
|
8269
|
-
const info =
|
|
8270
|
-
const usage =
|
|
9334
|
+
const info = isRecord3(payload.info) ? payload.info : null;
|
|
9335
|
+
const usage = isRecord3(info?.total_token_usage) ? info?.total_token_usage : isRecord3(info?.last_token_usage) ? info?.last_token_usage : null;
|
|
8271
9336
|
if (!usage) {
|
|
8272
9337
|
return [];
|
|
8273
9338
|
}
|
|
@@ -8309,7 +9374,7 @@ function mapEventPayload(payload, timestamp, context) {
|
|
|
8309
9374
|
if (!agentId) {
|
|
8310
9375
|
return [];
|
|
8311
9376
|
}
|
|
8312
|
-
const nestedText = typeof payload.prompt === "string" && payload.prompt.length > 0 ? payload.prompt :
|
|
9377
|
+
const nestedText = typeof payload.prompt === "string" && payload.prompt.length > 0 ? payload.prompt : stringifyValue2(payload.status);
|
|
8313
9378
|
return [
|
|
8314
9379
|
{
|
|
8315
9380
|
type: "subagent-entry",
|
|
@@ -8367,7 +9432,7 @@ function buildCodexToolIdMap(entries) {
|
|
|
8367
9432
|
if (entry.type !== "response_item") {
|
|
8368
9433
|
continue;
|
|
8369
9434
|
}
|
|
8370
|
-
const payload =
|
|
9435
|
+
const payload = isRecord3(entry.payload) ? entry.payload : null;
|
|
8371
9436
|
if (!payload) {
|
|
8372
9437
|
continue;
|
|
8373
9438
|
}
|
|
@@ -8380,7 +9445,7 @@ function buildCodexToolIdMap(entries) {
|
|
|
8380
9445
|
function mapCodexEntry(entry, context) {
|
|
8381
9446
|
const timestamp = typeof entry.timestamp === "string" ? entry.timestamp : (/* @__PURE__ */ new Date(0)).toISOString();
|
|
8382
9447
|
if (entry.type === "turn_context") {
|
|
8383
|
-
const payload2 =
|
|
9448
|
+
const payload2 = isRecord3(entry.payload) ? entry.payload : null;
|
|
8384
9449
|
context.currentModel = typeof payload2?.model === "string" ? payload2.model : context.currentModel;
|
|
8385
9450
|
return [];
|
|
8386
9451
|
}
|
|
@@ -8388,7 +9453,7 @@ function mapCodexEntry(entry, context) {
|
|
|
8388
9453
|
return [];
|
|
8389
9454
|
}
|
|
8390
9455
|
if (entry.type === "compacted") {
|
|
8391
|
-
const payload2 =
|
|
9456
|
+
const payload2 = isRecord3(entry.payload) ? entry.payload : null;
|
|
8392
9457
|
return [
|
|
8393
9458
|
{
|
|
8394
9459
|
type: "compaction",
|
|
@@ -8397,7 +9462,7 @@ function mapCodexEntry(entry, context) {
|
|
|
8397
9462
|
}
|
|
8398
9463
|
];
|
|
8399
9464
|
}
|
|
8400
|
-
const payload =
|
|
9465
|
+
const payload = isRecord3(entry.payload) ? entry.payload : null;
|
|
8401
9466
|
if (!payload || typeof payload.type !== "string") {
|
|
8402
9467
|
return [];
|
|
8403
9468
|
}
|
|
@@ -8437,129 +9502,750 @@ function parseCodexTranscript(content) {
|
|
|
8437
9502
|
const context = createCodexMapperContext(buildCodexToolIdMap(rawEntries));
|
|
8438
9503
|
return rawEntries.flatMap((entry) => mapCodexEntry(entry, context));
|
|
8439
9504
|
}
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
9505
|
+
function createDroidMapperContext(options) {
|
|
9506
|
+
return {
|
|
9507
|
+
toolIdMap: options?.toolIdMap ?? /* @__PURE__ */ new Map(),
|
|
9508
|
+
transcriptPath: options?.transcriptPath
|
|
9509
|
+
};
|
|
9510
|
+
}
|
|
9511
|
+
function isRecord4(value) {
|
|
9512
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9513
|
+
}
|
|
9514
|
+
function isDroidContentBlockArray(value) {
|
|
9515
|
+
return Array.isArray(value) && value.every((item) => isRecord4(item));
|
|
9516
|
+
}
|
|
9517
|
+
function stringifyContent2(value) {
|
|
9518
|
+
if (typeof value === "string") {
|
|
9519
|
+
return value;
|
|
8449
9520
|
}
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
mapperState;
|
|
8453
|
-
options;
|
|
8454
|
-
byteOffset = 0;
|
|
8455
|
-
buffer = "";
|
|
8456
|
-
watcher = null;
|
|
8457
|
-
debounceTimer = null;
|
|
8458
|
-
started = false;
|
|
8459
|
-
usingPolling = false;
|
|
8460
|
-
onEntries(handler) {
|
|
8461
|
-
this.handlers.add(handler);
|
|
9521
|
+
if (Array.isArray(value)) {
|
|
9522
|
+
return value.map((item) => stringifyContent2(item)).join("\n");
|
|
8462
9523
|
}
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
return;
|
|
8466
|
-
}
|
|
8467
|
-
this.started = true;
|
|
8468
|
-
if (existsSync22(this.transcriptPath)) {
|
|
8469
|
-
this.readNewContent();
|
|
8470
|
-
}
|
|
8471
|
-
this.installWatcher();
|
|
9524
|
+
if (isRecord4(value)) {
|
|
9525
|
+
return JSON.stringify(value);
|
|
8472
9526
|
}
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
9527
|
+
if (value === null || value === void 0) {
|
|
9528
|
+
return "";
|
|
9529
|
+
}
|
|
9530
|
+
return String(value);
|
|
9531
|
+
}
|
|
9532
|
+
function toTimestamp2(entry) {
|
|
9533
|
+
return typeof entry.timestamp === "string" ? entry.timestamp : (/* @__PURE__ */ new Date(0)).toISOString();
|
|
9534
|
+
}
|
|
9535
|
+
function buildDroidToolIdMap(entries) {
|
|
9536
|
+
const toolIdMap = /* @__PURE__ */ new Map();
|
|
9537
|
+
for (const entry of entries) {
|
|
9538
|
+
if (entry.type !== "message") {
|
|
9539
|
+
continue;
|
|
8478
9540
|
}
|
|
8479
|
-
|
|
8480
|
-
|
|
8481
|
-
|
|
9541
|
+
const message = isRecord4(entry.message) ? entry.message : null;
|
|
9542
|
+
if (message?.role !== "assistant" || !isDroidContentBlockArray(message.content)) {
|
|
9543
|
+
continue;
|
|
8482
9544
|
}
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
9545
|
+
for (const block of message.content) {
|
|
9546
|
+
if (block.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string") {
|
|
9547
|
+
toolIdMap.set(block.id, block.name);
|
|
9548
|
+
}
|
|
8486
9549
|
}
|
|
8487
9550
|
}
|
|
8488
|
-
|
|
8489
|
-
|
|
9551
|
+
return toolIdMap;
|
|
9552
|
+
}
|
|
9553
|
+
function resolveUsageSettingsPath(transcriptPath) {
|
|
9554
|
+
if (!transcriptPath || !transcriptPath.endsWith(".jsonl")) {
|
|
9555
|
+
return null;
|
|
8490
9556
|
}
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
}
|
|
9557
|
+
return transcriptPath.slice(0, -".jsonl".length) + ".settings.json";
|
|
9558
|
+
}
|
|
9559
|
+
function readUsageSnapshot(transcriptPath) {
|
|
9560
|
+
const settingsPath = resolveUsageSettingsPath(transcriptPath);
|
|
9561
|
+
if (!settingsPath || !existsSync22(settingsPath)) {
|
|
9562
|
+
return null;
|
|
8498
9563
|
}
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
9564
|
+
try {
|
|
9565
|
+
const parsed = JSON.parse(readFileSync22(settingsPath, "utf-8"));
|
|
9566
|
+
if (!isRecord4(parsed)) {
|
|
9567
|
+
return null;
|
|
8502
9568
|
}
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
});
|
|
8507
|
-
}
|
|
8508
|
-
scheduleRead() {
|
|
8509
|
-
if (!this.started) {
|
|
8510
|
-
return;
|
|
9569
|
+
const tokenUsage = isRecord4(parsed.tokenUsage) ? parsed.tokenUsage : null;
|
|
9570
|
+
if (!tokenUsage) {
|
|
9571
|
+
return null;
|
|
8511
9572
|
}
|
|
8512
|
-
|
|
8513
|
-
|
|
9573
|
+
return {
|
|
9574
|
+
inputTokens: typeof tokenUsage.inputTokens === "number" ? tokenUsage.inputTokens : 0,
|
|
9575
|
+
outputTokens: typeof tokenUsage.outputTokens === "number" ? tokenUsage.outputTokens : 0,
|
|
9576
|
+
cacheCreationTokens: typeof tokenUsage.cacheCreationTokens === "number" ? tokenUsage.cacheCreationTokens : 0,
|
|
9577
|
+
cacheReadTokens: typeof tokenUsage.cacheReadTokens === "number" ? tokenUsage.cacheReadTokens : 0,
|
|
9578
|
+
thinkingTokens: typeof tokenUsage.thinkingTokens === "number" ? tokenUsage.thinkingTokens : 0,
|
|
9579
|
+
model: typeof parsed.model === "string" ? parsed.model : void 0
|
|
9580
|
+
};
|
|
9581
|
+
} catch {
|
|
9582
|
+
return null;
|
|
9583
|
+
}
|
|
9584
|
+
}
|
|
9585
|
+
function diffUsageSnapshot(current, previous) {
|
|
9586
|
+
const inputTokens = Math.max(0, current.inputTokens - (previous?.inputTokens ?? 0));
|
|
9587
|
+
const outputTokens = Math.max(0, current.outputTokens - (previous?.outputTokens ?? 0));
|
|
9588
|
+
const cacheCreationTokens = Math.max(0, current.cacheCreationTokens - (previous?.cacheCreationTokens ?? 0));
|
|
9589
|
+
const cacheReadTokens = Math.max(0, current.cacheReadTokens - (previous?.cacheReadTokens ?? 0));
|
|
9590
|
+
const reasoningTokens = Math.max(0, current.thinkingTokens - (previous?.thinkingTokens ?? 0));
|
|
9591
|
+
if (inputTokens === 0 && outputTokens === 0 && cacheCreationTokens === 0 && cacheReadTokens === 0 && reasoningTokens === 0) {
|
|
9592
|
+
return null;
|
|
9593
|
+
}
|
|
9594
|
+
return {
|
|
9595
|
+
inputTokens,
|
|
9596
|
+
outputTokens,
|
|
9597
|
+
cacheCreationTokens: cacheCreationTokens || void 0,
|
|
9598
|
+
cacheReadTokens: cacheReadTokens || void 0,
|
|
9599
|
+
reasoningTokens: reasoningTokens || void 0
|
|
9600
|
+
};
|
|
9601
|
+
}
|
|
9602
|
+
function maybeEmitUsage(context, timestamp) {
|
|
9603
|
+
const snapshot = readUsageSnapshot(context.transcriptPath);
|
|
9604
|
+
if (!snapshot) {
|
|
9605
|
+
return [];
|
|
9606
|
+
}
|
|
9607
|
+
const usageDelta = diffUsageSnapshot(snapshot, context.lastUsageSnapshot);
|
|
9608
|
+
context.lastUsageSnapshot = snapshot;
|
|
9609
|
+
if (!usageDelta) {
|
|
9610
|
+
return [];
|
|
9611
|
+
}
|
|
9612
|
+
return [
|
|
9613
|
+
{
|
|
9614
|
+
type: "usage",
|
|
9615
|
+
model: snapshot.model,
|
|
9616
|
+
timestamp,
|
|
9617
|
+
...usageDelta
|
|
8514
9618
|
}
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
9619
|
+
];
|
|
9620
|
+
}
|
|
9621
|
+
function mapDroidUserMessage(entry, context) {
|
|
9622
|
+
const message = isRecord4(entry.message) ? entry.message : null;
|
|
9623
|
+
if (!message) {
|
|
9624
|
+
return [];
|
|
8518
9625
|
}
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
9626
|
+
const content = message.content;
|
|
9627
|
+
const timestamp = toTimestamp2(entry);
|
|
9628
|
+
if (typeof content === "string") {
|
|
9629
|
+
return [
|
|
9630
|
+
{
|
|
9631
|
+
type: "message",
|
|
9632
|
+
role: "human",
|
|
9633
|
+
text: content,
|
|
9634
|
+
timestamp
|
|
9635
|
+
},
|
|
9636
|
+
...maybeEmitUsage(context, timestamp)
|
|
9637
|
+
];
|
|
9638
|
+
}
|
|
9639
|
+
if (!isDroidContentBlockArray(content)) {
|
|
9640
|
+
return maybeEmitUsage(context, timestamp);
|
|
9641
|
+
}
|
|
9642
|
+
const mappedEntries = [];
|
|
9643
|
+
for (const block of content) {
|
|
9644
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
9645
|
+
mappedEntries.push({
|
|
9646
|
+
type: "message",
|
|
9647
|
+
role: "human",
|
|
9648
|
+
text: block.text,
|
|
9649
|
+
timestamp
|
|
9650
|
+
});
|
|
9651
|
+
continue;
|
|
8522
9652
|
}
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
9653
|
+
if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
|
|
9654
|
+
const toolId = block.tool_use_id;
|
|
9655
|
+
mappedEntries.push({
|
|
9656
|
+
type: "tool-result",
|
|
9657
|
+
id: toolId,
|
|
9658
|
+
tool: context.toolIdMap.get(toolId) ?? "unknown",
|
|
9659
|
+
output: stringifyContent2(block.content),
|
|
9660
|
+
error: block.is_error === true,
|
|
9661
|
+
timestamp
|
|
9662
|
+
});
|
|
8528
9663
|
}
|
|
8529
|
-
|
|
8530
|
-
|
|
8531
|
-
|
|
9664
|
+
}
|
|
9665
|
+
mappedEntries.push(...maybeEmitUsage(context, timestamp));
|
|
9666
|
+
return mappedEntries;
|
|
9667
|
+
}
|
|
9668
|
+
function mapDroidAssistantMessage(entry, context) {
|
|
9669
|
+
const message = isRecord4(entry.message) ? entry.message : null;
|
|
9670
|
+
if (!message || !isDroidContentBlockArray(message.content)) {
|
|
9671
|
+
return maybeEmitUsage(context, toTimestamp2(entry));
|
|
9672
|
+
}
|
|
9673
|
+
const mappedEntries = [];
|
|
9674
|
+
const timestamp = toTimestamp2(entry);
|
|
9675
|
+
for (const block of message.content) {
|
|
9676
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
9677
|
+
mappedEntries.push({
|
|
9678
|
+
type: "message",
|
|
9679
|
+
role: "agent",
|
|
9680
|
+
text: block.text,
|
|
9681
|
+
timestamp
|
|
9682
|
+
});
|
|
9683
|
+
continue;
|
|
8532
9684
|
}
|
|
8533
|
-
if (
|
|
8534
|
-
|
|
9685
|
+
if (block.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string") {
|
|
9686
|
+
context.toolIdMap.set(block.id, block.name);
|
|
9687
|
+
mappedEntries.push({
|
|
9688
|
+
type: "tool-call",
|
|
9689
|
+
id: block.id,
|
|
9690
|
+
tool: block.name,
|
|
9691
|
+
input: isRecord4(block.input) ? block.input : {},
|
|
9692
|
+
timestamp
|
|
9693
|
+
});
|
|
8535
9694
|
}
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
9695
|
+
}
|
|
9696
|
+
mappedEntries.push(...maybeEmitUsage(context, timestamp));
|
|
9697
|
+
return mappedEntries;
|
|
9698
|
+
}
|
|
9699
|
+
function mapDroidMessageEntry(entry, context) {
|
|
9700
|
+
const message = isRecord4(entry.message) ? entry.message : null;
|
|
9701
|
+
const role = typeof message?.role === "string" ? message.role : null;
|
|
9702
|
+
if (role === "assistant") {
|
|
9703
|
+
return mapDroidAssistantMessage(entry, context);
|
|
9704
|
+
}
|
|
9705
|
+
if (role === "user" || role === "developer") {
|
|
9706
|
+
return mapDroidUserMessage(entry, context);
|
|
9707
|
+
}
|
|
9708
|
+
return maybeEmitUsage(context, toTimestamp2(entry));
|
|
9709
|
+
}
|
|
9710
|
+
function mapSessionStart(entry, context) {
|
|
9711
|
+
context.session = {
|
|
9712
|
+
sessionId: typeof entry.id === "string" ? entry.id : void 0,
|
|
9713
|
+
title: typeof entry.title === "string" ? entry.title : void 0,
|
|
9714
|
+
sessionTitle: typeof entry.sessionTitle === "string" ? entry.sessionTitle : void 0,
|
|
9715
|
+
owner: typeof entry.owner === "string" ? entry.owner : void 0,
|
|
9716
|
+
cwd: typeof entry.cwd === "string" ? entry.cwd : void 0,
|
|
9717
|
+
version: typeof entry.version === "number" ? entry.version : void 0
|
|
9718
|
+
};
|
|
9719
|
+
return maybeEmitUsage(context, toTimestamp2(entry));
|
|
9720
|
+
}
|
|
9721
|
+
function mapCompactionState(entry, context) {
|
|
9722
|
+
const timestamp = toTimestamp2(entry);
|
|
9723
|
+
const anchorMessage = isRecord4(entry.anchorMessage) ? entry.anchorMessage : null;
|
|
9724
|
+
const compactionEntry = {
|
|
9725
|
+
type: "compaction",
|
|
9726
|
+
timestamp,
|
|
9727
|
+
summary: typeof entry.summaryText === "string" ? entry.summaryText : void 0,
|
|
9728
|
+
summaryTokens: typeof entry.summaryTokens === "number" ? entry.summaryTokens : void 0,
|
|
9729
|
+
summaryKind: typeof entry.summaryKind === "string" ? entry.summaryKind : void 0,
|
|
9730
|
+
anchorMessageId: typeof anchorMessage?.id === "string" ? anchorMessage.id : void 0,
|
|
9731
|
+
removedCount: typeof entry.removedCount === "number" ? entry.removedCount : void 0
|
|
9732
|
+
};
|
|
9733
|
+
return [compactionEntry, ...maybeEmitUsage(context, timestamp)];
|
|
9734
|
+
}
|
|
9735
|
+
function mapDroidEntry(entry, context) {
|
|
9736
|
+
switch (entry.type) {
|
|
9737
|
+
case "session_start":
|
|
9738
|
+
return mapSessionStart(entry, context);
|
|
9739
|
+
case "message":
|
|
9740
|
+
return mapDroidMessageEntry(entry, context);
|
|
9741
|
+
case "compaction_state":
|
|
9742
|
+
return mapCompactionState(entry, context);
|
|
9743
|
+
case "todo_state":
|
|
9744
|
+
return [];
|
|
9745
|
+
default:
|
|
9746
|
+
return [];
|
|
9747
|
+
}
|
|
9748
|
+
}
|
|
9749
|
+
function parseDroidTranscript(content, options) {
|
|
9750
|
+
const rawEntries = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => {
|
|
8539
9751
|
try {
|
|
8540
|
-
|
|
8541
|
-
}
|
|
8542
|
-
|
|
9752
|
+
return JSON.parse(line);
|
|
9753
|
+
} catch {
|
|
9754
|
+
return null;
|
|
8543
9755
|
}
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
9756
|
+
}).filter((entry) => entry !== null);
|
|
9757
|
+
const context = createDroidMapperContext({
|
|
9758
|
+
toolIdMap: buildDroidToolIdMap(rawEntries),
|
|
9759
|
+
transcriptPath: options?.transcriptPath
|
|
9760
|
+
});
|
|
9761
|
+
return rawEntries.flatMap((entry) => mapDroidEntry(entry, context));
|
|
9762
|
+
}
|
|
9763
|
+
function createGeminiMapperContext(toolIdMap = /* @__PURE__ */ new Map()) {
|
|
9764
|
+
return { toolIdMap };
|
|
9765
|
+
}
|
|
9766
|
+
function isRecord5(value) {
|
|
9767
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9768
|
+
}
|
|
9769
|
+
function stringifyValue22(value) {
|
|
9770
|
+
if (typeof value === "string") {
|
|
9771
|
+
return value;
|
|
9772
|
+
}
|
|
9773
|
+
if (Array.isArray(value)) {
|
|
9774
|
+
return value.map((item) => stringifyValue22(item)).filter((item) => item.length > 0).join("\n");
|
|
9775
|
+
}
|
|
9776
|
+
if (isRecord5(value)) {
|
|
9777
|
+
return JSON.stringify(value);
|
|
9778
|
+
}
|
|
9779
|
+
if (value === null || value === void 0) {
|
|
9780
|
+
return "";
|
|
9781
|
+
}
|
|
9782
|
+
return String(value);
|
|
9783
|
+
}
|
|
9784
|
+
function normalizeTimestamp(value) {
|
|
9785
|
+
return typeof value === "string" ? value : (/* @__PURE__ */ new Date(0)).toISOString();
|
|
9786
|
+
}
|
|
9787
|
+
function extractUserText(content) {
|
|
9788
|
+
if (typeof content === "string") {
|
|
9789
|
+
return content;
|
|
9790
|
+
}
|
|
9791
|
+
if (!Array.isArray(content)) {
|
|
9792
|
+
return "";
|
|
9793
|
+
}
|
|
9794
|
+
return content.map((item) => {
|
|
9795
|
+
if (!isRecord5(item)) {
|
|
9796
|
+
return "";
|
|
9797
|
+
}
|
|
9798
|
+
if (typeof item.text === "string") {
|
|
9799
|
+
return item.text;
|
|
9800
|
+
}
|
|
9801
|
+
return stringifyValue22(item);
|
|
9802
|
+
}).filter((item) => item.length > 0).join("\n");
|
|
9803
|
+
}
|
|
9804
|
+
function mapUserMessage(message) {
|
|
9805
|
+
const text = extractUserText(message.content);
|
|
9806
|
+
if (text.length === 0) {
|
|
9807
|
+
return [];
|
|
9808
|
+
}
|
|
9809
|
+
return [
|
|
9810
|
+
{
|
|
9811
|
+
type: "message",
|
|
9812
|
+
role: "human",
|
|
9813
|
+
text,
|
|
9814
|
+
timestamp: normalizeTimestamp(message.timestamp)
|
|
9815
|
+
}
|
|
9816
|
+
];
|
|
9817
|
+
}
|
|
9818
|
+
function mapGeminiThoughts(message) {
|
|
9819
|
+
if (!Array.isArray(message.thoughts)) {
|
|
9820
|
+
return [];
|
|
9821
|
+
}
|
|
9822
|
+
const entries = [];
|
|
9823
|
+
for (const thought of message.thoughts) {
|
|
9824
|
+
if (!isRecord5(thought)) {
|
|
9825
|
+
continue;
|
|
9826
|
+
}
|
|
9827
|
+
const parts = [
|
|
9828
|
+
typeof thought.subject === "string" && thought.subject.length > 0 ? thought.subject : "",
|
|
9829
|
+
typeof thought.description === "string" ? thought.description : ""
|
|
9830
|
+
].filter((part) => part.length > 0);
|
|
9831
|
+
if (parts.length === 0) {
|
|
9832
|
+
continue;
|
|
9833
|
+
}
|
|
9834
|
+
entries.push({
|
|
9835
|
+
type: "thinking",
|
|
9836
|
+
text: parts.join("\n\n"),
|
|
9837
|
+
timestamp: normalizeTimestamp(thought.timestamp ?? message.timestamp)
|
|
9838
|
+
});
|
|
9839
|
+
}
|
|
9840
|
+
return entries;
|
|
9841
|
+
}
|
|
9842
|
+
function mapGeminiToolCalls(message, context) {
|
|
9843
|
+
if (!Array.isArray(message.toolCalls)) {
|
|
9844
|
+
return [];
|
|
9845
|
+
}
|
|
9846
|
+
const entries = [];
|
|
9847
|
+
for (const toolCall of message.toolCalls) {
|
|
9848
|
+
if (!isRecord5(toolCall) || typeof toolCall.id !== "string") {
|
|
9849
|
+
continue;
|
|
9850
|
+
}
|
|
9851
|
+
const toolName = typeof toolCall.name === "string" ? toolCall.name : "unknown";
|
|
9852
|
+
const timestamp = normalizeTimestamp(toolCall.timestamp ?? message.timestamp);
|
|
9853
|
+
context.toolIdMap.set(toolCall.id, toolName);
|
|
9854
|
+
entries.push({
|
|
9855
|
+
type: "tool-call",
|
|
9856
|
+
id: toolCall.id,
|
|
9857
|
+
tool: toolName,
|
|
9858
|
+
input: isRecord5(toolCall.args) ? toolCall.args : {},
|
|
9859
|
+
timestamp
|
|
9860
|
+
});
|
|
9861
|
+
if (!Array.isArray(toolCall.result)) {
|
|
9862
|
+
continue;
|
|
9863
|
+
}
|
|
9864
|
+
for (const result of toolCall.result) {
|
|
9865
|
+
if (!isRecord5(result)) {
|
|
9866
|
+
continue;
|
|
9867
|
+
}
|
|
9868
|
+
const functionResponse = isRecord5(result.functionResponse) ? result.functionResponse : null;
|
|
9869
|
+
const response = isRecord5(functionResponse?.response) ? functionResponse?.response : null;
|
|
9870
|
+
if (!response) {
|
|
9871
|
+
continue;
|
|
9872
|
+
}
|
|
9873
|
+
const output = typeof response.output === "string" ? response.output : typeof response.error === "string" ? response.error : stringifyValue22(response);
|
|
9874
|
+
entries.push({
|
|
9875
|
+
type: "tool-result",
|
|
9876
|
+
id: typeof functionResponse?.id === "string" ? functionResponse.id : toolCall.id,
|
|
9877
|
+
tool: typeof functionResponse?.name === "string" ? functionResponse.name : context.toolIdMap.get(toolCall.id) ?? toolName,
|
|
9878
|
+
output,
|
|
9879
|
+
error: toolCall.status === "error" || typeof response.error === "string",
|
|
9880
|
+
timestamp
|
|
9881
|
+
});
|
|
9882
|
+
}
|
|
9883
|
+
}
|
|
9884
|
+
return entries;
|
|
9885
|
+
}
|
|
9886
|
+
function mapGeminiUsage(message) {
|
|
9887
|
+
const tokens = isRecord5(message.tokens) ? message.tokens : null;
|
|
9888
|
+
if (!tokens) {
|
|
9889
|
+
return [];
|
|
9890
|
+
}
|
|
9891
|
+
const entry = {
|
|
9892
|
+
type: "usage",
|
|
9893
|
+
inputTokens: typeof tokens.input === "number" ? tokens.input : 0,
|
|
9894
|
+
outputTokens: typeof tokens.output === "number" ? tokens.output : 0,
|
|
9895
|
+
cacheReadTokens: typeof tokens.cached === "number" ? tokens.cached : void 0,
|
|
9896
|
+
reasoningTokens: typeof tokens.thoughts === "number" ? tokens.thoughts : void 0,
|
|
9897
|
+
model: typeof message.model === "string" ? message.model : void 0,
|
|
9898
|
+
timestamp: normalizeTimestamp(message.timestamp)
|
|
9899
|
+
};
|
|
9900
|
+
return [entry];
|
|
9901
|
+
}
|
|
9902
|
+
function mapGeminiMessage(message, context) {
|
|
9903
|
+
const timestamp = normalizeTimestamp(message.timestamp);
|
|
9904
|
+
const entries = [];
|
|
9905
|
+
entries.push(...mapGeminiThoughts(message));
|
|
9906
|
+
if (typeof message.content === "string" && message.content.length > 0) {
|
|
9907
|
+
entries.push({
|
|
9908
|
+
type: "message",
|
|
9909
|
+
role: "agent",
|
|
9910
|
+
text: message.content,
|
|
9911
|
+
timestamp
|
|
9912
|
+
});
|
|
9913
|
+
}
|
|
9914
|
+
entries.push(...mapGeminiToolCalls(message, context));
|
|
9915
|
+
entries.push(...mapGeminiUsage(message));
|
|
9916
|
+
return entries;
|
|
9917
|
+
}
|
|
9918
|
+
function mapInfoMessage(message) {
|
|
9919
|
+
if (typeof message.content !== "string" || message.content.length === 0) {
|
|
9920
|
+
return [];
|
|
9921
|
+
}
|
|
9922
|
+
return [
|
|
9923
|
+
{
|
|
9924
|
+
type: "message",
|
|
9925
|
+
role: "agent",
|
|
9926
|
+
text: message.content,
|
|
9927
|
+
timestamp: normalizeTimestamp(message.timestamp),
|
|
9928
|
+
isMeta: true
|
|
9929
|
+
}
|
|
9930
|
+
];
|
|
9931
|
+
}
|
|
9932
|
+
function mapGeminiMessageEntry(message, context) {
|
|
9933
|
+
switch (message.type) {
|
|
9934
|
+
case "user":
|
|
9935
|
+
return mapUserMessage(message);
|
|
9936
|
+
case "gemini":
|
|
9937
|
+
return mapGeminiMessage(message, context);
|
|
9938
|
+
case "info":
|
|
9939
|
+
return mapInfoMessage(message);
|
|
9940
|
+
default:
|
|
9941
|
+
return [];
|
|
9942
|
+
}
|
|
9943
|
+
}
|
|
9944
|
+
function buildGeminiToolIdMap(messages) {
|
|
9945
|
+
const toolIdMap = /* @__PURE__ */ new Map();
|
|
9946
|
+
for (const message of messages) {
|
|
9947
|
+
if (message.type !== "gemini" || !Array.isArray(message.toolCalls)) {
|
|
9948
|
+
continue;
|
|
9949
|
+
}
|
|
9950
|
+
for (const toolCall of message.toolCalls) {
|
|
9951
|
+
if (!isRecord5(toolCall) || typeof toolCall.id !== "string" || typeof toolCall.name !== "string") {
|
|
9952
|
+
continue;
|
|
9953
|
+
}
|
|
9954
|
+
toolIdMap.set(toolCall.id, toolCall.name);
|
|
9955
|
+
}
|
|
9956
|
+
}
|
|
9957
|
+
return toolIdMap;
|
|
9958
|
+
}
|
|
9959
|
+
function parseGeminiTranscript(content) {
|
|
9960
|
+
let parsed;
|
|
9961
|
+
try {
|
|
9962
|
+
parsed = JSON.parse(content);
|
|
9963
|
+
} catch {
|
|
9964
|
+
return [];
|
|
9965
|
+
}
|
|
9966
|
+
const messages = Array.isArray(parsed.messages) ? parsed.messages.filter((message) => isRecord5(message)) : [];
|
|
9967
|
+
const context = createGeminiMapperContext(buildGeminiToolIdMap(messages));
|
|
9968
|
+
return messages.flatMap((message) => mapGeminiMessageEntry(message, context));
|
|
9969
|
+
}
|
|
9970
|
+
var JsonlTranscriptWatcher = class {
|
|
9971
|
+
constructor(transcriptPath, mapper, options) {
|
|
9972
|
+
this.transcriptPath = transcriptPath;
|
|
9973
|
+
this.mapper = mapper;
|
|
9974
|
+
this.mapperState = mapper.createState();
|
|
9975
|
+
this.options = {
|
|
9976
|
+
debounceMs: options?.debounceMs ?? 100,
|
|
9977
|
+
pollIntervalMs: options?.pollIntervalMs ?? 500
|
|
9978
|
+
};
|
|
9979
|
+
}
|
|
9980
|
+
handlers = /* @__PURE__ */ new Set();
|
|
9981
|
+
errorHandlers = /* @__PURE__ */ new Set();
|
|
9982
|
+
entries = [];
|
|
9983
|
+
mapperState;
|
|
9984
|
+
options;
|
|
9985
|
+
byteOffset = 0;
|
|
9986
|
+
buffer = "";
|
|
9987
|
+
watcher = null;
|
|
9988
|
+
debounceTimer = null;
|
|
9989
|
+
started = false;
|
|
9990
|
+
usingPolling = false;
|
|
9991
|
+
onEntries(handler) {
|
|
9992
|
+
this.handlers.add(handler);
|
|
9993
|
+
}
|
|
9994
|
+
onError(handler) {
|
|
9995
|
+
this.errorHandlers.add(handler);
|
|
9996
|
+
}
|
|
9997
|
+
start() {
|
|
9998
|
+
if (this.started) {
|
|
9999
|
+
return;
|
|
10000
|
+
}
|
|
10001
|
+
this.started = true;
|
|
10002
|
+
if (existsSync32(this.transcriptPath)) {
|
|
10003
|
+
this.readNewContent();
|
|
10004
|
+
}
|
|
10005
|
+
this.installWatcher();
|
|
10006
|
+
}
|
|
10007
|
+
stop() {
|
|
10008
|
+
this.started = false;
|
|
10009
|
+
if (this.debounceTimer) {
|
|
10010
|
+
clearTimeout(this.debounceTimer);
|
|
10011
|
+
this.debounceTimer = null;
|
|
10012
|
+
}
|
|
10013
|
+
if (this.watcher) {
|
|
10014
|
+
this.watcher.close();
|
|
10015
|
+
this.watcher = null;
|
|
10016
|
+
}
|
|
10017
|
+
if (this.usingPolling) {
|
|
10018
|
+
unwatchFile(this.transcriptPath);
|
|
10019
|
+
this.usingPolling = false;
|
|
10020
|
+
}
|
|
10021
|
+
}
|
|
10022
|
+
getEntries() {
|
|
10023
|
+
return [...this.entries];
|
|
10024
|
+
}
|
|
10025
|
+
installWatcher() {
|
|
10026
|
+
try {
|
|
10027
|
+
this.watcher = watch(this.transcriptPath, { persistent: false }, () => this.scheduleRead());
|
|
10028
|
+
this.watcher.on("error", (error3) => {
|
|
10029
|
+
this.reportError(error3, "fs.watch failed");
|
|
10030
|
+
this.watcher?.close();
|
|
10031
|
+
this.watcher = null;
|
|
10032
|
+
this.installPollingWatcher();
|
|
10033
|
+
});
|
|
10034
|
+
} catch (error3) {
|
|
10035
|
+
this.reportError(error3, "Failed to install fs.watch");
|
|
10036
|
+
this.installPollingWatcher();
|
|
10037
|
+
}
|
|
10038
|
+
}
|
|
10039
|
+
installPollingWatcher() {
|
|
10040
|
+
if (this.usingPolling) {
|
|
10041
|
+
return;
|
|
10042
|
+
}
|
|
10043
|
+
this.usingPolling = true;
|
|
10044
|
+
watchFile(this.transcriptPath, { interval: this.options.pollIntervalMs, persistent: false }, () => {
|
|
10045
|
+
this.scheduleRead();
|
|
10046
|
+
});
|
|
10047
|
+
}
|
|
10048
|
+
scheduleRead() {
|
|
10049
|
+
if (!this.started) {
|
|
10050
|
+
return;
|
|
10051
|
+
}
|
|
10052
|
+
if (this.debounceTimer) {
|
|
10053
|
+
clearTimeout(this.debounceTimer);
|
|
10054
|
+
}
|
|
10055
|
+
this.debounceTimer = setTimeout(() => {
|
|
10056
|
+
this.readNewContent();
|
|
10057
|
+
}, this.options.debounceMs);
|
|
10058
|
+
}
|
|
10059
|
+
readNewContent() {
|
|
10060
|
+
if (!this.started || !existsSync32(this.transcriptPath)) {
|
|
10061
|
+
return;
|
|
10062
|
+
}
|
|
10063
|
+
let fileSize = 0;
|
|
10064
|
+
try {
|
|
10065
|
+
fileSize = statSync(this.transcriptPath).size;
|
|
10066
|
+
} catch {
|
|
10067
|
+
return;
|
|
10068
|
+
}
|
|
10069
|
+
if (fileSize < this.byteOffset) {
|
|
10070
|
+
this.byteOffset = 0;
|
|
10071
|
+
this.buffer = "";
|
|
10072
|
+
}
|
|
10073
|
+
if (fileSize === this.byteOffset) {
|
|
10074
|
+
return;
|
|
10075
|
+
}
|
|
10076
|
+
const bytesToRead = fileSize - this.byteOffset;
|
|
10077
|
+
const buffer = Buffer.alloc(bytesToRead);
|
|
10078
|
+
const fileDescriptor = openSync(this.transcriptPath, "r");
|
|
10079
|
+
try {
|
|
10080
|
+
readSync(fileDescriptor, buffer, 0, bytesToRead, this.byteOffset);
|
|
10081
|
+
} finally {
|
|
10082
|
+
closeSync(fileDescriptor);
|
|
10083
|
+
}
|
|
10084
|
+
this.byteOffset = fileSize;
|
|
10085
|
+
const pendingText = `${this.buffer}${buffer.toString("utf-8")}`;
|
|
10086
|
+
const lines = pendingText.split("\n");
|
|
10087
|
+
this.buffer = lines.pop() ?? "";
|
|
10088
|
+
const newEntries = [];
|
|
10089
|
+
for (const line of lines) {
|
|
10090
|
+
const trimmed = line.trim();
|
|
10091
|
+
if (trimmed.length === 0) {
|
|
8552
10092
|
continue;
|
|
8553
10093
|
}
|
|
8554
10094
|
try {
|
|
8555
|
-
const parsed = JSON.parse(trimmed);
|
|
8556
|
-
newEntries.push(...this.mapper.map(parsed, this.mapperState));
|
|
8557
|
-
} catch {
|
|
8558
|
-
this.buffer = `${trimmed}
|
|
8559
|
-
${this.buffer}`;
|
|
8560
|
-
break;
|
|
10095
|
+
const parsed = JSON.parse(trimmed);
|
|
10096
|
+
newEntries.push(...this.mapper.map(parsed, this.mapperState));
|
|
10097
|
+
} catch {
|
|
10098
|
+
this.buffer = `${trimmed}
|
|
10099
|
+
${this.buffer}`;
|
|
10100
|
+
break;
|
|
10101
|
+
}
|
|
10102
|
+
}
|
|
10103
|
+
if (newEntries.length === 0) {
|
|
10104
|
+
return;
|
|
10105
|
+
}
|
|
10106
|
+
this.entries.push(...newEntries);
|
|
10107
|
+
const allEntries = [...this.entries];
|
|
10108
|
+
for (const handler of this.handlers) {
|
|
10109
|
+
handler(newEntries, allEntries);
|
|
10110
|
+
}
|
|
10111
|
+
}
|
|
10112
|
+
reportError(error3, fallbackMessage) {
|
|
10113
|
+
const resolved = error3 instanceof Error ? error3 : new Error(typeof error3 === "string" ? error3 : fallbackMessage);
|
|
10114
|
+
for (const handler of this.errorHandlers) {
|
|
10115
|
+
handler(resolved);
|
|
10116
|
+
}
|
|
10117
|
+
}
|
|
10118
|
+
};
|
|
10119
|
+
function createJsonlTranscriptWatcher(transcriptPath, mapper, options) {
|
|
10120
|
+
return new JsonlTranscriptWatcher(transcriptPath, mapper, options);
|
|
10121
|
+
}
|
|
10122
|
+
var JsonSessionWatcher = class {
|
|
10123
|
+
constructor(transcriptPath, mapper, options) {
|
|
10124
|
+
this.transcriptPath = transcriptPath;
|
|
10125
|
+
this.mapper = mapper;
|
|
10126
|
+
this.mapperState = mapper.createState();
|
|
10127
|
+
this.options = {
|
|
10128
|
+
debounceMs: options?.debounceMs ?? 100,
|
|
10129
|
+
pollIntervalMs: options?.pollIntervalMs ?? 500
|
|
10130
|
+
};
|
|
10131
|
+
}
|
|
10132
|
+
handlers = /* @__PURE__ */ new Set();
|
|
10133
|
+
errorHandlers = /* @__PURE__ */ new Set();
|
|
10134
|
+
options;
|
|
10135
|
+
entries = [];
|
|
10136
|
+
mapperState;
|
|
10137
|
+
messageCount = 0;
|
|
10138
|
+
watcher = null;
|
|
10139
|
+
debounceTimer = null;
|
|
10140
|
+
started = false;
|
|
10141
|
+
usingPolling = false;
|
|
10142
|
+
onEntries(handler) {
|
|
10143
|
+
this.handlers.add(handler);
|
|
10144
|
+
}
|
|
10145
|
+
onError(handler) {
|
|
10146
|
+
this.errorHandlers.add(handler);
|
|
10147
|
+
}
|
|
10148
|
+
start() {
|
|
10149
|
+
if (this.started) {
|
|
10150
|
+
return;
|
|
10151
|
+
}
|
|
10152
|
+
this.started = true;
|
|
10153
|
+
if (existsSync42(this.transcriptPath)) {
|
|
10154
|
+
this.readSession();
|
|
10155
|
+
}
|
|
10156
|
+
this.installWatcher();
|
|
10157
|
+
}
|
|
10158
|
+
stop() {
|
|
10159
|
+
this.started = false;
|
|
10160
|
+
if (this.debounceTimer) {
|
|
10161
|
+
clearTimeout(this.debounceTimer);
|
|
10162
|
+
this.debounceTimer = null;
|
|
10163
|
+
}
|
|
10164
|
+
if (this.watcher) {
|
|
10165
|
+
this.watcher.close();
|
|
10166
|
+
this.watcher = null;
|
|
10167
|
+
}
|
|
10168
|
+
if (this.usingPolling) {
|
|
10169
|
+
unwatchFile2(this.transcriptPath);
|
|
10170
|
+
this.usingPolling = false;
|
|
10171
|
+
}
|
|
10172
|
+
}
|
|
10173
|
+
getEntries() {
|
|
10174
|
+
return [...this.entries];
|
|
10175
|
+
}
|
|
10176
|
+
installWatcher() {
|
|
10177
|
+
try {
|
|
10178
|
+
this.watcher = watch2(this.transcriptPath, { persistent: false }, () => this.scheduleRead());
|
|
10179
|
+
this.watcher.on("error", (error3) => {
|
|
10180
|
+
this.reportError(error3, "fs.watch failed");
|
|
10181
|
+
this.watcher?.close();
|
|
10182
|
+
this.watcher = null;
|
|
10183
|
+
this.installPollingWatcher();
|
|
10184
|
+
});
|
|
10185
|
+
} catch (error3) {
|
|
10186
|
+
this.reportError(error3, "Failed to install fs.watch");
|
|
10187
|
+
this.installPollingWatcher();
|
|
10188
|
+
}
|
|
10189
|
+
}
|
|
10190
|
+
installPollingWatcher() {
|
|
10191
|
+
if (this.usingPolling) {
|
|
10192
|
+
return;
|
|
10193
|
+
}
|
|
10194
|
+
this.usingPolling = true;
|
|
10195
|
+
watchFile2(this.transcriptPath, { interval: this.options.pollIntervalMs, persistent: false }, () => {
|
|
10196
|
+
this.scheduleRead();
|
|
10197
|
+
});
|
|
10198
|
+
}
|
|
10199
|
+
scheduleRead() {
|
|
10200
|
+
if (!this.started) {
|
|
10201
|
+
return;
|
|
10202
|
+
}
|
|
10203
|
+
if (this.debounceTimer) {
|
|
10204
|
+
clearTimeout(this.debounceTimer);
|
|
10205
|
+
}
|
|
10206
|
+
this.debounceTimer = setTimeout(() => {
|
|
10207
|
+
this.readSession();
|
|
10208
|
+
}, this.options.debounceMs);
|
|
10209
|
+
}
|
|
10210
|
+
resetState() {
|
|
10211
|
+
this.entries = [];
|
|
10212
|
+
this.mapperState = this.mapper.createState();
|
|
10213
|
+
this.messageCount = 0;
|
|
10214
|
+
}
|
|
10215
|
+
readSession() {
|
|
10216
|
+
if (!this.started || !existsSync42(this.transcriptPath)) {
|
|
10217
|
+
return;
|
|
10218
|
+
}
|
|
10219
|
+
let parsed;
|
|
10220
|
+
try {
|
|
10221
|
+
parsed = JSON.parse(readFileSync3(this.transcriptPath, "utf-8"));
|
|
10222
|
+
} catch (error3) {
|
|
10223
|
+
this.reportError(error3, "Failed to parse JSON session");
|
|
10224
|
+
return;
|
|
10225
|
+
}
|
|
10226
|
+
let messages;
|
|
10227
|
+
try {
|
|
10228
|
+
messages = this.mapper.getMessages(parsed);
|
|
10229
|
+
} catch (error3) {
|
|
10230
|
+
this.reportError(error3, "Failed to read session messages");
|
|
10231
|
+
return;
|
|
10232
|
+
}
|
|
10233
|
+
if (messages.length < this.messageCount) {
|
|
10234
|
+
this.resetState();
|
|
10235
|
+
}
|
|
10236
|
+
const newMessages = messages.slice(this.messageCount);
|
|
10237
|
+
if (newMessages.length === 0) {
|
|
10238
|
+
return;
|
|
10239
|
+
}
|
|
10240
|
+
const newEntries = [];
|
|
10241
|
+
for (const message of newMessages) {
|
|
10242
|
+
try {
|
|
10243
|
+
newEntries.push(...this.mapper.map(message, this.mapperState));
|
|
10244
|
+
} catch (error3) {
|
|
10245
|
+
this.reportError(error3, "Failed to map JSON session entry");
|
|
8561
10246
|
}
|
|
8562
10247
|
}
|
|
10248
|
+
this.messageCount = messages.length;
|
|
8563
10249
|
if (newEntries.length === 0) {
|
|
8564
10250
|
return;
|
|
8565
10251
|
}
|
|
@@ -8569,9 +10255,15 @@ ${this.buffer}`;
|
|
|
8569
10255
|
handler(newEntries, allEntries);
|
|
8570
10256
|
}
|
|
8571
10257
|
}
|
|
10258
|
+
reportError(error3, fallbackMessage) {
|
|
10259
|
+
const resolved = error3 instanceof Error ? error3 : new Error(typeof error3 === "string" ? error3 : fallbackMessage);
|
|
10260
|
+
for (const handler of this.errorHandlers) {
|
|
10261
|
+
handler(resolved);
|
|
10262
|
+
}
|
|
10263
|
+
}
|
|
8572
10264
|
};
|
|
8573
|
-
function
|
|
8574
|
-
return new
|
|
10265
|
+
function createJsonSessionWatcher(transcriptPath, mapper, options) {
|
|
10266
|
+
return new JsonSessionWatcher(transcriptPath, mapper, options);
|
|
8575
10267
|
}
|
|
8576
10268
|
function buildTranscriptPath(cwd, nativeSessionId) {
|
|
8577
10269
|
const sanitized = cwd.replace(/[^a-zA-Z0-9\-_]/g, "-");
|
|
@@ -8623,7 +10315,7 @@ function createClaudeHarness() {
|
|
|
8623
10315
|
},
|
|
8624
10316
|
resolveTranscriptPath(nativeSessionId, cwd) {
|
|
8625
10317
|
const candidate = buildTranscriptPath(cwd, nativeSessionId);
|
|
8626
|
-
if (
|
|
10318
|
+
if (existsSync52(candidate)) {
|
|
8627
10319
|
return candidate;
|
|
8628
10320
|
}
|
|
8629
10321
|
return null;
|
|
@@ -8643,7 +10335,7 @@ function createClaudeHarness() {
|
|
|
8643
10335
|
};
|
|
8644
10336
|
}
|
|
8645
10337
|
function listDateDirectories(root) {
|
|
8646
|
-
if (!
|
|
10338
|
+
if (!existsSync6(root)) {
|
|
8647
10339
|
return [];
|
|
8648
10340
|
}
|
|
8649
10341
|
const directories = [];
|
|
@@ -8668,10 +10360,10 @@ function listDateDirectories(root) {
|
|
|
8668
10360
|
}
|
|
8669
10361
|
function resolveCodexSessionIndex(root, nativeSessionId) {
|
|
8670
10362
|
const indexPath = join32(root, "session_index.jsonl");
|
|
8671
|
-
if (!
|
|
10363
|
+
if (!existsSync6(indexPath)) {
|
|
8672
10364
|
return null;
|
|
8673
10365
|
}
|
|
8674
|
-
const lines =
|
|
10366
|
+
const lines = readFileSync4(indexPath, "utf-8").split("\n");
|
|
8675
10367
|
for (const line of lines) {
|
|
8676
10368
|
const trimmed = line.trim();
|
|
8677
10369
|
if (trimmed.length === 0) {
|
|
@@ -8698,56 +10390,406 @@ function createCodexHarness() {
|
|
|
8698
10390
|
maxTurns: false,
|
|
8699
10391
|
budgetLimit: false,
|
|
8700
10392
|
toolHooks: false,
|
|
8701
|
-
subagentVisibility: true,
|
|
10393
|
+
subagentVisibility: true,
|
|
10394
|
+
structuredOutput: true,
|
|
10395
|
+
permissionBypass: true
|
|
10396
|
+
},
|
|
10397
|
+
buildSpawnArgs(config) {
|
|
10398
|
+
const args = ["exec", config.prompt, "--json", "--dangerously-bypass-approvals-and-sandbox"];
|
|
10399
|
+
if (config.model) {
|
|
10400
|
+
args.push("--model", config.model);
|
|
10401
|
+
}
|
|
10402
|
+
if (config.extraArgs) {
|
|
10403
|
+
args.push(...config.extraArgs);
|
|
10404
|
+
}
|
|
10405
|
+
return args;
|
|
10406
|
+
},
|
|
10407
|
+
buildResumeArgs(nativeSessionId, config) {
|
|
10408
|
+
const args = ["exec", "resume", nativeSessionId, "--json", "--dangerously-bypass-approvals-and-sandbox"];
|
|
10409
|
+
if (config.prompt) {
|
|
10410
|
+
args.push(config.prompt);
|
|
10411
|
+
}
|
|
10412
|
+
if (config.extraArgs) {
|
|
10413
|
+
args.push(...config.extraArgs);
|
|
10414
|
+
}
|
|
10415
|
+
return args;
|
|
10416
|
+
},
|
|
10417
|
+
resolveTranscriptPath(nativeSessionId) {
|
|
10418
|
+
const sessionsRoot = join32(homedir22(), ".codex", "sessions");
|
|
10419
|
+
const indexedPath = resolveCodexSessionIndex(sessionsRoot, nativeSessionId);
|
|
10420
|
+
if (indexedPath) {
|
|
10421
|
+
return indexedPath;
|
|
10422
|
+
}
|
|
10423
|
+
for (const directory of listDateDirectories(sessionsRoot)) {
|
|
10424
|
+
for (const entry of readdirSync2(directory)) {
|
|
10425
|
+
if (entry.includes(nativeSessionId) && entry.endsWith(".jsonl")) {
|
|
10426
|
+
return join32(directory, entry);
|
|
10427
|
+
}
|
|
10428
|
+
}
|
|
10429
|
+
}
|
|
10430
|
+
return null;
|
|
10431
|
+
},
|
|
10432
|
+
createWatcher(transcriptPath) {
|
|
10433
|
+
return createJsonlTranscriptWatcher(transcriptPath, {
|
|
10434
|
+
createState: () => createCodexMapperContext(),
|
|
10435
|
+
map: (entry, state) => mapCodexEntry(entry, state)
|
|
10436
|
+
});
|
|
10437
|
+
},
|
|
10438
|
+
parseTranscript(content) {
|
|
10439
|
+
return parseCodexTranscript(content);
|
|
10440
|
+
},
|
|
10441
|
+
async isAvailable() {
|
|
10442
|
+
return spawnSync22("which", ["codex"], { stdio: "ignore" }).status === 0;
|
|
10443
|
+
}
|
|
10444
|
+
};
|
|
10445
|
+
}
|
|
10446
|
+
var TRANSCRIPT_DISCOVERY_PADDING_MS = 5 * 6e4;
|
|
10447
|
+
var DEFAULT_MAX_DISCOVERY_CANDIDATES = 40;
|
|
10448
|
+
function sanitizeFactoryCwd(cwd) {
|
|
10449
|
+
return cwd.replace(/[\\/]/g, "-");
|
|
10450
|
+
}
|
|
10451
|
+
function buildScopedTranscriptPath(cwd, nativeSessionId) {
|
|
10452
|
+
return join42(homedir32(), ".factory", "sessions", sanitizeFactoryCwd(cwd), `${nativeSessionId}.jsonl`);
|
|
10453
|
+
}
|
|
10454
|
+
function buildLegacyTranscriptPath(nativeSessionId) {
|
|
10455
|
+
return join42(homedir32(), ".factory", "sessions", `${nativeSessionId}.jsonl`);
|
|
10456
|
+
}
|
|
10457
|
+
function getDroidSessionsRoot() {
|
|
10458
|
+
return join42(homedir32(), ".factory", "sessions");
|
|
10459
|
+
}
|
|
10460
|
+
function parseStartedAtMs(startedAt) {
|
|
10461
|
+
if (typeof startedAt === "number" && Number.isFinite(startedAt)) {
|
|
10462
|
+
return startedAt;
|
|
10463
|
+
}
|
|
10464
|
+
if (typeof startedAt === "string") {
|
|
10465
|
+
const parsed = new Date(startedAt).getTime();
|
|
10466
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
10467
|
+
}
|
|
10468
|
+
return null;
|
|
10469
|
+
}
|
|
10470
|
+
function isTranscriptRecentEnough(transcriptPath, startedAt) {
|
|
10471
|
+
const startedAtMs = parseStartedAtMs(startedAt);
|
|
10472
|
+
if (startedAtMs == null) {
|
|
10473
|
+
return true;
|
|
10474
|
+
}
|
|
10475
|
+
try {
|
|
10476
|
+
return statSync2(transcriptPath).mtimeMs >= startedAtMs - TRANSCRIPT_DISCOVERY_PADDING_MS;
|
|
10477
|
+
} catch {
|
|
10478
|
+
return true;
|
|
10479
|
+
}
|
|
10480
|
+
}
|
|
10481
|
+
function readDroidSessionId(transcriptPath) {
|
|
10482
|
+
try {
|
|
10483
|
+
const firstLine = readFileSync5(transcriptPath, "utf-8").split(/\r?\n/, 1)[0]?.trim();
|
|
10484
|
+
if (!firstLine) {
|
|
10485
|
+
return basename4(transcriptPath, ".jsonl");
|
|
10486
|
+
}
|
|
10487
|
+
const parsed = JSON.parse(firstLine);
|
|
10488
|
+
if (typeof parsed.id === "string" && parsed.id.length > 0) {
|
|
10489
|
+
return parsed.id;
|
|
10490
|
+
}
|
|
10491
|
+
} catch {
|
|
10492
|
+
}
|
|
10493
|
+
return basename4(transcriptPath, ".jsonl");
|
|
10494
|
+
}
|
|
10495
|
+
function listDroidTranscriptPaths(cwd) {
|
|
10496
|
+
const candidateDirs = [join42(getDroidSessionsRoot(), sanitizeFactoryCwd(cwd)), getDroidSessionsRoot()];
|
|
10497
|
+
const transcriptPaths = /* @__PURE__ */ new Map();
|
|
10498
|
+
for (const directory of candidateDirs) {
|
|
10499
|
+
if (!existsSync7(directory)) {
|
|
10500
|
+
continue;
|
|
10501
|
+
}
|
|
10502
|
+
try {
|
|
10503
|
+
for (const entry of readdirSync3(directory, { withFileTypes: true })) {
|
|
10504
|
+
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) {
|
|
10505
|
+
continue;
|
|
10506
|
+
}
|
|
10507
|
+
const transcriptPath = join42(directory, entry.name);
|
|
10508
|
+
transcriptPaths.set(transcriptPath, statSync2(transcriptPath).mtimeMs);
|
|
10509
|
+
}
|
|
10510
|
+
} catch {
|
|
10511
|
+
continue;
|
|
10512
|
+
}
|
|
10513
|
+
}
|
|
10514
|
+
return Array.from(transcriptPaths.entries()).sort((left, right) => right[1] - left[1]).map(([transcriptPath]) => transcriptPath);
|
|
10515
|
+
}
|
|
10516
|
+
function discoverDroidNativeSessionByOrbhSessionId(cwd, orbhSessionId, options) {
|
|
10517
|
+
const transcriptPaths = listDroidTranscriptPaths(cwd).slice(0, options?.maxCandidates ?? DEFAULT_MAX_DISCOVERY_CANDIDATES);
|
|
10518
|
+
for (const transcriptPath of transcriptPaths) {
|
|
10519
|
+
if (!isTranscriptRecentEnough(transcriptPath, options?.startedAt)) {
|
|
10520
|
+
continue;
|
|
10521
|
+
}
|
|
10522
|
+
try {
|
|
10523
|
+
const content = readFileSync5(transcriptPath, "utf-8");
|
|
10524
|
+
if (!content.includes(orbhSessionId)) {
|
|
10525
|
+
continue;
|
|
10526
|
+
}
|
|
10527
|
+
const nativeSessionId = readDroidSessionId(transcriptPath);
|
|
10528
|
+
if (!nativeSessionId) {
|
|
10529
|
+
continue;
|
|
10530
|
+
}
|
|
10531
|
+
return {
|
|
10532
|
+
nativeSessionId,
|
|
10533
|
+
transcriptPath
|
|
10534
|
+
};
|
|
10535
|
+
} catch {
|
|
10536
|
+
continue;
|
|
10537
|
+
}
|
|
10538
|
+
}
|
|
10539
|
+
return null;
|
|
10540
|
+
}
|
|
10541
|
+
function createDroidHarness() {
|
|
10542
|
+
return {
|
|
10543
|
+
name: "droid",
|
|
10544
|
+
capabilities: {
|
|
10545
|
+
headless: true,
|
|
10546
|
+
interactive: true,
|
|
10547
|
+
preassignSessionId: true,
|
|
10548
|
+
maxTurns: false,
|
|
10549
|
+
budgetLimit: false,
|
|
10550
|
+
toolHooks: false,
|
|
10551
|
+
subagentVisibility: false,
|
|
10552
|
+
structuredOutput: true,
|
|
10553
|
+
permissionBypass: true
|
|
10554
|
+
},
|
|
10555
|
+
buildSpawnArgs(config) {
|
|
10556
|
+
const args = ["exec", config.prompt, "--output-format", "stream-json"];
|
|
10557
|
+
if (config.sessionId) {
|
|
10558
|
+
args.push("--session-id", config.sessionId);
|
|
10559
|
+
}
|
|
10560
|
+
args.push("--skip-permissions-unsafe", "--cwd", config.cwd);
|
|
10561
|
+
if (config.model) {
|
|
10562
|
+
args.push("--model", config.model);
|
|
10563
|
+
}
|
|
10564
|
+
if (config.extraArgs) {
|
|
10565
|
+
args.push(...config.extraArgs);
|
|
10566
|
+
}
|
|
10567
|
+
return args;
|
|
10568
|
+
},
|
|
10569
|
+
buildResumeArgs(nativeSessionId, config) {
|
|
10570
|
+
const args = [
|
|
10571
|
+
"exec",
|
|
10572
|
+
config.prompt ?? "Continue working",
|
|
10573
|
+
"--session-id",
|
|
10574
|
+
nativeSessionId,
|
|
10575
|
+
"--output-format",
|
|
10576
|
+
"stream-json",
|
|
10577
|
+
"--skip-permissions-unsafe"
|
|
10578
|
+
];
|
|
10579
|
+
if (config.extraArgs) {
|
|
10580
|
+
args.push(...config.extraArgs);
|
|
10581
|
+
}
|
|
10582
|
+
return args;
|
|
10583
|
+
},
|
|
10584
|
+
resolveTranscriptPath(nativeSessionId, cwd) {
|
|
10585
|
+
const scopedPath = buildScopedTranscriptPath(cwd, nativeSessionId);
|
|
10586
|
+
if (existsSync7(scopedPath)) {
|
|
10587
|
+
return scopedPath;
|
|
10588
|
+
}
|
|
10589
|
+
const legacyPath = buildLegacyTranscriptPath(nativeSessionId);
|
|
10590
|
+
if (existsSync7(legacyPath)) {
|
|
10591
|
+
return legacyPath;
|
|
10592
|
+
}
|
|
10593
|
+
return scopedPath;
|
|
10594
|
+
},
|
|
10595
|
+
createWatcher(transcriptPath) {
|
|
10596
|
+
return createJsonlTranscriptWatcher(transcriptPath, {
|
|
10597
|
+
createState: () => createDroidMapperContext({ transcriptPath }),
|
|
10598
|
+
map: (entry, state) => mapDroidEntry(entry, state)
|
|
10599
|
+
});
|
|
10600
|
+
},
|
|
10601
|
+
parseTranscript(content, options) {
|
|
10602
|
+
return parseDroidTranscript(content, { transcriptPath: options?.transcriptPath });
|
|
10603
|
+
},
|
|
10604
|
+
async isAvailable() {
|
|
10605
|
+
return spawnSync32("which", ["droid"], { stdio: "ignore" }).status === 0;
|
|
10606
|
+
}
|
|
10607
|
+
};
|
|
10608
|
+
}
|
|
10609
|
+
var TRANSCRIPT_DISCOVERY_PADDING_MS2 = 5 * 6e4;
|
|
10610
|
+
var DEFAULT_MAX_DISCOVERY_CANDIDATES2 = 20;
|
|
10611
|
+
var DEFAULT_GEMINI_MODEL = "gemini-3.1-pro-preview";
|
|
10612
|
+
function slugifyProjectName(name) {
|
|
10613
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
10614
|
+
}
|
|
10615
|
+
function getGeminiTmpRoot() {
|
|
10616
|
+
return join52(homedir42(), ".gemini", "tmp");
|
|
10617
|
+
}
|
|
10618
|
+
function getProjectSlug(cwd) {
|
|
10619
|
+
return slugifyProjectName(basename22(cwd));
|
|
10620
|
+
}
|
|
10621
|
+
function getGeminiChatsDir(cwd) {
|
|
10622
|
+
return join52(getGeminiTmpRoot(), getProjectSlug(cwd), "chats");
|
|
10623
|
+
}
|
|
10624
|
+
function listGeminiTranscriptPaths(cwd) {
|
|
10625
|
+
const chatsDir = getGeminiChatsDir(cwd);
|
|
10626
|
+
if (!existsSync8(chatsDir)) {
|
|
10627
|
+
return [];
|
|
10628
|
+
}
|
|
10629
|
+
return readdirSync4(chatsDir).filter((entry) => entry.startsWith("session-") && entry.endsWith(".json")).map((entry) => join52(chatsDir, entry)).sort((left, right) => right.localeCompare(left));
|
|
10630
|
+
}
|
|
10631
|
+
function readGeminiSessionId(transcriptPath) {
|
|
10632
|
+
try {
|
|
10633
|
+
const parsed = JSON.parse(readFileSync6(transcriptPath, "utf-8"));
|
|
10634
|
+
return typeof parsed.sessionId === "string" ? parsed.sessionId : null;
|
|
10635
|
+
} catch {
|
|
10636
|
+
return null;
|
|
10637
|
+
}
|
|
10638
|
+
}
|
|
10639
|
+
function parseGeminiSessionList(output) {
|
|
10640
|
+
const mapping = /* @__PURE__ */ new Map();
|
|
10641
|
+
for (const line of output.split("\n")) {
|
|
10642
|
+
const match = line.match(/^\s*(\d+)\.\s+.*\[(.+?)\]\s*$/);
|
|
10643
|
+
if (!match) {
|
|
10644
|
+
continue;
|
|
10645
|
+
}
|
|
10646
|
+
const index = match[1];
|
|
10647
|
+
const sessionId = match[2];
|
|
10648
|
+
if (index && sessionId) {
|
|
10649
|
+
mapping.set(sessionId, index);
|
|
10650
|
+
}
|
|
10651
|
+
}
|
|
10652
|
+
return mapping;
|
|
10653
|
+
}
|
|
10654
|
+
function parseStartedAtMs2(startedAt) {
|
|
10655
|
+
if (typeof startedAt === "number" && Number.isFinite(startedAt)) {
|
|
10656
|
+
return startedAt;
|
|
10657
|
+
}
|
|
10658
|
+
if (typeof startedAt === "string") {
|
|
10659
|
+
const parsed = new Date(startedAt).getTime();
|
|
10660
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
10661
|
+
}
|
|
10662
|
+
return null;
|
|
10663
|
+
}
|
|
10664
|
+
function isTranscriptRecentEnough2(transcriptPath, startedAt) {
|
|
10665
|
+
const startedAtMs = parseStartedAtMs2(startedAt);
|
|
10666
|
+
if (startedAtMs == null) {
|
|
10667
|
+
return true;
|
|
10668
|
+
}
|
|
10669
|
+
try {
|
|
10670
|
+
return statSync3(transcriptPath).mtimeMs >= startedAtMs - TRANSCRIPT_DISCOVERY_PADDING_MS2;
|
|
10671
|
+
} catch {
|
|
10672
|
+
return true;
|
|
10673
|
+
}
|
|
10674
|
+
}
|
|
10675
|
+
function resolveGeminiResumeTarget(nativeSessionId, cwd) {
|
|
10676
|
+
if (nativeSessionId === "latest" || /^\d+$/.test(nativeSessionId)) {
|
|
10677
|
+
return nativeSessionId;
|
|
10678
|
+
}
|
|
10679
|
+
const result = spawnSync4("gemini", ["--list-sessions"], {
|
|
10680
|
+
cwd,
|
|
10681
|
+
encoding: "utf-8",
|
|
10682
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
10683
|
+
});
|
|
10684
|
+
if (result.status !== 0) {
|
|
10685
|
+
return nativeSessionId;
|
|
10686
|
+
}
|
|
10687
|
+
const sessionIndex = parseGeminiSessionList(result.stdout).get(nativeSessionId);
|
|
10688
|
+
return sessionIndex ?? nativeSessionId;
|
|
10689
|
+
}
|
|
10690
|
+
function discoverGeminiNativeSession(cwd, options) {
|
|
10691
|
+
const excludedPaths = options?.excludeTranscriptPaths;
|
|
10692
|
+
for (const transcriptPath of listGeminiTranscriptPaths(cwd)) {
|
|
10693
|
+
if (excludedPaths?.has(transcriptPath)) {
|
|
10694
|
+
continue;
|
|
10695
|
+
}
|
|
10696
|
+
const nativeSessionId = readGeminiSessionId(transcriptPath);
|
|
10697
|
+
if (!nativeSessionId) {
|
|
10698
|
+
continue;
|
|
10699
|
+
}
|
|
10700
|
+
return { nativeSessionId, transcriptPath };
|
|
10701
|
+
}
|
|
10702
|
+
return null;
|
|
10703
|
+
}
|
|
10704
|
+
function discoverGeminiNativeSessionByOrbhSessionId(cwd, orbhSessionId, options) {
|
|
10705
|
+
const transcriptPaths = listGeminiTranscriptPaths(cwd).slice(0, options?.maxCandidates ?? DEFAULT_MAX_DISCOVERY_CANDIDATES2);
|
|
10706
|
+
for (const transcriptPath of transcriptPaths) {
|
|
10707
|
+
if (!isTranscriptRecentEnough2(transcriptPath, options?.startedAt)) {
|
|
10708
|
+
continue;
|
|
10709
|
+
}
|
|
10710
|
+
try {
|
|
10711
|
+
const content = readFileSync6(transcriptPath, "utf-8");
|
|
10712
|
+
if (!content.includes(orbhSessionId)) {
|
|
10713
|
+
continue;
|
|
10714
|
+
}
|
|
10715
|
+
const parsed = JSON.parse(content);
|
|
10716
|
+
if (typeof parsed.sessionId !== "string") {
|
|
10717
|
+
continue;
|
|
10718
|
+
}
|
|
10719
|
+
return {
|
|
10720
|
+
nativeSessionId: parsed.sessionId,
|
|
10721
|
+
transcriptPath
|
|
10722
|
+
};
|
|
10723
|
+
} catch {
|
|
10724
|
+
continue;
|
|
10725
|
+
}
|
|
10726
|
+
}
|
|
10727
|
+
return null;
|
|
10728
|
+
}
|
|
10729
|
+
async function waitForGeminiNativeSession(cwd, timeoutMs, pollMs, options) {
|
|
10730
|
+
const deadline = Date.now() + timeoutMs;
|
|
10731
|
+
while (Date.now() <= deadline) {
|
|
10732
|
+
const discovered = discoverGeminiNativeSession(cwd, options);
|
|
10733
|
+
if (discovered) {
|
|
10734
|
+
return discovered;
|
|
10735
|
+
}
|
|
10736
|
+
await new Promise((resolve11) => setTimeout(resolve11, pollMs));
|
|
10737
|
+
}
|
|
10738
|
+
return null;
|
|
10739
|
+
}
|
|
10740
|
+
function createGeminiHarness() {
|
|
10741
|
+
return {
|
|
10742
|
+
name: "gemini",
|
|
10743
|
+
capabilities: {
|
|
10744
|
+
headless: true,
|
|
10745
|
+
interactive: true,
|
|
10746
|
+
preassignSessionId: false,
|
|
10747
|
+
maxTurns: false,
|
|
10748
|
+
budgetLimit: false,
|
|
10749
|
+
toolHooks: false,
|
|
10750
|
+
subagentVisibility: false,
|
|
8702
10751
|
structuredOutput: true,
|
|
8703
10752
|
permissionBypass: true
|
|
8704
10753
|
},
|
|
8705
10754
|
buildSpawnArgs(config) {
|
|
8706
|
-
const args = ["
|
|
8707
|
-
|
|
8708
|
-
args.push("--model", config.model);
|
|
8709
|
-
}
|
|
10755
|
+
const args = ["-p", config.prompt, "--yolo", "-o", "stream-json"];
|
|
10756
|
+
args.push("--model", config.model || DEFAULT_GEMINI_MODEL);
|
|
8710
10757
|
if (config.extraArgs) {
|
|
8711
10758
|
args.push(...config.extraArgs);
|
|
8712
10759
|
}
|
|
8713
10760
|
return args;
|
|
8714
10761
|
},
|
|
8715
10762
|
buildResumeArgs(nativeSessionId, config) {
|
|
8716
|
-
const args = ["
|
|
8717
|
-
if (config.prompt) {
|
|
8718
|
-
args.push(config.prompt);
|
|
8719
|
-
}
|
|
10763
|
+
const args = ["-p", config.prompt ?? "Continue working", "--yolo", "-o", "stream-json", "--model", DEFAULT_GEMINI_MODEL, "--resume", resolveGeminiResumeTarget(nativeSessionId, config.cwd)];
|
|
8720
10764
|
if (config.extraArgs) {
|
|
8721
10765
|
args.push(...config.extraArgs);
|
|
8722
10766
|
}
|
|
8723
10767
|
return args;
|
|
8724
10768
|
},
|
|
8725
|
-
resolveTranscriptPath(nativeSessionId) {
|
|
8726
|
-
const
|
|
8727
|
-
const
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
if (entry.includes(nativeSessionId) && entry.endsWith(".jsonl")) {
|
|
8734
|
-
return join32(directory, entry);
|
|
8735
|
-
}
|
|
10769
|
+
resolveTranscriptPath(nativeSessionId, cwd) {
|
|
10770
|
+
const prefix = nativeSessionId.slice(0, 8);
|
|
10771
|
+
for (const transcriptPath of listGeminiTranscriptPaths(cwd)) {
|
|
10772
|
+
if (basename22(transcriptPath).includes(prefix)) {
|
|
10773
|
+
return transcriptPath;
|
|
10774
|
+
}
|
|
10775
|
+
if (readGeminiSessionId(transcriptPath) === nativeSessionId) {
|
|
10776
|
+
return transcriptPath;
|
|
8736
10777
|
}
|
|
8737
10778
|
}
|
|
8738
10779
|
return null;
|
|
8739
10780
|
},
|
|
8740
10781
|
createWatcher(transcriptPath) {
|
|
8741
|
-
return
|
|
8742
|
-
createState: () =>
|
|
8743
|
-
|
|
10782
|
+
return createJsonSessionWatcher(transcriptPath, {
|
|
10783
|
+
createState: () => createGeminiMapperContext(),
|
|
10784
|
+
getMessages: (payload) => Array.isArray(payload.messages) ? payload.messages.filter((message) => typeof message === "object" && message !== null && !Array.isArray(message)) : [],
|
|
10785
|
+
map: (message, state) => mapGeminiMessageEntry(message, state)
|
|
8744
10786
|
});
|
|
8745
10787
|
},
|
|
8746
10788
|
parseTranscript(content) {
|
|
8747
|
-
return
|
|
10789
|
+
return parseGeminiTranscript(content);
|
|
8748
10790
|
},
|
|
8749
10791
|
async isAvailable() {
|
|
8750
|
-
return
|
|
10792
|
+
return spawnSync4("which", ["gemini"], { stdio: "ignore" }).status === 0;
|
|
8751
10793
|
}
|
|
8752
10794
|
};
|
|
8753
10795
|
}
|
|
@@ -8763,8 +10805,14 @@ function listHarnesses() {
|
|
|
8763
10805
|
}
|
|
8764
10806
|
registerHarness(createClaudeHarness());
|
|
8765
10807
|
registerHarness(createCodexHarness());
|
|
10808
|
+
registerHarness(createDroidHarness());
|
|
10809
|
+
registerHarness(createGeminiHarness());
|
|
8766
10810
|
|
|
8767
10811
|
// src/commands/export-session.ts
|
|
10812
|
+
import { writeFile as writeFile3, mkdir as mkdir5, stat as stat5, readFile as readFile6 } from "fs/promises";
|
|
10813
|
+
import { join as join11 } from "path";
|
|
10814
|
+
import { homedir as homedir6 } from "os";
|
|
10815
|
+
import pc27 from "picocolors";
|
|
8768
10816
|
function resolveProjectDir(cwd) {
|
|
8769
10817
|
return join11(homedir6(), ".claude", "projects", cwd.replace(/[^a-zA-Z0-9\-_]/g, "-"));
|
|
8770
10818
|
}
|
|
@@ -8785,12 +10833,22 @@ function buildFrontmatter(sessionId) {
|
|
|
8785
10833
|
return lines.join("\n");
|
|
8786
10834
|
}
|
|
8787
10835
|
async function exportSession(flintPath, sessionId) {
|
|
10836
|
+
const existingPath = join11(flintPath, "Mesh", "Agents", "Claude Code", `${sessionId}.md`);
|
|
10837
|
+
try {
|
|
10838
|
+
const existingContent = await readFile6(existingPath, "utf-8");
|
|
10839
|
+
const frontmatterMatch = existingContent.match(/^---\n([\s\S]*?)\n---/);
|
|
10840
|
+
if (frontmatterMatch && !frontmatterMatch[1].includes("live: true")) {
|
|
10841
|
+
console.log(pc27.dim("Session already exported by server, skipping CLI export."));
|
|
10842
|
+
return;
|
|
10843
|
+
}
|
|
10844
|
+
} catch {
|
|
10845
|
+
}
|
|
8788
10846
|
const projectDir = resolveProjectDir(flintPath);
|
|
8789
10847
|
let transcriptPath = null;
|
|
8790
10848
|
for (const name of [`${sessionId}.jsonl`, `transcript-${sessionId}.jsonl`]) {
|
|
8791
10849
|
const filePath = join11(projectDir, name);
|
|
8792
10850
|
try {
|
|
8793
|
-
await
|
|
10851
|
+
await stat5(filePath);
|
|
8794
10852
|
transcriptPath = filePath;
|
|
8795
10853
|
break;
|
|
8796
10854
|
} catch {
|
|
@@ -8817,7 +10875,7 @@ async function exportSession(flintPath, sessionId) {
|
|
|
8817
10875
|
}
|
|
8818
10876
|
|
|
8819
10877
|
// src/commands/export-codex-session.ts
|
|
8820
|
-
import { writeFile as writeFile4, mkdir as mkdir6, readFile as readFile7, readdir as readdir2, stat as
|
|
10878
|
+
import { writeFile as writeFile4, mkdir as mkdir6, readFile as readFile7, readdir as readdir2, stat as stat6 } from "fs/promises";
|
|
8821
10879
|
import { join as join12 } from "path";
|
|
8822
10880
|
import { homedir as homedir7 } from "os";
|
|
8823
10881
|
import pc28 from "picocolors";
|
|
@@ -8838,7 +10896,7 @@ async function findCodexTranscript(sessionId, startedAfter) {
|
|
|
8838
10896
|
if (!file.endsWith(".jsonl")) continue;
|
|
8839
10897
|
if (file.includes(sessionId)) {
|
|
8840
10898
|
const filePath = join12(dayDir, file);
|
|
8841
|
-
const s = await
|
|
10899
|
+
const s = await stat6(filePath);
|
|
8842
10900
|
if (s.mtimeMs >= startedAfter) {
|
|
8843
10901
|
return filePath;
|
|
8844
10902
|
}
|
|
@@ -8868,6 +10926,16 @@ function buildFrontmatter2(sessionId) {
|
|
|
8868
10926
|
return lines.join("\n");
|
|
8869
10927
|
}
|
|
8870
10928
|
async function exportCodexSession(flintPath, sessionId, startedAt) {
|
|
10929
|
+
const existingPath = join12(flintPath, "Mesh", "Agents", "Codex", `${sessionId}.md`);
|
|
10930
|
+
try {
|
|
10931
|
+
const existingContent = await readFile7(existingPath, "utf-8");
|
|
10932
|
+
const frontmatterMatch = existingContent.match(/^---\n([\s\S]*?)\n---/);
|
|
10933
|
+
if (frontmatterMatch && !frontmatterMatch[1].includes("live: true")) {
|
|
10934
|
+
console.log(pc28.dim("Session already exported by server, skipping CLI export."));
|
|
10935
|
+
return;
|
|
10936
|
+
}
|
|
10937
|
+
} catch {
|
|
10938
|
+
}
|
|
8871
10939
|
const transcriptPath = await findCodexTranscript(sessionId, startedAt);
|
|
8872
10940
|
if (!transcriptPath) {
|
|
8873
10941
|
console.log(pc28.dim("No Codex session transcript found to export."));
|
|
@@ -8907,6 +10975,62 @@ function askYesNo(question) {
|
|
|
8907
10975
|
});
|
|
8908
10976
|
});
|
|
8909
10977
|
}
|
|
10978
|
+
function getSessionsDir(flintPath) {
|
|
10979
|
+
return join13(flintPath, ".flint", "sessions");
|
|
10980
|
+
}
|
|
10981
|
+
function buildSessionFrontmatter(sessionId, runtime2) {
|
|
10982
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
10983
|
+
const runtimeTag = runtime2 === "claude" ? "claude-code" : runtime2;
|
|
10984
|
+
const runtimeTitle = runtime2 === "claude" ? "Claude Code" : runtime2.charAt(0).toUpperCase() + runtime2.slice(1);
|
|
10985
|
+
return [
|
|
10986
|
+
"---",
|
|
10987
|
+
`id: ${sessionId}`,
|
|
10988
|
+
"tags:",
|
|
10989
|
+
' - "#agent/session"',
|
|
10990
|
+
` - "#agent/${runtimeTag}"`,
|
|
10991
|
+
`date: ${now}`,
|
|
10992
|
+
"---",
|
|
10993
|
+
"",
|
|
10994
|
+
`# ${runtimeTitle} Session`,
|
|
10995
|
+
""
|
|
10996
|
+
].join("\n");
|
|
10997
|
+
}
|
|
10998
|
+
function exportOrbhSessionTranscript(session, flintPath) {
|
|
10999
|
+
const harness = getHarness(session.runtime);
|
|
11000
|
+
if (!harness) {
|
|
11001
|
+
return;
|
|
11002
|
+
}
|
|
11003
|
+
const run = getCurrentRun2(session);
|
|
11004
|
+
const nativeId = run?.nativeSessionId ?? session.id;
|
|
11005
|
+
const transcriptPath = harness.resolveTranscriptPath(nativeId, flintPath);
|
|
11006
|
+
if (!transcriptPath) {
|
|
11007
|
+
console.log(pc29.dim("No transcript found to export."));
|
|
11008
|
+
return;
|
|
11009
|
+
}
|
|
11010
|
+
let content;
|
|
11011
|
+
try {
|
|
11012
|
+
content = readFileSync7(transcriptPath, "utf-8");
|
|
11013
|
+
} catch {
|
|
11014
|
+
console.log(pc29.dim("Could not read transcript file."));
|
|
11015
|
+
return;
|
|
11016
|
+
}
|
|
11017
|
+
const entries = harness.parseTranscript(content);
|
|
11018
|
+
if (entries.length === 0) {
|
|
11019
|
+
console.log(pc29.dim("Transcript is empty, skipping export."));
|
|
11020
|
+
return;
|
|
11021
|
+
}
|
|
11022
|
+
const body = formatTranscriptMarkdown(entries);
|
|
11023
|
+
const markdown = buildSessionFrontmatter(nativeId, session.runtime) + body;
|
|
11024
|
+
const runtimeDir = session.runtime === "claude" ? "Claude Code" : session.runtime.charAt(0).toUpperCase() + session.runtime.slice(1);
|
|
11025
|
+
const outputDir = join13(flintPath, "Mesh", "Agents", runtimeDir);
|
|
11026
|
+
mkdirSync3(outputDir, { recursive: true });
|
|
11027
|
+
const outputPath = join13(outputDir, `${nativeId}.md`);
|
|
11028
|
+
writeFileSync2(outputPath, markdown, "utf-8");
|
|
11029
|
+
console.log(pc29.green(`Session exported \u2192 Mesh/Agents/${runtimeDir}/${nativeId}.md`));
|
|
11030
|
+
}
|
|
11031
|
+
function buildGeminiInitPrompt(sessionId) {
|
|
11032
|
+
return `init, you are a gemini session, your session id is ${sessionId}, please read init-f.md and (System) Flint Init.md`;
|
|
11033
|
+
}
|
|
8910
11034
|
var CLIENT_INFO = {
|
|
8911
11035
|
name: "flint_code",
|
|
8912
11036
|
title: "Flint Code",
|
|
@@ -8914,7 +11038,7 @@ var CLIENT_INFO = {
|
|
|
8914
11038
|
};
|
|
8915
11039
|
async function bootstrapCodexSession(cwd, initPrompt) {
|
|
8916
11040
|
return new Promise((resolve11, reject) => {
|
|
8917
|
-
const proc =
|
|
11041
|
+
const proc = spawn5("codex", ["app-server"], {
|
|
8918
11042
|
stdio: ["pipe", "pipe", "pipe"],
|
|
8919
11043
|
cwd
|
|
8920
11044
|
});
|
|
@@ -8934,7 +11058,7 @@ async function bootstrapCodexSession(cwd, initPrompt) {
|
|
|
8934
11058
|
let pollInterval = null;
|
|
8935
11059
|
const startPolling = () => {
|
|
8936
11060
|
pollInterval = setInterval(() => {
|
|
8937
|
-
if (sessionPath &&
|
|
11061
|
+
if (sessionPath && existsSync9(sessionPath)) {
|
|
8938
11062
|
if (pollInterval) clearInterval(pollInterval);
|
|
8939
11063
|
send({ method: "turn/interrupt", id: 4, params: { threadId } });
|
|
8940
11064
|
setTimeout(() => {
|
|
@@ -8999,7 +11123,7 @@ codeCommand.command("claude").description("Open Claude Code TUI").option("-p, --
|
|
|
8999
11123
|
sessionId = randomUUID3();
|
|
9000
11124
|
args.push("--session-id", sessionId, await buildClaudeInitPrompt(sessionId));
|
|
9001
11125
|
}
|
|
9002
|
-
const child =
|
|
11126
|
+
const child = spawn5("claude", args, {
|
|
9003
11127
|
cwd: flintPath,
|
|
9004
11128
|
stdio: "inherit"
|
|
9005
11129
|
});
|
|
@@ -9068,7 +11192,7 @@ codeCommand.command("codex").description("Open Codex TUI with session tracking")
|
|
|
9068
11192
|
console.log(pc29.green(`Session ID: ${threadId}`));
|
|
9069
11193
|
console.log("");
|
|
9070
11194
|
const resumePrompt = options.continue ? `continuing session ${threadId}` : `your session id is ${threadId}`;
|
|
9071
|
-
const child =
|
|
11195
|
+
const child = spawn5("codex", [
|
|
9072
11196
|
"resume",
|
|
9073
11197
|
threadId,
|
|
9074
11198
|
"--dangerously-bypass-approvals-and-sandbox",
|
|
@@ -9102,7 +11226,7 @@ codeCommand.command("codex").description("Open Codex TUI with session tracking")
|
|
|
9102
11226
|
process.exit(1);
|
|
9103
11227
|
}
|
|
9104
11228
|
});
|
|
9105
|
-
codeCommand.command("gemini").description("Open Gemini CLI with session tracking").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("-r, --resume <id>", "Resume a previous Gemini session").action(async (options) => {
|
|
11229
|
+
codeCommand.command("gemini").description("Open Gemini CLI with Orbh session tracking").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("-r, --resume <id>", "Resume a previous Gemini or Orbh session").action(async (options) => {
|
|
9106
11230
|
try {
|
|
9107
11231
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9108
11232
|
if (!flintPath) {
|
|
@@ -9111,15 +11235,75 @@ codeCommand.command("gemini").description("Open Gemini CLI with session tracking
|
|
|
9111
11235
|
);
|
|
9112
11236
|
process.exit(1);
|
|
9113
11237
|
}
|
|
9114
|
-
const
|
|
11238
|
+
const sessionsDir = getSessionsDir(flintPath);
|
|
11239
|
+
let session;
|
|
11240
|
+
let args;
|
|
11241
|
+
let nativeDiscovery = null;
|
|
9115
11242
|
if (options.resume) {
|
|
9116
|
-
|
|
11243
|
+
const existing = resolveSession2(sessionsDir, options.resume);
|
|
11244
|
+
if (existing) {
|
|
11245
|
+
if (existing.runtime !== "gemini") {
|
|
11246
|
+
console.error(pc29.red(`Error: Session ${options.resume} is a ${existing.runtime} session, not gemini.`));
|
|
11247
|
+
process.exit(1);
|
|
11248
|
+
}
|
|
11249
|
+
session = existing;
|
|
11250
|
+
const lastRun = getCurrentRun2(session);
|
|
11251
|
+
const nativeResumeTarget = resolveGeminiResumeTarget(lastRun?.nativeSessionId ?? "latest", flintPath);
|
|
11252
|
+
addRun2(session, {
|
|
11253
|
+
nativeSessionId: lastRun?.nativeSessionId ?? null,
|
|
11254
|
+
continuesRunId: lastRun?.id ?? null
|
|
11255
|
+
});
|
|
11256
|
+
session.status = "in-progress";
|
|
11257
|
+
writeSession(sessionsDir, session);
|
|
11258
|
+
args = ["--yolo", "--resume", nativeResumeTarget];
|
|
11259
|
+
} else {
|
|
11260
|
+
session = createSession2(sessionsDir, "gemini", "", {
|
|
11261
|
+
title: "(Interactive) Gemini Session",
|
|
11262
|
+
description: "Interactive Gemini CLI session from flint code gemini"
|
|
11263
|
+
});
|
|
11264
|
+
addRun2(session, { nativeSessionId: options.resume });
|
|
11265
|
+
session.status = "in-progress";
|
|
11266
|
+
writeSession(sessionsDir, session);
|
|
11267
|
+
args = ["--yolo", "--resume", options.resume];
|
|
11268
|
+
}
|
|
11269
|
+
} else {
|
|
11270
|
+
session = createSession2(sessionsDir, "gemini", "", {
|
|
11271
|
+
title: "(Interactive) Gemini Session",
|
|
11272
|
+
description: "Interactive Gemini CLI session from flint code gemini"
|
|
11273
|
+
});
|
|
11274
|
+
addRun2(session, { nativeSessionId: null });
|
|
11275
|
+
session.status = "in-progress";
|
|
11276
|
+
writeSession(sessionsDir, session);
|
|
11277
|
+
const knownTranscriptPaths = new Set(listGeminiTranscriptPaths(flintPath));
|
|
11278
|
+
args = ["--yolo", "--prompt-interactive", buildGeminiInitPrompt(session.id)];
|
|
11279
|
+
nativeDiscovery = waitForGeminiNativeSession(flintPath, 3e4, 250, {
|
|
11280
|
+
excludeTranscriptPaths: knownTranscriptPaths
|
|
11281
|
+
}).then((discovered) => {
|
|
11282
|
+
if (!discovered) {
|
|
11283
|
+
return;
|
|
11284
|
+
}
|
|
11285
|
+
const fresh = readSession2(sessionsDir, session.id);
|
|
11286
|
+
if (!fresh) {
|
|
11287
|
+
return;
|
|
11288
|
+
}
|
|
11289
|
+
updateCurrentRun2(fresh, { nativeSessionId: discovered.nativeSessionId });
|
|
11290
|
+
writeSession(sessionsDir, fresh);
|
|
11291
|
+
});
|
|
9117
11292
|
}
|
|
9118
|
-
const child =
|
|
11293
|
+
const child = spawn5("gemini", args, {
|
|
9119
11294
|
cwd: flintPath,
|
|
9120
|
-
stdio: "inherit"
|
|
11295
|
+
stdio: "inherit",
|
|
11296
|
+
env: { ...process.env, ORBH_SESSION_ID: session.id }
|
|
9121
11297
|
});
|
|
11298
|
+
if (child.pid) {
|
|
11299
|
+
updateCurrentRun2(session, { pid: child.pid });
|
|
11300
|
+
session.status = "in-progress";
|
|
11301
|
+
writeSession(sessionsDir, session);
|
|
11302
|
+
}
|
|
9122
11303
|
child.on("error", (err) => {
|
|
11304
|
+
updateCurrentRun2(session, { status: "failed", ended: (/* @__PURE__ */ new Date()).toISOString() });
|
|
11305
|
+
session.status = "failed";
|
|
11306
|
+
writeSession(sessionsDir, session);
|
|
9123
11307
|
if (err.code === "ENOENT") {
|
|
9124
11308
|
console.error(pc29.red("Error: Gemini CLI is not installed."));
|
|
9125
11309
|
console.log("");
|
|
@@ -9130,7 +11314,34 @@ codeCommand.command("gemini").description("Open Gemini CLI with session tracking
|
|
|
9130
11314
|
console.error(pc29.red(`Error: ${err.message}`));
|
|
9131
11315
|
process.exit(1);
|
|
9132
11316
|
});
|
|
9133
|
-
child.on("exit", (code) => {
|
|
11317
|
+
child.on("exit", async (code) => {
|
|
11318
|
+
if (nativeDiscovery) {
|
|
11319
|
+
await Promise.race([
|
|
11320
|
+
nativeDiscovery,
|
|
11321
|
+
new Promise((resolve11) => setTimeout(resolve11, 500))
|
|
11322
|
+
]);
|
|
11323
|
+
}
|
|
11324
|
+
const fresh = readSession2(sessionsDir, session.id) ?? session;
|
|
11325
|
+
updateCurrentRun2(fresh, {
|
|
11326
|
+
ended: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11327
|
+
exitCode: code ?? null,
|
|
11328
|
+
status: code === 0 ? "completed" : "failed"
|
|
11329
|
+
});
|
|
11330
|
+
fresh.status = code === 0 ? "finished" : "failed";
|
|
11331
|
+
writeSession(sessionsDir, fresh);
|
|
11332
|
+
try {
|
|
11333
|
+
const nativeId = getCurrentRun2(fresh)?.nativeSessionId ?? fresh.id;
|
|
11334
|
+
if (sessionReferencedInMesh(flintPath, fresh.id) || sessionReferencedInMesh(flintPath, nativeId)) {
|
|
11335
|
+
exportOrbhSessionTranscript(fresh, flintPath);
|
|
11336
|
+
} else {
|
|
11337
|
+
const save = await askYesNo(pc29.dim("Save session transcript? (y/N) "));
|
|
11338
|
+
if (save) {
|
|
11339
|
+
exportOrbhSessionTranscript(fresh, flintPath);
|
|
11340
|
+
}
|
|
11341
|
+
}
|
|
11342
|
+
} catch (err) {
|
|
11343
|
+
console.error(pc29.dim(`Session export failed: ${err instanceof Error ? err.message : err}`));
|
|
11344
|
+
}
|
|
9134
11345
|
process.exit(code || 0);
|
|
9135
11346
|
});
|
|
9136
11347
|
} catch (err) {
|
|
@@ -9143,8 +11354,8 @@ codeCommand.command("gemini").description("Open Gemini CLI with session tracking
|
|
|
9143
11354
|
// src/commands/helper.ts
|
|
9144
11355
|
import { Command as Command25 } from "commander";
|
|
9145
11356
|
import pc30 from "picocolors";
|
|
9146
|
-
import { readdirSync as
|
|
9147
|
-
import { join as join14, basename as
|
|
11357
|
+
import { readdirSync as readdirSync5, existsSync as existsSync10, statSync as statSync4 } from "fs";
|
|
11358
|
+
import { join as join14, basename as basename5 } from "path";
|
|
9148
11359
|
function extractNumberFromFile(filename, typeName) {
|
|
9149
11360
|
const regex = new RegExp(`^\\(${typeName}\\)\\s+(\\d+)`, "i");
|
|
9150
11361
|
const match = filename.match(regex);
|
|
@@ -9152,18 +11363,18 @@ function extractNumberFromFile(filename, typeName) {
|
|
|
9152
11363
|
}
|
|
9153
11364
|
function collectFilesRecursively(dirPath) {
|
|
9154
11365
|
const files = [];
|
|
9155
|
-
if (!
|
|
11366
|
+
if (!existsSync10(dirPath)) {
|
|
9156
11367
|
return files;
|
|
9157
11368
|
}
|
|
9158
|
-
const entries =
|
|
11369
|
+
const entries = readdirSync5(dirPath);
|
|
9159
11370
|
for (const entry of entries) {
|
|
9160
11371
|
const fullPath = join14(dirPath, entry);
|
|
9161
11372
|
try {
|
|
9162
|
-
const
|
|
9163
|
-
if (
|
|
11373
|
+
const stat9 = statSync4(fullPath);
|
|
11374
|
+
if (stat9.isDirectory()) {
|
|
9164
11375
|
files.push(...collectFilesRecursively(fullPath));
|
|
9165
|
-
} else if (
|
|
9166
|
-
files.push(
|
|
11376
|
+
} else if (stat9.isFile()) {
|
|
11377
|
+
files.push(basename5(fullPath));
|
|
9167
11378
|
}
|
|
9168
11379
|
} catch {
|
|
9169
11380
|
continue;
|
|
@@ -9173,7 +11384,7 @@ function collectFilesRecursively(dirPath) {
|
|
|
9173
11384
|
}
|
|
9174
11385
|
function getNextNumber(flintPath, typeName) {
|
|
9175
11386
|
const meshDir = join14(flintPath, "Mesh");
|
|
9176
|
-
if (!
|
|
11387
|
+
if (!existsSync10(meshDir)) {
|
|
9177
11388
|
return 1;
|
|
9178
11389
|
}
|
|
9179
11390
|
const allFiles = collectFilesRecursively(meshDir);
|
|
@@ -9340,7 +11551,7 @@ var resolveCommand = new Command27("resolve").description("Resolve a reference t
|
|
|
9340
11551
|
// src/commands/fulfill.ts
|
|
9341
11552
|
import { Command as Command28 } from "commander";
|
|
9342
11553
|
import pc33 from "picocolors";
|
|
9343
|
-
import { stat as
|
|
11554
|
+
import { stat as stat7 } from "fs/promises";
|
|
9344
11555
|
import { resolve as resolve8 } from "path";
|
|
9345
11556
|
import { homedir as homedir8 } from "os";
|
|
9346
11557
|
function expandPath3(p) {
|
|
@@ -9349,7 +11560,7 @@ function expandPath3(p) {
|
|
|
9349
11560
|
}
|
|
9350
11561
|
async function pathExists(p) {
|
|
9351
11562
|
try {
|
|
9352
|
-
await
|
|
11563
|
+
await stat7(p);
|
|
9353
11564
|
return true;
|
|
9354
11565
|
} catch {
|
|
9355
11566
|
return false;
|
|
@@ -9456,7 +11667,7 @@ function prompt5(message) {
|
|
|
9456
11667
|
// src/commands/update.ts
|
|
9457
11668
|
import { Command as Command29 } from "commander";
|
|
9458
11669
|
import pc34 from "picocolors";
|
|
9459
|
-
import { readFileSync as
|
|
11670
|
+
import { readFileSync as readFileSync8, existsSync as existsSync11 } from "fs";
|
|
9460
11671
|
import { dirname as dirname3, join as join15 } from "path";
|
|
9461
11672
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9462
11673
|
import { execSync as execSync4 } from "child_process";
|
|
@@ -9465,8 +11676,8 @@ var __dirname2 = dirname3(fileURLToPath2(import.meta.url));
|
|
|
9465
11676
|
function readPkgVersion() {
|
|
9466
11677
|
for (const rel of ["../..", ".."]) {
|
|
9467
11678
|
const p = join15(__dirname2, rel, "package.json");
|
|
9468
|
-
if (
|
|
9469
|
-
return JSON.parse(
|
|
11679
|
+
if (existsSync11(p)) {
|
|
11680
|
+
return JSON.parse(readFileSync8(p, "utf-8")).version;
|
|
9470
11681
|
}
|
|
9471
11682
|
}
|
|
9472
11683
|
throw new Error("Could not determine current version");
|
|
@@ -9541,11 +11752,11 @@ var updateCommand = new Command29("update").description("Update flint-cli to the
|
|
|
9541
11752
|
import { Command as Command30 } from "commander";
|
|
9542
11753
|
import pc35 from "picocolors";
|
|
9543
11754
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
9544
|
-
import { copyFile as copyFile2, mkdir as mkdir7, writeFile as writeFile5, unlink as unlink2, stat as
|
|
9545
|
-
import { join as join16, basename as
|
|
9546
|
-
async function exists3(
|
|
11755
|
+
import { copyFile as copyFile2, mkdir as mkdir7, writeFile as writeFile5, unlink as unlink2, stat as stat8 } from "fs/promises";
|
|
11756
|
+
import { join as join16, basename as basename6, resolve as resolve9 } from "path";
|
|
11757
|
+
async function exists3(path5) {
|
|
9547
11758
|
try {
|
|
9548
|
-
await
|
|
11759
|
+
await stat8(path5);
|
|
9549
11760
|
return true;
|
|
9550
11761
|
} catch {
|
|
9551
11762
|
return false;
|
|
@@ -9574,7 +11785,7 @@ var sendCommand = new Command30("send").description("Send files to another Flint
|
|
|
9574
11785
|
const copyFileNames = /* @__PURE__ */ new Set();
|
|
9575
11786
|
if (options.copy) {
|
|
9576
11787
|
for (const cf of options.copy) {
|
|
9577
|
-
copyFileNames.add(
|
|
11788
|
+
copyFileNames.add(basename6(resolve9(cf)));
|
|
9578
11789
|
}
|
|
9579
11790
|
}
|
|
9580
11791
|
const moveFiles = [];
|
|
@@ -9585,7 +11796,7 @@ var sendCommand = new Command30("send").description("Send files to another Flint
|
|
|
9585
11796
|
console.error(pc35.red(`Error: File not found: ${file}`));
|
|
9586
11797
|
process.exit(1);
|
|
9587
11798
|
}
|
|
9588
|
-
const fileName =
|
|
11799
|
+
const fileName = basename6(file);
|
|
9589
11800
|
const entry = { sourcePath, fileName };
|
|
9590
11801
|
if (copyFileNames.has(fileName)) {
|
|
9591
11802
|
copyFiles.push(entry);
|
|
@@ -9596,8 +11807,8 @@ var sendCommand = new Command30("send").description("Send files to another Flint
|
|
|
9596
11807
|
if (options.copy) {
|
|
9597
11808
|
for (const cf of options.copy) {
|
|
9598
11809
|
const sourcePath = resolve9(cf);
|
|
9599
|
-
const fileName =
|
|
9600
|
-
if (files.some((f) =>
|
|
11810
|
+
const fileName = basename6(cf);
|
|
11811
|
+
if (files.some((f) => basename6(resolve9(f)) === fileName)) continue;
|
|
9601
11812
|
if (!await exists3(sourcePath)) {
|
|
9602
11813
|
console.error(pc35.red(`Error: Copy file not found: ${cf}`));
|
|
9603
11814
|
process.exit(1);
|
|
@@ -9622,7 +11833,7 @@ var sendCommand = new Command30("send").description("Send files to another Flint
|
|
|
9622
11833
|
console.log();
|
|
9623
11834
|
let sourceFlintName = "Unknown";
|
|
9624
11835
|
try {
|
|
9625
|
-
const { readFlintToml: readFlintToml3 } = await import("./dist-
|
|
11836
|
+
const { readFlintToml: readFlintToml3 } = await import("./dist-RGQKIZQW.js");
|
|
9626
11837
|
const toml = await readFlintToml3(flintPath);
|
|
9627
11838
|
if (toml?.flint?.name) {
|
|
9628
11839
|
sourceFlintName = toml.flint.name;
|
|
@@ -9721,7 +11932,7 @@ var whoamiCommand = new Command31("whoami").description("Show the current person
|
|
|
9721
11932
|
// src/commands/migrate.ts
|
|
9722
11933
|
import { Command as Command32 } from "commander";
|
|
9723
11934
|
import pc37 from "picocolors";
|
|
9724
|
-
var migrateCommand = new Command32("migrate").description("Run pending workspace migrations").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--dry-run", "Show pending migrations without running them").action(async (options) => {
|
|
11935
|
+
var migrateCommand = new Command32("migrate").description("Run pending workspace migrations").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--dry-run", "Show pending migrations without running them").option("--only <id>", "Run a single migration by ID (no version bump)").option("--list", "List all available migrations from the current version onwards").action(async (options) => {
|
|
9725
11936
|
try {
|
|
9726
11937
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9727
11938
|
if (!flintPath) {
|
|
@@ -9730,6 +11941,75 @@ var migrateCommand = new Command32("migrate").description("Run pending workspace
|
|
|
9730
11941
|
);
|
|
9731
11942
|
process.exit(1);
|
|
9732
11943
|
}
|
|
11944
|
+
if (options.list) {
|
|
11945
|
+
const check2 = await checkMigrations(flintPath);
|
|
11946
|
+
const steps = getVersionSteps();
|
|
11947
|
+
console.log(pc37.bold("\nAll migrations from current version onwards:\n"));
|
|
11948
|
+
let hasAny = false;
|
|
11949
|
+
for (const step2 of steps) {
|
|
11950
|
+
const stepMigrations = getMigrationsForVersion(step2);
|
|
11951
|
+
const sealed = isVersionStepSealed(step2);
|
|
11952
|
+
const hasPending = stepMigrations.some(
|
|
11953
|
+
(m) => check2.pending.some((p) => p.id === m.id)
|
|
11954
|
+
);
|
|
11955
|
+
const hasSkipped = stepMigrations.some(
|
|
11956
|
+
(m) => check2.skipped.some((s) => s.id === m.id)
|
|
11957
|
+
);
|
|
11958
|
+
if (!hasPending && !hasSkipped) continue;
|
|
11959
|
+
hasAny = true;
|
|
11960
|
+
const sealLabel = sealed ? pc37.green("sealed") : pc37.yellow("unsealed");
|
|
11961
|
+
console.log(pc37.bold(` \u2192 ${step2}`) + ` ${pc37.dim("(")}${sealLabel}${pc37.dim(")")}`);
|
|
11962
|
+
for (const m of stepMigrations) {
|
|
11963
|
+
const isPending = check2.pending.some((p) => p.id === m.id);
|
|
11964
|
+
const isSkipped = check2.skipped.some((s) => s.id === m.id);
|
|
11965
|
+
const status = isPending ? pc37.yellow("pending") : isSkipped ? pc37.dim("done") : pc37.dim("unknown");
|
|
11966
|
+
console.log(` ${isPending ? pc37.yellow("\u25CB") : pc37.dim("\u2713")} ${m.name} ${pc37.dim(`[${m.id}]`)} ${pc37.dim("\u2014")} ${status}`);
|
|
11967
|
+
console.log(` ${pc37.dim(m.description)}`);
|
|
11968
|
+
}
|
|
11969
|
+
}
|
|
11970
|
+
if (!hasAny) {
|
|
11971
|
+
console.log(pc37.green(" No migrations available \u2014 workspace is up to date."));
|
|
11972
|
+
}
|
|
11973
|
+
console.log("");
|
|
11974
|
+
return;
|
|
11975
|
+
}
|
|
11976
|
+
if (options.only) {
|
|
11977
|
+
console.log(pc37.bold(`
|
|
11978
|
+
Running single migration: ${options.only}
|
|
11979
|
+
`));
|
|
11980
|
+
const result2 = await runSingleMigration(flintPath, options.only, {
|
|
11981
|
+
log: (msg) => console.log(pc37.dim(` ${msg}`)),
|
|
11982
|
+
warn: (msg) => console.log(pc37.yellow(` ! ${msg}`)),
|
|
11983
|
+
error: (msg) => console.log(pc37.red(` \u2717 ${msg}`))
|
|
11984
|
+
});
|
|
11985
|
+
for (const m of result2.applied) {
|
|
11986
|
+
console.log(` ${pc37.green("\u2713")} ${m.name}`);
|
|
11987
|
+
for (const change of m.changes) {
|
|
11988
|
+
console.log(` ${pc37.dim("\u2192")} ${change}`);
|
|
11989
|
+
}
|
|
11990
|
+
if (m.warnings) {
|
|
11991
|
+
for (const warning of m.warnings) {
|
|
11992
|
+
console.log(` ${pc37.yellow("!")} ${warning}`);
|
|
11993
|
+
}
|
|
11994
|
+
}
|
|
11995
|
+
}
|
|
11996
|
+
for (const m of result2.skipped) {
|
|
11997
|
+
console.log(` ${pc37.dim("\u25CB")} ${m.name} ${pc37.dim("(already done)")}`);
|
|
11998
|
+
}
|
|
11999
|
+
for (const m of result2.failed) {
|
|
12000
|
+
console.log(` ${pc37.red("\u2717")} ${m.name}`);
|
|
12001
|
+
console.log(` ${pc37.red("\u2192")} ${m.error}`);
|
|
12002
|
+
}
|
|
12003
|
+
console.log("");
|
|
12004
|
+
if (result2.failed.length > 0) {
|
|
12005
|
+
console.log(pc37.red("Migration failed."));
|
|
12006
|
+
process.exit(1);
|
|
12007
|
+
}
|
|
12008
|
+
if (result2.applied.length > 0) {
|
|
12009
|
+
console.log(pc37.green("\u2713 Migration applied (no version bump)."));
|
|
12010
|
+
}
|
|
12011
|
+
return;
|
|
12012
|
+
}
|
|
9733
12013
|
const check = await checkMigrations(flintPath);
|
|
9734
12014
|
if (check.pending.length === 0) {
|
|
9735
12015
|
console.log(pc37.green("\u2713 No pending migrations."));
|
|
@@ -9745,7 +12025,9 @@ var migrateCommand = new Command32("migrate").description("Run pending workspace
|
|
|
9745
12025
|
${check.pending.length} migration(s) pending:
|
|
9746
12026
|
`));
|
|
9747
12027
|
for (const [version, items] of groups) {
|
|
9748
|
-
|
|
12028
|
+
const sealed = isVersionStepSealed(version);
|
|
12029
|
+
const sealLabel = sealed ? pc37.green("sealed") : pc37.yellow("unsealed");
|
|
12030
|
+
console.log(pc37.bold(` \u2192 ${version}`) + ` ${pc37.dim("(")}${sealLabel}${pc37.dim(")")}`);
|
|
9749
12031
|
for (const m of items) {
|
|
9750
12032
|
console.log(` ${pc37.dim("\u25CB")} ${m.name}`);
|
|
9751
12033
|
console.log(` ${pc37.dim(m.description)}`);
|
|
@@ -9945,6 +12227,7 @@ async function requireTinderboxRoot() {
|
|
|
9945
12227
|
function printSummary(result) {
|
|
9946
12228
|
console.log(pc40.bold("\nSummary"));
|
|
9947
12229
|
console.log(` Cloned: ${result.cloned.length}`);
|
|
12230
|
+
console.log(` Moved: ${result.moved.length}`);
|
|
9948
12231
|
console.log(` Referenced: ${result.referenced.length}`);
|
|
9949
12232
|
console.log(` Already present: ${result.present.length}`);
|
|
9950
12233
|
console.log(` Registry updated: ${result.registryUpdated.length}`);
|
|
@@ -10120,6 +12403,12 @@ var tinderboxCommand = new Command35("tinderbox").description("Orchestrate opera
|
|
|
10120
12403
|
console.log(` ${pc40.green("\u2713")} ${name}`);
|
|
10121
12404
|
}
|
|
10122
12405
|
}
|
|
12406
|
+
if (result.moved.length > 0) {
|
|
12407
|
+
console.log(pc40.bold("\nMoved"));
|
|
12408
|
+
for (const entry of result.moved) {
|
|
12409
|
+
console.log(` ${pc40.green("\u2713")} ${entry.name} ${pc40.dim(`${abbreviatePath(entry.from)} \u2192 ${abbreviatePath(entry.to)}`)}`);
|
|
12410
|
+
}
|
|
12411
|
+
}
|
|
10123
12412
|
if (result.referenced.length > 0) {
|
|
10124
12413
|
console.log(pc40.bold("\nReferenced From Registry"));
|
|
10125
12414
|
for (const name of result.referenced) {
|
|
@@ -10263,11 +12552,12 @@ var tinderboxCommand = new Command35("tinderbox").description("Orchestrate opera
|
|
|
10263
12552
|
// src/commands/orb.ts
|
|
10264
12553
|
import { Command as Command36 } from "commander";
|
|
10265
12554
|
import pc41 from "picocolors";
|
|
10266
|
-
import { spawn as
|
|
10267
|
-
import { existsSync as
|
|
12555
|
+
import { spawn as spawn6, spawnSync as spawnSync5, execSync as execSync5 } from "child_process";
|
|
12556
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync9, readdirSync as readdirSync6, statSync as statSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
10268
12557
|
import { join as join17 } from "path";
|
|
12558
|
+
import { homedir as homedir9 } from "os";
|
|
10269
12559
|
import { createInterface as createInterface7 } from "readline";
|
|
10270
|
-
function
|
|
12560
|
+
function getSessionsDir2(flintPath) {
|
|
10271
12561
|
return join17(flintPath, ".flint", "sessions");
|
|
10272
12562
|
}
|
|
10273
12563
|
async function resolveFlintPath4(optionPath) {
|
|
@@ -10280,7 +12570,7 @@ async function resolveFlintPath4(optionPath) {
|
|
|
10280
12570
|
}
|
|
10281
12571
|
async function resolveCtx(optionPath) {
|
|
10282
12572
|
const flintPath = await resolveFlintPath4(optionPath);
|
|
10283
|
-
return { flintPath, sessionsDir:
|
|
12573
|
+
return { flintPath, sessionsDir: getSessionsDir2(flintPath) };
|
|
10284
12574
|
}
|
|
10285
12575
|
function sessionReferencedInMesh2(flintPath, sessionId) {
|
|
10286
12576
|
try {
|
|
@@ -10307,8 +12597,8 @@ function readTranscriptEntries(session, flintPath) {
|
|
|
10307
12597
|
const transcriptPath = harness.resolveTranscriptPath(nativeId, flintPath);
|
|
10308
12598
|
if (!transcriptPath) return null;
|
|
10309
12599
|
try {
|
|
10310
|
-
const content =
|
|
10311
|
-
return harness.parseTranscript(content);
|
|
12600
|
+
const content = readFileSync9(transcriptPath, "utf-8");
|
|
12601
|
+
return harness.parseTranscript(content, { transcriptPath });
|
|
10312
12602
|
} catch {
|
|
10313
12603
|
return null;
|
|
10314
12604
|
}
|
|
@@ -10330,7 +12620,7 @@ function formatTokenSummary(usage) {
|
|
|
10330
12620
|
var DETACHED_ORB_MONITOR = String.raw`
|
|
10331
12621
|
const { spawn, spawnSync } = require('node:child_process');
|
|
10332
12622
|
const { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, renameSync } = require('node:fs');
|
|
10333
|
-
const { dirname, join } = require('node:path');
|
|
12623
|
+
const { basename, dirname, join } = require('node:path');
|
|
10334
12624
|
const { homedir } = require('node:os');
|
|
10335
12625
|
|
|
10336
12626
|
const configJson = process.env.ORBH_MONITOR_CONFIG;
|
|
@@ -10388,7 +12678,7 @@ child.on('error', () => {
|
|
|
10388
12678
|
updateCurrentRun(s, { status: 'failed', ended: new Date().toISOString() });
|
|
10389
12679
|
writeSessionFile(s);
|
|
10390
12680
|
}
|
|
10391
|
-
notify('
|
|
12681
|
+
notify('Orbh Session Failed', (s?.title || s?.description || 'Unknown').slice(0, 100));
|
|
10392
12682
|
process.exit(1);
|
|
10393
12683
|
});
|
|
10394
12684
|
|
|
@@ -10456,6 +12746,57 @@ if (command === 'codex') {
|
|
|
10456
12746
|
}, 500);
|
|
10457
12747
|
}
|
|
10458
12748
|
|
|
12749
|
+
// Gemini native session discovery — poll for a new session-*.json transcript
|
|
12750
|
+
if (command === 'gemini') {
|
|
12751
|
+
const slugify = (name) => name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
12752
|
+
const geminiChatsDir = join(homedir(), '.gemini', 'tmp', slugify(basename(cwd)), 'chats');
|
|
12753
|
+
|
|
12754
|
+
// Snapshot existing transcript paths before launch to exclude them
|
|
12755
|
+
const existingTranscripts = new Set();
|
|
12756
|
+
try {
|
|
12757
|
+
for (const f of readdirSync(geminiChatsDir)) {
|
|
12758
|
+
if (f.startsWith('session-') && f.endsWith('.json')) {
|
|
12759
|
+
existingTranscripts.add(join(geminiChatsDir, f));
|
|
12760
|
+
}
|
|
12761
|
+
}
|
|
12762
|
+
} catch {}
|
|
12763
|
+
|
|
12764
|
+
function discoverGeminiSession() {
|
|
12765
|
+
if (!existsSync(geminiChatsDir)) return null;
|
|
12766
|
+
const files = readdirSync(geminiChatsDir)
|
|
12767
|
+
.filter(f => f.startsWith('session-') && f.endsWith('.json'))
|
|
12768
|
+
.map(f => join(geminiChatsDir, f))
|
|
12769
|
+
.sort((a, b) => b.localeCompare(a));
|
|
12770
|
+
for (const fp of files) {
|
|
12771
|
+
if (existingTranscripts.has(fp)) continue;
|
|
12772
|
+
try {
|
|
12773
|
+
const parsed = JSON.parse(readFileSync(fp, 'utf-8'));
|
|
12774
|
+
if (typeof parsed.sessionId === 'string') {
|
|
12775
|
+
return { nativeSessionId: parsed.sessionId, transcriptPath: fp };
|
|
12776
|
+
}
|
|
12777
|
+
} catch { continue; }
|
|
12778
|
+
}
|
|
12779
|
+
return null;
|
|
12780
|
+
}
|
|
12781
|
+
|
|
12782
|
+
let geminiDiscoveryAttempts = 0;
|
|
12783
|
+
const geminiMaxAttempts = 60; // 30s at 500ms interval
|
|
12784
|
+
const geminiDiscoveryTimer = setInterval(() => {
|
|
12785
|
+
geminiDiscoveryAttempts++;
|
|
12786
|
+
const found = discoverGeminiSession();
|
|
12787
|
+
if (found) {
|
|
12788
|
+
clearInterval(geminiDiscoveryTimer);
|
|
12789
|
+
const s = readSession();
|
|
12790
|
+
if (s) {
|
|
12791
|
+
updateCurrentRun(s, { nativeSessionId: found.nativeSessionId });
|
|
12792
|
+
writeSessionFile(s);
|
|
12793
|
+
}
|
|
12794
|
+
} else if (geminiDiscoveryAttempts >= geminiMaxAttempts) {
|
|
12795
|
+
clearInterval(geminiDiscoveryTimer);
|
|
12796
|
+
}
|
|
12797
|
+
}, 500);
|
|
12798
|
+
}
|
|
12799
|
+
|
|
10459
12800
|
child.on('exit', (code) => {
|
|
10460
12801
|
const s = readSession();
|
|
10461
12802
|
if (!s) { process.exit(typeof code === 'number' ? code : 1); return; }
|
|
@@ -10477,7 +12818,7 @@ child.on('exit', (code) => {
|
|
|
10477
12818
|
s.status = 'finished';
|
|
10478
12819
|
}
|
|
10479
12820
|
writeSessionFile(s);
|
|
10480
|
-
notify('
|
|
12821
|
+
notify('Orbh Session Complete', desc);
|
|
10481
12822
|
} else {
|
|
10482
12823
|
if (!runIsTerminal) {
|
|
10483
12824
|
updateCurrentRun(s, { status: 'failed' });
|
|
@@ -10487,7 +12828,7 @@ child.on('exit', (code) => {
|
|
|
10487
12828
|
}
|
|
10488
12829
|
writeSessionFile(s);
|
|
10489
12830
|
const errLine = stderr.trim().split(/\r?\n/).find(Boolean);
|
|
10490
|
-
notify('
|
|
12831
|
+
notify('Orbh Session Failed', desc + (errLine ? ': ' + errLine.slice(0, 80) : ' (exit ' + code + ')'));
|
|
10491
12832
|
}
|
|
10492
12833
|
|
|
10493
12834
|
process.exit(typeof code === 'number' ? code : 1);
|
|
@@ -10555,9 +12896,9 @@ async function buildOrbInitPrompt(sessionId, runtime2, flintPath, options) {
|
|
|
10555
12896
|
}
|
|
10556
12897
|
return `init, you are a ${runtime2} session, please read init-f.md and (System) Flint Init.md${identityClause}
|
|
10557
12898
|
|
|
10558
|
-
You are running in headless mode via
|
|
12899
|
+
You are running in headless mode via Orbh. Your session ID is: ${sessionId}
|
|
10559
12900
|
|
|
10560
|
-
After initialization, load the Flint
|
|
12901
|
+
After initialization, load the Flint Orbh shard by reading Shards/(Dev) Flint Orbh/init-foh.md.
|
|
10561
12902
|
|
|
10562
12903
|
IMPORTANT: Use flint orb commands, NOT flint agent session commands.
|
|
10563
12904
|
|
|
@@ -10582,11 +12923,12 @@ async function buildInteractiveInitPrompt(sessionId, runtime2, flintPath) {
|
|
|
10582
12923
|
}
|
|
10583
12924
|
} catch {
|
|
10584
12925
|
}
|
|
10585
|
-
|
|
12926
|
+
const sessionIdClause = runtime2 === "codex" ? `Your Orbh session ID is ${sessionId}. If Codex later shows you a native Codex session ID or thread ID, that is different from the Orbh session ID and must not be used with flint orb commands.` : `Your session ID is ${sessionId}.`;
|
|
12927
|
+
return `init, you are a ${runtime2} session, please read init-f.md and (System) Flint Init.md. ${sessionIdClause}${identityClause}
|
|
10586
12928
|
|
|
10587
|
-
You are running as an interactive
|
|
12929
|
+
You are running as an interactive Orbh session. Your session is tracked via the orbh system.
|
|
10588
12930
|
|
|
10589
|
-
After initialization, load the Flint
|
|
12931
|
+
After initialization, load the Flint Orbh shard by reading Shards/(Dev) Flint Orbh/init-foh.md.
|
|
10590
12932
|
|
|
10591
12933
|
IMPORTANT: Use flint orb commands, NOT flint agent session commands.
|
|
10592
12934
|
|
|
@@ -10595,7 +12937,7 @@ This is an interactive session \u2014 the human is present and will guide the co
|
|
|
10595
12937
|
|
|
10596
12938
|
Use flint orb commands to keep your status and interface updated while you work.`;
|
|
10597
12939
|
}
|
|
10598
|
-
function
|
|
12940
|
+
function buildSessionFrontmatter2(sessionId, runtime2) {
|
|
10599
12941
|
const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
10600
12942
|
const runtimeTag = runtime2 === "claude" ? "claude-code" : runtime2;
|
|
10601
12943
|
const runtimeTitle = runtime2 === "claude" ? "Claude Code" : runtime2.charAt(0).toUpperCase() + runtime2.slice(1);
|
|
@@ -10624,29 +12966,29 @@ function exportSessionTranscript(session, flintPath) {
|
|
|
10624
12966
|
}
|
|
10625
12967
|
let content;
|
|
10626
12968
|
try {
|
|
10627
|
-
content =
|
|
12969
|
+
content = readFileSync9(transcriptPath, "utf-8");
|
|
10628
12970
|
} catch {
|
|
10629
12971
|
console.log(pc41.dim("Could not read transcript file."));
|
|
10630
12972
|
return;
|
|
10631
12973
|
}
|
|
10632
|
-
const entries = harness.parseTranscript(content);
|
|
12974
|
+
const entries = harness.parseTranscript(content, { transcriptPath });
|
|
10633
12975
|
if (entries.length === 0) {
|
|
10634
12976
|
console.log(pc41.dim("Transcript is empty, skipping export."));
|
|
10635
12977
|
return;
|
|
10636
12978
|
}
|
|
10637
12979
|
const body = formatTranscriptMarkdown(entries);
|
|
10638
|
-
const markdown =
|
|
12980
|
+
const markdown = buildSessionFrontmatter2(nativeId, session.runtime) + body;
|
|
10639
12981
|
const runtimeDir = session.runtime === "claude" ? "Claude Code" : session.runtime.charAt(0).toUpperCase() + session.runtime.slice(1);
|
|
10640
12982
|
const outputDir = join17(flintPath, "Mesh", "Agents", runtimeDir);
|
|
10641
|
-
|
|
12983
|
+
mkdirSync4(outputDir, { recursive: true });
|
|
10642
12984
|
const outputPath = join17(outputDir, `${nativeId}.md`);
|
|
10643
|
-
|
|
12985
|
+
writeFileSync3(outputPath, markdown, "utf-8");
|
|
10644
12986
|
console.log(pc41.green(`Session exported \u2192 Mesh/Agents/${runtimeDir}/${nativeId}.md`));
|
|
10645
12987
|
}
|
|
10646
12988
|
function startDetachedMonitor(sessionsDir, sessionId, cwd, command, args) {
|
|
10647
12989
|
const sessionPath = getSessionPath2(sessionsDir, sessionId);
|
|
10648
12990
|
const config = JSON.stringify({ sessionPath, cwd, command, args });
|
|
10649
|
-
const monitor =
|
|
12991
|
+
const monitor = spawn6(process.execPath, ["-e", DETACHED_ORB_MONITOR], {
|
|
10650
12992
|
cwd,
|
|
10651
12993
|
detached: true,
|
|
10652
12994
|
stdio: "ignore",
|
|
@@ -10742,51 +13084,24 @@ function formatEntry2(entry, maxLen, depth = 0, agentCalls) {
|
|
|
10742
13084
|
return null;
|
|
10743
13085
|
}
|
|
10744
13086
|
}
|
|
10745
|
-
var orbCommand = new Command36("orb").description("
|
|
10746
|
-
function isProcessAlive(pid) {
|
|
10747
|
-
try {
|
|
10748
|
-
process.kill(pid, 0);
|
|
10749
|
-
return true;
|
|
10750
|
-
} catch {
|
|
10751
|
-
return false;
|
|
10752
|
-
}
|
|
10753
|
-
}
|
|
13087
|
+
var orbCommand = new Command36("orb").description("Orbh meta-harness agent management").enablePositionalOptions();
|
|
10754
13088
|
orbCommand.command("heal").description("Fix sessions stuck in non-terminal states (stale PIDs, orphaned runs)").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--dry-run", "Show what would be healed without making changes").action(async (options) => {
|
|
10755
13089
|
const { sessionsDir } = await resolveCtx(options.path);
|
|
10756
13090
|
const sessions = listSessions2(sessionsDir);
|
|
10757
13091
|
let healed = 0;
|
|
10758
13092
|
for (const session of sessions) {
|
|
10759
|
-
if (isTerminalStatus2(session.status)) continue;
|
|
10760
13093
|
const currentRun = getCurrentRun2(session);
|
|
10761
|
-
|
|
13094
|
+
const prevStatus = session.status;
|
|
13095
|
+
const prevRunStatus = currentRun?.status;
|
|
13096
|
+
if (healSession(session)) {
|
|
13097
|
+
const runDesc = currentRun ? `run ${shortId2(currentRun.id)} PID ${currentRun.pid ?? "none"} ${prevRunStatus} \u2192 ${currentRun.status}` : `no runs, ${prevStatus} \u2192 ${session.status}`;
|
|
10762
13098
|
if (options.dryRun) {
|
|
10763
|
-
console.log(`${pc41.yellow("would heal")} ${shortId2(session.id)} \u2014
|
|
13099
|
+
console.log(`${pc41.yellow("would heal")} ${shortId2(session.id)} \u2014 ${runDesc}`);
|
|
10764
13100
|
} else {
|
|
10765
|
-
session.status = "failed";
|
|
10766
13101
|
writeSession(sessionsDir, session);
|
|
10767
|
-
console.log(`${pc41.green("healed")} ${shortId2(session.id)} \u2014
|
|
13102
|
+
console.log(`${pc41.green("healed")} ${shortId2(session.id)} \u2014 ${runDesc}`);
|
|
10768
13103
|
}
|
|
10769
13104
|
healed++;
|
|
10770
|
-
continue;
|
|
10771
|
-
}
|
|
10772
|
-
if (currentRun.status === "running") {
|
|
10773
|
-
const pid = currentRun.pid;
|
|
10774
|
-
const alive = pid ? isProcessAlive(pid) : false;
|
|
10775
|
-
if (!alive) {
|
|
10776
|
-
if (options.dryRun) {
|
|
10777
|
-
console.log(`${pc41.yellow("would heal")} ${shortId2(session.id)} \u2014 run ${shortId2(currentRun.id)} PID ${pid ?? "none"} is dead, status: ${session.status}`);
|
|
10778
|
-
} else {
|
|
10779
|
-
updateCurrentRun2(session, {
|
|
10780
|
-
status: "failed",
|
|
10781
|
-
ended: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10782
|
-
exitCode: currentRun.exitCode ?? -1
|
|
10783
|
-
});
|
|
10784
|
-
session.status = "failed";
|
|
10785
|
-
writeSession(sessionsDir, session);
|
|
10786
|
-
console.log(`${pc41.green("healed")} ${shortId2(session.id)} \u2014 dead PID ${pid ?? "none"} \u2192 failed`);
|
|
10787
|
-
}
|
|
10788
|
-
healed++;
|
|
10789
|
-
}
|
|
10790
13105
|
}
|
|
10791
13106
|
}
|
|
10792
13107
|
if (healed === 0) {
|
|
@@ -10827,7 +13142,7 @@ orbCommand.command("launch").description("Launch a new headless agent session").
|
|
|
10827
13142
|
const run = addRun2(session, { nativeSessionId });
|
|
10828
13143
|
writeSession(sessionsDir, session);
|
|
10829
13144
|
startDetachedMonitor(sessionsDir, session.id, flintPath, harness.name, args);
|
|
10830
|
-
console.log(`${pc41.bold("
|
|
13145
|
+
console.log(`${pc41.bold("Orbh Agent Session")}`);
|
|
10831
13146
|
console.log(` ID: ${pc41.cyan(session.id)}`);
|
|
10832
13147
|
console.log(` Runtime: ${pc41.cyan(runtime2)}`);
|
|
10833
13148
|
console.log(` Run: ${pc41.dim(shortId2(run.id))}`);
|
|
@@ -10863,7 +13178,7 @@ orbCommand.command("resume").description("Resume an existing session (adds a new
|
|
|
10863
13178
|
session.status = "queued";
|
|
10864
13179
|
writeSession(sessionsDir, session);
|
|
10865
13180
|
startDetachedMonitor(sessionsDir, session.id, flintPath, harness.name, args);
|
|
10866
|
-
console.log(`${pc41.bold("
|
|
13181
|
+
console.log(`${pc41.bold("Orbh Session Resumed")}`);
|
|
10867
13182
|
console.log(` ID: ${pc41.cyan(session.id)}`);
|
|
10868
13183
|
console.log(` Run: ${pc41.dim(shortId2(run.id))} (run #${session.runs.length})`);
|
|
10869
13184
|
console.log("");
|
|
@@ -10894,6 +13209,24 @@ function buildCodexResumeArgs(threadId, prompt6, options) {
|
|
|
10894
13209
|
if (prompt6) args.push(prompt6);
|
|
10895
13210
|
return args;
|
|
10896
13211
|
}
|
|
13212
|
+
function buildInteractiveDroidArgs(prompt6) {
|
|
13213
|
+
return prompt6 ? [prompt6] : [];
|
|
13214
|
+
}
|
|
13215
|
+
function buildInteractiveDroidResumeArgs(nativeSessionId, prompt6) {
|
|
13216
|
+
const args = ["--resume", nativeSessionId];
|
|
13217
|
+
if (prompt6) args.push(prompt6);
|
|
13218
|
+
return args;
|
|
13219
|
+
}
|
|
13220
|
+
function buildInteractiveGeminiArgs(prompt6, options) {
|
|
13221
|
+
const args = ["--yolo", "--model", options.model || DEFAULT_GEMINI_MODEL];
|
|
13222
|
+
if (prompt6) args.push(prompt6);
|
|
13223
|
+
return args;
|
|
13224
|
+
}
|
|
13225
|
+
function buildInteractiveGeminiResumeArgs(nativeSessionId, prompt6, options) {
|
|
13226
|
+
const args = ["--yolo", "--model", options.model || DEFAULT_GEMINI_MODEL, "--resume", nativeSessionId];
|
|
13227
|
+
if (prompt6) args.push(prompt6);
|
|
13228
|
+
return args;
|
|
13229
|
+
}
|
|
10897
13230
|
orbCommand.command("i").alias("interactive").description("Launch an interactive agent TUI with orbh session tracking").argument("<runtime>", `Harness runtime (${listHarnesses().join(", ")})`).argument("[prompt]", "Optional initial prompt").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("-c, --continue <sessionId>", "Continue a previous orbh session").option("--continues <sessionId>", "Link as continuation of another session (new session)").option("--model <model>", "Model override").option("--dev-channels", "Load development MCP channels (e.g. orbh)").option("--no-export", "Skip transcript export on exit").action(async (runtime2, userPrompt, options) => {
|
|
10898
13231
|
try {
|
|
10899
13232
|
const { flintPath, sessionsDir } = await resolveCtx(options.path);
|
|
@@ -10918,7 +13251,17 @@ orbCommand.command("i").alias("interactive").description("Launch an interactive
|
|
|
10918
13251
|
}
|
|
10919
13252
|
session = existing;
|
|
10920
13253
|
const lastRun = getCurrentRun2(session);
|
|
10921
|
-
|
|
13254
|
+
let nativeId = lastRun?.nativeSessionId ?? session.id;
|
|
13255
|
+
if (!lastRun?.nativeSessionId && runtime2 === "droid") {
|
|
13256
|
+
nativeId = discoverDroidNativeSessionByOrbhSessionId(flintPath, session.id, {
|
|
13257
|
+
startedAt: lastRun?.started ?? session.started
|
|
13258
|
+
})?.nativeSessionId ?? nativeId;
|
|
13259
|
+
}
|
|
13260
|
+
if (!lastRun?.nativeSessionId && runtime2 === "gemini") {
|
|
13261
|
+
nativeId = discoverGeminiNativeSessionByOrbhSessionId(flintPath, session.id, {
|
|
13262
|
+
startedAt: lastRun?.started ?? session.started
|
|
13263
|
+
})?.nativeSessionId ?? nativeId;
|
|
13264
|
+
}
|
|
10922
13265
|
const resumePrompt = userPrompt || `continuing session ${session.id}`;
|
|
10923
13266
|
if (runtime2 === "claude") {
|
|
10924
13267
|
spawnCommand = "claude";
|
|
@@ -10929,6 +13272,12 @@ orbCommand.command("i").alias("interactive").description("Launch an interactive
|
|
|
10929
13272
|
} else if (runtime2 === "codex") {
|
|
10930
13273
|
spawnCommand = "codex";
|
|
10931
13274
|
spawnArgs = buildCodexResumeArgs(nativeId, resumePrompt, { model: options.model });
|
|
13275
|
+
} else if (runtime2 === "droid") {
|
|
13276
|
+
spawnCommand = "droid";
|
|
13277
|
+
spawnArgs = buildInteractiveDroidResumeArgs(nativeId, resumePrompt);
|
|
13278
|
+
} else if (runtime2 === "gemini") {
|
|
13279
|
+
spawnCommand = "gemini";
|
|
13280
|
+
spawnArgs = buildInteractiveGeminiResumeArgs(nativeId, resumePrompt, { model: options.model });
|
|
10932
13281
|
} else {
|
|
10933
13282
|
spawnCommand = harness.name;
|
|
10934
13283
|
spawnArgs = resumePrompt ? [resumePrompt] : [];
|
|
@@ -10936,7 +13285,7 @@ orbCommand.command("i").alias("interactive").description("Launch an interactive
|
|
|
10936
13285
|
addRun2(session, { nativeSessionId: nativeId, continuesRunId: lastRun?.id ?? null });
|
|
10937
13286
|
session.status = "in-progress";
|
|
10938
13287
|
writeSession(sessionsDir, session);
|
|
10939
|
-
console.log(`${pc41.bold("
|
|
13288
|
+
console.log(`${pc41.bold("Orbh Interactive Session (resumed)")}`);
|
|
10940
13289
|
console.log(` ID: ${pc41.cyan(session.id)}`);
|
|
10941
13290
|
console.log(` Run: ${pc41.dim(shortId2(session.runs[session.runs.length - 1].id))} (run #${session.runs.length})`);
|
|
10942
13291
|
console.log("");
|
|
@@ -10975,11 +13324,23 @@ ${prompt6}` : initPrompt;
|
|
|
10975
13324
|
process.exit(1);
|
|
10976
13325
|
}
|
|
10977
13326
|
spawnCommand = "codex";
|
|
10978
|
-
const codexResumePrompt = `
|
|
13327
|
+
const codexResumePrompt = `Your native Codex session ID is ${threadId}. Your Orbh session ID remains ${session.id}. Use the Orbh session ID with flint orb commands, not the native Codex session ID. Please initialize now.`;
|
|
10979
13328
|
spawnArgs = buildCodexResumeArgs(threadId, codexResumePrompt, { model: options.model });
|
|
10980
13329
|
addRun2(session, { nativeSessionId: threadId });
|
|
10981
13330
|
session.status = "in-progress";
|
|
10982
13331
|
writeSession(sessionsDir, session);
|
|
13332
|
+
} else if (runtime2 === "droid") {
|
|
13333
|
+
spawnCommand = "droid";
|
|
13334
|
+
spawnArgs = buildInteractiveDroidArgs(fullPrompt);
|
|
13335
|
+
addRun2(session, { nativeSessionId: null });
|
|
13336
|
+
session.status = "in-progress";
|
|
13337
|
+
writeSession(sessionsDir, session);
|
|
13338
|
+
} else if (runtime2 === "gemini") {
|
|
13339
|
+
spawnCommand = "gemini";
|
|
13340
|
+
spawnArgs = buildInteractiveGeminiArgs(fullPrompt, { model: options.model });
|
|
13341
|
+
addRun2(session, { nativeSessionId: null });
|
|
13342
|
+
session.status = "in-progress";
|
|
13343
|
+
writeSession(sessionsDir, session);
|
|
10983
13344
|
} else {
|
|
10984
13345
|
spawnCommand = harness.name;
|
|
10985
13346
|
spawnArgs = [fullPrompt];
|
|
@@ -10987,17 +13348,48 @@ ${prompt6}` : initPrompt;
|
|
|
10987
13348
|
session.status = "in-progress";
|
|
10988
13349
|
writeSession(sessionsDir, session);
|
|
10989
13350
|
}
|
|
10990
|
-
console.log(`${pc41.bold("
|
|
13351
|
+
console.log(`${pc41.bold("Orbh Interactive Session")}`);
|
|
10991
13352
|
console.log(` ID: ${pc41.cyan(session.id)}`);
|
|
10992
13353
|
console.log(` Runtime: ${pc41.cyan(runtime2)}`);
|
|
10993
13354
|
if (options.continues) console.log(` Continues: ${pc41.dim(options.continues)}`);
|
|
10994
13355
|
console.log("");
|
|
10995
13356
|
}
|
|
10996
|
-
const child =
|
|
13357
|
+
const child = spawn6(spawnCommand, spawnArgs, {
|
|
10997
13358
|
cwd: flintPath,
|
|
10998
13359
|
stdio: "inherit",
|
|
10999
13360
|
env: { ...process.env, ORBH_SESSION_ID: session.id }
|
|
11000
13361
|
});
|
|
13362
|
+
if (child.pid) {
|
|
13363
|
+
updateCurrentRun2(session, { pid: child.pid });
|
|
13364
|
+
session.status = "in-progress";
|
|
13365
|
+
writeSession(sessionsDir, session);
|
|
13366
|
+
}
|
|
13367
|
+
let nativeDiscoveryTimer = null;
|
|
13368
|
+
if ((runtime2 === "droid" || runtime2 === "gemini") && !getCurrentRun2(session)?.nativeSessionId) {
|
|
13369
|
+
const startedAt = getCurrentRun2(session)?.started ?? session.started;
|
|
13370
|
+
nativeDiscoveryTimer = setInterval(() => {
|
|
13371
|
+
const fresh = readSession2(sessionsDir, session.id) ?? session;
|
|
13372
|
+
const currentRun = getCurrentRun2(fresh);
|
|
13373
|
+
if (!currentRun || currentRun.nativeSessionId) {
|
|
13374
|
+
if (nativeDiscoveryTimer) {
|
|
13375
|
+
clearInterval(nativeDiscoveryTimer);
|
|
13376
|
+
nativeDiscoveryTimer = null;
|
|
13377
|
+
}
|
|
13378
|
+
return;
|
|
13379
|
+
}
|
|
13380
|
+
const discovered = runtime2 === "droid" ? discoverDroidNativeSessionByOrbhSessionId(flintPath, session.id, { startedAt }) : discoverGeminiNativeSessionByOrbhSessionId(flintPath, session.id, { startedAt });
|
|
13381
|
+
if (!discovered) {
|
|
13382
|
+
return;
|
|
13383
|
+
}
|
|
13384
|
+
updateCurrentRun2(fresh, { nativeSessionId: discovered.nativeSessionId });
|
|
13385
|
+
writeSession(sessionsDir, fresh);
|
|
13386
|
+
session = fresh;
|
|
13387
|
+
if (nativeDiscoveryTimer) {
|
|
13388
|
+
clearInterval(nativeDiscoveryTimer);
|
|
13389
|
+
nativeDiscoveryTimer = null;
|
|
13390
|
+
}
|
|
13391
|
+
}, 500);
|
|
13392
|
+
}
|
|
11001
13393
|
child.on("error", (err) => {
|
|
11002
13394
|
if (err.code === "ENOENT") {
|
|
11003
13395
|
console.error(pc41.red(`Error: ${runtime2} is not installed.`));
|
|
@@ -11010,35 +13402,40 @@ ${prompt6}` : initPrompt;
|
|
|
11010
13402
|
process.exit(1);
|
|
11011
13403
|
});
|
|
11012
13404
|
child.on("exit", async (code) => {
|
|
11013
|
-
|
|
13405
|
+
if (nativeDiscoveryTimer) {
|
|
13406
|
+
clearInterval(nativeDiscoveryTimer);
|
|
13407
|
+
nativeDiscoveryTimer = null;
|
|
13408
|
+
}
|
|
13409
|
+
const fresh = readSession2(sessionsDir, session.id) ?? session;
|
|
13410
|
+
const run = getCurrentRun2(fresh);
|
|
11014
13411
|
const runIsTerminal = run && (run.status === "completed" || run.status === "failed" || run.status === "cancelled" || run.status === "suspended");
|
|
11015
|
-
updateCurrentRun2(
|
|
13412
|
+
updateCurrentRun2(fresh, { ended: (/* @__PURE__ */ new Date()).toISOString(), exitCode: code });
|
|
11016
13413
|
if (code === 0) {
|
|
11017
13414
|
if (!runIsTerminal) {
|
|
11018
13415
|
const agentReturned = run && run.result;
|
|
11019
|
-
updateCurrentRun2(
|
|
13416
|
+
updateCurrentRun2(fresh, { status: agentReturned ? "completed" : "suspended" });
|
|
11020
13417
|
}
|
|
11021
|
-
if (!isTerminalStatus2(
|
|
11022
|
-
|
|
13418
|
+
if (!isTerminalStatus2(fresh.status) && fresh.status !== "deferred") {
|
|
13419
|
+
fresh.status = "finished";
|
|
11023
13420
|
}
|
|
11024
13421
|
} else {
|
|
11025
13422
|
if (!runIsTerminal) {
|
|
11026
|
-
updateCurrentRun2(
|
|
13423
|
+
updateCurrentRun2(fresh, { status: "failed" });
|
|
11027
13424
|
}
|
|
11028
|
-
if (!isTerminalStatus2(
|
|
11029
|
-
|
|
13425
|
+
if (!isTerminalStatus2(fresh.status) && fresh.status !== "deferred") {
|
|
13426
|
+
fresh.status = "failed";
|
|
11030
13427
|
}
|
|
11031
13428
|
}
|
|
11032
|
-
writeSession(sessionsDir,
|
|
13429
|
+
writeSession(sessionsDir, fresh);
|
|
11033
13430
|
if (options.export !== false) {
|
|
11034
13431
|
try {
|
|
11035
|
-
const nativeId = run?.nativeSessionId ??
|
|
11036
|
-
if (sessionReferencedInMesh2(flintPath,
|
|
11037
|
-
exportSessionTranscript(
|
|
13432
|
+
const nativeId = run?.nativeSessionId ?? fresh.id;
|
|
13433
|
+
if (sessionReferencedInMesh2(flintPath, fresh.id) || sessionReferencedInMesh2(flintPath, nativeId)) {
|
|
13434
|
+
exportSessionTranscript(fresh, flintPath);
|
|
11038
13435
|
} else {
|
|
11039
13436
|
const save = await askYesNo2(pc41.dim("Save session transcript? (y/N) "));
|
|
11040
13437
|
if (save) {
|
|
11041
|
-
exportSessionTranscript(
|
|
13438
|
+
exportSessionTranscript(fresh, flintPath);
|
|
11042
13439
|
}
|
|
11043
13440
|
}
|
|
11044
13441
|
} catch (err) {
|
|
@@ -11057,6 +13454,11 @@ orbCommand.command("list").description("List all agent sessions").option("-p, --
|
|
|
11057
13454
|
const { flintPath, sessionsDir } = await resolveCtx(options.path);
|
|
11058
13455
|
const renderTable = (interactive) => {
|
|
11059
13456
|
let sessions = listSessions2(sessionsDir);
|
|
13457
|
+
for (const s of sessions) {
|
|
13458
|
+
if (healSession(s)) {
|
|
13459
|
+
writeSession(sessionsDir, s);
|
|
13460
|
+
}
|
|
13461
|
+
}
|
|
11060
13462
|
if (options.status) {
|
|
11061
13463
|
sessions = sessions.filter((s) => s.status === options.status);
|
|
11062
13464
|
}
|
|
@@ -11070,7 +13472,7 @@ orbCommand.command("list").description("List all agent sessions").option("-p, --
|
|
|
11070
13472
|
);
|
|
11071
13473
|
}
|
|
11072
13474
|
if (!options.all) sessions = sessions.slice(0, 30);
|
|
11073
|
-
const lines = ["", pc41.bold("
|
|
13475
|
+
const lines = ["", pc41.bold("Orbh Sessions"), ""];
|
|
11074
13476
|
if (sessions.length === 0) {
|
|
11075
13477
|
lines.push(pc41.dim("No sessions found."));
|
|
11076
13478
|
} else {
|
|
@@ -11097,7 +13499,8 @@ orbCommand.command("list").description("List all agent sessions").option("-p, --
|
|
|
11097
13499
|
statsCol = `${pc41.dim("-").padEnd(6)} ${pc41.dim("-").padEnd(12)} `;
|
|
11098
13500
|
}
|
|
11099
13501
|
}
|
|
11100
|
-
|
|
13502
|
+
const metaHint = s.metadata && Object.keys(s.metadata).length > 0 ? pc41.dim(` [meta: ${typeof s.metadata.plate === "string" ? s.metadata.plate : Object.keys(s.metadata).length + "k"}]`) : "";
|
|
13503
|
+
lines.push(` ${icon} ${s.status.padEnd(13)} ${pc41.cyan(sid)} ${rt} ${runs} ${dur} ${statsCol}${desc}${cont}${metaHint}`);
|
|
11101
13504
|
}
|
|
11102
13505
|
}
|
|
11103
13506
|
if (interactive) {
|
|
@@ -11129,15 +13532,34 @@ orbCommand.command("list").description("List all agent sessions").option("-p, --
|
|
|
11129
13532
|
}
|
|
11130
13533
|
process.stdout.write(renderTable());
|
|
11131
13534
|
});
|
|
11132
|
-
orbCommand.command("inspect").description("Inspect a specific session in detail").argument("<id>", "Session ID (full or partial)").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (id, options) => {
|
|
13535
|
+
orbCommand.command("inspect").description("Inspect a specific session in detail").argument("<id>", "Session ID (full or partial)").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("-r, --results", "Show run results").action(async (id, options) => {
|
|
11133
13536
|
const { flintPath, sessionsDir } = await resolveCtx(options.path);
|
|
11134
13537
|
const session = resolveSession2(sessionsDir, id);
|
|
11135
13538
|
if (!session) {
|
|
11136
13539
|
console.error(pc41.red(`Error: Session not found: ${id}`));
|
|
11137
13540
|
process.exit(1);
|
|
11138
13541
|
}
|
|
13542
|
+
if (healSession(session)) {
|
|
13543
|
+
writeSession(sessionsDir, session);
|
|
13544
|
+
}
|
|
13545
|
+
if (options.results) {
|
|
13546
|
+
const runsWithResults = session.runs.filter((r) => r.result);
|
|
13547
|
+
if (runsWithResults.length === 0) {
|
|
13548
|
+
console.log(pc41.dim("No results for this session."));
|
|
13549
|
+
return;
|
|
13550
|
+
}
|
|
13551
|
+
console.log(`
|
|
13552
|
+
${pc41.bold("Results")} ${pc41.dim(`\u2014 session ${shortId2(session.id)}`)}
|
|
13553
|
+
`);
|
|
13554
|
+
for (const run of runsWithResults) {
|
|
13555
|
+
console.log(` ${pc41.dim(`run ${shortId2(run.id)}`)} ${pc41.dim(formatLocalTime2(run.started))}`);
|
|
13556
|
+
console.log(` ${run.result}`);
|
|
13557
|
+
console.log("");
|
|
13558
|
+
}
|
|
13559
|
+
return;
|
|
13560
|
+
}
|
|
11139
13561
|
console.log(`
|
|
11140
|
-
${pc41.bold("
|
|
13562
|
+
${pc41.bold("Orbh Session")}
|
|
11141
13563
|
`);
|
|
11142
13564
|
console.log(` ${pc41.dim("ID:")} ${session.id}`);
|
|
11143
13565
|
console.log(` ${pc41.dim("Runtime:")} ${session.runtime}`);
|
|
@@ -11149,12 +13571,6 @@ ${pc41.bold("OrbH Session")}
|
|
|
11149
13571
|
console.log(` ${pc41.dim("Updated:")} ${formatLocalTime2(session.updated)}`);
|
|
11150
13572
|
console.log(` ${pc41.dim("Duration:")} ${formatDuration2(session.started, isTerminalStatus2(session.status) ? session.updated : void 0)}`);
|
|
11151
13573
|
if (session.continues) console.log(` ${pc41.dim("Continues:")} ${session.continues}`);
|
|
11152
|
-
const latestRun = getCurrentRun2(session);
|
|
11153
|
-
if (latestRun?.result) {
|
|
11154
|
-
console.log(`
|
|
11155
|
-
${pc41.bold("Result:")} ${pc41.dim(`(run ${shortId2(latestRun.id)})`)}`);
|
|
11156
|
-
console.log(` ${latestRun.result}`);
|
|
11157
|
-
}
|
|
11158
13574
|
const entries = readTranscriptEntries(session, flintPath);
|
|
11159
13575
|
if (entries && entries.length > 0) {
|
|
11160
13576
|
const turns = groupIntoTurns(entries);
|
|
@@ -11214,8 +13630,26 @@ ${pc41.bold("OrbH Session")}
|
|
|
11214
13630
|
console.log(` ${pc41.cyan(key)}: ${val}`);
|
|
11215
13631
|
}
|
|
11216
13632
|
}
|
|
13633
|
+
const meta = session.metadata;
|
|
13634
|
+
if (meta && Object.keys(meta).length > 0) {
|
|
13635
|
+
console.log(`
|
|
13636
|
+
${pc41.bold("Metadata:")}`);
|
|
13637
|
+
for (const [key, val] of Object.entries(meta)) {
|
|
13638
|
+
const display = typeof val === "string" ? val : JSON.stringify(val);
|
|
13639
|
+
console.log(` ${pc41.cyan(key)}: ${display}`);
|
|
13640
|
+
}
|
|
13641
|
+
}
|
|
11217
13642
|
console.log("");
|
|
11218
13643
|
});
|
|
13644
|
+
orbCommand.command("export").description("Export a session transcript to Mesh/Agents/<Runtime>/").argument("<id>", "Session ID (full or partial)").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (id, options) => {
|
|
13645
|
+
const { flintPath, sessionsDir } = await resolveCtx(options.path);
|
|
13646
|
+
const session = resolveSession2(sessionsDir, id);
|
|
13647
|
+
if (!session) {
|
|
13648
|
+
console.error(pc41.red(`Error: Session not found: ${id}`));
|
|
13649
|
+
process.exit(1);
|
|
13650
|
+
}
|
|
13651
|
+
exportSessionTranscript(session, flintPath);
|
|
13652
|
+
});
|
|
11219
13653
|
orbCommand.command("requests").description("View request/response pairs for a session").argument("<id>", "Session ID (full or partial)").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--pending", "Show only unanswered requests").action(async (id, options) => {
|
|
11220
13654
|
const { sessionsDir } = await resolveCtx(options.path);
|
|
11221
13655
|
const session = resolveSession2(sessionsDir, id);
|
|
@@ -11293,7 +13727,7 @@ orbCommand.command("stats").description("Show detailed session statistics \u2014
|
|
|
11293
13727
|
}
|
|
11294
13728
|
}
|
|
11295
13729
|
console.log(`
|
|
11296
|
-
${pc41.bold("
|
|
13730
|
+
${pc41.bold("Orbh Session Stats")} ${pc41.dim("\xB7")} ${pc41.cyan(shortId2(session.id))} ${pc41.dim("\xB7")} ${session.runtime}
|
|
11297
13731
|
`);
|
|
11298
13732
|
console.log(` ${pc41.bold("Overview")}`);
|
|
11299
13733
|
console.log(` Status: ${statusIcon2(session.status)} ${session.status}`);
|
|
@@ -11405,22 +13839,40 @@ orbCommand.command("watch").description("Stream a live session transcript to the
|
|
|
11405
13839
|
process.exit(1);
|
|
11406
13840
|
}
|
|
11407
13841
|
const run = getCurrentRun2(session);
|
|
11408
|
-
|
|
11409
|
-
|
|
13842
|
+
let nativeId = run?.nativeSessionId ?? session.id;
|
|
13843
|
+
let transcriptPath = harness.resolveTranscriptPath(nativeId, flintPath);
|
|
11410
13844
|
const maxLen = options.verbose ? Infinity : 200;
|
|
13845
|
+
if (!transcriptPath && !isTerminalStatus2(session.status)) {
|
|
13846
|
+
const deadline = Date.now() + 3e4;
|
|
13847
|
+
process.stdout.write(pc41.dim("Waiting for transcript path resolution..."));
|
|
13848
|
+
while (Date.now() <= deadline) {
|
|
13849
|
+
await new Promise((resolve11) => setTimeout(resolve11, 500));
|
|
13850
|
+
const fresh = resolveSession2(sessionsDir, id);
|
|
13851
|
+
if (!fresh) break;
|
|
13852
|
+
const freshRun = getCurrentRun2(fresh);
|
|
13853
|
+
const freshNativeId = freshRun?.nativeSessionId ?? fresh.id;
|
|
13854
|
+
transcriptPath = harness.resolveTranscriptPath(freshNativeId, flintPath);
|
|
13855
|
+
if (transcriptPath) {
|
|
13856
|
+
nativeId = freshNativeId;
|
|
13857
|
+
break;
|
|
13858
|
+
}
|
|
13859
|
+
}
|
|
13860
|
+
process.stdout.write("\r\x1B[2K");
|
|
13861
|
+
}
|
|
11411
13862
|
if (!transcriptPath) {
|
|
11412
13863
|
console.error(pc41.red(`Error: Could not resolve transcript path for session ${shortId2(session.id)}`));
|
|
11413
13864
|
process.exit(1);
|
|
11414
13865
|
}
|
|
11415
13866
|
const watchTitle = session.title ? ` ${pc41.dim("\xB7")} ${session.title}` : "";
|
|
11416
|
-
|
|
13867
|
+
const watchMeta = session.metadata && Object.keys(session.metadata).length > 0 ? ` ${pc41.dim("\xB7")} ${pc41.dim(`meta: ${typeof session.metadata.plate === "string" ? session.metadata.plate : Object.keys(session.metadata).length + " keys"}`)}` : "";
|
|
13868
|
+
console.log(`${pc41.bold("Watching")} ${pc41.cyan(shortId2(session.id))} ${pc41.dim("\xB7")} ${session.runtime}${watchTitle} ${pc41.dim("\xB7")} ${statusIcon2(session.status)} ${session.status}${watchMeta}`);
|
|
11417
13869
|
console.log(pc41.dim(transcriptPath));
|
|
11418
13870
|
console.log("");
|
|
11419
|
-
if (!
|
|
13871
|
+
if (!existsSync12(transcriptPath)) {
|
|
11420
13872
|
process.stdout.write(pc41.dim("Waiting for transcript..."));
|
|
11421
13873
|
await new Promise((resolve11, reject) => {
|
|
11422
13874
|
const poll = setInterval(() => {
|
|
11423
|
-
if (
|
|
13875
|
+
if (existsSync12(transcriptPath)) {
|
|
11424
13876
|
clearInterval(poll);
|
|
11425
13877
|
process.stdout.write("\r\x1B[2K");
|
|
11426
13878
|
resolve11();
|
|
@@ -11630,7 +14082,7 @@ orbCommand.command("ask").description("Ask a blocking question and wait for a re
|
|
|
11630
14082
|
session.status = "blocked";
|
|
11631
14083
|
writeSession(sessionsDir, session);
|
|
11632
14084
|
try {
|
|
11633
|
-
|
|
14085
|
+
spawnSync5("osascript", ["-e", `display notification "${question.slice(0, 100)}" with title "Orbh Agent Needs Input"`], { stdio: "ignore" });
|
|
11634
14086
|
} catch {
|
|
11635
14087
|
}
|
|
11636
14088
|
const startTime = Date.now();
|
|
@@ -11664,7 +14116,7 @@ orbCommand.command("request").description("Post a deferred question and exit imm
|
|
|
11664
14116
|
session.status = "deferred";
|
|
11665
14117
|
writeSession(sessionsDir, session);
|
|
11666
14118
|
try {
|
|
11667
|
-
|
|
14119
|
+
spawnSync5("osascript", ["-e", `display notification "${question.slice(0, 100)}" with title "Orbh Agent Needs Input"`], { stdio: "ignore" });
|
|
11668
14120
|
} catch {
|
|
11669
14121
|
}
|
|
11670
14122
|
console.log(`Question posted. Session ${shortId2(session.id)} is now deferred.`);
|
|
@@ -11700,7 +14152,7 @@ orbCommand.command("respond").description("Answer a pending question on a sessio
|
|
|
11700
14152
|
console.log(`Response sent to session ${shortId2(session.id)}`);
|
|
11701
14153
|
console.log(pc41.dim("Deferred question answered \u2014 auto-resuming session..."));
|
|
11702
14154
|
const resumePrompt = `Your deferred question has been answered. Run \`flint orb requests ${session.id}\` to see the response, then continue working.`;
|
|
11703
|
-
|
|
14155
|
+
spawnSync5("flint", ["orb", "resume", session.id, resumePrompt], {
|
|
11704
14156
|
cwd: process.cwd(),
|
|
11705
14157
|
stdio: "inherit"
|
|
11706
14158
|
});
|
|
@@ -11713,24 +14165,24 @@ orbCommand.command("respond").description("Answer a pending question on a sessio
|
|
|
11713
14165
|
|
|
11714
14166
|
// src/index.ts
|
|
11715
14167
|
var __dirname3 = dirname4(fileURLToPath3(import.meta.url));
|
|
11716
|
-
var pkg = JSON.parse(
|
|
14168
|
+
var pkg = JSON.parse(readFileSync10(join18(__dirname3, "..", "package.json"), "utf-8"));
|
|
11717
14169
|
var runtime = resolveRuntimeSync({ cliname: "flint" });
|
|
11718
14170
|
var devAvailable = runtime.mode === "dev";
|
|
11719
14171
|
var newDir = getConfigDir("flint");
|
|
11720
|
-
var oldDir = join18(
|
|
11721
|
-
var intermediateDir = join18(
|
|
14172
|
+
var oldDir = join18(homedir10(), ".flint");
|
|
14173
|
+
var intermediateDir = join18(homedir10(), ".nuucognition", ".flint");
|
|
11722
14174
|
function migrateDir(sourceDir, label) {
|
|
11723
|
-
if (!
|
|
14175
|
+
if (!existsSync13(sourceDir)) return false;
|
|
11724
14176
|
try {
|
|
11725
|
-
const entries =
|
|
14177
|
+
const entries = readdirSync7(sourceDir);
|
|
11726
14178
|
const filesToMigrate = entries.filter((e) => !e.startsWith(".DS_Store"));
|
|
11727
14179
|
if (filesToMigrate.length === 0) return false;
|
|
11728
|
-
|
|
14180
|
+
mkdirSync5(newDir, { recursive: true });
|
|
11729
14181
|
let migrated = 0;
|
|
11730
14182
|
for (const entry of filesToMigrate) {
|
|
11731
14183
|
const src = join18(sourceDir, entry);
|
|
11732
14184
|
const dest = join18(newDir, entry);
|
|
11733
|
-
if (!
|
|
14185
|
+
if (!existsSync13(dest)) {
|
|
11734
14186
|
cpSync(src, dest, { recursive: true });
|
|
11735
14187
|
migrated++;
|
|
11736
14188
|
}
|
|
@@ -11834,3 +14286,42 @@ program.on("command:*", (operands) => {
|
|
|
11834
14286
|
process.exit(1);
|
|
11835
14287
|
});
|
|
11836
14288
|
await program.parseAsync(process.argv);
|
|
14289
|
+
/*! Bundled license information:
|
|
14290
|
+
|
|
14291
|
+
smol-toml/dist/error.js:
|
|
14292
|
+
smol-toml/dist/util.js:
|
|
14293
|
+
smol-toml/dist/date.js:
|
|
14294
|
+
smol-toml/dist/primitive.js:
|
|
14295
|
+
smol-toml/dist/extract.js:
|
|
14296
|
+
smol-toml/dist/struct.js:
|
|
14297
|
+
smol-toml/dist/parse.js:
|
|
14298
|
+
smol-toml/dist/stringify.js:
|
|
14299
|
+
smol-toml/dist/index.js:
|
|
14300
|
+
(*!
|
|
14301
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
14302
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
14303
|
+
*
|
|
14304
|
+
* Redistribution and use in source and binary forms, with or without
|
|
14305
|
+
* modification, are permitted provided that the following conditions are met:
|
|
14306
|
+
*
|
|
14307
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
14308
|
+
* list of conditions and the following disclaimer.
|
|
14309
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
14310
|
+
* this list of conditions and the following disclaimer in the
|
|
14311
|
+
* documentation and/or other materials provided with the distribution.
|
|
14312
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
14313
|
+
* may be used to endorse or promote products derived from this software without
|
|
14314
|
+
* specific prior written permission.
|
|
14315
|
+
*
|
|
14316
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
14317
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
14318
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
14319
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
14320
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
14321
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
14322
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
14323
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
14324
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
14325
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
14326
|
+
*)
|
|
14327
|
+
*/
|