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