@sonde/agent 0.2.5 → 0.2.7

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 (54) hide show
  1. package/.turbo/turbo-build.log +6 -4
  2. package/.turbo/turbo-test.log +96 -23
  3. package/CHANGELOG.md +20 -0
  4. package/dist/cli/packs.d.ts +6 -0
  5. package/dist/cli/packs.d.ts.map +1 -1
  6. package/dist/cli/packs.js +42 -8
  7. package/dist/cli/packs.js.map +1 -1
  8. package/dist/cli/packs.test.js +56 -1
  9. package/dist/cli/packs.test.js.map +1 -1
  10. package/dist/cli/service.d.ts +12 -0
  11. package/dist/cli/service.d.ts.map +1 -0
  12. package/dist/cli/service.js +164 -0
  13. package/dist/cli/service.js.map +1 -0
  14. package/dist/cli/service.test.d.ts +2 -0
  15. package/dist/cli/service.test.d.ts.map +1 -0
  16. package/dist/cli/service.test.js +99 -0
  17. package/dist/cli/service.test.js.map +1 -0
  18. package/dist/cli/update.d.ts.map +1 -1
  19. package/dist/cli/update.js +7 -8
  20. package/dist/cli/update.js.map +1 -1
  21. package/dist/config.d.ts +13 -0
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js +55 -0
  24. package/dist/config.js.map +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +126 -5
  27. package/dist/index.js.map +1 -1
  28. package/dist/tui/installer/InstallerApp.d.ts.map +1 -1
  29. package/dist/tui/installer/InstallerApp.js +3 -1
  30. package/dist/tui/installer/InstallerApp.js.map +1 -1
  31. package/dist/tui/installer/StepComplete.d.ts.map +1 -1
  32. package/dist/tui/installer/StepComplete.js +10 -1
  33. package/dist/tui/installer/StepComplete.js.map +1 -1
  34. package/dist/tui/installer/StepService.d.ts +6 -0
  35. package/dist/tui/installer/StepService.d.ts.map +1 -0
  36. package/dist/tui/installer/StepService.js +49 -0
  37. package/dist/tui/installer/StepService.js.map +1 -0
  38. package/dist/tui/manager/ManagerApp.d.ts +2 -1
  39. package/dist/tui/manager/ManagerApp.d.ts.map +1 -1
  40. package/dist/tui/manager/ManagerApp.js +3 -2
  41. package/dist/tui/manager/ManagerApp.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/cli/packs.test.ts +65 -0
  44. package/src/cli/packs.ts +56 -10
  45. package/src/cli/service.test.ts +124 -0
  46. package/src/cli/service.ts +178 -0
  47. package/src/cli/update.ts +7 -8
  48. package/src/config.ts +57 -0
  49. package/src/index.ts +156 -5
  50. package/src/tui/installer/InstallerApp.tsx +6 -2
  51. package/src/tui/installer/StepComplete.tsx +12 -1
  52. package/src/tui/installer/StepService.tsx +112 -0
  53. package/src/tui/manager/ManagerApp.tsx +4 -2
  54. package/tsconfig.tsbuildinfo +1 -1
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { packRegistry } from '@sonde/packs';
2
3
  import { Box, Text, useApp, useInput } from 'ink';
3
4
  import Spinner from 'ink-spinner';
4
5
  import { useEffect, useState } from 'react';
6
+ import { buildEnabledPacks } from '../../cli/packs.js';
5
7
  import { saveConfig } from '../../config.js';
6
8
  import { enrollWithHub } from '../../runtime/connection.js';
7
9
  import { ProbeExecutor } from '../../runtime/executor.js';
