@nextclaw/service 0.1.6 → 0.1.8

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 (80) hide show
  1. package/dist/cli/commands/agent/agent-runtime.utils.js +2 -2
  2. package/dist/cli/commands/agent/cli-agent-runner.utils.js +2 -2
  3. package/dist/cli/commands/agent/index.js +1 -1
  4. package/dist/cli/commands/config/services/config-commands.service.js +1 -1
  5. package/dist/cli/commands/cron/services/cron-commands.service.js +2 -2
  6. package/dist/cli/commands/cron/services/cron-local.service.d.ts +1 -1
  7. package/dist/cli/commands/cron/services/cron-local.service.js +1 -1
  8. package/dist/cli/commands/restart/index.js +2 -2
  9. package/dist/cli/commands/skills/marketplace.metadata.js +1 -1
  10. package/dist/cli/commands/skills/marketplace.service.js +2 -2
  11. package/dist/cli/commands/skills/skills-query.service.js +1 -1
  12. package/dist/commands/channel/index.js +2 -2
  13. package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.js +3 -3
  14. package/dist/commands/plugin/development-source/{first-party-plugin-load-paths.d.ts → first-party-plugin-load-paths.utils.d.ts} +1 -1
  15. package/dist/commands/plugin/development-source/{first-party-plugin-load-paths.js → first-party-plugin-load-paths.utils.js} +3 -3
  16. package/dist/commands/plugin/index.d.ts +1 -1
  17. package/dist/commands/plugin/index.js +5 -5
  18. package/dist/commands/plugin/plugin-command-utils.d.ts +1 -1
  19. package/dist/commands/plugin/plugin-mutation-actions.js +2 -2
  20. package/dist/commands/plugin/{plugin-registry-loader.d.ts → plugin-registry-loader.utils.d.ts} +1 -1
  21. package/dist/commands/plugin/{plugin-registry-loader.js → plugin-registry-loader.utils.js} +2 -2
  22. package/dist/commands/remote/services/remote-service-control.service.js +1 -1
  23. package/dist/commands/remote/utils/remote-runtime-support.utils.js +1 -1
  24. package/dist/commands/service/services/autostart/host-autostart-runtime.service.js +2 -2
  25. package/dist/commands/service/services/autostart/linux-systemd-autostart.service.js +2 -2
  26. package/dist/commands/service/services/autostart/macos-launch-agent-autostart.service.js +2 -2
  27. package/dist/commands/service/services/autostart/windows-task-autostart.service.js +2 -2
  28. package/dist/index.d.ts +2 -2
  29. package/dist/launcher/npm-runtime-bundle-layout.store.js +1 -1
  30. package/dist/launcher/npm-runtime-bundle.service.js +1 -1
  31. package/dist/launcher/npm-runtime-launcher.service.js +5 -5
  32. package/dist/launcher/npm-runtime-update-command.service.js +2 -2
  33. package/dist/launcher/npm-runtime-update-source.service.js +2 -2
  34. package/dist/launcher/npm-runtime-update-state.store.js +1 -1
  35. package/dist/launcher/npm-runtime-update.manager.js +1 -1
  36. package/dist/launcher/npm-runtime-update.service.js +2 -2
  37. package/dist/service-runtime.service.d.ts +0 -2
  38. package/dist/service-runtime.service.js +31 -33
  39. package/dist/shared/controllers/gateway.controller.js +1 -1
  40. package/dist/shared/services/extensions/extension-lifecycle.service.js +1 -1
  41. package/dist/shared/services/extensions/service-extension-runtime.service.d.ts +1 -1
  42. package/dist/shared/services/extensions/service-extension-runtime.service.js +7 -6
  43. package/dist/shared/services/gateway/gateway-restart-wake.service.js +2 -1
  44. package/dist/shared/services/gateway/managers/gateway-plugin.manager.js +17 -3
  45. package/dist/shared/services/gateway/managers/gateway-remote.manager.d.ts +2 -2
  46. package/dist/shared/services/gateway/managers/gateway-remote.manager.js +1 -1
  47. package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts +1 -1
  48. package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js +10 -10
  49. package/dist/shared/services/gateway/service-bootstrap-status.service.d.ts +1 -1
  50. package/dist/shared/services/gateway/service-startup-support.service.d.ts +1 -1
  51. package/dist/shared/services/marketplace/service-marketplace-installer.service.js +2 -2
  52. package/dist/shared/services/plugin/utils/plugin-runtime-bridge.utils.js +1 -1
  53. package/dist/shared/services/restart/restart-sentinel.service.js +1 -1
  54. package/dist/shared/services/runtime/runtime-command.service.d.ts +3 -0
  55. package/dist/shared/services/runtime/runtime-command.service.js +27 -3
  56. package/dist/shared/services/runtime/service-managed-startup.service.d.ts +4 -28
  57. package/dist/shared/services/runtime/service-managed-startup.service.js +61 -65
  58. package/dist/shared/services/runtime/utils/managed-service-routing.utils.d.ts +30 -0
  59. package/dist/shared/services/runtime/utils/managed-service-routing.utils.js +62 -0
  60. package/dist/shared/services/runtime/utils/service-remote-runtime.utils.js +2 -2
  61. package/dist/shared/services/session/service-deferred-ncp-agent.service.d.ts +1 -1
  62. package/dist/shared/services/ui/companion-runtime.service.d.ts +2 -0
  63. package/dist/shared/services/ui/companion-runtime.service.js +40 -8
  64. package/dist/shared/services/ui/local-ui-discovery.service.js +1 -1
  65. package/dist/shared/services/ui/npm-runtime-update-host.service.js +2 -2
  66. package/dist/shared/services/ui/runtime-control-host.service.js +1 -1
  67. package/dist/shared/services/ui/service-remote-access.service.js +1 -1
  68. package/dist/shared/services/workspace/workspace-manager.service.js +3 -3
  69. package/dist/shared/stores/companion-runtime.store.js +1 -1
  70. package/dist/shared/stores/local-ui-runtime.store.js +1 -1
  71. package/dist/shared/stores/managed-service-state.store.js +1 -1
  72. package/dist/shared/types/cli.types.d.ts +1 -14
  73. package/dist/shared/utils/cli.utils.js +2 -2
  74. package/dist/shared/utils/marketplace/cli-subcommand-launch.utils.js +1 -1
  75. package/dist/shared/utils/package/package-manifest.utils.js +2 -2
  76. package/package.json +21 -19
  77. package/dist/cli/commands/companion/index.d.ts +0 -15
  78. package/dist/cli/commands/companion/index.js +0 -24
  79. package/dist/cli/commands/companion/services/companion-process.service.d.ts +0 -17
  80. package/dist/cli/commands/companion/services/companion-process.service.js +0 -49
