@herdingchats/friday 0.1.591 → 0.1.600
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/herd.mjs +292 -159
- package/package.json +2 -2
package/herd.mjs
CHANGED
|
@@ -18,7 +18,7 @@ var __export = (target, all) => {
|
|
|
18
18
|
var define_HERD_PACKAGE_default;
|
|
19
19
|
var init_define_HERD_PACKAGE = __esm({
|
|
20
20
|
"<define:HERD_PACKAGE>"() {
|
|
21
|
-
define_HERD_PACKAGE_default = { version: "0.1.
|
|
21
|
+
define_HERD_PACKAGE_default = { version: "0.1.600", gitHead: "258e3577331c639de77e7ab7f0cdccc48b275a89" };
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
|
|
@@ -2115,21 +2115,21 @@ var init_usb = __esm({
|
|
|
2115
2115
|
// ../common-board/src/time.ts
|
|
2116
2116
|
function when(at, now, theme) {
|
|
2117
2117
|
if (theme.mode === "live") return ago2(now - at);
|
|
2118
|
-
const
|
|
2118
|
+
const day2 = (time8) => new Intl.DateTimeFormat("en-CA", { timeZone: theme.timeZone }).format(time8);
|
|
2119
2119
|
const clock = new Intl.DateTimeFormat("en-US", {
|
|
2120
2120
|
timeZone: theme.timeZone,
|
|
2121
2121
|
hour: "numeric",
|
|
2122
2122
|
minute: "2-digit"
|
|
2123
2123
|
}).format(at);
|
|
2124
|
-
if (
|
|
2124
|
+
if (day2(at) === day2(now)) return clock;
|
|
2125
2125
|
const weekday = new Intl.DateTimeFormat("en-US", {
|
|
2126
2126
|
timeZone: theme.timeZone,
|
|
2127
2127
|
weekday: "short"
|
|
2128
2128
|
}).format(at);
|
|
2129
2129
|
return `${weekday} ${clock}`;
|
|
2130
2130
|
}
|
|
2131
|
-
function ago2(
|
|
2132
|
-
const minutes = Math.floor(Math.max(0,
|
|
2131
|
+
function ago2(ms2) {
|
|
2132
|
+
const minutes = Math.floor(Math.max(0, ms2) / 6e4);
|
|
2133
2133
|
if (minutes < 1) return "just now";
|
|
2134
2134
|
if (minutes < 60) return `${minutes}m ago`;
|
|
2135
2135
|
const hours = Math.floor(minutes / 60);
|
|
@@ -2385,7 +2385,7 @@ var init_widget = __esm({
|
|
|
2385
2385
|
});
|
|
2386
2386
|
|
|
2387
2387
|
// ../common-board/src/widgets/conversations.tsx
|
|
2388
|
-
import { z as
|
|
2388
|
+
import { z as z28 } from "zod";
|
|
2389
2389
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2390
2390
|
function badge(item) {
|
|
2391
2391
|
if (pullRequestBadge(item)) {
|
|
@@ -2429,10 +2429,10 @@ var init_conversations = __esm({
|
|
|
2429
2429
|
conversations2 = defineWidget({
|
|
2430
2430
|
kind: "conversations",
|
|
2431
2431
|
describe: "Blocked, working and queued conversations, then the latest done, with what each is doing, where it came from and who holds it",
|
|
2432
|
-
options:
|
|
2433
|
-
states:
|
|
2434
|
-
limit:
|
|
2435
|
-
show:
|
|
2432
|
+
options: z28.object({
|
|
2433
|
+
states: z28.array(conversationStateSchema).min(1).default(["stuck", "working", "waiting", "done"]),
|
|
2434
|
+
limit: z28.number().int().min(1).max(BOARD_ITEMS).default(4),
|
|
2435
|
+
show: z28.array(z28.enum(DETAILS)).default([...DETAILS])
|
|
2436
2436
|
}),
|
|
2437
2437
|
reads: ["items", "machines"],
|
|
2438
2438
|
Component: ({ board, options, theme, now }) => {
|
|
@@ -2476,7 +2476,7 @@ var init_conversations = __esm({
|
|
|
2476
2476
|
});
|
|
2477
2477
|
|
|
2478
2478
|
// ../common-board/src/widgets/counts.tsx
|
|
2479
|
-
import { z as
|
|
2479
|
+
import { z as z29 } from "zod";
|
|
2480
2480
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2481
2481
|
var COUNTS, LABELS2, counts;
|
|
2482
2482
|
var init_counts = __esm({
|
|
@@ -2496,8 +2496,8 @@ var init_counts = __esm({
|
|
|
2496
2496
|
counts = defineWidget({
|
|
2497
2497
|
kind: "counts",
|
|
2498
2498
|
describe: "How many conversations are stuck, unanswered, waiting and working, and done today",
|
|
2499
|
-
options:
|
|
2500
|
-
show:
|
|
2499
|
+
options: z29.object({
|
|
2500
|
+
show: z29.array(z29.enum(COUNTS)).min(1).max(5).default([...COUNTS])
|
|
2501
2501
|
}),
|
|
2502
2502
|
reads: ["counts", "doneToday"],
|
|
2503
2503
|
Component: ({ board, options, theme }) => {
|
|
@@ -2536,7 +2536,7 @@ var init_counts = __esm({
|
|
|
2536
2536
|
});
|
|
2537
2537
|
|
|
2538
2538
|
// ../common-board/src/widgets/header.tsx
|
|
2539
|
-
import { z as
|
|
2539
|
+
import { z as z30 } from "zod";
|
|
2540
2540
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2541
2541
|
function summary(board) {
|
|
2542
2542
|
const parts = [
|
|
@@ -2561,9 +2561,9 @@ var init_header = __esm({
|
|
|
2561
2561
|
header = defineWidget({
|
|
2562
2562
|
kind: "header",
|
|
2563
2563
|
describe: "The board's title, a line of how much is open, and when it was drawn",
|
|
2564
|
-
options:
|
|
2565
|
-
title:
|
|
2566
|
-
summary:
|
|
2564
|
+
options: z30.object({
|
|
2565
|
+
title: z30.string().min(1).max(40).default(`@${BOT_NAME}`),
|
|
2566
|
+
summary: z30.boolean().default(true)
|
|
2567
2567
|
}),
|
|
2568
2568
|
reads: ["counts"],
|
|
2569
2569
|
Component: ({ board, options, theme, now }) => {
|
|
@@ -2581,7 +2581,7 @@ var init_header = __esm({
|
|
|
2581
2581
|
});
|
|
2582
2582
|
|
|
2583
2583
|
// ../common-board/src/widgets/machines.tsx
|
|
2584
|
-
import { z as
|
|
2584
|
+
import { z as z31 } from "zod";
|
|
2585
2585
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2586
2586
|
function usageText(worker) {
|
|
2587
2587
|
const usage = worker.usage;
|
|
@@ -2612,7 +2612,7 @@ var init_machines2 = __esm({
|
|
|
2612
2612
|
machines = defineWidget({
|
|
2613
2613
|
kind: "machines",
|
|
2614
2614
|
describe: "One bubble per agent on an online machine, with its usage, most recently active first",
|
|
2615
|
-
options:
|
|
2615
|
+
options: z31.object({ limit: z31.number().int().min(1).max(8).default(3) }),
|
|
2616
2616
|
reads: ["machines"],
|
|
2617
2617
|
Component: ({ board, options, theme }) => {
|
|
2618
2618
|
const workers2 = board.machines.filter((machine) => machine.online).flatMap((machine) => machine.workers.map((worker) => ({ ...worker, machine: machine.name }))).sort((a, b) => (b.reportedAt ?? 0) - (a.reportedAt ?? 0));
|
|
@@ -2729,9 +2729,9 @@ var init_board2 = __esm({
|
|
|
2729
2729
|
});
|
|
2730
2730
|
|
|
2731
2731
|
// ../common-board/src/composition.ts
|
|
2732
|
-
import { z as
|
|
2732
|
+
import { z as z32 } from "zod";
|
|
2733
2733
|
function readComposition(stored) {
|
|
2734
|
-
const shape =
|
|
2734
|
+
const shape = z32.object({ widgets: z32.array(placedWidgetSchema) }).safeParse(stored);
|
|
2735
2735
|
if (!shape.success) return DEFAULT_COMPOSITION;
|
|
2736
2736
|
const known = shape.data.widgets.filter(
|
|
2737
2737
|
(widget) => WIDGETS[widget.kind]?.options.safeParse(widget.options).success
|
|
@@ -2746,11 +2746,11 @@ var init_composition = __esm({
|
|
|
2746
2746
|
init_registry();
|
|
2747
2747
|
MAX_WIDGETS = 12;
|
|
2748
2748
|
MAX_COMPOSITION_BYTES = 4096;
|
|
2749
|
-
placedWidgetSchema =
|
|
2750
|
-
kind:
|
|
2751
|
-
options:
|
|
2749
|
+
placedWidgetSchema = z32.object({
|
|
2750
|
+
kind: z32.string().min(1),
|
|
2751
|
+
options: z32.record(z32.string(), z32.unknown()).default({})
|
|
2752
2752
|
});
|
|
2753
|
-
compositionSchema =
|
|
2753
|
+
compositionSchema = z32.object({ widgets: z32.array(placedWidgetSchema).max(MAX_WIDGETS) }).superRefine((composition, context2) => {
|
|
2754
2754
|
if (JSON.stringify(composition).length > MAX_COMPOSITION_BYTES) {
|
|
2755
2755
|
context2.addIssue({
|
|
2756
2756
|
code: "custom",
|
|
@@ -3031,13 +3031,13 @@ var init_png = __esm({
|
|
|
3031
3031
|
"use strict";
|
|
3032
3032
|
init_define_HERD_PACKAGE();
|
|
3033
3033
|
CRC_TABLE = (() => {
|
|
3034
|
-
const
|
|
3034
|
+
const table2 = new Uint32Array(256);
|
|
3035
3035
|
for (let n = 0; n < 256; n++) {
|
|
3036
3036
|
let c = n;
|
|
3037
3037
|
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
3038
|
-
|
|
3038
|
+
table2[n] = c >>> 0;
|
|
3039
3039
|
}
|
|
3040
|
-
return
|
|
3040
|
+
return table2;
|
|
3041
3041
|
})();
|
|
3042
3042
|
}
|
|
3043
3043
|
});
|
|
@@ -3636,7 +3636,7 @@ function dayFolders(home) {
|
|
|
3636
3636
|
const days = [];
|
|
3637
3637
|
for (const year of list(root)) {
|
|
3638
3638
|
for (const month of list(join2(root, year))) {
|
|
3639
|
-
for (const
|
|
3639
|
+
for (const day2 of list(join2(root, year, month))) days.push(join2(root, year, month, day2));
|
|
3640
3640
|
}
|
|
3641
3641
|
}
|
|
3642
3642
|
return days;
|
|
@@ -3672,14 +3672,14 @@ var realpath = (path) => {
|
|
|
3672
3672
|
};
|
|
3673
3673
|
function findSessionByCwd(cwd, since, home = codexHome()) {
|
|
3674
3674
|
const wanted = realpath(cwd);
|
|
3675
|
-
for (const
|
|
3675
|
+
for (const day2 of dayFolders(home).slice(0, 2)) {
|
|
3676
3676
|
let names;
|
|
3677
3677
|
try {
|
|
3678
|
-
names = readdirSync(
|
|
3678
|
+
names = readdirSync(day2).filter((name) => /^rollout-.*\.jsonl$/.test(name));
|
|
3679
3679
|
} catch {
|
|
3680
3680
|
continue;
|
|
3681
3681
|
}
|
|
3682
|
-
const found = names.map((name) => join2(
|
|
3682
|
+
const found = names.map((name) => join2(day2, name)).filter((path) => {
|
|
3683
3683
|
try {
|
|
3684
3684
|
return statSync(path).mtimeMs >= since - 2e3;
|
|
3685
3685
|
} catch {
|
|
@@ -3696,10 +3696,10 @@ function findSessionByCwd(cwd, since, home = codexHome()) {
|
|
|
3696
3696
|
}
|
|
3697
3697
|
function findSessionById(id2, home = codexHome()) {
|
|
3698
3698
|
const suffix = `-${id2}.jsonl`;
|
|
3699
|
-
for (const
|
|
3699
|
+
for (const day2 of dayFolders(home)) {
|
|
3700
3700
|
try {
|
|
3701
|
-
const name = readdirSync(
|
|
3702
|
-
if (name) return join2(
|
|
3701
|
+
const name = readdirSync(day2).find((n) => n.startsWith("rollout-") && n.endsWith(suffix));
|
|
3702
|
+
if (name) return join2(day2, name);
|
|
3703
3703
|
} catch {
|
|
3704
3704
|
}
|
|
3705
3705
|
}
|
|
@@ -4965,7 +4965,7 @@ function activateDecision(request, code) {
|
|
|
4965
4965
|
}
|
|
4966
4966
|
};
|
|
4967
4967
|
}
|
|
4968
|
-
var sleep = (
|
|
4968
|
+
var sleep = (ms2) => new Promise((resolve7) => setTimeout(resolve7, ms2));
|
|
4969
4969
|
var label = (agent) => AGENTS[agent]?.label ?? agent;
|
|
4970
4970
|
var Activator = class {
|
|
4971
4971
|
constructor(options) {
|
|
@@ -5290,7 +5290,7 @@ function askToActivate(herdHome2, now = Date.now()) {
|
|
|
5290
5290
|
requestActivation(herdHome2, now);
|
|
5291
5291
|
return now;
|
|
5292
5292
|
}
|
|
5293
|
-
var sleep2 = (
|
|
5293
|
+
var sleep2 = (ms2) => new Promise((resolve7) => setTimeout(resolve7, ms2));
|
|
5294
5294
|
function settledLine(cli, activation) {
|
|
5295
5295
|
if (activation.state === "activated") return `${label2(cli)} is activated.`;
|
|
5296
5296
|
return `${label2(cli)} ${activationText(cli, activation).replace(" there", " on this computer")}.`;
|
|
@@ -6178,11 +6178,11 @@ var Supervisor = class {
|
|
|
6178
6178
|
await this.stopLeftoverDaemon();
|
|
6179
6179
|
this.save();
|
|
6180
6180
|
this.spawnDaemon();
|
|
6181
|
-
const schedule = (
|
|
6181
|
+
const schedule = (ms2) => {
|
|
6182
6182
|
this.checkTimer = setTimeout(async () => {
|
|
6183
6183
|
await this.check().catch((error) => this.log(`The release check failed: ${error}`));
|
|
6184
6184
|
if (!this.stopping) schedule(this.options.checkMs ?? 12e4);
|
|
6185
|
-
},
|
|
6185
|
+
}, ms2);
|
|
6186
6186
|
};
|
|
6187
6187
|
schedule(this.options.firstCheckMs ?? 5e3);
|
|
6188
6188
|
}
|
|
@@ -7196,7 +7196,7 @@ async function registerRunner({
|
|
|
7196
7196
|
url = buildsUrl(),
|
|
7197
7197
|
fetchImpl = fetch,
|
|
7198
7198
|
say = (line2) => console.log(line2),
|
|
7199
|
-
sleep: sleep8 = (
|
|
7199
|
+
sleep: sleep8 = (ms2) => new Promise((resolve7) => setTimeout(resolve7, ms2)),
|
|
7200
7200
|
pollMs = 2e3,
|
|
7201
7201
|
waitMs = 15 * 60 * 1e3
|
|
7202
7202
|
}) {
|
|
@@ -7233,6 +7233,120 @@ async function registerRunner({
|
|
|
7233
7233
|
);
|
|
7234
7234
|
}
|
|
7235
7235
|
|
|
7236
|
+
// src/build-speed.ts
|
|
7237
|
+
init_define_HERD_PACKAGE();
|
|
7238
|
+
import { z as z25 } from "zod";
|
|
7239
|
+
var ms = z25.number().int().nullable();
|
|
7240
|
+
var figuresSchema = z25.object({ count: z25.number().int(), median: ms, p90: ms });
|
|
7241
|
+
var buildTimesSchema = z25.object({ run: figuresSchema, push: figuresSchema });
|
|
7242
|
+
var stepFiguresSchema = z25.object({
|
|
7243
|
+
ran: z25.number().int(),
|
|
7244
|
+
remembered: z25.number().int(),
|
|
7245
|
+
median: ms,
|
|
7246
|
+
p90: ms,
|
|
7247
|
+
overBudget: z25.number().int()
|
|
7248
|
+
});
|
|
7249
|
+
var kindSchema = z25.object({
|
|
7250
|
+
builds: z25.object({ current: buildTimesSchema, previous: buildTimesSchema }),
|
|
7251
|
+
steps: z25.array(
|
|
7252
|
+
z25.object({ label: z25.string(), current: stepFiguresSchema, previous: stepFiguresSchema })
|
|
7253
|
+
),
|
|
7254
|
+
overBudget: z25.array(
|
|
7255
|
+
z25.object({ label: z25.string(), current: z25.number().int(), previous: z25.number().int() })
|
|
7256
|
+
)
|
|
7257
|
+
});
|
|
7258
|
+
var range = z25.object({ from: z25.number(), to: z25.number() });
|
|
7259
|
+
var speedReportSchema = z25.object({
|
|
7260
|
+
periods: z25.object({ current: range, previous: range }),
|
|
7261
|
+
repos: z25.array(
|
|
7262
|
+
z25.object({
|
|
7263
|
+
repo: z25.string(),
|
|
7264
|
+
capped: z25.boolean(),
|
|
7265
|
+
pullRequests: kindSchema,
|
|
7266
|
+
main: kindSchema
|
|
7267
|
+
})
|
|
7268
|
+
)
|
|
7269
|
+
});
|
|
7270
|
+
async function fetchSpeed(key, fetchImpl = fetch) {
|
|
7271
|
+
let response;
|
|
7272
|
+
try {
|
|
7273
|
+
response = await fetchImpl(`${key.url}/speed`, {
|
|
7274
|
+
headers: { Authorization: `Bearer ${key.key}` }
|
|
7275
|
+
});
|
|
7276
|
+
} catch (error) {
|
|
7277
|
+
throw new HerdError(`Couldn't reach the build service at ${key.url}: ${String(error)}`);
|
|
7278
|
+
}
|
|
7279
|
+
if (response.status === 404)
|
|
7280
|
+
throw new HerdError(
|
|
7281
|
+
"The build service doesn't accept this machine's runner key, as after it was revoked. Register it again with herd builds register."
|
|
7282
|
+
);
|
|
7283
|
+
if (!response.ok)
|
|
7284
|
+
throw new HerdError(`The build service couldn't give build speed (${response.status}).`);
|
|
7285
|
+
return speedReportSchema.parse(await response.json());
|
|
7286
|
+
}
|
|
7287
|
+
function duration(value) {
|
|
7288
|
+
if (value === null) return "-";
|
|
7289
|
+
if (value < 1e3) return `${value}ms`;
|
|
7290
|
+
if (value < 6e4) return `${(value / 1e3).toFixed(1)}s`;
|
|
7291
|
+
const seconds = Math.round(value / 1e3);
|
|
7292
|
+
return `${Math.floor(seconds / 60)}m${String(seconds % 60).padStart(2, "0")}s`;
|
|
7293
|
+
}
|
|
7294
|
+
function table(rows) {
|
|
7295
|
+
const widths = [];
|
|
7296
|
+
for (const row of rows) {
|
|
7297
|
+
row.forEach((cell, i) => {
|
|
7298
|
+
widths[i] = Math.max(widths[i] ?? 0, cell.length);
|
|
7299
|
+
});
|
|
7300
|
+
}
|
|
7301
|
+
return rows.map(
|
|
7302
|
+
(row) => row.map((cell, i) => i === 0 ? cell.padEnd(widths[i] ?? 0) : cell.padStart(widths[i] ?? 0)).join(" ").trimEnd()
|
|
7303
|
+
);
|
|
7304
|
+
}
|
|
7305
|
+
var day = (time8) => new Date(time8).toISOString().slice(0, 10);
|
|
7306
|
+
function kindLines(name, kind) {
|
|
7307
|
+
const { current, previous } = kind.builds;
|
|
7308
|
+
const rows = [
|
|
7309
|
+
[name, "median", "p90", "builds", "|", "median", "p90", "builds"],
|
|
7310
|
+
...["run", "push"].map((which) => [
|
|
7311
|
+
which === "run" ? " start to finish" : " push to finish",
|
|
7312
|
+
duration(current[which].median),
|
|
7313
|
+
duration(current[which].p90),
|
|
7314
|
+
String(current[which].count),
|
|
7315
|
+
"|",
|
|
7316
|
+
duration(previous[which].median),
|
|
7317
|
+
duration(previous[which].p90),
|
|
7318
|
+
String(previous[which].count)
|
|
7319
|
+
]),
|
|
7320
|
+
[" steps, slowest first", "", "", "ran/rem", "|", "", "", "ran/rem"],
|
|
7321
|
+
...kind.steps.map((step) => [
|
|
7322
|
+
` ${step.label}`,
|
|
7323
|
+
duration(step.current.median),
|
|
7324
|
+
duration(step.current.p90),
|
|
7325
|
+
`${step.current.ran}/${step.current.remembered}`,
|
|
7326
|
+
"|",
|
|
7327
|
+
duration(step.previous.median),
|
|
7328
|
+
duration(step.previous.p90),
|
|
7329
|
+
`${step.previous.ran}/${step.previous.remembered}`
|
|
7330
|
+
])
|
|
7331
|
+
];
|
|
7332
|
+
const over = kind.overBudget.map((s) => `${s.label} ${s.current}x (${s.previous}x before)`);
|
|
7333
|
+
return [...table(rows), ...over.length ? [` over budget most often: ${over.join(", ")}`] : []];
|
|
7334
|
+
}
|
|
7335
|
+
function formatSpeed(report) {
|
|
7336
|
+
const { current, previous } = report.periods;
|
|
7337
|
+
const lines = [
|
|
7338
|
+
`Last 14 days (${day(current.from)} to ${day(current.to)}) | 14 days before (${day(previous.from)} to ${day(previous.to)}).`,
|
|
7339
|
+
"Builds that passed or failed; steps only when they ran, not when remembered."
|
|
7340
|
+
];
|
|
7341
|
+
if (report.repos.length === 0) lines.push("", "No repos are built for this machine's owner yet.");
|
|
7342
|
+
for (const repo of report.repos) {
|
|
7343
|
+
lines.push("", `${repo.repo}${repo.capped ? " (only the newest builds count)" : ""}`);
|
|
7344
|
+
lines.push(...kindLines("pull requests", repo.pullRequests), "");
|
|
7345
|
+
lines.push(...kindLines("main", repo.main));
|
|
7346
|
+
}
|
|
7347
|
+
return lines.join("\n");
|
|
7348
|
+
}
|
|
7349
|
+
|
|
7236
7350
|
// src/builds-admin.ts
|
|
7237
7351
|
init_define_HERD_PACKAGE();
|
|
7238
7352
|
import { mkdirSync as mkdirSync13, readFileSync as readFileSync14, rmSync as rmSync10, writeFileSync as writeFileSync10 } from "node:fs";
|
|
@@ -7270,6 +7384,14 @@ Usage:
|
|
|
7270
7384
|
herd builds register Register it: prints a link its owner opens to approve it, then waits
|
|
7271
7385
|
and keeps the runner key. Only registered runners are offered builds,
|
|
7272
7386
|
and only the workspace's admin can register one.
|
|
7387
|
+
herd builds speed [--json]
|
|
7388
|
+
How long builds take: the median and 90th percentile of build time,
|
|
7389
|
+
start to finish and push to finish, for pull requests and main apart,
|
|
7390
|
+
over the last 14 days against the 14 before, and each step's when it
|
|
7391
|
+
ran, slowest first, with how often it was remembered or over budget.
|
|
7392
|
+
Read with this machine's runner key, so only a registered runner can.
|
|
7393
|
+
--json prints the figures as JSON. People see them on
|
|
7394
|
+
/manage/speed of the build service.
|
|
7273
7395
|
|
|
7274
7396
|
How many builds a runner takes at once is "builds" in ~/.herd/herd.config.ts: true for one, or
|
|
7275
7397
|
{ max: <n> } for up to 4.`;
|
|
@@ -7295,6 +7417,16 @@ async function runBuilds(args) {
|
|
|
7295
7417
|
console.log("The daemon connects as a runner once it restarts.");
|
|
7296
7418
|
return 0;
|
|
7297
7419
|
}
|
|
7420
|
+
if (sub === "speed") {
|
|
7421
|
+
const key2 = readRunnerKey();
|
|
7422
|
+
if (!key2)
|
|
7423
|
+
throw new HerdError(
|
|
7424
|
+
"Build speed is read with a runner key, and this machine isn't a build runner. herd builds register makes it one."
|
|
7425
|
+
);
|
|
7426
|
+
const report = await fetchSpeed(key2);
|
|
7427
|
+
console.log(args.includes("--json") ? JSON.stringify(report, null, 2) : formatSpeed(report));
|
|
7428
|
+
return 0;
|
|
7429
|
+
}
|
|
7298
7430
|
if (sub !== void 0) throw new HerdError(`herd builds doesn't understand "${sub}".
|
|
7299
7431
|
|
|
7300
7432
|
${HELP3}`);
|
|
@@ -7556,7 +7688,7 @@ function withStartKey(command, startKey) {
|
|
|
7556
7688
|
return startKey ? `HERD_START=${startKey} ${command}` : command;
|
|
7557
7689
|
}
|
|
7558
7690
|
var DEFAULT_TIMING = { settleMs: 800, pollMs: 150, startMs: 6e4, confirmMs: 3e3 };
|
|
7559
|
-
var sleep3 = (
|
|
7691
|
+
var sleep3 = (ms2) => new Promise((resolve7) => setTimeout(resolve7, ms2));
|
|
7560
7692
|
var EXIT_WAIT_MS = 5e3;
|
|
7561
7693
|
var AgentDriver = class {
|
|
7562
7694
|
constructor(terminals, timing = {}) {
|
|
@@ -7578,8 +7710,8 @@ var AgentDriver = class {
|
|
|
7578
7710
|
async read(name) {
|
|
7579
7711
|
return readClaudeScreen(await this.terminals.screen(name));
|
|
7580
7712
|
}
|
|
7581
|
-
async until(name, check2,
|
|
7582
|
-
const end = Date.now() +
|
|
7713
|
+
async until(name, check2, ms2) {
|
|
7714
|
+
const end = Date.now() + ms2;
|
|
7583
7715
|
for (; ; ) {
|
|
7584
7716
|
const reading = await this.read(name);
|
|
7585
7717
|
if (check2(reading)) return reading;
|
|
@@ -7862,7 +7994,7 @@ function writeAgyFiles(worktree, herd) {
|
|
|
7862
7994
|
// src/agy-driver.ts
|
|
7863
7995
|
var AGY_FLAGS = `--dangerously-skip-permissions --settings ${AGY_SETTINGS_FILE}`;
|
|
7864
7996
|
var DEFAULT_TIMING2 = { settleMs: 800, pollMs: 150, startMs: 6e4, confirmMs: 3e3 };
|
|
7865
|
-
var sleep4 = (
|
|
7997
|
+
var sleep4 = (ms2) => new Promise((resolve7) => setTimeout(resolve7, ms2));
|
|
7866
7998
|
var EXIT_WAIT_MS2 = 5e3;
|
|
7867
7999
|
var AgyDriver = class {
|
|
7868
8000
|
constructor(terminals, timing = {}) {
|
|
@@ -7879,8 +8011,8 @@ var AgyDriver = class {
|
|
|
7879
8011
|
async read(name) {
|
|
7880
8012
|
return readAgyScreen(await this.terminals.screen(name));
|
|
7881
8013
|
}
|
|
7882
|
-
async until(name, check2,
|
|
7883
|
-
const end = Date.now() +
|
|
8014
|
+
async until(name, check2, ms2) {
|
|
8015
|
+
const end = Date.now() + ms2;
|
|
7884
8016
|
for (; ; ) {
|
|
7885
8017
|
const reading = await this.read(name);
|
|
7886
8018
|
if (check2(reading)) return reading;
|
|
@@ -8854,7 +8986,7 @@ var DEFAULT_TIMING3 = {
|
|
|
8854
8986
|
confirmMs: 8e3,
|
|
8855
8987
|
pasteMs: 600
|
|
8856
8988
|
};
|
|
8857
|
-
var sleep5 = (
|
|
8989
|
+
var sleep5 = (ms2) => new Promise((resolve7) => setTimeout(resolve7, ms2));
|
|
8858
8990
|
var EXIT_WAIT_MS3 = 5e3;
|
|
8859
8991
|
var CodexDriver = class {
|
|
8860
8992
|
constructor(terminals, timing = {}) {
|
|
@@ -8871,8 +9003,8 @@ var CodexDriver = class {
|
|
|
8871
9003
|
async read(name) {
|
|
8872
9004
|
return readCodexScreen(await this.terminals.screen(name));
|
|
8873
9005
|
}
|
|
8874
|
-
async until(name, check2,
|
|
8875
|
-
const end = Date.now() +
|
|
9006
|
+
async until(name, check2, ms2) {
|
|
9007
|
+
const end = Date.now() + ms2;
|
|
8876
9008
|
for (; ; ) {
|
|
8877
9009
|
const reading = await this.read(name);
|
|
8878
9010
|
if (check2(reading)) return reading;
|
|
@@ -9334,7 +9466,7 @@ function machineFolderProblem(root, convos, checks = {}) {
|
|
|
9334
9466
|
async function waitForFolders(problem, {
|
|
9335
9467
|
timeoutMs = FOLDER_WAIT_MS,
|
|
9336
9468
|
pollMs = 2e3,
|
|
9337
|
-
sleep: sleep8 = (
|
|
9469
|
+
sleep: sleep8 = (ms2) => new Promise((done) => setTimeout(done, ms2)),
|
|
9338
9470
|
now = Date.now,
|
|
9339
9471
|
log = (line2) => console.log(line2)
|
|
9340
9472
|
} = {}) {
|
|
@@ -9744,7 +9876,7 @@ var hostsDir = () => join25(herdHome(), "terminals");
|
|
|
9744
9876
|
var legacyHostSocketPath = () => join25(herdHome(), "terminals.sock");
|
|
9745
9877
|
var currentHostSocketPath = (version = hostVersion()) => join25(hostsDir(), `${version}.sock`);
|
|
9746
9878
|
var speaksProtocol = (protocol) => protocol === HOST_PROTOCOL || protocol === HOST_PROTOCOL - 1;
|
|
9747
|
-
var sleep6 = (
|
|
9879
|
+
var sleep6 = (ms2) => new Promise((resolve7) => setTimeout(resolve7, ms2));
|
|
9748
9880
|
function askHost(path, request) {
|
|
9749
9881
|
return new Promise((resolve7, reject) => {
|
|
9750
9882
|
const socket = connect2(path);
|
|
@@ -10045,7 +10177,7 @@ init_define_HERD_PACKAGE();
|
|
|
10045
10177
|
init_src();
|
|
10046
10178
|
init_self();
|
|
10047
10179
|
import { join as join26 } from "node:path";
|
|
10048
|
-
import { z as
|
|
10180
|
+
import { z as z26 } from "zod";
|
|
10049
10181
|
function hasThread(events) {
|
|
10050
10182
|
return events.some(
|
|
10051
10183
|
(event2) => event2.type === "prompt.opened" || event2.type === "message.created" && !(event2.payload.direction === "inbound" && event2.payload.automation) && !event2.payload.quiet && !event2.payload.post
|
|
@@ -10111,16 +10243,16 @@ var WAITING_NOTIFICATIONS = /* @__PURE__ */ new Set([
|
|
|
10111
10243
|
"agent_needs_input",
|
|
10112
10244
|
"elicitation_dialog"
|
|
10113
10245
|
]);
|
|
10114
|
-
var agentMessageSchema =
|
|
10115
|
-
text:
|
|
10116
|
-
files:
|
|
10246
|
+
var agentMessageSchema = z26.object({
|
|
10247
|
+
text: z26.string().trim().min(1).max(12e3),
|
|
10248
|
+
files: z26.array(z26.object({ path: z26.string().min(1), title: z26.string().optional() })).max(10).optional()
|
|
10117
10249
|
});
|
|
10118
|
-
var workspaceRepoSchema =
|
|
10119
|
-
folder:
|
|
10120
|
-
remote:
|
|
10121
|
-
branch:
|
|
10250
|
+
var workspaceRepoSchema = z26.object({
|
|
10251
|
+
folder: z26.string(),
|
|
10252
|
+
remote: z26.string(),
|
|
10253
|
+
branch: z26.string(),
|
|
10122
10254
|
/** For a conversation from before folders: the name of the repo it was allowed as. */
|
|
10123
|
-
name:
|
|
10255
|
+
name: z26.string().optional()
|
|
10124
10256
|
});
|
|
10125
10257
|
function fromBeforeFolders(raw) {
|
|
10126
10258
|
if (!raw || typeof raw !== "object" || "folder" in raw) return raw;
|
|
@@ -10141,106 +10273,106 @@ function fromBeforeFolders(raw) {
|
|
|
10141
10273
|
legacy: true
|
|
10142
10274
|
};
|
|
10143
10275
|
}
|
|
10144
|
-
var workspaceFields =
|
|
10145
|
-
conversationId:
|
|
10276
|
+
var workspaceFields = z26.object({
|
|
10277
|
+
conversationId: z26.string(),
|
|
10146
10278
|
/** The conversation's own folder, where its terminals start. */
|
|
10147
|
-
folder:
|
|
10279
|
+
folder: z26.string(),
|
|
10148
10280
|
/** The repos in it, in the order they were added. */
|
|
10149
|
-
worktrees:
|
|
10281
|
+
worktrees: z26.array(workspaceRepoSchema).default([]),
|
|
10150
10282
|
/** A conversation from before folders, which works in its one repo's worktree. */
|
|
10151
|
-
legacy:
|
|
10152
|
-
lead:
|
|
10153
|
-
secret:
|
|
10154
|
-
readSeq:
|
|
10155
|
-
claimId:
|
|
10156
|
-
claimRenewedAt:
|
|
10157
|
-
started:
|
|
10283
|
+
legacy: z26.boolean().default(false),
|
|
10284
|
+
lead: z26.string(),
|
|
10285
|
+
secret: z26.string(),
|
|
10286
|
+
readSeq: z26.number(),
|
|
10287
|
+
claimId: z26.string().nullable(),
|
|
10288
|
+
claimRenewedAt: z26.number(),
|
|
10289
|
+
started: z26.boolean(),
|
|
10158
10290
|
/** Messages to deliver once the current turn ends. */
|
|
10159
|
-
deferred:
|
|
10291
|
+
deferred: z26.boolean(),
|
|
10160
10292
|
/** A `herd run` command finished, which the agent hears about even with nothing to claim. */
|
|
10161
|
-
terminalNotice:
|
|
10162
|
-
status:
|
|
10293
|
+
terminalNotice: z26.boolean().default(false),
|
|
10294
|
+
status: z26.string().nullable(),
|
|
10163
10295
|
/** Set once the thread has been told the agent is waiting, so it's told once per wait. */
|
|
10164
|
-
toldWaiting:
|
|
10165
|
-
runs:
|
|
10296
|
+
toldWaiting: z26.boolean(),
|
|
10297
|
+
runs: z26.array(z26.object({ name: z26.string(), secret: z26.string(), reported: z26.boolean() })),
|
|
10166
10298
|
/** The subscription usage Claude Code last reported in this worktree. */
|
|
10167
10299
|
usage: usageSchema.nullable().default(null),
|
|
10168
10300
|
/** When that usage was reported, or 0 if it was before this was kept. */
|
|
10169
|
-
usageAt:
|
|
10301
|
+
usageAt: z26.number().default(0),
|
|
10170
10302
|
/** The lead agent's Claude Code session, as its `SessionStart` hook reported it. */
|
|
10171
|
-
sessionId:
|
|
10303
|
+
sessionId: z26.string().nullable().default(null),
|
|
10172
10304
|
/** When the agent's last turn ended with nothing left to do, for shutting it down later. */
|
|
10173
|
-
idleSince:
|
|
10305
|
+
idleSince: z26.number().nullable().default(null),
|
|
10174
10306
|
/** The agent ran `herd exit`, so its session ends after this turn. */
|
|
10175
|
-
exitRequested:
|
|
10307
|
+
exitRequested: z26.boolean().default(false),
|
|
10176
10308
|
/** Whether the agent sent anything with `herd send` this turn. */
|
|
10177
|
-
sentThisTurn:
|
|
10309
|
+
sentThisTurn: z26.boolean().default(false),
|
|
10178
10310
|
/** Whether it's been asked this turn to reply. */
|
|
10179
|
-
askedToReply:
|
|
10311
|
+
askedToReply: z26.boolean().default(false),
|
|
10180
10312
|
/** Whether it ran `herd handled` this turn, which handles the turn's messages with no reply. */
|
|
10181
|
-
handledThisTurn:
|
|
10313
|
+
handledThisTurn: z26.boolean().default(false),
|
|
10182
10314
|
/** The newest waiting message it's been pointed at, so one arrival is pointed out once. */
|
|
10183
|
-
nudgedSeq:
|
|
10315
|
+
nudgedSeq: z26.number().default(0),
|
|
10184
10316
|
/** When a `Stop` hook last ended a turn. */
|
|
10185
|
-
hookIdleAt:
|
|
10317
|
+
hookIdleAt: z26.number().default(0),
|
|
10186
10318
|
/** When a turn last ended with background work still running, which keeps its messages held. */
|
|
10187
|
-
pausedAt:
|
|
10319
|
+
pausedAt: z26.number().nullable().default(null),
|
|
10188
10320
|
/** The version of the terminal host the lead terminal was opened in, if it was recorded. */
|
|
10189
|
-
hostVersion:
|
|
10321
|
+
hostVersion: z26.string().nullable().default(null),
|
|
10190
10322
|
/** When a notice last failed for a reason other than someone's draft, to wait before retrying. */
|
|
10191
|
-
noticeFailedAt:
|
|
10323
|
+
noticeFailedAt: z26.number().nullable().default(null),
|
|
10192
10324
|
/** Why the last notice failed, so the history records each reason once, not every attempt. */
|
|
10193
|
-
noticeFailure:
|
|
10325
|
+
noticeFailure: z26.string().nullable().default(null),
|
|
10194
10326
|
/** A recorded dialog herd pressed its way out of, so a dialog that stays isn't pressed again. */
|
|
10195
|
-
closedDialog:
|
|
10327
|
+
closedDialog: z26.string().nullable().default(null),
|
|
10196
10328
|
/**
|
|
10197
10329
|
* Prompts Claude Code's hooks reported that haven't had their `Stop`. A turn is open while this
|
|
10198
10330
|
* is above zero. It's a count because a prompt queued mid-turn is reported as it's queued, and
|
|
10199
10331
|
* runs as a turn of its own, ending with a second `Stop`.
|
|
10200
10332
|
*/
|
|
10201
|
-
promptsOpen:
|
|
10333
|
+
promptsOpen: z26.number().default(0),
|
|
10202
10334
|
/** The messages the latest claim or addition took, for choosing which notice to type. */
|
|
10203
|
-
claimedSeqs:
|
|
10335
|
+
claimedSeqs: z26.array(z26.number()).default([]),
|
|
10204
10336
|
/** The investigator looking at a screen herd can't read, from opening to the owner's answer. */
|
|
10205
|
-
investigation:
|
|
10206
|
-
terminal:
|
|
10207
|
-
secret:
|
|
10208
|
-
startedAt:
|
|
10337
|
+
investigation: z26.object({
|
|
10338
|
+
terminal: z26.string(),
|
|
10339
|
+
secret: z26.string(),
|
|
10340
|
+
startedAt: z26.number(),
|
|
10209
10341
|
/** The stuck screen when it opened, saved with the key if the owner approves one. */
|
|
10210
|
-
screen:
|
|
10211
|
-
key:
|
|
10212
|
-
promptId:
|
|
10342
|
+
screen: z26.array(z26.string()),
|
|
10343
|
+
key: z26.string().nullable(),
|
|
10344
|
+
promptId: z26.string().nullable()
|
|
10213
10345
|
}).nullable().default(null),
|
|
10214
10346
|
/** The failed notice an investigator was opened for, so each failure gets one. */
|
|
10215
|
-
investigatedFailure:
|
|
10347
|
+
investigatedFailure: z26.number().nullable().default(null),
|
|
10216
10348
|
/** The agent CLI this conversation's worker runs, as its offer named it. */
|
|
10217
|
-
agent:
|
|
10349
|
+
agent: z26.string().default("claude-code"),
|
|
10218
10350
|
/** Whether what the current claim took needs a reply, which other agents' messages don't. */
|
|
10219
|
-
replyWanted:
|
|
10351
|
+
replyWanted: z26.boolean().default(true),
|
|
10220
10352
|
/** For a delegate: the conversation that started it, which its starting prompt names. */
|
|
10221
|
-
parent:
|
|
10353
|
+
parent: z26.string().nullable().default(null),
|
|
10222
10354
|
/** Codex's session file for this worktree, once found, and how far the daemon has read it. */
|
|
10223
|
-
codexFile:
|
|
10224
|
-
codexOffset:
|
|
10355
|
+
codexFile: z26.string().nullable().default(null),
|
|
10356
|
+
codexOffset: z26.number().default(0),
|
|
10225
10357
|
/** When the agent was last started, so Codex's new session file is told from older ones. */
|
|
10226
|
-
agentStartedAt:
|
|
10358
|
+
agentStartedAt: z26.number().default(0),
|
|
10227
10359
|
/**
|
|
10228
10360
|
* The key the agent was last started with, as `HERD_START`. Its `herd inbox` carrying this key
|
|
10229
10361
|
* is what proves the start works: never a hook, a prompt being taken, or the screen.
|
|
10230
10362
|
*/
|
|
10231
|
-
startKey:
|
|
10363
|
+
startKey: z26.string().nullable().default(null),
|
|
10232
10364
|
/** Whether the current start has checked in. One from before keys counts as proven. */
|
|
10233
|
-
startProven:
|
|
10365
|
+
startProven: z26.boolean().default(true),
|
|
10234
10366
|
/** When the check-in window of an unproven start began, or null once it's proven or for none. */
|
|
10235
|
-
checkInFrom:
|
|
10367
|
+
checkInFrom: z26.number().nullable().default(null),
|
|
10236
10368
|
/** Whether this start has been flagged as needing someone at its terminal, so it's said once. */
|
|
10237
|
-
needsAttention:
|
|
10369
|
+
needsAttention: z26.boolean().default(false),
|
|
10238
10370
|
/** What agy's status line last said its agent was doing, and when. */
|
|
10239
|
-
agentState:
|
|
10240
|
-
agentStateAt:
|
|
10371
|
+
agentState: z26.enum(["working", "idle"]).nullable().default(null),
|
|
10372
|
+
agentStateAt: z26.number().default(0)
|
|
10241
10373
|
});
|
|
10242
|
-
var workspaceSchema =
|
|
10243
|
-
var stateSchema =
|
|
10374
|
+
var workspaceSchema = z26.preprocess(fromBeforeFolders, workspaceFields);
|
|
10375
|
+
var stateSchema = z26.object({ workspaces: z26.record(z26.string(), workspaceSchema) });
|
|
10244
10376
|
|
|
10245
10377
|
// src/workspaces/claims.ts
|
|
10246
10378
|
var holder = (ws, workspace) => `${ws.options.machineName()}/${workspace.lead}`;
|
|
@@ -11335,19 +11467,19 @@ function resolveAttachments(worktree, files) {
|
|
|
11335
11467
|
// src/workers.ts
|
|
11336
11468
|
init_define_HERD_PACKAGE();
|
|
11337
11469
|
init_src();
|
|
11338
|
-
import { z as
|
|
11339
|
-
var workerListingSchema =
|
|
11340
|
-
workers:
|
|
11341
|
-
machines:
|
|
11342
|
-
|
|
11343
|
-
id:
|
|
11344
|
-
name:
|
|
11345
|
-
online:
|
|
11346
|
-
missing:
|
|
11347
|
-
configError:
|
|
11470
|
+
import { z as z27 } from "zod";
|
|
11471
|
+
var workerListingSchema = z27.object({
|
|
11472
|
+
workers: z27.array(workerSchema),
|
|
11473
|
+
machines: z27.array(
|
|
11474
|
+
z27.object({
|
|
11475
|
+
id: z27.string(),
|
|
11476
|
+
name: z27.string(),
|
|
11477
|
+
online: z27.boolean(),
|
|
11478
|
+
missing: z27.array(z27.string()),
|
|
11479
|
+
configError: z27.string().optional()
|
|
11348
11480
|
})
|
|
11349
11481
|
),
|
|
11350
|
-
configType:
|
|
11482
|
+
configType: z27.string()
|
|
11351
11483
|
});
|
|
11352
11484
|
async function readWorkers(fetch2) {
|
|
11353
11485
|
const response = await fetch2("/api/workers");
|
|
@@ -11411,20 +11543,20 @@ function formatWorkers(listing, current = null) {
|
|
|
11411
11543
|
);
|
|
11412
11544
|
return lines.join("\n");
|
|
11413
11545
|
}
|
|
11414
|
-
var routingCheckSchema =
|
|
11415
|
-
suits:
|
|
11416
|
-
eligible:
|
|
11417
|
-
removed:
|
|
11418
|
-
questions:
|
|
11419
|
-
|
|
11546
|
+
var routingCheckSchema = z27.object({
|
|
11547
|
+
suits: z27.array(z27.object({ key: z27.string(), name: z27.string() })),
|
|
11548
|
+
eligible: z27.array(z27.object({ key: z27.string(), name: z27.string() })),
|
|
11549
|
+
removed: z27.array(z27.object({ key: z27.string(), name: z27.string(), rule: z27.string() })),
|
|
11550
|
+
questions: z27.array(
|
|
11551
|
+
z27.object({ id: z27.string(), question: z27.string(), probability: z27.number().nullable() })
|
|
11420
11552
|
),
|
|
11421
|
-
fallback:
|
|
11422
|
-
fits:
|
|
11423
|
-
|
|
11424
|
-
key:
|
|
11425
|
-
fit:
|
|
11426
|
-
statement:
|
|
11427
|
-
level:
|
|
11553
|
+
fallback: z27.string().optional(),
|
|
11554
|
+
fits: z27.array(
|
|
11555
|
+
z27.object({
|
|
11556
|
+
key: z27.string(),
|
|
11557
|
+
fit: z27.number(),
|
|
11558
|
+
statement: z27.string().optional(),
|
|
11559
|
+
level: z27.string().optional()
|
|
11428
11560
|
})
|
|
11429
11561
|
).optional()
|
|
11430
11562
|
});
|
|
@@ -13088,11 +13220,11 @@ function agyAnswer(event2, output2) {
|
|
|
13088
13220
|
}
|
|
13089
13221
|
|
|
13090
13222
|
// src/hook-client.ts
|
|
13091
|
-
var sleep7 = (
|
|
13092
|
-
function within2(promise,
|
|
13223
|
+
var sleep7 = (ms2) => new Promise((resolve7) => setTimeout(resolve7, ms2));
|
|
13224
|
+
function within2(promise, ms2) {
|
|
13093
13225
|
let timer;
|
|
13094
13226
|
const timeout = new Promise((resolve7) => {
|
|
13095
|
-
timer = setTimeout(() => resolve7(null),
|
|
13227
|
+
timer = setTimeout(() => resolve7(null), ms2);
|
|
13096
13228
|
});
|
|
13097
13229
|
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
|
|
13098
13230
|
}
|
|
@@ -13625,7 +13757,7 @@ async function runTerminalHost(rest) {
|
|
|
13625
13757
|
// src/commands/repo.ts
|
|
13626
13758
|
init_define_HERD_PACKAGE();
|
|
13627
13759
|
import { join as join35 } from "node:path";
|
|
13628
|
-
import { z as
|
|
13760
|
+
import { z as z33 } from "zod";
|
|
13629
13761
|
var REPO_HELP = `Usage: herd repo <url or owner/name> [folder]
|
|
13630
13762
|
|
|
13631
13763
|
Checks a repo out in this conversation's folder, on a branch named for the conversation, started
|
|
@@ -13639,16 +13771,16 @@ var REPOS_HELP = `Usage: herd repos [--json]
|
|
|
13639
13771
|
|
|
13640
13772
|
Lists the repos in this conversation's folder, the repos checked out in this machine's root, and
|
|
13641
13773
|
the repos your owner's herd.config.ts describes, with what each is for. Add one with herd repo.`;
|
|
13642
|
-
var repoContextSchema =
|
|
13643
|
-
folder:
|
|
13644
|
-
root:
|
|
13645
|
-
branch:
|
|
13646
|
-
legacy:
|
|
13647
|
-
legacyReason:
|
|
13648
|
-
recorded:
|
|
13649
|
-
cloned:
|
|
13650
|
-
described:
|
|
13651
|
-
|
|
13774
|
+
var repoContextSchema = z33.object({
|
|
13775
|
+
folder: z33.string(),
|
|
13776
|
+
root: z33.string(),
|
|
13777
|
+
branch: z33.string(),
|
|
13778
|
+
legacy: z33.boolean(),
|
|
13779
|
+
legacyReason: z33.string().optional(),
|
|
13780
|
+
recorded: z33.array(z33.object({ folder: z33.string(), remote: z33.string(), branch: z33.string() })),
|
|
13781
|
+
cloned: z33.array(z33.object({ key: z33.string(), remote: z33.string() })),
|
|
13782
|
+
described: z33.array(
|
|
13783
|
+
z33.object({ remote: z33.string(), key: z33.string().nullable(), about: z33.string().optional() })
|
|
13652
13784
|
)
|
|
13653
13785
|
});
|
|
13654
13786
|
var isUrl = (text4) => /^[a-z][a-z0-9+.-]*:\/\//i.test(text4) || text4.startsWith("/") || /^[^@/\s]+@[^:/\s]+:/.test(text4);
|
|
@@ -14018,7 +14150,7 @@ async function runWatch(command, rest) {
|
|
|
14018
14150
|
// src/commands/work.ts
|
|
14019
14151
|
init_define_HERD_PACKAGE();
|
|
14020
14152
|
init_src();
|
|
14021
|
-
import { z as
|
|
14153
|
+
import { z as z34 } from "zod";
|
|
14022
14154
|
var WORK_HELP = `Usage: herd work <url> [--kind <kind>] [--title "<title>"] [--status <status>]
|
|
14023
14155
|
[--detail "<detail>"] [--made] [--phase <phase>]
|
|
14024
14156
|
herd work --remove <url>
|
|
@@ -14110,9 +14242,9 @@ ${WORK_HELP}`
|
|
|
14110
14242
|
};
|
|
14111
14243
|
return { kind: "record", change, json };
|
|
14112
14244
|
}
|
|
14113
|
-
var followSchema =
|
|
14114
|
-
|
|
14115
|
-
|
|
14245
|
+
var followSchema = z34.union([
|
|
14246
|
+
z34.object({ following: z34.literal(true) }),
|
|
14247
|
+
z34.object({ following: z34.literal(false), reason: z34.string() })
|
|
14116
14248
|
]);
|
|
14117
14249
|
function formatFollow(follow) {
|
|
14118
14250
|
return follow.following ? "Following it: its reviews, CI and merge will reach herd inbox." : `Not followed: ${follow.reason}`;
|
|
@@ -14128,7 +14260,7 @@ function formatWork(work, own) {
|
|
|
14128
14260
|
return ` ${parts.join(" \xB7 ")}${work.made ? " made here" : ""}
|
|
14129
14261
|
${work.url}${whose}`;
|
|
14130
14262
|
}
|
|
14131
|
-
var listSchema =
|
|
14263
|
+
var listSchema = z34.array(workObjectSchema);
|
|
14132
14264
|
async function runWork(rest) {
|
|
14133
14265
|
const parsed = parseWork(rest);
|
|
14134
14266
|
if (parsed.kind === "help") {
|
|
@@ -14377,8 +14509,9 @@ On this computer:
|
|
|
14377
14509
|
Run this machine's daemon, working from its root folder. Repos given with
|
|
14378
14510
|
--repo are only listed as known, since herd works in its own clones
|
|
14379
14511
|
attach [<terminal>] Watch or take over a terminal. Ctrl+\\ detaches. With no name, lists them
|
|
14380
|
-
builds [register]
|
|
14381
|
-
|
|
14512
|
+
builds [register|speed]
|
|
14513
|
+
Whether this machine is a build runner, register it, with its owner's
|
|
14514
|
+
approval in the browser, or show how long builds take. See builds --help
|
|
14382
14515
|
setup Show what's set up for Friday and what's left, with how to do each step.
|
|
14383
14516
|
--json prints it as JSON. Inside a terminal, it's your owner's
|
|
14384
14517
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herdingchats/friday",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.600",
|
|
4
4
|
"description": "Friday, HerdingChats' agent daemon, and the herd command it runs agents with.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
"satori": "0.32.0",
|
|
23
23
|
"zod": "4.6.7"
|
|
24
24
|
},
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "258e3577331c639de77e7ab7f0cdccc48b275a89"
|
|
26
26
|
}
|