@nextclaw/kernel 0.1.9 → 0.1.11

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.d.ts CHANGED
@@ -246,11 +246,13 @@ declare class SessionRunManager {
246
246
  deleteActiveSessionRun: (sessionId: string, runId: string) => void;
247
247
  streamSessionEvents: (payload: NcpStreamRequestPayload, options?: NcpAgentRunStreamOptions) => AsyncIterable<NcpEndpointEvent>;
248
248
  updateToolCallResult: UpdateToolCallResult;
249
+ patchSessionMetadata: (sessionId: string, patcher: (metadata: Record<string, unknown>) => Record<string, unknown> | null) => Promise<boolean>;
249
250
  appendSessionEvent: (sessionId: string, event: NcpEndpointEvent, options?: PublishSessionEventOptions) => Promise<void>;
250
251
  private readonly ensureLiveSession;
251
252
  private readonly requireLiveSession;
252
253
  private readonly publishSessionEvent;
253
254
  private readonly persistLiveSessionEvent;
255
+ private readonly persistSessionMetadata;
254
256
  private readonly assertNotDisposed;
255
257
  private publishSessionRunStatus;
256
258
  }
package/dist/index.js CHANGED
@@ -2693,6 +2693,18 @@ var SessionRunManager = class {
2693
2693
  });
2694
2694
  await this.onSessionUpdated(normalizedSessionId);
2695
2695
  };
2696
+ patchSessionMetadata = async (sessionId, patcher) => {
2697
+ this.assertNotDisposed();
2698
+ const normalizedSessionId = sessionId.trim();
2699
+ if (!normalizedSessionId) return false;
2700
+ const liveSession = this.liveSessions.get(normalizedSessionId) ?? null;
2701
+ const storedSession = liveSession ? null : await this.ncpAgentSessionStore.getSession(normalizedSessionId);
2702
+ if (!liveSession && !storedSession) return false;
2703
+ const nextMetadata = patcher(structuredClone(liveSession?.metadata ?? storedSession?.metadata ?? {}));
2704
+ if (!nextMetadata) return false;
2705
+ if (liveSession) liveSession.metadata = structuredClone(nextMetadata);
2706
+ return await this.persistSessionMetadata(normalizedSessionId, nextMetadata);
2707
+ };
2696
2708
  appendSessionEvent = async (sessionId, event, options = {}) => {
2697
2709
  await this.publishSessionEvent(this.requireLiveSession(sessionId), event, options);
2698
2710
  };
@@ -2731,7 +2743,14 @@ var SessionRunManager = class {
2731
2743
  stateManager,
2732
2744
  sessionMetadata: metadata,
2733
2745
  setSessionMetadata: (nextMetadata) => {
2734
- session.metadata = structuredClone(nextMetadata);
2746
+ session.metadata = {
2747
+ ...session.metadata,
2748
+ ...structuredClone(nextMetadata)
2749
+ };
2750
+ this.persistSessionMetadata(session.sessionId, session.metadata).catch((error) => {
2751
+ const message = error instanceof Error ? error.stack ?? error.message : String(error);
2752
+ console.error(`[session-run] failed to persist runtime metadata for ${session.sessionId}: ${message}`);
2753
+ });
2735
2754
  }
2736
2755
  });
2737
2756
  this.liveSessions.set(sessionId, session);
