@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,338 @@
|
|
|
1
|
+
import { resolveDevFirstPartyPluginDir } from "../../../commands/plugin/development-source/first-party-plugin-load-paths.js";
|
|
2
|
+
import { ExtensionLifecycleService, ExtensionManifestDiscoveryService } from "./extension-lifecycle.service.js";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { getDataPath } from "@nextclaw/core";
|
|
7
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
//#region src/shared/services/extensions/service-extension-runtime.service.ts
|
|
10
|
+
const EXTENSION_CONFIG_GET_INGRESS_TYPE = "extension.channel.config.get";
|
|
11
|
+
const EXTENSION_MESSAGE_SUBMIT_INGRESS_TYPE = "extension.channel.message.submit";
|
|
12
|
+
const EXTENSION_REQUEST_EVENT_TYPE = "extension.request";
|
|
13
|
+
const EXTENSION_RESPONSE_INGRESS_TYPE = "extension.response";
|
|
14
|
+
const serviceRequire = createRequire(import.meta.url);
|
|
15
|
+
const EXTENSION_REQUEST_TIMEOUT_MS = 6e4;
|
|
16
|
+
var ExtensionChannelAuthClient = class {
|
|
17
|
+
constructor(params) {
|
|
18
|
+
this.params = params;
|
|
19
|
+
}
|
|
20
|
+
login = async ({ accountId, baseUrl, verbose }) => await this.params.request({
|
|
21
|
+
extensionId: this.params.extensionId,
|
|
22
|
+
kind: "channel.auth.login",
|
|
23
|
+
payload: {
|
|
24
|
+
channelId: this.params.channelId,
|
|
25
|
+
accountId,
|
|
26
|
+
baseUrl,
|
|
27
|
+
verbose
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
start = async ({ accountId, baseUrl }) => await this.params.request({
|
|
31
|
+
extensionId: this.params.extensionId,
|
|
32
|
+
kind: "channel.auth.start",
|
|
33
|
+
payload: {
|
|
34
|
+
channelId: this.params.channelId,
|
|
35
|
+
accountId,
|
|
36
|
+
baseUrl
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
poll = async ({ sessionId }) => await this.params.request({
|
|
40
|
+
extensionId: this.params.extensionId,
|
|
41
|
+
kind: "channel.auth.poll",
|
|
42
|
+
payload: {
|
|
43
|
+
channelId: this.params.channelId,
|
|
44
|
+
sessionId
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
function uniquePaths(paths) {
|
|
49
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50
|
+
const unique = [];
|
|
51
|
+
for (const path of paths) {
|
|
52
|
+
const normalized = resolve(path);
|
|
53
|
+
if (seen.has(normalized)) continue;
|
|
54
|
+
seen.add(normalized);
|
|
55
|
+
unique.push(normalized);
|
|
56
|
+
}
|
|
57
|
+
return unique;
|
|
58
|
+
}
|
|
59
|
+
function findExtensionManifestRoot(startPath) {
|
|
60
|
+
let current = resolve(startPath);
|
|
61
|
+
while (true) {
|
|
62
|
+
if (existsSync(join(current, "nextclaw.extension.json"))) return current;
|
|
63
|
+
const parent = dirname(current);
|
|
64
|
+
if (parent === current) return;
|
|
65
|
+
current = parent;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function readBuiltinExtensionPackages() {
|
|
69
|
+
const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), "../../../..", "package.json");
|
|
70
|
+
try {
|
|
71
|
+
const packages = JSON.parse(readFileSync(packageJsonPath, "utf-8")).nextclaw?.builtinExtensions;
|
|
72
|
+
return Array.isArray(packages) ? packages.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
|
|
73
|
+
} catch {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function readPackageName(packageJsonPath) {
|
|
78
|
+
try {
|
|
79
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
80
|
+
return typeof packageJson.name === "string" ? packageJson.name : void 0;
|
|
81
|
+
} catch {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function readDirectoryNames(root) {
|
|
86
|
+
try {
|
|
87
|
+
return readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => String(entry.name));
|
|
88
|
+
} catch {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function findWorkspacePackageRoot(packageName) {
|
|
93
|
+
const roots = [
|
|
94
|
+
resolve(process.cwd(), "packages", "extensions"),
|
|
95
|
+
resolve(process.cwd(), "packages"),
|
|
96
|
+
resolve(process.cwd(), "apps"),
|
|
97
|
+
resolve(process.cwd(), "workers")
|
|
98
|
+
];
|
|
99
|
+
for (const root of roots) for (const name of readDirectoryNames(root)) {
|
|
100
|
+
const candidateRoot = join(root, name);
|
|
101
|
+
if (readPackageName(join(candidateRoot, "package.json")) === packageName && existsSync(join(candidateRoot, "nextclaw.extension.json"))) return candidateRoot;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function resolveBuiltinExtensionManifestRoots() {
|
|
105
|
+
const roots = [];
|
|
106
|
+
for (const packageName of readBuiltinExtensionPackages()) {
|
|
107
|
+
try {
|
|
108
|
+
const root = findExtensionManifestRoot(dirname(serviceRequire.resolve(packageName)));
|
|
109
|
+
if (root) roots.push(root);
|
|
110
|
+
} catch {}
|
|
111
|
+
const workspaceRoot = findWorkspacePackageRoot(packageName);
|
|
112
|
+
if (workspaceRoot) roots.push(workspaceRoot);
|
|
113
|
+
}
|
|
114
|
+
return uniquePaths(roots);
|
|
115
|
+
}
|
|
116
|
+
function readRecord(value) {
|
|
117
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
118
|
+
}
|
|
119
|
+
function readRequiredString(value, name) {
|
|
120
|
+
if (typeof value !== "string" || !value.trim()) throw new Error(`${name} is required`);
|
|
121
|
+
return value.trim();
|
|
122
|
+
}
|
|
123
|
+
function readTextContent(value) {
|
|
124
|
+
const content = readRecord(value);
|
|
125
|
+
if (content.type !== "text" || typeof content.text !== "string") throw new Error("only text channel messages are supported by the first ingress bridge");
|
|
126
|
+
return content.text;
|
|
127
|
+
}
|
|
128
|
+
function readOptionalString(value) {
|
|
129
|
+
if (typeof value !== "string") return;
|
|
130
|
+
return value.trim() || void 0;
|
|
131
|
+
}
|
|
132
|
+
function readOptionalNumber(value) {
|
|
133
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
134
|
+
}
|
|
135
|
+
function readInboundAttachments(value) {
|
|
136
|
+
if (!Array.isArray(value)) return [];
|
|
137
|
+
return value.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))).map((entry) => ({
|
|
138
|
+
...readOptionalString(entry.id) ? { id: readOptionalString(entry.id) } : {},
|
|
139
|
+
...readOptionalString(entry.name) ? { name: readOptionalString(entry.name) } : {},
|
|
140
|
+
...readOptionalString(entry.path) ? { path: readOptionalString(entry.path) } : {},
|
|
141
|
+
...readOptionalString(entry.url) ? { url: readOptionalString(entry.url) } : {},
|
|
142
|
+
...readOptionalString(entry.assetUri) ? { assetUri: readOptionalString(entry.assetUri) } : {},
|
|
143
|
+
...readOptionalString(entry.mimeType) ? { mimeType: readOptionalString(entry.mimeType) } : {},
|
|
144
|
+
...readOptionalNumber(entry.size) !== void 0 ? { size: readOptionalNumber(entry.size) } : {},
|
|
145
|
+
...readOptionalString(entry.source) ? { source: readOptionalString(entry.source) } : {},
|
|
146
|
+
...entry.status === "ready" || entry.status === "remote-only" ? { status: entry.status } : {},
|
|
147
|
+
...readOptionalString(entry.errorCode) ? { errorCode: readOptionalString(entry.errorCode) } : {}
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
function toInboundMessage(payload) {
|
|
151
|
+
const metadata = readRecord(payload.metadata);
|
|
152
|
+
return {
|
|
153
|
+
channel: readRequiredString(payload.channelId, "channelId"),
|
|
154
|
+
chatId: readRequiredString(payload.conversationId, "conversationId"),
|
|
155
|
+
senderId: readRequiredString(payload.senderId, "senderId"),
|
|
156
|
+
content: readTextContent(payload.content),
|
|
157
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
158
|
+
attachments: readInboundAttachments(payload.attachments),
|
|
159
|
+
metadata
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function resolveExtensionManifestRoots(params) {
|
|
163
|
+
const devExtensionsDir = resolveDevFirstPartyPluginDir(process.env.NEXTCLAW_DEV_FIRST_PARTY_PLUGIN_DIR);
|
|
164
|
+
return uniquePaths([
|
|
165
|
+
join(getDataPath(), "extensions"),
|
|
166
|
+
join(params.workspace, ".nextclaw", "extensions"),
|
|
167
|
+
...devExtensionsDir ? [devExtensionsDir] : [],
|
|
168
|
+
...resolveBuiltinExtensionManifestRoots(),
|
|
169
|
+
...params.config.plugins.load?.paths ?? []
|
|
170
|
+
]);
|
|
171
|
+
}
|
|
172
|
+
async function startDiscoveredExtensions(params) {
|
|
173
|
+
const { config, discovery: providedDiscovery, endpoint, lifecycle: providedLifecycle, token, workspace } = params;
|
|
174
|
+
const discovery = providedDiscovery ?? new ExtensionManifestDiscoveryService();
|
|
175
|
+
const lifecycle = providedLifecycle ?? new ExtensionLifecycleService({
|
|
176
|
+
endpoint,
|
|
177
|
+
token
|
|
178
|
+
});
|
|
179
|
+
const manifests = await discovery.discover(resolveExtensionManifestRoots({
|
|
180
|
+
config,
|
|
181
|
+
workspace
|
|
182
|
+
}));
|
|
183
|
+
return {
|
|
184
|
+
lifecycle,
|
|
185
|
+
running: await lifecycle.startAll(manifests)
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
var ServiceExtensionRuntime = class {
|
|
189
|
+
token = randomUUID();
|
|
190
|
+
lifecycle = null;
|
|
191
|
+
manifests = [];
|
|
192
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
193
|
+
constructor(gateway) {
|
|
194
|
+
this.gateway = gateway;
|
|
195
|
+
}
|
|
196
|
+
registerIngressHandlers = (ingress) => {
|
|
197
|
+
ingress.addHandler(EXTENSION_CONFIG_GET_INGRESS_TYPE, this.handleChannelConfigGet);
|
|
198
|
+
ingress.addHandler(EXTENSION_MESSAGE_SUBMIT_INGRESS_TYPE, this.handleChannelMessageSubmit);
|
|
199
|
+
ingress.addHandler(EXTENSION_RESPONSE_INGRESS_TYPE, this.handleExtensionResponse);
|
|
200
|
+
};
|
|
201
|
+
loadContributions = async () => {
|
|
202
|
+
this.manifests = await this.discoverManifests();
|
|
203
|
+
return this.toContributions(this.manifests);
|
|
204
|
+
};
|
|
205
|
+
start = async () => {
|
|
206
|
+
const endpoint = this.gateway.uiStartup.endpoint || null;
|
|
207
|
+
if (!endpoint) return;
|
|
208
|
+
const lifecycle = this.lifecycle ?? new ExtensionLifecycleService({
|
|
209
|
+
endpoint,
|
|
210
|
+
token: this.token
|
|
211
|
+
});
|
|
212
|
+
const manifests = this.manifests.length > 0 ? this.manifests : await this.discoverManifests();
|
|
213
|
+
const running = await lifecycle.startAll(manifests);
|
|
214
|
+
this.lifecycle = lifecycle;
|
|
215
|
+
if (running.length > 0) console.log(`✓ Extensions started: ${running.map((entry) => entry.manifest.id).join(", ")}`);
|
|
216
|
+
};
|
|
217
|
+
stop = async () => {
|
|
218
|
+
await this.lifecycle?.stopAll();
|
|
219
|
+
this.lifecycle = null;
|
|
220
|
+
for (const [requestId, request] of this.pendingRequests) {
|
|
221
|
+
clearTimeout(request.timeout);
|
|
222
|
+
request.reject(/* @__PURE__ */ new Error(`Extension request cancelled: ${requestId}`));
|
|
223
|
+
}
|
|
224
|
+
this.pendingRequests.clear();
|
|
225
|
+
};
|
|
226
|
+
handleChannelConfigGet = (envelope, context) => {
|
|
227
|
+
this.assertAuthorized(context);
|
|
228
|
+
const channelId = readRequiredString(readRecord(envelope.payload).channelId, "channelId");
|
|
229
|
+
return { config: this.gateway.configManager.loadConfig().channels[channelId] ?? {} };
|
|
230
|
+
};
|
|
231
|
+
handleChannelMessageSubmit = async (envelope, context) => {
|
|
232
|
+
this.assertAuthorized(context);
|
|
233
|
+
await this.gateway.messageBus.publishInbound(toInboundMessage(readRecord(envelope.payload)));
|
|
234
|
+
return { accepted: true };
|
|
235
|
+
};
|
|
236
|
+
handleExtensionResponse = (envelope, context) => {
|
|
237
|
+
this.assertAuthorized(context);
|
|
238
|
+
const payload = readRecord(envelope.payload);
|
|
239
|
+
const requestId = readRequiredString(payload.requestId, "requestId");
|
|
240
|
+
const pending = this.pendingRequests.get(requestId);
|
|
241
|
+
if (!pending) return { accepted: false };
|
|
242
|
+
this.pendingRequests.delete(requestId);
|
|
243
|
+
clearTimeout(pending.timeout);
|
|
244
|
+
if (payload.ok === false) {
|
|
245
|
+
const error = readRecord(payload.error);
|
|
246
|
+
const message = typeof error.message === "string" && error.message.trim() ? error.message.trim() : "Extension request failed";
|
|
247
|
+
pending.reject(new Error(message));
|
|
248
|
+
return { accepted: true };
|
|
249
|
+
}
|
|
250
|
+
pending.resolve(payload.data);
|
|
251
|
+
return { accepted: true };
|
|
252
|
+
};
|
|
253
|
+
discoverManifests = async () => {
|
|
254
|
+
return await new ExtensionManifestDiscoveryService().discover(resolveExtensionManifestRoots({
|
|
255
|
+
config: this.gateway.configManager.loadConfig(),
|
|
256
|
+
workspace: this.gateway.workspace
|
|
257
|
+
}));
|
|
258
|
+
};
|
|
259
|
+
toContributions = (manifests) => {
|
|
260
|
+
const channelBindings = [];
|
|
261
|
+
const uiMetadata = [];
|
|
262
|
+
for (const manifest of manifests) {
|
|
263
|
+
const channels = manifest.contributes?.channels ?? [];
|
|
264
|
+
for (const channel of channels) {
|
|
265
|
+
const channelId = readOptionalString(channel.id);
|
|
266
|
+
if (!channelId) continue;
|
|
267
|
+
const configUiHints = this.readConfigUiHints(channel.configUiHints);
|
|
268
|
+
channelBindings.push({
|
|
269
|
+
pluginId: manifest.id,
|
|
270
|
+
channelId,
|
|
271
|
+
channel: {
|
|
272
|
+
id: channelId,
|
|
273
|
+
meta: {
|
|
274
|
+
label: channel.name ?? channelId,
|
|
275
|
+
selectionLabel: channel.name ?? channelId,
|
|
276
|
+
...channel.description ? { blurb: channel.description } : {},
|
|
277
|
+
...channel.meta ?? {}
|
|
278
|
+
},
|
|
279
|
+
...channel.configSchema ? { configSchema: {
|
|
280
|
+
schema: channel.configSchema,
|
|
281
|
+
...configUiHints ? { uiHints: configUiHints } : {}
|
|
282
|
+
} } : {},
|
|
283
|
+
...channel.auth ? { auth: this.createChannelAuth(manifest.id, channelId) } : {}
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
uiMetadata.push({
|
|
287
|
+
id: manifest.id,
|
|
288
|
+
configSchema: channel.configSchema,
|
|
289
|
+
...configUiHints ? { configUiHints } : {}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
channelBindings,
|
|
295
|
+
uiMetadata
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
readConfigUiHints = (value) => {
|
|
299
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
300
|
+
return value;
|
|
301
|
+
};
|
|
302
|
+
createChannelAuth = (extensionId, channelId) => new ExtensionChannelAuthClient({
|
|
303
|
+
extensionId,
|
|
304
|
+
channelId,
|
|
305
|
+
request: this.requestExtension
|
|
306
|
+
});
|
|
307
|
+
requestExtension = async (params) => {
|
|
308
|
+
const requestId = randomUUID();
|
|
309
|
+
const result = new Promise((resolvePromise, rejectPromise) => {
|
|
310
|
+
const timeout = setTimeout(() => {
|
|
311
|
+
this.pendingRequests.delete(requestId);
|
|
312
|
+
rejectPromise(/* @__PURE__ */ new Error(`Extension request timed out: ${params.kind}`));
|
|
313
|
+
}, EXTENSION_REQUEST_TIMEOUT_MS);
|
|
314
|
+
this.pendingRequests.set(requestId, {
|
|
315
|
+
resolve: (value) => resolvePromise(value),
|
|
316
|
+
reject: rejectPromise,
|
|
317
|
+
timeout
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
this.gateway.appEventBus.emitEnvelope({
|
|
321
|
+
type: EXTENSION_REQUEST_EVENT_TYPE,
|
|
322
|
+
payload: {
|
|
323
|
+
requestId,
|
|
324
|
+
extensionId: params.extensionId,
|
|
325
|
+
kind: params.kind,
|
|
326
|
+
payload: params.payload
|
|
327
|
+
},
|
|
328
|
+
emittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
329
|
+
source: "backend"
|
|
330
|
+
});
|
|
331
|
+
return await result;
|
|
332
|
+
};
|
|
333
|
+
assertAuthorized = (context) => {
|
|
334
|
+
if (context.token !== this.token) throw new Error("Unauthorized ingress token");
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
//#endregion
|
|
338
|
+
export { ServiceExtensionRuntime, resolveBuiltinExtensionManifestRoots, resolveExtensionManifestRoots, startDiscoveredExtensions };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MessageBus } from "@nextclaw/core";
|
|
2
|
+
import { NcpAgentRunApi } from "@nextclaw/ncp";
|
|
3
|
+
|
|
4
|
+
//#region src/shared/services/gateway/cron-job-handler.service.d.ts
|
|
5
|
+
type CronJobLike = {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
payload: {
|
|
9
|
+
message: string;
|
|
10
|
+
agentId?: string | null;
|
|
11
|
+
sessionId?: string | null;
|
|
12
|
+
deliver?: boolean;
|
|
13
|
+
channel?: string | null;
|
|
14
|
+
to?: string | null;
|
|
15
|
+
accountId?: string | null;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
type BackgroundNcpAgent = {
|
|
19
|
+
runApi: NcpAgentRunApi;
|
|
20
|
+
};
|
|
21
|
+
declare function createCronJobHandler(params: {
|
|
22
|
+
resolveNcpAgent: () => BackgroundNcpAgent | null;
|
|
23
|
+
bus: MessageBus;
|
|
24
|
+
}): (job: CronJobLike) => Promise<string>;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { createCronJobHandler };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { NcpEventType } from "@nextclaw/ncp";
|
|
2
|
+
//#region src/shared/services/gateway/cron-job-handler.service.ts
|
|
3
|
+
function normalizeOptionalString(value) {
|
|
4
|
+
if (typeof value !== "string") return;
|
|
5
|
+
return value.trim() || void 0;
|
|
6
|
+
}
|
|
7
|
+
function buildCronSessionMetadata(params) {
|
|
8
|
+
const { job, agentId, accountId } = params;
|
|
9
|
+
const channel = normalizeOptionalString(job.payload.channel) ?? "cli";
|
|
10
|
+
const chatId = normalizeOptionalString(job.payload.to) ?? "direct";
|
|
11
|
+
const metadata = {
|
|
12
|
+
agentId,
|
|
13
|
+
agent_id: agentId,
|
|
14
|
+
channel,
|
|
15
|
+
chatId,
|
|
16
|
+
chat_id: chatId,
|
|
17
|
+
label: job.name,
|
|
18
|
+
cron_job_id: job.id,
|
|
19
|
+
cron_job_name: job.name,
|
|
20
|
+
session_origin: "cron"
|
|
21
|
+
};
|
|
22
|
+
if (accountId) {
|
|
23
|
+
metadata.accountId = accountId;
|
|
24
|
+
metadata.account_id = accountId;
|
|
25
|
+
}
|
|
26
|
+
return metadata;
|
|
27
|
+
}
|
|
28
|
+
function buildCronUserMessage(params) {
|
|
29
|
+
const { sessionId, content, metadata } = params;
|
|
30
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
31
|
+
return {
|
|
32
|
+
id: `${sessionId}:user:cron:${timestamp}`,
|
|
33
|
+
sessionId,
|
|
34
|
+
role: "user",
|
|
35
|
+
status: "final",
|
|
36
|
+
timestamp,
|
|
37
|
+
parts: [{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: content
|
|
40
|
+
}],
|
|
41
|
+
metadata: structuredClone(metadata)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function extractMessageText(message) {
|
|
45
|
+
return message.parts.flatMap((part) => {
|
|
46
|
+
if (part.type === "text" || part.type === "rich-text") return [part.text];
|
|
47
|
+
return [];
|
|
48
|
+
}).map((text) => text.trim()).filter((text) => text.length > 0).join("\n\n");
|
|
49
|
+
}
|
|
50
|
+
async function runJobOverNcp(params) {
|
|
51
|
+
const { agent, sessionId, message, metadata, missingCompletedMessageError, runErrorMessage } = params;
|
|
52
|
+
let completedMessage;
|
|
53
|
+
for await (const event of agent.runApi.send({
|
|
54
|
+
sessionId,
|
|
55
|
+
message,
|
|
56
|
+
metadata
|
|
57
|
+
})) {
|
|
58
|
+
if (event.type === NcpEventType.MessageFailed) throw new Error(event.payload.error.message);
|
|
59
|
+
if (event.type === NcpEventType.RunError) throw new Error(event.payload.error ?? runErrorMessage);
|
|
60
|
+
if (event.type === NcpEventType.MessageCompleted) completedMessage = event.payload.message;
|
|
61
|
+
}
|
|
62
|
+
if (!completedMessage) throw new Error(missingCompletedMessageError);
|
|
63
|
+
return extractMessageText(completedMessage);
|
|
64
|
+
}
|
|
65
|
+
function createCronJobHandler(params) {
|
|
66
|
+
return async (job) => {
|
|
67
|
+
const ncpAgent = params.resolveNcpAgent();
|
|
68
|
+
if (!ncpAgent) throw new Error("NCP agent is not ready for cron execution.");
|
|
69
|
+
const accountId = normalizeOptionalString(job.payload.accountId);
|
|
70
|
+
const agentId = normalizeOptionalString(job.payload.agentId) ?? "main";
|
|
71
|
+
const sessionId = normalizeOptionalString(job.payload.sessionId) ?? `cron:${job.id}`;
|
|
72
|
+
const metadata = buildCronSessionMetadata({
|
|
73
|
+
job,
|
|
74
|
+
agentId,
|
|
75
|
+
accountId
|
|
76
|
+
});
|
|
77
|
+
const response = await runJobOverNcp({
|
|
78
|
+
agent: ncpAgent,
|
|
79
|
+
sessionId,
|
|
80
|
+
message: buildCronUserMessage({
|
|
81
|
+
sessionId,
|
|
82
|
+
content: job.payload.message,
|
|
83
|
+
metadata
|
|
84
|
+
}),
|
|
85
|
+
metadata,
|
|
86
|
+
missingCompletedMessageError: "cron job completed without a final assistant message",
|
|
87
|
+
runErrorMessage: "cron job failed"
|
|
88
|
+
});
|
|
89
|
+
if (job.payload.deliver && job.payload.to) await params.bus.publishOutbound({
|
|
90
|
+
channel: job.payload.channel ?? "cli",
|
|
91
|
+
chatId: job.payload.to,
|
|
92
|
+
content: response,
|
|
93
|
+
media: [],
|
|
94
|
+
metadata
|
|
95
|
+
});
|
|
96
|
+
return response;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { createCronJobHandler };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NextclawGatewayRuntime } from "./nextclaw-gateway-runtime.service.js";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/services/gateway/gateway-restart-wake.service.d.ts
|
|
4
|
+
declare class GatewayRestartWakeService {
|
|
5
|
+
private readonly gateway;
|
|
6
|
+
constructor(gateway: NextclawGatewayRuntime);
|
|
7
|
+
wakeFromRestartSentinel: () => Promise<void>;
|
|
8
|
+
private resolveMostRecentRoutableSessionKey;
|
|
9
|
+
private buildRestartWakePrompt;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { GatewayRestartWakeService };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { consumeRestartSentinel, formatRestartSentinelMessage, parseSessionKey } from "../restart/restart-sentinel.service.js";
|
|
2
|
+
import { resolveSessionRouteCandidate } from "../runtime/service-managed-startup.service.js";
|
|
3
|
+
import { parseAgentScopedSessionKey } from "@nextclaw/core";
|
|
4
|
+
//#region src/shared/services/gateway/gateway-restart-wake.service.ts
|
|
5
|
+
function normalizeOptionalString(value) {
|
|
6
|
+
if (typeof value !== "string") return;
|
|
7
|
+
return value.trim() || void 0;
|
|
8
|
+
}
|
|
9
|
+
var GatewayRestartWakeService = class {
|
|
10
|
+
constructor(gateway) {
|
|
11
|
+
this.gateway = gateway;
|
|
12
|
+
}
|
|
13
|
+
wakeFromRestartSentinel = async () => {
|
|
14
|
+
const sentinel = await consumeRestartSentinel();
|
|
15
|
+
if (!sentinel) return;
|
|
16
|
+
await new Promise((resolvePromise) => setTimeout(resolvePromise, 750));
|
|
17
|
+
const payload = sentinel.payload;
|
|
18
|
+
const summary = formatRestartSentinelMessage(payload);
|
|
19
|
+
const sentinelSessionKey = normalizeOptionalString(payload.sessionKey);
|
|
20
|
+
const fallbackSessionKey = sentinelSessionKey ? void 0 : this.resolveMostRecentRoutableSessionKey();
|
|
21
|
+
if (!sentinelSessionKey && fallbackSessionKey) console.warn(`Warning: restart sentinel missing sessionKey; fallback to ${fallbackSessionKey}.`);
|
|
22
|
+
const sessionKey = sentinelSessionKey ?? fallbackSessionKey ?? "cli:default";
|
|
23
|
+
const parsedSession = parseSessionKey(sessionKey);
|
|
24
|
+
const parsedAgentSession = parseAgentScopedSessionKey(sessionKey);
|
|
25
|
+
const parsedSessionRoute = parsedSession && parsedSession.channel !== "agent" ? parsedSession : null;
|
|
26
|
+
const context = payload.deliveryContext;
|
|
27
|
+
const channel = normalizeOptionalString(context?.channel) ?? parsedSessionRoute?.channel ?? normalizeOptionalString((this.gateway.sessionManager.getIfExists(sessionKey)?.metadata ?? {}).last_channel);
|
|
28
|
+
const chatId = normalizeOptionalString(context?.chatId) ?? parsedSessionRoute?.chatId ?? normalizeOptionalString((this.gateway.sessionManager.getIfExists(sessionKey)?.metadata ?? {}).last_to);
|
|
29
|
+
const replyTo = normalizeOptionalString(context?.replyTo);
|
|
30
|
+
const accountId = normalizeOptionalString(context?.accountId);
|
|
31
|
+
if (!channel || !chatId) {
|
|
32
|
+
console.warn(`Warning: restart sentinel cannot resolve route for session ${sessionKey}.`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
await this.gateway.messageBus.publishInbound({
|
|
36
|
+
channel: "system",
|
|
37
|
+
senderId: "restart-sentinel",
|
|
38
|
+
chatId: `${channel}:${chatId}`,
|
|
39
|
+
content: this.buildRestartWakePrompt({
|
|
40
|
+
summary,
|
|
41
|
+
reason: normalizeOptionalString(payload.stats?.reason),
|
|
42
|
+
note: normalizeOptionalString(payload.message),
|
|
43
|
+
...replyTo ? { replyTo } : {}
|
|
44
|
+
}),
|
|
45
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
46
|
+
attachments: [],
|
|
47
|
+
metadata: {
|
|
48
|
+
source: "restart-sentinel",
|
|
49
|
+
restart_summary: summary,
|
|
50
|
+
session_key_override: sessionKey,
|
|
51
|
+
...replyTo ? { reply_to: replyTo } : {},
|
|
52
|
+
...parsedAgentSession ? { target_agent_id: parsedAgentSession.agentId } : {},
|
|
53
|
+
...accountId ? {
|
|
54
|
+
account_id: accountId,
|
|
55
|
+
accountId
|
|
56
|
+
} : {}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
resolveMostRecentRoutableSessionKey = () => {
|
|
61
|
+
let best = null;
|
|
62
|
+
for (const session of this.gateway.sessionManager.listSessions()) {
|
|
63
|
+
const candidate = resolveSessionRouteCandidate({
|
|
64
|
+
session,
|
|
65
|
+
normalizeOptionalString
|
|
66
|
+
});
|
|
67
|
+
if (!candidate) continue;
|
|
68
|
+
if (!best || candidate.updatedAt >= best.updatedAt) best = candidate;
|
|
69
|
+
}
|
|
70
|
+
return best?.key;
|
|
71
|
+
};
|
|
72
|
+
buildRestartWakePrompt = (params) => {
|
|
73
|
+
const { note, reason, replyTo, summary } = params;
|
|
74
|
+
const lines = [
|
|
75
|
+
"System event: the gateway has restarted successfully.",
|
|
76
|
+
"Please send one short confirmation to the user that you are back online.",
|
|
77
|
+
"Do not call any tools.",
|
|
78
|
+
"Use the same language as the user's recent conversation.",
|
|
79
|
+
`Reference summary: ${summary}`
|
|
80
|
+
];
|
|
81
|
+
const normalizedReason = normalizeOptionalString(reason);
|
|
82
|
+
if (normalizedReason) lines.push(`Restart reason: ${normalizedReason}`);
|
|
83
|
+
const normalizedNote = normalizeOptionalString(note);
|
|
84
|
+
if (normalizedNote) lines.push(`Extra note: ${normalizedNote}`);
|
|
85
|
+
const normalizedReplyTo = normalizeOptionalString(replyTo);
|
|
86
|
+
if (normalizedReplyTo) lines.push(`Reply target message id: ${normalizedReplyTo}. If suitable, include [[reply_to:${normalizedReplyTo}]].`);
|
|
87
|
+
return lines.join("\n");
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
//#endregion
|
|
91
|
+
export { GatewayRestartWakeService };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { NextclawExtensionRegistry } from "../../../../commands/plugin/plugin-extension-registry.js";
|
|
2
|
+
import { NextclawGatewayRuntime } from "../nextclaw-gateway-runtime.service.js";
|
|
3
|
+
import { Config } from "@nextclaw/core";
|
|
4
|
+
import { PluginChannelBinding, PluginRegistry, PluginUiMetadata } from "@nextclaw/openclaw-compat";
|
|
5
|
+
|
|
6
|
+
//#region src/shared/services/gateway/managers/gateway-plugin.manager.d.ts
|
|
7
|
+
declare class GatewayPluginManager {
|
|
8
|
+
private readonly gateway;
|
|
9
|
+
private extensionContributions;
|
|
10
|
+
private snapshot;
|
|
11
|
+
private gatewayHandles;
|
|
12
|
+
constructor(gateway: NextclawGatewayRuntime);
|
|
13
|
+
getRegistry: () => PluginRegistry;
|
|
14
|
+
getExtensionRegistry: () => NextclawExtensionRegistry;
|
|
15
|
+
getChannelBindings: () => PluginChannelBinding[];
|
|
16
|
+
getUiMetadata: () => PluginUiMetadata[];
|
|
17
|
+
load: () => Promise<void>;
|
|
18
|
+
reloadForConfigChange: (params: {
|
|
19
|
+
config: Config;
|
|
20
|
+
changedPaths: string[];
|
|
21
|
+
}) => Promise<{
|
|
22
|
+
restartChannels: boolean;
|
|
23
|
+
}>;
|
|
24
|
+
reloadForDevHotReload: (changedPaths: string[]) => Promise<void>;
|
|
25
|
+
startGateways: () => Promise<void>;
|
|
26
|
+
publishConfigChanges: () => void;
|
|
27
|
+
restartGateways: () => Promise<void>;
|
|
28
|
+
stopGateways: () => Promise<void>;
|
|
29
|
+
private startChannelGateways;
|
|
30
|
+
private resolveGatewayAccountIds;
|
|
31
|
+
private reportGatewayStartFailure;
|
|
32
|
+
private isChannelEnabled;
|
|
33
|
+
private replaceSnapshot;
|
|
34
|
+
private loadKernelExtensionContributions;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { GatewayPluginManager };
|