pi-roundtable 0.33.0 → 0.35.0

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 (261) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +1 -1
  3. package/README.zh-TW.md +1 -1
  4. package/docs/plugins.md +2 -2
  5. package/package.json +1 -2
  6. package/src/cli/checks/configuration.ts +2 -2
  7. package/src/cli/checks/database.ts +2 -2
  8. package/src/cli/checks/identity.ts +1 -1
  9. package/src/cli/checks/model.ts +1 -1
  10. package/src/cli/cli.ts +2 -2
  11. package/src/cli/principal.ts +1 -1
  12. package/src/cli/project.ts +2 -2
  13. package/src/cli/runtime.ts +3 -3
  14. package/src/cli/start.ts +1 -1
  15. package/src/core/agents/agent-claim.ts +4 -4
  16. package/src/core/agents/agent-dashboard.ts +3 -3
  17. package/src/core/agents/agent-messages.ts +2 -2
  18. package/src/core/agents/agent-outbox.ts +1 -1
  19. package/src/core/agents/agent-ports.ts +1 -1
  20. package/src/core/agents/agent-prompt.ts +4 -4
  21. package/src/core/agents/agent-rules.ts +1 -1
  22. package/src/core/agents/agent-schema.ts +4 -1
  23. package/src/core/agents/agent-settings.ts +2 -2
  24. package/src/core/agents/agent-store.ts +9 -9
  25. package/src/core/agents/agent-team-fixture.ts +4 -3
  26. package/src/core/agents/agent-team.ts +12 -16
  27. package/src/core/agents/agent-tools.ts +15 -15
  28. package/src/core/agents/avatar-refresh.ts +1 -1
  29. package/src/core/agents/avatar-studio.ts +2 -2
  30. package/src/core/agents/group-round.ts +2 -2
  31. package/src/core/agents/group-turns.ts +1 -1
  32. package/src/core/agents/helper-create.ts +24 -40
  33. package/src/core/agents/helper-modes.ts +2 -2
  34. package/src/core/agents/helper-preset-ops.ts +207 -0
  35. package/src/core/agents/helper-preset-tools.ts +109 -0
  36. package/src/core/agents/helper-presets.ts +128 -0
  37. package/src/core/agents/helper-test-kit.ts +1 -1
  38. package/src/core/agents/helper-tools.ts +42 -22
  39. package/src/core/agents/helper-work.ts +1 -1
  40. package/src/core/agents/message-target.ts +1 -1
  41. package/src/core/agents/routes.ts +1 -1
  42. package/src/core/agents/team-approval.ts +2 -2
  43. package/src/core/agents/team-editing.ts +2 -2
  44. package/src/core/agents/team-keys.ts +1 -1
  45. package/src/core/agents/team-layout.ts +1 -1
  46. package/src/core/agents/team-options.ts +4 -4
  47. package/src/core/agents/team-selection.ts +1 -1
  48. package/src/core/agents/team-status.ts +1 -1
  49. package/src/core/agents/team-text.ts +3 -3
  50. package/src/core/agents/team-turn-types.ts +7 -7
  51. package/src/core/agents/team-turns.ts +3 -3
  52. package/src/core/attachments/attachment-fetcher.ts +1 -1
  53. package/src/core/attachments/attachment-port.ts +2 -2
  54. package/src/core/attachments/attachment-retention.ts +3 -3
  55. package/src/core/attachments/attachment-store.ts +2 -2
  56. package/src/core/attachments/model-images.ts +1 -1
  57. package/src/core/attachments/turn-attachments.ts +1 -1
  58. package/src/core/builtin/agent-server.ts +17 -10
  59. package/src/core/builtin/channel-context.ts +2 -2
  60. package/src/core/builtin/discord-admin.ts +2 -2
  61. package/src/core/builtin/discord.ts +4 -3
  62. package/src/core/{identity/identity-plugin.ts → builtin/identity.ts} +15 -12
  63. package/src/core/builtin/modules.ts +12 -12
  64. package/src/core/builtin/prompts.ts +3 -3
  65. package/src/core/builtin/seeds.ts +1 -1
  66. package/src/core/builtin/session-tool.ts +1 -1
  67. package/src/core/builtin/skills.ts +3 -3
  68. package/src/core/builtin/stores.ts +10 -5
  69. package/src/core/builtin/threads.ts +2 -2
  70. package/src/core/builtin/worker-sessions.ts +3 -3
  71. package/src/core/config/access.ts +3 -3
  72. package/src/core/config/adapters.ts +1 -1
  73. package/src/core/config/config-schema.ts +9 -3
  74. package/src/core/config/config.ts +9 -10
  75. package/src/core/config/ops.ts +1 -1
  76. package/src/core/config/peer-bots.ts +74 -0
  77. package/src/core/config/routing.ts +1 -1
  78. package/src/core/contract/attachments.ts +1 -1
  79. package/src/core/contract/channels.ts +3 -5
  80. package/src/core/contract/runtime.ts +6 -6
  81. package/src/core/contract/surface.ts +3 -3
  82. package/src/core/conversations/conversation-registry.ts +1 -1
  83. package/src/core/conversations/conversation-retention.ts +2 -2
  84. package/src/core/conversations/conversation-store.ts +1 -1
  85. package/src/core/conversations/conversations-plugin.ts +2 -2
  86. package/src/core/db/migrations.ts +2 -2
  87. package/src/core/discord/agent-commands.ts +2 -2
  88. package/src/core/discord/agent-discord.ts +1 -1
  89. package/src/core/discord/agent-panel.ts +1 -1
  90. package/src/core/discord/card-audience.ts +1 -1
  91. package/src/core/discord/card-copies.ts +1 -1
  92. package/src/core/discord/channel-context.ts +1 -1
  93. package/src/core/discord/channel-executor.ts +1 -1
  94. package/src/core/discord/channel-operations.ts +1 -1
  95. package/src/core/discord/command-collection.ts +1 -1
  96. package/src/core/discord/compose-commands.ts +1 -1
  97. package/src/core/discord/context-images.ts +1 -1
  98. package/src/core/discord/discord-owners.ts +2 -2
  99. package/src/core/discord/discord-surface.ts +2 -2
  100. package/src/core/discord/member-events.ts +2 -2
  101. package/src/core/discord/message-changes.ts +1 -1
  102. package/src/core/discord/owner-cards.ts +1 -1
  103. package/src/core/discord/owner-command.ts +1 -1
  104. package/src/core/discord/schedule-commands.ts +1 -1
  105. package/src/core/domain/conversation.ts +5 -3
  106. package/src/core/{models.ts → domain/models.ts} +1 -1
  107. package/src/core/domain/ports.ts +2 -2
  108. package/src/core/{sessions.ts → domain/sessions.ts} +6 -6
  109. package/src/core/{define-roundtable.ts → host/define-roundtable.ts} +29 -29
  110. package/src/core/{drain.ts → host/drain.ts} +2 -7
  111. package/src/core/{events.ts → host/events.ts} +2 -2
  112. package/src/core/{host-background.ts → host/host-background.ts} +3 -3
  113. package/src/core/{host-registration.ts → host/host-registration.ts} +30 -30
  114. package/src/core/{host.ts → host/host.ts} +19 -15
  115. package/src/core/http/listeners.ts +2 -2
  116. package/src/core/http/websocket.ts +1 -1
  117. package/src/core/identity/access-policy.ts +8 -8
  118. package/src/core/identity/actor-facts.ts +1 -1
  119. package/src/core/identity/caching-principal-store.ts +1 -1
  120. package/src/core/identity/config-owner.ts +1 -1
  121. package/src/core/identity/contact.ts +2 -2
  122. package/src/core/identity/identity-links.ts +2 -2
  123. package/src/core/identity/identity-port.ts +2 -2
  124. package/src/core/identity/identity-schema.ts +1 -1
  125. package/src/core/identity/identity-service.ts +3 -3
  126. package/src/core/identity/identity-view.ts +1 -1
  127. package/src/core/{identity.ts → identity/owner-identity.ts} +1 -1
  128. package/src/core/identity/person-profiles.ts +1 -1
  129. package/src/core/identity/plugin-identities.ts +2 -2
  130. package/src/core/identity/principal-reads.ts +1 -1
  131. package/src/core/identity/principal-store.ts +1 -1
  132. package/src/core/identity/principal-types.ts +1 -1
  133. package/src/core/identity/seen-throttle.ts +1 -1
  134. package/src/core/{speakers.ts → identity/speakers.ts} +3 -6
  135. package/src/core/images/codex-images-plugin.ts +3 -3
  136. package/src/core/interactions/prompts.ts +1 -1
  137. package/src/core/judging/confirmation-judge.ts +1 -1
  138. package/src/core/judging/effort-judge.ts +2 -2
  139. package/src/core/judging/model-judge.ts +1 -1
  140. package/src/core/modes/conversation-modes.ts +4 -4
  141. package/src/core/modes/mode-inheritance.ts +1 -1
  142. package/src/core/modes/modes-plugin.ts +2 -2
  143. package/src/core/modules/background/background-turns.ts +4 -4
  144. package/src/core/modules/delegation/delegate.ts +3 -3
  145. package/src/core/modules/delegation/delegator.ts +4 -4
  146. package/src/core/modules/delegation/web-research-worker.ts +2 -2
  147. package/src/core/modules/delegation/worker-session.ts +5 -2
  148. package/src/core/modules/discord-admin/discord-admin.ts +1 -1
  149. package/src/core/modules/host-shell/shell-policy.ts +1 -1
  150. package/src/core/modules/memory/owner-memory-store.ts +1 -1
  151. package/src/core/modules/memory/owner-memory.ts +6 -3
  152. package/src/core/modules/notify/notify.ts +4 -1
  153. package/src/core/modules/notify/session-notify.ts +3 -3
  154. package/src/core/modules/prompts/prompt-documents.ts +1 -1
  155. package/src/core/modules/schedules/precheck-tools.ts +4 -4
  156. package/src/core/modules/schedules/prechecks.ts +2 -2
  157. package/src/core/modules/schedules/recurrence.ts +6 -1
  158. package/src/core/modules/schedules/schedule-prechecks.ts +4 -4
  159. package/src/core/modules/schedules/schedule-store.ts +2 -2
  160. package/src/core/modules/schedules/schedule-tools.ts +4 -4
  161. package/src/core/modules/schedules/scheduled-turn-text.ts +1 -1
  162. package/src/core/modules/schedules/scheduler.ts +3 -3
  163. package/src/core/modules/schedules/schedules.ts +5 -5
  164. package/src/core/modules/skills/missing-warning.ts +1 -1
  165. package/src/core/modules/skills/package-skills.ts +1 -1
  166. package/src/core/modules/skills/skill-registry.ts +2 -2
  167. package/src/core/modules/skills/skill-rules.ts +1 -1
  168. package/src/core/modules/skills/skill-tools.ts +1 -1
  169. package/src/core/ops/error-reporter.ts +2 -2
  170. package/src/core/ops/ops-alerts.ts +1 -1
  171. package/src/core/{define.ts → plugin-api/define.ts} +18 -20
  172. package/src/core/{event-types.ts → plugin-api/event-types.ts} +1 -1
  173. package/src/core/{holds.ts → plugin-api/holds.ts} +3 -3
  174. package/src/core/{plugin-removed.ts → plugin-api/plugin-removed.ts} +2 -2
  175. package/src/core/{plugin.ts → plugin-api/plugin.ts} +26 -26
  176. package/src/core/{services.ts → plugin-api/services.ts} +28 -28
  177. package/src/core/{tool-turn.ts → plugin-api/tool-turn.ts} +12 -5
  178. package/src/core/presence/delivery-router.ts +1 -1
  179. package/src/core/presence/direct-channels.ts +1 -1
  180. package/src/core/registry/chat-commands.ts +1 -1
  181. package/src/core/registry/contributions.ts +11 -11
  182. package/src/core/registry/providers.ts +2 -2
  183. package/src/core/registry/services.ts +2 -2
  184. package/src/core/registry/surface-service.ts +1 -1
  185. package/src/core/routing/actor-of.ts +1 -1
  186. package/src/core/routing/channel-queue.ts +2 -2
  187. package/src/core/routing/channel-router.ts +3 -3
  188. package/src/core/routing/claim-events.ts +2 -2
  189. package/src/core/routing/conversation-turns.ts +10 -6
  190. package/src/core/routing/forward-join.ts +1 -1
  191. package/src/core/routing/message-observers.ts +1 -1
  192. package/src/core/routing/message-text.ts +1 -1
  193. package/src/core/routing/peer-bots.ts +6 -74
  194. package/src/core/routing/queued-messages.ts +2 -2
  195. package/src/core/routing/settle-turn.ts +1 -1
  196. package/src/core/routing/surface-port.ts +3 -3
  197. package/src/core/runtime/ask-questions.ts +1 -1
  198. package/src/core/runtime/bridge-guard.ts +5 -5
  199. package/src/core/runtime/chat-only.ts +1 -1
  200. package/src/core/runtime/conversation-sessions.ts +2 -2
  201. package/src/core/runtime/extensions/agent-prompt.ts +1 -1
  202. package/src/core/runtime/extensions/ask-user-text.ts +5 -1
  203. package/src/core/runtime/extensions/ask-user.ts +4 -1
  204. package/src/core/runtime/extensions/card-ask.ts +1 -1
  205. package/src/core/runtime/extensions/confirmation-fixture.ts +1 -1
  206. package/src/core/runtime/extensions/confirmation-gate-extension.ts +1 -1
  207. package/src/core/runtime/extensions/confirmation-gate.ts +5 -5
  208. package/src/core/runtime/extensions/gate-refusals.ts +5 -2
  209. package/src/core/runtime/extensions/held-calls.ts +2 -2
  210. package/src/core/runtime/extensions/hold-describer.ts +3 -3
  211. package/src/core/runtime/extensions/hold-lookups.ts +4 -4
  212. package/src/core/runtime/extensions/persona-prompt.ts +1 -1
  213. package/src/core/runtime/extensions/prompt-read.ts +1 -1
  214. package/src/core/runtime/extensions/yolo.ts +1 -1
  215. package/src/core/runtime/interim-text.ts +1 -1
  216. package/src/core/runtime/pi-agent-runtime.ts +4 -4
  217. package/src/core/runtime/running-turn.ts +1 -1
  218. package/src/core/runtime/runtime-plugin.ts +13 -8
  219. package/src/core/runtime/runtime-types.ts +14 -10
  220. package/src/core/runtime/session-conversation.ts +3 -3
  221. package/src/core/runtime/session-factory.ts +5 -5
  222. package/src/core/runtime/thinking-level.ts +2 -2
  223. package/src/core/{tool-tiers.ts → runtime/tool-tiers.ts} +5 -5
  224. package/src/core/runtime/turn-answer.ts +1 -1
  225. package/src/core/runtime/turn-budget.ts +1 -1
  226. package/src/core/runtime/turn-limits.ts +1 -1
  227. package/src/core/runtime/turn-tools.ts +2 -2
  228. package/src/core/runtime/worker-task.ts +1 -1
  229. package/src/core/shared/attach-file-tool.ts +1 -1
  230. package/src/core/shared/child-env.ts +3 -5
  231. package/src/core/shared/delegate-tool.ts +1 -1
  232. package/src/core/shared/generate-image-tool.ts +1 -1
  233. package/src/core/{modules/background → shared}/personal-target.ts +2 -2
  234. package/src/core/{reply-files.ts → shared/reply-files.ts} +1 -1
  235. package/src/core/testing/eager-catalog.ts +1 -1
  236. package/src/core/testing/locale.ts +1 -1
  237. package/src/core/testing/map-identity.ts +5 -1
  238. package/src/core/testing/module-sessions.ts +3 -3
  239. package/src/core/testing/modules.ts +17 -13
  240. package/src/core/testing/owner.ts +2 -2
  241. package/src/core/testing/recording-logger.ts +1 -1
  242. package/src/core/testing/run-tool.ts +2 -2
  243. package/src/core/testing/surface-contract-support.ts +1 -1
  244. package/src/core/testing/surface-contract.ts +2 -2
  245. package/src/core/testing/test-host.ts +12 -12
  246. package/src/core/testing/thread-host.ts +1 -1
  247. package/src/core/testing/tool-set.ts +3 -3
  248. package/src/core/threads/dispatch-threads.ts +1 -1
  249. package/src/core/tool-set.snapshot.json +12 -0
  250. package/src/index.ts +76 -72
  251. package/src/kit/domain.ts +9 -9
  252. package/src/kit/holds.ts +4 -1
  253. package/src/kit/jev-judge.ts +1 -1
  254. package/src/kit/jev.ts +1 -1
  255. package/src/kit/presentation.ts +1 -1
  256. package/src/kit/support.ts +3 -3
  257. package/src/testing.ts +21 -20
  258. /package/src/core/{errors.ts → kernel/errors.ts} +0 -0
  259. /package/src/core/{freeze.ts → kernel/freeze.ts} +0 -0
  260. /package/src/core/{log.ts → kernel/log.ts} +0 -0
  261. /package/src/core/{time.ts → kernel/time.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,25 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.35.0] - 2026-11-06
