@tpsdev-ai/adk-flair 0.48.0 → 0.50.0
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/README.md +59 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/memory_service.d.ts +175 -14
- package/dist/memory_service.d.ts.map +1 -1
- package/dist/memory_service.js +456 -64
- package/dist/memory_service.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,14 +89,21 @@ server.start();
|
|
|
89
89
|
|
|
90
90
|
All values can also be passed directly to the constructor.
|
|
91
91
|
|
|
92
|
+
Hosted Flair (non-localhost `FLAIR_URL`) uses the same Ed25519 triple as the
|
|
93
|
+
Python package — agent id, keyfile, server-side `Agent` row with a matching
|
|
94
|
+
public key. A 404 on `GET`/`PUT /Memory/{id}` is fail-closed ownership, not
|
|
95
|
+
an existence signal. Walkthrough:
|
|
96
|
+
[docs/integrations.md — Hosted Flair auth](../../docs/integrations.md#hosted-flair-auth--your-agent-got-a-404).
|
|
97
|
+
|
|
92
98
|
## Architecture
|
|
93
99
|
|
|
94
100
|
### Scope model
|
|
95
101
|
|
|
96
102
|
Each ADK app authenticates as **one Flair agent** (its service identity).
|
|
97
103
|
Per-user isolation is enforced by a **compound tag** — `adk:<app_name>:<user_id>`
|
|
98
|
-
— attached to every record and filtered on every search.
|
|
99
|
-
|
|
104
|
+
— attached to every record and filtered on every search. Reserved characters
|
|
105
|
+
(`%`, `:`, `_`) in `app_name` or `user_id` are percent-encoded so distinct
|
|
106
|
+
identities never collide and the `:` delimiter stays unambiguous.
|
|
100
107
|
|
|
101
108
|
### Search path
|
|
102
109
|
|
|
@@ -107,7 +114,13 @@ or `user_id` are replaced with underscores to prevent delimiter breakage.
|
|
|
107
114
|
|
|
108
115
|
### Write path
|
|
109
116
|
|
|
110
|
-
- Deterministic record IDs: `app:user:session:eventId` — re-ingestion upserts
|
|
117
|
+
- Deterministic record IDs: `app:user:session:eventId` — re-ingestion upserts.
|
|
118
|
+
Direct `addMemory()` writes use the entry's `id` when supplied, else the
|
|
119
|
+
first 32 hex chars of the content's SHA-256 (re-adds replace, not duplicate)
|
|
120
|
+
- Creates ride `POST /Memory/` (the create verb) with the id in the body; a
|
|
121
|
+
`409` (record already exists) falls back to `PUT /Memory/{id}`, preserving
|
|
122
|
+
replace semantics — a PUT-shaped create 404s on Harper deployments where
|
|
123
|
+
PUT is update-only (flair#1336)
|
|
111
124
|
- Write failures log a structured warning (session id, event count, HTTP status)
|
|
112
125
|
- No-text events are filtered (Vertex parity)
|
|
113
126
|
|
|
@@ -140,8 +153,49 @@ Implements `BaseMemoryService` from `@google/adk`.
|
|
|
140
153
|
|
|
141
154
|
#### Extra methods (Vertex parity, not called by ADK)
|
|
142
155
|
|
|
143
|
-
- **`addEventsToMemory(appName, userId, events, sessionId)`** — incremental per-turn writes
|
|
144
|
-
- **`addMemory(appName, userId, memories)`** — direct
|
|
156
|
+
- **`addEventsToMemory(appName, userId, events, sessionId, customMetadata?)`** — incremental per-turn writes
|
|
157
|
+
- **`addMemory(appName, userId, memories, customMetadata?, opts?)`** — direct
|
|
158
|
+
memory writes. `opts`: `{ subject?, durability?, visibility? }`
|
|
159
|
+
- **`listMemories(appName, userId, { limit?, offset? })`** — Flair-specific
|
|
160
|
+
browsing extension (NOT part of `BaseMemoryService`)
|
|
161
|
+
|
|
162
|
+
### Custom metadata & subject
|
|
163
|
+
|
|
164
|
+
`customMetadata` (an arbitrary JSON-serializable object) is stored on every
|
|
165
|
+
record a write call produces, as an opaque blob on the record's `metadata`
|
|
166
|
+
field, and round-trips back on `FlairMemoryEntry.customMetadata` from
|
|
167
|
+
`searchMemory` / `listMemories`.
|
|
168
|
+
|
|
169
|
+
**Store-and-return only** — ADK's contract: no key inside the blob has ANY
|
|
170
|
+
server-side effect. `{"visibility": "shared"}` in the blob does **not** share
|
|
171
|
+
the memory; use the explicit `opts.visibility` for that. Caps (throw before
|
|
172
|
+
any write; reject, never truncate): 64KB serialized, nesting depth ≤ 16,
|
|
173
|
+
≤ 512 total keys. Non-JSON-serializable values skip that key with a warning.
|
|
174
|
+
|
|
175
|
+
`subject` is a short human-readable title (≤ 512 chars) promoted to the
|
|
176
|
+
record's top-level indexed `subject` column — supplied via `opts.subject` or
|
|
177
|
+
`customMetadata.subject` (the explicit option is authoritative when both are
|
|
178
|
+
present), never auto-extracted from content. On read it surfaces both as
|
|
179
|
+
`entry.subject` and `customMetadata["subject"]` (the column is authoritative
|
|
180
|
+
over a divergent blob key; the `customMetadata` channel matches the Python
|
|
181
|
+
package's return shape exactly).
|
|
182
|
+
|
|
183
|
+
Read-path notes: `searchMemory` opts into `/SemanticSearch`'s
|
|
184
|
+
`includeMetadata` projection flag; a malformed stored blob fails soft to `{}`
|
|
185
|
+
with a warning naming the record id (a corrupt blob never takes recall down).
|
|
186
|
+
Returned entries also carry the record `id`, `author` (the writing Flair
|
|
187
|
+
agent id), and `timestamp` (the record's `createdAt`).
|
|
188
|
+
|
|
189
|
+
### listMemories
|
|
190
|
+
|
|
191
|
+
Lists an app+user's memories newest-first (`createdAt` DESC) with the full
|
|
192
|
+
projection — no query needed. Scope is the compound tag AND the service's
|
|
193
|
+
agent identity, both pushed down server-side and re-verified client-side.
|
|
194
|
+
`limit` is 1..200 — over-cap **rejects** (never silently clamps); `offset` is
|
|
195
|
+
positional over a point-in-time snapshot, not a live cursor. Unlike
|
|
196
|
+
`searchMemory` (whose swallow-to-empty contract is ADK's), transport and HTTP
|
|
197
|
+
failures **propagate** — a browsing UI must be able to tell "no memories"
|
|
198
|
+
from "Flair is down".
|
|
145
199
|
|
|
146
200
|
## License
|
|
147
201
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
6
|
export { FlairMemoryService } from "./memory_service.js";
|
|
7
|
+
export type { FlairMemoryEntry, FlairSearchMemoryResponse, AddMemoryOptions, ListMemoriesOptions, FlairDurability, FlairVisibility, } from "./memory_service.js";
|
|
7
8
|
export { compoundTag, sanitizeTagSegment, desanitizeTagSegment } from "./tag.js";
|
|
8
9
|
export { loadEd25519Key, signRequest } from "./signing.js";
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EACV,gBAAgB,EAChB,yBAAyB,EACzB,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AASzD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/memory_service.d.ts
CHANGED
|
@@ -2,22 +2,91 @@
|
|
|
2
2
|
* FlairMemoryService — Flair as the memory backend for Google ADK (JS/TS).
|
|
3
3
|
*
|
|
4
4
|
* Implements @google/adk's `BaseMemoryService` interface (2 required methods)
|
|
5
|
-
* plus the Vertex-parity extras (`addEventsToMemory`, `addMemory`)
|
|
5
|
+
* plus the Vertex-parity extras (`addEventsToMemory`, `addMemory`) and the
|
|
6
|
+
* Flair-specific `listMemories` browsing extension.
|
|
6
7
|
*
|
|
7
8
|
* Ported from the Python `adk-flair` package. See specs/ADK-FLAIR-ADAPTER.md
|
|
8
|
-
* in the tpsdev-ai/cli repo for the full design
|
|
9
|
+
* in the tpsdev-ai/cli repo for the full design; customMetadata/subject/
|
|
10
|
+
* listMemories semantics mirror the Python package's flair#1332/#1333
|
|
11
|
+
* implementation (#1334), and the create-verb semantics mirror flair#1336
|
|
12
|
+
* (#1339).
|
|
9
13
|
*/
|
|
10
14
|
import type { BaseMemoryService, SearchMemoryRequest, SearchMemoryResponse } from "@google/adk";
|
|
11
15
|
import type { MemoryEntry } from "@google/adk";
|
|
12
16
|
import type { Session } from "@google/adk";
|
|
13
17
|
import type { Event } from "@google/adk";
|
|
18
|
+
/** Explicit write knobs accepted by the Memory schema. */
|
|
19
|
+
export type FlairDurability = "permanent" | "persistent" | "standard" | "ephemeral";
|
|
20
|
+
export type FlairVisibility = "private" | "shared";
|
|
21
|
+
/**
|
|
22
|
+
* A MemoryEntry as returned by this service's read paths (searchMemory /
|
|
23
|
+
* listMemories).
|
|
24
|
+
*
|
|
25
|
+
* @google/adk's `MemoryEntry` is a plain-object interface (content, author?,
|
|
26
|
+
* timestamp?) — unlike the Python package's pydantic model it drops nothing at
|
|
27
|
+
* runtime, so Flair surfaces its extra fields BOTH top-level and (for
|
|
28
|
+
* `subject`) inside `customMetadata`:
|
|
29
|
+
*
|
|
30
|
+
* - `customMetadata` — the stored metadata blob parsed back to an object
|
|
31
|
+
* (fail-soft `{}` + warning on a malformed blob). When the record carries a
|
|
32
|
+
* top-level `subject` column it is ALSO surfaced as
|
|
33
|
+
* `customMetadata["subject"]` — the column is authoritative over any
|
|
34
|
+
* divergent blob key, and this channel keeps the return shape identical to
|
|
35
|
+
* the Python package (whose MemoryEntry has no subject attribute, making
|
|
36
|
+
* custom_metadata its only subject return channel).
|
|
37
|
+
* - `subject` — the top-level subject column, surfaced directly as well
|
|
38
|
+
* (JS-only convenience; same value as `customMetadata["subject"]`).
|
|
39
|
+
* - `id` — the Flair record id.
|
|
40
|
+
*/
|
|
41
|
+
export interface FlairMemoryEntry extends MemoryEntry {
|
|
42
|
+
/** Flair Memory record id. */
|
|
43
|
+
id?: string;
|
|
44
|
+
/** Top-level `subject` column value, when the record carries one. */
|
|
45
|
+
subject?: string;
|
|
46
|
+
/** Stored customMetadata blob, parsed back. Always present (possibly {}). */
|
|
47
|
+
customMetadata: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
/** searchMemory response with the Flair-typed entries. */
|
|
50
|
+
export interface FlairSearchMemoryResponse extends SearchMemoryResponse {
|
|
51
|
+
memories: FlairMemoryEntry[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Options for `addMemory` (flair#1332 + Python-parity explicit knobs).
|
|
55
|
+
*
|
|
56
|
+
* All are trust-anchor opt-ins — never model-selected, never sourced from
|
|
57
|
+
* `customMetadata` (except `subject`, which `customMetadata.subject` may also
|
|
58
|
+
* supply; the explicit option is authoritative when both are present).
|
|
59
|
+
*/
|
|
60
|
+
export interface AddMemoryOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Short human-readable title promoted to the record's top-level indexed
|
|
63
|
+
* `subject` column. <= 512 chars (rejects beyond). Never auto-extracted
|
|
64
|
+
* from content. Authoritative over `customMetadata["subject"]`.
|
|
65
|
+
*/
|
|
66
|
+
subject?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Explicit durability. Omitted → "standard" in the body (unchanged
|
|
69
|
+
* behaviour). One of permanent | persistent | standard | ephemeral.
|
|
70
|
+
*/
|
|
71
|
+
durability?: FlairDurability;
|
|
72
|
+
/**
|
|
73
|
+
* Explicit visibility. Omitted → no visibility key in the body (server
|
|
74
|
+
* applies its durability-keyed default). One of private | shared.
|
|
75
|
+
*/
|
|
76
|
+
visibility?: FlairVisibility;
|
|
77
|
+
}
|
|
78
|
+
/** Options for `listMemories` (flair#1333). */
|
|
79
|
+
export interface ListMemoriesOptions {
|
|
80
|
+
/** Page size, 1..200. Over-cap REJECTS (never silently clamps). Default 50. */
|
|
81
|
+
limit?: number;
|
|
82
|
+
/** Number of newest records to skip (>= 0). Positional, not a live cursor. */
|
|
83
|
+
offset?: number;
|
|
84
|
+
}
|
|
14
85
|
export declare class FlairMemoryService implements BaseMemoryService {
|
|
15
86
|
private readonly _url;
|
|
16
87
|
private readonly _agentId;
|
|
17
88
|
private readonly _privateKey;
|
|
18
89
|
private readonly _timeoutMs;
|
|
19
|
-
/** Per-session state for custom_metadata warn-once (Python parity). */
|
|
20
|
-
private _warnedSessions;
|
|
21
90
|
/**
|
|
22
91
|
* @param url - Flair HTTP URL (default: FLAIR_URL env or http://localhost:19926)
|
|
23
92
|
* @param agentId - Flair agent ID (default: FLAIR_AGENT_ID env)
|
|
@@ -31,29 +100,121 @@ export declare class FlairMemoryService implements BaseMemoryService {
|
|
|
31
100
|
timeoutMs?: number;
|
|
32
101
|
});
|
|
33
102
|
addSessionToMemory(session: Session): Promise<void>;
|
|
34
|
-
searchMemory(request: SearchMemoryRequest): Promise<
|
|
103
|
+
searchMemory(request: SearchMemoryRequest): Promise<FlairSearchMemoryResponse>;
|
|
35
104
|
/**
|
|
36
105
|
* Add events to memory incrementally (the quickstart's after_agent_callback path).
|
|
37
106
|
* Not called by ADK — use in after_agent_callback or directly.
|
|
38
107
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
108
|
+
* customMetadata (flair#1332) is stored on every record this call writes,
|
|
109
|
+
* as an opaque JSON blob on the Memory record's `metadata` field, and
|
|
110
|
+
* round-trips back on `FlairMemoryEntry.customMetadata` from searchMemory /
|
|
111
|
+
* listMemories. Store-and-return only — no key in it has any server-side
|
|
112
|
+
* effect. Caps (Error before any write): 64KB serialized, nesting depth
|
|
113
|
+
* <= 16, <= 512 total keys. customMetadata["subject"] (a string) is
|
|
114
|
+
* additionally promoted to the record's top-level `subject` column
|
|
115
|
+
* (<= 512 chars).
|
|
41
116
|
*/
|
|
42
117
|
addEventsToMemory(appName: string, userId: string, events: Event[], sessionId: string, customMetadata?: Record<string, unknown>): Promise<void>;
|
|
43
118
|
/**
|
|
44
119
|
* Add memory entries directly.
|
|
45
120
|
* Not called by ADK — use for direct memory writes.
|
|
46
121
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
122
|
+
* customMetadata (flair#1332) is stored on every record this call writes,
|
|
123
|
+
* as an opaque JSON blob on the Memory record's `metadata` field, and
|
|
124
|
+
* round-trips back on `FlairMemoryEntry.customMetadata` from searchMemory /
|
|
125
|
+
* listMemories. Store-and-return only (the ADK contract, flair#1202): no
|
|
126
|
+
* key inside the blob has ANY server-side effect — {"visibility":"shared"}
|
|
127
|
+
* in here does not share the memory (use the explicit `visibility` option
|
|
128
|
+
* for that). Caps (Error before any write; reject, never truncate): 64KB
|
|
129
|
+
* serialized, nesting depth <= 16, <= 512 total keys. Non-JSON-serializable
|
|
130
|
+
* values skip that key with a warning.
|
|
131
|
+
*
|
|
132
|
+
* opts.subject (flair#1332, Flair-specific extension): short human-readable
|
|
133
|
+
* title promoted to the record's top-level indexed `subject` column.
|
|
134
|
+
* Sourced from this option or customMetadata["subject"]; the explicit
|
|
135
|
+
* option is authoritative when both are present. <= 512 chars (Error
|
|
136
|
+
* beyond). Never auto-extracted from content.
|
|
137
|
+
*
|
|
138
|
+
* opts.durability / opts.visibility: trust-anchor opt-ins (Python-parity
|
|
139
|
+
* explicit knobs), validated against the schema enums. Omitted durability →
|
|
140
|
+
* "standard"; omitted visibility → no key in the body (server default).
|
|
141
|
+
*
|
|
142
|
+
* Record ids mirror the Python package: `entry.id` when the caller supplies
|
|
143
|
+
* one (FlairMemoryEntry input), else the first 32 hex chars of the content's
|
|
144
|
+
* SHA-256 — deterministic, so re-adding identical content replaces rather
|
|
145
|
+
* than duplicates.
|
|
49
146
|
*/
|
|
50
|
-
addMemory(appName: string, userId: string, memories: MemoryEntry
|
|
147
|
+
addMemory(appName: string, userId: string, memories: Array<MemoryEntry & {
|
|
148
|
+
id?: string;
|
|
149
|
+
}>, customMetadata?: Record<string, unknown>, opts?: AddMemoryOptions): Promise<void>;
|
|
51
150
|
/**
|
|
52
|
-
*
|
|
151
|
+
* List recent memories for an app+user, newest first.
|
|
152
|
+
*
|
|
153
|
+
* Flair-specific extension — NOT part of ADK's BaseMemoryService (which
|
|
154
|
+
* specifies only searchMemory). Useful for memory review UIs, dashboards,
|
|
155
|
+
* and agent contextual browsing where there is no query to search with.
|
|
156
|
+
*
|
|
157
|
+
* Scope: the same compound tag (adk:<app>:<user>) searchMemory uses, AND
|
|
158
|
+
* agentId === this service's agent identity — both pushed down as
|
|
159
|
+
* server-side query conditions and re-verified client-side on every
|
|
160
|
+
* returned row (defense in depth).
|
|
161
|
+
*
|
|
162
|
+
* Pagination: `offset` is POSITIONAL over a point-in-time snapshot ordered
|
|
163
|
+
* by createdAt descending — not a live cursor. Memories written between
|
|
164
|
+
* two pages shift positions, so a record can appear twice or be skipped
|
|
165
|
+
* across page boundaries. For a consistent view, take one page, or dedupe
|
|
166
|
+
* by id across pages.
|
|
167
|
+
*
|
|
168
|
+
* Throws on invalid arguments, and — unlike searchMemory (whose
|
|
169
|
+
* empty-on-error contract is ADK's) — PROPAGATES transport and HTTP
|
|
170
|
+
* failures: a browsing UI must be able to tell "no memories" from
|
|
171
|
+
* "Flair is down".
|
|
172
|
+
*/
|
|
173
|
+
listMemories(appName: string, userId: string, opts?: ListMemoriesOptions): Promise<FlairMemoryEntry[]>;
|
|
174
|
+
/**
|
|
175
|
+
* Map a Flair Memory record/hit onto a FlairMemoryEntry.
|
|
176
|
+
*
|
|
177
|
+
* author derives from the record's agentId — the writing Flair agent
|
|
178
|
+
* (flair#1332 incidental fix, mirrored: records carry no "author" field,
|
|
179
|
+
* so reading hit.author was always undefined). timestamp derives from the
|
|
180
|
+
* record's createdAt for the same reason.
|
|
181
|
+
*/
|
|
182
|
+
private _hitToMemoryEntry;
|
|
183
|
+
/**
|
|
184
|
+
* Rebuild FlairMemoryEntry.customMetadata from a record's stored fields.
|
|
185
|
+
*
|
|
186
|
+
* - `metadata` (the opaque JSON blob) parses back to an object. FAIL-SOFT:
|
|
187
|
+
* malformed JSON (or JSON that isn't an object) yields {} plus a warning
|
|
188
|
+
* naming the record id — a corrupt blob on one record must never take
|
|
189
|
+
* the whole read path down.
|
|
190
|
+
* - A top-level `subject` column is surfaced as customMetadata["subject"].
|
|
191
|
+
* The COLUMN is authoritative (flair#1332 ruling): when the blob carries
|
|
192
|
+
* a divergent "subject" key, the column value overwrites it in the
|
|
193
|
+
* returned object. This keeps the customMetadata return shape identical
|
|
194
|
+
* to the Python package — a subject written via the explicit option
|
|
195
|
+
* (never in the blob) still round-trips through customMetadata.
|
|
196
|
+
*/
|
|
197
|
+
private _hitCustomMetadata;
|
|
198
|
+
/**
|
|
199
|
+
* Send one signed JSON-bodied request. The signing payload covers the full
|
|
200
|
+
* path (METHOD:pathname), so the path passed here is the one signed.
|
|
201
|
+
*/
|
|
202
|
+
private _sendJson;
|
|
203
|
+
/**
|
|
204
|
+
* Create-or-replace one Memory record.
|
|
205
|
+
*
|
|
206
|
+
* Creates via `POST /Memory/` — Harper's collection create verb — with the
|
|
207
|
+
* id in the body. The previous shape, `PUT /Memory/{id}`, is update-only on
|
|
208
|
+
* some Harper deployments and 404s when the record does not exist yet
|
|
209
|
+
* (flair#1336, observed on hosted Harper Fabric; not reproducible on stock
|
|
210
|
+
* Harper 5.2.x, where PUT upserts). Mirrors the Python package's #1339 fix.
|
|
53
211
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
212
|
+
* A 409 from POST means the record already exists — re-ingestion of a
|
|
213
|
+
* deterministic id (addSessionToMemory re-saves a growing session's earlier
|
|
214
|
+
* events every time) or a caller-supplied id being rewritten. Fall back to
|
|
215
|
+
* `PUT /Memory/{id}` for exactly that case, preserving the pre-#1336
|
|
216
|
+
* replace/refresh semantics for existing rows. Any other error propagates
|
|
217
|
+
* unchanged (the write-path warning logs carry the real HTTP status).
|
|
57
218
|
*/
|
|
58
219
|
private _writeRecord;
|
|
59
220
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory_service.d.ts","sourceRoot":"","sources":["../src/memory_service.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"memory_service.d.ts","sourceRoot":"","sources":["../src/memory_service.ts"],"names":[],"mappings":"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"}
|
package/dist/memory_service.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
* FlairMemoryService — Flair as the memory backend for Google ADK (JS/TS).
|
|
3
3
|
*
|
|
4
4
|
* Implements @google/adk's `BaseMemoryService` interface (2 required methods)
|
|
5
|
-
* plus the Vertex-parity extras (`addEventsToMemory`, `addMemory`)
|
|
5
|
+
* plus the Vertex-parity extras (`addEventsToMemory`, `addMemory`) and the
|
|
6
|
+
* Flair-specific `listMemories` browsing extension.
|
|
6
7
|
*
|
|
7
8
|
* Ported from the Python `adk-flair` package. See specs/ADK-FLAIR-ADAPTER.md
|
|
8
|
-
* in the tpsdev-ai/cli repo for the full design
|
|
9
|
+
* in the tpsdev-ai/cli repo for the full design; customMetadata/subject/
|
|
10
|
+
* listMemories semantics mirror the Python package's flair#1332/#1333
|
|
11
|
+
* implementation (#1334), and the create-verb semantics mirror flair#1336
|
|
12
|
+
* (#1339).
|
|
9
13
|
*/
|
|
10
14
|
import * as crypto from "node:crypto";
|
|
11
15
|
import { loadEd25519Key, signRequest } from "./signing.js";
|
|
@@ -14,6 +18,31 @@ import { compoundTag } from "./tag.js";
|
|
|
14
18
|
const LOCALHOST_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
|
|
15
19
|
const ALLOW_REMOTE_ENV = "FLAIR_ALLOW_REMOTE_URL";
|
|
16
20
|
const DEFAULT_FLAIR_URL = "http://localhost:19926";
|
|
21
|
+
// customMetadata caps (flair#1332, Sherlock hard requirements — mirrors the
|
|
22
|
+
// Python package). REJECT, never truncate — a truncated blob silently corrupts
|
|
23
|
+
// the store-and-return round-trip guarantee, which is the entire contract of
|
|
24
|
+
// the field.
|
|
25
|
+
// - METADATA_MAX_BYTES: serialized JSON size cap. 64KB is generous for
|
|
26
|
+
// structured attributes (merchant/price/category/media refs) while keeping
|
|
27
|
+
// a single memory record from becoming a blob store.
|
|
28
|
+
// - METADATA_MAX_DEPTH / METADATA_MAX_KEYS: cheap structural caps checked
|
|
29
|
+
// BEFORE serialization (billion-laughs-adjacent guard — a pathologically
|
|
30
|
+
// nested/wide object is refused without ever attempting to serialize it).
|
|
31
|
+
const METADATA_MAX_BYTES = 64 * 1024;
|
|
32
|
+
const METADATA_MAX_DEPTH = 16;
|
|
33
|
+
const METADATA_MAX_KEYS = 512;
|
|
34
|
+
// subject cap (flair#1332): subject is a short human-readable title promoted
|
|
35
|
+
// to the record's top-level indexed `subject` column — never a content field.
|
|
36
|
+
const SUBJECT_MAX_CHARS = 512;
|
|
37
|
+
// listMemories page-size hard cap (flair#1333). Reject-with-error (never
|
|
38
|
+
// clamp) — consistent with every other adk-flair validation: a silently
|
|
39
|
+
// clamped limit would make "I asked for 500, why did I get 200" a debugging
|
|
40
|
+
// session instead of an immediate, actionable error.
|
|
41
|
+
const LIST_MEMORIES_MAX_LIMIT = 200;
|
|
42
|
+
// Valid enum values for the explicit write knobs (mirrors the Python
|
|
43
|
+
// package's flair#1234/#1238 validation).
|
|
44
|
+
const VALID_DURABILITIES = new Set(["permanent", "persistent", "standard", "ephemeral"]);
|
|
45
|
+
const VALID_VISIBILITIES = new Set(["private", "shared"]);
|
|
17
46
|
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
18
47
|
function isLocalhost(hostname) {
|
|
19
48
|
return LOCALHOST_HOSTS.has(hostname);
|
|
@@ -42,14 +71,142 @@ function extractText(content) {
|
|
|
42
71
|
.filter(Boolean)
|
|
43
72
|
.join(" ");
|
|
44
73
|
}
|
|
74
|
+
function isPlainObjectLike(value) {
|
|
75
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
76
|
+
}
|
|
77
|
+
// ─── customMetadata / subject (flair#1332 — mirrors the Python package) ─────
|
|
78
|
+
/**
|
|
79
|
+
* Structural caps on customMetadata, checked BEFORE serialization.
|
|
80
|
+
*
|
|
81
|
+
* Rejects nesting deeper than METADATA_MAX_DEPTH levels or more than
|
|
82
|
+
* METADATA_MAX_KEYS total object keys (counted across every level) with an
|
|
83
|
+
* Error. Iterative traversal — no recursion, so adversarial nesting can't
|
|
84
|
+
* blow the stack; a self-referencing structure terminates via the depth cap
|
|
85
|
+
* (each revisit is pushed one level deeper), so a circular blob is rejected
|
|
86
|
+
* here and never reaches JSON.stringify.
|
|
87
|
+
*/
|
|
88
|
+
function validateMetadataShape(customMetadata) {
|
|
89
|
+
const stack = [[customMetadata, 1]];
|
|
90
|
+
let keyCount = 0;
|
|
91
|
+
while (stack.length > 0) {
|
|
92
|
+
const [node, depth] = stack.pop();
|
|
93
|
+
if (depth > METADATA_MAX_DEPTH) {
|
|
94
|
+
throw new Error(`customMetadata nesting exceeds ${METADATA_MAX_DEPTH} levels — ` +
|
|
95
|
+
"flatten the structure, or store a reference to the data instead " +
|
|
96
|
+
"of embedding it");
|
|
97
|
+
}
|
|
98
|
+
let children;
|
|
99
|
+
if (Array.isArray(node)) {
|
|
100
|
+
children = node;
|
|
101
|
+
}
|
|
102
|
+
else if (isPlainObjectLike(node)) {
|
|
103
|
+
const keys = Object.keys(node);
|
|
104
|
+
keyCount += keys.length;
|
|
105
|
+
if (keyCount > METADATA_MAX_KEYS) {
|
|
106
|
+
throw new Error(`customMetadata carries more than ${METADATA_MAX_KEYS} keys ` +
|
|
107
|
+
"in total — split the data across memories, or store a " +
|
|
108
|
+
"reference to it instead");
|
|
109
|
+
}
|
|
110
|
+
children = keys.map((k) => node[k]);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
for (const child of children) {
|
|
116
|
+
if (Array.isArray(child) || isPlainObjectLike(child)) {
|
|
117
|
+
stack.push([child, depth + 1]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Serialize customMetadata to the JSON string stored in Memory.metadata.
|
|
124
|
+
*
|
|
125
|
+
* Store-and-return contract (flair#1202): the blob is opaque to the server —
|
|
126
|
+
* stored verbatim, returned verbatim, no key in it influences any server
|
|
127
|
+
* decision.
|
|
128
|
+
*
|
|
129
|
+
* - Structural caps (depth/key-count) and the serialized 64KB cap REJECT
|
|
130
|
+
* with an Error — never truncate (truncation corrupts the round-trip
|
|
131
|
+
* guarantee; Sherlock hard requirement, mirrored from the Python package).
|
|
132
|
+
* - A non-serializable VALUE skips that key with a warning naming the
|
|
133
|
+
* session key — one bad value must not discard the caller's whole blob.
|
|
134
|
+
* (In JS "non-serializable" means JSON.stringify yields undefined —
|
|
135
|
+
* functions, symbols, bare undefined — or throws: BigInt. Object keys are
|
|
136
|
+
* always strings in JS, so the Python non-string-key skip has no analogue.)
|
|
137
|
+
*
|
|
138
|
+
* Returns null when there is nothing to store (no metadata, or every key
|
|
139
|
+
* was skipped).
|
|
140
|
+
*/
|
|
141
|
+
function serializeCustomMetadata(customMetadata, contextKey) {
|
|
142
|
+
if (!customMetadata || Object.keys(customMetadata).length === 0)
|
|
143
|
+
return null;
|
|
144
|
+
validateMetadataShape(customMetadata);
|
|
145
|
+
const clean = {};
|
|
146
|
+
for (const [key, value] of Object.entries(customMetadata)) {
|
|
147
|
+
let probe;
|
|
148
|
+
try {
|
|
149
|
+
probe = JSON.stringify(value);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
probe = undefined;
|
|
153
|
+
}
|
|
154
|
+
if (probe === undefined) {
|
|
155
|
+
console.warn(`[adk-flair] customMetadata key "${key}" skipped — value is not ` +
|
|
156
|
+
`JSON-serializable (session=${contextKey})`);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
clean[key] = value;
|
|
160
|
+
}
|
|
161
|
+
if (Object.keys(clean).length === 0)
|
|
162
|
+
return null;
|
|
163
|
+
const serialized = JSON.stringify(clean);
|
|
164
|
+
const size = Buffer.byteLength(serialized, "utf8");
|
|
165
|
+
if (size > METADATA_MAX_BYTES) {
|
|
166
|
+
throw new Error(`customMetadata serializes to ${size} bytes, over the ` +
|
|
167
|
+
`${METADATA_MAX_BYTES}-byte cap — store large payloads elsewhere ` +
|
|
168
|
+
"and keep a reference here. Rejected rather than truncated: a " +
|
|
169
|
+
"truncated blob would silently corrupt the store-and-return " +
|
|
170
|
+
"round-trip guarantee.");
|
|
171
|
+
}
|
|
172
|
+
return serialized;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Resolve the top-level `subject` column value (flair#1332).
|
|
176
|
+
*
|
|
177
|
+
* Precedence: an explicit subject option is authoritative over
|
|
178
|
+
* customMetadata["subject"] when both are supplied. NEVER auto-extracted
|
|
179
|
+
* from content. Rejects non-string or over-cap (512 chars) values with an
|
|
180
|
+
* Error — subject is a short human-readable title promoted to an indexed
|
|
181
|
+
* column, not a content field. Returns null when neither source supplies
|
|
182
|
+
* one (empty strings resolve to null — nothing to promote).
|
|
183
|
+
*/
|
|
184
|
+
function resolveSubject(explicitSubject, customMetadata) {
|
|
185
|
+
let subject = explicitSubject;
|
|
186
|
+
let source = "subject option";
|
|
187
|
+
if ((subject === undefined || subject === null) && customMetadata !== undefined) {
|
|
188
|
+
subject = customMetadata["subject"];
|
|
189
|
+
source = 'customMetadata["subject"]';
|
|
190
|
+
}
|
|
191
|
+
if (subject === undefined || subject === null)
|
|
192
|
+
return null;
|
|
193
|
+
if (typeof subject !== "string") {
|
|
194
|
+
throw new Error(`${source} must be a string (got: ${typeof subject}) — ` +
|
|
195
|
+
"subject is promoted to the record's top-level subject column");
|
|
196
|
+
}
|
|
197
|
+
if (subject.length > SUBJECT_MAX_CHARS) {
|
|
198
|
+
throw new Error(`${source} is ${subject.length} characters, over the ` +
|
|
199
|
+
`${SUBJECT_MAX_CHARS}-char cap — subject is a short ` +
|
|
200
|
+
"human-readable title; put longer text in content or customMetadata");
|
|
201
|
+
}
|
|
202
|
+
return subject || null;
|
|
203
|
+
}
|
|
45
204
|
// ─── FlairMemoryService ─────────────────────────────────────────────────────
|
|
46
205
|
export class FlairMemoryService {
|
|
47
206
|
_url;
|
|
48
207
|
_agentId;
|
|
49
208
|
_privateKey;
|
|
50
209
|
_timeoutMs;
|
|
51
|
-
/** Per-session state for custom_metadata warn-once (Python parity). */
|
|
52
|
-
_warnedSessions = new Set();
|
|
53
210
|
/**
|
|
54
211
|
* @param url - Flair HTTP URL (default: FLAIR_URL env or http://localhost:19926)
|
|
55
212
|
* @param agentId - Flair agent ID (default: FLAIR_AGENT_ID env)
|
|
@@ -126,6 +283,12 @@ export class FlairMemoryService {
|
|
|
126
283
|
q: query,
|
|
127
284
|
tag,
|
|
128
285
|
limit: 20,
|
|
286
|
+
// flair#1332: opt into the `metadata` blob in each hit.
|
|
287
|
+
// /SemanticSearch's default projection deliberately omits it (other
|
|
288
|
+
// consumers must not pay result-size for a blob they never read);
|
|
289
|
+
// this flag widens the projection for THIS request only. `subject`
|
|
290
|
+
// is in the default projection.
|
|
291
|
+
includeMetadata: true,
|
|
129
292
|
});
|
|
130
293
|
const start = Date.now();
|
|
131
294
|
let phase = "connect";
|
|
@@ -152,22 +315,17 @@ export class FlairMemoryService {
|
|
|
152
315
|
return { memories: [] };
|
|
153
316
|
}
|
|
154
317
|
const data = (await resp.json());
|
|
155
|
-
const results = data.results
|
|
318
|
+
const results = Array.isArray(data.results) ? data.results : [];
|
|
156
319
|
const memories = [];
|
|
157
320
|
for (const hit of results) {
|
|
158
|
-
|
|
159
|
-
|
|
321
|
+
if (!isPlainObjectLike(hit))
|
|
322
|
+
continue;
|
|
323
|
+
// Per-hit tag re-verification: drop hits missing the compound tag.
|
|
324
|
+
// Client-side analogue of Flair's isAllowed defense-in-depth.
|
|
325
|
+
const hitTags = Array.isArray(hit["tags"]) ? hit["tags"] : [];
|
|
160
326
|
if (!hitTags.includes(tag))
|
|
161
327
|
continue;
|
|
162
|
-
|
|
163
|
-
role: "user",
|
|
164
|
-
parts: [{ text: hit.content ?? "" }],
|
|
165
|
-
};
|
|
166
|
-
memories.push({
|
|
167
|
-
content,
|
|
168
|
-
author: hit.author,
|
|
169
|
-
timestamp: hit.timestamp,
|
|
170
|
-
});
|
|
328
|
+
memories.push(this._hitToMemoryEntry(hit));
|
|
171
329
|
}
|
|
172
330
|
return { memories };
|
|
173
331
|
}
|
|
@@ -188,24 +346,27 @@ export class FlairMemoryService {
|
|
|
188
346
|
* Add events to memory incrementally (the quickstart's after_agent_callback path).
|
|
189
347
|
* Not called by ADK — use in after_agent_callback or directly.
|
|
190
348
|
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
349
|
+
* customMetadata (flair#1332) is stored on every record this call writes,
|
|
350
|
+
* as an opaque JSON blob on the Memory record's `metadata` field, and
|
|
351
|
+
* round-trips back on `FlairMemoryEntry.customMetadata` from searchMemory /
|
|
352
|
+
* listMemories. Store-and-return only — no key in it has any server-side
|
|
353
|
+
* effect. Caps (Error before any write): 64KB serialized, nesting depth
|
|
354
|
+
* <= 16, <= 512 total keys. customMetadata["subject"] (a string) is
|
|
355
|
+
* additionally promoted to the record's top-level `subject` column
|
|
356
|
+
* (<= 512 chars).
|
|
193
357
|
*/
|
|
194
358
|
async addEventsToMemory(appName, userId, events, sessionId, customMetadata) {
|
|
195
|
-
if (!events || events.length === 0)
|
|
196
|
-
return;
|
|
197
|
-
// custom_metadata warn-once per session (Python parity)
|
|
198
|
-
if (customMetadata) {
|
|
199
|
-
const sessionKey = `${appName}:${userId}:${sessionId}`;
|
|
200
|
-
if (!this._warnedSessions.has(sessionKey)) {
|
|
201
|
-
this._warnedSessions.add(sessionKey);
|
|
202
|
-
console.warn("adk-flair: custom_metadata ignored — adk-flair does not " +
|
|
203
|
-
`support custom_metadata keys (session=${sessionKey})`);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
359
|
const tag = compoundTag(appName, userId);
|
|
360
|
+
// customMetadata → opaque JSON blob + optional promoted subject
|
|
361
|
+
// (flair#1332). Validated/serialized ONCE, before any write — a cap
|
|
362
|
+
// violation throws here and zero events are written, never a partial
|
|
363
|
+
// batch with silently-dropped metadata.
|
|
364
|
+
const sessionKey = `${appName}:${userId}:${sessionId}`;
|
|
365
|
+
const metadataJson = serializeCustomMetadata(customMetadata, sessionKey);
|
|
366
|
+
const subjectValue = resolveSubject(undefined, customMetadata);
|
|
207
367
|
let written = 0;
|
|
208
|
-
|
|
368
|
+
const eventList = events ?? [];
|
|
369
|
+
for (const event of eventList) {
|
|
209
370
|
const text = extractText(event.content);
|
|
210
371
|
if (!text)
|
|
211
372
|
continue;
|
|
@@ -219,6 +380,10 @@ export class FlairMemoryService {
|
|
|
219
380
|
tags: [tag],
|
|
220
381
|
createdAt: epochMsToIso(event.timestamp),
|
|
221
382
|
};
|
|
383
|
+
if (metadataJson !== null)
|
|
384
|
+
body["metadata"] = metadataJson;
|
|
385
|
+
if (subjectValue !== null)
|
|
386
|
+
body["subject"] = subjectValue;
|
|
222
387
|
try {
|
|
223
388
|
await this._writeRecord(recordId, body);
|
|
224
389
|
written++;
|
|
@@ -226,7 +391,7 @@ export class FlairMemoryService {
|
|
|
226
391
|
catch (err) {
|
|
227
392
|
const msg = err instanceof Error ? err.message : String(err);
|
|
228
393
|
console.warn(`[adk-flair] write failed for session ${sessionId} event ${event.id} ` +
|
|
229
|
-
`(written=${written}/${
|
|
394
|
+
`(written=${written}/${eventList.length}): ${msg}`);
|
|
230
395
|
}
|
|
231
396
|
}
|
|
232
397
|
if (written === 0)
|
|
@@ -236,39 +401,72 @@ export class FlairMemoryService {
|
|
|
236
401
|
* Add memory entries directly.
|
|
237
402
|
* Not called by ADK — use for direct memory writes.
|
|
238
403
|
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
404
|
+
* customMetadata (flair#1332) is stored on every record this call writes,
|
|
405
|
+
* as an opaque JSON blob on the Memory record's `metadata` field, and
|
|
406
|
+
* round-trips back on `FlairMemoryEntry.customMetadata` from searchMemory /
|
|
407
|
+
* listMemories. Store-and-return only (the ADK contract, flair#1202): no
|
|
408
|
+
* key inside the blob has ANY server-side effect — {"visibility":"shared"}
|
|
409
|
+
* in here does not share the memory (use the explicit `visibility` option
|
|
410
|
+
* for that). Caps (Error before any write; reject, never truncate): 64KB
|
|
411
|
+
* serialized, nesting depth <= 16, <= 512 total keys. Non-JSON-serializable
|
|
412
|
+
* values skip that key with a warning.
|
|
413
|
+
*
|
|
414
|
+
* opts.subject (flair#1332, Flair-specific extension): short human-readable
|
|
415
|
+
* title promoted to the record's top-level indexed `subject` column.
|
|
416
|
+
* Sourced from this option or customMetadata["subject"]; the explicit
|
|
417
|
+
* option is authoritative when both are present. <= 512 chars (Error
|
|
418
|
+
* beyond). Never auto-extracted from content.
|
|
419
|
+
*
|
|
420
|
+
* opts.durability / opts.visibility: trust-anchor opt-ins (Python-parity
|
|
421
|
+
* explicit knobs), validated against the schema enums. Omitted durability →
|
|
422
|
+
* "standard"; omitted visibility → no key in the body (server default).
|
|
423
|
+
*
|
|
424
|
+
* Record ids mirror the Python package: `entry.id` when the caller supplies
|
|
425
|
+
* one (FlairMemoryEntry input), else the first 32 hex chars of the content's
|
|
426
|
+
* SHA-256 — deterministic, so re-adding identical content replaces rather
|
|
427
|
+
* than duplicates.
|
|
241
428
|
*/
|
|
242
|
-
async addMemory(appName, userId, memories, customMetadata) {
|
|
243
|
-
if (!memories || memories.length === 0)
|
|
244
|
-
return;
|
|
245
|
-
// custom_metadata warn-once (Python parity)
|
|
246
|
-
if (customMetadata) {
|
|
247
|
-
const sessionKey = `${appName}:${userId}:direct`;
|
|
248
|
-
if (!this._warnedSessions.has(sessionKey)) {
|
|
249
|
-
this._warnedSessions.add(sessionKey);
|
|
250
|
-
console.warn("adk-flair: custom_metadata ignored — adk-flair does not " +
|
|
251
|
-
"support custom_metadata keys");
|
|
252
|
-
}
|
|
253
|
-
}
|
|
429
|
+
async addMemory(appName, userId, memories, customMetadata, opts) {
|
|
254
430
|
const tag = compoundTag(appName, userId);
|
|
431
|
+
// Validate explicit durability / visibility (mirrors Python flair#1238).
|
|
432
|
+
if (opts?.durability !== undefined && !VALID_DURABILITIES.has(opts.durability)) {
|
|
433
|
+
throw new Error(`durability must be one of ${[...VALID_DURABILITIES].sort().join(", ")} ` +
|
|
434
|
+
`(got: ${JSON.stringify(opts.durability)})`);
|
|
435
|
+
}
|
|
436
|
+
if (opts?.visibility !== undefined && !VALID_VISIBILITIES.has(opts.visibility)) {
|
|
437
|
+
throw new Error(`visibility must be one of ${[...VALID_VISIBILITIES].sort().join(", ")} ` +
|
|
438
|
+
`(got: ${JSON.stringify(opts.visibility)})`);
|
|
439
|
+
}
|
|
440
|
+
// customMetadata → opaque JSON blob + optional promoted subject
|
|
441
|
+
// (flair#1332). Validated/serialized ONCE, before any write — a cap
|
|
442
|
+
// violation throws here and zero records are written.
|
|
443
|
+
const metadataJson = serializeCustomMetadata(customMetadata, `${appName}:${userId}:direct`);
|
|
444
|
+
const subjectValue = resolveSubject(opts?.subject, customMetadata);
|
|
255
445
|
let written = 0;
|
|
256
|
-
|
|
446
|
+
const memoryList = memories ?? [];
|
|
447
|
+
for (const mem of memoryList) {
|
|
257
448
|
const text = extractText(mem.content);
|
|
258
449
|
if (!text)
|
|
259
450
|
continue;
|
|
260
|
-
const recordId =
|
|
451
|
+
const recordId = mem.id ??
|
|
452
|
+
crypto.createHash("sha256").update(text, "utf8").digest("hex").slice(0, 32);
|
|
261
453
|
const body = {
|
|
262
454
|
id: recordId,
|
|
263
455
|
agentId: this._agentId,
|
|
264
456
|
content: text,
|
|
265
457
|
type: "session",
|
|
266
|
-
durability: "standard",
|
|
458
|
+
durability: opts?.durability ?? "standard",
|
|
267
459
|
tags: [tag],
|
|
268
|
-
createdAt: mem.timestamp
|
|
460
|
+
createdAt: mem.timestamp || new Date().toISOString(),
|
|
269
461
|
};
|
|
462
|
+
if (opts?.visibility !== undefined)
|
|
463
|
+
body["visibility"] = opts.visibility;
|
|
464
|
+
if (metadataJson !== null)
|
|
465
|
+
body["metadata"] = metadataJson;
|
|
466
|
+
if (subjectValue !== null)
|
|
467
|
+
body["subject"] = subjectValue;
|
|
270
468
|
if (mem.author) {
|
|
271
|
-
body
|
|
469
|
+
body["author"] = mem.author;
|
|
272
470
|
}
|
|
273
471
|
try {
|
|
274
472
|
await this._writeRecord(recordId, body);
|
|
@@ -277,28 +475,196 @@ export class FlairMemoryService {
|
|
|
277
475
|
catch (err) {
|
|
278
476
|
const msg = err instanceof Error ? err.message : String(err);
|
|
279
477
|
console.warn(`[adk-flair] direct memory write failed for id ${recordId} ` +
|
|
280
|
-
`(written=${written}/${
|
|
478
|
+
`(written=${written}/${memoryList.length}): ${msg}`);
|
|
281
479
|
}
|
|
282
480
|
}
|
|
283
481
|
if (written === 0)
|
|
284
482
|
return;
|
|
285
483
|
}
|
|
286
|
-
// ───
|
|
484
|
+
// ─── listMemories (flair#1333 — Flair-specific extension) ─────────────────
|
|
287
485
|
/**
|
|
288
|
-
*
|
|
486
|
+
* List recent memories for an app+user, newest first.
|
|
289
487
|
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
488
|
+
* Flair-specific extension — NOT part of ADK's BaseMemoryService (which
|
|
489
|
+
* specifies only searchMemory). Useful for memory review UIs, dashboards,
|
|
490
|
+
* and agent contextual browsing where there is no query to search with.
|
|
491
|
+
*
|
|
492
|
+
* Scope: the same compound tag (adk:<app>:<user>) searchMemory uses, AND
|
|
493
|
+
* agentId === this service's agent identity — both pushed down as
|
|
494
|
+
* server-side query conditions and re-verified client-side on every
|
|
495
|
+
* returned row (defense in depth).
|
|
496
|
+
*
|
|
497
|
+
* Pagination: `offset` is POSITIONAL over a point-in-time snapshot ordered
|
|
498
|
+
* by createdAt descending — not a live cursor. Memories written between
|
|
499
|
+
* two pages shift positions, so a record can appear twice or be skipped
|
|
500
|
+
* across page boundaries. For a consistent view, take one page, or dedupe
|
|
501
|
+
* by id across pages.
|
|
502
|
+
*
|
|
503
|
+
* Throws on invalid arguments, and — unlike searchMemory (whose
|
|
504
|
+
* empty-on-error contract is ADK's) — PROPAGATES transport and HTTP
|
|
505
|
+
* failures: a browsing UI must be able to tell "no memories" from
|
|
506
|
+
* "Flair is down".
|
|
293
507
|
*/
|
|
294
|
-
async
|
|
295
|
-
const
|
|
296
|
-
const
|
|
508
|
+
async listMemories(appName, userId, opts) {
|
|
509
|
+
const limit = opts?.limit ?? 50;
|
|
510
|
+
const offset = opts?.offset ?? 0;
|
|
511
|
+
if (!appName) {
|
|
512
|
+
throw new Error("appName is required");
|
|
513
|
+
}
|
|
514
|
+
if (!userId) {
|
|
515
|
+
throw new Error("userId is required — listMemories never lists unscoped");
|
|
516
|
+
}
|
|
517
|
+
if (typeof limit !== "number" || !Number.isInteger(limit) || limit < 1) {
|
|
518
|
+
throw new Error(`limit must be a positive integer (got: ${JSON.stringify(limit)})`);
|
|
519
|
+
}
|
|
520
|
+
if (limit > LIST_MEMORIES_MAX_LIMIT) {
|
|
521
|
+
throw new Error(`limit ${limit} exceeds the hard cap of ${LIST_MEMORIES_MAX_LIMIT} ` +
|
|
522
|
+
"— page with offset instead");
|
|
523
|
+
}
|
|
524
|
+
if (typeof offset !== "number" || !Number.isInteger(offset) || offset < 0) {
|
|
525
|
+
throw new Error(`offset must be a non-negative integer (got: ${JSON.stringify(offset)})`);
|
|
526
|
+
}
|
|
527
|
+
const tag = compoundTag(appName, userId);
|
|
528
|
+
// Harper REST collection query (signed like every other request — the
|
|
529
|
+
// signature covers path+query). The tag value is percent-encoded
|
|
530
|
+
// WHOLESALE: compound tags legitimately contain literal %XX escapes from
|
|
531
|
+
// sanitizeTagSegment, which must survive the server's URL decode.
|
|
532
|
+
// limit(start,end) is Harper's offset window: start=offset,
|
|
533
|
+
// end=offset+limit.
|
|
534
|
+
const path = `/Memory/?tags=${encodeURIComponent(tag)}` +
|
|
535
|
+
`&agentId=${encodeURIComponent(this._agentId)}` +
|
|
536
|
+
`&select(id,agentId,content,metadata,subject,tags,createdAt)` +
|
|
537
|
+
`&sort(-createdAt)` +
|
|
538
|
+
`&limit(${offset},${offset + limit})`;
|
|
539
|
+
const authHeader = signRequest(this._privateKey, this._agentId, "GET", path);
|
|
297
540
|
const controller = new AbortController();
|
|
298
541
|
const timeoutId = setTimeout(() => controller.abort(), this._timeoutMs);
|
|
542
|
+
let rows;
|
|
299
543
|
try {
|
|
300
544
|
const resp = await fetch(`${this._url}${path}`, {
|
|
301
|
-
method: "
|
|
545
|
+
method: "GET",
|
|
546
|
+
headers: { "Authorization": authHeader },
|
|
547
|
+
signal: controller.signal,
|
|
548
|
+
});
|
|
549
|
+
if (!resp.ok) {
|
|
550
|
+
const text = await resp.text().catch(() => "");
|
|
551
|
+
throw new Error(`Flair GET /Memory/ → HTTP ${resp.status}` +
|
|
552
|
+
`${text ? `: ${text.slice(0, 200)}` : ""}`);
|
|
553
|
+
}
|
|
554
|
+
rows = await resp.json();
|
|
555
|
+
}
|
|
556
|
+
finally {
|
|
557
|
+
clearTimeout(timeoutId);
|
|
558
|
+
}
|
|
559
|
+
if (!Array.isArray(rows)) {
|
|
560
|
+
return [];
|
|
561
|
+
}
|
|
562
|
+
const entries = [];
|
|
563
|
+
for (const row of rows) {
|
|
564
|
+
if (!isPlainObjectLike(row))
|
|
565
|
+
continue;
|
|
566
|
+
// Defense in depth: re-verify both scope conditions client-side,
|
|
567
|
+
// mirroring searchMemory's tag re-verification.
|
|
568
|
+
const rowTags = Array.isArray(row["tags"]) ? row["tags"] : [];
|
|
569
|
+
if (!rowTags.includes(tag))
|
|
570
|
+
continue;
|
|
571
|
+
if (row["agentId"] !== this._agentId)
|
|
572
|
+
continue;
|
|
573
|
+
entries.push(this._hitToMemoryEntry(row));
|
|
574
|
+
}
|
|
575
|
+
return entries;
|
|
576
|
+
}
|
|
577
|
+
// ─── Hit → MemoryEntry mapping ─────────────────────────────────────────────
|
|
578
|
+
/**
|
|
579
|
+
* Map a Flair Memory record/hit onto a FlairMemoryEntry.
|
|
580
|
+
*
|
|
581
|
+
* author derives from the record's agentId — the writing Flair agent
|
|
582
|
+
* (flair#1332 incidental fix, mirrored: records carry no "author" field,
|
|
583
|
+
* so reading hit.author was always undefined). timestamp derives from the
|
|
584
|
+
* record's createdAt for the same reason.
|
|
585
|
+
*/
|
|
586
|
+
_hitToMemoryEntry(hit) {
|
|
587
|
+
const contentText = typeof hit["content"] === "string" ? hit["content"] : "";
|
|
588
|
+
const customMetadata = this._hitCustomMetadata(hit);
|
|
589
|
+
const subject = hit["subject"];
|
|
590
|
+
const entry = {
|
|
591
|
+
content: {
|
|
592
|
+
role: "model",
|
|
593
|
+
parts: [{ text: contentText }],
|
|
594
|
+
},
|
|
595
|
+
customMetadata,
|
|
596
|
+
};
|
|
597
|
+
if (typeof hit["id"] === "string")
|
|
598
|
+
entry.id = hit["id"];
|
|
599
|
+
if (typeof hit["agentId"] === "string")
|
|
600
|
+
entry.author = hit["agentId"];
|
|
601
|
+
if (typeof hit["createdAt"] === "string")
|
|
602
|
+
entry.timestamp = hit["createdAt"];
|
|
603
|
+
if (typeof subject === "string" && subject)
|
|
604
|
+
entry.subject = subject;
|
|
605
|
+
return entry;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Rebuild FlairMemoryEntry.customMetadata from a record's stored fields.
|
|
609
|
+
*
|
|
610
|
+
* - `metadata` (the opaque JSON blob) parses back to an object. FAIL-SOFT:
|
|
611
|
+
* malformed JSON (or JSON that isn't an object) yields {} plus a warning
|
|
612
|
+
* naming the record id — a corrupt blob on one record must never take
|
|
613
|
+
* the whole read path down.
|
|
614
|
+
* - A top-level `subject` column is surfaced as customMetadata["subject"].
|
|
615
|
+
* The COLUMN is authoritative (flair#1332 ruling): when the blob carries
|
|
616
|
+
* a divergent "subject" key, the column value overwrites it in the
|
|
617
|
+
* returned object. This keeps the customMetadata return shape identical
|
|
618
|
+
* to the Python package — a subject written via the explicit option
|
|
619
|
+
* (never in the blob) still round-trips through customMetadata.
|
|
620
|
+
*/
|
|
621
|
+
_hitCustomMetadata(hit) {
|
|
622
|
+
let parsed = {};
|
|
623
|
+
const raw = hit["metadata"];
|
|
624
|
+
if (raw) {
|
|
625
|
+
let loaded;
|
|
626
|
+
let malformed = false;
|
|
627
|
+
if (typeof raw === "string") {
|
|
628
|
+
try {
|
|
629
|
+
loaded = JSON.parse(raw);
|
|
630
|
+
}
|
|
631
|
+
catch {
|
|
632
|
+
malformed = true;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
malformed = true;
|
|
637
|
+
}
|
|
638
|
+
if (malformed) {
|
|
639
|
+
console.warn(`[adk-flair] malformed metadata JSON on record ${String(hit["id"])} — ` +
|
|
640
|
+
"returning empty customMetadata for it");
|
|
641
|
+
}
|
|
642
|
+
else if (isPlainObjectLike(loaded)) {
|
|
643
|
+
parsed = loaded;
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
console.warn(`[adk-flair] metadata on record ${String(hit["id"])} is JSON but not ` +
|
|
647
|
+
"an object — returning empty customMetadata for it");
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
const subject = hit["subject"];
|
|
651
|
+
if (typeof subject === "string" && subject) {
|
|
652
|
+
parsed["subject"] = subject;
|
|
653
|
+
}
|
|
654
|
+
return parsed;
|
|
655
|
+
}
|
|
656
|
+
// ─── Internal ─────────────────────────────────────────────────────────────
|
|
657
|
+
/**
|
|
658
|
+
* Send one signed JSON-bodied request. The signing payload covers the full
|
|
659
|
+
* path (METHOD:pathname), so the path passed here is the one signed.
|
|
660
|
+
*/
|
|
661
|
+
async _sendJson(method, path, body) {
|
|
662
|
+
const authHeader = signRequest(this._privateKey, this._agentId, method, path);
|
|
663
|
+
const controller = new AbortController();
|
|
664
|
+
const timeoutId = setTimeout(() => controller.abort(), this._timeoutMs);
|
|
665
|
+
try {
|
|
666
|
+
return await fetch(`${this._url}${path}`, {
|
|
667
|
+
method,
|
|
302
668
|
headers: {
|
|
303
669
|
"Authorization": authHeader,
|
|
304
670
|
"Content-Type": "application/json",
|
|
@@ -306,15 +672,41 @@ export class FlairMemoryService {
|
|
|
306
672
|
body: JSON.stringify(body),
|
|
307
673
|
signal: controller.signal,
|
|
308
674
|
});
|
|
309
|
-
if (!resp.ok) {
|
|
310
|
-
const text = await resp.text().catch(() => "");
|
|
311
|
-
throw new Error(`HTTP ${resp.status}${text ? `: ${text.slice(0, 200)}` : ""}`);
|
|
312
|
-
}
|
|
313
675
|
}
|
|
314
676
|
finally {
|
|
315
677
|
clearTimeout(timeoutId);
|
|
316
678
|
}
|
|
317
679
|
}
|
|
680
|
+
/**
|
|
681
|
+
* Create-or-replace one Memory record.
|
|
682
|
+
*
|
|
683
|
+
* Creates via `POST /Memory/` — Harper's collection create verb — with the
|
|
684
|
+
* id in the body. The previous shape, `PUT /Memory/{id}`, is update-only on
|
|
685
|
+
* some Harper deployments and 404s when the record does not exist yet
|
|
686
|
+
* (flair#1336, observed on hosted Harper Fabric; not reproducible on stock
|
|
687
|
+
* Harper 5.2.x, where PUT upserts). Mirrors the Python package's #1339 fix.
|
|
688
|
+
*
|
|
689
|
+
* A 409 from POST means the record already exists — re-ingestion of a
|
|
690
|
+
* deterministic id (addSessionToMemory re-saves a growing session's earlier
|
|
691
|
+
* events every time) or a caller-supplied id being rewritten. Fall back to
|
|
692
|
+
* `PUT /Memory/{id}` for exactly that case, preserving the pre-#1336
|
|
693
|
+
* replace/refresh semantics for existing rows. Any other error propagates
|
|
694
|
+
* unchanged (the write-path warning logs carry the real HTTP status).
|
|
695
|
+
*/
|
|
696
|
+
async _writeRecord(recordId, body) {
|
|
697
|
+
const resp = await this._sendJson("POST", "/Memory/", body);
|
|
698
|
+
if (resp.ok)
|
|
699
|
+
return;
|
|
700
|
+
if (resp.status !== 409) {
|
|
701
|
+
const text = await resp.text().catch(() => "");
|
|
702
|
+
throw new Error(`HTTP ${resp.status}${text ? `: ${text.slice(0, 200)}` : ""}`);
|
|
703
|
+
}
|
|
704
|
+
const putResp = await this._sendJson("PUT", `/Memory/${recordId}`, body);
|
|
705
|
+
if (!putResp.ok) {
|
|
706
|
+
const text = await putResp.text().catch(() => "");
|
|
707
|
+
throw new Error(`HTTP ${putResp.status}${text ? `: ${text.slice(0, 200)}` : ""}`);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
318
710
|
/**
|
|
319
711
|
* Close the service. No-op for the HTTP-based implementation;
|
|
320
712
|
* provided for API compatibility with the Python package.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory_service.js","sourceRoot":"","sources":["../src/memory_service.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memory_service.js","sourceRoot":"","sources":["../src/memory_service.ts"],"names":[],"mappings":"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"}
|