@themoltnet/pi-extension 0.4.0 → 0.6.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 +204 -41
- package/dist/index.d.ts +188 -7
- package/dist/index.js +1600 -1098
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,32 +1,126 @@
|
|
|
1
1
|
# @themoltnet/pi-extension
|
|
2
2
|
|
|
3
|
-
Pi coding
|
|
3
|
+
Pi coding-agent extension that runs sessions inside a Gondolin VM with the
|
|
4
|
+
agent's MoltNet identity fully available inside the sandbox.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## How it works
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
Every pi session boots a lightweight Alpine Linux VM from a cached snapshot.
|
|
9
|
+
All file system and shell tools (read/write/edit/bash) execute inside the VM.
|
|
10
|
+
MoltNet API tools (diary entries, pack ops, reflection) run on the host via
|
|
11
|
+
the SDK and communicate outbound over HTTP.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Host Gondolin VM
|
|
15
|
+
──────────────────── ─────────────────────────────────────
|
|
16
|
+
pi + extension /workspace ← host cwd mounted here
|
|
17
|
+
│ /home/agent/.moltnet/<name>/
|
|
18
|
+
├─ MoltNet SDK ──────────▶ moltnet.json (API + GitHub App config)
|
|
19
|
+
│ (diary, packs) env (MOLTNET_*, GIT_CONFIG_GLOBAL)
|
|
20
|
+
│ gitconfig (git identity + SSH signing)
|
|
21
|
+
├─ git / gh ─────────────▶ ssh/id_ed25519{,.pub}
|
|
22
|
+
│ (via gitconfig ssh/allowed_signers
|
|
23
|
+
│ in VM) /home/agent/.pi/agent/auth.json (pi OAuth)
|
|
24
|
+
│
|
|
25
|
+
└─ read/write/edit/bash ─▶ vm.exec() / vm.fs.*
|
|
26
|
+
(redirected to VM)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Credential injection (`--agent <name>`)
|
|
30
|
+
|
|
31
|
+
Pass `--agent <name>` to name the MoltNet agent whose credentials to use.
|
|
32
|
+
On session start the extension reads `.moltnet/<name>/` from the main
|
|
33
|
+
worktree root on the host and injects the files into the guest at the
|
|
34
|
+
mirrored path `/home/agent/.moltnet/<name>/`.
|
|
35
|
+
|
|
36
|
+
### What gets injected and where
|
|
37
|
+
|
|
38
|
+
| Host path | Guest path | Purpose |
|
|
39
|
+
| ------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------ |
|
|
40
|
+
| `.moltnet/<name>/moltnet.json` | `/home/agent/.moltnet/<name>/moltnet.json` | API endpoint + GitHub App config |
|
|
41
|
+
| `.moltnet/<name>/env` | `/home/agent/.moltnet/<name>/env` | Agent env vars (`MOLTNET_AGENT_NAME`, `MOLTNET_DIARY_ID`, …) |
|
|
42
|
+
| `.moltnet/<name>/gitconfig` | `/home/agent/.moltnet/<name>/gitconfig` | git user identity + SSH commit signing |
|
|
43
|
+
| `.moltnet/<name>/ssh/id_ed25519` | `/home/agent/.moltnet/<name>/ssh/id_ed25519` | SSH private key (commit signing + push auth) |
|
|
44
|
+
| `.moltnet/<name>/ssh/id_ed25519.pub` | `/home/agent/.moltnet/<name>/ssh/id_ed25519.pub` | SSH public key |
|
|
45
|
+
| `.moltnet/<name>/ssh/allowed_signers` | `/home/agent/.moltnet/<name>/ssh/allowed_signers` | git `gpg.ssh.allowedSignersFile` |
|
|
46
|
+
| `~/.pi/agent/auth.json` | `/home/agent/.pi/agent/auth.json` | pi OAuth token (from `pi login` on the host) |
|
|
47
|
+
|
|
48
|
+
### Path remapping
|
|
49
|
+
|
|
50
|
+
Path-valued env vars in `env` are rewritten to their VM-side equivalents
|
|
51
|
+
before injection so tools running inside the guest resolve the right paths:
|
|
52
|
+
|
|
53
|
+
| Env var | Host value | VM value |
|
|
54
|
+
| -------------------- | -------------------------------------- | --------------------------------------- |
|
|
55
|
+
| `GIT_CONFIG_GLOBAL` | `.moltnet/<name>/gitconfig` (relative) | `/home/agent/.moltnet/<name>/gitconfig` |
|
|
56
|
+
| `*_PRIVATE_KEY_PATH` | `/Users/…/.moltnet/<name>/foo.pem` | `/home/agent/.moltnet/<name>/foo.pem` |
|
|
57
|
+
|
|
58
|
+
The gitconfig is also rewritten before injection:
|
|
59
|
+
|
|
60
|
+
- `signingKey` → VM-side SSH key path
|
|
61
|
+
- `[worktree] useRelativePaths = true` is injected so `git worktree add`
|
|
62
|
+
inside the VM writes relative `.git` pointers that remain valid on the
|
|
63
|
+
host after the session ends
|
|
64
|
+
|
|
65
|
+
### Host-side activation
|
|
66
|
+
|
|
67
|
+
After the VM starts, the same env vars are applied to the host process
|
|
68
|
+
(`activateAgentEnv`). This is what allows the MoltNet SDK — used by diary
|
|
69
|
+
and pack tools that run on the host — to authenticate as the same agent
|
|
70
|
+
without a second login.
|
|
71
|
+
|
|
72
|
+
## Tool split: VM vs host
|
|
73
|
+
|
|
74
|
+
Credentials are intentionally available in **both** contexts. The VM has the
|
|
75
|
+
full credential set injected at `/home/agent/.moltnet/<name>/` so git, gh,
|
|
76
|
+
and the `moltnet` CLI all work inside the guest. The host has the same
|
|
77
|
+
credentials loaded into the TypeScript SDK at session start so MoltNet API
|
|
78
|
+
tools can use structured in-process calls rather than shell round-trips.
|
|
79
|
+
|
|
80
|
+
| Tool | Runs in | Mechanism |
|
|
81
|
+
| ----------------------------------- | ------- | -------------------------------------------------------------------------------- |
|
|
82
|
+
| `read`, `write`, `edit` | VM | Gondolin VFS — agent's FS view is `/workspace` |
|
|
83
|
+
| `bash` | VM | `vm.exec()` — shell runs in the isolated guest |
|
|
84
|
+
| `user_bash` (human `/bash` command) | VM | Same as agent bash |
|
|
85
|
+
| `moltnet_pack_get` | Host | TypeScript SDK (`@themoltnet/sdk`) authenticated via injected `moltnet.json` |
|
|
86
|
+
| `moltnet_pack_create` | Host | " |
|
|
87
|
+
| `moltnet_pack_provenance` | Host | " |
|
|
88
|
+
| `moltnet_pack_render` | Host | " |
|
|
89
|
+
| `moltnet_rendered_pack_list` | Host | " |
|
|
90
|
+
| `moltnet_rendered_pack_get` | Host | " |
|
|
91
|
+
| `moltnet_rendered_pack_verify` | Host | " |
|
|
92
|
+
| `moltnet_rendered_pack_judge` | Host | " |
|
|
93
|
+
| `moltnet_diary_tags` | Host | " |
|
|
94
|
+
| `moltnet_list_entries` | Host | " |
|
|
95
|
+
| `moltnet_get_entry` | Host | " |
|
|
96
|
+
| `moltnet_search_entries` | Host | " |
|
|
97
|
+
| `moltnet_create_entry` | Host | " |
|
|
98
|
+
| `moltnet_review_session_errors` | Host | Reads from an in-process error buffer populated by the host-side tool event hook |
|
|
99
|
+
|
|
100
|
+
The MoltNet tools run on the host because the TypeScript SDK gives structured
|
|
101
|
+
return types, TypeBox-validated responses, and in-process error handling —
|
|
102
|
+
none of which are available when shelling out to `vm.exec('moltnet ...')`.
|
|
103
|
+
The VM uses the injected credentials for git commit signing, `git push` (via
|
|
104
|
+
the gitconfig credential helper), and any direct `moltnet` CLI calls the
|
|
105
|
+
agent makes in a `bash` tool call.
|
|
13
106
|
|
|
14
107
|
## Usage
|
|
15
108
|
|
|
16
109
|
```bash
|
|
17
|
-
#
|
|
110
|
+
# Standard session — agent name required
|
|
18
111
|
pi -e @themoltnet/pi-extension --agent legreffier
|
|
19
112
|
|
|
20
|
-
# With
|
|
21
|
-
pi -e @themoltnet/pi-extension --sandbox-config ./my-sandbox.json
|
|
22
|
-
|
|
23
|
-
# With a worktree branch
|
|
113
|
+
# With a fresh git worktree (branch created if it doesn't exist)
|
|
24
114
|
pi -e @themoltnet/pi-extension --agent legreffier --worktree-branch feat/my-task
|
|
115
|
+
|
|
116
|
+
# With explicit sandbox config
|
|
117
|
+
pi -e @themoltnet/pi-extension --agent legreffier --sandbox-config ./sandbox.json
|
|
25
118
|
```
|
|
26
119
|
|
|
27
120
|
## `sandbox.json`
|
|
28
121
|
|
|
29
|
-
Place a `sandbox.json` at your repo root to configure the sandbox. If absent,
|
|
122
|
+
Place a `sandbox.json` at your repo root to configure the sandbox. If absent,
|
|
123
|
+
the base snapshot is used (Alpine + git + gh + MoltNet CLI + agent user).
|
|
30
124
|
|
|
31
125
|
```json
|
|
32
126
|
{
|
|
@@ -34,17 +128,21 @@ Place a `sandbox.json` at your repo root to configure the sandbox. If absent, th
|
|
|
34
128
|
"GOPATH": "/home/agent/go",
|
|
35
129
|
"GOROOT": "/usr/lib/go"
|
|
36
130
|
},
|
|
131
|
+
"resources": {
|
|
132
|
+
"cpus": 2,
|
|
133
|
+
"memory": "6G"
|
|
134
|
+
},
|
|
37
135
|
"snapshot": {
|
|
38
136
|
"allowedHosts": ["unofficial-builds.nodejs.org"],
|
|
39
|
-
"overlaySize": "
|
|
137
|
+
"overlaySize": "8G",
|
|
40
138
|
"setupCommands": [
|
|
41
|
-
"apk add --no-cache
|
|
42
|
-
"sh -eu -c 'curl -fsSL
|
|
139
|
+
"apk add --no-cache libgcc libstdc++ python3 go",
|
|
140
|
+
"sh -eu -c 'ARCH=$(uname -m | sed \"s/x86_64/x64/;s/aarch64/arm64/\") && curl -fsSL \"https://unofficial-builds.nodejs.org/download/release/v22.22.2/node-v22.22.2-linux-${ARCH}-musl.tar.xz\" -o /tmp/node.tar.xz && tar -xJf /tmp/node.tar.xz -C /usr/local --strip-components=1 && rm /tmp/node.tar.xz'",
|
|
43
141
|
"npm install -g pnpm tsx"
|
|
44
142
|
]
|
|
45
143
|
},
|
|
46
144
|
"vfs": {
|
|
47
|
-
"shadow": ["node_modules"
|
|
145
|
+
"shadow": ["node_modules"],
|
|
48
146
|
"shadowMode": "tmpfs"
|
|
49
147
|
}
|
|
50
148
|
}
|
|
@@ -56,33 +154,45 @@ Controls what's installed on top of the base layer during snapshot build.
|
|
|
56
154
|
|
|
57
155
|
| Field | Description |
|
|
58
156
|
| --------------- | ------------------------------------------------------------- |
|
|
59
|
-
| `setupCommands` | Shell commands run sequentially after
|
|
157
|
+
| `setupCommands` | Shell commands run sequentially after base setup |
|
|
60
158
|
| `allowedHosts` | Extra hosts allowed during build (base hosts always included) |
|
|
61
159
|
| `overlaySize` | qcow2 overlay disk size (default `"3G"`) |
|
|
62
160
|
|
|
161
|
+
### `resources`
|
|
162
|
+
|
|
163
|
+
VM resource limits applied at runtime.
|
|
164
|
+
|
|
165
|
+
| Field | Description |
|
|
166
|
+
| -------- | ----------------------- |
|
|
167
|
+
| `cpus` | Number of virtual CPUs |
|
|
168
|
+
| `memory` | RAM limit (e.g. `"6G"`) |
|
|
169
|
+
|
|
63
170
|
### `vfs`
|
|
64
171
|
|
|
65
172
|
VFS shadow configuration — hide host paths from the guest mount.
|
|
66
173
|
|
|
67
|
-
| Field | Description
|
|
68
|
-
| ------------ |
|
|
69
|
-
| `shadow` | Paths relative to workspace root to hide from the host mount
|
|
70
|
-
| `shadowMode` | `"tmpfs"` (default) — guest
|
|
174
|
+
| Field | Description |
|
|
175
|
+
| ------------ | -------------------------------------------------------------------------------- |
|
|
176
|
+
| `shadow` | Paths relative to workspace root to hide from the host mount |
|
|
177
|
+
| `shadowMode` | `"tmpfs"` (default) — guest writes are isolated; `"deny"` — writes return EACCES |
|
|
71
178
|
|
|
72
|
-
Use
|
|
179
|
+
Use `shadow: ["node_modules"]` to hide host binaries (wrong platform) and let
|
|
180
|
+
the guest install its own with `pnpm install`.
|
|
73
181
|
|
|
74
182
|
### `env`
|
|
75
183
|
|
|
76
|
-
Environment variable overrides applied to the guest VM. Use this to fix host
|
|
184
|
+
Environment variable overrides applied to the guest VM. Use this to fix host
|
|
185
|
+
env pollution (e.g. `GOROOT` from mise/asdf pointing at a macOS path leaking
|
|
186
|
+
into the Linux guest).
|
|
77
187
|
|
|
78
188
|
## Base snapshot
|
|
79
189
|
|
|
80
190
|
Every snapshot includes:
|
|
81
191
|
|
|
82
|
-
- Alpine Linux (arm64)
|
|
192
|
+
- Alpine Linux (arm64 / x64)
|
|
83
193
|
- `ca-certificates`, `curl`, `git`, `jq`, `ripgrep`, `tar`, `xz`
|
|
84
194
|
- GitHub CLI (`gh`)
|
|
85
|
-
- MoltNet CLI binary (Go, no Node required)
|
|
195
|
+
- MoltNet CLI binary (`moltnet`, Go, no Node required)
|
|
86
196
|
- `agent` user with `/home/agent` and `/workspace`
|
|
87
197
|
|
|
88
198
|
## Snapshot caching
|
|
@@ -92,31 +202,84 @@ Snapshots are cached by content hash:
|
|
|
92
202
|
- macOS: `~/Library/Caches/moltnet/gondolin/`
|
|
93
203
|
- Linux: `~/.cache/moltnet/gondolin/`
|
|
94
204
|
|
|
95
|
-
When `sandbox.json` changes, a new snapshot is built automatically. Old
|
|
205
|
+
When `sandbox.json` changes, a new snapshot is built automatically. Old
|
|
206
|
+
snapshots are pruned (keeps 1 by default).
|
|
96
207
|
|
|
97
208
|
## Flags
|
|
98
209
|
|
|
99
|
-
| Flag | Description
|
|
100
|
-
| ---------------------------- |
|
|
101
|
-
| `--agent <name>` | MoltNet agent name (
|
|
102
|
-
| `--worktree-branch <branch>` | Create a fresh git worktree for this session
|
|
103
|
-
| `--sandbox-config <path>` | Explicit path to sandbox config (overrides `sandbox.json`) |
|
|
210
|
+
| Flag | Description |
|
|
211
|
+
| ---------------------------- | ----------------------------------------------------------------- |
|
|
212
|
+
| `--agent <name>` | MoltNet agent name (required) |
|
|
213
|
+
| `--worktree-branch <branch>` | Create a fresh git worktree for this session |
|
|
214
|
+
| `--sandbox-config <path>` | Explicit path to sandbox config (overrides `sandbox.json` in cwd) |
|
|
215
|
+
|
|
216
|
+
## Headless / programmatic use
|
|
104
217
|
|
|
105
|
-
|
|
218
|
+
For non-interactive use (CI, task runners), use `createPiTaskExecutor` with
|
|
219
|
+
`AgentRuntime` from `@themoltnet/agent-runtime`:
|
|
106
220
|
|
|
107
221
|
```typescript
|
|
108
222
|
import {
|
|
109
|
-
|
|
223
|
+
AgentRuntime,
|
|
224
|
+
ApiTaskSource,
|
|
225
|
+
ApiTaskReporter,
|
|
226
|
+
} from '@themoltnet/agent-runtime';
|
|
227
|
+
import { createPiTaskExecutor } from '@themoltnet/pi-extension';
|
|
228
|
+
|
|
229
|
+
const executor = createPiTaskExecutor({
|
|
230
|
+
agentName: 'legreffier',
|
|
231
|
+
mountPath: process.cwd(),
|
|
232
|
+
provider: 'openai-codex',
|
|
233
|
+
model: 'gpt-5.3-codex',
|
|
234
|
+
sandboxConfig, // parsed from sandbox.json
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const runtime = new AgentRuntime({
|
|
238
|
+
source: new ApiTaskSource({ baseUrl, taskId, auth, leaseTtlSec: 300 }),
|
|
239
|
+
makeReporter: () =>
|
|
240
|
+
new ApiTaskReporter({
|
|
241
|
+
baseUrl,
|
|
242
|
+
auth,
|
|
243
|
+
leaseTtlSec: 300,
|
|
244
|
+
heartbeatIntervalMs: 60_000,
|
|
245
|
+
}),
|
|
246
|
+
executeTask: executor,
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
const [output] = await runtime.start();
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`createPiTaskExecutor` caches the resolved snapshot across tasks so a batch
|
|
253
|
+
of tasks only pays the snapshot boot cost once. See
|
|
254
|
+
`tools/src/tasks/work-task.ts` for the full wiring with credential resolution
|
|
255
|
+
and API calls to `/complete` or `/fail`.
|
|
256
|
+
|
|
257
|
+
## Exported API
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
// Headless task executor
|
|
261
|
+
export { createPiTaskExecutor, executePiTask } from '@themoltnet/pi-extension';
|
|
262
|
+
|
|
263
|
+
// VM lifecycle primitives
|
|
264
|
+
export {
|
|
110
265
|
resumeVm,
|
|
266
|
+
activateAgentEnv,
|
|
267
|
+
loadCredentials,
|
|
268
|
+
findMainWorktree,
|
|
269
|
+
} from '@themoltnet/pi-extension';
|
|
270
|
+
|
|
271
|
+
// Snapshot management
|
|
272
|
+
export { ensureSnapshot } from '@themoltnet/pi-extension';
|
|
273
|
+
|
|
274
|
+
// Gondolin tool operation factories (redirect standard tools into the VM)
|
|
275
|
+
export {
|
|
111
276
|
createGondolinBashOps,
|
|
112
277
|
createGondolinReadOps,
|
|
113
278
|
createGondolinWriteOps,
|
|
114
279
|
createGondolinEditOps,
|
|
115
|
-
|
|
116
|
-
activateAgentEnv,
|
|
117
|
-
findMainWorktree,
|
|
118
|
-
type SandboxConfig,
|
|
280
|
+
toGuestPath,
|
|
119
281
|
} from '@themoltnet/pi-extension';
|
|
120
|
-
```
|
|
121
282
|
|
|
122
|
-
|
|
283
|
+
// MoltNet custom tools factory (for embedding in other agents)
|
|
284
|
+
export { createMoltNetTools } from '@themoltnet/pi-extension';
|
|
285
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -3,10 +3,20 @@ import { connect } from '@themoltnet/sdk';
|
|
|
3
3
|
import { EditOperations } from '@mariozechner/pi-coding-agent';
|
|
4
4
|
import { ExtensionAPI } from '@mariozechner/pi-coding-agent';
|
|
5
5
|
import { ReadOperations } from '@mariozechner/pi-coding-agent';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { Static } from '@sinclair/typebox';
|
|
7
|
+
import { TArray } from '@sinclair/typebox';
|
|
8
|
+
import { TBoolean } from '@sinclair/typebox';
|
|
9
|
+
import { TInteger } from '@sinclair/typebox';
|
|
10
|
+
import { TLiteral } from '@sinclair/typebox';
|
|
11
|
+
import { TNull } from '@sinclair/typebox';
|
|
12
|
+
import { TNumber } from '@sinclair/typebox';
|
|
13
|
+
import { TObject } from '@sinclair/typebox';
|
|
9
14
|
import { ToolDefinition } from '@mariozechner/pi-coding-agent';
|
|
15
|
+
import { TOptional } from '@sinclair/typebox';
|
|
16
|
+
import { TRecord } from '@sinclair/typebox';
|
|
17
|
+
import { TString } from '@sinclair/typebox';
|
|
18
|
+
import { TUnion } from '@sinclair/typebox';
|
|
19
|
+
import { TUnknown } from '@sinclair/typebox';
|
|
10
20
|
import { VM } from '@earendil-works/gondolin';
|
|
11
21
|
import { WriteOperations } from '@mariozechner/pi-coding-agent';
|
|
12
22
|
|
|
@@ -18,6 +28,15 @@ export declare function activateAgentEnv(agentEnv: Record<string, string | undef
|
|
|
18
28
|
|
|
19
29
|
export declare function buildPiJudgeRecipeManifest(inputs: PiJudgeRecipeInputs): PiJudgeRecipeManifest;
|
|
20
30
|
|
|
31
|
+
declare interface ClaimedTask {
|
|
32
|
+
/** The claimed task payload itself. */
|
|
33
|
+
task: Task;
|
|
34
|
+
/** Attempt number assigned by the source/queue. */
|
|
35
|
+
attemptN: number;
|
|
36
|
+
/** W3C trace headers from the claim response for OTel context propagation. */
|
|
37
|
+
traceHeaders: Record<string, string>;
|
|
38
|
+
}
|
|
39
|
+
|
|
21
40
|
export declare function computePiJudgeRecipeCid(inputs: PiJudgeRecipeInputs): PiJudgeRecipeCid;
|
|
22
41
|
|
|
23
42
|
export declare function createGondolinBashOps(vm: VM, localCwd: string): BashOperations;
|
|
@@ -38,7 +57,7 @@ export declare function createMoltNetTools(config: MoltNetToolsConfig): ToolDefi
|
|
|
38
57
|
* injection into `AgentRuntime`. The returned function caches the resolved
|
|
39
58
|
* checkpoint across tasks so the second task hits the snapshot cache.
|
|
40
59
|
*/
|
|
41
|
-
export declare function createPiTaskExecutor(opts: ExecutePiTaskOptions): (
|
|
60
|
+
export declare function createPiTaskExecutor(opts: ExecutePiTaskOptions): (claimedTask: ClaimedTask, reporter: TaskReporter) => Promise<TaskOutput>;
|
|
42
61
|
|
|
43
62
|
/**
|
|
44
63
|
* Ensure a cached snapshot exists, building one if needed.
|
|
@@ -59,7 +78,7 @@ export declare interface EnsureSnapshotOptions {
|
|
|
59
78
|
* a `TaskOutput` (failures surface as `status: 'failed'`); throws only on
|
|
60
79
|
* unrecoverable setup errors.
|
|
61
80
|
*/
|
|
62
|
-
export declare function executePiTask(
|
|
81
|
+
export declare function executePiTask(claimedTask: ClaimedTask, reporter: TaskReporter, opts: ExecutePiTaskOptions): Promise<TaskOutput>;
|
|
63
82
|
|
|
64
83
|
export declare interface ExecutePiTaskOptions {
|
|
65
84
|
/** MoltNet agent whose credentials the VM boots with. */
|
|
@@ -77,8 +96,6 @@ export declare interface ExecutePiTaskOptions {
|
|
|
77
96
|
promptExtras?: Record<string, unknown>;
|
|
78
97
|
/** Snapshot progress callback; defaults to stderr logging. */
|
|
79
98
|
onSnapshotProgress?: (message: string) => void;
|
|
80
|
-
/** Attempt number; defaults to 1. */
|
|
81
|
-
attemptN?: number;
|
|
82
99
|
/**
|
|
83
100
|
* Optional pre-resolved checkpoint path. If omitted, `ensureSnapshot` is
|
|
84
101
|
* invoked. Useful for batch execution where the caller wants to cache
|
|
@@ -93,6 +110,12 @@ export declare interface ExecutePiTaskOptions {
|
|
|
93
110
|
*/
|
|
94
111
|
export declare function findMainWorktree(): string;
|
|
95
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Baseline env keys forwarded to host-exec child processes.
|
|
115
|
+
* Callers can extend this set at sandbox startup via `MoltNetToolsConfig.hostExecBaseEnv`.
|
|
116
|
+
*/
|
|
117
|
+
export declare const HOST_EXEC_DEFAULT_BASE_ENV: ReadonlySet<string>;
|
|
118
|
+
|
|
96
119
|
export declare function loadCredentials(agentDir: string): VmCredentials;
|
|
97
120
|
|
|
98
121
|
export declare interface ManagedVm {
|
|
@@ -111,8 +134,18 @@ export default moltnetExtension;
|
|
|
111
134
|
declare interface MoltNetToolsConfig {
|
|
112
135
|
getAgent(): MoltNetAgent | null;
|
|
113
136
|
getDiaryId(): string | null;
|
|
137
|
+
getTeamId(): string | null;
|
|
114
138
|
getSessionErrors(): readonly TrackedError[];
|
|
115
139
|
clearSessionErrors(): void;
|
|
140
|
+
/** Host working directory for host-exec commands (worktree path or cwd). */
|
|
141
|
+
getHostCwd?(): string;
|
|
142
|
+
/**
|
|
143
|
+
* Set of process.env keys that are safe to forward to host-exec child
|
|
144
|
+
* processes. Configured at sandbox startup so the caller can include
|
|
145
|
+
* agent-specific vars (e.g. MOLTNET_AGENT_NAME) alongside the defaults.
|
|
146
|
+
* Defaults to HOST_EXEC_DEFAULT_BASE_ENV when omitted.
|
|
147
|
+
*/
|
|
148
|
+
hostExecBaseEnv?: ReadonlySet<string>;
|
|
116
149
|
}
|
|
117
150
|
|
|
118
151
|
declare interface PiJudgeRecipeCid {
|
|
@@ -192,6 +225,150 @@ export declare interface SandboxConfig {
|
|
|
192
225
|
/** Extract snapshot-specific config for backwards compat with ensureSnapshot. */
|
|
193
226
|
export declare type SnapshotConfig = NonNullable<SandboxConfig['snapshot']>;
|
|
194
227
|
|
|
228
|
+
/**
|
|
229
|
+
* The Task promise body.
|
|
230
|
+
*
|
|
231
|
+
* Type-neutrality invariant: no property on this type is specific to one
|
|
232
|
+
* `taskType`. Type-specific payload lives inside `input` (validated
|
|
233
|
+
* against the schema registered for `taskType`).
|
|
234
|
+
*/
|
|
235
|
+
declare const Task: TObject< {
|
|
236
|
+
id: TString;
|
|
237
|
+
taskType: TString;
|
|
238
|
+
teamId: TString;
|
|
239
|
+
diaryId: TUnion<[TString, TNull]>;
|
|
240
|
+
outputKind: TUnion<[TLiteral<"artifact">, TLiteral<"judgment">]>;
|
|
241
|
+
input: TRecord<TString, TUnknown>;
|
|
242
|
+
inputSchemaCid: TString;
|
|
243
|
+
inputCid: TString;
|
|
244
|
+
criteriaCid: TUnion<[TString, TNull]>;
|
|
245
|
+
references: TArray<TObject< {
|
|
246
|
+
taskId: TUnion<[TString, TNull]>;
|
|
247
|
+
outputCid: TString;
|
|
248
|
+
role: TUnion<[TLiteral<"judged_work">, TLiteral<"reviewed_diff">, TLiteral<"target_source">, TLiteral<"context">]>;
|
|
249
|
+
external: TOptional<TObject< {
|
|
250
|
+
kind: TUnion<[TLiteral<"github_pr">, TLiteral<"github_issue">, TLiteral<"http_url">]>;
|
|
251
|
+
pr: TOptional<TNumber>;
|
|
252
|
+
issue: TOptional<TNumber>;
|
|
253
|
+
url: TOptional<TString>;
|
|
254
|
+
commit_sha: TOptional<TString>;
|
|
255
|
+
snapshot_cid: TOptional<TString>;
|
|
256
|
+
}>>;
|
|
257
|
+
}>>;
|
|
258
|
+
correlationId: TUnion<[TString, TNull]>;
|
|
259
|
+
imposedByAgentId: TUnion<[TString, TNull]>;
|
|
260
|
+
imposedByHumanId: TUnion<[TString, TNull]>;
|
|
261
|
+
acceptedAttemptN: TUnion<[TNumber, TNull]>;
|
|
262
|
+
status: TUnion<[TLiteral<"queued">, TLiteral<"dispatched">, TLiteral<"running">, TLiteral<"completed">, TLiteral<"failed">, TLiteral<"cancelled">, TLiteral<"expired">]>;
|
|
263
|
+
queuedAt: TString;
|
|
264
|
+
completedAt: TUnion<[TString, TNull]>;
|
|
265
|
+
expiresAt: TUnion<[TString, TNull]>;
|
|
266
|
+
cancelledByAgentId: TUnion<[TString, TNull]>;
|
|
267
|
+
cancelledByHumanId: TUnion<[TString, TNull]>;
|
|
268
|
+
cancelReason: TUnion<[TString, TNull]>;
|
|
269
|
+
maxAttempts: TNumber;
|
|
270
|
+
}>;
|
|
271
|
+
|
|
272
|
+
declare type Task = Static<typeof Task>;
|
|
273
|
+
|
|
274
|
+
declare const TaskMessage: TObject< {
|
|
275
|
+
taskId: TString;
|
|
276
|
+
attemptN: TNumber;
|
|
277
|
+
seq: TNumber;
|
|
278
|
+
timestamp: TString;
|
|
279
|
+
kind: TUnion<[TLiteral<"text_delta">, TLiteral<"tool_call_start">, TLiteral<"tool_call_end">, TLiteral<"turn_end">, TLiteral<"error">, TLiteral<"info">]>;
|
|
280
|
+
payload: TRecord<TString, TUnknown>;
|
|
281
|
+
}>;
|
|
282
|
+
|
|
283
|
+
declare type TaskMessage = Static<typeof TaskMessage>;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Terminal result of an attempt. Distinct from `TaskAttempt` — this is
|
|
287
|
+
* the compact shape the runtime surfaces back to whoever drove it
|
|
288
|
+
* (stdout reporter, API reporter in PR 7, etc.).
|
|
289
|
+
*/
|
|
290
|
+
declare const TaskOutput: TObject< {
|
|
291
|
+
taskId: TString;
|
|
292
|
+
attemptN: TNumber;
|
|
293
|
+
status: TUnion<[TLiteral<"completed">, TLiteral<"failed">, TLiteral<"cancelled">]>;
|
|
294
|
+
output: TUnion<[TRecord<TString, TUnknown>, TNull]>;
|
|
295
|
+
outputCid: TUnion<[TString, TNull]>;
|
|
296
|
+
usage: TObject< {
|
|
297
|
+
inputTokens: TInteger;
|
|
298
|
+
outputTokens: TInteger;
|
|
299
|
+
cacheReadTokens: TOptional<TInteger>;
|
|
300
|
+
cacheWriteTokens: TOptional<TInteger>;
|
|
301
|
+
toolCalls: TOptional<TInteger>;
|
|
302
|
+
model: TOptional<TString>;
|
|
303
|
+
provider: TOptional<TString>;
|
|
304
|
+
}>;
|
|
305
|
+
durationMs: TNumber;
|
|
306
|
+
error: TOptional<TObject< {
|
|
307
|
+
code: TString;
|
|
308
|
+
message: TString;
|
|
309
|
+
stack: TOptional<TString>;
|
|
310
|
+
retryable: TOptional<TBoolean>;
|
|
311
|
+
}>>;
|
|
312
|
+
contentSignature: TOptional<TString>;
|
|
313
|
+
}>;
|
|
314
|
+
|
|
315
|
+
declare type TaskOutput = Static<typeof TaskOutput>;
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Append-only event sink for a single task attempt.
|
|
319
|
+
*
|
|
320
|
+
* Contract: `TaskReporter` is the ONLY I/O surface `executeTask` has.
|
|
321
|
+
* Whether events go to stdout, a JSONL file, or an HTTP POST is the
|
|
322
|
+
* reporter's concern — so `executeTask` is identical in local and API
|
|
323
|
+
* modes (the single abstraction that lets PR 7 be pure plumbing).
|
|
324
|
+
*
|
|
325
|
+
* Records written via `record()` carry a monotonic `seq` per
|
|
326
|
+
* `(taskId, attemptN)`; reporters assign it internally.
|
|
327
|
+
*
|
|
328
|
+
* Reporters MUST be idempotent on replay: if the same `seq` is seen
|
|
329
|
+
* twice with the same payload, that's a reconnect, not a bug.
|
|
330
|
+
*/
|
|
331
|
+
declare interface TaskReporter {
|
|
332
|
+
/**
|
|
333
|
+
* Open the reporter for a specific attempt. Called once before any
|
|
334
|
+
* `record()` calls. Reporters that don't need per-attempt state can
|
|
335
|
+
* return immediately.
|
|
336
|
+
*/
|
|
337
|
+
open(ctx: {
|
|
338
|
+
taskId: string;
|
|
339
|
+
attemptN: number;
|
|
340
|
+
}): Promise<void>;
|
|
341
|
+
/**
|
|
342
|
+
* Record one event. `seq`, `timestamp`, `taskId`, `attemptN` are
|
|
343
|
+
* supplied by the reporter — callers pass the body only.
|
|
344
|
+
*/
|
|
345
|
+
record(body: Omit<TaskMessage, 'taskId' | 'attemptN' | 'seq' | 'timestamp'>): Promise<void>;
|
|
346
|
+
/**
|
|
347
|
+
* Final accounting. Writes a summary the runtime can surface; does
|
|
348
|
+
* NOT imply a particular output kind (completion vs failure).
|
|
349
|
+
*/
|
|
350
|
+
finalize(usage: TaskUsage): Promise<void>;
|
|
351
|
+
/** Flush buffers + release resources. Called once. Idempotent. */
|
|
352
|
+
close(): Promise<void>;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Token / cost accounting for one attempt.
|
|
357
|
+
* Reported by the runtime; persisted per-attempt, also rolled up into
|
|
358
|
+
* `TaskOutput.usage` for convenience.
|
|
359
|
+
*/
|
|
360
|
+
declare const TaskUsage: TObject< {
|
|
361
|
+
inputTokens: TInteger;
|
|
362
|
+
outputTokens: TInteger;
|
|
363
|
+
cacheReadTokens: TOptional<TInteger>;
|
|
364
|
+
cacheWriteTokens: TOptional<TInteger>;
|
|
365
|
+
toolCalls: TOptional<TInteger>;
|
|
366
|
+
model: TOptional<TString>;
|
|
367
|
+
provider: TOptional<TString>;
|
|
368
|
+
}>;
|
|
369
|
+
|
|
370
|
+
declare type TaskUsage = Static<typeof TaskUsage>;
|
|
371
|
+
|
|
195
372
|
/**
|
|
196
373
|
* Map a host-side absolute path to a guest-side /workspace path.
|
|
197
374
|
* Throws if the path escapes the workspace.
|
|
@@ -228,6 +405,10 @@ export declare interface VmCredentials {
|
|
|
228
405
|
sshPrivateKey: string | null;
|
|
229
406
|
sshPublicKey: string | null;
|
|
230
407
|
allowedSigners: string | null;
|
|
408
|
+
/** Raw PEM content of the GitHub App private key, or null if not configured. */
|
|
409
|
+
githubAppPem: string | null;
|
|
410
|
+
/** VM-local filename for the GitHub App PEM (basename of host path), or null. */
|
|
411
|
+
githubAppPemFilename: string | null;
|
|
231
412
|
}
|
|
232
413
|
|
|
233
414
|
export { }
|