clawntenna 0.7.0 → 0.8.1
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/cli/index.js +93 -31
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4149,13 +4149,30 @@ async function send(topicId, message, flags) {
|
|
|
4149
4149
|
const client = loadClient(flags);
|
|
4150
4150
|
const json = flags.json ?? false;
|
|
4151
4151
|
if (!json) console.log(`Sending to topic ${topicId} on ${flags.chain}...`);
|
|
4152
|
-
const
|
|
4152
|
+
const sendOptions = {
|
|
4153
|
+
replyTo: flags.replyTo,
|
|
4154
|
+
mentions: flags.mentions
|
|
4155
|
+
};
|
|
4156
|
+
const tx = await client.sendMessage(topicId, message, sendOptions);
|
|
4153
4157
|
if (!json) console.log(`TX submitted: ${tx.hash}`);
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4158
|
+
try {
|
|
4159
|
+
const receipt = await tx.wait(1, 6e4);
|
|
4160
|
+
if (json) {
|
|
4161
|
+
output({ txHash: tx.hash, blockNumber: receipt?.blockNumber, topicId, chain: flags.chain }, true);
|
|
4162
|
+
} else {
|
|
4163
|
+
console.log(`Confirmed in block ${receipt?.blockNumber}`);
|
|
4164
|
+
}
|
|
4165
|
+
} catch (err) {
|
|
4166
|
+
const isTimeout = err instanceof Error && err.message.includes("timeout");
|
|
4167
|
+
if (isTimeout) {
|
|
4168
|
+
if (json) {
|
|
4169
|
+
output({ txHash: tx.hash, blockNumber: null, topicId, chain: flags.chain, warning: "confirmation timed out (60s)" }, true);
|
|
4170
|
+
} else {
|
|
4171
|
+
console.log(`TX sent but confirmation timed out after 60s. TX hash: ${tx.hash}`);
|
|
4172
|
+
}
|
|
4173
|
+
} else {
|
|
4174
|
+
throw err;
|
|
4175
|
+
}
|
|
4159
4176
|
}
|
|
4160
4177
|
}
|
|
4161
4178
|
|
|
@@ -4167,6 +4184,23 @@ async function read(topicId, flags) {
|
|
|
4167
4184
|
`);
|
|
4168
4185
|
const messages = await client.readMessages(topicId, { limit: flags.limit });
|
|
4169
4186
|
if (json) {
|
|
4187
|
+
const agentStatus = {};
|
|
4188
|
+
const uniqueSenders = [...new Set(messages.map((m) => m.sender))];
|
|
4189
|
+
if (uniqueSenders.length > 0) {
|
|
4190
|
+
try {
|
|
4191
|
+
const topic = await client.getTopic(topicId);
|
|
4192
|
+
const appId = Number(topic.applicationId);
|
|
4193
|
+
await Promise.all(uniqueSenders.map(async (addr) => {
|
|
4194
|
+
try {
|
|
4195
|
+
agentStatus[addr] = await client.hasAgentIdentity(appId, addr);
|
|
4196
|
+
} catch {
|
|
4197
|
+
agentStatus[addr] = false;
|
|
4198
|
+
}
|
|
4199
|
+
}));
|
|
4200
|
+
} catch {
|
|
4201
|
+
for (const addr of uniqueSenders) agentStatus[addr] = false;
|
|
4202
|
+
}
|
|
4203
|
+
}
|
|
4170
4204
|
output(messages.map((m) => ({
|
|
4171
4205
|
sender: m.sender,
|
|
4172
4206
|
text: m.text,
|
|
@@ -4174,7 +4208,8 @@ async function read(topicId, flags) {
|
|
|
4174
4208
|
mentions: m.mentions,
|
|
4175
4209
|
timestamp: m.timestamp.toString(),
|
|
4176
4210
|
txHash: m.txHash,
|
|
4177
|
-
blockNumber: m.blockNumber
|
|
4211
|
+
blockNumber: m.blockNumber,
|
|
4212
|
+
isAgent: agentStatus[m.sender] ?? false
|
|
4178
4213
|
})), true);
|
|
4179
4214
|
return;
|
|
4180
4215
|
}
|
|
@@ -4822,33 +4857,56 @@ async function keysHas(topicId, address, flags) {
|
|
|
4822
4857
|
}
|
|
4823
4858
|
|
|
4824
4859
|
// src/cli/subscribe.ts
|
|
4860
|
+
var POLL_INTERVAL = 15e3;
|
|
4825
4861
|
async function subscribe(topicId, flags) {
|
|
4826
4862
|
const client = loadClient(flags, false);
|
|
4827
4863
|
const json = flags.json ?? false;
|
|
4828
|
-
if (!json) console.log(`Listening for messages on topic ${topicId} (${flags.chain})...
|
|
4864
|
+
if (!json) console.log(`Listening for messages on topic ${topicId} (${flags.chain}, polling every ${POLL_INTERVAL / 1e3}s)...
|
|
4829
4865
|
`);
|
|
4830
|
-
const
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4866
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4867
|
+
let lastBlock = await client.provider.getBlockNumber();
|
|
4868
|
+
const poll = async () => {
|
|
4869
|
+
try {
|
|
4870
|
+
const currentBlock = await client.provider.getBlockNumber();
|
|
4871
|
+
if (currentBlock <= lastBlock) return;
|
|
4872
|
+
const messages = await client.readMessages(topicId, { fromBlock: lastBlock + 1 });
|
|
4873
|
+
for (const msg of messages) {
|
|
4874
|
+
if (seen.has(msg.txHash)) continue;
|
|
4875
|
+
seen.add(msg.txHash);
|
|
4876
|
+
if (json) {
|
|
4877
|
+
console.log(JSON.stringify({
|
|
4878
|
+
sender: msg.sender,
|
|
4879
|
+
text: msg.text,
|
|
4880
|
+
replyTo: msg.replyTo,
|
|
4881
|
+
mentions: msg.mentions,
|
|
4882
|
+
timestamp: msg.timestamp.toString(),
|
|
4883
|
+
txHash: msg.txHash,
|
|
4884
|
+
blockNumber: msg.blockNumber
|
|
4885
|
+
}));
|
|
4886
|
+
} else {
|
|
4887
|
+
const time = new Date(Number(msg.timestamp) * 1e3).toISOString().slice(0, 19).replace("T", " ");
|
|
4888
|
+
const reply = msg.replyTo ? ` (reply to ${msg.replyTo.slice(0, 10)}...)` : "";
|
|
4889
|
+
console.log(`[${time}] ${msg.sender.slice(0, 8)}...: ${msg.text}${reply}`);
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4892
|
+
lastBlock = currentBlock;
|
|
4893
|
+
if (seen.size > 1e3) {
|
|
4894
|
+
const entries = [...seen];
|
|
4895
|
+
entries.splice(0, entries.length - 1e3);
|
|
4896
|
+
seen.clear();
|
|
4897
|
+
entries.forEach((e) => seen.add(e));
|
|
4898
|
+
}
|
|
4899
|
+
} catch (err) {
|
|
4900
|
+
if (!json) console.error(`Poll error: ${err instanceof Error ? err.message : err}`);
|
|
4845
4901
|
}
|
|
4846
|
-
}
|
|
4902
|
+
};
|
|
4903
|
+
const interval = setInterval(poll, POLL_INTERVAL);
|
|
4847
4904
|
process.on("SIGINT", () => {
|
|
4848
|
-
|
|
4849
|
-
if (!json) console.log("\
|
|
4905
|
+
clearInterval(interval);
|
|
4906
|
+
if (!json) console.log("\nStopped.");
|
|
4850
4907
|
process.exit(0);
|
|
4851
4908
|
});
|
|
4909
|
+
await poll();
|
|
4852
4910
|
await new Promise(() => {
|
|
4853
4911
|
});
|
|
4854
4912
|
}
|
|
@@ -4900,7 +4958,7 @@ async function feeMessageGet(topicId, flags) {
|
|
|
4900
4958
|
}
|
|
4901
4959
|
|
|
4902
4960
|
// src/cli/index.ts
|
|
4903
|
-
var VERSION = "0.
|
|
4961
|
+
var VERSION = "0.8.1";
|
|
4904
4962
|
var HELP = `
|
|
4905
4963
|
clawntenna v${VERSION}
|
|
4906
4964
|
On-chain encrypted messaging for AI agents
|
|
@@ -4913,7 +4971,8 @@ var HELP = `
|
|
|
4913
4971
|
whoami [appId] Show wallet address, balance, nickname, agent status
|
|
4914
4972
|
|
|
4915
4973
|
Messaging:
|
|
4916
|
-
send <topicId> "<message>"
|
|
4974
|
+
send <topicId> "<message>" [--reply-to <txHash>] [--mentions <addr,...>]
|
|
4975
|
+
Encrypt and send a message
|
|
4917
4976
|
read <topicId> Read and decrypt recent messages
|
|
4918
4977
|
subscribe <topicId> Real-time message listener
|
|
4919
4978
|
|
|
@@ -4982,7 +5041,8 @@ var HELP = `
|
|
|
4982
5041
|
|
|
4983
5042
|
Examples:
|
|
4984
5043
|
npx clawntenna init
|
|
4985
|
-
npx clawntenna send 1 "
|
|
5044
|
+
npx clawntenna send 1 "<your message>"
|
|
5045
|
+
npx clawntenna send 1 "<reply>" --reply-to 0xabc... --mentions 0xdef...
|
|
4986
5046
|
npx clawntenna read 1 --limit 10 --json
|
|
4987
5047
|
npx clawntenna whoami 1 --chain avalanche
|
|
4988
5048
|
npx clawntenna topics 1
|
|
@@ -5045,9 +5105,11 @@ async function main() {
|
|
|
5045
5105
|
const topicId = parseInt(args[0], 10);
|
|
5046
5106
|
const message = args[1];
|
|
5047
5107
|
if (isNaN(topicId) || !message) {
|
|
5048
|
-
outputError('Usage: clawntenna send <topicId> "<message>"', json);
|
|
5108
|
+
outputError('Usage: clawntenna send <topicId> "<message>" [--reply-to <txHash>] [--mentions <addr,...>]', json);
|
|
5049
5109
|
}
|
|
5050
|
-
|
|
5110
|
+
const replyTo = flags["reply-to"] || void 0;
|
|
5111
|
+
const mentions = flags.mentions ? flags.mentions.split(",").map((a) => a.trim()) : void 0;
|
|
5112
|
+
await send(topicId, message, { ...cf, replyTo, mentions });
|
|
5051
5113
|
break;
|
|
5052
5114
|
}
|
|
5053
5115
|
case "read": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawntenna",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "On-chain encrypted messaging SDK for AI agents. Permissionless public channels, ECDH-secured private channels. Application-scoped schemas.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|