@totalreclaw/totalreclaw 3.3.12-rc.2 → 3.3.12-rc.21
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/CHANGELOG.md +26 -0
- package/SKILL.md +34 -249
- package/api-client.ts +17 -9
- package/batch-gate.ts +42 -0
- package/billing-cache.ts +25 -20
- package/claims-helper.ts +7 -1
- package/config.ts +54 -12
- package/consolidation.ts +6 -13
- package/contradiction-sync.ts +19 -14
- package/credential-provider.ts +184 -0
- package/crypto.ts +27 -160
- package/dist/api-client.js +17 -9
- package/dist/batch-gate.js +40 -0
- package/dist/billing-cache.js +19 -21
- package/dist/claims-helper.js +7 -1
- package/dist/config.js +54 -12
- package/dist/consolidation.js +6 -15
- package/dist/contradiction-sync.js +15 -15
- package/dist/credential-provider.js +145 -0
- package/dist/crypto.js +17 -137
- package/dist/download-ux.js +11 -7
- package/dist/embedder-loader.js +266 -0
- package/dist/embedding.js +36 -3
- package/dist/entry.js +123 -0
- package/dist/extractor.js +134 -0
- package/dist/fs-helpers.js +116 -241
- package/dist/import-adapters/chatgpt-adapter.js +14 -0
- package/dist/import-adapters/claude-adapter.js +14 -0
- package/dist/import-adapters/gemini-adapter.js +43 -159
- package/dist/import-adapters/mcp-memory-adapter.js +14 -0
- package/dist/import-state-manager.js +100 -0
- package/dist/index.js +1130 -2520
- package/dist/llm-client.js +69 -1
- package/dist/memory-runtime.js +459 -0
- package/dist/native-memory.js +123 -0
- package/dist/onboarding-cli.js +3 -2
- package/dist/pair-cli.js +1 -1
- package/dist/pair-crypto.js +16 -358
- package/dist/pair-http.js +147 -4
- package/dist/relay.js +140 -0
- package/dist/reranker.js +13 -8
- package/dist/semantic-dedup.js +5 -7
- package/dist/skill-register.js +97 -0
- package/dist/subgraph-search.js +3 -1
- package/dist/subgraph-store.js +315 -282
- package/dist/tool-gating.js +39 -26
- package/dist/tools.js +367 -0
- package/dist/tr-cli-export-helper.js +103 -0
- package/dist/tr-cli.js +220 -127
- package/dist/trajectory-poller.js +155 -9
- package/dist/vault-crypto.js +551 -0
- package/download-ux.ts +12 -6
- package/embedder-loader.ts +293 -1
- package/embedding.ts +43 -3
- package/entry.ts +132 -0
- package/extractor.ts +167 -0
- package/fs-helpers.ts +166 -292
- package/import-adapters/chatgpt-adapter.ts +18 -0
- package/import-adapters/claude-adapter.ts +18 -0
- package/import-adapters/gemini-adapter.ts +56 -183
- package/import-adapters/mcp-memory-adapter.ts +18 -0
- package/import-adapters/types.ts +1 -1
- package/import-state-manager.ts +139 -0
- package/index.ts +1432 -3002
- package/llm-client.ts +74 -1
- package/memory-runtime.ts +723 -0
- package/native-memory.ts +196 -0
- package/onboarding-cli.ts +3 -2
- package/openclaw.plugin.json +5 -17
- package/package.json +7 -4
- package/pair-cli.ts +1 -1
- package/pair-crypto.ts +41 -483
- package/pair-http.ts +194 -5
- package/postinstall.mjs +138 -0
- package/relay.ts +172 -0
- package/reranker.ts +13 -8
- package/semantic-dedup.ts +5 -6
- package/skill-register.ts +146 -0
- package/skill.json +1 -1
- package/subgraph-search.ts +3 -1
- package/subgraph-store.ts +334 -299
- package/tool-gating.ts +39 -26
- package/tools.ts +499 -0
- package/tr-cli-export-helper.ts +138 -0
- package/tr-cli.ts +263 -133
- package/trajectory-poller.ts +162 -10
- package/vault-crypto.ts +705 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tr-cli-export-helper.ts
|
|
3
|
+
*
|
|
4
|
+
* Helper module for `tr export` — paginates through the subgraph and
|
|
5
|
+
* decrypts every active fact owned by the caller's Smart Account address.
|
|
6
|
+
*
|
|
7
|
+
* Lives in its own file because tr-cli.ts already contains a synchronous
|
|
8
|
+
* disk read (status command reads credentials.json + onboarding state), and
|
|
9
|
+
* combining that with outbound HTTP in the same file would trip the
|
|
10
|
+
* OpenClaw skill scanner's exfil rule (see ../scripts/check-scanner.mjs).
|
|
11
|
+
*
|
|
12
|
+
* Phrase-safety: this module never touches the recovery phrase. It receives
|
|
13
|
+
* pre-derived auth-key + wallet-address + encryption-key from the caller.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { CONFIG } from './config.js';
|
|
17
|
+
import { buildRelayHeaders } from './relay-headers.js';
|
|
18
|
+
import { decrypt } from './crypto.js';
|
|
19
|
+
|
|
20
|
+
/** Decode a hex blob written by submitFactBatchOnChain back to plaintext. */
|
|
21
|
+
function fromHexBlob(hexBlob: string, encryptionKey: Buffer): string {
|
|
22
|
+
const hex = hexBlob.startsWith('0x') ? hexBlob.slice(2) : hexBlob;
|
|
23
|
+
const b64 = Buffer.from(hex, 'hex').toString('base64');
|
|
24
|
+
return decrypt(b64, encryptionKey);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface FactRow {
|
|
28
|
+
id: string;
|
|
29
|
+
encryptedBlob: string;
|
|
30
|
+
timestamp: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ExportedFact {
|
|
34
|
+
id: string;
|
|
35
|
+
text: string;
|
|
36
|
+
metadata: Record<string, unknown>;
|
|
37
|
+
created_at: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Pull every active fact for `walletAddress` from the subgraph, decrypt
|
|
42
|
+
* each blob, and return a flat array sorted in subgraph-cursor order.
|
|
43
|
+
*
|
|
44
|
+
* Uses /v1/subgraph relay endpoint with cursor-based pagination (id_gt).
|
|
45
|
+
* Mirrors the totalreclaw_export native tool path (index.ts:4352-4415).
|
|
46
|
+
*/
|
|
47
|
+
export async function exportAllFacts(
|
|
48
|
+
walletAddress: string,
|
|
49
|
+
authKeyHex: string,
|
|
50
|
+
encryptionKey: Buffer,
|
|
51
|
+
): Promise<ExportedFact[]> {
|
|
52
|
+
const relayUrl = CONFIG.serverUrl || 'https://api.totalreclaw.xyz';
|
|
53
|
+
const subgraphUrl = `${relayUrl}/v1/subgraph`;
|
|
54
|
+
const PAGE_SIZE = 1000;
|
|
55
|
+
|
|
56
|
+
async function gql<T>(
|
|
57
|
+
query: string,
|
|
58
|
+
variables: Record<string, unknown>,
|
|
59
|
+
): Promise<T | null> {
|
|
60
|
+
try {
|
|
61
|
+
const resp = await fetch(subgraphUrl, {
|
|
62
|
+
method: 'POST',
|
|
63
|
+
headers: buildRelayHeaders({
|
|
64
|
+
'Content-Type': 'application/json',
|
|
65
|
+
Authorization: `Bearer ${authKeyHex}`,
|
|
66
|
+
}),
|
|
67
|
+
body: JSON.stringify({ query, variables }),
|
|
68
|
+
});
|
|
69
|
+
if (!resp.ok) {
|
|
70
|
+
const body = await resp.text().catch(() => '');
|
|
71
|
+
process.stderr.write(
|
|
72
|
+
`[warn] subgraph HTTP ${resp.status}: ${body.slice(0, 200)}\n`,
|
|
73
|
+
);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const json = (await resp.json()) as {
|
|
77
|
+
data?: T;
|
|
78
|
+
errors?: Array<{ message: string }>;
|
|
79
|
+
};
|
|
80
|
+
if (json.errors) {
|
|
81
|
+
process.stderr.write(
|
|
82
|
+
`[warn] subgraph errors: ${json.errors
|
|
83
|
+
.map((e) => e.message)
|
|
84
|
+
.join('; ')}\n`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
return json.data ?? null;
|
|
88
|
+
} catch (err) {
|
|
89
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
90
|
+
process.stderr.write(`[warn] subgraph request failed: ${msg}\n`);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const allFacts: ExportedFact[] = [];
|
|
96
|
+
let lastId = '';
|
|
97
|
+
|
|
98
|
+
while (true) {
|
|
99
|
+
const hasLastId = lastId !== '';
|
|
100
|
+
const query = hasLastId
|
|
101
|
+
? `query($owner:Bytes!,$first:Int!,$lastId:String!){facts(where:{owner:$owner,isActive:true,id_gt:$lastId},first:$first,orderBy:id,orderDirection:asc){id encryptedBlob timestamp}}`
|
|
102
|
+
: `query($owner:Bytes!,$first:Int!){facts(where:{owner:$owner,isActive:true},first:$first,orderBy:id,orderDirection:asc){id encryptedBlob timestamp}}`;
|
|
103
|
+
const variables: Record<string, unknown> = hasLastId
|
|
104
|
+
? { owner: walletAddress, first: PAGE_SIZE, lastId }
|
|
105
|
+
: { owner: walletAddress, first: PAGE_SIZE };
|
|
106
|
+
|
|
107
|
+
const data = await gql<{ facts?: FactRow[] }>(query, variables);
|
|
108
|
+
const facts = data?.facts ?? [];
|
|
109
|
+
if (facts.length === 0) break;
|
|
110
|
+
|
|
111
|
+
for (const f of facts) {
|
|
112
|
+
try {
|
|
113
|
+
const docJson = fromHexBlob(f.encryptedBlob, encryptionKey);
|
|
114
|
+
const parsed = JSON.parse(docJson) as {
|
|
115
|
+
text?: string;
|
|
116
|
+
metadata?: Record<string, unknown>;
|
|
117
|
+
};
|
|
118
|
+
if (!parsed.text) continue; // skip digests / tombstones
|
|
119
|
+
const created = parseInt(f.timestamp, 10);
|
|
120
|
+
allFacts.push({
|
|
121
|
+
id: f.id,
|
|
122
|
+
text: parsed.text,
|
|
123
|
+
metadata: parsed.metadata ?? {},
|
|
124
|
+
created_at: Number.isFinite(created)
|
|
125
|
+
? new Date(created * 1000).toISOString()
|
|
126
|
+
: new Date(0).toISOString(),
|
|
127
|
+
});
|
|
128
|
+
} catch {
|
|
129
|
+
// Skip undecryptable facts
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (facts.length < PAGE_SIZE) break;
|
|
134
|
+
lastId = facts[facts.length - 1].id;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return allFacts;
|
|
138
|
+
}
|