pi-roundtable-sandbox 0.7.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 +15 -0
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/examples/roundtable.config.ts +36 -0
- package/package.json +47 -0
- package/src/broker.ts +387 -0
- package/src/channel-store.ts +81 -0
- package/src/claim.ts +77 -0
- package/src/commands.ts +63 -0
- package/src/container-driver.ts +193 -0
- package/src/index.ts +29 -0
- package/src/model-input.ts +177 -0
- package/src/plugin.ts +85 -0
- package/src/protocol.ts +108 -0
- package/src/runtime.ts +240 -0
- package/worker/Dockerfile +6 -0
- package/worker/agent.ts +271 -0
- package/worker/main.ts +16 -0
- package/worker/memory.ts +138 -0
- package/worker/transport.ts +61 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
- Move into the pi-roundtable monorepo at `packages/sandbox`, preserving Git history.
|
|
6
|
+
- Align the version, core development dependency, and peer range with core 0.7.0 (`>=0.7.0 <0.8.0`).
|
|
7
|
+
- Use the shared checks and lockstep publication workflow; the Docker integration remains opt-in locally and runs explicitly in Linux CI.
|
|
8
|
+
|
|
9
|
+
## 0.1.0
|
|
10
|
+
|
|
11
|
+
- Add sealed text-only guest channels for pi-roundtable 0.6.1 using Docker on Linux.
|
|
12
|
+
- Add a per-turn Unix broker with fixed model forwarding, host-only credential swapping, tool and MCP allow-lists, and bounded requests.
|
|
13
|
+
- Add persistent channel and speaker memory inside each isolated workspace.
|
|
14
|
+
- Add owner-only sandbox on, off, and status commands using the shared channel queue.
|
|
15
|
+
- Ship the minimal worker image, setup example, threat model, offline tests, optional Docker integration test, and CI/publish workflows.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pi-roundtable-sandbox contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# pi-roundtable-sandbox
|
|
2
|
+
|
|
3
|
+
Sealed guest channels for pi-roundtable 0.7.
|
|
4
|
+
Source lives in [`packages/sandbox`][source] in the pi-roundtable repository and releases in lockstep with the core.
|
|
5
|
+
Each addressed message runs a small tool-using agent in a new Docker container with no network and no real credentials.
|
|
6
|
+
A host-side Unix-socket broker is its only way out.
|
|
7
|
+
Channel memory and recent conversation text persist in the channel's dedicated workspace between containers.
|
|
8
|
+
|
|
9
|
+
[source]: https://github.com/wayne930242/pi-roundtable/tree/master/packages/sandbox
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- Bun 1.4.2 or later and pi-roundtable `>=0.7.0 <0.8.0`.
|
|
14
|
+
- A native Linux host with a local Docker daemon and a non-root service account permitted to run Docker.
|
|
15
|
+
- The worker UID/GID match that account; root workers are refused.
|
|
16
|
+
- A trusted OpenAI-compatible, non-streaming Chat Completions endpoint supporting function tools and `max_tokens`.
|
|
17
|
+
- A host-side API credential for that endpoint.
|
|
18
|
+
A subscription-specific login is not necessarily compatible with Chat Completions.
|
|
19
|
+
|
|
20
|
+
macOS supports offline development, tests, and building the image.
|
|
21
|
+
Actual sandbox execution requires Linux: Docker Desktop does not share host Unix sockets into its Linux VM.
|
|
22
|
+
Remote Docker daemons are unsupported because bind paths and Unix sockets must exist on the same host.
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
Install the package alongside pi-roundtable after it is published:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
bun add pi-roundtable-sandbox
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Build the image from the installed package, or from this repository during development:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
docker build -f node_modules/pi-roundtable-sandbox/worker/Dockerfile -t pi-roundtable-sandbox:local node_modules/pi-roundtable-sandbox
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Add the plugin to `roundtable.config.ts`:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { join } from "node:path";
|
|
42
|
+
import { sandbox } from "pi-roundtable-sandbox";
|
|
43
|
+
|
|
44
|
+
const home = process.env.HOME;
|
|
45
|
+
if (!home) throw new Error("HOME is required");
|
|
46
|
+
|
|
47
|
+
// Merge with the rest of the configuration generated by pi-roundtable init.
|
|
48
|
+
export const guestPlugins = [sandbox({
|
|
49
|
+
image: "pi-roundtable-sandbox:local",
|
|
50
|
+
runRoot: "/tmp/roundtable-sandbox-run",
|
|
51
|
+
workspaceRoot: join(home, ".local/share/roundtable-sandbox/workspaces"),
|
|
52
|
+
stateFile: join(home, ".local/share/roundtable-sandbox/state/channels.json"),
|
|
53
|
+
provider: "openai",
|
|
54
|
+
model: "operator-selected-model",
|
|
55
|
+
modelUrl: "https://api.openai.com/v1/chat/completions",
|
|
56
|
+
})];
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Choose a model available to your endpoint and sign the host into its provider.
|
|
60
|
+
By default, `context.apiKey(provider)` is read on every request, allowing login refresh without copying credentials into the worker.
|
|
61
|
+
Alternatively supply `apiKey: () => process.env.MODEL_API_KEY` when the endpoint uses a separate key.
|
|
62
|
+
Keep secrets in the service's protected environment, not configuration source or the worker image.
|
|
63
|
+
All directories must be dedicated to this package and owned by the service account.
|
|
64
|
+
Existing roots and the state directory must have no group/other permissions; insecure permissions are refused at startup.
|
|
65
|
+
The `uid` and `gid` options may make deployment settings explicit but must match the host process.
|
|
66
|
+
Keep `runRoot` short enough for a Unix socket path (at most 100 characters including the per-turn suffix).
|
|
67
|
+
Keep `stateFile` outside both roots; it is host-only routing state.
|
|
68
|
+
Keep the roots outside Docker's daemon data directory; Docker rejects private propagation for bind sources inside that directory.
|
|
69
|
+
Back up that state and the workspaces together, without following workspace symlinks.
|
|
70
|
+
Only one host process may own these directories.
|
|
71
|
+
|
|
72
|
+
Restart the bot, then run `/roundtable sandbox on` in a guild channel as the owner.
|
|
73
|
+
The command root follows your `discord.rootCommand` setting.
|
|
74
|
+
The claim outranks the core agent-server claim (priority 200 versus 100), including when the owner speaks there.
|
|
75
|
+
It answers non-bot, non-integration guild messages that mention the bot or reply to it.
|
|
76
|
+
Other messages are dropped, never routed to a host agent.
|
|
77
|
+
`/roundtable sandbox status` shows the mode; `/roundtable sandbox off` retains memory and restores normal routing after queued work completes.
|
|
78
|
+
These commands are guarded by the published owner-command helper and serialized through the shared channel queue.
|
|
79
|
+
Do not disable sandbox routing in a channel that should remain a guest-only boundary.
|
|
80
|
+
`initialChannels` seeds the first state file only; subsequent starts use its saved state.
|
|
81
|
+
The `SANDBOX` service exposes `channels` and `runtime` for other trusted plugins.
|
|
82
|
+
Threads have separate channel keys and do not inherit a parent channel's sandbox mode; enable each thread explicitly through the trusted channel service if needed.
|
|
83
|
+
|
|
84
|
+
## Allowed host tools
|
|
85
|
+
|
|
86
|
+
No host tool is enabled by default.
|
|
87
|
+
Supply only capabilities you intend every guest in every configured sandbox channel to use:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import type { HostTool } from "pi-roundtable-sandbox";
|
|
91
|
+
|
|
92
|
+
const tools: HostTool[] = [{
|
|
93
|
+
name: "clock",
|
|
94
|
+
description: "Read the current UTC time",
|
|
95
|
+
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
96
|
+
run: (_input, context) => {
|
|
97
|
+
context.signal.throwIfAborted();
|
|
98
|
+
return new Date().toISOString();
|
|
99
|
+
},
|
|
100
|
+
}];
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Pass `tools` to `sandbox()`.
|
|
104
|
+
Host tool and MCP server/tool names must match `[a-z][a-z0-9_]{0,47}`.
|
|
105
|
+
The worker exposes them as `host_clock`, while the broker accepts only `POST /tools/clock`.
|
|
106
|
+
The host binds `context.channel` and `context.speaker` to the current admitted turn.
|
|
107
|
+
The callback signal combines the request's deadline/closure and the turn's cancellation, and aborts when either scope ends.
|
|
108
|
+
Body fields cannot change that identity, even if a guest replaces the worker or forges a broker call.
|
|
109
|
+
Callbacks must validate every input field, enforce their own authorization and rate limits, obey cancellation, and avoid returning secrets.
|
|
110
|
+
Parameter schemas are model guidance, not a host-side validator.
|
|
111
|
+
Do not expose shell execution, arbitrary file paths, arbitrary URLs, owner memory, or a generic tool dispatcher.
|
|
112
|
+
All configured tools are available to all sandbox channels; use a context-aware callback when policies differ.
|
|
113
|
+
|
|
114
|
+
## Optional MCP tools
|
|
115
|
+
|
|
116
|
+
Supply `mcp: [{ name, url, apiKey, tools }]` to allow specific tools of specific servers.
|
|
117
|
+
Each tool declares `name`, `description` and a JSON-schema `parameters` object.
|
|
118
|
+
The worker exposes names such as `mcp_0_search` and sends calls through `POST /mcp/<server>`.
|
|
119
|
+
Only single `tools/call` requests naming a declared tool are accepted.
|
|
120
|
+
Unknown servers, tools, RPC batches, resources, prompts, discovery and arbitrary RPC methods are refused.
|
|
121
|
+
The endpoint is operator-configured and never sent to the container.
|
|
122
|
+
`apiKey` is optional for unauthenticated servers and otherwise read on each call; the broker inserts a bearer credential.
|
|
123
|
+
This minimal adapter supports stateless Streamable HTTP endpoints returning JSON directly.
|
|
124
|
+
It does not perform initialization/session negotiation, accept SSE, or provide a raw general-purpose MCP proxy.
|
|
125
|
+
Choose narrow server tools, and apply server-side authorization as well.
|
|
126
|
+
|
|
127
|
+
## Threat model
|
|
128
|
+
|
|
129
|
+
Treat guest prompts, model outputs and everything in a container as untrusted, including a worker compromised into arbitrary code execution.
|
|
130
|
+
The operator, Docker daemon, Linux kernel, built image, host callbacks and upstream model/MCP services are trusted.
|
|
131
|
+
Docker is a process-isolation boundary, not a VM or a guarantee against kernel vulnerabilities.
|
|
132
|
+
Use a patched host and a dedicated machine for higher-risk workloads.
|
|
133
|
+
|
|
134
|
+
A container has:
|
|
135
|
+
|
|
136
|
+
- `--network none`, a read-only root filesystem, all capabilities dropped, and `no-new-privileges`.
|
|
137
|
+
- A non-root UID/GID, 512 MiB RAM with no additional swap, one CPU, 64 PIDs, and a bounded temporary filesystem.
|
|
138
|
+
- Exactly two bind mounts: its channel workspace (writable) and its current-turn broker directory (read-only).
|
|
139
|
+
The workspace remains executable; the threat model already assumes arbitrary container code execution and does not rely on `noexec`.
|
|
140
|
+
- No Docker socket, host home, owner workspace, auth file, host environment, host tool registry or other channel's files.
|
|
141
|
+
- Only the public tool descriptions, current message and speaker, system prompt, time zone, and a dummy API key in worker code.
|
|
142
|
+
|
|
143
|
+
The worker talks to the broker over a read-only Unix-socket mount.
|
|
144
|
+
The host reads its final reply from Docker stdout, never from a guest-writable socket or file path.
|
|
145
|
+
A new container and broker are created per turn and never reused across channels.
|
|
146
|
+
On cancellation, the run CLI is killed with SIGKILL and the exact named container is force-removed; each removal command has a five-second deadline.
|
|
147
|
+
Cleanup failures end the turn with an error and a generic host log requiring operator inspection, rather than hanging a channel queue.
|
|
148
|
+
A short second removal covers the local create/attach race.
|
|
149
|
+
An unresponsive daemon or delayed create request may still leave a stopped orphan; treat daemon failures and host crashes as an operator cleanup condition.
|
|
150
|
+
Containers use `--log-driver none` to avoid unbounded daemon log files and `--pull never` to run only the image the operator already built.
|
|
151
|
+
Channel keys are hashed for workspace names and are not interpreted as paths.
|
|
152
|
+
The channel queue prevents overlapping turns; other channels run independently.
|
|
153
|
+
|
|
154
|
+
The broker accepts only POSTs to `/model`, explicitly listed `/tools/<name>`, and explicitly listed `/mcp/<server>`.
|
|
155
|
+
Queries, extra path segments, unknown routes, hop headers, cookies, proxy headers, forwarded headers, unknown headers and non-dummy caller credentials are refused.
|
|
156
|
+
Request headers are rebuilt rather than forwarded.
|
|
157
|
+
The model route fixes the complete upstream URL, model, non-streaming mode and output-token limit; the guest cannot select another endpoint or increase that limit.
|
|
158
|
+
It accepts only system/user/assistant/tool roles with string content and function tool calls.
|
|
159
|
+
Media URLs, account file references, audio payloads and native provider tools are refused.
|
|
160
|
+
Schema keywords `$ref`, `$dynamicRef`, `$recursiveRef`, `$id`, `$schema` and `$vocabulary` accept only local fragments, not remote URLs.
|
|
161
|
+
Checks visit actual schema positions, not property names or enum/const data.
|
|
162
|
+
Upstream redirects are refused and no upstream response headers or cookies reach the guest.
|
|
163
|
+
Only bounded JSON responses are accepted; obvious raw, URL-encoded, base64, base64url and hex credential reflections are refused after JSON decoding.
|
|
164
|
+
This is defense in depth for trusted upstreams, not a detector for every possible encoding or secret fragment.
|
|
165
|
+
Errors are generic and never include upstream URLs, headers or exception text.
|
|
166
|
+
No broker payloads or credentials are logged.
|
|
167
|
+
|
|
168
|
+
The real model/MCP credential exists only on the host and is swapped in immediately before an upstream call.
|
|
169
|
+
This protects the credential value, not the ability to spend it through the allowed model endpoint during a turn.
|
|
170
|
+
A malicious guest can call allowed routes directly and exercise every granted capability.
|
|
171
|
+
Default bounds are 48 broker calls per turn, 256 KiB request bodies, 1 MiB upstream/tool responses, one in-flight broker call, a 60-second upstream deadline, a 120-second turn deadline, and 4,096 output tokens per model request.
|
|
172
|
+
Each broker listener permits at most 16 connections, a ten-second initial-header deadline and a 60-second request deadline.
|
|
173
|
+
The worker itself stops after 12 model calls and eight tools per response.
|
|
174
|
+
Malformed or unavailable provider tool names are refused through a local placeholder; invalid or duplicate call IDs are normalized together with their paired replies.
|
|
175
|
+
Tune container resources with `limits: { memoryMb, cpus, pids }` and the turn deadline with `turnTimeoutMs` (1 to 600 seconds).
|
|
176
|
+
These are not billing quotas, global concurrency limits or disk quotas.
|
|
177
|
+
Apply provider spend limits, ingress rate limits, a per-workspace filesystem quota, and host capacity controls before exposing a busy public channel.
|
|
178
|
+
Host callbacks that ignore cancellation cannot be forcibly undone; write them to honor `context.signal`.
|
|
179
|
+
An abrupt host crash can leave an isolated container behind; inspect and remove only stale containers prefixed `roundtable-sandbox-` belonging to this installation before restarting.
|
|
180
|
+
|
|
181
|
+
## Memory and scope
|
|
182
|
+
|
|
183
|
+
`memory_set`, `memory_get`, and `memory_remove` run inside the sandbox and accept a `speaker` or `channel` scope.
|
|
184
|
+
The current speaker selects the speaker namespace; a tool argument cannot select somebody else.
|
|
185
|
+
Channel notes are shared within that workspace; other channels and host agents do not see them.
|
|
186
|
+
Entries are persisted as JSON, capped at 256 entries, 2,048 characters per value and 512 KiB total.
|
|
187
|
+
Up to ten settled user/assistant exchanges persist as channel conversation context; raw tool transcripts are not retained.
|
|
188
|
+
History entries are capped at 8 KiB of JSON-encoded text, system-prompt memory previews at 4 KiB per scope, and current user context at 48 KiB.
|
|
189
|
+
Full notes remain in the store and can be retrieved or removed by key with the memory tools.
|
|
190
|
+
Model request context stays below 192 KiB by dropping old text history or complete tool-call groups, not partial tool transcripts.
|
|
191
|
+
The worker marks truncated text; bounded tool descriptions and tool results cannot grow a later turn past the broker's body limit.
|
|
192
|
+
Treat every channel's history and memory as potentially visible to all guests in that channel.
|
|
193
|
+
Speaker namespaces prevent accidental tool cross-talk, not access by code that compromises the shared channel container.
|
|
194
|
+
Never put confidential data in a guest workspace.
|
|
195
|
+
`startFresh` resets history on the next successful turn and preserves memory; a pending reset is process-local and does not survive host restart.
|
|
196
|
+
Turning mode off does not erase workspace files.
|
|
197
|
+
|
|
198
|
+
This first version is text-only and uses a minimal Chat Completions agent loop rather than loading a full Pi session inside the container.
|
|
199
|
+
Attachments are not downloaded; the agent is told they are unsupported.
|
|
200
|
+
It does not load skills or extensions and has no shell, schedules, delegation, image tools, personas, or access to the host runtime.
|
|
201
|
+
|
|
202
|
+
## Development and verification
|
|
203
|
+
|
|
204
|
+
From the pi-roundtable repository root:
|
|
205
|
+
|
|
206
|
+
```sh
|
|
207
|
+
bun install --frozen-lockfile
|
|
208
|
+
bun run --cwd packages/sandbox test
|
|
209
|
+
bun run --cwd packages/sandbox typecheck
|
|
210
|
+
bun run --cwd packages/sandbox lint
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Offline tests cover credential swapping and reflection, route/header/media refusals, host-bound identity, host-tool and MCP allow-lists, real Unix transport, generated Docker arguments, routing precedence, cancellation/cleanup, persistence and memory scopes.
|
|
214
|
+
The Docker integration test is skipped by default and requires a native Linux non-root host with local Docker:
|
|
215
|
+
|
|
216
|
+
```sh
|
|
217
|
+
cd packages/sandbox
|
|
218
|
+
SANDBOX_DOCKER_TEST=1 bun test src/docker.integration.test.ts
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
It builds the image and runs a turn against a fake model endpoint on the host, checking that only the broker receives the real test credential.
|
|
222
|
+
It also runs a hostile PID 1 that ignores SIGTERM and verifies that the turn deadline removes that container.
|
|
223
|
+
No live provider, Discord connection or database is needed.
|
|
224
|
+
Shared CI runs offline checks and explicitly enables that Linux Docker test on its Ubuntu runner.
|
|
225
|
+
The shared publish workflow repeats local checks and requires a version-matching `v*` tag for the core and all official packages.
|
|
226
|
+
The owner performs the first sandbox publication and configures trusted publishing as described in [workspace releases][releases].
|
|
227
|
+
|
|
228
|
+
[releases]: https://github.com/wayne930242/pi-roundtable/blob/master/.github/PACKAGE-RELEASES.md
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import type { RoundtableConfig } from "pi-roundtable";
|
|
3
|
+
import { sandbox } from "../src/index.ts";
|
|
4
|
+
|
|
5
|
+
const home = process.env.HOME;
|
|
6
|
+
if (!home) throw new Error("HOME is required");
|
|
7
|
+
|
|
8
|
+
/** Merge these plugins into the configuration generated by pi-roundtable init. */
|
|
9
|
+
export const sandboxConfig = {
|
|
10
|
+
plugins: [
|
|
11
|
+
sandbox({
|
|
12
|
+
image: "pi-roundtable-sandbox:local",
|
|
13
|
+
runRoot: "/tmp/roundtable-sandbox-run",
|
|
14
|
+
workspaceRoot: join(home, ".local/share/roundtable-sandbox/workspaces"),
|
|
15
|
+
stateFile: join(
|
|
16
|
+
home,
|
|
17
|
+
".local/share/roundtable-sandbox/state/channels.json",
|
|
18
|
+
),
|
|
19
|
+
provider: "openai",
|
|
20
|
+
model: "operator-selected-model",
|
|
21
|
+
modelUrl: "https://api.openai.com/v1/chat/completions",
|
|
22
|
+
tools: [
|
|
23
|
+
{
|
|
24
|
+
name: "clock",
|
|
25
|
+
description: "Read the current UTC time",
|
|
26
|
+
parameters: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {},
|
|
29
|
+
additionalProperties: false,
|
|
30
|
+
},
|
|
31
|
+
run: () => new Date().toISOString(),
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
}),
|
|
35
|
+
],
|
|
36
|
+
} satisfies Pick<RoundtableConfig, "plugins">;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-roundtable-sandbox",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Sealed guest channels and an allow-listed credential broker for pi-roundtable",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"engines": {
|
|
8
|
+
"bun": ">=1.4.2"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./src/index.ts"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src",
|
|
15
|
+
"!src/**/*.test.ts",
|
|
16
|
+
"worker",
|
|
17
|
+
"!worker/**/*.test.ts",
|
|
18
|
+
"examples",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md"
|
|
22
|
+
],
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/wayne930242/pi-roundtable.git",
|
|
26
|
+
"directory": "packages/sandbox"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public",
|
|
30
|
+
"provenance": true
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test": "bun test",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"lint": "biome check ."
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"pi-roundtable": ">=0.7.0 <0.8.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@biomejs/biome": "2.5.15",
|
|
42
|
+
"@types/bun": "1.4.2",
|
|
43
|
+
"discord.js": "14.27.0",
|
|
44
|
+
"pi-roundtable": "0.7.0",
|
|
45
|
+
"typescript": "7.0.2"
|
|
46
|
+
}
|
|
47
|
+
}
|