dominds 1.25.19 → 1.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/README.zh.md +17 -0
- package/dist/apps/runtime.d.ts +2 -4
- package/dist/apps-host/client.d.ts +2 -5
- package/dist/apps-host/ipc-types.d.ts +2 -5
- package/dist/apps-host/ipc-types.js +5 -1
- package/dist/bootstrap/rtws-cli.d.ts +1 -0
- package/dist/bootstrap/rtws-cli.js +8 -8
- package/dist/cli/cert.d.ts +4 -0
- package/dist/cli/cert.js +247 -0
- package/dist/cli/create.d.ts +1 -1
- package/dist/cli/create.js +1 -1
- package/dist/cli/read.js +1 -1
- package/dist/cli/tui.js +1 -1
- package/dist/cli/webui.d.ts +1 -1
- package/dist/cli/webui.js +35 -5
- package/dist/cli-runner.d.ts +31 -0
- package/dist/cli-runner.js +349 -0
- package/dist/cli.d.ts +0 -30
- package/dist/cli.js +540 -292
- package/dist/docs/cli-usage.md +40 -3
- package/dist/docs/cli-usage.zh.md +40 -3
- package/dist/docs/dialog-persistence.md +1 -1
- package/dist/docs/dominds-terminology.md +2 -2
- package/dist/llm/kernel-driver/drive.js +19 -14
- package/dist/runtime/driver-messages.d.ts +2 -0
- package/dist/runtime/driver-messages.js +24 -4
- package/dist/server/auth.d.ts +7 -0
- package/dist/server/auth.js +15 -4
- package/dist/server/certificates.d.ts +61 -0
- package/dist/server/certificates.js +418 -0
- package/dist/server/dominds-self-update.js +33 -121
- package/dist/server/network-hosts.d.ts +5 -0
- package/dist/server/network-hosts.js +277 -0
- package/dist/server/server-core.d.ts +12 -1
- package/dist/server/server-core.js +26 -4
- package/dist/server/websocket-handler.d.ts +3 -2
- package/dist/server/websocket-handler.js +15 -8
- package/dist/server-debug.d.ts +2 -0
- package/dist/server-debug.js +79 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +101 -126
- package/dist/supervisor-protocol.d.ts +15 -0
- package/dist/supervisor-protocol.js +4 -0
- package/package.json +6 -5
- package/dist/server/dominds-self-update-restart-helper.d.ts +0 -15
- package/dist/server/dominds-self-update-restart-helper.js +0 -305
package/dist/server.js
CHANGED
|
@@ -1,50 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.startServer = startServer;
|
|
37
|
-
/**
|
|
38
|
-
* Module: server
|
|
39
|
-
*
|
|
40
|
-
* HTTP/WebSocket server for both development and production modes:
|
|
41
|
-
* - Serves static files with MIME detection and SPA fallback (production)
|
|
42
|
-
* - Provides `/api/*` endpoints and `/ws` WebSocket communication
|
|
43
|
-
* - CLI bootstrap with optional cwd/port/host/mode parameters
|
|
44
|
-
* - Development mode: `tsx --watch src/server.ts -p <port> --mode dev`
|
|
45
|
-
* - Production mode: `node dist/server.js` (default port behavior: 5666-)
|
|
46
|
-
*/
|
|
47
|
-
const path = __importStar(require("path"));
|
|
48
4
|
const runtime_1 = require("./apps/runtime");
|
|
49
5
|
const dialog_display_state_1 = require("./dialog-display-state");
|
|
50
6
|
const kernel_driver_1 = require("./llm/kernel-driver");
|
|
@@ -54,7 +10,9 @@ const open_generation_recovery_1 = require("./recovery/open-generation-recovery"
|
|
|
54
10
|
const reply_delivery_recovery_1 = require("./recovery/reply-delivery-recovery");
|
|
55
11
|
const work_language_1 = require("./runtime/work-language");
|
|
56
12
|
const auth_1 = require("./server/auth");
|
|
13
|
+
const certificates_1 = require("./server/certificates");
|
|
57
14
|
const dominds_self_update_1 = require("./server/dominds-self-update");
|
|
15
|
+
const network_hosts_1 = require("./server/network-hosts");
|
|
58
16
|
const port_selection_1 = require("./server/port-selection");
|
|
59
17
|
const server_core_1 = require("./server/server-core");
|
|
60
18
|
const websocket_handler_1 = require("./server/websocket-handler");
|
|
@@ -75,45 +33,6 @@ process.on('uncaughtException', (error) => {
|
|
|
75
33
|
// Optionally, exit with code 1
|
|
76
34
|
// process.exit(1);
|
|
77
35
|
});
|
|
78
|
-
function parseArgs(argv) {
|
|
79
|
-
const out = {};
|
|
80
|
-
for (let i = 0; i < argv.length; i++) {
|
|
81
|
-
const a = argv[i];
|
|
82
|
-
if (a === '-C' || a === '--chdir') {
|
|
83
|
-
out['C'] = argv[i + 1];
|
|
84
|
-
i++;
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
if (a === '-p' || a === '--port') {
|
|
88
|
-
out['p'] = argv[i + 1];
|
|
89
|
-
i++;
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
if (a.startsWith('--port=')) {
|
|
93
|
-
out['p'] = a.slice('--port='.length);
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
if (a === '-H' || a === '--host') {
|
|
97
|
-
out['H'] = argv[i + 1];
|
|
98
|
-
i++;
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
if (a.startsWith('--host=')) {
|
|
102
|
-
out['H'] = a.slice('--host='.length);
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
if (a === '--mode') {
|
|
106
|
-
out['mode'] = argv[i + 1];
|
|
107
|
-
i++;
|
|
108
|
-
continue;
|
|
109
|
-
}
|
|
110
|
-
if (a.startsWith('--mode=')) {
|
|
111
|
-
out['mode'] = a.slice('--mode='.length);
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return out;
|
|
116
|
-
}
|
|
117
36
|
function attachPostListenStartupCancellation(httpServer, token) {
|
|
118
37
|
const originalStop = httpServer.stop.bind(httpServer);
|
|
119
38
|
httpServer.stop = async () => {
|
|
@@ -128,6 +47,15 @@ function getErrnoCode(error) {
|
|
|
128
47
|
const withCode = error;
|
|
129
48
|
return typeof withCode.code === 'string' ? withCode.code : undefined;
|
|
130
49
|
}
|
|
50
|
+
function buildAdjacentHttpsPortCandidates(params) {
|
|
51
|
+
if (params.preferredPort < 1 || params.preferredPort > 65535)
|
|
52
|
+
return [];
|
|
53
|
+
return (0, port_selection_1.buildWebuiPortCandidates)({
|
|
54
|
+
preferredPort: params.preferredPort,
|
|
55
|
+
strictPort: false,
|
|
56
|
+
direction: params.direction,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
131
59
|
async function runPostListenStartup(params) {
|
|
132
60
|
await new Promise((resolve) => {
|
|
133
61
|
setImmediate(resolve);
|
|
@@ -177,7 +105,6 @@ async function startServer(opts = {}) {
|
|
|
177
105
|
strictPort,
|
|
178
106
|
direction: portAutoDirection,
|
|
179
107
|
});
|
|
180
|
-
log.info(`Starting server in ${mode} mode on ${host}:${preferredPort} (${strictPort ? 'strict port' : `auto port ${portAutoDirection}`}; working language: ${(0, work_language_1.getWorkLanguage)()} from ${source})`);
|
|
181
108
|
// WebSocket clients set
|
|
182
109
|
const clients = new Set();
|
|
183
110
|
const serverMode = mode === 'dev' ? 'development' : 'production';
|
|
@@ -185,6 +112,26 @@ async function startServer(opts = {}) {
|
|
|
185
112
|
mode: serverMode,
|
|
186
113
|
env: process.env,
|
|
187
114
|
});
|
|
115
|
+
const certificateLookup = await (0, certificates_1.findAutoHttpsCertificateForHost)({
|
|
116
|
+
host,
|
|
117
|
+
certsDirAbs: opts.certsDirAbs,
|
|
118
|
+
});
|
|
119
|
+
for (const diagnostic of certificateLookup.diagnostics) {
|
|
120
|
+
log.warn(diagnostic.message);
|
|
121
|
+
}
|
|
122
|
+
const tls = certificateLookup.kind === 'found' && !strictPort ? certificateLookup.certificate : undefined;
|
|
123
|
+
const urlHost = (0, network_hosts_1.resolveHttpUrlHostForBindHost)(host);
|
|
124
|
+
log.info(`Starting server in ${mode} mode on ${(0, auth_1.formatServerOrigin)({
|
|
125
|
+
scheme: 'http',
|
|
126
|
+
host: urlHost,
|
|
127
|
+
port: preferredPort,
|
|
128
|
+
})} (bind ${host}; ${strictPort ? 'strict port' : `auto port ${portAutoDirection}`}; working language: ${(0, work_language_1.getWorkLanguage)()} from ${source})`);
|
|
129
|
+
if (certificateLookup.kind === 'found' && strictPort) {
|
|
130
|
+
log.info(`HTTPS certificate found but Dominds HTTPS is disabled for strict --port; assuming HTTPS, if needed, is handled by a front proxy (${certificateLookup.certificate.certPath})`);
|
|
131
|
+
}
|
|
132
|
+
else if (tls !== undefined) {
|
|
133
|
+
log.info(`HTTPS certificate available: ${tls.certPath} (matched host ${tls.matchedHost})`);
|
|
134
|
+
}
|
|
188
135
|
let startedCore = null;
|
|
189
136
|
let boundPort = null;
|
|
190
137
|
for (const candidatePort of portCandidates) {
|
|
@@ -199,7 +146,6 @@ async function startServer(opts = {}) {
|
|
|
199
146
|
const candidateServer = (0, server_core_1.createHttpServer)(config);
|
|
200
147
|
try {
|
|
201
148
|
boundPort = await candidateServer.start();
|
|
202
|
-
(0, websocket_handler_1.setupWebSocketServer)(candidateServer.getHttpServer(), clients, auth, (0, work_language_1.getWorkLanguage)(), config.mode);
|
|
203
149
|
startedCore = candidateServer;
|
|
204
150
|
break;
|
|
205
151
|
}
|
|
@@ -209,9 +155,6 @@ async function startServer(opts = {}) {
|
|
|
209
155
|
log.warn(`WebUI port ${candidatePort} is already in use; trying the next ${nextDirection} port`);
|
|
210
156
|
continue;
|
|
211
157
|
}
|
|
212
|
-
if (boundPort !== null && startedCore === null) {
|
|
213
|
-
await candidateServer.stop();
|
|
214
|
-
}
|
|
215
158
|
throw error;
|
|
216
159
|
}
|
|
217
160
|
}
|
|
@@ -225,8 +168,66 @@ async function startServer(opts = {}) {
|
|
|
225
168
|
if (!strictPort && boundPort !== preferredPort) {
|
|
226
169
|
log.warn(`WebUI preferred port ${preferredPort} was unavailable; listening on ${boundPort}`);
|
|
227
170
|
}
|
|
171
|
+
let httpsServer;
|
|
172
|
+
let httpsPort;
|
|
173
|
+
let httpsUrlHost;
|
|
174
|
+
if (tls !== undefined) {
|
|
175
|
+
const preferredHttpsPort = portAutoDirection === 'up' ? boundPort + 1 : boundPort - 1;
|
|
176
|
+
const httpsPortCandidates = buildAdjacentHttpsPortCandidates({
|
|
177
|
+
preferredPort: preferredHttpsPort,
|
|
178
|
+
direction: portAutoDirection,
|
|
179
|
+
});
|
|
180
|
+
for (const candidatePort of httpsPortCandidates) {
|
|
181
|
+
const config = {
|
|
182
|
+
mode: serverMode,
|
|
183
|
+
staticRoot: 'webapp/dist',
|
|
184
|
+
host,
|
|
185
|
+
port: candidatePort,
|
|
186
|
+
tls,
|
|
187
|
+
clients,
|
|
188
|
+
auth,
|
|
189
|
+
};
|
|
190
|
+
const candidateServer = (0, server_core_1.createHttpServer)(config);
|
|
191
|
+
try {
|
|
192
|
+
httpsPort = await candidateServer.start();
|
|
193
|
+
httpsServer = candidateServer;
|
|
194
|
+
httpsUrlHost = tls.matchedHost;
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
if (getErrnoCode(error) === 'EADDRINUSE') {
|
|
199
|
+
const nextDirection = portAutoDirection === 'down' ? 'lower' : 'higher';
|
|
200
|
+
log.warn(`WebUI HTTPS port ${candidatePort} is already in use; trying the next ${nextDirection} port`);
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
await startedCore.stop();
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (httpsServer === undefined || httpsPort === undefined || httpsUrlHost === undefined) {
|
|
208
|
+
await startedCore.stop();
|
|
209
|
+
throw new Error(`Failed to start WebUI HTTPS: no available adjacent port found from ${preferredHttpsPort}`);
|
|
210
|
+
}
|
|
211
|
+
log.info(`HTTPS WebUI ready: ${(0, auth_1.formatServerOrigin)({
|
|
212
|
+
scheme: 'https',
|
|
213
|
+
host: httpsUrlHost,
|
|
214
|
+
port: httpsPort,
|
|
215
|
+
})}`);
|
|
216
|
+
}
|
|
217
|
+
(0, websocket_handler_1.setupWebSocketServer)(httpsServer === undefined
|
|
218
|
+
? startedCore.getHttpServer()
|
|
219
|
+
: [startedCore.getHttpServer(), httpsServer.getHttpServer()], clients, auth, (0, work_language_1.getWorkLanguage)(), serverMode);
|
|
228
220
|
const postListenStartupToken = { canceled: false };
|
|
229
221
|
const httpServer = attachPostListenStartupCancellation(startedCore, postListenStartupToken);
|
|
222
|
+
if (httpsServer !== undefined) {
|
|
223
|
+
const originalStop = httpServer.stop.bind(httpServer);
|
|
224
|
+
const httpsServerToStop = httpsServer;
|
|
225
|
+
httpServer.stop = async () => {
|
|
226
|
+
postListenStartupToken.canceled = true;
|
|
227
|
+
await httpsServerToStop.stop();
|
|
228
|
+
await originalStop();
|
|
229
|
+
};
|
|
230
|
+
}
|
|
230
231
|
try {
|
|
231
232
|
const rtwsRootAbs = process.cwd();
|
|
232
233
|
(0, dominds_self_update_1.configureDomindsSelfUpdate)({
|
|
@@ -259,7 +260,7 @@ async function startServer(opts = {}) {
|
|
|
259
260
|
}
|
|
260
261
|
const postListenStartup = runPostListenStartup({
|
|
261
262
|
rtwsRootAbs,
|
|
262
|
-
kernel: { host, port: boundPort },
|
|
263
|
+
kernel: { scheme: 'http', host: urlHost, port: boundPort },
|
|
263
264
|
startBackendDriver,
|
|
264
265
|
token: postListenStartupToken,
|
|
265
266
|
});
|
|
@@ -279,41 +280,15 @@ async function startServer(opts = {}) {
|
|
|
279
280
|
}
|
|
280
281
|
throw error;
|
|
281
282
|
}
|
|
282
|
-
return {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
try {
|
|
294
|
-
process.chdir(wsDir);
|
|
295
|
-
}
|
|
296
|
-
catch (err) {
|
|
297
|
-
throw new Error(`Failed to change working directory to ${wsDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
// Get port, host, and mode from CLI args
|
|
301
|
-
const portSpecRaw = cliArgs['p'];
|
|
302
|
-
const parsedPort = typeof portSpecRaw === 'string' ? (0, port_selection_1.parseWebuiPortSpec)(portSpecRaw) : undefined;
|
|
303
|
-
if (portSpecRaw !== undefined && parsedPort === null) {
|
|
304
|
-
throw new Error('Invalid --port value: expected a port number, optionally suffixed with + or -');
|
|
305
|
-
}
|
|
306
|
-
const port = parsedPort?.port;
|
|
307
|
-
const strictPort = parsedPort?.strictPort;
|
|
308
|
-
const portAutoDirection = parsedPort?.portAutoDirection;
|
|
309
|
-
const host = cliArgs['H'] || undefined;
|
|
310
|
-
const mode = cliArgs['mode'] || undefined;
|
|
311
|
-
await startServer({ port, host, mode, strictPort, portAutoDirection, returnAfterListen: true });
|
|
312
|
-
}
|
|
313
|
-
// Start server if this file is run directly
|
|
314
|
-
if (require.main === module) {
|
|
315
|
-
main().catch((error) => {
|
|
316
|
-
log.error('Web UI startup failed', error);
|
|
317
|
-
process.exit(1);
|
|
318
|
-
});
|
|
283
|
+
return {
|
|
284
|
+
httpServer,
|
|
285
|
+
httpsServer,
|
|
286
|
+
auth,
|
|
287
|
+
host,
|
|
288
|
+
urlHost,
|
|
289
|
+
port: boundPort,
|
|
290
|
+
httpsPort,
|
|
291
|
+
httpsUrlHost,
|
|
292
|
+
mode,
|
|
293
|
+
};
|
|
319
294
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DomindsSelfUpdateRunKind } from '@longrun-ai/kernel/types';
|
|
2
|
+
export declare const DOMINDS_SUPERVISOR_RESTART_WEBUI = "dominds.supervisor.restart_webui.v1";
|
|
3
|
+
export type DomindsSupervisorRestartRunKind = Extract<DomindsSelfUpdateRunKind, 'global' | 'npx'>;
|
|
4
|
+
export type DomindsSupervisorRestartWebuiMessage = Readonly<{
|
|
5
|
+
type: typeof DOMINDS_SUPERVISOR_RESTART_WEBUI;
|
|
6
|
+
cwd: string;
|
|
7
|
+
host: string;
|
|
8
|
+
port: number;
|
|
9
|
+
traceFile: string;
|
|
10
|
+
debugDir: string;
|
|
11
|
+
currentVersion: string;
|
|
12
|
+
targetVersion: string | null;
|
|
13
|
+
runKind: DomindsSupervisorRestartRunKind;
|
|
14
|
+
}>;
|
|
15
|
+
export type DomindsRunnerToSupervisorMessage = DomindsSupervisorRestartWebuiMessage;
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dominds",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.1",
|
|
4
4
|
"description": "Dominds CLI and aggregation shell for the LongRun AI kernel/runtime packages.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
9
|
"bin": {
|
|
10
|
-
"dominds": "dist/cli.js"
|
|
10
|
+
"dominds": "dist/cli.js",
|
|
11
|
+
"dominds-runner": "dist/cli-runner.js"
|
|
11
12
|
},
|
|
12
13
|
"exports": {
|
|
13
14
|
"./cli": {
|
|
@@ -52,9 +53,9 @@
|
|
|
52
53
|
"ws": "^8.19.0",
|
|
53
54
|
"yaml": "^2.8.2",
|
|
54
55
|
"zod": "^4.3.6",
|
|
56
|
+
"@longrun-ai/kernel": "1.16.0",
|
|
55
57
|
"@longrun-ai/codex-auth": "0.13.0",
|
|
56
|
-
"@longrun-ai/
|
|
57
|
-
"@longrun-ai/shell": "1.15.12"
|
|
58
|
+
"@longrun-ai/shell": "1.16.0"
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|
|
60
61
|
"@types/node": "^25.3.5",
|
|
@@ -83,6 +84,6 @@
|
|
|
83
84
|
"lint:types": "pnpm -r --filter './packages/*' --filter ./webapp run lint:types && tsc -p main/tsconfig.dev.json --noEmit",
|
|
84
85
|
"format": "prettier --write \"{main,webapp/src,docs,tests}/**/*.{js,jsx,ts,tsx}\" && prettier --write \"{main,webapp/src,docs,tests}/**/*.{css,md,json,html}\"",
|
|
85
86
|
"format:check": "prettier --check \"{main,webapp/src,docs,tests}/**/*.{js,jsx,ts,tsx}\" && prettier --check \"{main,webapp/src,docs,tests}/**/*.{css,md,json,html}\"",
|
|
86
|
-
"build:backend": "pnpm -C tests run manual-size-guard && rm -rf ./dist && pnpm -r --filter './packages/*' --filter ./codex-auth run build && tsc -p main/tsconfig.json --rootDir main && mkdir -p dist/llm dist/minds dist/tools dist/snippets dist/docs && cp main/llm/defaults.yaml dist/llm/ && cp -r main/minds/builtin dist/minds/ && cp -r main/tools/prompts dist/tools/ && cp -r snippets/. dist/snippets/ && cp -r docs/. dist/docs/ && chmod +x ./dist/cli.js ./dist/cli/*.js 2>/dev/null"
|
|
87
|
+
"build:backend": "pnpm -C tests run manual-size-guard && rm -rf ./dist && pnpm -r --filter './packages/*' --filter ./codex-auth run build && tsc -p main/tsconfig.json --rootDir main && mkdir -p dist/llm dist/minds dist/tools dist/snippets dist/docs && cp main/llm/defaults.yaml dist/llm/ && cp -r main/minds/builtin dist/minds/ && cp -r main/tools/prompts dist/tools/ && cp -r snippets/. dist/snippets/ && cp -r docs/. dist/docs/ && chmod +x ./dist/cli.js ./dist/cli-runner.js ./dist/server-debug.js ./dist/cli/*.js 2>/dev/null"
|
|
87
88
|
}
|
|
88
89
|
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type RestartHelperStdioMode = 'inherit' | 'ignore';
|
|
2
|
-
export type RestartHelperPayload = Readonly<{
|
|
3
|
-
command: string;
|
|
4
|
-
args: readonly string[];
|
|
5
|
-
cwd: string;
|
|
6
|
-
host: string;
|
|
7
|
-
port: number;
|
|
8
|
-
retiringPid: number;
|
|
9
|
-
forceKillAfterMs: number;
|
|
10
|
-
probeIntervalMs: number;
|
|
11
|
-
portReleaseTimeoutMs: number;
|
|
12
|
-
stdioMode: RestartHelperStdioMode;
|
|
13
|
-
traceFile: string;
|
|
14
|
-
debugDir: string;
|
|
15
|
-
}>;
|
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const child_process_1 = require("child_process");
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const net_1 = __importDefault(require("net"));
|
|
9
|
-
const time_1 = require("@longrun-ai/kernel/utils/time");
|
|
10
|
-
function isRecord(value) {
|
|
11
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
12
|
-
}
|
|
13
|
-
function isStringArray(value) {
|
|
14
|
-
return Array.isArray(value) && value.every((item) => typeof item === 'string');
|
|
15
|
-
}
|
|
16
|
-
function readString(value, key) {
|
|
17
|
-
const candidate = value[key];
|
|
18
|
-
if (typeof candidate !== 'string' || candidate.trim() === '') {
|
|
19
|
-
throw new Error(`Invalid Dominds restart helper payload: ${key} must be a non-empty string`);
|
|
20
|
-
}
|
|
21
|
-
return candidate;
|
|
22
|
-
}
|
|
23
|
-
function readNumber(value, key) {
|
|
24
|
-
const candidate = value[key];
|
|
25
|
-
if (typeof candidate !== 'number' || !Number.isFinite(candidate)) {
|
|
26
|
-
throw new Error(`Invalid Dominds restart helper payload: ${key} must be a finite number`);
|
|
27
|
-
}
|
|
28
|
-
return candidate;
|
|
29
|
-
}
|
|
30
|
-
function readPositiveInteger(value, key) {
|
|
31
|
-
const candidate = readNumber(value, key);
|
|
32
|
-
if (!Number.isInteger(candidate) || candidate <= 0) {
|
|
33
|
-
throw new Error(`Invalid Dominds restart helper payload: ${key} must be a positive integer`);
|
|
34
|
-
}
|
|
35
|
-
return candidate;
|
|
36
|
-
}
|
|
37
|
-
function readPort(value, key) {
|
|
38
|
-
const candidate = readPositiveInteger(value, key);
|
|
39
|
-
if (candidate > 65535) {
|
|
40
|
-
throw new Error(`Invalid Dominds restart helper payload: ${key} must be <= 65535`);
|
|
41
|
-
}
|
|
42
|
-
return candidate;
|
|
43
|
-
}
|
|
44
|
-
function parsePayload(raw) {
|
|
45
|
-
if (typeof raw !== 'string' || raw.trim() === '') {
|
|
46
|
-
throw new Error('Missing Dominds restart helper payload');
|
|
47
|
-
}
|
|
48
|
-
const parsed = JSON.parse(raw);
|
|
49
|
-
if (!isRecord(parsed)) {
|
|
50
|
-
throw new Error('Invalid Dominds restart helper payload: expected an object');
|
|
51
|
-
}
|
|
52
|
-
const args = parsed['args'];
|
|
53
|
-
if (!isStringArray(args)) {
|
|
54
|
-
throw new Error('Invalid Dominds restart helper payload: args must be a string array');
|
|
55
|
-
}
|
|
56
|
-
const stdioMode = parsed['stdioMode'];
|
|
57
|
-
if (stdioMode !== 'inherit' && stdioMode !== 'ignore') {
|
|
58
|
-
throw new Error('Invalid Dominds restart helper payload: stdioMode must be inherit or ignore');
|
|
59
|
-
}
|
|
60
|
-
return {
|
|
61
|
-
command: readString(parsed, 'command'),
|
|
62
|
-
args,
|
|
63
|
-
cwd: readString(parsed, 'cwd'),
|
|
64
|
-
host: readString(parsed, 'host'),
|
|
65
|
-
port: readPort(parsed, 'port'),
|
|
66
|
-
retiringPid: readPositiveInteger(parsed, 'retiringPid'),
|
|
67
|
-
forceKillAfterMs: readPositiveInteger(parsed, 'forceKillAfterMs'),
|
|
68
|
-
probeIntervalMs: readPositiveInteger(parsed, 'probeIntervalMs'),
|
|
69
|
-
portReleaseTimeoutMs: readPositiveInteger(parsed, 'portReleaseTimeoutMs'),
|
|
70
|
-
stdioMode,
|
|
71
|
-
traceFile: readString(parsed, 'traceFile'),
|
|
72
|
-
debugDir: readString(parsed, 'debugDir'),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function trace(payload, event, details = {}) {
|
|
76
|
-
const record = {
|
|
77
|
-
...details,
|
|
78
|
-
event,
|
|
79
|
-
capturedAt: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
80
|
-
helperPid: process.pid,
|
|
81
|
-
platform: process.platform,
|
|
82
|
-
};
|
|
83
|
-
try {
|
|
84
|
-
fs_1.default.mkdirSync(payload.debugDir, { recursive: true });
|
|
85
|
-
fs_1.default.appendFileSync(payload.traceFile, `${JSON.stringify(record)}\n`, 'utf8');
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
89
|
-
console.error(`Failed to write Dominds restart helper trace: ${message}`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function isPortBusy(payload) {
|
|
93
|
-
return new Promise((resolve) => {
|
|
94
|
-
const socket = net_1.default.createConnection({ host: payload.host, port: payload.port });
|
|
95
|
-
let settled = false;
|
|
96
|
-
const finish = (busy) => {
|
|
97
|
-
if (settled)
|
|
98
|
-
return;
|
|
99
|
-
settled = true;
|
|
100
|
-
socket.destroy();
|
|
101
|
-
resolve(busy);
|
|
102
|
-
};
|
|
103
|
-
socket.once('connect', () => finish(true));
|
|
104
|
-
socket.once('error', () => finish(false));
|
|
105
|
-
socket.setTimeout(1000, () => finish(true));
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
function getErrorCode(error) {
|
|
109
|
-
return isRecord(error) && typeof error['code'] === 'string' ? error['code'] : '';
|
|
110
|
-
}
|
|
111
|
-
function assertValidRetiringPid(payload) {
|
|
112
|
-
if (!Number.isInteger(payload.retiringPid) || payload.retiringPid <= 0) {
|
|
113
|
-
throw new Error(`Invalid retiring Dominds pid for restart: ${String(payload.retiringPid)}`);
|
|
114
|
-
}
|
|
115
|
-
if (payload.retiringPid === process.pid) {
|
|
116
|
-
throw new Error(`Refusing to kill restart helper pid ${String(process.pid)}`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
function isRetiringProcessAlive(payload) {
|
|
120
|
-
assertValidRetiringPid(payload);
|
|
121
|
-
try {
|
|
122
|
-
process.kill(payload.retiringPid, 0);
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
const code = getErrorCode(error);
|
|
127
|
-
if (code === 'ESRCH')
|
|
128
|
-
return false;
|
|
129
|
-
if (code === 'EPERM')
|
|
130
|
-
return true;
|
|
131
|
-
throw error;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
async function delayMs(ms) {
|
|
135
|
-
await new Promise((resolve) => {
|
|
136
|
-
setTimeout(resolve, ms);
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
async function waitForRetiringProcessExit(payload, timeoutMs) {
|
|
140
|
-
const deadline = Date.now() + timeoutMs;
|
|
141
|
-
while (Date.now() < deadline) {
|
|
142
|
-
if (!isRetiringProcessAlive(payload))
|
|
143
|
-
return true;
|
|
144
|
-
await delayMs(payload.probeIntervalMs);
|
|
145
|
-
}
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
async function waitForPortReleaseUntil(payload, deadline) {
|
|
149
|
-
let consecutiveReady = 0;
|
|
150
|
-
while (Date.now() < deadline) {
|
|
151
|
-
if (!(await isPortBusy(payload))) {
|
|
152
|
-
consecutiveReady += 1;
|
|
153
|
-
if (consecutiveReady >= 2)
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
consecutiveReady = 0;
|
|
158
|
-
}
|
|
159
|
-
await delayMs(payload.probeIntervalMs);
|
|
160
|
-
}
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
async function runBestEffortKiller(payload, command, args) {
|
|
164
|
-
await new Promise((resolve) => {
|
|
165
|
-
trace(payload, 'helper.force_kill.spawn', { command, args });
|
|
166
|
-
const killer = (0, child_process_1.spawn)(command, [...args], {
|
|
167
|
-
stdio: payload.stdioMode,
|
|
168
|
-
windowsHide: payload.stdioMode !== 'inherit',
|
|
169
|
-
});
|
|
170
|
-
killer.once('error', (error) => {
|
|
171
|
-
trace(payload, 'helper.force_kill.error', { message: error.message });
|
|
172
|
-
resolve();
|
|
173
|
-
});
|
|
174
|
-
killer.once('exit', (code, signal) => {
|
|
175
|
-
trace(payload, 'helper.force_kill.exit', { code, signal });
|
|
176
|
-
resolve();
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
async function forceKillRetiringProcess(payload) {
|
|
181
|
-
assertValidRetiringPid(payload);
|
|
182
|
-
try {
|
|
183
|
-
process.kill(payload.retiringPid, 'SIGKILL');
|
|
184
|
-
}
|
|
185
|
-
catch (error) {
|
|
186
|
-
const code = getErrorCode(error);
|
|
187
|
-
if (code === 'ESRCH')
|
|
188
|
-
return;
|
|
189
|
-
if (process.platform !== 'win32')
|
|
190
|
-
throw error;
|
|
191
|
-
}
|
|
192
|
-
if (process.platform === 'win32') {
|
|
193
|
-
await runBestEffortKiller(payload, 'taskkill.exe', ['/PID', String(payload.retiringPid), '/F']);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
async function runRestartHelper(payload) {
|
|
197
|
-
const detached = payload.stdioMode !== 'inherit';
|
|
198
|
-
trace(payload, 'helper.start', {
|
|
199
|
-
command: payload.command,
|
|
200
|
-
args: payload.args,
|
|
201
|
-
cwd: payload.cwd,
|
|
202
|
-
host: payload.host,
|
|
203
|
-
port: payload.port,
|
|
204
|
-
retiringPid: payload.retiringPid,
|
|
205
|
-
detached,
|
|
206
|
-
stdioMode: payload.stdioMode,
|
|
207
|
-
forceKillAfterMs: payload.forceKillAfterMs,
|
|
208
|
-
portReleaseTimeoutMs: payload.portReleaseTimeoutMs,
|
|
209
|
-
probeIntervalMs: payload.probeIntervalMs,
|
|
210
|
-
});
|
|
211
|
-
const forceKillDeadline = Date.now() + payload.forceKillAfterMs;
|
|
212
|
-
trace(payload, 'helper.wait_retiring_process_exit.start', {
|
|
213
|
-
retiringPid: payload.retiringPid,
|
|
214
|
-
timeoutMs: payload.forceKillAfterMs,
|
|
215
|
-
});
|
|
216
|
-
const exitedGracefully = await waitForRetiringProcessExit(payload, payload.forceKillAfterMs);
|
|
217
|
-
trace(payload, 'helper.wait_retiring_process_exit.finish', {
|
|
218
|
-
retiringPid: payload.retiringPid,
|
|
219
|
-
exited: exitedGracefully,
|
|
220
|
-
});
|
|
221
|
-
if (!exitedGracefully) {
|
|
222
|
-
trace(payload, 'helper.force_kill.start', { retiringPid: payload.retiringPid });
|
|
223
|
-
await forceKillRetiringProcess(payload);
|
|
224
|
-
trace(payload, 'helper.force_kill.finish', { retiringPid: payload.retiringPid });
|
|
225
|
-
trace(payload, 'helper.wait_retiring_process_exit_after_kill.start', {
|
|
226
|
-
retiringPid: payload.retiringPid,
|
|
227
|
-
timeoutMs: payload.portReleaseTimeoutMs,
|
|
228
|
-
});
|
|
229
|
-
const exitedAfterKill = await waitForRetiringProcessExit(payload, payload.portReleaseTimeoutMs);
|
|
230
|
-
trace(payload, 'helper.wait_retiring_process_exit_after_kill.finish', {
|
|
231
|
-
retiringPid: payload.retiringPid,
|
|
232
|
-
exited: exitedAfterKill,
|
|
233
|
-
});
|
|
234
|
-
if (!exitedAfterKill) {
|
|
235
|
-
throw new Error(`Dominds retiring process is still alive after force-killing pid ${String(payload.retiringPid)}`);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
const portReleaseDeadline = Math.max(forceKillDeadline, Date.now() + payload.portReleaseTimeoutMs);
|
|
239
|
-
trace(payload, 'helper.wait_port_release.start', {
|
|
240
|
-
host: payload.host,
|
|
241
|
-
port: payload.port,
|
|
242
|
-
deadlineMsFromNow: portReleaseDeadline - Date.now(),
|
|
243
|
-
});
|
|
244
|
-
const portReleased = await waitForPortReleaseUntil(payload, portReleaseDeadline);
|
|
245
|
-
trace(payload, 'helper.wait_port_release.finish', {
|
|
246
|
-
host: payload.host,
|
|
247
|
-
port: payload.port,
|
|
248
|
-
released: portReleased,
|
|
249
|
-
});
|
|
250
|
-
if (!portReleased) {
|
|
251
|
-
throw new Error(`Dominds restart port is still busy after retiring pid ${String(payload.retiringPid)} exited; port=${String(payload.host)}:${String(payload.port)}`);
|
|
252
|
-
}
|
|
253
|
-
trace(payload, 'helper.spawn_new_process.start', {
|
|
254
|
-
command: payload.command,
|
|
255
|
-
args: payload.args,
|
|
256
|
-
cwd: payload.cwd,
|
|
257
|
-
detached,
|
|
258
|
-
stdioMode: payload.stdioMode,
|
|
259
|
-
});
|
|
260
|
-
const child = (0, child_process_1.spawn)(payload.command, [...payload.args], {
|
|
261
|
-
cwd: payload.cwd,
|
|
262
|
-
env: process.env,
|
|
263
|
-
detached,
|
|
264
|
-
stdio: payload.stdioMode,
|
|
265
|
-
shell: false,
|
|
266
|
-
windowsHide: payload.stdioMode !== 'inherit',
|
|
267
|
-
});
|
|
268
|
-
if (detached)
|
|
269
|
-
child.unref();
|
|
270
|
-
await new Promise((resolve, reject) => {
|
|
271
|
-
child.once('error', (error) => {
|
|
272
|
-
trace(payload, 'helper.spawn_new_process.error', {
|
|
273
|
-
command: payload.command,
|
|
274
|
-
args: payload.args,
|
|
275
|
-
cwd: payload.cwd,
|
|
276
|
-
message: error.message,
|
|
277
|
-
stack: error.stack ?? null,
|
|
278
|
-
});
|
|
279
|
-
reject(error);
|
|
280
|
-
});
|
|
281
|
-
child.once('spawn', resolve);
|
|
282
|
-
});
|
|
283
|
-
trace(payload, 'helper.spawn_new_process.finish', { childPid: child.pid ?? null });
|
|
284
|
-
trace(payload, 'helper.exit', { code: 0 });
|
|
285
|
-
}
|
|
286
|
-
async function main() {
|
|
287
|
-
let payload = null;
|
|
288
|
-
try {
|
|
289
|
-
payload = parsePayload(process.argv[2]);
|
|
290
|
-
await runRestartHelper(payload);
|
|
291
|
-
process.exit(0);
|
|
292
|
-
}
|
|
293
|
-
catch (error) {
|
|
294
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
295
|
-
const stack = error instanceof Error ? (error.stack ?? null) : null;
|
|
296
|
-
if (payload !== null) {
|
|
297
|
-
trace(payload, 'helper.error', { message, stack });
|
|
298
|
-
}
|
|
299
|
-
console.error(message);
|
|
300
|
-
process.exit(1);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
if (require.main === module) {
|
|
304
|
-
void main();
|
|
305
|
-
}
|