thumbgate 1.27.11 → 1.27.13
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/plugin.json +1 -1
- package/.well-known/llms.txt +2 -1
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +2 -4
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/mcp/server-stdio.js +1 -1
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/policy-engine/ethicore-guardian-client.js +68 -0
- package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +260 -0
- package/bin/cli.js +78 -259
- package/config/builtin-lessons.json +23 -0
- package/config/gate-templates.json +0 -228
- package/config/gates/claim-verification.json +0 -18
- package/package.json +35 -25
- package/public/assets/brand/thumbgate-logo-transparent.svg +22 -0
- package/public/assets/brand/thumbgate-mark-inline-v3.svg +19 -0
- package/public/assets/brand/thumbgate-mark.svg +11 -5
- package/public/blog.html +0 -30
- package/public/brand/thumbgate-mark.svg +9 -5
- package/public/chatgpt-app.html +2 -2
- package/public/compare.html +2 -1
- package/public/dashboard.html +1 -1
- package/public/federal.html +1 -1
- package/public/index.html +95 -216
- package/public/learn.html +59 -35
- package/public/lessons.html +1 -1
- package/public/numbers.html +2 -2
- package/public/pro.html +7 -7
- package/scripts/aws-blocks-guardrails.js +228 -0
- package/scripts/cli-schema.js +22 -10
- package/scripts/dashboard-chat.js +2 -1
- package/scripts/document-intake.js +1 -49
- package/scripts/durability/step.js +3 -3
- package/scripts/gate-stats.js +5 -11
- package/scripts/gemini-embedding-policy.js +2 -1
- package/scripts/hook-stop-anti-claim.js +116 -184
- package/scripts/hosted-config.js +0 -12
- package/scripts/llm-client.js +187 -5
- package/scripts/plausible-domain-config.js +3 -1
- package/scripts/seo-gsd.js +240 -1
- package/scripts/tool-registry.js +2 -2
- package/scripts/vector-store.js +44 -0
- package/scripts/workspace-evolver.js +62 -2
- package/src/api/server.js +340 -131
- package/public/assets/brand/thumbgate-mark-inline.svg +0 -15
- package/public/compare/adopt-ai.html +0 -219
- package/public/compare/agentix-labs.html +0 -197
- package/public/compare/ai-experience-orchestration.html +0 -216
- package/public/compare/anthropic-claude-for-legal.html +0 -260
- package/public/compare/anthropic-containment.html +0 -280
- package/public/compare/arcade.html +0 -175
- package/public/compare/arcjet.html +0 -239
- package/public/compare/bumblebee.html +0 -307
- package/public/compare/claude-code-hooks.html +0 -294
- package/public/compare/databricks-unity-ai-gateway.html +0 -215
- package/public/compare/fallow.html +0 -351
- package/public/compare/heidi.html +0 -233
- package/public/compare/mem0.html +0 -342
- package/public/compare/oak-and-sparrow-gatekeeper.html +0 -289
- package/public/compare/rein.html +0 -236
- package/public/compare/sigmashake.html +0 -256
- package/public/compare/speclock.html +0 -342
- package/public/guides/agent-harness-optimization.html +0 -342
- package/public/guides/agentic-web-governance.html +0 -406
- package/public/guides/ai-agent-governance-sprint.html +0 -415
- package/public/guides/ai-agent-pre-action-approval-gates.html +0 -401
- package/public/guides/ai-agent-workflow-migration-checklist.html +0 -392
- package/public/guides/ai-deployment-readiness.html +0 -415
- package/public/guides/ai-mode-ads-agent-governance.html +0 -401
- package/public/guides/ai-search-topical-presence.html +0 -342
- package/public/guides/autoresearch-agent-safety.html +0 -342
- package/public/guides/background-agent-governance.html +0 -358
- package/public/guides/best-tools-stop-ai-agents-breaking-production.html +0 -363
- package/public/guides/browser-automation-safety.html +0 -342
- package/public/guides/chatgpt-ads-trust.html +0 -353
- package/public/guides/claude-code-feedback.html +0 -339
- package/public/guides/claude-code-prevent-repeated-mistakes.html +0 -161
- package/public/guides/claude-code-skills-guardrails.html +0 -343
- package/public/guides/claude-desktop.html +0 -356
- package/public/guides/code-knowledge-graph-guardrails.html +0 -365
- package/public/guides/codex-cli-guardrails.html +0 -339
- package/public/guides/cursor-agent-guardrails.html +0 -339
- package/public/guides/cursor-prevent-repeated-mistakes.html +0 -161
- package/public/guides/database-agent-safety.html +0 -406
- package/public/guides/deepseek-v4-runtime-guardrails.html +0 -346
- package/public/guides/developer-machine-supply-chain-guardrails.html +0 -358
- package/public/guides/gcp-mcp-guardrails.html +0 -147
- package/public/guides/gemini-cli-feedback-memory.html +0 -339
- package/public/guides/gpt-5-5-model-evaluation.html +0 -358
- package/public/guides/internal-ai-engineering-stack-guardrails.html +0 -348
- package/public/guides/long-running-agent-context-management.html +0 -346
- package/public/guides/mcp-tool-governance.html +0 -401
- package/public/guides/multica-thumbgate-setup.html +0 -134
- package/public/guides/native-messaging-host-security.html +0 -342
- package/public/guides/policy-engine-pre-action-gates.html +0 -346
- package/public/guides/pre-action-checks.html +0 -342
- package/public/guides/pretooluse-hooks-vs-advisory-prompt-rules.html +0 -342
- package/public/guides/prompt-tricks-to-workflow-rules.html +0 -365
- package/public/guides/proxy-pointer-rag-guardrails.html +0 -352
- package/public/guides/rag-precision-tuning-guardrails.html +0 -352
- package/public/guides/reasoning-compression-guardrails.html +0 -346
- package/public/guides/relational-knowledge-ai-recommendations.html +0 -342
- package/public/guides/roo-code-alternative-cline.html +0 -339
- package/public/guides/semantic-programmatic-seo-guardrails.html +0 -352
- package/public/guides/seo-agent-skills-guardrails.html +0 -344
- package/public/guides/stop-repeated-ai-agent-mistakes.html +0 -342
- package/public/learn/ac-dc-runtime-enforcement.html +0 -277
- package/public/learn/agent-harness-pattern.html +0 -181
- package/public/learn/agent-identity-connector-governance.html +0 -146
- package/public/learn/agent-swarms-shared-gates.html +0 -173
- package/public/learn/agentic-enterprise-context-brain.html +0 -117
- package/public/learn/agentic-os-team-governance.html +0 -146
- package/public/learn/ai-agent-governance.html +0 -158
- package/public/learn/ai-agent-persistent-memory.html +0 -211
- package/public/learn/anthropomorphic-claim-gates.html +0 -180
- package/public/learn/background-agent-control-layer.html +0 -184
- package/public/learn/claude-code-goal-with-rubrics.html +0 -205
- package/public/learn/codex-role-plugins-need-governance.html +0 -125
- package/public/learn/cost-aware-agent-gate-routing.html +0 -173
- package/public/learn/databricks-unity-ai-gateway-runtime-governance.html +0 -157
- package/public/learn/deterministic-agent-workflows.html +0 -185
- package/public/learn/feedback-loop-vs-decision-layer.html +0 -283
- package/public/learn/from-prototype-to-production.html +0 -223
- package/public/learn/learn.css +0 -51
- package/public/learn/mcp-pre-action-checks-explained.html +0 -172
- package/public/learn/pretix-stripe-connect-marketplaces.html +0 -161
- package/public/learn/regulated-agent-execution-boundary.html +0 -196
- package/public/learn/spec-driven-development.html +0 -168
- package/public/learn/stop-ai-agent-force-push.html +0 -134
- package/public/learn/vibe-coding-safety-net.html +0 -142
- package/scripts/reddit-browser-notification-watch.js +0 -230
package/scripts/llm-client.js
CHANGED
|
@@ -4,24 +4,61 @@
|
|
|
4
4
|
const { runStep } = require('./durability/step');
|
|
5
5
|
|
|
6
6
|
const MODELS = {
|
|
7
|
-
FAST: '
|
|
8
|
-
SMART: '
|
|
7
|
+
FAST: 'glm-5.2',
|
|
8
|
+
SMART: 'glm-5.2',
|
|
9
|
+
ZAI_CODING: 'glm-5.2',
|
|
10
|
+
LEGACY_CLAUDE_FAST: 'claude-haiku-4-5-20251001',
|
|
11
|
+
LEGACY_CLAUDE_SMART: 'claude-sonnet-4-6',
|
|
9
12
|
};
|
|
10
13
|
|
|
11
14
|
const DEFAULT_MODEL = MODELS.FAST;
|
|
12
15
|
const DEFAULT_MAX_TOKENS = 1024;
|
|
13
16
|
const DEFAULT_CACHE_TTL = '5m';
|
|
17
|
+
const DEFAULT_ZAI_BASE_URL = 'https://api.z.ai/api/coding/paas/v4';
|
|
18
|
+
const DEFAULT_ZAI_MODEL = MODELS.ZAI_CODING;
|
|
14
19
|
|
|
15
20
|
let _anthropicClient = null;
|
|
16
21
|
let _geminiClient = null;
|
|
17
22
|
|
|
18
|
-
function
|
|
19
|
-
return
|
|
23
|
+
function getZaiApiKey(env = process.env) {
|
|
24
|
+
return env.ZAI_API_KEY || env.THUMBGATE_ZAI_API_KEY || env.GLM_API_KEY || '';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getZaiBaseUrl(env = process.env) {
|
|
28
|
+
return (env.ZAI_API_BASE_URL || env.THUMBGATE_ZAI_API_BASE_URL || DEFAULT_ZAI_BASE_URL).replace(/\/+$/, '');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getZaiModel(env = process.env) {
|
|
32
|
+
return env.ZAI_API_MODEL || env.THUMBGATE_ZAI_MODEL || DEFAULT_ZAI_MODEL;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function hasZaiApiKey(env = process.env) {
|
|
36
|
+
return Boolean(getZaiApiKey(env));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isZaiProvider(provider = '') {
|
|
40
|
+
return /^(zai|z\.ai|glm|glm-coding)$/i.test(String(provider || '').trim());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isZaiModel(model = '') {
|
|
44
|
+
return /^(glm|zai|z\.ai)/i.test(String(model || '').trim());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isAvailable(provider = '') {
|
|
48
|
+
const normalizedProvider = String(provider || '').trim().toLowerCase();
|
|
49
|
+
if (isZaiProvider(normalizedProvider)) return hasZaiApiKey();
|
|
50
|
+
if (normalizedProvider === 'anthropic' || normalizedProvider === 'claude') {
|
|
51
|
+
return Boolean(process.env.ANTHROPIC_API_KEY);
|
|
52
|
+
}
|
|
53
|
+
if (normalizedProvider === 'gemini' || normalizedProvider === 'vertex') {
|
|
54
|
+
return Boolean(process.env.GEMINI_API_KEY || process.env.VERTEX_PROJECT_ID);
|
|
55
|
+
}
|
|
56
|
+
return Boolean(hasZaiApiKey() || process.env.ANTHROPIC_API_KEY || process.env.GEMINI_API_KEY || process.env.VERTEX_PROJECT_ID);
|
|
20
57
|
}
|
|
21
58
|
|
|
22
59
|
function getClient() {
|
|
23
60
|
if (_anthropicClient) return _anthropicClient;
|
|
24
|
-
if (!isAvailable()) return null;
|
|
61
|
+
if (!isAvailable('anthropic')) return null;
|
|
25
62
|
try {
|
|
26
63
|
const Anthropic = require('@anthropic-ai/sdk');
|
|
27
64
|
_anthropicClient = new Anthropic();
|
|
@@ -123,6 +160,63 @@ function buildClaudeRequest({
|
|
|
123
160
|
return request;
|
|
124
161
|
}
|
|
125
162
|
|
|
163
|
+
function normalizeMessageText(content) {
|
|
164
|
+
if (typeof content === 'string') return content;
|
|
165
|
+
if (Array.isArray(content)) {
|
|
166
|
+
return content.map((part) => {
|
|
167
|
+
if (typeof part === 'string') return part;
|
|
168
|
+
if (part && typeof part === 'object') return part.text || JSON.stringify(part);
|
|
169
|
+
return '';
|
|
170
|
+
}).join('');
|
|
171
|
+
}
|
|
172
|
+
if (content && typeof content === 'object') {
|
|
173
|
+
return content.text || JSON.stringify(content);
|
|
174
|
+
}
|
|
175
|
+
return '';
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function convertMessagesToOpenAi(messages, userPrompt, systemPrompt) {
|
|
179
|
+
const normalized = [];
|
|
180
|
+
if (systemPrompt) normalized.push({ role: 'system', content: systemPrompt });
|
|
181
|
+
|
|
182
|
+
const list = Array.isArray(messages) && messages.length > 0
|
|
183
|
+
? messages
|
|
184
|
+
: [{ role: 'user', content: userPrompt }];
|
|
185
|
+
|
|
186
|
+
for (const message of list) {
|
|
187
|
+
if (!message || typeof message !== 'object') continue;
|
|
188
|
+
const role = message.role === 'assistant' || message.role === 'system' ? message.role : 'user';
|
|
189
|
+
const content = normalizeMessageText(message.content);
|
|
190
|
+
if (content) normalized.push({ role, content });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (normalized.length === 0) {
|
|
194
|
+
normalized.push({ role: 'user', content: String(userPrompt || '') });
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return normalized;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function buildOpenAiCompatibleRequest({
|
|
201
|
+
systemPrompt,
|
|
202
|
+
userPrompt,
|
|
203
|
+
messages,
|
|
204
|
+
model,
|
|
205
|
+
maxTokens,
|
|
206
|
+
temperature,
|
|
207
|
+
metadata,
|
|
208
|
+
} = {}, env = process.env) {
|
|
209
|
+
const request = {
|
|
210
|
+
model: model || getZaiModel(env),
|
|
211
|
+
messages: convertMessagesToOpenAi(messages, userPrompt, systemPrompt),
|
|
212
|
+
max_tokens: maxTokens || DEFAULT_MAX_TOKENS,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
if (Number.isFinite(temperature)) request.temperature = temperature;
|
|
216
|
+
if (metadata && typeof metadata === 'object') request.metadata = metadata;
|
|
217
|
+
return request;
|
|
218
|
+
}
|
|
219
|
+
|
|
126
220
|
function extractTextContent(response) {
|
|
127
221
|
return (response?.content || [])
|
|
128
222
|
.filter((block) => block.type === 'text')
|
|
@@ -139,6 +233,51 @@ function parseClaudeJson(text) {
|
|
|
139
233
|
}
|
|
140
234
|
}
|
|
141
235
|
|
|
236
|
+
async function callZaiInternal(options = {}) {
|
|
237
|
+
const apiKey = getZaiApiKey();
|
|
238
|
+
if (!apiKey) return null;
|
|
239
|
+
if (typeof fetch !== 'function') return null;
|
|
240
|
+
|
|
241
|
+
const baseUrl = getZaiBaseUrl();
|
|
242
|
+
const requestedModel = options.model && isZaiModel(options.model) ? options.model : undefined;
|
|
243
|
+
const request = buildOpenAiCompatibleRequest({
|
|
244
|
+
...options,
|
|
245
|
+
model: requestedModel || getZaiModel(),
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
const response = await runStep('llm.callZai', {
|
|
250
|
+
retries: 2,
|
|
251
|
+
logger: (msg) => console.warn(msg),
|
|
252
|
+
}, async () => fetch(`${baseUrl}/chat/completions`, {
|
|
253
|
+
method: 'POST',
|
|
254
|
+
headers: {
|
|
255
|
+
Authorization: `Bearer ${apiKey}`,
|
|
256
|
+
'Content-Type': 'application/json',
|
|
257
|
+
},
|
|
258
|
+
body: JSON.stringify(request),
|
|
259
|
+
}));
|
|
260
|
+
|
|
261
|
+
if (!response || !response.ok) {
|
|
262
|
+
throw new Error(`Z.ai request failed with status ${response?.status || 'unknown'}`);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const json = await response.json();
|
|
266
|
+
const text = stripCodeFences(json?.choices?.[0]?.message?.content || '');
|
|
267
|
+
return {
|
|
268
|
+
text,
|
|
269
|
+
usage: json?.usage || null,
|
|
270
|
+
stopReason: json?.choices?.[0]?.finish_reason || null,
|
|
271
|
+
id: json?.id || null,
|
|
272
|
+
model: json?.model || request.model,
|
|
273
|
+
provider: 'zai',
|
|
274
|
+
};
|
|
275
|
+
} catch (err) {
|
|
276
|
+
console.error('Z.ai execution error:', err?.message || err);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
142
281
|
async function callGeminiInternal(options = {}) {
|
|
143
282
|
const env = process.env;
|
|
144
283
|
const { detectInferenceBackend } = require('./local-model-profile');
|
|
@@ -221,6 +360,13 @@ function convertMessagesToGemini(messages, userPrompt) {
|
|
|
221
360
|
|
|
222
361
|
async function callClaudeInternal(options = {}) {
|
|
223
362
|
const modelName = options.model || '';
|
|
363
|
+
const provider = options.provider || process.env.THUMBGATE_LLM_PROVIDER || process.env.LLM_PROVIDER || '';
|
|
364
|
+
const requestedZai = isZaiProvider(provider) || isZaiModel(modelName);
|
|
365
|
+
if (requestedZai || (!process.env.ANTHROPIC_API_KEY && hasZaiApiKey() && !modelName.startsWith('gemini') && !modelName.startsWith('vertex'))) {
|
|
366
|
+
const zaiOptions = requestedZai ? options : { ...options, model: undefined };
|
|
367
|
+
return callZaiInternal(zaiOptions);
|
|
368
|
+
}
|
|
369
|
+
|
|
224
370
|
if (modelName.startsWith('gemini') || modelName.startsWith('vertex')) {
|
|
225
371
|
return callGeminiInternal(options);
|
|
226
372
|
}
|
|
@@ -279,13 +425,49 @@ async function callClaudeJson(options = {}) {
|
|
|
279
425
|
return parsed;
|
|
280
426
|
}
|
|
281
427
|
|
|
428
|
+
async function callZai(options = {}) {
|
|
429
|
+
const result = await callZaiInternal(options);
|
|
430
|
+
if (!result) return null;
|
|
431
|
+
return options.returnMetadata ? result : result.text;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
async function callZaiJson(options = {}) {
|
|
435
|
+
const result = await callZaiInternal(options);
|
|
436
|
+
if (!result) return null;
|
|
437
|
+
|
|
438
|
+
const parsed = parseClaudeJson(result.text);
|
|
439
|
+
if (parsed === null) return null;
|
|
440
|
+
|
|
441
|
+
if (options.returnMetadata) {
|
|
442
|
+
return {
|
|
443
|
+
parsed,
|
|
444
|
+
text: result.text,
|
|
445
|
+
usage: result.usage,
|
|
446
|
+
stopReason: result.stopReason,
|
|
447
|
+
id: result.id,
|
|
448
|
+
model: result.model,
|
|
449
|
+
provider: result.provider,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return parsed;
|
|
454
|
+
}
|
|
455
|
+
|
|
282
456
|
module.exports = {
|
|
283
457
|
isAvailable,
|
|
284
458
|
callClaude,
|
|
285
459
|
callClaudeJson,
|
|
460
|
+
callZai,
|
|
461
|
+
callZaiJson,
|
|
286
462
|
stripCodeFences,
|
|
287
463
|
parseClaudeJson,
|
|
288
464
|
normalizeCacheOptions,
|
|
289
465
|
buildClaudeRequest,
|
|
466
|
+
buildOpenAiCompatibleRequest,
|
|
467
|
+
convertMessagesToOpenAi,
|
|
468
|
+
getZaiApiKey,
|
|
469
|
+
getZaiBaseUrl,
|
|
470
|
+
getZaiModel,
|
|
290
471
|
MODELS,
|
|
472
|
+
DEFAULT_ZAI_BASE_URL,
|
|
291
473
|
};
|
|
@@ -16,7 +16,9 @@ function normalizeDomain(value) {
|
|
|
16
16
|
try {
|
|
17
17
|
return new URL(input.includes('://') ? input : `https://${input}`).hostname.toLowerCase();
|
|
18
18
|
} catch {
|
|
19
|
-
|
|
19
|
+
const withoutProtocol = input.replace(/^https?:\/\//i, '');
|
|
20
|
+
const hostnameAndPort = withoutProtocol.split('/')[0];
|
|
21
|
+
return hostnameAndPort.toLowerCase().split(':')[0];
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
|
package/scripts/seo-gsd.js
CHANGED
|
@@ -105,6 +105,11 @@ const HIGH_ROI_QUERY_SEEDS = [
|
|
|
105
105
|
93,
|
|
106
106
|
'Fresh Slack engineering pattern where ThumbGate can gate director journals, critic reviews, credibility scoring, and timelines for long-running agents.',
|
|
107
107
|
),
|
|
108
|
+
querySeed(
|
|
109
|
+
'agent context governance',
|
|
110
|
+
95,
|
|
111
|
+
'Fresh AdaCoM, tokenmaxxing, and Claude Managed Agents demand where ThumbGate can govern context hygiene, session logs, sandbox boundaries, credential separation, and pre-action proof.',
|
|
112
|
+
),
|
|
108
113
|
querySeed(
|
|
109
114
|
'reasoning compression guardrails',
|
|
110
115
|
92,
|
|
@@ -234,6 +239,12 @@ const HIGH_ROI_QUERY_SEEDS = [
|
|
|
234
239
|
source: 'seed',
|
|
235
240
|
notes: 'Integration page for Gemini CLI users who need memory plus enforcement.',
|
|
236
241
|
},
|
|
242
|
+
{
|
|
243
|
+
query: 'hermes agent guardrails',
|
|
244
|
+
businessValue: 84,
|
|
245
|
+
source: 'seed',
|
|
246
|
+
notes: 'Integration page for Hermes Agent users who need pre-action gates around persistent memory, generated skills, messaging gateways, scheduled automations, and sandboxed execution.',
|
|
247
|
+
},
|
|
237
248
|
{
|
|
238
249
|
query: 'roo code alternative cline',
|
|
239
250
|
businessValue: 83,
|
|
@@ -2402,6 +2413,234 @@ const PAGE_BLUEPRINTS = [
|
|
|
2402
2413
|
],
|
|
2403
2414
|
relatedPaths: ['/compare/mem0', '/guides/stop-repeated-ai-agent-mistakes'],
|
|
2404
2415
|
},
|
|
2416
|
+
{
|
|
2417
|
+
query: 'hermes agent guardrails',
|
|
2418
|
+
path: '/guides/hermes-agent-guardrails',
|
|
2419
|
+
pageType: 'integration',
|
|
2420
|
+
pillar: 'agent-workflows',
|
|
2421
|
+
title: 'Hermes Agent Guardrails | Firewall for Self-Improving Agents',
|
|
2422
|
+
heroTitle: 'Hermes Agent can grow with you. ThumbGate keeps the growing agent safe.',
|
|
2423
|
+
heroSummary: 'Hermes Agent points at the next wave: persistent memory, generated skills, messaging gateways, scheduled automations, and sandboxed execution. ThumbGate is the enforcement layer those workflows need before a remembered mistake becomes another real tool call.',
|
|
2424
|
+
takeaways: [
|
|
2425
|
+
'Hermes validates the market shift toward long-running, self-improving agents.',
|
|
2426
|
+
'Memory and generated skills increase leverage, but they also increase the blast radius of repeated mistakes.',
|
|
2427
|
+
'ThumbGate should be positioned as the local-first pre-action firewall for Hermes-style agents, not as a general agent clone.',
|
|
2428
|
+
],
|
|
2429
|
+
sections: [
|
|
2430
|
+
{
|
|
2431
|
+
heading: 'Why Hermes-style agents need a separate execution gate',
|
|
2432
|
+
paragraphs: [
|
|
2433
|
+
'A persistent agent can remember projects, generate its own skills, run scheduled automations, and accept instructions from messaging gateways. That is powerful, but it also means one bad habit can persist longer and reach more surfaces.',
|
|
2434
|
+
'The safety problem is not only whether the agent remembers. It is whether remembered lessons can stop the next risky shell command, git action, database write, deploy, browser click, or payment workflow before execution.',
|
|
2435
|
+
],
|
|
2436
|
+
},
|
|
2437
|
+
{
|
|
2438
|
+
heading: 'What ThumbGate adds to Hermes-style workflows',
|
|
2439
|
+
bullets: [
|
|
2440
|
+
'Pre-action checks before risky tool calls execute.',
|
|
2441
|
+
'Thumbs-down feedback that becomes explicit prevention rules.',
|
|
2442
|
+
'Evidence requirements for deploys, migrations, API calls, and production-facing changes.',
|
|
2443
|
+
'Audit trails that show which lesson, rule, and workflow context allowed or blocked the action.',
|
|
2444
|
+
'A local-first path for teams that want agent memory without handing every correction to a hosted black box.',
|
|
2445
|
+
],
|
|
2446
|
+
},
|
|
2447
|
+
{
|
|
2448
|
+
heading: 'The buyer message',
|
|
2449
|
+
paragraphs: [
|
|
2450
|
+
'Hermes can be the agent that grows with you. ThumbGate is the firewall that makes sure growth does not mean repeating expensive mistakes faster across more surfaces.',
|
|
2451
|
+
'For teams evaluating persistent agents, the practical first step is not another prompt. It is one enforced rule from one real failure, proven locally, then expanded into Pro or a workflow hardening sprint when the risk is recurring.',
|
|
2452
|
+
],
|
|
2453
|
+
},
|
|
2454
|
+
],
|
|
2455
|
+
faq: [
|
|
2456
|
+
{
|
|
2457
|
+
question: 'Does ThumbGate replace Hermes Agent?',
|
|
2458
|
+
answer: 'No. Hermes is a general self-improving agent surface. ThumbGate is the enforcement layer that can sit around Hermes-style workflows so risky actions are checked before execution.',
|
|
2459
|
+
},
|
|
2460
|
+
{
|
|
2461
|
+
question: 'What Hermes features create the biggest need for guardrails?',
|
|
2462
|
+
answer: 'Persistent memory, generated skills, messaging gateways, scheduled automations, browser and tool control, and sandbox backends all increase the value of pre-action gates because the agent can act longer, faster, and from more entry points.',
|
|
2463
|
+
},
|
|
2464
|
+
{
|
|
2465
|
+
question: 'What should teams implement first?',
|
|
2466
|
+
answer: 'Start with one repeated failure pattern: force-push, destructive SQL, unsafe deploy, risky browser action, or off-scope file edit. Capture it once, convert it into a prevention rule, and require evidence before the next similar action runs.',
|
|
2467
|
+
},
|
|
2468
|
+
],
|
|
2469
|
+
relatedPaths: ['/guides/long-running-agent-context-management', '/guides/background-agent-governance', '/guides/browser-automation-safety'],
|
|
2470
|
+
},
|
|
2471
|
+
{
|
|
2472
|
+
query: 'safe self evolution',
|
|
2473
|
+
path: '/guides/safe-self-evolution',
|
|
2474
|
+
pageType: 'guide',
|
|
2475
|
+
pillar: 'agent-workflows',
|
|
2476
|
+
title: 'Safe Self-Evolution | Autonomous Prompt Optimization without Regression',
|
|
2477
|
+
heroTitle: 'Self-Evolution is Polarizing. Make It Safe with Execution Gates.',
|
|
2478
|
+
heroSummary: 'Hermes-style autonomous agents learn by observing their own execution failures and automatically rewriting their skills or instructions. But critics warn that blind self-evolution can overwrite stable patterns and introduce silent regressions. ThumbGate introduces the Safe Self-Evolution loop: weakness mining from explicit thumbs-down feedback, automated prompt optimization, local verification suites, and atomic git rollbacks.',
|
|
2479
|
+
takeaways: [
|
|
2480
|
+
'Self-improving agents need execution guardrails so a synthesized skill cannot bypass safety constraints.',
|
|
2481
|
+
'Blind self-evolution is unstable; ThumbGate ensures prompt changes are verified against a local holdout suite before committing.',
|
|
2482
|
+
'Rollback capability is mandatory: if validation fails, the evolution engine immediately reverts prompts to the last known-good state.',
|
|
2483
|
+
'Explicit feedback is the anchor: optimize based on real thumbs-down signals, not hallucinatory failure guesses.'
|
|
2484
|
+
],
|
|
2485
|
+
sections: [
|
|
2486
|
+
{
|
|
2487
|
+
heading: 'The self-evolution dilemma',
|
|
2488
|
+
paragraphs: [
|
|
2489
|
+
'Nous Research’s Hermes Agent points at a future where developers do not write static instructions like CLAUDE.md. Instead, the agent learns from its execution failures and modifies its own SKILL.md files in real-time. This dynamic adaptation yields massive speedups and handles custom codebase quirks autonomously.',
|
|
2490
|
+
'However, the critics are correct: when an agent has the power to edit its own rules without a verification gate, it will eventually overwrite a perfectly stable skill. This introduces regressions, makes debugging impossible, and can lead to security loops where the agent modifies its own guardrails to make a failing task pass.'
|
|
2491
|
+
]
|
|
2492
|
+
},
|
|
2493
|
+
{
|
|
2494
|
+
heading: 'Safe self-evolution with ThumbGate',
|
|
2495
|
+
paragraphs: [
|
|
2496
|
+
'ThumbGate implements a Safe Self-Evolution loop (based on the Self-Harness paradigm) that gives you the speed of self-improving agents without the instability:',
|
|
2497
|
+
'1. Explicit Weakness Mining: ThumbGate captures structured thumbs-up/down signals on agent actions and compiles them into a JSON log, avoiding random self-diagnosis.',
|
|
2498
|
+
'2. Harness Proposal: The self-harness-optimizer automatically formats these rules and injects them directly into the agent’s prompt instructions (AGENTS.md, GEMINI.md).',
|
|
2499
|
+
'3. Verification Gate: Before the updated prompts are committed, the optimizer runs a local quick verification suite and holdout tests.',
|
|
2500
|
+
'4. Atomic Rollback: If any test fails, the optimizer instantly reverts the workspace prompts and restores the previous snapshot. If they pass, it commits the update to Git.'
|
|
2501
|
+
]
|
|
2502
|
+
},
|
|
2503
|
+
{
|
|
2504
|
+
heading: 'Competing with blind self-improvement',
|
|
2505
|
+
paragraphs: [
|
|
2506
|
+
'To compete with agents like Hermes, you do not need to give up control of your codebase. You need a pre-action firewall and a prompt optimizer that treats rule generation as code changes—complete with tests, verification, and rollbacks.',
|
|
2507
|
+
'This keeps your agent fast, keeps your instructions dynamic, and ensures your production-facing surfaces remain secure.'
|
|
2508
|
+
]
|
|
2509
|
+
}
|
|
2510
|
+
],
|
|
2511
|
+
faq: [
|
|
2512
|
+
{
|
|
2513
|
+
question: 'Does ThumbGate prevent the agent from changing its own rules?',
|
|
2514
|
+
answer: 'Yes. ThumbGate scans newly generated skills and prompt updates against established rules to prevent the agent from bypassing safety gates or deleting security constraints.'
|
|
2515
|
+
},
|
|
2516
|
+
{
|
|
2517
|
+
question: 'How does the rollback mechanism work?',
|
|
2518
|
+
answer: 'When the self-harness optimizer proposes new prompt sections, it saves a snapshot of the current prompt files. It then runs the verification commands. If the status is non-zero, it restores the backup files.'
|
|
2519
|
+
},
|
|
2520
|
+
{
|
|
2521
|
+
question: 'Is this compatible with Hermes Agent?',
|
|
2522
|
+
answer: 'Yes. You can use ThumbGate as the pre-action gate around a Hermes Agent deployment to secure the skills it generates and the messaging channels it posts to.'
|
|
2523
|
+
}
|
|
2524
|
+
],
|
|
2525
|
+
relatedPaths: ['/guides/hermes-agent-guardrails', '/guides/agent-context-governance', '/guides/stop-repeated-ai-agent-mistakes'],
|
|
2526
|
+
},
|
|
2527
|
+
{
|
|
2528
|
+
query: 'agent context governance',
|
|
2529
|
+
path: '/guides/agent-context-governance',
|
|
2530
|
+
pageType: 'guide',
|
|
2531
|
+
pillar: 'pre-action-checks',
|
|
2532
|
+
title: 'Agent Context Governance | Stop Tokenmaxxing Drift Before Agents Act',
|
|
2533
|
+
heroTitle: 'More Context Is Not Governance. Clean Context Plus Action Gates Is.',
|
|
2534
|
+
heroSummary: 'AdaCoM-style context managers, the tokenmaxxing backlash, Claude Managed Agents, anti-rubber-stamp response prompts, model-provenance scares, ChatGPT Lockdown Mode, MCP routing attacks, resilient graph architectures, rising AI-authored code volume, AI email assistants, platform-agent orchestration, on-device QAT models, and backprop-style failure attribution all point to the same buyer need: long-running agents need structured intent, cleaner context, durable session logs, approved models, isolated execution, credential boundaries, tool lockdown, direct pushback, distributed gates, provenance, and pre-action checks before they touch real systems.',
|
|
2535
|
+
takeaways: [
|
|
2536
|
+
'Long-context agents get better when a separate manager rewrites, preserves, prunes, or merges working context before the next step.',
|
|
2537
|
+
'Tokenmaxxing creates uncontrolled spend and weak governance when teams cannot prove which agent work returned value.',
|
|
2538
|
+
'Managed-agent architectures decouple the brain, hands, sessions, credentials, and sandboxes; ThumbGate adds the local-first action gate around those boundaries.',
|
|
2539
|
+
'Response customization should become a gate too: no padded agreement, no vague completion claims, and no confident answer without evidence or blind-spot checks.',
|
|
2540
|
+
'Lockdown modes validate the egress-control story: sensitive workflows need tool-surface limits, not just better prompts.',
|
|
2541
|
+
'Model leaks and proxy resale scares make approved-provider checks a governance requirement, especially when frontier model cost is high.',
|
|
2542
|
+
'MCP security research makes local config integrity a first-class control: endpoint rewrites and token-routing changes must be monitored before agents act.',
|
|
2543
|
+
'Random-graph infrastructure suggests a governance architecture: use many small local gates that degrade proportionally instead of one central approval bottleneck.',
|
|
2544
|
+
'As AI-authored code volume rises, teams need provenance and evidence gates so generated diffs are attributable, tested, and owned before merge.',
|
|
2545
|
+
'AI customer-response assistants need draft governance: retrieved sources, prompt variables, category routing, and feedback should improve drafts without letting the agent send unsupported claims.',
|
|
2546
|
+
'Enterprise agent platforms need one shared execution contract: structured specs, approved tools, scoped permissions, retries, evals, and traceability instead of 100 fragile team-specific agents.',
|
|
2547
|
+
'On-device QAT models can reduce cost and preserve privacy for first-pass risk classification, but they should escalate rather than approve high-risk actions.',
|
|
2548
|
+
'Backpropagation suggests a useful product metaphor: trace the agent run graph, score local risk at each edge, and cache the blame path so the same failure is blocked faster next time.',
|
|
2549
|
+
],
|
|
2550
|
+
sections: [
|
|
2551
|
+
{
|
|
2552
|
+
heading: 'Why this matters now',
|
|
2553
|
+
paragraphs: [
|
|
2554
|
+
'The market is moving away from prompt-only agents. New research shows that a separate context manager can improve long-horizon work without retraining the main agent. At the same time, developer teams are realizing that simply buying more tokens does not create accountable engineering process.',
|
|
2555
|
+
'Claude Managed Agents adds the production vocabulary buyers now expect: agents, environments, sessions, sandbox isolation, credential separation, event logs, observability, permission policies, outcomes, and webhooks. ThumbGate should attach to that vocabulary as the pre-action governance layer.',
|
|
2556
|
+
],
|
|
2557
|
+
},
|
|
2558
|
+
{
|
|
2559
|
+
heading: 'What ThumbGate should enforce',
|
|
2560
|
+
bullets: [
|
|
2561
|
+
'Context hygiene gate: block high-risk actions when the agent is acting from raw chat history, stale memory, or unresolved contradictions.',
|
|
2562
|
+
'Session evidence gate: require an append-only event log, resumable session ID, and proof links before long-running work can deploy, charge, message, or mutate production data.',
|
|
2563
|
+
'Sandbox boundary gate: require isolated execution and explicit network or filesystem scope before generated code runs.',
|
|
2564
|
+
'Credential boundary gate: block actions where tool credentials live beside generated code or where the action lacks user/on-behalf-of attribution.',
|
|
2565
|
+
'Token ROI gate: flag tokenmaxxing workflows that spend heavily without a defined outcome, eval, or proof of returned value.',
|
|
2566
|
+
'Response quality gate: require the agent to lead with the useful answer, call out weak assumptions, and avoid completion claims unless the evidence is attached.',
|
|
2567
|
+
'Model provenance gate: require approved provider domains, known model IDs, expected price ceilings, and no shadow API proxy before routing frontier work.',
|
|
2568
|
+
'Tool lockdown gate: disable or require explicit approval for browsing, downloads, agent mode, generated-code networking, and other outbound paths when sensitive data is in context.',
|
|
2569
|
+
'MCP config integrity gate: alert on ~/.claude.json routing changes, unfamiliar MCP endpoints, localhost proxy additions, OAuth refresh anomalies, and dependency postinstall hooks.',
|
|
2570
|
+
'Distributed gate mesh: keep enforcement close to each repo, tool, and workflow so one failed gate reduces coverage locally instead of collapsing the entire governance path.',
|
|
2571
|
+
'AI-authored code gate: require generated-diff provenance, human owner, tests, risk label, and rollback evidence once agent-authored changes cross a team-defined threshold.',
|
|
2572
|
+
'Customer-response draft gate: require retrieved source links, customer objective, response category, human approval, and no unsupported pricing/security claims before an email leaves draft mode.',
|
|
2573
|
+
'Structured intent gate: require scope, out-of-scope systems, ordered steps, allowed tools, acceptance criteria, and rollback expectations before async agent execution starts.',
|
|
2574
|
+
'Tool contract gate: require versioned schemas, explicit read/write permissions, stable error codes, observability hooks, and audit logging for every MCP tool call.',
|
|
2575
|
+
'Evaluation gate: require golden tasks, regression checks, build/test evidence, and traceable PR or artifact output before a repeated workflow is promoted to platform automation.',
|
|
2576
|
+
'Local classifier gate: run low-cost on-device models for first-pass risk labels, sensitive-data detection, and route selection, then escalate uncertain or high-blast-radius actions to stronger checks.',
|
|
2577
|
+
'Failure attribution graph: record intent, retrieved context, tool choice, local risk score, evidence, and outcome for each step so future gates reuse the causal path instead of starting from scratch.',
|
|
2578
|
+
],
|
|
2579
|
+
},
|
|
2580
|
+
{
|
|
2581
|
+
heading: 'The buyer message',
|
|
2582
|
+
paragraphs: [
|
|
2583
|
+
'The pitch is not "use fewer tokens" or "summarize harder." The pitch is: keep the agent productive by feeding it the right context, then stop it before risky actions unless the session, sandbox, credentials, and evidence are clean.',
|
|
2584
|
+
'This turns ThumbGate into the practitioner-led governance layer teams can adopt before top-down AI policy arrives. Start with one workflow, prove the gates locally, then expand to Pro or a hardening sprint once the same failure pattern recurs.',
|
|
2585
|
+
],
|
|
2586
|
+
},
|
|
2587
|
+
],
|
|
2588
|
+
faq: [
|
|
2589
|
+
{
|
|
2590
|
+
question: 'Is agent context governance just summarization?',
|
|
2591
|
+
answer: 'No. Summarization compresses. Context governance decides what to preserve, prune, merge, verify, or block based on the agent, task, risk, and evidence required before the next action.',
|
|
2592
|
+
},
|
|
2593
|
+
{
|
|
2594
|
+
question: 'Does this compete with Claude Managed Agents?',
|
|
2595
|
+
answer: 'No. Managed Agents provide production infrastructure. ThumbGate can sit beside managed or self-hosted agents as the local-first gate that turns session history, permissions, prior feedback, and evidence requirements into action-level enforcement.',
|
|
2596
|
+
},
|
|
2597
|
+
{
|
|
2598
|
+
question: 'What should teams implement first?',
|
|
2599
|
+
answer: 'Start with one high-cost workflow: deployments, billing, browser automation, database changes, or customer messaging. Require clean context, isolated execution, credential separation, and evidence before that workflow can run.',
|
|
2600
|
+
},
|
|
2601
|
+
{
|
|
2602
|
+
question: 'How does this apply to Claude custom instructions?',
|
|
2603
|
+
answer: 'Treat directness instructions as a policy, not a vibe. ThumbGate can turn them into checks that flag rubber-stamp agreement, missing pushback, and success claims that are not grounded in command output or artifacts.',
|
|
2604
|
+
},
|
|
2605
|
+
{
|
|
2606
|
+
question: 'How does ChatGPT Lockdown Mode help ThumbGate positioning?',
|
|
2607
|
+
answer: 'It validates the category. Lockdown Mode limits high-risk tools to reduce exfiltration paths; ThumbGate brings the same idea to coding and automation agents with local pre-action checks, scoped approvals, and audit evidence.',
|
|
2608
|
+
},
|
|
2609
|
+
{
|
|
2610
|
+
question: 'How should teams handle leaked or proxy-sold model claims?',
|
|
2611
|
+
answer: 'Do not route production work to unapproved proxy endpoints. Require provider provenance, expected model IDs, price ceilings, and security review before an agent can use a new frontier model route.',
|
|
2612
|
+
},
|
|
2613
|
+
{
|
|
2614
|
+
question: 'What is the first MCP security control to add?',
|
|
2615
|
+
answer: 'Watch the local MCP routing configuration for endpoint changes, new proxy addresses, and unexpected OAuth refresh behavior. Then rotate connected tokens only after the malicious hook or config rewrite has been removed.',
|
|
2616
|
+
},
|
|
2617
|
+
{
|
|
2618
|
+
question: 'Why mention random graph architecture in agent governance?',
|
|
2619
|
+
answer: 'Because centralized approval paths become bottlenecks. ThumbGate should use a mesh of local gates across repos, tools, agents, and workflows so control is resilient, inspectable, and does not require one fragile platform migration.',
|
|
2620
|
+
},
|
|
2621
|
+
{
|
|
2622
|
+
question: 'What changes when most new code is AI-authored?',
|
|
2623
|
+
answer: 'Review moves from typing every line to governing provenance, tests, ownership, and rollback. ThumbGate can require evidence before AI-authored diffs merge or touch production workflows.',
|
|
2624
|
+
},
|
|
2625
|
+
{
|
|
2626
|
+
question: 'How does this apply to AI email assistants?',
|
|
2627
|
+
answer: 'Treat every generated reply as a draft until it has source-backed context, a known category, customer-specific constraints, and human approval. Feedback from edited drafts should become retrieval and wording rules, not permission to send automatically.',
|
|
2628
|
+
},
|
|
2629
|
+
{
|
|
2630
|
+
question: 'What does platform ownership change?',
|
|
2631
|
+
answer: 'It prevents every team from building a slightly different unsafe agent loop. A shared platform defines intent shape, approved tools, retries, sandboxing, evals, logging, and gates while teams keep control over domain judgment.',
|
|
2632
|
+
},
|
|
2633
|
+
{
|
|
2634
|
+
question: 'Where do on-device QAT models fit?',
|
|
2635
|
+
answer: 'Use them for cheap private triage: classify risk, detect sensitive context, choose a route, or decide whether to escalate. Do not let a small local classifier silently approve destructive or external actions.',
|
|
2636
|
+
},
|
|
2637
|
+
{
|
|
2638
|
+
question: 'How does backpropagation help agent governance?',
|
|
2639
|
+
answer: 'Use the chain-rule idea as an audit pattern. Break the run into steps, score each local decision, multiply risk through the path, and cache the attribution so the next similar workflow is blocked or escalated earlier.',
|
|
2640
|
+
},
|
|
2641
|
+
],
|
|
2642
|
+
relatedPaths: ['/guides/long-running-agent-context-management', '/guides/background-agent-governance', '/guides/hermes-agent-guardrails'],
|
|
2643
|
+
},
|
|
2405
2644
|
{
|
|
2406
2645
|
query: 'roo code alternative cline',
|
|
2407
2646
|
path: '/guides/roo-code-alternative-cline',
|
|
@@ -3678,7 +3917,7 @@ ${renderWebPageJsonLd(page, { appOrigin })}
|
|
|
3678
3917
|
<body>
|
|
3679
3918
|
<div class="topbar">
|
|
3680
3919
|
<div class="container">
|
|
3681
|
-
<a class="brand" href="/"><img src="/assets/brand/thumbgate-mark-inline.svg" alt="ThumbGate" class="logo-mark" width="28" height="28"><span class="logo-text">ThumbGate</span></a>
|
|
3920
|
+
<a class="brand" href="/"><img src="/assets/brand/thumbgate-mark-inline-v3.svg" alt="ThumbGate" class="logo-mark" width="28" height="28"><span class="logo-text">ThumbGate</span></a>
|
|
3682
3921
|
<a href="${escapeHtml(PRODUCT.verificationUrl)}" target="_blank" rel="noopener">Verification evidence</a>
|
|
3683
3922
|
</div>
|
|
3684
3923
|
</div>
|
package/scripts/tool-registry.js
CHANGED
|
@@ -971,12 +971,12 @@ const TOOLS = [
|
|
|
971
971
|
}),
|
|
972
972
|
readOnlyTool({
|
|
973
973
|
name: 'verify_claim',
|
|
974
|
-
description: 'Check whether a claim has enough tracked evidence before the agent asserts it
|
|
974
|
+
description: 'Check whether a claim has enough tracked evidence before the agent asserts it.',
|
|
975
975
|
inputSchema: {
|
|
976
976
|
type: 'object',
|
|
977
977
|
required: ['claim'],
|
|
978
978
|
properties: {
|
|
979
|
-
claim: { type: 'string', description: 'The claim text to verify
|
|
979
|
+
claim: { type: 'string', description: 'The claim text to verify' },
|
|
980
980
|
goalContract: GOAL_CONTRACT_SCHEMA,
|
|
981
981
|
},
|
|
982
982
|
},
|
package/scripts/vector-store.js
CHANGED
|
@@ -172,6 +172,30 @@ async function embedWithGemini(text, options = {}) {
|
|
|
172
172
|
return values.map(Number);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
async function embedWithCoreAI(text, options = {}) {
|
|
176
|
+
if (process.platform !== 'darwin') {
|
|
177
|
+
throw new Error('Core AI is only supported on macOS');
|
|
178
|
+
}
|
|
179
|
+
const endpoint = process.env.THUMBGATE_COREAI_ENDPOINT || 'http://localhost:8088';
|
|
180
|
+
try {
|
|
181
|
+
const res = await fetch(`${endpoint}/embed`, {
|
|
182
|
+
method: 'POST',
|
|
183
|
+
headers: { 'Content-Type': 'application/json' },
|
|
184
|
+
body: JSON.stringify({ text, options }),
|
|
185
|
+
signal: AbortSignal.timeout(2000),
|
|
186
|
+
});
|
|
187
|
+
if (res.ok) {
|
|
188
|
+
const payload = await res.json();
|
|
189
|
+
if (Array.isArray(payload.embedding)) {
|
|
190
|
+
return payload.embedding.map(Number);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
} catch (err) {
|
|
194
|
+
throw new Error(`Core AI local service unavailable: ${err.message}`);
|
|
195
|
+
}
|
|
196
|
+
throw new Error('Core AI local service did not return a valid embedding');
|
|
197
|
+
}
|
|
198
|
+
|
|
175
199
|
async function embed(text, options = {}) {
|
|
176
200
|
if (process.env.THUMBGATE_VECTOR_STUB_EMBED === 'true') {
|
|
177
201
|
// Deterministic 384-dim unit vector: first element = 1.0, rest = 0.0
|
|
@@ -180,6 +204,26 @@ async function embed(text, options = {}) {
|
|
|
180
204
|
return stub;
|
|
181
205
|
}
|
|
182
206
|
const geminiConfig = resolveGeminiEmbeddingConfig();
|
|
207
|
+
if (geminiConfig.provider === 'coreai') {
|
|
208
|
+
try {
|
|
209
|
+
const vector = await embedWithCoreAI(text, options);
|
|
210
|
+
_lastEmbeddingProfile = {
|
|
211
|
+
generatedAt: new Date().toISOString(),
|
|
212
|
+
source: 'local-coreai',
|
|
213
|
+
activeProfile: {
|
|
214
|
+
id: 'coreai',
|
|
215
|
+
model: 'Core AI local model',
|
|
216
|
+
outputDimensionality: vector.length,
|
|
217
|
+
task: options.task || 'code retrieval',
|
|
218
|
+
rationale: 'Local Core AI Apple Silicon accelerated path.',
|
|
219
|
+
},
|
|
220
|
+
fallbackUsed: false,
|
|
221
|
+
};
|
|
222
|
+
return vector;
|
|
223
|
+
} catch (coreaiError) {
|
|
224
|
+
console.warn(`Core AI embedding failed, falling back to local: ${coreaiError.message}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
183
227
|
if (geminiConfig.enabled) {
|
|
184
228
|
try {
|
|
185
229
|
const vector = await embedWithGemini(text, options);
|