@clawchatsai/connector 0.0.47 → 0.0.48
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 +9 -0
- package/dist/index.js +38 -2
- package/package.json +1 -1
- package/server.js +14 -2
package/dist/index.d.ts
CHANGED
|
@@ -47,6 +47,15 @@ interface PluginApi {
|
|
|
47
47
|
text: string;
|
|
48
48
|
};
|
|
49
49
|
}) => void;
|
|
50
|
+
registerHook: (events: string | string[], handler: (event: Record<string, unknown>, ctx: Record<string, unknown>) => void | Promise<void>, opts: {
|
|
51
|
+
name: string;
|
|
52
|
+
description?: string;
|
|
53
|
+
}) => void;
|
|
54
|
+
registerTypedHook: (hookName: string, handler: (event: Record<string, unknown>, ctx: Record<string, unknown>) => void | Promise<void>, opts?: {
|
|
55
|
+
name?: string;
|
|
56
|
+
description?: string;
|
|
57
|
+
priority?: number;
|
|
58
|
+
}) => void;
|
|
50
59
|
runtime: {
|
|
51
60
|
requestRestart?: (reason: string) => void;
|
|
52
61
|
};
|
package/dist/index.js
CHANGED
|
@@ -123,7 +123,7 @@ async function ensureNativeModules(ctx) {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
async function startClawChats(ctx, api) {
|
|
126
|
+
async function startClawChats(ctx, api, mediaStash) {
|
|
127
127
|
_stopRequested = false;
|
|
128
128
|
let config = loadConfig();
|
|
129
129
|
if (!config) {
|
|
@@ -175,6 +175,7 @@ async function startClawChats(ctx, api) {
|
|
|
175
175
|
gatewayUrl: 'ws://localhost:18789',
|
|
176
176
|
authToken: '', // P2P: DataChannel is the auth boundary (signaling authenticates both sides)
|
|
177
177
|
gatewayToken, // For WS auth to local OpenClaw gateway
|
|
178
|
+
mediaStash, // Shared Map populated by after_tool_call hook (captures MEDIA: paths from exec)
|
|
178
179
|
});
|
|
179
180
|
// 4. Connect createApp's gateway client (handles persistence + event relay)
|
|
180
181
|
app.gatewayClient.connect();
|
|
@@ -958,10 +959,45 @@ const plugin = {
|
|
|
958
959
|
name: 'ClawChats',
|
|
959
960
|
description: 'Connects your gateway to ClawChats via WebRTC P2P',
|
|
960
961
|
register(api) {
|
|
962
|
+
// Shared stash: after_tool_call hook populates this; saveAssistantMessage reads + clears it.
|
|
963
|
+
// Keyed by sessionKey → absolute paths extracted from MEDIA: lines in exec stdout.
|
|
964
|
+
const mediaStash = new Map();
|
|
965
|
+
// Capture MEDIA: paths from exec tool results before the gateway strips them from message text.
|
|
966
|
+
// Fires after every tool call; we filter to exec only and check for MEDIA: lines.
|
|
967
|
+
api.registerTypedHook('after_tool_call', (event, ctx) => {
|
|
968
|
+
// Diagnostic: log every tool call so we can confirm hook fires + see real tool names
|
|
969
|
+
console.log(`[clawchats] hook:after_tool_call toolName=${String(event.toolName)} sessionKey=${String(ctx.sessionKey)}`);
|
|
970
|
+
if (event.toolName !== 'exec')
|
|
971
|
+
return;
|
|
972
|
+
// result is { content: [{ type: 'text', text: '...' }] } — extract text defensively
|
|
973
|
+
const result = event.result;
|
|
974
|
+
let text = '';
|
|
975
|
+
if (typeof result?.text === 'string') {
|
|
976
|
+
text = result.text;
|
|
977
|
+
}
|
|
978
|
+
else if (Array.isArray(result?.content)) {
|
|
979
|
+
text = result.content
|
|
980
|
+
.filter(c => c.type === 'text' && typeof c.text === 'string')
|
|
981
|
+
.map(c => c.text)
|
|
982
|
+
.join('\n');
|
|
983
|
+
}
|
|
984
|
+
else if (result != null) {
|
|
985
|
+
text = String(result);
|
|
986
|
+
}
|
|
987
|
+
const paths = [...text.matchAll(/^MEDIA:\s*(\S+)/gm)].map(m => m[1].trim());
|
|
988
|
+
if (paths.length === 0)
|
|
989
|
+
return;
|
|
990
|
+
const sessionKey = ctx.sessionKey;
|
|
991
|
+
if (!sessionKey)
|
|
992
|
+
return;
|
|
993
|
+
const existing = mediaStash.get(sessionKey) ?? [];
|
|
994
|
+
mediaStash.set(sessionKey, [...existing, ...paths]);
|
|
995
|
+
console.log(`[clawchats] media-capture: stashed ${paths.length} path(s) for ${sessionKey}:`, paths);
|
|
996
|
+
}, { name: 'clawchats-media-capture', description: 'Captures MEDIA: paths from exec results for inline image rendering' });
|
|
961
997
|
// Background service: signaling + gateway bridge + future WebRTC
|
|
962
998
|
api.registerService({
|
|
963
999
|
id: 'connector-service',
|
|
964
|
-
start: (ctx) => startClawChats(ctx, api),
|
|
1000
|
+
start: (ctx) => startClawChats(ctx, api, mediaStash),
|
|
965
1001
|
stop: (ctx) => stopClawChats(ctx),
|
|
966
1002
|
});
|
|
967
1003
|
// CLI commands
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -4061,8 +4061,20 @@ export function createApp(config = {}) {
|
|
|
4061
4061
|
const db = _getDb(parsed.workspace);
|
|
4062
4062
|
const thread = db.prepare('SELECT id FROM threads WHERE id = ?').get(parsed.threadId);
|
|
4063
4063
|
if (!thread) { console.log(`Ignoring response for deleted thread: ${parsed.threadId}`); return; }
|
|
4064
|
-
|
|
4064
|
+
let content = extractContent(message);
|
|
4065
4065
|
if (!content || !content.trim()) { console.log(`Skipping empty assistant response for thread ${parsed.threadId}`); return; }
|
|
4066
|
+
|
|
4067
|
+
// Attach any images captured by the after_tool_call hook (MEDIA: lines from exec stdout).
|
|
4068
|
+
// Always clear the stash entry regardless of whether we find paths, to prevent leaking across turns.
|
|
4069
|
+
const _mediaStash = config.mediaStash;
|
|
4070
|
+
const _pendingPaths = _mediaStash?.get(sessionKey) ?? [];
|
|
4071
|
+
_mediaStash?.delete(sessionKey);
|
|
4072
|
+
if (_pendingPaths.length > 0) {
|
|
4073
|
+
const imageMarkdown = _pendingPaths.map(p => ``).join('\n');
|
|
4074
|
+
content = content.trimEnd() + '\n\n' + imageMarkdown;
|
|
4075
|
+
console.log(`[clawchats] media-attach: appended ${_pendingPaths.length} image(s) to message for ${sessionKey}`);
|
|
4076
|
+
}
|
|
4077
|
+
|
|
4066
4078
|
const now = Date.now();
|
|
4067
4079
|
|
|
4068
4080
|
// Check for pending activity message
|
|
@@ -4633,7 +4645,7 @@ if (isDirectRun) {
|
|
|
4633
4645
|
app.gatewayClient.connect();
|
|
4634
4646
|
|
|
4635
4647
|
// Initialize global DB (custom emojis, etc.)
|
|
4636
|
-
getGlobalDb(
|
|
4648
|
+
getGlobalDb(DATA_DIR);
|
|
4637
4649
|
});
|
|
4638
4650
|
|
|
4639
4651
|
// Graceful shutdown
|