@nextclaw/service 0.1.1
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/LICENSE +21 -0
- package/dist/cli/commands/agent/agent-runtime.utils.d.ts +15 -0
- package/dist/cli/commands/agent/agent-runtime.utils.js +85 -0
- package/dist/cli/commands/agent/cli-agent-runner.utils.d.ts +21 -0
- package/dist/cli/commands/agent/cli-agent-runner.utils.js +89 -0
- package/dist/cli/commands/agent/index.d.ts +3 -0
- package/dist/cli/commands/agent/index.js +3 -0
- package/dist/cli/commands/agent/services/agent-commands.service.d.ts +17 -0
- package/dist/cli/commands/agent/services/agent-commands.service.js +112 -0
- package/dist/cli/commands/companion/index.d.ts +15 -0
- package/dist/cli/commands/companion/index.js +24 -0
- package/dist/cli/commands/companion/services/companion-process.service.d.ts +17 -0
- package/dist/cli/commands/companion/services/companion-process.service.js +49 -0
- package/dist/cli/commands/config/index.d.ts +2 -0
- package/dist/cli/commands/config/index.js +2 -0
- package/dist/cli/commands/config/services/config-commands.service.d.ts +18 -0
- package/dist/cli/commands/config/services/config-commands.service.js +133 -0
- package/dist/cli/commands/cron/index.d.ts +2 -0
- package/dist/cli/commands/cron/index.js +2 -0
- package/dist/cli/commands/cron/services/cron-commands.service.d.ts +22 -0
- package/dist/cli/commands/cron/services/cron-commands.service.js +107 -0
- package/dist/cli/commands/cron/services/cron-local.service.d.ts +25 -0
- package/dist/cli/commands/cron/services/cron-local.service.js +95 -0
- package/dist/cli/commands/cron/utils/cron-job.utils.d.ts +31 -0
- package/dist/cli/commands/cron/utils/cron-job.utils.js +15 -0
- package/dist/cli/commands/diagnostics/index.d.ts +2 -0
- package/dist/cli/commands/diagnostics/index.js +2 -0
- package/dist/cli/commands/diagnostics/services/diagnostics-commands.service.d.ts +22 -0
- package/dist/cli/commands/diagnostics/services/diagnostics-commands.service.js +319 -0
- package/dist/cli/commands/diagnostics/utils/diagnostics-render.utils.d.ts +23 -0
- package/dist/cli/commands/diagnostics/utils/diagnostics-render.utils.js +66 -0
- package/dist/cli/commands/gateway/index.d.ts +14 -0
- package/dist/cli/commands/gateway/index.js +15 -0
- package/dist/cli/commands/logs/index.d.ts +12 -0
- package/dist/cli/commands/logs/index.js +29 -0
- package/dist/cli/commands/mcp/index.d.ts +14 -0
- package/dist/cli/commands/mcp/index.js +193 -0
- package/dist/cli/commands/restart/index.d.ts +20 -0
- package/dist/cli/commands/restart/index.js +88 -0
- package/dist/cli/commands/secrets/index.d.ts +22 -0
- package/dist/cli/commands/secrets/index.js +280 -0
- package/dist/cli/commands/serve/index.d.ts +14 -0
- package/dist/cli/commands/serve/index.js +19 -0
- package/dist/cli/commands/skills/index.d.ts +26 -0
- package/dist/cli/commands/skills/index.js +147 -0
- package/dist/cli/commands/skills/marketplace-client.d.ts +31 -0
- package/dist/cli/commands/skills/marketplace-client.js +84 -0
- package/dist/cli/commands/skills/marketplace-command-options.utils.d.ts +25 -0
- package/dist/cli/commands/skills/marketplace-command-options.utils.js +31 -0
- package/dist/cli/commands/skills/marketplace-identity.utils.d.ts +14 -0
- package/dist/cli/commands/skills/marketplace-identity.utils.js +77 -0
- package/dist/cli/commands/skills/marketplace-network-retry.d.ts +4 -0
- package/dist/cli/commands/skills/marketplace-network-retry.js +32 -0
- package/dist/cli/commands/skills/marketplace.metadata.d.ts +29 -0
- package/dist/cli/commands/skills/marketplace.metadata.js +158 -0
- package/dist/cli/commands/skills/marketplace.service.d.ts +46 -0
- package/dist/cli/commands/skills/marketplace.service.js +238 -0
- package/dist/cli/commands/skills/skills-query.service.d.ts +141 -0
- package/dist/cli/commands/skills/skills-query.service.js +212 -0
- package/dist/cli/commands/start/index.d.ts +18 -0
- package/dist/cli/commands/start/index.js +25 -0
- package/dist/cli/commands/stop/index.d.ts +12 -0
- package/dist/cli/commands/stop/index.js +11 -0
- package/dist/cli/commands/ui/index.d.ts +14 -0
- package/dist/cli/commands/ui/index.js +17 -0
- package/dist/cli/commands/usage/index.d.ts +2 -0
- package/dist/cli/commands/usage/index.js +2 -0
- package/dist/cli/commands/usage/services/llm-usage-command.service.d.ts +22 -0
- package/dist/cli/commands/usage/services/llm-usage-command.service.js +160 -0
- package/dist/cli/commands/usage/services/llm-usage-query.service.d.ts +43 -0
- package/dist/cli/commands/usage/services/llm-usage-query.service.js +85 -0
- package/dist/commands/channel/channel-config-view.d.ts +7 -0
- package/dist/commands/channel/channel-config-view.js +7 -0
- package/dist/commands/channel/index.d.ts +28 -0
- package/dist/commands/channel/index.js +224 -0
- package/dist/commands/platform-auth/index.d.ts +2 -0
- package/dist/commands/platform-auth/index.js +2 -0
- package/dist/commands/platform-auth/services/account-status.service.d.ts +18 -0
- package/dist/commands/platform-auth/services/account-status.service.js +34 -0
- package/dist/commands/platform-auth/services/platform-auth-commands.service.d.ts +77 -0
- package/dist/commands/platform-auth/services/platform-auth-commands.service.js +295 -0
- package/dist/commands/platform-auth/utils/payload.utils.d.ts +28 -0
- package/dist/commands/platform-auth/utils/payload.utils.js +87 -0
- package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.d.ts +18 -0
- package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.js +111 -0
- package/dist/commands/plugin/development-source/first-party-plugin-load-paths.d.ts +9 -0
- package/dist/commands/plugin/development-source/first-party-plugin-load-paths.js +183 -0
- package/dist/commands/plugin/index.d.ts +30 -0
- package/dist/commands/plugin/index.js +266 -0
- package/dist/commands/plugin/plugin-command-utils.d.ts +13 -0
- package/dist/commands/plugin/plugin-command-utils.js +37 -0
- package/dist/commands/plugin/plugin-extension-registry.d.ts +10 -0
- package/dist/commands/plugin/plugin-extension-registry.js +35 -0
- package/dist/commands/plugin/plugin-mutation-actions.d.ts +15 -0
- package/dist/commands/plugin/plugin-mutation-actions.js +162 -0
- package/dist/commands/plugin/plugin-registry-loader.d.ts +15 -0
- package/dist/commands/plugin/plugin-registry-loader.js +43 -0
- package/dist/commands/plugin/plugin-reload.d.ts +13 -0
- package/dist/commands/plugin/plugin-reload.js +42 -0
- package/dist/commands/remote/index.d.ts +47 -0
- package/dist/commands/remote/index.js +174 -0
- package/dist/commands/remote/services/remote-access-host.service.d.ts +41 -0
- package/dist/commands/remote/services/remote-access-host.service.js +126 -0
- package/dist/commands/remote/services/remote-runtime-support.service.d.ts +15 -0
- package/dist/commands/remote/services/remote-runtime-support.service.js +79 -0
- package/dist/commands/remote/services/remote-service-control.service.d.ts +33 -0
- package/dist/commands/remote/services/remote-service-control.service.js +188 -0
- package/dist/commands/remote/utils/platform-api-base.utils.d.ts +14 -0
- package/dist/commands/remote/utils/platform-api-base.utils.js +39 -0
- package/dist/commands/service/index.d.ts +16 -0
- package/dist/commands/service/index.js +31 -0
- package/dist/commands/service/services/autostart/host-autostart-command.service.d.ts +29 -0
- package/dist/commands/service/services/autostart/host-autostart-command.service.js +158 -0
- package/dist/commands/service/services/autostart/host-autostart-runtime.service.d.ts +23 -0
- package/dist/commands/service/services/autostart/host-autostart-runtime.service.js +53 -0
- package/dist/commands/service/services/autostart/host-autostart.service.d.ts +41 -0
- package/dist/commands/service/services/autostart/host-autostart.service.js +48 -0
- package/dist/commands/service/services/autostart/linux-systemd-autostart.service.d.ts +48 -0
- package/dist/commands/service/services/autostart/linux-systemd-autostart.service.js +433 -0
- package/dist/commands/service/services/autostart/macos-launch-agent-autostart.service.d.ts +54 -0
- package/dist/commands/service/services/autostart/macos-launch-agent-autostart.service.js +405 -0
- package/dist/commands/service/services/autostart/windows-task-autostart.service.d.ts +54 -0
- package/dist/commands/service/services/autostart/windows-task-autostart.service.js +403 -0
- package/dist/commands/service/types/autostart/host-autostart.types.d.ts +64 -0
- package/dist/commands/service/types/autostart/host-autostart.types.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/launcher/npm-runtime-bundle-layout.store.d.ts +23 -0
- package/dist/launcher/npm-runtime-bundle-layout.store.js +37 -0
- package/dist/launcher/npm-runtime-bundle-manifest.service.d.ts +9 -0
- package/dist/launcher/npm-runtime-bundle-manifest.service.js +39 -0
- package/dist/launcher/npm-runtime-bundle.service.d.ts +47 -0
- package/dist/launcher/npm-runtime-bundle.service.js +150 -0
- package/dist/launcher/npm-runtime-bundle.types.d.ts +49 -0
- package/dist/launcher/npm-runtime-bundle.types.js +1 -0
- package/dist/launcher/npm-runtime-launcher.service.d.ts +19 -0
- package/dist/launcher/npm-runtime-launcher.service.js +57 -0
- package/dist/launcher/npm-runtime-update-command.service.d.ts +12 -0
- package/dist/launcher/npm-runtime-update-command.service.js +87 -0
- package/dist/launcher/npm-runtime-update-source.service.d.ts +19 -0
- package/dist/launcher/npm-runtime-update-source.service.js +57 -0
- package/dist/launcher/npm-runtime-update-state.store.d.ts +17 -0
- package/dist/launcher/npm-runtime-update-state.store.js +92 -0
- package/dist/launcher/npm-runtime-update.manager.d.ts +42 -0
- package/dist/launcher/npm-runtime-update.manager.js +179 -0
- package/dist/launcher/npm-runtime-update.service.d.ts +54 -0
- package/dist/launcher/npm-runtime-update.service.js +183 -0
- package/dist/service-runtime.service.d.ts +91 -0
- package/dist/service-runtime.service.js +392 -0
- package/dist/shared/controllers/gateway.controller.d.ts +61 -0
- package/dist/shared/controllers/gateway.controller.js +318 -0
- package/dist/shared/services/extensions/extension-lifecycle.service.d.ts +56 -0
- package/dist/shared/services/extensions/extension-lifecycle.service.js +143 -0
- package/dist/shared/services/extensions/service-extension-runtime.service.d.ts +51 -0
- package/dist/shared/services/extensions/service-extension-runtime.service.js +338 -0
- package/dist/shared/services/gateway/cron-job-handler.service.d.ts +26 -0
- package/dist/shared/services/gateway/cron-job-handler.service.js +100 -0
- package/dist/shared/services/gateway/gateway-restart-wake.service.d.ts +12 -0
- package/dist/shared/services/gateway/gateway-restart-wake.service.js +91 -0
- package/dist/shared/services/gateway/managers/gateway-plugin.manager.d.ts +37 -0
- package/dist/shared/services/gateway/managers/gateway-plugin.manager.js +218 -0
- package/dist/shared/services/gateway/managers/gateway-remote.manager.d.ts +20 -0
- package/dist/shared/services/gateway/managers/gateway-remote.manager.js +25 -0
- package/dist/shared/services/gateway/nextclaw-app.service.d.ts +22 -0
- package/dist/shared/services/gateway/nextclaw-app.service.js +53 -0
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts +89 -0
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js +337 -0
- package/dist/shared/services/gateway/service-bootstrap-status.d.ts +33 -0
- package/dist/shared/services/gateway/service-bootstrap-status.js +152 -0
- package/dist/shared/services/gateway/service-startup-support.service.d.ts +42 -0
- package/dist/shared/services/gateway/service-startup-support.service.js +96 -0
- package/dist/shared/services/gateway/utils/gateway-runtime-lifecycle.utils.d.ts +9 -0
- package/dist/shared/services/gateway/utils/gateway-runtime-lifecycle.utils.js +10 -0
- package/dist/shared/services/marketplace/service-marketplace-installer.service.d.ts +31 -0
- package/dist/shared/services/marketplace/service-marketplace-installer.service.js +99 -0
- package/dist/shared/services/marketplace/service-mcp-marketplace-ops.d.ts +39 -0
- package/dist/shared/services/marketplace/service-mcp-marketplace-ops.js +67 -0
- package/dist/shared/services/plugin/utils/plugin-dev-hot-reload.utils.d.ts +24 -0
- package/dist/shared/services/plugin/utils/plugin-dev-hot-reload.utils.js +117 -0
- package/dist/shared/services/plugin/utils/plugin-runtime-bridge.utils.d.ts +6 -0
- package/dist/shared/services/plugin/utils/plugin-runtime-bridge.utils.js +96 -0
- package/dist/shared/services/restart/restart-coordinator.service.d.ts +30 -0
- package/dist/shared/services/restart/restart-coordinator.service.js +51 -0
- package/dist/shared/services/restart/restart-sentinel.service.d.ts +39 -0
- package/dist/shared/services/restart/restart-sentinel.service.js +88 -0
- package/dist/shared/services/restart/runtime-restart-request.service.d.ts +24 -0
- package/dist/shared/services/restart/runtime-restart-request.service.js +42 -0
- package/dist/shared/services/runtime/runtime-command.service.d.ts +37 -0
- package/dist/shared/services/runtime/runtime-command.service.js +163 -0
- package/dist/shared/services/runtime/runtime-config-init.service.d.ts +4 -0
- package/dist/shared/services/runtime/runtime-config-init.service.js +10 -0
- package/dist/shared/services/runtime/service-managed-startup.service.d.ts +146 -0
- package/dist/shared/services/runtime/service-managed-startup.service.js +426 -0
- package/dist/shared/services/runtime/service-remote-runtime.service.d.ts +53 -0
- package/dist/shared/services/runtime/service-remote-runtime.service.js +173 -0
- package/dist/shared/services/runtime/utils/skills-loader.utils.d.ts +12 -0
- package/dist/shared/services/runtime/utils/skills-loader.utils.js +9 -0
- package/dist/shared/services/session/service-deferred-ncp-agent.service.d.ts +14 -0
- package/dist/shared/services/session/service-deferred-ncp-agent.service.js +85 -0
- package/dist/shared/services/ui/companion-runtime.service.d.ts +33 -0
- package/dist/shared/services/ui/companion-runtime.service.js +145 -0
- package/dist/shared/services/ui/local-ui-discovery.service.d.ts +19 -0
- package/dist/shared/services/ui/local-ui-discovery.service.js +41 -0
- package/dist/shared/services/ui/npm-runtime-update-host.service.d.ts +40 -0
- package/dist/shared/services/ui/npm-runtime-update-host.service.js +181 -0
- package/dist/shared/services/ui/runtime-control-host.service.d.ts +28 -0
- package/dist/shared/services/ui/runtime-control-host.service.js +89 -0
- package/dist/shared/services/ui/service-remote-access.service.d.ts +25 -0
- package/dist/shared/services/ui/service-remote-access.service.js +38 -0
- package/dist/shared/services/ui/ui-bridge-api.service.d.ts +16 -0
- package/dist/shared/services/ui/ui-bridge-api.service.js +43 -0
- package/dist/shared/services/workspace/workspace-manager.service.d.ts +19 -0
- package/dist/shared/services/workspace/workspace-manager.service.js +135 -0
- package/dist/shared/stores/companion-runtime.store.d.ts +15 -0
- package/dist/shared/stores/companion-runtime.store.js +27 -0
- package/dist/shared/stores/local-ui-runtime.store.d.ts +25 -0
- package/dist/shared/stores/local-ui-runtime.store.js +54 -0
- package/dist/shared/stores/managed-service-state.store.d.ts +28 -0
- package/dist/shared/stores/managed-service-state.store.js +38 -0
- package/dist/shared/stores/pending-restart.store.d.ts +21 -0
- package/dist/shared/stores/pending-restart.store.js +35 -0
- package/dist/shared/types/cli.types.d.ts +295 -0
- package/dist/shared/types/cli.types.js +1 -0
- package/dist/shared/utils/cli.utils.d.ts +34 -0
- package/dist/shared/utils/cli.utils.js +262 -0
- package/dist/shared/utils/config-path.d.ts +15 -0
- package/dist/shared/utils/config-path.js +167 -0
- package/dist/shared/utils/marketplace/cli-subcommand-launch.utils.d.ts +16 -0
- package/dist/shared/utils/marketplace/cli-subcommand-launch.utils.js +46 -0
- package/dist/shared/utils/marketplace/service-marketplace-helpers.utils.d.ts +9 -0
- package/dist/shared/utils/marketplace/service-marketplace-helpers.utils.js +33 -0
- package/dist/shared/utils/package/package-manifest.utils.d.ts +8 -0
- package/dist/shared/utils/package/package-manifest.utils.js +48 -0
- package/dist/shared/utils/runtime-helpers.d.ts +14 -0
- package/dist/shared/utils/runtime-helpers.js +26 -0
- package/dist/shared/utils/service-port-probe.utils.d.ts +41 -0
- package/dist/shared/utils/service-port-probe.utils.js +164 -0
- package/dist/shared/utils/startup-trace.d.ts +7 -0
- package/dist/shared/utils/startup-trace.js +37 -0
- package/dist/shared/utils/top-level-nextclaw-command-env.utils.d.ts +4 -0
- package/dist/shared/utils/top-level-nextclaw-command-env.utils.js +10 -0
- package/package.json +68 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { NpmRuntimeBundleManifestReader } from "./npm-runtime-bundle-manifest.service.js";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { cp, readdir, rename, rm } from "node:fs/promises";
|
|
5
|
+
//#region src/launcher/npm-runtime-bundle.service.ts
|
|
6
|
+
function shouldRetryInstallWithCopy(error) {
|
|
7
|
+
if (!error || typeof error !== "object") return false;
|
|
8
|
+
const code = "code" in error ? String(error.code) : "";
|
|
9
|
+
return code === "EXDEV" || code === "EPERM";
|
|
10
|
+
}
|
|
11
|
+
var NpmRuntimeBundleService = class {
|
|
12
|
+
manifestReader;
|
|
13
|
+
platform;
|
|
14
|
+
arch;
|
|
15
|
+
launcherVersion;
|
|
16
|
+
now;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
this.manifestReader = options.manifestReader ?? new NpmRuntimeBundleManifestReader();
|
|
20
|
+
this.platform = options.platform ?? process.platform;
|
|
21
|
+
this.arch = options.arch ?? process.arch;
|
|
22
|
+
this.launcherVersion = options.launcherVersion?.trim() || null;
|
|
23
|
+
this.now = options.now ?? Date.now;
|
|
24
|
+
}
|
|
25
|
+
resolveCurrentBundle = () => {
|
|
26
|
+
const pointer = this.options.layout.readCurrentPointer();
|
|
27
|
+
if (!pointer) return null;
|
|
28
|
+
return this.resolveVersion(pointer.version);
|
|
29
|
+
};
|
|
30
|
+
resolveVersion = (version) => {
|
|
31
|
+
const bundleDirectory = this.options.layout.getVersionDir(version);
|
|
32
|
+
const bundle = this.verifyBundle(bundleDirectory);
|
|
33
|
+
if (bundle.manifest.bundleVersion !== version) throw new Error(`runtime bundle version mismatch: pointer expects ${version} but manifest is ${bundle.manifest.bundleVersion}`);
|
|
34
|
+
return bundle;
|
|
35
|
+
};
|
|
36
|
+
installFromDirectory = async (sourceDirectory) => {
|
|
37
|
+
this.options.layout.ensureLauncherDirs();
|
|
38
|
+
const sourceBundle = this.verifyBundle(sourceDirectory);
|
|
39
|
+
const targetDirectory = this.options.layout.getVersionDir(sourceBundle.manifest.bundleVersion);
|
|
40
|
+
if (existsSync(targetDirectory)) return this.verifyBundle(targetDirectory);
|
|
41
|
+
try {
|
|
42
|
+
await rename(sourceDirectory, targetDirectory);
|
|
43
|
+
return this.verifyBundle(targetDirectory);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (!shouldRetryInstallWithCopy(error)) throw error;
|
|
46
|
+
}
|
|
47
|
+
const stagingDirectory = join(this.options.layout.getStagingDir(), `${sourceBundle.manifest.bundleVersion}-${this.now()}`);
|
|
48
|
+
await rm(stagingDirectory, {
|
|
49
|
+
recursive: true,
|
|
50
|
+
force: true
|
|
51
|
+
});
|
|
52
|
+
try {
|
|
53
|
+
await cp(sourceDirectory, stagingDirectory, { recursive: true });
|
|
54
|
+
await rename(stagingDirectory, targetDirectory);
|
|
55
|
+
return this.verifyBundle(targetDirectory);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
await rm(stagingDirectory, {
|
|
58
|
+
recursive: true,
|
|
59
|
+
force: true
|
|
60
|
+
});
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
activateVersion = (version) => {
|
|
65
|
+
this.resolveVersion(version);
|
|
66
|
+
const currentPointer = this.options.layout.readCurrentPointer();
|
|
67
|
+
if (currentPointer) this.options.layout.writePreviousPointer(currentPointer);
|
|
68
|
+
this.options.layout.writeCurrentPointer({ version });
|
|
69
|
+
this.options.stateStore.update((state) => ({
|
|
70
|
+
...state,
|
|
71
|
+
currentVersion: version,
|
|
72
|
+
previousVersion: currentPointer?.version ?? state.previousVersion,
|
|
73
|
+
candidateVersion: version,
|
|
74
|
+
candidateLaunchCount: 0,
|
|
75
|
+
downloadedVersion: null,
|
|
76
|
+
downloadedReleaseNotesUrl: null
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
pruneRetainedArtifacts = async () => {
|
|
80
|
+
this.options.layout.ensureLauncherDirs();
|
|
81
|
+
const state = this.options.stateStore.read();
|
|
82
|
+
const retained = new Set([
|
|
83
|
+
state.currentVersion,
|
|
84
|
+
state.previousVersion,
|
|
85
|
+
state.candidateVersion,
|
|
86
|
+
state.lastKnownGoodVersion,
|
|
87
|
+
state.downloadedVersion,
|
|
88
|
+
this.options.layout.readCurrentPointer()?.version,
|
|
89
|
+
this.options.layout.readPreviousPointer()?.version
|
|
90
|
+
].filter((version) => Boolean(version?.trim())));
|
|
91
|
+
const entries = await readdir(this.options.layout.getVersionsDir(), { withFileTypes: true });
|
|
92
|
+
for (const entry of entries.sort((left, right) => compareNpmRuntimeVersions(left.name, right.name))) {
|
|
93
|
+
if (!entry.isDirectory() || retained.has(entry.name)) continue;
|
|
94
|
+
await rm(join(this.options.layout.getVersionsDir(), entry.name), {
|
|
95
|
+
recursive: true,
|
|
96
|
+
force: true
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
await this.clearStagingDirectory();
|
|
100
|
+
};
|
|
101
|
+
clearStagingDirectory = async () => {
|
|
102
|
+
const entries = await readdir(this.options.layout.getStagingDir(), { withFileTypes: true });
|
|
103
|
+
await Promise.all(entries.map(async (entry) => await rm(join(this.options.layout.getStagingDir(), entry.name), {
|
|
104
|
+
recursive: true,
|
|
105
|
+
force: true
|
|
106
|
+
})));
|
|
107
|
+
};
|
|
108
|
+
verifyBundle = (bundleDirectory) => {
|
|
109
|
+
const manifest = this.manifestReader.readFile(resolve(bundleDirectory, "manifest.json"));
|
|
110
|
+
if (manifest.platform !== this.platform) throw new Error(`runtime bundle platform mismatch: expected ${this.platform} but got ${manifest.platform}`);
|
|
111
|
+
if (manifest.arch !== this.arch) throw new Error(`runtime bundle arch mismatch: expected ${this.arch} but got ${manifest.arch}`);
|
|
112
|
+
if (this.launcherVersion && compareNpmRuntimeVersions(this.launcherVersion, manifest.launcherCompatibility.minVersion) < 0) throw new Error(`runtime bundle requires launcher >= ${manifest.launcherCompatibility.minVersion} but current launcher is ${this.launcherVersion}`);
|
|
113
|
+
const runtimeScriptPath = resolve(bundleDirectory, manifest.entrypoints.runtimeScript);
|
|
114
|
+
if (!existsSync(runtimeScriptPath)) throw new Error(`runtime bundle script missing: ${runtimeScriptPath}`);
|
|
115
|
+
return {
|
|
116
|
+
bundleDirectory,
|
|
117
|
+
manifest,
|
|
118
|
+
runtimeScriptPath
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
function compareNpmRuntimeVersions(left, right) {
|
|
123
|
+
const leftParts = parseVersionParts(left);
|
|
124
|
+
const rightParts = parseVersionParts(right);
|
|
125
|
+
const length = Math.max(leftParts.length, rightParts.length);
|
|
126
|
+
for (let index = 0; index < length; index += 1) {
|
|
127
|
+
const leftPart = leftParts[index] ?? 0;
|
|
128
|
+
const rightPart = rightParts[index] ?? 0;
|
|
129
|
+
if (leftPart !== rightPart) return leftPart - rightPart;
|
|
130
|
+
}
|
|
131
|
+
return left.localeCompare(right);
|
|
132
|
+
}
|
|
133
|
+
function resolveEffectiveNpmRuntimeVersion(params) {
|
|
134
|
+
const launcherVersion = params.launcherVersion?.trim() || null;
|
|
135
|
+
const currentBundleVersion = params.currentBundleVersion?.trim() || null;
|
|
136
|
+
if (!launcherVersion) return currentBundleVersion;
|
|
137
|
+
if (!currentBundleVersion) return launcherVersion;
|
|
138
|
+
return compareNpmRuntimeVersions(launcherVersion, currentBundleVersion) > 0 ? launcherVersion : currentBundleVersion;
|
|
139
|
+
}
|
|
140
|
+
function shouldPreferPackagedNpmRuntime(params) {
|
|
141
|
+
const launcherVersion = params.launcherVersion?.trim() || null;
|
|
142
|
+
const currentBundleVersion = params.currentBundleVersion?.trim() || null;
|
|
143
|
+
if (!launcherVersion || !currentBundleVersion) return false;
|
|
144
|
+
return resolveEffectiveNpmRuntimeVersion(params) === launcherVersion;
|
|
145
|
+
}
|
|
146
|
+
function parseVersionParts(version) {
|
|
147
|
+
return version.split(/[.-]/).map((part) => Number(part)).map((part) => Number.isFinite(part) ? part : 0);
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
export { NpmRuntimeBundleService, compareNpmRuntimeVersions, resolveEffectiveNpmRuntimeVersion, shouldPreferPackagedNpmRuntime };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { UpdateManifest, UpdateProgress, UpdateSnapshot } from "@nextclaw/kernel/update-contract";
|
|
2
|
+
|
|
3
|
+
//#region src/launcher/npm-runtime-bundle.types.d.ts
|
|
4
|
+
type NpmRuntimeBundleManifest = {
|
|
5
|
+
bundleVersion: string;
|
|
6
|
+
platform: string;
|
|
7
|
+
arch: string;
|
|
8
|
+
uiVersion: string;
|
|
9
|
+
runtimeVersion: string;
|
|
10
|
+
builtInPluginSetVersion: string;
|
|
11
|
+
launcherCompatibility: {
|
|
12
|
+
minVersion: string;
|
|
13
|
+
};
|
|
14
|
+
entrypoints: {
|
|
15
|
+
runtimeScript: string;
|
|
16
|
+
};
|
|
17
|
+
migrationVersion: number;
|
|
18
|
+
};
|
|
19
|
+
type NpmRuntimeBundlePointer = {
|
|
20
|
+
version: string;
|
|
21
|
+
};
|
|
22
|
+
type NpmRuntimeUpdateState = {
|
|
23
|
+
channel: "stable" | "beta";
|
|
24
|
+
currentVersion: string | null;
|
|
25
|
+
previousVersion: string | null;
|
|
26
|
+
candidateVersion: string | null;
|
|
27
|
+
candidateLaunchCount: number;
|
|
28
|
+
lastKnownGoodVersion: string | null;
|
|
29
|
+
badVersions: string[];
|
|
30
|
+
lastUpdateCheckAt: string | null;
|
|
31
|
+
downloadedVersion: string | null;
|
|
32
|
+
downloadedReleaseNotesUrl: string | null;
|
|
33
|
+
updatePreferences: {
|
|
34
|
+
automaticChecks: boolean;
|
|
35
|
+
autoDownload: boolean;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
type NpmRuntimeDownloadedUpdate = {
|
|
39
|
+
manifest: UpdateManifest;
|
|
40
|
+
downloadedVersion: string;
|
|
41
|
+
bundleDirectory: string;
|
|
42
|
+
};
|
|
43
|
+
type NpmRuntimeUpdateProgressReporter = (progress: UpdateProgress) => void;
|
|
44
|
+
type NpmRuntimeUpdateCommandResult = {
|
|
45
|
+
snapshot: UpdateSnapshot;
|
|
46
|
+
message: string;
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
export { NpmRuntimeBundleManifest, NpmRuntimeBundlePointer, NpmRuntimeDownloadedUpdate, NpmRuntimeUpdateCommandResult, NpmRuntimeUpdateProgressReporter, NpmRuntimeUpdateState };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NpmRuntimeBundleLayoutStore } from "./npm-runtime-bundle-layout.store.js";
|
|
2
|
+
|
|
3
|
+
//#region src/launcher/npm-runtime-launcher.service.d.ts
|
|
4
|
+
type NpmRuntimeLauncherOptions = {
|
|
5
|
+
argv: string[];
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
layout?: NpmRuntimeBundleLayoutStore;
|
|
8
|
+
};
|
|
9
|
+
declare class NpmRuntimeLauncher {
|
|
10
|
+
private readonly options;
|
|
11
|
+
private readonly env;
|
|
12
|
+
private readonly layout;
|
|
13
|
+
constructor(options: NpmRuntimeLauncherOptions);
|
|
14
|
+
run: () => never;
|
|
15
|
+
private resolveRuntimeScriptPath;
|
|
16
|
+
private resolvePackagedAppEntrypoint;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { NpmRuntimeLauncher };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { NpmRuntimeBundleLayoutStore } from "./npm-runtime-bundle-layout.store.js";
|
|
2
|
+
import { NpmRuntimeBundleService, shouldPreferPackagedNpmRuntime } from "./npm-runtime-bundle.service.js";
|
|
3
|
+
import { inferDefaultNpmRuntimeReleaseChannel } from "./npm-runtime-update-source.service.js";
|
|
4
|
+
import { NpmRuntimeUpdateStateStore } from "./npm-runtime-update-state.store.js";
|
|
5
|
+
import { getPackageVersion as getPackageVersion$1 } from "../shared/utils/package/package-manifest.utils.js";
|
|
6
|
+
import "../shared/utils/cli.utils.js";
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { dirname, resolve } from "node:path";
|
|
10
|
+
import { createExternalCommandEnv } from "@nextclaw/core";
|
|
11
|
+
//#region src/launcher/npm-runtime-launcher.service.ts
|
|
12
|
+
var NpmRuntimeLauncher = class {
|
|
13
|
+
env;
|
|
14
|
+
layout;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.options = options;
|
|
17
|
+
this.env = options.env ?? process.env;
|
|
18
|
+
this.layout = options.layout ?? new NpmRuntimeBundleLayoutStore();
|
|
19
|
+
}
|
|
20
|
+
run = () => {
|
|
21
|
+
const runtimeScriptPath = this.resolveRuntimeScriptPath();
|
|
22
|
+
const result = spawnSync(process.execPath, [runtimeScriptPath, ...this.options.argv.slice(2)], {
|
|
23
|
+
stdio: "inherit",
|
|
24
|
+
env: {
|
|
25
|
+
...createExternalCommandEnv(this.env),
|
|
26
|
+
NEXTCLAW_RUNTIME_BUNDLE_CHILD: "1"
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
process.exit(typeof result.status === "number" ? result.status : 1);
|
|
30
|
+
};
|
|
31
|
+
resolveRuntimeScriptPath = () => {
|
|
32
|
+
if (this.env.NEXTCLAW_DISABLE_RUNTIME_BUNDLE_LAUNCHER === "1" || this.env.NEXTCLAW_RUNTIME_BUNDLE_CHILD === "1") return this.resolvePackagedAppEntrypoint();
|
|
33
|
+
const stateStore = new NpmRuntimeUpdateStateStore(this.layout.getStatePath(), { defaultChannel: inferDefaultNpmRuntimeReleaseChannel(getPackageVersion$1()) });
|
|
34
|
+
const bundleService = new NpmRuntimeBundleService({
|
|
35
|
+
layout: this.layout,
|
|
36
|
+
stateStore,
|
|
37
|
+
launcherVersion: getPackageVersion$1()
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
const currentBundle = bundleService.resolveCurrentBundle();
|
|
41
|
+
if (currentBundle && shouldPreferPackagedNpmRuntime({
|
|
42
|
+
launcherVersion: getPackageVersion$1(),
|
|
43
|
+
currentBundleVersion: currentBundle.manifest.runtimeVersion ?? currentBundle.manifest.bundleVersion
|
|
44
|
+
})) return this.resolvePackagedAppEntrypoint();
|
|
45
|
+
return currentBundle?.runtimeScriptPath ?? this.resolvePackagedAppEntrypoint();
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(`Cannot start current runtime bundle: ${error instanceof Error ? error.message : String(error)}`);
|
|
48
|
+
console.error("Falling back to the packaged npm launcher runtime.");
|
|
49
|
+
return this.resolvePackagedAppEntrypoint();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
resolvePackagedAppEntrypoint = () => {
|
|
53
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), "../app/index.js");
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
export { NpmRuntimeLauncher };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { UpdateCommandOptions } from "../shared/types/cli.types.js";
|
|
2
|
+
import { UpdateSnapshot } from "@nextclaw/kernel/update-contract";
|
|
3
|
+
|
|
4
|
+
//#region src/launcher/npm-runtime-update-command.service.d.ts
|
|
5
|
+
declare class NpmRuntimeUpdateCommandService {
|
|
6
|
+
run: (opts: UpdateCommandOptions) => Promise<UpdateSnapshot>;
|
|
7
|
+
runManaged: (opts: UpdateCommandOptions) => Promise<UpdateSnapshot>;
|
|
8
|
+
private printProgress;
|
|
9
|
+
private printSnapshot;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { NpmRuntimeUpdateCommandService };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { NpmRuntimeBundleLayoutStore } from "./npm-runtime-bundle-layout.store.js";
|
|
2
|
+
import { NpmRuntimeBundleService } from "./npm-runtime-bundle.service.js";
|
|
3
|
+
import { NpmRuntimeUpdateSourceService } from "./npm-runtime-update-source.service.js";
|
|
4
|
+
import { NpmRuntimeUpdateStateStore } from "./npm-runtime-update-state.store.js";
|
|
5
|
+
import { getPackageVersion } from "../shared/utils/package/package-manifest.utils.js";
|
|
6
|
+
import "../shared/utils/cli.utils.js";
|
|
7
|
+
import { NpmRuntimeUpdateManager } from "./npm-runtime-update.manager.js";
|
|
8
|
+
import { NpmRuntimeUpdateService } from "./npm-runtime-update.service.js";
|
|
9
|
+
//#region src/launcher/npm-runtime-update-command.service.ts
|
|
10
|
+
var NpmRuntimeUpdateCommandService = class {
|
|
11
|
+
run = async (opts) => {
|
|
12
|
+
const snapshot = await this.runManaged(opts);
|
|
13
|
+
if (opts.json) console.log(JSON.stringify(snapshot, null, 2));
|
|
14
|
+
else this.printSnapshot(snapshot);
|
|
15
|
+
return snapshot;
|
|
16
|
+
};
|
|
17
|
+
runManaged = async (opts) => {
|
|
18
|
+
const source = new NpmRuntimeUpdateSourceService();
|
|
19
|
+
const launcherVersion = getPackageVersion();
|
|
20
|
+
const channel = source.resolveChannel(opts.channel, launcherVersion);
|
|
21
|
+
const manifestUrl = source.resolveManifestUrl(channel, opts.manifestUrl);
|
|
22
|
+
const layout = new NpmRuntimeBundleLayoutStore();
|
|
23
|
+
const stateStore = new NpmRuntimeUpdateStateStore(layout.getStatePath(), { defaultChannel: channel });
|
|
24
|
+
const bundleService = new NpmRuntimeBundleService({
|
|
25
|
+
layout,
|
|
26
|
+
stateStore,
|
|
27
|
+
launcherVersion
|
|
28
|
+
});
|
|
29
|
+
return await new NpmRuntimeUpdateManager({
|
|
30
|
+
layout,
|
|
31
|
+
stateStore,
|
|
32
|
+
bundleService,
|
|
33
|
+
updateService: new NpmRuntimeUpdateService({
|
|
34
|
+
layout,
|
|
35
|
+
bundleService,
|
|
36
|
+
launcherVersion,
|
|
37
|
+
bundlePublicKey: source.resolveBundlePublicKey() ?? void 0
|
|
38
|
+
}),
|
|
39
|
+
resolveManifestUrl: () => manifestUrl,
|
|
40
|
+
launcherVersion,
|
|
41
|
+
channel
|
|
42
|
+
}).run({
|
|
43
|
+
apply: Boolean(opts.apply),
|
|
44
|
+
checkOnly: Boolean(opts.check),
|
|
45
|
+
download: opts.download === void 0 ? true : Boolean(opts.download),
|
|
46
|
+
onProgress: opts.json ? void 0 : this.printProgress
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
printProgress = (progress) => {
|
|
50
|
+
const percent = progress.percent === null ? "" : ` ${progress.percent}%`;
|
|
51
|
+
const total = progress.totalBytes === null ? "" : ` / ${progress.totalBytes} bytes`;
|
|
52
|
+
process.stdout.write(`\rDownloading${percent} (${progress.downloadedBytes} bytes${total})`);
|
|
53
|
+
if (progress.percent === 100) process.stdout.write("\n");
|
|
54
|
+
};
|
|
55
|
+
printSnapshot = (snapshot) => {
|
|
56
|
+
if (snapshot.status === "blocked") {
|
|
57
|
+
console.error(`Update blocked: ${snapshot.errorMessage ?? snapshot.blockReason ?? "unknown reason"}`);
|
|
58
|
+
if (snapshot.recoveryCommand) console.error(`Recovery: ${snapshot.recoveryCommand}`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (snapshot.status === "failed") {
|
|
62
|
+
console.error(`Update failed: ${snapshot.errorMessage ?? "unknown error"}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (snapshot.status === "up-to-date") {
|
|
66
|
+
console.log(`NextClaw runtime is already up to date (${snapshot.currentVersion ?? snapshot.hostVersion ?? "unknown"}).`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (snapshot.status === "downloaded") {
|
|
70
|
+
console.log(`Runtime update downloaded: ${snapshot.downloadedVersion ?? snapshot.availableVersion}`);
|
|
71
|
+
console.log("Run `nextclaw update --apply` to switch to the downloaded runtime.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (snapshot.status === "restart-required") {
|
|
75
|
+
console.log(`Runtime update applied: ${snapshot.currentVersion}`);
|
|
76
|
+
console.log("Restart the running NextClaw service or start a new CLI process to use it.");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (snapshot.status === "update-available") {
|
|
80
|
+
console.log(`Runtime update available: ${snapshot.currentVersion ?? "none"} -> ${snapshot.availableVersion}`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
console.log(`Update status: ${snapshot.status}`);
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
//#endregion
|
|
87
|
+
export { NpmRuntimeUpdateCommandService };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/launcher/npm-runtime-update-source.service.d.ts
|
|
2
|
+
type NpmRuntimeReleaseChannel = "stable" | "beta";
|
|
3
|
+
type NpmRuntimeUpdateSourceServiceOptions = {
|
|
4
|
+
env?: NodeJS.ProcessEnv;
|
|
5
|
+
platform?: NodeJS.Platform;
|
|
6
|
+
arch?: string;
|
|
7
|
+
};
|
|
8
|
+
declare function inferDefaultNpmRuntimeReleaseChannel(launcherVersion?: string | null): NpmRuntimeReleaseChannel;
|
|
9
|
+
declare class NpmRuntimeUpdateSourceService {
|
|
10
|
+
private readonly env;
|
|
11
|
+
private readonly platform;
|
|
12
|
+
private readonly arch;
|
|
13
|
+
constructor(options?: NpmRuntimeUpdateSourceServiceOptions);
|
|
14
|
+
resolveChannel: (explicitChannel?: unknown, launcherVersion?: string | null) => NpmRuntimeReleaseChannel;
|
|
15
|
+
resolveManifestUrl: (channel: NpmRuntimeReleaseChannel, explicitManifestUrl?: unknown) => string | null;
|
|
16
|
+
resolveBundlePublicKey: () => string | null;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { NpmRuntimeReleaseChannel, NpmRuntimeUpdateSourceService, inferDefaultNpmRuntimeReleaseChannel };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
//#region src/launcher/npm-runtime-update-source.service.ts
|
|
5
|
+
const DEFAULT_NPM_RUNTIME_UPDATE_BASE_URL = "https://Peiiii.github.io/nextclaw/npm-runtime-updates";
|
|
6
|
+
function normalizeOptionalString(value) {
|
|
7
|
+
if (typeof value !== "string") return null;
|
|
8
|
+
const trimmed = value.trim();
|
|
9
|
+
return trimmed ? trimmed : null;
|
|
10
|
+
}
|
|
11
|
+
function normalizeChannel(value) {
|
|
12
|
+
return typeof value === "string" && value.trim().toLowerCase() === "beta" ? "beta" : "stable";
|
|
13
|
+
}
|
|
14
|
+
function inferDefaultNpmRuntimeReleaseChannel(launcherVersion) {
|
|
15
|
+
return typeof launcherVersion === "string" && launcherVersion.toLowerCase().includes("-beta") ? "beta" : "stable";
|
|
16
|
+
}
|
|
17
|
+
function resolvePackagedPublicKeyPath() {
|
|
18
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const candidates = [
|
|
20
|
+
resolve(moduleDir, "..", "resources", "update-bundle-public.pem"),
|
|
21
|
+
resolve(moduleDir, "../../..", "resources", "update-bundle-public.pem"),
|
|
22
|
+
resolve(moduleDir, "../../../..", "resources", "update-bundle-public.pem")
|
|
23
|
+
];
|
|
24
|
+
return candidates.find((candidate) => existsSync(candidate)) ?? candidates[0];
|
|
25
|
+
}
|
|
26
|
+
var NpmRuntimeUpdateSourceService = class {
|
|
27
|
+
env;
|
|
28
|
+
platform;
|
|
29
|
+
arch;
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
this.env = options.env ?? process.env;
|
|
32
|
+
this.platform = options.platform ?? process.platform;
|
|
33
|
+
this.arch = options.arch ?? process.arch;
|
|
34
|
+
}
|
|
35
|
+
resolveChannel = (explicitChannel, launcherVersion) => {
|
|
36
|
+
if (explicitChannel !== void 0 || this.env.NEXTCLAW_UPDATE_CHANNEL !== void 0) return normalizeChannel(explicitChannel ?? this.env.NEXTCLAW_UPDATE_CHANNEL);
|
|
37
|
+
return inferDefaultNpmRuntimeReleaseChannel(launcherVersion);
|
|
38
|
+
};
|
|
39
|
+
resolveManifestUrl = (channel, explicitManifestUrl) => {
|
|
40
|
+
const manifestUrl = normalizeOptionalString(explicitManifestUrl) ?? normalizeOptionalString(this.env.NEXTCLAW_UPDATE_MANIFEST_URL);
|
|
41
|
+
if (manifestUrl) return manifestUrl;
|
|
42
|
+
const baseUrl = normalizeOptionalString(this.env.NEXTCLAW_UPDATE_MANIFEST_BASE_URL) ?? DEFAULT_NPM_RUNTIME_UPDATE_BASE_URL;
|
|
43
|
+
return new URL(`${channel}/manifest-${channel}-${this.platform}-${this.arch}.json`, `${baseUrl.replace(/\/+$/, "")}/`).toString();
|
|
44
|
+
};
|
|
45
|
+
resolveBundlePublicKey = () => {
|
|
46
|
+
const explicitPublicKey = normalizeOptionalString(this.env.NEXTCLAW_UPDATE_BUNDLE_PUBLIC_KEY);
|
|
47
|
+
if (explicitPublicKey) return explicitPublicKey;
|
|
48
|
+
const publicKeyPath = normalizeOptionalString(this.env.NEXTCLAW_UPDATE_BUNDLE_PUBLIC_KEY_PATH);
|
|
49
|
+
if (!publicKeyPath || !existsSync(publicKeyPath)) {
|
|
50
|
+
const packagedPublicKeyPath = resolvePackagedPublicKeyPath();
|
|
51
|
+
return existsSync(packagedPublicKeyPath) ? readFileSync(packagedPublicKeyPath, "utf8").trim() : null;
|
|
52
|
+
}
|
|
53
|
+
return readFileSync(publicKeyPath, "utf8").trim();
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
export { NpmRuntimeUpdateSourceService, inferDefaultNpmRuntimeReleaseChannel };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NpmRuntimeUpdateState } from "./npm-runtime-bundle.types.js";
|
|
2
|
+
import { NpmRuntimeReleaseChannel } from "./npm-runtime-update-source.service.js";
|
|
3
|
+
|
|
4
|
+
//#region src/launcher/npm-runtime-update-state.store.d.ts
|
|
5
|
+
type NpmRuntimeUpdateStateStoreOptions = {
|
|
6
|
+
defaultChannel?: NpmRuntimeReleaseChannel;
|
|
7
|
+
};
|
|
8
|
+
declare class NpmRuntimeUpdateStateStore {
|
|
9
|
+
private readonly statePath;
|
|
10
|
+
private readonly defaultChannel;
|
|
11
|
+
constructor(statePath: string, options?: NpmRuntimeUpdateStateStoreOptions);
|
|
12
|
+
read: () => NpmRuntimeUpdateState;
|
|
13
|
+
write: (state: NpmRuntimeUpdateState) => void;
|
|
14
|
+
update: (updater: (state: NpmRuntimeUpdateState) => NpmRuntimeUpdateState) => NpmRuntimeUpdateState;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { NpmRuntimeUpdateStateStore };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { dirname } from "node:path";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
//#region src/launcher/npm-runtime-update-state.store.ts
|
|
4
|
+
function createDefaultState(channel) {
|
|
5
|
+
return {
|
|
6
|
+
channel,
|
|
7
|
+
currentVersion: null,
|
|
8
|
+
previousVersion: null,
|
|
9
|
+
candidateVersion: null,
|
|
10
|
+
candidateLaunchCount: 0,
|
|
11
|
+
lastKnownGoodVersion: null,
|
|
12
|
+
badVersions: [],
|
|
13
|
+
lastUpdateCheckAt: null,
|
|
14
|
+
downloadedVersion: null,
|
|
15
|
+
downloadedReleaseNotesUrl: null,
|
|
16
|
+
updatePreferences: {
|
|
17
|
+
automaticChecks: true,
|
|
18
|
+
autoDownload: true
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function normalizeOptionalString(value) {
|
|
23
|
+
if (typeof value !== "string") return null;
|
|
24
|
+
const trimmed = value.trim();
|
|
25
|
+
return trimmed ? trimmed : null;
|
|
26
|
+
}
|
|
27
|
+
function normalizeChannel(value, fallback) {
|
|
28
|
+
if (typeof value !== "string") return fallback;
|
|
29
|
+
const trimmed = value.trim().toLowerCase();
|
|
30
|
+
if (trimmed === "beta") return "beta";
|
|
31
|
+
if (trimmed === "stable") return "stable";
|
|
32
|
+
return fallback;
|
|
33
|
+
}
|
|
34
|
+
function normalizeStringArray(value) {
|
|
35
|
+
if (!Array.isArray(value)) return [];
|
|
36
|
+
return [...new Set(value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean))];
|
|
37
|
+
}
|
|
38
|
+
function normalizeUpdatePreferences(value) {
|
|
39
|
+
const defaultState = createDefaultState("stable");
|
|
40
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return { ...defaultState.updatePreferences };
|
|
41
|
+
const record = value;
|
|
42
|
+
return {
|
|
43
|
+
automaticChecks: typeof record.automaticChecks === "boolean" ? record.automaticChecks : defaultState.updatePreferences.automaticChecks,
|
|
44
|
+
autoDownload: typeof record.autoDownload === "boolean" ? record.autoDownload : defaultState.updatePreferences.autoDownload
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function normalizeState(input, defaultChannel) {
|
|
48
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error("npm runtime update state must be an object");
|
|
49
|
+
const record = input;
|
|
50
|
+
const candidateLaunchCount = Number(record.candidateLaunchCount);
|
|
51
|
+
return {
|
|
52
|
+
channel: normalizeChannel(record.channel, defaultChannel),
|
|
53
|
+
currentVersion: normalizeOptionalString(record.currentVersion),
|
|
54
|
+
previousVersion: normalizeOptionalString(record.previousVersion),
|
|
55
|
+
candidateVersion: normalizeOptionalString(record.candidateVersion),
|
|
56
|
+
candidateLaunchCount: Number.isInteger(candidateLaunchCount) && candidateLaunchCount >= 0 ? candidateLaunchCount : 0,
|
|
57
|
+
lastKnownGoodVersion: normalizeOptionalString(record.lastKnownGoodVersion),
|
|
58
|
+
badVersions: normalizeStringArray(record.badVersions),
|
|
59
|
+
lastUpdateCheckAt: normalizeOptionalString(record.lastUpdateCheckAt),
|
|
60
|
+
downloadedVersion: normalizeOptionalString(record.downloadedVersion),
|
|
61
|
+
downloadedReleaseNotesUrl: normalizeOptionalString(record.downloadedReleaseNotesUrl),
|
|
62
|
+
updatePreferences: normalizeUpdatePreferences(record.updatePreferences)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
var NpmRuntimeUpdateStateStore = class {
|
|
66
|
+
defaultChannel;
|
|
67
|
+
constructor(statePath, options = {}) {
|
|
68
|
+
this.statePath = statePath;
|
|
69
|
+
this.defaultChannel = options.defaultChannel ?? "stable";
|
|
70
|
+
}
|
|
71
|
+
read = () => {
|
|
72
|
+
if (!existsSync(this.statePath)) {
|
|
73
|
+
const defaultState = createDefaultState(this.defaultChannel);
|
|
74
|
+
return {
|
|
75
|
+
...defaultState,
|
|
76
|
+
updatePreferences: { ...defaultState.updatePreferences }
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return normalizeState(JSON.parse(readFileSync(this.statePath, "utf8")), this.defaultChannel);
|
|
80
|
+
};
|
|
81
|
+
write = (state) => {
|
|
82
|
+
mkdirSync(dirname(this.statePath), { recursive: true });
|
|
83
|
+
writeFileSync(this.statePath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
|
|
84
|
+
};
|
|
85
|
+
update = (updater) => {
|
|
86
|
+
const nextState = updater(this.read());
|
|
87
|
+
this.write(nextState);
|
|
88
|
+
return nextState;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
//#endregion
|
|
92
|
+
export { NpmRuntimeUpdateStateStore };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { NpmRuntimeBundleLayoutStore } from "./npm-runtime-bundle-layout.store.js";
|
|
2
|
+
import { NpmRuntimeReleaseChannel } from "./npm-runtime-update-source.service.js";
|
|
3
|
+
import { NpmRuntimeUpdateStateStore } from "./npm-runtime-update-state.store.js";
|
|
4
|
+
import { NpmRuntimeBundleService } from "./npm-runtime-bundle.service.js";
|
|
5
|
+
import { NpmRuntimeUpdateService } from "./npm-runtime-update.service.js";
|
|
6
|
+
import { UpdateProgress, UpdateSnapshot } from "@nextclaw/kernel/update-contract";
|
|
7
|
+
|
|
8
|
+
//#region src/launcher/npm-runtime-update.manager.d.ts
|
|
9
|
+
type NpmRuntimeUpdateManagerOptions = {
|
|
10
|
+
layout: NpmRuntimeBundleLayoutStore;
|
|
11
|
+
stateStore: NpmRuntimeUpdateStateStore;
|
|
12
|
+
bundleService: NpmRuntimeBundleService;
|
|
13
|
+
updateService: NpmRuntimeUpdateService;
|
|
14
|
+
resolveManifestUrl: (channel: NpmRuntimeReleaseChannel) => string | null;
|
|
15
|
+
launcherVersion?: string;
|
|
16
|
+
channel: NpmRuntimeReleaseChannel;
|
|
17
|
+
now?: () => Date;
|
|
18
|
+
};
|
|
19
|
+
type NpmRuntimeUpdateActionOptions = {
|
|
20
|
+
download?: boolean;
|
|
21
|
+
apply?: boolean;
|
|
22
|
+
checkOnly?: boolean;
|
|
23
|
+
onProgress?: (progress: UpdateProgress) => void;
|
|
24
|
+
};
|
|
25
|
+
declare class NpmRuntimeUpdateManager {
|
|
26
|
+
private readonly options;
|
|
27
|
+
private readonly launcherVersion;
|
|
28
|
+
private readonly now;
|
|
29
|
+
private availableManifest;
|
|
30
|
+
constructor(options: NpmRuntimeUpdateManagerOptions);
|
|
31
|
+
getSnapshot: () => UpdateSnapshot;
|
|
32
|
+
run: (options?: NpmRuntimeUpdateActionOptions) => Promise<UpdateSnapshot>;
|
|
33
|
+
checkForUpdate: () => Promise<UpdateSnapshot>;
|
|
34
|
+
downloadUpdate: (onProgress?: (progress: UpdateProgress) => void) => Promise<UpdateSnapshot>;
|
|
35
|
+
applyDownloadedUpdate: () => UpdateSnapshot;
|
|
36
|
+
private ensureAvailableManifest;
|
|
37
|
+
private toSnapshotAfterCheck;
|
|
38
|
+
private syncStateFromCurrentPointer;
|
|
39
|
+
private toSnapshotFromState;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { NpmRuntimeUpdateManager };
|