pi-roundtable 0.1.0 → 0.2.1

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 (239) hide show
  1. package/CHANGELOG.md +148 -0
  2. package/README.md +10 -6
  3. package/README.zh-TW.md +144 -0
  4. package/docs/plugins.md +1448 -66
  5. package/examples/echo-runtime.test.ts +122 -0
  6. package/examples/echo-runtime.ts +107 -0
  7. package/examples/events.test.ts +1 -0
  8. package/examples/events.ts +2 -2
  9. package/examples/fake-surface.test.ts +180 -0
  10. package/examples/fake-surface.ts +109 -0
  11. package/examples/interactions.test.ts +12 -3
  12. package/examples/interactions.ts +19 -19
  13. package/examples/shared-services.test.ts +74 -0
  14. package/examples/shared-services.ts +60 -0
  15. package/examples/study-room.test.ts +69 -0
  16. package/examples/study-room.ts +52 -0
  17. package/examples/support-desk.test.ts +34 -0
  18. package/examples/support-desk.ts +40 -0
  19. package/package.json +11 -3
  20. package/src/cli/checks/database.ts +11 -30
  21. package/src/cli/checks/images.ts +19 -0
  22. package/src/cli/doctor.ts +6 -0
  23. package/src/cli/main.ts +2 -1
  24. package/src/core/agents/agent-claim.ts +42 -16
  25. package/src/core/agents/agent-messages.ts +4 -4
  26. package/src/core/agents/agent-ports.ts +8 -21
  27. package/src/core/agents/agent-prompt.ts +3 -1
  28. package/src/core/agents/agent-store.ts +6 -4
  29. package/src/core/agents/agent-team-fixture.ts +389 -0
  30. package/src/core/agents/agent-team.ts +26 -25
  31. package/src/core/agents/agent-tools.ts +34 -15
  32. package/src/core/agents/avatar-studio.ts +40 -6
  33. package/src/core/agents/fallback-avatar.ts +85 -0
  34. package/src/core/agents/team-editing.ts +49 -10
  35. package/src/core/agents/team-keys.ts +22 -9
  36. package/src/core/agents/team-layout.ts +4 -3
  37. package/src/core/agents/team-lifecycle.ts +28 -2
  38. package/src/core/agents/team-options.ts +9 -5
  39. package/src/core/agents/team-status.ts +4 -4
  40. package/src/core/agents/team-text.ts +8 -6
  41. package/src/core/agents/team-turn-types.ts +4 -4
  42. package/src/core/agents/team-turns.ts +6 -5
  43. package/src/core/builtin/agent-server.ts +187 -121
  44. package/src/core/builtin/discord-admin.ts +41 -0
  45. package/src/core/builtin/discord.ts +65 -40
  46. package/src/core/builtin/modules.ts +67 -58
  47. package/src/core/builtin/session-tool.ts +24 -0
  48. package/src/core/builtin/skills.ts +72 -0
  49. package/src/core/builtin/stores.ts +55 -31
  50. package/src/core/config/config.ts +45 -4
  51. package/src/core/config/schema.ts +6 -0
  52. package/src/core/contract/channels.ts +54 -14
  53. package/src/core/contract/providers.ts +17 -0
  54. package/src/core/contract/runtime.ts +138 -0
  55. package/src/core/contract/services.ts +45 -0
  56. package/src/core/contract/surface.ts +88 -0
  57. package/src/core/db/migrations.ts +118 -3
  58. package/src/core/define-roundtable.ts +70 -46
  59. package/src/core/define.ts +2 -1
  60. package/src/core/discord/agent-commands.ts +39 -14
  61. package/src/core/discord/agent-panel.ts +66 -0
  62. package/src/core/discord/channel-executor.ts +6 -3
  63. package/src/core/discord/channel-operations.ts +14 -11
  64. package/src/core/discord/command-collection.ts +46 -0
  65. package/src/core/{registry/interactions.ts → discord/compose-commands.ts} +5 -5
  66. package/src/core/discord/connection.ts +35 -0
  67. package/src/core/discord/discord-surface.ts +32 -94
  68. package/src/core/discord/dispatch-threads.ts +2 -2
  69. package/src/core/discord/inbound-message.ts +99 -0
  70. package/src/core/discord/interaction-module.ts +57 -1
  71. package/src/core/discord/owner-cards.ts +4 -4
  72. package/src/core/discord/owner-command.ts +44 -11
  73. package/src/core/discord/owner-discord.ts +2 -2
  74. package/src/core/discord/schedule-commands.ts +21 -18
  75. package/src/core/discord/stop-button.ts +44 -1
  76. package/src/core/domain/attachment.ts +12 -8
  77. package/src/core/domain/conversation.ts +3 -4
  78. package/src/core/domain/owner-prompts.ts +5 -5
  79. package/src/core/domain/ports.ts +9 -53
  80. package/src/core/freeze.ts +9 -0
  81. package/src/core/host.ts +255 -82
  82. package/src/core/http/listeners.ts +55 -20
  83. package/src/core/i18n/agent-panel.ts +4 -0
  84. package/src/core/i18n/index.ts +12 -2
  85. package/src/core/i18n/owner.ts +7 -1
  86. package/src/core/i18n/schedules.ts +12 -6
  87. package/src/core/identity.ts +1 -1
  88. package/src/core/judging/effort-judge.ts +25 -3
  89. package/src/core/log.ts +21 -3
  90. package/src/core/models.ts +2 -2
  91. package/src/core/modules/background/background-turns.ts +6 -4
  92. package/src/core/modules/delegation/delegate.ts +3 -2
  93. package/src/core/modules/delegation/delegator.ts +15 -13
  94. package/src/core/modules/delegation/{sol-worker.ts → web-research-worker.ts} +6 -6
  95. package/src/core/modules/discord-admin/discord-admin.ts +6 -6
  96. package/src/core/modules/host-shell/shell-policy.ts +8 -3
  97. package/src/core/modules/memory/owner-memory-store.ts +27 -25
  98. package/src/core/modules/memory/owner-memory.ts +9 -13
  99. package/src/core/modules/schedules/recurrence.ts +5 -3
  100. package/src/core/modules/schedules/schedule-store.ts +11 -11
  101. package/src/core/modules/schedules/schedule-tools.ts +22 -20
  102. package/src/core/modules/schedules/scheduler.ts +7 -2
  103. package/src/core/modules/schedules/schedules.ts +9 -3
  104. package/src/core/modules/skills/skill-registry.ts +3 -2
  105. package/src/core/modules/skills/skill-store.ts +2 -15
  106. package/src/core/modules/skills/skill-tools.ts +10 -4
  107. package/src/core/ops/error-reporter.ts +1 -1
  108. package/src/core/plugin.ts +232 -28
  109. package/src/core/registry/contributions.ts +173 -14
  110. package/src/core/registry/providers.ts +35 -5
  111. package/src/core/registry/services.ts +229 -0
  112. package/src/core/routing/channel-queue.ts +5 -0
  113. package/src/core/routing/channel-router.ts +21 -7
  114. package/src/core/routing/conversation-turns.ts +139 -0
  115. package/src/core/routing/message-text.ts +9 -2
  116. package/src/core/routing/surface-port.ts +39 -0
  117. package/src/core/runtime/conversation-sessions.ts +4 -3
  118. package/src/core/runtime/extensions/confirmation-fixture.ts +11 -0
  119. package/src/core/runtime/extensions/confirmation-gate.ts +11 -9
  120. package/src/core/runtime/mcp.ts +1 -1
  121. package/src/core/runtime/pending-confirmation-store.ts +10 -12
  122. package/src/core/runtime/pi-agent-runtime.ts +9 -6
  123. package/src/core/runtime/prompt-slot.ts +8 -3
  124. package/src/core/runtime/runtime-types.ts +9 -35
  125. package/src/core/runtime/session-factory.ts +21 -5
  126. package/src/core/runtime/text-tools.ts +1 -3
  127. package/src/core/services.ts +238 -90
  128. package/src/core/sessions.ts +3 -2
  129. package/src/core/shared/{profile-tools.ts → active-tools.ts} +2 -2
  130. package/src/core/shared/delegate-tool.ts +4 -3
  131. package/src/core/shared/schedule-tools.ts +22 -13
  132. package/src/core/shared/session-messages.ts +1 -1
  133. package/src/core/speakers.ts +6 -38
  134. package/src/core/testing/database.ts +1 -7
  135. package/src/core/testing/eager-catalog.ts +30 -0
  136. package/src/core/testing/locale.ts +23 -5
  137. package/src/core/testing/modules.ts +105 -41
  138. package/src/core/testing/test-host.ts +279 -0
  139. package/src/core/testing/tool-set.ts +64 -0
  140. package/src/core/time.ts +6 -1
  141. package/src/core/tool-set.snapshot.json +288 -0
  142. package/src/core/tool-tiers.ts +17 -57
  143. package/src/discord/index.ts +64 -0
  144. package/src/index.ts +181 -10
  145. package/src/kit/channels.ts +14 -0
  146. package/src/kit/domain.ts +18 -0
  147. package/src/kit/holds.ts +4 -0
  148. package/src/kit/index.ts +129 -0
  149. package/src/kit/judging.ts +10 -0
  150. package/src/kit/memory.ts +3 -0
  151. package/src/kit/mirror.ts +19 -0
  152. package/src/kit/presentation.ts +7 -0
  153. package/src/kit/shell.ts +7 -0
  154. package/src/kit/skills.ts +8 -0
  155. package/src/kit/support.ts +21 -0
  156. package/src/kit/threads.ts +7 -0
  157. package/src/kit/tools.ts +14 -0
  158. package/src/kit/worker.ts +16 -0
  159. package/src/testing.ts +394 -34
  160. package/examples/guide.test.ts +0 -52
  161. package/src/cli/add-plugin.test.ts +0 -107
  162. package/src/cli/checks/basic.test.ts +0 -276
  163. package/src/cli/checks/database.test.ts +0 -117
  164. package/src/cli/checks/discord.test.ts +0 -200
  165. package/src/cli/cli.test.ts +0 -122
  166. package/src/cli/config-edit.test.ts +0 -130
  167. package/src/cli/doctor.test.ts +0 -184
  168. package/src/cli/init.test.ts +0 -127
  169. package/src/cli/size.test.ts +0 -9
  170. package/src/cli/templates.test.ts +0 -129
  171. package/src/cli/testing/fixtures.ts +0 -106
  172. package/src/core/agents/agent-claim.test.ts +0 -142
  173. package/src/core/agents/agent-dashboard.test.ts +0 -120
  174. package/src/core/agents/agent-guild.test.ts +0 -124
  175. package/src/core/agents/agent-store.test.ts +0 -205
  176. package/src/core/agents/avatar-studio.test.ts +0 -88
  177. package/src/core/agents/group-round.test.ts +0 -143
  178. package/src/core/agents/owner-identity.test.ts +0 -172
  179. package/src/core/agents/team-turns.test.ts +0 -278
  180. package/src/core/attachments/attachments.test.ts +0 -85
  181. package/src/core/boundary.test.ts +0 -45
  182. package/src/core/builtin/modules.test.ts +0 -127
  183. package/src/core/config/config.test.ts +0 -135
  184. package/src/core/contract/discord.ts +0 -33
  185. package/src/core/db/migrations.test.ts +0 -237
  186. package/src/core/define-roundtable.test.ts +0 -134
  187. package/src/core/define.test.ts +0 -144
  188. package/src/core/discord/agent-commands.test.ts +0 -58
  189. package/src/core/discord/agent-discord.test.ts +0 -70
  190. package/src/core/discord/dispatch-thread-host.test.ts +0 -114
  191. package/src/core/discord/dispatch-threads.test.ts +0 -94
  192. package/src/core/discord/owner-cards.test.ts +0 -435
  193. package/src/core/discord/owner-discord.test.ts +0 -325
  194. package/src/core/domain/expression.ts +0 -21
  195. package/src/core/domain/profile.ts +0 -32
  196. package/src/core/drain.test.ts +0 -46
  197. package/src/core/events.test.ts +0 -81
  198. package/src/core/holds.test.ts +0 -54
  199. package/src/core/host.test.ts +0 -536
  200. package/src/core/http/listeners.test.ts +0 -164
  201. package/src/core/i18n/i18n.test.ts +0 -139
  202. package/src/core/identity.test.ts +0 -18
  203. package/src/core/judging/effort-judge.test.ts +0 -112
  204. package/src/core/judging/model-judge.test.ts +0 -126
  205. package/src/core/modules/delegation/delegator.test.ts +0 -170
  206. package/src/core/modules/memory/owner-memory-store.test.ts +0 -244
  207. package/src/core/modules/schedules/schedule.test.ts +0 -358
  208. package/src/core/modules/skills/skill-kind.test.ts +0 -55
  209. package/src/core/modules/skills/skill-registry.test.ts +0 -376
  210. package/src/core/ops/error-reporter.test.ts +0 -283
  211. package/src/core/presentation/card-cadence.ts +0 -41
  212. package/src/core/presentation/presentation.test.ts +0 -166
  213. package/src/core/public-entry.test.ts +0 -59
  214. package/src/core/registry/contributions.test.ts +0 -215
  215. package/src/core/registry/interactions.test.ts +0 -87
  216. package/src/core/registry/providers.test.ts +0 -103
  217. package/src/core/routing/channel-queue.test.ts +0 -31
  218. package/src/core/routing/channel-router.test.ts +0 -326
  219. package/src/core/routing/conversation-kind.ts +0 -14
  220. package/src/core/routing/settle-turn.test.ts +0 -21
  221. package/src/core/runtime/compaction-tiers.test.ts +0 -227
  222. package/src/core/runtime/extensions/ask-user.test.ts +0 -114
  223. package/src/core/runtime/extensions/self-compact-guard.test.ts +0 -50
  224. package/src/core/runtime/pending-confirmation-store.test.ts +0 -52
  225. package/src/core/runtime/session-archive.test.ts +0 -20
  226. package/src/core/runtime/steerable-run.test.ts +0 -264
  227. package/src/core/runtime/text-tools.test.ts +0 -110
  228. package/src/core/runtime/turn-answer.test.ts +0 -72
  229. package/src/core/runtime/worker-task.test.ts +0 -82
  230. package/src/core/services.test.ts +0 -28
  231. package/src/core/sessions.test.ts +0 -85
  232. package/src/core/shared/unix-server.ts +0 -18
  233. package/src/core/size.test.ts +0 -9
  234. package/src/core/speakers.test.ts +0 -78
  235. package/src/core/testing/file-size.ts +0 -34
  236. package/src/core/time.test.ts +0 -166
  237. package/src/core/tool-tiers.test.ts +0 -117
  238. package/src/entries.test.ts +0 -112
  239. package/src/testing.test.ts +0 -156