@@ -2755,13 +2774,14 @@ var SessionRunManager = class {
2755
2774
  persistLiveSessionEvent = async (session, event) => {
2756
2775
  const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2757
2776
  if (this.ncpAgentSessionStore.appendSessionEvent) {
2777
+ const storedSession = await this.ncpAgentSessionStore.getSession(session.sessionId);
2758
2778
  await this.ncpAgentSessionStore.appendSessionEvent({
2759
2779
  session: {
2760
2780
  sessionId: session.sessionId,
2761
2781
  ...session.agentId ? { agentId: session.agentId } : {},
2762
2782
  createdAt: session.createdAt,
2763
2783
  updatedAt,
2764
- metadata: structuredClone(session.metadata)
2784
+ metadata: storedSession ? {} : structuredClone(session.metadata)
2765
2785
  },
2766
2786
  event,
2767
2787
  updatedAt
@@ -2770,6 +2790,13 @@ var SessionRunManager = class {
2770
2790
  }
2771
2791
  await this.ncpAgentSessionStore.saveSession(buildSessionRecord(session, updatedAt));
2772
2792
  };
2793
+ persistSessionMetadata = async (sessionId, metadata) => {
2794
+ return await this.ncpAgentSessionStore.updateSessionMetadata({
2795
+ sessionId,
2796
+ metadata: structuredClone(metadata),
2797
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2798
+ });
2799
+ };
2773
2800
  assertNotDisposed = () => {
2774
2801
  if (this.disposed) throw new Error("Session run manager has already been disposed.");
2775
2802
  };
@@ -5335,25 +5362,25 @@ function toAssetPayload(record, contentBasePath) {
5335
5362
  }
5336
5363
  var AssetPutTool = class {
5337
5364
  name = "asset_put";
5338
- description = "Put a normal file path or base64 bytes into the managed asset store.";
5365
+ description = "Publish a file to the user as a chat/channel attachment with preview and download support.";
5339
5366
  parameters = {
5340
5367
  type: "object",
5341
5368
  properties: {
5342
5369
  path: {
5343
5370
  type: "string",
5344
- description: "Existing local file path to put into the asset store."
5371
+ description: "Existing local file path to publish to the user as an attachment."
5345
5372
  },
5346
5373
  bytesBase64: {
5347
5374
  type: "string",
5348
- description: "Base64 file bytes. Use together with fileName when no source path exists."
5375
+ description: "Base64 file bytes to publish when no source path exists. Use with fileName."
5349
5376
  },
5350
5377
  fileName: {
5351
5378
  type: "string",
5352
- description: "Optional asset file name override. Required when using bytesBase64."
5379
+ description: "Optional display/download file name. Required when using bytesBase64."
5353
5380
  },
5354
5381
  mimeType: {
5355
5382
  type: "string",
5356
- description: "Optional mime type override."
5383
+ description: "Optional MIME type override for preview and download rendering."
5357
5384
  }
5358
5385
  },
5359
5386
  additionalProperties: false
@@ -5917,7 +5944,6 @@ function writeSessionActivityPreviewMetadata(metadata, projection) {
5917
5944
  //#region src/contributions/session-activity-preview/index.ts
5918
5945
  var SessionActivityPreviewContribution = class {
5919
5946
  unsubscribeNcpEvent = null;
5920
- previewWriteChains = /* @__PURE__ */ new Map();
5921
5947
  constructor(kernel) {
5922
5948
  this.kernel = kernel;
5923
5949
  }
@@ -5932,26 +5958,13 @@ var SessionActivityPreviewContribution = class {
5932
5958
  dispose = () => {
5933
5959
  this.unsubscribeNcpEvent?.();
5934
5960
  this.unsubscribeNcpEvent = null;
5935
- this.previewWriteChains.clear();
5936
5961
  };
5937
5962
  updatePreview = (projection) => {
5938
- const next = (this.previewWriteChains.get(projection.sessionId) ?? Promise.resolve()).catch(() => void 0).then(() => this.persistPreview(projection));
5939
- this.previewWriteChains.set(projection.sessionId, next);
5940
- next.catch((error) => {
5963
+ this.kernel.sessionRunManager.patchSessionMetadata(projection.sessionId, (metadata) => writeSessionActivityPreviewMetadata(metadata, projection)).catch((error) => {
5941
5964
  const message = error instanceof Error ? error.stack ?? error.message : String(error);
5942
5965
  console.error(`[session-activity-preview] failed to update ${projection.sessionId}: ${message}`);
5943
- }).finally(() => {
5944
- if (this.previewWriteChains.get(projection.sessionId) === next) this.previewWriteChains.delete(projection.sessionId);
5945
5966
  });
5946
5967
  };
5947
- persistPreview = async (projection) => {
5948
- if (!this.unsubscribeNcpEvent) return;
5949
- const summary = await this.kernel.ncpSessionApi.getSession(projection.sessionId);
5950
- if (!summary || !this.unsubscribeNcpEvent) return;
5951
- const nextMetadata = writeSessionActivityPreviewMetadata(summary.metadata && typeof summary.metadata === "object" && !Array.isArray(summary.metadata) ? summary.metadata : void 0, projection);
5952
- if (!nextMetadata) return;
5953
- await this.kernel.ncpSessionApi.updateSession(projection.sessionId, { metadata: nextMetadata });
5954
- };
5955
5968
  };
5956
5969
  //#endregion
5957
5970
  //#region src/tools/session-request.tools.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/kernel",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "private": false,
5
5
  "description": "NextClaw product kernel skeleton for agents, tasks, sessions, context, tools, skills, providers, automation, and channels.",
6
6
  "type": "module",
@@ -21,19 +21,19 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "yaml": "^2.8.1",
24
- "@nextclaw/channel-extension-feishu": "0.1.4",
25
- "@nextclaw/core": "0.12.20",
26
- "@nextclaw/channel-extension-weixin": "0.1.7",
27
- "@nextclaw/mcp": "0.1.85",
28
- "@nextclaw/ncp-agent-runtime": "0.3.23",
29
- "@nextclaw/ncp-mcp": "0.1.87",
30
- "@nextclaw/ncp-toolkit": "0.5.18",
31
- "@nextclaw/nextclaw-ncp-runtime-http-client": "0.1.12",
32
- "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.1.13",
33
- "@nextclaw/openclaw-compat": "1.0.20",
34
- "@nextclaw/runtime": "0.2.52",
35
- "@nextclaw/shared": "0.1.7",
36
- "@nextclaw/ncp": "0.5.13"
24
+ "@nextclaw/channel-extension-feishu": "0.1.5",
25
+ "@nextclaw/channel-extension-weixin": "0.1.8",
26
+ "@nextclaw/core": "0.12.21",
27
+ "@nextclaw/mcp": "0.1.86",
28
+ "@nextclaw/ncp-agent-runtime": "0.3.25",
29
+ "@nextclaw/ncp-mcp": "0.1.88",
30
+ "@nextclaw/ncp-toolkit": "0.5.19",
31
+ "@nextclaw/nextclaw-ncp-runtime-http-client": "0.1.13",
32
+ "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.1.14",
33
+ "@nextclaw/openclaw-compat": "1.0.21",
34
+ "@nextclaw/runtime": "0.2.53",
35
+ "@nextclaw/ncp": "0.5.14",
36
+ "@nextclaw/shared": "0.1.8"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^20.17.6",