pi-roundtable 0.1.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.
- package/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/docs/plugins.md +924 -0
- package/examples/channels.test.ts +13 -0
- package/examples/channels.ts +27 -0
- package/examples/dashboard.test.ts +11 -0
- package/examples/dashboard.ts +9 -0
- package/examples/events.test.ts +26 -0
- package/examples/events.ts +25 -0
- package/examples/guide.test.ts +52 -0
- package/examples/holds.test.ts +16 -0
- package/examples/holds.ts +30 -0
- package/examples/http.test.ts +12 -0
- package/examples/http.ts +17 -0
- package/examples/interactions.test.ts +25 -0
- package/examples/interactions.ts +28 -0
- package/examples/migrations.test.ts +31 -0
- package/examples/migrations.ts +42 -0
- package/examples/packages.test.ts +9 -0
- package/examples/packages.ts +9 -0
- package/examples/preflight.test.ts +11 -0
- package/examples/preflight.ts +19 -0
- package/examples/prompt.test.ts +25 -0
- package/examples/prompt.ts +20 -0
- package/examples/providers.test.ts +10 -0
- package/examples/providers.ts +17 -0
- package/examples/seeds.test.ts +12 -0
- package/examples/seeds.ts +18 -0
- package/examples/selection.test.ts +13 -0
- package/examples/selection.ts +14 -0
- package/examples/services.test.ts +20 -0
- package/examples/services.ts +30 -0
- package/examples/session-tools.test.ts +24 -0
- package/examples/session-tools.ts +34 -0
- package/examples/tools.test.ts +18 -0
- package/examples/tools.ts +28 -0
- package/package.json +55 -0
- package/src/cli/add-plugin.test.ts +107 -0
- package/src/cli/add-plugin.ts +75 -0
- package/src/cli/checks/basic.test.ts +276 -0
- package/src/cli/checks/bun.ts +26 -0
- package/src/cli/checks/configuration.ts +28 -0
- package/src/cli/checks/database.test.ts +117 -0
- package/src/cli/checks/database.ts +100 -0
- package/src/cli/checks/discord.test.ts +200 -0
- package/src/cli/checks/discord.ts +218 -0
- package/src/cli/checks/environment.ts +27 -0
- package/src/cli/checks/model.ts +28 -0
- package/src/cli/checks/public-url.ts +40 -0
- package/src/cli/cli.test.ts +122 -0
- package/src/cli/cli.ts +166 -0
- package/src/cli/config-edit.test.ts +130 -0
- package/src/cli/config-edit.ts +199 -0
- package/src/cli/discord-api.ts +96 -0
- package/src/cli/doctor.test.ts +184 -0
- package/src/cli/doctor.ts +92 -0
- package/src/cli/http.ts +23 -0
- package/src/cli/init.test.ts +127 -0
- package/src/cli/init.ts +82 -0
- package/src/cli/main.ts +13 -0
- package/src/cli/project.ts +123 -0
- package/src/cli/report.ts +68 -0
- package/src/cli/roundtable.mjs +22 -0
- package/src/cli/runtime.ts +53 -0
- package/src/cli/size.test.ts +9 -0
- package/src/cli/start.ts +33 -0
- package/src/cli/templates.test.ts +129 -0
- package/src/cli/templates.ts +119 -0
- package/src/cli/testing/fixtures.ts +106 -0
- package/src/core/agents/agent-claim.test.ts +142 -0
- package/src/core/agents/agent-claim.ts +170 -0
- package/src/core/agents/agent-dashboard.test.ts +120 -0
- package/src/core/agents/agent-dashboard.ts +185 -0
- package/src/core/agents/agent-guild.test.ts +124 -0
- package/src/core/agents/agent-messages.ts +189 -0
- package/src/core/agents/agent-ports.ts +103 -0
- package/src/core/agents/agent-prompt.ts +163 -0
- package/src/core/agents/agent-rules.ts +106 -0
- package/src/core/agents/agent-schema.ts +115 -0
- package/src/core/agents/agent-settings.ts +49 -0
- package/src/core/agents/agent-store.test.ts +205 -0
- package/src/core/agents/agent-store.ts +384 -0
- package/src/core/agents/agent-team.ts +445 -0
- package/src/core/agents/agent-tools.ts +386 -0
- package/src/core/agents/avatar-studio.test.ts +88 -0
- package/src/core/agents/avatar-studio.ts +147 -0
- package/src/core/agents/group-messages.ts +99 -0
- package/src/core/agents/group-round.test.ts +143 -0
- package/src/core/agents/group-round.ts +117 -0
- package/src/core/agents/group-turns.ts +132 -0
- package/src/core/agents/owner-identity.test.ts +172 -0
- package/src/core/agents/team-editing.ts +205 -0
- package/src/core/agents/team-keys.ts +40 -0
- package/src/core/agents/team-layout.ts +135 -0
- package/src/core/agents/team-lifecycle.ts +188 -0
- package/src/core/agents/team-options.ts +52 -0
- package/src/core/agents/team-status.ts +80 -0
- package/src/core/agents/team-text.ts +60 -0
- package/src/core/agents/team-turn-types.ts +107 -0
- package/src/core/agents/team-turns.test.ts +278 -0
- package/src/core/agents/team-turns.ts +323 -0
- package/src/core/assets/neutral.png +0 -0
- package/src/core/assets/prompts/shared-guest.md +11 -0
- package/src/core/assets/prompts/shared.md +11 -0
- package/src/core/assets/skills/writing-skills/SKILL.md +21 -0
- package/src/core/attachments/attachment-dir.ts +15 -0
- package/src/core/attachments/attachment-fetcher.ts +83 -0
- package/src/core/attachments/attachments.test.ts +85 -0
- package/src/core/attachments/image-prep.ts +50 -0
- package/src/core/attachments/prompt-block.ts +37 -0
- package/src/core/attachments/turn-attachments.ts +79 -0
- package/src/core/boundary.test.ts +45 -0
- package/src/core/builtin/agent-server.ts +275 -0
- package/src/core/builtin/discord.ts +95 -0
- package/src/core/builtin/modules.test.ts +127 -0
- package/src/core/builtin/modules.ts +176 -0
- package/src/core/builtin/seeds.ts +10 -0
- package/src/core/builtin/stores.ts +42 -0
- package/src/core/config/config.test.ts +135 -0
- package/src/core/config/config.ts +285 -0
- package/src/core/config/schema.ts +181 -0
- package/src/core/contract/channels.ts +152 -0
- package/src/core/contract/discord.ts +33 -0
- package/src/core/contract/providers.ts +67 -0
- package/src/core/db/guild-scope.ts +53 -0
- package/src/core/db/migrations.test.ts +237 -0
- package/src/core/db/migrations.ts +37 -0
- package/src/core/define-roundtable.test.ts +134 -0
- package/src/core/define-roundtable.ts +195 -0
- package/src/core/define.test.ts +144 -0
- package/src/core/define.ts +154 -0
- package/src/core/discord/agent-commands.test.ts +58 -0
- package/src/core/discord/agent-commands.ts +385 -0
- package/src/core/discord/agent-discord.test.ts +70 -0
- package/src/core/discord/agent-discord.ts +367 -0
- package/src/core/discord/channel-executor.ts +404 -0
- package/src/core/discord/channel-operations.ts +329 -0
- package/src/core/discord/discord-surface.ts +431 -0
- package/src/core/discord/dispatch-thread-host.test.ts +114 -0
- package/src/core/discord/dispatch-thread-host.ts +72 -0
- package/src/core/discord/dispatch-threads.test.ts +94 -0
- package/src/core/discord/dispatch-threads.ts +180 -0
- package/src/core/discord/interaction-module.ts +1 -0
- package/src/core/discord/owner-cards.test.ts +435 -0
- package/src/core/discord/owner-cards.ts +463 -0
- package/src/core/discord/owner-command.ts +126 -0
- package/src/core/discord/owner-discord-access.ts +183 -0
- package/src/core/discord/owner-discord-threads.ts +160 -0
- package/src/core/discord/owner-discord.test.ts +325 -0
- package/src/core/discord/owner-discord.ts +282 -0
- package/src/core/discord/owner-panel.ts +103 -0
- package/src/core/discord/schedule-commands.ts +149 -0
- package/src/core/discord/stop-button.ts +20 -0
- package/src/core/domain/attachment.ts +39 -0
- package/src/core/domain/conversation.ts +42 -0
- package/src/core/domain/errors.ts +31 -0
- package/src/core/domain/expression.ts +21 -0
- package/src/core/domain/owner-prompts.ts +45 -0
- package/src/core/domain/ports.ts +91 -0
- package/src/core/domain/profile.ts +32 -0
- package/src/core/drain.test.ts +46 -0
- package/src/core/drain.ts +33 -0
- package/src/core/errors.ts +29 -0
- package/src/core/events.test.ts +81 -0
- package/src/core/events.ts +55 -0
- package/src/core/holds.test.ts +54 -0
- package/src/core/holds.ts +46 -0
- package/src/core/host.test.ts +536 -0
- package/src/core/host.ts +297 -0
- package/src/core/http/listeners.test.ts +164 -0
- package/src/core/http/listeners.ts +151 -0
- package/src/core/i18n/agent-panel.ts +96 -0
- package/src/core/i18n/cards.ts +64 -0
- package/src/core/i18n/channels.ts +28 -0
- package/src/core/i18n/conversation.ts +49 -0
- package/src/core/i18n/dashboard.ts +72 -0
- package/src/core/i18n/discord.ts +23 -0
- package/src/core/i18n/en.ts +27 -0
- package/src/core/i18n/i18n.test.ts +139 -0
- package/src/core/i18n/index.ts +58 -0
- package/src/core/i18n/owner.ts +35 -0
- package/src/core/i18n/schedules.ts +92 -0
- package/src/core/i18n/time-zones.ts +27 -0
- package/src/core/i18n/types.ts +7 -0
- package/src/core/i18n/zh-tw.ts +26 -0
- package/src/core/identity.test.ts +18 -0
- package/src/core/identity.ts +31 -0
- package/src/core/judging/confirmation-judge.ts +68 -0
- package/src/core/judging/effort-judge.test.ts +112 -0
- package/src/core/judging/effort-judge.ts +158 -0
- package/src/core/judging/model-judge.test.ts +126 -0
- package/src/core/judging/model-judge.ts +193 -0
- package/src/core/log.ts +45 -0
- package/src/core/models.ts +52 -0
- package/src/core/modules/background/background-turns.ts +78 -0
- package/src/core/modules/delegation/delegate.ts +54 -0
- package/src/core/modules/delegation/delegator.test.ts +170 -0
- package/src/core/modules/delegation/delegator.ts +191 -0
- package/src/core/modules/delegation/sol-worker.ts +78 -0
- package/src/core/modules/discord-admin/discord-admin.ts +288 -0
- package/src/core/modules/host-shell/shell-policy.ts +386 -0
- package/src/core/modules/memory/owner-memory-store.test.ts +244 -0
- package/src/core/modules/memory/owner-memory-store.ts +228 -0
- package/src/core/modules/memory/owner-memory.ts +153 -0
- package/src/core/modules/notify/notify.ts +26 -0
- package/src/core/modules/schedules/recurrence.ts +206 -0
- package/src/core/modules/schedules/schedule-store.ts +213 -0
- package/src/core/modules/schedules/schedule-tools.ts +196 -0
- package/src/core/modules/schedules/schedule.test.ts +358 -0
- package/src/core/modules/schedules/scheduler.ts +121 -0
- package/src/core/modules/schedules/schedules.ts +87 -0
- package/src/core/modules/skills/repo-name.ts +11 -0
- package/src/core/modules/skills/skill-kind.test.ts +55 -0
- package/src/core/modules/skills/skill-link.ts +69 -0
- package/src/core/modules/skills/skill-listing.ts +128 -0
- package/src/core/modules/skills/skill-registry.test.ts +376 -0
- package/src/core/modules/skills/skill-registry.ts +323 -0
- package/src/core/modules/skills/skill-rules.ts +120 -0
- package/src/core/modules/skills/skill-store.ts +285 -0
- package/src/core/modules/skills/skill-tools.ts +207 -0
- package/src/core/ops/error-reporter.test.ts +283 -0
- package/src/core/ops/error-reporter.ts +271 -0
- package/src/core/plugin.ts +200 -0
- package/src/core/presentation/card-cadence.ts +41 -0
- package/src/core/presentation/headline.ts +34 -0
- package/src/core/presentation/presentation.test.ts +166 -0
- package/src/core/presentation/quiet-links.ts +36 -0
- package/src/core/presentation/reply-splitter.ts +110 -0
- package/src/core/presentation/thinking-line.ts +24 -0
- package/src/core/public-entry.test.ts +59 -0
- package/src/core/registry/contributions.test.ts +215 -0
- package/src/core/registry/contributions.ts +249 -0
- package/src/core/registry/interactions.test.ts +87 -0
- package/src/core/registry/interactions.ts +55 -0
- package/src/core/registry/providers.test.ts +103 -0
- package/src/core/registry/providers.ts +55 -0
- package/src/core/routing/channel-queue.test.ts +31 -0
- package/src/core/routing/channel-queue.ts +44 -0
- package/src/core/routing/channel-router.test.ts +326 -0
- package/src/core/routing/channel-router.ts +157 -0
- package/src/core/routing/conversation-kind.ts +14 -0
- package/src/core/routing/forward-join.ts +65 -0
- package/src/core/routing/message-text.ts +16 -0
- package/src/core/routing/settle-turn.test.ts +21 -0
- package/src/core/routing/settle-turn.ts +26 -0
- package/src/core/runtime/compaction-tiers.test.ts +227 -0
- package/src/core/runtime/compaction-tiers.ts +203 -0
- package/src/core/runtime/conversation-sessions.ts +162 -0
- package/src/core/runtime/extensions/agent-prompt.ts +16 -0
- package/src/core/runtime/extensions/ask-user.test.ts +114 -0
- package/src/core/runtime/extensions/ask-user.ts +98 -0
- package/src/core/runtime/extensions/confirmation-gate.ts +247 -0
- package/src/core/runtime/extensions/self-compact-guard.test.ts +50 -0
- package/src/core/runtime/extensions/self-compact-guard.ts +23 -0
- package/src/core/runtime/mcp.ts +23 -0
- package/src/core/runtime/pending-confirmation-store.test.ts +52 -0
- package/src/core/runtime/pending-confirmation-store.ts +75 -0
- package/src/core/runtime/pi-agent-runtime.ts +477 -0
- package/src/core/runtime/prompt-slot.ts +81 -0
- package/src/core/runtime/runtime-types.ts +150 -0
- package/src/core/runtime/session-archive.test.ts +20 -0
- package/src/core/runtime/session-archive.ts +17 -0
- package/src/core/runtime/session-factory.ts +291 -0
- package/src/core/runtime/steerable-run.test.ts +264 -0
- package/src/core/runtime/steerable-run.ts +109 -0
- package/src/core/runtime/text-tools.test.ts +110 -0
- package/src/core/runtime/text-tools.ts +66 -0
- package/src/core/runtime/turn-answer.test.ts +72 -0
- package/src/core/runtime/turn-answer.ts +79 -0
- package/src/core/runtime/worker-task.test.ts +82 -0
- package/src/core/runtime/worker-task.ts +65 -0
- package/src/core/services.test.ts +28 -0
- package/src/core/services.ts +107 -0
- package/src/core/sessions.test.ts +85 -0
- package/src/core/sessions.ts +149 -0
- package/src/core/shared/attachment-reader.ts +91 -0
- package/src/core/shared/delegate-tool.ts +15 -0
- package/src/core/shared/mcp-adapter.ts +58 -0
- package/src/core/shared/package-dir.ts +9 -0
- package/src/core/shared/profile-tools.ts +16 -0
- package/src/core/shared/read-attachment-tool.ts +43 -0
- package/src/core/shared/schedule-tools.ts +118 -0
- package/src/core/shared/session-messages.ts +50 -0
- package/src/core/shared/tool-result.ts +9 -0
- package/src/core/shared/unix-server.ts +18 -0
- package/src/core/size.test.ts +9 -0
- package/src/core/speakers.test.ts +78 -0
- package/src/core/speakers.ts +143 -0
- package/src/core/testing/database.ts +52 -0
- package/src/core/testing/file-size.ts +34 -0
- package/src/core/testing/locale.ts +8 -0
- package/src/core/testing/modules.ts +97 -0
- package/src/core/testing/owner.ts +15 -0
- package/src/core/testing/thread-host.ts +60 -0
- package/src/core/time.test.ts +166 -0
- package/src/core/time.ts +67 -0
- package/src/core/tool-tiers.test.ts +117 -0
- package/src/core/tool-tiers.ts +127 -0
- package/src/entries.test.ts +112 -0
- package/src/index.ts +28 -0
- package/src/testing.test.ts +156 -0
- package/src/testing.ts +182 -0
- package/templates/.env.example +22 -0
- package/templates/README.md +11 -0
- package/templates/_gitignore +3 -0
- package/templates/agents.ts +12 -0
- package/templates/biome.json.tmpl +7 -0
- package/templates/docker-compose.yml +16 -0
- package/templates/package.json.tmpl +24 -0
- package/templates/persona/shared.md +2 -0
- package/templates/plugin/plugin.test.ts.tmpl +13 -0
- package/templates/plugin/plugin.ts +18 -0
- package/templates/roundtable.config.ts +24 -0
- package/templates/tsconfig.json.tmpl +16 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import type { ExtensionFactory } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { TurnAttachments } from "../domain/attachment.ts";
|
|
3
|
+
import type { ChannelKey, TurnResult } from "../domain/conversation.ts";
|
|
4
|
+
import { AgentError, ScheduleError } from "../domain/errors.ts";
|
|
5
|
+
import type { AgentTurnScope } from "../domain/ports.ts";
|
|
6
|
+
import type { ThinkingSetting } from "../models.ts";
|
|
7
|
+
import { SHELL_TOOLS } from "../modules/host-shell/shell-policy.ts";
|
|
8
|
+
import type { ResolvedSkill } from "../modules/skills/skill-registry.ts";
|
|
9
|
+
import {
|
|
10
|
+
SKILL_TOOLS,
|
|
11
|
+
skillToolsExtension,
|
|
12
|
+
} from "../modules/skills/skill-tools.ts";
|
|
13
|
+
import type { TurnSelection } from "../sessions.ts";
|
|
14
|
+
import { type Speaker, THE_SPEAKER } from "../speakers.ts";
|
|
15
|
+
import { agentSystemPrompt } from "./agent-prompt.ts";
|
|
16
|
+
import type { Agent } from "./agent-store.ts";
|
|
17
|
+
import {
|
|
18
|
+
AGENT_TOOLS,
|
|
19
|
+
type AgentOps,
|
|
20
|
+
type AvatarMode,
|
|
21
|
+
agentToolsExtension,
|
|
22
|
+
MESSAGE_AGENT_TOOL,
|
|
23
|
+
} from "./agent-tools.ts";
|
|
24
|
+
import { TeamEditing } from "./team-editing.ts";
|
|
25
|
+
import { channelKey, channelOwner } from "./team-keys.ts";
|
|
26
|
+
import {
|
|
27
|
+
layoutText,
|
|
28
|
+
planArrangement,
|
|
29
|
+
resolveArrangement,
|
|
30
|
+
} from "./team-layout.ts";
|
|
31
|
+
import { TeamLifecycle } from "./team-lifecycle.ts";
|
|
32
|
+
import type { AgentTeamOptions, TeamContext } from "./team-options.ts";
|
|
33
|
+
import { type TeamStatus, teamStatus } from "./team-status.ts";
|
|
34
|
+
import {
|
|
35
|
+
agentDetails,
|
|
36
|
+
channelIdFromRef,
|
|
37
|
+
messageLine,
|
|
38
|
+
teamListText,
|
|
39
|
+
} from "./team-text.ts";
|
|
40
|
+
import { TeamTurns } from "./team-turns.ts";
|
|
41
|
+
|
|
42
|
+
export type { AgentTeamOptions } from "./team-options.ts";
|
|
43
|
+
export type { AgentStatus, GroupStatus, TeamStatus } from "./team-status.ts";
|
|
44
|
+
|
|
45
|
+
const READ_LIMIT = 50;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The agent server: every agent is one channel and one conversation with every owner tool.
|
|
49
|
+
* This team creates, changes, arranges, and archives agents and groups; its TeamTurns runs
|
|
50
|
+
* their turns, group rounds, and messages between agents.
|
|
51
|
+
*/
|
|
52
|
+
export class AgentTeam implements AgentOps {
|
|
53
|
+
readonly #options: AgentTeamOptions;
|
|
54
|
+
readonly #turns: TeamTurns;
|
|
55
|
+
readonly #listeners: (() => void)[] = [];
|
|
56
|
+
readonly #context: TeamContext;
|
|
57
|
+
readonly #lifecycle: TeamLifecycle;
|
|
58
|
+
readonly #editing: TeamEditing;
|
|
59
|
+
|
|
60
|
+
constructor(options: AgentTeamOptions) {
|
|
61
|
+
this.#options = options;
|
|
62
|
+
this.#turns = new TeamTurns({
|
|
63
|
+
...options,
|
|
64
|
+
selection: (scope) => this.selection(scope),
|
|
65
|
+
changed: () => this.#changed(),
|
|
66
|
+
});
|
|
67
|
+
this.#context = {
|
|
68
|
+
options,
|
|
69
|
+
turns: this.#turns,
|
|
70
|
+
changed: () => {
|
|
71
|
+
this.#changed();
|
|
72
|
+
options.events?.changed();
|
|
73
|
+
},
|
|
74
|
+
modelOf: (name) => this.modelOf(name),
|
|
75
|
+
retitle: (group) => this.#lifecycle.retitle(group),
|
|
76
|
+
};
|
|
77
|
+
this.#lifecycle = new TeamLifecycle(this.#context);
|
|
78
|
+
this.#editing = new TeamEditing(this.#context);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get guildId(): string {
|
|
82
|
+
return this.#options.guildId;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Called when a turn starts or ends and when an agent or group changes. */
|
|
86
|
+
onChange(listener: () => void): void {
|
|
87
|
+
this.#listeners.push(listener);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#changed(): void {
|
|
91
|
+
for (const listener of this.#listeners) listener();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Every active agent and group, with what each is doing now. */
|
|
95
|
+
status(): Promise<TeamStatus> {
|
|
96
|
+
return teamStatus(this.#context);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The agent or group that owns a channel of the agent server. */
|
|
100
|
+
owns(channel: ChannelKey): "agent" | "group" | undefined {
|
|
101
|
+
return channelOwner(this.#options.store, channel);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** The tools every agent turn runs with: the plugins', plus the shell, agent, and skill tools. */
|
|
105
|
+
selection(scope?: AgentTurnScope): TurnSelection {
|
|
106
|
+
const plugged = this.#options.pluginSelection();
|
|
107
|
+
return {
|
|
108
|
+
id: "agent",
|
|
109
|
+
tools: [
|
|
110
|
+
...new Set([
|
|
111
|
+
...plugged.tools,
|
|
112
|
+
...SHELL_TOOLS,
|
|
113
|
+
// Group members hand off by mentioning each other, so a group seat has no message_agent.
|
|
114
|
+
...AGENT_TOOLS.filter(
|
|
115
|
+
(tool) => !(scope?.group && tool === MESSAGE_AGENT_TOOL),
|
|
116
|
+
),
|
|
117
|
+
...SKILL_TOOLS,
|
|
118
|
+
...(this.#options.pluginTools?.() ?? []),
|
|
119
|
+
]),
|
|
120
|
+
],
|
|
121
|
+
groups: plugged.groups,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** The system prompt addition of an agent session, read before each of its runs. */
|
|
126
|
+
systemPrompt(scope: AgentTurnScope): string {
|
|
127
|
+
const {
|
|
128
|
+
store,
|
|
129
|
+
workDir,
|
|
130
|
+
sharedPrompt,
|
|
131
|
+
guestPrompt,
|
|
132
|
+
entryChannelId,
|
|
133
|
+
owner,
|
|
134
|
+
shellUser,
|
|
135
|
+
} = this.#options;
|
|
136
|
+
const agent = store.agent(scope.name);
|
|
137
|
+
if (!agent) throw new AgentError(`no agent ${scope.name}`);
|
|
138
|
+
const group = scope.group ? store.group(scope.group) : undefined;
|
|
139
|
+
const coordinator = store.agentByChannel(entryChannelId);
|
|
140
|
+
const speaker = this.#turns.speakerOf(scope);
|
|
141
|
+
const base = agentSystemPrompt({
|
|
142
|
+
agent,
|
|
143
|
+
...(speaker ? { speaker } : {}),
|
|
144
|
+
...(coordinator ? { coordinator } : {}),
|
|
145
|
+
shared: sharedPrompt,
|
|
146
|
+
...(guestPrompt ? { guestShared: guestPrompt } : {}),
|
|
147
|
+
workDir,
|
|
148
|
+
owner,
|
|
149
|
+
shellUser,
|
|
150
|
+
...(group
|
|
151
|
+
? {
|
|
152
|
+
group: {
|
|
153
|
+
group,
|
|
154
|
+
members: group.members
|
|
155
|
+
.map((m) => store.agent(m))
|
|
156
|
+
.filter((m): m is Agent => m !== undefined),
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
: {}),
|
|
160
|
+
});
|
|
161
|
+
const added = (this.#options.promptSections?.() ?? []).flatMap(
|
|
162
|
+
(section) =>
|
|
163
|
+
section.build({
|
|
164
|
+
agent: { name: agent.name, displayName: agent.displayName },
|
|
165
|
+
speaker,
|
|
166
|
+
scope,
|
|
167
|
+
}) ?? [],
|
|
168
|
+
);
|
|
169
|
+
return [base, ...added.filter((text) => text.trim() !== "")].join("\n\n");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** The model and thinking setting of an agent's next run: its own, or the assistant's. */
|
|
173
|
+
modelOf(name: string): { model: string; thinking: ThinkingSetting } {
|
|
174
|
+
const { store, models } = this.#options;
|
|
175
|
+
const agent = store.agent(name);
|
|
176
|
+
return {
|
|
177
|
+
model: agent?.model ?? models.defaults.model,
|
|
178
|
+
thinking: agent?.thinking ?? models.defaults.thinking,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** The assistant's model and thinking setting, which agents without their own follow. */
|
|
183
|
+
defaultModel(): { model: string; thinking: ThinkingSetting } {
|
|
184
|
+
return this.#options.models.defaults;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Models an agent can be set to: every one the host runs, `current` first when given. */
|
|
188
|
+
async usableModels(current?: string): Promise<string[]> {
|
|
189
|
+
const usable = await this.#options.models.usable();
|
|
190
|
+
return current ? [current, ...usable.filter((m) => m !== current)] : usable;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** The agent and skill tools of one agent session. */
|
|
194
|
+
extension(scope: AgentTurnScope): ExtensionFactory {
|
|
195
|
+
const { skills, store } = this.#options;
|
|
196
|
+
const agentTools = agentToolsExtension(this, scope, THE_SPEAKER);
|
|
197
|
+
const skillTools = skillToolsExtension(skills, (name) => {
|
|
198
|
+
store.activeAgent(name);
|
|
199
|
+
});
|
|
200
|
+
return async (pi) => {
|
|
201
|
+
await agentTools(pi);
|
|
202
|
+
await skillTools(pi);
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** The skill files an agent's sessions load, built-in ones included. */
|
|
207
|
+
skillsOf(name: string): ResolvedSkill[] {
|
|
208
|
+
return this.#options.skills.carried(name).skills;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Another active agent's channel, for schedule_list. */
|
|
212
|
+
channelOf(name: string): ChannelKey {
|
|
213
|
+
try {
|
|
214
|
+
const agent = this.#options.store.activeAgent(name);
|
|
215
|
+
if (!agent.channelId) throw new AgentError(`${name} has no channel yet`);
|
|
216
|
+
return channelKey(agent.channelId);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
throw new ScheduleError(
|
|
219
|
+
error instanceof Error ? error.message : String(error),
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ── Startup and archive, run by TeamLifecycle ──────────────────────────
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Inserts the seed agents, gives every active agent a channel, archives agents and groups
|
|
228
|
+
* whose channels were deleted while the assistant was down, and draws missing avatars in the
|
|
229
|
+
* background.
|
|
230
|
+
*/
|
|
231
|
+
start(): Promise<void> {
|
|
232
|
+
return this.#lifecycle.start();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Starts an agent's or every group member's conversation over; call inside the channel's queue. */
|
|
236
|
+
startFresh(channel: ChannelKey): Promise<void> {
|
|
237
|
+
return this.#lifecycle.startFresh(channel);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** A deleted channel archives the agent or group that owned it. */
|
|
241
|
+
channelDeleted(channelId: string): Promise<void> {
|
|
242
|
+
return this.#lifecycle.channelDeleted(channelId);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Archives an agent or group like a deleted channel, then keeps its channel under Archive,
|
|
247
|
+
* where no one owns it and so nothing answers.
|
|
248
|
+
*/
|
|
249
|
+
archive(caller: AgentTurnScope, name: string): Promise<string> {
|
|
250
|
+
return this.#lifecycle.archive(caller, name);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ── Turns, run by TeamTurns ────────────────────────────────────────────
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The owner's message in an agent's channel; call inside the channel's queue. `text`
|
|
257
|
+
* carries the reference, `replyText` is what he typed.
|
|
258
|
+
*/
|
|
259
|
+
answerOwner(
|
|
260
|
+
channel: ChannelKey,
|
|
261
|
+
speaker: Speaker,
|
|
262
|
+
text: string,
|
|
263
|
+
replyText: string,
|
|
264
|
+
attachments: TurnAttachments,
|
|
265
|
+
): Promise<TurnResult> {
|
|
266
|
+
return this.#turns.answerOwner(
|
|
267
|
+
channel,
|
|
268
|
+
speaker,
|
|
269
|
+
text,
|
|
270
|
+
replyText,
|
|
271
|
+
attachments,
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* A schedule's or a report's turn in an agent's channel; call inside its queue. A report's
|
|
277
|
+
* turn is interactive: it may ask the owner on cards.
|
|
278
|
+
*/
|
|
279
|
+
answerBackground(
|
|
280
|
+
channel: ChannelKey,
|
|
281
|
+
speaker: Speaker,
|
|
282
|
+
text: string,
|
|
283
|
+
interactive = false,
|
|
284
|
+
): Promise<TurnResult> {
|
|
285
|
+
return this.#turns.answerBackground(channel, speaker, text, interactive);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** One owner message in a group channel, answered by a round of members; call inside the queue. */
|
|
289
|
+
answerGroup(
|
|
290
|
+
channel: ChannelKey,
|
|
291
|
+
speaker: Speaker,
|
|
292
|
+
text: string,
|
|
293
|
+
replyText: string,
|
|
294
|
+
attachments: TurnAttachments,
|
|
295
|
+
repliedToName: string | undefined,
|
|
296
|
+
): Promise<void> {
|
|
297
|
+
return this.#turns.answerGroup(
|
|
298
|
+
channel,
|
|
299
|
+
speaker,
|
|
300
|
+
text,
|
|
301
|
+
replyText,
|
|
302
|
+
attachments,
|
|
303
|
+
repliedToName,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/** Posts text under the caller's name in the channel of its turn. */
|
|
308
|
+
postAs(caller: AgentTurnScope, text: string): Promise<void> {
|
|
309
|
+
return this.#turns.postAs(caller, text);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** The channel the scope's turns run in: the group's in a group round, otherwise its own. */
|
|
313
|
+
turnChannel(scope: AgentTurnScope): ChannelKey {
|
|
314
|
+
return this.#turns.turnChannel(scope);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/** The assistant's own notice, posted in the coordinator's channel under its name. */
|
|
318
|
+
announce(text: string): Promise<void> {
|
|
319
|
+
return this.#turns.announce(text);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
message(caller: AgentTurnScope, to: string, text: string): string {
|
|
323
|
+
return this.#turns.message(caller, to, text);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async read(
|
|
327
|
+
channel: string,
|
|
328
|
+
around: string | undefined,
|
|
329
|
+
limit: number | undefined,
|
|
330
|
+
): Promise<string> {
|
|
331
|
+
const id = channelIdFromRef(channel);
|
|
332
|
+
const messages = await this.#options.channels.read(id, {
|
|
333
|
+
limit: Math.min(Math.max(limit ?? 20, 1), READ_LIMIT),
|
|
334
|
+
...(around ? { around } : {}),
|
|
335
|
+
});
|
|
336
|
+
return messages.length > 0
|
|
337
|
+
? messages.map(messageLine).join("\n")
|
|
338
|
+
: `<#${id}> has no messages there.`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// ── AgentOps ───────────────────────────────────────────────────────────
|
|
342
|
+
|
|
343
|
+
async list(): Promise<string> {
|
|
344
|
+
return `${teamListText(this.#options.store)}\n\n${await this.#layoutText()}`;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
async #layoutText(): Promise<string> {
|
|
348
|
+
const { store, channels } = this.#options;
|
|
349
|
+
return layoutText(await channels.layout(), store);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Sorts agent and group channels into team categories and orders them (spec behavior 57):
|
|
354
|
+
* the listed categories and channels first, everything else after in its current order. A
|
|
355
|
+
* wrong entry refuses the whole call before anything moves.
|
|
356
|
+
*/
|
|
357
|
+
async arrange(
|
|
358
|
+
entries: { category: string; names: string[] }[],
|
|
359
|
+
): Promise<string> {
|
|
360
|
+
const { store, channels, logger } = this.#options;
|
|
361
|
+
const listed = resolveArrangement(entries, store);
|
|
362
|
+
const { layout, remove } = planArrangement(listed, await channels.layout());
|
|
363
|
+
await channels.arrange(layout, remove);
|
|
364
|
+
logger.info(
|
|
365
|
+
{ entries: listed.map((l) => l.category), removed: remove.length },
|
|
366
|
+
"agent channels arranged",
|
|
367
|
+
);
|
|
368
|
+
const removed =
|
|
369
|
+
remove.length > 0
|
|
370
|
+
? ` ${remove.length} empty team categories were deleted.`
|
|
371
|
+
: "";
|
|
372
|
+
return `Arranged the channels.${removed}\n\n${await this.#layoutText()}`;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
get(name: string): string {
|
|
376
|
+
const { store, models, skills } = this.#options;
|
|
377
|
+
const agent = store.agent(name);
|
|
378
|
+
if (!agent)
|
|
379
|
+
throw new AgentError(`There is no agent "${name}"; see agent_list.`);
|
|
380
|
+
return agentDetails(
|
|
381
|
+
agent,
|
|
382
|
+
models.defaults,
|
|
383
|
+
skills.describeCarried(agent.name),
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// ── Editing, run by TeamEditing ────────────────────────────────────────
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Changes an agent's display name, prompt, model, or thinking level; `default` returns the
|
|
391
|
+
* model or thinking level to the assistant's. A model must be one the host runs.
|
|
392
|
+
*/
|
|
393
|
+
update(
|
|
394
|
+
name: string,
|
|
395
|
+
change: {
|
|
396
|
+
displayName?: string;
|
|
397
|
+
prompt?: string;
|
|
398
|
+
model?: string;
|
|
399
|
+
thinking?: string;
|
|
400
|
+
},
|
|
401
|
+
): Promise<string> {
|
|
402
|
+
return this.#editing.update(name, change);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
create(
|
|
406
|
+
caller: AgentTurnScope,
|
|
407
|
+
input: {
|
|
408
|
+
name: string;
|
|
409
|
+
displayName: string;
|
|
410
|
+
prompt: string;
|
|
411
|
+
avatarPrompt: string;
|
|
412
|
+
task: string;
|
|
413
|
+
category?: string;
|
|
414
|
+
skills?: string[];
|
|
415
|
+
},
|
|
416
|
+
): Promise<string> {
|
|
417
|
+
return this.#editing.create(caller, input);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
avatar(name: string, mode: AvatarMode, text?: string): Promise<string> {
|
|
421
|
+
return this.#editing.avatar(name, mode, text);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** Draws and stores a new picture; the owner's panel and the agent tool both use it. */
|
|
425
|
+
redrawAvatar(name: string, mode: AvatarMode, text?: string): Promise<Agent> {
|
|
426
|
+
return this.#editing.redrawAvatar(name, mode, text);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
createGroup(input: {
|
|
430
|
+
name: string;
|
|
431
|
+
displayName: string;
|
|
432
|
+
members: string[];
|
|
433
|
+
host?: string;
|
|
434
|
+
category?: string;
|
|
435
|
+
}): Promise<string> {
|
|
436
|
+
return this.#editing.createGroup(input);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
updateGroup(
|
|
440
|
+
name: string,
|
|
441
|
+
change: { displayName?: string; members?: string[]; host?: string },
|
|
442
|
+
): Promise<string> {
|
|
443
|
+
return this.#editing.updateGroup(name, change);
|
|
444
|
+
}
|
|
445
|
+
}
|