@nextclaw/service 0.2.8 → 0.2.10-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/cli/commands/cron/services/cron-local.service.d.ts.map +1 -1
  2. package/dist/cli/commands/cron/services/cron-local.service.js +1 -9
  3. package/dist/cli/commands/cron/services/cron-local.service.js.map +1 -1
  4. package/dist/cli/commands/cron/utils/cron-job.utils.d.ts +0 -4
  5. package/dist/cli/commands/cron/utils/cron-job.utils.d.ts.map +1 -1
  6. package/dist/cli/commands/cron/utils/cron-job.utils.js.map +1 -1
  7. package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts +2 -2
  8. package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts.map +1 -1
  9. package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js +3 -4
  10. package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js.map +1 -1
  11. package/dist/shared/services/gateway/utils/cron-job-handler.utils.d.ts +0 -6
  12. package/dist/shared/services/gateway/utils/cron-job-handler.utils.d.ts.map +1 -1
  13. package/dist/shared/services/gateway/utils/cron-job-handler.utils.js +22 -18
  14. package/dist/shared/services/gateway/utils/cron-job-handler.utils.js.map +1 -1
  15. package/dist/shared/services/runtime/utils/service-remote-runtime.utils.d.ts.map +1 -1
  16. package/dist/shared/services/runtime/utils/service-remote-runtime.utils.js +30 -26
  17. package/dist/shared/services/runtime/utils/service-remote-runtime.utils.js.map +1 -1
  18. package/dist/shared/stores/companion-runtime.store.js +2 -2
  19. package/dist/shared/stores/companion-runtime.store.js.map +1 -1
  20. package/dist/shared/stores/local-ui-runtime.store.js +2 -2
  21. package/dist/shared/stores/local-ui-runtime.store.js.map +1 -1
  22. package/dist/shared/stores/managed-service-state.store.js +2 -2
  23. package/dist/shared/stores/managed-service-state.store.js.map +1 -1
  24. package/dist/shared/types/cli.types.d.ts +0 -4
  25. package/dist/shared/types/cli.types.d.ts.map +1 -1
  26. package/dist/shared/utils/cli.utils.js +2 -2
  27. package/dist/shared/utils/cli.utils.js.map +1 -1
  28. package/dist/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.d.ts +5 -0
  29. package/dist/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.d.ts.map +1 -0
  30. package/dist/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.js +29 -0
  31. package/dist/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.js.map +1 -0
  32. package/dist/shared/utils/restart/restart-sentinel.utils.js +2 -2
  33. package/dist/shared/utils/restart/restart-sentinel.utils.js.map +1 -1
  34. package/package.json +26 -25
@@ -1 +1 @@
1
- {"version":3,"file":"cron-local.service.d.ts","names":[],"sources":["../../../../../src/cli/commands/cron/services/cron-local.service.ts"],"mappings":";;;;;;iBAwCgB,uBAAA,CAAwB,IAAA,EAAM,cAAA;EAAmB,OAAA,GAAU,iBAAA;EAAmB,KAAA;AAAA;AAAA,cAyBjF,gBAAA;EAAA,iBAEQ,UAAA;cAAA,UAAA,GAAU,iBAAA;EAAA,SAKpB,IAAA,GAAQ,GAAA,cAAe,WAAA;EAAA,SAIvB,UAAA,GAAc,OAAA,EAAS,iBAAA,KAAoB,WAAA;EAAA,SAe3C,GAAA,GAAO,IAAA,EAAM,cAAA;IAAmB,GAAA,EAAK,WAAA;IAAoB,KAAA;EAAA;EAAA,SAQzD,MAAA,GAAU,KAAA;EAAA,SAIV,MAAA,GAAU,KAAA,UAAe,OAAA,cAAmB,WAAA;EAAA,SAI5C,GAAA,GAAa,KAAA,UAAe,KAAA,cAAiB,OAAA;AAAA"}
1
+ {"version":3,"file":"cron-local.service.d.ts","names":[],"sources":["../../../../../src/cli/commands/cron/services/cron-local.service.ts"],"mappings":";;;;;;iBAwCgB,uBAAA,CAAwB,IAAA,EAAM,cAAA;EAAmB,OAAA,GAAU,iBAAA;EAAmB,KAAA;AAAA;AAAA,cAqBjF,gBAAA;EAAA,iBAEQ,UAAA;cAAA,UAAA,GAAU,iBAAA;EAAA,SAKpB,IAAA,GAAQ,GAAA,cAAe,WAAA;EAAA,SAIvB,UAAA,GAAc,OAAA,EAAS,iBAAA,KAAoB,WAAA;EAAA,SAW3C,GAAA,GAAO,IAAA,EAAM,cAAA;IAAmB,GAAA,EAAK,WAAA;IAAoB,KAAA;EAAA;EAAA,SAQzD,MAAA,GAAU,KAAA;EAAA,SAIV,MAAA,GAAU,KAAA,UAAe,OAAA,cAAmB,WAAA;EAAA,SAI5C,GAAA,GAAa,KAAA,UAAe,KAAA,cAAiB,OAAA;AAAA"}
@@ -45,11 +45,7 @@ function createCronCreateRequest(opts) {
45
45
  message,
46
46
  schedule: schedule.schedule,
47
47
  agentId: readTrimmed(opts.agent),
48
- sessionId: readTrimmed(opts.session),
49
- deliver: Boolean(opts.deliver),
50
- channel: readTrimmed(opts.channel),
51
- to: readTrimmed(opts.to),
52
- accountId: readTrimmed(opts.account)
48
+ sessionId: readTrimmed(opts.session)
53
49
  } };
54
50
  }
55
51
  var CronLocalService = class {
@@ -66,10 +62,6 @@ var CronLocalService = class {
66
62
  message: request.message,
67
63
  agentId: request.agentId ?? void 0,
68
64
  sessionId: request.sessionId ?? void 0,
69
- deliver: request.deliver === true,
70
- channel: request.channel ?? void 0,
71
- to: request.to ?? void 0,
72
- accountId: request.accountId ?? void 0,
73
65
  deleteAfterRun: request.deleteAfterRun === true
74
66
  });
75
67
  };
@@ -1 +1 @@
1
- {"version":3,"file":"cron-local.service.js","names":[],"sources":["../../../../../src/cli/commands/cron/services/cron-local.service.ts"],"sourcesContent":["import { getDataDir } from \"@nextclaw/core\";\nimport { AutomationManager } from \"@nextclaw/kernel\";\nimport type { CronCreateRequest } from \"@nextclaw/server\";\nimport type { CronAddOptions } from \"@nextclaw-service/shared/types/cli.types.js\";\nimport type { CronJobView } from \"@nextclaw-service/cli/commands/cron/utils/cron-job.utils.js\";\nimport { resolve } from \"node:path\";\n\nfunction readTrimmed(value: string | undefined): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction toSchedule(opts: CronAddOptions): { schedule?: CronCreateRequest[\"schedule\"]; error?: string } {\n const every = readTrimmed(opts.every);\n const cron = readTrimmed(opts.cron);\n const at = readTrimmed(opts.at);\n const scheduleFlags = [every, cron, at].filter((value) => value !== undefined);\n if (scheduleFlags.length !== 1) {\n return { error: \"Error: Must specify exactly one of --every, --cron, or --at\" };\n }\n if (every) {\n const everySeconds = Number(every);\n if (!Number.isFinite(everySeconds) || everySeconds <= 0) {\n return { error: \"Error: --every must be a positive number of seconds\" };\n }\n return { schedule: { kind: \"every\", everyMs: everySeconds * 1000 } };\n }\n if (cron) {\n return { schedule: { kind: \"cron\", expr: cron } };\n }\n const atMs = Date.parse(String(at));\n if (!Number.isFinite(atMs)) {\n return { error: \"Error: --at must be a valid ISO datetime\" };\n }\n return { schedule: { kind: \"at\", atMs } };\n}\n\nexport function createCronCreateRequest(opts: CronAddOptions): { request?: CronCreateRequest; error?: string } {\n const name = readTrimmed(opts.name);\n const message = readTrimmed(opts.message);\n if (!name || !message) {\n return { error: \"Error: name and message are required\" };\n }\n const schedule = toSchedule(opts);\n if (!schedule.schedule) {\n return { error: schedule.error ?? \"Error: Must specify --every, --cron, or --at\" };\n }\n return {\n request: {\n name,\n message,\n schedule: schedule.schedule,\n agentId: readTrimmed(opts.agent),\n sessionId: readTrimmed(opts.session),\n deliver: Boolean(opts.deliver),\n channel: readTrimmed(opts.channel),\n to: readTrimmed(opts.to),\n accountId: readTrimmed(opts.account)\n }\n };\n}\n\nexport class CronLocalService {\n constructor(\n private readonly automation = new AutomationManager({\n storePath: resolve(getDataDir(), \"cron\", \"jobs.json\")\n })\n ) {}\n\n readonly list = (all: boolean): CronJobView[] => {\n return this.automation.listJobs(all) as CronJobView[];\n };\n\n readonly addRequest = (request: CronCreateRequest): CronJobView => {\n return this.automation.addJob({\n name: request.name,\n schedule: request.schedule,\n message: request.message,\n agentId: request.agentId ?? undefined,\n sessionId: request.sessionId ?? undefined,\n deliver: request.deliver === true,\n channel: request.channel ?? undefined,\n to: request.to ?? undefined,\n accountId: request.accountId ?? undefined,\n deleteAfterRun: request.deleteAfterRun === true\n }) as CronJobView;\n };\n\n readonly add = (opts: CronAddOptions): { job: CronJobView | null; error?: string } => {\n const request = createCronCreateRequest(opts);\n if (!request.request) {\n return { job: null, error: request.error };\n }\n return { job: this.addRequest(request.request) };\n };\n\n readonly remove = (jobId: string): boolean => {\n return this.automation.removeJob(jobId);\n };\n\n readonly enable = (jobId: string, enabled: boolean): CronJobView | null => {\n return (this.automation.enableJob(jobId, enabled) as CronJobView | null) ?? null;\n };\n\n readonly run = async (jobId: string, force: boolean): Promise<boolean> => {\n return this.automation.runJob(jobId, force);\n };\n}\n"],"mappings":";;;;AAOA,SAAS,YAAY,OAA+C;AAClE,KAAI,OAAO,UAAU,SACnB;AAGF,QADgB,MAAM,MAAM,IACV,KAAA;;AAGpB,SAAS,WAAW,MAAoF;CACtG,MAAM,QAAQ,YAAY,KAAK,MAAM;CACrC,MAAM,OAAO,YAAY,KAAK,KAAK;CACnC,MAAM,KAAK,YAAY,KAAK,GAAG;AAE/B,KADsB;EAAC;EAAO;EAAM;EAAG,CAAC,QAAQ,UAAU,UAAU,KAAA,EAAU,CAC5D,WAAW,EAC3B,QAAO,EAAE,OAAO,+DAA+D;AAEjF,KAAI,OAAO;EACT,MAAM,eAAe,OAAO,MAAM;AAClC,MAAI,CAAC,OAAO,SAAS,aAAa,IAAI,gBAAgB,EACpD,QAAO,EAAE,OAAO,uDAAuD;AAEzE,SAAO,EAAE,UAAU;GAAE,MAAM;GAAS,SAAS,eAAe;GAAM,EAAE;;AAEtE,KAAI,KACF,QAAO,EAAE,UAAU;EAAE,MAAM;EAAQ,MAAM;EAAM,EAAE;CAEnD,MAAM,OAAO,KAAK,MAAM,OAAO,GAAG,CAAC;AACnC,KAAI,CAAC,OAAO,SAAS,KAAK,CACxB,QAAO,EAAE,OAAO,4CAA4C;AAE9D,QAAO,EAAE,UAAU;EAAE,MAAM;EAAM;EAAM,EAAE;;AAG3C,SAAgB,wBAAwB,MAAuE;CAC7G,MAAM,OAAO,YAAY,KAAK,KAAK;CACnC,MAAM,UAAU,YAAY,KAAK,QAAQ;AACzC,KAAI,CAAC,QAAQ,CAAC,QACZ,QAAO,EAAE,OAAO,wCAAwC;CAE1D,MAAM,WAAW,WAAW,KAAK;AACjC,KAAI,CAAC,SAAS,SACZ,QAAO,EAAE,OAAO,SAAS,SAAS,gDAAgD;AAEpF,QAAO,EACL,SAAS;EACP;EACA;EACA,UAAU,SAAS;EACnB,SAAS,YAAY,KAAK,MAAM;EAChC,WAAW,YAAY,KAAK,QAAQ;EACpC,SAAS,QAAQ,KAAK,QAAQ;EAC9B,SAAS,YAAY,KAAK,QAAQ;EAClC,IAAI,YAAY,KAAK,GAAG;EACxB,WAAW,YAAY,KAAK,QAAQ;EACrC,EACF;;AAGH,IAAa,mBAAb,MAA8B;CAC5B,YACE,aAA8B,IAAI,kBAAkB,EAClD,WAAW,QAAQ,YAAY,EAAE,QAAQ,YAAY,EACtD,CAAC,EACF;AAHiB,OAAA,aAAA;;CAKnB,QAAiB,QAAgC;AAC/C,SAAO,KAAK,WAAW,SAAS,IAAI;;CAGtC,cAAuB,YAA4C;AACjE,SAAO,KAAK,WAAW,OAAO;GAC5B,MAAM,QAAQ;GACd,UAAU,QAAQ;GAClB,SAAS,QAAQ;GACjB,SAAS,QAAQ,WAAW,KAAA;GAC5B,WAAW,QAAQ,aAAa,KAAA;GAChC,SAAS,QAAQ,YAAY;GAC7B,SAAS,QAAQ,WAAW,KAAA;GAC5B,IAAI,QAAQ,MAAM,KAAA;GAClB,WAAW,QAAQ,aAAa,KAAA;GAChC,gBAAgB,QAAQ,mBAAmB;GAC5C,CAAC;;CAGJ,OAAgB,SAAsE;EACpF,MAAM,UAAU,wBAAwB,KAAK;AAC7C,MAAI,CAAC,QAAQ,QACX,QAAO;GAAE,KAAK;GAAM,OAAO,QAAQ;GAAO;AAE5C,SAAO,EAAE,KAAK,KAAK,WAAW,QAAQ,QAAQ,EAAE;;CAGlD,UAAmB,UAA2B;AAC5C,SAAO,KAAK,WAAW,UAAU,MAAM;;CAGzC,UAAmB,OAAe,YAAyC;AACzE,SAAQ,KAAK,WAAW,UAAU,OAAO,QAAQ,IAA2B;;CAG9E,MAAe,OAAO,OAAe,UAAqC;AACxE,SAAO,KAAK,WAAW,OAAO,OAAO,MAAM"}
1
+ {"version":3,"file":"cron-local.service.js","names":[],"sources":["../../../../../src/cli/commands/cron/services/cron-local.service.ts"],"sourcesContent":["import { getDataDir } from \"@nextclaw/core\";\nimport { AutomationManager } from \"@nextclaw/kernel\";\nimport type { CronCreateRequest } from \"@nextclaw/server\";\nimport type { CronAddOptions } from \"@nextclaw-service/shared/types/cli.types.js\";\nimport type { CronJobView } from \"@nextclaw-service/cli/commands/cron/utils/cron-job.utils.js\";\nimport { resolve } from \"node:path\";\n\nfunction readTrimmed(value: string | undefined): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction toSchedule(opts: CronAddOptions): { schedule?: CronCreateRequest[\"schedule\"]; error?: string } {\n const every = readTrimmed(opts.every);\n const cron = readTrimmed(opts.cron);\n const at = readTrimmed(opts.at);\n const scheduleFlags = [every, cron, at].filter((value) => value !== undefined);\n if (scheduleFlags.length !== 1) {\n return { error: \"Error: Must specify exactly one of --every, --cron, or --at\" };\n }\n if (every) {\n const everySeconds = Number(every);\n if (!Number.isFinite(everySeconds) || everySeconds <= 0) {\n return { error: \"Error: --every must be a positive number of seconds\" };\n }\n return { schedule: { kind: \"every\", everyMs: everySeconds * 1000 } };\n }\n if (cron) {\n return { schedule: { kind: \"cron\", expr: cron } };\n }\n const atMs = Date.parse(String(at));\n if (!Number.isFinite(atMs)) {\n return { error: \"Error: --at must be a valid ISO datetime\" };\n }\n return { schedule: { kind: \"at\", atMs } };\n}\n\nexport function createCronCreateRequest(opts: CronAddOptions): { request?: CronCreateRequest; error?: string } {\n const name = readTrimmed(opts.name);\n const message = readTrimmed(opts.message);\n if (!name || !message) {\n return { error: \"Error: name and message are required\" };\n }\n const schedule = toSchedule(opts);\n if (!schedule.schedule) {\n return { error: schedule.error ?? \"Error: Must specify --every, --cron, or --at\" };\n }\n return {\n request: {\n name,\n message,\n schedule: schedule.schedule,\n agentId: readTrimmed(opts.agent),\n sessionId: readTrimmed(opts.session),\n }\n };\n}\n\nexport class CronLocalService {\n constructor(\n private readonly automation = new AutomationManager({\n storePath: resolve(getDataDir(), \"cron\", \"jobs.json\")\n })\n ) {}\n\n readonly list = (all: boolean): CronJobView[] => {\n return this.automation.listJobs(all) as CronJobView[];\n };\n\n readonly addRequest = (request: CronCreateRequest): CronJobView => {\n return this.automation.addJob({\n name: request.name,\n schedule: request.schedule,\n message: request.message,\n agentId: request.agentId ?? undefined,\n sessionId: request.sessionId ?? undefined,\n deleteAfterRun: request.deleteAfterRun === true\n }) as CronJobView;\n };\n\n readonly add = (opts: CronAddOptions): { job: CronJobView | null; error?: string } => {\n const request = createCronCreateRequest(opts);\n if (!request.request) {\n return { job: null, error: request.error };\n }\n return { job: this.addRequest(request.request) };\n };\n\n readonly remove = (jobId: string): boolean => {\n return this.automation.removeJob(jobId);\n };\n\n readonly enable = (jobId: string, enabled: boolean): CronJobView | null => {\n return (this.automation.enableJob(jobId, enabled) as CronJobView | null) ?? null;\n };\n\n readonly run = async (jobId: string, force: boolean): Promise<boolean> => {\n return this.automation.runJob(jobId, force);\n };\n}\n"],"mappings":";;;;AAOA,SAAS,YAAY,OAA+C;AAClE,KAAI,OAAO,UAAU,SACnB;AAGF,QADgB,MAAM,MAAM,IACV,KAAA;;AAGpB,SAAS,WAAW,MAAoF;CACtG,MAAM,QAAQ,YAAY,KAAK,MAAM;CACrC,MAAM,OAAO,YAAY,KAAK,KAAK;CACnC,MAAM,KAAK,YAAY,KAAK,GAAG;AAE/B,KADsB;EAAC;EAAO;EAAM;EAAG,CAAC,QAAQ,UAAU,UAAU,KAAA,EAAU,CAC5D,WAAW,EAC3B,QAAO,EAAE,OAAO,+DAA+D;AAEjF,KAAI,OAAO;EACT,MAAM,eAAe,OAAO,MAAM;AAClC,MAAI,CAAC,OAAO,SAAS,aAAa,IAAI,gBAAgB,EACpD,QAAO,EAAE,OAAO,uDAAuD;AAEzE,SAAO,EAAE,UAAU;GAAE,MAAM;GAAS,SAAS,eAAe;GAAM,EAAE;;AAEtE,KAAI,KACF,QAAO,EAAE,UAAU;EAAE,MAAM;EAAQ,MAAM;EAAM,EAAE;CAEnD,MAAM,OAAO,KAAK,MAAM,OAAO,GAAG,CAAC;AACnC,KAAI,CAAC,OAAO,SAAS,KAAK,CACxB,QAAO,EAAE,OAAO,4CAA4C;AAE9D,QAAO,EAAE,UAAU;EAAE,MAAM;EAAM;EAAM,EAAE;;AAG3C,SAAgB,wBAAwB,MAAuE;CAC7G,MAAM,OAAO,YAAY,KAAK,KAAK;CACnC,MAAM,UAAU,YAAY,KAAK,QAAQ;AACzC,KAAI,CAAC,QAAQ,CAAC,QACZ,QAAO,EAAE,OAAO,wCAAwC;CAE1D,MAAM,WAAW,WAAW,KAAK;AACjC,KAAI,CAAC,SAAS,SACZ,QAAO,EAAE,OAAO,SAAS,SAAS,gDAAgD;AAEpF,QAAO,EACL,SAAS;EACP;EACA;EACA,UAAU,SAAS;EACnB,SAAS,YAAY,KAAK,MAAM;EAChC,WAAW,YAAY,KAAK,QAAQ;EACrC,EACF;;AAGH,IAAa,mBAAb,MAA8B;CAC5B,YACE,aAA8B,IAAI,kBAAkB,EAClD,WAAW,QAAQ,YAAY,EAAE,QAAQ,YAAY,EACtD,CAAC,EACF;AAHiB,OAAA,aAAA;;CAKnB,QAAiB,QAAgC;AAC/C,SAAO,KAAK,WAAW,SAAS,IAAI;;CAGtC,cAAuB,YAA4C;AACjE,SAAO,KAAK,WAAW,OAAO;GAC5B,MAAM,QAAQ;GACd,UAAU,QAAQ;GAClB,SAAS,QAAQ;GACjB,SAAS,QAAQ,WAAW,KAAA;GAC5B,WAAW,QAAQ,aAAa,KAAA;GAChC,gBAAgB,QAAQ,mBAAmB;GAC5C,CAAC;;CAGJ,OAAgB,SAAsE;EACpF,MAAM,UAAU,wBAAwB,KAAK;AAC7C,MAAI,CAAC,QAAQ,QACX,QAAO;GAAE,KAAK;GAAM,OAAO,QAAQ;GAAO;AAE5C,SAAO,EAAE,KAAK,KAAK,WAAW,QAAQ,QAAQ,EAAE;;CAGlD,UAAmB,UAA2B;AAC5C,SAAO,KAAK,WAAW,UAAU,MAAM;;CAGzC,UAAmB,OAAe,YAAyC;AACzE,SAAQ,KAAK,WAAW,UAAU,OAAO,QAAQ,IAA2B;;CAG9E,MAAe,OAAO,OAAe,UAAqC;AACxE,SAAO,KAAK,WAAW,OAAO,OAAO,MAAM"}
@@ -13,10 +13,6 @@ type CronPayload = {
13
13
  message: string;
14
14
  agentId?: string | null;
15
15
  sessionId?: string | null;
16
- deliver?: boolean;
17
- channel?: string | null;
18
- to?: string | null;
19
- accountId?: string | null;
20
16
  };
