@agent-webui/ai-desk-daemon 1.0.62-beta1 → 1.0.63

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 CHANGED
@@ -239,7 +239,7 @@ await daemonService.executeStreaming(
239
239
  "*"
240
240
  ],
241
241
  "allowed_working_dirs": [
242
- "/path/to/your/home"
242
+ "*"
243
243
  ],
244
244
  "require_authentication": false,
245
245
  "auth_token": "",
package/bin/cli.js CHANGED
@@ -11,13 +11,6 @@ const path = require('path');
11
11
  const { start, stop, restart, status } = require('../lib/daemon-manager');
12
12
  const { getLogPath } = require('../lib/platform');
13
13
  const { VERSION } = require('../lib/platform');
14
- const { getPort } = require('../lib/config');
15
- const {
16
- configureRegistryUrl,
17
- getRegistryConfig,
18
- reportLifecycle,
19
- syncRegistryConfigToDaemonConfig,
20
- } = require('../lib/daemon-registry');
21
14
  const { upgradePackage } = require('../lib/self-upgrade');
22
15
 
23
16
  function wait(ms) {
@@ -135,74 +128,11 @@ function configureRequestedMode(mode) {
135
128
  });
136
129
  }
137
130
 
138
- async function reportRegistryLifecycle(event) {
139
- try {
140
- await reportLifecycle(event, {
141
- port: Number(getPort()),
142
- version: VERSION,
143
- });
144
- } catch (error) {
145
- console.warn(chalk.yellow(`[registry] Failed to report daemon ${event}: ${error.message || error}`));
146
- }
147
- }
148
-
149
- function syncRegistryConfigForDaemonStart() {
150
- try {
151
- syncRegistryConfigToDaemonConfig();
152
- } catch (error) {
153
- console.warn(chalk.yellow(`[registry] Failed to sync daemon registry config: ${error.message || error}`));
154
- }
155
- }
156
-
157
131
  program
158
132
  .name('aidesk')
159
133
  .description('AI Desk Daemon - CLI tool for managing the AI Desk daemon service')
160
134
  .version(VERSION);
161
135
 
162
- const registryCommand = program
163
- .command('registry')
164
- .description('Manage shared runtime registry backend settings');
165
-
166
- registryCommand
167
- .command('set-url <url>')
168
- .description('Persist the AI Desk backend URL used for daemon registry reporting')
169
- .option('--insecure-skip-tls-verify', 'Skip TLS certificate verification for this registry URL')
170
- .option('--strict-tls', 'Require strict TLS certificate verification for this registry URL')
171
- .action((url, options) => {
172
- try {
173
- if (options.insecureSkipTlsVerify && options.strictTls) {
174
- throw new Error('Use either --insecure-skip-tls-verify or --strict-tls, not both');
175
- }
176
- const tlsInsecureSkipVerify = options.insecureSkipTlsVerify
177
- ? true
178
- : (options.strictTls ? false : undefined);
179
- const config = configureRegistryUrl(url, { tlsInsecureSkipVerify });
180
- console.log(chalk.green('✓ Registry URL updated'));
181
- console.log(`API base URL: ${config.apiBaseUrl}`);
182
- console.log(`TLS verification: ${config.tlsInsecureSkipVerify ? 'skip for this URL' : 'strict'}`);
183
- console.log(chalk.cyan('Restart the daemon for the new registry URL to be used by background heartbeats.'));
184
- } catch (error) {
185
- console.error(chalk.red('Failed to update registry URL:'), error.message);
186
- process.exit(1);
187
- }
188
- });
189
-
190
- registryCommand
191
- .command('status')
192
- .description('Show the effective daemon registry backend settings')
193
- .action(() => {
194
- const config = getRegistryConfig();
195
- if (!config) {
196
- console.log(chalk.yellow('Registry reporting is disabled'));
197
- return;
198
- }
199
- console.log(`API base URL: ${config.apiBaseUrl}`);
200
- console.log(`RC account ID: ${config.rcAccountId || '(empty)'}`);
201
- console.log(`RC extension ID: ${config.rcExtensionId || '(empty)'}`);
202
- console.log(`RC username: ${config.rcUsername || '(empty)'}`);
203
- console.log(`TLS verification: ${config.tlsInsecureSkipVerify ? 'skip for this URL' : 'strict'}`);
204
- });
205
-
206
136
  // Start command
207
137
  program
208
138
  .command('start')
