@herdingchats/friday 0.1.541 → 0.1.548
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 +538 -526
- package/package.json +2 -2
package/herd.mjs
CHANGED
|
@@ -18,12 +18,12 @@ 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.548", gitHead: "9f61cd323e160358d58bbb45c3835f3ae1bc25b3" };
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
// ../common-chat/src/activation.ts
|
|
26
|
-
import { z
|
|
26
|
+
import { z } from "zod";
|
|
27
27
|
function activationText(agent, activation) {
|
|
28
28
|
if (!activation || activation.state === "activated") return "activated";
|
|
29
29
|
if (activation.state === "waiting") {
|
|
@@ -45,8 +45,8 @@ var init_activation = __esm({
|
|
|
45
45
|
"../common-chat/src/activation.ts"() {
|
|
46
46
|
"use strict";
|
|
47
47
|
init_define_HERD_PACKAGE();
|
|
48
|
-
time =
|
|
49
|
-
activationFailureSchema =
|
|
48
|
+
time = z.number().int().nonnegative();
|
|
49
|
+
activationFailureSchema = z.enum([
|
|
50
50
|
// The agent showed its own sign-in, and nobody finished it in time.
|
|
51
51
|
"signed_out",
|
|
52
52
|
// A screen herd doesn't know was in the way.
|
|
@@ -56,11 +56,11 @@ var init_activation = __esm({
|
|
|
56
56
|
// It didn't start in its terminal at all.
|
|
57
57
|
"didnt_start"
|
|
58
58
|
]);
|
|
59
|
-
agentActivationSchema =
|
|
60
|
-
state:
|
|
61
|
-
version:
|
|
59
|
+
agentActivationSchema = z.object({
|
|
60
|
+
state: z.enum(["activated", "waiting", "failed"]),
|
|
61
|
+
version: z.string().min(1).max(100),
|
|
62
62
|
at: time,
|
|
63
|
-
signingIn:
|
|
63
|
+
signingIn: z.boolean().optional(),
|
|
64
64
|
reason: activationFailureSchema.optional()
|
|
65
65
|
});
|
|
66
66
|
activationSignedOut = (activation) => Boolean(
|
|
@@ -71,34 +71,34 @@ var init_activation = __esm({
|
|
|
71
71
|
codex: "codex",
|
|
72
72
|
agy: "agy"
|
|
73
73
|
};
|
|
74
|
-
gitHubCliSchema =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
gitHubCliSchema = z.discriminatedUnion("state", [
|
|
75
|
+
z.object({ state: z.literal("signed_in"), login: z.string().min(1).max(100), checkedAt: time }),
|
|
76
|
+
z.object({ state: z.literal("signed_out"), checkedAt: time }),
|
|
77
|
+
z.object({ state: z.literal("missing"), checkedAt: time })
|
|
78
78
|
]);
|
|
79
|
-
signInToolSchema =
|
|
79
|
+
signInToolSchema = z.enum(["gh"]);
|
|
80
80
|
GITHUB_DEVICE_URL = "https://github.com/login/device";
|
|
81
|
-
signInUpdateSchema =
|
|
82
|
-
|
|
83
|
-
state:
|
|
84
|
-
code:
|
|
85
|
-
url:
|
|
81
|
+
signInUpdateSchema = z.discriminatedUnion("state", [
|
|
82
|
+
z.object({
|
|
83
|
+
state: z.literal("code"),
|
|
84
|
+
code: z.string().regex(/^[A-Z0-9]{4}-[A-Z0-9]{4}$/),
|
|
85
|
+
url: z.literal(GITHUB_DEVICE_URL)
|
|
86
86
|
}),
|
|
87
|
-
|
|
87
|
+
z.object({ state: z.literal("signed_in"), login: z.string().min(1).max(100) }),
|
|
88
88
|
// `no_code`: it printed nothing herd recognizes. `not_signed_in`: it ended without signing in.
|
|
89
|
-
|
|
89
|
+
z.object({ state: z.literal("failed"), reason: z.enum(["no_code", "not_signed_in"]) })
|
|
90
90
|
]);
|
|
91
91
|
}
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
// ../common-chat/src/github-triggers.ts
|
|
95
|
-
import { z as
|
|
95
|
+
import { z as z2 } from "zod";
|
|
96
96
|
var nonEmpty, GITHUB_TRIGGER_KINDS, githubTriggerKindSchema, GITHUB_TRIGGER_LABELS, githubTriggerEventSchema;
|
|
97
97
|
var init_github_triggers = __esm({
|
|
98
98
|
"../common-chat/src/github-triggers.ts"() {
|
|
99
99
|
"use strict";
|
|
100
100
|
init_define_HERD_PACKAGE();
|
|
101
|
-
nonEmpty =
|
|
101
|
+
nonEmpty = z2.string().min(1);
|
|
102
102
|
GITHUB_TRIGGER_KINDS = [
|
|
103
103
|
"opened",
|
|
104
104
|
"review_requested",
|
|
@@ -107,7 +107,7 @@ var init_github_triggers = __esm({
|
|
|
107
107
|
"merged",
|
|
108
108
|
"mention"
|
|
109
109
|
];
|
|
110
|
-
githubTriggerKindSchema =
|
|
110
|
+
githubTriggerKindSchema = z2.enum(GITHUB_TRIGGER_KINDS);
|
|
111
111
|
GITHUB_TRIGGER_LABELS = {
|
|
112
112
|
opened: "Pull requests you open",
|
|
113
113
|
review_requested: "Review requests",
|
|
@@ -116,33 +116,33 @@ var init_github_triggers = __esm({
|
|
|
116
116
|
merged: "Your pull requests merged",
|
|
117
117
|
mention: "Mentions of you"
|
|
118
118
|
};
|
|
119
|
-
githubTriggerEventSchema =
|
|
119
|
+
githubTriggerEventSchema = z2.object({
|
|
120
120
|
/** The event, so each fires an automation once. */
|
|
121
121
|
key: nonEmpty,
|
|
122
122
|
kind: githubTriggerKindSchema,
|
|
123
|
-
repoId:
|
|
123
|
+
repoId: z2.number().int(),
|
|
124
124
|
/** `owner/name`. */
|
|
125
125
|
repo: nonEmpty,
|
|
126
|
-
number:
|
|
126
|
+
number: z2.number().int().positive(),
|
|
127
127
|
/** The pull request's link. */
|
|
128
|
-
url:
|
|
128
|
+
url: z2.url(),
|
|
129
129
|
/** Where the event itself is, such as the review or the comment. */
|
|
130
|
-
eventUrl:
|
|
130
|
+
eventUrl: z2.url().optional(),
|
|
131
131
|
/** The pull request's title, when the event says it. */
|
|
132
|
-
title:
|
|
132
|
+
title: z2.string().max(300).optional(),
|
|
133
133
|
/** Who caused it. */
|
|
134
134
|
by: nonEmpty,
|
|
135
135
|
/** For a review, its state: `approved`, `changes_requested` or `commented`. */
|
|
136
|
-
state:
|
|
137
|
-
private:
|
|
138
|
-
at:
|
|
136
|
+
state: z2.string().optional(),
|
|
137
|
+
private: z2.boolean(),
|
|
138
|
+
at: z2.number().int().nonnegative()
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
});
|
|
142
142
|
|
|
143
143
|
// ../common-chat/src/automations.ts
|
|
144
144
|
import { Cron } from "croner";
|
|
145
|
-
import { z as
|
|
145
|
+
import { z as z3 } from "zod";
|
|
146
146
|
function isTimeZone(timeZone) {
|
|
147
147
|
try {
|
|
148
148
|
new Intl.DateTimeFormat("en-US", { timeZone }).format(0);
|
|
@@ -212,56 +212,56 @@ var init_automations = __esm({
|
|
|
212
212
|
MIN_SCHEDULE_INTERVAL_MS = 15 * 60 * 1e3;
|
|
213
213
|
MAX_WEBHOOK_BODY = 64 * 1024;
|
|
214
214
|
MAX_ONCE_AHEAD_MS = 366 * 24 * 60 * 60 * 1e3;
|
|
215
|
-
nonEmpty2 =
|
|
215
|
+
nonEmpty2 = z3.string().trim().min(1);
|
|
216
216
|
timeZoneSchema = nonEmpty2.max(64).refine(isTimeZone, "That isn't a time zone. Use an IANA name, such as America/Los_Angeles.");
|
|
217
|
-
triggerSchema =
|
|
217
|
+
triggerSchema = z3.discriminatedUnion("kind", [
|
|
218
218
|
// A five-field cron expression, read in its time zone.
|
|
219
|
-
|
|
219
|
+
z3.object({ kind: z3.literal("cron"), cron: nonEmpty2.max(100), timeZone: timeZoneSchema }),
|
|
220
220
|
// A single instant, with the time zone it's described in.
|
|
221
|
-
|
|
221
|
+
z3.object({ kind: z3.literal("once"), at: z3.number().int().positive(), timeZone: timeZoneSchema }),
|
|
222
222
|
// A secret URL on the hooks hostname, which anything can post to.
|
|
223
|
-
|
|
223
|
+
z3.object({ kind: z3.literal("webhook") }),
|
|
224
224
|
// The owner's own GitHub events, of these kinds, and only in these repos when it names any.
|
|
225
225
|
// `unfollowed` keeps only pull requests none of the owner's conversations follow or made.
|
|
226
|
-
|
|
227
|
-
kind:
|
|
228
|
-
events:
|
|
229
|
-
unfollowed:
|
|
230
|
-
repos:
|
|
231
|
-
|
|
226
|
+
z3.object({
|
|
227
|
+
kind: z3.literal("github"),
|
|
228
|
+
events: z3.array(githubTriggerKindSchema).min(1).max(GITHUB_TRIGGER_KINDS.length),
|
|
229
|
+
unfollowed: z3.boolean().optional(),
|
|
230
|
+
repos: z3.array(
|
|
231
|
+
z3.string().trim().regex(/^[A-Za-z0-9-]{1,39}\/[A-Za-z0-9._-]{1,100}$/, "Name each repo as owner/name.")
|
|
232
232
|
).max(10).optional()
|
|
233
233
|
})
|
|
234
234
|
]);
|
|
235
235
|
triggerTimeZone = (trigger) => trigger.kind === "cron" || trigger.kind === "once" ? trigger.timeZone : "UTC";
|
|
236
|
-
targetInputSchema =
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
236
|
+
targetInputSchema = z3.discriminatedUnion("kind", [
|
|
237
|
+
z3.object({ kind: z3.literal("direct") }),
|
|
238
|
+
z3.object({ kind: z3.literal("channel"), channel: nonEmpty2.max(100) }),
|
|
239
|
+
z3.object({ kind: z3.literal("conversation"), conversationId: nonEmpty2.max(100) })
|
|
240
240
|
]);
|
|
241
|
-
targetSchema =
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
kind:
|
|
241
|
+
targetSchema = z3.discriminatedUnion("kind", [
|
|
242
|
+
z3.object({ kind: z3.literal("direct") }),
|
|
243
|
+
z3.object({
|
|
244
|
+
kind: z3.literal("channel"),
|
|
245
245
|
channel: nonEmpty2,
|
|
246
246
|
name: nonEmpty2,
|
|
247
|
-
isPrivate:
|
|
247
|
+
isPrivate: z3.boolean()
|
|
248
248
|
}),
|
|
249
|
-
|
|
249
|
+
z3.object({ kind: z3.literal("conversation"), conversationId: nonEmpty2 })
|
|
250
250
|
]);
|
|
251
251
|
MAX_AUTOMATION_REPOS = 10;
|
|
252
|
-
automationInputSchema =
|
|
252
|
+
automationInputSchema = z3.object({
|
|
253
253
|
name: nonEmpty2.max(80),
|
|
254
254
|
trigger: triggerSchema,
|
|
255
255
|
target: targetInputSchema,
|
|
256
256
|
instructions: nonEmpty2.max(MAX_INSTRUCTIONS),
|
|
257
257
|
// The repos each firing's conversation starts with, as hints. `repo` is the one-repo form from
|
|
258
258
|
// before automations could name several, read as a list of one.
|
|
259
|
-
repos:
|
|
259
|
+
repos: z3.array(nonEmpty2.max(300)).max(MAX_AUTOMATION_REPOS).optional(),
|
|
260
260
|
repo: nonEmpty2.max(300).nullable().optional()
|
|
261
261
|
});
|
|
262
262
|
automationChangeSchema = automationInputSchema.partial();
|
|
263
|
-
automationStateSchema =
|
|
264
|
-
firingOutcomeSchema =
|
|
263
|
+
automationStateSchema = z3.enum(["pending_approval", "active", "paused", "finished"]);
|
|
264
|
+
firingOutcomeSchema = z3.enum([
|
|
265
265
|
// Waiting to reach its conversation.
|
|
266
266
|
"pending",
|
|
267
267
|
"delivered",
|
|
@@ -275,7 +275,7 @@ var init_automations = __esm({
|
|
|
275
275
|
});
|
|
276
276
|
|
|
277
277
|
// ../common-chat/src/content.ts
|
|
278
|
-
import { z as
|
|
278
|
+
import { z as z4 } from "zod";
|
|
279
279
|
function exactlyOneBody(message, ctx) {
|
|
280
280
|
if (message.text === void 0 === (message.markdown === void 0)) {
|
|
281
281
|
ctx.addIssue({
|
|
@@ -306,80 +306,80 @@ var init_content = __esm({
|
|
|
306
306
|
MAX_FILES_PER_MESSAGE = 10;
|
|
307
307
|
MAX_FILE_BYTES = 100 * 1024 * 1024;
|
|
308
308
|
MAX_CONVERSATION_FILE_BYTES = 1024 * 1024 * 1024;
|
|
309
|
-
layoutPlatformSchema =
|
|
310
|
-
blockSchema =
|
|
311
|
-
blocksSchema =
|
|
309
|
+
layoutPlatformSchema = z4.enum(["slack"]);
|
|
310
|
+
blockSchema = z4.looseObject({ type: z4.string().min(1) });
|
|
311
|
+
blocksSchema = z4.array(blockSchema).min(1).max(MAX_LAYOUT_BLOCKS, `A message can have at most ${MAX_LAYOUT_BLOCKS} blocks.`).refine(
|
|
312
312
|
(blocks) => new TextEncoder().encode(JSON.stringify(blocks)).length <= MAX_LAYOUT_BYTES,
|
|
313
313
|
`Blocks can be at most ${MAX_LAYOUT_BYTES / 1e3} KB as JSON.`
|
|
314
314
|
);
|
|
315
|
-
layoutSchema =
|
|
315
|
+
layoutSchema = z4.strictObject({
|
|
316
316
|
platform: layoutPlatformSchema,
|
|
317
317
|
blocks: blocksSchema
|
|
318
318
|
});
|
|
319
|
-
textBody =
|
|
319
|
+
textBody = z4.string().max(
|
|
320
320
|
MAX_TEXT_LENGTH,
|
|
321
321
|
`Text can be at most ${MAX_TEXT_LENGTH.toLocaleString("en-US")} characters.`
|
|
322
322
|
).refine((text4) => text4.trim().length > 0, "The message is empty.");
|
|
323
|
-
markdownBody =
|
|
323
|
+
markdownBody = z4.string().max(
|
|
324
324
|
MAX_MARKDOWN_LENGTH,
|
|
325
325
|
`Markdown can be at most ${MAX_MARKDOWN_LENGTH.toLocaleString("en-US")} characters.`
|
|
326
326
|
).refine((text4) => text4.trim().length > 0, "The message is empty.");
|
|
327
|
-
title =
|
|
328
|
-
alt =
|
|
329
|
-
channelTargetSchema =
|
|
327
|
+
title = z4.string().trim().min(1).max(255);
|
|
328
|
+
alt = z4.string().trim().min(1).max(1e3);
|
|
329
|
+
channelTargetSchema = z4.string().trim().regex(/^(#[a-z0-9][a-z0-9._-]{0,79}|[CG][A-Z0-9]{2,})$/, {
|
|
330
330
|
message: "A channel is an ID such as C0123ABCD, or a name such as #eng."
|
|
331
331
|
});
|
|
332
|
-
herdMessageSchema =
|
|
332
|
+
herdMessageSchema = z4.strictObject({
|
|
333
333
|
text: textBody.optional(),
|
|
334
334
|
markdown: markdownBody.optional(),
|
|
335
335
|
blocks: blocksSchema.optional(),
|
|
336
|
-
files:
|
|
337
|
-
|
|
336
|
+
files: z4.array(
|
|
337
|
+
z4.strictObject({ path: z4.string().min(1), title: title.optional(), alt: alt.optional() })
|
|
338
338
|
).min(1).max(MAX_FILES_PER_MESSAGE, `A message can have at most ${MAX_FILES_PER_MESSAGE} files.`).optional(),
|
|
339
339
|
channel: channelTargetSchema.optional()
|
|
340
340
|
}).superRefine(exactlyOneBody);
|
|
341
|
-
sendMessageSchema =
|
|
341
|
+
sendMessageSchema = z4.strictObject({
|
|
342
342
|
text: textBody.optional(),
|
|
343
343
|
markdown: markdownBody.optional(),
|
|
344
344
|
layout: layoutSchema.optional(),
|
|
345
|
-
files:
|
|
346
|
-
|
|
347
|
-
id:
|
|
345
|
+
files: z4.array(
|
|
346
|
+
z4.strictObject({
|
|
347
|
+
id: z4.string().min(1).max(100),
|
|
348
348
|
title: title.optional(),
|
|
349
349
|
alt: alt.optional()
|
|
350
350
|
})
|
|
351
351
|
).min(1).max(MAX_FILES_PER_MESSAGE, `A message can have at most ${MAX_FILES_PER_MESSAGE} files.`).optional(),
|
|
352
352
|
channel: channelTargetSchema.optional(),
|
|
353
|
-
quiet:
|
|
353
|
+
quiet: z4.boolean().optional(),
|
|
354
354
|
// Which client an agent sent it through, such as "Claude Code", recorded on the message.
|
|
355
|
-
client:
|
|
355
|
+
client: z4.string().trim().min(1).max(40).regex(/^[^\r\n]+$/).optional()
|
|
356
356
|
}).superRefine(exactlyOneBody).superRefine((message, ctx) => {
|
|
357
357
|
if (message.quiet && message.channel) {
|
|
358
358
|
ctx.addIssue({ code: "custom", message: "A channel post can't be quiet.", path: ["quiet"] });
|
|
359
359
|
}
|
|
360
360
|
});
|
|
361
|
-
messageFileStateSchema =
|
|
362
|
-
messageFileSchema =
|
|
363
|
-
id:
|
|
364
|
-
name:
|
|
365
|
-
type:
|
|
366
|
-
size:
|
|
367
|
-
title:
|
|
368
|
-
alt:
|
|
361
|
+
messageFileStateSchema = z4.enum(["pending", "ready", "unavailable"]);
|
|
362
|
+
messageFileSchema = z4.object({
|
|
363
|
+
id: z4.string().min(1),
|
|
364
|
+
name: z4.string().min(1),
|
|
365
|
+
type: z4.string().min(1),
|
|
366
|
+
size: z4.number().int().nonnegative(),
|
|
367
|
+
title: z4.string().optional(),
|
|
368
|
+
alt: z4.string().optional(),
|
|
369
369
|
state: messageFileStateSchema.optional(),
|
|
370
370
|
// Why an `unavailable` file couldn't come in, for a person to read.
|
|
371
|
-
reason:
|
|
371
|
+
reason: z4.string().optional()
|
|
372
372
|
});
|
|
373
|
-
postTargetSchema =
|
|
374
|
-
place:
|
|
375
|
-
placeName:
|
|
376
|
-
conversationId:
|
|
373
|
+
postTargetSchema = z4.object({
|
|
374
|
+
place: z4.string().min(1),
|
|
375
|
+
placeName: z4.string().min(1),
|
|
376
|
+
conversationId: z4.string().min(1)
|
|
377
377
|
});
|
|
378
378
|
}
|
|
379
379
|
});
|
|
380
380
|
|
|
381
381
|
// ../common-chat/src/github.ts
|
|
382
|
-
import { z as
|
|
382
|
+
import { z as z5 } from "zod";
|
|
383
383
|
function parsePullRequestRef(text4) {
|
|
384
384
|
const trimmed = text4.trim();
|
|
385
385
|
const short = trimmed.match(new RegExp(`^(${NAME})/(${REPO})#(\\d{1,10})$`));
|
|
@@ -397,16 +397,16 @@ var init_github = __esm({
|
|
|
397
397
|
"../common-chat/src/github.ts"() {
|
|
398
398
|
"use strict";
|
|
399
399
|
init_define_HERD_PACKAGE();
|
|
400
|
-
nonEmpty3 =
|
|
400
|
+
nonEmpty3 = z5.string().min(1);
|
|
401
401
|
MAX_EXTERNAL_TEXT = 4e3;
|
|
402
|
-
subscriptionOriginSchema =
|
|
403
|
-
subscriptionEndSchema =
|
|
402
|
+
subscriptionOriginSchema = z5.enum(["watch", "branch", "work"]);
|
|
403
|
+
subscriptionEndSchema = z5.enum([
|
|
404
404
|
"resource_closed",
|
|
405
405
|
"unsubscribed",
|
|
406
406
|
"uninstalled",
|
|
407
407
|
"conversation_deleted"
|
|
408
408
|
]);
|
|
409
|
-
githubEventKindSchema =
|
|
409
|
+
githubEventKindSchema = z5.enum([
|
|
410
410
|
"pull_request",
|
|
411
411
|
"review",
|
|
412
412
|
"review_comment",
|
|
@@ -414,48 +414,48 @@ var init_github = __esm({
|
|
|
414
414
|
"comment",
|
|
415
415
|
"ci"
|
|
416
416
|
]);
|
|
417
|
-
githubSenderSchema =
|
|
418
|
-
id:
|
|
417
|
+
githubSenderSchema = z5.object({
|
|
418
|
+
id: z5.number().int(),
|
|
419
419
|
login: nonEmpty3,
|
|
420
|
-
association:
|
|
421
|
-
bot:
|
|
420
|
+
association: z5.string().optional(),
|
|
421
|
+
bot: z5.boolean()
|
|
422
422
|
});
|
|
423
|
-
githubEventSummarySchema =
|
|
423
|
+
githubEventSummarySchema = z5.object({
|
|
424
424
|
resource: nonEmpty3,
|
|
425
425
|
/** `owner/name#number`, for people. */
|
|
426
426
|
label: nonEmpty3,
|
|
427
427
|
kind: githubEventKindSchema,
|
|
428
428
|
action: nonEmpty3,
|
|
429
429
|
/** What it reports, such as `merged`, `changes_requested` or `failed`. */
|
|
430
|
-
state:
|
|
431
|
-
url:
|
|
430
|
+
state: z5.string().optional(),
|
|
431
|
+
url: z5.url(),
|
|
432
432
|
sender: githubSenderSchema,
|
|
433
433
|
/** A person's words, cut to `MAX_EXTERNAL_TEXT`. */
|
|
434
|
-
text:
|
|
435
|
-
sha:
|
|
434
|
+
text: z5.string().max(MAX_EXTERNAL_TEXT).optional(),
|
|
435
|
+
sha: z5.string().optional(),
|
|
436
436
|
/** For CI: the check or status that settled it, or failed first. */
|
|
437
|
-
check:
|
|
438
|
-
wakes:
|
|
437
|
+
check: z5.object({ name: nonEmpty3, conclusion: z5.string().optional() }).optional(),
|
|
438
|
+
wakes: z5.boolean(),
|
|
439
439
|
reason: nonEmpty3,
|
|
440
440
|
/** Set when its author isn't an owner, member or collaborator of the repo. */
|
|
441
|
-
outsider:
|
|
441
|
+
outsider: z5.boolean().optional(),
|
|
442
442
|
/** Set when its author is a GitHub account linked to the subscriber. */
|
|
443
|
-
own:
|
|
443
|
+
own: z5.boolean().optional(),
|
|
444
444
|
/**
|
|
445
445
|
* Whether its repo is private, and GitHub's numeric ID for the repo, so its words are shown only
|
|
446
446
|
* to people who can read it. A summary stored without `private` is treated as private.
|
|
447
447
|
*/
|
|
448
|
-
private:
|
|
449
|
-
repoId:
|
|
448
|
+
private: z5.boolean().optional(),
|
|
449
|
+
repoId: z5.number().int().optional(),
|
|
450
450
|
/** Set where a reader can't see the words of a private repo, which were taken out. */
|
|
451
|
-
withheld:
|
|
451
|
+
withheld: z5.boolean().optional()
|
|
452
452
|
});
|
|
453
|
-
subscriptionSchema =
|
|
453
|
+
subscriptionSchema = z5.object({
|
|
454
454
|
resource: nonEmpty3,
|
|
455
455
|
label: nonEmpty3,
|
|
456
|
-
url:
|
|
456
|
+
url: z5.url(),
|
|
457
457
|
createdBy: subscriptionOriginSchema,
|
|
458
|
-
createdAt:
|
|
458
|
+
createdAt: z5.number().int().nonnegative()
|
|
459
459
|
});
|
|
460
460
|
NAME = "[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})";
|
|
461
461
|
REPO = "[A-Za-z0-9._-]{1,100}";
|
|
@@ -463,7 +463,7 @@ var init_github = __esm({
|
|
|
463
463
|
});
|
|
464
464
|
|
|
465
465
|
// ../common-chat/src/usage.ts
|
|
466
|
-
import { z as
|
|
466
|
+
import { z as z6 } from "zod";
|
|
467
467
|
function currentUsage(usage, now) {
|
|
468
468
|
if (!usage) return void 0;
|
|
469
469
|
const fresh = (window) => window && window.resetsAt > now ? window : void 0;
|
|
@@ -481,38 +481,38 @@ var init_usage = __esm({
|
|
|
481
481
|
"../common-chat/src/usage.ts"() {
|
|
482
482
|
"use strict";
|
|
483
483
|
init_define_HERD_PACKAGE();
|
|
484
|
-
usageWindowSchema =
|
|
485
|
-
usedPercentage:
|
|
486
|
-
resetsAt:
|
|
484
|
+
usageWindowSchema = z6.object({
|
|
485
|
+
usedPercentage: z6.number().min(0).max(100),
|
|
486
|
+
resetsAt: z6.number().int().nonnegative()
|
|
487
487
|
});
|
|
488
488
|
USAGE_AGENTS = {
|
|
489
489
|
"claude-code": "Claude",
|
|
490
490
|
codex: "Codex",
|
|
491
491
|
agy: "Antigravity"
|
|
492
492
|
};
|
|
493
|
-
usageSchema =
|
|
493
|
+
usageSchema = z6.object({
|
|
494
494
|
fiveHour: usageWindowSchema.optional(),
|
|
495
495
|
sevenDay: usageWindowSchema.optional(),
|
|
496
|
-
agent:
|
|
496
|
+
agent: z6.enum(["claude-code", "codex", "agy"]).optional()
|
|
497
497
|
}).refine((usage) => usage.fiveHour || usage.sevenDay, "Usage needs at least one window");
|
|
498
498
|
MAX_ACTIVITY_LENGTH = 150;
|
|
499
|
-
activityTextSchema =
|
|
499
|
+
activityTextSchema = z6.string().trim().min(1).max(MAX_ACTIVITY_LENGTH).regex(/^[^\r\n]+$/);
|
|
500
500
|
MAX_TITLE_LENGTH = 40;
|
|
501
|
-
titleSchema =
|
|
502
|
-
listedWindowSchema =
|
|
501
|
+
titleSchema = z6.string().trim().min(1).max(MAX_TITLE_LENGTH).regex(/^[^\r\n]+$/);
|
|
502
|
+
listedWindowSchema = z6.union([
|
|
503
503
|
usageWindowSchema,
|
|
504
|
-
|
|
504
|
+
z6.object({ reset: z6.literal(true), resetsAt: z6.number().int().nonnegative() })
|
|
505
505
|
]);
|
|
506
|
-
listedUsageSchema =
|
|
506
|
+
listedUsageSchema = z6.object({
|
|
507
507
|
fiveHour: listedWindowSchema.optional(),
|
|
508
508
|
sevenDay: listedWindowSchema.optional(),
|
|
509
|
-
agent:
|
|
509
|
+
agent: z6.enum(["claude-code", "codex", "agy"]).optional()
|
|
510
510
|
});
|
|
511
511
|
}
|
|
512
512
|
});
|
|
513
513
|
|
|
514
514
|
// ../common-chat/src/workers.ts
|
|
515
|
-
import { z as
|
|
515
|
+
import { z as z7 } from "zod";
|
|
516
516
|
function agentShortName(cli) {
|
|
517
517
|
return AGENTS[cli]?.short ?? cli;
|
|
518
518
|
}
|
|
@@ -548,11 +548,11 @@ var init_workers = __esm({
|
|
|
548
548
|
"xcode",
|
|
549
549
|
"image_generation"
|
|
550
550
|
];
|
|
551
|
-
capabilitySchema =
|
|
551
|
+
capabilitySchema = z7.enum(CAPABILITIES);
|
|
552
552
|
PLATFORMS = ["macos", "linux", "windows"];
|
|
553
|
-
platformSchema =
|
|
553
|
+
platformSchema = z7.enum(PLATFORMS);
|
|
554
554
|
TOOLS = ["xcode", "gpu"];
|
|
555
|
-
toolSchema =
|
|
555
|
+
toolSchema = z7.enum(TOOLS);
|
|
556
556
|
CAPABILITY_WORDING = {
|
|
557
557
|
macos: "a Mac running macOS",
|
|
558
558
|
linux: "a Linux computer",
|
|
@@ -570,51 +570,51 @@ var init_workers = __esm({
|
|
|
570
570
|
PHRASE_MAX = 100;
|
|
571
571
|
PHRASES_MAX = 10;
|
|
572
572
|
ABOUT_MAX = 500;
|
|
573
|
-
phrase =
|
|
574
|
-
phrases =
|
|
573
|
+
phrase = z7.string().trim().min(1).max(PHRASE_MAX, `at most ${PHRASE_MAX} characters`);
|
|
574
|
+
phrases = z7.array(phrase).max(PHRASES_MAX, `at most ${PHRASES_MAX} phrases`);
|
|
575
575
|
SHARES = ["off", "little", "some", "lot"];
|
|
576
|
-
shareSchema =
|
|
576
|
+
shareSchema = z7.enum(SHARES);
|
|
577
577
|
SHARE_LABELS = {
|
|
578
578
|
off: "off",
|
|
579
579
|
little: "a little",
|
|
580
580
|
some: "some",
|
|
581
581
|
lot: "a lot"
|
|
582
582
|
};
|
|
583
|
-
harnessConfigSchema =
|
|
583
|
+
harnessConfigSchema = z7.object({
|
|
584
584
|
share: shareSchema.optional(),
|
|
585
585
|
/** Read as `share: "off"` when false, from files written before shares. */
|
|
586
|
-
enabled:
|
|
586
|
+
enabled: z7.boolean().optional(),
|
|
587
587
|
only: phrases.optional(),
|
|
588
588
|
great: phrases.optional(),
|
|
589
589
|
good: phrases.optional(),
|
|
590
590
|
okay: phrases.optional(),
|
|
591
591
|
cant: phrases.optional(),
|
|
592
592
|
/** false starts the harness's profile empty, rather than from herd's defaults. */
|
|
593
|
-
defaults:
|
|
593
|
+
defaults: z7.boolean().optional(),
|
|
594
594
|
/** Read as `great`, from files written before profiles. */
|
|
595
595
|
prefer: phrases.optional(),
|
|
596
596
|
/** Read as `cant`, from files written before profiles. */
|
|
597
597
|
avoid: phrases.optional(),
|
|
598
|
-
priority:
|
|
598
|
+
priority: z7.number().int().min(-100).max(100).optional()
|
|
599
599
|
}).strict();
|
|
600
600
|
BUILDS_MAX = 4;
|
|
601
|
-
buildsSettingSchema =
|
|
602
|
-
|
|
603
|
-
|
|
601
|
+
buildsSettingSchema = z7.union([
|
|
602
|
+
z7.literal(true),
|
|
603
|
+
z7.object({ max: z7.number().int().min(1).max(BUILDS_MAX) }).strict()
|
|
604
604
|
]);
|
|
605
605
|
CONFIG_REPOS_MAX = 50;
|
|
606
|
-
configRepoSchema =
|
|
607
|
-
remote:
|
|
608
|
-
about:
|
|
606
|
+
configRepoSchema = z7.object({
|
|
607
|
+
remote: z7.string().trim().min(1).max(300),
|
|
608
|
+
about: z7.string().trim().max(PHRASE_MAX, `at most ${PHRASE_MAX} characters`).optional()
|
|
609
609
|
}).strict();
|
|
610
|
-
herdConfigSchema =
|
|
611
|
-
about:
|
|
610
|
+
herdConfigSchema = z7.object({
|
|
611
|
+
about: z7.string().trim().max(ABOUT_MAX, `at most ${ABOUT_MAX} characters`).optional(),
|
|
612
612
|
cant: phrases.optional(),
|
|
613
613
|
/** Read as `cant`, from files written before profiles. */
|
|
614
614
|
avoid: phrases.optional(),
|
|
615
|
-
harnesses:
|
|
615
|
+
harnesses: z7.record(z7.string().regex(/^[a-z][a-z0-9-]*$/), harnessConfigSchema).optional(),
|
|
616
616
|
builds: buildsSettingSchema.optional(),
|
|
617
|
-
repos:
|
|
617
|
+
repos: z7.array(configRepoSchema).max(CONFIG_REPOS_MAX, `at most ${CONFIG_REPOS_MAX} repos`).optional()
|
|
618
618
|
}).strict();
|
|
619
619
|
HERD_CONFIG_TYPE = `type HerdConfig = {
|
|
620
620
|
/** What this machine is for, in plain words. At most ${ABOUT_MAX} characters. */
|
|
@@ -665,41 +665,41 @@ export default {
|
|
|
665
665
|
harnesses: { claude: { great: ["code review"] }, codex: { cant: ["the billing service"] } },
|
|
666
666
|
} satisfies HerdConfig;`;
|
|
667
667
|
PROFILE_LEVELS = ["great", "good", "okay", "cant"];
|
|
668
|
-
profileEntrySchema =
|
|
669
|
-
statement:
|
|
670
|
-
level:
|
|
671
|
-
source:
|
|
668
|
+
profileEntrySchema = z7.object({
|
|
669
|
+
statement: z7.string().min(1),
|
|
670
|
+
level: z7.enum(PROFILE_LEVELS),
|
|
671
|
+
source: z7.enum(["default", "owner"])
|
|
672
672
|
});
|
|
673
|
-
workerSchema =
|
|
674
|
-
key:
|
|
675
|
-
name:
|
|
676
|
-
machineId:
|
|
677
|
-
machineName:
|
|
678
|
-
agent:
|
|
679
|
-
capabilities:
|
|
680
|
-
about:
|
|
681
|
-
only:
|
|
673
|
+
workerSchema = z7.object({
|
|
674
|
+
key: z7.string().min(1),
|
|
675
|
+
name: z7.string().min(1),
|
|
676
|
+
machineId: z7.string().min(1),
|
|
677
|
+
machineName: z7.string().min(1),
|
|
678
|
+
agent: z7.string().min(1),
|
|
679
|
+
capabilities: z7.array(capabilitySchema),
|
|
680
|
+
about: z7.string().optional(),
|
|
681
|
+
only: z7.array(z7.string()),
|
|
682
682
|
/** What it's great, good and okay at, and can't do: its agent's defaults with its owner's word. */
|
|
683
|
-
profile:
|
|
684
|
-
priority:
|
|
683
|
+
profile: z7.array(profileEntrySchema),
|
|
684
|
+
priority: z7.number().int(),
|
|
685
685
|
/** How much of its agent its owner has. Servers from before shares send none, which is "some". */
|
|
686
686
|
share: shareSchema.default("some"),
|
|
687
|
-
enabled:
|
|
687
|
+
enabled: z7.boolean(),
|
|
688
688
|
/** Whether its agent checked in from herd's terminal on this version, so it's offered work. */
|
|
689
|
-
activated:
|
|
689
|
+
activated: z7.boolean(),
|
|
690
690
|
activation: agentActivationSchema.optional(),
|
|
691
|
-
online:
|
|
691
|
+
online: z7.boolean(),
|
|
692
692
|
// Its machine's repos, each marked whether herd has cloned it there. Older daemons send no `cloned`.
|
|
693
|
-
repos:
|
|
694
|
-
|
|
693
|
+
repos: z7.array(
|
|
694
|
+
z7.object({ name: z7.string(), remote: z7.string(), cloned: z7.boolean().optional() })
|
|
695
695
|
),
|
|
696
|
-
machineCreatedAt:
|
|
696
|
+
machineCreatedAt: z7.number().int().nonnegative()
|
|
697
697
|
});
|
|
698
698
|
}
|
|
699
699
|
});
|
|
700
700
|
|
|
701
701
|
// ../common-chat/src/machines.ts
|
|
702
|
-
import { z as
|
|
702
|
+
import { z as z8 } from "zod";
|
|
703
703
|
var nonEmpty4, time2, terminalStateSchema, agentStatusSchema, machineRepoSchema, isCloned, machineCliSchema, machineRegistrationSchema, machineSchema, machinePresenceSchema, worktreeSchema, MAX_REPO_HINTS, repoHintSchema, terminalSchema, offerSchema, offerAnswerSchema, dispatchFrameSchema, machineMessageSchema;
|
|
704
704
|
var init_machines = __esm({
|
|
705
705
|
"../common-chat/src/machines.ts"() {
|
|
@@ -708,9 +708,9 @@ var init_machines = __esm({
|
|
|
708
708
|
init_activation();
|
|
709
709
|
init_usage();
|
|
710
710
|
init_workers();
|
|
711
|
-
nonEmpty4 =
|
|
712
|
-
time2 =
|
|
713
|
-
terminalStateSchema =
|
|
711
|
+
nonEmpty4 = z8.string().min(1);
|
|
712
|
+
time2 = z8.number().int().nonnegative();
|
|
713
|
+
terminalStateSchema = z8.enum([
|
|
714
714
|
"working",
|
|
715
715
|
"idle",
|
|
716
716
|
"waiting_on_someone",
|
|
@@ -718,55 +718,55 @@ var init_machines = __esm({
|
|
|
718
718
|
"signed_out",
|
|
719
719
|
"unknown"
|
|
720
720
|
]);
|
|
721
|
-
agentStatusSchema =
|
|
722
|
-
machineRepoSchema =
|
|
721
|
+
agentStatusSchema = z8.enum(["working", "idle", "waiting_on_someone", "exited"]);
|
|
722
|
+
machineRepoSchema = z8.object({
|
|
723
723
|
name: nonEmpty4,
|
|
724
724
|
remote: nonEmpty4,
|
|
725
|
-
cloned:
|
|
725
|
+
cloned: z8.boolean().optional()
|
|
726
726
|
});
|
|
727
727
|
isCloned = (repo) => repo.cloned !== false;
|
|
728
|
-
machineCliSchema =
|
|
728
|
+
machineCliSchema = z8.object({
|
|
729
729
|
name: nonEmpty4,
|
|
730
730
|
version: nonEmpty4,
|
|
731
|
-
runnable:
|
|
732
|
-
capabilities:
|
|
731
|
+
runnable: z8.boolean().optional(),
|
|
732
|
+
capabilities: z8.array(capabilitySchema).optional(),
|
|
733
733
|
activation: agentActivationSchema.optional()
|
|
734
734
|
});
|
|
735
|
-
machineRegistrationSchema =
|
|
735
|
+
machineRegistrationSchema = z8.object({
|
|
736
736
|
id: nonEmpty4,
|
|
737
737
|
name: nonEmpty4,
|
|
738
|
-
repos:
|
|
739
|
-
clis:
|
|
738
|
+
repos: z8.array(machineRepoSchema),
|
|
739
|
+
clis: z8.array(machineCliSchema),
|
|
740
740
|
// The platform the agent actually runs on, and tools from herd's fixed list.
|
|
741
741
|
platform: platformSchema.optional(),
|
|
742
|
-
tools:
|
|
742
|
+
tools: z8.array(toolSchema).optional(),
|
|
743
743
|
// The machine's validated `herd.config.ts`, and why the file on disk didn't load if it didn't.
|
|
744
744
|
config: herdConfigSchema.optional(),
|
|
745
|
-
configError:
|
|
745
|
+
configError: z8.string().max(1e3).optional(),
|
|
746
746
|
// Whether its GitHub CLI is signed in, and as whom.
|
|
747
747
|
gh: gitHubCliSchema.optional()
|
|
748
748
|
});
|
|
749
749
|
machineSchema = machineRegistrationSchema.extend({
|
|
750
750
|
ownerId: nonEmpty4,
|
|
751
|
-
online:
|
|
751
|
+
online: z8.boolean(),
|
|
752
752
|
lastSeenAt: time2,
|
|
753
753
|
createdAt: time2
|
|
754
754
|
});
|
|
755
|
-
machinePresenceSchema =
|
|
756
|
-
worktreeSchema =
|
|
755
|
+
machinePresenceSchema = z8.object({ name: nonEmpty4, online: z8.boolean() });
|
|
756
|
+
worktreeSchema = z8.object({ repo: nonEmpty4, branch: nonEmpty4 });
|
|
757
757
|
MAX_REPO_HINTS = 10;
|
|
758
|
-
repoHintSchema =
|
|
758
|
+
repoHintSchema = z8.object({
|
|
759
759
|
remote: nonEmpty4,
|
|
760
760
|
branch: nonEmpty4.optional(),
|
|
761
761
|
folder: nonEmpty4.optional()
|
|
762
762
|
});
|
|
763
|
-
terminalSchema =
|
|
763
|
+
terminalSchema = z8.object({
|
|
764
764
|
id: nonEmpty4,
|
|
765
765
|
name: nonEmpty4,
|
|
766
766
|
machineId: nonEmpty4,
|
|
767
767
|
conversationId: nonEmpty4,
|
|
768
768
|
// The lead terminal receives the conversation's notices. Others are started with `herd run`.
|
|
769
|
-
lead:
|
|
769
|
+
lead: z8.boolean(),
|
|
770
770
|
// Only for a conversation from before folders, which works in one repo's worktree.
|
|
771
771
|
worktree: worktreeSchema.optional(),
|
|
772
772
|
// The program the screen reader recognized, such as `claude-code` or `shell`, when it knows.
|
|
@@ -774,7 +774,7 @@ var init_machines = __esm({
|
|
|
774
774
|
state: terminalStateSchema,
|
|
775
775
|
updatedAt: time2
|
|
776
776
|
});
|
|
777
|
-
offerSchema =
|
|
777
|
+
offerSchema = z8.object({
|
|
778
778
|
id: nonEmpty4,
|
|
779
779
|
conversationId: nonEmpty4,
|
|
780
780
|
machineId: nonEmpty4,
|
|
@@ -782,33 +782,33 @@ var init_machines = __esm({
|
|
|
782
782
|
expiresAt: time2,
|
|
783
783
|
// The repos the work hints, which the machine adds to the conversation's folder before the agent
|
|
784
784
|
// starts. Hints never decide which machines are offered the work.
|
|
785
|
-
repos:
|
|
785
|
+
repos: z8.array(repoHintSchema).max(MAX_REPO_HINTS).optional(),
|
|
786
786
|
// The first hint's remote, for daemons from before `repos`, which work in that one repo.
|
|
787
787
|
repo: nonEmpty4.optional(),
|
|
788
788
|
// The agent CLI of the worker it's offered to. Without one, it's Claude Code.
|
|
789
789
|
agent: nonEmpty4.optional(),
|
|
790
790
|
// A handed-off conversation restores each of its repos from its branch, if the remote has it.
|
|
791
|
-
handoff:
|
|
791
|
+
handoff: z8.boolean().optional()
|
|
792
792
|
});
|
|
793
|
-
offerAnswerSchema =
|
|
794
|
-
|
|
795
|
-
|
|
793
|
+
offerAnswerSchema = z8.discriminatedUnion("answer", [
|
|
794
|
+
z8.object({ answer: z8.literal("accept") }),
|
|
795
|
+
z8.object({ answer: z8.literal("refuse"), reason: nonEmpty4 })
|
|
796
796
|
]);
|
|
797
|
-
dispatchFrameSchema =
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
type:
|
|
797
|
+
dispatchFrameSchema = z8.discriminatedUnion("type", [
|
|
798
|
+
z8.object({ type: z8.literal("offer"), offer: offerSchema }),
|
|
799
|
+
z8.object({
|
|
800
|
+
type: z8.literal("message"),
|
|
801
801
|
conversationId: nonEmpty4,
|
|
802
|
-
delivery:
|
|
802
|
+
delivery: z8.enum(["interrupt", "defer"])
|
|
803
803
|
}),
|
|
804
|
-
|
|
804
|
+
z8.object({ type: z8.literal("reconnect") }),
|
|
805
805
|
// Its owner asked for a sign-in on this machine, which the daemon runs and reports on.
|
|
806
|
-
|
|
806
|
+
z8.object({ type: z8.literal("sign_in"), signInId: nonEmpty4, tool: signInToolSchema })
|
|
807
807
|
]);
|
|
808
|
-
machineMessageSchema =
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
type:
|
|
808
|
+
machineMessageSchema = z8.discriminatedUnion("type", [
|
|
809
|
+
z8.object({ type: z8.literal("ack"), conversationId: nonEmpty4 }),
|
|
810
|
+
z8.object({
|
|
811
|
+
type: z8.literal("usage"),
|
|
812
812
|
/** The worker's agent on this machine, such as `claude-code`. */
|
|
813
813
|
agent: nonEmpty4,
|
|
814
814
|
usage: usageSchema,
|
|
@@ -819,39 +819,39 @@ var init_machines = __esm({
|
|
|
819
819
|
});
|
|
820
820
|
|
|
821
821
|
// ../common-chat/src/prompts.ts
|
|
822
|
-
import { z as
|
|
822
|
+
import { z as z9 } from "zod";
|
|
823
823
|
var nonEmpty5, id, promptKindSchema, promptOptionSchema, promptQuestionSchema, promptRequestSchema, promptOutcomeSchema;
|
|
824
824
|
var init_prompts = __esm({
|
|
825
825
|
"../common-chat/src/prompts.ts"() {
|
|
826
826
|
"use strict";
|
|
827
827
|
init_define_HERD_PACKAGE();
|
|
828
|
-
nonEmpty5 =
|
|
829
|
-
id =
|
|
830
|
-
promptKindSchema =
|
|
831
|
-
promptOptionSchema =
|
|
828
|
+
nonEmpty5 = z9.string().min(1);
|
|
829
|
+
id = z9.string().regex(/^[A-Za-z0-9_-]{1,40}$/).describe("Short, so it fits in a button's value and action ID");
|
|
830
|
+
promptKindSchema = z9.enum(["permission", "question", "plan", "automation"]);
|
|
831
|
+
promptOptionSchema = z9.object({
|
|
832
832
|
id,
|
|
833
|
-
label:
|
|
834
|
-
description:
|
|
833
|
+
label: z9.string().trim().min(1).max(75),
|
|
834
|
+
description: z9.string().max(200).optional(),
|
|
835
835
|
// How a button for it is drawn: `primary` to go ahead, `danger` to refuse.
|
|
836
|
-
style:
|
|
836
|
+
style: z9.enum(["primary", "danger"]).optional()
|
|
837
837
|
});
|
|
838
|
-
promptQuestionSchema =
|
|
838
|
+
promptQuestionSchema = z9.object({
|
|
839
839
|
id,
|
|
840
|
-
text:
|
|
841
|
-
options:
|
|
840
|
+
text: z9.string().trim().min(1).max(300),
|
|
841
|
+
options: z9.array(promptOptionSchema).min(1).max(10)
|
|
842
842
|
});
|
|
843
|
-
promptRequestSchema =
|
|
843
|
+
promptRequestSchema = z9.object({
|
|
844
844
|
kind: promptKindSchema,
|
|
845
|
-
title:
|
|
846
|
-
detail:
|
|
847
|
-
questions:
|
|
845
|
+
title: z9.string().trim().min(1).max(150),
|
|
846
|
+
detail: z9.string().max(2800).optional(),
|
|
847
|
+
questions: z9.array(promptQuestionSchema).min(1).max(4)
|
|
848
848
|
});
|
|
849
|
-
promptOutcomeSchema =
|
|
849
|
+
promptOutcomeSchema = z9.enum(["answered", "cancelled"]);
|
|
850
850
|
}
|
|
851
851
|
});
|
|
852
852
|
|
|
853
853
|
// ../common-chat/src/pull-requests.ts
|
|
854
|
-
import { z as
|
|
854
|
+
import { z as z10 } from "zod";
|
|
855
855
|
function statusOfPhase(phase) {
|
|
856
856
|
return phase === "merged" ? "done" : phase === "closed" ? "closed" : "open";
|
|
857
857
|
}
|
|
@@ -890,8 +890,8 @@ var init_pull_requests = __esm({
|
|
|
890
890
|
"../common-chat/src/pull-requests.ts"() {
|
|
891
891
|
"use strict";
|
|
892
892
|
init_define_HERD_PACKAGE();
|
|
893
|
-
time3 =
|
|
894
|
-
pullRequestPhaseSchema =
|
|
893
|
+
time3 = z10.number().int().nonnegative();
|
|
894
|
+
pullRequestPhaseSchema = z10.enum([
|
|
895
895
|
"draft",
|
|
896
896
|
"checks_running",
|
|
897
897
|
"checks_failed",
|
|
@@ -902,7 +902,7 @@ var init_pull_requests = __esm({
|
|
|
902
902
|
"merged",
|
|
903
903
|
"closed"
|
|
904
904
|
]);
|
|
905
|
-
pullRequestMoveSchema =
|
|
905
|
+
pullRequestMoveSchema = z10.enum(["you", "agent", "others", "nobody"]);
|
|
906
906
|
PHASE_LABELS = {
|
|
907
907
|
draft: "draft",
|
|
908
908
|
checks_running: "checks running",
|
|
@@ -914,22 +914,22 @@ var init_pull_requests = __esm({
|
|
|
914
914
|
merged: "merged",
|
|
915
915
|
closed: "closed"
|
|
916
916
|
};
|
|
917
|
-
leadChangeSchema =
|
|
917
|
+
leadChangeSchema = z10.object({
|
|
918
918
|
/** Its repo and number, such as `api#104`, or "a pull request" when hidden. */
|
|
919
|
-
label:
|
|
919
|
+
label: z10.string().min(1),
|
|
920
920
|
phase: pullRequestPhaseSchema,
|
|
921
921
|
move: pullRequestMoveSchema,
|
|
922
922
|
changedAt: time3,
|
|
923
923
|
/** How many of the conversation's other open pull requests are also the person's move. */
|
|
924
|
-
moreForYou:
|
|
924
|
+
moreForYou: z10.number().int().nonnegative(),
|
|
925
925
|
/** Absent when hidden. */
|
|
926
|
-
url:
|
|
926
|
+
url: z10.string().optional()
|
|
927
927
|
});
|
|
928
928
|
}
|
|
929
929
|
});
|
|
930
930
|
|
|
931
931
|
// ../common-chat/src/work-objects.ts
|
|
932
|
-
import { z as
|
|
932
|
+
import { z as z11 } from "zod";
|
|
933
933
|
function workLine(work) {
|
|
934
934
|
const parts = [
|
|
935
935
|
work.phase ? `${work.kind} ${PHASE_LABELS[work.phase]}` : `${work.kind} ${work.status}`
|
|
@@ -944,21 +944,21 @@ var init_work_objects = __esm({
|
|
|
944
944
|
"use strict";
|
|
945
945
|
init_define_HERD_PACKAGE();
|
|
946
946
|
init_pull_requests();
|
|
947
|
-
time4 =
|
|
948
|
-
workKindSchema =
|
|
949
|
-
workStatusSchema =
|
|
950
|
-
workSourceSchema =
|
|
947
|
+
time4 = z11.number().int().nonnegative();
|
|
948
|
+
workKindSchema = z11.enum(["change", "ticket", "deploy", "document", "other"]);
|
|
949
|
+
workStatusSchema = z11.enum(["open", "done", "closed"]);
|
|
950
|
+
workSourceSchema = z11.enum(["agent", "provider"]);
|
|
951
951
|
MAX_WORK_TITLE = 200;
|
|
952
952
|
MAX_WORK_DETAIL = 100;
|
|
953
953
|
MAX_WORK_URL = 2048;
|
|
954
|
-
workObjectSchema =
|
|
955
|
-
url:
|
|
954
|
+
workObjectSchema = z11.object({
|
|
955
|
+
url: z11.string().min(1).max(MAX_WORK_URL),
|
|
956
956
|
kind: workKindSchema,
|
|
957
|
-
title:
|
|
957
|
+
title: z11.string().min(1).max(MAX_WORK_TITLE),
|
|
958
958
|
status: workStatusSchema,
|
|
959
|
-
detail:
|
|
959
|
+
detail: z11.string().max(MAX_WORK_DETAIL).nullable(),
|
|
960
960
|
/** Whether the conversation made it, rather than only being about it. */
|
|
961
|
-
made:
|
|
961
|
+
made: z11.boolean(),
|
|
962
962
|
changedAt: time4,
|
|
963
963
|
changedBy: workSourceSchema,
|
|
964
964
|
createdAt: time4,
|
|
@@ -966,21 +966,21 @@ var init_work_objects = __esm({
|
|
|
966
966
|
phase: pullRequestPhaseSchema.nullable().optional(),
|
|
967
967
|
move: pullRequestMoveSchema.nullable().optional(),
|
|
968
968
|
/** The delegate holding it, when it's read from an ancestor. */
|
|
969
|
-
conversationId:
|
|
969
|
+
conversationId: z11.string().min(1).optional()
|
|
970
970
|
});
|
|
971
|
-
workChangeSchema =
|
|
972
|
-
url:
|
|
971
|
+
workChangeSchema = z11.object({
|
|
972
|
+
url: z11.string().trim().min(1).max(MAX_WORK_URL),
|
|
973
973
|
kind: workKindSchema.optional(),
|
|
974
|
-
title:
|
|
974
|
+
title: z11.string().trim().min(1).max(2e3).optional(),
|
|
975
975
|
status: workStatusSchema.optional(),
|
|
976
|
-
detail:
|
|
977
|
-
made:
|
|
976
|
+
detail: z11.string().trim().max(2e3).nullable().optional(),
|
|
977
|
+
made: z11.boolean().optional(),
|
|
978
978
|
/** Only for a `change`. Its status then follows it. */
|
|
979
979
|
phase: pullRequestPhaseSchema.optional(),
|
|
980
980
|
/** Set by a provider, which knows who was asked to review. Otherwise it follows the phase. */
|
|
981
981
|
move: pullRequestMoveSchema.optional()
|
|
982
982
|
});
|
|
983
|
-
workFieldSchema =
|
|
983
|
+
workFieldSchema = z11.enum([
|
|
984
984
|
"kind",
|
|
985
985
|
"title",
|
|
986
986
|
"status",
|
|
@@ -989,27 +989,27 @@ var init_work_objects = __esm({
|
|
|
989
989
|
"phase",
|
|
990
990
|
"move"
|
|
991
991
|
]);
|
|
992
|
-
workObjectSummarySchema =
|
|
992
|
+
workObjectSummarySchema = z11.object({
|
|
993
993
|
kind: workKindSchema,
|
|
994
994
|
status: workStatusSchema,
|
|
995
|
-
made:
|
|
995
|
+
made: z11.boolean(),
|
|
996
996
|
changedAt: time4,
|
|
997
997
|
/** A pull request's phase and move, which say nothing of its content, so they're never hidden. */
|
|
998
998
|
phase: pullRequestPhaseSchema.nullable().optional(),
|
|
999
999
|
move: pullRequestMoveSchema.nullable().optional(),
|
|
1000
|
-
url:
|
|
1001
|
-
title:
|
|
1002
|
-
detail:
|
|
1000
|
+
url: z11.string().optional(),
|
|
1001
|
+
title: z11.string().optional(),
|
|
1002
|
+
detail: z11.string().nullable().optional(),
|
|
1003
1003
|
/** The delegate holding it, when it isn't the item's own conversation. */
|
|
1004
|
-
conversationId:
|
|
1004
|
+
conversationId: z11.string().min(1).optional()
|
|
1005
1005
|
});
|
|
1006
1006
|
}
|
|
1007
1007
|
});
|
|
1008
1008
|
|
|
1009
1009
|
// ../common-chat/src/events.ts
|
|
1010
|
-
import { z as
|
|
1010
|
+
import { z as z12 } from "zod";
|
|
1011
1011
|
function event(type, payload) {
|
|
1012
|
-
return
|
|
1012
|
+
return z12.object({ ...eventBase, type: z12.literal(type), payload: z12.object(payload) });
|
|
1013
1013
|
}
|
|
1014
1014
|
var routeSchema, deliveryModeSchema, eventSourceSchema, nonEmpty6, actorSchema, eventBase, entryIds, routingRecordSchema, conversationEventSchema, conversationVisibilitySchema, conversationStatusSchema, conversationSummarySchema, placementSchema, treeSummarySchema, conversationSnapshotSchema, liveFrameSchema, adapterCapabilitiesSchema;
|
|
1015
1015
|
var init_events = __esm({
|
|
@@ -1023,129 +1023,129 @@ var init_events = __esm({
|
|
|
1023
1023
|
init_usage();
|
|
1024
1024
|
init_work_objects();
|
|
1025
1025
|
init_workers();
|
|
1026
|
-
routeSchema =
|
|
1027
|
-
deliveryModeSchema =
|
|
1028
|
-
eventSourceSchema =
|
|
1029
|
-
nonEmpty6 =
|
|
1030
|
-
actorSchema =
|
|
1026
|
+
routeSchema = z12.enum(["direct", "mention", "joined"]);
|
|
1027
|
+
deliveryModeSchema = z12.enum(["interrupt", "defer"]);
|
|
1028
|
+
eventSourceSchema = z12.enum(["slack", "discord", "web", "api", "cli", "mcp", "system"]);
|
|
1029
|
+
nonEmpty6 = z12.string().min(1);
|
|
1030
|
+
actorSchema = z12.discriminatedUnion("kind", [
|
|
1031
1031
|
// Someone signed in to this system. `id` is the stable person identifier.
|
|
1032
|
-
|
|
1032
|
+
z12.object({ kind: z12.literal("person"), id: nonEmpty6, name: nonEmpty6 }),
|
|
1033
1033
|
// An account on a platform, which may or may not be linked to a person.
|
|
1034
|
-
|
|
1035
|
-
kind:
|
|
1034
|
+
z12.object({
|
|
1035
|
+
kind: z12.literal("account"),
|
|
1036
1036
|
provider: nonEmpty6,
|
|
1037
1037
|
tenant: nonEmpty6,
|
|
1038
1038
|
subject: nonEmpty6,
|
|
1039
|
-
name:
|
|
1040
|
-
isBot:
|
|
1039
|
+
name: z12.string().optional(),
|
|
1040
|
+
isBot: z12.boolean()
|
|
1041
1041
|
}),
|
|
1042
|
-
|
|
1042
|
+
z12.object({ kind: z12.literal("system") })
|
|
1043
1043
|
]);
|
|
1044
1044
|
eventBase = {
|
|
1045
|
-
seq:
|
|
1045
|
+
seq: z12.number().int().positive(),
|
|
1046
1046
|
source: eventSourceSchema,
|
|
1047
1047
|
actor: actorSchema,
|
|
1048
|
-
createdAt:
|
|
1048
|
+
createdAt: z12.number().int().nonnegative()
|
|
1049
1049
|
};
|
|
1050
|
-
entryIds =
|
|
1051
|
-
routingRecordSchema =
|
|
1052
|
-
eligible:
|
|
1053
|
-
questions:
|
|
1054
|
-
|
|
1050
|
+
entryIds = z12.array(nonEmpty6);
|
|
1051
|
+
routingRecordSchema = z12.object({
|
|
1052
|
+
eligible: z12.array(z12.object({ key: nonEmpty6, name: nonEmpty6 })),
|
|
1053
|
+
questions: z12.array(
|
|
1054
|
+
z12.object({
|
|
1055
1055
|
id: nonEmpty6,
|
|
1056
1056
|
question: nonEmpty6,
|
|
1057
|
-
probability:
|
|
1057
|
+
probability: z12.number().min(0).max(1).nullable()
|
|
1058
1058
|
})
|
|
1059
1059
|
),
|
|
1060
1060
|
model: nonEmpty6.optional(),
|
|
1061
1061
|
// Why the model's answers weren't used, when they weren't.
|
|
1062
|
-
fallback:
|
|
1063
|
-
removed:
|
|
1064
|
-
order:
|
|
1062
|
+
fallback: z12.string().optional(),
|
|
1063
|
+
removed: z12.array(z12.object({ key: nonEmpty6, name: nonEmpty6, rule: nonEmpty6 })),
|
|
1064
|
+
order: z12.array(nonEmpty6),
|
|
1065
1065
|
// Each ordered worker's fit, and the profile statement and level that gave it, when the model
|
|
1066
1066
|
// answered.
|
|
1067
|
-
fits:
|
|
1068
|
-
|
|
1067
|
+
fits: z12.array(
|
|
1068
|
+
z12.object({
|
|
1069
1069
|
key: nonEmpty6,
|
|
1070
|
-
fit:
|
|
1071
|
-
statement:
|
|
1072
|
-
level:
|
|
1070
|
+
fit: z12.number().min(0).max(1),
|
|
1071
|
+
statement: z12.string().optional(),
|
|
1072
|
+
level: z12.enum(["great", "good", "okay"]).optional()
|
|
1073
1073
|
})
|
|
1074
1074
|
).optional(),
|
|
1075
1075
|
// Profile statements left out to keep within the most questions one call asks.
|
|
1076
|
-
dropped:
|
|
1076
|
+
dropped: z12.array(z12.string()).optional(),
|
|
1077
1077
|
// The repos the work hinted, and the workers whose machine had cloned every one, which go first
|
|
1078
1078
|
// among workers that tie on fit and priority.
|
|
1079
|
-
hints:
|
|
1080
|
-
warm:
|
|
1079
|
+
hints: z12.array(nonEmpty6).optional(),
|
|
1080
|
+
warm: z12.array(nonEmpty6).optional(),
|
|
1081
1081
|
// Each ordered worker's share, how its weekly usage is pacing, and the weight that gives it. The
|
|
1082
1082
|
// first worker was drawn by weight from those in `drawn`, which suited the work equally.
|
|
1083
|
-
shares:
|
|
1084
|
-
|
|
1083
|
+
shares: z12.array(
|
|
1084
|
+
z12.object({
|
|
1085
1085
|
key: nonEmpty6,
|
|
1086
1086
|
share: shareSchema,
|
|
1087
|
-
pacing:
|
|
1088
|
-
weight:
|
|
1087
|
+
pacing: z12.enum(["ahead", "even", "under", "unknown"]),
|
|
1088
|
+
weight: z12.number().nonnegative()
|
|
1089
1089
|
})
|
|
1090
1090
|
).optional(),
|
|
1091
|
-
drawn:
|
|
1091
|
+
drawn: z12.array(nonEmpty6).optional()
|
|
1092
1092
|
});
|
|
1093
|
-
conversationEventSchema =
|
|
1093
|
+
conversationEventSchema = z12.discriminatedUnion("type", [
|
|
1094
1094
|
event("message.created", {
|
|
1095
1095
|
messageId: nonEmpty6,
|
|
1096
|
-
text:
|
|
1097
|
-
direction:
|
|
1096
|
+
text: z12.string(),
|
|
1097
|
+
direction: z12.enum(["inbound", "outbound"]),
|
|
1098
1098
|
route: routeSchema.optional(),
|
|
1099
1099
|
// Why the message did or didn't wake the conversation.
|
|
1100
|
-
reason:
|
|
1100
|
+
reason: z12.string().optional(),
|
|
1101
1101
|
// Loaded from before the conversation joined the thread, so it never waits for a response.
|
|
1102
|
-
isContext:
|
|
1102
|
+
isContext: z12.boolean().optional(),
|
|
1103
1103
|
// Set when the message was deleted on its platform. `text` is then empty.
|
|
1104
|
-
deleted:
|
|
1104
|
+
deleted: z12.boolean().optional(),
|
|
1105
1105
|
// Sent through the API but kept out of the platform, so only clients see it.
|
|
1106
|
-
quiet:
|
|
1106
|
+
quiet: z12.boolean().optional(),
|
|
1107
1107
|
// The client an agent sent it through, such as "Claude Code". Such a message is the agent's.
|
|
1108
|
-
client:
|
|
1108
|
+
client: z12.string().optional(),
|
|
1109
1109
|
// How to read `text`. Absent means plain text, as every message before this field was.
|
|
1110
|
-
format:
|
|
1110
|
+
format: z12.enum(["markdown"]).optional(),
|
|
1111
1111
|
// Files attached to it, kept with the conversation.
|
|
1112
|
-
files:
|
|
1112
|
+
files: z12.array(messageFileSchema).optional(),
|
|
1113
1113
|
// A platform's own layout, shown there in place of `text`. Every other surface shows `text`.
|
|
1114
|
-
layout:
|
|
1114
|
+
layout: z12.object({ platform: layoutPlatformSchema, blocks: z12.array(z12.unknown()) }).optional(),
|
|
1115
1115
|
// Set when this was posted in another channel, starting the conversation named here.
|
|
1116
1116
|
post: postTargetSchema.optional(),
|
|
1117
1117
|
// Set on a channel post's own conversation: the conversation that posted it. Its ID is left
|
|
1118
1118
|
// out for anyone who can't read that conversation.
|
|
1119
|
-
origin:
|
|
1119
|
+
origin: z12.object({ conversationId: nonEmpty6.optional() }).optional(),
|
|
1120
1120
|
// Set on Friday's one notice that a firing with no thread can't run yet, saying why.
|
|
1121
1121
|
threadNotice: nonEmpty6.optional(),
|
|
1122
1122
|
// Set when this reply answered an open prompt, so it never waits as a message of its own.
|
|
1123
1123
|
answersPrompt: nonEmpty6.optional(),
|
|
1124
1124
|
// Set on a child conversation's first message: the brief its parent's agent wrote, from the
|
|
1125
1125
|
// principal's own account. `by` is the parent's worker.
|
|
1126
|
-
delegation:
|
|
1126
|
+
delegation: z12.object({ parent: nonEmpty6, by: nonEmpty6 }).optional(),
|
|
1127
1127
|
// Set on a message from another of the principal's conversations' agents, which is that agent's
|
|
1128
1128
|
// words, not a person's. `posted` means a delegate already posted it in the thread, and
|
|
1129
1129
|
// `outsideTree` that the sender isn't in this conversation's tree.
|
|
1130
|
-
agentMessage:
|
|
1130
|
+
agentMessage: z12.object({
|
|
1131
1131
|
from: nonEmpty6,
|
|
1132
1132
|
worker: nonEmpty6,
|
|
1133
|
-
posted:
|
|
1134
|
-
overdue:
|
|
1133
|
+
posted: z12.boolean().optional(),
|
|
1134
|
+
overdue: z12.boolean().optional(),
|
|
1135
1135
|
// herd's own note about the delegate, such as that it's waiting for its worker.
|
|
1136
|
-
notice:
|
|
1137
|
-
outsideTree:
|
|
1136
|
+
notice: z12.boolean().optional(),
|
|
1137
|
+
outsideTree: z12.boolean().optional()
|
|
1138
1138
|
}).optional(),
|
|
1139
1139
|
// Set on a message a root posted for one of its children, which is labelled as the child's.
|
|
1140
|
-
forChild:
|
|
1140
|
+
forChild: z12.object({ id: nonEmpty6, worker: nonEmpty6, for: nonEmpty6 }).optional(),
|
|
1141
1141
|
// Set on an automation's firing, whose `text` is the owner's instructions, and on the opening
|
|
1142
1142
|
// post that starts a conversation for one. `payload` is what the trigger brought: untrusted.
|
|
1143
|
-
automation:
|
|
1143
|
+
automation: z12.object({
|
|
1144
1144
|
id: nonEmpty6,
|
|
1145
1145
|
name: nonEmpty6,
|
|
1146
1146
|
reason: nonEmpty6,
|
|
1147
1147
|
key: nonEmpty6,
|
|
1148
|
-
payload:
|
|
1148
|
+
payload: z12.string().optional(),
|
|
1149
1149
|
// The opening post a firing's reactions are shown on, in a conversation it started.
|
|
1150
1150
|
opener: nonEmpty6.optional()
|
|
1151
1151
|
}).optional(),
|
|
@@ -1153,27 +1153,27 @@ var init_events = __esm({
|
|
|
1153
1153
|
// follows. `text` is a short line about it, and anyone's words in it are untrusted.
|
|
1154
1154
|
github: githubEventSummarySchema.optional()
|
|
1155
1155
|
}),
|
|
1156
|
-
event("message.updated", { messageId: nonEmpty6, text:
|
|
1156
|
+
event("message.updated", { messageId: nonEmpty6, text: z12.string() }),
|
|
1157
1157
|
// A decision model judged whether a reply in a joined thread was meant for the bot. `for_bot`
|
|
1158
1158
|
// woke the conversation. `failed` means it couldn't be decided in time, so nothing woke.
|
|
1159
1159
|
event("message.decided", {
|
|
1160
1160
|
messageId: nonEmpty6,
|
|
1161
|
-
messageSeq:
|
|
1162
|
-
outcome:
|
|
1163
|
-
probability:
|
|
1161
|
+
messageSeq: z12.number().int().positive(),
|
|
1162
|
+
outcome: z12.enum(["for_bot", "not_for_bot", "failed"]),
|
|
1163
|
+
probability: z12.number().min(0).max(1).optional(),
|
|
1164
1164
|
model: nonEmpty6,
|
|
1165
|
-
error:
|
|
1165
|
+
error: z12.string().optional()
|
|
1166
1166
|
}),
|
|
1167
1167
|
// A decision model judged whether the bot's last message of a turn asks a person to answer,
|
|
1168
1168
|
// decide, provide or confirm something before it can carry on. `asks` keeps the conversation
|
|
1169
1169
|
// waiting on them. `failed` means it couldn't be judged in time, so nothing changed.
|
|
1170
1170
|
event("message.asked", {
|
|
1171
1171
|
messageId: nonEmpty6,
|
|
1172
|
-
messageSeq:
|
|
1173
|
-
outcome:
|
|
1174
|
-
probability:
|
|
1172
|
+
messageSeq: z12.number().int().positive(),
|
|
1173
|
+
outcome: z12.enum(["asks", "doesnt_ask", "failed"]),
|
|
1174
|
+
probability: z12.number().min(0).max(1).optional(),
|
|
1175
1175
|
model: nonEmpty6,
|
|
1176
|
-
error:
|
|
1176
|
+
error: z12.string().optional()
|
|
1177
1177
|
}),
|
|
1178
1178
|
// One of an incoming message's files arrived, or couldn't. `file` replaces the one with its ID.
|
|
1179
1179
|
event("message.file_changed", { messageId: nonEmpty6, file: messageFileSchema }),
|
|
@@ -1185,21 +1185,21 @@ var init_events = __esm({
|
|
|
1185
1185
|
event("context.unavailable", { reason: nonEmpty6 }),
|
|
1186
1186
|
event("mailbox.queued", {
|
|
1187
1187
|
entryId: nonEmpty6,
|
|
1188
|
-
messageSeq:
|
|
1188
|
+
messageSeq: z12.number().int().positive(),
|
|
1189
1189
|
delivery: deliveryModeSchema
|
|
1190
1190
|
}),
|
|
1191
1191
|
event("mailbox.claimed", {
|
|
1192
1192
|
claimId: nonEmpty6,
|
|
1193
1193
|
entryIds,
|
|
1194
1194
|
holder: nonEmpty6,
|
|
1195
|
-
expiresAt:
|
|
1195
|
+
expiresAt: z12.number().int()
|
|
1196
1196
|
}),
|
|
1197
|
-
event("mailbox.renewed", { claimId: nonEmpty6, expiresAt:
|
|
1197
|
+
event("mailbox.renewed", { claimId: nonEmpty6, expiresAt: z12.number().int() }),
|
|
1198
1198
|
event("mailbox.released", {
|
|
1199
1199
|
claimId: nonEmpty6,
|
|
1200
1200
|
entryIds,
|
|
1201
1201
|
// `delegates` means messages held for delegates are waiting again now that they've settled.
|
|
1202
|
-
reason:
|
|
1202
|
+
reason: z12.enum(["released", "expired", "delegates"])
|
|
1203
1203
|
}),
|
|
1204
1204
|
// A turn ended with delegates still open, so the messages it worked on wait for them, still ⏳.
|
|
1205
1205
|
event("mailbox.held", { claimId: nonEmpty6, entryIds }),
|
|
@@ -1207,7 +1207,7 @@ var init_events = __esm({
|
|
|
1207
1207
|
event("mailbox.completed", {
|
|
1208
1208
|
entryIds,
|
|
1209
1209
|
claimId: nonEmpty6.optional(),
|
|
1210
|
-
outcome:
|
|
1210
|
+
outcome: z12.enum(["passed"]).optional()
|
|
1211
1211
|
}),
|
|
1212
1212
|
event("mailbox.cancelled", { entryIds, reason: nonEmpty6 }),
|
|
1213
1213
|
// A person asked for what's waiting to be delivered again. The entries stay waiting.
|
|
@@ -1224,15 +1224,15 @@ var init_events = __esm({
|
|
|
1224
1224
|
// The message it was delivering, when it was one of the conversation's own messages.
|
|
1225
1225
|
messageId: nonEmpty6.optional(),
|
|
1226
1226
|
// For `kind: "files"`, which of that message's files didn't arrive.
|
|
1227
|
-
fileIds:
|
|
1227
|
+
fileIds: z12.array(nonEmpty6).optional()
|
|
1228
1228
|
}),
|
|
1229
1229
|
event("status.changed", { status: agentStatusSchema }),
|
|
1230
1230
|
// A work object was added or changed: the whole of it as it now stands, which fields changed, and
|
|
1231
1231
|
// whether the agent or a provider changed them. Recording one never wakes the conversation.
|
|
1232
1232
|
event("work.recorded", {
|
|
1233
1233
|
work: workObjectSchema.omit({ conversationId: true }),
|
|
1234
|
-
changed:
|
|
1235
|
-
added:
|
|
1234
|
+
changed: z12.array(workFieldSchema),
|
|
1235
|
+
added: z12.boolean(),
|
|
1236
1236
|
by: workSourceSchema
|
|
1237
1237
|
}),
|
|
1238
1238
|
event("work.removed", { url: nonEmpty6, by: workSourceSchema }),
|
|
@@ -1245,7 +1245,7 @@ var init_events = __esm({
|
|
|
1245
1245
|
event("prompt.opened", {
|
|
1246
1246
|
promptId: nonEmpty6,
|
|
1247
1247
|
...promptRequestSchema.shape,
|
|
1248
|
-
forChild:
|
|
1248
|
+
forChild: z12.object({ id: nonEmpty6, worker: nonEmpty6, promptId: nonEmpty6 }).optional()
|
|
1249
1249
|
}),
|
|
1250
1250
|
// A reply in the thread answers with its `messageId`, and with `text` when it was taken as the
|
|
1251
1251
|
// answer in its own words rather than as naming an option.
|
|
@@ -1254,12 +1254,12 @@ var init_events = __esm({
|
|
|
1254
1254
|
questionId: nonEmpty6,
|
|
1255
1255
|
optionId: nonEmpty6.optional(),
|
|
1256
1256
|
messageId: nonEmpty6.optional(),
|
|
1257
|
-
text:
|
|
1257
|
+
text: z12.string().optional()
|
|
1258
1258
|
}),
|
|
1259
1259
|
event("prompt.closed", {
|
|
1260
1260
|
promptId: nonEmpty6,
|
|
1261
1261
|
outcome: promptOutcomeSchema,
|
|
1262
|
-
reason:
|
|
1262
|
+
reason: z12.string().optional()
|
|
1263
1263
|
}),
|
|
1264
1264
|
// Dispatch: which machine the conversation was offered to, and which one holds it.
|
|
1265
1265
|
event("dispatch.offered", {
|
|
@@ -1283,19 +1283,19 @@ var init_events = __esm({
|
|
|
1283
1283
|
// An agent started a child conversation on another worker, and how the child has gone since.
|
|
1284
1284
|
event("delegation.started", {
|
|
1285
1285
|
childId: nonEmpty6,
|
|
1286
|
-
workers:
|
|
1287
|
-
routed:
|
|
1286
|
+
workers: z12.array(nonEmpty6),
|
|
1287
|
+
routed: z12.boolean()
|
|
1288
1288
|
}),
|
|
1289
1289
|
event("delegation.settled", { childId: nonEmpty6 }),
|
|
1290
1290
|
event("delegation.overdue", { childId: nonEmpty6 }),
|
|
1291
|
-
event("delegation.waiting", { childId: nonEmpty6, waiting:
|
|
1291
|
+
event("delegation.waiting", { childId: nonEmpty6, waiting: z12.boolean() }),
|
|
1292
1292
|
// An agent asked for its conversation to move to another worker once its turn ends.
|
|
1293
1293
|
event("dispatch.handoff_requested", { workerKey: nonEmpty6, workerName: nonEmpty6 }),
|
|
1294
1294
|
// Terminals on the bound machine. Their output never enters the history, only these facts.
|
|
1295
1295
|
event("terminal.opened", {
|
|
1296
1296
|
terminalId: nonEmpty6,
|
|
1297
1297
|
machineId: nonEmpty6,
|
|
1298
|
-
lead:
|
|
1298
|
+
lead: z12.boolean(),
|
|
1299
1299
|
// Only for a conversation from before folders, which works in one repo's worktree.
|
|
1300
1300
|
worktree: worktreeSchema.optional()
|
|
1301
1301
|
}),
|
|
@@ -1307,9 +1307,9 @@ var init_events = __esm({
|
|
|
1307
1307
|
folder: nonEmpty6,
|
|
1308
1308
|
branch: nonEmpty6,
|
|
1309
1309
|
base: nonEmpty6.optional(),
|
|
1310
|
-
fetchFailed:
|
|
1310
|
+
fetchFailed: z12.string().max(1e3).optional()
|
|
1311
1311
|
}),
|
|
1312
|
-
event("terminal.exited", { terminalId: nonEmpty6, exitCode:
|
|
1312
|
+
event("terminal.exited", { terminalId: nonEmpty6, exitCode: z12.number().int().nullable() }),
|
|
1313
1313
|
event("terminal.notice_failed", { terminalId: nonEmpty6, reason: nonEmpty6 }),
|
|
1314
1314
|
/** The daemon closed one of Claude Code's own dialogs that it has recorded, named by its title. */
|
|
1315
1315
|
event("terminal.dialog_closed", { terminalId: nonEmpty6, dialog: nonEmpty6 }),
|
|
@@ -1319,7 +1319,7 @@ var init_events = __esm({
|
|
|
1319
1319
|
event("subscription.created", {
|
|
1320
1320
|
resource: nonEmpty6,
|
|
1321
1321
|
label: nonEmpty6,
|
|
1322
|
-
url:
|
|
1322
|
+
url: z12.url(),
|
|
1323
1323
|
subscriber: nonEmpty6,
|
|
1324
1324
|
createdBy: subscriptionOriginSchema
|
|
1325
1325
|
}),
|
|
@@ -1331,72 +1331,72 @@ var init_events = __esm({
|
|
|
1331
1331
|
// A subscription reached its hourly limit of wakes, noted once each hour.
|
|
1332
1332
|
event("subscription.limited", { resource: nonEmpty6 })
|
|
1333
1333
|
]);
|
|
1334
|
-
conversationVisibilitySchema =
|
|
1335
|
-
conversationStatusSchema =
|
|
1336
|
-
conversationSummarySchema =
|
|
1334
|
+
conversationVisibilitySchema = z12.enum(["public", "private"]);
|
|
1335
|
+
conversationStatusSchema = z12.enum(["idle", "waiting", "working"]);
|
|
1336
|
+
conversationSummarySchema = z12.object({
|
|
1337
1337
|
id: nonEmpty6,
|
|
1338
1338
|
provider: nonEmpty6,
|
|
1339
1339
|
visibility: conversationVisibilitySchema,
|
|
1340
1340
|
title: nonEmpty6,
|
|
1341
1341
|
// Where the conversation lives on its platform, when it has a link.
|
|
1342
|
-
placeUrl:
|
|
1342
|
+
placeUrl: z12.string().nullable(),
|
|
1343
1343
|
status: conversationStatusSchema,
|
|
1344
|
-
waitingCount:
|
|
1345
|
-
createdAt:
|
|
1346
|
-
lastActivityAt:
|
|
1347
|
-
expiresAt:
|
|
1344
|
+
waitingCount: z12.number().int().nonnegative(),
|
|
1345
|
+
createdAt: z12.number().int(),
|
|
1346
|
+
lastActivityAt: z12.number().int(),
|
|
1347
|
+
expiresAt: z12.number().int()
|
|
1348
1348
|
});
|
|
1349
|
-
placementSchema =
|
|
1350
|
-
|
|
1351
|
-
kind:
|
|
1352
|
-
machine:
|
|
1349
|
+
placementSchema = z12.discriminatedUnion("kind", [
|
|
1350
|
+
z12.object({
|
|
1351
|
+
kind: z12.literal("bound"),
|
|
1352
|
+
machine: z12.object({ name: nonEmpty6, online: z12.boolean() }),
|
|
1353
1353
|
// The worker's name, such as `mac-mini/claude`, and never its configuration or capabilities.
|
|
1354
1354
|
worker: nonEmpty6.optional()
|
|
1355
1355
|
}),
|
|
1356
|
-
|
|
1357
|
-
|
|
1356
|
+
z12.object({ kind: z12.literal("waiting_for_machine") }),
|
|
1357
|
+
z12.object({ kind: z12.literal("author_not_linked") })
|
|
1358
1358
|
]);
|
|
1359
|
-
treeSummarySchema =
|
|
1359
|
+
treeSummarySchema = z12.object({
|
|
1360
1360
|
parent: nonEmpty6.nullable(),
|
|
1361
1361
|
root: nonEmpty6,
|
|
1362
|
-
children:
|
|
1363
|
-
|
|
1362
|
+
children: z12.array(
|
|
1363
|
+
z12.object({
|
|
1364
1364
|
id: nonEmpty6,
|
|
1365
1365
|
title: nonEmpty6,
|
|
1366
|
-
state:
|
|
1367
|
-
createdAt:
|
|
1366
|
+
state: z12.string().nullable(),
|
|
1367
|
+
createdAt: z12.number()
|
|
1368
1368
|
})
|
|
1369
1369
|
)
|
|
1370
1370
|
});
|
|
1371
|
-
conversationSnapshotSchema =
|
|
1371
|
+
conversationSnapshotSchema = z12.object({
|
|
1372
1372
|
conversation: conversationSummarySchema,
|
|
1373
|
-
events:
|
|
1373
|
+
events: z12.array(conversationEventSchema),
|
|
1374
1374
|
/**
|
|
1375
1375
|
* Each person actor's display name, by ID, as it is now. A person is shown by this, never by
|
|
1376
1376
|
* the name stored with an event, which for older events was their address.
|
|
1377
1377
|
*/
|
|
1378
|
-
people:
|
|
1378
|
+
people: z12.record(z12.string(), z12.string()).optional(),
|
|
1379
1379
|
placement: placementSchema.nullable().optional(),
|
|
1380
1380
|
tree: treeSummarySchema.optional()
|
|
1381
1381
|
});
|
|
1382
|
-
liveFrameSchema =
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1382
|
+
liveFrameSchema = z12.discriminatedUnion("type", [
|
|
1383
|
+
z12.object({ type: z12.literal("event"), event: conversationEventSchema }),
|
|
1384
|
+
z12.object({ type: z12.literal("reconnect") }),
|
|
1385
|
+
z12.object({ type: z12.literal("expired") })
|
|
1386
1386
|
]);
|
|
1387
|
-
adapterCapabilitiesSchema =
|
|
1388
|
-
messages:
|
|
1389
|
-
edits:
|
|
1390
|
-
deletes:
|
|
1391
|
-
reactions:
|
|
1392
|
-
status:
|
|
1393
|
-
search:
|
|
1387
|
+
adapterCapabilitiesSchema = z12.object({
|
|
1388
|
+
messages: z12.enum(["push", "window"]),
|
|
1389
|
+
edits: z12.enum(["push", "rescan"]),
|
|
1390
|
+
deletes: z12.enum(["push", "rescan"]),
|
|
1391
|
+
reactions: z12.enum(["push", "counts"]),
|
|
1392
|
+
status: z12.boolean(),
|
|
1393
|
+
search: z12.boolean()
|
|
1394
1394
|
});
|
|
1395
1395
|
}
|
|
1396
1396
|
});
|
|
1397
1397
|
|
|
1398
1398
|
// ../common-chat/src/conversation-state.ts
|
|
1399
|
-
import { z as
|
|
1399
|
+
import { z as z13 } from "zod";
|
|
1400
1400
|
function openRank(item) {
|
|
1401
1401
|
if (item.state === "stuck") return 0;
|
|
1402
1402
|
if (leadOpen(item.lead) && item.lead?.move === "you") return 1;
|
|
@@ -1433,8 +1433,8 @@ var init_conversation_state = __esm({
|
|
|
1433
1433
|
init_machines();
|
|
1434
1434
|
init_pull_requests();
|
|
1435
1435
|
init_work_objects();
|
|
1436
|
-
nonEmpty7 =
|
|
1437
|
-
time5 =
|
|
1436
|
+
nonEmpty7 = z13.string().min(1);
|
|
1437
|
+
time5 = z13.number().int().nonnegative();
|
|
1438
1438
|
REACTIONS = {
|
|
1439
1439
|
waiting: "eyes",
|
|
1440
1440
|
working: "hourglass_flowing_sand",
|
|
@@ -1443,14 +1443,14 @@ var init_conversation_state = __esm({
|
|
|
1443
1443
|
passed: "ok_hand",
|
|
1444
1444
|
stuck: "warning"
|
|
1445
1445
|
};
|
|
1446
|
-
conversationStateSchema =
|
|
1446
|
+
conversationStateSchema = z13.enum([
|
|
1447
1447
|
"waiting",
|
|
1448
1448
|
"working",
|
|
1449
1449
|
"stuck",
|
|
1450
1450
|
"unanswered",
|
|
1451
1451
|
"done"
|
|
1452
1452
|
]);
|
|
1453
|
-
stuckReasonSchema =
|
|
1453
|
+
stuckReasonSchema = z13.enum([
|
|
1454
1454
|
"approval",
|
|
1455
1455
|
"waiting_on_someone",
|
|
1456
1456
|
// A delegate has an open prompt or is waiting on a person.
|
|
@@ -1467,43 +1467,43 @@ var init_conversation_state = __esm({
|
|
|
1467
1467
|
"awaiting_answer"
|
|
1468
1468
|
]);
|
|
1469
1469
|
STUCK_REASONS = stuckReasonSchema.options;
|
|
1470
|
-
placeKindSchema =
|
|
1471
|
-
conversationSourceSchema =
|
|
1470
|
+
placeKindSchema = z13.enum(["channel", "direct", "group", "web"]);
|
|
1471
|
+
conversationSourceSchema = z13.object({
|
|
1472
1472
|
provider: nonEmpty7,
|
|
1473
1473
|
kind: placeKindSchema,
|
|
1474
1474
|
/** Such as a Slack channel's name, without its `#`. Left out where it's unknown or hidden. */
|
|
1475
|
-
name:
|
|
1475
|
+
name: z13.string().optional()
|
|
1476
1476
|
});
|
|
1477
1477
|
LATEST_MESSAGE_LENGTH = 200;
|
|
1478
|
-
latestMessageSchema =
|
|
1479
|
-
text:
|
|
1478
|
+
latestMessageSchema = z13.object({
|
|
1479
|
+
text: z13.string().max(LATEST_MESSAGE_LENGTH),
|
|
1480
1480
|
/** A person wrote it, or the agent did. */
|
|
1481
|
-
from:
|
|
1481
|
+
from: z13.enum(["person", "agent"]),
|
|
1482
1482
|
at: time5
|
|
1483
1483
|
});
|
|
1484
1484
|
listMachineSchema = machinePresenceSchema.extend({
|
|
1485
|
-
mine:
|
|
1485
|
+
mine: z13.boolean().optional(),
|
|
1486
1486
|
/** The agent holding it on that machine, such as `Claude Code`, when it's known. */
|
|
1487
|
-
agent:
|
|
1487
|
+
agent: z13.string().optional()
|
|
1488
1488
|
});
|
|
1489
|
-
conversationListItemSchema =
|
|
1489
|
+
conversationListItemSchema = z13.object({
|
|
1490
1490
|
id: nonEmpty7,
|
|
1491
1491
|
title: nonEmpty7,
|
|
1492
1492
|
visibility: conversationVisibilitySchema,
|
|
1493
1493
|
/** The conversation's page. */
|
|
1494
1494
|
url: nonEmpty7,
|
|
1495
1495
|
/** Its thread on its platform, when it has a link. */
|
|
1496
|
-
placeUrl:
|
|
1496
|
+
placeUrl: z13.string().nullable(),
|
|
1497
1497
|
state: conversationStateSchema,
|
|
1498
1498
|
// A reason this version no longer gives, such as one stored before it, reads as none.
|
|
1499
1499
|
reason: stuckReasonSchema.nullable().catch(null),
|
|
1500
1500
|
/** The start of the latest waking message. */
|
|
1501
|
-
latestRequest:
|
|
1501
|
+
latestRequest: z13.string().nullable(),
|
|
1502
1502
|
lastRequestAt: time5.nullable(),
|
|
1503
1503
|
/** When the bot last posted in the thread. */
|
|
1504
1504
|
lastReplyAt: time5.nullable(),
|
|
1505
1505
|
/** What the agent says it's doing, while it works. */
|
|
1506
|
-
activity:
|
|
1506
|
+
activity: z13.string().nullable(),
|
|
1507
1507
|
/** The machine holding it, by name and presence only, and whether it's the reader's own. */
|
|
1508
1508
|
machine: listMachineSchema.nullable(),
|
|
1509
1509
|
lastActivityAt: time5,
|
|
@@ -1514,28 +1514,28 @@ var init_conversation_state = __esm({
|
|
|
1514
1514
|
/** When its activity last changed, which says how long an agent has been quiet. */
|
|
1515
1515
|
activityAt: time5.nullable().optional(),
|
|
1516
1516
|
/** Set when the title, latest request, link and activity were left out because it's private. */
|
|
1517
|
-
hidden:
|
|
1517
|
+
hidden: z13.boolean().optional(),
|
|
1518
1518
|
/**
|
|
1519
1519
|
* What it's about, its delegates' included: at most 5, open ones first. Missing, from servers
|
|
1520
1520
|
* older than work objects, means none.
|
|
1521
1521
|
*/
|
|
1522
|
-
work:
|
|
1522
|
+
work: z13.array(workObjectSummarySchema).optional(),
|
|
1523
1523
|
/** How many more work objects it holds than `work` carries. */
|
|
1524
|
-
moreWork:
|
|
1524
|
+
moreWork: z13.number().int().nonnegative().optional(),
|
|
1525
1525
|
/** The pull request it leads with, from all of its tree's, not only those in `work`. */
|
|
1526
1526
|
lead: leadChangeSchema.nullable().optional()
|
|
1527
1527
|
});
|
|
1528
|
-
conversationListSchema =
|
|
1529
|
-
items:
|
|
1528
|
+
conversationListSchema = z13.object({
|
|
1529
|
+
items: z13.array(conversationListItemSchema),
|
|
1530
1530
|
/** Present when there's more, to pass back as `next` for the following page. */
|
|
1531
|
-
next:
|
|
1531
|
+
next: z13.string().optional()
|
|
1532
1532
|
});
|
|
1533
|
-
listFrameSchema =
|
|
1534
|
-
|
|
1533
|
+
listFrameSchema = z13.discriminatedUnion("type", [
|
|
1534
|
+
z13.object({ type: z13.literal("changed"), conversations: z13.array(nonEmpty7).min(1) }),
|
|
1535
1535
|
/** A machine went online or offline, or a worker's usage changed. */
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1536
|
+
z13.object({ type: z13.literal("machines") }),
|
|
1537
|
+
z13.object({ type: z13.literal("reconnect") }),
|
|
1538
|
+
z13.object({ type: z13.literal("expired") })
|
|
1539
1539
|
]);
|
|
1540
1540
|
STATE_REACTIONS = {
|
|
1541
1541
|
stuck: REACTIONS.stuck,
|
|
@@ -1574,7 +1574,7 @@ var init_conversation_state = __esm({
|
|
|
1574
1574
|
});
|
|
1575
1575
|
|
|
1576
1576
|
// ../common-chat/src/board.ts
|
|
1577
|
-
import { z as
|
|
1577
|
+
import { z as z14 } from "zod";
|
|
1578
1578
|
var nonEmpty8, time6, BOARD_ITEMS, boardItemSchema, boardWorkerSchema, boardMachineSchema, boardSchema;
|
|
1579
1579
|
var init_board = __esm({
|
|
1580
1580
|
"../common-chat/src/board.ts"() {
|
|
@@ -1583,27 +1583,27 @@ var init_board = __esm({
|
|
|
1583
1583
|
init_conversation_state();
|
|
1584
1584
|
init_pull_requests();
|
|
1585
1585
|
init_usage();
|
|
1586
|
-
nonEmpty8 =
|
|
1587
|
-
time6 =
|
|
1586
|
+
nonEmpty8 = z14.string().min(1);
|
|
1587
|
+
time6 = z14.number().int().nonnegative();
|
|
1588
1588
|
BOARD_ITEMS = 8;
|
|
1589
|
-
boardItemSchema =
|
|
1589
|
+
boardItemSchema = z14.object({
|
|
1590
1590
|
id: nonEmpty8,
|
|
1591
1591
|
/** `HIDDEN_TITLE` when the item is private and the board doesn't show private titles. */
|
|
1592
1592
|
title: nonEmpty8,
|
|
1593
1593
|
state: conversationStateSchema,
|
|
1594
1594
|
reason: stuckReasonSchema.nullable().catch(null),
|
|
1595
1595
|
/** Where the work came from, such as `#herd-dev` or a direct message, when it's known. */
|
|
1596
|
-
source:
|
|
1596
|
+
source: z14.string().nullable(),
|
|
1597
1597
|
/** What the agent says it's doing, while it works. */
|
|
1598
|
-
activity:
|
|
1598
|
+
activity: z14.string().nullable(),
|
|
1599
1599
|
lastActivityAt: time6,
|
|
1600
1600
|
/** The machine and agent holding it, such as `mac-mini` and `Claude Code`, once it's bound. */
|
|
1601
|
-
heldBy:
|
|
1601
|
+
heldBy: z14.object({ machine: nonEmpty8, agent: nonEmpty8 }).nullable().optional(),
|
|
1602
1602
|
/** The pull request it leads with, and how many more are the person's move. */
|
|
1603
1603
|
change: leadChangeSchema.nullable().optional(),
|
|
1604
|
-
hidden:
|
|
1604
|
+
hidden: z14.boolean().optional()
|
|
1605
1605
|
});
|
|
1606
|
-
boardWorkerSchema =
|
|
1606
|
+
boardWorkerSchema = z14.object({
|
|
1607
1607
|
/** The worker's short name, such as `claude`, under its machine. */
|
|
1608
1608
|
name: nonEmpty8,
|
|
1609
1609
|
/** Its agent CLI, such as `claude-code`, which names it on the board. */
|
|
@@ -1612,33 +1612,33 @@ var init_board = __esm({
|
|
|
1612
1612
|
usage: usageSchema.nullable(),
|
|
1613
1613
|
reportedAt: time6.nullable(),
|
|
1614
1614
|
/** What it's great at, from its profile: its owner's statements, or herd's defaults. */
|
|
1615
|
-
strengths:
|
|
1615
|
+
strengths: z14.array(z14.string().min(1).max(100)).max(3).optional()
|
|
1616
1616
|
});
|
|
1617
|
-
boardMachineSchema =
|
|
1617
|
+
boardMachineSchema = z14.object({
|
|
1618
1618
|
name: nonEmpty8,
|
|
1619
|
-
online:
|
|
1620
|
-
workers:
|
|
1619
|
+
online: z14.boolean(),
|
|
1620
|
+
workers: z14.array(boardWorkerSchema).max(8)
|
|
1621
1621
|
});
|
|
1622
|
-
boardSchema =
|
|
1622
|
+
boardSchema = z14.object({
|
|
1623
1623
|
/** How many are in each open state: every state but `done`, which is counted for the last day. */
|
|
1624
|
-
counts:
|
|
1625
|
-
stuck:
|
|
1626
|
-
unanswered:
|
|
1627
|
-
waiting:
|
|
1628
|
-
working:
|
|
1624
|
+
counts: z14.object({
|
|
1625
|
+
stuck: z14.number().int().nonnegative(),
|
|
1626
|
+
unanswered: z14.number().int().nonnegative(),
|
|
1627
|
+
waiting: z14.number().int().nonnegative(),
|
|
1628
|
+
working: z14.number().int().nonnegative(),
|
|
1629
1629
|
/** Open pull requests the person's conversations made that are their move, each counted. */
|
|
1630
|
-
pullRequests:
|
|
1630
|
+
pullRequests: z14.number().int().nonnegative().optional()
|
|
1631
1631
|
}),
|
|
1632
1632
|
/** How many became `done` in the last 24 hours. */
|
|
1633
|
-
doneToday:
|
|
1633
|
+
doneToday: z14.number().int().nonnegative(),
|
|
1634
1634
|
/**
|
|
1635
1635
|
* What needs the person (stuck, then pull requests that are their move), then what's working or
|
|
1636
1636
|
* has a pull request under way, then what's queued, then the latest finished to fill the rest.
|
|
1637
1637
|
*/
|
|
1638
|
-
items:
|
|
1639
|
-
machines:
|
|
1638
|
+
items: z14.array(boardItemSchema).max(BOARD_ITEMS),
|
|
1639
|
+
machines: z14.array(boardMachineSchema).max(16),
|
|
1640
1640
|
/** Changes whenever anything the board shows changes, and only then. */
|
|
1641
|
-
stamp:
|
|
1641
|
+
stamp: z14.string().regex(/^[0-9a-f]{12}$/),
|
|
1642
1642
|
/** When its content last changed. */
|
|
1643
1643
|
changedAt: time6
|
|
1644
1644
|
});
|
|
@@ -1646,41 +1646,45 @@ var init_board = __esm({
|
|
|
1646
1646
|
});
|
|
1647
1647
|
|
|
1648
1648
|
// ../common-chat/src/bot.ts
|
|
1649
|
-
var BOT_NAME;
|
|
1649
|
+
var BOT_NAME, NPM_SCOPE, FRIDAY_PACKAGE, FRIDAY_COMMAND, START_COMMAND;
|
|
1650
1650
|
var init_bot = __esm({
|
|
1651
1651
|
"../common-chat/src/bot.ts"() {
|
|
1652
1652
|
"use strict";
|
|
1653
1653
|
init_define_HERD_PACKAGE();
|
|
1654
1654
|
BOT_NAME = "Friday";
|
|
1655
|
+
NPM_SCOPE = "@herdingchats";
|
|
1656
|
+
FRIDAY_PACKAGE = `${NPM_SCOPE}/friday`;
|
|
1657
|
+
FRIDAY_COMMAND = `npx ${FRIDAY_PACKAGE}`;
|
|
1658
|
+
START_COMMAND = `${FRIDAY_COMMAND} start`;
|
|
1655
1659
|
}
|
|
1656
1660
|
});
|
|
1657
1661
|
|
|
1658
1662
|
// ../common-chat/src/builds.ts
|
|
1659
|
-
import { z as
|
|
1663
|
+
import { z as z15 } from "zod";
|
|
1660
1664
|
var nonEmpty9, time7, BUILD_LEASE_MS, BUILD_CLAIM_WINDOW_MS, MAX_LOG_CHUNK_BYTES, MAX_LOG_BYTES, MAX_NODE_MODULES_PART_BYTES, shaSchema, buildOfferSchema, buildCancelReasonSchema, runnerMessageSchema, serviceMessageSchema, runnerRegisterRequestSchema, runnerRegisterResponseSchema, runnerPollRequestSchema, runnerPollResponseSchema, buildStepSchema, buildFinishSchema, sharedPassSchema, passesResponseSchema, deployCredentialsSchema, deployedSchema, healthSchema;
|
|
1661
1665
|
var init_builds = __esm({
|
|
1662
1666
|
"../common-chat/src/builds.ts"() {
|
|
1663
1667
|
"use strict";
|
|
1664
1668
|
init_define_HERD_PACKAGE();
|
|
1665
1669
|
init_workers();
|
|
1666
|
-
nonEmpty9 =
|
|
1667
|
-
time7 =
|
|
1670
|
+
nonEmpty9 = z15.string().min(1);
|
|
1671
|
+
time7 = z15.number().int().nonnegative();
|
|
1668
1672
|
BUILD_LEASE_MS = 5 * 60 * 1e3;
|
|
1669
1673
|
BUILD_CLAIM_WINDOW_MS = 15 * 1e3;
|
|
1670
1674
|
MAX_LOG_CHUNK_BYTES = 256 * 1024;
|
|
1671
1675
|
MAX_LOG_BYTES = 5 * 1024 * 1024;
|
|
1672
1676
|
MAX_NODE_MODULES_PART_BYTES = 95 * 1024 * 1024;
|
|
1673
|
-
shaSchema =
|
|
1674
|
-
buildOfferSchema =
|
|
1677
|
+
shaSchema = z15.string().regex(/^[0-9a-f]{40}$/);
|
|
1678
|
+
buildOfferSchema = z15.object({
|
|
1675
1679
|
id: nonEmpty9,
|
|
1676
1680
|
offerId: nonEmpty9,
|
|
1677
1681
|
repo: nonEmpty9,
|
|
1678
1682
|
sha: shaSchema,
|
|
1679
1683
|
ref: nonEmpty9,
|
|
1680
|
-
main:
|
|
1684
|
+
main: z15.boolean(),
|
|
1681
1685
|
expiresAt: time7
|
|
1682
1686
|
});
|
|
1683
|
-
buildCancelReasonSchema =
|
|
1687
|
+
buildCancelReasonSchema = z15.enum([
|
|
1684
1688
|
// A newer push to the same branch replaced it.
|
|
1685
1689
|
"superseded",
|
|
1686
1690
|
// The branch was deleted.
|
|
@@ -1690,7 +1694,7 @@ var init_builds = __esm({
|
|
|
1690
1694
|
// Stopped for another reason, such as the repo being removed.
|
|
1691
1695
|
"cancelled"
|
|
1692
1696
|
]);
|
|
1693
|
-
runnerMessageSchema =
|
|
1697
|
+
runnerMessageSchema = z15.discriminatedUnion("type", [
|
|
1694
1698
|
/**
|
|
1695
1699
|
* Sent first, and again whenever any of it changes. `capacity` comes from `herd.config.ts`'s
|
|
1696
1700
|
* `builds` through `runnerCapacity`, `repos` are the normalized remotes of the repos herd has
|
|
@@ -1698,82 +1702,82 @@ var init_builds = __esm({
|
|
|
1698
1702
|
* any of its owner's repos, cloning one it hasn't got, and `repos` only puts it first for those.
|
|
1699
1703
|
* A daemon from before herd's root sent its configured checkouts here, which it builds from.
|
|
1700
1704
|
*/
|
|
1701
|
-
|
|
1702
|
-
type:
|
|
1705
|
+
z15.object({
|
|
1706
|
+
type: z15.literal("hello"),
|
|
1703
1707
|
/** How many builds at once. 0 when the machine can't sandbox a build, so it takes none. */
|
|
1704
|
-
capacity:
|
|
1705
|
-
repos:
|
|
1706
|
-
running:
|
|
1708
|
+
capacity: z15.number().int().min(0).max(BUILDS_MAX),
|
|
1709
|
+
repos: z15.array(nonEmpty9.max(300)).max(100),
|
|
1710
|
+
running: z15.array(nonEmpty9.max(100)).max(BUILDS_MAX * 2)
|
|
1707
1711
|
}),
|
|
1708
1712
|
/** An answer to an offer, before its `expiresAt`. A refusal may say why. */
|
|
1709
|
-
|
|
1710
|
-
type:
|
|
1713
|
+
z15.object({
|
|
1714
|
+
type: z15.literal("answer"),
|
|
1711
1715
|
buildId: nonEmpty9,
|
|
1712
1716
|
offerId: nonEmpty9,
|
|
1713
|
-
answer:
|
|
1714
|
-
reason:
|
|
1717
|
+
answer: z15.enum(["accept", "refuse"]),
|
|
1718
|
+
reason: z15.string().max(500).optional()
|
|
1715
1719
|
})
|
|
1716
1720
|
]);
|
|
1717
|
-
serviceMessageSchema =
|
|
1718
|
-
|
|
1721
|
+
serviceMessageSchema = z15.discriminatedUnion("type", [
|
|
1722
|
+
z15.object({ type: z15.literal("build"), build: buildOfferSchema }),
|
|
1719
1723
|
/** An accepted offer: the build's own secret, and how long its claim lasts between renewals. */
|
|
1720
|
-
|
|
1721
|
-
type:
|
|
1724
|
+
z15.object({
|
|
1725
|
+
type: z15.literal("accepted"),
|
|
1722
1726
|
buildId: nonEmpty9,
|
|
1723
1727
|
secret: nonEmpty9,
|
|
1724
|
-
leaseMs:
|
|
1728
|
+
leaseMs: z15.number().int().positive()
|
|
1725
1729
|
}),
|
|
1726
1730
|
/**
|
|
1727
1731
|
* Stop a build this runner holds, within 5 seconds. An accept that came too late, for an offer
|
|
1728
1732
|
* that had expired or was withdrawn, gets this too, with the reason `cancelled`.
|
|
1729
1733
|
*/
|
|
1730
|
-
|
|
1734
|
+
z15.object({ type: z15.literal("build-cancel"), buildId: nonEmpty9, reason: buildCancelReasonSchema }),
|
|
1731
1735
|
/** Connect again. Sent before the service closes a socket that another replaced. */
|
|
1732
|
-
|
|
1736
|
+
z15.object({ type: z15.literal("reconnect") })
|
|
1733
1737
|
]);
|
|
1734
|
-
runnerRegisterRequestSchema =
|
|
1735
|
-
runnerRegisterResponseSchema =
|
|
1738
|
+
runnerRegisterRequestSchema = z15.object({ name: z15.string().trim().min(1).max(100) });
|
|
1739
|
+
runnerRegisterResponseSchema = z15.object({
|
|
1736
1740
|
/** Shown to the owner, so they can match the approval page to the machine. */
|
|
1737
1741
|
code: nonEmpty9,
|
|
1738
1742
|
/** The page the owner opens, signed in, to approve it. */
|
|
1739
|
-
approveUrl:
|
|
1743
|
+
approveUrl: z15.url(),
|
|
1740
1744
|
/** Sent to `POST /runners/register/poll`. Only this machine has it. */
|
|
1741
1745
|
pollToken: nonEmpty9,
|
|
1742
1746
|
expiresAt: time7.optional(),
|
|
1743
1747
|
/** How often to poll. */
|
|
1744
|
-
pollMs:
|
|
1748
|
+
pollMs: z15.number().int().positive().optional()
|
|
1745
1749
|
});
|
|
1746
|
-
runnerPollRequestSchema =
|
|
1747
|
-
runnerPollResponseSchema =
|
|
1748
|
-
|
|
1750
|
+
runnerPollRequestSchema = z15.object({ pollToken: nonEmpty9.max(200) });
|
|
1751
|
+
runnerPollResponseSchema = z15.discriminatedUnion("status", [
|
|
1752
|
+
z15.object({ status: z15.literal("waiting") }),
|
|
1749
1753
|
/** Approved. The key is returned this once, and the service keeps only its hash. */
|
|
1750
|
-
|
|
1754
|
+
z15.object({ status: z15.literal("approved"), runnerId: nonEmpty9, key: nonEmpty9 }),
|
|
1751
1755
|
/** Expired, or the key was already collected. Start again. */
|
|
1752
|
-
|
|
1756
|
+
z15.object({ status: z15.literal("expired") })
|
|
1753
1757
|
]);
|
|
1754
|
-
buildStepSchema =
|
|
1755
|
-
label:
|
|
1756
|
-
key:
|
|
1757
|
-
status:
|
|
1758
|
-
ms:
|
|
1758
|
+
buildStepSchema = z15.object({
|
|
1759
|
+
label: z15.string().min(1).max(200),
|
|
1760
|
+
key: z15.string().regex(/^[0-9a-zA-Z_-]{8,128}$/),
|
|
1761
|
+
status: z15.enum(["passed", "failed", "remembered"]),
|
|
1762
|
+
ms: z15.number().int().nonnegative(),
|
|
1759
1763
|
/** Only some of the step's tests ran, so its pass isn't shared. */
|
|
1760
|
-
partial:
|
|
1761
|
-
budgetMs:
|
|
1764
|
+
partial: z15.boolean().default(false),
|
|
1765
|
+
budgetMs: z15.number().int().positive().nullable().default(null)
|
|
1762
1766
|
});
|
|
1763
|
-
buildFinishSchema =
|
|
1764
|
-
status:
|
|
1765
|
-
summary:
|
|
1766
|
-
deployed:
|
|
1767
|
+
buildFinishSchema = z15.object({
|
|
1768
|
+
status: z15.enum(["success", "failure", "error"]),
|
|
1769
|
+
summary: z15.string().max(2e3).default(""),
|
|
1770
|
+
deployed: z15.boolean().default(false)
|
|
1767
1771
|
});
|
|
1768
|
-
sharedPassSchema =
|
|
1772
|
+
sharedPassSchema = z15.object({
|
|
1769
1773
|
step: nonEmpty9,
|
|
1770
1774
|
passedAt: time7,
|
|
1771
1775
|
sha: nonEmpty9,
|
|
1772
1776
|
runner: nonEmpty9,
|
|
1773
|
-
partial:
|
|
1777
|
+
partial: z15.boolean()
|
|
1774
1778
|
});
|
|
1775
|
-
passesResponseSchema =
|
|
1776
|
-
deployCredentialsSchema =
|
|
1779
|
+
passesResponseSchema = z15.object({ passes: z15.record(z15.string(), sharedPassSchema) });
|
|
1780
|
+
deployCredentialsSchema = z15.object({
|
|
1777
1781
|
cloudflareToken: nonEmpty9,
|
|
1778
1782
|
/** Publishes `@herdingchats/friday`. Missing when the build service has none set. */
|
|
1779
1783
|
npmToken: nonEmpty9.optional(),
|
|
@@ -1782,20 +1786,20 @@ var init_builds = __esm({
|
|
|
1782
1786
|
/** `owner/name`, for moving `deployed`. */
|
|
1783
1787
|
repo: nonEmpty9,
|
|
1784
1788
|
/** The commit being built, which `deployed` moves to. Older services don't send it. */
|
|
1785
|
-
sha:
|
|
1789
|
+
sha: z15.string().regex(/^[0-9a-f]{40}$/).optional(),
|
|
1786
1790
|
/** Each Worker's key at its last successful deploy. */
|
|
1787
|
-
lastDeployed:
|
|
1791
|
+
lastDeployed: z15.record(z15.string(), z15.string())
|
|
1788
1792
|
});
|
|
1789
|
-
deployedSchema =
|
|
1790
|
-
worker:
|
|
1791
|
-
key:
|
|
1793
|
+
deployedSchema = z15.object({
|
|
1794
|
+
worker: z15.string().regex(/^[a-z][a-z0-9-]{0,62}$/),
|
|
1795
|
+
key: z15.string().regex(/^[0-9a-zA-Z_-]{8,128}$/)
|
|
1792
1796
|
});
|
|
1793
|
-
healthSchema =
|
|
1797
|
+
healthSchema = z15.object({ ok: z15.boolean(), version: z15.string() });
|
|
1794
1798
|
}
|
|
1795
1799
|
});
|
|
1796
1800
|
|
|
1797
1801
|
// ../common-chat/src/setup.ts
|
|
1798
|
-
import { z as
|
|
1802
|
+
import { z as z16 } from "zod";
|
|
1799
1803
|
function actionText(action) {
|
|
1800
1804
|
if (action.kind === "link") return `${action.label}: ${action.url}`;
|
|
1801
1805
|
if (action.kind === "sign_in") {
|
|
@@ -1830,42 +1834,42 @@ var init_setup = __esm({
|
|
|
1830
1834
|
init_activation();
|
|
1831
1835
|
init_bot();
|
|
1832
1836
|
SETUP_STEP_IDS = ["slack", "machine", "github", "repos"];
|
|
1833
|
-
setupActionSchema =
|
|
1837
|
+
setupActionSchema = z16.discriminatedUnion("kind", [
|
|
1834
1838
|
/** A page to open, which signs in to HerdingChats first. */
|
|
1835
|
-
|
|
1839
|
+
z16.object({ kind: z16.literal("link"), url: z16.string(), label: z16.string() }),
|
|
1836
1840
|
/** A command to run on the computer. */
|
|
1837
|
-
|
|
1841
|
+
z16.object({ kind: z16.literal("command"), command: z16.string() }),
|
|
1838
1842
|
/**
|
|
1839
1843
|
* A sign-in herd starts on one of the person's machines, from Slack or the page, whose code
|
|
1840
1844
|
* Friday sends to their direct message.
|
|
1841
1845
|
*/
|
|
1842
|
-
|
|
1843
|
-
kind:
|
|
1844
|
-
machineId:
|
|
1846
|
+
z16.object({
|
|
1847
|
+
kind: z16.literal("sign_in"),
|
|
1848
|
+
machineId: z16.string(),
|
|
1845
1849
|
tool: signInToolSchema,
|
|
1846
|
-
label:
|
|
1850
|
+
label: z16.string()
|
|
1847
1851
|
})
|
|
1848
1852
|
]);
|
|
1849
|
-
setupStepSchema =
|
|
1850
|
-
id:
|
|
1853
|
+
setupStepSchema = z16.object({
|
|
1854
|
+
id: z16.enum(SETUP_STEP_IDS),
|
|
1851
1855
|
/** `unavailable` is a step nobody can take yet, such as GitHub linking before an admin turns it on. */
|
|
1852
|
-
state:
|
|
1853
|
-
optional:
|
|
1854
|
-
title:
|
|
1856
|
+
state: z16.enum(["done", "todo", "unavailable"]),
|
|
1857
|
+
optional: z16.boolean(),
|
|
1858
|
+
title: z16.string(),
|
|
1855
1859
|
/** What was found, such as the machine and whether it's online, or why it can't be done yet. */
|
|
1856
|
-
detail:
|
|
1860
|
+
detail: z16.string().nullable(),
|
|
1857
1861
|
/** What to do next. None once it's done, or while it's unavailable. */
|
|
1858
1862
|
action: setupActionSchema.nullable(),
|
|
1859
1863
|
/**
|
|
1860
1864
|
* More that can be done, which doesn't decide whether the step is done, such as signing in a
|
|
1861
1865
|
* computer's GitHub CLI. Shown whatever the step's state.
|
|
1862
1866
|
*/
|
|
1863
|
-
extra:
|
|
1867
|
+
extra: z16.array(setupActionSchema).optional()
|
|
1864
1868
|
});
|
|
1865
|
-
setupStatusSchema =
|
|
1866
|
-
steps:
|
|
1869
|
+
setupStatusSchema = z16.object({
|
|
1870
|
+
steps: z16.array(setupStepSchema),
|
|
1867
1871
|
/** Whether every step that isn't optional is done, so Friday can take work. */
|
|
1868
|
-
ready:
|
|
1872
|
+
ready: z16.boolean()
|
|
1869
1873
|
});
|
|
1870
1874
|
READY_TEXT = `You're set up: mention @${BOT_NAME} in any channel it's in, or message it directly.`;
|
|
1871
1875
|
READY_SUGGESTIONS_TITLE = "Some things to try:";
|
|
@@ -3135,6 +3139,7 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
|
3135
3139
|
|
|
3136
3140
|
// src/friday/main.ts
|
|
3137
3141
|
init_define_HERD_PACKAGE();
|
|
3142
|
+
init_src();
|
|
3138
3143
|
import { spawn as spawn5 } from "node:child_process";
|
|
3139
3144
|
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
3140
3145
|
import { homedir as homedir4 } from "node:os";
|
|
@@ -3148,21 +3153,21 @@ import { chmodSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:
|
|
|
3148
3153
|
import { createServer } from "node:http";
|
|
3149
3154
|
import { homedir } from "node:os";
|
|
3150
3155
|
import { join } from "node:path";
|
|
3151
|
-
import { z } from "zod";
|
|
3156
|
+
import { z as z17 } from "zod";
|
|
3152
3157
|
var herdHome = () => process.env.HERD_HOME ?? join(homedir(), ".herd");
|
|
3153
3158
|
var apiUrl = () => (process.env.HERD_API_URL ?? "https://api.herdingchats.com").replace(/\/+$/, "");
|
|
3154
3159
|
var isLocal = (url) => /^http:\/\/localhost:\d+\/?$/.test(url);
|
|
3155
3160
|
var localSignIn = () => process.env.HERD_LOCAL_SLACK ? { "X-Herd-Local-Slack": process.env.HERD_LOCAL_SLACK } : {};
|
|
3156
3161
|
var HerdError = class extends Error {
|
|
3157
3162
|
};
|
|
3158
|
-
var credentialsSchema =
|
|
3159
|
-
api:
|
|
3160
|
-
tokenEndpoint:
|
|
3161
|
-
revocationEndpoint:
|
|
3162
|
-
clientId:
|
|
3163
|
-
accessToken:
|
|
3164
|
-
accessTokenExpiresAt:
|
|
3165
|
-
refreshToken:
|
|
3163
|
+
var credentialsSchema = z17.object({
|
|
3164
|
+
api: z17.string(),
|
|
3165
|
+
tokenEndpoint: z17.string(),
|
|
3166
|
+
revocationEndpoint: z17.string().optional(),
|
|
3167
|
+
clientId: z17.string(),
|
|
3168
|
+
accessToken: z17.string(),
|
|
3169
|
+
accessTokenExpiresAt: z17.number(),
|
|
3170
|
+
refreshToken: z17.string()
|
|
3166
3171
|
});
|
|
3167
3172
|
var credentialsPath = () => join(herdHome(), "credentials.json");
|
|
3168
3173
|
function readCredentials() {
|
|
@@ -3178,16 +3183,16 @@ function writeCredentials(credentials) {
|
|
|
3178
3183
|
writeFileSync(credentialsPath(), JSON.stringify(credentials, null, 2), { mode: 384 });
|
|
3179
3184
|
chmodSync(credentialsPath(), 384);
|
|
3180
3185
|
}
|
|
3181
|
-
var metadataSchema =
|
|
3182
|
-
authorization_endpoint:
|
|
3183
|
-
token_endpoint:
|
|
3184
|
-
registration_endpoint:
|
|
3185
|
-
revocation_endpoint:
|
|
3186
|
+
var metadataSchema = z17.object({
|
|
3187
|
+
authorization_endpoint: z17.string(),
|
|
3188
|
+
token_endpoint: z17.string(),
|
|
3189
|
+
registration_endpoint: z17.string(),
|
|
3190
|
+
revocation_endpoint: z17.string().optional()
|
|
3186
3191
|
});
|
|
3187
|
-
var tokenSchema =
|
|
3188
|
-
access_token:
|
|
3189
|
-
refresh_token:
|
|
3190
|
-
expires_in:
|
|
3192
|
+
var tokenSchema = z17.object({
|
|
3193
|
+
access_token: z17.string().min(1),
|
|
3194
|
+
refresh_token: z17.string().min(1),
|
|
3195
|
+
expires_in: z17.number()
|
|
3191
3196
|
});
|
|
3192
3197
|
var base64url = (bytes) => bytes.toString("base64url");
|
|
3193
3198
|
async function postForm(url, fields) {
|
|
@@ -3219,7 +3224,7 @@ async function login(openBrowser2, { api = apiUrl(), timeoutMs = 10 * 60 * 1e3 }
|
|
|
3219
3224
|
token_endpoint_auth_method: "none"
|
|
3220
3225
|
})
|
|
3221
3226
|
});
|
|
3222
|
-
const client =
|
|
3227
|
+
const client = z17.object({ client_id: z17.string() }).safeParse(await registration2.json());
|
|
3223
3228
|
if (!registration2.ok || !client.success) {
|
|
3224
3229
|
throw new HerdError("The sign-in server refused to register this tool.");
|
|
3225
3230
|
}
|
|
@@ -5142,7 +5147,9 @@ async function awaitActivations(options, chosen, since, print) {
|
|
|
5142
5147
|
}
|
|
5143
5148
|
}
|
|
5144
5149
|
if (!started && said.size === 0 && Date.now() > startBy) {
|
|
5145
|
-
print(
|
|
5150
|
+
print(
|
|
5151
|
+
`Friday hasn't started activating your agents yet. ${FRIDAY_COMMAND} logs shows what it's doing.`
|
|
5152
|
+
);
|
|
5146
5153
|
break;
|
|
5147
5154
|
}
|
|
5148
5155
|
await sleep2(pollMs);
|
|
@@ -5153,6 +5160,7 @@ var herdConfigIn = (herdHome2) => join7(herdHome2, "herd.config.ts");
|
|
|
5153
5160
|
|
|
5154
5161
|
// src/friday/home.ts
|
|
5155
5162
|
init_define_HERD_PACKAGE();
|
|
5163
|
+
init_src();
|
|
5156
5164
|
import { spawnSync } from "node:child_process";
|
|
5157
5165
|
import {
|
|
5158
5166
|
closeSync as closeSync2,
|
|
@@ -5165,7 +5173,7 @@ import {
|
|
|
5165
5173
|
writeFileSync as writeFileSync6
|
|
5166
5174
|
} from "node:fs";
|
|
5167
5175
|
import { dirname as dirname6, join as join8, resolve as resolve2 } from "node:path";
|
|
5168
|
-
var PACKAGE_NAME =
|
|
5176
|
+
var PACKAGE_NAME = FRIDAY_PACKAGE;
|
|
5169
5177
|
function fridayPaths(herdHome2) {
|
|
5170
5178
|
const logs = join8(herdHome2, "logs");
|
|
5171
5179
|
return {
|
|
@@ -5800,7 +5808,7 @@ async function runStart(options) {
|
|
|
5800
5808
|
const repo = insideWorkTree(root);
|
|
5801
5809
|
if (repo) {
|
|
5802
5810
|
throw new StartError(
|
|
5803
|
-
`${root} is inside the git repo ${repo}, so it can't be the machine's root: every conversation would load that repo's settings. Run
|
|
5811
|
+
`${root} is inside the git repo ${repo}, so it can't be the machine's root: every conversation would load that repo's settings. Run ${START_COMMAND} in an empty folder outside any repo, such as ~/friday.`
|
|
5804
5812
|
);
|
|
5805
5813
|
}
|
|
5806
5814
|
if ((options.platform ?? process.platform) === "linux") {
|
|
@@ -5830,10 +5838,13 @@ async function runStart(options) {
|
|
|
5830
5838
|
const changed = await service.install();
|
|
5831
5839
|
await service.start(changed);
|
|
5832
5840
|
print(
|
|
5833
|
-
`Friday is running from ${root}, version ${currentVersion(paths)}, ${service.kind === "launchd" ? "and starts whenever you log in" : service.kind === "systemd" ? "and starts whenever you log in, as a systemd user service" : "in the background"}
|
|
5841
|
+
`Friday is running from ${root}, version ${currentVersion(paths)}, ${service.kind === "launchd" ? "and starts whenever you log in" : service.kind === "systemd" ? "and starts whenever you log in, as a systemd user service" : "in the background"}.`
|
|
5834
5842
|
);
|
|
5835
5843
|
await waitForAgents(options, asked, print);
|
|
5836
5844
|
await printSetup(options, print, { waitForMachine: true });
|
|
5845
|
+
print(
|
|
5846
|
+
`${FRIDAY_COMMAND} status says how it's doing, and ${FRIDAY_COMMAND} logs shows what it's done.`
|
|
5847
|
+
);
|
|
5837
5848
|
return 0;
|
|
5838
5849
|
}
|
|
5839
5850
|
async function chooseAndAsk(options, print) {
|
|
@@ -5884,7 +5895,7 @@ async function ensureInstalled(options, print) {
|
|
|
5884
5895
|
if (current && !await versionRuns(paths.current, current, options.run)) return;
|
|
5885
5896
|
if (version === "dev" && !options.install?.spec) {
|
|
5886
5897
|
throw new StartError(
|
|
5887
|
-
|
|
5898
|
+
`This friday runs from the repo, which has no version to install. Run ${START_COMMAND}, or npx herd daemon to watch a daemon in the foreground.`
|
|
5888
5899
|
);
|
|
5889
5900
|
}
|
|
5890
5901
|
print(`Installing Friday ${version}.`);
|
|
@@ -5896,6 +5907,7 @@ async function ensureInstalled(options, print) {
|
|
|
5896
5907
|
|
|
5897
5908
|
// src/friday/supervisor.ts
|
|
5898
5909
|
init_define_HERD_PACKAGE();
|
|
5910
|
+
init_src();
|
|
5899
5911
|
import { spawn as spawn4 } from "node:child_process";
|
|
5900
5912
|
import {
|
|
5901
5913
|
closeSync as closeSync3,
|
|
@@ -5975,7 +5987,7 @@ var Supervisor = class {
|
|
|
5975
5987
|
try {
|
|
5976
5988
|
dir = realpathSync4(this.options.paths.current);
|
|
5977
5989
|
} catch {
|
|
5978
|
-
throw new Error(
|
|
5990
|
+
throw new Error(`Nothing is installed in ~/.herd/current. Run ${START_COMMAND}.`);
|
|
5979
5991
|
}
|
|
5980
5992
|
return [process.execPath, binOf(dir, "herd"), "daemon"];
|
|
5981
5993
|
}
|
|
@@ -6120,7 +6132,7 @@ var Supervisor = class {
|
|
|
6120
6132
|
// src/friday/main.ts
|
|
6121
6133
|
var HELP = `friday: run HerdingChats' agent daemon on this computer.
|
|
6122
6134
|
|
|
6123
|
-
Usage:
|
|
6135
|
+
Usage: ${FRIDAY_COMMAND} <command>
|
|
6124
6136
|
|
|
6125
6137
|
start Make this computer a machine, with the folder this runs in as its root, where
|
|
6126
6138
|
Friday keeps its repos and conversations. Signs in through your browser when
|
|
@@ -6128,7 +6140,7 @@ Usage: friday <command>
|
|
|
6128
6140
|
you log in, waits for each agent to check in, then shows what's left to set up.
|
|
6129
6141
|
Safe to run again. --agents claude=lot,codex=little sets the shares without
|
|
6130
6142
|
asking: off, little, some or lot, where a bare name is some and one left out off
|
|
6131
|
-
stop Stop the daemon until you log in again, or run
|
|
6143
|
+
stop Stop the daemon until you log in again, or run start again
|
|
6132
6144
|
status Whether the daemon is running, which version, and its root
|
|
6133
6145
|
logs [-f] Show the daemon's latest log lines. -f keeps following them
|
|
6134
6146
|
--version Print this version
|
|
@@ -6267,7 +6279,7 @@ async function runStop(deps) {
|
|
|
6267
6279
|
});
|
|
6268
6280
|
await service.stop();
|
|
6269
6281
|
deps.print(
|
|
6270
|
-
running ?
|
|
6282
|
+
running ? `Stopped Friday. Its terminals keep running. ${START_COMMAND} starts it again, and so does logging in.` : "Friday wasn't running."
|
|
6271
6283
|
);
|
|
6272
6284
|
return 0;
|
|
6273
6285
|
}
|
|
@@ -6288,12 +6300,12 @@ function runStatus(deps) {
|
|
|
6288
6300
|
pin = "";
|
|
6289
6301
|
}
|
|
6290
6302
|
if (!version && !running) {
|
|
6291
|
-
print(
|
|
6303
|
+
print(`Friday isn't set up on this computer. Run ${START_COMMAND} in its root.`);
|
|
6292
6304
|
return 1;
|
|
6293
6305
|
}
|
|
6294
6306
|
const daemon = running && status2.daemonPid && alive2(status2.daemonPid);
|
|
6295
6307
|
print(
|
|
6296
|
-
running ? `Friday is running, version ${status2.version}${daemon ? `, with the daemon at pid ${status2.daemonPid}` : ", restarting the daemon"}.` :
|
|
6308
|
+
running ? `Friday is running, version ${status2.version}${daemon ? `, with the daemon at pid ${status2.daemonPid}` : ", restarting the daemon"}.` : `Friday isn't running. ${START_COMMAND} starts it.`
|
|
6297
6309
|
);
|
|
6298
6310
|
if (version) print(`Installed: ${version}${pin ? `, pinned to ${pin} in ${paths.pin}` : ""}.`);
|
|
6299
6311
|
if (root) print(`Root: ${root}`);
|