@mlola/browser-daemon 0.1.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/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/bin.d.ts +6 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +29 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli-args.d.ts +7 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +28 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/client.d.ts +45 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +158 -0
- package/dist/client.js.map +1 -0
- package/dist/human.d.ts +25 -0
- package/dist/human.d.ts.map +1 -0
- package/dist/human.js +43 -0
- package/dist/human.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +320 -0
- package/dist/server.js.map +1 -0
- package/dist/state.d.ts +23 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +77 -0
- package/dist/state.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MLola
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @mlola/browser-daemon
|
|
2
|
+
|
|
3
|
+
`mlola-browserd`: the local daemon of the
|
|
4
|
+
[MLola Browser Runtime](https://mlola.com/browser-runtime). Owns detached runs,
|
|
5
|
+
the run/event registry, approvals, human help and artifacts behind a
|
|
6
|
+
token-protected HTTP API bound to 127.0.0.1.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx mlola-browserd --port 7717
|
|
10
|
+
curl -s localhost:7717/v1/health
|
|
11
|
+
```
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;GAEG"}
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* mlola-browserd — the local browser runtime daemon.
|
|
4
|
+
*/
|
|
5
|
+
import { parseArgs } from "./cli-args.js";
|
|
6
|
+
import { BrowserDaemon } from "./server.js";
|
|
7
|
+
import { DEFAULT_DAEMON_PORT } from "./state.js";
|
|
8
|
+
import { resolveHome } from "@mlola/browser-trace";
|
|
9
|
+
const main = async () => {
|
|
10
|
+
const { flags } = parseArgs(process.argv.slice(2));
|
|
11
|
+
const portFlag = flags["port"];
|
|
12
|
+
const port = typeof portFlag === "string" ? Number(portFlag) : DEFAULT_DAEMON_PORT;
|
|
13
|
+
const home = typeof flags["home"] === "string" ? flags["home"] : resolveHome();
|
|
14
|
+
const daemon = new BrowserDaemon({ port: Number.isFinite(port) ? port : DEFAULT_DAEMON_PORT, home });
|
|
15
|
+
const { url } = await daemon.start();
|
|
16
|
+
process.stdout.write(`mlola-browserd listening on ${url} (home ${home})\n`);
|
|
17
|
+
const shutdown = async (signal) => {
|
|
18
|
+
process.stdout.write(`mlola-browserd: ${signal}, stopping\n`);
|
|
19
|
+
await daemon.stop();
|
|
20
|
+
process.exit(0);
|
|
21
|
+
};
|
|
22
|
+
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
23
|
+
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
24
|
+
};
|
|
25
|
+
main().catch((error) => {
|
|
26
|
+
process.stderr.write(`mlola-browserd failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;IACrC,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC;IACnF,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAE/E,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;IACrG,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAErC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,GAAG,UAAU,IAAI,KAAK,CAAC,CAAC;IAE5E,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAiB,EAAE;QACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,MAAM,cAAc,CAAC,CAAC;QAC9D,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Argument parsing for the daemon process (no CLI dependency). */
|
|
2
|
+
export interface DaemonArgs {
|
|
3
|
+
flags: Record<string, string | boolean>;
|
|
4
|
+
positional: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare const parseArgs: (argv: string[]) => DaemonArgs;
|
|
7
|
+
//# sourceMappingURL=cli-args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;IACxC,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,KAAG,UAwB1C,CAAC"}
|
package/dist/cli-args.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Argument parsing for the daemon process (no CLI dependency). */
|
|
2
|
+
export const parseArgs = (argv) => {
|
|
3
|
+
const flags = {};
|
|
4
|
+
const positional = [];
|
|
5
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
6
|
+
const arg = argv[i];
|
|
7
|
+
if (arg.startsWith("--")) {
|
|
8
|
+
const eq = arg.indexOf("=");
|
|
9
|
+
if (eq > 0) {
|
|
10
|
+
flags[arg.slice(2, eq)] = arg.slice(eq + 1);
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
const key = arg.slice(2);
|
|
14
|
+
const next = argv[i + 1];
|
|
15
|
+
if (next !== undefined && !next.startsWith("-")) {
|
|
16
|
+
flags[key] = next;
|
|
17
|
+
i += 1;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
flags[key] = true;
|
|
21
|
+
}
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
positional.push(arg);
|
|
25
|
+
}
|
|
26
|
+
return { flags, positional };
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=cli-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAOnE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAc,EAAc,EAAE;IACtD,MAAM,KAAK,GAAqC,EAAE,CAAC;IACnD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;gBACX,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC5C,SAAS;YACX,CAAC;YACD,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChD,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;gBAClB,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACpB,CAAC;YACD,SAAS;QACX,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon client: lifecycle helpers and the typed local API client.
|
|
3
|
+
*/
|
|
4
|
+
import type { RunEvent, RunResult, TaskSpec } from "@mlola/browser-protocol";
|
|
5
|
+
import { type DaemonState } from "./state.ts";
|
|
6
|
+
export interface DaemonStatusResult {
|
|
7
|
+
running: boolean;
|
|
8
|
+
version?: string;
|
|
9
|
+
protocol?: string;
|
|
10
|
+
sessions?: number;
|
|
11
|
+
port?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare const daemonStatus: (home?: string) => Promise<DaemonStatusResult>;
|
|
14
|
+
export declare const startDaemon: (options?: {
|
|
15
|
+
port?: number;
|
|
16
|
+
foreground?: boolean;
|
|
17
|
+
home?: string;
|
|
18
|
+
}) => Promise<{
|
|
19
|
+
started: boolean;
|
|
20
|
+
url: string;
|
|
21
|
+
pid: number;
|
|
22
|
+
tokenPath: string;
|
|
23
|
+
}>;
|
|
24
|
+
export declare const stopDaemon: (home?: string) => Promise<{
|
|
25
|
+
stopped: boolean;
|
|
26
|
+
forced?: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
export declare const daemonFetch: <T>(state: DaemonState, method: "GET" | "POST", path: string, body?: unknown, home?: string) => Promise<T>;
|
|
29
|
+
export interface DaemonRunClient {
|
|
30
|
+
runId: string;
|
|
31
|
+
status: string;
|
|
32
|
+
result?: RunResult;
|
|
33
|
+
pendingHelp: string[];
|
|
34
|
+
error?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare const createRunViaDaemon: (task: TaskSpec, home?: string) => Promise<DaemonRunClient>;
|
|
37
|
+
export declare const getRunViaDaemon: (runId: string, home?: string) => Promise<DaemonRunClient>;
|
|
38
|
+
export declare const listRunEventsViaDaemon: (runId: string, since?: number, home?: string) => Promise<{
|
|
39
|
+
events: RunEvent[];
|
|
40
|
+
lastSeq: number;
|
|
41
|
+
}>;
|
|
42
|
+
export declare const cancelRunViaDaemon: (runId: string, home?: string) => Promise<void>;
|
|
43
|
+
export declare const resolveHelpViaDaemon: (runId: string, helpId: string, resolution: "completed" | "cancelled" | "takeover", home?: string) => Promise<void>;
|
|
44
|
+
export declare const resolveApprovalViaDaemon: (runId: string, approvalId: string, resolution: "approved" | "denied" | "takeover", home?: string) => Promise<void>;
|
|
45
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAE7E,OAAO,EAOL,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,YAAY,GAAU,aAAoB,KAAG,OAAO,CAAC,kBAAkB,CAmBnF,CAAC;AAEF,eAAO,MAAM,WAAW,GACtB,UAAS;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,KACnE,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAwC3E,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,aAAoB,KAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CA4CrG,CAAC;AAIF,eAAO,MAAM,WAAW,GAAU,CAAC,EACjC,OAAO,WAAW,EAClB,QAAQ,KAAK,GAAG,MAAM,EACtB,MAAM,MAAM,EACZ,OAAO,OAAO,EACd,aAAoB,KACnB,OAAO,CAAC,CAAC,CAgBX,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,kBAAkB,GAAU,MAAM,QAAQ,EAAE,aAAoB,KAAG,OAAO,CAAC,eAAe,CAGtG,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,OAAO,MAAM,EAAE,aAAoB,KAAG,OAAO,CAAC,eAAe,CAGlG,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,OAAO,MAAM,EACb,cAAS,EACT,aAAoB,KACnB,OAAO,CAAC;IAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CASjD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,OAAO,MAAM,EAAE,aAAoB,KAAG,OAAO,CAAC,IAAI,CAG1F,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,YAAY,WAAW,GAAG,WAAW,GAAG,UAAU,EAClD,aAAoB,KACnB,OAAO,CAAC,IAAI,CAGd,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,OAAO,MAAM,EACb,YAAY,MAAM,EAClB,YAAY,UAAU,GAAG,QAAQ,GAAG,UAAU,EAC9C,aAAoB,KACnB,OAAO,CAAC,IAAI,CAGd,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon client: lifecycle helpers and the typed local API client.
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
|
+
import { resolveHome } from "@mlola/browser-trace";
|
|
8
|
+
import { DEFAULT_DAEMON_PORT, clearDaemonState, daemonStatePath, isProcessAlive, readDaemonState, readToken, } from "./state.js";
|
|
9
|
+
export const daemonStatus = async (home = resolveHome()) => {
|
|
10
|
+
const state = readDaemonState(home);
|
|
11
|
+
if (!state || !isProcessAlive(state.pid))
|
|
12
|
+
return { running: false };
|
|
13
|
+
try {
|
|
14
|
+
const health = await daemonFetch(state, "GET", "/v1/health");
|
|
15
|
+
return {
|
|
16
|
+
running: health.status === "ok",
|
|
17
|
+
version: health.version,
|
|
18
|
+
protocol: health.protocol,
|
|
19
|
+
sessions: health.sessions,
|
|
20
|
+
port: state.port,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return { running: false, port: state.port };
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export const startDaemon = async (options = {}) => {
|
|
28
|
+
const home = options.home ?? resolveHome();
|
|
29
|
+
const existing = await daemonStatus(home);
|
|
30
|
+
if (existing.running) {
|
|
31
|
+
const state = readDaemonState(home);
|
|
32
|
+
return { started: false, url: state.url, pid: state.pid, tokenPath: state.tokenPath };
|
|
33
|
+
}
|
|
34
|
+
const port = options.port ?? DEFAULT_DAEMON_PORT;
|
|
35
|
+
const here = fileURLToPath(import.meta.url);
|
|
36
|
+
const extension = here.endsWith(".ts") ? ".ts" : ".js";
|
|
37
|
+
const binPath = join(dirname(here), `bin${extension}`);
|
|
38
|
+
const child = spawn(process.execPath, [binPath, "--port", String(port), ...(options.foreground ? ["--foreground"] : [])], {
|
|
39
|
+
detached: !options.foreground,
|
|
40
|
+
stdio: options.foreground ? "inherit" : "ignore",
|
|
41
|
+
env: { ...process.env, MLOLA_HOME: home },
|
|
42
|
+
});
|
|
43
|
+
if (!options.foreground)
|
|
44
|
+
child.unref();
|
|
45
|
+
// Wait for the daemon to answer on its health endpoint.
|
|
46
|
+
const deadline = Date.now() + 15_000;
|
|
47
|
+
while (Date.now() < deadline) {
|
|
48
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
49
|
+
const state = readDaemonState(home);
|
|
50
|
+
if (!state)
|
|
51
|
+
continue;
|
|
52
|
+
try {
|
|
53
|
+
const health = await daemonFetch(state, "GET", "/v1/health");
|
|
54
|
+
if (health.status === "ok") {
|
|
55
|
+
return { started: true, url: state.url, pid: state.pid, tokenPath: state.tokenPath };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
/* keep waiting */
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`daemon did not become healthy within 15s (bin: ${binPath})`);
|
|
63
|
+
};
|
|
64
|
+
export const stopDaemon = async (home = resolveHome()) => {
|
|
65
|
+
const state = readDaemonState(home);
|
|
66
|
+
if (!state)
|
|
67
|
+
return { stopped: false };
|
|
68
|
+
if (!isProcessAlive(state.pid)) {
|
|
69
|
+
clearDaemonState(home);
|
|
70
|
+
return { stopped: false };
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
await daemonFetch(state, "POST", "/v1/shutdown");
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
/* fall through to signals */
|
|
77
|
+
}
|
|
78
|
+
const gracefulDeadline = Date.now() + 5000;
|
|
79
|
+
while (Date.now() < gracefulDeadline) {
|
|
80
|
+
if (!isProcessAlive(state.pid)) {
|
|
81
|
+
clearDaemonState(home);
|
|
82
|
+
return { stopped: true };
|
|
83
|
+
}
|
|
84
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
process.kill(state.pid, "SIGTERM");
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
/* already gone */
|
|
91
|
+
}
|
|
92
|
+
const killDeadline = Date.now() + 3000;
|
|
93
|
+
while (Date.now() < killDeadline) {
|
|
94
|
+
if (!isProcessAlive(state.pid)) {
|
|
95
|
+
clearDaemonState(home);
|
|
96
|
+
return { stopped: true };
|
|
97
|
+
}
|
|
98
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
process.kill(state.pid, "SIGKILL");
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
/* already gone */
|
|
105
|
+
}
|
|
106
|
+
clearDaemonState(home);
|
|
107
|
+
return { stopped: true, forced: true };
|
|
108
|
+
};
|
|
109
|
+
/* ─────────────────────────────── typed API ───────────────────────────────── */
|
|
110
|
+
export const daemonFetch = async (state, method, path, body, home = resolveHome()) => {
|
|
111
|
+
const token = readToken(home);
|
|
112
|
+
if (!token)
|
|
113
|
+
throw new Error(`daemon token not found at ${state.tokenPath}`);
|
|
114
|
+
const response = await fetch(`${state.url}${path}`, {
|
|
115
|
+
method,
|
|
116
|
+
headers: {
|
|
117
|
+
authorization: `Bearer ${token}`,
|
|
118
|
+
...(body !== undefined ? { "content-type": "application/json" } : {}),
|
|
119
|
+
},
|
|
120
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
121
|
+
});
|
|
122
|
+
const text = await response.text();
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
throw new Error(`daemon ${method} ${path} failed (${response.status}): ${text.slice(0, 300)}`);
|
|
125
|
+
}
|
|
126
|
+
return (text.length > 0 ? JSON.parse(text) : {});
|
|
127
|
+
};
|
|
128
|
+
export const createRunViaDaemon = async (task, home = resolveHome()) => {
|
|
129
|
+
const state = requireState(home);
|
|
130
|
+
return daemonFetch(state, "POST", "/v1/runs", task, home);
|
|
131
|
+
};
|
|
132
|
+
export const getRunViaDaemon = async (runId, home = resolveHome()) => {
|
|
133
|
+
const state = requireState(home);
|
|
134
|
+
return daemonFetch(state, "GET", `/v1/runs/${runId}`, undefined, home);
|
|
135
|
+
};
|
|
136
|
+
export const listRunEventsViaDaemon = async (runId, since = 0, home = resolveHome()) => {
|
|
137
|
+
const state = requireState(home);
|
|
138
|
+
return daemonFetch(state, "GET", `/v1/runs/${runId}/events?since=${since}`, undefined, home);
|
|
139
|
+
};
|
|
140
|
+
export const cancelRunViaDaemon = async (runId, home = resolveHome()) => {
|
|
141
|
+
const state = requireState(home);
|
|
142
|
+
await daemonFetch(state, "POST", `/v1/runs/${runId}/cancel`, {}, home);
|
|
143
|
+
};
|
|
144
|
+
export const resolveHelpViaDaemon = async (runId, helpId, resolution, home = resolveHome()) => {
|
|
145
|
+
const state = requireState(home);
|
|
146
|
+
await daemonFetch(state, "POST", `/v1/runs/${runId}/help/${helpId}`, { resolution }, home);
|
|
147
|
+
};
|
|
148
|
+
export const resolveApprovalViaDaemon = async (runId, approvalId, resolution, home = resolveHome()) => {
|
|
149
|
+
const state = requireState(home);
|
|
150
|
+
await daemonFetch(state, "POST", `/v1/runs/${runId}/approvals/${approvalId}`, { resolution }, home);
|
|
151
|
+
};
|
|
152
|
+
const requireState = (home) => {
|
|
153
|
+
const state = readDaemonState(home);
|
|
154
|
+
if (!state)
|
|
155
|
+
throw new Error(`daemon is not running (no state file at ${daemonStatePath(home)})`);
|
|
156
|
+
return state;
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/human.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote human loop (PRD §19, §59).
|
|
3
|
+
*
|
|
4
|
+
* In daemon mode the person is reached over the local HTTP API: help requests
|
|
5
|
+
* and approvals are queued with their ids and resolved by a client.
|
|
6
|
+
*/
|
|
7
|
+
import type { ApprovalRequest, HumanHelpRequest, HumanHelpResolution } from "@mlola/browser-protocol";
|
|
8
|
+
import { ApprovalBroker } from "@mlola/browser-policy";
|
|
9
|
+
import type { HumanHelpHost } from "@mlola/browser-takeover";
|
|
10
|
+
export declare class RemoteHumanHelpHost implements HumanHelpHost {
|
|
11
|
+
#private;
|
|
12
|
+
constructor(onRequest?: (request: HumanHelpRequest) => void);
|
|
13
|
+
ask(request: HumanHelpRequest): Promise<HumanHelpResolution>;
|
|
14
|
+
resolve(id: string, resolution: HumanHelpResolution): boolean;
|
|
15
|
+
pending(): string[];
|
|
16
|
+
cancelAll(): void;
|
|
17
|
+
}
|
|
18
|
+
export declare class RemoteApprovalBroker extends ApprovalBroker {
|
|
19
|
+
constructor();
|
|
20
|
+
}
|
|
21
|
+
export interface PendingApproval {
|
|
22
|
+
request: ApprovalRequest;
|
|
23
|
+
at: number;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=human.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../src/human.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACtG,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,qBAAa,mBAAoB,YAAW,aAAa;;gBAI3C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI;IAIrD,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAOlE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,mBAAmB,GAAG,OAAO;IAQ7D,OAAO,IAAI,MAAM,EAAE;IAInB,SAAS,IAAI,IAAI;CAMlB;AAED,qBAAa,oBAAqB,SAAQ,cAAc;;CAIvD;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,eAAe,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;CACZ"}
|
package/dist/human.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote human loop (PRD §19, §59).
|
|
3
|
+
*
|
|
4
|
+
* In daemon mode the person is reached over the local HTTP API: help requests
|
|
5
|
+
* and approvals are queued with their ids and resolved by a client.
|
|
6
|
+
*/
|
|
7
|
+
import { ApprovalBroker } from "@mlola/browser-policy";
|
|
8
|
+
export class RemoteHumanHelpHost {
|
|
9
|
+
#pending = new Map();
|
|
10
|
+
#onRequest;
|
|
11
|
+
constructor(onRequest) {
|
|
12
|
+
this.#onRequest = onRequest;
|
|
13
|
+
}
|
|
14
|
+
async ask(request) {
|
|
15
|
+
this.#onRequest?.(request);
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
this.#pending.set(request.id, resolve);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
resolve(id, resolution) {
|
|
21
|
+
const resolve = this.#pending.get(id);
|
|
22
|
+
if (!resolve)
|
|
23
|
+
return false;
|
|
24
|
+
this.#pending.delete(id);
|
|
25
|
+
resolve(resolution);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
pending() {
|
|
29
|
+
return [...this.#pending.keys()];
|
|
30
|
+
}
|
|
31
|
+
cancelAll() {
|
|
32
|
+
for (const [id, resolve] of this.#pending) {
|
|
33
|
+
this.#pending.delete(id);
|
|
34
|
+
resolve("cancelled");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class RemoteApprovalBroker extends ApprovalBroker {
|
|
39
|
+
constructor() {
|
|
40
|
+
super({ timeoutMs: 10 * 60 * 1000 });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=human.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"human.js","sourceRoot":"","sources":["../src/human.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,MAAM,OAAO,mBAAmB;IAC9B,QAAQ,GAAG,IAAI,GAAG,EAAqD,CAAC;IACxE,UAAU,CAAoD;IAE9D,YAAY,SAA+C;QACzD,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAyB;QACjC,IAAI,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,CAAC;QAC3B,OAAO,IAAI,OAAO,CAAsB,CAAC,OAAO,EAAE,EAAE;YAClD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,EAAU,EAAE,UAA+B;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,CAAC,UAAU,CAAC,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,SAAS;QACP,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACzB,OAAO,CAAC,WAAW,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,cAAc;IACtD;QACE,KAAK,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mlola-browserd HTTP server (PRD §47, §59).
|
|
3
|
+
*
|
|
4
|
+
* Local-only JSON API: runs, sessions, events, approvals, human help and
|
|
5
|
+
* artifacts. Bound to 127.0.0.1 and protected by a token file so that other
|
|
6
|
+
* local processes cannot drive a browser session by accident.
|
|
7
|
+
*/
|
|
8
|
+
export interface DaemonOptions {
|
|
9
|
+
port?: number;
|
|
10
|
+
home?: string;
|
|
11
|
+
/** When true, do not write a pid/state file (useful for tests). */
|
|
12
|
+
ephemeral?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class BrowserDaemon {
|
|
15
|
+
#private;
|
|
16
|
+
readonly home: string;
|
|
17
|
+
constructor(options?: DaemonOptions);
|
|
18
|
+
get port(): number;
|
|
19
|
+
get url(): string;
|
|
20
|
+
start(): Promise<{
|
|
21
|
+
port: number;
|
|
22
|
+
url: string;
|
|
23
|
+
}>;
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
get sessions(): number;
|
|
26
|
+
}
|
|
27
|
+
export declare const createDaemon: (options?: DaemonOptions) => BrowserDaemon;
|
|
28
|
+
export declare const ensureDaemonDirs: (home?: string) => void;
|
|
29
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0CH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,aAAa;;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAQV,OAAO,GAAE,aAAkB;IAOvC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAEK,KAAK,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IA8B/C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,IAAI,QAAQ,IAAI,MAAM,CAErB;CA0OF;AAkBD,eAAO,MAAM,YAAY,GAAI,UAAS,aAAkB,KAAG,aAA2C,CAAC;AAEvG,eAAO,MAAM,gBAAgB,GAAI,aAAoB,KAAG,IAEvD,CAAC"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mlola-browserd HTTP server (PRD §47, §59).
|
|
3
|
+
*
|
|
4
|
+
* Local-only JSON API: runs, sessions, events, approvals, human help and
|
|
5
|
+
* artifacts. Bound to 127.0.0.1 and protected by a token file so that other
|
|
6
|
+
* local processes cannot drive a browser session by accident.
|
|
7
|
+
*/
|
|
8
|
+
import { createServer } from "node:http";
|
|
9
|
+
import { mkdirSync } from "node:fs";
|
|
10
|
+
import { PROTOCOL_VERSION, RUNTIME_CAPABILITIES, createRunRequestSchema, formatZodError, approvalResolutionSchema, helpResolutionSchema, } from "@mlola/browser-protocol";
|
|
11
|
+
import { ApprovalBroker } from "@mlola/browser-policy";
|
|
12
|
+
import { BrowserAgent } from "@mlola/browser-runtime";
|
|
13
|
+
import { readRunEvents, readRunSummary, resolveHome } from "@mlola/browser-trace";
|
|
14
|
+
import { DEFAULT_DAEMON_PORT, clearDaemonState, ensureToken, readDaemonState, writeDaemonState, } from "./state.js";
|
|
15
|
+
import { RemoteApprovalBroker, RemoteHumanHelpHost } from "./human.js";
|
|
16
|
+
const VERSION = "0.1.0";
|
|
17
|
+
export class BrowserDaemon {
|
|
18
|
+
home;
|
|
19
|
+
#port;
|
|
20
|
+
#ephemeral;
|
|
21
|
+
#server;
|
|
22
|
+
#token;
|
|
23
|
+
#runs = new Map();
|
|
24
|
+
#startedAt = Date.now();
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
this.home = options.home ?? resolveHome();
|
|
27
|
+
this.#port = options.port ?? DEFAULT_DAEMON_PORT;
|
|
28
|
+
this.#ephemeral = options.ephemeral ?? false;
|
|
29
|
+
this.#token = ensureToken(this.home);
|
|
30
|
+
}
|
|
31
|
+
get port() {
|
|
32
|
+
return this.#port;
|
|
33
|
+
}
|
|
34
|
+
get url() {
|
|
35
|
+
return `http://127.0.0.1:${this.#port}`;
|
|
36
|
+
}
|
|
37
|
+
async start() {
|
|
38
|
+
const server = createServer((req, res) => {
|
|
39
|
+
void this.#handle(req, res);
|
|
40
|
+
});
|
|
41
|
+
this.#server = server;
|
|
42
|
+
await new Promise((resolve, reject) => {
|
|
43
|
+
server.once("error", reject);
|
|
44
|
+
server.listen(this.#port, "127.0.0.1", () => resolve());
|
|
45
|
+
});
|
|
46
|
+
const address = server.address();
|
|
47
|
+
if (address && typeof address === "object")
|
|
48
|
+
this.#port = address.port;
|
|
49
|
+
if (!this.#ephemeral) {
|
|
50
|
+
writeDaemonState({
|
|
51
|
+
pid: process.pid,
|
|
52
|
+
port: this.#port,
|
|
53
|
+
url: this.url,
|
|
54
|
+
startedAt: this.#startedAt,
|
|
55
|
+
tokenPath: ensureTokenPath(this.home),
|
|
56
|
+
version: VERSION,
|
|
57
|
+
}, this.home);
|
|
58
|
+
}
|
|
59
|
+
return { port: this.#port, url: this.url };
|
|
60
|
+
}
|
|
61
|
+
async stop() {
|
|
62
|
+
for (const run of this.#runs.values()) {
|
|
63
|
+
run.agent.stop("daemon shutdown");
|
|
64
|
+
run.human.cancelAll();
|
|
65
|
+
run.approvals.cancelAll("denied");
|
|
66
|
+
}
|
|
67
|
+
if (this.#server) {
|
|
68
|
+
await new Promise((resolve) => this.#server.close(() => resolve()));
|
|
69
|
+
this.#server = undefined;
|
|
70
|
+
}
|
|
71
|
+
if (!this.#ephemeral)
|
|
72
|
+
clearDaemonState(this.home);
|
|
73
|
+
}
|
|
74
|
+
get sessions() {
|
|
75
|
+
return [...this.#runs.values()].filter((run) => run.status === "running").length;
|
|
76
|
+
}
|
|
77
|
+
/* ─────────────────────────────── routing ─────────────────────────────── */
|
|
78
|
+
async #handle(req, res) {
|
|
79
|
+
const url = new URL(req.url ?? "/", this.url);
|
|
80
|
+
const path = url.pathname;
|
|
81
|
+
try {
|
|
82
|
+
// Health is unauthenticated so `doctor` and `status` can probe safely.
|
|
83
|
+
if (req.method === "GET" && path === "/v1/health") {
|
|
84
|
+
return this.#json(res, 200, {
|
|
85
|
+
status: "ok",
|
|
86
|
+
version: VERSION,
|
|
87
|
+
protocol: PROTOCOL_VERSION,
|
|
88
|
+
sessions: this.sessions,
|
|
89
|
+
uptimeMs: Date.now() - this.#startedAt,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (!this.#authorized(req)) {
|
|
93
|
+
return this.#json(res, 401, { error: "unauthorized", detail: "missing or invalid bearer token" });
|
|
94
|
+
}
|
|
95
|
+
if (req.method === "GET" && path === "/v1/meta") {
|
|
96
|
+
const { readDaemonState: _read } = await import("./state.js");
|
|
97
|
+
void _read;
|
|
98
|
+
return this.#json(res, 200, {
|
|
99
|
+
protocol: PROTOCOL_VERSION,
|
|
100
|
+
runtime: RUNTIME_CAPABILITIES,
|
|
101
|
+
version: VERSION,
|
|
102
|
+
port: this.#port,
|
|
103
|
+
home: this.home,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (req.method === "POST" && path === "/v1/runs") {
|
|
107
|
+
const body = await readJson(req);
|
|
108
|
+
const parsed = createRunRequestSchema.safeParse(body);
|
|
109
|
+
if (!parsed.success)
|
|
110
|
+
return this.#json(res, 400, { error: formatZodError(parsed.error, "run request") });
|
|
111
|
+
const created = await this.#createRun(parsed.data);
|
|
112
|
+
return this.#json(res, 202, created);
|
|
113
|
+
}
|
|
114
|
+
if (req.method === "GET" && path === "/v1/runs") {
|
|
115
|
+
return this.#json(res, 200, { runs: this.#listRuns() });
|
|
116
|
+
}
|
|
117
|
+
const runMatch = /^\/v1\/runs\/([^/]+)$/.exec(path);
|
|
118
|
+
if (req.method === "GET" && runMatch) {
|
|
119
|
+
const runId = runMatch[1];
|
|
120
|
+
const active = this.#runs.get(runId);
|
|
121
|
+
const summary = readRunSummary(runId, this.home);
|
|
122
|
+
if (!active && !summary)
|
|
123
|
+
return this.#json(res, 404, { error: `unknown run ${runId}` });
|
|
124
|
+
return this.#json(res, 200, {
|
|
125
|
+
runId,
|
|
126
|
+
status: active?.status ?? summary?.status ?? "unknown",
|
|
127
|
+
goal: active?.goal ?? summary?.reason,
|
|
128
|
+
result: active?.result ?? summary,
|
|
129
|
+
...(active?.error ? { error: active.error } : {}),
|
|
130
|
+
pendingHelp: active?.human.pending() ?? [],
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const eventsMatch = /^\/v1\/runs\/([^/]+)\/events$/.exec(path);
|
|
134
|
+
if (req.method === "GET" && eventsMatch) {
|
|
135
|
+
const runId = eventsMatch[1];
|
|
136
|
+
const since = Number(url.searchParams.get("since") ?? 0);
|
|
137
|
+
const events = readRunEvents(runId, this.home).filter((event) => event.seq > since);
|
|
138
|
+
if (url.searchParams.get("stream") === "1") {
|
|
139
|
+
return this.#stream(res, runId, since);
|
|
140
|
+
}
|
|
141
|
+
return this.#json(res, 200, { events, lastSeq: events[events.length - 1]?.seq ?? since });
|
|
142
|
+
}
|
|
143
|
+
const cancelMatch = /^\/v1\/runs\/([^/]+)\/cancel$/.exec(path);
|
|
144
|
+
if (req.method === "POST" && cancelMatch) {
|
|
145
|
+
const run = this.#runs.get(cancelMatch[1]);
|
|
146
|
+
if (!run)
|
|
147
|
+
return this.#json(res, 404, { error: "unknown or finished run" });
|
|
148
|
+
run.agent.stop("cancelled via daemon API");
|
|
149
|
+
return this.#json(res, 200, { ok: true });
|
|
150
|
+
}
|
|
151
|
+
const helpMatch = /^\/v1\/runs\/([^/]+)\/help\/([^/]+)$/.exec(path);
|
|
152
|
+
if (req.method === "POST" && helpMatch) {
|
|
153
|
+
const run = this.#runs.get(helpMatch[1]);
|
|
154
|
+
if (!run)
|
|
155
|
+
return this.#json(res, 404, { error: "unknown run" });
|
|
156
|
+
const body = await readJson(req);
|
|
157
|
+
const parsed = helpResolutionSchema.safeParse(body);
|
|
158
|
+
if (!parsed.success)
|
|
159
|
+
return this.#json(res, 400, { error: formatZodError(parsed.error, "help resolution") });
|
|
160
|
+
const resolution = parsed.data.resolution === "takeover" ? "takeover" : parsed.data.resolution;
|
|
161
|
+
const ok = run.human.resolve(helpMatch[2], resolution);
|
|
162
|
+
return this.#json(res, ok ? 200 : 404, { ok });
|
|
163
|
+
}
|
|
164
|
+
const approvalMatch = /^\/v1\/runs\/([^/]+)\/approvals\/([^/]+)$/.exec(path);
|
|
165
|
+
if (req.method === "POST" && approvalMatch) {
|
|
166
|
+
const run = this.#runs.get(approvalMatch[1]);
|
|
167
|
+
if (!run)
|
|
168
|
+
return this.#json(res, 404, { error: "unknown run" });
|
|
169
|
+
const body = await readJson(req);
|
|
170
|
+
const parsed = approvalResolutionSchema.safeParse(body);
|
|
171
|
+
if (!parsed.success)
|
|
172
|
+
return this.#json(res, 400, { error: formatZodError(parsed.error, "approval resolution") });
|
|
173
|
+
const ok = run.approvals.resolve(approvalMatch[2], parsed.data.resolution);
|
|
174
|
+
return this.#json(res, ok ? 200 : 404, { ok });
|
|
175
|
+
}
|
|
176
|
+
const artifactsMatch = /^\/v1\/runs\/([^/]+)\/artifacts$/.exec(path);
|
|
177
|
+
if (req.method === "GET" && artifactsMatch) {
|
|
178
|
+
const summary = readRunSummary(artifactsMatch[1], this.home);
|
|
179
|
+
return this.#json(res, 200, { artifacts: summary?.artifacts ?? [] });
|
|
180
|
+
}
|
|
181
|
+
if (req.method === "POST" && path === "/v1/shutdown") {
|
|
182
|
+
this.#json(res, 200, { ok: true });
|
|
183
|
+
setTimeout(() => {
|
|
184
|
+
void this.stop().then(() => process.exit(0));
|
|
185
|
+
}, 50);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
return this.#json(res, 404, { error: `no route for ${req.method} ${path}` });
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
return this.#json(res, 500, {
|
|
192
|
+
error: "internal error",
|
|
193
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
#authorized(req) {
|
|
198
|
+
const header = req.headers["authorization"];
|
|
199
|
+
if (typeof header !== "string")
|
|
200
|
+
return false;
|
|
201
|
+
const token = header.replace(/^Bearer\s+/i, "").trim();
|
|
202
|
+
return token.length > 0 && token === this.#token;
|
|
203
|
+
}
|
|
204
|
+
#json(res, status, payload) {
|
|
205
|
+
const body = JSON.stringify(payload);
|
|
206
|
+
res.writeHead(status, { "content-type": "application/json", "content-length": Buffer.byteLength(body) });
|
|
207
|
+
res.end(body);
|
|
208
|
+
}
|
|
209
|
+
/* ─────────────────────────────── runs ─────────────────────────────────── */
|
|
210
|
+
async #createRun(request) {
|
|
211
|
+
const human = new RemoteHumanHelpHost();
|
|
212
|
+
const approvals = new RemoteApprovalBroker();
|
|
213
|
+
const agent = new BrowserAgent({
|
|
214
|
+
decision: request.providers?.decision ?? "typesafe",
|
|
215
|
+
humanHelp: human,
|
|
216
|
+
approvals,
|
|
217
|
+
screenshot: request.screenshot ?? "on-failure",
|
|
218
|
+
home: this.home,
|
|
219
|
+
// The run's real id arrives with its first event; re-key the registry then.
|
|
220
|
+
onEvent: (event) => {
|
|
221
|
+
if (run.runId === placeholder && event.runId && event.runId !== placeholder) {
|
|
222
|
+
run.runId = event.runId;
|
|
223
|
+
this.#runs.delete(placeholder);
|
|
224
|
+
this.#runs.set(event.runId, run);
|
|
225
|
+
}
|
|
226
|
+
for (const subscriber of run.subscribers)
|
|
227
|
+
subscriber(event);
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
// A placeholder id is replaced once the run starts; the daemon maps by it.
|
|
231
|
+
const placeholder = `pending-${Date.now()}-${Math.random().toString(16).slice(2, 8)}`;
|
|
232
|
+
const run = {
|
|
233
|
+
runId: placeholder,
|
|
234
|
+
goal: request.goal,
|
|
235
|
+
startedAt: Date.now(),
|
|
236
|
+
agent,
|
|
237
|
+
human,
|
|
238
|
+
approvals,
|
|
239
|
+
status: "running",
|
|
240
|
+
subscribers: new Set(),
|
|
241
|
+
};
|
|
242
|
+
this.#runs.set(placeholder, run);
|
|
243
|
+
void agent
|
|
244
|
+
.run(request)
|
|
245
|
+
.then((result) => {
|
|
246
|
+
run.status =
|
|
247
|
+
result.status === "completed" ? "completed" : result.status === "cancelled" ? "cancelled" : "failed";
|
|
248
|
+
run.result = result;
|
|
249
|
+
if (this.#runs.get(run.runId) === undefined)
|
|
250
|
+
this.#runs.set(run.runId, run);
|
|
251
|
+
this.#runs.delete(placeholder);
|
|
252
|
+
})
|
|
253
|
+
.catch((error) => {
|
|
254
|
+
run.status = "failed";
|
|
255
|
+
run.error = error instanceof Error ? error.message : String(error);
|
|
256
|
+
this.#runs.delete(placeholder);
|
|
257
|
+
});
|
|
258
|
+
// Give the run a moment to obtain its real id (the first event carries it).
|
|
259
|
+
for (let i = 0; i < 120; i += 1) {
|
|
260
|
+
if (run.runId !== placeholder)
|
|
261
|
+
break;
|
|
262
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
263
|
+
}
|
|
264
|
+
return { runId: run.runId, status: run.status };
|
|
265
|
+
}
|
|
266
|
+
#listRuns() {
|
|
267
|
+
return [...this.#runs.values()].map((run) => ({
|
|
268
|
+
runId: run.runId,
|
|
269
|
+
goal: run.goal,
|
|
270
|
+
status: run.status,
|
|
271
|
+
startedAt: run.startedAt,
|
|
272
|
+
...(run.result ? { steps: run.result.steps } : {}),
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
#stream(res, runId, since) {
|
|
276
|
+
res.writeHead(200, {
|
|
277
|
+
"content-type": "text/event-stream",
|
|
278
|
+
"cache-control": "no-cache",
|
|
279
|
+
connection: "keep-alive",
|
|
280
|
+
});
|
|
281
|
+
let lastSeq = since;
|
|
282
|
+
const timer = setInterval(() => {
|
|
283
|
+
const events = readRunEvents(runId, this.home).filter((event) => event.seq > lastSeq);
|
|
284
|
+
for (const event of events) {
|
|
285
|
+
lastSeq = event.seq;
|
|
286
|
+
res.write(`id: ${event.seq}\ndata: ${JSON.stringify(event)}\n\n`);
|
|
287
|
+
}
|
|
288
|
+
const active = this.#runs.get(runId);
|
|
289
|
+
if (!active && events.length === 0 && !readRunSummary(runId, this.home)) {
|
|
290
|
+
res.write(`event: end\ndata: {}\n\n`);
|
|
291
|
+
clearInterval(timer);
|
|
292
|
+
res.end();
|
|
293
|
+
}
|
|
294
|
+
}, 500);
|
|
295
|
+
timer.unref?.();
|
|
296
|
+
res.on("close", () => clearInterval(timer));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const readJson = async (req) => {
|
|
300
|
+
const chunks = [];
|
|
301
|
+
for await (const chunk of req)
|
|
302
|
+
chunks.push(chunk);
|
|
303
|
+
if (chunks.length === 0)
|
|
304
|
+
return {};
|
|
305
|
+
try {
|
|
306
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
throw new Error("request body is not valid JSON");
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
const ensureTokenPath = (home) => {
|
|
313
|
+
const state = readDaemonState(home);
|
|
314
|
+
return state?.tokenPath ?? `${home}/daemon/token`;
|
|
315
|
+
};
|
|
316
|
+
export const createDaemon = (options = {}) => new BrowserDaemon(options);
|
|
317
|
+
export const ensureDaemonDirs = (home = resolveHome()) => {
|
|
318
|
+
mkdirSync(`${home}/daemon`, { recursive: true });
|
|
319
|
+
};
|
|
320
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon state and lifecycle helpers (PRD §59).
|
|
3
|
+
*
|
|
4
|
+
* The daemon is a local process that owns sessions, runs, events, approvals and
|
|
5
|
+
* artifacts so the browser keeps working after a CLI command exits.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_DAEMON_PORT = 7717;
|
|
8
|
+
export interface DaemonState {
|
|
9
|
+
pid: number;
|
|
10
|
+
port: number;
|
|
11
|
+
url: string;
|
|
12
|
+
startedAt: number;
|
|
13
|
+
tokenPath: string;
|
|
14
|
+
version: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const daemonStatePath: (home?: string) => string;
|
|
17
|
+
export declare const readDaemonState: (home?: string) => DaemonState | undefined;
|
|
18
|
+
export declare const writeDaemonState: (state: DaemonState, home?: string) => void;
|
|
19
|
+
export declare const clearDaemonState: (home?: string) => void;
|
|
20
|
+
export declare const ensureToken: (home?: string) => string;
|
|
21
|
+
export declare const readToken: (home?: string) => string | undefined;
|
|
22
|
+
export declare const isProcessAlive: (pid: number) => boolean;
|
|
23
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,eAAe,GAAI,aAAoB,KAAG,MAAqC,CAAC;AAE7F,eAAO,MAAM,eAAe,GAAI,aAAoB,KAAG,WAAW,GAAG,SAUpE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,WAAW,EAAE,aAAoB,KAAG,IAK3E,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,aAAoB,KAAG,IASvD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,aAAoB,KAAG,MAYlD,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,aAAoB,KAAG,MAAM,GAAG,SAQzD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,OAO5C,CAAC"}
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon state and lifecycle helpers (PRD §59).
|
|
3
|
+
*
|
|
4
|
+
* The daemon is a local process that owns sessions, runs, events, approvals and
|
|
5
|
+
* artifacts so the browser keeps working after a CLI command exits.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, rmSync, mkdirSync, chmodSync } from "node:fs";
|
|
8
|
+
import { randomBytes } from "node:crypto";
|
|
9
|
+
import { daemonPaths, resolveHome } from "@mlola/browser-trace";
|
|
10
|
+
export const DEFAULT_DAEMON_PORT = 7717;
|
|
11
|
+
export const daemonStatePath = (home = resolveHome()) => daemonPaths(home).statePath;
|
|
12
|
+
export const readDaemonState = (home = resolveHome()) => {
|
|
13
|
+
const path = daemonStatePath(home);
|
|
14
|
+
if (!existsSync(path))
|
|
15
|
+
return undefined;
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
18
|
+
if (typeof parsed.pid !== "number" || typeof parsed.port !== "number")
|
|
19
|
+
return undefined;
|
|
20
|
+
return parsed;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
export const writeDaemonState = (state, home = resolveHome()) => {
|
|
27
|
+
const paths = daemonPaths(home);
|
|
28
|
+
mkdirSync(paths.dir, { recursive: true });
|
|
29
|
+
writeFileSync(paths.statePath, `${JSON.stringify(state, null, 2)}\n`);
|
|
30
|
+
writeFileSync(paths.pidPath, String(state.pid));
|
|
31
|
+
};
|
|
32
|
+
export const clearDaemonState = (home = resolveHome()) => {
|
|
33
|
+
const paths = daemonPaths(home);
|
|
34
|
+
for (const path of [paths.statePath, paths.pidPath]) {
|
|
35
|
+
try {
|
|
36
|
+
rmSync(path, { force: true });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
/* best effort */
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
export const ensureToken = (home = resolveHome()) => {
|
|
44
|
+
const paths = daemonPaths(home);
|
|
45
|
+
mkdirSync(paths.dir, { recursive: true });
|
|
46
|
+
if (!existsSync(paths.tokenPath)) {
|
|
47
|
+
writeFileSync(paths.tokenPath, randomBytes(24).toString("hex"));
|
|
48
|
+
try {
|
|
49
|
+
chmodSync(paths.tokenPath, 0o600);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
/* platform dependent */
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return readFileSync(paths.tokenPath, "utf8").trim();
|
|
56
|
+
};
|
|
57
|
+
export const readToken = (home = resolveHome()) => {
|
|
58
|
+
const paths = daemonPaths(home);
|
|
59
|
+
if (!existsSync(paths.tokenPath))
|
|
60
|
+
return undefined;
|
|
61
|
+
try {
|
|
62
|
+
return readFileSync(paths.tokenPath, "utf8").trim();
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
export const isProcessAlive = (pid) => {
|
|
69
|
+
try {
|
|
70
|
+
process.kill(pid, 0);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mlola/browser-daemon",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "mlola-browserd: local daemon owning sessions, runs, events, takeover and artifacts.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mlola-browserd": "./dist/bin.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"development": "./src/index.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=22.18"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/mlolahq/browser-runtime.git"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://mlola.com/browser-runtime",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/mlolahq/browser-runtime.git/issues"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"browser-automation",
|
|
38
|
+
"browser-agent",
|
|
39
|
+
"runtime",
|
|
40
|
+
"playwright",
|
|
41
|
+
"agent",
|
|
42
|
+
"jev",
|
|
43
|
+
"llm",
|
|
44
|
+
"automation"
|
|
45
|
+
],
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc -b"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@mlola/browser-protocol": "0.1.0",
|
|
54
|
+
"@mlola/browser-core": "0.1.0",
|
|
55
|
+
"@mlola/browser-runtime": "0.1.0",
|
|
56
|
+
"@mlola/browser-trace": "0.1.0"
|
|
57
|
+
}
|
|
58
|
+
}
|