pi-roundtable 0.25.0 → 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.
- package/CHANGELOG.md +27 -0
- package/docs/plugins.md +129 -6
- package/package.json +1 -1
- package/src/cli/checks/agent-tools.ts +23 -0
- package/src/cli/doctor.ts +6 -0
- package/src/cli/principal.ts +9 -2
- package/src/core/agents/agent-prompt.ts +6 -1
- package/src/core/agents/agent-team.ts +2 -0
- package/src/core/agents/team-editing.ts +4 -0
- package/src/core/agents/team-options.ts +3 -1
- package/src/core/agents/team-selection.ts +6 -2
- package/src/core/builtin/agent-server.ts +1 -0
- package/src/core/builtin/channel-context.ts +21 -0
- package/src/core/builtin/discord.ts +4 -1
- package/src/core/config/config-schema.ts +22 -6
- package/src/core/config/config.ts +30 -2
- package/src/core/config/conversations.ts +21 -0
- package/src/core/config/profiles.ts +53 -0
- package/src/core/contract/channel-context.ts +106 -0
- package/src/core/contract/surface.ts +16 -0
- package/src/core/conversations/conversation-registry.ts +6 -0
- package/src/core/conversations/conversation-retention.ts +107 -0
- package/src/core/conversations/conversation-store.ts +6 -0
- package/src/core/conversations/conversations-plugin.ts +19 -3
- package/src/core/define-roundtable.ts +9 -2
- package/src/core/discord/channel-context.ts +47 -78
- package/src/core/discord/discord-surface.ts +16 -0
- package/src/core/events.ts +1 -0
- package/src/core/host-registration.ts +4 -0
- package/src/core/host.ts +3 -1
- package/src/core/identity/actor-facts.ts +7 -0
- package/src/core/identity/identity-plugin.ts +27 -5
- package/src/core/identity/identity-port.ts +62 -0
- package/src/core/identity/identity-schema.ts +2 -0
- package/src/core/identity/identity-service.ts +45 -52
- package/src/core/identity/identity-view.ts +1 -0
- package/src/core/identity/person-profiles.ts +275 -0
- package/src/core/identity/principal-tables.ts +10 -0
- package/src/core/identity/profile-choices.ts +45 -0
- package/src/core/identity/profile-memory.ts +65 -0
- package/src/core/identity/profile-picture.ts +117 -0
- package/src/core/identity/profiles-view.ts +20 -0
- package/src/core/identity/profiles.ts +82 -0
- package/src/core/modules/host-shell/shell-policy.ts +18 -3
- package/src/core/plugin.ts +40 -0
- package/src/core/registry/contributions.ts +8 -1
- package/src/core/runtime/chat-only.ts +32 -0
- package/src/core/runtime/conversation-sessions.ts +2 -1
- package/src/core/runtime/runtime-plugin.ts +1 -0
- package/src/core/runtime/runtime-types.ts +3 -1
- package/src/core/runtime/session-factory.ts +19 -30
- package/src/core/runtime/session-helpers.ts +27 -0
- package/src/core/services.ts +9 -0
- package/src/index.ts +18 -0
- package/src/kit/index.ts +1 -0
- package/src/kit/oidc.ts +16 -0
- package/src/testing.ts +1 -0
package/src/core/plugin.ts
CHANGED
|
@@ -107,10 +107,30 @@ export interface EventHandlers {
|
|
|
107
107
|
turnProgress?(event: TurnProgressEvent): Promise<void> | void;
|
|
108
108
|
/** The team changed: an agent or group was created, edited, arranged, archived, or started over. */
|
|
109
109
|
changed?(): Promise<void> | void;
|
|
110
|
+
/**
|
|
111
|
+
* Something a person did through a plugin's surface, reported by any plugin through
|
|
112
|
+
* `context.events.action`: for example a support inbox's "assign", "reply" or "close". It names
|
|
113
|
+
* the kind, who did it and whether it worked, never the content.
|
|
114
|
+
*/
|
|
115
|
+
action?(event: ActionEvent): Promise<void> | void;
|
|
110
116
|
/** The shutdown drain ended, before any service stops; `left` is the work it gave up on. */
|
|
111
117
|
shutdown?(left: readonly string[]): Promise<void> | void;
|
|
112
118
|
}
|
|
113
119
|
|
|
120
|
+
/** One thing a person did through a plugin's surface, as a handler hears of it. */
|
|
121
|
+
export interface ActionEvent {
|
|
122
|
+
/** What was done, in the reporting plugin's words, such as "assign" or "close". */
|
|
123
|
+
kind: string;
|
|
124
|
+
/** The `Speaker.id` of who did it. */
|
|
125
|
+
actor: string;
|
|
126
|
+
principalId: string;
|
|
127
|
+
/** The conversation or page it concerns, when there is one. */
|
|
128
|
+
channel?: ChannelKey | `page:${string}`;
|
|
129
|
+
/** Whether it worked. */
|
|
130
|
+
ok: boolean;
|
|
131
|
+
at: Date;
|
|
132
|
+
}
|
|
133
|
+
|
|
114
134
|
/** What the core reports to the plugins' handlers. */
|
|
115
135
|
export interface EventSink {
|
|
116
136
|
turnStarted(turn: TurnEvent): void;
|
|
@@ -118,6 +138,8 @@ export interface EventSink {
|
|
|
118
138
|
/** Optional, so a sink of your own written before it still fits. */
|
|
119
139
|
turnProgress?(event: TurnProgressEvent): void;
|
|
120
140
|
changed(): void;
|
|
141
|
+
/** Optional, as `turnProgress` is: a sink of your own written before it still fits. */
|
|
142
|
+
action?(event: ActionEvent): void;
|
|
121
143
|
}
|
|
122
144
|
|
|
123
145
|
/** What a prompt section is built for: one agent's turn. */
|
|
@@ -265,6 +287,12 @@ export interface LinkedSessions {
|
|
|
265
287
|
agentSelection(): ToolSelection;
|
|
266
288
|
}
|
|
267
289
|
|
|
290
|
+
/**
|
|
291
|
+
* What the agents' turns may use of the machine: "full" gives them the shell and file tools, and
|
|
292
|
+
* "chat-only" none of them, as `agentServer: { tools: "chat-only" }` configures.
|
|
293
|
+
*/
|
|
294
|
+
export type AgentTools = "full" | "chat-only";
|
|
295
|
+
|
|
268
296
|
/** The host's own locale and time zone, as its plugins read them. */
|
|
269
297
|
export interface HostEnv {
|
|
270
298
|
readonly locale: Locale;
|
|
@@ -284,6 +312,12 @@ export interface HostEnv {
|
|
|
284
312
|
* agent wears the same ones.
|
|
285
313
|
*/
|
|
286
314
|
readonly characterSkins: readonly Hex[];
|
|
315
|
+
/**
|
|
316
|
+
* Whether the agents' turns carry the shell and file tools. A plugin whose tools reach the host
|
|
317
|
+
* checks it before it offers them to agents; under "chat-only" the host refuses to start with a
|
|
318
|
+
* plugin that declares `hostAccess`.
|
|
319
|
+
*/
|
|
320
|
+
readonly agentTools: AgentTools;
|
|
287
321
|
}
|
|
288
322
|
|
|
289
323
|
/** What the host gives every plugin. */
|
|
@@ -391,6 +425,12 @@ export interface RoundtablePlugin {
|
|
|
391
425
|
* dropped plugin provides a service this one does not replace.
|
|
392
426
|
*/
|
|
393
427
|
replaces?: readonly ServiceKey<unknown>[];
|
|
428
|
+
/**
|
|
429
|
+
* Marks a plugin whose tools reach the host's machine, such as one that runs shells or edits
|
|
430
|
+
* its files for the agents. A host that configures `agentServer: { tools: "chat-only" }`
|
|
431
|
+
* refuses to start with one registered, with a ConfigError that names the plugin.
|
|
432
|
+
*/
|
|
433
|
+
hostAccess?: true;
|
|
394
434
|
setup(context: PluginContext): Promise<Contribution> | Contribution;
|
|
395
435
|
/**
|
|
396
436
|
* Runs once every plugin is set up and linked, before any service starts; a failure stops the
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type DirectChannelProvider,
|
|
26
26
|
directChannelsPort,
|
|
27
27
|
} from "../presence/direct-channels.ts";
|
|
28
|
+
import { refuseShellTools } from "../runtime/chat-only.ts";
|
|
28
29
|
import {
|
|
29
30
|
compileSessionPlan,
|
|
30
31
|
type SessionTool,
|
|
@@ -451,8 +452,14 @@ export async function collectContributions(
|
|
|
451
452
|
registry.holdRules.push(tool.hold);
|
|
452
453
|
}
|
|
453
454
|
}
|
|
454
|
-
if (contribution.agentSelection)
|
|
455
|
+
if (contribution.agentSelection) {
|
|
456
|
+
if (context.env.agentTools === "chat-only")
|
|
457
|
+
refuseShellTools(
|
|
458
|
+
contribution.agentSelection().tools,
|
|
459
|
+
`plugin ${plugin.name}: agentSelection`,
|
|
460
|
+
);
|
|
455
461
|
registry.agentSelections.push(contribution.agentSelection);
|
|
462
|
+
}
|
|
456
463
|
if (events) registry.handlers.push({ plugin: plugin.name, events });
|
|
457
464
|
registry.routes.push(...http);
|
|
458
465
|
registry.holdRules.push(...holdRules);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ConfigError } from "../domain/errors.ts";
|
|
2
|
+
import { SHELL_TOOLS } from "../modules/host-shell/shell-policy.ts";
|
|
3
|
+
import type { RoundtablePlugin } from "../plugin.ts";
|
|
4
|
+
|
|
5
|
+
const CHAT_ONLY = 'agentServer: { tools: "chat-only" }';
|
|
6
|
+
|
|
7
|
+
/** The shell and file tools among these names. */
|
|
8
|
+
export function shellToolsIn(names: Iterable<string>): string[] {
|
|
9
|
+
const shell: readonly string[] = SHELL_TOOLS;
|
|
10
|
+
return [...new Set(names)].filter((name) => shell.includes(name));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Refuses names that carry the machine's shell and file tools: the one place a chat-only host
|
|
15
|
+
* checks, where a selection turns into active tools. `where` says whose selection it is.
|
|
16
|
+
*/
|
|
17
|
+
export function refuseShellTools(names: Iterable<string>, where: string): void {
|
|
18
|
+
const found = shellToolsIn(names);
|
|
19
|
+
if (found.length > 0)
|
|
20
|
+
throw new ConfigError(
|
|
21
|
+
`${where} names ${found.join(", ")}, which ${CHAT_ONLY} withholds from every turn. Take the tool out of the selection, or remove tools: "chat-only" from agentServer to give the agents the shell.`,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Refuses, at start, a plugin whose tools reach the host: an agent of a chat-only host must not. */
|
|
26
|
+
export function refuseHostAccess(plugins: readonly RoundtablePlugin[]): void {
|
|
27
|
+
const reaching = plugins.find((plugin) => plugin.hostAccess === true);
|
|
28
|
+
if (reaching)
|
|
29
|
+
throw new ConfigError(
|
|
30
|
+
`plugin ${reaching.name} declares hostAccess: its tools reach the host's machine, and the configuration says ${CHAT_ONLY}. Remove the plugin, or remove tools: "chat-only" from agentServer.`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -102,7 +102,8 @@ export class ConversationSessions {
|
|
|
102
102
|
this.#factory.link().holds,
|
|
103
103
|
this.#options.owner,
|
|
104
104
|
await this.#options.confirmations.load(key),
|
|
105
|
-
agents
|
|
105
|
+
// A chat-only host's agents have no shell, so their gate judges no workspace.
|
|
106
|
+
agents && this.#options.agentTools !== "chat-only"
|
|
106
107
|
? {
|
|
107
108
|
workspace: agents.workDir,
|
|
108
109
|
...(agents.scratchDir ? { scratchDir: agents.scratchDir } : {}),
|
|
@@ -16,7 +16,7 @@ import type { Logger } from "../log.ts";
|
|
|
16
16
|
import type { EffortPolicy, ThinkingLevel, ThinkingPicker } from "../models.ts";
|
|
17
17
|
import type { Autonomy } from "../modes/autonomy.ts";
|
|
18
18
|
import type { ConversationModes } from "../modes/conversation-modes.ts";
|
|
19
|
-
import type { LinkedSessions } from "../plugin.ts";
|
|
19
|
+
import type { AgentTools, LinkedSessions } from "../plugin.ts";
|
|
20
20
|
import {
|
|
21
21
|
planOrder,
|
|
22
22
|
type SessionContext,
|
|
@@ -75,6 +75,8 @@ export interface PiAgentRuntimeOptions {
|
|
|
75
75
|
sessions: () => LinkedSessions;
|
|
76
76
|
/** The agent server's sessions: their shared workspace, model, and skills. */
|
|
77
77
|
agents?: AgentSessions;
|
|
78
|
+
/** "chat-only": no turn carries the shell and file tools, and agent sessions have no workspace; default "full". */
|
|
79
|
+
agentTools?: AgentTools;
|
|
78
80
|
/**
|
|
79
81
|
* The prompts of a channel for an interactive turn's scope, made from its speaker and its
|
|
80
82
|
* conversation's visibility; undefined for a channel that cannot show them. Without it every
|
|
@@ -3,14 +3,11 @@ import { join } from "node:path";
|
|
|
3
3
|
import {
|
|
4
4
|
type AgentSession,
|
|
5
5
|
createAgentSession,
|
|
6
|
-
createBashToolDefinition,
|
|
7
6
|
DefaultResourceLoader,
|
|
8
7
|
type ModelRuntime,
|
|
9
8
|
type SessionManager,
|
|
10
|
-
type ToolDefinition,
|
|
11
9
|
} from "@earendil-works/pi-coding-agent";
|
|
12
10
|
import { channelSegment } from "../attachments/attachment-dir.ts";
|
|
13
|
-
import type { ImageDrawer } from "../contract/providers.ts";
|
|
14
11
|
import type { ClientPort } from "../domain/client.ts";
|
|
15
12
|
import type { ChannelKey } from "../domain/conversation.ts";
|
|
16
13
|
import { ConfigError } from "../domain/errors.ts";
|
|
@@ -29,16 +26,13 @@ import {
|
|
|
29
26
|
ATTACH_FILE_TOOL,
|
|
30
27
|
attachFileExtension,
|
|
31
28
|
} from "../shared/attach-file-tool.ts";
|
|
32
|
-
import {
|
|
33
|
-
GENERATE_IMAGE_TOOL,
|
|
34
|
-
generateImageExtension,
|
|
35
|
-
} from "../shared/generate-image-tool.ts";
|
|
29
|
+
import { GENERATE_IMAGE_TOOL } from "../shared/generate-image-tool.ts";
|
|
36
30
|
import { packageDir } from "../shared/package-dir.ts";
|
|
37
31
|
import { readAttachmentExtension } from "../shared/read-attachment-tool.ts";
|
|
38
|
-
import type { WorkspaceRoots } from "../shared/workspace-files.ts";
|
|
39
32
|
import { type Speaker, THE_SPEAKER } from "../speakers.ts";
|
|
40
33
|
import { currentToolNames } from "../tool-tiers.ts";
|
|
41
34
|
import { toolTurn } from "../tool-turn.ts";
|
|
35
|
+
import { refuseShellTools } from "./chat-only.ts";
|
|
42
36
|
import {
|
|
43
37
|
CompactionTiers,
|
|
44
38
|
compactionEngine,
|
|
@@ -64,7 +58,6 @@ import type { PromptSlot } from "./prompt-slot.ts";
|
|
|
64
58
|
import type {
|
|
65
59
|
ChannelSession,
|
|
66
60
|
CompactionEnd,
|
|
67
|
-
CoreExtensions,
|
|
68
61
|
PiAgentRuntimeOptions,
|
|
69
62
|
} from "./runtime-types.ts";
|
|
70
63
|
import {
|
|
@@ -78,6 +71,9 @@ import {
|
|
|
78
71
|
sessionAddressee,
|
|
79
72
|
turnAddressee,
|
|
80
73
|
} from "./session-conversation.ts";
|
|
74
|
+
import { imageTools, scratchBash } from "./session-helpers.ts";
|
|
75
|
+
|
|
76
|
+
export { imageTools, scratchBash };
|
|
81
77
|
|
|
82
78
|
/** What a session factory asks of the runtime that owns the turns. */
|
|
83
79
|
export interface SessionFactoryDeps {
|
|
@@ -139,11 +135,22 @@ export class SessionFactory {
|
|
|
139
135
|
);
|
|
140
136
|
}
|
|
141
137
|
|
|
138
|
+
/** Whether the host's agents carry no shell or file tools. */
|
|
139
|
+
get chatOnly(): boolean {
|
|
140
|
+
return this.#options.agentTools === "chat-only";
|
|
141
|
+
}
|
|
142
|
+
|
|
142
143
|
get plan(): SessionPlan {
|
|
143
144
|
return this.link().plan;
|
|
144
145
|
}
|
|
145
146
|
|
|
147
|
+
/**
|
|
148
|
+
* The tools a selection turns into. A chat-only host refuses a selection that names a shell or
|
|
149
|
+
* file tool, whatever built it (the agent team, `context.turns`, a plugin), so the turn fails
|
|
150
|
+
* closed before any session runs it.
|
|
151
|
+
*/
|
|
146
152
|
toolsFor(selection: ToolSelection): string[] {
|
|
153
|
+
if (this.chatOnly) refuseShellTools(selection.tools, "a tool selection");
|
|
147
154
|
const groups = planOrder(this.plan).flatMap(
|
|
148
155
|
(tool) => tool.snapshot().groups ?? [],
|
|
149
156
|
);
|
|
@@ -360,7 +367,8 @@ export class SessionFactory {
|
|
|
360
367
|
},
|
|
361
368
|
conversation,
|
|
362
369
|
addressee,
|
|
363
|
-
|
|
370
|
+
// A chat-only host's agents work in no workspace.
|
|
371
|
+
...(agents && !this.chatOnly
|
|
364
372
|
? {
|
|
365
373
|
workspace: {
|
|
366
374
|
workspace: cwd,
|
|
@@ -450,7 +458,7 @@ export class SessionFactory {
|
|
|
450
458
|
cwd,
|
|
451
459
|
agentDir,
|
|
452
460
|
// Pi's bash under its own name, run with TMPDIR at the agents' scratch dir.
|
|
453
|
-
...(agents?.scratchDir
|
|
461
|
+
...(agents?.scratchDir && !this.chatOnly
|
|
454
462
|
? { customTools: [scratchBash(cwd, agents.scratchDir)] }
|
|
455
463
|
: {}),
|
|
456
464
|
thinkingLevel: thinking,
|
|
@@ -479,22 +487,3 @@ export class SessionFactory {
|
|
|
479
487
|
return Object.assign(state, { session });
|
|
480
488
|
}
|
|
481
489
|
}
|
|
482
|
-
|
|
483
|
-
/** `generate_image` for a session of a host with an image provider; nothing without one. */
|
|
484
|
-
export function imageTools(
|
|
485
|
-
images: ImageDrawer | undefined,
|
|
486
|
-
roots: WorkspaceRoots,
|
|
487
|
-
): Pick<CoreExtensions, "generateImage"> {
|
|
488
|
-
return images ? { generateImage: generateImageExtension(images, roots) } : {};
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
/** Pi's bash tool with TMPDIR set to `scratchDir`, so tools that read TMPDIR and GNU `mktemp` write there (BSD `mktemp` needs `-p "$TMPDIR"`). */
|
|
492
|
-
export function scratchBash(cwd: string, scratchDir: string): ToolDefinition {
|
|
493
|
-
// SAFETY: Pi's bash definition is a ToolDefinition typed by its own parameter schema, which the session takes as any custom tool.
|
|
494
|
-
return createBashToolDefinition(cwd, {
|
|
495
|
-
spawnHook: (context) => ({
|
|
496
|
-
...context,
|
|
497
|
-
env: { ...context.env, TMPDIR: scratchDir },
|
|
498
|
-
}),
|
|
499
|
-
}) as unknown as ToolDefinition;
|
|
500
|
-
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createBashToolDefinition,
|
|
3
|
+
type ToolDefinition,
|
|
4
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import type { ImageDrawer } from "../contract/providers.ts";
|
|
6
|
+
import { generateImageExtension } from "../shared/generate-image-tool.ts";
|
|
7
|
+
import type { WorkspaceRoots } from "../shared/workspace-files.ts";
|
|
8
|
+
import type { CoreExtensions } from "./runtime-types.ts";
|
|
9
|
+
|
|
10
|
+
/** `generate_image` for a session of a host with an image provider; nothing without one. */
|
|
11
|
+
export function imageTools(
|
|
12
|
+
images: ImageDrawer | undefined,
|
|
13
|
+
roots: WorkspaceRoots,
|
|
14
|
+
): Pick<CoreExtensions, "generateImage"> {
|
|
15
|
+
return images ? { generateImage: generateImageExtension(images, roots) } : {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Pi's bash tool with TMPDIR set to `scratchDir`, so tools that read TMPDIR and GNU `mktemp` write there (BSD `mktemp` needs `-p "$TMPDIR"`). */
|
|
19
|
+
export function scratchBash(cwd: string, scratchDir: string): ToolDefinition {
|
|
20
|
+
// SAFETY: Pi's bash definition is a ToolDefinition typed by its own parameter schema, which the session takes as any custom tool.
|
|
21
|
+
return createBashToolDefinition(cwd, {
|
|
22
|
+
spawnHook: (context) => ({
|
|
23
|
+
...context,
|
|
24
|
+
env: { ...context.env, TMPDIR: scratchDir },
|
|
25
|
+
}),
|
|
26
|
+
}) as unknown as ToolDefinition;
|
|
27
|
+
}
|
package/src/core/services.ts
CHANGED
|
@@ -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 {
|
|
@@ -53,6 +55,10 @@ import type { DispatchThreads } from "./threads/dispatch-threads.ts";
|
|
|
53
55
|
*/
|
|
54
56
|
export const IDENTITY: ServiceKey<IdentityService> =
|
|
55
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
|
+
);
|
|
56
62
|
/**
|
|
57
63
|
* Links a person's own account to their principal, which `IDENTITY` cannot. Provided by the
|
|
58
64
|
* `identity` plugin only when the configuration lists providers in `access.selfLink`; read it with
|
|
@@ -92,6 +98,9 @@ export const MODES: ServiceKey<ConversationModes> =
|
|
|
92
98
|
*/
|
|
93
99
|
export const THREADS: ServiceKey<DispatchThreads> =
|
|
94
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");
|
|
95
104
|
/** The agent server: its team, its directory, the runtime that runs every agent turn. Provided by the agent-server plugin. */
|
|
96
105
|
export const AGENTS: ServiceKey<AgentServer> = serviceKey<AgentServer>(
|
|
97
106
|
"roundtable.agents",
|
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,
|
|
@@ -306,6 +320,8 @@ export type {
|
|
|
306
320
|
} from "./core/modules/skills/skill-rules.ts";
|
|
307
321
|
export { SkillConflictError } from "./core/modules/skills/skill-rules.ts";
|
|
308
322
|
export type {
|
|
323
|
+
ActionEvent,
|
|
324
|
+
AgentTools,
|
|
309
325
|
Contribution,
|
|
310
326
|
EventHandlers,
|
|
311
327
|
EventSink,
|
|
@@ -360,6 +376,7 @@ export type {
|
|
|
360
376
|
export {
|
|
361
377
|
AGENTS,
|
|
362
378
|
BACKGROUND_TURNS,
|
|
379
|
+
CHANNEL_CONTEXT,
|
|
363
380
|
CONVERSATIONS,
|
|
364
381
|
DELEGATION,
|
|
365
382
|
IDENTITY,
|
|
@@ -367,6 +384,7 @@ export {
|
|
|
367
384
|
MEMORY,
|
|
368
385
|
MODES,
|
|
369
386
|
PRECHECKS,
|
|
387
|
+
PROFILES,
|
|
370
388
|
PROMPTS,
|
|
371
389
|
RUNTIME,
|
|
372
390
|
SCHEDULES,
|
package/src/kit/index.ts
CHANGED
package/src/kit/oidc.ts
ADDED
|
@@ -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`.
|