@nextclaw/service 0.3.4 → 0.3.6

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.
@@ -0,0 +1,22 @@
1
+ import { NextclawKernel } from "@nextclaw/kernel";
2
+
3
+ //#region src/controllers/commands/project/project-command.controller.d.ts
4
+ type ProjectCommandOptions = {
5
+ json?: boolean;
6
+ };
7
+ type ProjectCreateCommandOptions = ProjectCommandOptions & {
8
+ path?: string;
9
+ template?: "empty" | "knowledge-base";
10
+ };
11
+ declare class ProjectCommands {
12
+ private readonly createKernel;
13
+ constructor(createKernel: () => NextclawKernel);
14
+ list: (options?: ProjectCommandOptions) => Promise<void>;
15
+ templates: (options?: ProjectCommandOptions) => Promise<void>;
16
+ create: (name: string, options?: ProjectCreateCommandOptions) => Promise<void>;
17
+ private printCreatedProject;
18
+ private withKernel;
19
+ }
20
+ //#endregion
21
+ export { ProjectCommandOptions, ProjectCommands, ProjectCreateCommandOptions };
22
+ //# sourceMappingURL=project-command.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-command.controller.d.ts","names":[],"sources":["../../../../src/controllers/commands/project/project-command.controller.ts"],"mappings":";;;KAMY,qBAAA;EACV,IAAA;AAAA;AAAA,KAGU,2BAAA,GAA8B,qBAAA;EACxC,IAAA;EACA,QAAA;AAAA;AAAA,cAGW,eAAA;EAAA,iBACkB,YAAA;cAAA,YAAA,QAAoB,cAAA;EAEjD,IAAA,GAAc,OAAA,GAAS,qBAAA,KAA6B,OAAA;EAiBpD,SAAA,GAAmB,OAAA,GAAS,qBAAA,KAA6B,OAAA;EAazD,MAAA,GACE,IAAA,UACA,OAAA,GAAS,2BAAA,KACR,OAAA;EAAA,QAYK,mBAAA;EAAA,QAQA,UAAA;AAAA"}
@@ -0,0 +1,63 @@
1
+ //#region src/controllers/commands/project/project-command.controller.ts
2
+ var ProjectCommands = class {
3
+ constructor(createKernel) {
4
+ this.createKernel = createKernel;
5
+ }
6
+ list = async (options = {}) => {
7
+ await this.withKernel(async (kernel) => {
8
+ const projects = await kernel.projectManager.listProjects();
9
+ if (options.json) {
10
+ console.log(JSON.stringify({
11
+ projects,
12
+ total: projects.length
13
+ }, null, 2));
14
+ return;
15
+ }
16
+ if (projects.length === 0) {
17
+ console.log("No projects registered.");
18
+ return;
19
+ }
20
+ for (const project of projects) console.log(`${project.name}\t${project.template ?? "existing"}\t${project.rootPath}`);
21
+ });
22
+ };
23
+ templates = async (options = {}) => {
24
+ await this.withKernel(async (kernel) => {
25
+ const templates = kernel.projectManager.listTemplates();
26
+ if (options.json) {
27
+ console.log(JSON.stringify({ templates }, null, 2));
28
+ return;
29
+ }
30
+ for (const template of templates) console.log(`${template.id}\t${template.description}`);
31
+ });
32
+ };
33
+ create = async (name, options = {}) => {
34
+ await this.withKernel(async (kernel) => {
35
+ const input = {
36
+ name,
37
+ ...options.path ? { rootPath: options.path } : {},
38
+ ...options.template ? { template: options.template } : {}
39
+ };
40
+ const project = await kernel.projectManager.createProject(input);
41
+ this.printCreatedProject(project, Boolean(options.json));
42
+ });
43
+ };
44
+ printCreatedProject = (project, json) => {
45
+ if (json) {
46
+ console.log(JSON.stringify(project, null, 2));
47
+ return;
48
+ }
49
+ console.log(`Created project "${project.name}" at ${project.rootPath}`);
50
+ };
51
+ withKernel = async (action) => {
52
+ const kernel = this.createKernel();
53
+ try {
54
+ return await action(kernel);
55
+ } finally {
56
+ await kernel.dispose();
57
+ }
58
+ };
59
+ };
60
+ //#endregion
61
+ export { ProjectCommands };
62
+
63
+ //# sourceMappingURL=project-command.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-command.controller.js","names":[],"sources":["../../../../src/controllers/commands/project/project-command.controller.ts"],"sourcesContent":["import type {\n CreateProjectInput,\n NextclawKernel,\n ProjectRecord,\n} from \"@nextclaw/kernel\";\n\nexport type ProjectCommandOptions = {\n json?: boolean;\n};\n\nexport type ProjectCreateCommandOptions = ProjectCommandOptions & {\n path?: string;\n template?: \"empty\" | \"knowledge-base\";\n};\n\nexport class ProjectCommands {\n constructor(private readonly createKernel: () => NextclawKernel) {}\n\n list = async (options: ProjectCommandOptions = {}): Promise<void> => {\n await this.withKernel(async (kernel) => {\n const projects = await kernel.projectManager.listProjects();\n if (options.json) {\n console.log(JSON.stringify({ projects, total: projects.length }, null, 2));\n return;\n }\n if (projects.length === 0) {\n console.log(\"No projects registered.\");\n return;\n }\n for (const project of projects) {\n console.log(`${project.name}\\t${project.template ?? \"existing\"}\\t${project.rootPath}`);\n }\n });\n };\n\n templates = async (options: ProjectCommandOptions = {}): Promise<void> => {\n await this.withKernel(async (kernel) => {\n const templates = kernel.projectManager.listTemplates();\n if (options.json) {\n console.log(JSON.stringify({ templates }, null, 2));\n return;\n }\n for (const template of templates) {\n console.log(`${template.id}\\t${template.description}`);\n }\n });\n };\n\n create = async (\n name: string,\n options: ProjectCreateCommandOptions = {},\n ): Promise<void> => {\n await this.withKernel(async (kernel) => {\n const input: CreateProjectInput = {\n name,\n ...(options.path ? { rootPath: options.path } : {}),\n ...(options.template ? { template: options.template } : {}),\n };\n const project = await kernel.projectManager.createProject(input);\n this.printCreatedProject(project, Boolean(options.json));\n });\n };\n\n private printCreatedProject = (project: ProjectRecord, json: boolean): void => {\n if (json) {\n console.log(JSON.stringify(project, null, 2));\n return;\n }\n console.log(`Created project \"${project.name}\" at ${project.rootPath}`);\n };\n\n private withKernel = async <T>(action: (kernel: NextclawKernel) => Promise<T>): Promise<T> => {\n const kernel = this.createKernel();\n try {\n return await action(kernel);\n } finally {\n await kernel.dispose();\n }\n };\n}\n"],"mappings":";AAeA,IAAa,kBAAb,MAA6B;CAC3B,YAAY,cAAqD;AAApC,OAAA,eAAA;;CAE7B,OAAO,OAAO,UAAiC,EAAE,KAAoB;AACnE,QAAM,KAAK,WAAW,OAAO,WAAW;GACtC,MAAM,WAAW,MAAM,OAAO,eAAe,cAAc;AAC3D,OAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU;KAAE;KAAU,OAAO,SAAS;KAAQ,EAAE,MAAM,EAAE,CAAC;AAC1E;;AAEF,OAAI,SAAS,WAAW,GAAG;AACzB,YAAQ,IAAI,0BAA0B;AACtC;;AAEF,QAAK,MAAM,WAAW,SACpB,SAAQ,IAAI,GAAG,QAAQ,KAAK,IAAI,QAAQ,YAAY,WAAW,IAAI,QAAQ,WAAW;IAExF;;CAGJ,YAAY,OAAO,UAAiC,EAAE,KAAoB;AACxE,QAAM,KAAK,WAAW,OAAO,WAAW;GACtC,MAAM,YAAY,OAAO,eAAe,eAAe;AACvD,OAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AACnD;;AAEF,QAAK,MAAM,YAAY,UACrB,SAAQ,IAAI,GAAG,SAAS,GAAG,IAAI,SAAS,cAAc;IAExD;;CAGJ,SAAS,OACP,MACA,UAAuC,EAAE,KACvB;AAClB,QAAM,KAAK,WAAW,OAAO,WAAW;GACtC,MAAM,QAA4B;IAChC;IACA,GAAI,QAAQ,OAAO,EAAE,UAAU,QAAQ,MAAM,GAAG,EAAE;IAClD,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,UAAU,GAAG,EAAE;IAC3D;GACD,MAAM,UAAU,MAAM,OAAO,eAAe,cAAc,MAAM;AAChE,QAAK,oBAAoB,SAAS,QAAQ,QAAQ,KAAK,CAAC;IACxD;;CAGJ,uBAA+B,SAAwB,SAAwB;AAC7E,MAAI,MAAM;AACR,WAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;AAC7C;;AAEF,UAAQ,IAAI,oBAAoB,QAAQ,KAAK,OAAO,QAAQ,WAAW;;CAGzE,aAAqB,OAAU,WAA+D;EAC5F,MAAM,SAAS,KAAK,cAAc;AAClC,MAAI;AACF,UAAO,MAAM,OAAO,OAAO;YACnB;AACR,SAAM,OAAO,SAAS"}
@@ -0,0 +1,17 @@
1
+ import { NextclawKernel } from "@nextclaw/kernel";
2
+
3
+ //#region src/controllers/commands/session/session-command.controller.d.ts
4
+ type SessionCommandOptions = {
5
+ json?: boolean;
6
+ };
7
+ declare class SessionCommands {
8
+ private readonly createKernel;
9
+ constructor(createKernel: () => NextclawKernel);
10
+ rename: (sessionId: string, label: string, options?: SessionCommandOptions) => Promise<void>;
11
+ setProject: (sessionId: string, projectRoot: string, options?: SessionCommandOptions) => Promise<void>;
12
+ clearProject: (sessionId: string, options?: SessionCommandOptions) => Promise<void>;
13
+ private update;
14
+ }
15
+ //#endregion
16
+ export { SessionCommandOptions, SessionCommands };
17
+ //# sourceMappingURL=session-command.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-command.controller.d.ts","names":[],"sources":["../../../../src/controllers/commands/session/session-command.controller.ts"],"mappings":";;;KAEY,qBAAA;EACV,IAAA;AAAA;AAAA,cAGW,eAAA;EAAA,iBACkB,YAAA;cAAA,YAAA,QAAoB,cAAA;EAEjD,MAAA,GACE,SAAA,UACA,KAAA,UACA,OAAA,GAAS,qBAAA,KACR,OAAA;EAIH,UAAA,GACE,SAAA,UACA,WAAA,UACA,OAAA,GAAS,qBAAA,KACR,OAAA;EAIH,YAAA,GACE,SAAA,UACA,OAAA,GAAS,qBAAA,KACR,OAAA;EAAA,QAIK,MAAA;AAAA"}
@@ -0,0 +1,29 @@
1
+ //#region src/controllers/commands/session/session-command.controller.ts
2
+ var SessionCommands = class {
3
+ constructor(createKernel) {
4
+ this.createKernel = createKernel;
5
+ }
6
+ rename = async (sessionId, label, options = {}) => {
7
+ await this.update(sessionId, { label }, options);
8
+ };
9
+ setProject = async (sessionId, projectRoot, options = {}) => {
10
+ await this.update(sessionId, { projectRoot }, options);
11
+ };
12
+ clearProject = async (sessionId, options = {}) => {
13
+ await this.update(sessionId, { projectRoot: null }, options);
14
+ };
15
+ update = async (sessionId, patch, options) => {
16
+ const kernel = this.createKernel();
17
+ try {
18
+ const session = await kernel.sessionManager.patchSessionSettings(sessionId, patch);
19
+ if (!session) throw new Error(`Session not found: ${sessionId}`);
20
+ console.log(options.json ? JSON.stringify(session, null, 2) : `Updated session ${session.sessionId}`);
21
+ } finally {
22
+ await kernel.dispose();
23
+ }
24
+ };
25
+ };
26
+ //#endregion
27
+ export { SessionCommands };
28
+
29
+ //# sourceMappingURL=session-command.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-command.controller.js","names":[],"sources":["../../../../src/controllers/commands/session/session-command.controller.ts"],"sourcesContent":["import type { NextclawKernel } from \"@nextclaw/kernel\";\n\nexport type SessionCommandOptions = {\n json?: boolean;\n};\n\nexport class SessionCommands {\n constructor(private readonly createKernel: () => NextclawKernel) {}\n\n rename = async (\n sessionId: string,\n label: string,\n options: SessionCommandOptions = {},\n ): Promise<void> => {\n await this.update(sessionId, { label }, options);\n };\n\n setProject = async (\n sessionId: string,\n projectRoot: string,\n options: SessionCommandOptions = {},\n ): Promise<void> => {\n await this.update(sessionId, { projectRoot }, options);\n };\n\n clearProject = async (\n sessionId: string,\n options: SessionCommandOptions = {},\n ): Promise<void> => {\n await this.update(sessionId, { projectRoot: null }, options);\n };\n\n private update = async (\n sessionId: string,\n patch: { label?: string; projectRoot?: string | null },\n options: SessionCommandOptions,\n ): Promise<void> => {\n const kernel = this.createKernel();\n try {\n const session = await kernel.sessionManager.patchSessionSettings(sessionId, patch);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n console.log(options.json\n ? JSON.stringify(session, null, 2)\n : `Updated session ${session.sessionId}`);\n } finally {\n await kernel.dispose();\n }\n };\n}\n"],"mappings":";AAMA,IAAa,kBAAb,MAA6B;CAC3B,YAAY,cAAqD;AAApC,OAAA,eAAA;;CAE7B,SAAS,OACP,WACA,OACA,UAAiC,EAAE,KACjB;AAClB,QAAM,KAAK,OAAO,WAAW,EAAE,OAAO,EAAE,QAAQ;;CAGlD,aAAa,OACX,WACA,aACA,UAAiC,EAAE,KACjB;AAClB,QAAM,KAAK,OAAO,WAAW,EAAE,aAAa,EAAE,QAAQ;;CAGxD,eAAe,OACb,WACA,UAAiC,EAAE,KACjB;AAClB,QAAM,KAAK,OAAO,WAAW,EAAE,aAAa,MAAM,EAAE,QAAQ;;CAG9D,SAAiB,OACf,WACA,OACA,YACkB;EAClB,MAAM,SAAS,KAAK,cAAc;AAClC,MAAI;GACF,MAAM,UAAU,MAAM,OAAO,eAAe,qBAAqB,WAAW,MAAM;AAClF,OAAI,CAAC,QACH,OAAM,IAAI,MAAM,sBAAsB,YAAY;AAEpD,WAAQ,IAAI,QAAQ,OAChB,KAAK,UAAU,SAAS,MAAM,EAAE,GAChC,mBAAmB,QAAQ,YAAY;YACnC;AACR,SAAM,OAAO,SAAS"}
@@ -19,6 +19,8 @@ import { ServiceCommands } from "../controllers/commands/service-command.control
19
19
  import { StopCommands } from "../controllers/commands/stop-command.controller.js";
