lobstah-openclaw-plugin 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +825 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { definePluginEntry } from "openclaw/plugin-sdk/core";
|
|
3
3
|
|
|
4
4
|
// apps/node/src/tools.ts
|
|
5
|
-
import * as
|
|
6
|
-
import * as
|
|
5
|
+
import * as fs7 from "node:fs";
|
|
6
|
+
import * as path5 from "node:path";
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
8
|
|
|
9
9
|
// packages/core/dist/types.js
|
|
@@ -119,6 +119,729 @@ function requestCancel(id, lane) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
// packages/core/dist/config.js
|
|
122
|
+
import * as fs4 from "node:fs";
|
|
123
|
+
import * as os2 from "node:os";
|
|
124
|
+
import * as path3 from "node:path";
|
|
125
|
+
|
|
126
|
+
// node_modules/.pnpm/smol-toml@1.8.0/node_modules/smol-toml/dist/date.js
|
|
127
|
+
var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
128
|
+
var TomlDate = class _TomlDate extends Date {
|
|
129
|
+
#hasDate = false;
|
|
130
|
+
#hasTime = false;
|
|
131
|
+
#offset = null;
|
|
132
|
+
constructor(date) {
|
|
133
|
+
let hasDate = true;
|
|
134
|
+
let hasTime = true;
|
|
135
|
+
let offset = "Z";
|
|
136
|
+
if (typeof date === "string") {
|
|
137
|
+
let match = date.match(DATE_TIME_RE);
|
|
138
|
+
if (match) {
|
|
139
|
+
if (!match[1]) {
|
|
140
|
+
hasDate = false;
|
|
141
|
+
date = `0000-01-01T${date}`;
|
|
142
|
+
}
|
|
143
|
+
hasTime = !!match[2];
|
|
144
|
+
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
145
|
+
if (match[2] && +match[2] > 23) {
|
|
146
|
+
date = "";
|
|
147
|
+
} else {
|
|
148
|
+
offset = match[3] || null;
|
|
149
|
+
date = date.toUpperCase();
|
|
150
|
+
if (!offset && hasTime)
|
|
151
|
+
date += "Z";
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
date = "";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
super(date);
|
|
158
|
+
if (!isNaN(this.getTime())) {
|
|
159
|
+
this.#hasDate = hasDate;
|
|
160
|
+
this.#hasTime = hasTime;
|
|
161
|
+
this.#offset = offset;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
isDateTime() {
|
|
165
|
+
return this.#hasDate && this.#hasTime;
|
|
166
|
+
}
|
|
167
|
+
isLocal() {
|
|
168
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
169
|
+
}
|
|
170
|
+
isDate() {
|
|
171
|
+
return this.#hasDate && !this.#hasTime;
|
|
172
|
+
}
|
|
173
|
+
isTime() {
|
|
174
|
+
return this.#hasTime && !this.#hasDate;
|
|
175
|
+
}
|
|
176
|
+
isValid() {
|
|
177
|
+
return this.#hasDate || this.#hasTime;
|
|
178
|
+
}
|
|
179
|
+
toISOString() {
|
|
180
|
+
let iso = super.toISOString();
|
|
181
|
+
if (this.isDate())
|
|
182
|
+
return iso.slice(0, 10);
|
|
183
|
+
if (this.isTime())
|
|
184
|
+
return iso.slice(11, 23);
|
|
185
|
+
if (this.#offset === null)
|
|
186
|
+
return iso.slice(0, -1);
|
|
187
|
+
if (this.#offset === "Z")
|
|
188
|
+
return iso;
|
|
189
|
+
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
190
|
+
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
191
|
+
let offsetDate = new Date(this.getTime() - offset * 6e4);
|
|
192
|
+
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
193
|
+
}
|
|
194
|
+
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
195
|
+
let date = new _TomlDate(jsDate);
|
|
196
|
+
date.#offset = offset;
|
|
197
|
+
return date;
|
|
198
|
+
}
|
|
199
|
+
static wrapAsLocalDateTime(jsDate) {
|
|
200
|
+
let date = new _TomlDate(jsDate);
|
|
201
|
+
date.#offset = null;
|
|
202
|
+
return date;
|
|
203
|
+
}
|
|
204
|
+
static wrapAsLocalDate(jsDate) {
|
|
205
|
+
let date = new _TomlDate(jsDate);
|
|
206
|
+
date.#hasTime = false;
|
|
207
|
+
date.#offset = null;
|
|
208
|
+
return date;
|
|
209
|
+
}
|
|
210
|
+
static wrapAsLocalTime(jsDate) {
|
|
211
|
+
let date = new _TomlDate(jsDate);
|
|
212
|
+
date.#hasDate = false;
|
|
213
|
+
date.#offset = null;
|
|
214
|
+
return date;
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// node_modules/.pnpm/smol-toml@1.8.0/node_modules/smol-toml/dist/error.js
|
|
219
|
+
function getLineColFromPtr(string, ptr) {
|
|
220
|
+
let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
|
|
221
|
+
return [lines.length, lines.pop().length + 1];
|
|
222
|
+
}
|
|
223
|
+
function makeCodeBlock(string, line, column) {
|
|
224
|
+
let lines = string.split(/\r\n|\n|\r/g);
|
|
225
|
+
let codeblock = "";
|
|
226
|
+
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
227
|
+
for (let i = line - 1; i <= line + 1; i++) {
|
|
228
|
+
let l = lines[i - 1];
|
|
229
|
+
if (!l)
|
|
230
|
+
continue;
|
|
231
|
+
codeblock += i.toString().padEnd(numberLen, " ");
|
|
232
|
+
codeblock += ": ";
|
|
233
|
+
codeblock += l;
|
|
234
|
+
codeblock += "\n";
|
|
235
|
+
if (i === line) {
|
|
236
|
+
codeblock += " ".repeat(numberLen + column + 2);
|
|
237
|
+
codeblock += "^\n";
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return codeblock;
|
|
241
|
+
}
|
|
242
|
+
var TomlError = class extends Error {
|
|
243
|
+
line;
|
|
244
|
+
column;
|
|
245
|
+
codeblock;
|
|
246
|
+
constructor(message, options) {
|
|
247
|
+
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
|
248
|
+
const codeblock = makeCodeBlock(options.toml, line, column);
|
|
249
|
+
super(`Invalid TOML document: ${message}
|
|
250
|
+
|
|
251
|
+
${codeblock}`, options);
|
|
252
|
+
this.line = line;
|
|
253
|
+
this.column = column;
|
|
254
|
+
this.codeblock = codeblock;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// node_modules/.pnpm/smol-toml@1.8.0/node_modules/smol-toml/dist/util.js
|
|
259
|
+
function indexOfNewline(str, start = 0) {
|
|
260
|
+
let idx = str.indexOf("\n", start);
|
|
261
|
+
if (str.charCodeAt(idx - 1) === 13)
|
|
262
|
+
idx--;
|
|
263
|
+
return idx;
|
|
264
|
+
}
|
|
265
|
+
function skipComment(ctx) {
|
|
266
|
+
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
267
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
268
|
+
if (c === 10)
|
|
269
|
+
break;
|
|
270
|
+
if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) {
|
|
271
|
+
ctx.p++;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
if (c < 32 && c !== 9 || c === 127) {
|
|
275
|
+
throw new TomlError("control characters are not allowed in comments", {
|
|
276
|
+
toml: ctx.s,
|
|
277
|
+
ptr: ctx.p
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function skipVoid(ctx, banNewLines, banComments) {
|
|
283
|
+
let c;
|
|
284
|
+
while (1) {
|
|
285
|
+
while ((c = ctx.s.charCodeAt(ctx.p)) === 32 || c === 9 || !banNewLines && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10))
|
|
286
|
+
ctx.p++;
|
|
287
|
+
if (banComments || c !== 35)
|
|
288
|
+
break;
|
|
289
|
+
skipComment(ctx);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function skipUntil(ctx, sep, end) {
|
|
293
|
+
let ptr = ctx.p;
|
|
294
|
+
if (!end) {
|
|
295
|
+
ptr = indexOfNewline(ctx.s, ptr);
|
|
296
|
+
ctx.p = ptr < 0 ? ctx.s.length : ptr;
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
300
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
301
|
+
if (c === 35) {
|
|
302
|
+
skipComment(ctx);
|
|
303
|
+
} else if (c === end || c === sep) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
throw new TomlError("cannot find end of structure", {
|
|
308
|
+
toml: ctx.s,
|
|
309
|
+
ptr
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// node_modules/.pnpm/smol-toml@1.8.0/node_modules/smol-toml/dist/primitive.js
|
|
314
|
+
var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
|
|
315
|
+
var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
|
|
316
|
+
var LEADING_ZERO = /^[+-]?0[0-9_]/;
|
|
317
|
+
function parseString(ctx) {
|
|
318
|
+
let start = ctx.p;
|
|
319
|
+
let c = ctx.s.charCodeAt(ctx.p++);
|
|
320
|
+
let first = c;
|
|
321
|
+
let isLiteral = c === 39;
|
|
322
|
+
let isMultiline = c === ctx.s.charCodeAt(ctx.p) && c === ctx.s.charCodeAt(ctx.p + 1);
|
|
323
|
+
if (isMultiline) {
|
|
324
|
+
if ((c = ctx.s.charCodeAt(ctx.p += 2)) === 10)
|
|
325
|
+
ctx.p++;
|
|
326
|
+
else if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)
|
|
327
|
+
ctx.p += 2;
|
|
328
|
+
}
|
|
329
|
+
let parsed = "";
|
|
330
|
+
let sliceStart = ctx.p;
|
|
331
|
+
let state = 0;
|
|
332
|
+
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
333
|
+
c = ctx.s.charCodeAt(ctx.p);
|
|
334
|
+
if (isMultiline && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)) {
|
|
335
|
+
state = state && 3;
|
|
336
|
+
} else if (c < 32 && c !== 9 || c === 127) {
|
|
337
|
+
throw new TomlError("control characters are not allowed in strings", {
|
|
338
|
+
toml: ctx.s,
|
|
339
|
+
ptr: ctx.p
|
|
340
|
+
});
|
|
341
|
+
} else if ((!state || state === 3) && c === first && (!isMultiline || ctx.s.charCodeAt(ctx.p + 1) === first && ctx.s.charCodeAt(ctx.p + 2) === first)) {
|
|
342
|
+
if (isMultiline) {
|
|
343
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first)
|
|
344
|
+
ctx.p++;
|
|
345
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first)
|
|
346
|
+
ctx.p++;
|
|
347
|
+
}
|
|
348
|
+
if (!state)
|
|
349
|
+
parsed += ctx.s.slice(sliceStart, ctx.p);
|
|
350
|
+
ctx.p += isMultiline ? 3 : 1;
|
|
351
|
+
return parsed;
|
|
352
|
+
} else if (!state) {
|
|
353
|
+
if (!isLiteral && c === 92) {
|
|
354
|
+
parsed += ctx.s.slice(sliceStart, sliceStart = ctx.p);
|
|
355
|
+
state = 1;
|
|
356
|
+
}
|
|
357
|
+
} else if (state === 1) {
|
|
358
|
+
if (c === 120 || c === 117 || c === 85) {
|
|
359
|
+
let value = 0;
|
|
360
|
+
let len = c === 120 ? 2 : c === 117 ? 4 : 8;
|
|
361
|
+
for (let j = 0; j < len; j++, ctx.p++) {
|
|
362
|
+
let hex = ctx.s.charCodeAt(ctx.p + 1);
|
|
363
|
+
let digit = (
|
|
364
|
+
/* 0-9 */
|
|
365
|
+
hex >= 48 && hex <= 57 ? hex - 48 : (
|
|
366
|
+
/* A-F */
|
|
367
|
+
hex >= 65 && hex <= 70 ? hex - 65 + 10 : (
|
|
368
|
+
/* a-f */
|
|
369
|
+
hex >= 97 && hex <= 102 ? hex - 97 + 10 : -1
|
|
370
|
+
)
|
|
371
|
+
)
|
|
372
|
+
);
|
|
373
|
+
if (digit < 0)
|
|
374
|
+
throw new TomlError("invalid non-hex character in unicode escape", { toml: ctx.s, ptr: ctx.p + 1 });
|
|
375
|
+
value = value << 4 | digit;
|
|
376
|
+
}
|
|
377
|
+
if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
|
|
378
|
+
throw new TomlError("invalid unicode escape", { toml: ctx.s, ptr: ctx.p });
|
|
379
|
+
}
|
|
380
|
+
parsed += String.fromCodePoint(value);
|
|
381
|
+
sliceStart = ctx.p + 1;
|
|
382
|
+
state = 0;
|
|
383
|
+
} else if (c === 32 || c === 9) {
|
|
384
|
+
state = 2;
|
|
385
|
+
} else {
|
|
386
|
+
if (c === 98)
|
|
387
|
+
parsed += "\b";
|
|
388
|
+
else if (c === 116)
|
|
389
|
+
parsed += " ";
|
|
390
|
+
else if (c === 110)
|
|
391
|
+
parsed += "\n";
|
|
392
|
+
else if (c === 102)
|
|
393
|
+
parsed += "\f";
|
|
394
|
+
else if (c === 114)
|
|
395
|
+
parsed += "\r";
|
|
396
|
+
else if (c === 101)
|
|
397
|
+
parsed += "\x1B";
|
|
398
|
+
else if (c === 34)
|
|
399
|
+
parsed += '"';
|
|
400
|
+
else if (c === 92)
|
|
401
|
+
parsed += "\\";
|
|
402
|
+
else
|
|
403
|
+
throw new TomlError("unrecognized escape sequence", { toml: ctx.s, ptr: ctx.p });
|
|
404
|
+
sliceStart = ctx.p + 1;
|
|
405
|
+
state = 0;
|
|
406
|
+
}
|
|
407
|
+
} else if (c !== 32 && c !== 9) {
|
|
408
|
+
if (state === 2) {
|
|
409
|
+
throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
|
|
410
|
+
toml: ctx.s,
|
|
411
|
+
ptr: sliceStart
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
state = !isLiteral && c === 92 ? 1 : 0;
|
|
415
|
+
sliceStart = ctx.p;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
throw new TomlError("unfinished string", { toml: ctx.s, ptr: start });
|
|
419
|
+
}
|
|
420
|
+
function sliceAndTrimEndOf(ctx, start, end) {
|
|
421
|
+
let value = ctx.s.slice(start, end);
|
|
422
|
+
let commentIdx = value.indexOf("#");
|
|
423
|
+
if (commentIdx > 0) {
|
|
424
|
+
skipComment({ s: value, p: commentIdx, d: 0 });
|
|
425
|
+
value = value.slice(0, commentIdx);
|
|
426
|
+
}
|
|
427
|
+
return value.trimEnd();
|
|
428
|
+
}
|
|
429
|
+
function parseValue(ctx, integersAsBigInt, end) {
|
|
430
|
+
let ptr = ctx.p;
|
|
431
|
+
let err = { toml: ctx.s, ptr };
|
|
432
|
+
skipUntil(ctx, 44, end);
|
|
433
|
+
let value = sliceAndTrimEndOf(ctx, ptr, ctx.p);
|
|
434
|
+
if (!value)
|
|
435
|
+
throw new TomlError("incomplete declaration: value expected", err);
|
|
436
|
+
if (value === "-inf")
|
|
437
|
+
return -Infinity;
|
|
438
|
+
if (value === "inf" || value === "+inf")
|
|
439
|
+
return Infinity;
|
|
440
|
+
if (value === "nan" || value === "+nan" || value === "-nan")
|
|
441
|
+
return NaN;
|
|
442
|
+
if (value === "-0")
|
|
443
|
+
return integersAsBigInt ? 0n : 0;
|
|
444
|
+
let isInt = INT_REGEX.test(value);
|
|
445
|
+
if (isInt || FLOAT_REGEX.test(value)) {
|
|
446
|
+
if (LEADING_ZERO.test(value)) {
|
|
447
|
+
throw new TomlError("leading zeroes are not allowed", err);
|
|
448
|
+
}
|
|
449
|
+
value = value.replace(/_/g, "");
|
|
450
|
+
let numeric = +value;
|
|
451
|
+
if (isNaN(numeric)) {
|
|
452
|
+
throw new TomlError("invalid number", err);
|
|
453
|
+
}
|
|
454
|
+
if (isInt) {
|
|
455
|
+
if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
|
|
456
|
+
throw new TomlError("integer value cannot be represented losslessly", err);
|
|
457
|
+
}
|
|
458
|
+
if (isInt || integersAsBigInt === true)
|
|
459
|
+
numeric = BigInt(value);
|
|
460
|
+
}
|
|
461
|
+
return numeric;
|
|
462
|
+
}
|
|
463
|
+
const date = new TomlDate(value);
|
|
464
|
+
if (!date.isValid())
|
|
465
|
+
throw new TomlError("invalid value", err);
|
|
466
|
+
return date;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// node_modules/.pnpm/smol-toml@1.8.0/node_modules/smol-toml/dist/extract.js
|
|
470
|
+
function extractValue(ctx, end, integersAsBigInt) {
|
|
471
|
+
let ptr = ctx.p;
|
|
472
|
+
let c = ctx.s.charCodeAt(ptr);
|
|
473
|
+
if (c === 91 || c === 123) {
|
|
474
|
+
if (!ctx.d--) {
|
|
475
|
+
throw new TomlError("document contains excessively nested structures. aborting.", {
|
|
476
|
+
toml: ctx.s,
|
|
477
|
+
ptr
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
let value = c === 91 ? parseArray(ctx, integersAsBigInt) : parseInlineTable(ctx, integersAsBigInt);
|
|
481
|
+
ctx.d++;
|
|
482
|
+
return value;
|
|
483
|
+
}
|
|
484
|
+
if (c === 34 || c === 39) {
|
|
485
|
+
return parseString(ctx);
|
|
486
|
+
}
|
|
487
|
+
if (c === 116) {
|
|
488
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 114 || ctx.s.charCodeAt(++ctx.p) !== 117 || ctx.s.charCodeAt(++ctx.p) !== 101)
|
|
489
|
+
throw new TomlError("invalid value", { toml: ctx.s, ptr });
|
|
490
|
+
ctx.p++;
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
493
|
+
if (c === 102) {
|
|
494
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 108 || ctx.s.charCodeAt(++ctx.p) !== 115 || ctx.s.charCodeAt(++ctx.p) !== 101)
|
|
495
|
+
throw new TomlError("invalid value", { toml: ctx.s, ptr });
|
|
496
|
+
ctx.p++;
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
return parseValue(ctx, integersAsBigInt, end);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// node_modules/.pnpm/smol-toml@1.8.0/node_modules/smol-toml/dist/struct.js
|
|
503
|
+
var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
|
|
504
|
+
function parseKey(ctx, end = "=") {
|
|
505
|
+
let start = ctx.p;
|
|
506
|
+
let dot = start - 1;
|
|
507
|
+
let parsed = [];
|
|
508
|
+
let endPtr = ctx.s.indexOf(end, start);
|
|
509
|
+
if (endPtr < 0) {
|
|
510
|
+
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
511
|
+
toml: ctx.s,
|
|
512
|
+
ptr: start
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
do {
|
|
516
|
+
let c = ctx.s.charCodeAt(ctx.p = ++dot);
|
|
517
|
+
if (c !== 32 && c !== 9) {
|
|
518
|
+
if (c === 34 || c === 39) {
|
|
519
|
+
if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2)) {
|
|
520
|
+
throw new TomlError("multiline strings are not allowed in keys", {
|
|
521
|
+
toml: ctx.s,
|
|
522
|
+
ptr: ctx.p
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
let part = parseString(ctx);
|
|
526
|
+
dot = ctx.s.indexOf(".", ctx.p);
|
|
527
|
+
let strEnd = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
528
|
+
let newLine = indexOfNewline(strEnd);
|
|
529
|
+
if (newLine > -1) {
|
|
530
|
+
throw new TomlError("newlines are not allowed in keys", {
|
|
531
|
+
toml: ctx.s,
|
|
532
|
+
ptr: newLine
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
if (strEnd.trimStart()) {
|
|
536
|
+
throw new TomlError("found extra tokens after the string part", {
|
|
537
|
+
toml: ctx.s,
|
|
538
|
+
ptr: ctx.p
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
if (endPtr < ctx.p) {
|
|
542
|
+
endPtr = ctx.s.indexOf(end, ctx.p);
|
|
543
|
+
if (endPtr < 0) {
|
|
544
|
+
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
545
|
+
toml: ctx.s,
|
|
546
|
+
ptr: start
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
parsed.push(part);
|
|
551
|
+
} else {
|
|
552
|
+
dot = ctx.s.indexOf(".", ctx.p);
|
|
553
|
+
let part = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
554
|
+
if (!KEY_PART_RE.test(part)) {
|
|
555
|
+
throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
|
|
556
|
+
toml: ctx.s,
|
|
557
|
+
ptr: ctx.p
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
parsed.push(part.trimEnd());
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
} while (dot + 1 && dot < endPtr);
|
|
564
|
+
ctx.p = endPtr + 1;
|
|
565
|
+
skipVoid(ctx, true, true);
|
|
566
|
+
return parsed;
|
|
567
|
+
}
|
|
568
|
+
function parseInlineTable(ctx, integersAsBigInt) {
|
|
569
|
+
let res = {};
|
|
570
|
+
let seen = /* @__PURE__ */ new Set();
|
|
571
|
+
let c;
|
|
572
|
+
ctx.p++;
|
|
573
|
+
while (ctx.p < ctx.s.length) {
|
|
574
|
+
skipVoid(ctx);
|
|
575
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 125) {
|
|
576
|
+
ctx.p++;
|
|
577
|
+
return res;
|
|
578
|
+
}
|
|
579
|
+
let k;
|
|
580
|
+
let t = res;
|
|
581
|
+
let hasOwn = false;
|
|
582
|
+
let p = ctx.p;
|
|
583
|
+
let key = parseKey(ctx);
|
|
584
|
+
for (let i = 0; i < key.length; i++) {
|
|
585
|
+
if (i)
|
|
586
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
587
|
+
k = key[i];
|
|
588
|
+
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
|
|
589
|
+
throw new TomlError("trying to redefine an already defined value", {
|
|
590
|
+
toml: ctx.s,
|
|
591
|
+
ptr: p
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
if (!hasOwn && k === "__proto__") {
|
|
595
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (hasOwn) {
|
|
599
|
+
throw new TomlError("trying to redefine an already defined value", {
|
|
600
|
+
toml: ctx.s,
|
|
601
|
+
ptr: ctx.p
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
let value = extractValue(ctx, 125, integersAsBigInt);
|
|
605
|
+
seen.add(t[k] = value);
|
|
606
|
+
skipVoid(ctx);
|
|
607
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 125) {
|
|
608
|
+
return res;
|
|
609
|
+
}
|
|
610
|
+
if (c !== 44) {
|
|
611
|
+
throw new TomlError("expected comma or end of structure", { toml: ctx.s, ptr: ctx.p - 1 });
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
throw new TomlError("unfinished table encountered", {
|
|
615
|
+
toml: ctx.s,
|
|
616
|
+
ptr: ctx.p
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
function parseArray(ctx, integersAsBigInt) {
|
|
620
|
+
let res = [];
|
|
621
|
+
let c;
|
|
622
|
+
ctx.p++;
|
|
623
|
+
while (ctx.p < ctx.s.length) {
|
|
624
|
+
skipVoid(ctx);
|
|
625
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 93) {
|
|
626
|
+
ctx.p++;
|
|
627
|
+
return res;
|
|
628
|
+
}
|
|
629
|
+
res.push(extractValue(ctx, 93, integersAsBigInt));
|
|
630
|
+
skipVoid(ctx);
|
|
631
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 93) {
|
|
632
|
+
return res;
|
|
633
|
+
}
|
|
634
|
+
if (c !== 44) {
|
|
635
|
+
throw new TomlError("expected comma or end of structure", { toml: ctx.s, ptr: ctx.p - 1 });
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
throw new TomlError("unfinished array encountered", {
|
|
639
|
+
toml: ctx.s,
|
|
640
|
+
ptr: ctx.p
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// node_modules/.pnpm/smol-toml@1.8.0/node_modules/smol-toml/dist/parse.js
|
|
645
|
+
function peekTable(key, table, meta, type) {
|
|
646
|
+
let t = table;
|
|
647
|
+
let m = meta;
|
|
648
|
+
let k;
|
|
649
|
+
let hasOwn = false;
|
|
650
|
+
let state;
|
|
651
|
+
for (let i = 0; i < key.length; i++) {
|
|
652
|
+
if (i) {
|
|
653
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
654
|
+
m = (state = m[k]).c;
|
|
655
|
+
if (type === 0 && (state.t === 1 || state.t === 2)) {
|
|
656
|
+
return null;
|
|
657
|
+
}
|
|
658
|
+
if (state.t === 2) {
|
|
659
|
+
let l = t.length - 1;
|
|
660
|
+
t = t[l];
|
|
661
|
+
m = m[l].c;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
k = key[i];
|
|
665
|
+
if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) {
|
|
666
|
+
return null;
|
|
667
|
+
}
|
|
668
|
+
if (!hasOwn) {
|
|
669
|
+
if (k === "__proto__") {
|
|
670
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
671
|
+
Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
|
|
672
|
+
}
|
|
673
|
+
m[k] = {
|
|
674
|
+
t: i < key.length - 1 && type === 2 ? 3 : type,
|
|
675
|
+
d: false,
|
|
676
|
+
i: 0,
|
|
677
|
+
c: {}
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
state = m[k];
|
|
682
|
+
if (state.t !== type && !(type === 1 && state.t === 3)) {
|
|
683
|
+
return null;
|
|
684
|
+
}
|
|
685
|
+
if (type === 2) {
|
|
686
|
+
if (!state.d) {
|
|
687
|
+
state.d = true;
|
|
688
|
+
t[k] = [];
|
|
689
|
+
}
|
|
690
|
+
t[k].push(t = {});
|
|
691
|
+
state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} };
|
|
692
|
+
}
|
|
693
|
+
if (state.d) {
|
|
694
|
+
return null;
|
|
695
|
+
}
|
|
696
|
+
state.d = true;
|
|
697
|
+
if (type === 1) {
|
|
698
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
699
|
+
} else if (type === 0 && hasOwn) {
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
return [k, t, state.c];
|
|
703
|
+
}
|
|
704
|
+
function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
705
|
+
let ctx = { s: toml, p: 0, d: maxDepth };
|
|
706
|
+
let res = {};
|
|
707
|
+
let meta = {};
|
|
708
|
+
let tmp;
|
|
709
|
+
let tbl = res;
|
|
710
|
+
let m = meta;
|
|
711
|
+
skipVoid(ctx);
|
|
712
|
+
while (ctx.p < toml.length) {
|
|
713
|
+
if (toml.charCodeAt(ctx.p) === 91) {
|
|
714
|
+
let isTableArray = toml.charCodeAt(++ctx.p) === 91;
|
|
715
|
+
tmp = ctx.p += +isTableArray;
|
|
716
|
+
let k = parseKey(ctx, "]");
|
|
717
|
+
if (isTableArray) {
|
|
718
|
+
if (toml.charCodeAt(ctx.p - 1) !== 93) {
|
|
719
|
+
throw new TomlError("expected end of table declaration", {
|
|
720
|
+
toml,
|
|
721
|
+
ptr: ctx.p - 1
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
ctx.p++;
|
|
725
|
+
}
|
|
726
|
+
let p = peekTable(
|
|
727
|
+
k,
|
|
728
|
+
res,
|
|
729
|
+
meta,
|
|
730
|
+
isTableArray ? 2 : 1
|
|
731
|
+
/* Type.EXPLICIT */
|
|
732
|
+
);
|
|
733
|
+
if (!p) {
|
|
734
|
+
throw new TomlError("trying to redefine an already defined table or value", {
|
|
735
|
+
toml,
|
|
736
|
+
ptr: tmp
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
m = p[2];
|
|
740
|
+
tbl = p[1];
|
|
741
|
+
} else {
|
|
742
|
+
tmp = ctx.p;
|
|
743
|
+
let k = parseKey(ctx);
|
|
744
|
+
let p = peekTable(
|
|
745
|
+
k,
|
|
746
|
+
tbl,
|
|
747
|
+
m,
|
|
748
|
+
0
|
|
749
|
+
/* Type.DOTTED */
|
|
750
|
+
);
|
|
751
|
+
if (!p) {
|
|
752
|
+
throw new TomlError("trying to redefine an already defined table or value", {
|
|
753
|
+
toml,
|
|
754
|
+
ptr: tmp
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
p[1][p[0]] = extractValue(ctx, void 0, integersAsBigInt);
|
|
758
|
+
}
|
|
759
|
+
skipVoid(ctx, true);
|
|
760
|
+
if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 10 && tmp !== 13) {
|
|
761
|
+
throw new TomlError("each key-value declaration must be followed by an end-of-line", {
|
|
762
|
+
toml,
|
|
763
|
+
ptr: ctx.p
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
skipVoid(ctx);
|
|
767
|
+
}
|
|
768
|
+
return res;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// packages/core/dist/config.js
|
|
772
|
+
var POOL_NAME = /^[A-Za-z0-9_-]+$/;
|
|
773
|
+
function parsePools(raw, repos) {
|
|
774
|
+
const out = {};
|
|
775
|
+
if (raw === void 0)
|
|
776
|
+
return out;
|
|
777
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
778
|
+
throw new Error(`[pools] must be a table of pools in ${configPath()}`);
|
|
779
|
+
for (const [name, p] of Object.entries(raw)) {
|
|
780
|
+
const where = `[pools.${name}] in ${configPath()}`;
|
|
781
|
+
if (!POOL_NAME.test(name))
|
|
782
|
+
throw new Error(`${where}: a pool name may use letters, digits, "-" and "_" only`);
|
|
783
|
+
const repo = String(p?.repo ?? "");
|
|
784
|
+
if (!repos[repo])
|
|
785
|
+
throw new Error(`${where}: repo "${repo}" is not a configured [repos.<key>]`);
|
|
786
|
+
const size = p.size ?? 1;
|
|
787
|
+
if (typeof size !== "number" || !Number.isInteger(size) || size < 1)
|
|
788
|
+
throw new Error(`${where}: size must be a positive integer`);
|
|
789
|
+
const overflow = p.overflow ?? "headless";
|
|
790
|
+
if (overflow !== "headless" && overflow !== "queue")
|
|
791
|
+
throw new Error(`${where}: overflow must be "headless" or "queue"`);
|
|
792
|
+
out[name] = { repo, size, overflow };
|
|
793
|
+
}
|
|
794
|
+
return out;
|
|
795
|
+
}
|
|
796
|
+
var BRIEF_KINDS = ["conflict", "checks", "review", "ciFix", "rebase"];
|
|
797
|
+
function parseBriefHooks(raw) {
|
|
798
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
799
|
+
return void 0;
|
|
800
|
+
const out = {};
|
|
801
|
+
for (const kind of [...BRIEF_KINDS, "all"]) {
|
|
802
|
+
const text2 = raw[kind];
|
|
803
|
+
if (typeof text2 === "string" && text2.trim())
|
|
804
|
+
out[kind] = text2.trim();
|
|
805
|
+
}
|
|
806
|
+
return Object.keys(out).length ? out : void 0;
|
|
807
|
+
}
|
|
808
|
+
var ATTENTION_KINDS = ["question", "decision", "landed", "pr:draft", "pr:review", "pr:checks", "pr:conflict", "pr:ready", "report", "stack-ready"];
|
|
809
|
+
var DEFAULT_ATTENTION_KINDS = ["question", "decision", "pr:ready", "pr:review", "pr:conflict", "pr:checks"];
|
|
810
|
+
function parseAttentionKinds(raw) {
|
|
811
|
+
if (raw === void 0)
|
|
812
|
+
return [...DEFAULT_ATTENTION_KINDS];
|
|
813
|
+
if (!Array.isArray(raw)) {
|
|
814
|
+
throw new Error(`attentionKinds must be an array of kinds (${ATTENTION_KINDS.join(", ")}) in ${configPath()}`);
|
|
815
|
+
}
|
|
816
|
+
for (const k of raw) {
|
|
817
|
+
if (!ATTENTION_KINDS.includes(k)) {
|
|
818
|
+
throw new Error(`attentionKinds: unknown kind "${String(k)}" in ${configPath()} \u2014 valid kinds: ${ATTENTION_KINDS.join(", ")}`);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
return [...new Set(raw)];
|
|
822
|
+
}
|
|
823
|
+
function parseSoak(raw) {
|
|
824
|
+
const soak = { ...DEFAULT_SOAK, ...raw ?? {} };
|
|
825
|
+
if (soak.terminal !== void 0 && soak.terminal !== "terminal" && soak.terminal !== "iterm") {
|
|
826
|
+
throw new Error(`soak.terminal: unknown terminal "${String(soak.terminal)}" in ${configPath()} \u2014 use "terminal" or "iterm"`);
|
|
827
|
+
}
|
|
828
|
+
return soak;
|
|
829
|
+
}
|
|
830
|
+
var DEFAULT_SOAK = {
|
|
831
|
+
deferSecs: 90,
|
|
832
|
+
claimIdleNoticeSecs: 180,
|
|
833
|
+
ttlSecs: 1800,
|
|
834
|
+
beat: true,
|
|
835
|
+
pausedTtlSecs: 86400,
|
|
836
|
+
signOffGraceSecs: 600
|
|
837
|
+
};
|
|
838
|
+
var DEFAULT_HELM = {
|
|
839
|
+
ttlSecs: 1800,
|
|
840
|
+
reportSecs: 900,
|
|
841
|
+
armGraceSecs: 5
|
|
842
|
+
};
|
|
843
|
+
var DEFAULT_GLASS = { port: 4949 };
|
|
844
|
+
var DEFAULT_WATCH = { maxForksPerCycle: 3, autoRepair: true, conflicts: true, checks: true, maxRepairsPerPr: 2, maxRepairsWithoutProgress: 2, repairSettleSecs: 600, repairCooldownSecs: 0, repairTrapWaitSecs: 600 };
|
|
122
845
|
var DEFAULT_LIMITS = {
|
|
123
846
|
maxConcurrent: 2,
|
|
124
847
|
choreConcurrent: 1,
|
|
@@ -137,14 +860,82 @@ var DEFAULT_LIMITS = {
|
|
|
137
860
|
reuseWorktree: true,
|
|
138
861
|
releaseOnMerge: false
|
|
139
862
|
};
|
|
863
|
+
function configPath() {
|
|
864
|
+
return path3.join(lobstahHome(), "config.toml");
|
|
865
|
+
}
|
|
866
|
+
function expandHome(p) {
|
|
867
|
+
return p.startsWith("~/") ? path3.join(os2.homedir(), p.slice(2)) : p;
|
|
868
|
+
}
|
|
869
|
+
function loadConfig() {
|
|
870
|
+
const file = configPath();
|
|
871
|
+
const raw = fs4.existsSync(file) ? parse(fs4.readFileSync(file, "utf8")) : {};
|
|
872
|
+
const watch = { ...DEFAULT_WATCH, ...raw.watch ?? {} };
|
|
873
|
+
if (typeof watch.repairCooldownSecs !== "number" || !Number.isFinite(watch.repairCooldownSecs) || watch.repairCooldownSecs < 0) {
|
|
874
|
+
throw new Error(`[watch].repairCooldownSecs must be a non-negative number in ${configPath()}`);
|
|
875
|
+
}
|
|
876
|
+
const readySettleSecs = raw.readySettleSecs ?? 600;
|
|
877
|
+
if (typeof readySettleSecs !== "number" || !Number.isFinite(readySettleSecs) || readySettleSecs < 0) {
|
|
878
|
+
throw new Error(`readySettleSecs must be a non-negative number in ${configPath()}`);
|
|
879
|
+
}
|
|
880
|
+
const reposRaw = raw.repos ?? {};
|
|
881
|
+
const repos = {};
|
|
882
|
+
for (const [key, r] of Object.entries(reposRaw)) {
|
|
883
|
+
repos[key] = {
|
|
884
|
+
path: expandHome(String(r.path ?? "")),
|
|
885
|
+
origin: r.origin ? String(r.origin) : void 0,
|
|
886
|
+
trunk: String(r.trunk ?? "main"),
|
|
887
|
+
setup: Array.isArray(r.setup) ? r.setup.map(String) : void 0,
|
|
888
|
+
env: r.env ?? void 0,
|
|
889
|
+
harness: r.harness ?? void 0,
|
|
890
|
+
pickup: r.pickup === void 0 ? void 0 : Boolean(r.pickup),
|
|
891
|
+
scratch: Array.isArray(r.scratch) ? r.scratch.map(String) : void 0,
|
|
892
|
+
pushEarly: r.pushEarly === void 0 ? void 0 : Boolean(r.pushEarly),
|
|
893
|
+
draftPr: r.draftPr === void 0 ? void 0 : Boolean(r.draftPr),
|
|
894
|
+
checkpointOnStop: r.checkpointOnStop === void 0 ? void 0 : Boolean(r.checkpointOnStop),
|
|
895
|
+
humanGateChecks: Array.isArray(r.humanGateChecks) ? r.humanGateChecks.map(String).filter(Boolean) : void 0,
|
|
896
|
+
briefHooks: parseBriefHooks(r.briefHooks),
|
|
897
|
+
poolKeep: Array.isArray(r.poolKeep) ? r.poolKeep.map(String).filter(Boolean) : void 0
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
const groundsRaw = raw.grounds ?? {};
|
|
901
|
+
const grounds = {};
|
|
902
|
+
for (const [key, g] of Object.entries(groundsRaw)) {
|
|
903
|
+
grounds[key] = { repos: Array.isArray(g.repos) ? g.repos.map(String) : [] };
|
|
904
|
+
}
|
|
905
|
+
return {
|
|
906
|
+
repos,
|
|
907
|
+
harness: raw.harness ?? {},
|
|
908
|
+
limits: { ...DEFAULT_LIMITS, ...raw.limits ?? {} },
|
|
909
|
+
soak: parseSoak(raw.soak),
|
|
910
|
+
helm: { ...DEFAULT_HELM, ...raw.helm ?? {} },
|
|
911
|
+
glass: { ...DEFAULT_GLASS, ...raw.glass ?? {} },
|
|
912
|
+
watch,
|
|
913
|
+
grounds,
|
|
914
|
+
pools: parsePools(raw.pools, repos),
|
|
915
|
+
notifyCommand: raw.notifyCommand ? String(raw.notifyCommand) : void 0,
|
|
916
|
+
notifyVerbs: Array.isArray(raw.notifyVerbs) ? raw.notifyVerbs.map(String) : void 0,
|
|
917
|
+
remindSecs: raw.remindSecs !== void 0 ? Number(raw.remindSecs) : void 0,
|
|
918
|
+
readySettleSecs,
|
|
919
|
+
attentionKinds: parseAttentionKinds(raw.attentionKinds)
|
|
920
|
+
};
|
|
921
|
+
}
|
|
140
922
|
|
|
141
923
|
// packages/core/dist/pr.js
|
|
142
924
|
var PR_VIEW_FIELDS = "title,state,isDraft,isCrossRepository,headRefOid,baseRefName,baseRefOid,headRefName,mergeStateStatus,reviewDecision,statusCheckRollup,mergedAt,closedAt,updatedAt,reviews";
|
|
143
925
|
var PR_VIEW_FIELDS_NO_CHECKS = PR_VIEW_FIELDS.split(",").filter((f) => f !== "statusCheckRollup").join(",");
|
|
144
926
|
|
|
927
|
+
// packages/core/dist/worktrees.js
|
|
928
|
+
var WARM_LOCK_MAX_MS = 15 * 6e4;
|
|
929
|
+
|
|
145
930
|
// packages/core/dist/disk.js
|
|
146
931
|
var GB = 1024 ** 3;
|
|
147
932
|
|
|
933
|
+
// packages/core/dist/pools.js
|
|
934
|
+
var POOL_WARM_MAX_MS = 60 * 6e4;
|
|
935
|
+
var POOL_RETRY_MS = 10 * 6e4;
|
|
936
|
+
var POOL_FETCH_MS = 10 * 6e4;
|
|
937
|
+
var POOL_RECHECK_MS = 5 * 6e4;
|
|
938
|
+
|
|
148
939
|
// packages/core/dist/decisions.js
|
|
149
940
|
var DECISION_DETAIL_MAX = 64 * 1024;
|
|
150
941
|
var ANSWER_TYPES = {
|
|
@@ -169,35 +960,35 @@ var ANSWER_TYPES = {
|
|
|
169
960
|
var ANSWER_EXTENSIONS = Object.keys(ANSWER_TYPES);
|
|
170
961
|
|
|
171
962
|
// packages/core/dist/inbox.js
|
|
172
|
-
import * as
|
|
173
|
-
import * as
|
|
963
|
+
import * as fs5 from "node:fs";
|
|
964
|
+
import * as path4 from "node:path";
|
|
174
965
|
var metaName = (file) => file.replace(/\.msg$/, ".meta.json");
|
|
175
966
|
function inboxDir(id, lane) {
|
|
176
|
-
return
|
|
967
|
+
return path4.join(laneDirs(lane).inbox, id);
|
|
177
968
|
}
|
|
178
969
|
function sendMessage(id, lane, text2, from, attachments = []) {
|
|
179
970
|
const dir = inboxDir(id, lane);
|
|
180
|
-
|
|
181
|
-
const existing =
|
|
182
|
-
const handled =
|
|
971
|
+
fs5.mkdirSync(path4.join(dir, "handled"), { recursive: true });
|
|
972
|
+
const existing = fs5.readdirSync(dir).filter((f) => f.endsWith(".msg")).length;
|
|
973
|
+
const handled = fs5.readdirSync(path4.join(dir, "handled")).filter((f) => f.endsWith(".msg")).length;
|
|
183
974
|
const name = `${String(existing + handled + 1).padStart(3, "0")}.msg`;
|
|
184
|
-
const tmp =
|
|
975
|
+
const tmp = path4.join(dir, `.tmp-${process.pid}-${Date.now()}`);
|
|
185
976
|
if (from !== void 0 || attachments.length > 0) {
|
|
186
977
|
const meta = { from: from ?? "unknown", at: (/* @__PURE__ */ new Date()).toISOString(), ...attachments.length ? { attachments } : {} };
|
|
187
978
|
const metaTmp = `${tmp}.meta`;
|
|
188
|
-
|
|
189
|
-
|
|
979
|
+
fs5.writeFileSync(metaTmp, JSON.stringify(meta, null, 2));
|
|
980
|
+
fs5.renameSync(metaTmp, path4.join(dir, metaName(name)));
|
|
190
981
|
}
|
|
191
|
-
|
|
192
|
-
|
|
982
|
+
fs5.writeFileSync(tmp, text2);
|
|
983
|
+
fs5.renameSync(tmp, path4.join(dir, name));
|
|
193
984
|
return name;
|
|
194
985
|
}
|
|
195
986
|
|
|
196
987
|
// packages/core/dist/events.js
|
|
197
|
-
import * as
|
|
988
|
+
import * as fs6 from "node:fs";
|
|
198
989
|
function lastEventAt(id, lane) {
|
|
199
990
|
try {
|
|
200
|
-
return
|
|
991
|
+
return fs6.statSync(eventsPath(id, lane)).mtimeMs;
|
|
201
992
|
} catch {
|
|
202
993
|
return void 0;
|
|
203
994
|
}
|
|
@@ -233,7 +1024,7 @@ function text(payload, details = {}) {
|
|
|
233
1024
|
function findLane(id) {
|
|
234
1025
|
for (const lane of ["work", "chore"]) {
|
|
235
1026
|
const d = laneDirs(lane);
|
|
236
|
-
if (
|
|
1027
|
+
if (fs7.existsSync(path5.join(d.active, id)) || fs7.existsSync(path5.join(d.queue, `${id}.json`)) || fs7.existsSync(path5.join(d.done, id)) || fs7.existsSync(path5.join(d.state, `${id}.status`))) {
|
|
237
1028
|
return lane;
|
|
238
1029
|
}
|
|
239
1030
|
}
|
|
@@ -259,16 +1050,26 @@ function dispatchTool() {
|
|
|
259
1050
|
harness: { type: "string", enum: ["claude", "codex"] },
|
|
260
1051
|
model: { type: "string" },
|
|
261
1052
|
effort: { type: "string" },
|
|
262
|
-
followUp: { type: "string", description: "Earlier dispatch UUID whose session to fork" }
|
|
1053
|
+
followUp: { type: "string", description: "Earlier dispatch UUID whose session to fork" },
|
|
1054
|
+
pool: {
|
|
1055
|
+
type: "string",
|
|
1056
|
+
description: "Worktree pool from the host config ([pools.<name>]): run in a warm pool worktree with a fresh session. repo defaults to the pool's repo."
|
|
1057
|
+
}
|
|
263
1058
|
},
|
|
264
|
-
required: ["
|
|
1059
|
+
required: ["brief"],
|
|
265
1060
|
additionalProperties: false
|
|
266
1061
|
},
|
|
267
1062
|
async execute(_id, params) {
|
|
268
1063
|
ensureLayout();
|
|
269
|
-
const
|
|
1064
|
+
const poolName = param(params, "pool");
|
|
1065
|
+
const pool = poolName !== void 0 ? loadConfig().pools[poolName] : void 0;
|
|
1066
|
+
if (poolName !== void 0 && !pool) throw new Error(`lobstah_dispatch: unknown pool "${poolName}"`);
|
|
1067
|
+
if (pool && param(params, "repo") !== void 0 && param(params, "repo") !== pool.repo) {
|
|
1068
|
+
throw new Error(`lobstah_dispatch: pool ${poolName} serves repo ${pool.repo}, not ${param(params, "repo")}`);
|
|
1069
|
+
}
|
|
1070
|
+
const repo = param(params, "repo") ?? pool?.repo;
|
|
270
1071
|
const brief = param(params, "brief");
|
|
271
|
-
if (!repo || !brief) throw new Error("lobstah_dispatch requires
|
|
1072
|
+
if (!repo || !brief) throw new Error("lobstah_dispatch requires brief, and repo or pool");
|
|
272
1073
|
const d = {
|
|
273
1074
|
id: randomUUID(),
|
|
274
1075
|
repo,
|
|
@@ -276,12 +1077,13 @@ function dispatchTool() {
|
|
|
276
1077
|
harness: param(params, "harness"),
|
|
277
1078
|
model: param(params, "model"),
|
|
278
1079
|
effort: param(params, "effort"),
|
|
279
|
-
followUp: param(params, "followUp")
|
|
1080
|
+
followUp: param(params, "followUp"),
|
|
1081
|
+
...poolName !== void 0 ? { pool: poolName } : {}
|
|
280
1082
|
};
|
|
281
1083
|
if (d.harness) d.harnessExplicit = true;
|
|
282
1084
|
if (d.model) d.modelExplicit = true;
|
|
283
1085
|
enqueue(d, "work");
|
|
284
|
-
return text(toonKV({ id: d.id, repo, queued: (/* @__PURE__ */ new Date()).toISOString() }), { id: d.id });
|
|
1086
|
+
return text(toonKV({ id: d.id, repo, ...d.pool ? { pool: d.pool } : {}, queued: (/* @__PURE__ */ new Date()).toISOString() }), { id: d.id });
|
|
285
1087
|
}
|
|
286
1088
|
};
|
|
287
1089
|
}
|
|
@@ -305,7 +1107,7 @@ function statusTool() {
|
|
|
305
1107
|
return text(toonKV({ id, lane, state, lastNote: log.at(-1)?.note }), { id, state });
|
|
306
1108
|
}
|
|
307
1109
|
const rows = ["work", "chore"].flatMap(
|
|
308
|
-
(lane) =>
|
|
1110
|
+
(lane) => fs7.readdirSync(laneDirs(lane).active).filter((f) => !f.startsWith(".")).map((did) => ({ id: did, lane, state: stateOf(did, lane) }))
|
|
309
1111
|
);
|
|
310
1112
|
return text(toonTable("active", rows, ["id", "lane", "state"]), { count: rows.length });
|
|
311
1113
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lobstah-openclaw-plugin",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "OpenClaw plugin for lobstah: gives fleet agents dispatch/status/send/cancel tools and operators a /lobstah command.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "aequitas labs LLC",
|