@kubitnodes/stellaris 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +139 -15
- package/dist/server/index.js +210 -31
- package/package.json +1 -1
- package/web/dist/assets/BackLink-BW0sb-M0.js +1 -0
- package/web/dist/assets/ChannelView-DmTE9aUA.js +1 -0
- package/web/dist/assets/CitizenView-lrA6vZDK.js +2 -0
- package/web/dist/assets/CitizensView-MRVffBnU.js +1 -0
- package/web/dist/assets/KnowledgeView-C2N-x5yS.js +1 -0
- package/web/dist/assets/{Markdown-MZnGPfvk.js → Markdown-CS3NCze-.js} +4 -4
- package/web/dist/assets/MessageItem-CL3XDi7l.js +1 -0
- package/web/dist/assets/MetricsView-CR5u5k5n.js +1 -0
- package/web/dist/assets/NeedsYouView-BwUvwyVt.js +1 -0
- package/web/dist/assets/Overview-DxFOFviB.js +1 -0
- package/web/dist/assets/{Pane-B-pz52UC.js → Pane-voa6GU0F.js} +1 -1
- package/web/dist/assets/ProjectView-BkNG_qdh.js +1 -0
- package/web/dist/assets/ProposalView-G89UmLF5.js +1 -0
- package/web/dist/assets/ProposalsView-CzpL-POB.js +1 -0
- package/web/dist/assets/RunnersView-SKNIDsjR.js +1 -0
- package/web/dist/assets/{SocietyView-DA_65uyo.js → SocietyView-CCFXEYZW.js} +1 -1
- package/web/dist/assets/SubjectThread-JQG2FxkA.js +1 -0
- package/web/dist/assets/TaskFileView-BKoGmHGz.js +4 -0
- package/web/dist/assets/TaskView-BIYqIFU4.js +1 -0
- package/web/dist/assets/TasksView-n2ssgQOL.js +1 -0
- package/web/dist/assets/ThreadCard-CzQXJXSd.js +1 -0
- package/web/dist/assets/{ThreadForms-BipMby65.js → ThreadForms-0LpUc2jJ.js} +1 -1
- package/web/dist/assets/ThreadView-_LgGISSH.js +1 -0
- package/web/dist/assets/citizen-DvJr6Ibu.js +1 -0
- package/web/dist/assets/format-C7bqWt6N.js +55 -0
- package/web/dist/assets/index-D4oCtkuZ.css +2 -0
- package/web/dist/assets/index-DM00hlle.js +23 -0
- package/web/dist/assets/{tasks-DnJj3psB.js → tasks-B4bx7Gg3.js} +1 -1
- package/web/dist/assets/{useStickyScroll-D_7q2RKi.js → useStickyScroll-DCsF4GYJ.js} +1 -1
- package/web/dist/index.html +4 -4
- package/web/dist/assets/BackLink-DivaHiZ7.js +0 -1
- package/web/dist/assets/ChannelView-DgkkiZuY.js +0 -1
- package/web/dist/assets/CitizenView-BzhH1ycF.js +0 -2
- package/web/dist/assets/CitizensView-BzGNyC2f.js +0 -1
- package/web/dist/assets/KnowledgeView-DedLlEZd.js +0 -1
- package/web/dist/assets/MessageItem-Deq-ntT8.js +0 -1
- package/web/dist/assets/MetricsView-C-2j71rI.js +0 -1
- package/web/dist/assets/NeedsYouView-D4xqHNDU.js +0 -1
- package/web/dist/assets/Overview-DxCYcW_A.js +0 -1
- package/web/dist/assets/ProjectView-BhZYFv7f.js +0 -1
- package/web/dist/assets/ProposalView-DAc9lEHB.js +0 -1
- package/web/dist/assets/ProposalsView-CmwwJuop.js +0 -1
- package/web/dist/assets/RunnersView-Dqo_BEoK.js +0 -1
- package/web/dist/assets/SubjectThread-M4F1paqV.js +0 -1
- package/web/dist/assets/TaskFileView-CCNVrooP.js +0 -4
- package/web/dist/assets/TaskView-BTSDk1yL.js +0 -1
- package/web/dist/assets/TasksView-0IQm6u-_.js +0 -1
- package/web/dist/assets/ThreadCard-BTGP4fOT.js +0 -1
- package/web/dist/assets/ThreadView-D96DZAOM.js +0 -1
- package/web/dist/assets/citizen-CYBzbWt-.js +0 -1
- package/web/dist/assets/format-11lojpK1.js +0 -55
- package/web/dist/assets/index-BXq4t0NA.js +0 -23
- package/web/dist/assets/index-CKjqsZME.css +0 -2
package/dist/server/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import path9 from "node:path";
|
|
|
6
6
|
import { serve } from "@hono/node-server";
|
|
7
7
|
|
|
8
8
|
// packages/board-core/dist/board.js
|
|
9
|
-
import { readdir as readdir3, readFile as readFile5, rename as rename3, stat as stat2 } from "node:fs/promises";
|
|
9
|
+
import { mkdir as mkdir4, readdir as readdir3, readFile as readFile5, rename as rename3, stat as stat2 } from "node:fs/promises";
|
|
10
10
|
import path6 from "node:path";
|
|
11
11
|
import { decodeTime, monotonicFactory } from "ulid";
|
|
12
12
|
import { z as z12 } from "zod";
|
|
@@ -56,7 +56,8 @@ var VERB_NAMES = [
|
|
|
56
56
|
"plan_task",
|
|
57
57
|
"advance_task",
|
|
58
58
|
"configure_project",
|
|
59
|
-
"archive_project"
|
|
59
|
+
"archive_project",
|
|
60
|
+
"remove_knowledge"
|
|
60
61
|
];
|
|
61
62
|
var VerbNameSchema = z2.enum(VERB_NAMES);
|
|
62
63
|
var CharterTriggerSchema = z2.enum(["user_post", "ops_event", "heartbeat"]);
|
|
@@ -100,6 +101,7 @@ var MEMBER_VERBS = [
|
|
|
100
101
|
"join_project",
|
|
101
102
|
"leave_project",
|
|
102
103
|
"write_knowledge",
|
|
104
|
+
"remove_knowledge",
|
|
103
105
|
"plan_task",
|
|
104
106
|
"advance_task"
|
|
105
107
|
];
|
|
@@ -301,11 +303,23 @@ function mayHoldStage(member, task) {
|
|
|
301
303
|
return !(stage.gate && task.stages.slice(0, index).some((s) => s.holders.includes(member.name)));
|
|
302
304
|
}
|
|
303
305
|
var ModelNameSchema = z3.string().trim().min(1).max(120).regex(/^[\w.:/[\]-]+$/, "a model name is one word of letters, digits, and . _ : / - [ ]");
|
|
306
|
+
var EffortSchema = z3.string().trim().min(1).max(32).regex(/^[a-z][a-z0-9_-]*$/, "an effort is one lowercase word, such as high");
|
|
307
|
+
var EffortOptionSchema = z3.object({
|
|
308
|
+
id: EffortSchema,
|
|
309
|
+
description: z3.string().default("")
|
|
310
|
+
});
|
|
304
311
|
var ModelOptionSchema = z3.object({
|
|
305
312
|
id: ModelNameSchema,
|
|
306
313
|
name: z3.string(),
|
|
307
314
|
description: z3.string().default(""),
|
|
308
|
-
isDefault: z3.boolean().default(false)
|
|
315
|
+
isDefault: z3.boolean().default(false),
|
|
316
|
+
efforts: z3.array(EffortOptionSchema).default([]),
|
|
317
|
+
defaultEffort: EffortSchema.optional()
|
|
318
|
+
});
|
|
319
|
+
var RunnerModelsSchema = z3.object({
|
|
320
|
+
runner: NameSchema,
|
|
321
|
+
cli: CliKindSchema,
|
|
322
|
+
models: z3.array(ModelOptionSchema)
|
|
309
323
|
});
|
|
310
324
|
var AgentStatusSchema = z3.enum(["active", "retired"]);
|
|
311
325
|
var AgentSchema = z3.object({
|
|
@@ -313,6 +327,8 @@ var AgentSchema = z3.object({
|
|
|
313
327
|
role: NameSchema,
|
|
314
328
|
cli: CliKindSchema.nullable(),
|
|
315
329
|
model: z3.string().optional(),
|
|
330
|
+
/** The reasoning effort set for the agent's turns; the model's own default applies otherwise. */
|
|
331
|
+
effort: z3.string().optional(),
|
|
316
332
|
/** The runner preferred for the agent's turns where nothing else decides; any runner with its CLI otherwise. */
|
|
317
333
|
homeRunner: NameSchema.optional(),
|
|
318
334
|
memberships: z3.array(NameSchema),
|
|
@@ -334,6 +350,8 @@ var MemberSchema = z3.object({
|
|
|
334
350
|
model: z3.string().optional(),
|
|
335
351
|
/** The model the CLI reported on the citizen's last turn. */
|
|
336
352
|
lastModel: z3.string().optional(),
|
|
353
|
+
/** The reasoning effort configured on the record, if any; the model's own default applies otherwise. */
|
|
354
|
+
effort: z3.string().optional(),
|
|
337
355
|
/** The citizen's own skills, by name. */
|
|
338
356
|
skills: z3.array(NameSchema).default([]),
|
|
339
357
|
memberships: z3.array(NameSchema),
|
|
@@ -523,6 +541,12 @@ var KnowledgeSchema = z3.object({
|
|
|
523
541
|
updatedBy: NameSchema,
|
|
524
542
|
updatedAt: IsoDateTimeSchema
|
|
525
543
|
});
|
|
544
|
+
var RemovedKnowledgeSchema = z3.object({
|
|
545
|
+
topic: NameSchema,
|
|
546
|
+
project: NameSchema.nullable(),
|
|
547
|
+
removedBy: NameSchema,
|
|
548
|
+
removedAt: IsoDateTimeSchema
|
|
549
|
+
});
|
|
526
550
|
var ProposalFrontmatterSchema = z3.object({
|
|
527
551
|
id: UlidSchema,
|
|
528
552
|
kind: ProposalKindSchema,
|
|
@@ -619,6 +643,11 @@ var VerbInputs = {
|
|
|
619
643
|
topic: NameSchema,
|
|
620
644
|
body: z4.string().min(1)
|
|
621
645
|
}),
|
|
646
|
+
remove_knowledge: z4.object({
|
|
647
|
+
/** As for write_knowledge: a project you belong to, or null for society knowledge. */
|
|
648
|
+
project: NameSchema.nullable().default(null),
|
|
649
|
+
topic: NameSchema
|
|
650
|
+
}),
|
|
622
651
|
plan_task: z4.object({
|
|
623
652
|
task_id: UlidSchema,
|
|
624
653
|
stages: z4.array(PlanEditStageSchema),
|
|
@@ -652,6 +681,7 @@ var VERB_DESCRIPTIONS = {
|
|
|
652
681
|
join_project: "Join a project, or add another citizen to one when your role allows it. Membership gives the pair a worktree and an onboarding turn.",
|
|
653
682
|
leave_project: "Leave a project, or remove another citizen from one when your role allows it.",
|
|
654
683
|
write_knowledge: "Write or replace a knowledge topic: durable facts every member of a project should know, or with project null the society's shared knowledge (steward and user). Not a message; use post_message for those.",
|
|
684
|
+
remove_knowledge: "Remove a knowledge topic that is wrong, superseded, or folded into another, so no turn or search finds it again. Whoever may write the topic may remove it; the board keeps its text aside for the user to restore.",
|
|
655
685
|
plan_task: "Reshape a task's plan from the current stage onward, or after it while someone holds it: keep a stage by passing its id, drop it by leaving it out, add one without an id. Gated stages and on_done: user, steward, concierge.",
|
|
656
686
|
advance_task: "Finish the stage you hold, with a note for the task's thread on what you did. The next stage becomes current; past the last one the task is done.",
|
|
657
687
|
configure_project: "Set a project's completion effect: none, or merge to land each finished task's branch on the default branch.",
|
|
@@ -693,6 +723,7 @@ var BOARD_EVENT_TYPES = [
|
|
|
693
723
|
"agent.joined",
|
|
694
724
|
"agent.left",
|
|
695
725
|
"knowledge.written",
|
|
726
|
+
"knowledge.removed",
|
|
696
727
|
"skill.promoted",
|
|
697
728
|
"runner.added",
|
|
698
729
|
"user.signed_in",
|
|
@@ -877,6 +908,8 @@ var TurnJobSchema = z6.object({
|
|
|
877
908
|
role: NameSchema,
|
|
878
909
|
cli: CliKindSchema,
|
|
879
910
|
model: z6.string().optional(),
|
|
911
|
+
/** The reasoning effort set on the agent; absent for the model's own default. */
|
|
912
|
+
effort: z6.string().optional(),
|
|
880
913
|
/** A project slug, or the society scope. */
|
|
881
914
|
scope: NameSchema,
|
|
882
915
|
/** The thread whose conversation the turn is in; absent for the home conversation. */
|
|
@@ -1113,6 +1146,8 @@ var TurnHistoryEntrySchema = z7.object({
|
|
|
1113
1146
|
trigger: z7.string(),
|
|
1114
1147
|
exitReason: z7.string().nullable(),
|
|
1115
1148
|
costUsd: z7.number(),
|
|
1149
|
+
/** The tokens the turn used; absent for turns logged before turns recorded them. */
|
|
1150
|
+
usage: UsageSchema.optional(),
|
|
1116
1151
|
model: z7.string().nullable(),
|
|
1117
1152
|
summary: z7.string().nullable(),
|
|
1118
1153
|
error: z7.string().nullable(),
|
|
@@ -1341,7 +1376,7 @@ var RunnerConfigSchema = z10.object({
|
|
|
1341
1376
|
});
|
|
1342
1377
|
|
|
1343
1378
|
// packages/shared/dist/version.js
|
|
1344
|
-
var STELLARIS_VERSION = "0.3.
|
|
1379
|
+
var STELLARIS_VERSION = "0.3.7";
|
|
1345
1380
|
|
|
1346
1381
|
// packages/board-core/dist/errors.js
|
|
1347
1382
|
var BoardError = class extends Error {
|
|
@@ -2377,6 +2412,10 @@ var BoardPaths = class {
|
|
|
2377
2412
|
pausedFile() {
|
|
2378
2413
|
return path5.join(this.state(), "paused.json");
|
|
2379
2414
|
}
|
|
2415
|
+
/** Removed knowledge topics, set aside outside the projection, by scope. */
|
|
2416
|
+
removedKnowledge(scope) {
|
|
2417
|
+
return path5.join(this.state(), "removed-knowledge", scope);
|
|
2418
|
+
}
|
|
2380
2419
|
};
|
|
2381
2420
|
|
|
2382
2421
|
// packages/board-core/dist/tokens.js
|
|
@@ -2410,6 +2449,7 @@ var TurnHistoryPayloadSchema = z12.object({
|
|
|
2410
2449
|
trigger: z12.string().default("manual"),
|
|
2411
2450
|
exitReason: z12.string().nullable().default(null),
|
|
2412
2451
|
costUsd: z12.number().default(0),
|
|
2452
|
+
usage: UsageSchema.optional(),
|
|
2413
2453
|
model: z12.string().nullable().default(null),
|
|
2414
2454
|
summary: z12.string().nullable().default(null),
|
|
2415
2455
|
error: z12.string().nullable().default(null),
|
|
@@ -2469,6 +2509,7 @@ var OPS_CHANNEL_RETIRED = "ops-channel-retired";
|
|
|
2469
2509
|
var DECISIONS_CHANNEL_RETIRED = "decisions-channel-retired";
|
|
2470
2510
|
var THREAD_CONVERSATIONS = "thread-conversations";
|
|
2471
2511
|
var ASKS_CHANNEL_OPENED = "asks-channel-opened";
|
|
2512
|
+
var KNOWLEDGE_REMOVAL = "knowledge-removal-granted";
|
|
2472
2513
|
var PLANNING_ROLES = [USER_ROLE, "steward", "concierge"];
|
|
2473
2514
|
var REALLOCATING_ROLES = [USER_ROLE, "steward", "concierge"];
|
|
2474
2515
|
var PROFILE_TEMPLATE = "# Profile\n\nOne short paragraph, kept current: what I do well, what I am working on, and what to send my way. The board projects this into the roster the front desk reads.\n";
|
|
@@ -2658,7 +2699,8 @@ var Board = class _Board {
|
|
|
2658
2699
|
OPS_CHANNEL_RETIRED,
|
|
2659
2700
|
DECISIONS_CHANNEL_RETIRED,
|
|
2660
2701
|
THREAD_CONVERSATIONS,
|
|
2661
|
-
ASKS_CHANNEL_OPENED
|
|
2702
|
+
ASKS_CHANNEL_OPENED,
|
|
2703
|
+
KNOWLEDGE_REMOVAL
|
|
2662
2704
|
].filter((name) => !applied.includes(name));
|
|
2663
2705
|
if (pending.length === 0) {
|
|
2664
2706
|
return;
|
|
@@ -2687,8 +2729,22 @@ var Board = class _Board {
|
|
|
2687
2729
|
if (pending.includes(ASKS_CHANNEL_OPENED)) {
|
|
2688
2730
|
await this.openAsksChannel();
|
|
2689
2731
|
}
|
|
2732
|
+
if (pending.includes(KNOWLEDGE_REMOVAL)) {
|
|
2733
|
+
await this.grantKnowledgeRemoval();
|
|
2734
|
+
}
|
|
2690
2735
|
await writeJson(file, { applied: [...applied, ...pending] });
|
|
2691
2736
|
}
|
|
2737
|
+
/**
|
|
2738
|
+
* Whoever may write a scope's knowledge may remove it, so every charter granting
|
|
2739
|
+
* `write_knowledge` is granted `remove_knowledge` once; seed roles have it from their seed.
|
|
2740
|
+
*/
|
|
2741
|
+
async grantKnowledgeRemoval() {
|
|
2742
|
+
for (const charter of await this.listRoles()) {
|
|
2743
|
+
if (charter.verbs.includes("write_knowledge") && !charter.verbs.includes("remove_knowledge")) {
|
|
2744
|
+
await this.writeRoleUnlocked(USER_NAME, { ...charter, verbs: [...charter.verbs, "remove_knowledge"] }, { verbsAdded: ["remove_knowledge"] });
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2692
2748
|
/**
|
|
2693
2749
|
* A task sent back before tasks recorded it kept no trace outside the event log. A task still
|
|
2694
2750
|
* short of the stage its latest `task.moved` came from is in that rework, and records it.
|
|
@@ -3920,16 +3976,7 @@ ${task.body}`;
|
|
|
3920
3976
|
const args = VerbInputs.write_knowledge.parse(input);
|
|
3921
3977
|
await this.authorize(actor, "write_knowledge");
|
|
3922
3978
|
return this.mutex.run(async () => {
|
|
3923
|
-
|
|
3924
|
-
if (!CURATING_ROLES.includes(actor.role)) {
|
|
3925
|
-
throw new BoardError("FORBIDDEN", "society knowledge is curated by the steward and the user");
|
|
3926
|
-
}
|
|
3927
|
-
} else {
|
|
3928
|
-
const project = await this.readActiveProject(args.project);
|
|
3929
|
-
if (!CURATING_ROLES.includes(actor.role) && !project.members.includes(actor.name)) {
|
|
3930
|
-
throw new BoardError("FORBIDDEN", `${actor.name} is not a member of ${args.project}`);
|
|
3931
|
-
}
|
|
3932
|
-
}
|
|
3979
|
+
await this.assertMayCurate(actor, args.project);
|
|
3933
3980
|
const data = KnowledgeSchema.parse({
|
|
3934
3981
|
topic: args.topic,
|
|
3935
3982
|
project: args.project,
|
|
@@ -3949,6 +3996,52 @@ ${task.body}`;
|
|
|
3949
3996
|
return { ...data, body: args.body };
|
|
3950
3997
|
});
|
|
3951
3998
|
}
|
|
3999
|
+
/**
|
|
4000
|
+
* Retires a topic, by whoever may write it. Its file leaves the knowledge directory, so no turn,
|
|
4001
|
+
* search, or digest finds it again, and is set aside under `state/removed-knowledge`, outside
|
|
4002
|
+
* the projection, for the user to restore by hand. The note in the matching general channel
|
|
4003
|
+
* carries no mention, as a write's does.
|
|
4004
|
+
*/
|
|
4005
|
+
async removeKnowledge(actor, input) {
|
|
4006
|
+
const args = VerbInputs.remove_knowledge.parse(input);
|
|
4007
|
+
await this.authorize(actor, "remove_knowledge");
|
|
4008
|
+
return this.mutex.run(async () => {
|
|
4009
|
+
await this.assertMayCurate(actor, args.project);
|
|
4010
|
+
const file = args.project === null ? this.paths.societyKnowledgeFile(args.topic) : this.paths.projectKnowledgeFile(args.project, args.topic);
|
|
4011
|
+
if (!await exists(file)) {
|
|
4012
|
+
throw new BoardError("NOT_FOUND", `${args.project ?? "the society"} has no knowledge topic ${args.topic}`);
|
|
4013
|
+
}
|
|
4014
|
+
const removed = RemovedKnowledgeSchema.parse({
|
|
4015
|
+
topic: args.topic,
|
|
4016
|
+
project: args.project,
|
|
4017
|
+
removedBy: actor.name,
|
|
4018
|
+
removedAt: this.now().toISOString()
|
|
4019
|
+
});
|
|
4020
|
+
const aside = this.paths.removedKnowledge(args.project ?? SOCIETY_SCOPE);
|
|
4021
|
+
await mkdir4(aside, { recursive: true });
|
|
4022
|
+
await rename3(file, path6.join(aside, `${args.topic}.${removed.removedAt.replaceAll(":", "-")}.md`));
|
|
4023
|
+
await this.events.append("knowledge.removed", actor.name, {
|
|
4024
|
+
topic: args.topic,
|
|
4025
|
+
project: args.project
|
|
4026
|
+
});
|
|
4027
|
+
const where = args.project === null ? "general" : channelRef(args.project, "general");
|
|
4028
|
+
await this.appendMessage(actor.name, where, `Knowledge removed: ${args.topic}. It is no longer under knowledge/${args.topic}.md${args.project === null ? " of the society" : ""}.`);
|
|
4029
|
+
return removed;
|
|
4030
|
+
});
|
|
4031
|
+
}
|
|
4032
|
+
/** Society knowledge is the steward's and the user's; a project's, its members' too. */
|
|
4033
|
+
async assertMayCurate(actor, project) {
|
|
4034
|
+
if (project === null) {
|
|
4035
|
+
if (!CURATING_ROLES.includes(actor.role)) {
|
|
4036
|
+
throw new BoardError("FORBIDDEN", "society knowledge is curated by the steward and the user");
|
|
4037
|
+
}
|
|
4038
|
+
return;
|
|
4039
|
+
}
|
|
4040
|
+
const active = await this.readActiveProject(project);
|
|
4041
|
+
if (!CURATING_ROLES.includes(actor.role) && !active.members.includes(actor.name)) {
|
|
4042
|
+
throw new BoardError("FORBIDDEN", `${actor.name} is not a member of ${project}`);
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
3952
4045
|
async openThread(actor, input) {
|
|
3953
4046
|
const args = VerbInputs.open_thread.parse(input);
|
|
3954
4047
|
await this.authorize(actor, "open_thread");
|
|
@@ -4775,6 +4868,8 @@ ${rationale}`}`);
|
|
|
4775
4868
|
return this.leaveProject(actor, VerbInputs.leave_project.parse(input));
|
|
4776
4869
|
case "write_knowledge":
|
|
4777
4870
|
return this.writeKnowledge(actor, VerbInputs.write_knowledge.parse(input));
|
|
4871
|
+
case "remove_knowledge":
|
|
4872
|
+
return this.removeKnowledge(actor, VerbInputs.remove_knowledge.parse(input));
|
|
4778
4873
|
case "plan_task":
|
|
4779
4874
|
return this.planTask(actor, VerbInputs.plan_task.parse(input));
|
|
4780
4875
|
case "advance_task":
|
|
@@ -5013,6 +5108,7 @@ ${rationale}`}`);
|
|
|
5013
5108
|
session: parsed.session,
|
|
5014
5109
|
exitReason: parsed.exitReason,
|
|
5015
5110
|
costUsd: parsed.costUsd,
|
|
5111
|
+
...parsed.usage === null ? {} : { usage: parsed.usage },
|
|
5016
5112
|
toolCalls: parsed.toolCalls,
|
|
5017
5113
|
model: parsed.model,
|
|
5018
5114
|
summary: parsed.status?.summary ?? null,
|
|
@@ -5469,6 +5565,7 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
5469
5565
|
resident: charter.resident,
|
|
5470
5566
|
...agent.model === void 0 ? {} : { model: agent.model },
|
|
5471
5567
|
...lastModel === void 0 ? {} : { lastModel },
|
|
5568
|
+
...agent.effort === void 0 ? {} : { effort: agent.effort },
|
|
5472
5569
|
skills: (await this.listAgentSkills(name)).map((skill) => skill.name),
|
|
5473
5570
|
memberships: agent.memberships,
|
|
5474
5571
|
subscriptions: agent.subscriptions,
|
|
@@ -5517,6 +5614,29 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
5517
5614
|
return next;
|
|
5518
5615
|
});
|
|
5519
5616
|
}
|
|
5617
|
+
/**
|
|
5618
|
+
* Sets the reasoning effort a citizen's turns run with, or clears it for the model's own default.
|
|
5619
|
+
* It applies from the citizen's next turn; the runner starts a warm session afresh when it changes.
|
|
5620
|
+
*/
|
|
5621
|
+
async setAgentEffort(actor, name, effort) {
|
|
5622
|
+
this.assertUser(actor, "only the user may change a citizen's reasoning effort");
|
|
5623
|
+
const chosen = effort === null ? null : EffortSchema.parse(effort);
|
|
5624
|
+
return this.mutex.run(async () => {
|
|
5625
|
+
const current = await this.readAgent(name);
|
|
5626
|
+
if (current.status !== "active" || current.cli === null) {
|
|
5627
|
+
throw new BoardError("INVALID_STATE", `${name} takes no turns, so it has no effort to set`);
|
|
5628
|
+
}
|
|
5629
|
+
const { effort: previous, ...rest } = current;
|
|
5630
|
+
const next = await this.updateAgent(name, () => chosen === null ? rest : { ...rest, effort: chosen });
|
|
5631
|
+
await this.refreshMember(name);
|
|
5632
|
+
await this.events.append("agent.configured", actor.name, {
|
|
5633
|
+
agent: name,
|
|
5634
|
+
effort: chosen,
|
|
5635
|
+
previous: previous ?? null
|
|
5636
|
+
});
|
|
5637
|
+
return next;
|
|
5638
|
+
});
|
|
5639
|
+
}
|
|
5520
5640
|
async updateAgent(name, mutate) {
|
|
5521
5641
|
const current = await this.readAgent(name);
|
|
5522
5642
|
const next = AgentSchema.parse(mutate(current));
|
|
@@ -8024,6 +8144,7 @@ var TurnHost = class {
|
|
|
8024
8144
|
role: agent.role,
|
|
8025
8145
|
cli: agent.cli,
|
|
8026
8146
|
...agent.model === void 0 ? {} : { model: agent.model },
|
|
8147
|
+
...agent.effort === void 0 ? {} : { effort: agent.effort },
|
|
8027
8148
|
scope: dispatch.project,
|
|
8028
8149
|
...thread === void 0 ? {} : { thread: thread.id },
|
|
8029
8150
|
session: recorded ?? null,
|
|
@@ -8431,6 +8552,7 @@ var RunnerHub = class {
|
|
|
8431
8552
|
pending = /* @__PURE__ */ new Map();
|
|
8432
8553
|
/** Disconnects being recorded, which `close` waits for. */
|
|
8433
8554
|
detaching = /* @__PURE__ */ new Set();
|
|
8555
|
+
runnerListeners = /* @__PURE__ */ new Set();
|
|
8434
8556
|
constructor(options) {
|
|
8435
8557
|
this.board = options.board;
|
|
8436
8558
|
this.host = options.host;
|
|
@@ -8486,6 +8608,7 @@ var RunnerHub = class {
|
|
|
8486
8608
|
clis: hello.clis,
|
|
8487
8609
|
capabilities: hello.capabilities
|
|
8488
8610
|
});
|
|
8611
|
+
this.runnerChanged(name);
|
|
8489
8612
|
this.log.info({ runner: name, clis: hello.clis, slots: hello.slots }, "runner registered");
|
|
8490
8613
|
return { name, version: this.version };
|
|
8491
8614
|
}
|
|
@@ -8502,6 +8625,7 @@ var RunnerHub = class {
|
|
|
8502
8625
|
seat.grace = null;
|
|
8503
8626
|
}
|
|
8504
8627
|
await this.board.markRunner(name, { status: "connected" });
|
|
8628
|
+
this.runnerChanged(name);
|
|
8505
8629
|
return async () => {
|
|
8506
8630
|
if (seat.send !== send) {
|
|
8507
8631
|
return;
|
|
@@ -8774,16 +8898,37 @@ var RunnerHub = class {
|
|
|
8774
8898
|
return changes;
|
|
8775
8899
|
}
|
|
8776
8900
|
/** The models a CLI offers, asked of a connected runner that has it; none when no runner has it. */
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8901
|
+
/**
|
|
8902
|
+
* The connected runner a model list for `cli` comes from: the first of `prefer` that has the CLI,
|
|
8903
|
+
* else the least busy that does; null when no connected runner has it.
|
|
8904
|
+
*/
|
|
8905
|
+
modelRunner(cli, prefer = []) {
|
|
8906
|
+
const able = (seat) => seat !== void 0 && seat.send !== null && seat.hello.clis.includes(cli);
|
|
8907
|
+
const preferred = prefer.map((name) => this.seats.get(name)).find(able);
|
|
8908
|
+
return (preferred ?? this.byLoad().find(able))?.name ?? null;
|
|
8909
|
+
}
|
|
8910
|
+
/** The models `cli` lists on a runner, `modelRunner`'s choice when none is named. */
|
|
8911
|
+
async models(cli, runner) {
|
|
8912
|
+
const name = runner ?? this.modelRunner(cli);
|
|
8913
|
+
const seat = name === null ? void 0 : this.seats.get(name);
|
|
8914
|
+
if (seat === void 0 || seat.send === null || !seat.hello.clis.includes(cli)) {
|
|
8915
|
+
throw new RunnerAwayError(runner === void 0 ? `no connected runner has ${cli}` : `runner ${runner} is not connected with ${cli}`);
|
|
8781
8916
|
}
|
|
8782
8917
|
return ModelListSchema.parse(await this.request(seat, (request) => ({ type: "models", request, cli })));
|
|
8783
8918
|
}
|
|
8919
|
+
/** Calls `listener` whenever a runner registers, connects, or goes away. */
|
|
8920
|
+
onRunnerChange(listener) {
|
|
8921
|
+
this.runnerListeners.add(listener);
|
|
8922
|
+
}
|
|
8923
|
+
runnerChanged(runner) {
|
|
8924
|
+
for (const listener of this.runnerListeners) {
|
|
8925
|
+
listener(runner);
|
|
8926
|
+
}
|
|
8927
|
+
}
|
|
8784
8928
|
// -------------------------------------------------------------------------------------------
|
|
8785
8929
|
async detach(seat) {
|
|
8786
8930
|
seat.send = null;
|
|
8931
|
+
this.runnerChanged(seat.name);
|
|
8787
8932
|
seat.disconnectedAt = this.now().getTime();
|
|
8788
8933
|
for (const [id, pending] of this.pending) {
|
|
8789
8934
|
if (pending.runner === seat.name) {
|
|
@@ -9453,6 +9598,7 @@ var RunnerBodySchema = z15.object({ name: NameSchema });
|
|
|
9453
9598
|
var EnrollmentApprovalSchema = z15.object({ name: NameSchema });
|
|
9454
9599
|
var HomeRunnerBodySchema = z15.object({ runner: NameSchema.nullable() });
|
|
9455
9600
|
var ModelBodySchema = z15.object({ model: ModelNameSchema.nullable() });
|
|
9601
|
+
var EffortBodySchema = z15.object({ effort: EffortSchema.nullable() });
|
|
9456
9602
|
var HistoryLimitSchema = z15.coerce.number().int().min(1).max(500);
|
|
9457
9603
|
var ChannelBodySchema = z15.object({
|
|
9458
9604
|
project: NameSchema.nullable().default(null),
|
|
@@ -9577,6 +9723,11 @@ function createApp(deps) {
|
|
|
9577
9723
|
const { tokenHash: _hash, ...agent } = await board2.setAgentModel(c.get("actor"), c.req.param("name"), body.model);
|
|
9578
9724
|
return c.json(agent);
|
|
9579
9725
|
});
|
|
9726
|
+
api.put("/agents/:name/effort", async (c) => {
|
|
9727
|
+
const body = EffortBodySchema.parse(await c.req.json());
|
|
9728
|
+
const { tokenHash: _hash, ...agent } = await board2.setAgentEffort(c.get("actor"), c.req.param("name"), body.effort);
|
|
9729
|
+
return c.json(agent);
|
|
9730
|
+
});
|
|
9580
9731
|
api.put("/agents/:name/runner", async (c) => {
|
|
9581
9732
|
const body = HomeRunnerBodySchema.parse(await c.req.json());
|
|
9582
9733
|
const { tokenHash: _hash, ...agent } = await board2.setAgentRunner(c.get("actor"), c.req.param("name"), body.runner);
|
|
@@ -9584,7 +9735,19 @@ function createApp(deps) {
|
|
|
9584
9735
|
});
|
|
9585
9736
|
api.get("/models/:cli", async (c) => {
|
|
9586
9737
|
const cli = CliKindSchema.parse(c.req.param("cli"));
|
|
9587
|
-
return c.json(models === void 0 ? [] : await models.list(cli).
|
|
9738
|
+
return c.json(models === void 0 ? [] : await models.list(cli).then((listed) => listed.models, () => []));
|
|
9739
|
+
});
|
|
9740
|
+
api.get("/agents/:name/models", async (c) => {
|
|
9741
|
+
const agent = await board2.readAgent(c.req.param("name"));
|
|
9742
|
+
if (agent.cli === null) {
|
|
9743
|
+
throw new BoardError("INVALID_STATE", `${agent.name} takes no turns, so it has no models`);
|
|
9744
|
+
}
|
|
9745
|
+
if (models === void 0) {
|
|
9746
|
+
throw new RunnerAwayError("this server asks no runner for models");
|
|
9747
|
+
}
|
|
9748
|
+
const placed = new Map((await board2.listProjects()).map((project) => [project.slug, project.runner]));
|
|
9749
|
+
const prefer = [agent.homeRunner, ...agent.memberships.map((slug) => placed.get(slug))].filter((runner) => runner !== void 0);
|
|
9750
|
+
return c.json(await models.list(agent.cli, prefer));
|
|
9588
9751
|
});
|
|
9589
9752
|
api.put("/roles/:name", async (c) => {
|
|
9590
9753
|
const charter = RoleCharterSchema.parse({
|
|
@@ -9867,26 +10030,42 @@ var EnrollmentDesk = class {
|
|
|
9867
10030
|
// apps/server/dist/models.js
|
|
9868
10031
|
var HOUR = 60 * 6e4;
|
|
9869
10032
|
var ModelCatalog = class {
|
|
9870
|
-
|
|
10033
|
+
runners;
|
|
9871
10034
|
ttlMs;
|
|
9872
10035
|
now;
|
|
9873
10036
|
kept = /* @__PURE__ */ new Map();
|
|
9874
|
-
constructor(
|
|
9875
|
-
this.
|
|
10037
|
+
constructor(runners2, ttlMs = HOUR, now = Date.now) {
|
|
10038
|
+
this.runners = runners2;
|
|
9876
10039
|
this.ttlMs = ttlMs;
|
|
9877
10040
|
this.now = now;
|
|
10041
|
+
runners2.onRunnerChange((runner) => this.forget(runner));
|
|
9878
10042
|
}
|
|
9879
|
-
list(cli) {
|
|
9880
|
-
const
|
|
10043
|
+
async list(cli, prefer = []) {
|
|
10044
|
+
const runner = this.runners.modelRunner(cli, prefer);
|
|
10045
|
+
if (runner === null) {
|
|
10046
|
+
throw new RunnerAwayError(`no connected runner has ${cli}`);
|
|
10047
|
+
}
|
|
10048
|
+
const key = `${runner}/${cli}`;
|
|
10049
|
+
const kept = this.kept.get(key);
|
|
9881
10050
|
if (kept !== void 0 && this.now() - kept.at < this.ttlMs) {
|
|
9882
|
-
return kept.models;
|
|
10051
|
+
return { runner, cli, models: await kept.models };
|
|
9883
10052
|
}
|
|
9884
|
-
const models = this.
|
|
9885
|
-
this.kept.set(
|
|
10053
|
+
const models = this.runners.models(cli, runner);
|
|
10054
|
+
this.kept.set(key, { at: this.now(), models });
|
|
9886
10055
|
models.catch(() => {
|
|
9887
|
-
this.kept.
|
|
10056
|
+
if (this.kept.get(key)?.models === models) {
|
|
10057
|
+
this.kept.delete(key);
|
|
10058
|
+
}
|
|
9888
10059
|
});
|
|
9889
|
-
return models;
|
|
10060
|
+
return { runner, cli, models: await models };
|
|
10061
|
+
}
|
|
10062
|
+
/** Drops every list a runner gave. */
|
|
10063
|
+
forget(runner) {
|
|
10064
|
+
for (const key of this.kept.keys()) {
|
|
10065
|
+
if (key.startsWith(`${runner}/`)) {
|
|
10066
|
+
this.kept.delete(key);
|
|
10067
|
+
}
|
|
10068
|
+
}
|
|
9890
10069
|
}
|
|
9891
10070
|
};
|
|
9892
10071
|
|
|
@@ -9994,7 +10173,7 @@ var app = createApp({
|
|
|
9994
10173
|
version: VERSION,
|
|
9995
10174
|
turns,
|
|
9996
10175
|
scheduler: view,
|
|
9997
|
-
models: new ModelCatalog(
|
|
10176
|
+
models: new ModelCatalog(runners),
|
|
9998
10177
|
runners,
|
|
9999
10178
|
webDir,
|
|
10000
10179
|
signIn: { github: config.github, log },
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{b as e,ln as t,wt as n}from"./format-C7bqWt6N.js";import{L as r,S as i,n as a,r as o,t as s}from"./index-DM00hlle.js";var c=t(),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:t}){let u=n(),d=r({select:e=>e.location.state.__TSR_index}),f=o(),p=i(),m=e(),h=a(f,d);if(h===null)return t;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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{D as e,F as t,Ht as n,R as r,b as i,g as a,ln as o,pn as s,un as c,y as l}from"./format-C7bqWt6N.js";import{I as u,V as d,c as f,i as p}from"./index-DM00hlle.js";import{t as m}from"./MessageItem-CL3XDi7l.js";import{n as h,t as g}from"./Pane-voa6GU0F.js";import{n as _}from"./ThreadCard-CzQXJXSd.js";import{i as v}from"./ThreadForms-0LpUc2jJ.js";import{t as y}from"./useStickyScroll-DCsF4GYJ.js";var b=s(c(),1),x=o();function S(){let{_splat:e=`general`}=d({from:`/c/$`});return(0,x.jsx)(C,{channel:e},e)}function C({channel:o}){let{api:s}=e(),c=n({queryKey:[`channel`,o],queryFn:()=>s.channel(o)}),d=t(),S=a(),C=i(),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=(d.data??[]).filter(e=>e.channel===o).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,d.data,o]),O=c.data?.at(-1)?.id??null;(0,b.useEffect)(()=>u(o,O),[o,O]);let{ref:k,onScroll:A}=y(),[j,M]=o.split(`/`),N=M??j??o,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:o,onDone:()=>E(!1)}):null,(0,x.jsx)(`div`,{ref:k,onScroll:A,className:`flex-1 overflow-y-auto py-2`,children:c.error instanceof r&&c.error.status===404?(0,x.jsxs)(h,{children:[`There is no channel `,o,`.`]}):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:o},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,T as s,_ as c,a as l,cn as u,ct as d,d as f,f as p,g as m,ln as h,o as g,p as _,pn as v,t as y,un as b,w as x,y as S}from"./format-C7bqWt6N.js";import{B as C,H as w,R as T,S as E,T as D,V as ee,_ as te,c as O,f as k,g as ne,h as re,i as ie,m as A,p as j,v as M,x as N,y as P}from"./index-DM00hlle.js";import{t as F}from"./Markdown-CS3NCze-.js";import{n as I,t as ae}from"./Pane-voa6GU0F.js";import{n as oe,r as L}from"./ThreadForms-0LpUc2jJ.js";import{t as se}from"./useStickyScroll-DCsF4GYJ.js";import{a as R,c as ce,i as z,l as B,n as le,o as V,s as ue,t as de}from"./citizen-DvJr6Ibu.js";var H=v(b(),1),U=h(),fe={completed:`completed`,timeout:`timed out`,error:`failed`,interrupted:`was interrupted`,blocked:`was blocked`,stopped:`was stopped by you`};function W(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1})}function G({label:e,tone:t,children:n}){return(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`p`,{className:`px-0.5 pb-0.5 text-[10px] tracking-wider text-fg-muted uppercase`,children:e}),(0,U.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,U.jsx)(`li`,{className:`py-1.5 text-sm`,title:W(e.at),children:(0,U.jsx)(F,{text:e.text})});if(e.kind===`error`)return(0,U.jsx)(`li`,{className:`py-1 font-mono text-xs break-words text-red-400`,title:W(e.at),children:e.message});if(e.kind===`steer`)return(0,U.jsx)(`li`,{children:(0,U.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,U.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,U.jsx)(`span`,{"aria-hidden":`true`,className:`grid w-3 shrink-0 place-items-center text-sky-300`,children:`↳`}),(0,U.jsxs)(`span`,{className:`shrink-0 text-fg-tertiary`,children:[`Took `,re(e.posts.length)]}),(0,U.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,U.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:W(e.at)})]}),(0,U.jsx)(`ul`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:e.posts.map(e=>(0,U.jsxs)(`li`,{className:`rounded-md bg-surface-0/40 px-2.5 py-2`,children:[(0,U.jsxs)(`p`,{className:`flex gap-1.5 text-meta`,children:[(0,U.jsx)(`span`,{className:`text-fg-secondary`,children:e.author}),(0,U.jsxs)(`span`,{className:`min-w-0 truncate`,children:[`in `,e.where]}),e.at===``?null:(0,U.jsx)(`span`,{className:`ml-auto shrink-0 font-mono`,children:W(e.at)})]}),(0,U.jsx)(`div`,{className:`mt-1 text-sm`,children:(0,U.jsx)(F,{text:e.body})})]},`${e.at}-${e.author}`))})]})});let n=e.ok===null?(0,U.jsx)(`span`,{"aria-label":`running`,className:`size-1.5 animate-pulse rounded-full bg-amber-300`}):e.ok?(0,U.jsx)(`span`,{"aria-label":`succeeded`,className:`text-[11px] text-emerald-400`,children:`✓`}):(0,U.jsx)(`span`,{"aria-label":`failed`,className:`text-[11px] text-red-400`,children:`✕`});return(0,U.jsx)(`li`,{children:(0,U.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,U.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,U.jsx)(`span`,{className:`grid w-3 shrink-0 place-items-center`,children:n}),(0,U.jsx)(`span`,{className:`shrink-0 font-mono text-fg-tertiary`,children:ne(e.name)}),(0,U.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-fg-secondary`,children:e.summary}),(0,U.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:W(e.at)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:[(0,U.jsx)(G,{label:`Input`,tone:`text-fg-secondary`,children:e.detail}),e.output===null?null:(0,U.jsx)(G,{label:e.ok===!1?`Returned an error`:`Returned`,tone:e.ok===!1?`text-red-300`:`text-fg-tertiary`,children:e.output})]})]})})}function K({steps:e}){let[t,n]=(0,H.useState)(!1),r=e.filter(e=>e.kind===`tool`).length;return e.length===0?(0,U.jsx)(`p`,{className:`mt-2 text-meta`,children:`No steps yet.`}):(0,U.jsxs)(U.Fragment,{children:[r===0?null:(0,U.jsxs)(`p`,{className:`mt-2 flex items-center gap-2 text-meta`,children:[r===1?`1 tool call`:`${r} tool calls`,(0,U.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,U.jsx)(`ol`,{className:`mt-1 space-y-0.5`,children:e.map(e=>(0,U.jsx)(pe,{step:e,open:t},e.seq))})]})}function me({turn:e,running:t,now:n}){return e.end===null?t?(0,U.jsxs)(`p`,{className:`mt-3 flex items-center gap-2 text-meta`,"aria-live":`polite`,children:[(0,U.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}),`Working · last step `,y(e.lastAt,n)]}):(0,U.jsx)(`p`,{className:`mt-3 text-meta`,children:`The turn ended without a report.`}):(0,U.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,U.jsxs)(`p`,{className:`text-caps`,children:[`The turn `,fe[e.end.exitReason],` `,y(e.end.at,n),e.fromStart?` · ${j(e.startedAt,Date.parse(e.end.at))}`:``]}),e.end.summary===null?null:(0,U.jsx)(`p`,{className:`mt-1 text-sm text-fg-secondary`,children:e.end.summary})]})}var q=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,U.jsxs)(`div`,{children:[(0,U.jsxs)(`p`,{className:`text-xs text-fg-secondary`,children:[e.path,e.status===`modified`?``:(0,U.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,e.status]})]}),e.patch===null?(0,U.jsx)(`p`,{className:`mt-1 text-meta`,children:`A binary file; its contents are not shown.`}):e.patch===``?(0,U.jsx)(`p`,{className:`mt-1 text-meta`,children:`Empty.`}):(0,U.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,U.jsx)(`span`,{className:`block whitespace-pre-wrap break-words ${ye(e)}`,children:e===``?` `:e},t))}),e.truncated?(0,U.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=f(e,t.commit,!0);return(0,U.jsxs)(`div`,{className:`space-y-3 px-4 pt-1 pb-3`,children:[(0,U.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,U.jsx)(T,{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,U.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,W(t.at)]})]}),n.data===void 0?(0,U.jsx)(`p`,{className:`text-meta`,children:n.isError?`Could not read the change.`:`Reading the change…`}):n.data.map(e=>(0,U.jsx)(be,{file:e},e.path))]})}function Se({name:e,change:t,now:n}){let[r,i]=(0,H.useState)(!1),a=t.files.length===0?t.subject:ve(t);return(0,U.jsx)(`li`,{className:`border-b border-line/60 last:border-b-0`,children:(0,U.jsxs)(`details`,{className:`group`,onToggle:e=>i(e.currentTarget.open),children:[(0,U.jsx)(`summary`,{"aria-label":`${ge[t.kind]} ${y(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,U.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,U.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:he[t.kind]}),(0,U.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg-secondary`,children:a}),(0,U.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:y(t.at,n)}),(0,U.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]})}),r?(0,U.jsx)(xe,{name:e,change:t}):null]})})}function Ce({name:e}){let[t,n]=(0,H.useState)(q),r=_(e,t),i=S(3e4);if(r.data===void 0)return(0,U.jsx)(I,{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,U.jsxs)(I,{children:[e,`'s home has no history yet; it starts with the citizen's first turn.`]}):(0,U.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,U.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,U.jsx)(`ol`,{children:a.map(t=>(0,U.jsx)(Se,{name:e,change:t,now:i},t.commit))}),o?(0,U.jsx)(`button`,{type:`button`,onClick:()=>n(t+q),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:`Show earlier changes`}):null]})}function J({title:e,children:t}){return(0,U.jsxs)(`section`,{className:`border-t border-line pt-4 first:border-t-0 first:pt-0`,children:[(0,U.jsx)(`h3`,{className:`text-section`,children:e}),(0,U.jsx)(`div`,{className:`mt-2`,children:t})]})}function we({member:e,charter:t}){let n=c(e.name),r=g(e.name),i=p(e.name),a=S(3e4);return(0,U.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,U.jsxs)(J,{title:`Edits to reconcile`,children:[(0,U.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,U.jsx)(`ul`,{className:`mt-2 space-y-1.5`,children:i.data.map(e=>(0,U.jsxs)(`li`,{className:`text-sm`,children:[(0,U.jsx)(`span`,{className:`text-fg-primary`,children:e.file}),(0,U.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,e.path.slice(e.path.lastIndexOf(`/`)+1),` · left`,` `,y(e.since,a)]})]},e.path))})]}),(0,U.jsx)(J,{title:`Profile`,children:e.profile.trim()===``?(0,U.jsx)(`p`,{className:`text-meta`,children:`No profile yet. The citizen writes its own profile.md.`}):(0,U.jsx)(F,{text:B(e.profile,`Profile`)})}),(0,U.jsx)(J,{title:`Core memory`,children:n.data===void 0?(0,U.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):n.data.body.trim()===``?(0,U.jsx)(`p`,{className:`text-meta`,children:`Empty. Every turn loads this file in full.`}):(0,U.jsx)(F,{text:B(n.data.body,`Core memory`)})}),(0,U.jsx)(J,{title:`Own skills`,children:r.data===void 0?(0,U.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):r.data.length===0?(0,U.jsx)(`p`,{className:`text-meta`,children:`None yet.`}):(0,U.jsx)(`ul`,{className:`space-y-1.5`,children:r.data.map(e=>(0,U.jsxs)(`li`,{className:`text-sm`,children:[(0,U.jsx)(`span`,{className:`text-fg-primary`,children:e.name}),e.summary===``?null:(0,U.jsxs)(`span`,{className:`text-fg-secondary`,children:[` · `,e.summary]})]},e.name))})}),t===void 0?null:(0,U.jsxs)(J,{title:`Charter of ${t.name}`,children:[(0,U.jsx)(`p`,{className:`text-sm text-fg-secondary`,children:t.purpose}),(0,U.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,U.jsx)(`p`,{className:`mt-2 flex flex-wrap gap-1`,children:t.verbs.map(e=>(0,U.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 Te(e,t){let n=r(e,t?.turnId??null);return{turn:(0,H.useMemo)(()=>t===void 0||n.data===void 0?void 0:te(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 Ee({name:e,entry:t,now:n,opened:r}){let[i,a]=(0,H.useState)(r),o=(0,H.useRef)(null);(0,H.useEffect)(()=>{r&&o.current?.scrollIntoView({block:`start`})},[r]);let s=E(),c=ue(t),l=t.thread===void 0?null:s.get(t.thread)?.title??`a thread`,u=t.error??t.summary??``,d=t.error===null?`text-fg-secondary`:`text-red-300`;return(0,U.jsx)(`li`,{ref:o,className:`border-b border-line/60 last:border-b-0`,children:(0,U.jsxs)(`details`,{className:`group`,open:i,onToggle:e=>a(e.currentTarget.open),children:[(0,U.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,U.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,U.jsxs)(`span`,{className:`min-w-0 truncate text-fg-secondary`,children:[z(t.project),l===null?``:` · ${l}`]}),(0,U.jsx)(`span`,{className:`text-fg-muted`,children:t.trigger}),(0,U.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-fg-muted`,children:[de(t),` `,y(t.ts,n)]}),(0,U.jsx)(`span`,{className:`shrink-0 font-mono text-[11px] text-fg-tertiary`,title:t.usage===void 0?void 0:R(t.usage),children:[c,t.toolCalls===void 0?null:`${t.toolCalls} tools`,t.usage===void 0?null:V(t.usage)].filter(e=>e!==null).join(` · `)}),(0,U.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]}),u.trim()===``?null:(0,U.jsx)(`span`,{className:`mt-1 line-clamp-2 block text-xs leading-relaxed group-open:hidden ${d}`,children:(0,U.jsx)(N,{text:u,links:!1})})]}),i?(0,U.jsx)(De,{name:e,entry:t,text:u,tone:d}):null]})})}function De({name:e,entry:t,text:n,tone:r}){let i=Te(e,t);return(0,U.jsxs)(`div`,{className:`px-4 pt-1 pb-3`,children:[n.trim()===``?null:(0,U.jsx)(`p`,{className:`text-xs leading-relaxed whitespace-pre-wrap ${r}`,children:(0,U.jsx)(N,{text:n})}),(0,U.jsx)(`div`,{className:`mt-2`,children:t.turnId===void 0?(0,U.jsx)(`p`,{className:`text-meta`,children:`This turn ran before turns kept their steps.`}):i.loading?(0,U.jsx)(`p`,{className:`text-meta`,children:`Reading the steps…`}):i.turn===void 0?(0,U.jsx)(`p`,{className:`text-meta`,children:`No steps were kept for this turn.`}):(0,U.jsxs)(U.Fragment,{children:[t.startedAt===void 0?null:(0,U.jsxs)(`p`,{className:`text-caps`,children:[`Started `,W(t.startedAt)]}),(0,U.jsx)(K,{steps:i.turn.steps})]})})]})}function Oe({name:e,opened:t}){let[n,r]=(0,H.useState)(Y),a=i(e,n),o=S(3e4);if(a.data===void 0)return(0,U.jsx)(I,{children:`Reading the turns…`});let s=a.data.toReversed();if(s.length===0)return(0,U.jsxs)(I,{children:[e,` has not finished a turn yet.`]});let c=le(s),l=c.usage===null?``:` · ${V(c.usage)}${c.withUsage<c.turns?` over ${c.withUsage} of them`:``}`;return(0,U.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,U.jsxs)(`p`,{className:`px-4 pt-3 pb-1 text-meta`,title:c.usage===null?void 0:R(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,U.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,U.jsx)(`ol`,{children:s.map(n=>(0,U.jsx)(Ee,{name:e,entry:n,now:o,opened:t!==null&&n.turnId===t},n.id))}),a.data.length===n?(0,U.jsxs)(`button`,{type:`button`,onClick:()=>r(n+Y),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:[`Show `,Y,` earlier turns`]}):null]})}function ke(e){return e===void 0?``:`${e.name}${e.id===null?``:` · ${e.id}`}`}function X({label:e,choices:t,value:n,onChange:r,listClassName:i=`inset-x-0`}){let[a,o]=(0,H.useState)(!1),s=(0,H.useRef)(null),c=(0,H.useRef)(null),l=(0,H.useRef)([]),u=t.findIndex(e=>e.value===n);(0,H.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,U.jsxs)(`div`,{ref:s,className:`relative min-w-0 flex-1`,children:[(0,U.jsxs)(`button`,{ref:c,type:`button`,"aria-label":`${e}: ${ke(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,U.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-left`,children:[f?.name,f?.id===null||f===void 0?null:(0,U.jsxs)(`span`,{className:`text-fg-tertiary`,children:[` · `,f.id]})]}),(0,U.jsx)(`span`,{"aria-hidden":`true`,className:`text-[10px] text-fg-muted transition-transform ${a?`rotate-180`:``}`,children:`▾`})]}),a?(0,U.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,U.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,U.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,U.jsxs)(`span`,{className:`block truncate text-xs text-fg-secondary`,children:[e.name,e.id===null?null:(0,U.jsxs)(`span`,{className:`text-fg-tertiary`,children:[` · `,e.id]})]}),e.description===``?null:(0,U.jsx)(`span`,{className:`block truncate text-[11px] text-fg-muted`,children:e.description})]}),(0,U.jsx)(`span`,{"aria-hidden":`true`,className:`w-3 shrink-0 pt-px text-[11px] text-fg-primary`,children:i?`✓`:``})]},e.value)})}):null]})}var Z=``,Q=``;function Ae(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 je(e,t){return[{value:Q,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 Me({member:t,onDone:n}){let{api:r}=e(),i=u(),a=l(t.name),s=t.model??Z,c=t.effort??Q,[d,f]=(0,H.useState)(s),[p,m]=(0,H.useState)(c),h=w({mutationFn:async()=>{d!==s&&await r.setModel(t.name,d===Z?null:d),p!==c&&await r.setEffort(t.name,p===Q?null:p)},onSettled:()=>void i.invalidateQueries({queryKey:[`members`]}),onSuccess:n}),g=a.data?.models??[],_=t.model!==void 0&&!g.some(e=>e.id===t.model)?t.model:null,v=e=>g.find(t=>e===Z?t.isDefault:t.id===e),y=v(d)?.efforts??[],b=p!==Q&&!y.some(e=>e.id===p)?p:null,x=e=>{f(e);let t=v(e)?.efforts??[];p!==Q&&!t.some(e=>e.id===p)&&m(Q)},S=d!==s||p!==c;return(0,U.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(),h.mutate()},children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a.isPending?(0,U.jsxs)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:[`Asking `,t.cli,` for its models…`]}):a.error===null?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(X,{label:`Model`,choices:Ae(g,_),value:d,onChange:x}),y.length===0&&b===null?null:(0,U.jsx)(`div`,{className:`flex w-32 shrink-0`,children:(0,U.jsx)(X,{label:`Effort`,choices:je(v(d),b),value:p,onChange:m,listClassName:`right-0 w-64`})})]}):(0,U.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,U.jsx)(O,{onClick:n,children:`Cancel`}),(0,U.jsx)(O,{variant:`primary`,type:`submit`,disabled:h.isPending||!S||a.error!==null,children:h.isPending?`Saving…`:`Save`})]}),a.data===void 0?null:(0,U.jsxs)(`p`,{className:`text-meta`,children:[`As `,a.data.cli,` on `,a.data.runner,` lists them, where this citizen's turns run.`]}),(0,U.jsx)(L,{error:h.error})]})}var $=``;function Ne(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 Pe(e,t){return[{value:$,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:Ne(e,t)}))]}function Fe({member:t,onDone:n}){let{api:r}=e(),i=u(),a=s(),o=t.homeRunner??$,[c,l]=(0,H.useState)(o),d=w({mutationFn:()=>r.setRunner(t.name,c===$?null:c),onSuccess:()=>{i.invalidateQueries({queryKey:[`members`]}),n()}});return(0,U.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(),d.mutate()},children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a.data===void 0?(0,U.jsx)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:`Reading the runners…`}):(0,U.jsx)(X,{label:`Runner`,choices:Pe(a.data,t),value:c,onChange:l}),(0,U.jsx)(O,{onClick:n,children:`Cancel`}),(0,U.jsx)(O,{variant:`primary`,type:`submit`,disabled:d.isPending||c===o,children:d.isPending?`Saving…`:`Run here`})]}),(0,U.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,U.jsx)(L,{error:d.error})]})}function Ie(e){return e.thread===void 0?{channel:e.channel??(e.scope===`society`?`general`:`${e.scope}/general`)}:{threadId:e.thread}}function Le({name:t,turn:n}){let{api:r}=e(),i=u(),[a,o]=(0,H.useState)(!1),s=w({mutationFn:()=>r.stopTurn(n.turnId),onSuccess:()=>{o(!1),i.invalidateQueries({queryKey:[`scheduler`]})}});return(0,U.jsxs)(`div`,{className:`border-t border-line`,children:[(0,U.jsx)(ie,{target:Ie(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,U.jsxs)(`div`,{className:`flex items-center gap-2 px-3 pb-3`,children:[(0,U.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,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(O,{onClick:()=>{o(!1),s.reset()},children:`Keep it running`}),(0,U.jsx)(O,{variant:`primary`,disabled:s.isPending,onClick:()=>{s.mutate()},children:s.isPending?`Stopping…`:`Stop the turn`})]}):(0,U.jsx)(O,{onClick:()=>o(!0),children:`Stop…`})]}):null,s.error===null?null:(0,U.jsx)(`div`,{className:`px-3 pb-3`,children:(0,U.jsx)(L,{error:s.error})})]})}function Re({member:t,scopes:n,preferred:r,running:i,paused:a,onDone:o}){let{api:s}=e(),c=u(),[l,d]=(0,H.useState)(`manual`),[f,p]=(0,H.useState)(r!==null&&n.includes(r)?r:n[0]??``),[m,h]=(0,H.useState)(``),g=(0,H.useRef)(null);(0,H.useEffect)(()=>g.current?.focus(),[]);let _=w({mutationFn:()=>s.wake({agent:t.name,project:f,kind:l,...m.trim()===``?{}:{reason:m.trim()}}),onSuccess:()=>{c.invalidateQueries({queryKey:[`scheduler`]}),o()}}),v=z(f),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(f)?` ${t.name} is in a turn there now; this one follows it.`:``;return(0,U.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,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsxs)(`fieldset`,{className:`flex gap-1`,children:[(0,U.jsx)(`legend`,{className:`sr-only`,children:`Kind of turn`}),[`manual`,`reflection`].map(e=>(0,U.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,U.jsx)(`input`,{type:`radio`,name:`kind`,value:e,checked:l===e,onChange:()=>d(e),className:`sr-only`}),e===`manual`?`A turn`:`A reflection`]},e))]}),(0,U.jsxs)(`label`,{className:`ml-auto flex items-center gap-2 text-xs text-fg-tertiary`,children:[`at`,(0,U.jsx)(`select`,{value:f,onChange:e=>p(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,U.jsx)(`option`,{value:e,children:z(e)},e))})]})]}),(0,U.jsx)(`textarea`,{ref:g,value:m,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:`${oe} resize-none`}),(0,U.jsxs)(`p`,{className:`text-[11px] leading-relaxed text-fg-muted`,children:[y,b,` Each turn costs money.`]}),(0,U.jsxs)(`div`,{className:`flex items-center justify-end gap-2`,children:[(0,U.jsx)(O,{onClick:o,children:`Cancel`}),(0,U.jsx)(O,{variant:`primary`,type:`submit`,disabled:_.isPending||f===``,children:_.isPending?`Waking…`:l===`reflection`?`Ask for a reflection`:`Wake ${t.name}`})]}),(0,U.jsx)(L,{error:_.error})]})}var ze={working:`bg-emerald-500/15 text-emerald-300`,queued:`bg-amber-500/15 text-amber-300`,idle:`bg-surface-2 text-fg-tertiary`};function Be({project:e,name:t}){let n=(a(e).data??[]).filter(e=>e.status===`claimed`&&e.claimedBy===t);return n.length===0?null:(0,U.jsx)(`ul`,{className:`mt-1.5 space-y-1`,children:n.map(e=>(0,U.jsx)(`li`,{children:(0,U.jsxs)(T,{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,U.jsx)(`span`,{"aria-hidden":`true`,className:`text-fg-muted`,children:`◇`}),(0,U.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.title}),(0,U.jsx)(`span`,{className:`max-w-[40%] shrink-0 truncate font-mono text-[11px] text-fg-muted`,children:d(e)?.name??e.stage})]})},e.id))})}function Ve(){let{name:e}=ee({from:`/citizen/$name`}),{scope:t,tab:n,turn:r}=C({from:`/citizen/$name`});return(0,U.jsx)(Ue,{name:e,chosen:t??null,tab:n??`now`,turn:r??null},e)}var He=[{tab:`now`,label:`Now`},{tab:`turns`,label:`Turns`},{tab:`memory`,label:`Memory`},{tab:`history`,label:`History`}];function Ue({name:e,chosen:r,tab:i,turn:a}){let o=m(),s=x(),c=t(),l=P(),[u,d]=(0,H.useState)(null),f=o.data?.find(t=>t.name===e);if(f===void 0)return(0,U.jsx)(I,{children:o.data===void 0?`Reading the roster…`:`There is no citizen ${e}.`});let p=n(c.data?.running??[]).filter(t=>t.agent===e),h=[...new Set(p.map(e=>e.scope))],g=p.map(e=>A(e.agent,e.scope,e.thread)),_=n(c.data?.pending??[]).find(t=>t.agent===e),v=h.length>0?`working`:_===void 0?`idle`:`queued`,y=M(l,e)[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),E=ce(f),ee=f.status===`active`&&f.cli!==null;return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(ae,{leading:f.cli===null?null:(0,U.jsx)(`span`,{className:`grid size-9 shrink-0 place-items-center rounded-lg bg-surface-2/70`,children:(0,U.jsx)(D,{cli:f.cli,size:20})}),title:e,subtitle:(0,U.jsxs)(U.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,U.jsxs)(U.Fragment,{children:[ee&&u===null?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)(O,{onClick:()=>d(`model`),children:`Model…`}),(0,U.jsx)(O,{onClick:()=>d(`runner`),children:`Runner…`}),(0,U.jsx)(O,{onClick:()=>d(`wake`),children:`Wake…`})]}):null,(0,U.jsx)(`span`,{className:`shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium ${ze[v]}`,children:v})]})}),u===`wake`?(0,U.jsx)(Re,{member:f,scopes:E,preferred:r?.split(`/`)[0]??y?.scope??null,running:h,paused:c.data?.paused??!1,onDone:()=>d(null)}):u===`model`?(0,U.jsx)(Me,{member:f,onDone:()=>d(null)}):u===`runner`?(0,U.jsx)(Fe,{member:f,onDone:()=>d(null)}):null,(0,U.jsx)(`nav`,{"aria-label":`Citizen views`,className:`flex gap-1 border-b border-line px-3 py-2`,children:He.map(t=>(0,U.jsx)(T,{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,U.jsx)(Oe,{name:e,opened:a},a):i===`memory`?(0,U.jsx)(we,{member:f,charter:w}):i===`history`?(0,U.jsx)(Ce,{name:e}):(0,U.jsx)(Ge,{name:e,chosen:r,lastTurnAt:f.lastTurnAt,state:v,runningScopes:h,runningKeys:g,runningTurns:(c.data?.turns??[]).filter(t=>t.agent===e),queuedScope:_?.scope??null})]})}function We(e){return e.toSorted((e,t)=>e.startedAt.localeCompare(t.startedAt))[0]}function Ge({name:e,chosen:t,lastTurnAt:n,state:r,runningScopes:a,runningKeys:o,runningTurns:s,queuedScope:c}){let l=P(),u=S(5e3),{ref:d,onScroll:f}=se(),p=M(l,e),m=i(e,1),h=Te(e,p.length===0?m.data?.at(-1):void 0),g=E(),_=e=>e.end===null&&o.includes(A(e.agent,e.scope,e.thread)),v=t?.split(`/`)[0]??null,b=(t?.includes(`/`)===!0?p.find(e=>k(e)===t):void 0)??We(p.filter(e=>e.scope===v&&_(e)))??p.find(e=>k(e)===t)??We(p.filter(_))??p[0]??h.turn,x=e=>e.thread===void 0?z(e.scope):`${z(e.scope)} · ${g.get(e.thread)?.title??`a thread`}`,C=b!==void 0&&_(b),w=b?.scope??a[0]??c,D=(b===void 0?void 0:s.find(e=>e.scope===b.scope&&e.thread===b.thread))??(C?void 0:s[0]);return(0,U.jsxs)(U.Fragment,{children:[(0,U.jsxs)(`section`,{className:`border-b border-line px-4 py-3 text-xs text-fg-tertiary`,children:[(0,U.jsx)(`p`,{children:C?`In a turn at ${z(b.scope)} for ${b.fromStart?``:`at least `}${j(b.startedAt,u)}`:a.length>0?`In a turn at ${a.map(z).join(` and `)}`:c===null?n===void 0?`No turns yet`:`Last turn ${y(n,u)}`:`Queued for a turn at ${z(c)}`}),w===null||w===`society`?null:(0,U.jsx)(Be,{project:w,name:e})]}),(0,U.jsx)(`div`,{ref:d,onScroll:f,className:`flex-1 overflow-y-auto px-4 py-3`,children:b===void 0?(0,U.jsx)(I,{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,U.jsxs)(U.Fragment,{children:[p.length>1?(0,U.jsx)(`div`,{className:`mb-3 flex flex-wrap gap-1.5`,"aria-label":`Turns by conversation`,children:p.toSorted((e,t)=>k(e).localeCompare(k(t))).map(t=>(0,U.jsxs)(T,{to:`/citizen/$name`,params:{name:e},search:{scope:k(t)},replace:!0,"aria-current":t===b?`true`:void 0,className:`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-[11px] transition-colors ${t===b?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:[_(t)?(0,U.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}):null,x(t)]},k(t)))}):null,(0,U.jsxs)(`p`,{className:`text-caps`,children:[C?`This turn`:`Last turn`,` · `,x(b),` · started`,` `,b.fromStart?W(b.startedAt):`before the earliest step shown`]}),b.fromStart?null:(0,U.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,U.jsx)(K,{steps:b.steps}),(0,U.jsx)(me,{turn:b,running:C,now:u})]})}),D===void 0?null:(0,U.jsx)(Le,{name:e,turn:D})]})}export{Ve as CitizenView};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{E as e,H as t,b as n,g as r,ln as i}from"./format-C7bqWt6N.js";import{R as a,T as o}from"./index-DM00hlle.js";import{n as s,t as c}from"./Pane-voa6GU0F.js";import{i as l,r as u}from"./citizen-DvJr6Ibu.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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{D as e,b as t,cn as n,ln as r,m as i,ot as a,pn as o,t as s,un as c,y as l}from"./format-C7bqWt6N.js";import{H as u,R as d,V as f,c as p,z as m}from"./index-DM00hlle.js";import{t as h}from"./Markdown-CS3NCze-.js";import{n as g,t as _}from"./Pane-voa6GU0F.js";import{r as v}from"./ThreadForms-0LpUc2jJ.js";import{t as y}from"./BackLink-BW0sb-M0.js";var b=o(c(),1),x=r(),S=`grid size-7 shrink-0 place-items-center rounded-lg text-fg-tertiary hover:bg-surface-2/70 hover:text-fg-primary`;function C(){let{scope:r,topic:o}=f({from:`/knowledge/$scope/$topic`}),{api:c}=e(),C=n(),w=m(),T=i(r),E=t(),D=l(3e4),[O,k]=(0,b.useState)(!1),A=r===a,j=A?`the society`:E.data?.find(e=>e.slug===r)?.name??r,M=T.data?.find(e=>e.topic===o),N=u({mutationFn:()=>c.removeKnowledge({project:A?null:r,topic:o}),onSuccess:async()=>{await C.invalidateQueries({queryKey:[`knowledge`,r]}),await w(A?{to:`/society`}:{to:`/p/$slug`,params:{slug:r}})}}),P=A?(0,x.jsx)(d,{to:`/society`,"aria-label":`Back to the society`,className:S,children:`←`}):(0,x.jsx)(d,{to:`/p/$slug`,params:{slug:r},"aria-label":`Back to ${j}`,className:S,children:`←`});return M===void 0?(0,x.jsx)(g,{children:T.data===void 0?`Reading…`:`${j} has no topic ${o}.`}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(_,{leading:(0,x.jsx)(y,{fallback:P}),title:M.topic,subtitle:`Knowledge of ${j} · written by ${M.updatedBy} ${s(M.updatedAt,D)}`,trailing:O?null:(0,x.jsx)(p,{onClick:()=>k(!0),children:`Remove…`})}),O?(0,x.jsxs)(`form`,{"aria-label":`Remove the topic`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),N.mutate()},children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,x.jsxs)(`p`,{className:`min-w-0 flex-1 text-meta`,children:[`No turn or search finds `,M.topic,` again, and a note in`,` `,A?`#general`:`#${r}/general`,` says so without waking anyone. The server keeps its text aside.`]}),(0,x.jsx)(p,{onClick:()=>k(!1),children:`Cancel`}),(0,x.jsx)(p,{variant:`primary`,type:`submit`,disabled:N.isPending,children:N.isPending?`Removing…`:`Remove topic`})]}),(0,x.jsx)(v,{error:N.error})]}):null,(0,x.jsx)(`div`,{className:`flex-1 overflow-y-auto px-4 py-4`,children:(0,x.jsx)(h,{text:M.body})})]})}export{C as KnowledgeView};
|