9
+
10
+ ### Added
11
+
12
+ - Temp-knight presets: an agent saves the role prompt, skills, look, and model of a temp knight it makes often with `helper_preset_set`, reads them with `helper_preset_list`, removes one with `helper_preset_delete`, and makes it with `helper_create` and `preset`. Fields given in the call replace the preset's, and skills given are added to the preset's. A preset belongs to the agent that saved it, at most 20 each, and is checked at save and again when used, with the tier and skill rules `helper_create` applies. The tools are offered with `helper_create` at the member tier, never to a temp knight or with `helpers: false`. The presets live in a new `helper_presets` table, created by the agent server's migrations.
13
+ - `AgentOps.helperPreset`; `AgentOps.helperCreate` takes `preset`, and its `displayName` and `prompt` are optional when a preset gives them.
14
+
15
+ ## [0.34.0] - 2026-11-04
16
+
17
+ This is a minor release with a breaking default: an agent's shell no longer gets `GH_TOKEN`.
18
+
19
+ ### Changed
20
+
21
+ - `DEFAULT_SHELL_PASS` is empty: without `shellEnv.pass` no host secret reaches an agent's shell or a coding worker's `bash`, `GH_TOKEN` included. A public host's token is often broad, and 0.33.0 handed it to every agent's shell without the host asking. The coding shelf's git and gh calls (`repo_add`, fetch, `repo_push`) still get the token through the coding plugin's `githubToken`, which is unaffected.
22
+
23
+ ### Migration
24
+
25
+ - A host whose agents run `gh`, or `git push` through `gh auth git-credential`, in their shell names the token: `shellEnv: { pass: ["GH_TOKEN"] }`, or better a narrower token given in `set` as `GH_TOKEN`.
26
+
8
27
  ## [0.33.0] - 2026-11-04
