@kubitnodes/stellaris 0.3.5 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/cli/index.js +139 -15
  2. package/dist/server/index.js +210 -31
  3. package/package.json +1 -1
  4. package/web/dist/assets/BackLink-BW0sb-M0.js +1 -0
  5. package/web/dist/assets/ChannelView-DmTE9aUA.js +1 -0
  6. package/web/dist/assets/CitizenView-lrA6vZDK.js +2 -0
  7. package/web/dist/assets/CitizensView-MRVffBnU.js +1 -0
  8. package/web/dist/assets/KnowledgeView-C2N-x5yS.js +1 -0
  9. package/web/dist/assets/{Markdown-MZnGPfvk.js → Markdown-CS3NCze-.js} +4 -4
  10. package/web/dist/assets/MessageItem-CL3XDi7l.js +1 -0
  11. package/web/dist/assets/MetricsView-CR5u5k5n.js +1 -0
  12. package/web/dist/assets/NeedsYouView-BwUvwyVt.js +1 -0
  13. package/web/dist/assets/Overview-DxFOFviB.js +1 -0
  14. package/web/dist/assets/{Pane-B-pz52UC.js → Pane-voa6GU0F.js} +1 -1
  15. package/web/dist/assets/ProjectView-BkNG_qdh.js +1 -0
  16. package/web/dist/assets/ProposalView-G89UmLF5.js +1 -0
  17. package/web/dist/assets/ProposalsView-CzpL-POB.js +1 -0
  18. package/web/dist/assets/RunnersView-SKNIDsjR.js +1 -0
  19. package/web/dist/assets/{SocietyView-DA_65uyo.js → SocietyView-CCFXEYZW.js} +1 -1
  20. package/web/dist/assets/SubjectThread-JQG2FxkA.js +1 -0
  21. package/web/dist/assets/TaskFileView-BKoGmHGz.js +4 -0
  22. package/web/dist/assets/TaskView-BIYqIFU4.js +1 -0
  23. package/web/dist/assets/TasksView-n2ssgQOL.js +1 -0
  24. package/web/dist/assets/ThreadCard-CzQXJXSd.js +1 -0
  25. package/web/dist/assets/{ThreadForms-BipMby65.js → ThreadForms-0LpUc2jJ.js} +1 -1
  26. package/web/dist/assets/ThreadView-_LgGISSH.js +1 -0
  27. package/web/dist/assets/citizen-DvJr6Ibu.js +1 -0
  28. package/web/dist/assets/format-C7bqWt6N.js +55 -0
  29. package/web/dist/assets/index-D4oCtkuZ.css +2 -0
  30. package/web/dist/assets/index-DM00hlle.js +23 -0
  31. package/web/dist/assets/{tasks-DnJj3psB.js → tasks-B4bx7Gg3.js} +1 -1
  32. package/web/dist/assets/{useStickyScroll-D_7q2RKi.js → useStickyScroll-DCsF4GYJ.js} +1 -1
  33. package/web/dist/index.html +4 -4
  34. package/web/dist/assets/BackLink-DivaHiZ7.js +0 -1
  35. package/web/dist/assets/ChannelView-DgkkiZuY.js +0 -1
  36. package/web/dist/assets/CitizenView-BzhH1ycF.js +0 -2
  37. package/web/dist/assets/CitizensView-BzGNyC2f.js +0 -1
  38. package/web/dist/assets/KnowledgeView-DedLlEZd.js +0 -1
  39. package/web/dist/assets/MessageItem-Deq-ntT8.js +0 -1
  40. package/web/dist/assets/MetricsView-C-2j71rI.js +0 -1
  41. package/web/dist/assets/NeedsYouView-D4xqHNDU.js +0 -1
  42. package/web/dist/assets/Overview-DxCYcW_A.js +0 -1
  43. package/web/dist/assets/ProjectView-BhZYFv7f.js +0 -1
  44. package/web/dist/assets/ProposalView-DAc9lEHB.js +0 -1
  45. package/web/dist/assets/ProposalsView-CmwwJuop.js +0 -1
  46. package/web/dist/assets/RunnersView-Dqo_BEoK.js +0 -1
  47. package/web/dist/assets/SubjectThread-M4F1paqV.js +0 -1
  48. package/web/dist/assets/TaskFileView-CCNVrooP.js +0 -4
  49. package/web/dist/assets/TaskView-BTSDk1yL.js +0 -1
  50. package/web/dist/assets/TasksView-0IQm6u-_.js +0 -1
  51. package/web/dist/assets/ThreadCard-BTGP4fOT.js +0 -1
  52. package/web/dist/assets/ThreadView-D96DZAOM.js +0 -1
  53. package/web/dist/assets/citizen-CYBzbWt-.js +0 -1
  54. package/web/dist/assets/format-11lojpK1.js +0 -55
  55. package/web/dist/assets/index-BXq4t0NA.js +0 -23
  56. package/web/dist/assets/index-CKjqsZME.css +0 -2
