@kubitnodes/stellaris 0.3.12 → 0.3.13

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 (38) hide show
  1. package/dist/cli/index.js +55 -3
  2. package/dist/server/index.js +171 -8
  3. package/package.json +1 -1
  4. package/web/dist/assets/{BackLink-BlJvN2RA.js → BackLink-d0xz7ZLb.js} +1 -1
  5. package/web/dist/assets/{ChannelForms-CmFxBXNK.js → ChannelForms-BIRwT9CY.js} +1 -1
  6. package/web/dist/assets/{ChannelView-4s--IwKC.js → ChannelView-BvMlzMiN.js} +1 -1
  7. package/web/dist/assets/{CitizenView-B5-LVVCG.js → CitizenView-DNQwjpIp.js} +1 -1
  8. package/web/dist/assets/{CitizensView-B8lVGSBD.js → CitizensView-Bv04iH-y.js} +1 -1
  9. package/web/dist/assets/{CliIcon-CT5ljQDC.js → CliIcon-tYTwI_RQ.js} +1 -1
  10. package/web/dist/assets/{KnowledgeView-DbI8DIZb.js → KnowledgeView-L0pdaM_2.js} +1 -1
  11. package/web/dist/assets/{Markdown-B5zEdYuO.js → Markdown-BLiIulgZ.js} +1 -1
  12. package/web/dist/assets/{MessageItem-DuxSZwn0.js → MessageItem-CHrmjF7P.js} +1 -1
  13. package/web/dist/assets/{MetricsView-D8D-y-sz.js → MetricsView-DG1alTgs.js} +1 -1
  14. package/web/dist/assets/{NeedsYouView-Buwq8-_l.js → NeedsYouView-Doc0fKPi.js} +1 -1
  15. package/web/dist/assets/{Overview-CrQ8ybpq.js → Overview-ChsOgIEW.js} +1 -1
  16. package/web/dist/assets/{Pane-CFoSKOo5.js → Pane-MJgGXQBb.js} +1 -1
  17. package/web/dist/assets/{ProjectView-BBQg-ZxC.js → ProjectView-CQTn7yDo.js} +1 -1
  18. package/web/dist/assets/{ProposalView-BjPHVxj4.js → ProposalView-C92OJ_w1.js} +1 -1
  19. package/web/dist/assets/{ProposalsView-DjyZpZe0.js → ProposalsView-CSA8neXR.js} +1 -1
  20. package/web/dist/assets/{RunnersView-2h5NWUuD.js → RunnersView-Dx21LDFu.js} +1 -1
  21. package/web/dist/assets/{SocietyView-BuaSb_3d.js → SocietyView-CdVW2DgG.js} +1 -1
  22. package/web/dist/assets/{SubjectThread-C1mHvHMI.js → SubjectThread-egXeFhT1.js} +1 -1
  23. package/web/dist/assets/{TaskFileView-CeEzbSCL.js → TaskFileView-BqqzxJKb.js} +1 -1
  24. package/web/dist/assets/{TaskView-yL9hCM7G.js → TaskView-rks26vuF.js} +2 -2
  25. package/web/dist/assets/{TasksView-DCVU5oZn.js → TasksView-Ba5fPAvy.js} +1 -1
  26. package/web/dist/assets/{ThreadCard-CXXf9qfA.js → ThreadCard-D6i69_15.js} +1 -1
  27. package/web/dist/assets/{ThreadForms-CTBaAJ57.js → ThreadForms-ChTFRu-P.js} +1 -1
  28. package/web/dist/assets/{ThreadView-zg8KqF3t.js → ThreadView-CnJPNS_8.js} +1 -1
  29. package/web/dist/assets/{citizen-CImM6WB6.js → citizen-D-dxX00V.js} +1 -1
  30. package/web/dist/assets/{compose-BG_-Tp87.js → compose-BgpUWGYE.js} +1 -1
  31. package/web/dist/assets/{format-BWr3zKWg.js → format-C3aawMM6.js} +1 -1
  32. package/web/dist/assets/{governance-cDTg2_iq.js → governance-Di4MijNG.js} +1 -1
  33. package/web/dist/assets/{index-Cxqhrg2v.js → index-krHkeIbX.js} +3 -3
  34. package/web/dist/assets/{link-CFdt17Sp.js → link-DAMxBItI.js} +1 -1
  35. package/web/dist/assets/{tasks-C10zwkED.js → tasks-bwj_EdwF.js} +1 -1
  36. package/web/dist/assets/{useMatch-BpnmzT6s.js → useMatch-B-8IcuU6.js} +1 -1
  37. package/web/dist/assets/{useStickyScroll-BjqdEt_f.js → useStickyScroll-BILPUgGj.js} +1 -1
  38. package/web/dist/index.html +8 -8
package/dist/cli/index.js CHANGED
@@ -218,7 +218,12 @@ var PullRequestLinkSchema = z3.object({
218
218
  subject: MergeSubjectSchema.optional(),
219
219
  body: z3.string().max(2e4).optional(),
220
220
  linkedBy: NameSchema,
221
- linkedAt: IsoDateTimeSchema
221
+ linkedAt: IsoDateTimeSchema,
222
+ /**
223
+ * Once its `ghpr` task was abandoned, how the board's closing of it on GitHub went: `ok` false
224
+ * leaves it open, for the reason `detail` gives.
225
+ */
226
+ closed: z3.object({ at: IsoDateTimeSchema, ok: z3.boolean(), detail: z3.string() }).optional()
222
227
  });
223
228
  var DefaultBranchSchema = z3.string().trim().min(1).max(100).regex(/^[A-Za-z0-9][A-Za-z0-9._/-]*$/, "a branch name is letters, digits, and . _ / -").refine((branch) => !branch.includes("..") && !branch.includes("//") && !branch.endsWith("/") && !branch.endsWith(".") && !branch.endsWith(".lock"), "not a branch name git takes").refine((branch) => !branch.startsWith("task/") && !branch.startsWith("agent/"), "task/ and agent/ hold the board's own branches");
224
229
  var StageIdSchema = z3.string().regex(/^s[1-9][0-9]*$/, "expected a stage id such as s1");
@@ -616,12 +621,19 @@ var DashboardSchema = z3.object({
616
621
  updatedAt: IsoDateTimeSchema.optional(),
617
622
  body: z3.string()
618
623
  });
624
+ var ProposalOriginSchema = z3.object({
625
+ scope: NameSchema,
626
+ thread: UlidSchema.optional(),
627
+ channel: NameSchema.optional()
628
+ });
619
629
  var ProposalFrontmatterSchema = z3.object({
620
630
  id: UlidSchema,
621
631
  kind: ProposalKindSchema,
622
632
  proposedBy: NameSchema,
623
633
  status: ProposalStatusSchema,
624
634
  createdAt: IsoDateTimeSchema,
635
+ /** Absent for a proposal filed outside a turn, or before proposals recorded it. */
636
+ filedFrom: ProposalOriginSchema.optional(),
625
637
  decidedBy: NameSchema.optional(),
626
638
  decidedAt: IsoDateTimeSchema.optional(),
627
639
  reason: z3.string().optional(),
@@ -814,6 +826,8 @@ var BOARD_EVENT_TYPES = [
814
826
  "turn.failed",
815
827
  "merge.completed",
816
828
  "merge.failed",
829
+ "pull_request.closed",
830
+ "pull_request.close_failed",
817
831
  "workspace.leftovers"
818
832
  ];
819
833
  var BoardEventTypeSchema = z5.enum(BOARD_EVENT_TYPES);
@@ -1052,6 +1066,11 @@ var LandRequestSchema = z6.object({
1052
1066
  body: z6.string().optional()
1053
1067
  }).optional()
1054
1068
  });
1069
+ var CloseRequestSchema = z6.object({
1070
+ repo: ProjectRepoSchema,
1071
+ url: z6.string().min(1),
1072
+ comment: z6.string().min(1)
1073
+ });
1055
1074
  var MergeOutcomeSchema = z6.object({ ok: z6.boolean(), detail: z6.string() });
1056
1075
  var ModelListSchema = z6.array(ModelOptionSchema);
1057
1076
  var BRANCH_FILE_LIMIT_BYTES = 8 * 1024 * 1024;
@@ -1119,6 +1138,8 @@ var TurnSteerSchema = z6.object({ id: z6.uuid(), text: z6.string().min(1) });
1119
1138
  var RunnerMessageSchema = z6.discriminatedUnion("type", [
1120
1139
  z6.object({ type: z6.literal("turn"), job: TurnJobSchema }),
1121
1140
  z6.object({ type: z6.literal("land"), request: z6.string().min(1), land: LandRequestSchema }),
1141
+ /** Answered with a `MergeOutcome`. */
1142
+ z6.object({ type: z6.literal("close"), request: z6.string().min(1), close: CloseRequestSchema }),
1122
1143
  z6.object({ type: z6.literal("models"), request: z6.string().min(1), cli: CliKindSchema }),
1123
1144
  /** Answered with a `BranchFile`, or null when the branch or the path does not exist. */
1124
1145
  z6.object({ type: z6.literal("file"), request: z6.string().min(1), read: BranchReadSchema }),
@@ -1463,7 +1484,7 @@ var RunnerConfigSchema = z10.object({
1463
1484
  });
1464
1485
 
1465
1486
  // packages/shared/dist/version.js
1466
- var STELLARIS_VERSION = "0.3.12";
1487
+ var STELLARIS_VERSION = "0.3.13";
1467
1488
 
1468
1489
  // packages/board-core/dist/errors.js
1469
1490
  var BoardError = class extends Error {
@@ -5025,6 +5046,13 @@ ${args.summary}`);
5025
5046
  proposedBy: actor.name,
5026
5047
  status: "proposed",
5027
5048
  createdAt: this.now().toISOString(),
5049
+ ...actor.scope === void 0 ? {} : {
5050
+ filedFrom: {
5051
+ scope: actor.scope,
5052
+ ...actor.thread === void 0 ? {} : { thread: actor.thread },
5053
+ ...actor.channel === void 0 ? {} : { channel: actor.channel }
5054
+ }
5055
+ },
5028
5056
  charter: parsed.data
5029
5057
  }),
5030
5058
  body: args.rationale
@@ -5525,6 +5553,29 @@ ${rationale}`}`);
5525
5553
  });
5526
5554
  });
5527
5555
  }
5556
+ /**
5557
+ * Records how closing an abandoned `ghpr` task's pull request on GitHub went, once: the task's
5558
+ * link keeps it, so a restart does not try again.
5559
+ */
5560
+ async recordPullRequestClosed(actor, input) {
5561
+ return this.mutex.run(async () => {
5562
+ const location = await this.findTask(input.taskId);
5563
+ const current = location.task;
5564
+ const pull = current.pullRequest;
5565
+ if (pull === void 0 || pull.closed !== void 0) {
5566
+ return current;
5567
+ }
5568
+ const task2 = await this.writeTask(location.project, {
5569
+ ...current,
5570
+ pullRequest: {
5571
+ ...pull,
5572
+ closed: { at: this.now().toISOString(), ok: input.ok, detail: input.detail }
5573
+ }
5574
+ });
5575
+ await this.events.append(input.ok ? "pull_request.closed" : "pull_request.close_failed", actor.name, { project: location.project, taskId: task2.id, url: pull.url, detail: input.detail });
5576
+ return task2;
5577
+ });
5578
+ }
5528
5579
  /**
5529
5580
  * Records that a citizen's workspace in a conversation that has ended holds work on no branch, so
5530
5581
  * the scheduler gives the citizen a closing turn there to decide about it. False, recording
@@ -6757,7 +6808,8 @@ ${charter.purpose}
6757
6808
  proposalId,
6758
6809
  outcome,
6759
6810
  kind: proposal2.kind,
6760
- proposedBy: proposal2.proposedBy
6811
+ proposedBy: proposal2.proposedBy,
6812
+ ...proposal2.filedFrom === void 0 ? {} : { filedFrom: proposal2.filedFrom }
6761
6813
  });
6762
6814
  if (provision !== void 0) {
6763
6815
  await this.events.append("proposal.provisioned", actor.name, {
@@ -218,7 +218,12 @@ var PullRequestLinkSchema = z3.object({
218
218
  subject: MergeSubjectSchema.optional(),
219
219
  body: z3.string().max(2e4).optional(),
220
220
  linkedBy: NameSchema,
221
- linkedAt: IsoDateTimeSchema
221
+ linkedAt: IsoDateTimeSchema,
222
+ /**
223
+ * Once its `ghpr` task was abandoned, how the board's closing of it on GitHub went: `ok` false
224
+ * leaves it open, for the reason `detail` gives.
225
+ */
226
+ closed: z3.object({ at: IsoDateTimeSchema, ok: z3.boolean(), detail: z3.string() }).optional()
222
227
  });
223
228
  var DefaultBranchSchema = z3.string().trim().min(1).max(100).regex(/^[A-Za-z0-9][A-Za-z0-9._/-]*$/, "a branch name is letters, digits, and . _ / -").refine((branch) => !branch.includes("..") && !branch.includes("//") && !branch.endsWith("/") && !branch.endsWith(".") && !branch.endsWith(".lock"), "not a branch name git takes").refine((branch) => !branch.startsWith("task/") && !branch.startsWith("agent/"), "task/ and agent/ hold the board's own branches");
224
229
  var StageIdSchema = z3.string().regex(/^s[1-9][0-9]*$/, "expected a stage id such as s1");
@@ -616,12 +621,19 @@ var DashboardSchema = z3.object({
616
621
  updatedAt: IsoDateTimeSchema.optional(),
617
622
  body: z3.string()
618
623
  });
624
+ var ProposalOriginSchema = z3.object({
625
+ scope: NameSchema,
626
+ thread: UlidSchema.optional(),
627
+ channel: NameSchema.optional()
628
+ });
619
629
  var ProposalFrontmatterSchema = z3.object({
620
630
  id: UlidSchema,
621
631
  kind: ProposalKindSchema,
622
632
  proposedBy: NameSchema,
623
633
  status: ProposalStatusSchema,
624
634
  createdAt: IsoDateTimeSchema,
635
+ /** Absent for a proposal filed outside a turn, or before proposals recorded it. */
636
+ filedFrom: ProposalOriginSchema.optional(),
625
637
  decidedBy: NameSchema.optional(),
626
638
  decidedAt: IsoDateTimeSchema.optional(),
627
639
  reason: z3.string().optional(),
@@ -843,6 +855,8 @@ var BOARD_EVENT_TYPES = [
843
855
  "turn.failed",
844
856
  "merge.completed",
845
857
  "merge.failed",
858
+ "pull_request.closed",
859
+ "pull_request.close_failed",
846
860
  "workspace.leftovers"
847
861
  ];
848
862
  var BoardEventTypeSchema = z5.enum(BOARD_EVENT_TYPES);
@@ -1097,6 +1111,11 @@ var LandRequestSchema = z6.object({
1097
1111
  body: z6.string().optional()
1098
1112
  }).optional()
1099
1113
  });
1114
+ var CloseRequestSchema = z6.object({
1115
+ repo: ProjectRepoSchema,
1116
+ url: z6.string().min(1),
1117
+ comment: z6.string().min(1)
1118
+ });
1100
1119
  var MergeOutcomeSchema = z6.object({ ok: z6.boolean(), detail: z6.string() });
1101
1120
  var ModelListSchema = z6.array(ModelOptionSchema);
1102
1121
  var BRANCH_FILE_LIMIT_BYTES = 8 * 1024 * 1024;
@@ -1170,6 +1189,8 @@ var TurnSteerSchema = z6.object({ id: z6.uuid(), text: z6.string().min(1) });
1170
1189
  var RunnerMessageSchema = z6.discriminatedUnion("type", [
1171
1190
  z6.object({ type: z6.literal("turn"), job: TurnJobSchema }),
1172
1191
  z6.object({ type: z6.literal("land"), request: z6.string().min(1), land: LandRequestSchema }),
1192
+ /** Answered with a `MergeOutcome`. */
1193
+ z6.object({ type: z6.literal("close"), request: z6.string().min(1), close: CloseRequestSchema }),
1173
1194
  z6.object({ type: z6.literal("models"), request: z6.string().min(1), cli: CliKindSchema }),
1174
1195
  /** Answered with a `BranchFile`, or null when the branch or the path does not exist. */
1175
1196
  z6.object({ type: z6.literal("file"), request: z6.string().min(1), read: BranchReadSchema }),
@@ -1572,7 +1593,7 @@ var RunnerConfigSchema = z10.object({
1572
1593
  });
1573
1594
 
1574
1595
  // packages/shared/dist/version.js
1575
- var STELLARIS_VERSION = "0.3.12";
1596
+ var STELLARIS_VERSION = "0.3.13";
1576
1597
 
1577
1598
  // packages/board-core/dist/errors.js
1578
1599
  var BoardError = class extends Error {
@@ -5137,6 +5158,13 @@ ${args.summary}`);
5137
5158
  proposedBy: actor.name,
5138
5159
  status: "proposed",
5139
5160
  createdAt: this.now().toISOString(),
5161
+ ...actor.scope === void 0 ? {} : {
5162
+ filedFrom: {
5163
+ scope: actor.scope,
5164
+ ...actor.thread === void 0 ? {} : { thread: actor.thread },
5165
+ ...actor.channel === void 0 ? {} : { channel: actor.channel }
5166
+ }
5167
+ },
5140
5168
  charter: parsed.data
5141
5169
  }),
