@clawchatsai/connector 0.1.9 → 0.1.10

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/server/gateway.js +30 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawchatsai/connector",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "description": "ClawChats OpenClaw plugin — P2P tunnel + local API bridge",
6
6
  "main": "dist/index.js",
package/server/gateway.js CHANGED
@@ -11,9 +11,13 @@ export class GatewayClient {
11
11
  this.debugLogger = debugLogger;
12
12
  this.gatewayWsUrl = gatewayWsUrl;
13
13
  this.authToken = authToken;
14
- // Per-session buffer of MEDIA: paths extracted from exec tool args (echo "MEDIA:/...").
14
+ // Per-session buffer of attachment paths captured during a run. Drained by saveAssistantMessage.
15
+ // Sources: (1) MEDIA: paths from exec tool's echo args, (2) Write/Edit tool args.path.
15
16
  // Lives on the stable singleton — safe from plugin re-registration that broke the old closure-based stash.
16
17
  this._runMediaPaths = new Map();
18
+ // Per-toolCallId staging for Write/Edit: path captured at phase:start, promoted to _runMediaPaths
19
+ // at phase:result if the call succeeded. Keyed by toolCallId; value: { sessionKey, path }.
20
+ this._runWriteBuffers = new Map();
17
21
 
18
22
  this.ws = null;
19
23
  this.connected = false;
@@ -379,6 +383,31 @@ export class GatewayClient {
379
383
  this._runMediaPaths.set(sessionKey, [...new Set([...existing, ...paths])]);
380
384
  }
381
385
  }
386
+ // Capture Write/Edit tool paths. The split pane (and existing attachment chip render) handles
387
+ // any text-ish or PDF file, so allow that broad set; image/audio extensions also flow through
388
+ // — saveAssistantMessage routes them by ext (image → markdown, audio → audio chip).
389
+ // Buffer at phase:start when args.path is present; promote to _runMediaPaths at phase:result
390
+ // only if the call succeeded — failed writes shouldn't surface a chip for a file that may not exist.
391
+ const VIEWABLE_EXTS = new Set([
392
+ 'pdf','md','mdx','rst','txt','log',
393
+ 'csv','tsv','json','xml','yaml','yml','toml','ini','env','conf',
394
+ 'js','jsx','mjs','cjs','ts','tsx','py','rb','go','rs','java','c','cpp','h','hpp','cs','php',
395
+ 'html','htm','css','scss','sass','less','sh','bash','zsh','sql','pl','lua','r','swift','kt','dart',
396
+ 'png','jpg','jpeg','gif','webp','bmp','svg','ico','avif','tiff',
397
+ 'mp3','wav','ogg','m4a','flac','aac','opus','wma'
398
+ ]);
399
+ if (sessionKey && data?.toolCallId && /^(write|edit|multiedit|notebookedit)$/i.test(data?.name || '') && data?.phase === 'start' && typeof data?.args?.path === 'string' && data.args.path.length > 0) {
400
+ const ext = (data.args.path.split('.').pop() || '').toLowerCase();
401
+ if (VIEWABLE_EXTS.has(ext)) this._runWriteBuffers.set(data.toolCallId, { sessionKey, path: data.args.path });
402
+ }
403
+ if (data?.toolCallId && data?.phase === 'result' && this._runWriteBuffers.has(data.toolCallId)) {
404
+ const buf = this._runWriteBuffers.get(data.toolCallId);
405
+ this._runWriteBuffers.delete(data.toolCallId);
406
+ if (!data.isError && buf.sessionKey === sessionKey) {
407
+ const existing = this._runMediaPaths.get(buf.sessionKey) ?? [];
408
+ this._runMediaPaths.set(buf.sessionKey, [...new Set([...existing, buf.path])]);
409
+ }
410
+ }
382
411
  const step = { type: 'tool', timestamp: Date.now(), name: data?.name || 'unknown', phase: data?.phase || 'start', toolCallId: data?.toolCallId, meta: data?.meta || (argsMeta ? String(argsMeta) : undefined), isError: data?.isError || false };
383
412
  if (data?.phase === 'result') {
384
413
  const existing = log.steps.findLast(s => s.toolCallId === data.toolCallId && (s.phase === 'start' || s.phase === 'running'));