@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,162 @@
|
|
|
1
|
+
import { buildReservedPluginLoadOptions } from "./plugin-command-utils.js";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { expandHome, getWorkspacePath, loadConfig, saveConfig } from "@nextclaw/core";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { addPluginLoadPath, buildPluginStatusReport, disablePluginInConfig, enablePluginInConfig, installPluginFromNpmSpec, installPluginFromPath, recordPluginInstall, uninstallPlugin } from "@nextclaw/openclaw-compat";
|
|
6
|
+
//#region src/commands/plugin/plugin-mutation-actions.ts
|
|
7
|
+
const pluginInstallLogger = {
|
|
8
|
+
info: (message) => console.log(message),
|
|
9
|
+
warn: (message) => console.warn(message)
|
|
10
|
+
};
|
|
11
|
+
function resolveFileNpmSpecToLocalPath(raw) {
|
|
12
|
+
const trimmed = raw.trim();
|
|
13
|
+
if (!trimmed.toLowerCase().startsWith("file:")) return null;
|
|
14
|
+
const rest = trimmed.slice(5);
|
|
15
|
+
if (!rest) return {
|
|
16
|
+
ok: false,
|
|
17
|
+
error: "unsupported file: spec: missing path"
|
|
18
|
+
};
|
|
19
|
+
if (rest.startsWith("///")) return {
|
|
20
|
+
ok: true,
|
|
21
|
+
path: rest.slice(2)
|
|
22
|
+
};
|
|
23
|
+
if (rest.startsWith("//localhost/")) return {
|
|
24
|
+
ok: true,
|
|
25
|
+
path: rest.slice(11)
|
|
26
|
+
};
|
|
27
|
+
if (rest.startsWith("//")) return {
|
|
28
|
+
ok: false,
|
|
29
|
+
error: "unsupported file: URL host (expected \"file:<path>\" or \"file:///abs/path\")"
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
ok: true,
|
|
33
|
+
path: rest
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function looksLikePath(raw) {
|
|
37
|
+
return raw.startsWith(".") || raw.startsWith("~") || raw.startsWith("/") || raw.endsWith(".ts") || raw.endsWith(".js") || raw.endsWith(".mjs") || raw.endsWith(".cjs") || raw.endsWith(".tgz") || raw.endsWith(".tar.gz") || raw.endsWith(".tar") || raw.endsWith(".zip");
|
|
38
|
+
}
|
|
39
|
+
function isArchivePath(filePath) {
|
|
40
|
+
const lower = filePath.toLowerCase();
|
|
41
|
+
return lower.endsWith(".zip") || lower.endsWith(".tgz") || lower.endsWith(".tar.gz") || lower.endsWith(".tar");
|
|
42
|
+
}
|
|
43
|
+
function saveLinkedPluginInstall(config, params) {
|
|
44
|
+
let next = addPluginLoadPath(config, params.resolvedPath);
|
|
45
|
+
next = enablePluginInConfig(next, params.pluginId);
|
|
46
|
+
next = recordPluginInstall(next, {
|
|
47
|
+
pluginId: params.pluginId,
|
|
48
|
+
source: "path",
|
|
49
|
+
sourcePath: params.resolvedPath,
|
|
50
|
+
installPath: params.resolvedPath,
|
|
51
|
+
version: params.version ?? void 0
|
|
52
|
+
});
|
|
53
|
+
saveConfig(next);
|
|
54
|
+
return { message: `Linked plugin path: ${params.resolvedPath}` };
|
|
55
|
+
}
|
|
56
|
+
function saveInstalledPluginResult(config, params) {
|
|
57
|
+
let next = enablePluginInConfig(config, params.pluginId);
|
|
58
|
+
next = recordPluginInstall(next, {
|
|
59
|
+
pluginId: params.pluginId,
|
|
60
|
+
source: params.source,
|
|
61
|
+
sourcePath: params.sourcePath,
|
|
62
|
+
spec: params.spec,
|
|
63
|
+
installPath: params.installPath,
|
|
64
|
+
version: params.version ?? void 0
|
|
65
|
+
});
|
|
66
|
+
saveConfig(next);
|
|
67
|
+
return { message: `Installed plugin: ${params.pluginId}` };
|
|
68
|
+
}
|
|
69
|
+
async function installPluginFromLocalPath(config, resolvedPath, link) {
|
|
70
|
+
if (link) {
|
|
71
|
+
const probe = await installPluginFromPath({
|
|
72
|
+
path: resolvedPath,
|
|
73
|
+
dryRun: true
|
|
74
|
+
});
|
|
75
|
+
if (!probe.ok) throw new Error(probe.error);
|
|
76
|
+
return saveLinkedPluginInstall(config, {
|
|
77
|
+
resolvedPath,
|
|
78
|
+
pluginId: probe.pluginId,
|
|
79
|
+
version: probe.version
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const result = await installPluginFromPath({
|
|
83
|
+
path: resolvedPath,
|
|
84
|
+
logger: pluginInstallLogger
|
|
85
|
+
});
|
|
86
|
+
if (!result.ok) throw new Error(result.error);
|
|
87
|
+
return saveInstalledPluginResult(config, {
|
|
88
|
+
pluginId: result.pluginId,
|
|
89
|
+
source: isArchivePath(resolvedPath) ? "archive" : "path",
|
|
90
|
+
sourcePath: resolvedPath,
|
|
91
|
+
installPath: result.targetDir,
|
|
92
|
+
version: result.version
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
async function installPluginFromRegistrySpec(config, spec) {
|
|
96
|
+
const result = await installPluginFromNpmSpec({
|
|
97
|
+
spec,
|
|
98
|
+
logger: pluginInstallLogger
|
|
99
|
+
});
|
|
100
|
+
if (!result.ok) throw new Error(result.error);
|
|
101
|
+
return saveInstalledPluginResult(config, {
|
|
102
|
+
pluginId: result.pluginId,
|
|
103
|
+
source: "npm",
|
|
104
|
+
spec,
|
|
105
|
+
installPath: result.targetDir,
|
|
106
|
+
version: result.version
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async function enablePluginMutation(id) {
|
|
110
|
+
saveConfig(enablePluginInConfig(loadConfig(), id));
|
|
111
|
+
return { message: `Enabled plugin "${id}".` };
|
|
112
|
+
}
|
|
113
|
+
async function disablePluginMutation(id) {
|
|
114
|
+
saveConfig(disablePluginInConfig(loadConfig(), id));
|
|
115
|
+
return { message: `Disabled plugin "${id}".` };
|
|
116
|
+
}
|
|
117
|
+
async function uninstallPluginMutation(id, opts = {}) {
|
|
118
|
+
const config = loadConfig();
|
|
119
|
+
const report = buildPluginStatusReport({
|
|
120
|
+
config,
|
|
121
|
+
workspaceDir: getWorkspacePath(config.agents.defaults.workspace),
|
|
122
|
+
...buildReservedPluginLoadOptions()
|
|
123
|
+
});
|
|
124
|
+
const keepFiles = Boolean(opts.keepFiles || opts.keepConfig);
|
|
125
|
+
const plugin = report.plugins.find((entry) => entry.id === id || entry.name === id);
|
|
126
|
+
const pluginId = plugin?.id ?? id;
|
|
127
|
+
const hasEntry = pluginId in (config.plugins.entries ?? {});
|
|
128
|
+
const hasInstall = pluginId in (config.plugins.installs ?? {});
|
|
129
|
+
if (!hasEntry && !hasInstall) {
|
|
130
|
+
if (plugin) throw new Error(`Plugin "${pluginId}" is not managed by plugins config/install records and cannot be uninstalled.`);
|
|
131
|
+
throw new Error(`Plugin not found: ${id}`);
|
|
132
|
+
}
|
|
133
|
+
const result = await uninstallPlugin({
|
|
134
|
+
config,
|
|
135
|
+
pluginId,
|
|
136
|
+
deleteFiles: !keepFiles
|
|
137
|
+
});
|
|
138
|
+
if (!result.ok) throw new Error(result.error);
|
|
139
|
+
saveConfig(result.config);
|
|
140
|
+
const removed = [];
|
|
141
|
+
if (result.actions.entry) removed.push("config entry");
|
|
142
|
+
if (result.actions.install) removed.push("install record");
|
|
143
|
+
if (result.actions.allowlist) removed.push("allowlist");
|
|
144
|
+
if (result.actions.loadPath) removed.push("load path");
|
|
145
|
+
if (result.actions.directory) removed.push("directory");
|
|
146
|
+
return {
|
|
147
|
+
message: `Uninstalled plugin "${pluginId}". Removed: ${removed.length > 0 ? removed.join(", ") : "nothing"}.`,
|
|
148
|
+
warnings: result.warnings
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
async function installPluginMutation(pathOrSpec, opts = {}) {
|
|
152
|
+
const fileSpec = resolveFileNpmSpecToLocalPath(pathOrSpec);
|
|
153
|
+
if (fileSpec && !fileSpec.ok) throw new Error(fileSpec.error);
|
|
154
|
+
const resolved = resolve(expandHome(fileSpec && fileSpec.ok ? fileSpec.path : pathOrSpec));
|
|
155
|
+
const config = loadConfig();
|
|
156
|
+
if (existsSync(resolved)) return installPluginFromLocalPath(config, resolved, Boolean(opts.link));
|
|
157
|
+
if (opts.link) throw new Error("`--link` requires a local path.");
|
|
158
|
+
if (looksLikePath(pathOrSpec)) throw new Error(`Path not found: ${resolved}`);
|
|
159
|
+
return installPluginFromRegistrySpec(config, pathOrSpec);
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
export { disablePluginMutation, enablePluginMutation, installPluginMutation, uninstallPluginMutation };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Config } from "@nextclaw/core";
|
|
2
|
+
import * as _$_nextclaw_openclaw_compat0 from "@nextclaw/openclaw-compat";
|
|
3
|
+
import { PluginRegistry } from "@nextclaw/openclaw-compat";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/plugin/plugin-registry-loader.d.ts
|
|
6
|
+
declare function loadPluginRegistryProgressively(config: Config, workspaceDir: string, options?: {
|
|
7
|
+
onPluginProcessed?: (params: {
|
|
8
|
+
loadedPluginCount: number;
|
|
9
|
+
pluginId?: string;
|
|
10
|
+
}) => void;
|
|
11
|
+
}): Promise<PluginRegistry>;
|
|
12
|
+
declare function discoverPluginRegistryStatus(config: Config, workspaceDir: string): _$_nextclaw_openclaw_compat0.PluginStatusReport;
|
|
13
|
+
declare function createEmptyPluginRegistry(): PluginRegistry;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { createEmptyPluginRegistry, discoverPluginRegistryStatus, loadPluginRegistryProgressively };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { buildReservedPluginLoadOptions } from "./plugin-command-utils.js";
|
|
2
|
+
import { resolveDevFirstPartyPluginDir } from "./development-source/first-party-plugin-load-paths.js";
|
|
3
|
+
import { resolveDevPluginLoadingContext } from "./development-source/dev-plugin-overrides.utils.js";
|
|
4
|
+
import { getAppLogger } from "@nextclaw/core";
|
|
5
|
+
import { discoverPluginStatusReport, loadOpenClawPluginsProgressively } from "@nextclaw/openclaw-compat";
|
|
6
|
+
//#region src/commands/plugin/plugin-registry-loader.ts
|
|
7
|
+
function createPluginLogger() {
|
|
8
|
+
return getAppLogger("plugin.registry_loader");
|
|
9
|
+
}
|
|
10
|
+
function withDevFirstPartyPluginPaths(config) {
|
|
11
|
+
return resolveDevPluginLoadingContext(config, resolveDevFirstPartyPluginDir(process.env.NEXTCLAW_DEV_FIRST_PARTY_PLUGIN_DIR));
|
|
12
|
+
}
|
|
13
|
+
async function loadPluginRegistryProgressively(config, workspaceDir, options = {}) {
|
|
14
|
+
const { configWithDevPluginOverrides, excludedRoots } = withDevFirstPartyPluginPaths(config);
|
|
15
|
+
return await loadOpenClawPluginsProgressively({
|
|
16
|
+
config: configWithDevPluginOverrides,
|
|
17
|
+
workspaceDir,
|
|
18
|
+
excludeRoots: excludedRoots,
|
|
19
|
+
...buildReservedPluginLoadOptions(),
|
|
20
|
+
onPluginProcessed: options.onPluginProcessed,
|
|
21
|
+
logger: createPluginLogger()
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function discoverPluginRegistryStatus(config, workspaceDir) {
|
|
25
|
+
const { configWithDevPluginOverrides } = withDevFirstPartyPluginPaths(config);
|
|
26
|
+
return discoverPluginStatusReport({
|
|
27
|
+
config: configWithDevPluginOverrides,
|
|
28
|
+
workspaceDir
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function createEmptyPluginRegistry() {
|
|
32
|
+
return {
|
|
33
|
+
plugins: [],
|
|
34
|
+
tools: [],
|
|
35
|
+
channels: [],
|
|
36
|
+
providers: [],
|
|
37
|
+
ncpAgentRuntimes: [],
|
|
38
|
+
diagnostics: [],
|
|
39
|
+
resolvedTools: []
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { createEmptyPluginRegistry, discoverPluginRegistryStatus, loadPluginRegistryProgressively };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ExtensionChannelRegistration } from "@nextclaw/core";
|
|
2
|
+
import { PluginChannelBinding } from "@nextclaw/openclaw-compat";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/plugin/plugin-reload.d.ts
|
|
5
|
+
declare function shouldRestartChannelsForPluginReload(params: {
|
|
6
|
+
changedPaths: readonly string[];
|
|
7
|
+
currentPluginChannelBindings: readonly PluginChannelBinding[];
|
|
8
|
+
nextPluginChannelBindings: readonly PluginChannelBinding[];
|
|
9
|
+
currentExtensionChannels: readonly ExtensionChannelRegistration[];
|
|
10
|
+
nextExtensionChannels: readonly ExtensionChannelRegistration[];
|
|
11
|
+
}): boolean;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { shouldRestartChannelsForPluginReload };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/commands/plugin/plugin-reload.ts
|
|
2
|
+
function buildPluginChannelBindingSignature(binding) {
|
|
3
|
+
return `${binding.pluginId}:${binding.channelId}`;
|
|
4
|
+
}
|
|
5
|
+
function buildSortedBindingSignatures(bindings) {
|
|
6
|
+
return bindings.map(buildPluginChannelBindingSignature).sort();
|
|
7
|
+
}
|
|
8
|
+
function buildSortedExtensionChannelIds(channels) {
|
|
9
|
+
return channels.map((registration) => registration.channel.id).filter((id) => typeof id === "string" && id.trim().length > 0).sort();
|
|
10
|
+
}
|
|
11
|
+
function areSortedStringListsEqual(left, right) {
|
|
12
|
+
if (left.length !== right.length) return false;
|
|
13
|
+
for (let index = 0; index < left.length; index += 1) if (left[index] !== right[index]) return false;
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
function readPluginIdFromPluginsEntryPath(path) {
|
|
17
|
+
if (!path.startsWith("plugins.entries.")) return null;
|
|
18
|
+
const [pluginId] = path.slice(16).split(".");
|
|
19
|
+
return pluginId?.trim() ? pluginId.trim() : null;
|
|
20
|
+
}
|
|
21
|
+
function readChannelIdFromChannelPath(path) {
|
|
22
|
+
if (!path.startsWith("channels.")) return null;
|
|
23
|
+
const [channelId] = path.slice(9).split(".");
|
|
24
|
+
return channelId?.trim() ? channelId.trim() : null;
|
|
25
|
+
}
|
|
26
|
+
function shouldRestartChannelsForPluginReload(params) {
|
|
27
|
+
if (!areSortedStringListsEqual(buildSortedBindingSignatures(params.currentPluginChannelBindings), buildSortedBindingSignatures(params.nextPluginChannelBindings))) return true;
|
|
28
|
+
if (!areSortedStringListsEqual(buildSortedExtensionChannelIds(params.currentExtensionChannels), buildSortedExtensionChannelIds(params.nextExtensionChannels))) return true;
|
|
29
|
+
const channelPluginIds = /* @__PURE__ */ new Set();
|
|
30
|
+
for (const binding of params.currentPluginChannelBindings) channelPluginIds.add(binding.pluginId);
|
|
31
|
+
for (const binding of params.nextPluginChannelBindings) channelPluginIds.add(binding.pluginId);
|
|
32
|
+
for (const path of params.changedPaths) {
|
|
33
|
+
const pluginId = readPluginIdFromPluginsEntryPath(path);
|
|
34
|
+
if (pluginId && channelPluginIds.has(pluginId)) return true;
|
|
35
|
+
const channelId = readChannelIdFromChannelPath(path);
|
|
36
|
+
if (!channelId) continue;
|
|
37
|
+
if (params.currentPluginChannelBindings.some((binding) => binding.channelId === channelId) || params.nextPluginChannelBindings.some((binding) => binding.channelId === channelId)) return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { shouldRestartChannelsForPluginReload };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { buildNextclawConfiguredRemoteState, createNextclawRemoteConnector, createNextclawRemoteStatusStore, hasRunningNextclawManagedService, resolveNextclawRemoteStatusSnapshot } from "./services/remote-runtime-support.service.js";
|
|
2
|
+
import { buildPlatformApiBaseErrorMessage, resolvePlatformApiBase } from "./utils/platform-api-base.utils.js";
|
|
3
|
+
import { Config } from "@nextclaw/core";
|
|
4
|
+
import { RemoteConnectCommandOptions, RemoteDoctorCommandOptions, RemoteEnableCommandOptions, RemoteStatusCommandOptions, RemoteStatusSnapshot } from "@nextclaw/remote";
|
|
5
|
+
|
|
6
|
+
//#region src/commands/remote/index.d.ts
|
|
7
|
+
type RemoteConfigChange = {
|
|
8
|
+
changed: boolean;
|
|
9
|
+
config: Config;
|
|
10
|
+
};
|
|
11
|
+
type RemoteCommandStatusView = {
|
|
12
|
+
configuredEnabled: boolean;
|
|
13
|
+
runtime: RemoteStatusSnapshot["runtime"];
|
|
14
|
+
localOrigin: string;
|
|
15
|
+
deviceName: string;
|
|
16
|
+
platformBase: string | null;
|
|
17
|
+
};
|
|
18
|
+
type RemoteCommandDoctorCheck = {
|
|
19
|
+
name: string;
|
|
20
|
+
ok: boolean;
|
|
21
|
+
detail: string;
|
|
22
|
+
};
|
|
23
|
+
type RemoteCommandDoctorView = {
|
|
24
|
+
generatedAt: string;
|
|
25
|
+
checks: RemoteCommandDoctorCheck[];
|
|
26
|
+
snapshot: RemoteStatusSnapshot;
|
|
27
|
+
};
|
|
28
|
+
declare class RemoteCommands {
|
|
29
|
+
private readonly deps;
|
|
30
|
+
constructor(deps?: {
|
|
31
|
+
currentLocalOrigin?: string;
|
|
32
|
+
});
|
|
33
|
+
updateConfig(params?: {
|
|
34
|
+
enabled?: boolean;
|
|
35
|
+
apiBase?: string;
|
|
36
|
+
name?: string;
|
|
37
|
+
}): RemoteConfigChange;
|
|
38
|
+
enableConfig(opts?: RemoteEnableCommandOptions): RemoteConfigChange;
|
|
39
|
+
disableConfig(): RemoteConfigChange;
|
|
40
|
+
connect(opts?: RemoteConnectCommandOptions): Promise<void>;
|
|
41
|
+
getStatusView(): RemoteCommandStatusView;
|
|
42
|
+
status(opts?: RemoteStatusCommandOptions): Promise<void>;
|
|
43
|
+
getDoctorView(): Promise<RemoteCommandDoctorView>;
|
|
44
|
+
doctor(opts?: RemoteDoctorCommandOptions): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { RemoteCommandDoctorCheck, RemoteCommandDoctorView, RemoteCommandStatusView, RemoteCommands, buildNextclawConfiguredRemoteState, buildPlatformApiBaseErrorMessage, createNextclawRemoteConnector, createNextclawRemoteStatusStore, hasRunningNextclawManagedService, resolveNextclawRemoteStatusSnapshot, resolvePlatformApiBase };
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { localUiDiscoveryService } from "../../shared/services/ui/local-ui-discovery.service.js";
|
|
2
|
+
import { buildPlatformApiBaseErrorMessage, resolvePlatformApiBase } from "./utils/platform-api-base.utils.js";
|
|
3
|
+
import { buildNextclawConfiguredRemoteState, createNextclawRemoteConnector, createNextclawRemoteStatusStore, hasRunningNextclawManagedService, resolveNextclawRemoteStatusSnapshot } from "./services/remote-runtime-support.service.js";
|
|
4
|
+
import { getConfigPath, loadConfig, saveConfig } from "@nextclaw/core";
|
|
5
|
+
import { readPlatformSessionTokenState } from "@nextclaw/remote";
|
|
6
|
+
import { hostname } from "node:os";
|
|
7
|
+
//#region src/commands/remote/index.ts
|
|
8
|
+
function normalizeOptionalString(value) {
|
|
9
|
+
if (typeof value !== "string") return;
|
|
10
|
+
const trimmed = value.trim();
|
|
11
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
12
|
+
}
|
|
13
|
+
function resolveConfiguredLocalOrigin(config) {
|
|
14
|
+
return localUiDiscoveryService.resolveLocalOrigin(config);
|
|
15
|
+
}
|
|
16
|
+
async function probeLocalUi(localOrigin) {
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(`${localOrigin}/api/health`);
|
|
19
|
+
if (!response.ok) return {
|
|
20
|
+
ok: false,
|
|
21
|
+
detail: `health returned ${response.status}`
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
ok: true,
|
|
25
|
+
detail: "health endpoint returned ok"
|
|
26
|
+
};
|
|
27
|
+
} catch (error) {
|
|
28
|
+
return {
|
|
29
|
+
ok: false,
|
|
30
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function describePlatformTokenCheck(token) {
|
|
35
|
+
const tokenState = readPlatformSessionTokenState(token);
|
|
36
|
+
if (tokenState.valid) return {
|
|
37
|
+
name: "platform-token",
|
|
38
|
+
ok: true,
|
|
39
|
+
detail: "platform session token configured"
|
|
40
|
+
};
|
|
41
|
+
if (tokenState.reason === "expired") return {
|
|
42
|
+
name: "platform-token",
|
|
43
|
+
ok: false,
|
|
44
|
+
detail: "platform session token expired; run remote browser login or \"nextclaw login\" again"
|
|
45
|
+
};
|
|
46
|
+
if (tokenState.reason === "malformed") return {
|
|
47
|
+
name: "platform-token",
|
|
48
|
+
ok: false,
|
|
49
|
+
detail: "platform session token invalid; run remote browser login or \"nextclaw login\" again"
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
name: "platform-token",
|
|
53
|
+
ok: false,
|
|
54
|
+
detail: "run remote browser login or \"nextclaw login\" first"
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
var RemoteCommands = class {
|
|
58
|
+
constructor(deps = {}) {
|
|
59
|
+
this.deps = deps;
|
|
60
|
+
}
|
|
61
|
+
updateConfig(params = {}) {
|
|
62
|
+
const config = loadConfig(getConfigPath());
|
|
63
|
+
const nextEnabled = typeof params.enabled === "boolean" ? params.enabled : config.remote.enabled;
|
|
64
|
+
const nextPlatformApiBase = typeof params.apiBase === "string" ? params.apiBase.trim() : config.remote.platformApiBase;
|
|
65
|
+
const nextDeviceName = typeof params.name === "string" ? params.name.trim() : config.remote.deviceName;
|
|
66
|
+
const next = {
|
|
67
|
+
...config,
|
|
68
|
+
remote: {
|
|
69
|
+
...config.remote,
|
|
70
|
+
enabled: nextEnabled,
|
|
71
|
+
platformApiBase: nextPlatformApiBase,
|
|
72
|
+
deviceName: nextDeviceName
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
saveConfig(next);
|
|
76
|
+
return {
|
|
77
|
+
changed: config.remote.enabled !== next.remote.enabled || config.remote.platformApiBase !== next.remote.platformApiBase || config.remote.deviceName !== next.remote.deviceName,
|
|
78
|
+
config: next
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
enableConfig(opts = {}) {
|
|
82
|
+
return this.updateConfig({
|
|
83
|
+
enabled: true,
|
|
84
|
+
apiBase: typeof opts.apiBase === "string" ? opts.apiBase : void 0,
|
|
85
|
+
name: typeof opts.name === "string" ? opts.name : void 0
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
disableConfig() {
|
|
89
|
+
return this.updateConfig({ enabled: false });
|
|
90
|
+
}
|
|
91
|
+
async connect(opts = {}) {
|
|
92
|
+
await createNextclawRemoteConnector().run({
|
|
93
|
+
...opts,
|
|
94
|
+
mode: "foreground"
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
getStatusView() {
|
|
98
|
+
const config = loadConfig(getConfigPath());
|
|
99
|
+
const snapshot = resolveNextclawRemoteStatusSnapshot(config);
|
|
100
|
+
const resolvedLocalOrigin = snapshot.runtime?.localOrigin ?? this.deps.currentLocalOrigin ?? resolveConfiguredLocalOrigin(config);
|
|
101
|
+
return {
|
|
102
|
+
configuredEnabled: snapshot.configuredEnabled,
|
|
103
|
+
runtime: snapshot.runtime,
|
|
104
|
+
localOrigin: resolvedLocalOrigin,
|
|
105
|
+
deviceName: snapshot.runtime?.deviceName ?? normalizeOptionalString(config.remote.deviceName) ?? hostname(),
|
|
106
|
+
platformBase: snapshot.runtime?.platformBase ?? normalizeOptionalString(config.remote.platformApiBase) ?? normalizeOptionalString(config.providers.nextclaw?.apiBase) ?? null
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
async status(opts = {}) {
|
|
110
|
+
const view = this.getStatusView();
|
|
111
|
+
if (opts.json) {
|
|
112
|
+
console.log(JSON.stringify(view, null, 2));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const runtime = view.runtime;
|
|
116
|
+
console.log("NextClaw Remote Status");
|
|
117
|
+
console.log(`Enabled: ${view.configuredEnabled ? "yes" : "no"}`);
|
|
118
|
+
console.log(`Mode: ${runtime?.mode ?? "service"}`);
|
|
119
|
+
console.log(`State: ${runtime?.state ?? "disabled"}`);
|
|
120
|
+
console.log(`Device: ${view.deviceName}`);
|
|
121
|
+
console.log(`Platform: ${view.platformBase ?? "not set"}`);
|
|
122
|
+
console.log(`Local origin: ${runtime?.localOrigin ?? view.localOrigin}`);
|
|
123
|
+
if (runtime?.deviceId) console.log(`Device ID: ${runtime.deviceId}`);
|
|
124
|
+
if (runtime?.lastConnectedAt) console.log(`Last connected: ${runtime.lastConnectedAt}`);
|
|
125
|
+
if (runtime?.lastError) console.log(`Last error: ${runtime.lastError}`);
|
|
126
|
+
}
|
|
127
|
+
async getDoctorView() {
|
|
128
|
+
const config = loadConfig(getConfigPath());
|
|
129
|
+
const snapshot = resolveNextclawRemoteStatusSnapshot(config);
|
|
130
|
+
const localOrigin = snapshot.runtime?.localOrigin ?? this.deps.currentLocalOrigin ?? resolveConfiguredLocalOrigin(config);
|
|
131
|
+
const localUi = await probeLocalUi(localOrigin);
|
|
132
|
+
const token = normalizeOptionalString(config.providers.nextclaw?.apiKey);
|
|
133
|
+
const platformApiBase = normalizeOptionalString(config.remote.platformApiBase) ?? normalizeOptionalString(config.providers.nextclaw?.apiBase);
|
|
134
|
+
const checks = [
|
|
135
|
+
{
|
|
136
|
+
name: "remote-enabled",
|
|
137
|
+
ok: snapshot.configuredEnabled,
|
|
138
|
+
detail: snapshot.configuredEnabled ? "enabled in config" : "disabled in config"
|
|
139
|
+
},
|
|
140
|
+
describePlatformTokenCheck(token),
|
|
141
|
+
{
|
|
142
|
+
name: "platform-api-base",
|
|
143
|
+
ok: Boolean(platformApiBase),
|
|
144
|
+
detail: platformApiBase ?? "set remote.platformApiBase or login with --api-base"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "local-ui",
|
|
148
|
+
ok: localUi.ok,
|
|
149
|
+
detail: `${localOrigin} (${localUi.detail})`
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "service-runtime",
|
|
153
|
+
ok: snapshot.runtime?.state === "connected",
|
|
154
|
+
detail: snapshot.runtime ? snapshot.runtime.state : "no managed remote runtime detected"
|
|
155
|
+
}
|
|
156
|
+
];
|
|
157
|
+
return {
|
|
158
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
159
|
+
checks,
|
|
160
|
+
snapshot
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
async doctor(opts = {}) {
|
|
164
|
+
const report = await this.getDoctorView();
|
|
165
|
+
if (opts.json) {
|
|
166
|
+
console.log(JSON.stringify(report, null, 2));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
console.log("NextClaw Remote Doctor");
|
|
170
|
+
for (const check of report.checks) console.log(`${check.ok ? "✓" : "✗"} ${check.name}: ${check.detail}`);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
//#endregion
|
|
174
|
+
export { RemoteCommands, buildNextclawConfiguredRemoteState, buildPlatformApiBaseErrorMessage, createNextclawRemoteConnector, createNextclawRemoteStatusStore, hasRunningNextclawManagedService, resolveNextclawRemoteStatusSnapshot, resolvePlatformApiBase };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PlatformAuthCommands } from "../../platform-auth/services/platform-auth-commands.service.js";
|
|
2
|
+
import { RemoteCommands } from "../index.js";
|
|
3
|
+
import { RemoteAccessHostServiceCommands, RemoteRuntimeController } from "./remote-service-control.service.js";
|
|
4
|
+
import { RemoteAccessView, RemoteBrowserAuthPollRequest, RemoteBrowserAuthPollResult, RemoteBrowserAuthStartRequest, RemoteBrowserAuthStartResult, RemoteDoctorView, RemoteServiceAction, RemoteServiceActionResult, RemoteSettingsUpdateRequest, UiRemoteAccessHost } from "@nextclaw/server";
|
|
5
|
+
|
|
6
|
+
//#region src/commands/remote/services/remote-access-host.service.d.ts
|
|
7
|
+
declare class RemoteAccessHost implements UiRemoteAccessHost {
|
|
8
|
+
private readonly deps;
|
|
9
|
+
constructor(deps: {
|
|
10
|
+
serviceCommands: RemoteAccessHostServiceCommands;
|
|
11
|
+
requestManagedServiceRestart: (options?: {
|
|
12
|
+
uiPort?: number;
|
|
13
|
+
reason?: string;
|
|
14
|
+
}) => Promise<void>;
|
|
15
|
+
remoteCommands: RemoteCommands;
|
|
16
|
+
platformAuthCommands: PlatformAuthCommands;
|
|
17
|
+
currentUi?: {
|
|
18
|
+
host: string;
|
|
19
|
+
port: number;
|
|
20
|
+
};
|
|
21
|
+
remoteRuntimeController?: RemoteRuntimeController | null;
|
|
22
|
+
});
|
|
23
|
+
getStatus: () => RemoteAccessView;
|
|
24
|
+
login: (input: {
|
|
25
|
+
email: string;
|
|
26
|
+
password: string;
|
|
27
|
+
apiBase?: string;
|
|
28
|
+
}) => Promise<RemoteAccessView>;
|
|
29
|
+
startBrowserAuth: (input: RemoteBrowserAuthStartRequest) => Promise<RemoteBrowserAuthStartResult>;
|
|
30
|
+
pollBrowserAuth: (input: RemoteBrowserAuthPollRequest) => Promise<RemoteBrowserAuthPollResult>;
|
|
31
|
+
logout: () => RemoteAccessView;
|
|
32
|
+
updateSettings: (input: RemoteSettingsUpdateRequest) => RemoteAccessView;
|
|
33
|
+
runDoctor: () => Promise<RemoteDoctorView>;
|
|
34
|
+
controlService: (action: RemoteServiceAction) => Promise<RemoteServiceActionResult>;
|
|
35
|
+
private readAccountView;
|
|
36
|
+
updateProfile: (input: {
|
|
37
|
+
username: string;
|
|
38
|
+
}) => Promise<RemoteAccessView>;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { RemoteAccessHost };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { controlRemoteService, resolveRemoteServiceView } from "./remote-service-control.service.js";
|
|
2
|
+
import { getConfigPath, loadConfig } from "@nextclaw/core";
|
|
3
|
+
import { readPlatformSessionTokenState } from "@nextclaw/remote";
|
|
4
|
+
//#region src/commands/remote/services/remote-access-host.service.ts
|
|
5
|
+
function normalizeOptionalString(value) {
|
|
6
|
+
if (typeof value !== "string") return null;
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
9
|
+
}
|
|
10
|
+
function toRemoteRuntimeView(runtime) {
|
|
11
|
+
if (!runtime) return null;
|
|
12
|
+
return {
|
|
13
|
+
enabled: runtime.enabled,
|
|
14
|
+
mode: runtime.mode,
|
|
15
|
+
state: runtime.state,
|
|
16
|
+
deviceId: runtime.deviceId,
|
|
17
|
+
deviceName: runtime.deviceName,
|
|
18
|
+
platformBase: runtime.platformBase,
|
|
19
|
+
localOrigin: runtime.localOrigin,
|
|
20
|
+
lastConnectedAt: runtime.lastConnectedAt,
|
|
21
|
+
lastError: runtime.lastError,
|
|
22
|
+
updatedAt: runtime.updatedAt
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
var RemoteAccessHost = class {
|
|
26
|
+
constructor(deps) {
|
|
27
|
+
this.deps = deps;
|
|
28
|
+
}
|
|
29
|
+
getStatus = () => {
|
|
30
|
+
const config = loadConfig(getConfigPath());
|
|
31
|
+
const status = this.deps.remoteCommands.getStatusView();
|
|
32
|
+
return {
|
|
33
|
+
account: this.readAccountView({
|
|
34
|
+
token: normalizeOptionalString(config.providers.nextclaw?.apiKey),
|
|
35
|
+
apiBase: normalizeOptionalString(config.providers.nextclaw?.apiBase),
|
|
36
|
+
platformBase: status.platformBase
|
|
37
|
+
}),
|
|
38
|
+
settings: {
|
|
39
|
+
enabled: config.remote.enabled,
|
|
40
|
+
deviceName: config.remote.deviceName,
|
|
41
|
+
platformApiBase: config.remote.platformApiBase
|
|
42
|
+
},
|
|
43
|
+
service: resolveRemoteServiceView(this.deps.currentUi),
|
|
44
|
+
localOrigin: status.localOrigin,
|
|
45
|
+
configuredEnabled: status.configuredEnabled,
|
|
46
|
+
platformBase: status.platformBase,
|
|
47
|
+
runtime: toRemoteRuntimeView(status.runtime)
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
login = async (input) => {
|
|
51
|
+
await this.deps.platformAuthCommands.loginResult(input);
|
|
52
|
+
return this.getStatus();
|
|
53
|
+
};
|
|
54
|
+
startBrowserAuth = async (input) => {
|
|
55
|
+
const result = await this.deps.platformAuthCommands.startBrowserAuth({ apiBase: input.apiBase });
|
|
56
|
+
return {
|
|
57
|
+
sessionId: result.sessionId,
|
|
58
|
+
verificationUri: result.verificationUri,
|
|
59
|
+
expiresAt: result.expiresAt,
|
|
60
|
+
intervalMs: result.intervalMs
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
pollBrowserAuth = async (input) => {
|
|
64
|
+
const config = loadConfig(getConfigPath());
|
|
65
|
+
const result = await this.deps.platformAuthCommands.pollBrowserAuth({
|
|
66
|
+
apiBase: normalizeOptionalString(input.apiBase) ?? normalizeOptionalString(config.remote.platformApiBase) ?? normalizeOptionalString(config.providers.nextclaw?.apiBase) ?? void 0,
|
|
67
|
+
sessionId: input.sessionId
|
|
68
|
+
});
|
|
69
|
+
if (result.status !== "authorized") return result;
|
|
70
|
+
return {
|
|
71
|
+
status: "authorized",
|
|
72
|
+
email: result.email,
|
|
73
|
+
role: result.role
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
logout = () => {
|
|
77
|
+
this.deps.platformAuthCommands.logout();
|
|
78
|
+
return this.getStatus();
|
|
79
|
+
};
|
|
80
|
+
updateSettings = (input) => {
|
|
81
|
+
this.deps.remoteCommands.updateConfig({
|
|
82
|
+
enabled: input.enabled,
|
|
83
|
+
apiBase: input.platformApiBase,
|
|
84
|
+
name: input.deviceName
|
|
85
|
+
});
|
|
86
|
+
return this.getStatus();
|
|
87
|
+
};
|
|
88
|
+
runDoctor = async () => {
|
|
89
|
+
const report = await this.deps.remoteCommands.getDoctorView();
|
|
90
|
+
return {
|
|
91
|
+
generatedAt: report.generatedAt,
|
|
92
|
+
checks: report.checks,
|
|
93
|
+
snapshot: {
|
|
94
|
+
configuredEnabled: report.snapshot.configuredEnabled,
|
|
95
|
+
runtime: toRemoteRuntimeView(report.snapshot.runtime)
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
controlService = async (action) => {
|
|
100
|
+
return controlRemoteService(action, this.deps);
|
|
101
|
+
};
|
|
102
|
+
readAccountView = (params) => {
|
|
103
|
+
const { apiBase, platformBase, token } = params;
|
|
104
|
+
const tokenState = readPlatformSessionTokenState(token);
|
|
105
|
+
if (!tokenState.valid) return {
|
|
106
|
+
loggedIn: false,
|
|
107
|
+
apiBase,
|
|
108
|
+
platformBase
|
|
109
|
+
};
|
|
110
|
+
const payload = tokenState.payload;
|
|
111
|
+
return {
|
|
112
|
+
loggedIn: true,
|
|
113
|
+
email: typeof payload?.email === "string" ? payload.email : void 0,
|
|
114
|
+
username: typeof payload?.username === "string" ? payload.username : void 0,
|
|
115
|
+
role: typeof payload?.role === "string" ? payload.role : void 0,
|
|
116
|
+
apiBase,
|
|
117
|
+
platformBase
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
updateProfile = async (input) => {
|
|
121
|
+
await this.deps.platformAuthCommands.updateProfile({ username: input.username });
|
|
122
|
+
return this.getStatus();
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
//#endregion
|
|
126
|
+
export { RemoteAccessHost };
|