pi-harness-workspace 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/README.md +152 -0
- package/apps/web/dist/assets/index-C4tLweAB.js +20 -0
- package/apps/web/dist/assets/index-DPgRbQ4_.css +1 -0
- package/apps/web/dist/index.html +14 -0
- package/apps/web/index.html +13 -0
- package/apps/web/package.json +24 -0
- package/apps/web/profile/cordis.yml +44 -0
- package/apps/web/server-dist/bin.d.ts +3 -0
- package/apps/web/server-dist/bin.d.ts.map +1 -0
- package/apps/web/server-dist/bin.js +67 -0
- package/apps/web/server-dist/bin.js.map +1 -0
- package/apps/web/src/command-palette.ts +84 -0
- package/apps/web/src/file-diff.ts +42 -0
- package/apps/web/src/main.ts +12 -0
- package/apps/web/src/runtime.css +4 -0
- package/apps/web/src/server/bin.ts +64 -0
- package/apps/web/src/style.css +7 -0
- package/apps/web/tsconfig.build.json +1 -0
- package/apps/web/tsconfig.json +1 -0
- package/package.json +41 -0
- package/packages/api-gateway/dist/index.d.ts +8 -0
- package/packages/api-gateway/dist/index.d.ts.map +1 -0
- package/packages/api-gateway/dist/index.js +582 -0
- package/packages/api-gateway/dist/index.js.map +1 -0
- package/packages/api-gateway/package.json +22 -0
- package/packages/api-gateway/src/index.ts +577 -0
- package/packages/api-gateway/test/index.test.ts +327 -0
- package/packages/api-gateway/tsconfig.build.json +1 -0
- package/packages/api-gateway/tsconfig.json +1 -0
- package/packages/bundle-web-app/cordis.patch.yml +12 -0
- package/packages/bundle-web-app/dist/index.d.ts +12 -0
- package/packages/bundle-web-app/dist/index.d.ts.map +1 -0
- package/packages/bundle-web-app/dist/index.js +63 -0
- package/packages/bundle-web-app/dist/index.js.map +1 -0
- package/packages/bundle-web-app/package.json +22 -0
- package/packages/bundle-web-app/src/index.ts +69 -0
- package/packages/bundle-web-app/test/index.test.ts +29 -0
- package/packages/bundle-web-app/tsconfig.build.json +1 -0
- package/packages/bundle-web-app/tsconfig.json +1 -0
- package/packages/cli/dist/args.d.ts +16 -0
- package/packages/cli/dist/args.d.ts.map +1 -0
- package/packages/cli/dist/args.js +53 -0
- package/packages/cli/dist/args.js.map +1 -0
- package/packages/cli/dist/bin.d.ts +3 -0
- package/packages/cli/dist/bin.d.ts.map +1 -0
- package/packages/cli/dist/bin.js +40 -0
- package/packages/cli/dist/bin.js.map +1 -0
- package/packages/cli/dist/main.d.ts +14 -0
- package/packages/cli/dist/main.d.ts.map +1 -0
- package/packages/cli/dist/main.js +148 -0
- package/packages/cli/dist/main.js.map +1 -0
- package/packages/cli/dist/node-stdio.d.ts +10 -0
- package/packages/cli/dist/node-stdio.d.ts.map +1 -0
- package/packages/cli/dist/node-stdio.js +34 -0
- package/packages/cli/dist/node-stdio.js.map +1 -0
- package/packages/cli/dist/relaunch.d.ts +5 -0
- package/packages/cli/dist/relaunch.d.ts.map +1 -0
- package/packages/cli/dist/relaunch.js +52 -0
- package/packages/cli/dist/relaunch.js.map +1 -0
- package/packages/cli/package.json +25 -0
- package/packages/cli/src/args.ts +50 -0
- package/packages/cli/src/bin.ts +41 -0
- package/packages/cli/src/main.ts +155 -0
- package/packages/cli/src/node-stdio.ts +40 -0
- package/packages/cli/src/relaunch.ts +48 -0
- package/packages/cli/test/args.test.ts +28 -0
- package/packages/cli/test/cli.test.ts +153 -0
- package/packages/cli/test/relaunch.test.ts +29 -0
- package/packages/cli/tsconfig.build.json +11 -0
- package/packages/cli/tsconfig.json +10 -0
- package/packages/client-web/dist/control-room.d.ts +102 -0
- package/packages/client-web/dist/control-room.d.ts.map +1 -0
- package/packages/client-web/dist/control-room.js +12 -0
- package/packages/client-web/dist/control-room.js.map +1 -0
- package/packages/client-web/dist/design-contract.d.ts +85 -0
- package/packages/client-web/dist/design-contract.d.ts.map +1 -0
- package/packages/client-web/dist/design-contract.js +99 -0
- package/packages/client-web/dist/design-contract.js.map +1 -0
- package/packages/client-web/dist/index.d.ts +17 -0
- package/packages/client-web/dist/index.d.ts.map +1 -0
- package/packages/client-web/dist/index.js +19 -0
- package/packages/client-web/dist/index.js.map +1 -0
- package/packages/client-web/dist/react-room.d.ts +6 -0
- package/packages/client-web/dist/react-room.d.ts.map +1 -0
- package/packages/client-web/dist/react-room.js +103 -0
- package/packages/client-web/dist/react-room.js.map +1 -0
- package/packages/client-web/package.json +29 -0
- package/packages/client-web/src/control-room.ts +10 -0
- package/packages/client-web/src/design-contract.ts +112 -0
- package/packages/client-web/src/index.ts +21 -0
- package/packages/client-web/src/react-room.tsx +78 -0
- package/packages/client-web/test/design-contract.test.ts +24 -0
- package/packages/client-web/tsconfig.build.json +1 -0
- package/packages/client-web/tsconfig.json +1 -0
- package/packages/core/dist/boot.d.ts +13 -0
- package/packages/core/dist/boot.d.ts.map +1 -0
- package/packages/core/dist/boot.js +96 -0
- package/packages/core/dist/boot.js.map +1 -0
- package/packages/core/dist/context.d.ts +3 -0
- package/packages/core/dist/context.d.ts.map +1 -0
- package/packages/core/dist/context.js +2 -0
- package/packages/core/dist/context.js.map +1 -0
- package/packages/core/dist/index.d.ts +7 -0
- package/packages/core/dist/index.d.ts.map +1 -0
- package/packages/core/dist/index.js +6 -0
- package/packages/core/dist/index.js.map +1 -0
- package/packages/core/dist/plugins/model.d.ts +8 -0
- package/packages/core/dist/plugins/model.d.ts.map +1 -0
- package/packages/core/dist/plugins/model.js +12 -0
- package/packages/core/dist/plugins/model.js.map +1 -0
- package/packages/core/dist/plugins/models.d.ts +16 -0
- package/packages/core/dist/plugins/models.d.ts.map +1 -0
- package/packages/core/dist/plugins/models.js +24 -0
- package/packages/core/dist/plugins/models.js.map +1 -0
- package/packages/core/dist/plugins/resources.d.ts +18 -0
- package/packages/core/dist/plugins/resources.d.ts.map +1 -0
- package/packages/core/dist/plugins/resources.js +48 -0
- package/packages/core/dist/plugins/resources.js.map +1 -0
- package/packages/core/dist/plugins/runtime.d.ts +14 -0
- package/packages/core/dist/plugins/runtime.d.ts.map +1 -0
- package/packages/core/dist/plugins/runtime.js +68 -0
- package/packages/core/dist/plugins/runtime.js.map +1 -0
- package/packages/core/dist/plugins/session.d.ts +15 -0
- package/packages/core/dist/plugins/session.d.ts.map +1 -0
- package/packages/core/dist/plugins/session.js +20 -0
- package/packages/core/dist/plugins/session.js.map +1 -0
- package/packages/core/dist/plugins/stdio.d.ts +8 -0
- package/packages/core/dist/plugins/stdio.d.ts.map +1 -0
- package/packages/core/dist/plugins/stdio.js +20 -0
- package/packages/core/dist/plugins/stdio.js.map +1 -0
- package/packages/core/dist/plugins/tools.d.ts +13 -0
- package/packages/core/dist/plugins/tools.d.ts.map +1 -0
- package/packages/core/dist/plugins/tools.js +17 -0
- package/packages/core/dist/plugins/tools.js.map +1 -0
- package/packages/core/dist/profile.d.ts +8 -0
- package/packages/core/dist/profile.d.ts.map +1 -0
- package/packages/core/dist/profile.js +28 -0
- package/packages/core/dist/profile.js.map +1 -0
- package/packages/core/dist/runtime.d.ts +16 -0
- package/packages/core/dist/runtime.d.ts.map +1 -0
- package/packages/core/dist/runtime.js +33 -0
- package/packages/core/dist/runtime.js.map +1 -0
- package/packages/core/dist/services.d.ts +63 -0
- package/packages/core/dist/services.d.ts.map +1 -0
- package/packages/core/dist/services.js +39 -0
- package/packages/core/dist/services.js.map +1 -0
- package/packages/core/dist/stdio.d.ts +25 -0
- package/packages/core/dist/stdio.d.ts.map +1 -0
- package/packages/core/dist/stdio.js +74 -0
- package/packages/core/dist/stdio.js.map +1 -0
- package/packages/core/package.json +44 -0
- package/packages/core/profiles/default/cordis.yml +35 -0
- package/packages/core/profiles/development/cordis.yml +47 -0
- package/packages/core/src/boot.ts +103 -0
- package/packages/core/src/context.ts +3 -0
- package/packages/core/src/index.ts +6 -0
- package/packages/core/src/plugins/model.ts +12 -0
- package/packages/core/src/plugins/models.ts +32 -0
- package/packages/core/src/plugins/resources.ts +57 -0
- package/packages/core/src/plugins/runtime.ts +73 -0
- package/packages/core/src/plugins/session.ts +27 -0
- package/packages/core/src/plugins/stdio.ts +20 -0
- package/packages/core/src/plugins/tools.ts +23 -0
- package/packages/core/src/profile.ts +31 -0
- package/packages/core/src/runtime.ts +39 -0
- package/packages/core/src/services.ts +105 -0
- package/packages/core/src/stdio.ts +88 -0
- package/packages/core/test/boot.test.ts +86 -0
- package/packages/core/test/profile.test.ts +39 -0
- package/packages/core/test/profiles.integration.test.ts +93 -0
- package/packages/core/test/runtime-fixture.ts +31 -0
- package/packages/core/test/runtime.test.ts +54 -0
- package/packages/core/test/services.test.ts +131 -0
- package/packages/core/test/stdio.test.ts +87 -0
- package/packages/core/tsconfig.build.json +10 -0
- package/packages/core/tsconfig.json +10 -0
- package/packages/host-webserver/dist/index.d.ts +29 -0
- package/packages/host-webserver/dist/index.d.ts.map +1 -0
- package/packages/host-webserver/dist/index.js +73 -0
- package/packages/host-webserver/dist/index.js.map +1 -0
- package/packages/host-webserver/package.json +18 -0
- package/packages/host-webserver/src/index.ts +97 -0
- package/packages/host-webserver/test/index.test.ts +43 -0
- package/packages/host-webserver/tsconfig.build.json +1 -0
- package/packages/host-webserver/tsconfig.json +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Pi Harness
|
|
2
|
+
|
|
3
|
+
Pi Harness is a plugin-first web host for [Pi](https://github.com/earendil-works/pi) built on the published DeepSeek Cordis stack. The browser console, HTTP API, static asset server, models, resources, sessions, tools, runtime, logging, timers, and HMR are Cordis plugins. A CLI surface remains available for scripted and terminal workflows.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js 22.19 or newer
|
|
8
|
+
- npm 10 or newer
|
|
9
|
+
- Provider credentials supported by Pi for real model requests
|
|
10
|
+
|
|
11
|
+
## Run from source
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm ci
|
|
15
|
+
npm run build
|
|
16
|
+
node packages/cli/dist/bin.js --help
|
|
17
|
+
node packages/cli/dist/bin.js "Explain this repository"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Run the web console
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm ci
|
|
24
|
+
npm run web
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The web launcher builds the Vite browser bundle, starts the Cordis host, and prints a local URL (by default `http://127.0.0.1:3080`). Set `PI_HARNESS_HOST`, `PI_HARNESS_PORT`, and `PI_AGENT_DIR` to change the bind address, port, or Pi state directory. The browser surface is served by the `@pi-harness/web-app` plugin and talks to `@pi-harness/api-gateway` over `/api/status`, `/api/session`, `/api/sessions`, `/api/session/new`, `/api/session/open`, `/api/models`, `/api/model`, `/api/files`, `/api/prompt`, `/api/abort`, and the `/api/events` Server-Sent Events stream. The launcher refuses non-loopback hosts unless `PI_HARNESS_ALLOW_REMOTE=1` is explicitly set on a trusted network; the API is intended for local use and has no user authentication layer.
|
|
28
|
+
|
|
29
|
+
The default profile selects `deepseek/deepseek-v4-flash`, stores JSONL sessions under `$PI_AGENT_DIR/sessions`, and loads Pi resources from the current project and agent directory. `PI_AGENT_DIR` defaults to `~/.pi/agent`.
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
web launcher / CLI launcher
|
|
35
|
+
└── Cordis Context
|
|
36
|
+
├── Loader
|
|
37
|
+
└── Include(profile YAML)
|
|
38
|
+
└── Group
|
|
39
|
+
├── models -> piModelRuntime
|
|
40
|
+
├── resources -> piResources + extension providers
|
|
41
|
+
├── model -> piModels
|
|
42
|
+
├── session -> piSession
|
|
43
|
+
├── tools -> piTools
|
|
44
|
+
├── runtime -> piRuntime
|
|
45
|
+
├── webserver -> webServer
|
|
46
|
+
├── api -> HTTP JSON routes
|
|
47
|
+
├── web-app -> static Vite bundle + SPA fallback
|
|
48
|
+
└── stdio -> piApplication
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Cordis owns module loading, configuration validation, dependency injection, activation ordering, lifecycle effects, rollback, grouping, and development HMR. Pi owns model discovery, project resources, session persistence, tool execution, provider calls, and agent events. There is no parallel plugin registry or lifecycle abstraction.
|
|
52
|
+
|
|
53
|
+
## CLI
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
# Built-in production profile
|
|
57
|
+
pih --profile default "Summarize the current directory"
|
|
58
|
+
|
|
59
|
+
# Built-in development profile with logger, timer, and HMR
|
|
60
|
+
pih --profile development "Summarize the current directory"
|
|
61
|
+
|
|
62
|
+
# Project-owned Cordis entry tree
|
|
63
|
+
pih --config ./cordis.yml "Summarize the current directory"
|
|
64
|
+
|
|
65
|
+
# Inspect a profile without importing plugins
|
|
66
|
+
pih --profile default --dump-config
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Launcher options are `--profile`, `--config`, `--dump-config`, `--help`, and `--version`. Remaining arguments are passed unchanged to the active application plugin. The bundled stdio application accepts `--prompt <text>`, a positional prompt, or piped stdin.
|
|
70
|
+
|
|
71
|
+
The built-in development profile watches the invocation working directory and the launcher automatically supervises a child process with Node's `--expose-internals` flag, which Cordis HMR requires. Cordis performs partial plugin reloads in place and requests a supervised process restart when a framework module changes. Production does not expose Node internals. A custom profile that mounts `@deepseek-ai/cordis-plugin-hmr` must start the CLI entry with `node --expose-internals`.
|
|
72
|
+
|
|
73
|
+
## Profiles
|
|
74
|
+
|
|
75
|
+
Profiles are YAML arrays of Cordis Loader entries. Every entry needs a stable `id`, a module `name`, and optional `config`, `inject`, `group`, or `disabled` fields. IDs must be unique across the complete entry tree because Cordis groups share their owning tree's entry store.
|
|
76
|
+
|
|
77
|
+
Bare module specifiers resolve from the directory containing the profile. Keep project profiles in a package that installs every referenced plugin. Relative specifiers resolve from the same directory.
|
|
78
|
+
|
|
79
|
+
Pi Harness reads and hot-refreshes profile files but does not persist Loader mutations back into them. This prevents an activation rollback from rewriting a source profile; edit the YAML directly to make changes.
|
|
80
|
+
|
|
81
|
+
## Author a plugin
|
|
82
|
+
|
|
83
|
+
[`examples/plugin-hello`](./examples/plugin-hello) is a complete external Cordis plugin. It contributes a native Pi `ToolDefinition`, registers cleanup with `ctx.effect()`, and provides a readiness marker after registration:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
export default {
|
|
87
|
+
name: "pi-hello",
|
|
88
|
+
inject: ["piTools"],
|
|
89
|
+
apply(ctx: Context) {
|
|
90
|
+
ctx.effect(() => ctx.piTools.register(helloTool));
|
|
91
|
+
ctx.provide("piHelloTool", helloTool);
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Custom tools are a startup contract. The runtime leases an immutable tool snapshot while its Pi session exists, so a profile must make runtime activation depend on every tool plugin's marker:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
- id: tools
|
|
100
|
+
name: "@pi-harness/core/plugins/tools"
|
|
101
|
+
config:
|
|
102
|
+
names: [read, bash, edit, write]
|
|
103
|
+
- id: hello
|
|
104
|
+
name: "@pi-harness/plugin-hello"
|
|
105
|
+
config: {}
|
|
106
|
+
- id: runtime
|
|
107
|
+
name: "@pi-harness/core/plugins/runtime"
|
|
108
|
+
inject:
|
|
109
|
+
- piHelloTool
|
|
110
|
+
config:
|
|
111
|
+
thinkingLevel: medium
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This uses Cordis injection for deterministic ordering. A late contribution fails startup instead of being silently omitted from the active AgentSession. When HMR unloads a tool marker, Cordis first disposes the dependent runtime and releases its snapshot; the reloaded tool plugin can then register against the same lifecycle-owned registry.
|
|
115
|
+
|
|
116
|
+
## Failure and security boundaries
|
|
117
|
+
|
|
118
|
+
- A profile can load arbitrary Node.js modules. Treat profile files and plugin packages as executable code.
|
|
119
|
+
- Missing modules, invalid configuration, unresolved injections, model lookup failures, and plugin activation failures abort startup and dispose the partial tree.
|
|
120
|
+
- The runtime does not fall back to a different model or storage backend.
|
|
121
|
+
- Signals cancel startup or abort the active Pi run before the Cordis tree is disposed. Runtime abort and root disposal have a five-second deadline, after which the executable forces the signal-compatible exit code.
|
|
122
|
+
- The production profile excludes HMR. Development HMR grants access to Node internal ESM loader APIs only in the relaunched development process.
|
|
123
|
+
- Existing Pi resources and extensions under `PI_AGENT_DIR` participate in startup and shutdown. Use an isolated agent directory for deterministic tests.
|
|
124
|
+
|
|
125
|
+
## Development
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
npm test
|
|
129
|
+
npm run typecheck
|
|
130
|
+
npm run lint
|
|
131
|
+
npm run build
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`npm test` builds every workspace before running Vitest, so Loader integration tests resolve the same package exports shipped to users. Tests use real Cordis contexts and real Pi sessions; deterministic provider fixtures avoid paid network requests.
|
|
135
|
+
|
|
136
|
+
## Release
|
|
137
|
+
|
|
138
|
+
Publishing is triggered by a push to `main` (including a merged pull request), or manually with `workflow_dispatch`. The `Release packages` workflow runs the complete test, lint, and diff gate, publishes the root `pi-harness-workspace` package and six public workspaces to npm with provenance, skips package versions that already exist, and creates a matching GitHub Release tag. The web app and example plugin workspaces are private and are never published.
|
|
139
|
+
|
|
140
|
+
Before the first release, add the npm automation token as the GitHub Actions secret `NPM_TOKEN`. The workflow passes the secret through `NODE_AUTH_TOKEN` and publishes to npm without provenance because this repository is private and npm rejects provenance attestations from private GitHub sources. The token must be allowed to publish the seven package names and, if npm two-factor authentication is enabled, use an automation-compatible publish policy. Bump all published workspace versions together and update their internal `@pi-harness/*` dependency versions before merging to `main`; the merge then publishes and creates the matching GitHub Release automatically.
|
|
141
|
+
|
|
142
|
+
## Workspace layout
|
|
143
|
+
|
|
144
|
+
- `packages/core`: Cordis boot host, typed Pi services, runtime plugins, and built-in profiles
|
|
145
|
+
- `packages/cli`: launcher argument, process, stdio, signal, and development re-exec handling
|
|
146
|
+
- `packages/host-webserver`: Cordis-owned HTTP server and route lifecycle
|
|
147
|
+
- `packages/api-gateway`: Cordis API plugin for status, live sessions, model selection, workspace files, prompts, abort, and SSE events
|
|
148
|
+
- `packages/client-web`: browser-side Cordis plugin tree and console surface
|
|
149
|
+
- `packages/bundle-web-app`: static frontend and SPA fallback plugin
|
|
150
|
+
- `apps/web`: Vite entrypoint and production web launcher
|
|
151
|
+
- `examples/plugin-hello`: lifecycle-safe external Pi tool plugin
|
|
152
|
+
- `docs/plans`: accepted architecture and implementation plan
|