@kubitnodes/stellaris 0.3.4 → 0.3.5

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 (45) hide show
  1. package/dist/cli/index.js +23 -4
  2. package/dist/server/index.js +83 -9
  3. package/package.json +1 -1
  4. package/web/dist/assets/BackLink-DivaHiZ7.js +1 -0
  5. package/web/dist/assets/{ChannelView-CZyYu_Zi.js → ChannelView-DgkkiZuY.js} +1 -1
  6. package/web/dist/assets/CitizenView-BzhH1ycF.js +2 -0
  7. package/web/dist/assets/{CitizensView-7vHTRRIs.js → CitizensView-BzGNyC2f.js} +1 -1
  8. package/web/dist/assets/KnowledgeView-DedLlEZd.js +1 -0
  9. package/web/dist/assets/{Markdown-BrvfGmz7.js → Markdown-MZnGPfvk.js} +4 -4
  10. package/web/dist/assets/{MessageItem-DXU3Ovq1.js → MessageItem-Deq-ntT8.js} +1 -1
  11. package/web/dist/assets/MetricsView-C-2j71rI.js +1 -0
  12. package/web/dist/assets/NeedsYouView-D4xqHNDU.js +1 -0
  13. package/web/dist/assets/{Overview-D76LQcxp.js → Overview-DxCYcW_A.js} +1 -1
  14. package/web/dist/assets/{Pane-JzhKR0rO.js → Pane-B-pz52UC.js} +1 -1
  15. package/web/dist/assets/ProjectView-BhZYFv7f.js +1 -0
  16. package/web/dist/assets/ProposalView-DAc9lEHB.js +1 -0
  17. package/web/dist/assets/{ProposalsView-DQW7OmOU.js → ProposalsView-CmwwJuop.js} +1 -1
  18. package/web/dist/assets/{RunnersView-BLwSywI7.js → RunnersView-Dqo_BEoK.js} +1 -1
  19. package/web/dist/assets/{SocietyView-OCdDJqhz.js → SocietyView-DA_65uyo.js} +1 -1
  20. package/web/dist/assets/{SubjectThread-DQNXXY4q.js → SubjectThread-M4F1paqV.js} +1 -1
  21. package/web/dist/assets/TaskFileView-CCNVrooP.js +4 -0
  22. package/web/dist/assets/TaskView-BTSDk1yL.js +1 -0
  23. package/web/dist/assets/{TasksView-C1cdPYRc.js → TasksView-0IQm6u-_.js} +1 -1
  24. package/web/dist/assets/ThreadCard-BTGP4fOT.js +1 -0
  25. package/web/dist/assets/{ThreadForms-C4ytMMBB.js → ThreadForms-BipMby65.js} +1 -1
  26. package/web/dist/assets/ThreadView-D96DZAOM.js +1 -0
  27. package/web/dist/assets/{citizen-TjyiyFqE.js → citizen-CYBzbWt-.js} +1 -1
  28. package/web/dist/assets/{format-8m6fdeP8.js → format-11lojpK1.js} +1 -1
  29. package/web/dist/assets/index-BXq4t0NA.js +23 -0
  30. package/web/dist/assets/index-CKjqsZME.css +2 -0
  31. package/web/dist/assets/{tasks-Di8iatzY.js → tasks-DnJj3psB.js} +1 -1
  32. package/web/dist/assets/{useStickyScroll-BPuANcOs.js → useStickyScroll-D_7q2RKi.js} +1 -1
  33. package/web/dist/index.html +4 -4
  34. package/web/dist/assets/CitizenView-JsI89Tn3.js +0 -2
  35. package/web/dist/assets/KnowledgeView-eBae2Dix.js +0 -1
  36. package/web/dist/assets/MetricsView-CxXGHRtN.js +0 -1
  37. package/web/dist/assets/NeedsYouView-R-oQddyC.js +0 -1
  38. package/web/dist/assets/ProjectView-vYKWw1Ck.js +0 -1
  39. package/web/dist/assets/ProposalView-dskJSjhm.js +0 -1
  40. package/web/dist/assets/TaskFileView-Bl1vm7Op.js +0 -4
  41. package/web/dist/assets/TaskView-Bq-vXuc5.js +0 -1
  42. package/web/dist/assets/ThreadCard-CliRbP_c.js +0 -1
  43. package/web/dist/assets/ThreadView-CvXd68Ml.js +0 -1
  44. package/web/dist/assets/index-CADeLxUP.js +0 -23
  45. package/web/dist/assets/index-iNICYkef.css +0 -2
package/dist/cli/index.js CHANGED
@@ -1261,7 +1261,7 @@ var RunnerConfigSchema = z10.object({
1261
1261
  });
1262
1262
 
1263
1263
  // packages/shared/dist/version.js
1264
- var STELLARIS_VERSION = "0.3.4";
1264
+ var STELLARIS_VERSION = "0.3.5";
1265
1265
 
1266
1266
  // packages/board-core/dist/errors.js
