@node-agent/local 0.0.0-stage → 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.
@@ -0,0 +1,336 @@
1
+ // The runtime API: a small HTTP surface over the Runtime interface.
2
+ //
3
+ // The server owns no process table of its own; it forwards every request to the Runtime it was
4
+ // constructed with. That keeps the transport (HTTP) separate from the policy (who may start what),
5
+ // and lets one Runtime be used in-process by tests and out-of-process by a service entry.
6
+ //
7
+ // Authentication is a service bearer token. A runtime is not a public API: callers are a frontend
8
+ // or a store, both of which already hold a service credential.
9
+ import { createServer } from 'node:http';
10
+ import { Link, Remote } from 'node-agent-bus';
11
+ import { createHash } from 'node:crypto';
12
+ import { timingSafeEqual } from 'node:crypto';
13
+ import { RuntimeError, } from './base.js';
14
+ function json(res, status, value) {
15
+ const body = JSON.stringify(value);
16
+ res.writeHead(status, {
17
+ 'content-type': 'application/json; charset=utf-8',
18
+ 'content-length': Buffer.byteLength(body),
19
+ });
20
+ res.end(body);
21
+ }
22
+ function equal(left, right) {
23
+ const a = Buffer.from(left);
24
+ const b = Buffer.from(right);
25
+ return a.length === b.length && timingSafeEqual(a, b);
26
+ }
27
+ async function bodyOf(req) {
28
+ const pieces = [];
29
+ let size = 0;
30
+ for await (const chunk of req) {
31
+ const piece = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
32
+ size += piece.length;
33
+ if (size > 64 * 1024)
34
+ throw new RuntimeError('invalid_user', 'request body is too large');
35
+ pieces.push(piece);
36
+ }
37
+ if (size === 0)
38
+ return {};
39
+ try {
40
+ const parsed = JSON.parse(Buffer.concat(pieces).toString('utf8'));
41
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
42
+ throw new Error('body must be a JSON object');
43
+ return parsed;
44
+ }
45
+ catch (error) {
46
+ throw new RuntimeError('invalid_user', `invalid JSON body: ${error instanceof Error ? error.message : String(error)}`);
47
+ }
48
+ }
49
+ function text(value, field) {
50
+ if (typeof value !== 'string' || value.trim() === '')
51
+ throw new RuntimeError('invalid_user', `body.${field} must be a non-empty string`);
52
+ return value.trim();
53
+ }
54
+ function object(value) {
55
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
56
+ ? value
57
+ : undefined;
58
+ }
59
+ function busView(handle) {
60
+ return {
61
+ kind: 'bus',
62
+ host: handle.host,
63
+ port: handle.port,
64
+ url: handle.url,
65
+ pid: handle.pid ?? null,
66
+ state: handle.state,
67
+ };
68
+ }
69
+ function nodeView(handle) {
70
+ return {
71
+ kind: 'node',
72
+ name: handle.name,
73
+ version: handle.version,
74
+ dir: handle.dir,
75
+ pid: handle.pid ?? null,
76
+ state: handle.state,
77
+ };
78
+ }
79
+ function statusOf(error) {
80
+ switch (error.code) {
81
+ case 'invalid_user':
82
+ case 'invalid_node':
83
+ return 400;
84
+ case 'bus_not_running':
85
+ case 'node_not_running':
86
+ return 404;
87
+ case 'spawn_failed':
88
+ case 'bus_start_failed':
89
+ case 'node_start_failed':
90
+ return 502;
91
+ default:
92
+ return 500;
93
+ }
94
+ }
95
+ /** The HTTP runtime service. `start()` binds; `stop()` releases the socket. */
96
+ export class RuntimeServer {
97
+ runtime;
98
+ token;
99
+ host;
100
+ port;
101
+ logger;
102
+ server;
103
+ address;
104
+ constructor(options) {
105
+ if (options.token.trim() === '')
106
+ throw new RuntimeError('invalid_user', 'a runtime server needs a service token');
107
+ this.runtime = options.runtime;
108
+ this.token = options.token;
109
+ this.host = options.host ?? '127.0.0.1';
110
+ this.port = options.port ?? 0;
111
+ this.logger = options.logger;
112
+ }
113
+ get url() {
114
+ return this.address?.url;
115
+ }
116
+ async start() {
117
+ if (this.server !== undefined)
118
+ return this.address;
119
+ const server = createServer((req, res) => {
120
+ void this.handle(req, res);
121
+ });
122
+ server.on('upgrade', (req, socket, head) => {
123
+ void this.upgrade(req, socket, head);
124
+ });
125
+ await new Promise((resolve, reject) => {
126
+ server.once('error', reject);
127
+ server.listen(this.port, this.host, () => {
128
+ server.off('error', reject);
129
+ resolve();
130
+ });
131
+ });
132
+ const address = server.address();
133
+ const port = typeof address === 'object' && address !== null ? address.port : this.port;
134
+ this.server = server;
135
+ this.address = { host: this.host, port, url: `http://${this.host}:${port}` };
136
+ this.logger?.info(`runtime api: ${this.address.url}`);
137
+ return this.address;
138
+ }
139
+ async stop() {
140
+ const server = this.server;
141
+ if (server === undefined)
142
+ return;
143
+ await new Promise((resolve) => server.close(() => resolve()));
144
+ this.server = undefined;
145
+ this.address = undefined;
146
+ }
147
+ authorized(req) {
148
+ const header = req.headers.authorization ?? '';
149
+ const prefix = 'Bearer ';
150
+ return header.startsWith(prefix) && equal(header.slice(prefix.length), this.token);
151
+ }
152
+ stackNodes() {
153
+ const raw = process.env.NODE_AGENT_RUNTIME_NODES ??
154
+ 'history,agent,system,provider,notes,todo,timer,search,webui';
155
+ return raw
156
+ .split(',')
157
+ .map((one) => one.trim())
158
+ .filter((one) => one !== '');
159
+ }
160
+ /** A private WebSocket door onto the one shared bus. */
161
+ async upgrade(req, socket, head) {
162
+ const url = new URL(req.url ?? '/', 'http://runtime.local');
163
+ const match = /^\/bus\/([^/]+)$/.exec(url.pathname);
164
+ if (match === null || !this.authorized(req)) {
165
+ socket.destroy();
166
+ return;
167
+ }
168
+ const user = decodeURIComponent(match[1]);
169
+ const session = (await this.runtime.sessions(user));
170
+ if ((session.agents ?? []).length === 0) {
171
+ socket.destroy();
172
+ return;
173
+ }
174
+ const target = this.runtime.busTarget?.();
175
+ if (target === undefined) {
176
+ socket.destroy();
177
+ return;
178
+ }
179
+ const key = req.headers['sec-websocket-key'];
180
+ if (typeof key !== 'string' || key === '') {
181
+ socket.destroy();
182
+ return;
183
+ }
184
+ const accept = createHash('sha1')
185
+ .update(`${key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`)
186
+ .digest('base64');
187
+ socket.write('HTTP/1.1 101 Switching Protocols\r\n' +
188
+ 'Upgrade: websocket\r\n' +
189
+ 'Connection: Upgrade\r\n' +
190
+ `Sec-WebSocket-Accept: ${accept}\r\n\r\n`);
191
+ const link = new Link(socket, head);
192
+ const dial = new URL(target.url);
193
+ dial.searchParams.set('token', target.token);
194
+ const remote = new Remote(target.url, dial.toString());
195
+ const pending = [];
196
+ remote.receive((frame) => link.send(JSON.stringify(frame)), () => link.close());
197
+ link.receive((frame) => {
198
+ const text = JSON.stringify(frame);
199
+ if (!remote.send(text))
200
+ pending.push(text);
201
+ }, () => remote.close());
202
+ remote.dial().then(() => {
203
+ for (const text of pending)
204
+ remote.send(text);
205
+ pending.length = 0;
206
+ }, (error) => {
207
+ this.logger?.warn(`bus proxy: ${error instanceof Error ? error.message : String(error)}`);
208
+ link.close();
209
+ });
210
+ }
211
+ async handle(req, res) {
212
+ try {
213
+ const url = new URL(req.url ?? '/', 'http://runtime.local');
214
+ const path = url.pathname;
215
+ if (req.method === 'GET' && path === '/healthz') {
216
+ json(res, 200, { ok: true, service: 'runtime' });
217
+ return;
218
+ }
219
+ if (!this.authorized(req)) {
220
+ res.setHeader('www-authenticate', 'Bearer');
221
+ json(res, 401, {
222
+ error: 'missing or wrong service token',
223
+ code: 'unauthorized',
224
+ });
225
+ return;
226
+ }
227
+ if (req.method === 'GET' && path === '/whoami') {
228
+ json(res, 200, { ok: true, service: 'runtime' });
229
+ return;
230
+ }
231
+ const body = req.method === 'POST' ? await bodyOf(req) : {};
232
+ // User lifecycle. A user is the persistent boundary; destroying it removes only that home
233
+ // and that user's node table, never the shared bus or its processes.
234
+ if (req.method === 'POST' && (path === '/users/create' || path === '/create_user')) {
235
+ const user = text(body.user, 'user');
236
+ const handle = await this.runtime.createUser(user);
237
+ json(res, 201, { user: handle.user, home: handle.home, state: handle.state });
238
+ return;
239
+ }
240
+ if (req.method === 'POST' && (path === '/users/destroy' || path === '/destroy_user')) {
241
+ const user = text(body.user, 'user');
242
+ await this.runtime.destroyUser(user);
243
+ json(res, 200, { ok: true, user });
244
+ return;
245
+ }
246
+ // Bus lifecycle. One bus, shared nodes; a user is only a connection.
247
+ if (req.method === 'POST' && path === '/bus/launch') {
248
+ const handle = await this.runtime.launchBus(object(body.options));
249
+ json(res, 201, busView(handle));
250
+ return;
251
+ }
252
+ if (req.method === 'POST' && path === '/bus/stop') {
253
+ await this.runtime.stopBus();
254
+ json(res, 200, { ok: true });
255
+ return;
256
+ }
257
+ if (req.method === 'POST' && path === '/agents/create') {
258
+ const user = text(body.user, 'user');
259
+ const name = typeof body.name === 'string' && body.name.trim() !== '' ? body.name.trim() : user;
260
+ await this.runtime.createUser(user);
261
+ await this.runtime.launchBus();
262
+ for (const ref of this.stackNodes()) {
263
+ const node = await this.runtime.launchNode(ref);
264
+ await this.runtime.connect(user, node.name);
265
+ }
266
+ json(res, 200, { user, name, state: 'running' });
267
+ return;
268
+ }
269
+ if (req.method === 'POST' && path === '/agents/stop') {
270
+ const user = text(body.user, 'user');
271
+ const session = (await this.runtime.sessions(user));
272
+ for (const node of session.nodes ?? []) {
273
+ if (typeof node.name === 'string')
274
+ await this.runtime.disconnect(user, node.name);
275
+ }
276
+ json(res, 200, { user, stopped: true });
277
+ return;
278
+ }
279
+ // Node lifecycle.
280
+ if (req.method === 'POST' && path === '/node/launch') {
281
+ const node = text(body.node, 'node');
282
+ const handle = await this.runtime.launchNode(node, object(body.options));
283
+ json(res, 201, nodeView(handle));
284
+ return;
285
+ }
286
+ if (req.method === 'POST' && path === '/node/stop') {
287
+ const node = text(body.node, 'node');
288
+ await this.runtime.stopNode(node);
289
+ json(res, 200, { ok: true, node });
290
+ return;
291
+ }
292
+ // The composed operations.
293
+ if (req.method === 'POST' && (path === '/connect' || path === '/nodes/connect')) {
294
+ const user = text(body.user, 'user');
295
+ const node = text(body.node ?? body.name, 'name');
296
+ const handle = await this.runtime.connect(user, node, object(body.options));
297
+ json(res, 200, {
298
+ user,
299
+ name: handle.name,
300
+ version: handle.version,
301
+ started: false,
302
+ running: handle.state === 'running',
303
+ session: handle.name,
304
+ dir: handle.dir,
305
+ pid: handle.pid ?? null,
306
+ });
307
+ return;
308
+ }
309
+ if (req.method === 'POST' && (path === '/disconnect' || path === '/nodes/disconnect')) {
310
+ const user = text(body.user, 'user');
311
+ const node = text(body.node ?? body.name, 'name');
312
+ await this.runtime.disconnect(user, node);
313
+ json(res, 200, { ok: true, user, name: node, stopped: true });
314
+ return;
315
+ }
316
+ if (req.method === 'GET' && path === '/sessions') {
317
+ const asked = (url.searchParams.get('user') ?? '').trim();
318
+ json(res, 200, await this.runtime.sessions(asked === '' ? undefined : asked));
319
+ return;
320
+ }
321
+ json(res, 404, {
322
+ error: `no route: ${req.method ?? '?'} ${path}`,
323
+ code: 'not_found',
324
+ });
325
+ }
326
+ catch (error) {
327
+ if (error instanceof RuntimeError) {
328
+ json(res, statusOf(error), { error: error.message, code: error.code });
329
+ return;
330
+ }
331
+ this.logger?.error(`runtime api: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`);
332
+ json(res, 500, { error: 'runtime request failed', code: 'internal' });
333
+ }
334
+ }
335
+ }
336
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/serve.js ADDED
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env node
2
+ // node-agent: the headless core as a process — one runtime, one shared bus, every node on it.
3
+ //
4
+ // The order is deliberate:
5
+ //
6
+ // 1. runtime starts and binds the bus
7
+ // 2. core and optional nodes start and register with that bus (global, not per user)
8
+ // 3. the deployment's user is created
9
+ // 4. that user is connected to the nodes this process started
10
+ //
11
+ // A node is a package root with `dist/serve.js`; the runtime starts it as a worker and waits for its manifest to
12
+ // appear in the global registry. `NODE_AGENT_NODES` names extra package roots (comma separated);
13
+ // `NODE_AGENT_USER` names the deployment user. Core nodes are connected to a private runtime service
14
+ // user while they start, so system can call history before the deployment user exists.
15
+ //
16
+ // NODE_AGENT_NODES=node-agent-webui node-agent
17
+ //
18
+ // NODE_AGENT_ACCESS_TOKEN puts the optional proxy in front of the page (src/proxy.ts): one token, one
19
+ // login page, /bus and /events piped through. Unset, nothing is added and no port is opened.
20
+ //
21
+ // Stopping is SIGINT / SIGTERM, and nothing else.
22
+ import { createRequire } from 'node:module';
23
+ import { dirname, join } from 'node:path';
24
+ import { existsSync } from 'node:fs';
25
+ import { fileURLToPath } from 'node:url';
26
+ import { SERVICE_TENANT, privateNodeToken } from 'node-agent-bus';
27
+ import { busArgsOrExit } from './index.js';
28
+ import { LocalRuntime } from './local.js';
29
+ import { startProxy } from './proxy.js';
30
+ const ARGS = busArgsOrExit('node-agent', { ownsBus: true });
31
+ const PORT = ARGS.bind?.port ?? Number(process.env.NODE_AGENT_BUS_PORT ?? 0);
32
+ const BIND = ARGS.bind?.host ?? process.env.NODE_AGENT_BUS_BIND ?? '127.0.0.1';
33
+ // No store node here: this is the personal build, whose third-party nodes dial the local bus
34
+ // themselves (`npx @node-agent/sdk .`) instead of being published and connected through a store.
35
+ /** The package that runs the stack's setup once, after everything else is up. */
36
+ const INTRODUCE = 'node-agent-introduce';
37
+ const DEFAULT_NODES = 'node-agent-provider,node-agent-webui,node-agent-notes,node-agent-todo,node-agent-timer,node-agent-search,node-agent-introduce';
38
+ const SIBLINGS = {
39
+ 'node-agent-provider': {
40
+ env: 'NODE_AGENT_PROVIDER_ROOT',
41
+ fallback: '../../nodes/provider',
42
+ },
43
+ };
44
+ function specsFrom(value) {
45
+ const text = value.trim();
46
+ if (text === '')
47
+ return [];
48
+ return text.split(',').map((item) => {
49
+ const module = item.split(':')[0]?.trim() ?? '';
50
+ if (module === '')
51
+ throw new Error(`NODE_AGENT_NODES item "${item.trim()}" names no module`);
52
+ return { module };
53
+ });
54
+ }
55
+ function untilStopped() {
56
+ return new Promise((resolve) => {
57
+ process.once('SIGINT', () => resolve());
58
+ process.once('SIGTERM', () => resolve());
59
+ });
60
+ }
61
+ /** Resolve a node package to its root: env override, installed package, then a sibling checkout. */
62
+ function rootOf(moduleName) {
63
+ const override = SIBLINGS[moduleName];
64
+ const configured = override === undefined ? undefined : process.env[override.env]?.trim();
65
+ if (configured)
66
+ return configured;
67
+ // The published launcher installs every core node as a dependency. Resolve the package first;
68
+ // the sibling path below is only for a source checkout that has not run npm install yet.
69
+ try {
70
+ const require = createRequire(import.meta.url);
71
+ let root = dirname(require.resolve(moduleName));
72
+ while (!existsSync(join(root, 'package.json')))
73
+ root = dirname(root);
74
+ return root;
75
+ }
76
+ catch {
77
+ const short = moduleName.startsWith('@')
78
+ ? (moduleName.split('/')[1] ?? moduleName)
79
+ : moduleName.replace(/^node-agent-/, '');
80
+ const local = fileURLToPath(new URL(`../../nodes/${short}`, import.meta.url));
81
+ if (existsSync(join(local, 'package.json')))
82
+ return local;
83
+ throw new Error(`cannot resolve Node package ${moduleName}`);
84
+ }
85
+ }
86
+ /** NODE_AGENT_PROXY_*: loopback HTTP by default, because the browser is normally on this host. */
87
+ function proxyOptions(env, token, upstream) {
88
+ const bind = env.NODE_AGENT_PROXY_BIND?.trim() || '127.0.0.1';
89
+ const port = Number(env.NODE_AGENT_PROXY_PORT ?? 8080);
90
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
91
+ throw new Error(`NODE_AGENT_PROXY_PORT "${env.NODE_AGENT_PROXY_PORT}" is not a port`);
92
+ }
93
+ // Opt-in and off by default: a login over plain loopback HTTP must still be able to set a cookie.
94
+ const secure = env.NODE_AGENT_PROXY_SECURE === '1';
95
+ return { token, upstream, bind, port, secure };
96
+ }
97
+ async function main() {
98
+ let specs;
99
+ try {
100
+ specs = specsFrom(process.env.NODE_AGENT_NODES ?? DEFAULT_NODES);
101
+ }
102
+ catch (e) {
103
+ console.error(e instanceof Error ? e.message : String(e));
104
+ process.exit(1);
105
+ }
106
+ const runtime = new LocalRuntime({
107
+ host: BIND,
108
+ basePort: PORT,
109
+ token: ARGS.token,
110
+ logger: console,
111
+ });
112
+ // 1. Runtime: bind the one bus every node and every user shares.
113
+ let bus;
114
+ try {
115
+ bus = await runtime.launchBus({ host: BIND, port: PORT, token: ARGS.token });
116
+ }
117
+ catch (e) {
118
+ console.error(`runtime failed to start (port ${PORT}): ${e instanceof Error ? e.message : String(e)}`);
119
+ process.exit(1);
120
+ }
121
+ const names = [];
122
+ const userId = process.env.NODE_AGENT_USER?.trim() || 'default';
123
+ const userTenant = runtime.busUser(userId);
124
+ // The page advertises this, never the shared bus token: a node that presents it registers
125
+ // privately in this user's space and therefore appears in this user's UI.
126
+ const joinToken = privateNodeToken(bus.token, userTenant);
127
+ try {
128
+ // 2. Nodes: start and register globally. The service user is connected as each one arrives so
129
+ // core nodes can call each other during their own startup.
130
+ const core = ['node-agent-history', 'node-agent-agent', 'node-agent-system'].map(rootOf);
131
+ const roots = [
132
+ ...core,
133
+ ...specs.filter((spec) => spec.module !== INTRODUCE).map((spec) => rootOf(spec.module)),
134
+ ];
135
+ for (const root of roots) {
136
+ // NODE_AGENT_USER_TENANT is the deployment user's bus id: a node that has to speak as that
137
+ // user before anyone has called it (introduce seeds the user's transcript) needs the identity the
138
+ // caller would otherwise hand it.
139
+ const handle = await runtime.launchNode(root, {
140
+ dir: root,
141
+ env: { NODE_AGENT_USER_TENANT: userTenant, NODE_AGENT_JOIN_TOKEN: joinToken },
142
+ });
143
+ names.push(handle.name);
144
+ runtime.bus?.user(SERVICE_TENANT, true)?.connect(handle.name);
145
+ }
146
+ // 3. The deployment user exists only after the shared nodes do.
147
+ await runtime.createUser(userId);
148
+ // 4. Then grant that user every node this process started.
149
+ for (const name of names)
150
+ await runtime.connect(userId, name);
151
+ // 5. Last, start the node that owns the page. Its setup is the page's to run: the reader picks
152
+ // a language there, and the node files the stack's first documents then. Nothing at startup
153
+ // calls it -- a stack that is never visited stays uninitialized, and says so on its page.
154
+ for (const spec of specs.filter((one) => one.module === INTRODUCE)) {
155
+ const root = rootOf(spec.module);
156
+ const handle = await runtime.launchNode(root, {
157
+ dir: root,
158
+ env: { NODE_AGENT_USER_TENANT: userTenant, NODE_AGENT_JOIN_TOKEN: joinToken },
159
+ });
160
+ names.push(handle.name);
161
+ await runtime.connect(userId, handle.name);
162
+ }
163
+ }
164
+ catch (e) {
165
+ await runtime.stopAll();
166
+ console.error(`node-agent failed to come up: ${e instanceof Error ? e.message : String(e)}`);
167
+ process.exit(1);
168
+ }
169
+ console.log(`bus: ${BIND}:${bus.port}`);
170
+ console.log(`nodes: ${names.join(', ')}`);
171
+ const user = runtime.bus?.user(runtime.busUser(userId));
172
+ console.log(`user: ${userId} -> ${[...(user?.nodes ?? [])].join(', ')}`);
173
+ // The webui prints the address it actually bound (port 0 gets a real port), so surface that line
174
+ // once it has had a moment to flush, without duplicating every node's log.
175
+ let webui;
176
+ if (names.includes('webui')) {
177
+ for (let attempt = 0; attempt < 40; attempt += 1) {
178
+ const match = runtime.nodeOutput('webui')?.match(/webui: (http:\/\/\S+)/);
179
+ if (match !== null && match !== undefined) {
180
+ webui = match[1];
181
+ console.log(`webui: ${webui}`);
182
+ break;
183
+ }
184
+ await new Promise((resolve) => setTimeout(resolve, 50));
185
+ }
186
+ }
187
+ // The optional door. NODE_AGENT_ACCESS_TOKEN is the switch: unset, none of the below runs, no port
188
+ // is opened, and the lines above are the whole output exactly as before. It is deliberately not
189
+ // NODE_AGENT_TOKEN: that one is the bus credential and never leaves this host.
190
+ let proxy;
191
+ const accessToken = (process.env.NODE_AGENT_ACCESS_TOKEN ?? '').trim();
192
+ if (accessToken !== '') {
193
+ if (webui === undefined) {
194
+ console.error('proxy not started: the webui never printed its address');
195
+ process.exitCode = 1;
196
+ }
197
+ else {
198
+ try {
199
+ proxy = await startProxy(proxyOptions(process.env, accessToken, webui));
200
+ console.log(`proxy: ${proxy.url}`);
201
+ }
202
+ catch (e) {
203
+ console.error(`proxy failed to start: ${e instanceof Error ? e.message : String(e)}`);
204
+ process.exitCode = 1;
205
+ }
206
+ }
207
+ }
208
+ const connectUrl = proxy?.url ?? webui;
209
+ console.log('Ready to connect');
210
+ if (connectUrl === undefined) {
211
+ console.log('connect: no web UI enabled');
212
+ }
213
+ else {
214
+ console.log(`connect: ${connectUrl}`);
215
+ }
216
+ await untilStopped();
217
+ await proxy?.close();
218
+ await runtime.stopBus();
219
+ }
220
+ await main();
221
+ process.exit(process.exitCode ?? 0);
222
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}