@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 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
+ }
@@ -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);