@tpsdev-ai/flair-client 0.1.0 → 0.2.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
@@ -33,17 +33,24 @@ export declare class FlairClient {
33
33
  declare class MemoryApi {
34
34
  private client;
35
35
  constructor(client: FlairClient);
36
- /** Write a memory. */
36
+ /** Write a memory. Optionally checks for near-duplicates before writing. */
37
37
  write(content: string, opts?: {
38
38
  id?: string;
39
39
  type?: MemoryType;
40
40
  durability?: Durability;
41
41
  tags?: string[];
42
42
  subject?: string;
43
+ /** Check for similar existing memories before writing. If a near-duplicate
44
+ * is found (score >= threshold), returns it instead of creating a new one.
45
+ * Default: false (no dedup check). */
46
+ dedup?: boolean;
47
+ /** Similarity threshold for dedup. Default: 0.7 */
48
+ dedupThreshold?: number;
43
49
  }): Promise<Memory>;
44
50
  /** Search memories by meaning. */
45
51
  search(query: string, opts?: {
46
52
  limit?: number;
53
+ minScore?: number;
47
54
  }): Promise<SearchResult[]>;
48
55
  /** Get a memory by ID. */
49
56
  get(id: string): Promise<Memory | null>;
package/dist/client.js CHANGED
@@ -20,8 +20,8 @@ export class FlairClient {
20
20
  keyPath;
21
21
  timeoutMs;
22
22
  constructor(config) {
23
- this.url = (config.url ?? DEFAULT_URL).replace(/\/$/, "");
24
- this.agentId = config.agentId;
23
+ this.url = (config.url ?? process.env.FLAIR_URL ?? DEFAULT_URL).replace(/\/$/, "");
24
+ this.agentId = config.agentId || process.env.FLAIR_AGENT_ID || "";
25
25
  this.keyPath = config.keyPath;
26
26
  this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT;
27
27
  this.memory = new MemoryApi(this);
@@ -77,10 +77,22 @@ class MemoryApi {
77
77
  constructor(client) {
78
78
  this.client = client;
79
79
  }
80
- /** Write a memory. */
80
+ /** Write a memory. Optionally checks for near-duplicates before writing. */
81
81
  async write(content, opts = {}) {
82
+ // Near-duplicate check — skip for very short content where similarity
83
+ // is unreliable (e.g., "ok", "thanks" would match each other)
84
+ if (opts.dedup && content.length >= 20) {
85
+ const threshold = opts.dedupThreshold ?? 0.7;
86
+ const existing = await this.search(content, { limit: 1, minScore: threshold });
87
+ if (existing.length > 0) {
88
+ // Return the existing memory instead of creating a duplicate
89
+ const match = await this.get(existing[0].id);
90
+ if (match)
91
+ return match;
92
+ }
93
+ }
82
94
  const id = opts.id ?? `${this.client.agentId}-${Date.now()}`;
83
- return this.client.request("PUT", `/Memory/${id}`, {
95
+ const record = {
84
96
  id,
85
97
  agentId: this.client.agentId,
86
98
  content,
@@ -89,20 +101,26 @@ class MemoryApi {
89
101
  tags: opts.tags ?? [],
90
102
  subject: opts.subject,
91
103
  createdAt: new Date().toISOString(),
92
- });
104
+ };
105
+ await this.client.request("PUT", `/Memory/${id}`, record);
106
+ // Harper PUT returns {} — return the record we constructed
107
+ return record;
93
108
  }
94
109
  /** Search memories by meaning. */
95
110
  async search(query, opts = {}) {
96
111
  const result = await this.client.request("POST", "/SemanticSearch", { agentId: this.client.agentId, q: query, limit: opts.limit ?? 5 });
97
- return (result.results ?? []).map((r) => ({
112
+ const minScore = opts.minScore ?? 0;
113
+ return (result.results ?? [])
114
+ .map((r) => ({
98
115
  id: r.id ?? r.memory?.id ?? "",
99
116
  content: r.content ?? r.memory?.content ?? "",
100
- score: r.score ?? r.similarity ?? 0,
117
+ score: r._score ?? r.score ?? r.similarity ?? 0,
101
118
  type: r.type ?? r.memory?.type,
102
119
  durability: r.durability ?? r.memory?.durability,
103
120
  tags: r.tags ?? r.memory?.tags,
104
121
  createdAt: r.createdAt ?? r.memory?.createdAt,
105
- }));
122
+ }))
123
+ .filter((r) => r.score >= minScore);
106
124
  }
107
125
  /** Get a memory by ID. */
108
126
  async get(id) {
package/dist/types.d.ts CHANGED
@@ -43,8 +43,8 @@ export interface BootstrapResult {
43
43
  export interface FlairClientConfig {
44
44
  /** Flair server URL. Default: http://localhost:9926 */
45
45
  url?: string;
46
- /** Agent ID for authentication and data scoping. */
47
- agentId: string;
46
+ /** Agent ID for authentication and data scoping. Falls back to FLAIR_AGENT_ID env var. */
47
+ agentId?: string;
48
48
  /** Path to Ed25519 private key file. Auto-resolved if omitted. */
49
49
  keyPath?: string;
50
50
  /** Request timeout in ms. Default: 10000 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpsdev-ai/flair-client",
3
- "version": "0.1.0",
3
+ "version": "0.2.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",