@nextclaw/service 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli/commands/agent/agent-runtime.utils.d.ts +15 -0
  3. package/dist/cli/commands/agent/agent-runtime.utils.js +85 -0
  4. package/dist/cli/commands/agent/cli-agent-runner.utils.d.ts +21 -0
  5. package/dist/cli/commands/agent/cli-agent-runner.utils.js +89 -0
  6. package/dist/cli/commands/agent/index.d.ts +3 -0
  7. package/dist/cli/commands/agent/index.js +3 -0
  8. package/dist/cli/commands/agent/services/agent-commands.service.d.ts +17 -0
  9. package/dist/cli/commands/agent/services/agent-commands.service.js +112 -0
  10. package/dist/cli/commands/companion/index.d.ts +15 -0
  11. package/dist/cli/commands/companion/index.js +24 -0
  12. package/dist/cli/commands/companion/services/companion-process.service.d.ts +17 -0
  13. package/dist/cli/commands/companion/services/companion-process.service.js +49 -0
  14. package/dist/cli/commands/config/index.d.ts +2 -0
  15. package/dist/cli/commands/config/index.js +2 -0
  16. package/dist/cli/commands/config/services/config-commands.service.d.ts +18 -0
  17. package/dist/cli/commands/config/services/config-commands.service.js +133 -0
  18. package/dist/cli/commands/cron/index.d.ts +2 -0
  19. package/dist/cli/commands/cron/index.js +2 -0
  20. package/dist/cli/commands/cron/services/cron-commands.service.d.ts +22 -0
  21. package/dist/cli/commands/cron/services/cron-commands.service.js +107 -0
  22. package/dist/cli/commands/cron/services/cron-local.service.d.ts +25 -0
  23. package/dist/cli/commands/cron/services/cron-local.service.js +95 -0
  24. package/dist/cli/commands/cron/utils/cron-job.utils.d.ts +31 -0
  25. package/dist/cli/commands/cron/utils/cron-job.utils.js +15 -0
  26. package/dist/cli/commands/diagnostics/index.d.ts +2 -0
  27. package/dist/cli/commands/diagnostics/index.js +2 -0
  28. package/dist/cli/commands/diagnostics/services/diagnostics-commands.service.d.ts +22 -0
  29. package/dist/cli/commands/diagnostics/services/diagnostics-commands.service.js +319 -0
  30. package/dist/cli/commands/diagnostics/utils/diagnostics-render.utils.d.ts +23 -0
  31. package/dist/cli/commands/diagnostics/utils/diagnostics-render.utils.js +66 -0
  32. package/dist/cli/commands/gateway/index.d.ts +14 -0
  33. package/dist/cli/commands/gateway/index.js +15 -0
  34. package/dist/cli/commands/logs/index.d.ts +12 -0
  35. package/dist/cli/commands/logs/index.js +29 -0
  36. package/dist/cli/commands/mcp/index.d.ts +14 -0
  37. package/dist/cli/commands/mcp/index.js +193 -0
  38. package/dist/cli/commands/restart/index.d.ts +20 -0
  39. package/dist/cli/commands/restart/index.js +88 -0
  40. package/dist/cli/commands/secrets/index.d.ts +22 -0
  41. package/dist/cli/commands/secrets/index.js +280 -0
  42. package/dist/cli/commands/serve/index.d.ts +14 -0
  43. package/dist/cli/commands/serve/index.js +19 -0
  44. package/dist/cli/commands/skills/index.d.ts +26 -0
  45. package/dist/cli/commands/skills/index.js +147 -0
  46. package/dist/cli/commands/skills/marketplace-client.d.ts +31 -0
  47. package/dist/cli/commands/skills/marketplace-client.js +84 -0
  48. package/dist/cli/commands/skills/marketplace-command-options.utils.d.ts +25 -0
  49. package/dist/cli/commands/skills/marketplace-command-options.utils.js +31 -0
  50. package/dist/cli/commands/skills/marketplace-identity.utils.d.ts +14 -0
  51. package/dist/cli/commands/skills/marketplace-identity.utils.js +77 -0
  52. package/dist/cli/commands/skills/marketplace-network-retry.d.ts +4 -0
  53. package/dist/cli/commands/skills/marketplace-network-retry.js +32 -0
  54. package/dist/cli/commands/skills/marketplace.metadata.d.ts +29 -0
  55. package/dist/cli/commands/skills/marketplace.metadata.js +158 -0
  56. package/dist/cli/commands/skills/marketplace.service.d.ts +46 -0
  57. package/dist/cli/commands/skills/marketplace.service.js +238 -0
  58. package/dist/cli/commands/skills/skills-query.service.d.ts +141 -0
  59. package/dist/cli/commands/skills/skills-query.service.js +212 -0
  60. package/dist/cli/commands/start/index.d.ts +18 -0
  61. package/dist/cli/commands/start/index.js +25 -0
  62. package/dist/cli/commands/stop/index.d.ts +12 -0
  63. package/dist/cli/commands/stop/index.js +11 -0
  64. package/dist/cli/commands/ui/index.d.ts +14 -0
  65. package/dist/cli/commands/ui/index.js +17 -0
  66. package/dist/cli/commands/usage/index.d.ts +2 -0
  67. package/dist/cli/commands/usage/index.js +2 -0
  68. package/dist/cli/commands/usage/services/llm-usage-command.service.d.ts +22 -0
  69. package/dist/cli/commands/usage/services/llm-usage-command.service.js +160 -0
  70. package/dist/cli/commands/usage/services/llm-usage-query.service.d.ts +43 -0
  71. package/dist/cli/commands/usage/services/llm-usage-query.service.js +85 -0
  72. package/dist/commands/channel/channel-config-view.d.ts +7 -0
  73. package/dist/commands/channel/channel-config-view.js +7 -0
  74. package/dist/commands/channel/index.d.ts +28 -0
  75. package/dist/commands/channel/index.js +224 -0
  76. package/dist/commands/platform-auth/index.d.ts +2 -0
  77. package/dist/commands/platform-auth/index.js +2 -0
  78. package/dist/commands/platform-auth/services/account-status.service.d.ts +18 -0
  79. package/dist/commands/platform-auth/services/account-status.service.js +34 -0
  80. package/dist/commands/platform-auth/services/platform-auth-commands.service.d.ts +77 -0
  81. package/dist/commands/platform-auth/services/platform-auth-commands.service.js +295 -0
  82. package/dist/commands/platform-auth/utils/payload.utils.d.ts +28 -0
  83. package/dist/commands/platform-auth/utils/payload.utils.js +87 -0
  84. package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.d.ts +18 -0
  85. package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.js +111 -0
  86. package/dist/commands/plugin/development-source/first-party-plugin-load-paths.d.ts +9 -0
  87. package/dist/commands/plugin/development-source/first-party-plugin-load-paths.js +183 -0
  88. package/dist/commands/plugin/index.d.ts +30 -0
  89. package/dist/commands/plugin/index.js +266 -0
  90. package/dist/commands/plugin/plugin-command-utils.d.ts +13 -0
  91. package/dist/commands/plugin/plugin-command-utils.js +37 -0
  92. package/dist/commands/plugin/plugin-extension-registry.d.ts +10 -0
  93. package/dist/commands/plugin/plugin-extension-registry.js +35 -0
  94. package/dist/commands/plugin/plugin-mutation-actions.d.ts +15 -0
  95. package/dist/commands/plugin/plugin-mutation-actions.js +162 -0
  96. package/dist/commands/plugin/plugin-registry-loader.d.ts +15 -0
  97. package/dist/commands/plugin/plugin-registry-loader.js +43 -0
  98. package/dist/commands/plugin/plugin-reload.d.ts +13 -0
  99. package/dist/commands/plugin/plugin-reload.js +42 -0
  100. package/dist/commands/remote/index.d.ts +47 -0
  101. package/dist/commands/remote/index.js +174 -0
  102. package/dist/commands/remote/services/remote-access-host.service.d.ts +41 -0
  103. package/dist/commands/remote/services/remote-access-host.service.js +126 -0
  104. package/dist/commands/remote/services/remote-runtime-support.service.d.ts +15 -0
  105. package/dist/commands/remote/services/remote-runtime-support.service.js +79 -0
  106. package/dist/commands/remote/services/remote-service-control.service.d.ts +33 -0
  107. package/dist/commands/remote/services/remote-service-control.service.js +188 -0
  108. package/dist/commands/remote/utils/platform-api-base.utils.d.ts +14 -0
  109. package/dist/commands/remote/utils/platform-api-base.utils.js +39 -0
  110. package/dist/commands/service/index.d.ts +16 -0
  111. package/dist/commands/service/index.js +31 -0
  112. package/dist/commands/service/services/autostart/host-autostart-command.service.d.ts +29 -0
  113. package/dist/commands/service/services/autostart/host-autostart-command.service.js +158 -0
  114. package/dist/commands/service/services/autostart/host-autostart-runtime.service.d.ts +23 -0
  115. package/dist/commands/service/services/autostart/host-autostart-runtime.service.js +53 -0
  116. package/dist/commands/service/services/autostart/host-autostart.service.d.ts +41 -0
  117. package/dist/commands/service/services/autostart/host-autostart.service.js +48 -0
  118. package/dist/commands/service/services/autostart/linux-systemd-autostart.service.d.ts +48 -0
  119. package/dist/commands/service/services/autostart/linux-systemd-autostart.service.js +433 -0
  120. package/dist/commands/service/services/autostart/macos-launch-agent-autostart.service.d.ts +54 -0
  121. package/dist/commands/service/services/autostart/macos-launch-agent-autostart.service.js +405 -0
  122. package/dist/commands/service/services/autostart/windows-task-autostart.service.d.ts +54 -0
  123. package/dist/commands/service/services/autostart/windows-task-autostart.service.js +403 -0
  124. package/dist/commands/service/types/autostart/host-autostart.types.d.ts +64 -0
  125. package/dist/commands/service/types/autostart/host-autostart.types.js +1 -0
  126. package/dist/index.d.ts +4 -0
  127. package/dist/index.js +3 -0
  128. package/dist/launcher/npm-runtime-bundle-layout.store.d.ts +23 -0
  129. package/dist/launcher/npm-runtime-bundle-layout.store.js +37 -0
  130. package/dist/launcher/npm-runtime-bundle-manifest.service.d.ts +9 -0
  131. package/dist/launcher/npm-runtime-bundle-manifest.service.js +39 -0
  132. package/dist/launcher/npm-runtime-bundle.service.d.ts +47 -0
  133. package/dist/launcher/npm-runtime-bundle.service.js +150 -0
  134. package/dist/launcher/npm-runtime-bundle.types.d.ts +49 -0
  135. package/dist/launcher/npm-runtime-bundle.types.js +1 -0
  136. package/dist/launcher/npm-runtime-launcher.service.d.ts +19 -0
  137. package/dist/launcher/npm-runtime-launcher.service.js +57 -0
  138. package/dist/launcher/npm-runtime-update-command.service.d.ts +12 -0
  139. package/dist/launcher/npm-runtime-update-command.service.js +87 -0
  140. package/dist/launcher/npm-runtime-update-source.service.d.ts +19 -0
  141. package/dist/launcher/npm-runtime-update-source.service.js +57 -0
  142. package/dist/launcher/npm-runtime-update-state.store.d.ts +17 -0
  143. package/dist/launcher/npm-runtime-update-state.store.js +92 -0
  144. package/dist/launcher/npm-runtime-update.manager.d.ts +42 -0
  145. package/dist/launcher/npm-runtime-update.manager.js +179 -0
  146. package/dist/launcher/npm-runtime-update.service.d.ts +54 -0
  147. package/dist/launcher/npm-runtime-update.service.js +183 -0
  148. package/dist/service-runtime.service.d.ts +91 -0
  149. package/dist/service-runtime.service.js +392 -0
  150. package/dist/shared/controllers/gateway.controller.d.ts +61 -0
  151. package/dist/shared/controllers/gateway.controller.js +318 -0
  152. package/dist/shared/services/extensions/extension-lifecycle.service.d.ts +56 -0
  153. package/dist/shared/services/extensions/extension-lifecycle.service.js +143 -0
  154. package/dist/shared/services/extensions/service-extension-runtime.service.d.ts +51 -0
  155. package/dist/shared/services/extensions/service-extension-runtime.service.js +338 -0
  156. package/dist/shared/services/gateway/cron-job-handler.service.d.ts +26 -0
  157. package/dist/shared/services/gateway/cron-job-handler.service.js +100 -0
  158. package/dist/shared/services/gateway/gateway-restart-wake.service.d.ts +12 -0
  159. package/dist/shared/services/gateway/gateway-restart-wake.service.js +91 -0
  160. package/dist/shared/services/gateway/managers/gateway-plugin.manager.d.ts +37 -0
  161. package/dist/shared/services/gateway/managers/gateway-plugin.manager.js +218 -0
  162. package/dist/shared/services/gateway/managers/gateway-remote.manager.d.ts +20 -0
  163. package/dist/shared/services/gateway/managers/gateway-remote.manager.js +25 -0
  164. package/dist/shared/services/gateway/nextclaw-app.service.d.ts +22 -0
  165. package/dist/shared/services/gateway/nextclaw-app.service.js +53 -0
  166. package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts +89 -0
  167. package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js +337 -0
  168. package/dist/shared/services/gateway/service-bootstrap-status.d.ts +33 -0
  169. package/dist/shared/services/gateway/service-bootstrap-status.js +152 -0
  170. package/dist/shared/services/gateway/service-startup-support.service.d.ts +42 -0
  171. package/dist/shared/services/gateway/service-startup-support.service.js +96 -0
  172. package/dist/shared/services/gateway/utils/gateway-runtime-lifecycle.utils.d.ts +9 -0
  173. package/dist/shared/services/gateway/utils/gateway-runtime-lifecycle.utils.js +10 -0
  174. package/dist/shared/services/marketplace/service-marketplace-installer.service.d.ts +31 -0
  175. package/dist/shared/services/marketplace/service-marketplace-installer.service.js +99 -0
  176. package/dist/shared/services/marketplace/service-mcp-marketplace-ops.d.ts +39 -0
  177. package/dist/shared/services/marketplace/service-mcp-marketplace-ops.js +67 -0
  178. package/dist/shared/services/plugin/utils/plugin-dev-hot-reload.utils.d.ts +24 -0
  179. package/dist/shared/services/plugin/utils/plugin-dev-hot-reload.utils.js +117 -0
  180. package/dist/shared/services/plugin/utils/plugin-runtime-bridge.utils.d.ts +6 -0
  181. package/dist/shared/services/plugin/utils/plugin-runtime-bridge.utils.js +96 -0
  182. package/dist/shared/services/restart/restart-coordinator.service.d.ts +30 -0
  183. package/dist/shared/services/restart/restart-coordinator.service.js +51 -0
  184. package/dist/shared/services/restart/restart-sentinel.service.d.ts +39 -0
  185. package/dist/shared/services/restart/restart-sentinel.service.js +88 -0
  186. package/dist/shared/services/restart/runtime-restart-request.service.d.ts +24 -0
  187. package/dist/shared/services/restart/runtime-restart-request.service.js +42 -0
  188. package/dist/shared/services/runtime/runtime-command.service.d.ts +37 -0
  189. package/dist/shared/services/runtime/runtime-command.service.js +163 -0
  190. package/dist/shared/services/runtime/runtime-config-init.service.d.ts +4 -0
  191. package/dist/shared/services/runtime/runtime-config-init.service.js +10 -0
  192. package/dist/shared/services/runtime/service-managed-startup.service.d.ts +146 -0
  193. package/dist/shared/services/runtime/service-managed-startup.service.js +426 -0
  194. package/dist/shared/services/runtime/service-remote-runtime.service.d.ts +53 -0
  195. package/dist/shared/services/runtime/service-remote-runtime.service.js +173 -0
  196. package/dist/shared/services/runtime/utils/skills-loader.utils.d.ts +12 -0
  197. package/dist/shared/services/runtime/utils/skills-loader.utils.js +9 -0
  198. package/dist/shared/services/session/service-deferred-ncp-agent.service.d.ts +14 -0
  199. package/dist/shared/services/session/service-deferred-ncp-agent.service.js +85 -0
  200. package/dist/shared/services/ui/companion-runtime.service.d.ts +33 -0
  201. package/dist/shared/services/ui/companion-runtime.service.js +145 -0
  202. package/dist/shared/services/ui/local-ui-discovery.service.d.ts +19 -0
  203. package/dist/shared/services/ui/local-ui-discovery.service.js +41 -0
  204. package/dist/shared/services/ui/npm-runtime-update-host.service.d.ts +40 -0
  205. package/dist/shared/services/ui/npm-runtime-update-host.service.js +181 -0
  206. package/dist/shared/services/ui/runtime-control-host.service.d.ts +28 -0
  207. package/dist/shared/services/ui/runtime-control-host.service.js +89 -0
  208. package/dist/shared/services/ui/service-remote-access.service.d.ts +25 -0
  209. package/dist/shared/services/ui/service-remote-access.service.js +38 -0
  210. package/dist/shared/services/ui/ui-bridge-api.service.d.ts +16 -0
  211. package/dist/shared/services/ui/ui-bridge-api.service.js +43 -0
  212. package/dist/shared/services/workspace/workspace-manager.service.d.ts +19 -0
  213. package/dist/shared/services/workspace/workspace-manager.service.js +135 -0
  214. package/dist/shared/stores/companion-runtime.store.d.ts +15 -0
  215. package/dist/shared/stores/companion-runtime.store.js +27 -0
  216. package/dist/shared/stores/local-ui-runtime.store.d.ts +25 -0
  217. package/dist/shared/stores/local-ui-runtime.store.js +54 -0
  218. package/dist/shared/stores/managed-service-state.store.d.ts +28 -0
  219. package/dist/shared/stores/managed-service-state.store.js +38 -0
  220. package/dist/shared/stores/pending-restart.store.d.ts +21 -0
  221. package/dist/shared/stores/pending-restart.store.js +35 -0
  222. package/dist/shared/types/cli.types.d.ts +295 -0
  223. package/dist/shared/types/cli.types.js +1 -0
  224. package/dist/shared/utils/cli.utils.d.ts +34 -0
  225. package/dist/shared/utils/cli.utils.js +262 -0
  226. package/dist/shared/utils/config-path.d.ts +15 -0
  227. package/dist/shared/utils/config-path.js +167 -0
  228. package/dist/shared/utils/marketplace/cli-subcommand-launch.utils.d.ts +16 -0
  229. package/dist/shared/utils/marketplace/cli-subcommand-launch.utils.js +46 -0
  230. package/dist/shared/utils/marketplace/service-marketplace-helpers.utils.d.ts +9 -0
  231. package/dist/shared/utils/marketplace/service-marketplace-helpers.utils.js +33 -0
  232. package/dist/shared/utils/package/package-manifest.utils.d.ts +8 -0
  233. package/dist/shared/utils/package/package-manifest.utils.js +48 -0
  234. package/dist/shared/utils/runtime-helpers.d.ts +14 -0
  235. package/dist/shared/utils/runtime-helpers.js +26 -0
  236. package/dist/shared/utils/service-port-probe.utils.d.ts +41 -0
  237. package/dist/shared/utils/service-port-probe.utils.js +164 -0
  238. package/dist/shared/utils/startup-trace.d.ts +7 -0
  239. package/dist/shared/utils/startup-trace.js +37 -0
  240. package/dist/shared/utils/top-level-nextclaw-command-env.utils.d.ts +4 -0
  241. package/dist/shared/utils/top-level-nextclaw-command-env.utils.js +10 -0
  242. package/package.json +68 -0
