nextclaw 0.18.12-beta.0 → 0.18.12-beta.10
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/app/index.js +870 -264
- package/dist/cli/launcher/index.js +8 -3
- package/dist/{npm-runtime-update-state.store-DaF0iDY9.js → npm-runtime-update-state.store-75vzvn0B.js} +200 -30
- package/package.json +17 -16
- package/resources/USAGE.md +41 -1
- package/ui-dist/assets/api-BcqDx0tm.js +15 -0
- package/ui-dist/assets/app-manager-provider-DVYBjif-.js +1 -0
- package/ui-dist/assets/app-navigation.config-CMoWvFEI.js +1 -0
- package/ui-dist/assets/{book-open-B4mOKdz8.js → book-open-DgLqYpNY.js} +1 -1
- package/ui-dist/assets/{channels-list-page-WJ7d4zMI.js → channels-list-page-CsoI4OJm.js} +2 -2
- package/ui-dist/assets/chat-CA3aRmhx.js +61 -0
- package/ui-dist/assets/chat-page-gdSN6Pr6.js +1 -0
- package/ui-dist/assets/chunk-JZWAC4HX-u4uYphxM.js +3 -0
- package/ui-dist/assets/{config-split-page-B3PRA_AV.js → config-split-page-BMRGuCJQ.js} +1 -1
- package/ui-dist/assets/{createLucideIcon-C_GFKVuW.js → createLucideIcon-BZkY6emz.js} +1 -1
- package/ui-dist/assets/desktop-update-config-CD6-2PfI.js +1 -0
- package/ui-dist/assets/{dialog-BHcaU6NE.js → dialog-csshWetU.js} +1 -1
- package/ui-dist/assets/{dist-DtBFqZ6_.js → dist-Bl94Ahwx.js} +1 -1
- package/ui-dist/assets/{doc-browser-CwgI7ipB.js → doc-browser-BUlCkZo2.js} +1 -1
- package/ui-dist/assets/doc-browser-CzCV73NJ.js +1 -0
- package/ui-dist/assets/doc-browser-Doh2541x.js +1 -0
- package/ui-dist/assets/{doc-browser-context-Dib9sS83.js → doc-browser-context-DfLHAWbG.js} +1 -1
- package/ui-dist/assets/{es2015-BlNhrQUG.js → es2015-JCM5-KtW.js} +1 -1
- package/ui-dist/assets/{external-link-DP2IJ7AM.js → external-link-Sw3ah_JD.js} +1 -1
- package/ui-dist/assets/{folder-BPwc278w.js → folder-D7-VTnkz.js} +1 -1
- package/ui-dist/assets/{hash-CvcvtMBq.js → hash-zajSTDXZ.js} +1 -1
- package/ui-dist/assets/i18n-C5Mibli1.js +1 -0
- package/ui-dist/assets/index-BTDFuKka.js +2 -0
- package/ui-dist/assets/index-CUmk8xFK.css +1 -0
- package/ui-dist/assets/{key-round-BQXmPSxD.js → key-round-CnI1mc9F.js} +1 -1
- package/ui-dist/assets/loader-circle-B5i8oMMY.js +1 -0
- package/ui-dist/assets/{logo-badge-uB4SwANR.js → logo-badge-BQgKnVtz.js} +1 -1
- package/ui-dist/assets/{logos-BcELLmYh.js → logos-CqVm0q0W.js} +1 -1
- package/ui-dist/assets/marketplace-page-DJGDpTAo.js +1 -0
- package/ui-dist/assets/{marketplace-page-DiqqX25V.js → marketplace-page-DxlxHCFm.js} +2 -2
- package/ui-dist/assets/mcp-marketplace-page-5UjYRWOR.js +40 -0
- package/ui-dist/assets/mcp-marketplace-page-C1XaHZZO.js +1 -0
- package/ui-dist/assets/message-square-D6Z4NwpG.js +1 -0
- package/ui-dist/assets/{model-config-B0L43HTL.js → model-config-PccJ9XyH.js} +1 -1
- package/ui-dist/assets/{notice-card-C9PFAR67.js → notice-card-CCgk6FvF.js} +1 -1
- package/ui-dist/assets/play-D8WJLnJe.js +1 -0
- package/ui-dist/assets/plus-Di0KAkiO.js +1 -0
- package/ui-dist/assets/{popover-B8msg2FQ.js → popover-YAsxDBhY.js} +1 -1
- package/ui-dist/assets/{provider-scoped-model-input-DeAo2Y65.js → provider-scoped-model-input-CzpF7cug.js} +1 -1
- package/ui-dist/assets/{providers-list-5_VShcn7.js → providers-list-8qDMER8o.js} +1 -1
- package/ui-dist/assets/{refresh-ccw-CeG203yU.js → refresh-ccw-Bii4w8aB.js} +1 -1
- package/ui-dist/assets/refresh-cw-BxojR62w.js +1 -0
- package/ui-dist/assets/remote-D4TtLPAp.js +1 -0
- package/ui-dist/assets/{rotate-cw-F7aThvYj.js → rotate-cw-1Xqa7LZ8.js} +1 -1
- package/ui-dist/assets/runtime-config-page-D-4c5H5z.js +1 -0
- package/ui-dist/assets/{save-7ztImRj7.js → save--BVI5wZX.js} +1 -1
- package/ui-dist/assets/search-config-D3a65l3r.js +1 -0
- package/ui-dist/assets/{search-DZSNKEGp.js → search-vChioOoe.js} +1 -1
- package/ui-dist/assets/{secrets-config-DKFeFii1.js → secrets-config-CoMlR_7i.js} +2 -2
- package/ui-dist/assets/{select-DRDejPLk.js → select-DIZrwsKU.js} +1 -1
- package/ui-dist/assets/{sessions-config-page-CZGqS32n.js → sessions-config-page-Cc0TJStn.js} +2 -2
- package/ui-dist/assets/{setting-row-BcF6eTW0.js → setting-row-DiQyrE81.js} +1 -1
- package/ui-dist/assets/{settings-DjvNMJde.js → settings-CiRChctQ.js} +1 -1
- package/ui-dist/assets/skeleton-CFQRIUzt.js +1 -0
- package/ui-dist/assets/{sparkles-CyDTgTM4.js → sparkles-D1ZKWdm4.js} +1 -1
- package/ui-dist/assets/{status-dot-aQU9Mia4.js → status-dot-Dv_hiUVa.js} +1 -1
- package/ui-dist/assets/{tabs-custom-C4P7g4vR.js → tabs-custom-CsACkVji.js} +1 -1
- package/ui-dist/assets/{tag-chip-CVIqyMv7.js → tag-chip-C3wDBe_-.js} +1 -1
- package/ui-dist/assets/theme-provider-aOmrJ9J6.js +1 -0
- package/ui-dist/assets/{tooltip-C6VPreZ7.js → tooltip-Dq5Xehpk.js} +1 -1
- package/ui-dist/assets/{trash-2-C1cdqL6V.js → trash-2-rY9ZteZX.js} +1 -1
- package/ui-dist/assets/use-config-BQJjq1mP.js +1 -0
- package/ui-dist/assets/{use-confirm-dialog-DvIbSUX3.js → use-confirm-dialog-DBoV5n5P.js} +1 -1
- package/ui-dist/assets/{use-infinite-scroll-loader-D8h0k-iL.js → use-infinite-scroll-loader-JAicqVC5.js} +1 -1
- package/ui-dist/assets/{use-viewport-layout-D-pjxsyz.js → use-viewport-layout-BX3XqzJ4.js} +1 -1
- package/ui-dist/assets/x-DpTzXQcX.js +1 -0
- package/ui-dist/index.html +40 -39
- package/ui-dist/assets/api-C51456xV.js +0 -15
- package/ui-dist/assets/app-manager-provider-D_cKqqRG.js +0 -1
- package/ui-dist/assets/app-navigation.config-Dve1W20Y.js +0 -1
- package/ui-dist/assets/chat-BxA-mw53.js +0 -58
- package/ui-dist/assets/chat-page-DLFTPfmu.js +0 -1
- package/ui-dist/assets/chunk-JZWAC4HX-ptDyT_1C.js +0 -3
- package/ui-dist/assets/desktop-update-config-CzGi43xw.js +0 -1
- package/ui-dist/assets/doc-browser-CoKIUCJj.js +0 -1
- package/ui-dist/assets/doc-browser-DYKpRqe-.js +0 -1
- package/ui-dist/assets/i18n-BnNAQpVM.js +0 -1
- package/ui-dist/assets/index-CAYF44Dz.js +0 -2
- package/ui-dist/assets/index-mRmSAB-e.css +0 -1
- package/ui-dist/assets/loader-circle-C6gg2m2a.js +0 -1
- package/ui-dist/assets/marketplace-page-0sEdt5sA.js +0 -1
- package/ui-dist/assets/mcp-marketplace-page-B8vmu9xe.js +0 -1
- package/ui-dist/assets/mcp-marketplace-page-C_akqPwv.js +0 -40
- package/ui-dist/assets/message-square-CLVODA23.js +0 -1
- package/ui-dist/assets/play-DeNVUA5C.js +0 -1
- package/ui-dist/assets/plus-BptLViq1.js +0 -1
- package/ui-dist/assets/remote-pzp4oLcL.js +0 -1
- package/ui-dist/assets/runtime-config-page-B-y_0HIS.js +0 -1
- package/ui-dist/assets/search-config-DJTm9Fno.js +0 -1
- package/ui-dist/assets/skeleton-5Mg6vZHN.js +0 -1
- package/ui-dist/assets/theme-provider-dHqcWU-j.js +0 -1
- package/ui-dist/assets/use-config-DFja1sda.js +0 -1
- package/ui-dist/assets/x-BjMO7v8q.js +0 -1
- /package/ui-dist/assets/{config-hints-CPNzbMEp.js → config-hints-MogHYQ8G.js} +0 -0
package/dist/cli/app/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { S as waitForExit, _ as resolvePublicIp, a as compareNpmRuntimeVersions, b as resolveUiConfig, c as NpmRuntimeBundleLayoutStore, d as getPackageVersion$1, f as isLoopbackHost, g as prompt, h as printAgentResponse, i as NpmRuntimeBundleService, l as findExecutableOnPath, m as openBrowser, n as NpmRuntimeUpdateSourceService, o as resolveEffectiveNpmRuntimeVersion, p as isProcessRunning, t as NpmRuntimeUpdateStateStore, u as findListeningProcessByPort, v as resolveServiceLogPath, x as resolveUiStaticDir, y as resolveUiApiBase } from "../../npm-runtime-update-state.store-75vzvn0B.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as NextclawCore from "@nextclaw/core";
|
|
5
5
|
import { APP_NAME, APP_TAGLINE, AgentRouteResolver, BUILTIN_MAIN_AGENT_ID, ChannelManager, CommandRegistry, ConfigSchema, ContextBuilder, CronService, CronTool, DEFAULT_WORKSPACE_DIR, DEFAULT_WORKSPACE_PATH, DisposableStore, EditFileTool, ExecTool, ExtensionToolAdapter, FileLogSink, GatewayTool, InputBudgetPruner, LLMProvider, ListDirTool, MemoryGetTool, MemorySearchTool, MessageBus, MessageTool, ProviderManager, ReadFileTool, RequestedSkillsMetadataReader, SessionManager, SessionsHistoryTool, SessionsListTool, SkillsLoader, Tool, ToolRegistry, WebFetchTool, WebSearchTool, WriteFileTool, buildConfigSchema, buildMinimalSystemExecutionPrompt, buildReloadPlan, buildToolCatalogEntries, createAgentProfile, createAssistantStreamDeltaControlMessage, createAssistantStreamResetControlMessage, createGlobalTypedEventBus, createTypedEventKey, createTypingStopControlMessage, diffConfigPaths, expandHome, findEffectiveAgentProfile, getAppLogger, getConfigPath, getDataDir, getDataPath, getLoggingRuntime, getWorkspacePath, hasSecretRef, loadConfig, normalizeInlineSecretRefs, parseAgentScopedSessionKey, parseThinkingLevel, readSessionProjectRoot, redactConfigObject, removeAgentProfile, resolveAppLogPath, resolveConfigSecrets, resolveDefaultAgentProfileId, resolveEffectiveAgentProfiles, resolveLocalUiBaseUrl, resolveProviderRuntime, resolveSessionWorkspacePath, resolveThinkingLevel, saveConfig, toDisposable, updateAgentProfile } from "@nextclaw/core";
|
|
@@ -168,7 +168,7 @@ function maskToken(value) {
|
|
|
168
168
|
if (value.length <= 12) return "<redacted>";
|
|
169
169
|
return `${value.slice(0, 6)}...${value.slice(-4)}`;
|
|
170
170
|
}
|
|
171
|
-
function normalizeOptionalString$
|
|
171
|
+
function normalizeOptionalString$9(value) {
|
|
172
172
|
if (typeof value !== "string") return;
|
|
173
173
|
const trimmed = value.trim();
|
|
174
174
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
@@ -266,8 +266,8 @@ var RemotePlatformClient = class {
|
|
|
266
266
|
if (tokenState.reason === "missing") throw new Error("NextClaw platform token is missing. Run \"nextclaw login\" first.");
|
|
267
267
|
if (tokenState.reason === "expired") throw new Error("NextClaw platform token expired. Run \"nextclaw login\" or browser sign-in again.");
|
|
268
268
|
if (tokenState.reason === "malformed") throw new Error("NextClaw platform token is invalid. Run \"nextclaw login\" again.");
|
|
269
|
-
const configuredApiBase = normalizeOptionalString$
|
|
270
|
-
const rawApiBase = normalizeOptionalString$
|
|
269
|
+
const configuredApiBase = normalizeOptionalString$9(config.remote.platformApiBase) ?? (typeof nextclawProvider?.apiBase === "string" ? nextclawProvider.apiBase.trim() : "");
|
|
270
|
+
const rawApiBase = normalizeOptionalString$9(opts.apiBase) ?? configuredApiBase;
|
|
271
271
|
if (!rawApiBase) throw new Error("Platform API base is missing. Pass --api-base, run nextclaw login, or set remote.platformApiBase.");
|
|
272
272
|
return {
|
|
273
273
|
platformBase: this.deps.resolvePlatformBase(rawApiBase),
|
|
@@ -276,14 +276,14 @@ var RemotePlatformClient = class {
|
|
|
276
276
|
};
|
|
277
277
|
}
|
|
278
278
|
resolveLocalOrigin(config, opts) {
|
|
279
|
-
const explicitOrigin = normalizeOptionalString$
|
|
279
|
+
const explicitOrigin = normalizeOptionalString$9(opts.localOrigin);
|
|
280
280
|
if (explicitOrigin) return explicitOrigin.replace(/\/$/, "");
|
|
281
281
|
const state = this.deps.readManagedServiceState?.();
|
|
282
282
|
if (state && this.deps.isProcessRunning?.(state.pid) && Number.isFinite(state.uiPort)) return `http://127.0.0.1:${state.uiPort}`;
|
|
283
283
|
return `http://127.0.0.1:${typeof config.ui?.port === "number" && Number.isFinite(config.ui.port) ? config.ui.port : 55667}`;
|
|
284
284
|
}
|
|
285
285
|
resolveDisplayName(config, opts) {
|
|
286
|
-
return normalizeOptionalString$
|
|
286
|
+
return normalizeOptionalString$9(opts.name) ?? normalizeOptionalString$9(config.remote.deviceName) ?? hostname();
|
|
287
287
|
}
|
|
288
288
|
};
|
|
289
289
|
//#endregion
|
|
@@ -4493,7 +4493,7 @@ var RemoteConnector = class {
|
|
|
4493
4493
|
};
|
|
4494
4494
|
//#endregion
|
|
4495
4495
|
//#region ../nextclaw-remote/src/remote-status-store.ts
|
|
4496
|
-
function normalizeOptionalString$
|
|
4496
|
+
function normalizeOptionalString$8(value) {
|
|
4497
4497
|
if (typeof value !== "string") return;
|
|
4498
4498
|
const trimmed = value.trim();
|
|
4499
4499
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
@@ -4504,8 +4504,8 @@ function buildConfiguredRemoteState(config) {
|
|
|
4504
4504
|
enabled: Boolean(remote.enabled),
|
|
4505
4505
|
mode: "service",
|
|
4506
4506
|
state: remote.enabled ? "disconnected" : "disabled",
|
|
4507
|
-
...normalizeOptionalString$
|
|
4508
|
-
...normalizeOptionalString$
|
|
4507
|
+
...normalizeOptionalString$8(remote.deviceName) ? { deviceName: normalizeOptionalString$8(remote.deviceName) } : {},
|
|
4508
|
+
...normalizeOptionalString$8(remote.platformApiBase) ? { platformBase: normalizeOptionalString$8(remote.platformApiBase) } : {},
|
|
4509
4509
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4510
4510
|
};
|
|
4511
4511
|
}
|
|
@@ -4518,7 +4518,7 @@ function resolveRemoteStatusSnapshot(params) {
|
|
|
4518
4518
|
configuredEnabled: true,
|
|
4519
4519
|
runtime: {
|
|
4520
4520
|
...buildConfiguredRemoteState(params.config),
|
|
4521
|
-
deviceName: normalizeOptionalString$
|
|
4521
|
+
deviceName: normalizeOptionalString$8(params.config.remote.deviceName) ?? normalizeOptionalString$8(params.fallbackDeviceName) ?? hostname()
|
|
4522
4522
|
}
|
|
4523
4523
|
};
|
|
4524
4524
|
return {
|
|
@@ -5062,30 +5062,6 @@ function parseSessionKey(sessionKey) {
|
|
|
5062
5062
|
};
|
|
5063
5063
|
}
|
|
5064
5064
|
//#endregion
|
|
5065
|
-
//#region src/cli/shared/utils/runtime-helpers.ts
|
|
5066
|
-
function resolveSkillsInstallWorkdir(params) {
|
|
5067
|
-
if (params.explicitWorkdir) return expandHome(params.explicitWorkdir);
|
|
5068
|
-
return getWorkspacePath(params.configuredWorkspace);
|
|
5069
|
-
}
|
|
5070
|
-
function parseStartTimeoutMs(value) {
|
|
5071
|
-
if (value === void 0) return;
|
|
5072
|
-
const parsed = Number(value);
|
|
5073
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
5074
|
-
console.error("Invalid --start-timeout value. Provide milliseconds (e.g. 45000).");
|
|
5075
|
-
process.exit(1);
|
|
5076
|
-
}
|
|
5077
|
-
return Math.floor(parsed);
|
|
5078
|
-
}
|
|
5079
|
-
function resolveManagedServiceUiOverrides(params) {
|
|
5080
|
-
const uiOverrides = {
|
|
5081
|
-
enabled: true,
|
|
5082
|
-
host: params.forcedPublicHost,
|
|
5083
|
-
open: false
|
|
5084
|
-
};
|
|
5085
|
-
if (params.uiPort) uiOverrides.port = Number(params.uiPort);
|
|
5086
|
-
return uiOverrides;
|
|
5087
|
-
}
|
|
5088
|
-
//#endregion
|
|
5089
5065
|
//#region src/cli/shared/utils/startup-trace.ts
|
|
5090
5066
|
const STARTUP_TRACE_ENABLED = process.env.NEXTCLAW_STARTUP_TRACE === "1";
|
|
5091
5067
|
const STARTUP_TRACE_ORIGIN_MS = Date.now();
|
|
@@ -5260,10 +5236,14 @@ var NpmRuntimeUpdateManager = class {
|
|
|
5260
5236
|
};
|
|
5261
5237
|
syncStateFromCurrentPointer = () => {
|
|
5262
5238
|
const currentPointer = this.options.layout.readCurrentPointer();
|
|
5263
|
-
|
|
5239
|
+
const effectiveCurrentVersion = resolveEffectiveNpmRuntimeVersion({
|
|
5240
|
+
launcherVersion: this.launcherVersion,
|
|
5241
|
+
currentBundleVersion: currentPointer?.version ?? null
|
|
5242
|
+
});
|
|
5243
|
+
if (!effectiveCurrentVersion) return;
|
|
5264
5244
|
this.options.stateStore.update((state) => ({
|
|
5265
5245
|
...state,
|
|
5266
|
-
currentVersion:
|
|
5246
|
+
currentVersion: effectiveCurrentVersion
|
|
5267
5247
|
}));
|
|
5268
5248
|
};
|
|
5269
5249
|
toSnapshotFromState = (state, patch) => {
|
|
@@ -5467,49 +5447,6 @@ function readDirectoryNames(directory) {
|
|
|
5467
5447
|
return readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
5468
5448
|
}
|
|
5469
5449
|
//#endregion
|
|
5470
|
-
//#region src/cli/launcher/npm-runtime-update-source.service.ts
|
|
5471
|
-
const DEFAULT_NPM_RUNTIME_UPDATE_BASE_URL = "https://Peiiii.github.io/nextclaw/npm-runtime-updates";
|
|
5472
|
-
function normalizeOptionalString$8(value) {
|
|
5473
|
-
if (typeof value !== "string") return null;
|
|
5474
|
-
const trimmed = value.trim();
|
|
5475
|
-
return trimmed ? trimmed : null;
|
|
5476
|
-
}
|
|
5477
|
-
function normalizeChannel(value) {
|
|
5478
|
-
return typeof value === "string" && value.trim().toLowerCase() === "beta" ? "beta" : "stable";
|
|
5479
|
-
}
|
|
5480
|
-
function resolvePackagedPublicKeyPath() {
|
|
5481
|
-
return resolve(dirname(fileURLToPath(import.meta.url)), "../../..", "resources", "update-bundle-public.pem");
|
|
5482
|
-
}
|
|
5483
|
-
var NpmRuntimeUpdateSourceService = class {
|
|
5484
|
-
env;
|
|
5485
|
-
platform;
|
|
5486
|
-
arch;
|
|
5487
|
-
constructor(options = {}) {
|
|
5488
|
-
this.env = options.env ?? process.env;
|
|
5489
|
-
this.platform = options.platform ?? process.platform;
|
|
5490
|
-
this.arch = options.arch ?? process.arch;
|
|
5491
|
-
}
|
|
5492
|
-
resolveChannel = (explicitChannel) => {
|
|
5493
|
-
return normalizeChannel(explicitChannel ?? this.env.NEXTCLAW_UPDATE_CHANNEL);
|
|
5494
|
-
};
|
|
5495
|
-
resolveManifestUrl = (channel, explicitManifestUrl) => {
|
|
5496
|
-
const manifestUrl = normalizeOptionalString$8(explicitManifestUrl) ?? normalizeOptionalString$8(this.env.NEXTCLAW_UPDATE_MANIFEST_URL);
|
|
5497
|
-
if (manifestUrl) return manifestUrl;
|
|
5498
|
-
const baseUrl = normalizeOptionalString$8(this.env.NEXTCLAW_UPDATE_MANIFEST_BASE_URL) ?? DEFAULT_NPM_RUNTIME_UPDATE_BASE_URL;
|
|
5499
|
-
return new URL(`${channel}/manifest-${channel}-${this.platform}-${this.arch}.json`, `${baseUrl.replace(/\/+$/, "")}/`).toString();
|
|
5500
|
-
};
|
|
5501
|
-
resolveBundlePublicKey = () => {
|
|
5502
|
-
const explicitPublicKey = normalizeOptionalString$8(this.env.NEXTCLAW_UPDATE_BUNDLE_PUBLIC_KEY);
|
|
5503
|
-
if (explicitPublicKey) return explicitPublicKey;
|
|
5504
|
-
const publicKeyPath = normalizeOptionalString$8(this.env.NEXTCLAW_UPDATE_BUNDLE_PUBLIC_KEY_PATH);
|
|
5505
|
-
if (!publicKeyPath || !existsSync(publicKeyPath)) {
|
|
5506
|
-
const packagedPublicKeyPath = resolvePackagedPublicKeyPath();
|
|
5507
|
-
return existsSync(packagedPublicKeyPath) ? readFileSync(packagedPublicKeyPath, "utf8").trim() : null;
|
|
5508
|
-
}
|
|
5509
|
-
return readFileSync(publicKeyPath, "utf8").trim();
|
|
5510
|
-
};
|
|
5511
|
-
};
|
|
5512
|
-
//#endregion
|
|
5513
5450
|
//#region src/cli/launcher/npm-runtime-update-command.service.ts
|
|
5514
5451
|
var NpmRuntimeUpdateCommandService = class {
|
|
5515
5452
|
run = async (opts) => {
|
|
@@ -5520,11 +5457,11 @@ var NpmRuntimeUpdateCommandService = class {
|
|
|
5520
5457
|
};
|
|
5521
5458
|
runManaged = async (opts) => {
|
|
5522
5459
|
const source = new NpmRuntimeUpdateSourceService();
|
|
5523
|
-
const
|
|
5460
|
+
const launcherVersion = getPackageVersion$1();
|
|
5461
|
+
const channel = source.resolveChannel(opts.channel, launcherVersion);
|
|
5524
5462
|
const manifestUrl = source.resolveManifestUrl(channel, opts.manifestUrl);
|
|
5525
5463
|
const layout = new NpmRuntimeBundleLayoutStore();
|
|
5526
|
-
const stateStore = new NpmRuntimeUpdateStateStore(layout.getStatePath());
|
|
5527
|
-
const launcherVersion = getPackageVersion$1();
|
|
5464
|
+
const stateStore = new NpmRuntimeUpdateStateStore(layout.getStatePath(), { defaultChannel: channel });
|
|
5528
5465
|
const bundleService = new NpmRuntimeBundleService({
|
|
5529
5466
|
layout,
|
|
5530
5467
|
stateStore,
|
|
@@ -5748,11 +5685,9 @@ const readInstalledFirstPartyPluginMatches = (workspaceExtensionsDir) => {
|
|
|
5748
5685
|
const workspacePackage = workspacePackageByName.get(packageName);
|
|
5749
5686
|
if (!workspacePackage) continue;
|
|
5750
5687
|
matches.push({
|
|
5751
|
-
pluginId: workspacePackage.pluginId,
|
|
5752
5688
|
packageName,
|
|
5753
5689
|
workspaceDir: workspacePackage.dir,
|
|
5754
|
-
installPath: packageDir
|
|
5755
|
-
supportsDevelopmentSource: workspacePackage.supportsDevelopmentSource
|
|
5690
|
+
installPath: packageDir
|
|
5756
5691
|
});
|
|
5757
5692
|
}
|
|
5758
5693
|
return matches;
|
|
@@ -5772,35 +5707,6 @@ const findWorkspacePackageForInstallRecord = (installRecord, workspacePackages,
|
|
|
5772
5707
|
if (installPathCandidates.size === 0) return;
|
|
5773
5708
|
return workspacePackages.find((workspacePackage) => installPathCandidates.has(path.resolve(workspacePackage.dir)));
|
|
5774
5709
|
};
|
|
5775
|
-
const buildDevelopmentSourceEntryDefaults = (config, workspacePackages, installedPluginMatches) => {
|
|
5776
|
-
const packageByName = new Map(workspacePackages.map((entry) => [entry.packageName, entry]));
|
|
5777
|
-
const nextEntries = { ...config.plugins.entries ?? {} };
|
|
5778
|
-
let didDefaultDevelopmentSource = false;
|
|
5779
|
-
for (const installedPlugin of installedPluginMatches) {
|
|
5780
|
-
if (!installedPlugin.supportsDevelopmentSource) continue;
|
|
5781
|
-
const existingEntry = nextEntries[installedPlugin.pluginId];
|
|
5782
|
-
if (existingEntry?.source) continue;
|
|
5783
|
-
nextEntries[installedPlugin.pluginId] = {
|
|
5784
|
-
...existingEntry,
|
|
5785
|
-
source: "development"
|
|
5786
|
-
};
|
|
5787
|
-
didDefaultDevelopmentSource = true;
|
|
5788
|
-
}
|
|
5789
|
-
for (const [pluginId, installRecord] of Object.entries(config.plugins.installs ?? {})) {
|
|
5790
|
-
if (!findWorkspacePackageForInstallRecord(installRecord, workspacePackages, packageByName)?.supportsDevelopmentSource) continue;
|
|
5791
|
-
const existingEntry = nextEntries[pluginId];
|
|
5792
|
-
if (existingEntry?.source) continue;
|
|
5793
|
-
nextEntries[pluginId] = {
|
|
5794
|
-
...existingEntry,
|
|
5795
|
-
source: "development"
|
|
5796
|
-
};
|
|
5797
|
-
didDefaultDevelopmentSource = true;
|
|
5798
|
-
}
|
|
5799
|
-
return {
|
|
5800
|
-
didDefaultDevelopmentSource,
|
|
5801
|
-
nextEntries
|
|
5802
|
-
};
|
|
5803
|
-
};
|
|
5804
5710
|
const resolveDevFirstPartyPluginLoadPaths = (config, workspaceExtensionsDir) => {
|
|
5805
5711
|
const rootDir = resolveDevFirstPartyPluginDir(workspaceExtensionsDir);
|
|
5806
5712
|
if (!rootDir) return [];
|
|
@@ -5850,18 +5756,15 @@ const resolveDevFirstPartyPluginInstallRoots = (config, workspaceExtensionsDir)
|
|
|
5850
5756
|
const applyDevFirstPartyPluginLoadPaths = (config, workspaceExtensionsDir) => {
|
|
5851
5757
|
const rootDir = resolveDevFirstPartyPluginDir(workspaceExtensionsDir);
|
|
5852
5758
|
if (!rootDir) return config;
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
const installedPluginMatches = readInstalledFirstPartyPluginMatches(rootDir);
|
|
5759
|
+
if (readWorkspacePluginPackages(rootDir).length === 0) return config;
|
|
5760
|
+
readInstalledFirstPartyPluginMatches(rootDir);
|
|
5856
5761
|
const devLoadPaths = resolveDevFirstPartyPluginLoadPaths(config, rootDir);
|
|
5857
5762
|
if (devLoadPaths.length === 0) return config;
|
|
5858
5763
|
const mergedLoadPaths = mergeLoadPaths$1(Array.isArray(config.plugins.load?.paths) ? config.plugins.load.paths.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [], devLoadPaths);
|
|
5859
|
-
const { didDefaultDevelopmentSource, nextEntries } = buildDevelopmentSourceEntryDefaults(config, workspacePackages, installedPluginMatches);
|
|
5860
5764
|
return {
|
|
5861
5765
|
...config,
|
|
5862
5766
|
plugins: {
|
|
5863
5767
|
...config.plugins,
|
|
5864
|
-
entries: didDefaultDevelopmentSource ? nextEntries : config.plugins.entries,
|
|
5865
5768
|
load: {
|
|
5866
5769
|
...config.plugins.load,
|
|
5867
5770
|
paths: mergedLoadPaths
|
|
@@ -5872,10 +5775,10 @@ const applyDevFirstPartyPluginLoadPaths = (config, workspaceExtensionsDir) => {
|
|
|
5872
5775
|
//#endregion
|
|
5873
5776
|
//#region src/cli/commands/plugin/development-source/dev-plugin-overrides.utils.ts
|
|
5874
5777
|
const DEV_PLUGIN_OVERRIDES_ENV = "NEXTCLAW_DEV_PLUGIN_OVERRIDES";
|
|
5875
|
-
function isRecord$
|
|
5778
|
+
function isRecord$7(value) {
|
|
5876
5779
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5877
5780
|
}
|
|
5878
|
-
function readOptionalString$
|
|
5781
|
+
function readOptionalString$7(value) {
|
|
5879
5782
|
if (typeof value !== "string") return;
|
|
5880
5783
|
return value.trim() || void 0;
|
|
5881
5784
|
}
|
|
@@ -5901,9 +5804,9 @@ function assertOverridePluginReadable(override) {
|
|
|
5901
5804
|
}
|
|
5902
5805
|
}
|
|
5903
5806
|
function readOverrideRecord(value, index) {
|
|
5904
|
-
if (!isRecord$
|
|
5905
|
-
const pluginId = readOptionalString$
|
|
5906
|
-
const pluginPath = readOptionalString$
|
|
5807
|
+
if (!isRecord$7(value)) throw new Error(`[dev-plugin-override] override[${index}] must be an object`);
|
|
5808
|
+
const pluginId = readOptionalString$7(value.pluginId);
|
|
5809
|
+
const pluginPath = readOptionalString$7(value.pluginPath);
|
|
5907
5810
|
const source = value.source === "development" ? "development" : "production";
|
|
5908
5811
|
if (!pluginId || !pluginPath) throw new Error(`[dev-plugin-override] override[${index}] requires pluginId and pluginPath`);
|
|
5909
5812
|
const normalized = {
|
|
@@ -5960,7 +5863,7 @@ function resolveDevPluginOverrideInstallRoots(config, overrides) {
|
|
|
5960
5863
|
const installRoots = [];
|
|
5961
5864
|
for (const override of overrides) {
|
|
5962
5865
|
const installRecord = config.plugins.installs?.[override.pluginId];
|
|
5963
|
-
const installPath = readOptionalString$
|
|
5866
|
+
const installPath = readOptionalString$7(installRecord?.installPath);
|
|
5964
5867
|
if (!installPath || installRoots.includes(installPath)) continue;
|
|
5965
5868
|
installRoots.push(installPath);
|
|
5966
5869
|
}
|
|
@@ -8423,13 +8326,13 @@ var AgentCommands = class {
|
|
|
8423
8326
|
};
|
|
8424
8327
|
//#endregion
|
|
8425
8328
|
//#region src/cli/commands/ncp/features/runtime/ncp-asset-tools.ts
|
|
8426
|
-
function readOptionalString$
|
|
8329
|
+
function readOptionalString$6(value) {
|
|
8427
8330
|
if (typeof value !== "string") return null;
|
|
8428
8331
|
const trimmed = value.trim();
|
|
8429
8332
|
return trimmed.length > 0 ? trimmed : null;
|
|
8430
8333
|
}
|
|
8431
8334
|
function readOptionalBase64Bytes(value) {
|
|
8432
|
-
const base64 = readOptionalString$
|
|
8335
|
+
const base64 = readOptionalString$6(value);
|
|
8433
8336
|
if (!base64) return null;
|
|
8434
8337
|
try {
|
|
8435
8338
|
return Buffer.from(base64, "base64");
|
|
@@ -8480,18 +8383,18 @@ var AssetPutTool = class {
|
|
|
8480
8383
|
this.contentBasePath = contentBasePath;
|
|
8481
8384
|
}
|
|
8482
8385
|
validateArgs = (args) => {
|
|
8483
|
-
const path = readOptionalString$
|
|
8484
|
-
const bytesBase64 = readOptionalString$
|
|
8485
|
-
const fileName = readOptionalString$
|
|
8386
|
+
const path = readOptionalString$6(args.path);
|
|
8387
|
+
const bytesBase64 = readOptionalString$6(args.bytesBase64);
|
|
8388
|
+
const fileName = readOptionalString$6(args.fileName);
|
|
8486
8389
|
if (path && bytesBase64) return ["Provide either path, or bytesBase64 + fileName, not both."];
|
|
8487
8390
|
if (path) return [];
|
|
8488
8391
|
if (bytesBase64) return fileName ? [] : ["fileName is required when using bytesBase64."];
|
|
8489
8392
|
return ["Provide either path, or bytesBase64 + fileName."];
|
|
8490
8393
|
};
|
|
8491
8394
|
execute = async (args) => {
|
|
8492
|
-
const path = readOptionalString$
|
|
8493
|
-
const fileName = readOptionalString$
|
|
8494
|
-
const mimeType = readOptionalString$
|
|
8395
|
+
const path = readOptionalString$6(args?.path);
|
|
8396
|
+
const fileName = readOptionalString$6(args?.fileName);
|
|
8397
|
+
const mimeType = readOptionalString$6(args?.mimeType);
|
|
8495
8398
|
const bytes = readOptionalBase64Bytes(args?.bytesBase64);
|
|
8496
8399
|
if (path) return {
|
|
8497
8400
|
ok: true,
|
|
@@ -8534,8 +8437,8 @@ var AssetExportTool = class {
|
|
|
8534
8437
|
this.assetStore = assetStore;
|
|
8535
8438
|
}
|
|
8536
8439
|
execute = async (args) => {
|
|
8537
|
-
const assetUri = readOptionalString$
|
|
8538
|
-
const targetPath = readOptionalString$
|
|
8440
|
+
const assetUri = readOptionalString$6(args?.assetUri);
|
|
8441
|
+
const targetPath = readOptionalString$6(args?.targetPath);
|
|
8539
8442
|
if (!assetUri || !targetPath) throw new Error("asset_export requires assetUri and targetPath.");
|
|
8540
8443
|
return {
|
|
8541
8444
|
ok: true,
|
|
@@ -8561,7 +8464,7 @@ var AssetStatTool = class {
|
|
|
8561
8464
|
this.contentBasePath = contentBasePath;
|
|
8562
8465
|
}
|
|
8563
8466
|
execute = async (args) => {
|
|
8564
|
-
const assetUri = readOptionalString$
|
|
8467
|
+
const assetUri = readOptionalString$6(args?.assetUri);
|
|
8565
8468
|
if (!assetUri) throw new Error("asset_stat requires assetUri.");
|
|
8566
8469
|
const record = await this.assetStore.statRecord(assetUri);
|
|
8567
8470
|
if (!record) return {
|
|
@@ -8593,11 +8496,11 @@ function normalizeString(value) {
|
|
|
8593
8496
|
const trimmed = value.trim();
|
|
8594
8497
|
return trimmed.length > 0 ? trimmed : null;
|
|
8595
8498
|
}
|
|
8596
|
-
function isRecord$
|
|
8499
|
+
function isRecord$6(value) {
|
|
8597
8500
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8598
8501
|
}
|
|
8599
8502
|
function cloneMetadata(value) {
|
|
8600
|
-
return isRecord$
|
|
8503
|
+
return isRecord$6(value) ? structuredClone(value) : void 0;
|
|
8601
8504
|
}
|
|
8602
8505
|
function readStringArray(value) {
|
|
8603
8506
|
if (!Array.isArray(value)) return null;
|
|
@@ -9088,7 +8991,7 @@ function readRequiredString$1(params, key) {
|
|
|
9088
8991
|
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string.`);
|
|
9089
8992
|
return value.trim();
|
|
9090
8993
|
}
|
|
9091
|
-
function readOptionalString$
|
|
8994
|
+
function readOptionalString$5(params, key) {
|
|
9092
8995
|
const value = params[key];
|
|
9093
8996
|
if (typeof value !== "string") return;
|
|
9094
8997
|
const trimmed = value.trim();
|
|
@@ -9149,14 +9052,14 @@ var SessionRequestTool = class extends Tool {
|
|
|
9149
9052
|
const target = params.target;
|
|
9150
9053
|
if (!target || typeof target !== "object" || Array.isArray(target)) throw new Error("target must be an object.");
|
|
9151
9054
|
const task = readRequiredString$1(params, "task");
|
|
9152
|
-
const notifyMode = readOptionalString$
|
|
9055
|
+
const notifyMode = readOptionalString$5(params, "notify")?.toLowerCase();
|
|
9153
9056
|
if (notifyMode !== "none" && notifyMode !== "final_reply") throw new Error("notify must be \"none\" or \"final_reply\".");
|
|
9154
9057
|
return this.broker.requestSession({
|
|
9155
9058
|
sourceSessionId: this.sourceSessionId,
|
|
9156
9059
|
sourceToolCallId: toolCallId,
|
|
9157
9060
|
targetSessionId: readRequiredString$1(target, "session_id"),
|
|
9158
9061
|
task,
|
|
9159
|
-
title: readOptionalString$
|
|
9062
|
+
title: readOptionalString$5(params, "title"),
|
|
9160
9063
|
notify: notifyMode,
|
|
9161
9064
|
handoffDepth: this.handoffDepth
|
|
9162
9065
|
});
|
|
@@ -9168,13 +9071,13 @@ function readRequiredString(value, key) {
|
|
|
9168
9071
|
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string.`);
|
|
9169
9072
|
return value.trim();
|
|
9170
9073
|
}
|
|
9171
|
-
function readOptionalString$
|
|
9074
|
+
function readOptionalString$4(value) {
|
|
9172
9075
|
if (typeof value !== "string") return;
|
|
9173
9076
|
const trimmed = value.trim();
|
|
9174
9077
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
9175
9078
|
}
|
|
9176
9079
|
function readSpawnScope(value) {
|
|
9177
|
-
const normalized = readOptionalString$
|
|
9080
|
+
const normalized = readOptionalString$4(value)?.toLowerCase();
|
|
9178
9081
|
if (!normalized || normalized === "standalone") return "standalone";
|
|
9179
9082
|
if (normalized === "child") return "child";
|
|
9180
9083
|
throw new Error("scope must be \"standalone\" or \"child\".");
|
|
@@ -9182,7 +9085,7 @@ function readSpawnScope(value) {
|
|
|
9182
9085
|
function readSpawnRequestOptions(value) {
|
|
9183
9086
|
if (typeof value === "undefined") return;
|
|
9184
9087
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("request must be an object.");
|
|
9185
|
-
const notifyMode = readOptionalString$
|
|
9088
|
+
const notifyMode = readOptionalString$4(value.notify)?.toLowerCase();
|
|
9186
9089
|
if (notifyMode === "none" || notifyMode === "final_reply") return { notify: notifyMode };
|
|
9187
9090
|
throw new Error("request.notify must be \"none\" or \"final_reply\".");
|
|
9188
9091
|
}
|
|
@@ -9260,21 +9163,21 @@ var SessionSpawnTool = class extends Tool {
|
|
|
9260
9163
|
sourceToolCallId: toolCallId,
|
|
9261
9164
|
sourceSessionMetadata: this.sourceSessionMetadata,
|
|
9262
9165
|
task,
|
|
9263
|
-
title: readOptionalString$
|
|
9264
|
-
agentId: readOptionalString$
|
|
9265
|
-
model: readOptionalString$
|
|
9266
|
-
runtime: readOptionalString$
|
|
9166
|
+
title: readOptionalString$4(rawTitle),
|
|
9167
|
+
agentId: readOptionalString$4(rawAgentId),
|
|
9168
|
+
model: readOptionalString$4(rawModel),
|
|
9169
|
+
runtime: readOptionalString$4(rawRuntime),
|
|
9267
9170
|
handoffDepth: this.handoffDepth,
|
|
9268
9171
|
...parentSessionId ? { parentSessionId } : {},
|
|
9269
9172
|
notify: request.notify
|
|
9270
9173
|
});
|
|
9271
9174
|
const session = this.sessionCreationService.createSession({
|
|
9272
9175
|
task,
|
|
9273
|
-
title: readOptionalString$
|
|
9176
|
+
title: readOptionalString$4(rawTitle),
|
|
9274
9177
|
sourceSessionMetadata: this.sourceSessionMetadata,
|
|
9275
|
-
agentId: readOptionalString$
|
|
9276
|
-
model: readOptionalString$
|
|
9277
|
-
runtime: readOptionalString$
|
|
9178
|
+
agentId: readOptionalString$4(rawAgentId),
|
|
9179
|
+
model: readOptionalString$4(rawModel),
|
|
9180
|
+
runtime: readOptionalString$4(rawRuntime),
|
|
9278
9181
|
...parentSessionId ? { parentSessionId } : {}
|
|
9279
9182
|
});
|
|
9280
9183
|
return {
|
|
@@ -9298,10 +9201,10 @@ var SessionSpawnTool = class extends Tool {
|
|
|
9298
9201
|
//#endregion
|
|
9299
9202
|
//#region src/cli/commands/ncp/nextclaw-ncp-tool-registry.ts
|
|
9300
9203
|
function toToolParams(args) {
|
|
9301
|
-
if (isRecord$
|
|
9204
|
+
if (isRecord$6(args)) return args;
|
|
9302
9205
|
if (typeof args === "string") try {
|
|
9303
9206
|
const parsed = JSON.parse(args);
|
|
9304
|
-
return isRecord$
|
|
9207
|
+
return isRecord$6(parsed) ? parsed : {};
|
|
9305
9208
|
} catch {
|
|
9306
9209
|
return {};
|
|
9307
9210
|
}
|
|
@@ -9479,14 +9382,14 @@ function readAccountIdForHints(metadata, sessionMetadata) {
|
|
|
9479
9382
|
//#endregion
|
|
9480
9383
|
//#region src/cli/commands/ncp/nextclaw-ncp-context-builder.ts
|
|
9481
9384
|
const TIME_HINT_TRIGGER_PATTERNS = [/\b(now|right now|current time|what time|today|tonight|tomorrow|yesterday|this morning|this afternoon|this evening|date)\b/i, /(现在|此刻|当前时间|现在几点|几点了|今天|今晚|今早|今晨|明天|昨天|日期)/];
|
|
9482
|
-
function isRecord$
|
|
9385
|
+
function isRecord$5(value) {
|
|
9483
9386
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9484
9387
|
}
|
|
9485
9388
|
function mergeInputMetadata(input) {
|
|
9486
|
-
const messageMetadata = input.messages.slice().reverse().find((message) => isRecord$
|
|
9389
|
+
const messageMetadata = input.messages.slice().reverse().find((message) => isRecord$5(message.metadata))?.metadata;
|
|
9487
9390
|
return {
|
|
9488
|
-
...isRecord$
|
|
9489
|
-
...isRecord$
|
|
9391
|
+
...isRecord$5(messageMetadata) ? structuredClone(messageMetadata) : {},
|
|
9392
|
+
...isRecord$5(input.metadata) ? structuredClone(input.metadata) : {}
|
|
9490
9393
|
};
|
|
9491
9394
|
}
|
|
9492
9395
|
const REQUESTED_SKILLS_METADATA_READER = new RequestedSkillsMetadataReader();
|
|
@@ -10110,7 +10013,7 @@ const CHILD_SESSION_PARENT_METADATA_KEY = "parent_session_id";
|
|
|
10110
10013
|
const CHILD_SESSION_REQUEST_METADATA_KEY = "spawned_by_request_id";
|
|
10111
10014
|
const CHILD_SESSION_LIFECYCLE_METADATA_KEY = "session_lifecycle";
|
|
10112
10015
|
const CHILD_SESSION_PROMOTED_METADATA_KEY = "child_session_promoted";
|
|
10113
|
-
function readOptionalString$
|
|
10016
|
+
function readOptionalString$3(value) {
|
|
10114
10017
|
if (typeof value !== "string") return null;
|
|
10115
10018
|
const trimmed = value.trim();
|
|
10116
10019
|
return trimmed.length > 0 ? trimmed : null;
|
|
@@ -10150,14 +10053,14 @@ function buildSessionId() {
|
|
|
10150
10053
|
return `ncp-${Date.now().toString(36)}-${randomUUID().replace(/-/g, "").slice(0, 8)}`;
|
|
10151
10054
|
}
|
|
10152
10055
|
function resolveSessionAgentId(params) {
|
|
10153
|
-
return readOptionalString$
|
|
10056
|
+
return readOptionalString$3(params.agentId) ?? resolveDefaultAgentProfileId(params.getConfig());
|
|
10154
10057
|
}
|
|
10155
10058
|
function resolveSessionTitle(params) {
|
|
10156
|
-
return readOptionalString$
|
|
10059
|
+
return readOptionalString$3(params.title) ?? summarizeTask(params.task);
|
|
10157
10060
|
}
|
|
10158
10061
|
function resolveSessionType(params) {
|
|
10159
10062
|
const { metadata, runtime, sessionType } = params;
|
|
10160
|
-
return readOptionalString$
|
|
10063
|
+
return readOptionalString$3(runtime) ?? readOptionalString$3(metadata.runtime) ?? readOptionalString$3(sessionType) ?? readOptionalString$3(metadata.session_type) ?? DEFAULT_SESSION_TYPE;
|
|
10161
10064
|
}
|
|
10162
10065
|
function applySessionOverrides(params) {
|
|
10163
10066
|
const { lifecycle, metadata, model, parentSessionId, projectRoot, requestId, sessionType, thinkingLevel, title } = params;
|
|
@@ -10170,15 +10073,15 @@ function applySessionOverrides(params) {
|
|
|
10170
10073
|
metadata[CHILD_SESSION_PROMOTED_METADATA_KEY] = false;
|
|
10171
10074
|
}
|
|
10172
10075
|
if (requestId) metadata[CHILD_SESSION_REQUEST_METADATA_KEY] = requestId;
|
|
10173
|
-
if (readOptionalString$
|
|
10076
|
+
if (readOptionalString$3(model)) {
|
|
10174
10077
|
metadata.model = model?.trim();
|
|
10175
10078
|
metadata.preferred_model = model?.trim();
|
|
10176
10079
|
}
|
|
10177
|
-
if (readOptionalString$
|
|
10080
|
+
if (readOptionalString$3(thinkingLevel)) {
|
|
10178
10081
|
metadata.thinking = thinkingLevel?.trim();
|
|
10179
10082
|
metadata.preferred_thinking = thinkingLevel?.trim();
|
|
10180
10083
|
}
|
|
10181
|
-
if (readOptionalString$
|
|
10084
|
+
if (readOptionalString$3(projectRoot)) metadata.project_root = projectRoot?.trim();
|
|
10182
10085
|
}
|
|
10183
10086
|
var SessionCreationService = class {
|
|
10184
10087
|
constructor(sessionManager, getConfig, onSessionUpdated) {
|
|
@@ -10200,8 +10103,8 @@ var SessionCreationService = class {
|
|
|
10200
10103
|
task
|
|
10201
10104
|
});
|
|
10202
10105
|
const metadata = cloneInheritedMetadata(sourceSessionMetadata);
|
|
10203
|
-
const parentSessionId = readOptionalString$
|
|
10204
|
-
const requestId = readOptionalString$
|
|
10106
|
+
const parentSessionId = readOptionalString$3(rawParentSessionId);
|
|
10107
|
+
const requestId = readOptionalString$3(rawRequestId);
|
|
10205
10108
|
const sessionType = resolveSessionType({
|
|
10206
10109
|
runtime,
|
|
10207
10110
|
sessionType: requestedSessionType,
|
|
@@ -10254,12 +10157,12 @@ var SessionCreationService = class {
|
|
|
10254
10157
|
return true;
|
|
10255
10158
|
};
|
|
10256
10159
|
isChildSessionRecord = (metadata) => {
|
|
10257
|
-
return Boolean(readOptionalString$
|
|
10160
|
+
return Boolean(readOptionalString$3(metadata?.[CHILD_SESSION_PARENT_METADATA_KEY]));
|
|
10258
10161
|
};
|
|
10259
10162
|
};
|
|
10260
10163
|
//#endregion
|
|
10261
10164
|
//#region src/cli/commands/ncp/session-request/session-request-result.ts
|
|
10262
|
-
function readOptionalString$
|
|
10165
|
+
function readOptionalString$2(value) {
|
|
10263
10166
|
if (typeof value !== "string") return null;
|
|
10264
10167
|
const trimmed = value.trim();
|
|
10265
10168
|
return trimmed.length > 0 ? trimmed : null;
|
|
@@ -10280,7 +10183,7 @@ function extractSessionMessageText(message) {
|
|
|
10280
10183
|
return parts.join("\n\n");
|
|
10281
10184
|
}
|
|
10282
10185
|
function readParentSessionId(metadata) {
|
|
10283
|
-
return readOptionalString$
|
|
10186
|
+
return readOptionalString$2(metadata?.["parent_session_id"]) ?? void 0;
|
|
10284
10187
|
}
|
|
10285
10188
|
function buildSessionRequestToolResult(params) {
|
|
10286
10189
|
const { request, task, title, agentId, isChildSession, parentSessionId, spawnedByRequestId, message } = params;
|
|
@@ -10419,7 +10322,7 @@ var SessionRequestBroker = class {
|
|
|
10419
10322
|
sourceToolCallId,
|
|
10420
10323
|
targetSessionId: normalizedTargetSessionId,
|
|
10421
10324
|
task,
|
|
10422
|
-
title: readOptionalString$
|
|
10325
|
+
title: readOptionalString$2(title) ?? readOptionalString$2(targetSummary.metadata?.label) ?? summarizeSessionRequestTask(task),
|
|
10423
10326
|
handoffDepth: handoffDepth ?? 0,
|
|
10424
10327
|
notify,
|
|
10425
10328
|
agentId: targetSummary.agentId,
|
|
@@ -10955,7 +10858,7 @@ var SessionSearchStoreService = class {
|
|
|
10955
10858
|
};
|
|
10956
10859
|
//#endregion
|
|
10957
10860
|
//#region src/cli/commands/ncp/session-search/session-search-tool.service.ts
|
|
10958
|
-
function isRecord$
|
|
10861
|
+
function isRecord$4(value) {
|
|
10959
10862
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
10960
10863
|
}
|
|
10961
10864
|
function readOptionalInteger(value) {
|
|
@@ -11005,7 +10908,7 @@ var SessionSearchTool = class {
|
|
|
11005
10908
|
return issues;
|
|
11006
10909
|
};
|
|
11007
10910
|
execute = async (args) => {
|
|
11008
|
-
if (!isRecord$
|
|
10911
|
+
if (!isRecord$4(args)) throw new Error("session_search requires an object argument.");
|
|
11009
10912
|
const issues = this.validateArgs(args);
|
|
11010
10913
|
if (issues.length > 0) throw new Error(issues.join(" "));
|
|
11011
10914
|
return this.queryService.search({
|
|
@@ -11937,12 +11840,12 @@ function createContextWindowUpdatedEvent(params) {
|
|
|
11937
11840
|
}
|
|
11938
11841
|
};
|
|
11939
11842
|
}
|
|
11940
|
-
function isRecord$
|
|
11843
|
+
function isRecord$3(value) {
|
|
11941
11844
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
11942
11845
|
}
|
|
11943
11846
|
function resolveNativeReasoningNormalizationMode(params) {
|
|
11944
11847
|
const runtimeEntry = params.config.agents.runtimes.entries.native?.config ?? params.config.ui.ncp.runtimes.native;
|
|
11945
|
-
const runtimeMetadata = isRecord$
|
|
11848
|
+
const runtimeMetadata = isRecord$3(runtimeEntry) ? runtimeEntry : {};
|
|
11946
11849
|
return readAssistantReasoningNormalizationModeFromMetadata(params.sessionMetadata) ?? readAssistantReasoningNormalizationMode(runtimeMetadata.reasoningNormalization) ?? readAssistantReasoningNormalizationMode(runtimeMetadata.reasoning_normalization) ?? readAssistantReasoningNormalizationMode(runtimeMetadata.reasoningNormalizationMode) ?? readAssistantReasoningNormalizationMode(runtimeMetadata.reasoning_normalization_mode) ?? "think-tags";
|
|
11947
11850
|
}
|
|
11948
11851
|
function createMcpRuntimeSupport(getConfig) {
|
|
@@ -14004,7 +13907,7 @@ var ServiceMarketplaceInstaller = class {
|
|
|
14004
13907
|
};
|
|
14005
13908
|
//#endregion
|
|
14006
13909
|
//#region src/cli/shared/utils/marketplace/cli-subcommand-launch.utils.ts
|
|
14007
|
-
const require$
|
|
13910
|
+
const require$3 = createRequire(import.meta.url);
|
|
14008
13911
|
const TYPESCRIPT_EXTENSIONS$1 = new Set([
|
|
14009
13912
|
".ts",
|
|
14010
13913
|
".tsx",
|
|
@@ -14012,7 +13915,7 @@ const TYPESCRIPT_EXTENSIONS$1 = new Set([
|
|
|
14012
13915
|
".cts"
|
|
14013
13916
|
]);
|
|
14014
13917
|
const isTypeScriptEntry = (entry) => TYPESCRIPT_EXTENSIONS$1.has(extname(entry).toLowerCase());
|
|
14015
|
-
const resolveTsxCliEntry = () => require$
|
|
13918
|
+
const resolveTsxCliEntry = () => require$3.resolve("tsx/cli");
|
|
14016
13919
|
const resolveCliAppEntryFromImportMeta$1 = (importMetaUrl) => {
|
|
14017
13920
|
const modulePath = fileURLToPath(importMetaUrl);
|
|
14018
13921
|
const cliRootIndex = modulePath.replace(/\\/g, "/").lastIndexOf("/cli/");
|
|
@@ -14369,6 +14272,13 @@ async function describeUnmanagedHealthyTargetMessage(params) {
|
|
|
14369
14272
|
//#endregion
|
|
14370
14273
|
//#region src/cli/shared/services/runtime/service-managed-startup.service.ts
|
|
14371
14274
|
const { APP_NAME: APP_NAME$1, loadConfig: loadConfig$4 } = NextclawCore;
|
|
14275
|
+
function resolveLauncherCliEntry(importMetaUrl) {
|
|
14276
|
+
const modulePath = fileURLToPath(importMetaUrl);
|
|
14277
|
+
const cliRootIndex = modulePath.replace(/\\/g, "/").lastIndexOf("/cli/");
|
|
14278
|
+
if (cliRootIndex === -1) return fileURLToPath(new URL("../../../launcher/index.js", importMetaUrl));
|
|
14279
|
+
const extension = extname(modulePath) || ".js";
|
|
14280
|
+
return resolve(modulePath.slice(0, cliRootIndex + 5), "launcher", `index${extension}`);
|
|
14281
|
+
}
|
|
14372
14282
|
function toObjectRecord(value) {
|
|
14373
14283
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
14374
14284
|
return value;
|
|
@@ -14420,7 +14330,7 @@ function spawnManagedService(params) {
|
|
|
14420
14330
|
appendStartupStage(logPath, `start requested: ui=${uiConfig.host}:${uiConfig.port}, readinessTimeoutMs=${readinessTimeoutMs}`);
|
|
14421
14331
|
console.log(`Starting ${appName} background service (readiness timeout ${Math.ceil(readinessTimeoutMs / 1e3)}s)...`);
|
|
14422
14332
|
const cliLaunch = resolveCliSubcommandLaunch({
|
|
14423
|
-
argvEntry:
|
|
14333
|
+
argvEntry: resolveLauncherCliEntry(import.meta.url),
|
|
14424
14334
|
importMetaUrl: import.meta.url,
|
|
14425
14335
|
cliArgs: [
|
|
14426
14336
|
"serve",
|
|
@@ -15199,6 +15109,173 @@ function createRemoteAccessHost(params) {
|
|
|
15199
15109
|
});
|
|
15200
15110
|
}
|
|
15201
15111
|
//#endregion
|
|
15112
|
+
//#region src/cli/shared/services/ui/npm-runtime-update-host.service.ts
|
|
15113
|
+
const INITIAL_DOWNLOAD_PROGRESS = {
|
|
15114
|
+
downloadedBytes: 0,
|
|
15115
|
+
totalBytes: null,
|
|
15116
|
+
percent: null
|
|
15117
|
+
};
|
|
15118
|
+
var NpmRuntimeUpdateHost = class {
|
|
15119
|
+
source = new NpmRuntimeUpdateSourceService();
|
|
15120
|
+
layout = new NpmRuntimeBundleLayoutStore();
|
|
15121
|
+
launcherVersion = getPackageVersion$1();
|
|
15122
|
+
stateStore = new NpmRuntimeUpdateStateStore(this.layout.getStatePath(), { defaultChannel: this.source.resolveChannel(void 0, this.launcherVersion) });
|
|
15123
|
+
bundleService = new NpmRuntimeBundleService({
|
|
15124
|
+
layout: this.layout,
|
|
15125
|
+
stateStore: this.stateStore,
|
|
15126
|
+
launcherVersion: this.launcherVersion
|
|
15127
|
+
});
|
|
15128
|
+
updateService = new NpmRuntimeUpdateService({
|
|
15129
|
+
layout: this.layout,
|
|
15130
|
+
bundleService: this.bundleService,
|
|
15131
|
+
launcherVersion: this.launcherVersion,
|
|
15132
|
+
bundlePublicKey: this.source.resolveBundlePublicKey() ?? void 0
|
|
15133
|
+
});
|
|
15134
|
+
snapshot;
|
|
15135
|
+
activeTask = null;
|
|
15136
|
+
automaticSyncStarted = false;
|
|
15137
|
+
constructor(deps) {
|
|
15138
|
+
this.deps = deps;
|
|
15139
|
+
this.snapshot = this.createManager().getSnapshot();
|
|
15140
|
+
this.startAutomaticSync();
|
|
15141
|
+
}
|
|
15142
|
+
getState = async () => {
|
|
15143
|
+
this.startAutomaticSync();
|
|
15144
|
+
return this.snapshot;
|
|
15145
|
+
};
|
|
15146
|
+
checkForUpdates = async () => {
|
|
15147
|
+
return this.startCheck({ autoDownload: false });
|
|
15148
|
+
};
|
|
15149
|
+
downloadUpdate = async () => {
|
|
15150
|
+
return this.startDownload();
|
|
15151
|
+
};
|
|
15152
|
+
applyDownloadedUpdate = async () => {
|
|
15153
|
+
if (this.activeTask) return this.snapshot;
|
|
15154
|
+
this.snapshot = {
|
|
15155
|
+
...this.snapshot,
|
|
15156
|
+
status: "applying",
|
|
15157
|
+
progress: null,
|
|
15158
|
+
errorMessage: null
|
|
15159
|
+
};
|
|
15160
|
+
try {
|
|
15161
|
+
const snapshot = this.createManager().applyDownloadedUpdate();
|
|
15162
|
+
this.snapshot = this.deps.applyRestartMode === "managed-service-restart" ? snapshot : {
|
|
15163
|
+
...snapshot,
|
|
15164
|
+
recoveryCommand: "Restart this NextClaw process to launch the downloaded runtime."
|
|
15165
|
+
};
|
|
15166
|
+
if (this.deps.applyRestartMode === "managed-service-restart") await requestManagedServiceRestart(this.deps.requestRestart, {
|
|
15167
|
+
reason: "runtime update apply",
|
|
15168
|
+
uiPort: this.deps.uiConfig.port
|
|
15169
|
+
});
|
|
15170
|
+
return this.snapshot;
|
|
15171
|
+
} catch (error) {
|
|
15172
|
+
this.snapshot = this.toFailedSnapshot(error);
|
|
15173
|
+
throw error;
|
|
15174
|
+
}
|
|
15175
|
+
};
|
|
15176
|
+
updatePreferences = async (preferences) => {
|
|
15177
|
+
const nextState = this.stateStore.update((current) => ({
|
|
15178
|
+
...current,
|
|
15179
|
+
updatePreferences: {
|
|
15180
|
+
...current.updatePreferences,
|
|
15181
|
+
...preferences
|
|
15182
|
+
}
|
|
15183
|
+
}));
|
|
15184
|
+
this.snapshot = this.createManager(nextState.channel).getSnapshot();
|
|
15185
|
+
if (nextState.updatePreferences.automaticChecks) this.startAutomaticSync({ force: true });
|
|
15186
|
+
return this.snapshot;
|
|
15187
|
+
};
|
|
15188
|
+
updateChannel = async (channel) => {
|
|
15189
|
+
const nextState = this.stateStore.update((current) => ({
|
|
15190
|
+
...current,
|
|
15191
|
+
channel
|
|
15192
|
+
}));
|
|
15193
|
+
this.snapshot = this.createManager(nextState.channel).getSnapshot();
|
|
15194
|
+
if (nextState.updatePreferences.automaticChecks) return this.startCheck({ autoDownload: nextState.updatePreferences.autoDownload });
|
|
15195
|
+
return this.snapshot;
|
|
15196
|
+
};
|
|
15197
|
+
startAutomaticSync = (options = {}) => {
|
|
15198
|
+
if (this.activeTask) return;
|
|
15199
|
+
if (this.automaticSyncStarted && !options.force) return;
|
|
15200
|
+
this.automaticSyncStarted = true;
|
|
15201
|
+
const state = this.stateStore.read();
|
|
15202
|
+
if (!state.updatePreferences.automaticChecks || state.downloadedVersion) return;
|
|
15203
|
+
this.startCheck({ autoDownload: state.updatePreferences.autoDownload });
|
|
15204
|
+
};
|
|
15205
|
+
startCheck = async (options) => {
|
|
15206
|
+
if (this.activeTask) return this.snapshot;
|
|
15207
|
+
this.snapshot = {
|
|
15208
|
+
...this.createManager().getSnapshot(),
|
|
15209
|
+
status: "checking",
|
|
15210
|
+
progress: null,
|
|
15211
|
+
errorMessage: null
|
|
15212
|
+
};
|
|
15213
|
+
this.activeTask = (async () => {
|
|
15214
|
+
try {
|
|
15215
|
+
const checkedSnapshot = await this.createManager().checkForUpdate();
|
|
15216
|
+
this.snapshot = checkedSnapshot;
|
|
15217
|
+
if (options.autoDownload && checkedSnapshot.status === "update-available") await this.runDownloadTask();
|
|
15218
|
+
} catch (error) {
|
|
15219
|
+
this.snapshot = this.toFailedSnapshot(error);
|
|
15220
|
+
} finally {
|
|
15221
|
+
this.activeTask = null;
|
|
15222
|
+
}
|
|
15223
|
+
})();
|
|
15224
|
+
return this.snapshot;
|
|
15225
|
+
};
|
|
15226
|
+
startDownload = async () => {
|
|
15227
|
+
if (this.activeTask) return this.snapshot;
|
|
15228
|
+
this.snapshot = {
|
|
15229
|
+
...this.createManager().getSnapshot(),
|
|
15230
|
+
status: "downloading",
|
|
15231
|
+
progress: INITIAL_DOWNLOAD_PROGRESS,
|
|
15232
|
+
errorMessage: null
|
|
15233
|
+
};
|
|
15234
|
+
this.activeTask = (async () => {
|
|
15235
|
+
try {
|
|
15236
|
+
await this.runDownloadTask();
|
|
15237
|
+
} catch (error) {
|
|
15238
|
+
this.snapshot = this.toFailedSnapshot(error);
|
|
15239
|
+
} finally {
|
|
15240
|
+
this.activeTask = null;
|
|
15241
|
+
}
|
|
15242
|
+
})();
|
|
15243
|
+
return this.snapshot;
|
|
15244
|
+
};
|
|
15245
|
+
runDownloadTask = async () => {
|
|
15246
|
+
this.snapshot = await this.createManager().downloadUpdate((progress) => {
|
|
15247
|
+
this.snapshot = {
|
|
15248
|
+
...this.snapshot,
|
|
15249
|
+
status: "downloading",
|
|
15250
|
+
progress,
|
|
15251
|
+
errorMessage: null
|
|
15252
|
+
};
|
|
15253
|
+
});
|
|
15254
|
+
};
|
|
15255
|
+
createManager = (channel = this.stateStore.read().channel) => {
|
|
15256
|
+
return new NpmRuntimeUpdateManager({
|
|
15257
|
+
layout: this.layout,
|
|
15258
|
+
stateStore: this.stateStore,
|
|
15259
|
+
bundleService: this.bundleService,
|
|
15260
|
+
updateService: this.updateService,
|
|
15261
|
+
resolveManifestUrl: (resolvedChannel) => this.source.resolveManifestUrl(resolvedChannel),
|
|
15262
|
+
launcherVersion: this.launcherVersion,
|
|
15263
|
+
channel
|
|
15264
|
+
});
|
|
15265
|
+
};
|
|
15266
|
+
toFailedSnapshot = (error) => {
|
|
15267
|
+
return {
|
|
15268
|
+
...this.createManager().getSnapshot(),
|
|
15269
|
+
status: "failed",
|
|
15270
|
+
progress: null,
|
|
15271
|
+
errorMessage: error instanceof Error ? error.message : String(error ?? "Unknown error")
|
|
15272
|
+
};
|
|
15273
|
+
};
|
|
15274
|
+
};
|
|
15275
|
+
function createNpmRuntimeUpdateHost(params) {
|
|
15276
|
+
return new NpmRuntimeUpdateHost(params);
|
|
15277
|
+
}
|
|
15278
|
+
//#endregion
|
|
15202
15279
|
//#region src/cli/shared/stores/pending-restart.store.ts
|
|
15203
15280
|
const clonePendingRestartState = (state) => {
|
|
15204
15281
|
if (!state) return null;
|
|
@@ -15320,12 +15397,19 @@ function createRuntimeControlHost(params) {
|
|
|
15320
15397
|
//#endregion
|
|
15321
15398
|
//#region src/cli/shared/services/ui/service-ui-hosts.service.ts
|
|
15322
15399
|
function createServiceUiHosts(params) {
|
|
15400
|
+
const { requestRestart, serviceCommands, uiConfig } = params;
|
|
15401
|
+
const applyRestartMode = managedServiceStateStore.read()?.pid === process.pid ? "managed-service-restart" : "manual-process-restart";
|
|
15323
15402
|
return {
|
|
15324
15403
|
remoteAccess: createRemoteAccessHost(params),
|
|
15325
15404
|
runtimeControl: createRuntimeControlHost({
|
|
15326
|
-
serviceCommands
|
|
15327
|
-
requestRestart
|
|
15328
|
-
uiConfig
|
|
15405
|
+
serviceCommands,
|
|
15406
|
+
requestRestart,
|
|
15407
|
+
uiConfig
|
|
15408
|
+
}),
|
|
15409
|
+
runtimeUpdate: process.env.NEXTCLAW_DISABLE_RUNTIME_UPDATE_HOST === "1" ? void 0 : createNpmRuntimeUpdateHost({
|
|
15410
|
+
applyRestartMode,
|
|
15411
|
+
requestRestart,
|
|
15412
|
+
uiConfig
|
|
15329
15413
|
})
|
|
15330
15414
|
};
|
|
15331
15415
|
}
|
|
@@ -15665,6 +15749,9 @@ var ConfigReloader = class {
|
|
|
15665
15749
|
setReloadMcp(callback) {
|
|
15666
15750
|
this.options.reloadMcp = callback;
|
|
15667
15751
|
}
|
|
15752
|
+
setReloadCompanion(callback) {
|
|
15753
|
+
this.options.reloadCompanion = callback;
|
|
15754
|
+
}
|
|
15668
15755
|
async applyReloadPlan(nextConfig) {
|
|
15669
15756
|
const changedPaths = diffConfigPaths(this.currentConfig, nextConfig);
|
|
15670
15757
|
if (!changedPaths.length) return;
|
|
@@ -15686,6 +15773,13 @@ var ConfigReloader = class {
|
|
|
15686
15773
|
});
|
|
15687
15774
|
console.log("Config reload: MCP servers reloaded.");
|
|
15688
15775
|
}
|
|
15776
|
+
if (plan.reloadCompanion) {
|
|
15777
|
+
await this.reloadCompanion({
|
|
15778
|
+
config: nextConfig,
|
|
15779
|
+
changedPaths
|
|
15780
|
+
});
|
|
15781
|
+
console.log("Config reload: companion setting applied.");
|
|
15782
|
+
}
|
|
15689
15783
|
if (plan.restartChannels || reloadPluginsResult?.restartChannels) {
|
|
15690
15784
|
await this.reloadChannels(nextConfig, { start: true });
|
|
15691
15785
|
console.log("Config reload: channels restarted.");
|
|
@@ -15781,6 +15875,10 @@ var ConfigReloader = class {
|
|
|
15781
15875
|
if (!this.options.reloadMcp) return;
|
|
15782
15876
|
await this.options.reloadMcp(params);
|
|
15783
15877
|
}
|
|
15878
|
+
async reloadCompanion(params) {
|
|
15879
|
+
if (!this.options.reloadCompanion) return;
|
|
15880
|
+
await this.options.reloadCompanion(params);
|
|
15881
|
+
}
|
|
15784
15882
|
};
|
|
15785
15883
|
//#endregion
|
|
15786
15884
|
//#region src/cli/shared/services/gateway/cron-job-handler.service.ts
|
|
@@ -16161,11 +16259,11 @@ function createSystemSessionUpdatedPublisher(params) {
|
|
|
16161
16259
|
}
|
|
16162
16260
|
async function startUiShell(params) {
|
|
16163
16261
|
logStartupTrace("service.start_ui_shell.begin");
|
|
16164
|
-
const { applyLiveConfigReload, configPath, cronService, getBootstrapStatus, getPluginChannelBindings, getPluginUiMetadata, initializeAgentHomeDirectory, marketplace, ncpSessionService, openBrowserWindow, productVersion, remoteAccess, runtimeControl, uiConfig, uiStaticDir } = params;
|
|
16262
|
+
const { applyLiveConfigReload, configPath, cronService, getBootstrapStatus, getPluginChannelBindings, getPluginUiMetadata, initializeAgentHomeDirectory, marketplace, ncpSessionService, openBrowserWindow, productVersion, remoteAccess, runtimeControl, runtimeUpdate, uiConfig, uiStaticDir } = params;
|
|
16165
16263
|
if (!uiConfig.enabled) return null;
|
|
16166
16264
|
let publishUiEvent = null;
|
|
16167
16265
|
const deferredNcpAgent = createDeferredUiNcpAgent();
|
|
16168
|
-
const uiServer = startUiServer({
|
|
16266
|
+
const uiServer = await startUiServer({
|
|
16169
16267
|
host: uiConfig.host,
|
|
16170
16268
|
port: uiConfig.port,
|
|
16171
16269
|
configPath,
|
|
@@ -16177,6 +16275,7 @@ async function startUiShell(params) {
|
|
|
16177
16275
|
marketplace,
|
|
16178
16276
|
remoteAccess,
|
|
16179
16277
|
runtimeControl,
|
|
16278
|
+
runtimeUpdate,
|
|
16180
16279
|
getBootstrapStatus,
|
|
16181
16280
|
getPluginChannelBindings,
|
|
16182
16281
|
getPluginUiMetadata,
|
|
@@ -16779,17 +16878,17 @@ function readStringList(value) {
|
|
|
16779
16878
|
if (!Array.isArray(value)) return [];
|
|
16780
16879
|
return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
|
|
16781
16880
|
}
|
|
16782
|
-
function readOptionalString(value) {
|
|
16881
|
+
function readOptionalString$1(value) {
|
|
16783
16882
|
if (typeof value !== "string") return;
|
|
16784
16883
|
return value.trim() || void 0;
|
|
16785
16884
|
}
|
|
16786
16885
|
function resolvePluginRuntimeAttachments(ctx) {
|
|
16787
16886
|
const mediaPaths = readStringList(ctx.MediaPaths);
|
|
16788
16887
|
const mediaUrls = readStringList(ctx.MediaUrls);
|
|
16789
|
-
const fallbackPath = readOptionalString(ctx.MediaPath);
|
|
16790
|
-
const fallbackUrl = readOptionalString(ctx.MediaUrl);
|
|
16888
|
+
const fallbackPath = readOptionalString$1(ctx.MediaPath);
|
|
16889
|
+
const fallbackUrl = readOptionalString$1(ctx.MediaUrl);
|
|
16791
16890
|
const mediaTypes = readStringList(ctx.MediaTypes);
|
|
16792
|
-
const fallbackType = readOptionalString(ctx.MediaType);
|
|
16891
|
+
const fallbackType = readOptionalString$1(ctx.MediaType);
|
|
16793
16892
|
const entryCount = Math.max(mediaPaths.length, mediaUrls.length, fallbackPath ? 1 : 0, fallbackUrl ? 1 : 0);
|
|
16794
16893
|
const attachments = [];
|
|
16795
16894
|
for (let index = 0; index < entryCount; index += 1) {
|
|
@@ -16812,7 +16911,7 @@ function resolvePluginRuntimeAttachments(ctx) {
|
|
|
16812
16911
|
//#region src/cli/shared/services/plugin/service-plugin-reload.service.ts
|
|
16813
16912
|
async function reloadServicePlugins(params) {
|
|
16814
16913
|
const nextWorkspace = getWorkspacePath(params.nextConfig.agents.defaults.workspace);
|
|
16815
|
-
const nextPluginRegistry =
|
|
16914
|
+
const nextPluginRegistry = await loadPluginRegistryProgressively(params.nextConfig, nextWorkspace);
|
|
16816
16915
|
const nextExtensionRegistry = toExtensionRegistry(nextPluginRegistry);
|
|
16817
16916
|
const nextPluginChannelBindings = getPluginChannelBindings(nextPluginRegistry);
|
|
16818
16917
|
const shouldRestartChannels = shouldRestartChannelsForPluginReload({
|
|
@@ -16868,30 +16967,52 @@ function applyGatewayRuntimeCapabilityState(params) {
|
|
|
16868
16967
|
params.state.extensionRegistry = params.next.extensionRegistry;
|
|
16869
16968
|
params.state.pluginChannelBindings = params.next.pluginChannelBindings;
|
|
16870
16969
|
}
|
|
16970
|
+
async function applyGatewayPluginReload(params) {
|
|
16971
|
+
const result = await reloadServicePlugins({
|
|
16972
|
+
nextConfig: params.nextConfig,
|
|
16973
|
+
changedPaths: params.changedPaths,
|
|
16974
|
+
pluginRegistry: params.state.pluginRegistry,
|
|
16975
|
+
extensionRegistry: params.state.extensionRegistry,
|
|
16976
|
+
pluginChannelBindings: params.state.pluginChannelBindings,
|
|
16977
|
+
pluginGatewayHandles: params.state.pluginGatewayHandles,
|
|
16978
|
+
pluginGatewayLogger,
|
|
16979
|
+
logPluginGatewayDiagnostics
|
|
16980
|
+
});
|
|
16981
|
+
applyGatewayRuntimeCapabilityState({
|
|
16982
|
+
gateway: params.gateway,
|
|
16983
|
+
state: params.state,
|
|
16984
|
+
next: {
|
|
16985
|
+
pluginRegistry: result.pluginRegistry,
|
|
16986
|
+
extensionRegistry: result.extensionRegistry,
|
|
16987
|
+
pluginChannelBindings: result.pluginChannelBindings
|
|
16988
|
+
}
|
|
16989
|
+
});
|
|
16990
|
+
params.state.pluginUiMetadata = getPluginUiMetadataFromRegistry(result.pluginRegistry);
|
|
16991
|
+
params.state.pluginGatewayHandles = result.pluginGatewayHandles;
|
|
16992
|
+
params.getLiveUiNcpAgent()?.applyExtensionRegistry?.(result.extensionRegistry);
|
|
16993
|
+
return { restartChannels: result.restartChannels };
|
|
16994
|
+
}
|
|
16995
|
+
async function reloadGatewayPluginRuntimeForChanges(params) {
|
|
16996
|
+
const nextConfig = resolveConfigSecrets$2(loadConfig$2(), { configPath: params.gateway.runtimeConfigPath });
|
|
16997
|
+
const result = await applyGatewayPluginReload({
|
|
16998
|
+
gateway: params.gateway,
|
|
16999
|
+
state: params.state,
|
|
17000
|
+
getLiveUiNcpAgent: params.getLiveUiNcpAgent,
|
|
17001
|
+
nextConfig,
|
|
17002
|
+
changedPaths: params.changedPaths
|
|
17003
|
+
});
|
|
17004
|
+
if (result.restartChannels) await params.gateway.reloader.rebuildChannels(nextConfig, { start: true });
|
|
17005
|
+
return result;
|
|
17006
|
+
}
|
|
16871
17007
|
function configureGatewayPluginRuntime(params) {
|
|
16872
17008
|
params.gateway.reloader.setReloadPlugins(async ({ config: nextConfig, changedPaths }) => {
|
|
16873
|
-
const result = await
|
|
16874
|
-
nextConfig,
|
|
16875
|
-
changedPaths,
|
|
16876
|
-
pluginRegistry: params.state.pluginRegistry,
|
|
16877
|
-
extensionRegistry: params.state.extensionRegistry,
|
|
16878
|
-
pluginChannelBindings: params.state.pluginChannelBindings,
|
|
16879
|
-
pluginGatewayHandles: params.state.pluginGatewayHandles,
|
|
16880
|
-
pluginGatewayLogger,
|
|
16881
|
-
logPluginGatewayDiagnostics
|
|
16882
|
-
});
|
|
16883
|
-
applyGatewayRuntimeCapabilityState({
|
|
17009
|
+
const result = await applyGatewayPluginReload({
|
|
16884
17010
|
gateway: params.gateway,
|
|
16885
17011
|
state: params.state,
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
pluginChannelBindings: result.pluginChannelBindings
|
|
16890
|
-
}
|
|
17012
|
+
getLiveUiNcpAgent: params.getLiveUiNcpAgent,
|
|
17013
|
+
nextConfig,
|
|
17014
|
+
changedPaths
|
|
16891
17015
|
});
|
|
16892
|
-
params.state.pluginUiMetadata = getPluginUiMetadataFromRegistry(result.pluginRegistry);
|
|
16893
|
-
params.state.pluginGatewayHandles = result.pluginGatewayHandles;
|
|
16894
|
-
params.getLiveUiNcpAgent()?.applyExtensionRegistry?.(result.extensionRegistry);
|
|
16895
17016
|
if (result.restartChannels) console.log("Config reload: plugin channel gateways restarted.");
|
|
16896
17017
|
return { restartChannels: result.restartChannels };
|
|
16897
17018
|
});
|
|
@@ -16962,8 +17083,282 @@ async function cleanupGatewayRuntime(params) {
|
|
|
16962
17083
|
setPluginRuntimeBridge(null);
|
|
16963
17084
|
}
|
|
16964
17085
|
//#endregion
|
|
17086
|
+
//#region src/cli/shared/services/plugin/service-plugin-dev-hot-reload.service.ts
|
|
17087
|
+
const DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV = "NEXTCLAW_DEV_PLUGIN_HOT_RELOAD_TARGETS";
|
|
17088
|
+
function isRecord$2(value) {
|
|
17089
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
17090
|
+
}
|
|
17091
|
+
function readOptionalString(value) {
|
|
17092
|
+
if (typeof value !== "string") return null;
|
|
17093
|
+
const trimmed = value.trim();
|
|
17094
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
17095
|
+
}
|
|
17096
|
+
function normalizeWatchPaths(value) {
|
|
17097
|
+
if (!Array.isArray(value)) return [];
|
|
17098
|
+
const watchPaths = [];
|
|
17099
|
+
for (const entry of value) {
|
|
17100
|
+
const normalized = readOptionalString(entry);
|
|
17101
|
+
if (!normalized) continue;
|
|
17102
|
+
const resolvedPath = resolve(normalized);
|
|
17103
|
+
if (!watchPaths.includes(resolvedPath)) watchPaths.push(resolvedPath);
|
|
17104
|
+
}
|
|
17105
|
+
return watchPaths;
|
|
17106
|
+
}
|
|
17107
|
+
function resolveDevPluginHotReloadTargets(rawValue = process.env[DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV]) {
|
|
17108
|
+
if (typeof rawValue !== "string" || rawValue.trim().length === 0) return [];
|
|
17109
|
+
let parsed;
|
|
17110
|
+
try {
|
|
17111
|
+
parsed = JSON.parse(rawValue);
|
|
17112
|
+
} catch (error) {
|
|
17113
|
+
throw new Error(`[dev-plugin-hot-reload] failed to parse ${DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV}: ${error instanceof Error ? error.message : String(error)}`);
|
|
17114
|
+
}
|
|
17115
|
+
if (!Array.isArray(parsed)) throw new Error(`[dev-plugin-hot-reload] ${DEV_PLUGIN_HOT_RELOAD_TARGETS_ENV} must be a JSON array`);
|
|
17116
|
+
const seenPluginIds = /* @__PURE__ */ new Set();
|
|
17117
|
+
const targets = [];
|
|
17118
|
+
for (const entry of parsed) {
|
|
17119
|
+
if (!isRecord$2(entry)) continue;
|
|
17120
|
+
const pluginId = readOptionalString(entry.pluginId);
|
|
17121
|
+
const pluginPath = readOptionalString(entry.pluginPath);
|
|
17122
|
+
const watchPaths = normalizeWatchPaths(entry.watchPaths);
|
|
17123
|
+
if (!pluginId || !pluginPath || watchPaths.length === 0) continue;
|
|
17124
|
+
if (seenPluginIds.has(pluginId)) throw new Error(`[dev-plugin-hot-reload] duplicate plugin target for "${pluginId}"`);
|
|
17125
|
+
seenPluginIds.add(pluginId);
|
|
17126
|
+
targets.push({
|
|
17127
|
+
pluginId,
|
|
17128
|
+
pluginPath: resolve(pluginPath),
|
|
17129
|
+
watchPaths
|
|
17130
|
+
});
|
|
17131
|
+
}
|
|
17132
|
+
return targets;
|
|
17133
|
+
}
|
|
17134
|
+
function startDevPluginHotReloadWatcher(params) {
|
|
17135
|
+
const targets = params.targets ?? resolveDevPluginHotReloadTargets();
|
|
17136
|
+
if (targets.length === 0) return;
|
|
17137
|
+
const pendingPluginIds = /* @__PURE__ */ new Set();
|
|
17138
|
+
let flushTimer = null;
|
|
17139
|
+
let reloadRunning = false;
|
|
17140
|
+
let reloadPending = false;
|
|
17141
|
+
const flushReload = async () => {
|
|
17142
|
+
if (reloadRunning) {
|
|
17143
|
+
reloadPending = true;
|
|
17144
|
+
return;
|
|
17145
|
+
}
|
|
17146
|
+
const pluginIds = [...pendingPluginIds];
|
|
17147
|
+
pendingPluginIds.clear();
|
|
17148
|
+
if (pluginIds.length === 0) return;
|
|
17149
|
+
reloadRunning = true;
|
|
17150
|
+
try {
|
|
17151
|
+
console.log(`[dev] Plugin dist updated: ${pluginIds.join(", ")}`);
|
|
17152
|
+
await params.reloadPlugins(pluginIds);
|
|
17153
|
+
console.log(`[dev] Plugin hot reload applied: ${pluginIds.join(", ")}`);
|
|
17154
|
+
} catch (error) {
|
|
17155
|
+
console.error(`[dev] Plugin hot reload failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
17156
|
+
} finally {
|
|
17157
|
+
reloadRunning = false;
|
|
17158
|
+
if (reloadPending || pendingPluginIds.size > 0) {
|
|
17159
|
+
reloadPending = false;
|
|
17160
|
+
await flushReload();
|
|
17161
|
+
}
|
|
17162
|
+
}
|
|
17163
|
+
};
|
|
17164
|
+
const scheduleReload = (pluginId) => {
|
|
17165
|
+
pendingPluginIds.add(pluginId);
|
|
17166
|
+
if (flushTimer) clearTimeout(flushTimer);
|
|
17167
|
+
flushTimer = setTimeout(() => {
|
|
17168
|
+
flushTimer = null;
|
|
17169
|
+
flushReload();
|
|
17170
|
+
}, 150);
|
|
17171
|
+
};
|
|
17172
|
+
const watcher = chokidar.watch(targets.flatMap((entry) => entry.watchPaths), {
|
|
17173
|
+
ignoreInitial: true,
|
|
17174
|
+
awaitWriteFinish: {
|
|
17175
|
+
stabilityThreshold: 200,
|
|
17176
|
+
pollInterval: 50
|
|
17177
|
+
}
|
|
17178
|
+
});
|
|
17179
|
+
params.watcherRegistry.remember(watcher);
|
|
17180
|
+
watcher.on("all", (_event, changedPath) => {
|
|
17181
|
+
const normalizedChangedPath = resolve(changedPath);
|
|
17182
|
+
for (const target of targets) if (target.watchPaths.some((watchPath) => normalizedChangedPath === watchPath || normalizedChangedPath.startsWith(`${watchPath}${sep}`))) scheduleReload(target.pluginId);
|
|
17183
|
+
});
|
|
17184
|
+
console.log(`[dev] Plugin hot reload watcher: ${targets.map((entry) => entry.pluginId).join(", ")}`);
|
|
17185
|
+
}
|
|
17186
|
+
function wrapStartChannelsWithDevPluginHotReload(params) {
|
|
17187
|
+
return async () => {
|
|
17188
|
+
await params.startChannels();
|
|
17189
|
+
console.log(`[dev] Plugin hot reload watcher will arm after ${params.startupSettleMs}ms startup settle window.`);
|
|
17190
|
+
setTimeout(() => {
|
|
17191
|
+
if (!params.isRuntimeActive()) return;
|
|
17192
|
+
startDevPluginHotReloadWatcher({
|
|
17193
|
+
watcherRegistry: params.watcherRegistry,
|
|
17194
|
+
reloadPlugins: params.reloadPlugins
|
|
17195
|
+
});
|
|
17196
|
+
}, params.startupSettleMs).unref?.();
|
|
17197
|
+
};
|
|
17198
|
+
}
|
|
17199
|
+
//#endregion
|
|
17200
|
+
//#region src/cli/shared/stores/companion-runtime.store.ts
|
|
17201
|
+
var CompanionRuntimeStore = class {
|
|
17202
|
+
get path() {
|
|
17203
|
+
return resolve(getDataDir(), "run", "companion.json");
|
|
17204
|
+
}
|
|
17205
|
+
read = () => {
|
|
17206
|
+
if (!existsSync(this.path)) return null;
|
|
17207
|
+
try {
|
|
17208
|
+
return JSON.parse(readFileSync(this.path, "utf-8"));
|
|
17209
|
+
} catch {
|
|
17210
|
+
return null;
|
|
17211
|
+
}
|
|
17212
|
+
};
|
|
17213
|
+
write = (state) => {
|
|
17214
|
+
mkdirSync(resolve(this.path, ".."), { recursive: true });
|
|
17215
|
+
writeFileSync(this.path, JSON.stringify(state, null, 2));
|
|
17216
|
+
};
|
|
17217
|
+
clear = () => {
|
|
17218
|
+
if (existsSync(this.path)) rmSync(this.path, { force: true });
|
|
17219
|
+
};
|
|
17220
|
+
};
|
|
17221
|
+
const companionRuntimeStore = new CompanionRuntimeStore();
|
|
17222
|
+
//#endregion
|
|
17223
|
+
//#region src/cli/shared/services/ui/companion-runtime.service.ts
|
|
17224
|
+
const require$2 = createRequire(import.meta.url);
|
|
17225
|
+
var CompanionRuntimeService = class {
|
|
17226
|
+
constructor(runtimeStore = companionRuntimeStore, uiDiscoveryService = localUiDiscoveryService) {
|
|
17227
|
+
this.runtimeStore = runtimeStore;
|
|
17228
|
+
this.uiDiscoveryService = uiDiscoveryService;
|
|
17229
|
+
}
|
|
17230
|
+
getRunningState = () => {
|
|
17231
|
+
const state = this.runtimeStore.read();
|
|
17232
|
+
if (!state) return null;
|
|
17233
|
+
if (!isProcessRunning(state.pid)) {
|
|
17234
|
+
this.runtimeStore.clear();
|
|
17235
|
+
return null;
|
|
17236
|
+
}
|
|
17237
|
+
return state;
|
|
17238
|
+
};
|
|
17239
|
+
resolveDiscoveredBaseUrl = () => {
|
|
17240
|
+
return this.uiDiscoveryService.resolveApiBase();
|
|
17241
|
+
};
|
|
17242
|
+
applyConfig = async (config) => {
|
|
17243
|
+
if (!config.companion.enabled) {
|
|
17244
|
+
await this.ensureStopped();
|
|
17245
|
+
return;
|
|
17246
|
+
}
|
|
17247
|
+
await this.ensureStarted({ baseUrl: this.uiDiscoveryService.resolveLocalOrigin(config) });
|
|
17248
|
+
};
|
|
17249
|
+
updateEnabled = async (enabled, options = {}) => {
|
|
17250
|
+
const config = loadConfig(getConfigPath());
|
|
17251
|
+
const next = {
|
|
17252
|
+
...config,
|
|
17253
|
+
companion: {
|
|
17254
|
+
...config.companion,
|
|
17255
|
+
enabled
|
|
17256
|
+
}
|
|
17257
|
+
};
|
|
17258
|
+
saveConfig(next, getConfigPath());
|
|
17259
|
+
if (enabled) {
|
|
17260
|
+
const explicitBaseUrl = options.baseUrl?.trim();
|
|
17261
|
+
if (explicitBaseUrl) {
|
|
17262
|
+
await this.ensureStarted({ baseUrl: explicitBaseUrl });
|
|
17263
|
+
return next;
|
|
17264
|
+
}
|
|
17265
|
+
const discoveredBaseUrl = this.uiDiscoveryService.resolveApiBase();
|
|
17266
|
+
if (discoveredBaseUrl) await this.ensureStarted({ baseUrl: discoveredBaseUrl });
|
|
17267
|
+
return next;
|
|
17268
|
+
}
|
|
17269
|
+
await this.ensureStopped();
|
|
17270
|
+
return next;
|
|
17271
|
+
};
|
|
17272
|
+
ensureStarted = async (options) => {
|
|
17273
|
+
const baseUrl = options.baseUrl.trim().replace(/\/+$/, "");
|
|
17274
|
+
const runningState = this.getRunningState();
|
|
17275
|
+
if (runningState?.baseUrl === baseUrl) return runningState;
|
|
17276
|
+
if (runningState) {
|
|
17277
|
+
this.killProcess(runningState.pid, false);
|
|
17278
|
+
this.runtimeStore.clear();
|
|
17279
|
+
}
|
|
17280
|
+
const launchSpec = this.resolveLaunchSpec();
|
|
17281
|
+
const child = spawn(launchSpec.command, [
|
|
17282
|
+
...launchSpec.args,
|
|
17283
|
+
"--base-url",
|
|
17284
|
+
baseUrl
|
|
17285
|
+
], {
|
|
17286
|
+
detached: true,
|
|
17287
|
+
stdio: "ignore",
|
|
17288
|
+
env: {
|
|
17289
|
+
...process.env,
|
|
17290
|
+
NEXTCLAW_COMPANION_RUNTIME_STATE_PATH: this.runtimeStore.path
|
|
17291
|
+
}
|
|
17292
|
+
});
|
|
17293
|
+
child.unref();
|
|
17294
|
+
return await this.waitForRunningState(baseUrl, child.pid ?? -1);
|
|
17295
|
+
};
|
|
17296
|
+
ensureStopped = async (options = {}) => {
|
|
17297
|
+
const state = this.runtimeStore.read();
|
|
17298
|
+
if (!state) return false;
|
|
17299
|
+
if (!isProcessRunning(state.pid)) {
|
|
17300
|
+
this.runtimeStore.clear();
|
|
17301
|
+
return false;
|
|
17302
|
+
}
|
|
17303
|
+
this.killProcess(state.pid, options.force === true);
|
|
17304
|
+
this.runtimeStore.clear();
|
|
17305
|
+
return true;
|
|
17306
|
+
};
|
|
17307
|
+
printStatus = (options = {}) => {
|
|
17308
|
+
const runningState = this.getRunningState();
|
|
17309
|
+
const config = loadConfig(getConfigPath());
|
|
17310
|
+
const view = runningState ? {
|
|
17311
|
+
configuredEnabled: config.companion.enabled,
|
|
17312
|
+
running: true,
|
|
17313
|
+
...runningState
|
|
17314
|
+
} : {
|
|
17315
|
+
configuredEnabled: config.companion.enabled,
|
|
17316
|
+
running: false
|
|
17317
|
+
};
|
|
17318
|
+
if (options.json) {
|
|
17319
|
+
console.log(JSON.stringify(view, null, 2));
|
|
17320
|
+
return;
|
|
17321
|
+
}
|
|
17322
|
+
if (!runningState) {
|
|
17323
|
+
console.log(config.companion.enabled ? "Companion is enabled in config but is not running." : "Companion is disabled and not running.");
|
|
17324
|
+
return;
|
|
17325
|
+
}
|
|
17326
|
+
console.log(`Companion is running (pid ${runningState.pid}) at ${runningState.baseUrl}. Configured enabled: ${config.companion.enabled ? "yes" : "no"}.`);
|
|
17327
|
+
};
|
|
17328
|
+
printStarted = (state) => {
|
|
17329
|
+
console.log(`Started ${APP_NAME} companion (pid ${state.pid}) using ${state.baseUrl}.`);
|
|
17330
|
+
};
|
|
17331
|
+
printStopped = (stopped) => {
|
|
17332
|
+
console.log(stopped ? "Stopped companion process." : "Companion is not running.");
|
|
17333
|
+
};
|
|
17334
|
+
killProcess = (pid, force) => {
|
|
17335
|
+
process.kill(pid, force ? "SIGKILL" : "SIGTERM");
|
|
17336
|
+
};
|
|
17337
|
+
resolveLaunchSpec = () => {
|
|
17338
|
+
const packageJsonPath = require$2.resolve("@nextclaw/companion/package.json");
|
|
17339
|
+
const packageRoot = dirname(packageJsonPath);
|
|
17340
|
+
const mainPath = resolve(packageRoot, "dist", "src", "main.js");
|
|
17341
|
+
if (!existsSync(mainPath)) throw new Error(`Companion app build is missing at ${mainPath}. Build @nextclaw/companion first.`);
|
|
17342
|
+
return {
|
|
17343
|
+
command: createRequire(packageJsonPath)("electron"),
|
|
17344
|
+
args: [packageRoot]
|
|
17345
|
+
};
|
|
17346
|
+
};
|
|
17347
|
+
waitForRunningState = async (baseUrl, fallbackPid) => {
|
|
17348
|
+
const timeoutAt = Date.now() + 5e3;
|
|
17349
|
+
while (Date.now() < timeoutAt) {
|
|
17350
|
+
const state = this.getRunningState();
|
|
17351
|
+
if (state?.baseUrl === baseUrl) return state;
|
|
17352
|
+
await new Promise((resolvePromise) => setTimeout(resolvePromise, 100));
|
|
17353
|
+
}
|
|
17354
|
+
throw new Error(fallbackPid > 0 ? `Companion started but did not report a live runtime state (launcher pid ${fallbackPid}).` : "Companion started but did not report a live runtime state.");
|
|
17355
|
+
};
|
|
17356
|
+
};
|
|
17357
|
+
const companionRuntimeService = new CompanionRuntimeService();
|
|
17358
|
+
//#endregion
|
|
16965
17359
|
//#region src/cli/shared/services/runtime/runtime-command.service.ts
|
|
16966
17360
|
const { getApiBase, getConfigPath: getConfigPath$1, getProvider, getProviderName, getWorkspacePath: getWorkspacePath$1, loadConfig: loadConfig$1, LiteLLMProvider, MessageBus: MessageBus$1, resolveConfigSecrets: resolveConfigSecrets$1, SessionManager: SessionManager$1, parseAgentScopedSessionKey: parseAgentScopedSessionKey$1 } = NextclawCore;
|
|
17361
|
+
const DEV_PLUGIN_HOT_RELOAD_STARTUP_SETTLE_MS = 5e3;
|
|
16967
17362
|
function createSkillsLoader(workspace) {
|
|
16968
17363
|
const ctor = NextclawCore.SkillsLoader;
|
|
16969
17364
|
if (!ctor) return null;
|
|
@@ -17008,38 +17403,16 @@ var RuntimeCommandService = class {
|
|
|
17008
17403
|
runCliSubcommand: (args) => this.runCliSubcommand(args),
|
|
17009
17404
|
installBuiltinSkill: (slug, force) => this.installBuiltinMarketplaceSkill(slug, force)
|
|
17010
17405
|
}).createInstaller();
|
|
17011
|
-
const
|
|
17012
|
-
|
|
17013
|
-
requestRestart: this.deps.requestRestart,
|
|
17014
|
-
uiConfig: shellContext.uiConfig,
|
|
17015
|
-
remoteModule: shellContext.remoteModule
|
|
17016
|
-
});
|
|
17017
|
-
const uiStartup = await measureStartupAsync("service.start_ui_shell", async () => await startUiShell({
|
|
17018
|
-
uiConfig: shellContext.uiConfig,
|
|
17019
|
-
uiStaticDir: shellContext.uiStaticDir,
|
|
17020
|
-
cronService: shellContext.cron,
|
|
17021
|
-
getConfig: getRuntimeConfig,
|
|
17022
|
-
configPath: getConfigPath$1(),
|
|
17023
|
-
productVersion: getPackageVersion$1(),
|
|
17024
|
-
getPluginChannelBindings: () => runtimeState?.pluginChannelBindings ?? [],
|
|
17025
|
-
getPluginUiMetadata: () => runtimeState?.pluginUiMetadata ?? [],
|
|
17026
|
-
marketplace: {
|
|
17027
|
-
apiBaseUrl: process.env.NEXTCLAW_MARKETPLACE_API_BASE,
|
|
17028
|
-
installer: marketplaceInstaller
|
|
17029
|
-
},
|
|
17030
|
-
remoteAccess,
|
|
17031
|
-
runtimeControl,
|
|
17032
|
-
getBootstrapStatus: () => bootstrapStatus.getStatus(),
|
|
17033
|
-
openBrowserWindow: shellContext.uiConfig.open,
|
|
17406
|
+
const uiStartup = await this.startGatewayUiShell({
|
|
17407
|
+
shellContext,
|
|
17034
17408
|
applyLiveConfigReload,
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
setUiEventPublisher: (publish) => ncpSessionRealtimeBridge.setUiEventPublisher(publish),
|
|
17041
|
-
uiConfig: shellContext.uiConfig
|
|
17409
|
+
bootstrapStatus,
|
|
17410
|
+
marketplaceInstaller,
|
|
17411
|
+
ncpSessionRealtimeBridge,
|
|
17412
|
+
getRuntimeConfig,
|
|
17413
|
+
getRuntimeState: () => runtimeState
|
|
17042
17414
|
});
|
|
17415
|
+
await companionRuntimeService.applyConfig(shellContext.config);
|
|
17043
17416
|
bootstrapStatus.markShellReady();
|
|
17044
17417
|
await setImmediate$1();
|
|
17045
17418
|
const gateway = measureStartupSync("service.create_gateway_startup_context", () => createGatewayStartupContext({
|
|
@@ -17057,33 +17430,14 @@ var RuntimeCommandService = class {
|
|
|
17057
17430
|
const loadGatewayConfig = () => resolveConfigSecrets$1(loadConfig$1(), { configPath: gateway.runtimeConfigPath });
|
|
17058
17431
|
const gatewayRuntimeState = createGatewayRuntimeState(gateway);
|
|
17059
17432
|
runtimeState = gatewayRuntimeState;
|
|
17060
|
-
|
|
17061
|
-
|
|
17062
|
-
payload: { path: "channels" }
|
|
17063
|
-
});
|
|
17064
|
-
uiStartup?.publish({
|
|
17065
|
-
type: "config.updated",
|
|
17066
|
-
payload: { path: "plugins" }
|
|
17433
|
+
gateway.reloader.setReloadCompanion(async ({ config: nextConfig }) => {
|
|
17434
|
+
await companionRuntimeService.applyConfig(nextConfig);
|
|
17067
17435
|
});
|
|
17068
|
-
|
|
17436
|
+
await this.hydrateGatewayRuntime({
|
|
17069
17437
|
gateway,
|
|
17070
|
-
|
|
17071
|
-
|
|
17438
|
+
gatewayRuntimeState,
|
|
17439
|
+
uiStartup
|
|
17072
17440
|
});
|
|
17073
|
-
console.log("✓ Capability hydration: scheduled in background");
|
|
17074
|
-
await measureStartupAsync("service.start_gateway_support_services", async () => await startGatewayRuntimeSupport({
|
|
17075
|
-
cronJobs: gateway.cron.status().jobs,
|
|
17076
|
-
remoteModule: gateway.remoteModule,
|
|
17077
|
-
watchConfigFile: () => watchServiceConfigFile({
|
|
17078
|
-
configPath: resolve(getConfigPath$1()),
|
|
17079
|
-
watcherRegistry: this.fileWatchers,
|
|
17080
|
-
scheduleReload: (reason) => gateway.reloader.scheduleReload(reason)
|
|
17081
|
-
}),
|
|
17082
|
-
startCron: () => gateway.cron.start(),
|
|
17083
|
-
cronStorePath: resolve(join(NextclawCore.getDataDir(), "cron", "jobs.json")),
|
|
17084
|
-
reloadCronStore: () => gateway.cron.reloadFromStore(),
|
|
17085
|
-
watcherRegistry: this.fileWatchers
|
|
17086
|
-
}));
|
|
17087
17441
|
const deferredGatewayStartupHooks = createDeferredGatewayStartupHooks({
|
|
17088
17442
|
uiStartup,
|
|
17089
17443
|
gateway,
|
|
@@ -17098,6 +17452,20 @@ var RuntimeCommandService = class {
|
|
|
17098
17452
|
sessionManager: gateway.sessionManager
|
|
17099
17453
|
})
|
|
17100
17454
|
});
|
|
17455
|
+
deferredGatewayStartupHooks.startChannels = wrapStartChannelsWithDevPluginHotReload({
|
|
17456
|
+
startChannels: deferredGatewayStartupHooks.startChannels,
|
|
17457
|
+
watcherRegistry: this.fileWatchers,
|
|
17458
|
+
isRuntimeActive: () => Boolean(this.applyLiveConfigReload),
|
|
17459
|
+
reloadPlugins: async (pluginIds) => {
|
|
17460
|
+
await reloadGatewayPluginRuntimeForChanges({
|
|
17461
|
+
gateway,
|
|
17462
|
+
state: gatewayRuntimeState,
|
|
17463
|
+
getLiveUiNcpAgent: () => this.liveUiNcpAgent,
|
|
17464
|
+
changedPaths: pluginIds.map((pluginId) => `plugins.entries.${pluginId}.source`)
|
|
17465
|
+
});
|
|
17466
|
+
},
|
|
17467
|
+
startupSettleMs: DEV_PLUGIN_HOT_RELOAD_STARTUP_SETTLE_MS
|
|
17468
|
+
});
|
|
17101
17469
|
await runConfiguredGatewayRuntime({
|
|
17102
17470
|
uiStartup,
|
|
17103
17471
|
bootstrapStatus,
|
|
@@ -17125,14 +17493,84 @@ var RuntimeCommandService = class {
|
|
|
17125
17493
|
this.applyLiveConfigReload = null;
|
|
17126
17494
|
this.liveUiNcpAgent = null;
|
|
17127
17495
|
},
|
|
17128
|
-
clearRealtimeBridge: () =>
|
|
17496
|
+
clearRealtimeBridge: () => {
|
|
17497
|
+
ncpSessionRealtimeBridge.clear();
|
|
17498
|
+
},
|
|
17129
17499
|
uiStartup,
|
|
17130
17500
|
remoteModule: gateway.remoteModule,
|
|
17131
17501
|
runtimeState
|
|
17132
17502
|
})
|
|
17133
17503
|
});
|
|
17504
|
+
await companionRuntimeService.ensureStopped();
|
|
17134
17505
|
logStartupTrace("service.start_gateway.end");
|
|
17135
17506
|
};
|
|
17507
|
+
startGatewayUiShell = async (params) => {
|
|
17508
|
+
const { applyLiveConfigReload, bootstrapStatus, getRuntimeConfig, getRuntimeState, marketplaceInstaller, ncpSessionRealtimeBridge, shellContext } = params;
|
|
17509
|
+
const { remoteAccess, runtimeControl, runtimeUpdate } = createServiceUiHosts({
|
|
17510
|
+
serviceCommands: this,
|
|
17511
|
+
requestRestart: this.deps.requestRestart,
|
|
17512
|
+
uiConfig: shellContext.uiConfig,
|
|
17513
|
+
remoteModule: shellContext.remoteModule
|
|
17514
|
+
});
|
|
17515
|
+
const uiStartup = await measureStartupAsync("service.start_ui_shell", async () => await startUiShell({
|
|
17516
|
+
uiConfig: shellContext.uiConfig,
|
|
17517
|
+
uiStaticDir: shellContext.uiStaticDir,
|
|
17518
|
+
cronService: shellContext.cron,
|
|
17519
|
+
getConfig: getRuntimeConfig,
|
|
17520
|
+
configPath: getConfigPath$1(),
|
|
17521
|
+
productVersion: getPackageVersion$1(),
|
|
17522
|
+
getPluginChannelBindings: () => getRuntimeState()?.pluginChannelBindings ?? [],
|
|
17523
|
+
getPluginUiMetadata: () => getRuntimeState()?.pluginUiMetadata ?? [],
|
|
17524
|
+
marketplace: {
|
|
17525
|
+
apiBaseUrl: process.env.NEXTCLAW_MARKETPLACE_API_BASE,
|
|
17526
|
+
installer: marketplaceInstaller
|
|
17527
|
+
},
|
|
17528
|
+
remoteAccess,
|
|
17529
|
+
runtimeControl,
|
|
17530
|
+
runtimeUpdate,
|
|
17531
|
+
getBootstrapStatus: () => bootstrapStatus.getStatus(),
|
|
17532
|
+
openBrowserWindow: shellContext.uiConfig.open,
|
|
17533
|
+
applyLiveConfigReload,
|
|
17534
|
+
ncpSessionService: ncpSessionRealtimeBridge.sessionService,
|
|
17535
|
+
initializeAgentHomeDirectory: this.deps.initializeAgentHomeDirectory
|
|
17536
|
+
}));
|
|
17537
|
+
finalizeLocalUiStartup({
|
|
17538
|
+
uiStartup,
|
|
17539
|
+
setUiEventPublisher: (publish) => ncpSessionRealtimeBridge.setUiEventPublisher(publish),
|
|
17540
|
+
uiConfig: shellContext.uiConfig
|
|
17541
|
+
});
|
|
17542
|
+
return uiStartup;
|
|
17543
|
+
};
|
|
17544
|
+
hydrateGatewayRuntime = async (params) => {
|
|
17545
|
+
const { gateway, gatewayRuntimeState, uiStartup } = params;
|
|
17546
|
+
uiStartup?.publish({
|
|
17547
|
+
type: "config.updated",
|
|
17548
|
+
payload: { path: "channels" }
|
|
17549
|
+
});
|
|
17550
|
+
uiStartup?.publish({
|
|
17551
|
+
type: "config.updated",
|
|
17552
|
+
payload: { path: "plugins" }
|
|
17553
|
+
});
|
|
17554
|
+
configureGatewayPluginRuntime({
|
|
17555
|
+
gateway,
|
|
17556
|
+
state: gatewayRuntimeState,
|
|
17557
|
+
getLiveUiNcpAgent: () => this.liveUiNcpAgent
|
|
17558
|
+
});
|
|
17559
|
+
console.log("✓ Capability hydration: scheduled in background");
|
|
17560
|
+
await measureStartupAsync("service.start_gateway_support_services", async () => await startGatewayRuntimeSupport({
|
|
17561
|
+
cronJobs: gateway.cron.status().jobs,
|
|
17562
|
+
remoteModule: gateway.remoteModule,
|
|
17563
|
+
watchConfigFile: () => watchServiceConfigFile({
|
|
17564
|
+
configPath: resolve(getConfigPath$1()),
|
|
17565
|
+
watcherRegistry: this.fileWatchers,
|
|
17566
|
+
scheduleReload: (reason) => gateway.reloader.scheduleReload(reason)
|
|
17567
|
+
}),
|
|
17568
|
+
startCron: () => gateway.cron.start(),
|
|
17569
|
+
cronStorePath: resolve(join(NextclawCore.getDataDir(), "cron", "jobs.json")),
|
|
17570
|
+
reloadCronStore: () => gateway.cron.reloadFromStore(),
|
|
17571
|
+
watcherRegistry: this.fileWatchers
|
|
17572
|
+
}));
|
|
17573
|
+
};
|
|
17136
17574
|
normalizeOptionalString = (value) => {
|
|
17137
17575
|
if (typeof value !== "string") return;
|
|
17138
17576
|
return value.trim() || void 0;
|
|
@@ -18167,7 +18605,7 @@ var MacosLaunchAgentAutostartService = class {
|
|
|
18167
18605
|
` <string>${this.escapeXml(homeDir)}</string>`,
|
|
18168
18606
|
" </dict>",
|
|
18169
18607
|
" <key>RunAtLoad</key><true/>",
|
|
18170
|
-
" <key>KeepAlive</key><
|
|
18608
|
+
" <key>KeepAlive</key><false/>",
|
|
18171
18609
|
` <key>StandardOutPath</key><string>${this.escapeXml(stdoutPath)}</string>`,
|
|
18172
18610
|
` <key>StandardErrorPath</key><string>${this.escapeXml(stderrPath)}</string>`,
|
|
18173
18611
|
"</dict>",
|
|
@@ -19035,6 +19473,30 @@ var RuntimeRestartRequestService = class {
|
|
|
19035
19473
|
};
|
|
19036
19474
|
};
|
|
19037
19475
|
//#endregion
|
|
19476
|
+
//#region src/cli/shared/utils/runtime-helpers.ts
|
|
19477
|
+
function resolveSkillsInstallWorkdir(params) {
|
|
19478
|
+
if (params.explicitWorkdir) return expandHome(params.explicitWorkdir);
|
|
19479
|
+
return getWorkspacePath(params.configuredWorkspace);
|
|
19480
|
+
}
|
|
19481
|
+
function parseStartTimeoutMs(value) {
|
|
19482
|
+
if (value === void 0) return;
|
|
19483
|
+
const parsed = Number(value);
|
|
19484
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
19485
|
+
console.error("Invalid --start-timeout value. Provide milliseconds (e.g. 45000).");
|
|
19486
|
+
process.exit(1);
|
|
19487
|
+
}
|
|
19488
|
+
return Math.floor(parsed);
|
|
19489
|
+
}
|
|
19490
|
+
function resolveManagedServiceUiOverrides(params) {
|
|
19491
|
+
const uiOverrides = {
|
|
19492
|
+
enabled: true,
|
|
19493
|
+
host: params.forcedPublicHost,
|
|
19494
|
+
open: false
|
|
19495
|
+
};
|
|
19496
|
+
if (params.uiPort) uiOverrides.port = Number(params.uiPort);
|
|
19497
|
+
return uiOverrides;
|
|
19498
|
+
}
|
|
19499
|
+
//#endregion
|
|
19038
19500
|
//#region src/cli/commands/skills/marketplace-command-options.utils.ts
|
|
19039
19501
|
function buildMarketplacePublishOptions(options) {
|
|
19040
19502
|
const { apiBaseUrl, author, description, dir, homepage, meta, name, packageName, publishedAt, scope, slug, sourceRepo, summary, tag, token, updatedAt } = options;
|
|
@@ -20079,17 +20541,31 @@ var RestartCommands = class {
|
|
|
20079
20541
|
uiPort: opts.uiPort,
|
|
20080
20542
|
forcedPublicHost: this.deps.forcedPublicHost
|
|
20081
20543
|
});
|
|
20544
|
+
const targetUi = resolveUiConfig(loadConfig(), uiOverrides);
|
|
20082
20545
|
const state = managedServiceStateStore.read();
|
|
20083
20546
|
if (state && isProcessRunning(state.pid)) {
|
|
20084
20547
|
console.log(`Restarting ${APP_NAME}...`);
|
|
20085
20548
|
await this.deps.runtimeCommandService.stopService();
|
|
20086
20549
|
} else {
|
|
20550
|
+
const foregroundRuntime = localUiRuntimeStore.read();
|
|
20551
|
+
const foregroundMatchesTarget = Boolean(foregroundRuntime && isProcessRunning(foregroundRuntime.pid) && foregroundRuntime.uiPort === targetUi.port);
|
|
20552
|
+
if (foregroundRuntime && foregroundMatchesTarget) {
|
|
20553
|
+
if (!await this.restartForegroundRuntime(foregroundRuntime.pid)) return;
|
|
20554
|
+
await this.deps.startCommands.run(opts);
|
|
20555
|
+
return;
|
|
20556
|
+
}
|
|
20087
20557
|
if (state) {
|
|
20088
20558
|
managedServiceStateStore.clear();
|
|
20089
20559
|
console.log("Service state was stale and has been cleaned up.");
|
|
20090
20560
|
}
|
|
20091
20561
|
const unmanagedHealthyServiceMessage = await describeUnmanagedHealthyTargetMessage({ uiOverrides });
|
|
20092
20562
|
if (unmanagedHealthyServiceMessage) {
|
|
20563
|
+
const adoptedRuntimePid = this.resolveAdoptableForegroundRuntimePid(targetUi.port);
|
|
20564
|
+
if (adoptedRuntimePid) {
|
|
20565
|
+
if (!await this.restartForegroundRuntime(adoptedRuntimePid)) return;
|
|
20566
|
+
await this.deps.startCommands.run(opts);
|
|
20567
|
+
return;
|
|
20568
|
+
}
|
|
20093
20569
|
console.error(`Error: Cannot restart ${APP_NAME} because the target UI/API port is already served by a healthy unmanaged instance.`);
|
|
20094
20570
|
console.error(unmanagedHealthyServiceMessage);
|
|
20095
20571
|
return;
|
|
@@ -20098,6 +20574,40 @@ var RestartCommands = class {
|
|
|
20098
20574
|
}
|
|
20099
20575
|
await this.deps.startCommands.run(opts);
|
|
20100
20576
|
};
|
|
20577
|
+
restartForegroundRuntime = async (pid) => {
|
|
20578
|
+
console.log(`Restarting ${APP_NAME} foreground runtime (PID ${pid})...`);
|
|
20579
|
+
try {
|
|
20580
|
+
process.kill(pid, "SIGTERM");
|
|
20581
|
+
} catch (error) {
|
|
20582
|
+
console.error(`Failed to stop foreground runtime: ${String(error)}`);
|
|
20583
|
+
return false;
|
|
20584
|
+
}
|
|
20585
|
+
if (!await waitForExit(pid, 3e3)) {
|
|
20586
|
+
try {
|
|
20587
|
+
process.kill(pid, "SIGKILL");
|
|
20588
|
+
} catch (error) {
|
|
20589
|
+
console.error(`Failed to force stop foreground runtime: ${String(error)}`);
|
|
20590
|
+
return false;
|
|
20591
|
+
}
|
|
20592
|
+
if (!await waitForExit(pid, 2e3)) {
|
|
20593
|
+
console.error(`Failed to stop foreground runtime PID ${pid}.`);
|
|
20594
|
+
return false;
|
|
20595
|
+
}
|
|
20596
|
+
}
|
|
20597
|
+
localUiRuntimeStore.clearIfOwnedByProcess(pid);
|
|
20598
|
+
console.log(`✓ ${APP_NAME} foreground runtime stopped`);
|
|
20599
|
+
return true;
|
|
20600
|
+
};
|
|
20601
|
+
resolveAdoptableForegroundRuntimePid = (port) => {
|
|
20602
|
+
const listeningProcess = findListeningProcessByPort(port);
|
|
20603
|
+
if (!listeningProcess || !isProcessRunning(listeningProcess.pid)) return null;
|
|
20604
|
+
return this.isAdoptableNextclawRuntimeCommand(listeningProcess.command) ? listeningProcess.pid : null;
|
|
20605
|
+
};
|
|
20606
|
+
isAdoptableNextclawRuntimeCommand = (command) => {
|
|
20607
|
+
const normalized = command?.trim() ?? "";
|
|
20608
|
+
if (!normalized) return false;
|
|
20609
|
+
return /\bserve\b/.test(normalized) && (normalized.includes("/dist/cli/app/index.js") || normalized.includes("/src/cli/app/index.js") || normalized.includes("/runtime/dist/cli/app/index.js"));
|
|
20610
|
+
};
|
|
20101
20611
|
};
|
|
20102
20612
|
//#endregion
|
|
20103
20613
|
//#region src/cli/commands/serve/index.ts
|
|
@@ -20127,6 +20637,74 @@ var StopCommands = class {
|
|
|
20127
20637
|
};
|
|
20128
20638
|
};
|
|
20129
20639
|
//#endregion
|
|
20640
|
+
//#region src/cli/commands/companion/services/companion-process.service.ts
|
|
20641
|
+
var CompanionProcessService = class {
|
|
20642
|
+
constructor(runtimeService = companionRuntimeService) {
|
|
20643
|
+
this.runtimeService = runtimeService;
|
|
20644
|
+
}
|
|
20645
|
+
start = async (options = {}) => {
|
|
20646
|
+
const state = await this.runtimeService.ensureStarted({ baseUrl: this.resolveBaseUrl(options) });
|
|
20647
|
+
this.runtimeService.printStarted(state);
|
|
20648
|
+
};
|
|
20649
|
+
status = async (options = {}) => {
|
|
20650
|
+
this.runtimeService.printStatus(options);
|
|
20651
|
+
};
|
|
20652
|
+
stop = async (options = {}) => {
|
|
20653
|
+
const stopped = await this.runtimeService.ensureStopped(options);
|
|
20654
|
+
this.runtimeService.printStopped(stopped);
|
|
20655
|
+
};
|
|
20656
|
+
enable = async (options = {}) => {
|
|
20657
|
+
const nextConfig = await this.runtimeService.updateEnabled(true, options);
|
|
20658
|
+
this.printConfigEnabled(nextConfig, options.baseUrl);
|
|
20659
|
+
};
|
|
20660
|
+
disable = async (_options = {}) => {
|
|
20661
|
+
const nextConfig = await this.runtimeService.updateEnabled(false);
|
|
20662
|
+
console.log(nextConfig.companion.enabled ? "Companion remains enabled." : "Companion feature disabled. It will stay off until you enable it again.");
|
|
20663
|
+
};
|
|
20664
|
+
resolveBaseUrl = (options) => {
|
|
20665
|
+
const explicitBaseUrl = options.baseUrl?.trim();
|
|
20666
|
+
if (explicitBaseUrl) return explicitBaseUrl.replace(/\/+$/, "");
|
|
20667
|
+
const discoveredBaseUrl = this.runtimeService.resolveDiscoveredBaseUrl();
|
|
20668
|
+
if (discoveredBaseUrl) return discoveredBaseUrl;
|
|
20669
|
+
const runningState = this.runtimeService.getRunningState();
|
|
20670
|
+
if (runningState) return runningState.baseUrl;
|
|
20671
|
+
throw new Error("Cannot resolve NextClaw UI base URL. Start NextClaw first or pass --base-url.");
|
|
20672
|
+
};
|
|
20673
|
+
printConfigEnabled = (config, baseUrl) => {
|
|
20674
|
+
if (this.runtimeService.getRunningState()) {
|
|
20675
|
+
console.log("Companion feature enabled and companion started.");
|
|
20676
|
+
return;
|
|
20677
|
+
}
|
|
20678
|
+
if (baseUrl?.trim()) {
|
|
20679
|
+
console.log("Companion feature enabled.");
|
|
20680
|
+
return;
|
|
20681
|
+
}
|
|
20682
|
+
console.log(config.companion.enabled ? "Companion feature enabled. It will auto-start the next time a local NextClaw runtime is available." : "Companion feature is not enabled.");
|
|
20683
|
+
};
|
|
20684
|
+
};
|
|
20685
|
+
//#endregion
|
|
20686
|
+
//#region src/cli/commands/companion/index.ts
|
|
20687
|
+
var CompanionCommands = class {
|
|
20688
|
+
constructor(companionProcessService = new CompanionProcessService()) {
|
|
20689
|
+
this.companionProcessService = companionProcessService;
|
|
20690
|
+
}
|
|
20691
|
+
start = async (options = {}) => {
|
|
20692
|
+
await this.companionProcessService.start(options);
|
|
20693
|
+
};
|
|
20694
|
+
enable = async (options = {}) => {
|
|
20695
|
+
await this.companionProcessService.enable(options);
|
|
20696
|
+
};
|
|
20697
|
+
disable = async (options = {}) => {
|
|
20698
|
+
await this.companionProcessService.disable(options);
|
|
20699
|
+
};
|
|
20700
|
+
status = async (options = {}) => {
|
|
20701
|
+
await this.companionProcessService.status(options);
|
|
20702
|
+
};
|
|
20703
|
+
stop = async (options = {}) => {
|
|
20704
|
+
await this.companionProcessService.stop(options);
|
|
20705
|
+
};
|
|
20706
|
+
};
|
|
20707
|
+
//#endregion
|
|
20130
20708
|
//#region src/cli/app/runtime.ts
|
|
20131
20709
|
const LOGO = "🤖";
|
|
20132
20710
|
const FORCED_PUBLIC_UI_HOST = "0.0.0.0";
|
|
@@ -20158,6 +20736,7 @@ var CliRuntime = class {
|
|
|
20158
20736
|
restartCommands;
|
|
20159
20737
|
serveCommands;
|
|
20160
20738
|
stopCommands;
|
|
20739
|
+
companionCommands;
|
|
20161
20740
|
constructor(options = {}) {
|
|
20162
20741
|
logStartupTrace("cli.runtime.constructor.begin");
|
|
20163
20742
|
this.logo = options.logo ?? "🤖";
|
|
@@ -20190,6 +20769,7 @@ var CliRuntime = class {
|
|
|
20190
20769
|
forcedPublicHost: FORCED_PUBLIC_UI_HOST
|
|
20191
20770
|
}));
|
|
20192
20771
|
this.stopCommands = measureStartupSync("cli.runtime.stop_commands", () => new StopCommands({ runtimeCommandService: this.runtimeCommandService }));
|
|
20772
|
+
this.companionCommands = measureStartupSync("cli.runtime.companion_commands", () => new CompanionCommands());
|
|
20193
20773
|
this.serviceCommands = measureStartupSync("cli.runtime.service_commands", () => new ServiceCommands());
|
|
20194
20774
|
this.configCommands = measureStartupSync("cli.runtime.config_commands", () => new ConfigCommands({ requestRestart: (params) => this.requestRestart(params) }));
|
|
20195
20775
|
this.mcpCommands = measureStartupSync("cli.runtime.mcp_commands", () => new McpCommands());
|
|
@@ -20422,6 +21002,21 @@ var CliRuntime = class {
|
|
|
20422
21002
|
stop = async () => {
|
|
20423
21003
|
await this.stopCommands.run();
|
|
20424
21004
|
};
|
|
21005
|
+
companionStart = async (opts = {}) => {
|
|
21006
|
+
await this.companionCommands.start(opts);
|
|
21007
|
+
};
|
|
21008
|
+
companionEnable = async (opts = {}) => {
|
|
21009
|
+
await this.companionCommands.enable(opts);
|
|
21010
|
+
};
|
|
21011
|
+
companionDisable = async (opts = {}) => {
|
|
21012
|
+
await this.companionCommands.disable(opts);
|
|
21013
|
+
};
|
|
21014
|
+
companionStatus = async (opts = {}) => {
|
|
21015
|
+
await this.companionCommands.status(opts);
|
|
21016
|
+
};
|
|
21017
|
+
companionStop = async (opts = {}) => {
|
|
21018
|
+
await this.companionCommands.stop(opts);
|
|
21019
|
+
};
|
|
20425
21020
|
agent = async (opts) => {
|
|
20426
21021
|
const configPath = getConfigPath();
|
|
20427
21022
|
const config = resolveConfigSecrets(loadConfig(), { configPath });
|
|
@@ -20594,6 +21189,16 @@ function registerAgentsCommands(program, runtime) {
|
|
|
20594
21189
|
agents.command("remove <agentId>").description("Remove an agent").option("--json", "Output JSON", false).action(async (agentId, opts) => runtime.agentsRemove(agentId, opts));
|
|
20595
21190
|
}
|
|
20596
21191
|
//#endregion
|
|
21192
|
+
//#region src/cli/app/register-companion-commands.ts
|
|
21193
|
+
function registerCompanionCommands(program, runtime) {
|
|
21194
|
+
const companion = program.command("companion").description("Manage the standalone NextClaw companion shell");
|
|
21195
|
+
companion.command("start").description("Start the companion shell in the background").option("--base-url <url>", "Explicit NextClaw UI base URL").action(async (opts) => runtime.companionStart(opts));
|
|
21196
|
+
companion.command("enable").description("Enable the companion feature and start it when a local runtime is available").option("--base-url <url>", "Explicit NextClaw UI base URL").action(async (opts) => runtime.companionEnable(opts));
|
|
21197
|
+
companion.command("disable").description("Disable the companion feature and stop any running companion process").action(async (opts) => runtime.companionDisable(opts));
|
|
21198
|
+
companion.command("status").description("Show companion process status").option("--json", "Output JSON", false).action(async (opts) => runtime.companionStatus(opts));
|
|
21199
|
+
companion.command("stop").description("Stop the companion process").option("--force", "Force kill the companion process", false).action(async (opts) => runtime.companionStop(opts));
|
|
21200
|
+
}
|
|
21201
|
+
//#endregion
|
|
20597
21202
|
//#region src/cli/app/service-command-registration.service.ts
|
|
20598
21203
|
const registerServiceCommands = ({ program, getServiceCommands }) => {
|
|
20599
21204
|
const service = program.command("service").description("Manage host service integrations");
|
|
@@ -20649,6 +21254,7 @@ program.command("start").description(`Start the ${APP_NAME} gateway + UI in the
|
|
|
20649
21254
|
program.command("restart").description(`Restart the ${APP_NAME} background service`).option("--ui-port <port>", "UI port").option("--start-timeout <ms>", "Maximum wait time for startup readiness in milliseconds").option("--open", "Open browser after restart", false).action(async (opts) => runtime.restart(opts));
|
|
20650
21255
|
program.command("serve").description(`Run the ${APP_NAME} gateway + UI in the foreground`).option("--ui-port <port>", "UI port").option("--open", "Open browser after start", false).action(async (opts) => runtime.serve(opts));
|
|
20651
21256
|
program.command("stop").description(`Stop the ${APP_NAME} background service`).action(async () => runtime.stop());
|
|
21257
|
+
registerCompanionCommands(program, runtime);
|
|
20652
21258
|
registerServiceCommands({
|
|
20653
21259
|
program,
|
|
20654
21260
|
getServiceCommands
|
|
@@ -20699,6 +21305,6 @@ const logs = program.command("logs").description("Inspect local runtime logs");
|
|
|
20699
21305
|
logs.command("path").description("Show local log file paths").action(() => runtime.logsPath());
|
|
20700
21306
|
logs.command("tail").description("Show recent local log entries").option("--lines <n>", "Number of lines to show", "40").option("--crash", "Tail crash.log instead of service.log", false).action((opts) => runtime.logsTail(opts));
|
|
20701
21307
|
program.command("usage").description("Show observed LLM usage snapshots, history, and prompt cache stats").option("--history", "Show recent usage history", false).option("--stats", "Show aggregated usage stats from local history", false).option("--limit <n>", "Maximum number of history records to show", "10").option("--json", "Output JSON", false).action(async (opts) => llmUsageCommands.show(opts));
|
|
20702
|
-
program.parseAsync(process.argv);
|
|
21308
|
+
await program.parseAsync(process.argv);
|
|
20703
21309
|
//#endregion
|
|
20704
21310
|
export {};
|