@@ -11,13 +13,20 @@ export function StepComplete({ hubConfig, selectedPacks }) {
11
13
  const [agentId, setAgentId] = useState('');
12
14
  const [error, setError] = useState('');
13
15
  useEffect(() => {
16
+ const selectedNames = new Set(selectedPacks.map((p) => p.name));
17
+ const disabledPacks = [...packRegistry.keys()]
18
+ .filter((name) => !selectedNames.has(name));
14
19
  const config = {
15
20
  hubUrl: hubConfig.hubUrl,
16
21
  apiKey: hubConfig.apiKey,
17
22
  agentName: hubConfig.agentName,
23
+ disabledPacks: disabledPacks.length > 0
24
+ ? disabledPacks
25
+ : undefined,
18
26
  };
19
27
  saveConfig(config);
20
- const executor = new ProbeExecutor();
28
+ const enabledPacks = buildEnabledPacks(packRegistry, disabledPacks);
29
+ const executor = new ProbeExecutor(enabledPacks);
21
30
  enrollWithHub(config, executor)
22
31
  .then(({ agentId: id, apiKey: mintedKey }) => {
23
32
  config.agentId = id;
@@ -1 +1 @@
1
- {"version":3,"file":"StepComplete.js","sourceRoot":"","sources":["../../../src/tui/installer/StepComplete.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StepComplete.js","sourceRoot":"","sources":["../../../src/tui/installer/StepComplete.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ interface StepServiceProps {
2
+ onNext: () => void;
3
+ }
4
+ export declare function StepService({ onNext }: StepServiceProps): JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=StepService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StepService.d.ts","sourceRoot":"","sources":["../../../src/tui/installer/StepService.tsx"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAID,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,gBAAgB,GAAG,GAAG,CAAC,OAAO,CAoGrE"}
@@ -0,0 +1,49 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text, useInput } from 'ink';
3
+ import Spinner from 'ink-spinner';
4
+ import { useState } from 'react';
5
+ import { installService } from '../../cli/service.js';
6
+ export function StepService({ onNext }) {
7
+ const [phase, setPhase] = useState('prompt');
8
+ const [result, setResult] = useState(null);
9
+ const isLinux = process.platform === 'linux';
10
+ useInput((input, key) => {
11
+ if (!isLinux) {
12
+ if (key.return)
13
+ onNext();
14
+ return;
15
+ }
16
+ if (phase === 'prompt') {
17
+ if (input === 'y' || input === 'Y' || key.return) {
18
+ setPhase('installing');
19
+ // Run async to let the spinner render
20
+ setTimeout(() => {
21
+ const res = installService();
22
+ setResult(res);
23
+ setPhase('done');
24
+ }, 0);
25
+ }
26
+ else if (input === 'n' || input === 'N') {
27
+ setResult(null);
28
+ setPhase('done');
29
+ }
30
+ }
31
+ if (phase === 'done' && (key.return || input)) {
32
+ onNext();
33
+ }
34
+ });
35
+ if (!isLinux) {
36
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Systemd Service" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Skipped \u2014 systemd services are only available on Linux." }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press Enter to continue." }) })] }));
37
+ }
38
+ if (phase === 'installing') {
39
+ return (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: " Installing systemd service..." })] }));
40
+ }
41
+ if (phase === 'done') {
42
+ if (result === null) {
43
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Systemd Service" }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "gray", children: ["Skipped. You can set this up later with:", ' ', _jsx(Text, { color: "cyan", children: "sonde service install" })] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press any key to continue." }) })] }));
44
+ }
45
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Systemd Service" }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: result.success ? 'green' : 'red', children: [result.success ? ' OK' : ' !!', " ", result.message] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press any key to continue." }) })] }));
46
+ }
47
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: "Systemd Service" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "Set up sonde-agent as a systemd service? (starts on boot)" }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "y: install service | n: skip" }) })] }));
48
+ }
49
+ //# sourceMappingURL=StepService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StepService.js","sourceRoot":"","sources":["../../../src/tui/installer/StepService.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,OAAO,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAsB,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAQ1E,MAAM,UAAU,WAAW,CAAC,EAAE,MAAM,EAAoB;IACtD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAQ,QAAQ,CAAC,CAAC;IACpD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAuB,IAAI,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;IAE7C,QAAQ,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,GAAG,CAAC,MAAM;gBAAE,MAAM,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QAED,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvB,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBACjD,QAAQ,CAAC,YAAY,CAAC,CAAC;gBACvB,sCAAsC;gBACtC,UAAU,CAAC,GAAG,EAAE;oBACd,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;oBAC7B,SAAS,CAAC,GAAG,CAAC,CAAC;oBACf,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACnB,CAAC,EAAE,CAAC,CAAC,CAAC;YACR,CAAC;iBAAM,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;gBAC1C,SAAS,CAAC,IAAI,CAAC,CAAC;gBAChB,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAED,IAAI,KAAK,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC;YAC9C,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAC,IAAI,IAAC,IAAI,sCAAuB,EACjC,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,6EAA+D,GAC7E,EACN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,yCAAgC,GAC9C,IACF,CACP,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;QAC3B,OAAO,CACL,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAChB,KAAC,OAAO,IAAC,IAAI,EAAC,MAAM,GAAG,GAClB,EACP,KAAC,IAAI,iDAAsC,IACvC,CACP,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAC,IAAI,IAAC,IAAI,sCAAuB,EACjC,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,yDACyB,GAAG,EAC5C,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,sCAA6B,IAC1C,GACH,EACN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,2CAAkC,GAChD,IACF,CACP,CAAC;QACJ,CAAC;QAED,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAC,IAAI,IAAC,IAAI,sCAAuB,EACjC,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,MAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,aAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,OAAG,MAAM,CAAC,OAAO,IAC7C,GACH,EACN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,2CAAkC,GAChD,IACF,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAC,IAAI,IAAC,IAAI,sCAAuB,EACjC,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,4EAAiE,GAClE,EACN,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,6CAAoC,GAClD,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -14,7 +14,8 @@ interface Runtime {
14
14
  }
