adp-openclaw 0.0.57 → 0.0.58

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 +3 -126
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adp-openclaw",
3
- "version": "0.0.57",
3
+ "version": "0.0.58",
4
4
  "description": "ADP-OpenClaw demo channel plugin (Go WebSocket backend)",
5
5
  "type": "module",
6
6
  "dependencies": {
package/src/monitor.ts CHANGED
@@ -24,7 +24,6 @@ import {
24
24
  } from "./tool-result-message-blocks.js";
25
25
  import crypto from "crypto";
26
26
  import fs from "fs";
27
- import path from "path";
28
27
  // @ts-ignore - import JSON file
29
28
  import packageJson from "../package.json" with { type: "json" };
30
29
 
@@ -165,120 +164,6 @@ async function markSessionAborted(params: {
165
164
  }
166
165
  }
167
166
 
168
- /**
169
- * After an abort, trim the aborted user message and any partial assistant reply
170
- * from the JSONL transcript file. This prevents the AI from seeing the cancelled
171
- * request in its context window and resuming it on the next turn.
172
- *
173
- * The JSONL transcript is a tree structure (id + parentId). We find the last
174
- * user message entry and remove it (plus any subsequent entries like partial
175
- * assistant replies). This is equivalent to SessionManager.branch(parentId).
176
- */
177
- async function trimAbortedMessagesFromTranscript(params: {
178
- sessionKey: string;
179
- runtime: ReturnType<typeof getAdpOpenclawRuntime>;
180
- cfg?: ClawdbotConfig;
181
- log?: PluginLogger;
182
- }): Promise<void> {
183
- const { sessionKey, runtime, cfg, log } = params;
184
- try {
185
- const storePath = runtime.channel.session.resolveStorePath(cfg?.session?.store);
186
- if (!storePath || !fs.existsSync(storePath)) {
187
- log?.warn?.(`[adp-openclaw] Cannot trim transcript: store not found at ${storePath}`);
188
- return;
189
- }
190
-
191
- const raw = fs.readFileSync(storePath, "utf-8");
192
- const store = JSON.parse(raw) as Record<string, { sessionId?: string; sessionFile?: string; [key: string]: unknown }>;
193
-
194
- // Find matching session entry
195
- const candidates = [sessionKey, `agent:main:${sessionKey}`];
196
- let entry: { sessionId?: string; sessionFile?: string; [key: string]: unknown } | undefined;
197
- for (const key of candidates) {
198
- if (store[key]) {
199
- entry = store[key];
200
- break;
201
- }
202
- }
203
-
204
- if (!entry?.sessionId) {
205
- log?.info?.(`[adp-openclaw] Session entry not found for transcript trimming: ${sessionKey}`);
206
- return;
207
- }
208
-
209
- // Resolve transcript file path
210
- let transcriptPath: string;
211
- if (entry.sessionFile) {
212
- transcriptPath = entry.sessionFile;
213
- } else {
214
- // Fallback: same directory as sessions.json, filename = <sessionId>.jsonl
215
- transcriptPath = path.join(path.dirname(storePath), `${entry.sessionId}.jsonl`);
216
- }
217
-
218
- if (!fs.existsSync(transcriptPath)) {
219
- log?.info?.(`[adp-openclaw] Transcript file not found: ${transcriptPath}`);
220
- return;
221
- }
222
-
223
- // Read and parse JSONL lines
224
- const content = fs.readFileSync(transcriptPath, "utf-8");
225
- const lines = content.split("\n").filter((l) => l.trim());
226
-
227
- if (lines.length === 0) return;
228
-
229
- // Parse each line into JSON entries
230
- type TranscriptEntry = {
231
- type?: string;
232
- id?: string;
233
- parentId?: string | null;
234
- message?: { role?: string; content?: unknown };
235
- [key: string]: unknown;
236
- };
237
-
238
- const entries: TranscriptEntry[] = [];
239
- for (const line of lines) {
240
- try {
241
- entries.push(JSON.parse(line));
242
- } catch {
243
- entries.push({ _raw: line } as unknown as TranscriptEntry);
244
- }
245
- }
246
-
247
- // Find the last user message entry (searching from the end)
248
- let lastUserMsgIdx = -1;
249
- for (let i = entries.length - 1; i >= 0; i--) {
250
- const e = entries[i];
251
- if (e.type === "message" && e.message?.role === "user") {
252
- lastUserMsgIdx = i;
253
- break;
254
- }
255
- }
256
-
257
- if (lastUserMsgIdx < 0) {
258
- log?.info?.(`[adp-openclaw] No user message found in transcript to trim`);
259
- return;
260
- }
261
-
262
- // Check if the last user message is at or near the end (within last few entries)
263
- // This ensures we only trim the most recent aborted conversation, not old ones
264
- if (lastUserMsgIdx < entries.length - 5) {
265
- log?.info?.(`[adp-openclaw] Last user message is not recent enough to trim (idx=${lastUserMsgIdx}, total=${entries.length})`);
266
- return;
267
- }
268
-
269
- // Truncate: keep everything before the last user message
270
- const trimmedLines = lines.slice(0, lastUserMsgIdx);
271
- const trimmedContent = trimmedLines.join("\n") + "\n";
272
-
273
- fs.writeFileSync(transcriptPath, trimmedContent, "utf-8");
274
-
275
- const removedCount = lines.length - lastUserMsgIdx;
276
- log?.info?.(`[adp-openclaw] Trimmed ${removedCount} aborted entries from transcript (kept ${lastUserMsgIdx} entries)`);
277
- } catch (err) {
278
- log?.error?.(`[adp-openclaw] Failed to trim aborted messages from transcript: ${err}`);
279
- }
280
- }
281
-
282
167
  export async function monitorAdpOpenclaw(params: MonitorParams): Promise<void> {
283
168
  const { wsUrl, clientToken, signKey, abortSignal, log, cfg } = params;
284
169
  const runtime = getAdpOpenclawRuntime();
@@ -748,23 +633,15 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
748
633
  sendOutboundEnd(cancelText);
749
634
 
750
635
  // Mark the session as aborted so the SDK injects an "abort hint"
751
- // on the next message, preventing the AI from resuming the cancelled task
636
+ // on the next message, preventing the AI from resuming the cancelled task.
637
+ // This aligns with openclaw's behavior: keep all transcript history intact,
638
+ // only set abortedLastRun=true so next turn gets "Resume carefully" hint.
752
639
  await markSessionAborted({
753
640
  sessionKey: route.sessionKey,
754
641
  runtime,
755
642
  cfg,
756
643
  log,
757
644
  });
758
-
759
- // Remove the aborted user message and partial assistant reply from
760
- // the JSONL transcript. Without this, the AI sees the old cancelled
761
- // request in its context and may resume it instead of answering the new one.
762
- await trimAbortedMessagesFromTranscript({
763
- sessionKey: route.sessionKey,
764
- runtime,
765
- cfg,
766
- log,
767
- });
768
645
  }
769
646
 
770
647
  // IMPORTANT: After dispatchReplyWithBufferedBlockDispatcher completes,