9
28
 
10
29
  This is a minor release with breaking defaults: the agents' shell and the coding plugin's workers no longer inherit the host's environment, and more shell commands are held. See the migration notes below.
package/README.md CHANGED
@@ -274,7 +274,7 @@ pi-roundtable runs one assistant for one owner.
274
274
  - **Approvals.** A held call is approved only by the speaker whose turn held it, at a tier that still holds the call, or, in a shared conversation, by an owner, on its card or by a confirming message. In a private conversation nobody else may, and a call above the speaker's tier is not approved there.
275
275
  - **Conversations.** In Discord an agent's channel and a group room are shared: everyone who writes there adds to one conversation the agent reads. A web chat conversation belongs to the person who opened it: in the web chat only they may read it, write in it, or answer its prompts, but the owner can read it through the owner console ([pi-roundtable-web](packages/web)), and the operator through the database and the data directory.
276
276
  - **Memory isolation.** Memory follows the principal, not owner tier: a private conversation's person, or the current speaker in a shared room. Link accounts to share one person's memory across Discord and web. In shared requests and summaries, memory-tool and memory-loaded-worker exchanges (arguments and results together) are hidden from other speakers, and earlier reasoning is removed with provider-aware handling. Other tools' arguments and public assistant replies remain public, even if the model repeats private memory there; this is not general secret-flow prevention. Third-party compactors must use `privateCompaction` before summarizing shared history. `claude-bridge` shared turns refuse when raw reader records, including compacted turns, show another reader's private memory (even prompt-only memory and its reasoning), or an exchange is hidden from the current reader. A turn with no private memory does not block other readers, and disabling future memory does not bypass prior private history; admitting other people only warns at boot and in doctor. SYSTEM counts as primary owner for this core guard alone, so it can read and publicly repeat the owner's retained exchanges/reasoning; pre-0.9 untagged built-in memory results before the first scope record retain owner attribution. Sandbox party-wide prompt blocks must explicitly use `memory.visibility: "shared"`, and private turns require worker capabilities. Bridge replays unfiltered history outside these projections; see the [exact rule and remaining risk](docs/migration-0.9.md#claude-bridge-guard).