@@ -1,5 +1,6 @@
1
1
  import { consumeRestartSentinel, formatRestartSentinelMessage, parseSessionKey } from "../restart/restart-sentinel.service.js";
2
- import { resolveSessionRouteCandidate } from "../runtime/service-managed-startup.service.js";
2
+ import { resolveSessionRouteCandidate } from "../runtime/utils/managed-service-routing.utils.js";
3
+ import "../runtime/service-managed-startup.service.js";
3
4
  import { parseAgentScopedSessionKey } from "@nextclaw/core";
4
5
  //#region src/shared/services/gateway/gateway-restart-wake.service.ts
5
6
  function normalizeOptionalString(value) {
@@ -1,18 +1,32 @@
1
1
  import { toExtensionRegistry } from "../../../../commands/plugin/plugin-extension-registry.js";
2
- import { createEmptyPluginRegistry, discoverPluginRegistryStatus, loadPluginRegistryProgressively } from "../../../../commands/plugin/plugin-registry-loader.js";
2
+ import { createEmptyPluginRegistry, discoverPluginRegistryStatus, loadPluginRegistryProgressively } from "../../../../commands/plugin/plugin-registry-loader.utils.js";
3
3
  import { logPluginDiagnostics } from "../../../../commands/plugin/index.js";
4
4
  import { shouldRestartChannelsForPluginReload } from "../../../../commands/plugin/plugin-reload.js";
5
5
  import { logPluginGatewayDiagnostics, pluginGatewayLogger } from "../service-startup-support.service.js";
6
6
  import { getWorkspacePath } from "@nextclaw/core";
7
- import { eventKeys } from "@nextclaw/shared";
8
7
  import { getPluginChannelBindings, getPluginUiMetadataFromRegistry, toPluginConfigView } from "@nextclaw/openclaw-compat";
8
+ import { eventKeys } from "@nextclaw/shared";
9
9
  //#region src/shared/services/gateway/managers/gateway-plugin.manager.ts
10
+ function toManifestChannelRegistrations(channelBindings) {
11
+ return channelBindings.map((binding) => ({
12
+ extensionId: binding.pluginId,
13
+ channel: binding.channel,
14
+ source: "extension-manifest"
15
+ }));
16
+ }
10
17
  function buildSnapshot(registry, extensionContributions) {
11
18
  const extensionChannelIds = new Set(extensionContributions.channelBindings.map((binding) => binding.channelId));
12
19
  const extensionPluginIds = new Set(extensionContributions.uiMetadata.map((metadata) => metadata.id));
20
+ const registryExtensionRegistry = toExtensionRegistry(registry);
13
21
  return {
14
22
  registry,
15
- extensionRegistry: toExtensionRegistry(registry),
23
+ extensionRegistry: {
24
+ ...registryExtensionRegistry,
25
+ channels: [...registryExtensionRegistry.channels.filter((registration) => {
26
+ const channelId = registration.channel.id?.trim();
27
+ return !channelId || !extensionChannelIds.has(channelId);
28
+ }), ...toManifestChannelRegistrations(extensionContributions.channelBindings)]
29
+ },
16
30
  channelBindings: [...getPluginChannelBindings(registry).filter((binding) => !extensionChannelIds.has(binding.channelId)), ...extensionContributions.channelBindings],
17
31
  uiMetadata: [...getPluginUiMetadataFromRegistry(registry).filter((metadata) => !extensionPluginIds.has(metadata.id)), ...extensionContributions.uiMetadata]
18
32
  };
@@ -1,9 +1,9 @@
1
1
  import { createManagedRemoteModuleForUi } from "../../runtime/utils/service-remote-runtime.utils.js";
2
2
  import { GatewayRuntimeDeps } from "../nextclaw-gateway-runtime.service.js";
3
3
  import { Config } from "@nextclaw/core";
4
- import { UiRemoteAccessHost } from "@nextclaw/server";
5
- import { RemoteRuntimeState } from "@nextclaw/remote";
6
4
  import { ConfigManager } from "@nextclaw/kernel";
5
+ import { RemoteRuntimeState } from "@nextclaw/remote";
6
+ import { UiRemoteAccessHost } from "@nextclaw/server";
7
7
 
8
8
  //#region src/shared/services/gateway/managers/gateway-remote.manager.d.ts
9
9
  type RemoteServiceModule$1 = ReturnType<typeof createManagedRemoteModuleForUi>;
@@ -1,5 +1,5 @@
1
- import { createRemoteAccessHost } from "../../ui/service-remote-access.service.js";
2
1
  import { createManagedRemoteModuleForUi } from "../../runtime/utils/service-remote-runtime.utils.js";
2
+ import { createRemoteAccessHost } from "../../ui/service-remote-access.service.js";
3
3
  //#region src/shared/services/gateway/managers/gateway-remote.manager.ts
4
4
  var GatewayRemoteManager = class {
5
5
  remoteModule;
@@ -9,9 +9,9 @@ import { ServiceBootstrapStatusStore } from "./service-bootstrap-status.service.
9
9
  import { ServiceFileWatcherRegistry } from "./service-startup-support.service.js";
10
10
  import { ServiceExtensionRuntime } from "../extensions/service-extension-runtime.service.js";
11
11
  import * as NextclawCore from "@nextclaw/core";
12
+ import { AgentRuntimeHandle, AutomationManager, ConfigManager, LlmProviderManager, NextclawKernel } from "@nextclaw/kernel";
12
13
  import { MarketplaceApiConfig, UiNcpAgent, UiRuntimeControlHost, UiRuntimeUpdateHost } from "@nextclaw/server";
13
14
  import { EventBus, Ingress } from "@nextclaw/shared";
14
- import { AgentRuntimeHandle, AutomationManager, ConfigManager, LlmProviderManager, NextclawKernel } from "@nextclaw/kernel";
15
15
 
16
16
  //#region src/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts
17
17
  type Config$1 = NextclawCore.Config;
@@ -1,31 +1,31 @@
1
+ import { logStartupTrace, measureStartupAsync, measureStartupSync } from "../../utils/startup-trace.js";
1
2
  import { openBrowser, resolveUiConfig, resolveUiStaticDir } from "../../utils/cli.utils.js";
2
3
  import { NextclawDistributionService } from "../runtime/nextclaw-distribution.service.js";
3
- import { localUiRuntimeStore } from "../../stores/local-ui-runtime.store.js";
4
4
  import { managedServiceStateStore } from "../../stores/managed-service-state.store.js";
5
- import { logStartupTrace, measureStartupAsync, measureStartupSync } from "../../utils/startup-trace.js";
6
- import { GatewayControllerImpl } from "../../controllers/gateway.controller.js";
7
- import { companionRuntimeService } from "../ui/companion-runtime.service.js";
8
- import { createRuntimeControlHost } from "../ui/runtime-control-host.service.js";
9
- import { NpmRuntimeUpdateHost } from "../ui/npm-runtime-update-host.service.js";
10
- import { ServiceMarketplaceInstaller } from "../marketplace/service-marketplace-installer.service.js";
11
5
  import { resolveChannelConfigView } from "../../../commands/channel/channel-config-view.js";
6
+ import { localUiRuntimeStore } from "../../stores/local-ui-runtime.store.js";
7
+ import { GatewayControllerImpl } from "../../controllers/gateway.controller.js";
12
8
  import { ServiceExtensionRuntime } from "../extensions/service-extension-runtime.service.js";
13
9
  import { ServiceFileWatcherRegistry, markLocalUiRuntimeIfStarted, startGatewayRuntimeSupport, watchServiceConfigFile } from "./service-startup-support.service.js";
14
10
  import { GatewayPluginManager } from "./managers/gateway-plugin.manager.js";
15
11
  import { GatewayRemoteManager } from "./managers/gateway-remote.manager.js";
16
12
  import { GatewayRestartWakeService } from "./gateway-restart-wake.service.js";
17
13
  import { createCronJobHandler } from "./cron-job-handler.service.js";
14
+ import { companionRuntimeService } from "../ui/companion-runtime.service.js";
18
15
  import { handleGatewayDeferredStartupError } from "./utils/gateway-runtime-lifecycle.utils.js";
19
16
  import { NextclawApp } from "./nextclaw-app.service.js";
20
17
  import { ServiceBootstrapStatusStore } from "./service-bootstrap-status.service.js";
21
18
  import { createDeferredUiNcpAgent } from "../session/service-deferred-ncp-agent.service.js";
22
19
  import { installPluginRuntimeBridge } from "../plugin/utils/plugin-runtime-bridge.utils.js";
23
20
  import { wrapStartChannelsWithDevPluginHotReload } from "../plugin/utils/plugin-dev-hot-reload.utils.js";
24
- import { resolve } from "node:path";
21
+ import { ServiceMarketplaceInstaller } from "../marketplace/service-marketplace-installer.service.js";
22
+ import { NpmRuntimeUpdateHost } from "../ui/npm-runtime-update-host.service.js";
23
+ import { createRuntimeControlHost } from "../ui/runtime-control-host.service.js";
25
24
  import * as NextclawCore from "@nextclaw/core";
26
- import { startUiServer } from "@nextclaw/server";
27
- import { setPluginRuntimeBridge } from "@nextclaw/openclaw-compat";
28
25
  import { NextclawKernel, runGatewayInboundLoop } from "@nextclaw/kernel";
26
+ import { setPluginRuntimeBridge } from "@nextclaw/openclaw-compat";
27
+ import { resolve } from "node:path";
28
+ import { startUiServer } from "@nextclaw/server";
29
29
  import { setImmediate } from "node:timers/promises";
30
30
  //#region src/shared/services/gateway/nextclaw-gateway-runtime.service.ts
31
31
  const { getConfigPath: getConfigPath$1, getDataDir: getDataDir$1, getWorkspacePath: getWorkspacePath$1, saveConfig: saveConfig$1 } = NextclawCore;
@@ -1,5 +1,5 @@
1
- import { BootstrapRemoteState, BootstrapStatusView } from "@nextclaw/server";
2
1
  import { RemoteRuntimeState } from "@nextclaw/remote";
2
+ import { BootstrapRemoteState, BootstrapStatusView } from "@nextclaw/server";
3
3
 
4
4
  //#region src/shared/services/gateway/service-bootstrap-status.service.d.ts
5
5
  declare class ServiceBootstrapStatusStore {
@@ -1,7 +1,7 @@
1
1
  import { Config } from "@nextclaw/core";
2
+ import { AutomationManager } from "@nextclaw/kernel";
2
3
  import { RemoteServiceModule } from "@nextclaw/remote";
3
4
  import { PluginDiagnostic } from "@nextclaw/openclaw-compat";
4
- import { AutomationManager } from "@nextclaw/kernel";
5
5
  import { FSWatcher } from "chokidar";
6
6
 
7
7
  //#region src/shared/services/gateway/service-startup-support.service.d.ts
@@ -1,9 +1,9 @@
1
- import { buildMarketplaceSkillInstallArgs, pickUserFacingCommandSummary } from "../../utils/marketplace/service-marketplace-helpers.utils.js";
2
1
  import { disablePluginMutation, enablePluginMutation, installPluginMutation, uninstallPluginMutation } from "../../../commands/plugin/plugin-mutation-actions.js";
2
+ import { buildMarketplaceSkillInstallArgs, pickUserFacingCommandSummary } from "../../utils/marketplace/service-marketplace-helpers.utils.js";
3
3
  import { ServiceMcpMarketplaceOps } from "./service-mcp-marketplace-ops.js";
4
- import { join } from "node:path";
5
4
  import { getWorkspacePath, loadConfig } from "@nextclaw/core";
6
5
  import { existsSync, rmSync } from "node:fs";
6
+ import { join } from "node:path";
7
7
  //#region src/shared/services/marketplace/service-marketplace-installer.service.ts
8
8
  var ServiceMarketplaceInstaller = class {
9
9
  constructor(deps) {
@@ -1,6 +1,6 @@
1
1
  import { loadConfig, saveConfig } from "@nextclaw/core";
2
- import { setPluginRuntimeBridge } from "@nextclaw/openclaw-compat";
3
2
  import { dispatchPromptOverNcp } from "@nextclaw/kernel";
3
+ import { setPluginRuntimeBridge } from "@nextclaw/openclaw-compat";
4
4
  //#region src/shared/services/plugin/utils/plugin-runtime-bridge.utils.ts
5
5
  function installPluginRuntimeBridge(gateway) {
6
6
  setPluginRuntimeBridge({
@@ -1,6 +1,6 @@
1
- import { resolve } from "node:path";
2
1
  import { getDataDir } from "@nextclaw/core";
3
2
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
4
  //#region src/shared/services/restart/restart-sentinel.service.ts
5
5
  const RESTART_SENTINEL_FILENAME = "restart-sentinel.json";
6
6
  const PENDING_SYSTEM_EVENTS_KEY = "pending_system_events";
@@ -9,6 +9,8 @@ type Config$1 = NextclawCore.Config;
9
9
  declare class RuntimeCommandService {
10
10
  private deps;
11
11
  private loggingInstalled;
12
+ private processExitLoggingInstalled;
13
+ private readonly runtimeLogger;
12
14
  private readonly managedServiceCommandService;
13
15
  constructor(deps: {
14
16
  requestRestart: (params: RequestRestartParams) => Promise<void>;
@@ -29,6 +31,7 @@ declare class RuntimeCommandService {
29
31
  private runCliSubcommand;
30
32
  private runCommand;
31
33
  private ensureRuntimeLoggingInstalled;
34
+ private installProcessExitLogging;
32
35
  private checkUiPortPreflight;
33
36
  private printPublicUiUrls;
34
37
  private printServiceControlHints;
@@ -1,17 +1,19 @@
1
1
  import { isLoopbackHost, resolvePublicIp, resolveUiStaticDir } from "../../utils/cli.utils.js";
2
2
  import { NextclawDistributionService } from "./nextclaw-distribution.service.js";
3
- import { describeUnmanagedHealthyTargetMessage, inspectUiTarget } from "../../utils/service-port-probe.utils.js";
4
- import { buildMarketplaceSkillInstallArgs, pickUserFacingCommandSummary } from "../../utils/marketplace/service-marketplace-helpers.utils.js";
5
3
  import { resolveCliSubcommandEntry } from "../../utils/marketplace/cli-subcommand-launch.utils.js";
4
+ import { describeUnmanagedHealthyTargetMessage, inspectUiTarget } from "../../utils/service-port-probe.utils.js";
6
5
  import { ManagedServiceCommandService } from "./service-managed-startup.service.js";
6
+ import { buildMarketplaceSkillInstallArgs, pickUserFacingCommandSummary } from "../../utils/marketplace/service-marketplace-helpers.utils.js";
7
7
  import { NextclawGatewayRuntime } from "../gateway/nextclaw-gateway-runtime.service.js";
8
8
  import { createSkillsLoader } from "./utils/skills-loader.utils.js";
9
- import { spawn } from "node:child_process";
10
9
  import * as NextclawCore from "@nextclaw/core";
10
+ import { spawn } from "node:child_process";
11
11
  //#region src/shared/services/runtime/runtime-command.service.ts
12
12
  const { getWorkspacePath: getWorkspacePath$1, loadConfig: loadConfig$1 } = NextclawCore;
13
13
  var RuntimeCommandService = class {
14
14
  loggingInstalled = false;
15
+ processExitLoggingInstalled = false;
16
+ runtimeLogger = NextclawCore.getAppLogger("service.runtime");
15
17
  managedServiceCommandService = new ManagedServiceCommandService({
16
18
  startGateway: async (options) => await this.startGateway(options),
17
19
  printPublicUiUrls: async (host, port) => await this.printPublicUiUrls(host, port),
@@ -24,6 +26,12 @@ var RuntimeCommandService = class {
24
26
  }
25
27
  startGateway = async (options = {}) => {
26
28
  this.ensureRuntimeLoggingInstalled();
29
+ this.installProcessExitLogging();
30
+ this.runtimeLogger.info("runtime.process.started", {
31
+ runtimeKind: "serve-process",
32
+ pid: process.pid,
33
+ source: "RuntimeCommandService.startGateway"
34
+ });
27
35
  await new NextclawGatewayRuntime({
28
36
  requestRestart: this.deps.requestRestart,
29
37
  initializeAgentHomeDirectory: this.deps.initializeAgentHomeDirectory,
@@ -32,6 +40,11 @@ var RuntimeCommandService = class {
32
40
  runCliSubcommand: this.runCliSubcommand,
33
41
  installBuiltinMarketplaceSkill: this.installBuiltinMarketplaceSkill
34
42
  }, { ...options }).start();
43
+ this.runtimeLogger.info("runtime.process.ready", {
44
+ runtimeKind: "serve-process",
45
+ pid: process.pid,
46
+ source: "RuntimeCommandService.startGateway"
47
+ });
35
48
  };
36
49
  startService = async (options) => {
37
50
  await this.managedServiceCommandService.startService(options);
@@ -115,6 +128,17 @@ var RuntimeCommandService = class {
115
128
  });
116
129
  this.loggingInstalled = true;
117
130
  };
131
+ installProcessExitLogging = () => {
132
+ if (this.processExitLoggingInstalled) return;
133
+ this.processExitLoggingInstalled = true;
134
+ process.once("exit", (code) => {
135
+ this.runtimeLogger.warn("runtime.process.exited", {
136
+ runtimeKind: "serve-process",
137
+ pid: process.pid,
138
+ code
139
+ });
140
+ });
141
+ };
118
142
  checkUiPortPreflight = async (params) => {
119
143
  const target = await inspectUiTarget(params);
120
144
  if (target.state === "available") return {
@@ -1,7 +1,6 @@
1
- import { ManagedServiceState } from "../../stores/managed-service-state.store.js";
2
- import { localUiRuntimeStore } from "../../stores/local-ui-runtime.store.js";
3
- import { spawn } from "node:child_process";
1
+ import { ManagedServiceSnapshot, resolveManagedServiceReadySnapshot, resolveManagedServiceUiBinding, resolveSessionRouteCandidate } from "./utils/managed-service-routing.utils.js";
4
2
  import * as NextclawCore from "@nextclaw/core";
3
+ import { spawn } from "node:child_process";
5
4
 
6
5
  //#region src/shared/services/runtime/service-managed-startup.service.d.ts
7
6
  type Config$1 = NextclawCore.Config;
@@ -10,30 +9,6 @@ type StartServiceOptions = {
10
9
  open: boolean;
11
10
  startupTimeoutMs?: number;
12
11
  };
13
- type ManagedServiceSnapshot = {
14
- pid: number;
15
- uiUrl: string;
16
- apiUrl: string;
17
- uiHost: string;
18
- uiPort: number;
19
- logPath: string;
20
- };
21
- declare function resolveManagedServiceReadySnapshot(params: {
22
- snapshot: ManagedServiceSnapshot;
23
- readLocalUiRuntimeState?: typeof localUiRuntimeStore.read;
24
- isProcessRunningFn?: (pid: number) => boolean;
25
- }): ManagedServiceSnapshot;
26
- declare function resolveManagedServiceUiBinding(state: ManagedServiceState): {
27
- host: string;
28
- port: number;
29
- };
30
- declare function resolveSessionRouteCandidate(params: {
31
- session: unknown;
32
- normalizeOptionalString: (value: unknown) => string | undefined;
33
- }): {
34
- key: string;
35
- updatedAt: number;
36
- } | null;
37
12
  declare function spawnManagedService(params: {
38
13
  appName: string;
39
14
  config: NextclawCore.Config;
@@ -109,6 +84,7 @@ declare class ManagedServiceCommandService {
109
84
  private readonly deps;
110
85
  private readonly loggingRuntime;
111
86
  private readonly serviceLogger;
87
+ private readonly startupLogger;
112
88
  constructor(deps: {
113
89
  startGateway: (options: {
114
90
  uiOverrides: Partial<Config$1["ui"]>;
@@ -144,4 +120,4 @@ declare class ManagedServiceCommandService {
144
120
  private printStartupFailureDiagnostics;
145
121
  }
146
122
  //#endregion
147
- export { ManagedServiceCommandService, ManagedServiceSnapshot, StartServiceOptions, reportManagedServiceStart, resolveManagedServiceReadySnapshot, resolveManagedServiceUiBinding, resolveSessionRouteCandidate, spawnManagedService, waitForManagedServiceReadiness };
123
+ export { ManagedServiceCommandService, StartServiceOptions, reportManagedServiceStart, resolveManagedServiceReadySnapshot, resolveManagedServiceUiBinding, resolveSessionRouteCandidate, spawnManagedService, waitForManagedServiceReadiness };
@@ -1,71 +1,19 @@
1
+ import { createTopLevelNextclawCommandEnv } from "../../utils/top-level-nextclaw-command-env.utils.js";
1
2
  import { isProcessRunning, openBrowser, resolveServiceLogPath, resolveUiApiBase, resolveUiConfig, waitForExit } from "../../utils/cli.utils.js";
2
- import { localUiRuntimeStore } from "../../stores/local-ui-runtime.store.js";
3
3
  import { managedServiceStateStore } from "../../stores/managed-service-state.store.js";
4
- import { probeHealthEndpoint } from "../../utils/service-port-probe.utils.js";
4
+ import { localUiRuntimeStore } from "../../stores/local-ui-runtime.store.js";
5
5
  import { resolveCliSubcommandLaunch } from "../../utils/marketplace/cli-subcommand-launch.utils.js";
6
- import { createTopLevelNextclawCommandEnv } from "../../utils/top-level-nextclaw-command-env.utils.js";
7
6
  import { writeInitialManagedServiceState, writeReadyManagedServiceState } from "./utils/service-remote-runtime.utils.js";
8
- import { spawn } from "node:child_process";
9
- import { dirname } from "node:path";
7
+ import { resolveManagedServiceReadySnapshot, resolveManagedServiceUiBinding, resolveSessionRouteCandidate } from "./utils/managed-service-routing.utils.js";
8
+ import { probeHealthEndpoint } from "../../utils/service-port-probe.utils.js";
10
9
  import * as NextclawCore from "@nextclaw/core";
11
10
  import { FileLogSink } from "@nextclaw/core";
12
11
  import { mkdirSync } from "node:fs";
12
+ import { dirname } from "node:path";
13
+ import { spawn } from "node:child_process";
13
14
  //#region src/shared/services/runtime/service-managed-startup.service.ts
14
15
  const { APP_NAME: APP_NAME$1, loadConfig: loadConfig$1 } = NextclawCore;
15
- function resolveManagedServiceReadySnapshot(params) {
16
- const { snapshot, readLocalUiRuntimeState, isProcessRunningFn: providedIsProcessRunningFn } = params;
17
- const localUiRuntimeState = (readLocalUiRuntimeState ?? localUiRuntimeStore.read)();
18
- const isProcessRunningFn = providedIsProcessRunningFn ?? isProcessRunning;
19
- if (!localUiRuntimeState || typeof localUiRuntimeState.pid !== "number" || !Number.isFinite(localUiRuntimeState.pid) || localUiRuntimeState.uiPort !== snapshot.uiPort || !isProcessRunningFn(localUiRuntimeState.pid)) return snapshot;
20
- return {
21
- ...snapshot,
22
- pid: localUiRuntimeState.pid,
23
- uiUrl: localUiRuntimeState.uiUrl,
24
- apiUrl: localUiRuntimeState.apiUrl,
25
- uiHost: localUiRuntimeState.uiHost ?? snapshot.uiHost,
26
- uiPort: localUiRuntimeState.uiPort ?? snapshot.uiPort
27
- };
28
- }
29
- function toObjectRecord(value) {
30
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
31
- return value;
32
- }
33
- function hasSessionRoutingMetadata(params) {
34
- const context = toObjectRecord(params.metadata.last_delivery_context) ?? {};
35
- const hasPrimaryRoute = Boolean(params.normalizeOptionalString(context.channel)) && Boolean(params.normalizeOptionalString(context.chatId));
36
- const hasFallbackRoute = Boolean(params.normalizeOptionalString(params.metadata.last_channel)) && Boolean(params.normalizeOptionalString(params.metadata.last_to));
37
- return hasPrimaryRoute || hasFallbackRoute;
38
- }
39
- function resolveManagedServiceUiBinding(state) {
40
- try {
41
- const parsed = new URL(state.uiUrl);
42
- const parsedPort = Number(parsed.port || 80);
43
- return {
44
- host: state.uiHost ?? parsed.hostname,
45
- port: Number.isFinite(parsedPort) ? parsedPort : state.uiPort ?? 55667
46
- };
47
- } catch {
48
- return {
49
- host: state.uiHost ?? "127.0.0.1",
50
- port: state.uiPort ?? 55667
51
- };
52
- }
53
- }
54
- function resolveSessionRouteCandidate(params) {
55
- const sessionRecord = toObjectRecord(params.session);
56
- const key = params.normalizeOptionalString(sessionRecord?.key);
57
- if (!key || key.startsWith("cli:")) return null;
58
- if (!hasSessionRoutingMetadata({
59
- metadata: toObjectRecord(sessionRecord?.metadata) ?? {},
60
- normalizeOptionalString: params.normalizeOptionalString
61
- })) return null;
62
- const updatedAtRaw = params.normalizeOptionalString(sessionRecord?.updated_at);
63
- const updatedAt = updatedAtRaw ? Date.parse(updatedAtRaw) : NaN;
64
- return {
65
- key,
66
- updatedAt: Number.isFinite(updatedAt) ? updatedAt : 0
67
- };
68
- }
16
+ const serviceStartupLogger = NextclawCore.getAppLogger("service.startup");
69
17
  function spawnManagedService(params) {
70
18
  const { appName, config, uiConfig, uiUrl, apiUrl, healthUrl, startupTimeoutMs, resolveStartupTimeoutMs, appendStartupStage, printStartupFailureDiagnostics, resolveServiceLogPath } = params;
71
19
  const logPath = resolveServiceLogPath();
@@ -119,6 +67,22 @@ function spawnManagedService(params) {
119
67
  readinessTimeoutMs,
120
68
  snapshot
121
69
  });
70
+ serviceStartupLogger.info("runtime.process.started", {
71
+ runtimeKind: "managed-service",
72
+ childPid: child.pid,
73
+ uiUrl,
74
+ apiUrl,
75
+ uiHost: uiConfig.host,
76
+ uiPort: uiConfig.port,
77
+ entrypoint: `${cliLaunch.command} ${childArgs.join(" ")}`
78
+ });
79
+ serviceStartupLogger.info("service_state.written", {
80
+ runtimeKind: "managed-service",
81
+ childPid: child.pid,
82
+ statePath: managedServiceStateStore.path,
83
+ uiUrl,
84
+ apiUrl
85
+ });
122
86
  return {
123
87
  child,
124
88
  logPath,
@@ -162,6 +126,7 @@ async function reportManagedServiceStart(params) {
162
126
  var ManagedServiceCommandService = class {
163
127
  loggingRuntime = NextclawCore.getLoggingRuntime();
164
128
  serviceLogger = this.loggingRuntime.getLogger("service");
129
+ startupLogger = this.serviceLogger.child("startup");
165
130
  constructor(deps) {
166
131
  this.deps = deps;
167
132
  }
@@ -237,6 +202,13 @@ var ManagedServiceCommandService = class {
237
202
  return;
238
203
  }
239
204
  console.log(`Stopping ${APP_NAME$1} (PID ${state.pid})...`);
205
+ this.serviceLogger.info("runtime.process.stop_requested", {
206
+ runtimeKind: "managed-service",
207
+ pid: state.pid,
208
+ reason: "nextclaw-stop-command",
209
+ uiUrl: state.uiUrl,
210
+ apiUrl: state.apiUrl
211
+ });
240
212
  try {
241
213
  process.kill(state.pid, "SIGTERM");
242
214
  } catch (error) {
@@ -244,6 +216,14 @@ var ManagedServiceCommandService = class {
244
216
  return;
245
217
  }
246
218
  if (!await waitForExit(state.pid, 3e3)) {
219
+ this.serviceLogger.warn("runtime.process.stop_requested", {
220
+ runtimeKind: "managed-service",
221
+ pid: state.pid,
222
+ reason: "nextclaw-stop-command-force",
223
+ signal: "SIGKILL",
224
+ uiUrl: state.uiUrl,
225
+ apiUrl: state.apiUrl
226
+ });
247
227
  try {
248
228
  process.kill(state.pid, "SIGKILL");
249
229
  } catch (error) {
@@ -254,6 +234,13 @@ var ManagedServiceCommandService = class {
254
234
  }
255
235
  managedServiceStateStore.clear();
256
236
  localUiRuntimeStore.clearIfOwnedByProcess(state.pid);
237
+ this.serviceLogger.info("service_state.cleared", {
238
+ runtimeKind: "managed-service",
239
+ pid: state.pid,
240
+ statePath: managedServiceStateStore.path,
241
+ uiUrl: state.uiUrl,
242
+ apiUrl: state.apiUrl
243
+ });
257
244
  console.log(`✓ ${APP_NAME$1} stopped`);
258
245
  };
259
246
  handleExistingManagedService = async (params) => {
@@ -348,13 +335,22 @@ var ManagedServiceCommandService = class {
348
335
  }
349
336
  startup.child.unref();
350
337
  const readySnapshot = resolveManagedServiceReadySnapshot({ snapshot: startup.snapshot });
338
+ const state = writeReadyManagedServiceState({
339
+ readinessTimeoutMs: startup.readinessTimeoutMs,
340
+ readiness,
341
+ snapshot: readySnapshot
342
+ });
343
+ this.startupLogger.info("runtime.process.ready", {
344
+ runtimeKind: "managed-service",
345
+ pid: state.pid,
346
+ uiUrl: state.uiUrl,
347
+ apiUrl: state.apiUrl,
348
+ startupState: state.startupState,
349
+ readinessTimeoutMs: startup.readinessTimeoutMs
350
+ });
351
351
  await reportManagedServiceStart({
352
352
  appName: APP_NAME$1,
353
- state: writeReadyManagedServiceState({
354
- readinessTimeoutMs: startup.readinessTimeoutMs,
355
- readiness,
356
- snapshot: readySnapshot
357
- }),
353
+ state,
358
354
  uiConfig,
359
355
  uiUrl,
360
356
  apiUrl,
@@ -401,7 +397,7 @@ var ManagedServiceCommandService = class {
401
397
  };
402
398
  appendStartupStage = (logPath, message) => {
403
399
  try {
404
- this.serviceLogger.child("startup").info(message, { logPath });
400
+ this.startupLogger.info(message, { logPath });
405
401
  } catch (error) {
406
402
  const detail = error instanceof Error ? error.message : String(error);
407
403
  console.error(`Warning: failed to write startup diagnostics log (${logPath}): ${detail}`);
@@ -0,0 +1,30 @@
1
+ import { ManagedServiceState } from "../../../stores/managed-service-state.store.js";
2
+ import { localUiRuntimeStore } from "../../../stores/local-ui-runtime.store.js";
3
+
4
+ //#region src/shared/services/runtime/utils/managed-service-routing.utils.d.ts
5
+ type ManagedServiceSnapshot = {
6
+ pid: number;
7
+ uiUrl: string;
8
+ apiUrl: string;
9
+ uiHost: string;
10
+ uiPort: number;
11
+ logPath: string;
12
+ };
13
+ declare function resolveManagedServiceReadySnapshot(params: {
14
+ snapshot: ManagedServiceSnapshot;
15
+ readLocalUiRuntimeState?: typeof localUiRuntimeStore.read;
16
+ isProcessRunningFn?: (pid: number) => boolean;
17
+ }): ManagedServiceSnapshot;
18
+ declare function resolveManagedServiceUiBinding(state: ManagedServiceState): {
19
+ host: string;
20
+ port: number;
21
+ };
22
+ declare function resolveSessionRouteCandidate(params: {
23
+ session: unknown;
24
+ normalizeOptionalString: (value: unknown) => string | undefined;
25
+ }): {
26
+ key: string;
27
+ updatedAt: number;
28
+ } | null;
29
+ //#endregion
30
+ export { ManagedServiceSnapshot, resolveManagedServiceReadySnapshot, resolveManagedServiceUiBinding, resolveSessionRouteCandidate };
@@ -0,0 +1,62 @@
1
+ import { isProcessRunning } from "../../../utils/cli.utils.js";
2
+ import "../../../stores/managed-service-state.store.js";
3
+ import { localUiRuntimeStore } from "../../../stores/local-ui-runtime.store.js";
4
+ //#region src/shared/services/runtime/utils/managed-service-routing.utils.ts
5
+ function resolveManagedServiceReadySnapshot(params) {
6
+ const { snapshot, readLocalUiRuntimeState, isProcessRunningFn: providedIsProcessRunningFn } = params;
7
+ const localUiRuntimeState = (readLocalUiRuntimeState ?? localUiRuntimeStore.read)();
8
+ const isProcessRunningFn = providedIsProcessRunningFn ?? isProcessRunning;
9
+ if (!localUiRuntimeState || typeof localUiRuntimeState.pid !== "number" || !Number.isFinite(localUiRuntimeState.pid) || localUiRuntimeState.uiPort !== snapshot.uiPort || !isProcessRunningFn(localUiRuntimeState.pid)) return snapshot;
10
+ return {
11
+ ...snapshot,
12
+ pid: localUiRuntimeState.pid,
13
+ uiUrl: localUiRuntimeState.uiUrl,
14
+ apiUrl: localUiRuntimeState.apiUrl,
15
+ uiHost: localUiRuntimeState.uiHost ?? snapshot.uiHost,
16
+ uiPort: localUiRuntimeState.uiPort ?? snapshot.uiPort
17
+ };
18
+ }
19
+ function toObjectRecord(value) {
20
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
21
+ return value;
22
+ }
23
+ function hasSessionRoutingMetadata(params) {
24
+ const { metadata, normalizeOptionalString } = params;
25
+ const context = toObjectRecord(metadata.last_delivery_context) ?? {};
26
+ const hasPrimaryRoute = Boolean(normalizeOptionalString(context.channel)) && Boolean(normalizeOptionalString(context.chatId));
27
+ const hasFallbackRoute = Boolean(normalizeOptionalString(metadata.last_channel)) && Boolean(normalizeOptionalString(metadata.last_to));
28
+ return hasPrimaryRoute || hasFallbackRoute;
29
+ }
30
+ function resolveManagedServiceUiBinding(state) {
31
+ try {
32
+ const parsed = new URL(state.uiUrl);
33
+ const parsedPort = Number(parsed.port || 80);
34
+ return {
35
+ host: state.uiHost ?? parsed.hostname,
36
+ port: Number.isFinite(parsedPort) ? parsedPort : state.uiPort ?? 55667
37
+ };
38
+ } catch {
39
+ return {
40
+ host: state.uiHost ?? "127.0.0.1",
41
+ port: state.uiPort ?? 55667
42
+ };
43
+ }
44
+ }
45
+ function resolveSessionRouteCandidate(params) {
46
+ const { session, normalizeOptionalString } = params;
47
+ const sessionRecord = toObjectRecord(session);
48
+ const key = normalizeOptionalString(sessionRecord?.key);
49
+ if (!key || key.startsWith("cli:")) return null;
50
+ if (!hasSessionRoutingMetadata({
51
+ metadata: toObjectRecord(sessionRecord?.metadata) ?? {},
52
+ normalizeOptionalString
53
+ })) return null;
54
+ const updatedAtRaw = normalizeOptionalString(sessionRecord?.updated_at);
55
+ const updatedAt = updatedAtRaw ? Date.parse(updatedAtRaw) : NaN;
56
+ return {
57
+ key,
58
+ updatedAt: Number.isFinite(updatedAt) ? updatedAt : 0
59
+ };
60
+ }
61
+ //#endregion
62
+ export { resolveManagedServiceReadySnapshot, resolveManagedServiceUiBinding, resolveSessionRouteCandidate };
@@ -1,10 +1,10 @@
1
1
  import { isProcessRunning, resolveUiApiBase } from "../../../utils/cli.utils.js";
2
2
  import { managedServiceStateStore } from "../../../stores/managed-service-state.store.js";
3
3
  import { buildNextclawConfiguredRemoteState, createNextclawRemoteConnector, createNextclawRemoteStatusStore } from "../../../../commands/remote/utils/remote-runtime-support.utils.js";
4
- import { dirname, resolve } from "node:path";
5
4
  import { getDataDir } from "@nextclaw/core";
6
- import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
7
5
  import { RemoteServiceModule } from "@nextclaw/remote";
6
+ import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
7
+ import { dirname, resolve } from "node:path";
8
8
  //#region src/shared/services/runtime/utils/service-remote-runtime.utils.ts
9
9
  function resolveRemoteOwnershipLockPath() {
10
10
  return resolve(getDataDir(), "run", "remote-owner.lock.json");
@@ -1,5 +1,5 @@
1
- import { UiNcpAgent } from "@nextclaw/server";
2
1
  import { AgentRuntimeHandle } from "@nextclaw/kernel";
2
+ import { UiNcpAgent } from "@nextclaw/server";
3
3
 
4
4
  //#region src/shared/services/session/service-deferred-ncp-agent.service.d.ts
5
5
  type DeferredUiNcpAgentController = {
@@ -9,6 +9,7 @@ declare class CompanionRuntimeService {
9
9
  constructor(runtimeStore?: CompanionRuntimeStore, uiDiscoveryService?: LocalUiDiscoveryService);
10
10
  readonly getRunningState: () => CompanionRuntimeState | null;
11
11
  readonly resolveDiscoveredBaseUrl: () => string | null;
12
+ readonly isAvailable: () => boolean;
12
13
  readonly applyConfig: (config: Config) => Promise<void>;
13
14
  readonly updateEnabled: (enabled: boolean, options?: {
14
15
  baseUrl?: string;
@@ -25,6 +26,7 @@ declare class CompanionRuntimeService {
25
26
  readonly printStarted: (state: CompanionRuntimeState) => void;
26
27
  readonly printStopped: (stopped: boolean) => void;
27
28
  private readonly killProcess;
29
+ private readonly ensureStartedIfAvailable;
28
30
  private readonly resolveLaunchSpec;
29
31
  private readonly waitForRunningState;
30
32
  }