15
15
  interface ManagerAppProps {
16
16
  createRuntime: (events: ConnectionEvents) => Runtime;
17
+ onDetach?: () => void;
17
18
  }
18
- export declare function ManagerApp({ createRuntime }: ManagerAppProps): JSX.Element;
19
+ export declare function ManagerApp({ createRuntime, onDetach }: ManagerAppProps): JSX.Element;
19
20
  export {};
20
21
  //# sourceMappingURL=ManagerApp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManagerApp.d.ts","sourceRoot":"","sources":["../../../src/tui/manager/ManagerApp.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAQ/D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,OAAO;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED,UAAU,eAAe;IACvB,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC;CACtD;AAID,wBAAgB,UAAU,CAAC,EAAE,aAAa,EAAE,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,CA4H1E"}
1
+ {"version":3,"file":"ManagerApp.d.ts","sourceRoot":"","sources":["../../../src/tui/manager/ManagerApp.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAQ/D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,OAAO;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED,UAAU,eAAe;IACvB,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC;IACrD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAID,wBAAgB,UAAU,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,CA6HpF"}
@@ -7,7 +7,7 @@ import { AuditView } from './AuditView.js';
7
7
  import { PackManager } from './PackManager.js';
8
8
  import { StatusView } from './StatusView.js';
9
9
  const MAX_ACTIVITY = 50;
10
- export function ManagerApp({ createRuntime }) {
10
+ export function ManagerApp({ createRuntime, onDetach }) {
11
11
  const { exit } = useApp();
12
12
  const [view, setView] = useState('status');
13
13
  const [connected, setConnected] = useState(false);
@@ -63,6 +63,7 @@ export function ManagerApp({ createRuntime }) {
63
63
  break;
64
64
  case 'q':
65
65
  runtimeRef.current?.connection.stop();
66
+ onDetach?.();
66
67
  exit();
67
68
  break;
68
69
  }
@@ -74,6 +75,6 @@ export function ManagerApp({ createRuntime }) {
74
75
  const statusColor = connected ? 'green' : 'yellow';
75
76
  const statusText = connected ? 'Connected' : 'Connecting...';
76
77
  const displayId = agentId ? ` (${agentId})` : '';
77
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "Sonde Agent" }), _jsx(Text, { children: " " }), _jsx(Text, { color: statusColor, children: statusText }), _jsx(Text, { color: "gray", children: displayId })] }), view === 'status' && config && executor && auditLog && (_jsx(StatusView, { config: config, connected: connected, agentId: agentId, executor: executor, auditLog: auditLog, activity: activity })), view === 'packs' && executor && _jsx(PackManager, { executor: executor }), view === 'activity' && _jsx(ActivityLog, { activity: activity }), view === 'audit' && auditLog && _jsx(AuditView, { auditLog: auditLog }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: view === 'status' ? 'cyan' : 'gray', bold: view === 'status', children: "s:status" }), _jsx(Text, { children: " " }), _jsx(Text, { color: view === 'packs' ? 'cyan' : 'gray', bold: view === 'packs', children: "p:packs" }), _jsx(Text, { children: " " }), _jsx(Text, { color: view === 'activity' ? 'cyan' : 'gray', bold: view === 'activity', children: "l:activity" }), _jsx(Text, { children: " " }), _jsx(Text, { color: view === 'audit' ? 'cyan' : 'gray', bold: view === 'audit', children: "a:audit" }), _jsx(Text, { children: " " }), _jsx(Text, { color: "gray", children: "q:quit" })] })] }));
78
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "Sonde Agent" }), _jsx(Text, { children: " " }), _jsx(Text, { color: statusColor, children: statusText }), _jsx(Text, { color: "gray", children: displayId })] }), view === 'status' && config && executor && auditLog && (_jsx(StatusView, { config: config, connected: connected, agentId: agentId, executor: executor, auditLog: auditLog, activity: activity })), view === 'packs' && executor && _jsx(PackManager, { executor: executor }), view === 'activity' && _jsx(ActivityLog, { activity: activity }), view === 'audit' && auditLog && _jsx(AuditView, { auditLog: auditLog }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: view === 'status' ? 'cyan' : 'gray', bold: view === 'status', children: "s:status" }), _jsx(Text, { children: " " }), _jsx(Text, { color: view === 'packs' ? 'cyan' : 'gray', bold: view === 'packs', children: "p:packs" }), _jsx(Text, { children: " " }), _jsx(Text, { color: view === 'activity' ? 'cyan' : 'gray', bold: view === 'activity', children: "l:activity" }), _jsx(Text, { children: " " }), _jsx(Text, { color: view === 'audit' ? 'cyan' : 'gray', bold: view === 'audit', children: "a:audit" }), _jsx(Text, { children: " " }), _jsx(Text, { color: "gray", children: "q:detach" })] })] }));
78
79
  }
