@marcoscale98/pi-extensible-workflows 5.19.1-fork.1 → 6.2.1-fork.1
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 +77 -0
- package/README.md +2 -2
- package/dist/src/agent-execution.d.ts +43 -10
- package/dist/src/agent-execution.js +365 -127
- package/dist/src/background-widget.d.ts +0 -1
- package/dist/src/background-widget.js +4 -9
- package/dist/src/decoders.d.ts +2 -3
- package/dist/src/decoders.js +33 -37
- package/dist/src/execution.d.ts +2 -0
- package/dist/src/execution.js +5 -5
- package/dist/src/host-delivery.js +4 -8
- package/dist/src/host-navigator.js +5 -2
- package/dist/src/host-phases.d.ts +1 -0
- package/dist/src/host-recovery.d.ts +6 -6
- package/dist/src/host-recovery.js +14 -22
- package/dist/src/host-runtime.js +56 -5
- package/dist/src/host-view.d.ts +1 -1
- package/dist/src/host-view.js +17 -15
- package/dist/src/host.js +62 -87
- package/dist/src/index.d.ts +1 -2
- package/dist/src/index.js +1523 -1630
- package/dist/src/index.js.map +3 -3
- package/dist/src/paths.d.ts +7 -6
- package/dist/src/paths.js +24 -15
- package/dist/src/persistence.d.ts +1 -0
- package/dist/src/persistence.js +1 -0
- package/dist/src/pi-runtime-runner.js +4 -1
- package/dist/src/registry.d.ts +9 -7
- package/dist/src/registry.js +28 -70
- package/dist/src/runtime/agent-runner.d.ts +2 -0
- package/dist/src/session-lease.d.ts +1 -1
- package/dist/src/session-lease.js +45 -11
- package/dist/src/settings.d.ts +6 -3
- package/dist/src/settings.js +36 -47
- package/dist/src/store.d.ts +3 -1
- package/dist/src/store.js +17 -1
- package/dist/src/trajectory.d.ts +0 -1
- package/dist/src/trajectory.js +2 -3
- package/dist/src/types.d.ts +100 -44
- package/dist/src/types.js +4 -7
- package/dist/src/utils.d.ts +3 -2
- package/dist/src/utils.js +20 -10
- package/dist/src/validation.d.ts +8 -2
- package/dist/src/validation.js +122 -86
- package/dist/starter/index.js +8 -9
- package/dist/starter/index.js.map +1 -1
- package/dist/starter/review-loop.js +8 -7
- package/dist/subagents/index.js +654 -814
- package/dist/subagents/index.js.map +3 -3
- package/dist/subagents/src/contracts.d.ts +4 -3
- package/dist/subagents/src/contracts.js +2 -2
- package/dist/subagents/src/index.d.ts +1 -1
- package/dist/subagents/src/index.js +1 -2
- package/dist/subagents/src/manager.js +49 -70
- package/dist/subagents/src/navigator.js +3 -14
- package/dist/subagents/src/view.d.ts +0 -1
- package/dist/subagents/src/view.js +2 -16
- package/dist/subagents/src/worktree.js +1 -1
- package/dist/trajectory/assets/index.html +8 -8
- package/dist/trajectory/index.js +487 -891
- package/dist/trajectory/index.js.map +3 -3
- package/dist/trajectory/src/assets/index.html +8 -8
- package/dist/trajectory/src/index.js +126 -86
- package/dist/trajectory/src/server.js +264 -25
- package/dist/trajectory/src/server.js.map +3 -3
- package/dist/trajectory/src/startup-mutex.d.ts +17 -0
- package/dist/trajectory/src/startup-mutex.js +172 -0
- package/examples/workflow-extension-template/README.md +4 -7
- package/examples/workflow-extension-template/extension.test.mjs +4 -8
- package/examples/workflow-extension-template/index.js +0 -3
- package/package.json +5 -5
- package/skills/pi-extensible-workflows/SKILL.md +10 -8
- package/src/agent-execution.ts +339 -127
- package/src/background-widget.ts +4 -10
- package/src/decoders.ts +31 -37
- package/src/execution.ts +5 -5
- package/src/host-delivery.ts +4 -8
- package/src/host-navigator.ts +4 -2
- package/src/host-phases.ts +1 -1
- package/src/host-recovery.ts +20 -26
- package/src/host-runtime.ts +44 -6
- package/src/host-view.ts +18 -11
- package/src/host.ts +62 -113
- package/src/index.ts +1 -2
- package/src/paths.ts +18 -12
- package/src/persistence.ts +1 -0
- package/src/pi-runtime-runner.ts +3 -1
- package/src/registry.ts +27 -63
- package/src/runtime/agent-runner.ts +2 -0
- package/src/session-lease.ts +34 -6
- package/src/settings.ts +35 -47
- package/src/store.ts +18 -2
- package/src/trajectory.ts +2 -4
- package/src/types.ts +71 -30
- package/src/utils.ts +18 -9
- package/src/validation.ts +102 -79
- package/starter/index.ts +0 -1
- package/starter/review-loop.ts +8 -7
- package/starter/roles/developer.md +0 -1
- package/starter/roles/oracle.md +0 -1
- package/starter/roles/researcher.md +0 -1
- package/starter/roles/reviewer.md +0 -1
- package/starter/roles/scout.md +0 -1
- package/subagents/README.md +8 -14
- package/subagents/src/contracts.ts +3 -4
- package/subagents/src/index.ts +2 -3
- package/subagents/src/manager.ts +45 -125
- package/subagents/src/navigator.ts +4 -13
- package/subagents/src/view.ts +4 -14
- package/subagents/src/worktree.ts +1 -1
- package/trajectory/src/assets/index.html +8 -8
- package/trajectory/src/index.ts +106 -82
- package/trajectory/src/server.ts +44 -8
- package/trajectory/src/startup-mutex.ts +127 -0
- package/dist/src/roles.d.ts +0 -70
- package/dist/src/roles.js +0 -326
- package/dist/starter/roles/developer.md +0 -6
- package/dist/starter/roles/oracle.md +0 -18
- package/dist/starter/roles/researcher.md +0 -20
- package/dist/starter/roles/reviewer.md +0 -19
- package/dist/starter/roles/scout.md +0 -18
- package/examples/workflow-extension-template/roles/reviewer.md +0 -4
- package/src/roles.ts +0 -327
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// trajectory/src/server.ts
|
|
2
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { createHash, randomUUID as randomUUID3 } from "node:crypto";
|
|
3
3
|
import { createServer } from "node:http";
|
|
4
|
-
import { readFile, rm
|
|
4
|
+
import { readFile as readFile3, rm as rm3 } from "node:fs/promises";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { URL } from "node:url";
|
|
7
7
|
|
|
@@ -18,9 +18,12 @@ function trajectoryActionError(action, target) {
|
|
|
18
18
|
return target.kind === "subagent" && (action === "checkpoint-approve" || action === "checkpoint-reject" || action === "pause" || action === "resume" || action === "share") ? `Trajectory action ${action} is not supported for subagent targets` : target.kind === "run" && action === "steer" ? "Trajectory action steer is not supported for run targets" : void 0;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
// src/
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
21
|
+
// src/io.ts
|
|
22
|
+
import { execFile } from "node:child_process";
|
|
23
|
+
import { randomUUID } from "node:crypto";
|
|
24
|
+
import { renameSync, rmSync, writeFileSync } from "node:fs";
|
|
25
|
+
import { readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
26
|
+
import { promisify } from "node:util";
|
|
24
27
|
|
|
25
28
|
// src/types.ts
|
|
26
29
|
var WORKFLOW_AGENT_STALL_THRESHOLD_MS = 10 * 60 * 1e3;
|
|
@@ -1896,12 +1899,78 @@ minimatch.escape = escape;
|
|
|
1896
1899
|
minimatch.unescape = unescape;
|
|
1897
1900
|
|
|
1898
1901
|
// src/utils.ts
|
|
1902
|
+
function object(value) {
|
|
1903
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1904
|
+
}
|
|
1899
1905
|
var ESCAPE_CHARACTER = String.fromCharCode(27);
|
|
1900
1906
|
var BELL_CHARACTER = String.fromCharCode(7);
|
|
1901
1907
|
var ANSI_ESCAPE_SEQUENCE = new RegExp(`${ESCAPE_CHARACTER}(?:\\[[0-?]*[ -/]*[@-~]|\\][^${BELL_CHARACTER}]*(?:${BELL_CHARACTER}|${ESCAPE_CHARACTER}\\\\))`, "g");
|
|
1902
1908
|
var TERMINAL_CONTROL_CHARACTER = new RegExp(`[${String.fromCharCode(0)}-${String.fromCharCode(31)}${String.fromCharCode(127)}-${String.fromCharCode(159)}]`, "g");
|
|
1909
|
+
function positiveInteger(value) {
|
|
1910
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0;
|
|
1911
|
+
}
|
|
1912
|
+
function isNodeError(error, code) {
|
|
1913
|
+
return object(error) && error.code === code;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
// src/io.ts
|
|
1917
|
+
var execute = promisify(execFile);
|
|
1918
|
+
var RENAME_RETRY_DELAYS_MS = [10, 25, 50, 100, 200, 400, 800];
|
|
1919
|
+
var syncSleepBuffer = new Int32Array(new SharedArrayBuffer(4));
|
|
1920
|
+
function retryableRenameError(error) {
|
|
1921
|
+
return isNodeError(error, "EPERM") || isNodeError(error, "EBUSY") || isNodeError(error, "EACCES");
|
|
1922
|
+
}
|
|
1923
|
+
async function renameWithRetry(from, to) {
|
|
1924
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
1925
|
+
try {
|
|
1926
|
+
await rename(from, to);
|
|
1927
|
+
return;
|
|
1928
|
+
} catch (error) {
|
|
1929
|
+
const delayMs = RENAME_RETRY_DELAYS_MS[attempt];
|
|
1930
|
+
if (!retryableRenameError(error) || delayMs === void 0) throw error;
|
|
1931
|
+
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
function renameSyncWithRetry(from, to) {
|
|
1936
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
1937
|
+
try {
|
|
1938
|
+
renameSync(from, to);
|
|
1939
|
+
return;
|
|
1940
|
+
} catch (error) {
|
|
1941
|
+
const delayMs = RENAME_RETRY_DELAYS_MS[attempt];
|
|
1942
|
+
if (!retryableRenameError(error) || delayMs === void 0) throw error;
|
|
1943
|
+
Atomics.wait(syncSleepBuffer, 0, 0, delayMs);
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
function atomicWriteFile(path2, content, sync = false) {
|
|
1948
|
+
const temporary = `${path2}.${String(process.pid)}.${randomUUID()}.tmp`;
|
|
1949
|
+
if (sync) {
|
|
1950
|
+
try {
|
|
1951
|
+
writeFileSync(temporary, content, { encoding: "utf8", mode: 384 });
|
|
1952
|
+
renameSyncWithRetry(temporary, path2);
|
|
1953
|
+
} catch (error) {
|
|
1954
|
+
try {
|
|
1955
|
+
rmSync(temporary, { force: true });
|
|
1956
|
+
} catch {
|
|
1957
|
+
}
|
|
1958
|
+
throw error;
|
|
1959
|
+
}
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
return writeFile(temporary, content, { encoding: "utf8", mode: 384 }).then(() => renameWithRetry(temporary, path2)).catch(async (error) => {
|
|
1963
|
+
try {
|
|
1964
|
+
await rm(temporary, { force: true });
|
|
1965
|
+
} catch {
|
|
1966
|
+
}
|
|
1967
|
+
throw error;
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1903
1970
|
|
|
1904
1971
|
// src/paths.ts
|
|
1972
|
+
import { realpathSync } from "node:fs";
|
|
1973
|
+
import { basename, isAbsolute, join, relative, resolve, sep as sep2 } from "node:path";
|
|
1905
1974
|
function canonicalPath(path2) {
|
|
1906
1975
|
const absolute = resolve(path2);
|
|
1907
1976
|
try {
|
|
@@ -1914,6 +1983,137 @@ function sameFilesystemPath(left, right) {
|
|
|
1914
1983
|
return canonicalPath(left) === canonicalPath(right);
|
|
1915
1984
|
}
|
|
1916
1985
|
|
|
1986
|
+
// trajectory/src/startup-mutex.ts
|
|
1987
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
1988
|
+
import { readFileSync } from "node:fs";
|
|
1989
|
+
import { mkdir, readdir, readFile as readFile2, rm as rm2 } from "node:fs/promises";
|
|
1990
|
+
import { join as join2 } from "node:path";
|
|
1991
|
+
var bootId;
|
|
1992
|
+
function processStart(pid) {
|
|
1993
|
+
if (process.platform !== "linux") return void 0;
|
|
1994
|
+
try {
|
|
1995
|
+
bootId ??= readFileSync("/proc/sys/kernel/random/boot_id", "utf8").trim();
|
|
1996
|
+
const stat = readFileSync(`/proc/${String(pid)}/stat`, "utf8");
|
|
1997
|
+
const startTicks = stat.slice(stat.lastIndexOf(")") + 2).split(" ")[19];
|
|
1998
|
+
return startTicks === void 0 || !/^\d+$/.test(startTicks) ? void 0 : `${bootId}:${startTicks}`;
|
|
1999
|
+
} catch {
|
|
2000
|
+
return void 0;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
function processLive(identity) {
|
|
2004
|
+
try {
|
|
2005
|
+
process.kill(identity.pid, 0);
|
|
2006
|
+
} catch (error) {
|
|
2007
|
+
if (isNodeError(error, "ESRCH")) return false;
|
|
2008
|
+
}
|
|
2009
|
+
if (identity.start === void 0) return true;
|
|
2010
|
+
const current = processStart(identity.pid);
|
|
2011
|
+
return current === void 0 || current === identity.start;
|
|
2012
|
+
}
|
|
2013
|
+
function processConfirmed(identity) {
|
|
2014
|
+
return identity.start !== void 0 && processStart(identity.pid) === identity.start;
|
|
2015
|
+
}
|
|
2016
|
+
function holderDirectory(lockPath) {
|
|
2017
|
+
return `${lockPath}.startup`;
|
|
2018
|
+
}
|
|
2019
|
+
function holderPath(lockPath, token) {
|
|
2020
|
+
return join2(holderDirectory(lockPath), `${token}.json`);
|
|
2021
|
+
}
|
|
2022
|
+
function identityOf(pid) {
|
|
2023
|
+
const start = processStart(pid);
|
|
2024
|
+
return start === void 0 ? { pid } : { pid, start };
|
|
2025
|
+
}
|
|
2026
|
+
function processIdentity(value) {
|
|
2027
|
+
if (!object(value) || !positiveInteger(value.pid)) return void 0;
|
|
2028
|
+
return typeof value.start === "string" ? { pid: value.pid, start: value.start } : { pid: value.pid };
|
|
2029
|
+
}
|
|
2030
|
+
function decodeHolder(text) {
|
|
2031
|
+
try {
|
|
2032
|
+
const parsed = JSON.parse(text);
|
|
2033
|
+
const holder = processIdentity(parsed);
|
|
2034
|
+
if (holder === void 0 || !object(parsed) || typeof parsed.token !== "string") return void 0;
|
|
2035
|
+
const server = processIdentity(parsed.server);
|
|
2036
|
+
return { ...holder, token: parsed.token, ...server === void 0 ? {} : { server } };
|
|
2037
|
+
} catch {
|
|
2038
|
+
return void 0;
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
function readStartupHolder(lockPath, token) {
|
|
2042
|
+
try {
|
|
2043
|
+
return decodeHolder(readFileSync(holderPath(lockPath, token), "utf8"));
|
|
2044
|
+
} catch (error) {
|
|
2045
|
+
if (isNodeError(error, "ENOENT")) return void 0;
|
|
2046
|
+
throw error;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
async function serverPending(lockPath, server) {
|
|
2050
|
+
if (!processLive(server)) return false;
|
|
2051
|
+
let text;
|
|
2052
|
+
try {
|
|
2053
|
+
text = await readFile2(lockPath, "utf8");
|
|
2054
|
+
} catch (error) {
|
|
2055
|
+
if (isNodeError(error, "ENOENT")) return true;
|
|
2056
|
+
throw error;
|
|
2057
|
+
}
|
|
2058
|
+
try {
|
|
2059
|
+
const lock = JSON.parse(text);
|
|
2060
|
+
return !(object(lock) && lock.pid === server.pid);
|
|
2061
|
+
} catch {
|
|
2062
|
+
return true;
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
async function holderLive(lockPath, path2, read) {
|
|
2066
|
+
if (processLive(read)) return true;
|
|
2067
|
+
let holder;
|
|
2068
|
+
try {
|
|
2069
|
+
holder = decodeHolder(await readFile2(path2, "utf8"));
|
|
2070
|
+
} catch (error) {
|
|
2071
|
+
if (isNodeError(error, "ENOENT")) return false;
|
|
2072
|
+
throw error;
|
|
2073
|
+
}
|
|
2074
|
+
if (holder?.server === void 0 || !await serverPending(lockPath, holder.server)) return false;
|
|
2075
|
+
if (!processConfirmed(holder.server)) return true;
|
|
2076
|
+
try {
|
|
2077
|
+
process.kill(holder.server.pid, "SIGKILL");
|
|
2078
|
+
} catch (error) {
|
|
2079
|
+
if (!isNodeError(error, "ESRCH")) throw error;
|
|
2080
|
+
}
|
|
2081
|
+
return true;
|
|
2082
|
+
}
|
|
2083
|
+
async function tryAcquireStartupMutex(lockPath) {
|
|
2084
|
+
const directory = holderDirectory(lockPath);
|
|
2085
|
+
await mkdir(directory, { recursive: true, mode: 448 });
|
|
2086
|
+
const token = randomUUID2();
|
|
2087
|
+
const own = `${token}.json`;
|
|
2088
|
+
await atomicWriteFile(join2(directory, own), `${JSON.stringify({ ...identityOf(process.pid), token })}
|
|
2089
|
+
`);
|
|
2090
|
+
let contended = false;
|
|
2091
|
+
try {
|
|
2092
|
+
for (const name of await readdir(directory)) {
|
|
2093
|
+
if (name === own || !name.endsWith(".json")) continue;
|
|
2094
|
+
const path2 = join2(directory, name);
|
|
2095
|
+
let holder;
|
|
2096
|
+
try {
|
|
2097
|
+
holder = decodeHolder(await readFile2(path2, "utf8"));
|
|
2098
|
+
} catch (error) {
|
|
2099
|
+
if (isNodeError(error, "ENOENT")) continue;
|
|
2100
|
+
throw error;
|
|
2101
|
+
}
|
|
2102
|
+
if (holder !== void 0 && await holderLive(lockPath, path2, holder)) contended = true;
|
|
2103
|
+
else await rm2(path2, { force: true });
|
|
2104
|
+
}
|
|
2105
|
+
} catch (error) {
|
|
2106
|
+
await rm2(join2(directory, own), { force: true });
|
|
2107
|
+
throw error;
|
|
2108
|
+
}
|
|
2109
|
+
if (!contended) return token;
|
|
2110
|
+
await rm2(join2(directory, own), { force: true });
|
|
2111
|
+
return void 0;
|
|
2112
|
+
}
|
|
2113
|
+
async function releaseStartupMutex(lockPath, token) {
|
|
2114
|
+
await rm2(holderPath(lockPath, token), { force: true });
|
|
2115
|
+
}
|
|
2116
|
+
|
|
1917
2117
|
// src/tool-timing.ts
|
|
1918
2118
|
var TOOL_TIMING_ENTRY_TYPE = "pi-workflows:tool-timing";
|
|
1919
2119
|
|
|
@@ -2233,7 +2433,7 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2233
2433
|
return requests;
|
|
2234
2434
|
};
|
|
2235
2435
|
const hasPendingRequest = (requests, requestId) => [...requests.values()].some((request) => request.requestId === requestId);
|
|
2236
|
-
const publisherRequestIdFor = (requestId) => [...pending.values()].some((requests) => requests.has(requestId)) ?
|
|
2436
|
+
const publisherRequestIdFor = (requestId) => [...pending.values()].some((requests) => requests.has(requestId)) ? randomUUID3() : requestId;
|
|
2237
2437
|
const errorResponse = (_publisherRequestId, request, status, error) => request.kind === "action" ? { type: "action-result", requestId: request.requestId, ok: false, error } : { type: "transcript", requestId: request.requestId, publisherId: request.publisherId, ...request.target.runId === void 0 ? {} : { runId: request.target.runId }, ...request.target.agentId === void 0 ? {} : { agentId: request.target.agentId }, ...request.target.subagentId === void 0 ? {} : { subagentId: request.target.subagentId }, ok: false, status, revision: request.target.revision ?? 0, error };
|
|
2238
2438
|
const clearPending = (client, error) => {
|
|
2239
2439
|
const own = pending.get(client);
|
|
@@ -2262,21 +2462,45 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2262
2462
|
if (!requests.size) pending.delete(browser);
|
|
2263
2463
|
emit(browser, errorResponse(requestId, request, "failed", error));
|
|
2264
2464
|
};
|
|
2465
|
+
const busy = () => closed || [...publishers.values()].some(({ value }) => value.connected === true);
|
|
2265
2466
|
const scheduleIdleExit = () => {
|
|
2266
|
-
if (
|
|
2467
|
+
if (busy() || idleTimer !== void 0) return;
|
|
2267
2468
|
idleTimer = setTimeout(() => {
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
}
|
|
2274
|
-
|
|
2469
|
+
idleTimer = void 0;
|
|
2470
|
+
void tryAcquireStartupMutex(lockPath).then(async (token) => {
|
|
2471
|
+
if (token === void 0) {
|
|
2472
|
+
scheduleIdleExit();
|
|
2473
|
+
return;
|
|
2474
|
+
}
|
|
2475
|
+
if (busy() || idleTimer !== void 0) {
|
|
2476
|
+
await releaseStartupMutex(lockPath, token);
|
|
2477
|
+
return;
|
|
2478
|
+
}
|
|
2479
|
+
server.closeAllConnections();
|
|
2480
|
+
for (const client of clients) client.socket.destroy();
|
|
2481
|
+
server.close(() => {
|
|
2482
|
+
void removeOwnLock().then(() => releaseStartupMutex(lockPath, token)).then(() => {
|
|
2483
|
+
process.exit(0);
|
|
2484
|
+
}).catch(() => {
|
|
2485
|
+
process.exit(1);
|
|
2486
|
+
});
|
|
2275
2487
|
});
|
|
2488
|
+
}).catch(() => {
|
|
2489
|
+
process.exit(1);
|
|
2276
2490
|
});
|
|
2277
2491
|
}, TRAJECTORY_IDLE_EXIT_MS);
|
|
2278
2492
|
idleTimer.unref();
|
|
2279
2493
|
};
|
|
2494
|
+
const removeOwnLock = async () => {
|
|
2495
|
+
let current;
|
|
2496
|
+
try {
|
|
2497
|
+
current = JSON.parse(await readFile3(lockPath, "utf8"));
|
|
2498
|
+
} catch (error) {
|
|
2499
|
+
if (isNodeError(error, "ENOENT")) return;
|
|
2500
|
+
throw error;
|
|
2501
|
+
}
|
|
2502
|
+
if (object(current) && current.pid === process.pid && current.startedAt === startedAt) await rm3(lockPath, { force: true });
|
|
2503
|
+
};
|
|
2280
2504
|
const cancelIdleExit = () => {
|
|
2281
2505
|
if (idleTimer !== void 0) {
|
|
2282
2506
|
clearTimeout(idleTimer);
|
|
@@ -2423,7 +2647,7 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2423
2647
|
const runRequest = validId(message.runId) && validId(message.agentId) && message.subagentId === void 0;
|
|
2424
2648
|
const subagentRequest = validId(message.subagentId) && message.runId === void 0 && message.agentId === void 0;
|
|
2425
2649
|
if (!runRequest && !subagentRequest) return;
|
|
2426
|
-
const requestId2 = validId(message.requestId) ? message.requestId :
|
|
2650
|
+
const requestId2 = validId(message.requestId) ? message.requestId : randomUUID3();
|
|
2427
2651
|
const revision = message.revision === void 0 ? void 0 : typeof message.revision === "number" && Number.isSafeInteger(message.revision) && message.revision >= 0 ? message.revision : void 0;
|
|
2428
2652
|
const target2 = publishers.get(message.publisherId);
|
|
2429
2653
|
if (!target2 || !target2.value.connected) {
|
|
@@ -2471,7 +2695,7 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2471
2695
|
return;
|
|
2472
2696
|
}
|
|
2473
2697
|
if (client.kind !== "browser" || message.type !== "ui:action" || typeof message.publisherId !== "string") return;
|
|
2474
|
-
const requestId = typeof message.requestId === "string" && message.requestId.length >= 1 && message.requestId.length <= 200 ? message.requestId :
|
|
2698
|
+
const requestId = typeof message.requestId === "string" && message.requestId.length >= 1 && message.requestId.length <= 200 ? message.requestId : randomUUID3();
|
|
2475
2699
|
if (!isTrajectoryAction(message.action)) {
|
|
2476
2700
|
emit(client, { type: "action-result", requestId, ok: false, error: "Unsupported Trajectory action" });
|
|
2477
2701
|
return;
|
|
@@ -2525,7 +2749,7 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2525
2749
|
return;
|
|
2526
2750
|
}
|
|
2527
2751
|
if (request.method === "GET" && (path2 === "/" || path2 === "/index.html")) {
|
|
2528
|
-
void
|
|
2752
|
+
void readFile3(new URL("./assets/index.html", import.meta.url)).then((html) => {
|
|
2529
2753
|
response.writeHead(200, { "content-type": "text/html; charset=utf-8", "content-length": html.byteLength, "cache-control": "no-store" });
|
|
2530
2754
|
response.end(html);
|
|
2531
2755
|
}).catch(() => {
|
|
@@ -2534,7 +2758,7 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2534
2758
|
return;
|
|
2535
2759
|
}
|
|
2536
2760
|
if (request.method === "GET" && path2 === "/marked.min.js") {
|
|
2537
|
-
void
|
|
2761
|
+
void readFile3(new URL("./assets/marked.min.js", import.meta.url)).then((script) => {
|
|
2538
2762
|
response.writeHead(200, { "content-type": "application/javascript; charset=utf-8", "content-length": script.byteLength, "cache-control": "no-store" });
|
|
2539
2763
|
response.end(script);
|
|
2540
2764
|
}).catch(() => {
|
|
@@ -2543,7 +2767,7 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2543
2767
|
return;
|
|
2544
2768
|
}
|
|
2545
2769
|
if (request.method === "GET" && path2 === "/morphdom.min.js") {
|
|
2546
|
-
void
|
|
2770
|
+
void readFile3(new URL("./assets/morphdom.min.js", import.meta.url)).then((script) => {
|
|
2547
2771
|
response.writeHead(200, { "content-type": "application/javascript; charset=utf-8", "content-length": script.byteLength, "cache-control": "no-store" });
|
|
2548
2772
|
response.end(script);
|
|
2549
2773
|
}).catch(() => {
|
|
@@ -2552,7 +2776,7 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2552
2776
|
return;
|
|
2553
2777
|
}
|
|
2554
2778
|
if (request.method === "GET" && path2 === "/prism.min.js") {
|
|
2555
|
-
void
|
|
2779
|
+
void readFile3(new URL("./assets/prism.min.js", import.meta.url)).then((script) => {
|
|
2556
2780
|
response.writeHead(200, { "content-type": "application/javascript; charset=utf-8", "content-length": script.byteLength, "cache-control": "no-store" });
|
|
2557
2781
|
response.end(script);
|
|
2558
2782
|
}).catch(() => {
|
|
@@ -2561,7 +2785,7 @@ function createTrajectoryServer(port, lockPath, options = {}) {
|
|
|
2561
2785
|
return;
|
|
2562
2786
|
}
|
|
2563
2787
|
if (request.method === "GET" && (path2 === "/favicon.png" || path2 === "/favicon.ico")) {
|
|
2564
|
-
void
|
|
2788
|
+
void readFile3(new URL("./assets/favicon.png", import.meta.url)).then((icon) => {
|
|
2565
2789
|
response.writeHead(200, { "content-type": "image/png", "content-length": icon.byteLength, "cache-control": "no-store" });
|
|
2566
2790
|
response.end(icon);
|
|
2567
2791
|
}).catch(() => {
|
|
@@ -2621,10 +2845,14 @@ Sec-WebSocket-Accept: ${accept}\r
|
|
|
2621
2845
|
});
|
|
2622
2846
|
server.once("listening", () => {
|
|
2623
2847
|
startedAt = Date.now();
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
})
|
|
2848
|
+
try {
|
|
2849
|
+
atomicWriteFile(lockPath, `${JSON.stringify({ pid: process.pid, port, fingerprint: serverFingerprint, startedAt, start: processStart(process.pid) })}
|
|
2850
|
+
`, true);
|
|
2851
|
+
} catch (error) {
|
|
2852
|
+
server.close();
|
|
2853
|
+
server.emit("error", error);
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2628
2856
|
scheduleIdleExit();
|
|
2629
2857
|
});
|
|
2630
2858
|
server.on("close", () => {
|
|
@@ -2636,13 +2864,24 @@ Sec-WebSocket-Accept: ${accept}\r
|
|
|
2636
2864
|
});
|
|
2637
2865
|
return server;
|
|
2638
2866
|
}
|
|
2867
|
+
async function awaitStartupRecord(lockPath, token) {
|
|
2868
|
+
for (let attempt = 0; attempt < 60; attempt += 1) {
|
|
2869
|
+
const holder = readStartupHolder(lockPath, token);
|
|
2870
|
+
if (holder === void 0) break;
|
|
2871
|
+
if (holder.server?.pid === process.pid) return;
|
|
2872
|
+
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
2873
|
+
}
|
|
2874
|
+
throw new Error("Trajectory startup was abandoned before the server listened");
|
|
2875
|
+
}
|
|
2639
2876
|
async function main() {
|
|
2640
2877
|
const args = /* @__PURE__ */ new Map();
|
|
2641
2878
|
for (let index = 2; index + 1 < process.argv.length; index += 2) args.set(process.argv[index] ?? "", process.argv[index + 1] ?? "");
|
|
2642
2879
|
const port = Number(args.get("--port"));
|
|
2643
2880
|
const lockPath = args.get("--lock");
|
|
2644
2881
|
const fingerprint = args.get("--fingerprint");
|
|
2882
|
+
const startupToken = args.get("--startup");
|
|
2645
2883
|
if (!Number.isSafeInteger(port) || port < 1 || port > 65535 || !lockPath || !fingerprint) throw new Error("Invalid Trajectory server arguments");
|
|
2884
|
+
if (startupToken !== void 0) await awaitStartupRecord(lockPath, startupToken);
|
|
2646
2885
|
const server = createTrajectoryServer(port, lockPath, { fingerprint });
|
|
2647
2886
|
await new Promise((resolve2, reject) => {
|
|
2648
2887
|
server.once("error", reject);
|