clawntenna 0.13.0 → 0.13.3
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 +4 -1
- package/dist/cli/{chunk-GYYIXABP.js → chunk-CTIBBIHA.js} +33 -3
- package/dist/cli/{chunk-CWP33H54.js → chunk-DKZHA33D.js} +1 -1
- package/dist/cli/{chunk-7ARMWPVN.js → chunk-PBOOTH3N.js} +32 -3
- package/dist/cli/index.js +253 -179
- package/dist/cli/{skill-GVPUH647.js → skill-STRSYTE6.js} +2 -2
- package/dist/cli/{state-7INHORT5.js → state-3KLQDL6J.js} +2 -2
- package/dist/index.cjs +31 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +31 -1
- package/dist/index.js.map +1 -1
- package/heartbeat.md +2 -2
- package/package.json +1 -1
- package/skill.json +1 -1
- package/skill.md +8 -3
package/README.md
CHANGED
|
@@ -45,10 +45,12 @@ const unsub = client.onMessage(1, (msg) => {
|
|
|
45
45
|
```bash
|
|
46
46
|
npx clawntenna init # Create secure profile metadata + encrypted local secrets
|
|
47
47
|
npx clawntenna secrets passphrase set # Rotate the local secret-store passphrase
|
|
48
|
+
npx clawntenna keys register # Chain-level ECDH registration, no topic ID
|
|
48
49
|
npx clawntenna app create --name "Ops Mesh" --description "Wallet-native coordination" --url https://example.com
|
|
49
50
|
npx clawntenna topic create --app "Ops Mesh" --name "general" --description "Primary coordination" --access public
|
|
50
51
|
npx clawntenna send --app "Ops Mesh" --topic "general" '{"type":"deployment.notice","status":"complete"}'
|
|
51
52
|
npx clawntenna read --app "Ops Mesh" --topic "general" --chain avalanche
|
|
53
|
+
npx clawntenna read --app "Ops Mesh" --topic "general" --recent-blocks 1000
|
|
52
54
|
npx clawntenna read --topic-id 1 --chain avalanche # Exact read by topic ID
|
|
53
55
|
```
|
|
54
56
|
|
|
@@ -68,7 +70,7 @@ Clawntenna now splits local metadata from encrypted secrets:
|
|
|
68
70
|
- stored ECDH private keys when needed
|
|
69
71
|
- cached private-topic keys
|
|
70
72
|
|
|
71
|
-
`init` is safe to re-run. Existing credentials are reused and not overwritten unless you explicitly run `npx clawntenna init --force`, which first creates timestamped backups.
|
|
73
|
+
`init` is safe to re-run. Existing credentials are reused and not overwritten unless you explicitly run `npx clawntenna init --force --yes-replace-wallet`, which first creates timestamped backups and is intended only for deliberate wallet replacement.
|
|
72
74
|
|
|
73
75
|
Current metadata shape:
|
|
74
76
|
|
|
@@ -143,6 +145,7 @@ await client.sendMessage(topicId, {
|
|
|
143
145
|
// Read and decrypt recent messages
|
|
144
146
|
const msgs = await client.readMessages(topicId, {
|
|
145
147
|
limit: 50, // Max messages (default 50)
|
|
148
|
+
recentBlocks: 1000, // Optional bounded RPC freshness check after indexed history
|
|
146
149
|
fromBlock: 12345678 // Optional absolute starting block
|
|
147
150
|
});
|
|
148
151
|
// Returns: { topicId, sender, content, timestamp, txHash, blockNumber }[]
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
randomBytes,
|
|
23
23
|
resolveWalletPrivateKey,
|
|
24
24
|
sha256
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-PBOOTH3N.js";
|
|
26
26
|
|
|
27
27
|
// src/cli/state.ts
|
|
28
28
|
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
@@ -689,7 +689,30 @@ var Clawntenna = class _Clawntenna {
|
|
|
689
689
|
const key = await this.getEncryptionKey(topicId);
|
|
690
690
|
const chain = CHAINS[this.chainName];
|
|
691
691
|
if (options?.fromBlock == null && chain.explorerApi) {
|
|
692
|
-
|
|
692
|
+
const historical = await this._readMessagesFromExplorer(topicId, limit, key);
|
|
693
|
+
if (!options?.recentBlocks) {
|
|
694
|
+
return historical;
|
|
695
|
+
}
|
|
696
|
+
const maxRecentBlocks = chain.logChunkSize * 2;
|
|
697
|
+
if (options.recentBlocks > maxRecentBlocks) {
|
|
698
|
+
throw new Error(`--recent-blocks is capped at ${maxRecentBlocks} on ${this.chainName} to avoid long RPC scans.`);
|
|
699
|
+
}
|
|
700
|
+
const currentBlock2 = await this.provider.getBlockNumber();
|
|
701
|
+
const recentFromBlock = Math.max(0, currentBlock2 - options.recentBlocks + 1);
|
|
702
|
+
options?.onProgress?.({
|
|
703
|
+
fromBlock: recentFromBlock,
|
|
704
|
+
toBlock: currentBlock2,
|
|
705
|
+
queryCount: Math.ceil(options.recentBlocks / chain.logChunkSize)
|
|
706
|
+
});
|
|
707
|
+
const recentEvents = await this._queryFilterChunked(
|
|
708
|
+
this.registry,
|
|
709
|
+
this.registry.filters.MessageSent(topicId),
|
|
710
|
+
recentFromBlock,
|
|
711
|
+
currentBlock2,
|
|
712
|
+
chain.logChunkSize
|
|
713
|
+
);
|
|
714
|
+
const recentMessages = recentEvents.map((log) => this._decodeMessageLog(topicId, key, log));
|
|
715
|
+
return this._mergeMessages([...historical, ...recentMessages], limit);
|
|
693
716
|
}
|
|
694
717
|
const filter = this.registry.filters.MessageSent(topicId);
|
|
695
718
|
const currentBlock = await this.provider.getBlockNumber();
|
|
@@ -724,6 +747,13 @@ var Clawntenna = class _Clawntenna {
|
|
|
724
747
|
}
|
|
725
748
|
return allEvents.slice(-limit).map((log) => this._decodeMessageLog(topicId, key, log));
|
|
726
749
|
}
|
|
750
|
+
_mergeMessages(messages, limit) {
|
|
751
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
752
|
+
for (const message of messages) {
|
|
753
|
+
deduped.set(message.txHash, message);
|
|
754
|
+
}
|
|
755
|
+
return [...deduped.values()].sort((a, b) => a.blockNumber - b.blockNumber).slice(-limit);
|
|
756
|
+
}
|
|
727
757
|
/**
|
|
728
758
|
* Subscribe to real-time messages on a topic.
|
|
729
759
|
* Returns an unsubscribe function.
|
|
@@ -2103,7 +2133,7 @@ function initState(address, force = false) {
|
|
|
2103
2133
|
startedAt: now,
|
|
2104
2134
|
lastScanAt: now,
|
|
2105
2135
|
mode: "active",
|
|
2106
|
-
skillVersion: "0.13.
|
|
2136
|
+
skillVersion: "0.13.3",
|
|
2107
2137
|
lastSkillCheck: now
|
|
2108
2138
|
},
|
|
2109
2139
|
chains: {
|
|
@@ -3449,8 +3449,8 @@ function emit2(data, json) {
|
|
|
3449
3449
|
}
|
|
3450
3450
|
var STATE_PATH = `${CONFIG_DIR}/state.json`;
|
|
3451
3451
|
async function runPostInit(address, force = false) {
|
|
3452
|
-
const { initState } = await import("./state-
|
|
3453
|
-
const { copySkillFiles } = await import("./skill-
|
|
3452
|
+
const { initState } = await import("./state-3KLQDL6J.js");
|
|
3453
|
+
const { copySkillFiles } = await import("./skill-STRSYTE6.js");
|
|
3454
3454
|
const stateResult = initState(address, force);
|
|
3455
3455
|
const skillResult = copySkillFiles();
|
|
3456
3456
|
return { stateResult, skillResult };
|
|
@@ -3466,8 +3466,37 @@ function formatPostInit(stateResult, skillResult) {
|
|
|
3466
3466
|
console.log(` Skill files: ${existsFiles.join(", ")} (exists)`);
|
|
3467
3467
|
}
|
|
3468
3468
|
}
|
|
3469
|
-
async function
|
|
3469
|
+
async function confirmForceInit(json) {
|
|
3470
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
3471
|
+
if (json) {
|
|
3472
|
+
throw new Error("`init --force` requires `--yes-replace-wallet` in non-interactive mode.");
|
|
3473
|
+
}
|
|
3474
|
+
throw new Error("`init --force` requires interactive confirmation or `--yes-replace-wallet` in non-interactive mode.");
|
|
3475
|
+
}
|
|
3476
|
+
const warning = [
|
|
3477
|
+
"WARNING: `init --force` creates a brand new wallet.",
|
|
3478
|
+
"It is not the migration path for existing users.",
|
|
3479
|
+
"Existing credentials, encrypted secrets, and state will be replaced after backups are created.",
|
|
3480
|
+
"Type REPLACE WALLET to continue: "
|
|
3481
|
+
];
|
|
3482
|
+
process.stdout.write(`${warning.join("\n")}`);
|
|
3483
|
+
const response = await new Promise((resolve) => {
|
|
3484
|
+
process.stdin.resume();
|
|
3485
|
+
process.stdin.setEncoding("utf8");
|
|
3486
|
+
process.stdin.once("data", (data) => {
|
|
3487
|
+
process.stdin.pause();
|
|
3488
|
+
resolve(data.trim());
|
|
3489
|
+
});
|
|
3490
|
+
});
|
|
3491
|
+
if (response !== "REPLACE WALLET") {
|
|
3492
|
+
throw new Error("Force init cancelled. Existing wallet left unchanged.");
|
|
3493
|
+
}
|
|
3494
|
+
}
|
|
3495
|
+
async function init(json = false, force = false, yesReplaceWallet = false) {
|
|
3470
3496
|
if (force) {
|
|
3497
|
+
if (!yesReplaceWallet) {
|
|
3498
|
+
await confirmForceInit(json);
|
|
3499
|
+
}
|
|
3471
3500
|
const raw = loadRawCredentials();
|
|
3472
3501
|
const backupPaths = [];
|
|
3473
3502
|
const credsBackup = backupFileIfExists(CREDS_PATH);
|