21
17
  type CronJobView = {
22
18
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"cron-job.utils.d.ts","names":[],"sources":["../../../../../src/cli/commands/cron/utils/cron-job.utils.ts"],"mappings":";KAAY,YAAA;EACN,IAAA;EAAe,OAAA;AAAA;EACf,IAAA;EAAc,IAAA;AAAA;EACd,IAAA;EAAY,IAAA;AAAA;AAAA,KAEN,WAAA;EACV,OAAA;EACA,OAAA;EACA,SAAA;EACA,OAAA;EACA,OAAA;EACA,EAAA;EACA,SAAA;AAAA;AAAA,KAGU,WAAA;EACV,EAAA;EACA,IAAA;EACA,OAAA;EACA,QAAA,EAAU,YAAA;EACV,OAAA,EAAS,WAAA;AAAA;AAAA,iBAGK,kBAAA,CAAmB,QAAA,EAAU,YAAA;AAAA,iBAU7B,aAAA,CAAc,IAAA,EAAM,WAAA"}
1
+ {"version":3,"file":"cron-job.utils.d.ts","names":[],"sources":["../../../../../src/cli/commands/cron/utils/cron-job.utils.ts"],"mappings":";KAAY,YAAA;EACN,IAAA;EAAe,OAAA;AAAA;EACf,IAAA;EAAc,IAAA;AAAA;EACd,IAAA;EAAY,IAAA;AAAA;AAAA,KAEN,WAAA;EACV,OAAA;EACA,OAAA;EACA,SAAA;AAAA;AAAA,KAGU,WAAA;EACV,EAAA;EACA,IAAA;EACA,OAAA;EACA,QAAA,EAAU,YAAA;EACV,OAAA,EAAS,WAAA;AAAA;AAAA,iBAGK,kBAAA,CAAmB,QAAA,EAAU,YAAA;AAAA,iBAU7B,aAAA,CAAc,IAAA,EAAM,WAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"cron-job.utils.js","names":[],"sources":["../../../../../src/cli/commands/cron/utils/cron-job.utils.ts"],"sourcesContent":["export type CronSchedule =\n | { kind: \"every\"; everyMs?: number | null }\n | { kind: \"cron\"; expr?: string | null }\n | { kind: \"at\"; atMs?: number | null };\n\nexport type CronPayload = {\n message: string;\n agentId?: string | null;\n sessionId?: string | null;\n deliver?: boolean;\n channel?: string | null;\n to?: string | null;\n accountId?: string | null;\n};\n\nexport type CronJobView = {\n id: string;\n name: string;\n enabled: boolean;\n schedule: CronSchedule;\n payload: CronPayload;\n};\n\nexport function formatCronSchedule(schedule: CronSchedule): string {\n if (schedule.kind === \"every\") {\n return `every ${Math.round((schedule.everyMs ?? 0) / 1000)}s`;\n }\n if (schedule.kind === \"cron\") {\n return schedule.expr ?? \"\";\n }\n return schedule.atMs ? new Date(schedule.atMs).toISOString() : \"\";\n}\n\nexport function printCronJobs(jobs: CronJobView[]): void {\n if (!jobs.length) {\n console.log(\"No scheduled jobs.\");\n return;\n }\n for (const job of jobs) {\n console.log(`${job.id} [${job.enabled ? \"enabled\" : \"disabled\"}] ${job.name} ${formatCronSchedule(job.schedule)}`);\n }\n}\n"],"mappings":";AAuBA,SAAgB,mBAAmB,UAAgC;AACjE,KAAI,SAAS,SAAS,QACpB,QAAO,SAAS,KAAK,OAAO,SAAS,WAAW,KAAK,IAAK,CAAC;AAE7D,KAAI,SAAS,SAAS,OACpB,QAAO,SAAS,QAAQ;AAE1B,QAAO,SAAS,OAAO,IAAI,KAAK,SAAS,KAAK,CAAC,aAAa,GAAG;;AAGjE,SAAgB,cAAc,MAA2B;AACvD,KAAI,CAAC,KAAK,QAAQ;AAChB,UAAQ,IAAI,qBAAqB;AACjC;;AAEF,MAAK,MAAM,OAAO,KAChB,SAAQ,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,UAAU,YAAY,WAAW,IAAI,IAAI,KAAK,GAAG,mBAAmB,IAAI,SAAS,GAAG"}
1
+ {"version":3,"file":"cron-job.utils.js","names":[],"sources":["../../../../../src/cli/commands/cron/utils/cron-job.utils.ts"],"sourcesContent":["export type CronSchedule =\n | { kind: \"every\"; everyMs?: number | null }\n | { kind: \"cron\"; expr?: string | null }\n | { kind: \"at\"; atMs?: number | null };\n\nexport type CronPayload = {\n message: string;\n agentId?: string | null;\n sessionId?: string | null;\n};\n\nexport type CronJobView = {\n id: string;\n name: string;\n enabled: boolean;\n schedule: CronSchedule;\n payload: CronPayload;\n};\n\nexport function formatCronSchedule(schedule: CronSchedule): string {\n if (schedule.kind === \"every\") {\n return `every ${Math.round((schedule.everyMs ?? 0) / 1000)}s`;\n }\n if (schedule.kind === \"cron\") {\n return schedule.expr ?? \"\";\n }\n return schedule.atMs ? new Date(schedule.atMs).toISOString() : \"\";\n}\n\nexport function printCronJobs(jobs: CronJobView[]): void {\n if (!jobs.length) {\n console.log(\"No scheduled jobs.\");\n return;\n }\n for (const job of jobs) {\n console.log(`${job.id} [${job.enabled ? \"enabled\" : \"disabled\"}] ${job.name} ${formatCronSchedule(job.schedule)}`);\n }\n}\n"],"mappings":";AAmBA,SAAgB,mBAAmB,UAAgC;AACjE,KAAI,SAAS,SAAS,QACpB,QAAO,SAAS,KAAK,OAAO,SAAS,WAAW,KAAK,IAAK,CAAC;AAE7D,KAAI,SAAS,SAAS,OACpB,QAAO,SAAS,QAAQ;AAE1B,QAAO,SAAS,OAAO,IAAI,KAAK,SAAS,KAAK,CAAC,aAAa,GAAG;;AAGjE,SAAgB,cAAc,MAA2B;AACvD,KAAI,CAAC,KAAK,QAAQ;AAChB,UAAQ,IAAI,qBAAqB;AACjC;;AAEF,MAAK,MAAM,OAAO,KAChB,SAAQ,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,UAAU,YAAY,WAAW,IAAI,IAAI,KAAK,GAAG,mBAAmB,IAAI,SAAS,GAAG"}
@@ -14,7 +14,7 @@ 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
- type MessageBus$1 = NextclawCore.MessageBus;
17
+ type MessageBus = NextclawCore.MessageBus;
18
18
  type GatewayRuntimeOptions = {
19
19
  uiOverrides?: Partial<Config$1["ui"]>;
20
20
  uiStaticDir?: string | null;
@@ -38,7 +38,7 @@ declare class NextclawGatewayRuntime {
38
38
  private readonly options;
39
39
  readonly kernel: NextclawKernel;
40
40
  readonly appEventBus: EventBus;
41
- readonly messageBus: MessageBus$1;
41
+ readonly messageBus: MessageBus;
42
42
  readonly sessionManager: SessionManager;
43
43
  readonly automation: AutomationManager;
44
44
  readonly agentRunClient: AgentRunClient;
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"nextclaw-gateway-runtime.service.d.ts","names":[],"sources":["../../../../src/shared/services/gateway/nextclaw-gateway-runtime.service.ts"],"mappings":";;;;;;;;;;;;;;;KA8DK,QAAA,GAAS,YAAA,CAAa,MAAA;AAAA,KACtB,UAAA,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,UAAA;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;EA4D5B,KAAA,QAAkB,OAAA;EAAA,QAaV,KAAA;EAAA,QAOA,qBAAA;EAAA,QAOA,uBAAA;EAAA,QAIA,cAAA;EAAA,QAiCA,qBAAA;EAAA,QAmBA,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"}
@@ -16,6 +16,7 @@ import { ServiceFileWatcherRegistry, markLocalUiRuntimeIfStarted, startGatewayRu
16
16
  import { ServiceMarketplaceInstaller } from "../marketplace/service-marketplace-installer.service.js";
17
17
  import { NpmRuntimeUpdateHost } from "../ui/npm-runtime-update-host.service.js";
18
18
  import { createRuntimeControlHost } from "../ui/runtime-control-host.service.js";
19
+ import { readPanelAppClientSdkScript } from "../../utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.js";
19
20
  import * as NextclawCore from "@nextclaw/core";
20
21
  import { AgentRunClient, NextclawKernel, runGatewayInboundLoop } from "@nextclaw/kernel";
21
22
  import { resolve } from "node:path";
@@ -105,10 +106,7 @@ var NextclawGatewayRuntime = class {
105
106
  this.gatewayController = this.createGatewayController();
106
107
  this.kernel.provideGatewayController(this.gatewayController);
107
108
  this.deferredChannelStarter = this.startChannels;
108
- this.automation.onJob = createCronJobHandler({
109
- agentRunClient: this.agentRunClient,
110
- bus: this.messageBus
111
- });
109
+ this.automation.onJob = createCronJobHandler({ agentRunClient: this.agentRunClient });
112
110
  }
113
111
  start = async () => {
114
112
  logStartupTrace("service.start_gateway.begin");
@@ -165,6 +163,7 @@ var NextclawGatewayRuntime = class {
165
163
  appEventBus: this.appEventBus,
166
164
  uiConfig: this.uiConfig,
167
165
  uiStaticDir: this.uiStaticDir,
166
+ panelAppClientSdkScript: readPanelAppClientSdkScript,
168
167
  productVersion: this.productVersion,
169
168
  applyLiveConfigReload: this.configManager.applyLiveConfigReload,
170
169
  initializeAgentHomeDirectory: this.deps.initializeAgentHomeDirectory,
@@ -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 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
+ {"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 { readPanelAppClientSdkScript } from \"@nextclaw-service/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.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 });\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 panelAppClientSdkScript: readPanelAppClientSdkScript,\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,4 +1,3 @@
1
- import { MessageBus } from "@nextclaw/core";
2
1
  import { AgentRunClient } from "@nextclaw/kernel";
3
2
 
4
3
  //#region src/shared/services/gateway/utils/cron-job-handler.utils.d.ts
@@ -9,15 +8,10 @@ type CronJobLike = {
9
8
  message: string;
10
9
  agentId?: string | null;
11
10
  sessionId?: string | null;
12
- deliver?: boolean;
13
- channel?: string | null;
14
- to?: string | null;
15
- accountId?: string | null;
16
11
  };
17
12
  };
18
13
  declare function createCronJobHandler(params: {
19
14
  agentRunClient: AgentRunClient;
20
- bus: MessageBus;
21
15
  }): (job: CronJobLike) => Promise<string>;
22
16
  //#endregion
23
17
  export { createCronJobHandler };
@@ -1 +1 @@
1
- {"version":3,"file":"cron-job-handler.utils.d.ts","names":[],"sources":["../../../../../src/shared/services/gateway/utils/cron-job-handler.utils.ts"],"mappings":";;;;KAMK,WAAA;EACH,EAAA;EACA,IAAA;EACA,OAAA;IACE,OAAA;IACA,OAAA;IACA,SAAA;IACA,OAAA;IACA,OAAA;IACA,EAAA;IACA,SAAA;EAAA;AAAA;AAAA,iBAmCY,oBAAA,CAAqB,MAAA;EACnC,cAAA,EAAgB,cAAA;EAChB,GAAA,EAAK,UAAA;AAAA,KACF,GAAA,EAAK,WAAA,KAAgB,OAAA"}
1
+ {"version":3,"file":"cron-job-handler.utils.d.ts","names":[],"sources":["../../../../../src/shared/services/gateway/utils/cron-job-handler.utils.ts"],"mappings":";;;KAMK,WAAA;EACH,EAAA;EACA,IAAA;EACA,OAAA;IACE,OAAA;IACA,OAAA;IACA,SAAA;EAAA;AAAA;AAAA,iBAqDY,oBAAA,CAAqB,MAAA;EACnC,cAAA,EAAgB,cAAA;AAAA,KACb,GAAA,EAAK,WAAA,KAAgB,OAAA"}
@@ -5,45 +5,49 @@ function normalizeOptionalString(value) {
5
5
  return value.trim() || void 0;
6
6
  }
7
7
  function buildCronSessionMetadata(params) {
8
- const { job, agentId, accountId } = params;
9
- const metadata = {
8
+ const { job, agentId } = params;
9
+ return {
10
10
  agentId,
11
- channel: normalizeOptionalString(job.payload.channel) ?? "cli",
12
- chatId: normalizeOptionalString(job.payload.to) ?? "direct",
13
11
  label: job.name,
14
12
  cron_job_id: job.id,
15
13
  cron_job_name: job.name,
16
14
  session_origin: "cron"
17
15
  };
18
- if (accountId) metadata.accountId = accountId;
19
- return metadata;
16
+ }
17
+ function readToolFailureMessage(result) {
18
+ if (typeof result === "string" && result.startsWith("Error:")) return result.slice(6).trim() || result;
19
+ if (!result || typeof result !== "object" || !("ok" in result) || result.ok !== false) return null;
20
+ const error = "error" in result ? result.error : null;
21
+ if (error && typeof error === "object" && "message" in error && typeof error.message === "string") return error.message;
22
+ return "message tool failed";
23
+ }
24
+ function findMessageToolFailure(message) {
25
+ for (const part of message.parts) {
26
+ if (part.type !== "tool-invocation" || part.toolName !== "message" || part.state !== "result") continue;
27
+ const failureMessage = readToolFailureMessage(part.result);
28
+ if (failureMessage) return failureMessage;
29
+ }
30
+ return null;
20
31
  }
21
32
  function createCronJobHandler(params) {
22
33
  return async (job) => {
23
- const accountId = normalizeOptionalString(job.payload.accountId);
24
34
  const agentId = normalizeOptionalString(job.payload.agentId) ?? "main";
25
35
  const sessionId = normalizeOptionalString(job.payload.sessionId) ?? `cron:${job.id}`;
26
36
  const metadata = buildCronSessionMetadata({
27
37
  job,
28
- agentId,
29
- accountId
38
+ agentId
30
39
  });
31
- const response = (await params.agentRunClient.sendAndWaitForReply(await buildAgentRunSendPayload({
40
+ const result = await params.agentRunClient.sendAndWaitForReply(await buildAgentRunSendPayload({
32
41
  sessionId,
33
42
  content: job.payload.message,
34
43
  metadata
35
44
  }), {
36
45
  missingCompletedMessageError: "cron job completed without a final assistant message",
37
46
  runErrorMessage: "cron job failed"
38
- })).text;
39
- if (job.payload.deliver && job.payload.to) await params.bus.publishOutbound({
40
- channel: job.payload.channel ?? "cli",
41
- chatId: job.payload.to,
42
- content: response,
43
- media: [],
44
- metadata
45
47
  });
46
- return response;
48
+ const messageFailure = findMessageToolFailure(result.completedMessage);
49
+ if (messageFailure) throw new Error(`cron message delivery failed: ${messageFailure}`);
50
+ return result.text;
47
51
  };
48
52
  }
49
53
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"cron-job-handler.utils.js","names":[],"sources":["../../../../../src/shared/services/gateway/utils/cron-job-handler.utils.ts"],"sourcesContent":["import type { MessageBus } from \"@nextclaw/core\";\nimport {\n buildAgentRunSendPayload,\n type AgentRunClient,\n} from \"@nextclaw/kernel\";\n\ntype CronJobLike = {\n id: string;\n name: string;\n payload: {\n message: string;\n agentId?: string | null;\n sessionId?: string | null;\n deliver?: boolean;\n channel?: string | null;\n to?: string | null;\n accountId?: string | null;\n };\n};\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\nfunction buildCronSessionMetadata(params: {\n job: CronJobLike;\n agentId: string;\n accountId?: string;\n}): Record<string, unknown> {\n const { job, agentId, accountId } = params;\n const channel = normalizeOptionalString(job.payload.channel) ?? \"cli\";\n const chatId = normalizeOptionalString(job.payload.to) ?? \"direct\";\n const metadata: Record<string, unknown> = {\n agentId,\n channel,\n chatId,\n label: job.name,\n cron_job_id: job.id,\n cron_job_name: job.name,\n session_origin: \"cron\",\n };\n if (accountId) {\n metadata.accountId = accountId;\n }\n return metadata;\n}\n\nexport function createCronJobHandler(params: {\n agentRunClient: AgentRunClient;\n bus: MessageBus;\n}): (job: CronJobLike) => Promise<string> {\n return async (job: CronJobLike): Promise<string> => {\n const accountId = normalizeOptionalString(job.payload.accountId);\n const agentId = normalizeOptionalString(job.payload.agentId) ?? \"main\";\n const sessionId = normalizeOptionalString(job.payload.sessionId) ?? `cron:${job.id}`;\n const metadata = buildCronSessionMetadata({\n job,\n agentId,\n accountId,\n });\n const result = await params.agentRunClient.sendAndWaitForReply(await buildAgentRunSendPayload({\n sessionId,\n content: job.payload.message,\n metadata,\n }), {\n missingCompletedMessageError: \"cron job completed without a final assistant message\",\n runErrorMessage: \"cron job failed\",\n });\n const response = result.text;\n\n if (job.payload.deliver && job.payload.to) {\n await params.bus.publishOutbound({\n channel: job.payload.channel ?? \"cli\",\n chatId: job.payload.to,\n content: response,\n media: [],\n metadata,\n });\n }\n\n return response;\n };\n}\n"],"mappings":";;AAoBA,SAAS,wBAAwB,OAAoC;AACnE,KAAI,OAAO,UAAU,SACnB;AAGF,QADgB,MAAM,MAAM,IACV,KAAA;;AAGpB,SAAS,yBAAyB,QAIN;CAC1B,MAAM,EAAE,KAAK,SAAS,cAAc;CAGpC,MAAM,WAAoC;EACxC;EACA,SAJc,wBAAwB,IAAI,QAAQ,QAAQ,IAAI;EAK9D,QAJa,wBAAwB,IAAI,QAAQ,GAAG,IAAI;EAKxD,OAAO,IAAI;EACX,aAAa,IAAI;EACjB,eAAe,IAAI;EACnB,gBAAgB;EACjB;AACD,KAAI,UACF,UAAS,YAAY;AAEvB,QAAO;;AAGT,SAAgB,qBAAqB,QAGK;AACxC,QAAO,OAAO,QAAsC;EAClD,MAAM,YAAY,wBAAwB,IAAI,QAAQ,UAAU;EAChE,MAAM,UAAU,wBAAwB,IAAI,QAAQ,QAAQ,IAAI;EAChE,MAAM,YAAY,wBAAwB,IAAI,QAAQ,UAAU,IAAI,QAAQ,IAAI;EAChF,MAAM,WAAW,yBAAyB;GACxC;GACA;GACA;GACD,CAAC;EASF,MAAM,YARS,MAAM,OAAO,eAAe,oBAAoB,MAAM,yBAAyB;GAC5F;GACA,SAAS,IAAI,QAAQ;GACrB;GACD,CAAC,EAAE;GACF,8BAA8B;GAC9B,iBAAiB;GAClB,CAAC,EACsB;AAExB,MAAI,IAAI,QAAQ,WAAW,IAAI,QAAQ,GACrC,OAAM,OAAO,IAAI,gBAAgB;GAC/B,SAAS,IAAI,QAAQ,WAAW;GAChC,QAAQ,IAAI,QAAQ;GACpB,SAAS;GACT,OAAO,EAAE;GACT;GACD,CAAC;AAGJ,SAAO"}
1
+ {"version":3,"file":"cron-job-handler.utils.js","names":[],"sources":["../../../../../src/shared/services/gateway/utils/cron-job-handler.utils.ts"],"sourcesContent":["import {\n buildAgentRunSendPayload,\n type AgentRunClient,\n} from \"@nextclaw/kernel\";\nimport type { NcpMessage, NcpToolInvocationPart } from \"@nextclaw/ncp\";\n\ntype CronJobLike = {\n id: string;\n name: string;\n payload: {\n message: string;\n agentId?: string | null;\n sessionId?: string | null;\n };\n};\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\nfunction buildCronSessionMetadata(params: {\n job: CronJobLike;\n agentId: string;\n}): Record<string, unknown> {\n const { job, agentId } = params;\n return {\n agentId,\n label: job.name,\n cron_job_id: job.id,\n cron_job_name: job.name,\n session_origin: \"cron\",\n };\n}\n\nfunction readToolFailureMessage(result: unknown): string | null {\n if (typeof result === \"string\" && result.startsWith(\"Error:\")) {\n return result.slice(\"Error:\".length).trim() || result;\n }\n if (!result || typeof result !== \"object\" || !(\"ok\" in result) || result.ok !== false) {\n return null;\n }\n const error = \"error\" in result ? result.error : null;\n if (error && typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\") {\n return error.message;\n }\n return \"message tool failed\";\n}\n\nfunction findMessageToolFailure(message: NcpMessage): string | null {\n for (const part of message.parts) {\n if (part.type !== \"tool-invocation\" || part.toolName !== \"message\" || part.state !== \"result\") {\n continue;\n }\n const failureMessage = readToolFailureMessage((part as NcpToolInvocationPart).result);\n if (failureMessage) {\n return failureMessage;\n }\n }\n return null;\n}\n\nexport function createCronJobHandler(params: {\n agentRunClient: AgentRunClient;\n}): (job: CronJobLike) => Promise<string> {\n return async (job: CronJobLike): Promise<string> => {\n const agentId = normalizeOptionalString(job.payload.agentId) ?? \"main\";\n const sessionId = normalizeOptionalString(job.payload.sessionId) ?? `cron:${job.id}`;\n const metadata = buildCronSessionMetadata({\n job,\n agentId,\n });\n const result = await params.agentRunClient.sendAndWaitForReply(await buildAgentRunSendPayload({\n sessionId,\n content: job.payload.message,\n metadata,\n }), {\n missingCompletedMessageError: \"cron job completed without a final assistant message\",\n runErrorMessage: \"cron job failed\",\n });\n const messageFailure = findMessageToolFailure(result.completedMessage);\n if (messageFailure) {\n throw new Error(`cron message delivery failed: ${messageFailure}`);\n }\n return result.text;\n };\n}\n"],"mappings":";;AAgBA,SAAS,wBAAwB,OAAoC;AACnE,KAAI,OAAO,UAAU,SACnB;AAGF,QADgB,MAAM,MAAM,IACV,KAAA;;AAGpB,SAAS,yBAAyB,QAGN;CAC1B,MAAM,EAAE,KAAK,YAAY;AACzB,QAAO;EACL;EACA,OAAO,IAAI;EACX,aAAa,IAAI;EACjB,eAAe,IAAI;EACnB,gBAAgB;EACjB;;AAGH,SAAS,uBAAuB,QAAgC;AAC9D,KAAI,OAAO,WAAW,YAAY,OAAO,WAAW,SAAS,CAC3D,QAAO,OAAO,MAAM,EAAgB,CAAC,MAAM,IAAI;AAEjD,KAAI,CAAC,UAAU,OAAO,WAAW,YAAY,EAAE,QAAQ,WAAW,OAAO,OAAO,MAC9E,QAAO;CAET,MAAM,QAAQ,WAAW,SAAS,OAAO,QAAQ;AACjD,KAAI,SAAS,OAAO,UAAU,YAAY,aAAa,SAAS,OAAO,MAAM,YAAY,SACvF,QAAO,MAAM;AAEf,QAAO;;AAGT,SAAS,uBAAuB,SAAoC;AAClE,MAAK,MAAM,QAAQ,QAAQ,OAAO;AAChC,MAAI,KAAK,SAAS,qBAAqB,KAAK,aAAa,aAAa,KAAK,UAAU,SACnF;EAEF,MAAM,iBAAiB,uBAAwB,KAA+B,OAAO;AACrF,MAAI,eACF,QAAO;;AAGX,QAAO;;AAGT,SAAgB,qBAAqB,QAEK;AACxC,QAAO,OAAO,QAAsC;EAClD,MAAM,UAAU,wBAAwB,IAAI,QAAQ,QAAQ,IAAI;EAChE,MAAM,YAAY,wBAAwB,IAAI,QAAQ,UAAU,IAAI,QAAQ,IAAI;EAChF,MAAM,WAAW,yBAAyB;GACxC;GACA;GACD,CAAC;EACF,MAAM,SAAS,MAAM,OAAO,eAAe,oBAAoB,MAAM,yBAAyB;GAC5F;GACA,SAAS,IAAI,QAAQ;GACrB;GACD,CAAC,EAAE;GACF,8BAA8B;GAC9B,iBAAiB;GAClB,CAAC;EACF,MAAM,iBAAiB,uBAAuB,OAAO,iBAAiB;AACtE,MAAI,eACF,OAAM,IAAI,MAAM,iCAAiC,iBAAiB;AAEpE,SAAO,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"service-remote-runtime.utils.d.ts","names":[],"sources":["../../../../../src/shared/services/runtime/utils/service-remote-runtime.utils.ts"],"mappings":";;;;;KA0BK,sBAAA;EACH,GAAA;EACA,KAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,KASG,2BAAA;EAAgC,EAAA;EAAU,OAAA;AAAA;EAA0B,EAAA;EAAW,KAAA;AAAA;AAAA,iBA2IpE,kCAAA,CAAmC,MAAA;EACjD,WAAA;EACA,QAAA;EACA,UAAA;EACA,GAAA;EACA,kBAAA,IAAsB,GAAA;EACtB,kBAAA,SAA2B,mBAAA;AAAA,IACzB,2BAAA;AAAA,iBA+BY,yBAAA,CAA0B,MAAA;EACxC,UAAA,QAAkB,MAAA;EAClB,SAAA;EACA,WAAA;EACA,mBAAA,IAAuB,KAAA,EAAO,kBAAA;AAAA,IAC5B,mBAAA;AAAA,iBAmBY,8BAAA,CAA+B,MAAA;EAC7C,UAAA,QAAkB,MAAA;EAClB,QAAA,EAAU,IAAA,CAAK,MAAA;EACf,mBAAA;EAA8B,mBAAA,IAAuB,KAAA,EAAO,kBAAA;AAAA,IAC1D,mBAAA;AAAA,iBAaY,+BAAA,CAAgC,MAAA;EAC9C,MAAA,EAAQ,MAAA;EACR,KAAA,GAAQ,mBAAA;EACR,kBAAA;EACA,QAAA,EAAU,sBAAA;AAAA;AAAA,iBAmBI,6BAAA,CAA8B,MAAA;EAC5C,KAAA,GAAQ,mBAAA;EACR,kBAAA;EACA,SAAA;IAAa,KAAA;IAAgB,cAAA;EAAA;EAC7B,QAAA,EAAU,sBAAA;AAAA,IACR,mBAAA"}
1
+ {"version":3,"file":"service-remote-runtime.utils.d.ts","names":[],"sources":["../../../../../src/shared/services/runtime/utils/service-remote-runtime.utils.ts"],"mappings":";;;;;KA0BK,sBAAA;EACH,GAAA;EACA,KAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,KASG,2BAAA;EAAgC,EAAA;EAAU,OAAA;AAAA;EAA0B,EAAA;EAAW,KAAA;AAAA;AAAA,iBA4IpE,kCAAA,CAAmC,MAAA;EACjD,WAAA;EACA,QAAA;EACA,UAAA;EACA,GAAA;EACA,kBAAA,IAAsB,GAAA;EACtB,kBAAA,SAA2B,mBAAA;AAAA,IACzB,2BAAA;AAAA,iBAuCY,yBAAA,CAA0B,MAAA;EACxC,UAAA,QAAkB,MAAA;EAClB,SAAA;EACA,WAAA;EACA,mBAAA,IAAuB,KAAA,EAAO,kBAAA;AAAA,IAC5B,mBAAA;AAAA,iBAoBY,8BAAA,CAA+B,MAAA;EAC7C,UAAA,QAAkB,MAAA;EAClB,QAAA,EAAU,IAAA,CAAK,MAAA;EACf,mBAAA;EAA8B,mBAAA,IAAuB,KAAA,EAAO,kBAAA;AAAA,IAC1D,mBAAA;AAAA,iBAcY,+BAAA,CAAgC,MAAA;EAC9C,MAAA,EAAQ,MAAA;EACR,KAAA,GAAQ,mBAAA;EACR,kBAAA;EACA,QAAA,EAAU,sBAAA;AAAA;AAAA,iBAmBI,6BAAA,CAA8B,MAAA;EAC5C,KAAA,GAAQ,mBAAA;EACR,kBAAA;EACA,SAAA;IAAa,KAAA;IAAgB,cAAA;EAAA;EAC7B,QAAA,EAAU,sBAAA;AAAA,IACR,mBAAA"}
@@ -1,13 +1,13 @@
1
1
  import { isProcessRunning, resolveUiApiBase } from "../../../utils/cli.utils.js";
2
2
  import { managedServiceStateStore } from "../../../stores/managed-service-state.store.js";
3
3
  import { buildNextclawConfiguredRemoteState, createNextclawRemoteConnector, createNextclawRemoteStatusStore } from "../../../../commands/remote/utils/remote-runtime-support.utils.js";
4
- import { getDataDir } from "@nextclaw/core";
4
+ import { getRunPath } from "@nextclaw/core";
5
5
  import { RemoteServiceModule } from "@nextclaw/remote";
6
6
  import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
7
7
  import { dirname, resolve } from "node:path";
8
8
  //#region src/shared/services/runtime/utils/service-remote-runtime.utils.ts
9
9
  function resolveRemoteOwnershipLockPath() {
10
- return resolve(getDataDir(), "run", "remote-owner.lock.json");
10
+ return resolve(getRunPath(), "remote-owner.lock.json");
11
11
  }
12
12
  function readRemoteOwnershipRecord(lockPath) {
13
13
  try {
@@ -57,15 +57,16 @@ function detectManagedRemoteOwnershipConflict(params) {
57
57
  });
58
58
  }
59
59
  function tryClaimRemoteOwnershipLock(params) {
60
+ const { claim, currentPid, isProcessRunningFn, lockPath } = params;
60
61
  for (let attempt = 0; attempt < 2; attempt += 1) try {
61
- const fd = openSync(params.lockPath, "wx");
62
- writeFileSync(fd, `${JSON.stringify(params.claim, null, 2)}\n`, "utf-8");
62
+ const fd = openSync(lockPath, "wx");
63
+ writeFileSync(fd, `${JSON.stringify(claim, null, 2)}\n`, "utf-8");
63
64
  closeSync(fd);
64
65
  return {
65
66
  ok: true,
66
67
  release: createRemoteOwnershipRelease({
67
- lockPath: params.lockPath,
68
- claim: params.claim
68
+ lockPath,
69
+ claim
69
70
  })
70
71
  };
71
72
  } catch (error) {
@@ -73,12 +74,12 @@ function tryClaimRemoteOwnershipLock(params) {
73
74
  ok: false,
74
75
  error: `Failed to claim local remote runtime ownership: ${error instanceof Error ? error.message : String(error)}`
75
76
  };
76
- const existing = readRemoteOwnershipRecord(params.lockPath);
77
- if (existing && existing.pid !== params.currentPid && params.isProcessRunningFn(existing.pid)) return {
77
+ const existing = readRemoteOwnershipRecord(lockPath);
78
+ if (existing && existing.pid !== currentPid && isProcessRunningFn(existing.pid)) return {
78
79
  ok: false,
79
80
  error: buildLocalProcessOwnershipError(existing)
80
81
  };
81
- removeRemoteOwnershipLock(params.lockPath);
82
+ removeRemoteOwnershipLock(lockPath);
82
83
  }
83
84
  return {
84
85
  ok: false,
@@ -86,14 +87,15 @@ function tryClaimRemoteOwnershipLock(params) {
86
87
  };
87
88
  }
88
89
  function claimManagedRemoteRuntimeOwnership(params) {
89
- const lockPath = params.lockPath ?? resolveRemoteOwnershipLockPath();
90
- const currentPid = params.currentPid ?? process.pid;
91
- const now = params.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
92
- const isProcessRunningFn = params.isProcessRunningFn ?? isProcessRunning;
90
+ const { localOrigin, lockPath: lockPathOverride, currentPid: currentPidOverride, now: nowOverride, isProcessRunningFn: isProcessRunningOverride, readServiceStateFn: readServiceStateOverride } = params;
91
+ const lockPath = lockPathOverride ?? resolveRemoteOwnershipLockPath();
92
+ const currentPid = currentPidOverride ?? process.pid;
93
+ const now = nowOverride ?? (() => (/* @__PURE__ */ new Date()).toISOString());
94
+ const isProcessRunningFn = isProcessRunningOverride ?? isProcessRunning;
93
95
  const managedConflict = detectManagedRemoteOwnershipConflict({
94
96
  currentPid,
95
97
  isProcessRunningFn,
96
- readServiceStateFn: params.readServiceStateFn ?? managedServiceStateStore.read
98
+ readServiceStateFn: readServiceStateOverride ?? managedServiceStateStore.read
97
99
  });
98
100
  if (managedConflict) return {
99
101
  ok: false,
@@ -104,7 +106,7 @@ function claimManagedRemoteRuntimeOwnership(params) {
104
106
  lockPath,
105
107
  claim: {
106
108
  pid: currentPid,
107
- localOrigin: params.localOrigin,
109
+ localOrigin,
108
110
  claimedAt: now()
109
111
  },
110
112
  currentPid,
@@ -112,14 +114,15 @@ function claimManagedRemoteRuntimeOwnership(params) {
112
114
  });
113
115
  }
114
116
  function createManagedRemoteModule(params) {
115
- if (!params.uiEnabled) return null;
117
+ const { loadConfig, localOrigin, onRemoteStateChange, uiEnabled } = params;
118
+ if (!uiEnabled) return null;
116
119
  return new RemoteServiceModule({
117
- loadConfig: params.loadConfig,
118
- uiEnabled: params.uiEnabled,
119
- localOrigin: params.localOrigin,
120
- statusStore: createNextclawRemoteStatusStore("service", params.onRemoteStateChange),
120
+ loadConfig,
121
+ uiEnabled,
122
+ localOrigin,
123
+ statusStore: createNextclawRemoteStatusStore("service", onRemoteStateChange),
121
124
  createConnector: (logger) => createNextclawRemoteConnector({ logger }),
122
- claimOwnership: () => claimManagedRemoteRuntimeOwnership({ localOrigin: params.localOrigin }),
125
+ claimOwnership: () => claimManagedRemoteRuntimeOwnership({ localOrigin }),
123
126
  logger: {
124
127
  info: (message) => console.log(`[remote] ${message}`),
125
128
  warn: (message) => console.warn(`[remote] ${message}`),
@@ -128,12 +131,13 @@ function createManagedRemoteModule(params) {
128
131
  });
129
132
  }
130
133
  function createManagedRemoteModuleForUi(params) {
131
- const explicitLocalOrigin = params.localOriginOverride?.trim() ?? process.env.NEXTCLAW_REMOTE_LOCAL_ORIGIN?.trim();
134
+ const { loadConfig, localOriginOverride, onRemoteStateChange, uiConfig } = params;
135
+ const explicitLocalOrigin = localOriginOverride?.trim() ?? process.env.NEXTCLAW_REMOTE_LOCAL_ORIGIN?.trim();
132
136
  return createManagedRemoteModule({
133
- loadConfig: params.loadConfig,
134
- uiEnabled: params.uiConfig.enabled,
135
- onRemoteStateChange: params.onRemoteStateChange,
136
- localOrigin: explicitLocalOrigin && explicitLocalOrigin.length > 0 ? explicitLocalOrigin.replace(/\/+$/, "") : resolveUiApiBase(params.uiConfig.host, params.uiConfig.port)
137
+ loadConfig,
138
+ uiEnabled: uiConfig.enabled,
139
+ onRemoteStateChange,
140
+ localOrigin: explicitLocalOrigin && explicitLocalOrigin.length > 0 ? explicitLocalOrigin.replace(/\/+$/, "") : resolveUiApiBase(uiConfig.host, uiConfig.port)
137
141
  });
138
142
  }
139
143
  function writeInitialManagedServiceState(params) {
@@ -1 +1 @@
1
- {"version":3,"file":"service-remote-runtime.utils.js","names":[],"sources":["../../../../../src/shared/services/runtime/utils/service-remote-runtime.utils.ts"],"sourcesContent":["import type { Config } from \"@nextclaw/core\";\nimport { RemoteServiceModule, type RemoteRuntimeState } from \"@nextclaw/remote\";\nimport {\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readFileSync,\n rmSync,\n unlinkSync,\n writeFileSync\n} from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { getDataDir } from \"@nextclaw/core\";\nimport { resolveUiApiBase, isProcessRunning } from \"@nextclaw-service/shared/utils/cli.utils.js\";\nimport {\n managedServiceStateStore,\n type ManagedServiceLease,\n type ManagedServiceState\n} from \"@nextclaw-service/shared/stores/managed-service-state.store.js\";\nimport {\n buildNextclawConfiguredRemoteState,\n createNextclawRemoteConnector,\n createNextclawRemoteStatusStore\n} from \"@nextclaw-service/commands/remote/utils/remote-runtime-support.utils.js\";\n\ntype ManagedServiceSnapshot = {\n pid: number;\n uiUrl: string;\n apiUrl: string;\n uiHost: string;\n uiPort: number;\n logPath: string;\n};\n\ntype RemoteRuntimeOwnerRecord = {\n pid: number;\n localOrigin: string;\n claimedAt: string;\n};\n\ntype RemoteRuntimeOwnershipClaim = { ok: true; release: () => void } | { ok: false; error: string };\n\nfunction resolveRemoteOwnershipLockPath(): string {\n return resolve(getDataDir(), \"run\", \"remote-owner.lock.json\");\n}\n\nfunction readRemoteOwnershipRecord(lockPath: string): RemoteRuntimeOwnerRecord | null {\n try {\n const raw = JSON.parse(readFileSync(lockPath, \"utf-8\")) as Partial<RemoteRuntimeOwnerRecord>;\n if (typeof raw.pid !== \"number\" || !Number.isFinite(raw.pid)) {\n return null;\n }\n return {\n pid: raw.pid,\n localOrigin: typeof raw.localOrigin === \"string\" ? raw.localOrigin : \"\",\n claimedAt: typeof raw.claimedAt === \"string\" ? raw.claimedAt : \"\"\n };\n } catch {\n return null;\n }\n}\n\nfunction removeRemoteOwnershipLock(lockPath: string): void {\n if (!existsSync(lockPath)) {\n return;\n }\n try {\n unlinkSync(lockPath);\n } catch {\n try {\n rmSync(lockPath, { force: true });\n } catch {\n // Ignore cleanup failures.\n }\n }\n}\n\nfunction buildManagedServiceOwnershipError(params: {\n pid: number;\n ownerOrigin?: string;\n}): string {\n return (\n `Remote access is already owned by running NextClaw service PID ${params.pid}`\n + `${params.ownerOrigin ? ` (${params.ownerOrigin})` : \"\"}. `\n + \"Stop that service or disable remote there before starting another process with the same NEXTCLAW_HOME.\"\n );\n}\n\nfunction buildLocalProcessOwnershipError(record: RemoteRuntimeOwnerRecord): string {\n const originText = record.localOrigin ? ` (${record.localOrigin})` : \"\";\n return (\n `Remote access is already owned by local NextClaw process PID ${record.pid}${originText}. `\n + \"Stop that process or use a different NEXTCLAW_HOME before starting another remote-enabled process.\"\n );\n}\n\nfunction createRemoteOwnershipRelease(params: {\n lockPath: string;\n claim: RemoteRuntimeOwnerRecord;\n}): () => void {\n let released = false;\n return () => {\n if (released) {\n return;\n }\n released = true;\n const current = readRemoteOwnershipRecord(params.lockPath);\n if (!current || (current.pid === params.claim.pid && current.claimedAt === params.claim.claimedAt)) {\n removeRemoteOwnershipLock(params.lockPath);\n }\n };\n}\n\nfunction detectManagedRemoteOwnershipConflict(params: {\n currentPid: number;\n isProcessRunningFn: (pid: number) => boolean;\n readServiceStateFn: () => ManagedServiceState | null;\n}): string | null {\n const runningService = params.readServiceStateFn();\n if (\n !runningService\n || runningService.pid === params.currentPid\n || !params.isProcessRunningFn(runningService.pid)\n || !runningService.remote?.enabled\n ) {\n return null;\n }\n\n return buildManagedServiceOwnershipError({\n pid: runningService.pid,\n ownerOrigin: runningService.remote.localOrigin ?? runningService.uiUrl\n });\n}\n\nfunction tryClaimRemoteOwnershipLock(params: {\n lockPath: string;\n claim: RemoteRuntimeOwnerRecord;\n currentPid: number;\n isProcessRunningFn: (pid: number) => boolean;\n}): RemoteRuntimeOwnershipClaim {\n for (let attempt = 0; attempt < 2; attempt += 1) {\n try {\n const fd = openSync(params.lockPath, \"wx\");\n writeFileSync(fd, `${JSON.stringify(params.claim, null, 2)}\\n`, \"utf-8\");\n closeSync(fd);\n return {\n ok: true,\n release: createRemoteOwnershipRelease({\n lockPath: params.lockPath,\n claim: params.claim\n })\n };\n } catch (error) {\n const code = typeof error === \"object\" && error && \"code\" in error ? String(error.code) : \"\";\n if (code !== \"EEXIST\") {\n return {\n ok: false,\n error: `Failed to claim local remote runtime ownership: ${error instanceof Error ? error.message : String(error)}`\n };\n }\n\n const existing = readRemoteOwnershipRecord(params.lockPath);\n if (existing && existing.pid !== params.currentPid && params.isProcessRunningFn(existing.pid)) {\n return {\n ok: false,\n error: buildLocalProcessOwnershipError(existing)\n };\n }\n\n removeRemoteOwnershipLock(params.lockPath);\n }\n }\n\n return {\n ok: false,\n error: \"Failed to claim local remote runtime ownership after clearing a stale lock.\"\n };\n}\n\nexport function claimManagedRemoteRuntimeOwnership(params: {\n localOrigin: string;\n lockPath?: string;\n currentPid?: number;\n now?: () => string;\n isProcessRunningFn?: (pid: number) => boolean;\n readServiceStateFn?: () => ManagedServiceState | null;\n}): RemoteRuntimeOwnershipClaim {\n const lockPath = params.lockPath ?? resolveRemoteOwnershipLockPath();\n const currentPid = params.currentPid ?? process.pid;\n const now = params.now ?? (() => new Date().toISOString());\n const isProcessRunningFn = params.isProcessRunningFn ?? isProcessRunning;\n const readServiceStateFn = params.readServiceStateFn ?? managedServiceStateStore.read;\n const managedConflict = detectManagedRemoteOwnershipConflict({\n currentPid,\n isProcessRunningFn,\n readServiceStateFn\n });\n if (managedConflict) {\n return {\n ok: false,\n error: managedConflict\n };\n }\n\n mkdirSync(dirname(lockPath), { recursive: true });\n return tryClaimRemoteOwnershipLock({\n lockPath,\n claim: {\n pid: currentPid,\n localOrigin: params.localOrigin,\n claimedAt: now()\n },\n currentPid,\n isProcessRunningFn\n });\n}\n\nexport function createManagedRemoteModule(params: {\n loadConfig: () => Config;\n uiEnabled: boolean;\n localOrigin: string;\n onRemoteStateChange?: (state: RemoteRuntimeState) => void;\n}): RemoteServiceModule | null {\n if (!params.uiEnabled) {\n return null;\n }\n return new RemoteServiceModule({\n loadConfig: params.loadConfig,\n uiEnabled: params.uiEnabled,\n localOrigin: params.localOrigin,\n statusStore: createNextclawRemoteStatusStore(\"service\", params.onRemoteStateChange),\n createConnector: (logger) => createNextclawRemoteConnector({ logger }),\n claimOwnership: () => claimManagedRemoteRuntimeOwnership({ localOrigin: params.localOrigin }),\n logger: {\n info: (message) => console.log(`[remote] ${message}`),\n warn: (message) => console.warn(`[remote] ${message}`),\n error: (message) => console.error(`[remote] ${message}`)\n }\n });\n}\n\nexport function createManagedRemoteModuleForUi(params: {\n loadConfig: () => Config;\n uiConfig: Pick<Config[\"ui\"], \"enabled\" | \"host\" | \"port\">;\n localOriginOverride?: string; onRemoteStateChange?: (state: RemoteRuntimeState) => void;\n}): RemoteServiceModule | null {\n const explicitLocalOrigin = params.localOriginOverride?.trim() ?? process.env.NEXTCLAW_REMOTE_LOCAL_ORIGIN?.trim();\n return createManagedRemoteModule({\n loadConfig: params.loadConfig,\n uiEnabled: params.uiConfig.enabled,\n onRemoteStateChange: params.onRemoteStateChange,\n localOrigin:\n explicitLocalOrigin && explicitLocalOrigin.length > 0\n ? explicitLocalOrigin.replace(/\\/+$/, \"\")\n : resolveUiApiBase(params.uiConfig.host, params.uiConfig.port)\n });\n}\n\nexport function writeInitialManagedServiceState(params: {\n config: Config;\n lease?: ManagedServiceLease;\n readinessTimeoutMs: number;\n snapshot: ManagedServiceSnapshot;\n}): void {\n const { config, lease, readinessTimeoutMs, snapshot } = params;\n managedServiceStateStore.write({\n pid: snapshot.pid,\n startedAt: new Date().toISOString(),\n uiUrl: snapshot.uiUrl,\n apiUrl: snapshot.apiUrl,\n uiHost: snapshot.uiHost,\n uiPort: snapshot.uiPort,\n logPath: snapshot.logPath,\n ...(lease ? { lease } : {}),\n startupLastProbeError: null,\n startupTimeoutMs: readinessTimeoutMs,\n startupCheckedAt: new Date().toISOString(),\n ...(config.remote.enabled ? { remote: buildNextclawConfiguredRemoteState(config) } : {})\n });\n}\n\nexport function writeReadyManagedServiceState(params: {\n lease?: ManagedServiceLease;\n readinessTimeoutMs: number;\n readiness: { ready: boolean; lastProbeError: string | null };\n snapshot: ManagedServiceSnapshot;\n}): ManagedServiceState {\n const { lease, readiness, readinessTimeoutMs, snapshot } = params;\n const currentState = managedServiceStateStore.read();\n const state: ManagedServiceState = {\n pid: snapshot.pid,\n startedAt: currentState?.startedAt ?? new Date().toISOString(),\n uiUrl: snapshot.uiUrl,\n apiUrl: snapshot.apiUrl,\n uiHost: snapshot.uiHost,\n uiPort: snapshot.uiPort,\n logPath: snapshot.logPath,\n ...(lease ? { lease } : currentState?.lease ? { lease: currentState.lease } : {}),\n startupState: readiness.ready ? \"ready\" : \"degraded\",\n startupLastProbeError: readiness.lastProbeError,\n startupTimeoutMs: readinessTimeoutMs,\n startupCheckedAt: new Date().toISOString(),\n ...(currentState?.remote ? { remote: currentState.remote } : {})\n };\n managedServiceStateStore.write(state);\n return state;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service-remote-runtime.utils.js","names":[],"sources":["../../../../../src/shared/services/runtime/utils/service-remote-runtime.utils.ts"],"sourcesContent":["import type { Config } from \"@nextclaw/core\";\nimport { RemoteServiceModule, type RemoteRuntimeState } from \"@nextclaw/remote\";\nimport {\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readFileSync,\n rmSync,\n unlinkSync,\n writeFileSync\n} from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { getRunPath } from \"@nextclaw/core\";\nimport { resolveUiApiBase, isProcessRunning } from \"@nextclaw-service/shared/utils/cli.utils.js\";\nimport {\n managedServiceStateStore,\n type ManagedServiceLease,\n type ManagedServiceState\n} from \"@nextclaw-service/shared/stores/managed-service-state.store.js\";\nimport {\n buildNextclawConfiguredRemoteState,\n createNextclawRemoteConnector,\n createNextclawRemoteStatusStore\n} from \"@nextclaw-service/commands/remote/utils/remote-runtime-support.utils.js\";\n\ntype ManagedServiceSnapshot = {\n pid: number;\n uiUrl: string;\n apiUrl: string;\n uiHost: string;\n uiPort: number;\n logPath: string;\n};\n\ntype RemoteRuntimeOwnerRecord = {\n pid: number;\n localOrigin: string;\n claimedAt: string;\n};\n\ntype RemoteRuntimeOwnershipClaim = { ok: true; release: () => void } | { ok: false; error: string };\n\nfunction resolveRemoteOwnershipLockPath(): string {\n return resolve(getRunPath(), \"remote-owner.lock.json\");\n}\n\nfunction readRemoteOwnershipRecord(lockPath: string): RemoteRuntimeOwnerRecord | null {\n try {\n const raw = JSON.parse(readFileSync(lockPath, \"utf-8\")) as Partial<RemoteRuntimeOwnerRecord>;\n if (typeof raw.pid !== \"number\" || !Number.isFinite(raw.pid)) {\n return null;\n }\n return {\n pid: raw.pid,\n localOrigin: typeof raw.localOrigin === \"string\" ? raw.localOrigin : \"\",\n claimedAt: typeof raw.claimedAt === \"string\" ? raw.claimedAt : \"\"\n };\n } catch {\n return null;\n }\n}\n\nfunction removeRemoteOwnershipLock(lockPath: string): void {\n if (!existsSync(lockPath)) {\n return;\n }\n try {\n unlinkSync(lockPath);\n } catch {\n try {\n rmSync(lockPath, { force: true });\n } catch {\n // Ignore cleanup failures.\n }\n }\n}\n\nfunction buildManagedServiceOwnershipError(params: {\n pid: number;\n ownerOrigin?: string;\n}): string {\n return (\n `Remote access is already owned by running NextClaw service PID ${params.pid}`\n + `${params.ownerOrigin ? ` (${params.ownerOrigin})` : \"\"}. `\n + \"Stop that service or disable remote there before starting another process with the same NEXTCLAW_HOME.\"\n );\n}\n\nfunction buildLocalProcessOwnershipError(record: RemoteRuntimeOwnerRecord): string {\n const originText = record.localOrigin ? ` (${record.localOrigin})` : \"\";\n return (\n `Remote access is already owned by local NextClaw process PID ${record.pid}${originText}. `\n + \"Stop that process or use a different NEXTCLAW_HOME before starting another remote-enabled process.\"\n );\n}\n\nfunction createRemoteOwnershipRelease(params: {\n lockPath: string;\n claim: RemoteRuntimeOwnerRecord;\n}): () => void {\n let released = false;\n return () => {\n if (released) {\n return;\n }\n released = true;\n const current = readRemoteOwnershipRecord(params.lockPath);\n if (!current || (current.pid === params.claim.pid && current.claimedAt === params.claim.claimedAt)) {\n removeRemoteOwnershipLock(params.lockPath);\n }\n };\n}\n\nfunction detectManagedRemoteOwnershipConflict(params: {\n currentPid: number;\n isProcessRunningFn: (pid: number) => boolean;\n readServiceStateFn: () => ManagedServiceState | null;\n}): string | null {\n const runningService = params.readServiceStateFn();\n if (\n !runningService\n || runningService.pid === params.currentPid\n || !params.isProcessRunningFn(runningService.pid)\n || !runningService.remote?.enabled\n ) {\n return null;\n }\n\n return buildManagedServiceOwnershipError({\n pid: runningService.pid,\n ownerOrigin: runningService.remote.localOrigin ?? runningService.uiUrl\n });\n}\n\nfunction tryClaimRemoteOwnershipLock(params: {\n lockPath: string;\n claim: RemoteRuntimeOwnerRecord;\n currentPid: number;\n isProcessRunningFn: (pid: number) => boolean;\n}): RemoteRuntimeOwnershipClaim {\n const { claim, currentPid, isProcessRunningFn, lockPath } = params;\n for (let attempt = 0; attempt < 2; attempt += 1) {\n try {\n const fd = openSync(lockPath, \"wx\");\n writeFileSync(fd, `${JSON.stringify(claim, null, 2)}\\n`, \"utf-8\");\n closeSync(fd);\n return {\n ok: true,\n release: createRemoteOwnershipRelease({\n lockPath,\n claim\n })\n };\n } catch (error) {\n const code = typeof error === \"object\" && error && \"code\" in error ? String(error.code) : \"\";\n if (code !== \"EEXIST\") {\n return {\n ok: false,\n error: `Failed to claim local remote runtime ownership: ${error instanceof Error ? error.message : String(error)}`\n };\n }\n\n const existing = readRemoteOwnershipRecord(lockPath);\n if (existing && existing.pid !== currentPid && isProcessRunningFn(existing.pid)) {\n return {\n ok: false,\n error: buildLocalProcessOwnershipError(existing)\n };\n }\n\n removeRemoteOwnershipLock(lockPath);\n }\n }\n\n return {\n ok: false,\n error: \"Failed to claim local remote runtime ownership after clearing a stale lock.\"\n };\n}\n\nexport function claimManagedRemoteRuntimeOwnership(params: {\n localOrigin: string;\n lockPath?: string;\n currentPid?: number;\n now?: () => string;\n isProcessRunningFn?: (pid: number) => boolean;\n readServiceStateFn?: () => ManagedServiceState | null;\n}): RemoteRuntimeOwnershipClaim {\n const {\n localOrigin,\n lockPath: lockPathOverride,\n currentPid: currentPidOverride,\n now: nowOverride,\n isProcessRunningFn: isProcessRunningOverride,\n readServiceStateFn: readServiceStateOverride\n } = params;\n const lockPath = lockPathOverride ?? resolveRemoteOwnershipLockPath();\n const currentPid = currentPidOverride ?? process.pid;\n const now = nowOverride ?? (() => new Date().toISOString());\n const isProcessRunningFn = isProcessRunningOverride ?? isProcessRunning;\n const readServiceStateFn = readServiceStateOverride ?? managedServiceStateStore.read;\n const managedConflict = detectManagedRemoteOwnershipConflict({\n currentPid,\n isProcessRunningFn,\n readServiceStateFn\n });\n if (managedConflict) {\n return {\n ok: false,\n error: managedConflict\n };\n }\n\n mkdirSync(dirname(lockPath), { recursive: true });\n return tryClaimRemoteOwnershipLock({\n lockPath,\n claim: {\n pid: currentPid,\n localOrigin,\n claimedAt: now()\n },\n currentPid,\n isProcessRunningFn\n });\n}\n\nexport function createManagedRemoteModule(params: {\n loadConfig: () => Config;\n uiEnabled: boolean;\n localOrigin: string;\n onRemoteStateChange?: (state: RemoteRuntimeState) => void;\n}): RemoteServiceModule | null {\n const { loadConfig, localOrigin, onRemoteStateChange, uiEnabled } = params;\n if (!uiEnabled) {\n return null;\n }\n return new RemoteServiceModule({\n loadConfig,\n uiEnabled,\n localOrigin,\n statusStore: createNextclawRemoteStatusStore(\"service\", onRemoteStateChange),\n createConnector: (logger) => createNextclawRemoteConnector({ logger }),\n claimOwnership: () => claimManagedRemoteRuntimeOwnership({ localOrigin }),\n logger: {\n info: (message) => console.log(`[remote] ${message}`),\n warn: (message) => console.warn(`[remote] ${message}`),\n error: (message) => console.error(`[remote] ${message}`)\n }\n });\n}\n\nexport function createManagedRemoteModuleForUi(params: {\n loadConfig: () => Config;\n uiConfig: Pick<Config[\"ui\"], \"enabled\" | \"host\" | \"port\">;\n localOriginOverride?: string; onRemoteStateChange?: (state: RemoteRuntimeState) => void;\n}): RemoteServiceModule | null {\n const { loadConfig, localOriginOverride, onRemoteStateChange, uiConfig } = params;\n const explicitLocalOrigin = localOriginOverride?.trim() ?? process.env.NEXTCLAW_REMOTE_LOCAL_ORIGIN?.trim();\n return createManagedRemoteModule({\n loadConfig,\n uiEnabled: uiConfig.enabled,\n onRemoteStateChange,\n localOrigin:\n explicitLocalOrigin && explicitLocalOrigin.length > 0\n ? explicitLocalOrigin.replace(/\\/+$/, \"\")\n : resolveUiApiBase(uiConfig.host, uiConfig.port)\n });\n}\n\nexport function writeInitialManagedServiceState(params: {\n config: Config;\n lease?: ManagedServiceLease;\n readinessTimeoutMs: number;\n snapshot: ManagedServiceSnapshot;\n}): void {\n const { config, lease, readinessTimeoutMs, snapshot } = params;\n managedServiceStateStore.write({\n pid: snapshot.pid,\n startedAt: new Date().toISOString(),\n uiUrl: snapshot.uiUrl,\n apiUrl: snapshot.apiUrl,\n uiHost: snapshot.uiHost,\n uiPort: snapshot.uiPort,\n logPath: snapshot.logPath,\n ...(lease ? { lease } : {}),\n startupLastProbeError: null,\n startupTimeoutMs: readinessTimeoutMs,\n startupCheckedAt: new Date().toISOString(),\n ...(config.remote.enabled ? { remote: buildNextclawConfiguredRemoteState(config) } : {})\n });\n}\n\nexport function writeReadyManagedServiceState(params: {\n lease?: ManagedServiceLease;\n readinessTimeoutMs: number;\n readiness: { ready: boolean; lastProbeError: string | null };\n snapshot: ManagedServiceSnapshot;\n}): ManagedServiceState {\n const { lease, readiness, readinessTimeoutMs, snapshot } = params;\n const currentState = managedServiceStateStore.read();\n const state: ManagedServiceState = {\n pid: snapshot.pid,\n startedAt: currentState?.startedAt ?? new Date().toISOString(),\n uiUrl: snapshot.uiUrl,\n apiUrl: snapshot.apiUrl,\n uiHost: snapshot.uiHost,\n uiPort: snapshot.uiPort,\n logPath: snapshot.logPath,\n ...(lease ? { lease } : currentState?.lease ? { lease: currentState.lease } : {}),\n startupState: readiness.ready ? \"ready\" : \"degraded\",\n startupLastProbeError: readiness.lastProbeError,\n startupTimeoutMs: readinessTimeoutMs,\n startupCheckedAt: new Date().toISOString(),\n ...(currentState?.remote ? { remote: currentState.remote } : {})\n };\n managedServiceStateStore.write(state);\n return state;\n}\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
- import { getDataDir } from "@nextclaw/core";
1
+ import { getRunPath } from "@nextclaw/core";
2
2
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  //#region src/shared/stores/companion-runtime.store.ts
5
5
  var CompanionRuntimeStore = class {
6
6
  get path() {
7
- return resolve(getDataDir(), "run", "companion.json");
7
+ return resolve(getRunPath(), "companion.json");
8
8
  }
9
9
  read = () => {
10
10
  if (!existsSync(this.path)) return null;
@@ -1 +1 @@
1
- {"version":3,"file":"companion-runtime.store.js","names":[],"sources":["../../../src/shared/stores/companion-runtime.store.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getDataDir } from \"@nextclaw/core\";\n\nexport type CompanionRuntimeState = {\n pid: number;\n startedAt: string;\n baseUrl: string;\n};\n\nexport class CompanionRuntimeStore {\n get path(): string {\n return resolve(getDataDir(), \"run\", \"companion.json\");\n }\n\n readonly read = (): CompanionRuntimeState | null => {\n if (!existsSync(this.path)) {\n return null;\n }\n try {\n return JSON.parse(readFileSync(this.path, \"utf-8\")) as CompanionRuntimeState;\n } catch {\n return null;\n }\n };\n\n readonly write = (state: CompanionRuntimeState): void => {\n mkdirSync(resolve(this.path, \"..\"), { recursive: true });\n writeFileSync(this.path, JSON.stringify(state, null, 2));\n };\n\n readonly clear = (): void => {\n if (existsSync(this.path)) {\n rmSync(this.path, { force: true });\n }\n };\n}\n\nexport const companionRuntimeStore = new CompanionRuntimeStore();\n"],"mappings":";;;;AAUA,IAAa,wBAAb,MAAmC;CACjC,IAAI,OAAe;AACjB,SAAO,QAAQ,YAAY,EAAE,OAAO,iBAAiB;;CAGvD,aAAoD;AAClD,MAAI,CAAC,WAAW,KAAK,KAAK,CACxB,QAAO;AAET,MAAI;AACF,UAAO,KAAK,MAAM,aAAa,KAAK,MAAM,QAAQ,CAAC;UAC7C;AACN,UAAO;;;CAIX,SAAkB,UAAuC;AACvD,YAAU,QAAQ,KAAK,MAAM,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACxD,gBAAc,KAAK,MAAM,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;;CAG1D,cAA6B;AAC3B,MAAI,WAAW,KAAK,KAAK,CACvB,QAAO,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC;;;AAKxC,MAAa,wBAAwB,IAAI,uBAAuB"}
1
+ {"version":3,"file":"companion-runtime.store.js","names":[],"sources":["../../../src/shared/stores/companion-runtime.store.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getRunPath } from \"@nextclaw/core\";\n\nexport type CompanionRuntimeState = {\n pid: number;\n startedAt: string;\n baseUrl: string;\n};\n\nexport class CompanionRuntimeStore {\n get path(): string {\n return resolve(getRunPath(), \"companion.json\");\n }\n\n readonly read = (): CompanionRuntimeState | null => {\n if (!existsSync(this.path)) {\n return null;\n }\n try {\n return JSON.parse(readFileSync(this.path, \"utf-8\")) as CompanionRuntimeState;\n } catch {\n return null;\n }\n };\n\n readonly write = (state: CompanionRuntimeState): void => {\n mkdirSync(resolve(this.path, \"..\"), { recursive: true });\n writeFileSync(this.path, JSON.stringify(state, null, 2));\n };\n\n readonly clear = (): void => {\n if (existsSync(this.path)) {\n rmSync(this.path, { force: true });\n }\n };\n}\n\nexport const companionRuntimeStore = new CompanionRuntimeStore();\n"],"mappings":";;;;AAUA,IAAa,wBAAb,MAAmC;CACjC,IAAI,OAAe;AACjB,SAAO,QAAQ,YAAY,EAAE,iBAAiB;;CAGhD,aAAoD;AAClD,MAAI,CAAC,WAAW,KAAK,KAAK,CACxB,QAAO;AAET,MAAI;AACF,UAAO,KAAK,MAAM,aAAa,KAAK,MAAM,QAAQ,CAAC;UAC7C;AACN,UAAO;;;CAIX,SAAkB,UAAuC;AACvD,YAAU,QAAQ,KAAK,MAAM,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACxD,gBAAc,KAAK,MAAM,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;;CAG1D,cAA6B;AAC3B,MAAI,WAAW,KAAK,KAAK,CACvB,QAAO,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC;;;AAKxC,MAAa,wBAAwB,IAAI,uBAAuB"}
@@ -1,11 +1,11 @@
1
1
  import { resolveUiApiBase } from "../utils/cli.utils.js";
2
- import { getDataDir } from "@nextclaw/core";
2
+ import { getRunPath } from "@nextclaw/core";
3
3
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { resolve } from "node:path";
5
5
  //#region src/shared/stores/local-ui-runtime.store.ts
6
6
  var LocalUiRuntimeStore = class {
7
7
  get path() {
8
- return resolve(getDataDir(), "run", "ui-runtime.json");
8
+ return resolve(getRunPath(), "ui-runtime.json");
9
9
  }
10
10
  read = () => {
11
11
  if (!existsSync(this.path)) return null;
@@ -1 +1 @@
1
- {"version":3,"file":"local-ui-runtime.store.js","names":[],"sources":["../../../src/shared/stores/local-ui-runtime.store.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getDataDir, type Config } from \"@nextclaw/core\";\nimport type { RemoteRuntimeState } from \"@nextclaw/remote\";\nimport { resolveUiApiBase } from \"../utils/cli.utils.js\";\n\nexport type LocalUiRuntimeState = {\n pid: number;\n startedAt: string;\n uiUrl: string;\n apiUrl: string;\n uiHost?: string;\n uiPort?: number;\n remote?: RemoteRuntimeState;\n};\n\nexport class LocalUiRuntimeStore {\n get path(): string {\n return resolve(getDataDir(), \"run\", \"ui-runtime.json\");\n }\n\n readonly read = (): LocalUiRuntimeState | null => {\n if (!existsSync(this.path)) {\n return null;\n }\n try {\n const raw = readFileSync(this.path, \"utf-8\");\n return JSON.parse(raw) as LocalUiRuntimeState;\n } catch {\n return null;\n }\n };\n\n readonly write = (state: LocalUiRuntimeState): void => {\n mkdirSync(resolve(this.path, \"..\"), { recursive: true });\n writeFileSync(this.path, JSON.stringify(state, null, 2));\n };\n\n readonly update = (updater: (state: LocalUiRuntimeState) => LocalUiRuntimeState): LocalUiRuntimeState | null => {\n const current = this.read();\n if (!current) {\n return null;\n }\n const next = updater(current);\n this.write(next);\n return next;\n };\n\n readonly clear = (): void => {\n if (existsSync(this.path)) {\n rmSync(this.path, { force: true });\n }\n };\n\n readonly clearIfOwnedByProcess = (pid = process.pid): void => {\n if (this.read()?.pid === pid) {\n this.clear();\n }\n };\n\n readonly writeCurrentProcess = (\n uiConfig: Pick<Config[\"ui\"], \"host\" | \"port\">,\n pid = process.pid\n ): LocalUiRuntimeState => {\n const existing = this.read();\n const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);\n const state: LocalUiRuntimeState = {\n pid,\n startedAt:\n existing?.pid === pid && typeof existing.startedAt === \"string\"\n ? existing.startedAt\n : new Date().toISOString(),\n uiUrl,\n apiUrl: `${uiUrl}/api`,\n uiHost: uiConfig.host,\n uiPort: uiConfig.port,\n ...(existing?.remote ? { remote: existing.remote } : {})\n };\n this.write(state);\n return state;\n };\n}\n\nexport const localUiRuntimeStore = new LocalUiRuntimeStore();\n"],"mappings":";;;;;AAgBA,IAAa,sBAAb,MAAiC;CAC/B,IAAI,OAAe;AACjB,SAAO,QAAQ,YAAY,EAAE,OAAO,kBAAkB;;CAGxD,aAAkD;AAChD,MAAI,CAAC,WAAW,KAAK,KAAK,CACxB,QAAO;AAET,MAAI;GACF,MAAM,MAAM,aAAa,KAAK,MAAM,QAAQ;AAC5C,UAAO,KAAK,MAAM,IAAI;UAChB;AACN,UAAO;;;CAIX,SAAkB,UAAqC;AACrD,YAAU,QAAQ,KAAK,MAAM,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACxD,gBAAc,KAAK,MAAM,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;;CAG1D,UAAmB,YAA6F;EAC9G,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,CAAC,QACH,QAAO;EAET,MAAM,OAAO,QAAQ,QAAQ;AAC7B,OAAK,MAAM,KAAK;AAChB,SAAO;;CAGT,cAA6B;AAC3B,MAAI,WAAW,KAAK,KAAK,CACvB,QAAO,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC;;CAItC,yBAAkC,MAAM,QAAQ,QAAc;AAC5D,MAAI,KAAK,MAAM,EAAE,QAAQ,IACvB,MAAK,OAAO;;CAIhB,uBACE,UACA,MAAM,QAAQ,QACU;EACxB,MAAM,WAAW,KAAK,MAAM;EAC5B,MAAM,QAAQ,iBAAiB,SAAS,MAAM,SAAS,KAAK;EAC5D,MAAM,QAA6B;GACjC;GACA,WACE,UAAU,QAAQ,OAAO,OAAO,SAAS,cAAc,WACnD,SAAS,6BACT,IAAI,MAAM,EAAC,aAAa;GAC9B;GACA,QAAQ,GAAG,MAAM;GACjB,QAAQ,SAAS;GACjB,QAAQ,SAAS;GACjB,GAAI,UAAU,SAAS,EAAE,QAAQ,SAAS,QAAQ,GAAG,EAAE;GACxD;AACD,OAAK,MAAM,MAAM;AACjB,SAAO;;;AAIX,MAAa,sBAAsB,IAAI,qBAAqB"}
1
+ {"version":3,"file":"local-ui-runtime.store.js","names":[],"sources":["../../../src/shared/stores/local-ui-runtime.store.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getRunPath, type Config } from \"@nextclaw/core\";\nimport type { RemoteRuntimeState } from \"@nextclaw/remote\";\nimport { resolveUiApiBase } from \"../utils/cli.utils.js\";\n\nexport type LocalUiRuntimeState = {\n pid: number;\n startedAt: string;\n uiUrl: string;\n apiUrl: string;\n uiHost?: string;\n uiPort?: number;\n remote?: RemoteRuntimeState;\n};\n\nexport class LocalUiRuntimeStore {\n get path(): string {\n return resolve(getRunPath(), \"ui-runtime.json\");\n }\n\n readonly read = (): LocalUiRuntimeState | null => {\n if (!existsSync(this.path)) {\n return null;\n }\n try {\n const raw = readFileSync(this.path, \"utf-8\");\n return JSON.parse(raw) as LocalUiRuntimeState;\n } catch {\n return null;\n }\n };\n\n readonly write = (state: LocalUiRuntimeState): void => {\n mkdirSync(resolve(this.path, \"..\"), { recursive: true });\n writeFileSync(this.path, JSON.stringify(state, null, 2));\n };\n\n readonly update = (updater: (state: LocalUiRuntimeState) => LocalUiRuntimeState): LocalUiRuntimeState | null => {\n const current = this.read();\n if (!current) {\n return null;\n }\n const next = updater(current);\n this.write(next);\n return next;\n };\n\n readonly clear = (): void => {\n if (existsSync(this.path)) {\n rmSync(this.path, { force: true });\n }\n };\n\n readonly clearIfOwnedByProcess = (pid = process.pid): void => {\n if (this.read()?.pid === pid) {\n this.clear();\n }\n };\n\n readonly writeCurrentProcess = (\n uiConfig: Pick<Config[\"ui\"], \"host\" | \"port\">,\n pid = process.pid\n ): LocalUiRuntimeState => {\n const existing = this.read();\n const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);\n const state: LocalUiRuntimeState = {\n pid,\n startedAt:\n existing?.pid === pid && typeof existing.startedAt === \"string\"\n ? existing.startedAt\n : new Date().toISOString(),\n uiUrl,\n apiUrl: `${uiUrl}/api`,\n uiHost: uiConfig.host,\n uiPort: uiConfig.port,\n ...(existing?.remote ? { remote: existing.remote } : {})\n };\n this.write(state);\n return state;\n };\n}\n\nexport const localUiRuntimeStore = new LocalUiRuntimeStore();\n"],"mappings":";;;;;AAgBA,IAAa,sBAAb,MAAiC;CAC/B,IAAI,OAAe;AACjB,SAAO,QAAQ,YAAY,EAAE,kBAAkB;;CAGjD,aAAkD;AAChD,MAAI,CAAC,WAAW,KAAK,KAAK,CACxB,QAAO;AAET,MAAI;GACF,MAAM,MAAM,aAAa,KAAK,MAAM,QAAQ;AAC5C,UAAO,KAAK,MAAM,IAAI;UAChB;AACN,UAAO;;;CAIX,SAAkB,UAAqC;AACrD,YAAU,QAAQ,KAAK,MAAM,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACxD,gBAAc,KAAK,MAAM,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;;CAG1D,UAAmB,YAA6F;EAC9G,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,CAAC,QACH,QAAO;EAET,MAAM,OAAO,QAAQ,QAAQ;AAC7B,OAAK,MAAM,KAAK;AAChB,SAAO;;CAGT,cAA6B;AAC3B,MAAI,WAAW,KAAK,KAAK,CACvB,QAAO,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC;;CAItC,yBAAkC,MAAM,QAAQ,QAAc;AAC5D,MAAI,KAAK,MAAM,EAAE,QAAQ,IACvB,MAAK,OAAO;;CAIhB,uBACE,UACA,MAAM,QAAQ,QACU;EACxB,MAAM,WAAW,KAAK,MAAM;EAC5B,MAAM,QAAQ,iBAAiB,SAAS,MAAM,SAAS,KAAK;EAC5D,MAAM,QAA6B;GACjC;GACA,WACE,UAAU,QAAQ,OAAO,OAAO,SAAS,cAAc,WACnD,SAAS,6BACT,IAAI,MAAM,EAAC,aAAa;GAC9B;GACA,QAAQ,GAAG,MAAM;GACjB,QAAQ,SAAS;GACjB,QAAQ,SAAS;GACjB,GAAI,UAAU,SAAS,EAAE,QAAQ,SAAS,QAAQ,GAAG,EAAE;GACxD;AACD,OAAK,MAAM,MAAM;AACjB,SAAO;;;AAIX,MAAa,sBAAsB,IAAI,qBAAqB"}
@@ -1,10 +1,10 @@
1
- import { getDataDir } from "@nextclaw/core";
1
+ import { getRunPath } from "@nextclaw/core";
2
2
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  //#region src/shared/stores/managed-service-state.store.ts
5
5
  var ManagedServiceStateStore = class {
6
6
  get path() {
7
- return resolve(getDataDir(), "run", "service.json");
7
+ return resolve(getRunPath(), "service.json");
8
8
  }
9
9
  read = () => {
10
10
  if (!existsSync(this.path)) return null;
@@ -1 +1 @@
1
- {"version":3,"file":"managed-service-state.store.js","names":[],"sources":["../../../src/shared/stores/managed-service-state.store.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getDataDir } from \"@nextclaw/core\";\nimport type { RemoteRuntimeState } from \"@nextclaw/remote\";\n\nexport type ManagedServiceLease = {\n ownerPid: number;\n heartbeatAt: string;\n heartbeatIntervalMs: number;\n ttlMs: number;\n};\n\ntype ManagedServiceExitReason =\n | \"exit\"\n | \"signal\"\n | \"uncaughtException\";\n\nexport type ManagedServiceLastExit = {\n pid: number;\n reason: ManagedServiceExitReason;\n exitedAt: string;\n code?: number | null;\n signal?: string | null;\n message?: string | null;\n};\n\nexport type ManagedServiceState = {\n pid: number;\n startedAt: string;\n uiUrl: string;\n apiUrl: string;\n uiHost?: string;\n uiPort?: number;\n logPath: string;\n startupState?: \"ready\" | \"degraded\";\n startupLastProbeError?: string | null;\n startupTimeoutMs?: number;\n startupCheckedAt?: string;\n lease?: ManagedServiceLease;\n lastExit?: ManagedServiceLastExit;\n remote?: RemoteRuntimeState;\n};\n\nexport class ManagedServiceStateStore {\n get path(): string {\n return resolve(getDataDir(), \"run\", \"service.json\");\n }\n\n readonly read = (): ManagedServiceState | null => {\n if (!existsSync(this.path)) {\n return null;\n }\n try {\n const raw = readFileSync(this.path, \"utf-8\");\n return JSON.parse(raw) as ManagedServiceState;\n } catch {\n return null;\n }\n };\n\n readonly write = (state: ManagedServiceState): void => {\n mkdirSync(resolve(this.path, \"..\"), { recursive: true });\n writeFileSync(this.path, JSON.stringify(state, null, 2));\n };\n\n readonly update = (updater: (state: ManagedServiceState) => ManagedServiceState): ManagedServiceState | null => {\n const current = this.read();\n if (!current) {\n return null;\n }\n const next = updater(current);\n this.write(next);\n return next;\n };\n\n readonly clear = (): void => {\n if (existsSync(this.path)) {\n rmSync(this.path, { force: true });\n }\n };\n\n readonly clearIfOwnedByProcess = (pid = process.pid): void => {\n if (this.read()?.pid === pid) {\n this.clear();\n }\n };\n}\n\nexport const managedServiceStateStore = new ManagedServiceStateStore();\n"],"mappings":";;;;AA2CA,IAAa,2BAAb,MAAsC;CACpC,IAAI,OAAe;AACjB,SAAO,QAAQ,YAAY,EAAE,OAAO,eAAe;;CAGrD,aAAkD;AAChD,MAAI,CAAC,WAAW,KAAK,KAAK,CACxB,QAAO;AAET,MAAI;GACF,MAAM,MAAM,aAAa,KAAK,MAAM,QAAQ;AAC5C,UAAO,KAAK,MAAM,IAAI;UAChB;AACN,UAAO;;;CAIX,SAAkB,UAAqC;AACrD,YAAU,QAAQ,KAAK,MAAM,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACxD,gBAAc,KAAK,MAAM,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;;CAG1D,UAAmB,YAA6F;EAC9G,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,CAAC,QACH,QAAO;EAET,MAAM,OAAO,QAAQ,QAAQ;AAC7B,OAAK,MAAM,KAAK;AAChB,SAAO;;CAGT,cAA6B;AAC3B,MAAI,WAAW,KAAK,KAAK,CACvB,QAAO,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC;;CAItC,yBAAkC,MAAM,QAAQ,QAAc;AAC5D,MAAI,KAAK,MAAM,EAAE,QAAQ,IACvB,MAAK,OAAO;;;AAKlB,MAAa,2BAA2B,IAAI,0BAA0B"}
1
+ {"version":3,"file":"managed-service-state.store.js","names":[],"sources":["../../../src/shared/stores/managed-service-state.store.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getRunPath } from \"@nextclaw/core\";\nimport type { RemoteRuntimeState } from \"@nextclaw/remote\";\n\nexport type ManagedServiceLease = {\n ownerPid: number;\n heartbeatAt: string;\n heartbeatIntervalMs: number;\n ttlMs: number;\n};\n\ntype ManagedServiceExitReason =\n | \"exit\"\n | \"signal\"\n | \"uncaughtException\";\n\nexport type ManagedServiceLastExit = {\n pid: number;\n reason: ManagedServiceExitReason;\n exitedAt: string;\n code?: number | null;\n signal?: string | null;\n message?: string | null;\n};\n\nexport type ManagedServiceState = {\n pid: number;\n startedAt: string;\n uiUrl: string;\n apiUrl: string;\n uiHost?: string;\n uiPort?: number;\n logPath: string;\n startupState?: \"ready\" | \"degraded\";\n startupLastProbeError?: string | null;\n startupTimeoutMs?: number;\n startupCheckedAt?: string;\n lease?: ManagedServiceLease;\n lastExit?: ManagedServiceLastExit;\n remote?: RemoteRuntimeState;\n};\n\nexport class ManagedServiceStateStore {\n get path(): string {\n return resolve(getRunPath(), \"service.json\");\n }\n\n readonly read = (): ManagedServiceState | null => {\n if (!existsSync(this.path)) {\n return null;\n }\n try {\n const raw = readFileSync(this.path, \"utf-8\");\n return JSON.parse(raw) as ManagedServiceState;\n } catch {\n return null;\n }\n };\n\n readonly write = (state: ManagedServiceState): void => {\n mkdirSync(resolve(this.path, \"..\"), { recursive: true });\n writeFileSync(this.path, JSON.stringify(state, null, 2));\n };\n\n readonly update = (updater: (state: ManagedServiceState) => ManagedServiceState): ManagedServiceState | null => {\n const current = this.read();\n if (!current) {\n return null;\n }\n const next = updater(current);\n this.write(next);\n return next;\n };\n\n readonly clear = (): void => {\n if (existsSync(this.path)) {\n rmSync(this.path, { force: true });\n }\n };\n\n readonly clearIfOwnedByProcess = (pid = process.pid): void => {\n if (this.read()?.pid === pid) {\n this.clear();\n }\n };\n}\n\nexport const managedServiceStateStore = new ManagedServiceStateStore();\n"],"mappings":";;;;AA2CA,IAAa,2BAAb,MAAsC;CACpC,IAAI,OAAe;AACjB,SAAO,QAAQ,YAAY,EAAE,eAAe;;CAG9C,aAAkD;AAChD,MAAI,CAAC,WAAW,KAAK,KAAK,CACxB,QAAO;AAET,MAAI;GACF,MAAM,MAAM,aAAa,KAAK,MAAM,QAAQ;AAC5C,UAAO,KAAK,MAAM,IAAI;UAChB;AACN,UAAO;;;CAIX,SAAkB,UAAqC;AACrD,YAAU,QAAQ,KAAK,MAAM,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACxD,gBAAc,KAAK,MAAM,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;;CAG1D,UAAmB,YAA6F;EAC9G,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,CAAC,QACH,QAAO;EAET,MAAM,OAAO,QAAQ,QAAQ;AAC7B,OAAK,MAAM,KAAK;AAChB,SAAO;;CAGT,cAA6B;AAC3B,MAAI,WAAW,KAAK,KAAK,CACvB,QAAO,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC;;CAItC,yBAAkC,MAAM,QAAQ,QAAc;AAC5D,MAAI,KAAK,MAAM,EAAE,QAAQ,IACvB,MAAK,OAAO;;;AAKlB,MAAa,2BAA2B,IAAI,0BAA0B"}
@@ -207,10 +207,6 @@ type CronAddOptions = {
207
207
  every?: string;
208
208
  cron?: string;
209
209
  at?: string;
210
- deliver?: boolean;
211
- to?: string;
212
- channel?: string;
213
- account?: string;
214
210
  };
215
211
  type StatusCommandOptions = {
216
212
  json?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"cli.types.d.ts","names":[],"sources":["../../../src/shared/types/cli.types.ts"],"mappings":"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"}
1
+ {"version":3,"file":"cli.types.d.ts","names":[],"sources":["../../../src/shared/types/cli.types.ts"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { getPackageVersion } from "./package/package-manifest.utils.js";
2
- import { createExternalCommandEnv, getLogsPath, resolveLocalUiBaseUrl } from "@nextclaw/core";
2
+ import { createExternalCommandEnv, getRuntimeLogsPath, resolveLocalUiBaseUrl } from "@nextclaw/core";
3
3
  import { existsSync } from "node:fs";
4
4
  import { spawn, spawnSync } from "node:child_process";
5
5
  import { join, resolve } from "node:path";
@@ -52,7 +52,7 @@ async function resolvePublicIp(timeoutMs = 1500) {
52
52
  return null;
53
53
  }
54
54
  function resolveServiceLogPath() {
55
- return resolve(getLogsPath(), "service.log");
55
+ return resolve(getRuntimeLogsPath(), "service.log");
56
56
  }
57
57
  function isProcessRunning(pid) {
58
58
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"cli.utils.js","names":[],"sources":["../../../src/shared/utils/cli.utils.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { isIP } from \"node:net\";\nimport type { Interface } from \"node:readline\";\nimport {\n createExternalCommandEnv,\n getLogsPath,\n resolveLocalUiBaseUrl,\n type Config\n} from \"@nextclaw/core\";\n\nexport { getPackageVersion } from \"./package/package-manifest.utils.js\";\n\nexport function resolveUiConfig(config: Config, overrides?: Partial<Config[\"ui\"]>): Config[\"ui\"] {\n const base = config.ui ?? { enabled: false, host: \"127.0.0.1\", port: 55667, open: false };\n return { ...base, ...(overrides ?? {}) };\n}\n\nexport function resolveUiApiBase(host: string, port: number): string {\n return resolveLocalUiBaseUrl({ host, port });\n}\n\nexport function isLoopbackHost(host: string): boolean {\n const normalized = host.trim().toLowerCase();\n return normalized === \"127.0.0.1\" || normalized === \"localhost\" || normalized === \"::1\";\n}\n\nconst PUBLIC_IP_CHECK_URLS = [\"https://api.ipify.org\", \"https://ifconfig.me/ip\"];\n\nasync function fetchPublicIpFrom(url: string, timeoutMs: number): Promise<string | null> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(url, {\n signal: controller.signal,\n headers: {\n Accept: \"text/plain\"\n }\n });\n if (!response.ok) {\n return null;\n }\n const text = (await response.text()).trim();\n return isIP(text) ? text : null;\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function resolvePublicIp(timeoutMs = 1500): Promise<string | null> {\n for (const endpoint of PUBLIC_IP_CHECK_URLS) {\n const candidate = await fetchPublicIpFrom(endpoint, timeoutMs);\n if (candidate) {\n return candidate;\n }\n }\n return null;\n}\n\nexport function resolveServiceLogPath(): string {\n return resolve(getLogsPath(), \"service.log\");\n}\n\nexport function isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function waitForExit(pid: number, timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (!isProcessRunning(pid)) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, 200));\n }\n return !isProcessRunning(pid);\n}\n\nexport type ListeningProcessInfo = {\n pid: number;\n command: string | null;\n};\n\ntype CommandResult = {\n ok: boolean;\n stdout: string;\n};\n\nfunction runLookupCommand(command: string, args: string[]): CommandResult {\n try {\n const result = spawnSync(command, args, {\n encoding: \"utf8\",\n env: createExternalCommandEnv(process.env)\n });\n if (result.error || result.status !== 0) {\n return {\n ok: false,\n stdout: \"\"\n };\n }\n return {\n ok: true,\n stdout: result.stdout ?? \"\"\n };\n } catch {\n return {\n ok: false,\n stdout: \"\"\n };\n }\n}\n\nfunction parseListeningPidFromLsof(raw: string): number | null {\n for (const line of raw.split(\"\\n\")) {\n if (!line.startsWith(\"p\")) {\n continue;\n }\n const pid = Number(line.slice(1));\n if (Number.isFinite(pid) && pid > 0) {\n return pid;\n }\n }\n return null;\n}\n\nfunction parseListeningPidFromNetstat(raw: string, port: number): number | null {\n const portSuffix = `:${port}`;\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || !trimmed.includes(\"LISTEN\")) {\n continue;\n }\n const columns = trimmed.split(/\\s+/);\n if (columns.length < 5) {\n continue;\n }\n const localAddress = columns[1] ?? \"\";\n if (!localAddress.endsWith(portSuffix)) {\n continue;\n }\n const pid = Number(columns[4]);\n if (Number.isFinite(pid) && pid > 0) {\n return pid;\n }\n }\n return null;\n}\n\nfunction lookupProcessCommandByPid(pid: number): string | null {\n if (!Number.isFinite(pid) || pid <= 0) {\n return null;\n }\n\n if (process.platform === \"win32\") {\n const script = `(Get-CimInstance Win32_Process -Filter \"ProcessId = ${pid}\").CommandLine`;\n const result = runLookupCommand(\"powershell\", [\"-NoProfile\", \"-Command\", script]);\n if (!result.ok) {\n return null;\n }\n const command = result.stdout.trim();\n return command.length > 0 ? command : null;\n }\n\n const result = runLookupCommand(\"ps\", [\"-p\", String(pid), \"-o\", \"command=\"]);\n if (!result.ok) {\n return null;\n }\n const command = result.stdout.trim();\n return command.length > 0 ? command : null;\n}\n\nexport function findListeningProcessByPort(port: number): ListeningProcessInfo | null {\n if (!Number.isFinite(port) || port <= 0) {\n return null;\n }\n\n let pid: number | null = null;\n if (process.platform === \"win32\") {\n const result = runLookupCommand(\"netstat\", [\"-ano\", \"-p\", \"tcp\"]);\n if (!result.ok) {\n return null;\n }\n pid = parseListeningPidFromNetstat(result.stdout, port);\n } else {\n const result = runLookupCommand(\"lsof\", [\"-nP\", `-iTCP:${port}`, \"-sTCP:LISTEN\", \"-F\", \"p\"]);\n if (!result.ok) {\n return null;\n }\n pid = parseListeningPidFromLsof(result.stdout);\n }\n\n if (!pid) {\n return null;\n }\n\n return {\n pid,\n command: lookupProcessCommandByPid(pid)\n };\n}\n\nexport function resolveUiStaticDir(packagedUiDistDir?: string | null): string | null {\n if (process.env.NEXTCLAW_DISABLE_STATIC_UI === \"1\") {\n return null;\n }\n\n const envDir = process.env.NEXTCLAW_UI_STATIC_DIR;\n if (envDir) {\n return existsSync(join(envDir, \"index.html\")) ? envDir : null;\n }\n\n if (!packagedUiDistDir) {\n return null;\n }\n return existsSync(join(packagedUiDistDir, \"index.html\")) ? packagedUiDistDir : null;\n}\n\nexport function openBrowser(url: string): boolean {\n const platform = process.platform;\n let command: string;\n let args: string[];\n if (platform === \"darwin\") {\n command = \"open\";\n args = [url];\n } else if (platform === \"win32\") {\n command = \"cmd\";\n args = [\"/c\", \"start\", \"\", url];\n } else {\n command = \"xdg-open\";\n args = [url];\n }\n if (!findExecutableOnPath(command)) {\n return false;\n }\n try {\n const child = spawn(command, args, {\n stdio: \"ignore\",\n detached: true,\n env: createExternalCommandEnv(process.env),\n windowsHide: true\n });\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n\nexport type ExecutableLookupEnv = {\n [key: string]: string | undefined;\n PATH?: string;\n Path?: string;\n path?: string;\n PATHEXT?: string;\n};\n\nfunction normalizePathEntries(rawPath: string, platform: NodeJS.Platform): string[] {\n const delimiter = platform === \"win32\" ? \";\" : \":\";\n return rawPath.split(delimiter).map((entry) => entry.trim().replace(/^\"+|\"+$/g, \"\")).filter(Boolean);\n}\n\nfunction normalizeWindowsPathExt(rawPathExt: string | undefined): string[] {\n const source = (rawPathExt && rawPathExt.trim().length > 0) ? rawPathExt : \".COM;.EXE;.BAT;.CMD\";\n const unique = new Set<string>();\n for (const ext of source.split(\";\")) {\n const trimmed = ext.trim();\n if (!trimmed) {\n continue;\n }\n const normalized = trimmed.startsWith(\".\") ? trimmed : `.${trimmed}`;\n unique.add(normalized.toUpperCase());\n }\n return [...unique];\n}\n\nfunction hasFileExtension(binary: string): boolean {\n return binary.lastIndexOf(\".\") > Math.max(binary.lastIndexOf(\"/\"), binary.lastIndexOf(\"\\\\\"));\n}\n\nexport function findExecutableOnPath(\n binary: string,\n env: ExecutableLookupEnv = process.env,\n platform: NodeJS.Platform = process.platform\n): string | null {\n const target = binary.trim();\n if (!target) {\n return null;\n }\n\n if (target.includes(\"/\") || target.includes(\"\\\\\")) {\n return existsSync(target) ? target : null;\n }\n\n const rawPath = env.PATH ?? env.Path ?? env.path ?? \"\";\n if (!rawPath.trim()) {\n return null;\n }\n\n const entries = normalizePathEntries(rawPath, platform);\n if (entries.length === 0) {\n return null;\n }\n\n for (const dir of entries) {\n const direct = join(dir, target);\n if (existsSync(direct)) {\n return direct;\n }\n\n if (platform !== \"win32\" || hasFileExtension(target)) {\n continue;\n }\n\n for (const ext of normalizeWindowsPathExt(env.PATHEXT)) {\n const withExt = join(dir, `${target}${ext}`);\n if (existsSync(withExt)) {\n return withExt;\n }\n }\n }\n\n return null;\n}\n\nexport function printAgentResponse(response: string): void {\n console.log(\"\\n\" + response + \"\\n\");\n}\n\nexport async function prompt(rl: Interface, question: string): Promise<string> {\n rl.setPrompt(question);\n rl.prompt();\n return new Promise((resolve) => {\n rl.once(\"line\", (line) => resolve(line));\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.utils.js","names":[],"sources":["../../../src/shared/utils/cli.utils.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { isIP } from \"node:net\";\nimport type { Interface } from \"node:readline\";\nimport {\n createExternalCommandEnv,\n getRuntimeLogsPath,\n resolveLocalUiBaseUrl,\n type Config\n} from \"@nextclaw/core\";\n\nexport { getPackageVersion } from \"./package/package-manifest.utils.js\";\n\nexport function resolveUiConfig(config: Config, overrides?: Partial<Config[\"ui\"]>): Config[\"ui\"] {\n const base = config.ui ?? { enabled: false, host: \"127.0.0.1\", port: 55667, open: false };\n return { ...base, ...(overrides ?? {}) };\n}\n\nexport function resolveUiApiBase(host: string, port: number): string {\n return resolveLocalUiBaseUrl({ host, port });\n}\n\nexport function isLoopbackHost(host: string): boolean {\n const normalized = host.trim().toLowerCase();\n return normalized === \"127.0.0.1\" || normalized === \"localhost\" || normalized === \"::1\";\n}\n\nconst PUBLIC_IP_CHECK_URLS = [\"https://api.ipify.org\", \"https://ifconfig.me/ip\"];\n\nasync function fetchPublicIpFrom(url: string, timeoutMs: number): Promise<string | null> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(url, {\n signal: controller.signal,\n headers: {\n Accept: \"text/plain\"\n }\n });\n if (!response.ok) {\n return null;\n }\n const text = (await response.text()).trim();\n return isIP(text) ? text : null;\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function resolvePublicIp(timeoutMs = 1500): Promise<string | null> {\n for (const endpoint of PUBLIC_IP_CHECK_URLS) {\n const candidate = await fetchPublicIpFrom(endpoint, timeoutMs);\n if (candidate) {\n return candidate;\n }\n }\n return null;\n}\n\nexport function resolveServiceLogPath(): string {\n return resolve(getRuntimeLogsPath(), \"service.log\");\n}\n\nexport function isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function waitForExit(pid: number, timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (!isProcessRunning(pid)) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, 200));\n }\n return !isProcessRunning(pid);\n}\n\nexport type ListeningProcessInfo = {\n pid: number;\n command: string | null;\n};\n\ntype CommandResult = {\n ok: boolean;\n stdout: string;\n};\n\nfunction runLookupCommand(command: string, args: string[]): CommandResult {\n try {\n const result = spawnSync(command, args, {\n encoding: \"utf8\",\n env: createExternalCommandEnv(process.env)\n });\n if (result.error || result.status !== 0) {\n return {\n ok: false,\n stdout: \"\"\n };\n }\n return {\n ok: true,\n stdout: result.stdout ?? \"\"\n };\n } catch {\n return {\n ok: false,\n stdout: \"\"\n };\n }\n}\n\nfunction parseListeningPidFromLsof(raw: string): number | null {\n for (const line of raw.split(\"\\n\")) {\n if (!line.startsWith(\"p\")) {\n continue;\n }\n const pid = Number(line.slice(1));\n if (Number.isFinite(pid) && pid > 0) {\n return pid;\n }\n }\n return null;\n}\n\nfunction parseListeningPidFromNetstat(raw: string, port: number): number | null {\n const portSuffix = `:${port}`;\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || !trimmed.includes(\"LISTEN\")) {\n continue;\n }\n const columns = trimmed.split(/\\s+/);\n if (columns.length < 5) {\n continue;\n }\n const localAddress = columns[1] ?? \"\";\n if (!localAddress.endsWith(portSuffix)) {\n continue;\n }\n const pid = Number(columns[4]);\n if (Number.isFinite(pid) && pid > 0) {\n return pid;\n }\n }\n return null;\n}\n\nfunction lookupProcessCommandByPid(pid: number): string | null {\n if (!Number.isFinite(pid) || pid <= 0) {\n return null;\n }\n\n if (process.platform === \"win32\") {\n const script = `(Get-CimInstance Win32_Process -Filter \"ProcessId = ${pid}\").CommandLine`;\n const result = runLookupCommand(\"powershell\", [\"-NoProfile\", \"-Command\", script]);\n if (!result.ok) {\n return null;\n }\n const command = result.stdout.trim();\n return command.length > 0 ? command : null;\n }\n\n const result = runLookupCommand(\"ps\", [\"-p\", String(pid), \"-o\", \"command=\"]);\n if (!result.ok) {\n return null;\n }\n const command = result.stdout.trim();\n return command.length > 0 ? command : null;\n}\n\nexport function findListeningProcessByPort(port: number): ListeningProcessInfo | null {\n if (!Number.isFinite(port) || port <= 0) {\n return null;\n }\n\n let pid: number | null = null;\n if (process.platform === \"win32\") {\n const result = runLookupCommand(\"netstat\", [\"-ano\", \"-p\", \"tcp\"]);\n if (!result.ok) {\n return null;\n }\n pid = parseListeningPidFromNetstat(result.stdout, port);\n } else {\n const result = runLookupCommand(\"lsof\", [\"-nP\", `-iTCP:${port}`, \"-sTCP:LISTEN\", \"-F\", \"p\"]);\n if (!result.ok) {\n return null;\n }\n pid = parseListeningPidFromLsof(result.stdout);\n }\n\n if (!pid) {\n return null;\n }\n\n return {\n pid,\n command: lookupProcessCommandByPid(pid)\n };\n}\n\nexport function resolveUiStaticDir(packagedUiDistDir?: string | null): string | null {\n if (process.env.NEXTCLAW_DISABLE_STATIC_UI === \"1\") {\n return null;\n }\n\n const envDir = process.env.NEXTCLAW_UI_STATIC_DIR;\n if (envDir) {\n return existsSync(join(envDir, \"index.html\")) ? envDir : null;\n }\n\n if (!packagedUiDistDir) {\n return null;\n }\n return existsSync(join(packagedUiDistDir, \"index.html\")) ? packagedUiDistDir : null;\n}\n\nexport function openBrowser(url: string): boolean {\n const platform = process.platform;\n let command: string;\n let args: string[];\n if (platform === \"darwin\") {\n command = \"open\";\n args = [url];\n } else if (platform === \"win32\") {\n command = \"cmd\";\n args = [\"/c\", \"start\", \"\", url];\n } else {\n command = \"xdg-open\";\n args = [url];\n }\n if (!findExecutableOnPath(command)) {\n return false;\n }\n try {\n const child = spawn(command, args, {\n stdio: \"ignore\",\n detached: true,\n env: createExternalCommandEnv(process.env),\n windowsHide: true\n });\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n\nexport type ExecutableLookupEnv = {\n [key: string]: string | undefined;\n PATH?: string;\n Path?: string;\n path?: string;\n PATHEXT?: string;\n};\n\nfunction normalizePathEntries(rawPath: string, platform: NodeJS.Platform): string[] {\n const delimiter = platform === \"win32\" ? \";\" : \":\";\n return rawPath.split(delimiter).map((entry) => entry.trim().replace(/^\"+|\"+$/g, \"\")).filter(Boolean);\n}\n\nfunction normalizeWindowsPathExt(rawPathExt: string | undefined): string[] {\n const source = (rawPathExt && rawPathExt.trim().length > 0) ? rawPathExt : \".COM;.EXE;.BAT;.CMD\";\n const unique = new Set<string>();\n for (const ext of source.split(\";\")) {\n const trimmed = ext.trim();\n if (!trimmed) {\n continue;\n }\n const normalized = trimmed.startsWith(\".\") ? trimmed : `.${trimmed}`;\n unique.add(normalized.toUpperCase());\n }\n return [...unique];\n}\n\nfunction hasFileExtension(binary: string): boolean {\n return binary.lastIndexOf(\".\") > Math.max(binary.lastIndexOf(\"/\"), binary.lastIndexOf(\"\\\\\"));\n}\n\nexport function findExecutableOnPath(\n binary: string,\n env: ExecutableLookupEnv = process.env,\n platform: NodeJS.Platform = process.platform\n): string | null {\n const target = binary.trim();\n if (!target) {\n return null;\n }\n\n if (target.includes(\"/\") || target.includes(\"\\\\\")) {\n return existsSync(target) ? target : null;\n }\n\n const rawPath = env.PATH ?? env.Path ?? env.path ?? \"\";\n if (!rawPath.trim()) {\n return null;\n }\n\n const entries = normalizePathEntries(rawPath, platform);\n if (entries.length === 0) {\n return null;\n }\n\n for (const dir of entries) {\n const direct = join(dir, target);\n if (existsSync(direct)) {\n return direct;\n }\n\n if (platform !== \"win32\" || hasFileExtension(target)) {\n continue;\n }\n\n for (const ext of normalizeWindowsPathExt(env.PATHEXT)) {\n const withExt = join(dir, `${target}${ext}`);\n if (existsSync(withExt)) {\n return withExt;\n }\n }\n }\n\n return null;\n}\n\nexport function printAgentResponse(response: string): void {\n console.log(\"\\n\" + response + \"\\n\");\n}\n\nexport async function prompt(rl: Interface, question: string): Promise<string> {\n rl.setPrompt(question);\n rl.prompt();\n return new Promise((resolve) => {\n rl.once(\"line\", (line) => resolve(line));\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region src/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.d.ts
2
+ declare function readPanelAppClientSdkScript(): Promise<string>;
3
+ //#endregion
4
+ export { readPanelAppClientSdkScript };
5
+ //# sourceMappingURL=panel-app-client-sdk-script.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-app-client-sdk-script.utils.d.ts","names":[],"sources":["../../../../src/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.ts"],"mappings":";iBAUgB,2BAAA,CAAA,GAA+B,OAAA"}
@@ -0,0 +1,29 @@
1
+ import { createRequire } from "node:module";
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { readFile } from "node:fs/promises";
5
+ //#region src/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.ts
6
+ const require = createRequire(import.meta.url);
7
+ const CLIENT_SDK_BROWSER_BUNDLE = join("browser", "browser-global-registration.utils.iife.js");
8
+ let cachedScript = null;
9
+ function readPanelAppClientSdkScript() {
10
+ cachedScript ??= readFile(resolvePanelAppClientSdkScriptPath(), "utf8");
11
+ return cachedScript;
12
+ }
13
+ function resolvePanelAppClientSdkScriptPath() {
14
+ const bundlePath = join(resolveClientSdkPackageRoot(), "dist", CLIENT_SDK_BROWSER_BUNDLE);
15
+ if (!existsSync(bundlePath)) throw new Error(`Panel App client SDK browser bundle is missing at ${bundlePath}. Run @nextclaw/client-sdk build first.`);
16
+ return bundlePath;
17
+ }
18
+ function resolveClientSdkPackageRoot() {
19
+ let current = dirname(require.resolve("@nextclaw/client-sdk"));
20
+ while (current !== dirname(current)) {
21
+ if (existsSync(join(current, "package.json"))) return current;
22
+ current = dirname(current);
23
+ }
24
+ throw new Error("Unable to resolve @nextclaw/client-sdk package root.");
25
+ }
26
+ //#endregion
27
+ export { readPanelAppClientSdkScript };
28
+
29
+ //# sourceMappingURL=panel-app-client-sdk-script.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-app-client-sdk-script.utils.js","names":[],"sources":["../../../../src/shared/utils/panel-app-client-sdk/panel-app-client-sdk-script.utils.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\n\nconst require = createRequire(import.meta.url);\nconst CLIENT_SDK_BROWSER_BUNDLE = join(\"browser\", \"browser-global-registration.utils.iife.js\");\n\nlet cachedScript: Promise<string> | null = null;\n\nexport function readPanelAppClientSdkScript(): Promise<string> {\n cachedScript ??= readFile(resolvePanelAppClientSdkScriptPath(), \"utf8\");\n return cachedScript;\n}\n\nfunction resolvePanelAppClientSdkScriptPath(): string {\n const packageRoot = resolveClientSdkPackageRoot();\n const bundlePath = join(packageRoot, \"dist\", CLIENT_SDK_BROWSER_BUNDLE);\n if (!existsSync(bundlePath)) {\n throw new Error(\n `Panel App client SDK browser bundle is missing at ${bundlePath}. Run @nextclaw/client-sdk build first.`,\n );\n }\n return bundlePath;\n}\n\nfunction resolveClientSdkPackageRoot(): string {\n let current = dirname(require.resolve(\"@nextclaw/client-sdk\"));\n while (current !== dirname(current)) {\n if (existsSync(join(current, \"package.json\"))) {\n return current;\n }\n current = dirname(current);\n }\n throw new Error(\"Unable to resolve @nextclaw/client-sdk package root.\");\n}\n"],"mappings":";;;;;AAKA,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;AAC9C,MAAM,4BAA4B,KAAK,WAAW,4CAA4C;AAE9F,IAAI,eAAuC;AAE3C,SAAgB,8BAA+C;AAC7D,kBAAiB,SAAS,oCAAoC,EAAE,OAAO;AACvE,QAAO;;AAGT,SAAS,qCAA6C;CAEpD,MAAM,aAAa,KADC,6BAA6B,EACZ,QAAQ,0BAA0B;AACvE,KAAI,CAAC,WAAW,WAAW,CACzB,OAAM,IAAI,MACR,qDAAqD,WAAW,yCACjE;AAEH,QAAO;;AAGT,SAAS,8BAAsC;CAC7C,IAAI,UAAU,QAAQ,QAAQ,QAAQ,uBAAuB,CAAC;AAC9D,QAAO,YAAY,QAAQ,QAAQ,EAAE;AACnC,MAAI,WAAW,KAAK,SAAS,eAAe,CAAC,CAC3C,QAAO;AAET,YAAU,QAAQ,QAAQ;;AAE5B,OAAM,IAAI,MAAM,uDAAuD"}
@@ -1,4 +1,4 @@
1
- import { getDataDir } from "@nextclaw/core";
1
+ import { getRunPath } from "@nextclaw/core";
2
2
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  //#region src/shared/utils/restart/restart-sentinel.utils.ts
@@ -17,7 +17,7 @@ function normalizeLine(value, maxChars) {
17
17
  return trimmed ? trimmed : null;
18
18
  }
19
19
  function resolveRestartSentinelPath() {
20
- return resolve(getDataDir(), "run", RESTART_SENTINEL_FILENAME);
20
+ return resolve(getRunPath(), RESTART_SENTINEL_FILENAME);
21
21
  }
22
22
  async function writeRestartSentinel(payload) {
23
23
  const path = resolveRestartSentinelPath();
@@ -1 +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"}
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 { getRunPath } 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(getRunPath(), 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,0BAA0B;;AAGzD,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.2.8",
3
+ "version": "0.2.10-beta.0",
4
4
  "private": false,
5
5
  "description": "NextClaw long-running service host and runtime lifecycle.",
6
6
  "type": "module",
@@ -42,30 +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.1.12",
46
- "@nextclaw/channel-extension-discord": "0.1.12",
47
- "@nextclaw/channel-extension-feishu": "0.1.19",
48
- "@nextclaw/channel-extension-slack": "0.1.12",
49
- "@nextclaw/channel-extension-wecom": "0.1.12",
50
- "@nextclaw/channel-extension-email": "0.1.12",
51
- "@nextclaw/channel-extension-qq": "0.1.16",
52
- "@nextclaw/channel-extension-weixin": "0.1.23",
53
- "@nextclaw/ncp": "0.5.27",
54
- "@nextclaw/mcp": "0.2.8",
55
- "@nextclaw/ncp-agent-runtime": "0.3.38",
56
- "@nextclaw/kernel": "0.3.2",
57
- "@nextclaw/ncp-mcp": "0.1.103",
58
- "@nextclaw/ncp-toolkit": "0.5.32",
59
- "@nextclaw/nextclaw-ncp-runtime-http-client": "0.2.7",
60
- "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.2.7",
61
- "@nextclaw/nextclaw-hermes-acp-bridge": "0.2.7",
62
- "@nextclaw/runtime": "0.3.8",
63
- "@nextclaw/remote": "0.2.8",
64
- "@nextclaw/server": "0.13.8",
65
- "@nextclaw/channel-extension-whatsapp": "0.1.12",
66
- "@nextclaw/channel-extension-telegram": "0.1.12",
67
- "@nextclaw/core": "0.13.8",
68
- "@nextclaw/shared": "0.2.7"
45
+ "@nextclaw/channel-extension-dingtalk": "0.1.14-beta.0",
46
+ "@nextclaw/channel-extension-discord": "0.1.14-beta.0",
47
+ "@nextclaw/channel-extension-email": "0.1.14-beta.0",
48
+ "@nextclaw/channel-extension-qq": "0.1.18-beta.0",
49
+ "@nextclaw/channel-extension-feishu": "0.1.21-beta.0",
50
+ "@nextclaw/channel-extension-slack": "0.1.14-beta.0",
51
+ "@nextclaw/channel-extension-telegram": "0.1.14-beta.0",
52
+ "@nextclaw/channel-extension-wecom": "0.1.14-beta.0",
53
+ "@nextclaw/channel-extension-weixin": "0.1.25-beta.0",
54
+ "@nextclaw/channel-extension-whatsapp": "0.1.14-beta.0",
55
+ "@nextclaw/core": "0.13.10-beta.0",
56
+ "@nextclaw/client-sdk": "0.2.10-beta.0",
57
+ "@nextclaw/kernel": "0.3.4-beta.0",
58
+ "@nextclaw/ncp": "0.5.29-beta.0",
59
+ "@nextclaw/mcp": "0.2.10-beta.0",
60
+ "@nextclaw/ncp-agent-runtime": "0.3.40-beta.0",
61
+ "@nextclaw/ncp-mcp": "0.1.105-beta.0",
62
+ "@nextclaw/ncp-toolkit": "0.5.34-beta.0",
63
+ "@nextclaw/nextclaw-hermes-acp-bridge": "0.2.9-beta.0",
64
+ "@nextclaw/nextclaw-ncp-runtime-http-client": "0.2.9-beta.0",
65
+ "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.2.9-beta.0",
66
+ "@nextclaw/remote": "0.2.10-beta.0",
67
+ "@nextclaw/shared": "0.2.9-beta.0",
68
+ "@nextclaw/server": "0.13.10-beta.0",
69
+ "@nextclaw/runtime": "0.3.10-beta.0"
69
70
  },
70
71
  "devDependencies": {
71
72
  "@types/node": "^20.17.6",