@clude/sdk 3.0.3 → 3.2.0
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 +1 -1
- package/dist/cli/index.js +2284 -157
- package/dist/mcp/server.js +515 -27
- package/dist/sdk/index.js +517 -29
- package/package.json +8 -10
- package/supabase-schema.sql +107 -0
package/dist/sdk/index.js
CHANGED
|
@@ -348,13 +348,18 @@ async function initDatabase() {
|
|
|
348
348
|
is_active BOOLEAN DEFAULT TRUE,
|
|
349
349
|
metadata JSONB DEFAULT '{}',
|
|
350
350
|
owner_wallet TEXT,
|
|
351
|
-
privy_did TEXT
|
|
351
|
+
privy_did TEXT,
|
|
352
|
+
email TEXT
|
|
352
353
|
);
|
|
353
354
|
|
|
355
|
+
-- Backfill: older deployments may have agent_keys without the email column.
|
|
356
|
+
ALTER TABLE agent_keys ADD COLUMN IF NOT EXISTS email TEXT;
|
|
357
|
+
|
|
354
358
|
CREATE INDEX IF NOT EXISTS idx_agent_keys_api_key ON agent_keys(api_key);
|
|
355
359
|
CREATE INDEX IF NOT EXISTS idx_agent_keys_owner ON agent_keys(owner_wallet);
|
|
356
360
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_keys_owner_unique ON agent_keys(owner_wallet) WHERE owner_wallet IS NOT NULL;
|
|
357
361
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_keys_privy_did ON agent_keys(privy_did) WHERE privy_did IS NOT NULL;
|
|
362
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_keys_email ON agent_keys(email) WHERE email IS NOT NULL AND is_active = true;
|
|
358
363
|
|
|
359
364
|
-- Cortex recall performance: owner_wallet scoped queries
|
|
360
365
|
CREATE INDEX IF NOT EXISTS idx_cortex_owner_recall ON memories(owner_wallet, decay_factor DESC, created_at DESC);
|
|
@@ -788,6 +793,19 @@ async function initDatabase() {
|
|
|
788
793
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
789
794
|
);
|
|
790
795
|
CREATE INDEX IF NOT EXISTS idx_chat_usage_wallet ON chat_usage(wallet_address, created_at DESC);
|
|
796
|
+
|
|
797
|
+
-- Wiki pack installations: which packs (Workspace, Compliance, Sales)
|
|
798
|
+
-- each wallet has installed. Drives the topic rail in /wiki and
|
|
799
|
+
-- the auto-categorisation rules applied to incoming memories.
|
|
800
|
+
CREATE TABLE IF NOT EXISTS wiki_pack_installations (
|
|
801
|
+
id BIGSERIAL PRIMARY KEY,
|
|
802
|
+
owner_wallet TEXT NOT NULL,
|
|
803
|
+
pack_id TEXT NOT NULL,
|
|
804
|
+
installed_at TIMESTAMPTZ DEFAULT NOW(),
|
|
805
|
+
UNIQUE (owner_wallet, pack_id)
|
|
806
|
+
);
|
|
807
|
+
CREATE INDEX IF NOT EXISTS idx_wiki_pack_installations_owner
|
|
808
|
+
ON wiki_pack_installations(owner_wallet);
|
|
791
809
|
`
|
|
792
810
|
});
|
|
793
811
|
if (error) {
|
|
@@ -1050,11 +1068,13 @@ var init_openrouter_client = __esm({
|
|
|
1050
1068
|
OPENROUTER_API_URL = "https://openrouter.ai/api/v1";
|
|
1051
1069
|
OPENROUTER_MODELS = {
|
|
1052
1070
|
// Frontier (Anthropic)
|
|
1071
|
+
"claude-opus-4.7": "anthropic/claude-opus-4.7",
|
|
1053
1072
|
"claude-opus-4.6": "anthropic/claude-opus-4.6",
|
|
1054
1073
|
"claude-sonnet-4.6": "anthropic/claude-sonnet-4.6",
|
|
1055
1074
|
"claude-opus-4.5": "anthropic/claude-opus-4.5",
|
|
1056
1075
|
"claude-sonnet-4.5": "anthropic/claude-sonnet-4.5",
|
|
1057
1076
|
// Frontier (Other providers)
|
|
1077
|
+
"gpt-5.5": "openai/gpt-5.5",
|
|
1058
1078
|
"gpt-5.4": "openai/gpt-5.4",
|
|
1059
1079
|
"grok-4.1": "x-ai/grok-4.1-fast",
|
|
1060
1080
|
"gemini-3-pro": "google/gemini-3-pro-preview",
|
|
@@ -1674,8 +1694,8 @@ function deriveRegistryPDA(authority) {
|
|
|
1674
1694
|
);
|
|
1675
1695
|
}
|
|
1676
1696
|
function anchorDiscriminator(name) {
|
|
1677
|
-
const { createHash:
|
|
1678
|
-
const hash =
|
|
1697
|
+
const { createHash: createHash3 } = require("crypto");
|
|
1698
|
+
const hash = createHash3("sha256").update(`global:${name}`).digest();
|
|
1679
1699
|
return hash.subarray(0, 8);
|
|
1680
1700
|
}
|
|
1681
1701
|
async function initializeRegistry() {
|
|
@@ -1890,6 +1910,335 @@ var init_utils = __esm({
|
|
|
1890
1910
|
}
|
|
1891
1911
|
});
|
|
1892
1912
|
|
|
1913
|
+
// packages/tokenization/src/content-hash.ts
|
|
1914
|
+
function stableStringify(value) {
|
|
1915
|
+
if (value === null) return "null";
|
|
1916
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1917
|
+
return JSON.stringify(value);
|
|
1918
|
+
}
|
|
1919
|
+
if (Array.isArray(value)) {
|
|
1920
|
+
return "[" + value.map(stableStringify).join(",") + "]";
|
|
1921
|
+
}
|
|
1922
|
+
if (typeof value === "object") {
|
|
1923
|
+
const obj = value;
|
|
1924
|
+
const keys = Object.keys(obj).sort();
|
|
1925
|
+
const pairs = keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k]));
|
|
1926
|
+
return "{" + pairs.join(",") + "}";
|
|
1927
|
+
}
|
|
1928
|
+
throw new Error(`stableStringify: unsupported value of type ${typeof value}`);
|
|
1929
|
+
}
|
|
1930
|
+
function normaliseString(s) {
|
|
1931
|
+
return s.normalize("NFC").trim();
|
|
1932
|
+
}
|
|
1933
|
+
function normaliseNullable(s) {
|
|
1934
|
+
return s === null ? null : normaliseString(s);
|
|
1935
|
+
}
|
|
1936
|
+
function normaliseTags(tags) {
|
|
1937
|
+
const trimmed = tags.map(normaliseString).filter((t) => t.length > 0);
|
|
1938
|
+
return Array.from(new Set(trimmed)).sort();
|
|
1939
|
+
}
|
|
1940
|
+
function canonicaliseMemory(input) {
|
|
1941
|
+
const normalised = {
|
|
1942
|
+
algorithm: HASH_ALGORITHM,
|
|
1943
|
+
content: normaliseString(input.content),
|
|
1944
|
+
created_at: input.created_at,
|
|
1945
|
+
memory_type: input.memory_type,
|
|
1946
|
+
owner_wallet: normaliseNullable(input.owner_wallet),
|
|
1947
|
+
related_user: normaliseNullable(input.related_user),
|
|
1948
|
+
related_wallet: normaliseNullable(input.related_wallet),
|
|
1949
|
+
source: normaliseNullable(input.source),
|
|
1950
|
+
tags: normaliseTags(input.tags)
|
|
1951
|
+
};
|
|
1952
|
+
return stableStringify(normalised);
|
|
1953
|
+
}
|
|
1954
|
+
function memoryContentHash(input) {
|
|
1955
|
+
return (0, import_node_crypto.createHash)("sha256").update(canonicaliseMemory(input), "utf8").digest("hex");
|
|
1956
|
+
}
|
|
1957
|
+
var import_node_crypto, HASH_ALGORITHM;
|
|
1958
|
+
var init_content_hash = __esm({
|
|
1959
|
+
"packages/tokenization/src/content-hash.ts"() {
|
|
1960
|
+
"use strict";
|
|
1961
|
+
import_node_crypto = require("node:crypto");
|
|
1962
|
+
HASH_ALGORITHM = "memory-hash-v1";
|
|
1963
|
+
}
|
|
1964
|
+
});
|
|
1965
|
+
|
|
1966
|
+
// packages/tokenization/src/pack-merkle.ts
|
|
1967
|
+
var init_pack_merkle = __esm({
|
|
1968
|
+
"packages/tokenization/src/pack-merkle.ts"() {
|
|
1969
|
+
"use strict";
|
|
1970
|
+
}
|
|
1971
|
+
});
|
|
1972
|
+
|
|
1973
|
+
// packages/tokenization/src/mint-client.ts
|
|
1974
|
+
var init_mint_client = __esm({
|
|
1975
|
+
"packages/tokenization/src/mint-client.ts"() {
|
|
1976
|
+
"use strict";
|
|
1977
|
+
}
|
|
1978
|
+
});
|
|
1979
|
+
|
|
1980
|
+
// packages/tokenization/src/tokenize-memory.ts
|
|
1981
|
+
var init_tokenize_memory = __esm({
|
|
1982
|
+
"packages/tokenization/src/tokenize-memory.ts"() {
|
|
1983
|
+
"use strict";
|
|
1984
|
+
init_content_hash();
|
|
1985
|
+
}
|
|
1986
|
+
});
|
|
1987
|
+
|
|
1988
|
+
// packages/tokenization/src/tokenize-batch.ts
|
|
1989
|
+
var init_tokenize_batch = __esm({
|
|
1990
|
+
"packages/tokenization/src/tokenize-batch.ts"() {
|
|
1991
|
+
"use strict";
|
|
1992
|
+
init_content_hash();
|
|
1993
|
+
init_pack_merkle();
|
|
1994
|
+
}
|
|
1995
|
+
});
|
|
1996
|
+
|
|
1997
|
+
// packages/tokenization/src/tokenize-pack.ts
|
|
1998
|
+
var init_tokenize_pack = __esm({
|
|
1999
|
+
"packages/tokenization/src/tokenize-pack.ts"() {
|
|
2000
|
+
"use strict";
|
|
2001
|
+
init_pack_merkle();
|
|
2002
|
+
}
|
|
2003
|
+
});
|
|
2004
|
+
|
|
2005
|
+
// packages/tokenization/src/verify.ts
|
|
2006
|
+
var init_verify = __esm({
|
|
2007
|
+
"packages/tokenization/src/verify.ts"() {
|
|
2008
|
+
"use strict";
|
|
2009
|
+
init_pack_merkle();
|
|
2010
|
+
}
|
|
2011
|
+
});
|
|
2012
|
+
|
|
2013
|
+
// packages/tokenization/src/index.ts
|
|
2014
|
+
var init_src = __esm({
|
|
2015
|
+
"packages/tokenization/src/index.ts"() {
|
|
2016
|
+
"use strict";
|
|
2017
|
+
init_content_hash();
|
|
2018
|
+
init_pack_merkle();
|
|
2019
|
+
init_mint_client();
|
|
2020
|
+
init_tokenize_memory();
|
|
2021
|
+
init_tokenize_batch();
|
|
2022
|
+
init_tokenize_pack();
|
|
2023
|
+
init_verify();
|
|
2024
|
+
}
|
|
2025
|
+
});
|
|
2026
|
+
|
|
2027
|
+
// packages/shared/src/wiki-packs.ts
|
|
2028
|
+
function getPackManifest(id) {
|
|
2029
|
+
return ALL_PACK_MANIFESTS.find((p) => p.id === id);
|
|
2030
|
+
}
|
|
2031
|
+
function matchesKeyword(text, phrase) {
|
|
2032
|
+
if (!phrase) return false;
|
|
2033
|
+
const escaped = phrase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2034
|
+
const re = new RegExp(`(?<![\\w-])${escaped}(?![\\w-])`, "i");
|
|
2035
|
+
return re.test(text);
|
|
2036
|
+
}
|
|
2037
|
+
function autoCategorizeTags(opts) {
|
|
2038
|
+
const haystack = [
|
|
2039
|
+
opts.content || "",
|
|
2040
|
+
opts.summary || "",
|
|
2041
|
+
...opts.existingTags || []
|
|
2042
|
+
].join(" ");
|
|
2043
|
+
const matched = new Set(opts.existingTags || []);
|
|
2044
|
+
const ids = /* @__PURE__ */ new Set([DEFAULT_PACK_ID, ...opts.installedPackIds]);
|
|
2045
|
+
for (const packId of ids) {
|
|
2046
|
+
const pack = getPackManifest(packId);
|
|
2047
|
+
if (!pack) continue;
|
|
2048
|
+
for (const rule of pack.rules) {
|
|
2049
|
+
if (matched.has(rule.topicId)) continue;
|
|
2050
|
+
const hasMatch = rule.keywords.some((kw) => matchesKeyword(haystack, kw));
|
|
2051
|
+
if (!hasMatch) continue;
|
|
2052
|
+
const isVetoed = (rule.excludeKeywords || []).some((kw) => matchesKeyword(haystack, kw));
|
|
2053
|
+
if (isVetoed) continue;
|
|
2054
|
+
matched.add(rule.topicId);
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
return Array.from(matched);
|
|
2058
|
+
}
|
|
2059
|
+
function topicEmbedSources(installedPackIds) {
|
|
2060
|
+
const out = [];
|
|
2061
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2062
|
+
const ids = /* @__PURE__ */ new Set([DEFAULT_PACK_ID, ...installedPackIds]);
|
|
2063
|
+
for (const packId of ids) {
|
|
2064
|
+
const pack = getPackManifest(packId);
|
|
2065
|
+
if (!pack) continue;
|
|
2066
|
+
for (const t of pack.topics) {
|
|
2067
|
+
if (seen.has(t.id)) continue;
|
|
2068
|
+
seen.add(t.id);
|
|
2069
|
+
const sectionTitles = (t.sectionTemplates || []).map((s) => s.title).join(". ");
|
|
2070
|
+
const text = [t.name, t.summary, sectionTitles].filter(Boolean).join(" \u2014 ");
|
|
2071
|
+
out.push({ topicId: t.id, packId, text });
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
return out;
|
|
2075
|
+
}
|
|
2076
|
+
function cosineSimilarity(a, b) {
|
|
2077
|
+
if (a.length !== b.length || a.length === 0) return 0;
|
|
2078
|
+
let dot = 0;
|
|
2079
|
+
let normA = 0;
|
|
2080
|
+
let normB = 0;
|
|
2081
|
+
for (let i = 0; i < a.length; i++) {
|
|
2082
|
+
dot += a[i] * b[i];
|
|
2083
|
+
normA += a[i] * a[i];
|
|
2084
|
+
normB += b[i] * b[i];
|
|
2085
|
+
}
|
|
2086
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
2087
|
+
return denom === 0 ? 0 : dot / denom;
|
|
2088
|
+
}
|
|
2089
|
+
function semanticTagMatches(memoryEmbedding, topicEmbeddings, threshold = EMBEDDING_TAG_THRESHOLD) {
|
|
2090
|
+
const matched = [];
|
|
2091
|
+
for (const { topicId, embedding } of topicEmbeddings) {
|
|
2092
|
+
const sim = cosineSimilarity(memoryEmbedding, embedding);
|
|
2093
|
+
if (sim >= threshold) matched.push(topicId);
|
|
2094
|
+
}
|
|
2095
|
+
return matched;
|
|
2096
|
+
}
|
|
2097
|
+
var WORKSPACE_PACK, COMPLIANCE_PACK, SALES_PACK, ALL_PACK_MANIFESTS, DEFAULT_PACK_ID, EMBEDDING_TAG_THRESHOLD;
|
|
2098
|
+
var init_wiki_packs = __esm({
|
|
2099
|
+
"packages/shared/src/wiki-packs.ts"() {
|
|
2100
|
+
"use strict";
|
|
2101
|
+
WORKSPACE_PACK = {
|
|
2102
|
+
id: "workspace",
|
|
2103
|
+
name: "Workspace Essentials",
|
|
2104
|
+
vendor: "Clude",
|
|
2105
|
+
vertical: "General",
|
|
2106
|
+
version: "1.0.0",
|
|
2107
|
+
installedByDefault: true,
|
|
2108
|
+
description: "The default knowledge-worker pack. Roadmaps, decisions, customer research, hiring, team process \u2014 everything you'd want a colleague to be able to skim.",
|
|
2109
|
+
topics: [
|
|
2110
|
+
{ id: "q3-roadmap", name: "Q3 Roadmap", cluster: "architecture", color: "#2244FF", summary: "What ships this quarter, what got cut, and the calls behind those decisions." },
|
|
2111
|
+
{ id: "auth-migration", name: "Auth Migration", cluster: "architecture", color: "#2244FF", summary: "Moving from session cookies to JWT \u2014 incidents, fixes, and the rollback plan." },
|
|
2112
|
+
{ id: "customer-research", name: "Customer Research", cluster: "research", color: "#F59E0B", summary: "Patterns surfaced across customer calls." },
|
|
2113
|
+
{ id: "pricing-model", name: "Pricing Model", cluster: "product", color: "#10B981", summary: "Per-token vs per-seat \u2014 the active disagreement." },
|
|
2114
|
+
{ id: "demo-day-prep", name: "Demo Day Prep", cluster: "product", color: "#10B981", summary: "What works in the live demo, what breaks." },
|
|
2115
|
+
{ id: "hiring", name: "Hiring Pipeline", cluster: "product", color: "#10B981", summary: "Candidates in flight and interview-signal patterns." },
|
|
2116
|
+
{ id: "team-process", name: "Team Process", cluster: "self", color: "#8B5CF6", summary: "What's working in how the team operates and what isn't." },
|
|
2117
|
+
{ id: "design-decisions", name: "Design Decisions", cluster: "research", color: "#F59E0B", summary: "API shapes, naming choices, and the reasons behind them." }
|
|
2118
|
+
],
|
|
2119
|
+
rules: [
|
|
2120
|
+
{ topicId: "q3-roadmap", keywords: ["roadmap", "q3", "quarter", "sprint plan", "priority"] },
|
|
2121
|
+
{ topicId: "auth-migration", keywords: ["auth", "jwt", "session cookie", "oauth", "sso", "token migration"] },
|
|
2122
|
+
{ topicId: "customer-research", keywords: ["customer call", "interview", "feedback", "user research", "persona"] },
|
|
2123
|
+
{ topicId: "pricing-model", keywords: ["pricing", "per-token", "per-seat", "subscription", "billing tier"] },
|
|
2124
|
+
{ topicId: "demo-day-prep", keywords: ["demo", "rehearsal", "investor", "pitch"] },
|
|
2125
|
+
{
|
|
2126
|
+
topicId: "hiring",
|
|
2127
|
+
keywords: ["candidate", "interview", "hire", "phone screen", "onsite", "offer"],
|
|
2128
|
+
// Suppress when "hire" is in the wrong context — got fired, rejected an offer,
|
|
2129
|
+
// hire-purchase, etc. The classic substring-match false positive.
|
|
2130
|
+
excludeKeywords: ["fired me", "i was fired", "hire purchase", "rejected my offer", "rejected the offer"]
|
|
2131
|
+
},
|
|
2132
|
+
{ topicId: "team-process", keywords: ["standup", "retro", "sprint", "1:1", "process", "team"] },
|
|
2133
|
+
{ topicId: "design-decisions", keywords: ["api design", "schema", "naming", "rfc", "design doc"] }
|
|
2134
|
+
]
|
|
2135
|
+
};
|
|
2136
|
+
COMPLIANCE_PACK = {
|
|
2137
|
+
id: "compliance",
|
|
2138
|
+
name: "Clude Compliance",
|
|
2139
|
+
vendor: "Clude",
|
|
2140
|
+
vertical: "Compliance",
|
|
2141
|
+
version: "1.0.0",
|
|
2142
|
+
description: "Auto-organises every compliance-relevant decision your agents make into an audit-ready wiki. Audit logs, evidence collection, regulator asks, policy decisions \u2014 each with a cryptographic receipt anchored to Solana.",
|
|
2143
|
+
topics: [
|
|
2144
|
+
{
|
|
2145
|
+
id: "audit-logs",
|
|
2146
|
+
name: "Audit Logs",
|
|
2147
|
+
cluster: "architecture",
|
|
2148
|
+
color: "#0EA5E9",
|
|
2149
|
+
summary: "Every flagged agent action with attribution, timestamp, and a Solana-anchored hash a regulator can verify without trusting us.",
|
|
2150
|
+
sectionTemplates: [
|
|
2151
|
+
{ id: "recent-events", title: "Recent flagged events", kind: "overview" },
|
|
2152
|
+
{ id: "anomalies", title: "Anomalies & escalations", kind: "concern" },
|
|
2153
|
+
{ id: "retention", title: "Retention policy", kind: "decision" }
|
|
2154
|
+
]
|
|
2155
|
+
},
|
|
2156
|
+
{
|
|
2157
|
+
id: "evidence",
|
|
2158
|
+
name: "Evidence Collection",
|
|
2159
|
+
cluster: "product",
|
|
2160
|
+
color: "#06B6D4",
|
|
2161
|
+
summary: "Documentation gathered for SOC2, HIPAA, and ISO 27001 \u2014 what we have, what we still need, and what auditors have already accepted.",
|
|
2162
|
+
sectionTemplates: [
|
|
2163
|
+
{ id: "have", title: "What we have", kind: "highlight" },
|
|
2164
|
+
{ id: "gaps", title: "Gaps to fill", kind: "action" },
|
|
2165
|
+
{ id: "accepted", title: "What auditors accepted", kind: "decision" }
|
|
2166
|
+
]
|
|
2167
|
+
},
|
|
2168
|
+
{
|
|
2169
|
+
id: "regulator-asks",
|
|
2170
|
+
name: "Regulator Asks",
|
|
2171
|
+
cluster: "research",
|
|
2172
|
+
color: "#F59E0B",
|
|
2173
|
+
summary: "Specific requests from regulators \u2014 owner, deadline, response status. Nothing falls through the cracks.",
|
|
2174
|
+
sectionTemplates: [
|
|
2175
|
+
{ id: "open", title: "Open requests", kind: "action" },
|
|
2176
|
+
{ id: "responded", title: "Responded", kind: "decision" },
|
|
2177
|
+
{ id: "patterns", title: "Recurring patterns", kind: "highlight" }
|
|
2178
|
+
]
|
|
2179
|
+
},
|
|
2180
|
+
{
|
|
2181
|
+
id: "policy-decisions",
|
|
2182
|
+
name: "Policy Decisions",
|
|
2183
|
+
cluster: "self",
|
|
2184
|
+
color: "#8B5CF6",
|
|
2185
|
+
summary: "Calls made about what the agents are allowed to do \u2014 data handling, escalation triggers, redaction rules \u2014 each anchored on-chain.",
|
|
2186
|
+
sectionTemplates: [
|
|
2187
|
+
{ id: "standing", title: "Standing policy", kind: "decision" },
|
|
2188
|
+
{ id: "changes", title: "Recent changes", kind: "overview" },
|
|
2189
|
+
{ id: "open", title: "Open questions", kind: "question" }
|
|
2190
|
+
]
|
|
2191
|
+
},
|
|
2192
|
+
{
|
|
2193
|
+
id: "soc2-status",
|
|
2194
|
+
name: "SOC2 Status",
|
|
2195
|
+
cluster: "product",
|
|
2196
|
+
color: "#10B981",
|
|
2197
|
+
summary: "Where we are in the SOC2 audit cycle, what controls are passing, what still needs evidence.",
|
|
2198
|
+
sectionTemplates: [
|
|
2199
|
+
{ id: "controls", title: "Control status", kind: "overview" },
|
|
2200
|
+
{ id: "next", title: "Up next", kind: "action" }
|
|
2201
|
+
]
|
|
2202
|
+
}
|
|
2203
|
+
],
|
|
2204
|
+
rules: [
|
|
2205
|
+
{ topicId: "audit-logs", keywords: ["audit", "audit log", "trail", "attribution", "flagged"] },
|
|
2206
|
+
{ topicId: "evidence", keywords: ["evidence", "soc2", "hipaa", "iso 27001", "compliance evidence", "control"] },
|
|
2207
|
+
{ topicId: "regulator-asks", keywords: ["regulator", "subpoena", "compliance request", "data request"] },
|
|
2208
|
+
{ topicId: "policy-decisions", keywords: ["policy", "redaction", "pii", "escalation rule", "data handling"] },
|
|
2209
|
+
{ topicId: "soc2-status", keywords: ["soc2", "audit cycle", "control test"] }
|
|
2210
|
+
]
|
|
2211
|
+
};
|
|
2212
|
+
SALES_PACK = {
|
|
2213
|
+
id: "sales",
|
|
2214
|
+
name: "Sales Intelligence",
|
|
2215
|
+
vendor: "Clude",
|
|
2216
|
+
vertical: "Sales",
|
|
2217
|
+
version: "1.0.0",
|
|
2218
|
+
description: "Auto-organises pipeline conversations, deal blockers, objection patterns, and post-call follow-ups. Built for AEs who hate CRM data entry.",
|
|
2219
|
+
topics: [
|
|
2220
|
+
{ id: "pipeline", name: "Pipeline", cluster: "product", color: "#10B981", summary: "Active deals, stages, blockers." },
|
|
2221
|
+
{ id: "objections", name: "Objections", cluster: "research", color: "#F59E0B", summary: "Patterns across discovery calls." },
|
|
2222
|
+
{ id: "follow-ups", name: "Follow-ups", cluster: "product", color: "#10B981", summary: "What you committed to send and to whom." },
|
|
2223
|
+
{ id: "champions", name: "Champions", cluster: "self", color: "#8B5CF6", summary: "Who is championing your product internally at each account." }
|
|
2224
|
+
],
|
|
2225
|
+
rules: [
|
|
2226
|
+
{ topicId: "pipeline", keywords: ["deal", "opportunity", "stage", "close date", "mql", "sql"] },
|
|
2227
|
+
{ topicId: "objections", keywords: ["objection", "concern raised", "pushback", "competitor mentioned"] },
|
|
2228
|
+
{ topicId: "follow-ups", keywords: ["follow up", "send", "next step", "committed to"] },
|
|
2229
|
+
{ topicId: "champions", keywords: ["champion", "sponsor", "advocate", "introduced me to"] }
|
|
2230
|
+
]
|
|
2231
|
+
};
|
|
2232
|
+
ALL_PACK_MANIFESTS = [
|
|
2233
|
+
WORKSPACE_PACK,
|
|
2234
|
+
COMPLIANCE_PACK,
|
|
2235
|
+
SALES_PACK
|
|
2236
|
+
];
|
|
2237
|
+
DEFAULT_PACK_ID = "workspace";
|
|
2238
|
+
EMBEDDING_TAG_THRESHOLD = 0.78;
|
|
2239
|
+
}
|
|
2240
|
+
});
|
|
2241
|
+
|
|
1893
2242
|
// packages/brain/src/experimental/config.ts
|
|
1894
2243
|
function envBool(key, fallback) {
|
|
1895
2244
|
const val = process.env[key];
|
|
@@ -2365,6 +2714,7 @@ __export(memory_exports, {
|
|
|
2365
2714
|
getSelfModel: () => getSelfModel,
|
|
2366
2715
|
hydrateMemories: () => hydrateMemories,
|
|
2367
2716
|
inferConcepts: () => inferConcepts,
|
|
2717
|
+
invalidateInstalledPacksCache: () => invalidateInstalledPacksCache,
|
|
2368
2718
|
isValidHashId: () => isValidHashId,
|
|
2369
2719
|
listMemories: () => listMemories,
|
|
2370
2720
|
markJepaQueried: () => markJepaQueried,
|
|
@@ -2467,13 +2817,83 @@ function isDuplicateWrite(source, summary) {
|
|
|
2467
2817
|
}
|
|
2468
2818
|
return false;
|
|
2469
2819
|
}
|
|
2820
|
+
async function getInstalledPackIdsCached(ownerWallet) {
|
|
2821
|
+
const key = ownerWallet ?? "__no_owner__";
|
|
2822
|
+
const now = Date.now();
|
|
2823
|
+
const cached = installedPacksCache.get(key);
|
|
2824
|
+
if (cached && cached.expiresAt > now) return cached.ids;
|
|
2825
|
+
let ids = [DEFAULT_PACK_ID];
|
|
2826
|
+
if (ownerWallet) {
|
|
2827
|
+
try {
|
|
2828
|
+
const db = getDb();
|
|
2829
|
+
const { data, error } = await db.from("wiki_pack_installations").select("pack_id").eq("owner_wallet", ownerWallet);
|
|
2830
|
+
if (!error && data) {
|
|
2831
|
+
const fromDb = data.map((r) => r.pack_id);
|
|
2832
|
+
ids = Array.from(/* @__PURE__ */ new Set([DEFAULT_PACK_ID, ...fromDb]));
|
|
2833
|
+
}
|
|
2834
|
+
} catch (err) {
|
|
2835
|
+
log10.debug({ err }, "Failed to fetch installed packs (using default only)");
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
installedPacksCache.set(key, { ids, expiresAt: now + INSTALLED_PACKS_TTL_MS });
|
|
2839
|
+
if (installedPacksCache.size > 200) {
|
|
2840
|
+
for (const [k, v] of installedPacksCache) {
|
|
2841
|
+
if (v.expiresAt <= now) installedPacksCache.delete(k);
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
return ids;
|
|
2845
|
+
}
|
|
2846
|
+
function invalidateInstalledPacksCache(ownerWallet) {
|
|
2847
|
+
if (ownerWallet) installedPacksCache.delete(ownerWallet);
|
|
2848
|
+
else installedPacksCache.clear();
|
|
2849
|
+
}
|
|
2850
|
+
async function ensureTopicEmbeddings(installedPackIds) {
|
|
2851
|
+
const sources = topicEmbedSources(installedPackIds);
|
|
2852
|
+
const missing = sources.filter((s) => !topicEmbeddingCache.has(s.topicId));
|
|
2853
|
+
if (missing.length === 0) {
|
|
2854
|
+
return new Map(sources.map((s) => [s.topicId, topicEmbeddingCache.get(s.topicId)]));
|
|
2855
|
+
}
|
|
2856
|
+
if (topicEmbeddingPopulationLock) {
|
|
2857
|
+
await topicEmbeddingPopulationLock;
|
|
2858
|
+
}
|
|
2859
|
+
const stillMissing = sources.filter((s) => !topicEmbeddingCache.has(s.topicId));
|
|
2860
|
+
if (stillMissing.length === 0) {
|
|
2861
|
+
return new Map(sources.map((s) => [s.topicId, topicEmbeddingCache.get(s.topicId)]));
|
|
2862
|
+
}
|
|
2863
|
+
topicEmbeddingPopulationLock = (async () => {
|
|
2864
|
+
try {
|
|
2865
|
+
const texts = stillMissing.map((s) => s.text);
|
|
2866
|
+
const embeddings = await generateEmbeddings(texts);
|
|
2867
|
+
stillMissing.forEach((s, i) => {
|
|
2868
|
+
const emb = embeddings[i];
|
|
2869
|
+
if (emb) topicEmbeddingCache.set(s.topicId, emb);
|
|
2870
|
+
});
|
|
2871
|
+
} catch (err) {
|
|
2872
|
+
log10.warn({ err }, "Failed to populate topic embeddings cache");
|
|
2873
|
+
} finally {
|
|
2874
|
+
topicEmbeddingPopulationLock = null;
|
|
2875
|
+
}
|
|
2876
|
+
})();
|
|
2877
|
+
await topicEmbeddingPopulationLock;
|
|
2878
|
+
return new Map(
|
|
2879
|
+
sources.filter((s) => topicEmbeddingCache.has(s.topicId)).map((s) => [s.topicId, topicEmbeddingCache.get(s.topicId)])
|
|
2880
|
+
);
|
|
2881
|
+
}
|
|
2470
2882
|
async function storeMemory(opts) {
|
|
2471
2883
|
if (opts.source.startsWith("shiro_") && isDuplicateWrite(opts.source, opts.summary)) {
|
|
2472
2884
|
log10.debug({ source: opts.source, summary: opts.summary.slice(0, 60) }, "Skipping duplicate memory write");
|
|
2473
2885
|
return null;
|
|
2474
2886
|
}
|
|
2475
2887
|
const db = getDb();
|
|
2888
|
+
const ownerWallet = getOwnerWallet();
|
|
2476
2889
|
const concepts = opts.concepts || inferConcepts(opts.summary, opts.source, opts.tags || []);
|
|
2890
|
+
const installedPackIds = await getInstalledPackIdsCached(ownerWallet);
|
|
2891
|
+
const taggedTags = autoCategorizeTags({
|
|
2892
|
+
content: opts.content,
|
|
2893
|
+
summary: opts.summary,
|
|
2894
|
+
existingTags: opts.tags || [],
|
|
2895
|
+
installedPackIds
|
|
2896
|
+
});
|
|
2477
2897
|
const hashId = generateHashId();
|
|
2478
2898
|
try {
|
|
2479
2899
|
const plaintextContent = opts.content.slice(0, MEMORY_MAX_CONTENT_LENGTH);
|
|
@@ -2484,7 +2904,7 @@ async function storeMemory(opts) {
|
|
|
2484
2904
|
memory_type: opts.type,
|
|
2485
2905
|
content: storedContent,
|
|
2486
2906
|
summary: opts.summary.slice(0, MEMORY_MAX_SUMMARY_LENGTH),
|
|
2487
|
-
tags:
|
|
2907
|
+
tags: taggedTags,
|
|
2488
2908
|
concepts,
|
|
2489
2909
|
emotional_valence: clamp(opts.emotionalValence ?? 0, -1, 1),
|
|
2490
2910
|
importance: clamp(opts.importance ?? 0.5, 0, 1),
|
|
@@ -2497,8 +2917,8 @@ async function storeMemory(opts) {
|
|
|
2497
2917
|
compacted: false,
|
|
2498
2918
|
encrypted: shouldEncrypt,
|
|
2499
2919
|
encryption_pubkey: shouldEncrypt ? getEncryptionPubkey() : null,
|
|
2500
|
-
owner_wallet:
|
|
2501
|
-
}).select("id, hash_id").single();
|
|
2920
|
+
owner_wallet: ownerWallet || null
|
|
2921
|
+
}).select("id, hash_id, content, memory_type, owner_wallet, created_at, tags, source, related_user, related_wallet").single();
|
|
2502
2922
|
if (error) {
|
|
2503
2923
|
log10.error({ error: error.message }, "Failed to store memory");
|
|
2504
2924
|
return null;
|
|
@@ -2516,7 +2936,9 @@ async function storeMemory(opts) {
|
|
|
2516
2936
|
memoryType: opts.type,
|
|
2517
2937
|
source: opts.source
|
|
2518
2938
|
});
|
|
2519
|
-
commitMemoryToChain(data.id, opts).catch(
|
|
2939
|
+
commitMemoryToChain(data.id, opts, data).catch(
|
|
2940
|
+
(err) => log10.warn({ err }, "On-chain memory commit failed")
|
|
2941
|
+
);
|
|
2520
2942
|
embedMemory(data.id, opts).catch((err) => log10.warn({ err }, "Embedding generation failed"));
|
|
2521
2943
|
autoLinkMemory(data.id, opts).catch((err) => log10.warn({ err }, "Auto-linking failed"));
|
|
2522
2944
|
extractAndLinkEntitiesForMemory(data.id, opts).catch((err) => log10.debug({ err }, "Entity extraction failed"));
|
|
@@ -2526,9 +2948,19 @@ async function storeMemory(opts) {
|
|
|
2526
2948
|
return null;
|
|
2527
2949
|
}
|
|
2528
2950
|
}
|
|
2529
|
-
async function commitMemoryToChain(memoryId, opts) {
|
|
2530
|
-
if (
|
|
2531
|
-
const
|
|
2951
|
+
async function commitMemoryToChain(memoryId, opts, row) {
|
|
2952
|
+
if (TOKENISATION_SKIP_SOURCES.has(opts.source)) return;
|
|
2953
|
+
const canonicalHash = memoryContentHash({
|
|
2954
|
+
content: row.content,
|
|
2955
|
+
memory_type: row.memory_type,
|
|
2956
|
+
owner_wallet: row.owner_wallet,
|
|
2957
|
+
created_at: row.created_at,
|
|
2958
|
+
tags: row.tags ?? [],
|
|
2959
|
+
source: row.source,
|
|
2960
|
+
related_user: row.related_user,
|
|
2961
|
+
related_wallet: row.related_wallet
|
|
2962
|
+
});
|
|
2963
|
+
const contentHashBuf = Buffer.from(canonicalHash, "hex");
|
|
2532
2964
|
let signature = null;
|
|
2533
2965
|
if (isRegistryEnabled()) {
|
|
2534
2966
|
const encrypted = isEncryptionEnabled();
|
|
@@ -2541,22 +2973,61 @@ async function commitMemoryToChain(memoryId, opts) {
|
|
|
2541
2973
|
);
|
|
2542
2974
|
}
|
|
2543
2975
|
if (!signature) {
|
|
2544
|
-
const
|
|
2545
|
-
const memo = `clude-memory | v2 | ${contentHashHex}`;
|
|
2976
|
+
const memo = `clude:v1:sha256:${canonicalHash}`;
|
|
2546
2977
|
signature = await writeMemo(memo);
|
|
2547
2978
|
}
|
|
2548
|
-
if (!signature) return;
|
|
2549
2979
|
const db = getDb();
|
|
2550
|
-
|
|
2551
|
-
|
|
2980
|
+
if (!signature) {
|
|
2981
|
+
await db.from("memories").update({ content_hash: canonicalHash, tokenization_status: "failed" }).eq("id", memoryId);
|
|
2982
|
+
return;
|
|
2983
|
+
}
|
|
2984
|
+
await db.from("memories").update({
|
|
2985
|
+
solana_signature: signature,
|
|
2986
|
+
content_hash: canonicalHash,
|
|
2987
|
+
cnft_address: signature,
|
|
2988
|
+
// PDA-based v0.1 — assetId = tx sig; LightMintClient (v0.2) will use real cNFT mints
|
|
2989
|
+
cnft_tx_sig: signature,
|
|
2990
|
+
cnft_tree: null,
|
|
2991
|
+
cnft_leaf_index: null,
|
|
2992
|
+
tokenization_status: "minted",
|
|
2993
|
+
tokenized_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2994
|
+
}).eq("id", memoryId);
|
|
2995
|
+
log10.debug({ memoryId, signature: signature.slice(0, 16) }, "Memory committed on-chain (PMP + legacy)");
|
|
2552
2996
|
}
|
|
2553
2997
|
async function embedMemory(memoryId, opts) {
|
|
2554
2998
|
if (!isEmbeddingEnabled()) return;
|
|
2555
2999
|
const db = getDb();
|
|
2556
3000
|
const embeddings = await generateEmbeddings([opts.summary]);
|
|
2557
3001
|
const summaryEmbedding = embeddings[0];
|
|
2558
|
-
if (summaryEmbedding) {
|
|
2559
|
-
|
|
3002
|
+
if (!summaryEmbedding) {
|
|
3003
|
+
log10.debug({ memoryId }, "No embedding generated; skipping semantic tagging");
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
3006
|
+
await db.from("memories").update({ embedding: JSON.stringify(summaryEmbedding) }).eq("id", memoryId);
|
|
3007
|
+
try {
|
|
3008
|
+
const ownerWallet = getOwnerWallet();
|
|
3009
|
+
const installedPacks = await getInstalledPackIdsCached(ownerWallet);
|
|
3010
|
+
const topicEmbeddings = await ensureTopicEmbeddings(installedPacks);
|
|
3011
|
+
if (topicEmbeddings.size > 0) {
|
|
3012
|
+
const semantic = semanticTagMatches(
|
|
3013
|
+
summaryEmbedding,
|
|
3014
|
+
Array.from(topicEmbeddings, ([topicId, embedding]) => ({ topicId, embedding }))
|
|
3015
|
+
);
|
|
3016
|
+
if (semantic.length > 0) {
|
|
3017
|
+
const { data: row } = await db.from("memories").select("tags").eq("id", memoryId).maybeSingle();
|
|
3018
|
+
const existing = row?.tags ?? [];
|
|
3019
|
+
const merged = Array.from(/* @__PURE__ */ new Set([...existing, ...semantic]));
|
|
3020
|
+
if (merged.length !== existing.length) {
|
|
3021
|
+
await db.from("memories").update({ tags: merged }).eq("id", memoryId);
|
|
3022
|
+
log10.debug({
|
|
3023
|
+
memoryId,
|
|
3024
|
+
added: semantic.filter((t) => !existing.includes(t))
|
|
3025
|
+
}, "Semantic pack tags appended");
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
3029
|
+
} catch (err) {
|
|
3030
|
+
log10.debug({ err, memoryId }, "Semantic tagging skipped");
|
|
2560
3031
|
}
|
|
2561
3032
|
log10.debug({ memoryId }, "Memory embedded");
|
|
2562
3033
|
}
|
|
@@ -3278,25 +3749,31 @@ async function getMemoryStats() {
|
|
|
3278
3749
|
embeddedCount: 0
|
|
3279
3750
|
};
|
|
3280
3751
|
try {
|
|
3281
|
-
let countQuery = db.from("memories").select("id", { count: "exact", head: true })
|
|
3752
|
+
let countQuery = db.from("memories").select("id", { count: "exact", head: true });
|
|
3282
3753
|
countQuery = scopeToOwner(countQuery);
|
|
3283
3754
|
const { count: totalCount } = await countQuery;
|
|
3284
3755
|
stats.total = totalCount || 0;
|
|
3285
|
-
let embeddedQuery = db.from("memories").select("id", { count: "exact", head: true }).
|
|
3756
|
+
let embeddedQuery = db.from("memories").select("id", { count: "exact", head: true }).not("embedding", "is", null);
|
|
3286
3757
|
embeddedQuery = scopeToOwner(embeddedQuery);
|
|
3287
3758
|
const { count: embCount } = await embeddedQuery;
|
|
3288
3759
|
stats.embeddedCount = embCount || 0;
|
|
3289
|
-
const
|
|
3760
|
+
const TYPES = ["episodic", "semantic", "procedural", "self_model", "introspective"];
|
|
3761
|
+
await Promise.all(TYPES.map(async (type) => {
|
|
3762
|
+
let q = db.from("memories").select("id", { count: "exact", head: true }).eq("memory_type", type);
|
|
3763
|
+
q = scopeToOwner(q);
|
|
3764
|
+
const { count: count2 } = await q;
|
|
3765
|
+
stats.byType[type] = count2 || 0;
|
|
3766
|
+
}));
|
|
3767
|
+
const PAGE_SIZE = 1e3;
|
|
3768
|
+
const MAX_PAGES = 20;
|
|
3290
3769
|
let allMemories = [];
|
|
3291
|
-
let page = 0;
|
|
3292
|
-
|
|
3293
|
-
let pageQuery = db.from("memories").select("memory_type, importance, decay_factor, created_at, related_user, tags, concepts").gt("decay_factor", MEMORY_MIN_DECAY).range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1);
|
|
3770
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
3771
|
+
let pageQuery = db.from("memories").select("importance, decay_factor, created_at, related_user, tags, concepts").order("id", { ascending: true }).range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE - 1);
|
|
3294
3772
|
pageQuery = scopeToOwner(pageQuery);
|
|
3295
3773
|
const { data: pageData } = await pageQuery;
|
|
3296
3774
|
if (!pageData || pageData.length === 0) break;
|
|
3297
3775
|
allMemories = allMemories.concat(pageData);
|
|
3298
3776
|
if (pageData.length < PAGE_SIZE) break;
|
|
3299
|
-
page++;
|
|
3300
3777
|
}
|
|
3301
3778
|
if (allMemories.length > 0) {
|
|
3302
3779
|
let impSum = 0;
|
|
@@ -3305,8 +3782,6 @@ async function getMemoryStats() {
|
|
|
3305
3782
|
const conceptCounts = {};
|
|
3306
3783
|
const users = /* @__PURE__ */ new Set();
|
|
3307
3784
|
for (const m of allMemories) {
|
|
3308
|
-
const type = m.memory_type;
|
|
3309
|
-
if (type in stats.byType) stats.byType[type]++;
|
|
3310
3785
|
impSum += m.importance;
|
|
3311
3786
|
decaySum += m.decay_factor;
|
|
3312
3787
|
if (m.related_user) users.add(m.related_user);
|
|
@@ -3494,7 +3969,7 @@ function moodToValence(mood) {
|
|
|
3494
3969
|
return 0;
|
|
3495
3970
|
}
|
|
3496
3971
|
}
|
|
3497
|
-
var import_crypto2, EMBED_CACHE_MAX, embeddingCache, _ownerWallet, SCOPE_BOT_OWN, HASH_ID_PREFIX, log10, DEDUP_TTL_MS, dedupCache, STOPWORDS;
|
|
3972
|
+
var import_crypto2, EMBED_CACHE_MAX, embeddingCache, _ownerWallet, SCOPE_BOT_OWN, HASH_ID_PREFIX, log10, DEDUP_TTL_MS, dedupCache, installedPacksCache, INSTALLED_PACKS_TTL_MS, topicEmbeddingCache, topicEmbeddingPopulationLock, TOKENISATION_SKIP_SOURCES, STOPWORDS;
|
|
3498
3973
|
var init_memory = __esm({
|
|
3499
3974
|
"packages/brain/src/memory/memory.ts"() {
|
|
3500
3975
|
"use strict";
|
|
@@ -3503,7 +3978,9 @@ var init_memory = __esm({
|
|
|
3503
3978
|
init_utils();
|
|
3504
3979
|
init_claude_client();
|
|
3505
3980
|
init_solana_client();
|
|
3981
|
+
init_src();
|
|
3506
3982
|
init_embeddings();
|
|
3983
|
+
init_wiki_packs();
|
|
3507
3984
|
init_config2();
|
|
3508
3985
|
init_bm25_search();
|
|
3509
3986
|
init_openrouter_client();
|
|
@@ -3520,6 +3997,16 @@ var init_memory = __esm({
|
|
|
3520
3997
|
log10 = createChildLogger("memory");
|
|
3521
3998
|
DEDUP_TTL_MS = 10 * 60 * 1e3;
|
|
3522
3999
|
dedupCache = /* @__PURE__ */ new Map();
|
|
4000
|
+
installedPacksCache = /* @__PURE__ */ new Map();
|
|
4001
|
+
INSTALLED_PACKS_TTL_MS = 6e4;
|
|
4002
|
+
topicEmbeddingCache = /* @__PURE__ */ new Map();
|
|
4003
|
+
topicEmbeddingPopulationLock = null;
|
|
4004
|
+
TOKENISATION_SKIP_SOURCES = /* @__PURE__ */ new Set([
|
|
4005
|
+
"demo",
|
|
4006
|
+
"demo-maas",
|
|
4007
|
+
"locomo-benchmark",
|
|
4008
|
+
"longmemeval-benchmark"
|
|
4009
|
+
]);
|
|
3523
4010
|
STOPWORDS = /* @__PURE__ */ new Set([
|
|
3524
4011
|
"the",
|
|
3525
4012
|
"a",
|
|
@@ -3625,6 +4112,7 @@ __export(memory_exports2, {
|
|
|
3625
4112
|
getSelfModel: () => getSelfModel,
|
|
3626
4113
|
hydrateMemories: () => hydrateMemories,
|
|
3627
4114
|
inferConcepts: () => inferConcepts,
|
|
4115
|
+
invalidateInstalledPacksCache: () => invalidateInstalledPacksCache,
|
|
3628
4116
|
isValidHashId: () => isValidHashId,
|
|
3629
4117
|
listMemories: () => listMemories,
|
|
3630
4118
|
moodToValence: () => moodToValence,
|
|
@@ -6037,10 +6525,10 @@ var Cortex = class {
|
|
|
6037
6525
|
this.requireSelfHosted("verifyOnChain");
|
|
6038
6526
|
const { hydrateMemories: hydrateMemories2 } = (init_memory2(), __toCommonJS(memory_exports2));
|
|
6039
6527
|
const { verifyMemoryOnChain: verifyMemoryOnChain2 } = (init_solana_client(), __toCommonJS(solana_client_exports));
|
|
6040
|
-
const { createHash:
|
|
6528
|
+
const { createHash: createHash3 } = require("crypto");
|
|
6041
6529
|
const memories = await hydrateMemories2([memoryId]);
|
|
6042
6530
|
if (memories.length === 0) return false;
|
|
6043
|
-
const contentHash =
|
|
6531
|
+
const contentHash = createHash3("sha256").update(memories[0].content).digest();
|
|
6044
6532
|
return verifyMemoryOnChain2(contentHash);
|
|
6045
6533
|
}
|
|
6046
6534
|
/** Clean up resources and stop schedules. */
|