@mclean-capital/neura 1.10.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.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -0
  3. package/dist/audio/capture.d.ts +19 -0
  4. package/dist/audio/capture.d.ts.map +1 -0
  5. package/dist/audio/capture.js +52 -0
  6. package/dist/audio/capture.js.map +1 -0
  7. package/dist/audio/install-hints.d.ts +12 -0
  8. package/dist/audio/install-hints.d.ts.map +1 -0
  9. package/dist/audio/install-hints.js +29 -0
  10. package/dist/audio/install-hints.js.map +1 -0
  11. package/dist/audio/playback.d.ts +33 -0
  12. package/dist/audio/playback.d.ts.map +1 -0
  13. package/dist/audio/playback.js +408 -0
  14. package/dist/audio/playback.js.map +1 -0
  15. package/dist/commands/backup.d.ts +5 -0
  16. package/dist/commands/backup.d.ts.map +1 -0
  17. package/dist/commands/backup.js +72 -0
  18. package/dist/commands/backup.js.map +1 -0
  19. package/dist/commands/chat.d.ts +4 -0
  20. package/dist/commands/chat.d.ts.map +1 -0
  21. package/dist/commands/chat.js +183 -0
  22. package/dist/commands/chat.js.map +1 -0
  23. package/dist/commands/config.d.ts +5 -0
  24. package/dist/commands/config.d.ts.map +1 -0
  25. package/dist/commands/config.js +36 -0
  26. package/dist/commands/config.js.map +1 -0
  27. package/dist/commands/install.d.ts +2 -0
  28. package/dist/commands/install.d.ts.map +1 -0
  29. package/dist/commands/install.js +158 -0
  30. package/dist/commands/install.js.map +1 -0
  31. package/dist/commands/listen.d.ts +5 -0
  32. package/dist/commands/listen.d.ts.map +1 -0
  33. package/dist/commands/listen.js +321 -0
  34. package/dist/commands/listen.js.map +1 -0
  35. package/dist/commands/logs.d.ts +5 -0
  36. package/dist/commands/logs.d.ts.map +1 -0
  37. package/dist/commands/logs.js +40 -0
  38. package/dist/commands/logs.js.map +1 -0
  39. package/dist/commands/open.d.ts +2 -0
  40. package/dist/commands/open.d.ts.map +1 -0
  41. package/dist/commands/open.js +43 -0
  42. package/dist/commands/open.js.map +1 -0
  43. package/dist/commands/restart.d.ts +2 -0
  44. package/dist/commands/restart.d.ts.map +1 -0
  45. package/dist/commands/restart.js +22 -0
  46. package/dist/commands/restart.js.map +1 -0
  47. package/dist/commands/start.d.ts +2 -0
  48. package/dist/commands/start.d.ts.map +1 -0
  49. package/dist/commands/start.js +28 -0
  50. package/dist/commands/start.js.map +1 -0
  51. package/dist/commands/status.d.ts +2 -0
  52. package/dist/commands/status.d.ts.map +1 -0
  53. package/dist/commands/status.js +36 -0
  54. package/dist/commands/status.js.map +1 -0
  55. package/dist/commands/stop.d.ts +2 -0
  56. package/dist/commands/stop.d.ts.map +1 -0
  57. package/dist/commands/stop.js +17 -0
  58. package/dist/commands/stop.js.map +1 -0
  59. package/dist/commands/uninstall.d.ts +4 -0
  60. package/dist/commands/uninstall.d.ts.map +1 -0
  61. package/dist/commands/uninstall.js +52 -0
  62. package/dist/commands/uninstall.js.map +1 -0
  63. package/dist/commands/update.d.ts +2 -0
  64. package/dist/commands/update.d.ts.map +1 -0
  65. package/dist/commands/update.js +25 -0
  66. package/dist/commands/update.js.map +1 -0
  67. package/dist/commands/version.d.ts +2 -0
  68. package/dist/commands/version.d.ts.map +1 -0
  69. package/dist/commands/version.js +25 -0
  70. package/dist/commands/version.js.map +1 -0
  71. package/dist/config.d.ts +12 -0
  72. package/dist/config.d.ts.map +1 -0
  73. package/dist/config.js +107 -0
  74. package/dist/config.js.map +1 -0
  75. package/dist/constants.d.ts +3 -0
  76. package/dist/constants.d.ts.map +1 -0
  77. package/dist/constants.js +3 -0
  78. package/dist/constants.js.map +1 -0
  79. package/dist/download.d.ts +28 -0
  80. package/dist/download.d.ts.map +1 -0
  81. package/dist/download.js +125 -0
  82. package/dist/download.js.map +1 -0
  83. package/dist/format/tools.d.ts +13 -0
  84. package/dist/format/tools.d.ts.map +1 -0
  85. package/dist/format/tools.js +48 -0
  86. package/dist/format/tools.js.map +1 -0
  87. package/dist/health.d.ts +15 -0
  88. package/dist/health.d.ts.map +1 -0
  89. package/dist/health.js +30 -0
  90. package/dist/health.js.map +1 -0
  91. package/dist/index.d.ts +3 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +74 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/port.d.ts +10 -0
  96. package/dist/port.d.ts.map +1 -0
  97. package/dist/port.js +39 -0
  98. package/dist/port.js.map +1 -0
  99. package/dist/service/detect.d.ts +10 -0
  100. package/dist/service/detect.d.ts.map +1 -0
  101. package/dist/service/detect.js +38 -0
  102. package/dist/service/detect.js.map +1 -0
  103. package/dist/service/linux.d.ts +20 -0
  104. package/dist/service/linux.d.ts.map +1 -0
  105. package/dist/service/linux.js +91 -0
  106. package/dist/service/linux.js.map +1 -0
  107. package/dist/service/macos.d.ts +20 -0
  108. package/dist/service/macos.d.ts.map +1 -0
  109. package/dist/service/macos.js +118 -0
  110. package/dist/service/macos.js.map +1 -0
  111. package/dist/service/manager.d.ts +16 -0
  112. package/dist/service/manager.d.ts.map +1 -0
  113. package/dist/service/manager.js +16 -0
  114. package/dist/service/manager.js.map +1 -0
  115. package/dist/service/windows.d.ts +20 -0
  116. package/dist/service/windows.d.ts.map +1 -0
  117. package/dist/service/windows.js +103 -0
  118. package/dist/service/windows.js.map +1 -0
  119. package/dist/update-check.d.ts +7 -0
  120. package/dist/update-check.d.ts.map +1 -0
  121. package/dist/update-check.js +71 -0
  122. package/dist/update-check.js.map +1 -0
  123. package/dist/version.d.ts +12 -0
  124. package/dist/version.d.ts.map +1 -0
  125. package/dist/version.js +15 -0
  126. package/dist/version.js.map +1 -0
  127. package/package.json +59 -0