79
80
  //# sourceMappingURL=ManagerApp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ManagerApp.js","sourceRoot":"","sources":["../../../src/tui/manager/ManagerApp.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ManagerApp.js","sourceRoot":"","sources":["../../../src/tui/manager/ManagerApp.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonde/agent",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -4,6 +4,7 @@ import type { SystemChecker } from '../system/scanner.js';
4
4
  import {
5
5
  type PackCommandDeps,
6
6
  type PackState,
7
+ buildEnabledPacks,
7
8
  cmdPacksInstall,
8
9
  cmdPacksList,
9
10
  cmdPacksScan,
@@ -52,6 +53,7 @@ function createDeps(overrides: Partial<PackCommandDeps> = {}): PackCommandDeps {
52
53
  checker: createMockChecker(),
53
54
  getUserGroups: () => [],
54
55
  log: vi.fn(),
56
+ persist: vi.fn(),
55
57
  ...overrides,
56
58
  };
57
59
  }
@@ -210,4 +212,67 @@ describe('cmdPacksUninstall', () => {
210
212
  const log = deps.log as ReturnType<typeof vi.fn>;
211
213
  expect(log).toHaveBeenCalledWith('Error: Pack "docker" is not installed.');
212
214
  });
215
+
216
+ it('persists disabled packs on uninstall', () => {
217
+ const deps = createDeps();
218
+ cmdPacksUninstall('system', deps);
219
+
220
+ const persist = deps.persist as ReturnType<typeof vi.fn>;
221
+ expect(persist).toHaveBeenCalledTimes(1);
222
+ const firstCall = persist.mock.calls[0] as unknown[];
223
+ const disabled = firstCall[0] as string[];
224
+ expect(disabled).toContain('system');
225
+ expect(disabled).toContain('docker');
226
+ });
227
+ });
228
+
229
+ describe('cmdPacksInstall persistence', () => {
230
+ it('persists disabled packs on install', () => {
231
+ const deps = createDeps();
232
+ cmdPacksInstall('docker', deps);
233
+
234
+ const persist = deps.persist as ReturnType<typeof vi.fn>;
235
+ expect(persist).toHaveBeenCalledTimes(1);
236
+ const firstCall = persist.mock.calls[0] as unknown[];
237
+ const disabled = firstCall[0] as string[];
238
+ expect(disabled).not.toContain('docker');
239
+ expect(disabled).not.toContain('system');
240
+ });
241
+
242
+ it('does not persist when install fails', () => {
243
+ const deps = createDeps();
244
+ cmdPacksInstall('nonexistent', deps);
245
+
246
+ const persist = deps.persist as ReturnType<typeof vi.fn>;
247
+ expect(persist).not.toHaveBeenCalled();
248
+ });
249
+ });
250
+
251
+ describe('buildEnabledPacks', () => {
252
+ it('returns all packs when none disabled', () => {
253
+ const registry = new Map([
254
+ ['system', createMockPack('system')],
255
+ ['docker', createMockPack('docker')],
256
+ ]);
257
+ const result = buildEnabledPacks(registry, []);
258
+ expect([...result.keys()]).toEqual(['system', 'docker']);
259
+ });
260
+
261
+ it('filters out disabled packs', () => {
262
+ const registry = new Map([
263
+ ['system', createMockPack('system')],
264
+ ['docker', createMockPack('docker')],
265
+ ['nginx', createMockPack('nginx')],
266
+ ]);
267
+ const result = buildEnabledPacks(registry, ['docker', 'nginx']);
268
+ expect([...result.keys()]).toEqual(['system']);
269
+ });
270
+
271
+ it('ignores disabled names not in registry', () => {
272
+ const registry = new Map([
273
+ ['system', createMockPack('system')],
274
+ ]);
275
+ const result = buildEnabledPacks(registry, ['nonexistent']);
276
+ expect([...result.keys()]).toEqual(['system']);
277
+ });
213
278
  });
