@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,31 @@
|
|
|
1
|
+
import { MarketplaceInstaller } from "@nextclaw/server";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/services/marketplace/service-marketplace-installer.service.d.ts
|
|
4
|
+
type UserFacingResult = {
|
|
5
|
+
message: string;
|
|
6
|
+
output?: string;
|
|
7
|
+
};
|
|
8
|
+
type BuiltinSkillInstallResult = UserFacingResult | null;
|
|
9
|
+
declare class ServiceMarketplaceInstaller {
|
|
10
|
+
private readonly deps;
|
|
11
|
+
constructor(deps: {
|
|
12
|
+
applyLiveConfigReload?: () => Promise<void>;
|
|
13
|
+
runCliSubcommand: (args: string[]) => Promise<string>;
|
|
14
|
+
installBuiltinSkill: (slug: string, force?: boolean) => BuiltinSkillInstallResult;
|
|
15
|
+
});
|
|
16
|
+
createInstaller(): MarketplaceInstaller;
|
|
17
|
+
private installPlugin;
|
|
18
|
+
private installSkill;
|
|
19
|
+
private installMcp;
|
|
20
|
+
private enablePlugin;
|
|
21
|
+
private disablePlugin;
|
|
22
|
+
private uninstallPlugin;
|
|
23
|
+
private uninstallSkill;
|
|
24
|
+
private enableMcp;
|
|
25
|
+
private disableMcp;
|
|
26
|
+
private removeMcp;
|
|
27
|
+
private doctorMcp;
|
|
28
|
+
private createMcpMarketplaceOps;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { ServiceMarketplaceInstaller };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { buildMarketplaceSkillInstallArgs, pickUserFacingCommandSummary } from "../../utils/marketplace/service-marketplace-helpers.utils.js";
|
|
2
|
+
import { disablePluginMutation, enablePluginMutation, installPluginMutation, uninstallPluginMutation } from "../../../commands/plugin/plugin-mutation-actions.js";
|
|
3
|
+
import { ServiceMcpMarketplaceOps } from "./service-mcp-marketplace-ops.js";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { getWorkspacePath, loadConfig } from "@nextclaw/core";
|
|
6
|
+
import { existsSync, rmSync } from "node:fs";
|
|
7
|
+
//#region src/shared/services/marketplace/service-marketplace-installer.service.ts
|
|
8
|
+
var ServiceMarketplaceInstaller = class {
|
|
9
|
+
constructor(deps) {
|
|
10
|
+
this.deps = deps;
|
|
11
|
+
}
|
|
12
|
+
createInstaller() {
|
|
13
|
+
return {
|
|
14
|
+
installPlugin: (spec) => this.installPlugin(spec),
|
|
15
|
+
installSkill: (params) => this.installSkill(params),
|
|
16
|
+
installMcp: (params) => this.installMcp(params),
|
|
17
|
+
enablePlugin: (id) => this.enablePlugin(id),
|
|
18
|
+
disablePlugin: (id) => this.disablePlugin(id),
|
|
19
|
+
uninstallPlugin: (id) => this.uninstallPlugin(id),
|
|
20
|
+
uninstallSkill: (slug) => this.uninstallSkill(slug),
|
|
21
|
+
enableMcp: (name) => this.enableMcp(name),
|
|
22
|
+
disableMcp: (name) => this.disableMcp(name),
|
|
23
|
+
removeMcp: (name) => this.removeMcp(name),
|
|
24
|
+
doctorMcp: (name) => this.doctorMcp(name)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async installPlugin(spec) {
|
|
28
|
+
const result = await installPluginMutation(spec);
|
|
29
|
+
await this.deps.applyLiveConfigReload?.();
|
|
30
|
+
return { message: result.message };
|
|
31
|
+
}
|
|
32
|
+
async installSkill(params) {
|
|
33
|
+
if (params.kind === "builtin") {
|
|
34
|
+
const result = this.deps.installBuiltinSkill(params.slug, params.force);
|
|
35
|
+
if (!result) throw new Error(`Builtin skill not found: ${params.slug}`);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
if (params.kind && params.kind !== "marketplace") throw new Error(`Unsupported marketplace skill kind: ${params.kind}`);
|
|
39
|
+
const workspace = getWorkspacePath(loadConfig().agents.defaults.workspace);
|
|
40
|
+
const args = buildMarketplaceSkillInstallArgs({
|
|
41
|
+
slug: params.slug,
|
|
42
|
+
workspace,
|
|
43
|
+
force: params.force
|
|
44
|
+
});
|
|
45
|
+
try {
|
|
46
|
+
return { message: pickUserFacingCommandSummary(await this.deps.runCliSubcommand(args), `Installed skill: ${params.slug}`) };
|
|
47
|
+
} catch (error) {
|
|
48
|
+
const fallback = this.deps.installBuiltinSkill(params.slug, params.force);
|
|
49
|
+
if (!fallback) throw error;
|
|
50
|
+
return fallback;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async installMcp(params) {
|
|
54
|
+
return await this.createMcpMarketplaceOps().install(params);
|
|
55
|
+
}
|
|
56
|
+
async enablePlugin(id) {
|
|
57
|
+
const result = await enablePluginMutation(id);
|
|
58
|
+
await this.deps.applyLiveConfigReload?.();
|
|
59
|
+
return { message: result.message };
|
|
60
|
+
}
|
|
61
|
+
async disablePlugin(id) {
|
|
62
|
+
const result = await disablePluginMutation(id);
|
|
63
|
+
await this.deps.applyLiveConfigReload?.();
|
|
64
|
+
return { message: result.message };
|
|
65
|
+
}
|
|
66
|
+
async uninstallPlugin(id) {
|
|
67
|
+
await disablePluginMutation(id);
|
|
68
|
+
await this.deps.applyLiveConfigReload?.();
|
|
69
|
+
const result = await uninstallPluginMutation(id, { force: true });
|
|
70
|
+
await this.deps.applyLiveConfigReload?.();
|
|
71
|
+
return { message: result.message };
|
|
72
|
+
}
|
|
73
|
+
async uninstallSkill(slug) {
|
|
74
|
+
const targetDir = join(getWorkspacePath(loadConfig().agents.defaults.workspace), "skills", slug);
|
|
75
|
+
if (!existsSync(targetDir)) throw new Error(`Skill not installed in workspace: ${slug}`);
|
|
76
|
+
rmSync(targetDir, {
|
|
77
|
+
recursive: true,
|
|
78
|
+
force: true
|
|
79
|
+
});
|
|
80
|
+
return { message: `Uninstalled skill: ${slug}` };
|
|
81
|
+
}
|
|
82
|
+
async enableMcp(name) {
|
|
83
|
+
return await this.createMcpMarketplaceOps().enable(name);
|
|
84
|
+
}
|
|
85
|
+
async disableMcp(name) {
|
|
86
|
+
return await this.createMcpMarketplaceOps().disable(name);
|
|
87
|
+
}
|
|
88
|
+
async removeMcp(name) {
|
|
89
|
+
return await this.createMcpMarketplaceOps().remove(name);
|
|
90
|
+
}
|
|
91
|
+
async doctorMcp(name) {
|
|
92
|
+
return await this.createMcpMarketplaceOps().doctor(name);
|
|
93
|
+
}
|
|
94
|
+
createMcpMarketplaceOps() {
|
|
95
|
+
return new ServiceMcpMarketplaceOps({ applyLiveConfigReload: this.deps.applyLiveConfigReload });
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
//#endregion
|
|
99
|
+
export { ServiceMarketplaceInstaller };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as _$_nextclaw_mcp0 from "@nextclaw/mcp";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/services/marketplace/service-mcp-marketplace-ops.d.ts
|
|
4
|
+
declare class ServiceMcpMarketplaceOps {
|
|
5
|
+
private readonly options;
|
|
6
|
+
constructor(options: {
|
|
7
|
+
applyLiveConfigReload?: () => Promise<void>;
|
|
8
|
+
});
|
|
9
|
+
install(params: {
|
|
10
|
+
spec: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
allAgents?: boolean;
|
|
14
|
+
agents?: string[];
|
|
15
|
+
inputs?: Record<string, string>;
|
|
16
|
+
template?: unknown;
|
|
17
|
+
}): Promise<{
|
|
18
|
+
name: string;
|
|
19
|
+
message: string;
|
|
20
|
+
output?: string;
|
|
21
|
+
}>;
|
|
22
|
+
enable(name: string): Promise<{
|
|
23
|
+
message: string;
|
|
24
|
+
output?: string;
|
|
25
|
+
}>;
|
|
26
|
+
disable(name: string): Promise<{
|
|
27
|
+
message: string;
|
|
28
|
+
output?: string;
|
|
29
|
+
}>;
|
|
30
|
+
remove(name: string): Promise<{
|
|
31
|
+
message: string;
|
|
32
|
+
output?: string;
|
|
33
|
+
}>;
|
|
34
|
+
doctor(name: string): Promise<_$_nextclaw_mcp0.McpDoctorReport>;
|
|
35
|
+
private createMutationService;
|
|
36
|
+
private createDoctorFacade;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ServiceMcpMarketplaceOps };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { loadConfig, saveConfig } from "@nextclaw/core";
|
|
2
|
+
import { McpDoctorFacade, McpMutationService } from "@nextclaw/mcp";
|
|
3
|
+
//#region src/shared/services/marketplace/service-mcp-marketplace-ops.ts
|
|
4
|
+
var ServiceMcpMarketplaceOps = class {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.options = options;
|
|
7
|
+
}
|
|
8
|
+
async install(params) {
|
|
9
|
+
if (!params.template) throw new Error(`Missing MCP marketplace template for ${params.spec}`);
|
|
10
|
+
const template = params.template;
|
|
11
|
+
const result = this.createMutationService().installFromTemplate({
|
|
12
|
+
template,
|
|
13
|
+
name: params.name,
|
|
14
|
+
enabled: params.enabled,
|
|
15
|
+
scope: {
|
|
16
|
+
allAgents: params.allAgents ?? true,
|
|
17
|
+
agents: params.allAgents === false ? params.agents ?? [] : []
|
|
18
|
+
},
|
|
19
|
+
inputs: params.inputs,
|
|
20
|
+
metadata: {
|
|
21
|
+
source: "marketplace",
|
|
22
|
+
catalogSlug: params.spec,
|
|
23
|
+
displayName: template.defaultName
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
if (!result.changed) throw new Error(result.message);
|
|
27
|
+
await this.options.applyLiveConfigReload?.();
|
|
28
|
+
return {
|
|
29
|
+
name: result.name,
|
|
30
|
+
message: result.message
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async enable(name) {
|
|
34
|
+
const result = this.createMutationService().toggleEnabled(name, true);
|
|
35
|
+
if (!result.changed) throw new Error(result.message);
|
|
36
|
+
await this.options.applyLiveConfigReload?.();
|
|
37
|
+
return { message: result.message };
|
|
38
|
+
}
|
|
39
|
+
async disable(name) {
|
|
40
|
+
const result = this.createMutationService().toggleEnabled(name, false);
|
|
41
|
+
if (!result.changed) throw new Error(result.message);
|
|
42
|
+
await this.options.applyLiveConfigReload?.();
|
|
43
|
+
return { message: result.message };
|
|
44
|
+
}
|
|
45
|
+
async remove(name) {
|
|
46
|
+
const result = this.createMutationService().removeServer(name);
|
|
47
|
+
if (!result.changed) throw new Error(result.message);
|
|
48
|
+
await this.options.applyLiveConfigReload?.();
|
|
49
|
+
return { message: result.message };
|
|
50
|
+
}
|
|
51
|
+
async doctor(name) {
|
|
52
|
+
const report = await this.createDoctorFacade().inspectOne(name);
|
|
53
|
+
if (!report) throw new Error(`Unknown MCP server: ${name}`);
|
|
54
|
+
return report;
|
|
55
|
+
}
|
|
56
|
+
createMutationService() {
|
|
57
|
+
return new McpMutationService({
|
|
58
|
+
getConfig: () => loadConfig(),
|
|
59
|
+
saveConfig: (config) => saveConfig(config)
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
createDoctorFacade() {
|
|
63
|
+
return new McpDoctorFacade({ getConfig: () => loadConfig() });
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
export { ServiceMcpMarketplaceOps };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ServiceFileWatcherRegistry } from "../../gateway/service-startup-support.service.js";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/services/plugin/utils/plugin-dev-hot-reload.utils.d.ts
|
|
4
|
+
declare const DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV = "NEXTCLAW_DEV_PLUGIN_HOT_RELOAD_TARGETS";
|
|
5
|
+
type DevPluginHotReloadTarget = {
|
|
6
|
+
pluginId: string;
|
|
7
|
+
pluginPath: string;
|
|
8
|
+
watchPaths: string[];
|
|
9
|
+
};
|
|
10
|
+
declare function resolveDevPluginHotReloadTargets(rawValue?: string | undefined): DevPluginHotReloadTarget[];
|
|
11
|
+
declare function startDevPluginHotReloadWatcher(params: {
|
|
12
|
+
watcherRegistry: ServiceFileWatcherRegistry;
|
|
13
|
+
reloadPlugins: (pluginIds: string[]) => Promise<void>;
|
|
14
|
+
targets?: DevPluginHotReloadTarget[];
|
|
15
|
+
}): void;
|
|
16
|
+
declare function wrapStartChannelsWithDevPluginHotReload(params: {
|
|
17
|
+
startChannels: () => Promise<void>;
|
|
18
|
+
watcherRegistry: ServiceFileWatcherRegistry;
|
|
19
|
+
isRuntimeActive: () => boolean;
|
|
20
|
+
reloadPlugins: (pluginIds: string[]) => Promise<void>;
|
|
21
|
+
startupSettleMs: number;
|
|
22
|
+
}): () => Promise<void>;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV, DevPluginHotReloadTarget, resolveDevPluginHotReloadTargets, startDevPluginHotReloadWatcher, wrapStartChannelsWithDevPluginHotReload };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { resolve, sep } from "node:path";
|
|
2
|
+
import chokidar from "chokidar";
|
|
3
|
+
//#region src/shared/services/plugin/utils/plugin-dev-hot-reload.utils.ts
|
|
4
|
+
const DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV = "NEXTCLAW_DEV_PLUGIN_HOT_RELOAD_TARGETS";
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function readOptionalString(value) {
|
|
9
|
+
if (typeof value !== "string") return null;
|
|
10
|
+
const trimmed = value.trim();
|
|
11
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
12
|
+
}
|
|
13
|
+
function normalizeWatchPaths(value) {
|
|
14
|
+
if (!Array.isArray(value)) return [];
|
|
15
|
+
const watchPaths = [];
|
|
16
|
+
for (const entry of value) {
|
|
17
|
+
const normalized = readOptionalString(entry);
|
|
18
|
+
if (!normalized) continue;
|
|
19
|
+
const resolvedPath = resolve(normalized);
|
|
20
|
+
if (!watchPaths.includes(resolvedPath)) watchPaths.push(resolvedPath);
|
|
21
|
+
}
|
|
22
|
+
return watchPaths;
|
|
23
|
+
}
|
|
24
|
+
function resolveDevPluginHotReloadTargets(rawValue = process.env[DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV]) {
|
|
25
|
+
if (typeof rawValue !== "string" || rawValue.trim().length === 0) return [];
|
|
26
|
+
let parsed;
|
|
27
|
+
try {
|
|
28
|
+
parsed = JSON.parse(rawValue);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
throw new Error(`[dev-plugin-hot-reload] failed to parse ${DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV}: ${error instanceof Error ? error.message : String(error)}`);
|
|
31
|
+
}
|
|
32
|
+
if (!Array.isArray(parsed)) throw new Error(`[dev-plugin-hot-reload] ${DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV} must be a JSON array`);
|
|
33
|
+
const seenPluginIds = /* @__PURE__ */ new Set();
|
|
34
|
+
const targets = [];
|
|
35
|
+
for (const entry of parsed) {
|
|
36
|
+
if (!isRecord(entry)) continue;
|
|
37
|
+
const pluginId = readOptionalString(entry.pluginId);
|
|
38
|
+
const pluginPath = readOptionalString(entry.pluginPath);
|
|
39
|
+
const watchPaths = normalizeWatchPaths(entry.watchPaths);
|
|
40
|
+
if (!pluginId || !pluginPath || watchPaths.length === 0) continue;
|
|
41
|
+
if (seenPluginIds.has(pluginId)) throw new Error(`[dev-plugin-hot-reload] duplicate plugin target for "${pluginId}"`);
|
|
42
|
+
seenPluginIds.add(pluginId);
|
|
43
|
+
targets.push({
|
|
44
|
+
pluginId,
|
|
45
|
+
pluginPath: resolve(pluginPath),
|
|
46
|
+
watchPaths
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return targets;
|
|
50
|
+
}
|
|
51
|
+
function startDevPluginHotReloadWatcher(params) {
|
|
52
|
+
const targets = params.targets ?? resolveDevPluginHotReloadTargets();
|
|
53
|
+
if (targets.length === 0) return;
|
|
54
|
+
const pendingPluginIds = /* @__PURE__ */ new Set();
|
|
55
|
+
let flushTimer = null;
|
|
56
|
+
let reloadRunning = false;
|
|
57
|
+
let reloadPending = false;
|
|
58
|
+
const flushReload = async () => {
|
|
59
|
+
if (reloadRunning) {
|
|
60
|
+
reloadPending = true;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const pluginIds = [...pendingPluginIds];
|
|
64
|
+
pendingPluginIds.clear();
|
|
65
|
+
if (pluginIds.length === 0) return;
|
|
66
|
+
reloadRunning = true;
|
|
67
|
+
try {
|
|
68
|
+
console.log(`[dev] Plugin dist updated: ${pluginIds.join(", ")}`);
|
|
69
|
+
await params.reloadPlugins(pluginIds);
|
|
70
|
+
console.log(`[dev] Plugin hot reload applied: ${pluginIds.join(", ")}`);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error(`[dev] Plugin hot reload failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
73
|
+
} finally {
|
|
74
|
+
reloadRunning = false;
|
|
75
|
+
if (reloadPending || pendingPluginIds.size > 0) {
|
|
76
|
+
reloadPending = false;
|
|
77
|
+
await flushReload();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const scheduleReload = (pluginId) => {
|
|
82
|
+
pendingPluginIds.add(pluginId);
|
|
83
|
+
if (flushTimer) clearTimeout(flushTimer);
|
|
84
|
+
flushTimer = setTimeout(() => {
|
|
85
|
+
flushTimer = null;
|
|
86
|
+
flushReload();
|
|
87
|
+
}, 150);
|
|
88
|
+
};
|
|
89
|
+
const watcher = chokidar.watch(targets.flatMap((entry) => entry.watchPaths), {
|
|
90
|
+
ignoreInitial: true,
|
|
91
|
+
awaitWriteFinish: {
|
|
92
|
+
stabilityThreshold: 200,
|
|
93
|
+
pollInterval: 50
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
params.watcherRegistry.remember(watcher);
|
|
97
|
+
watcher.on("all", (_event, changedPath) => {
|
|
98
|
+
const normalizedChangedPath = resolve(changedPath);
|
|
99
|
+
for (const target of targets) if (target.watchPaths.some((watchPath) => normalizedChangedPath === watchPath || normalizedChangedPath.startsWith(`${watchPath}${sep}`))) scheduleReload(target.pluginId);
|
|
100
|
+
});
|
|
101
|
+
console.log(`[dev] Plugin hot reload watcher: ${targets.map((entry) => entry.pluginId).join(", ")}`);
|
|
102
|
+
}
|
|
103
|
+
function wrapStartChannelsWithDevPluginHotReload(params) {
|
|
104
|
+
return async () => {
|
|
105
|
+
await params.startChannels();
|
|
106
|
+
console.log(`[dev] Plugin hot reload watcher will arm after ${params.startupSettleMs}ms startup settle window.`);
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
if (!params.isRuntimeActive()) return;
|
|
109
|
+
startDevPluginHotReloadWatcher({
|
|
110
|
+
watcherRegistry: params.watcherRegistry,
|
|
111
|
+
reloadPlugins: params.reloadPlugins
|
|
112
|
+
});
|
|
113
|
+
}, params.startupSettleMs).unref?.();
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
export { DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV, resolveDevPluginHotReloadTargets, startDevPluginHotReloadWatcher, wrapStartChannelsWithDevPluginHotReload };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NextclawGatewayRuntime } from "../../gateway/nextclaw-gateway-runtime.service.js";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/services/plugin/utils/plugin-runtime-bridge.utils.d.ts
|
|
4
|
+
declare function installPluginRuntimeBridge(gateway: NextclawGatewayRuntime): void;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { installPluginRuntimeBridge };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { loadConfig, saveConfig } from "@nextclaw/core";
|
|
2
|
+
import { setPluginRuntimeBridge } from "@nextclaw/openclaw-compat";
|
|
3
|
+
import { dispatchPromptOverNcp } from "@nextclaw/kernel";
|
|
4
|
+
//#region src/shared/services/plugin/utils/plugin-runtime-bridge.utils.ts
|
|
5
|
+
function installPluginRuntimeBridge(gateway) {
|
|
6
|
+
setPluginRuntimeBridge({
|
|
7
|
+
loadConfig: () => gateway.kernel.extensions.toConfigView(gateway.configManager.loadConfig()),
|
|
8
|
+
writeConfigFile: async (nextConfigView) => {
|
|
9
|
+
if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) throw new Error("plugin runtime writeConfigFile expects an object config");
|
|
10
|
+
const current = loadConfig();
|
|
11
|
+
saveConfig(gateway.kernel.extensions.mergeConfigView(current, nextConfigView));
|
|
12
|
+
},
|
|
13
|
+
dispatchReplyWithBufferedBlockDispatcher: async ({ ctx, dispatcherOptions }) => {
|
|
14
|
+
const request = resolvePluginRuntimeRequest(ctx);
|
|
15
|
+
if (!request) return;
|
|
16
|
+
try {
|
|
17
|
+
await dispatcherOptions.onReplyStart?.();
|
|
18
|
+
const response = await dispatchPromptOverNcp({
|
|
19
|
+
config: gateway.configManager.loadConfig(),
|
|
20
|
+
sessionManager: gateway.sessionManager,
|
|
21
|
+
resolveNcpAgent: () => gateway.liveAgentRuntime,
|
|
22
|
+
...request
|
|
23
|
+
});
|
|
24
|
+
const replyText = typeof response === "string" ? response : String(response ?? "");
|
|
25
|
+
if (replyText.trim()) await dispatcherOptions.deliver({ text: replyText }, { kind: "final" });
|
|
26
|
+
} catch (error) {
|
|
27
|
+
dispatcherOptions.onError?.(error);
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function resolvePluginRuntimeRequest(ctx) {
|
|
34
|
+
const bodyForAgent = typeof ctx.BodyForAgent === "string" ? ctx.BodyForAgent : "";
|
|
35
|
+
const body = typeof ctx.Body === "string" ? ctx.Body : "";
|
|
36
|
+
const content = (bodyForAgent || body).trim();
|
|
37
|
+
const attachments = resolvePluginRuntimeAttachments(ctx);
|
|
38
|
+
if (!content && attachments.length === 0) return null;
|
|
39
|
+
const sessionKey = typeof ctx.SessionKey === "string" && ctx.SessionKey.trim().length > 0 ? ctx.SessionKey : void 0;
|
|
40
|
+
const channel = typeof ctx.OriginatingChannel === "string" && ctx.OriginatingChannel.trim().length > 0 ? ctx.OriginatingChannel : "cli";
|
|
41
|
+
const chatId = typeof ctx.OriginatingTo === "string" && ctx.OriginatingTo.trim().length > 0 ? ctx.OriginatingTo : typeof ctx.SenderId === "string" && ctx.SenderId.trim().length > 0 ? ctx.SenderId : "direct";
|
|
42
|
+
const agentId = typeof ctx.AgentId === "string" ? ctx.AgentId : void 0;
|
|
43
|
+
const modelOverride = resolveModelOverride(ctx);
|
|
44
|
+
const accountId = typeof ctx.AccountId === "string" && ctx.AccountId.trim().length > 0 ? ctx.AccountId : void 0;
|
|
45
|
+
return {
|
|
46
|
+
content,
|
|
47
|
+
sessionKey,
|
|
48
|
+
channel,
|
|
49
|
+
chatId,
|
|
50
|
+
agentId,
|
|
51
|
+
attachments,
|
|
52
|
+
metadata: {
|
|
53
|
+
...accountId ? { account_id: accountId } : {},
|
|
54
|
+
...modelOverride ? { model: modelOverride } : {}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function resolveModelOverride(ctx) {
|
|
59
|
+
if (typeof ctx.Model === "string" && ctx.Model.trim().length > 0) return ctx.Model.trim();
|
|
60
|
+
if (typeof ctx.AgentModel === "string" && ctx.AgentModel.trim().length > 0) return ctx.AgentModel.trim();
|
|
61
|
+
}
|
|
62
|
+
function readStringList(value) {
|
|
63
|
+
if (!Array.isArray(value)) return [];
|
|
64
|
+
return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
|
|
65
|
+
}
|
|
66
|
+
function readOptionalString(value) {
|
|
67
|
+
if (typeof value !== "string") return;
|
|
68
|
+
return value.trim() || void 0;
|
|
69
|
+
}
|
|
70
|
+
function resolvePluginRuntimeAttachments(ctx) {
|
|
71
|
+
const mediaPaths = readStringList(ctx.MediaPaths);
|
|
72
|
+
const mediaUrls = readStringList(ctx.MediaUrls);
|
|
73
|
+
const fallbackPath = readOptionalString(ctx.MediaPath);
|
|
74
|
+
const fallbackUrl = readOptionalString(ctx.MediaUrl);
|
|
75
|
+
const mediaTypes = readStringList(ctx.MediaTypes);
|
|
76
|
+
const fallbackType = readOptionalString(ctx.MediaType);
|
|
77
|
+
const entryCount = Math.max(mediaPaths.length, mediaUrls.length, fallbackPath ? 1 : 0, fallbackUrl ? 1 : 0);
|
|
78
|
+
const attachments = [];
|
|
79
|
+
for (let index = 0; index < entryCount; index += 1) {
|
|
80
|
+
const path = mediaPaths[index] ?? (index === 0 ? fallbackPath : void 0);
|
|
81
|
+
const rawUrl = mediaUrls[index] ?? (index === 0 ? fallbackUrl : void 0);
|
|
82
|
+
const url = rawUrl && rawUrl !== path ? rawUrl : void 0;
|
|
83
|
+
const mimeType = mediaTypes[index] ?? fallbackType;
|
|
84
|
+
if (!path && !url) continue;
|
|
85
|
+
attachments.push({
|
|
86
|
+
path,
|
|
87
|
+
url,
|
|
88
|
+
mimeType,
|
|
89
|
+
source: "plugin-runtime",
|
|
90
|
+
status: path ? "ready" : "remote-only"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return attachments;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { installPluginRuntimeBridge };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ManagedServiceState } from "../../stores/managed-service-state.store.js";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/services/restart/restart-coordinator.service.d.ts
|
|
4
|
+
type RestartStrategy = "background-service-or-manual" | "background-service-or-exit" | "exit-process";
|
|
5
|
+
type RestartRequest = {
|
|
6
|
+
reason: string;
|
|
7
|
+
strategy?: RestartStrategy;
|
|
8
|
+
delayMs?: number;
|
|
9
|
+
manualMessage?: string;
|
|
10
|
+
};
|
|
11
|
+
type RestartResult = {
|
|
12
|
+
status: "service-restarted" | "restart-in-progress" | "exit-scheduled" | "manual-required";
|
|
13
|
+
message: string;
|
|
14
|
+
};
|
|
15
|
+
type RestartCoordinatorDeps = {
|
|
16
|
+
readServiceState: () => ManagedServiceState | null;
|
|
17
|
+
isProcessRunning: (pid: number) => boolean;
|
|
18
|
+
currentPid: () => number;
|
|
19
|
+
restartBackgroundService: (reason: string) => Promise<boolean>;
|
|
20
|
+
scheduleProcessExit: (delayMs: number, reason: string) => void;
|
|
21
|
+
};
|
|
22
|
+
declare class RestartCoordinator {
|
|
23
|
+
private deps;
|
|
24
|
+
private restartingService;
|
|
25
|
+
private exitScheduled;
|
|
26
|
+
constructor(deps: RestartCoordinatorDeps);
|
|
27
|
+
readonly requestRestart: (request: RestartRequest) => Promise<RestartResult>;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { RestartCoordinator, RestartRequest, RestartResult, RestartStrategy };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/shared/services/restart/restart-coordinator.service.ts
|
|
2
|
+
var RestartCoordinator = class {
|
|
3
|
+
restartingService = false;
|
|
4
|
+
exitScheduled = false;
|
|
5
|
+
constructor(deps) {
|
|
6
|
+
this.deps = deps;
|
|
7
|
+
}
|
|
8
|
+
requestRestart = async (request) => {
|
|
9
|
+
const reason = request.reason.trim() || "config changed";
|
|
10
|
+
const strategy = request.strategy ?? "background-service-or-manual";
|
|
11
|
+
if (strategy !== "exit-process") {
|
|
12
|
+
const state = this.deps.readServiceState();
|
|
13
|
+
const serviceRunning = Boolean(state && this.deps.isProcessRunning(state.pid));
|
|
14
|
+
const managedByCurrentProcess = Boolean(state && state.pid === this.deps.currentPid());
|
|
15
|
+
if (serviceRunning && !managedByCurrentProcess) {
|
|
16
|
+
if (this.restartingService) return {
|
|
17
|
+
status: "restart-in-progress",
|
|
18
|
+
message: "Restart already in progress; skipping duplicate request."
|
|
19
|
+
};
|
|
20
|
+
this.restartingService = true;
|
|
21
|
+
try {
|
|
22
|
+
if (await this.deps.restartBackgroundService(reason)) return {
|
|
23
|
+
status: "service-restarted",
|
|
24
|
+
message: `Restarted background service to apply changes (${reason}).`
|
|
25
|
+
};
|
|
26
|
+
} finally {
|
|
27
|
+
this.restartingService = false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (strategy === "background-service-or-exit" || strategy === "exit-process") {
|
|
32
|
+
if (this.exitScheduled) return {
|
|
33
|
+
status: "exit-scheduled",
|
|
34
|
+
message: "Restart already scheduled; skipping duplicate request."
|
|
35
|
+
};
|
|
36
|
+
const delay = typeof request.delayMs === "number" && Number.isFinite(request.delayMs) ? Math.max(0, Math.floor(request.delayMs)) : 100;
|
|
37
|
+
this.exitScheduled = true;
|
|
38
|
+
this.deps.scheduleProcessExit(delay, reason);
|
|
39
|
+
return {
|
|
40
|
+
status: "exit-scheduled",
|
|
41
|
+
message: `Restart scheduled (${reason}).`
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
status: "manual-required",
|
|
46
|
+
message: request.manualMessage ?? "Restart the gateway to apply changes."
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { RestartCoordinator };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SessionManager } from "@nextclaw/core";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/services/restart/restart-sentinel.service.d.ts
|
|
4
|
+
type RestartSentinelDeliveryContext = {
|
|
5
|
+
channel?: string;
|
|
6
|
+
chatId?: string;
|
|
7
|
+
replyTo?: string | null;
|
|
8
|
+
accountId?: string | null;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
type RestartSentinelPayload = {
|
|
12
|
+
kind: "config.apply" | "config.patch" | "update.run" | "restart";
|
|
13
|
+
status: "ok" | "error" | "skipped";
|
|
14
|
+
ts: number;
|
|
15
|
+
sessionKey?: string;
|
|
16
|
+
deliveryContext?: RestartSentinelDeliveryContext;
|
|
17
|
+
message?: string | null;
|
|
18
|
+
stats?: {
|
|
19
|
+
reason?: string | null;
|
|
20
|
+
strategy?: string | null;
|
|
21
|
+
durationMs?: number | null;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
type RestartSentinelFile = {
|
|
25
|
+
version: 1;
|
|
26
|
+
payload: RestartSentinelPayload;
|
|
27
|
+
};
|
|
28
|
+
declare function resolveRestartSentinelPath(): string;
|
|
29
|
+
declare function writeRestartSentinel(payload: RestartSentinelPayload): Promise<string>;
|
|
30
|
+
declare function consumeRestartSentinel(): Promise<RestartSentinelFile | null>;
|
|
31
|
+
declare function summarizeRestartSentinel(payload: RestartSentinelPayload): string;
|
|
32
|
+
declare function formatRestartSentinelMessage(payload: RestartSentinelPayload): string;
|
|
33
|
+
declare function parseSessionKey(sessionKey?: string): {
|
|
34
|
+
channel: string;
|
|
35
|
+
chatId: string;
|
|
36
|
+
} | null;
|
|
37
|
+
declare function enqueuePendingSystemEvent(sessionManager: SessionManager, sessionKey: string, message: string): void;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { RestartSentinelDeliveryContext, RestartSentinelPayload, consumeRestartSentinel, enqueuePendingSystemEvent, formatRestartSentinelMessage, parseSessionKey, resolveRestartSentinelPath, summarizeRestartSentinel, writeRestartSentinel };
|