feat: Gemini bridge, browser extension hardening, shared memory
Nexus gateway (measured 2026-08-07, not assumed):
- Gemini speaks Google-GenAI (/v1beta/models/{id}:streamGenerateContent, header
api-key), NOT the Azure-OpenAI path — that returned 404 "no Route matched" and
was the cause of the reported failures. New agent/gemini_bridge.py translates
Bedrock Converse <-> Gemini in both directions.
- Only gemini-3.6-flash is subscribed; 2.5-flash/2.5-pro/3.1-flash-lite give 403,
every other name 404. Catalog corrected.
- Four Gemini rules, each previously an HTTP 400, now covered by tests:
thought signatures are mandatory, they belong to the TURN (not the individual
call), functionResponse turns must be homogeneous, arrays need `items`.
- Prompt caching is NOT available: cachePoint is accepted and ignored.
System prompt:
- Was an f-string; a code sample containing braces broke build_system_prompt at
request time (CLI and web both 500, import stayed green). Now a plain template
with __TOKEN__ placeholders. Regression guards in tests/test_system_prompt.py.
CLI:
- `agent resume` now prints the stored transcript. The history was always loaded
into the model context, only the terminal stayed empty.
Memory (new, all three surfaces):
- agent/memory.py stores notes about the user in one local file, written
atomically; memory.cnull.net remains an optional mirror that can never fail a
write. Tools memory_save/search/forget, injected into the prompt with a budget.
HTTP surface /api/memory for the extension.
Browser extension (agent/extension, first commit of the source):
- driveMode 'direct' talks to Nexus without the Python broker: Claude via
Bedrock converse, GPT via Azure-OpenAI, Gemini via Google-GenAI.
- browser_type no longer guesses the focused element — that wrote whole mails
into Outlook's subject line. Read-back now reports where the text actually
landed, so a mis-target is visible instead of silent.
- aria-labelledby is resolved across all ids (it is a list); contenteditable is
interactive and marked editable. Without this, subject and message body look
identical to the model.
- Hard block against sending mail, independent of riskMode.
- Runs survive the panel: events are buffered and replayed by sequence number.
- Image input (paste, file, drag&drop), on-page glow/spotlight, memory tools.
Cost: fixed tokens per round 11434 -> 6540 (-43%) by trimming tool schemas,
dropping gateway docs from the browser prompt and sending site knowledge only
where it applies.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import * as esbuild from 'esbuild';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
const watch = process.argv.includes('--watch');
|
||||
|
||||
/** @type {import('esbuild').BuildOptions} */
|
||||
const common = {
|
||||
bundle: true,
|
||||
sourcemap: true,
|
||||
target: 'es2022',
|
||||
format: 'esm',
|
||||
logLevel: 'info',
|
||||
};
|
||||
|
||||
const configs = [
|
||||
{
|
||||
...common,
|
||||
entryPoints: ['src/background/index.ts'],
|
||||
outfile: 'dist/background.js',
|
||||
},
|
||||
{
|
||||
...common,
|
||||
entryPoints: ['src/content/inject.ts'],
|
||||
outfile: 'dist/content.js',
|
||||
},
|
||||
{
|
||||
...common,
|
||||
entryPoints: ['src/sidepanel/app.ts'],
|
||||
outfile: 'dist/sidepanel.js',
|
||||
},
|
||||
{
|
||||
// Laeuft per Manifest in der MAIN world der Seite. Nur so ist der Konsolen-Hook
|
||||
// von der Content-Security-Policy der Seite ausgenommen.
|
||||
...common,
|
||||
format: 'iife',
|
||||
entryPoints: ['src/content/console-hook.ts'],
|
||||
outfile: 'dist/console-hook.js',
|
||||
},
|
||||
];
|
||||
|
||||
if (watch) {
|
||||
for (const cfg of configs) {
|
||||
const ctx = await esbuild.context(cfg);
|
||||
await ctx.watch();
|
||||
}
|
||||
console.log('Watching...');
|
||||
} else {
|
||||
for (const cfg of configs) {
|
||||
await esbuild.build(cfg);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user