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.
- package/CHANGELOG.md +148 -0
- package/README.md +10 -6
- package/README.zh-TW.md +144 -0
- package/docs/plugins.md +1448 -66
- package/examples/echo-runtime.test.ts +122 -0
- package/examples/echo-runtime.ts +107 -0
- package/examples/events.test.ts +1 -0
- package/examples/events.ts +2 -2
- package/examples/fake-surface.test.ts +180 -0
- package/examples/fake-surface.ts +109 -0
- package/examples/interactions.test.ts +12 -3
- package/examples/interactions.ts +19 -19
- package/examples/shared-services.test.ts +74 -0
- package/examples/shared-services.ts +60 -0
- package/examples/study-room.test.ts +69 -0
- package/examples/study-room.ts +52 -0
- package/examples/support-desk.test.ts +34 -0
- package/examples/support-desk.ts +40 -0
- package/package.json +11 -3
- package/src/cli/checks/database.ts +11 -30
- package/src/cli/checks/images.ts +19 -0
- package/src/cli/doctor.ts +6 -0
- package/src/cli/main.ts +2 -1
- package/src/core/agents/agent-claim.ts +42 -16
- package/src/core/agents/agent-messages.ts +4 -4
- package/src/core/agents/agent-ports.ts +8 -21
- package/src/core/agents/agent-prompt.ts +3 -1
- package/src/core/agents/agent-store.ts +6 -4
- package/src/core/agents/agent-team-fixture.ts +389 -0
- package/src/core/agents/agent-team.ts +26 -25
- package/src/core/agents/agent-tools.ts +34 -15
- package/src/core/agents/avatar-studio.ts +40 -6
- package/src/core/agents/fallback-avatar.ts +85 -0
- package/src/core/agents/team-editing.ts +49 -10
- package/src/core/agents/team-keys.ts +22 -9
- package/src/core/agents/team-layout.ts +4 -3
- package/src/core/agents/team-lifecycle.ts +28 -2
- package/src/core/agents/team-options.ts +9 -5
- package/src/core/agents/team-status.ts +4 -4
- package/src/core/agents/team-text.ts +8 -6
- package/src/core/agents/team-turn-types.ts +4 -4
- package/src/core/agents/team-turns.ts +6 -5
- package/src/core/builtin/agent-server.ts +187 -121
- package/src/core/builtin/discord-admin.ts +41 -0
- package/src/core/builtin/discord.ts +65 -40
- package/src/core/builtin/modules.ts +67 -58
- package/src/core/builtin/session-tool.ts +24 -0
- package/src/core/builtin/skills.ts +72 -0
- package/src/core/builtin/stores.ts +55 -31
- package/src/core/config/config.ts +45 -4
- package/src/core/config/schema.ts +6 -0
- package/src/core/contract/channels.ts +54 -14
- package/src/core/contract/providers.ts +17 -0
- package/src/core/contract/runtime.ts +138 -0
- package/src/core/contract/services.ts +45 -0
- package/src/core/contract/surface.ts +88 -0
- package/src/core/db/migrations.ts +118 -3
- package/src/core/define-roundtable.ts +70 -46
- package/src/core/define.ts +2 -1
- package/src/core/discord/agent-commands.ts +39 -14
- package/src/core/discord/agent-panel.ts +66 -0
- package/src/core/discord/channel-executor.ts +6 -3
- package/src/core/discord/channel-operations.ts +14 -11
- package/src/core/discord/command-collection.ts +46 -0
- package/src/core/{registry/interactions.ts → discord/compose-commands.ts} +5 -5
- package/src/core/discord/connection.ts +35 -0
- package/src/core/discord/discord-surface.ts +32 -94
- package/src/core/discord/dispatch-threads.ts +2 -2
- package/src/core/discord/inbound-message.ts +99 -0
- package/src/core/discord/interaction-module.ts +57 -1
- package/src/core/discord/owner-cards.ts +4 -4
- package/src/core/discord/owner-command.ts +44 -11
- package/src/core/discord/owner-discord.ts +2 -2
- package/src/core/discord/schedule-commands.ts +21 -18
- package/src/core/discord/stop-button.ts +44 -1
- package/src/core/domain/attachment.ts +12 -8
- package/src/core/domain/conversation.ts +3 -4
- package/src/core/domain/owner-prompts.ts +5 -5
- package/src/core/domain/ports.ts +9 -53
- package/src/core/freeze.ts +9 -0
- package/src/core/host.ts +255 -82
- package/src/core/http/listeners.ts +55 -20
- package/src/core/i18n/agent-panel.ts +4 -0
- package/src/core/i18n/index.ts +12 -2
- package/src/core/i18n/owner.ts +7 -1
- package/src/core/i18n/schedules.ts +12 -6
- package/src/core/identity.ts +1 -1
- package/src/core/judging/effort-judge.ts +25 -3
- package/src/core/log.ts +21 -3
- package/src/core/models.ts +2 -2
- package/src/core/modules/background/background-turns.ts +6 -4
- package/src/core/modules/delegation/delegate.ts +3 -2
- package/src/core/modules/delegation/delegator.ts +15 -13
- package/src/core/modules/delegation/{sol-worker.ts → web-research-worker.ts} +6 -6
- package/src/core/modules/discord-admin/discord-admin.ts +6 -6
- package/src/core/modules/host-shell/shell-policy.ts +8 -3
- package/src/core/modules/memory/owner-memory-store.ts +27 -25
- package/src/core/modules/memory/owner-memory.ts +9 -13
- package/src/core/modules/schedules/recurrence.ts +5 -3
- package/src/core/modules/schedules/schedule-store.ts +11 -11
- package/src/core/modules/schedules/schedule-tools.ts +22 -20
- package/src/core/modules/schedules/scheduler.ts +7 -2
- package/src/core/modules/schedules/schedules.ts +9 -3
- package/src/core/modules/skills/skill-registry.ts +3 -2
- package/src/core/modules/skills/skill-store.ts +2 -15
- package/src/core/modules/skills/skill-tools.ts +10 -4
- package/src/core/ops/error-reporter.ts +1 -1
- package/src/core/plugin.ts +232 -28
- package/src/core/registry/contributions.ts +173 -14
- package/src/core/registry/providers.ts +35 -5
- package/src/core/registry/services.ts +229 -0
- package/src/core/routing/channel-queue.ts +5 -0
- package/src/core/routing/channel-router.ts +21 -7
- package/src/core/routing/conversation-turns.ts +139 -0
- package/src/core/routing/message-text.ts +9 -2
- package/src/core/routing/surface-port.ts +39 -0
- package/src/core/runtime/conversation-sessions.ts +4 -3
- package/src/core/runtime/extensions/confirmation-fixture.ts +11 -0
- package/src/core/runtime/extensions/confirmation-gate.ts +11 -9
- package/src/core/runtime/mcp.ts +1 -1
- package/src/core/runtime/pending-confirmation-store.ts +10 -12
- package/src/core/runtime/pi-agent-runtime.ts +9 -6
- package/src/core/runtime/prompt-slot.ts +8 -3
- package/src/core/runtime/runtime-types.ts +9 -35
- package/src/core/runtime/session-factory.ts +21 -5
- package/src/core/runtime/text-tools.ts +1 -3
- package/src/core/services.ts +238 -90
- package/src/core/sessions.ts +3 -2
- package/src/core/shared/{profile-tools.ts → active-tools.ts} +2 -2
- package/src/core/shared/delegate-tool.ts +4 -3
- package/src/core/shared/schedule-tools.ts +22 -13
- package/src/core/shared/session-messages.ts +1 -1
- package/src/core/speakers.ts +6 -38
- package/src/core/testing/database.ts +1 -7
- package/src/core/testing/eager-catalog.ts +30 -0
- package/src/core/testing/locale.ts +23 -5
- package/src/core/testing/modules.ts +105 -41
- package/src/core/testing/test-host.ts +279 -0
- package/src/core/testing/tool-set.ts +64 -0
- package/src/core/time.ts +6 -1
- package/src/core/tool-set.snapshot.json +288 -0
- package/src/core/tool-tiers.ts +17 -57
- package/src/discord/index.ts +64 -0
- package/src/index.ts +181 -10
- package/src/kit/channels.ts +14 -0
- package/src/kit/domain.ts +18 -0
- package/src/kit/holds.ts +4 -0
- package/src/kit/index.ts +129 -0
- package/src/kit/judging.ts +10 -0
- package/src/kit/memory.ts +3 -0
- package/src/kit/mirror.ts +19 -0
- package/src/kit/presentation.ts +7 -0
- package/src/kit/shell.ts +7 -0
- package/src/kit/skills.ts +8 -0
- package/src/kit/support.ts +21 -0
- package/src/kit/threads.ts +7 -0
- package/src/kit/tools.ts +14 -0
- package/src/kit/worker.ts +16 -0
- package/src/testing.ts +394 -34
- package/examples/guide.test.ts +0 -52
- package/src/cli/add-plugin.test.ts +0 -107
- package/src/cli/checks/basic.test.ts +0 -276
- package/src/cli/checks/database.test.ts +0 -117
- package/src/cli/checks/discord.test.ts +0 -200
- package/src/cli/cli.test.ts +0 -122
- package/src/cli/config-edit.test.ts +0 -130
- package/src/cli/doctor.test.ts +0 -184
- package/src/cli/init.test.ts +0 -127
- package/src/cli/size.test.ts +0 -9
- package/src/cli/templates.test.ts +0 -129
- package/src/cli/testing/fixtures.ts +0 -106
- package/src/core/agents/agent-claim.test.ts +0 -142
- package/src/core/agents/agent-dashboard.test.ts +0 -120
- package/src/core/agents/agent-guild.test.ts +0 -124
- package/src/core/agents/agent-store.test.ts +0 -205
- package/src/core/agents/avatar-studio.test.ts +0 -88
- package/src/core/agents/group-round.test.ts +0 -143
- package/src/core/agents/owner-identity.test.ts +0 -172
- package/src/core/agents/team-turns.test.ts +0 -278
- package/src/core/attachments/attachments.test.ts +0 -85
- package/src/core/boundary.test.ts +0 -45
- package/src/core/builtin/modules.test.ts +0 -127
- package/src/core/config/config.test.ts +0 -135
- package/src/core/contract/discord.ts +0 -33
- package/src/core/db/migrations.test.ts +0 -237
- package/src/core/define-roundtable.test.ts +0 -134
- package/src/core/define.test.ts +0 -144
- package/src/core/discord/agent-commands.test.ts +0 -58
- package/src/core/discord/agent-discord.test.ts +0 -70
- package/src/core/discord/dispatch-thread-host.test.ts +0 -114
- package/src/core/discord/dispatch-threads.test.ts +0 -94
- package/src/core/discord/owner-cards.test.ts +0 -435
- package/src/core/discord/owner-discord.test.ts +0 -325
- package/src/core/domain/expression.ts +0 -21
- package/src/core/domain/profile.ts +0 -32
- package/src/core/drain.test.ts +0 -46
- package/src/core/events.test.ts +0 -81
- package/src/core/holds.test.ts +0 -54
- package/src/core/host.test.ts +0 -536
- package/src/core/http/listeners.test.ts +0 -164
- package/src/core/i18n/i18n.test.ts +0 -139
- package/src/core/identity.test.ts +0 -18
- package/src/core/judging/effort-judge.test.ts +0 -112
- package/src/core/judging/model-judge.test.ts +0 -126
- package/src/core/modules/delegation/delegator.test.ts +0 -170
- package/src/core/modules/memory/owner-memory-store.test.ts +0 -244
- package/src/core/modules/schedules/schedule.test.ts +0 -358
- package/src/core/modules/skills/skill-kind.test.ts +0 -55
- package/src/core/modules/skills/skill-registry.test.ts +0 -376
- package/src/core/ops/error-reporter.test.ts +0 -283
- package/src/core/presentation/card-cadence.ts +0 -41
- package/src/core/presentation/presentation.test.ts +0 -166
- package/src/core/public-entry.test.ts +0 -59
- package/src/core/registry/contributions.test.ts +0 -215
- package/src/core/registry/interactions.test.ts +0 -87
- package/src/core/registry/providers.test.ts +0 -103
- package/src/core/routing/channel-queue.test.ts +0 -31
- package/src/core/routing/channel-router.test.ts +0 -326
- package/src/core/routing/conversation-kind.ts +0 -14
- package/src/core/routing/settle-turn.test.ts +0 -21
- package/src/core/runtime/compaction-tiers.test.ts +0 -227
- package/src/core/runtime/extensions/ask-user.test.ts +0 -114
- package/src/core/runtime/extensions/self-compact-guard.test.ts +0 -50
- package/src/core/runtime/pending-confirmation-store.test.ts +0 -52
- package/src/core/runtime/session-archive.test.ts +0 -20
- package/src/core/runtime/steerable-run.test.ts +0 -264
- package/src/core/runtime/text-tools.test.ts +0 -110
- package/src/core/runtime/turn-answer.test.ts +0 -72
- package/src/core/runtime/worker-task.test.ts +0 -82
- package/src/core/services.test.ts +0 -28
- package/src/core/sessions.test.ts +0 -85
- package/src/core/shared/unix-server.ts +0 -18
- package/src/core/size.test.ts +0 -9
- package/src/core/speakers.test.ts +0 -78
- package/src/core/testing/file-size.ts +0 -34
- package/src/core/time.test.ts +0 -166
- package/src/core/tool-tiers.test.ts +0 -117
- package/src/entries.test.ts +0 -112
- package/src/testing.test.ts +0 -156
package/src/core/plugin.ts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import type { SQL } from "bun";
|
|
2
2
|
import type { AgentSeed } from "./agents/agent-store.ts";
|
|
3
3
|
import type {
|
|
4
|
+
BackgroundTarget,
|
|
4
5
|
ChannelClaim,
|
|
5
6
|
ConversationPort,
|
|
6
7
|
QueuePort,
|
|
7
8
|
} from "./contract/channels.ts";
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
9
|
+
import type { Providers, ResolvedProviders } from "./contract/providers.ts";
|
|
10
|
+
import type { ServiceKey, Services } from "./contract/services.ts";
|
|
11
|
+
import type { ChatSurface, SurfacePort } from "./contract/surface.ts";
|
|
10
12
|
import type { Migration } from "./db/migrations.ts";
|
|
11
13
|
import type { ToolContribution } from "./define.ts";
|
|
14
|
+
import { PluginError } from "./errors.ts";
|
|
12
15
|
import type { HoldCheck, HoldRule } from "./holds.ts";
|
|
13
16
|
import type { HttpRoute } from "./http/listeners.ts";
|
|
17
|
+
import type { Locale } from "./i18n/index.ts";
|
|
14
18
|
import type { Logger } from "./log.ts";
|
|
15
|
-
import type {
|
|
16
|
-
import type { CoreAccess, CoreRegistry } from "./services.ts";
|
|
19
|
+
import type { ConversationTurns } from "./routing/conversation-turns.ts";
|
|
17
20
|
import type {
|
|
18
21
|
AgentTurnScope,
|
|
19
22
|
ChannelKey,
|
|
@@ -21,7 +24,7 @@ import type {
|
|
|
21
24
|
SessionTool,
|
|
22
25
|
ToolSelection,
|
|
23
26
|
} from "./sessions.ts";
|
|
24
|
-
import type { Speaker } from "./speakers.ts";
|
|
27
|
+
import type { Speaker, Tier } from "./speakers.ts";
|
|
25
28
|
import type { ToolTiers } from "./tool-tiers.ts";
|
|
26
29
|
|
|
27
30
|
/**
|
|
@@ -31,17 +34,34 @@ import type { ToolTiers } from "./tool-tiers.ts";
|
|
|
31
34
|
export interface Service {
|
|
32
35
|
name: string;
|
|
33
36
|
start?(): Promise<void> | void;
|
|
37
|
+
/**
|
|
38
|
+
* Starts once every service's `start` and the HTTP listeners are up, without holding up the
|
|
39
|
+
* boot: a failure is logged and heard as `serviceStarted` with `failed`, never fatal, and the
|
|
40
|
+
* other services' background starts still run. `stop` runs for it like for any started service.
|
|
41
|
+
*/
|
|
42
|
+
startInBackground?(): Promise<void>;
|
|
34
43
|
stop?(): Promise<void> | void;
|
|
35
44
|
/** Work still running or waiting, one entry each; the shutdown drain waits until every list is empty. */
|
|
36
45
|
busy?(): string[];
|
|
37
46
|
}
|
|
38
47
|
|
|
39
|
-
/** How
|
|
40
|
-
export type
|
|
48
|
+
/** How a service's background start ended. */
|
|
49
|
+
export type ServiceStartOutcome = "ready" | "failed";
|
|
50
|
+
|
|
51
|
+
/** A service's `startInBackground` ended, as a handler hears of it. */
|
|
52
|
+
export interface ServiceStartedEvent {
|
|
53
|
+
/** The plugin that contributed the service. */
|
|
54
|
+
plugin: string;
|
|
55
|
+
service: string;
|
|
56
|
+
outcome: ServiceStartOutcome;
|
|
57
|
+
}
|
|
41
58
|
|
|
42
|
-
/** One
|
|
59
|
+
/** One turn, as a handler hears of it: an agent's, or a conversation run through `context.turns`. */
|
|
43
60
|
export interface TurnEvent {
|
|
44
|
-
agent
|
|
61
|
+
/** The agent whose turn it is; absent for a conversation of another kind, such as a study room's. */
|
|
62
|
+
agent?: string;
|
|
63
|
+
/** The conversation's kind: "agent" for an agent's turn, else the kind the turn ran as, such as "owner" or "study". */
|
|
64
|
+
kind: string;
|
|
45
65
|
/** The channel the turn runs in: the agent's own, or a group's. */
|
|
46
66
|
channel: ChannelKey;
|
|
47
67
|
/** Who the turn is for. */
|
|
@@ -57,11 +77,15 @@ export interface TurnEndEvent extends TurnEvent {
|
|
|
57
77
|
|
|
58
78
|
/** What a plugin may react to; a handler that throws is logged and never stops the others. */
|
|
59
79
|
export interface EventHandlers {
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
80
|
+
/**
|
|
81
|
+
* A service's background start ended, in the order the services were contributed; the rest
|
|
82
|
+
* of the process runs either way. The agent server's is the `AGENT_TEAM_SERVICE` service of
|
|
83
|
+
* the `AGENT_SERVER_PLUGIN` plugin.
|
|
84
|
+
*/
|
|
85
|
+
serviceStarted?(event: ServiceStartedEvent): Promise<void> | void;
|
|
86
|
+
/** An agent's turn, or a turn run through `context.turns`, began. */
|
|
63
87
|
turnStarted?(turn: TurnEvent): Promise<void> | void;
|
|
64
|
-
/**
|
|
88
|
+
/** A turn that began ended, however it ended. */
|
|
65
89
|
turnEnded?(turn: TurnEndEvent): Promise<void> | void;
|
|
66
90
|
/** The team changed: an agent or group was created, edited, arranged, archived, or started over. */
|
|
67
91
|
changed?(): Promise<void> | void;
|
|
@@ -91,12 +115,24 @@ export interface PromptSection {
|
|
|
91
115
|
build(turn: PromptTurn): string | undefined;
|
|
92
116
|
}
|
|
93
117
|
|
|
118
|
+
/**
|
|
119
|
+
* The system prompt of every non-agent conversation of one kind. A conversation's kind is the
|
|
120
|
+
* string its claim returns from `startFresh` and passes as `kind` to `context.turns.run`.
|
|
121
|
+
*/
|
|
122
|
+
export interface Persona {
|
|
123
|
+
/** The conversation kind the prompt is for; "agent" is reserved for the agent server's own. */
|
|
124
|
+
kind: string;
|
|
125
|
+
/**
|
|
126
|
+
* The prompt text, read when a conversation's session is made, so text from the message catalog
|
|
127
|
+
* is in the host's language.
|
|
128
|
+
*/
|
|
129
|
+
prompt(): string;
|
|
130
|
+
}
|
|
131
|
+
|
|
94
132
|
/** What a plugin adds to the process; a plugin that adds nothing is refused. */
|
|
95
133
|
export interface Contribution {
|
|
96
134
|
services?: Service[];
|
|
97
135
|
events?: EventHandlers;
|
|
98
|
-
/** Modules that answer Discord interactions, with their subcommands under the root command. */
|
|
99
|
-
interactions?: InteractionContribution[];
|
|
100
136
|
/** Handlers on the host's HTTP listeners. */
|
|
101
137
|
http?: HttpRoute[];
|
|
102
138
|
/** Rules deciding which tool calls wait for the owner's approval, asked in contribution order. */
|
|
@@ -107,10 +143,39 @@ export interface Contribution {
|
|
|
107
143
|
sessionTools?: readonly SessionTool[];
|
|
108
144
|
/** The channels whose conversations the plugin owns. */
|
|
109
145
|
channels?: readonly ChannelClaim[];
|
|
146
|
+
/**
|
|
147
|
+
* Chat networks the plugin connects the host to, one per channel-key prefix. Each starts as a
|
|
148
|
+
* service named `surface:<prefix>` before the plugin's own services.
|
|
149
|
+
*/
|
|
150
|
+
surfaces?: readonly ChatSurface[];
|
|
151
|
+
/**
|
|
152
|
+
* The system prompts of conversation kinds the plugin owns, one per kind. A plugin that owns the
|
|
153
|
+
* owner's own conversations contributes the `"owner"` kind's prompt; without one those
|
|
154
|
+
* conversations start with an empty system prompt.
|
|
155
|
+
*/
|
|
156
|
+
personas?: readonly Persona[];
|
|
157
|
+
/**
|
|
158
|
+
* Tools startup refuses to run without, besides those each session tool requires: the host's
|
|
159
|
+
* preflight builds a session and fails when one of these names is not registered. Merged over
|
|
160
|
+
* every plugin, each name once.
|
|
161
|
+
*/
|
|
162
|
+
requiredTools?: readonly string[];
|
|
163
|
+
/**
|
|
164
|
+
* The background targets the plugin's claims answer, one per name across every plugin: a
|
|
165
|
+
* schedule or delegated task names one, and a turn for a target nobody contributes is skipped.
|
|
166
|
+
*/
|
|
167
|
+
backgroundTargets?: readonly BackgroundTarget[];
|
|
110
168
|
/** Lines the agent server's dashboard shows under its title, such as links, in contribution order. */
|
|
111
169
|
dashboard?: readonly string[];
|
|
112
170
|
/** Tools the plugin adds, each with the lowest tier that may use it; built with `defineTool`. */
|
|
113
171
|
tools?: readonly ToolContribution[];
|
|
172
|
+
/**
|
|
173
|
+
* The lowest tier that may use each of the plugin's raw session tools, by tool name: the tools
|
|
174
|
+
* its `sessionTools` extensions register. An operator's `toolTiers` still wins; a tool nobody
|
|
175
|
+
* names needs the owner. Two plugins naming one tool is a PluginError; use `tools` instead
|
|
176
|
+
* when `defineTool` builds the tool.
|
|
177
|
+
*/
|
|
178
|
+
toolTiers?: Readonly<Record<string, Tier>>;
|
|
114
179
|
/** Agents created on the first start; one already stored is never overwritten. */
|
|
115
180
|
seeds?: readonly AgentSeed[];
|
|
116
181
|
/** Sections added to every agent turn's system prompt, in contribution order. */
|
|
@@ -126,17 +191,21 @@ export interface Contribution {
|
|
|
126
191
|
export const CONTRIBUTION_KEYS = [
|
|
127
192
|
"services",
|
|
128
193
|
"events",
|
|
129
|
-
"interactions",
|
|
130
194
|
"http",
|
|
131
195
|
"holdRules",
|
|
132
196
|
"piPackages",
|
|
133
197
|
"sessionTools",
|
|
134
198
|
"channels",
|
|
199
|
+
"surfaces",
|
|
200
|
+
"personas",
|
|
201
|
+
"backgroundTargets",
|
|
135
202
|
"dashboard",
|
|
136
203
|
"tools",
|
|
204
|
+
"toolTiers",
|
|
137
205
|
"seeds",
|
|
138
206
|
"prompt",
|
|
139
207
|
"agentSelection",
|
|
208
|
+
"requiredTools",
|
|
140
209
|
] as const satisfies readonly (keyof Contribution)[];
|
|
141
210
|
|
|
142
211
|
/** The session parts the host links from every plugin's contributions once all are set up. */
|
|
@@ -150,15 +219,30 @@ export interface LinkedSessions {
|
|
|
150
219
|
seeds: readonly AgentSeed[];
|
|
151
220
|
/** Every plugin's prompt sections, in contribution order. */
|
|
152
221
|
prompt: readonly PromptSection[];
|
|
222
|
+
/** The prompt of a conversation kind, from the plugin that contributes its persona; undefined when none does. */
|
|
223
|
+
persona(kind: string): string | undefined;
|
|
224
|
+
/** Every tool name plugins require at startup, each once. */
|
|
225
|
+
requiredTools: readonly string[];
|
|
153
226
|
/** The tools plugins defined for agents, by name. */
|
|
154
227
|
agentTools: readonly string[];
|
|
155
228
|
/** Every plugin's agent selection merged, read before each agent turn. */
|
|
156
229
|
agentSelection(): ToolSelection;
|
|
157
230
|
}
|
|
158
231
|
|
|
232
|
+
/** The host's own locale and time zone, as its plugins read them. */
|
|
233
|
+
export interface HostEnv {
|
|
234
|
+
readonly locale: Locale;
|
|
235
|
+
/** The IANA zone the host was configured with. */
|
|
236
|
+
readonly timeZone: string;
|
|
237
|
+
/** The current instant. */
|
|
238
|
+
now(): Date;
|
|
239
|
+
}
|
|
240
|
+
|
|
159
241
|
/** What the host gives every plugin. */
|
|
160
242
|
export interface PluginContext {
|
|
161
243
|
logger: Logger;
|
|
244
|
+
/** The host's locale and time zone, fixed for the run. */
|
|
245
|
+
env: HostEnv;
|
|
162
246
|
/** The linked session parts; throws NotLinkedError when called during setup. */
|
|
163
247
|
sessions(): LinkedSessions;
|
|
164
248
|
/** The one channel queue every conversation and channel operation shares. */
|
|
@@ -169,12 +253,19 @@ export interface PluginContext {
|
|
|
169
253
|
events: EventSink;
|
|
170
254
|
/** The claimed channels' conversations; calls during setup throw NotLinkedError. */
|
|
171
255
|
conversations: ConversationPort;
|
|
256
|
+
/** Every contributed chat surface, chosen by a channel's prefix; calls during setup throw NotLinkedError. */
|
|
257
|
+
surfaces: SurfacePort;
|
|
258
|
+
/** Runs conversation turns of any kind over the runtime and the surfaces; calls during setup throw NotLinkedError. */
|
|
259
|
+
turns: ConversationTurns;
|
|
172
260
|
/** The host's one connection pool, migrated before any setup; throws PluginError without a database. */
|
|
173
261
|
database(): SQL;
|
|
174
|
-
/**
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
262
|
+
/**
|
|
263
|
+
* The services plugins provide to each other, read by key: `services.get(SCHEDULES)`. Reading one
|
|
264
|
+
* before its plugin has set up throws a PluginError naming the plugin to register first.
|
|
265
|
+
*/
|
|
266
|
+
services: Services;
|
|
267
|
+
/** Each provider slot, from the plugin that fills it or the core's default; `filled` names the slots a plugin fills. */
|
|
268
|
+
providers: ResolvedProviders;
|
|
178
269
|
/** Every plugin's dashboard lines, in contribution order; throws NotLinkedError during setup. */
|
|
179
270
|
dashboard(): readonly string[];
|
|
180
271
|
}
|
|
@@ -185,16 +276,129 @@ export interface RoundtablePlugin {
|
|
|
185
276
|
migrations?: readonly Migration[];
|
|
186
277
|
/** The provider slots the plugin fills, resolved before any setup; two plugins cannot fill one slot. */
|
|
187
278
|
providers?: Partial<Providers>;
|
|
279
|
+
/**
|
|
280
|
+
* The services this plugin's setup provides with `context.services.provide`; the host reads the
|
|
281
|
+
* list before any setup, and refuses the plugin when setup returns without providing one.
|
|
282
|
+
*/
|
|
283
|
+
provides?: readonly ServiceKey<unknown>[];
|
|
284
|
+
/**
|
|
285
|
+
* Services this plugin replaces. The host drops the plugin that provides them and sets this one
|
|
286
|
+
* up where it stood, so it may read what the plugins before that place provide and nothing
|
|
287
|
+
* after. It refuses a key no other plugin provides, a key two plugins replace, a service
|
|
288
|
+
* replaced but not listed in this plugin's `provides`, and a partial replacement, where the
|
|
289
|
+
* dropped plugin provides a service this one does not replace.
|
|
290
|
+
*/
|
|
291
|
+
replaces?: readonly ServiceKey<unknown>[];
|
|
188
292
|
setup(context: PluginContext): Promise<Contribution> | Contribution;
|
|
189
293
|
/**
|
|
190
|
-
* Runs once every plugin is set up and linked, before
|
|
191
|
-
*
|
|
294
|
+
* Runs once every plugin is set up and linked, before any service starts; a failure stops the
|
|
295
|
+
* boot, so a broken setup never reaches Discord. The Discord plugin composes the slash commands
|
|
296
|
+
* here, so a plugin adds its own from setup.
|
|
192
297
|
*/
|
|
193
298
|
preflight?(): Promise<void> | void;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* The plugin fields of 0.1.0 that are gone, each with what replaces it. The host refuses a
|
|
303
|
+
* plugin that still has one, so a plugin written for 0.1.0 fails at once instead of being ignored.
|
|
304
|
+
*/
|
|
305
|
+
const REMOVED_PLUGIN_FIELDS = {
|
|
306
|
+
useCommands:
|
|
307
|
+
"the composed slash commands go to the Discord plugin's surface, not to a plugin; add the commands from setup with context.services.get(DISCORD).commands.add(...), with DISCORD from pi-roundtable/discord",
|
|
308
|
+
agentServer:
|
|
309
|
+
"give the plugin a service with startInBackground, and hear how it ended in a serviceStarted event handler",
|
|
310
|
+
stopTurn:
|
|
311
|
+
"put stop(channel) on the channel claim that owns the channel; the router asks only the owning claim",
|
|
312
|
+
} as const;
|
|
313
|
+
|
|
314
|
+
/** The contribution parts of 0.1.0 that are gone, each with what replaces it. */
|
|
315
|
+
const REMOVED_PARTS = {
|
|
316
|
+
interactions:
|
|
317
|
+
"slash commands belong to the Discord plugin now; add them from setup with context.services.get(DISCORD).commands.add({ module, rootOptions }), with DISCORD from pi-roundtable/discord",
|
|
318
|
+
} as const;
|
|
319
|
+
|
|
320
|
+
/** The chat surface methods of 0.1.0 that are gone, each with what replaces it. */
|
|
321
|
+
const REMOVED_SURFACE_METHODS = {
|
|
322
|
+
useCommands:
|
|
323
|
+
"the host no longer composes slash commands or hands them to a surface; the Discord plugin composes them, and a plugin adds its own with context.services.get(DISCORD).commands.add(...) from pi-roundtable/discord",
|
|
324
|
+
} as const;
|
|
325
|
+
|
|
326
|
+
const REMOVED_EVENT = {
|
|
327
|
+
agentServer:
|
|
328
|
+
"hear serviceStarted instead, which names the plugin and service whose background start ended",
|
|
329
|
+
} as const;
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* The context one plugin's setup gets: the host's parts and that plugin's view of the services.
|
|
333
|
+
* `context.core` of 0.1.0 is gone; reading it throws a PluginError naming `context.services`, where
|
|
334
|
+
* a plugin written for 0.1.0 meets it on its first line, instead of getting `undefined`.
|
|
335
|
+
*/
|
|
336
|
+
export function pluginContext(
|
|
337
|
+
plugin: RoundtablePlugin,
|
|
338
|
+
base: Omit<PluginContext, "services">,
|
|
339
|
+
services: Services,
|
|
340
|
+
): PluginContext {
|
|
341
|
+
// Every line a plugin logs carries its name.
|
|
342
|
+
const context = {
|
|
343
|
+
...base,
|
|
344
|
+
logger: base.logger.child({ plugin: plugin.name }),
|
|
345
|
+
services,
|
|
346
|
+
};
|
|
347
|
+
Object.defineProperty(context, "core", {
|
|
348
|
+
enumerable: false,
|
|
349
|
+
get() {
|
|
350
|
+
throw new PluginError(
|
|
351
|
+
`plugin ${plugin.name}: context.core was removed in 0.2.0; read a service with context.services.get(KEY), for example services.get(SCHEDULES), and provide one with services.provide(KEY, value) after listing KEY in the plugin's provides.`,
|
|
352
|
+
);
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
return context;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Refuses a plugin that still has a field of 0.1.0 that is gone, naming what replaces it, so it
|
|
360
|
+
* fails where it is written or when the host links it instead of being ignored.
|
|
361
|
+
*/
|
|
362
|
+
export function refuseRemovedFields(plugin: RoundtablePlugin): void {
|
|
363
|
+
for (const [field, replacement] of Object.entries(REMOVED_PLUGIN_FIELDS))
|
|
364
|
+
if (field in plugin)
|
|
365
|
+
throw new PluginError(
|
|
366
|
+
`plugin ${plugin.name}: "${field}" was removed in 0.2.0; ${replacement}.`,
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Refuses a contribution part of 0.1.0 that is gone, naming what replaces it. */
|
|
371
|
+
export function refuseRemovedParts(
|
|
372
|
+
plugin: string,
|
|
373
|
+
contribution: Contribution,
|
|
374
|
+
): void {
|
|
375
|
+
for (const [part, replacement] of Object.entries(REMOVED_PARTS))
|
|
376
|
+
if (part in contribution)
|
|
377
|
+
throw new PluginError(
|
|
378
|
+
`plugin ${plugin}: the "${part}" part was removed in 0.2.0; ${replacement}.`,
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** Refuses a chat surface that still has a method of 0.1.0 that is gone, naming what replaces it. */
|
|
383
|
+
export function refuseRemovedSurfaceMethods(
|
|
384
|
+
plugin: string,
|
|
385
|
+
surface: ChatSurface,
|
|
386
|
+
): void {
|
|
387
|
+
for (const [method, replacement] of Object.entries(REMOVED_SURFACE_METHODS))
|
|
388
|
+
if (method in surface)
|
|
389
|
+
throw new PluginError(
|
|
390
|
+
`plugin ${plugin}: surface ${surface.surface} has ${method}, which was removed in 0.2.0; ${replacement}.`,
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** Refuses an event handler of 0.1.0 that is gone, naming what replaces it. */
|
|
395
|
+
export function refuseRemovedEvents(
|
|
396
|
+
plugin: string,
|
|
397
|
+
events: EventHandlers,
|
|
398
|
+
): void {
|
|
399
|
+
for (const [event, replacement] of Object.entries(REMOVED_EVENT))
|
|
400
|
+
if (event in events)
|
|
401
|
+
throw new PluginError(
|
|
402
|
+
`plugin ${plugin}: the "${event}" event was removed in 0.2.0; ${replacement}.`,
|
|
403
|
+
);
|
|
200
404
|
}
|