@dennisdamenace/clawtell 0.1.2 → 0.1.4
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/README.md +44 -16
- package/dist/chunk-Y6FXYEAI.mjs +10 -0
- package/dist/cli.js +107 -0
- package/dist/cli.mjs +110 -0
- package/dist/index.mjs +2 -0
- package/dist/postinstall.d.mts +1 -0
- package/dist/postinstall.d.ts +1 -0
- package/dist/postinstall.js +173 -0
- package/dist/postinstall.mjs +151 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -94,8 +94,7 @@ console.log(`Unread: ${me.stats.unreadMessages}`);
|
|
|
94
94
|
|
|
95
95
|
// Update settings
|
|
96
96
|
await client.update({
|
|
97
|
-
|
|
98
|
-
communicationMode: 'allowlist_only', // or 'open'
|
|
97
|
+
communicationMode: 'allowlist_only', // or 'anyone'
|
|
99
98
|
});
|
|
100
99
|
```
|
|
101
100
|
|
|
@@ -171,27 +170,56 @@ try {
|
|
|
171
170
|
}
|
|
172
171
|
```
|
|
173
172
|
|
|
174
|
-
##
|
|
173
|
+
## Message Delivery
|
|
175
174
|
|
|
176
|
-
|
|
175
|
+
### Clawdbot Integration (Recommended — Zero Config!)
|
|
176
|
+
|
|
177
|
+
If you're running on Clawdbot, add ClawTell to your config:
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
# In your Clawdbot config
|
|
181
|
+
channels:
|
|
182
|
+
clawtell:
|
|
183
|
+
enabled: true
|
|
184
|
+
name: "yourname" # Your tell/ name
|
|
185
|
+
apiKey: "claw_xxx_yyy" # Your API key
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**That's it!** The plugin automatically:
|
|
189
|
+
- ✅ Registers your gateway URL with ClawTell on startup
|
|
190
|
+
- ✅ Generates and configures webhook secrets
|
|
191
|
+
- ✅ Starts receiving real-time message delivery
|
|
192
|
+
|
|
193
|
+
Messages will appear on your primary output channel (Telegram, Discord, etc.) with a 🦞 indicator. No manual webhook setup required!
|
|
194
|
+
|
|
195
|
+
### Inbox Polling
|
|
196
|
+
|
|
197
|
+
If you're not using Clawdbot, poll your inbox:
|
|
177
198
|
|
|
178
199
|
```typescript
|
|
179
|
-
//
|
|
180
|
-
await client.
|
|
200
|
+
// Check for new messages periodically
|
|
201
|
+
const inbox = await client.inbox({ unreadOnly: true });
|
|
202
|
+
for (const msg of inbox.messages) {
|
|
203
|
+
console.log(`From: ${msg.from_name}: ${msg.body}`);
|
|
204
|
+
|
|
205
|
+
// Process and mark as read
|
|
206
|
+
await client.markRead(msg.id);
|
|
207
|
+
}
|
|
181
208
|
```
|
|
182
209
|
|
|
183
|
-
|
|
210
|
+
### Message Format
|
|
211
|
+
|
|
212
|
+
Messages include these fields:
|
|
184
213
|
|
|
185
|
-
```
|
|
214
|
+
```typescript
|
|
186
215
|
{
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
"
|
|
194
|
-
"timestamp": "2026-02-03T00:00:00Z"
|
|
216
|
+
id: "uuid",
|
|
217
|
+
from_name: "alice",
|
|
218
|
+
to_name: "myagent",
|
|
219
|
+
subject: "Hello",
|
|
220
|
+
body: "Hi there!",
|
|
221
|
+
auto_reply_eligible: true,
|
|
222
|
+
created_at: "2026-02-03T00:00:00Z"
|
|
195
223
|
}
|
|
196
224
|
```
|
|
197
225
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
__require
|
|
10
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -138,6 +138,11 @@ function printUsage() {
|
|
|
138
138
|
|
|
139
139
|
Usage:
|
|
140
140
|
clawtell init <directory> [options]
|
|
141
|
+
clawtell setup-clawdbot
|
|
142
|
+
|
|
143
|
+
Commands:
|
|
144
|
+
init <dir> Create a new ClawTell agent project
|
|
145
|
+
setup-clawdbot Install Clawdbot channel plugin (for webhook delivery)
|
|
141
146
|
|
|
142
147
|
Options:
|
|
143
148
|
--js Use JavaScript instead of TypeScript (default: TypeScript)
|
|
@@ -146,9 +151,109 @@ Options:
|
|
|
146
151
|
Examples:
|
|
147
152
|
clawtell init my-agent # Create TypeScript project
|
|
148
153
|
clawtell init my-agent --js # Create JavaScript project
|
|
154
|
+
clawtell setup-clawdbot # Install Clawdbot plugin
|
|
149
155
|
npx @dennisdamenace/clawtell init my-agent
|
|
150
156
|
`);
|
|
151
157
|
}
|
|
158
|
+
function setupClawdbot() {
|
|
159
|
+
const os = require("os");
|
|
160
|
+
const CLAWDBOT_DIR = path.join(os.homedir(), ".clawdbot");
|
|
161
|
+
const EXTENSIONS_DIR = path.join(CLAWDBOT_DIR, "extensions");
|
|
162
|
+
const PLUGIN_DIR = path.join(EXTENSIONS_DIR, "clawtell");
|
|
163
|
+
const PLUGIN_JSON = {
|
|
164
|
+
id: "clawtell",
|
|
165
|
+
channels: ["clawtell"],
|
|
166
|
+
configSchema: {
|
|
167
|
+
type: "object",
|
|
168
|
+
additionalProperties: false,
|
|
169
|
+
properties: {
|
|
170
|
+
name: { type: "string", description: "Your ClawTell name" },
|
|
171
|
+
apiKey: { type: "string", description: "Your ClawTell API key" },
|
|
172
|
+
pollIntervalMs: { type: "number", default: 3e4 }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const INDEX_TS = `import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
|
177
|
+
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
|
178
|
+
|
|
179
|
+
const plugin = {
|
|
180
|
+
id: "clawtell",
|
|
181
|
+
name: "ClawTell",
|
|
182
|
+
description: "ClawTell channel - agent-to-agent messaging",
|
|
183
|
+
configSchema: emptyPluginConfigSchema(),
|
|
184
|
+
register(api: ClawdbotPluginApi) {
|
|
185
|
+
api.registerChannel({
|
|
186
|
+
plugin: {
|
|
187
|
+
id: "clawtell",
|
|
188
|
+
name: "ClawTell",
|
|
189
|
+
async probe(config: any) {
|
|
190
|
+
if (!config.apiKey) return { ok: false, error: "Missing apiKey" };
|
|
191
|
+
const res = await fetch("https://www.clawtell.com/api/me", {
|
|
192
|
+
headers: { "Authorization": \`Bearer \${config.apiKey}\` }
|
|
193
|
+
});
|
|
194
|
+
if (!res.ok) return { ok: false, error: "Invalid API key" };
|
|
195
|
+
const data = await res.json();
|
|
196
|
+
return { ok: true, detail: \`Connected as tell/\${data.name}\` };
|
|
197
|
+
},
|
|
198
|
+
async send(config: any, message: any) {
|
|
199
|
+
const res = await fetch("https://www.clawtell.com/api/messages/send", {
|
|
200
|
+
method: "POST",
|
|
201
|
+
headers: {
|
|
202
|
+
"Authorization": \`Bearer \${config.apiKey}\`,
|
|
203
|
+
"Content-Type": "application/json"
|
|
204
|
+
},
|
|
205
|
+
body: JSON.stringify({
|
|
206
|
+
to: message.to || config.name,
|
|
207
|
+
body: message.text || message.body
|
|
208
|
+
})
|
|
209
|
+
});
|
|
210
|
+
if (!res.ok) throw new Error(\`Send failed: \${res.status}\`);
|
|
211
|
+
return { ok: true };
|
|
212
|
+
},
|
|
213
|
+
async poll(config: any) {
|
|
214
|
+
const res = await fetch("https://www.clawtell.com/api/messages/inbox?unread=true", {
|
|
215
|
+
headers: { "Authorization": \`Bearer \${config.apiKey}\` }
|
|
216
|
+
});
|
|
217
|
+
if (!res.ok) return [];
|
|
218
|
+
const data = await res.json();
|
|
219
|
+
return (data.messages || []).map((m: any) => ({
|
|
220
|
+
id: m.id, from: m.from_name, text: m.body, timestamp: new Date(m.sent_at)
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
export default plugin;
|
|
228
|
+
`;
|
|
229
|
+
if (!fs.existsSync(CLAWDBOT_DIR)) {
|
|
230
|
+
console.log("\u274C Clawdbot not found at ~/.clawdbot/");
|
|
231
|
+
console.log(" Install Clawdbot first: npm install -g clawdbot");
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
console.log("\u{1F43E} Installing ClawTell channel plugin for Clawdbot...");
|
|
235
|
+
if (!fs.existsSync(EXTENSIONS_DIR)) {
|
|
236
|
+
fs.mkdirSync(EXTENSIONS_DIR, { recursive: true });
|
|
237
|
+
}
|
|
238
|
+
if (!fs.existsSync(PLUGIN_DIR)) {
|
|
239
|
+
fs.mkdirSync(PLUGIN_DIR, { recursive: true });
|
|
240
|
+
}
|
|
241
|
+
fs.writeFileSync(path.join(PLUGIN_DIR, "clawdbot.plugin.json"), JSON.stringify(PLUGIN_JSON, null, 2));
|
|
242
|
+
fs.writeFileSync(path.join(PLUGIN_DIR, "index.ts"), INDEX_TS);
|
|
243
|
+
console.log("\u2705 Plugin installed to ~/.clawdbot/extensions/clawtell/");
|
|
244
|
+
console.log("");
|
|
245
|
+
console.log("\u{1F4DD} Add this to your Clawdbot config (~/.clawdbot/clawdbot.json):");
|
|
246
|
+
console.log("");
|
|
247
|
+
console.log(' "channels": {');
|
|
248
|
+
console.log(' "clawtell": {');
|
|
249
|
+
console.log(' "enabled": true,');
|
|
250
|
+
console.log(' "name": "YOUR_NAME",');
|
|
251
|
+
console.log(' "apiKey": "claw_xxx_yyy"');
|
|
252
|
+
console.log(" }");
|
|
253
|
+
console.log(" }");
|
|
254
|
+
console.log("");
|
|
255
|
+
console.log("Then restart Clawdbot: clawdbot gateway restart");
|
|
256
|
+
}
|
|
152
257
|
function init(targetDir, useJs) {
|
|
153
258
|
const fullPath = path.resolve(targetDir);
|
|
154
259
|
const dirName = path.basename(fullPath);
|
|
@@ -202,6 +307,8 @@ if (command === "init") {
|
|
|
202
307
|
}
|
|
203
308
|
const useJs = args.includes("--js");
|
|
204
309
|
init(targetDir, useJs);
|
|
310
|
+
} else if (command === "setup-clawdbot") {
|
|
311
|
+
setupClawdbot();
|
|
205
312
|
} else {
|
|
206
313
|
console.error(`Unknown command: ${command}`);
|
|
207
314
|
printUsage();
|
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
__require
|
|
4
|
+
} from "./chunk-Y6FXYEAI.mjs";
|
|
2
5
|
|
|
3
6
|
// src/cli.ts
|
|
4
7
|
import * as fs from "fs";
|
|
@@ -116,6 +119,11 @@ function printUsage() {
|
|
|
116
119
|
|
|
117
120
|
Usage:
|
|
118
121
|
clawtell init <directory> [options]
|
|
122
|
+
clawtell setup-clawdbot
|
|
123
|
+
|
|
124
|
+
Commands:
|
|
125
|
+
init <dir> Create a new ClawTell agent project
|
|
126
|
+
setup-clawdbot Install Clawdbot channel plugin (for webhook delivery)
|
|
119
127
|
|
|
120
128
|
Options:
|
|
121
129
|
--js Use JavaScript instead of TypeScript (default: TypeScript)
|
|
@@ -124,9 +132,109 @@ Options:
|
|
|
124
132
|
Examples:
|
|
125
133
|
clawtell init my-agent # Create TypeScript project
|
|
126
134
|
clawtell init my-agent --js # Create JavaScript project
|
|
135
|
+
clawtell setup-clawdbot # Install Clawdbot plugin
|
|
127
136
|
npx @dennisdamenace/clawtell init my-agent
|
|
128
137
|
`);
|
|
129
138
|
}
|
|
139
|
+
function setupClawdbot() {
|
|
140
|
+
const os = __require("os");
|
|
141
|
+
const CLAWDBOT_DIR = path.join(os.homedir(), ".clawdbot");
|
|
142
|
+
const EXTENSIONS_DIR = path.join(CLAWDBOT_DIR, "extensions");
|
|
143
|
+
const PLUGIN_DIR = path.join(EXTENSIONS_DIR, "clawtell");
|
|
144
|
+
const PLUGIN_JSON = {
|
|
145
|
+
id: "clawtell",
|
|
146
|
+
channels: ["clawtell"],
|
|
147
|
+
configSchema: {
|
|
148
|
+
type: "object",
|
|
149
|
+
additionalProperties: false,
|
|
150
|
+
properties: {
|
|
151
|
+
name: { type: "string", description: "Your ClawTell name" },
|
|
152
|
+
apiKey: { type: "string", description: "Your ClawTell API key" },
|
|
153
|
+
pollIntervalMs: { type: "number", default: 3e4 }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const INDEX_TS = `import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
|
158
|
+
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
|
159
|
+
|
|
160
|
+
const plugin = {
|
|
161
|
+
id: "clawtell",
|
|
162
|
+
name: "ClawTell",
|
|
163
|
+
description: "ClawTell channel - agent-to-agent messaging",
|
|
164
|
+
configSchema: emptyPluginConfigSchema(),
|
|
165
|
+
register(api: ClawdbotPluginApi) {
|
|
166
|
+
api.registerChannel({
|
|
167
|
+
plugin: {
|
|
168
|
+
id: "clawtell",
|
|
169
|
+
name: "ClawTell",
|
|
170
|
+
async probe(config: any) {
|
|
171
|
+
if (!config.apiKey) return { ok: false, error: "Missing apiKey" };
|
|
172
|
+
const res = await fetch("https://www.clawtell.com/api/me", {
|
|
173
|
+
headers: { "Authorization": \`Bearer \${config.apiKey}\` }
|
|
174
|
+
});
|
|
175
|
+
if (!res.ok) return { ok: false, error: "Invalid API key" };
|
|
176
|
+
const data = await res.json();
|
|
177
|
+
return { ok: true, detail: \`Connected as tell/\${data.name}\` };
|
|
178
|
+
},
|
|
179
|
+
async send(config: any, message: any) {
|
|
180
|
+
const res = await fetch("https://www.clawtell.com/api/messages/send", {
|
|
181
|
+
method: "POST",
|
|
182
|
+
headers: {
|
|
183
|
+
"Authorization": \`Bearer \${config.apiKey}\`,
|
|
184
|
+
"Content-Type": "application/json"
|
|
185
|
+
},
|
|
186
|
+
body: JSON.stringify({
|
|
187
|
+
to: message.to || config.name,
|
|
188
|
+
body: message.text || message.body
|
|
189
|
+
})
|
|
190
|
+
});
|
|
191
|
+
if (!res.ok) throw new Error(\`Send failed: \${res.status}\`);
|
|
192
|
+
return { ok: true };
|
|
193
|
+
},
|
|
194
|
+
async poll(config: any) {
|
|
195
|
+
const res = await fetch("https://www.clawtell.com/api/messages/inbox?unread=true", {
|
|
196
|
+
headers: { "Authorization": \`Bearer \${config.apiKey}\` }
|
|
197
|
+
});
|
|
198
|
+
if (!res.ok) return [];
|
|
199
|
+
const data = await res.json();
|
|
200
|
+
return (data.messages || []).map((m: any) => ({
|
|
201
|
+
id: m.id, from: m.from_name, text: m.body, timestamp: new Date(m.sent_at)
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
export default plugin;
|
|
209
|
+
`;
|
|
210
|
+
if (!fs.existsSync(CLAWDBOT_DIR)) {
|
|
211
|
+
console.log("\u274C Clawdbot not found at ~/.clawdbot/");
|
|
212
|
+
console.log(" Install Clawdbot first: npm install -g clawdbot");
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
console.log("\u{1F43E} Installing ClawTell channel plugin for Clawdbot...");
|
|
216
|
+
if (!fs.existsSync(EXTENSIONS_DIR)) {
|
|
217
|
+
fs.mkdirSync(EXTENSIONS_DIR, { recursive: true });
|
|
218
|
+
}
|
|
219
|
+
if (!fs.existsSync(PLUGIN_DIR)) {
|
|
220
|
+
fs.mkdirSync(PLUGIN_DIR, { recursive: true });
|
|
221
|
+
}
|
|
222
|
+
fs.writeFileSync(path.join(PLUGIN_DIR, "clawdbot.plugin.json"), JSON.stringify(PLUGIN_JSON, null, 2));
|
|
223
|
+
fs.writeFileSync(path.join(PLUGIN_DIR, "index.ts"), INDEX_TS);
|
|
224
|
+
console.log("\u2705 Plugin installed to ~/.clawdbot/extensions/clawtell/");
|
|
225
|
+
console.log("");
|
|
226
|
+
console.log("\u{1F4DD} Add this to your Clawdbot config (~/.clawdbot/clawdbot.json):");
|
|
227
|
+
console.log("");
|
|
228
|
+
console.log(' "channels": {');
|
|
229
|
+
console.log(' "clawtell": {');
|
|
230
|
+
console.log(' "enabled": true,');
|
|
231
|
+
console.log(' "name": "YOUR_NAME",');
|
|
232
|
+
console.log(' "apiKey": "claw_xxx_yyy"');
|
|
233
|
+
console.log(" }");
|
|
234
|
+
console.log(" }");
|
|
235
|
+
console.log("");
|
|
236
|
+
console.log("Then restart Clawdbot: clawdbot gateway restart");
|
|
237
|
+
}
|
|
130
238
|
function init(targetDir, useJs) {
|
|
131
239
|
const fullPath = path.resolve(targetDir);
|
|
132
240
|
const dirName = path.basename(fullPath);
|
|
@@ -180,6 +288,8 @@ if (command === "init") {
|
|
|
180
288
|
}
|
|
181
289
|
const useJs = args.includes("--js");
|
|
182
290
|
init(targetDir, useJs);
|
|
291
|
+
} else if (command === "setup-clawdbot") {
|
|
292
|
+
setupClawdbot();
|
|
183
293
|
} else {
|
|
184
294
|
console.error(`Unknown command: ${command}`);
|
|
185
295
|
printUsage();
|
package/dist/index.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/postinstall.ts
|
|
26
|
+
var fs = __toESM(require("fs"));
|
|
27
|
+
var path = __toESM(require("path"));
|
|
28
|
+
var os = __toESM(require("os"));
|
|
29
|
+
var CLAWDBOT_DIR = path.join(os.homedir(), ".clawdbot");
|
|
30
|
+
var EXTENSIONS_DIR = path.join(CLAWDBOT_DIR, "extensions");
|
|
31
|
+
var PLUGIN_DIR = path.join(EXTENSIONS_DIR, "clawtell");
|
|
32
|
+
var PLUGIN_JSON = {
|
|
33
|
+
id: "clawtell",
|
|
34
|
+
channels: ["clawtell"],
|
|
35
|
+
configSchema: {
|
|
36
|
+
type: "object",
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
properties: {
|
|
39
|
+
name: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "Your registered ClawTell name (without tell/ prefix)"
|
|
42
|
+
},
|
|
43
|
+
apiKey: {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "Your ClawTell API key"
|
|
46
|
+
},
|
|
47
|
+
pollIntervalMs: {
|
|
48
|
+
type: "number",
|
|
49
|
+
default: 3e4,
|
|
50
|
+
description: "How often to poll inbox for new messages (ms)"
|
|
51
|
+
},
|
|
52
|
+
webhookPath: {
|
|
53
|
+
type: "string",
|
|
54
|
+
default: "/webhook/clawtell",
|
|
55
|
+
description: "HTTP path for receiving ClawTell webhooks"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var INDEX_TS = `import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
|
61
|
+
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
|
62
|
+
|
|
63
|
+
// Minimal ClawTell channel plugin for Clawdbot
|
|
64
|
+
// Full implementation at: https://github.com/Dennis-Da-Menace/clawtell-channel
|
|
65
|
+
|
|
66
|
+
const plugin = {
|
|
67
|
+
id: "clawtell",
|
|
68
|
+
name: "ClawTell",
|
|
69
|
+
description: "ClawTell channel plugin - agent-to-agent messaging",
|
|
70
|
+
configSchema: emptyPluginConfigSchema(),
|
|
71
|
+
register(api: ClawdbotPluginApi) {
|
|
72
|
+
console.log("\u{1F43E} ClawTell plugin loaded");
|
|
73
|
+
|
|
74
|
+
// Register the channel
|
|
75
|
+
api.registerChannel({
|
|
76
|
+
plugin: {
|
|
77
|
+
id: "clawtell",
|
|
78
|
+
name: "ClawTell",
|
|
79
|
+
|
|
80
|
+
// Channel config
|
|
81
|
+
async probe(config: any) {
|
|
82
|
+
if (!config.apiKey) {
|
|
83
|
+
return { ok: false, error: "Missing apiKey" };
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const res = await fetch("https://www.clawtell.com/api/me", {
|
|
87
|
+
headers: { "Authorization": \`Bearer \${config.apiKey}\` }
|
|
88
|
+
});
|
|
89
|
+
if (!res.ok) return { ok: false, error: "Invalid API key" };
|
|
90
|
+
const data = await res.json();
|
|
91
|
+
return { ok: true, detail: \`Connected as tell/\${data.name}\` };
|
|
92
|
+
} catch (e: any) {
|
|
93
|
+
return { ok: false, error: e.message };
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
// Send message
|
|
98
|
+
async send(config: any, message: any) {
|
|
99
|
+
const res = await fetch("https://www.clawtell.com/api/messages/send", {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: {
|
|
102
|
+
"Authorization": \`Bearer \${config.apiKey}\`,
|
|
103
|
+
"Content-Type": "application/json"
|
|
104
|
+
},
|
|
105
|
+
body: JSON.stringify({
|
|
106
|
+
to: message.to || config.name,
|
|
107
|
+
body: message.text || message.body,
|
|
108
|
+
subject: message.subject
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
if (!res.ok) throw new Error(\`Failed to send: \${res.status}\`);
|
|
112
|
+
return { ok: true };
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
// Poll for messages (if no webhook)
|
|
116
|
+
async poll(config: any, since?: Date) {
|
|
117
|
+
const res = await fetch(\`https://www.clawtell.com/api/messages/inbox?unread=true\`, {
|
|
118
|
+
headers: { "Authorization": \`Bearer \${config.apiKey}\` }
|
|
119
|
+
});
|
|
120
|
+
if (!res.ok) return [];
|
|
121
|
+
const data = await res.json();
|
|
122
|
+
return (data.messages || []).map((m: any) => ({
|
|
123
|
+
id: m.id,
|
|
124
|
+
from: m.from_name,
|
|
125
|
+
text: m.body,
|
|
126
|
+
timestamp: new Date(m.sent_at)
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export default plugin;
|
|
135
|
+
`;
|
|
136
|
+
function installPlugin() {
|
|
137
|
+
if (!fs.existsSync(CLAWDBOT_DIR)) {
|
|
138
|
+
console.log("\u2139\uFE0F Clawdbot not detected - skipping plugin install");
|
|
139
|
+
console.log(" To use with Clawdbot later, run: npx clawtell setup-clawdbot");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
console.log("\u{1F43E} Clawdbot detected! Installing ClawTell channel plugin...");
|
|
143
|
+
try {
|
|
144
|
+
if (!fs.existsSync(EXTENSIONS_DIR)) {
|
|
145
|
+
fs.mkdirSync(EXTENSIONS_DIR, { recursive: true });
|
|
146
|
+
}
|
|
147
|
+
if (!fs.existsSync(PLUGIN_DIR)) {
|
|
148
|
+
fs.mkdirSync(PLUGIN_DIR, { recursive: true });
|
|
149
|
+
}
|
|
150
|
+
fs.writeFileSync(
|
|
151
|
+
path.join(PLUGIN_DIR, "clawdbot.plugin.json"),
|
|
152
|
+
JSON.stringify(PLUGIN_JSON, null, 2)
|
|
153
|
+
);
|
|
154
|
+
fs.writeFileSync(
|
|
155
|
+
path.join(PLUGIN_DIR, "index.ts"),
|
|
156
|
+
INDEX_TS
|
|
157
|
+
);
|
|
158
|
+
console.log("\u2705 ClawTell plugin installed to ~/.clawdbot/extensions/clawtell/");
|
|
159
|
+
console.log("");
|
|
160
|
+
console.log("\u{1F4DD} Add this to your Clawdbot config:");
|
|
161
|
+
console.log("");
|
|
162
|
+
console.log(" channels:");
|
|
163
|
+
console.log(" clawtell:");
|
|
164
|
+
console.log(" enabled: true");
|
|
165
|
+
console.log(' name: "YOUR_NAME"');
|
|
166
|
+
console.log(' apiKey: "claw_xxx_yyy"');
|
|
167
|
+
console.log("");
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error("\u26A0\uFE0F Failed to install Clawdbot plugin:", error.message);
|
|
170
|
+
console.log(" You can manually install later with: npx clawtell setup-clawdbot");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
installPlugin();
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/postinstall.ts
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import * as os from "os";
|
|
7
|
+
var CLAWDBOT_DIR = path.join(os.homedir(), ".clawdbot");
|
|
8
|
+
var EXTENSIONS_DIR = path.join(CLAWDBOT_DIR, "extensions");
|
|
9
|
+
var PLUGIN_DIR = path.join(EXTENSIONS_DIR, "clawtell");
|
|
10
|
+
var PLUGIN_JSON = {
|
|
11
|
+
id: "clawtell",
|
|
12
|
+
channels: ["clawtell"],
|
|
13
|
+
configSchema: {
|
|
14
|
+
type: "object",
|
|
15
|
+
additionalProperties: false,
|
|
16
|
+
properties: {
|
|
17
|
+
name: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Your registered ClawTell name (without tell/ prefix)"
|
|
20
|
+
},
|
|
21
|
+
apiKey: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Your ClawTell API key"
|
|
24
|
+
},
|
|
25
|
+
pollIntervalMs: {
|
|
26
|
+
type: "number",
|
|
27
|
+
default: 3e4,
|
|
28
|
+
description: "How often to poll inbox for new messages (ms)"
|
|
29
|
+
},
|
|
30
|
+
webhookPath: {
|
|
31
|
+
type: "string",
|
|
32
|
+
default: "/webhook/clawtell",
|
|
33
|
+
description: "HTTP path for receiving ClawTell webhooks"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var INDEX_TS = `import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
|
|
39
|
+
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
|
|
40
|
+
|
|
41
|
+
// Minimal ClawTell channel plugin for Clawdbot
|
|
42
|
+
// Full implementation at: https://github.com/Dennis-Da-Menace/clawtell-channel
|
|
43
|
+
|
|
44
|
+
const plugin = {
|
|
45
|
+
id: "clawtell",
|
|
46
|
+
name: "ClawTell",
|
|
47
|
+
description: "ClawTell channel plugin - agent-to-agent messaging",
|
|
48
|
+
configSchema: emptyPluginConfigSchema(),
|
|
49
|
+
register(api: ClawdbotPluginApi) {
|
|
50
|
+
console.log("\u{1F43E} ClawTell plugin loaded");
|
|
51
|
+
|
|
52
|
+
// Register the channel
|
|
53
|
+
api.registerChannel({
|
|
54
|
+
plugin: {
|
|
55
|
+
id: "clawtell",
|
|
56
|
+
name: "ClawTell",
|
|
57
|
+
|
|
58
|
+
// Channel config
|
|
59
|
+
async probe(config: any) {
|
|
60
|
+
if (!config.apiKey) {
|
|
61
|
+
return { ok: false, error: "Missing apiKey" };
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const res = await fetch("https://www.clawtell.com/api/me", {
|
|
65
|
+
headers: { "Authorization": \`Bearer \${config.apiKey}\` }
|
|
66
|
+
});
|
|
67
|
+
if (!res.ok) return { ok: false, error: "Invalid API key" };
|
|
68
|
+
const data = await res.json();
|
|
69
|
+
return { ok: true, detail: \`Connected as tell/\${data.name}\` };
|
|
70
|
+
} catch (e: any) {
|
|
71
|
+
return { ok: false, error: e.message };
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// Send message
|
|
76
|
+
async send(config: any, message: any) {
|
|
77
|
+
const res = await fetch("https://www.clawtell.com/api/messages/send", {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: {
|
|
80
|
+
"Authorization": \`Bearer \${config.apiKey}\`,
|
|
81
|
+
"Content-Type": "application/json"
|
|
82
|
+
},
|
|
83
|
+
body: JSON.stringify({
|
|
84
|
+
to: message.to || config.name,
|
|
85
|
+
body: message.text || message.body,
|
|
86
|
+
subject: message.subject
|
|
87
|
+
})
|
|
88
|
+
});
|
|
89
|
+
if (!res.ok) throw new Error(\`Failed to send: \${res.status}\`);
|
|
90
|
+
return { ok: true };
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
// Poll for messages (if no webhook)
|
|
94
|
+
async poll(config: any, since?: Date) {
|
|
95
|
+
const res = await fetch(\`https://www.clawtell.com/api/messages/inbox?unread=true\`, {
|
|
96
|
+
headers: { "Authorization": \`Bearer \${config.apiKey}\` }
|
|
97
|
+
});
|
|
98
|
+
if (!res.ok) return [];
|
|
99
|
+
const data = await res.json();
|
|
100
|
+
return (data.messages || []).map((m: any) => ({
|
|
101
|
+
id: m.id,
|
|
102
|
+
from: m.from_name,
|
|
103
|
+
text: m.body,
|
|
104
|
+
timestamp: new Date(m.sent_at)
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export default plugin;
|
|
113
|
+
`;
|
|
114
|
+
function installPlugin() {
|
|
115
|
+
if (!fs.existsSync(CLAWDBOT_DIR)) {
|
|
116
|
+
console.log("\u2139\uFE0F Clawdbot not detected - skipping plugin install");
|
|
117
|
+
console.log(" To use with Clawdbot later, run: npx clawtell setup-clawdbot");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
console.log("\u{1F43E} Clawdbot detected! Installing ClawTell channel plugin...");
|
|
121
|
+
try {
|
|
122
|
+
if (!fs.existsSync(EXTENSIONS_DIR)) {
|
|
123
|
+
fs.mkdirSync(EXTENSIONS_DIR, { recursive: true });
|
|
124
|
+
}
|
|
125
|
+
if (!fs.existsSync(PLUGIN_DIR)) {
|
|
126
|
+
fs.mkdirSync(PLUGIN_DIR, { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
fs.writeFileSync(
|
|
129
|
+
path.join(PLUGIN_DIR, "clawdbot.plugin.json"),
|
|
130
|
+
JSON.stringify(PLUGIN_JSON, null, 2)
|
|
131
|
+
);
|
|
132
|
+
fs.writeFileSync(
|
|
133
|
+
path.join(PLUGIN_DIR, "index.ts"),
|
|
134
|
+
INDEX_TS
|
|
135
|
+
);
|
|
136
|
+
console.log("\u2705 ClawTell plugin installed to ~/.clawdbot/extensions/clawtell/");
|
|
137
|
+
console.log("");
|
|
138
|
+
console.log("\u{1F4DD} Add this to your Clawdbot config:");
|
|
139
|
+
console.log("");
|
|
140
|
+
console.log(" channels:");
|
|
141
|
+
console.log(" clawtell:");
|
|
142
|
+
console.log(" enabled: true");
|
|
143
|
+
console.log(' name: "YOUR_NAME"');
|
|
144
|
+
console.log(' apiKey: "claw_xxx_yyy"');
|
|
145
|
+
console.log("");
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error("\u26A0\uFE0F Failed to install Clawdbot plugin:", error.message);
|
|
148
|
+
console.log(" You can manually install later with: npx clawtell setup-clawdbot");
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
installPlugin();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dennisdamenace/clawtell",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Universal messaging SDK for AI agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"build": "tsup src/index.ts src/cli.ts --format cjs,esm --dts",
|
|
22
|
+
"build": "tsup src/index.ts src/cli.ts src/postinstall.ts --format cjs,esm --dts",
|
|
23
23
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
24
24
|
"test": "vitest",
|
|
25
25
|
"lint": "eslint src",
|
|
26
|
-
"prepublishOnly": "npm run build"
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"postinstall": "node dist/postinstall.js || true"
|
|
27
28
|
},
|
|
28
29
|
"keywords": [
|
|
29
30
|
"ai",
|