nextclaw 0.18.12-beta.2 → 0.18.12-beta.3

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.
Files changed (91) hide show
  1. package/dist/cli/app/index.js +554 -87
  2. package/dist/cli/launcher/index.js +1 -1
  3. package/dist/{npm-runtime-update-state.store-DaF0iDY9.js → npm-runtime-update-state.store-CQ8tFzah.js} +1 -1
  4. package/package.json +17 -16
  5. package/ui-dist/assets/api-C412zuay.js +15 -0
  6. package/ui-dist/assets/app-manager-provider-Cm-KiZZG.js +1 -0
  7. package/ui-dist/assets/app-navigation.config-BORqHkbN.js +1 -0
  8. package/ui-dist/assets/{book-open-C5p9re7m.js → book-open-DgLqYpNY.js} +1 -1
  9. package/ui-dist/assets/{channels-list-page-CZAdoJ3s.js → channels-list-page-sISO_4Yj.js} +2 -2
  10. package/ui-dist/assets/{chat-a-_X0PmT.js → chat-ChCu7LQD.js} +8 -8
  11. package/ui-dist/assets/chat-page-BCaNZJGT.js +1 -0
  12. package/ui-dist/assets/{chunk-JZWAC4HX-CD1w8mri.js → chunk-JZWAC4HX-DvbcIVPf.js} +1 -1
  13. package/ui-dist/assets/{config-split-page-YB7xRSn7.js → config-split-page-BMRGuCJQ.js} +1 -1
  14. package/ui-dist/assets/{createLucideIcon-D48LQ7_3.js → createLucideIcon-BZkY6emz.js} +1 -1
  15. package/ui-dist/assets/desktop-update-config-BfJ5iSeY.js +1 -0
  16. package/ui-dist/assets/{dialog-BNdeIVqc.js → dialog-B-CXiFPZ.js} +1 -1
  17. package/ui-dist/assets/{dist-BjUfmI6n.js → dist-DYVfg3q5.js} +1 -1
  18. package/ui-dist/assets/{doc-browser-CX_BvO6R.js → doc-browser-BUlCkZo2.js} +1 -1
  19. package/ui-dist/assets/{doc-browser-CLdhFEsz.js → doc-browser-CzCV73NJ.js} +1 -1
  20. package/ui-dist/assets/doc-browser-Doh2541x.js +1 -0
  21. package/ui-dist/assets/{doc-browser-context-5mbkyvid.js → doc-browser-context-DfLHAWbG.js} +1 -1
  22. package/ui-dist/assets/{es2015-Db-PtAnL.js → es2015-BXroVnPi.js} +1 -1
  23. package/ui-dist/assets/{external-link-BwNyDSMe.js → external-link-Sw3ah_JD.js} +1 -1
  24. package/ui-dist/assets/{folder-BSLCUICp.js → folder-D7-VTnkz.js} +1 -1
  25. package/ui-dist/assets/{hash-DpL5u6Fu.js → hash-zajSTDXZ.js} +1 -1
  26. package/ui-dist/assets/i18n-C5Mibli1.js +1 -0
  27. package/ui-dist/assets/index-CqPDhosM.js +2 -0
  28. package/ui-dist/assets/{key-round-BNTFD7Jk.js → key-round-CnI1mc9F.js} +1 -1
  29. package/ui-dist/assets/loader-circle-B5i8oMMY.js +1 -0
  30. package/ui-dist/assets/{logo-badge-a-OsoTKw.js → logo-badge-BQgKnVtz.js} +1 -1
  31. package/ui-dist/assets/{logos--4c27B_Z.js → logos-CqVm0q0W.js} +1 -1
  32. package/ui-dist/assets/marketplace-page-C8uaWkfd.js +1 -0
  33. package/ui-dist/assets/{marketplace-page-PA3qcNzv.js → marketplace-page-C9oZ01rM.js} +2 -2
  34. package/ui-dist/assets/mcp-marketplace-page-DuEixgSs.js +40 -0
  35. package/ui-dist/assets/mcp-marketplace-page-rNqr6ZpD.js +1 -0
  36. package/ui-dist/assets/message-square-D6Z4NwpG.js +1 -0
  37. package/ui-dist/assets/{model-config-C3-m1Sua.js → model-config-mfhqEZBG.js} +1 -1
  38. package/ui-dist/assets/{notice-card-DE4jOEXF.js → notice-card-CozHB03G.js} +1 -1
  39. package/ui-dist/assets/play-D8WJLnJe.js +1 -0
  40. package/ui-dist/assets/plus-Di0KAkiO.js +1 -0
  41. package/ui-dist/assets/{popover-B6dtrFF5.js → popover-CPUPma-w.js} +1 -1
  42. package/ui-dist/assets/{provider-scoped-model-input-BkpcdlQB.js → provider-scoped-model-input-CL9sti2I.js} +1 -1
  43. package/ui-dist/assets/{providers-list-EzKC5s0y.js → providers-list-HPmL2akJ.js} +1 -1
  44. package/ui-dist/assets/refresh-ccw-Bii4w8aB.js +1 -0
  45. package/ui-dist/assets/refresh-cw-BxojR62w.js +1 -0
  46. package/ui-dist/assets/remote-oDlAdgVA.js +1 -0
  47. package/ui-dist/assets/{rotate-cw-CeTNbfMs.js → rotate-cw-1Xqa7LZ8.js} +1 -1
  48. package/ui-dist/assets/runtime-config-page-BCshTAAE.js +1 -0
  49. package/ui-dist/assets/{save-B8Rym7bl.js → save--BVI5wZX.js} +1 -1
  50. package/ui-dist/assets/{search-config-CNh9FS_N.js → search-config-Bcnk9VlL.js} +1 -1
  51. package/ui-dist/assets/{search-BUGoDsjN.js → search-vChioOoe.js} +1 -1
  52. package/ui-dist/assets/{secrets-config-Bau56GeM.js → secrets-config-Dde-5Y1w.js} +2 -2
  53. package/ui-dist/assets/{select-BuXrS7g3.js → select-BELPuXLW.js} +1 -1
  54. package/ui-dist/assets/{sessions-config-page-BDF04GaS.js → sessions-config-page-CG49_0Z6.js} +2 -2
  55. package/ui-dist/assets/{setting-row-CifMdz8g.js → setting-row-D5DtT6Ny.js} +1 -1
  56. package/ui-dist/assets/settings-CiRChctQ.js +1 -0
  57. package/ui-dist/assets/skeleton-CFQRIUzt.js +1 -0
  58. package/ui-dist/assets/{sparkles-Bo0DxmaB.js → sparkles-D1ZKWdm4.js} +1 -1
  59. package/ui-dist/assets/{status-dot-CS7yRd9c.js → status-dot-Dv_hiUVa.js} +1 -1
  60. package/ui-dist/assets/{tabs-custom-HBN-j_Kn.js → tabs-custom-CsACkVji.js} +1 -1
  61. package/ui-dist/assets/{tag-chip-BZSHb3cE.js → tag-chip-D9BWWgYg.js} +1 -1
  62. package/ui-dist/assets/theme-provider-DeBrTglS.js +1 -0
  63. package/ui-dist/assets/{tooltip-BMz2ki-V.js → tooltip-CI0rpNee.js} +1 -1
  64. package/ui-dist/assets/{trash-2-gWTb2oNS.js → trash-2-rY9ZteZX.js} +1 -1
  65. package/ui-dist/assets/use-config-CrWZ_TSF.js +1 -0
  66. package/ui-dist/assets/{use-confirm-dialog-DLVARUvb.js → use-confirm-dialog-hbynwWf2.js} +1 -1
  67. package/ui-dist/assets/{use-infinite-scroll-loader-BdGMvR3y.js → use-infinite-scroll-loader-Cw5qQr3-.js} +1 -1
  68. package/ui-dist/assets/{use-viewport-layout-DOqJ0LPT.js → use-viewport-layout-CWHVDC6z.js} +1 -1
  69. package/ui-dist/assets/x-DpTzXQcX.js +1 -0
  70. package/ui-dist/index.html +39 -35
  71. package/ui-dist/assets/api-BsY-53_V.js +0 -15
  72. package/ui-dist/assets/app-manager-provider-DTrWjVLB.js +0 -1
  73. package/ui-dist/assets/chat-page-BCypc4bi.js +0 -1
  74. package/ui-dist/assets/desktop-B9azAgEh.js +0 -2
  75. package/ui-dist/assets/desktop-update-config-Dm_cedSL.js +0 -1
  76. package/ui-dist/assets/doc-browser-eF2QWInq.js +0 -1
  77. package/ui-dist/assets/i18n-jGA3YQz4.js +0 -1
  78. package/ui-dist/assets/index-o_M3x0GR.js +0 -2
  79. package/ui-dist/assets/loader-circle-C3XJNZy7.js +0 -1
  80. package/ui-dist/assets/marketplace-page-DvmfPCAY.js +0 -1
  81. package/ui-dist/assets/mcp-marketplace-page-Dl8wdAtD.js +0 -1
  82. package/ui-dist/assets/mcp-marketplace-page-DukryaOq.js +0 -40
  83. package/ui-dist/assets/play-DGBx1fWI.js +0 -1
  84. package/ui-dist/assets/plus-CUuByV8j.js +0 -1
  85. package/ui-dist/assets/remote-Xzy42m-0.js +0 -1
  86. package/ui-dist/assets/runtime-config-page-DAMnv5Xp.js +0 -1
  87. package/ui-dist/assets/settings-COxdZHdu.js +0 -1
  88. package/ui-dist/assets/skeleton-DW5F83p8.js +0 -1
  89. package/ui-dist/assets/use-config-Ds7DyaYQ.js +0 -1
  90. package/ui-dist/assets/x-CxanI1fH.js +0 -1
  91. /package/ui-dist/assets/{config-hints-fDrYfl0l.js → config-hints-MogHYQ8G.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { _ as waitForExit, a as findExecutableOnPath, c as isProcessRunning, d as prompt, f as resolvePublicIp, g as resolveUiStaticDir, h as resolveUiConfig, i as NpmRuntimeBundleLayoutStore, l as openBrowser, m as resolveUiApiBase, n as NpmRuntimeBundleService, o as getPackageVersion$1, p as resolveServiceLogPath, r as compareNpmRuntimeVersions, s as isLoopbackHost, t as NpmRuntimeUpdateStateStore, u as printAgentResponse } from "../../npm-runtime-update-state.store-DaF0iDY9.js";
2
+ import { _ as waitForExit, a as findExecutableOnPath, c as isProcessRunning, d as prompt, f as resolvePublicIp, g as resolveUiStaticDir, h as resolveUiConfig, i as NpmRuntimeBundleLayoutStore, l as openBrowser, m as resolveUiApiBase, n as NpmRuntimeBundleService, o as getPackageVersion$1, p as resolveServiceLogPath, r as compareNpmRuntimeVersions, s as isLoopbackHost, t as NpmRuntimeUpdateStateStore, u as printAgentResponse } from "../../npm-runtime-update-state.store-CQ8tFzah.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";
@@ -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();
@@ -14004,7 +13980,7 @@ var ServiceMarketplaceInstaller = class {
14004
13980
  };
14005
13981
  //#endregion
14006
13982
  //#region src/cli/shared/utils/marketplace/cli-subcommand-launch.utils.ts
14007
- const require$2 = createRequire(import.meta.url);
13983
+ const require$3 = createRequire(import.meta.url);
14008
13984
  const TYPESCRIPT_EXTENSIONS$1 = new Set([
14009
13985
  ".ts",
14010
13986
  ".tsx",
@@ -14012,7 +13988,7 @@ const TYPESCRIPT_EXTENSIONS$1 = new Set([
14012
13988
  ".cts"
14013
13989
  ]);
14014
13990
  const isTypeScriptEntry = (entry) => TYPESCRIPT_EXTENSIONS$1.has(extname(entry).toLowerCase());
14015
- const resolveTsxCliEntry = () => require$2.resolve("tsx/cli");
13991
+ const resolveTsxCliEntry = () => require$3.resolve("tsx/cli");
14016
13992
  const resolveCliAppEntryFromImportMeta$1 = (importMetaUrl) => {
14017
13993
  const modulePath = fileURLToPath(importMetaUrl);
14018
13994
  const cliRootIndex = modulePath.replace(/\\/g, "/").lastIndexOf("/cli/");
@@ -15199,6 +15175,169 @@ function createRemoteAccessHost(params) {
15199
15175
  });
15200
15176
  }
15201
15177
  //#endregion
15178
+ //#region src/cli/shared/services/ui/npm-runtime-update-host.service.ts
15179
+ const INITIAL_DOWNLOAD_PROGRESS = {
15180
+ downloadedBytes: 0,
15181
+ totalBytes: null,
15182
+ percent: null
15183
+ };
15184
+ var NpmRuntimeUpdateHost = class {
15185
+ source = new NpmRuntimeUpdateSourceService();
15186
+ layout = new NpmRuntimeBundleLayoutStore();
15187
+ stateStore = new NpmRuntimeUpdateStateStore(this.layout.getStatePath());
15188
+ launcherVersion = getPackageVersion$1();
15189
+ bundleService = new NpmRuntimeBundleService({
15190
+ layout: this.layout,
15191
+ stateStore: this.stateStore,
15192
+ launcherVersion: this.launcherVersion
15193
+ });
15194
+ updateService = new NpmRuntimeUpdateService({
15195
+ layout: this.layout,
15196
+ bundleService: this.bundleService,
15197
+ launcherVersion: this.launcherVersion,
15198
+ bundlePublicKey: this.source.resolveBundlePublicKey() ?? void 0
15199
+ });
15200
+ snapshot;
15201
+ activeTask = null;
15202
+ automaticSyncStarted = false;
15203
+ constructor(deps) {
15204
+ this.deps = deps;
15205
+ this.snapshot = this.createManager().getSnapshot();
15206
+ this.startAutomaticSync();
15207
+ }
15208
+ getState = async () => {
15209
+ this.startAutomaticSync();
15210
+ return this.snapshot;
15211
+ };
15212
+ checkForUpdates = async () => {
15213
+ return this.startCheck({ autoDownload: false });
15214
+ };
15215
+ downloadUpdate = async () => {
15216
+ return this.startDownload();
15217
+ };
15218
+ applyDownloadedUpdate = async () => {
15219
+ if (this.activeTask) return this.snapshot;
15220
+ this.snapshot = {
15221
+ ...this.snapshot,
15222
+ status: "applying",
15223
+ progress: null,
15224
+ errorMessage: null
15225
+ };
15226
+ try {
15227
+ this.snapshot = this.createManager().applyDownloadedUpdate();
15228
+ await requestManagedServiceRestart(this.deps.requestRestart, {
15229
+ reason: "runtime update apply",
15230
+ uiPort: this.deps.uiConfig.port
15231
+ });
15232
+ return this.snapshot;
15233
+ } catch (error) {
15234
+ this.snapshot = this.toFailedSnapshot(error);
15235
+ throw error;
15236
+ }
15237
+ };
15238
+ updatePreferences = async (preferences) => {
15239
+ const nextState = this.stateStore.update((current) => ({
15240
+ ...current,
15241
+ updatePreferences: {
15242
+ ...current.updatePreferences,
15243
+ ...preferences
15244
+ }
15245
+ }));
15246
+ this.snapshot = this.createManager(nextState.channel).getSnapshot();
15247
+ if (nextState.updatePreferences.automaticChecks) this.startAutomaticSync({ force: true });
15248
+ return this.snapshot;
15249
+ };
15250
+ updateChannel = async (channel) => {
15251
+ const nextState = this.stateStore.update((current) => ({
15252
+ ...current,
15253
+ channel
15254
+ }));
15255
+ this.snapshot = this.createManager(nextState.channel).getSnapshot();
15256
+ if (nextState.updatePreferences.automaticChecks) return this.startCheck({ autoDownload: nextState.updatePreferences.autoDownload });
15257
+ return this.snapshot;
15258
+ };
15259
+ startAutomaticSync = (options = {}) => {
15260
+ if (this.activeTask) return;
15261
+ if (this.automaticSyncStarted && !options.force) return;
15262
+ this.automaticSyncStarted = true;
15263
+ const state = this.stateStore.read();
15264
+ if (!state.updatePreferences.automaticChecks || state.downloadedVersion) return;
15265
+ this.startCheck({ autoDownload: state.updatePreferences.autoDownload });
15266
+ };
15267
+ startCheck = async (options) => {
15268
+ if (this.activeTask) return this.snapshot;
15269
+ this.snapshot = {
15270
+ ...this.createManager().getSnapshot(),
15271
+ status: "checking",
15272
+ progress: null,
15273
+ errorMessage: null
15274
+ };
15275
+ this.activeTask = (async () => {
15276
+ try {
15277
+ const checkedSnapshot = await this.createManager().checkForUpdate();
15278
+ this.snapshot = checkedSnapshot;
15279
+ if (options.autoDownload && checkedSnapshot.status === "update-available") await this.runDownloadTask();
15280
+ } catch (error) {
15281
+ this.snapshot = this.toFailedSnapshot(error);
15282
+ } finally {
15283
+ this.activeTask = null;
15284
+ }
15285
+ })();
15286
+ return this.snapshot;
15287
+ };
15288
+ startDownload = async () => {
15289
+ if (this.activeTask) return this.snapshot;
15290
+ this.snapshot = {
15291
+ ...this.createManager().getSnapshot(),
15292
+ status: "downloading",
15293
+ progress: INITIAL_DOWNLOAD_PROGRESS,
15294
+ errorMessage: null
15295
+ };
15296
+ this.activeTask = (async () => {
15297
+ try {
15298
+ await this.runDownloadTask();
15299
+ } catch (error) {
15300
+ this.snapshot = this.toFailedSnapshot(error);
15301
+ } finally {
15302
+ this.activeTask = null;
15303
+ }
15304
+ })();
15305
+ return this.snapshot;
15306
+ };
15307
+ runDownloadTask = async () => {
15308
+ this.snapshot = await this.createManager().downloadUpdate((progress) => {
15309
+ this.snapshot = {
15310
+ ...this.snapshot,
15311
+ status: "downloading",
15312
+ progress,
15313
+ errorMessage: null
15314
+ };
15315
+ });
15316
+ };
15317
+ createManager = (channel = this.stateStore.read().channel) => {
15318
+ return new NpmRuntimeUpdateManager({
15319
+ layout: this.layout,
15320
+ stateStore: this.stateStore,
15321
+ bundleService: this.bundleService,
15322
+ updateService: this.updateService,
15323
+ resolveManifestUrl: (resolvedChannel) => this.source.resolveManifestUrl(resolvedChannel),
15324
+ launcherVersion: this.launcherVersion,
15325
+ channel
15326
+ });
15327
+ };
15328
+ toFailedSnapshot = (error) => {
15329
+ return {
15330
+ ...this.createManager().getSnapshot(),
15331
+ status: "failed",
15332
+ progress: null,
15333
+ errorMessage: error instanceof Error ? error.message : String(error ?? "Unknown error")
15334
+ };
15335
+ };
15336
+ };
15337
+ function createNpmRuntimeUpdateHost(params) {
15338
+ return new NpmRuntimeUpdateHost(params);
15339
+ }
15340
+ //#endregion
15202
15341
  //#region src/cli/shared/stores/pending-restart.store.ts
15203
15342
  const clonePendingRestartState = (state) => {
15204
15343
  if (!state) return null;
@@ -15320,12 +15459,17 @@ function createRuntimeControlHost(params) {
15320
15459
  //#endregion
15321
15460
  //#region src/cli/shared/services/ui/service-ui-hosts.service.ts
15322
15461
  function createServiceUiHosts(params) {
15462
+ const { requestRestart, serviceCommands, uiConfig } = params;
15323
15463
  return {
15324
15464
  remoteAccess: createRemoteAccessHost(params),
15325
15465
  runtimeControl: createRuntimeControlHost({
15326
- serviceCommands: params.serviceCommands,
15327
- requestRestart: params.requestRestart,
15328
- uiConfig: params.uiConfig
15466
+ serviceCommands,
15467
+ requestRestart,
15468
+ uiConfig
15469
+ }),
15470
+ runtimeUpdate: process.env.NEXTCLAW_DISABLE_RUNTIME_UPDATE_HOST === "1" ? void 0 : createNpmRuntimeUpdateHost({
15471
+ requestRestart,
15472
+ uiConfig
15329
15473
  })
15330
15474
  };
15331
15475
  }
@@ -15665,6 +15809,9 @@ var ConfigReloader = class {
15665
15809
  setReloadMcp(callback) {
15666
15810
  this.options.reloadMcp = callback;
15667
15811
  }
15812
+ setReloadCompanion(callback) {
15813
+ this.options.reloadCompanion = callback;
15814
+ }
15668
15815
  async applyReloadPlan(nextConfig) {
15669
15816
  const changedPaths = diffConfigPaths(this.currentConfig, nextConfig);
15670
15817
  if (!changedPaths.length) return;
@@ -15686,6 +15833,13 @@ var ConfigReloader = class {
15686
15833
  });
15687
15834
  console.log("Config reload: MCP servers reloaded.");
15688
15835
  }
15836
+ if (plan.reloadCompanion) {
15837
+ await this.reloadCompanion({
15838
+ config: nextConfig,
15839
+ changedPaths
15840
+ });
15841
+ console.log("Config reload: companion setting applied.");
15842
+ }
15689
15843
  if (plan.restartChannels || reloadPluginsResult?.restartChannels) {
15690
15844
  await this.reloadChannels(nextConfig, { start: true });
15691
15845
  console.log("Config reload: channels restarted.");
@@ -15781,6 +15935,10 @@ var ConfigReloader = class {
15781
15935
  if (!this.options.reloadMcp) return;
15782
15936
  await this.options.reloadMcp(params);
15783
15937
  }
15938
+ async reloadCompanion(params) {
15939
+ if (!this.options.reloadCompanion) return;
15940
+ await this.options.reloadCompanion(params);
15941
+ }
15784
15942
  };
15785
15943
  //#endregion
15786
15944
  //#region src/cli/shared/services/gateway/cron-job-handler.service.ts
@@ -16161,7 +16319,7 @@ function createSystemSessionUpdatedPublisher(params) {
16161
16319
  }
16162
16320
  async function startUiShell(params) {
16163
16321
  logStartupTrace("service.start_ui_shell.begin");
16164
- const { applyLiveConfigReload, configPath, cronService, getBootstrapStatus, getPluginChannelBindings, getPluginUiMetadata, initializeAgentHomeDirectory, marketplace, ncpSessionService, openBrowserWindow, productVersion, remoteAccess, runtimeControl, uiConfig, uiStaticDir } = params;
16322
+ const { applyLiveConfigReload, configPath, cronService, getBootstrapStatus, getPluginChannelBindings, getPluginUiMetadata, initializeAgentHomeDirectory, marketplace, ncpSessionService, openBrowserWindow, productVersion, remoteAccess, runtimeControl, runtimeUpdate, uiConfig, uiStaticDir } = params;
16165
16323
  if (!uiConfig.enabled) return null;
16166
16324
  let publishUiEvent = null;
16167
16325
  const deferredNcpAgent = createDeferredUiNcpAgent();
@@ -16177,6 +16335,7 @@ async function startUiShell(params) {
16177
16335
  marketplace,
16178
16336
  remoteAccess,
16179
16337
  runtimeControl,
16338
+ runtimeUpdate,
16180
16339
  getBootstrapStatus,
16181
16340
  getPluginChannelBindings,
16182
16341
  getPluginUiMetadata,
@@ -16962,6 +17121,165 @@ async function cleanupGatewayRuntime(params) {
16962
17121
  setPluginRuntimeBridge(null);
16963
17122
  }
16964
17123
  //#endregion
17124
+ //#region src/cli/shared/stores/companion-runtime.store.ts
17125
+ var CompanionRuntimeStore = class {
17126
+ get path() {
17127
+ return resolve(getDataDir(), "run", "companion.json");
17128
+ }
17129
+ read = () => {
17130
+ if (!existsSync(this.path)) return null;
17131
+ try {
17132
+ return JSON.parse(readFileSync(this.path, "utf-8"));
17133
+ } catch {
17134
+ return null;
17135
+ }
17136
+ };
17137
+ write = (state) => {
17138
+ mkdirSync(resolve(this.path, ".."), { recursive: true });
17139
+ writeFileSync(this.path, JSON.stringify(state, null, 2));
17140
+ };
17141
+ clear = () => {
17142
+ if (existsSync(this.path)) rmSync(this.path, { force: true });
17143
+ };
17144
+ };
17145
+ const companionRuntimeStore = new CompanionRuntimeStore();
17146
+ //#endregion
17147
+ //#region src/cli/shared/services/ui/companion-runtime.service.ts
17148
+ const require$2 = createRequire(import.meta.url);
17149
+ var CompanionRuntimeService = class {
17150
+ constructor(runtimeStore = companionRuntimeStore, uiDiscoveryService = localUiDiscoveryService) {
17151
+ this.runtimeStore = runtimeStore;
17152
+ this.uiDiscoveryService = uiDiscoveryService;
17153
+ }
17154
+ getRunningState = () => {
17155
+ const state = this.runtimeStore.read();
17156
+ if (!state) return null;
17157
+ if (!isProcessRunning(state.pid)) {
17158
+ this.runtimeStore.clear();
17159
+ return null;
17160
+ }
17161
+ return state;
17162
+ };
17163
+ resolveDiscoveredBaseUrl = () => {
17164
+ return this.uiDiscoveryService.resolveApiBase();
17165
+ };
17166
+ applyConfig = async (config) => {
17167
+ if (!config.companion.enabled) {
17168
+ await this.ensureStopped();
17169
+ return;
17170
+ }
17171
+ await this.ensureStarted({ baseUrl: this.uiDiscoveryService.resolveLocalOrigin(config) });
17172
+ };
17173
+ updateEnabled = async (enabled, options = {}) => {
17174
+ const config = loadConfig(getConfigPath());
17175
+ const next = {
17176
+ ...config,
17177
+ companion: {
17178
+ ...config.companion,
17179
+ enabled
17180
+ }
17181
+ };
17182
+ saveConfig(next, getConfigPath());
17183
+ if (enabled) {
17184
+ const explicitBaseUrl = options.baseUrl?.trim();
17185
+ if (explicitBaseUrl) {
17186
+ await this.ensureStarted({ baseUrl: explicitBaseUrl });
17187
+ return next;
17188
+ }
17189
+ const discoveredBaseUrl = this.uiDiscoveryService.resolveApiBase();
17190
+ if (discoveredBaseUrl) await this.ensureStarted({ baseUrl: discoveredBaseUrl });
17191
+ return next;
17192
+ }
17193
+ await this.ensureStopped();
17194
+ return next;
17195
+ };
17196
+ ensureStarted = async (options) => {
17197
+ const baseUrl = options.baseUrl.trim().replace(/\/+$/, "");
17198
+ const runningState = this.getRunningState();
17199
+ if (runningState?.baseUrl === baseUrl) return runningState;
17200
+ if (runningState) {
17201
+ this.killProcess(runningState.pid, false);
17202
+ this.runtimeStore.clear();
17203
+ }
17204
+ const launchSpec = this.resolveLaunchSpec();
17205
+ const child = spawn(launchSpec.command, [
17206
+ ...launchSpec.args,
17207
+ "--base-url",
17208
+ baseUrl
17209
+ ], {
17210
+ detached: true,
17211
+ stdio: "ignore",
17212
+ env: {
17213
+ ...process.env,
17214
+ NEXTCLAW_COMPANION_RUNTIME_STATE_PATH: this.runtimeStore.path
17215
+ }
17216
+ });
17217
+ child.unref();
17218
+ return await this.waitForRunningState(baseUrl, child.pid ?? -1);
17219
+ };
17220
+ ensureStopped = async (options = {}) => {
17221
+ const state = this.runtimeStore.read();
17222
+ if (!state) return false;
17223
+ if (!isProcessRunning(state.pid)) {
17224
+ this.runtimeStore.clear();
17225
+ return false;
17226
+ }
17227
+ this.killProcess(state.pid, options.force === true);
17228
+ this.runtimeStore.clear();
17229
+ return true;
17230
+ };
17231
+ printStatus = (options = {}) => {
17232
+ const runningState = this.getRunningState();
17233
+ const config = loadConfig(getConfigPath());
17234
+ const view = runningState ? {
17235
+ configuredEnabled: config.companion.enabled,
17236
+ running: true,
17237
+ ...runningState
17238
+ } : {
17239
+ configuredEnabled: config.companion.enabled,
17240
+ running: false
17241
+ };
17242
+ if (options.json) {
17243
+ console.log(JSON.stringify(view, null, 2));
17244
+ return;
17245
+ }
17246
+ if (!runningState) {
17247
+ console.log(config.companion.enabled ? "Companion is enabled in config but is not running." : "Companion is disabled and not running.");
17248
+ return;
17249
+ }
17250
+ console.log(`Companion is running (pid ${runningState.pid}) at ${runningState.baseUrl}. Configured enabled: ${config.companion.enabled ? "yes" : "no"}.`);
17251
+ };
17252
+ printStarted = (state) => {
17253
+ console.log(`Started ${APP_NAME} companion (pid ${state.pid}) using ${state.baseUrl}.`);
17254
+ };
17255
+ printStopped = (stopped) => {
17256
+ console.log(stopped ? "Stopped companion process." : "Companion is not running.");
17257
+ };
17258
+ killProcess = (pid, force) => {
17259
+ process.kill(pid, force ? "SIGKILL" : "SIGTERM");
17260
+ };
17261
+ resolveLaunchSpec = () => {
17262
+ const packageJsonPath = require$2.resolve("@nextclaw/companion/package.json");
17263
+ const packageRoot = dirname(packageJsonPath);
17264
+ const mainPath = resolve(packageRoot, "dist", "src", "main.js");
17265
+ if (!existsSync(mainPath)) throw new Error(`Companion app build is missing at ${mainPath}. Build @nextclaw/companion first.`);
17266
+ return {
17267
+ command: createRequire(packageJsonPath)("electron"),
17268
+ args: [packageRoot]
17269
+ };
17270
+ };
17271
+ waitForRunningState = async (baseUrl, fallbackPid) => {
17272
+ const timeoutAt = Date.now() + 5e3;
17273
+ while (Date.now() < timeoutAt) {
17274
+ const state = this.getRunningState();
17275
+ if (state?.baseUrl === baseUrl) return state;
17276
+ await new Promise((resolvePromise) => setTimeout(resolvePromise, 100));
17277
+ }
17278
+ 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.");
17279
+ };
17280
+ };
17281
+ const companionRuntimeService = new CompanionRuntimeService();
17282
+ //#endregion
16965
17283
  //#region src/cli/shared/services/runtime/runtime-command.service.ts
16966
17284
  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;
16967
17285
  function createSkillsLoader(workspace) {
@@ -17008,38 +17326,16 @@ var RuntimeCommandService = class {
17008
17326
  runCliSubcommand: (args) => this.runCliSubcommand(args),
17009
17327
  installBuiltinSkill: (slug, force) => this.installBuiltinMarketplaceSkill(slug, force)
17010
17328
  }).createInstaller();
17011
- const { remoteAccess, runtimeControl } = createServiceUiHosts({
17012
- serviceCommands: this,
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,
17329
+ const uiStartup = await this.startGatewayUiShell({
17330
+ shellContext,
17034
17331
  applyLiveConfigReload,
17035
- ncpSessionService: ncpSessionRealtimeBridge.sessionService,
17036
- initializeAgentHomeDirectory: this.deps.initializeAgentHomeDirectory
17037
- }));
17038
- finalizeLocalUiStartup({
17039
- uiStartup,
17040
- setUiEventPublisher: (publish) => ncpSessionRealtimeBridge.setUiEventPublisher(publish),
17041
- uiConfig: shellContext.uiConfig
17332
+ bootstrapStatus,
17333
+ marketplaceInstaller,
17334
+ ncpSessionRealtimeBridge,
17335
+ getRuntimeConfig,
17336
+ getRuntimeState: () => runtimeState
17042
17337
  });
17338
+ await companionRuntimeService.applyConfig(shellContext.config);
17043
17339
  bootstrapStatus.markShellReady();
17044
17340
  await setImmediate$1();
17045
17341
  const gateway = measureStartupSync("service.create_gateway_startup_context", () => createGatewayStartupContext({
@@ -17057,33 +17353,14 @@ var RuntimeCommandService = class {
17057
17353
  const loadGatewayConfig = () => resolveConfigSecrets$1(loadConfig$1(), { configPath: gateway.runtimeConfigPath });
17058
17354
  const gatewayRuntimeState = createGatewayRuntimeState(gateway);
17059
17355
  runtimeState = gatewayRuntimeState;
17060
- uiStartup?.publish({
17061
- type: "config.updated",
17062
- payload: { path: "channels" }
17356
+ gateway.reloader.setReloadCompanion(async ({ config: nextConfig }) => {
17357
+ await companionRuntimeService.applyConfig(nextConfig);
17063
17358
  });
17064
- uiStartup?.publish({
17065
- type: "config.updated",
17066
- payload: { path: "plugins" }
17067
- });
17068
- configureGatewayPluginRuntime({
17359
+ await this.hydrateGatewayRuntime({
17069
17360
  gateway,
17070
- state: gatewayRuntimeState,
17071
- getLiveUiNcpAgent: () => this.liveUiNcpAgent
17361
+ gatewayRuntimeState,
17362
+ uiStartup
17072
17363
  });
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
17364
  const deferredGatewayStartupHooks = createDeferredGatewayStartupHooks({
17088
17365
  uiStartup,
17089
17366
  gateway,
@@ -17125,14 +17402,84 @@ var RuntimeCommandService = class {
17125
17402
  this.applyLiveConfigReload = null;
17126
17403
  this.liveUiNcpAgent = null;
17127
17404
  },
17128
- clearRealtimeBridge: () => ncpSessionRealtimeBridge.clear(),
17405
+ clearRealtimeBridge: () => {
17406
+ ncpSessionRealtimeBridge.clear();
17407
+ },
17129
17408
  uiStartup,
17130
17409
  remoteModule: gateway.remoteModule,
17131
17410
  runtimeState
17132
17411
  })
17133
17412
  });
17413
+ await companionRuntimeService.ensureStopped();
17134
17414
  logStartupTrace("service.start_gateway.end");
17135
17415
  };
17416
+ startGatewayUiShell = async (params) => {
17417
+ const { applyLiveConfigReload, bootstrapStatus, getRuntimeConfig, getRuntimeState, marketplaceInstaller, ncpSessionRealtimeBridge, shellContext } = params;
17418
+ const { remoteAccess, runtimeControl, runtimeUpdate } = createServiceUiHosts({
17419
+ serviceCommands: this,
17420
+ requestRestart: this.deps.requestRestart,
17421
+ uiConfig: shellContext.uiConfig,
17422
+ remoteModule: shellContext.remoteModule
17423
+ });
17424
+ const uiStartup = await measureStartupAsync("service.start_ui_shell", async () => await startUiShell({
17425
+ uiConfig: shellContext.uiConfig,
17426
+ uiStaticDir: shellContext.uiStaticDir,
17427
+ cronService: shellContext.cron,
17428
+ getConfig: getRuntimeConfig,
17429
+ configPath: getConfigPath$1(),
17430
+ productVersion: getPackageVersion$1(),
17431
+ getPluginChannelBindings: () => getRuntimeState()?.pluginChannelBindings ?? [],
17432
+ getPluginUiMetadata: () => getRuntimeState()?.pluginUiMetadata ?? [],
17433
+ marketplace: {
17434
+ apiBaseUrl: process.env.NEXTCLAW_MARKETPLACE_API_BASE,
17435
+ installer: marketplaceInstaller
17436
+ },
17437
+ remoteAccess,
17438
+ runtimeControl,
17439
+ runtimeUpdate,
17440
+ getBootstrapStatus: () => bootstrapStatus.getStatus(),
17441
+ openBrowserWindow: shellContext.uiConfig.open,
17442
+ applyLiveConfigReload,
17443
+ ncpSessionService: ncpSessionRealtimeBridge.sessionService,
17444
+ initializeAgentHomeDirectory: this.deps.initializeAgentHomeDirectory
17445
+ }));
17446
+ finalizeLocalUiStartup({
17447
+ uiStartup,
17448
+ setUiEventPublisher: (publish) => ncpSessionRealtimeBridge.setUiEventPublisher(publish),
17449
+ uiConfig: shellContext.uiConfig
17450
+ });
17451
+ return uiStartup;
17452
+ };
17453
+ hydrateGatewayRuntime = async (params) => {
17454
+ const { gateway, gatewayRuntimeState, uiStartup } = params;
17455
+ uiStartup?.publish({
17456
+ type: "config.updated",
17457
+ payload: { path: "channels" }
17458
+ });
17459
+ uiStartup?.publish({
17460
+ type: "config.updated",
17461
+ payload: { path: "plugins" }
17462
+ });
17463
+ configureGatewayPluginRuntime({
17464
+ gateway,
17465
+ state: gatewayRuntimeState,
17466
+ getLiveUiNcpAgent: () => this.liveUiNcpAgent
17467
+ });
17468
+ console.log("✓ Capability hydration: scheduled in background");
17469
+ await measureStartupAsync("service.start_gateway_support_services", async () => await startGatewayRuntimeSupport({
17470
+ cronJobs: gateway.cron.status().jobs,
17471
+ remoteModule: gateway.remoteModule,
17472
+ watchConfigFile: () => watchServiceConfigFile({
17473
+ configPath: resolve(getConfigPath$1()),
17474
+ watcherRegistry: this.fileWatchers,
17475
+ scheduleReload: (reason) => gateway.reloader.scheduleReload(reason)
17476
+ }),
17477
+ startCron: () => gateway.cron.start(),
17478
+ cronStorePath: resolve(join(NextclawCore.getDataDir(), "cron", "jobs.json")),
17479
+ reloadCronStore: () => gateway.cron.reloadFromStore(),
17480
+ watcherRegistry: this.fileWatchers
17481
+ }));
17482
+ };
17136
17483
  normalizeOptionalString = (value) => {
17137
17484
  if (typeof value !== "string") return;
17138
17485
  return value.trim() || void 0;
@@ -19035,6 +19382,30 @@ var RuntimeRestartRequestService = class {
19035
19382
  };
19036
19383
  };
19037
19384
  //#endregion
19385
+ //#region src/cli/shared/utils/runtime-helpers.ts
19386
+ function resolveSkillsInstallWorkdir(params) {
19387
+ if (params.explicitWorkdir) return expandHome(params.explicitWorkdir);
19388
+ return getWorkspacePath(params.configuredWorkspace);
19389
+ }
19390
+ function parseStartTimeoutMs(value) {
19391
+ if (value === void 0) return;
19392
+ const parsed = Number(value);
19393
+ if (!Number.isFinite(parsed) || parsed <= 0) {
19394
+ console.error("Invalid --start-timeout value. Provide milliseconds (e.g. 45000).");
19395
+ process.exit(1);
19396
+ }
19397
+ return Math.floor(parsed);
19398
+ }
19399
+ function resolveManagedServiceUiOverrides(params) {
19400
+ const uiOverrides = {
19401
+ enabled: true,
19402
+ host: params.forcedPublicHost,
19403
+ open: false
19404
+ };
19405
+ if (params.uiPort) uiOverrides.port = Number(params.uiPort);
19406
+ return uiOverrides;
19407
+ }
19408
+ //#endregion
19038
19409
  //#region src/cli/commands/skills/marketplace-command-options.utils.ts
19039
19410
  function buildMarketplacePublishOptions(options) {
19040
19411
  const { apiBaseUrl, author, description, dir, homepage, meta, name, packageName, publishedAt, scope, slug, sourceRepo, summary, tag, token, updatedAt } = options;
@@ -20127,6 +20498,74 @@ var StopCommands = class {
20127
20498
  };
20128
20499
  };
20129
20500
  //#endregion
20501
+ //#region src/cli/commands/companion/services/companion-process.service.ts
20502
+ var CompanionProcessService = class {
20503
+ constructor(runtimeService = companionRuntimeService) {
20504
+ this.runtimeService = runtimeService;
20505
+ }
20506
+ start = async (options = {}) => {
20507
+ const state = await this.runtimeService.ensureStarted({ baseUrl: this.resolveBaseUrl(options) });
20508
+ this.runtimeService.printStarted(state);
20509
+ };
20510
+ status = async (options = {}) => {
20511
+ this.runtimeService.printStatus(options);
20512
+ };
20513
+ stop = async (options = {}) => {
20514
+ const stopped = await this.runtimeService.ensureStopped(options);
20515
+ this.runtimeService.printStopped(stopped);
20516
+ };
20517
+ enable = async (options = {}) => {
20518
+ const nextConfig = await this.runtimeService.updateEnabled(true, options);
20519
+ this.printConfigEnabled(nextConfig, options.baseUrl);
20520
+ };
20521
+ disable = async (_options = {}) => {
20522
+ const nextConfig = await this.runtimeService.updateEnabled(false);
20523
+ console.log(nextConfig.companion.enabled ? "Companion remains enabled." : "Companion feature disabled. It will stay off until you enable it again.");
20524
+ };
20525
+ resolveBaseUrl = (options) => {
20526
+ const explicitBaseUrl = options.baseUrl?.trim();
20527
+ if (explicitBaseUrl) return explicitBaseUrl.replace(/\/+$/, "");
20528
+ const discoveredBaseUrl = this.runtimeService.resolveDiscoveredBaseUrl();
20529
+ if (discoveredBaseUrl) return discoveredBaseUrl;
20530
+ const runningState = this.runtimeService.getRunningState();
20531
+ if (runningState) return runningState.baseUrl;
20532
+ throw new Error("Cannot resolve NextClaw UI base URL. Start NextClaw first or pass --base-url.");
20533
+ };
20534
+ printConfigEnabled = (config, baseUrl) => {
20535
+ if (this.runtimeService.getRunningState()) {
20536
+ console.log("Companion feature enabled and companion started.");
20537
+ return;
20538
+ }
20539
+ if (baseUrl?.trim()) {
20540
+ console.log("Companion feature enabled.");
20541
+ return;
20542
+ }
20543
+ 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.");
20544
+ };
20545
+ };
20546
+ //#endregion
20547
+ //#region src/cli/commands/companion/index.ts
20548
+ var CompanionCommands = class {
20549
+ constructor(companionProcessService = new CompanionProcessService()) {
20550
+ this.companionProcessService = companionProcessService;
20551
+ }
20552
+ start = async (options = {}) => {
20553
+ await this.companionProcessService.start(options);
20554
+ };
20555
+ enable = async (options = {}) => {
20556
+ await this.companionProcessService.enable(options);
20557
+ };
20558
+ disable = async (options = {}) => {
20559
+ await this.companionProcessService.disable(options);
20560
+ };
20561
+ status = async (options = {}) => {
20562
+ await this.companionProcessService.status(options);
20563
+ };
20564
+ stop = async (options = {}) => {
20565
+ await this.companionProcessService.stop(options);
20566
+ };
20567
+ };
20568
+ //#endregion
20130
20569
  //#region src/cli/app/runtime.ts
20131
20570
  const LOGO = "🤖";
20132
20571
  const FORCED_PUBLIC_UI_HOST = "0.0.0.0";
@@ -20158,6 +20597,7 @@ var CliRuntime = class {
20158
20597
  restartCommands;
20159
20598
  serveCommands;
20160
20599
  stopCommands;
20600
+ companionCommands;
20161
20601
  constructor(options = {}) {
20162
20602
  logStartupTrace("cli.runtime.constructor.begin");
20163
20603
  this.logo = options.logo ?? "🤖";
@@ -20190,6 +20630,7 @@ var CliRuntime = class {
20190
20630
  forcedPublicHost: FORCED_PUBLIC_UI_HOST
20191
20631
  }));
20192
20632
  this.stopCommands = measureStartupSync("cli.runtime.stop_commands", () => new StopCommands({ runtimeCommandService: this.runtimeCommandService }));
20633
+ this.companionCommands = measureStartupSync("cli.runtime.companion_commands", () => new CompanionCommands());
20193
20634
  this.serviceCommands = measureStartupSync("cli.runtime.service_commands", () => new ServiceCommands());
20194
20635
  this.configCommands = measureStartupSync("cli.runtime.config_commands", () => new ConfigCommands({ requestRestart: (params) => this.requestRestart(params) }));
20195
20636
  this.mcpCommands = measureStartupSync("cli.runtime.mcp_commands", () => new McpCommands());
@@ -20422,6 +20863,21 @@ var CliRuntime = class {
20422
20863
  stop = async () => {
20423
20864
  await this.stopCommands.run();
20424
20865
  };
20866
+ companionStart = async (opts = {}) => {
20867
+ await this.companionCommands.start(opts);
20868
+ };
20869
+ companionEnable = async (opts = {}) => {
20870
+ await this.companionCommands.enable(opts);
20871
+ };
20872
+ companionDisable = async (opts = {}) => {
20873
+ await this.companionCommands.disable(opts);
20874
+ };
20875
+ companionStatus = async (opts = {}) => {
20876
+ await this.companionCommands.status(opts);
20877
+ };
20878
+ companionStop = async (opts = {}) => {
20879
+ await this.companionCommands.stop(opts);
20880
+ };
20425
20881
  agent = async (opts) => {
20426
20882
  const configPath = getConfigPath();
20427
20883
  const config = resolveConfigSecrets(loadConfig(), { configPath });
@@ -20594,6 +21050,16 @@ function registerAgentsCommands(program, runtime) {
20594
21050
  agents.command("remove <agentId>").description("Remove an agent").option("--json", "Output JSON", false).action(async (agentId, opts) => runtime.agentsRemove(agentId, opts));
20595
21051
  }
20596
21052
  //#endregion
21053
+ //#region src/cli/app/register-companion-commands.ts
21054
+ function registerCompanionCommands(program, runtime) {
21055
+ const companion = program.command("companion").description("Manage the standalone NextClaw companion shell");
21056
+ 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));
21057
+ 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));
21058
+ companion.command("disable").description("Disable the companion feature and stop any running companion process").action(async (opts) => runtime.companionDisable(opts));
21059
+ companion.command("status").description("Show companion process status").option("--json", "Output JSON", false).action(async (opts) => runtime.companionStatus(opts));
21060
+ companion.command("stop").description("Stop the companion process").option("--force", "Force kill the companion process", false).action(async (opts) => runtime.companionStop(opts));
21061
+ }
21062
+ //#endregion
20597
21063
  //#region src/cli/app/service-command-registration.service.ts
20598
21064
  const registerServiceCommands = ({ program, getServiceCommands }) => {
20599
21065
  const service = program.command("service").description("Manage host service integrations");
@@ -20649,6 +21115,7 @@ program.command("start").description(`Start the ${APP_NAME} gateway + UI in the
20649
21115
  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
21116
  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
21117
  program.command("stop").description(`Stop the ${APP_NAME} background service`).action(async () => runtime.stop());
21118
+ registerCompanionCommands(program, runtime);
20652
21119
  registerServiceCommands({
20653
21120
  program,
20654
21121
  getServiceCommands
@@ -20699,6 +21166,6 @@ const logs = program.command("logs").description("Inspect local runtime logs");
20699
21166
  logs.command("path").description("Show local log file paths").action(() => runtime.logsPath());
20700
21167
  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
21168
  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);
21169
+ await program.parseAsync(process.argv);
20703
21170
  //#endregion
20704
21171
  export {};