@chainingintention/pi-web-cn 1.202610.3 → 1.202610.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/cli.js +129 -122
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/PiWebApp-CN3g7SqA.js +4362 -0
- package/dist/client/assets/external-DUGCSDhZ.js +2 -0
- package/dist/client/assets/index-JduZlbIF.js +2 -0
- package/dist/client/index.html +4 -4
- package/dist/client/manifest.webmanifest +2 -1
- package/dist/localization.js +24 -0
- package/dist/localization.js.map +1 -0
- package/dist/nativeServices/serviceDoctor.js +45 -44
- package/dist/nativeServices/serviceDoctor.js.map +1 -1
- package/dist/pi-packages/captains-log/dist/browser/index.js +46 -45
- package/dist/pi-packages/captains-log/dist/browser/markdown.js +2 -1
- package/dist/pi-packages/captains-log/dist/browser/panel.js +56 -55
- package/dist/pi-packages/captains-log/i18n.js +7 -0
- package/dist/pi-packages/relays/i18n.js +7 -0
- package/dist/pi-packages/relays/markdownDocument.js +2 -1
- package/dist/pi-packages/relays/pi-web-plugin.js +8 -6
- package/dist/pi-packages/relays/relaysPanelElement.js +24 -23
- package/dist/pi-web-plugins/files/browser/pi-web-plugin.js +124 -124
- package/dist/pi-web-plugins/git/browser/git-contract.js +13 -12
- package/dist/pi-web-plugins/git/browser/git-panel.js +25 -24
- package/dist/pi-web-plugins/git/browser/i18n.js +7 -0
- package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +7 -3
- package/dist/pi-web-plugins/git/git-backend.js +10 -9
- package/dist/pi-web-plugins/git/i18n.js +7 -0
- package/dist/pi-web-plugins/git/server-plugin.js +21 -19
- package/dist/pi-web-plugins/info/i18n.js +7 -0
- package/dist/pi-web-plugins/info/infoInternals.js +57 -62
- package/dist/pi-web-plugins/info/pi-web-plugin.js +34 -36
- package/dist/pi-web-plugins/mermaid/browser/pi-web-plugin.js +3 -3
- package/dist/pi-web-plugins/terminal/browser/pi-web-plugin.js +55 -52
- package/dist/pi-web-plugins/terminal/i18n.js +7 -0
- package/dist/pi-web-plugins/terminal/server-plugin.js +23 -21
- package/dist/pi-web-plugins/terminal/terminalService.js +22 -21
- package/dist/pi-web-plugins/updates/i18n.js +7 -0
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +58 -54
- package/dist/pi-web-plugins/updates/updatesLogic.js +21 -20
- package/dist/pi-web-plugins/workspace-tasks/config.js +12 -11
- package/dist/pi-web-plugins/workspace-tasks/i18n.js +7 -0
- package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +8 -6
- package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +20 -19
- package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +12 -11
- package/dist/pi-web-plugins/zh-cn/auth.json +9 -0
- package/dist/pi-web-plugins/zh-cn/bundled.json +176 -0
- package/dist/pi-web-plugins/zh-cn/cli.json +171 -0
- package/dist/pi-web-plugins/zh-cn/client.json +219 -0
- package/dist/pi-web-plugins/zh-cn/components.json +1002 -0
- package/dist/pi-web-plugins/zh-cn/config-errors.json +172 -0
- package/dist/pi-web-plugins/zh-cn/files.json +41 -0
- package/dist/pi-web-plugins/zh-cn/machines.json +28 -0
- package/dist/pi-web-plugins/zh-cn/main.json +459 -0
- package/dist/pi-web-plugins/zh-cn/management-errors.json +23 -0
- package/dist/pi-web-plugins/zh-cn/manifest.webmanifest +25 -0
- package/dist/pi-web-plugins/zh-cn/metadata.json +3 -0
- package/dist/pi-web-plugins/zh-cn/package.json +10 -0
- package/dist/pi-web-plugins/zh-cn/pi-web-plugin.js +16 -0
- package/dist/pi-web-plugins/zh-cn/projects.json +6 -0
- package/dist/pi-web-plugins/zh-cn/provider-auth.json +17 -0
- package/dist/pi-web-plugins/zh-cn/routing.json +68 -0
- package/dist/pi-web-plugins/zh-cn/server-main.json +99 -0
- package/dist/pi-web-plugins/zh-cn/server.json +174 -0
- package/dist/piWebVersionReport.js +17 -16
- package/dist/piWebVersionReport.js.map +1 -1
- package/dist/plugin-api.d.ts +4 -1
- package/dist/pluginRecoveryCli.js +25 -24
- package/dist/pluginRecoveryCli.js.map +1 -1
- package/dist/server/app.js +43 -28
- package/dist/server/app.js.map +1 -1
- package/dist/server/audit/normalToolAuditCli.js +45 -43
- package/dist/server/audit/normalToolAuditCli.js.map +1 -1
- package/dist/server/configRoutes.js +39 -30
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/diagnostics/nodePtyNativeModule.js +7 -6
- package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -1
- package/dist/server/diagnostics/nodePtySpawnHelper.js +21 -20
- package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -1
- package/dist/server/knownAutoInstallPiPackages.js +2 -2
- package/dist/server/knownAutoInstallPiPackages.js.map +1 -1
- package/dist/server/knownPiPackages.js +2 -2
- package/dist/server/knownPiPackages.js.map +1 -1
- package/dist/server/machines/machineClient.js +8 -6
- package/dist/server/machines/machineClient.js.map +1 -1
- package/dist/server/machines/machinePluginProxyRoutes.js +11 -10
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineProxyRoutes.js +27 -29
- package/dist/server/machines/machineProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineRoutes.js +10 -12
- package/dist/server/machines/machineRoutes.js.map +1 -1
- package/dist/server/machines/machineService.js +17 -18
- package/dist/server/machines/machineService.js.map +1 -1
- package/dist/server/managementEmbed.js +26 -25
- package/dist/server/managementEmbed.js.map +1 -1
- package/dist/server/normalAuth.js +29 -26
- package/dist/server/normalAuth.js.map +1 -1
- package/dist/server/passwordVerifier.js +2 -1
- package/dist/server/passwordVerifier.js.map +1 -1
- package/dist/server/piPackageService.js +7 -5
- package/dist/server/piPackageService.js.map +1 -1
- package/dist/server/piWebPluginService.js +27 -11
- package/dist/server/piWebPluginService.js.map +1 -1
- package/dist/server/piWebStatus.js +16 -14
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/plugins/serverPluginRuntime.js +4 -2
- package/dist/server/plugins/serverPluginRuntime.js.map +1 -1
- package/dist/server/projects/projectService.js +4 -3
- package/dist/server/projects/projectService.js.map +1 -1
- package/dist/server/sessiond/projectMutationRoutes.js +5 -4
- package/dist/server/sessiond/projectMutationRoutes.js.map +1 -1
- package/dist/server/sessiond/sessionProxyRoutes.js +11 -8
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
- package/dist/server/sessiond/workspaceCatalogRoutes.js +5 -3
- package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -1
- package/dist/server/sessiond.js +8 -3
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/authRoutes.js +20 -19
- package/dist/server/sessions/authRoutes.js.map +1 -1
- package/dist/server/sessions/authService.js +13 -10
- package/dist/server/sessions/authService.js.map +1 -1
- package/dist/server/sessions/builtinCommands.js +28 -21
- package/dist/server/sessions/builtinCommands.js.map +1 -1
- package/dist/server/sessions/oauthLoginFlowService.js +17 -15
- package/dist/server/sessions/oauthLoginFlowService.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +229 -208
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/projectAuthService.js +5 -3
- package/dist/server/sessions/projectAuthService.js.map +1 -1
- package/dist/server/sessions/sessionArchiveMapping.js +8 -7
- package/dist/server/sessions/sessionArchiveMapping.js.map +1 -1
- package/dist/server/sessions/sessionCleanup.js +4 -3
- package/dist/server/sessions/sessionCleanup.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +70 -67
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionNotificationStore.js +12 -11
- package/dist/server/sessions/sessionNotificationStore.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +74 -72
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/sessionTreeProjection.js +50 -49
- package/dist/server/sessions/sessionTreeProjection.js.map +1 -1
- package/dist/server/sessions/sessionUnreadStore.js +25 -2
- package/dist/server/sessions/sessionUnreadStore.js.map +1 -1
- package/dist/server/terminals/managementCommandRunService.js +13 -12
- package/dist/server/terminals/managementCommandRunService.js.map +1 -1
- package/dist/server/workbench/accessStateStore.js +9 -7
- package/dist/server/workbench/accessStateStore.js.map +1 -1
- package/dist/server/workbench/capabilitySearch.js +3 -2
- package/dist/server/workbench/capabilitySearch.js.map +1 -1
- package/dist/server/workbench/knowledgeSearch.js +8 -7
- package/dist/server/workbench/knowledgeSearch.js.map +1 -1
- package/dist/server/workbench/mcpClient.js +6 -5
- package/dist/server/workbench/mcpClient.js.map +1 -1
- package/dist/server/workbench/skillSync.js +4 -2
- package/dist/server/workbench/skillSync.js.map +1 -1
- package/dist/server/workbench/workbenchClient.js +8 -7
- package/dist/server/workbench/workbenchClient.js.map +1 -1
- package/dist/server/workbench/workbenchTools.js +8 -6
- package/dist/server/workbench/workbenchTools.js.map +1 -1
- package/dist/server/workingDirectory.js +3 -2
- package/dist/server/workingDirectory.js.map +1 -1
- package/dist/server/workspaceExplorerRoutes.js +16 -13
- package/dist/server/workspaceExplorerRoutes.js.map +1 -1
- package/dist/server/workspaces/fileContentService.js +11 -10
- package/dist/server/workspaces/fileContentService.js.map +1 -1
- package/dist/server/workspaces/fileOperationService.js +7 -6
- package/dist/server/workspaces/fileOperationService.js.map +1 -1
- package/dist/server/workspaces/filePreviewService.js +5 -4
- package/dist/server/workspaces/filePreviewService.js.map +1 -1
- package/dist/server/workspaces/fileSuggestions.js +2 -1
- package/dist/server/workspaces/fileSuggestions.js.map +1 -1
- package/dist/server/workspaces/pathAccessPolicy.js +24 -18
- package/dist/server/workspaces/pathAccessPolicy.js.map +1 -1
- package/dist/server/workspaces/pathSafety.js +6 -5
- package/dist/server/workspaces/pathSafety.js.map +1 -1
- package/dist/server/workspaces/projectPiWebConfig.js +3 -2
- package/dist/server/workspaces/projectPiWebConfig.js.map +1 -1
- package/dist/server/workspaces/workspaceRemovalService.js +4 -3
- package/dist/server/workspaces/workspaceRemovalService.js.map +1 -1
- package/dist/server/workspaces/workspaceRouteErrors.js +4 -2
- package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -1
- package/dist/server/workspaces/workspaceUserError.js +18 -0
- package/dist/server/workspaces/workspaceUserError.js.map +1 -0
- package/dist/server-plugin-api.d.ts +3 -1
- package/dist/server-plugin-api.js.map +1 -1
- package/dist/serverPluginRecovery.js +3 -2
- package/dist/serverPluginRecovery.js.map +1 -1
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/i18n.js +41 -0
- package/dist/shared/i18n.js.map +1 -0
- package/dist/shared/piWebConfigParsing.js +52 -49
- package/dist/shared/piWebConfigParsing.js.map +1 -1
- package/dist/shared/pluginApiTypes.d.ts +7 -0
- package/dist/shared/requiredTerminalPlugin.js +1 -1
- package/dist/shared/requiredTerminalPlugin.js.map +1 -1
- package/dist/shared/sessionDefaults.js +7 -6
- package/dist/shared/sessionDefaults.js.map +1 -1
- package/dist/shared/thinkingLevels.js +17 -16
- package/dist/shared/thinkingLevels.js.map +1 -1
- package/docs/config.md +10 -1
- package/docs/plugins.md +8 -0
- package/package.json +1 -1
- package/dist/client/assets/index-CFhaGb5m.js +0 -4357
package/README.md
CHANGED
|
@@ -130,6 +130,7 @@ npm run verify
|
|
|
130
130
|
|
|
131
131
|
## 文档
|
|
132
132
|
|
|
133
|
+
- [代码库维护文档:架构、模块契约、改动地图与验证](https://github.com/nayuto-wakusei/pi-web-ChineseTranslation/blob/main/docs/maintenance.md)
|
|
133
134
|
- [上游网站](https://pi-web.dev/)
|
|
134
135
|
- [安装](https://pi-web.dev/install)
|
|
135
136
|
- [远端优先](https://pi-web.dev/remote-first)
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { loadNodeTranslator } from "./localization.js";
|
|
3
|
+
import { createTranslator } from "./shared/i18n.js";
|
|
2
4
|
import { spawnSync } from "node:child_process";
|
|
3
5
|
import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
4
6
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
@@ -48,22 +50,22 @@ export function serviceBackendForPlatform(platform) {
|
|
|
48
50
|
function currentServiceBackend() {
|
|
49
51
|
return serviceBackendForPlatform(process.platform);
|
|
50
52
|
}
|
|
51
|
-
function requireServiceBackend(command) {
|
|
53
|
+
function requireServiceBackend(command, t = createTranslator("en", {})) {
|
|
52
54
|
const backend = currentServiceBackend();
|
|
53
55
|
if (backend !== undefined)
|
|
54
56
|
return backend;
|
|
55
|
-
throw new Error(
|
|
57
|
+
throw new Error(t("service.unsupported", "`{command}` requires a supported per-user service manager (systemd user services or LaunchAgents) and is not supported on {platform}.\n\n{advice}", { command, platform: platformLabel(), advice: manualRunAdvice(t) }));
|
|
56
58
|
}
|
|
57
|
-
function manualRunAdvice() {
|
|
59
|
+
function manualRunAdvice(t = createTranslator("en", {})) {
|
|
58
60
|
return [
|
|
59
|
-
"Run PI WEB manually from a checkout:",
|
|
61
|
+
t("manual.checkout", "Run PI WEB manually from a checkout:"),
|
|
60
62
|
" npm run start:sessiond",
|
|
61
63
|
" PI_WEB_PORT=8504 npm start",
|
|
62
64
|
"",
|
|
63
|
-
"For development in one terminal:",
|
|
65
|
+
t("manual.singleTerminal", "For development in one terminal:"),
|
|
64
66
|
" npm run dev",
|
|
65
67
|
"",
|
|
66
|
-
"For split development, keep sessiond separate and run web/API plus Vite UI separately:",
|
|
68
|
+
t("manual.split", "For split development, keep sessiond separate and run web/API plus Vite UI separately:"),
|
|
67
69
|
" npm run dev:sessiond",
|
|
68
70
|
" npm run dev:web",
|
|
69
71
|
" npm run dev:client",
|
|
@@ -113,7 +115,7 @@ function isLingerEnabled() {
|
|
|
113
115
|
return false;
|
|
114
116
|
return undefined;
|
|
115
117
|
}
|
|
116
|
-
function parseInstallOptions(args) {
|
|
118
|
+
function parseInstallOptions(args, t = createTranslator("en", {})) {
|
|
117
119
|
const options = { host: "127.0.0.1", port: "8504", mode: "production" };
|
|
118
120
|
for (let i = 0; i < args.length; i += 1) {
|
|
119
121
|
const arg = args[i];
|
|
@@ -122,7 +124,7 @@ function parseInstallOptions(args) {
|
|
|
122
124
|
if (arg === "--host") {
|
|
123
125
|
const value = args[i + 1];
|
|
124
126
|
if (value === undefined)
|
|
125
|
-
throw new Error("--host requires a value");
|
|
127
|
+
throw new Error(t("install.hostRequired", "--host requires a value"));
|
|
126
128
|
options.host = value;
|
|
127
129
|
i += 1;
|
|
128
130
|
}
|
|
@@ -132,7 +134,7 @@ function parseInstallOptions(args) {
|
|
|
132
134
|
else if (arg === "--port") {
|
|
133
135
|
const value = args[i + 1];
|
|
134
136
|
if (value === undefined)
|
|
135
|
-
throw new Error("--port requires a value");
|
|
137
|
+
throw new Error(t("install.portRequired", "--port requires a value"));
|
|
136
138
|
options.port = value;
|
|
137
139
|
i += 1;
|
|
138
140
|
}
|
|
@@ -142,7 +144,7 @@ function parseInstallOptions(args) {
|
|
|
142
144
|
else if (arg === "--config") {
|
|
143
145
|
const value = args[i + 1];
|
|
144
146
|
if (value === undefined)
|
|
145
|
-
throw new Error("--config requires a value");
|
|
147
|
+
throw new Error(t("install.configRequired", "--config requires a value"));
|
|
146
148
|
options.config = value;
|
|
147
149
|
i += 1;
|
|
148
150
|
}
|
|
@@ -156,7 +158,7 @@ function parseInstallOptions(args) {
|
|
|
156
158
|
// Accepted for backwards-compatible readability; PI WEB chooses the native user service backend automatically.
|
|
157
159
|
}
|
|
158
160
|
else {
|
|
159
|
-
throw new Error(
|
|
161
|
+
throw new Error(t("install.unknownOption", "Unknown install option: {arg}", { arg: arg }));
|
|
160
162
|
}
|
|
161
163
|
}
|
|
162
164
|
return options;
|
|
@@ -233,14 +235,14 @@ function stopOrder(refs) {
|
|
|
233
235
|
function devRootPath() {
|
|
234
236
|
return resolve(process.cwd());
|
|
235
237
|
}
|
|
236
|
-
function validateDevCheckout(root) {
|
|
238
|
+
function validateDevCheckout(root, t) {
|
|
237
239
|
const packageJsonPath = join(root, "package.json");
|
|
238
240
|
if (!existsSync(packageJsonPath)) {
|
|
239
|
-
throw new Error(
|
|
241
|
+
throw new Error(t("install.checkoutMissing", "Development mode must be installed from a PI WEB checkout. Missing package.json: {path}", { path: packageJsonPath }));
|
|
240
242
|
}
|
|
241
243
|
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
242
244
|
if (!isRecord(parsed) || parsed["name"] !== PI_WEB_PACKAGE_NAME) {
|
|
243
|
-
throw new Error(
|
|
245
|
+
throw new Error(t("install.checkoutWrong", "Development mode must be installed from a PI WEB checkout. {path} is not {packageName}.", { path: packageJsonPath, packageName: PI_WEB_PACKAGE_NAME }));
|
|
244
246
|
}
|
|
245
247
|
}
|
|
246
248
|
function launchdLogPath(ref) {
|
|
@@ -363,12 +365,12 @@ async function uninstallNativeServices(backend) {
|
|
|
363
365
|
else
|
|
364
366
|
await uninstallLaunchdServices();
|
|
365
367
|
}
|
|
366
|
-
function serviceDisplayName(ref) {
|
|
368
|
+
function serviceDisplayName(ref, t = createTranslator("en", {})) {
|
|
367
369
|
if (ref.id === "sessiond")
|
|
368
|
-
return "session daemon";
|
|
370
|
+
return t("service.sessiond", "session daemon");
|
|
369
371
|
if (ref.id === "uiDev")
|
|
370
|
-
return "UI/API dev server";
|
|
371
|
-
return "web server";
|
|
372
|
+
return t("service.uiDev", "UI/API dev server");
|
|
373
|
+
return t("service.web", "web server");
|
|
372
374
|
}
|
|
373
375
|
function statusServiceRefs(backend) {
|
|
374
376
|
const ids = installedServiceIds(backend);
|
|
@@ -382,20 +384,20 @@ function statusServiceRefs(backend) {
|
|
|
382
384
|
return productionServiceRefs();
|
|
383
385
|
return serviceRefList(["sessiond"]);
|
|
384
386
|
}
|
|
385
|
-
function serviceInstallMode(backend) {
|
|
387
|
+
function serviceInstallMode(backend, t) {
|
|
386
388
|
const ids = installedServiceIds(backend);
|
|
387
389
|
if (ids.size === 0)
|
|
388
|
-
return "not installed";
|
|
390
|
+
return t("service.notInstalled", "not installed");
|
|
389
391
|
const hasSessiond = ids.has("sessiond");
|
|
390
392
|
const hasWeb = ids.has("web");
|
|
391
393
|
const hasUiDev = ids.has("uiDev");
|
|
392
394
|
if (hasWeb && hasUiDev)
|
|
393
|
-
return "mixed";
|
|
395
|
+
return t("service.mixed", "mixed");
|
|
394
396
|
if (hasUiDev)
|
|
395
|
-
return hasSessiond ? "development" : "development (incomplete)";
|
|
397
|
+
return hasSessiond ? t("service.development", "development") : t("service.developmentIncomplete", "development (incomplete)");
|
|
396
398
|
if (hasWeb)
|
|
397
|
-
return hasSessiond ? "production" : "production (incomplete)";
|
|
398
|
-
return "partial";
|
|
399
|
+
return hasSessiond ? t("service.production", "production") : t("service.productionIncomplete", "production (incomplete)");
|
|
400
|
+
return t("service.partial", "partial");
|
|
399
401
|
}
|
|
400
402
|
function makeServiceRuntimeStatus(ref, health, detail, target, filePath, pid) {
|
|
401
403
|
return {
|
|
@@ -462,25 +464,25 @@ function launchdRuntimeStatus(backend, ref) {
|
|
|
462
464
|
function runtimeStatus(backend, ref) {
|
|
463
465
|
return backend.kind === "systemd" ? systemdRuntimeStatus(backend, ref) : launchdRuntimeStatus(backend, ref);
|
|
464
466
|
}
|
|
465
|
-
function printServiceStatus(status) {
|
|
467
|
+
function printServiceStatus(status, t = createTranslator("en", {})) {
|
|
466
468
|
const icon = status.health === "running" ? "✓" : "✗";
|
|
467
469
|
const pid = status.pid === undefined ? "" : `, pid ${status.pid}`;
|
|
468
|
-
console.log(`${icon} ${serviceDisplayName(status.ref)}: ${status.detail} (${status.target}${pid})`);
|
|
470
|
+
console.log(`${icon} ${serviceDisplayName(status.ref, t)}: ${status.detail} (${status.target}${pid})`);
|
|
469
471
|
if (status.health === "not-installed")
|
|
470
|
-
console.log(
|
|
472
|
+
console.log(t("status.missingFile", " missing service file: {filePath}", { filePath: status.filePath }));
|
|
471
473
|
}
|
|
472
|
-
function printServiceStatusReport(backend) {
|
|
474
|
+
function printServiceStatusReport(backend, t = createTranslator("en", {})) {
|
|
473
475
|
const refs = statusServiceRefs(backend);
|
|
474
|
-
console.log(
|
|
476
|
+
console.log(t("status.services", "PI WEB services: {mode} ({backend})", { mode: serviceInstallMode(backend, t), backend: backend.label }));
|
|
475
477
|
if (refs.length === 0) {
|
|
476
|
-
console.log("✗ no PI WEB service files found");
|
|
477
|
-
console.log(" Run `pi-web install` or `pi-web install --dev`.");
|
|
478
|
+
console.log(t("status.noServices", "✗ no PI WEB service files found"));
|
|
479
|
+
console.log(t("status.installAdvice", " Run `pi-web install` or `pi-web install --dev`."));
|
|
478
480
|
return false;
|
|
479
481
|
}
|
|
480
482
|
const statuses = refs.map((ref) => runtimeStatus(backend, ref));
|
|
481
483
|
for (const status of statuses)
|
|
482
|
-
printServiceStatus(status);
|
|
483
|
-
console.log("\nUse `pi-web logs` for service logs.");
|
|
484
|
+
printServiceStatus(status, t);
|
|
485
|
+
console.log(t("status.logsAdvice", "\nUse `pi-web logs` for service logs."));
|
|
484
486
|
return statuses.every((status) => status.health === "running");
|
|
485
487
|
}
|
|
486
488
|
function configuredServiceCommand(name) {
|
|
@@ -527,17 +529,17 @@ function nativeServiceInstallCandidate(options, backend, configPath, devRoot) {
|
|
|
527
529
|
},
|
|
528
530
|
};
|
|
529
531
|
}
|
|
530
|
-
function printNativeServiceInstallFailure(failure) {
|
|
532
|
+
function printNativeServiceInstallFailure(failure, t) {
|
|
531
533
|
if (failure.kind === "plan-resolution") {
|
|
532
534
|
for (const item of failure.failures) {
|
|
533
535
|
if (item.kind === "probe-infrastructure") {
|
|
534
|
-
console.log(
|
|
536
|
+
console.log(t("install.probeFailure", "✗ Service-manager probe infrastructure failure ({reason}): {message}", { reason: item.reason, message: item.message }));
|
|
535
537
|
}
|
|
536
538
|
else if (item.kind === "entrypoint-inspection-failure") {
|
|
537
|
-
console.log(
|
|
539
|
+
console.log(t("install.entrypointFailure", "✗ Could not inspect bundled {service} entrypoint {path}: {message}", { service: item.serviceId, path: item.entrypointPath, message: item.message }));
|
|
538
540
|
}
|
|
539
541
|
else {
|
|
540
|
-
console.log(
|
|
542
|
+
console.log(t("install.commandMissing", "✗ {command} is unavailable to the service manager, and bundled entrypoint {path} is missing.", { command: item.namedCommand, path: item.bundledEntrypointPath }));
|
|
541
543
|
if (item.namedCommandFailure !== null)
|
|
542
544
|
console.log(` ${item.namedCommandFailure}`);
|
|
543
545
|
}
|
|
@@ -546,7 +548,7 @@ function printNativeServiceInstallFailure(failure) {
|
|
|
546
548
|
}
|
|
547
549
|
for (const item of failure.failures) {
|
|
548
550
|
if (item.kind === "probe-infrastructure") {
|
|
549
|
-
console.log(
|
|
551
|
+
console.log(t("install.probeFailure", "✗ Service-manager probe infrastructure failure ({reason}): {message}", { reason: item.reason, message: item.message }));
|
|
550
552
|
}
|
|
551
553
|
else {
|
|
552
554
|
console.log(`✗ ${item.prerequisite.description}`);
|
|
@@ -555,19 +557,19 @@ function printNativeServiceInstallFailure(failure) {
|
|
|
555
557
|
}
|
|
556
558
|
}
|
|
557
559
|
}
|
|
558
|
-
async function install(args) {
|
|
559
|
-
const backend = requireServiceBackend("pi-web install");
|
|
560
|
-
const options = parseInstallOptions(args);
|
|
560
|
+
async function install(args, t = createTranslator("en", {})) {
|
|
561
|
+
const backend = requireServiceBackend("pi-web install", t);
|
|
562
|
+
const options = parseInstallOptions(args, t);
|
|
561
563
|
const devRoot = options.mode === "dev" ? devRootPath() : undefined;
|
|
562
564
|
if (devRoot !== undefined)
|
|
563
|
-
validateDevCheckout(devRoot);
|
|
565
|
+
validateDevCheckout(devRoot, t);
|
|
564
566
|
const configPath = installConfigPath(options);
|
|
565
567
|
const candidate = nativeServiceInstallCandidate(options, backend, configPath, devRoot);
|
|
566
|
-
console.log(
|
|
567
|
-
console.log(
|
|
568
|
-
console.log(
|
|
569
|
-
if (!printNodePtyNativeModuleCheck()) {
|
|
570
|
-
throw new Error("Install preflight checks failed without changing config or services. Fix the failure above, then run `pi-web doctor` for more detail.");
|
|
568
|
+
console.log(t("install.preflight", "Running PI WEB {mode} install preflight checks...", { mode: options.mode }));
|
|
569
|
+
console.log(t("service.backend", "Service backend: {label}", { label: backend.label }));
|
|
570
|
+
console.log(t("service.shell", "Service shell: {value}", { value: describeServiceShell() }));
|
|
571
|
+
if (!printNodePtyNativeModuleCheck(t)) {
|
|
572
|
+
throw new Error(t("install.preflightFailed", "Install preflight checks failed without changing config or services. Fix the failure above, then run `pi-web doctor` for more detail."));
|
|
571
573
|
}
|
|
572
574
|
const result = await installNativeServiceCandidate(candidate, {
|
|
573
575
|
probe: createNativeServiceAuthoritativeProbe(),
|
|
@@ -576,47 +578,47 @@ async function install(args) {
|
|
|
576
578
|
replaceServices: installNativeServices,
|
|
577
579
|
});
|
|
578
580
|
if (!result.ok) {
|
|
579
|
-
printNativeServiceInstallFailure(result.failure);
|
|
581
|
+
printNativeServiceInstallFailure(result.failure, t);
|
|
580
582
|
if (nativeServiceInstallFailureNeedsPathAdvice(result.failure))
|
|
581
|
-
printPathSetupAdvice();
|
|
582
|
-
throw new Error("Install preflight checks failed without changing config or services. Fix the failure above, then run `pi-web doctor` for more detail.");
|
|
583
|
+
printPathSetupAdvice(undefined, t);
|
|
584
|
+
throw new Error(t("install.preflightFailed", "Install preflight checks failed without changing config or services. Fix the failure above, then run `pi-web doctor` for more detail."));
|
|
583
585
|
}
|
|
584
586
|
for (const service of result.plan.services.filter((item) => item.strategy.kind === "configured-override")) {
|
|
585
|
-
console.log(
|
|
587
|
+
console.log(t("install.overrideSkipped", "! {service} uses a configured command override; preflight did not execute that arbitrary command.", { service: service.description }));
|
|
586
588
|
}
|
|
587
|
-
console.log(
|
|
588
|
-
console.log(
|
|
589
|
+
console.log(t("install.started", "\nPI WEB {mode} services are installed and starting.", { mode: options.mode }));
|
|
590
|
+
console.log(t("install.config", "Config: {configPath}", { configPath: configPath }));
|
|
589
591
|
if (options.mode === "dev") {
|
|
590
|
-
console.log("Open: http://127.0.0.1:8505");
|
|
592
|
+
console.log(t("install.open", "Open: {url}", { url: "http://127.0.0.1:8505" }));
|
|
591
593
|
}
|
|
592
594
|
else {
|
|
593
|
-
console.log(
|
|
595
|
+
console.log(t("install.open", "Open: {url}", { url: `http://${options.host === "0.0.0.0" ? "127.0.0.1" : options.host}:${options.port}` }));
|
|
594
596
|
}
|
|
595
597
|
if (backend.kind === "systemd") {
|
|
596
598
|
const linger = isLingerEnabled();
|
|
597
599
|
if (linger === false) {
|
|
598
|
-
console.log("\nRecommended for server use: keep user services running after logout/reboot:");
|
|
600
|
+
console.log(t("install.lingerAdvice", "\nRecommended for server use: keep user services running after logout/reboot:"));
|
|
599
601
|
console.log(` sudo loginctl enable-linger ${userInfo().username}`);
|
|
600
602
|
}
|
|
601
603
|
else if (linger === undefined) {
|
|
602
|
-
console.log("\nRecommended for server use: enable systemd user lingering so services survive logout/reboot:");
|
|
604
|
+
console.log(t("install.enableLinger", "\nRecommended for server use: enable systemd user lingering so services survive logout/reboot:"));
|
|
603
605
|
console.log(` sudo loginctl enable-linger ${userInfo().username}`);
|
|
604
606
|
}
|
|
605
607
|
}
|
|
606
|
-
console.log("\nUseful commands:");
|
|
608
|
+
console.log(t("install.commands", "\nUseful commands:"));
|
|
607
609
|
console.log(" pi-web status");
|
|
608
610
|
console.log(" pi-web logs");
|
|
609
611
|
console.log(" pi-web restart");
|
|
610
612
|
}
|
|
611
|
-
async function uninstall() {
|
|
612
|
-
const backend = requireServiceBackend("pi-web uninstall");
|
|
613
|
+
async function uninstall(t = createTranslator("en", {})) {
|
|
614
|
+
const backend = requireServiceBackend("pi-web uninstall", t);
|
|
613
615
|
await uninstallNativeServices(backend);
|
|
614
|
-
console.log(
|
|
616
|
+
console.log(t("uninstall.done", "PI WEB {label} removed. Production and development service files were removed; config and data were left in place.", { label: backend.label }));
|
|
615
617
|
}
|
|
616
|
-
async function serviceAction(action) {
|
|
618
|
+
async function serviceAction(action, t = createTranslator("en", {})) {
|
|
617
619
|
const backend = requireServiceBackend(`pi-web ${action}`);
|
|
618
620
|
if (action === "status") {
|
|
619
|
-
if (!printServiceStatusReport(backend))
|
|
621
|
+
if (!printServiceStatusReport(backend, t))
|
|
620
622
|
process.exitCode = 1;
|
|
621
623
|
return;
|
|
622
624
|
}
|
|
@@ -693,8 +695,8 @@ function activeDockerMode(env) {
|
|
|
693
695
|
function truthyEnvValue(value) {
|
|
694
696
|
return value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false";
|
|
695
697
|
}
|
|
696
|
-
function logs() {
|
|
697
|
-
const backend = requireServiceBackend("pi-web logs");
|
|
698
|
+
function logs(t = createTranslator("en", {})) {
|
|
699
|
+
const backend = requireServiceBackend("pi-web logs", t);
|
|
698
700
|
const refs = installedServiceRefs(backend);
|
|
699
701
|
if (backend.kind === "systemd") {
|
|
700
702
|
run("journalctl", ["--user", ...refs.flatMap((ref) => ["-u", ref.systemdName]), "-f"]);
|
|
@@ -763,7 +765,7 @@ function optionalDoctorChecks() {
|
|
|
763
765
|
const shell = serviceShellLabel();
|
|
764
766
|
return [[`Caller login ${shell} can find optional ripgrep (rg)`, serviceShellCommand(commandCheck("rg"))]];
|
|
765
767
|
}
|
|
766
|
-
function printOptionalDoctorChecks() {
|
|
768
|
+
function printOptionalDoctorChecks(t = createTranslator("en", {})) {
|
|
767
769
|
let missingOptionalTool = false;
|
|
768
770
|
for (const [label, command] of optionalDoctorChecks()) {
|
|
769
771
|
const [bin, ...args] = command;
|
|
@@ -776,8 +778,8 @@ function printOptionalDoctorChecks() {
|
|
|
776
778
|
printCheckOutput(result.stdout || result.stderr);
|
|
777
779
|
}
|
|
778
780
|
if (missingOptionalTool) {
|
|
779
|
-
console.log(" Install ripgrep, or make rg visible to the service shell, for faster all-file @ suggestions.");
|
|
780
|
-
console.log(" PI WEB falls back to a bounded filesystem scan when rg is unavailable.");
|
|
781
|
+
console.log(t("doctor.ripgrep", " Install ripgrep, or make rg visible to the service shell, for faster all-file @ suggestions."));
|
|
782
|
+
console.log(t("doctor.scanFallback", " PI WEB falls back to a bounded filesystem scan when rg is unavailable."));
|
|
781
783
|
}
|
|
782
784
|
}
|
|
783
785
|
function installedServiceDefinitions(backend, ids, purpose, warn = (message) => { console.warn(`! ${message}`); }) {
|
|
@@ -877,7 +879,7 @@ export async function runReadinessCliCommand(command, dependencies) {
|
|
|
877
879
|
managedInspectionFailed,
|
|
878
880
|
});
|
|
879
881
|
}
|
|
880
|
-
function readinessCliCommandDependencies() {
|
|
882
|
+
function readinessCliCommandDependencies(t = createTranslator("en", {})) {
|
|
881
883
|
return {
|
|
882
884
|
environment: process.env,
|
|
883
885
|
currentBackend: currentServiceBackend,
|
|
@@ -887,23 +889,23 @@ function readinessCliCommandDependencies() {
|
|
|
887
889
|
// warnings there, including when an explicit config bypasses selection here.
|
|
888
890
|
inspectDefinitions: (backend, ids, purpose) => installedServiceDefinitions(backend, ids, purpose, purpose === "doctor" ? () => { } : undefined),
|
|
889
891
|
runLifecycle: performLifecycleServiceAction,
|
|
890
|
-
runDoctor: doctor,
|
|
892
|
+
runDoctor: (context) => doctor(context, t),
|
|
891
893
|
printVersion: async () => { await printPiWebVersionReport(); },
|
|
892
894
|
};
|
|
893
895
|
}
|
|
894
|
-
function nativeServiceDoctorTarget(backend, ids) {
|
|
896
|
+
function nativeServiceDoctorTarget(backend, ids, t = createTranslator("en", {})) {
|
|
895
897
|
const mode = inferInstalledNativeServiceMode(ids);
|
|
896
898
|
if (mode === "ambiguous") {
|
|
897
899
|
return {
|
|
898
900
|
kind: "inspection-failure",
|
|
899
|
-
message:
|
|
901
|
+
message: t("doctor.ambiguousMode", "installed service IDs do not identify one mode ({ids}).", { ids: [...ids].join(", ") || "none" }),
|
|
900
902
|
};
|
|
901
903
|
}
|
|
902
904
|
if (mode === "none") {
|
|
903
905
|
return {
|
|
904
906
|
kind: "prospective-production",
|
|
905
907
|
input: productionNativeServicePlanInput(backend, detectServiceShell(), {}),
|
|
906
|
-
reason: "no installed service strategy is available",
|
|
908
|
+
reason: t("doctor.noStrategy", "no installed service strategy is available"),
|
|
907
909
|
};
|
|
908
910
|
}
|
|
909
911
|
const expectedIds = mode === "production"
|
|
@@ -913,7 +915,7 @@ function nativeServiceDoctorTarget(backend, ids) {
|
|
|
913
915
|
if (missingId !== undefined) {
|
|
914
916
|
return {
|
|
915
917
|
kind: "inspection-failure",
|
|
916
|
-
message:
|
|
918
|
+
message: t("doctor.incompleteSet", "installed {mode} service set is incomplete; {service} is missing.", { mode, service: missingId }),
|
|
917
919
|
};
|
|
918
920
|
}
|
|
919
921
|
const definitions = installedServiceDefinitions(backend, expectedIds, "doctor");
|
|
@@ -930,22 +932,22 @@ function nativeServiceDoctorTarget(backend, ids) {
|
|
|
930
932
|
? {
|
|
931
933
|
kind: "prospective-production",
|
|
932
934
|
input: productionNativeServicePlanInput(backend, inspection.value.shell, inspection.value.environment),
|
|
933
|
-
reason: "installed executable strategy is not recorded",
|
|
935
|
+
reason: t("doctor.unrecordedStrategy", "installed executable strategy is not recorded"),
|
|
934
936
|
}
|
|
935
937
|
: { kind: "inspection-failure", message: inspection.message };
|
|
936
938
|
}
|
|
937
|
-
async function printNativeServiceDoctorChecks(backend, installedIds) {
|
|
938
|
-
const result = await runNativeServiceDoctor(nativeServiceDoctorTarget(backend, installedIds), {
|
|
939
|
+
async function printNativeServiceDoctorChecks(backend, installedIds, t = createTranslator("en", {})) {
|
|
940
|
+
const result = await runNativeServiceDoctor(nativeServiceDoctorTarget(backend, installedIds, t), {
|
|
939
941
|
probe: createNativeServiceAuthoritativeProbe(),
|
|
940
942
|
fileExists: regularFileExists,
|
|
941
943
|
});
|
|
942
|
-
const report = formatNativeServiceDoctorResult(result);
|
|
944
|
+
const report = formatNativeServiceDoctorResult(result, t);
|
|
943
945
|
for (const line of report.lines)
|
|
944
946
|
console.log(line);
|
|
945
|
-
printCallerContextComparisons(report);
|
|
947
|
+
printCallerContextComparisons(report, t);
|
|
946
948
|
return report;
|
|
947
949
|
}
|
|
948
|
-
function printCallerContextComparisons(report) {
|
|
950
|
+
function printCallerContextComparisons(report, t) {
|
|
949
951
|
if (report.plan === null || report.failedPrerequisites.length === 0)
|
|
950
952
|
return;
|
|
951
953
|
const seen = new Set();
|
|
@@ -956,7 +958,11 @@ function printCallerContextComparisons(report) {
|
|
|
956
958
|
const service = report.plan.services.find((candidate) => candidate.prerequisites.some((item) => item.id === prerequisite.id));
|
|
957
959
|
const command = nativeServicePrerequisiteShellCheck(report.plan.shell.name, prerequisite);
|
|
958
960
|
const result = captureServiceShell(report.plan.shell, command, service?.workingDirectory ?? null);
|
|
959
|
-
console.log(
|
|
961
|
+
console.log(t("doctor.callerComparison", " Caller-invoked {shell} -lc {outcome} {requirement}; the service-manager result is authoritative.", {
|
|
962
|
+
shell: report.plan.shell.name,
|
|
963
|
+
outcome: result.status === 0 ? t("doctor.satisfies", "satisfies") : t("doctor.unsatisfied", "also does not satisfy"),
|
|
964
|
+
requirement: prerequisite.description,
|
|
965
|
+
}));
|
|
960
966
|
}
|
|
961
967
|
}
|
|
962
968
|
function captureServiceShell(shell, command, workingDirectory) {
|
|
@@ -968,20 +974,20 @@ function captureServiceShell(shell, command, workingDirectory) {
|
|
|
968
974
|
function shellQuoteFor(shell, value) {
|
|
969
975
|
return shell === "fish" ? fishSingleQuote(value) : shellSingleQuote(value);
|
|
970
976
|
}
|
|
971
|
-
function printPathSetupAdvice(shell = detectServiceShell()) {
|
|
972
|
-
console.log("\nPATH setup advice:");
|
|
977
|
+
function printPathSetupAdvice(shell = detectServiceShell(), t = createTranslator("en", {})) {
|
|
978
|
+
console.log(t("doctor.pathAdvice", "\nPATH setup advice:"));
|
|
973
979
|
if (shell.name === "bash") {
|
|
974
|
-
console.log(" Detected bash. Put PATH setup for node/version managers/tools in ~/.bash_profile or ~/.profile.");
|
|
975
|
-
console.log(" If ~/.bash_profile exists, bash will not read ~/.profile unless you source it from ~/.bash_profile.");
|
|
976
|
-
console.log(" Do not rely only on ~/.bashrc or prompt hooks for tools needed by services or agents.");
|
|
980
|
+
console.log(t("doctor.bashPath", " Detected bash. Put PATH setup for node/version managers/tools in ~/.bash_profile or ~/.profile."));
|
|
981
|
+
console.log(t("doctor.bashProfile", " If ~/.bash_profile exists, bash will not read ~/.profile unless you source it from ~/.bash_profile."));
|
|
982
|
+
console.log(t("doctor.bashHooks", " Do not rely only on ~/.bashrc or prompt hooks for tools needed by services or agents."));
|
|
977
983
|
}
|
|
978
984
|
else if (shell.name === "zsh") {
|
|
979
|
-
console.log(" Detected zsh. Put PATH setup for node/version managers/tools in ~/.zprofile, not only ~/.zshrc.");
|
|
980
|
-
console.log(" Avoid relying on prompt hooks; PI WEB services run non-interactive login shells.");
|
|
985
|
+
console.log(t("doctor.zshPath", " Detected zsh. Put PATH setup for node/version managers/tools in ~/.zprofile, not only ~/.zshrc."));
|
|
986
|
+
console.log(t("doctor.promptHooks", " Avoid relying on prompt hooks; PI WEB services run non-interactive login shells."));
|
|
981
987
|
}
|
|
982
988
|
else {
|
|
983
|
-
console.log(" Detected fish. Prefer universal PATH setup such as `fish_add_path -U ...` for tools needed by services or agents.");
|
|
984
|
-
console.log(" Avoid relying on prompt hooks; PI WEB services run non-interactive login shells.");
|
|
989
|
+
console.log(t("doctor.fishPath", " Detected fish. Prefer universal PATH setup such as `fish_add_path -U ...` for tools needed by services or agents."));
|
|
990
|
+
console.log(t("doctor.promptHooks", " Avoid relying on prompt hooks; PI WEB services run non-interactive login shells."));
|
|
985
991
|
}
|
|
986
992
|
}
|
|
987
993
|
/**
|
|
@@ -1006,13 +1012,13 @@ export function expectedRunningComponents(installedServices, env) {
|
|
|
1006
1012
|
export function doctorExitCode(generalReadinessOk, nativeServicePlanOk, nodePtyRuntimeOk, runningComponentsOk) {
|
|
1007
1013
|
return generalReadinessOk && nativeServicePlanOk && nodePtyRuntimeOk && runningComponentsOk ? 0 : 1;
|
|
1008
1014
|
}
|
|
1009
|
-
async function doctor(context) {
|
|
1015
|
+
async function doctor(context, t = createTranslator("en", {})) {
|
|
1010
1016
|
const { backend, installedIds, environment, versionReportOptions, managedInspectionFailed } = context;
|
|
1011
1017
|
console.log(`Platform: ${platformLabel()}`);
|
|
1012
1018
|
console.log(`Service backend: ${backend?.label ?? "manual run only"}`);
|
|
1013
1019
|
console.log(`Service shell: ${describeServiceShell()}`);
|
|
1014
1020
|
if (backend === undefined) {
|
|
1015
|
-
console.log(
|
|
1021
|
+
console.log(t("doctor.nativeSkipped", "- Native user service plan checks skipped on {value}; no native-service drift is reported.", { value: platformLabel() }));
|
|
1016
1022
|
}
|
|
1017
1023
|
console.log("");
|
|
1018
1024
|
const runningVersionInfo = await printPiWebVersionReport(versionReportOptions);
|
|
@@ -1022,12 +1028,12 @@ async function doctor(context) {
|
|
|
1022
1028
|
console.log("\n✗ Installed PI WEB services are unavailable or stale (see \"Running services\" above).");
|
|
1023
1029
|
console.log(" Run `pi-web restart`, then check `pi-web status`.");
|
|
1024
1030
|
}
|
|
1025
|
-
console.log("\nGeneral login-shell readiness (separate from native-service requirements):");
|
|
1031
|
+
console.log(t("doctor.loginShell", "\nGeneral login-shell readiness (separate from native-service requirements):"));
|
|
1026
1032
|
const generalReadinessOk = runChecks(generalDoctorChecks());
|
|
1027
|
-
printOptionalDoctorChecks();
|
|
1028
|
-
console.log("\nNative terminal runtime readiness:");
|
|
1029
|
-
const nodePtyNativeModuleOk = printNodePtyNativeModuleCheck();
|
|
1030
|
-
const nodePtySpawnHelperOk = nodePtyNativeModuleOk ? printNodePtyDarwinSpawnHelperCheck() : true;
|
|
1033
|
+
printOptionalDoctorChecks(t);
|
|
1034
|
+
console.log(t("doctor.terminal", "\nNative terminal runtime readiness:"));
|
|
1035
|
+
const nodePtyNativeModuleOk = printNodePtyNativeModuleCheck(t);
|
|
1036
|
+
const nodePtySpawnHelperOk = nodePtyNativeModuleOk ? printNodePtyDarwinSpawnHelperCheck(t) : true;
|
|
1031
1037
|
let nativeServiceReport = null;
|
|
1032
1038
|
if (backend !== undefined) {
|
|
1033
1039
|
console.log("\nNative service plan checks (service-manager context):");
|
|
@@ -1036,52 +1042,52 @@ async function doctor(context) {
|
|
|
1036
1042
|
console.log(" Repair the reported service-manager definition before relying on doctor results.");
|
|
1037
1043
|
}
|
|
1038
1044
|
else {
|
|
1039
|
-
nativeServiceReport = await printNativeServiceDoctorChecks(backend, installedIds);
|
|
1045
|
+
nativeServiceReport = await printNativeServiceDoctorChecks(backend, installedIds, t);
|
|
1040
1046
|
}
|
|
1041
1047
|
}
|
|
1042
1048
|
if (backend?.kind === "systemd") {
|
|
1043
1049
|
const linger = isLingerEnabled();
|
|
1044
1050
|
if (linger === true) {
|
|
1045
|
-
console.log("✓ systemd user lingering enabled");
|
|
1051
|
+
console.log(t("doctor.lingerEnabled", "✓ systemd user lingering enabled"));
|
|
1046
1052
|
}
|
|
1047
1053
|
else if (linger === false) {
|
|
1048
|
-
console.log("✗ systemd user lingering disabled");
|
|
1049
|
-
console.log(
|
|
1054
|
+
console.log(t("doctor.lingerDisabled", "✗ systemd user lingering disabled"));
|
|
1055
|
+
console.log(t("doctor.lingerCommand", " Recommended on servers: sudo loginctl enable-linger {username}", { username: userInfo().username }));
|
|
1050
1056
|
}
|
|
1051
1057
|
else {
|
|
1052
|
-
console.log("? systemd user lingering unknown");
|
|
1053
|
-
console.log(
|
|
1058
|
+
console.log(t("doctor.lingerUnknown", "? systemd user lingering unknown"));
|
|
1059
|
+
console.log(t("doctor.lingerCommand", " Recommended on servers: sudo loginctl enable-linger {username}", { username: userInfo().username }));
|
|
1054
1060
|
}
|
|
1055
1061
|
}
|
|
1056
1062
|
else if (backend?.kind === "launchd") {
|
|
1057
|
-
console.log("- user services start at login with LaunchAgents");
|
|
1063
|
+
console.log(t("doctor.launchAgents", "- user services start at login with LaunchAgents"));
|
|
1058
1064
|
}
|
|
1059
1065
|
else {
|
|
1060
|
-
console.log(
|
|
1066
|
+
console.log(t("doctor.lingerSkipped", "- systemd user lingering skipped on {value}", { value: platformLabel() }));
|
|
1061
1067
|
}
|
|
1062
1068
|
const nativeServicePlanOk = !managedInspectionFailed && (nativeServiceReport?.ok ?? true);
|
|
1063
1069
|
const pathFailure = !generalReadinessOk || nativeServiceReport?.pathAdviceRecommended === true;
|
|
1064
1070
|
if (pathFailure) {
|
|
1065
|
-
console.log("\nIf a command works in your terminal but fails in the service-manager check, compare the caller and manager contexts above.");
|
|
1071
|
+
console.log(t("doctor.compareContexts", "\nIf a command works in your terminal but fails in the service-manager check, compare the caller and manager contexts above."));
|
|
1066
1072
|
const adviceShell = nativeServiceReport?.pathAdviceRecommended === true && nativeServiceReport.adviceShell !== null
|
|
1067
1073
|
? nativeServiceReport.adviceShell
|
|
1068
1074
|
: detectServiceShell();
|
|
1069
|
-
printPathSetupAdvice(adviceShell);
|
|
1075
|
+
printPathSetupAdvice(adviceShell, t);
|
|
1070
1076
|
}
|
|
1071
1077
|
if (generalReadinessOk && backend === undefined) {
|
|
1072
|
-
console.log(`\n${manualRunAdvice()}`);
|
|
1078
|
+
console.log(`\n${manualRunAdvice(t)}`);
|
|
1073
1079
|
}
|
|
1074
1080
|
if (doctorExitCode(generalReadinessOk, nativeServicePlanOk, nodePtyNativeModuleOk && nodePtySpawnHelperOk, runningComponentsOk) !== 0)
|
|
1075
1081
|
process.exitCode = 1;
|
|
1076
1082
|
}
|
|
1077
|
-
function printNodePtyNativeModuleCheck() {
|
|
1078
|
-
const result = formatNodePtyNativeModuleCheck(checkNodePtyNativeModule());
|
|
1083
|
+
function printNodePtyNativeModuleCheck(t) {
|
|
1084
|
+
const result = formatNodePtyNativeModuleCheck(checkNodePtyNativeModule(), t);
|
|
1079
1085
|
for (const line of result.lines)
|
|
1080
1086
|
console.log(line);
|
|
1081
1087
|
return result.ok;
|
|
1082
1088
|
}
|
|
1083
|
-
function printNodePtyDarwinSpawnHelperCheck() {
|
|
1084
|
-
const result = formatNodePtyDarwinSpawnHelperCheck(checkNodePtyDarwinSpawnHelper());
|
|
1089
|
+
function printNodePtyDarwinSpawnHelperCheck(t) {
|
|
1090
|
+
const result = formatNodePtyDarwinSpawnHelperCheck(checkNodePtyDarwinSpawnHelper(), t);
|
|
1085
1091
|
for (const line of result.lines)
|
|
1086
1092
|
console.log(line);
|
|
1087
1093
|
return result.ok;
|
|
@@ -1089,8 +1095,8 @@ function printNodePtyDarwinSpawnHelperCheck() {
|
|
|
1089
1095
|
function isRecord(value) {
|
|
1090
1096
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1091
1097
|
}
|
|
1092
|
-
function
|
|
1093
|
-
|
|
1098
|
+
export function cliHelp(t) {
|
|
1099
|
+
return t("help", `PI WEB
|
|
1094
1100
|
|
|
1095
1101
|
Usage:
|
|
1096
1102
|
pi-web install [--dev] [--host 127.0.0.1] [--port 8504] [--config ~/.config/pi-web/config.json]
|
|
@@ -1114,30 +1120,31 @@ Development service install from a checkout:
|
|
|
1114
1120
|
`);
|
|
1115
1121
|
}
|
|
1116
1122
|
async function main() {
|
|
1123
|
+
const t = loadNodeTranslator("cli");
|
|
1117
1124
|
const [command = "help", ...args] = process.argv.slice(2);
|
|
1118
1125
|
if (command === "install")
|
|
1119
|
-
await install(args);
|
|
1126
|
+
await install(args, t);
|
|
1120
1127
|
else if (command === "uninstall")
|
|
1121
|
-
await uninstall();
|
|
1128
|
+
await uninstall(t);
|
|
1122
1129
|
else if (command === "start" || command === "restart" || command === "doctor" || command === "version") {
|
|
1123
|
-
await runReadinessCliCommand(command, readinessCliCommandDependencies());
|
|
1130
|
+
await runReadinessCliCommand(command, readinessCliCommandDependencies(t));
|
|
1124
1131
|
}
|
|
1125
1132
|
else if (command === "stop" || command === "status")
|
|
1126
|
-
await serviceAction(command);
|
|
1133
|
+
await serviceAction(command, t);
|
|
1127
1134
|
else if (command === "logs")
|
|
1128
|
-
logs();
|
|
1135
|
+
logs(t);
|
|
1129
1136
|
else if (command === "audit") {
|
|
1130
1137
|
const { runNormalToolAuditCommand } = await import("./server/audit/normalToolAuditCli.js");
|
|
1131
1138
|
runNormalToolAuditCommand(args);
|
|
1132
1139
|
}
|
|
1133
1140
|
else if (command === "plugins")
|
|
1134
|
-
runPluginRecoveryCli(args, { restartPlan: (context) => sessionDaemonRestartPlan(context) });
|
|
1141
|
+
runPluginRecoveryCli(args, { restartPlan: (context) => sessionDaemonRestartPlan(context) }, t);
|
|
1135
1142
|
else if (command === "--version" || command === "-v")
|
|
1136
1143
|
console.log(packageVersion());
|
|
1137
1144
|
else if (command === "help" || command === "--help" || command === "-h")
|
|
1138
|
-
|
|
1145
|
+
console.log(cliHelp(t));
|
|
1139
1146
|
else
|
|
1140
|
-
throw new Error(
|
|
1147
|
+
throw new Error(t("cli.unknownCommand", "Unknown command: {command}", { command: command }));
|
|
1141
1148
|
}
|
|
1142
1149
|
export function isCliEntrypoint(entrypoint = process.argv[1], modulePath = fileURLToPath(import.meta.url)) {
|
|
1143
1150
|
if (entrypoint === undefined)
|