package/src/cli/packs.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { Pack } from '@sonde/packs';
2
2
  import { packRegistry } from '@sonde/packs';
3
3
  import type { PackManifest } from '@sonde/shared';
4
+ import { loadConfig, saveConfig } from '../config.js';
4
5
  import {
5
6
  type PermissionCheck,
6
7
  type ScanResult,
@@ -10,6 +11,24 @@ import {
10
11
  scanForSoftware,
11
12
  } from '../system/scanner.js';
12
13
 
14
+ /**
15
+ * Build a pack map filtered by a disabled list.
16
+ * Used by both the CLI commands and ProbeExecutor creation.
17
+ */
18
+ export function buildEnabledPacks(
19
+ registry: ReadonlyMap<string, Pack>,
20
+ disabledPacks: string[],
21
+ ): Map<string, Pack> {
22
+ const disabled = new Set(disabledPacks);
23
+ const result = new Map<string, Pack>();
24
+ for (const [name, pack] of registry) {
25
+ if (!disabled.has(name)) {
26
+ result.set(name, pack);
27
+ }
28
+ }
29
+ return result;
30
+ }
31
+
13
32
  export interface PackState {
14
33
  /** Packs currently loaded/active on this agent */
15
34
  installed: Map<string, Pack>;
@@ -22,17 +41,28 @@ export interface PackCommandDeps {
22
41
  checker: SystemChecker;
23
42
  getUserGroups: () => string[];
24
43
  log: (msg: string) => void;
44
+ persist: (disabledPacks: string[]) => void;
25
45
  }
26
46
 
27
47
  function createDefaultDeps(): PackCommandDeps {
48
+ const config = loadConfig();
49
+ const disabledPacks = config?.disabledPacks ?? [];
28
50
  return {
29
51
  state: {
30
- installed: new Map(packRegistry),
52
+ installed: buildEnabledPacks(packRegistry, disabledPacks),
31
53
  available: packRegistry,
32
54
  },
33
55
  checker: createSystemChecker(),
34
56
  getUserGroups: getProcessUserGroups,
35
57
  log: console.log,
58
+ persist: (disabled) => {
59
+ const current = loadConfig();
60
+ if (current) {
61
+ current.disabledPacks =
62
+ disabled.length > 0 ? disabled : undefined;
63
+ saveConfig(current);
64
+ }
65
+ },
36
66
  };
37
67
  }
38
68
 
@@ -58,17 +88,20 @@ export function cmdPacksList(deps?: PackCommandDeps): void {
58
88
  return;
59
89
  }
60
90
 
91
+ const bold = (s: string) => `\x1b[1m${s}\x1b[0m`;
92
+
61
93
  log('Installed packs:');
62
94
  log('');
63
95
  for (const [name, pack] of state.installed) {
64
96
  const probeCount = pack.manifest.probes.length;
65
- log(` ${name} v${pack.manifest.version} (${probeCount} probes)`);
97
+ log(` ${bold(name)} v${pack.manifest.version} (${probeCount} probes)`);
66
98
  log(` ${pack.manifest.description}`);
67
99
  for (const probe of pack.manifest.probes) {
68
100
  log(` - ${name}.${probe.name}: ${probe.description}`);
69
101
  }
70
102
  log('');
71
103
  }
104
+ log(` Manage: sonde packs install ${bold('<name>')} | uninstall ${bold('<name>')}`);
72
105
  }
73
106
 
74
107
  export function cmdPacksScan(deps?: PackCommandDeps): ScanResult[] {
@@ -112,7 +145,8 @@ export function cmdPacksInstall(
112
145
  name: string,
113
146
  deps?: PackCommandDeps,
114
147
  ): { success: boolean; permissions?: PermissionCheck } {
115
- const { state, checker, getUserGroups, log } = deps ?? createDefaultDeps();
148
+ const { state, checker, getUserGroups, log, persist } =
149
+ deps ?? createDefaultDeps();
116
150
 
117
151
  const pack = state.available.get(name);
118
152
  if (!pack) {
@@ -128,7 +162,9 @@ export function cmdPacksInstall(
128
162
 
129
163
  // Check permissions
130
164
  const userGroups = getUserGroups();
131
- const permissions = checkPackPermissions(pack.manifest, checker, userGroups);
165
+ const permissions = checkPackPermissions(
166
+ pack.manifest, checker, userGroups,
167
+ );
132
168
 
133
169
  if (!permissions.satisfied) {
134
170
  log(`Pack "${name}" requires additional permissions:`);
@@ -150,13 +186,19 @@ export function cmdPacksInstall(
150
186
  }
151
187
 
152
188
  state.installed.set(name, pack);
189
+ const disabled = [...state.available.keys()]
190
+ .filter((k) => !state.installed.has(k));
191
+ persist(disabled);
153
192
  log(`Pack "${name}" installed successfully.`);
154
193
  log(` ${pack.manifest.probes.length} probes now available.`);
155
194
  return { success: true, permissions };
156
195
  }
157
196
 
158
- export function cmdPacksUninstall(name: string, deps?: PackCommandDeps): boolean {
159
- const { state, log } = deps ?? createDefaultDeps();
197
+ export function cmdPacksUninstall(
198
+ name: string,
199
+ deps?: PackCommandDeps,
200
+ ): boolean {
201
+ const { state, log, persist } = deps ?? createDefaultDeps();
160
202
 
161
203
  if (!state.installed.has(name)) {
162
204
  log(`Error: Pack "${name}" is not installed.`);
@@ -164,19 +206,23 @@ export function cmdPacksUninstall(name: string, deps?: PackCommandDeps): boolean
164
206
  }
165
207
 
166
208
  state.installed.delete(name);
209
+ const disabled = [...state.available.keys()]
210
+ .filter((k) => !state.installed.has(k));
211
+ persist(disabled);
167
212
  log(`Pack "${name}" uninstalled.`);
168
213
  return true;
169
214
  }
170
215
 
171
216
  export function handlePacksCommand(subArgs: string[]): void {
172
217
  const subcommand = subArgs[0];
218
+ const deps = createDefaultDeps();
173
219
 
174
220
  switch (subcommand) {
175
221
  case 'list':
176
- cmdPacksList();
222
+ cmdPacksList(deps);
177
223
  break;
178
224
  case 'scan':
179
- cmdPacksScan();
225
+ cmdPacksScan(deps);
180
226
  break;
181
227
  case 'install': {
182
228
  const name = subArgs[1];
@@ -184,7 +230,7 @@ export function handlePacksCommand(subArgs: string[]): void {
184
230
  console.error('Usage: sonde packs install <name>');
185
231
  process.exit(1);
186
232
  }
187
- const result = cmdPacksInstall(name);
233
+ const result = cmdPacksInstall(name, deps);
188
234
  if (!result.success) process.exit(1);
189
235
  break;
190
236
  }
@@ -194,7 +240,7 @@ export function handlePacksCommand(subArgs: string[]): void {
194
240
  console.error('Usage: sonde packs uninstall <name>');
195
241
  process.exit(1);
196
242
  }
197
- if (!cmdPacksUninstall(name)) process.exit(1);
243
+ if (!cmdPacksUninstall(name, deps)) process.exit(1);
198
244
  break;
199
245
  }
200
246
  default:
@@ -0,0 +1,124 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ vi.mock('node:child_process', () => ({
4
+ execFileSync: vi.fn(),
5
+ }));
6
+
7
+ vi.mock('node:fs', () => ({
8
+ default: { existsSync: vi.fn() },
9
+ }));
10
+
11
+ vi.mock('node:os', () => ({
12
+ default: {
13
+ userInfo: () => ({
14
+ username: 'testuser',
15
+ homedir: '/home/testuser',
16
+ }),
17
+ },
18
+ }));
19
+
20
+ import { execFileSync } from 'node:child_process';
21
+ import fs from 'node:fs';
22
+ import {
23
+ generateUnitFile,
24
+ getServiceStatus,
25
+ isServiceInstalled,
26
+ } from './service.js';
27
+
28
+ const mockExec = vi.mocked(execFileSync);
29
+ const mockExists = vi.mocked(fs.existsSync);
30
+
31
+ describe('generateUnitFile', () => {
32
+ it('includes the current user and home directory', () => {
33
+ mockExec.mockReturnValueOnce('/usr/local/bin/sonde\n');
34
+ const unit = generateUnitFile();
35
+ expect(unit).toContain('User=testuser');
36
+ expect(unit).toContain('Environment=HOME=/home/testuser');
37
+ });
38
+
39
+ it('includes the resolved sonde binary path', () => {
40
+ mockExec.mockReturnValueOnce('/usr/local/bin/sonde\n');
41
+ const unit = generateUnitFile();
42
+ expect(unit).toContain(
43
+ 'ExecStart=/usr/local/bin/sonde start --headless',
44
+ );
45
+ });
46
+
47
+ it('sets restart on failure with 5s delay', () => {
48
+ mockExec.mockReturnValueOnce('/usr/bin/sonde\n');
49
+ const unit = generateUnitFile();
50
+ expect(unit).toContain('Restart=on-failure');
51
+ expect(unit).toContain('RestartSec=5');
52
+ });
53
+
54
+ it('targets network-online', () => {
55
+ mockExec.mockReturnValueOnce('/usr/bin/sonde\n');
56
+ const unit = generateUnitFile();
57
+ expect(unit).toContain('After=network-online.target');
58
+ expect(unit).toContain('Wants=network-online.target');
59
+ });
60
+ });
61
+
62
+ describe('isServiceInstalled', () => {
63
+ const originalPlatform = process.platform;
64
+
65
+ afterEach(() => {
66
+ Object.defineProperty(process, 'platform', {
67
+ value: originalPlatform,
68
+ });
69
+ });
70
+
71
+ it('returns false on non-Linux platforms', () => {
72
+ Object.defineProperty(process, 'platform', { value: 'darwin' });
73
+ expect(isServiceInstalled()).toBe(false);
74
+ });
75
+
76
+ it('returns true when unit file exists on Linux', () => {
77
+ Object.defineProperty(process, 'platform', { value: 'linux' });
78
+ mockExists.mockReturnValueOnce(true);
79
+ expect(isServiceInstalled()).toBe(true);
80
+ });
81
+
82
+ it('returns false when unit file is missing on Linux', () => {
83
+ Object.defineProperty(process, 'platform', { value: 'linux' });
84
+ mockExists.mockReturnValueOnce(false);
85
+ expect(isServiceInstalled()).toBe(false);
86
+ });
87
+ });
88
+
89
+ describe('getServiceStatus', () => {
90
+ const originalPlatform = process.platform;
91
+
92
+ afterEach(() => {
93
+ Object.defineProperty(process, 'platform', {
94
+ value: originalPlatform,
95
+ });
96
+ });
97
+
98
+ it('returns unsupported on non-Linux', () => {
99
+ Object.defineProperty(process, 'platform', { value: 'darwin' });
100
+ expect(getServiceStatus()).toBe('unsupported');
101
+ });
102
+
103
+ it('returns not-installed when unit file missing', () => {
104
+ Object.defineProperty(process, 'platform', { value: 'linux' });
105
+ mockExists.mockReturnValueOnce(false);
106
+ expect(getServiceStatus()).toBe('not-installed');
107
+ });
108
+
109
+ it('returns active status from systemctl', () => {
110
+ Object.defineProperty(process, 'platform', { value: 'linux' });
111
+ mockExists.mockReturnValueOnce(true);
112
+ mockExec.mockReturnValueOnce('active\n');
113
+ expect(getServiceStatus()).toBe('active');
114
+ });
115
+
116
+ it('returns inactive when systemctl throws', () => {
117
+ Object.defineProperty(process, 'platform', { value: 'linux' });
118
+ mockExists.mockReturnValueOnce(true);
119
+ mockExec.mockImplementationOnce(() => {
120
+ throw new Error('exit code 3');
121
+ });
122
+ expect(getServiceStatus()).toBe('inactive');
123
+ });
124
+ });