5142
5170
  body: args.rationale
@@ -5637,6 +5665,29 @@ ${rationale}`}`);
5637
5665
  });
5638
5666
  });
5639
5667
  }
5668
+ /**
5669
+ * Records how closing an abandoned `ghpr` task's pull request on GitHub went, once: the task's
5670
+ * link keeps it, so a restart does not try again.
5671
+ */
5672
+ async recordPullRequestClosed(actor, input) {
5673
+ return this.mutex.run(async () => {
5674
+ const location = await this.findTask(input.taskId);
5675
+ const current = location.task;
5676
+ const pull = current.pullRequest;
5677
+ if (pull === void 0 || pull.closed !== void 0) {
5678
+ return current;
5679
+ }
5680
+ const task = await this.writeTask(location.project, {
5681
+ ...current,
5682
+ pullRequest: {
5683
+ ...pull,
5684
+ closed: { at: this.now().toISOString(), ok: input.ok, detail: input.detail }
5685
+ }
5686
+ });
5687
+ await this.events.append(input.ok ? "pull_request.closed" : "pull_request.close_failed", actor.name, { project: location.project, taskId: task.id, url: pull.url, detail: input.detail });
5688
+ return task;
5689
+ });
5690
+ }
5640
5691
  /**
5641
5692
  * Records that a citizen's workspace in a conversation that has ended holds work on no branch, so
5642
5693
  * the scheduler gives the citizen a closing turn there to decide about it. False, recording
@@ -6869,7 +6920,8 @@ ${charter.purpose}
6869
6920
  proposalId,
6870
6921
  outcome,
6871
6922
  kind: proposal.kind,
6872
- proposedBy: proposal.proposedBy
6923
+ proposedBy: proposal.proposedBy,
6924
+ ...proposal.filedFrom === void 0 ? {} : { filedFrom: proposal.filedFrom }
6873
6925
  });
6874
6926
  if (provision !== void 0) {
6875
6927
  await this.events.append("proposal.provisioned", actor.name, {
@@ -7150,6 +7202,9 @@ function stringArray(value) {
7150
7202
  function stringOf(value) {
7151
7203
  return typeof value === "string" ? value : null;
7152
7204
  }
7205
+ function awaitsClosing(task) {
7206
+ return task.status === "abandoned" && task.onDone === "ghpr" && task.pullRequest !== void 0 && task.pullRequest.closed === void 0;
7207
+ }
7153
7208
  function inPlay(task) {
7154
7209
  return (task.status === "open" || task.status === "claimed") && !task.completing;
7155
7210
  }
@@ -7182,6 +7237,9 @@ var Scheduler = class {
7182
7237
  steering = /* @__PURE__ */ new Map();
7183
7238
  /** Tasks whose completion effect waits for the turn that finished their last stage to end. */
7184
7239
  completions = /* @__PURE__ */ new Map();
7240
+ /** Abandoned `ghpr` tasks whose pull request waits to be closed, by task id, with its project. */
7241
+ closings = /* @__PURE__ */ new Map();
7242
+ /** Completions and closings under way. */
7185
7243
  completing = /* @__PURE__ */ new Set();
7186
7244
  /** Running turns that must run alone among their citizen's, by session key: see `heldBack`. */
7187
7245
  exclusive = /* @__PURE__ */ new Map();
@@ -7281,6 +7339,7 @@ var Scheduler = class {
7281
7339
  this.lastSweep = now;
7282
7340
  }
7283
7341
  this.runCompletions();
7342
+ this.runClosings();
7284
7343
  if (!paused) {
7285
7344
  await this.dispatchReady(now);
7286
7345
  }
@@ -7308,6 +7367,9 @@ var Scheduler = class {
7308
7367
  if (task.completing) {
7309
7368
  this.completions.set(task.id, { project: project.slug, actor: USER_NAME });
7310
7369
  }
7370
+ if (awaitsClosing(task)) {
7371
+ this.closings.set(task.id, project.slug);
7372
+ }
7311
7373
  }
7312
7374
  }
7313
7375
  this.loaded = true;
@@ -7416,6 +7478,7 @@ var Scheduler = class {
7416
7478
  const taskId = stringOf(payload["taskId"]);
7417
7479
  if (taskId !== null && payload["to"] === "abandoned") {
7418
7480
  delete this.state.releaseCounts[taskId];
7481
+ await this.queueClosing(taskId);
7419
7482
  }
7420
7483
  if (taskId !== null) {
7421
7484
  await this.pruneStageWakes(taskId);
@@ -7755,13 +7818,16 @@ var Scheduler = class {
7755
7818
  reason: "a conversation you took part in has ended, and its workspace holds work on no branch"
7756
7819
  }, now, beside);
7757
7820
  }
7758
- /** A decided proposal wakes the citizen that made it, to carry on with what it enables. */
7821
+ /**
7822
+ * A decided proposal wakes the citizen that made it, to carry on with what it enables, in the
7823
+ * conversation it was filed from, where that work waits on the decision.
7824
+ */
7759
7825
  async wakeProposer(proposalId, proposer, event, now) {
7760
7826
  const agent = await this.tryReadAgent(proposer);
7761
7827
  if (agent === null) {
7762
7828
  return;
7763
7829
  }
7764
- const scope = this.scopeForProject(agent, null);
7830
+ const { scope, beside } = await this.filedFrom(agent, event.payload["filedFrom"]);
7765
7831
  const kind = stringOf(event.payload["kind"]) ?? "";
7766
7832
  const outcome = stringOf(event.payload["outcome"]) ?? "decided";
7767
7833
  this.enqueue(agent.name, scope, {
@@ -7769,7 +7835,27 @@ var Scheduler = class {
7769
7835
  from: event.actor,
7770
7836
  fromUser: event.actor === USER_NAME,
7771
7837
  reason: `your ${kind} proposal ${proposalId} was ${outcome} by ${event.actor}`
7772
- }, now);
7838
+ }, now, beside);
7839
+ }
7840
+ /**
7841
+ * The conversation a proposal was filed from while it is still open; its scope's home once it
7842
+ * has ended; and the home outside projects when the citizen has left that scope, or the proposal
7843
+ * names none, filed outside a turn or before proposals recorded it.
7844
+ */
7845
+ async filedFrom(agent, recorded) {
7846
+ const origin = ProposalOriginSchema.safeParse(recorded);
7847
+ if (!origin.success || origin.data.scope !== SOCIETY_SCOPE && !agent.memberships.includes(origin.data.scope)) {
7848
+ return { scope: this.scopeForProject(agent, null) };
7849
+ }
7850
+ const scope = origin.data.scope;
7851
+ const conversation = workspaceConversationOf(origin.data);
7852
+ if (conversation === null || await this.board.conversationEnded(conversation)) {
7853
+ return { scope };
7854
+ }
7855
+ return {
7856
+ scope,
7857
+ beside: conversation.kind === "thread" ? { thread: await this.conversationOf(conversation.id, scope) } : { channel: conversation.name }
7858
+ };
7773
7859
  }
7774
7860
  /**
7775
7861
  * A thread's conversation for a turn in `scope`, and whether it is a task's in that scope, whose
@@ -8419,6 +8505,40 @@ var Scheduler = class {
8419
8505
  }
8420
8506
  return others.some((other) => this.exclusive.get(other) === "reflection");
8421
8507
  }
8508
+ /** Queues closing an abandoned task's pull request, when it is a `ghpr` task with one open. */
8509
+ async queueClosing(taskId) {
8510
+ if (this.runner.closePullRequest === void 0) {
8511
+ return;
8512
+ }
8513
+ try {
8514
+ const { task } = await this.board.findTask(taskId);
8515
+ if (awaitsClosing(task)) {
8516
+ this.closings.set(taskId, task.project);
8517
+ }
8518
+ } catch {
8519
+ }
8520
+ }
8521
+ /** Starts closing each queued pull request; one whose runner is away waits in the queue. */
8522
+ runClosings() {
8523
+ const close = this.runner.closePullRequest?.bind(this.runner);
8524
+ if (close === void 0) {
8525
+ return;
8526
+ }
8527
+ for (const [taskId, project] of this.closings) {
8528
+ this.closings.delete(taskId);
8529
+ const promise = close(project, taskId).then((outcome) => {
8530
+ if (outcome === "deferred" && !this.closings.has(taskId)) {
8531
+ this.closings.set(taskId, project);
8532
+ }
8533
+ return void 0;
8534
+ }).catch((error) => {
8535
+ this.log.error({ project, taskId, error: String(error) }, "closing a pull request failed");
8536
+ }).finally(() => {
8537
+ this.completing.delete(promise);
8538
+ });
8539
+ this.completing.add(promise);
8540
+ }
8541
+ }
8422
8542
  /** Starts each queued completion once the turn that finished the task's last stage has ended. */