package/dist/index.js ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { CLI_VERSION } from './version.js';
4
+ import { installCommand } from './commands/install.js';
5
+ import { statusCommand } from './commands/status.js';
6
+ import { startCommand } from './commands/start.js';
7
+ import { stopCommand } from './commands/stop.js';
8
+ import { restartCommand } from './commands/restart.js';
9
+ import { configGetCommand, configSetCommand, configListCommand, configPathCommand, } from './commands/config.js';
10
+ import { logsCommand } from './commands/logs.js';
11
+ import { uninstallCommand } from './commands/uninstall.js';
12
+ import { versionCommand } from './commands/version.js';
13
+ import { openCommand } from './commands/open.js';
14
+ import { updateCommand } from './commands/update.js';
15
+ import { backupCommand, restoreCommand } from './commands/backup.js';
16
+ import { chatCommand } from './commands/chat.js';
17
+ import { listenCommand } from './commands/listen.js';
18
+ const program = new Command();
19
+ program.name('neura').description('Neura — AI assistant core service manager').version(CLI_VERSION);
20
+ // Install & setup
21
+ program
22
+ .command('install')
23
+ .description('Interactive setup wizard + service registration')
24
+ .action(installCommand);
25
+ program
26
+ .command('uninstall')
27
+ .description('Remove service and optionally clean data')
28
+ .option('--force', 'Skip confirmation prompts')
29
+ .action(uninstallCommand);
30
+ // Service lifecycle
31
+ program.command('start').description('Start the core service').action(startCommand);
32
+ program.command('stop').description('Stop the core service').action(stopCommand);
33
+ program.command('restart').description('Restart the core service').action(restartCommand);
34
+ program.command('status').description('Show core service status').action(statusCommand);
35
+ // Configuration
36
+ const configCmd = program.command('config').description('Manage configuration');
37
+ configCmd.command('get <key>').description('Get a config value').action(configGetCommand);
38
+ configCmd.command('set <key> <value>').description('Set a config value').action(configSetCommand);
39
+ configCmd.command('list').description('Show all configuration').action(configListCommand);
40
+ configCmd
41
+ .command('path')
42
+ .description('Print the Neura home directory path')
43
+ .action(configPathCommand);
44
+ // Utilities
45
+ program
46
+ .command('logs')
47
+ .description('View core service logs')
48
+ .option('-n, --lines <count>', 'Number of lines to show', '50')
49
+ .option('-f, --follow', 'Follow log output')
50
+ .action(logsCommand);
51
+ program.command('open').description('Open the web UI in default browser').action(openCommand);
52
+ program.command('update').description('Download the latest core binary').action(updateCommand);
53
+ program.command('version').description('Show CLI and core versions').action(versionCommand);
54
+ // Data management
55
+ program.command('backup').description('Create a memory backup').action(backupCommand);
56
+ program
57
+ .command('restore')
58
+ .description('Restore memories from backup')
59
+ .option('--force', 'Skip confirmation prompt')
60
+ .action(restoreCommand);
61
+ // Interactive client
62
+ program
63
+ .command('chat')
64
+ .description('Text chat with Neura')
65
+ .option('-p, --port <port>', 'Core server port (default: config or 3002)')
66
+ .action(chatCommand);
67
+ program
68
+ .command('listen')
69
+ .description('Voice chat with Neura (mic + speaker)')
70
+ .option('-p, --port <port>', 'Core server port (default: config or 3002)')
71
+ .option('--debug', 'Print audio pipeline stats every 2s')
72
+ .action(listenCommand);
73
+ program.parse();
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/port.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Find a free port in the 18000-19000 range.
3
+ * Starts at a random offset to avoid collisions between multiple installs.
4
+ *
5
+ * Note: This is a best-effort TOCTOU check — the port could be claimed between
6
+ * this probe and core actually starting. Core's EADDRINUSE retry loop in
7
+ * server.ts is the safety net for that race.
8
+ */
9
+ export declare function findFreePort(): Promise<number>;
10
+ //# sourceMappingURL=port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../src/port.ts"],"names":[],"mappings":"AAmBA;;;;;;;GAOG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAYpD"}
package/dist/port.js ADDED
@@ -0,0 +1,39 @@
1
+ import { createServer } from 'net';
2
+ const PORT_MIN = 18000;
3
+ const PORT_MAX = 19000;
4
+ /**
5
+ * Check if a TCP port is free by attempting to listen on it.
6
+ */
7
+ function isPortFree(port) {
8
+ return new Promise((resolve) => {
9
+ const srv = createServer();
10
+ srv.once('error', () => resolve(false));
11
+ srv.once('listening', () => {
12
+ srv.close(() => resolve(true));
13
+ });
14
+ srv.listen(port, '127.0.0.1');
15
+ });
16
+ }
17
+ /**
18
+ * Find a free port in the 18000-19000 range.
19
+ * Starts at a random offset to avoid collisions between multiple installs.
20
+ *
21
+ * Note: This is a best-effort TOCTOU check — the port could be claimed between
22
+ * this probe and core actually starting. Core's EADDRINUSE retry loop in
23
+ * server.ts is the safety net for that race.
24
+ */
25
+ export async function findFreePort() {
26
+ const start = PORT_MIN + Math.floor(Math.random() * (PORT_MAX - PORT_MIN));
27
+ // Scan from random start to end of range
28
+ for (let port = start; port < PORT_MAX; port++) {
29
+ if (await isPortFree(port))
30
+ return port;
31
+ }
32
+ // Wrap around to beginning of range
33
+ for (let port = PORT_MIN; port < start; port++) {
34
+ if (await isPortFree(port))
35
+ return port;
36
+ }
37
+ throw new Error(`No free port found in range ${PORT_MIN}-${PORT_MAX}`);
38
+ }
39
+ //# sourceMappingURL=port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port.js","sourceRoot":"","sources":["../src/port.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAEnC,MAAM,QAAQ,GAAG,KAAK,CAAC;AACvB,MAAM,QAAQ,GAAG,KAAK,CAAC;AAEvB;;GAEG;AACH,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YACzB,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC;IAE3E,yCAAyC;IACzC,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QAC/C,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IAC1C,CAAC;IACD,oCAAoC;IACpC,KAAK,IAAI,IAAI,GAAG,QAAQ,EAAE,IAAI,GAAG,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QAC/C,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IAC1C,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,IAAI,QAAQ,EAAE,CAAC,CAAC;AACzE,CAAC"}
@@ -0,0 +1,10 @@
1
+ export type Platform = 'windows' | 'macos' | 'linux';
2
+ export declare function detectPlatform(): Platform;
3
+ /**
4
+ * Check if the current process has admin/root privileges.
5
+ * Windows: checks via `net session` (only succeeds when elevated).
6
+ * Unix: checks effective UID.
7
+ */
8
+ export declare function isElevated(): boolean;
9
+ export declare function getPlatformLabel(): string;
10
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/service/detect.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAErD,wBAAgB,cAAc,IAAI,QAAQ,CASzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAUpC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAOzC"}
@@ -0,0 +1,38 @@
1
+ import { platform } from 'os';
2
+ import { execSync } from 'child_process';
3
+ export function detectPlatform() {
4
+ switch (platform()) {
5
+ case 'win32':
6
+ return 'windows';
7
+ case 'darwin':
8
+ return 'macos';
9
+ default:
10
+ return 'linux';
11
+ }
12
+ }
13
+ /**
14
+ * Check if the current process has admin/root privileges.
15
+ * Windows: checks via `net session` (only succeeds when elevated).
16
+ * Unix: checks effective UID.
17
+ */
18
+ export function isElevated() {
19
+ if (platform() === 'win32') {
20
+ try {
21
+ execSync('net session', { stdio: 'ignore' });
22
+ return true;
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ return process.getuid?.() === 0;
29
+ }
30
+ export function getPlatformLabel() {
31
+ const labels = {
32
+ windows: 'Windows Service (winsw)',
33
+ macos: 'launchd Agent',
34
+ linux: 'systemd User Service',
35
+ };
36
+ return labels[detectPlatform()];
37
+ }
38
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/service/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC,MAAM,UAAU,cAAc;IAC5B,QAAQ,QAAQ,EAAE,EAAE,CAAC;QACnB,KAAK,OAAO;YACV,OAAO,SAAS,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC;QACjB;YACE,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,QAAQ,EAAE,KAAK,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,QAAQ,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAA6B;QACvC,OAAO,EAAE,yBAAyB;QAClC,KAAK,EAAE,eAAe;QACtB,KAAK,EAAE,sBAAsB;KAC9B,CAAC;IACF,OAAO,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,20 @@
1
+ export declare function isInstalled(): boolean;
2
+ export declare function isRunning(): boolean;
3
+ export declare function install(): void;
4
+ export declare function uninstall(): void;
5
+ export declare function start(): void;
6
+ export declare function stop(): void;
7
+ export declare function restart(): void;
8
+ export declare function getLogPath(): string;
9
+ declare const _default: {
10
+ readonly isInstalled: typeof isInstalled;
11
+ readonly isRunning: typeof isRunning;
12
+ readonly install: typeof install;
13
+ readonly uninstall: typeof uninstall;
14
+ readonly start: typeof start;
15
+ readonly stop: typeof stop;
16
+ readonly restart: typeof restart;
17
+ readonly getLogPath: typeof getLogPath;
18
+ };
19
+ export default _default;
20
+ //# sourceMappingURL=linux.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linux.d.ts","sourceRoot":"","sources":["../../src/service/linux.ts"],"names":[],"mappings":"AAaA,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,wBAAgB,SAAS,IAAI,OAAO,CASnC;AAED,wBAAgB,OAAO,IAAI,IAAI,CA4B9B;AAED,wBAAgB,SAAS,IAAI,IAAI,CAchC;AAED,wBAAgB,KAAK,IAAI,IAAI,CAE5B;AAED,wBAAgB,IAAI,IAAI,IAAI,CAE3B;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;;;;;;;;;;;AAED,wBASW"}
@@ -0,0 +1,91 @@
1
+ import { writeFileSync, existsSync, unlinkSync, mkdirSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+ import { execSync } from 'child_process';
5
+ import { getNeuraHome } from '../config.js';
6
+ import { getCoreBinaryPath } from '../download.js';
7
+ const SERVICE_NAME = 'neura-core';
8
+ function getUnitPath() {
9
+ return join(homedir(), '.config', 'systemd', 'user', `${SERVICE_NAME}.service`);
10
+ }
11
+ export function isInstalled() {
12
+ return existsSync(getUnitPath());
13
+ }
14
+ export function isRunning() {
15
+ try {
16
+ execSync(`systemctl --user is-active ${SERVICE_NAME}`, {
17
+ stdio: ['pipe', 'pipe', 'pipe'],
18
+ });
19
+ return true;
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
25
+ export function install() {
26
+ const home = getNeuraHome();
27
+ const binaryPath = getCoreBinaryPath();
28
+ const unitPath = getUnitPath();
29
+ mkdirSync(join(homedir(), '.config', 'systemd', 'user'), { recursive: true });
30
+ const unit = `[Unit]
31
+ Description=Neura Core Service
32
+ After=network.target
33
+
34
+ [Service]
35
+ Type=simple
36
+ ExecStart=${binaryPath}
37
+ WorkingDirectory=${home}
38
+ Restart=on-failure
39
+ RestartSec=5
40
+ Environment=NEURA_HOME=${home}
41
+ StandardOutput=append:${home}/logs/core.log
42
+ StandardError=append:${home}/logs/core.error.log
43
+
44
+ [Install]
45
+ WantedBy=default.target
46
+ `;
47
+ writeFileSync(unitPath, unit, 'utf-8');
48
+ execSync('systemctl --user daemon-reload', { stdio: 'inherit' });
49
+ execSync(`systemctl --user enable ${SERVICE_NAME}`, { stdio: 'inherit' });
50
+ }
51
+ export function uninstall() {
52
+ try {
53
+ execSync(`systemctl --user stop ${SERVICE_NAME}`, { stdio: 'ignore' });
54
+ execSync(`systemctl --user disable ${SERVICE_NAME}`, { stdio: 'ignore' });
55
+ }
56
+ catch {
57
+ // May not be running/enabled
58
+ }
59
+ const unitPath = getUnitPath();
60
+ if (existsSync(unitPath))
61
+ unlinkSync(unitPath);
62
+ try {
63
+ execSync('systemctl --user daemon-reload', { stdio: 'ignore' });
64
+ }
65
+ catch {
66
+ // Best effort
67
+ }
68
+ }
69
+ export function start() {
70
+ execSync(`systemctl --user start ${SERVICE_NAME}`, { stdio: 'inherit' });
71
+ }
72
+ export function stop() {
73
+ execSync(`systemctl --user stop ${SERVICE_NAME}`, { stdio: 'inherit' });
74
+ }
75
+ export function restart() {
76
+ execSync(`systemctl --user restart ${SERVICE_NAME}`, { stdio: 'inherit' });
77
+ }
78
+ export function getLogPath() {
79
+ return join(getNeuraHome(), 'logs', 'core.log');
80
+ }
81
+ export default {
82
+ isInstalled,
83
+ isRunning,
84
+ install,
85
+ uninstall,
86
+ start,
87
+ stop,
88
+ restart,
89
+ getLogPath,
90
+ };
91
+ //# sourceMappingURL=linux.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linux.js","sourceRoot":"","sources":["../../src/service/linux.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export declare function isInstalled(): boolean;
2
+ export declare function isRunning(): boolean;
3
+ export declare function install(): void;
4
+ export declare function uninstall(): void;
5
+ export declare function start(): void;
6
+ export declare function stop(): void;
7
+ export declare function restart(): void;
8
+ export declare function getLogPath(): string;
9
+ declare const _default: {
10
+ readonly isInstalled: typeof isInstalled;
11
+ readonly isRunning: typeof isRunning;
12
+ readonly install: typeof install;
13
+ readonly uninstall: typeof uninstall;
14
+ readonly start: typeof start;
15
+ readonly stop: typeof stop;
16
+ readonly restart: typeof restart;
17
+ readonly getLogPath: typeof getLogPath;
18
+ };
19
+ export default _default;
20
+ //# sourceMappingURL=macos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macos.d.ts","sourceRoot":"","sources":["../../src/service/macos.ts"],"names":[],"mappings":"AAuBA,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,wBAAgB,SAAS,IAAI,OAAO,CAwBnC;AAED,wBAAgB,OAAO,IAAI,IAAI,CAoC9B;AAED,wBAAgB,SAAS,IAAI,IAAI,CAQhC;AAED,wBAAgB,KAAK,IAAI,IAAI,CAE5B;AAED,wBAAgB,IAAI,IAAI,IAAI,CAE3B;AAED,wBAAgB,OAAO,IAAI,IAAI,CAG9B;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;;;;;;;;;;;AAED,wBASW"}
@@ -0,0 +1,118 @@
1
+ import { writeFileSync, existsSync, unlinkSync, mkdirSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { homedir } from 'os';
4
+ import { execSync } from 'child_process';
5
+ import { getNeuraHome } from '../config.js';
6
+ import { getCoreBinaryPath } from '../download.js';
7
+ const LABEL = 'com.neura.core';
8
+ function getPlistPath() {
9
+ return join(homedir(), 'Library', 'LaunchAgents', `${LABEL}.plist`);
10
+ }
11
+ /** Escape XML special characters for safe plist interpolation. */
12
+ function escapeXml(str) {
13
+ return str
14
+ .replace(/&/g, '&amp;')
15
+ .replace(/</g, '&lt;')
16
+ .replace(/>/g, '&gt;')
17
+ .replace(/"/g, '&quot;')
18
+ .replace(/'/g, '&apos;');
19
+ }
20
+ export function isInstalled() {
21
+ return existsSync(getPlistPath());
22
+ }
23
+ export function isRunning() {
24
+ try {
25
+ const result = execSync(`launchctl list ${LABEL}`, {
26
+ encoding: 'utf-8',
27
+ stdio: ['pipe', 'pipe', 'pipe'],
28
+ });
29
+ // launchctl list <label> outputs a table with "PID" in the header.
30
+ // When running, the PID line shows a number. When stopped, it shows "-".
31
+ // Format: "PID" = <number> or "-"
32
+ const pidMatch = /"PID"\s*=\s*(\S+)/.exec(result);
33
+ if (pidMatch)
34
+ return pidMatch[1] !== '-' && pidMatch[1] !== '0';
35
+ // Fallback: first line of tabular output is "<pid>\t<status>\t<label>"
36
+ const lines = result.trim().split('\n');
37
+ for (const line of lines) {
38
+ const parts = line.trim().split(/\s+/);
39
+ if (parts.length >= 3 && parts[2] === LABEL) {
40
+ return parts[0] !== '-' && parts[0] !== '0';
41
+ }
42
+ }
43
+ return false;
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ export function install() {
50
+ const home = escapeXml(getNeuraHome());
51
+ const binaryPath = escapeXml(getCoreBinaryPath());
52
+ const plistPath = getPlistPath();
53
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
54
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
55
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
56
+ <plist version="1.0">
57
+ <dict>
58
+ <key>Label</key>
59
+ <string>${LABEL}</string>
60
+ <key>ProgramArguments</key>
61
+ <array>
62
+ <string>${binaryPath}</string>
63
+ </array>
64
+ <key>WorkingDirectory</key>
65
+ <string>${home}</string>
66
+ <key>RunAtLoad</key>
67
+ <true/>
68
+ <key>KeepAlive</key>
69
+ <true/>
70
+ <key>StandardOutPath</key>
71
+ <string>${home}/logs/core.log</string>
72
+ <key>StandardErrorPath</key>
73
+ <string>${home}/logs/core.error.log</string>
74
+ <key>EnvironmentVariables</key>
75
+ <dict>
76
+ <key>NEURA_HOME</key>
77
+ <string>${home}</string>
78
+ </dict>
79
+ </dict>
80
+ </plist>`;
81
+ mkdirSync(dirname(plistPath), { recursive: true });
82
+ writeFileSync(plistPath, plist, 'utf-8');
83
+ }
84
+ export function uninstall() {
85
+ const plistPath = getPlistPath();
86
+ try {
87
+ execSync(`launchctl unload -w "${plistPath}"`, { stdio: 'ignore' });
88
+ }
89
+ catch {
90
+ // May not be loaded
91
+ }
92
+ if (existsSync(plistPath))
93
+ unlinkSync(plistPath);
94
+ }
95
+ export function start() {
96
+ execSync(`launchctl load -w "${getPlistPath()}"`, { stdio: 'inherit' });
97
+ }
98
+ export function stop() {
99
+ execSync(`launchctl unload "${getPlistPath()}"`, { stdio: 'inherit' });
100
+ }
101
+ export function restart() {
102
+ stop();
103
+ start();
104
+ }
105
+ export function getLogPath() {
106
+ return join(getNeuraHome(), 'logs', 'core.log');
107
+ }
108
+ export default {
109
+ isInstalled,
110
+ isRunning,
111
+ install,
112
+ uninstall,
113
+ start,
114
+ stop,
115
+ restart,
116
+ getLogPath,
117
+ };
118
+ //# sourceMappingURL=macos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macos.js","sourceRoot":"","sources":["../../src/service/macos.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface ServiceManager {
2
+ isInstalled(): boolean;
3
+ isRunning(): boolean;
4
+ install(): void | Promise<void>;
5
+ uninstall(): void | Promise<void>;
6
+ start(): void;
7
+ stop(): void;
8
+ restart(): void;
9
+ getLogPath(): string;
10
+ }
11
+ /**
12
+ * Returns the platform-specific service manager.
13
+ * Dynamically imports to avoid loading Windows-specific code on macOS, etc.
14
+ */
15
+ export declare function getServiceManager(): Promise<ServiceManager>;
16
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/service/manager.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,WAAW,IAAI,OAAO,CAAC;IACvB,SAAS,IAAI,OAAO,CAAC;IACrB,OAAO,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,SAAS,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,IAAI,IAAI,CAAC;IAChB,UAAU,IAAI,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAWjE"}
@@ -0,0 +1,16 @@
1
+ import { detectPlatform } from './detect.js';
2
+ /**
3
+ * Returns the platform-specific service manager.
4
+ * Dynamically imports to avoid loading Windows-specific code on macOS, etc.
5
+ */
6
+ export async function getServiceManager() {
7
+ const platform = detectPlatform();
8
+ const loaders = {
9
+ windows: () => import('./windows.js'),
10
+ macos: () => import('./macos.js'),
11
+ linux: () => import('./linux.js'),
12
+ };
13
+ const mod = await loaders[platform]();
14
+ return mod.default;
15
+ }
16
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/service/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AAa5D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAElC,MAAM,OAAO,GAAiE;QAC5E,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC;QACrC,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC;QACjC,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC;KAClC,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC"}
@@ -0,0 +1,20 @@
1
+ export declare function isInstalled(): boolean;
2
+ export declare function isRunning(): boolean;
3
+ export declare function install(): void;
4
+ export declare function uninstall(): void;
5
+ export declare function start(): void;
6
+ export declare function stop(): void;
7
+ export declare function restart(): void;
8
+ export declare function getLogPath(): string;
9
+ declare const _default: {
10
+ readonly isInstalled: typeof isInstalled;
11
+ readonly isRunning: typeof isRunning;
12
+ readonly install: typeof install;
13
+ readonly uninstall: typeof uninstall;
14
+ readonly start: typeof start;
15
+ readonly stop: typeof stop;
16
+ readonly restart: typeof restart;
17
+ readonly getLogPath: typeof getLogPath;
18
+ };
19
+ export default _default;
20
+ //# sourceMappingURL=windows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows.d.ts","sourceRoot":"","sources":["../../src/service/windows.ts"],"names":[],"mappings":"AAgBA,wBAAgB,WAAW,IAAI,OAAO,CAUrC;AAED,wBAAgB,SAAS,IAAI,OAAO,CAUnC;AAED,wBAAgB,OAAO,IAAI,IAAI,CAe9B;AAED,wBAAgB,SAAS,IAAI,IAAI,CAQhC;AAED,wBAAgB,KAAK,IAAI,IAAI,CAG5B;AAED,wBAAgB,IAAI,IAAI,IAAI,CAG3B;AAkBD,wBAAgB,OAAO,IAAI,IAAI,CAK9B;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;;;;;;;;;;;AAED,wBASW"}
@@ -0,0 +1,103 @@
1
+ import { join } from 'path';
2
+ import { execSync } from 'child_process';
3
+ import { getNeuraHome } from '../config.js';
4
+ import { isElevated } from './detect.js';
5
+ const SERVICE_NAME = 'neura-core';
6
+ function requireElevation() {
7
+ if (!isElevated()) {
8
+ throw new Error('Administrator privileges required.\n' +
9
+ 'Right-click your terminal and select "Run as administrator", then retry.');
10
+ }
11
+ }
12
+ export function isInstalled() {
13
+ try {
14
+ const result = execSync(`sc query ${SERVICE_NAME}`, {
15
+ encoding: 'utf-8',
16
+ stdio: ['pipe', 'pipe', 'pipe'],
17
+ });
18
+ return !result.includes('does not exist');
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ export function isRunning() {
25
+ try {
26
+ const result = execSync(`sc query ${SERVICE_NAME}`, {
27
+ encoding: 'utf-8',
28
+ stdio: ['pipe', 'pipe', 'pipe'],
29
+ });
30
+ return result.includes('RUNNING');
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ export function install() {
37
+ requireElevation();
38
+ // Windows Services must implement the SCM protocol (ServiceMain callback).
39
+ // A plain Node.js/Bun binary cannot respond to SCM handshakes and will fail
40
+ // with error 1053. A service wrapper like WinSW or NSSM is required to bridge
41
+ // the gap. This will be implemented in Phase 2 of the CLI service architecture.
42
+ //
43
+ // See: docs/cli-service-architecture.md — Phase 2: OS Service Registration
44
+ throw new Error('Windows Service registration requires a service wrapper (WinSW).\n' +
45
+ 'This is planned for Phase 2. For now, run core manually:\n\n' +
46
+ ' neura-core (if binary installed)\n' +
47
+ ' npm run dev -w @neura/core (from source)\n');
48
+ }
49
+ export function uninstall() {
50
+ requireElevation();
51
+ try {
52
+ execSync(`sc stop ${SERVICE_NAME}`, { stdio: 'ignore' });
53
+ }
54
+ catch {
55
+ // May already be stopped
56
+ }
57
+ execSync(`sc delete ${SERVICE_NAME}`, { stdio: 'inherit' });
58
+ }
59
+ export function start() {
60
+ requireElevation();
61
+ execSync(`sc start ${SERVICE_NAME}`, { stdio: 'inherit' });
62
+ }
63
+ export function stop() {
64
+ requireElevation();
65
+ execSync(`sc stop ${SERVICE_NAME}`, { stdio: 'inherit' });
66
+ }
67
+ function waitForStopped(timeoutMs = 10_000) {
68
+ const deadline = Date.now() + timeoutMs;
69
+ while (Date.now() < deadline) {
70
+ try {
71
+ const result = execSync(`sc query ${SERVICE_NAME}`, {
72
+ encoding: 'utf-8',
73
+ stdio: ['pipe', 'pipe', 'pipe'],
74
+ });
75
+ if (result.includes('STOPPED'))
76
+ return;
77
+ }
78
+ catch {
79
+ return; // Service doesn't exist or query failed — treat as stopped
80
+ }
81
+ execSync('timeout /t 1 /nobreak >nul 2>&1', { stdio: 'ignore' });
82
+ }
83
+ }
84
+ export function restart() {
85
+ requireElevation();
86
+ stop();
87
+ waitForStopped();
88
+ start();
89
+ }
90
+ export function getLogPath() {
91
+ return join(getNeuraHome(), 'logs', 'core.log');
92
+ }
93
+ export default {
94
+ isInstalled,
95
+ isRunning,
96
+ install,
97
+ uninstall,
98
+ start,
99
+ stop,
100
+ restart,
101
+ getLogPath,
102
+ };
103
+ //# sourceMappingURL=windows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows.js","sourceRoot":"","sources":["../../src/service/windows.ts"],"names":[],"mappings":"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"}