@farmslot/agent-runtime 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +2 -2
- package/bin/farmslot-agent.mjs +3 -43
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/native/affinity.test.d.ts +2 -0
- package/dist/native/affinity.test.d.ts.map +1 -0
- package/dist/native/affinity.test.js +30 -0
- package/dist/native/affinity.test.js.map +1 -0
- package/dist/native/claude.d.ts +11 -0
- package/dist/native/claude.d.ts.map +1 -0
- package/dist/native/claude.js +490 -0
- package/dist/native/claude.js.map +1 -0
- package/dist/native/client.d.ts +21 -0
- package/dist/native/client.d.ts.map +1 -0
- package/dist/native/client.js +106 -0
- package/dist/native/client.js.map +1 -0
- package/dist/native/codex.d.ts +3 -0
- package/dist/native/codex.d.ts.map +1 -0
- package/dist/native/codex.js +266 -0
- package/dist/native/codex.js.map +1 -0
- package/dist/native/durability.test.d.ts +2 -0
- package/dist/native/durability.test.d.ts.map +1 -0
- package/dist/native/durability.test.js +516 -0
- package/dist/native/durability.test.js.map +1 -0
- package/dist/native/host.d.ts +2 -0
- package/dist/native/host.d.ts.map +1 -0
- package/dist/native/host.js +90 -0
- package/dist/native/host.js.map +1 -0
- package/dist/native/index.d.ts +4 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +3 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native/ipc.d.ts +49 -0
- package/dist/native/ipc.d.ts.map +1 -0
- package/dist/native/ipc.js +109 -0
- package/dist/native/ipc.js.map +1 -0
- package/dist/native/manager.d.ts +43 -0
- package/dist/native/manager.d.ts.map +1 -0
- package/dist/native/manager.js +510 -0
- package/dist/native/manager.js.map +1 -0
- package/dist/native/process-tree.d.ts +15 -0
- package/dist/native/process-tree.d.ts.map +1 -0
- package/dist/native/process-tree.js +128 -0
- package/dist/native/process-tree.js.map +1 -0
- package/dist/native/process-tree.test.d.ts +2 -0
- package/dist/native/process-tree.test.d.ts.map +1 -0
- package/dist/native/process-tree.test.js +49 -0
- package/dist/native/process-tree.test.js.map +1 -0
- package/dist/native/process.d.ts +34 -0
- package/dist/native/process.d.ts.map +1 -0
- package/dist/native/process.js +223 -0
- package/dist/native/process.js.map +1 -0
- package/dist/native/service.d.ts +7 -0
- package/dist/native/service.d.ts.map +1 -0
- package/dist/native/service.js +117 -0
- package/dist/native/service.js.map +1 -0
- package/dist/native/storage.d.ts +11 -0
- package/dist/native/storage.d.ts.map +1 -0
- package/dist/native/storage.js +102 -0
- package/dist/native/storage.js.map +1 -0
- package/dist/native/supervisor.d.ts +2 -0
- package/dist/native/supervisor.d.ts.map +1 -0
- package/dist/native/supervisor.js +127 -0
- package/dist/native/supervisor.js.map +1 -0
- package/dist/native/types.d.ts +26 -0
- package/dist/native/types.d.ts.map +1 -0
- package/dist/native/types.js +2 -0
- package/dist/native/types.js.map +1 -0
- package/dist/native/workspace-files.d.ts +6 -0
- package/dist/native/workspace-files.d.ts.map +1 -0
- package/dist/native/workspace-files.js +62 -0
- package/dist/native/workspace-files.js.map +1 -0
- package/dist/native/workspace.d.ts +5 -0
- package/dist/native/workspace.d.ts.map +1 -0
- package/dist/native/workspace.js +120 -0
- package/dist/native/workspace.js.map +1 -0
- package/dist/task-init/index.d.ts +66 -0
- package/dist/task-init/index.d.ts.map +1 -0
- package/dist/task-init/index.js +120 -0
- package/dist/task-init/index.js.map +1 -0
- package/dist/task-init/task-document.d.ts +98 -0
- package/dist/task-init/task-document.d.ts.map +1 -0
- package/dist/task-init/task-document.js +184 -0
- package/dist/task-init/task-document.js.map +1 -0
- package/dist/task-init/write.d.ts +48 -0
- package/dist/task-init/write.d.ts.map +1 -0
- package/dist/task-init/write.js +70 -0
- package/dist/task-init/write.js.map +1 -0
- package/package.json +13 -4
- package/scripts/checklist-target.cjs +5 -3
- package/scripts/execution-template-cli.mjs +9 -7
- package/scripts/mark-checklist-step.cjs +1 -1
- package/scripts/task-init-cli.mjs +166 -0
- package/scripts/worker-terminal-contract.cjs +15 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { closeSync, fsyncSync, ftruncateSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
/** Drop only an incomplete final write before any recovery reader or writer proceeds. */
|
|
5
|
+
export function readJournal(path) {
|
|
6
|
+
const fd = openSync(path, 'r+');
|
|
7
|
+
try {
|
|
8
|
+
const bytes = readFileSync(fd);
|
|
9
|
+
const end = bytes.lastIndexOf(10) + 1;
|
|
10
|
+
if (end < bytes.length) {
|
|
11
|
+
ftruncateSync(fd, end);
|
|
12
|
+
fsyncSync(fd);
|
|
13
|
+
}
|
|
14
|
+
return bytes.subarray(0, end).toString().split('\n').filter(Boolean);
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
closeSync(fd);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function privateDirectory(path) {
|
|
21
|
+
mkdirSync(path, { recursive: true, mode: 0o700 });
|
|
22
|
+
const stat = lstatSync(path);
|
|
23
|
+
if (!stat.isDirectory() || stat.uid !== process.getuid?.() || (stat.mode & 0o077) !== 0)
|
|
24
|
+
throw new Error(`Native state directory must be owned by this OS user with mode 0700: ${path}`);
|
|
25
|
+
}
|
|
26
|
+
export function durableWrite(path, value) {
|
|
27
|
+
const temp = `${path}.${process.pid}.tmp`;
|
|
28
|
+
const fd = openSync(temp, 'w', 0o600);
|
|
29
|
+
try {
|
|
30
|
+
writeFileSync(fd, JSON.stringify(value));
|
|
31
|
+
fsyncSync(fd);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
closeSync(fd);
|
|
35
|
+
}
|
|
36
|
+
renameSync(temp, path);
|
|
37
|
+
const directory = openSync(dirname(path), 'r');
|
|
38
|
+
try {
|
|
39
|
+
fsyncSync(directory);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
closeSync(directory);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function readJson(path) {
|
|
46
|
+
const stat = lstatSync(path);
|
|
47
|
+
if (!stat.isFile() || stat.uid !== process.getuid?.() || (stat.mode & 0o077) !== 0)
|
|
48
|
+
throw new Error('Native state file must be private and owned by this OS user');
|
|
49
|
+
// Only trusted, private runtime files use this decoder. IPC validates its input separately.
|
|
50
|
+
return JSON.parse(readFileSync(path, 'utf8'));
|
|
51
|
+
}
|
|
52
|
+
export function alive(pid) {
|
|
53
|
+
try {
|
|
54
|
+
process.kill(pid, 0);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error.code === 'ESRCH')
|
|
59
|
+
return false;
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function signalGroup(pid, signal) {
|
|
64
|
+
try {
|
|
65
|
+
process.kill(-pid, signal);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// A group that already exited is the requested stopped outcome.
|
|
69
|
+
if (error.code !== 'ESRCH')
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Structured process argv evidence, never runner stdout or a terminal rendering. */
|
|
74
|
+
export function matchesProcess(pid, identity) {
|
|
75
|
+
if (!alive(pid))
|
|
76
|
+
return false;
|
|
77
|
+
try {
|
|
78
|
+
const argv = execFileSync('ps', ['-p', String(pid), '-o', 'command='], {
|
|
79
|
+
encoding: 'utf8',
|
|
80
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
81
|
+
timeout: 1_000,
|
|
82
|
+
});
|
|
83
|
+
return argv.split(/\s+/).includes(identity);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
// The process may exit between the liveness and argv reads. No signal is needed then.
|
|
87
|
+
if (!alive(pid))
|
|
88
|
+
return false;
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function appendDurable(path, value) {
|
|
93
|
+
const fd = openSync(path, 'a', 0o600);
|
|
94
|
+
try {
|
|
95
|
+
writeFileSync(fd, `${JSON.stringify(value)}\n`);
|
|
96
|
+
fsyncSync(fd);
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
closeSync(fd);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/native/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../../src/native/supervisor.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { fork } from 'node:child_process';
|
|
2
|
+
import { randomBytes } from 'node:crypto';
|
|
3
|
+
import { existsSync, mkdirSync, readdirSync, rmSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { socketDirectory } from './ipc.js';
|
|
7
|
+
import { NativeProcessTree } from './process-tree.js';
|
|
8
|
+
import { alive, appendDurable, durableWrite, matchesProcess, privateDirectory, readJournal, readJson, signalGroup, } from './storage.js';
|
|
9
|
+
const root = process.argv[2];
|
|
10
|
+
process.umask(0o077);
|
|
11
|
+
privateDirectory(root);
|
|
12
|
+
const lock = join(root, 'lock');
|
|
13
|
+
// Serializes stale-lock reclamation as well as first start. A torn claim fails closed.
|
|
14
|
+
const claim = join(root, 'claim');
|
|
15
|
+
try {
|
|
16
|
+
mkdirSync(claim, { mode: 0o700 });
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (error.code === 'EEXIST')
|
|
20
|
+
process.exit(0);
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
let acquired = false;
|
|
24
|
+
try {
|
|
25
|
+
let occupied = false;
|
|
26
|
+
if (existsSync(lock)) {
|
|
27
|
+
const previous = readJson(join(lock, 'owner.json'));
|
|
28
|
+
occupied = alive(previous.pid);
|
|
29
|
+
if (!occupied) {
|
|
30
|
+
const previousHost = existsSync(join(root, 'worker.json'))
|
|
31
|
+
? readJson(join(root, 'worker.json'))
|
|
32
|
+
: undefined;
|
|
33
|
+
if (previousHost && alive(previousHost.pid))
|
|
34
|
+
throw new Error('Native host survived its supervisor; refusing competing ownership');
|
|
35
|
+
const cleanupPath = join(root, 'cleanup.json');
|
|
36
|
+
if (existsSync(cleanupPath) && readJson(cleanupPath).state !== 'complete')
|
|
37
|
+
throw new Error('Previous native cleanup is unresolved; verify owned processes before recovery');
|
|
38
|
+
rmSync(lock, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!occupied) {
|
|
42
|
+
mkdirSync(lock, { mode: 0o700 });
|
|
43
|
+
durableWrite(join(lock, 'owner.json'), { pid: process.pid });
|
|
44
|
+
acquired = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
rmSync(claim, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
if (!acquired)
|
|
51
|
+
process.exit(0);
|
|
52
|
+
rmSync(join(root, 'ready.json'), { force: true });
|
|
53
|
+
const socket = join(socketDirectory(root), 's');
|
|
54
|
+
privateDirectory(socketDirectory(root));
|
|
55
|
+
durableWrite(join(root, 'host.json'), {
|
|
56
|
+
supportsEnsure: true,
|
|
57
|
+
executionNodeId: process.env.FARMSLOT_NATIVE_EXECUTION_NODE_ID ?? 'local',
|
|
58
|
+
pid: process.pid,
|
|
59
|
+
token: randomBytes(32).toString('hex'),
|
|
60
|
+
socket,
|
|
61
|
+
});
|
|
62
|
+
const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'js';
|
|
63
|
+
const child = fork(fileURLToPath(new URL(`./host.${extension}`, import.meta.url)), [root], {
|
|
64
|
+
stdio: ['ignore', 'inherit', 'inherit', 'ipc'],
|
|
65
|
+
});
|
|
66
|
+
const tree = new NativeProcessTree(child.pid);
|
|
67
|
+
const treeTimer = setInterval(() => tree.capture(), 100);
|
|
68
|
+
treeTimer.unref();
|
|
69
|
+
durableWrite(join(root, 'worker.json'), { pid: child.pid });
|
|
70
|
+
durableWrite(join(root, 'cleanup.json'), { hostPid: child.pid, state: 'pending' });
|
|
71
|
+
child.send('start');
|
|
72
|
+
// A host crash loses stdin ownership. Clean its recorded process groups before releasing the lock.
|
|
73
|
+
child.on('message', (message) => {
|
|
74
|
+
if (message === 'ready')
|
|
75
|
+
durableWrite(join(root, 'ready.json'), { pid: child.pid });
|
|
76
|
+
});
|
|
77
|
+
child.on('error', (error) => {
|
|
78
|
+
throw error;
|
|
79
|
+
});
|
|
80
|
+
child.on('exit', () => {
|
|
81
|
+
void cleanup().then(() => process.exit(1), (error) => {
|
|
82
|
+
durableWrite(join(root, 'cleanup.json'), {
|
|
83
|
+
hostPid: child.pid,
|
|
84
|
+
state: 'unknown',
|
|
85
|
+
error: error.message,
|
|
86
|
+
});
|
|
87
|
+
// Keep the ownership lock. Replacement must fail closed until cleanup is resolved.
|
|
88
|
+
process.stderr.write(`Native cleanup failed: ${error.message}\n`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
async function cleanup() {
|
|
93
|
+
clearInterval(treeTimer);
|
|
94
|
+
rmSync(join(root, 'ready.json'), { force: true });
|
|
95
|
+
tree.stop();
|
|
96
|
+
const sessions = join(root, 'sessions');
|
|
97
|
+
const records = [];
|
|
98
|
+
if (existsSync(sessions))
|
|
99
|
+
for (const name of readdirSync(sessions).filter((name) => name.endsWith('.journal'))) {
|
|
100
|
+
const path = join(sessions, name);
|
|
101
|
+
for (const line of readJournal(path).reverse()) {
|
|
102
|
+
const entry = JSON.parse(line);
|
|
103
|
+
if (!entry.info)
|
|
104
|
+
continue;
|
|
105
|
+
const info = entry.info;
|
|
106
|
+
if (info.hostPid === child.pid && info.processPid && !info.processStopped) {
|
|
107
|
+
records.push({ path, info });
|
|
108
|
+
if (info.processIdentity && matchesProcess(info.processPid, info.processIdentity))
|
|
109
|
+
signalGroup(info.processPid, 'SIGKILL');
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const stopped = () => tree.empty() && records.every(({ info }) => !alive(-info.processPid));
|
|
115
|
+
const deadline = Date.now() + 5_000;
|
|
116
|
+
while (!stopped() && Date.now() < deadline)
|
|
117
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
118
|
+
if (!stopped())
|
|
119
|
+
throw new Error('Native descendants remain alive; replacement owner is blocked');
|
|
120
|
+
for (const { path, info } of records)
|
|
121
|
+
appendDurable(path, { info: { ...info, processStopped: true } });
|
|
122
|
+
durableWrite(join(root, 'cleanup.json'), { hostPid: child.pid, state: 'complete' });
|
|
123
|
+
rmSync(lock, { recursive: true });
|
|
124
|
+
}
|
|
125
|
+
for (const signal of ['SIGTERM', 'SIGINT'])
|
|
126
|
+
process.on(signal, () => child.kill(signal));
|
|
127
|
+
//# sourceMappingURL=supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../src/native/supervisor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { NativeSessionCapabilities, NativeSessionEvent, NativeSessionResponse } from '@farmslot/protocol';
|
|
2
|
+
export type NativeEventInput = Omit<NativeSessionEvent, 'sequence' | 'at' | 'sessionId' | 'generation'>;
|
|
3
|
+
export interface NativeAdapterOptions {
|
|
4
|
+
cwd: string;
|
|
5
|
+
onSpawn?: (pid: number, identity: string) => void;
|
|
6
|
+
executable: string;
|
|
7
|
+
model?: string;
|
|
8
|
+
mode?: 'default' | 'plan';
|
|
9
|
+
resumeSessionId?: string;
|
|
10
|
+
env?: NodeJS.ProcessEnv;
|
|
11
|
+
}
|
|
12
|
+
export interface NativeAdapterSession {
|
|
13
|
+
nativeSessionId: string;
|
|
14
|
+
capabilities?: NativeSessionCapabilities;
|
|
15
|
+
send(text: string, commandId: string): Promise<void>;
|
|
16
|
+
respond(requestId: string, response: NativeSessionResponse): Promise<void>;
|
|
17
|
+
interrupt(): Promise<void>;
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export interface NativeAdapter {
|
|
21
|
+
capabilities: NativeSessionCapabilities;
|
|
22
|
+
/** Compatibility policy based on the native executable's version metadata. */
|
|
23
|
+
resumeUnavailableReason?: (version: string) => string | undefined;
|
|
24
|
+
start(options: NativeAdapterOptions, emit: (event: NativeEventInput) => void): Promise<NativeAdapterSession>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/native/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,kBAAkB,EAClB,UAAU,GAAG,IAAI,GAAG,WAAW,GAAG,YAAY,CAC/C,CAAC;AACF,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AACD,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,yBAAyB,CAAC;IACzC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AACD,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,yBAAyB,CAAC;IACxC,8EAA8E;IAC9E,uBAAuB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAClE,KAAK,CACH,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GACtC,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAClC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/native/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const WORKSPACE_TEXT_LIMIT: number;
|
|
2
|
+
/** Native workspace readers share lexical and symlink checks. Node lacks openat2;
|
|
3
|
+
* whole-path races against an agent with equivalent local OS access remain possible. */
|
|
4
|
+
export declare function workspacePath(root: string, relative: string, missing?: boolean): Promise<string>;
|
|
5
|
+
export declare function readWorkspaceText(root: string, relative: string): Promise<string>;
|
|
6
|
+
//# sourceMappingURL=workspace-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-files.d.ts","sourceRoot":"","sources":["../../src/native/workspace-files.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB,QAAc,CAAC;AAEhD;wFACwF;AACxF,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,UAAQ,GACd,OAAO,CAAC,MAAM,CAAC,CAwBjB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBvF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import { lstat, open, realpath } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
export const WORKSPACE_TEXT_LIMIT = 1024 * 1024;
|
|
5
|
+
/** Native workspace readers share lexical and symlink checks. Node lacks openat2;
|
|
6
|
+
* whole-path races against an agent with equivalent local OS access remain possible. */
|
|
7
|
+
export async function workspacePath(root, relative, missing = false) {
|
|
8
|
+
// Reject even legal POSIX backslash filenames to avoid separator ambiguity across clients.
|
|
9
|
+
if (path.isAbsolute(relative) || relative.includes('\\') || relative.includes('\0'))
|
|
10
|
+
throw new Error('Use a relative workspace path');
|
|
11
|
+
const parts = relative.split('/').filter((part) => part && part !== '.');
|
|
12
|
+
if (parts.some((part) => part === '..' || part.toLowerCase() === '.git'))
|
|
13
|
+
throw new Error('Path outside workspace is not allowed');
|
|
14
|
+
const base = await realpath(root);
|
|
15
|
+
const target = path.resolve(base, ...parts);
|
|
16
|
+
const within = path.relative(base, target);
|
|
17
|
+
if (within === '..' || within.startsWith(`..${path.sep}`) || path.isAbsolute(within))
|
|
18
|
+
throw new Error('Path outside workspace is not allowed');
|
|
19
|
+
let current = base;
|
|
20
|
+
for (const part of parts) {
|
|
21
|
+
current = path.join(current, part);
|
|
22
|
+
try {
|
|
23
|
+
if ((await lstat(current)).isSymbolicLink())
|
|
24
|
+
throw new Error('Workspace symlinks are not readable');
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (missing && error.code === 'ENOENT')
|
|
28
|
+
break;
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return target;
|
|
33
|
+
}
|
|
34
|
+
export async function readWorkspaceText(root, relative) {
|
|
35
|
+
const target = await workspacePath(root, relative);
|
|
36
|
+
const handle = await open(target, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
37
|
+
try {
|
|
38
|
+
const info = await handle.stat();
|
|
39
|
+
if (!info.isFile())
|
|
40
|
+
throw new Error('Select a regular file');
|
|
41
|
+
if (info.size > WORKSPACE_TEXT_LIMIT)
|
|
42
|
+
throw new Error('File exceeds the 1 MiB viewer limit');
|
|
43
|
+
const buffer = Buffer.alloc(WORKSPACE_TEXT_LIMIT + 1);
|
|
44
|
+
let length = 0;
|
|
45
|
+
while (length < buffer.length) {
|
|
46
|
+
const { bytesRead } = await handle.read(buffer, length, buffer.length - length, length);
|
|
47
|
+
if (!bytesRead)
|
|
48
|
+
break;
|
|
49
|
+
length += bytesRead;
|
|
50
|
+
}
|
|
51
|
+
if (length > WORKSPACE_TEXT_LIMIT)
|
|
52
|
+
throw new Error('File exceeds the 1 MiB viewer limit');
|
|
53
|
+
const bytes = buffer.subarray(0, length);
|
|
54
|
+
if (bytes.includes(0))
|
|
55
|
+
throw new Error('Binary files cannot be displayed');
|
|
56
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await handle.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=workspace-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-files.js","sourceRoot":"","sources":["../../src/native/workspace-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NativeWorkspaceChangesResult, NativeWorkspaceListResult } from '@farmslot/protocol';
|
|
2
|
+
export declare function nativeWorkspaceList(cwd: string, relative: string): Promise<NativeWorkspaceListResult>;
|
|
3
|
+
export declare function nativeWorkspaceChanges(cwd: string, relative?: string): Promise<NativeWorkspaceChangesResult>;
|
|
4
|
+
export declare function nativeWorkspaceDiff(cwd: string, relative: string): Promise<string>;
|
|
5
|
+
//# sourceMappingURL=workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/native/workspace.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,4BAA4B,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AA6ClG,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,yBAAyB,CAAC,CAkBpC;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,QAAQ,SAAM,GACb,OAAO,CAAC,4BAA4B,CAAC,CA0BvC;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiCxF"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { execFile as execFileCallback } from 'node:child_process';
|
|
2
|
+
import { opendir, realpath } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { readWorkspaceText, WORKSPACE_TEXT_LIMIT, workspacePath } from './workspace-files.js';
|
|
6
|
+
const execFile = promisify(execFileCallback);
|
|
7
|
+
const STATUS_OUTPUT_LIMIT = 8 * WORKSPACE_TEXT_LIMIT;
|
|
8
|
+
const DIFF_TOO_LARGE = 'Diff exceeds the 1 MiB viewer limit.';
|
|
9
|
+
async function git(cwd, args, maxBuffer = WORKSPACE_TEXT_LIMIT) {
|
|
10
|
+
try {
|
|
11
|
+
const { stdout } = await execFile('git', [
|
|
12
|
+
'--literal-pathspecs',
|
|
13
|
+
'--no-optional-locks',
|
|
14
|
+
'-c',
|
|
15
|
+
'core.quotePath=false',
|
|
16
|
+
'-c',
|
|
17
|
+
'core.fsmonitor=false',
|
|
18
|
+
...args,
|
|
19
|
+
], {
|
|
20
|
+
cwd,
|
|
21
|
+
maxBuffer,
|
|
22
|
+
timeout: 15_000,
|
|
23
|
+
// Explicit directory arguments cannot be redirected by inherited Git plumbing variables.
|
|
24
|
+
env: Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith('GIT_'))),
|
|
25
|
+
});
|
|
26
|
+
return stdout;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
// Output limits are expected for large workspaces; preserve other Git errors.
|
|
30
|
+
if (error.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER')
|
|
31
|
+
throw new Error(args[0] === 'status'
|
|
32
|
+
? 'Changes list exceeds the 8 MiB limit. Use Files to inspect individual paths.'
|
|
33
|
+
: DIFF_TOO_LARGE, { cause: error });
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function nativeWorkspaceList(cwd, relative) {
|
|
38
|
+
const directory = await opendir(await workspacePath(cwd, relative));
|
|
39
|
+
const entries = [];
|
|
40
|
+
let truncated = false;
|
|
41
|
+
for await (const entry of directory) {
|
|
42
|
+
if (entry.name.toLowerCase() === '.git' || (!entry.isFile() && !entry.isDirectory()))
|
|
43
|
+
continue;
|
|
44
|
+
if (entries.length === 500) {
|
|
45
|
+
truncated = true;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
entries.push({
|
|
49
|
+
path: [relative === '.' ? '' : relative, entry.name].filter(Boolean).join('/'),
|
|
50
|
+
name: entry.name,
|
|
51
|
+
directory: entry.isDirectory(),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
entries.sort((a, b) => Number(b.directory) - Number(a.directory) || a.name.localeCompare(b.name));
|
|
55
|
+
return { entries, truncated };
|
|
56
|
+
}
|
|
57
|
+
export async function nativeWorkspaceChanges(cwd, relative = '.') {
|
|
58
|
+
cwd = await realpath(cwd);
|
|
59
|
+
if (relative !== '.')
|
|
60
|
+
await workspacePath(cwd, relative, true);
|
|
61
|
+
const raw = await git(cwd, ['status', '--porcelain=v1', '-z', '--untracked-files=all', '--', relative], STATUS_OUTPUT_LIMIT);
|
|
62
|
+
const repository = (await git(cwd, ['rev-parse', '--show-toplevel'])).replace(/\n$/, '');
|
|
63
|
+
const records = raw.split('\0');
|
|
64
|
+
const files = [];
|
|
65
|
+
let truncated = false;
|
|
66
|
+
for (let i = 0; i < records.length; i++) {
|
|
67
|
+
if (!records[i])
|
|
68
|
+
continue;
|
|
69
|
+
if (files.length === 500) {
|
|
70
|
+
truncated = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
const status = records[i].slice(0, 2);
|
|
74
|
+
const file = path.relative(cwd, path.join(repository, records[i].slice(3)));
|
|
75
|
+
if (file === '..' || file.startsWith('../') || path.isAbsolute(file))
|
|
76
|
+
throw new Error('Git returned a path outside the session workspace');
|
|
77
|
+
if (status.includes('R') || status.includes('C'))
|
|
78
|
+
i++;
|
|
79
|
+
files.push({ path: file, status });
|
|
80
|
+
}
|
|
81
|
+
return { files, truncated };
|
|
82
|
+
}
|
|
83
|
+
export async function nativeWorkspaceDiff(cwd, relative) {
|
|
84
|
+
await workspacePath(cwd, relative, true);
|
|
85
|
+
const changes = await nativeWorkspaceChanges(cwd, relative);
|
|
86
|
+
const file = changes.files.find((candidate) => candidate.path === relative);
|
|
87
|
+
if (!file)
|
|
88
|
+
return '';
|
|
89
|
+
if (file.status === '??') {
|
|
90
|
+
const text = await readWorkspaceText(cwd, relative);
|
|
91
|
+
if (!text)
|
|
92
|
+
return '';
|
|
93
|
+
const lines = text.split('\n');
|
|
94
|
+
if (lines.at(-1) === '')
|
|
95
|
+
lines.pop();
|
|
96
|
+
const name = JSON.stringify(`b/${relative}`);
|
|
97
|
+
const diff = `diff --git ${JSON.stringify(`a/${relative}`)} ${name}\nnew file mode 100644\n--- /dev/null\n+++ ${name}\n@@ -0,0 +1,${lines.length} @@\n${lines.map((line) => `+${line}\n`).join('')}${text.endsWith('\n') ? '' : '\\n'}`;
|
|
98
|
+
if (Buffer.byteLength(diff) > WORKSPACE_TEXT_LIMIT)
|
|
99
|
+
throw new Error(DIFF_TOO_LARGE);
|
|
100
|
+
return diff;
|
|
101
|
+
}
|
|
102
|
+
// HEAD shows both staged and unstaged workspace changes. On an unborn branch,
|
|
103
|
+
// staged additions have no HEAD, so use the empty tree produced by Git itself.
|
|
104
|
+
const head = await git(cwd, ['rev-parse', '--verify', '--quiet', 'HEAD']).catch(async (error) => {
|
|
105
|
+
if (error.code !== 1)
|
|
106
|
+
throw error;
|
|
107
|
+
return git(cwd, ['hash-object', '-t', 'tree', '/dev/null']);
|
|
108
|
+
});
|
|
109
|
+
return git(cwd, [
|
|
110
|
+
'diff',
|
|
111
|
+
'--no-ext-diff',
|
|
112
|
+
'--no-textconv',
|
|
113
|
+
'--no-renames',
|
|
114
|
+
'--relative',
|
|
115
|
+
head.trim(),
|
|
116
|
+
'--',
|
|
117
|
+
relative,
|
|
118
|
+
]);
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/native/workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type ExecutionTemplateReference, type ExecutionTemplateRunMode, type TemplateProvenance, type WorkerTerminalContractDocument } from '@farmslot/protocol';
|
|
2
|
+
import type { ExecutionTemplateSource } from '../execution-template/types.js';
|
|
3
|
+
import { type HandoffExecutionTemplate, type HandoffMetadata, type HandoffSourceKind } from './task-document.js';
|
|
4
|
+
import { type WrittenTaskDir } from './write.js';
|
|
5
|
+
export * from './task-document.js';
|
|
6
|
+
export * from './write.js';
|
|
7
|
+
export { renderTemplatePlaceholders } from '@farmslot/protocol';
|
|
8
|
+
/** Built-in terminal contract for a flow, as the gateway resolves it without project overrides. */
|
|
9
|
+
export declare function builtinTerminalContract(flow: string, options?: {
|
|
10
|
+
mode?: string;
|
|
11
|
+
now?: string;
|
|
12
|
+
}): WorkerTerminalContractDocument;
|
|
13
|
+
export interface TaskInitTemplateSelection {
|
|
14
|
+
sources: ExecutionTemplateSource[];
|
|
15
|
+
explicitId?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TaskInitSpec {
|
|
18
|
+
/** Task directory, absolute or relative to cwd; created when missing. */
|
|
19
|
+
taskDir: string;
|
|
20
|
+
/** How the worker should refer to the task dir (`TASK_DIR` placeholder); defaults to `taskDir` as given. */
|
|
21
|
+
taskDirLabel?: string;
|
|
22
|
+
flow: string;
|
|
23
|
+
runMode: ExecutionTemplateRunMode;
|
|
24
|
+
platform: string;
|
|
25
|
+
domain?: string;
|
|
26
|
+
template: TaskInitTemplateSelection;
|
|
27
|
+
task: {
|
|
28
|
+
title: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
acceptanceCriteria?: ReadonlyArray<string>;
|
|
31
|
+
sourceKind: HandoffSourceKind;
|
|
32
|
+
ticket?: string;
|
|
33
|
+
sourceRef?: string;
|
|
34
|
+
};
|
|
35
|
+
handoff: {
|
|
36
|
+
surface: string;
|
|
37
|
+
project: string;
|
|
38
|
+
attemptId?: string;
|
|
39
|
+
repo?: string;
|
|
40
|
+
startedAt?: string;
|
|
41
|
+
};
|
|
42
|
+
/** Extra `{{PLACEHOLDER}}` values for the checklist and task block. */
|
|
43
|
+
vars?: Record<string, string>;
|
|
44
|
+
modePreamble?: string;
|
|
45
|
+
/** Addendum template inserted before the checklist pointer; rendered with the same vars as the checklist. */
|
|
46
|
+
addendum?: string | null;
|
|
47
|
+
markCommand?: string;
|
|
48
|
+
terminalContract?: WorkerTerminalContractDocument;
|
|
49
|
+
bugInput?: unknown;
|
|
50
|
+
}
|
|
51
|
+
export interface TaskInitResult extends WrittenTaskDir {
|
|
52
|
+
executionTemplate: HandoffExecutionTemplate;
|
|
53
|
+
handoffMetadata: HandoffMetadata;
|
|
54
|
+
}
|
|
55
|
+
export declare function taskInit(spec: TaskInitSpec): Promise<TaskInitResult>;
|
|
56
|
+
export interface TaskProvenance {
|
|
57
|
+
executionTemplate?: HandoffExecutionTemplate | ExecutionTemplateReference;
|
|
58
|
+
templateProvenance?: Omit<TemplateProvenance, 'executionTemplate'>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Selected-template provenance for a task dir. Reads `inputs/handoff.json`;
|
|
62
|
+
* falls back to the pre-0.9 `inputs/template-provenance.json` for task dirs
|
|
63
|
+
* written before the merge. Drop the fallback next release.
|
|
64
|
+
*/
|
|
65
|
+
export declare function readTaskProvenance(taskDir: string): TaskProvenance | null;
|
|
66
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/task-init/index.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAE7B,KAAK,kBAAkB,EACvB,KAAK,8BAA8B,EACpC,MAAM,oBAAoB,CAAC;AAO5B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAE9E,OAAO,EAIL,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAUhE,mGAAmG;AACnG,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,8BAA8B,CAMhC;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,4GAA4G;IAC5G,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,wBAAwB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,yBAAyB,CAAC;IACpC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;QAC3C,UAAU,EAAE,iBAAiB,CAAC;QAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6GAA6G;IAC7G,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,8BAA8B,CAAC;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,eAAe,EAAE,eAAe,CAAC;CAClC;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CA+E1E;AAED,MAAM,WAAW,cAAc;IAC7B,iBAAiB,CAAC,EAAE,wBAAwB,GAAG,0BAA0B,CAAC;IAC1E,kBAAkB,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;CACpE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAgBzE"}
|