8423
8543
  runCompletions() {
8424
8544
  for (const [taskId, item] of this.completions) {
@@ -8651,7 +8771,7 @@ function buildTurnPrompt(input) {
8651
8771
  lines.push("A task you created is done. Tell whoever asked for it, if anyone did.");
8652
8772
  }
8653
8773
  if (dispatch.trigger.kind === "proposal_decided") {
8654
- lines.push("A proposal you made was decided; the decision is the last post in its thread. Carry on with what an approval enables or a rejection asks, and stay silent if nothing follows.");
8774
+ lines.push("A proposal you made was decided; the decision is the last post in the proposal's thread. A decision wakes you in the conversation you filed the proposal from, or at home once that has ended. Carry on with what an approval enables or a rejection asks, and stay silent if nothing follows.");
8655
8775
  }
8656
8776
  if (dispatch.trigger.kind === "user_post") {
8657
8777
  lines.push("The user posted. Route it: answer where it was posted, in its thread when it came in one, or create what it needs: a task with a plan whose stages name who does them, a thread, or a project, adding citizens to a project first when they are not members. Stay silent when the user already addressed a citizen and nothing else is needed.");
@@ -8737,7 +8857,7 @@ function buildTurnPrompt(input) {
8737
8857
  }
8738
8858
  if (project !== void 0 && project !== null && landing === "ghpr") {
8739
8859
  const base = project.defaultBranch;
8740
- lines.push("", `## Project ${project.slug}`, "", `A finished task lands by the board merging its pull request on GitHub into ${base}. Open the pull request yourself, from a branch named for what it does that holds the same files as task/<id>, as \`git push origin task/<id>:<branch>\` gives, and link it to the task with update_task pull_request before its last stage completes, with the merge commit's merge_subject and merge_body, which you may change by linking again until it lands. Never merge the pull request or ${base} yourself, nor push other work to ${base}: the board merges once the task's stages are done, and the runner refuses the pushes.`);
8860
+ lines.push("", `## Project ${project.slug}`, "", `A finished task lands by the board merging its pull request on GitHub into ${base}. Open the pull request yourself, from a branch named for what it does that holds the same files as task/<id>, as \`git push origin task/<id>:<branch>\` gives, and link it to the task with update_task pull_request before its last stage completes, with the merge commit's merge_subject and merge_body, which you may change by linking again until it lands. Never merge the pull request or ${base} yourself, nor push other work to ${base}: the board merges once the task's stages are done, and the runner refuses the pushes. Abandoning the task closes its linked pull request and deletes its branch.`);
8741
8861
  }
8742
8862
  if (conflicts.length > 0) {
8743
8863
  lines.push("", "## Edits to reconcile in your home", "", "Two of your turns changed these files at once on different runners. The file in place kept the other turn's version; yours is the copy named here, beside it. Merge what still holds into the file, then delete the copy.", "", ...conflicts.map((conflict) => `- ${conflict.path}, beside ${conflict.file}, since ${conflict.since}`));
@@ -9895,6 +10015,49 @@ var RunnerHub = class {
9895
10015
  });
9896
10016
  return "done";
9897
10017
  }
10018
+ /**
10019
+ * Closes the pull request of a `ghpr` task abandoned with one linked, on the runner its project
10020
+ * lives on, whose `gh` login reaches GitHub, and records how it went on the task; `deferred`
10021
+ * while that runner is away.
10022
+ */
10023
+ async closePullRequest(project, taskId) {
10024
+ const { task } = await this.board.findTask(taskId);
10025
+ const pull = task.pullRequest;
10026
+ if (task.status !== "abandoned" || task.onDone !== "ghpr" || pull === void 0 || pull.closed !== void 0) {
10027
+ return "done";
10028
+ }
10029
+ const record = await this.board.readProject(project);
10030
+ let outcome = {
10031
+ ok: false,
10032
+ detail: `${project} lives on no runner yet, so none could close ${pull.url}`
10033
+ };
10034
+ if (record.runner !== void 0) {
10035
+ const seat = this.seats.get(record.runner);
10036
+ if (seat === void 0 || seat.send === null) {
10037
+ return "deferred";
10038
+ }
10039
+ try {
10040
+ outcome = MergeOutcomeSchema.parse(await this.request(seat, (request) => ({
10041
+ type: "close",
10042
+ request,
10043
+ close: {
10044
+ repo: projectRepo(record),
10045
+ url: pull.url,
10046
+ comment: `Closed by Stellaris: the task this pull request was opened for, "${task.title}", was abandoned.`
10047
+ }
10048
+ })));
10049
+ } catch (error) {
10050
+ this.log.warn({ project, taskId, error: String(error) }, "closing a pull request deferred");
10051
+ return "deferred";
10052
+ }
10053
+ }
10054
+ await this.board.recordPullRequestClosed(SYSTEM_ACTOR, {
10055
+ taskId,
10056
+ ok: outcome.ok,
10057
+ detail: outcome.detail
10058
+ });
10059
+ return "done";
10060
+ }
9898
10061
  /**
9899
10062
  * One path on a branch of a project's repository, read on the runner the project lives on.
9900
10063
  * NOT_FOUND when the project has no runner yet or the branch or the path does not exist, and
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "codex",
9
9
  "multi-agent"
10
10
  ],
11
- "version": "0.3.12",
11
+ "version": "0.3.13",
12
12
  "license": "MIT",
13
13
  "homepage": "https://github.com/kr4t0n/stellaris",
14
14
  "repository": {
@@ -1 +1 @@
1
- import{Ot as e,b as t,pn as n}from"./format-BWr3zKWg.js";import{C as r,n as i,r as a,t as o,v as s}from"./index-Cxqhrg2v.js";var c=n(),l=`grid size-7 shrink-0 place-items-center rounded-lg text-fg-tertiary hover:bg-surface-2/70 hover:text-fg-primary`;function u({fallback:n}){let u=e(),d=r({select:e=>e.location.state.__TSR_index}),f=a(),p=s(),m=t(),h=i(f,d);if(h===null)return n;let g=o(h,{entity:e=>p.get(e)?.title,project:e=>m.data?.find(t=>t.slug===e)?.name});return(0,c.jsx)(`button`,{type:`button`,onClick:()=>u.history.back(),"aria-label":`Back to ${g}`,title:`Back to ${g}`,className:l,children:`←`})}export{u as t};
1
+ import{Ot as e,b as t,pn as n}from"./format-C3aawMM6.js";import{C as r,n as i,r as a,t as o,v as s}from"./index-krHkeIbX.js";var c=n(),l=`grid size-7 shrink-0 place-items-center rounded-lg text-fg-tertiary hover:bg-surface-2/70 hover:text-fg-primary`;function u({fallback:n}){let u=e(),d=r({select:e=>e.location.state.__TSR_index}),f=a(),p=s(),m=t(),h=i(f,d);if(h===null)return n;let g=o(h,{entity:e=>p.get(e)?.title,project:e=>m.data?.find(t=>t.slug===e)?.name});return(0,c.jsx)(`button`,{type:`button`,onClick:()=>u.history.back(),"aria-label":`Back to ${g}`,title:`Back to ${g}`,className:l,children:`←`})}export{u as t};
@@ -1 +1 @@
1
- import{O as e,_n as t,fn as n,mn as r,pn as i,t as a}from"./format-BWr3zKWg.js";import{c as o,l as s,s as c}from"./compose-BG_-Tp87.js";import{t as l}from"./link-CFdt17Sp.js";import{n as u,r as d}from"./ThreadForms-CTBaAJ57.js";var f=t(r(),1),p=i();function m({project:t,onDone:r}){let{api:i}=e(),a=n(),l=o(),[m,h]=(0,f.useState)(``),[g,_]=(0,f.useState)(``),v=(0,f.useRef)(null);(0,f.useEffect)(()=>v.current?.focus(),[]);let y=s({mutationFn:()=>i.createChannel({project:t,name:m.trim(),purpose:g.trim()}),onSuccess:async e=>{await a.invalidateQueries({queryKey:[`channels`]}),r(),await l({to:`/c/$`,params:{_splat:e}})}});return(0,p.jsxs)(`form`,{"aria-label":`New channel`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),y.mutate()},children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`div`,{className:`w-40 shrink-0`,children:(0,p.jsx)(`input`,{ref:v,value:m,maxLength:64,spellCheck:!1,"aria-label":`Channel name`,placeholder:`release-0-4`,onChange:e=>h(e.target.value),className:`${u} font-mono`})}),(0,p.jsx)(`input`,{value:g,"aria-label":`Purpose`,placeholder:`What the channel is for`,onChange:e=>_(e.target.value),className:`${u} min-w-0 flex-1`}),(0,p.jsx)(c,{onClick:r,children:`Cancel`}),(0,p.jsx)(c,{variant:`primary`,type:`submit`,disabled:y.isPending||m.trim()===``||g.trim()===``,children:y.isPending?`Opening…`:`Open`})]}),(0,p.jsx)(`p`,{className:`text-meta`,children:t===null?`Announced in the society's general, and followed by whoever subscribes to it; you read every channel without following one.`:`Announced in ${t}'s general, where its members choose to follow it; you read every channel without following one. Tasks filed in it hang their threads here, and it is archived once its tasks are done.`}),(0,p.jsx)(d,{error:y.error})]})}function h({channel:t,onDone:r}){let{api:i}=e(),a=n(),[o,l]=(0,f.useState)(``),m=s({mutationFn:()=>i.archiveChannel({channel:t,reason:o.trim()}),onSuccess:async()=>{await a.invalidateQueries({queryKey:[`channels`]}),r()}});return(0,p.jsxs)(`form`,{"aria-label":`Archive the channel`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),m.mutate()},children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`input`,{value:o,"aria-label":`Reason`,placeholder:`Why its work is done`,onChange:e=>l(e.target.value),className:`${u} min-w-0 flex-1`}),(0,p.jsx)(c,{onClick:r,children:`Cancel`}),(0,p.jsx)(c,{variant:`primary`,type:`submit`,disabled:m.isPending||o.trim()===``,children:m.isPending?`Archiving…`:`Archive channel`})]}),(0,p.jsx)(`p`,{className:`text-meta`,children:`Its open threads close, nobody follows it, and nothing more is posted or filed here; its posts, threads, and tasks stay readable. The board refuses while a task filed here is in play.`}),(0,p.jsx)(d,{error:m.error})]})}function g({channels:e,now:t}){return e.length===0?(0,p.jsx)(`p`,{className:`text-meta`,children:`No channels.`}):(0,p.jsx)(`ul`,{className:`space-y-1`,children:e.map(e=>(0,p.jsxs)(`li`,{children:[(0,p.jsxs)(l,{to:`/c/$`,params:{_splat:e.ref},className:`text-sm hover:text-fg-primary ${e.archived===void 0?`text-fg-secondary`:`text-fg-tertiary`}`,children:[`# `,e.name]}),(0,p.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,e.messages,` messages`,e.archived===void 0?``:` · archived ${a(e.archived.at,t)}`]})]},e.ref))})}export{g as n,m as r,h as t};
1
+ import{O as e,_n as t,fn as n,mn as r,pn as i,t as a}from"./format-C3aawMM6.js";import{c as o,l as s,s as c}from"./compose-BgpUWGYE.js";import{t as l}from"./link-DAMxBItI.js";import{n as u,r as d}from"./ThreadForms-ChTFRu-P.js";var f=t(r(),1),p=i();function m({project:t,onDone:r}){let{api:i}=e(),a=n(),l=o(),[m,h]=(0,f.useState)(``),[g,_]=(0,f.useState)(``),v=(0,f.useRef)(null);(0,f.useEffect)(()=>v.current?.focus(),[]);let y=s({mutationFn:()=>i.createChannel({project:t,name:m.trim(),purpose:g.trim()}),onSuccess:async e=>{await a.invalidateQueries({queryKey:[`channels`]}),r(),await l({to:`/c/$`,params:{_splat:e}})}});return(0,p.jsxs)(`form`,{"aria-label":`New channel`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),y.mutate()},children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`div`,{className:`w-40 shrink-0`,children:(0,p.jsx)(`input`,{ref:v,value:m,maxLength:64,spellCheck:!1,"aria-label":`Channel name`,placeholder:`release-0-4`,onChange:e=>h(e.target.value),className:`${u} font-mono`})}),(0,p.jsx)(`input`,{value:g,"aria-label":`Purpose`,placeholder:`What the channel is for`,onChange:e=>_(e.target.value),className:`${u} min-w-0 flex-1`}),(0,p.jsx)(c,{onClick:r,children:`Cancel`}),(0,p.jsx)(c,{variant:`primary`,type:`submit`,disabled:y.isPending||m.trim()===``||g.trim()===``,children:y.isPending?`Opening…`:`Open`})]}),(0,p.jsx)(`p`,{className:`text-meta`,children:t===null?`Announced in the society's general, and followed by whoever subscribes to it; you read every channel without following one.`:`Announced in ${t}'s general, where its members choose to follow it; you read every channel without following one. Tasks filed in it hang their threads here, and it is archived once its tasks are done.`}),(0,p.jsx)(d,{error:y.error})]})}function h({channel:t,onDone:r}){let{api:i}=e(),a=n(),[o,l]=(0,f.useState)(``),m=s({mutationFn:()=>i.archiveChannel({channel:t,reason:o.trim()}),onSuccess:async()=>{await a.invalidateQueries({queryKey:[`channels`]}),r()}});return(0,p.jsxs)(`form`,{"aria-label":`Archive the channel`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),m.mutate()},children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`input`,{value:o,"aria-label":`Reason`,placeholder:`Why its work is done`,onChange:e=>l(e.target.value),className:`${u} min-w-0 flex-1`}),(0,p.jsx)(c,{onClick:r,children:`Cancel`}),(0,p.jsx)(c,{variant:`primary`,type:`submit`,disabled:m.isPending||o.trim()===``,children:m.isPending?`Archiving…`:`Archive channel`})]}),(0,p.jsx)(`p`,{className:`text-meta`,children:`Its open threads close, nobody follows it, and nothing more is posted or filed here; its posts, threads, and tasks stay readable. The board refuses while a task filed here is in play.`}),(0,p.jsx)(d,{error:m.error})]})}function g({channels:e,now:t}){return e.length===0?(0,p.jsx)(`p`,{className:`text-meta`,children:`No channels.`}):(0,p.jsx)(`ul`,{className:`space-y-1`,children:e.map(e=>(0,p.jsxs)(`li`,{children:[(0,p.jsxs)(l,{to:`/c/$`,params:{_splat:e.ref},className:`text-sm hover:text-fg-primary ${e.archived===void 0?`text-fg-secondary`:`text-fg-tertiary`}`,children:[`# `,e.name]}),(0,p.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,e.messages,` messages`,e.archived===void 0?``:` · archived ${a(e.archived.at,t)}`]})]},e.ref))})}export{g as n,m as r,h as t};
@@ -1 +1 @@
1
- import{I as e,Kt as t,O as n,_n as r,b as i,c as a,g as o,mn as s,pn as c,pt as l,t as u,y as d,z as f}from"./format-BWr3zKWg.js";import{s as p}from"./compose-BG_-Tp87.js";import{S as m,T as h,i as g}from"./index-Cxqhrg2v.js";import{i as _}from"./ThreadForms-CTBaAJ57.js";import{t as v}from"./ChannelForms-CmFxBXNK.js";import{t as y}from"./MessageItem-DuxSZwn0.js";import{n as b,t as x}from"./Pane-CFoSKOo5.js";import{n as S}from"./ThreadCard-CXXf9qfA.js";import{t as C}from"./useStickyScroll-BjqdEt_f.js";var w=r(s(),1),T=c();function E(){let{_splat:e=`general`}=h({from:`/c/$`});return(0,T.jsx)(D,{channel:e},e)}function D({channel:r}){let{api:s}=n(),c=t({queryKey:[`channel`,r],queryFn:()=>s.channel(r)}),h=e(),E=o(),D=i(),O=a(),k=d(3e4),[A,j]=(0,w.useState)(!1),[M,N]=(0,w.useState)(!1),P=(0,w.useMemo)(()=>{let e=(c.data??[]).map(e=>({kind:`message`,at:e.ts,id:e.id,message:e})),t=(h.data??[]).filter(e=>e.channel===r).map(e=>({kind:`thread`,at:e.openedAt,id:e.id,thread:e}));return[...e,...t].toSorted((e,t)=>e.at.localeCompare(t.at)||e.id.localeCompare(t.id))},[c.data,h.data,r]),F=c.data?.at(-1)?.id??null;(0,w.useEffect)(()=>m(r,F),[r,F]);let{ref:I,onScroll:L}=C(),[R,z]=r.split(`/`),B=z??R??r,V=z===void 0?void 0:D.data?.find(e=>e.slug===R),H=z===void 0?`society`:V?.name??R,U=O.data?.find(e=>e.ref===r)?.archived,W=V?.archived!==void 0||U!==void 0,G=!W&&!l(z===void 0?null:R??null,B),K=P.filter(e=>e.kind===`thread`&&e.thread.state===`open`);return(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(x,{title:`# ${B}`,subtitle:`${H} · ${c.data?.length??0} messages${K.length>0?` · ${K.length} open threads`:``}`,trailing:A||M||W?null:(0,T.jsxs)(T.Fragment,{children:[G?(0,T.jsx)(p,{onClick:()=>N(!0),children:`Archive…`}):null,(0,T.jsx)(p,{onClick:()=>j(!0),children:`New thread`})]})}),A?(0,T.jsx)(_,{channel:r,onDone:()=>j(!1)}):null,M?(0,T.jsx)(v,{channel:r,onDone:()=>N(!1)}):null,(0,T.jsx)(`div`,{ref:I,onScroll:L,className:`flex-1 overflow-y-auto py-2`,children:c.error instanceof f&&c.error.status===404?(0,T.jsxs)(b,{children:[`There is no channel `,r,`.`]}):c.data===void 0?(0,T.jsx)(b,{children:`Reading the channel…`}):P.length===0?(0,T.jsx)(b,{children:`Nothing has been said here yet.`}):P.map(e=>e.kind===`message`?(0,T.jsx)(y,{message:e.message,members:E.data,now:k},e.id):(0,T.jsx)(S,{thread:e.thread,now:k},e.id))}),c.data===void 0?null:U===void 0?W?(0,T.jsxs)(`p`,{className:`border-t border-line px-4 py-3 text-meta`,children:[H,` is archived, so its channels are read-only.`]}):(0,T.jsx)(g,{target:{channel:r},placeholder:`Message #${B}`}):(0,T.jsxs)(`p`,{className:`border-t border-line px-4 py-3 text-meta`,children:[`Archived `,u(U.at,k),` by `,U.by,`: `,U.reason,`. Its posts, threads, and tasks stay readable; nothing more is posted or filed here.`]})]})}export{E as ChannelView};
1
+ import{I as e,Kt as t,O as n,_n as r,b as i,c as a,g as o,mn as s,pn as c,pt as l,t as u,y as d,z as f}from"./format-C3aawMM6.js";import{s as p}from"./compose-BgpUWGYE.js";import{S as m,T as h,i as g}from"./index-krHkeIbX.js";import{i as _}from"./ThreadForms-ChTFRu-P.js";import{t as v}from"./ChannelForms-BIRwT9CY.js";import{t as y}from"./MessageItem-CHrmjF7P.js";import{n as b,t as x}from"./Pane-MJgGXQBb.js";import{n as S}from"./ThreadCard-D6i69_15.js";import{t as C}from"./useStickyScroll-BILPUgGj.js";var w=r(s(),1),T=c();function E(){let{_splat:e=`general`}=h({from:`/c/$`});return(0,T.jsx)(D,{channel:e},e)}function D({channel:r}){let{api:s}=n(),c=t({queryKey:[`channel`,r],queryFn:()=>s.channel(r)}),h=e(),E=o(),D=i(),O=a(),k=d(3e4),[A,j]=(0,w.useState)(!1),[M,N]=(0,w.useState)(!1),P=(0,w.useMemo)(()=>{let e=(c.data??[]).map(e=>({kind:`message`,at:e.ts,id:e.id,message:e})),t=(h.data??[]).filter(e=>e.channel===r).map(e=>({kind:`thread`,at:e.openedAt,id:e.id,thread:e}));return[...e,...t].toSorted((e,t)=>e.at.localeCompare(t.at)||e.id.localeCompare(t.id))},[c.data,h.data,r]),F=c.data?.at(-1)?.id??null;(0,w.useEffect)(()=>m(r,F),[r,F]);let{ref:I,onScroll:L}=C(),[R,z]=r.split(`/`),B=z??R??r,V=z===void 0?void 0:D.data?.find(e=>e.slug===R),H=z===void 0?`society`:V?.name??R,U=O.data?.find(e=>e.ref===r)?.archived,W=V?.archived!==void 0||U!==void 0,G=!W&&!l(z===void 0?null:R??null,B),K=P.filter(e=>e.kind===`thread`&&e.thread.state===`open`);return(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(x,{title:`# ${B}`,subtitle:`${H} · ${c.data?.length??0} messages${K.length>0?` · ${K.length} open threads`:``}`,trailing:A||M||W?null:(0,T.jsxs)(T.Fragment,{children:[G?(0,T.jsx)(p,{onClick:()=>N(!0),children:`Archive…`}):null,(0,T.jsx)(p,{onClick:()=>j(!0),children:`New thread`})]})}),A?(0,T.jsx)(_,{channel:r,onDone:()=>j(!1)}):null,M?(0,T.jsx)(v,{channel:r,onDone:()=>N(!1)}):null,(0,T.jsx)(`div`,{ref:I,onScroll:L,className:`flex-1 overflow-y-auto py-2`,children:c.error instanceof f&&c.error.status===404?(0,T.jsxs)(b,{children:[`There is no channel `,r,`.`]}):c.data===void 0?(0,T.jsx)(b,{children:`Reading the channel…`}):P.length===0?(0,T.jsx)(b,{children:`Nothing has been said here yet.`}):P.map(e=>e.kind===`message`?(0,T.jsx)(y,{message:e.message,members:E.data,now:k},e.id):(0,T.jsx)(S,{thread:e.thread,now:k},e.id))}),c.data===void 0?null:U===void 0?W?(0,T.jsxs)(`p`,{className:`border-t border-line px-4 py-3 text-meta`,children:[H,` is archived, so its channels are read-only.`]}):(0,T.jsx)(g,{target:{channel:r},placeholder:`Message #${B}`}):(0,T.jsxs)(`p`,{className:`border-t border-line px-4 py-3 text-meta`,children:[`Archived `,u(U.at,k),` by `,U.by,`: `,U.reason,`. Its posts, threads, and tasks stay readable; nothing more is posted or filed here.`]})]})}export{E as ChannelView};
@@ -1,2 +1,2 @@
1
- import{E as e,F as t,L as n,O as r,R as i,T as a,U as o,_ as s,_n as c,a as l,bt as u,d,dt as f,f as p,fn as m,g as h,mn as g,o as _,p as v,pn as y,t as b,w as x,y as S,z as C}from"./format-BWr3zKWg.js";import{l as w,s as T}from"./compose-BG_-Tp87.js";import{t as E}from"./link-CFdt17Sp.js";import{t as ee}from"./CliIcon-CT5ljQDC.js";import{T as te,_ as D,c as O,d as ne,f as re,h as k,i as ie,l as A,m as j,p as ae,u as M,v as oe,w as se}from"./index-Cxqhrg2v.js";import{n as ce,r as N}from"./ThreadForms-CTBaAJ57.js";import{t as P}from"./Markdown-B5zEdYuO.js";import{n as F,t as le}from"./Pane-CFoSKOo5.js";import{t as ue}from"./useStickyScroll-BjqdEt_f.js";import{a as I,c as de,i as L,l as R,n as fe,o as z,s as pe,t as me}from"./citizen-CImM6WB6.js";var B=c(g(),1),V=y(),he={completed:`completed`,timeout:`timed out`,error:`failed`,interrupted:`was interrupted`,blocked:`was blocked`,stopped:`was stopped by you`};function H(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1})}function U({label:e,tone:t,children:n}){return(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`p`,{className:`px-0.5 pb-0.5 text-[10px] tracking-wider text-fg-muted uppercase`,children:e}),(0,V.jsx)(`pre`,{className:`max-h-72 overflow-auto rounded-md bg-surface-0/60 p-2 font-mono text-[11px] leading-relaxed whitespace-pre-wrap break-words ${t}`,children:n})]})}function ge({step:e,open:t}){if(e.kind===`say`)return(0,V.jsx)(`li`,{className:`py-1.5 text-sm`,title:H(e.at),children:(0,V.jsx)(P,{text:e.text})});if(e.kind===`error`)return(0,V.jsx)(`li`,{className:`py-1 font-mono text-xs break-words text-red-400`,title:H(e.at),children:e.message});if(e.kind===`steer`)return(0,V.jsx)(`li`,{children:(0,V.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,V.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-center gap-2 rounded-md px-1.5 py-1 text-xs hover:bg-surface-2/40`,children:[(0,V.jsx)(`span`,{"aria-hidden":`true`,className:`grid w-3 shrink-0 place-items-center text-sky-300`,children:`↳`}),(0,V.jsxs)(`span`,{className:`shrink-0 text-fg-tertiary`,children:[`Took `,ne(e.posts.length)]}),(0,V.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg-secondary`,children:e.from.length===0?``:`from ${e.from.join(`, `)}, delivered mid-turn`}),(0,V.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:H(e.at)})]}),(0,V.jsx)(`ul`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:e.posts.map(e=>(0,V.jsxs)(`li`,{className:`rounded-md bg-surface-0/40 px-2.5 py-2`,children:[(0,V.jsxs)(`p`,{className:`flex gap-1.5 text-meta`,children:[(0,V.jsx)(`span`,{className:`text-fg-secondary`,children:e.author}),(0,V.jsxs)(`span`,{className:`min-w-0 truncate`,children:[`in `,e.where]}),e.at===``?null:(0,V.jsx)(`span`,{className:`ml-auto shrink-0 font-mono`,children:H(e.at)})]}),(0,V.jsx)(`div`,{className:`mt-1 text-sm`,children:(0,V.jsx)(P,{text:e.body})})]},`${e.at}-${e.author}`))})]})});let n=e.ok===null?(0,V.jsx)(`span`,{"aria-label":`running`,className:`size-1.5 animate-pulse rounded-full bg-amber-300`}):e.ok?(0,V.jsx)(`span`,{"aria-label":`succeeded`,className:`text-[11px] text-emerald-400`,children:`✓`}):(0,V.jsx)(`span`,{"aria-label":`failed`,className:`text-[11px] text-red-400`,children:`✕`});return(0,V.jsx)(`li`,{children:(0,V.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,V.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-center gap-2 rounded-md px-1.5 py-1 text-xs hover:bg-surface-2/40`,children:[(0,V.jsx)(`span`,{className:`grid w-3 shrink-0 place-items-center`,children:n}),(0,V.jsx)(`span`,{className:`shrink-0 font-mono text-fg-tertiary`,children:re(e.name)}),(0,V.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-fg-secondary`,children:e.summary}),(0,V.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:H(e.at)})]}),(0,V.jsxs)(`div`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:[(0,V.jsx)(U,{label:`Input`,tone:`text-fg-secondary`,children:e.detail}),e.output===null?null:(0,V.jsx)(U,{label:e.ok===!1?`Returned an error`:`Returned`,tone:e.ok===!1?`text-red-300`:`text-fg-tertiary`,children:e.output})]})]})})}function W({steps:e}){let[t,n]=(0,B.useState)(!1),r=e.filter(e=>e.kind===`tool`).length;return e.length===0?(0,V.jsx)(`p`,{className:`mt-2 text-meta`,children:`No steps yet.`}):(0,V.jsxs)(V.Fragment,{children:[r===0?null:(0,V.jsxs)(`p`,{className:`mt-2 flex items-center gap-2 text-meta`,children:[r===1?`1 tool call`:`${r} tool calls`,(0,V.jsx)(`button`,{type:`button`,onClick:()=>n(!t),className:`rounded-md px-1.5 py-0.5 text-fg-tertiary transition-colors hover:bg-surface-2/60 hover:text-fg-primary`,children:t?`Collapse all`:`Expand all`})]}),(0,V.jsx)(`ol`,{className:`mt-1 space-y-0.5`,children:e.map(e=>(0,V.jsx)(ge,{step:e,open:t},e.seq))})]})}function _e({turn:e,running:t,now:n}){return e.end===null?t?(0,V.jsxs)(`p`,{className:`mt-3 flex items-center gap-2 text-meta`,"aria-live":`polite`,children:[(0,V.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}),`Working · last step `,b(e.lastAt,n)]}):(0,V.jsx)(`p`,{className:`mt-3 text-meta`,children:`The turn ended without a report.`}):(0,V.jsxs)(`section`,{className:`mt-3 rounded-xl bg-surface-2/40 px-3.5 py-3 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]`,children:[(0,V.jsxs)(`p`,{className:`text-caps`,children:[`The turn `,he[e.end.exitReason],` `,b(e.end.at,n),e.fromStart?` · ${A(e.startedAt,Date.parse(e.end.at))}`:``]}),e.end.summary===null?null:(0,V.jsx)(`p`,{className:`mt-1 text-sm text-fg-secondary`,children:e.end.summary})]})}var G=30,ve={turn:`turn`,board:`board`,merge:`both kept`},ye={turn:`Changed by a turn`,board:`Written by the board`,merge:`Both versions kept`};function be(e){return e.status===`added`?`new`:e.status===`deleted`?`deleted`:e.added===null||e.removed===null?`binary`:`+${e.added} −${e.removed}`}function xe(e){return e.files.map(e=>`${e.path} ${be(e)}`).join(`, `)}function Se(e){return e.startsWith(`@@`)||e.startsWith(`\\`)?`text-fg-muted`:e.startsWith(`+`)?`text-emerald-300`:e.startsWith(`-`)?`text-red-300`:`text-fg-tertiary`}function Ce({file:e}){return(0,V.jsxs)(`div`,{children:[(0,V.jsxs)(`p`,{className:`text-xs text-fg-secondary`,children:[e.path,e.status===`modified`?``:(0,V.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,e.status]})]}),e.patch===null?(0,V.jsx)(`p`,{className:`mt-1 text-meta`,children:`A binary file; its contents are not shown.`}):e.patch===``?(0,V.jsx)(`p`,{className:`mt-1 text-meta`,children:`Empty.`}):(0,V.jsx)(`pre`,{className:`mt-1 max-h-96 overflow-auto rounded-md bg-surface-0/60 p-2 font-mono text-[11px] leading-relaxed`,children:e.patch.split(`
1
+ import{E as e,F as t,L as n,O as r,R as i,T as a,U as o,_ as s,_n as c,a as l,bt as u,d,dt as f,f as p,fn as m,g as h,mn as g,o as _,p as v,pn as y,t as b,w as x,y as S,z as C}from"./format-C3aawMM6.js";import{l as w,s as T}from"./compose-BgpUWGYE.js";import{t as E}from"./link-DAMxBItI.js";import{t as ee}from"./CliIcon-tYTwI_RQ.js";import{T as te,_ as D,c as O,d as ne,f as re,h as k,i as ie,l as A,m as j,p as ae,u as M,v as oe,w as se}from"./index-krHkeIbX.js";import{n as ce,r as N}from"./ThreadForms-ChTFRu-P.js";import{t as P}from"./Markdown-BLiIulgZ.js";import{n as F,t as le}from"./Pane-MJgGXQBb.js";import{t as ue}from"./useStickyScroll-BILPUgGj.js";import{a as I,c as de,i as L,l as R,n as fe,o as z,s as pe,t as me}from"./citizen-D-dxX00V.js";var B=c(g(),1),V=y(),he={completed:`completed`,timeout:`timed out`,error:`failed`,interrupted:`was interrupted`,blocked:`was blocked`,stopped:`was stopped by you`};function H(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1})}function U({label:e,tone:t,children:n}){return(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`p`,{className:`px-0.5 pb-0.5 text-[10px] tracking-wider text-fg-muted uppercase`,children:e}),(0,V.jsx)(`pre`,{className:`max-h-72 overflow-auto rounded-md bg-surface-0/60 p-2 font-mono text-[11px] leading-relaxed whitespace-pre-wrap break-words ${t}`,children:n})]})}function ge({step:e,open:t}){if(e.kind===`say`)return(0,V.jsx)(`li`,{className:`py-1.5 text-sm`,title:H(e.at),children:(0,V.jsx)(P,{text:e.text})});if(e.kind===`error`)return(0,V.jsx)(`li`,{className:`py-1 font-mono text-xs break-words text-red-400`,title:H(e.at),children:e.message});if(e.kind===`steer`)return(0,V.jsx)(`li`,{children:(0,V.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,V.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-center gap-2 rounded-md px-1.5 py-1 text-xs hover:bg-surface-2/40`,children:[(0,V.jsx)(`span`,{"aria-hidden":`true`,className:`grid w-3 shrink-0 place-items-center text-sky-300`,children:`↳`}),(0,V.jsxs)(`span`,{className:`shrink-0 text-fg-tertiary`,children:[`Took `,ne(e.posts.length)]}),(0,V.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg-secondary`,children:e.from.length===0?``:`from ${e.from.join(`, `)}, delivered mid-turn`}),(0,V.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:H(e.at)})]}),(0,V.jsx)(`ul`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:e.posts.map(e=>(0,V.jsxs)(`li`,{className:`rounded-md bg-surface-0/40 px-2.5 py-2`,children:[(0,V.jsxs)(`p`,{className:`flex gap-1.5 text-meta`,children:[(0,V.jsx)(`span`,{className:`text-fg-secondary`,children:e.author}),(0,V.jsxs)(`span`,{className:`min-w-0 truncate`,children:[`in `,e.where]}),e.at===``?null:(0,V.jsx)(`span`,{className:`ml-auto shrink-0 font-mono`,children:H(e.at)})]}),(0,V.jsx)(`div`,{className:`mt-1 text-sm`,children:(0,V.jsx)(P,{text:e.body})})]},`${e.at}-${e.author}`))})]})});let n=e.ok===null?(0,V.jsx)(`span`,{"aria-label":`running`,className:`size-1.5 animate-pulse rounded-full bg-amber-300`}):e.ok?(0,V.jsx)(`span`,{"aria-label":`succeeded`,className:`text-[11px] text-emerald-400`,children:`✓`}):(0,V.jsx)(`span`,{"aria-label":`failed`,className:`text-[11px] text-red-400`,children:`✕`});return(0,V.jsx)(`li`,{children:(0,V.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,V.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-center gap-2 rounded-md px-1.5 py-1 text-xs hover:bg-surface-2/40`,children:[(0,V.jsx)(`span`,{className:`grid w-3 shrink-0 place-items-center`,children:n}),(0,V.jsx)(`span`,{className:`shrink-0 font-mono text-fg-tertiary`,children:re(e.name)}),(0,V.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-fg-secondary`,children:e.summary}),(0,V.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:H(e.at)})]}),(0,V.jsxs)(`div`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:[(0,V.jsx)(U,{label:`Input`,tone:`text-fg-secondary`,children:e.detail}),e.output===null?null:(0,V.jsx)(U,{label:e.ok===!1?`Returned an error`:`Returned`,tone:e.ok===!1?`text-red-300`:`text-fg-tertiary`,children:e.output})]})]})})}function W({steps:e}){let[t,n]=(0,B.useState)(!1),r=e.filter(e=>e.kind===`tool`).length;return e.length===0?(0,V.jsx)(`p`,{className:`mt-2 text-meta`,children:`No steps yet.`}):(0,V.jsxs)(V.Fragment,{children:[r===0?null:(0,V.jsxs)(`p`,{className:`mt-2 flex items-center gap-2 text-meta`,children:[r===1?`1 tool call`:`${r} tool calls`,(0,V.jsx)(`button`,{type:`button`,onClick:()=>n(!t),className:`rounded-md px-1.5 py-0.5 text-fg-tertiary transition-colors hover:bg-surface-2/60 hover:text-fg-primary`,children:t?`Collapse all`:`Expand all`})]}),(0,V.jsx)(`ol`,{className:`mt-1 space-y-0.5`,children:e.map(e=>(0,V.jsx)(ge,{step:e,open:t},e.seq))})]})}function _e({turn:e,running:t,now:n}){return e.end===null?t?(0,V.jsxs)(`p`,{className:`mt-3 flex items-center gap-2 text-meta`,"aria-live":`polite`,children:[(0,V.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}),`Working · last step `,b(e.lastAt,n)]}):(0,V.jsx)(`p`,{className:`mt-3 text-meta`,children:`The turn ended without a report.`}):(0,V.jsxs)(`section`,{className:`mt-3 rounded-xl bg-surface-2/40 px-3.5 py-3 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]`,children:[(0,V.jsxs)(`p`,{className:`text-caps`,children:[`The turn `,he[e.end.exitReason],` `,b(e.end.at,n),e.fromStart?` · ${A(e.startedAt,Date.parse(e.end.at))}`:``]}),e.end.summary===null?null:(0,V.jsx)(`p`,{className:`mt-1 text-sm text-fg-secondary`,children:e.end.summary})]})}var G=30,ve={turn:`turn`,board:`board`,merge:`both kept`},ye={turn:`Changed by a turn`,board:`Written by the board`,merge:`Both versions kept`};function be(e){return e.status===`added`?`new`:e.status===`deleted`?`deleted`:e.added===null||e.removed===null?`binary`:`+${e.added} −${e.removed}`}function xe(e){return e.files.map(e=>`${e.path} ${be(e)}`).join(`, `)}function Se(e){return e.startsWith(`@@`)||e.startsWith(`\\`)?`text-fg-muted`:e.startsWith(`+`)?`text-emerald-300`:e.startsWith(`-`)?`text-red-300`:`text-fg-tertiary`}function Ce({file:e}){return(0,V.jsxs)(`div`,{children:[(0,V.jsxs)(`p`,{className:`text-xs text-fg-secondary`,children:[e.path,e.status===`modified`?``:(0,V.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,e.status]})]}),e.patch===null?(0,V.jsx)(`p`,{className:`mt-1 text-meta`,children:`A binary file; its contents are not shown.`}):e.patch===``?(0,V.jsx)(`p`,{className:`mt-1 text-meta`,children:`Empty.`}):(0,V.jsx)(`pre`,{className:`mt-1 max-h-96 overflow-auto rounded-md bg-surface-0/60 p-2 font-mono text-[11px] leading-relaxed`,children:e.patch.split(`
2
2
  `).map((e,t)=>(0,V.jsx)(`span`,{className:`block whitespace-pre-wrap break-words ${Se(e)}`,children:e===``?` `:e},t))}),e.truncated?(0,V.jsx)(`p`,{className:`mt-1 text-meta`,children:`The rest of this file's change is cut.`}):null]})}function we({name:e,change:t}){let n=d(e,t.commit,!0);return(0,V.jsxs)(`div`,{className:`space-y-3 px-4 pt-1 pb-3`,children:[(0,V.jsxs)(`p`,{className:`text-xs text-fg-secondary`,children:[t.kind===`merge`?`Two turns on different runners changed the same lines at once. The file kept one turn's version, and this copy holds the other's until the citizen reconciles them.`:t.kind===`board`?`Written by the board: ${t.subject.replace(/^home: /,``)}.`:t.turnId===void 0?t.subject:(0,V.jsx)(E,{to:`/citizen/$name`,params:{name:e},search:{tab:`turns`,turn:t.turnId},className:`text-fg-secondary underline decoration-line underline-offset-2 hover:text-fg-primary`,children:`Open the turn that made it`}),(0,V.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,H(t.at)]})]}),n.data===void 0?(0,V.jsx)(`p`,{className:`text-meta`,children:n.isError?`Could not read the change.`:`Reading the change…`}):n.data.map(e=>(0,V.jsx)(Ce,{file:e},e.path))]})}function Te({name:e,change:t,now:n}){let[r,i]=(0,B.useState)(!1),a=t.files.length===0?t.subject:xe(t);return(0,V.jsx)(`li`,{className:`border-b border-line/60 last:border-b-0`,children:(0,V.jsxs)(`details`,{className:`group`,onToggle:e=>i(e.currentTarget.open),children:[(0,V.jsx)(`summary`,{"aria-label":`${ye[t.kind]} ${b(t.at,n)}: ${a}`,className:`block cursor-pointer list-none px-4 py-2.5 transition-colors hover:bg-surface-2/30 group-open:bg-surface-2/20`,children:(0,V.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,V.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:ve[t.kind]}),(0,V.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg-secondary`,children:a}),(0,V.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:b(t.at,n)}),(0,V.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]})}),r?(0,V.jsx)(we,{name:e,change:t}):null]})})}function Ee({name:e}){let[t,n]=(0,B.useState)(G),r=v(e,t),i=S(3e4);if(r.data===void 0)return(0,V.jsx)(F,{children:r.isError?`Could not read the home's history.`:`Reading the history…`});let{changes:a,more:o}=r.data;return a.length===0?(0,V.jsxs)(F,{children:[e,`'s home has no history yet; it starts with the citizen's first turn.`]}):(0,V.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,V.jsxs)(`p`,{className:`px-4 pt-3 pb-1 text-meta`,children:[`What `,e,`'s turns changed in its memory, skills, and profile, newest first.`]}),(0,V.jsx)(`ol`,{children:a.map(t=>(0,V.jsx)(Te,{name:e,change:t,now:i},t.commit))}),o?(0,V.jsx)(`button`,{type:`button`,onClick:()=>n(t+G),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:`Show earlier changes`}):null]})}function K({title:e,children:t}){return(0,V.jsxs)(`section`,{className:`border-t border-line pt-4 first:border-t-0 first:pt-0`,children:[(0,V.jsx)(`h3`,{className:`text-section`,children:e}),(0,V.jsx)(`div`,{className:`mt-2`,children:t})]})}function De({member:e,charter:t}){let n=s(e.name),r=_(e.name),i=p(e.name),a=S(3e4);return(0,V.jsxs)(`div`,{className:`flex-1 space-y-5 overflow-y-auto px-4 py-4`,children:[i.data===void 0||i.data.length===0?null:(0,V.jsxs)(K,{title:`Edits to reconcile`,children:[(0,V.jsxs)(`p`,{className:`text-sm text-fg-secondary`,children:[`Two turns on different runners changed these files at once. Each file kept one version; the other waits beside it until `,e.name,` merges it in and deletes the copy.`]}),(0,V.jsx)(`ul`,{className:`mt-2 space-y-1.5`,children:i.data.map(e=>(0,V.jsxs)(`li`,{className:`text-sm`,children:[(0,V.jsx)(`span`,{className:`text-fg-primary`,children:e.file}),(0,V.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,e.path.slice(e.path.lastIndexOf(`/`)+1),` · left`,` `,b(e.since,a)]})]},e.path))})]}),(0,V.jsx)(K,{title:`Profile`,children:e.profile.trim()===``?(0,V.jsx)(`p`,{className:`text-meta`,children:`No profile yet. The citizen writes its own profile.md.`}):(0,V.jsx)(P,{text:R(e.profile,`Profile`)})}),(0,V.jsx)(K,{title:`Core memory`,children:n.data===void 0?(0,V.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):n.data.body.trim()===``?(0,V.jsx)(`p`,{className:`text-meta`,children:`Empty. Every turn loads this file in full.`}):(0,V.jsx)(P,{text:R(n.data.body,`Core memory`)})}),(0,V.jsx)(K,{title:`Own skills`,children:r.data===void 0?(0,V.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):r.data.length===0?(0,V.jsx)(`p`,{className:`text-meta`,children:`None yet.`}):(0,V.jsx)(`ul`,{className:`space-y-1.5`,children:r.data.map(e=>(0,V.jsxs)(`li`,{className:`text-sm`,children:[(0,V.jsx)(`span`,{className:`text-fg-primary`,children:e.name}),e.summary===``?null:(0,V.jsxs)(`span`,{className:`text-fg-secondary`,children:[` · `,e.summary]})]},e.name))})}),t===void 0?null:(0,V.jsxs)(K,{title:`Charter of ${t.name}`,children:[(0,V.jsx)(`p`,{className:`text-sm text-fg-secondary`,children:t.purpose}),(0,V.jsxs)(`p`,{className:`mt-2 text-meta`,children:[`Wakes on mentions, stages, and `,t.wakeTriggers.join(`, `)||`nothing else`,t.resident?` · keeps a warm session`:``,t.reflects?` · reflects`:``]}),(0,V.jsx)(`p`,{className:`mt-2 flex flex-wrap gap-1`,children:t.verbs.map(e=>(0,V.jsx)(`span`,{className:`rounded-md bg-surface-2/70 px-1.5 py-px font-mono text-[11px] text-fg-tertiary`,children:e},e))})]})]})}function q(e,t){let r=n(e,t?.turnId??null);return{turn:(0,B.useMemo)(()=>t===void 0||r.data===void 0?void 0:ae(r.data,e,t.project,t),[t,r.data,e]),loading:t?.turnId!==void 0&&r.isPending,missing:t!==void 0&&(t.turnId===void 0||r.isError)}}var J=50;function Oe({name:e,entry:t,now:n,opened:r}){let[i,a]=(0,B.useState)(r),o=(0,B.useRef)(null);(0,B.useEffect)(()=>{r&&o.current?.scrollIntoView({block:`start`})},[r]);let s=oe(),c=pe(t),l=t.thread===void 0?t.channel===void 0?null:`#${t.channel}`:s.get(t.thread)?.title??`a thread`,u=t.error??t.summary??``,d=t.error===null?`text-fg-secondary`:`text-red-300`;return(0,V.jsx)(`li`,{ref:o,className:`border-b border-line/60 last:border-b-0`,children:(0,V.jsxs)(`details`,{className:`group`,open:i,onToggle:e=>a(e.currentTarget.open),children:[(0,V.jsxs)(`summary`,{className:`block cursor-pointer list-none px-4 py-2.5 transition-colors hover:bg-surface-2/30 group-open:bg-surface-2/20`,children:[(0,V.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,V.jsxs)(`span`,{className:`min-w-0 truncate text-fg-secondary`,children:[L(t.project),l===null?``:` · ${l}`]}),(0,V.jsx)(`span`,{className:`text-fg-muted`,children:t.trigger}),(0,V.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-fg-muted`,children:[me(t),` `,b(t.ts,n)]}),(0,V.jsx)(`span`,{className:`shrink-0 font-mono text-[11px] text-fg-tertiary`,title:t.usage===void 0?void 0:I(t.usage),children:[c,t.toolCalls===void 0?null:`${t.toolCalls} tools`,t.usage===void 0?null:z(t.usage)].filter(e=>e!==null).join(` · `)}),(0,V.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]}),u.trim()===``?null:(0,V.jsx)(`span`,{className:`mt-1 line-clamp-2 block text-xs leading-relaxed group-open:hidden ${d}`,children:(0,V.jsx)(D,{text:u,links:!1})})]}),i?(0,V.jsx)(ke,{name:e,entry:t,text:u,tone:d}):null]})})}function ke({name:e,entry:t,text:n,tone:r}){let i=q(e,t);return(0,V.jsxs)(`div`,{className:`px-4 pt-1 pb-3`,children:[n.trim()===``?null:(0,V.jsx)(`p`,{className:`text-xs leading-relaxed whitespace-pre-wrap ${r}`,children:(0,V.jsx)(D,{text:n})}),(0,V.jsx)(`div`,{className:`mt-2`,children:t.turnId===void 0?(0,V.jsx)(`p`,{className:`text-meta`,children:`This turn ran before turns kept their steps.`}):i.loading?(0,V.jsx)(`p`,{className:`text-meta`,children:`Reading the steps…`}):i.turn===void 0?(0,V.jsx)(`p`,{className:`text-meta`,children:`No steps were kept for this turn.`}):(0,V.jsxs)(V.Fragment,{children:[t.startedAt===void 0?null:(0,V.jsxs)(`p`,{className:`text-caps`,children:[`Started `,H(t.startedAt)]}),(0,V.jsx)(W,{steps:i.turn.steps})]})})]})}function Ae({name:e,opened:t}){let[n,r]=(0,B.useState)(J),a=i(e,n),o=S(3e4);if(a.data===void 0)return(0,V.jsx)(F,{children:`Reading the turns…`});let s=a.data.toReversed();if(s.length===0)return(0,V.jsxs)(F,{children:[e,` has not finished a turn yet.`]});let c=fe(s),l=c.usage===null?``:` · ${z(c.usage)}${c.withUsage<c.turns?` over ${c.withUsage} of them`:``}`;return(0,V.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,V.jsxs)(`p`,{className:`px-4 pt-3 pb-1 text-meta`,title:c.usage===null?void 0:I(c.usage),children:[c.turns===1?`1 turn`:`${c.turns} turns`,c.failed===0?``:`, ${c.failed} not completed`,l]}),t!==null&&!s.some(e=>e.turnId===t)?(0,V.jsx)(`p`,{className:`px-4 pb-1 text-meta`,children:a.data.length===n?`The turn this address opens is further back; show earlier turns to reach it.`:`The turn this address opens is not in this citizen's history.`}):null,(0,V.jsx)(`ol`,{children:s.map(n=>(0,V.jsx)(Oe,{name:e,entry:n,now:o,opened:t!==null&&n.turnId===t},n.id))}),a.data.length===n?(0,V.jsxs)(`button`,{type:`button`,onClick:()=>r(n+J),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:[`Show `,J,` earlier turns`]}):null]})}function je(e){return e===void 0?``:`${e.name}${e.id===null?``:` · ${e.id}`}`}function Y({label:e,choices:t,value:n,onChange:r,listClassName:i=`inset-x-0`}){let[a,o]=(0,B.useState)(!1),s=(0,B.useRef)(null),c=(0,B.useRef)(null),l=(0,B.useRef)([]),u=t.findIndex(e=>e.value===n);(0,B.useEffect)(()=>{if(!a)return;l.current[Math.max(u,0)]?.focus();let e=e=>{e.target instanceof Node&&s.current?.contains(e.target)===!0||o(!1)};return window.addEventListener(`pointerdown`,e),()=>window.removeEventListener(`pointerdown`,e)},[a,u]);let d=e=>{if(e.key===`Escape`){e.stopPropagation(),o(!1),c.current?.focus();return}if(e.key!==`ArrowDown`&&e.key!==`ArrowUp`)return;e.preventDefault();let n=(l.current.findIndex(e=>e===document.activeElement)+(e.key===`ArrowDown`?1:-1)+t.length)%t.length;l.current[n]?.focus()},f=t[u];return(0,V.jsxs)(`div`,{ref:s,className:`relative min-w-0 flex-1`,children:[(0,V.jsxs)(`button`,{ref:c,type:`button`,"aria-label":`${e}: ${je(f)}`,"aria-expanded":a,onClick:()=>o(!a),onKeyDown:a?d:void 0,className:`flex h-7 w-full items-center gap-1.5 rounded-md bg-surface-2/60 px-2.5 text-xs text-fg-secondary transition-colors hover:bg-surface-2 focus-visible:ring-2 focus-visible:ring-fg-primary/30 focus-visible:outline-none`,children:[(0,V.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-left`,children:[f?.name,f?.id===null||f===void 0?null:(0,V.jsxs)(`span`,{className:`text-fg-tertiary`,children:[` · `,f.id]})]}),(0,V.jsx)(`span`,{"aria-hidden":`true`,className:`text-[10px] text-fg-muted transition-transform ${a?`rotate-180`:``}`,children:`▾`})]}),a?(0,V.jsx)(`div`,{className:`absolute ${i} top-full z-20 mt-1 max-h-80 overflow-y-auto rounded-xl bg-surface-1/95 p-1 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.08),0_16px_32px_-12px_rgba(0,0,0,0.8)] backdrop-blur-xl`,children:t.map((e,t)=>{let i=e.value===n;return(0,V.jsxs)(`button`,{ref:e=>{l.current[t]=e},type:`button`,"aria-current":i?`true`:void 0,onKeyDown:d,onClick:()=>{r(e.value),o(!1),c.current?.focus()},className:`flex w-full items-start gap-2 rounded-lg px-2.5 py-1.5 text-left transition-colors focus-visible:outline-none ${i?`bg-surface-2/80`:`hover:bg-surface-2/50 focus-visible:bg-surface-2/50`}`,children:[(0,V.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,V.jsxs)(`span`,{className:`block truncate text-xs text-fg-secondary`,children:[e.name,e.id===null?null:(0,V.jsxs)(`span`,{className:`text-fg-tertiary`,children:[` · `,e.id]})]}),e.description===``?null:(0,V.jsx)(`span`,{className:`block truncate text-[11px] text-fg-muted`,children:e.description})]}),(0,V.jsx)(`span`,{"aria-hidden":`true`,className:`w-3 shrink-0 pt-px text-[11px] text-fg-primary`,children:i?`✓`:``})]},e.value)})}):null]})}var X=``,Z=``;function Me(e,t){return[{value:X,name:`CLI default`,id:e.find(e=>e.isDefault)?.name??null,description:`Whatever the CLI runs when no model is set.`},...e.map(e=>({value:e.id,name:e.name,id:e.name===e.id?null:e.id,description:e.description})),...t===null?[]:[{value:t,name:t,id:null,description:`Not in the CLI's list.`}]]}function Ne(e,t){return[{value:Z,name:`Default`,id:e?.defaultEffort??null,description:`Whatever the model runs unset.`},...(e?.efforts??[]).map(e=>({value:e.id,name:e.id,id:null,description:e.description})),...t===null?[]:[{value:t,name:t,id:null,description:`Not in the model's list.`}]]}function Pe({member:e,onDone:t}){let{api:n}=r(),i=m(),a=l(e.name),o=e.model??X,s=e.effort??Z,[c,u]=(0,B.useState)(o),[d,f]=(0,B.useState)(s),p=w({mutationFn:async()=>{c!==o&&await n.setModel(e.name,c===X?null:c),d!==s&&await n.setEffort(e.name,d===Z?null:d)},onSettled:()=>void i.invalidateQueries({queryKey:[`members`]}),onSuccess:t}),h=a.data?.models??[],g=e.model!==void 0&&!h.some(t=>t.id===e.model)?e.model:null,_=e=>h.find(t=>e===X?t.isDefault:t.id===e),v=_(c)?.efforts??[],y=d!==Z&&!v.some(e=>e.id===d)?d:null,b=e=>{u(e);let t=_(e)?.efforts??[];d!==Z&&!t.some(e=>e.id===d)&&f(Z)},x=c!==o||d!==s;return(0,V.jsxs)(`form`,{"aria-label":`Model of ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),p.mutate()},children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a.isPending?(0,V.jsxs)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:[`Asking `,e.cli,` for its models…`]}):a.error===null?(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(Y,{label:`Model`,choices:Me(h,g),value:c,onChange:b}),v.length===0&&y===null?null:(0,V.jsx)(`div`,{className:`flex w-32 shrink-0`,children:(0,V.jsx)(Y,{label:`Effort`,choices:Ne(_(c),y),value:d,onChange:f,listClassName:`right-0 w-64`})})]}):(0,V.jsxs)(`p`,{role:`alert`,className:`min-w-0 flex-1 truncate text-xs text-red-400`,children:[e.cli,` did not list its models:`,` `,a.error instanceof C?a.error.message:`the board server did not answer`]}),(0,V.jsx)(T,{onClick:t,children:`Cancel`}),(0,V.jsx)(T,{variant:`primary`,type:`submit`,disabled:p.isPending||!x||a.error!==null,children:p.isPending?`Saving…`:`Save`})]}),a.data===void 0?null:(0,V.jsxs)(`p`,{className:`text-meta`,children:[`As `,a.data.cli,` on `,a.data.runner,` lists them, where this citizen's turns run.`]}),(0,V.jsx)(N,{error:p.error})]})}var Q=``;function Fe(e,t){let n=t.cli;return[e.status,e.clis.length===0?`offers no CLI yet`:e.clis.join(`, `),n!==null&&e.clis.length>0&&!e.clis.includes(n)?`has no ${n}`:``,e.capabilities.length===0?``:e.capabilities.join(`, `)].filter(e=>e!==``).join(` · `)}function Ie(e,t){return[{value:Q,name:`Any runner`,id:null,description:`Pinned to the least busy runner on its next turn outside a project.`},...e.map(e=>({value:e.name,name:e.name,id:e.os,description:Fe(e,t)}))]}function Le({member:e,onDone:t}){let{api:n}=r(),i=m(),o=a(),s=e.homeRunner??Q,[c,l]=(0,B.useState)(s),u=w({mutationFn:()=>n.setRunner(e.name,c===Q?null:c),onSuccess:()=>{i.invalidateQueries({queryKey:[`members`]}),t()}});return(0,V.jsxs)(`form`,{"aria-label":`Runner of ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),u.mutate()},children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[o.data===void 0?(0,V.jsx)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:`Reading the runners…`}):(0,V.jsx)(Y,{label:`Runner`,choices:Ie(o.data,e),value:c,onChange:l}),(0,V.jsx)(T,{onClick:t,children:`Cancel`}),(0,V.jsx)(T,{variant:`primary`,type:`submit`,disabled:u.isPending||c===s,children:u.isPending?`Saving…`:`Run here`})]}),(0,V.jsx)(`p`,{className:`text-meta`,children:`Its conversations outside projects start afresh there from its next turn; its memory and skills follow it. Project work runs where each project lives.`}),(0,V.jsx)(N,{error:u.error})]})}function Re(e){if(e.thread!==void 0)return{threadId:e.thread};let t=e.scope===`society`?null:e.scope;return e.channel===void 0?{channel:e.askedIn??u(t,`general`)}:{channel:u(t,e.channel)}}function ze({name:e,turn:t}){let{api:n}=r(),i=m(),[a,o]=(0,B.useState)(!1),s=w({mutationFn:()=>n.stopTurn(t.turnId),onSuccess:()=>{o(!1),i.invalidateQueries({queryKey:[`scheduler`]})}});return(0,V.jsxs)(`div`,{className:`border-t border-line`,children:[(0,V.jsx)(ie,{target:Re(t),initialText:`@${e} `,placeholder:t.steerable?`Message ${e} while it works`:`Message ${e} for its next turn`,className:`px-3 pt-3 pb-2`},t.turnId),t.stoppable?(0,V.jsxs)(`div`,{className:`flex items-center gap-2 px-3 pb-3`,children:[(0,V.jsx)(`p`,{className:`min-w-0 flex-1 text-[11px] leading-snug text-fg-muted`,children:a?`Ends the turn now. What it was shown counts as read; its stages stay held.`:t.steerable?`Posts reach the turn at its next step.`:`This runner delivers posts after the turn ends.`}),a?(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(T,{onClick:()=>{o(!1),s.reset()},children:`Keep it running`}),(0,V.jsx)(T,{variant:`primary`,disabled:s.isPending,onClick:()=>{s.mutate()},children:s.isPending?`Stopping…`:`Stop the turn`})]}):(0,V.jsx)(T,{onClick:()=>o(!0),children:`Stop…`})]}):null,s.error===null?null:(0,V.jsx)(`div`,{className:`px-3 pb-3`,children:(0,V.jsx)(N,{error:s.error})})]})}function Be({member:e,scopes:t,preferred:n,running:i,paused:a,onDone:o}){let{api:s}=r(),c=m(),[l,u]=(0,B.useState)(`manual`),[d,f]=(0,B.useState)(n!==null&&t.includes(n)?n:t[0]??``),[p,h]=(0,B.useState)(``),g=(0,B.useRef)(null);(0,B.useEffect)(()=>g.current?.focus(),[]);let _=w({mutationFn:()=>s.wake({agent:e.name,project:d,kind:l,...p.trim()===``?{}:{reason:p.trim()}}),onSuccess:()=>{c.invalidateQueries({queryKey:[`scheduler`]}),o()}}),v=L(d),y=l===`reflection`?`Asks ${e.name} to reflect at ${v}: consolidate its memory, skills, and profile, and take no new work. It restarts the reflection clock.`:`Starts a turn for ${e.name} at ${v} as soon as the scheduler takes it.`,b=a?` The society is paused, so it waits until you resume.`:i.includes(d)?` ${e.name} is in a turn there now; this one follows it.`:``;return(0,V.jsxs)(`form`,{"aria-label":`Wake ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),_.mutate()},children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,V.jsxs)(`fieldset`,{className:`flex gap-1`,children:[(0,V.jsx)(`legend`,{className:`sr-only`,children:`Kind of turn`}),[`manual`,`reflection`].map(e=>(0,V.jsxs)(`label`,{className:`cursor-pointer rounded-md px-2.5 py-1 text-xs transition-colors has-focus-visible:ring-2 has-focus-visible:ring-fg-primary/30 ${l===e?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:[(0,V.jsx)(`input`,{type:`radio`,name:`kind`,value:e,checked:l===e,onChange:()=>u(e),className:`sr-only`}),e===`manual`?`A turn`:`A reflection`]},e))]}),(0,V.jsxs)(`label`,{className:`ml-auto flex items-center gap-2 text-xs text-fg-tertiary`,children:[`at`,(0,V.jsx)(`select`,{value:d,onChange:e=>f(e.target.value),"aria-label":`Where`,className:`rounded-md bg-surface-2/60 px-2 py-1 text-xs text-fg-primary outline-none`,children:t.map(e=>(0,V.jsx)(`option`,{value:e,children:L(e)},e))})]})]}),(0,V.jsx)(`textarea`,{ref:g,value:p,rows:2,placeholder:l===`reflection`?`Anything to reflect on in particular? Optional.`:`What should it look at? It reads this as the reason it was woken.`,"aria-label":`Reason`,onChange:e=>h(e.target.value),className:`${ce} resize-none`}),(0,V.jsxs)(`p`,{className:`text-[11px] leading-relaxed text-fg-muted`,children:[y,b,` Each turn costs money.`]}),(0,V.jsxs)(`div`,{className:`flex items-center justify-end gap-2`,children:[(0,V.jsx)(T,{onClick:o,children:`Cancel`}),(0,V.jsx)(T,{variant:`primary`,type:`submit`,disabled:_.isPending||d===``,children:_.isPending?`Waking…`:l===`reflection`?`Ask for a reflection`:`Wake ${e.name}`})]}),(0,V.jsx)(N,{error:_.error})]})}var Ve={working:`bg-emerald-500/15 text-emerald-300`,queued:`bg-amber-500/15 text-amber-300`,idle:`bg-surface-2 text-fg-tertiary`};function He({project:e,name:n}){let r=(t(e).data??[]).filter(e=>e.status===`claimed`&&e.claimedBy===n);return r.length===0?null:(0,V.jsx)(`ul`,{className:`mt-1.5 space-y-1`,children:r.map(e=>(0,V.jsx)(`li`,{children:(0,V.jsxs)(E,{to:`/task/$taskId`,params:{taskId:e.id},className:`flex items-center gap-2 rounded-md text-xs text-fg-secondary hover:text-fg-primary`,children:[(0,V.jsx)(`span`,{"aria-hidden":`true`,className:`text-fg-muted`,children:`◇`}),(0,V.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.title}),(0,V.jsx)(`span`,{className:`max-w-[40%] shrink-0 truncate font-mono text-[11px] text-fg-muted`,children:f(e)?.name??e.stage})]})},e.id))})}function Ue(){let{name:e}=te({from:`/citizen/$name`}),{scope:t,tab:n,turn:r}=se({from:`/citizen/$name`});return(0,V.jsx)(Ge,{name:e,chosen:t??null,tab:n??`now`,turn:r??null},e)}var We=[{tab:`now`,label:`Now`},{tab:`turns`,label:`Turns`},{tab:`memory`,label:`Memory`},{tab:`history`,label:`History`}];function Ge({name:t,chosen:n,tab:r,turn:i}){let a=h(),s=x(),c=e(),l=k(),[u,d]=(0,B.useState)(null),f=a.data?.find(e=>e.name===t);if(f===void 0)return(0,V.jsx)(F,{children:a.data===void 0?`Reading the roster…`:`There is no citizen ${t}.`});let p=o(c.data?.running??[]).filter(e=>e.agent===t),m=[...new Set(p.map(e=>e.scope))],g=p.map(e=>M(e.agent,e.scope,e)),_=o(c.data?.pending??[]).find(e=>e.agent===t),v=m.length>0?`working`:_===void 0?`idle`:`queued`,y=j(l,t)[0],b=y?.model??f.lastModel,S=b??f.model??`CLI default`,C=f.model!==void 0&&f.model!==b?f.model:null,w=s.data?.find(e=>e.name===f.role),te=de(f),D=f.status===`active`&&f.cli!==null;return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(le,{leading:f.cli===null?null:(0,V.jsx)(`span`,{className:`grid size-9 shrink-0 place-items-center rounded-lg bg-surface-2/70`,children:(0,V.jsx)(ee,{cli:f.cli,size:20})}),title:t,subtitle:(0,V.jsxs)(V.Fragment,{children:[f.role,` · `,S,C===null?``:` · set to ${C}`,f.effort===void 0?``:` · ${f.effort} effort`,f.homeRunner===void 0?``:` · on ${f.homeRunner}`,f.status===`retired`?` · retired`:``]}),trailing:(0,V.jsxs)(V.Fragment,{children:[D&&u===null?(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(T,{onClick:()=>d(`model`),children:`Model…`}),(0,V.jsx)(T,{onClick:()=>d(`runner`),children:`Runner…`}),(0,V.jsx)(T,{onClick:()=>d(`wake`),children:`Wake…`})]}):null,(0,V.jsx)(`span`,{className:`shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium ${Ve[v]}`,children:v})]})}),u===`wake`?(0,V.jsx)(Be,{member:f,scopes:te,preferred:n?.split(`/`)[0]??y?.scope??null,running:m,paused:c.data?.paused??!1,onDone:()=>d(null)}):u===`model`?(0,V.jsx)(Pe,{member:f,onDone:()=>d(null)}):u===`runner`?(0,V.jsx)(Le,{member:f,onDone:()=>d(null)}):null,(0,V.jsx)(`nav`,{"aria-label":`Citizen views`,className:`flex gap-1 border-b border-line px-3 py-2`,children:We.map(e=>(0,V.jsx)(E,{to:`/citizen/$name`,params:{name:t},search:{...n===null?{}:{scope:n},...e.tab===`now`?{}:{tab:e.tab}},replace:!0,"aria-current":e.tab===r?`page`:void 0,className:`rounded-md px-2.5 py-1 text-xs transition-colors ${e.tab===r?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:e.label},e.tab))}),r===`turns`?(0,V.jsx)(Ae,{name:t,opened:i},i):r===`memory`?(0,V.jsx)(De,{member:f,charter:w}):r===`history`?(0,V.jsx)(Ee,{name:t}):(0,V.jsx)(Ke,{name:t,chosen:n,lastTurnAt:f.lastTurnAt,state:v,runningScopes:m,runningKeys:g,runningTurns:(c.data?.turns??[]).filter(e=>e.agent===t),queuedScope:_?.scope??null})]})}function $(e){return e.toSorted((e,t)=>e.startedAt.localeCompare(t.startedAt))[0]}function Ke({name:e,chosen:t,lastTurnAt:n,state:r,runningScopes:a,runningKeys:o,runningTurns:s,queuedScope:c}){let l=k(),u=S(5e3),{ref:d,onScroll:f}=ue(),p=j(l,e),m=i(e,1),h=q(e,p.length===0?m.data?.at(-1):void 0),g=oe(),_=e=>e.end===null&&o.includes(M(e.agent,e.scope,e)),v=t?.split(`/`)[0]??null,y=(t?.includes(`/`)===!0?p.find(e=>O(e)===t):void 0)??$(p.filter(e=>e.scope===v&&_(e)))??p.find(e=>O(e)===t)??$(p.filter(_))??p[0]??h.turn,x=e=>e.thread===void 0?e.channel===void 0?L(e.scope):`${L(e.scope)} · #${e.channel}`:`${L(e.scope)} · ${g.get(e.thread)?.title??`a thread`}`,C=y!==void 0&&_(y),w=y?.scope??a[0]??c,T=(y===void 0?void 0:s.find(e=>e.scope===y.scope&&e.thread===y.thread&&e.channel===y.channel))??(C?void 0:s[0]);return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsxs)(`section`,{className:`border-b border-line px-4 py-3 text-xs text-fg-tertiary`,children:[(0,V.jsx)(`p`,{children:C?`In a turn at ${L(y.scope)} for ${y.fromStart?``:`at least `}${A(y.startedAt,u)}`:a.length>0?`In a turn at ${a.map(L).join(` and `)}`:c===null?n===void 0?`No turns yet`:`Last turn ${b(n,u)}`:`Queued for a turn at ${L(c)}`}),w===null||w===`society`?null:(0,V.jsx)(He,{project:w,name:e})]}),(0,V.jsx)(`div`,{ref:d,onScroll:f,className:`flex-1 overflow-y-auto px-4 py-3`,children:y===void 0?(0,V.jsx)(F,{children:r===`working`?`The turn has not reported a step yet.`:h.loading?`Reading the last turn…`:n===void 0?`${e} has not taken a turn yet.`:`${e}'s last turn kept no steps; Turns lists every finished one.`}):(0,V.jsxs)(V.Fragment,{children:[p.length>1?(0,V.jsx)(`div`,{className:`mb-3 flex flex-wrap gap-1.5`,"aria-label":`Turns by conversation`,children:p.toSorted((e,t)=>O(e).localeCompare(O(t))).map(t=>(0,V.jsxs)(E,{to:`/citizen/$name`,params:{name:e},search:{scope:O(t)},replace:!0,"aria-current":t===y?`true`:void 0,className:`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-[11px] transition-colors ${t===y?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:[_(t)?(0,V.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}):null,x(t)]},O(t)))}):null,(0,V.jsxs)(`p`,{className:`text-caps`,children:[C?`This turn`:`Last turn`,` · `,x(y),` · started`,` `,y.fromStart?H(y.startedAt):`before the earliest step shown`]}),y.fromStart?null:(0,V.jsxs)(`p`,{className:`mt-1 text-meta`,children:[`Earlier steps of this turn are no longer in the server's live buffer`,C?``:`; Turns has the whole turn`,`.`]}),(0,V.jsx)(W,{steps:y.steps}),(0,V.jsx)(_e,{turn:y,running:C,now:u})]})}),T===void 0?null:(0,V.jsx)(ze,{name:e,turn:T})]})}export{Ue as CitizenView};
@@ -1 +1 @@
1
- import{E as e,U as t,b as n,g as r,pn as i}from"./format-BWr3zKWg.js";import{t as a}from"./link-CFdt17Sp.js";import{t as o}from"./CliIcon-CT5ljQDC.js";import{n as s,t as c}from"./Pane-CFoSKOo5.js";import{i as l,r as u}from"./citizen-CImM6WB6.js";var d=i();function f(e){let t=e.lastModel??e.model??`CLI default`,n=e.model!==void 0&&e.model!==t?`${t} · set to ${e.model}`:t;return e.effort===void 0?n:`${n} · ${e.effort}`}function p(e,t){return e.name.localeCompare(t.name)}function m(e,t){return e.role.localeCompare(t.role)||p(e,t)}function h(){let i=r(),h=e(),g=n();if(i.data===void 0)return(0,d.jsx)(s,{children:`Reading the roster…`});let _=i.data.filter(e=>e.cli!==null),v=_.filter(e=>e.status===`active`).toSorted(m),y=_.filter(e=>e.status!==`active`).toSorted(p),b=new Set(v.map(e=>e.role)).size,x=t(h.data?.running??[]),S=t(h.data?.pending??[]),C=new Map((g.data??[]).flatMap(e=>e.runner===void 0?[]:[[e.slug,e.runner]])),w=e=>{let t=[...new Set(x.filter(t=>t.agent===e.name).map(e=>e.scope))];return t.length>0?{label:`working`,detail:`in a turn at ${t.map(l).join(` and `)}`,tone:`text-emerald-300`}:S.some(t=>t.agent===e.name)?{label:`queued`,detail:`queued for a turn`,tone:`text-amber-300`}:{label:`resting`,detail:`resting`,tone:`text-fg-muted`}};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(c,{title:`Citizens`,subtitle:`${v.length} active in ${b===1?`1 role`:`${b} roles`}${y.length===0?``:` · ${y.length} retired`}`}),(0,d.jsxs)(`div`,{className:`flex-1 overflow-y-auto px-2 py-2`,children:[v.length===0?(0,d.jsx)(`p`,{className:`px-2 py-2 text-meta`,children:`No citizens yet. Ask the concierge for one.`}):null,(0,d.jsx)(`ul`,{className:`grid grid-cols-[auto_auto_auto_minmax(0,max-content)_auto_minmax(3rem,1fr)_auto] gap-x-3`,children:v.map(e=>{let t=w(e),n=f(e),r=e.memberships.length===0?`no projects`:e.memberships.join(`, `),i=u(e,C);return(0,d.jsx)(`li`,{className:`col-span-full grid grid-cols-subgrid`,children:(0,d.jsxs)(a,{to:`/citizen/$name`,params:{name:e.name},className:`col-span-full grid grid-cols-subgrid items-center rounded-lg px-2 py-1.5 text-sm transition-colors hover:bg-surface-2/50`,children:[(0,d.jsx)(`span`,{className:`grid size-4 place-items-center`,children:e.cli===null?null:(0,d.jsx)(o,{cli:e.cli,size:13})}),(0,d.jsx)(`span`,{className:`text-fg-primary`,children:e.name}),(0,d.jsx)(`span`,{className:`text-fg-secondary`,children:e.role}),(0,d.jsx)(`span`,{className:`truncate text-xs text-fg-muted`,title:n,children:n}),(0,d.jsx)(`span`,{className:`text-xs text-fg-muted`,title:i.detail,children:i.label}),(0,d.jsx)(`span`,{className:`truncate text-xs text-fg-muted`,title:r,children:r}),(0,d.jsx)(`span`,{className:`text-right text-xs ${t.tone}`,title:t.detail,children:t.label})]})},e.name)})}),y.length===0?null:(0,d.jsxs)(`p`,{className:`mt-2 border-t border-line px-2 pt-2 text-meta`,children:[`Retired: `,y.map(e=>`${e.name} (${e.role})`).join(`, `)]})]})]})}export{h as CitizensView};
1
+ import{E as e,U as t,b as n,g as r,pn as i}from"./format-C3aawMM6.js";import{t as a}from"./link-DAMxBItI.js";import{t as o}from"./CliIcon-tYTwI_RQ.js";import{n as s,t as c}from"./Pane-MJgGXQBb.js";import{i as l,r as u}from"./citizen-D-dxX00V.js";var d=i();function f(e){let t=e.lastModel??e.model??`CLI default`,n=e.model!==void 0&&e.model!==t?`${t} · set to ${e.model}`:t;return e.effort===void 0?n:`${n} · ${e.effort}`}function p(e,t){return e.name.localeCompare(t.name)}function m(e,t){return e.role.localeCompare(t.role)||p(e,t)}function h(){let i=r(),h=e(),g=n();if(i.data===void 0)return(0,d.jsx)(s,{children:`Reading the roster…`});let _=i.data.filter(e=>e.cli!==null),v=_.filter(e=>e.status===`active`).toSorted(m),y=_.filter(e=>e.status!==`active`).toSorted(p),b=new Set(v.map(e=>e.role)).size,x=t(h.data?.running??[]),S=t(h.data?.pending??[]),C=new Map((g.data??[]).flatMap(e=>e.runner===void 0?[]:[[e.slug,e.runner]])),w=e=>{let t=[...new Set(x.filter(t=>t.agent===e.name).map(e=>e.scope))];return t.length>0?{label:`working`,detail:`in a turn at ${t.map(l).join(` and `)}`,tone:`text-emerald-300`}:S.some(t=>t.agent===e.name)?{label:`queued`,detail:`queued for a turn`,tone:`text-amber-300`}:{label:`resting`,detail:`resting`,tone:`text-fg-muted`}};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(c,{title:`Citizens`,subtitle:`${v.length} active in ${b===1?`1 role`:`${b} roles`}${y.length===0?``:` · ${y.length} retired`}`}),(0,d.jsxs)(`div`,{className:`flex-1 overflow-y-auto px-2 py-2`,children:[v.length===0?(0,d.jsx)(`p`,{className:`px-2 py-2 text-meta`,children:`No citizens yet. Ask the concierge for one.`}):null,(0,d.jsx)(`ul`,{className:`grid grid-cols-[auto_auto_auto_minmax(0,max-content)_auto_minmax(3rem,1fr)_auto] gap-x-3`,children:v.map(e=>{let t=w(e),n=f(e),r=e.memberships.length===0?`no projects`:e.memberships.join(`, `),i=u(e,C);return(0,d.jsx)(`li`,{className:`col-span-full grid grid-cols-subgrid`,children:(0,d.jsxs)(a,{to:`/citizen/$name`,params:{name:e.name},className:`col-span-full grid grid-cols-subgrid items-center rounded-lg px-2 py-1.5 text-sm transition-colors hover:bg-surface-2/50`,children:[(0,d.jsx)(`span`,{className:`grid size-4 place-items-center`,children:e.cli===null?null:(0,d.jsx)(o,{cli:e.cli,size:13})}),(0,d.jsx)(`span`,{className:`text-fg-primary`,children:e.name}),(0,d.jsx)(`span`,{className:`text-fg-secondary`,children:e.role}),(0,d.jsx)(`span`,{className:`truncate text-xs text-fg-muted`,title:n,children:n}),(0,d.jsx)(`span`,{className:`text-xs text-fg-muted`,title:i.detail,children:i.label}),(0,d.jsx)(`span`,{className:`truncate text-xs text-fg-muted`,title:r,children:r}),(0,d.jsx)(`span`,{className:`text-right text-xs ${t.tone}`,title:t.detail,children:t.label})]})},e.name)})}),y.length===0?null:(0,d.jsxs)(`p`,{className:`mt-2 border-t border-line px-2 pt-2 text-meta`,children:[`Retired: `,y.map(e=>`${e.name} (${e.role})`).join(`, `)]})]})]})}export{h as CitizensView};
@@ -1 +1 @@
1
- import{pn as e}from"./format-BWr3zKWg.js";var t=`M6.766 11.328c-2.063-.25-3.516-1.734-3.516-3.656 0-.781.281-1.625.75-2.188-.203-.515-.172-1.609.063-2.062.625-.078 1.468.25 1.968.703.594-.187 1.219-.281 1.985-.281.765 0 1.39.094 1.953.265.484-.437 1.344-.765 1.969-.687.218.422.25 1.515.046 2.047.5.593.766 1.39.766 2.203 0 1.922-1.453 3.375-3.547 3.64.531.344.89 1.094.89 1.954v1.625c0 .468.391.734.86.547C13.781 14.359 16 11.53 16 8.03 16 3.61 12.406 0 7.984 0 3.563 0 0 3.61 0 8.031a7.88 7.88 0 0 0 5.172 7.422c.422.156.828-.125.828-.547v-1.25c-.219.094-.5.156-.75.156-1.031 0-1.64-.562-2.078-1.609-.172-.422-.36-.672-.719-.719-.187-.015-.25-.093-.25-.187 0-.188.313-.328.625-.328.453 0 .844.281 1.25.86.313.452.64.655 1.031.655s.641-.14 1-.5c.266-.265.47-.5.657-.656`,n={claude:{label:`Claude Code`,path:`M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z`,fill:`#D97757`,accent:`#fb923c`},codex:{label:`Codex`,path:`M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z`,fill:`#f5f5f5`,accent:`#10b981`}},r=e();function i({cli:e,size:t=16}){let i=n[e];return(0,r.jsx)(`svg`,{viewBox:`0 0 24 24`,width:t,height:t,"aria-hidden":`true`,className:`shrink-0`,children:(0,r.jsx)(`path`,{d:i.path,fill:i.fill,fillRule:`evenodd`,clipRule:`evenodd`})})}export{n,t as r,i as t};
1
+ import{pn as e}from"./format-C3aawMM6.js";var t=`M6.766 11.328c-2.063-.25-3.516-1.734-3.516-3.656 0-.781.281-1.625.75-2.188-.203-.515-.172-1.609.063-2.062.625-.078 1.468.25 1.968.703.594-.187 1.219-.281 1.985-.281.765 0 1.39.094 1.953.265.484-.437 1.344-.765 1.969-.687.218.422.25 1.515.046 2.047.5.593.766 1.39.766 2.203 0 1.922-1.453 3.375-3.547 3.64.531.344.89 1.094.89 1.954v1.625c0 .468.391.734.86.547C13.781 14.359 16 11.53 16 8.03 16 3.61 12.406 0 7.984 0 3.563 0 0 3.61 0 8.031a7.88 7.88 0 0 0 5.172 7.422c.422.156.828-.125.828-.547v-1.25c-.219.094-.5.156-.75.156-1.031 0-1.64-.562-2.078-1.609-.172-.422-.36-.672-.719-.719-.187-.015-.25-.093-.25-.187 0-.188.313-.328.625-.328.453 0 .844.281 1.25.86.313.452.64.655 1.031.655s.641-.14 1-.5c.266-.265.47-.5.657-.656`,n={claude:{label:`Claude Code`,path:`M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z`,fill:`#D97757`,accent:`#fb923c`},codex:{label:`Codex`,path:`M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z`,fill:`#f5f5f5`,accent:`#10b981`}},r=e();function i({cli:e,size:t=16}){let i=n[e];return(0,r.jsx)(`svg`,{viewBox:`0 0 24 24`,width:t,height:t,"aria-hidden":`true`,className:`shrink-0`,children:(0,r.jsx)(`path`,{d:i.path,fill:i.fill,fillRule:`evenodd`,clipRule:`evenodd`})})}export{n,t as r,i as t};