@kubitnodes/stellaris 0.3.17 → 0.3.18
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 +87 -27
- package/dist/server/index.js +59 -7
- package/package.json +1 -1
- package/web/dist/assets/BackLink-DUOMS3fv.js +1 -0
- package/web/dist/assets/{ChannelForms-B3XwkJj_.js → ChannelForms-DfG4vYvk.js} +1 -1
- package/web/dist/assets/{ChannelView-B3qNylz5.js → ChannelView-DTLhLXy4.js} +2 -2
- package/web/dist/assets/{CitizenView-BUeC52q2.js → CitizenView-q24CExsI.js} +2 -2
- package/web/dist/assets/{CitizensView-BSWYcQ-Q.js → CitizensView-bKbUaCab.js} +1 -1
- package/web/dist/assets/{CliIcon-CFObB9XW.js → CliIcon-DTVk0pGU.js} +1 -1
- package/web/dist/assets/{CronsView-BBIx84f7.js → CronsView-DaG1xhQu.js} +1 -1
- package/web/dist/assets/{KnowledgeView-C8r5hAa_.js → KnowledgeView-Dt7wE3FT.js} +1 -1
- package/web/dist/assets/{Markdown-BO_bF8WD.js → Markdown-DeF9PKNm.js} +4 -4
- package/web/dist/assets/{MessageItem-BkDlfhQC.js → MessageItem-DDs7m3-4.js} +1 -1
- package/web/dist/assets/MetricsView-Bw7nL6Y9.js +1 -0
- package/web/dist/assets/NeedsYouView-DbESNtQT.js +1 -0
- package/web/dist/assets/Overview-Dv7SS4yW.js +1 -0
- package/web/dist/assets/{Pane-DHXhVwfI.js → Pane-v044FaP5.js} +1 -1
- package/web/dist/assets/{Picker-CQQ7hj8T.js → Picker-wWsO86nu.js} +1 -1
- package/web/dist/assets/ProjectView--nzlqSDA.js +1 -0
- package/web/dist/assets/ProposalView-Cdw_xzG1.js +1 -0
- package/web/dist/assets/{ProposalsView-BJg4ZsTy.js → ProposalsView-dVA50yG1.js} +1 -1
- package/web/dist/assets/{RunnersView-DOW8xq-J.js → RunnersView-C-l5QYIa.js} +1 -1
- package/web/dist/assets/SocietyView--mWRXRj_.js +1 -0
- package/web/dist/assets/{SubjectThread-Do5As1cO.js → SubjectThread-DvvsxHN9.js} +1 -1
- package/web/dist/assets/TaskFileView-DYuPrCdk.js +4 -0
- package/web/dist/assets/{TaskView-q6Kn30K7.js → TaskView-BgJcOmGj.js} +2 -2
- package/web/dist/assets/{TasksView-CT9Cui_C.js → TasksView-f8KIsif_.js} +1 -1
- package/web/dist/assets/ThreadCard-BRLvjdz3.js +1 -0
- package/web/dist/assets/ThreadForms-CXsunS-N.js +1 -0
- package/web/dist/assets/{ThreadView-BZ2nKfyD.js → ThreadView-DzpaXkik.js} +1 -1
- package/web/dist/assets/{citizen-DFaT61S1.js → citizen-VtLNxjtf.js} +1 -1
- package/web/dist/assets/compose-D-SO-HE-.js +1 -0
- package/web/dist/assets/{format-Cp_C4ygr.js → format-CkySAdH1.js} +1 -1
- package/web/dist/assets/{governance-BbogC_X-.js → governance-1UeTD2K_.js} +1 -1
- package/web/dist/assets/index-CwkK8XtJ.js +23 -0
- package/web/dist/assets/{index-BoTts74M.css → index-DaES0xVj.css} +1 -1
- package/web/dist/assets/{link-DIpiSYJj.js → link-BN04dcBX.js} +1 -1
- package/web/dist/assets/{tasks-C1wf85BJ.js → tasks-CD70eybR.js} +1 -1
- package/web/dist/assets/useMatch-i33QT_GI.js +1 -0
- package/web/dist/assets/{useStickyScroll-7ZZcyLI0.js → useStickyScroll-WSVpAMrA.js} +1 -1
- package/web/dist/index.html +9 -9
- package/web/dist/assets/BackLink-CssfJ-vJ.js +0 -1
- package/web/dist/assets/MetricsView-DqAQ4th0.js +0 -1
- package/web/dist/assets/NeedsYouView-D2Z-iLdT.js +0 -1
- package/web/dist/assets/Overview-DThLwb0l.js +0 -1
- package/web/dist/assets/ProjectView-DOtPYF6z.js +0 -1
- package/web/dist/assets/ProposalView-BpeiCg46.js +0 -1
- package/web/dist/assets/SocietyView-CbIpCGhP.js +0 -1
- package/web/dist/assets/TaskFileView-CPwEmR6p.js +0 -4
- package/web/dist/assets/ThreadCard-DsIkg4Br.js +0 -1
- package/web/dist/assets/ThreadForms-BPowHd4M.js +0 -1
- package/web/dist/assets/compose-96HAETM2.js +0 -1
- package/web/dist/assets/index-BXHV32GA.js +0 -23
- package/web/dist/assets/useMatch-DYOY33wl.js +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -63,7 +63,8 @@ var VERB_NAMES = [
|
|
|
63
63
|
"update_dashboard",
|
|
64
64
|
"create_cron",
|
|
65
65
|
"update_cron",
|
|
66
|
-
"remove_cron"
|
|
66
|
+
"remove_cron",
|
|
67
|
+
"remove_skill"
|
|
67
68
|
];
|
|
68
69
|
var VerbNameSchema = z2.enum(VERB_NAMES);
|
|
69
70
|
var CharterTriggerSchema = z2.enum(["user_post", "ops_event", "heartbeat"]);
|
|
@@ -123,6 +124,7 @@ var PLANNING_VERBS = [
|
|
|
123
124
|
"archive_channel"
|
|
124
125
|
];
|
|
125
126
|
var ARCHIVE_VERBS = ["archive_project"];
|
|
127
|
+
var CURATING_VERBS = ["remove_skill"];
|
|
126
128
|
var SEED_ROLES = [
|
|
127
129
|
{
|
|
128
130
|
name: USER_ROLE,
|
|
@@ -132,7 +134,8 @@ var SEED_ROLES = [
|
|
|
132
134
|
...GOVERNANCE_VERBS,
|
|
133
135
|
...FRONT_DESK_VERBS,
|
|
134
136
|
...PLANNING_VERBS,
|
|
135
|
-
...ARCHIVE_VERBS
|
|
137
|
+
...ARCHIVE_VERBS,
|
|
138
|
+
...CURATING_VERBS
|
|
136
139
|
],
|
|
137
140
|
wakeTriggers: [],
|
|
138
141
|
maxReplicas: 1,
|
|
@@ -144,7 +147,7 @@ var SEED_ROLES = [
|
|
|
144
147
|
{
|
|
145
148
|
name: "steward",
|
|
146
149
|
purpose: "Watches the operations signals and the task board for capacity, skill, and capability gaps, and turns signals into proposals: a member when a project's plans need a role nobody fills or a backlog persists, a role when a project's work needs one no existing role covers, a retirement when a member has been idle for a long time. Opens a channel with create_channel when a topic or a workstream needs one, and archives it once its work is done. Owns how work is shaped over time: answers stages waiting too long, stages assigned to roles nobody fills, and work sent back again and again by replanning with plan_task, adjusting gates, or proposing the role a plan needs; sets each project's completion effect with configure_project; turns recurring plan shapes into society skills and planning norms into the society's norms. Prefers scaling an existing role over inventing a new one. Never approves its own proposals; hiring, roles, and retirements are decided by the user, and channels, reallocations, and skills the steward may decide. Curates society knowledge and skills.",
|
|
147
|
-
verbs: [...MEMBER_VERBS, ...GOVERNANCE_VERBS, ...PLANNING_VERBS],
|
|
150
|
+
verbs: [...MEMBER_VERBS, ...GOVERNANCE_VERBS, ...PLANNING_VERBS, ...CURATING_VERBS],
|
|
148
151
|
wakeTriggers: ["ops_event", "heartbeat"],
|
|
149
152
|
maxReplicas: 1,
|
|
150
153
|
backlogThreshold: 3,
|
|
@@ -697,6 +700,12 @@ var SkillSchema = z4.object({
|
|
|
697
700
|
scope: z4.enum(["own", "society"]),
|
|
698
701
|
path: z4.string().min(1)
|
|
699
702
|
});
|
|
703
|
+
var RemovedSkillSchema = z4.object({
|
|
704
|
+
name: NameSchema,
|
|
705
|
+
reason: z4.string().min(1),
|
|
706
|
+
removedBy: NameSchema,
|
|
707
|
+
removedAt: IsoDateTimeSchema
|
|
708
|
+
});
|
|
700
709
|
var HomeConflictSchema = z4.object({
|
|
701
710
|
/** The copy, relative to the home. */
|
|
702
711
|
path: z4.string().min(1),
|
|
@@ -940,7 +949,8 @@ var VerbInputs = {
|
|
|
940
949
|
timezone: TimeZoneSchema.nullable().optional(),
|
|
941
950
|
at: MomentSchema.optional()
|
|
942
951
|
}),
|
|
943
|
-
remove_cron: z5.object({ cron_id: UlidSchema, reason: z5.string().trim().min(1) })
|
|
952
|
+
remove_cron: z5.object({ cron_id: UlidSchema, reason: z5.string().trim().min(1) }),
|
|
953
|
+
remove_skill: z5.object({ name: NameSchema, reason: z5.string().trim().min(1) })
|
|
944
954
|
};
|
|
945
955
|
|
|
946
956
|
// packages/shared/dist/events.js
|
|
@@ -982,6 +992,7 @@ var BOARD_EVENT_TYPES = [
|
|
|
982
992
|
"knowledge.removed",
|
|
983
993
|
"dashboard.updated",
|
|
984
994
|
"skill.promoted",
|
|
995
|
+
"skill.removed",
|
|
985
996
|
"runner.added",
|
|
986
997
|
"user.signed_in",
|
|
987
998
|
"user.signed_out",
|
|
@@ -1695,7 +1706,7 @@ var RunnerConfigSchema = z11.object({
|
|
|
1695
1706
|
});
|
|
1696
1707
|
|
|
1697
1708
|
// packages/shared/dist/version.js
|
|
1698
|
-
var STELLARIS_VERSION = "0.3.
|
|
1709
|
+
var STELLARIS_VERSION = "0.3.18";
|
|
1699
1710
|
|
|
1700
1711
|
// packages/board-core/dist/errors.js
|
|
1701
1712
|
var BoardError = class extends Error {
|
|
@@ -2717,11 +2728,11 @@ var BoardPaths = class {
|
|
|
2717
2728
|
agentSkills(name) {
|
|
2718
2729
|
return path5.join(this.agent(name), "skills");
|
|
2719
2730
|
}
|
|
2720
|
-
agentSkill(name,
|
|
2721
|
-
return path5.join(this.agentSkills(name),
|
|
2731
|
+
agentSkill(name, skill2) {
|
|
2732
|
+
return path5.join(this.agentSkills(name), skill2);
|
|
2722
2733
|
}
|
|
2723
|
-
agentSkillFile(name,
|
|
2724
|
-
return path5.join(this.agentSkill(name,
|
|
2734
|
+
agentSkillFile(name, skill2) {
|
|
2735
|
+
return path5.join(this.agentSkill(name, skill2), "SKILL.md");
|
|
2725
2736
|
}
|
|
2726
2737
|
agentProjects(name) {
|
|
2727
2738
|
return path5.join(this.agent(name), "projects");
|
|
@@ -2755,6 +2766,10 @@ var BoardPaths = class {
|
|
|
2755
2766
|
removedKnowledge(scope) {
|
|
2756
2767
|
return path5.join(this.state(), "removed-knowledge", scope);
|
|
2757
2768
|
}
|
|
2769
|
+
/** Skills removed from the society, set aside outside the projection, one directory per removal. */
|
|
2770
|
+
removedSkills() {
|
|
2771
|
+
return path5.join(this.state(), "removed-skills");
|
|
2772
|
+
}
|
|
2758
2773
|
};
|
|
2759
2774
|
|
|
2760
2775
|
// packages/board-core/dist/tokens.js
|
|
@@ -4476,11 +4491,11 @@ ${task2.body}`;
|
|
|
4476
4491
|
file: path6.join(this.paths.societyKnowledge(), file)
|
|
4477
4492
|
});
|
|
4478
4493
|
}
|
|
4479
|
-
for (const
|
|
4480
|
-
shared.push({ kind: "skill", ref: `society/skills/${
|
|
4494
|
+
for (const skill2 of await this.listSocietySkills()) {
|
|
4495
|
+
shared.push({ kind: "skill", ref: `society/skills/${skill2.name}`, file: skill2.path });
|
|
4481
4496
|
}
|
|
4482
|
-
for (const
|
|
4483
|
-
shared.push({ kind: "skill", ref: `skills/${
|
|
4497
|
+
for (const skill2 of await this.listAgentSkills(actor.name)) {
|
|
4498
|
+
shared.push({ kind: "skill", ref: `skills/${skill2.name}`, file: skill2.path });
|
|
4484
4499
|
}
|
|
4485
4500
|
for (const file of await listFiles(this.paths.agentMemory(actor.name))) {
|
|
4486
4501
|
shared.push({
|
|
@@ -4583,6 +4598,40 @@ ${task2.body}`;
|
|
|
4583
4598
|
throw new BoardError("FORBIDDEN", `${actor.name} is not a member of ${project2}`);
|
|
4584
4599
|
}
|
|
4585
4600
|
}
|
|
4601
|
+
/**
|
|
4602
|
+
* Takes a skill out of the society's skills, by the steward or the user. Its directory leaves
|
|
4603
|
+
* the projection, so no skills index or search lists it from the next turn, and is set aside
|
|
4604
|
+
* under `state/removed-skills` for the user to restore by hand. The notice is the board's, as a
|
|
4605
|
+
* promotion's is, so a removal by the user wakes no front desk, and quotes the reason without
|
|
4606
|
+
* its mentions. The proposer's own copy in its home is not touched.
|
|
4607
|
+
*/
|
|
4608
|
+
async removeSkill(actor, input) {
|
|
4609
|
+
const args = VerbInputs.remove_skill.parse(input);
|
|
4610
|
+
await this.authorize(actor, "remove_skill");
|
|
4611
|
+
if (!CURATING_ROLES.includes(actor.role)) {
|
|
4612
|
+
throw new BoardError("FORBIDDEN", "the society's skills are curated by the steward and the user");
|
|
4613
|
+
}
|
|
4614
|
+
return this.mutex.run(async () => {
|
|
4615
|
+
if (!await exists(this.paths.societySkillFile(args.name))) {
|
|
4616
|
+
throw new BoardError("NOT_FOUND", `the society has no skill ${args.name}`);
|
|
4617
|
+
}
|
|
4618
|
+
const removed = RemovedSkillSchema.parse({
|
|
4619
|
+
name: args.name,
|
|
4620
|
+
reason: args.reason,
|
|
4621
|
+
removedBy: actor.name,
|
|
4622
|
+
removedAt: this.now().toISOString()
|
|
4623
|
+
});
|
|
4624
|
+
const aside = this.paths.removedSkills();
|
|
4625
|
+
await mkdir4(aside, { recursive: true });
|
|
4626
|
+
await rename3(this.paths.societySkill(args.name), path6.join(aside, `${args.name}.${removed.removedAt.replaceAll(":", "-")}`));
|
|
4627
|
+
await this.events.append("skill.removed", actor.name, {
|
|
4628
|
+
name: args.name,
|
|
4629
|
+
reason: args.reason
|
|
4630
|
+
});
|
|
4631
|
+
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${args.name} removed from the society by ${actor.name}: ${sentence(withoutMentions(args.reason))}. Every citizen's skills index stops listing it from its next turn.`);
|
|
4632
|
+
return removed;
|
|
4633
|
+
});
|
|
4634
|
+
}
|
|
4586
4635
|
/**
|
|
4587
4636
|
* Replaces a project's dashboard, by a member or the user. A turn reads the dashboard from the
|
|
4588
4637
|
* copy of the projection pulled when it started, so a revision other than the current one means
|
|
@@ -5805,6 +5854,8 @@ ${rationale}`}`);
|
|
|
5805
5854
|
return this.writeKnowledge(actor, VerbInputs.write_knowledge.parse(input));
|
|
5806
5855
|
case "remove_knowledge":
|
|
5807
5856
|
return this.removeKnowledge(actor, VerbInputs.remove_knowledge.parse(input));
|
|
5857
|
+
case "remove_skill":
|
|
5858
|
+
return this.removeSkill(actor, VerbInputs.remove_skill.parse(input));
|
|
5808
5859
|
case "plan_task":
|
|
5809
5860
|
return this.planTask(actor, VerbInputs.plan_task.parse(input));
|
|
5810
5861
|
case "advance_task":
|
|
@@ -6648,7 +6699,7 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
6648
6699
|
...agent2.model === void 0 ? {} : { model: agent2.model },
|
|
6649
6700
|
...lastModel === void 0 ? {} : { lastModel },
|
|
6650
6701
|
...agent2.effort === void 0 ? {} : { effort: agent2.effort },
|
|
6651
|
-
skills: (await this.listAgentSkills(name)).map((
|
|
6702
|
+
skills: (await this.listAgentSkills(name)).map((skill2) => skill2.name),
|
|
6652
6703
|
memberships: agent2.memberships,
|
|
6653
6704
|
subscriptions: agent2.subscriptions,
|
|
6654
6705
|
claimsHeld,
|
|
@@ -6797,9 +6848,9 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
6797
6848
|
return { agent: agent2.name, releasedTasks };
|
|
6798
6849
|
}
|
|
6799
6850
|
case "skill": {
|
|
6800
|
-
const
|
|
6801
|
-
const replaced = await this.promoteSkillUnlocked(by, proposal2.proposedBy,
|
|
6802
|
-
return { skill:
|
|
6851
|
+
const skill2 = SkillProposalSchema.parse(proposal2.charter);
|
|
6852
|
+
const replaced = await this.promoteSkillUnlocked(by, proposal2.proposedBy, skill2, meta);
|
|
6853
|
+
return { skill: skill2.name, replaced };
|
|
6803
6854
|
}
|
|
6804
6855
|
case "archive": {
|
|
6805
6856
|
const input = ArchiveProposalSchema.parse(proposal2.charter);
|
|
@@ -6813,23 +6864,23 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
6813
6864
|
}
|
|
6814
6865
|
}
|
|
6815
6866
|
/** Writes a promoted skill under the society's skills, where every citizen's skills index lists it. */
|
|
6816
|
-
async promoteSkillUnlocked(by, proposedBy,
|
|
6817
|
-
const file = this.paths.societySkillFile(
|
|
6867
|
+
async promoteSkillUnlocked(by, proposedBy, skill2, meta) {
|
|
6868
|
+
const file = this.paths.societySkillFile(skill2.name);
|
|
6818
6869
|
const replaced = await exists(file);
|
|
6819
|
-
await ensureDir(this.paths.societySkill(
|
|
6870
|
+
await ensureDir(this.paths.societySkill(skill2.name));
|
|
6820
6871
|
await writeMarkdown(file, {
|
|
6821
|
-
name:
|
|
6822
|
-
description:
|
|
6872
|
+
name: skill2.name,
|
|
6873
|
+
description: skill2.summary,
|
|
6823
6874
|
metadata: { proposedBy, promotedBy: by, promotedAt: this.now().toISOString() }
|
|
6824
|
-
},
|
|
6875
|
+
}, skill2.body);
|
|
6825
6876
|
await this.events.append("skill.promoted", by, {
|
|
6826
|
-
name:
|
|
6827
|
-
summary:
|
|
6877
|
+
name: skill2.name,
|
|
6878
|
+
summary: skill2.summary,
|
|
6828
6879
|
proposedBy,
|
|
6829
6880
|
replaced,
|
|
6830
6881
|
...meta
|
|
6831
6882
|
});
|
|
6832
|
-
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${
|
|
6883
|
+
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${skill2.name} ${replaced ? "updated in" : "promoted to"} the society: ${sentence(skill2.summary)}. Every citizen's skills index now lists it.`);
|
|
6833
6884
|
return replaced;
|
|
6834
6885
|
}
|
|
6835
6886
|
async validateAddAgent(input) {
|
|
@@ -8008,7 +8059,8 @@ knowledge.command("write <topic>").description("Write a knowledge topic as the u
|
|
|
8008
8059
|
});
|
|
8009
8060
|
print(written, () => `Wrote ${written.topic} for ${written.project ?? "the society"}`);
|
|
8010
8061
|
});
|
|
8011
|
-
program.command("skill").description("Skills promoted to the society")
|
|
8062
|
+
var skill = program.command("skill").description("Skills promoted to the society");
|
|
8063
|
+
skill.command("list").description("List the society's skills, and each member's own").action(async () => {
|
|
8012
8064
|
const board = await open();
|
|
8013
8065
|
const society = await board.listSocietySkills();
|
|
8014
8066
|
const own = [];
|
|
@@ -8023,6 +8075,14 @@ program.command("skill").description("Skills promoted to the society").command("
|
|
|
8023
8075
|
...own.flatMap(({ agent: name, skills }) => skills.map((s) => `${name} ${s.name} ${s.summary}`))
|
|
8024
8076
|
].join("\n") || "No skills yet.");
|
|
8025
8077
|
});
|
|
8078
|
+
skill.command("remove <name>").description("Remove a skill from the society's skills; its text is set aside, not destroyed").requiredOption("--reason <text>", "why it is wrong, superseded, or no longer used").option("--as <agent>", "act as this agent instead of the user").action(async (name, opts) => {
|
|
8079
|
+
const board = await open();
|
|
8080
|
+
const removed = await board.removeSkill(await actorFor(board, opts.as), {
|
|
8081
|
+
name,
|
|
8082
|
+
reason: opts.reason
|
|
8083
|
+
});
|
|
8084
|
+
print(removed, () => `Removed ${removed.name} from the society's skills: ${removed.reason}`);
|
|
8085
|
+
});
|
|
8026
8086
|
var turn = program.command("turn").description("Turn operations");
|
|
8027
8087
|
turn.command("digest <agent>").description("Show the unread messages the agent's next turn opens with, in one scope or all; the cursors stay put").option("--limit <n>", "maximum messages", "50").option("--project <slug>", "the scope whose turn to show: a project, or society").action(async (agentName, opts) => {
|
|
8028
8088
|
const board = await open();
|
package/dist/server/index.js
CHANGED
|
@@ -63,7 +63,8 @@ var VERB_NAMES = [
|
|
|
63
63
|
"update_dashboard",
|
|
64
64
|
"create_cron",
|
|
65
65
|
"update_cron",
|
|
66
|
-
"remove_cron"
|
|
66
|
+
"remove_cron",
|
|
67
|
+
"remove_skill"
|
|
67
68
|
];
|
|
68
69
|
var VerbNameSchema = z2.enum(VERB_NAMES);
|
|
69
70
|
var CharterTriggerSchema = z2.enum(["user_post", "ops_event", "heartbeat"]);
|
|
@@ -123,6 +124,7 @@ var PLANNING_VERBS = [
|
|
|
123
124
|
"archive_channel"
|
|
124
125
|
];
|
|
125
126
|
var ARCHIVE_VERBS = ["archive_project"];
|
|
127
|
+
var CURATING_VERBS = ["remove_skill"];
|
|
126
128
|
var SEED_ROLES = [
|
|
127
129
|
{
|
|
128
130
|
name: USER_ROLE,
|
|
@@ -132,7 +134,8 @@ var SEED_ROLES = [
|
|
|
132
134
|
...GOVERNANCE_VERBS,
|
|
133
135
|
...FRONT_DESK_VERBS,
|
|
134
136
|
...PLANNING_VERBS,
|
|
135
|
-
...ARCHIVE_VERBS
|
|
137
|
+
...ARCHIVE_VERBS,
|
|
138
|
+
...CURATING_VERBS
|
|
136
139
|
],
|
|
137
140
|
wakeTriggers: [],
|
|
138
141
|
maxReplicas: 1,
|
|
@@ -144,7 +147,7 @@ var SEED_ROLES = [
|
|
|
144
147
|
{
|
|
145
148
|
name: "steward",
|
|
146
149
|
purpose: "Watches the operations signals and the task board for capacity, skill, and capability gaps, and turns signals into proposals: a member when a project's plans need a role nobody fills or a backlog persists, a role when a project's work needs one no existing role covers, a retirement when a member has been idle for a long time. Opens a channel with create_channel when a topic or a workstream needs one, and archives it once its work is done. Owns how work is shaped over time: answers stages waiting too long, stages assigned to roles nobody fills, and work sent back again and again by replanning with plan_task, adjusting gates, or proposing the role a plan needs; sets each project's completion effect with configure_project; turns recurring plan shapes into society skills and planning norms into the society's norms. Prefers scaling an existing role over inventing a new one. Never approves its own proposals; hiring, roles, and retirements are decided by the user, and channels, reallocations, and skills the steward may decide. Curates society knowledge and skills.",
|
|
147
|
-
verbs: [...MEMBER_VERBS, ...GOVERNANCE_VERBS, ...PLANNING_VERBS],
|
|
150
|
+
verbs: [...MEMBER_VERBS, ...GOVERNANCE_VERBS, ...PLANNING_VERBS, ...CURATING_VERBS],
|
|
148
151
|
wakeTriggers: ["ops_event", "heartbeat"],
|
|
149
152
|
maxReplicas: 1,
|
|
150
153
|
backlogThreshold: 3,
|
|
@@ -712,6 +715,12 @@ var SkillSchema = z4.object({
|
|
|
712
715
|
scope: z4.enum(["own", "society"]),
|
|
713
716
|
path: z4.string().min(1)
|
|
714
717
|
});
|
|
718
|
+
var RemovedSkillSchema = z4.object({
|
|
719
|
+
name: NameSchema,
|
|
720
|
+
reason: z4.string().min(1),
|
|
721
|
+
removedBy: NameSchema,
|
|
722
|
+
removedAt: IsoDateTimeSchema
|
|
723
|
+
});
|
|
715
724
|
var HomeConflictSchema = z4.object({
|
|
716
725
|
/** The copy, relative to the home. */
|
|
717
726
|
path: z4.string().min(1),
|
|
@@ -955,7 +964,8 @@ var VerbInputs = {
|
|
|
955
964
|
timezone: TimeZoneSchema.nullable().optional(),
|
|
956
965
|
at: MomentSchema.optional()
|
|
957
966
|
}),
|
|
958
|
-
remove_cron: z5.object({ cron_id: UlidSchema, reason: z5.string().trim().min(1) })
|
|
967
|
+
remove_cron: z5.object({ cron_id: UlidSchema, reason: z5.string().trim().min(1) }),
|
|
968
|
+
remove_skill: z5.object({ name: NameSchema, reason: z5.string().trim().min(1) })
|
|
959
969
|
};
|
|
960
970
|
var VERB_DESCRIPTIONS = {
|
|
961
971
|
post_message: "Post a markdown message to a channel, or into a thread when thread_id is given; a thread's message goes to the thread's channel.",
|
|
@@ -987,7 +997,8 @@ var VERB_DESCRIPTIONS = {
|
|
|
987
997
|
update_dashboard: "Replace the dashboard of a project you are a member of, the status page the user reads on its view, with a whole markdown body. Pass the revision from the frontmatter of the dashboard you read; if it was updated since, the call is refused with the current text to merge yours into. dashboard.md in the board projection is a copy, so editing it changes nothing.",
|
|
988
998
|
create_cron: "Set a cron that wakes you later: a title, a note on what to do then, and either cron, a five-field expression (minute hour day-of-month month day-of-week) read in timezone or the society's, or at, one time. It fires in this turn's conversation unless you name a project, thread_id, or channel, at most every 15 minutes, and every fire is a turn. Only the user, the steward, and the concierge set one that wakes another citizen (agent).",
|
|
989
999
|
update_cron: "Pause or resume a cron, or change its title, note, or schedule; resuming or rescheduling starts it afresh from now. Yours, or anyone's for the user, the steward, and the concierge.",
|
|
990
|
-
remove_cron: "End a cron for good, with a reason. Yours, or anyone's for the user, the steward, and the concierge. A cron also ends with its conversation, and a one-time cron once it fires."
|
|
1000
|
+
remove_cron: "End a cron for good, with a reason. Yours, or anyone's for the user, the steward, and the concierge. A cron also ends with its conversation, and a one-time cron once it fires.",
|
|
1001
|
+
remove_skill: "Remove a skill from the society's skills, with a reason, when it is wrong, superseded, or no longer used: no skills index lists it from the next turn, and a notice in general says so with the reason. Its proposer's own copy stays in its home. Steward and user only; the board keeps its text aside for the user to restore."
|
|
991
1002
|
};
|
|
992
1003
|
|
|
993
1004
|
// packages/shared/dist/events.js
|
|
@@ -1029,6 +1040,7 @@ var BOARD_EVENT_TYPES = [
|
|
|
1029
1040
|
"knowledge.removed",
|
|
1030
1041
|
"dashboard.updated",
|
|
1031
1042
|
"skill.promoted",
|
|
1043
|
+
"skill.removed",
|
|
1032
1044
|
"runner.added",
|
|
1033
1045
|
"user.signed_in",
|
|
1034
1046
|
"user.signed_out",
|
|
@@ -1822,7 +1834,7 @@ var RunnerConfigSchema = z11.object({
|
|
|
1822
1834
|
});
|
|
1823
1835
|
|
|
1824
1836
|
// packages/shared/dist/version.js
|
|
1825
|
-
var STELLARIS_VERSION = "0.3.
|
|
1837
|
+
var STELLARIS_VERSION = "0.3.18";
|
|
1826
1838
|
|
|
1827
1839
|
// packages/board-core/dist/errors.js
|
|
1828
1840
|
var BoardError = class extends Error {
|
|
@@ -2885,6 +2897,10 @@ var BoardPaths = class {
|
|
|
2885
2897
|
removedKnowledge(scope) {
|
|
2886
2898
|
return path5.join(this.state(), "removed-knowledge", scope);
|
|
2887
2899
|
}
|
|
2900
|
+
/** Skills removed from the society, set aside outside the projection, one directory per removal. */
|
|
2901
|
+
removedSkills() {
|
|
2902
|
+
return path5.join(this.state(), "removed-skills");
|
|
2903
|
+
}
|
|
2888
2904
|
};
|
|
2889
2905
|
|
|
2890
2906
|
// packages/board-core/dist/tokens.js
|
|
@@ -4713,6 +4729,40 @@ ${task.body}`;
|
|
|
4713
4729
|
throw new BoardError("FORBIDDEN", `${actor.name} is not a member of ${project}`);
|
|
4714
4730
|
}
|
|
4715
4731
|
}
|
|
4732
|
+
/**
|
|
4733
|
+
* Takes a skill out of the society's skills, by the steward or the user. Its directory leaves
|
|
4734
|
+
* the projection, so no skills index or search lists it from the next turn, and is set aside
|
|
4735
|
+
* under `state/removed-skills` for the user to restore by hand. The notice is the board's, as a
|
|
4736
|
+
* promotion's is, so a removal by the user wakes no front desk, and quotes the reason without
|
|
4737
|
+
* its mentions. The proposer's own copy in its home is not touched.
|
|
4738
|
+
*/
|
|
4739
|
+
async removeSkill(actor, input) {
|
|
4740
|
+
const args = VerbInputs.remove_skill.parse(input);
|
|
4741
|
+
await this.authorize(actor, "remove_skill");
|
|
4742
|
+
if (!CURATING_ROLES.includes(actor.role)) {
|
|
4743
|
+
throw new BoardError("FORBIDDEN", "the society's skills are curated by the steward and the user");
|
|
4744
|
+
}
|
|
4745
|
+
return this.mutex.run(async () => {
|
|
4746
|
+
if (!await exists(this.paths.societySkillFile(args.name))) {
|
|
4747
|
+
throw new BoardError("NOT_FOUND", `the society has no skill ${args.name}`);
|
|
4748
|
+
}
|
|
4749
|
+
const removed = RemovedSkillSchema.parse({
|
|
4750
|
+
name: args.name,
|
|
4751
|
+
reason: args.reason,
|
|
4752
|
+
removedBy: actor.name,
|
|
4753
|
+
removedAt: this.now().toISOString()
|
|
4754
|
+
});
|
|
4755
|
+
const aside = this.paths.removedSkills();
|
|
4756
|
+
await mkdir4(aside, { recursive: true });
|
|
4757
|
+
await rename3(this.paths.societySkill(args.name), path6.join(aside, `${args.name}.${removed.removedAt.replaceAll(":", "-")}`));
|
|
4758
|
+
await this.events.append("skill.removed", actor.name, {
|
|
4759
|
+
name: args.name,
|
|
4760
|
+
reason: args.reason
|
|
4761
|
+
});
|
|
4762
|
+
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${args.name} removed from the society by ${actor.name}: ${sentence(withoutMentions(args.reason))}. Every citizen's skills index stops listing it from its next turn.`);
|
|
4763
|
+
return removed;
|
|
4764
|
+
});
|
|
4765
|
+
}
|
|
4716
4766
|
/**
|
|
4717
4767
|
* Replaces a project's dashboard, by a member or the user. A turn reads the dashboard from the
|
|
4718
4768
|
* copy of the projection pulled when it started, so a revision other than the current one means
|
|
@@ -5935,6 +5985,8 @@ ${rationale}`}`);
|
|
|
5935
5985
|
return this.writeKnowledge(actor, VerbInputs.write_knowledge.parse(input));
|
|
5936
5986
|
case "remove_knowledge":
|
|
5937
5987
|
return this.removeKnowledge(actor, VerbInputs.remove_knowledge.parse(input));
|
|
5988
|
+
case "remove_skill":
|
|
5989
|
+
return this.removeSkill(actor, VerbInputs.remove_skill.parse(input));
|
|
5938
5990
|
case "plan_task":
|
|
5939
5991
|
return this.planTask(actor, VerbInputs.plan_task.parse(input));
|
|
5940
5992
|
case "advance_task":
|
|
@@ -9307,7 +9359,7 @@ var GOVERNANCE = [
|
|
|
9307
9359
|
' - retirement: {"agent", "reason"}',
|
|
9308
9360
|
' - archive: {"project", "reason"}: approval archives the project: its members leave, its open threads close, and nothing more is posted, filed, or joined there, while its files and history stay; refused while a task there is in play',
|
|
9309
9361
|
' - reallocation: {"description"}',
|
|
9310
|
-
|
|
9362
|
+
' - skill: {"name", "summary", "body"}: the SKILL.md text; approval publishes it under society/skills, where every citizen\'s skills index lists it until the steward or the user removes it with `remove_skill`; ask the steward to remove one that is wrong or superseded',
|
|
9311
9363
|
"- Projects and membership: a project is a lasting area of work, not one request; `create_project` opens one with its general channel (front desk and user), and `configure_project` sets its completion effect, its display name, or its default branch, never its slug (user, steward, concierge). A workstream within a project or the society, such as a release, gets a channel of its own: `create_channel` opens it, which its opener follows, and announces it in the place's general, where members subscribe when it concerns them, `create_task` with `channel` files the workstream's tasks there, and `archive_channel` ends it once none of its tasks is in play, leaving its history readable (user, steward, concierge; others propose a channel). A project whose work is finished or has moved to another project is archived by proposal, once no task there is in play. `join_project` and `leave_project` move yourself, or another citizen when you are the concierge, the steward, or the user; joining gives the pair a worktree and an onboarding turn. A society role, one that keeps watch over the whole society as the concierge and the steward do, is never in a project: it moves others, never itself.",
|
|
9312
9364
|
"- Prefer scaling an existing role over inventing one; a new role is justified by work a project needs that no existing role covers. A role that needs a tool the board lacks is an engineering task, not a hiring request.",
|
|
9313
9365
|
"- Operations signals are counters and timers the board logs, listed in the prompt of a role that reads them: stages waiting for a holder, backlog per role, stages waiting on a role nobody fills, churn, stale threads, idle members, missing capabilities, replicas added, spend. They are not posts in any channel; interpreting them is your judgment."
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Pt as e,x as t,yn as n}from"./format-CkySAdH1.js";import{D as r,n as i,r as a,t as o,v as s}from"./index-CwkK8XtJ.js";var c=n(),l=`grid size-7 shrink-0 place-items-center rounded-lg text-fg-tertiary hover:bg-surface-2/70 hover:text-fg-primary`;function u({fallback:n}){let u=e(),d=r({select:e=>e.location.state.__TSR_index}),f=a(),p=s(),m=t(),h=i(f,d);if(h===null)return n;let g=o(h,{entity:e=>p.get(e)?.title,project:e=>m.data?.find(t=>t.slug===e)?.name});return(0,c.jsx)(`button`,{type:`button`,onClick:()=>u.history.back(),"aria-label":`Back to ${g}`,title:`Back to ${g}`,className:l,children:`←`})}export{u as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Cn as e,
|
|
1
|
+
import{Cn as e,bn as t,k as n,t as r,vn as i,yn as a}from"./format-CkySAdH1.js";import{a as o,o as s,s as c}from"./compose-D-SO-HE-.js";import{t as l}from"./link-BN04dcBX.js";import{n as u,r as d}from"./ThreadForms-CXsunS-N.js";var f=e(t(),1),p=a();function m({project:e,onDone:t}){let{api:r}=n(),a=i(),l=s(),[m,h]=(0,f.useState)(``),[g,_]=(0,f.useState)(``),v=(0,f.useRef)(null);(0,f.useEffect)(()=>v.current?.focus(),[]);let y=c({mutationFn:()=>r.createChannel({project:e,name:m.trim(),purpose:g.trim()}),onSuccess:async e=>{await a.invalidateQueries({queryKey:[`channels`]}),t(),await l({to:`/c/$`,params:{_splat:e}})}});return(0,p.jsxs)(`form`,{"aria-label":`New channel`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),y.mutate()},children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`div`,{className:`w-40 shrink-0`,children:(0,p.jsx)(`input`,{ref:v,value:m,maxLength:64,spellCheck:!1,"aria-label":`Channel name`,placeholder:`release-0-4`,onChange:e=>h(e.target.value),className:`${u} font-mono`})}),(0,p.jsx)(`input`,{value:g,"aria-label":`Purpose`,placeholder:`What the channel is for`,onChange:e=>_(e.target.value),className:`${u} min-w-0 flex-1`}),(0,p.jsx)(o,{onClick:t,children:`Cancel`}),(0,p.jsx)(o,{variant:`primary`,type:`submit`,disabled:y.isPending||m.trim()===``||g.trim()===``,children:y.isPending?`Opening…`:`Open`})]}),(0,p.jsx)(`p`,{className:`text-meta`,children:e===null?`Announced in the society's general, and followed by whoever subscribes to it; you read every channel without following one.`:`Announced in ${e}'s general, where its members choose to follow it; you read every channel without following one. Tasks filed in it hang their threads here, and it is archived once its tasks are done.`}),(0,p.jsx)(d,{error:y.error})]})}function h({channel:e,onDone:t}){let{api:r}=n(),a=i(),[s,l]=(0,f.useState)(``),m=c({mutationFn:()=>r.archiveChannel({channel:e,reason:s.trim()}),onSuccess:async()=>{await a.invalidateQueries({queryKey:[`channels`]}),t()}});return(0,p.jsxs)(`form`,{"aria-label":`Archive the channel`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),m.mutate()},children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`input`,{value:s,"aria-label":`Reason`,placeholder:`Why its work is done`,onChange:e=>l(e.target.value),className:`${u} min-w-0 flex-1`}),(0,p.jsx)(o,{onClick:t,children:`Cancel`}),(0,p.jsx)(o,{variant:`primary`,type:`submit`,disabled:m.isPending||s.trim()===``,children:m.isPending?`Archiving…`:`Archive channel`})]}),(0,p.jsx)(`p`,{className:`text-meta`,children:`Its open threads close, nobody follows it, and nothing more is posted or filed here; its posts, threads, and tasks stay readable. The board refuses while a task filed here is in play.`}),(0,p.jsx)(d,{error:m.error})]})}function g({channels:e,now:t}){return e.length===0?(0,p.jsx)(`p`,{className:`text-meta`,children:`No channels.`}):(0,p.jsx)(`ul`,{className:`space-y-1`,children:e.map(e=>(0,p.jsxs)(`li`,{children:[(0,p.jsxs)(l,{to:`/c/$`,params:{_splat:e.ref},className:`text-sm hover:text-fg-primary ${e.archived===void 0?`text-fg-secondary`:`text-fg-tertiary`}`,children:[`# `,e.name]}),(0,p.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,e.messages,` messages`,e.archived===void 0?``:` · archived ${r(e.archived.at,t)}`]})]},e.ref))})}export{g as n,m as r,h as t};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Cn as e,
|
|
2
|
-
`),className:`shrink-0`,children:u(r.ts,t)})]})}function I(){let{_splat:e=`general`}=_({from:`/c/$`});return(0,j.jsx)(L,{channel:e},e)}function L({channel:e}){let{api:
|
|
1
|
+
import{Cn as e,Qt as t,R as n,V as r,_ as i,b as a,bn as o,c as s,k as c,mt as l,t as u,x as d,yn as f}from"./format-CkySAdH1.js";import{a as p}from"./compose-D-SO-HE-.js";import{t as m}from"./link-BN04dcBX.js";import{S as h,i as g,k as _,s as v}from"./index-CwkK8XtJ.js";import{i as y}from"./ThreadForms-CXsunS-N.js";import{t as b}from"./ChannelForms-DfG4vYvk.js";import{t as x}from"./MessageItem-DDs7m3-4.js";import{n as S,t as C}from"./Pane-v044FaP5.js";import{n as w}from"./ThreadCard-BRLvjdz3.js";import{t as T}from"./useStickyScroll-WSVpAMrA.js";var E=e(o(),1);function D(e,t){let n=e.notices.at(-1);return n!==void 0&&n.kind===`knowledge`&&t.kind===`knowledge`&&n.action!==`removed`&&t.action===`updated`&&n.topic===t.topic&&n.project===t.project}function O(e,t){let n=[],r=null;for(let i of e){let e=t(i),a=e?.notice;e===void 0||a===void 0?(n.push({kind:`item`,item:i}),r=null):r!==null&&D(r,a)?(r.messages.push(e),r.notices.push(a)):(r={messages:[e],notices:[a]},n.push({kind:`notices`,run:r}))}return n}function k(e){let[t]=e,n=e.length-1;return t===void 0||t.action===`removed`?{did:`removed`,times:null}:t.action===`written`?{did:`wrote`,times:n===0?null:`then updated it ${n===1?`once`:`${n} times`}`}:{did:`updated`,times:n===0?null:`${e.length} times`}}function A(e){let t=[...new Set(e)];return t.length<=2?t.join(` and `):`${t.slice(0,-1).join(`, `)}, and ${t.at(-1)??``}`}var j=f();function M(){return(0,j.jsx)(`svg`,{viewBox:`0 0 16 16`,"aria-hidden":`true`,className:`size-3.5`,children:(0,j.jsx)(`path`,{d:`M8 4.2C6.4 3 4.4 2.8 2.2 3.4v9.2c2.2-.6 4.2-.4 5.8.8m0-9.2c1.6-1.2 3.6-1.4 5.8-.8v9.2c-2.2-.6-4.2-.4-5.8.8m0-9.2v9.2`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.2`,strokeLinejoin:`round`})})}function N({notices:e}){let[t]=e;if(t===void 0)return null;let{did:n,times:r}=k(e);return(0,j.jsxs)(j.Fragment,{children:[n,` knowledge`,` `,t.action===`removed`?(0,j.jsx)(`span`,{className:`text-fg-secondary`,children:t.topic}):(0,j.jsx)(m,{to:`/knowledge/$scope/$topic`,params:{scope:t.project??`society`,topic:t.topic},className:`text-fg-secondary hover:text-fg-primary`,children:t.topic}),r===null?null:` · ${r}`]})}function P(e){let t=e.notices.filter(e=>e.kind===`knowledge`);return{mark:(0,j.jsx)(M,{}),text:(0,j.jsx)(N,{notices:t})}}function F({run:e,now:t}){let n=v(),r=e.messages.at(-1);if(r===void 0)return null;let{mark:i,text:a}=P(e);return(0,j.jsxs)(`div`,{className:`flex items-center gap-3 px-4 py-1 text-meta`,children:[(0,j.jsx)(`span`,{className:`grid w-7 shrink-0 place-items-center text-fg-muted`,children:i}),(0,j.jsxs)(`p`,{className:`min-w-0 flex-1 truncate`,children:[A(e.messages.map(e=>n(e.author))),` `,a]}),(0,j.jsx)(`time`,{dateTime:r.ts,title:e.messages.map(e=>`${n(e.author)} ${e.ts}`).join(`
|
|
2
|
+
`),className:`shrink-0`,children:u(r.ts,t)})]})}function I(){let{_splat:e=`general`}=_({from:`/c/$`});return(0,j.jsx)(L,{channel:e},e)}function L({channel:e}){let{api:o}=c(),f=t({queryKey:[`channel`,e],queryFn:()=>o.channel(e)}),m=n(),_=i(),v=d(),D=s(),k=a(3e4),[A,M]=(0,E.useState)(!1),[N,P]=(0,E.useState)(!1),I=(0,E.useMemo)(()=>{let t=(f.data??[]).map(e=>({kind:`message`,at:e.ts,id:e.id,message:e})),n=(m.data??[]).filter(t=>t.channel===e).map(e=>({kind:`thread`,at:e.openedAt,id:e.id,thread:e}));return[...t,...n].toSorted((e,t)=>e.at.localeCompare(t.at)||e.id.localeCompare(t.id))},[f.data,m.data,e]),L=(0,E.useMemo)(()=>O(I,e=>e.kind===`message`?e.message:void 0),[I]),R=f.data?.at(-1)?.id??null;(0,E.useEffect)(()=>h(e,R),[e,R]);let{ref:z,onScroll:B}=T(),[V,H]=e.split(`/`),U=H??V??e,W=H===void 0?void 0:v.data?.find(e=>e.slug===V),G=H===void 0?`society`:W?.name??V,K=D.data?.find(t=>t.ref===e)?.archived,q=W?.archived!==void 0||K!==void 0,J=!q&&!l(H===void 0?null:V??null,U),Y=I.filter(e=>e.kind===`thread`&&e.thread.state===`open`);return(0,j.jsxs)(j.Fragment,{children:[(0,j.jsx)(C,{title:`# ${U}`,subtitle:`${G} · ${f.data?.length??0} messages${Y.length>0?` · ${Y.length} open threads`:``}`,trailing:A||N||q?null:(0,j.jsxs)(j.Fragment,{children:[J?(0,j.jsx)(p,{onClick:()=>P(!0),children:`Archive…`}):null,(0,j.jsx)(p,{onClick:()=>M(!0),children:`New thread`})]})}),A?(0,j.jsx)(y,{channel:e,onDone:()=>M(!1)}):null,N?(0,j.jsx)(b,{channel:e,onDone:()=>P(!1)}):null,(0,j.jsx)(`div`,{ref:z,onScroll:B,className:`flex-1 overflow-y-auto py-2`,children:f.error instanceof r&&f.error.status===404?(0,j.jsxs)(S,{children:[`There is no channel `,e,`.`]}):f.data===void 0?(0,j.jsx)(S,{children:`Reading the channel…`}):I.length===0?(0,j.jsx)(S,{children:`Nothing has been said here yet.`}):L.map(e=>{if(e.kind===`notices`){let t=e.run.messages[0]?.id??``;return(0,j.jsx)(F,{run:e.run,now:k},t)}let{item:t}=e;return t.kind===`message`?(0,j.jsx)(x,{message:t.message,members:_.data,now:k},t.id):(0,j.jsx)(w,{thread:t.thread,now:k},t.id)})}),f.data===void 0?null:K===void 0?q?(0,j.jsxs)(`p`,{className:`border-t border-line px-4 py-3 text-meta`,children:[G,` is archived, so its channels are read-only.`]}):(0,j.jsx)(g,{target:{channel:e},placeholder:`Message #${U}`}):(0,j.jsxs)(`p`,{className:`border-t border-line px-4 py-3 text-meta`,children:[`Archived `,u(K.at,k),` by `,K.by,`: `,K.reason,`. Its posts, threads, and tasks stay readable; nothing more is posted or filed here.`]})]})}export{I as ChannelView};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{B as e,Cn as t,D as n,
|
|
2
|
-
`).map((e,t)=>(0,W.jsx)(`span`,{className:`block whitespace-pre-wrap break-words ${Se(e)}`,children:e===``?` `:e},t))}),e.truncated?(0,W.jsx)(`p`,{className:`mt-1 text-meta`,children:`The rest of this file's change is cut.`}):null]})}function we({name:e,change:t}){let n=p(e,t.commit,!0);return(0,W.jsxs)(`div`,{className:`space-y-3 px-4 pt-1 pb-3`,children:[(0,W.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,W.jsx)(D,{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,W.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,G(t.at)]})]}),n.data===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:n.isError?`Could not read the change.`:`Reading the change…`}):n.data.map(e=>(0,W.jsx)(Ce,{file:e},e.path))]})}function Te({name:e,change:t,now:n}){let[r,i]=(0,U.useState)(!1),a=t.files.length===0?t.subject:xe(t);return(0,W.jsx)(`li`,{className:`border-b border-line/60 last:border-b-0`,children:(0,W.jsxs)(`details`,{className:`group`,onToggle:e=>i(e.currentTarget.open),children:[(0,W.jsx)(`summary`,{"aria-label":`${ye[t.kind]} ${x(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,W.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,W.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:ve[t.kind]}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg-secondary`,children:a}),(0,W.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:x(t.at,n)}),(0,W.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]})}),r?(0,W.jsx)(we,{name:e,change:t}):null]})})}function Ee({name:e}){let[t,n]=(0,U.useState)(J),r=_(e,t),i=f(3e4);if(r.data===void 0)return(0,W.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,W.jsxs)(L,{children:[e,`'s home has no history yet; it starts with the citizen's first turn.`]}):(0,W.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,W.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,W.jsx)(`ol`,{children:a.map(t=>(0,W.jsx)(Te,{name:e,change:t,now:i},t.commit))}),o?(0,W.jsx)(`button`,{type:`button`,onClick:()=>n(t+J),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:`Show earlier changes`}):null]})}function Y({title:e,children:t}){return(0,W.jsxs)(`section`,{className:`border-t border-line pt-4 first:border-t-0 first:pt-0`,children:[(0,W.jsx)(`h3`,{className:`text-section`,children:e}),(0,W.jsx)(`div`,{className:`mt-2`,children:t})]})}function De({member:e,charter:t}){let n=S(e.name),r=v(e.name),i=y(e.name),a=f(3e4);return(0,W.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,W.jsxs)(Y,{title:`Edits to reconcile`,children:[(0,W.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,W.jsx)(`ul`,{className:`mt-2 space-y-1.5`,children:i.data.map(e=>(0,W.jsxs)(`li`,{className:`text-sm`,children:[(0,W.jsx)(`span`,{className:`text-fg-primary`,children:e.file}),(0,W.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,e.path.slice(e.path.lastIndexOf(`/`)+1),` · left`,` `,x(e.since,a)]})]},e.path))})]}),(0,W.jsx)(Y,{title:`Profile`,children:e.profile.trim()===``?(0,W.jsx)(`p`,{className:`text-meta`,children:`No profile yet. The citizen writes its own profile.md.`}):(0,W.jsx)(I,{text:V(e.profile,`Profile`)})}),(0,W.jsx)(Y,{title:`Core memory`,children:n.data===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):n.data.body.trim()===``?(0,W.jsx)(`p`,{className:`text-meta`,children:`Empty. Every turn loads this file in full.`}):(0,W.jsx)(I,{text:V(n.data.body,`Core memory`)})}),(0,W.jsx)(Y,{title:`Own skills`,children:r.data===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):r.data.length===0?(0,W.jsx)(`p`,{className:`text-meta`,children:`None yet.`}):(0,W.jsx)(`ul`,{className:`space-y-1.5`,children:r.data.map(e=>(0,W.jsxs)(`li`,{className:`text-sm`,children:[(0,W.jsx)(`span`,{className:`text-fg-primary`,children:e.name}),e.summary===``?null:(0,W.jsxs)(`span`,{className:`text-fg-secondary`,children:[` · `,e.summary]})]},e.name))})}),t===void 0?null:(0,W.jsxs)(Y,{title:`Charter of ${t.name}`,children:[(0,W.jsx)(`p`,{className:`text-sm text-fg-secondary`,children:t.purpose}),(0,W.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,W.jsx)(`p`,{className:`mt-2 flex flex-wrap gap-1`,children:t.verbs.map(e=>(0,W.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 Oe(e,t){let n=w(e,t?.turnId??null);return{turn:(0,U.useMemo)(()=>t===void 0||n.data===void 0?void 0:ie(n.data,e,t.project,t),[t,n.data,e]),loading:t?.turnId!==void 0&&n.isPending,missing:t!==void 0&&(t.turnId===void 0||n.isError)}}var X=50;function ke({name:e,entry:t,now:n,opened:r}){let[i,a]=(0,U.useState)(r),o=(0,U.useRef)(null);(0,U.useEffect)(()=>{r&&o.current?.scrollIntoView({block:`start`})},[r]);let s=oe(),c=ue(t),l=t.thread===void 0?t.channel===void 0?null:`#${t.channel}`:s.get(t.thread)?.title??`a thread`,u=t.error??t.summary??``,d=t.error===null?`text-fg-secondary`:`text-red-300`;return(0,W.jsx)(`li`,{ref:o,className:`border-b border-line/60 last:border-b-0`,children:(0,W.jsxs)(`details`,{className:`group`,open:i,onToggle:e=>a(e.currentTarget.open),children:[(0,W.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,W.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,W.jsxs)(`span`,{className:`min-w-0 truncate text-fg-secondary`,children:[R(t.project),l===null?``:` · ${l}`]}),(0,W.jsx)(`span`,{className:`text-fg-muted`,children:t.trigger}),(0,W.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-fg-muted`,children:[me(t),` `,x(t.ts,n)]}),(0,W.jsx)(`span`,{className:`shrink-0 font-mono text-[11px] text-fg-tertiary`,title:t.usage===void 0?void 0:z(t.usage),children:[c,t.toolCalls===void 0?null:`${t.toolCalls} tools`,t.usage===void 0?null:B(t.usage)].filter(e=>e!==null).join(` · `)}),(0,W.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]}),u.trim()===``?null:(0,W.jsx)(`span`,{className:`mt-1 line-clamp-2 block text-xs leading-relaxed group-open:hidden ${d}`,children:(0,W.jsx)(k,{text:u,links:!1})})]}),i?(0,W.jsx)(Ae,{name:e,entry:t,text:u,tone:d}):null]})})}function Ae({name:e,entry:t,text:n,tone:r}){let i=Oe(e,t);return(0,W.jsxs)(`div`,{className:`px-4 pt-1 pb-3`,children:[n.trim()===``?null:(0,W.jsx)(`p`,{className:`text-xs leading-relaxed whitespace-pre-wrap ${r}`,children:(0,W.jsx)(k,{text:n})}),(0,W.jsx)(`div`,{className:`mt-2`,children:t.turnId===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:`This turn ran before turns kept their steps.`}):i.loading?(0,W.jsx)(`p`,{className:`text-meta`,children:`Reading the steps…`}):i.turn===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:`No steps were kept for this turn.`}):(0,W.jsxs)(W.Fragment,{children:[t.startedAt===void 0?null:(0,W.jsxs)(`p`,{className:`text-caps`,children:[`Started `,G(t.startedAt)]}),(0,W.jsx)(q,{steps:i.turn.steps})]})})]})}function je({name:t,opened:n}){let[r,i]=(0,U.useState)(X),a=e(t,r),o=f(3e4);if(a.data===void 0)return(0,W.jsx)(L,{children:`Reading the turns…`});let s=a.data.toReversed();if(s.length===0)return(0,W.jsxs)(L,{children:[t,` has not finished a turn yet.`]});let c=pe(s),l=c.usage===null?``:` · ${B(c.usage)}${c.withUsage<c.turns?` over ${c.withUsage} of them`:``}`;return(0,W.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,W.jsxs)(`p`,{className:`px-4 pt-3 pb-1 text-meta`,title:c.usage===null?void 0:z(c.usage),children:[c.turns===1?`1 turn`:`${c.turns} turns`,c.failed===0?``:`, ${c.failed} not completed`,l]}),n!==null&&!s.some(e=>e.turnId===n)?(0,W.jsx)(`p`,{className:`px-4 pb-1 text-meta`,children:a.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,W.jsx)(`ol`,{children:s.map(e=>(0,W.jsx)(ke,{name:t,entry:e,now:o,opened:n!==null&&e.turnId===n},e.id))}),a.data.length===r?(0,W.jsxs)(`button`,{type:`button`,onClick:()=>i(r+X),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:[`Show `,X,` earlier turns`]}):null]})}var Z=``,Q=``;function Me(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 Ne(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 Pe({member:e,onDone:t}){let{api:n}=m(),r=C(),i=d(e.name),a=e.model??Z,o=e.effort??Q,[s,c]=(0,U.useState)(a),[u,f]=(0,U.useState)(o),p=T({mutationFn:async()=>{s!==a&&await n.setModel(e.name,s===Z?null:s),u!==o&&await n.setEffort(e.name,u===Q?null:u)},onSettled:()=>void r.invalidateQueries({queryKey:[`members`]}),onSuccess:t}),h=i.data?.models??[],g=e.model!==void 0&&!h.some(t=>t.id===e.model)?e.model:null,_=e=>h.find(t=>e===Z?t.isDefault:t.id===e),v=_(s)?.efforts??[],y=u!==Q&&!v.some(e=>e.id===u)?u:null,b=e=>{c(e);let t=_(e)?.efforts??[];u!==Q&&!t.some(e=>e.id===u)&&f(Q)},x=s!==a||u!==o;return(0,W.jsxs)(`form`,{"aria-label":`Model of ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),p.mutate()},children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[i.isPending?(0,W.jsxs)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:[`Asking `,e.cli,` for its models…`]}):i.error===null?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(H,{label:`Model`,choices:Me(h,g),value:s,onChange:b}),v.length===0&&y===null?null:(0,W.jsx)(`div`,{className:`flex w-32 shrink-0`,children:(0,W.jsx)(H,{label:`Effort`,choices:Ne(_(s),y),value:u,onChange:f,listClassName:`right-0 w-64`})})]}):(0,W.jsxs)(`p`,{role:`alert`,className:`min-w-0 flex-1 truncate text-xs text-red-400`,children:[e.cli,` did not list its models:`,` `,i.error instanceof l?i.error.message:`the board server did not answer`]}),(0,W.jsx)(E,{onClick:t,children:`Cancel`}),(0,W.jsx)(E,{variant:`primary`,type:`submit`,disabled:p.isPending||!x||i.error!==null,children:p.isPending?`Saving…`:`Save`})]}),i.data===void 0?null:(0,W.jsxs)(`p`,{className:`text-meta`,children:[`As `,i.data.cli,` on `,i.data.runner,` lists them, where this citizen's turns run.`]}),(0,W.jsx)(F,{error:p.error})]})}var $=``;function Fe(e,t){let n=t.cli;return[e.status,e.clis.length===0?`offers no CLI yet`:e.clis.join(`, `),n!==null&&e.clis.length>0&&!e.clis.includes(n)?`has no ${n}`:``,e.capabilities.length===0?``:e.capabilities.join(`, `)].filter(e=>e!==``).join(` · `)}function Ie(e,t){return[{value:$,name:`Any runner`,id:null,description:`Pinned to the least busy runner on its next turn outside a project.`},...e.map(e=>({value:e.name,name:e.name,id:e.os,description:Fe(e,t)}))]}function Le({member:e,onDone:t}){let{api:n}=m(),i=C(),a=r(),o=e.homeRunner??$,[s,c]=(0,U.useState)(o),l=T({mutationFn:()=>n.setRunner(e.name,s===$?null:s),onSuccess:()=>{i.invalidateQueries({queryKey:[`members`]}),t()}});return(0,W.jsxs)(`form`,{"aria-label":`Runner of ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),l.mutate()},children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a.data===void 0?(0,W.jsx)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:`Reading the runners…`}):(0,W.jsx)(H,{label:`Runner`,choices:Ie(a.data,e),value:s,onChange:c}),(0,W.jsx)(E,{onClick:t,children:`Cancel`}),(0,W.jsx)(E,{variant:`primary`,type:`submit`,disabled:l.isPending||s===o,children:l.isPending?`Saving…`:`Run here`})]}),(0,W.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,W.jsx)(F,{error:l.error})]})}function Re(e){if(e.thread!==void 0)return{threadId:e.thread};let t=e.scope===`society`?null:e.scope;return e.channel===void 0?{channel:e.askedIn??h(t,`general`)}:{channel:h(t,e.channel)}}function ze({name:e,turn:t}){let{api:n}=m(),r=C(),[i,a]=(0,U.useState)(!1),o=T({mutationFn:()=>n.stopTurn(t.turnId),onSuccess:()=>{a(!1),r.invalidateQueries({queryKey:[`scheduler`]})}});return(0,W.jsxs)(`div`,{className:`border-t border-line`,children:[(0,W.jsx)(ne,{target:Re(t),initialText:`@${e} `,placeholder:t.steerable?`Message ${e} while it works`:`Message ${e} for its next turn`,className:`px-3 pt-3 pb-2`},t.turnId),t.stoppable?(0,W.jsxs)(`div`,{className:`flex items-center gap-2 px-3 pb-3`,children:[(0,W.jsx)(`p`,{className:`min-w-0 flex-1 text-[11px] leading-snug text-fg-muted`,children:i?`Ends the turn now. What it was shown counts as read; its stages stay held.`:t.steerable?`Posts reach the turn at its next step.`:`This runner delivers posts after the turn ends.`}),i?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(E,{onClick:()=>{a(!1),o.reset()},children:`Keep it running`}),(0,W.jsx)(E,{variant:`primary`,disabled:o.isPending,onClick:()=>{o.mutate()},children:o.isPending?`Stopping…`:`Stop the turn`})]}):(0,W.jsx)(E,{onClick:()=>a(!0),children:`Stop…`})]}):null,o.error===null?null:(0,W.jsx)(`div`,{className:`px-3 pb-3`,children:(0,W.jsx)(F,{error:o.error})})]})}function Be({member:e,scopes:t,preferred:n,running:r,paused:i,onDone:a}){let{api:o}=m(),s=C(),[c,l]=(0,U.useState)(`manual`),[u,d]=(0,U.useState)(n!==null&&t.includes(n)?n:t[0]??``),[f,p]=(0,U.useState)(``),h=(0,U.useRef)(null);(0,U.useEffect)(()=>h.current?.focus(),[]);let g=T({mutationFn:()=>o.wake({agent:e.name,project:u,kind:c,...f.trim()===``?{}:{reason:f.trim()}}),onSuccess:()=>{s.invalidateQueries({queryKey:[`scheduler`]}),a()}}),_=R(u),v=c===`reflection`?`Asks ${e.name} to reflect at ${_}: consolidate its memory, skills, and profile, and take no new work. It restarts the reflection clock.`:`Starts a turn for ${e.name} at ${_} as soon as the scheduler takes it.`,y=i?` The society is paused, so it waits until you resume.`:r.includes(u)?` ${e.name} is in a turn there now; this one follows it.`:``;return(0,W.jsxs)(`form`,{"aria-label":`Wake ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),g.mutate()},children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsxs)(`fieldset`,{className:`flex gap-1`,children:[(0,W.jsx)(`legend`,{className:`sr-only`,children:`Kind of turn`}),[`manual`,`reflection`].map(e=>(0,W.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 ${c===e?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:[(0,W.jsx)(`input`,{type:`radio`,name:`kind`,value:e,checked:c===e,onChange:()=>l(e),className:`sr-only`}),e===`manual`?`A turn`:`A reflection`]},e))]}),(0,W.jsxs)(`div`,{className:`ml-auto flex w-52 items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`shrink-0 text-xs text-fg-tertiary`,children:`at`}),(0,W.jsx)(H,{label:`Where`,choices:de(t),value:u,onChange:d})]})]}),(0,W.jsx)(`textarea`,{ref:h,value:f,rows:2,placeholder:c===`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=>p(e.target.value),className:`${se} resize-none`}),(0,W.jsxs)(`p`,{className:`text-[11px] leading-relaxed text-fg-muted`,children:[v,y,` Each turn costs money.`]}),(0,W.jsxs)(`div`,{className:`flex items-center justify-end gap-2`,children:[(0,W.jsx)(E,{onClick:a,children:`Cancel`}),(0,W.jsx)(E,{variant:`primary`,type:`submit`,disabled:g.isPending||u===``,children:g.isPending?`Waking…`:c===`reflection`?`Ask for a reflection`:`Wake ${e.name}`})]}),(0,W.jsx)(F,{error:g.error})]})}var Ve={working:`bg-emerald-500/15 text-emerald-300`,queued:`bg-amber-500/15 text-amber-300`,idle:`bg-surface-2 text-fg-tertiary`};function He({project:e,name:t}){let n=(o(e).data??[]).filter(e=>e.status===`claimed`&&e.claimedBy===t);return n.length===0?null:(0,W.jsx)(`ul`,{className:`mt-1.5 space-y-1`,children:n.map(e=>(0,W.jsx)(`li`,{children:(0,W.jsxs)(D,{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,W.jsx)(`span`,{"aria-hidden":`true`,className:`text-fg-muted`,children:`◇`}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.title}),(0,W.jsx)(`span`,{className:`max-w-[40%] shrink-0 truncate font-mono text-[11px] text-fg-muted`,children:b(e)?.name??e.stage})]})},e.id))})}function Ue(){let{name:e}=re({from:`/citizen/$name`}),{scope:t,tab:n,turn:r}=O({from:`/citizen/$name`});return(0,W.jsx)(Ge,{name:e,chosen:t??null,tab:n??`now`,turn:r??null},e)}var We=[{tab:`now`,label:`Now`},{tab:`turns`,label:`Turns`},{tab:`memory`,label:`Memory`},{tab:`history`,label:`History`}];function Ge({name:e,chosen:t,tab:r,turn:i}){let o=u(),s=c(),l=n(),d=M(),f=g(),[p,m]=(0,U.useState)(null),h=o.data?.find(t=>t.name===e);if(h===void 0)return(0,W.jsx)(L,{children:o.data===void 0?`Reading the roster…`:`There is no citizen ${e}.`});let _=a(l.data?.running??[]).filter(t=>t.agent===e),v=[...new Set(_.map(e=>e.scope))],y=_.map(e=>ae(e.agent,e.scope,e)),b=a(l.data?.pending??[]).find(t=>t.agent===e),x=v.length>0?`working`:b===void 0?`idle`:`queued`,S=P(d,e)[0],C=S?.model??h.lastModel,w=C??h.model??`CLI default`,T=h.model!==void 0&&h.model!==C?h.model:null,O=s.data?.find(e=>e.name===h.role),k=fe(h),A=h.status===`active`&&h.cli!==null,j=(f.data??[]).filter(t=>t.agent===e&&t.ended===void 0).length;return(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(ce,{leading:h.cli===null?null:(0,W.jsx)(`span`,{className:`grid size-9 shrink-0 place-items-center rounded-lg bg-surface-2/70`,children:(0,W.jsx)(ee,{cli:h.cli,size:20})}),title:e,subtitle:(0,W.jsxs)(W.Fragment,{children:[h.role,` · `,w,T===null?``:` · set to ${T}`,h.effort===void 0?``:` · ${h.effort} effort`,h.homeRunner===void 0?``:` · on ${h.homeRunner}`,h.status===`retired`?` · retired`:``]}),trailing:(0,W.jsxs)(W.Fragment,{children:[j===0?null:(0,W.jsx)(D,{to:`/crons`,search:{agent:e},className:`inline-flex h-7 shrink-0 items-center rounded-md px-3 text-xs text-fg-tertiary transition-colors hover:bg-surface-2/70 hover:text-fg-primary focus-visible:ring-2 focus-visible:ring-fg-primary/30 focus-visible:outline-none`,children:j===1?`1 cron`:`${j} crons`}),A&&p===null?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(E,{onClick:()=>m(`model`),children:`Model…`}),(0,W.jsx)(E,{onClick:()=>m(`runner`),children:`Runner…`}),(0,W.jsx)(E,{onClick:()=>m(`wake`),children:`Wake…`})]}):null,(0,W.jsx)(`span`,{className:`shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium ${Ve[x]}`,children:x})]})}),p===`wake`?(0,W.jsx)(Be,{member:h,scopes:k,preferred:t?.split(`/`)[0]??S?.scope??null,running:v,paused:l.data?.paused??!1,onDone:()=>m(null)}):p===`model`?(0,W.jsx)(Pe,{member:h,onDone:()=>m(null)}):p===`runner`?(0,W.jsx)(Le,{member:h,onDone:()=>m(null)}):null,(0,W.jsx)(`nav`,{"aria-label":`Citizen views`,className:`flex gap-1 border-b border-line px-3 py-2`,children:We.map(n=>(0,W.jsx)(D,{to:`/citizen/$name`,params:{name:e},search:{...t===null?{}:{scope:t},...n.tab===`now`?{}:{tab:n.tab}},replace:!0,"aria-current":n.tab===r?`page`:void 0,className:`rounded-md px-2.5 py-1 text-xs transition-colors ${n.tab===r?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:n.label},n.tab))}),r===`turns`?(0,W.jsx)(je,{name:e,opened:i},i):r===`memory`?(0,W.jsx)(De,{member:h,charter:O}):r===`history`?(0,W.jsx)(Ee,{name:e}):(0,W.jsx)(qe,{name:e,chosen:t,lastTurnAt:h.lastTurnAt,state:x,runningScopes:v,runningKeys:y,runningTurns:(l.data?.turns??[]).filter(t=>t.agent===e),queuedScope:b?.scope??null})]})}function Ke(e){return e.toSorted((e,t)=>e.startedAt.localeCompare(t.startedAt))[0]}function qe({name:t,chosen:n,lastTurnAt:r,state:i,runningScopes:a,runningKeys:o,runningTurns:s,queuedScope:c}){let l=M(),u=f(5e3),{ref:d,onScroll:p}=le(),m=P(l,t),h=e(t,1),g=Oe(t,m.length===0?h.data?.at(-1):void 0),_=oe(),v=e=>e.end===null&&o.includes(ae(e.agent,e.scope,e)),y=n?.split(`/`)[0]??null,b=(n?.includes(`/`)===!0?m.find(e=>A(e)===n):void 0)??Ke(m.filter(e=>e.scope===y&&v(e)))??m.find(e=>A(e)===n)??Ke(m.filter(v))??m[0]??g.turn,S=e=>e.thread===void 0?e.channel===void 0?R(e.scope):`${R(e.scope)} · #${e.channel}`:`${R(e.scope)} · ${_.get(e.thread)?.title??`a thread`}`,C=b!==void 0&&v(b),w=b?.scope??a[0]??c,T=(b===void 0?void 0:s.find(e=>e.scope===b.scope&&e.thread===b.thread&&e.channel===b.channel))??(C?void 0:s[0]);return(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`section`,{className:`border-b border-line px-4 py-3 text-xs text-fg-tertiary`,children:[(0,W.jsx)(`p`,{children:C?`In a turn at ${R(b.scope)} for ${b.fromStart?``:`at least `}${N(b.startedAt,u)}`:a.length>0?`In a turn at ${a.map(R).join(` and `)}`:c===null?r===void 0?`No turns yet`:`Last turn ${x(r,u)}`:`Queued for a turn at ${R(c)}`}),w===null||w===`society`?null:(0,W.jsx)(He,{project:w,name:t})]}),(0,W.jsx)(`div`,{ref:d,onScroll:p,className:`flex-1 overflow-y-auto px-4 py-3`,children:b===void 0?(0,W.jsx)(L,{children:i===`working`?`The turn has not reported a step yet.`:g.loading?`Reading the last turn…`:r===void 0?`${t} has not taken a turn yet.`:`${t}'s last turn kept no steps; Turns lists every finished one.`}):(0,W.jsxs)(W.Fragment,{children:[m.length>1?(0,W.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(e=>(0,W.jsxs)(D,{to:`/citizen/$name`,params:{name:t},search:{scope:A(e)},replace:!0,"aria-current":e===b?`true`:void 0,className:`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-[11px] transition-colors ${e===b?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:[v(e)?(0,W.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}):null,S(e)]},A(e)))}):null,(0,W.jsxs)(`p`,{className:`text-caps`,children:[C?`This turn`:`Last turn`,` · `,S(b),` · started`,` `,b.fromStart?G(b.startedAt):`before the earliest step shown`]}),b.fromStart?null:(0,W.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,W.jsx)(q,{steps:b.steps}),(0,W.jsx)(_e,{turn:b,running:C,now:u})]})}),T===void 0?null:(0,W.jsx)(ze,{name:t,turn:T})]})}export{Ue as CitizenView};
|
|
1
|
+
import{B as e,Cn as t,D as n,Dt as r,E as i,G as a,L as o,T as s,V as c,_ as l,a as u,b as d,bn as f,f as p,ft as m,k as h,l as g,m as _,o as v,p as y,t as b,v as x,vn as S,yn as C,z as w}from"./format-CkySAdH1.js";import{a as T,s as E}from"./compose-D-SO-HE-.js";import{t as D}from"./link-BN04dcBX.js";import{t as ee}from"./CliIcon-DTVk0pGU.js";import{O,_ as k,c as A,d as j,f as te,h as M,i as ne,k as re,l as N,m as P,p as ie,u as ae,v as oe}from"./index-CwkK8XtJ.js";import{n as se,r as F}from"./ThreadForms-CXsunS-N.js";import{t as I}from"./Markdown-DeF9PKNm.js";import{n as L,t as ce}from"./Pane-v044FaP5.js";import{t as le}from"./useStickyScroll-WSVpAMrA.js";import{a as R,c as ue,i as de,l as fe,n as pe,o as z,s as B,t as me,u as V}from"./citizen-VtLNxjtf.js";import{n as H}from"./Picker-wWsO86nu.js";var U=t(f(),1),W=C(),he={completed:`completed`,timeout:`timed out`,error:`failed`,interrupted:`was interrupted`,blocked:`was blocked`,stopped:`was stopped by you`};function G(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1})}function K({label:e,tone:t,children:n}){return(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`p`,{className:`px-0.5 pb-0.5 text-[10px] tracking-wider text-fg-muted uppercase`,children:e}),(0,W.jsx)(`pre`,{className:`max-h-72 overflow-auto rounded-md bg-surface-0/60 p-2 font-mono text-[11px] leading-relaxed whitespace-pre-wrap break-words ${t}`,children:n})]})}function ge({step:e,open:t}){if(e.kind===`say`)return(0,W.jsx)(`li`,{className:`py-1.5 text-sm`,title:G(e.at),children:(0,W.jsx)(I,{text:e.text})});if(e.kind===`error`)return(0,W.jsx)(`li`,{className:`py-1 font-mono text-xs break-words text-red-400`,title:G(e.at),children:e.message});if(e.kind===`steer`)return(0,W.jsx)(`li`,{children:(0,W.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,W.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,W.jsx)(`span`,{"aria-hidden":`true`,className:`grid w-3 shrink-0 place-items-center text-sky-300`,children:`↳`}),(0,W.jsxs)(`span`,{className:`shrink-0 text-fg-tertiary`,children:[`Took `,j(e.posts.length)]}),(0,W.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,W.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:G(e.at)})]}),(0,W.jsx)(`ul`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:e.posts.map(e=>(0,W.jsxs)(`li`,{className:`rounded-md bg-surface-0/40 px-2.5 py-2`,children:[(0,W.jsxs)(`p`,{className:`flex gap-1.5 text-meta`,children:[(0,W.jsx)(`span`,{className:`text-fg-secondary`,children:e.author}),(0,W.jsxs)(`span`,{className:`min-w-0 truncate`,children:[`in `,e.where]}),e.at===``?null:(0,W.jsx)(`span`,{className:`ml-auto shrink-0 font-mono`,children:G(e.at)})]}),(0,W.jsx)(`div`,{className:`mt-1 text-sm`,children:(0,W.jsx)(I,{text:e.body})})]},`${e.at}-${e.author}`))})]})});let n=e.ok===null?(0,W.jsx)(`span`,{"aria-label":`running`,className:`size-1.5 animate-pulse rounded-full bg-amber-300`}):e.ok?(0,W.jsx)(`span`,{"aria-label":`succeeded`,className:`text-[11px] text-emerald-400`,children:`✓`}):(0,W.jsx)(`span`,{"aria-label":`failed`,className:`text-[11px] text-red-400`,children:`✕`});return(0,W.jsx)(`li`,{children:(0,W.jsxs)(`details`,{open:t,className:`group rounded-md open:bg-surface-2/30`,children:[(0,W.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,W.jsx)(`span`,{className:`grid w-3 shrink-0 place-items-center`,children:n}),(0,W.jsx)(`span`,{className:`shrink-0 font-mono text-fg-tertiary`,children:te(e.name)}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-fg-secondary`,children:e.summary}),(0,W.jsx)(`span`,{className:`shrink-0 font-mono text-[10px] text-fg-muted`,children:G(e.at)})]}),(0,W.jsxs)(`div`,{className:`space-y-1.5 px-1.5 pb-1.5`,children:[(0,W.jsx)(K,{label:`Input`,tone:`text-fg-secondary`,children:e.detail}),e.output===null?null:(0,W.jsx)(K,{label:e.ok===!1?`Returned an error`:`Returned`,tone:e.ok===!1?`text-red-300`:`text-fg-tertiary`,children:e.output})]})]})})}function q({steps:e}){let[t,n]=(0,U.useState)(!1),r=e.filter(e=>e.kind===`tool`).length;return e.length===0?(0,W.jsx)(`p`,{className:`mt-2 text-meta`,children:`No steps yet.`}):(0,W.jsxs)(W.Fragment,{children:[r===0?null:(0,W.jsxs)(`p`,{className:`mt-2 flex items-center gap-2 text-meta`,children:[r===1?`1 tool call`:`${r} tool calls`,(0,W.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,W.jsx)(`ol`,{className:`mt-1 space-y-0.5`,children:e.map(e=>(0,W.jsx)(ge,{step:e,open:t},e.seq))})]})}function _e({turn:e,running:t,now:n}){return e.end===null?t?(0,W.jsxs)(`p`,{className:`mt-3 flex items-center gap-2 text-meta`,"aria-live":`polite`,children:[(0,W.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}),`Working · last step `,b(e.lastAt,n)]}):(0,W.jsx)(`p`,{className:`mt-3 text-meta`,children:`The turn ended without a report.`}):(0,W.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,W.jsxs)(`p`,{className:`text-caps`,children:[`The turn `,he[e.end.exitReason],` `,b(e.end.at,n),e.fromStart?` · ${N(e.startedAt,Date.parse(e.end.at))}`:``]}),e.end.summary===null?null:(0,W.jsx)(`p`,{className:`mt-1 text-sm text-fg-secondary`,children:e.end.summary})]})}var J=30,ve={turn:`turn`,board:`board`,merge:`both kept`},ye={turn:`Changed by a turn`,board:`Written by the board`,merge:`Both versions kept`};function be(e){return e.status===`added`?`new`:e.status===`deleted`?`deleted`:e.added===null||e.removed===null?`binary`:`+${e.added} −${e.removed}`}function xe(e){return e.files.map(e=>`${e.path} ${be(e)}`).join(`, `)}function Se(e){return e.startsWith(`@@`)||e.startsWith(`\\`)?`text-fg-muted`:e.startsWith(`+`)?`text-emerald-300`:e.startsWith(`-`)?`text-red-300`:`text-fg-tertiary`}function Ce({file:e}){return(0,W.jsxs)(`div`,{children:[(0,W.jsxs)(`p`,{className:`text-xs text-fg-secondary`,children:[e.path,e.status===`modified`?``:(0,W.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,e.status]})]}),e.patch===null?(0,W.jsx)(`p`,{className:`mt-1 text-meta`,children:`A binary file; its contents are not shown.`}):e.patch===``?(0,W.jsx)(`p`,{className:`mt-1 text-meta`,children:`Empty.`}):(0,W.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,W.jsx)(`span`,{className:`block whitespace-pre-wrap break-words ${Se(e)}`,children:e===``?` `:e},t))}),e.truncated?(0,W.jsx)(`p`,{className:`mt-1 text-meta`,children:`The rest of this file's change is cut.`}):null]})}function we({name:e,change:t}){let n=p(e,t.commit,!0);return(0,W.jsxs)(`div`,{className:`space-y-3 px-4 pt-1 pb-3`,children:[(0,W.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,W.jsx)(D,{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,W.jsxs)(`span`,{className:`text-fg-muted`,children:[` · `,G(t.at)]})]}),n.data===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:n.isError?`Could not read the change.`:`Reading the change…`}):n.data.map(e=>(0,W.jsx)(Ce,{file:e},e.path))]})}function Te({name:e,change:t,now:n}){let[r,i]=(0,U.useState)(!1),a=t.files.length===0?t.subject:xe(t);return(0,W.jsx)(`li`,{className:`border-b border-line/60 last:border-b-0`,children:(0,W.jsxs)(`details`,{className:`group`,onToggle:e=>i(e.currentTarget.open),children:[(0,W.jsx)(`summary`,{"aria-label":`${ye[t.kind]} ${b(t.at,n)}: ${a}`,className:`block cursor-pointer list-none px-4 py-2.5 transition-colors hover:bg-surface-2/30 group-open:bg-surface-2/20`,children:(0,W.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,W.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:ve[t.kind]}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg-secondary`,children:a}),(0,W.jsx)(`span`,{className:`shrink-0 text-fg-muted`,children:b(t.at,n)}),(0,W.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]})}),r?(0,W.jsx)(we,{name:e,change:t}):null]})})}function Ee({name:e}){let[t,n]=(0,U.useState)(J),r=_(e,t),i=d(3e4);if(r.data===void 0)return(0,W.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,W.jsxs)(L,{children:[e,`'s home has no history yet; it starts with the citizen's first turn.`]}):(0,W.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,W.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,W.jsx)(`ol`,{children:a.map(t=>(0,W.jsx)(Te,{name:e,change:t,now:i},t.commit))}),o?(0,W.jsx)(`button`,{type:`button`,onClick:()=>n(t+J),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:`Show earlier changes`}):null]})}function Y({title:e,children:t}){return(0,W.jsxs)(`section`,{className:`border-t border-line pt-4 first:border-t-0 first:pt-0`,children:[(0,W.jsx)(`h3`,{className:`text-section`,children:e}),(0,W.jsx)(`div`,{className:`mt-2`,children:t})]})}function De({member:e,charter:t}){let n=x(e.name),r=v(e.name),i=y(e.name),a=d(3e4);return(0,W.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,W.jsxs)(Y,{title:`Edits to reconcile`,children:[(0,W.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,W.jsx)(`ul`,{className:`mt-2 space-y-1.5`,children:i.data.map(e=>(0,W.jsxs)(`li`,{className:`text-sm`,children:[(0,W.jsx)(`span`,{className:`text-fg-primary`,children:e.file}),(0,W.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,e.path.slice(e.path.lastIndexOf(`/`)+1),` · left`,` `,b(e.since,a)]})]},e.path))})]}),(0,W.jsx)(Y,{title:`Profile`,children:e.profile.trim()===``?(0,W.jsx)(`p`,{className:`text-meta`,children:`No profile yet. The citizen writes its own profile.md.`}):(0,W.jsx)(I,{text:V(e.profile,`Profile`)})}),(0,W.jsx)(Y,{title:`Core memory`,children:n.data===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):n.data.body.trim()===``?(0,W.jsx)(`p`,{className:`text-meta`,children:`Empty. Every turn loads this file in full.`}):(0,W.jsx)(I,{text:V(n.data.body,`Core memory`)})}),(0,W.jsx)(Y,{title:`Own skills`,children:r.data===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:`Reading…`}):r.data.length===0?(0,W.jsx)(`p`,{className:`text-meta`,children:`None yet.`}):(0,W.jsx)(`ul`,{className:`space-y-1.5`,children:r.data.map(e=>(0,W.jsxs)(`li`,{className:`text-sm`,children:[(0,W.jsx)(`span`,{className:`text-fg-primary`,children:e.name}),e.summary===``?null:(0,W.jsxs)(`span`,{className:`text-fg-secondary`,children:[` · `,e.summary]})]},e.name))})}),t===void 0?null:(0,W.jsxs)(Y,{title:`Charter of ${t.name}`,children:[(0,W.jsx)(`p`,{className:`text-sm text-fg-secondary`,children:t.purpose}),(0,W.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,W.jsx)(`p`,{className:`mt-2 flex flex-wrap gap-1`,children:t.verbs.map(e=>(0,W.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 Oe(e,t){let n=w(e,t?.turnId??null);return{turn:(0,U.useMemo)(()=>t===void 0||n.data===void 0?void 0:ie(n.data,e,t.project,t),[t,n.data,e]),loading:t?.turnId!==void 0&&n.isPending,missing:t!==void 0&&(t.turnId===void 0||n.isError)}}var X=50;function ke({name:e,entry:t,now:n,opened:r}){let[i,a]=(0,U.useState)(r),o=(0,U.useRef)(null);(0,U.useEffect)(()=>{r&&o.current?.scrollIntoView({block:`start`})},[r]);let s=oe(),c=ue(t),l=t.thread===void 0?t.channel===void 0?null:`#${t.channel}`:s.get(t.thread)?.title??`a thread`,u=t.error??t.summary??``,d=t.error===null?`text-fg-secondary`:`text-red-300`;return(0,W.jsx)(`li`,{ref:o,className:`border-b border-line/60 last:border-b-0`,children:(0,W.jsxs)(`details`,{className:`group`,open:i,onToggle:e=>a(e.currentTarget.open),children:[(0,W.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,W.jsxs)(`span`,{className:`flex items-center gap-2 text-xs`,children:[(0,W.jsxs)(`span`,{className:`min-w-0 truncate text-fg-secondary`,children:[R(t.project),l===null?``:` · ${l}`]}),(0,W.jsx)(`span`,{className:`text-fg-muted`,children:t.trigger}),(0,W.jsxs)(`span`,{className:`min-w-0 flex-1 truncate text-fg-muted`,children:[me(t),` `,b(t.ts,n)]}),(0,W.jsx)(`span`,{className:`shrink-0 font-mono text-[11px] text-fg-tertiary`,title:t.usage===void 0?void 0:z(t.usage),children:[c,t.toolCalls===void 0?null:`${t.toolCalls} tools`,t.usage===void 0?null:B(t.usage)].filter(e=>e!==null).join(` · `)}),(0,W.jsx)(`span`,{"aria-hidden":`true`,className:`shrink-0 text-[10px] text-fg-muted transition-transform group-open:rotate-90`,children:`▸`})]}),u.trim()===``?null:(0,W.jsx)(`span`,{className:`mt-1 line-clamp-2 block text-xs leading-relaxed group-open:hidden ${d}`,children:(0,W.jsx)(k,{text:u,links:!1})})]}),i?(0,W.jsx)(Ae,{name:e,entry:t,text:u,tone:d}):null]})})}function Ae({name:e,entry:t,text:n,tone:r}){let i=Oe(e,t);return(0,W.jsxs)(`div`,{className:`px-4 pt-1 pb-3`,children:[n.trim()===``?null:(0,W.jsx)(`p`,{className:`text-xs leading-relaxed whitespace-pre-wrap ${r}`,children:(0,W.jsx)(k,{text:n})}),(0,W.jsx)(`div`,{className:`mt-2`,children:t.turnId===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:`This turn ran before turns kept their steps.`}):i.loading?(0,W.jsx)(`p`,{className:`text-meta`,children:`Reading the steps…`}):i.turn===void 0?(0,W.jsx)(`p`,{className:`text-meta`,children:`No steps were kept for this turn.`}):(0,W.jsxs)(W.Fragment,{children:[t.startedAt===void 0?null:(0,W.jsxs)(`p`,{className:`text-caps`,children:[`Started `,G(t.startedAt)]}),(0,W.jsx)(q,{steps:i.turn.steps})]})})]})}function je({name:t,opened:n}){let[r,i]=(0,U.useState)(X),a=e(t,r),o=d(3e4);if(a.data===void 0)return(0,W.jsx)(L,{children:`Reading the turns…`});let s=a.data.toReversed();if(s.length===0)return(0,W.jsxs)(L,{children:[t,` has not finished a turn yet.`]});let c=pe(s),l=c.usage===null?``:` · ${B(c.usage)}${c.withUsage<c.turns?` over ${c.withUsage} of them`:``}`;return(0,W.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[(0,W.jsxs)(`p`,{className:`px-4 pt-3 pb-1 text-meta`,title:c.usage===null?void 0:z(c.usage),children:[c.turns===1?`1 turn`:`${c.turns} turns`,c.failed===0?``:`, ${c.failed} not completed`,l]}),n!==null&&!s.some(e=>e.turnId===n)?(0,W.jsx)(`p`,{className:`px-4 pb-1 text-meta`,children:a.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,W.jsx)(`ol`,{children:s.map(e=>(0,W.jsx)(ke,{name:t,entry:e,now:o,opened:n!==null&&e.turnId===n},e.id))}),a.data.length===r?(0,W.jsxs)(`button`,{type:`button`,onClick:()=>i(r+X),className:`px-4 py-3 text-xs text-fg-tertiary hover:text-fg-primary`,children:[`Show `,X,` earlier turns`]}):null]})}var Z=``,Q=``;function Me(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 Ne(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 Pe({member:e,onDone:t}){let{api:n}=h(),r=S(),i=u(e.name),a=e.model??Z,o=e.effort??Q,[s,l]=(0,U.useState)(a),[d,f]=(0,U.useState)(o),p=E({mutationFn:async()=>{s!==a&&await n.setModel(e.name,s===Z?null:s),d!==o&&await n.setEffort(e.name,d===Q?null:d)},onSettled:()=>void r.invalidateQueries({queryKey:[`members`]}),onSuccess:t}),m=i.data?.models??[],g=e.model!==void 0&&!m.some(t=>t.id===e.model)?e.model:null,_=e=>m.find(t=>e===Z?t.isDefault:t.id===e),v=_(s)?.efforts??[],y=d!==Q&&!v.some(e=>e.id===d)?d:null,b=e=>{l(e);let t=_(e)?.efforts??[];d!==Q&&!t.some(e=>e.id===d)&&f(Q)},x=s!==a||d!==o;return(0,W.jsxs)(`form`,{"aria-label":`Model of ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),p.mutate()},children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[i.isPending?(0,W.jsxs)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:[`Asking `,e.cli,` for its models…`]}):i.error===null?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(H,{label:`Model`,choices:Me(m,g),value:s,onChange:b}),v.length===0&&y===null?null:(0,W.jsx)(`div`,{className:`flex w-32 shrink-0`,children:(0,W.jsx)(H,{label:`Effort`,choices:Ne(_(s),y),value:d,onChange:f,listClassName:`right-0 w-64`})})]}):(0,W.jsxs)(`p`,{role:`alert`,className:`min-w-0 flex-1 truncate text-xs text-red-400`,children:[e.cli,` did not list its models:`,` `,i.error instanceof c?i.error.message:`the board server did not answer`]}),(0,W.jsx)(T,{onClick:t,children:`Cancel`}),(0,W.jsx)(T,{variant:`primary`,type:`submit`,disabled:p.isPending||!x||i.error!==null,children:p.isPending?`Saving…`:`Save`})]}),i.data===void 0?null:(0,W.jsxs)(`p`,{className:`text-meta`,children:[`As `,i.data.cli,` on `,i.data.runner,` lists them, where this citizen's turns run.`]}),(0,W.jsx)(F,{error:p.error})]})}var $=``;function Fe(e,t){let n=t.cli;return[e.status,e.clis.length===0?`offers no CLI yet`:e.clis.join(`, `),n!==null&&e.clis.length>0&&!e.clis.includes(n)?`has no ${n}`:``,e.capabilities.length===0?``:e.capabilities.join(`, `)].filter(e=>e!==``).join(` · `)}function Ie(e,t){return[{value:$,name:`Any runner`,id:null,description:`Pinned to the least busy runner on its next turn outside a project.`},...e.map(e=>({value:e.name,name:e.name,id:e.os,description:Fe(e,t)}))]}function Le({member:e,onDone:t}){let{api:n}=h(),r=S(),a=i(),o=e.homeRunner??$,[s,c]=(0,U.useState)(o),l=E({mutationFn:()=>n.setRunner(e.name,s===$?null:s),onSuccess:()=>{r.invalidateQueries({queryKey:[`members`]}),t()}});return(0,W.jsxs)(`form`,{"aria-label":`Runner of ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),l.mutate()},children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[a.data===void 0?(0,W.jsx)(`p`,{className:`min-w-0 flex-1 truncate text-meta`,children:`Reading the runners…`}):(0,W.jsx)(H,{label:`Runner`,choices:Ie(a.data,e),value:s,onChange:c}),(0,W.jsx)(T,{onClick:t,children:`Cancel`}),(0,W.jsx)(T,{variant:`primary`,type:`submit`,disabled:l.isPending||s===o,children:l.isPending?`Saving…`:`Run here`})]}),(0,W.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,W.jsx)(F,{error:l.error})]})}function Re(e){if(e.thread!==void 0)return{threadId:e.thread};let t=e.scope===`society`?null:e.scope;return e.channel===void 0?{channel:e.askedIn??r(t,`general`)}:{channel:r(t,e.channel)}}function ze({name:e,turn:t}){let{api:n}=h(),r=S(),[i,a]=(0,U.useState)(!1),o=E({mutationFn:()=>n.stopTurn(t.turnId),onSuccess:()=>{a(!1),r.invalidateQueries({queryKey:[`scheduler`]})}});return(0,W.jsxs)(`div`,{className:`border-t border-line`,children:[(0,W.jsx)(ne,{target:Re(t),initialText:`@${e} `,placeholder:t.steerable?`Message ${e} while it works`:`Message ${e} for its next turn`,className:`px-3 pt-3 pb-2`},t.turnId),t.stoppable?(0,W.jsxs)(`div`,{className:`flex items-center gap-2 px-3 pb-3`,children:[(0,W.jsx)(`p`,{className:`min-w-0 flex-1 text-[11px] leading-snug text-fg-muted`,children:i?`Ends the turn now. What it was shown counts as read; its stages stay held.`:t.steerable?`Posts reach the turn at its next step.`:`This runner delivers posts after the turn ends.`}),i?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(T,{onClick:()=>{a(!1),o.reset()},children:`Keep it running`}),(0,W.jsx)(T,{variant:`primary`,disabled:o.isPending,onClick:()=>{o.mutate()},children:o.isPending?`Stopping…`:`Stop the turn`})]}):(0,W.jsx)(T,{onClick:()=>a(!0),children:`Stop…`})]}):null,o.error===null?null:(0,W.jsx)(`div`,{className:`px-3 pb-3`,children:(0,W.jsx)(F,{error:o.error})})]})}function Be({member:e,scopes:t,preferred:n,running:r,paused:i,onDone:a}){let{api:o}=h(),s=S(),[c,l]=(0,U.useState)(`manual`),[u,d]=(0,U.useState)(n!==null&&t.includes(n)?n:t[0]??``),[f,p]=(0,U.useState)(``),m=(0,U.useRef)(null);(0,U.useEffect)(()=>m.current?.focus(),[]);let g=E({mutationFn:()=>o.wake({agent:e.name,project:u,kind:c,...f.trim()===``?{}:{reason:f.trim()}}),onSuccess:()=>{s.invalidateQueries({queryKey:[`scheduler`]}),a()}}),_=R(u),v=c===`reflection`?`Asks ${e.name} to reflect at ${_}: consolidate its memory, skills, and profile, and take no new work. It restarts the reflection clock.`:`Starts a turn for ${e.name} at ${_} as soon as the scheduler takes it.`,y=i?` The society is paused, so it waits until you resume.`:r.includes(u)?` ${e.name} is in a turn there now; this one follows it.`:``;return(0,W.jsxs)(`form`,{"aria-label":`Wake ${e.name}`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),g.mutate()},children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsxs)(`fieldset`,{className:`flex gap-1`,children:[(0,W.jsx)(`legend`,{className:`sr-only`,children:`Kind of turn`}),[`manual`,`reflection`].map(e=>(0,W.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 ${c===e?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:[(0,W.jsx)(`input`,{type:`radio`,name:`kind`,value:e,checked:c===e,onChange:()=>l(e),className:`sr-only`}),e===`manual`?`A turn`:`A reflection`]},e))]}),(0,W.jsxs)(`div`,{className:`ml-auto flex w-52 items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`shrink-0 text-xs text-fg-tertiary`,children:`at`}),(0,W.jsx)(H,{label:`Where`,choices:de(t),value:u,onChange:d})]})]}),(0,W.jsx)(`textarea`,{ref:m,value:f,rows:2,placeholder:c===`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=>p(e.target.value),className:`${se} resize-none`}),(0,W.jsxs)(`p`,{className:`text-[11px] leading-relaxed text-fg-muted`,children:[v,y,` Each turn costs money.`]}),(0,W.jsxs)(`div`,{className:`flex items-center justify-end gap-2`,children:[(0,W.jsx)(T,{onClick:a,children:`Cancel`}),(0,W.jsx)(T,{variant:`primary`,type:`submit`,disabled:g.isPending||u===``,children:g.isPending?`Waking…`:c===`reflection`?`Ask for a reflection`:`Wake ${e.name}`})]}),(0,W.jsx)(F,{error:g.error})]})}var Ve={working:`bg-emerald-500/15 text-emerald-300`,queued:`bg-amber-500/15 text-amber-300`,idle:`bg-surface-2 text-fg-tertiary`};function He({project:e,name:t}){let n=(o(e).data??[]).filter(e=>e.status===`claimed`&&e.claimedBy===t);return n.length===0?null:(0,W.jsx)(`ul`,{className:`mt-1.5 space-y-1`,children:n.map(e=>(0,W.jsx)(`li`,{children:(0,W.jsxs)(D,{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,W.jsx)(`span`,{"aria-hidden":`true`,className:`text-fg-muted`,children:`◇`}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.title}),(0,W.jsx)(`span`,{className:`max-w-[40%] shrink-0 truncate font-mono text-[11px] text-fg-muted`,children:m(e)?.name??e.stage})]})},e.id))})}function Ue(){let{name:e}=re({from:`/citizen/$name`}),{scope:t,tab:n,turn:r}=O({from:`/citizen/$name`});return(0,W.jsx)(Ge,{name:e,chosen:t??null,tab:n??`now`,turn:r??null},e)}var We=[{tab:`now`,label:`Now`},{tab:`turns`,label:`Turns`},{tab:`memory`,label:`Memory`},{tab:`history`,label:`History`}];function Ge({name:e,chosen:t,tab:r,turn:i}){let o=l(),c=s(),u=n(),d=M(),f=g(),[p,m]=(0,U.useState)(null),h=o.data?.find(t=>t.name===e);if(h===void 0)return(0,W.jsx)(L,{children:o.data===void 0?`Reading the roster…`:`There is no citizen ${e}.`});let _=a(u.data?.running??[]).filter(t=>t.agent===e),v=[...new Set(_.map(e=>e.scope))],y=_.map(e=>ae(e.agent,e.scope,e)),b=a(u.data?.pending??[]).find(t=>t.agent===e),x=v.length>0?`working`:b===void 0?`idle`:`queued`,S=P(d,e)[0],C=S?.model??h.lastModel,w=C??h.model??`CLI default`,E=h.model!==void 0&&h.model!==C?h.model:null,O=c.data?.find(e=>e.name===h.role),k=fe(h),A=h.status===`active`&&h.cli!==null,j=(f.data??[]).filter(t=>t.agent===e&&t.ended===void 0).length;return(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(ce,{leading:h.cli===null?null:(0,W.jsx)(`span`,{className:`grid size-9 shrink-0 place-items-center rounded-lg bg-surface-2/70`,children:(0,W.jsx)(ee,{cli:h.cli,size:20})}),title:e,subtitle:(0,W.jsxs)(W.Fragment,{children:[h.role,` · `,w,E===null?``:` · set to ${E}`,h.effort===void 0?``:` · ${h.effort} effort`,h.homeRunner===void 0?``:` · on ${h.homeRunner}`,h.status===`retired`?` · retired`:``]}),trailing:(0,W.jsxs)(W.Fragment,{children:[j===0?null:(0,W.jsx)(D,{to:`/crons`,search:{agent:e},className:`inline-flex h-7 shrink-0 items-center rounded-md px-3 text-xs text-fg-tertiary transition-colors hover:bg-surface-2/70 hover:text-fg-primary focus-visible:ring-2 focus-visible:ring-fg-primary/30 focus-visible:outline-none`,children:j===1?`1 cron`:`${j} crons`}),A&&p===null?(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(T,{onClick:()=>m(`model`),children:`Model…`}),(0,W.jsx)(T,{onClick:()=>m(`runner`),children:`Runner…`}),(0,W.jsx)(T,{onClick:()=>m(`wake`),children:`Wake…`})]}):null,(0,W.jsx)(`span`,{className:`shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium ${Ve[x]}`,children:x})]})}),p===`wake`?(0,W.jsx)(Be,{member:h,scopes:k,preferred:t?.split(`/`)[0]??S?.scope??null,running:v,paused:u.data?.paused??!1,onDone:()=>m(null)}):p===`model`?(0,W.jsx)(Pe,{member:h,onDone:()=>m(null)}):p===`runner`?(0,W.jsx)(Le,{member:h,onDone:()=>m(null)}):null,(0,W.jsx)(`nav`,{"aria-label":`Citizen views`,className:`flex gap-1 border-b border-line px-3 py-2`,children:We.map(n=>(0,W.jsx)(D,{to:`/citizen/$name`,params:{name:e},search:{...t===null?{}:{scope:t},...n.tab===`now`?{}:{tab:n.tab}},replace:!0,"aria-current":n.tab===r?`page`:void 0,className:`rounded-md px-2.5 py-1 text-xs transition-colors ${n.tab===r?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:n.label},n.tab))}),r===`turns`?(0,W.jsx)(je,{name:e,opened:i},i):r===`memory`?(0,W.jsx)(De,{member:h,charter:O}):r===`history`?(0,W.jsx)(Ee,{name:e}):(0,W.jsx)(qe,{name:e,chosen:t,lastTurnAt:h.lastTurnAt,state:x,runningScopes:v,runningKeys:y,runningTurns:(u.data?.turns??[]).filter(t=>t.agent===e),queuedScope:b?.scope??null})]})}function Ke(e){return e.toSorted((e,t)=>e.startedAt.localeCompare(t.startedAt))[0]}function qe({name:t,chosen:n,lastTurnAt:r,state:i,runningScopes:a,runningKeys:o,runningTurns:s,queuedScope:c}){let l=M(),u=d(5e3),{ref:f,onScroll:p}=le(),m=P(l,t),h=e(t,1),g=Oe(t,m.length===0?h.data?.at(-1):void 0),_=oe(),v=e=>e.end===null&&o.includes(ae(e.agent,e.scope,e)),y=n?.split(`/`)[0]??null,x=(n?.includes(`/`)===!0?m.find(e=>A(e)===n):void 0)??Ke(m.filter(e=>e.scope===y&&v(e)))??m.find(e=>A(e)===n)??Ke(m.filter(v))??m[0]??g.turn,S=e=>e.thread===void 0?e.channel===void 0?R(e.scope):`${R(e.scope)} · #${e.channel}`:`${R(e.scope)} · ${_.get(e.thread)?.title??`a thread`}`,C=x!==void 0&&v(x),w=x?.scope??a[0]??c,T=(x===void 0?void 0:s.find(e=>e.scope===x.scope&&e.thread===x.thread&&e.channel===x.channel))??(C?void 0:s[0]);return(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`section`,{className:`border-b border-line px-4 py-3 text-xs text-fg-tertiary`,children:[(0,W.jsx)(`p`,{children:C?`In a turn at ${R(x.scope)} for ${x.fromStart?``:`at least `}${N(x.startedAt,u)}`:a.length>0?`In a turn at ${a.map(R).join(` and `)}`:c===null?r===void 0?`No turns yet`:`Last turn ${b(r,u)}`:`Queued for a turn at ${R(c)}`}),w===null||w===`society`?null:(0,W.jsx)(He,{project:w,name:t})]}),(0,W.jsx)(`div`,{ref:f,onScroll:p,className:`flex-1 overflow-y-auto px-4 py-3`,children:x===void 0?(0,W.jsx)(L,{children:i===`working`?`The turn has not reported a step yet.`:g.loading?`Reading the last turn…`:r===void 0?`${t} has not taken a turn yet.`:`${t}'s last turn kept no steps; Turns lists every finished one.`}):(0,W.jsxs)(W.Fragment,{children:[m.length>1?(0,W.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(e=>(0,W.jsxs)(D,{to:`/citizen/$name`,params:{name:t},search:{scope:A(e)},replace:!0,"aria-current":e===x?`true`:void 0,className:`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-[11px] transition-colors ${e===x?`bg-surface-2 text-fg-primary`:`text-fg-tertiary hover:bg-surface-2/60 hover:text-fg-primary`}`,children:[v(e)?(0,W.jsx)(`span`,{className:`size-1.5 animate-pulse rounded-full bg-emerald-400`}):null,S(e)]},A(e)))}):null,(0,W.jsxs)(`p`,{className:`text-caps`,children:[C?`This turn`:`Last turn`,` · `,S(x),` · started`,` `,x.fromStart?G(x.startedAt):`before the earliest step shown`]}),x.fromStart?null:(0,W.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,W.jsx)(q,{steps:x.steps}),(0,W.jsx)(_e,{turn:x,running:C,now:u})]})}),T===void 0?null:(0,W.jsx)(ze,{name:t,turn:T})]})}export{Ue as CitizenView};
|