@@ -215,9 +145,7 @@ program
215
145
  try {
216
146
  const mode = resolveRequestedMode(options) || 'native';
217
147
  const modeResult = configureRequestedMode(mode);
218
- syncRegistryConfigForDaemonStart();
219
148
  start();
220
- await reportRegistryLifecycle('start');
221
149
  if (mode === 'cli-anything' && modeResult?.runtimeInfo?.cliAnythingPath) {
222
150
  console.log(chalk.cyan(`CLI-Anything mode configured: ${modeResult.runtimeInfo.cliAnythingPath}`));
223
151
  } else if (mode === 'native') {
@@ -243,7 +171,7 @@ program
243
171
  const tail = startUnixLogFollow(logPath);
244
172
 
245
173
  // Handle Ctrl+C - stop the daemon
246
- process.on('SIGINT', async () => {
174
+ process.on('SIGINT', () => {
247
175
  console.log(chalk.yellow('\n\n⏹ Stopping daemon...'));
248
176
  tail.kill();
249
177
 
@@ -251,7 +179,6 @@ program
251
179
  // Stop the daemon
252
180
  const { stop } = require('../lib/daemon-manager');
253
181
  stop();
254
- await reportRegistryLifecycle('stop');
255
182
  console.log(chalk.green('✓ Daemon stopped successfully'));
256
183
  } catch (error) {
257
184
  console.error(chalk.red('✗ Failed to stop daemon:'), error.message);
@@ -265,7 +192,7 @@ program
265
192
 
266
193
  const pollInterval = startWindowsLogFollow(logPath);
267
194
 
268
- process.on('SIGINT', async () => {
195
+ process.on('SIGINT', () => {
269
196
  clearInterval(pollInterval);
270
197
  console.log(chalk.yellow('\n\n⏹ Stopping daemon...'));
271
198
 
@@ -273,7 +200,6 @@ program
273
200
  // Stop the daemon
274
201
  const { stop } = require('../lib/daemon-manager');
275
202
  stop();
276
- await reportRegistryLifecycle('stop');
277
203
  console.log(chalk.green('✓ Daemon stopped successfully'));
278
204
  } catch (error) {
279
205
  console.error(chalk.red('✗ Failed to stop daemon:'), error.message);
@@ -296,7 +222,6 @@ program
296
222
  .action(async () => {
297
223
  try {
298
224
  stop();
299
- await reportRegistryLifecycle('stop');
300
225
  console.log(chalk.green('✓ Daemon stopped successfully'));
301
226
  } catch (error) {
302
227
  console.error(chalk.red('✗ Failed to stop daemon:'), error.message);
@@ -315,9 +240,7 @@ program
315
240
  try {
316
241
  const mode = resolveRequestedMode(options);
317
242
  const modeResult = configureRequestedMode(mode);
318
- syncRegistryConfigForDaemonStart();
319
243
  restart();
320
- await reportRegistryLifecycle('restart');
321
244
  if (mode === 'cli-anything' && modeResult?.runtimeInfo?.cliAnythingPath) {
322
245
  console.log(chalk.cyan(`CLI-Anything mode configured: ${modeResult.runtimeInfo.cliAnythingPath}`));
323
246
  } else if (mode === 'native') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-webui/ai-desk-daemon",
3
- "version": "1.0.62-beta1",
3
+ "version": "1.0.63",
4
4
  "description": "AI Desk Daemon - CLI tool for managing the AI Desk daemon service",
5
5
  "workspaces": [
6
6
  "packages/*"
@@ -39,16 +39,16 @@
39
39
  "chalk": "^4.1.2"
40
40
  },
41
41
  "optionalDependencies": {
42
- "@agent-webui/ai-desk-daemon-darwin-arm64": "1.0.62-beta1",
43
- "@agent-webui/ai-desk-daemon-darwin-x64": "1.0.62-beta1",
44
- "@agent-webui/ai-desk-daemon-linux-arm64": "1.0.62-beta1",
45
- "@agent-webui/ai-desk-daemon-linux-x64": "1.0.62-beta1",
46
- "@agent-webui/ai-desk-daemon-win32-x64": "1.0.62-beta1",
47
- "@agent-webui/ai-desk-python-darwin-arm64": "1.0.62-beta1",
48
- "@agent-webui/ai-desk-python-darwin-x64": "1.0.62-beta1",
49
- "@agent-webui/ai-desk-python-linux-arm64": "1.0.62-beta1",
50
- "@agent-webui/ai-desk-python-linux-x64": "1.0.62-beta1",
51
- "@agent-webui/ai-desk-python-win32-x64": "1.0.62-beta1"
42
+ "@agent-webui/ai-desk-daemon-darwin-arm64": "1.0.63",
43
+ "@agent-webui/ai-desk-daemon-darwin-x64": "1.0.63",
44
+ "@agent-webui/ai-desk-daemon-linux-arm64": "1.0.63",
45
+ "@agent-webui/ai-desk-daemon-linux-x64": "1.0.63",
46
+ "@agent-webui/ai-desk-daemon-win32-x64": "1.0.63",
47
+ "@agent-webui/ai-desk-python-darwin-arm64": "1.0.63",
48
+ "@agent-webui/ai-desk-python-darwin-x64": "1.0.63",
49
+ "@agent-webui/ai-desk-python-linux-arm64": "1.0.63",
50
+ "@agent-webui/ai-desk-python-linux-x64": "1.0.63",
51
+ "@agent-webui/ai-desk-python-win32-x64": "1.0.63"
52
52
  },
53
53
  "repository": {
54
54
  "type": "git",
@@ -1,392 +0,0 @@
1
- const fs = require('fs');
2
- const os = require('os');
3
- const path = require('path');
4
- const http = require('http');
5
- const https = require('https');
6
- const crypto = require('crypto');
7
-
8
- const DEFAULT_REGISTRY_API_BASE_URL = 'https://desk.int.rclabenv.com/';
9
-
10
- function trim(value) {
11
- if (typeof value === 'string') return value.trim();
12
- if (typeof value === 'number' && Number.isFinite(value)) return String(value);
13
- return '';
14
- }
15
-
16
- function normalizeApiBaseUrl(value) {
17
- const raw = trim(value).replace(/\/+$/, '');
18
- if (!raw) return '';
19
- return raw.endsWith('/api/v1') ? raw : `${raw}/api/v1`;
20
- }
21
-
22
- function parseTruthyEnv(value) {
23
- const raw = trim(value).toLowerCase();
24
- if (!raw) return null;
25
- return raw === '1' || raw === 'true' || raw === 'yes' || raw === 'on';
26
- }
27
-
28
- function isPrivateRegistryHost(hostname) {
29
- const host = trim(hostname).toLowerCase();
30
- return (
31
- host === 'localhost' ||
32
- host === '127.0.0.1' ||
33
- host.endsWith('.local') ||
34
- /^10\./.test(host) ||
35
- /^192\.168\./.test(host) ||
36
- /^172\.(1[6-9]|2\d|3[0-1])\./.test(host)
37
- );
38
- }
39
-
40
- function inferTLSInsecureSkipVerify(apiBaseUrl) {
41
- try {
42
- const url = new URL(normalizeApiBaseUrl(apiBaseUrl));
43
- if (url.protocol !== 'https:') return false;
44
- if (url.hostname === 'desk.int.rclabenv.com') return false;
45
- return isPrivateRegistryHost(url.hostname);
46
- } catch {
47
- return false;
48
- }
49
- }
50
-
51
- function readRegistrySessionIdentity(homeDir = os.homedir()) {
52
- const sessionPath = path.join(homeDir, '.aidesktop', 'session.json');
53
- try {
54
- if (!fs.existsSync(sessionPath)) return null;
55
- const session = JSON.parse(fs.readFileSync(sessionPath, 'utf8'));
56
- if (!session || typeof session !== 'object') return null;
57
- const apiBaseUrl = normalizeApiBaseUrl(session.api_base_url || session.apiBaseUrl);
58
- const rcAccountId = trim(session.account_id || session.accountId);
59
- const rcExtensionId = trim(session.extension_id || session.extensionId);
60
- const rcUsername = trim(session.rc_username || session.rcUsername);
61
- const tlsInsecureSkipVerify = Boolean(
62
- session.tls_insecure_skip_verify || session.tlsInsecureSkipVerify,
63
- );
64
- if (!apiBaseUrl && !rcAccountId && !rcExtensionId && !rcUsername) return null;
65
- return { apiBaseUrl, rcAccountId, rcExtensionId, rcUsername, tlsInsecureSkipVerify };
66
- } catch {
67
- return null;
68
- }
69
- }
70
-
71
- function readRegistryConfigFromDaemonConfig(homeDir = os.homedir()) {
72
- const configPath = path.join(homeDir, '.aidesktop', 'daemon-config.json');
73
- try {
74
- if (!fs.existsSync(configPath)) return null;
75
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
76
- const registry = config && typeof config === 'object' ? config.registry : null;
77
- if (!registry || typeof registry !== 'object') return null;
78
- const sessionIdentity = readRegistrySessionIdentity(homeDir);
79
- const apiBaseUrl = normalizeApiBaseUrl(
80
- registry.api_base_url || registry.apiBaseUrl || DEFAULT_REGISTRY_API_BASE_URL,
81
- );
82
- const rcAccountId = trim(registry.rc_account_id || registry.rcAccountId) ||
83
- sessionIdentity?.rcAccountId || '';
84
- const rcExtensionId = trim(registry.rc_extension_id || registry.rcExtensionId) ||
85
- sessionIdentity?.rcExtensionId || '';
86
- if (!apiBaseUrl) return null;
87
- return {
88
- apiBaseUrl,
89
- rcAccountId,
90
- rcExtensionId,
91
- rcUsername: trim(registry.rc_username || registry.rcUsername) || sessionIdentity?.rcUsername || '',
92
- tlsInsecureSkipVerify: Boolean(registry.tls_insecure_skip_verify || registry.tlsInsecureSkipVerify),
93
- };
94
- } catch {
95
- return null;
96
- }
97
- }
98
-
99
- function getRegistryConfig(env = process.env, homeDir = os.homedir()) {
100
- const daemonConfig = readRegistryConfigFromDaemonConfig(homeDir);
101
- const sessionIdentity = readRegistrySessionIdentity(homeDir);
102
- const envApiBaseUrl = normalizeApiBaseUrl(
103
- env.AI_DESK_API_BASE_URL || env.AI_DESK_BACKEND_API_URL || env.AI_DESK_BACKEND_URL,
104
- );
105
- const apiBaseUrl = normalizeApiBaseUrl(
106
- envApiBaseUrl ||
107
- daemonConfig?.apiBaseUrl ||
108
- sessionIdentity?.apiBaseUrl ||
109
- DEFAULT_REGISTRY_API_BASE_URL,
110
- );
111
- const rcAccountId = trim(env.AI_DESK_RC_ACCOUNT_ID || env.rcAccountId) ||
112
- sessionIdentity?.rcAccountId ||
113
- daemonConfig?.rcAccountId ||
114
- '';
115
- const rcExtensionId = trim(env.AI_DESK_RC_EXTENSION_ID || env.rcExtensionId) ||
116
- sessionIdentity?.rcExtensionId ||
117
- daemonConfig?.rcExtensionId ||
118
- '';
119
- if (apiBaseUrl) {
120
- const tlsEnvValue = parseTruthyEnv(env.AI_DESK_TLS_INSECURE_SKIP_VERIFY);
121
- return {
122
- apiBaseUrl,
123
- rcAccountId,
124
- rcExtensionId,
125
- rcUsername: trim(env.AI_DESK_RC_USERNAME || env.rcUsername) ||
126
- sessionIdentity?.rcUsername ||
127
- daemonConfig?.rcUsername ||
128
- '',
129
- tlsInsecureSkipVerify: tlsEnvValue === null
130
- ? Boolean(daemonConfig?.tlsInsecureSkipVerify ?? sessionIdentity?.tlsInsecureSkipVerify ?? inferTLSInsecureSkipVerify(apiBaseUrl))
131
- : tlsEnvValue,
132
- };
133
- }
134
- return null;
135
- }
136
-
137
- function daemonConfigPath(homeDir = os.homedir()) {
138
- return path.join(homeDir, '.aidesktop', 'daemon-config.json');
139
- }
140
-
141
- function syncRegistryConfigToDaemonConfig(env = process.env, homeDir = os.homedir()) {
142
- const config = getRegistryConfig(env, homeDir);
143
- if (!config) return null;
144
-
145
- const configPath = daemonConfigPath(homeDir);
146
- let daemonConfig = {};
147
- try {
148
- if (fs.existsSync(configPath)) {
149
- const parsed = JSON.parse(fs.readFileSync(configPath, 'utf8'));
150
- if (parsed && typeof parsed === 'object') daemonConfig = parsed;
151
- }
152
- } catch {
153
- daemonConfig = {};
154
- }
155
-
156
- daemonConfig.registry = {
157
- ...(daemonConfig.registry && typeof daemonConfig.registry === 'object' ? daemonConfig.registry : {}),
158
- api_base_url: config.apiBaseUrl,
159
- rc_account_id: config.rcAccountId,
160
- rc_extension_id: config.rcExtensionId,
161
- rc_username: config.rcUsername,
162
- tls_insecure_skip_verify: Boolean(config.tlsInsecureSkipVerify),
163
- };
164
-
165
- fs.mkdirSync(path.dirname(configPath), { recursive: true });
166
- fs.writeFileSync(configPath, `${JSON.stringify(daemonConfig, null, 2)}\n`, 'utf8');
167
- return config;
168
- }
169
-
170
- function configureRegistryUrl(apiBaseUrl, options = {}) {
171
- const homeDir = options.homeDir || os.homedir();
172
- const normalizedApiBaseUrl = normalizeApiBaseUrl(apiBaseUrl);
173
- if (!normalizedApiBaseUrl) {
174
- throw new Error('Registry URL is required');
175
- }
176
-
177
- let parsedUrl;
178
- try {
179
- parsedUrl = new URL(normalizedApiBaseUrl);
180
- } catch {
181
- throw new Error(`Invalid registry URL: ${apiBaseUrl}`);
182
- }
183
- if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
184
- throw new Error(`Registry URL must use http or https: ${apiBaseUrl}`);
185
- }
186
-
187
- const configPath = daemonConfigPath(homeDir);
188
- let daemonConfig = {};
189
- try {
190
- if (fs.existsSync(configPath)) {
191
- const parsedConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
192
- if (parsedConfig && typeof parsedConfig === 'object') daemonConfig = parsedConfig;
193
- }
194
- } catch {
195
- daemonConfig = {};
196
- }
197
-
198
- const tlsInsecureSkipVerify = typeof options.tlsInsecureSkipVerify === 'boolean'
199
- ? options.tlsInsecureSkipVerify
200
- : inferTLSInsecureSkipVerify(normalizedApiBaseUrl);
201
-
202
- daemonConfig.registry = {
203
- ...(daemonConfig.registry && typeof daemonConfig.registry === 'object' ? daemonConfig.registry : {}),
204
- api_base_url: normalizedApiBaseUrl,
205
- tls_insecure_skip_verify: tlsInsecureSkipVerify,
206
- };
207
-
208
- fs.mkdirSync(path.dirname(configPath), { recursive: true });
209
- fs.writeFileSync(configPath, `${JSON.stringify(daemonConfig, null, 2)}\n`, 'utf8');
210
-
211
- return {
212
- apiBaseUrl: normalizedApiBaseUrl,
213
- tlsInsecureSkipVerify,
214
- };
215
- }
216
-
217
- function registryStatePaths(homeDir = os.homedir()) {
218
- const root = path.join(homeDir, '.aidesktop');
219
- return {
220
- root,
221
- instanceIdPath: path.join(root, 'daemon-instance-id'),
222
- runStatePath: path.join(root, 'daemon-run-state.json'),
223
- };
224
- }
225
-
226
- function ensureDaemonInstanceId(paths = registryStatePaths()) {
227
- try {
228
- fs.mkdirSync(paths.root, { recursive: true });
229
- if (fs.existsSync(paths.instanceIdPath)) {
230
- const existing = fs.readFileSync(paths.instanceIdPath, 'utf8').trim();
231
- if (existing) return existing;
232
- }
233
- const next = `daemon-${crypto.randomUUID()}`;
234
- fs.writeFileSync(paths.instanceIdPath, `${next}\n`, 'utf8');
235
- return next;
236
- } catch {
237
- return `daemon-${crypto.randomUUID()}`;
238
- }
239
- }
240
-
241
- function readRunState(paths = registryStatePaths()) {
242
- try {
243
- if (!fs.existsSync(paths.runStatePath)) return null;
244
- const data = JSON.parse(fs.readFileSync(paths.runStatePath, 'utf8'));
245
- return data && typeof data === 'object' ? data : null;
246
- } catch {
247
- return null;
248
- }
249
- }
250
-
251
- function writeRunState(state, paths = registryStatePaths()) {
252
- try {
253
- fs.mkdirSync(paths.root, { recursive: true });
254
- fs.writeFileSync(paths.runStatePath, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
255
- } catch {
256
- // best effort only
257
- }
258
- }
259
-
260
- function listIpAddresses() {
261
- const out = [];
262
- const interfaces = os.networkInterfaces();
263
- for (const items of Object.values(interfaces)) {
264
- for (const item of items || []) {
265
- if (!item.internal && item.address) {
266
- out.push(item.address);
267
- }
268
- }
269
- }
270
- return [...new Set(out)];
271
- }
272
-
273
- function listMacAddresses() {
274
- const out = [];
275
- const interfaces = os.networkInterfaces();
276
- for (const items of Object.values(interfaces)) {
277
- for (const item of items || []) {
278
- const mac = trim(item.mac).toLowerCase();
279
- if (!item.internal && mac && mac !== '00:00:00:00:00:00') {
280
- out.push(mac);
281
- }
282
- }
283
- }
284
- return [...new Set(out)];
285
- }
286
-
287
- function buildLifecyclePayload({
288
- event,
289
- runId,
290
- seq = 1,
291
- port,
292
- version,
293
- daemonInstanceId,
294
- }) {
295
- const macAddresses = listMacAddresses();
296
- return {
297
- daemonInstanceId,
298
- runId,
299
- event,
300
- seq,
301
- machineId: macAddresses[0] || daemonInstanceId,
302
- hostname: os.hostname(),
303
- osUsername: os.userInfo().username,
304
- daemonVersion: version,
305
- port,
306
- ipAddresses: listIpAddresses(),
307
- macAddresses,
308
- };
309
- }
310
-
311
- function postJSON(urlString, payload, config) {
312
- return new Promise((resolve, reject) => {
313
- const url = new URL(urlString);
314
- const body = JSON.stringify(payload);
315
- const transport = url.protocol === 'https:' ? https : http;
316
- const req = transport.request(
317
- url,
318
- {
319
- method: 'POST',
320
- ...(url.protocol === 'https:' && config.tlsInsecureSkipVerify
321
- ? { agent: new https.Agent({ rejectUnauthorized: false }) }
322
- : {}),
323
- headers: {
324
- 'Content-Type': 'application/json',
325
- 'Content-Length': Buffer.byteLength(body),
326
- ...(config.rcAccountId ? { rcAccountId: config.rcAccountId } : {}),
327
- ...(config.rcExtensionId ? { rcExtensionId: config.rcExtensionId } : {}),
328
- ...(config.rcUsername ? { rcUsername: config.rcUsername } : {}),
329
- },
330
- timeout: 3000,
331
- },
332
- (res) => {
333
- res.resume();
334
- res.on('end', () => {
335
- if (res.statusCode >= 200 && res.statusCode < 300) {
336
- resolve(true);
337
- } else {
338
- reject(new Error(`registry returned ${res.statusCode}`));
339
- }
340
- });
341
- },
342
- );
343
- req.on('timeout', () => {
344
- req.destroy(new Error('registry request timed out'));
345
- });
346
- req.on('error', reject);
347
- req.write(body);
348
- req.end();
349
- });
350
- }
351
-
352
- async function reportLifecycle(event, { port, version, seq = 1 } = {}) {
353
- const config = getRegistryConfig();
354
- if (!config) return false;
355
-
356
- const paths = registryStatePaths();
357
- const daemonInstanceId = ensureDaemonInstanceId(paths);
358
- let runState = readRunState(paths);
359
- if (event === 'start' || event === 'restart' || !runState?.runId) {
360
- runState = { runId: crypto.randomUUID(), seq: 0 };
361
- }
362
- runState.seq = Math.max(Number(runState.seq || 0) + 1, seq);
363
- writeRunState(runState, paths);
364
-
365
- const payload = buildLifecyclePayload({
366
- event,
367
- runId: runState.runId,
368
- seq: runState.seq,
369
- port,
370
- version,
371
- daemonInstanceId,
372
- });
373
- await postJSON(`${config.apiBaseUrl}/daemon-instances/lifecycle`, payload, config);
374
- return true;
375
- }
376
-
377
- module.exports = {
378
- buildLifecyclePayload,
379
- configureRegistryUrl,
380
- DEFAULT_REGISTRY_API_BASE_URL,
381
- inferTLSInsecureSkipVerify,
382
- getRegistryConfig,
383
- syncRegistryConfigToDaemonConfig,
384
- readRegistrySessionIdentity,
385
- readRegistryConfigFromDaemonConfig,
386
- registryStatePaths,
387
- ensureDaemonInstanceId,
388
- readRunState,
389
- writeRunState,
390
- listMacAddresses,
391
- reportLifecycle,
392
- };