1267
1267
  var BoardError = class extends Error {
@@ -2315,6 +2315,8 @@ var SignInsSchema = z12.object({
2315
2315
  signIns: z12.array(z12.object({
2316
2316
  tokenHash: z12.string().min(1),
2317
2317
  login: z12.string().min(1),
2318
+ /** The account's picture at the identity provider; sign-ins from before it have none. */
2319
+ avatarUrl: z12.url().optional(),
2318
2320
  createdAt: IsoDateTimeSchema,
2319
2321
  expiresAt: IsoDateTimeSchema
2320
2322
  })).default([])
@@ -2934,23 +2936,36 @@ ${charter.purpose}
2934
2936
  * token, shown once. Only its hash is kept, in `state/sign-ins.json`, so a sign-in outlives a
2935
2937
  * restart; it acts as the user, like the user's own token, until it expires or is signed out.
2936
2938
  */
2937
- async signIn(login, ttlMs) {
2939
+ async signIn(login, ttlMs, avatarUrl) {
2938
2940
  return this.mutex.run(async () => {
2939
2941
  const token = mintToken();
2940
2942
  const now = this.now().getTime();
2941
2943
  const record = {
2942
2944
  tokenHash: hashToken(token),
2943
2945
  login,
2946
+ ...avatarUrl === void 0 ? {} : { avatarUrl },
2944
2947
  createdAt: new Date(now).toISOString(),
2945
2948
  expiresAt: new Date(now + ttlMs).toISOString()
2946
2949
  };
2947
2950
  const live = (await this.readSignIns()).filter((each) => Date.parse(each.expiresAt) > now);
2948
2951
  await writeJson(this.signInsFile(), { signIns: [...live, record] });
2949
- this.signIns.set(record.tokenHash, { login, expiresAt: Date.parse(record.expiresAt) });
2952
+ this.signIns.set(record.tokenHash, {
2953
+ login,
2954
+ avatarUrl,
2955
+ expiresAt: Date.parse(record.expiresAt)
2956
+ });
2950
2957
  await this.events.append("user.signed_in", USER_NAME, { login });
2951
2958
  return token;
2952
2959
  });
2953
2960
  }
2961
+ /** Who a token signed in as, while its sign-in lasts; null for any other token. */
2962
+ signInOf(token) {
2963
+ const signIn = this.signIns.get(hashToken(token));
2964
+ if (signIn === void 0 || signIn.expiresAt <= this.now().getTime()) {
2965
+ return null;
2966
+ }
2967
+ return { login: signIn.login, avatarUrl: signIn.avatarUrl };
2968
+ }
2954
2969
  /** Ends the sign-in a token belongs to; false for a token that is no sign-in's. */
2955
2970
  async signOut(token) {
2956
2971
  const hash = hashToken(token);
@@ -2996,7 +3011,11 @@ ${charter.purpose}
2996
3011
  for (const signIn of await this.readSignIns()) {
2997
3012
  const expiresAt = Date.parse(signIn.expiresAt);
2998
3013
  if (expiresAt > now) {
2999
- this.signIns.set(signIn.tokenHash, { login: signIn.login, expiresAt });
3014
+ this.signIns.set(signIn.tokenHash, {
3015
+ login: signIn.login,
3016
+ avatarUrl: signIn.avatarUrl,
3017
+ expiresAt
3018
+ });
3000
3019
  }
3001
3020
  }
3002
3021
  }
@@ -1341,7 +1341,7 @@ var RunnerConfigSchema = z10.object({
1341
1341
  });
1342
1342
 
1343
1343
  // packages/shared/dist/version.js
1344
- var STELLARIS_VERSION = "0.3.4";
1344
+ var STELLARIS_VERSION = "0.3.5";
1345
1345
 
1346
1346
  // packages/board-core/dist/errors.js
1347
1347
  var BoardError = class extends Error {
@@ -2398,6 +2398,8 @@ var SignInsSchema = z12.object({
2398
2398
  signIns: z12.array(z12.object({
2399
2399
  tokenHash: z12.string().min(1),
2400
2400
  login: z12.string().min(1),
2401
+ /** The account's picture at the identity provider; sign-ins from before it have none. */
2402
+ avatarUrl: z12.url().optional(),
2401
2403
  createdAt: IsoDateTimeSchema,
2402
2404
  expiresAt: IsoDateTimeSchema
2403
2405
  })).default([])
@@ -3017,23 +3019,36 @@ ${charter.purpose}
3017
3019
  * token, shown once. Only its hash is kept, in `state/sign-ins.json`, so a sign-in outlives a
3018
3020
  * restart; it acts as the user, like the user's own token, until it expires or is signed out.
3019
3021
  */
3020
- async signIn(login, ttlMs) {
3022
+ async signIn(login, ttlMs, avatarUrl) {
3021
3023
  return this.mutex.run(async () => {
3022
3024
  const token = mintToken();
3023
3025
  const now = this.now().getTime();
3024
3026
  const record = {
3025
3027
  tokenHash: hashToken(token),
3026
3028
  login,
3029
+ ...avatarUrl === void 0 ? {} : { avatarUrl },
3027
3030
  createdAt: new Date(now).toISOString(),
3028
3031
  expiresAt: new Date(now + ttlMs).toISOString()
3029
3032
  };
3030
3033
  const live = (await this.readSignIns()).filter((each) => Date.parse(each.expiresAt) > now);
3031
3034
  await writeJson(this.signInsFile(), { signIns: [...live, record] });
3032
- this.signIns.set(record.tokenHash, { login, expiresAt: Date.parse(record.expiresAt) });
3035
+ this.signIns.set(record.tokenHash, {
3036
+ login,
3037
+ avatarUrl,
3038
+ expiresAt: Date.parse(record.expiresAt)
3039
+ });
3033
3040
  await this.events.append("user.signed_in", USER_NAME, { login });
3034
3041
  return token;
3035
3042
  });
3036
3043
  }
3044
+ /** Who a token signed in as, while its sign-in lasts; null for any other token. */
3045
+ signInOf(token) {
3046
+ const signIn = this.signIns.get(hashToken(token));
3047
+ if (signIn === void 0 || signIn.expiresAt <= this.now().getTime()) {
3048
+ return null;
3049
+ }
3050
+ return { login: signIn.login, avatarUrl: signIn.avatarUrl };
3051
+ }
3037
3052
  /** Ends the sign-in a token belongs to; false for a token that is no sign-in's. */
3038
3053
  async signOut(token) {
3039
3054
  const hash = hashToken(token);
@@ -3079,7 +3094,11 @@ ${charter.purpose}
3079
3094
  for (const signIn of await this.readSignIns()) {
3080
3095
  const expiresAt = Date.parse(signIn.expiresAt);
3081
3096
  if (expiresAt > now) {
3082
- this.signIns.set(signIn.tokenHash, { login: signIn.login, expiresAt });
3097
+ this.signIns.set(signIn.tokenHash, {
3098
+ login: signIn.login,
3099
+ avatarUrl: signIn.avatarUrl,
3100
+ expiresAt
3101
+ });
3083
3102
  }
3084
3103
  }
3085
3104
  }
@@ -6520,13 +6539,20 @@ var Scheduler = class {
6520
6539
  if (taskId !== null && !settled) {
6521
6540
  await this.wakeStage(taskId, event.actor, now);
6522
6541
  }
6542
+ if (taskId !== null) {
6543
+ await this.pruneStageWakes(taskId);
6544
+ }
6523
6545
  return;
6524
6546
  }
6525
6547
  case "task.claimed": {
6526
6548
  const taskId = stringOf(payload["taskId"]);
6527
- if (taskId !== null && stringOf(payload["thread"]) !== taskId) {
6549
+ if (taskId === null) {
6550
+ return;
6551
+ }
6552
+ if (stringOf(payload["thread"]) !== taskId) {
6528
6553
  await this.wakeHolder(taskId, event.actor, now);
6529
6554
  }
6555
+ await this.pruneStageWakes(taskId);
6530
6556
  return;
6531
6557
  }
6532
6558
  case "task.completing": {
@@ -6534,6 +6560,7 @@ var Scheduler = class {
6534
6560
  const project = stringOf(payload["project"]);
6535
6561
  if (taskId !== null && project !== null) {
6536
6562
  this.completions.set(taskId, { project, actor: event.actor });
6563
+ await this.pruneStageWakes(taskId);
6537
6564
  }
6538
6565
  return;
6539
6566
  }
@@ -6545,6 +6572,7 @@ var Scheduler = class {
6545
6572
  return;
6546
6573
  }
6547
6574
  delete this.state.releaseCounts[taskId];
6575
+ await this.pruneStageWakes(taskId);
6548
6576
  if (creator !== null && creator !== event.actor) {
6549
6577
  await this.wakeCreator(taskId, project, creator, event.actor, now);
6550
6578
  }
@@ -6555,6 +6583,9 @@ var Scheduler = class {
6555
6583
  if (taskId !== null && payload["to"] === "abandoned") {
6556
6584
  delete this.state.releaseCounts[taskId];
6557
6585
  }
6586
+ if (taskId !== null) {
6587
+ await this.pruneStageWakes(taskId);
6588
+ }
6558
6589
  return;
6559
6590
  }
6560
6591
  case "task.released":
@@ -6769,6 +6800,25 @@ var Scheduler = class {
6769
6800
  }, now, { id: task.id, task: scope === task.project });
6770
6801
  return sessionKey(agent.name, scope, task.id);
6771
6802
  }
6803
+ /**
6804
+ * Drops each queued turn made only of stage wakes, one of them for this task, once none of its
6805
+ * stages waits for its citizen any more: as soon as an event about the task could have changed
6806
+ * that, the stage taken by anyone, the plan moved on or reshaped, the task ended, rather than
6807
+ * only at dispatch, so a wake that will not run leaves the queue at once.
6808
+ */
6809
+ async pruneStageWakes(taskId) {
6810
+ for (const [key, item] of this.pending) {
6811
+ const wakes = item.stageWakes;
6812
+ if (wakes === void 0 || !wakes.some((wake) => wake.taskId === taskId)) {
6813
+ continue;
6814
+ }
6815
+ const due = await this.stillWaiting(item.dispatch.agent, wakes, item.holder === true);
6816
+ if (due === void 0 && this.pending.get(key) === item) {
6817
+ this.pending.delete(key);
6818
+ this.log.info({ agent: item.dispatch.agent, project: item.dispatch.project, taskId }, "dropping stage wake, the stage no longer waits for this agent");
6819
+ }
6820
+ }
6821
+ }
6772
6822
  /**
6773
6823
  * The first of these stage wakes still due: its task waits, unheld, on a stage the agent may
6774
6824
  * hold, or, with `holder`, the agent holds it, having claimed it outside the task's conversation.
@@ -8929,7 +8979,19 @@ var SIGN_IN_TTL_MS = 30 * 24 * 36e5;
8929
8979
  var STATE_TTL_MS = 10 * 6e4;
8930
8980
  var MAX_STATES = 1e3;
8931
8981
  var TokenAnswerSchema = z14.object({ access_token: z14.string().min(1) });
8932
- var GithubUserSchema = z14.object({ login: z14.string().min(1), id: z14.number().int() });
8982
+ var GithubUserSchema = z14.object({
8983
+ login: z14.string().min(1),
8984
+ id: z14.number().int(),
8985
+ avatar_url: z14.string().optional()
8986
+ });
8987
+ function githubAvatar(url) {
8988
+ try {
8989
+ const parsed = new URL(url ?? "");
8990
+ return parsed.protocol === "https:" && parsed.hostname === "avatars.githubusercontent.com" ? parsed.href : void 0;
8991
+ } catch {
8992
+ return void 0;
8993
+ }
8994
+ }
8933
8995
  function safeNext(next) {
8934
8996
  return next !== void 0 && /^\/(?![/\\])/.test(next) ? next : "/";
8935
8997
  }
@@ -8973,6 +9035,7 @@ function githubAuthRoutes(options) {
8973
9035
  }
8974
9036
  let login;
8975
9037
  let id;
9038
+ let avatar;
8976
9039
  try {
8977
9040
  const tokenAnswer = await fetchImpl("https://github.com/login/oauth/access_token", {
8978
9041
  method: "POST",
@@ -8994,7 +9057,9 @@ function githubAuthRoutes(options) {
8994
9057
  if (!userAnswer.ok) {
8995
9058
  throw new Error(`GitHub answered ${userAnswer.status} for the user`);
8996
9059
  }
8997
- ({ login, id } = GithubUserSchema.parse(await userAnswer.json()));
9060
+ const user = GithubUserSchema.parse(await userAnswer.json());
9061
+ ({ login, id } = user);
9062
+ avatar = githubAvatar(user.avatar_url);
8998
9063
  } catch (error) {
8999
9064
  options.log?.warn({ error: String(error) }, "GitHub sign-in failed");
9000
9065
  return land(c, pending.next, "signin-error=github");
@@ -9003,7 +9068,7 @@ function githubAuthRoutes(options) {
9003
9068
  options.log?.warn({ login }, "GitHub sign-in refused a login that is not on the list");
9004
9069
  return land(c, pending.next, "signin-error=not-allowed");
9005
9070
  }
9006
- const token = await board2.signIn(login, SIGN_IN_TTL_MS);
9071
+ const token = await board2.signIn(login, SIGN_IN_TTL_MS, avatar);
9007
9072
  return land(c, pending.next, `session=${encodeURIComponent(token)}`);
9008
9073
  });
9009
9074
  return routes;
@@ -9429,7 +9494,16 @@ function createApp(deps) {
9429
9494
  };
9430
9495
  const api = new Hono3();
9431
9496
  api.use("*", authenticate);
9432
- api.get("/me", (c) => c.json(c.get("actor")));
9497
+ api.get("/me", (c) => {
9498
+ const signIn = board2.signInOf(bearer2(c) ?? "");
9499
+ return c.json(signIn === null ? c.get("actor") : {
9500
+ ...c.get("actor"),
9501
+ signIn: {
9502
+ login: signIn.login,
9503
+ avatarUrl: signIn.avatarUrl ?? `https://github.com/${encodeURIComponent(signIn.login)}.png`
9504
+ }
9505
+ });
9506
+ });
9433
9507
  api.delete("/sign-in", async (c) => c.json({ signedOut: await board2.signOut(bearer2(c) ?? "") }));
9434
9508
  api.get("/society", async (c) => c.json(await board2.society()));
9435
9509
  api.get("/agents", async (c) => c.json((await board2.listAgents()).map(({ tokenHash: _hash, ...agent }) => agent)));
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "codex",
9
9
  "multi-agent"
10
10
  ],
11
- "version": "0.3.4",
11
+ "version": "0.3.5",
12
12
  "license": "MIT",
13
13
  "homepage": "https://github.com/kr4t0n/stellaris",
14
14
  "repository": {
@@ -0,0 +1 @@
1
+ import{_n as e,b as t,wt as n}from"./format-11lojpK1.js";import{L as r,S as i,n as a,r as o,t as s}from"./index-BXq4t0NA.js";var c=e(),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:e}){let u=n(),d=r({select:e=>e.location.state.__TSR_index}),f=o(),p=i(),m=t(),h=a(f,d);if(h===null)return e;let g=s(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{E as e,L as t,P as n,Yt as r,_n as i,bn as a,gn as o,m as s,v as c,y as l}from"./format-8m6fdeP8.js";import{I as u,N as d,a as f,t as p}from"./index-CADeLxUP.js";import{t as m}from"./MessageItem-DXU3Ovq1.js";import{n as h,t as g}from"./Pane-JzhKR0rO.js";import{n as _}from"./ThreadCard-CliRbP_c.js";import{i as v}from"./ThreadForms-C4ytMMBB.js";import{t as y}from"./useStickyScroll-BPuANcOs.js";var b=a(i(),1),x=o();function S(){let{_splat:e=`general`}=u({from:`/c/$`});return(0,x.jsx)(C,{channel:e},e)}function C({channel:i}){let{api:a}=e(),o=r({queryKey:[`channel`,i],queryFn:()=>a.channel(i)}),u=n(),S=s(),C=l(),w=c(3e4),[T,E]=(0,b.useState)(!1),D=(0,b.useMemo)(()=>{let e=(o.data??[]).map(e=>({kind:`message`,at:e.ts,id:e.id,message:e})),t=(u.data??[]).filter(e=>e.channel===i).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))},[o.data,u.data,i]),O=o.data?.at(-1)?.id??null;(0,b.useEffect)(()=>d(i,O),[i,O]);let{ref:k,onScroll:A}=y(),[j,M]=i.split(`/`),N=M??j??i,P=M===void 0?void 0:C.data?.find(e=>e.slug===j),F=M===void 0?`society`:P?.name??j,I=P?.archived!==void 0,L=D.filter(e=>e.kind===`thread`&&e.thread.state===`open`);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(g,{title:`# ${N}`,subtitle:`${F} · ${o.data?.length??0} messages${L.length>0?` · ${L.length} open threads`:``}`,trailing:T||I?null:(0,x.jsx)(f,{onClick:()=>E(!0),children:`New thread`})}),T?(0,x.jsx)(v,{channel:i,onDone:()=>E(!1)}):null,(0,x.jsx)(`div`,{ref:k,onScroll:A,className:`flex-1 overflow-y-auto py-2`,children:o.error instanceof t&&o.error.status===404?(0,x.jsxs)(h,{children:[`There is no channel `,i,`.`]}):o.data===void 0?(0,x.jsx)(h,{children:`Reading the channel…`}):D.length===0?(0,x.jsx)(h,{children:`Nothing has been said here yet.`}):D.map(e=>e.kind===`message`?(0,x.jsx)(m,{message:e.message,members:S.data,now:w},e.id):(0,x.jsx)(_,{thread:e.thread,now:w},e.id))}),o.data===void 0?null:I?(0,x.jsxs)(`p`,{className:`border-t border-line px-4 py-3 text-meta`,children:[F,` is archived, so its channels are read-only.`]}):(0,x.jsx)(p,{target:{channel:i},placeholder:`Message #${N}`})]})}export{S as ChannelView};
1
+ import{D as e,F as t,R as n,Xt as r,_n as i,b as a,h as o,vn as s,xn as c,y as l}from"./format-11lojpK1.js";import{B as u,I as d,c as f,i as p}from"./index-BXq4t0NA.js";import{t as m}from"./MessageItem-Deq-ntT8.js";import{n as h,t as g}from"./Pane-B-pz52UC.js";import{n as _}from"./ThreadCard-BTGP4fOT.js";import{i as v}from"./ThreadForms-BipMby65.js";import{t as y}from"./useStickyScroll-D_7q2RKi.js";var b=c(s(),1),x=i();function S(){let{_splat:e=`general`}=u({from:`/c/$`});return(0,x.jsx)(C,{channel:e},e)}function C({channel:i}){let{api:s}=e(),c=r({queryKey:[`channel`,i],queryFn:()=>s.channel(i)}),u=t(),S=o(),C=a(),w=l(3e4),[T,E]=(0,b.useState)(!1),D=(0,b.useMemo)(()=>{let e=(c.data??[]).map(e=>({kind:`message`,at:e.ts,id:e.id,message:e})),t=(u.data??[]).filter(e=>e.channel===i).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,u.data,i]),O=c.data?.at(-1)?.id??null;(0,b.useEffect)(()=>d(i,O),[i,O]);let{ref:k,onScroll:A}=y(),[j,M]=i.split(`/`),N=M??j??i,P=M===void 0?void 0:C.data?.find(e=>e.slug===j),F=M===void 0?`society`:P?.name??j,I=P?.archived!==void 0,L=D.filter(e=>e.kind===`thread`&&e.thread.state===`open`);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(g,{title:`# ${N}`,subtitle:`${F} · ${c.data?.length??0} messages${L.length>0?` · ${L.length} open threads`:``}`,trailing:T||I?null:(0,x.jsx)(f,{onClick:()=>E(!0),children:`New thread`})}),T?(0,x.jsx)(v,{channel:i,onDone:()=>E(!1)}):null,(0,x.jsx)(`div`,{ref:k,onScroll:A,className:`flex-1 overflow-y-auto py-2`,children:c.error instanceof n&&c.error.status===404?(0,x.jsxs)(h,{children:[`There is no channel `,i,`.`]}):c.data===void 0?(0,x.jsx)(h,{children:`Reading the channel…`}):D.length===0?(0,x.jsx)(h,{children:`Nothing has been said here yet.`}):D.map(e=>e.kind===`message`?(0,x.jsx)(m,{message:e.message,members:S.data,now:w},e.id):(0,x.jsx)(_,{thread:e.thread,now:w},e.id))}),c.data===void 0?null:I?(0,x.jsxs)(`p`,{className:`border-t border-line px-4 py-3 text-meta`,children:[F,` is archived, so its channels are read-only.`]}):(0,x.jsx)(p,{target:{channel:i},placeholder:`Message #${N}`})]})}export{S as ChannelView};
@@ -0,0 +1,2 @@
1
+ import{D as e,E as t,H as n,I as r,L as i,P as a,R as o,St as s,T as c,_n as l,a as u,d,f,g as p,gn as m,h,st as g,t as _,u as v,v as y,vn as b,w as x,xn as S,y as C}from"./format-11lojpK1.js";import{B as w,S as T,T as E,V as D,_ as O,c as k,f as A,g as ee,h as te,i as ne,m as j,p as M,v as N,x as P,y as F,z as re}from"./index-BXq4t0NA.js";import{t as I}from"./Markdown-MZnGPfvk.js";import{n as L,t as ie}from"./Pane-B-pz52UC.js";import{n as ae,r as R}from"./ThreadForms-BipMby65.js";import{t as oe}from"./useStickyScroll-D_7q2RKi.js";import{a as z,c as B,n as se,o as ce,r as le,s as ue,t as de}from"./citizen-CYBzbWt-.js";var V=S(b(),1),H=l(),fe={completed:`completed`,timeout:`timed out`,error:`failed`,interrupted:`was interrupted`,blocked:`was blocked`,stopped:`was stopped by you`};function U(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1})}function W({label:e,tone:t,children:n}){return(0,H.jsxs)(`div`,{children:[(0,H.jsx)(`p`,{className:`px-0.5 pb-0.5 text-[10px] tracking-wider text-fg-muted uppercase`,children:e}),(0,H.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 pe({step:e,open:t}){if(e.kind===`say`)return(0,H.jsx)(`li`,{className:`py-1.5 text-sm`,title:U(e.at),children:(0,H.jsx)(I,{text:e.text})});if(e.kind===`error`)return(0,H.jsx)(`li`,{className:`py-1 font-mono text-xs break-words text-red-400`,title:U(e.at),children:e.message});if(e.kind===`steer`)return(0,H.jsx)(`li`,{children:(0,H.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,H.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,H.jsx)(`span`,{"aria-hidden":`true`,className:`grid w-3 shrink-0 place-items-center text-sky-300`,children:`↳`}),(0,H.jsxs)(`span`,{className:`shrink-0 text-fg-tertiary`,children:[`Took `,te(e.posts.length)]}),(0,H.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,H.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:U(e.at)})]}),(0,H.jsx)(`ul`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:e.posts.map(e=>(0,H.jsxs)(`li`,{className:`rounded-md bg-surface-0/40 px-2.5 py-2`,children:[(0,H.jsxs)(`p`,{className:`flex gap-1.5 text-meta`,children:[(0,H.jsx)(`span`,{className:`text-fg-secondary`,children:e.author}),(0,H.jsxs)(`span`,{className:`min-w-0 truncate`,children:[`in `,e.where]}),e.at===``?null:(0,H.jsx)(`span`,{className:`ml-auto shrink-0 font-mono`,children:U(e.at)})]}),(0,H.jsx)(`div`,{className:`mt-1 text-sm`,children:(0,H.jsx)(I,{text:e.body})})]},`${e.at}-${e.author}`))})]})});let n=e.ok===null?(0,H.jsx)(`span`,{"aria-label":`running`,className:`size-1.5 animate-pulse rounded-full bg-amber-300`}):e.ok?(0,H.jsx)(`span`,{"aria-label":`succeeded`,className:`text-[11px] text-emerald-400`,children:`✓`}):(0,H.jsx)(`span`,{"aria-label":`failed`,className:`text-[11px] text-red-400`,children:`✕`});return(0,H.jsx)(`li`,{children:(0,H.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,H.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,H.jsx)(`span`,{className:`grid w-3 shrink-0 place-items-center`,children:n}),(0,H.jsx)(`span`,{className:`shrink-0 font-mono text-fg-tertiary`,children:ee(e.name)}),(0,H.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-fg-secondary`,children:e.summary}),(0,H.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:U(e.at)})]}),(0,H.jsxs)(`div`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:[(0,H.jsx)(W,{label:`Input`,tone:`text-fg-secondary`,children:e.detail}),e.output===null?null:(0,H.jsx)(W,{label:e.ok===!1?`Returned an error`:`Returned`,tone:e.ok===!1?`text-red-300`:`text-fg-tertiary`,children:e.output})]})]})})}function G({steps:e}){let[t,n]=(0,V.useState)(!1),r=e.filter(e=>e.kind===`tool`).length;return e.length===0?(0,H.jsx)(`p`,{className:`mt-2 text-meta`,children:`No steps yet.`}):(0,H.jsxs)(H.Fragment,{children:[r===0?null:(0,H.jsxs)(`p`,{className:`mt-2 flex items-center gap-2 text-meta`,children:[r===1?`1 tool call`:`${r} tool calls`,(0,H.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,H.jsx)(`ol`,{className:`mt-1 space-y-0.5`,children:e.map(e=>(0,H.jsx)(pe,{step:e,open:t},e.seq))})]})}function me({turn:e,running:t,now:n}){if(e.end!==null){let t=e.end.costUsd>0?` · $${e.end.costUsd.toFixed(2)}`:``;return(0,H.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,H.jsxs)(`p`,{className:`text-caps`,children:[`The turn `,fe[e.end.exitReason],` `,_(e.end.at,n),t,e.fromStart?` · ${M(e.startedAt,Date.parse(e.end.at))}`:``]}),e.end.summary===null?null:(0,H.jsx)(`p`,{className:`mt-1 text-sm text-fg-secondary`,children:e.end.summary})]})}return t?(0,H.jsxs)(`p`,{className:`mt-3 flex items-center gap-2 text-meta`,"aria-live":`polite`,children:[(0,H.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}),`Working · last step `,_(e.lastAt,n)]}):(0,H.jsx)(`p`,{className:`mt-3 text-meta`,children:`The turn ended without a report.`})}var K=30,he={turn:`turn`,board:`board`,merge:`both kept`},ge={turn:`Changed by a turn`,board:`Written by the board`,merge:`Both versions kept`};function _e(e){return e.status===`added`?`new`:e.status===`deleted`?`deleted`:e.added===null||e.removed===null?`binary`:`+${e.added} −${e.removed}`}function ve(e){return e.files.map(e=>`${e.path} ${_e(e)}`).join(`, `)}function ye(e){return e.startsWith(`@@`)||e.startsWith(`\\`)?`text-fg-muted`:e.startsWith(`+`)?`text-emerald-300`:e.startsWith(`-`)?`text-red-300`:`text-fg-tertiary`}function be({file:e}){return(0,H.jsxs)(`div`,{children:[(0,H.jsxs)(`p`,{className:`text-xs text-fg-secondary`,children:[e.path,e.status===`modified`?``:(0,H.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,e.status]})]}),e.patch===null?(0,H.jsx)(`p`,{className:`mt-1 text-meta`,children:`A binary file; its contents are not shown.`}):e.patch===``?(0,H.jsx)(`p`,{className:`mt-1 text-meta`,children:`Empty.`}):(0,H.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
+ `).map((e,t)=>(0,H.jsx)(`span`,{className:`block whitespace-pre-wrap break-words ${ye(e)}`,children:e===``?` `:e},t))}),e.truncated?(0,H.jsx)(`p`,{className:`mt-1 text-meta`,children:`The rest of this file's change is cut.`}):null]})}function xe({name:e,change:t}){let n=v(e,t.commit,!0);return(0,H.jsxs)(`div`,{className:`space-y-3 px-4 pt-1 pb-3`,children:[(0,H.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,H.jsx)(s,{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,H.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,U(t.at)]})]}),n.data===void 0?(0,H.jsx)(`p`,{className:`text-meta`,children:n.isError?`Could not read the change.`:`Reading the change…`}):n.data.map(e=>(0,H.jsx)(be,{file:e},e.path))]})}function Se({name:e,change:t,now:n}){let[r,i]=(0,V.useState)(!1),a=t.files.length===0?t.subject:ve(t);return(0,H.jsx)(`li`,{className:`border-b border-line/60 last:border-b-0`,children:(0,H.jsxs)(`details`,{className:`group`,onToggle:e=>i(e.currentTarget.open),children:[(0,H.jsx)(`summary`,{"aria-label":`${ge[t.kind]} ${_(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,H.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,H.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:he[t.kind]}),(0,H.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg-secondary`,children:a}),(0,H.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:_(t.at,n)}),(0,H.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]})}),r?(0,H.jsx)(xe,{name:e,change:t}):null]})})}function Ce({name:e}){let[t,n]=(0,V.useState)(K),r=f(e,t),i=C(3e4);if(r.data===void 0)return(0,H.jsx)(L,{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,H.jsxs)(L,{children:[e,`'s home has no history yet; it starts with the citizen's first turn.`]}):(0,H.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,H.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,H.jsx)(`ol`,{children:a.map(t=>(0,H.jsx)(Se,{name:e,change:t,now:i},t.commit))}),o?(0,H.jsx)(`button`,{type:`button`,onClick:()=>n(t+K),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:`Show earlier changes`}):null]})}function q({title:e,children:t}){return(0,H.jsxs)(`section`,{className:`border-t border-line pt-4 first:border-t-0 first:pt-0`,children:[(0,H.jsx)(`h3`,{className:`text-section`,children:e}),(0,H.jsx)(`div`,{className:`mt-2`,children:t})]})}function we({member:e,charter:t}){let n=p(e.name),r=u(e.name),i=d(e.name),a=C(3e4);return(0,H.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,H.jsxs)(q,{title:`Edits to reconcile`,children:[(0,H.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,H.jsx)(`ul`,{className:`mt-2 space-y-1.5`,children:i.data.map(e=>(0,H.jsxs)(`li`,{className:`text-sm`,children:[(0,H.jsx)(`span`,{className:`text-fg-primary`,children:e.file}),(0,H.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,e.path.slice(e.path.lastIndexOf(`/`)+1),` · left`,` `,_(e.since,a)]})]},e.path))})]}),(0,H.jsx)(q,{title:`Profile`,children:e.profile.trim()===``?(0,H.jsx)(`p`,{className:`text-meta`,children:`No profile yet. The citizen writes its own profile.md.`}):(0,H.jsx)(I,{text:B(e.profile,`Profile`)})}),(0,H.jsx)(q,{title:`Core memory`,children:n.data===void 0?(0,H.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):n.data.body.trim()===``?(0,H.jsx)(`p`,{className:`text-meta`,children:`Empty. Every turn loads this file in full.`}):(0,H.jsx)(I,{text:B(n.data.body,`Core memory`)})}),(0,H.jsx)(q,{title:`Own skills`,children:r.data===void 0?(0,H.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):r.data.length===0?(0,H.jsx)(`p`,{className:`text-meta`,children:`None yet.`}):(0,H.jsx)(`ul`,{className:`space-y-1.5`,children:r.data.map(e=>(0,H.jsxs)(`li`,{className:`text-sm`,children:[(0,H.jsx)(`span`,{className:`text-fg-primary`,children:e.name}),e.summary===``?null:(0,H.jsxs)(`span`,{className:`text-fg-secondary`,children:[` · `,e.summary]})]},e.name))})}),t===void 0?null:(0,H.jsxs)(q,{title:`Charter of ${t.name}`,children:[(0,H.jsx)(`p`,{className:`text-sm text-fg-secondary`,children:t.purpose}),(0,H.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,H.jsx)(`p`,{className:`mt-2 flex flex-wrap gap-1`,children:t.verbs.map(e=>(0,H.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 J(e,t){let n=r(e,t?.turnId??null);return{turn:(0,V.useMemo)(()=>t===void 0||n.data===void 0?void 0:O(n.data,e,t.project,t.thread),[t,n.data,e]),loading:t?.turnId!==void 0&&n.isPending,missing:t!==void 0&&(t.turnId===void 0||n.isError)}}var Y=50;function Te({name:e,entry:t,cli:n,now:r,opened:i}){let[a,o]=(0,V.useState)(i),s=(0,V.useRef)(null);(0,V.useEffect)(()=>{i&&s.current?.scrollIntoView({block:`start`})},[i]);let c=T(),l=ce(t),u=t.thread===void 0?null:c.get(t.thread)?.title??`a thread`,d=t.error??t.summary??``,f=t.error===null?`text-fg-secondary`:`text-red-300`;return(0,H.jsx)(`li`,{ref:s,className:`border-b border-line/60 last:border-b-0`,children:(0,H.jsxs)(`details`,{className:`group`,open:a,onToggle:e=>o(e.currentTarget.open),children:[(0,H.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,H.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,H.jsxs)(`span`,{className:`min-w-0 truncate text-fg-secondary`,children:[z(t.project),u===null?``:` · ${u}`]}),(0,H.jsx)(`span`,{className:`text-fg-muted`,children:t.trigger}),(0,H.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-fg-muted`,children:[se(t),` `,_(t.ts,r)]}),(0,H.jsx)(`span`,{className:`shrink-0 font-mono text-[11px] text-fg-tertiary`,children:[l,t.toolCalls===void 0?null:`${t.toolCalls} tools`,de(t,n)].filter(e=>e!==null).join(` · `)}),(0,H.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]}),d.trim()===``?null:(0,H.jsx)(`span`,{className:`mt-1 line-clamp-2 block text-xs leading-relaxed group-open:hidden ${f}`,children:(0,H.jsx)(P,{text:d,links:!1})})]}),a?(0,H.jsx)(Ee,{name:e,entry:t,text:d,tone:f}):null]})})}function Ee({name:e,entry:t,text:n,tone:r}){let i=J(e,t);return(0,H.jsxs)(`div`,{className:`px-4 pt-1 pb-3`,children:[n.trim()===``?null:(0,H.jsx)(`p`,{className:`text-xs leading-relaxed whitespace-pre-wrap ${r}`,children:(0,H.jsx)(P,{text:n})}),(0,H.jsx)(`div`,{className:`mt-2`,children:t.turnId===void 0?(0,H.jsx)(`p`,{className:`text-meta`,children:`This turn ran before turns kept their steps.`}):i.loading?(0,H.jsx)(`p`,{className:`text-meta`,children:`Reading the steps…`}):i.turn===void 0?(0,H.jsx)(`p`,{className:`text-meta`,children:`No steps were kept for this turn.`}):(0,H.jsxs)(H.Fragment,{children:[t.startedAt===void 0?null:(0,H.jsxs)(`p`,{className:`text-caps`,children:[`Started `,U(t.startedAt)]}),(0,H.jsx)(G,{steps:i.turn.steps})]})})]})}function De({name:e,cli:t,opened:n}){let[r,a]=(0,V.useState)(Y),o=i(e,r),s=C(3e4);if(o.data===void 0)return(0,H.jsx)(L,{children:`Reading the turns…`});let c=o.data.toReversed();if(c.length===0)return(0,H.jsxs)(L,{children:[e,` has not finished a turn yet.`]});let l=le(c),u=t===`codex`?`unmetered`:`$${l.costUsd.toFixed(2)}`;return(0,H.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,H.jsxs)(`p`,{className:`px-4 pt-3 pb-1 text-meta`,children:[l.turns===1?`1 turn`:`${l.turns} turns`,l.failed===0?``:`, ${l.failed} not completed`,` · `,u]}),n!==null&&!c.some(e=>e.turnId===n)?(0,H.jsx)(`p`,{className:`px-4 pb-1 text-meta`,children:o.data.length===r?`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,H.jsx)(`ol`,{children:c.map(r=>(0,H.jsx)(Te,{name:e,entry:r,cli:t,now:s,opened:n!==null&&r.turnId===n},r.id))}),o.data.length===r?(0,H.jsxs)(`button`,{type:`button`,onClick:()=>a(r+Y),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:[`Show `,Y,` earlier turns`]}):null]})}function Oe(e){return e===void 0?``:`${e.name}${e.id===null?``:` · ${e.id}`}`}function X({label:e,choices:t,value:n,onChange:r}){let[i,a]=(0,V.useState)(!1),o=(0,V.useRef)(null),s=(0,V.useRef)(null),c=(0,V.useRef)([]),l=t.findIndex(e=>e.value===n);(0,V.useEffect)(()=>{if(!i)return;c.current[Math.max(l,0)]?.focus();let e=e=>{e.target instanceof Node&&o.current?.contains(e.target)===!0||a(!1)};return window.addEventListener(`pointerdown`,e),()=>window.removeEventListener(`pointerdown`,e)},[i,l]);let u=e=>{if(e.key===`Escape`){e.stopPropagation(),a(!1),s.current?.focus();return}if(e.key!==`ArrowDown`&&e.key!==`ArrowUp`)return;e.preventDefault();let n=(c.current.findIndex(e=>e===document.activeElement)+(e.key===`ArrowDown`?1:-1)+t.length)%t.length;c.current[n]?.focus()},d=t[l];return(0,H.jsxs)(`div`,{ref:o,className:`relative min-w-0 flex-1`,children:[(0,H.jsxs)(`button`,{ref:s,type:`button`,"aria-label":`${e}: ${Oe(d)}`,"aria-expanded":i,onClick:()=>a(!i),onKeyDown:i?u: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,H.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-left`,children:[d?.name,d?.id===null||d===void 0?null:(0,H.jsxs)(`span`,{className:`text-fg-tertiary`,children:[` · `,d.id]})]}),(0,H.jsx)(`span`,{"aria-hidden":`true`,className:`text-[10px] text-fg-muted transition-transform ${i?`rotate-180`:``}`,children:`▾`})]}),i?(0,H.jsx)(`div`,{className:`absolute inset-x-0 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,H.jsxs)(`button`,{ref:e=>{c.current[t]=e},type:`button`,"aria-current":i?`true`:void 0,onKeyDown:u,onClick:()=>{r(e.value),a(!1),s.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,H.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,H.jsxs)(`span`,{className:`block truncate text-xs text-fg-secondary`,children:[e.name,e.id===null?null:(0,H.jsxs)(`span`,{className:`text-fg-tertiary`,children:[` · `,e.id]})]}),e.description===``?null:(0,H.jsx)(`span`,{className:`block truncate text-[11px] text-fg-muted`,children:e.description})]}),(0,H.jsx)(`span`,{"aria-hidden":`true`,className:`w-3 shrink-0 pt-px text-[11px] text-fg-primary`,children:i?`✓`:``})]},e.value)})}):null]})}var Z=``;function ke(e,t){return[{value:Z,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 Ae({member:t,onDone:n}){let{api:r}=e(),i=m(),a=y(t.cli),s=t.model??Z,[c,l]=(0,V.useState)(s),u=D({mutationFn:()=>r.setModel(t.name,c===Z?null:c),onSuccess:()=>{i.invalidateQueries({queryKey:[`members`]}),n()}}),d=a.data??[],f=t.model!==void 0&&!d.some(e=>e.id===t.model)?t.model:null;return(0,H.jsxs)(`form`,{"aria-label":`Model of ${t.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),u.mutate()},children:[(0,H.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a.isPending?(0,H.jsxs)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:[`Asking `,t.cli,` for its models…`]}):a.error===null?(0,H.jsx)(X,{label:`Model`,choices:ke(d,f),value:c,onChange:l}):(0,H.jsxs)(`p`,{role:`alert`,className:`min-w-0 flex-1 truncate text-xs text-red-400`,children:[t.cli,` did not list its models:`,` `,a.error instanceof o?a.error.message:`the board server did not answer`]}),(0,H.jsx)(k,{onClick:n,children:`Cancel`}),(0,H.jsx)(k,{variant:`primary`,type:`submit`,disabled:u.isPending||c===s||a.error!==null,children:u.isPending?`Saving…`:`Use this model`})]}),(0,H.jsx)(R,{error:u.error})]})}var Q=``;function je(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 Me(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:je(e,t)}))]}function Ne({member:t,onDone:n}){let{api:r}=e(),i=m(),a=c(),o=t.homeRunner??Q,[s,l]=(0,V.useState)(o),u=D({mutationFn:()=>r.setRunner(t.name,s===Q?null:s),onSuccess:()=>{i.invalidateQueries({queryKey:[`members`]}),n()}});return(0,H.jsxs)(`form`,{"aria-label":`Runner of ${t.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),u.mutate()},children:[(0,H.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a.data===void 0?(0,H.jsx)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:`Reading the runners…`}):(0,H.jsx)(X,{label:`Runner`,choices:Me(a.data,t),value:s,onChange:l}),(0,H.jsx)(k,{onClick:n,children:`Cancel`}),(0,H.jsx)(k,{variant:`primary`,type:`submit`,disabled:u.isPending||s===o,children:u.isPending?`Saving…`:`Run here`})]}),(0,H.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,H.jsx)(R,{error:u.error})]})}function Pe(e){return e.thread===void 0?{channel:e.channel??(e.scope===`society`?`general`:`${e.scope}/general`)}:{threadId:e.thread}}function Fe({name:t,turn:n}){let{api:r}=e(),i=m(),[a,o]=(0,V.useState)(!1),s=D({mutationFn:()=>r.stopTurn(n.turnId),onSuccess:()=>{o(!1),i.invalidateQueries({queryKey:[`scheduler`]})}});return(0,H.jsxs)(`div`,{className:`border-t border-line`,children:[(0,H.jsx)(ne,{target:Pe(n),initialText:`@${t} `,placeholder:n.steerable?`Message ${t} while it works`:`Message ${t} for its next turn`,className:`px-3 pt-3 pb-2`},n.turnId),n.stoppable?(0,H.jsxs)(`div`,{className:`flex items-center gap-2 px-3 pb-3`,children:[(0,H.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.`:n.steerable?`Posts reach the turn at its next step.`:`This runner delivers posts after the turn ends.`}),a?(0,H.jsxs)(H.Fragment,{children:[(0,H.jsx)(k,{onClick:()=>{o(!1),s.reset()},children:`Keep it running`}),(0,H.jsx)(k,{variant:`primary`,disabled:s.isPending,onClick:()=>{s.mutate()},children:s.isPending?`Stopping…`:`Stop the turn`})]}):(0,H.jsx)(k,{onClick:()=>o(!0),children:`Stop…`})]}):null,s.error===null?null:(0,H.jsx)(`div`,{className:`px-3 pb-3`,children:(0,H.jsx)(R,{error:s.error})})]})}function Ie({member:t,scopes:n,preferred:r,running:i,paused:a,onDone:o}){let{api:s}=e(),c=m(),[l,u]=(0,V.useState)(`manual`),[d,f]=(0,V.useState)(r!==null&&n.includes(r)?r:n[0]??``),[p,h]=(0,V.useState)(``),g=(0,V.useRef)(null);(0,V.useEffect)(()=>g.current?.focus(),[]);let _=D({mutationFn:()=>s.wake({agent:t.name,project:d,kind:l,...p.trim()===``?{}:{reason:p.trim()}}),onSuccess:()=>{c.invalidateQueries({queryKey:[`scheduler`]}),o()}}),v=z(d),y=l===`reflection`?`Asks ${t.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 ${t.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)?` ${t.name} is in a turn there now; this one follows it.`:``;return(0,H.jsxs)(`form`,{"aria-label":`Wake ${t.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),_.mutate()},children:[(0,H.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,H.jsxs)(`fieldset`,{className:`flex gap-1`,children:[(0,H.jsx)(`legend`,{className:`sr-only`,children:`Kind of turn`}),[`manual`,`reflection`].map(e=>(0,H.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,H.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,H.jsxs)(`label`,{className:`ml-auto flex items-center gap-2 text-xs text-fg-tertiary`,children:[`at`,(0,H.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:n.map(e=>(0,H.jsx)(`option`,{value:e,children:z(e)},e))})]})]}),(0,H.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:`${ae} resize-none`}),(0,H.jsxs)(`p`,{className:`text-[11px] leading-relaxed text-fg-muted`,children:[y,b,` Each turn costs money.`]}),(0,H.jsxs)(`div`,{className:`flex items-center justify-end gap-2`,children:[(0,H.jsx)(k,{onClick:o,children:`Cancel`}),(0,H.jsx)(k,{variant:`primary`,type:`submit`,disabled:_.isPending||d===``,children:_.isPending?`Waking…`:l===`reflection`?`Ask for a reflection`:`Wake ${t.name}`})]}),(0,H.jsx)(R,{error:_.error})]})}var Le={working:`bg-emerald-500/15 text-emerald-300`,queued:`bg-amber-500/15 text-amber-300`,idle:`bg-surface-2 text-fg-tertiary`};function Re({project:e,name:t}){let n=(a(e).data??[]).filter(e=>e.status===`claimed`&&e.claimedBy===t);return n.length===0?null:(0,H.jsx)(`ul`,{className:`mt-1.5 space-y-1`,children:n.map(e=>(0,H.jsx)(`li`,{children:(0,H.jsxs)(s,{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,H.jsx)(`span`,{"aria-hidden":`true`,className:`text-fg-muted`,children:`◇`}),(0,H.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.title}),(0,H.jsx)(`span`,{className:`max-w-[40%] shrink-0 truncate font-mono text-[11px] text-fg-muted`,children:g(e)?.name??e.stage})]})},e.id))})}function ze(){let{name:e}=w({from:`/citizen/$name`}),{scope:t,tab:n,turn:r}=re({from:`/citizen/$name`});return(0,H.jsx)(Ve,{name:e,chosen:t??null,tab:n??`now`,turn:r??null},e)}var Be=[{tab:`now`,label:`Now`},{tab:`turns`,label:`Turns`},{tab:`memory`,label:`Memory`},{tab:`history`,label:`History`}];function Ve({name:e,chosen:r,tab:i,turn:a}){let o=h(),c=x(),l=t(),u=F(),[d,f]=(0,V.useState)(null),p=o.data?.find(t=>t.name===e);if(p===void 0)return(0,H.jsx)(L,{children:o.data===void 0?`Reading the roster…`:`There is no citizen ${e}.`});let m=n(l.data?.running??[]).filter(t=>t.agent===e),g=[...new Set(m.map(e=>e.scope))],_=m.map(e=>j(e.agent,e.scope,e.thread)),v=n(l.data?.pending??[]).find(t=>t.agent===e),y=g.length>0?`working`:v===void 0?`idle`:`queued`,b=N(u,e)[0],S=b?.model??p.lastModel,C=S??p.model??`CLI default`,w=p.model!==void 0&&p.model!==S?p.model:null,T=c.data?.find(e=>e.name===p.role),D=ue(p),O=p.status===`active`&&p.cli!==null;return(0,H.jsxs)(H.Fragment,{children:[(0,H.jsx)(ie,{leading:p.cli===null?null:(0,H.jsx)(`span`,{className:`grid size-9 shrink-0 place-items-center rounded-lg bg-surface-2/70`,children:(0,H.jsx)(E,{cli:p.cli,size:20})}),title:e,subtitle:(0,H.jsxs)(H.Fragment,{children:[p.role,` · `,C,w===null?``:` · set to ${w}`,p.homeRunner===void 0?``:` · on ${p.homeRunner}`,p.status===`retired`?` · retired`:``]}),trailing:(0,H.jsxs)(H.Fragment,{children:[O&&d===null?(0,H.jsxs)(H.Fragment,{children:[(0,H.jsx)(k,{onClick:()=>f(`model`),children:`Model…`}),(0,H.jsx)(k,{onClick:()=>f(`runner`),children:`Runner…`}),(0,H.jsx)(k,{onClick:()=>f(`wake`),children:`Wake…`})]}):null,(0,H.jsx)(`span`,{className:`shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium ${Le[y]}`,children:y})]})}),d===`wake`?(0,H.jsx)(Ie,{member:p,scopes:D,preferred:r?.split(`/`)[0]??b?.scope??null,running:g,paused:l.data?.paused??!1,onDone:()=>f(null)}):d===`model`?(0,H.jsx)(Ae,{member:p,onDone:()=>f(null)}):d===`runner`?(0,H.jsx)(Ne,{member:p,onDone:()=>f(null)}):null,(0,H.jsx)(`nav`,{"aria-label":`Citizen views`,className:`flex gap-1 border-b border-line px-3 py-2`,children:Be.map(t=>(0,H.jsx)(s,{to:`/citizen/$name`,params:{name:e},search:{...r===null?{}:{scope:r},...t.tab===`now`?{}:{tab:t.tab}},replace:!0,"aria-current":t.tab===i?`page`:void 0,className:`rounded-md px-2.5 py-1 text-xs transition-colors ${t.tab===i?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:t.label},t.tab))}),i===`turns`?(0,H.jsx)(De,{name:e,cli:p.cli,opened:a},a):i===`memory`?(0,H.jsx)(we,{member:p,charter:T}):i===`history`?(0,H.jsx)(Ce,{name:e}):(0,H.jsx)(He,{name:e,chosen:r,lastTurnAt:p.lastTurnAt,state:y,runningScopes:g,runningKeys:_,runningTurns:(l.data?.turns??[]).filter(t=>t.agent===e),queuedScope:v?.scope??null})]})}function $(e){return e.toSorted((e,t)=>e.startedAt.localeCompare(t.startedAt))[0]}function He({name:e,chosen:t,lastTurnAt:n,state:r,runningScopes:a,runningKeys:o,runningTurns:c,queuedScope:l}){let u=F(),d=C(5e3),{ref:f,onScroll:p}=oe(),m=N(u,e),h=i(e,1),g=J(e,m.length===0?h.data?.at(-1):void 0),v=T(),y=e=>e.end===null&&o.includes(j(e.agent,e.scope,e.thread)),b=t?.split(`/`)[0]??null,x=(t?.includes(`/`)===!0?m.find(e=>A(e)===t):void 0)??$(m.filter(e=>e.scope===b&&y(e)))??m.find(e=>A(e)===t)??$(m.filter(y))??m[0]??g.turn,S=e=>e.thread===void 0?z(e.scope):`${z(e.scope)} · ${v.get(e.thread)?.title??`a thread`}`,w=x!==void 0&&y(x),E=x?.scope??a[0]??l,D=(x===void 0?void 0:c.find(e=>e.scope===x.scope&&e.thread===x.thread))??(w?void 0:c[0]);return(0,H.jsxs)(H.Fragment,{children:[(0,H.jsxs)(`section`,{className:`border-b border-line px-4 py-3 text-xs text-fg-tertiary`,children:[(0,H.jsx)(`p`,{children:w?`In a turn at ${z(x.scope)} for ${x.fromStart?``:`at least `}${M(x.startedAt,d)}`:a.length>0?`In a turn at ${a.map(z).join(` and `)}`:l===null?n===void 0?`No turns yet`:`Last turn ${_(n,d)}`:`Queued for a turn at ${z(l)}`}),E===null||E===`society`?null:(0,H.jsx)(Re,{project:E,name:e})]}),(0,H.jsx)(`div`,{ref:f,onScroll:p,className:`flex-1 overflow-y-auto px-4 py-3`,children:x===void 0?(0,H.jsx)(L,{children:r===`working`?`The turn has not reported a step yet.`:g.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,H.jsxs)(H.Fragment,{children:[m.length>1?(0,H.jsx)(`div`,{className:`mb-3 flex flex-wrap gap-1.5`,"aria-label":`Turns by conversation`,children:m.toSorted((e,t)=>A(e).localeCompare(A(t))).map(t=>(0,H.jsxs)(s,{to:`/citizen/$name`,params:{name:e},search:{scope:A(t)},replace:!0,"aria-current":t===x?`true`:void 0,className:`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-[11px] transition-colors ${t===x?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:[y(t)?(0,H.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}):null,S(t)]},A(t)))}):null,(0,H.jsxs)(`p`,{className:`text-caps`,children:[w?`This turn`:`Last turn`,` · `,S(x),` · started`,` `,x.fromStart?U(x.startedAt):`before the earliest step shown`]}),x.fromStart?null:(0,H.jsxs)(`p`,{className:`mt-1 text-meta`,children:[`Earlier steps of this turn are no longer in the server's live buffer`,w?``:`; Turns has the whole turn`,`.`]}),(0,H.jsx)(G,{steps:x.steps}),(0,H.jsx)(me,{turn:x,running:w,now:d})]})}),D===void 0?null:(0,H.jsx)(Fe,{name:e,turn:D})]})}export{ze as CitizenView};
@@ -1 +1 @@
1
- import{T as e,V as t,gn as n,m as r,xt as i,y as a}from"./format-8m6fdeP8.js";import{S as o}from"./index-CADeLxUP.js";import{n as s,t as c}from"./Pane-JzhKR0rO.js";import{a as l,i as u}from"./citizen-TjyiyFqE.js";var d=n();function f(e){let t=e.lastModel??e.model??`CLI default`;return e.model!==void 0&&e.model!==t?`${t} · set to ${e.model}`:t}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 n=r(),h=e(),g=a();if(n.data===void 0)return(0,d.jsx)(s,{children:`Reading the roster…`});let _=n.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(`, `),a=u(e,C);return(0,d.jsx)(`li`,{className:`col-span-full grid grid-cols-subgrid`,children:(0,d.jsxs)(i,{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:a.detail,children:a.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,H as t,St as n,_n as r,b as i,h as a}from"./format-11lojpK1.js";import{T as o}from"./index-BXq4t0NA.js";import{n as s,t as c}from"./Pane-B-pz52UC.js";import{a as l,i as u}from"./citizen-CYBzbWt-.js";var d=r();function f(e){let t=e.lastModel??e.model??`CLI default`;return e.model!==void 0&&e.model!==t?`${t} · set to ${e.model}`:t}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 r=a(),h=e(),g=i();if(r.data===void 0)return(0,d.jsx)(s,{children:`Reading the roster…`});let _=r.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),r=f(e),i=e.memberships.length===0?`no projects`:e.memberships.join(`, `),a=u(e,C);return(0,d.jsx)(`li`,{className:`col-span-full grid grid-cols-subgrid`,children:(0,d.jsxs)(n,{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:r,children:r}),(0,d.jsx)(`span`,{className:`text-xs text-fg-muted`,title:a.detail,children:a.label}),(0,d.jsx)(`span`,{className:`truncate text-xs text-fg-muted`,title:i,children:i}),(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};
@@ -0,0 +1 @@
1
+ import{St as e,_n as t,at as n,b as r,p as i,t as a,y as o}from"./format-11lojpK1.js";import{B as s}from"./index-BXq4t0NA.js";import{t as c}from"./Markdown-MZnGPfvk.js";import{n as l,t as u}from"./Pane-B-pz52UC.js";import{t as d}from"./BackLink-DivaHiZ7.js";var f=t(),p=`grid size-7 shrink-0 place-items-center rounded-lg text-fg-tertiary hover:bg-surface-2/70 hover:text-fg-primary`;function m(){let{scope:t,topic:m}=s({from:`/knowledge/$scope/$topic`}),h=i(t),g=r(),_=o(3e4),v=t===n,y=v?`the society`:g.data?.find(e=>e.slug===t)?.name??t,b=h.data?.find(e=>e.topic===m),x=v?(0,f.jsx)(e,{to:`/society`,"aria-label":`Back to the society`,className:p,children:`←`}):(0,f.jsx)(e,{to:`/p/$slug`,params:{slug:t},"aria-label":`Back to ${y}`,className:p,children:`←`});return b===void 0?(0,f.jsx)(l,{children:h.data===void 0?`Reading…`:`${y} has no topic ${m}.`}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(u,{leading:(0,f.jsx)(d,{fallback:x}),title:b.topic,subtitle:`Knowledge of ${y} · written by ${b.updatedBy} ${a(b.updatedAt,_)}`}),(0,f.jsx)(`div`,{className:`flex-1 overflow-y-auto px-4 py-4`,children:(0,f.jsx)(c,{text:b.body})})]})}export{m as KnowledgeView};