@cleocode/cleo-os 2026.4.100 → 2026.4.101
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/dist/harnesses/index.d.ts +62 -0
- package/dist/harnesses/index.d.ts.map +1 -0
- package/dist/harnesses/index.js +72 -0
- package/dist/harnesses/index.js.map +1 -0
- package/dist/harnesses/pi-coding-agent/adapter.d.ts +132 -0
- package/dist/harnesses/pi-coding-agent/adapter.d.ts.map +1 -0
- package/dist/harnesses/pi-coding-agent/adapter.js +265 -0
- package/dist/harnesses/pi-coding-agent/adapter.js.map +1 -0
- package/dist/harnesses/pi-coding-agent/docker-mode.d.ts +179 -0
- package/dist/harnesses/pi-coding-agent/docker-mode.d.ts.map +1 -0
- package/dist/harnesses/pi-coding-agent/docker-mode.js +241 -0
- package/dist/harnesses/pi-coding-agent/docker-mode.js.map +1 -0
- package/dist/harnesses/pi-coding-agent/index.d.ts +13 -0
- package/dist/harnesses/pi-coding-agent/index.d.ts.map +1 -0
- package/dist/harnesses/pi-coding-agent/index.js +12 -0
- package/dist/harnesses/pi-coding-agent/index.js.map +1 -0
- package/dist/harnesses/pi-coding-agent/pi-wrapper.d.ts +178 -0
- package/dist/harnesses/pi-coding-agent/pi-wrapper.d.ts.map +1 -0
- package/dist/harnesses/pi-coding-agent/pi-wrapper.js +359 -0
- package/dist/harnesses/pi-coding-agent/pi-wrapper.js.map +1 -0
- package/dist/harnesses/pi-coding-agent/types.d.ts +185 -0
- package/dist/harnesses/pi-coding-agent/types.d.ts.map +1 -0
- package/dist/harnesses/pi-coding-agent/types.js +20 -0
- package/dist/harnesses/pi-coding-agent/types.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pi binary wrapper — low-level launcher for the Pi coding agent CLI.
|
|
3
|
+
*
|
|
4
|
+
* Handles prompt delivery, process spawning, stdin/stdout/stderr wiring,
|
|
5
|
+
* and SIGTERM-then-SIGKILL cleanup. This module is the only place in
|
|
6
|
+
* cleo-os that touches `child_process.spawn` directly for Pi.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* Pi receives its prompt via **file mode**: the prompt text is written to a
|
|
10
|
+
* temporary file under `/tmp/` and passed as a positional CLI argument
|
|
11
|
+
* (`pi <file>`). This mirrors the pattern used by `PiSpawnProvider` in
|
|
12
|
+
* `packages/adapters/` and avoids stdin complexity for non-interactive runs.
|
|
13
|
+
*
|
|
14
|
+
* CleoOS extension injection follows the same mechanism as `cli.ts`: each
|
|
15
|
+
* discovered extension is prepended as `--extension <path>` so Pi loads
|
|
16
|
+
* bridges (CANT bridge, hooks bridge, etc.) even in non-interactive mode.
|
|
17
|
+
*
|
|
18
|
+
* Environment variable overrides (all optional):
|
|
19
|
+
* - `CLEO_PI_BINARY` — path to the `pi` binary (default: `pi` from PATH)
|
|
20
|
+
* - `CLEO_TERMINATE_GRACE_MS` — SIGTERM grace window in ms (default: `5000`)
|
|
21
|
+
* - `CLEO_HARNESS_OUTPUT_BUFFER` — ring buffer capacity per process (default: `500`)
|
|
22
|
+
*
|
|
23
|
+
* OpenClaw patterns adopted:
|
|
24
|
+
* - Extension injection via `--extension <path>` flags.
|
|
25
|
+
* - Prompt written to `/tmp/` with a unique suffix; cleaned up on exit.
|
|
26
|
+
* - `PI_TELEMETRY=0` injected by default to suppress telemetry in CI.
|
|
27
|
+
*
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
*/
|
|
30
|
+
import { spawn } from 'node:child_process';
|
|
31
|
+
import { existsSync } from 'node:fs';
|
|
32
|
+
import { unlink, writeFile } from 'node:fs/promises';
|
|
33
|
+
import { dirname, join } from 'node:path';
|
|
34
|
+
import { fileURLToPath } from 'node:url';
|
|
35
|
+
/** Maximum number of output lines retained in the ring buffer per process. */
|
|
36
|
+
const DEFAULT_OUTPUT_BUFFER_SIZE = 500;
|
|
37
|
+
/** Default SIGTERM → SIGKILL grace window in milliseconds. */
|
|
38
|
+
const DEFAULT_TERMINATE_GRACE_MS = 5000;
|
|
39
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Environment helpers
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the `pi` binary path.
|
|
45
|
+
*
|
|
46
|
+
* Honours `CLEO_PI_BINARY` env var when set (absolute path or bare name),
|
|
47
|
+
* otherwise defaults to `pi` (expects the binary on PATH).
|
|
48
|
+
*
|
|
49
|
+
* @returns Resolved binary path string.
|
|
50
|
+
*
|
|
51
|
+
* @public
|
|
52
|
+
*/
|
|
53
|
+
export function getPiBinaryPath() {
|
|
54
|
+
return process.env['CLEO_PI_BINARY'] ?? 'pi';
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Return the SIGTERM grace window in milliseconds.
|
|
58
|
+
*
|
|
59
|
+
* Reads `CLEO_TERMINATE_GRACE_MS` from the environment; falls back to
|
|
60
|
+
* {@link DEFAULT_TERMINATE_GRACE_MS} when absent or non-positive.
|
|
61
|
+
*
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
export function getTerminateGraceMs() {
|
|
65
|
+
const raw = process.env['CLEO_TERMINATE_GRACE_MS'];
|
|
66
|
+
if (raw !== undefined) {
|
|
67
|
+
const n = Number.parseInt(raw, 10);
|
|
68
|
+
if (Number.isFinite(n) && n > 0)
|
|
69
|
+
return n;
|
|
70
|
+
}
|
|
71
|
+
return DEFAULT_TERMINATE_GRACE_MS;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Return the output ring buffer capacity.
|
|
75
|
+
*
|
|
76
|
+
* Reads `CLEO_HARNESS_OUTPUT_BUFFER` from the environment; falls back to
|
|
77
|
+
* {@link DEFAULT_OUTPUT_BUFFER_SIZE} when absent or non-positive.
|
|
78
|
+
*
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
export function getOutputBufferSize() {
|
|
82
|
+
const raw = process.env['CLEO_HARNESS_OUTPUT_BUFFER'];
|
|
83
|
+
if (raw !== undefined) {
|
|
84
|
+
const n = Number.parseInt(raw, 10);
|
|
85
|
+
if (Number.isFinite(n) && n > 0)
|
|
86
|
+
return n;
|
|
87
|
+
}
|
|
88
|
+
return DEFAULT_OUTPUT_BUFFER_SIZE;
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Extension path resolution
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
/**
|
|
94
|
+
* Collect CleoOS extension paths that exist on disk.
|
|
95
|
+
*
|
|
96
|
+
* Resolves the standard extension list relative to the compiled package root
|
|
97
|
+
* (`extensions/` directory adjacent to `dist/`). Only paths that exist on
|
|
98
|
+
* disk are returned — missing extensions are skipped silently so the adapter
|
|
99
|
+
* degrades gracefully when extensions are not installed.
|
|
100
|
+
*
|
|
101
|
+
* Mirrors `collectExtensionPaths()` in `cli.ts` but does not depend on
|
|
102
|
+
* `@cleocode/core` to keep this module free of external package imports.
|
|
103
|
+
*
|
|
104
|
+
* @returns Array of absolute `.js` extension paths.
|
|
105
|
+
*
|
|
106
|
+
* @public
|
|
107
|
+
*/
|
|
108
|
+
export function resolveExtensionPaths() {
|
|
109
|
+
// Compiled path: dist/harnesses/pi-coding-agent/ → walk up to dist/ → package root
|
|
110
|
+
const packageRoot = join(__dirname, '..', '..', '..');
|
|
111
|
+
const extensionsDir = join(packageRoot, 'extensions');
|
|
112
|
+
const candidates = [
|
|
113
|
+
'cleo-startup.js',
|
|
114
|
+
'cleo-cant-bridge.js',
|
|
115
|
+
'cleo-hooks-bridge.js',
|
|
116
|
+
'cleo-chatroom.js',
|
|
117
|
+
'cleo-agent-monitor.js',
|
|
118
|
+
];
|
|
119
|
+
return candidates.map((name) => join(extensionsDir, name)).filter((p) => existsSync(p));
|
|
120
|
+
}
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Helpers
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
/**
|
|
125
|
+
* Append a line to a bounded ring buffer, evicting the oldest entry when the
|
|
126
|
+
* buffer is full.
|
|
127
|
+
*
|
|
128
|
+
* @param buffer - The mutable ring buffer.
|
|
129
|
+
* @param line - Line to append.
|
|
130
|
+
* @param bufferSize - Maximum buffer capacity.
|
|
131
|
+
*/
|
|
132
|
+
function appendOutputLine(buffer, line, bufferSize) {
|
|
133
|
+
buffer.push(line);
|
|
134
|
+
if (buffer.length > bufferSize) {
|
|
135
|
+
buffer.shift();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Delete a temporary prompt file, swallowing any errors.
|
|
140
|
+
*
|
|
141
|
+
* @param path - Absolute path to the temp file, or `null` to skip.
|
|
142
|
+
*/
|
|
143
|
+
async function cleanupTmpFile(path) {
|
|
144
|
+
if (path === null)
|
|
145
|
+
return;
|
|
146
|
+
try {
|
|
147
|
+
await unlink(path);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Best-effort cleanup — ignore ENOENT and other errors.
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Snapshot the current state of a process entry as a {@link HarnessProcessStatus}.
|
|
155
|
+
*
|
|
156
|
+
* @param entry - The process tracking entry.
|
|
157
|
+
* @returns Immutable status snapshot.
|
|
158
|
+
*
|
|
159
|
+
* @public
|
|
160
|
+
*/
|
|
161
|
+
export function buildStatus(entry) {
|
|
162
|
+
return {
|
|
163
|
+
instanceId: entry.instanceId,
|
|
164
|
+
taskId: entry.taskId,
|
|
165
|
+
state: entry.state,
|
|
166
|
+
pid: entry.pid,
|
|
167
|
+
startedAt: entry.startedAt,
|
|
168
|
+
...(entry.endedAt !== null ? { endedAt: entry.endedAt } : {}),
|
|
169
|
+
...(entry.state === 'exited' && entry.exitCode !== null ? { exitCode: entry.exitCode } : {}),
|
|
170
|
+
...(entry.error !== null ? { error: entry.error } : {}),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Create a new process tracking entry for a given instance and task.
|
|
175
|
+
*
|
|
176
|
+
* The entry starts in a transitional `'failed'` state that will be
|
|
177
|
+
* immediately overwritten by {@link PiWrapper.start} on success.
|
|
178
|
+
*
|
|
179
|
+
* @param instanceId - Stable instance identifier.
|
|
180
|
+
* @param taskId - CLEO task ID.
|
|
181
|
+
* @param resolveExit - Promise resolve callback wired to the exit promise.
|
|
182
|
+
* @returns Initialised (pre-spawn) tracking entry.
|
|
183
|
+
*
|
|
184
|
+
* @public
|
|
185
|
+
*/
|
|
186
|
+
export function createProcessEntry(instanceId, taskId, resolveExit) {
|
|
187
|
+
return {
|
|
188
|
+
pid: null,
|
|
189
|
+
child: null,
|
|
190
|
+
taskId,
|
|
191
|
+
instanceId,
|
|
192
|
+
startedAt: new Date().toISOString(),
|
|
193
|
+
state: 'failed', // overwritten by start() on success
|
|
194
|
+
exitCode: null,
|
|
195
|
+
terminatingSignal: null,
|
|
196
|
+
endedAt: null,
|
|
197
|
+
error: null,
|
|
198
|
+
outputBuffer: [],
|
|
199
|
+
resolveExit,
|
|
200
|
+
tmpFile: null,
|
|
201
|
+
killTimer: null,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// PiWrapper
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
/**
|
|
208
|
+
* Low-level Pi process launcher.
|
|
209
|
+
*
|
|
210
|
+
* Manages the full lifecycle of Pi CLI processes: spawning via
|
|
211
|
+
* {@link start}, output buffering into a ring buffer, and
|
|
212
|
+
* SIGTERM-then-SIGKILL termination via {@link terminate}. Process state
|
|
213
|
+
* is tracked in a {@link PiProcessEntry} held by the caller
|
|
214
|
+
* ({@link PiCodingAgentAdapter}).
|
|
215
|
+
*
|
|
216
|
+
* @public
|
|
217
|
+
*/
|
|
218
|
+
export class PiWrapper {
|
|
219
|
+
/**
|
|
220
|
+
* Spawn a Pi CLI process for the given task.
|
|
221
|
+
*
|
|
222
|
+
* Writes the prompt to a temporary file in `/tmp/`, builds the argument
|
|
223
|
+
* list (prepending `--extension <path>` for each available CleoOS
|
|
224
|
+
* extension), and spawns Pi as a child process. Stdout and stderr are
|
|
225
|
+
* line-buffered into `entry.outputBuffer`.
|
|
226
|
+
*
|
|
227
|
+
* When spawn fails (e.g. binary not found), `entry.state` is set to
|
|
228
|
+
* `'failed'` and `entry.resolveExit` is called before returning.
|
|
229
|
+
*
|
|
230
|
+
* @param entry - Pre-allocated process tracking entry. Mutated in place.
|
|
231
|
+
* @param prompt - Prompt text to deliver to Pi.
|
|
232
|
+
* @param cwd - Working directory for the child process.
|
|
233
|
+
* @param env - Environment variable overrides merged atop the current env.
|
|
234
|
+
* @returns The mutated `entry` (for chaining convenience).
|
|
235
|
+
*
|
|
236
|
+
* @public
|
|
237
|
+
*/
|
|
238
|
+
async start(entry, prompt, cwd, env) {
|
|
239
|
+
const bufferSize = getOutputBufferSize();
|
|
240
|
+
const binaryPath = getPiBinaryPath();
|
|
241
|
+
// Write prompt to a temporary file (file-mode delivery).
|
|
242
|
+
const tmpFile = `/tmp/cleo-pi-${entry.instanceId}.txt`;
|
|
243
|
+
entry.tmpFile = tmpFile;
|
|
244
|
+
try {
|
|
245
|
+
await writeFile(tmpFile, prompt, 'utf-8');
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
entry.state = 'failed';
|
|
249
|
+
entry.error = err instanceof Error ? err.message : String(err);
|
|
250
|
+
entry.endedAt = new Date().toISOString();
|
|
251
|
+
entry.resolveExit(buildStatus(entry));
|
|
252
|
+
return entry;
|
|
253
|
+
}
|
|
254
|
+
// Build argument list: [--extension <path>...] <promptFile>
|
|
255
|
+
const extensionPaths = resolveExtensionPaths();
|
|
256
|
+
const extensionFlags = extensionPaths.flatMap((p) => ['--extension', p]);
|
|
257
|
+
const args = [...extensionFlags, tmpFile];
|
|
258
|
+
// Merge environment: parent env → telemetry disable → caller overrides.
|
|
259
|
+
const parentEnv = Object.fromEntries(Object.entries(process.env).filter((pair) => pair[1] !== undefined));
|
|
260
|
+
const mergedEnv = {
|
|
261
|
+
...parentEnv,
|
|
262
|
+
PI_TELEMETRY: '0', // suppress telemetry in CI/sandbox runs
|
|
263
|
+
...env,
|
|
264
|
+
};
|
|
265
|
+
let child;
|
|
266
|
+
try {
|
|
267
|
+
child = spawn(binaryPath, args, {
|
|
268
|
+
cwd,
|
|
269
|
+
env: mergedEnv,
|
|
270
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
catch (err) {
|
|
274
|
+
entry.state = 'failed';
|
|
275
|
+
entry.error = err instanceof Error ? err.message : String(err);
|
|
276
|
+
entry.endedAt = new Date().toISOString();
|
|
277
|
+
await cleanupTmpFile(tmpFile);
|
|
278
|
+
entry.tmpFile = null;
|
|
279
|
+
entry.resolveExit(buildStatus(entry));
|
|
280
|
+
return entry;
|
|
281
|
+
}
|
|
282
|
+
entry.child = child;
|
|
283
|
+
entry.pid = child.pid ?? null;
|
|
284
|
+
entry.state = 'running';
|
|
285
|
+
// Buffer stdout lines into the ring buffer.
|
|
286
|
+
child.stdout?.setEncoding('utf-8');
|
|
287
|
+
child.stdout?.on('data', (chunk) => {
|
|
288
|
+
for (const rawLine of chunk.split('\n')) {
|
|
289
|
+
const line = rawLine.trimEnd();
|
|
290
|
+
if (line.length === 0)
|
|
291
|
+
continue;
|
|
292
|
+
appendOutputLine(entry.outputBuffer, { source: 'stdout', line, timestamp: new Date().toISOString() }, bufferSize);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
// Buffer stderr lines into the ring buffer.
|
|
296
|
+
child.stderr?.setEncoding('utf-8');
|
|
297
|
+
child.stderr?.on('data', (chunk) => {
|
|
298
|
+
for (const rawLine of chunk.split('\n')) {
|
|
299
|
+
const line = rawLine.trimEnd();
|
|
300
|
+
if (line.length === 0)
|
|
301
|
+
continue;
|
|
302
|
+
appendOutputLine(entry.outputBuffer, { source: 'stderr', line, timestamp: new Date().toISOString() }, bufferSize);
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
// Handle process exit.
|
|
306
|
+
child.on('close', async (code, signal) => {
|
|
307
|
+
if (entry.killTimer !== null) {
|
|
308
|
+
clearTimeout(entry.killTimer);
|
|
309
|
+
entry.killTimer = null;
|
|
310
|
+
}
|
|
311
|
+
entry.child = null;
|
|
312
|
+
entry.endedAt = new Date().toISOString();
|
|
313
|
+
if (entry.state === 'running') {
|
|
314
|
+
entry.state = signal !== null ? 'killed' : 'exited';
|
|
315
|
+
entry.exitCode = code;
|
|
316
|
+
entry.terminatingSignal = signal;
|
|
317
|
+
}
|
|
318
|
+
await cleanupTmpFile(entry.tmpFile);
|
|
319
|
+
entry.tmpFile = null;
|
|
320
|
+
entry.resolveExit(buildStatus(entry));
|
|
321
|
+
});
|
|
322
|
+
return entry;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Terminate a Pi process via SIGTERM-then-SIGKILL.
|
|
326
|
+
*
|
|
327
|
+
* Sends SIGTERM immediately. If the process has not exited within the
|
|
328
|
+
* configured grace window ({@link getTerminateGraceMs}), sends SIGKILL.
|
|
329
|
+
* Idempotent — subsequent calls when the process is already dead are no-ops.
|
|
330
|
+
*
|
|
331
|
+
* @param entry - The process tracking entry to terminate.
|
|
332
|
+
*
|
|
333
|
+
* @public
|
|
334
|
+
*/
|
|
335
|
+
terminate(entry) {
|
|
336
|
+
if (entry.child === null || entry.state !== 'running')
|
|
337
|
+
return;
|
|
338
|
+
const graceMs = getTerminateGraceMs();
|
|
339
|
+
entry.state = 'killed';
|
|
340
|
+
try {
|
|
341
|
+
entry.child.kill('SIGTERM');
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
// Process may have already exited between the state check and the signal.
|
|
345
|
+
}
|
|
346
|
+
entry.killTimer = setTimeout(() => {
|
|
347
|
+
entry.killTimer = null;
|
|
348
|
+
if (entry.child !== null) {
|
|
349
|
+
try {
|
|
350
|
+
entry.child.kill('SIGKILL');
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
// Already dead — ignore.
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}, graceMs);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=pi-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-wrapper.js","sourceRoot":"","sources":["../../../src/harnesses/pi-coding-agent/pi-wrapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HarnessAdapter type contract for cleo-os sandbox harnesses.
|
|
3
|
+
*
|
|
4
|
+
* Defines the minimal surface a cleo-os harness adapter must expose for
|
|
5
|
+
* controlling a process lifecycle: spawn, status, kill, and output streaming.
|
|
6
|
+
* This interface is intentionally simpler than the full CAAMP
|
|
7
|
+
* {@link packages/caamp | Harness} contract — cleo-os adapters wrap an
|
|
8
|
+
* external agent binary rather than a first-class CAAMP provider.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* cleo-os harness adapters follow the OpenClaw sandbox pattern: a thin
|
|
12
|
+
* TypeScript wrapper that controls an external binary (Pi, Claude Code, etc.)
|
|
13
|
+
* inside either a host-native or Docker sandbox environment.
|
|
14
|
+
*
|
|
15
|
+
* @see ADR-049 — CleoOS Sovereignty Invariants
|
|
16
|
+
* @see ADR-050 — CleoOS Sovereign Harness: Distribution Binding Charter
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Lifecycle state of a spawned harness process.
|
|
21
|
+
*
|
|
22
|
+
* - `'running'` — process was started and has not yet exited.
|
|
23
|
+
* - `'exited'` — process exited normally (exit code may be non-zero).
|
|
24
|
+
* - `'killed'` — process was terminated via {@link HarnessAdapter.kill}.
|
|
25
|
+
* - `'failed'` — process could not be started (pre-spawn error).
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export type HarnessProcessState = 'running' | 'exited' | 'killed' | 'failed';
|
|
30
|
+
/**
|
|
31
|
+
* Describes a running or completed harness process.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export interface HarnessProcessStatus {
|
|
36
|
+
/** Stable identifier for this process instance. */
|
|
37
|
+
instanceId: string;
|
|
38
|
+
/** Task ID associated with this process. */
|
|
39
|
+
taskId: string;
|
|
40
|
+
/** Current lifecycle state. */
|
|
41
|
+
state: HarnessProcessState;
|
|
42
|
+
/** OS process ID, or `null` when the process could not be started. */
|
|
43
|
+
pid: number | null;
|
|
44
|
+
/** ISO-8601 timestamp when the process was spawned. */
|
|
45
|
+
startedAt: string;
|
|
46
|
+
/**
|
|
47
|
+
* ISO-8601 timestamp when the process ended.
|
|
48
|
+
* Only populated when `state` is `'exited'` or `'killed'`.
|
|
49
|
+
* @defaultValue undefined
|
|
50
|
+
*/
|
|
51
|
+
endedAt?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Exit code from the process.
|
|
54
|
+
* Only populated when `state` is `'exited'`.
|
|
55
|
+
* @defaultValue undefined
|
|
56
|
+
*/
|
|
57
|
+
exitCode?: number | null;
|
|
58
|
+
/**
|
|
59
|
+
* Error message when `state` is `'failed'`.
|
|
60
|
+
* @defaultValue undefined
|
|
61
|
+
*/
|
|
62
|
+
error?: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A single line of output emitted from a harness process.
|
|
66
|
+
*
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
export interface HarnessOutputLine {
|
|
70
|
+
/** Source stream: stdout or stderr. */
|
|
71
|
+
source: 'stdout' | 'stderr';
|
|
72
|
+
/** The text content of this line (without trailing newline). */
|
|
73
|
+
line: string;
|
|
74
|
+
/** ISO-8601 timestamp when this line was captured. */
|
|
75
|
+
timestamp: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Options passed to {@link HarnessAdapter.spawn}.
|
|
79
|
+
*
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
export interface HarnessSpawnOptions {
|
|
83
|
+
/**
|
|
84
|
+
* Working directory for the spawned process.
|
|
85
|
+
* @defaultValue `process.cwd()`
|
|
86
|
+
*/
|
|
87
|
+
cwd?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Environment variable overrides merged atop the current process environment.
|
|
90
|
+
* @defaultValue undefined
|
|
91
|
+
*/
|
|
92
|
+
env?: Record<string, string>;
|
|
93
|
+
/**
|
|
94
|
+
* When `true`, run the process inside a Docker sandbox container instead of
|
|
95
|
+
* host-native. Requires `CLEO_PI_SANDBOXED=1` or explicit `sandboxed: true`.
|
|
96
|
+
* @defaultValue false
|
|
97
|
+
*/
|
|
98
|
+
sandboxed?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Abort signal. When it fires, the adapter terminates the process via
|
|
101
|
+
* SIGTERM-then-SIGKILL with the configured grace window.
|
|
102
|
+
* @defaultValue undefined
|
|
103
|
+
*/
|
|
104
|
+
signal?: AbortSignal;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Result returned synchronously from {@link HarnessAdapter.spawn}.
|
|
108
|
+
*
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
111
|
+
export interface HarnessSpawnResult {
|
|
112
|
+
/** Stable instance identifier (can be passed to status/kill/output). */
|
|
113
|
+
instanceId: string;
|
|
114
|
+
/** OS process ID, or `null` on failure. */
|
|
115
|
+
pid: number | null;
|
|
116
|
+
/** Promise resolving once the process exits or is killed. */
|
|
117
|
+
exitPromise: Promise<HarnessProcessStatus>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Contract every cleo-os harness adapter MUST implement.
|
|
121
|
+
*
|
|
122
|
+
* @remarks
|
|
123
|
+
* A harness adapter wraps one external agent binary and exposes a uniform
|
|
124
|
+
* lifecycle surface. The adapter is responsible for:
|
|
125
|
+
*
|
|
126
|
+
* - Writing the prompt to the correct location (temp file or stdin).
|
|
127
|
+
* - Launching the external binary with the right flags and environment.
|
|
128
|
+
* - Optionally routing the launch through a Docker sandbox container
|
|
129
|
+
* (see {@link HarnessSpawnOptions.sandboxed}).
|
|
130
|
+
* - Buffering recent output lines for post-mortem diagnostics.
|
|
131
|
+
* - Terminating processes cleanly via SIGTERM-then-SIGKILL.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const adapter = new PiCodingAgentAdapter();
|
|
136
|
+
* const { instanceId, exitPromise } = await adapter.spawn('T123', 'Implement the feature', { cwd: '/project' });
|
|
137
|
+
* const status = await exitPromise;
|
|
138
|
+
* console.log(status.exitCode);
|
|
139
|
+
* ```
|
|
140
|
+
*
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
export interface HarnessAdapter {
|
|
144
|
+
/** Short adapter identifier (e.g. `"pi-coding-agent"`). */
|
|
145
|
+
readonly id: string;
|
|
146
|
+
/**
|
|
147
|
+
* Spawn the agent binary with the given task prompt.
|
|
148
|
+
*
|
|
149
|
+
* @param taskId - Stable CLEO task identifier associated with this run.
|
|
150
|
+
* @param prompt - Prompt / instruction text to pass to the agent.
|
|
151
|
+
* @param opts - Spawn options (cwd, env, sandboxed, signal).
|
|
152
|
+
* @returns Spawn result containing the instance ID and exit promise.
|
|
153
|
+
*/
|
|
154
|
+
spawn(taskId: string, prompt: string, opts?: HarnessSpawnOptions): Promise<HarnessSpawnResult>;
|
|
155
|
+
/**
|
|
156
|
+
* Query the current status of a spawned process.
|
|
157
|
+
*
|
|
158
|
+
* @param instanceId - Instance ID returned from {@link spawn}.
|
|
159
|
+
* @returns Current status, or `null` when the ID is not tracked.
|
|
160
|
+
*/
|
|
161
|
+
status(instanceId: string): HarnessProcessStatus | null;
|
|
162
|
+
/**
|
|
163
|
+
* Terminate a running process.
|
|
164
|
+
*
|
|
165
|
+
* Sends SIGTERM, waits for the configured grace window (`CLEO_TERMINATE_GRACE_MS`
|
|
166
|
+
* or 5000 ms), then sends SIGKILL when the process has not yet exited.
|
|
167
|
+
* Idempotent — subsequent calls after the first are no-ops.
|
|
168
|
+
*
|
|
169
|
+
* @param instanceId - Instance ID returned from {@link spawn}.
|
|
170
|
+
*/
|
|
171
|
+
kill(instanceId: string): Promise<void>;
|
|
172
|
+
/**
|
|
173
|
+
* Return recently captured output lines for a process.
|
|
174
|
+
*
|
|
175
|
+
* The adapter keeps a bounded ring buffer of the last
|
|
176
|
+
* `CLEO_HARNESS_OUTPUT_BUFFER` (default: 500) lines. Useful for
|
|
177
|
+
* post-mortem diagnostics without injecting output into the parent
|
|
178
|
+
* LLM context.
|
|
179
|
+
*
|
|
180
|
+
* @param instanceId - Instance ID returned from {@link spawn}.
|
|
181
|
+
* @returns Array of recent output lines, oldest first.
|
|
182
|
+
*/
|
|
183
|
+
output(instanceId: string): HarnessOutputLine[];
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/harnesses/pi-coding-agent/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE7E;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,KAAK,EAAE,mBAAmB,CAAC;IAC3B,sEAAsE;IACtE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,6DAA6D;IAC7D,WAAW,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAE/F;;;;;OAKG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAAC;IAExD;;;;;;;;OAQG;IACH,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAAC;CACjD"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HarnessAdapter type contract for cleo-os sandbox harnesses.
|
|
3
|
+
*
|
|
4
|
+
* Defines the minimal surface a cleo-os harness adapter must expose for
|
|
5
|
+
* controlling a process lifecycle: spawn, status, kill, and output streaming.
|
|
6
|
+
* This interface is intentionally simpler than the full CAAMP
|
|
7
|
+
* {@link packages/caamp | Harness} contract — cleo-os adapters wrap an
|
|
8
|
+
* external agent binary rather than a first-class CAAMP provider.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* cleo-os harness adapters follow the OpenClaw sandbox pattern: a thin
|
|
12
|
+
* TypeScript wrapper that controls an external binary (Pi, Claude Code, etc.)
|
|
13
|
+
* inside either a host-native or Docker sandbox environment.
|
|
14
|
+
*
|
|
15
|
+
* @see ADR-049 — CleoOS Sovereignty Invariants
|
|
16
|
+
* @see ADR-050 — CleoOS Sovereign Harness: Distribution Binding Charter
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/harnesses/pi-coding-agent/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/cleo-os",
|
|
3
|
-
"version": "2026.4.
|
|
3
|
+
"version": "2026.4.101",
|
|
4
4
|
"description": "CleoOS — the batteries-included agentic development environment wrapping Pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"@mariozechner/pi-coding-agent": ">=0.60.0",
|
|
14
14
|
"@sinclair/typebox": "^0.34.49",
|
|
15
15
|
"env-paths": "^4.0.0",
|
|
16
|
-
"@cleocode/cant": "2026.4.
|
|
17
|
-
"@cleocode/
|
|
18
|
-
"@cleocode/
|
|
16
|
+
"@cleocode/cant": "2026.4.101",
|
|
17
|
+
"@cleocode/cleo": "2026.4.101",
|
|
18
|
+
"@cleocode/core": "2026.4.101"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"typescript": "^6.0.2",
|