@@ -2,7 +2,10 @@ import { ScheduleError } from "../../domain/errors.ts";
2
2
  import { messages } from "../../i18n/index.ts";
3
3
  import { timeZone, zonedDate, zonedInstant, zonedStamp } from "../../time.ts";
4
4
 
5
- export const WEEKDAYS = [
5
+ export type Weekday = "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat";
6
+
7
+ /** In the order of `Date#getUTCDay`. */
8
+ const WEEKDAYS: readonly Weekday[] = [
6
9
  "sun",
7
10
  "mon",
8
11
  "tue",
@@ -10,8 +13,7 @@ export const WEEKDAYS = [
10
13
  "thu",
11
14
  "fri",
12
15
  "sat",
13
- ] as const;
14
- export type Weekday = (typeof WEEKDAYS)[number];
16
+ ];
15
17
 
16
18
  /** When a schedule runs, in the configured wall-clock time. */
17
19
  export type Recurrence =
@@ -1,16 +1,15 @@
1
1
  import type { SQL } from "bun";
2
2
  import type { Migration } from "../../db/migrations.ts";
3
3
  import type { ChannelKey } from "../../domain/conversation.ts";
4
+ import type { ScheduleStore } from "../../services.ts";
4
5
  import type { Tier } from "../../speakers.ts";
5
6
  import type { Recurrence } from "./recurrence.ts";
6
7
 
7
- /** Owner schedules run the owner agent; party schedules run the channel's party role. */
8
- export type ScheduleMode = "owner" | "party";
9
-
10
8
  export interface Schedule {
11
9
  id: number;
12
10
  channel: ChannelKey;
13
- mode: ScheduleMode;
11
+ /** The name of the background target whose conversation runs it; stored in the `mode` column. */
12
+ target: string;
14
13
  title: string;
15
14
  prompt: string;
16
15
  recurrence: Recurrence;
@@ -26,7 +25,7 @@ export interface Schedule {
26
25
 
27
26
  export interface NewSchedule {
28
27
  channel: ChannelKey;
29
- mode: ScheduleMode;
28
+ target: string;
30
29
  title: string;
31
30
  prompt: string;
32
31
  recurrence: Recurrence;
@@ -46,7 +45,8 @@ export interface ScheduleChange {
46
45
  interface Row {
47
46
  id: string | number;
48
47
  channel_key: ChannelKey;
49
- mode: ScheduleMode;
48
+ /** The target's name; the column keeps the name it had before targets existed. */
49
+ mode: string;
50
50
  title: string;
51
51
  prompt: string;
52
52
  recurrence: string;
@@ -63,7 +63,7 @@ function toSchedule(row: Row): Schedule {
63
63
  return {
64
64
  id: Number(row.id),
65
65
  channel: row.channel_key,
66
- mode: row.mode,
66
+ target: row.mode,
67
67
  title: row.title,
68
68
  prompt: row.prompt,
69
69
  // pi-lens-ignore: unchecked-throwing-call — this store wrote the JSON; a corrupt row should fail loudly
@@ -79,7 +79,7 @@ function toSchedule(row: Row): Schedule {
79
79
  }
80
80
 
81
81
  /** Scheduled turns, in the database. A one-time schedule's row is deleted once it fires. */
82
- export class ScheduleStore {
82
+ export class PgScheduleStore implements ScheduleStore {
83
83
  readonly #sql: SQL;
84
84
 
85
85
  private constructor(sql: SQL) {
@@ -113,15 +113,15 @@ export class ScheduleStore {
113
113
  };
114
114
 
115
115
  /** The store over the host's migrated pool. */
116
- static async attach(sql: SQL): Promise<ScheduleStore> {
117
- return new ScheduleStore(sql);
116
+ static async attach(sql: SQL): Promise<PgScheduleStore> {
117
+ return new PgScheduleStore(sql);
118
118
  }
119
119
 
120
120
  async create(schedule: NewSchedule): Promise<Schedule> {
121
121
  const rows: Row[] = await this.#sql`
122
122
  INSERT INTO schedules (channel_key, mode, title, prompt, recurrence, next_run,
123
123
  created_by_id, created_by_name, created_tier)
124
- VALUES (${schedule.channel}, ${schedule.mode}, ${schedule.title}, ${schedule.prompt},
124
+ VALUES (${schedule.channel}, ${schedule.target}, ${schedule.title}, ${schedule.prompt},
125
125
  ${JSON.stringify(schedule.recurrence)}, ${schedule.nextRun},
126
126
  ${schedule.createdById}, ${schedule.createdByName}, ${schedule.createdTier})
127
127
  RETURNING *`;
@@ -1,6 +1,8 @@
1
+ import type { BackgroundTarget } from "../../contract/channels.ts";
1
2
  import type { ChannelKey } from "../../domain/conversation.ts";
2
3
  import { ScheduleError } from "../../domain/errors.ts";
3
4
  import { messages } from "../../i18n/index.ts";
5
+ import type { ScheduleStore } from "../../services.ts";
4
6
  import type { ScheduleToolName } from "../../shared/schedule-tools.ts";
5
7
  import { type Tier, tierAtLeast } from "../../speakers.ts";
6
8
  import { timeZone, zonedStamp } from "../../time.ts";
@@ -11,22 +13,8 @@ import {
11
13
  type Recurrence,
12
14
  type RecurrenceInput,
13
15
  } from "./recurrence.ts";
14
- import type {
15
- Schedule,
16
- ScheduleMode,
17
- ScheduleStore,
18
- } from "./schedule-store.ts";
16
+ import type { Schedule } from "./schedule-store.ts";
19
17
 
20
- /** Party channels are open to anyone, so their roles get tighter limits than the owner's agent. */
21
- export const SCHEDULE_LIMITS: Readonly<
22
- Record<
23
- ScheduleMode,
24
- { perChannel: number; promptChars: number; aheadDays: number }
25
- >
26
- > = {
27
- owner: { perChannel: 20, promptChars: 8_000, aheadDays: 366 },
28
- party: { perChannel: 5, promptChars: 2_000, aheadDays: 90 },
29
- };
30
18
  const TITLE_CHARS = 80;
31
19
  const LIST_PROMPT_PREVIEW = 200;
32
20
  const DAY_MS = 86_400_000;
@@ -37,12 +25,25 @@ export interface ScheduleToolContext {
37
25
  "create" | "get" | "forChannel" | "update" | "remove"
38
26
  >;
39
27
  channel: ChannelKey;
40
- mode: ScheduleMode;
28
+ /** Whose schedules these are; its `schedules` limits apply, and without them nothing is scheduled. */
29
+ target: BackgroundTarget;
41
30
  /** Who asked, recorded on created schedules; a scheduled run speaks for its creator. */
42
31
  author: { id: string; name: string; tier?: Tier };
43
32
  now: Date;
44
33
  }
45
34
 
35
+ /** The limits of the context's target; a target without them may not schedule. */
36
+ function limitsOf(
37
+ ctx: ScheduleToolContext,
38
+ ): NonNullable<BackgroundTarget["schedules"]> {
39
+ const { schedules } = ctx.target;
40
+ if (!schedules)
41
+ throw new ScheduleError(
42
+ `schedules are not available for ${ctx.target.name} conversations`,
43
+ );
44
+ return schedules;
45
+ }
46
+
46
47
  type Input = Record<string, unknown> & RecurrenceInput;
47
48
 
48
49
  function text(input: Input, name: string, max: number): string {
@@ -82,7 +83,7 @@ function timing(ctx: ScheduleToolContext, input: Input): [Recurrence, Date] {
82
83
  throw new ScheduleError(
83
84
  `that time has already passed; it is ${zonedStamp(ctx.now)} in ${messages().zoneName(timeZone())} now`,
84
85
  );
85
- const { aheadDays } = SCHEDULE_LIMITS[ctx.mode];
86
+ const { aheadDays } = limitsOf(ctx);
86
87
  if (next.getTime() - ctx.now.getTime() > aheadDays * DAY_MS)
87
88
  throw new ScheduleError(`the first run must be within ${aheadDays} days`);
88
89
  return [recurrence, next];
@@ -121,9 +122,10 @@ function changeable(ctx: ScheduleToolContext, schedule: Schedule): Schedule {
121
122
  export async function callScheduleTool(
122
123
  ctx: ScheduleToolContext,
123
124
  name: ScheduleToolName,
124
- input: Input,
125
+ rawInput: Record<string, unknown>,
125
126
  ): Promise<string> {
126
- const limits = SCHEDULE_LIMITS[ctx.mode];
127
+ const input = rawInput as Input;
128
+ const limits = limitsOf(ctx);
127
129
  switch (name) {
128
130
  case "schedule_create": {
129
131
  const title = text(input, "title", TITLE_CHARS);
@@ -136,7 +138,7 @@ export async function callScheduleTool(
136
138
  );
137
139
  const created = await ctx.store.create({
138
140
  channel: ctx.channel,
139
- mode: ctx.mode,
141
+ target: ctx.target.name,
140
142
  title,
141
143
  prompt,
142
144
  recurrence,
@@ -1,7 +1,8 @@
1
1
  import type { ScheduledOutcome } from "../../contract/channels.ts";
2
2
  import type { Logger } from "../../log.ts";
3
+ import type { ScheduleStore } from "../../services.ts";
3
4
  import { nextRun } from "./recurrence.ts";
4
- import type { Schedule, ScheduleStore } from "./schedule-store.ts";
5
+ import type { Schedule } from "./schedule-store.ts";
5
6
 
6
7
  export type { ScheduledOutcome };
7
8
 
@@ -104,7 +105,11 @@ export class Scheduler {
104
105
  async #fire(schedule: Schedule, firedAt: Date): Promise<void> {
105
106
  const { store, runner, logger } = this.#options;
106
107
  logger.info(
107
- { schedule: schedule.id, channel: schedule.channel, mode: schedule.mode },
108
+ {
109
+ schedule: schedule.id,
110
+ channel: schedule.channel,
111
+ target: schedule.target,
112
+ },
108
113
  "schedule firing",
109
114
  );
110
115
  const outcome = await runner.runScheduled(schedule, firedAt);
@@ -1,18 +1,21 @@
1
1
  import type { ExtensionFactory } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
+ import { OWNER_TARGET } from "../../agents/agent-claim.ts";
3
4
  import type { ChannelKey } from "../../domain/conversation.ts";
4
5
  import { ScheduleError } from "../../domain/errors.ts";
6
+ import { activeLocale } from "../../i18n/index.ts";
5
7
  import type { OwnerIdentity } from "../../identity.ts";
6
8
  import {
7
9
  type ToolInput,
8
10
  textToolsExtension,
9
11
  } from "../../runtime/text-tools.ts";
12
+ import type { ScheduleStore } from "../../services.ts";
10
13
  import {
11
14
  type ScheduleToolSpec,
12
15
  scheduleToolSpecs,
13
16
  } from "../../shared/schedule-tools.ts";
14
17
  import type { Speaker } from "../../speakers.ts";
15
- import type { ScheduleStore } from "./schedule-store.ts";
18
+ import { timeZone } from "../../time.ts";
16
19
  import { callScheduleTool } from "./schedule-tools.ts";
17
20
 
18
21
  export interface OwnerSchedules {
@@ -56,7 +59,10 @@ export function schedulesExtension(
56
59
  speaker: () => Speaker | undefined = () => undefined,
57
60
  ): ExtensionFactory {
58
61
  const { store, owner, channelFor } = schedules;
59
- const defs = scheduleToolSpecs().map((base) => {
62
+ const defs = scheduleToolSpecs({
63
+ locale: activeLocale(),
64
+ timeZone: timeZone(),
65
+ }).map((base) => {
60
66
  const spec = agents ? withAgentOption(base) : base;
61
67
  return {
62
68
  ...spec,
@@ -70,7 +76,7 @@ export function schedulesExtension(
70
76
  {
71
77
  store,
72
78
  channel: target,
73
- mode: "owner",
79
+ target: OWNER_TARGET,
74
80
  author: speaker() ?? owner,
75
81
  now: new Date(),
76
82
  },
@@ -1,6 +1,7 @@
1
1
  import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { AgentError } from "../../domain/errors.ts";
4
+ import type { SkillRegistry } from "../../services.ts";
4
5
  import { planLinkedSkills } from "./skill-link.ts";
5
6
  import { skillCatalog, skillListText } from "./skill-listing.ts";
6
7
  import {
@@ -28,8 +29,8 @@ export {
28
29
  type SkillSource,
29
30
  } from "./skill-rules.ts";
30
31
 
31
- /** The skill registry and what each agent carries (repos-and-skills spec behaviors 13–22). */
32
- export class SkillRegistry {
32
+ /** The skill registry and what each agent carries. */
33
+ export class StoredSkillRegistry implements SkillRegistry {
33
34
  readonly #options: SkillRegistryOptions;
34
35
 
35
36
  constructor(options: SkillRegistryOptions) {
@@ -4,7 +4,7 @@ import type { Migration } from "../../db/migrations.ts";
4
4
  import { AgentError } from "../../domain/errors.ts";
5
5
 
6
6
  /**
7
- * A registered skill (repos-and-skills spec behavior 13). A linked skill's name and description
7
+ * A registered skill. A linked skill's name and description
8
8
  * live in its repository's file; an agent-written one keeps them here.
9
9
  */
10
10
  export type SkillEntry =
@@ -17,7 +17,7 @@ export interface SkillGroup {
17
17
  skills: string[];
18
18
  }
19
19
 
20
- /** Who lost a removed skill (behavior 17). */
20
+ /** Who lost a removed skill. */
21
21
  export interface Detached {
22
22
  agents: string[];
23
23
  groups: string[];
@@ -59,12 +59,6 @@ const toGroup = (row: GroupRow): SkillGroup => ({
59
59
  skills: row.skills.split(",").filter(Boolean),
60
60
  });
61
61
 
62
- /**
63
- * The kind an agent-written skill was stored under before it became 'written': the first
64
- * consumer's own name, spelled from parts so the public tree names no consumer.
65
- */
66
- export const LEGACY_WRITTEN_KIND = ["mer", "lin"].join("");
67
-
68
62
  /**
69
63
  * Skills, skill groups, and the skills each agent carries, in the database. All of it is
70
64
  * also held in memory, because every agent turn resolves its skills and only this process
@@ -128,13 +122,6 @@ export class SkillStore {
128
122
  { table: "agent_skills", key: ["agent", "skill"] },
129
123
  ]),
130
124
  },
131
- {
132
- // Skills an agent wrote were stored under the legacy kind; the kind is now 'written'.
133
- name: "skills-written-kind",
134
- up: async (sql) => {
135
- await sql`UPDATE skills SET kind = 'written' WHERE kind = ${LEGACY_WRITTEN_KIND}`;
136
- },
137
- },
138
125
  ];
139
126
  }
140
127
 
@@ -7,7 +7,11 @@ import {
7
7
  stringList,
8
8
  textToolsExtension,
9
9
  } from "../../runtime/text-tools.ts";
10
- import { MAX_SKILL_BODY_CHARS, type SkillRegistry } from "./skill-registry.ts";
10
+ import type { SkillRegistry } from "../../services.ts";
11
+ import {
12
+ MAX_SKILL_BODY_CHARS,
13
+ type StoredSkillRegistry,
14
+ } from "./skill-registry.ts";
11
15
 
12
16
  export const SKILL_LIST_TOOL = "skill_list";
13
17
 
@@ -43,7 +47,9 @@ const BODY = Type.String({
43
47
  });
44
48
 
45
49
  /** skill_list, for the DM and for agents. */
46
- export function skillListExtension(registry: SkillRegistry): ExtensionFactory {
50
+ export function skillListExtension(
51
+ registry: Pick<SkillRegistry, "list">,
52
+ ): ExtensionFactory {
47
53
  return textToolsExtension(
48
54
  [
49
55
  {
@@ -75,9 +81,9 @@ export function skillListExtension(registry: SkillRegistry): ExtensionFactory {
75
81
  );
76
82
  }
77
83
 
78
- /** The skill tools of an agent session (repos-and-skills spec behaviors 15–19). */
84
+ /** The skill tools of an agent session. */
79
85
  export function skillToolsExtension(
80
- registry: SkillRegistry,
86
+ registry: StoredSkillRegistry,
81
87
  /** Throws AgentError unless the name is an active agent. */
82
88
  checkAgent: (name: string) => void,
83
89
  ): ExtensionFactory {
@@ -16,7 +16,7 @@ const FIELD_LIMIT = 200;
16
16
  const STACK_FRAMES = 8;
17
17
  /** pino's own keys, and the ones the report shows apart from the context. */
18
18
  const OWN_KEYS = new Set(["level", "time", "pid", "hostname", "msg", "err"]);
19
- const HEAD_KEYS = ["app", "module"];
19
+ const HEAD_KEYS = ["app", "plugin", "module"];
20
20
  const APP_FRAME = /((?:src|shared|worker)\/[^\s():]+\.ts):(\d+)/;
21
21
 
22
22
  /** Where the reports go, known once the Discord surface and the agent team are up. */