@jungjaehoon/mama-os 0.78.0 → 0.79.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.
- package/CHANGELOG.md +311 -0
- package/README.md +38 -24
- package/db/migrations/002-model-runs-parent-index.sql +11 -0
- package/db/migrations/003-upkeep-settled.sql +15 -0
- package/dist/api/google-read-actions.d.ts +30 -0
- package/dist/api/google-read-actions.d.ts.map +1 -0
- package/dist/api/google-read-actions.js +256 -0
- package/dist/api/google-read-actions.js.map +1 -0
- package/dist/api/record-actions.d.ts.map +1 -1
- package/dist/api/record-actions.js +23 -5
- package/dist/api/record-actions.js.map +1 -1
- package/dist/api/report-handler.d.ts +0 -6
- package/dist/api/report-handler.d.ts.map +1 -1
- package/dist/api/report-handler.js +0 -54
- package/dist/api/report-handler.js.map +1 -1
- package/dist/api/security-events.d.ts +1 -1
- package/dist/api/security-events.d.ts.map +1 -1
- package/dist/api/security-events.js.map +1 -1
- package/dist/api/source-actions.d.ts +9 -0
- package/dist/api/source-actions.d.ts.map +1 -1
- package/dist/api/source-actions.js +49 -0
- package/dist/api/source-actions.js.map +1 -1
- package/dist/api/viewer-request-security.d.ts +14 -1
- package/dist/api/viewer-request-security.d.ts.map +1 -1
- package/dist/api/viewer-request-security.js +26 -3
- package/dist/api/viewer-request-security.js.map +1 -1
- package/dist/api/viewer-server.d.ts +7 -0
- package/dist/api/viewer-server.d.ts.map +1 -1
- package/dist/api/viewer-server.js +32 -0
- package/dist/api/viewer-server.js.map +1 -1
- package/dist/api/work-actions.d.ts +19 -2
- package/dist/api/work-actions.d.ts.map +1 -1
- package/dist/api/work-actions.js +15 -0
- package/dist/api/work-actions.js.map +1 -1
- package/dist/cli/commands/backup.d.ts +7 -6
- package/dist/cli/commands/backup.d.ts.map +1 -1
- package/dist/cli/commands/backup.js +44 -7
- package/dist/cli/commands/backup.js.map +1 -1
- package/dist/cli/commands/control.d.ts +22 -4
- package/dist/cli/commands/control.d.ts.map +1 -1
- package/dist/cli/commands/control.js +172 -11
- package/dist/cli/commands/control.js.map +1 -1
- package/dist/cli/commands/daemon.d.ts +13 -2
- package/dist/cli/commands/daemon.d.ts.map +1 -1
- package/dist/cli/commands/daemon.js +211 -5
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/cli/commands/init-questions.d.ts +98 -0
- package/dist/cli/commands/init-questions.d.ts.map +1 -0
- package/dist/cli/commands/init-questions.js +420 -0
- package/dist/cli/commands/init-questions.js.map +1 -0
- package/dist/cli/commands/init-section.d.ts +13 -0
- package/dist/cli/commands/init-section.d.ts.map +1 -0
- package/dist/cli/commands/init-section.js +375 -0
- package/dist/cli/commands/init-section.js.map +1 -0
- package/dist/cli/commands/init.d.ts +56 -2
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +562 -351
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/node-move.d.ts +20 -0
- package/dist/cli/commands/node-move.d.ts.map +1 -0
- package/dist/cli/commands/node-move.js +289 -0
- package/dist/cli/commands/node-move.js.map +1 -0
- package/dist/cli/commands/register-owner.d.ts +3 -0
- package/dist/cli/commands/register-owner.d.ts.map +1 -1
- package/dist/cli/commands/register-owner.js +2 -0
- package/dist/cli/commands/register-owner.js.map +1 -1
- package/dist/cli/commands/restore.d.ts +2 -0
- package/dist/cli/commands/restore.d.ts.map +1 -1
- package/dist/cli/commands/restore.js +7 -0
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/service.d.ts +16 -0
- package/dist/cli/commands/service.d.ts.map +1 -1
- package/dist/cli/commands/service.js +36 -8
- package/dist/cli/commands/service.js.map +1 -1
- package/dist/cli/commands/tools.d.ts +1 -1
- package/dist/cli/commands/tools.d.ts.map +1 -1
- package/dist/cli/commands/tools.js +8 -3
- package/dist/cli/commands/tools.js.map +1 -1
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.js +78 -5
- package/dist/cli/commands/uninstall.js.map +1 -1
- package/dist/cli/commands/update.d.ts +59 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +948 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/index.js +8 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/launch-files.d.ts +36 -0
- package/dist/cli/launch-files.d.ts.map +1 -1
- package/dist/cli/launch-files.js +94 -1
- package/dist/cli/launch-files.js.map +1 -1
- package/dist/cli/prompt.d.ts +2 -1
- package/dist/cli/prompt.d.ts.map +1 -1
- package/dist/cli/prompt.js +5 -2
- package/dist/cli/prompt.js.map +1 -1
- package/dist/cli/runtime/backup.d.ts +17 -1
- package/dist/cli/runtime/backup.d.ts.map +1 -1
- package/dist/cli/runtime/backup.js +32 -4
- package/dist/cli/runtime/backup.js.map +1 -1
- package/dist/cli/runtime/daemon-control.d.ts +92 -7
- package/dist/cli/runtime/daemon-control.d.ts.map +1 -1
- package/dist/cli/runtime/daemon-control.js +183 -8
- package/dist/cli/runtime/daemon-control.js.map +1 -1
- package/dist/cli/runtime/default-roots.d.ts +27 -0
- package/dist/cli/runtime/default-roots.d.ts.map +1 -0
- package/dist/cli/runtime/default-roots.js +61 -0
- package/dist/cli/runtime/default-roots.js.map +1 -0
- package/dist/cli/runtime/diagnostics.d.ts +25 -0
- package/dist/cli/runtime/diagnostics.d.ts.map +1 -1
- package/dist/cli/runtime/diagnostics.js +249 -63
- package/dist/cli/runtime/diagnostics.js.map +1 -1
- package/dist/cli/runtime/init-state.d.ts +20 -0
- package/dist/cli/runtime/init-state.d.ts.map +1 -0
- package/dist/cli/runtime/init-state.js +51 -0
- package/dist/cli/runtime/init-state.js.map +1 -0
- package/dist/cli/runtime/install-kind.d.ts +54 -0
- package/dist/cli/runtime/install-kind.d.ts.map +1 -0
- package/dist/cli/runtime/install-kind.js +164 -0
- package/dist/cli/runtime/install-kind.js.map +1 -0
- package/dist/cli/runtime/node-move-journal.d.ts +44 -0
- package/dist/cli/runtime/node-move-journal.d.ts.map +1 -0
- package/dist/cli/runtime/node-move-journal.js +48 -0
- package/dist/cli/runtime/node-move-journal.js.map +1 -0
- package/dist/cli/runtime/release-check.d.ts +94 -0
- package/dist/cli/runtime/release-check.d.ts.map +1 -0
- package/dist/cli/runtime/release-check.js +316 -0
- package/dist/cli/runtime/release-check.js.map +1 -0
- package/dist/cli/runtime/setup-page.d.ts +57 -0
- package/dist/cli/runtime/setup-page.d.ts.map +1 -0
- package/dist/cli/runtime/setup-page.js +266 -0
- package/dist/cli/runtime/setup-page.js.map +1 -0
- package/dist/cli/runtime/source-tools.d.ts +60 -0
- package/dist/cli/runtime/source-tools.d.ts.map +1 -0
- package/dist/cli/runtime/source-tools.js +170 -0
- package/dist/cli/runtime/source-tools.js.map +1 -0
- package/dist/cli/runtime/telegram-pairing.d.ts +73 -0
- package/dist/cli/runtime/telegram-pairing.d.ts.map +1 -0
- package/dist/cli/runtime/telegram-pairing.js +184 -0
- package/dist/cli/runtime/telegram-pairing.js.map +1 -0
- package/dist/cli/runtime/update-journal.d.ts +135 -0
- package/dist/cli/runtime/update-journal.d.ts.map +1 -0
- package/dist/cli/runtime/update-journal.js +144 -0
- package/dist/cli/runtime/update-journal.js.map +1 -0
- package/dist/cli/runtime/update-progress.d.ts +95 -0
- package/dist/cli/runtime/update-progress.d.ts.map +1 -0
- package/dist/cli/runtime/update-progress.js +154 -0
- package/dist/cli/runtime/update-progress.js.map +1 -0
- package/dist/cli/runtime/update-request.d.ts +58 -0
- package/dist/cli/runtime/update-request.d.ts.map +1 -0
- package/dist/cli/runtime/update-request.js +172 -0
- package/dist/cli/runtime/update-request.js.map +1 -0
- package/dist/connectors/calendar/index.d.ts +5 -1
- package/dist/connectors/calendar/index.d.ts.map +1 -1
- package/dist/connectors/calendar/index.js +19 -28
- package/dist/connectors/calendar/index.js.map +1 -1
- package/dist/connectors/chatwork/index.d.ts.map +1 -1
- package/dist/connectors/chatwork/index.js +7 -3
- package/dist/connectors/chatwork/index.js.map +1 -1
- package/dist/connectors/config-loader.d.ts +5 -0
- package/dist/connectors/config-loader.d.ts.map +1 -1
- package/dist/connectors/config-loader.js +8 -0
- package/dist/connectors/config-loader.js.map +1 -1
- package/dist/connectors/discord/index.d.ts.map +1 -1
- package/dist/connectors/discord/index.js +4 -3
- package/dist/connectors/discord/index.js.map +1 -1
- package/dist/connectors/drive/index.d.ts.map +1 -1
- package/dist/connectors/drive/index.js +15 -13
- package/dist/connectors/drive/index.js.map +1 -1
- package/dist/connectors/framework/gws-utils.d.ts +62 -0
- package/dist/connectors/framework/gws-utils.d.ts.map +1 -1
- package/dist/connectors/framework/gws-utils.js +133 -3
- package/dist/connectors/framework/gws-utils.js.map +1 -1
- package/dist/connectors/framework/types.d.ts +24 -0
- package/dist/connectors/framework/types.d.ts.map +1 -1
- package/dist/connectors/framework/types.js +9 -0
- package/dist/connectors/framework/types.js.map +1 -1
- package/dist/connectors/gmail/index.d.ts.map +1 -1
- package/dist/connectors/gmail/index.js +14 -13
- package/dist/connectors/gmail/index.js.map +1 -1
- package/dist/connectors/index.d.ts +4 -4
- package/dist/connectors/index.d.ts.map +1 -1
- package/dist/connectors/index.js +4 -10
- package/dist/connectors/index.js.map +1 -1
- package/dist/connectors/notion/index.d.ts.map +1 -1
- package/dist/connectors/notion/index.js +5 -3
- package/dist/connectors/notion/index.js.map +1 -1
- package/dist/connectors/sheets/index.d.ts.map +1 -1
- package/dist/connectors/sheets/index.js +17 -12
- package/dist/connectors/sheets/index.js.map +1 -1
- package/dist/connectors/slack/index.d.ts.map +1 -1
- package/dist/connectors/slack/index.js +9 -3
- package/dist/connectors/slack/index.js.map +1 -1
- package/dist/connectors/telegram/index.d.ts.map +1 -1
- package/dist/connectors/telegram/index.js +4 -3
- package/dist/connectors/telegram/index.js.map +1 -1
- package/dist/connectors/trello/index.d.ts +1 -1
- package/dist/connectors/trello/index.d.ts.map +1 -1
- package/dist/connectors/trello/index.js +10 -5
- package/dist/connectors/trello/index.js.map +1 -1
- package/dist/gateways/discord.d.ts +6 -0
- package/dist/gateways/discord.d.ts.map +1 -1
- package/dist/gateways/discord.js +38 -27
- package/dist/gateways/discord.js.map +1 -1
- package/dist/gateways/slack.d.ts +6 -0
- package/dist/gateways/slack.d.ts.map +1 -1
- package/dist/gateways/slack.js +38 -27
- package/dist/gateways/slack.js.map +1 -1
- package/dist/gateways/telegram-commands.d.ts +124 -0
- package/dist/gateways/telegram-commands.d.ts.map +1 -0
- package/dist/gateways/telegram-commands.js +131 -0
- package/dist/gateways/telegram-commands.js.map +1 -0
- package/dist/gateways/telegram.d.ts +20 -0
- package/dist/gateways/telegram.d.ts.map +1 -1
- package/dist/gateways/telegram.js +138 -34
- package/dist/gateways/telegram.js.map +1 -1
- package/dist/gateways/turn-contract.d.ts +11 -0
- package/dist/gateways/turn-contract.d.ts.map +1 -1
- package/dist/runtime/action-surface.d.ts +1 -1
- package/dist/runtime/action-surface.d.ts.map +1 -1
- package/dist/runtime/action-surface.js +10 -0
- package/dist/runtime/action-surface.js.map +1 -1
- package/dist/runtime/backend-security.d.ts +23 -2
- package/dist/runtime/backend-security.d.ts.map +1 -1
- package/dist/runtime/backend-security.js +50 -5
- package/dist/runtime/backend-security.js.map +1 -1
- package/dist/runtime/member-paths.d.ts +15 -7
- package/dist/runtime/member-paths.d.ts.map +1 -1
- package/dist/runtime/member-paths.js +64 -12
- package/dist/runtime/member-paths.js.map +1 -1
- package/dist/runtime/member-session.d.ts +4 -0
- package/dist/runtime/member-session.d.ts.map +1 -1
- package/dist/runtime/member-session.js +23 -2
- package/dist/runtime/member-session.js.map +1 -1
- package/dist/runtime/native-session.d.ts +2 -0
- package/dist/runtime/native-session.d.ts.map +1 -1
- package/dist/runtime/native-session.js +1 -0
- package/dist/runtime/native-session.js.map +1 -1
- package/dist/runtime/owner-runtime.d.ts +63 -1
- package/dist/runtime/owner-runtime.d.ts.map +1 -1
- package/dist/runtime/owner-runtime.js +180 -3
- package/dist/runtime/owner-runtime.js.map +1 -1
- package/dist/runtime/owner-system-prompt.d.ts.map +1 -1
- package/dist/runtime/owner-system-prompt.js +0 -1
- package/dist/runtime/owner-system-prompt.js.map +1 -1
- package/dist/runtime/principal-access.d.ts +2 -0
- package/dist/runtime/principal-access.d.ts.map +1 -1
- package/dist/runtime/principal-access.js +7 -0
- package/dist/runtime/principal-access.js.map +1 -1
- package/dist/runtime/principal-sessions.d.ts.map +1 -1
- package/dist/runtime/principal-sessions.js +8 -1
- package/dist/runtime/principal-sessions.js.map +1 -1
- package/dist/runtime/record-orders.d.ts.map +1 -1
- package/dist/runtime/record-orders.js +3 -29
- package/dist/runtime/record-orders.js.map +1 -1
- package/dist/runtime/report-scheduler.d.ts +9 -2
- package/dist/runtime/report-scheduler.d.ts.map +1 -1
- package/dist/runtime/report-scheduler.js +37 -10
- package/dist/runtime/report-scheduler.js.map +1 -1
- package/dist/runtime/stimulus-delivery.d.ts +3 -0
- package/dist/runtime/stimulus-delivery.d.ts.map +1 -1
- package/dist/runtime/stimulus-delivery.js +19 -3
- package/dist/runtime/stimulus-delivery.js.map +1 -1
- package/dist/runtime/tools-paths.d.ts +7 -0
- package/dist/runtime/tools-paths.d.ts.map +1 -1
- package/dist/runtime/tools-paths.js +11 -5
- package/dist/runtime/tools-paths.js.map +1 -1
- package/dist/runtime/upkeep-close.d.ts +17 -0
- package/dist/runtime/upkeep-close.d.ts.map +1 -0
- package/dist/runtime/upkeep-close.js +127 -0
- package/dist/runtime/upkeep-close.js.map +1 -0
- package/dist/runtime/upkeep-orders.d.ts +124 -0
- package/dist/runtime/upkeep-orders.d.ts.map +1 -0
- package/dist/runtime/upkeep-orders.js +310 -0
- package/dist/runtime/upkeep-orders.js.map +1 -0
- package/dist/runtime/upkeep-reconcile.d.ts +25 -0
- package/dist/runtime/upkeep-reconcile.d.ts.map +1 -0
- package/dist/runtime/upkeep-reconcile.js +231 -0
- package/dist/runtime/upkeep-reconcile.js.map +1 -0
- package/dist/runtime/upkeep-writeback.d.ts +22 -0
- package/dist/runtime/upkeep-writeback.d.ts.map +1 -0
- package/dist/runtime/upkeep-writeback.js +203 -0
- package/dist/runtime/upkeep-writeback.js.map +1 -0
- package/dist/utils/untrusted-content.d.ts.map +1 -1
- package/dist/utils/untrusted-content.js +8 -1
- package/dist/utils/untrusted-content.js.map +1 -1
- package/install/install.sh +457 -0
- package/install/node.json +9 -0
- package/package.json +3 -4
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultRoots = defaultRoots;
|
|
4
|
+
exports.prepareRoot = prepareRoot;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_os_1 = require("node:os");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const prompt_js_1 = require("../prompt.js");
|
|
9
|
+
/**
|
|
10
|
+
* Where a new install keeps its member folders and its document tools: outside HOME, one place
|
|
11
|
+
* per person on the machine (plan decision 3). On macOS a folder of this user's sits directly in
|
|
12
|
+
* the sticky Shared folder beside the home folders, so no account uses a parent another set up;
|
|
13
|
+
* on Linux it is /var/lib/mama/<user>, which the installer creates once with sudo.
|
|
14
|
+
*/
|
|
15
|
+
function defaultRoots(options = {}) {
|
|
16
|
+
const platform = options.platform ?? process.platform;
|
|
17
|
+
const user = options.user ?? (0, node_os_1.userInfo)().username;
|
|
18
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(user))
|
|
19
|
+
return undefined;
|
|
20
|
+
const base = platform === 'darwin'
|
|
21
|
+
? (0, node_path_1.join)((0, node_path_1.dirname)(options.home ?? (0, node_os_1.homedir)()), 'Shared', `mama-${user}`)
|
|
22
|
+
: platform === 'linux'
|
|
23
|
+
? (0, node_path_1.join)('/var/lib/mama', user)
|
|
24
|
+
: undefined;
|
|
25
|
+
return base === undefined
|
|
26
|
+
? undefined
|
|
27
|
+
: { memberRoot: (0, node_path_1.join)(base, 'members'), toolsRoot: (0, node_path_1.join)(base, 'tools') };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Make a root that this user alone owns and writes, or refuse one that is not: the agent runs
|
|
31
|
+
* what tools_root holds and reads what member_root holds, and the Shared folder lets any account
|
|
32
|
+
* create a folder first. `ownParent` also checks the per-user folder a default sits in. A root
|
|
33
|
+
* this account cannot create (Linux's /var/lib/mama) names the one sudo step that makes its
|
|
34
|
+
* per-user folder; the subfolders are made here.
|
|
35
|
+
*/
|
|
36
|
+
function prepareRoot(path, options = {}) {
|
|
37
|
+
const uid = options.uid ?? process.getuid?.();
|
|
38
|
+
if (!(0, node_fs_1.existsSync)(path)) {
|
|
39
|
+
try {
|
|
40
|
+
(0, node_fs_1.mkdirSync)(path, { recursive: true, mode: 0o700 });
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const code = error.code;
|
|
44
|
+
if (code !== 'EACCES' && code !== 'EPERM' && code !== 'EROFS')
|
|
45
|
+
throw error;
|
|
46
|
+
const folder = options.ownParent ? (0, node_path_1.dirname)(path) : path;
|
|
47
|
+
throw new prompt_js_1.CliInputError(`${path} cannot be created. Create ${folder} for this account once: sudo install -d -o "$USER" -m 0700 ${folder}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
for (const folder of options.ownParent ? [(0, node_path_1.dirname)(path), path] : [path]) {
|
|
51
|
+
const stat = (0, node_fs_1.lstatSync)(folder);
|
|
52
|
+
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
53
|
+
throw new prompt_js_1.CliInputError(`${folder} must be a folder, not a link or a file`);
|
|
54
|
+
if (uid !== undefined && stat.uid !== uid)
|
|
55
|
+
throw new prompt_js_1.CliInputError(`${folder} belongs to another account; choose another folder`);
|
|
56
|
+
if ((stat.mode & 0o022) !== 0)
|
|
57
|
+
throw new prompt_js_1.CliInputError(`${folder} can be written by other accounts; run chmod 700 on it`);
|
|
58
|
+
}
|
|
59
|
+
(0, node_fs_1.accessSync)(path, node_fs_1.constants.W_OK);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=default-roots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-roots.js","sourceRoot":"","sources":["../../../src/cli/runtime/default-roots.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,12 @@ export interface Check {
|
|
|
12
12
|
readonly context?: string;
|
|
13
13
|
/** What to do about a warn or fail. */
|
|
14
14
|
readonly fix?: string;
|
|
15
|
+
/**
|
|
16
|
+
* A stable name for this finding where its detail carries values that an update or a backend
|
|
17
|
+
* self-update changes (versions, schema numbers). A check without one is the same finding
|
|
18
|
+
* while its name and detail are; `mama update` compares failures before and after by these.
|
|
19
|
+
*/
|
|
20
|
+
readonly code?: string;
|
|
15
21
|
}
|
|
16
22
|
export interface DiagnosticsOptions {
|
|
17
23
|
home?: string;
|
|
@@ -24,6 +30,8 @@ export interface DiagnosticsOptions {
|
|
|
24
30
|
/** A Telegram Bot API call; tests replace it. */
|
|
25
31
|
telegramCall?: (token: string, method: string, params?: Record<string, string>) => Promise<Record<string, unknown>>;
|
|
26
32
|
findIn?: (name: string, dirs: string[]) => string | undefined;
|
|
33
|
+
/** Where this shell finds a command; tests replace it. */
|
|
34
|
+
findExecutable?: (name: string) => string | undefined;
|
|
27
35
|
/** Ask the install's daemon for its status; tests replace it. */
|
|
28
36
|
askStatus?: () => Promise<DaemonControlReply>;
|
|
29
37
|
/** Builds a source as boot does; tests replace it so no source reaches the network. */
|
|
@@ -33,6 +41,12 @@ export interface DiagnosticsOptions {
|
|
|
33
41
|
/** Whether something listens on the viewer's address; tests replace it. */
|
|
34
42
|
portInUse?: (port: number, host: string) => Promise<boolean>;
|
|
35
43
|
}
|
|
44
|
+
/** auth.env's assignments, unquoted as sh reads them; values are never printed. */
|
|
45
|
+
export declare function readAuthEnv(root: string): Record<string, string>;
|
|
46
|
+
export declare function defaultTelegramCall(token: string, method: string, params?: Record<string, string>, timeoutMs?: number): Promise<Record<string, unknown>>;
|
|
47
|
+
/** True when something listens; a refusal means free; any other error (a host that cannot be
|
|
48
|
+
* reached or bound) rejects, since the viewer would fail on it too. */
|
|
49
|
+
export declare function portAnswers(port: number, host: string): Promise<boolean>;
|
|
36
50
|
/**
|
|
37
51
|
* Check an install as its service would run it. Nothing here writes MAMA's files or starts a
|
|
38
52
|
* service; the database is opened read-only (which can leave its -wal and -shm beside it), and the
|
|
@@ -40,4 +54,15 @@ export interface DiagnosticsOptions {
|
|
|
40
54
|
* Each check names what it found and, when it is not ok, what to do.
|
|
41
55
|
*/
|
|
42
56
|
export declare function runDiagnostics(options?: DiagnosticsOptions): Promise<Check[]>;
|
|
57
|
+
/**
|
|
58
|
+
* start.sh's Node: still there, outside one version's folder, and able to load MAMA's SQLite. On
|
|
59
|
+
* an install the install command made (its Node in `<root>/node`), also the Node the installed
|
|
60
|
+
* release pins in its install/node.json: running the install command again moves to that one.
|
|
61
|
+
*/
|
|
62
|
+
export declare function nodeCheck(node: string, cli: string, run: ProbeRun, root: string): Check;
|
|
63
|
+
export declare function telegramCheck(token: string | undefined, commonChat: string | number | undefined, call: NonNullable<DiagnosticsOptions['telegramCall']>): Promise<Check>;
|
|
64
|
+
/** The environment start.sh gives the daemon: auth.env, then its own exports, then its PATH. */
|
|
65
|
+
export declare function serviceEnvironment(home: string, auth: Record<string, string>, exports: Record<string, string>, path: readonly string[]): NodeJS.ProcessEnv;
|
|
66
|
+
/** Run with process.env as the daemon's process has it, then put this shell's back. */
|
|
67
|
+
export declare function withEnvironment<T>(env: NodeJS.ProcessEnv, run: () => Promise<T>): Promise<T>;
|
|
43
68
|
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../src/cli/runtime/diagnostics.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../src/cli/runtime/diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readAuthEnv = readAuthEnv;
|
|
4
|
+
exports.defaultTelegramCall = defaultTelegramCall;
|
|
5
|
+
exports.portAnswers = portAnswers;
|
|
3
6
|
exports.runDiagnostics = runDiagnostics;
|
|
7
|
+
exports.nodeCheck = nodeCheck;
|
|
8
|
+
exports.telegramCheck = telegramCheck;
|
|
9
|
+
exports.serviceEnvironment = serviceEnvironment;
|
|
10
|
+
exports.withEnvironment = withEnvironment;
|
|
4
11
|
const node_fs_1 = require("node:fs");
|
|
5
12
|
const node_module_1 = require("node:module");
|
|
6
13
|
const node_net_1 = require("node:net");
|
|
@@ -15,28 +22,19 @@ const timezone_js_1 = require("../../runtime/timezone.js");
|
|
|
15
22
|
const document_toolkit_js_1 = require("../../tools/document-toolkit.js");
|
|
16
23
|
const launch_files_js_1 = require("../launch-files.js");
|
|
17
24
|
const rotating_log_js_1 = require("../../runtime/rotating-log.js");
|
|
18
|
-
const secrets_js_1 = require("../secrets.js");
|
|
19
25
|
const daemon_js_1 = require("../commands/daemon.js");
|
|
20
26
|
const backend_probe_js_1 = require("./backend-probe.js");
|
|
21
27
|
const daemon_control_js_1 = require("./daemon-control.js");
|
|
28
|
+
const release_check_js_1 = require("./release-check.js");
|
|
29
|
+
const install_kind_js_1 = require("./install-kind.js");
|
|
30
|
+
const source_tools_js_1 = require("./source-tools.js");
|
|
31
|
+
const node_move_journal_js_1 = require("./node-move-journal.js");
|
|
32
|
+
const update_journal_js_1 = require("./update-journal.js");
|
|
22
33
|
const db_manager_1 = require("@jungjaehoon/mama-core/db-manager");
|
|
23
34
|
const migrations_source_js_1 = require("../../storage/migrations-source.js");
|
|
24
35
|
const systemd_service_js_1 = require("./systemd-service.js");
|
|
25
|
-
/** The PATH a service manager gives a unit that does not set one ($PATH in start.sh). */
|
|
26
|
-
const SERVICE_DEFAULT_PATH = {
|
|
27
|
-
darwin: ['/usr/bin', '/bin', '/usr/sbin', '/sbin'],
|
|
28
|
-
linux: ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', '/sbin', '/bin'],
|
|
29
|
-
};
|
|
30
36
|
/** systemd states of an installed unit that can be started or is running. */
|
|
31
37
|
const SYSTEMD_USABLE = new Set(['active', 'inactive', 'activating', 'deactivating', 'reloading']);
|
|
32
|
-
function findIn(name, dirs) {
|
|
33
|
-
for (const dir of dirs) {
|
|
34
|
-
const path = (0, node_path_1.join)(dir, name);
|
|
35
|
-
if ((0, node_fs_1.existsSync)(path))
|
|
36
|
-
return path;
|
|
37
|
-
}
|
|
38
|
-
return undefined;
|
|
39
|
-
}
|
|
40
38
|
function message(error) {
|
|
41
39
|
return error instanceof Error ? error.message : String(error);
|
|
42
40
|
}
|
|
@@ -64,9 +62,9 @@ function readAuthEnv(root) {
|
|
|
64
62
|
});
|
|
65
63
|
return values;
|
|
66
64
|
}
|
|
67
|
-
async function defaultTelegramCall(token, method, params = {}) {
|
|
65
|
+
async function defaultTelegramCall(token, method, params = {}, timeoutMs = 8_000) {
|
|
68
66
|
const query = new URLSearchParams(params).toString();
|
|
69
|
-
const response = await fetch(`https://api.telegram.org/bot${token}/${method}${query ? `?${query}` : ''}`, { signal: AbortSignal.timeout(
|
|
67
|
+
const response = await fetch(`https://api.telegram.org/bot${token}/${method}${query ? `?${query}` : ''}`, { signal: AbortSignal.timeout(timeoutMs) });
|
|
70
68
|
return (await response.json());
|
|
71
69
|
}
|
|
72
70
|
/** True when something listens; a refusal means free; any other error (a host that cannot be
|
|
@@ -85,10 +83,17 @@ function portAnswers(port, host) {
|
|
|
85
83
|
socket.once('error', (error) => error.code === 'ECONNREFUSED' ? resolve(false) : reject(error));
|
|
86
84
|
});
|
|
87
85
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
/**
|
|
87
|
+
* A source's tokens are entered on the setup page by the sources section, run again for that
|
|
88
|
+
* source, which needs no terminal (install.md, W2.4.5e). Every token source is built only with
|
|
89
|
+
* the token name it reads, which auth.env holds.
|
|
90
|
+
*/
|
|
91
|
+
function sourceSecretFixes(source, names, mama) {
|
|
92
|
+
return names.length === 0
|
|
93
|
+
? []
|
|
94
|
+
: [
|
|
95
|
+
`with MAMA stopped, run ${mama} init --section connectors --non-interactive with ${source}'s block from connectors.json in MAMA_INIT_CONNECTORS; its setup page takes ${names.join(' and ')}`,
|
|
96
|
+
];
|
|
92
97
|
}
|
|
93
98
|
/**
|
|
94
99
|
* Check an install as its service would run it. Nothing here writes MAMA's files or starts a
|
|
@@ -102,7 +107,7 @@ async function runDiagnostics(options = {}) {
|
|
|
102
107
|
const root = (0, node_path_1.dirname)(configPath);
|
|
103
108
|
const platform = options.platform ?? process.platform;
|
|
104
109
|
const run = options.run ?? backend_probe_js_1.defaultProbeRun;
|
|
105
|
-
const locate = options.findIn ?? findIn;
|
|
110
|
+
const locate = options.findIn ?? launch_files_js_1.findIn;
|
|
106
111
|
const checks = [];
|
|
107
112
|
if ((0, node_fs_1.existsSync)((0, daemon_control_js_1.restoreJournalPath)(root))) {
|
|
108
113
|
checks.push({
|
|
@@ -112,6 +117,7 @@ async function runDiagnostics(options = {}) {
|
|
|
112
117
|
fix: 'mama restore --rollback',
|
|
113
118
|
});
|
|
114
119
|
}
|
|
120
|
+
checks.push(...updateChecks(root, home));
|
|
115
121
|
let config = null;
|
|
116
122
|
// Setting names can be anything the owner typed, so they stay out of the report.
|
|
117
123
|
let ignored = [];
|
|
@@ -149,7 +155,10 @@ async function runDiagnostics(options = {}) {
|
|
|
149
155
|
}
|
|
150
156
|
// What the service runs: the start script's Node, PATH and exports, not this shell's.
|
|
151
157
|
const startPath = (0, node_path_1.join)(root, 'start.sh');
|
|
152
|
-
let servicePath =
|
|
158
|
+
let servicePath = (0, launch_files_js_1.startScriptPath)(null, home, platform);
|
|
159
|
+
// The Node start.sh runs: on an install the install command made, a source's tool installs
|
|
160
|
+
// beside MAMA with that Node (install.md, PR 3).
|
|
161
|
+
let serviceNode = null;
|
|
153
162
|
let exports = {};
|
|
154
163
|
// A script mama did not write is assumed to load auth.env; a generated one must still.
|
|
155
164
|
let loadsAuth = true;
|
|
@@ -186,13 +195,9 @@ async function runDiagnostics(options = {}) {
|
|
|
186
195
|
fix: 'mama service install --replace rewrites it',
|
|
187
196
|
});
|
|
188
197
|
}
|
|
189
|
-
|
|
190
|
-
servicePath = [
|
|
191
|
-
...(0, launch_files_js_1.startPathValue)(reading.path, home),
|
|
192
|
-
...(/\$\{?PATH\}?/.test(reading.path) ? servicePath : []),
|
|
193
|
-
];
|
|
194
|
-
}
|
|
198
|
+
servicePath = (0, launch_files_js_1.startScriptPath)(reading, home, platform);
|
|
195
199
|
const [, node, cli] = reading.exec === null ? [] : (0, launch_files_js_1.shellWords)(reading.exec);
|
|
200
|
+
serviceNode = node ?? null;
|
|
196
201
|
if (!reading.generated) {
|
|
197
202
|
checks.push({
|
|
198
203
|
name: 'start.sh',
|
|
@@ -210,7 +215,7 @@ async function runDiagnostics(options = {}) {
|
|
|
210
215
|
});
|
|
211
216
|
}
|
|
212
217
|
else {
|
|
213
|
-
checks.push(nodeCheck(node, cli, run));
|
|
218
|
+
checks.push(nodeCheck(node, cli, run, root));
|
|
214
219
|
}
|
|
215
220
|
}
|
|
216
221
|
catch (error) {
|
|
@@ -238,14 +243,7 @@ async function runDiagnostics(options = {}) {
|
|
|
238
243
|
fix: `correct the quoting in ${(0, node_path_1.join)(root, 'auth.env')}`,
|
|
239
244
|
});
|
|
240
245
|
}
|
|
241
|
-
const serviceEnv =
|
|
242
|
-
HOME: home,
|
|
243
|
-
USER: process.env.USER,
|
|
244
|
-
LOGNAME: process.env.LOGNAME,
|
|
245
|
-
...auth,
|
|
246
|
-
...exports,
|
|
247
|
-
PATH: servicePath.join(':'),
|
|
248
|
-
};
|
|
246
|
+
const serviceEnv = serviceEnvironment(home, auth, exports, servicePath);
|
|
249
247
|
const secret = (name) => Boolean(serviceEnv[name]?.trim());
|
|
250
248
|
if (config) {
|
|
251
249
|
const backend = config.agent.backend;
|
|
@@ -268,6 +266,7 @@ async function runDiagnostics(options = {}) {
|
|
|
268
266
|
name: 'backend',
|
|
269
267
|
status: 'fail',
|
|
270
268
|
detail: probe.problem ?? `${backend} ${probe.version} is older than ${probe.minimum}`,
|
|
269
|
+
...(probe.problem === null ? { code: 'backend.too_old' } : {}),
|
|
271
270
|
fix: `update ${backend} to ${probe.minimum} or newer`,
|
|
272
271
|
});
|
|
273
272
|
}
|
|
@@ -276,6 +275,7 @@ async function runDiagnostics(options = {}) {
|
|
|
276
275
|
name: 'backend',
|
|
277
276
|
status: 'fail',
|
|
278
277
|
detail: `${backend} ${probe.version} is not signed in for the service`,
|
|
278
|
+
code: 'backend.signed_out',
|
|
279
279
|
fix: backend === 'claude' ? 'claude auth login' : `CODEX_HOME='${codexHome}' codex login`,
|
|
280
280
|
});
|
|
281
281
|
}
|
|
@@ -299,7 +299,7 @@ async function runDiagnostics(options = {}) {
|
|
|
299
299
|
name: messenger,
|
|
300
300
|
status: 'fail',
|
|
301
301
|
detail: `${missing.join(' and ')} not set; boot stops at the messengers stage`,
|
|
302
|
-
fix: missing.map(
|
|
302
|
+
fix: missing.map((name) => `mama secret set ${name}`).join('; '),
|
|
303
303
|
});
|
|
304
304
|
}
|
|
305
305
|
else if (messenger === 'telegram' && !options.offline) {
|
|
@@ -309,7 +309,10 @@ async function runDiagnostics(options = {}) {
|
|
|
309
309
|
checks.push({ name: messenger, status: 'ok', detail: 'secrets set' });
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
|
-
checks.push(...(await sourceChecks(config, configPath,
|
|
312
|
+
checks.push(...(await sourceChecks(config, configPath, locate, secret, {
|
|
313
|
+
service: { path: servicePath, nodePath: serviceNode, exports },
|
|
314
|
+
findShell: options.findExecutable ?? launch_files_js_1.findExecutable,
|
|
315
|
+
home,
|
|
313
316
|
env: serviceEnv,
|
|
314
317
|
online: !options.offline,
|
|
315
318
|
load: options.loadSource ?? index_js_1.loadConnector,
|
|
@@ -332,6 +335,7 @@ async function runDiagnostics(options = {}) {
|
|
|
332
335
|
}
|
|
333
336
|
checks.push(...(await daemonChecks(options.askStatus ?? (() => (0, daemon_js_1.askDaemon)('status', { home, configPath })), port, serviceEnv.MAMA_API_HOST ?? '127.0.0.1', options.portInUse ?? portAnswers)));
|
|
334
337
|
checks.push(serviceCheck(platform, home, options.serviceRun ?? systemd_service_js_1.defaultServiceRun));
|
|
338
|
+
checks.push(releaseCheck(root, home));
|
|
335
339
|
// Each log against its own cap: the daemon rotates daemon.log and security-events.jsonl before
|
|
336
340
|
// they pass theirs, and start.sh empties crash.log at start past its own.
|
|
337
341
|
for (const [name, path, cap] of [
|
|
@@ -416,6 +420,7 @@ function schemaCheck(databasePath) {
|
|
|
416
420
|
name: 'schema',
|
|
417
421
|
status: 'fail',
|
|
418
422
|
detail: `the database is newer than this MAMA (${summary}); boot refuses it`,
|
|
423
|
+
code: 'schema.newer',
|
|
419
424
|
fix: 'install the version that wrote it, or mama restore a backup taken with this one',
|
|
420
425
|
};
|
|
421
426
|
}
|
|
@@ -436,8 +441,12 @@ function schemaCheck(databasePath) {
|
|
|
436
441
|
};
|
|
437
442
|
}
|
|
438
443
|
}
|
|
439
|
-
/**
|
|
440
|
-
|
|
444
|
+
/**
|
|
445
|
+
* start.sh's Node: still there, outside one version's folder, and able to load MAMA's SQLite. On
|
|
446
|
+
* an install the install command made (its Node in `<root>/node`), also the Node the installed
|
|
447
|
+
* release pins in its install/node.json: running the install command again moves to that one.
|
|
448
|
+
*/
|
|
449
|
+
function nodeCheck(node, cli, run, root) {
|
|
441
450
|
const rewrite = 'mama service install rewrites start.sh with a Node path that survives upgrades';
|
|
442
451
|
if (!(0, node_fs_1.existsSync)(node)) {
|
|
443
452
|
return {
|
|
@@ -497,6 +506,29 @@ function nodeCheck(node, cli, run) {
|
|
|
497
506
|
: 'run mama service install from a shell whose node is not an nvm, volta or fnm version',
|
|
498
507
|
};
|
|
499
508
|
}
|
|
509
|
+
if (node === (0, node_move_journal_js_1.managedNodePath)(root)) {
|
|
510
|
+
const packageRoot = (0, install_kind_js_1.packageRootOf)(cli);
|
|
511
|
+
if (packageRoot === null) {
|
|
512
|
+
return {
|
|
513
|
+
name: 'node',
|
|
514
|
+
status: 'fail',
|
|
515
|
+
detail: 'the MAMA command start.sh runs is not inside a MAMA OS package',
|
|
516
|
+
context: cli,
|
|
517
|
+
fix: 'run the install command again',
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
const pin = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(packageRoot, 'install', 'node.json'), 'utf8')).version;
|
|
521
|
+
if (version !== `v${pin}`) {
|
|
522
|
+
return {
|
|
523
|
+
name: 'node',
|
|
524
|
+
status: 'warn',
|
|
525
|
+
detail: `start.sh runs ${version}; this release pins Node.js ${pin}`,
|
|
526
|
+
code: 'node.pin',
|
|
527
|
+
context: node,
|
|
528
|
+
fix: `run the install command again, which moves it: ${node_move_journal_js_1.INSTALL_COMMAND}`,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
}
|
|
500
532
|
return { name: 'node', status: 'ok', detail: `${version} loads SQLite`, context: node };
|
|
501
533
|
}
|
|
502
534
|
function sandboxCheck(platform, servicePath, locate, run) {
|
|
@@ -619,8 +651,12 @@ async function telegramCheck(token, commonChat, call) {
|
|
|
619
651
|
: 'token valid; a member of the common group that reads its messages',
|
|
620
652
|
};
|
|
621
653
|
}
|
|
654
|
+
/** The secrets a source's requirements name. */
|
|
655
|
+
function secretNames(needs) {
|
|
656
|
+
return needs.flatMap((need) => need.type === 'token' && need.tokenName !== undefined ? [need.tokenName] : []);
|
|
657
|
+
}
|
|
622
658
|
/** connectors.json as the connector runtime reads it, and what each enabled source needs. */
|
|
623
|
-
async function sourceChecks(config, configPath,
|
|
659
|
+
async function sourceChecks(config, configPath, locate, secret, start) {
|
|
624
660
|
const paths = (0, daemon_js_1.pathsFor)(configPath, config);
|
|
625
661
|
let plan;
|
|
626
662
|
try {
|
|
@@ -646,14 +682,17 @@ async function sourceChecks(config, configPath, servicePath, locate, secret, sta
|
|
|
646
682
|
}
|
|
647
683
|
const checks = [];
|
|
648
684
|
const timeZone = (0, timezone_js_1.createTimeZoneSetting)(config.timezone);
|
|
685
|
+
const loaded = [];
|
|
649
686
|
for (const name of plan.enabledConnectorNames) {
|
|
650
|
-
let connector;
|
|
651
687
|
try {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
688
|
+
loaded.push({
|
|
689
|
+
name,
|
|
690
|
+
connector: await start.load(name, plan.config.config[name], (0, connectors_js_1.connectorLoadPaths)(name, {
|
|
691
|
+
statePath: paths.connectorsRoot,
|
|
692
|
+
kagemushaDbPath: paths.kagemushaDbPath,
|
|
693
|
+
timeZone,
|
|
694
|
+
})),
|
|
695
|
+
});
|
|
657
696
|
}
|
|
658
697
|
catch (error) {
|
|
659
698
|
checks.push({
|
|
@@ -662,26 +701,39 @@ async function sourceChecks(config, configPath, servicePath, locate, secret, sta
|
|
|
662
701
|
detail: 'cannot be built from connectors.json; boot stops at the connectors stage',
|
|
663
702
|
context: message(error),
|
|
664
703
|
});
|
|
665
|
-
continue;
|
|
666
704
|
}
|
|
667
|
-
|
|
705
|
+
}
|
|
706
|
+
const enabled = loaded.map(({ name, connector }) => ({
|
|
707
|
+
name,
|
|
708
|
+
connector,
|
|
709
|
+
needs: connector.getAuthRequirements(),
|
|
710
|
+
}));
|
|
711
|
+
for (const { name, connector, needs } of enabled) {
|
|
668
712
|
// A secret's name can carry an owner's channel key (iCal), so it stays out of the report.
|
|
669
|
-
const secrets = needs.
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
713
|
+
const secrets = secretNames(needs).filter((tokenName) => !secret(tokenName));
|
|
714
|
+
const tools = (0, source_tools_js_1.sourceTools)([{ name, needs }], start.service, { root: (0, node_path_1.dirname)(configPath), home: start.home }, { inDirs: locate, shell: start.findShell },
|
|
715
|
+
// One login of a tool serves every source that runs it, so it names what all of them need.
|
|
716
|
+
enabled);
|
|
717
|
+
const missing = tools.filter((tool) => tool.servicePath === null);
|
|
718
|
+
// Paths stay out of `detail`, which --report shares.
|
|
719
|
+
const context = [
|
|
720
|
+
...(secrets.length > 0 ? [secrets.join(', ')] : []),
|
|
721
|
+
...missing.flatMap(({ tool, shellPath }) => shellPath === null ? [] : [`this shell finds ${tool.command} at ${shellPath}`]),
|
|
722
|
+
];
|
|
723
|
+
if (secrets.length > 0 || missing.length > 0) {
|
|
674
724
|
checks.push({
|
|
675
725
|
name: `source ${name}`,
|
|
676
726
|
status: 'fail',
|
|
677
727
|
detail: [
|
|
678
728
|
...(secrets.length > 0 ? [`${secrets.length} secret(s) it needs are not set`] : []),
|
|
679
|
-
...
|
|
729
|
+
...missing.map(({ tool }) => `the ${tool.command} command is not on the service's PATH`),
|
|
680
730
|
].join('; '),
|
|
681
|
-
...(
|
|
731
|
+
...(context.length > 0 ? { context: context.join('; ') } : {}),
|
|
682
732
|
fix: [
|
|
683
|
-
...secrets.
|
|
684
|
-
...
|
|
733
|
+
...sourceSecretFixes(name, secrets, (0, launch_files_js_1.mamaCommand)((0, node_path_1.dirname)(configPath))),
|
|
734
|
+
...missing.map(({ shellPath, install, login }) => shellPath === null
|
|
735
|
+
? `install it: ${install.join(' or ')}; then log in: ${login}`
|
|
736
|
+
: `mama service install adds ${(0, node_path_1.dirname)(shellPath)} to start.sh's PATH, mama service restart applies it; then log in: ${login}`),
|
|
685
737
|
].join('; '),
|
|
686
738
|
});
|
|
687
739
|
continue;
|
|
@@ -702,6 +754,9 @@ async function sourceChecks(config, configPath, servicePath, locate, secret, sta
|
|
|
702
754
|
status: 'fail',
|
|
703
755
|
detail: 'does not start; boot stops at the connectors stage',
|
|
704
756
|
context: message(error),
|
|
757
|
+
// The tool is on the service's PATH here, so a source that runs one most often
|
|
758
|
+
// lacks its sign-in or a scope (Calendar's read check).
|
|
759
|
+
...(tools.length > 0 ? { fix: tools.map(({ login }) => login).join('; ') } : {}),
|
|
705
760
|
};
|
|
706
761
|
return;
|
|
707
762
|
}
|
|
@@ -710,10 +765,10 @@ async function sourceChecks(config, configPath, servicePath, locate, secret, sta
|
|
|
710
765
|
name: `source ${name}`,
|
|
711
766
|
status: 'fail',
|
|
712
767
|
detail: 'starts, but its credentials or sign-in are refused, so its polls fail',
|
|
713
|
-
fix:
|
|
714
|
-
.map((
|
|
715
|
-
.
|
|
716
|
-
|
|
768
|
+
fix: [
|
|
769
|
+
...tools.map(({ login }) => login),
|
|
770
|
+
...sourceSecretFixes(name, secretNames(needs), (0, launch_files_js_1.mamaCommand)((0, node_path_1.dirname)(configPath))),
|
|
771
|
+
].join('; ') || undefined,
|
|
717
772
|
};
|
|
718
773
|
}
|
|
719
774
|
}));
|
|
@@ -745,6 +800,17 @@ function bounded(ms, run) {
|
|
|
745
800
|
}),
|
|
746
801
|
]).finally(() => clearTimeout(timer));
|
|
747
802
|
}
|
|
803
|
+
/** The environment start.sh gives the daemon: auth.env, then its own exports, then its PATH. */
|
|
804
|
+
function serviceEnvironment(home, auth, exports, path) {
|
|
805
|
+
return {
|
|
806
|
+
HOME: home,
|
|
807
|
+
USER: process.env.USER,
|
|
808
|
+
LOGNAME: process.env.LOGNAME,
|
|
809
|
+
...auth,
|
|
810
|
+
...exports,
|
|
811
|
+
PATH: path.join(':'),
|
|
812
|
+
};
|
|
813
|
+
}
|
|
748
814
|
/** Run with process.env as the daemon's process has it, then put this shell's back. */
|
|
749
815
|
async function withEnvironment(env, run) {
|
|
750
816
|
const saved = { ...process.env };
|
|
@@ -903,6 +969,126 @@ async function daemonChecks(ask, port, host, portInUse) {
|
|
|
903
969
|
}
|
|
904
970
|
return checks;
|
|
905
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* An unfinished `mama update --node` (docs/development/work/install.md, "Moving the managed
|
|
974
|
+
* Node"): its journal, which the install command finishes or undoes. It holds the install on
|
|
975
|
+
* update.hold, so it comes before the hold's own check.
|
|
976
|
+
*/
|
|
977
|
+
function nodeMoveCheck(root) {
|
|
978
|
+
const path = (0, node_move_journal_js_1.nodeMovePlaces)(root).journal;
|
|
979
|
+
let journal;
|
|
980
|
+
try {
|
|
981
|
+
journal = (0, node_move_journal_js_1.readNodeMoveJournal)(path);
|
|
982
|
+
}
|
|
983
|
+
catch (error) {
|
|
984
|
+
return {
|
|
985
|
+
name: 'update',
|
|
986
|
+
status: 'fail',
|
|
987
|
+
detail: 'an unfinished move of the managed Node left a journal that cannot be read',
|
|
988
|
+
code: 'node_move.open',
|
|
989
|
+
context: message(error),
|
|
990
|
+
fix: `read ${path}; the install command's recovery needs it`,
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
if (journal === null)
|
|
994
|
+
return null;
|
|
995
|
+
return {
|
|
996
|
+
name: 'update',
|
|
997
|
+
status: 'fail',
|
|
998
|
+
detail: journal.phase === 'committed'
|
|
999
|
+
? `the move of the managed Node to ${journal.to} took effect, but its old folders are not removed yet`
|
|
1000
|
+
: `the move of the managed Node from ${journal.from} to ${journal.to} is unfinished (step ${journal.step}); the daemon may stay stopped until it is finished or undone`,
|
|
1001
|
+
code: 'node_move.open',
|
|
1002
|
+
context: path,
|
|
1003
|
+
fix: `run the install command again, which finishes or undoes it: ${node_move_journal_js_1.INSTALL_COMMAND}`,
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* An unfinished `mama update`: its journal (docs/development/work/update.md, PR 3), with the
|
|
1008
|
+
* command that resolves it by absolute paths, or a staging prefix an updater killed before it
|
|
1009
|
+
* wrote its journal left behind.
|
|
1010
|
+
*/
|
|
1011
|
+
function updateChecks(root, home) {
|
|
1012
|
+
const move = nodeMoveCheck(root);
|
|
1013
|
+
if (move !== null)
|
|
1014
|
+
return [move];
|
|
1015
|
+
const path = (0, update_journal_js_1.updatePaths)(root).journal;
|
|
1016
|
+
let journal;
|
|
1017
|
+
try {
|
|
1018
|
+
journal = (0, update_journal_js_1.readUpdateJournal)(path);
|
|
1019
|
+
}
|
|
1020
|
+
catch (error) {
|
|
1021
|
+
return [
|
|
1022
|
+
{
|
|
1023
|
+
name: 'update',
|
|
1024
|
+
status: 'fail',
|
|
1025
|
+
detail: 'an unfinished update left a journal that cannot be read',
|
|
1026
|
+
code: 'update.open',
|
|
1027
|
+
context: message(error),
|
|
1028
|
+
fix: `read ${path}; mama update --rollback needs it`,
|
|
1029
|
+
},
|
|
1030
|
+
];
|
|
1031
|
+
}
|
|
1032
|
+
if (journal !== null) {
|
|
1033
|
+
return [
|
|
1034
|
+
{
|
|
1035
|
+
name: 'update',
|
|
1036
|
+
status: 'fail',
|
|
1037
|
+
detail: journal.phase === 'committed'
|
|
1038
|
+
? `the update to ${journal.to} took effect, but it was not finished: its inputs may stay held, and nothing runs until the command below finishes it`
|
|
1039
|
+
: `the update from ${journal.from} to ${journal.to} is unfinished (${journal.phase}, step ${journal.step}); the daemon stays stopped or held until it is resolved`,
|
|
1040
|
+
code: 'update.open',
|
|
1041
|
+
fix: (0, update_journal_js_1.rollbackCommand)(journal),
|
|
1042
|
+
},
|
|
1043
|
+
];
|
|
1044
|
+
}
|
|
1045
|
+
const hold = (0, update_journal_js_1.updatePaths)(root).hold;
|
|
1046
|
+
if ((0, node_fs_1.existsSync)(hold)) {
|
|
1047
|
+
return [
|
|
1048
|
+
{
|
|
1049
|
+
name: 'update',
|
|
1050
|
+
status: 'fail',
|
|
1051
|
+
detail: 'an update hold file is in place with no update journal; start.sh exits at once, so the daemon does not start',
|
|
1052
|
+
code: 'update.hold',
|
|
1053
|
+
context: hold,
|
|
1054
|
+
fix: `rm ${hold}, then mama service start`,
|
|
1055
|
+
},
|
|
1056
|
+
];
|
|
1057
|
+
}
|
|
1058
|
+
const install = (0, install_kind_js_1.installKind)(root, home);
|
|
1059
|
+
const staging = install.kind === 'npm' ? (0, update_journal_js_1.leftoverStaging)((0, node_path_1.dirname)(install.packageRoot)) : [];
|
|
1060
|
+
return staging.length === 0
|
|
1061
|
+
? []
|
|
1062
|
+
: [
|
|
1063
|
+
{
|
|
1064
|
+
name: 'update',
|
|
1065
|
+
status: 'warn',
|
|
1066
|
+
detail: 'an interrupted mama update left its staging folder; the install runs as before',
|
|
1067
|
+
code: 'update.staging',
|
|
1068
|
+
context: staging.join(', '),
|
|
1069
|
+
fix: 'the next mama update removes it',
|
|
1070
|
+
},
|
|
1071
|
+
];
|
|
1072
|
+
}
|
|
1073
|
+
/** The daemon's last daily release check, from its file; doctor itself asks no registry. */
|
|
1074
|
+
function releaseCheck(root, home) {
|
|
1075
|
+
const report = (0, release_check_js_1.releaseReport)(root, home);
|
|
1076
|
+
if (report === null) {
|
|
1077
|
+
return {
|
|
1078
|
+
name: 'release',
|
|
1079
|
+
status: 'ok',
|
|
1080
|
+
detail: 'not checked yet; the running daemon checks once a day',
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
return {
|
|
1084
|
+
name: 'release',
|
|
1085
|
+
status: report.status,
|
|
1086
|
+
detail: report.detail,
|
|
1087
|
+
...(report.context === undefined ? {} : { context: report.context }),
|
|
1088
|
+
...(report.steps === undefined ? {} : { fix: report.steps.join('; then ') }),
|
|
1089
|
+
...(report.fix === undefined ? {} : { fix: report.fix }),
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
906
1092
|
function serviceCheck(platform, home, serviceRun) {
|
|
907
1093
|
let launchd;
|
|
908
1094
|
let unit;
|