Repository navigation
Gecko Suite for GAM: enrichment, embeddings and the new assistant - #58
Merged
Merged
Conversation
With AI_BACKEND=suite, build_provider and build_embedder (the two functions every enrichment job and the search already call) ask Gecko Suite instead of the providers and embedding settings this app keeps. They return objects with the same small interfaces as before, so no job changed shape: app/suite.py is everything GAM knows about the suite. "local" stays the default and the old path is untouched; the switch is a restart, in either direction. Enrichment is background work with no user session, so the suite is called as GAM on behalf of the asset's owner (SUITE_APP_SECRET, issued on the suite's Apps screen). The app refuses to start in suite mode without it, rather than every job failing hours later with a message that says nothing about why. Such a credential can use the gateway but never change anyone's settings. Describe, summarize and autotag each name their own job, so an administrator can route them to different models (a seeing one for describe, a cheap one for tagging); attribute follows summarize. The suite attributes the spend to the asset (gam:asset:<id>) and counts it, so record_completion writes nothing in this mode: nothing is counted twice. Speech and image-generation usage stays GAM's own until the suite takes those. A suite that is down does not stop the library. build_embedder answers None, exactly as for an unconfigured embedder, so search falls back to keywords; queueing enrichment is a 503 rather than a crash; a page import falls back to the bare links; jobs fail with one sentence and retry. The embedding width is SUITE_EMBEDDING_DIMENSIONS, 512: what this app has always asked OpenAI's text-embedding-3 models for, and what the existing index is wide, so switching under a populated library keeps it valid when the suite routes the same model. Settings says where AI is managed and links to the suite's Providers, Routing and Usage instead of a provider form and embedding settings that would never be used. The production overlay gains the suite's public name in extra_hosts (containers cannot reach the server's own public address). The client is pinned to a gecko-suite commit by archive URL, since python:3.13-slim has no git. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1geD2ELWgL2sDpxYbx3Aw
2 of 3 tasks
…osals to apply A conversation is saved; each turn runs as a job on the suite (chat.assistant) as GAM for the person who asked, with tools to search, read, list tags and propose. The turn ends with at most one proposal, stored on the turn row. Nothing in the library changes until Apply, which goes through the existing services (AI provenance for description and summary, human for an approved name, reindex on tag changes, enrichment jobs queued as usual). Only with AI_BACKEND=suite; local mode says so. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1geD2ELWgL2sDpxYbx3Aw
…osals to apply A Sparkles button in the header opens a panel beside the page. Its state is in a store (each route remounts the shell), a running turn is followed by polling and picked back up when reopened, and a proposal shows what would change per asset with a tick to leave some out. Says so plainly when the app isn't on Gecko Suite or no model is routed. Records the design decisions in the plan and CLAUDE.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1geD2ELWgL2sDpxYbx3Aw
The assistant uses run_agent's max_tokens_message, which the earlier pin predates. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1geD2ELWgL2sDpxYbx3Aw
1 of 2 tasks
main's merge of gecko-suite#3 predates the fix (davior/gecko-suite#4), so CI failed on SuiteEmbedder.resolve. Re-pin to main once #4 merges. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1geD2ELWgL2sDpxYbx3Aw
davior
marked this pull request as ready for review
November 2, 2026 11:39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
M2 for GAM: SA-1, SA-2, SA-5, SA-6 and SA-7 in gecko-suite's plan. Two parts, on one branch.
Merging this changes nothing until
AI_BACKEND=suiteis set.localis the default and the old path is untouched, so the move is one setting in either direction. The one addition that is not behind the switch is two new, empty tables (see Deployment).1. Enrichment and embeddings on the suite (SA-1, 5, 6, 7)
With
AI_BACKEND=suite,build_providerandbuild_embedderask Gecko Suite. These are the two functions every enrichment job and the search already call, so no job changed shape.app/suite.pyis everything GAM knows about the suite.SUITE_APP_SECRET, issued on the suite's Apps screen. The app refuses to start in suite mode without it. The credential can use the gateway but never change anyone's settings.enrich.describe,enrich.summarize,enrich.autotag(attribute follows summarize), so an administrator can route them to different models. The spend is attributed to the asset (gam:asset:<id>).record_completionwrites nothing in this mode and nothing is counted twice. Speech and image-generation usage stays GAM's own until the suite takes those (M3).build_embedderanswersNoneso search falls back to keywords; queueing enrichment is a 503, not a crash; a page import falls back to bare links; jobs fail with one sentence and retry.SUITE_EMBEDDING_DIMENSIONS), what the existing index is wide.Settings says where AI is managed and links to the suite's Providers, Routing and Usage, instead of a provider form that would never be used. Its Usage panel stays.
2. The assistant (SA-2)
A side panel (the sparkles button in the header) for asking about the library and having it tidied. Only with
AI_BACKEND=suite; otherwise the panel says so and offers no text box.search_assets,get_asset,read_transcript,list_tags) or record a proposal (propose_changes,propose_enrichment). There is no tool that writes.chat.assistant, so it can have a model of its own. A model without thetoolscapability is refused with a sentence saying where to change it.run_agentingecko-suite-client, the loop extracted from GVC.Not yet: generating images from the panel (suite M3), and reading pictures the person attaches. Both are additions to the tool list, not changes to the shape.
Review notes:
SuiteEmbedder: GAM readsembedder.modelbefore anyembed()call. Fixed in davior/gecko-suite#3; this PR pins the commit that has it.python:3.13-slimhas nogit. I'll re-pin tomainonce that PR merges.docker-compose.prod.ymlgainssuite.geckopico.cominextra_hosts: containers can't reach the server's own public address, so without it enrichment would fail in production while every test passed.Test plan
cd backend && pytest -q: 1518 passed. That includes 15 tests for suite-mode enrichment and 17 for the assistant: status, a turn end to end, apply once, apply a subset, discard, enrichment queued on apply, ownership, a no-op proposal, suite down mid-turn, stop before start, replayed history, one turn at a time, another user's conversation, delete.cd frontend && npm run format:check && npm run lint && npm test && npm run build: 470 tests passed; build typechecks.Deployment
Merging and redeploying changes nothing for users until you switch
AI_BACKEND.toolscapability; ideally one that can also see images, for describe;text-embedding-3-small), or search loses its semantic half until you run Backfill under Settings..env; all optional until you switch):AI_BACKEND=localis the default. Set it tosuiteto switch.SUITE_APP_SECRET: the secret from step 2. Required onceAI_BACKEND=suite; the app won't start without it.SUITE_BASE_URL=https://suite.geckopico.comandSUITE_EMBEDDING_DIMENSIONS=512are the defaults. Leave the second alone under a populated library.ASSISTANT_CONCURRENCY(2),ASSISTANT_MAX_ROUNDS(16),ASSISTANT_HISTORY_MESSAGES(20),ASSISTANT_TRANSCRIPT_CHARS(12000): defaults are fine.curl -f http://localhost:${APP_PORT}/api/healthc3a95e7d1f42(add_assistant_tables) runs on container start and creates two new tables,assistant_sessionandassistant_turn. It touches no existing data and downgrades by dropping them. Nothing needs backing up first.SUITE_APP_SECRETandAI_BACKEND=suitein.env, thendocker compose up -d. A restart, not a rebuild.AI_BACKEND=local, the panel says it needs the suite.AI_BACKEND=localand rundocker compose up -d. Your providers and embedding settings are still there. A job running at the moment of the switch fails and can be retried. Saved conversations stay in the database, unused.🤖 Generated with Claude Code
https://claude.ai/code/session_01V1geD2ELWgL2sDpxYbx3Aw