pi-roundtable 0.7.19 → 0.9.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 +140 -0
- package/README.md +72 -15
- package/README.zh-TW.md +65 -13
- package/docs/migrating-0.8.md +132 -0
- package/docs/migration-0.9.md +247 -0
- package/docs/plugins.md +853 -81
- package/examples/channel-context.test.ts +88 -0
- package/examples/channel-context.ts +62 -0
- package/examples/discord-adapter.test.ts +42 -0
- package/examples/discord-adapter.ts +26 -0
- package/examples/echo-runtime.test.ts +1 -0
- package/examples/echo-runtime.ts +1 -1
- package/examples/fake-surface.test.ts +69 -6
- package/examples/fake-surface.ts +73 -7
- package/examples/headless.test.ts +72 -0
- package/examples/headless.ts +35 -0
- package/examples/http.test.ts +31 -1
- package/examples/http.ts +39 -0
- package/examples/prechecks.test.ts +1 -0
- package/examples/principals.test.ts +60 -0
- package/examples/principals.ts +48 -0
- package/examples/prompt.test.ts +1 -1
- package/examples/study-room.test.ts +29 -1
- package/examples/study-room.ts +16 -19
- package/examples/support-desk.test.ts +3 -1
- package/examples/tools.test.ts +6 -1
- package/package.json +7 -3
- package/src/cli/checks/database.ts +11 -0
- package/src/cli/checks/identity.ts +225 -0
- package/src/cli/checks/model.ts +21 -3
- package/src/cli/cli.ts +130 -5
- package/src/cli/config-edit.ts +83 -13
- package/src/cli/doctor.ts +28 -5
- package/src/cli/init.ts +9 -1
- package/src/cli/line-diff.ts +72 -0
- package/src/cli/principal.ts +412 -0
- package/src/cli/project.ts +33 -2
- package/src/cli/report.ts +12 -3
- package/src/cli/templates.ts +46 -14
- package/src/cli/upgrade-rewrite.ts +102 -0
- package/src/cli/upgrade-source.ts +430 -0
- package/src/cli/upgrade.ts +176 -0
- package/src/core/agents/agent-claim.ts +56 -34
- package/src/core/agents/agent-team-fixture.ts +6 -0
- package/src/core/agents/team-turns.ts +10 -1
- package/src/core/builtin/agent-server.ts +38 -101
- package/src/core/builtin/discord-admin.ts +4 -1
- package/src/core/builtin/discord.ts +71 -13
- package/src/core/builtin/modules.ts +197 -43
- package/src/core/builtin/stores.ts +40 -21
- package/src/core/config/access.ts +229 -0
- package/src/core/config/adapters.ts +120 -0
- package/src/core/config/config.ts +228 -94
- package/src/core/contract/channel-context.ts +53 -0
- package/src/core/contract/channels.ts +81 -9
- package/src/core/contract/providers.ts +3 -2
- package/src/core/contract/runtime.ts +31 -11
- package/src/core/contract/surface.ts +35 -6
- package/src/core/conversations/conversation-registry.ts +56 -0
- package/src/core/conversations/conversation-store.ts +126 -0
- package/src/core/conversations/conversations-plugin.ts +29 -0
- package/src/core/define-roundtable.ts +157 -57
- package/src/core/discord/agent-panel.ts +2 -2
- package/src/core/discord/card-audience.ts +148 -0
- package/src/core/discord/channel-context.ts +348 -0
- package/src/core/discord/connection.ts +15 -3
- package/src/core/discord/direct-channel.ts +54 -0
- package/src/core/discord/discord-adapter.ts +9 -0
- package/src/core/discord/discord-owners.ts +133 -0
- package/src/core/discord/discord-surface.ts +69 -14
- package/src/core/discord/fresh-marker.ts +24 -0
- package/src/core/discord/inbound-message.ts +21 -7
- package/src/core/discord/interaction-module.ts +11 -1
- package/src/core/discord/owner-cards-fixture.ts +80 -0
- package/src/core/discord/owner-cards.ts +58 -86
- package/src/core/discord/owner-command.ts +27 -13
- package/src/core/discord/stop-button.ts +4 -4
- package/src/core/domain/conversation.ts +10 -0
- package/src/core/domain/errors.ts +5 -0
- package/src/core/domain/ports.ts +33 -2
- package/src/core/domain/progress.ts +10 -0
- package/src/core/events.ts +1 -0
- package/src/core/host.ts +32 -10
- package/src/core/http/listeners.ts +174 -21
- package/src/core/http/websocket.ts +316 -0
- package/src/core/i18n/cards.ts +11 -9
- package/src/core/identity/access-policy.ts +227 -0
- package/src/core/identity/actor-facts.ts +65 -0
- package/src/core/identity/caching-principal-store.ts +111 -0
- package/src/core/identity/config-owner.ts +145 -0
- package/src/core/identity/contact.ts +27 -0
- package/src/core/identity/identity-plugin.ts +56 -0
- package/src/core/identity/identity-schema.ts +282 -0
- package/src/core/identity/identity-service.ts +489 -0
- package/src/core/identity/identity-view.ts +77 -0
- package/src/core/identity/plugin-identities.ts +109 -0
- package/src/core/identity/principal-reads.ts +38 -0
- package/src/core/identity/principal-store.ts +478 -0
- package/src/core/identity/principal-tables.ts +53 -0
- package/src/core/identity/seen-throttle.ts +57 -0
- package/src/core/identity/ulid.ts +36 -0
- package/src/core/identity.ts +34 -5
- package/src/core/interactions/prompts.ts +127 -0
- package/src/core/modules/background/background-turns.ts +56 -17
- package/src/core/modules/background/personal-target.ts +50 -0
- package/src/core/modules/delegation/delegate.ts +28 -14
- package/src/core/modules/delegation/delegator.ts +23 -7
- package/src/core/modules/memory/owner-memory.ts +123 -50
- package/src/core/modules/notify/notify.ts +53 -13
- package/src/core/modules/notify/session-notify.ts +110 -0
- package/src/core/modules/schedules/prechecks.ts +8 -2
- package/src/core/modules/schedules/schedule-prechecks.ts +4 -1
- package/src/core/modules/schedules/schedule-store.ts +51 -20
- package/src/core/modules/schedules/schedule-tools.ts +122 -12
- package/src/core/modules/schedules/scheduler.ts +43 -2
- package/src/core/modules/schedules/schedules.ts +43 -14
- package/src/core/ops/error-reporter.ts +24 -12
- package/src/core/plugin.ts +62 -0
- package/src/core/presence/direct-channels.ts +104 -0
- package/src/core/registry/contributions.ts +63 -3
- package/src/core/registry/providers.ts +1 -1
- package/src/core/routing/channel-router.ts +226 -17
- package/src/core/routing/conversation-turns.ts +85 -1
- package/src/core/routing/surface-port.ts +35 -2
- package/src/core/routing/system-turns.ts +29 -0
- package/src/core/runtime/bridge-guard.ts +225 -0
- package/src/core/runtime/compaction-tiers.ts +5 -1
- package/src/core/runtime/conversation-sessions.ts +124 -12
- package/src/core/runtime/extensions/ask-user.ts +1 -1
- package/src/core/runtime/extensions/confirmation-gate.ts +32 -10
- package/src/core/runtime/extensions/private-memory.ts +447 -0
- package/src/core/runtime/extensions/self-compact-guard.ts +11 -0
- package/src/core/runtime/pending-confirmation-store.ts +67 -4
- package/src/core/runtime/pi-agent-runtime.ts +143 -135
- package/src/core/runtime/preflight-tools.ts +47 -0
- package/src/core/runtime/prompt-slot.ts +6 -6
- package/src/core/runtime/reader-history.ts +129 -0
- package/src/core/runtime/runtime-plugin.ts +205 -0
- package/src/core/runtime/runtime-types.ts +40 -12
- package/src/core/runtime/session-conversation.ts +143 -0
- package/src/core/runtime/session-factory.ts +115 -15
- package/src/core/runtime/session-scope.ts +78 -0
- package/src/core/runtime/steerable-run.ts +9 -0
- package/src/core/runtime/tool-call-scope.ts +43 -0
- package/src/core/runtime/turn-answer.ts +30 -1
- package/src/core/runtime/turn-progress.ts +116 -0
- package/src/core/services.ts +42 -2
- package/src/core/sessions.ts +30 -0
- package/src/core/shared/unix-server.ts +35 -5
- package/src/core/speakers.ts +21 -19
- package/src/core/testing/background.ts +31 -0
- package/src/core/testing/fixture-database.ts +55 -0
- package/src/core/testing/map-identity.ts +76 -0
- package/src/core/testing/module-sessions.ts +134 -0
- package/src/core/testing/modules.ts +149 -38
- package/src/core/testing/owner.ts +17 -0
- package/src/core/testing/surface-contract.ts +460 -0
- package/src/core/testing/test-host.ts +100 -19
- package/src/core/testing/tool-set.ts +32 -0
- package/src/core/tool-set.snapshot.json +4 -4
- package/src/core/tool-tiers.ts +57 -3
- package/src/discord/index.ts +10 -0
- package/src/index.ts +65 -8
- package/src/kit/compaction.ts +13 -0
- package/src/kit/index.ts +10 -0
- package/src/kit/support.ts +1 -1
- package/src/testing.ts +96 -21
- package/templates/.env.example +1 -1
- package/templates/adapters/web/.env.example +24 -0
- package/templates/adapters/web/README.md +22 -0
- package/templates/adapters/web/package.json.tmpl +26 -0
- package/templates/adapters/web/persona/assistant.md +2 -0
- package/templates/adapters/web/roundtable.config.ts +59 -0
- package/templates/package.json.tmpl +1 -0
- package/templates/plugins/self-compact.ts +11 -0
- package/templates/roundtable.config.ts +14 -2
- package/src/core/domain/owner-prompts.ts +0 -45
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copy this file to .env and fill it in. Bun loads .env by itself; never commit it.
|
|
2
|
+
|
|
3
|
+
# You: the operator who runs this host, named in the assistant's prompts.
|
|
4
|
+
OWNER_NAME=
|
|
5
|
+
|
|
6
|
+
# PostgreSQL. This matches docker-compose.yml: run `docker compose up -d`.
|
|
7
|
+
DATABASE_URL=postgres://roundtable:roundtable@localhost:5432/roundtable
|
|
8
|
+
|
|
9
|
+
# The assistant's model as <provider>/<id>, and the provider's API key (or log in with Pi and leave the key out).
|
|
10
|
+
MODEL=anthropic/claude-sonnet-5-5
|
|
11
|
+
# ANTHROPIC_API_KEY=
|
|
12
|
+
|
|
13
|
+
# Your OpenID Connect provider: register this API there, then copy its issuer (iss), the API's
|
|
14
|
+
# audience (aud), and the provider's signing keys address (jwks_uri in its discovery document).
|
|
15
|
+
OIDC_ISSUER=
|
|
16
|
+
OIDC_AUDIENCE=
|
|
17
|
+
OIDC_JWKS_URL=
|
|
18
|
+
|
|
19
|
+
# Who may chat: the role names your provider puts in the token's roles claim, comma-separated.
|
|
20
|
+
CHAT_MEMBER_ROLES=
|
|
21
|
+
# CHAT_ADMIN_ROLES=
|
|
22
|
+
|
|
23
|
+
# The origins of the web pages that open the chat, comma-separated, such as https://chat.example.com.
|
|
24
|
+
CHAT_ORIGINS=
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# __PROJECT__
|
|
2
|
+
|
|
3
|
+
A web chat agent server built on [pi-roundtable](https://www.npmjs.com/package/pi-roundtable) and [pi-roundtable-webchat](https://www.npmjs.com/package/pi-roundtable-webchat).
|
|
4
|
+
People your OpenID Connect provider signs in chat with the assistant in private conversations; there is no Discord.
|
|
5
|
+
|
|
6
|
+
1. Install: `bun install`, then copy `.env.example` to `.env` and fill it in.
|
|
7
|
+
2. Check: `bunx roundtable doctor` says what is still missing and how to fix it.
|
|
8
|
+
3. Run: `bunx roundtable start`, behind a reverse proxy that serves it over HTTPS.
|
|
9
|
+
|
|
10
|
+
The chat is under `/chat`: a web page gets a one-time ticket from `POST /chat/tickets` with the person's token, and opens `/chat/socket` with it.
|
|
11
|
+
The protocol is in `node_modules/pi-roundtable-webchat/README.md`.
|
|
12
|
+
Core `access` in `roundtable.config.ts` decides admission; token roles are prefixed with `web:role:` there.
|
|
13
|
+
New admitted users get principals, and linked Discord/web identities share private memory and quotas.
|
|
14
|
+
Link identities with `bunx roundtable principal link <principal> <identity>`; use `principal list` to inspect them.
|
|
15
|
+
|
|
16
|
+
The private inbox is `GET /chat/notices`, with `POST /chat/notices/<id>/read` to acknowledge an entry.
|
|
17
|
+
Online connections also receive additive `notice` frames.
|
|
18
|
+
Schedules and delegated reports can answer in their creator's private conversation; enable their tools in the persona selection only where intended and allowed by tier.
|
|
19
|
+
|
|
20
|
+
`roundtable.config.ts` holds the settings and lists the plugins; `plugins/` holds yours, and `persona/assistant.md` is the assistant's prompt.
|
|
21
|
+
Add another plugin with `bunx roundtable add plugin <name>`, and test it with `bun test`.
|
|
22
|
+
The plugin guide is in `node_modules/pi-roundtable/docs/plugins.md` and on the package's page.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PROJECT__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"engines": {
|
|
6
|
+
"bun": ">=1.3.0"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"doctor": "roundtable doctor",
|
|
10
|
+
"start": "roundtable start",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"lint": "biome check .",
|
|
13
|
+
"test": "bun test"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"pi-roundtable": "__VERSION__",
|
|
17
|
+
"pi-roundtable-webchat": "__VERSION__",
|
|
18
|
+
"pi-self-compact": "0.2.0",
|
|
19
|
+
"typebox": "1.3.34"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@biomejs/biome": "2.5.15",
|
|
23
|
+
"@types/bun": "1.4.2",
|
|
24
|
+
"typescript": "7.0.2"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import type { RoundtableConfig } from "pi-roundtable";
|
|
3
|
+
import { oidcJwtVerifier, webChat } from "pi-roundtable-webchat";
|
|
4
|
+
import { hello } from "./plugins/hello.ts";
|
|
5
|
+
import { selfCompact } from "./plugins/self-compact.ts";
|
|
6
|
+
|
|
7
|
+
// Credentials and ids come from .env, which Bun loads on its own; nothing secret belongs in this file.
|
|
8
|
+
const env = (name: string): string => process.env[name] ?? "";
|
|
9
|
+
const list = (name: string): string[] =>
|
|
10
|
+
env(name)
|
|
11
|
+
.split(",")
|
|
12
|
+
.map((value) => value.trim())
|
|
13
|
+
.filter(Boolean);
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
name: "Roundtable",
|
|
17
|
+
// The operator who runs this host, as the host's owner. People sign in through your OpenID
|
|
18
|
+
// Connect provider instead; core access maps their verified, surface-prefixed roles to tiers.
|
|
19
|
+
access: {
|
|
20
|
+
owners: [{ name: env("OWNER_NAME"), principal: "operator" }],
|
|
21
|
+
members: {
|
|
22
|
+
roles: list("CHAT_MEMBER_ROLES").map((role) => `web:role:${role}`),
|
|
23
|
+
},
|
|
24
|
+
admins: {
|
|
25
|
+
roles: list("CHAT_ADMIN_ROLES").map((role) => `web:role:${role}`),
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
database: { url: env("DATABASE_URL") },
|
|
29
|
+
// Paths are relative to the project directory, where the roundtable command runs.
|
|
30
|
+
dataDir: "./data",
|
|
31
|
+
model: env("MODEL"),
|
|
32
|
+
// Serve behind a reverse proxy that terminates TLS; the web chat lives under /chat.
|
|
33
|
+
http: { port: 3000, hostname: "127.0.0.1" },
|
|
34
|
+
plugins: [
|
|
35
|
+
selfCompact,
|
|
36
|
+
hello,
|
|
37
|
+
webChat({
|
|
38
|
+
// Accepts only a person's access token. Pin your tenant and pick a stable subject claim
|
|
39
|
+
// with subjectClaim and check: see "Provider settings" in the pi-roundtable-webchat README.
|
|
40
|
+
verifier: oidcJwtVerifier({
|
|
41
|
+
jwksUrl: env("OIDC_JWKS_URL"),
|
|
42
|
+
issuers: [env("OIDC_ISSUER")],
|
|
43
|
+
audiences: [env("OIDC_AUDIENCE")],
|
|
44
|
+
}),
|
|
45
|
+
origins: list("CHAT_ORIGINS"),
|
|
46
|
+
personas: [
|
|
47
|
+
{
|
|
48
|
+
kind: "assistant",
|
|
49
|
+
label: "Assistant",
|
|
50
|
+
prompt: () => readFileSync("./persona/assistant.md", "utf8"),
|
|
51
|
+
// The tools of its turns, by name. Schedules, delegated reports and notify can reach
|
|
52
|
+
// this private conversation; add those tools only where intended and permitted by tier.
|
|
53
|
+
// Leave out web_search and fetch_content unless people may make the server fetch any address.
|
|
54
|
+
selection: { tools: ["hello_greet"], groups: [] },
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
}),
|
|
58
|
+
],
|
|
59
|
+
} satisfies RoundtableConfig;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { definePlugin } from "pi-roundtable";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Loads the Pi package pi-self-compact in every conversation session. Its compact_session tool
|
|
5
|
+
* lets a turn compact a long conversation; every session carries it, so startup stops with
|
|
6
|
+
* "required tools are not registered: compact_session" when no plugin loads it.
|
|
7
|
+
*/
|
|
8
|
+
export const selfCompact = definePlugin({
|
|
9
|
+
name: "self-compact",
|
|
10
|
+
setup: () => ({ piPackages: ["pi-self-compact"] }),
|
|
11
|
+
});
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import type { RoundtableConfig } from "pi-roundtable";
|
|
2
2
|
import { agents } from "./agents.ts";
|
|
3
3
|
import { hello } from "./plugins/hello.ts";
|
|
4
|
+
import { selfCompact } from "./plugins/self-compact.ts";
|
|
4
5
|
|
|
5
6
|
// Credentials and ids come from .env, which Bun loads on its own; nothing secret belongs in this file.
|
|
6
7
|
const env = (name: string): string => process.env[name] ?? "";
|
|
7
8
|
|
|
8
9
|
export default {
|
|
9
10
|
name: "Roundtable",
|
|
10
|
-
owner:
|
|
11
|
+
// Who the host serves. You are the owner: your principal and your Discord identity are your
|
|
12
|
+
// Discord user id. Add admins and members by Discord user or role, such as
|
|
13
|
+
// members: { roles: ["discord:role:<role id>"] }.
|
|
14
|
+
access: {
|
|
15
|
+
owners: [
|
|
16
|
+
{
|
|
17
|
+
name: env("OWNER_NAME"),
|
|
18
|
+
principal: env("OWNER_ID"),
|
|
19
|
+
identities: [`discord:${env("OWNER_ID")}`],
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
},
|
|
11
23
|
discord: {
|
|
12
24
|
token: env("DISCORD_TOKEN"),
|
|
13
25
|
guild: env("DISCORD_GUILD_ID"),
|
|
@@ -20,5 +32,5 @@ export default {
|
|
|
20
32
|
http: { publicUrl: env("PUBLIC_URL") },
|
|
21
33
|
prompts: { shared: "./persona/shared.md" },
|
|
22
34
|
agents,
|
|
23
|
-
plugins: [hello],
|
|
35
|
+
plugins: [selfCompact, hello],
|
|
24
36
|
} satisfies RoundtableConfig;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { Tier } from "../speakers.ts";
|
|
2
|
-
/**
|
|
3
|
-
* The owner answering inside a running turn: a card in the turn's channel that only they may
|
|
4
|
-
* answer. Unanswered cards expire; a stopped turn cancels its open cards.
|
|
5
|
-
*/
|
|
6
|
-
export type Approval = "approved" | "declined" | "expired" | "cancelled";
|
|
7
|
-
|
|
8
|
-
export interface AskOption {
|
|
9
|
-
label: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface OwnerQuestion {
|
|
14
|
-
question: string;
|
|
15
|
-
/** Up to 25; none means a free-text answer. */
|
|
16
|
-
options: readonly AskOption[];
|
|
17
|
-
/** More than one option may be chosen. */
|
|
18
|
-
multi: boolean;
|
|
19
|
-
/** They may write an answer of their own besides the options. */
|
|
20
|
-
allowOther: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface OwnerAnswer {
|
|
24
|
-
/** The chosen options' labels, in the order they were offered. */
|
|
25
|
-
choices: string[];
|
|
26
|
-
/** What they wrote himself, if anything. */
|
|
27
|
-
text?: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface OwnerPrompts {
|
|
31
|
-
/** Asks them to approve an action; `signal` cancels the card when the turn stops. */
|
|
32
|
-
confirm(
|
|
33
|
-
title: string,
|
|
34
|
-
message: string,
|
|
35
|
-
signal?: AbortSignal,
|
|
36
|
-
/** The lowest tier that may approve; the owner only when absent. */
|
|
37
|
-
minTier?: Tier,
|
|
38
|
-
): Promise<Approval>;
|
|
39
|
-
/** Asks them a question; undefined when it expired or was cancelled. */
|
|
40
|
-
ask(
|
|
41
|
-
title: string,
|
|
42
|
-
question: OwnerQuestion,
|
|
43
|
-
signal?: AbortSignal,
|
|
44
|
-
): Promise<OwnerAnswer | undefined>;
|
|
45
|
-
}
|