fix(app): URLSearchParams crasht in Hermes — durch Mini-Query-Builder ersetzt
Inbox-Crash gefunden via App-Crash-Reporter (commit21a315c): "URLSearchParams.set is not implemented" at MemoryBrowser → brainApi.listMemories React Native's Hermes-Polyfill kennt zwar new URLSearchParams() aber nicht die .set()-Methode darauf. Pickup-Bug — auf iOS / aelteren Versionen geht's, Stefan's Android-Build crasht. Fix: kleine _qs()-Helper im brainApi.ts der einen Query-String aus einem flachen Object baut, ohne URLSearchParams: _qs({q:'cessna', k:5, type:'fact'}) → "?q=cessna&k=5&type=fact" Plus: undefined/null/empty Werte werden ausgelassen — saubererer als URLSearchParams.set wo man manuell prefilten muss. ErrorBoundary aus21a315chat den Crash sauber abgefangen, statt der App-Tot war ne Error-Box im Inbox-Modal mit der vollen Stack-Trace. Stefan konnte den Log via tools/fetch-app-logs.sh holen ohne ADB. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,18 @@ function _newRequestId(): string {
|
||||
return `brain_${Date.now().toString(36)}_${_nextId}`;
|
||||
}
|
||||
|
||||
/** Mini-Query-String-Builder ohne URLSearchParams (Hermes-Polyfill kennt
|
||||
* kein URLSearchParams.set, crasht). Akzeptiert object mit string/number/
|
||||
* bool-Values; undefined/null/leere Strings werden ausgelassen. */
|
||||
function _qs(params: Record<string, unknown>): string {
|
||||
const parts: string[] = [];
|
||||
for (const [k, v] of Object.entries(params)) {
|
||||
if (v === undefined || v === null || v === '') continue;
|
||||
parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
|
||||
}
|
||||
return parts.length ? `?${parts.join('&')}` : '';
|
||||
}
|
||||
|
||||
interface SendOpts {
|
||||
method?: 'GET' | 'POST' | 'PATCH' | 'DELETE';
|
||||
body?: AnyJson;
|
||||
@@ -119,29 +131,31 @@ export const brainApi = {
|
||||
|
||||
/** Liste aller Memories, optional nach Type gefiltert. */
|
||||
listMemories(opts: { type?: string; limit?: number } = {}): Promise<Memory[]> {
|
||||
const qs = new URLSearchParams();
|
||||
if (opts.type) qs.set('type', opts.type);
|
||||
qs.set('limit', String(opts.limit || 500));
|
||||
return _send(`/memory/list?${qs.toString()}`);
|
||||
const qs = _qs({ type: opts.type, limit: opts.limit || 500 });
|
||||
return _send(`/memory/list${qs}`);
|
||||
},
|
||||
|
||||
/** Volltext-Substring-Suche. */
|
||||
searchText(q: string, opts: { type?: string; includePinned?: boolean; k?: number } = {}): Promise<Memory[]> {
|
||||
const qs = new URLSearchParams({ q });
|
||||
if (opts.type) qs.set('type', opts.type);
|
||||
qs.set('include_pinned', String(opts.includePinned !== false));
|
||||
qs.set('k', String(opts.k || 50));
|
||||
return _send(`/memory/search-text?${qs.toString()}`);
|
||||
const qs = _qs({
|
||||
q,
|
||||
type: opts.type,
|
||||
include_pinned: opts.includePinned !== false,
|
||||
k: opts.k || 50,
|
||||
});
|
||||
return _send(`/memory/search-text${qs}`);
|
||||
},
|
||||
|
||||
/** Semantische Suche (Embedder). */
|
||||
searchSemantic(q: string, opts: { type?: string; includePinned?: boolean; k?: number; threshold?: number } = {}): Promise<Memory[]> {
|
||||
const qs = new URLSearchParams({ q });
|
||||
if (opts.type) qs.set('type', opts.type);
|
||||
qs.set('include_pinned', String(opts.includePinned !== false));
|
||||
qs.set('k', String(opts.k || 10));
|
||||
qs.set('score_threshold', String(opts.threshold ?? 0.30));
|
||||
return _send(`/memory/search?${qs.toString()}`);
|
||||
const qs = _qs({
|
||||
q,
|
||||
type: opts.type,
|
||||
include_pinned: opts.includePinned !== false,
|
||||
k: opts.k || 10,
|
||||
score_threshold: opts.threshold ?? 0.30,
|
||||
});
|
||||
return _send(`/memory/search${qs}`);
|
||||
},
|
||||
|
||||
/** Memory anlegen. */
|
||||
|
||||
Reference in New Issue
Block a user