@emblemvault/agentwallet 1.0.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/auth.js +38 -0
- package/conversation.js +83 -0
- package/enhanced-hustle.js +102 -0
- package/package.json +52 -0
- package/reset-conversation.js +44 -0
- package/resume-conversation.js +124 -0
package/auth.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// auth.js - EmblemVault Authentication Module
|
|
2
|
+
import fetch from 'node-fetch';
|
|
3
|
+
|
|
4
|
+
export class EmblemAuth {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.authEndpoint = 'https://auth.emblemvault.ai/api/auth/password/verify';
|
|
7
|
+
this.appId = 'emblem-agent-wallet';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async authenticate(password) {
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetch(this.authEndpoint, {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: {
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
appId: this.appId,
|
|
19
|
+
password: password
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const data = await response.json();
|
|
24
|
+
|
|
25
|
+
if (!data.success) {
|
|
26
|
+
throw new Error('Authentication failed');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
vaultId: data.session.user.vaultId,
|
|
31
|
+
authToken: data.session.authToken,
|
|
32
|
+
expiresAt: data.session.expiresAt
|
|
33
|
+
};
|
|
34
|
+
} catch (error) {
|
|
35
|
+
throw new Error(`Auth error: ${error.message}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
package/conversation.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// conversation.js - Conversation History Manager
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export class ConversationManager {
|
|
6
|
+
constructor(conversationFile = '.hustle-conversation.json') {
|
|
7
|
+
this.conversationFile = conversationFile;
|
|
8
|
+
this.maxHistoryLength = 50; // Prevent unlimited growth
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async loadConversation() {
|
|
12
|
+
try {
|
|
13
|
+
const data = await fs.readFile(this.conversationFile, 'utf8');
|
|
14
|
+
return JSON.parse(data);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
// File doesn't exist or is corrupted, return fresh conversation
|
|
17
|
+
return {
|
|
18
|
+
messages: [],
|
|
19
|
+
created: new Date().toISOString(),
|
|
20
|
+
lastUpdated: new Date().toISOString(),
|
|
21
|
+
totalExchanges: 0
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async saveConversation(conversation) {
|
|
27
|
+
conversation.lastUpdated = new Date().toISOString();
|
|
28
|
+
|
|
29
|
+
// Trim conversation if too long
|
|
30
|
+
if (conversation.messages.length > this.maxHistoryLength) {
|
|
31
|
+
conversation.messages = conversation.messages.slice(-this.maxHistoryLength);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await fs.writeFile(
|
|
35
|
+
this.conversationFile,
|
|
36
|
+
JSON.stringify(conversation, null, 2),
|
|
37
|
+
'utf8'
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
addUserMessage(conversation, message) {
|
|
42
|
+
conversation.messages.push({
|
|
43
|
+
role: 'user',
|
|
44
|
+
content: message,
|
|
45
|
+
timestamp: new Date().toISOString()
|
|
46
|
+
});
|
|
47
|
+
return conversation;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
addAssistantMessage(conversation, content) {
|
|
51
|
+
conversation.messages.push({
|
|
52
|
+
role: 'assistant',
|
|
53
|
+
content: content,
|
|
54
|
+
timestamp: new Date().toISOString()
|
|
55
|
+
});
|
|
56
|
+
conversation.totalExchanges++;
|
|
57
|
+
return conversation;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async resetConversation() {
|
|
61
|
+
if (await this.conversationExists()) {
|
|
62
|
+
// Backup current conversation
|
|
63
|
+
const backup = `conversation-backup-${Date.now()}.json`;
|
|
64
|
+
await fs.copyFile(this.conversationFile, backup);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Delete current conversation
|
|
68
|
+
try {
|
|
69
|
+
await fs.unlink(this.conversationFile);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
// File doesn't exist, that's fine
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async conversationExists() {
|
|
76
|
+
try {
|
|
77
|
+
await fs.access(this.conversationFile);
|
|
78
|
+
return true;
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// enhanced-hustle.js - Main Application
|
|
3
|
+
import { program } from 'commander';
|
|
4
|
+
import fetch from 'node-fetch';
|
|
5
|
+
import { EmblemAuth } from './auth.js';
|
|
6
|
+
import { ConversationManager } from './conversation.js';
|
|
7
|
+
|
|
8
|
+
class EnhancedHustle {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.auth = new EmblemAuth();
|
|
11
|
+
this.conversation = new ConversationManager();
|
|
12
|
+
this.chatEndpoint = 'https://agenthustle.ai/api/chat';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async queryHustle(password, message) {
|
|
16
|
+
try {
|
|
17
|
+
console.log('š Authenticating...');
|
|
18
|
+
const authData = await this.auth.authenticate(password);
|
|
19
|
+
|
|
20
|
+
console.log(`š± VaultId: ${authData.vaultId}`);
|
|
21
|
+
|
|
22
|
+
console.log('š¾ Loading conversation history...');
|
|
23
|
+
let conversation = await this.conversation.loadConversation();
|
|
24
|
+
|
|
25
|
+
// Add user message to history
|
|
26
|
+
conversation = this.conversation.addUserMessage(conversation, message);
|
|
27
|
+
|
|
28
|
+
console.log('š Querying Hustle AI...');
|
|
29
|
+
const response = await fetch(this.chatEndpoint, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: {
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
'Authorization': `Bearer ${authData.authToken}`
|
|
34
|
+
},
|
|
35
|
+
body: JSON.stringify({
|
|
36
|
+
messages: conversation.messages.map(msg => ({
|
|
37
|
+
role: msg.role,
|
|
38
|
+
content: msg.content
|
|
39
|
+
})),
|
|
40
|
+
vaultId: authData.vaultId
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log('š” Processing response stream...');
|
|
49
|
+
const responseText = await response.text();
|
|
50
|
+
|
|
51
|
+
// Parse SSE response - extract content from 0: lines
|
|
52
|
+
const contentChunks = [];
|
|
53
|
+
const lines = responseText.split('\n');
|
|
54
|
+
|
|
55
|
+
for (const line of lines) {
|
|
56
|
+
if (line.startsWith('0:"')) {
|
|
57
|
+
// Remove 0:" prefix and trailing "
|
|
58
|
+
let content = line.slice(3, -1);
|
|
59
|
+
// Handle escaped characters
|
|
60
|
+
content = content.replace(/\\"/g, '"').replace(/\\n/g, '\n');
|
|
61
|
+
contentChunks.push(content);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const fullResponse = contentChunks.join('');
|
|
66
|
+
|
|
67
|
+
if (fullResponse.trim()) {
|
|
68
|
+
// Add assistant response to history
|
|
69
|
+
conversation = this.conversation.addAssistantMessage(conversation, fullResponse);
|
|
70
|
+
|
|
71
|
+
// Save updated conversation
|
|
72
|
+
await this.conversation.saveConversation(conversation);
|
|
73
|
+
|
|
74
|
+
console.log('\nš¤ Hustle AI Response:');
|
|
75
|
+
console.log('ā'.repeat(50));
|
|
76
|
+
console.log(fullResponse);
|
|
77
|
+
console.log('ā'.repeat(50));
|
|
78
|
+
console.log(`š¬ Total exchanges: ${conversation.totalExchanges}`);
|
|
79
|
+
} else {
|
|
80
|
+
console.log('ā ļø Empty response received');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('ā Error:', error.message);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// CLI Setup
|
|
91
|
+
program
|
|
92
|
+
.name('enhanced-hustle')
|
|
93
|
+
.description('Stateful conversation with EmblemVault Hustle AI')
|
|
94
|
+
.version('1.0.0')
|
|
95
|
+
.requiredOption('-p, --password <password>', 'EmblemVault password')
|
|
96
|
+
.requiredOption('-m, --message <message>', 'Message to send to Hustle AI')
|
|
97
|
+
.parse();
|
|
98
|
+
|
|
99
|
+
const options = program.opts();
|
|
100
|
+
const hustle = new EnhancedHustle();
|
|
101
|
+
|
|
102
|
+
hustle.queryHustle(options.password, options.message);
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@emblemvault/agentwallet",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI for EmblemVault Hustle AI - autonomous crypto wallet management",
|
|
5
|
+
"main": "enhanced-hustle.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"emblem-hustle": "./enhanced-hustle.js",
|
|
9
|
+
"emblem-resume": "./resume-conversation.js",
|
|
10
|
+
"emblem-reset": "./reset-conversation.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"start": "node enhanced-hustle.js",
|
|
14
|
+
"resume": "node resume-conversation.js",
|
|
15
|
+
"reset": "node reset-conversation.js"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"node-fetch": "^3.3.2",
|
|
19
|
+
"commander": "^11.1.0"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"ai",
|
|
23
|
+
"crypto",
|
|
24
|
+
"hustle",
|
|
25
|
+
"emblem",
|
|
26
|
+
"agent",
|
|
27
|
+
"wallet",
|
|
28
|
+
"solana",
|
|
29
|
+
"ethereum",
|
|
30
|
+
"defi",
|
|
31
|
+
"trading",
|
|
32
|
+
"openclaw"
|
|
33
|
+
],
|
|
34
|
+
"author": "EmblemVault",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/EmblemCompany/EmblemAi-AgentWallet.git"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://emblemvault.ai",
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18.0.0"
|
|
43
|
+
},
|
|
44
|
+
"files": [
|
|
45
|
+
"enhanced-hustle.js",
|
|
46
|
+
"resume-conversation.js",
|
|
47
|
+
"reset-conversation.js",
|
|
48
|
+
"auth.js",
|
|
49
|
+
"conversation.js",
|
|
50
|
+
"README.md"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// reset-conversation.js - Reset conversation history
|
|
3
|
+
import { ConversationManager } from './conversation.js';
|
|
4
|
+
|
|
5
|
+
class ConversationReset {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.conversation = new ConversationManager();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async resetConversation() {
|
|
11
|
+
try {
|
|
12
|
+
console.log('š Checking for existing conversation...');
|
|
13
|
+
|
|
14
|
+
const exists = await this.conversation.conversationExists();
|
|
15
|
+
|
|
16
|
+
if (!exists) {
|
|
17
|
+
console.log('ā¹ļø No conversation history found. Nothing to reset.');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Load current conversation to show stats
|
|
22
|
+
const currentConversation = await this.conversation.loadConversation();
|
|
23
|
+
console.log(`š Found conversation with ${currentConversation.totalExchanges} exchanges`);
|
|
24
|
+
console.log(`š
Created: ${currentConversation.created}`);
|
|
25
|
+
console.log(`š
Last updated: ${currentConversation.lastUpdated}`);
|
|
26
|
+
|
|
27
|
+
// Reset conversation (creates backup)
|
|
28
|
+
console.log('\nš¾ Creating backup and resetting...');
|
|
29
|
+
await this.conversation.resetConversation();
|
|
30
|
+
|
|
31
|
+
console.log('ā
Conversation reset complete!');
|
|
32
|
+
console.log('š¦ Previous conversation backed up');
|
|
33
|
+
console.log('š Ready for fresh conversation');
|
|
34
|
+
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('ā Reset failed:', error.message);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Execute reset
|
|
43
|
+
const reset = new ConversationReset();
|
|
44
|
+
reset.resetConversation();
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// resume-conversation.js - Resume conversation from last state
|
|
3
|
+
import { program } from 'commander';
|
|
4
|
+
import fetch from 'node-fetch';
|
|
5
|
+
import { EmblemAuth } from './auth.js';
|
|
6
|
+
import { ConversationManager } from './conversation.js';
|
|
7
|
+
|
|
8
|
+
class ResumeHustle {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.auth = new EmblemAuth();
|
|
11
|
+
this.conversation = new ConversationManager();
|
|
12
|
+
this.chatEndpoint = 'https://agenthustle.ai/api/chat';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async resumeConversation(password, message) {
|
|
16
|
+
try {
|
|
17
|
+
console.log('š Resuming conversation...');
|
|
18
|
+
|
|
19
|
+
// Load existing conversation
|
|
20
|
+
const conversationData = await this.conversation.loadConversation();
|
|
21
|
+
|
|
22
|
+
if (conversationData.messages.length === 0) {
|
|
23
|
+
console.log('ā ļø No existing conversation found. Starting fresh.');
|
|
24
|
+
} else {
|
|
25
|
+
console.log(`š Found ${conversationData.totalExchanges} previous exchanges`);
|
|
26
|
+
console.log(`š
Last updated: ${conversationData.lastUpdated}`);
|
|
27
|
+
|
|
28
|
+
// Show last few exchanges for context
|
|
29
|
+
const recentMessages = conversationData.messages.slice(-4);
|
|
30
|
+
console.log('\nš Recent conversation context:');
|
|
31
|
+
console.log('ā'.repeat(50));
|
|
32
|
+
|
|
33
|
+
for (const msg of recentMessages) {
|
|
34
|
+
const role = msg.role === 'user' ? 'š¤ User' : 'š¤ Assistant';
|
|
35
|
+
const preview = msg.content.length > 100
|
|
36
|
+
? msg.content.substring(0, 100) + '...'
|
|
37
|
+
: msg.content;
|
|
38
|
+
console.log(`${role}: ${preview}`);
|
|
39
|
+
}
|
|
40
|
+
console.log('ā'.repeat(50));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Continue conversation with new message
|
|
44
|
+
console.log('\nš Authenticating...');
|
|
45
|
+
const authData = await this.auth.authenticate(password);
|
|
46
|
+
|
|
47
|
+
console.log(`š± VaultId: ${authData.vaultId}`);
|
|
48
|
+
|
|
49
|
+
// Add new user message
|
|
50
|
+
const updatedConversation = this.conversation.addUserMessage(conversationData, message);
|
|
51
|
+
|
|
52
|
+
console.log('š Sending to Hustle AI...');
|
|
53
|
+
const response = await fetch(this.chatEndpoint, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: {
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
'Authorization': `Bearer ${authData.authToken}`
|
|
58
|
+
},
|
|
59
|
+
body: JSON.stringify({
|
|
60
|
+
messages: updatedConversation.messages.map(msg => ({
|
|
61
|
+
role: msg.role,
|
|
62
|
+
content: msg.content
|
|
63
|
+
})),
|
|
64
|
+
vaultId: authData.vaultId
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log('š” Processing response...');
|
|
73
|
+
const responseText = await response.text();
|
|
74
|
+
|
|
75
|
+
// Parse SSE response
|
|
76
|
+
const contentChunks = [];
|
|
77
|
+
const lines = responseText.split('\n');
|
|
78
|
+
|
|
79
|
+
for (const line of lines) {
|
|
80
|
+
if (line.startsWith('0:"')) {
|
|
81
|
+
let content = line.slice(3, -1);
|
|
82
|
+
content = content.replace(/\\"/g, '"').replace(/\\n/g, '\n');
|
|
83
|
+
contentChunks.push(content);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const fullResponse = contentChunks.join('');
|
|
88
|
+
|
|
89
|
+
if (fullResponse.trim()) {
|
|
90
|
+
// Add assistant response
|
|
91
|
+
const finalConversation = this.conversation.addAssistantMessage(updatedConversation, fullResponse);
|
|
92
|
+
|
|
93
|
+
// Save updated conversation
|
|
94
|
+
await this.conversation.saveConversation(finalConversation);
|
|
95
|
+
|
|
96
|
+
console.log('\nš¤ Hustle AI Response:');
|
|
97
|
+
console.log('ā'.repeat(50));
|
|
98
|
+
console.log(fullResponse);
|
|
99
|
+
console.log('ā'.repeat(50));
|
|
100
|
+
console.log(`š¬ Total exchanges: ${finalConversation.totalExchanges}`);
|
|
101
|
+
} else {
|
|
102
|
+
console.log('ā ļø Empty response received');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error('ā Error:', error.message);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// CLI Setup
|
|
113
|
+
program
|
|
114
|
+
.name('resume-conversation')
|
|
115
|
+
.description('Resume conversation with EmblemVault Hustle AI')
|
|
116
|
+
.version('1.0.0')
|
|
117
|
+
.requiredOption('-p, --password <password>', 'EmblemVault password')
|
|
118
|
+
.requiredOption('-m, --message <message>', 'New message to continue conversation')
|
|
119
|
+
.parse();
|
|
120
|
+
|
|
121
|
+
const options = program.opts();
|
|
122
|
+
const resumeHustle = new ResumeHustle();
|
|
123
|
+
|
|
124
|
+
resumeHustle.resumeConversation(options.password, options.message);
|