package/dist/cli/index.js CHANGED
@@ -6,7 +6,7 @@ import path7 from "node:path";
6
6
  import { Command } from "commander";
7
7
 
8
8
  // packages/board-core/dist/board.js
9
- import { readdir as readdir3, readFile as readFile5, rename as rename3, stat as stat2 } from "node:fs/promises";
9
+ import { mkdir as mkdir4, readdir as readdir3, readFile as readFile5, rename as rename3, stat as stat2 } from "node:fs/promises";
10
10
  import path6 from "node:path";
11
11
  import { decodeTime, monotonicFactory } from "ulid";
12
12
  import { z as z12 } from "zod";
@@ -56,7 +56,8 @@ var VERB_NAMES = [
56
56
  "plan_task",
57
57
  "advance_task",
58
58
  "configure_project",
59
- "archive_project"
59
+ "archive_project",
60
+ "remove_knowledge"
60
61
  ];
61
62
  var VerbNameSchema = z2.enum(VERB_NAMES);
62
63
  var CharterTriggerSchema = z2.enum(["user_post", "ops_event", "heartbeat"]);
@@ -100,6 +101,7 @@ var MEMBER_VERBS = [
100
101
  "join_project",
101
102
  "leave_project",
102
103
  "write_knowledge",
104
+ "remove_knowledge",
103
105
  "plan_task",
104
106
  "advance_task"
105
107
  ];
@@ -301,11 +303,23 @@ function mayHoldStage(member, task2) {
301
303
  return !(stage.gate && task2.stages.slice(0, index).some((s) => s.holders.includes(member.name)));
302
304
  }
303
305
  var ModelNameSchema = z3.string().trim().min(1).max(120).regex(/^[\w.:/[\]-]+$/, "a model name is one word of letters, digits, and . _ : / - [ ]");
306
+ var EffortSchema = z3.string().trim().min(1).max(32).regex(/^[a-z][a-z0-9_-]*$/, "an effort is one lowercase word, such as high");
307
+ var EffortOptionSchema = z3.object({
308
+ id: EffortSchema,
309
+ description: z3.string().default("")
310
+ });
304
311
  var ModelOptionSchema = z3.object({
305
312
  id: ModelNameSchema,
306
313
  name: z3.string(),
307
314
  description: z3.string().default(""),
308
- isDefault: z3.boolean().default(false)
315
+ isDefault: z3.boolean().default(false),
316
+ efforts: z3.array(EffortOptionSchema).default([]),
317
+ defaultEffort: EffortSchema.optional()
318
+ });
319
+ var RunnerModelsSchema = z3.object({
320
+ runner: NameSchema,
321
+ cli: CliKindSchema,
322
+ models: z3.array(ModelOptionSchema)
309
323
  });
310
324
  var AgentStatusSchema = z3.enum(["active", "retired"]);
