@tpsdev-ai/adk-flair 0.48.0 → 0.49.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 CHANGED
@@ -95,8 +95,9 @@ All values can also be passed directly to the constructor.
95
95
 
96
96
  Each ADK app authenticates as **one Flair agent** (its service identity).
97
97
  Per-user isolation is enforced by a **compound tag** — `adk:<app_name>:<user_id>`
98
- — attached to every record and filtered on every search. Colons in `app_name`
99
- or `user_id` are replaced with underscores to prevent delimiter breakage.
98
+ — attached to every record and filtered on every search. Reserved characters
99
+ (`%`, `:`, `_`) in `app_name` or `user_id` are percent-encoded so distinct
100
+ identities never collide and the `:` delimiter stays unambiguous.
100
101
 
101
102
  ### Search path
102
103
 
@@ -107,7 +108,13 @@ or `user_id` are replaced with underscores to prevent delimiter breakage.
107
108
 
108
109
  ### Write path
109
110
 
110
- - Deterministic record IDs: `app:user:session:eventId` — re-ingestion upserts
111
+ - Deterministic record IDs: `app:user:session:eventId` — re-ingestion upserts.
112
+ Direct `addMemory()` writes use the entry's `id` when supplied, else the
113
+ first 32 hex chars of the content's SHA-256 (re-adds replace, not duplicate)
114
+ - Creates ride `POST /Memory/` (the create verb) with the id in the body; a
115
+ `409` (record already exists) falls back to `PUT /Memory/{id}`, preserving
116
+ replace semantics — a PUT-shaped create 404s on Harper deployments where
117
+ PUT is update-only (flair#1336)
111
118
  - Write failures log a structured warning (session id, event count, HTTP status)
112
119
  - No-text events are filtered (Vertex parity)
113
120
 
@@ -140,8 +147,49 @@ Implements `BaseMemoryService` from `@google/adk`.
140
147
 
141
148
  #### Extra methods (Vertex parity, not called by ADK)
142
149
 
143
- - **`addEventsToMemory(appName, userId, events, sessionId)`** — incremental per-turn writes
144
- - **`addMemory(appName, userId, memories)`** — direct memory writes
150
+ - **`addEventsToMemory(appName, userId, events, sessionId, customMetadata?)`** — incremental per-turn writes
151
+ - **`addMemory(appName, userId, memories, customMetadata?, opts?)`** — direct
152
+ memory writes. `opts`: `{ subject?, durability?, visibility? }`
153
+ - **`listMemories(appName, userId, { limit?, offset? })`** — Flair-specific
154
+ browsing extension (NOT part of `BaseMemoryService`)
155
+
156
+ ### Custom metadata & subject
157
+
158
+ `customMetadata` (an arbitrary JSON-serializable object) is stored on every
159
+ record a write call produces, as an opaque blob on the record's `metadata`
160
+ field, and round-trips back on `FlairMemoryEntry.customMetadata` from
161
+ `searchMemory` / `listMemories`.
162
+
163
+ **Store-and-return only** — ADK's contract: no key inside the blob has ANY
164
+ server-side effect. `{"visibility": "shared"}` in the blob does **not** share
165
+ the memory; use the explicit `opts.visibility` for that. Caps (throw before
166
+ any write; reject, never truncate): 64KB serialized, nesting depth ≤ 16,
167
+ ≤ 512 total keys. Non-JSON-serializable values skip that key with a warning.
168
+
169
+ `subject` is a short human-readable title (≤ 512 chars) promoted to the
170
+ record's top-level indexed `subject` column — supplied via `opts.subject` or
171
+ `customMetadata.subject` (the explicit option is authoritative when both are
172
+ present), never auto-extracted from content. On read it surfaces both as
173
+ `entry.subject` and `customMetadata["subject"]` (the column is authoritative
174
+ over a divergent blob key; the `customMetadata` channel matches the Python
175
+ package's return shape exactly).
176
+
177
+ Read-path notes: `searchMemory` opts into `/SemanticSearch`'s
178
+ `includeMetadata` projection flag; a malformed stored blob fails soft to `{}`
179
+ with a warning naming the record id (a corrupt blob never takes recall down).
180
+ Returned entries also carry the record `id`, `author` (the writing Flair
181
+ agent id), and `timestamp` (the record's `createdAt`).
182
+
183
+ ### listMemories
184
+
185
+ Lists an app+user's memories newest-first (`createdAt` DESC) with the full
186
+ projection — no query needed. Scope is the compound tag AND the service's
187
+ agent identity, both pushed down server-side and re-verified client-side.
188
+ `limit` is 1..200 — over-cap **rejects** (never silently clamps); `offset` is
189
+ positional over a point-in-time snapshot, not a live cursor. Unlike
190
+ `searchMemory` (whose swallow-to-empty contract is ADK's), transport and HTTP
191
+ failures **propagate** — a browsing UI must be able to tell "no memories"
192
+ from "Flair is down".
145
193
 
146
194
  ## License
147
195
 
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
@@ -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;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.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"}
@@ -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<SearchMemoryResponse>;
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
- * @param customMetadata - If provided, logs a once-per-session warning that
40
- * custom_metadata is not supported by adk-flair (Python parity).
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
- * @param customMetadata - If provided, logs a once-per-session warning that
48
- * custom_metadata is not supported by adk-flair (Python parity).
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[], customMetadata?: Record<string, unknown>): Promise<void>;
147
+ addMemory(appName: string, userId: string, memories: Array<MemoryEntry & {
148
+ id?: string;
149
+ }>, customMetadata?: Record<string, unknown>, opts?: AddMemoryOptions): Promise<void>;
51
150
  /**
52
- * Write a single record to Flair via PUT /Memory/{recordId}.
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
- * The deterministic record ID is embedded in the URL path so the server
55
- * can perform an idempotent upsert. The signing payload covers the full
56
- * path (METHOD:pathname), so the path MUST include the record ID.
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;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAiDzC,qBAAa,kBAAmB,YAAW,iBAAiB;IAC1D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,uEAAuE;IACvE,OAAO,CAAC,eAAe,CAA0B;IAEjD;;;;;OAKG;gBACS,IAAI,CAAC,EAAE;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;IAqCK,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCnD,YAAY,CAChB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,oBAAoB,CAAC;IAmGhC;;;;;;OAMG;IACG,iBAAiB,CACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,KAAK,EAAE,EACf,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC;IAgDhB;;;;;;OAMG;IACG,SAAS,CACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,EAAE,EACvB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC;IAqDhB;;;;;;OAMG;YACW,YAAY;IAqC1B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
1
+ {"version":3,"file":"memory_service.d.ts","sourceRoot":"","sources":["../src/memory_service.ts"],"names":[],"mappings":"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"}
@@ -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
- // Per-hit tag re-verification: drop hits missing the compound tag
159
- const hitTags = hit.tags ?? [];
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
- const content = {
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
- * @param customMetadata - If provided, logs a once-per-session warning that
192
- * custom_metadata is not supported by adk-flair (Python parity).
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
- for (const event of events) {
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}/${events.length}): ${msg}`);
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
- * @param customMetadata - If provided, logs a once-per-session warning that
240
- * custom_metadata is not supported by adk-flair (Python parity).
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
- for (const mem of memories) {
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 = `${appName}:${userId}:direct:${crypto.randomUUID()}`;
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 ?? new Date().toISOString(),
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.author = mem.author;
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}/${memories.length}): ${msg}`);
478
+ `(written=${written}/${memoryList.length}): ${msg}`);
281
479
  }
282
480
  }
283
481
  if (written === 0)
284
482
  return;
285
483
  }
286
- // ─── Internal ─────────────────────────────────────────────────────────────
484
+ // ─── listMemories (flair#1333 — Flair-specific extension) ─────────────────
287
485
  /**
288
- * Write a single record to Flair via PUT /Memory/{recordId}.
486
+ * List recent memories for an app+user, newest first.
289
487
  *
290
- * The deterministic record ID is embedded in the URL path so the server
291
- * can perform an idempotent upsert. The signing payload covers the full
292
- * path (METHOD:pathname), so the path MUST include the record ID.
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 _writeRecord(recordId, body) {
295
- const path = `/Memory/${recordId}`;
296
- const authHeader = signRequest(this._privateKey, this._agentId, "PUT", path);
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: "PUT",
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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpsdev-ai/adk-flair",
3
- "version": "0.48.0",
3
+ "version": "0.49.0",
4
4
  "description": "Flair memory backend for Google ADK — self-hosted, federated, portable agent memory",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",