@herdingchats/friday 0.1.538 → 0.1.547

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.
Files changed (2) hide show
  1. package/herd.mjs +546 -525
  2. 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.538", gitHead: "ddb7331693c41a23a60c6f16eefa82f7adc09860" };
21
+ define_HERD_PACKAGE_default = { version: "0.1.547", gitHead: "2bb0029716f49d8ffbe45379ba4c6b9a40de4359" };
22
22
  }
23
23
  });
24
24
 
25
25
  // ../common-chat/src/activation.ts
26
- import { z as z2 } from "zod";
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 = z2.number().int().nonnegative();
49
- activationFailureSchema = z2.enum([
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 = z2.object({
60
- state: z2.enum(["activated", "waiting", "failed"]),
61
- version: z2.string().min(1).max(100),
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: z2.boolean().optional(),
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 = z2.discriminatedUnion("state", [
75
- z2.object({ state: z2.literal("signed_in"), login: z2.string().min(1).max(100), checkedAt: time }),
76
- z2.object({ state: z2.literal("signed_out"), checkedAt: time }),
77
- z2.object({ state: z2.literal("missing"), checkedAt: time })
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 = z2.enum(["gh"]);
79
+ signInToolSchema = z.enum(["gh"]);
80
80
  GITHUB_DEVICE_URL = "https://github.com/login/device";
81
- signInUpdateSchema = z2.discriminatedUnion("state", [
82
- z2.object({
83
- state: z2.literal("code"),
84
- code: z2.string().regex(/^[A-Z0-9]{4}-[A-Z0-9]{4}$/),
85
- url: z2.literal(GITHUB_DEVICE_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
- z2.object({ state: z2.literal("signed_in"), login: z2.string().min(1).max(100) }),
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
- z2.object({ state: z2.literal("failed"), reason: z2.enum(["no_code", "not_signed_in"]) })
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 z3 } from "zod";
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 = z3.string().min(1);
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 = z3.enum(GITHUB_TRIGGER_KINDS);
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 = z3.object({
119
+ githubTriggerEventSchema = z2.object({
120
120
  /** The event, so each fires an automation once. */
121
121
  key: nonEmpty,
122
122
  kind: githubTriggerKindSchema,
123
- repoId: z3.number().int(),
123
+ repoId: z2.number().int(),
124
124
  /** `owner/name`. */
125
125
  repo: nonEmpty,
126
- number: z3.number().int().positive(),
126
+ number: z2.number().int().positive(),
127
127
  /** The pull request's link. */
128
- url: z3.url(),
128
+ url: z2.url(),
129
129
  /** Where the event itself is, such as the review or the comment. */
130
- eventUrl: z3.url().optional(),
130
+ eventUrl: z2.url().optional(),
131
131
  /** The pull request's title, when the event says it. */
132
- title: z3.string().max(300).optional(),
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: z3.string().optional(),
137
- private: z3.boolean(),
138
- at: z3.number().int().nonnegative()
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 z4 } from "zod";
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 = z4.string().trim().min(1);
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 = z4.discriminatedUnion("kind", [
217
+ triggerSchema = z3.discriminatedUnion("kind", [
218
218
  // A five-field cron expression, read in its time zone.
219
- z4.object({ kind: z4.literal("cron"), cron: nonEmpty2.max(100), timeZone: timeZoneSchema }),
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
- z4.object({ kind: z4.literal("once"), at: z4.number().int().positive(), timeZone: timeZoneSchema }),
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
- z4.object({ kind: z4.literal("webhook") }),
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
- z4.object({
227
- kind: z4.literal("github"),
228
- events: z4.array(githubTriggerKindSchema).min(1).max(GITHUB_TRIGGER_KINDS.length),
229
- unfollowed: z4.boolean().optional(),
230
- repos: z4.array(
231
- z4.string().trim().regex(/^[A-Za-z0-9-]{1,39}\/[A-Za-z0-9._-]{1,100}$/, "Name each repo as owner/name.")
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 = z4.discriminatedUnion("kind", [
237
- z4.object({ kind: z4.literal("direct") }),
238
- z4.object({ kind: z4.literal("channel"), channel: nonEmpty2.max(100) }),
239
- z4.object({ kind: z4.literal("conversation"), conversationId: nonEmpty2.max(100) })
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 = z4.discriminatedUnion("kind", [
242
- z4.object({ kind: z4.literal("direct") }),
243
- z4.object({
244
- kind: z4.literal("channel"),
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: z4.boolean()
247
+ isPrivate: z3.boolean()
248
248
  }),
249
- z4.object({ kind: z4.literal("conversation"), conversationId: nonEmpty2 })
249
+ z3.object({ kind: z3.literal("conversation"), conversationId: nonEmpty2 })
250
250
  ]);
251
251
  MAX_AUTOMATION_REPOS = 10;
252
- automationInputSchema = z4.object({
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: z4.array(nonEmpty2.max(300)).max(MAX_AUTOMATION_REPOS).optional(),
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 = z4.enum(["pending_approval", "active", "paused", "finished"]);
264
- firingOutcomeSchema = z4.enum([
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 z5 } from "zod";
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 = z5.enum(["slack"]);
310
- blockSchema = z5.looseObject({ type: z5.string().min(1) });
311
- blocksSchema = z5.array(blockSchema).min(1).max(MAX_LAYOUT_BLOCKS, `A message can have at most ${MAX_LAYOUT_BLOCKS} blocks.`).refine(
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 = z5.strictObject({
315
+ layoutSchema = z4.strictObject({
316
316
  platform: layoutPlatformSchema,
317
317
  blocks: blocksSchema
318
318
  });
319
- textBody = z5.string().max(
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 = z5.string().max(
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 = z5.string().trim().min(1).max(255);
328
- alt = z5.string().trim().min(1).max(1e3);
329
- channelTargetSchema = z5.string().trim().regex(/^(#[a-z0-9][a-z0-9._-]{0,79}|[CG][A-Z0-9]{2,})$/, {
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 = z5.strictObject({
332
+ herdMessageSchema = z4.strictObject({
333
333
  text: textBody.optional(),
334
334
  markdown: markdownBody.optional(),
335
335
  blocks: blocksSchema.optional(),
336
- files: z5.array(
337
- z5.strictObject({ path: z5.string().min(1), title: title.optional(), alt: alt.optional() })
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 = z5.strictObject({
341
+ sendMessageSchema = z4.strictObject({
342
342
  text: textBody.optional(),
343
343
  markdown: markdownBody.optional(),
344
344
  layout: layoutSchema.optional(),
345
- files: z5.array(
346
- z5.strictObject({
347
- id: z5.string().min(1).max(100),
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: z5.boolean().optional(),
353
+ quiet: z4.boolean().optional(),
354
354
  // Which client an agent sent it through, such as "Claude Code", recorded on the message.
355
- client: z5.string().trim().min(1).max(40).regex(/^[^\r\n]+$/).optional()
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 = z5.enum(["pending", "ready", "unavailable"]);
362
- messageFileSchema = z5.object({
363
- id: z5.string().min(1),
364
- name: z5.string().min(1),
365
- type: z5.string().min(1),
366
- size: z5.number().int().nonnegative(),
367
- title: z5.string().optional(),
368
- alt: z5.string().optional(),
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: z5.string().optional()
371
+ reason: z4.string().optional()
372
372
  });
373
- postTargetSchema = z5.object({
374
- place: z5.string().min(1),
375
- placeName: z5.string().min(1),
376
- conversationId: z5.string().min(1)
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 z6 } from "zod";
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 = z6.string().min(1);
400
+ nonEmpty3 = z5.string().min(1);
401
401
  MAX_EXTERNAL_TEXT = 4e3;
402
- subscriptionOriginSchema = z6.enum(["watch", "branch", "work"]);
403
- subscriptionEndSchema = z6.enum([
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 = z6.enum([
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 = z6.object({
418
- id: z6.number().int(),
417
+ githubSenderSchema = z5.object({
418
+ id: z5.number().int(),
419
419
  login: nonEmpty3,
420
- association: z6.string().optional(),
421
- bot: z6.boolean()
420
+ association: z5.string().optional(),
421
+ bot: z5.boolean()
422
422
  });
423
- githubEventSummarySchema = z6.object({
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: z6.string().optional(),
431
- url: z6.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: z6.string().max(MAX_EXTERNAL_TEXT).optional(),
435
- sha: z6.string().optional(),
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: z6.object({ name: nonEmpty3, conclusion: z6.string().optional() }).optional(),
438
- wakes: z6.boolean(),
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: z6.boolean().optional(),
441
+ outsider: z5.boolean().optional(),
442
442
  /** Set when its author is a GitHub account linked to the subscriber. */
443
- own: z6.boolean().optional(),
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: z6.boolean().optional(),
449
- repoId: z6.number().int().optional(),
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: z6.boolean().optional()
451
+ withheld: z5.boolean().optional()
452
452
  });
453
- subscriptionSchema = z6.object({
453
+ subscriptionSchema = z5.object({
454
454
  resource: nonEmpty3,
455
455
  label: nonEmpty3,
456
- url: z6.url(),
456
+ url: z5.url(),
457
457
  createdBy: subscriptionOriginSchema,
458
- createdAt: z6.number().int().nonnegative()
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 z7 } from "zod";
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 = z7.object({
485
- usedPercentage: z7.number().min(0).max(100),
486
- resetsAt: z7.number().int().nonnegative()
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 = z7.object({
493
+ usageSchema = z6.object({
494
494
  fiveHour: usageWindowSchema.optional(),
495
495
  sevenDay: usageWindowSchema.optional(),
496
- agent: z7.enum(["claude-code", "codex", "agy"]).optional()
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 = z7.string().trim().min(1).max(MAX_ACTIVITY_LENGTH).regex(/^[^\r\n]+$/);
499
+ activityTextSchema = z6.string().trim().min(1).max(MAX_ACTIVITY_LENGTH).regex(/^[^\r\n]+$/);
500
500
  MAX_TITLE_LENGTH = 40;
501
- titleSchema = z7.string().trim().min(1).max(MAX_TITLE_LENGTH).regex(/^[^\r\n]+$/);
502
- listedWindowSchema = z7.union([
501
+ titleSchema = z6.string().trim().min(1).max(MAX_TITLE_LENGTH).regex(/^[^\r\n]+$/);
502
+ listedWindowSchema = z6.union([
503
503
  usageWindowSchema,
504
- z7.object({ reset: z7.literal(true), resetsAt: z7.number().int().nonnegative() })
504
+ z6.object({ reset: z6.literal(true), resetsAt: z6.number().int().nonnegative() })
505
505
  ]);
506
- listedUsageSchema = z7.object({
506
+ listedUsageSchema = z6.object({
507
507
  fiveHour: listedWindowSchema.optional(),
508
508
  sevenDay: listedWindowSchema.optional(),
509
- agent: z7.enum(["claude-code", "codex", "agy"]).optional()
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 z8 } from "zod";
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 = z8.enum(CAPABILITIES);
551
+ capabilitySchema = z7.enum(CAPABILITIES);
552
552
  PLATFORMS = ["macos", "linux", "windows"];
553
- platformSchema = z8.enum(PLATFORMS);
553
+ platformSchema = z7.enum(PLATFORMS);
554
554
  TOOLS = ["xcode", "gpu"];
555
- toolSchema = z8.enum(TOOLS);
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 = z8.string().trim().min(1).max(PHRASE_MAX, `at most ${PHRASE_MAX} characters`);
574
- phrases = z8.array(phrase).max(PHRASES_MAX, `at most ${PHRASES_MAX} 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 = z8.enum(SHARES);
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 = z8.object({
583
+ harnessConfigSchema = z7.object({
584
584
  share: shareSchema.optional(),
585
585
  /** Read as `share: "off"` when false, from files written before shares. */
586
- enabled: z8.boolean().optional(),
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: z8.boolean().optional(),
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: z8.number().int().min(-100).max(100).optional()
598
+ priority: z7.number().int().min(-100).max(100).optional()
599
599
  }).strict();
600
600
  BUILDS_MAX = 4;
601
- buildsSettingSchema = z8.union([
602
- z8.literal(true),
603
- z8.object({ max: z8.number().int().min(1).max(BUILDS_MAX) }).strict()
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 = z8.object({
607
- remote: z8.string().trim().min(1).max(300),
608
- about: z8.string().trim().max(PHRASE_MAX, `at most ${PHRASE_MAX} characters`).optional()
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 = z8.object({
611
- about: z8.string().trim().max(ABOUT_MAX, `at most ${ABOUT_MAX} characters`).optional(),
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: z8.record(z8.string().regex(/^[a-z][a-z0-9-]*$/), harnessConfigSchema).optional(),
615
+ harnesses: z7.record(z7.string().regex(/^[a-z][a-z0-9-]*$/), harnessConfigSchema).optional(),
616
616
  builds: buildsSettingSchema.optional(),
617
- repos: z8.array(configRepoSchema).max(CONFIG_REPOS_MAX, `at most ${CONFIG_REPOS_MAX} repos`).optional()
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 = z8.object({
669
- statement: z8.string().min(1),
670
- level: z8.enum(PROFILE_LEVELS),
671
- source: z8.enum(["default", "owner"])
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 = z8.object({
674
- key: z8.string().min(1),
675
- name: z8.string().min(1),
676
- machineId: z8.string().min(1),
677
- machineName: z8.string().min(1),
678
- agent: z8.string().min(1),
679
- capabilities: z8.array(capabilitySchema),
680
- about: z8.string().optional(),
681
- only: z8.array(z8.string()),
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: z8.array(profileEntrySchema),
684
- priority: z8.number().int(),
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: z8.boolean(),
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: z8.boolean(),
689
+ activated: z7.boolean(),
690
690
  activation: agentActivationSchema.optional(),
691
- online: z8.boolean(),
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: z8.array(
694
- z8.object({ name: z8.string(), remote: z8.string(), cloned: z8.boolean().optional() })
693
+ repos: z7.array(
694
+ z7.object({ name: z7.string(), remote: z7.string(), cloned: z7.boolean().optional() })
695
695
  ),
696
- machineCreatedAt: z8.number().int().nonnegative()
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 z9 } from "zod";
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 = z9.string().min(1);
712
- time2 = z9.number().int().nonnegative();
713
- terminalStateSchema = z9.enum([
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 = z9.enum(["working", "idle", "waiting_on_someone", "exited"]);
722
- machineRepoSchema = z9.object({
721
+ agentStatusSchema = z8.enum(["working", "idle", "waiting_on_someone", "exited"]);
722
+ machineRepoSchema = z8.object({
723
723
  name: nonEmpty4,
724
724
  remote: nonEmpty4,
725
- cloned: z9.boolean().optional()
725
+ cloned: z8.boolean().optional()
726
726
  });
727
727
  isCloned = (repo) => repo.cloned !== false;
728
- machineCliSchema = z9.object({
728
+ machineCliSchema = z8.object({
729
729
  name: nonEmpty4,
730
730
  version: nonEmpty4,
731
- runnable: z9.boolean().optional(),
732
- capabilities: z9.array(capabilitySchema).optional(),
731
+ runnable: z8.boolean().optional(),
732
+ capabilities: z8.array(capabilitySchema).optional(),
733
733
  activation: agentActivationSchema.optional()
734
734
  });
735
- machineRegistrationSchema = z9.object({
735
+ machineRegistrationSchema = z8.object({
736
736
  id: nonEmpty4,
737
737
  name: nonEmpty4,
738
- repos: z9.array(machineRepoSchema),
739
- clis: z9.array(machineCliSchema),
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: z9.array(toolSchema).optional(),
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: z9.string().max(1e3).optional(),
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: z9.boolean(),
751
+ online: z8.boolean(),
752
752
  lastSeenAt: time2,
753
753
  createdAt: time2
754
754
  });
755
- machinePresenceSchema = z9.object({ name: nonEmpty4, online: z9.boolean() });
756
- worktreeSchema = z9.object({ repo: nonEmpty4, branch: nonEmpty4 });
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 = z9.object({
758
+ repoHintSchema = z8.object({
759
759
  remote: nonEmpty4,
760
760
  branch: nonEmpty4.optional(),
761
761
  folder: nonEmpty4.optional()
762
762
  });
763
- terminalSchema = z9.object({
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: z9.boolean(),
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 = z9.object({
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: z9.array(repoHintSchema).max(MAX_REPO_HINTS).optional(),
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: z9.boolean().optional()
791
+ handoff: z8.boolean().optional()
792
792
  });
793
- offerAnswerSchema = z9.discriminatedUnion("answer", [
794
- z9.object({ answer: z9.literal("accept") }),
795
- z9.object({ answer: z9.literal("refuse"), reason: nonEmpty4 })
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 = z9.discriminatedUnion("type", [
798
- z9.object({ type: z9.literal("offer"), offer: offerSchema }),
799
- z9.object({
800
- type: z9.literal("message"),
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: z9.enum(["interrupt", "defer"])
802
+ delivery: z8.enum(["interrupt", "defer"])
803
803
  }),
804
- z9.object({ type: z9.literal("reconnect") }),
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
- z9.object({ type: z9.literal("sign_in"), signInId: nonEmpty4, tool: signInToolSchema })
806
+ z8.object({ type: z8.literal("sign_in"), signInId: nonEmpty4, tool: signInToolSchema })
807
807
  ]);
808
- machineMessageSchema = z9.discriminatedUnion("type", [
809
- z9.object({ type: z9.literal("ack"), conversationId: nonEmpty4 }),
810
- z9.object({
811
- type: z9.literal("usage"),
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 z10 } from "zod";
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 = z10.string().min(1);
829
- id = z10.string().regex(/^[A-Za-z0-9_-]{1,40}$/).describe("Short, so it fits in a button's value and action ID");
830
- promptKindSchema = z10.enum(["permission", "question", "plan", "automation"]);
831
- promptOptionSchema = z10.object({
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: z10.string().trim().min(1).max(75),
834
- description: z10.string().max(200).optional(),
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: z10.enum(["primary", "danger"]).optional()
836
+ style: z9.enum(["primary", "danger"]).optional()
837
837
  });
838
- promptQuestionSchema = z10.object({
838
+ promptQuestionSchema = z9.object({
839
839
  id,
840
- text: z10.string().trim().min(1).max(300),
841
- options: z10.array(promptOptionSchema).min(1).max(10)
840
+ text: z9.string().trim().min(1).max(300),
841
+ options: z9.array(promptOptionSchema).min(1).max(10)
842
842
  });
843
- promptRequestSchema = z10.object({
843
+ promptRequestSchema = z9.object({
844
844
  kind: promptKindSchema,
845
- title: z10.string().trim().min(1).max(150),
846
- detail: z10.string().max(2800).optional(),
847
- questions: z10.array(promptQuestionSchema).min(1).max(4)
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 = z10.enum(["answered", "cancelled"]);
849
+ promptOutcomeSchema = z9.enum(["answered", "cancelled"]);
850
850
  }
851
851
  });
852
852
 
853
853
  // ../common-chat/src/pull-requests.ts
854
- import { z as z11 } from "zod";
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 = z11.number().int().nonnegative();
894
- pullRequestPhaseSchema = z11.enum([
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 = z11.enum(["you", "agent", "others", "nobody"]);
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 = z11.object({
917
+ leadChangeSchema = z10.object({
918
918
  /** Its repo and number, such as `api#104`, or "a pull request" when hidden. */
919
- label: z11.string().min(1),
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: z11.number().int().nonnegative(),
924
+ moreForYou: z10.number().int().nonnegative(),
925
925
  /** Absent when hidden. */
926
- url: z11.string().optional()
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 z12 } from "zod";
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 = z12.number().int().nonnegative();
948
- workKindSchema = z12.enum(["change", "ticket", "deploy", "document", "other"]);
949
- workStatusSchema = z12.enum(["open", "done", "closed"]);
950
- workSourceSchema = z12.enum(["agent", "provider"]);
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 = z12.object({
955
- url: z12.string().min(1).max(MAX_WORK_URL),
954
+ workObjectSchema = z11.object({
955
+ url: z11.string().min(1).max(MAX_WORK_URL),
956
956
  kind: workKindSchema,
957
- title: z12.string().min(1).max(MAX_WORK_TITLE),
957
+ title: z11.string().min(1).max(MAX_WORK_TITLE),
958
958
  status: workStatusSchema,
959
- detail: z12.string().max(MAX_WORK_DETAIL).nullable(),
959
+ detail: z11.string().max(MAX_WORK_DETAIL).nullable(),
960
960
  /** Whether the conversation made it, rather than only being about it. */
961
- made: z12.boolean(),
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: z12.string().min(1).optional()
969
+ conversationId: z11.string().min(1).optional()
970
970
  });
971
- workChangeSchema = z12.object({
972
- url: z12.string().trim().min(1).max(MAX_WORK_URL),
971
+ workChangeSchema = z11.object({
972
+ url: z11.string().trim().min(1).max(MAX_WORK_URL),
973
973
  kind: workKindSchema.optional(),
974
- title: z12.string().trim().min(1).max(2e3).optional(),
974
+ title: z11.string().trim().min(1).max(2e3).optional(),
975
975
  status: workStatusSchema.optional(),
976
- detail: z12.string().trim().max(2e3).nullable().optional(),
977
- made: z12.boolean().optional(),
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 = z12.enum([
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 = z12.object({
992
+ workObjectSummarySchema = z11.object({
993
993
  kind: workKindSchema,
994
994
  status: workStatusSchema,
995
- made: z12.boolean(),
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: z12.string().optional(),
1001
- title: z12.string().optional(),
1002
- detail: z12.string().nullable().optional(),
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: z12.string().min(1).optional()
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 z13 } from "zod";
1010
+ import { z as z12 } from "zod";
1011
1011
  function event(type, payload) {
1012
- return z13.object({ ...eventBase, type: z13.literal(type), payload: z13.object(payload) });
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 = z13.enum(["direct", "mention", "joined"]);
1027
- deliveryModeSchema = z13.enum(["interrupt", "defer"]);
1028
- eventSourceSchema = z13.enum(["slack", "discord", "web", "api", "cli", "mcp", "system"]);
1029
- nonEmpty6 = z13.string().min(1);
1030
- actorSchema = z13.discriminatedUnion("kind", [
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
- z13.object({ kind: z13.literal("person"), id: nonEmpty6, name: nonEmpty6 }),
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
- z13.object({
1035
- kind: z13.literal("account"),
1034
+ z12.object({
1035
+ kind: z12.literal("account"),
1036
1036
  provider: nonEmpty6,
1037
1037
  tenant: nonEmpty6,
1038
1038
  subject: nonEmpty6,
1039
- name: z13.string().optional(),
1040
- isBot: z13.boolean()
1039
+ name: z12.string().optional(),
1040
+ isBot: z12.boolean()
1041
1041
  }),
1042
- z13.object({ kind: z13.literal("system") })
1042
+ z12.object({ kind: z12.literal("system") })
1043
1043
  ]);
1044
1044
  eventBase = {
1045
- seq: z13.number().int().positive(),
1045
+ seq: z12.number().int().positive(),
1046
1046
  source: eventSourceSchema,
1047
1047
  actor: actorSchema,
1048
- createdAt: z13.number().int().nonnegative()
1048
+ createdAt: z12.number().int().nonnegative()
1049
1049
  };
1050
- entryIds = z13.array(nonEmpty6);
1051
- routingRecordSchema = z13.object({
1052
- eligible: z13.array(z13.object({ key: nonEmpty6, name: nonEmpty6 })),
1053
- questions: z13.array(
1054
- z13.object({
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: z13.number().min(0).max(1).nullable()
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: z13.string().optional(),
1063
- removed: z13.array(z13.object({ key: nonEmpty6, name: nonEmpty6, rule: nonEmpty6 })),
1064
- order: z13.array(nonEmpty6),
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: z13.array(
1068
- z13.object({
1067
+ fits: z12.array(
1068
+ z12.object({
1069
1069
  key: nonEmpty6,
1070
- fit: z13.number().min(0).max(1),
1071
- statement: z13.string().optional(),
1072
- level: z13.enum(["great", "good", "okay"]).optional()
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: z13.array(z13.string()).optional(),
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: z13.array(nonEmpty6).optional(),
1080
- warm: z13.array(nonEmpty6).optional(),
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: z13.array(
1084
- z13.object({
1083
+ shares: z12.array(
1084
+ z12.object({
1085
1085
  key: nonEmpty6,
1086
1086
  share: shareSchema,
1087
- pacing: z13.enum(["ahead", "even", "under", "unknown"]),
1088
- weight: z13.number().nonnegative()
1087
+ pacing: z12.enum(["ahead", "even", "under", "unknown"]),
1088
+ weight: z12.number().nonnegative()
1089
1089
  })
1090
1090
  ).optional(),
1091
- drawn: z13.array(nonEmpty6).optional()
1091
+ drawn: z12.array(nonEmpty6).optional()
1092
1092
  });
1093
- conversationEventSchema = z13.discriminatedUnion("type", [
1093
+ conversationEventSchema = z12.discriminatedUnion("type", [
1094
1094
  event("message.created", {
1095
1095
  messageId: nonEmpty6,
1096
- text: z13.string(),
1097
- direction: z13.enum(["inbound", "outbound"]),
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: z13.string().optional(),
1100
+ reason: z12.string().optional(),
1101
1101
  // Loaded from before the conversation joined the thread, so it never waits for a response.
1102
- isContext: z13.boolean().optional(),
1102
+ isContext: z12.boolean().optional(),
1103
1103
  // Set when the message was deleted on its platform. `text` is then empty.
1104
- deleted: z13.boolean().optional(),
1104
+ deleted: z12.boolean().optional(),
1105
1105
  // Sent through the API but kept out of the platform, so only clients see it.
1106
- quiet: z13.boolean().optional(),
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: z13.string().optional(),
1108
+ client: z12.string().optional(),
1109
1109
  // How to read `text`. Absent means plain text, as every message before this field was.
1110
- format: z13.enum(["markdown"]).optional(),
1110
+ format: z12.enum(["markdown"]).optional(),
1111
1111
  // Files attached to it, kept with the conversation.
1112
- files: z13.array(messageFileSchema).optional(),
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: z13.object({ platform: layoutPlatformSchema, blocks: z13.array(z13.unknown()) }).optional(),
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: z13.object({ conversationId: nonEmpty6.optional() }).optional(),
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: z13.object({ parent: nonEmpty6, by: nonEmpty6 }).optional(),
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: z13.object({
1130
+ agentMessage: z12.object({
1131
1131
  from: nonEmpty6,
1132
1132
  worker: nonEmpty6,
1133
- posted: z13.boolean().optional(),
1134
- overdue: z13.boolean().optional(),
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: z13.boolean().optional(),
1137
- outsideTree: z13.boolean().optional()
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: z13.object({ id: nonEmpty6, worker: nonEmpty6, for: nonEmpty6 }).optional(),
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: z13.object({
1143
+ automation: z12.object({
1144
1144
  id: nonEmpty6,
1145
1145
  name: nonEmpty6,
1146
1146
  reason: nonEmpty6,
1147
1147
  key: nonEmpty6,
1148
- payload: z13.string().optional(),
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: z13.string() }),
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: z13.number().int().positive(),
1162
- outcome: z13.enum(["for_bot", "not_for_bot", "failed"]),
1163
- probability: z13.number().min(0).max(1).optional(),
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: z13.string().optional()
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: z13.number().int().positive(),
1173
- outcome: z13.enum(["asks", "doesnt_ask", "failed"]),
1174
- probability: z13.number().min(0).max(1).optional(),
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: z13.string().optional()
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: z13.number().int().positive(),
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: z13.number().int()
1195
+ expiresAt: z12.number().int()
1196
1196
  }),
1197
- event("mailbox.renewed", { claimId: nonEmpty6, expiresAt: z13.number().int() }),
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: z13.enum(["released", "expired", "delegates"])
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: z13.enum(["passed"]).optional()
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: z13.array(nonEmpty6).optional()
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: z13.array(workFieldSchema),
1235
- added: z13.boolean(),
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: z13.object({ id: nonEmpty6, worker: nonEmpty6, promptId: nonEmpty6 }).optional()
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: z13.string().optional()
1257
+ text: z12.string().optional()
1258
1258
  }),
1259
1259
  event("prompt.closed", {
1260
1260
  promptId: nonEmpty6,
1261
1261
  outcome: promptOutcomeSchema,
1262
- reason: z13.string().optional()
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: z13.array(nonEmpty6),
1287
- routed: z13.boolean()
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: z13.boolean() }),
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: z13.boolean(),
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: z13.string().max(1e3).optional()
1310
+ fetchFailed: z12.string().max(1e3).optional()
1311
1311
  }),
1312
- event("terminal.exited", { terminalId: nonEmpty6, exitCode: z13.number().int().nullable() }),
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: z13.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 = z13.enum(["public", "private"]);
1335
- conversationStatusSchema = z13.enum(["idle", "waiting", "working"]);
1336
- conversationSummarySchema = z13.object({
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: z13.string().nullable(),
1342
+ placeUrl: z12.string().nullable(),
1343
1343
  status: conversationStatusSchema,
1344
- waitingCount: z13.number().int().nonnegative(),
1345
- createdAt: z13.number().int(),
1346
- lastActivityAt: z13.number().int(),
1347
- expiresAt: z13.number().int()
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 = z13.discriminatedUnion("kind", [
1350
- z13.object({
1351
- kind: z13.literal("bound"),
1352
- machine: z13.object({ name: nonEmpty6, online: z13.boolean() }),
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
- z13.object({ kind: z13.literal("waiting_for_machine") }),
1357
- z13.object({ kind: z13.literal("author_not_linked") })
1356
+ z12.object({ kind: z12.literal("waiting_for_machine") }),
1357
+ z12.object({ kind: z12.literal("author_not_linked") })
1358
1358
  ]);
1359
- treeSummarySchema = z13.object({
1359
+ treeSummarySchema = z12.object({
1360
1360
  parent: nonEmpty6.nullable(),
1361
1361
  root: nonEmpty6,
1362
- children: z13.array(
1363
- z13.object({
1362
+ children: z12.array(
1363
+ z12.object({
1364
1364
  id: nonEmpty6,
1365
1365
  title: nonEmpty6,
1366
- state: z13.string().nullable(),
1367
- createdAt: z13.number()
1366
+ state: z12.string().nullable(),
1367
+ createdAt: z12.number()
1368
1368
  })
1369
1369
  )
1370
1370
  });
1371
- conversationSnapshotSchema = z13.object({
1371
+ conversationSnapshotSchema = z12.object({
1372
1372
  conversation: conversationSummarySchema,
1373
- events: z13.array(conversationEventSchema),
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: z13.record(z13.string(), z13.string()).optional(),
1378
+ people: z12.record(z12.string(), z12.string()).optional(),
1379
1379
  placement: placementSchema.nullable().optional(),
1380
1380
  tree: treeSummarySchema.optional()
1381
1381
  });
1382
- liveFrameSchema = z13.discriminatedUnion("type", [
1383
- z13.object({ type: z13.literal("event"), event: conversationEventSchema }),
1384
- z13.object({ type: z13.literal("reconnect") }),
1385
- z13.object({ type: z13.literal("expired") })
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 = z13.object({
1388
- messages: z13.enum(["push", "window"]),
1389
- edits: z13.enum(["push", "rescan"]),
1390
- deletes: z13.enum(["push", "rescan"]),
1391
- reactions: z13.enum(["push", "counts"]),
1392
- status: z13.boolean(),
1393
- search: z13.boolean()
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 z14 } from "zod";
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 = z14.string().min(1);
1437
- time5 = z14.number().int().nonnegative();
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 = z14.enum([
1446
+ conversationStateSchema = z13.enum([
1447
1447
  "waiting",
1448
1448
  "working",
1449
1449
  "stuck",
1450
1450
  "unanswered",
1451
1451
  "done"
1452
1452
  ]);
1453
- stuckReasonSchema = z14.enum([
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 = z14.enum(["channel", "direct", "group", "web"]);
1471
- conversationSourceSchema = z14.object({
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: z14.string().optional()
1475
+ name: z13.string().optional()
1476
1476
  });
1477
1477
  LATEST_MESSAGE_LENGTH = 200;
1478
- latestMessageSchema = z14.object({
1479
- text: z14.string().max(LATEST_MESSAGE_LENGTH),
1478
+ latestMessageSchema = z13.object({
1479
+ text: z13.string().max(LATEST_MESSAGE_LENGTH),
1480
1480
  /** A person wrote it, or the agent did. */
1481
- from: z14.enum(["person", "agent"]),
1481
+ from: z13.enum(["person", "agent"]),
1482
1482
  at: time5
1483
1483
  });
1484
1484
  listMachineSchema = machinePresenceSchema.extend({
1485
- mine: z14.boolean().optional(),
1485
+ mine: z13.boolean().optional(),
1486
1486
  /** The agent holding it on that machine, such as `Claude Code`, when it's known. */
1487
- agent: z14.string().optional()
1487
+ agent: z13.string().optional()
1488
1488
  });
1489
- conversationListItemSchema = z14.object({
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: z14.string().nullable(),
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: z14.string().nullable(),
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: z14.string().nullable(),
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: z14.boolean().optional(),
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: z14.array(workObjectSummarySchema).optional(),
1522
+ work: z13.array(workObjectSummarySchema).optional(),
1523
1523
  /** How many more work objects it holds than `work` carries. */
1524
- moreWork: z14.number().int().nonnegative().optional(),
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 = z14.object({
1529
- items: z14.array(conversationListItemSchema),
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: z14.string().optional()
1531
+ next: z13.string().optional()
1532
1532
  });
1533
- listFrameSchema = z14.discriminatedUnion("type", [
1534
- z14.object({ type: z14.literal("changed"), conversations: z14.array(nonEmpty7).min(1) }),
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
- z14.object({ type: z14.literal("machines") }),
1537
- z14.object({ type: z14.literal("reconnect") }),
1538
- z14.object({ type: z14.literal("expired") })
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 z15 } from "zod";
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 = z15.string().min(1);
1587
- time6 = z15.number().int().nonnegative();
1586
+ nonEmpty8 = z14.string().min(1);
1587
+ time6 = z14.number().int().nonnegative();
1588
1588
  BOARD_ITEMS = 8;
1589
- boardItemSchema = z15.object({
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: z15.string().nullable(),
1596
+ source: z14.string().nullable(),
1597
1597
  /** What the agent says it's doing, while it works. */
1598
- activity: z15.string().nullable(),
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: z15.object({ machine: nonEmpty8, agent: nonEmpty8 }).nullable().optional(),
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: z15.boolean().optional()
1604
+ hidden: z14.boolean().optional()
1605
1605
  });
1606
- boardWorkerSchema = z15.object({
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: z15.array(z15.string().min(1).max(100)).max(3).optional()
1615
+ strengths: z14.array(z14.string().min(1).max(100)).max(3).optional()
1616
1616
  });
1617
- boardMachineSchema = z15.object({
1617
+ boardMachineSchema = z14.object({
1618
1618
  name: nonEmpty8,
1619
- online: z15.boolean(),
1620
- workers: z15.array(boardWorkerSchema).max(8)
1619
+ online: z14.boolean(),
1620
+ workers: z14.array(boardWorkerSchema).max(8)
1621
1621
  });
1622
- boardSchema = z15.object({
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: z15.object({
1625
- stuck: z15.number().int().nonnegative(),
1626
- unanswered: z15.number().int().nonnegative(),
1627
- waiting: z15.number().int().nonnegative(),
1628
- working: z15.number().int().nonnegative(),
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: z15.number().int().nonnegative().optional()
1630
+ pullRequests: z14.number().int().nonnegative().optional()
1631
1631
  }),
1632
1632
  /** How many became `done` in the last 24 hours. */
1633
- doneToday: z15.number().int().nonnegative(),
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: z15.array(boardItemSchema).max(BOARD_ITEMS),
1639
- machines: z15.array(boardMachineSchema).max(16),
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: z15.string().regex(/^[0-9a-f]{12}$/),
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,44 @@ 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, 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
+ START_COMMAND = `npx ${FRIDAY_PACKAGE} start`;
1655
1658
  }
1656
1659
  });
1657
1660
 
1658
1661
  // ../common-chat/src/builds.ts
1659
- import { z as z16 } from "zod";
1662
+ import { z as z15 } from "zod";
1660
1663
  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
1664
  var init_builds = __esm({
1662
1665
  "../common-chat/src/builds.ts"() {
1663
1666
  "use strict";
1664
1667
  init_define_HERD_PACKAGE();
1665
1668
  init_workers();
1666
- nonEmpty9 = z16.string().min(1);
1667
- time7 = z16.number().int().nonnegative();
1669
+ nonEmpty9 = z15.string().min(1);
1670
+ time7 = z15.number().int().nonnegative();
1668
1671
  BUILD_LEASE_MS = 5 * 60 * 1e3;
1669
1672
  BUILD_CLAIM_WINDOW_MS = 15 * 1e3;
1670
1673
  MAX_LOG_CHUNK_BYTES = 256 * 1024;
1671
1674
  MAX_LOG_BYTES = 5 * 1024 * 1024;
1672
1675
  MAX_NODE_MODULES_PART_BYTES = 95 * 1024 * 1024;
1673
- shaSchema = z16.string().regex(/^[0-9a-f]{40}$/);
1674
- buildOfferSchema = z16.object({
1676
+ shaSchema = z15.string().regex(/^[0-9a-f]{40}$/);
1677
+ buildOfferSchema = z15.object({
1675
1678
  id: nonEmpty9,
1676
1679
  offerId: nonEmpty9,
1677
1680
  repo: nonEmpty9,
1678
1681
  sha: shaSchema,
1679
1682
  ref: nonEmpty9,
1680
- main: z16.boolean(),
1683
+ main: z15.boolean(),
1681
1684
  expiresAt: time7
1682
1685
  });
1683
- buildCancelReasonSchema = z16.enum([
1686
+ buildCancelReasonSchema = z15.enum([
1684
1687
  // A newer push to the same branch replaced it.
1685
1688
  "superseded",
1686
1689
  // The branch was deleted.
@@ -1690,7 +1693,7 @@ var init_builds = __esm({
1690
1693
  // Stopped for another reason, such as the repo being removed.
1691
1694
  "cancelled"
1692
1695
  ]);
1693
- runnerMessageSchema = z16.discriminatedUnion("type", [
1696
+ runnerMessageSchema = z15.discriminatedUnion("type", [
1694
1697
  /**
1695
1698
  * Sent first, and again whenever any of it changes. `capacity` comes from `herd.config.ts`'s
1696
1699
  * `builds` through `runnerCapacity`, `repos` are the normalized remotes of the repos herd has
@@ -1698,82 +1701,82 @@ var init_builds = __esm({
1698
1701
  * any of its owner's repos, cloning one it hasn't got, and `repos` only puts it first for those.
1699
1702
  * A daemon from before herd's root sent its configured checkouts here, which it builds from.
1700
1703
  */
1701
- z16.object({
1702
- type: z16.literal("hello"),
1704
+ z15.object({
1705
+ type: z15.literal("hello"),
1703
1706
  /** How many builds at once. 0 when the machine can't sandbox a build, so it takes none. */
1704
- capacity: z16.number().int().min(0).max(BUILDS_MAX),
1705
- repos: z16.array(nonEmpty9.max(300)).max(100),
1706
- running: z16.array(nonEmpty9.max(100)).max(BUILDS_MAX * 2)
1707
+ capacity: z15.number().int().min(0).max(BUILDS_MAX),
1708
+ repos: z15.array(nonEmpty9.max(300)).max(100),
1709
+ running: z15.array(nonEmpty9.max(100)).max(BUILDS_MAX * 2)
1707
1710
  }),
1708
1711
  /** An answer to an offer, before its `expiresAt`. A refusal may say why. */
1709
- z16.object({
1710
- type: z16.literal("answer"),
1712
+ z15.object({
1713
+ type: z15.literal("answer"),
1711
1714
  buildId: nonEmpty9,
1712
1715
  offerId: nonEmpty9,
1713
- answer: z16.enum(["accept", "refuse"]),
1714
- reason: z16.string().max(500).optional()
1716
+ answer: z15.enum(["accept", "refuse"]),
1717
+ reason: z15.string().max(500).optional()
1715
1718
  })
1716
1719
  ]);
1717
- serviceMessageSchema = z16.discriminatedUnion("type", [
1718
- z16.object({ type: z16.literal("build"), build: buildOfferSchema }),
1720
+ serviceMessageSchema = z15.discriminatedUnion("type", [
1721
+ z15.object({ type: z15.literal("build"), build: buildOfferSchema }),
1719
1722
  /** An accepted offer: the build's own secret, and how long its claim lasts between renewals. */
1720
- z16.object({
1721
- type: z16.literal("accepted"),
1723
+ z15.object({
1724
+ type: z15.literal("accepted"),
1722
1725
  buildId: nonEmpty9,
1723
1726
  secret: nonEmpty9,
1724
- leaseMs: z16.number().int().positive()
1727
+ leaseMs: z15.number().int().positive()
1725
1728
  }),
1726
1729
  /**
1727
1730
  * Stop a build this runner holds, within 5 seconds. An accept that came too late, for an offer
1728
1731
  * that had expired or was withdrawn, gets this too, with the reason `cancelled`.
1729
1732
  */
1730
- z16.object({ type: z16.literal("build-cancel"), buildId: nonEmpty9, reason: buildCancelReasonSchema }),
1733
+ z15.object({ type: z15.literal("build-cancel"), buildId: nonEmpty9, reason: buildCancelReasonSchema }),
1731
1734
  /** Connect again. Sent before the service closes a socket that another replaced. */
1732
- z16.object({ type: z16.literal("reconnect") })
1735
+ z15.object({ type: z15.literal("reconnect") })
1733
1736
  ]);
1734
- runnerRegisterRequestSchema = z16.object({ name: z16.string().trim().min(1).max(100) });
1735
- runnerRegisterResponseSchema = z16.object({
1737
+ runnerRegisterRequestSchema = z15.object({ name: z15.string().trim().min(1).max(100) });
1738
+ runnerRegisterResponseSchema = z15.object({
1736
1739
  /** Shown to the owner, so they can match the approval page to the machine. */
1737
1740
  code: nonEmpty9,
1738
1741
  /** The page the owner opens, signed in, to approve it. */
1739
- approveUrl: z16.url(),
1742
+ approveUrl: z15.url(),
1740
1743
  /** Sent to `POST /runners/register/poll`. Only this machine has it. */
1741
1744
  pollToken: nonEmpty9,
1742
1745
  expiresAt: time7.optional(),
1743
1746
  /** How often to poll. */
1744
- pollMs: z16.number().int().positive().optional()
1747
+ pollMs: z15.number().int().positive().optional()
1745
1748
  });
1746
- runnerPollRequestSchema = z16.object({ pollToken: nonEmpty9.max(200) });
1747
- runnerPollResponseSchema = z16.discriminatedUnion("status", [
1748
- z16.object({ status: z16.literal("waiting") }),
1749
+ runnerPollRequestSchema = z15.object({ pollToken: nonEmpty9.max(200) });
1750
+ runnerPollResponseSchema = z15.discriminatedUnion("status", [
1751
+ z15.object({ status: z15.literal("waiting") }),
1749
1752
  /** Approved. The key is returned this once, and the service keeps only its hash. */
1750
- z16.object({ status: z16.literal("approved"), runnerId: nonEmpty9, key: nonEmpty9 }),
1753
+ z15.object({ status: z15.literal("approved"), runnerId: nonEmpty9, key: nonEmpty9 }),
1751
1754
  /** Expired, or the key was already collected. Start again. */
1752
- z16.object({ status: z16.literal("expired") })
1755
+ z15.object({ status: z15.literal("expired") })
1753
1756
  ]);
1754
- buildStepSchema = z16.object({
1755
- label: z16.string().min(1).max(200),
1756
- key: z16.string().regex(/^[0-9a-zA-Z_-]{8,128}$/),
1757
- status: z16.enum(["passed", "failed", "remembered"]),
1758
- ms: z16.number().int().nonnegative(),
1757
+ buildStepSchema = z15.object({
1758
+ label: z15.string().min(1).max(200),
1759
+ key: z15.string().regex(/^[0-9a-zA-Z_-]{8,128}$/),
1760
+ status: z15.enum(["passed", "failed", "remembered"]),
1761
+ ms: z15.number().int().nonnegative(),
1759
1762
  /** Only some of the step's tests ran, so its pass isn't shared. */
1760
- partial: z16.boolean().default(false),
1761
- budgetMs: z16.number().int().positive().nullable().default(null)
1763
+ partial: z15.boolean().default(false),
1764
+ budgetMs: z15.number().int().positive().nullable().default(null)
1762
1765
  });
1763
- buildFinishSchema = z16.object({
1764
- status: z16.enum(["success", "failure", "error"]),
1765
- summary: z16.string().max(2e3).default(""),
1766
- deployed: z16.boolean().default(false)
1766
+ buildFinishSchema = z15.object({
1767
+ status: z15.enum(["success", "failure", "error"]),
1768
+ summary: z15.string().max(2e3).default(""),
1769
+ deployed: z15.boolean().default(false)
1767
1770
  });
1768
- sharedPassSchema = z16.object({
1771
+ sharedPassSchema = z15.object({
1769
1772
  step: nonEmpty9,
1770
1773
  passedAt: time7,
1771
1774
  sha: nonEmpty9,
1772
1775
  runner: nonEmpty9,
1773
- partial: z16.boolean()
1776
+ partial: z15.boolean()
1774
1777
  });
1775
- passesResponseSchema = z16.object({ passes: z16.record(z16.string(), sharedPassSchema) });
1776
- deployCredentialsSchema = z16.object({
1778
+ passesResponseSchema = z15.object({ passes: z15.record(z15.string(), sharedPassSchema) });
1779
+ deployCredentialsSchema = z15.object({
1777
1780
  cloudflareToken: nonEmpty9,
1778
1781
  /** Publishes `@herdingchats/friday`. Missing when the build service has none set. */
1779
1782
  npmToken: nonEmpty9.optional(),
@@ -1782,20 +1785,20 @@ var init_builds = __esm({
1782
1785
  /** `owner/name`, for moving `deployed`. */
1783
1786
  repo: nonEmpty9,
1784
1787
  /** The commit being built, which `deployed` moves to. Older services don't send it. */
1785
- sha: z16.string().regex(/^[0-9a-f]{40}$/).optional(),
1788
+ sha: z15.string().regex(/^[0-9a-f]{40}$/).optional(),
1786
1789
  /** Each Worker's key at its last successful deploy. */
1787
- lastDeployed: z16.record(z16.string(), z16.string())
1790
+ lastDeployed: z15.record(z15.string(), z15.string())
1788
1791
  });
1789
- deployedSchema = z16.object({
1790
- worker: z16.string().regex(/^[a-z][a-z0-9-]{0,62}$/),
1791
- key: z16.string().regex(/^[0-9a-zA-Z_-]{8,128}$/)
1792
+ deployedSchema = z15.object({
1793
+ worker: z15.string().regex(/^[a-z][a-z0-9-]{0,62}$/),
1794
+ key: z15.string().regex(/^[0-9a-zA-Z_-]{8,128}$/)
1792
1795
  });
1793
- healthSchema = z16.object({ ok: z16.boolean(), version: z16.string() });
1796
+ healthSchema = z15.object({ ok: z15.boolean(), version: z15.string() });
1794
1797
  }
1795
1798
  });
1796
1799
 
1797
1800
  // ../common-chat/src/setup.ts
1798
- import { z as z17 } from "zod";
1801
+ import { z as z16 } from "zod";
1799
1802
  function actionText(action) {
1800
1803
  if (action.kind === "link") return `${action.label}: ${action.url}`;
1801
1804
  if (action.kind === "sign_in") {
@@ -1830,42 +1833,42 @@ var init_setup = __esm({
1830
1833
  init_activation();
1831
1834
  init_bot();
1832
1835
  SETUP_STEP_IDS = ["slack", "machine", "github", "repos"];
1833
- setupActionSchema = z17.discriminatedUnion("kind", [
1836
+ setupActionSchema = z16.discriminatedUnion("kind", [
1834
1837
  /** A page to open, which signs in to HerdingChats first. */
1835
- z17.object({ kind: z17.literal("link"), url: z17.string(), label: z17.string() }),
1838
+ z16.object({ kind: z16.literal("link"), url: z16.string(), label: z16.string() }),
1836
1839
  /** A command to run on the computer. */
1837
- z17.object({ kind: z17.literal("command"), command: z17.string() }),
1840
+ z16.object({ kind: z16.literal("command"), command: z16.string() }),
1838
1841
  /**
1839
1842
  * A sign-in herd starts on one of the person's machines, from Slack or the page, whose code
1840
1843
  * Friday sends to their direct message.
1841
1844
  */
1842
- z17.object({
1843
- kind: z17.literal("sign_in"),
1844
- machineId: z17.string(),
1845
+ z16.object({
1846
+ kind: z16.literal("sign_in"),
1847
+ machineId: z16.string(),
1845
1848
  tool: signInToolSchema,
1846
- label: z17.string()
1849
+ label: z16.string()
1847
1850
  })
1848
1851
  ]);
1849
- setupStepSchema = z17.object({
1850
- id: z17.enum(SETUP_STEP_IDS),
1852
+ setupStepSchema = z16.object({
1853
+ id: z16.enum(SETUP_STEP_IDS),
1851
1854
  /** `unavailable` is a step nobody can take yet, such as GitHub linking before an admin turns it on. */
1852
- state: z17.enum(["done", "todo", "unavailable"]),
1853
- optional: z17.boolean(),
1854
- title: z17.string(),
1855
+ state: z16.enum(["done", "todo", "unavailable"]),
1856
+ optional: z16.boolean(),
1857
+ title: z16.string(),
1855
1858
  /** What was found, such as the machine and whether it's online, or why it can't be done yet. */
1856
- detail: z17.string().nullable(),
1859
+ detail: z16.string().nullable(),
1857
1860
  /** What to do next. None once it's done, or while it's unavailable. */
1858
1861
  action: setupActionSchema.nullable(),
1859
1862
  /**
1860
1863
  * More that can be done, which doesn't decide whether the step is done, such as signing in a
1861
1864
  * computer's GitHub CLI. Shown whatever the step's state.
1862
1865
  */
1863
- extra: z17.array(setupActionSchema).optional()
1866
+ extra: z16.array(setupActionSchema).optional()
1864
1867
  });
1865
- setupStatusSchema = z17.object({
1866
- steps: z17.array(setupStepSchema),
1868
+ setupStatusSchema = z16.object({
1869
+ steps: z16.array(setupStepSchema),
1867
1870
  /** Whether every step that isn't optional is done, so Friday can take work. */
1868
- ready: z17.boolean()
1871
+ ready: z16.boolean()
1869
1872
  });
1870
1873
  READY_TEXT = `You're set up: mention @${BOT_NAME} in any channel it's in, or message it directly.`;
1871
1874
  READY_SUGGESTIONS_TITLE = "Some things to try:";
@@ -3135,6 +3138,7 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
3135
3138
 
3136
3139
  // src/friday/main.ts
3137
3140
  init_define_HERD_PACKAGE();
3141
+ init_src();
3138
3142
  import { spawn as spawn5 } from "node:child_process";
3139
3143
  import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
3140
3144
  import { homedir as homedir4 } from "node:os";
@@ -3148,21 +3152,21 @@ import { chmodSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:
3148
3152
  import { createServer } from "node:http";
3149
3153
  import { homedir } from "node:os";
3150
3154
  import { join } from "node:path";
3151
- import { z } from "zod";
3155
+ import { z as z17 } from "zod";
3152
3156
  var herdHome = () => process.env.HERD_HOME ?? join(homedir(), ".herd");
3153
3157
  var apiUrl = () => (process.env.HERD_API_URL ?? "https://api.herdingchats.com").replace(/\/+$/, "");
3154
3158
  var isLocal = (url) => /^http:\/\/localhost:\d+\/?$/.test(url);
3155
3159
  var localSignIn = () => process.env.HERD_LOCAL_SLACK ? { "X-Herd-Local-Slack": process.env.HERD_LOCAL_SLACK } : {};
3156
3160
  var HerdError = class extends Error {
3157
3161
  };
3158
- var credentialsSchema = z.object({
3159
- api: z.string(),
3160
- tokenEndpoint: z.string(),
3161
- revocationEndpoint: z.string().optional(),
3162
- clientId: z.string(),
3163
- accessToken: z.string(),
3164
- accessTokenExpiresAt: z.number(),
3165
- refreshToken: z.string()
3162
+ var credentialsSchema = z17.object({
3163
+ api: z17.string(),
3164
+ tokenEndpoint: z17.string(),
3165
+ revocationEndpoint: z17.string().optional(),
3166
+ clientId: z17.string(),
3167
+ accessToken: z17.string(),
3168
+ accessTokenExpiresAt: z17.number(),
3169
+ refreshToken: z17.string()
3166
3170
  });
3167
3171
  var credentialsPath = () => join(herdHome(), "credentials.json");
3168
3172
  function readCredentials() {
@@ -3178,16 +3182,16 @@ function writeCredentials(credentials) {
3178
3182
  writeFileSync(credentialsPath(), JSON.stringify(credentials, null, 2), { mode: 384 });
3179
3183
  chmodSync(credentialsPath(), 384);
3180
3184
  }
3181
- var metadataSchema = z.object({
3182
- authorization_endpoint: z.string(),
3183
- token_endpoint: z.string(),
3184
- registration_endpoint: z.string(),
3185
- revocation_endpoint: z.string().optional()
3185
+ var metadataSchema = z17.object({
3186
+ authorization_endpoint: z17.string(),
3187
+ token_endpoint: z17.string(),
3188
+ registration_endpoint: z17.string(),
3189
+ revocation_endpoint: z17.string().optional()
3186
3190
  });
3187
- var tokenSchema = z.object({
3188
- access_token: z.string().min(1),
3189
- refresh_token: z.string().min(1),
3190
- expires_in: z.number()
3191
+ var tokenSchema = z17.object({
3192
+ access_token: z17.string().min(1),
3193
+ refresh_token: z17.string().min(1),
3194
+ expires_in: z17.number()
3191
3195
  });
3192
3196
  var base64url = (bytes) => bytes.toString("base64url");
3193
3197
  async function postForm(url, fields) {
@@ -3219,7 +3223,7 @@ async function login(openBrowser2, { api = apiUrl(), timeoutMs = 10 * 60 * 1e3 }
3219
3223
  token_endpoint_auth_method: "none"
3220
3224
  })
3221
3225
  });
3222
- const client = z.object({ client_id: z.string() }).safeParse(await registration2.json());
3226
+ const client = z17.object({ client_id: z17.string() }).safeParse(await registration2.json());
3223
3227
  if (!registration2.ok || !client.success) {
3224
3228
  throw new HerdError("The sign-in server refused to register this tool.");
3225
3229
  }
@@ -4733,6 +4737,7 @@ async function permissionHook(raw, options = {}) {
4733
4737
  var ACTIVATION_DEADLINE_MS = 3 * 60 * 1e3;
4734
4738
  var ACTIVATION_POLL_MS = 500;
4735
4739
  var SIGN_IN_RESTART_MS = 20 * 1e3;
4740
+ var KILL_WAIT_MS = 5e3;
4736
4741
  var BUSY_POLL_MS = 2e3;
4737
4742
  var activationPrompt = (code) => `herd is checking that you can work from its terminals. Run \`herd activate ${code}\` now, then stop.`;
4738
4743
  var CODE_LETTERS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
@@ -4939,10 +4944,19 @@ var Activator = class {
4939
4944
  let startedAt = 0;
4940
4945
  let prompted = false;
4941
4946
  let signingIn = wasSignedOut;
4947
+ const stillRunning = async () => (await terminals.list().catch(() => [])).some(
4948
+ (t) => t.name === current.terminal && !t.exited
4949
+ );
4942
4950
  const start = async () => {
4943
- const existing = (await terminals.list()).find((t) => t.name === current.terminal);
4944
- if (existing) await terminals.kill(current.terminal).catch(() => {
4945
- });
4951
+ if (await stillRunning()) {
4952
+ await terminals.kill(current.terminal).catch(() => {
4953
+ });
4954
+ const until = Date.now() + (this.options.killWaitMs ?? KILL_WAIT_MS);
4955
+ while (await stillRunning()) {
4956
+ if (Date.now() >= until) return;
4957
+ await new Promise((resolve6) => setTimeout(resolve6, Math.min(pollMs, 100)));
4958
+ }
4959
+ }
4946
4960
  const shell = process.env.SHELL ?? "/bin/sh";
4947
4961
  await terminals.create({
4948
4962
  name: current.terminal,
@@ -5143,6 +5157,7 @@ var herdConfigIn = (herdHome2) => join7(herdHome2, "herd.config.ts");
5143
5157
 
5144
5158
  // src/friday/home.ts
5145
5159
  init_define_HERD_PACKAGE();
5160
+ init_src();
5146
5161
  import { spawnSync } from "node:child_process";
5147
5162
  import {
5148
5163
  closeSync as closeSync2,
@@ -5155,7 +5170,7 @@ import {
5155
5170
  writeFileSync as writeFileSync6
5156
5171
  } from "node:fs";
5157
5172
  import { dirname as dirname6, join as join8, resolve as resolve2 } from "node:path";
5158
- var PACKAGE_NAME = "@herdingchats/friday";
5173
+ var PACKAGE_NAME = FRIDAY_PACKAGE;
5159
5174
  function fridayPaths(herdHome2) {
5160
5175
  const logs = join8(herdHome2, "logs");
5161
5176
  return {
@@ -5874,7 +5889,7 @@ async function ensureInstalled(options, print) {
5874
5889
  if (current && !await versionRuns(paths.current, current, options.run)) return;
5875
5890
  if (version === "dev" && !options.install?.spec) {
5876
5891
  throw new StartError(
5877
- "This friday runs from the repo, which has no version to install. Run npx @herdingchats/friday start, or npx herd daemon to watch a daemon in the foreground."
5892
+ `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.`
5878
5893
  );
5879
5894
  }
5880
5895
  print(`Installing Friday ${version}.`);
@@ -5918,8 +5933,8 @@ var Supervisor = class {
5918
5933
  failures = 0;
5919
5934
  restartTimer = null;
5920
5935
  checkTimer = null;
5921
- /** Releases that failed to install, so each is logged once rather than every check. */
5922
- failed = /* @__PURE__ */ new Set();
5936
+ /** Releases that failed to install, and when, so each is retried rather than tried every check. */
5937
+ failed = /* @__PURE__ */ new Map();
5923
5938
  status;
5924
5939
  log;
5925
5940
  /** Starts the daemon and the release checks. */
@@ -6066,7 +6081,11 @@ var Supervisor = class {
6066
6081
  return "none";
6067
6082
  }
6068
6083
  const key = `${target} ${integrity ?? ""}`;
6069
- if (this.failed.has(key)) return "failed";
6084
+ const now = this.options.now?.() ?? Date.now();
6085
+ const failedAt = this.failed.get(key);
6086
+ if (failedAt !== void 0 && now - failedAt < (this.options.retryFailedMs ?? 10 * 6e4)) {
6087
+ return "failed";
6088
+ }
6070
6089
  const release = takeLock(paths.updateLock);
6071
6090
  if (!release) return "busy";
6072
6091
  try {
@@ -6076,7 +6095,9 @@ var Supervisor = class {
6076
6095
  log: this.log
6077
6096
  });
6078
6097
  if (!installed.ok) {
6079
- this.failed.add(key);
6098
+ const again = failedAt !== void 0;
6099
+ this.failed.set(key, now);
6100
+ if (again) return "failed";
6080
6101
  return this.problem(`Staying on ${current}: ${target} ${installed.reason}`);
6081
6102
  }
6082
6103
  activate(paths, target);
@@ -6272,7 +6293,7 @@ function runStatus(deps) {
6272
6293
  pin = "";
6273
6294
  }
6274
6295
  if (!version && !running) {
6275
- print("Friday isn't set up on this computer. Run npx @herdingchats/friday start in its root.");
6296
+ print(`Friday isn't set up on this computer. Run ${START_COMMAND} in its root.`);
6276
6297
  return 1;
6277
6298
  }
6278
6299
  const daemon = running && status2.daemonPid && alive2(status2.daemonPid);