frely-cli 0.23.10 → 0.23.11
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/agent/run-store.d.ts +80 -0
- package/dist/agent/run-store.js +154 -0
- package/dist/agent/run-store.js.map +1 -0
- package/dist/agent/run.d.ts +41 -0
- package/dist/agent/run.js +233 -0
- package/dist/agent/run.js.map +1 -0
- package/dist/agent/workspace-read.d.ts +78 -0
- package/dist/agent/workspace-read.js +292 -0
- package/dist/agent/workspace-read.js.map +1 -0
- package/dist/agent-help.d.ts +40 -4
- package/dist/agent-help.js +8 -2
- package/dist/agent-help.js.map +1 -1
- package/dist/cloud.d.ts +2 -42
- package/dist/cloud.js +8 -260
- package/dist/cloud.js.map +1 -1
- package/dist/controller/client.d.ts +6 -3
- package/dist/controller/client.js +7 -8
- package/dist/controller/client.js.map +1 -1
- package/dist/controller/session.d.ts +7 -2
- package/dist/controller/session.js +79 -22
- package/dist/controller/session.js.map +1 -1
- package/dist/index.js +79 -4
- package/dist/index.js.map +1 -1
- package/dist/skill/access.d.ts +23 -4
- package/dist/skill/access.js +59 -11
- package/dist/skill/access.js.map +1 -1
- package/dist/skill/entry.d.ts +1 -1
- package/dist/skill/entry.js +1 -1
- package/dist/skill/router.d.ts +51 -0
- package/dist/skill/router.js +76 -40
- package/dist/skill/router.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { CallerItem } from "../skill/router.js";
|
|
2
|
+
import type { FileRead } from "./workspace-read.js";
|
|
3
|
+
/** Finished runs are kept this long on this computer, then removed the next time a run starts. */
|
|
4
|
+
export declare const RUN_RETENTION_MS: number;
|
|
5
|
+
export type RunStatus = "running" | "completed" | "failed" | "cancelled" | "interrupted";
|
|
6
|
+
export interface RunRound {
|
|
7
|
+
readonly n: number;
|
|
8
|
+
readonly requestId?: string;
|
|
9
|
+
readonly startedAt: string;
|
|
10
|
+
readonly endedAt?: string;
|
|
11
|
+
readonly toolCalls: readonly string[];
|
|
12
|
+
readonly usage?: Readonly<{
|
|
13
|
+
input_tokens: number;
|
|
14
|
+
output_tokens: number;
|
|
15
|
+
total_tokens: number;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
/** Local record of one `frely agent run`. Full input and output stay on this computer (file mode 0600). */
|
|
19
|
+
export interface RunRecord {
|
|
20
|
+
readonly version: 1;
|
|
21
|
+
readonly runId: string;
|
|
22
|
+
readonly distributionId: string;
|
|
23
|
+
readonly modelId?: string;
|
|
24
|
+
readonly status: RunStatus;
|
|
25
|
+
readonly createdAt: string;
|
|
26
|
+
readonly updatedAt: string;
|
|
27
|
+
/** The detached worker that owns the run while it is `running`. */
|
|
28
|
+
readonly workerPid?: number;
|
|
29
|
+
readonly task: string;
|
|
30
|
+
/** Workspace root of `--read`; absent for a plain single call. */
|
|
31
|
+
readonly readRoot?: string;
|
|
32
|
+
readonly limits?: Readonly<{
|
|
33
|
+
totalBytes: number;
|
|
34
|
+
maxRounds: number;
|
|
35
|
+
}>;
|
|
36
|
+
readonly bridge?: Readonly<{
|
|
37
|
+
usedBytes: number;
|
|
38
|
+
roundsAnswered: number;
|
|
39
|
+
}>;
|
|
40
|
+
readonly items: readonly CallerItem[];
|
|
41
|
+
readonly rounds: readonly RunRound[];
|
|
42
|
+
readonly filesRead: readonly FileRead[];
|
|
43
|
+
readonly usage: Readonly<{
|
|
44
|
+
input_tokens: number;
|
|
45
|
+
output_tokens: number;
|
|
46
|
+
total_tokens: number;
|
|
47
|
+
}>;
|
|
48
|
+
readonly resumeCount: number;
|
|
49
|
+
readonly text?: string;
|
|
50
|
+
/** The Agent could not take local tools, so the run was done as one plain call. */
|
|
51
|
+
readonly toolsUnsupported?: boolean;
|
|
52
|
+
readonly error?: Readonly<{
|
|
53
|
+
code: string;
|
|
54
|
+
message: string;
|
|
55
|
+
}>;
|
|
56
|
+
}
|
|
57
|
+
export declare function runsDirectory(): string;
|
|
58
|
+
export declare function isRunId(value: string): boolean;
|
|
59
|
+
export declare function createRun(input: {
|
|
60
|
+
readonly distributionId: string;
|
|
61
|
+
readonly task: string;
|
|
62
|
+
readonly readRoot?: string;
|
|
63
|
+
readonly limits?: {
|
|
64
|
+
totalBytes: number;
|
|
65
|
+
maxRounds: number;
|
|
66
|
+
};
|
|
67
|
+
}): Promise<RunRecord>;
|
|
68
|
+
/** Atomic write: a reader never sees half a record. */
|
|
69
|
+
export declare function writeRun(record: RunRecord): Promise<RunRecord>;
|
|
70
|
+
export declare function readRun(runId: string): Promise<RunRecord | null>;
|
|
71
|
+
export declare function listRuns(): Promise<RunRecord[]>;
|
|
72
|
+
export declare function pruneRuns(now?: number): Promise<void>;
|
|
73
|
+
export declare function processAlive(pid: number | undefined): boolean;
|
|
74
|
+
/** `running` only counts while its worker is alive; otherwise the run was cut off (killed, rebooted) and is `interrupted`. */
|
|
75
|
+
export declare function effectiveStatus(record: RunRecord, now?: number): RunStatus;
|
|
76
|
+
/** A run can continue when a failed or interrupted run still has its Agent and (for `--read`) rounds to resume from. */
|
|
77
|
+
export declare function resumable(record: RunRecord): boolean;
|
|
78
|
+
/** `<id>` or `--last`. */
|
|
79
|
+
export declare function resolveRun(target: string | undefined): Promise<RunRecord>;
|
|
80
|
+
export declare function addUsage(total: RunRecord["usage"], usage: RunRecord["usage"] | undefined): RunRecord["usage"];
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { chmod, mkdir, readdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
/** Finished runs are kept this long on this computer, then removed the next time a run starts. */
|
|
6
|
+
export const RUN_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
7
|
+
export function runsDirectory() {
|
|
8
|
+
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "frely", "agent-runs");
|
|
9
|
+
}
|
|
10
|
+
const RUN_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
|
|
11
|
+
export function isRunId(value) {
|
|
12
|
+
return RUN_ID.test(value);
|
|
13
|
+
}
|
|
14
|
+
function runPath(runId) {
|
|
15
|
+
if (!isRunId(runId))
|
|
16
|
+
throw new Error("Invalid run id.");
|
|
17
|
+
return join(runsDirectory(), `${runId}.json`);
|
|
18
|
+
}
|
|
19
|
+
export async function createRun(input) {
|
|
20
|
+
await mkdir(runsDirectory(), { recursive: true, mode: 0o700 });
|
|
21
|
+
await chmod(runsDirectory(), 0o700).catch(() => undefined);
|
|
22
|
+
await pruneRuns().catch(() => undefined);
|
|
23
|
+
const now = new Date().toISOString();
|
|
24
|
+
const record = {
|
|
25
|
+
version: 1,
|
|
26
|
+
runId: randomUUID(),
|
|
27
|
+
distributionId: input.distributionId,
|
|
28
|
+
status: "running",
|
|
29
|
+
createdAt: now,
|
|
30
|
+
updatedAt: now,
|
|
31
|
+
task: input.task,
|
|
32
|
+
...(input.readRoot === undefined ? {} : { readRoot: input.readRoot }),
|
|
33
|
+
...(input.limits === undefined ? {} : { limits: input.limits }),
|
|
34
|
+
items: [],
|
|
35
|
+
rounds: [],
|
|
36
|
+
filesRead: [],
|
|
37
|
+
usage: { input_tokens: 0, output_tokens: 0, total_tokens: 0 },
|
|
38
|
+
resumeCount: 0,
|
|
39
|
+
};
|
|
40
|
+
await writeRun(record);
|
|
41
|
+
return record;
|
|
42
|
+
}
|
|
43
|
+
/** Atomic write: a reader never sees half a record. */
|
|
44
|
+
export async function writeRun(record) {
|
|
45
|
+
const next = { ...record, updatedAt: new Date().toISOString() };
|
|
46
|
+
const path = runPath(record.runId);
|
|
47
|
+
const temp = `${path}.${process.pid}.tmp`;
|
|
48
|
+
await writeFile(temp, `${JSON.stringify(next)}\n`, { mode: 0o600 });
|
|
49
|
+
// On Windows a rename onto a file another process is reading fails briefly (EPERM/EBUSY/EACCES): retry.
|
|
50
|
+
for (let attempt = 0;; attempt += 1) {
|
|
51
|
+
try {
|
|
52
|
+
await rename(temp, path);
|
|
53
|
+
return next;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const code = error.code;
|
|
57
|
+
if (attempt >= 50 || (code !== "EPERM" && code !== "EBUSY" && code !== "EACCES")) {
|
|
58
|
+
await rm(temp, { force: true });
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function readRun(runId) {
|
|
66
|
+
let raw;
|
|
67
|
+
for (let attempt = 0; attempt < 5 && raw === undefined; attempt += 1) {
|
|
68
|
+
try {
|
|
69
|
+
raw = await readFile(runPath(runId), "utf8");
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (error.code === "ENOENT")
|
|
73
|
+
return null;
|
|
74
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (raw === undefined)
|
|
78
|
+
return null;
|
|
79
|
+
try {
|
|
80
|
+
const value = JSON.parse(raw);
|
|
81
|
+
return value.version === 1 && value.runId === runId ? value : null;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export async function listRuns() {
|
|
88
|
+
let names;
|
|
89
|
+
try {
|
|
90
|
+
names = await readdir(runsDirectory());
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
const records = await Promise.all(names.filter((name) => name.endsWith(".json")).map((name) => readRun(name.slice(0, -5))));
|
|
96
|
+
return records.filter((record) => record !== null).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
97
|
+
}
|
|
98
|
+
export async function pruneRuns(now = Date.now()) {
|
|
99
|
+
for (const record of await listRuns()) {
|
|
100
|
+
if (record.status !== "running" && now - Date.parse(record.updatedAt) > RUN_RETENTION_MS)
|
|
101
|
+
await rm(runPath(record.runId), { force: true });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function processAlive(pid) {
|
|
105
|
+
if (pid === undefined)
|
|
106
|
+
return false;
|
|
107
|
+
try {
|
|
108
|
+
process.kill(pid, 0);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
return error.code === "EPERM";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** `running` only counts while its worker is alive; otherwise the run was cut off (killed, rebooted) and is `interrupted`. */
|
|
116
|
+
export function effectiveStatus(record, now = Date.now()) {
|
|
117
|
+
if (record.status !== "running")
|
|
118
|
+
return record.status;
|
|
119
|
+
// The worker records its pid as its first act; until then the run is only just starting.
|
|
120
|
+
if (record.workerPid === undefined)
|
|
121
|
+
return now - Date.parse(record.updatedAt) < WORKER_START_GRACE_MS ? "running" : "interrupted";
|
|
122
|
+
return processAlive(record.workerPid) ? "running" : "interrupted";
|
|
123
|
+
}
|
|
124
|
+
const WORKER_START_GRACE_MS = 20_000;
|
|
125
|
+
/** A run can continue when a failed or interrupted run still has its Agent and (for `--read`) rounds to resume from. */
|
|
126
|
+
export function resumable(record) {
|
|
127
|
+
const status = effectiveStatus(record);
|
|
128
|
+
return (status === "interrupted" || status === "failed") && (record.error?.code ?? "") !== "input_invalid";
|
|
129
|
+
}
|
|
130
|
+
/** `<id>` or `--last`. */
|
|
131
|
+
export async function resolveRun(target) {
|
|
132
|
+
if (target === undefined || target === "--last") {
|
|
133
|
+
const [latest] = await listRuns();
|
|
134
|
+
if (latest === undefined)
|
|
135
|
+
throw new Error("There are no agent runs on this computer.");
|
|
136
|
+
return latest;
|
|
137
|
+
}
|
|
138
|
+
if (!isRunId(target))
|
|
139
|
+
throw new Error("Use a run id from `frely agent runs`, or --last.");
|
|
140
|
+
const record = await readRun(target);
|
|
141
|
+
if (record === null)
|
|
142
|
+
throw new Error("This run is not on this computer (runs are removed after 7 days).");
|
|
143
|
+
return record;
|
|
144
|
+
}
|
|
145
|
+
export function addUsage(total, usage) {
|
|
146
|
+
if (usage === undefined)
|
|
147
|
+
return total;
|
|
148
|
+
return {
|
|
149
|
+
input_tokens: total.input_tokens + usage.input_tokens,
|
|
150
|
+
output_tokens: total.output_tokens + usage.output_tokens,
|
|
151
|
+
total_tokens: total.total_tokens + usage.total_tokens,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=run-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-store.js","sourceRoot":"","sources":["../../src/agent/run-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { SkillAccessError, type InstalledAgentSession } from "../skill/access.js";
|
|
2
|
+
import { type RunRecord } from "./run-store.js";
|
|
3
|
+
import { type ReadLimits } from "./workspace-read.js";
|
|
4
|
+
export interface RunDeps {
|
|
5
|
+
openSession(distributionId: string): Promise<InstalledAgentSession>;
|
|
6
|
+
invokePlain(distributionId: string, task: string, signal: AbortSignal): Promise<{
|
|
7
|
+
text: string;
|
|
8
|
+
modelId: string;
|
|
9
|
+
usage?: Readonly<Record<string, unknown>>;
|
|
10
|
+
}>;
|
|
11
|
+
/** Start the detached worker for a run. */
|
|
12
|
+
spawnWorker(runId: string): void;
|
|
13
|
+
stderr(text: string): void;
|
|
14
|
+
pollMs: number;
|
|
15
|
+
}
|
|
16
|
+
export declare const defaultRunDeps: RunDeps;
|
|
17
|
+
/** Create the run record, start the detached worker and wait for the end. The same call also serves `frely agent result --wait`. */
|
|
18
|
+
export declare function startRun(input: {
|
|
19
|
+
readonly distributionId: string;
|
|
20
|
+
readonly task: string;
|
|
21
|
+
readonly read?: {
|
|
22
|
+
readonly root: string;
|
|
23
|
+
readonly limits: ReadLimits;
|
|
24
|
+
};
|
|
25
|
+
}, deps?: RunDeps): Promise<RunRecord>;
|
|
26
|
+
/** Poll the local record until the run is no longer running; prints each newly read file to stderr. */
|
|
27
|
+
export declare function waitForRun(runId: string, deps?: Pick<RunDeps, "pollMs" | "stderr">): Promise<RunRecord>;
|
|
28
|
+
/** A finished run as the foreground command reports it: the result, or the error the call would have thrown. */
|
|
29
|
+
export declare function runOutcome(record: RunRecord): Record<string, unknown>;
|
|
30
|
+
export declare function runFailure(record: RunRecord): SkillAccessError;
|
|
31
|
+
/** The state `frely agent result` and `frely agent runs` print for a run (no task text; the result text only when finished). */
|
|
32
|
+
export declare function runSummary(record: RunRecord): Record<string, unknown>;
|
|
33
|
+
export declare function listRunSummaries(): Promise<Record<string, unknown>[]>;
|
|
34
|
+
/** Stop a run: ask its worker to abort the call (the server stops and settles what was used), or mark an orphaned record. */
|
|
35
|
+
export declare function cancelRun(target: string | undefined, deps?: Pick<RunDeps, "pollMs">): Promise<RunRecord>;
|
|
36
|
+
/** Prepare an interrupted or failed run to continue with the items it already has, and start a worker for it. */
|
|
37
|
+
export declare function resumeRun(target: string | undefined, deps?: RunDeps): Promise<RunRecord>;
|
|
38
|
+
/** The worker side: runs the call (and the tool rounds) of one record, saving after every step. */
|
|
39
|
+
export declare function executeRun(runId: string, deps?: RunDeps, signal?: AbortSignal): Promise<void>;
|
|
40
|
+
/** Entry of `frely agent __worker <runId>`: cancel on SIGTERM, ignore the terminal hang-up. */
|
|
41
|
+
export declare function workerMain(runId: string, deps?: RunDeps): Promise<void>;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { cliLaunchArguments } from "../cli-launch.js";
|
|
3
|
+
import { ClientToolsUnsupportedError, invokeInstalledAgent, openInstalledAgentSession, SkillAccessError, } from "../skill/access.js";
|
|
4
|
+
import { addUsage, createRun, effectiveStatus, listRuns, processAlive, readRun, resolveRun, resumable, writeRun, } from "./run-store.js";
|
|
5
|
+
import { READ_TOOLS, WorkspaceReadBridge } from "./workspace-read.js";
|
|
6
|
+
const MAX_TASK_BYTES = 128 * 1024;
|
|
7
|
+
const OVERVIEW_HEADER = "\n\n---\nLocal workspace (read-only file tools are available: read what you need, do not guess). Readable files:\n";
|
|
8
|
+
export const defaultRunDeps = {
|
|
9
|
+
openSession: (distributionId) => openInstalledAgentSession({ distributionId }),
|
|
10
|
+
invokePlain: async (distributionId, task, signal) => {
|
|
11
|
+
const result = await invokeInstalledAgent({ distributionId, task, signal });
|
|
12
|
+
return { text: result.text, modelId: result.modelId, ...("usage" in result && result.usage ? { usage: result.usage } : {}) };
|
|
13
|
+
},
|
|
14
|
+
spawnWorker: (runId) => {
|
|
15
|
+
// Detached, so Ctrl-C, a host command timeout or a killed parent does not stop the call it is waiting for.
|
|
16
|
+
const launch = cliLaunchArguments(process.argv[1] ?? "", ["agent", "__worker", runId]);
|
|
17
|
+
spawn(launch[0], launch.slice(1), { detached: true, stdio: "ignore", windowsHide: true, env: process.env }).unref();
|
|
18
|
+
},
|
|
19
|
+
stderr: (text) => { process.stderr.write(text); },
|
|
20
|
+
pollMs: 400,
|
|
21
|
+
};
|
|
22
|
+
/** Create the run record, start the detached worker and wait for the end. The same call also serves `frely agent result --wait`. */
|
|
23
|
+
export async function startRun(input, deps = defaultRunDeps) {
|
|
24
|
+
if (!input.task.trim() || Buffer.byteLength(input.task, "utf8") > MAX_TASK_BYTES)
|
|
25
|
+
throw new SkillAccessError("input_invalid", "Agent input must be non-empty and at most 128 KiB.");
|
|
26
|
+
const record = await createRun({
|
|
27
|
+
distributionId: input.distributionId,
|
|
28
|
+
task: input.task,
|
|
29
|
+
...(input.read === undefined ? {} : { readRoot: input.read.root, limits: input.read.limits }),
|
|
30
|
+
});
|
|
31
|
+
deps.stderr(`Run ${record.runId} started. If this command is cut off the run keeps going: frely agent result ${record.runId} --wait\n`);
|
|
32
|
+
deps.spawnWorker(record.runId);
|
|
33
|
+
return waitForRun(record.runId, deps);
|
|
34
|
+
}
|
|
35
|
+
/** Poll the local record until the run is no longer running; prints each newly read file to stderr. */
|
|
36
|
+
export async function waitForRun(runId, deps = defaultRunDeps) {
|
|
37
|
+
const seen = new Set();
|
|
38
|
+
while (true) {
|
|
39
|
+
const record = await readRun(runId);
|
|
40
|
+
if (record === null)
|
|
41
|
+
throw new SkillAccessError("remote_call_failed", "The run record is no longer on this computer.");
|
|
42
|
+
for (const file of record.filesRead) {
|
|
43
|
+
if (!seen.has(file.path)) {
|
|
44
|
+
seen.add(file.path);
|
|
45
|
+
deps.stderr(`read ${file.path}\n`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (effectiveStatus(record) !== "running")
|
|
49
|
+
return { ...record, status: effectiveStatus(record) };
|
|
50
|
+
await new Promise((resolve) => setTimeout(resolve, deps.pollMs));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** A finished run as the foreground command reports it: the result, or the error the call would have thrown. */
|
|
54
|
+
export function runOutcome(record) {
|
|
55
|
+
if (record.status === "completed") {
|
|
56
|
+
return {
|
|
57
|
+
ok: true,
|
|
58
|
+
runId: record.runId,
|
|
59
|
+
distributionId: record.distributionId,
|
|
60
|
+
...(record.modelId === undefined ? {} : { modelId: record.modelId }),
|
|
61
|
+
text: record.text ?? "",
|
|
62
|
+
...(record.readRoot === undefined ? {} : { filesRead: record.filesRead, rounds: record.rounds.length }),
|
|
63
|
+
...(record.usage.total_tokens > 0 ? { usage: record.usage } : {}),
|
|
64
|
+
...(record.toolsUnsupported === true ? { toolsUnsupported: true } : {}),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
throw runFailure(record);
|
|
68
|
+
}
|
|
69
|
+
export function runFailure(record) {
|
|
70
|
+
if (record.status === "interrupted") {
|
|
71
|
+
return new SkillAccessError("remote_call_failed", `The run was interrupted before it finished. Run \`frely agent result ${record.runId} --resume --wait\` to continue it; the interrupted round is billed again.`);
|
|
72
|
+
}
|
|
73
|
+
if (record.status === "cancelled")
|
|
74
|
+
return new SkillAccessError("remote_call_failed", `The run ${record.runId} was cancelled.`);
|
|
75
|
+
const code = (record.error?.code ?? "remote_call_failed");
|
|
76
|
+
return new SkillAccessError(code, record.error?.message ?? "The remote Frely Agent call failed.");
|
|
77
|
+
}
|
|
78
|
+
/** The state `frely agent result` and `frely agent runs` print for a run (no task text; the result text only when finished). */
|
|
79
|
+
export function runSummary(record) {
|
|
80
|
+
const status = effectiveStatus(record);
|
|
81
|
+
return {
|
|
82
|
+
ok: status === "running" || status === "completed",
|
|
83
|
+
runId: record.runId,
|
|
84
|
+
status,
|
|
85
|
+
distributionId: record.distributionId,
|
|
86
|
+
createdAt: record.createdAt,
|
|
87
|
+
updatedAt: record.updatedAt,
|
|
88
|
+
rounds: record.rounds.length,
|
|
89
|
+
filesRead: record.filesRead,
|
|
90
|
+
usage: record.usage,
|
|
91
|
+
...(status === "completed" ? { text: record.text ?? "" } : {}),
|
|
92
|
+
...(status === "completed" || record.error === undefined ? {} : { error: record.error }),
|
|
93
|
+
resumable: resumable(record),
|
|
94
|
+
...(status === "running" ? { note: "Still running. Progress so far is listed; run `frely agent result <runId> --wait` to wait for the answer." } : {}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
export async function listRunSummaries() {
|
|
98
|
+
return (await listRuns()).slice(0, 20).map((record) => {
|
|
99
|
+
const { filesRead, usage, ...rest } = runSummary(record);
|
|
100
|
+
return { ...rest, filesRead: record.filesRead.length, totalTokens: usage.total_tokens };
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/** Stop a run: ask its worker to abort the call (the server stops and settles what was used), or mark an orphaned record. */
|
|
104
|
+
export async function cancelRun(target, deps = defaultRunDeps) {
|
|
105
|
+
const record = await resolveRun(target);
|
|
106
|
+
if (record.status !== "running")
|
|
107
|
+
return record;
|
|
108
|
+
if (processAlive(record.workerPid)) {
|
|
109
|
+
try {
|
|
110
|
+
process.kill(record.workerPid, "SIGTERM");
|
|
111
|
+
}
|
|
112
|
+
catch { /* it just ended */ }
|
|
113
|
+
for (let waited = 0; waited < 5000; waited += deps.pollMs) {
|
|
114
|
+
await new Promise((resolve) => setTimeout(resolve, deps.pollMs));
|
|
115
|
+
const current = await readRun(record.runId);
|
|
116
|
+
if (current !== null && current.status !== "running")
|
|
117
|
+
return current;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const latest = await readRun(record.runId) ?? record;
|
|
121
|
+
if (latest.status !== "running")
|
|
122
|
+
return latest;
|
|
123
|
+
return writeRun({ ...latest, status: "cancelled" });
|
|
124
|
+
}
|
|
125
|
+
/** Prepare an interrupted or failed run to continue with the items it already has, and start a worker for it. */
|
|
126
|
+
export async function resumeRun(target, deps = defaultRunDeps) {
|
|
127
|
+
const record = await resolveRun(target);
|
|
128
|
+
if (!resumable(record))
|
|
129
|
+
throw new Error(effectiveStatus(record) === "running" ? "This run is still running." : "This run cannot be resumed.");
|
|
130
|
+
const { error: _error, workerPid: _pid, ...rest } = record;
|
|
131
|
+
const next = await writeRun({ ...rest, status: "running", resumeCount: record.resumeCount + 1 });
|
|
132
|
+
deps.stderr(`Resuming run ${record.runId}. The round that was interrupted is billed again.\n`);
|
|
133
|
+
deps.spawnWorker(record.runId);
|
|
134
|
+
return next;
|
|
135
|
+
}
|
|
136
|
+
/** The worker side: runs the call (and the tool rounds) of one record, saving after every step. */
|
|
137
|
+
export async function executeRun(runId, deps = defaultRunDeps, signal = new AbortController().signal) {
|
|
138
|
+
const loaded = await readRun(runId);
|
|
139
|
+
if (loaded === null || loaded.status !== "running")
|
|
140
|
+
return;
|
|
141
|
+
let record = await writeRun({ ...loaded, workerPid: process.pid });
|
|
142
|
+
const save = async (patch) => { record = await writeRun({ ...record, ...patch }); };
|
|
143
|
+
try {
|
|
144
|
+
if (record.readRoot === undefined) {
|
|
145
|
+
const result = await deps.invokePlain(record.distributionId, record.task, signal);
|
|
146
|
+
await save({ status: "completed", modelId: result.modelId, text: result.text });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
await runWithTools(record, save, () => record, deps, signal);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (signal.aborted) {
|
|
153
|
+
await save({ status: "cancelled" });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const code = error instanceof SkillAccessError ? error.code : "remote_call_failed";
|
|
157
|
+
const message = error instanceof SkillAccessError ? error.message : "The remote Frely Agent call failed.";
|
|
158
|
+
await save({ status: "failed", error: { code, message } });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function runWithTools(start, save, current, deps, signal) {
|
|
162
|
+
const limits = start.limits;
|
|
163
|
+
if (limits === undefined || start.readRoot === undefined)
|
|
164
|
+
throw new SkillAccessError("input_invalid", "The run has no workspace.");
|
|
165
|
+
const bridge = await WorkspaceReadBridge.open(start.readRoot, limits);
|
|
166
|
+
bridge.restore({ usedBytes: start.bridge?.usedBytes ?? 0, roundsAnswered: start.bridge?.roundsAnswered ?? 0, filesRead: start.filesRead });
|
|
167
|
+
const task = await withOverview(start.task, bridge);
|
|
168
|
+
const session = await deps.openSession(start.distributionId);
|
|
169
|
+
await save({ modelId: session.modelId });
|
|
170
|
+
const hardCap = limits.maxRounds + 3;
|
|
171
|
+
while (true) {
|
|
172
|
+
if (signal.aborted)
|
|
173
|
+
throw new Error("aborted");
|
|
174
|
+
const items = [...current().items];
|
|
175
|
+
const pending = unansweredCalls(items);
|
|
176
|
+
if (pending.length > 0) {
|
|
177
|
+
const outputs = await bridge.answerRound(pending);
|
|
178
|
+
for (const output of outputs)
|
|
179
|
+
items.push({ type: "function_call_output", call_id: output.callId, output: output.output });
|
|
180
|
+
await save({ items, filesRead: bridge.filesRead(), bridge: { usedBytes: bridge.state().usedBytes, roundsAnswered: bridge.state().roundsAnswered } });
|
|
181
|
+
}
|
|
182
|
+
if (current().rounds.length >= hardCap)
|
|
183
|
+
throw new SkillAccessError("remote_call_failed", "The Agent kept asking for files after the read budget was used up.");
|
|
184
|
+
const startedAt = new Date().toISOString();
|
|
185
|
+
let turn;
|
|
186
|
+
try {
|
|
187
|
+
turn = await session.turn({ task, tools: READ_TOOLS, items, signal });
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
if (error instanceof ClientToolsUnsupportedError && current().rounds.length === 0) {
|
|
191
|
+
// The Agent takes no caller tools: do the plain single call, as if --read had not been given.
|
|
192
|
+
const result = await deps.invokePlain(start.distributionId, start.task, signal);
|
|
193
|
+
await save({ status: "completed", modelId: result.modelId, text: result.text, toolsUnsupported: true });
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
const round = {
|
|
199
|
+
n: current().rounds.length + 1,
|
|
200
|
+
...(turn.requestId === undefined ? {} : { requestId: turn.requestId }),
|
|
201
|
+
startedAt,
|
|
202
|
+
endedAt: new Date().toISOString(),
|
|
203
|
+
toolCalls: turn.status === "tool_calls" ? turn.calls.map((call) => call.name) : [],
|
|
204
|
+
...(turn.usage === undefined ? {} : { usage: turn.usage }),
|
|
205
|
+
};
|
|
206
|
+
const usage = addUsage(current().usage, turn.usage);
|
|
207
|
+
if (turn.status === "completed") {
|
|
208
|
+
await save({ status: "completed", text: turn.text, rounds: [...current().rounds, round], usage });
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
await save({ rounds: [...current().rounds, round], usage, items: [...items, ...turn.items] });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function unansweredCalls(items) {
|
|
215
|
+
const answered = new Set(items.flatMap((item) => (item.type === "function_call_output" ? [item.call_id] : [])));
|
|
216
|
+
return items.flatMap((item) => (item.type === "function_call" && !answered.has(item.call_id) ? [{ callId: item.call_id, name: item.name, arguments: item.arguments }] : []));
|
|
217
|
+
}
|
|
218
|
+
/** Task plus the path tree of the readable files, kept inside the 128 KiB input limit. */
|
|
219
|
+
async function withOverview(task, bridge) {
|
|
220
|
+
const room = MAX_TASK_BYTES - Buffer.byteLength(task, "utf8") - Buffer.byteLength(OVERVIEW_HEADER, "utf8");
|
|
221
|
+
if (room < 256)
|
|
222
|
+
return task;
|
|
223
|
+
const overview = await bridge.overview(Math.min(8 * 1024, room));
|
|
224
|
+
return overview === "" ? task : `${task}${OVERVIEW_HEADER}${overview}`;
|
|
225
|
+
}
|
|
226
|
+
/** Entry of `frely agent __worker <runId>`: cancel on SIGTERM, ignore the terminal hang-up. */
|
|
227
|
+
export async function workerMain(runId, deps = defaultRunDeps) {
|
|
228
|
+
const controller = new AbortController();
|
|
229
|
+
process.on("SIGTERM", () => controller.abort());
|
|
230
|
+
process.on("SIGHUP", () => undefined);
|
|
231
|
+
await executeRun(runId, deps, controller.signal);
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/agent/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { CallerToolDefinition } from "../skill/router.js";
|
|
2
|
+
/** One tool result is cut at this size (the Agent runtime rejects larger caller tool outputs). */
|
|
3
|
+
export declare const TOOL_OUTPUT_LIMIT_BYTES: number;
|
|
4
|
+
export declare const DEFAULT_TOTAL_READ_BYTES: number;
|
|
5
|
+
export declare const DEFAULT_MAX_ROUNDS = 16;
|
|
6
|
+
export interface ReadLimits {
|
|
7
|
+
/** Total tool output handed to the Agent in one run. */
|
|
8
|
+
readonly totalBytes: number;
|
|
9
|
+
/** Rounds in which tool calls are answered; later calls get "budget exhausted". */
|
|
10
|
+
readonly maxRounds: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_READ_LIMITS: ReadLimits;
|
|
13
|
+
export interface FileRead {
|
|
14
|
+
readonly path: string;
|
|
15
|
+
readonly bytes: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Read-only tools, with the same names and parameters as the FrelyMCP workspace tools. They run on this computer; the Agent only sees
|
|
19
|
+
* what a call returns.
|
|
20
|
+
*/
|
|
21
|
+
export declare const READ_TOOLS: readonly CallerToolDefinition[];
|
|
22
|
+
/**
|
|
23
|
+
* Why a workspace path never leaves this computer, or null. Applies to every read-only tool result: git internals, environment files,
|
|
24
|
+
* key material, package-manager credentials. Gitignored files and binaries are checked separately (they need git and the file content).
|
|
25
|
+
*/
|
|
26
|
+
export declare function localDenyReason(relativePath: string): string | null;
|
|
27
|
+
/** Which of these workspace-relative paths git ignores. Outside a git repository nothing is ignored. */
|
|
28
|
+
export declare function gitIgnoredPaths(root: string, paths: readonly string[]): Promise<Set<string>>;
|
|
29
|
+
/** The repository root for `--read` without a directory: the git top level of the current directory, else the directory itself. */
|
|
30
|
+
export declare function defaultReadRoot(cwd: string): Promise<string>;
|
|
31
|
+
export declare class WorkspaceReadBridge {
|
|
32
|
+
private readonly workspace;
|
|
33
|
+
readonly limits: ReadLimits;
|
|
34
|
+
private used;
|
|
35
|
+
private roundsAnswered;
|
|
36
|
+
private readonly reads;
|
|
37
|
+
private constructor();
|
|
38
|
+
static open(root: string, limits?: ReadLimits): Promise<WorkspaceReadBridge>;
|
|
39
|
+
get root(): string;
|
|
40
|
+
/** Restore the counters of an earlier part of the same run (resume). */
|
|
41
|
+
restore(state: {
|
|
42
|
+
readonly usedBytes: number;
|
|
43
|
+
readonly roundsAnswered: number;
|
|
44
|
+
readonly filesRead: readonly FileRead[];
|
|
45
|
+
}): void;
|
|
46
|
+
state(): {
|
|
47
|
+
usedBytes: number;
|
|
48
|
+
roundsAnswered: number;
|
|
49
|
+
filesRead: FileRead[];
|
|
50
|
+
};
|
|
51
|
+
filesRead(): FileRead[];
|
|
52
|
+
/** True once the Agent has used up the round budget; its next tool calls only get "budget exhausted". */
|
|
53
|
+
get roundBudgetSpent(): boolean;
|
|
54
|
+
/** Answer one round of calls. Never throws: a failure is the tool's output. Returns `onRead(path)` events through `log`. */
|
|
55
|
+
answerRound(calls: readonly {
|
|
56
|
+
callId: string;
|
|
57
|
+
name: string;
|
|
58
|
+
arguments: string;
|
|
59
|
+
}[], log?: (path: string) => void): Promise<{
|
|
60
|
+
callId: string;
|
|
61
|
+
output: string;
|
|
62
|
+
}[]>;
|
|
63
|
+
private exhaustedMessage;
|
|
64
|
+
private run;
|
|
65
|
+
private sanitize;
|
|
66
|
+
private noteRead;
|
|
67
|
+
private dispatch;
|
|
68
|
+
private ignored;
|
|
69
|
+
/** Drop denied and gitignored entries from a listing. */
|
|
70
|
+
private visible;
|
|
71
|
+
/**
|
|
72
|
+
* A path tree of the files the Agent may read, cut at `maxBytes`: the first thing it gets, so it can choose what to open. Uses
|
|
73
|
+
* `git ls-files` (tracked and untracked, not ignored) in a repository, else a bounded walk.
|
|
74
|
+
*/
|
|
75
|
+
overview(maxBytes?: number): Promise<string>;
|
|
76
|
+
}
|
|
77
|
+
/** Cut at a byte limit on a character boundary, saying so, so the Agent knows to ask for a line range. */
|
|
78
|
+
export declare function limitBytes(text: string, limit: number): string;
|