@nextclaw/kernel 0.6.23 → 0.6.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import { CHAT_CONTINUATION_TARGET_MESSAGE_METADATA_KEY, CHAT_CONVERSATION_EXCERP
7
7
  import { LocalAssetStore, buildAssetContentPath, buildNcpUserContent, buildOpenAiFunctionTool, ncpMessageToOpenAiMessages, validateToolArgs } from "@nextclaw/ncp-agent-runtime";
8
8
  import { createHash, createHmac, randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
9
9
  import { catchError, filter, from, lastValueFrom, tap } from "rxjs";
10
- import { appendFileSync, chmodSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
10
+ import { appendFileSync, chmodSync, constants, createReadStream, existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
11
11
  import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
12
12
  import { execFileSync, spawn } from "node:child_process";
13
13
  import { access, appendFile, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
@@ -17,6 +17,7 @@ import { McpRegistryService, McpServerLifecycleManager } from "@nextclaw/mcp";
17
17
  import { McpNcpToolRegistryAdapter } from "@nextclaw/ncp-mcp";
18
18
  import { DefaultNcpAgentConversationStateManager, insertMessageByTimeline } from "@nextclaw/ncp-toolkit";
19
19
  import { parse } from "yaml";
20
+ import { createInterface } from "node:readline";
20
21
  import { HttpRuntimeConfigResolver, HttpRuntimeNcpAgentRuntime } from "@nextclaw/nextclaw-ncp-runtime-http-client";
21
22
  import { StdioRuntimeConfigResolver, StdioRuntimeNcpAgentRuntime, probeStdioRuntime } from "@nextclaw/nextclaw-ncp-runtime-stdio-client";
22
23
  import { DefaultNcpAgentRuntime } from "@nextclaw/ncp-agent-runtime-next";
@@ -2901,9 +2902,9 @@ var ConfigManager = class {
2901
2902
  required: true,
2902
2903
  automatic: false,
2903
2904
  changedPaths: [...plan.restartRequired],
2904
- message: `Config saved. Restart manually to apply: ${plan.restartRequired.join(", ")}.`
2905
+ message: `Config saved. Run nextclaw restart in an external terminal to apply: ${plan.restartRequired.join(", ")}.`
2905
2906
  } : null;
2906
- const message = changedPaths.length === 0 ? "Config already matched the requested state." : pendingRestart ? changedPaths.length > plan.restartRequired.length ? "Config saved. Supported changes were applied immediately; restart manually to apply the rest." : "Config saved. Restart manually to apply changes." : "Config saved and applied.";
2907
+ const message = changedPaths.length === 0 ? "Config already matched the requested state." : pendingRestart ? changedPaths.length > plan.restartRequired.length ? "Config saved. Supported changes were applied immediately; run nextclaw restart in an external terminal to apply the rest." : "Config saved. Run nextclaw restart in an external terminal to apply changes." : "Config saved and applied.";
2907
2908
  return {
2908
2909
  ok: true,
2909
2910
  note: note ?? null,
@@ -9639,23 +9640,61 @@ function resolveAgentHandoffDepth(metadata) {
9639
9640
  }
9640
9641
  //#endregion
9641
9642
  //#region src/utils/ncp-agent-unfinished-run.utils.ts
9642
- function readUnfinishedNcpAgentRun(sessionId, events) {
9643
- let activeRun = null;
9644
- for (const event of events) {
9645
- if (event.type === NcpEventType.RunStarted) {
9646
- activeRun = {
9647
- sessionId,
9648
- ...event.payload.messageId ? { messageId: event.payload.messageId } : {},
9649
- ...event.payload.runId ? { runId: event.payload.runId } : {},
9650
- ...event.payload.startedAt ? { startedAt: event.payload.startedAt } : {}
9651
- };
9652
- continue;
9653
- }
9654
- if (activeRun && (event.type === NcpEventType.RunFinished || event.type === NcpEventType.RunError || event.type === NcpEventType.MessageAbort) && (!event.payload.runId || !activeRun.runId || event.payload.runId === activeRun.runId)) activeRun = null;
9655
- }
9643
+ function applyNcpAgentRunLifecycleEvent(sessionId, activeRun, event) {
9644
+ if (event.type === NcpEventType.RunStarted) return {
9645
+ sessionId,
9646
+ ...event.payload.messageId ? { messageId: event.payload.messageId } : {},
9647
+ ...event.payload.runId ? { runId: event.payload.runId } : {},
9648
+ ...event.payload.startedAt ? { startedAt: event.payload.startedAt } : {}
9649
+ };
9650
+ if (activeRun && (event.type === NcpEventType.RunFinished || event.type === NcpEventType.RunError || event.type === NcpEventType.MessageAbort) && (!event.payload.runId || !activeRun.runId || event.payload.runId === activeRun.runId)) return null;
9656
9651
  return activeRun;
9657
9652
  }
9658
9653
  //#endregion
9654
+ //#region src/stores/ncp-agent-unfinished-run.store.ts
9655
+ var NcpAgentUnfinishedRunStore = class {
9656
+ constructor(journalDir, listSessionIds) {
9657
+ this.journalDir = journalDir;
9658
+ this.listSessionIds = listSessionIds;
9659
+ }
9660
+ list = async () => {
9661
+ const runs = [];
9662
+ for (const sessionId of await this.listSessionIds()) {
9663
+ const run = await this.read(sessionId);
9664
+ if (run) runs.push(run);
9665
+ }
9666
+ return runs;
9667
+ };
9668
+ read = async (sessionId) => {
9669
+ const input = createReadStream(this.sessionPath(sessionId), { encoding: "utf-8" });
9670
+ const lines = createInterface({
9671
+ input,
9672
+ crlfDelay: Infinity
9673
+ });
9674
+ let activeRun = null;
9675
+ try {
9676
+ for await (const line of lines) {
9677
+ if (!line.trim()) continue;
9678
+ let parsed;
9679
+ try {
9680
+ parsed = JSON.parse(line);
9681
+ } catch {
9682
+ continue;
9683
+ }
9684
+ if (!isRecord$12(parsed) || parsed._type !== "event" || !isRecord$12(parsed.event)) continue;
9685
+ activeRun = applyNcpAgentRunLifecycleEvent(sessionId, activeRun, parsed.event);
9686
+ }
9687
+ return activeRun;
9688
+ } catch {
9689
+ return null;
9690
+ } finally {
9691
+ lines.close();
9692
+ input.destroy();
9693
+ }
9694
+ };
9695
+ sessionPath = (sessionId) => join(this.journalDir, `${safeNcpSessionFilename(sessionId.replace(/:/g, "_"))}.jsonl`);
9696
+ };
9697
+ //#endregion
9659
9698
  //#region src/utils/ncp-agent-session-journal-entry.utils.ts
9660
9699
  function isNcpAgentSessionMessageProjectionBoundaryEvent(event) {
9661
9700
  return event.type === NcpEventType.MessageSent || event.type === NcpEventType.MessageCompleted || event.type === NcpEventType.MessageAbort || event.type === NcpEventType.RunFinished || event.type === NcpEventType.RunError || event.type === "session.snapshot.message";
@@ -9740,25 +9779,6 @@ function parseNcpAgentSessionJournal(raw) {
9740
9779
  return parser.finish();
9741
9780
  }
9742
9781
  //#endregion
9743
- //#region src/stores/ncp-agent-unfinished-run.store.ts
9744
- var NcpAgentUnfinishedRunStore = class {
9745
- constructor(journalDir, listSessionIds) {
9746
- this.journalDir = journalDir;
9747
- this.listSessionIds = listSessionIds;
9748
- }
9749
- list = async () => {
9750
- return (await Promise.all((await this.listSessionIds()).map(this.read))).filter((run) => run !== null);
9751
- };
9752
- read = async (sessionId) => {
9753
- try {
9754
- return readUnfinishedNcpAgentRun(sessionId, parseNcpAgentSessionJournal(await readFile(this.sessionPath(sessionId), "utf-8")).events);
9755
- } catch {
9756
- return null;
9757
- }
9758
- };
9759
- sessionPath = (sessionId) => join(this.journalDir, `${safeNcpSessionFilename(sessionId.replace(/:/g, "_"))}.jsonl`);
9760
- };
9761
- //#endregion
9762
9782
  //#region src/stores/ncp-agent-session-metadata.store.ts
9763
9783
  var NcpAgentSessionMetadataStore = class {
9764
9784
  constructor(journalDir) {
@@ -12051,23 +12071,24 @@ const createCliQuickReferenceContextProvider = () => {
12051
12071
  return staticBlock([
12052
12072
  `## ${APP_NAME} CLI Quick Reference`,
12053
12073
  `${APP_NAME} is controlled via subcommands. Do not invent commands.`,
12054
- "To manage the Gateway daemon service (start/stop/restart):",
12055
- `- ${appLower} gateway status`,
12056
- `- ${appLower} gateway start`,
12057
- `- ${appLower} gateway stop`,
12058
- `- ${appLower} gateway restart`,
12059
- `If unsure, ask the user to run \`${appLower} help\` (or \`${appLower} gateway --help\`) and paste the output.`
12074
+ "To manage the background service:",
12075
+ `- ${appLower} status`,
12076
+ `- ${appLower} start`,
12077
+ `- ${appLower} restart`,
12078
+ `- ${appLower} stop`,
12079
+ `The \`${appLower} gateway\` command starts a foreground gateway; it has no lifecycle subcommands.`,
12080
+ `If unsure, ask the user to run \`${appLower} help\` and paste the output.`
12060
12081
  ]);
12061
12082
  };
12062
12083
  const createSelfUpdateContextProvider = () => staticBlock([
12063
12084
  `## ${APP_NAME} Self-Update`,
12064
12085
  "Get Updates (self-update) is ONLY allowed when the user explicitly asks for it.",
12065
12086
  "Do not run config.apply or update.run unless the user explicitly requests an update or config change; if it's not explicit, ask first.",
12066
- "Actions: config.get, config.schema, config.apply (validate + write full config, then restart), config.patch (merge + restart), update.run (update deps or git, then restart).",
12087
+ "Actions: config.get, config.schema, config.apply (validate + write full config), config.patch (merge config), update.run (update the runtime and relaunch the service).",
12067
12088
  "When patching config, copy enum values exactly from config.schema; never invent new variants.",
12068
12089
  "session.dmScope legal values are exactly: main | per-peer | per-channel-peer | per-account-channel-peer.",
12069
12090
  "If an enum/path is uncertain, stop and call config.schema first; do not guess.",
12070
- `After restart, ${APP_NAME} pings the last active session automatically.`
12091
+ `If a config change requires restart, tell the user to run \`${APP_NAME.toLowerCase()} restart\` in an external terminal. Do not run it from the active agent session.`
12071
12092
  ]);
12072
12093
  const createReplyTagsContextProvider = () => staticBlock([
12073
12094
  "## Reply Tags",