slashvibe-mcp 0.3.21 → 0.3.23
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/LICENSE +21 -0
- package/README.md +280 -47
- package/auto-update.js +10 -15
- package/config.js +36 -31
- package/crypto.js +1 -6
- package/debug.js +12 -0
- package/discord.js +19 -19
- package/eslint.config.js +54 -0
- package/index.js +217 -207
- package/intelligence/index.js +2 -9
- package/intelligence/infer.js +10 -16
- package/intelligence/patterns.js +23 -18
- package/intelligence/proactive.js +16 -15
- package/intelligence/serendipity.js +57 -20
- package/memory.js +13 -8
- package/migrate-v2.js +72 -0
- package/notification-emitter.js +2 -2
- package/notify.js +39 -14
- package/package.json +28 -29
- package/post-install.js +141 -0
- package/presence.js +2 -2
- package/prompts.js +5 -9
- package/protocol/index.js +123 -87
- package/protocol/telegram-commands.js +36 -37
- package/store/api.js +358 -529
- package/store/local.js +9 -10
- package/store/profiles.js +48 -192
- package/store/reservations.js +2 -9
- package/store/skills.js +69 -71
- package/store/sqlite.js +355 -0
- package/test-skills-bootstrap.js +20 -0
- package/test-v2-integration.js +385 -0
- package/tools/_actions.js +48 -387
- package/tools/_connection-queue.js +45 -56
- package/tools/_discovery-enhanced.js +52 -57
- package/tools/_discovery.js +87 -185
- package/tools/{l2-status.js → _experimental/l2-status.js} +68 -70
- package/tools/{shipback.js → _experimental/shipback.js} +4 -3
- package/tools/_proactive-discovery.js +60 -73
- package/tools/_shared/index.js +41 -64
- package/tools/admin-inbox.js +10 -15
- package/tools/agents.js +1 -1
- package/tools/artifact-create.js +13 -23
- package/tools/artifact-view.js +4 -4
- package/tools/{_deprecated/back.js → back.js} +1 -1
- package/tools/bye.js +3 -5
- package/tools/consent.js +2 -2
- package/tools/context.js +9 -10
- package/tools/crossword.js +3 -2
- package/tools/discover.js +94 -356
- package/tools/dm.js +27 -86
- package/tools/doctor.js +12 -41
- package/tools/drawing.js +34 -20
- package/tools/echo.js +11 -11
- package/tools/feed.js +30 -58
- package/tools/follow.js +64 -187
- package/tools/{_deprecated/forget.js → forget.js} +4 -7
- package/tools/game.js +144 -48
- package/tools/handoff.js +6 -8
- package/tools/help.js +3 -3
- package/tools/idea.js +15 -27
- package/tools/inbox.js +121 -293
- package/tools/init.js +54 -151
- package/tools/invite.js +8 -21
- package/tools/migrate.js +27 -24
- package/tools/multiplayer-game.js +50 -40
- package/tools/{_deprecated/mute.js → mute.js} +4 -3
- package/tools/notifications.js +58 -48
- package/tools/observe.js +12 -15
- package/tools/onboarding.js +8 -11
- package/tools/open.js +13 -144
- package/tools/party-game.js +23 -12
- package/tools/patterns.js +2 -1
- package/tools/ping.js +5 -7
- package/tools/react.js +28 -30
- package/tools/{_deprecated/recall.js → recall.js} +5 -10
- package/tools/release.js +4 -2
- package/tools/{_deprecated/remember.js → remember.js} +4 -6
- package/tools/report.js +2 -2
- package/tools/request.js +6 -26
- package/tools/reserve.js +1 -1
- package/tools/session-fork.js +97 -0
- package/tools/session-save.js +109 -0
- package/tools/settings.js +30 -99
- package/tools/ship.js +74 -56
- package/tools/{_deprecated/skills-exchange.js → skills-exchange.js} +38 -39
- package/tools/social-inbox.js +22 -28
- package/tools/social-post.js +24 -27
- package/tools/solo-game.js +54 -46
- package/tools/start.js +14 -148
- package/tools/status.js +21 -68
- package/tools/submit.js +4 -2
- package/tools/suggest-tags.js +36 -33
- package/tools/summarize.js +19 -16
- package/tools/tag-suggestions.js +72 -73
- package/tools/test.js +1 -1
- package/tools/{_deprecated/tictactoe.js → tictactoe.js} +26 -26
- package/tools/token.js +4 -4
- package/tools/update.js +1 -2
- package/tools/watch.js +132 -112
- package/tools/who.js +20 -40
- package/tools/{_deprecated/wordassociation.js → wordassociation.js} +23 -20
- package/tools/workshop-buddy.js +52 -53
- package/tools/x-mentions.js +0 -1
- package/tools/x-reply.js +0 -1
- package/twitter.js +14 -20
- package/version.json +8 -10
- package/webhook-runner.js +132 -0
- package/auth-store.js +0 -148
- package/bridges/bridge-monitor.js +0 -388
- package/bridges/discord-bot.js +0 -431
- package/bridges/farcaster.js +0 -299
- package/bridges/telegram.js +0 -261
- package/bridges/webhook-health.js +0 -420
- package/bridges/webhook-server.js +0 -437
- package/bridges/whatsapp.js +0 -441
- package/bridges/x-webhook.js +0 -423
- package/games/arcade.js +0 -406
- package/games/chess.js +0 -451
- package/games/colorguess.js +0 -343
- package/games/crossword-words.js +0 -171
- package/games/crossword.js +0 -461
- package/games/drawing.js +0 -347
- package/games/gameroulette.js +0 -300
- package/games/gamerouter.js +0 -336
- package/games/gamestatus.js +0 -337
- package/games/guessnumber.js +0 -209
- package/games/hangman.js +0 -279
- package/games/memory.js +0 -338
- package/games/multiplayer-tictactoe.js +0 -389
- package/games/pixelart.js +0 -399
- package/games/quickduel.js +0 -354
- package/games/riddle.js +0 -371
- package/games/rockpaperscissors.js +0 -291
- package/games/snake.js +0 -406
- package/games/storybuilder.js +0 -343
- package/games/tictactoe.js +0 -345
- package/games/twentyquestions.js +0 -286
- package/games/twotruths.js +0 -207
- package/games/werewolf.js +0 -508
- package/games/wordassociation.js +0 -247
- package/games/wordchain.js +0 -135
- package/intelligence/interests.js +0 -369
- package/setup.js +0 -480
- package/smart-inbox.js +0 -276
- package/tools/_deprecated/auto-suggest-connections.js +0 -304
- package/tools/_deprecated/bootstrap-skills.js +0 -231
- package/tools/_deprecated/bridge-dashboard.js +0 -342
- package/tools/_deprecated/bridge-health.js +0 -400
- package/tools/_deprecated/bridge-live.js +0 -384
- package/tools/_deprecated/bridges.js +0 -383
- package/tools/_deprecated/colorguess.js +0 -281
- package/tools/_deprecated/discover-insights.js +0 -379
- package/tools/_deprecated/discover-momentum.js +0 -256
- package/tools/_deprecated/discovery-analytics.js +0 -345
- package/tools/_deprecated/discovery-auto-suggest.js +0 -275
- package/tools/_deprecated/discovery-bootstrap.js +0 -267
- package/tools/_deprecated/discovery-daily.js +0 -375
- package/tools/_deprecated/discovery-dashboard.js +0 -385
- package/tools/_deprecated/discovery-digest.js +0 -314
- package/tools/_deprecated/discovery-hub.js +0 -357
- package/tools/_deprecated/discovery-insights.js +0 -384
- package/tools/_deprecated/discovery-momentum.js +0 -281
- package/tools/_deprecated/discovery-monitor.js +0 -319
- package/tools/_deprecated/discovery-proactive.js +0 -300
- package/tools/_deprecated/draw.js +0 -317
- package/tools/_deprecated/farcaster.js +0 -307
- package/tools/_deprecated/games-catalog.js +0 -376
- package/tools/_deprecated/games.js +0 -313
- package/tools/_deprecated/guessnumber.js +0 -194
- package/tools/_deprecated/hangman.js +0 -129
- package/tools/_deprecated/multiplayer-tictactoe.js +0 -303
- package/tools/_deprecated/riddle.js +0 -240
- package/tools/_deprecated/run-bootstrap.js +0 -69
- package/tools/_deprecated/skills-analytics.js +0 -349
- package/tools/_deprecated/skills-bootstrap.js +0 -301
- package/tools/_deprecated/skills-dashboard.js +0 -268
- package/tools/_deprecated/skills.js +0 -380
- package/tools/_deprecated/smart-intro.js +0 -353
- package/tools/_deprecated/storybuilder.js +0 -331
- package/tools/_deprecated/telegram-bot.js +0 -183
- package/tools/_deprecated/telegram-setup.js +0 -214
- package/tools/_deprecated/twentyquestions.js +0 -143
- package/tools/_shared.js +0 -234
- package/tools/_work-context.js +0 -338
- package/tools/_work-context.manual-test.js +0 -199
- package/tools/_work-context.test.js +0 -260
- package/tools/activity.js +0 -220
- package/tools/agent-treasury.js +0 -288
- package/tools/analytics.js +0 -191
- package/tools/approve.js +0 -197
- package/tools/arcade.js +0 -173
- package/tools/artifacts-price.js +0 -107
- package/tools/ask-expert.js +0 -160
- package/tools/available.js +0 -120
- package/tools/become-expert.js +0 -150
- package/tools/broadcast.js +0 -325
- package/tools/chat.js +0 -202
- package/tools/collaborative-drawing.js +0 -286
- package/tools/connection-status.js +0 -178
- package/tools/earnings.js +0 -126
- package/tools/friends.js +0 -207
- package/tools/genesis.js +0 -233
- package/tools/gig-browse.js +0 -206
- package/tools/gig-complete.js +0 -144
- package/tools/health.js +0 -87
- package/tools/leaderboard.js +0 -117
- package/tools/lib/git-apply.js +0 -206
- package/tools/lib/git-bundle.js +0 -407
- package/tools/mint.js +0 -377
- package/tools/plan.js +0 -225
- package/tools/profile.js +0 -219
- package/tools/proof-of-work.js +0 -144
- package/tools/pulse.js +0 -218
- package/tools/reply.js +0 -166
- package/tools/reputation.js +0 -175
- package/tools/schedule.js +0 -367
- package/tools/search-messages.js +0 -123
- package/tools/session.js +0 -467
- package/tools/session_price.js +0 -128
- package/tools/smart-check.js +0 -201
- package/tools/social-processor.js +0 -445
- package/tools/streak.js +0 -147
- package/tools/stuck.js +0 -297
- package/tools/subscribe.js +0 -148
- package/tools/subscriptions.js +0 -134
- package/tools/tip.js +0 -193
- package/tools/wallet.js +0 -269
- package/tools/webhook-test.js +0 -388
- package/tools/withdraw.js +0 -145
- package/tools/work-summary.js +0 -96
- package/tools/workshop.js +0 -327
- /package/tools/{l2-bridge.js → _experimental/l2-bridge.js} +0 -0
- /package/tools/{l2.js → _experimental/l2.js} +0 -0
- /package/tools/{_deprecated/away.js → away.js} +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Test the skills bootstrap functionality
|
|
2
|
+
const skillsBootstrap = require('./tools/skills-bootstrap.js');
|
|
3
|
+
|
|
4
|
+
async function testBootstrap() {
|
|
5
|
+
try {
|
|
6
|
+
console.log('Testing skills bootstrap...');
|
|
7
|
+
|
|
8
|
+
// Check status first
|
|
9
|
+
const statusResult = await skillsBootstrap.handler({ action: 'status' });
|
|
10
|
+
console.log('Status check:', statusResult);
|
|
11
|
+
|
|
12
|
+
// Seed the marketplace
|
|
13
|
+
const seedResult = await skillsBootstrap.handler({ action: 'seed' });
|
|
14
|
+
console.log('Seed result:', seedResult);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error('Bootstrap test failed:', error);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
testBootstrap();
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* V2 Postgres Integration Test Suite
|
|
4
|
+
*
|
|
5
|
+
* Tests the complete message flow:
|
|
6
|
+
* 1. SQLite schema validation
|
|
7
|
+
* 2. Message saving (optimistic UI)
|
|
8
|
+
* 3. thread_id extraction from V2 API
|
|
9
|
+
* 4. Message status updates
|
|
10
|
+
* 5. Thread retrieval
|
|
11
|
+
*
|
|
12
|
+
* Run: node test-v2-integration.js
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const Database = require('better-sqlite3');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const os = require('os');
|
|
18
|
+
const sqlite = require('./store/sqlite');
|
|
19
|
+
|
|
20
|
+
const DB_PATH = path.join(os.homedir(), '.vibecodings', 'sessions.db');
|
|
21
|
+
|
|
22
|
+
class V2IntegrationTest {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.db = new Database(DB_PATH);
|
|
25
|
+
this.results = {
|
|
26
|
+
passed: [],
|
|
27
|
+
failed: [],
|
|
28
|
+
warnings: []
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
log(emoji, message) {
|
|
33
|
+
console.log(`${emoji} ${message}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pass(test, details = '') {
|
|
37
|
+
this.results.passed.push({ test, details });
|
|
38
|
+
this.log('✅', `${test}${details ? ': ' + details : ''}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fail(test, error) {
|
|
42
|
+
this.results.failed.push({ test, error });
|
|
43
|
+
this.log('❌', `${test}: ${error}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
warn(test, message) {
|
|
47
|
+
this.results.warnings.push({ test, message });
|
|
48
|
+
this.log('⚠️', `${test}: ${message}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Test 1: Schema Validation
|
|
52
|
+
testSchema() {
|
|
53
|
+
this.log('🔍', 'Test 1: Validating SQLite schema...');
|
|
54
|
+
|
|
55
|
+
const columns = this.db.prepare('PRAGMA table_info(messages)').all();
|
|
56
|
+
const columnNames = columns.map(c => c.name);
|
|
57
|
+
|
|
58
|
+
const requiredColumns = [
|
|
59
|
+
'local_id',
|
|
60
|
+
'server_id',
|
|
61
|
+
'thread_id', // V2 requirement
|
|
62
|
+
'from_handle',
|
|
63
|
+
'to_handle',
|
|
64
|
+
'content',
|
|
65
|
+
'created_at',
|
|
66
|
+
'status',
|
|
67
|
+
'sent_at',
|
|
68
|
+
'delivered_at',
|
|
69
|
+
'read_at',
|
|
70
|
+
'synced_at',
|
|
71
|
+
'retry_count'
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
const missing = requiredColumns.filter(col => !columnNames.includes(col));
|
|
75
|
+
|
|
76
|
+
if (missing.length > 0) {
|
|
77
|
+
this.fail('Schema validation', `Missing columns: ${missing.join(', ')}`);
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.pass('Schema validation', `All ${requiredColumns.length} columns present`);
|
|
82
|
+
|
|
83
|
+
// Check indexes
|
|
84
|
+
const indexes = this.db.prepare("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='messages'").all();
|
|
85
|
+
const indexNames = indexes.map(i => i.name);
|
|
86
|
+
|
|
87
|
+
if (!indexNames.includes('idx_messages_thread_id')) {
|
|
88
|
+
this.warn('Index check', 'idx_messages_thread_id missing');
|
|
89
|
+
} else {
|
|
90
|
+
this.pass('Index check', 'thread_id index exists');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Test 2: Message Saving (Optimistic UI)
|
|
97
|
+
testMessageSaving() {
|
|
98
|
+
this.log('🔍', 'Test 2: Testing optimistic message save...');
|
|
99
|
+
|
|
100
|
+
const testMessage = {
|
|
101
|
+
from_handle: 'test_alice',
|
|
102
|
+
to_handle: 'test_bob',
|
|
103
|
+
content: 'Test message for V2 integration',
|
|
104
|
+
status: 'pending'
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const local_id = sqlite.saveLocalMessage(testMessage);
|
|
109
|
+
|
|
110
|
+
if (!local_id) {
|
|
111
|
+
this.fail('Message saving', 'No local_id returned');
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Verify it was saved
|
|
116
|
+
const saved = this.db.prepare('SELECT * FROM messages WHERE local_id = ?').get(local_id);
|
|
117
|
+
|
|
118
|
+
if (!saved) {
|
|
119
|
+
this.fail('Message saving', 'Message not found after save');
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (saved.status !== 'pending') {
|
|
124
|
+
this.fail('Message saving', `Expected status 'pending', got '${saved.status}'`);
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this.pass('Message saving', `Saved with local_id: ${local_id.slice(0, 12)}...`);
|
|
129
|
+
return local_id;
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.fail('Message saving', error.message);
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Test 3: Status Update with thread_id
|
|
137
|
+
testStatusUpdate(local_id) {
|
|
138
|
+
if (!local_id) {
|
|
139
|
+
this.warn('Status update', 'Skipped (no local_id from previous test)');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.log('🔍', 'Test 3: Testing status update with thread_id...');
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
// Simulate V2 API response with server_id and thread_id
|
|
147
|
+
const server_id = 'msg_test_' + Date.now();
|
|
148
|
+
const thread_id = 'thread_test_' + Date.now();
|
|
149
|
+
|
|
150
|
+
sqlite.updateMessageStatus(local_id, 'sent', server_id, thread_id);
|
|
151
|
+
|
|
152
|
+
// Verify update
|
|
153
|
+
const updated = this.db.prepare('SELECT * FROM messages WHERE local_id = ?').get(local_id);
|
|
154
|
+
|
|
155
|
+
if (updated.status !== 'sent') {
|
|
156
|
+
this.fail('Status update', `Expected status 'sent', got '${updated.status}'`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (updated.server_id !== server_id) {
|
|
161
|
+
this.fail('Status update', `server_id mismatch`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (updated.thread_id !== thread_id) {
|
|
166
|
+
this.fail('Status update', `thread_id not saved correctly`);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (!updated.sent_at) {
|
|
171
|
+
this.warn('Status update', 'sent_at timestamp not set');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.pass('Status update', `Status: ${updated.status}, thread_id: ${thread_id.slice(0, 20)}...`);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
this.fail('Status update', error.message);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Test 4: Thread Retrieval
|
|
181
|
+
testThreadRetrieval() {
|
|
182
|
+
this.log('🔍', 'Test 4: Testing thread retrieval...');
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
const messages = sqlite.getThreadMessages('test_alice', 'test_bob', 100);
|
|
186
|
+
|
|
187
|
+
if (!Array.isArray(messages)) {
|
|
188
|
+
this.fail('Thread retrieval', 'Did not return an array');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (messages.length === 0) {
|
|
193
|
+
this.warn('Thread retrieval', 'No messages found (expected from test 2)');
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const msg = messages[0];
|
|
198
|
+
|
|
199
|
+
// Check that thread_id is included
|
|
200
|
+
if (msg.thread_id === undefined) {
|
|
201
|
+
this.fail('Thread retrieval', 'Message missing thread_id field');
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
this.pass('Thread retrieval', `Retrieved ${messages.length} message(s) with thread_id`);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
this.fail('Thread retrieval', error.message);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Test 5: Merge Server Messages (V2 format)
|
|
212
|
+
testMergeServerMessages() {
|
|
213
|
+
this.log('🔍', 'Test 5: Testing server message merge with V2 format...');
|
|
214
|
+
|
|
215
|
+
const v2Messages = [
|
|
216
|
+
{
|
|
217
|
+
id: 'msg_server_001',
|
|
218
|
+
thread_id: 'thread_xyz',
|
|
219
|
+
from: 'server_alice',
|
|
220
|
+
to: 'server_bob',
|
|
221
|
+
body: 'Server message 1',
|
|
222
|
+
created_at: new Date().toISOString()
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
id: 'msg_server_002',
|
|
226
|
+
thread_id: 'thread_xyz',
|
|
227
|
+
from: 'server_bob',
|
|
228
|
+
to: 'server_alice',
|
|
229
|
+
body: 'Server message 2',
|
|
230
|
+
created_at: new Date().toISOString()
|
|
231
|
+
}
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
const merged = sqlite.mergeServerMessages(v2Messages);
|
|
236
|
+
|
|
237
|
+
if (merged !== v2Messages.length) {
|
|
238
|
+
this.fail('Server message merge', `Expected ${v2Messages.length} merged, got ${merged}`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Verify messages were saved with thread_id
|
|
243
|
+
const saved = this.db
|
|
244
|
+
.prepare(
|
|
245
|
+
`
|
|
246
|
+
SELECT * FROM messages
|
|
247
|
+
WHERE server_id IN ('msg_server_001', 'msg_server_002')
|
|
248
|
+
ORDER BY created_at
|
|
249
|
+
`
|
|
250
|
+
)
|
|
251
|
+
.all();
|
|
252
|
+
|
|
253
|
+
if (saved.length !== 2) {
|
|
254
|
+
this.fail('Server message merge', `Expected 2 messages, found ${saved.length}`);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Check thread_id was preserved
|
|
259
|
+
const threadIds = saved.map(m => m.thread_id);
|
|
260
|
+
if (!threadIds.every(id => id === 'thread_xyz')) {
|
|
261
|
+
this.fail('Server message merge', 'thread_id not preserved correctly');
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
this.pass('Server message merge', `Merged ${merged} V2 messages with thread_id`);
|
|
266
|
+
} catch (error) {
|
|
267
|
+
this.fail('Server message merge', error.message);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Test 6: Code Review - Check api.js integration
|
|
272
|
+
testCodeIntegration() {
|
|
273
|
+
this.log('🔍', 'Test 6: Code integration check...');
|
|
274
|
+
|
|
275
|
+
const apiCode = require('fs').readFileSync('./store/api.js', 'utf-8');
|
|
276
|
+
|
|
277
|
+
// Check 1: sendMessage saves to SQLite
|
|
278
|
+
if (!apiCode.includes('sqlite.saveLocalMessage')) {
|
|
279
|
+
this.fail('Code integration', 'api.js missing sqlite.saveLocalMessage call');
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Check 2: sendMessage updates status with thread_id
|
|
284
|
+
if (!apiCode.includes('sqlite.updateMessageStatus')) {
|
|
285
|
+
this.fail('Code integration', 'api.js missing sqlite.updateMessageStatus call');
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Check 3: thread_id extraction from V2 response
|
|
290
|
+
if (!apiCode.includes('thread_id')) {
|
|
291
|
+
this.fail('Code integration', 'api.js not extracting thread_id from response');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Check 4: getThread uses sqlite
|
|
296
|
+
if (!apiCode.includes('sqlite.getThreadMessages')) {
|
|
297
|
+
this.fail('Code integration', 'api.js getThread not using SQLite');
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Check 5: getInbox uses sqlite
|
|
302
|
+
if (!apiCode.includes('sqlite.getInboxThreads')) {
|
|
303
|
+
this.warn('Code integration', 'api.js getInbox might not be using SQLite optimally');
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
this.pass('Code integration', 'All critical V2 integration points found in api.js');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Cleanup test data
|
|
310
|
+
cleanup() {
|
|
311
|
+
this.log('🧹', 'Cleaning up test data...');
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
this.db.exec(`
|
|
315
|
+
DELETE FROM messages
|
|
316
|
+
WHERE from_handle LIKE 'test_%'
|
|
317
|
+
OR from_handle LIKE 'server_%'
|
|
318
|
+
OR to_handle LIKE 'test_%'
|
|
319
|
+
OR to_handle LIKE 'server_%'
|
|
320
|
+
`);
|
|
321
|
+
this.pass('Cleanup', 'Test data removed');
|
|
322
|
+
} catch (error) {
|
|
323
|
+
this.warn('Cleanup', error.message);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Run all tests
|
|
328
|
+
async runAll() {
|
|
329
|
+
console.log('\n════════════════════════════════════════════════════════');
|
|
330
|
+
console.log(' V2 Postgres Integration Test Suite');
|
|
331
|
+
console.log('════════════════════════════════════════════════════════\n');
|
|
332
|
+
|
|
333
|
+
// Run tests
|
|
334
|
+
const schemaOk = this.testSchema();
|
|
335
|
+
|
|
336
|
+
if (schemaOk) {
|
|
337
|
+
const local_id = this.testMessageSaving();
|
|
338
|
+
this.testStatusUpdate(local_id);
|
|
339
|
+
this.testThreadRetrieval();
|
|
340
|
+
this.testMergeServerMessages();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
this.testCodeIntegration();
|
|
344
|
+
this.cleanup();
|
|
345
|
+
|
|
346
|
+
// Print summary
|
|
347
|
+
console.log('\n════════════════════════════════════════════════════════');
|
|
348
|
+
console.log(' Test Summary');
|
|
349
|
+
console.log('════════════════════════════════════════════════════════\n');
|
|
350
|
+
|
|
351
|
+
console.log(`✅ Passed: ${this.results.passed.length}`);
|
|
352
|
+
console.log(`❌ Failed: ${this.results.failed.length}`);
|
|
353
|
+
console.log(`⚠️ Warnings: ${this.results.warnings.length}`);
|
|
354
|
+
|
|
355
|
+
if (this.results.failed.length > 0) {
|
|
356
|
+
console.log('\n❌ Failed Tests:');
|
|
357
|
+
this.results.failed.forEach(({ test, error }) => {
|
|
358
|
+
console.log(` - ${test}: ${error}`);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (this.results.warnings.length > 0) {
|
|
363
|
+
console.log('\n⚠️ Warnings:');
|
|
364
|
+
this.results.warnings.forEach(({ test, message }) => {
|
|
365
|
+
console.log(` - ${test}: ${message}`);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
console.log('\n════════════════════════════════════════════════════════\n');
|
|
370
|
+
|
|
371
|
+
// Close database
|
|
372
|
+
this.db.close();
|
|
373
|
+
|
|
374
|
+
// Exit with appropriate code
|
|
375
|
+
process.exit(this.results.failed.length > 0 ? 1 : 0);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Run tests
|
|
380
|
+
if (require.main === module) {
|
|
381
|
+
const test = new V2IntegrationTest();
|
|
382
|
+
test.runAll();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
module.exports = V2IntegrationTest;
|