277
- - **The host shell.** An agent's shell runs as the host's user. Holds keep risky commands behind a card; they are not a sandbox. The shell gets only part of the host's environment (the paths, user, locale, terminal, `TMPDIR` and proxies, plus `GH_TOKEN` and what `shellEnv` adds), so the bot tokens, model logins, `DATABASE_URL` and keys the host holds stay in the host process; printing the environment, reading a secret file such as `.env` or `~/.ssh/*`, and `gh auth token` are held as `shell.secret-read`, which yolo mode always cards; a secret's value in a tool's output is replaced with `****`. This stops casual and accidental leaks, not a determined command run as the same user, which can read `/proc/<host pid>/environ` and any file that user can. To keep secrets from the agents, run their shells under a dedicated account without the `docker` group (membership in it equals root), or use [pi-roundtable-sandbox](packages/sandbox).
277
+ - **The host shell.** An agent's shell runs as the host's user. Holds keep risky commands behind a card; they are not a sandbox. The shell gets only part of the host's environment (the paths, user, locale, terminal, `TMPDIR` and proxies, plus what `shellEnv` adds), so the bot tokens, model logins, `GH_TOKEN`, `DATABASE_URL` and keys the host holds stay in the host process; printing the environment, reading a secret file such as `.env` or `~/.ssh/*`, and `gh auth token` are held as `shell.secret-read`, which yolo mode always cards; a secret's value in a tool's output is replaced with `****`. This stops casual and accidental leaks, not a determined command run as the same user, which can read `/proc/<host pid>/environ` and any file that user can. To keep secrets from the agents, run their shells under a dedicated account without the `docker` group (membership in it equals root), or use [pi-roundtable-sandbox](packages/sandbox).
278
278
  - **Model credentials.** Every turn, whoever speaks, runs on the host's model login and is billed to it. Per-person credentials are planned for a later release.
279
279
  - **Data.** Conversations, memory, and schedules sit unencrypted in PostgreSQL and the data directory.
280
280
 
package/README.zh-TW.md CHANGED
@@ -264,7 +264,7 @@ pi-roundtable 為一位擁有者執行騎士。
264
264
  - **核准。** 暫緩的呼叫只由當輪暫緩它的發言者核准,而且當下 tier 仍要足夠;在共用對話裡,擁有者也可以在卡片上或用確認訊息核准。私人對話裡別人都不能核准,高於發言者 tier 的呼叫在那裡也不會被核准。
265
265
  - **對話。** Discord 裡智慧體的頻道和群組房間是共用的:在那裡發言的每個人,都會寫進智慧體讀取的同一段對話。網頁聊天的對話屬於開啟它的人:在網頁聊天裡只有開啟者本人能讀、能發言、能回答它的提問,但擁有者可以透過擁有者主控台([pi-roundtable-web](packages/web))讀取,營運者也能從資料庫和資料目錄讀到。