20
20
  import { UiCommands } from "../controllers/commands/ui-command.controller.js";
21
21
  import { LlmUsageCommandService } from "../services/usage/llm-usage-command.service.js";
22
+ import { ProjectCommands } from "../controllers/commands/project/project-command.controller.js";
23
+ import { SessionCommands } from "../controllers/commands/session/session-command.controller.js";
22
24
  import { ServiceRestartManager } from "./service-restart.manager.js";
23
25
  import { ServiceWorkspaceManager } from "./service-workspace.manager.js";
24
26
  import { RemoteRuntimeActions } from "@nextclaw/remote";
@@ -43,6 +45,8 @@ type NextclawServiceCommands = {
43
45
  serve: ServeCommands;
44
46
  stop: StopCommands;
45
47
  usage: LlmUsageCommandService;
48
+ projects: ProjectCommands;
49
+ sessions: SessionCommands;
46
50
  };
47
51
  type ServiceCommandManagerDeps = {
48
52
  logo: string;
@@ -1 +1 @@
1
- {"version":3,"file":"service-command.manager.d.ts","names":[],"sources":["../../src/managers/service-command.manager.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;KA8BY,uBAAA;EACV,MAAA,EAAQ,oBAAA;EACR,MAAA,EAAQ,cAAA;EACR,OAAA,EAAS,eAAA;EACT,MAAA,EAAQ,cAAA;EACR,GAAA,EAAK,WAAA;EACL,OAAA,EAAS,eAAA;EACT,MAAA,EAAQ,aAAA;EACR,QAAA,EAAU,eAAA;EACV,IAAA,EAAM,YAAA;EACN,WAAA,EAAa,mBAAA;EACb,IAAA,EAAM,YAAA;EACN,OAAA,EAAS,eAAA;EACT,EAAA,EAAI,UAAA;EACJ,KAAA,EAAO,aAAA;EACP,OAAA,EAAS,eAAA;EACT,KAAA,EAAO,aAAA;EACP,IAAA,EAAM,YAAA;EACN,KAAA,EAAO,sBAAA;AAAA;AAAA,KAGJ,yBAAA;EACH,IAAA;EACA,IAAA,GAAO,MAAA;IAAU,MAAA;IAAiB,IAAA;IAAgB,KAAA;EAAA,MAAsB,OAAA;EACxE,cAAA,EAAgB,qBAAA;EAChB,OAAA,EAAS,qBAAA;EACT,SAAA,EAAW,uBAAA;AAAA;AAAA,cAGA,qBAAA;EAAA,iBAKkB,IAAA;EAAA,SAJpB,QAAA,EAAU,uBAAA;EAAA,SACV,YAAA,EAAc,oBAAA;EAAA,SACd,MAAA,EAAQ,cAAA;cAEY,IAAA,EAAM,yBAAA;AAAA"}
1
+ {"version":3,"file":"service-command.manager.d.ts","names":[],"sources":["../../src/managers/service-command.manager.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgCY,uBAAA;EACV,MAAA,EAAQ,oBAAA;EACR,MAAA,EAAQ,cAAA;EACR,OAAA,EAAS,eAAA;EACT,MAAA,EAAQ,cAAA;EACR,GAAA,EAAK,WAAA;EACL,OAAA,EAAS,eAAA;EACT,MAAA,EAAQ,aAAA;EACR,QAAA,EAAU,eAAA;EACV,IAAA,EAAM,YAAA;EACN,WAAA,EAAa,mBAAA;EACb,IAAA,EAAM,YAAA;EACN,OAAA,EAAS,eAAA;EACT,EAAA,EAAI,UAAA;EACJ,KAAA,EAAO,aAAA;EACP,OAAA,EAAS,eAAA;EACT,KAAA,EAAO,aAAA;EACP,IAAA,EAAM,YAAA;EACN,KAAA,EAAO,sBAAA;EACP,QAAA,EAAU,eAAA;EACV,QAAA,EAAU,eAAA;AAAA;AAAA,KAGP,yBAAA;EACH,IAAA;EACA,IAAA,GAAO,MAAA;IAAU,MAAA;IAAiB,IAAA;IAAgB,KAAA;EAAA,MAAsB,OAAA;EACxE,cAAA,EAAgB,qBAAA;EAChB,OAAA,EAAS,qBAAA;EACT,SAAA,EAAW,uBAAA;AAAA;AAAA,cAGA,qBAAA;EAAA,iBAKkB,IAAA;EAAA,SAJpB,QAAA,EAAU,uBAAA;EAAA,SACV,YAAA,EAAc,oBAAA;EAAA,SACd,MAAA,EAAQ,cAAA;cAEY,IAAA,EAAM,yBAAA;AAAA"}
@@ -25,8 +25,10 @@ import { StopCommands } from "../controllers/commands/stop-command.controller.js
25
25
  import { UiCommands } from "../controllers/commands/ui-command.controller.js";
26
26
  import { LlmUsageCommandService } from "../services/usage/llm-usage-command.service.js";
27
27
  import "../controllers/commands/usage-command.controller.js";
28
- import { APP_NAME } from "@nextclaw/core";
29
- import { AgentManager } from "@nextclaw/kernel";
28
+ import { ProjectCommands } from "../controllers/commands/project/project-command.controller.js";
29
+ import { SessionCommands } from "../controllers/commands/session/session-command.controller.js";
30
+ import { APP_NAME, getConfigPath, getDataDir } from "@nextclaw/core";
31
+ import { AgentManager, NextclawKernel } from "@nextclaw/kernel";
30
32
  import { RemoteRuntimeActions } from "@nextclaw/remote";
31
33
  //#region src/managers/service-command.manager.ts
32
34
  const FORCED_PUBLIC_UI_HOST = "0.0.0.0";
@@ -36,6 +38,10 @@ var ServiceCommandManager = class {
36
38
  remote;
37
39
  constructor(deps) {
38
40
  this.deps = deps;
41
+ const createKernel = () => new NextclawKernel({
42
+ homeDir: getDataDir(),
43
+ configPath: getConfigPath()
44
+ });
39
45
  const start = new StartCommands({
40
46
  runtimeCommandService: this.deps.managedService,
41
47
  forcedPublicHost: FORCED_PUBLIC_UI_HOST,
@@ -84,7 +90,9 @@ var ServiceCommandManager = class {
84
90
  forcedPublicHost: FORCED_PUBLIC_UI_HOST
85
91
  }),
86
92
  stop: new StopCommands({ runtimeCommandService: this.deps.managedService }),
87
- usage: new LlmUsageCommandService()
93
+ usage: new LlmUsageCommandService(),
94
+ projects: new ProjectCommands(createKernel),
95
+ sessions: new SessionCommands(createKernel)
88
96
  };
89
97
  }
90
98
  };
@@ -1 +1 @@
1
- {"version":3,"file":"service-command.manager.js","names":[],"sources":["../../src/managers/service-command.manager.ts"],"sourcesContent":["import { APP_NAME } from \"@nextclaw/core\";\nimport { AgentManager } from \"@nextclaw/kernel\";\nimport { RemoteRuntimeActions } from \"@nextclaw/remote\";\nimport { AgentCommands, runCliAgentCommand } from \"@nextclaw-service/controllers/commands/agent-command.controller.js\";\nimport { ChannelCommands } from \"@nextclaw-service/controllers/commands/channel-command.controller.js\";\nimport { ConfigCommands } from \"@nextclaw-service/controllers/commands/config-command.controller.js\";\nimport { CronCommands } from \"@nextclaw-service/controllers/commands/cron-command.controller.js\";\nimport { DiagnosticsCommands } from \"@nextclaw-service/controllers/commands/diagnostics-command.controller.js\";\nimport { GatewayCommands } from \"@nextclaw-service/controllers/commands/gateway-command.controller.js\";\nimport { LogsCommands } from \"@nextclaw-service/controllers/commands/logs-command.controller.js\";\nimport { SkillsCommands } from \"@nextclaw-service/controllers/commands/marketplace-skill-command.controller.js\";\nimport { McpCommands } from \"@nextclaw-service/controllers/commands/mcp-command.controller.js\";\nimport { PlatformAuthCommands } from \"@nextclaw-service/controllers/commands/platform-auth-command.controller.js\";\nimport { RemoteCommands, hasRunningNextclawManagedService } from \"@nextclaw-service/controllers/commands/remote-command.controller.js\";\nimport { RestartCommands } from \"@nextclaw-service/controllers/commands/restart-command.controller.js\";\nimport { SecretsCommands } from \"@nextclaw-service/controllers/commands/secrets-command.controller.js\";\nimport { ServeCommands } from \"@nextclaw-service/controllers/commands/serve-command.controller.js\";\nimport { ServiceCommands } from \"@nextclaw-service/controllers/commands/service-command.controller.js\";\nimport { StartCommands } from \"@nextclaw-service/controllers/commands/start-command.controller.js\";\nimport { StopCommands } from \"@nextclaw-service/controllers/commands/stop-command.controller.js\";\nimport { UiCommands } from \"@nextclaw-service/controllers/commands/ui-command.controller.js\";\nimport { LlmUsageCommandService } from \"@nextclaw-service/controllers/commands/usage-command.controller.js\";\nimport type { ManagedServiceManager } from \"@nextclaw-service/managers/managed-service.manager.js\";\nimport type { ServiceRestartManager } from \"@nextclaw-service/managers/service-restart.manager.js\";\nimport type { ServiceWorkspaceManager } from \"@nextclaw-service/managers/service-workspace.manager.js\";\n\nconst FORCED_PUBLIC_UI_HOST = \"0.0.0.0\";\n\nexport { runCliAgentCommand };\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\ntype ServiceCommandManagerDeps = {\n logo: string;\n init: (params: { source?: string; auto?: boolean; force?: boolean }) => Promise<void>;\n managedService: ManagedServiceManager;\n restart: ServiceRestartManager;\n workspace: ServiceWorkspaceManager;\n};\n\nexport class ServiceCommandManager {\n readonly commands: NextclawServiceCommands;\n readonly platformAuth: PlatformAuthCommands;\n readonly remote: RemoteCommands;\n\n constructor(private readonly deps: ServiceCommandManagerDeps) {\n const start = new StartCommands({\n runtimeCommandService: this.deps.managedService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST,\n init: (params) => this.deps.init(params)\n });\n this.platformAuth = new PlatformAuthCommands();\n this.remote = new RemoteCommands();\n this.commands = {\n remote: new RemoteRuntimeActions({\n appName: APP_NAME,\n initAuto: (source) => this.deps.init({ source, auto: true }),\n remoteCommands: this.remote,\n restartBackgroundService: (reason) => this.deps.restart.restartBackgroundService(reason),\n hasRunningManagedService: hasRunningNextclawManagedService\n }),\n skills: new SkillsCommands(),\n service: new ServiceCommands(),\n config: new ConfigCommands({\n requestRestart: (params) => this.deps.restart.requestRestart(params),\n }),\n mcp: new McpCommands(),\n secrets: new SecretsCommands({\n requestRestart: (params) => this.deps.restart.requestRestart(params),\n }),\n agents: new AgentCommands(new AgentManager(undefined, {\n initializeAgentHomeDirectory: (homeDirectory) =>\n this.deps.workspace.createWorkspaceTemplates(homeDirectory),\n })),\n channels: new ChannelCommands({\n requestRestart: (params) => this.deps.restart.requestRestart(params),\n }),\n cron: new CronCommands(),\n diagnostics: new DiagnosticsCommands({ logo: this.deps.logo }),\n logs: new LogsCommands(),\n gateway: new GatewayCommands({\n runtimeCommandService: this.deps.managedService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n }),\n ui: new UiCommands({\n runtimeCommandService: this.deps.managedService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n }),\n start,\n restart: new RestartCommands({\n runtimeCommandService: this.deps.managedService,\n startCommands: start,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST,\n writeRestartSentinelFromExecContext: (reason) => this.deps.restart.writeRestartSentinelFromExecContext(reason)\n }),\n serve: new ServeCommands({\n runtimeCommandService: this.deps.managedService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n }),\n stop: new StopCommands({\n runtimeCommandService: this.deps.managedService\n }),\n usage: new LlmUsageCommandService(),\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,wBAAwB;AAiC9B,IAAa,wBAAb,MAAmC;CACjC;CACA;CACA;CAEA,YAAY,MAAkD;AAAjC,OAAA,OAAA;EAC3B,MAAM,QAAQ,IAAI,cAAc;GAC9B,uBAAuB,KAAK,KAAK;GACjC,kBAAkB;GAClB,OAAO,WAAW,KAAK,KAAK,KAAK,OAAO;GACzC,CAAC;AACF,OAAK,eAAe,IAAI,sBAAsB;AAC9C,OAAK,SAAS,IAAI,gBAAgB;AAClC,OAAK,WAAW;GACd,QAAQ,IAAI,qBAAqB;IAC/B,SAAS;IACT,WAAW,WAAW,KAAK,KAAK,KAAK;KAAE;KAAQ,MAAM;KAAM,CAAC;IAC5D,gBAAgB,KAAK;IACrB,2BAA2B,WAAW,KAAK,KAAK,QAAQ,yBAAyB,OAAO;IACxF,0BAA0B;IAC3B,CAAC;GACF,QAAQ,IAAI,gBAAgB;GAC5B,SAAS,IAAI,iBAAiB;GAC9B,QAAQ,IAAI,eAAe,EACzB,iBAAiB,WAAW,KAAK,KAAK,QAAQ,eAAe,OAAO,EACrE,CAAC;GACF,KAAK,IAAI,aAAa;GACtB,SAAS,IAAI,gBAAgB,EAC3B,iBAAiB,WAAW,KAAK,KAAK,QAAQ,eAAe,OAAO,EACrE,CAAC;GACF,QAAQ,IAAI,cAAc,IAAI,aAAa,KAAA,GAAW,EACpD,+BAA+B,kBAC7B,KAAK,KAAK,UAAU,yBAAyB,cAAc,EAC9D,CAAC,CAAC;GACH,UAAU,IAAI,gBAAgB,EAC5B,iBAAiB,WAAW,KAAK,KAAK,QAAQ,eAAe,OAAO,EACrE,CAAC;GACF,MAAM,IAAI,cAAc;GACxB,aAAa,IAAI,oBAAoB,EAAE,MAAM,KAAK,KAAK,MAAM,CAAC;GAC9D,MAAM,IAAI,cAAc;GACxB,SAAS,IAAI,gBAAgB;IAC3B,uBAAuB,KAAK,KAAK;IACjC,kBAAkB;IACnB,CAAC;GACF,IAAI,IAAI,WAAW;IACjB,uBAAuB,KAAK,KAAK;IACjC,kBAAkB;IACnB,CAAC;GACF;GACA,SAAS,IAAI,gBAAgB;IAC3B,uBAAuB,KAAK,KAAK;IACjC,eAAe;IACf,kBAAkB;IAClB,sCAAsC,WAAW,KAAK,KAAK,QAAQ,oCAAoC,OAAO;IAC/G,CAAC;GACF,OAAO,IAAI,cAAc;IACvB,uBAAuB,KAAK,KAAK;IACjC,kBAAkB;IACnB,CAAC;GACF,MAAM,IAAI,aAAa,EACrB,uBAAuB,KAAK,KAAK,gBAClC,CAAC;GACF,OAAO,IAAI,wBAAwB;GACpC"}
1
+ {"version":3,"file":"service-command.manager.js","names":[],"sources":["../../src/managers/service-command.manager.ts"],"sourcesContent":["import { APP_NAME, getConfigPath, getDataDir } from \"@nextclaw/core\";\nimport { AgentManager, NextclawKernel } from \"@nextclaw/kernel\";\nimport { RemoteRuntimeActions } from \"@nextclaw/remote\";\nimport { AgentCommands, runCliAgentCommand } from \"@nextclaw-service/controllers/commands/agent-command.controller.js\";\nimport { ChannelCommands } from \"@nextclaw-service/controllers/commands/channel-command.controller.js\";\nimport { ConfigCommands } from \"@nextclaw-service/controllers/commands/config-command.controller.js\";\nimport { CronCommands } from \"@nextclaw-service/controllers/commands/cron-command.controller.js\";\nimport { DiagnosticsCommands } from \"@nextclaw-service/controllers/commands/diagnostics-command.controller.js\";\nimport { GatewayCommands } from \"@nextclaw-service/controllers/commands/gateway-command.controller.js\";\nimport { LogsCommands } from \"@nextclaw-service/controllers/commands/logs-command.controller.js\";\nimport { SkillsCommands } from \"@nextclaw-service/controllers/commands/marketplace-skill-command.controller.js\";\nimport { McpCommands } from \"@nextclaw-service/controllers/commands/mcp-command.controller.js\";\nimport { PlatformAuthCommands } from \"@nextclaw-service/controllers/commands/platform-auth-command.controller.js\";\nimport { RemoteCommands, hasRunningNextclawManagedService } from \"@nextclaw-service/controllers/commands/remote-command.controller.js\";\nimport { RestartCommands } from \"@nextclaw-service/controllers/commands/restart-command.controller.js\";\nimport { SecretsCommands } from \"@nextclaw-service/controllers/commands/secrets-command.controller.js\";\nimport { ServeCommands } from \"@nextclaw-service/controllers/commands/serve-command.controller.js\";\nimport { ServiceCommands } from \"@nextclaw-service/controllers/commands/service-command.controller.js\";\nimport { StartCommands } from \"@nextclaw-service/controllers/commands/start-command.controller.js\";\nimport { StopCommands } from \"@nextclaw-service/controllers/commands/stop-command.controller.js\";\nimport { UiCommands } from \"@nextclaw-service/controllers/commands/ui-command.controller.js\";\nimport { LlmUsageCommandService } from \"@nextclaw-service/controllers/commands/usage-command.controller.js\";\nimport { ProjectCommands } from \"@nextclaw-service/controllers/commands/project/project-command.controller.js\";\nimport { SessionCommands } from \"@nextclaw-service/controllers/commands/session/session-command.controller.js\";\nimport type { ManagedServiceManager } from \"@nextclaw-service/managers/managed-service.manager.js\";\nimport type { ServiceRestartManager } from \"@nextclaw-service/managers/service-restart.manager.js\";\nimport type { ServiceWorkspaceManager } from \"@nextclaw-service/managers/service-workspace.manager.js\";\n\nconst FORCED_PUBLIC_UI_HOST = \"0.0.0.0\";\n\nexport { runCliAgentCommand };\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 projects: ProjectCommands;\n sessions: SessionCommands;\n};\n\ntype ServiceCommandManagerDeps = {\n logo: string;\n init: (params: { source?: string; auto?: boolean; force?: boolean }) => Promise<void>;\n managedService: ManagedServiceManager;\n restart: ServiceRestartManager;\n workspace: ServiceWorkspaceManager;\n};\n\nexport class ServiceCommandManager {\n readonly commands: NextclawServiceCommands;\n readonly platformAuth: PlatformAuthCommands;\n readonly remote: RemoteCommands;\n\n constructor(private readonly deps: ServiceCommandManagerDeps) {\n const createKernel = () => new NextclawKernel({\n homeDir: getDataDir(),\n configPath: getConfigPath(),\n });\n const start = new StartCommands({\n runtimeCommandService: this.deps.managedService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST,\n init: (params) => this.deps.init(params)\n });\n this.platformAuth = new PlatformAuthCommands();\n this.remote = new RemoteCommands();\n this.commands = {\n remote: new RemoteRuntimeActions({\n appName: APP_NAME,\n initAuto: (source) => this.deps.init({ source, auto: true }),\n remoteCommands: this.remote,\n restartBackgroundService: (reason) => this.deps.restart.restartBackgroundService(reason),\n hasRunningManagedService: hasRunningNextclawManagedService\n }),\n skills: new SkillsCommands(),\n service: new ServiceCommands(),\n config: new ConfigCommands({\n requestRestart: (params) => this.deps.restart.requestRestart(params),\n }),\n mcp: new McpCommands(),\n secrets: new SecretsCommands({\n requestRestart: (params) => this.deps.restart.requestRestart(params),\n }),\n agents: new AgentCommands(new AgentManager(undefined, {\n initializeAgentHomeDirectory: (homeDirectory) =>\n this.deps.workspace.createWorkspaceTemplates(homeDirectory),\n })),\n channels: new ChannelCommands({\n requestRestart: (params) => this.deps.restart.requestRestart(params),\n }),\n cron: new CronCommands(),\n diagnostics: new DiagnosticsCommands({ logo: this.deps.logo }),\n logs: new LogsCommands(),\n gateway: new GatewayCommands({\n runtimeCommandService: this.deps.managedService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n }),\n ui: new UiCommands({\n runtimeCommandService: this.deps.managedService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n }),\n start,\n restart: new RestartCommands({\n runtimeCommandService: this.deps.managedService,\n startCommands: start,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST,\n writeRestartSentinelFromExecContext: (reason) => this.deps.restart.writeRestartSentinelFromExecContext(reason)\n }),\n serve: new ServeCommands({\n runtimeCommandService: this.deps.managedService,\n forcedPublicHost: FORCED_PUBLIC_UI_HOST\n }),\n stop: new StopCommands({\n runtimeCommandService: this.deps.managedService\n }),\n usage: new LlmUsageCommandService(),\n projects: new ProjectCommands(createKernel),\n sessions: new SessionCommands(createKernel),\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAM,wBAAwB;AAmC9B,IAAa,wBAAb,MAAmC;CACjC;CACA;CACA;CAEA,YAAY,MAAkD;AAAjC,OAAA,OAAA;EAC3B,MAAM,qBAAqB,IAAI,eAAe;GAC5C,SAAS,YAAY;GACrB,YAAY,eAAe;GAC5B,CAAC;EACF,MAAM,QAAQ,IAAI,cAAc;GAC9B,uBAAuB,KAAK,KAAK;GACjC,kBAAkB;GAClB,OAAO,WAAW,KAAK,KAAK,KAAK,OAAO;GACzC,CAAC;AACF,OAAK,eAAe,IAAI,sBAAsB;AAC9C,OAAK,SAAS,IAAI,gBAAgB;AAClC,OAAK,WAAW;GACd,QAAQ,IAAI,qBAAqB;IAC/B,SAAS;IACT,WAAW,WAAW,KAAK,KAAK,KAAK;KAAE;KAAQ,MAAM;KAAM,CAAC;IAC5D,gBAAgB,KAAK;IACrB,2BAA2B,WAAW,KAAK,KAAK,QAAQ,yBAAyB,OAAO;IACxF,0BAA0B;IAC3B,CAAC;GACF,QAAQ,IAAI,gBAAgB;GAC5B,SAAS,IAAI,iBAAiB;GAC9B,QAAQ,IAAI,eAAe,EACzB,iBAAiB,WAAW,KAAK,KAAK,QAAQ,eAAe,OAAO,EACrE,CAAC;GACF,KAAK,IAAI,aAAa;GACtB,SAAS,IAAI,gBAAgB,EAC3B,iBAAiB,WAAW,KAAK,KAAK,QAAQ,eAAe,OAAO,EACrE,CAAC;GACF,QAAQ,IAAI,cAAc,IAAI,aAAa,KAAA,GAAW,EACpD,+BAA+B,kBAC7B,KAAK,KAAK,UAAU,yBAAyB,cAAc,EAC9D,CAAC,CAAC;GACH,UAAU,IAAI,gBAAgB,EAC5B,iBAAiB,WAAW,KAAK,KAAK,QAAQ,eAAe,OAAO,EACrE,CAAC;GACF,MAAM,IAAI,cAAc;GACxB,aAAa,IAAI,oBAAoB,EAAE,MAAM,KAAK,KAAK,MAAM,CAAC;GAC9D,MAAM,IAAI,cAAc;GACxB,SAAS,IAAI,gBAAgB;IAC3B,uBAAuB,KAAK,KAAK;IACjC,kBAAkB;IACnB,CAAC;GACF,IAAI,IAAI,WAAW;IACjB,uBAAuB,KAAK,KAAK;IACjC,kBAAkB;IACnB,CAAC;GACF;GACA,SAAS,IAAI,gBAAgB;IAC3B,uBAAuB,KAAK,KAAK;IACjC,eAAe;IACf,kBAAkB;IAClB,sCAAsC,WAAW,KAAK,KAAK,QAAQ,oCAAoC,OAAO;IAC/G,CAAC;GACF,OAAO,IAAI,cAAc;IACvB,uBAAuB,KAAK,KAAK;IACjC,kBAAkB;IACnB,CAAC;GACF,MAAM,IAAI,aAAa,EACrB,uBAAuB,KAAK,KAAK,gBAClC,CAAC;GACF,OAAO,IAAI,wBAAwB;GACnC,UAAU,IAAI,gBAAgB,aAAa;GAC3C,UAAU,IAAI,gBAAgB,aAAa;GAC5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"service-restart.manager.d.ts","names":[],"sources":["../../src/managers/service-restart.manager.ts"],"mappings":";;;;KAYK,yBAAA;EACH,cAAA,EAAgB,qBAAA;AAAA;AAAA,cAGL,qBAAA;EAAA,iBAWkB,IAAA;EAAA,iBAVZ,kBAAA;EAAA,QAOT,kBAAA;EAAA,QACA,iBAAA;cAEqB,IAAA,EAAM,yBAAA;EAEnC,cAAA,GAAwB,MAAA,EAAQ,oBAAA,KAAuB,OAAA;EAgDvD,wBAAA,GAAkC,MAAA,aAAiB,OAAA;EAsCnD,mCAAA,GAA6C,MAAA,aAAiB,OAAA;EAAA,QA0BtD,mBAAA;EAAA,QAOA,yBAAA;AAAA"}
1
+ {"version":3,"file":"service-restart.manager.d.ts","names":[],"sources":["../../src/managers/service-restart.manager.ts"],"mappings":";;;;KAaK,yBAAA;EACH,cAAA,EAAgB,qBAAA;AAAA;AAAA,cAGL,qBAAA;EAAA,iBAWkB,IAAA;EAAA,iBAVZ,kBAAA;EAAA,QAOT,kBAAA;EAAA,QACA,iBAAA;cAEqB,IAAA,EAAM,yBAAA;EAEnC,cAAA,GAAwB,MAAA,EAAQ,oBAAA,KAAuB,OAAA;EAgDvD,wBAAA,GAAkC,MAAA,aAAiB,OAAA;EAsCnD,mCAAA,GAA6C,MAAA,aAAiB,OAAA;EAAA,QA0BtD,mBAAA;EAAA,QAOA,yBAAA;AAAA"}
@@ -2,6 +2,7 @@ import { isProcessRunning } from "../utils/cli.utils.js";
2
2
  import { managedServiceStateStore } from "../stores/managed-service-state.store.js";
3
3
  import { resolveCliSubcommandLaunch } from "../utils/marketplace/cli-subcommand-launch.utils.js";
4
4
  import { createTopLevelNextclawCommandEnv } from "../utils/top-level-nextclaw-command-env.utils.js";
5
+ import { NextclawDistributionService } from "../services/runtime/nextclaw-distribution.service.js";
5
6
  import { writeRestartSentinel } from "../utils/restart-sentinel.utils.js";
6
7
  import { pendingRestartStore } from "../stores/pending-restart.store.js";
7
8
  import { RestartCoordinator } from "../services/restart/restart-coordinator.service.js";
@@ -104,8 +105,7 @@ var ServiceRestartManager = class {
104
105
  }, delayMs);
105
106
  };
106
107
  armManagedServiceRelaunch = (params) => {
107
- const { delayMs: requestedDelayMs, reason, strategy: requestedStrategy } = params;
108
- const strategy = requestedStrategy ?? "background-service-or-manual";
108
+ const { delayMs: requestedDelayMs, reason, strategy = "background-service-or-manual" } = params;
109
109
  if (strategy !== "background-service-or-exit" && strategy !== "exit-process") return;
110
110
  if (this.selfRelaunchArmed) return;
111
111
  const state = managedServiceStateStore.read();
@@ -113,14 +113,13 @@ var ServiceRestartManager = class {
113
113
  const uiPort = typeof state.uiPort === "number" && Number.isFinite(state.uiPort) ? state.uiPort : 55667;
114
114
  const delayMs = typeof requestedDelayMs === "number" && Number.isFinite(requestedDelayMs) ? Math.max(0, Math.floor(requestedDelayMs)) : 100;
115
115
  const launch = resolveCliSubcommandLaunch({
116
- argvEntry: process.argv[1],
116
+ argvEntry: NextclawDistributionService.get().launcherEntrypoint,
117
117
  importMetaUrl: import.meta.url,
118
118
  cliArgs: [
119
119
  "start",
120
120
  "--ui-port",
121
121
  String(uiPort)
122
- ],
123
- nodePath: process.execPath
122
+ ]
124
123
  });
125
124
  const serviceStatePath = managedServiceStateStore.path;
126
125
  const helperScript = `
@@ -1 +1 @@
1
- {"version":3,"file":"service-restart.manager.js","names":[],"sources":["../../src/managers/service-restart.manager.ts"],"sourcesContent":["import { APP_NAME } from \"@nextclaw/core\";\nimport { spawn } from \"node:child_process\";\nimport type { ManagedServiceManager } from \"@nextclaw-service/managers/managed-service.manager.js\";\nimport { RestartCoordinator } from \"@nextclaw-service/services/restart/restart-coordinator.service.js\";\nimport { managedServiceStateStore } from \"@nextclaw-service/stores/managed-service-state.store.js\";\nimport { pendingRestartStore } from \"@nextclaw-service/stores/pending-restart.store.js\";\nimport type { RequestRestartParams } from \"@nextclaw-service/types/cli.types.js\";\nimport { isProcessRunning } from \"@nextclaw-service/utils/cli.utils.js\";\nimport { resolveCliSubcommandLaunch } from \"@nextclaw-service/utils/marketplace/cli-subcommand-launch.utils.js\";\nimport { writeRestartSentinel } from \"@nextclaw-service/utils/restart-sentinel.utils.js\";\nimport { createTopLevelNextclawCommandEnv } from \"@nextclaw-service/utils/top-level-nextclaw-command-env.utils.js\";\n\ntype ServiceRestartManagerDeps = {\n managedService: ManagedServiceManager;\n};\n\nexport class ServiceRestartManager {\n private readonly restartCoordinator = new RestartCoordinator({\n readServiceState: managedServiceStateStore.read,\n isProcessRunning,\n currentPid: () => process.pid,\n restartBackgroundService: async (reason) => this.restartBackgroundService(reason),\n scheduleProcessExit: (delayMs, reason) => this.scheduleProcessExit(delayMs, reason),\n });\n private serviceRestartTask: Promise<boolean> | null = null;\n private selfRelaunchArmed = false;\n\n constructor(private readonly deps: ServiceRestartManagerDeps) {}\n\n requestRestart = async (params: RequestRestartParams): Promise<void> => {\n const {\n changedPaths,\n delayMs,\n manualMessage,\n mode,\n reason,\n silentOnServiceRestart,\n strategy\n } = params;\n if (mode === \"notify\") {\n pendingRestartStore.mark({\n changedPaths,\n manualMessage,\n reason\n });\n console.warn(manualMessage);\n return;\n }\n\n this.armManagedServiceRelaunch({\n reason,\n strategy,\n delayMs\n });\n\n const result = await this.restartCoordinator.requestRestart({\n reason,\n strategy,\n delayMs,\n manualMessage\n });\n if (result.status === \"manual-required\" || result.status === \"restart-in-progress\") {\n console.log(result.message);\n return;\n }\n\n pendingRestartStore.clear();\n if (result.status === \"service-restarted\") {\n if (!silentOnServiceRestart) {\n console.log(result.message);\n }\n return;\n }\n\n console.warn(result.message);\n };\n\n 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 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.deps.managedService.stopService();\n await this.deps.managedService.startService({\n uiOverrides: {\n enabled: true,\n host: \"0.0.0.0\",\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 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 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 armManagedServiceRelaunch = (params: {\n reason: string;\n strategy?: RequestRestartParams[\"strategy\"];\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 = `\nconst { spawnSync } = require(\"node:child_process\");\nconst { readFileSync } = require(\"node:fs\");\nconst parentPid = ${process.pid};\nconst delayMs = ${delayMs};\nconst maxWaitMs = 120000;\nconst retryIntervalMs = 1000;\nconst command = ${JSON.stringify(launch.command)};\nconst args = ${JSON.stringify(launch.args)};\nconst serviceStatePath = ${JSON.stringify(serviceStatePath)};\nfunction isRunning(pid) {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\nfunction hasReplacementService() {\n try {\n const state = JSON.parse(readFileSync(serviceStatePath, \"utf-8\"));\n const pid = Number(state?.pid);\n return Number.isFinite(pid) && pid > 0 && pid !== parentPid && isRunning(pid);\n } catch { return false; }\n}\nfunction tryStart() {\n spawnSync(command, args, { stdio: \"ignore\", env: process.env, timeout: 60000, windowsHide: true });\n}\nsetTimeout(() => {\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`.trim();\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"],"mappings":"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"}
1
+ {"version":3,"file":"service-restart.manager.js","names":[],"sources":["../../src/managers/service-restart.manager.ts"],"sourcesContent":["import { APP_NAME } from \"@nextclaw/core\";\nimport { spawn } from \"node:child_process\";\nimport type { ManagedServiceManager } from \"@nextclaw-service/managers/managed-service.manager.js\";\nimport { NextclawDistributionService } from \"@nextclaw-service/services/runtime/nextclaw-distribution.service.js\";\nimport { RestartCoordinator } from \"@nextclaw-service/services/restart/restart-coordinator.service.js\";\nimport { managedServiceStateStore } from \"@nextclaw-service/stores/managed-service-state.store.js\";\nimport { pendingRestartStore } from \"@nextclaw-service/stores/pending-restart.store.js\";\nimport type { RequestRestartParams } from \"@nextclaw-service/types/cli.types.js\";\nimport { isProcessRunning } from \"@nextclaw-service/utils/cli.utils.js\";\nimport { resolveCliSubcommandLaunch } from \"@nextclaw-service/utils/marketplace/cli-subcommand-launch.utils.js\";\nimport { writeRestartSentinel } from \"@nextclaw-service/utils/restart-sentinel.utils.js\";\nimport { createTopLevelNextclawCommandEnv } from \"@nextclaw-service/utils/top-level-nextclaw-command-env.utils.js\";\n\ntype ServiceRestartManagerDeps = {\n managedService: ManagedServiceManager;\n};\n\nexport class ServiceRestartManager {\n private readonly restartCoordinator = new RestartCoordinator({\n readServiceState: managedServiceStateStore.read,\n isProcessRunning,\n currentPid: () => process.pid,\n restartBackgroundService: async (reason) => this.restartBackgroundService(reason),\n scheduleProcessExit: (delayMs, reason) => this.scheduleProcessExit(delayMs, reason),\n });\n private serviceRestartTask: Promise<boolean> | null = null;\n private selfRelaunchArmed = false;\n\n constructor(private readonly deps: ServiceRestartManagerDeps) {}\n\n requestRestart = async (params: RequestRestartParams): Promise<void> => {\n const {\n changedPaths,\n delayMs,\n manualMessage,\n mode,\n reason,\n silentOnServiceRestart,\n strategy\n } = params;\n if (mode === \"notify\") {\n pendingRestartStore.mark({\n changedPaths,\n manualMessage,\n reason\n });\n console.warn(manualMessage);\n return;\n }\n\n this.armManagedServiceRelaunch({\n reason,\n strategy,\n delayMs\n });\n\n const result = await this.restartCoordinator.requestRestart({\n reason,\n strategy,\n delayMs,\n manualMessage\n });\n if (result.status === \"manual-required\" || result.status === \"restart-in-progress\") {\n console.log(result.message);\n return;\n }\n\n pendingRestartStore.clear();\n if (result.status === \"service-restarted\") {\n if (!silentOnServiceRestart) {\n console.log(result.message);\n }\n return;\n }\n\n console.warn(result.message);\n };\n\n 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 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.deps.managedService.stopService();\n await this.deps.managedService.startService({\n uiOverrides: {\n enabled: true,\n host: \"0.0.0.0\",\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 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 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 armManagedServiceRelaunch = (params: {\n reason: string;\n strategy?: RequestRestartParams[\"strategy\"];\n delayMs?: number;\n }): void => {\n const { delayMs: requestedDelayMs, reason, strategy = \"background-service-or-manual\" } = params;\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: NextclawDistributionService.get().launcherEntrypoint,\n importMetaUrl: import.meta.url,\n cliArgs: [\"start\", \"--ui-port\", String(uiPort)]\n });\n const serviceStatePath = managedServiceStateStore.path;\n const helperScript = `\nconst { spawnSync } = require(\"node:child_process\");\nconst { readFileSync } = require(\"node:fs\");\nconst parentPid = ${process.pid};\nconst delayMs = ${delayMs};\nconst maxWaitMs = 120000;\nconst retryIntervalMs = 1000;\nconst command = ${JSON.stringify(launch.command)};\nconst args = ${JSON.stringify(launch.args)};\nconst serviceStatePath = ${JSON.stringify(serviceStatePath)};\nfunction isRunning(pid) {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\nfunction hasReplacementService() {\n try {\n const state = JSON.parse(readFileSync(serviceStatePath, \"utf-8\"));\n const pid = Number(state?.pid);\n return Number.isFinite(pid) && pid > 0 && pid !== parentPid && isRunning(pid);\n } catch { return false; }\n}\nfunction tryStart() {\n spawnSync(command, args, { stdio: \"ignore\", env: process.env, timeout: 60000, windowsHide: true });\n}\nsetTimeout(() => {\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`.trim();\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"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"npm-runtime-update-host.service.d.ts","names":[],"sources":["../../../src/services/runtime/npm-runtime-update-host.service.ts"],"mappings":";;;;;;KAyBK,wBAAA;EACH,QAAA,EAAU,QAAA;EACV,cAAA,GAAiB,MAAA,EAAQ,oBAAA,KAAyB,OAAA;EAClD,QAAA,EAAU,IAAA,CAAK,MAAA;EACf,gBAAA;AAAA;AAAA,cAGW,oBAAA,YAAgC,mBAAA;EAAA,iBAWd,IAAA;EAAA,iBAVZ,MAAA;EAAA,iBACA,MAAA;EAAA,iBACA,eAAA;EAAA,iBACA,UAAA;EAAA,iBACA,aAAA;EAAA,iBACA,aAAA;EAAA,QACT,QAAA;EAAA,QACA,UAAA;EAAA,QACA,oBAAA;cAEqB,IAAA,EAAM,wBAAA;EAyBnC,QAAA,QAAqB,OAAA,CAAQ,cAAA;EAK7B,eAAA,QAA4B,OAAA,CAAQ,cAAA;EAIpC,cAAA,QAA2B,OAAA,CAAQ,cAAA;EAInC,qBAAA,QAAkC,OAAA,CAAQ,cAAA;EAkC1C,iBAAA,GAA2B,WAAA,EAAa,OAAA,CAAQ,iBAAA,MAAqB,OAAA,CAAQ,cAAA;EAe7E,aAAA,GAAuB,OAAA,EAAS,cAAA,gBAA4B,OAAA,CAAQ,cAAA;EAAA,QAY5D,kBAAA;EAAA,QAeA,UAAA;EAAA,QA2BA,aAAA;EAAA,QAuBA,eAAA;EAAA,QAYA,aAAA;EAAA,QAYA,gBAAA;EAAA,QASA,WAAA;AAAA"}
1
+ {"version":3,"file":"npm-runtime-update-host.service.d.ts","names":[],"sources":["../../../src/services/runtime/npm-runtime-update-host.service.ts"],"mappings":";;;;;;KAyBK,wBAAA;EACH,QAAA,EAAU,QAAA;EACV,cAAA,GAAiB,MAAA,EAAQ,oBAAA,KAAyB,OAAA;EAClD,QAAA,EAAU,IAAA,CAAK,MAAA;EACf,gBAAA;AAAA;AAAA,cAGW,oBAAA,YAAgC,mBAAA;EAAA,iBAWd,IAAA;EAAA,iBAVZ,MAAA;EAAA,iBACA,MAAA;EAAA,iBACA,eAAA;EAAA,iBACA,UAAA;EAAA,iBACA,aAAA;EAAA,iBACA,aAAA;EAAA,QACT,QAAA;EAAA,QACA,UAAA;EAAA,QACA,oBAAA;cAEqB,IAAA,EAAM,wBAAA;EAyBnC,QAAA,QAAqB,OAAA,CAAQ,cAAA;EAK7B,eAAA,QAA4B,OAAA,CAAQ,cAAA;EAIpC,cAAA,QAA2B,OAAA,CAAQ,cAAA;EAInC,qBAAA,QAAkC,OAAA,CAAQ,cAAA;EAkC1C,iBAAA,GAA2B,WAAA,EAAa,OAAA,CAAQ,iBAAA,MAAqB,OAAA,CAAQ,cAAA;EAe7E,aAAA,GAAuB,OAAA,EAAS,cAAA,gBAA4B,OAAA,CAAQ,cAAA;EAAA,QAY5D,kBAAA;EAAA,QAeA,UAAA;EAAA,QA0BA,aAAA;EAAA,QAsBA,eAAA;EAAA,QAYA,aAAA;EAAA,QAYA,gBAAA;EAAA,QASA,WAAA;AAAA"}
@@ -108,43 +108,47 @@ var NpmRuntimeUpdateHost = class {
108
108
  this.startCheck({ autoDownload: state.updatePreferences.autoDownload });
109
109
  };
110
110
  startCheck = async (options) => {
111
- if (this.activeTask) return this.snapshot;
112
- this.setSnapshot({
113
- ...this.createManager().getSnapshot(),
114
- status: "checking",
115
- progress: null,
116
- errorMessage: null
117
- });
118
- this.activeTask = (async () => {
119
- try {
120
- const checkedSnapshot = await this.createManager().checkForUpdate();
121
- this.setSnapshot(checkedSnapshot);
122
- if (options.autoDownload && checkedSnapshot.status === "update-available") await this.runDownloadTask();
123
- } catch (error) {
124
- this.setSnapshot(this.toFailedSnapshot(error));
125
- } finally {
126
- this.activeTask = null;
127
- }
128
- })();
111
+ if (!this.activeTask) {
112
+ this.setSnapshot({
113
+ ...this.createManager().getSnapshot(),
114
+ status: "checking",
115
+ progress: null,
116
+ errorMessage: null
117
+ });
118
+ this.activeTask = (async () => {
119
+ try {
120
+ const checkedSnapshot = await this.createManager().checkForUpdate();
121
+ this.setSnapshot(checkedSnapshot);
122
+ if (options.autoDownload && checkedSnapshot.status === "update-available") await this.runDownloadTask();
123
+ } catch (error) {
124
+ this.setSnapshot(this.toFailedSnapshot(error));
125
+ } finally {
126
+ this.activeTask = null;
127
+ }
128
+ })();
129
+ }
130
+ await this.activeTask;
129
131
  return this.snapshot;
130
132
  };
131
133
  startDownload = async () => {
132
- if (this.activeTask) return this.snapshot;
133
- this.setSnapshot({
134
- ...this.createManager().getSnapshot(),
135
- status: "downloading",
136
- progress: INITIAL_DOWNLOAD_PROGRESS,
137
- errorMessage: null
138
- });
139
- this.activeTask = (async () => {
140
- try {
141
- await this.runDownloadTask();
142
- } catch (error) {
143
- this.setSnapshot(this.toFailedSnapshot(error));
144
- } finally {
145
- this.activeTask = null;
146
- }
147
- })();
134
+ if (!this.activeTask) {
135
+ this.setSnapshot({
136
+ ...this.createManager().getSnapshot(),
137
+ status: "downloading",
138
+ progress: INITIAL_DOWNLOAD_PROGRESS,
139
+ errorMessage: null
140
+ });
141
+ this.activeTask = (async () => {
142
+ try {
143
+ await this.runDownloadTask();
144
+ } catch (error) {
145
+ this.setSnapshot(this.toFailedSnapshot(error));
146
+ } finally {
147
+ this.activeTask = null;
148
+ }
149
+ })();
150
+ }
151
+ await this.activeTask;
148
152
  return this.snapshot;
149
153
  };
150
154
  runDownloadTask = async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"npm-runtime-update-host.service.js","names":[],"sources":["../../../src/services/runtime/npm-runtime-update-host.service.ts"],"sourcesContent":["import type { Config } from \"@nextclaw/core\";\nimport {\n eventKeys,\n type EventBus,\n type UpdatePreferences,\n type UpdateProgress,\n type UpdateSnapshot,\n} from \"@nextclaw/shared\";\nimport type { UiRuntimeUpdateHost } from \"@nextclaw/server\";\nimport { NpmRuntimeBundleLayoutStore } from \"@nextclaw-service/stores/npm-runtime-bundle-layout.store.js\";\nimport { NpmRuntimeBundleService } from \"@nextclaw-service/services/runtime/npm-runtime-bundle.service.js\";\nimport { RuntimeUpdateManager } from \"@nextclaw-service/managers/runtime-update.manager.js\";\nimport { NpmRuntimeUpdateService } from \"@nextclaw-service/services/runtime/npm-runtime-update.service.js\";\nimport { NpmRuntimeUpdateSourceService } from \"@nextclaw-service/services/runtime/npm-runtime-update-source.service.js\";\nimport { NpmRuntimeUpdateStateStore } from \"@nextclaw-service/stores/npm-runtime-update-state.store.js\";\nimport { NextclawDistributionService } from \"@nextclaw-service/services/runtime/nextclaw-distribution.service.js\";\nimport { requestManagedServiceRestart } from \"@nextclaw-service/services/ui/service-remote-access.service.js\";\nimport type { RequestRestartParams } from \"@nextclaw-service/types/cli.types.js\";\n\nconst INITIAL_DOWNLOAD_PROGRESS: UpdateProgress = {\n downloadedBytes: 0,\n totalBytes: null,\n percent: null\n};\n\ntype NpmRuntimeUpdateHostDeps = {\n eventBus: EventBus;\n requestRestart: (params: RequestRestartParams) => Promise<void>;\n uiConfig: Pick<Config[\"ui\"], \"port\">;\n applyRestartMode: \"managed-service-restart\" | \"manual-process-restart\";\n};\n\nexport class NpmRuntimeUpdateHost implements UiRuntimeUpdateHost {\n private readonly source: NpmRuntimeUpdateSourceService;\n private readonly layout: NpmRuntimeBundleLayoutStore;\n private readonly launcherVersion: string;\n private readonly stateStore: NpmRuntimeUpdateStateStore;\n private readonly bundleService: NpmRuntimeBundleService;\n private readonly updateService: NpmRuntimeUpdateService;\n private snapshot: UpdateSnapshot;\n private activeTask: Promise<void> | null = null;\n private automaticSyncStarted = false;\n\n constructor(private readonly deps: NpmRuntimeUpdateHostDeps) {\n const distribution = NextclawDistributionService.get();\n this.source = new NpmRuntimeUpdateSourceService({\n packagedPublicKeyPath: distribution.runtimeUpdatePublicKeyPath\n });\n this.layout = new NpmRuntimeBundleLayoutStore();\n this.launcherVersion = distribution.version;\n this.stateStore = new NpmRuntimeUpdateStateStore(this.layout.getStatePath(), {\n defaultChannel: this.source.resolveChannel(undefined, this.launcherVersion)\n });\n this.bundleService = new NpmRuntimeBundleService({\n layout: this.layout,\n stateStore: this.stateStore,\n launcherVersion: this.launcherVersion\n });\n this.updateService = new NpmRuntimeUpdateService({\n layout: this.layout,\n bundleService: this.bundleService,\n launcherVersion: this.launcherVersion,\n bundlePublicKey: this.source.resolveBundlePublicKey() ?? undefined\n });\n this.snapshot = this.createManager().getSnapshot();\n this.startAutomaticSync();\n }\n\n getState = async (): Promise<UpdateSnapshot> => {\n this.startAutomaticSync();\n return this.snapshot;\n };\n\n checkForUpdates = async (): Promise<UpdateSnapshot> => {\n return this.startCheck({ autoDownload: false });\n };\n\n downloadUpdate = async (): Promise<UpdateSnapshot> => {\n return this.startDownload();\n };\n\n applyDownloadedUpdate = async (): Promise<UpdateSnapshot> => {\n if (this.activeTask) {\n return this.snapshot;\n }\n\n this.setSnapshot({\n ...this.snapshot,\n status: \"applying\",\n progress: null,\n errorMessage: null\n });\n try {\n const snapshot = this.createManager().applyDownloadedUpdate();\n this.setSnapshot(\n this.deps.applyRestartMode === \"managed-service-restart\"\n ? snapshot\n : {\n ...snapshot,\n recoveryCommand: \"Restart this NextClaw process to launch the downloaded runtime.\"\n },\n );\n if (this.deps.applyRestartMode === \"managed-service-restart\") {\n await requestManagedServiceRestart(this.deps.requestRestart, {\n reason: \"runtime update apply\",\n uiPort: this.deps.uiConfig.port\n });\n }\n return this.snapshot;\n } catch (error) {\n this.setSnapshot(this.toFailedSnapshot(error));\n throw error;\n }\n };\n\n updatePreferences = async (preferences: Partial<UpdatePreferences>): Promise<UpdateSnapshot> => {\n const nextState = this.stateStore.update((current) => ({\n ...current,\n updatePreferences: {\n ...current.updatePreferences,\n ...preferences\n }\n }));\n this.setSnapshot(this.createManager(nextState.channel).getSnapshot());\n if (nextState.updatePreferences.automaticChecks) {\n this.startAutomaticSync({ force: true });\n }\n return this.snapshot;\n };\n\n updateChannel = async (channel: UpdateSnapshot[\"channel\"]): Promise<UpdateSnapshot> => {\n const nextState = this.stateStore.update((current) => ({\n ...current,\n channel\n }));\n this.setSnapshot(this.createManager(nextState.channel).getSnapshot());\n if (nextState.updatePreferences.automaticChecks) {\n return this.startCheck({ autoDownload: nextState.updatePreferences.autoDownload });\n }\n return this.snapshot;\n };\n\n private startAutomaticSync = (options: { force?: boolean } = {}): void => {\n if (this.activeTask) {\n return;\n }\n if (this.automaticSyncStarted && !options.force) {\n return;\n }\n this.automaticSyncStarted = true;\n const state = this.stateStore.read();\n if (!state.updatePreferences.automaticChecks || state.downloadedVersion) {\n return;\n }\n void this.startCheck({ autoDownload: state.updatePreferences.autoDownload });\n };\n\n private startCheck = async (options: { autoDownload: boolean }): Promise<UpdateSnapshot> => {\n if (this.activeTask) {\n return this.snapshot;\n }\n\n this.setSnapshot({\n ...this.createManager().getSnapshot(),\n status: \"checking\",\n progress: null,\n errorMessage: null\n });\n this.activeTask = (async () => {\n try {\n const checkedSnapshot = await this.createManager().checkForUpdate();\n this.setSnapshot(checkedSnapshot);\n if (options.autoDownload && checkedSnapshot.status === \"update-available\") {\n await this.runDownloadTask();\n }\n } catch (error) {\n this.setSnapshot(this.toFailedSnapshot(error));\n } finally {\n this.activeTask = null;\n }\n })();\n return this.snapshot;\n };\n\n private startDownload = async (): Promise<UpdateSnapshot> => {\n if (this.activeTask) {\n return this.snapshot;\n }\n\n this.setSnapshot({\n ...this.createManager().getSnapshot(),\n status: \"downloading\",\n progress: INITIAL_DOWNLOAD_PROGRESS,\n errorMessage: null\n });\n this.activeTask = (async () => {\n try {\n await this.runDownloadTask();\n } catch (error) {\n this.setSnapshot(this.toFailedSnapshot(error));\n } finally {\n this.activeTask = null;\n }\n })();\n return this.snapshot;\n };\n\n private runDownloadTask = async (): Promise<void> => {\n const downloadedSnapshot = await this.createManager().downloadUpdate((progress) => {\n this.setSnapshot({\n ...this.snapshot,\n status: \"downloading\",\n progress,\n errorMessage: null\n });\n });\n this.setSnapshot(downloadedSnapshot);\n };\n\n private createManager = (channel = this.stateStore.read().channel): RuntimeUpdateManager => {\n return new RuntimeUpdateManager({\n layout: this.layout,\n stateStore: this.stateStore,\n bundleService: this.bundleService,\n updateService: this.updateService,\n resolveManifestUrl: (resolvedChannel) => this.source.resolveManifestUrl(resolvedChannel),\n launcherVersion: this.launcherVersion,\n channel\n });\n };\n\n private toFailedSnapshot = (error: unknown): UpdateSnapshot => {\n return {\n ...this.createManager().getSnapshot(),\n status: \"failed\",\n progress: null,\n errorMessage: error instanceof Error ? error.message : String(error ?? \"Unknown error\")\n };\n };\n\n private setSnapshot = (snapshot: UpdateSnapshot): UpdateSnapshot => {\n this.snapshot = snapshot;\n this.deps.eventBus.emit(eventKeys.runtimeUpdateSnapshot, snapshot, {\n source: \"backend\"\n });\n return snapshot;\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"npm-runtime-update-host.service.js","names":[],"sources":["../../../src/services/runtime/npm-runtime-update-host.service.ts"],"sourcesContent":["import type { Config } from \"@nextclaw/core\";\nimport {\n eventKeys,\n type EventBus,\n type UpdatePreferences,\n type UpdateProgress,\n type UpdateSnapshot,\n} from \"@nextclaw/shared\";\nimport type { UiRuntimeUpdateHost } from \"@nextclaw/server\";\nimport { NpmRuntimeBundleLayoutStore } from \"@nextclaw-service/stores/npm-runtime-bundle-layout.store.js\";\nimport { NpmRuntimeBundleService } from \"@nextclaw-service/services/runtime/npm-runtime-bundle.service.js\";\nimport { RuntimeUpdateManager } from \"@nextclaw-service/managers/runtime-update.manager.js\";\nimport { NpmRuntimeUpdateService } from \"@nextclaw-service/services/runtime/npm-runtime-update.service.js\";\nimport { NpmRuntimeUpdateSourceService } from \"@nextclaw-service/services/runtime/npm-runtime-update-source.service.js\";\nimport { NpmRuntimeUpdateStateStore } from \"@nextclaw-service/stores/npm-runtime-update-state.store.js\";\nimport { NextclawDistributionService } from \"@nextclaw-service/services/runtime/nextclaw-distribution.service.js\";\nimport { requestManagedServiceRestart } from \"@nextclaw-service/services/ui/service-remote-access.service.js\";\nimport type { RequestRestartParams } from \"@nextclaw-service/types/cli.types.js\";\n\nconst INITIAL_DOWNLOAD_PROGRESS: UpdateProgress = {\n downloadedBytes: 0,\n totalBytes: null,\n percent: null\n};\n\ntype NpmRuntimeUpdateHostDeps = {\n eventBus: EventBus;\n requestRestart: (params: RequestRestartParams) => Promise<void>;\n uiConfig: Pick<Config[\"ui\"], \"port\">;\n applyRestartMode: \"managed-service-restart\" | \"manual-process-restart\";\n};\n\nexport class NpmRuntimeUpdateHost implements UiRuntimeUpdateHost {\n private readonly source: NpmRuntimeUpdateSourceService;\n private readonly layout: NpmRuntimeBundleLayoutStore;\n private readonly launcherVersion: string;\n private readonly stateStore: NpmRuntimeUpdateStateStore;\n private readonly bundleService: NpmRuntimeBundleService;\n private readonly updateService: NpmRuntimeUpdateService;\n private snapshot: UpdateSnapshot;\n private activeTask: Promise<void> | null = null;\n private automaticSyncStarted = false;\n\n constructor(private readonly deps: NpmRuntimeUpdateHostDeps) {\n const distribution = NextclawDistributionService.get();\n this.source = new NpmRuntimeUpdateSourceService({\n packagedPublicKeyPath: distribution.runtimeUpdatePublicKeyPath\n });\n this.layout = new NpmRuntimeBundleLayoutStore();\n this.launcherVersion = distribution.version;\n this.stateStore = new NpmRuntimeUpdateStateStore(this.layout.getStatePath(), {\n defaultChannel: this.source.resolveChannel(undefined, this.launcherVersion)\n });\n this.bundleService = new NpmRuntimeBundleService({\n layout: this.layout,\n stateStore: this.stateStore,\n launcherVersion: this.launcherVersion\n });\n this.updateService = new NpmRuntimeUpdateService({\n layout: this.layout,\n bundleService: this.bundleService,\n launcherVersion: this.launcherVersion,\n bundlePublicKey: this.source.resolveBundlePublicKey() ?? undefined\n });\n this.snapshot = this.createManager().getSnapshot();\n this.startAutomaticSync();\n }\n\n getState = async (): Promise<UpdateSnapshot> => {\n this.startAutomaticSync();\n return this.snapshot;\n };\n\n checkForUpdates = async (): Promise<UpdateSnapshot> => {\n return this.startCheck({ autoDownload: false });\n };\n\n downloadUpdate = async (): Promise<UpdateSnapshot> => {\n return this.startDownload();\n };\n\n applyDownloadedUpdate = async (): Promise<UpdateSnapshot> => {\n if (this.activeTask) {\n return this.snapshot;\n }\n\n this.setSnapshot({\n ...this.snapshot,\n status: \"applying\",\n progress: null,\n errorMessage: null\n });\n try {\n const snapshot = this.createManager().applyDownloadedUpdate();\n this.setSnapshot(\n this.deps.applyRestartMode === \"managed-service-restart\"\n ? snapshot\n : {\n ...snapshot,\n recoveryCommand: \"Restart this NextClaw process to launch the downloaded runtime.\"\n },\n );\n if (this.deps.applyRestartMode === \"managed-service-restart\") {\n await requestManagedServiceRestart(this.deps.requestRestart, {\n reason: \"runtime update apply\",\n uiPort: this.deps.uiConfig.port\n });\n }\n return this.snapshot;\n } catch (error) {\n this.setSnapshot(this.toFailedSnapshot(error));\n throw error;\n }\n };\n\n updatePreferences = async (preferences: Partial<UpdatePreferences>): Promise<UpdateSnapshot> => {\n const nextState = this.stateStore.update((current) => ({\n ...current,\n updatePreferences: {\n ...current.updatePreferences,\n ...preferences\n }\n }));\n this.setSnapshot(this.createManager(nextState.channel).getSnapshot());\n if (nextState.updatePreferences.automaticChecks) {\n this.startAutomaticSync({ force: true });\n }\n return this.snapshot;\n };\n\n updateChannel = async (channel: UpdateSnapshot[\"channel\"]): Promise<UpdateSnapshot> => {\n const nextState = this.stateStore.update((current) => ({\n ...current,\n channel\n }));\n this.setSnapshot(this.createManager(nextState.channel).getSnapshot());\n if (nextState.updatePreferences.automaticChecks) {\n return this.startCheck({ autoDownload: nextState.updatePreferences.autoDownload });\n }\n return this.snapshot;\n };\n\n private startAutomaticSync = (options: { force?: boolean } = {}): void => {\n if (this.activeTask) {\n return;\n }\n if (this.automaticSyncStarted && !options.force) {\n return;\n }\n this.automaticSyncStarted = true;\n const state = this.stateStore.read();\n if (!state.updatePreferences.automaticChecks || state.downloadedVersion) {\n return;\n }\n void this.startCheck({ autoDownload: state.updatePreferences.autoDownload });\n };\n\n private startCheck = async (options: { autoDownload: boolean }): Promise<UpdateSnapshot> => {\n if (!this.activeTask) {\n this.setSnapshot({\n ...this.createManager().getSnapshot(),\n status: \"checking\",\n progress: null,\n errorMessage: null\n });\n this.activeTask = (async () => {\n try {\n const checkedSnapshot = await this.createManager().checkForUpdate();\n this.setSnapshot(checkedSnapshot);\n if (options.autoDownload && checkedSnapshot.status === \"update-available\") {\n await this.runDownloadTask();\n }\n } catch (error) {\n this.setSnapshot(this.toFailedSnapshot(error));\n } finally {\n this.activeTask = null;\n }\n })();\n }\n await this.activeTask;\n return this.snapshot;\n };\n\n private startDownload = async (): Promise<UpdateSnapshot> => {\n if (!this.activeTask) {\n this.setSnapshot({\n ...this.createManager().getSnapshot(),\n status: \"downloading\",\n progress: INITIAL_DOWNLOAD_PROGRESS,\n errorMessage: null\n });\n this.activeTask = (async () => {\n try {\n await this.runDownloadTask();\n } catch (error) {\n this.setSnapshot(this.toFailedSnapshot(error));\n } finally {\n this.activeTask = null;\n }\n })();\n }\n await this.activeTask;\n return this.snapshot;\n };\n\n private runDownloadTask = async (): Promise<void> => {\n const downloadedSnapshot = await this.createManager().downloadUpdate((progress) => {\n this.setSnapshot({\n ...this.snapshot,\n status: \"downloading\",\n progress,\n errorMessage: null\n });\n });\n this.setSnapshot(downloadedSnapshot);\n };\n\n private createManager = (channel = this.stateStore.read().channel): RuntimeUpdateManager => {\n return new RuntimeUpdateManager({\n layout: this.layout,\n stateStore: this.stateStore,\n bundleService: this.bundleService,\n updateService: this.updateService,\n resolveManifestUrl: (resolvedChannel) => this.source.resolveManifestUrl(resolvedChannel),\n launcherVersion: this.launcherVersion,\n channel\n });\n };\n\n private toFailedSnapshot = (error: unknown): UpdateSnapshot => {\n return {\n ...this.createManager().getSnapshot(),\n status: \"failed\",\n progress: null,\n errorMessage: error instanceof Error ? error.message : String(error ?? \"Unknown error\")\n };\n };\n\n private setSnapshot = (snapshot: UpdateSnapshot): UpdateSnapshot => {\n this.snapshot = snapshot;\n this.deps.eventBus.emit(eventKeys.runtimeUpdateSnapshot, snapshot, {\n source: \"backend\"\n });\n return snapshot;\n };\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  //#region src/types/distribution.types.d.ts
2
2
  type NextclawDistribution = {
3
3
  version: string;
4
- packageRoot: string;
5
4
  appEntrypoint: string;
5
+ launcherEntrypoint: string;
6
6
  uiDistDir: string;
7
7
  runtimeUpdatePublicKeyPath: string;
8
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"distribution.types.d.ts","names":[],"sources":["../../src/types/distribution.types.ts"],"mappings":";KAAY,oBAAA;EACV,OAAA;EACA,WAAA;EACA,aAAA;EACA,SAAA;EACA,0BAAA;AAAA"}
1
+ {"version":3,"file":"distribution.types.d.ts","names":[],"sources":["../../src/types/distribution.types.ts"],"mappings":";KAAY,oBAAA;EACV,OAAA;EACA,aAAA;EACA,kBAAA;EACA,SAAA;EACA,0BAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/service",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "private": false,
5
5
  "description": "NextClaw long-running service host and runtime lifecycle.",
6
6
  "type": "module",
@@ -42,31 +42,31 @@
42
42
  "chokidar": "^3.6.0",
43
43
  "commander": "^12.1.0",
44
44
  "jszip": "^3.10.1",
45
- "@nextclaw/channel-extension-dingtalk": "0.2.3",
46
- "@nextclaw/channel-extension-discord": "0.2.3",
47
- "@nextclaw/channel-extension-feishu": "0.2.4",
48
- "@nextclaw/channel-extension-email": "0.2.3",
49
- "@nextclaw/channel-extension-qq": "0.2.3",
50
- "@nextclaw/channel-extension-slack": "0.2.3",
51
- "@nextclaw/channel-extension-telegram": "0.2.3",
52
- "@nextclaw/channel-extension-whatsapp": "0.2.3",
53
- "@nextclaw/channel-extension-wecom": "0.2.3",
54
- "@nextclaw/channel-extension-weixin": "0.2.4",
55
- "@nextclaw/core": "0.15.3",
56
- "@nextclaw/client-sdk": "0.5.4",
57
- "@nextclaw/kernel": "0.6.4",
58
- "@nextclaw/mcp": "0.3.3",
59
- "@nextclaw/ncp": "0.7.3",
60
- "@nextclaw/ncp-mcp": "0.2.3",
61
- "@nextclaw/nextclaw-ncp-runtime-http-client": "0.3.3",
62
- "@nextclaw/ncp-agent-runtime": "0.4.3",
63
- "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.3.4",
64
- "@nextclaw/remote": "0.3.4",
65
- "@nextclaw/nextclaw-hermes-acp-bridge": "0.3.3",
66
- "@nextclaw/shared": "0.4.3",
67
- "@nextclaw/runtime": "0.4.3",
68
- "@nextclaw/server": "0.15.4",
69
- "@nextclaw/ncp-toolkit": "0.6.4"
45
+ "@nextclaw/channel-extension-discord": "0.2.5",
46
+ "@nextclaw/channel-extension-dingtalk": "0.2.5",
47
+ "@nextclaw/channel-extension-email": "0.2.5",
48
+ "@nextclaw/channel-extension-feishu": "0.2.5",
49
+ "@nextclaw/channel-extension-qq": "0.2.4",
50
+ "@nextclaw/channel-extension-slack": "0.2.5",
51
+ "@nextclaw/channel-extension-telegram": "0.2.5",
52
+ "@nextclaw/channel-extension-whatsapp": "0.2.5",
53
+ "@nextclaw/core": "0.15.5",
54
+ "@nextclaw/channel-extension-weixin": "0.2.5",
55
+ "@nextclaw/client-sdk": "0.5.6",
56
+ "@nextclaw/mcp": "0.3.5",
57
+ "@nextclaw/ncp": "0.7.4",
58
+ "@nextclaw/kernel": "0.6.6",
59
+ "@nextclaw/ncp-agent-runtime": "0.4.4",
60
+ "@nextclaw/nextclaw-hermes-acp-bridge": "0.3.4",
61
+ "@nextclaw/ncp-toolkit": "0.6.5",
62
+ "@nextclaw/ncp-mcp": "0.2.5",
63
+ "@nextclaw/nextclaw-ncp-runtime-http-client": "0.3.4",
64
+ "@nextclaw/runtime": "0.4.5",
65
+ "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.3.6",
66
+ "@nextclaw/remote": "0.3.6",
67
+ "@nextclaw/shared": "0.4.4",
68
+ "@nextclaw/server": "0.15.6",
69
+ "@nextclaw/channel-extension-wecom": "0.2.5"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^20.17.6",