@@ -0,0 +1,426 @@
1
+ import { isProcessRunning, openBrowser, resolveServiceLogPath, resolveUiApiBase, resolveUiConfig, resolveUiStaticDir, waitForExit } from "../../utils/cli.utils.js";
2
+ import { localUiRuntimeStore } from "../../stores/local-ui-runtime.store.js";
3
+ import { managedServiceStateStore } from "../../stores/managed-service-state.store.js";
4
+ import { probeHealthEndpoint } from "../../utils/service-port-probe.utils.js";
5
+ import { resolveCliSubcommandLaunch } from "../../utils/marketplace/cli-subcommand-launch.utils.js";
6
+ import { createTopLevelNextclawCommandEnv } from "../../utils/top-level-nextclaw-command-env.utils.js";
7
+ import { writeInitialManagedServiceState, writeReadyManagedServiceState } from "./service-remote-runtime.service.js";
8
+ import { spawn } from "node:child_process";
9
+ import { dirname } from "node:path";
10
+ import * as NextclawCore from "@nextclaw/core";
11
+ import { FileLogSink } from "@nextclaw/core";
12
+ import { mkdirSync } from "node:fs";
13
+ //#region src/shared/services/runtime/service-managed-startup.service.ts
14
+ 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
+ }
69
+ function spawnManagedService(params) {
70
+ const { appName, config, uiConfig, uiUrl, apiUrl, healthUrl, startupTimeoutMs, resolveStartupTimeoutMs, appendStartupStage, printStartupFailureDiagnostics, resolveServiceLogPath } = params;
71
+ const logPath = resolveServiceLogPath();
72
+ new FileLogSink({ serviceLogPath: logPath }).ensureReady();
73
+ mkdirSync(dirname(logPath), { recursive: true });
74
+ const readinessTimeoutMs = resolveStartupTimeoutMs(startupTimeoutMs);
75
+ const quickPhaseTimeoutMs = Math.min(8e3, readinessTimeoutMs);
76
+ const extendedPhaseTimeoutMs = Math.max(0, readinessTimeoutMs - quickPhaseTimeoutMs);
77
+ appendStartupStage(logPath, `start requested: ui=${uiConfig.host}:${uiConfig.port}, readinessTimeoutMs=${readinessTimeoutMs}`);
78
+ console.log(`Starting ${appName} background service (readiness timeout ${Math.ceil(readinessTimeoutMs / 1e3)}s)...`);
79
+ const cliLaunch = resolveCliSubcommandLaunch({
80
+ argvEntry: process.argv[1],
81
+ importMetaUrl: import.meta.url,
82
+ cliArgs: [
83
+ "serve",
84
+ "--ui-port",
85
+ String(uiConfig.port)
86
+ ],
87
+ nodePath: process.execPath
88
+ });
89
+ const childArgs = [...process.execArgv, ...cliLaunch.args];
90
+ appendStartupStage(logPath, `spawning background process: ${cliLaunch.command} ${childArgs.join(" ")}`);
91
+ const child = spawn(cliLaunch.command, childArgs, {
92
+ env: createTopLevelNextclawCommandEnv(process.env),
93
+ stdio: "ignore",
94
+ detached: true
95
+ });
96
+ appendStartupStage(logPath, `spawned background process pid=${child.pid ?? "unknown"}`);
97
+ if (!child.pid) {
98
+ appendStartupStage(logPath, "spawn failed: child pid missing");
99
+ console.error("Error: Failed to start background service.");
100
+ printStartupFailureDiagnostics({
101
+ uiUrl,
102
+ apiUrl,
103
+ healthUrl,
104
+ logPath,
105
+ lastProbeError: null
106
+ });
107
+ return null;
108
+ }
109
+ const snapshot = {
110
+ pid: child.pid,
111
+ uiUrl,
112
+ apiUrl,
113
+ uiHost: uiConfig.host,
114
+ uiPort: uiConfig.port,
115
+ logPath
116
+ };
117
+ writeInitialManagedServiceState({
118
+ config,
119
+ readinessTimeoutMs,
120
+ snapshot
121
+ });
122
+ return {
123
+ child,
124
+ logPath,
125
+ readinessTimeoutMs,
126
+ quickPhaseTimeoutMs,
127
+ extendedPhaseTimeoutMs,
128
+ snapshot
129
+ };
130
+ }
131
+ async function waitForManagedServiceReadiness(params) {
132
+ params.appendStartupStage(params.logPath, `health probe started: ${params.healthUrl} (phase=quick, timeoutMs=${params.quickPhaseTimeoutMs})`);
133
+ let readiness = await params.waitForBackgroundServiceReady({
134
+ pid: params.childPid,
135
+ healthUrl: params.healthUrl,
136
+ timeoutMs: params.quickPhaseTimeoutMs
137
+ });
138
+ if (!readiness.ready && params.isProcessRunning(params.childPid) && params.extendedPhaseTimeoutMs > 0) {
139
+ console.warn(`Warning: Background service is still running but not ready after ${Math.ceil(params.quickPhaseTimeoutMs / 1e3)}s; waiting up to ${Math.ceil(params.extendedPhaseTimeoutMs / 1e3)}s more.`);
140
+ params.appendStartupStage(params.logPath, `health probe entering extended phase (timeoutMs=${params.extendedPhaseTimeoutMs}, lastError=${readiness.lastProbeError ?? "none"})`);
141
+ readiness = await params.waitForBackgroundServiceReady({
142
+ pid: params.childPid,
143
+ healthUrl: params.healthUrl,
144
+ timeoutMs: params.extendedPhaseTimeoutMs
145
+ });
146
+ }
147
+ if (!readiness.ready && params.isProcessRunning(params.childPid)) params.appendStartupStage(params.logPath, `startup degraded: process alive but health probe timed out after ${params.readinessTimeoutMs}ms (lastError=${readiness.lastProbeError ?? "none"})`);
148
+ return readiness;
149
+ }
150
+ async function reportManagedServiceStart(params) {
151
+ if (!params.readiness.ready) {
152
+ const hint = params.readiness.lastProbeError ? ` Last probe error: ${params.readiness.lastProbeError}` : "";
153
+ console.warn(`Warning: ${params.appName} is running (PID ${params.state.pid}) but not healthy yet after ${Math.ceil(params.readinessTimeoutMs / 1e3)}s. Marked as degraded.${hint}`);
154
+ console.warn(`Tip: Run "${params.appName} status --json" and check logs: ${params.state.logPath}`);
155
+ } else console.log(`✓ ${params.appName} started in background (PID ${params.state.pid})`);
156
+ console.log(`UI: ${params.uiUrl}`);
157
+ console.log(`API: ${params.apiUrl}`);
158
+ await params.printPublicUiUrls(params.uiConfig.host, params.uiConfig.port);
159
+ console.log(`Logs: ${params.state.logPath}`);
160
+ params.printServiceControlHints();
161
+ }
162
+ var ManagedServiceCommandService = class {
163
+ loggingRuntime = NextclawCore.getLoggingRuntime();
164
+ serviceLogger = this.loggingRuntime.getLogger("service");
165
+ constructor(deps) {
166
+ this.deps = deps;
167
+ }
168
+ runForeground = async (options) => {
169
+ const uiConfig = resolveUiConfig(loadConfig$1(), options.uiOverrides);
170
+ const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
171
+ if (options.open) openBrowser(uiUrl);
172
+ await this.deps.startGateway({
173
+ uiOverrides: options.uiOverrides,
174
+ uiStaticDir: resolveUiStaticDir()
175
+ });
176
+ };
177
+ startService = async (options) => {
178
+ this.loggingRuntime.ensureReady();
179
+ const { open, startupTimeoutMs, uiOverrides } = options;
180
+ const config = loadConfig$1();
181
+ const uiConfig = resolveUiConfig(config, uiOverrides);
182
+ const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
183
+ const apiUrl = `${uiUrl}/api`;
184
+ const staticDir = resolveUiStaticDir();
185
+ const existing = managedServiceStateStore.read();
186
+ if (existing && isProcessRunning(existing.pid)) {
187
+ await this.handleExistingManagedService({
188
+ existing,
189
+ uiConfig,
190
+ options
191
+ });
192
+ return;
193
+ }
194
+ if (existing) managedServiceStateStore.clear();
195
+ if (!staticDir) {
196
+ process.exitCode = 1, console.error(`Error: ${APP_NAME$1} UI frontend bundle not found. Reinstall or rebuild ${APP_NAME$1}. For dev-only overrides, set NEXTCLAW_UI_STATIC_DIR to a built frontend directory.`);
197
+ return;
198
+ }
199
+ const healthUrl = `${apiUrl}/health`;
200
+ const portPreflight = await this.deps.checkUiPortPreflight({
201
+ host: uiConfig.host,
202
+ port: uiConfig.port,
203
+ healthUrl
204
+ });
205
+ if (!portPreflight.ok) {
206
+ process.exitCode = 1, console.error(`Error: Cannot start ${APP_NAME$1} because UI port ${uiConfig.port} is already occupied.`), console.error(portPreflight.message);
207
+ return;
208
+ }
209
+ if (portPreflight.reusedExistingHealthyTarget) {
210
+ await this.reuseExistingHealthyStartTarget({
211
+ uiConfig,
212
+ uiUrl,
213
+ apiUrl,
214
+ open
215
+ });
216
+ return;
217
+ }
218
+ await this.startNewManagedServiceTarget({
219
+ config,
220
+ uiConfig,
221
+ uiUrl,
222
+ apiUrl,
223
+ healthUrl,
224
+ startupTimeoutMs
225
+ });
226
+ if (open) openBrowser(uiUrl);
227
+ };
228
+ stopService = async () => {
229
+ const state = managedServiceStateStore.read();
230
+ if (!state) {
231
+ console.log("No running background service found.");
232
+ return;
233
+ }
234
+ if (!isProcessRunning(state.pid)) {
235
+ console.log("Service is not running. Cleaning up state.");
236
+ managedServiceStateStore.clear();
237
+ return;
238
+ }
239
+ console.log(`Stopping ${APP_NAME$1} (PID ${state.pid})...`);
240
+ try {
241
+ process.kill(state.pid, "SIGTERM");
242
+ } catch (error) {
243
+ console.error(`Failed to stop service: ${String(error)}`);
244
+ return;
245
+ }
246
+ if (!await waitForExit(state.pid, 3e3)) {
247
+ try {
248
+ process.kill(state.pid, "SIGKILL");
249
+ } catch (error) {
250
+ console.error(`Failed to force stop service: ${String(error)}`);
251
+ return;
252
+ }
253
+ await waitForExit(state.pid, 2e3);
254
+ }
255
+ managedServiceStateStore.clear();
256
+ localUiRuntimeStore.clearIfOwnedByProcess(state.pid);
257
+ console.log(`✓ ${APP_NAME$1} stopped`);
258
+ };
259
+ handleExistingManagedService = async (params) => {
260
+ const { existing, options, uiConfig } = params;
261
+ console.log(`✓ ${APP_NAME$1} is already running (PID ${existing.pid})`);
262
+ console.log(`UI: ${existing.uiUrl}`);
263
+ console.log(`API: ${existing.apiUrl}`);
264
+ const binding = resolveManagedServiceUiBinding(existing);
265
+ if (binding.host !== uiConfig.host || binding.port !== uiConfig.port) {
266
+ console.log(`Detected running service UI bind (${binding.host}:${binding.port}); enforcing (${uiConfig.host}:${uiConfig.port})...`);
267
+ await this.stopService();
268
+ const stateAfterStop = managedServiceStateStore.read();
269
+ if (stateAfterStop && isProcessRunning(stateAfterStop.pid)) {
270
+ process.exitCode = 1;
271
+ console.error("Error: Failed to stop running service while enforcing public UI exposure.");
272
+ return true;
273
+ }
274
+ await this.startService(options);
275
+ return true;
276
+ }
277
+ await this.deps.printPublicUiUrls(binding.host, binding.port);
278
+ console.log(`Logs: ${existing.logPath}`);
279
+ this.deps.printServiceControlHints();
280
+ return true;
281
+ };
282
+ reuseExistingHealthyStartTarget = async (params) => {
283
+ const { apiUrl, open, uiConfig, uiUrl } = params;
284
+ console.log(`✓ ${APP_NAME$1} is already serving the target UI/API port`);
285
+ console.log(`UI: ${uiUrl}`);
286
+ console.log(`API: ${apiUrl}`);
287
+ console.warn([
288
+ `Warning: The healthy listener on ${uiConfig.port} is not tracked by ${managedServiceStateStore.path}.`,
289
+ "This start call reused the existing runtime instead of spawning another one.",
290
+ "Use the owning process or port-level tools to stop it; managed stop/restart will not control it automatically."
291
+ ].join(" "));
292
+ await this.deps.printPublicUiUrls(uiConfig.host, uiConfig.port);
293
+ if (open) openBrowser(uiUrl);
294
+ };
295
+ startNewManagedServiceTarget = async (params) => {
296
+ const { apiUrl, config, healthUrl, startupTimeoutMs, uiConfig, uiUrl } = params;
297
+ const startup = spawnManagedService({
298
+ appName: APP_NAME$1,
299
+ config,
300
+ uiConfig,
301
+ uiUrl,
302
+ apiUrl,
303
+ healthUrl,
304
+ startupTimeoutMs,
305
+ resolveStartupTimeoutMs: this.resolveStartupTimeoutMs,
306
+ appendStartupStage: this.appendStartupStage,
307
+ printStartupFailureDiagnostics: this.printStartupFailureDiagnostics,
308
+ resolveServiceLogPath
309
+ });
310
+ if (!startup) {
311
+ this.serviceLogger.fatal("managed service startup aborted", { reason: "child_process_not_created" });
312
+ process.exitCode = 1;
313
+ return;
314
+ }
315
+ const readiness = await waitForManagedServiceReadiness({
316
+ appName: APP_NAME$1,
317
+ childPid: startup.snapshot.pid,
318
+ healthUrl,
319
+ logPath: startup.logPath,
320
+ readinessTimeoutMs: startup.readinessTimeoutMs,
321
+ quickPhaseTimeoutMs: startup.quickPhaseTimeoutMs,
322
+ extendedPhaseTimeoutMs: startup.extendedPhaseTimeoutMs,
323
+ appendStartupStage: this.appendStartupStage,
324
+ waitForBackgroundServiceReady: this.waitForBackgroundServiceReady,
325
+ isProcessRunning
326
+ });
327
+ if (!readiness.ready && !isProcessRunning(startup.snapshot.pid)) {
328
+ process.exitCode = 1;
329
+ managedServiceStateStore.clear();
330
+ const hint = readiness.lastProbeError ? ` Last probe error: ${readiness.lastProbeError}` : "";
331
+ this.appendStartupStage(startup.logPath, `startup failed: process exited before ready.${hint}`);
332
+ this.serviceLogger.fatal("managed service exited before readiness completed", {
333
+ uiUrl,
334
+ apiUrl,
335
+ healthUrl,
336
+ logPath: startup.logPath,
337
+ ...readiness.lastProbeError ? { lastProbeError: readiness.lastProbeError } : {}
338
+ });
339
+ console.error(`Error: Failed to start background service. Check logs: ${startup.logPath}.${hint}`);
340
+ this.printStartupFailureDiagnostics({
341
+ uiUrl,
342
+ apiUrl,
343
+ healthUrl,
344
+ logPath: startup.logPath,
345
+ lastProbeError: readiness.lastProbeError
346
+ });
347
+ return;
348
+ }
349
+ startup.child.unref();
350
+ const readySnapshot = resolveManagedServiceReadySnapshot({ snapshot: startup.snapshot });
351
+ await reportManagedServiceStart({
352
+ appName: APP_NAME$1,
353
+ state: writeReadyManagedServiceState({
354
+ readinessTimeoutMs: startup.readinessTimeoutMs,
355
+ readiness,
356
+ snapshot: readySnapshot
357
+ }),
358
+ uiConfig,
359
+ uiUrl,
360
+ apiUrl,
361
+ readinessTimeoutMs: startup.readinessTimeoutMs,
362
+ readiness,
363
+ printPublicUiUrls: this.deps.printPublicUiUrls,
364
+ printServiceControlHints: this.deps.printServiceControlHints
365
+ });
366
+ };
367
+ waitForBackgroundServiceReady = async (params) => {
368
+ const { pid, healthUrl, timeoutMs } = params;
369
+ const startedAt = Date.now();
370
+ let lastProbeError = null;
371
+ while (Date.now() - startedAt < timeoutMs) {
372
+ if (!isProcessRunning(pid)) return {
373
+ ready: false,
374
+ lastProbeError
375
+ };
376
+ const probe = await probeHealthEndpoint(healthUrl);
377
+ if (!probe.healthy) {
378
+ lastProbeError = probe.error;
379
+ await new Promise((resolvePromise) => setTimeout(resolvePromise, 200));
380
+ continue;
381
+ }
382
+ await new Promise((resolvePromise) => setTimeout(resolvePromise, 300));
383
+ if (isProcessRunning(pid)) return {
384
+ ready: true,
385
+ lastProbeError: null
386
+ };
387
+ await new Promise((resolvePromise) => setTimeout(resolvePromise, 200));
388
+ }
389
+ return {
390
+ ready: false,
391
+ lastProbeError
392
+ };
393
+ };
394
+ resolveStartupTimeoutMs = (overrideTimeoutMs) => {
395
+ const fallback = process.platform === "win32" ? 28e3 : 33e3;
396
+ const envRaw = process.env.NEXTCLAW_START_TIMEOUT_MS?.trim();
397
+ const envValue = envRaw ? Number(envRaw) : NaN;
398
+ const fromEnv = Number.isFinite(envValue) && envValue > 0 ? Math.floor(envValue) : null;
399
+ const resolved = (Number.isFinite(overrideTimeoutMs) && Number(overrideTimeoutMs) > 0 ? Math.floor(Number(overrideTimeoutMs)) : null) ?? fromEnv ?? fallback;
400
+ return Math.max(3e3, resolved);
401
+ };
402
+ appendStartupStage = (logPath, message) => {
403
+ try {
404
+ this.serviceLogger.child("startup").info(message, { logPath });
405
+ } catch (error) {
406
+ const detail = error instanceof Error ? error.message : String(error);
407
+ console.error(`Warning: failed to write startup diagnostics log (${logPath}): ${detail}`);
408
+ }
409
+ };
410
+ printStartupFailureDiagnostics = (params) => {
411
+ const { apiUrl, healthUrl, lastProbeError, logPath, uiUrl } = params;
412
+ const statePath = managedServiceStateStore.path;
413
+ const lines = [
414
+ "Startup diagnostics:",
415
+ `- UI URL: ${uiUrl}`,
416
+ `- API URL: ${apiUrl}`,
417
+ `- Health probe: ${healthUrl}`,
418
+ `- Service state path: ${statePath}`,
419
+ `- Startup log path: ${logPath}`
420
+ ];
421
+ if (lastProbeError) lines.push(`- Last probe detail: ${lastProbeError}`);
422
+ console.error(lines.join("\n"));
423
+ };
424
+ };
425
+ //#endregion
426
+ export { ManagedServiceCommandService, reportManagedServiceStart, resolveManagedServiceReadySnapshot, resolveManagedServiceUiBinding, resolveSessionRouteCandidate, spawnManagedService, waitForManagedServiceReadiness };
@@ -0,0 +1,53 @@
1
+ import { ManagedServiceState } from "../../stores/managed-service-state.store.js";
2
+ import { Config } from "@nextclaw/core";
3
+ import { RemoteServiceModule } from "@nextclaw/remote";
4
+
5
+ //#region src/shared/services/runtime/service-remote-runtime.service.d.ts
6
+ type ManagedServiceSnapshot = {
7
+ pid: number;
8
+ uiUrl: string;
9
+ apiUrl: string;
10
+ uiHost: string;
11
+ uiPort: number;
12
+ logPath: string;
13
+ };
14
+ type RemoteRuntimeOwnershipClaim = {
15
+ ok: true;
16
+ release: () => void;
17
+ } | {
18
+ ok: false;
19
+ error: string;
20
+ };
21
+ declare function claimManagedRemoteRuntimeOwnership(params: {
22
+ localOrigin: string;
23
+ lockPath?: string;
24
+ currentPid?: number;
25
+ now?: () => string;
26
+ isProcessRunningFn?: (pid: number) => boolean;
27
+ readServiceStateFn?: () => ManagedServiceState | null;
28
+ }): RemoteRuntimeOwnershipClaim;
29
+ declare function createManagedRemoteModule(params: {
30
+ loadConfig: () => Config;
31
+ uiEnabled: boolean;
32
+ localOrigin: string;
33
+ }): RemoteServiceModule | null;
34
+ declare function createManagedRemoteModuleForUi(params: {
35
+ loadConfig: () => Config;
36
+ uiConfig: Pick<Config["ui"], "enabled" | "host" | "port">;
37
+ localOriginOverride?: string;
38
+ }): RemoteServiceModule | null;
39
+ declare function writeInitialManagedServiceState(params: {
40
+ config: Config;
41
+ readinessTimeoutMs: number;
42
+ snapshot: ManagedServiceSnapshot;
43
+ }): void;
44
+ declare function writeReadyManagedServiceState(params: {
45
+ readinessTimeoutMs: number;
46
+ readiness: {
47
+ ready: boolean;
48
+ lastProbeError: string | null;
49
+ };
50
+ snapshot: ManagedServiceSnapshot;
51
+ }): ManagedServiceState;
52
+ //#endregion
53
+ export { claimManagedRemoteRuntimeOwnership, createManagedRemoteModule, createManagedRemoteModuleForUi, writeInitialManagedServiceState, writeReadyManagedServiceState };
@@ -0,0 +1,173 @@
1
+ import { isProcessRunning, resolveUiApiBase } from "../../utils/cli.utils.js";
2
+ import { managedServiceStateStore } from "../../stores/managed-service-state.store.js";
3
+ import { buildNextclawConfiguredRemoteState, createNextclawRemoteConnector, createNextclawRemoteStatusStore } from "../../../commands/remote/services/remote-runtime-support.service.js";
4
+ import { dirname, resolve } from "node:path";
5
+ import { getDataDir } from "@nextclaw/core";
6
+ import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
7
+ import { RemoteServiceModule } from "@nextclaw/remote";
8
+ //#region src/shared/services/runtime/service-remote-runtime.service.ts
9
+ function resolveRemoteOwnershipLockPath() {
10
+ return resolve(getDataDir(), "run", "remote-owner.lock.json");
11
+ }
12
+ function readRemoteOwnershipRecord(lockPath) {
13
+ try {
14
+ const raw = JSON.parse(readFileSync(lockPath, "utf-8"));
15
+ if (typeof raw.pid !== "number" || !Number.isFinite(raw.pid)) return null;
16
+ return {
17
+ pid: raw.pid,
18
+ localOrigin: typeof raw.localOrigin === "string" ? raw.localOrigin : "",
19
+ claimedAt: typeof raw.claimedAt === "string" ? raw.claimedAt : ""
20
+ };
21
+ } catch {
22
+ return null;
23
+ }
24
+ }
25
+ function removeRemoteOwnershipLock(lockPath) {
26
+ if (!existsSync(lockPath)) return;
27
+ try {
28
+ unlinkSync(lockPath);
29
+ } catch {
30
+ try {
31
+ rmSync(lockPath, { force: true });
32
+ } catch {}
33
+ }
34
+ }
35
+ function buildManagedServiceOwnershipError(params) {
36
+ return `Remote access is already owned by running NextClaw service PID ${params.pid}${params.ownerOrigin ? ` (${params.ownerOrigin})` : ""}. Stop that service or disable remote there before starting another process with the same NEXTCLAW_HOME.`;
37
+ }
38
+ function buildLocalProcessOwnershipError(record) {
39
+ const originText = record.localOrigin ? ` (${record.localOrigin})` : "";
40
+ return `Remote access is already owned by local NextClaw process PID ${record.pid}${originText}. Stop that process or use a different NEXTCLAW_HOME before starting another remote-enabled process.`;
41
+ }
42
+ function createRemoteOwnershipRelease(params) {
43
+ let released = false;
44
+ return () => {
45
+ if (released) return;
46
+ released = true;
47
+ const current = readRemoteOwnershipRecord(params.lockPath);
48
+ if (!current || current.pid === params.claim.pid && current.claimedAt === params.claim.claimedAt) removeRemoteOwnershipLock(params.lockPath);
49
+ };
50
+ }
51
+ function detectManagedRemoteOwnershipConflict(params) {
52
+ const runningService = params.readServiceStateFn();
53
+ if (!runningService || runningService.pid === params.currentPid || !params.isProcessRunningFn(runningService.pid) || !runningService.remote?.enabled) return null;
54
+ return buildManagedServiceOwnershipError({
55
+ pid: runningService.pid,
56
+ ownerOrigin: runningService.remote.localOrigin ?? runningService.uiUrl
57
+ });
58
+ }
59
+ function tryClaimRemoteOwnershipLock(params) {
60
+ for (let attempt = 0; attempt < 2; attempt += 1) try {
61
+ const fd = openSync(params.lockPath, "wx");
62
+ writeFileSync(fd, `${JSON.stringify(params.claim, null, 2)}\n`, "utf-8");
63
+ closeSync(fd);
64
+ return {
65
+ ok: true,
66
+ release: createRemoteOwnershipRelease({
67
+ lockPath: params.lockPath,
68
+ claim: params.claim
69
+ })
70
+ };
71
+ } catch (error) {
72
+ if ((typeof error === "object" && error && "code" in error ? String(error.code) : "") !== "EEXIST") return {
73
+ ok: false,
74
+ error: `Failed to claim local remote runtime ownership: ${error instanceof Error ? error.message : String(error)}`
75
+ };
76
+ const existing = readRemoteOwnershipRecord(params.lockPath);
77
+ if (existing && existing.pid !== params.currentPid && params.isProcessRunningFn(existing.pid)) return {
78
+ ok: false,
79
+ error: buildLocalProcessOwnershipError(existing)
80
+ };
81
+ removeRemoteOwnershipLock(params.lockPath);
82
+ }
83
+ return {
84
+ ok: false,
85
+ error: "Failed to claim local remote runtime ownership after clearing a stale lock."
86
+ };
87
+ }
88
+ function claimManagedRemoteRuntimeOwnership(params) {
89
+ const lockPath = params.lockPath ?? resolveRemoteOwnershipLockPath();
90
+ const currentPid = params.currentPid ?? process.pid;
91
+ const now = params.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
92
+ const isProcessRunningFn = params.isProcessRunningFn ?? isProcessRunning;
93
+ const managedConflict = detectManagedRemoteOwnershipConflict({
94
+ currentPid,
95
+ isProcessRunningFn,
96
+ readServiceStateFn: params.readServiceStateFn ?? managedServiceStateStore.read
97
+ });
98
+ if (managedConflict) return {
99
+ ok: false,
100
+ error: managedConflict
101
+ };
102
+ mkdirSync(dirname(lockPath), { recursive: true });
103
+ return tryClaimRemoteOwnershipLock({
104
+ lockPath,
105
+ claim: {
106
+ pid: currentPid,
107
+ localOrigin: params.localOrigin,
108
+ claimedAt: now()
109
+ },
110
+ currentPid,
111
+ isProcessRunningFn
112
+ });
113
+ }
114
+ function createManagedRemoteModule(params) {
115
+ if (!params.uiEnabled) return null;
116
+ return new RemoteServiceModule({
117
+ loadConfig: params.loadConfig,
118
+ uiEnabled: params.uiEnabled,
119
+ localOrigin: params.localOrigin,
120
+ statusStore: createNextclawRemoteStatusStore("service"),
121
+ createConnector: (logger) => createNextclawRemoteConnector({ logger }),
122
+ claimOwnership: () => claimManagedRemoteRuntimeOwnership({ localOrigin: params.localOrigin }),
123
+ logger: {
124
+ info: (message) => console.log(`[remote] ${message}`),
125
+ warn: (message) => console.warn(`[remote] ${message}`),
126
+ error: (message) => console.error(`[remote] ${message}`)
127
+ }
128
+ });
129
+ }
130
+ function createManagedRemoteModuleForUi(params) {
131
+ const explicitLocalOrigin = params.localOriginOverride?.trim() ?? process.env.NEXTCLAW_REMOTE_LOCAL_ORIGIN?.trim();
132
+ return createManagedRemoteModule({
133
+ loadConfig: params.loadConfig,
134
+ uiEnabled: params.uiConfig.enabled,
135
+ localOrigin: explicitLocalOrigin && explicitLocalOrigin.length > 0 ? explicitLocalOrigin.replace(/\/+$/, "") : resolveUiApiBase(params.uiConfig.host, params.uiConfig.port)
136
+ });
137
+ }
138
+ function writeInitialManagedServiceState(params) {
139
+ managedServiceStateStore.write({
140
+ pid: params.snapshot.pid,
141
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
142
+ uiUrl: params.snapshot.uiUrl,
143
+ apiUrl: params.snapshot.apiUrl,
144
+ uiHost: params.snapshot.uiHost,
145
+ uiPort: params.snapshot.uiPort,
146
+ logPath: params.snapshot.logPath,
147
+ startupLastProbeError: null,
148
+ startupTimeoutMs: params.readinessTimeoutMs,
149
+ startupCheckedAt: (/* @__PURE__ */ new Date()).toISOString(),
150
+ ...params.config.remote.enabled ? { remote: buildNextclawConfiguredRemoteState(params.config) } : {}
151
+ });
152
+ }
153
+ function writeReadyManagedServiceState(params) {
154
+ const currentState = managedServiceStateStore.read();
155
+ const state = {
156
+ pid: params.snapshot.pid,
157
+ startedAt: currentState?.startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
158
+ uiUrl: params.snapshot.uiUrl,
159
+ apiUrl: params.snapshot.apiUrl,
160
+ uiHost: params.snapshot.uiHost,
161
+ uiPort: params.snapshot.uiPort,
162
+ logPath: params.snapshot.logPath,
163
+ startupState: params.readiness.ready ? "ready" : "degraded",
164
+ startupLastProbeError: params.readiness.lastProbeError,
165
+ startupTimeoutMs: params.readinessTimeoutMs,
166
+ startupCheckedAt: (/* @__PURE__ */ new Date()).toISOString(),
167
+ ...currentState?.remote ? { remote: currentState.remote } : {}
168
+ };
169
+ managedServiceStateStore.write(state);
170
+ return state;
171
+ }
172
+ //#endregion
173
+ export { claimManagedRemoteRuntimeOwnership, createManagedRemoteModule, createManagedRemoteModuleForUi, writeInitialManagedServiceState, writeReadyManagedServiceState };
@@ -0,0 +1,12 @@
1
+ //#region src/shared/services/runtime/utils/skills-loader.utils.d.ts
2
+ type SkillInfo = {
3
+ name: string;
4
+ path: string;
5
+ source: "workspace" | "builtin";
6
+ };
7
+ type SkillsLoaderInstance = {
8
+ listSkills: (filterUnavailable?: boolean) => SkillInfo[];
9
+ };
10
+ declare function createSkillsLoader(workspace: string): SkillsLoaderInstance | null;
11
+ //#endregion
12
+ export { createSkillsLoader };
@@ -0,0 +1,9 @@
1
+ import * as NextclawCore from "@nextclaw/core";
2
+ //#region src/shared/services/runtime/utils/skills-loader.utils.ts
3
+ function createSkillsLoader(workspace) {
4
+ const ctor = NextclawCore.SkillsLoader;
5
+ if (!ctor) return null;
6
+ return new ctor(workspace);
7
+ }
8
+ //#endregion
9
+ export { createSkillsLoader };
@@ -0,0 +1,14 @@
1
+ import { UiNcpAgent } from "@nextclaw/server";
2
+ import { AgentRuntimeHandle } from "@nextclaw/kernel";
3
+
4
+ //#region src/shared/services/session/service-deferred-ncp-agent.service.d.ts
5
+ type DeferredUiNcpAgentController = {
6
+ agent: UiNcpAgent;
7
+ activate: (agent: AgentRuntimeHandle) => void;
8
+ clear: () => void;
9
+ close: () => Promise<void>;
10
+ isReady: () => boolean;
11
+ };
12
+ declare function createDeferredUiNcpAgent(basePath?: string): DeferredUiNcpAgentController;
13
+ //#endregion
14
+ export { DeferredUiNcpAgentController, createDeferredUiNcpAgent };