pi-roundtable 0.24.2 → 0.26.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 (81) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/docs/plugins.md +174 -7
  3. package/package.json +1 -1
  4. package/src/cli/checks/agent-tools.ts +23 -0
  5. package/src/cli/doctor.ts +6 -0
  6. package/src/cli/principal.ts +9 -2
  7. package/src/core/agents/agent-book.ts +155 -0
  8. package/src/core/agents/agent-ports.ts +5 -1
  9. package/src/core/agents/agent-prompt.ts +6 -1
  10. package/src/core/agents/agent-schema.ts +3 -0
  11. package/src/core/agents/agent-statements.ts +179 -0
  12. package/src/core/agents/agent-store.ts +184 -191
  13. package/src/core/agents/agent-team-fixture.ts +21 -2
  14. package/src/core/agents/agent-team.ts +44 -36
  15. package/src/core/agents/agent-tools.ts +12 -6
  16. package/src/core/agents/team-editing.ts +154 -32
  17. package/src/core/agents/team-keys.ts +17 -0
  18. package/src/core/agents/team-lifecycle.ts +96 -23
  19. package/src/core/agents/team-options.ts +9 -4
  20. package/src/core/agents/team-selection.ts +32 -0
  21. package/src/core/builtin/agent-server.ts +30 -5
  22. package/src/core/builtin/channel-context.ts +21 -0
  23. package/src/core/builtin/discord.ts +4 -1
  24. package/src/core/builtin/prompts.ts +40 -0
  25. package/src/core/builtin/skills.ts +9 -5
  26. package/src/core/config/config-schema.ts +22 -6
  27. package/src/core/config/config.ts +30 -2
  28. package/src/core/config/conversations.ts +21 -0
  29. package/src/core/config/profiles.ts +53 -0
  30. package/src/core/contract/channel-context.ts +106 -0
  31. package/src/core/contract/surface.ts +16 -0
  32. package/src/core/conversations/conversation-registry.ts +6 -0
  33. package/src/core/conversations/conversation-retention.ts +107 -0
  34. package/src/core/conversations/conversation-store.ts +6 -0
  35. package/src/core/conversations/conversations-plugin.ts +19 -3
  36. package/src/core/define-roundtable.ts +12 -2
  37. package/src/core/discord/channel-context.ts +47 -78
  38. package/src/core/discord/discord-surface.ts +16 -0
  39. package/src/core/events.ts +1 -0
  40. package/src/core/host-registration.ts +4 -0
  41. package/src/core/host.ts +3 -1
  42. package/src/core/i18n/agent-panel.ts +4 -0
  43. package/src/core/i18n/cards.ts +1 -1
  44. package/src/core/identity/actor-facts.ts +7 -0
  45. package/src/core/identity/identity-plugin.ts +27 -5
  46. package/src/core/identity/identity-port.ts +62 -0
  47. package/src/core/identity/identity-schema.ts +2 -0
  48. package/src/core/identity/identity-service.ts +45 -52
  49. package/src/core/identity/identity-view.ts +1 -0
  50. package/src/core/identity/person-profiles.ts +275 -0
  51. package/src/core/identity/principal-tables.ts +10 -0
  52. package/src/core/identity/profile-choices.ts +45 -0
  53. package/src/core/identity/profile-memory.ts +65 -0
  54. package/src/core/identity/profile-picture.ts +117 -0
  55. package/src/core/identity/profiles-view.ts +20 -0
  56. package/src/core/identity/profiles.ts +82 -0
  57. package/src/core/modules/host-shell/shell-policy.ts +18 -3
  58. package/src/core/modules/prompts/prompt-documents.ts +425 -0
  59. package/src/core/modules/prompts/prompt-history.ts +103 -0
  60. package/src/core/modules/skills/skill-contract.ts +52 -0
  61. package/src/core/modules/skills/skill-document-files.ts +66 -0
  62. package/src/core/modules/skills/skill-registry.ts +136 -8
  63. package/src/core/modules/skills/skill-rules.ts +94 -0
  64. package/src/core/modules/skills/skill-store.ts +88 -17
  65. package/src/core/modules/skills/skill-tools.ts +18 -10
  66. package/src/core/plugin.ts +40 -0
  67. package/src/core/registry/contributions.ts +8 -1
  68. package/src/core/runtime/chat-only.ts +32 -0
  69. package/src/core/runtime/conversation-sessions.ts +2 -1
  70. package/src/core/runtime/extensions/agent-prompt.ts +20 -5
  71. package/src/core/runtime/extensions/persona-prompt.ts +39 -0
  72. package/src/core/runtime/extensions/prompt-read.ts +22 -0
  73. package/src/core/runtime/runtime-plugin.ts +1 -0
  74. package/src/core/runtime/runtime-types.ts +3 -1
  75. package/src/core/runtime/session-factory.ts +70 -65
  76. package/src/core/runtime/session-helpers.ts +27 -0
  77. package/src/core/services.ts +97 -33
  78. package/src/index.ts +31 -0
  79. package/src/kit/index.ts +1 -0
  80. package/src/kit/oidc.ts +16 -0
  81. package/src/testing.ts +1 -0