266
266
  - **記憶隔離。** 記憶依 principal 分開,不依擁有者 tier 判斷。私人對話讀本人的,共用對話讀當輪發言者的;連結 Discord 與網頁身分後,同一個人共用一份記憶。在共用對話送給模型的請求和摘要裡,記憶工具與載入記憶的 worker 的呼叫(參數和結果成對)會對其他發言者隱藏,先前回合的 reasoning 則依 provider 清除。其他工具的參數和公開的騎士回覆仍是公開內容,即使模型在裡面重述私人記憶;這不是一般的秘密流向防護。第三方摘要器必須先使用 `privateCompaction`,才能摘要共用歷史。`claude-bridge` 的共用回合只在原始讀者紀錄(含已壓縮的回合)顯示另一位讀者的私人記憶(連只放進 prompt 的記憶與其 reasoning 也算),或某個呼叫已對當前讀者隱藏時才被拒絕。沒有私人記憶的回合不會擋其他讀者,關掉之後的記憶也繞不過先前的私人歷史;開放其他人進來只會在開機和 doctor 裡警告。SYSTEM 只在這項核心防護裡算作主要擁有者,所以它能讀取並公開重述擁有者保留的呼叫與 reasoning;0.9 之前、第一筆範圍紀錄之前未標記的內建記憶結果,仍歸屬擁有者。沙盒的全場共用 prompt 區塊必須明確使用 `memory.visibility: "shared"`,私人回合需要 worker 能力。Bridge 會在這些投影之外重播未過濾的歷史;見[確切規則與剩餘風險](docs/migration-0.9.md#claude-bridge-guard)。
267
- - **主機上的 shell。** 智慧體的 shell 以主機的使用者身分執行。暫緩只是把有風險的指令擋在卡片後面,不是沙箱。shell 只拿到主機環境變數的一部分(路徑、使用者、語系、終端機、`TMPDIR`、proxy,加上 `GH_TOKEN` 與 `shellEnv` 額外給的),所以主機持有的 bot token、模型登入、`DATABASE_URL` 和金鑰都留在主機行程裡;印出環境變數、讀取 `.env` 或 `~/.ssh/*` 這類秘密檔案、`gh auth token` 會以 `shell.secret-read` 暫緩,yolo 模式一律出卡片;工具輸出裡的秘密值會換成 `****`。這擋得住隨手和意外的外洩,擋不住以同一個使用者刻意執行的指令:它讀得到 `/proc/<主機 pid>/environ`,也讀得到那個使用者能讀的任何檔案。要讓智慧體碰不到秘密,請讓它們的 shell 以不在 `docker` 群組裡的專用帳號執行(加入這個群組等同 root),或改用 [pi-roundtable-sandbox](packages/sandbox)。
267
+ - **主機上的 shell。** 智慧體的 shell 以主機的使用者身分執行。暫緩只是把有風險的指令擋在卡片後面,不是沙箱。shell 只拿到主機環境變數的一部分(路徑、使用者、語系、終端機、`TMPDIR`、proxy,加上 `shellEnv` 額外給的),所以主機持有的 `GH_TOKEN`、bot token、模型登入、`DATABASE_URL` 和金鑰都留在主機行程裡;印出環境變數、讀取 `.env` 或 `~/.ssh/*` 這類秘密檔案、`gh auth token` 會以 `shell.secret-read` 暫緩,yolo 模式一律出卡片;工具輸出裡的秘密值會換成 `****`。這擋得住隨手和意外的外洩,擋不住以同一個使用者刻意執行的指令:它讀得到 `/proc/<主機 pid>/environ`,也讀得到那個使用者能讀的任何檔案。要讓智慧體碰不到秘密,請讓它們的 shell 以不在 `docker` 群組裡的專用帳號執行(加入這個群組等同 root),或改用 [pi-roundtable-sandbox](packages/sandbox)。
268
268
  - **模型憑證。** 每一輪不論誰發言,都用主機的模型登入執行、由它計費。每個人自己的憑證預計在之後的版本加入。
269
269
  - **資料。** 對話、記憶和排程以未加密的形式存在 PostgreSQL 和資料目錄裡。
270
270
 
package/docs/plugins.md CHANGED
@@ -1210,8 +1210,8 @@ const shell = shellHoldRuleFor({
1210
1210
 
1211
1211
  The agents' `bash` does not inherit the host process's environment.
1212
1212
  It gets the names in `SHELL_ENV_NAMES` (`PATH`, `HOME`, `USER`, `LOGNAME`, `SHELL`, `LANG`, `LANGUAGE`, `LC_*`, `TZ`, `TERM`, `TMPDIR`, the proxy variables in both cases, `SSL_CERT_FILE`, `SSL_CERT_DIR`, and Pi's `PI_*` session names), and what the host's `shellEnv` adds: `pass`, more host variables by name (a trailing `*` matches a prefix), and `set`, fixed values that win.
1213
- Without `pass` it is `DEFAULT_SHELL_PASS`, `["GH_TOKEN"]`, so `gh` and a `git push` through `gh auth git-credential` work in the shell; `pass: []` keeps it out.
1214
- Any other secret the host needs (a bot token, a model login, `DATABASE_URL`) stays in the host process; give a shell one only by naming it:
1213
+ Without `pass` it is `DEFAULT_SHELL_PASS`, empty: no host secret reaches the shell, `GH_TOKEN` included.
1214
+ A secret the host needs (a bot token, a model login, `DATABASE_URL`, `GH_TOKEN`) stays in the host process; give a shell one only by naming it, for example a token for `gh` and a `git push` through `gh auth git-credential`, preferably a narrower one than the host's in `set`:
1215
1215
 
1216
1216
  ```ts
1217
1217
  export default {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-roundtable",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "A plugin-driven Pi agent server for one owner, reached through Discord or the web",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,7 +27,6 @@
27
27
  "files": [
28
28
  "src",
29
29
  "!src/**/*.test.ts",
30
- "!src/core/testing/file-size.ts",
31
30
  "!src/core/modules/host-shell/shell-fuzz-*.ts",
32
31
  "!src/core/testing/discord-limits.ts",
33
32
  "!src/core/testing/prompt-capture*.ts",
@@ -1,5 +1,5 @@
1
- import { Roundtable } from "../../core/host.ts";
2
- import { silentLogger } from "../../core/log.ts";
1
+ import { Roundtable } from "../../core/host/host.ts";
2
+ import { silentLogger } from "../../core/kernel/log.ts";
3
3
  import { CONFIG_FILE, type Project } from "../project.ts";
4
4
  import { fail, ok, type Result } from "../report.ts";
5
5
 
@@ -1,7 +1,7 @@
1
1
  import type { SQL } from "bun";
2
2
  import { nested, openPool, runMigrations } from "../../core/db/migrations.ts";
3
- import { MigrationError } from "../../core/errors.ts";
4
- import type { RoundtablePlugin } from "../../core/plugin.ts";
3
+ import { MigrationError } from "../../core/kernel/errors.ts";
4
+ import type { RoundtablePlugin } from "../../core/plugin-api/plugin.ts";
5
5
  import type { Project } from "../project.ts";
6
6
  import { fail, ok, type Result, skipped } from "../report.ts";
7
7
 
@@ -1,4 +1,5 @@
1
1
  import type { SQL } from "bun";
2
+ import { backfillLine } from "../../core/builtin/identity.ts";
2
3
  import { LEGACY_ACCESS } from "../../core/config/access.ts";
3
4
  import type { ResolvedConfig } from "../../core/config/config.ts";
4
5
  import {
@@ -7,7 +8,6 @@ import {
7
8
  } from "../../core/identity/access-policy.ts";
8
9
  import { identityOf, parseIdentity } from "../../core/identity/actor-facts.ts";
9
10
  import { declaredConflict } from "../../core/identity/config-owner.ts";
10
- import { backfillLine } from "../../core/identity/identity-plugin.ts";
11
11
  import {
12
12
  type BackfillSummary,
13
13
  backfillPrincipals,
@@ -1,4 +1,4 @@
1
- import { parseModelRef } from "../../core/models.ts";
1
+ import { parseModelRef } from "../../core/domain/models.ts";
2
2
  import {
3
3
  BRIDGE_MEMORY_FIX,
4
4
  bridgeMemoryProblem,
package/src/cli/cli.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
3
  import { resolveConfig } from "../core/config/config.ts";
4
- import type { DefinedRoundtable } from "../core/define-roundtable.ts";
5
- import { Roundtable } from "../core/host.ts";
4
+ import type { DefinedRoundtable } from "../core/host/define-roundtable.ts";
5
+ import { Roundtable } from "../core/host/host.ts";
6
6
  import { declaredIdentities } from "../core/identity/plugin-identities.ts";
7
7
  import { addPackage } from "./add-package.ts";
8
8
  import { addPlugin } from "./add-plugin.ts";
@@ -12,7 +12,7 @@ import {
12
12
  type RoleGrant,
13
13
  } from "../core/identity/principal-store.ts";
14
14
  import { chosenProfileSource } from "../core/identity/profile-choices.ts";
15
- import type { Tier } from "../core/speakers.ts";
15
+ import type { Tier } from "../core/identity/speakers.ts";
16
16
  import { CONFIG_FILE } from "./project.ts";
17
17
 
18
18
  export const PRINCIPAL_USAGE = ` roundtable principal list every principal, with its roles and its identities written as
@@ -7,8 +7,8 @@ import {
7
7
  type RoundtableConfig,
8
8
  resolveConfig,
9
9
  } from "../core/config/config.ts";
10
- import type { DefinedRoundtable } from "../core/define-roundtable.ts";
11
- import { type Logger, silentLogger } from "../core/log.ts";
10
+ import type { DefinedRoundtable } from "../core/host/define-roundtable.ts";
11
+ import { type Logger, silentLogger } from "../core/kernel/log.ts";
12
12
  import { fail, type Result } from "./report.ts";
13
13
 
14
14
  export const CONFIG_FILE = "roundtable.config.ts";
@@ -2,9 +2,9 @@ import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import type { Credential, CredentialStore } from "@earendil-works/pi-ai";
4
4
  import { ModelRuntime } from "@earendil-works/pi-coding-agent";
5
- import type { DefinedRoundtable } from "../core/define-roundtable.ts";
6
- import { defineRoundtable } from "../core/define-roundtable.ts";
7
- import type { Logger } from "../core/log.ts";
5
+ import type { DefinedRoundtable } from "../core/host/define-roundtable.ts";
6
+ import { defineRoundtable } from "../core/host/define-roundtable.ts";
7
+ import type { Logger } from "../core/kernel/log.ts";
8
8
 
9
9
  /** A credential store that holds nothing and refuses writes, so looking never creates `auth.json`. */
10
10
  const emptyCredentials: CredentialStore = {
package/src/cli/start.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DefinedRoundtable } from "../core/define-roundtable.ts";
1
+ import type { DefinedRoundtable } from "../core/host/define-roundtable.ts";
2
2
  import { buildChecks, type DoctorInputs } from "./doctor.ts";
3
3
  import { Project } from "./project.ts";
4
4
  import { failed, type Outcome, runChecks } from "./report.ts";
@@ -14,14 +14,14 @@ import type {
14
14
  import type { AgentRuntime } from "../contract/runtime.ts";
15
15
  import { parseChannelKey, type SurfacePort } from "../contract/surface.ts";
16
16
  import type { ChannelKey } from "../domain/conversation.ts";
17
- import type { OwnerIdentity } from "../identity.ts";
18
- import type { Logger } from "../log.ts";
19
- import { PERSONAL_TARGET } from "../modules/background/personal-target.ts";
17
+ import type { OwnerIdentity } from "../identity/owner-identity.ts";
18
+ import { addressee, attributed, type Speaker } from "../identity/speakers.ts";
19
+ import type { Logger } from "../kernel/log.ts";
20
20
  import { withReference } from "../routing/message-text.ts";
21
21
  import { answersAuthor } from "../routing/peer-bots.ts";
22
22
  import { outcome } from "../routing/settle-turn.ts";
23
23
  import { systemTurn } from "../routing/system-turns.ts";
24
- import { addressee, attributed, type Speaker } from "../speakers.ts";
24
+ import { PERSONAL_TARGET } from "../shared/personal-target.ts";
25
25
  import type { DiscordAgentTeam } from "./agent-team.ts";
26
26
  import { discordIdOf, roomOf } from "./team-keys.ts";
27
27
 
@@ -1,7 +1,7 @@
1
+ import { thinkingLabel } from "../domain/models.ts";
1
2
  import { messages } from "../i18n/index.ts";
2
- import type { Logger } from "../log.ts";
3
- import { thinkingLabel } from "../models.ts";
4
- import { zonedDate, zonedStamp } from "../time.ts";
3
+ import type { Logger } from "../kernel/log.ts";
4
+ import { zonedDate, zonedStamp } from "../kernel/time.ts";
5
5
  import type { ContextUse, DashboardBoard } from "./agent-ports.ts";
6
6
  import type { AgentStatus, GroupStatus, TeamStatus } from "./agent-team.ts";
7
7
 
@@ -1,12 +1,12 @@
1
1
  import type { ChannelKey, IntercomCard } from "../domain/conversation.ts";
2
2
  import { AgentError, IdentityError } from "../domain/errors.ts";
3
3
  import type { AgentTurnScope } from "../domain/ports.ts";
4
- import { HostStoppingError } from "../errors.ts";
5
4
  import { SYSTEM_PRINCIPAL } from "../identity/principal-store.ts";
5
+ import { addressee, type Speaker } from "../identity/speakers.ts";
6
+ import { HostStoppingError } from "../kernel/errors.ts";
6
7
  import { intercomPlain } from "../presentation/intercom.ts";
7
8
  import { isQuiet } from "../presentation/reply-body.ts";
8
9
  import { splitReply } from "../presentation/reply-splitter.ts";
9
- import { addressee, type Speaker } from "../speakers.ts";
10
10
  import type { OutboxEntry, StoredOutboxEntry } from "./agent-outbox.ts";
11
11
  import {
12
12
  agentFailureText,
@@ -1,7 +1,7 @@
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 { Speaker } from "../speakers.ts";
4
+ import type { Speaker } from "../identity/speakers.ts";
5
5
 
6
6
  /**
7
7
  * An agent message the host stopped before it could deliver. `message` is the request to the
@@ -1,7 +1,7 @@
1
1
  import type { AgentRuntime, ContextUse } from "../contract/runtime.ts";
2
2
  import type { IntercomCard } from "../domain/conversation.ts";
3
3
  import type { InterimPosts } from "../domain/interim.ts";
4
- import type { ThinkingSetting } from "../models.ts";
4
+ import type { ThinkingSetting } from "../domain/models.ts";
5
5
 
6
6
  export type { ContextUse };
7
7
 
@@ -1,9 +1,9 @@
1
1
  import { parseChannelKey, type SurfacePort } from "../contract/surface.ts";
2
2
  import type { ChannelKey } from "../domain/conversation.ts";
3
3
  import { messages } from "../i18n/index.ts";
4
- import { type OwnerIdentity, ownerWords } from "../identity.ts";
5
- import type { AgentTools } from "../plugin.ts";
6
- import { addressee, type Speaker } from "../speakers.ts";
4
+ import { type OwnerIdentity, ownerWords } from "../identity/owner-identity.ts";
5
+ import { addressee, type Speaker } from "../identity/speakers.ts";
6
+ import type { AgentTools } from "../plugin-api/plugin.ts";
7
7
  import type { Agent, AgentGroup, Backlog } from "./agent-store.ts";
8
8
 
9
9
  /**
@@ -58,7 +58,7 @@ export function agentSystemPrompt(input: {
58
58
  );
59
59
  else if (input.helpers)
60
60
  parts.push(
61
- "A task that stands on its own, such as one of several things to look up or compare, can go to a temp knight: helper_create makes one of yours that works in parallel, its answer comes back to you as a new turn, and helper_end clears the ones you are done with.",
61
+ "A task that stands on its own, such as one of several things to look up or compare, can go to a temp knight: helper_create makes one of yours that works in parallel, its answer comes back to you as a new turn, and helper_end clears the ones you are done with. A temp knight you make often can be saved as a preset (helper_preset_set), then made with helper_create and preset.",
62
62
  );
63
63
  if (group) {
64
64
  const others = group.members
@@ -4,7 +4,7 @@ import {
4
4
  suggestCharacter,
5
5
  } from "../../characters/index.ts";
6
6
  import { AgentError } from "../domain/errors.ts";
7
- import { THINKING_LEVELS, type ThinkingLevel } from "../models.ts";
7
+ import { THINKING_LEVELS, type ThinkingLevel } from "../domain/models.ts";
8
8
 
9
9
  export const MAX_PROMPT_CHARS = 4_000;
10
10
  export const MAX_AVATAR_PROMPT_CHARS = 1_000;
@@ -1,11 +1,12 @@
1
1
  import { readCharacter } from "../../characters/index.ts";
2
2
  import { scopeToGuild } from "../db/guild-scope.ts";
3
3
  import type { Migration } from "../db/migrations.ts";
4
- import type { ThinkingLevel } from "../models.ts";
4
+ import type { ThinkingLevel } from "../domain/models.ts";
5
5
  import { promptHistoryMigration } from "../modules/prompts/prompt-history.ts";
6
6
  import { AgentConversations } from "./agent-conversations.ts";
7
7
  import { outboxMigration } from "./agent-outbox.ts";
8
8
  import type { Agent, AgentGroup, AgentStatus } from "./agent-rules.ts";
9
+ import { HelperPresets } from "./helper-presets.ts";
9
10
 
10
11
  export interface AgentRow {
11
12
  name: string;
@@ -164,5 +165,7 @@ export function agentMigrations(guildId: string): Migration[] {
164
165
  outboxMigration(),
165
166
  // Where each agent last ran a turn, so a message to it finds that conversation after a restart.
166
167
  AgentConversations.migration,
168
+ // The temp-knight presets each agent saved; kept when the agent is archived.
169
+ HelperPresets.migration,
167
170
  ];
168
171
  }
@@ -1,10 +1,10 @@
1
1
  import { AgentError } from "../domain/errors.ts";
2
- import { assistantName } from "../i18n/index.ts";
3
2
  import {
4
3
  AUTO_THINKING,
5
4
  type ThinkingLevel,
6
5
  type ThinkingSetting,
7
- } from "../models.ts";
6
+ } from "../domain/models.ts";
7
+ import { assistantName } from "../i18n/index.ts";
8
8
  import { checkModelRef, checkThinking } from "./agent-store.ts";
9
9
 
10
10
  /** Resets a model or thinking setting to the assistant's. */
@@ -2,12 +2,12 @@ import type { SQL } from "bun";
2
2
  import type { CharacterSpec } from "../../characters/index.ts";
3
3
  import type { Migration } from "../db/migrations.ts";
4
4
  import { AgentError } from "../domain/errors.ts";
5
- import type { ThinkingLevel } from "../models.ts";
5
+ import type { ThinkingLevel } from "../domain/models.ts";
6
6
  import {
7
7
  PromptHistory,
8
8
  type PromptVersion,
9
9
  } from "../modules/prompts/prompt-history.ts";
10
- import type { AgentDirectory } from "../services.ts";
10
+ import type { AgentDirectory } from "../plugin-api/services.ts";
11
11
  import { AgentBook } from "./agent-book.ts";
12
12
  import { AgentConversations } from "./agent-conversations.ts";
13
13
  import { AgentOutbox } from "./agent-outbox.ts";
@@ -15,7 +15,6 @@ import {
15
15
  type Agent,
16
16
  type AgentGroup,
17
17
  type AgentSeed,
18
- type AgentStatus,
19
18
  type Backlog,
20
19
  checkAgentName,
21
20
  checkAvatarPrompt,
@@ -35,6 +34,7 @@ import {
35
34
  } from "./agent-schema.ts";
36
35
  import { AgentStatements } from "./agent-statements.ts";
37
36
  import { GroupMessages } from "./group-messages.ts";
37
+ import { HelperPresets } from "./helper-presets.ts";
38
38
 
39
39
  export {
40
40
  type Agent,
@@ -74,6 +74,8 @@ export class PgAgentStore extends AgentBook implements AgentDirectory {
74
74
  readonly outbox: AgentOutbox;
75
75
  /** The conversation each agent last ran a turn in. */
76
76
  readonly conversations: AgentConversations;
77
+ /** The temp-knight presets each agent saved. */
78
+ readonly presets: HelperPresets;
77
79
 
78
80
  private constructor(
79
81
  sql: SQL,
@@ -88,6 +90,7 @@ export class PgAgentStore extends AgentBook implements AgentDirectory {
88
90
  this.#messages = new GroupMessages(sql, guildId);
89
91
  this.#prompts = new PromptHistory(sql, guildId);
90
92
  this.outbox = new AgentOutbox(sql, guildId);
93
+ this.presets = new HelperPresets(sql, guildId);
91
94
  }
92
95
 
93
96
  /** The store's tables; the host runs this before any store attaches. */
@@ -454,12 +457,9 @@ export class PgAgentStore extends AgentBook implements AgentDirectory {
454
457
 
455
458
  async #writeGroup(
456
459
  name: string,
457
- change: {
458
- displayName?: string;
459
- members?: string[];
460
- host?: string;
461
- status?: AgentStatus;
462
- },
460
+ change: Partial<
461
+ Pick<AgentGroup, "displayName" | "members" | "host" | "status">
462
+ >,
463
463
  ): Promise<AgentGroup> {
464
464
  const current = this.groupMap.get(name);
465
465
  if (!current) throw new AgentError(`There is no group "${name}".`);
@@ -12,11 +12,12 @@ import type {
12
12
  } from "../domain/conversation.ts";
13
13
  import type { RoundProgress } from "../domain/round.ts";
14
14
  import type { IdentityService } from "../identity/identity-port.ts";
15
- import { silentLogger } from "../log.ts";
15
+ import { silentLogger } from "../kernel/log.ts";
16
16
  import { StoredSkillRegistry as SkillRegistry } from "../modules/skills/skill-registry.ts";
17
17
  import { SkillStore } from "../modules/skills/skill-store.ts";
18
- import type { PromptSection } from "../plugin.ts";
18
+ import type { PromptSection } from "../plugin-api/plugin.ts";
19
19
  import { type ChannelQueue, channelQueue } from "../routing/channel-queue.ts";
20
+ import { toolTiers } from "../runtime/tool-tiers.ts";
20
21
  import {
21
22
  openTestStore,
22
23
  TEST_GUILD,
@@ -25,7 +26,6 @@ import {
25
26
  } from "../testing/database.ts";
26
27
  import { useTestLocale } from "../testing/locale.ts";
27
28
  import { OWNER_SPEAKER, TEST_OWNER } from "../testing/owner.ts";
28
- import { toolTiers } from "../tool-tiers.ts";
29
29
  import type {
30
30
  AgentCategory,
31
31
  AgentChannels,
@@ -305,6 +305,7 @@ export function useTeamFixture(
305
305
  "skill_versions",
306
306
  "skill_groups",
307
307
  "agent_skills",
308
+ "helper_presets",
308
309
  ])
309
310
  await admin.unsafe(`DROP TABLE IF EXISTS ${table}`);
310
311
  await admin.close();
@@ -3,13 +3,13 @@ import type { CharacterInput } from "../../characters/index.ts";
3
3
  import type { TurnAttachments } from "../domain/attachment.ts";
4
4
  import type { ChannelKey, TurnResult } from "../domain/conversation.ts";
5
5
  import { AgentError, ScheduleError } from "../domain/errors.ts";
6
+ import type { ThinkingSetting } from "../domain/models.ts";
6
7
  import type { AgentTurnScope } from "../domain/ports.ts";
7
- import type { ThinkingSetting } from "../models.ts";
8
+ import type { TurnSelection } from "../domain/sessions.ts";
9
+ import { type Speaker, THE_SPEAKER } from "../identity/speakers.ts";
8
10
  import type { PromptVersion } from "../modules/prompts/prompt-history.ts";
9
11
  import type { ResolvedSkill } from "../modules/skills/skill-rules.ts";
10
- import type { AgentChange, AgentTeam } from "../services.ts";
11
- import type { TurnSelection } from "../sessions.ts";
12
- import { type Speaker, THE_SPEAKER } from "../speakers.ts";
12
+ import type { AgentChange, AgentTeam } from "../plugin-api/services.ts";
13
13
  import type { Agent } from "./agent-store.ts";
14
14
  import {
15
15
  type AgentOps,
@@ -17,6 +17,7 @@ import {
17
17
  agentToolsExtension,
18
18
  } from "./agent-tools.ts";
19
19
  import type { HelperTeam } from "./helper-ops.ts";
20
+ import { type PresetAction, presetAction } from "./helper-preset-ops.ts";
20
21
  import { type Routes, routesOf } from "./routes.ts";
21
22
  import { TeamEditing } from "./team-editing.ts";
22
23
  import type { TeamHelpers } from "./team-helpers.ts";
@@ -257,19 +258,9 @@ export class DiscordAgentTeam implements AgentOps, AgentTeam {
257
258
 
258
259
  /** The owner's message in an agent's channel; call inside its queue. `text` has the reference, `replyText` what they typed. */
259
260
  answerOwner(
260
- channel: ChannelKey,
261
- speaker: Speaker,
262
- text: string,
263
- replyText: string,
264
- attachments: TurnAttachments,
261
+ ...args: Parameters<TeamTurns["answerOwner"]>
265
262
  ): Promise<TurnResult> {
266
- return this.#turns.answerOwner(
267
- channel,
268
- speaker,
269
- text,
270
- replyText,
271
- attachments,
272
- );
263
+ return this.#turns.answerOwner(...args);
273
264
  }
274
265
 
275
266
  /**
@@ -422,6 +413,11 @@ export class DiscordAgentTeam implements AgentOps, AgentTeam {
422
413
  return this.#editing.createHelper(caller, input);
423
414
  }
424
415
 
416
+ /** A knight keeps its own temp-knight presets; see `AgentOps.helperPreset`. */
417
+ helperPreset(caller: AgentTurnScope, action: PresetAction): Promise<string> {
418
+ return presetAction(this.#context, caller, action);
419
+ }
420
+
425
421
  /** A knight archives its own temp knights; the pages that show the parent are told. */
426
422
  helperEnd(
427
423
  caller: AgentTurnScope,
@@ -2,10 +2,11 @@ import type { ExtensionFactory } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
3
  import type { CharacterInput } from "../../characters/index.ts";
4
4
  import { AgentError } from "../domain/errors.ts";
5
+ import { THINKING_LEVELS } from "../domain/models.ts";
5
6
  import type { AgentTurnScope } from "../domain/ports.ts";
6
7
  import { assistantName, messages } from "../i18n/index.ts";
7
- import { type OwnerIdentity, ownerWords } from "../identity.ts";
8
- import { THINKING_LEVELS } from "../models.ts";
8
+ import { type OwnerIdentity, ownerWords } from "../identity/owner-identity.ts";
9
+ import { timeZone } from "../kernel/time.ts";
9
10
  import {
10
11
  optionalString,
11
12
  requiredString,
@@ -13,7 +14,6 @@ import {
13
14
  type TextToolDef,
14
15
  textToolsExtension,
15
16
  } from "../runtime/text-tools.ts";
16
- import { timeZone } from "../time.ts";
17
17
  import { MAX_GROUP_MEMBERS, MIN_GROUP_MEMBERS } from "./agent-store.ts";
18
18
  import {
19
19
  CLASS,
@@ -24,6 +24,7 @@ import {
24
24
  PARTS,
25
25
  PROMPT,
26
26
  } from "./agent-tool-schema.ts";
27
+ import type { HelperFields, PresetAction } from "./helper-preset-ops.ts";
27
28
  import { helperToolDefs } from "./helper-tools.ts";
28
29
 
29
30
  /** The tool that hands a request to another agent; a group seat has none. */
@@ -32,8 +33,14 @@ export const MESSAGE_AGENT_TOOL = "message_agent";
32
33
  /** The tool that changes an agent's look; every host offers it. */
33
34
  export const AVATAR_TOOL = "agent_avatar";
34
35
 
35
- /** The tools that make and end temp knights; `helpers: false` leaves them out. */
36
- export const HELPER_TOOLS = ["helper_create", "helper_end"] as const;
36
+ /** The tools that make and end temp knights and keep their presets; `helpers: false` leaves them out. */
37
+ export const HELPER_TOOLS = [
38
+ "helper_create",
39
+ "helper_end",
40
+ "helper_preset_set",
41
+ "helper_preset_list",
42
+ "helper_preset_delete",
43
+ ] as const;
37
44
 
38
45
  export const AGENT_TOOLS = [
39
46
  "agent_list",
@@ -103,17 +110,10 @@ export interface AgentOps {
103
110
  /** Makes a temp knight of the caller for one task; the answer returns to the caller's conversation. */
104
111
  helperCreate(
105
112
  caller: AgentTurnScope,
106
- input: {
107
- name?: string;
108
- displayName: string;
109
- prompt: string;
110
- task: string;
111
- character?: CharacterInput;
112
- skills?: string[];
113
- model?: string;
114
- thinking?: string;
115
- },
113
+ input: HelperFields & { name?: string; task: string },
116
114
  ): Promise<string>;
115
+ /** Saves, lists, or deletes the caller's own temp-knight presets. */
116
+ helperPreset(caller: AgentTurnScope, action: PresetAction): Promise<string>;
117
117
  /** Archives the caller's own temp knights: the named ones, or every one that is finished. */
118
118
  helperEnd(
119
119
  caller: AgentTurnScope,
@@ -1,5 +1,5 @@
1
1
  import type { CharacterSpec } from "../../characters/index.ts";
2
- import type { Logger } from "../log.ts";
2
+ import type { Logger } from "../kernel/log.ts";
3
3
  import type { Agent } from "./agent-store.ts";
4
4
 
5
5
  /** What the refresh needs of the team: the agents, a render, and a way to set the picture. */
@@ -6,9 +6,9 @@ import { resolveCharacter } from "../../characters/index.ts";
6
6
  import { squarePng } from "../attachments/square-png.ts";
7
7
  import type { ImageDrawer } from "../contract/providers.ts";
8
8
  import { ConfigError } from "../domain/errors.ts";
9
- import { ProviderError } from "../errors.ts";
10
9
  import type { HttpRoute } from "../http/listeners.ts";
11
- import type { AvatarStudio } from "../services.ts";
10
+ import { ProviderError } from "../kernel/errors.ts";
11
+ import type { AvatarStudio } from "../plugin-api/services.ts";
12
12
  import { characterPng } from "./character-png.ts";
13
13
  import { fallbackAvatar } from "./fallback-avatar.ts";
14
14
 
@@ -1,6 +1,6 @@
1
1
  import type { Judge } from "../contract/providers.ts";
2
- import { type OwnerIdentity, ownerWords } from "../identity.ts";
3
- import type { Logger } from "../log.ts";
2
+ import { type OwnerIdentity, ownerWords } from "../identity/owner-identity.ts";
3
+ import type { Logger } from "../kernel/log.ts";
4
4
  import type { Agent, GroupMessage } from "./agent-store.ts";
5
5
 
6
6
  /** Members at or above this relevance answer an owner message nobody is named in; a message naming members is answered by them alone. */
@@ -3,7 +3,7 @@ import type { ChannelKey, TurnResult } from "../domain/conversation.ts";
3
3
  import { AgentError } from "../domain/errors.ts";
4
4
  import type { RoundEnd, RoundProgress } from "../domain/round.ts";
5
5
  import { messages } from "../i18n/index.ts";
6
- import type { Speaker } from "../speakers.ts";
6
+ import type { Speaker } from "../identity/speakers.ts";
7
7
  import { groupTurnText } from "./agent-prompt.ts";
8
8
  import type { Agent, AgentGroup } from "./agent-store.ts";
9
9
  import {