311
325
  var AgentSchema = z3.object({
@@ -313,6 +327,8 @@ var AgentSchema = z3.object({
313
327
  role: NameSchema,
314
328
  cli: CliKindSchema.nullable(),
315
329
  model: z3.string().optional(),
330
+ /** The reasoning effort set for the agent's turns; the model's own default applies otherwise. */
331
+ effort: z3.string().optional(),
316
332
  /** The runner preferred for the agent's turns where nothing else decides; any runner with its CLI otherwise. */
317
333
  homeRunner: NameSchema.optional(),
318
334
  memberships: z3.array(NameSchema),
@@ -334,6 +350,8 @@ var MemberSchema = z3.object({
334
350
  model: z3.string().optional(),
335
351
  /** The model the CLI reported on the citizen's last turn. */
336
352
  lastModel: z3.string().optional(),
353
+ /** The reasoning effort configured on the record, if any; the model's own default applies otherwise. */
354
+ effort: z3.string().optional(),
337
355
  /** The citizen's own skills, by name. */
338
356
  skills: z3.array(NameSchema).default([]),
339
357
  memberships: z3.array(NameSchema),
@@ -523,6 +541,12 @@ var KnowledgeSchema = z3.object({
523
541
  updatedBy: NameSchema,
524
542
  updatedAt: IsoDateTimeSchema
525
543
  });
544
+ var RemovedKnowledgeSchema = z3.object({
545
+ topic: NameSchema,
546
+ project: NameSchema.nullable(),
547
+ removedBy: NameSchema,
548
+ removedAt: IsoDateTimeSchema
549
+ });
526
550
  var ProposalFrontmatterSchema = z3.object({
527
551
  id: UlidSchema,
528
552
  kind: ProposalKindSchema,
@@ -619,6 +643,11 @@ var VerbInputs = {
619
643
  topic: NameSchema,
620
644
  body: z4.string().min(1)
621
645
  }),
646
+ remove_knowledge: z4.object({
647
+ /** As for write_knowledge: a project you belong to, or null for society knowledge. */
648
+ project: NameSchema.nullable().default(null),
649
+ topic: NameSchema
650
+ }),
622
651
  plan_task: z4.object({
623
652
  task_id: UlidSchema,
624
653
  stages: z4.array(PlanEditStageSchema),
@@ -668,6 +697,7 @@ var BOARD_EVENT_TYPES = [
668
697
  "agent.joined",
669
698
  "agent.left",
670
699
  "knowledge.written",
700
+ "knowledge.removed",
671
701
  "skill.promoted",
672
702
  "runner.added",
673
703
  "user.signed_in",
@@ -845,6 +875,8 @@ var TurnJobSchema = z6.object({
845
875
  role: NameSchema,
846
876
  cli: CliKindSchema,
847
877
  model: z6.string().optional(),
878
+ /** The reasoning effort set on the agent; absent for the model's own default. */
879
+ effort: z6.string().optional(),
848
880
  /** A project slug, or the society scope. */
849
881
  scope: NameSchema,
850
882
  /** The thread whose conversation the turn is in; absent for the home conversation. */
@@ -1078,6 +1110,8 @@ var TurnHistoryEntrySchema = z7.object({
1078
1110
  trigger: z7.string(),
1079
1111
  exitReason: z7.string().nullable(),
1080
1112
  costUsd: z7.number(),
1113
+ /** The tokens the turn used; absent for turns logged before turns recorded them. */
1114
+ usage: UsageSchema.optional(),
1081
1115
  model: z7.string().nullable(),
1082
1116
  summary: z7.string().nullable(),
1083
1117
  error: z7.string().nullable(),
@@ -1261,7 +1295,7 @@ var RunnerConfigSchema = z10.object({
1261
1295
  });
1262
1296
 
1263
1297
  // packages/shared/dist/version.js
1264
- var STELLARIS_VERSION = "0.3.5";
1298
+ var STELLARIS_VERSION = "0.3.7";
1265
1299
 
1266
1300
  // packages/board-core/dist/errors.js
1267
1301
  var BoardError = class extends Error {
@@ -2294,6 +2328,10 @@ var BoardPaths = class {
2294
2328
  pausedFile() {
2295
2329
  return path5.join(this.state(), "paused.json");
2296
2330
  }
2331
+ /** Removed knowledge topics, set aside outside the projection, by scope. */
2332
+ removedKnowledge(scope) {
2333
+ return path5.join(this.state(), "removed-knowledge", scope);
2334
+ }
2297
2335
  };
2298
2336
 
2299
2337
  // packages/board-core/dist/tokens.js
@@ -2327,6 +2365,7 @@ var TurnHistoryPayloadSchema = z12.object({
2327
2365
  trigger: z12.string().default("manual"),
2328
2366
  exitReason: z12.string().nullable().default(null),
2329
2367
  costUsd: z12.number().default(0),
2368
+ usage: UsageSchema.optional(),
2330
2369
  model: z12.string().nullable().default(null),
2331
2370
  summary: z12.string().nullable().default(null),
2332
2371
  error: z12.string().nullable().default(null),
@@ -2386,6 +2425,7 @@ var OPS_CHANNEL_RETIRED = "ops-channel-retired";
2386
2425
  var DECISIONS_CHANNEL_RETIRED = "decisions-channel-retired";
2387
2426
  var THREAD_CONVERSATIONS = "thread-conversations";
2388
2427
  var ASKS_CHANNEL_OPENED = "asks-channel-opened";
2428
+ var KNOWLEDGE_REMOVAL = "knowledge-removal-granted";
2389
2429
  var PLANNING_ROLES = [USER_ROLE, "steward", "concierge"];
2390
2430
  var REALLOCATING_ROLES = [USER_ROLE, "steward", "concierge"];
2391
2431
  var PROFILE_TEMPLATE = "# Profile\n\nOne short paragraph, kept current: what I do well, what I am working on, and what to send my way. The board projects this into the roster the front desk reads.\n";
@@ -2575,7 +2615,8 @@ var Board = class _Board {
2575
2615
  OPS_CHANNEL_RETIRED,
2576
2616
  DECISIONS_CHANNEL_RETIRED,
2577
2617
  THREAD_CONVERSATIONS,
2578
- ASKS_CHANNEL_OPENED
2618
+ ASKS_CHANNEL_OPENED,
2619
+ KNOWLEDGE_REMOVAL
2579
2620
  ].filter((name) => !applied.includes(name));
2580
2621
  if (pending.length === 0) {
2581
2622
  return;
@@ -2604,8 +2645,22 @@ var Board = class _Board {
2604
2645
  if (pending.includes(ASKS_CHANNEL_OPENED)) {
2605
2646
  await this.openAsksChannel();
2606
2647
  }
2648
+ if (pending.includes(KNOWLEDGE_REMOVAL)) {
2649
+ await this.grantKnowledgeRemoval();
2650
+ }
2607
2651
  await writeJson(file, { applied: [...applied, ...pending] });
2608
2652
  }
2653
+ /**
2654
+ * Whoever may write a scope's knowledge may remove it, so every charter granting
2655
+ * `write_knowledge` is granted `remove_knowledge` once; seed roles have it from their seed.
2656
+ */
2657
+ async grantKnowledgeRemoval() {
2658
+ for (const charter of await this.listRoles()) {
2659
+ if (charter.verbs.includes("write_knowledge") && !charter.verbs.includes("remove_knowledge")) {
2660
+ await this.writeRoleUnlocked(USER_NAME, { ...charter, verbs: [...charter.verbs, "remove_knowledge"] }, { verbsAdded: ["remove_knowledge"] });
2661
+ }
2662
+ }
2663
+ }
2609
2664
  /**
2610
2665
  * A task sent back before tasks recorded it kept no trace outside the event log. A task still
2611
2666
  * short of the stage its latest `task.moved` came from is in that rework, and records it.
@@ -3837,16 +3892,7 @@ ${task2.body}`;
3837
3892
  const args = VerbInputs.write_knowledge.parse(input);
3838
3893
  await this.authorize(actor, "write_knowledge");
3839
3894
  return this.mutex.run(async () => {
3840
- if (args.project === null) {
3841
- if (!CURATING_ROLES.includes(actor.role)) {
3842
- throw new BoardError("FORBIDDEN", "society knowledge is curated by the steward and the user");
3843
- }
3844
- } else {
3845
- const project2 = await this.readActiveProject(args.project);
3846
- if (!CURATING_ROLES.includes(actor.role) && !project2.members.includes(actor.name)) {
3847
- throw new BoardError("FORBIDDEN", `${actor.name} is not a member of ${args.project}`);
3848
- }
3849
- }
3895
+ await this.assertMayCurate(actor, args.project);
3850
3896
  const data = KnowledgeSchema.parse({
3851
3897
  topic: args.topic,
3852
3898
  project: args.project,
@@ -3866,6 +3912,52 @@ ${task2.body}`;
3866
3912
  return { ...data, body: args.body };
3867
3913
  });
3868
3914
  }
3915
+ /**
3916
+ * Retires a topic, by whoever may write it. Its file leaves the knowledge directory, so no turn,
3917
+ * search, or digest finds it again, and is set aside under `state/removed-knowledge`, outside
3918
+ * the projection, for the user to restore by hand. The note in the matching general channel
3919
+ * carries no mention, as a write's does.
3920
+ */
3921
+ async removeKnowledge(actor, input) {
3922
+ const args = VerbInputs.remove_knowledge.parse(input);
3923
+ await this.authorize(actor, "remove_knowledge");
3924
+ return this.mutex.run(async () => {
3925
+ await this.assertMayCurate(actor, args.project);
3926
+ const file = args.project === null ? this.paths.societyKnowledgeFile(args.topic) : this.paths.projectKnowledgeFile(args.project, args.topic);
3927
+ if (!await exists(file)) {
3928
+ throw new BoardError("NOT_FOUND", `${args.project ?? "the society"} has no knowledge topic ${args.topic}`);
3929
+ }
3930
+ const removed = RemovedKnowledgeSchema.parse({
3931
+ topic: args.topic,
3932
+ project: args.project,
3933
+ removedBy: actor.name,
3934
+ removedAt: this.now().toISOString()
3935
+ });
3936
+ const aside = this.paths.removedKnowledge(args.project ?? SOCIETY_SCOPE);
3937
+ await mkdir4(aside, { recursive: true });
3938
+ await rename3(file, path6.join(aside, `${args.topic}.${removed.removedAt.replaceAll(":", "-")}.md`));
3939
+ await this.events.append("knowledge.removed", actor.name, {
3940
+ topic: args.topic,
3941
+ project: args.project
3942
+ });
3943
+ const where = args.project === null ? "general" : channelRef(args.project, "general");
3944
+ await this.appendMessage(actor.name, where, `Knowledge removed: ${args.topic}. It is no longer under knowledge/${args.topic}.md${args.project === null ? " of the society" : ""}.`);
3945
+ return removed;
3946
+ });
3947
+ }
3948
+ /** Society knowledge is the steward's and the user's; a project's, its members' too. */
3949
+ async assertMayCurate(actor, project2) {
3950
+ if (project2 === null) {
3951
+ if (!CURATING_ROLES.includes(actor.role)) {
3952
+ throw new BoardError("FORBIDDEN", "society knowledge is curated by the steward and the user");
3953
+ }
3954
+ return;
3955
+ }
3956
+ const active = await this.readActiveProject(project2);
3957
+ if (!CURATING_ROLES.includes(actor.role) && !active.members.includes(actor.name)) {
3958
+ throw new BoardError("FORBIDDEN", `${actor.name} is not a member of ${project2}`);
3959
+ }
3960
+ }
3869
3961
  async openThread(actor, input) {
3870
3962
  const args = VerbInputs.open_thread.parse(input);
3871
3963
  await this.authorize(actor, "open_thread");
@@ -4692,6 +4784,8 @@ ${rationale}`}`);
4692
4784
  return this.leaveProject(actor, VerbInputs.leave_project.parse(input));
4693
4785
  case "write_knowledge":
4694
4786
  return this.writeKnowledge(actor, VerbInputs.write_knowledge.parse(input));
4787
+ case "remove_knowledge":
4788
+ return this.removeKnowledge(actor, VerbInputs.remove_knowledge.parse(input));
4695
4789
  case "plan_task":
4696
4790
  return this.planTask(actor, VerbInputs.plan_task.parse(input));
4697
4791
  case "advance_task":
@@ -4930,6 +5024,7 @@ ${rationale}`}`);
4930
5024
  session: parsed.session,
4931
5025
  exitReason: parsed.exitReason,
4932
5026
  costUsd: parsed.costUsd,
5027
+ ...parsed.usage === null ? {} : { usage: parsed.usage },
4933
5028
  toolCalls: parsed.toolCalls,
4934
5029
  model: parsed.model,
4935
5030
  summary: parsed.status?.summary ?? null,
@@ -5386,6 +5481,7 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
5386
5481
  resident: charter.resident,
5387
5482
  ...agent2.model === void 0 ? {} : { model: agent2.model },
5388
5483
  ...lastModel === void 0 ? {} : { lastModel },
5484
+ ...agent2.effort === void 0 ? {} : { effort: agent2.effort },
5389
5485
  skills: (await this.listAgentSkills(name)).map((skill) => skill.name),
5390
5486
  memberships: agent2.memberships,
5391
5487
  subscriptions: agent2.subscriptions,
@@ -5434,6 +5530,29 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
5434
5530
  return next;
5435
5531
  });
5436
5532
  }
5533
+ /**
5534
+ * Sets the reasoning effort a citizen's turns run with, or clears it for the model's own default.
5535
+ * It applies from the citizen's next turn; the runner starts a warm session afresh when it changes.
5536
+ */
5537
+ async setAgentEffort(actor, name, effort) {
5538
+ this.assertUser(actor, "only the user may change a citizen's reasoning effort");
5539
+ const chosen = effort === null ? null : EffortSchema.parse(effort);
5540
+ return this.mutex.run(async () => {
5541
+ const current = await this.readAgent(name);
5542
+ if (current.status !== "active" || current.cli === null) {
5543
+ throw new BoardError("INVALID_STATE", `${name} takes no turns, so it has no effort to set`);
5544
+ }
5545
+ const { effort: previous, ...rest } = current;
5546
+ const next = await this.updateAgent(name, () => chosen === null ? rest : { ...rest, effort: chosen });
5547
+ await this.refreshMember(name);
5548
+ await this.events.append("agent.configured", actor.name, {
5549
+ agent: name,
5550
+ effort: chosen,
5551
+ previous: previous ?? null
5552
+ });
5553
+ return next;
5554
+ });
5555
+ }
5437
5556
  async updateAgent(name, mutate) {
5438
5557
  const current = await this.readAgent(name);
5439
5558
  const next = AgentSchema.parse(mutate(current));
@@ -6274,6 +6393,11 @@ agent.command("model <name> [model]").description("Set the model a member's turn
6274
6393
  const updated = await board.setAgentModel(board.userActor(), name, model ?? null);
6275
6394
  print(updated, () => `${updated.name} runs with ${updated.model ?? "its CLI's default model"} from its next turn`);
6276
6395
  });
6396
+ agent.command("effort <name> [effort]").description("Set the reasoning effort a member's turns run with, from its next turn, such as high; no effort means the model's default").action(async (name, effort) => {
6397
+ const board = await open();
6398
+ const updated = await board.setAgentEffort(board.userActor(), name, effort ?? null);
6399
+ print(updated, () => `${updated.name} runs with ${updated.effort === void 0 ? "its model's default effort" : `${updated.effort} effort`} from its next turn`);
6400
+ });
6277
6401
  agent.command("retire <name>").description("Retire a member: no more wakes, claims released, token revoked, sessions archived").requiredOption("--reason <text>", "why").action(async (name, opts) => {
6278
6402
  const board = await open();
6279
6403
  const retired = await board.retireAgent(board.userActor(), { name, reason: opts.reason });