@nextclaw/service 0.1.11 → 0.1.12
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/dist/cli/commands/agent/agent-runtime.utils.d.ts +1 -2
- package/dist/cli/commands/agent/agent-runtime.utils.js +6 -50
- package/dist/cli/commands/agent/cli-agent-runner.utils.d.ts +0 -2
- package/dist/cli/commands/agent/cli-agent-runner.utils.js +7 -9
- package/dist/cli/commands/agent/services/agent-commands.service.js +0 -1
- package/dist/cli/commands/skills/index.js +1 -1
- package/dist/cli/commands/skills/marketplace-client.d.ts +11 -1
- package/dist/cli/commands/skills/marketplace-client.js +39 -1
- package/dist/cli/commands/skills/marketplace-command-options.utils.d.ts +1 -1
- package/dist/cli/commands/skills/marketplace.metadata.d.ts +3 -12
- package/dist/cli/commands/skills/marketplace.metadata.js +1 -87
- package/dist/cli/commands/skills/{marketplace.service.d.ts → marketplace.utils.d.ts} +1 -1
- package/dist/cli/commands/skills/{marketplace.service.js → marketplace.utils.js} +11 -47
- package/dist/cli/commands/skills/skills-query.service.d.ts +5 -37
- package/dist/cli/commands/skills/skills-query.service.js +16 -98
- package/dist/cli/commands/usage/services/llm-usage-command.service.d.ts +3 -5
- package/dist/cli/commands/usage/services/llm-usage-command.service.js +16 -26
- package/dist/commands/channel/channel-list-view.service.d.ts +0 -1
- package/dist/commands/channel/channel-list-view.service.js +6 -23
- package/dist/commands/channel/index.js +0 -1
- package/dist/commands/plugin/index.d.ts +2 -4
- package/dist/commands/plugin/index.js +8 -20
- package/dist/commands/plugin/{plugin-command-utils.d.ts → plugin-command.utils.d.ts} +1 -2
- package/dist/commands/plugin/{plugin-command-utils.js → plugin-command.utils.js} +2 -4
- package/dist/commands/plugin/{plugin-mutation-actions.d.ts → plugin-mutation-actions.utils.d.ts} +1 -1
- package/dist/commands/plugin/{plugin-mutation-actions.js → plugin-mutation-actions.utils.js} +2 -2
- package/dist/commands/service/services/autostart/linux-systemd-autostart.service.js +1 -1
- package/dist/commands/service/services/autostart/macos-launch-agent-autostart.service.js +1 -1
- package/dist/commands/service/services/autostart/windows-task-autostart.service.js +1 -1
- package/dist/launcher/npm-runtime-launcher.service.js +1 -1
- package/dist/service-runtime.service.d.ts +1 -1
- package/dist/service-runtime.service.js +7 -15
- package/dist/shared/controllers/gateway.controller.d.ts +3 -11
- package/dist/shared/controllers/gateway.controller.js +24 -180
- package/dist/shared/services/gateway/managers/gateway-plugin.manager.d.ts +3 -9
- package/dist/shared/services/gateway/managers/gateway-plugin.manager.js +30 -88
- package/dist/shared/services/gateway/nextclaw-app.service.d.ts +2 -7
- package/dist/shared/services/gateway/nextclaw-app.service.js +6 -16
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts +4 -9
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js +12 -46
- package/dist/shared/services/gateway/{cron-job-handler.service.d.ts → utils/cron-job-handler.utils.d.ts} +3 -6
- package/dist/shared/services/gateway/utils/cron-job-handler.utils.js +57 -0
- package/dist/shared/services/marketplace/service-marketplace-installer.service.js +3 -3
- package/dist/shared/services/plugin/utils/plugin-runtime-bridge.utils.js +1 -1
- package/dist/shared/services/runtime/runtime-command.service.js +2 -2
- package/dist/shared/services/runtime/service-managed-startup.service.js +1 -1
- package/dist/shared/services/ui/companion-runtime.service.js +1 -1
- package/dist/shared/services/workspace/workspace-manager.service.js +8 -10
- package/dist/shared/utils/cli.utils.js +1 -1
- package/package.json +20 -20
- package/dist/cli/commands/usage/services/llm-usage-query.service.d.ts +0 -43
- package/dist/cli/commands/usage/services/llm-usage-query.service.js +0 -85
- package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.d.ts +0 -18
- package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.js +0 -111
- package/dist/commands/plugin/development-source/first-party-plugin-load-paths.utils.d.ts +0 -9
- package/dist/commands/plugin/development-source/first-party-plugin-load-paths.utils.js +0 -183
- package/dist/commands/plugin/plugin-extension-registry.d.ts +0 -10
- package/dist/commands/plugin/plugin-extension-registry.js +0 -35
- package/dist/commands/plugin/plugin-registry-loader.utils.d.ts +0 -14
- package/dist/commands/plugin/plugin-registry-loader.utils.js +0 -43
- package/dist/commands/plugin/plugin-reload.d.ts +0 -13
- package/dist/commands/plugin/plugin-reload.js +0 -42
- package/dist/shared/services/extensions/extension-lifecycle.service.d.ts +0 -63
- package/dist/shared/services/extensions/extension-lifecycle.service.js +0 -174
- package/dist/shared/services/extensions/service-extension-runtime.service.d.ts +0 -52
- package/dist/shared/services/extensions/service-extension-runtime.service.js +0 -325
- package/dist/shared/services/gateway/cron-job-handler.service.js +0 -100
- package/dist/shared/services/runtime/utils/skills-loader.utils.d.ts +0 -12
- package/dist/shared/services/runtime/utils/skills-loader.utils.js +0 -9
- package/dist/shared/services/session/service-deferred-ncp-agent.service.d.ts +0 -14
- package/dist/shared/services/session/service-deferred-ncp-agent.service.js +0 -85
|
@@ -2,59 +2,8 @@ import { parseSessionKey, writeRestartSentinel } from "../services/restart/resta
|
|
|
2
2
|
import { getPackageVersion as getPackageVersion$1 } from "../utils/package/package-manifest.utils.js";
|
|
3
3
|
import "../utils/cli.utils.js";
|
|
4
4
|
import { NpmRuntimeUpdateCommandService } from "../../launcher/npm-runtime-update-command.service.js";
|
|
5
|
-
import
|
|
6
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
-
import { createHash } from "node:crypto";
|
|
5
|
+
import "@nextclaw/core";
|
|
8
6
|
//#region src/shared/controllers/gateway.controller.ts
|
|
9
|
-
const hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
|
|
10
|
-
const readConfigSnapshot = (getConfigPath) => {
|
|
11
|
-
const path = getConfigPath();
|
|
12
|
-
let raw = "";
|
|
13
|
-
let parsed = {};
|
|
14
|
-
if (existsSync(path)) {
|
|
15
|
-
raw = readFileSync(path, "utf-8");
|
|
16
|
-
try {
|
|
17
|
-
parsed = JSON.parse(raw);
|
|
18
|
-
} catch {
|
|
19
|
-
parsed = {};
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
let config;
|
|
23
|
-
let valid = true;
|
|
24
|
-
try {
|
|
25
|
-
config = ConfigSchema.parse(normalizeInlineSecretRefs(parsed));
|
|
26
|
-
} catch {
|
|
27
|
-
config = ConfigSchema.parse({});
|
|
28
|
-
valid = false;
|
|
29
|
-
}
|
|
30
|
-
if (!raw) raw = JSON.stringify(config, null, 2);
|
|
31
|
-
const hash = hashRaw(raw);
|
|
32
|
-
const schema = buildConfigSchema({ version: getPackageVersion$1() });
|
|
33
|
-
const redacted = redactConfigObject(config, schema.uiHints);
|
|
34
|
-
return {
|
|
35
|
-
raw: valid ? JSON.stringify(redacted, null, 2) : null,
|
|
36
|
-
hash: valid ? hash : null,
|
|
37
|
-
config,
|
|
38
|
-
redacted,
|
|
39
|
-
valid
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
const redactValue = (value) => {
|
|
43
|
-
return redactConfigObject(value, buildConfigSchema({ version: getPackageVersion$1() }).uiHints);
|
|
44
|
-
};
|
|
45
|
-
const mergeDeep = (base, patch) => {
|
|
46
|
-
const next = { ...base };
|
|
47
|
-
for (const [key, value] of Object.entries(patch)) if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
48
|
-
const baseVal = base[key];
|
|
49
|
-
if (baseVal && typeof baseVal === "object" && !Array.isArray(baseVal)) next[key] = mergeDeep(baseVal, value);
|
|
50
|
-
else next[key] = mergeDeep({}, value);
|
|
51
|
-
} else next[key] = value;
|
|
52
|
-
return next;
|
|
53
|
-
};
|
|
54
|
-
const buildPendingRestartMessage = (paths) => {
|
|
55
|
-
if (paths.length === 0) return "Config saved. Restart manually to apply changes.";
|
|
56
|
-
return `Config saved. Restart manually to apply: ${paths.join(", ")}.`;
|
|
57
|
-
};
|
|
58
7
|
var GatewayControllerImpl = class {
|
|
59
8
|
constructor(deps) {
|
|
60
9
|
this.deps = deps;
|
|
@@ -87,19 +36,20 @@ var GatewayControllerImpl = class {
|
|
|
87
36
|
};
|
|
88
37
|
};
|
|
89
38
|
writeRestartSentinelPayload = async (params) => {
|
|
90
|
-
const sessionKey =
|
|
39
|
+
const { kind, note, reason, sessionKey: rawSessionKey, status, strategy } = params;
|
|
40
|
+
const sessionKey = this.normalizeOptionalString(rawSessionKey);
|
|
91
41
|
const deliveryContext = this.resolveDeliveryContext(sessionKey);
|
|
92
42
|
try {
|
|
93
43
|
return await writeRestartSentinel({
|
|
94
|
-
kind
|
|
95
|
-
status
|
|
44
|
+
kind,
|
|
45
|
+
status,
|
|
96
46
|
ts: Date.now(),
|
|
97
47
|
sessionKey,
|
|
98
48
|
deliveryContext,
|
|
99
|
-
message:
|
|
49
|
+
message: note ?? null,
|
|
100
50
|
stats: {
|
|
101
|
-
reason:
|
|
102
|
-
strategy:
|
|
51
|
+
reason: reason ?? null,
|
|
52
|
+
strategy: strategy ?? null
|
|
103
53
|
}
|
|
104
54
|
});
|
|
105
55
|
} catch {
|
|
@@ -107,58 +57,22 @@ var GatewayControllerImpl = class {
|
|
|
107
57
|
}
|
|
108
58
|
};
|
|
109
59
|
requestRestart = async (options) => {
|
|
60
|
+
const { delayMs, reason } = options ?? {};
|
|
110
61
|
if (this.deps.requestRestart) {
|
|
111
62
|
await this.deps.requestRestart(options);
|
|
112
63
|
return;
|
|
113
64
|
}
|
|
114
|
-
const delay = typeof
|
|
115
|
-
console.log(`Gateway restart requested via tool${
|
|
65
|
+
const delay = typeof delayMs === "number" && Number.isFinite(delayMs) ? Math.max(0, delayMs) : 100;
|
|
66
|
+
console.log(`Gateway restart requested via tool${reason ? ` (${reason})` : ""}.`);
|
|
116
67
|
setTimeout(() => {
|
|
117
68
|
process.exit(0);
|
|
118
69
|
}, delay);
|
|
119
70
|
};
|
|
120
|
-
createConfigMutationResult = (params) => {
|
|
121
|
-
const pendingRestart = params.plan.restartRequired.length > 0 ? {
|
|
122
|
-
required: true,
|
|
123
|
-
automatic: false,
|
|
124
|
-
changedPaths: [...params.plan.restartRequired],
|
|
125
|
-
message: buildPendingRestartMessage(params.plan.restartRequired)
|
|
126
|
-
} : null;
|
|
127
|
-
const message = params.changedPaths.length === 0 ? "Config already matched the requested state." : pendingRestart ? params.changedPaths.length > params.plan.restartRequired.length ? "Config saved. Supported changes were applied immediately; restart manually to apply the rest." : "Config saved. Restart manually to apply changes." : "Config saved and applied.";
|
|
128
|
-
return {
|
|
129
|
-
ok: true,
|
|
130
|
-
note: params.note ?? null,
|
|
131
|
-
path: this.deps.getConfigPath(),
|
|
132
|
-
config: redactValue(params.config),
|
|
133
|
-
changedPaths: [...params.changedPaths],
|
|
134
|
-
message,
|
|
135
|
-
pendingRestart
|
|
136
|
-
};
|
|
137
|
-
};
|
|
138
|
-
applyConfigChange = async (params) => {
|
|
139
|
-
const { nextConfig, note } = params;
|
|
140
|
-
const changedPaths = diffConfigPaths(readConfigSnapshot(this.deps.getConfigPath).config, nextConfig);
|
|
141
|
-
const plan = buildReloadPlan(changedPaths);
|
|
142
|
-
if (changedPaths.length === 0) return this.createConfigMutationResult({
|
|
143
|
-
changedPaths,
|
|
144
|
-
config: nextConfig,
|
|
145
|
-
note,
|
|
146
|
-
plan
|
|
147
|
-
});
|
|
148
|
-
this.deps.saveConfig(nextConfig);
|
|
149
|
-
await this.deps.configManager.applyReloadPlan(nextConfig);
|
|
150
|
-
return this.createConfigMutationResult({
|
|
151
|
-
changedPaths,
|
|
152
|
-
config: nextConfig,
|
|
153
|
-
note,
|
|
154
|
-
plan
|
|
155
|
-
});
|
|
156
|
-
};
|
|
157
71
|
status = () => {
|
|
158
72
|
return {
|
|
159
73
|
channels: this.deps.channels.enabledChannels,
|
|
160
74
|
cron: this.deps.cron.status(),
|
|
161
|
-
configPath: this.deps.
|
|
75
|
+
configPath: this.deps.configManager.configPath
|
|
162
76
|
};
|
|
163
77
|
};
|
|
164
78
|
reloadConfig = async (reason) => {
|
|
@@ -175,95 +89,25 @@ var GatewayControllerImpl = class {
|
|
|
175
89
|
return "Restart scheduled";
|
|
176
90
|
};
|
|
177
91
|
getConfig = async () => {
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
raw: snapshot.raw,
|
|
181
|
-
hash: snapshot.hash,
|
|
182
|
-
path: this.deps.getConfigPath(),
|
|
183
|
-
config: snapshot.redacted,
|
|
184
|
-
parsed: snapshot.redacted,
|
|
185
|
-
resolved: snapshot.redacted,
|
|
186
|
-
valid: snapshot.valid
|
|
187
|
-
};
|
|
92
|
+
return this.deps.configManager.getConfigSnapshot({ version: getPackageVersion$1() });
|
|
188
93
|
};
|
|
189
94
|
getConfigSchema = async () => {
|
|
190
|
-
return
|
|
95
|
+
return this.deps.configManager.getConfigSchema({ version: getPackageVersion$1() });
|
|
191
96
|
};
|
|
192
97
|
applyConfig = async (params) => {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (!snapshot.valid || !snapshot.hash) return {
|
|
199
|
-
ok: false,
|
|
200
|
-
error: "config base hash unavailable; re-run config.get and retry"
|
|
201
|
-
};
|
|
202
|
-
if (params.baseHash !== snapshot.hash) return {
|
|
203
|
-
ok: false,
|
|
204
|
-
error: "config changed since last load; re-run config.get and retry"
|
|
205
|
-
};
|
|
206
|
-
let parsedRaw;
|
|
207
|
-
try {
|
|
208
|
-
parsedRaw = JSON.parse(params.raw);
|
|
209
|
-
} catch {
|
|
210
|
-
return {
|
|
211
|
-
ok: false,
|
|
212
|
-
error: "invalid JSON in raw config"
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
let validated;
|
|
216
|
-
try {
|
|
217
|
-
validated = ConfigSchema.parse(normalizeInlineSecretRefs(parsedRaw));
|
|
218
|
-
} catch (err) {
|
|
219
|
-
return {
|
|
220
|
-
ok: false,
|
|
221
|
-
error: `invalid config: ${String(err)}`
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
return this.applyConfigChange({
|
|
225
|
-
kind: "config.apply",
|
|
226
|
-
nextConfig: validated,
|
|
227
|
-
note: params.note
|
|
98
|
+
return this.deps.configManager.applyRawConfig({
|
|
99
|
+
raw: params.raw,
|
|
100
|
+
baseHash: params.baseHash,
|
|
101
|
+
note: params.note,
|
|
102
|
+
version: getPackageVersion$1()
|
|
228
103
|
});
|
|
229
104
|
};
|
|
230
105
|
patchConfig = async (params) => {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (!snapshot.valid || !snapshot.hash) return {
|
|
237
|
-
ok: false,
|
|
238
|
-
error: "config base hash unavailable; re-run config.get and retry"
|
|
239
|
-
};
|
|
240
|
-
if (params.baseHash !== snapshot.hash) return {
|
|
241
|
-
ok: false,
|
|
242
|
-
error: "config changed since last load; re-run config.get and retry"
|
|
243
|
-
};
|
|
244
|
-
let patch;
|
|
245
|
-
try {
|
|
246
|
-
patch = JSON.parse(params.raw);
|
|
247
|
-
} catch {
|
|
248
|
-
return {
|
|
249
|
-
ok: false,
|
|
250
|
-
error: "invalid JSON in raw config"
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
const merged = mergeDeep(snapshot.config, patch);
|
|
254
|
-
let validated;
|
|
255
|
-
try {
|
|
256
|
-
validated = ConfigSchema.parse(normalizeInlineSecretRefs(merged));
|
|
257
|
-
} catch (err) {
|
|
258
|
-
return {
|
|
259
|
-
ok: false,
|
|
260
|
-
error: `invalid config: ${String(err)}`
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
return this.applyConfigChange({
|
|
264
|
-
kind: "config.patch",
|
|
265
|
-
nextConfig: validated,
|
|
266
|
-
note: params.note
|
|
106
|
+
return this.deps.configManager.patchRawConfig({
|
|
107
|
+
raw: params.raw,
|
|
108
|
+
baseHash: params.baseHash,
|
|
109
|
+
note: params.note,
|
|
110
|
+
version: getPackageVersion$1()
|
|
267
111
|
});
|
|
268
112
|
};
|
|
269
113
|
updateRun = async (params) => {
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
import { NextclawExtensionRegistry } from "../../../../commands/plugin/plugin-extension-registry.js";
|
|
2
1
|
import { NextclawGatewayRuntime } from "../nextclaw-gateway-runtime.service.js";
|
|
3
2
|
import { Config } from "@nextclaw/core";
|
|
4
|
-
import
|
|
3
|
+
import * as _$_nextclaw_openclaw_compat0 from "@nextclaw/openclaw-compat";
|
|
4
|
+
import { PluginChannelBinding } from "@nextclaw/openclaw-compat";
|
|
5
5
|
|
|
6
6
|
//#region src/shared/services/gateway/managers/gateway-plugin.manager.d.ts
|
|
7
7
|
declare class GatewayPluginManager {
|
|
8
8
|
private readonly gateway;
|
|
9
|
-
private extensionContributions;
|
|
10
|
-
private snapshot;
|
|
11
9
|
private gatewayHandles;
|
|
12
10
|
constructor(gateway: NextclawGatewayRuntime);
|
|
13
|
-
getRegistry: () => PluginRegistry;
|
|
14
|
-
getExtensionRegistry: () => NextclawExtensionRegistry;
|
|
15
11
|
getChannelBindings: () => PluginChannelBinding[];
|
|
16
|
-
getUiMetadata: () => PluginUiMetadata[];
|
|
12
|
+
getUiMetadata: () => _$_nextclaw_openclaw_compat0.PluginUiMetadata[];
|
|
17
13
|
load: () => Promise<void>;
|
|
18
14
|
reloadForConfigChange: (params: {
|
|
19
15
|
config: Config;
|
|
@@ -30,8 +26,6 @@ declare class GatewayPluginManager {
|
|
|
30
26
|
private resolveGatewayAccountIds;
|
|
31
27
|
private reportGatewayStartFailure;
|
|
32
28
|
private isChannelEnabled;
|
|
33
|
-
private replaceSnapshot;
|
|
34
|
-
private loadKernelExtensionContributions;
|
|
35
29
|
}
|
|
36
30
|
//#endregion
|
|
37
31
|
export { GatewayPluginManager };
|
|
@@ -1,76 +1,38 @@
|
|
|
1
|
-
import { toExtensionRegistry } from "../../../../commands/plugin/plugin-extension-registry.js";
|
|
2
|
-
import { createEmptyPluginRegistry, discoverPluginRegistryStatus, loadPluginRegistryProgressively } from "../../../../commands/plugin/plugin-registry-loader.utils.js";
|
|
3
1
|
import { logPluginDiagnostics } from "../../../../commands/plugin/index.js";
|
|
4
|
-
import { shouldRestartChannelsForPluginReload } from "../../../../commands/plugin/plugin-reload.js";
|
|
5
2
|
import { logPluginGatewayDiagnostics, pluginGatewayLogger } from "../service-startup-support.service.js";
|
|
6
|
-
import {
|
|
7
|
-
import { getPluginChannelBindings, getPluginUiMetadataFromRegistry, toPluginConfigView } from "@nextclaw/openclaw-compat";
|
|
3
|
+
import { toPluginConfigView } from "@nextclaw/openclaw-compat";
|
|
8
4
|
import { eventKeys } from "@nextclaw/shared";
|
|
9
5
|
//#region src/shared/services/gateway/managers/gateway-plugin.manager.ts
|
|
10
|
-
function toManifestChannelRegistrations(channelBindings) {
|
|
11
|
-
return channelBindings.map((binding) => ({
|
|
12
|
-
extensionId: binding.pluginId,
|
|
13
|
-
channel: binding.channel,
|
|
14
|
-
source: "extension-manifest"
|
|
15
|
-
}));
|
|
16
|
-
}
|
|
17
|
-
function buildSnapshot(registry, extensionContributions) {
|
|
18
|
-
const extensionChannelIds = new Set(extensionContributions.channelBindings.map((binding) => binding.channelId));
|
|
19
|
-
const extensionPluginIds = new Set(extensionContributions.uiMetadata.map((metadata) => metadata.id));
|
|
20
|
-
const registryExtensionRegistry = toExtensionRegistry(registry);
|
|
21
|
-
return {
|
|
22
|
-
registry,
|
|
23
|
-
extensionRegistry: {
|
|
24
|
-
...registryExtensionRegistry,
|
|
25
|
-
channels: [...registryExtensionRegistry.channels.filter((registration) => {
|
|
26
|
-
const channelId = registration.channel.id?.trim();
|
|
27
|
-
return !channelId || !extensionChannelIds.has(channelId);
|
|
28
|
-
}), ...toManifestChannelRegistrations(extensionContributions.channelBindings)]
|
|
29
|
-
},
|
|
30
|
-
channelBindings: [...getPluginChannelBindings(registry).filter((binding) => !extensionChannelIds.has(binding.channelId)), ...extensionContributions.channelBindings],
|
|
31
|
-
uiMetadata: [...getPluginUiMetadataFromRegistry(registry).filter((metadata) => !extensionPluginIds.has(metadata.id)), ...extensionContributions.uiMetadata]
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
function countEnabledPlugins(config, workspaceDir) {
|
|
35
|
-
return discoverPluginRegistryStatus(config, workspaceDir).plugins.filter((plugin) => plugin.enabled).length;
|
|
36
|
-
}
|
|
37
6
|
var GatewayPluginManager = class {
|
|
38
|
-
extensionContributions = {
|
|
39
|
-
channelBindings: [],
|
|
40
|
-
uiMetadata: []
|
|
41
|
-
};
|
|
42
|
-
snapshot = buildSnapshot(createEmptyPluginRegistry(), this.extensionContributions);
|
|
43
7
|
gatewayHandles = [];
|
|
44
8
|
constructor(gateway) {
|
|
45
9
|
this.gateway = gateway;
|
|
46
10
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
getChannelBindings = () => this.snapshot.channelBindings;
|
|
50
|
-
getUiMetadata = () => this.snapshot.uiMetadata;
|
|
11
|
+
getChannelBindings = () => this.gateway.kernel.extensions.getChannelBindings();
|
|
12
|
+
getUiMetadata = () => this.gateway.kernel.extensions.getUiMetadata();
|
|
51
13
|
load = async () => {
|
|
52
14
|
const config = this.gateway.configManager.loadConfig();
|
|
53
|
-
|
|
54
|
-
const totalPluginCount = countEnabledPlugins(config, workspace);
|
|
55
|
-
let loadedPluginCount = 0;
|
|
56
|
-
this.gateway.bootstrapStatus.markPluginHydrationRunning({ totalPluginCount });
|
|
15
|
+
let totalPluginCount = 0;
|
|
57
16
|
this.gateway.bootstrapStatus.markChannelsPending();
|
|
58
17
|
try {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
totalPluginCount
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
18
|
+
const result = await this.gateway.kernel.extensions.load({
|
|
19
|
+
config,
|
|
20
|
+
onLoadStart: ({ totalPluginCount: nextTotalPluginCount }) => {
|
|
21
|
+
totalPluginCount = nextTotalPluginCount;
|
|
22
|
+
this.gateway.bootstrapStatus.markPluginHydrationRunning({ totalPluginCount: nextTotalPluginCount });
|
|
23
|
+
},
|
|
24
|
+
onPluginProcessed: ({ loadedPluginCount: nextCount }) => {
|
|
25
|
+
this.gateway.bootstrapStatus.markPluginHydrationProgress({
|
|
26
|
+
loadedPluginCount: nextCount,
|
|
27
|
+
totalPluginCount
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
logPluginDiagnostics({ diagnostics: result.diagnostics });
|
|
32
|
+
if (result.shouldRestartChannels) await this.gateway.configManager.rebuildChannels(config, { start: false });
|
|
71
33
|
this.publishConfigChanges();
|
|
72
34
|
this.gateway.bootstrapStatus.markPluginHydrationReady({
|
|
73
|
-
loadedPluginCount: loadedPluginCount
|
|
35
|
+
loadedPluginCount: result.loadedPluginCount,
|
|
74
36
|
totalPluginCount
|
|
75
37
|
});
|
|
76
38
|
} catch (error) {
|
|
@@ -79,15 +41,14 @@ var GatewayPluginManager = class {
|
|
|
79
41
|
}
|
|
80
42
|
};
|
|
81
43
|
reloadForConfigChange = async (params) => {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (restartChannels) await this.restartGateways();
|
|
44
|
+
const result = await this.gateway.kernel.extensions.reloadForConfigChange({
|
|
45
|
+
config: params.config,
|
|
46
|
+
changedPaths: params.changedPaths
|
|
47
|
+
});
|
|
48
|
+
logPluginDiagnostics({ diagnostics: result.diagnostics });
|
|
49
|
+
if (result.shouldRestartChannels) await this.restartGateways();
|
|
89
50
|
this.publishConfigChanges();
|
|
90
|
-
return { restartChannels };
|
|
51
|
+
return { restartChannels: result.shouldRestartChannels };
|
|
91
52
|
};
|
|
92
53
|
reloadForDevHotReload = async (changedPaths) => {
|
|
93
54
|
const config = this.gateway.configManager.loadConfig();
|
|
@@ -100,8 +61,9 @@ var GatewayPluginManager = class {
|
|
|
100
61
|
const config = this.gateway.configManager.loadConfig();
|
|
101
62
|
const diagnostics = [];
|
|
102
63
|
const handles = [];
|
|
103
|
-
const
|
|
104
|
-
|
|
64
|
+
const channelBindings = this.gateway.kernel.extensions.getChannelBindings();
|
|
65
|
+
const configView = toPluginConfigView(config, channelBindings);
|
|
66
|
+
for (const binding of channelBindings) {
|
|
105
67
|
if (!this.isChannelEnabled(binding.channelId, configView)) continue;
|
|
106
68
|
await this.startChannelGateways({
|
|
107
69
|
binding,
|
|
@@ -207,26 +169,6 @@ var GatewayPluginManager = class {
|
|
|
207
169
|
if (!channelConfig || typeof channelConfig !== "object" || Array.isArray(channelConfig)) return false;
|
|
208
170
|
return channelConfig.enabled === true;
|
|
209
171
|
};
|
|
210
|
-
replaceSnapshot = (registry, changedPaths) => {
|
|
211
|
-
const nextSnapshot = buildSnapshot(registry, this.extensionContributions);
|
|
212
|
-
const shouldRestartChannels = shouldRestartChannelsForPluginReload({
|
|
213
|
-
changedPaths,
|
|
214
|
-
currentPluginChannelBindings: this.snapshot.channelBindings,
|
|
215
|
-
nextPluginChannelBindings: nextSnapshot.channelBindings,
|
|
216
|
-
currentExtensionChannels: this.snapshot.extensionRegistry.channels,
|
|
217
|
-
nextExtensionChannels: nextSnapshot.extensionRegistry.channels
|
|
218
|
-
});
|
|
219
|
-
this.snapshot = nextSnapshot;
|
|
220
|
-
return shouldRestartChannels;
|
|
221
|
-
};
|
|
222
|
-
loadKernelExtensionContributions = (registry) => {
|
|
223
|
-
this.gateway.kernel.extensions.loadContributions({
|
|
224
|
-
registry,
|
|
225
|
-
extensionRegistry: this.snapshot.extensionRegistry,
|
|
226
|
-
channelBindings: this.snapshot.channelBindings,
|
|
227
|
-
uiMetadata: this.snapshot.uiMetadata
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
172
|
};
|
|
231
173
|
//#endregion
|
|
232
174
|
export { GatewayPluginManager };
|
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
import { DeferredUiNcpAgentController } from "../session/service-deferred-ncp-agent.service.js";
|
|
2
1
|
import { NextclawGatewayRuntime } from "./nextclaw-gateway-runtime.service.js";
|
|
3
|
-
import { NextclawKernel } from "@nextclaw/kernel";
|
|
4
2
|
|
|
5
3
|
//#region src/shared/services/gateway/nextclaw-app.service.d.ts
|
|
6
4
|
type UiStartupHandle = {
|
|
7
|
-
deferredNcpAgent: DeferredUiNcpAgentController;
|
|
8
5
|
endpoint: string;
|
|
9
6
|
};
|
|
10
|
-
type NextclawAppKernel = Pick<NextclawKernel, "agentRuntimeManager" | "start">;
|
|
11
7
|
declare class NextclawApp {
|
|
12
8
|
private readonly gateway;
|
|
13
9
|
private readonly kernel;
|
|
14
|
-
|
|
15
|
-
constructor(gateway: NextclawGatewayRuntime, kernel?: NextclawAppKernel);
|
|
10
|
+
constructor(gateway: NextclawGatewayRuntime);
|
|
16
11
|
start: () => Promise<void>;
|
|
17
12
|
bootstrapKernel: () => Promise<void>;
|
|
18
|
-
|
|
13
|
+
startDeferredRuntimeServices: () => Promise<void>;
|
|
19
14
|
private readonly handleKernelStartupError;
|
|
20
15
|
}
|
|
21
16
|
//#endregion
|
|
@@ -2,10 +2,9 @@ import { logStartupTrace, measureStartupAsync } from "../../utils/startup-trace.
|
|
|
2
2
|
//#region src/shared/services/gateway/nextclaw-app.service.ts
|
|
3
3
|
var NextclawApp = class {
|
|
4
4
|
kernel;
|
|
5
|
-
|
|
6
|
-
constructor(gateway, kernel) {
|
|
5
|
+
constructor(gateway) {
|
|
7
6
|
this.gateway = gateway;
|
|
8
|
-
this.kernel =
|
|
7
|
+
this.kernel = gateway.kernel;
|
|
9
8
|
}
|
|
10
9
|
start = async () => {
|
|
11
10
|
logStartupTrace("service.deferred_startup.begin");
|
|
@@ -14,35 +13,26 @@ var NextclawApp = class {
|
|
|
14
13
|
} catch (error) {
|
|
15
14
|
this.handleKernelStartupError(error);
|
|
16
15
|
}
|
|
17
|
-
await this.
|
|
16
|
+
await this.startDeferredRuntimeServices();
|
|
18
17
|
console.log("✓ Deferred startup: plugin gateways and channels settled");
|
|
19
18
|
logStartupTrace("service.deferred_startup.end");
|
|
20
19
|
};
|
|
21
20
|
bootstrapKernel = async () => {
|
|
22
21
|
this.gateway.bootstrapStatus.markNcpAgentRunning();
|
|
23
22
|
await measureStartupAsync("service.deferred_startup.bootstrap_kernel", async () => await this.kernel.start());
|
|
24
|
-
|
|
25
|
-
if (!ncpAgent) throw new Error("Kernel start completed without an agent runtime handle.");
|
|
26
|
-
this.gateway.activateAgentRuntime(ncpAgent);
|
|
27
|
-
this.kernelReady = true;
|
|
23
|
+
this.gateway.bootstrapStatus.markNcpAgentReady();
|
|
28
24
|
if (this.gateway.uiConfig.enabled) {
|
|
29
25
|
console.log("✓ UI NCP agent: ready");
|
|
30
26
|
return;
|
|
31
27
|
}
|
|
32
28
|
console.log("✓ Service NCP agent: ready");
|
|
33
29
|
};
|
|
34
|
-
|
|
30
|
+
startDeferredRuntimeServices = async () => {
|
|
35
31
|
await measureStartupAsync("service.deferred_startup.load_plugins", this.gateway.plugins.load);
|
|
36
32
|
await measureStartupAsync("service.deferred_startup.start_plugin_gateways", this.gateway.plugins.startGateways);
|
|
37
|
-
await measureStartupAsync("service.deferred_startup.start_extensions", this.
|
|
33
|
+
await measureStartupAsync("service.deferred_startup.start_extensions", async () => await this.kernel.extensions.start({ endpoint: this.gateway.uiStartup.endpoint }));
|
|
38
34
|
await measureStartupAsync("service.deferred_startup.start_channels", this.gateway.startDeferredChannels);
|
|
39
35
|
await measureStartupAsync("service.deferred_startup.wake_restart_sentinel", this.gateway.restartWake.wakeFromRestartSentinel);
|
|
40
|
-
if (!this.kernelReady) return;
|
|
41
|
-
setTimeout(() => {
|
|
42
|
-
measureStartupAsync("service.deferred_startup.warm_ncp_capabilities", async () => await this.kernel.agentRuntimeManager.warmDerivedCapabilities()).catch((error) => {
|
|
43
|
-
console.warn(`UI NCP derived capability warmup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
-
});
|
|
45
|
-
}, 0).unref?.();
|
|
46
36
|
};
|
|
47
37
|
handleKernelStartupError = (error) => {
|
|
48
38
|
this.gateway.bootstrapStatus.markNcpAgentError(error instanceof Error ? error.message : String(error));
|
|
@@ -3,14 +3,13 @@ import { NextclawDistribution } from "../../types/distribution.types.js";
|
|
|
3
3
|
import { GatewayControllerImpl } from "../../controllers/gateway.controller.js";
|
|
4
4
|
import { GatewayPluginManager } from "./managers/gateway-plugin.manager.js";
|
|
5
5
|
import { GatewayRemoteManager } from "./managers/gateway-remote.manager.js";
|
|
6
|
-
import { GatewayRestartWakeService } from "./gateway-restart-wake.service.js";
|
|
7
6
|
import { UiStartupHandle } from "./nextclaw-app.service.js";
|
|
8
7
|
import { ServiceBootstrapStatusStore } from "./service-bootstrap-status.service.js";
|
|
9
8
|
import { ServiceFileWatcherRegistry } from "./service-startup-support.service.js";
|
|
10
|
-
import {
|
|
9
|
+
import { GatewayRestartWakeService } from "./gateway-restart-wake.service.js";
|
|
11
10
|
import * as NextclawCore from "@nextclaw/core";
|
|
12
|
-
import {
|
|
13
|
-
import { MarketplaceApiConfig,
|
|
11
|
+
import { AutomationManager, ConfigManager, LlmProviderManager, NextclawKernel } from "@nextclaw/kernel";
|
|
12
|
+
import { MarketplaceApiConfig, UiRuntimeControlHost, UiRuntimeUpdateHost } from "@nextclaw/server";
|
|
14
13
|
import { EventBus, Ingress } from "@nextclaw/shared";
|
|
15
14
|
|
|
16
15
|
//#region src/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts
|
|
@@ -60,15 +59,11 @@ declare class NextclawGatewayRuntime {
|
|
|
60
59
|
readonly restartWake: GatewayRestartWakeService;
|
|
61
60
|
bootstrapStatus: ServiceBootstrapStatusStore;
|
|
62
61
|
uiStartup: UiStartupHandle;
|
|
63
|
-
readonly extensions: ServiceExtensionRuntime;
|
|
64
|
-
liveAgentRuntime: AgentRuntimeHandle | null;
|
|
65
62
|
readonly fileWatchers: ServiceFileWatcherRegistry;
|
|
66
63
|
private deferredChannelStarter;
|
|
67
64
|
constructor(deps: GatewayRuntimeDeps, options: GatewayRuntimeOptions);
|
|
68
65
|
start: () => Promise<void>;
|
|
69
66
|
private reset;
|
|
70
|
-
get ncpAgent(): UiNcpAgent;
|
|
71
|
-
activateAgentRuntime: (ncpAgent: AgentRuntimeHandle) => void;
|
|
72
67
|
private createBootstrapStatus;
|
|
73
68
|
private createDisabledUiStartup;
|
|
74
69
|
private startUiRuntime;
|
|
@@ -84,7 +79,7 @@ declare class NextclawGatewayRuntime {
|
|
|
84
79
|
private createGatewayController;
|
|
85
80
|
private startSupportServices;
|
|
86
81
|
private configurePluginRuntime;
|
|
87
|
-
private
|
|
82
|
+
private installConfigHostHooks;
|
|
88
83
|
private configureIngressHandlers;
|
|
89
84
|
}
|
|
90
85
|
//#endregion
|