@xache/langchain 0.1.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 +177 -0
- package/dist/index.d.mts +457 -0
- package/dist/index.d.ts +457 -0
- package/dist/index.js +567 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +533 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +68 -0
- package/src/chat_history.ts +232 -0
- package/src/collective.ts +195 -0
- package/src/extraction.ts +172 -0
- package/src/index.ts +59 -0
- package/src/memory.ts +121 -0
- package/src/reputation.ts +195 -0
- package/src/retriever.ts +100 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @xache/langchain
|
|
3
|
+
* LangChain.js integration for Xache Protocol
|
|
4
|
+
*
|
|
5
|
+
* Drop-in memory, retrieval, and collective intelligence with verifiable receipts.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // One-line memory replacement
|
|
10
|
+
* import { XacheMemory } from '@xache/langchain';
|
|
11
|
+
*
|
|
12
|
+
* const memory = new XacheMemory({
|
|
13
|
+
* walletAddress: '0x...',
|
|
14
|
+
* privateKey: '0x...',
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Use with any LangChain chain
|
|
18
|
+
* const chain = new ConversationChain({ llm, memory });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// Memory
|
|
25
|
+
export { XacheMemory, XacheConversationBufferMemory } from './memory';
|
|
26
|
+
export type { XacheMemoryConfig } from './memory';
|
|
27
|
+
|
|
28
|
+
// Chat History
|
|
29
|
+
export { XacheChatMessageHistory } from './chat_history';
|
|
30
|
+
export type { XacheChatMessageHistoryConfig } from './chat_history';
|
|
31
|
+
|
|
32
|
+
// Retrieval
|
|
33
|
+
export { XacheRetriever } from './retriever';
|
|
34
|
+
export type { XacheRetrieverConfig } from './retriever';
|
|
35
|
+
|
|
36
|
+
// Extraction
|
|
37
|
+
export { XacheExtractor } from './extraction';
|
|
38
|
+
export type {
|
|
39
|
+
XacheExtractorConfig,
|
|
40
|
+
ExtractedMemory,
|
|
41
|
+
ExtractionResult,
|
|
42
|
+
} from './extraction';
|
|
43
|
+
|
|
44
|
+
// Collective Intelligence
|
|
45
|
+
export {
|
|
46
|
+
createCollectiveContributeTool,
|
|
47
|
+
createCollectiveQueryTool,
|
|
48
|
+
XacheCollectiveContributeTool,
|
|
49
|
+
XacheCollectiveQueryTool,
|
|
50
|
+
} from './collective';
|
|
51
|
+
export type { CollectiveToolConfig } from './collective';
|
|
52
|
+
|
|
53
|
+
// Reputation
|
|
54
|
+
export {
|
|
55
|
+
createReputationTool,
|
|
56
|
+
XacheReputationTool,
|
|
57
|
+
XacheReputationChecker,
|
|
58
|
+
} from './reputation';
|
|
59
|
+
export type { ReputationToolConfig, ReputationResult } from './reputation';
|
package/src/memory.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Xache Memory for LangChain.js
|
|
3
|
+
* Drop-in replacement for ConversationBufferMemory with verifiable receipts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { BaseMemory, InputValues, OutputValues, MemoryVariables } from '@langchain/core/memory';
|
|
7
|
+
import { XacheChatMessageHistory, XacheChatMessageHistoryConfig } from './chat_history';
|
|
8
|
+
|
|
9
|
+
export interface XacheMemoryConfig extends XacheChatMessageHistoryConfig {
|
|
10
|
+
/** Memory key for input (default: 'input') */
|
|
11
|
+
inputKey?: string;
|
|
12
|
+
/** Memory key for output (default: 'output') */
|
|
13
|
+
outputKey?: string;
|
|
14
|
+
/** Key for returning memory (default: 'history') */
|
|
15
|
+
memoryKey?: string;
|
|
16
|
+
/** Return messages as list vs string */
|
|
17
|
+
returnMessages?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Drop-in replacement for LangChain memory with Xache storage.
|
|
22
|
+
*
|
|
23
|
+
* Provides persistent, verifiable memory that survives across sessions.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import { XacheMemory } from '@xache/langchain';
|
|
28
|
+
* import { ChatOpenAI } from '@langchain/openai';
|
|
29
|
+
* import { ConversationChain } from 'langchain/chains';
|
|
30
|
+
*
|
|
31
|
+
* const memory = new XacheMemory({
|
|
32
|
+
* walletAddress: '0x...',
|
|
33
|
+
* privateKey: '0x...',
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* const chain = new ConversationChain({
|
|
37
|
+
* llm: new ChatOpenAI(),
|
|
38
|
+
* memory,
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* await chain.call({ input: 'Hello!' });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export class XacheMemory extends BaseMemory {
|
|
45
|
+
lc_namespace = ['xache', 'memory'];
|
|
46
|
+
|
|
47
|
+
private chatHistory: XacheChatMessageHistory;
|
|
48
|
+
private inputKey: string;
|
|
49
|
+
private outputKey: string;
|
|
50
|
+
private memoryKey: string;
|
|
51
|
+
private returnMessages: boolean;
|
|
52
|
+
|
|
53
|
+
constructor(config: XacheMemoryConfig) {
|
|
54
|
+
super();
|
|
55
|
+
this.chatHistory = new XacheChatMessageHistory(config);
|
|
56
|
+
this.inputKey = config.inputKey || 'input';
|
|
57
|
+
this.outputKey = config.outputKey || 'output';
|
|
58
|
+
this.memoryKey = config.memoryKey || 'history';
|
|
59
|
+
this.returnMessages = config.returnMessages ?? false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get memoryKeys(): string[] {
|
|
63
|
+
return [this.memoryKey];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Load memory variables
|
|
68
|
+
*/
|
|
69
|
+
async loadMemoryVariables(_values: InputValues): Promise<MemoryVariables> {
|
|
70
|
+
const messages = await this.chatHistory.getMessages();
|
|
71
|
+
|
|
72
|
+
if (this.returnMessages) {
|
|
73
|
+
return { [this.memoryKey]: messages };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Convert to string format
|
|
77
|
+
const history = messages
|
|
78
|
+
.map((m) => {
|
|
79
|
+
const role = m._getType() === 'human' ? 'Human' : 'AI';
|
|
80
|
+
const content =
|
|
81
|
+
typeof m.content === 'string' ? m.content : JSON.stringify(m.content);
|
|
82
|
+
return `${role}: ${content}`;
|
|
83
|
+
})
|
|
84
|
+
.join('\n');
|
|
85
|
+
|
|
86
|
+
return { [this.memoryKey]: history };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Save context from this conversation to buffer
|
|
91
|
+
*/
|
|
92
|
+
async saveContext(
|
|
93
|
+
inputValues: InputValues,
|
|
94
|
+
outputValues: OutputValues
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
const input = inputValues[this.inputKey];
|
|
97
|
+
const output = outputValues[this.outputKey];
|
|
98
|
+
|
|
99
|
+
if (input) {
|
|
100
|
+
await this.chatHistory.addUserMessage(String(input));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (output) {
|
|
104
|
+
await this.chatHistory.addAIMessage(String(output));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Clear memory contents
|
|
110
|
+
*/
|
|
111
|
+
async clear(): Promise<void> {
|
|
112
|
+
await this.chatHistory.clear();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Extended memory with conversation buffer capabilities
|
|
118
|
+
*/
|
|
119
|
+
export class XacheConversationBufferMemory extends XacheMemory {
|
|
120
|
+
lc_namespace = ['xache', 'memory', 'buffer'];
|
|
121
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Xache Reputation for LangChain.js
|
|
3
|
+
* Portable, verifiable agent reputation with ERC-8004 support
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { XacheClient, DID } from '@xache/sdk';
|
|
9
|
+
|
|
10
|
+
export interface ReputationToolConfig {
|
|
11
|
+
/** Wallet address for authentication */
|
|
12
|
+
walletAddress: string;
|
|
13
|
+
/** Private key for signing */
|
|
14
|
+
privateKey: string;
|
|
15
|
+
/** API URL (defaults to https://api.xache.xyz) */
|
|
16
|
+
apiUrl?: string;
|
|
17
|
+
/** Chain: 'base' or 'solana' */
|
|
18
|
+
chain?: 'base' | 'solana';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ReputationResult {
|
|
22
|
+
/** Reputation score (0-1) */
|
|
23
|
+
score: number;
|
|
24
|
+
/** Reputation level */
|
|
25
|
+
level: string;
|
|
26
|
+
/** Total contributions made */
|
|
27
|
+
totalContributions: number;
|
|
28
|
+
/** Total payments made */
|
|
29
|
+
totalPayments: number;
|
|
30
|
+
/** Whether ERC-8004 is enabled */
|
|
31
|
+
erc8004Enabled: boolean;
|
|
32
|
+
/** ERC-8004 agent ID if enabled */
|
|
33
|
+
erc8004AgentId?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get reputation level from score
|
|
38
|
+
*/
|
|
39
|
+
function getLevel(score: number): string {
|
|
40
|
+
if (score >= 0.9) return 'Elite';
|
|
41
|
+
if (score >= 0.7) return 'Trusted';
|
|
42
|
+
if (score >= 0.5) return 'Established';
|
|
43
|
+
if (score >= 0.3) return 'Developing';
|
|
44
|
+
return 'New';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Create an Xache client for reputation tools
|
|
49
|
+
*/
|
|
50
|
+
function createClient(config: ReputationToolConfig): XacheClient {
|
|
51
|
+
const chainPrefix = config.chain === 'solana' ? 'sol' : 'evm';
|
|
52
|
+
const did = `did:agent:${chainPrefix}:${config.walletAddress.toLowerCase()}` as DID;
|
|
53
|
+
|
|
54
|
+
return new XacheClient({
|
|
55
|
+
apiUrl: config.apiUrl || 'https://api.xache.xyz',
|
|
56
|
+
did,
|
|
57
|
+
privateKey: config.privateKey,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create a tool for checking your own reputation.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* import { createReputationTool } from '@xache/langchain';
|
|
67
|
+
*
|
|
68
|
+
* const repTool = createReputationTool({
|
|
69
|
+
* walletAddress: '0x...',
|
|
70
|
+
* privateKey: '0x...',
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* const tools = [repTool, ...];
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function createReputationTool(
|
|
77
|
+
config: ReputationToolConfig
|
|
78
|
+
): DynamicStructuredTool {
|
|
79
|
+
const client = createClient(config);
|
|
80
|
+
|
|
81
|
+
return new DynamicStructuredTool({
|
|
82
|
+
name: 'xache_check_reputation',
|
|
83
|
+
description:
|
|
84
|
+
'Check your current reputation score and status. ' +
|
|
85
|
+
'Returns your score (0-1), level, and ERC-8004 on-chain status. ' +
|
|
86
|
+
'Higher reputation means lower costs and more trust from other agents.',
|
|
87
|
+
schema: z.object({}),
|
|
88
|
+
func: async () => {
|
|
89
|
+
const result = await client.reputation.getReputation();
|
|
90
|
+
|
|
91
|
+
// Overall score is 0-100, normalize to 0-1
|
|
92
|
+
const score = (result.overall || 0) / 100;
|
|
93
|
+
const level = getLevel(score);
|
|
94
|
+
|
|
95
|
+
let output = `Reputation Score: ${score.toFixed(2)}/1.00 (${level})\n`;
|
|
96
|
+
output += `Memory Quality: ${result.memoryQuality || 0}/100\n`;
|
|
97
|
+
output += `Contribution Success: ${result.contribSuccess || 0}/100\n`;
|
|
98
|
+
output += `Economic Value: ${result.economicValue || 0}/100\n`;
|
|
99
|
+
|
|
100
|
+
// Check ERC-8004 status separately
|
|
101
|
+
try {
|
|
102
|
+
const erc8004Status = await client.reputation.getERC8004Status();
|
|
103
|
+
if (erc8004Status.enabled) {
|
|
104
|
+
output += `ERC-8004 Status: Enabled\n`;
|
|
105
|
+
output += 'Your reputation is verifiable on-chain!';
|
|
106
|
+
} else {
|
|
107
|
+
output += 'ERC-8004 Status: Not enabled\n';
|
|
108
|
+
output += 'Enable ERC-8004 to make your reputation portable and verifiable.';
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
output += 'ERC-8004 Status: Unknown';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return output;
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Class-based reputation tool (alternative API)
|
|
121
|
+
*/
|
|
122
|
+
export class XacheReputationTool {
|
|
123
|
+
private tool: DynamicStructuredTool;
|
|
124
|
+
|
|
125
|
+
constructor(config: ReputationToolConfig) {
|
|
126
|
+
this.tool = createReputationTool(config);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
asTool(): DynamicStructuredTool {
|
|
130
|
+
return this.tool;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Utility class for checking reputation of any agent.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* import { XacheReputationChecker } from '@xache/langchain';
|
|
140
|
+
*
|
|
141
|
+
* const checker = new XacheReputationChecker({
|
|
142
|
+
* walletAddress: '0x...',
|
|
143
|
+
* privateKey: '0x...',
|
|
144
|
+
* });
|
|
145
|
+
*
|
|
146
|
+
* const rep = await checker.check('did:agent:evm:0xOtherAgent...');
|
|
147
|
+
* if (rep.score >= 0.5) {
|
|
148
|
+
* console.log('Agent is trustworthy');
|
|
149
|
+
* }
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export class XacheReputationChecker {
|
|
153
|
+
private client: XacheClient;
|
|
154
|
+
|
|
155
|
+
constructor(config: ReputationToolConfig) {
|
|
156
|
+
this.client = createClient(config);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Check an agent's reputation
|
|
161
|
+
*/
|
|
162
|
+
async check(agentDid: string): Promise<ReputationResult> {
|
|
163
|
+
const result = await this.client.reputation.getReputation(agentDid as DID);
|
|
164
|
+
|
|
165
|
+
// Overall score is 0-100, normalize to 0-1
|
|
166
|
+
const score = (result.overall || 0) / 100;
|
|
167
|
+
|
|
168
|
+
// Try to get ERC-8004 status
|
|
169
|
+
let erc8004Enabled = false;
|
|
170
|
+
let erc8004AgentId: string | undefined;
|
|
171
|
+
try {
|
|
172
|
+
const erc8004Status = await this.client.reputation.getERC8004Status();
|
|
173
|
+
erc8004Enabled = erc8004Status.enabled;
|
|
174
|
+
} catch {
|
|
175
|
+
// ERC-8004 status not available
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
score,
|
|
180
|
+
level: getLevel(score),
|
|
181
|
+
totalContributions: 0, // Not available in current API
|
|
182
|
+
totalPayments: 0, // Not available in current API
|
|
183
|
+
erc8004Enabled,
|
|
184
|
+
erc8004AgentId,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Check if an agent meets minimum reputation threshold
|
|
190
|
+
*/
|
|
191
|
+
async meetsThreshold(agentDid: string, minScore: number): Promise<boolean> {
|
|
192
|
+
const result = await this.check(agentDid);
|
|
193
|
+
return result.score >= minScore;
|
|
194
|
+
}
|
|
195
|
+
}
|
package/src/retriever.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Xache Retriever for LangChain.js
|
|
3
|
+
* Memory retrieval for RAG pipelines with verifiable receipts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { BaseRetriever, BaseRetrieverInput } from '@langchain/core/retrievers';
|
|
7
|
+
import { Document } from '@langchain/core/documents';
|
|
8
|
+
import { CallbackManagerForRetrieverRun } from '@langchain/core/callbacks/manager';
|
|
9
|
+
import { XacheClient, DID } from '@xache/sdk';
|
|
10
|
+
|
|
11
|
+
export interface XacheRetrieverConfig extends BaseRetrieverInput {
|
|
12
|
+
/** Wallet address for authentication */
|
|
13
|
+
walletAddress: string;
|
|
14
|
+
/** Private key for signing */
|
|
15
|
+
privateKey: string;
|
|
16
|
+
/** Number of documents to retrieve */
|
|
17
|
+
k?: number;
|
|
18
|
+
/** Filter by context */
|
|
19
|
+
context?: string;
|
|
20
|
+
/** API URL (defaults to https://api.xache.xyz) */
|
|
21
|
+
apiUrl?: string;
|
|
22
|
+
/** Chain: 'base' or 'solana' */
|
|
23
|
+
chain?: 'base' | 'solana';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Retriever that fetches documents from Xache memory storage.
|
|
28
|
+
*
|
|
29
|
+
* Use this for RAG pipelines with persistent, verifiable document storage.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { XacheRetriever } from '@xache/langchain';
|
|
34
|
+
* import { ChatOpenAI } from '@langchain/openai';
|
|
35
|
+
* import { RetrievalQAChain } from 'langchain/chains';
|
|
36
|
+
*
|
|
37
|
+
* const retriever = new XacheRetriever({
|
|
38
|
+
* walletAddress: '0x...',
|
|
39
|
+
* privateKey: '0x...',
|
|
40
|
+
* k: 5,
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* const qa = RetrievalQAChain.fromLLM(new ChatOpenAI(), retriever);
|
|
44
|
+
* const result = await qa.call({ query: 'What do you know about X?' });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export class XacheRetriever extends BaseRetriever {
|
|
48
|
+
lc_namespace = ['xache', 'retriever'];
|
|
49
|
+
|
|
50
|
+
static lc_name() {
|
|
51
|
+
return 'XacheRetriever';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private client: XacheClient;
|
|
55
|
+
private k: number;
|
|
56
|
+
private filterContext?: string;
|
|
57
|
+
|
|
58
|
+
constructor(config: XacheRetrieverConfig) {
|
|
59
|
+
super(config);
|
|
60
|
+
|
|
61
|
+
const chainPrefix = config.chain === 'solana' ? 'sol' : 'evm';
|
|
62
|
+
const did = `did:agent:${chainPrefix}:${config.walletAddress.toLowerCase()}` as DID;
|
|
63
|
+
|
|
64
|
+
this.client = new XacheClient({
|
|
65
|
+
apiUrl: config.apiUrl || 'https://api.xache.xyz',
|
|
66
|
+
did,
|
|
67
|
+
privateKey: config.privateKey,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
this.k = config.k ?? 5;
|
|
71
|
+
this.filterContext = config.context;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async _getRelevantDocuments(
|
|
75
|
+
_query: string,
|
|
76
|
+
_runManager?: CallbackManagerForRetrieverRun
|
|
77
|
+
): Promise<Document[]> {
|
|
78
|
+
// Use list method to get memories filtered by context
|
|
79
|
+
const result = await this.client.memory.list({
|
|
80
|
+
context: this.filterContext,
|
|
81
|
+
limit: this.k,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const memories = result.memories || [];
|
|
85
|
+
|
|
86
|
+
return memories.map(
|
|
87
|
+
(m) =>
|
|
88
|
+
new Document({
|
|
89
|
+
pageContent: m.context || '',
|
|
90
|
+
metadata: {
|
|
91
|
+
storageKey: m.storage_key,
|
|
92
|
+
context: m.context,
|
|
93
|
+
tier: m.storage_tier,
|
|
94
|
+
createdAt: m.created_at,
|
|
95
|
+
size: m.size_bytes,
|
|
96
|
+
},
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|