Skip to content

Feat/mobile backend - #7

Open
People62 wants to merge 28 commits into
mainfrom
feat/mobile-backend
Open

Feat/mobile backend#7
People62 wants to merge 28 commits into
mainfrom
feat/mobile-backend

Conversation

@People62

Copy link
Copy Markdown
Collaborator

No description provided.

HV NQRust and others added 28 commits July 17, 2026 05:43
- getMobileContext helper (Bearer userId + auto-resolved org)
- GET/POST /api/mobile/assistants (list w/ user default id, create)
- GET/PUT/DELETE /api/mobile/assistants/[id]
- POST /api/mobile/assistants/[id]/default (per-user default agent)
- POST /api/mobile/assistants/[id]/duplicate
- GET /api/mobile/models (slim list for the builder dropdown)
Load the session's assistant and use its systemPrompt (persona), model, and
modelConfig (temperature/topP/penalties). Clamp output tokens via the correct
AI SDK v6 field maxOutputTokens (the old maxTokens was silently ignored).
Bearer-auth mobile routes over the existing (auth-agnostic) workflow service:
- GET /api/mobile/workflows (org-scoped list)
- GET/PUT(status)/DELETE /api/mobile/workflows/[id]
- POST /api/mobile/workflows/[id]/execute (STANDARD only; CHATFLOW guarded)
- GET /api/mobile/workflows/[id]/runs and /runs/[runId]
authorizeMobileWorkflow enforces org scoping (web dashboard routes don't).
…xy, uploads)

Bearer-auth mobile routes over the existing (auth-agnostic) media service:
- POST/GET /api/mobile/media/jobs (generate image/audio, synchronous; VIDEO rejected)
- GET /api/mobile/media/assets (org gallery) + /[id] GET/PATCH(favorite)/DELETE
- GET /api/mobile/media/assets/[id]/file (proxy bytes so the phone never hits
  the internal S3 host — the key delivery fix)
- GET /api/mobile/media/models?modality=
- POST /api/mobile/media/uploads (multipart image → reference asset)
Org context is required (media is org-scoped).
…WAV)

OpenRouter requires stream:true for audio, and streaming only allows raw pcm16.
Rather than change the shared web generateAudio, mobile audio uses its own path
that streams pcm16 and wraps it into a playable WAV. The mobile jobs route
branches AUDIO -> createMobileAudioJob, IMAGE -> shared createMediaJob. No web
file is touched. Reuses the shared repository/storage (data layer) only.
React Native's <Image>/<Video> can't reliably attach an Authorization header on
Android, so the /file proxy now also accepts the JWT via a ?token= query param
(verified the same way). Adds userIdFromMobileToken helper.
Image models via OpenRouter ignore width/height (always square). Mobile now
center-crops the generated image to the requested aspect ratio and persists the
new bytes + dimensions (sharp). Mobile-only; web generation path unchanged.
Bearer-auth mobile routes over the existing (auth-decoupled, org-scoped)
knowledge service:
- GET/POST /api/mobile/knowledge/documents (list + upload; sync ingestion,
  maxDuration 600 since extract+OCR+chunk+embed run inline)
- GET/PUT/DELETE /api/mobile/knowledge/documents/[id]
- GET /api/mobile/knowledge/documents/[id]/file (byte proxy, ?token=)
- GET/POST /api/mobile/knowledge/groups + /[id] (GET/PUT/DELETE)
- GET/POST /api/mobile/knowledge/categories
…d ingest

- GET /api/mobile/knowledge/documents/[id]/intelligence (entities + relations,
  org-authorized via the document)
- upload defaults useEnhanced=true (entity/relation extraction) so the mobile
  Intelligence view has data; client can send enhanced=false to skip it
Two levers against the ~30s full-scan cosine that dominates KB chat latency:
- embeddings: send OpenAI-compatible `dimensions` = KB_EMBEDDING_DIM so query +
  re-embed can produce e.g. 1024-dim (qwen3 MRL) instead of 4096. Full-scan cost
  is ~O(N*dim), so 4096->1024 is a ~4x cut on its own. At dim=4096 (default) the
  body is identical to before (native), so the main corpus is unaffected.
- hybrid vectorSearch: opt-in KB_VECTOR_KNN=true uses the SurrealDB HNSW KNN
  operator (<|K,ef|>) instead of full scan — sub-linear, sub-second once an HNSW
  index exists at the lower dim. Gated: only for UNSCOPED queries (the operator
  returns global K nearest and can't honor an extra WHERE filter), with a
  full-scan fallback on error, so scoped/multi-tenant paths are untouched.

Both default OFF/native; enabled per-deployment via env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcfEvWTTaubz6wAhhaidHo
- bulk-re-embed: SurrealDB JS SDK v2 returns `id` from SELECT as a RecordId
  object, so `UPDATE document_chunk:\`${c.id}\`` built a malformed target and
  silently updated nothing — re-embeds reported success but never persisted.
  Bind the RecordId as a param (`UPDATE $rid ...`). This is why the demo's
  4096->1024 re-embed initially no-op'd.
- hybrid vectorSearch: KB_VECTOR_KNN now engages even for scoped queries (the
  widget always scopes to its KB's document_ids). Over-fetch index candidates
  (k=max(limit*5,100)) then AND the scope filter, so enough survive. Measured on
  the 11.5k-chunk / 1024-dim demo corpus: full-scan 5452ms -> KNN 109ms unscoped,
  616ms scoped. Still full-scan fallback on error; default OFF.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcfEvWTTaubz6wAhhaidHo
…ARCH_ENABLED

hybridRetrieve's entity arm runs an entity/graph traversal that, on a KB with no
populated entity graph, returns 0 results yet adds large, variable latency
(measured up to +28s on the 11.5k-chunk demo KB; entity results consistently 0).
Default stays on; set KB_ENTITY_SEARCH_ENABLED=false to skip it — quality-neutral
there and the single biggest remaining latency lever after HNSW KNN. Explicit
options.enableEntitySearch still overrides.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcfEvWTTaubz6wAhhaidHo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants