nterminal 1.2.22 → 1.2.24

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 (38) hide show
  1. package/bin/nterminal.js +1 -0
  2. package/dist/client/assets/{MarkdownPreview-D8zAIfDx.js → MarkdownPreview-DCfGMtwX.js} +1 -1
  3. package/dist/client/assets/{index-Bzw1v9JR.css → index-f-1XNznv.css} +1 -1
  4. package/dist/client/assets/{index-CXBkB4aI.js → index-ljxLHcWv.js} +22 -26
  5. package/dist/client/index.html +2 -2
  6. package/dist/scripts/onboarding.js +241 -3
  7. package/dist/scripts/onboarding.js.map +1 -1
  8. package/dist/server/agent/agentRoutes.js +11 -0
  9. package/dist/server/agent/agentRoutes.js.map +1 -1
  10. package/dist/server/config.d.ts +1 -0
  11. package/dist/server/config.js +12 -0
  12. package/dist/server/config.js.map +1 -1
  13. package/dist/server/index.js +44 -35
  14. package/dist/server/index.js.map +1 -1
  15. package/dist/server/routes/updateRoutes.js +11 -1
  16. package/dist/server/routes/updateRoutes.js.map +1 -1
  17. package/dist/server/runtimeState.d.ts +4 -0
  18. package/dist/server/runtimeState.js +13 -0
  19. package/dist/server/runtimeState.js.map +1 -0
  20. package/dist/server/storage/fileStore.d.ts +11 -1
  21. package/dist/server/storage/fileStore.js +20 -1
  22. package/dist/server/storage/fileStore.js.map +1 -1
  23. package/dist/server/terminal/transcriptHistory.js +6 -6
  24. package/dist/server/terminal/transcriptHistory.js.map +1 -1
  25. package/dist/server/update/packageUpdate.js +50 -10
  26. package/dist/server/update/packageUpdate.js.map +1 -1
  27. package/dist/server/update/stateCheckpoint.d.ts +3 -0
  28. package/dist/server/update/stateCheckpoint.js +34 -0
  29. package/dist/server/update/stateCheckpoint.js.map +1 -0
  30. package/dist/shared/manualUpdate.d.ts +1 -1
  31. package/dist/shared/manualUpdate.js +2 -2
  32. package/dist/shared/manualUpdate.js.map +1 -1
  33. package/docs/configuration.md +1 -0
  34. package/docs/features.md +2 -2
  35. package/docs/onboarding.md +1 -1
  36. package/docs/operations.md +4 -2
  37. package/package.json +1 -1
  38. package/scripts/nterminalctl +91 -0
@@ -5,6 +5,7 @@ import path from 'node:path';
5
5
  import { createManualUpdateInfo, isPermissionUpdateFailure } from '../../shared/manualUpdate.js';
6
6
  const updateLockStaleMs = 10 * 60 * 1000;
7
7
  const packageUpdateTimeoutMs = 5 * 60 * 1000;
8
+ const defaultUpdateHelperPath = '/usr/local/sbin/nterminal-update';
8
9
  function appDir() {
9
10
  return process.env.NTERMINAL_APP_DIR ? path.resolve(process.env.NTERMINAL_APP_DIR) : process.cwd();
10
11
  }
@@ -16,6 +17,27 @@ function npm(args, cwd, timeout = 60_000) {
16
17
  stderr: (result.stderr ?? '').trim()
17
18
  };
18
19
  }
20
+ function updateHelperPath() {
21
+ return process.env.NTERMINAL_UPDATE_HELPER_PATH?.trim() || defaultUpdateHelperPath;
22
+ }
23
+ function sudoBin() {
24
+ return process.env.NTERMINAL_SUDO_BIN?.trim() || 'sudo';
25
+ }
26
+ function runUpdateHelper(action, cwd, timeout = 60_000) {
27
+ const result = spawnSync(sudoBin(), ['-n', updateHelperPath(), action], { cwd, encoding: 'utf8', timeout });
28
+ return {
29
+ ok: result.status === 0,
30
+ stdout: (result.stdout ?? '').trim(),
31
+ stderr: (result.stderr ?? '').trim()
32
+ };
33
+ }
34
+ function helperOutput(result) {
35
+ return result.stderr || result.stdout || 'privileged update helper failed';
36
+ }
37
+ function isHelperPermissionFailure(output) {
38
+ return (isPermissionUpdateFailure(output) ||
39
+ /sudo|password is required|a password is required|not in the sudoers file|not allowed|authentication|privileged update helper/i.test(output));
40
+ }
19
41
  function readPackageName(cwd) {
20
42
  try {
21
43
  const pkg = JSON.parse(readFileSync(path.join(cwd, 'package.json'), 'utf8'));
@@ -136,19 +158,37 @@ export function runUpdate(cwd = appDir()) {
136
158
  if (!check.latestVersion || installedVersion !== check.latestVersion) {
137
159
  const install = npm(['install', '-g', `${packageName}@latest`, '--prefer-online'], cwd, packageUpdateTimeoutMs);
138
160
  if (!install.ok) {
139
- releaseUpdateLock(cwd);
140
161
  const output = install.stderr || install.stdout || 'npm install -g failed';
141
- const manualUpdate = isPermissionUpdateFailure(output) ? createManualUpdateInfo(packageName) : null;
142
- return {
143
- ok: false,
144
- changed: false,
145
- message: manualUpdate?.message ?? output,
146
- restarting: false,
147
- ...(manualUpdate ? { manualUpdate } : {})
148
- };
162
+ const helperCheck = isPermissionUpdateFailure(output) ? runUpdateHelper('check', cwd) : null;
163
+ if (helperCheck?.ok) {
164
+ const helperInstall = runUpdateHelper('install', cwd, packageUpdateTimeoutMs);
165
+ if (!helperInstall.ok) {
166
+ releaseUpdateLock(cwd);
167
+ const elevatedOutput = helperOutput(helperInstall);
168
+ const manualUpdate = isHelperPermissionFailure(elevatedOutput) ? createManualUpdateInfo(packageName) : null;
169
+ return {
170
+ ok: false,
171
+ changed: false,
172
+ message: manualUpdate?.message ?? elevatedOutput,
173
+ restarting: false,
174
+ ...(manualUpdate ? { manualUpdate } : {})
175
+ };
176
+ }
177
+ }
178
+ else {
179
+ releaseUpdateLock(cwd);
180
+ const manualUpdate = isPermissionUpdateFailure(output) || (helperCheck && isHelperPermissionFailure(helperOutput(helperCheck))) ? createManualUpdateInfo(packageName) : null;
181
+ return {
182
+ ok: false,
183
+ changed: false,
184
+ message: manualUpdate?.message ?? output,
185
+ restarting: false,
186
+ ...(manualUpdate ? { manualUpdate } : {})
187
+ };
188
+ }
149
189
  }
150
190
  }
151
- const restart = spawn('sh', ['-c', 'sleep 0.2; exec bash "$1" restart', 'nterminal-restart', path.join(cwd, 'scripts/nterminalctl')], {
191
+ const restart = spawn('sh', ['-c', 'sleep 0.2; exec bash "$1" restart-after-update', 'nterminal-restart', path.join(cwd, 'scripts/nterminalctl')], {
152
192
  cwd,
153
193
  detached: true,
154
194
  env: { ...process.env, NTERMINAL_UPDATE_LOCK_PATH: lockPath(cwd) },
@@ -1 +1 @@
1
- {"version":3,"file":"packageUpdate.js","sourceRoot":"","sources":["../../../src/server/update/packageUpdate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1G,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEjG,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACzC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAuB7C,SAAS,MAAM;IACb,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;AACrG,CAAC;AAED,SAAS,GAAG,CAAC,IAAc,EAAE,GAAW,EAAE,OAAO,GAAG,MAAM;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3G,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QACvB,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QACpC,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAsB,CAAC;QAClG,OAAO,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAC;QACrG,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,2EAA2E;AAC3E,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC;AAC/B,MAAM,cAAc,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;AAEzD,8FAA8F;AAC9F,iGAAiG;AACjG,SAAS,kBAAkB,CAAC,GAAW,EAAE,KAAa;IACpD,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC;IAC5D,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAChH,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,iBAAiB,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,SAAS,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,SAAS,CAAC;QACR,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC;gBACH,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACxC,CAAC;oBAAS,CAAC;gBACT,SAAS,CAAC,EAAE,CAAC,CAAC;YAChB,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,aAAa,CAAC,KAAK,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACtC,MAAM,KAAK,CAAC;YACd,CAAC;YACD,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAG,GAAG,MAAM,EAAE,EAAE,eAAwC,IAAI;IACzF,OAAO;QACL,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAChC,cAAc,EAAE,qBAAqB,CAAC,GAAG,CAAC;QAC1C,YAAY;KACb,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAG,GAAG,MAAM,EAAE;IAC/C,MAAM,cAAc,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,WAAW,SAAS,EAAE,SAAS,EAAE,iBAAiB,CAAC,EAAE,GAAG,CAAC,CAAC;IACzF,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO;YACL,cAAc;YACd,aAAa,EAAE,IAAI;YACnB,eAAe,EAAE,IAAI;YACrB,KAAK,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,iBAAiB;SAC3D,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;IAC1E,OAAO;QACL,cAAc;QACd,aAAa;QACb,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC,aAAa,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI;KACzE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAG,GAAG,MAAM,EAAE;IACtC,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kDAAkD,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACvH,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;QAC3B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACzF,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kDAAkD,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACvH,CAAC;IACD,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,gBAAgB,KAAK,KAAK,CAAC,aAAa,EAAE,CAAC;QACrE,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,WAAW,SAAS,EAAE,iBAAiB,CAAC,EAAE,GAAG,EAAE,sBAAsB,CAAC,CAAC;QAChH,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACvB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,uBAAuB,CAAC;YAC3E,MAAM,YAAY,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACpG,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,YAAY,EAAE,OAAO,IAAI,MAAM;gBACxC,UAAU,EAAE,KAAK;gBACjB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,mCAAmC,EAAE,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC,EAAE;QACpI,GAAG;QACH,QAAQ,EAAE,IAAI;QACd,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,0BAA0B,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE;QAClE,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;IACH,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,WAAW,WAAW,IAAI,KAAK,CAAC,cAAc,IAAI,EAAE,OAAO,KAAK,CAAC,aAAa,IAAI,QAAQ,eAAe;QAClH,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAE,KAA4B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACjI,CAAC"}
1
+ {"version":3,"file":"packageUpdate.js","sourceRoot":"","sources":["../../../src/server/update/packageUpdate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1G,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEjG,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACzC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7C,MAAM,uBAAuB,GAAG,kCAAkC,CAAC;AAuBnE,SAAS,MAAM;IACb,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;AACrG,CAAC;AAED,SAAS,GAAG,CAAC,IAAc,EAAE,GAAW,EAAE,OAAO,GAAG,MAAM;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3G,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QACvB,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QACpC,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,IAAI,EAAE,IAAI,uBAAuB,CAAC;AACrF,CAAC;AAED,SAAS,OAAO;IACd,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC;AAC1D,CAAC;AAED,SAAS,eAAe,CAAC,MAA2B,EAAE,GAAW,EAAE,OAAO,GAAG,MAAM;IACjF,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5G,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QACvB,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QACpC,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,MAA0C;IAC9D,OAAO,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,iCAAiC,CAAC;AAC7E,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAc;IAC/C,OAAO,CACL,yBAAyB,CAAC,MAAM,CAAC;QACjC,+HAA+H,CAAC,IAAI,CAAC,MAAM,CAAC,CAC7I,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAsB,CAAC;QAClG,OAAO,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAC;QACrG,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,2EAA2E;AAC3E,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC;AAC/B,MAAM,cAAc,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;AAEzD,8FAA8F;AAC9F,iGAAiG;AACjG,SAAS,kBAAkB,CAAC,GAAW,EAAE,KAAa;IACpD,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC;IAC5D,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAChH,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,iBAAiB,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,SAAS,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,SAAS,CAAC;QACR,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC;gBACH,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACxC,CAAC;oBAAS,CAAC;gBACT,SAAS,CAAC,EAAE,CAAC,CAAC;YAChB,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,aAAa,CAAC,KAAK,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACtC,MAAM,KAAK,CAAC;YACd,CAAC;YACD,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAG,GAAG,MAAM,EAAE,EAAE,eAAwC,IAAI;IACzF,OAAO;QACL,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC;QAChC,cAAc,EAAE,qBAAqB,CAAC,GAAG,CAAC;QAC1C,YAAY;KACb,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAG,GAAG,MAAM,EAAE;IAC/C,MAAM,cAAc,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,WAAW,SAAS,EAAE,SAAS,EAAE,iBAAiB,CAAC,EAAE,GAAG,CAAC,CAAC;IACzF,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO;YACL,cAAc;YACd,aAAa,EAAE,IAAI;YACnB,eAAe,EAAE,IAAI;YACrB,KAAK,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,iBAAiB;SAC3D,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;IAC1E,OAAO;QACL,cAAc;QACd,aAAa;QACb,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC,aAAa,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI;KACzE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAG,GAAG,MAAM,EAAE;IACtC,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kDAAkD,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACvH,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;QAC3B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACzF,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kDAAkD,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACvH,CAAC;IACD,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,gBAAgB,KAAK,KAAK,CAAC,aAAa,EAAE,CAAC;QACrE,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,WAAW,SAAS,EAAE,iBAAiB,CAAC,EAAE,GAAG,EAAE,sBAAsB,CAAC,CAAC;QAChH,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,uBAAuB,CAAC;YAC3E,MAAM,WAAW,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7F,IAAI,WAAW,EAAE,EAAE,EAAE,CAAC;gBACpB,MAAM,aAAa,GAAG,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,sBAAsB,CAAC,CAAC;gBAC9E,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;oBACtB,iBAAiB,CAAC,GAAG,CAAC,CAAC;oBACvB,MAAM,cAAc,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;oBACnD,MAAM,YAAY,GAAG,yBAAyB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBAC5G,OAAO;wBACL,EAAE,EAAE,KAAK;wBACT,OAAO,EAAE,KAAK;wBACd,OAAO,EAAE,YAAY,EAAE,OAAO,IAAI,cAAc;wBAChD,UAAU,EAAE,KAAK;wBACjB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC1C,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBACvB,MAAM,YAAY,GAAG,yBAAyB,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,yBAAyB,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC7K,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,OAAO,EAAE,KAAK;oBACd,OAAO,EAAE,YAAY,EAAE,OAAO,IAAI,MAAM;oBACxC,UAAU,EAAE,KAAK;oBACjB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC1C,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,gDAAgD,EAAE,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC,EAAE;QACjJ,GAAG;QACH,QAAQ,EAAE,IAAI;QACd,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,0BAA0B,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE;QAClE,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;IACH,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,WAAW,WAAW,IAAI,KAAK,CAAC,cAAc,IAAI,EAAE,OAAO,KAAK,CAAC,aAAa,IAAI,QAAQ,eAAe;QAClH,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAE,KAA4B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACjI,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AppConfig } from '../config.js';
2
+ import type { FileStore } from '../storage/fileStore.js';
3
+ export declare function checkpointStateBeforeUpdate(config: AppConfig, fileStore: FileStore): Promise<void>;
@@ -0,0 +1,34 @@
1
+ export async function checkpointStateBeforeUpdate(config, fileStore) {
2
+ const checkpointOptions = config.role === 'main' ? { validateSnapshot: validateMainSnapshot } : {};
3
+ const { snapshot, disk } = await fileStore.checkpoint(checkpointOptions);
4
+ if (config.role === 'main') {
5
+ validateMainDiskCheckpoint(snapshot, disk);
6
+ }
7
+ }
8
+ function validateMainSnapshot(snapshot) {
9
+ requireMainPassword(snapshot);
10
+ }
11
+ function validateMainDiskCheckpoint(snapshot, disk) {
12
+ const snapshotPassword = requireMainPassword(snapshot);
13
+ if (!disk.passwordCredential) {
14
+ throw new Error('main state checkpoint did not preserve the password credential on disk');
15
+ }
16
+ if (disk.passwordCredential.hash !== snapshotPassword.hash ||
17
+ disk.passwordCredential.salt !== snapshotPassword.salt ||
18
+ disk.passwordCredential.createdAt !== snapshotPassword.createdAt ||
19
+ disk.passwordCredential.updatedAt !== snapshotPassword.updatedAt) {
20
+ throw new Error('main state checkpoint changed the password credential on disk');
21
+ }
22
+ const diskAgentIds = new Set(disk.agents.map((agent) => agent.id));
23
+ const missingAgentIds = snapshot.agents.map((agent) => agent.id).filter((agentId) => !diskAgentIds.has(agentId));
24
+ if (missingAgentIds.length > 0) {
25
+ throw new Error(`main state checkpoint lost ${missingAgentIds.length} registered secondary server(s)`);
26
+ }
27
+ }
28
+ function requireMainPassword(snapshot) {
29
+ if (!snapshot.passwordCredential) {
30
+ throw new Error('main state has no password credential in memory');
31
+ }
32
+ return snapshot.passwordCredential;
33
+ }
34
+ //# sourceMappingURL=stateCheckpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateCheckpoint.js","sourceRoot":"","sources":["../../../src/server/update/stateCheckpoint.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,MAAiB,EAAE,SAAoB;IACvF,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnG,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IACzE,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,0BAA0B,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAqB;IACjD,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,0BAA0B,CAAC,QAAqB,EAAE,IAAiB;IAC1E,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;IACD,IACE,IAAI,CAAC,kBAAkB,CAAC,IAAI,KAAK,gBAAgB,CAAC,IAAI;QACtD,IAAI,CAAC,kBAAkB,CAAC,IAAI,KAAK,gBAAgB,CAAC,IAAI;QACtD,IAAI,CAAC,kBAAkB,CAAC,SAAS,KAAK,gBAAgB,CAAC,SAAS;QAChE,IAAI,CAAC,kBAAkB,CAAC,SAAS,KAAK,gBAAgB,CAAC,SAAS,EAChE,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACjH,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,8BAA8B,eAAe,CAAC,MAAM,iCAAiC,CAAC,CAAC;IACzG,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAqB;IAChD,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,QAAQ,CAAC,kBAAkB,CAAC;AACrC,CAAC"}
@@ -1,4 +1,4 @@
1
1
  import type { ManualUpdateInfo } from './protocol.js';
2
- export declare const manualUpdateMessage = "Automatic update needs write access to the global npm install. Run the manual update command as the NTerminal runtime user; only the npm install step should use sudo.";
2
+ export declare const manualUpdateMessage = "Automatic update needs write access to the global npm install. Run this from a normal NTerminal runtime-user shell; only the npm install step uses sudo.";
3
3
  export declare function createManualUpdateInfo(packageName?: string, detectedAt?: Date): ManualUpdateInfo;
4
4
  export declare function isPermissionUpdateFailure(output: string): boolean;
@@ -1,9 +1,9 @@
1
- export const manualUpdateMessage = 'Automatic update needs write access to the global npm install. Run the manual update command as the NTerminal runtime user; only the npm install step should use sudo.';
1
+ export const manualUpdateMessage = 'Automatic update needs write access to the global npm install. Run this from a normal NTerminal runtime-user shell; only the npm install step uses sudo.';
2
2
  export function createManualUpdateInfo(packageName = 'nterminal', detectedAt = new Date()) {
3
3
  return {
4
4
  reason: 'permission',
5
5
  message: manualUpdateMessage,
6
- command: `sudo npm i -g ${packageName}@latest --prefer-online && nterminal restart`,
6
+ command: `sudo npm i -g ${packageName}@latest --prefer-online && nterminal restart-after-update`,
7
7
  detectedAt: detectedAt.toISOString()
8
8
  };
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"manualUpdate.js","sourceRoot":"","sources":["../../src/shared/manualUpdate.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAC9B,wKAAwK,CAAC;AAE3K,MAAM,UAAU,sBAAsB,CAAC,WAAW,GAAG,WAAW,EAAE,UAAU,GAAG,IAAI,IAAI,EAAE;IACvF,OAAO;QACL,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,mBAAmB;QAC5B,OAAO,EAAE,iBAAiB,WAAW,8CAA8C;QACnF,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,OAAO,qKAAqK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5L,CAAC"}
1
+ {"version":3,"file":"manualUpdate.js","sourceRoot":"","sources":["../../src/shared/manualUpdate.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAC9B,0JAA0J,CAAC;AAE7J,MAAM,UAAU,sBAAsB,CAAC,WAAW,GAAG,WAAW,EAAE,UAAU,GAAG,IAAI,IAAI,EAAE;IACvF,OAAO;QACL,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,mBAAmB;QAC5B,OAAO,EAAE,iBAAiB,WAAW,2DAA2D;QAChG,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,OAAO,qKAAqK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5L,CAAC"}
@@ -20,6 +20,7 @@ Onboarding writes `.env` for you, including an absolute `NTERMINAL_STATE_PATH` s
20
20
 
21
21
  | Setting | Default | Purpose |
22
22
  | --- | --- | --- |
23
+ | `NTERMINAL_ROLE` | required | `main` or `secondary`. Onboarding writes it; runtime startup fails if it is missing. |
23
24
  | `NTERMINAL_HOST` | `127.0.0.1` | Bind host. Keep the main server local unless a separate access boundary is in front. |
24
25
  | `NTERMINAL_PORT` | `3107` | HTTP server port. |
25
26
  | `NTERMINAL_WORKSPACE_ROOT` | home directory | Startup directory for new terminal tabs. |
package/docs/features.md CHANGED
@@ -44,9 +44,9 @@
44
44
  - Mouse wheel scrolling is captured for terminal output history instead of Codex/Claude prompt history.
45
45
  - tmux-backed panes load older scrollback incrementally when the viewport reaches the top.
46
46
  - Scroll progress indicators, jump-to-bottom controls, and follow-tail behavior keep large outputs usable.
47
- - Supported Codex/Claude panes show a `JSONL` header indicator and can continue into archived transcript history.
47
+ - Supported Codex/Claude panes show a `View history` header button and can continue into archived transcript history.
48
48
  - JSONL transcript history is loaded by cursor only when NTerminal can determine the session source unambiguously.
49
- - The JSONL viewer supports search, role/type filters, collapsible long tool blocks, and scroll-to-load older entries.
49
+ - The history viewer opens near fullscreen, renders the transcript as terminal-like raw output, starts at the newest line, and loads older entries as you scroll upward.
50
50
 
51
51
  ## Files
52
52
 
@@ -78,6 +78,6 @@ The "Main is ready" summary is printed only after the selected setup path has co
78
78
 
79
79
  You can re-run onboarding to refresh generated config or register a secondary server again.
80
80
 
81
- Existing `NTERMINAL_HOST`, `NTERMINAL_PORT`, `NTERMINAL_SESSION_SECRET`, and `NTERMINAL_AGENT_TOKEN` values are preserved on re-run, so onboarding does not silently change the bind address, kick live sessions, or rotate a secondary server identity.
81
+ Existing `NTERMINAL_PORT`, `NTERMINAL_SESSION_SECRET`, and `NTERMINAL_AGENT_TOKEN` values are preserved on re-run. Main onboarding always forces `NTERMINAL_HOST=127.0.0.1` so public traffic goes through nginx/TLS; secondary onboarding preserves its existing bind host.
82
82
 
83
83
  Registering the same secondary server URL again replaces the previous entry for that URL.
@@ -34,14 +34,16 @@ Each server updates itself as an npm package install.
34
34
  The **updates** panel in the main server sidebar footer can manage the fleet:
35
35
 
36
36
  - **Check for updates** checks the npm registry.
37
- - **Update** runs `npm install -g nterminal@latest --prefer-online` plus restart.
38
- - **Update all** updates secondary servers in parallel first and the main server last.
37
+ - **Update** runs `npm install -g nterminal@latest --prefer-online` plus a package-aware restart.
38
+ - **Update all** updates secondary servers in parallel first, then still attempts the main server last even if a secondary failed.
39
39
 
40
40
  Notes:
41
41
 
42
42
  - npm package updates run as the same user that owns the running server process. Use a user-writable npm prefix, not a root-owned global install, if you want UI updates to work without sudo.
43
+ - If the global npm prefix is root-owned, onboarding can install a restricted sudo helper pinned to the detected npm prefix for `nterminal@latest` updates only.
43
44
  - An npm registry or permission error is reported as an explanatory status.
44
45
  - Update endpoints require the same auth boundary as the rest of NTerminal.
46
+ - Runtime startup refuses to create missing main state. If `~/.nterminal/state.json` is missing or has no password credential, restore it or run onboarding instead of booting into a new empty setup.
45
47
 
46
48
  ## Clean Uninstall
47
49
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nterminal",
3
- "version": "1.2.22",
3
+ "version": "1.2.24",
4
4
  "license": "GPL-3.0-only",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.7",
@@ -81,6 +81,7 @@ LOG_PATH="$(resolve_path "${NTERMINAL_LOG_PATH:-${NTERMINAL_RUNTIME_LOG_PATH:-$D
81
81
  STATE_PATH="$(resolve_path "${NTERMINAL_STATE_PATH:-${NTERMINAL_RUNTIME_STATE_PATH:-$DEFAULT_STATE_PATH}}")"
82
82
  HEALTH_TIMEOUT_SECONDS="${NTERMINAL_HEALTH_TIMEOUT_SECONDS:-15}"
83
83
  STOP_TIMEOUT_SECONDS="${NTERMINAL_STOP_TIMEOUT_SECONDS:-20}"
84
+ FATAL_STARTUP_EXIT_CODE="${NTERMINAL_FATAL_STARTUP_EXIT_CODE:-78}"
84
85
  RUNTIME_ENTRY="$APP_DIR/dist/server/index.js"
85
86
  LAUNCHD_LABEL="${NTERMINAL_LAUNCHD_LABEL:-com.nterminal.local}"
86
87
  UPDATE_LOCK_PATH="${NTERMINAL_UPDATE_LOCK_PATH:-}"
@@ -147,9 +148,41 @@ validate_required_env() {
147
148
  missing=1
148
149
  fi
149
150
  done
151
+ if [[ "${NTERMINAL_ROLE:-}" != "main" && "${NTERMINAL_ROLE:-}" != "secondary" ]]; then
152
+ echo "missing or invalid env: NTERMINAL_ROLE (expected main or secondary)"
153
+ missing=1
154
+ fi
155
+ if [[ "${NTERMINAL_ROLE:-}" == "secondary" ]]; then
156
+ local agent_token="${NTERMINAL_AGENT_TOKEN:-}"
157
+ if (( ${#agent_token} < 32 )); then
158
+ echo "missing or too-short env: NTERMINAL_AGENT_TOKEN"
159
+ missing=1
160
+ fi
161
+ fi
150
162
  return "$missing"
151
163
  }
152
164
 
165
+ doctor_runtime_state() {
166
+ local role="${NTERMINAL_ROLE:-}"
167
+ if [[ "$role" != "main" && "$role" != "secondary" ]]; then
168
+ return 1
169
+ fi
170
+ if [[ ! -f "$STATE_PATH" ]]; then
171
+ echo "fail state: state file not found at $STATE_PATH"
172
+ return 1
173
+ fi
174
+ if [[ "$role" == "secondary" ]]; then
175
+ echo "ok state: $STATE_PATH"
176
+ return 0
177
+ fi
178
+ if "$NODE_BIN" -e 'const fs = require("node:fs"); const state = JSON.parse(fs.readFileSync(process.argv[1], "utf8")); process.exit(state && typeof state.passwordCredential === "object" && state.passwordCredential ? 0 : 2);' "$STATE_PATH" >/dev/null 2>&1; then
179
+ echo "ok state: main password credential present"
180
+ return 0
181
+ fi
182
+ echo "fail state: main state has no passwordCredential at $STATE_PATH"
183
+ return 1
184
+ }
185
+
153
186
  prepare_start() {
154
187
  ensure_app_dir
155
188
  ensure_env_file
@@ -438,6 +471,11 @@ cmd_supervise() {
438
471
  rm -f "$MONITOR_PID_PATH"
439
472
  exit 0
440
473
  fi
474
+ if (( status == FATAL_STARTUP_EXIT_CODE )); then
475
+ printf '[%s] NTerminal process exited with fatal startup status=%s; supervisor will not restart it\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$status" >> "$LOG_PATH"
476
+ rm -f "$MONITOR_PID_PATH"
477
+ exit "$status"
478
+ fi
441
479
 
442
480
  printf '[%s] NTerminal process exited status=%s; restarting in 2s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$status" >> "$LOG_PATH"
443
481
  sleep 2
@@ -480,6 +518,30 @@ wait_for_health() {
480
518
  return 1
481
519
  }
482
520
 
521
+ restart_supervised_child() {
522
+ local monitor_pid="$1"
523
+ local old_pid="${2:-}"
524
+
525
+ if [[ -n "$old_pid" ]]; then
526
+ stop_supervised_child "$old_pid"
527
+ fi
528
+
529
+ local pid=""
530
+ local deadline=$((SECONDS + HEALTH_TIMEOUT_SECONDS))
531
+ while (( SECONDS <= deadline )); do
532
+ if ! is_running "$monitor_pid"; then
533
+ return 1
534
+ fi
535
+ pid="$(current_pid || true)"
536
+ if [[ -n "$pid" && "$pid" != "$old_pid" ]] && wait_for_health "$pid"; then
537
+ info "NTerminal restarted pid=$pid supervisor=$monitor_pid url=$(public_url) log=$LOG_PATH"
538
+ return 0
539
+ fi
540
+ sleep 0.25
541
+ done
542
+ return 1
543
+ }
544
+
483
545
  port_owner_pid() {
484
546
  if command -v lsof >/dev/null 2>&1; then
485
547
  lsof -nP -iTCP:"$PORT" -sTCP:LISTEN -t 2>/dev/null | head -n 1
@@ -645,12 +707,37 @@ cmd_restart() {
645
707
  start_launchd
646
708
  else
647
709
  prepare_start
710
+ remove_stale_pid
711
+ remove_stale_monitor_pid
712
+ local monitor_pid
713
+ monitor_pid="$(current_monitor_pid || true)"
714
+ if [[ -n "$monitor_pid" ]]; then
715
+ local pid
716
+ pid="$(current_pid || true)"
717
+ if restart_supervised_child "$monitor_pid" "$pid"; then
718
+ return 0
719
+ fi
720
+ echo "NTerminal failed to restart under supervisor. Last log lines:" >&2
721
+ tail -n 40 "$LOG_PATH" >&2 || true
722
+ return 1
723
+ fi
648
724
  cmd_stop >/dev/null
649
725
  cmd_start
650
726
  fi
651
727
  info "NTerminal restarted"
652
728
  }
653
729
 
730
+ cmd_restart_after_update() {
731
+ prepare_start
732
+ if launchd_controls_app; then
733
+ start_launchd
734
+ info "NTerminal restarted after update"
735
+ return 0
736
+ fi
737
+ cmd_stop >/dev/null || true
738
+ cmd_start
739
+ }
740
+
654
741
  cmd_build() {
655
742
  ensure_app_dir
656
743
  ensure_runtime
@@ -804,6 +891,7 @@ cmd_doctor() {
804
891
  echo "fail env: .env not found at $ENV_FILE"
805
892
  failed=1
806
893
  fi
894
+ doctor_runtime_state || failed=1
807
895
 
808
896
  if [[ -f "$RUNTIME_ENTRY" ]]; then
809
897
  echo "ok runtime: dist/server/index.js"
@@ -842,6 +930,8 @@ Commands:
842
930
  start Start the built server in the background.
843
931
  stop Stop the managed server and supervisor with SIGTERM, then SIGKILL after timeout.
844
932
  restart Stop and start the server.
933
+ restart-after-update
934
+ Stop the supervisor and start again after an npm package update.
845
935
  build No-op for package installs; verifies the bundled runtime exists.
846
936
  deploy Restart the installed package using the bundled runtime.
847
937
  clean --force Stop server, kill NTerminal tmux sessions, and remove local state/log/pid files.
@@ -875,6 +965,7 @@ case "$COMMAND" in
875
965
  supervise) cmd_supervise "$@" ;;
876
966
  stop) cmd_stop "$@" ;;
877
967
  restart|reload) cmd_restart "$@" ;;
968
+ restart-after-update) cmd_restart_after_update "$@" ;;
878
969
  build) cmd_build "$@" ;;
879
970
  deploy) cmd_deploy "$@" ;;
880
971
  clean|purge) cmd_clean "$@" ;;