@openagt/dashboard 0.10.0 → 0.12.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/README.md +1 -6
- package/dist/built-in.d.ts +18 -2
- package/dist/built-in.d.ts.map +1 -1
- package/dist/built-in.js +29 -6
- package/dist/built-in.js.map +1 -1
- package/dist/cli.d.ts +4 -10
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -67
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +2 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3 -4
- package/dist/client.js.map +1 -1
- package/dist/clone-project.d.ts +69 -0
- package/dist/clone-project.d.ts.map +1 -0
- package/dist/clone-project.js +124 -0
- package/dist/clone-project.js.map +1 -0
- package/dist/daemon-runtime.d.ts +12 -12
- package/dist/daemon-runtime.d.ts.map +1 -1
- package/dist/daemon-runtime.js +96 -35
- package/dist/daemon-runtime.js.map +1 -1
- package/dist/daemon.d.ts +3 -14
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +15 -26
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/bridge-endpoints.d.ts +5 -5
- package/dist/dashboard/bridge-endpoints.js +5 -5
- package/dist/dashboard/http.d.ts +1 -1
- package/dist/dashboard/http.js +1 -1
- package/dist/dashboard/machine-call.d.ts +10 -0
- package/dist/dashboard/machine-call.d.ts.map +1 -0
- package/dist/dashboard/machine-call.js +86 -0
- package/dist/dashboard/machine-call.js.map +1 -0
- package/dist/dashboard/module-serve.d.ts +6 -0
- package/dist/dashboard/module-serve.d.ts.map +1 -1
- package/dist/dashboard/module-serve.js +24 -8
- package/dist/dashboard/module-serve.js.map +1 -1
- package/dist/dashboard/relay-endpoints.d.ts +26 -17
- package/dist/dashboard/relay-endpoints.d.ts.map +1 -1
- package/dist/dashboard/relay-endpoints.js +70 -27
- package/dist/dashboard/relay-endpoints.js.map +1 -1
- package/dist/dashboard/remote-run.d.ts +77 -32
- package/dist/dashboard/remote-run.d.ts.map +1 -1
- package/dist/dashboard/remote-run.js +120 -42
- package/dist/dashboard/remote-run.js.map +1 -1
- package/dist/dashboard/rpc-serve.d.ts +28 -25
- package/dist/dashboard/rpc-serve.d.ts.map +1 -1
- package/dist/dashboard/rpc-serve.js +26 -22
- package/dist/dashboard/rpc-serve.js.map +1 -1
- package/dist/dashboard/screen.d.ts +53 -0
- package/dist/dashboard/screen.d.ts.map +1 -0
- package/dist/dashboard/screen.js +175 -0
- package/dist/dashboard/screen.js.map +1 -0
- package/dist/dashboard/server.d.ts +18 -19
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +57 -84
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/types.d.ts +11 -16
- package/dist/dashboard/types.d.ts.map +1 -1
- package/dist/dashboard/web-start-endpoints.d.ts +2 -2
- package/dist/dashboard/web-start-endpoints.js +1 -1
- package/dist/dashboard-bundle/assets/main-BHMlP40v.css +2 -0
- package/dist/dashboard-bundle/assets/main-D0qZC1r-.js +140 -0
- package/dist/dashboard-bundle/assets/{module-gKz-ZvkG.js → module-ZjyA5WUg.js} +4 -4
- package/dist/dashboard-bundle/host/module.js +1 -1
- package/dist/dashboard-bundle/index.html +3 -3
- package/dist/dashboard-rpc/context.d.ts +4 -4
- package/dist/dashboard-rpc/context.js +5 -5
- package/dist/dashboard-rpc/context.js.map +1 -1
- package/dist/dashboard-rpc/control.d.ts +1 -1
- package/dist/dashboard-rpc/control.js +7 -7
- package/dist/dashboard-rpc/control.js.map +1 -1
- package/dist/dashboard-rpc/events.d.ts +1 -1
- package/dist/dashboard-rpc/events.js +1 -1
- package/dist/dashboard-rpc/index.d.ts +3 -3
- package/dist/dashboard-rpc/index.d.ts.map +1 -1
- package/dist/dashboard-rpc/index.js +5 -5
- package/dist/dashboard-rpc/index.js.map +1 -1
- package/dist/dashboard-rpc/machines.d.ts +52 -0
- package/dist/dashboard-rpc/machines.d.ts.map +1 -0
- package/dist/dashboard-rpc/machines.js +82 -0
- package/dist/dashboard-rpc/machines.js.map +1 -0
- package/dist/dashboard-rpc/modules.d.ts +12 -4
- package/dist/dashboard-rpc/modules.d.ts.map +1 -1
- package/dist/dashboard-rpc/modules.js +24 -5
- package/dist/dashboard-rpc/modules.js.map +1 -1
- package/dist/dashboard-rpc/projects.d.ts +18 -0
- package/dist/dashboard-rpc/projects.d.ts.map +1 -1
- package/dist/dashboard-rpc/projects.js +27 -5
- package/dist/dashboard-rpc/projects.js.map +1 -1
- package/dist/dashboard-rpc/reads.d.ts +3 -4
- package/dist/dashboard-rpc/reads.d.ts.map +1 -1
- package/dist/dashboard-rpc/reads.js +5 -6
- package/dist/dashboard-rpc/reads.js.map +1 -1
- package/dist/dashboard-rpc/relay-agent.d.ts +3 -3
- package/dist/dashboard-rpc/relay-agent.js +3 -3
- package/dist/dashboard-rpc/relay-dispatch.d.ts +4 -4
- package/dist/dashboard-rpc/relay-dispatch.d.ts.map +1 -1
- package/dist/dashboard-rpc/relay-dispatch.js +7 -7
- package/dist/dashboard-rpc/relay-dispatch.js.map +1 -1
- package/dist/dashboard-rpc/test-context.js +1 -1
- package/dist/dashboard-rpc/test-context.js.map +1 -1
- package/dist/events.d.ts +4 -3
- package/dist/events.d.ts.map +1 -1
- package/dist/loopback-host.d.ts +3 -5
- package/dist/loopback-host.d.ts.map +1 -1
- package/dist/loopback-host.js +3 -5
- package/dist/loopback-host.js.map +1 -1
- package/dist/machine-link.d.ts +21 -0
- package/dist/machine-link.d.ts.map +1 -0
- package/dist/machine-link.js +20 -0
- package/dist/machine-link.js.map +1 -0
- package/dist/module-server.d.ts +1 -1
- package/dist/module-types/dashboard/components/QrCode.d.ts +8 -0
- package/dist/module-types/dashboard/lib/draft-handoff.d.ts +5 -9
- package/dist/module-types/dashboard/module/index.d.ts +56 -4
- package/dist/module-types/dashboard/rpc/modules.d.ts +1 -0
- package/dist/module-types/src/built-in.d.ts +18 -2
- package/dist/module-types/src/client.d.ts +2 -1
- package/dist/module-types/src/clone-project.d.ts +68 -0
- package/dist/module-types/src/dashboard/bridge-endpoints.d.ts +5 -5
- package/dist/module-types/src/dashboard/http.d.ts +1 -1
- package/dist/module-types/src/dashboard/machine-call.d.ts +9 -0
- package/dist/module-types/src/dashboard/module-serve.d.ts +6 -0
- package/dist/module-types/src/dashboard/remote-run.d.ts +77 -32
- package/dist/module-types/src/dashboard/rpc-serve.d.ts +28 -25
- package/dist/module-types/src/dashboard/types.d.ts +11 -16
- package/dist/module-types/src/dashboard-rpc/context.d.ts +4 -4
- package/dist/module-types/src/dashboard-rpc/control.d.ts +1 -1
- package/dist/module-types/src/dashboard-rpc/events.d.ts +1 -1
- package/dist/module-types/src/dashboard-rpc/index.d.ts +3 -3
- package/dist/module-types/src/dashboard-rpc/machines.d.ts +51 -0
- package/dist/module-types/src/dashboard-rpc/modules.d.ts +12 -4
- package/dist/module-types/src/dashboard-rpc/projects.d.ts +18 -0
- package/dist/module-types/src/dashboard-rpc/reads.d.ts +3 -4
- package/dist/module-types/src/dashboard-rpc/relay-agent.d.ts +3 -3
- package/dist/module-types/src/events.d.ts +4 -3
- package/dist/module-types/src/loopback-host.d.ts +3 -5
- package/dist/module-types/src/machine-link.d.ts +20 -0
- package/dist/module-types/src/pick-directory.d.ts +2 -0
- package/dist/module-types/src/project-modules.d.ts +12 -3
- package/dist/module-types/src/registry.d.ts +59 -16
- package/dist/module-types/src/repository-address.d.ts +22 -0
- package/dist/module-types/src/screens.d.ts +13 -0
- package/dist/module-types/src/store/agent-store.d.ts +2 -2
- package/dist/module-types/src/version.d.ts +1 -0
- package/dist/package-services.d.ts +27 -0
- package/dist/package-services.d.ts.map +1 -0
- package/dist/package-services.js +62 -0
- package/dist/package-services.js.map +1 -0
- package/dist/pick-directory.d.ts +2 -0
- package/dist/pick-directory.d.ts.map +1 -1
- package/dist/pick-directory.js +7 -1
- package/dist/pick-directory.js.map +1 -1
- package/dist/project-modules.d.ts +12 -3
- package/dist/project-modules.d.ts.map +1 -1
- package/dist/project-modules.js +20 -2
- package/dist/project-modules.js.map +1 -1
- package/dist/registry.d.ts +59 -16
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +91 -20
- package/dist/registry.js.map +1 -1
- package/dist/repository-address.d.ts +23 -0
- package/dist/repository-address.d.ts.map +1 -0
- package/dist/repository-address.js +38 -0
- package/dist/repository-address.js.map +1 -0
- package/dist/screens.d.ts +14 -0
- package/dist/screens.d.ts.map +1 -0
- package/dist/screens.js +40 -0
- package/dist/screens.js.map +1 -0
- package/dist/store/agent-store.d.ts +2 -2
- package/dist/store/agent-store.d.ts.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +26 -0
- package/dist/version.js.map +1 -0
- package/package.json +15 -11
- package/dist/dashboard-bundle/assets/main-Q7JMdMJI.css +0 -2
- package/dist/dashboard-bundle/assets/main-fDZWGOub.js +0 -140
- package/dist/dashboard-rpc/devices.d.ts +0 -9
- package/dist/dashboard-rpc/devices.d.ts.map +0 -1
- package/dist/dashboard-rpc/devices.js +0 -12
- package/dist/dashboard-rpc/devices.js.map +0 -1
- package/dist/install.d.ts +0 -31
- package/dist/install.d.ts.map +0 -1
- package/dist/install.js +0 -54
- package/dist/install.js.map +0 -1
- package/dist/module-types/src/dashboard-rpc/devices.d.ts +0 -8
- package/dist/module-types/src/openagent-gitignore.d.ts +0 -11
- package/dist/openagent-gitignore.d.ts +0 -12
- package/dist/openagent-gitignore.d.ts.map +0 -1
- package/dist/openagent-gitignore.js +0 -19
- package/dist/openagent-gitignore.js.map +0 -1
package/dist/daemon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAkB,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,wBAAwB,EAAoB,MAAM,eAAe,CAAA;AAC5I,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,11 +5,11 @@ export type { BridgeOption, BridgeQuestion } from './bridge-question.js';
|
|
|
5
5
|
* The browser bridge (#1237): the one endpoint an extension running in the user's own Claude
|
|
6
6
|
* session posts to, so a question a cloud agent is parked on becomes visible in the dashboard.
|
|
7
7
|
*
|
|
8
|
-
* **Why this route carries its own token, unlike every other one.**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* **Why this route carries its own token, unlike every other one.** What protects the daemon,
|
|
9
|
+
* which listens on its own computer only, is the same-origin check on `/_rpc`: a page on another
|
|
10
|
+
* origin is refused outright. This route is the first that is *meant* to be reached from another
|
|
11
|
+
* origin, so that check does not protect it, and it demands `Authorization: Bearer <bridgeToken>`
|
|
12
|
+
* unconditionally instead.
|
|
13
13
|
*
|
|
14
14
|
* **No CORS headers, on purpose.** An extension's service worker holding `host_permissions`
|
|
15
15
|
* fetches without a preflight, so the bridge does not need `Access-Control-Allow-Origin` and
|
|
@@ -4,11 +4,11 @@ import { end, readPost, requireGet, sendJson } from './http.js';
|
|
|
4
4
|
* The browser bridge (#1237): the one endpoint an extension running in the user's own Claude
|
|
5
5
|
* session posts to, so a question a cloud agent is parked on becomes visible in the dashboard.
|
|
6
6
|
*
|
|
7
|
-
* **Why this route carries its own token, unlike every other one.**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* **Why this route carries its own token, unlike every other one.** What protects the daemon,
|
|
8
|
+
* which listens on its own computer only, is the same-origin check on `/_rpc`: a page on another
|
|
9
|
+
* origin is refused outright. This route is the first that is *meant* to be reached from another
|
|
10
|
+
* origin, so that check does not protect it, and it demands `Authorization: Bearer <bridgeToken>`
|
|
11
|
+
* unconditionally instead.
|
|
12
12
|
*
|
|
13
13
|
* **No CORS headers, on purpose.** An extension's service worker holding `host_permissions`
|
|
14
14
|
* fetches without a preflight, so the bridge does not need `Access-Control-Allow-Origin` and
|
package/dist/dashboard/http.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
2
|
/**
|
|
3
3
|
* The plumbing every one of the daemon's non-RPC HTTP surfaces shares: the browser bridge
|
|
4
|
-
* (`/_bridge`), the web-start queue (`/_web-start`) and the
|
|
4
|
+
* (`/_bridge`), the web-start queue (`/_web-start`) and the machine relay (`/_relay`).
|
|
5
5
|
*
|
|
6
6
|
* All three answer plain-text statuses, JSON payloads, and read capped JSON request bodies, and
|
|
7
7
|
* each carried its own copy — two body readers that differed only in which message they rejected
|
package/dist/dashboard/http.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The plumbing every one of the daemon's non-RPC HTTP surfaces shares: the browser bridge
|
|
3
|
-
* (`/_bridge`), the web-start queue (`/_web-start`) and the
|
|
3
|
+
* (`/_bridge`), the web-start queue (`/_web-start`) and the machine relay (`/_relay`).
|
|
4
4
|
*
|
|
5
5
|
* All three answer plain-text statuses, JSON payloads, and read capped JSON request bodies, and
|
|
6
6
|
* each carried its own copy — two body readers that differed only in which message they rejected
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** What a call says when the machine at the address shows another key than the one it was added with. */
|
|
2
|
+
export declare const NOT_THE_MACHINE = "what answers at this address is not the machine that was added: add the machine again, with a new link";
|
|
3
|
+
export interface MachineCall {
|
|
4
|
+
method?: string;
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
body?: string;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
}
|
|
9
|
+
export declare function machineFetch(url: string, pin: string | undefined, init?: MachineCall): Promise<Response>;
|
|
10
|
+
//# sourceMappingURL=machine-call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-call.d.ts","sourceRoot":"","sources":["../../src/dashboard/machine-call.ts"],"names":[],"mappings":"AAuBA,yGAAyG;AACzG,eAAO,MAAM,eAAe,2GAA2G,CAAA;AAKvI,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwD5G"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { request } from 'node:https';
|
|
3
|
+
import { isIP } from 'node:net';
|
|
4
|
+
import { Readable } from 'node:stream';
|
|
5
|
+
import { connect } from 'node:tls';
|
|
6
|
+
/**
|
|
7
|
+
* One call to a saved machine. A machine reached over HTTPS whose link carried what its key is
|
|
8
|
+
* known by is known by that key alone: the connection is made, the key the machine shows is
|
|
9
|
+
* compared, and only then is anything sent, so a key and a prompt never reach whoever holds the
|
|
10
|
+
* machine's address next. The key stays when the machine renews its certificate, and a
|
|
11
|
+
* certificate that ran out while its office could not be reached does not cut the machine off.
|
|
12
|
+
*
|
|
13
|
+
* Any other machine (one on the same Wi-Fi, over plain HTTP) is called as it always was. Neither
|
|
14
|
+
* kind of call follows a redirect.
|
|
15
|
+
*/
|
|
16
|
+
/** What a key is known by: the SHA-256 of its public half, URL-safe. */
|
|
17
|
+
function fingerprintOf(socket) {
|
|
18
|
+
const shown = socket.getPeerX509Certificate();
|
|
19
|
+
return shown && createHash('sha256').update(shown.publicKey.export({ type: 'spki', format: 'der' })).digest('base64url');
|
|
20
|
+
}
|
|
21
|
+
/** What a call says when the machine at the address shows another key than the one it was added with. */
|
|
22
|
+
export const NOT_THE_MACHINE = 'what answers at this address is not the machine that was added: add the machine again, with a new link';
|
|
23
|
+
/** How long a machine gets to show its key once it took the connection. */
|
|
24
|
+
const HANDSHAKE_MS = 10_000;
|
|
25
|
+
export function machineFetch(url, pin, init = {}) {
|
|
26
|
+
const target = new URL(url);
|
|
27
|
+
if (target.protocol !== 'https:' || pin === undefined)
|
|
28
|
+
return fetch(url, { ...init, redirect: 'error' });
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const host = target.hostname.replace(/^\[|\]$/g, '');
|
|
31
|
+
const signal = init.signal;
|
|
32
|
+
const givenUp = () => (signal?.reason instanceof Error ? signal.reason : new Error('the call was given up on'));
|
|
33
|
+
// A call given up on before the machine took the connection ends here: the request itself
|
|
34
|
+
// says nothing until it has a connection.
|
|
35
|
+
signal?.addEventListener('abort', () => reject(givenUp()), { once: true });
|
|
36
|
+
const req = request(target, {
|
|
37
|
+
method: init.method ?? 'GET',
|
|
38
|
+
headers: init.headers ?? {},
|
|
39
|
+
...(signal ? { signal } : {}),
|
|
40
|
+
// The connection is made here, by no agent, and handed over only once the machine has
|
|
41
|
+
// shown the key it is known by: one connection for one call.
|
|
42
|
+
createConnection: (_options, handOver) => {
|
|
43
|
+
const socket = connect({ host, port: Number(target.port) || 443, ...(isIP(host) ? {} : { servername: host }), rejectUnauthorized: false });
|
|
44
|
+
// The connection goes with the call: one that is given up on, and one a machine takes
|
|
45
|
+
// and then says nothing on, is not left open.
|
|
46
|
+
const drop = () => void socket.destroy(givenUp());
|
|
47
|
+
if (signal?.aborted)
|
|
48
|
+
drop();
|
|
49
|
+
else
|
|
50
|
+
signal?.addEventListener('abort', drop, { once: true });
|
|
51
|
+
socket.once('close', () => signal?.removeEventListener('abort', drop));
|
|
52
|
+
socket.setTimeout(HANDSHAKE_MS, () => socket.destroy(new Error('the machine took the connection and did not go on')));
|
|
53
|
+
socket.once('error', err => handOver(err, socket));
|
|
54
|
+
socket.once('secureConnect', () => {
|
|
55
|
+
socket.setTimeout(0);
|
|
56
|
+
if (fingerprintOf(socket) === pin)
|
|
57
|
+
return handOver(null, socket);
|
|
58
|
+
socket.destroy();
|
|
59
|
+
handOver(new Error(NOT_THE_MACHINE), socket);
|
|
60
|
+
});
|
|
61
|
+
return undefined;
|
|
62
|
+
},
|
|
63
|
+
}, res => {
|
|
64
|
+
const headers = new Headers();
|
|
65
|
+
for (const [name, value] of Object.entries(res.headers))
|
|
66
|
+
for (const one of Array.isArray(value) ? value : value === undefined ? [] : [value])
|
|
67
|
+
headers.append(name, one);
|
|
68
|
+
const status = res.statusCode ?? 502;
|
|
69
|
+
// A status with no body is answered without one: `Response` refuses a body there.
|
|
70
|
+
const empty = status === 204 || status === 205 || status === 304 || init.method === 'HEAD';
|
|
71
|
+
if (empty)
|
|
72
|
+
res.resume();
|
|
73
|
+
try {
|
|
74
|
+
resolve(new Response(empty ? null : Readable.toWeb(res), { status, headers }));
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
// A status no answer can carry: the machine's fault, told as a failed call.
|
|
78
|
+
res.destroy();
|
|
79
|
+
reject(err);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
req.once('error', reject);
|
|
83
|
+
req.end(init.body);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=machine-call.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-call.js","sourceRoot":"","sources":["../../src/dashboard/machine-call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,OAAO,EAAkB,MAAM,UAAU,CAAA;AAElD;;;;;;;;;GASG;AAEH,wEAAwE;AACxE,SAAS,aAAa,CAAC,MAAiB;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,sBAAsB,EAAE,CAAA;IAC7C,OAAO,KAAK,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;AAC1H,CAAC;AAED,yGAAyG;AACzG,MAAM,CAAC,MAAM,eAAe,GAAG,wGAAwG,CAAA;AAEvI,2EAA2E;AAC3E,MAAM,YAAY,GAAG,MAAM,CAAA;AAS3B,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,GAAuB,EAAE,IAAI,GAAgB,EAAE;IACvF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAA;IACxG,OAAO,IAAI,OAAO,CAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,MAAM,OAAO,GAAG,GAAU,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAA;QACtH,0FAA0F;QAC1F,0CAA0C;QAC1C,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1E,MAAM,GAAG,GAAG,OAAO,CACjB,MAAM,EACN;YACE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;YAC5B,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;YAC3B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7B,sFAAsF;YACtF,6DAA6D;YAC7D,gBAAgB,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE;gBACvC,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAA;gBAC1I,sFAAsF;gBACtF,8CAA8C;gBAC9C,MAAM,IAAI,GAAG,GAAS,EAAE,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;gBACvD,IAAI,MAAM,EAAE,OAAO;oBAAE,IAAI,EAAE,CAAA;;oBACtB,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;gBAC5D,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAA;gBACtE,MAAM,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC,CAAA;gBACrH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAA;gBAClD,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE;oBAChC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;oBACpB,IAAI,aAAa,CAAC,MAAM,CAAC,KAAK,GAAG;wBAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;oBAChE,MAAM,CAAC,OAAO,EAAE,CAAA;oBAChB,QAAQ,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,CAAA;gBAC9C,CAAC,CAAC,CAAA;gBACF,OAAO,SAAkB,CAAA;YAC3B,CAAC;SACF,EACD,GAAG,CAAC,EAAE;YACJ,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;YAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;oBAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YACvK,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAA;YACpC,kFAAkF;YAClF,MAAM,KAAK,GAAG,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAA;YAC1F,IAAI,KAAK;gBAAE,GAAG,CAAC,MAAM,EAAE,CAAA;YACvB,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAgC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;YAChH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,4EAA4E;gBAC5E,GAAG,CAAC,OAAO,EAAE,CAAA;gBACb,MAAM,CAAC,GAAG,CAAC,CAAA;YACb,CAAC;QACH,CAAC,CACF,CAAA;QACD,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACzB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpB,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -3,8 +3,12 @@ import { type ProjectsProvider } from './projects.js';
|
|
|
3
3
|
import { type ProjectModule } from '../project-modules.js';
|
|
4
4
|
/** Where module files are served: `/_modules/<project id>/<package>/<file>`, each segment encoded. */
|
|
5
5
|
export declare const MODULES_PREFIX = "/_modules";
|
|
6
|
+
/** Where the files of the computer's modules are served, which are no project's: `/_computer-modules/<package>/<file>`. */
|
|
7
|
+
export declare const COMPUTER_MODULES_PREFIX = "/_computer-modules";
|
|
6
8
|
/** The URL a module's browser part is served at from one project. */
|
|
7
9
|
export declare function moduleUrl(projectId: string, module: Pick<ProjectModule, 'package' | 'entry'>): string;
|
|
10
|
+
/** The URL the browser part of one of the computer's modules is served at. */
|
|
11
|
+
export declare function computerModuleUrl(module: Pick<ProjectModule, 'package' | 'entry'>): string;
|
|
8
12
|
/**
|
|
9
13
|
* Serve one module file (#1774): the project must be registered, the package must be a module of
|
|
10
14
|
* that project, and the file must sit inside the module's browser part's own directory. Anything else is a
|
|
@@ -12,4 +16,6 @@ export declare function moduleUrl(projectId: string, module: Pick<ProjectModule,
|
|
|
12
16
|
* Served as `no-cache`, since a module is rebuilt in place under the same name.
|
|
13
17
|
*/
|
|
14
18
|
export declare function serveModuleFile(req: IncomingMessage, res: ServerResponse, pathname: string, projects?: ProjectsProvider): Promise<void>;
|
|
19
|
+
/** Serve one file of a module that is the computer's: as {@link serveModuleFile}, with no project to be registered. */
|
|
20
|
+
export declare function serveComputerModuleFile(req: IncomingMessage, res: ServerResponse, pathname: string): Promise<void>;
|
|
15
21
|
//# sourceMappingURL=module-serve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-serve.d.ts","sourceRoot":"","sources":["../../src/dashboard/module-serve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC9E,OAAO,
|
|
1
|
+
{"version":3,"file":"module-serve.d.ts","sourceRoot":"","sources":["../../src/dashboard/module-serve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC9E,OAAO,EAAqD,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE7G,sGAAsG;AACtG,eAAO,MAAM,cAAc,cAAc,CAAA;AAEzC,2HAA2H;AAC3H,eAAO,MAAM,uBAAuB,uBAAuB,CAAA;AAI3D,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,MAAM,CAErG;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,MAAM,CAE1F;AAUD;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,gBAA4C,GACrD,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,uHAAuH;AACvH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExH"}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { contentTypeFor } from './content-type.js';
|
|
3
3
|
import { defaultProjectsProvider } from './projects.js';
|
|
4
|
-
import { findProjectModule, moduleFile } from '../project-modules.js';
|
|
4
|
+
import { findComputerModule, findProjectModule, moduleFile } from '../project-modules.js';
|
|
5
5
|
/** Where module files are served: `/_modules/<project id>/<package>/<file>`, each segment encoded. */
|
|
6
6
|
export const MODULES_PREFIX = '/_modules';
|
|
7
|
+
/** Where the files of the computer's modules are served, which are no project's: `/_computer-modules/<package>/<file>`. */
|
|
8
|
+
export const COMPUTER_MODULES_PREFIX = '/_computer-modules';
|
|
9
|
+
const encoded = (path) => path.split('/').map(encodeURIComponent).join('/');
|
|
7
10
|
/** The URL a module's browser part is served at from one project. */
|
|
8
11
|
export function moduleUrl(projectId, module) {
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
return `${MODULES_PREFIX}/${encodeURIComponent(projectId)}/${encodeURIComponent(module.package)}/${encoded(module.entry)}`;
|
|
13
|
+
}
|
|
14
|
+
/** The URL the browser part of one of the computer's modules is served at. */
|
|
15
|
+
export function computerModuleUrl(module) {
|
|
16
|
+
return `${COMPUTER_MODULES_PREFIX}/${encodeURIComponent(module.package)}/${encoded(module.entry)}`;
|
|
11
17
|
}
|
|
12
18
|
function decode(segment) {
|
|
13
19
|
try {
|
|
@@ -24,17 +30,27 @@ function decode(segment) {
|
|
|
24
30
|
* Served as `no-cache`, since a module is rebuilt in place under the same name.
|
|
25
31
|
*/
|
|
26
32
|
export async function serveModuleFile(req, res, pathname, projects = defaultProjectsProvider()) {
|
|
33
|
+
const [projectSegment, ...rest] = pathname.slice(MODULES_PREFIX.length + 1).split('/');
|
|
34
|
+
const projectId = projectSegment !== undefined ? decode(projectSegment) : undefined;
|
|
35
|
+
return serveFileOf(req, res, rest, async (pkg) => {
|
|
36
|
+
const root = projectId ? await projects.resolvePath(projectId) : undefined;
|
|
37
|
+
return root ? findProjectModule(root, pkg) : undefined;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** Serve one file of a module that is the computer's: as {@link serveModuleFile}, with no project to be registered. */
|
|
41
|
+
export async function serveComputerModuleFile(req, res, pathname) {
|
|
42
|
+
return serveFileOf(req, res, pathname.slice(COMPUTER_MODULES_PREFIX.length + 1).split('/'), findComputerModule);
|
|
43
|
+
}
|
|
44
|
+
/** Answer the file `<package>/<file>` names, of the module `find` knows the package as. */
|
|
45
|
+
async function serveFileOf(req, res, [packageSegment, ...rest], find) {
|
|
27
46
|
const notFound = () => void res.writeHead(404, { 'content-type': 'text/plain' }).end('no such module file');
|
|
28
47
|
if (req.method !== 'GET' && req.method !== 'HEAD')
|
|
29
48
|
return void res.writeHead(405, { allow: 'GET, HEAD' }).end();
|
|
30
|
-
const [projectSegment, packageSegment, ...rest] = pathname.slice(MODULES_PREFIX.length + 1).split('/');
|
|
31
|
-
const projectId = projectSegment !== undefined ? decode(projectSegment) : undefined;
|
|
32
49
|
const pkg = packageSegment !== undefined ? decode(packageSegment) : undefined;
|
|
33
50
|
const rel = rest.map(decode);
|
|
34
|
-
if (!
|
|
51
|
+
if (!pkg || rel.length === 0 || rel.some(part => part === undefined))
|
|
35
52
|
return notFound();
|
|
36
|
-
const
|
|
37
|
-
const module = root ? await findProjectModule(root, pkg).catch(() => undefined) : undefined;
|
|
53
|
+
const module = await find(pkg).catch(() => undefined);
|
|
38
54
|
const file = module ? await moduleFile(module, rel.join('/')) : undefined;
|
|
39
55
|
const body = file ? await readFile(file).catch(() => undefined) : undefined;
|
|
40
56
|
if (!file || body === undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-serve.js","sourceRoot":"","sources":["../../src/dashboard/module-serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,uBAAuB,EAAyB,MAAM,eAAe,CAAA;AAC9E,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAsB,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"module-serve.js","sourceRoot":"","sources":["../../src/dashboard/module-serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,30 +2,39 @@ import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
|
2
2
|
import type { OpenAgentEvent } from '../events.js';
|
|
3
3
|
import type { StartAgentOptions, StartAgentResult } from './types.js';
|
|
4
4
|
/**
|
|
5
|
-
* The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* The machine-side of the remote-agent relay (#1067): the endpoints through which another
|
|
6
|
+
* machine's daemon runs a session here and watches it. They live under `/_relay`. This daemon
|
|
7
|
+
* listens on its own computer only: a call from another machine reaches them through whatever
|
|
8
|
+
* this computer opened to the network, which lets in only a machine that holds a key of its own
|
|
9
|
+
* and passes its call on as this computer's own would arrive.
|
|
10
10
|
*
|
|
11
|
-
* - `POST /_relay/start` starts an ordinary local agent and returns its {@link StartAgentResult}.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* saved device with its token; a token-less caller is already 401'd by the shared-token guard (#1051) above.
|
|
11
|
+
* - `POST /_relay/start` starts an ordinary local agent and returns its {@link StartAgentResult}.
|
|
12
|
+
* - `GET /_relay/events?run=<id>&project=<address>` streams that agent's events as
|
|
13
|
+
* newline-delimited JSON until it ends or the caller disconnects.
|
|
14
|
+
* - `GET /_relay/ping` (#1072) a reachability probe: 200 and this OpenAgent's version, starts nothing. The
|
|
15
|
+
* online/offline status the dashboard shows is the local daemon calling this on each saved
|
|
16
|
+
* machine with its key there.
|
|
18
17
|
* - `POST /_relay/rpc` (#1067 slice 2) runs one whitelisted run-scoped RPC (a read/diff/steer/handoff/
|
|
19
|
-
* push/PR) against this
|
|
18
|
+
* push/PR) against this machine's own checkout for the daemon relaying an agent here, answering {result}.
|
|
19
|
+
* - `GET /_relay/screen/stream?run=<id>&project=<address>` and `POST /_relay/screen/input?…` pass
|
|
20
|
+
* one call on to the live screen of a run here (screen.ts), for the daemon whose person watches it.
|
|
21
|
+
*
|
|
22
|
+
* All but the ping name their project by its repository's address, and work in this machine's own
|
|
23
|
+
* project cloned from it. A call that names none, or one this machine does not have, starts and
|
|
24
|
+
* reads nothing: there is no project a call falls back to.
|
|
20
25
|
*/
|
|
21
26
|
export declare const RELAY_PREFIX = "/_relay";
|
|
22
27
|
/** What the daemon wires behind the relay endpoints: its own start closure and an events tail. */
|
|
23
28
|
export interface RelayHandlers {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
/** This machine's own id for its project cloned from `address`, or undefined when it has none. */
|
|
30
|
+
project: (address: string) => Promise<string | undefined>;
|
|
31
|
+
start: (prompt: string, options: StartAgentOptions, projectId: string) => StartAgentResult | Promise<StartAgentResult>;
|
|
32
|
+
tailEvents: (projectId: string, agentId: string, onEvent: (event: OpenAgentEvent) => void) => () => void;
|
|
33
|
+
/** Run one whitelisted read/steer/handoff RPC against THIS machine's own checkout, for the daemon
|
|
27
34
|
* relaying an agent here (#1067 slice 2); the caller wraps the result as {result}. */
|
|
28
|
-
rpc?: (fn: string, args: unknown[]) => Promise<unknown>;
|
|
35
|
+
rpc?: (projectId: string, fn: string, args: unknown[]) => Promise<unknown>;
|
|
36
|
+
/** Where the live screen of a run here answers; nothing when the run has none. */
|
|
37
|
+
screen?: (projectId: string, agentId: string) => Promise<string | undefined>;
|
|
29
38
|
}
|
|
30
39
|
/** Route a `/_relay/*` request. A host that wired no relay handlers 404s every relay route. */
|
|
31
40
|
export declare function handleRelayRequest(req: IncomingMessage, res: ServerResponse, pathname: string, handlers: RelayHandlers | undefined): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-endpoints.d.ts","sourceRoot":"","sources":["../../src/dashboard/relay-endpoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"relay-endpoints.d.ts","sourceRoot":"","sources":["../../src/dashboard/relay-endpoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAOrE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,YAAY,YAAY,CAAA;AAErC,kGAAkG;AAClG,MAAM,WAAW,aAAa;IAC5B,kGAAkG;IAClG,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACzD,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,KAAK,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACtH,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;IACxG;2FACuF;IACvF,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1E,kFAAkF;IAClF,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAC7E;AAgBD,+FAA+F;AAC/F,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,aAAa,GAAG,SAAS,GAClC,OAAO,CAAC,IAAI,CAAC,CAWf"}
|
|
@@ -1,27 +1,39 @@
|
|
|
1
1
|
import { end, readJsonBody, requireGet, sendJson } from './http.js';
|
|
2
|
+
import { passToScreen, screenCallOf } from './screen.js';
|
|
3
|
+
import { isRunId } from '../store/index.js';
|
|
4
|
+
import { openagentVersion } from '../version.js';
|
|
2
5
|
/**
|
|
3
|
-
* The
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* The machine-side of the remote-agent relay (#1067): the endpoints through which another
|
|
7
|
+
* machine's daemon runs a session here and watches it. They live under `/_relay`. This daemon
|
|
8
|
+
* listens on its own computer only: a call from another machine reaches them through whatever
|
|
9
|
+
* this computer opened to the network, which lets in only a machine that holds a key of its own
|
|
10
|
+
* and passes its call on as this computer's own would arrive.
|
|
8
11
|
*
|
|
9
|
-
* - `POST /_relay/start` starts an ordinary local agent and returns its {@link StartAgentResult}.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* saved device with its token; a token-less caller is already 401'd by the shared-token guard (#1051) above.
|
|
12
|
+
* - `POST /_relay/start` starts an ordinary local agent and returns its {@link StartAgentResult}.
|
|
13
|
+
* - `GET /_relay/events?run=<id>&project=<address>` streams that agent's events as
|
|
14
|
+
* newline-delimited JSON until it ends or the caller disconnects.
|
|
15
|
+
* - `GET /_relay/ping` (#1072) a reachability probe: 200 and this OpenAgent's version, starts nothing. The
|
|
16
|
+
* online/offline status the dashboard shows is the local daemon calling this on each saved
|
|
17
|
+
* machine with its key there.
|
|
16
18
|
* - `POST /_relay/rpc` (#1067 slice 2) runs one whitelisted run-scoped RPC (a read/diff/steer/handoff/
|
|
17
|
-
* push/PR) against this
|
|
19
|
+
* push/PR) against this machine's own checkout for the daemon relaying an agent here, answering {result}.
|
|
20
|
+
* - `GET /_relay/screen/stream?run=<id>&project=<address>` and `POST /_relay/screen/input?…` pass
|
|
21
|
+
* one call on to the live screen of a run here (screen.ts), for the daemon whose person watches it.
|
|
22
|
+
*
|
|
23
|
+
* All but the ping name their project by its repository's address, and work in this machine's own
|
|
24
|
+
* project cloned from it. A call that names none, or one this machine does not have, starts and
|
|
25
|
+
* reads nothing: there is no project a call falls back to.
|
|
18
26
|
*/
|
|
19
27
|
export const RELAY_PREFIX = '/_relay';
|
|
28
|
+
/** This machine's id for the project a call names, or undefined: no address, or no such project here. */
|
|
29
|
+
async function projectNamed(handlers, address) {
|
|
30
|
+
return typeof address === 'string' && address ? handlers.project(address) : undefined;
|
|
31
|
+
}
|
|
20
32
|
const MAX_START_BODY = 256 * 1024;
|
|
21
33
|
/** Route a `/_relay/*` request. A host that wired no relay handlers 404s every relay route. */
|
|
22
34
|
export async function handleRelayRequest(req, res, pathname, handlers) {
|
|
23
|
-
// Ping is a pure reachability
|
|
24
|
-
// so it answers even on a host that enabled no relay.
|
|
35
|
+
// Ping is a pure reachability probe (#1072): it needs no wired handlers and starts nothing,
|
|
36
|
+
// so it answers even on a host that enabled no relay.
|
|
25
37
|
if (pathname === `${RELAY_PREFIX}/ping`)
|
|
26
38
|
return handlePing(req, res);
|
|
27
39
|
if (!handlers)
|
|
@@ -32,14 +44,31 @@ export async function handleRelayRequest(req, res, pathname, handlers) {
|
|
|
32
44
|
return handleEvents(req, res, handlers);
|
|
33
45
|
if (pathname === `${RELAY_PREFIX}/rpc`)
|
|
34
46
|
return handleRpc(req, res, handlers);
|
|
47
|
+
const screenCall = screenCallOf(pathname, `${RELAY_PREFIX}/screen`);
|
|
48
|
+
if (screenCall)
|
|
49
|
+
return handleScreen(req, res, handlers, screenCall);
|
|
35
50
|
end(res, 404, 'not found');
|
|
36
51
|
}
|
|
37
|
-
/**
|
|
38
|
-
|
|
52
|
+
/** `/_relay/screen/<call>?run=<id>&project=<address>`: pass the call on to the run's live screen here. */
|
|
53
|
+
async function handleScreen(req, res, handlers, call) {
|
|
54
|
+
if (!handlers.screen)
|
|
55
|
+
return end(res, 404, 'relay screen not enabled');
|
|
56
|
+
const query = new URL(req.url ?? '/', 'http://localhost').searchParams;
|
|
57
|
+
const agentId = query.get('run');
|
|
58
|
+
if (!agentId || !isRunId(agentId))
|
|
59
|
+
return end(res, 400, 'missing run id');
|
|
60
|
+
const projectId = await projectNamed(handlers, query.get('project')).catch(() => undefined);
|
|
61
|
+
if (projectId === undefined)
|
|
62
|
+
return end(res, 404, 'no such project on this machine');
|
|
63
|
+
await passToScreen(req, res, call, await handlers.screen(projectId, agentId).catch(() => undefined));
|
|
64
|
+
}
|
|
65
|
+
/** `GET /_relay/ping` (#1072): answer 200 with this OpenAgent's version. Starts nothing; it proves this
|
|
66
|
+
* daemon is reachable, and to another machine that its key still lets it in, and tells that
|
|
67
|
+
* machine whether this one fell behind it. */
|
|
39
68
|
function handlePing(req, res) {
|
|
40
69
|
if (!requireGet(req, res))
|
|
41
70
|
return;
|
|
42
|
-
|
|
71
|
+
sendJson(res, { version: openagentVersion() });
|
|
43
72
|
}
|
|
44
73
|
/** `POST /_relay/start`: read the agent request, start it locally, and answer with the result JSON. */
|
|
45
74
|
async function handleStart(req, res, handlers) {
|
|
@@ -55,26 +84,37 @@ async function handleStart(req, res, handlers) {
|
|
|
55
84
|
const prompt = typeof body.prompt === 'string' ? body.prompt : '';
|
|
56
85
|
const options = (body.options && typeof body.options === 'object' ? body.options : {});
|
|
57
86
|
// Never relay onward from a relayed agent: strip any nested target before starting it here.
|
|
58
|
-
// And a start relayed to a
|
|
59
|
-
const {
|
|
87
|
+
// And a start relayed to a machine never names a branch: the caller's branches are not this machine's.
|
|
88
|
+
const { machine: _drop, base: _callers, ...local } = options;
|
|
60
89
|
let result;
|
|
61
90
|
try {
|
|
62
|
-
|
|
91
|
+
const projectId = await projectNamed(handlers, body.project);
|
|
92
|
+
result =
|
|
93
|
+
projectId === undefined
|
|
94
|
+
? { ok: false, error: `no project on this machine is cloned from ${String(body.project)}`, noProject: true }
|
|
95
|
+
: await handlers.start(prompt, local, projectId);
|
|
63
96
|
}
|
|
64
97
|
catch (err) {
|
|
65
98
|
result = { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
66
99
|
}
|
|
67
100
|
sendJson(res, result);
|
|
68
101
|
}
|
|
69
|
-
/** `GET /_relay/events?run=<id>`: stream the agent's events as newline-delimited JSON. */
|
|
70
|
-
function handleEvents(req, res, handlers) {
|
|
102
|
+
/** `GET /_relay/events?run=<id>&project=<address>`: stream the agent's events as newline-delimited JSON. */
|
|
103
|
+
async function handleEvents(req, res, handlers) {
|
|
71
104
|
if (!requireGet(req, res))
|
|
72
105
|
return;
|
|
73
|
-
const
|
|
106
|
+
const query = new URL(req.url ?? '/', 'http://localhost').searchParams;
|
|
107
|
+
const agentId = query.get('run');
|
|
74
108
|
if (!agentId)
|
|
75
109
|
return end(res, 400, 'missing run id');
|
|
110
|
+
const projectId = await projectNamed(handlers, query.get('project')).catch(() => undefined);
|
|
111
|
+
if (projectId === undefined)
|
|
112
|
+
return end(res, 404, 'no such project on this machine');
|
|
113
|
+
// The caller went away while the project was looked up: a tail started now would never be stopped.
|
|
114
|
+
if (res.destroyed || req.socket.destroyed)
|
|
115
|
+
return;
|
|
76
116
|
res.writeHead(200, { 'content-type': 'application/x-ndjson', 'cache-control': 'no-cache' });
|
|
77
|
-
const stop = handlers.tailEvents(agentId, event => {
|
|
117
|
+
const stop = handlers.tailEvents(projectId, agentId, event => {
|
|
78
118
|
// A dropped write (the caller went away mid-line) must not throw out of the tail callback.
|
|
79
119
|
try {
|
|
80
120
|
res.write(`${JSON.stringify(event)}\n`);
|
|
@@ -88,7 +128,7 @@ function handleEvents(req, res, handlers) {
|
|
|
88
128
|
req.on('close', close);
|
|
89
129
|
}
|
|
90
130
|
const MAX_RPC_BODY = 256 * 1024;
|
|
91
|
-
/** POST /_relay/rpc: run one whitelisted RPC on this
|
|
131
|
+
/** POST /_relay/rpc: run one whitelisted RPC on this machine and answer {result}. */
|
|
92
132
|
async function handleRpc(req, res, handlers) {
|
|
93
133
|
if (req.method !== 'POST')
|
|
94
134
|
return end(res, 405, 'method not allowed', { allow: 'POST' });
|
|
@@ -106,7 +146,10 @@ async function handleRpc(req, res, handlers) {
|
|
|
106
146
|
if (!fn)
|
|
107
147
|
return end(res, 400, 'missing rpc name');
|
|
108
148
|
try {
|
|
109
|
-
|
|
149
|
+
const projectId = await projectNamed(handlers, body.project);
|
|
150
|
+
if (projectId === undefined)
|
|
151
|
+
return end(res, 404, 'no such project on this machine');
|
|
152
|
+
sendJson(res, { result: await handlers.rpc(projectId, fn, args) });
|
|
110
153
|
}
|
|
111
154
|
catch (err) {
|
|
112
155
|
end(res, 500, err instanceof Error ? err.message : 'rpc failed');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-endpoints.js","sourceRoot":"","sources":["../../src/dashboard/relay-endpoints.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"relay-endpoints.js","sourceRoot":"","sources":["../../src/dashboard/relay-endpoints.ts"],"names":[],"mappings":"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"}
|