@@ -3,6 +3,7 @@ import type { CharacterInput, CharacterSpec } from "../characters/index.ts";
3
3
  import type { Agent, AgentGroup } from "./agents/agent-rules.ts";
4
4
  import type { AvatarMode } from "./agents/agent-tools.ts";
5
5
  import type { TeamStatus } from "./agents/team-status.ts";
6
+ import type { ChannelContexts } from "./contract/channel-context.ts";
6
7
  import type {
7
8
  BackgroundRunsAs,
8
9
  ScheduledOutcome,
@@ -14,6 +15,7 @@ import type { PendingConfirmation } from "./domain/conversation.ts";
14
15
  import type { HttpRoute } from "./http/listeners.ts";
15
16
  import type { IdentityLinks } from "./identity/identity-links.ts";
16
17
  import type { IdentityService } from "./identity/identity-service.ts";
18
+ import type { PersonProfiles } from "./identity/profiles.ts";
17
19
  import type { ThinkingLevel, ThinkingSetting } from "./models.ts";
18
20
  import type { ConversationModes } from "./modes/conversation-modes.ts";
19
21
  import type {
@@ -25,6 +27,10 @@ import type {
25
27
  MemoryKind,
26
28
  PromptMemory,
27
29
  } from "./modules/memory/owner-memory-store.ts";
30
+ import type {
31
+ PromptDocuments,
32
+ PromptVersion,
33
+ } from "./modules/prompts/prompt-documents.ts";
28
34
  import type {
29
35
  PrecheckFinding,
30
36
  PrecheckRegistry,
@@ -34,11 +40,9 @@ import type {
34
40
  Schedule,
35
41
  ScheduleChange,
36
42
  } from "./modules/schedules/schedule-store.ts";
37
- import type {
38
- SkillCatalogEntry,
39
- SkillSet,
40
- } from "./modules/skills/skill-rules.ts";
43
+ import type { SkillRegistry } from "./modules/skills/skill-contract.ts";
41
44
  import type { AgentTurnScope, ChannelKey } from "./sessions.ts";
45
+ import type { Speaker } from "./speakers.ts";
42
46
  import type { DispatchThreads } from "./threads/dispatch-threads.ts";
43
47
 
44
48
  // The services the built-in plugins provide, and the ports they keep to. Each port is an
@@ -51,6 +55,10 @@ import type { DispatchThreads } from "./threads/dispatch-threads.ts";
51
55
  */
52
56
  export const IDENTITY: ServiceKey<IdentityService> =
53
57
  serviceKey<IdentityService>("roundtable.identity");
58
+ /** How the core names a person (linked accounts' names and pictures, the chosen one, plugin sources); from the `identity` plugin. */
59
+ export const PROFILES: ServiceKey<PersonProfiles> = serviceKey<PersonProfiles>(
60
+ "roundtable.profiles",
61
+ );
54
62
  /**
55
63
  * Links a person's own account to their principal, which `IDENTITY` cannot. Provided by the
56
64
  * `identity` plugin only when the configuration lists providers in `access.selfLink`; read it with
@@ -90,6 +98,9 @@ export const MODES: ServiceKey<ConversationModes> =
90
98
  */
91
99
  export const THREADS: ServiceKey<DispatchThreads> =
92
100
  serviceKey<DispatchThreads>("roundtable.threads");
101
+ /** The channel context of any surface, chosen by the message's channel key as `THREADS` is; provided by the `channel-context` plugin, which every host registers. */
102
+ export const CHANNEL_CONTEXT: ServiceKey<ChannelContexts> =
103
+ serviceKey<ChannelContexts>("roundtable.channel-context");
93
104
  /** The agent server: its team, its directory, the runtime that runs every agent turn. Provided by the agent-server plugin. */
94
105
  export const AGENTS: ServiceKey<AgentServer> = serviceKey<AgentServer>(
95
106
  "roundtable.agents",
@@ -145,6 +156,16 @@ export const SKILLS: ServiceKey<SkillRegistry> = serviceKey<SkillRegistry>(
145
156
  },
146
157
  );
147
158
 
159
+ /**
160
+ * The prompt texts the owner edits in the app, each with a file version, an override and a
161
+ * history. Provided by the built-in `prompts` plugin, which registers `shared` and `guest` (the
162
+ * prompts of the agent server) and which every plugin set up after it may register more with; a
163
+ * plugin reads a document's `text()` when it builds a prompt, so an override applies from the next
164
+ * turn. Read it with `get`: the plugin is always on.
165
+ */
166
+ export const PROMPTS: ServiceKey<PromptDocuments> =
167
+ serviceKey<PromptDocuments>("roundtable.prompts");
168
+
148
169
  /** What the agent server builds, for the plugins set up after it. */
149
170
  export interface AgentServer {
150
171
  team: AgentTeam;
@@ -209,6 +230,29 @@ export interface AgentDirectory {
209
230
  groupByChannel(channelId: string): AgentGroup | undefined;
210
231
  }
211
232
 
233
+ /** What an owner gives to create an agent: the fields of `agent_create`, with the settings `update` takes. */
234
+ export interface NewAgent {
235
+ /** Permanent: lowercase letters, digits and dashes, 1 to 32. */
236
+ name: string;
237
+ displayName: string;
238
+ prompt: string;
239
+ /** Fields of its look; any left out come from the look its role suggests. */
240
+ character?: CharacterInput;
241
+ /** Its opening task; without it the agent only exists. */
242
+ task?: string;
243
+ /**
244
+ * The surface whose room the opening task runs in, so the person who asked sees it start
245
+ * there. Without it, or for a surface that hosts no rooms, the task runs where `agent_create`
246
+ * runs it: the agent's Discord channel, else its first room.
247
+ */
248
+ openIn?: string;
249
+ category?: string;
250
+ /** Skills it carries; refused when the skills addon is off. */
251
+ skills?: string[];
252
+ model?: string;
253
+ thinking?: string;
254
+ }
255
+
212
256
  /** What an agent's settings may change, as `update` takes it. */
213
257
  export interface AgentChange {
214
258
  displayName?: string;
@@ -259,8 +303,54 @@ export interface AgentTeam {
259
303
  postAs(caller: AgentTurnScope, text: string): Promise<void>;
260
304
  /** The assistant's own notice, posted in the coordinator's channel under its name. */
261
305
  announce(text: string): Promise<void>;
262
- /** Changes an agent's display name, prompt, model, or thinking level; a model must be one the host runs. */
263
- update(name: string, change: AgentChange): Promise<string>;
306
+ /**
307
+ * Changes an agent's display name, prompt, model, or thinking level; a model must be one the
308
+ * host runs. `by` names who asks; a changed prompt is kept in the agent's prompt history under it.
309
+ */
310
+ update(name: string, change: AgentChange, by?: string): Promise<string>;
311
+ /** The changes of an agent's prompt, newest first: who made each, when, and the text it replaced. */
312
+ promptHistory(name: string, limit?: number): Promise<PromptVersion[]>;
313
+ /**
314
+ * Creates an agent for an owner, outside any agent turn: the checks, picture, channel and
315
+ * opening task of `agent_create`, with `speaker` as the one who asked. `model` and `thinking`
316
+ * take what `update` takes and are checked before anything is made; `task` is optional, and
317
+ * without it the agent waits in its room. Throws AgentError for a bad or taken name, an
318
+ * unusable model or an unknown skill.
319
+ */
320
+ createAgent(speaker: Speaker, input: NewAgent): Promise<Agent>;
321
+ /**
322
+ * Archives an agent or group like the `archive` tool: it stops answering, its schedules are
323
+ * cancelled, an agent leaves its groups, and its history is kept. `caller` is the agent that
324
+ * asks, which cannot archive itself; an owner's request has none. The coordinator cannot be
325
+ * archived.
326
+ */
327
+ archive(caller: AgentTurnScope | undefined, name: string): Promise<string>;
328
+ /**
329
+ * Returns an archived agent or group to the active ones. An agent rejoins no group; a group
330
+ * needs all its members active. Throws AgentError for an unknown or active name.
331
+ */
332
+ restore(name: string): Promise<string>;
333
+ /**
334
+ * Deletes an archived agent or group for good and frees its name. Throws AgentError for an
335
+ * unknown name, for an active one (archive it first), and for an agent the host's seeds name,
336
+ * which the next start would seed again. `cleanup` is a surface's own part of the delete (what
337
+ * it kept under the name): it runs once the checks have passed and before anything is deleted,
338
+ * and one that throws leaves the agent or group in place, so the delete can be tried again.
339
+ */
340
+ remove(name: string, cleanup?: () => Promise<void>): Promise<string>;
341
+ /** Creates a group of 2 to 6 agents; the host is the first member unless given. */
342
+ createGroup(input: {
343
+ name: string;
344
+ displayName: string;
345
+ members: string[];
346
+ host?: string;
347
+ category?: string;
348
+ }): Promise<string>;
349
+ /** Changes a group's display name, members (all of them) or host. */
350
+ updateGroup(
351
+ name: string,
352
+ change: { displayName?: string; members?: string[]; host?: string },
353
+ ): Promise<string>;
264
354
  /**
265
355
  * Changes an agent's look: `input` is resolved over its current character (a new class keeps
266
356
  * its colors unless the input gives a palette or colors), rendered, and stored with the new
@@ -406,30 +496,4 @@ export interface SpeakerMemory {
406
496
  remove(text: string): Promise<string[]>;
407
497
  }
408
498
 
409
- /** The skills agents carry: built in, linked from repositories, or written by an agent. */
410
- export interface SkillRegistry {
411
- /** The built-in skills plus the named registered ones, resolved to their files. */
412
- resolve(names: readonly string[]): SkillSet;
413
- /** What an agent carries, built-in skills included. */
414
- carried(agent: string): SkillSet;
415
- /** The registered skills an agent carries, as the dashboard lists them. */
416
- carriedNames(agent: string): string[];
417
- /** An agent's skills as `agent_get` shows them. */
418
- describeCarried(agent: string): string;
419
- /** Every skill, built-in ones first. */
420
- catalog(): SkillCatalogEntry[];
421
- /** Every skill, or those of a group or matching a query, as the `skill_list` tool shows them. */
422
- list(filter?: { group?: string; query?: string }): string;
423
- /** The skills linked from a managed repository. */
424
- linkedFrom(repo: string): string[];
425
- /** Throws AgentError when a name is not registered; built-in names are carried already. */
426
- checkRegistered(names: readonly string[]): void;
427
- /** Links the skill at a repository path, or every child folder with a SKILL.md. */
428
- link(repo: string, path: string): Promise<string>;
429
- /** Adds and removes an agent's registered skills together, or changes nothing; returns what it carries after. */
430
- attach(
431
- agent: string,
432
- add: readonly string[],
433
- remove: readonly string[],
434
- ): Promise<string[]>;
435
- }
499
+ export type { SkillRegistry } from "./modules/skills/skill-contract.ts";
package/src/index.ts CHANGED
@@ -47,7 +47,9 @@ export type {
47
47
  RoundtableConfig,
48
48
  TierConfig,
49
49
  } from "./core/config/config.ts";
50
+ export type { ConversationsConfig } from "./core/config/conversations.ts";
50
51
  export type { LimitsConfig } from "./core/config/limits.ts";
52
+ export type { ProfilesConfig } from "./core/config/profiles.ts";
51
53
  export type { SkillsConfig } from "./core/config/skills-config.ts";
52
54
  export type {
53
55
  AttachmentPort,
@@ -58,6 +60,12 @@ export type {
58
60
  TurnAttachmentOptions,
59
61
  } from "./core/contract/attachments.ts";
60
62
  export { AttachmentRefusal } from "./core/contract/attachments.ts";
63
+ export type {
64
+ ChannelContextSource,
65
+ ChannelContextSourceAttachment,
66
+ ChannelContexts,
67
+ ChannelContextVerdict,
68
+ } from "./core/contract/channel-context.ts";
61
69
  export type {
62
70
  Admission,
63
71
  AttachmentContent,
@@ -213,6 +221,12 @@ export type {
213
221
  RoleSource,
214
222
  } from "./core/identity/principal-store.ts";
215
223
  export { SYSTEM_PRINCIPAL } from "./core/identity/principal-store.ts";
224
+ export type {
225
+ PersonDisplay,
226
+ PersonProfiles,
227
+ ProfileRules,
228
+ ProfileSource,
229
+ } from "./core/identity/profiles.ts";
216
230
  export type {
217
231
  Approval,
218
232
  ApprovalDetails,
@@ -264,6 +278,14 @@ export type {
264
278
  PromptMemory,
265
279
  } from "./core/modules/memory/owner-memory-store.ts";
266
280
  export { MEMORY_KINDS } from "./core/modules/memory/owner-memory-store.ts";
281
+ export type {
282
+ PromptDocumentSpec,
283
+ PromptDocuments,
284
+ PromptDocumentView,
285
+ PromptHandle,
286
+ PromptVersion,
287
+ } from "./core/modules/prompts/prompt-documents.ts";
288
+ export { PromptConflictError } from "./core/modules/prompts/prompt-documents.ts";
267
289
  export type { PrecheckTool } from "./core/modules/schedules/precheck-tools.ts";
268
290
  export type {
269
291
  Precheck,
@@ -291,10 +313,15 @@ export type {
291
313
  export type {
292
314
  ResolvedSkill,
293
315
  SkillCatalogEntry,
316
+ SkillDocument,
294
317
  SkillSet,
295
318
  SkillSource,
319
+ SkillVersion,
296
320
  } from "./core/modules/skills/skill-rules.ts";
321
+ export { SkillConflictError } from "./core/modules/skills/skill-rules.ts";
297
322
  export type {
323
+ ActionEvent,
324
+ AgentTools,
298
325
  Contribution,
299
326
  EventHandlers,
300
327
  EventSink,
@@ -339,6 +366,7 @@ export type {
339
366
  DelegationRequest,
340
367
  Delegator,
341
368
  MemoryStore,
369
+ NewAgent,
342
370
  ScheduleStore,
343
371
  SkillRegistry,
344
372
  SpeakerMemory,
@@ -348,6 +376,7 @@ export type {
348
376
  export {
349
377
  AGENTS,
350
378
  BACKGROUND_TURNS,
379
+ CHANNEL_CONTEXT,
351
380
  CONVERSATIONS,
352
381
  DELEGATION,
353
382
  IDENTITY,
@@ -355,6 +384,8 @@ export {
355
384
  MEMORY,
356
385
  MODES,
357
386
  PRECHECKS,
387
+ PROFILES,
388
+ PROMPTS,
358
389
  RUNTIME,
359
390
  SCHEDULES,
360
391
  SKILLS,
package/src/kit/index.ts CHANGED
@@ -116,6 +116,7 @@ export {
116
116
  SCHEDULE_TOOLS,
117
117
  scheduleToolSpecs,
118
118
  } from "./mirror.ts";
119
+ export { oidcIdentity, oidcProvider } from "./oidc.ts";
119
120
  export type {
120
121
  OpsAlertKind,
121
122
  OpsAlertsOptions,
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The identity provider of an OpenID issuer, as `access.owners[].identities`, `selfLink.providers`
3
+ * and `ActorFacts.provider` write it: `oidc:<base64url(issuer)>`. The issuer is encoded so its own
4
+ * colons stay apart from the subject's.
5
+ */
6
+ export function oidcProvider(issuer: string): string {
7
+ return `oidc:${Buffer.from(issuer).toString("base64url")}`;
8
+ }
9
+
10
+ /**
11
+ * The identity of one OpenID subject, `oidcProvider(issuer)` and the subject: the form
12
+ * `roundtable principal link` and `access.owners[].identities` take, and the 0.8 web speaker id.
13
+ */
14
+ export function oidcIdentity(issuer: string, subject: string): string {
15
+ return `${oidcProvider(issuer)}:${subject}`;
16
+ }
package/src/testing.ts CHANGED
@@ -455,6 +455,7 @@ export async function testPlugin(
455
455
  timeZone: "UTC",
456
456
  now: () => new Date(),
457
457
  characterSkins: CATALOG.skins,
458
+ agentTools: "full",
458
459
  ...options.env,
459
460
  };
460
461
  // What the agent server does with the slot: the provider's runtime serves `context.turns`.