@openagt/dashboard 0.9.0 → 0.11.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 +9 -17
- package/dist/built-in.d.ts +45 -16
- package/dist/built-in.d.ts.map +1 -1
- package/dist/built-in.js +95 -32
- 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/daemon-runtime.d.ts +12 -12
- package/dist/daemon-runtime.d.ts.map +1 -1
- package/dist/daemon-runtime.js +97 -37
- 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/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 +19 -25
- package/dist/dashboard/rpc-serve.d.ts.map +1 -1
- package/dist/dashboard/rpc-serve.js +11 -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 +52 -81
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/start-branch.d.ts +32 -0
- package/dist/dashboard/start-branch.d.ts.map +1 -0
- package/dist/dashboard/start-branch.js +47 -0
- package/dist/dashboard/start-branch.js.map +1 -0
- package/dist/dashboard/types.d.ts +6 -14
- 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-9Xb8Ao4p.css +2 -0
- package/dist/dashboard-bundle/assets/main-DTyyQ0jM.js +140 -0
- package/dist/dashboard-bundle/assets/{module-v213KWfH.js → module-DKd-4BTU.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 +2 -1
- package/dist/dashboard-rpc/index.d.ts.map +1 -1
- package/dist/dashboard-rpc/index.js +5 -3
- 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 +1 -1
- package/dist/dashboard-rpc/modules.js +2 -2
- package/dist/dashboard-rpc/modules.js.map +1 -1
- package/dist/dashboard-rpc/projects.d.ts +2 -0
- package/dist/dashboard-rpc/projects.d.ts.map +1 -1
- package/dist/dashboard-rpc/projects.js +10 -2
- 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/skills.d.ts +80 -0
- package/dist/dashboard-rpc/skills.d.ts.map +1 -0
- package/dist/dashboard-rpc/skills.js +84 -0
- package/dist/dashboard-rpc/skills.js.map +1 -0
- 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/ui/switch.d.ts +7 -0
- package/dist/module-types/dashboard/lib/draft-handoff.d.ts +5 -9
- package/dist/module-types/dashboard/module/index.d.ts +46 -0
- package/dist/module-types/src/built-in.d.ts +45 -16
- package/dist/module-types/src/client.d.ts +2 -1
- 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/remote-run.d.ts +77 -32
- package/dist/module-types/src/dashboard/rpc-serve.d.ts +19 -25
- package/dist/module-types/src/dashboard/start-branch.d.ts +31 -0
- package/dist/module-types/src/dashboard/types.d.ts +6 -14
- 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 +2 -1
- package/dist/module-types/src/dashboard-rpc/machines.d.ts +51 -0
- package/dist/module-types/src/dashboard-rpc/modules.d.ts +1 -1
- package/dist/module-types/src/dashboard-rpc/projects.d.ts +2 -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/dashboard-rpc/skills.d.ts +79 -0
- 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/openagent-dir.d.ts +3 -5
- package/dist/module-types/src/project-commands.d.ts +4 -0
- package/dist/module-types/src/project-hooks.d.ts +8 -5
- package/dist/module-types/src/project-modules.d.ts +8 -6
- 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/store/branches.d.ts +1 -1
- package/dist/module-types/src/store/git-host.d.ts +1 -1
- package/dist/module-types/src/store/queue.d.ts +1 -1
- package/dist/module-types/src/store/runs.d.ts +1 -1
- package/dist/module-types/src/store/tickets.d.ts +1 -1
- package/dist/module-types/src/version.d.ts +1 -0
- package/dist/openagent-dir.d.ts +3 -5
- package/dist/openagent-dir.d.ts.map +1 -1
- package/dist/openagent-dir.js +3 -5
- package/dist/openagent-dir.js.map +1 -1
- 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/project-commands.d.ts +4 -0
- package/dist/project-commands.d.ts.map +1 -1
- package/dist/project-commands.js.map +1 -1
- package/dist/project-hooks.d.ts +8 -5
- package/dist/project-hooks.d.ts.map +1 -1
- package/dist/project-hooks.js +9 -6
- package/dist/project-hooks.js.map +1 -1
- package/dist/project-modules.d.ts +8 -6
- package/dist/project-modules.d.ts.map +1 -1
- package/dist/project-modules.js +7 -13
- package/dist/project-modules.js.map +1 -1
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +1 -2
- package/dist/project.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/store/branches.d.ts +1 -1
- package/dist/store/branches.js +1 -1
- package/dist/store/git-host.d.ts +1 -1
- package/dist/store/git-host.js +2 -2
- package/dist/store/git-host.js.map +1 -1
- package/dist/store/queue.d.ts +1 -1
- package/dist/store/queue.js +1 -1
- package/dist/store/runs.d.ts +1 -1
- package/dist/store/runs.js +1 -1
- package/dist/store/test-branches.d.ts +0 -8
- package/dist/store/test-branches.d.ts.map +1 -1
- package/dist/store/test-branches.js +0 -24
- package/dist/store/test-branches.js.map +1 -1
- package/dist/store/tickets.d.ts +1 -1
- package/dist/store/tickets.js +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 +19 -13
- package/dist/dashboard-bundle/assets/main-B98UOA3_.js +0 -140
- package/dist/dashboard-bundle/assets/main-ByRjbCiA.css +0 -2
- 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
|
@@ -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":"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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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"}
|
|
@@ -3,50 +3,90 @@ import type { OpenAgentEvent } from '../events.js';
|
|
|
3
3
|
import type { AgentMeta } from '../store/index.js';
|
|
4
4
|
import type { StartAgentOptions, StartAgentResult } from './types.js';
|
|
5
5
|
/**
|
|
6
|
-
* The server-side half of "run on a
|
|
7
|
-
*
|
|
6
|
+
* The server-side half of "run on a saved machine" (#1067). The local daemon holds this computer's
|
|
7
|
+
* key on the saved machine, so it - not the browser - drives the remote daemon: it POSTs the agent to the
|
|
8
8
|
* remote's `/_relay/start` and then fetch-streams the remote's `/_relay/events` back into a local
|
|
9
9
|
* {@link EventStream}, which the dashboard reads over its normal same-origin `onEvents` channel. So
|
|
10
|
-
* the browser never talks cross-origin and the
|
|
10
|
+
* the browser never talks cross-origin and the key never leaves the two daemons (issue #1067 (b)).
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Every call but the ping names its project, by its repository's address
|
|
13
|
+
* (repository-address.ts): a project's folder, and so its id, is another one on each machine.
|
|
14
|
+
*
|
|
15
|
+
* The other OpenAgent listens on its own computer only. What answers at a machine's address is
|
|
16
|
+
* whatever that computer opened to the network, which lets this computer in once, with the code
|
|
17
|
+
* a machine's link carries ({@link enterRemote}), answers a key of this computer's own, and from
|
|
18
|
+
* then on passes each call that carries the key (`Authorization: Bearer`, no `Origin`) to its
|
|
19
|
+
* OpenAgent as that computer's own browser would have made it.
|
|
15
20
|
*/
|
|
16
|
-
/**
|
|
17
|
-
export interface
|
|
21
|
+
/** How a machine is reached: where its OpenAgent answers, this computer's key there, and what the machine's own key is known by when its link said. */
|
|
22
|
+
export interface MachineAccess {
|
|
18
23
|
url: string;
|
|
19
|
-
|
|
24
|
+
key: string;
|
|
25
|
+
pin?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Where a relayed agent works: a machine, and the project there, by its repository's address. */
|
|
28
|
+
export interface RemoteTarget extends MachineAccess {
|
|
29
|
+
project: string;
|
|
20
30
|
}
|
|
21
|
-
/**
|
|
31
|
+
/** What a relay start forwards to the remote's `/_relay/start`, beside the project. */
|
|
22
32
|
export interface RelayStartBody {
|
|
23
33
|
prompt: string;
|
|
24
34
|
options: StartAgentOptions;
|
|
25
35
|
}
|
|
26
36
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
* What a machine answers a relayed start with: a Start's own outcome, or `noProject` when it has
|
|
38
|
+
* no project cloned from the address the start named.
|
|
39
|
+
*/
|
|
40
|
+
export type RelayStartResult = StartAgentResult | {
|
|
41
|
+
ok: false;
|
|
42
|
+
error: string;
|
|
43
|
+
noProject: true;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Health-check a saved machine (#1072): true when it answers this computer's key. This is how
|
|
47
|
+
* the browser's status dots learn reachable from not.
|
|
48
|
+
*/
|
|
49
|
+
export declare function pingRemote(target: MachineAccess): Promise<boolean>;
|
|
50
|
+
/** The OpenAgent a saved machine runs, as its ping tells it; nothing for a machine that does not answer, or does not say. */
|
|
51
|
+
export declare function remoteVersion(target: MachineAccess): Promise<string | undefined>;
|
|
52
|
+
/** What asking to be let in came to: this computer's key there, or why not, in words. */
|
|
53
|
+
export type EnterResult = {
|
|
54
|
+
ok: true;
|
|
55
|
+
key: string;
|
|
56
|
+
} | {
|
|
57
|
+
ok: false;
|
|
58
|
+
error: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Ask a machine to let this computer in, with the code its link carries, under `name`. The code
|
|
62
|
+
* is good once: a link used before, or older than a few minutes, is refused.
|
|
63
|
+
*/
|
|
64
|
+
export declare function enterRemote(door: string, code: string, name: string, pin?: string): Promise<EnterResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Take this computer out of a machine: its key there stops working. Whether the machine did;
|
|
67
|
+
* one that cannot be reached keeps the key until this computer is removed there by hand.
|
|
31
68
|
*/
|
|
32
|
-
export declare function
|
|
69
|
+
export declare function leaveRemote(machine: MachineAccess & {
|
|
70
|
+
door: string;
|
|
71
|
+
}): Promise<boolean>;
|
|
33
72
|
/**
|
|
34
|
-
* Start an agent on the remote daemon
|
|
35
|
-
* id). A non-2xx or a transport failure surfaces as an
|
|
36
|
-
* same shape a local refusal has, so the caller does
|
|
73
|
+
* Start an agent on the remote daemon, in its project cloned from `target.project`, and return
|
|
74
|
+
* what it answered (with the remote's own run id). A non-2xx or a transport failure surfaces as an
|
|
75
|
+
* `ok: false` result the dashboard shows, the same shape a local refusal has, so the caller does
|
|
76
|
+
* not special-case remote errors.
|
|
37
77
|
*/
|
|
38
|
-
export declare function startRemoteAgent(target: RemoteTarget, body: RelayStartBody): Promise<
|
|
78
|
+
export declare function startRemoteAgent(target: RemoteTarget, body: RelayStartBody): Promise<RelayStartResult>;
|
|
39
79
|
/**
|
|
40
|
-
* Relay one run-scoped RPC to the
|
|
41
|
-
* holds
|
|
42
|
-
* {fn, args} to the remote's /_relay/rpc
|
|
43
|
-
* result. Throws on an unreachable
|
|
80
|
+
* Relay one run-scoped RPC to the machine that owns a remote agent (#1067 slice 2). The local daemon
|
|
81
|
+
* holds this computer's key there, so a read/diff/handoff/push/PR for a relayed agent runs ON the machine: POST
|
|
82
|
+
* {fn, args} to the remote's /_relay/rpc with the key (no Origin), returning the machine's
|
|
83
|
+
* result. Throws on an unreachable machine or a non-2xx so the caller falls back to its own empty/error
|
|
44
84
|
* shape, the same way a failed local read does.
|
|
45
85
|
*/
|
|
46
86
|
export declare function relayRpc(target: RemoteTarget, fn: string, args: unknown[]): Promise<unknown>;
|
|
47
87
|
/**
|
|
48
88
|
* Fetch-stream a remote agent's newline-delimited events into `onEvent` until the remote closes the
|
|
49
|
-
* body, the agent ends, or `cancel()` is called. A 401 (
|
|
89
|
+
* body, the agent ends, or `cancel()` is called. A 401 (this computer was removed there) ends the stream
|
|
50
90
|
* cleanly rather than as an error, so the dashboard sees a normal `done`, not a lost connection.
|
|
51
91
|
* Returns a cancel function; calling it aborts the fetch and releases the reader.
|
|
52
92
|
*/
|
|
@@ -54,11 +94,12 @@ export declare function streamRemoteEvents(target: RemoteTarget, agentId: string
|
|
|
54
94
|
/**
|
|
55
95
|
* The local daemon's live relayed runs (#1067), keyed by the remote agent id. Registering an agent opens
|
|
56
96
|
* an {@link EventStream} the dashboard reads through `onEvents`, fed by {@link streamRemoteEvents}
|
|
57
|
-
* from the remote.
|
|
58
|
-
* run
|
|
97
|
+
* from the remote. The target is the saved machine as it was at the Start. A machine is not
|
|
98
|
+
* removed while a run is at work on it ({@link working}); the runs that ended there before it
|
|
99
|
+
* was removed read as unreachable, and one added again answers for them with its new key ({@link rekey}).
|
|
59
100
|
*
|
|
60
101
|
* The `targets` map outlives the event pump (#1067 slice 2): a finished remote agent's post-run reads,
|
|
61
|
-
* open-PR and merge still have to reach the
|
|
102
|
+
* open-PR and merge still have to reach the machine after its event stream has ended, so the machine
|
|
62
103
|
* target is kept until {@link dispose} clears it, not dropped when the stream closes.
|
|
63
104
|
*
|
|
64
105
|
* The `metas` map (#1077) holds a local {@link AgentMeta} stub per relayed agent so `onAgents` can show a
|
|
@@ -73,22 +114,26 @@ export declare class RelayedAgents {
|
|
|
73
114
|
register(agentId: string, target: RemoteTarget, meta: AgentMeta, projectId: string): void;
|
|
74
115
|
/** The live event stream for a relayed agent, or undefined when this daemon is not relaying it. */
|
|
75
116
|
get(agentId: string | undefined): EventStream<OpenAgentEvent> | undefined;
|
|
76
|
-
/** The
|
|
117
|
+
/** The machine a relayed agent runs on, kept past the event stream so post-run push/PR still reach it. */
|
|
77
118
|
target(agentId: string | undefined): RemoteTarget | undefined;
|
|
119
|
+
/** Whether a run this daemon follows is still at work on the machine at `url`: its events still stream. */
|
|
120
|
+
working(url: string): boolean;
|
|
121
|
+
/** How the machine at `url` is reached since it was added again, for the runs kept from before: this computer's new key there, and the key the machine is known by. */
|
|
122
|
+
rekey(url: string, key: string, pin?: string): void;
|
|
78
123
|
/** A project's relayed run stubs (#1077), newest-first, so `onAgents` can surface them in the list. */
|
|
79
124
|
list(projectId: string): AgentMeta[];
|
|
80
125
|
/** Fold each relayed event into the agent's list row via the store's own reducer (#1077), so the
|
|
81
|
-
* local stub mirrors the
|
|
126
|
+
* local stub mirrors the machine: the terminal status on `end`, the waiting flag while it is parked
|
|
82
127
|
* (#785), the driver once its session starts. Events carry no write time, so this stamps its own. */
|
|
83
128
|
private apply;
|
|
84
129
|
/** Close a relayed agent's event stream (not its target). Idempotent. */
|
|
85
130
|
private endStream;
|
|
86
|
-
/** Stop every pump, close every stream, and forget every
|
|
131
|
+
/** Stop every pump, close every stream, and forget every machine target + list stub, on daemon shutdown. */
|
|
87
132
|
dispose(): void;
|
|
88
133
|
}
|
|
89
134
|
/**
|
|
90
|
-
* Fold one relayed event into the memory-only row of a run on a
|
|
91
|
-
* card would say, kept here because that card is on the
|
|
135
|
+
* Fold one relayed event into the memory-only row of a run on a machine: what the machine's own
|
|
136
|
+
* card would say, kept here because that card is on the machine. The events are the ones a run's
|
|
92
137
|
* diary yields: the agent's session id, its cost, its end.
|
|
93
138
|
*/
|
|
94
139
|
export declare function foldRelayedEvent(meta: AgentMeta, event: OpenAgentEvent, at: string): AgentMeta;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-run.d.ts","sourceRoot":"","sources":["../../src/dashboard/remote-run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"remote-run.d.ts","sourceRoot":"","sources":["../../src/dashboard/remote-run.ts"],"names":[],"mappings":"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"}
|