@nextclaw/service 0.1.18-beta.6 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/service-runtime.service.js +1 -1
- package/dist/service-runtime.service.js.map +1 -1
- package/dist/shared/controllers/gateway.controller.d.ts +2 -2
- package/dist/shared/controllers/gateway.controller.d.ts.map +1 -1
- package/dist/shared/controllers/gateway.controller.js +4 -4
- package/dist/shared/controllers/gateway.controller.js.map +1 -1
- package/dist/shared/services/gateway/gateway-restart-wake.service.d.ts.map +1 -1
- package/dist/shared/services/gateway/gateway-restart-wake.service.js +12 -7
- package/dist/shared/services/gateway/gateway-restart-wake.service.js.map +1 -1
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts +2 -3
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts.map +1 -1
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js +1 -1
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js.map +1 -1
- package/dist/shared/{services/restart/restart-sentinel.service.d.ts → utils/restart/restart-sentinel.utils.d.ts} +3 -6
- package/dist/shared/utils/restart/restart-sentinel.utils.d.ts.map +1 -0
- package/dist/shared/{services/restart/restart-sentinel.service.js → utils/restart/restart-sentinel.utils.js} +3 -17
- package/dist/shared/utils/restart/restart-sentinel.utils.js.map +1 -0
- package/package.json +25 -25
- package/dist/shared/services/restart/restart-sentinel.service.d.ts.map +0 -1
- package/dist/shared/services/restart/restart-sentinel.service.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RestartCoordinator } from "./shared/services/restart/restart-coordinator.service.js";
|
|
2
2
|
import { initializeConfigIfMissing } from "./shared/services/runtime/runtime-config-init.service.js";
|
|
3
|
-
import { writeRestartSentinel } from "./shared/
|
|
3
|
+
import { writeRestartSentinel } from "./shared/utils/restart/restart-sentinel.utils.js";
|
|
4
4
|
import { createTopLevelNextclawCommandEnv } from "./shared/utils/top-level-nextclaw-command-env.utils.js";
|
|
5
5
|
import { resolveCliSubcommandLaunch } from "./shared/utils/marketplace/cli-subcommand-launch.utils.js";
|
|
6
6
|
import { logStartupTrace, measureStartupSync } from "./shared/utils/startup-trace.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-runtime.service.js","names":[],"sources":["../src/service-runtime.service.ts"],"sourcesContent":["import { loadConfig, getConfigPath, getDataDir, resolveWorkspacePath, APP_NAME } from \"@nextclaw/core\";\nimport { NextclawKernel } from \"@nextclaw/kernel\";\nimport { RemoteRuntimeActions } from \"@nextclaw/remote\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { RestartCoordinator } from \"@nextclaw-service/shared/services/restart/restart-coordinator.service.js\";\nimport type { RestartStrategy } from \"@nextclaw-service/shared/services/restart/restart-coordinator.service.js\";\nimport { initializeConfigIfMissing } from \"@nextclaw-service/shared/services/runtime/runtime-config-init.service.js\";\nimport { writeRestartSentinel } from \"@nextclaw-service/shared/services/restart/restart-sentinel.service.js\";\nimport { createTopLevelNextclawCommandEnv } from \"@nextclaw-service/shared/utils/top-level-nextclaw-command-env.utils.js\";\nimport { resolveCliSubcommandLaunch } from \"@nextclaw-service/shared/utils/marketplace/cli-subcommand-launch.utils.js\";\nimport { logStartupTrace, measureStartupSync } from \"@nextclaw-service/shared/utils/startup-trace.js\";\nimport { isProcessRunning } from \"@nextclaw-service/shared/utils/cli.utils.js\";\nimport { NpmRuntimeUpdateCommandService } from \"@nextclaw-service/launcher/npm-runtime-update-command.service.js\";\nimport { NpmRuntimeLauncher } from \"@nextclaw-service/launcher/npm-runtime-launcher.service.js\";\nimport { managedServiceStateStore } from \"@nextclaw-service/shared/stores/managed-service-state.store.js\";\nimport { ConfigCommands } from \"@nextclaw-service/cli/commands/config/index.js\";\nimport { McpCommands } from \"@nextclaw-service/cli/commands/mcp/index.js\";\nimport { SecretsCommands } from \"@nextclaw-service/cli/commands/secrets/index.js\";\nimport { ChannelCommands } from \"@nextclaw-service/commands/channel/index.js\";\nimport { CronCommands } from \"@nextclaw-service/cli/commands/cron/index.js\";\nimport { AgentCommands, runCliAgentCommand } from \"@nextclaw-service/cli/commands/agent/index.js\";\nimport { PlatformAuthCommands } from \"@nextclaw-service/commands/platform-auth/index.js\";\nimport { RemoteCommands, hasRunningNextclawManagedService } from \"@nextclaw-service/commands/remote/index.js\";\nimport { DiagnosticsCommands } from \"@nextclaw-service/cli/commands/diagnostics/index.js\";\nimport { LogsCommands } from \"@nextclaw-service/cli/commands/logs/index.js\";\nimport { RuntimeCommandService } from \"@nextclaw-service/shared/services/runtime/runtime-command.service.js\";\nimport { NextclawDistributionService } from \"@nextclaw-service/shared/services/runtime/nextclaw-distribution.service.js\";\nimport { ServiceCommands } from \"@nextclaw-service/commands/service/index.js\";\nimport { WorkspaceManager } from \"@nextclaw-service/shared/services/workspace/workspace-manager.service.js\";\nimport { RuntimeRestartRequestService } from \"@nextclaw-service/shared/services/restart/runtime-restart-request.service.js\";\nimport { SkillsCommands } from \"@nextclaw-service/cli/commands/skills/index.js\";\nimport { GatewayCommands } from \"@nextclaw-service/cli/commands/gateway/index.js\";\nimport { UiCommands } from \"@nextclaw-service/cli/commands/ui/index.js\";\nimport { StartCommands } from \"@nextclaw-service/cli/commands/start/index.js\";\nimport { RestartCommands } from \"@nextclaw-service/cli/commands/restart/index.js\";\nimport { ServeCommands } from \"@nextclaw-service/cli/commands/serve/index.js\";\nimport { StopCommands } from \"@nextclaw-service/cli/commands/stop/index.js\";\nimport { LlmUsageCommandService } from \"@nextclaw-service/cli/commands/usage/index.js\";\nimport type { AgentCommandOptions, LoginCommandOptions, RequestRestartParams, UpdateCommandOptions } from \"@nextclaw-service/shared/types/cli.types.js\";\nconst FORCED_PUBLIC_UI_HOST = \"0.0.0.0\";\n\nexport type NextclawServiceRuntimeOptions = {\n logo?: string;\n};\n\nexport type NextclawServiceRuntimeAccount = {\n status: (opts?: { apiBase?: string; json?: boolean }) => Promise<void>;\n setUsername: (\n username: string,\n opts?: { apiBase?: string; json?: boolean },\n ) => Promise<void>;\n};\n\nexport type NextclawServiceCommands = {\n remote: RemoteRuntimeActions;\n skills: SkillsCommands;\n service: ServiceCommands;\n config: ConfigCommands;\n mcp: McpCommands;\n secrets: SecretsCommands;\n agents: AgentCommands;\n channels: ChannelCommands;\n cron: CronCommands;\n diagnostics: DiagnosticsCommands;\n logs: LogsCommands;\n gateway: GatewayCommands;\n ui: UiCommands;\n start: StartCommands;\n restart: RestartCommands;\n serve: ServeCommands;\n stop: StopCommands;\n usage: LlmUsageCommandService;\n};\n\nexport class NextclawServiceRuntime {\n private logo: string;\n private restartCoordinator: RestartCoordinator;\n private serviceRestartTask: Promise<boolean> | null = null;\n private selfRelaunchArmed = false;\n private restartRequestService: RuntimeRestartRequestService;\n private workspaceManager: WorkspaceManager;\n private runtimeCommandService: RuntimeCommandService;\n private platformAuthCommands!: PlatformAuthCommands;\n private remoteCommands!: RemoteCommands;\n account: NextclawServiceRuntimeAccount;\n commands: NextclawServiceCommands;\n constructor(options: NextclawServiceRuntimeOptions) {\n logStartupTrace(\"cli.runtime.constructor.begin\");\n this.logo = options.logo ?? \"🤖\";\n this.workspaceManager = measureStartupSync(\"cli.runtime.workspace_manager\", () => new WorkspaceManager());\n this.runtimeCommandService = measureStartupSync(\"cli.runtime.runtime_command_service\", () => new RuntimeCommandService({\n requestRestart: (params) => this.requestRestart(params),\n initializeAgentHomeDirectory: (homeDirectory) => this.workspaceManager.createWorkspaceTemplates(homeDirectory)\n }));\n this.commands = this.createCommands();\n\n this.restartCoordinator = measureStartupSync(\"cli.runtime.restart_coordinator\", () => new RestartCoordinator({\n readServiceState: managedServiceStateStore.read,\n isProcessRunning,\n currentPid: () => process.pid,\n restartBackgroundService: async (reason) =>\n this.restartBackgroundService(reason),\n scheduleProcessExit: (delayMs, reason) =>\n this.scheduleProcessExit(delayMs, reason),\n }));\n this.restartRequestService = new RuntimeRestartRequestService({\n armManagedServiceRelaunch: (params) => this.armManagedServiceRelaunch(params),\n requestRestartFromCoordinator: async (params) =>\n await this.restartCoordinator.requestRestart(params)\n });\n this.account = {\n status: async (opts = {}) => {\n await this.init({ source: \"account status\", auto: true });\n await this.platformAuthCommands.accountStatus(opts);\n },\n setUsername: async (username, opts = {}) => {\n await this.init({ source: \"account set-username\", auto: true });\n await this.platformAuthCommands.accountSetUsername({\n apiBase: opts.apiBase,\n json: opts.json,\n username\n });\n },\n };\n logStartupTrace(\"cli.runtime.constructor.end\");\n }\n\n private createCommands = (): NextclawServiceCommands => {\n const start = measureStartupSync(\"cli.runtime.start_commands\", () => new StartCommands({\n runtimeCommandService: this.runtimeCommandService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST,\n init: (params) => this.init(params)\n }));\n this.platformAuthCommands = measureStartupSync(\"cli.runtime.platform_auth_commands\", () => new PlatformAuthCommands());\n this.remoteCommands = measureStartupSync(\"cli.runtime.remote_commands\", () => new RemoteCommands());\n return {\n remote: measureStartupSync(\"cli.runtime.remote_runtime_actions\", () => new RemoteRuntimeActions({\n appName: APP_NAME,\n initAuto: (source) => this.init({ source, auto: true }),\n remoteCommands: this.remoteCommands,\n restartBackgroundService: (reason) => this.restartBackgroundService(reason),\n hasRunningManagedService: hasRunningNextclawManagedService\n })),\n skills: measureStartupSync(\"cli.runtime.skills_commands\", () => new SkillsCommands()),\n service: measureStartupSync(\"cli.runtime.service_commands\", () => new ServiceCommands()),\n config: measureStartupSync(\"cli.runtime.config_commands\", () => new ConfigCommands({\n requestRestart: (params) => this.requestRestart(params),\n })),\n mcp: measureStartupSync(\"cli.runtime.mcp_commands\", () => new McpCommands()),\n secrets: measureStartupSync(\"cli.runtime.secrets_commands\", () => new SecretsCommands({\n requestRestart: (params) => this.requestRestart(params),\n })),\n agents: measureStartupSync(\"cli.runtime.agent_commands\", () => new AgentCommands({\n initializeAgentHomeDirectory: (homeDirectory) => this.workspaceManager.createWorkspaceTemplates(homeDirectory)\n })),\n channels: measureStartupSync(\"cli.runtime.channel_commands\", () => new ChannelCommands({\n requestRestart: (params) => this.requestRestart(params),\n })),\n cron: measureStartupSync(\"cli.runtime.cron_commands\", () => new CronCommands()),\n diagnostics: measureStartupSync(\"cli.runtime.diagnostics_commands\", () => new DiagnosticsCommands({ logo: this.logo })),\n logs: measureStartupSync(\"cli.runtime.logs_commands\", () => new LogsCommands()),\n gateway: measureStartupSync(\"cli.runtime.gateway_commands\", () => new GatewayCommands({\n runtimeCommandService: this.runtimeCommandService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n })),\n ui: measureStartupSync(\"cli.runtime.ui_commands\", () => new UiCommands({\n runtimeCommandService: this.runtimeCommandService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n })),\n start,\n restart: measureStartupSync(\"cli.runtime.restart_commands\", () => new RestartCommands({\n runtimeCommandService: this.runtimeCommandService,\n startCommands: start,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST,\n writeRestartSentinelFromExecContext: (reason) => this.writeRestartSentinelFromExecContext(reason)\n })),\n serve: measureStartupSync(\"cli.runtime.serve_commands\", () => new ServeCommands({\n runtimeCommandService: this.runtimeCommandService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n })),\n stop: measureStartupSync(\"cli.runtime.stop_commands\", () => new StopCommands({\n runtimeCommandService: this.runtimeCommandService\n })),\n usage: measureStartupSync(\"cli.runtime.usage_commands\", () => new LlmUsageCommandService()),\n };\n };\n\n get version(): string {\n return NextclawDistributionService.get().version;\n }\n\n private scheduleProcessExit = (delayMs: number, reason: string): void => {\n console.warn(`Gateway restart requested (${reason}).`);\n setTimeout(() => {\n process.exit(0);\n }, delayMs);\n };\n\n private restartBackgroundService = async (reason: string): Promise<boolean> => {\n if (this.serviceRestartTask) {\n return this.serviceRestartTask;\n }\n\n this.serviceRestartTask = (async () => {\n const state = managedServiceStateStore.read();\n if (!state || !isProcessRunning(state.pid) || state.pid === process.pid) {\n return false;\n }\n\n const uiHost = FORCED_PUBLIC_UI_HOST;\n const uiPort =\n typeof state.uiPort === \"number\" && Number.isFinite(state.uiPort)\n ? state.uiPort\n : 55667;\n\n console.log(\n `Applying changes (${reason}): restarting ${APP_NAME} background service...`,\n );\n await this.runtimeCommandService.stopService();\n await this.runtimeCommandService.startService({\n uiOverrides: {\n enabled: true,\n host: uiHost,\n port: uiPort,\n },\n open: false,\n });\n return true;\n })();\n\n try {\n return await this.serviceRestartTask;\n } finally {\n this.serviceRestartTask = null;\n }\n };\n\n private armManagedServiceRelaunch = (params: {\n reason: string;\n strategy?: RestartStrategy;\n delayMs?: number;\n }): void => {\n const { delayMs: requestedDelayMs, reason, strategy: requestedStrategy } = params;\n const strategy = requestedStrategy ?? \"background-service-or-manual\";\n if (\n strategy !== \"background-service-or-exit\" &&\n strategy !== \"exit-process\"\n ) {\n return;\n }\n if (this.selfRelaunchArmed) {\n return;\n }\n\n const state = managedServiceStateStore.read();\n if (!state || state.pid !== process.pid) {\n return;\n }\n\n const uiPort =\n typeof state.uiPort === \"number\" && Number.isFinite(state.uiPort)\n ? state.uiPort\n : 55667;\n const delayMs =\n typeof requestedDelayMs === \"number\" && Number.isFinite(requestedDelayMs)\n ? Math.max(0, Math.floor(requestedDelayMs))\n : 100;\n const launch = resolveCliSubcommandLaunch({\n argvEntry: process.argv[1],\n importMetaUrl: import.meta.url,\n cliArgs: [\"start\", \"--ui-port\", String(uiPort)],\n nodePath: process.execPath\n });\n const serviceStatePath = managedServiceStateStore.path;\n const helperScript = [\n 'const { spawnSync } = require(\"node:child_process\");',\n 'const { readFileSync } = require(\"node:fs\");',\n `const parentPid = ${process.pid};`,\n `const delayMs = ${delayMs};`,\n \"const maxWaitMs = 120000;\",\n \"const retryIntervalMs = 1000;\",\n `const command = ${JSON.stringify(launch.command)};`,\n `const args = ${JSON.stringify(launch.args)};`,\n `const serviceStatePath = ${JSON.stringify(serviceStatePath)};`,\n \"function isRunning(pid) {\",\n \" try {\",\n \" process.kill(pid, 0);\",\n \" return true;\",\n \" } catch {\",\n \" return false;\",\n \" }\",\n \"}\",\n \"function hasReplacementService() {\",\n \" try {\",\n ' const raw = readFileSync(serviceStatePath, \"utf-8\");',\n \" const state = JSON.parse(raw);\",\n \" const pid = Number(state?.pid);\",\n \" return Number.isFinite(pid) && pid > 0 && pid !== parentPid && isRunning(pid);\",\n \" } catch {\",\n \" return false;\",\n \" }\",\n \"}\",\n \"function tryStart() {\",\n \" spawnSync(command, args, {\",\n ' stdio: \"ignore\",',\n \" env: process.env,\",\n \" timeout: 60000,\",\n \" windowsHide: true\",\n \" });\",\n \"}\",\n \"setTimeout(() => {\",\n \" const startedAt = Date.now();\",\n \" const tick = () => {\",\n \" if (hasReplacementService() || Date.now() - startedAt >= maxWaitMs) {\",\n \" process.exit(0);\",\n \" return;\",\n \" }\",\n \" tryStart();\",\n \" if (hasReplacementService()) {\",\n \" process.exit(0);\",\n \" return;\",\n \" }\",\n \" setTimeout(tick, retryIntervalMs);\",\n \" };\",\n \" tick();\",\n \"}, delayMs);\",\n ].join(\"\\n\");\n\n try {\n const helper = spawn(process.execPath, [\"-e\", helperScript], {\n detached: true,\n stdio: \"ignore\",\n env: createTopLevelNextclawCommandEnv(process.env),\n windowsHide: true\n });\n helper.unref();\n this.selfRelaunchArmed = true;\n console.warn(`Gateway self-restart armed (${reason}).`);\n } catch (error) {\n console.error(`Failed to arm gateway self-restart: ${String(error)}`);\n }\n };\n\n private requestRestart = async (params: RequestRestartParams): Promise<void> => {\n await this.restartRequestService.run(params);\n };\n\n private writeRestartSentinelFromExecContext = async (reason: string): Promise<void> => {\n const sessionKeyRaw = process.env.NEXTCLAW_RUNTIME_SESSION_KEY;\n const sessionKey =\n typeof sessionKeyRaw === \"string\" ? sessionKeyRaw.trim() : \"\";\n if (!sessionKey) {\n return;\n }\n\n try {\n await writeRestartSentinel({\n kind: \"restart\",\n status: \"ok\",\n ts: Date.now(),\n sessionKey,\n stats: {\n reason: reason || \"cli.restart\",\n strategy: \"exec-tool\",\n },\n });\n } catch (error) {\n console.warn(\n `Warning: failed to write restart sentinel from exec context: ${String(error)}`,\n );\n }\n };\n\n onboard = async (): Promise<void> => {\n console.warn(\n `Warning: ${APP_NAME} onboard is deprecated. Use \"${APP_NAME} init\" instead.`,\n );\n await this.init({ source: \"onboard\" });\n };\n\n init = async (options: { source?: string; auto?: boolean; force?: boolean } = {}): Promise<void> => {\n const source = options.source ?? \"init\";\n const prefix = options.auto ? \"Auto init\" : \"Init\";\n const force = Boolean(options.force);\n\n const configPath = getConfigPath();\n const createdConfig = initializeConfigIfMissing(configPath);\n\n const config = loadConfig();\n const workspacePath = resolveWorkspacePath(config.agents.defaults.workspace);\n const workspaceExisted = existsSync(workspacePath);\n mkdirSync(workspacePath, { recursive: true });\n const templateResult = this.workspaceManager.createWorkspaceTemplates(\n workspacePath,\n { force },\n );\n\n if (createdConfig) {\n console.log(`✓ ${prefix}: created config at ${configPath}`);\n }\n if (!workspaceExisted) {\n console.log(`✓ ${prefix}: created workspace at ${workspacePath}`);\n }\n for (const file of templateResult.created) {\n console.log(`✓ ${prefix}: created ${file}`);\n }\n if (\n !createdConfig &&\n workspaceExisted &&\n templateResult.created.length === 0\n ) {\n console.log(`${prefix}: already initialized.`);\n }\n\n if (!options.auto) {\n console.log(`\\n${this.logo} ${APP_NAME} is ready! (${source})`);\n console.log(\"\\nNext steps:\");\n console.log(` 1. Add your API key to ${configPath}`);\n console.log(` 2. Chat: ${APP_NAME} agent -m \"Hello!\"`);\n } else {\n console.log(\n `Tip: Run \"${APP_NAME} init${force ? \" --force\" : \"\"}\" to re-run initialization if needed.`,\n );\n }\n };\n\n login = async (opts: LoginCommandOptions = {}): Promise<void> => {\n await this.init({ source: \"login\", auto: true });\n await this.platformAuthCommands.login(opts);\n };\n\n agent = async (opts: AgentCommandOptions): Promise<void> => {\n const configPath = getConfigPath();\n const kernel = new NextclawKernel({\n homeDir: getDataDir(),\n configPath,\n });\n const config = kernel.configManager.config;\n\n await runCliAgentCommand({\n logo: this.logo,\n opts,\n config,\n kernel,\n });\n };\n\n update = async (opts: UpdateCommandOptions): Promise<void> => {\n const versionBefore = this.version;\n if (!opts.json) {\n const installationLabel = process.env.NEXTCLAW_DESKTOP_COMMAND_SURFACE === \"1\" ? \"desktop runtime\" : \"npm launcher\";\n console.log(`Current ${installationLabel} version: ${versionBefore}`);\n }\n const snapshot = await new NpmRuntimeUpdateCommandService().run(opts);\n if (snapshot.status === \"blocked\" || snapshot.status === \"failed\") {\n process.exit(1);\n }\n\n const state = managedServiceStateStore.read();\n if (snapshot.requiresRestart && state && isProcessRunning(state.pid)) {\n console.log(`Tip: restart ${APP_NAME} to apply the update.`);\n }\n };\n}\n\nexport const runNextclawNpmRuntimeLauncher = (\n argv: string[] = process.argv,\n): void => {\n const distribution = NextclawDistributionService.get();\n new NpmRuntimeLauncher({\n argv,\n launcherVersion: distribution.version,\n packagedAppEntrypoint: distribution.appEntrypoint,\n }).run();\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service-runtime.service.js","names":[],"sources":["../src/service-runtime.service.ts"],"sourcesContent":["import { loadConfig, getConfigPath, getDataDir, resolveWorkspacePath, APP_NAME } from \"@nextclaw/core\";\nimport { NextclawKernel } from \"@nextclaw/kernel\";\nimport { RemoteRuntimeActions } from \"@nextclaw/remote\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { RestartCoordinator } from \"@nextclaw-service/shared/services/restart/restart-coordinator.service.js\";\nimport type { RestartStrategy } from \"@nextclaw-service/shared/services/restart/restart-coordinator.service.js\";\nimport { initializeConfigIfMissing } from \"@nextclaw-service/shared/services/runtime/runtime-config-init.service.js\";\nimport { writeRestartSentinel } from \"@nextclaw-service/shared/utils/restart/restart-sentinel.utils.js\";\nimport { createTopLevelNextclawCommandEnv } from \"@nextclaw-service/shared/utils/top-level-nextclaw-command-env.utils.js\";\nimport { resolveCliSubcommandLaunch } from \"@nextclaw-service/shared/utils/marketplace/cli-subcommand-launch.utils.js\";\nimport { logStartupTrace, measureStartupSync } from \"@nextclaw-service/shared/utils/startup-trace.js\";\nimport { isProcessRunning } from \"@nextclaw-service/shared/utils/cli.utils.js\";\nimport { NpmRuntimeUpdateCommandService } from \"@nextclaw-service/launcher/npm-runtime-update-command.service.js\";\nimport { NpmRuntimeLauncher } from \"@nextclaw-service/launcher/npm-runtime-launcher.service.js\";\nimport { managedServiceStateStore } from \"@nextclaw-service/shared/stores/managed-service-state.store.js\";\nimport { ConfigCommands } from \"@nextclaw-service/cli/commands/config/index.js\";\nimport { McpCommands } from \"@nextclaw-service/cli/commands/mcp/index.js\";\nimport { SecretsCommands } from \"@nextclaw-service/cli/commands/secrets/index.js\";\nimport { ChannelCommands } from \"@nextclaw-service/commands/channel/index.js\";\nimport { CronCommands } from \"@nextclaw-service/cli/commands/cron/index.js\";\nimport { AgentCommands, runCliAgentCommand } from \"@nextclaw-service/cli/commands/agent/index.js\";\nimport { PlatformAuthCommands } from \"@nextclaw-service/commands/platform-auth/index.js\";\nimport { RemoteCommands, hasRunningNextclawManagedService } from \"@nextclaw-service/commands/remote/index.js\";\nimport { DiagnosticsCommands } from \"@nextclaw-service/cli/commands/diagnostics/index.js\";\nimport { LogsCommands } from \"@nextclaw-service/cli/commands/logs/index.js\";\nimport { RuntimeCommandService } from \"@nextclaw-service/shared/services/runtime/runtime-command.service.js\";\nimport { NextclawDistributionService } from \"@nextclaw-service/shared/services/runtime/nextclaw-distribution.service.js\";\nimport { ServiceCommands } from \"@nextclaw-service/commands/service/index.js\";\nimport { WorkspaceManager } from \"@nextclaw-service/shared/services/workspace/workspace-manager.service.js\";\nimport { RuntimeRestartRequestService } from \"@nextclaw-service/shared/services/restart/runtime-restart-request.service.js\";\nimport { SkillsCommands } from \"@nextclaw-service/cli/commands/skills/index.js\";\nimport { GatewayCommands } from \"@nextclaw-service/cli/commands/gateway/index.js\";\nimport { UiCommands } from \"@nextclaw-service/cli/commands/ui/index.js\";\nimport { StartCommands } from \"@nextclaw-service/cli/commands/start/index.js\";\nimport { RestartCommands } from \"@nextclaw-service/cli/commands/restart/index.js\";\nimport { ServeCommands } from \"@nextclaw-service/cli/commands/serve/index.js\";\nimport { StopCommands } from \"@nextclaw-service/cli/commands/stop/index.js\";\nimport { LlmUsageCommandService } from \"@nextclaw-service/cli/commands/usage/index.js\";\nimport type { AgentCommandOptions, LoginCommandOptions, RequestRestartParams, UpdateCommandOptions } from \"@nextclaw-service/shared/types/cli.types.js\";\nconst FORCED_PUBLIC_UI_HOST = \"0.0.0.0\";\n\nexport type NextclawServiceRuntimeOptions = {\n logo?: string;\n};\n\nexport type NextclawServiceRuntimeAccount = {\n status: (opts?: { apiBase?: string; json?: boolean }) => Promise<void>;\n setUsername: (\n username: string,\n opts?: { apiBase?: string; json?: boolean },\n ) => Promise<void>;\n};\n\nexport type NextclawServiceCommands = {\n remote: RemoteRuntimeActions;\n skills: SkillsCommands;\n service: ServiceCommands;\n config: ConfigCommands;\n mcp: McpCommands;\n secrets: SecretsCommands;\n agents: AgentCommands;\n channels: ChannelCommands;\n cron: CronCommands;\n diagnostics: DiagnosticsCommands;\n logs: LogsCommands;\n gateway: GatewayCommands;\n ui: UiCommands;\n start: StartCommands;\n restart: RestartCommands;\n serve: ServeCommands;\n stop: StopCommands;\n usage: LlmUsageCommandService;\n};\n\nexport class NextclawServiceRuntime {\n private logo: string;\n private restartCoordinator: RestartCoordinator;\n private serviceRestartTask: Promise<boolean> | null = null;\n private selfRelaunchArmed = false;\n private restartRequestService: RuntimeRestartRequestService;\n private workspaceManager: WorkspaceManager;\n private runtimeCommandService: RuntimeCommandService;\n private platformAuthCommands!: PlatformAuthCommands;\n private remoteCommands!: RemoteCommands;\n account: NextclawServiceRuntimeAccount;\n commands: NextclawServiceCommands;\n constructor(options: NextclawServiceRuntimeOptions) {\n logStartupTrace(\"cli.runtime.constructor.begin\");\n this.logo = options.logo ?? \"🤖\";\n this.workspaceManager = measureStartupSync(\"cli.runtime.workspace_manager\", () => new WorkspaceManager());\n this.runtimeCommandService = measureStartupSync(\"cli.runtime.runtime_command_service\", () => new RuntimeCommandService({\n requestRestart: (params) => this.requestRestart(params),\n initializeAgentHomeDirectory: (homeDirectory) => this.workspaceManager.createWorkspaceTemplates(homeDirectory)\n }));\n this.commands = this.createCommands();\n\n this.restartCoordinator = measureStartupSync(\"cli.runtime.restart_coordinator\", () => new RestartCoordinator({\n readServiceState: managedServiceStateStore.read,\n isProcessRunning,\n currentPid: () => process.pid,\n restartBackgroundService: async (reason) =>\n this.restartBackgroundService(reason),\n scheduleProcessExit: (delayMs, reason) =>\n this.scheduleProcessExit(delayMs, reason),\n }));\n this.restartRequestService = new RuntimeRestartRequestService({\n armManagedServiceRelaunch: (params) => this.armManagedServiceRelaunch(params),\n requestRestartFromCoordinator: async (params) =>\n await this.restartCoordinator.requestRestart(params)\n });\n this.account = {\n status: async (opts = {}) => {\n await this.init({ source: \"account status\", auto: true });\n await this.platformAuthCommands.accountStatus(opts);\n },\n setUsername: async (username, opts = {}) => {\n await this.init({ source: \"account set-username\", auto: true });\n await this.platformAuthCommands.accountSetUsername({\n apiBase: opts.apiBase,\n json: opts.json,\n username\n });\n },\n };\n logStartupTrace(\"cli.runtime.constructor.end\");\n }\n\n private createCommands = (): NextclawServiceCommands => {\n const start = measureStartupSync(\"cli.runtime.start_commands\", () => new StartCommands({\n runtimeCommandService: this.runtimeCommandService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST,\n init: (params) => this.init(params)\n }));\n this.platformAuthCommands = measureStartupSync(\"cli.runtime.platform_auth_commands\", () => new PlatformAuthCommands());\n this.remoteCommands = measureStartupSync(\"cli.runtime.remote_commands\", () => new RemoteCommands());\n return {\n remote: measureStartupSync(\"cli.runtime.remote_runtime_actions\", () => new RemoteRuntimeActions({\n appName: APP_NAME,\n initAuto: (source) => this.init({ source, auto: true }),\n remoteCommands: this.remoteCommands,\n restartBackgroundService: (reason) => this.restartBackgroundService(reason),\n hasRunningManagedService: hasRunningNextclawManagedService\n })),\n skills: measureStartupSync(\"cli.runtime.skills_commands\", () => new SkillsCommands()),\n service: measureStartupSync(\"cli.runtime.service_commands\", () => new ServiceCommands()),\n config: measureStartupSync(\"cli.runtime.config_commands\", () => new ConfigCommands({\n requestRestart: (params) => this.requestRestart(params),\n })),\n mcp: measureStartupSync(\"cli.runtime.mcp_commands\", () => new McpCommands()),\n secrets: measureStartupSync(\"cli.runtime.secrets_commands\", () => new SecretsCommands({\n requestRestart: (params) => this.requestRestart(params),\n })),\n agents: measureStartupSync(\"cli.runtime.agent_commands\", () => new AgentCommands({\n initializeAgentHomeDirectory: (homeDirectory) => this.workspaceManager.createWorkspaceTemplates(homeDirectory)\n })),\n channels: measureStartupSync(\"cli.runtime.channel_commands\", () => new ChannelCommands({\n requestRestart: (params) => this.requestRestart(params),\n })),\n cron: measureStartupSync(\"cli.runtime.cron_commands\", () => new CronCommands()),\n diagnostics: measureStartupSync(\"cli.runtime.diagnostics_commands\", () => new DiagnosticsCommands({ logo: this.logo })),\n logs: measureStartupSync(\"cli.runtime.logs_commands\", () => new LogsCommands()),\n gateway: measureStartupSync(\"cli.runtime.gateway_commands\", () => new GatewayCommands({\n runtimeCommandService: this.runtimeCommandService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n })),\n ui: measureStartupSync(\"cli.runtime.ui_commands\", () => new UiCommands({\n runtimeCommandService: this.runtimeCommandService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n })),\n start,\n restart: measureStartupSync(\"cli.runtime.restart_commands\", () => new RestartCommands({\n runtimeCommandService: this.runtimeCommandService,\n startCommands: start,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST,\n writeRestartSentinelFromExecContext: (reason) => this.writeRestartSentinelFromExecContext(reason)\n })),\n serve: measureStartupSync(\"cli.runtime.serve_commands\", () => new ServeCommands({\n runtimeCommandService: this.runtimeCommandService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n })),\n stop: measureStartupSync(\"cli.runtime.stop_commands\", () => new StopCommands({\n runtimeCommandService: this.runtimeCommandService\n })),\n usage: measureStartupSync(\"cli.runtime.usage_commands\", () => new LlmUsageCommandService()),\n };\n };\n\n get version(): string {\n return NextclawDistributionService.get().version;\n }\n\n private scheduleProcessExit = (delayMs: number, reason: string): void => {\n console.warn(`Gateway restart requested (${reason}).`);\n setTimeout(() => {\n process.exit(0);\n }, delayMs);\n };\n\n private restartBackgroundService = async (reason: string): Promise<boolean> => {\n if (this.serviceRestartTask) {\n return this.serviceRestartTask;\n }\n\n this.serviceRestartTask = (async () => {\n const state = managedServiceStateStore.read();\n if (!state || !isProcessRunning(state.pid) || state.pid === process.pid) {\n return false;\n }\n\n const uiHost = FORCED_PUBLIC_UI_HOST;\n const uiPort =\n typeof state.uiPort === \"number\" && Number.isFinite(state.uiPort)\n ? state.uiPort\n : 55667;\n\n console.log(\n `Applying changes (${reason}): restarting ${APP_NAME} background service...`,\n );\n await this.runtimeCommandService.stopService();\n await this.runtimeCommandService.startService({\n uiOverrides: {\n enabled: true,\n host: uiHost,\n port: uiPort,\n },\n open: false,\n });\n return true;\n })();\n\n try {\n return await this.serviceRestartTask;\n } finally {\n this.serviceRestartTask = null;\n }\n };\n\n private armManagedServiceRelaunch = (params: {\n reason: string;\n strategy?: RestartStrategy;\n delayMs?: number;\n }): void => {\n const { delayMs: requestedDelayMs, reason, strategy: requestedStrategy } = params;\n const strategy = requestedStrategy ?? \"background-service-or-manual\";\n if (\n strategy !== \"background-service-or-exit\" &&\n strategy !== \"exit-process\"\n ) {\n return;\n }\n if (this.selfRelaunchArmed) {\n return;\n }\n\n const state = managedServiceStateStore.read();\n if (!state || state.pid !== process.pid) {\n return;\n }\n\n const uiPort =\n typeof state.uiPort === \"number\" && Number.isFinite(state.uiPort)\n ? state.uiPort\n : 55667;\n const delayMs =\n typeof requestedDelayMs === \"number\" && Number.isFinite(requestedDelayMs)\n ? Math.max(0, Math.floor(requestedDelayMs))\n : 100;\n const launch = resolveCliSubcommandLaunch({\n argvEntry: process.argv[1],\n importMetaUrl: import.meta.url,\n cliArgs: [\"start\", \"--ui-port\", String(uiPort)],\n nodePath: process.execPath\n });\n const serviceStatePath = managedServiceStateStore.path;\n const helperScript = [\n 'const { spawnSync } = require(\"node:child_process\");',\n 'const { readFileSync } = require(\"node:fs\");',\n `const parentPid = ${process.pid};`,\n `const delayMs = ${delayMs};`,\n \"const maxWaitMs = 120000;\",\n \"const retryIntervalMs = 1000;\",\n `const command = ${JSON.stringify(launch.command)};`,\n `const args = ${JSON.stringify(launch.args)};`,\n `const serviceStatePath = ${JSON.stringify(serviceStatePath)};`,\n \"function isRunning(pid) {\",\n \" try {\",\n \" process.kill(pid, 0);\",\n \" return true;\",\n \" } catch {\",\n \" return false;\",\n \" }\",\n \"}\",\n \"function hasReplacementService() {\",\n \" try {\",\n ' const raw = readFileSync(serviceStatePath, \"utf-8\");',\n \" const state = JSON.parse(raw);\",\n \" const pid = Number(state?.pid);\",\n \" return Number.isFinite(pid) && pid > 0 && pid !== parentPid && isRunning(pid);\",\n \" } catch {\",\n \" return false;\",\n \" }\",\n \"}\",\n \"function tryStart() {\",\n \" spawnSync(command, args, {\",\n ' stdio: \"ignore\",',\n \" env: process.env,\",\n \" timeout: 60000,\",\n \" windowsHide: true\",\n \" });\",\n \"}\",\n \"setTimeout(() => {\",\n \" const startedAt = Date.now();\",\n \" const tick = () => {\",\n \" if (hasReplacementService() || Date.now() - startedAt >= maxWaitMs) {\",\n \" process.exit(0);\",\n \" return;\",\n \" }\",\n \" tryStart();\",\n \" if (hasReplacementService()) {\",\n \" process.exit(0);\",\n \" return;\",\n \" }\",\n \" setTimeout(tick, retryIntervalMs);\",\n \" };\",\n \" tick();\",\n \"}, delayMs);\",\n ].join(\"\\n\");\n\n try {\n const helper = spawn(process.execPath, [\"-e\", helperScript], {\n detached: true,\n stdio: \"ignore\",\n env: createTopLevelNextclawCommandEnv(process.env),\n windowsHide: true\n });\n helper.unref();\n this.selfRelaunchArmed = true;\n console.warn(`Gateway self-restart armed (${reason}).`);\n } catch (error) {\n console.error(`Failed to arm gateway self-restart: ${String(error)}`);\n }\n };\n\n private requestRestart = async (params: RequestRestartParams): Promise<void> => {\n await this.restartRequestService.run(params);\n };\n\n private writeRestartSentinelFromExecContext = async (reason: string): Promise<void> => {\n const sessionKeyRaw = process.env.NEXTCLAW_RUNTIME_SESSION_KEY;\n const sessionKey =\n typeof sessionKeyRaw === \"string\" ? sessionKeyRaw.trim() : \"\";\n if (!sessionKey) {\n return;\n }\n\n try {\n await writeRestartSentinel({\n kind: \"restart\",\n status: \"ok\",\n ts: Date.now(),\n sessionKey,\n stats: {\n reason: reason || \"cli.restart\",\n strategy: \"exec-tool\",\n },\n });\n } catch (error) {\n console.warn(\n `Warning: failed to write restart sentinel from exec context: ${String(error)}`,\n );\n }\n };\n\n onboard = async (): Promise<void> => {\n console.warn(\n `Warning: ${APP_NAME} onboard is deprecated. Use \"${APP_NAME} init\" instead.`,\n );\n await this.init({ source: \"onboard\" });\n };\n\n init = async (options: { source?: string; auto?: boolean; force?: boolean } = {}): Promise<void> => {\n const source = options.source ?? \"init\";\n const prefix = options.auto ? \"Auto init\" : \"Init\";\n const force = Boolean(options.force);\n\n const configPath = getConfigPath();\n const createdConfig = initializeConfigIfMissing(configPath);\n\n const config = loadConfig();\n const workspacePath = resolveWorkspacePath(config.agents.defaults.workspace);\n const workspaceExisted = existsSync(workspacePath);\n mkdirSync(workspacePath, { recursive: true });\n const templateResult = this.workspaceManager.createWorkspaceTemplates(\n workspacePath,\n { force },\n );\n\n if (createdConfig) {\n console.log(`✓ ${prefix}: created config at ${configPath}`);\n }\n if (!workspaceExisted) {\n console.log(`✓ ${prefix}: created workspace at ${workspacePath}`);\n }\n for (const file of templateResult.created) {\n console.log(`✓ ${prefix}: created ${file}`);\n }\n if (\n !createdConfig &&\n workspaceExisted &&\n templateResult.created.length === 0\n ) {\n console.log(`${prefix}: already initialized.`);\n }\n\n if (!options.auto) {\n console.log(`\\n${this.logo} ${APP_NAME} is ready! (${source})`);\n console.log(\"\\nNext steps:\");\n console.log(` 1. Add your API key to ${configPath}`);\n console.log(` 2. Chat: ${APP_NAME} agent -m \"Hello!\"`);\n } else {\n console.log(\n `Tip: Run \"${APP_NAME} init${force ? \" --force\" : \"\"}\" to re-run initialization if needed.`,\n );\n }\n };\n\n login = async (opts: LoginCommandOptions = {}): Promise<void> => {\n await this.init({ source: \"login\", auto: true });\n await this.platformAuthCommands.login(opts);\n };\n\n agent = async (opts: AgentCommandOptions): Promise<void> => {\n const configPath = getConfigPath();\n const kernel = new NextclawKernel({\n homeDir: getDataDir(),\n configPath,\n });\n const config = kernel.configManager.config;\n\n await runCliAgentCommand({\n logo: this.logo,\n opts,\n config,\n kernel,\n });\n };\n\n update = async (opts: UpdateCommandOptions): Promise<void> => {\n const versionBefore = this.version;\n if (!opts.json) {\n const installationLabel = process.env.NEXTCLAW_DESKTOP_COMMAND_SURFACE === \"1\" ? \"desktop runtime\" : \"npm launcher\";\n console.log(`Current ${installationLabel} version: ${versionBefore}`);\n }\n const snapshot = await new NpmRuntimeUpdateCommandService().run(opts);\n if (snapshot.status === \"blocked\" || snapshot.status === \"failed\") {\n process.exit(1);\n }\n\n const state = managedServiceStateStore.read();\n if (snapshot.requiresRestart && state && isProcessRunning(state.pid)) {\n console.log(`Tip: restart ${APP_NAME} to apply the update.`);\n }\n };\n}\n\nexport const runNextclawNpmRuntimeLauncher = (\n argv: string[] = process.argv,\n): void => {\n const distribution = NextclawDistributionService.get();\n new NpmRuntimeLauncher({\n argv,\n launcherVersion: distribution.version,\n packagedAppEntrypoint: distribution.appEntrypoint,\n }).run();\n};\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CronService, GatewayController
|
|
2
|
-
import { ChannelManager, ConfigManager } from "@nextclaw/kernel";
|
|
1
|
+
import { CronService, GatewayController } from "@nextclaw/core";
|
|
2
|
+
import { ChannelManager, ConfigManager, SessionManager } from "@nextclaw/kernel";
|
|
3
3
|
|
|
4
4
|
//#region src/shared/controllers/gateway.controller.d.ts
|
|
5
5
|
type ControllerDeps = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.controller.d.ts","names":[],"sources":["../../../src/shared/controllers/gateway.controller.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"gateway.controller.d.ts","names":[],"sources":["../../../src/shared/controllers/gateway.controller.ts"],"mappings":";;;;KAaK,cAAA;EACH,aAAA,EAAe,aAAA;EACf,QAAA,EAAU,cAAA;EACV,IAAA,EAAM,WAAA;EACN,cAAA,GAAiB,cAAA;EACjB,cAAA,IAAkB,OAAA;IAAY,OAAA;IAAkB,MAAA;EAAA,MAAsB,OAAA;AAAA;AAAA,cAG3D,qBAAA,YAAiC,iBAAA;EAAA,QACxB,IAAA;cAAA,IAAA,EAAM,cAAA;EAAA,QAElB,uBAAA;EAAA,QAQA,sBAAA;EAAA,QAgDA,2BAAA;EAAA,QA6BA,cAAA;EAcR,MAAA,QAAa,MAAA;EAQb,YAAA,GAAsB,MAAA,cAAkB,OAAA;EAIxC,OAAA,GAAiB,OAAA;IAAY,OAAA;IAAkB,MAAA;IAAiB,UAAA;EAAA,MAAwB,OAAA;EAWxF,SAAA,QAAsB,OAAA,CAAQ,MAAA;EAI9B,eAAA,QAA4B,OAAA,CAAQ,MAAA;EAIpC,WAAA,GAAqB,MAAA;IACnB,GAAA;IACA,QAAA;IACA,IAAA;IACA,cAAA;IACA,UAAA;EAAA,MACE,OAAA,CAAQ,MAAA;EASZ,WAAA,GAAqB,MAAA;IACnB,GAAA;IACA,QAAA;IACA,IAAA;IACA,cAAA;IACA,UAAA;EAAA,MACE,OAAA,CAAQ,MAAA;EASZ,SAAA,GAAmB,MAAA;IACjB,IAAA;IACA,cAAA;IACA,SAAA;IACA,UAAA;EAAA,MACE,OAAA,CAAQ,MAAA;AAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseSessionKey, writeRestartSentinel } from "../
|
|
1
|
+
import { parseSessionKey, writeRestartSentinel } from "../utils/restart/restart-sentinel.utils.js";
|
|
2
2
|
import { getPackageVersion as getPackageVersion$1 } from "../utils/package/package-manifest.utils.js";
|
|
3
3
|
import "../utils/cli.utils.js";
|
|
4
4
|
import { NpmRuntimeUpdateCommandService } from "../../launcher/npm-runtime-update-command.service.js";
|
|
@@ -12,11 +12,11 @@ var GatewayControllerImpl = class {
|
|
|
12
12
|
if (typeof value !== "string") return;
|
|
13
13
|
return value.trim() || void 0;
|
|
14
14
|
};
|
|
15
|
-
resolveDeliveryContext = (sessionKey) => {
|
|
15
|
+
resolveDeliveryContext = async (sessionKey) => {
|
|
16
16
|
const normalizedSessionKey = this.normalizeOptionalString(sessionKey);
|
|
17
17
|
const keyTarget = parseSessionKey(normalizedSessionKey);
|
|
18
18
|
const keyRoute = keyTarget && keyTarget.channel !== "agent" ? keyTarget : null;
|
|
19
|
-
const metadata = (normalizedSessionKey ? this.deps.sessionManager?.
|
|
19
|
+
const metadata = (normalizedSessionKey ? await this.deps.sessionManager?.getSessionRecord(normalizedSessionKey) : null)?.metadata ?? {};
|
|
20
20
|
const rawContext = metadata.last_delivery_context;
|
|
21
21
|
const cachedContext = rawContext && typeof rawContext === "object" && !Array.isArray(rawContext) ? rawContext : null;
|
|
22
22
|
const cachedMetadataRaw = cachedContext?.metadata;
|
|
@@ -38,7 +38,7 @@ var GatewayControllerImpl = class {
|
|
|
38
38
|
writeRestartSentinelPayload = async (params) => {
|
|
39
39
|
const { kind, note, reason, sessionKey: rawSessionKey, status, strategy } = params;
|
|
40
40
|
const sessionKey = this.normalizeOptionalString(rawSessionKey);
|
|
41
|
-
const deliveryContext = this.resolveDeliveryContext(sessionKey);
|
|
41
|
+
const deliveryContext = await this.resolveDeliveryContext(sessionKey);
|
|
42
42
|
try {
|
|
43
43
|
return await writeRestartSentinel({
|
|
44
44
|
kind,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.controller.js","names":["getPackageVersion"],"sources":["../../../src/shared/controllers/gateway.controller.ts"],"sourcesContent":["import {\n type GatewayController,\n type CronService,\n type SessionManager\n} from \"@nextclaw/core\";\nimport type { ChannelManager, ConfigManager } from \"@nextclaw/kernel\";\nimport { getPackageVersion } from \"../utils/cli.utils.js\";\nimport { NpmRuntimeUpdateCommandService } from \"@nextclaw-service/launcher/npm-runtime-update-command.service.js\";\nimport {\n parseSessionKey,\n type RestartSentinelDeliveryContext,\n writeRestartSentinel\n} from \"../services/restart/restart-sentinel.service.js\";\n\ntype ControllerDeps = {\n configManager: ConfigManager;\n channels: ChannelManager;\n cron: CronService;\n sessionManager?: SessionManager;\n requestRestart?: (options?: { delayMs?: number; reason?: string }) => Promise<void> | void;\n};\n\nexport class GatewayControllerImpl implements GatewayController {\n constructor(private deps: ControllerDeps) {}\n\n private normalizeOptionalString = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n };\n\n private resolveDeliveryContext = (sessionKey?: string): RestartSentinelDeliveryContext | undefined => {\n const normalizedSessionKey = this.normalizeOptionalString(sessionKey);\n const keyTarget = parseSessionKey(normalizedSessionKey);\n const keyRoute = keyTarget && keyTarget.channel !== \"agent\" ? keyTarget : null;\n const session = normalizedSessionKey ? this.deps.sessionManager?.getIfExists(normalizedSessionKey) : null;\n const metadata = session?.metadata ?? {};\n const rawContext = metadata.last_delivery_context;\n const cachedContext =\n rawContext && typeof rawContext === \"object\" && !Array.isArray(rawContext)\n ? (rawContext as Record<string, unknown>)\n : null;\n const cachedMetadataRaw = cachedContext?.metadata;\n const cachedMetadata =\n cachedMetadataRaw && typeof cachedMetadataRaw === \"object\" && !Array.isArray(cachedMetadataRaw)\n ? ({ ...(cachedMetadataRaw as Record<string, unknown>) } as Record<string, unknown>)\n : {};\n\n const channel = this.normalizeOptionalString(cachedContext?.channel) ?? keyRoute?.channel;\n const chatId =\n this.normalizeOptionalString(cachedContext?.chatId) ??\n this.normalizeOptionalString(metadata.last_to) ??\n keyRoute?.chatId;\n const replyTo =\n this.normalizeOptionalString(cachedContext?.replyTo) ??\n this.normalizeOptionalString(metadata.last_message_id);\n const accountId =\n this.normalizeOptionalString(cachedContext?.accountId) ??\n this.normalizeOptionalString(metadata.last_account_id);\n\n if (!channel || !chatId) {\n return undefined;\n }\n\n if (accountId && !this.normalizeOptionalString(cachedMetadata.accountId)) {\n cachedMetadata.accountId = accountId;\n }\n\n return {\n channel,\n chatId,\n ...(replyTo ? { replyTo } : {}),\n ...(accountId ? { accountId } : {}),\n ...(Object.keys(cachedMetadata).length > 0 ? { metadata: cachedMetadata } : {})\n };\n };\n\n private writeRestartSentinelPayload = async (params: {\n kind: \"config.apply\" | \"config.patch\" | \"update.run\" | \"restart\";\n status: \"ok\" | \"error\" | \"skipped\";\n sessionKey?: string;\n note?: string;\n reason?: string;\n strategy?: string;\n }): Promise<string | null> => {\n const { kind, note, reason, sessionKey: rawSessionKey, status, strategy } = params;\n const sessionKey = this.normalizeOptionalString(rawSessionKey);\n const deliveryContext = this.resolveDeliveryContext(sessionKey);\n try {\n return await writeRestartSentinel({\n kind,\n status,\n ts: Date.now(),\n sessionKey,\n deliveryContext,\n message: note ?? null,\n stats: {\n reason: reason ?? null,\n strategy: strategy ?? null\n }\n });\n } catch {\n return null;\n }\n };\n\n private requestRestart = async (options?: { delayMs?: number; reason?: string }): Promise<void> => {\n const { delayMs, reason } = options ?? {};\n if (this.deps.requestRestart) {\n await this.deps.requestRestart(options);\n return;\n }\n const delay =\n typeof delayMs === \"number\" && Number.isFinite(delayMs) ? Math.max(0, delayMs) : 100;\n console.log(`Gateway restart requested via tool${reason ? ` (${reason})` : \"\"}.`);\n setTimeout(() => {\n process.exit(0);\n }, delay);\n };\n\n status = (): Record<string, unknown> => {\n return {\n channels: this.deps.channels.enabledChannels,\n cron: this.deps.cron.status(),\n configPath: this.deps.configManager.configPath\n };\n };\n\n reloadConfig = async (reason?: string): Promise<string> => {\n return this.deps.configManager.reloadConfig(reason);\n };\n\n restart = async (options?: { delayMs?: number; reason?: string; sessionKey?: string }): Promise<string> => {\n await this.writeRestartSentinelPayload({\n kind: \"restart\",\n status: \"ok\",\n sessionKey: options?.sessionKey,\n reason: options?.reason ?? \"gateway.restart\"\n });\n await this.requestRestart(options);\n return \"Restart scheduled\";\n };\n\n getConfig = async (): Promise<Record<string, unknown>> => {\n return this.deps.configManager.getConfigSnapshot({ version: getPackageVersion() });\n };\n\n getConfigSchema = async (): Promise<Record<string, unknown>> => {\n return this.deps.configManager.getConfigSchema({ version: getPackageVersion() });\n };\n\n applyConfig = async (params: {\n raw: string;\n baseHash?: string;\n note?: string;\n restartDelayMs?: number;\n sessionKey?: string;\n }): Promise<Record<string, unknown>> => {\n return this.deps.configManager.applyRawConfig({\n raw: params.raw,\n baseHash: params.baseHash,\n note: params.note,\n version: getPackageVersion()\n });\n };\n\n patchConfig = async (params: {\n raw: string;\n baseHash?: string;\n note?: string;\n restartDelayMs?: number;\n sessionKey?: string;\n }): Promise<Record<string, unknown>> => {\n return this.deps.configManager.patchRawConfig({\n raw: params.raw,\n baseHash: params.baseHash,\n note: params.note,\n version: getPackageVersion()\n });\n };\n\n updateRun = async (params: {\n note?: string;\n restartDelayMs?: number;\n timeoutMs?: number;\n sessionKey?: string;\n }): Promise<Record<string, unknown>> => {\n const { note, restartDelayMs, sessionKey, timeoutMs } = params;\n const versionBefore = getPackageVersion();\n void timeoutMs;\n const snapshot = await new NpmRuntimeUpdateCommandService().runManaged({});\n if (snapshot.status === \"blocked\" || snapshot.status === \"failed\") {\n return {\n ok: false,\n error: snapshot.errorMessage ?? snapshot.blockReason ?? \"update failed\",\n snapshot,\n version: {\n before: versionBefore,\n after: getPackageVersion(),\n changed: false\n }\n };\n }\n\n const versionAfter = getPackageVersion();\n const delayMs = restartDelayMs ?? 0;\n const sentinelPath = await this.writeRestartSentinelPayload({\n kind: \"update.run\",\n status: \"ok\",\n sessionKey,\n note,\n reason: \"update.run\",\n strategy: \"runtime-bundle\"\n });\n await this.requestRestart({ delayMs, reason: \"update.run\" });\n return {\n ok: true,\n note: note ?? null,\n restart: { scheduled: true, delayMs },\n strategy: \"runtime-bundle\",\n snapshot,\n version: {\n before: versionBefore,\n after: versionAfter,\n changed: versionBefore !== versionAfter\n },\n sentinel: sentinelPath ? { path: sentinelPath } : null\n };\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gateway.controller.js","names":["getPackageVersion"],"sources":["../../../src/shared/controllers/gateway.controller.ts"],"sourcesContent":["import {\n type GatewayController,\n type CronService,\n} from \"@nextclaw/core\";\nimport type { ChannelManager, ConfigManager, SessionManager } from \"@nextclaw/kernel\";\nimport { getPackageVersion } from \"../utils/cli.utils.js\";\nimport { NpmRuntimeUpdateCommandService } from \"@nextclaw-service/launcher/npm-runtime-update-command.service.js\";\nimport {\n parseSessionKey,\n type RestartSentinelDeliveryContext,\n writeRestartSentinel\n} from \"../utils/restart/restart-sentinel.utils.js\";\n\ntype ControllerDeps = {\n configManager: ConfigManager;\n channels: ChannelManager;\n cron: CronService;\n sessionManager?: SessionManager;\n requestRestart?: (options?: { delayMs?: number; reason?: string }) => Promise<void> | void;\n};\n\nexport class GatewayControllerImpl implements GatewayController {\n constructor(private deps: ControllerDeps) {}\n\n private normalizeOptionalString = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n };\n\n private resolveDeliveryContext = async (sessionKey?: string): Promise<RestartSentinelDeliveryContext | undefined> => {\n const normalizedSessionKey = this.normalizeOptionalString(sessionKey);\n const keyTarget = parseSessionKey(normalizedSessionKey);\n const keyRoute = keyTarget && keyTarget.channel !== \"agent\" ? keyTarget : null;\n const session = normalizedSessionKey\n ? await this.deps.sessionManager?.getSessionRecord(normalizedSessionKey)\n : null;\n const metadata = session?.metadata ?? {};\n const rawContext = metadata.last_delivery_context;\n const cachedContext =\n rawContext && typeof rawContext === \"object\" && !Array.isArray(rawContext)\n ? (rawContext as Record<string, unknown>)\n : null;\n const cachedMetadataRaw = cachedContext?.metadata;\n const cachedMetadata =\n cachedMetadataRaw && typeof cachedMetadataRaw === \"object\" && !Array.isArray(cachedMetadataRaw)\n ? ({ ...(cachedMetadataRaw as Record<string, unknown>) } as Record<string, unknown>)\n : {};\n\n const channel = this.normalizeOptionalString(cachedContext?.channel) ?? keyRoute?.channel;\n const chatId =\n this.normalizeOptionalString(cachedContext?.chatId) ??\n this.normalizeOptionalString(metadata.last_to) ??\n keyRoute?.chatId;\n const replyTo =\n this.normalizeOptionalString(cachedContext?.replyTo) ??\n this.normalizeOptionalString(metadata.last_message_id);\n const accountId =\n this.normalizeOptionalString(cachedContext?.accountId) ??\n this.normalizeOptionalString(metadata.last_account_id);\n\n if (!channel || !chatId) {\n return undefined;\n }\n\n if (accountId && !this.normalizeOptionalString(cachedMetadata.accountId)) {\n cachedMetadata.accountId = accountId;\n }\n\n return {\n channel,\n chatId,\n ...(replyTo ? { replyTo } : {}),\n ...(accountId ? { accountId } : {}),\n ...(Object.keys(cachedMetadata).length > 0 ? { metadata: cachedMetadata } : {})\n };\n };\n\n private writeRestartSentinelPayload = async (params: {\n kind: \"config.apply\" | \"config.patch\" | \"update.run\" | \"restart\";\n status: \"ok\" | \"error\" | \"skipped\";\n sessionKey?: string;\n note?: string;\n reason?: string;\n strategy?: string;\n }): Promise<string | null> => {\n const { kind, note, reason, sessionKey: rawSessionKey, status, strategy } = params;\n const sessionKey = this.normalizeOptionalString(rawSessionKey);\n const deliveryContext = await this.resolveDeliveryContext(sessionKey);\n try {\n return await writeRestartSentinel({\n kind,\n status,\n ts: Date.now(),\n sessionKey,\n deliveryContext,\n message: note ?? null,\n stats: {\n reason: reason ?? null,\n strategy: strategy ?? null\n }\n });\n } catch {\n return null;\n }\n };\n\n private requestRestart = async (options?: { delayMs?: number; reason?: string }): Promise<void> => {\n const { delayMs, reason } = options ?? {};\n if (this.deps.requestRestart) {\n await this.deps.requestRestart(options);\n return;\n }\n const delay =\n typeof delayMs === \"number\" && Number.isFinite(delayMs) ? Math.max(0, delayMs) : 100;\n console.log(`Gateway restart requested via tool${reason ? ` (${reason})` : \"\"}.`);\n setTimeout(() => {\n process.exit(0);\n }, delay);\n };\n\n status = (): Record<string, unknown> => {\n return {\n channels: this.deps.channels.enabledChannels,\n cron: this.deps.cron.status(),\n configPath: this.deps.configManager.configPath\n };\n };\n\n reloadConfig = async (reason?: string): Promise<string> => {\n return this.deps.configManager.reloadConfig(reason);\n };\n\n restart = async (options?: { delayMs?: number; reason?: string; sessionKey?: string }): Promise<string> => {\n await this.writeRestartSentinelPayload({\n kind: \"restart\",\n status: \"ok\",\n sessionKey: options?.sessionKey,\n reason: options?.reason ?? \"gateway.restart\"\n });\n await this.requestRestart(options);\n return \"Restart scheduled\";\n };\n\n getConfig = async (): Promise<Record<string, unknown>> => {\n return this.deps.configManager.getConfigSnapshot({ version: getPackageVersion() });\n };\n\n getConfigSchema = async (): Promise<Record<string, unknown>> => {\n return this.deps.configManager.getConfigSchema({ version: getPackageVersion() });\n };\n\n applyConfig = async (params: {\n raw: string;\n baseHash?: string;\n note?: string;\n restartDelayMs?: number;\n sessionKey?: string;\n }): Promise<Record<string, unknown>> => {\n return this.deps.configManager.applyRawConfig({\n raw: params.raw,\n baseHash: params.baseHash,\n note: params.note,\n version: getPackageVersion()\n });\n };\n\n patchConfig = async (params: {\n raw: string;\n baseHash?: string;\n note?: string;\n restartDelayMs?: number;\n sessionKey?: string;\n }): Promise<Record<string, unknown>> => {\n return this.deps.configManager.patchRawConfig({\n raw: params.raw,\n baseHash: params.baseHash,\n note: params.note,\n version: getPackageVersion()\n });\n };\n\n updateRun = async (params: {\n note?: string;\n restartDelayMs?: number;\n timeoutMs?: number;\n sessionKey?: string;\n }): Promise<Record<string, unknown>> => {\n const { note, restartDelayMs, sessionKey, timeoutMs } = params;\n const versionBefore = getPackageVersion();\n void timeoutMs;\n const snapshot = await new NpmRuntimeUpdateCommandService().runManaged({});\n if (snapshot.status === \"blocked\" || snapshot.status === \"failed\") {\n return {\n ok: false,\n error: snapshot.errorMessage ?? snapshot.blockReason ?? \"update failed\",\n snapshot,\n version: {\n before: versionBefore,\n after: getPackageVersion(),\n changed: false\n }\n };\n }\n\n const versionAfter = getPackageVersion();\n const delayMs = restartDelayMs ?? 0;\n const sentinelPath = await this.writeRestartSentinelPayload({\n kind: \"update.run\",\n status: \"ok\",\n sessionKey,\n note,\n reason: \"update.run\",\n strategy: \"runtime-bundle\"\n });\n await this.requestRestart({ delayMs, reason: \"update.run\" });\n return {\n ok: true,\n note: note ?? null,\n restart: { scheduled: true, delayMs },\n strategy: \"runtime-bundle\",\n snapshot,\n version: {\n before: versionBefore,\n after: versionAfter,\n changed: versionBefore !== versionAfter\n },\n sentinel: sentinelPath ? { path: sentinelPath } : null\n };\n };\n}\n"],"mappings":";;;;;;AAqBA,IAAa,wBAAb,MAAgE;CAC9D,YAAY,MAA8B;AAAtB,OAAA,OAAA;;CAEpB,2BAAmC,UAAuC;AACxE,MAAI,OAAO,UAAU,SACnB;AAGF,SADgB,MAAM,MAAM,IACV,KAAA;;CAGpB,yBAAiC,OAAO,eAA6E;EACnH,MAAM,uBAAuB,KAAK,wBAAwB,WAAW;EACrE,MAAM,YAAY,gBAAgB,qBAAqB;EACvD,MAAM,WAAW,aAAa,UAAU,YAAY,UAAU,YAAY;EAI1E,MAAM,YAHU,uBACZ,MAAM,KAAK,KAAK,gBAAgB,iBAAiB,qBAAqB,GACtE,OACsB,YAAY,EAAE;EACxC,MAAM,aAAa,SAAS;EAC5B,MAAM,gBACJ,cAAc,OAAO,eAAe,YAAY,CAAC,MAAM,QAAQ,WAAW,GACrE,aACD;EACN,MAAM,oBAAoB,eAAe;EACzC,MAAM,iBACJ,qBAAqB,OAAO,sBAAsB,YAAY,CAAC,MAAM,QAAQ,kBAAkB,GAC1F,EAAE,GAAI,mBAA+C,GACtD,EAAE;EAER,MAAM,UAAU,KAAK,wBAAwB,eAAe,QAAQ,IAAI,UAAU;EAClF,MAAM,SACJ,KAAK,wBAAwB,eAAe,OAAO,IACnD,KAAK,wBAAwB,SAAS,QAAQ,IAC9C,UAAU;EACZ,MAAM,UACJ,KAAK,wBAAwB,eAAe,QAAQ,IACpD,KAAK,wBAAwB,SAAS,gBAAgB;EACxD,MAAM,YACJ,KAAK,wBAAwB,eAAe,UAAU,IACtD,KAAK,wBAAwB,SAAS,gBAAgB;AAExD,MAAI,CAAC,WAAW,CAAC,OACf;AAGF,MAAI,aAAa,CAAC,KAAK,wBAAwB,eAAe,UAAU,CACtE,gBAAe,YAAY;AAG7B,SAAO;GACL;GACA;GACA,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;GAC9B,GAAI,YAAY,EAAE,WAAW,GAAG,EAAE;GAClC,GAAI,OAAO,KAAK,eAAe,CAAC,SAAS,IAAI,EAAE,UAAU,gBAAgB,GAAG,EAAE;GAC/E;;CAGH,8BAAsC,OAAO,WAOf;EAC5B,MAAM,EAAE,MAAM,MAAM,QAAQ,YAAY,eAAe,QAAQ,aAAa;EAC5E,MAAM,aAAa,KAAK,wBAAwB,cAAc;EAC9D,MAAM,kBAAkB,MAAM,KAAK,uBAAuB,WAAW;AACrE,MAAI;AACF,UAAO,MAAM,qBAAqB;IAChC;IACA;IACA,IAAI,KAAK,KAAK;IACd;IACA;IACA,SAAS,QAAQ;IACjB,OAAO;KACL,QAAQ,UAAU;KAClB,UAAU,YAAY;KACvB;IACF,CAAC;UACI;AACN,UAAO;;;CAIX,iBAAyB,OAAO,YAAmE;EACjG,MAAM,EAAE,SAAS,WAAW,WAAW,EAAE;AACzC,MAAI,KAAK,KAAK,gBAAgB;AAC5B,SAAM,KAAK,KAAK,eAAe,QAAQ;AACvC;;EAEF,MAAM,QACJ,OAAO,YAAY,YAAY,OAAO,SAAS,QAAQ,GAAG,KAAK,IAAI,GAAG,QAAQ,GAAG;AACnF,UAAQ,IAAI,qCAAqC,SAAS,KAAK,OAAO,KAAK,GAAG,GAAG;AACjF,mBAAiB;AACf,WAAQ,KAAK,EAAE;KACd,MAAM;;CAGX,eAAwC;AACtC,SAAO;GACL,UAAU,KAAK,KAAK,SAAS;GAC7B,MAAM,KAAK,KAAK,KAAK,QAAQ;GAC7B,YAAY,KAAK,KAAK,cAAc;GACrC;;CAGH,eAAe,OAAO,WAAqC;AACzD,SAAO,KAAK,KAAK,cAAc,aAAa,OAAO;;CAGrD,UAAU,OAAO,YAA0F;AACzG,QAAM,KAAK,4BAA4B;GACrC,MAAM;GACN,QAAQ;GACR,YAAY,SAAS;GACrB,QAAQ,SAAS,UAAU;GAC5B,CAAC;AACF,QAAM,KAAK,eAAe,QAAQ;AAClC,SAAO;;CAGT,YAAY,YAA8C;AACxD,SAAO,KAAK,KAAK,cAAc,kBAAkB,EAAE,SAASA,qBAAmB,EAAE,CAAC;;CAGpF,kBAAkB,YAA8C;AAC9D,SAAO,KAAK,KAAK,cAAc,gBAAgB,EAAE,SAASA,qBAAmB,EAAE,CAAC;;CAGlF,cAAc,OAAO,WAMmB;AACtC,SAAO,KAAK,KAAK,cAAc,eAAe;GAC5C,KAAK,OAAO;GACZ,UAAU,OAAO;GACjB,MAAM,OAAO;GACb,SAASA,qBAAmB;GAC7B,CAAC;;CAGJ,cAAc,OAAO,WAMmB;AACtC,SAAO,KAAK,KAAK,cAAc,eAAe;GAC5C,KAAK,OAAO;GACZ,UAAU,OAAO;GACjB,MAAM,OAAO;GACb,SAASA,qBAAmB;GAC7B,CAAC;;CAGJ,YAAY,OAAO,WAKqB;EACtC,MAAM,EAAE,MAAM,gBAAgB,YAAY,cAAc;EACxD,MAAM,gBAAgBA,qBAAmB;EAEzC,MAAM,WAAW,MAAM,IAAI,gCAAgC,CAAC,WAAW,EAAE,CAAC;AAC1E,MAAI,SAAS,WAAW,aAAa,SAAS,WAAW,SACvD,QAAO;GACL,IAAI;GACJ,OAAO,SAAS,gBAAgB,SAAS,eAAe;GACxD;GACA,SAAS;IACP,QAAQ;IACR,OAAOA,qBAAmB;IAC1B,SAAS;IACV;GACF;EAGH,MAAM,eAAeA,qBAAmB;EACxC,MAAM,UAAU,kBAAkB;EAClC,MAAM,eAAe,MAAM,KAAK,4BAA4B;GAC1D,MAAM;GACN,QAAQ;GACR;GACA;GACA,QAAQ;GACR,UAAU;GACX,CAAC;AACF,QAAM,KAAK,eAAe;GAAE;GAAS,QAAQ;GAAc,CAAC;AAC5D,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ;GACd,SAAS;IAAE,WAAW;IAAM;IAAS;GACrC,UAAU;GACV;GACA,SAAS;IACP,QAAQ;IACR,OAAO;IACP,SAAS,kBAAkB;IAC5B;GACD,UAAU,eAAe,EAAE,MAAM,cAAc,GAAG;GACnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-restart-wake.service.d.ts","names":[],"sources":["../../../../src/shared/services/gateway/gateway-restart-wake.service.ts"],"mappings":";;;cAmBa,yBAAA;EAAA,iBACkB,OAAA;cAAA,OAAA,EAAS,sBAAA;EAEtC,uBAAA,QAAoC,OAAA;EAAA,
|
|
1
|
+
{"version":3,"file":"gateway-restart-wake.service.d.ts","names":[],"sources":["../../../../src/shared/services/gateway/gateway-restart-wake.service.ts"],"mappings":";;;cAmBa,yBAAA;EAAA,iBACkB,OAAA;cAAA,OAAA,EAAS,sBAAA;EAEtC,uBAAA,QAAoC,OAAA;EAAA,QA8D5B,mCAAA;EAAA,QAqBA,sBAAA;AAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { consumeRestartSentinel, formatRestartSentinelMessage, parseSessionKey } from "
|
|
1
|
+
import { consumeRestartSentinel, formatRestartSentinelMessage, parseSessionKey } from "../../utils/restart/restart-sentinel.utils.js";
|
|
2
2
|
import { resolveSessionRouteCandidate } from "../runtime/utils/managed-service-routing.utils.js";
|
|
3
3
|
import "../runtime/service-managed-startup.service.js";
|
|
4
4
|
import { parseAgentScopedSessionKey } from "@nextclaw/core";
|
|
@@ -18,15 +18,16 @@ var GatewayRestartWakeService = class {
|
|
|
18
18
|
const payload = sentinel.payload;
|
|
19
19
|
const summary = formatRestartSentinelMessage(payload);
|
|
20
20
|
const sentinelSessionKey = normalizeOptionalString(payload.sessionKey);
|
|
21
|
-
const fallbackSessionKey = sentinelSessionKey ? void 0 : this.resolveMostRecentRoutableSessionKey();
|
|
21
|
+
const fallbackSessionKey = sentinelSessionKey ? void 0 : await this.resolveMostRecentRoutableSessionKey();
|
|
22
22
|
if (!sentinelSessionKey && fallbackSessionKey) console.warn(`Warning: restart sentinel missing sessionKey; fallback to ${fallbackSessionKey}.`);
|
|
23
23
|
const sessionKey = sentinelSessionKey ?? fallbackSessionKey ?? "cli:default";
|
|
24
24
|
const parsedSession = parseSessionKey(sessionKey);
|
|
25
25
|
const parsedAgentSession = parseAgentScopedSessionKey(sessionKey);
|
|
26
26
|
const parsedSessionRoute = parsedSession && parsedSession.channel !== "agent" ? parsedSession : null;
|
|
27
27
|
const context = payload.deliveryContext;
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const fallbackMetadata = (await this.gateway.sessionManager.getSessionRecord(sessionKey))?.metadata ?? {};
|
|
29
|
+
const channel = normalizeOptionalString(context?.channel) ?? parsedSessionRoute?.channel ?? normalizeOptionalString(fallbackMetadata.last_channel);
|
|
30
|
+
const chatId = normalizeOptionalString(context?.chatId) ?? parsedSessionRoute?.chatId ?? normalizeOptionalString(fallbackMetadata.last_to);
|
|
30
31
|
const replyTo = normalizeOptionalString(context?.replyTo);
|
|
31
32
|
const accountId = normalizeOptionalString(context?.accountId);
|
|
32
33
|
if (!channel || !chatId) {
|
|
@@ -58,11 +59,15 @@ var GatewayRestartWakeService = class {
|
|
|
58
59
|
}
|
|
59
60
|
});
|
|
60
61
|
};
|
|
61
|
-
resolveMostRecentRoutableSessionKey = () => {
|
|
62
|
+
resolveMostRecentRoutableSessionKey = async () => {
|
|
62
63
|
let best = null;
|
|
63
|
-
for (const session of this.gateway.sessionManager.listSessions()) {
|
|
64
|
+
for (const session of await this.gateway.sessionManager.listSessions()) {
|
|
64
65
|
const candidate = resolveSessionRouteCandidate({
|
|
65
|
-
session
|
|
66
|
+
session: {
|
|
67
|
+
key: session.sessionId,
|
|
68
|
+
updated_at: session.updatedAt,
|
|
69
|
+
metadata: session.metadata
|
|
70
|
+
},
|
|
66
71
|
normalizeOptionalString
|
|
67
72
|
});
|
|
68
73
|
if (!candidate) continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-restart-wake.service.js","names":[],"sources":["../../../../src/shared/services/gateway/gateway-restart-wake.service.ts"],"sourcesContent":["import {\n parseAgentScopedSessionKey,\n} from \"@nextclaw/core\";\nimport type { NextclawGatewayRuntime } from \"@nextclaw-service/shared/services/gateway/nextclaw-gateway-runtime.service.js\";\nimport {\n consumeRestartSentinel,\n formatRestartSentinelMessage,\n parseSessionKey,\n} from \"@nextclaw-service/shared/
|
|
1
|
+
{"version":3,"file":"gateway-restart-wake.service.js","names":[],"sources":["../../../../src/shared/services/gateway/gateway-restart-wake.service.ts"],"sourcesContent":["import {\n parseAgentScopedSessionKey,\n} from \"@nextclaw/core\";\nimport type { NextclawGatewayRuntime } from \"@nextclaw-service/shared/services/gateway/nextclaw-gateway-runtime.service.js\";\nimport {\n consumeRestartSentinel,\n formatRestartSentinelMessage,\n parseSessionKey,\n} from \"@nextclaw-service/shared/utils/restart/restart-sentinel.utils.js\";\nimport { resolveSessionRouteCandidate } from \"@nextclaw-service/shared/services/runtime/service-managed-startup.service.js\";\n\nfunction normalizeOptionalString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nexport class GatewayRestartWakeService {\n constructor(private readonly gateway: NextclawGatewayRuntime) {}\n\n wakeFromRestartSentinel = async (): Promise<void> => {\n const sentinel = await consumeRestartSentinel();\n if (!sentinel) {\n return;\n }\n\n await new Promise((resolvePromise) => setTimeout(resolvePromise, 750));\n\n const payload = sentinel.payload;\n const summary = formatRestartSentinelMessage(payload);\n const sentinelSessionKey = normalizeOptionalString(payload.sessionKey);\n const fallbackSessionKey = sentinelSessionKey ? undefined : await this.resolveMostRecentRoutableSessionKey();\n if (!sentinelSessionKey && fallbackSessionKey) {\n console.warn(`Warning: restart sentinel missing sessionKey; fallback to ${fallbackSessionKey}.`);\n }\n const sessionKey = sentinelSessionKey ?? fallbackSessionKey ?? \"cli:default\";\n const parsedSession = parseSessionKey(sessionKey);\n const parsedAgentSession = parseAgentScopedSessionKey(sessionKey);\n const parsedSessionRoute = parsedSession && parsedSession.channel !== \"agent\" ? parsedSession : null;\n\n const context = payload.deliveryContext;\n const fallbackSession = await this.gateway.sessionManager.getSessionRecord(sessionKey);\n const fallbackMetadata = fallbackSession?.metadata ?? {};\n const channel =\n normalizeOptionalString(context?.channel) ??\n parsedSessionRoute?.channel ??\n normalizeOptionalString(fallbackMetadata.last_channel);\n const chatId =\n normalizeOptionalString(context?.chatId) ??\n parsedSessionRoute?.chatId ??\n normalizeOptionalString(fallbackMetadata.last_to);\n const replyTo = normalizeOptionalString(context?.replyTo);\n const accountId = normalizeOptionalString(context?.accountId);\n\n if (!channel || !chatId) {\n console.warn(`Warning: restart sentinel cannot resolve route for session ${sessionKey}.`);\n return;\n }\n\n await this.gateway.messageBus.publishInbound({\n channel: \"system\",\n senderId: \"restart-sentinel\",\n chatId: `${channel}:${chatId}`,\n content: this.buildRestartWakePrompt({\n summary,\n reason: normalizeOptionalString(payload.stats?.reason),\n note: normalizeOptionalString(payload.message),\n ...(replyTo ? { replyTo } : {}),\n }),\n timestamp: new Date(),\n attachments: [],\n metadata: {\n source: \"restart-sentinel\",\n restart_summary: summary,\n session_key_override: sessionKey,\n ...(replyTo ? { reply_to: replyTo } : {}),\n ...(parsedAgentSession ? { target_agent_id: parsedAgentSession.agentId } : {}),\n ...(accountId ? { account_id: accountId, accountId } : {}),\n },\n });\n };\n\n private resolveMostRecentRoutableSessionKey = async (): Promise<string | undefined> => {\n let best: { key: string; updatedAt: number } | null = null;\n for (const session of await this.gateway.sessionManager.listSessions()) {\n const candidate = resolveSessionRouteCandidate({\n session: {\n key: session.sessionId,\n updated_at: session.updatedAt,\n metadata: session.metadata,\n },\n normalizeOptionalString,\n });\n if (!candidate) {\n continue;\n }\n if (!best || candidate.updatedAt >= best.updatedAt) {\n best = candidate;\n }\n }\n return best?.key;\n };\n\n private buildRestartWakePrompt = (params: {\n summary: string;\n reason?: string;\n note?: string;\n replyTo?: string;\n }): string => {\n const { note, reason, replyTo, summary } = params;\n const lines = [\n \"System event: the gateway has restarted successfully.\",\n \"Please send one short confirmation to the user that you are back online.\",\n \"Do not call any tools.\",\n \"Use the same language as the user's recent conversation.\",\n `Reference summary: ${summary}`,\n ];\n\n const normalizedReason = normalizeOptionalString(reason);\n if (normalizedReason) {\n lines.push(`Restart reason: ${normalizedReason}`);\n }\n\n const normalizedNote = normalizeOptionalString(note);\n if (normalizedNote) {\n lines.push(`Extra note: ${normalizedNote}`);\n }\n\n const normalizedReplyTo = normalizeOptionalString(replyTo);\n if (normalizedReplyTo) {\n lines.push(`Reply target message id: ${normalizedReplyTo}. If suitable, include [[reply_to:${normalizedReplyTo}]].`);\n }\n\n return lines.join(\"\\n\");\n };\n}\n"],"mappings":"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"}
|
|
@@ -8,14 +8,13 @@ import { ServiceBootstrapStatusStore } from "./service-bootstrap-status.service.
|
|
|
8
8
|
import { ServiceFileWatcherRegistry } from "./service-startup-support.service.js";
|
|
9
9
|
import { GatewayRestartWakeService } from "./gateway-restart-wake.service.js";
|
|
10
10
|
import * as NextclawCore from "@nextclaw/core";
|
|
11
|
-
import { AgentRunClient, AutomationManager, ConfigManager, LlmProviderManager, NextclawKernel } from "@nextclaw/kernel";
|
|
11
|
+
import { AgentRunClient, AutomationManager, ConfigManager, LlmProviderManager, NextclawKernel, SessionManager } from "@nextclaw/kernel";
|
|
12
12
|
import { MarketplaceApiConfig, UiRuntimeControlHost, UiRuntimeUpdateHost } from "@nextclaw/server";
|
|
13
13
|
import { EventBus, Ingress } from "@nextclaw/shared";
|
|
14
14
|
|
|
15
15
|
//#region src/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts
|
|
16
16
|
type Config$1 = NextclawCore.Config;
|
|
17
17
|
type MessageBus$1 = NextclawCore.MessageBus;
|
|
18
|
-
type SessionManager$1 = NextclawCore.SessionManager;
|
|
19
18
|
type GatewayRuntimeOptions = {
|
|
20
19
|
uiOverrides?: Partial<Config$1["ui"]>;
|
|
21
20
|
uiStaticDir?: string | null;
|
|
@@ -40,7 +39,7 @@ declare class NextclawGatewayRuntime {
|
|
|
40
39
|
readonly kernel: NextclawKernel;
|
|
41
40
|
readonly appEventBus: EventBus;
|
|
42
41
|
readonly messageBus: MessageBus$1;
|
|
43
|
-
readonly sessionManager: SessionManager
|
|
42
|
+
readonly sessionManager: SessionManager;
|
|
44
43
|
readonly automation: AutomationManager;
|
|
45
44
|
readonly agentRunClient: AgentRunClient;
|
|
46
45
|
readonly runtimeControl: UiRuntimeControlHost;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextclaw-gateway-runtime.service.d.ts","names":[],"sources":["../../../../src/shared/services/gateway/nextclaw-gateway-runtime.service.ts"],"mappings":";;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"nextclaw-gateway-runtime.service.d.ts","names":[],"sources":["../../../../src/shared/services/gateway/nextclaw-gateway-runtime.service.ts"],"mappings":";;;;;;;;;;;;;;;KA6DK,QAAA,GAAS,YAAA,CAAa,MAAA;AAAA,KACtB,YAAA,GAAa,YAAA,CAAa,UAAA;AAAA,KAE1B,qBAAA;EACH,WAAA,GAAc,OAAA,CAAQ,QAAA;EACtB,WAAA;AAAA;AAAA,KAGU,kBAAA;EACV,cAAA,GAAiB,MAAA,EAAQ,oBAAA,KAAyB,OAAA;EAClD,4BAAA,GAA+B,aAAA;EAC/B,YAAA,GAAe,OAAA;IAAW,WAAA,EAAa,MAAA;IAAyB,IAAA;EAAA,MAAoB,OAAA;EACpF,WAAA,QAAmB,OAAA;EACnB,gBAAA,GAAmB,IAAA,eAAmB,OAAA;EACtC,8BAAA,GAAiC,IAAA,UAAc,KAAA;IAAiC,OAAA;IAAiB,MAAA;EAAA;AAAA;AAAA,cAGtF,sBAAA;EAAA,iBA6BQ,IAAA;EAAA,iBACA,OAAA;EAAA,SA7BV,MAAA,EAAQ,cAAA;EAAA,SACR,WAAA,EAAa,QAAA;EAAA,SACb,UAAA,EAAY,YAAA;EAAA,SACZ,cAAA,EAAgB,cAAA;EAAA,SAChB,UAAA,EAAY,iBAAA;EAAA,SACZ,cAAA,EAAgB,cAAA;EAAA,SAChB,cAAA,EAAgB,oBAAA;EAAA,SAChB,aAAA,EAAe,mBAAA;EAAA,SACf,OAAA,EAAS,OAAA;EAAA,SACT,YAAA,EADgB,oBAAA;EAAA,SAEhB,cAAA;EAAA,SACA,eAAA,EAAiB,kBAAA;EAAA,SACjB,iBAAA,EAAmB,qBAAA;EAAA,SAEnB,aAAA,EAAe,aAAA;EAAA,SACf,QAAA,EAAU,QAAA;EAAA,SACV,WAAA;EAAA,SACA,SAAA;EAAA,SACA,aAAA,EAAe,oBAAA;EAAA,SACf,WAAA,EAAa,oBAAA;EAAA,SACb,UAAA,EAAY,uBAAA;EAAA,SACZ,WAAA,EAAa,yBAAA;EACtB,eAAA,EAAiB,2BAAA;EACjB,SAAA,EAAW,eAAA;EAAA,SACF,YAAA,EAAY,0BAAA;EAAA,QACb,sBAAA;cAGW,IAAA,EAAM,kBAAA,EACN,OAAA,EAAS,qBAAA;EA6D5B,KAAA,QAAkB,OAAA;EAAA,QAaV,KAAA;EAAA,QAOA,qBAAA;EAAA,QAOA,uBAAA;EAAA,QAIA,cAAA;EAAA,QAiCA,qBAAA;EAAA,QAkBA,cAAA;EAAA,QAmBA,oBAAA;EAAA,SAKC,qBAAA,QAAkC,OAAA;EAAA,iBAI1B,aAAA;EAAA,QAWT,iBAAA;EAAA,QASA,OAAA;EAAA,QAOA,kBAAA;EAAA,QAKA,uBAAA;EAAA,QAqBA,oBAAA;EAAA,QAgBA,sBAAA;EAAA,QAiBA,wBAAA;AAAA"}
|
|
@@ -75,7 +75,7 @@ var NextclawGatewayRuntime = class {
|
|
|
75
75
|
ingress: this.kernel.ingress
|
|
76
76
|
});
|
|
77
77
|
this.messageBus = this.kernel.messageBus;
|
|
78
|
-
this.sessionManager = this.kernel.
|
|
78
|
+
this.sessionManager = this.kernel.sessionManager;
|
|
79
79
|
this.automation = this.kernel.automation;
|
|
80
80
|
this.productVersion = this.distribution.version;
|
|
81
81
|
this.extensions = new GatewayExtensionManager(this);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nextclaw-gateway-runtime.service.js","names":["getConfigPath","getDataDir","getWorkspacePath","waitForNextTick"],"sources":["../../../../src/shared/services/gateway/nextclaw-gateway-runtime.service.ts"],"sourcesContent":["import * as NextclawCore from \"@nextclaw/core\";\nimport {\n AgentRunClient,\n NextclawKernel,\n runGatewayInboundLoop,\n type AutomationManager,\n type ConfigManager,\n type LlmProviderManager,\n} from \"@nextclaw/kernel\";\nimport type { EventBus, Ingress } from \"@nextclaw/shared\";\nimport {\n startUiServer,\n type MarketplaceApiConfig,\n type UiRouterOptions,\n type UiRuntimeControlHost,\n type UiRuntimeUpdateHost,\n} from \"@nextclaw/server\";\nimport { resolve } from \"node:path\";\nimport { setImmediate as waitForNextTick } from \"node:timers/promises\";\nimport { GatewayControllerImpl } from \"@nextclaw-service/shared/controllers/gateway.controller.js\";\nimport { GatewayExtensionManager } from \"@nextclaw-service/shared/services/gateway/managers/gateway-extension.manager.js\";\nimport { GatewayRemoteManager } from \"@nextclaw-service/shared/services/gateway/managers/gateway-remote.manager.js\";\nimport { GatewayRestartWakeService } from \"@nextclaw-service/shared/services/gateway/gateway-restart-wake.service.js\";\nimport { createCronJobHandler } from \"@nextclaw-service/shared/services/gateway/utils/cron-job-handler.utils.js\";\nimport { companionRuntimeService } from \"@nextclaw-service/shared/services/ui/companion-runtime.service.js\";\nimport { handleGatewayDeferredStartupError } from \"@nextclaw-service/shared/services/gateway/utils/gateway-runtime-lifecycle.utils.js\";\nimport { NextclawApp, type UiStartupHandle } from \"@nextclaw-service/shared/services/gateway/nextclaw-app.service.js\";\nimport { NextclawDistributionService } from \"@nextclaw-service/shared/services/runtime/nextclaw-distribution.service.js\";\nimport { ServiceBootstrapStatusStore } from \"@nextclaw-service/shared/services/gateway/service-bootstrap-status.service.js\";\nimport { ServiceFileWatcherRegistry, markLocalUiRuntimeIfStarted, startGatewayRuntimeSupport, watchServiceConfigFile } from \"@nextclaw-service/shared/services/gateway/service-startup-support.service.js\";\nimport { ServiceMarketplaceInstaller } from \"@nextclaw-service/shared/services/marketplace/service-marketplace-installer.service.js\";\nimport { NpmRuntimeUpdateHost } from \"@nextclaw-service/shared/services/ui/npm-runtime-update-host.service.js\";\nimport { createRuntimeControlHost } from \"@nextclaw-service/shared/services/ui/runtime-control-host.service.js\";\nimport { localUiRuntimeStore } from \"@nextclaw-service/shared/stores/local-ui-runtime.store.js\";\nimport { managedServiceStateStore } from \"@nextclaw-service/shared/stores/managed-service-state.store.js\";\nimport type { RequestRestartParams } from \"@nextclaw-service/shared/types/cli.types.js\";\nimport { openBrowser, resolveUiConfig, resolveUiStaticDir } from \"@nextclaw-service/shared/utils/cli.utils.js\";\nimport { logStartupTrace, measureStartupAsync, measureStartupSync } from \"@nextclaw-service/shared/utils/startup-trace.js\";\n\nconst {\n getConfigPath,\n getDataDir,\n getWorkspacePath,\n} = NextclawCore;\n\nfunction resolveApplyRestartMode(uiPort: number): \"managed-service-restart\" | \"manual-process-restart\" {\n const serviceState = managedServiceStateStore.read();\n if (serviceState?.pid === process.pid) {\n return \"managed-service-restart\";\n }\n if (\n process.env.NEXTCLAW_RUNTIME_BUNDLE_CHILD === \"1\" &&\n typeof serviceState?.uiPort === \"number\" &&\n serviceState.uiPort === uiPort\n ) {\n return \"managed-service-restart\";\n }\n return \"manual-process-restart\";\n}\n\ntype Config = NextclawCore.Config;\ntype MessageBus = NextclawCore.MessageBus;\ntype SessionManager = NextclawCore.SessionManager;\n\ntype GatewayRuntimeOptions = {\n uiOverrides?: Partial<Config[\"ui\"]>;\n uiStaticDir?: string | null;\n};\n\nexport type GatewayRuntimeDeps = {\n requestRestart: (params: RequestRestartParams) => Promise<void>;\n initializeAgentHomeDirectory: (homeDirectory: string) => void;\n startService: (options: { uiOverrides: Record<string, unknown>; open: boolean }) => Promise<void>;\n stopService: () => Promise<void>;\n runCliSubcommand: (args: string[]) => Promise<string>;\n installBuiltinMarketplaceSkill: (slug: string, force: boolean | undefined) => { message: string; output?: string } | null;\n};\n\nexport class NextclawGatewayRuntime {\n readonly kernel: NextclawKernel;\n readonly appEventBus: EventBus;\n readonly messageBus: MessageBus;\n readonly sessionManager: SessionManager;\n readonly automation: AutomationManager;\n readonly agentRunClient: AgentRunClient;\n readonly runtimeControl: UiRuntimeControlHost;\n readonly runtimeUpdate: UiRuntimeUpdateHost | null;\n readonly ingress: Ingress;\n readonly distribution = NextclawDistributionService.get();\n readonly productVersion: string;\n readonly providerManager: LlmProviderManager;\n readonly gatewayController: GatewayControllerImpl;\n\n readonly configManager: ConfigManager;\n readonly uiConfig: Config[\"ui\"];\n readonly uiStaticDir: string | null;\n readonly workspace: string;\n readonly remoteManager: GatewayRemoteManager;\n readonly marketplace: MarketplaceApiConfig;\n readonly extensions: GatewayExtensionManager;\n readonly restartWake: GatewayRestartWakeService;\n bootstrapStatus: ServiceBootstrapStatusStore;\n uiStartup: UiStartupHandle;\n readonly fileWatchers = new ServiceFileWatcherRegistry();\n private deferredChannelStarter: () => Promise<void>;\n\n constructor(\n private readonly deps: GatewayRuntimeDeps,\n private readonly options: GatewayRuntimeOptions,\n ) {\n const configPath = getConfigPath();\n this.kernel = measureStartupSync(\n \"service.gateway.kernel\",\n () => new NextclawKernel({\n homeDir: getDataDir(),\n configPath,\n }),\n );\n this.configManager = this.kernel.configManager;\n const config = this.configManager.config;\n this.uiConfig = resolveUiConfig(config, options.uiOverrides);\n this.uiStaticDir = options.uiStaticDir === undefined ? resolveUiStaticDir(this.distribution.uiDistDir) : options.uiStaticDir;\n this.workspace = getWorkspacePath(config.agents.defaults.workspace);\n this.appEventBus = this.kernel.eventBus;\n this.ingress = this.kernel.ingress;\n this.agentRunClient = new AgentRunClient({\n eventBus: this.kernel.eventBus,\n ingress: this.kernel.ingress,\n });\n this.messageBus = this.kernel.messageBus;\n this.sessionManager = this.kernel.sessions;\n this.automation = this.kernel.automation;\n this.productVersion = this.distribution.version;\n this.extensions = new GatewayExtensionManager(this);\n this.providerManager = this.kernel.llmProviders;\n this.installConfigHostHooks();\n this.restartWake = new GatewayRestartWakeService(this);\n this.bootstrapStatus = this.createBootstrapStatus();\n this.uiStartup = this.createDisabledUiStartup();\n this.remoteManager = new GatewayRemoteManager({\n deps: this.deps,\n configManager: this.configManager,\n uiConfig: this.uiConfig,\n onRemoteStateChange: (state) => this.bootstrapStatus.syncRemoteRuntimeState(state),\n });\n this.marketplace = this.createMarketplace();\n this.runtimeControl = createRuntimeControlHost({\n serviceCommands: this.deps,\n requestRestart: this.deps.requestRestart,\n uiConfig: this.uiConfig,\n });\n this.runtimeUpdate =\n process.env.NEXTCLAW_DISABLE_RUNTIME_UPDATE_HOST === \"1\"\n ? null\n : new NpmRuntimeUpdateHost({\n eventBus: this.appEventBus,\n applyRestartMode: resolveApplyRestartMode(this.uiConfig.port),\n requestRestart: this.deps.requestRestart,\n uiConfig: this.uiConfig,\n });\n this.gatewayController = this.createGatewayController();\n this.kernel.provideGatewayController(this.gatewayController);\n this.deferredChannelStarter = this.startChannels;\n this.automation.onJob = createCronJobHandler({\n agentRunClient: this.agentRunClient,\n bus: this.messageBus,\n });\n }\n\n start = async (): Promise<void> => {\n logStartupTrace(\"service.start_gateway.begin\");\n await this.reset();\n this.configureIngressHandlers();\n this.uiStartup = await this.startUiRuntime();\n await companionRuntimeService.applyConfig(this.configManager.config);\n await this.markUiRuntimeReady();\n await this.startSupportServices();\n await this.runRuntimeLoop();\n await companionRuntimeService.ensureStopped();\n logStartupTrace(\"service.start_gateway.end\");\n };\n\n private reset = async (): Promise<void> => {\n await this.fileWatchers.clear();\n this.bootstrapStatus = this.createBootstrapStatus();\n this.uiStartup = this.createDisabledUiStartup();\n this.deferredChannelStarter = this.startChannels;\n };\n\n private createBootstrapStatus = (): ServiceBootstrapStatusStore => {\n const bootstrapStatus = new ServiceBootstrapStatusStore();\n bootstrapStatus.markChannelsPending();\n bootstrapStatus.setRemoteState(this.configManager.config.remote.enabled ? \"pending\" : \"disabled\");\n return bootstrapStatus;\n };\n\n private createDisabledUiStartup = (): UiStartupHandle => ({\n endpoint: \"\",\n });\n\n private startUiRuntime = async (): Promise<UiStartupHandle> => {\n const uiStartup = await measureStartupAsync(\"service.start_ui_runtime\", async () => {\n logStartupTrace(\"service.start_ui_runtime.begin\");\n if (!this.uiConfig.enabled) {\n return this.createDisabledUiStartup();\n }\n const uiServer = await startUiServer(this.createUiRouterOptions());\n const uiUrl = NextclawCore.resolveLocalUiBaseUrl({\n host: uiServer.host,\n port: uiServer.port,\n });\n console.log(`✓ UI API: ${uiUrl}/api`);\n if (this.uiStaticDir) {\n console.log(`✓ UI frontend: ${uiUrl}`);\n }\n if (this.uiConfig.open) {\n openBrowser(uiUrl);\n }\n logStartupTrace(\"service.start_ui_runtime.ready\", {\n host: uiServer.host,\n port: uiServer.port,\n });\n return {\n endpoint: uiUrl,\n };\n });\n markLocalUiRuntimeIfStarted({\n uiStartup: this.uiConfig.enabled ? uiStartup : null,\n uiConfig: this.uiConfig,\n });\n return uiStartup;\n };\n\n private createUiRouterOptions = (): UiRouterOptions => ({\n kernel: this.kernel,\n configPath: this.configManager.configPath,\n appEventBus: this.appEventBus,\n uiConfig: this.uiConfig,\n uiStaticDir: this.uiStaticDir,\n productVersion: this.productVersion,\n applyLiveConfigReload: this.configManager.applyLiveConfigReload,\n initializeAgentHomeDirectory: this.deps.initializeAgentHomeDirectory,\n marketplace: this.marketplace,\n cron: this.automation,\n remoteAccess: this.remoteManager.remoteAccess,\n runtimeControl: this.runtimeControl,\n ...(this.runtimeUpdate ? { runtimeUpdate: this.runtimeUpdate } : {}),\n bootstrapStatus: this.bootstrapStatus,\n extensions: this.extensions,\n });\n\n private runRuntimeLoop = async (): Promise<void> => {\n logStartupTrace(\"service.start_gateway.runtime_loop_begin\");\n let startupTask: Promise<void> | null = null;\n try {\n const runtimeLoopTask = runGatewayInboundLoop(this);\n startupTask = this.startDeferredRuntime();\n void startupTask.catch((error) => handleGatewayDeferredStartupError({\n bootstrapStatus: this.bootstrapStatus,\n error,\n }));\n await runtimeLoopTask;\n } finally {\n if (startupTask) {\n await startupTask.catch(() => undefined);\n }\n await this.cleanup();\n }\n };\n\n private startDeferredRuntime = async (): Promise<void> => {\n const app = new NextclawApp(this);\n await app.start();\n };\n\n readonly startDeferredChannels = async (): Promise<void> => {\n await this.deferredChannelStarter();\n };\n\n private readonly startChannels = async (): Promise<void> => {\n await this.kernel.channels.start();\n const enabledChannels = this.kernel.channels.enabledChannels;\n if (enabledChannels.length > 0) {\n console.log(`✓ Channels enabled: ${enabledChannels.join(\", \")}`);\n } else {\n console.log(\"Warning: No channels enabled\");\n }\n this.bootstrapStatus.markChannelsReady(enabledChannels);\n };\n\n private createMarketplace = (): MarketplaceApiConfig => ({\n apiBaseUrl: process.env.NEXTCLAW_MARKETPLACE_API_BASE,\n installer: new ServiceMarketplaceInstaller({\n applyLiveConfigReload: this.configManager.applyLiveConfigReload,\n runCliSubcommand: this.deps.runCliSubcommand,\n installBuiltinSkill: this.deps.installBuiltinMarketplaceSkill,\n }).createInstaller(),\n });\n\n private cleanup = async (): Promise<void> => {\n localUiRuntimeStore.clearIfOwnedByProcess();\n await this.fileWatchers.clear();\n await this.kernel.extensions.stop();\n await this.remoteManager.stop();\n };\n\n private markUiRuntimeReady = async (): Promise<void> => {\n this.bootstrapStatus.markShellReady();\n await waitForNextTick();\n };\n\n private createGatewayController = (): GatewayControllerImpl => {\n return measureStartupSync(\n \"service.gateway.gateway_controller\",\n () => new GatewayControllerImpl({\n configManager: this.configManager,\n channels: this.kernel.channels,\n cron: this.automation,\n sessionManager: this.sessionManager,\n requestRestart: async (options) => {\n await this.deps.requestRestart({\n reason: options?.reason ?? \"gateway tool restart\",\n manualMessage: \"Restart the gateway to apply changes.\",\n strategy: \"background-service-or-exit\",\n delayMs: options?.delayMs,\n silentOnServiceRestart: true,\n });\n },\n })\n );\n };\n\n private startSupportServices = async (): Promise<void> => {\n this.extensions.publishConfigChanges();\n await measureStartupAsync(\"service.start_gateway_support_services\", async () =>\n await startGatewayRuntimeSupport({\n automation: this.automation,\n remoteModule: this.remoteManager.remoteModule,\n watchConfigFile: () => watchServiceConfigFile({\n configPath: resolve(getConfigPath()),\n watcherRegistry: this.fileWatchers,\n scheduleReload: (reason) => this.configManager.scheduleReload(reason)\n }),\n watcherRegistry: this.fileWatchers\n })\n );\n };\n\n private installConfigHostHooks = (): void => {\n this.configManager.installRuntimeHooks({\n reloadCompanion: async ({ config: nextConfig }) => {\n await companionRuntimeService.applyConfig(nextConfig);\n },\n onRestartRequired: (paths) => {\n void this.deps.requestRestart({\n changedPaths: paths,\n manualMessage: `已保存以下改动,等待你手动重启后生效:${paths.join(\", \")}`,\n mode: \"notify\",\n reason: `config reload requires restart: ${paths.join(\", \")}`,\n strategy: \"background-service-or-manual\",\n });\n },\n });\n };\n\n private configureIngressHandlers = (): void => {\n this.kernel.extensions.registerIngressHandlers();\n };\n\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nextclaw-gateway-runtime.service.js","names":["getConfigPath","getDataDir","getWorkspacePath","waitForNextTick"],"sources":["../../../../src/shared/services/gateway/nextclaw-gateway-runtime.service.ts"],"sourcesContent":["import * as NextclawCore from \"@nextclaw/core\";\nimport {\n AgentRunClient,\n NextclawKernel,\n runGatewayInboundLoop,\n type AutomationManager,\n type ConfigManager,\n type LlmProviderManager,\n type SessionManager,\n} from \"@nextclaw/kernel\";\nimport type { EventBus, Ingress } from \"@nextclaw/shared\";\nimport {\n startUiServer,\n type MarketplaceApiConfig,\n type UiRouterOptions,\n type UiRuntimeControlHost,\n type UiRuntimeUpdateHost,\n} from \"@nextclaw/server\";\nimport { resolve } from \"node:path\";\nimport { setImmediate as waitForNextTick } from \"node:timers/promises\";\nimport { GatewayControllerImpl } from \"@nextclaw-service/shared/controllers/gateway.controller.js\";\nimport { GatewayExtensionManager } from \"@nextclaw-service/shared/services/gateway/managers/gateway-extension.manager.js\";\nimport { GatewayRemoteManager } from \"@nextclaw-service/shared/services/gateway/managers/gateway-remote.manager.js\";\nimport { GatewayRestartWakeService } from \"@nextclaw-service/shared/services/gateway/gateway-restart-wake.service.js\";\nimport { createCronJobHandler } from \"@nextclaw-service/shared/services/gateway/utils/cron-job-handler.utils.js\";\nimport { companionRuntimeService } from \"@nextclaw-service/shared/services/ui/companion-runtime.service.js\";\nimport { handleGatewayDeferredStartupError } from \"@nextclaw-service/shared/services/gateway/utils/gateway-runtime-lifecycle.utils.js\";\nimport { NextclawApp, type UiStartupHandle } from \"@nextclaw-service/shared/services/gateway/nextclaw-app.service.js\";\nimport { NextclawDistributionService } from \"@nextclaw-service/shared/services/runtime/nextclaw-distribution.service.js\";\nimport { ServiceBootstrapStatusStore } from \"@nextclaw-service/shared/services/gateway/service-bootstrap-status.service.js\";\nimport { ServiceFileWatcherRegistry, markLocalUiRuntimeIfStarted, startGatewayRuntimeSupport, watchServiceConfigFile } from \"@nextclaw-service/shared/services/gateway/service-startup-support.service.js\";\nimport { ServiceMarketplaceInstaller } from \"@nextclaw-service/shared/services/marketplace/service-marketplace-installer.service.js\";\nimport { NpmRuntimeUpdateHost } from \"@nextclaw-service/shared/services/ui/npm-runtime-update-host.service.js\";\nimport { createRuntimeControlHost } from \"@nextclaw-service/shared/services/ui/runtime-control-host.service.js\";\nimport { localUiRuntimeStore } from \"@nextclaw-service/shared/stores/local-ui-runtime.store.js\";\nimport { managedServiceStateStore } from \"@nextclaw-service/shared/stores/managed-service-state.store.js\";\nimport type { RequestRestartParams } from \"@nextclaw-service/shared/types/cli.types.js\";\nimport { openBrowser, resolveUiConfig, resolveUiStaticDir } from \"@nextclaw-service/shared/utils/cli.utils.js\";\nimport { logStartupTrace, measureStartupAsync, measureStartupSync } from \"@nextclaw-service/shared/utils/startup-trace.js\";\n\nconst {\n getConfigPath,\n getDataDir,\n getWorkspacePath,\n} = NextclawCore;\n\nfunction resolveApplyRestartMode(uiPort: number): \"managed-service-restart\" | \"manual-process-restart\" {\n const serviceState = managedServiceStateStore.read();\n if (serviceState?.pid === process.pid) {\n return \"managed-service-restart\";\n }\n if (\n process.env.NEXTCLAW_RUNTIME_BUNDLE_CHILD === \"1\" &&\n typeof serviceState?.uiPort === \"number\" &&\n serviceState.uiPort === uiPort\n ) {\n return \"managed-service-restart\";\n }\n return \"manual-process-restart\";\n}\n\ntype Config = NextclawCore.Config;\ntype MessageBus = NextclawCore.MessageBus;\n\ntype GatewayRuntimeOptions = {\n uiOverrides?: Partial<Config[\"ui\"]>;\n uiStaticDir?: string | null;\n};\n\nexport type GatewayRuntimeDeps = {\n requestRestart: (params: RequestRestartParams) => Promise<void>;\n initializeAgentHomeDirectory: (homeDirectory: string) => void;\n startService: (options: { uiOverrides: Record<string, unknown>; open: boolean }) => Promise<void>;\n stopService: () => Promise<void>;\n runCliSubcommand: (args: string[]) => Promise<string>;\n installBuiltinMarketplaceSkill: (slug: string, force: boolean | undefined) => { message: string; output?: string } | null;\n};\n\nexport class NextclawGatewayRuntime {\n readonly kernel: NextclawKernel;\n readonly appEventBus: EventBus;\n readonly messageBus: MessageBus;\n readonly sessionManager: SessionManager;\n readonly automation: AutomationManager;\n readonly agentRunClient: AgentRunClient;\n readonly runtimeControl: UiRuntimeControlHost;\n readonly runtimeUpdate: UiRuntimeUpdateHost | null;\n readonly ingress: Ingress;\n readonly distribution = NextclawDistributionService.get();\n readonly productVersion: string;\n readonly providerManager: LlmProviderManager;\n readonly gatewayController: GatewayControllerImpl;\n\n readonly configManager: ConfigManager;\n readonly uiConfig: Config[\"ui\"];\n readonly uiStaticDir: string | null;\n readonly workspace: string;\n readonly remoteManager: GatewayRemoteManager;\n readonly marketplace: MarketplaceApiConfig;\n readonly extensions: GatewayExtensionManager;\n readonly restartWake: GatewayRestartWakeService;\n bootstrapStatus: ServiceBootstrapStatusStore;\n uiStartup: UiStartupHandle;\n readonly fileWatchers = new ServiceFileWatcherRegistry();\n private deferredChannelStarter: () => Promise<void>;\n\n constructor(\n private readonly deps: GatewayRuntimeDeps,\n private readonly options: GatewayRuntimeOptions,\n ) {\n const configPath = getConfigPath();\n this.kernel = measureStartupSync(\n \"service.gateway.kernel\",\n () => new NextclawKernel({\n homeDir: getDataDir(),\n configPath,\n }),\n );\n this.configManager = this.kernel.configManager;\n const config = this.configManager.config;\n this.uiConfig = resolveUiConfig(config, options.uiOverrides);\n this.uiStaticDir = options.uiStaticDir === undefined ? resolveUiStaticDir(this.distribution.uiDistDir) : options.uiStaticDir;\n this.workspace = getWorkspacePath(config.agents.defaults.workspace);\n this.appEventBus = this.kernel.eventBus;\n this.ingress = this.kernel.ingress;\n this.agentRunClient = new AgentRunClient({\n eventBus: this.kernel.eventBus,\n ingress: this.kernel.ingress,\n });\n this.messageBus = this.kernel.messageBus;\n this.sessionManager = this.kernel.sessionManager;\n this.automation = this.kernel.automation;\n this.productVersion = this.distribution.version;\n this.extensions = new GatewayExtensionManager(this);\n this.providerManager = this.kernel.llmProviders;\n this.installConfigHostHooks();\n this.restartWake = new GatewayRestartWakeService(this);\n this.bootstrapStatus = this.createBootstrapStatus();\n this.uiStartup = this.createDisabledUiStartup();\n this.remoteManager = new GatewayRemoteManager({\n deps: this.deps,\n configManager: this.configManager,\n uiConfig: this.uiConfig,\n onRemoteStateChange: (state) => this.bootstrapStatus.syncRemoteRuntimeState(state),\n });\n this.marketplace = this.createMarketplace();\n this.runtimeControl = createRuntimeControlHost({\n serviceCommands: this.deps,\n requestRestart: this.deps.requestRestart,\n uiConfig: this.uiConfig,\n });\n this.runtimeUpdate =\n process.env.NEXTCLAW_DISABLE_RUNTIME_UPDATE_HOST === \"1\"\n ? null\n : new NpmRuntimeUpdateHost({\n eventBus: this.appEventBus,\n applyRestartMode: resolveApplyRestartMode(this.uiConfig.port),\n requestRestart: this.deps.requestRestart,\n uiConfig: this.uiConfig,\n });\n this.gatewayController = this.createGatewayController();\n this.kernel.provideGatewayController(this.gatewayController);\n this.deferredChannelStarter = this.startChannels;\n this.automation.onJob = createCronJobHandler({\n agentRunClient: this.agentRunClient,\n bus: this.messageBus,\n });\n }\n\n start = async (): Promise<void> => {\n logStartupTrace(\"service.start_gateway.begin\");\n await this.reset();\n this.configureIngressHandlers();\n this.uiStartup = await this.startUiRuntime();\n await companionRuntimeService.applyConfig(this.configManager.config);\n await this.markUiRuntimeReady();\n await this.startSupportServices();\n await this.runRuntimeLoop();\n await companionRuntimeService.ensureStopped();\n logStartupTrace(\"service.start_gateway.end\");\n };\n\n private reset = async (): Promise<void> => {\n await this.fileWatchers.clear();\n this.bootstrapStatus = this.createBootstrapStatus();\n this.uiStartup = this.createDisabledUiStartup();\n this.deferredChannelStarter = this.startChannels;\n };\n\n private createBootstrapStatus = (): ServiceBootstrapStatusStore => {\n const bootstrapStatus = new ServiceBootstrapStatusStore();\n bootstrapStatus.markChannelsPending();\n bootstrapStatus.setRemoteState(this.configManager.config.remote.enabled ? \"pending\" : \"disabled\");\n return bootstrapStatus;\n };\n\n private createDisabledUiStartup = (): UiStartupHandle => ({\n endpoint: \"\",\n });\n\n private startUiRuntime = async (): Promise<UiStartupHandle> => {\n const uiStartup = await measureStartupAsync(\"service.start_ui_runtime\", async () => {\n logStartupTrace(\"service.start_ui_runtime.begin\");\n if (!this.uiConfig.enabled) {\n return this.createDisabledUiStartup();\n }\n const uiServer = await startUiServer(this.createUiRouterOptions());\n const uiUrl = NextclawCore.resolveLocalUiBaseUrl({\n host: uiServer.host,\n port: uiServer.port,\n });\n console.log(`✓ UI API: ${uiUrl}/api`);\n if (this.uiStaticDir) {\n console.log(`✓ UI frontend: ${uiUrl}`);\n }\n if (this.uiConfig.open) {\n openBrowser(uiUrl);\n }\n logStartupTrace(\"service.start_ui_runtime.ready\", {\n host: uiServer.host,\n port: uiServer.port,\n });\n return {\n endpoint: uiUrl,\n };\n });\n markLocalUiRuntimeIfStarted({\n uiStartup: this.uiConfig.enabled ? uiStartup : null,\n uiConfig: this.uiConfig,\n });\n return uiStartup;\n };\n\n private createUiRouterOptions = (): UiRouterOptions => ({\n kernel: this.kernel,\n configPath: this.configManager.configPath,\n appEventBus: this.appEventBus,\n uiConfig: this.uiConfig,\n uiStaticDir: this.uiStaticDir,\n productVersion: this.productVersion,\n applyLiveConfigReload: this.configManager.applyLiveConfigReload,\n initializeAgentHomeDirectory: this.deps.initializeAgentHomeDirectory,\n marketplace: this.marketplace,\n cron: this.automation,\n remoteAccess: this.remoteManager.remoteAccess,\n runtimeControl: this.runtimeControl,\n ...(this.runtimeUpdate ? { runtimeUpdate: this.runtimeUpdate } : {}),\n bootstrapStatus: this.bootstrapStatus,\n extensions: this.extensions,\n });\n\n private runRuntimeLoop = async (): Promise<void> => {\n logStartupTrace(\"service.start_gateway.runtime_loop_begin\");\n let startupTask: Promise<void> | null = null;\n try {\n const runtimeLoopTask = runGatewayInboundLoop(this);\n startupTask = this.startDeferredRuntime();\n void startupTask.catch((error) => handleGatewayDeferredStartupError({\n bootstrapStatus: this.bootstrapStatus,\n error,\n }));\n await runtimeLoopTask;\n } finally {\n if (startupTask) {\n await startupTask.catch(() => undefined);\n }\n await this.cleanup();\n }\n };\n\n private startDeferredRuntime = async (): Promise<void> => {\n const app = new NextclawApp(this);\n await app.start();\n };\n\n readonly startDeferredChannels = async (): Promise<void> => {\n await this.deferredChannelStarter();\n };\n\n private readonly startChannels = async (): Promise<void> => {\n await this.kernel.channels.start();\n const enabledChannels = this.kernel.channels.enabledChannels;\n if (enabledChannels.length > 0) {\n console.log(`✓ Channels enabled: ${enabledChannels.join(\", \")}`);\n } else {\n console.log(\"Warning: No channels enabled\");\n }\n this.bootstrapStatus.markChannelsReady(enabledChannels);\n };\n\n private createMarketplace = (): MarketplaceApiConfig => ({\n apiBaseUrl: process.env.NEXTCLAW_MARKETPLACE_API_BASE,\n installer: new ServiceMarketplaceInstaller({\n applyLiveConfigReload: this.configManager.applyLiveConfigReload,\n runCliSubcommand: this.deps.runCliSubcommand,\n installBuiltinSkill: this.deps.installBuiltinMarketplaceSkill,\n }).createInstaller(),\n });\n\n private cleanup = async (): Promise<void> => {\n localUiRuntimeStore.clearIfOwnedByProcess();\n await this.fileWatchers.clear();\n await this.kernel.extensions.stop();\n await this.remoteManager.stop();\n };\n\n private markUiRuntimeReady = async (): Promise<void> => {\n this.bootstrapStatus.markShellReady();\n await waitForNextTick();\n };\n\n private createGatewayController = (): GatewayControllerImpl => {\n return measureStartupSync(\n \"service.gateway.gateway_controller\",\n () => new GatewayControllerImpl({\n configManager: this.configManager,\n channels: this.kernel.channels,\n cron: this.automation,\n sessionManager: this.sessionManager,\n requestRestart: async (options) => {\n await this.deps.requestRestart({\n reason: options?.reason ?? \"gateway tool restart\",\n manualMessage: \"Restart the gateway to apply changes.\",\n strategy: \"background-service-or-exit\",\n delayMs: options?.delayMs,\n silentOnServiceRestart: true,\n });\n },\n })\n );\n };\n\n private startSupportServices = async (): Promise<void> => {\n this.extensions.publishConfigChanges();\n await measureStartupAsync(\"service.start_gateway_support_services\", async () =>\n await startGatewayRuntimeSupport({\n automation: this.automation,\n remoteModule: this.remoteManager.remoteModule,\n watchConfigFile: () => watchServiceConfigFile({\n configPath: resolve(getConfigPath()),\n watcherRegistry: this.fileWatchers,\n scheduleReload: (reason) => this.configManager.scheduleReload(reason)\n }),\n watcherRegistry: this.fileWatchers\n })\n );\n };\n\n private installConfigHostHooks = (): void => {\n this.configManager.installRuntimeHooks({\n reloadCompanion: async ({ config: nextConfig }) => {\n await companionRuntimeService.applyConfig(nextConfig);\n },\n onRestartRequired: (paths) => {\n void this.deps.requestRestart({\n changedPaths: paths,\n manualMessage: `已保存以下改动,等待你手动重启后生效:${paths.join(\", \")}`,\n mode: \"notify\",\n reason: `config reload requires restart: ${paths.join(\", \")}`,\n strategy: \"background-service-or-manual\",\n });\n },\n });\n };\n\n private configureIngressHandlers = (): void => {\n this.kernel.extensions.registerIngressHandlers();\n };\n\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//#region src/shared/services/restart/restart-sentinel.service.d.ts
|
|
1
|
+
//#region src/shared/utils/restart/restart-sentinel.utils.d.ts
|
|
4
2
|
type RestartSentinelDeliveryContext = {
|
|
5
3
|
channel?: string;
|
|
6
4
|
chatId?: string;
|
|
@@ -34,7 +32,6 @@ declare function parseSessionKey(sessionKey?: string): {
|
|
|
34
32
|
channel: string;
|
|
35
33
|
chatId: string;
|
|
36
34
|
} | null;
|
|
37
|
-
declare function enqueuePendingSystemEvent(sessionManager: SessionManager, sessionKey: string, message: string): void;
|
|
38
35
|
//#endregion
|
|
39
|
-
export { RestartSentinelDeliveryContext, RestartSentinelPayload, consumeRestartSentinel,
|
|
40
|
-
//# sourceMappingURL=restart-sentinel.
|
|
36
|
+
export { RestartSentinelDeliveryContext, RestartSentinelPayload, consumeRestartSentinel, formatRestartSentinelMessage, parseSessionKey, resolveRestartSentinelPath, summarizeRestartSentinel, writeRestartSentinel };
|
|
37
|
+
//# sourceMappingURL=restart-sentinel.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart-sentinel.utils.d.ts","names":[],"sources":["../../../../src/shared/utils/restart/restart-sentinel.utils.ts"],"mappings":";KAIY,8BAAA;EACV,OAAA;EACA,MAAA;EACA,OAAA;EACA,SAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,KAGD,sBAAA;EACV,IAAA;EACA,MAAA;EACA,EAAA;EACA,UAAA;EACA,eAAA,GAAkB,8BAAA;EAClB,OAAA;EACA,KAAA;IACE,MAAA;IACA,QAAA;IACA,UAAA;EAAA;AAAA;AAAA,KAIC,mBAAA;EACH,OAAA;EACA,OAAA,EAAS,sBAAA;AAAA;AAAA,iBAwBK,0BAAA,CAAA;AAAA,iBAIM,oBAAA,CAAqB,OAAA,EAAS,sBAAA,GAAyB,OAAA;AAAA,iBAWvD,sBAAA,CAAA,GAA0B,OAAA,CAAQ,mBAAA;AAAA,iBAoBxC,wBAAA,CAAyB,OAAA,EAAS,sBAAA;AAAA,iBAkBlC,4BAAA,CAA6B,OAAA,EAAS,sBAAA;AAAA,iBAetC,eAAA,CACd,UAAA;EACG,OAAA;EAAiB,MAAA;AAAA"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { getDataDir } from "@nextclaw/core";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
-
//#region src/shared/
|
|
4
|
+
//#region src/shared/utils/restart/restart-sentinel.utils.ts
|
|
5
5
|
const RESTART_SENTINEL_FILENAME = "restart-sentinel.json";
|
|
6
|
-
const PENDING_SYSTEM_EVENTS_KEY = "pending_system_events";
|
|
7
6
|
const RESTART_REASON_MAX_CHARS = 240;
|
|
8
7
|
const RESTART_NOTE_MAX_CHARS = 600;
|
|
9
8
|
const RESTART_OUTBOUND_MAX_CHARS = 1200;
|
|
@@ -71,20 +70,7 @@ function parseSessionKey(sessionKey) {
|
|
|
71
70
|
chatId: value.slice(separator + 1)
|
|
72
71
|
};
|
|
73
72
|
}
|
|
74
|
-
function enqueuePendingSystemEvent(sessionManager, sessionKey, message) {
|
|
75
|
-
const text = message.trim();
|
|
76
|
-
if (!text) return;
|
|
77
|
-
const session = sessionManager.getOrCreate(sessionKey);
|
|
78
|
-
const queueRaw = session.metadata[PENDING_SYSTEM_EVENTS_KEY];
|
|
79
|
-
const queue = Array.isArray(queueRaw) ? queueRaw.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean) : [];
|
|
80
|
-
if (queue.at(-1) === text) return;
|
|
81
|
-
queue.push(text);
|
|
82
|
-
if (queue.length > 20) queue.splice(0, queue.length - 20);
|
|
83
|
-
session.metadata[PENDING_SYSTEM_EVENTS_KEY] = queue;
|
|
84
|
-
session.updatedAt = /* @__PURE__ */ new Date();
|
|
85
|
-
sessionManager.save(session);
|
|
86
|
-
}
|
|
87
73
|
//#endregion
|
|
88
|
-
export { consumeRestartSentinel,
|
|
74
|
+
export { consumeRestartSentinel, formatRestartSentinelMessage, parseSessionKey, resolveRestartSentinelPath, summarizeRestartSentinel, writeRestartSentinel };
|
|
89
75
|
|
|
90
|
-
//# sourceMappingURL=restart-sentinel.
|
|
76
|
+
//# sourceMappingURL=restart-sentinel.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart-sentinel.utils.js","names":[],"sources":["../../../../src/shared/utils/restart/restart-sentinel.utils.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getDataDir } from \"@nextclaw/core\";\n\nexport type RestartSentinelDeliveryContext = {\n channel?: string;\n chatId?: string;\n replyTo?: string | null;\n accountId?: string | null;\n metadata?: Record<string, unknown>;\n};\n\nexport type RestartSentinelPayload = {\n kind: \"config.apply\" | \"config.patch\" | \"update.run\" | \"restart\";\n status: \"ok\" | \"error\" | \"skipped\";\n ts: number;\n sessionKey?: string;\n deliveryContext?: RestartSentinelDeliveryContext;\n message?: string | null;\n stats?: {\n reason?: string | null;\n strategy?: string | null;\n durationMs?: number | null;\n };\n};\n\ntype RestartSentinelFile = {\n version: 1;\n payload: RestartSentinelPayload;\n};\n\nconst RESTART_SENTINEL_FILENAME = \"restart-sentinel.json\";\nconst RESTART_REASON_MAX_CHARS = 240;\nconst RESTART_NOTE_MAX_CHARS = 600;\nconst RESTART_OUTBOUND_MAX_CHARS = 1200;\n\nfunction trimTo(value: string, maxChars: number): string {\n const text = value.trim();\n if (!text) {\n return \"\";\n }\n if (text.length <= maxChars) {\n return text;\n }\n return `${text.slice(0, Math.max(0, maxChars - 1)).trimEnd()}…`;\n}\n\nfunction normalizeLine(value: string, maxChars: number): string | null {\n const trimmed = trimTo(value, maxChars);\n return trimmed ? trimmed : null;\n}\n\nexport function resolveRestartSentinelPath(): string {\n return resolve(getDataDir(), \"run\", RESTART_SENTINEL_FILENAME);\n}\n\nexport async function writeRestartSentinel(payload: RestartSentinelPayload): Promise<string> {\n const path = resolveRestartSentinelPath();\n mkdirSync(resolve(path, \"..\"), { recursive: true });\n const file: RestartSentinelFile = {\n version: 1,\n payload\n };\n writeFileSync(path, `${JSON.stringify(file, null, 2)}\\n`, \"utf-8\");\n return path;\n}\n\nexport async function consumeRestartSentinel(): Promise<RestartSentinelFile | null> {\n const path = resolveRestartSentinelPath();\n if (!existsSync(path)) {\n return null;\n }\n try {\n const raw = readFileSync(path, \"utf-8\");\n const parsed = JSON.parse(raw) as RestartSentinelFile;\n if (!parsed || parsed.version !== 1 || !parsed.payload) {\n rmSync(path, { force: true });\n return null;\n }\n rmSync(path, { force: true });\n return parsed;\n } catch {\n rmSync(path, { force: true });\n return null;\n }\n}\n\nexport function summarizeRestartSentinel(payload: RestartSentinelPayload): string {\n const reason = normalizeLine(payload.stats?.reason ?? \"\", RESTART_REASON_MAX_CHARS);\n if (payload.kind === \"update.run\") {\n return payload.status === \"ok\"\n ? \"✅ NextClaw update completed and service restarted.\"\n : \"⚠️ NextClaw update finished with issues.\";\n }\n if (payload.kind === \"config.apply\" || payload.kind === \"config.patch\") {\n return payload.status === \"ok\"\n ? \"✅ Config applied and service restarted.\"\n : \"⚠️ Config change restart finished with issues.\";\n }\n if (reason) {\n return `Gateway restart complete (${reason}).`;\n }\n return \"Gateway restart complete.\";\n}\n\nexport function formatRestartSentinelMessage(payload: RestartSentinelPayload): string {\n const lines = [summarizeRestartSentinel(payload)];\n const note = normalizeLine(payload.message ?? \"\", RESTART_NOTE_MAX_CHARS);\n if (note) {\n lines.push(note);\n }\n const reason = normalizeLine(payload.stats?.reason ?? \"\", RESTART_REASON_MAX_CHARS);\n if (reason && !lines.some((line) => line.includes(reason))) {\n lines.push(`Reason: ${reason}`);\n }\n\n const message = lines.join(\"\\n\").trim();\n return trimTo(message, RESTART_OUTBOUND_MAX_CHARS);\n}\n\nexport function parseSessionKey(\n sessionKey?: string\n): { channel: string; chatId: string } | null {\n const value = sessionKey?.trim();\n if (!value) {\n return null;\n }\n const separator = value.indexOf(\":\");\n if (separator <= 0 || separator >= value.length - 1) {\n return null;\n }\n return {\n channel: value.slice(0, separator),\n chatId: value.slice(separator + 1)\n };\n}\n"],"mappings":";;;;AA+BA,MAAM,4BAA4B;AAClC,MAAM,2BAA2B;AACjC,MAAM,yBAAyB;AAC/B,MAAM,6BAA6B;AAEnC,SAAS,OAAO,OAAe,UAA0B;CACvD,MAAM,OAAO,MAAM,MAAM;AACzB,KAAI,CAAC,KACH,QAAO;AAET,KAAI,KAAK,UAAU,SACjB,QAAO;AAET,QAAO,GAAG,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC;;AAG/D,SAAS,cAAc,OAAe,UAAiC;CACrE,MAAM,UAAU,OAAO,OAAO,SAAS;AACvC,QAAO,UAAU,UAAU;;AAG7B,SAAgB,6BAAqC;AACnD,QAAO,QAAQ,YAAY,EAAE,OAAO,0BAA0B;;AAGhE,eAAsB,qBAAqB,SAAkD;CAC3F,MAAM,OAAO,4BAA4B;AACzC,WAAU,QAAQ,MAAM,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AAKnD,eAAc,MAAM,GAAG,KAAK,UAJM;EAChC,SAAS;EACT;EACD,EAC2C,MAAM,EAAE,CAAC,KAAK,QAAQ;AAClE,QAAO;;AAGT,eAAsB,yBAA8D;CAClF,MAAM,OAAO,4BAA4B;AACzC,KAAI,CAAC,WAAW,KAAK,CACnB,QAAO;AAET,KAAI;EACF,MAAM,MAAM,aAAa,MAAM,QAAQ;EACvC,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,MAAI,CAAC,UAAU,OAAO,YAAY,KAAK,CAAC,OAAO,SAAS;AACtD,UAAO,MAAM,EAAE,OAAO,MAAM,CAAC;AAC7B,UAAO;;AAET,SAAO,MAAM,EAAE,OAAO,MAAM,CAAC;AAC7B,SAAO;SACD;AACN,SAAO,MAAM,EAAE,OAAO,MAAM,CAAC;AAC7B,SAAO;;;AAIX,SAAgB,yBAAyB,SAAyC;CAChF,MAAM,SAAS,cAAc,QAAQ,OAAO,UAAU,IAAI,yBAAyB;AACnF,KAAI,QAAQ,SAAS,aACnB,QAAO,QAAQ,WAAW,OACtB,uDACA;AAEN,KAAI,QAAQ,SAAS,kBAAkB,QAAQ,SAAS,eACtD,QAAO,QAAQ,WAAW,OACtB,4CACA;AAEN,KAAI,OACF,QAAO,6BAA6B,OAAO;AAE7C,QAAO;;AAGT,SAAgB,6BAA6B,SAAyC;CACpF,MAAM,QAAQ,CAAC,yBAAyB,QAAQ,CAAC;CACjD,MAAM,OAAO,cAAc,QAAQ,WAAW,IAAI,uBAAuB;AACzE,KAAI,KACF,OAAM,KAAK,KAAK;CAElB,MAAM,SAAS,cAAc,QAAQ,OAAO,UAAU,IAAI,yBAAyB;AACnF,KAAI,UAAU,CAAC,MAAM,MAAM,SAAS,KAAK,SAAS,OAAO,CAAC,CACxD,OAAM,KAAK,WAAW,SAAS;AAIjC,QAAO,OADS,MAAM,KAAK,KAAK,CAAC,MAAM,EAChB,2BAA2B;;AAGpD,SAAgB,gBACd,YAC4C;CAC5C,MAAM,QAAQ,YAAY,MAAM;AAChC,KAAI,CAAC,MACH,QAAO;CAET,MAAM,YAAY,MAAM,QAAQ,IAAI;AACpC,KAAI,aAAa,KAAK,aAAa,MAAM,SAAS,EAChD,QAAO;AAET,QAAO;EACL,SAAS,MAAM,MAAM,GAAG,UAAU;EAClC,QAAQ,MAAM,MAAM,YAAY,EAAE;EACnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/service",
|
|
3
|
-
"version": "0.1.18
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "NextClaw long-running service host and runtime lifecycle.",
|
|
6
6
|
"type": "module",
|
|
@@ -42,30 +42,30 @@
|
|
|
42
42
|
"chokidar": "^3.6.0",
|
|
43
43
|
"commander": "^12.1.0",
|
|
44
44
|
"jszip": "^3.10.1",
|
|
45
|
-
"@nextclaw/channel-extension-
|
|
46
|
-
"@nextclaw/channel-extension-
|
|
47
|
-
"@nextclaw/channel-extension-email": "0.1.1
|
|
48
|
-
"@nextclaw/channel-extension-
|
|
49
|
-
"@nextclaw/channel-extension-
|
|
50
|
-
"@nextclaw/channel-extension-
|
|
51
|
-
"@nextclaw/channel-extension-
|
|
52
|
-
"@nextclaw/channel-extension-
|
|
53
|
-
"@nextclaw/channel-extension-
|
|
54
|
-
"@nextclaw/
|
|
55
|
-
"@nextclaw/
|
|
56
|
-
"@nextclaw/
|
|
57
|
-
"@nextclaw/ncp-agent-runtime": "0.3.29
|
|
58
|
-
"@nextclaw/
|
|
59
|
-
"@nextclaw/
|
|
60
|
-
"@nextclaw/ncp-toolkit": "0.5.23
|
|
61
|
-
"@nextclaw/ncp
|
|
62
|
-
"@nextclaw/nextclaw-ncp-runtime-
|
|
63
|
-
"@nextclaw/ncp": "0.
|
|
64
|
-
"@nextclaw/
|
|
65
|
-
"@nextclaw/
|
|
66
|
-
"@nextclaw/server": "0.12.26
|
|
67
|
-
"@nextclaw/shared": "0.1.12
|
|
68
|
-
"@nextclaw/
|
|
45
|
+
"@nextclaw/channel-extension-dingtalk": "0.1.1",
|
|
46
|
+
"@nextclaw/channel-extension-discord": "0.1.1",
|
|
47
|
+
"@nextclaw/channel-extension-email": "0.1.1",
|
|
48
|
+
"@nextclaw/channel-extension-feishu": "0.1.9",
|
|
49
|
+
"@nextclaw/channel-extension-qq": "0.1.6",
|
|
50
|
+
"@nextclaw/channel-extension-telegram": "0.1.1",
|
|
51
|
+
"@nextclaw/channel-extension-slack": "0.1.1",
|
|
52
|
+
"@nextclaw/channel-extension-wecom": "0.1.1",
|
|
53
|
+
"@nextclaw/channel-extension-weixin": "0.1.12",
|
|
54
|
+
"@nextclaw/core": "0.12.25",
|
|
55
|
+
"@nextclaw/mcp": "0.1.90",
|
|
56
|
+
"@nextclaw/kernel": "0.1.15",
|
|
57
|
+
"@nextclaw/ncp-agent-runtime": "0.3.29",
|
|
58
|
+
"@nextclaw/ncp-mcp": "0.1.92",
|
|
59
|
+
"@nextclaw/channel-extension-whatsapp": "0.1.1",
|
|
60
|
+
"@nextclaw/ncp-toolkit": "0.5.23",
|
|
61
|
+
"@nextclaw/ncp": "0.5.18",
|
|
62
|
+
"@nextclaw/nextclaw-ncp-runtime-http-client": "0.1.17",
|
|
63
|
+
"@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.1.18",
|
|
64
|
+
"@nextclaw/runtime": "0.2.57",
|
|
65
|
+
"@nextclaw/nextclaw-hermes-acp-bridge": "0.1.17",
|
|
66
|
+
"@nextclaw/server": "0.12.26",
|
|
67
|
+
"@nextclaw/shared": "0.1.12",
|
|
68
|
+
"@nextclaw/remote": "0.1.103"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^20.17.6",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"restart-sentinel.service.d.ts","names":[],"sources":["../../../../src/shared/services/restart/restart-sentinel.service.ts"],"mappings":";;;KAIY,8BAAA;EACV,OAAA;EACA,MAAA;EACA,OAAA;EACA,SAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,KAGD,sBAAA;EACV,IAAA;EACA,MAAA;EACA,EAAA;EACA,UAAA;EACA,eAAA,GAAkB,8BAAA;EAClB,OAAA;EACA,KAAA;IACE,MAAA;IACA,QAAA;IACA,UAAA;EAAA;AAAA;AAAA,KAIC,mBAAA;EACH,OAAA;EACA,OAAA,EAAS,sBAAA;AAAA;AAAA,iBAyBK,0BAAA,CAAA;AAAA,iBAIM,oBAAA,CAAqB,OAAA,EAAS,sBAAA,GAAyB,OAAA;AAAA,iBAWvD,sBAAA,CAAA,GAA0B,OAAA,CAAQ,mBAAA;AAAA,iBAoBxC,wBAAA,CAAyB,OAAA,EAAS,sBAAA;AAAA,iBAkBlC,4BAAA,CAA6B,OAAA,EAAS,sBAAA;AAAA,iBAetC,eAAA,CACd,UAAA;EACG,OAAA;EAAiB,MAAA;AAAA;AAAA,iBAeN,yBAAA,CACd,cAAA,EAAgB,cAAA,EAChB,UAAA,UACA,OAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"restart-sentinel.service.js","names":[],"sources":["../../../../src/shared/services/restart/restart-sentinel.service.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getDataDir, type SessionManager } from \"@nextclaw/core\";\n\nexport type RestartSentinelDeliveryContext = {\n channel?: string;\n chatId?: string;\n replyTo?: string | null;\n accountId?: string | null;\n metadata?: Record<string, unknown>;\n};\n\nexport type RestartSentinelPayload = {\n kind: \"config.apply\" | \"config.patch\" | \"update.run\" | \"restart\";\n status: \"ok\" | \"error\" | \"skipped\";\n ts: number;\n sessionKey?: string;\n deliveryContext?: RestartSentinelDeliveryContext;\n message?: string | null;\n stats?: {\n reason?: string | null;\n strategy?: string | null;\n durationMs?: number | null;\n };\n};\n\ntype RestartSentinelFile = {\n version: 1;\n payload: RestartSentinelPayload;\n};\n\nconst RESTART_SENTINEL_FILENAME = \"restart-sentinel.json\";\nconst PENDING_SYSTEM_EVENTS_KEY = \"pending_system_events\";\nconst RESTART_REASON_MAX_CHARS = 240;\nconst RESTART_NOTE_MAX_CHARS = 600;\nconst RESTART_OUTBOUND_MAX_CHARS = 1200;\n\nfunction trimTo(value: string, maxChars: number): string {\n const text = value.trim();\n if (!text) {\n return \"\";\n }\n if (text.length <= maxChars) {\n return text;\n }\n return `${text.slice(0, Math.max(0, maxChars - 1)).trimEnd()}…`;\n}\n\nfunction normalizeLine(value: string, maxChars: number): string | null {\n const trimmed = trimTo(value, maxChars);\n return trimmed ? trimmed : null;\n}\n\nexport function resolveRestartSentinelPath(): string {\n return resolve(getDataDir(), \"run\", RESTART_SENTINEL_FILENAME);\n}\n\nexport async function writeRestartSentinel(payload: RestartSentinelPayload): Promise<string> {\n const path = resolveRestartSentinelPath();\n mkdirSync(resolve(path, \"..\"), { recursive: true });\n const file: RestartSentinelFile = {\n version: 1,\n payload\n };\n writeFileSync(path, `${JSON.stringify(file, null, 2)}\\n`, \"utf-8\");\n return path;\n}\n\nexport async function consumeRestartSentinel(): Promise<RestartSentinelFile | null> {\n const path = resolveRestartSentinelPath();\n if (!existsSync(path)) {\n return null;\n }\n try {\n const raw = readFileSync(path, \"utf-8\");\n const parsed = JSON.parse(raw) as RestartSentinelFile;\n if (!parsed || parsed.version !== 1 || !parsed.payload) {\n rmSync(path, { force: true });\n return null;\n }\n rmSync(path, { force: true });\n return parsed;\n } catch {\n rmSync(path, { force: true });\n return null;\n }\n}\n\nexport function summarizeRestartSentinel(payload: RestartSentinelPayload): string {\n const reason = normalizeLine(payload.stats?.reason ?? \"\", RESTART_REASON_MAX_CHARS);\n if (payload.kind === \"update.run\") {\n return payload.status === \"ok\"\n ? \"✅ NextClaw update completed and service restarted.\"\n : \"⚠️ NextClaw update finished with issues.\";\n }\n if (payload.kind === \"config.apply\" || payload.kind === \"config.patch\") {\n return payload.status === \"ok\"\n ? \"✅ Config applied and service restarted.\"\n : \"⚠️ Config change restart finished with issues.\";\n }\n if (reason) {\n return `Gateway restart complete (${reason}).`;\n }\n return \"Gateway restart complete.\";\n}\n\nexport function formatRestartSentinelMessage(payload: RestartSentinelPayload): string {\n const lines = [summarizeRestartSentinel(payload)];\n const note = normalizeLine(payload.message ?? \"\", RESTART_NOTE_MAX_CHARS);\n if (note) {\n lines.push(note);\n }\n const reason = normalizeLine(payload.stats?.reason ?? \"\", RESTART_REASON_MAX_CHARS);\n if (reason && !lines.some((line) => line.includes(reason))) {\n lines.push(`Reason: ${reason}`);\n }\n\n const message = lines.join(\"\\n\").trim();\n return trimTo(message, RESTART_OUTBOUND_MAX_CHARS);\n}\n\nexport function parseSessionKey(\n sessionKey?: string\n): { channel: string; chatId: string } | null {\n const value = sessionKey?.trim();\n if (!value) {\n return null;\n }\n const separator = value.indexOf(\":\");\n if (separator <= 0 || separator >= value.length - 1) {\n return null;\n }\n return {\n channel: value.slice(0, separator),\n chatId: value.slice(separator + 1)\n };\n}\n\nexport function enqueuePendingSystemEvent(\n sessionManager: SessionManager,\n sessionKey: string,\n message: string\n): void {\n const text = message.trim();\n if (!text) {\n return;\n }\n const session = sessionManager.getOrCreate(sessionKey);\n const queueRaw = session.metadata[PENDING_SYSTEM_EVENTS_KEY];\n const queue = Array.isArray(queueRaw)\n ? queueRaw\n .filter((item): item is string => typeof item === \"string\")\n .map((item) => item.trim())\n .filter(Boolean)\n : [];\n if (queue.at(-1) === text) {\n return;\n }\n queue.push(text);\n if (queue.length > 20) {\n queue.splice(0, queue.length - 20);\n }\n session.metadata[PENDING_SYSTEM_EVENTS_KEY] = queue;\n session.updatedAt = new Date();\n sessionManager.save(session);\n}\n"],"mappings":"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"}
|