@tpsdev-ai/flair-client 0.53.0 → 0.54.1

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/dist/client.d.ts CHANGED
@@ -120,22 +120,26 @@ declare class MemoryApi {
120
120
  /**
121
121
  * List recent memories. All filters combine with AND.
122
122
  *
123
- * Uses Harper's `POST /Memory/search_by_conditions` endpoint with an
124
- * explicit conditions array. The Memory.search() override injects the
125
- * agentId scoping condition.
123
+ * Reads go through the supported Harper REST collection GET
124
+ * (`GET /Memory?agentId=…`) the same shape `SoulApi.list()` and the CLI's
125
+ * `flair memory list` use. The previous `POST /Memory/search_by_conditions`
126
+ * shape was never a REST route: Harper's dispatcher maps every POST to
127
+ * `resource.post()` and has no URL-suffix routing, so it answered 405.
126
128
  *
127
- * Note: `order` is applied client-side after retrieval. Harper's
128
- * search_by_conditions does not accept a sort/order field in the body.
129
+ * The server applies the caller's read scope. The remaining filters
130
+ * (subject, tags, type, durability), `order`, and `limit` are applied
131
+ * client-side after retrieval. `type` has to be — it is an undeclared,
132
+ * non-queryable Memory column (see schemas/memory.graphql), so it can never
133
+ * be a server-side condition.
129
134
  */
130
135
  list(opts?: {
131
136
  tags?: string[];
132
137
  limit?: number;
133
138
  type?: MemoryType;
134
139
  durability?: Durability;
135
- /** Filter by subject (entity the memory is about). Indexed; efficient. */
140
+ /** Filter by subject (entity the memory is about). */
136
141
  subject?: string;
137
- /** Chronological ordering applied client-side after retrieval.
138
- * Server-side sort is not available via search_by_conditions. */
142
+ /** Chronological ordering applied client-side after retrieval. */
139
143
  order?: "createdAt-asc" | "createdAt-desc";
140
144
  }): Promise<Memory[]>;
141
145
  /** Delete a memory. */
package/dist/client.js CHANGED
@@ -315,45 +315,48 @@ class MemoryApi {
315
315
  /**
316
316
  * List recent memories. All filters combine with AND.
317
317
  *
318
- * Uses Harper's `POST /Memory/search_by_conditions` endpoint with an
319
- * explicit conditions array. The Memory.search() override injects the
320
- * agentId scoping condition.
318
+ * Reads go through the supported Harper REST collection GET
319
+ * (`GET /Memory?agentId=…`) the same shape `SoulApi.list()` and the CLI's
320
+ * `flair memory list` use. The previous `POST /Memory/search_by_conditions`
321
+ * shape was never a REST route: Harper's dispatcher maps every POST to
322
+ * `resource.post()` and has no URL-suffix routing, so it answered 405.
321
323
  *
322
- * Note: `order` is applied client-side after retrieval. Harper's
323
- * search_by_conditions does not accept a sort/order field in the body.
324
+ * The server applies the caller's read scope. The remaining filters
325
+ * (subject, tags, type, durability), `order`, and `limit` are applied
326
+ * client-side after retrieval. `type` has to be — it is an undeclared,
327
+ * non-queryable Memory column (see schemas/memory.graphql), so it can never
328
+ * be a server-side condition.
324
329
  */
325
330
  async list(opts = {}) {
326
- // Build conditions array agentId is always scoped
327
- const conditions = [
328
- { search_attribute: "agentId", search_type: "equals", search_value: this.client.agentId },
329
- ];
330
- if (opts.subject) {
331
- conditions.push({ search_attribute: "subject", search_type: "equals", search_value: opts.subject });
332
- }
333
- for (const tag of opts.tags ?? []) {
334
- conditions.push({ search_attribute: "tags", search_type: "contains", search_value: tag });
335
- }
336
- if (opts.type) {
337
- conditions.push({ search_attribute: "type", search_type: "equals", search_value: opts.type });
338
- }
339
- if (opts.durability) {
340
- conditions.push({ search_attribute: "durability", search_type: "equals", search_value: opts.durability });
341
- }
342
- const body = {
343
- operator: "and",
344
- conditions,
345
- get_attributes: ["*"],
346
- };
347
- if (opts.limit)
348
- body.limit = opts.limit;
349
- const result = await this.client.request("POST", "/Memory/search_by_conditions", body);
350
- // search_by_conditions returns either an array or { results: [...] }
351
- const memories = Array.isArray(result) ? result : (result?.results ?? []);
352
- // Client-side sort (Harper's search_by_conditions does not accept sort in body)
331
+ const params = new URLSearchParams({ agentId: this.client.agentId });
332
+ const result = await this.client.request("GET", `/Memory?${params}`);
333
+ // Harper returns a plain array; tolerate a { results: [...] } wrapper too.
334
+ const rows = Array.isArray(result) ? result : (result?.results ?? []);
335
+ const memories = rows.filter((memory) => {
336
+ // Keep the agent-scoped contract: the server's read scope also admits
337
+ // shared memories granted to this agent, but list() is an own-memory
338
+ // listing (the old explicit agentId condition had the same effect).
339
+ if (memory.agentId !== this.client.agentId)
340
+ return false;
341
+ if (opts.subject !== undefined && memory.subject !== opts.subject)
342
+ return false;
343
+ if (opts.type !== undefined && memory.type !== opts.type)
344
+ return false;
345
+ if (opts.durability !== undefined && memory.durability !== opts.durability)
346
+ return false;
347
+ for (const tag of opts.tags ?? []) {
348
+ if (!Array.isArray(memory.tags) || !memory.tags.includes(tag))
349
+ return false;
350
+ }
351
+ return true;
352
+ });
353
353
  if (opts.order) {
354
354
  const dir = opts.order === "createdAt-desc" ? -1 : 1;
355
355
  memories.sort((a, b) => dir * (a.createdAt > b.createdAt ? 1 : a.createdAt < b.createdAt ? -1 : 0));
356
356
  }
357
+ // Applied after filtering/ordering so the window reflects the final set.
358
+ if (opts.limit && opts.limit > 0)
359
+ memories.splice(opts.limit);
357
360
  return memories;
358
361
  }
359
362
  /** Delete a memory. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpsdev-ai/flair-client",
3
- "version": "0.53.0",
3
+ "version": "0.54.1",
4
4
  "description": "Lightweight client for Flair — identity, memory, and soul for AI agents. Zero heavy dependencies.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",