adp-openclaw 0.0.55 → 0.0.56

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/monitor.ts +59 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adp-openclaw",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "description": "ADP-OpenClaw demo channel plugin (Go WebSocket backend)",
5
5
  "type": "module",
6
6
  "dependencies": {
package/src/monitor.ts CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  formatUploadResultAsMarkdown,
24
24
  } from "./tool-result-message-blocks.js";
25
25
  import crypto from "crypto";
26
+ import fs from "fs";
26
27
  // @ts-ignore - import JSON file
27
28
  import packageJson from "../package.json" with { type: "json" };
28
29
 
@@ -116,6 +117,53 @@ function generateRequestId(): string {
116
117
  return `req-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
117
118
  }
118
119
 
120
+ /**
121
+ * Mark a session's abortedLastRun flag in the sessions store.
122
+ * This tells the SDK to inject an "abort hint" on the next message,
123
+ * preventing the AI from resuming the cancelled task.
124
+ */
125
+ async function markSessionAborted(params: {
126
+ sessionKey: string;
127
+ runtime: ReturnType<typeof getAdpOpenclawRuntime>;
128
+ cfg?: ClawdbotConfig;
129
+ log?: PluginLogger;
130
+ }): Promise<void> {
131
+ const { sessionKey, runtime, cfg, log } = params;
132
+ try {
133
+ // Use SDK's resolveStorePath to find the sessions.json location
134
+ const storePath = runtime.channel.session.resolveStorePath(cfg?.session?.store);
135
+ if (!storePath || !fs.existsSync(storePath)) {
136
+ log?.warn?.(`[adp-openclaw] Cannot mark session aborted: store not found at ${storePath}`);
137
+ return;
138
+ }
139
+
140
+ const raw = fs.readFileSync(storePath, "utf-8");
141
+ const store = JSON.parse(raw) as Record<string, { abortedLastRun?: boolean; updatedAt?: number; [key: string]: unknown }>;
142
+
143
+ // Try both the raw sessionKey and the "agent:main:{sessionKey}" variant
144
+ const candidates = [sessionKey, `agent:main:${sessionKey}`];
145
+ let matchedKey: string | undefined;
146
+ for (const key of candidates) {
147
+ if (store[key]) {
148
+ matchedKey = key;
149
+ break;
150
+ }
151
+ }
152
+
153
+ if (!matchedKey) {
154
+ log?.info?.(`[adp-openclaw] Session key not found in store for abort marking: ${sessionKey}`);
155
+ return;
156
+ }
157
+
158
+ store[matchedKey].abortedLastRun = true;
159
+ store[matchedKey].updatedAt = Date.now();
160
+ fs.writeFileSync(storePath, JSON.stringify(store, null, 2), "utf-8");
161
+ log?.info?.(`[adp-openclaw] Marked session ${matchedKey} as abortedLastRun=true`);
162
+ } catch (err) {
163
+ log?.error?.(`[adp-openclaw] Failed to mark session aborted: ${err}`);
164
+ }
165
+ }
166
+
119
167
  export async function monitorAdpOpenclaw(params: MonitorParams): Promise<void> {
120
168
  const { wsUrl, clientToken, signKey, abortSignal, log, cfg } = params;
121
169
  const runtime = getAdpOpenclawRuntime();
@@ -255,6 +303,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
255
303
  log?.info(`[adp-openclaw] Received: ${inMsg.from}: ${inMsg.text} (conv=${inMsg.conversationId}, rec=${inMsg.recordId || 'none'}, user=${JSON.stringify(inMsg.user || {})})`);
256
304
 
257
305
  // Process the message with full user identity
306
+ const convIdForCleanup = inMsg.conversationId || `fallback-${Date.now()}`;
258
307
  try {
259
308
  // Build user identity string for From field (like Feishu: "feishu:user_id")
260
309
  const userIdentifier = inMsg.user?.userId || inMsg.from;
@@ -582,6 +631,15 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
582
631
  const cancelText = lastPartialText ? `${lastPartialText}\n\n[已停止生成]` : "[已停止生成]";
583
632
  log?.info(`[adp-openclaw] Generation cancelled, sending outbound_end with partial text`);
584
633
  sendOutboundEnd(cancelText);
634
+
635
+ // Mark the session as aborted so the SDK injects an "abort hint"
636
+ // on the next message, preventing the AI from resuming the cancelled task
637
+ await markSessionAborted({
638
+ sessionKey: route.sessionKey,
639
+ runtime,
640
+ cfg,
641
+ log,
642
+ });
585
643
  }
586
644
 
587
645
  // IMPORTANT: After dispatchReplyWithBufferedBlockDispatcher completes,
@@ -595,7 +653,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
595
653
  }
596
654
  } catch (err) {
597
655
  // Clean up on error
598
- activeGenerations.delete(convId);
656
+ activeGenerations.delete(convIdForCleanup);
599
657
  log?.error(`[adp-openclaw] Failed to process message: ${err}`);
600
658
  }
601
659
  break;