thumbgate 1.4.1 → 1.4.3
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/.claude-plugin/README.md +45 -34
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +3 -3
- package/.well-known/llms.txt +1 -1
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +26 -2
- package/adapters/README.md +4 -1
- package/adapters/chatgpt/INSTALL.md +39 -19
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/codex/config.toml +2 -2
- package/adapters/mcp/server-stdio.js +10 -4
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/perplexity/.mcp.json +36 -0
- package/adapters/perplexity/config.toml +16 -0
- package/adapters/perplexity/opencode.json +29 -0
- package/bin/cli.js +246 -90
- package/config/mcp-allowlists.json +11 -3
- package/package.json +28 -13
- package/plugins/claude-codex-bridge/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-codex-bridge/.mcp.json +1 -1
- package/plugins/codex-profile/.codex-plugin/plugin.json +1 -1
- package/plugins/codex-profile/.mcp.json +1 -1
- package/plugins/codex-profile/INSTALL.md +1 -1
- package/plugins/codex-profile/README.md +1 -1
- package/plugins/cursor-marketplace/.cursor-plugin/plugin.json +1 -1
- package/plugins/opencode-profile/INSTALL.md +1 -1
- package/public/index.html +121 -24
- package/public/llm-context.md +17 -1
- package/scripts/ai-search-visibility.js +10 -36
- package/scripts/audit-trail.js +25 -15
- package/scripts/auto-wire-hooks.js +127 -0
- package/scripts/cli-demo.js +102 -0
- package/scripts/cli-schema.js +285 -0
- package/scripts/cli-status.js +166 -0
- package/scripts/cross-encoder-reranker.js +235 -0
- package/scripts/explore-subcommands.js +277 -0
- package/scripts/explore.js +569 -0
- package/scripts/feedback-loop.js +20 -6
- package/scripts/lesson-inference.js +27 -2
- package/scripts/lesson-reranker.js +263 -0
- package/scripts/lesson-retrieval.js +34 -17
- package/scripts/lesson-search.js +69 -0
- package/scripts/perplexity-client.js +210 -0
- package/scripts/perplexity-command-center.js +644 -0
- package/scripts/perplexity-marketing.js +17 -29
- package/scripts/prove-packaged-runtime.js +5 -4
- package/scripts/ralph-mode-ci.js +122 -19
- package/scripts/reflector-agent.js +2 -2
- package/scripts/session-analyzer.js +533 -0
- package/scripts/social-analytics/db/marketing-db.js +179 -0
- package/scripts/social-analytics/db/schema.sql +23 -0
- package/scripts/social-analytics/generate-instagram-card.js +31 -5
- package/scripts/social-analytics/generate-slides.js +268 -0
- package/scripts/social-analytics/post-video.js +316 -0
- package/scripts/social-analytics/publishers/zernio.js +52 -23
- package/scripts/statusline-local-stats.js +3 -1
- package/scripts/statusline.sh +15 -10
- package/scripts/thumbgate-bench.js +494 -0
- package/src/api/server.js +65 -1
- package/scripts/social-analytics/db/analytics.sqlite +0 -0
|
@@ -21,10 +21,14 @@
|
|
|
21
21
|
|
|
22
22
|
const fs = require('fs');
|
|
23
23
|
const path = require('path');
|
|
24
|
+
const {
|
|
25
|
+
PerplexityClient,
|
|
26
|
+
extractChatText,
|
|
27
|
+
extractCitations,
|
|
28
|
+
} = require('./perplexity-client');
|
|
24
29
|
|
|
25
|
-
const API_KEY = process.env.PERPLEXITY_API_KEY;
|
|
26
30
|
const OUTPUT_DIR = path.join(__dirname, '..', '.amp', 'in', 'artifacts', 'marketing');
|
|
27
|
-
const
|
|
31
|
+
const perplexity = new PerplexityClient();
|
|
28
32
|
|
|
29
33
|
const PRODUCT = {
|
|
30
34
|
name: 'ThumbGate',
|
|
@@ -39,31 +43,15 @@ const PRODUCT = {
|
|
|
39
43
|
};
|
|
40
44
|
|
|
41
45
|
async function sonarRequest(model, messages, options = {}) {
|
|
42
|
-
if (!
|
|
46
|
+
if (!perplexity.hasApiKey()) {
|
|
43
47
|
throw new Error('PERPLEXITY_API_KEY not set. Get yours at https://www.perplexity.ai/settings/api');
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
return perplexity.chatCompletion({
|
|
47
51
|
model,
|
|
48
52
|
messages,
|
|
49
|
-
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const resp = await fetch(SONAR_URL, {
|
|
53
|
-
method: 'POST',
|
|
54
|
-
headers: {
|
|
55
|
-
'Authorization': `Bearer ${API_KEY}`,
|
|
56
|
-
'Content-Type': 'application/json',
|
|
57
|
-
},
|
|
58
|
-
body: JSON.stringify(body),
|
|
53
|
+
options,
|
|
59
54
|
});
|
|
60
|
-
|
|
61
|
-
if (!resp.ok) {
|
|
62
|
-
const text = await resp.text();
|
|
63
|
-
throw new Error(`Perplexity API ${resp.status}: ${text}`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return resp.json();
|
|
67
55
|
}
|
|
68
56
|
|
|
69
57
|
function ensureOutputDir() {
|
|
@@ -107,8 +95,8 @@ Be specific with URLs, community names, and actionable steps.`,
|
|
|
107
95
|
},
|
|
108
96
|
]);
|
|
109
97
|
|
|
110
|
-
const content = result
|
|
111
|
-
const citations = result
|
|
98
|
+
const content = extractChatText(result);
|
|
99
|
+
const citations = extractCitations(result);
|
|
112
100
|
|
|
113
101
|
let output = `# Market Research Report — ThumbGate\n\nGenerated: ${new Date().toISOString()}\n\n`;
|
|
114
102
|
output += content;
|
|
@@ -149,8 +137,8 @@ async function findThreads() {
|
|
|
149
137
|
web_search_options: { search_context_size: 'high' },
|
|
150
138
|
});
|
|
151
139
|
|
|
152
|
-
const content = result
|
|
153
|
-
const citations = result
|
|
140
|
+
const content = extractChatText(result);
|
|
141
|
+
const citations = extractCitations(result);
|
|
154
142
|
results.push({ query: q, content, citations });
|
|
155
143
|
} catch (err) {
|
|
156
144
|
console.log(` ⚠ Query failed: ${q} — ${err.message}`);
|
|
@@ -314,7 +302,7 @@ Requirements:
|
|
|
314
302
|
web_search_options: { search_context_size: 'low' },
|
|
315
303
|
});
|
|
316
304
|
|
|
317
|
-
const content = result
|
|
305
|
+
const content = extractChatText(result);
|
|
318
306
|
saveOutput(platform.file, `# ${platform.name.toUpperCase()} — Launch Post\n\nGenerated: ${new Date().toISOString()}\n\n${content}`);
|
|
319
307
|
posts.push({ platform: platform.name, content });
|
|
320
308
|
} catch (err) {
|
|
@@ -358,7 +346,7 @@ Make all content factually accurate and technically specific.`,
|
|
|
358
346
|
web_search_options: { search_context_size: 'medium' },
|
|
359
347
|
});
|
|
360
348
|
|
|
361
|
-
const content = result
|
|
349
|
+
const content = extractChatText(result);
|
|
362
350
|
saveOutput('04-seo-geo-content.md', `# SEO/GEO Optimization Content\n\nGenerated: ${new Date().toISOString()}\n\n${content}`);
|
|
363
351
|
console.log(' ✓ SEO content generated\n');
|
|
364
352
|
return content;
|
|
@@ -389,7 +377,7 @@ Include [PERSONALIZATION] placeholders.`,
|
|
|
389
377
|
},
|
|
390
378
|
]);
|
|
391
379
|
|
|
392
|
-
const content = result
|
|
380
|
+
const content = extractChatText(result);
|
|
393
381
|
saveOutput('05-outreach-templates.md', `# Outreach Templates\n\nGenerated: ${new Date().toISOString()}\n\n${content}`);
|
|
394
382
|
console.log(' ✓ Outreach templates generated\n');
|
|
395
383
|
return content;
|
|
@@ -405,7 +393,7 @@ async function main() {
|
|
|
405
393
|
console.log('║ ThumbGate — First Dollar Campaign ║');
|
|
406
394
|
console.log('╚══════════════════════════════════════════════════════╝');
|
|
407
395
|
|
|
408
|
-
if (!
|
|
396
|
+
if (!perplexity.hasApiKey()) {
|
|
409
397
|
console.error('\n❌ PERPLEXITY_API_KEY not set.');
|
|
410
398
|
console.error(' Add it to .env: PERPLEXITY_API_KEY=pplx-...');
|
|
411
399
|
console.error(' Get your key: https://www.perplexity.ai/settings/api\n');
|
|
@@ -71,14 +71,14 @@ function isTransientRegistryMiss(error) {
|
|
|
71
71
|
]
|
|
72
72
|
.filter(Boolean)
|
|
73
73
|
.join('\n');
|
|
74
|
-
return /ETARGET|No matching version found|npm error code E404|404 Not Found/i.test(text);
|
|
74
|
+
return /ETARGET|No matching version found|npm error code E404|404 Not Found|ETIMEDOUT|ENETUNREACH|ECONNRESET|EAI_AGAIN|ECONNREFUSED|network timeout/i.test(text);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
async function installPackageWithRetry(prefixDir, packageSpec, options = {}) {
|
|
78
78
|
const installImpl = options.installImpl || installPackage;
|
|
79
79
|
const sleepImpl = options.sleepImpl || sleep;
|
|
80
80
|
const remotePackage = options.remotePackage !== undefined ? options.remotePackage : isRemotePackageSpec(packageSpec);
|
|
81
|
-
const attempts =
|
|
81
|
+
const attempts = Number(options.attempts || (remotePackage ? DEFAULT_PUBLISH_INSTALL_RETRIES : 3));
|
|
82
82
|
let delayMs = Number(options.delayMs || DEFAULT_PUBLISH_INSTALL_DELAY_MS);
|
|
83
83
|
let lastError = null;
|
|
84
84
|
|
|
@@ -90,12 +90,13 @@ async function installPackageWithRetry(prefixDir, packageSpec, options = {}) {
|
|
|
90
90
|
return installImpl(prefixDir, packageSpec);
|
|
91
91
|
} catch (error) {
|
|
92
92
|
lastError = error;
|
|
93
|
-
const
|
|
93
|
+
const transient = isTransientRegistryMiss(error);
|
|
94
|
+
const retryable = transient && attempt < attempts;
|
|
94
95
|
if (!retryable) {
|
|
95
96
|
throw error;
|
|
96
97
|
}
|
|
97
98
|
process.stderr.write(
|
|
98
|
-
`Retrying
|
|
99
|
+
`Retrying package install for ${packageSpec} after transient npm failure (${attempt}/${attempts - 1})\n`
|
|
99
100
|
);
|
|
100
101
|
await sleepImpl(delayMs);
|
|
101
102
|
delayMs = Math.min(Math.round(delayMs * 1.5), MAX_PUBLISH_INSTALL_DELAY_MS);
|
package/scripts/ralph-mode-ci.js
CHANGED
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
const crypto = require('crypto');
|
|
11
11
|
const https = require('https');
|
|
12
12
|
|
|
13
|
-
// ── Env
|
|
14
|
-
const X_API_KEY = process.env.X_API_KEY;
|
|
15
|
-
const X_API_SECRET = process.env.X_API_SECRET;
|
|
16
|
-
const X_ACCESS_TOKEN = process.env.X_ACCESS_TOKEN;
|
|
17
|
-
const X_ACCESS_TOKEN_SECRET = process.env.X_ACCESS_TOKEN_SECRET;
|
|
18
|
-
const X_BEARER_TOKEN = process.env.X_BEARER_TOKEN;
|
|
13
|
+
// ── Env (trim to handle GitHub Actions trailing whitespace) ─────────────
|
|
14
|
+
const X_API_KEY = (process.env.X_API_KEY || '').trim();
|
|
15
|
+
const X_API_SECRET = (process.env.X_API_SECRET || '').trim();
|
|
16
|
+
const X_ACCESS_TOKEN = (process.env.X_ACCESS_TOKEN || '').trim();
|
|
17
|
+
const X_ACCESS_TOKEN_SECRET = (process.env.X_ACCESS_TOKEN_SECRET || '').trim();
|
|
18
|
+
const X_BEARER_TOKEN = (process.env.X_BEARER_TOKEN || '').trim();
|
|
19
19
|
const LINKEDIN_ACCESS_TOKEN = process.env.LINKEDIN_ACCESS_TOKEN;
|
|
20
20
|
const LINKEDIN_PERSON_URN = process.env.LINKEDIN_PERSON_URN;
|
|
21
21
|
const DEVTO_API_KEY = process.env.DEVTO_API_KEY;
|
|
@@ -44,13 +44,21 @@ function xAuthHeader(method, url) {
|
|
|
44
44
|
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
45
45
|
async function postTweet(text) {
|
|
46
46
|
const url = 'https://api.twitter.com/2/tweets';
|
|
47
|
+
console.log(' X auth debug: credentials ' + (X_API_KEY && X_ACCESS_TOKEN ? 'present' : 'missing'));
|
|
47
48
|
const r = await fetch(url, {
|
|
48
49
|
method: 'POST',
|
|
49
50
|
headers: { Authorization: xAuthHeader('POST', url), 'Content-Type': 'application/json' },
|
|
50
51
|
body: JSON.stringify({ text }),
|
|
51
52
|
});
|
|
52
|
-
const j = await r
|
|
53
|
-
|
|
53
|
+
const j = await parseJsonResponse(r);
|
|
54
|
+
if (!j.data?.id) console.log(' X error detail:', JSON.stringify(j).slice(0, 200));
|
|
55
|
+
const id = j.data?.id || '';
|
|
56
|
+
return {
|
|
57
|
+
id,
|
|
58
|
+
ok: r.ok && Boolean(id),
|
|
59
|
+
status: r.status,
|
|
60
|
+
error: id ? '' : extractApiError(j, r.status),
|
|
61
|
+
};
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
async function replyTweet(text, replyTo) {
|
|
@@ -60,8 +68,50 @@ async function replyTweet(text, replyTo) {
|
|
|
60
68
|
headers: { Authorization: xAuthHeader('POST', url), 'Content-Type': 'application/json' },
|
|
61
69
|
body: JSON.stringify({ text, reply: { in_reply_to_tweet_id: replyTo } }),
|
|
62
70
|
});
|
|
63
|
-
const j = await r
|
|
64
|
-
|
|
71
|
+
const j = await parseJsonResponse(r);
|
|
72
|
+
const id = j.data?.id || '';
|
|
73
|
+
return {
|
|
74
|
+
id,
|
|
75
|
+
ok: r.ok && Boolean(id),
|
|
76
|
+
status: r.status,
|
|
77
|
+
error: id ? '' : extractApiError(j, r.status),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function parseJsonResponse(response) {
|
|
82
|
+
try {
|
|
83
|
+
return await response.json();
|
|
84
|
+
} catch {
|
|
85
|
+
return {};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function extractApiError(payload = {}, status = 0) {
|
|
90
|
+
const firstError = Array.isArray(payload.errors) && payload.errors[0]
|
|
91
|
+
? payload.errors[0].message || payload.errors[0].detail || payload.errors[0].title
|
|
92
|
+
: '';
|
|
93
|
+
return payload.detail || payload.title || firstError || `HTTP ${status || 'unknown'}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function recordTweetPost(report, result, log = console.log) {
|
|
97
|
+
if (result && result.ok && result.id) {
|
|
98
|
+
log('Tweet posted: ' + result.id);
|
|
99
|
+
report.tweets++;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
log('Tweet skipped: ' + (result?.error || `HTTP ${result?.status || 'unknown'}`));
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function recordTweetReply(report, username, result, log = console.log) {
|
|
107
|
+
const handle = username ? '@' + username : 'unknown user';
|
|
108
|
+
if (result && result.ok && result.id) {
|
|
109
|
+
log(' Replied to ' + handle + ': ' + result.id);
|
|
110
|
+
report.replies++;
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
log(' Reply skipped for ' + handle + ': ' + (result?.error || `HTTP ${result?.status || 'unknown'}`));
|
|
114
|
+
return false;
|
|
65
115
|
}
|
|
66
116
|
|
|
67
117
|
async function postLinkedIn(text) {
|
|
@@ -128,7 +178,7 @@ const TWEET_ANGLES = [
|
|
|
128
178
|
'Thompson Sampling for AI agent gates:\n\nEach gate: Beta(alpha, beta)\nCorrect block → alpha++ → tighter\nFalse positive → beta++ → relaxes\n\nNo thresholds. Gates converge on their own.\n\nhttps://github.com/IgorGanapolsky/ThumbGate',
|
|
129
179
|
'Google DeepMind: hidden prompt injections commandeer AI agents 86% of the time.\n\nThumbGate gates the action, not the prompt. PreToolUse hooks are the last defense.\n\nhttps://github.com/IgorGanapolsky/ThumbGate',
|
|
130
180
|
'Every AI agent framework ships memory. None ship enforcement.\n\nMemory: "Don\'t force-push to main"\nEnforcement: *physically blocked*\n\nThumbGate is the enforcement layer.\n\nhttps://github.com/IgorGanapolsky/ThumbGate',
|
|
131
|
-
'
|
|
181
|
+
'ThumbGate Pro is $19/mo or $149/yr for solo AI agent operators.\n\nLocal dashboard, DPO export, self-distillation, SQL MCP gates, Thompson Sampling, and pre-action enforcement.\n\nTeam rollout starts with intake: $99/seat/mo.\n\nhttps://buy.stripe.com/5kQ4gzbmI9Lo6tPayn3sI06',
|
|
132
182
|
'Context-stuffing: skip RAG entirely.\n\nDump ALL prevention rules into agent context at session start. 20-200 rules = 1K-10K tokens.\n\nInspired by Karpathy. Simpler. Faster.\n\nhttps://github.com/IgorGanapolsky/ThumbGate',
|
|
133
183
|
'The AI agent safety stack:\n\nGovernance: Paperclip\nOrchestration: iloom\nContext: RepoWise\nEnforcement: ThumbGate\n\nAll open source. All necessary.\n\nhttps://github.com/IgorGanapolsky/ThumbGate',
|
|
134
184
|
];
|
|
@@ -170,8 +220,7 @@ async function main() {
|
|
|
170
220
|
const u = mu[t.author_id] || {};
|
|
171
221
|
const replyText = '@' + u.username + ' ThumbGate: PreToolUse enforcement for AI agents. Thompson Sampling adapts confidence. 68 tools on Smithery.\n\nhttps://github.com/IgorGanapolsky/ThumbGate';
|
|
172
222
|
const r = await replyTweet(replyText, t.id);
|
|
173
|
-
|
|
174
|
-
report.replies++;
|
|
223
|
+
recordTweetReply(report, u.username, r);
|
|
175
224
|
}
|
|
176
225
|
|
|
177
226
|
state.lastMentionCheck = new Date().toISOString();
|
|
@@ -183,8 +232,7 @@ async function main() {
|
|
|
183
232
|
try {
|
|
184
233
|
const angleIndex = Math.floor(Date.now() / 7200000) % TWEET_ANGLES.length;
|
|
185
234
|
const r = await postTweet(TWEET_ANGLES[angleIndex]);
|
|
186
|
-
|
|
187
|
-
report.tweets++;
|
|
235
|
+
recordTweetPost(report, r);
|
|
188
236
|
} catch (e) {
|
|
189
237
|
console.log('Tweet error: ' + e.message);
|
|
190
238
|
}
|
|
@@ -311,6 +359,9 @@ async function main() {
|
|
|
311
359
|
console.log('GitHub: skipped (no token)');
|
|
312
360
|
}
|
|
313
361
|
|
|
362
|
+
// ── 8. Perplexity visibility ──
|
|
363
|
+
await checkPerplexityVisibility();
|
|
364
|
+
|
|
314
365
|
// ── Save state ──
|
|
315
366
|
state.lastRun = new Date().toISOString();
|
|
316
367
|
saveState(state);
|
|
@@ -325,7 +376,59 @@ async function main() {
|
|
|
325
376
|
console.log('=== DONE ===');
|
|
326
377
|
}
|
|
327
378
|
|
|
328
|
-
main
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
379
|
+
function isDirectInvocation(mainModule = require.main) {
|
|
380
|
+
return Boolean(mainModule && mainModule.filename === __filename);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (isDirectInvocation()) {
|
|
384
|
+
main().catch(e => {
|
|
385
|
+
console.error('Ralph Mode CI fatal error:', e.message);
|
|
386
|
+
process.exit(1);
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// ── Perplexity AI Search Visibility (appended) ──────────────────────────
|
|
391
|
+
async function checkPerplexityVisibility() {
|
|
392
|
+
const PPLX_KEY = (process.env.PERPLEXITY_API_KEY || '').trim();
|
|
393
|
+
if (!PPLX_KEY) { console.log('Perplexity: skipped (no key)'); return; }
|
|
394
|
+
|
|
395
|
+
const prompts = [
|
|
396
|
+
'best pre-action gate tools for AI coding agents',
|
|
397
|
+
'how to prevent AI coding agent from making mistakes',
|
|
398
|
+
'Claude Code safety tools',
|
|
399
|
+
'alternatives to thumbgate',
|
|
400
|
+
];
|
|
401
|
+
|
|
402
|
+
console.log('Perplexity visibility check (' + prompts.length + ' queries):');
|
|
403
|
+
let found = 0;
|
|
404
|
+
for (const prompt of prompts) {
|
|
405
|
+
try {
|
|
406
|
+
const r = await fetch('https://api.perplexity.ai/chat/completions', {
|
|
407
|
+
method: 'POST',
|
|
408
|
+
headers: { Authorization: 'Bearer ' + PPLX_KEY, 'Content-Type': 'application/json' },
|
|
409
|
+
body: JSON.stringify({ model: 'sonar', messages: [{ role: 'user', content: prompt }] }),
|
|
410
|
+
});
|
|
411
|
+
const j = await r.json();
|
|
412
|
+
const text = j.choices?.[0]?.message?.content || '';
|
|
413
|
+
const mentioned = /thumbgate/i.test(text);
|
|
414
|
+
console.log(' "' + prompt.slice(0, 50) + '": ' + (mentioned ? 'FOUND' : 'MISSING'));
|
|
415
|
+
if (mentioned) found++;
|
|
416
|
+
} catch (e) {
|
|
417
|
+
console.log(' "' + prompt.slice(0, 50) + '": ERROR ' + e.message.slice(0, 30));
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
console.log('Perplexity: ThumbGate mentioned in ' + found + '/' + prompts.length + ' queries');
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
module.exports = {
|
|
424
|
+
TWEET_ANGLES,
|
|
425
|
+
extractApiError,
|
|
426
|
+
main,
|
|
427
|
+
parseJsonResponse,
|
|
428
|
+
postTweet,
|
|
429
|
+
isDirectInvocation,
|
|
430
|
+
recordTweetPost,
|
|
431
|
+
recordTweetReply,
|
|
432
|
+
replyTweet,
|
|
433
|
+
xAuthHeader,
|
|
434
|
+
};
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const {
|
|
15
|
+
const { retrieveWithRerankingSync } = require('./cross-encoder-reranker');
|
|
16
16
|
const {
|
|
17
17
|
extractFilePaths,
|
|
18
18
|
extractToolCalls,
|
|
@@ -99,7 +99,7 @@ function checkRecurrence(analysis, feedbackEvent) {
|
|
|
99
99
|
try {
|
|
100
100
|
const context = `${analysis.userIntent} ${analysis.assistantAction} ${analysis.corrections.join(' ')}`;
|
|
101
101
|
const toolName = analysis.toolsUsed[0] || 'unknown';
|
|
102
|
-
previousLessons =
|
|
102
|
+
previousLessons = retrieveWithRerankingSync(toolName, context, { candidateCount: 20, maxResults: 5 });
|
|
103
103
|
// Filter to only negative lessons
|
|
104
104
|
previousLessons = previousLessons.filter(l => l.signal === 'negative');
|
|
105
105
|
} catch (_err) {
|