openclaw-cloudflare-vectorize-memory 0.1.7 → 0.1.9

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
@@ -63,8 +63,18 @@ npm run publish:npmjs
63
63
 
64
64
  The script runs `check`, `test`, and `build` before calling `npm publish --access public`.
65
65
 
66
+ Before publishing, fill in the placeholder values in `.env`, set `OPENCLAW_CF_MEMORY_RUN_LIVE_INTEGRATION=1`, and run:
67
+
68
+ ```bash
69
+ npm run test:integration
70
+ ```
71
+
72
+ The live integration suite rebuilds the package first, resolves Cloudflare settings from `.env`, then fills any untouched placeholder values from `.env.example`, and exercises `doctor --create-index` plus a real `upsert` / `search` / `delete` round-trip against the configured backend. The default `npm test` command keeps running only the fast local test suite.
73
+
66
74
  ## Recommended environment variables
67
75
 
76
+ The repository includes `.env` and `.env.example` templates for the live integration tests. Replace the placeholder values in `.env` before enabling the suite.
77
+
68
78
  Cloudflare-standard variables:
69
79
 
70
80
  ```bash
@@ -86,6 +96,7 @@ Optional:
86
96
  set CLOUDFLARE_VECTORIZE_NAMESPACE=my-shared-namespace
87
97
  set OPENCLAW_CF_MEMORY_STORAGE_MODE=companion-store
88
98
  set OPENCLAW_CF_MEMORY_COMPANION_PATH=C:\path\to\companion-store.json
99
+ set OPENCLAW_CF_MEMORY_TEST_NAMESPACE_PREFIX=cf-memory-live
89
100
  ```
90
101
 
91
102
  If `CLOUDFLARE_VECTORIZE_NAMESPACE` is omitted, the plugin derives namespaces from the active OpenClaw agent/session when possible.
@@ -3,22 +3,32 @@ import { CloudflareApiError as e } from "./errors.js";
3
3
  function t(e, t) {
4
4
  return e?.errors?.map((e) => e.message).filter(Boolean).join("; ") || t;
5
5
  }
6
- function n(t) {
6
+ function n(e) {
7
+ return typeof e == "object" && !!e && "success" in e;
8
+ }
9
+ function r(e) {
10
+ if (e) return JSON.parse(e);
11
+ }
12
+ function i(t) {
7
13
  return t instanceof e && t.status === 404;
8
14
  }
9
- async function r(n) {
10
- let r = new Headers(n.headers);
11
- r.set("Authorization", `Bearer ${n.apiToken}`), !r.has("Content-Type") && n.body && r.set("Content-Type", "application/json");
12
- let i = await fetch(n.url, {
13
- method: n.method ?? (n.body ? "POST" : "GET"),
14
- headers: r,
15
- body: n.body
16
- }), a = await i.text(), o = a ? JSON.parse(a) : void 0;
17
- if (!i.ok) throw new e(t(o, `Cloudflare request failed with ${i.status}.`), i.status, o);
18
- if (!o?.success) throw new e(t(o, "Cloudflare request failed."), i.status, o);
19
- return o.result;
15
+ async function a(i) {
16
+ let a = new Headers(i.headers);
17
+ a.set("Authorization", `Bearer ${i.apiToken}`), !a.has("Content-Type") && i.body && a.set("Content-Type", "application/json");
18
+ let o = await fetch(i.url, {
19
+ method: i.method ?? (i.body ? "POST" : "GET"),
20
+ headers: a,
21
+ body: i.body
22
+ }), s = r(await o.text());
23
+ if (!o.ok) throw new e(t(n(s) ? s : void 0, `Cloudflare request failed with ${o.status}.`), o.status, s);
24
+ if (n(s)) {
25
+ if (!s.success) throw new e(t(s, "Cloudflare request failed."), o.status, s);
26
+ return s.result;
27
+ }
28
+ if ((i.responseMode ?? "envelope") === "auto") return s;
29
+ throw new e("Cloudflare response did not include the expected success/result envelope.", o.status, s);
20
30
  }
21
31
  //#endregion
22
- export { n as isCloudflareNotFoundError, r as requestCloudflare };
32
+ export { i as isCloudflareNotFoundError, a as requestCloudflare };
23
33
 
24
34
  //# sourceMappingURL=cloudflare-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare-api.js","names":[],"sources":["../src/cloudflare-api.ts"],"sourcesContent":["import { CloudflareApiError } from \"./errors.js\";\n\ntype CloudflareResponseEnvelope<T> = {\n\tsuccess: boolean;\n\tresult: T;\n\terrors?: Array<{ code?: number; message?: string }>;\n};\n\nfunction describeFailure(envelope: Partial<CloudflareResponseEnvelope<unknown>> | undefined, fallback: string): string {\n\tconst message = envelope?.errors\n\t\t?.map((entry) => entry.message)\n\t\t.filter(Boolean)\n\t\t.join(\"; \");\n\treturn message || fallback;\n}\n\nexport function isCloudflareNotFoundError(error: unknown): boolean {\n\treturn error instanceof CloudflareApiError && error.status === 404;\n}\n\nexport async function requestCloudflare<T>(params: {\n\turl: string;\n\tapiToken: string;\n\tmethod?: string;\n\theaders?: Record<string, string>;\n\tbody?: string;\n}): Promise<T> {\n\tconst headers = new Headers(params.headers);\n\theaders.set(\"Authorization\", `Bearer ${params.apiToken}`);\n\tif (!headers.has(\"Content-Type\") && params.body) {\n\t\theaders.set(\"Content-Type\", \"application/json\");\n\t}\n\n\tconst response = await fetch(params.url, {\n\t\tmethod: params.method ?? (params.body ? \"POST\" : \"GET\"),\n\t\theaders,\n\t\tbody: params.body,\n\t});\n\n\tconst rawText = await response.text();\n\tconst parsed = rawText ? (JSON.parse(rawText) as CloudflareResponseEnvelope<T>) : undefined;\n\tif (!response.ok) {\n\t\tthrow new CloudflareApiError(describeFailure(parsed, `Cloudflare request failed with ${response.status}.`), response.status, parsed);\n\t}\n\tif (!parsed?.success) {\n\t\tthrow new CloudflareApiError(describeFailure(parsed, \"Cloudflare request failed.\"), response.status, parsed);\n\t}\n\n\treturn parsed.result;\n}\n"],"mappings":";;AAQA,SAAS,EAAgB,GAAoE,GAA0B;AAKtH,QAJgB,GAAU,QACvB,KAAK,MAAU,EAAM,QAAQ,CAC9B,OAAO,QAAQ,CACf,KAAK,KAAK,IACM;;AAGnB,SAAgB,EAA0B,GAAyB;AAClE,QAAO,aAAiB,KAAsB,EAAM,WAAW;;AAGhE,eAAsB,EAAqB,GAM5B;CACd,IAAM,IAAU,IAAI,QAAQ,EAAO,QAAQ;AAE3C,CADA,EAAQ,IAAI,iBAAiB,UAAU,EAAO,WAAW,EACrD,CAAC,EAAQ,IAAI,eAAe,IAAI,EAAO,QAC1C,EAAQ,IAAI,gBAAgB,mBAAmB;CAGhD,IAAM,IAAW,MAAM,MAAM,EAAO,KAAK;EACxC,QAAQ,EAAO,WAAW,EAAO,OAAO,SAAS;EACjD;EACA,MAAM,EAAO;EACb,CAAC,EAEI,IAAU,MAAM,EAAS,MAAM,EAC/B,IAAS,IAAW,KAAK,MAAM,EAAQ,GAAqC,KAAA;AAClF,KAAI,CAAC,EAAS,GACb,OAAM,IAAI,EAAmB,EAAgB,GAAQ,kCAAkC,EAAS,OAAO,GAAG,EAAE,EAAS,QAAQ,EAAO;AAErI,KAAI,CAAC,GAAQ,QACZ,OAAM,IAAI,EAAmB,EAAgB,GAAQ,6BAA6B,EAAE,EAAS,QAAQ,EAAO;AAG7G,QAAO,EAAO"}
1
+ {"version":3,"file":"cloudflare-api.js","names":[],"sources":["../src/cloudflare-api.ts"],"sourcesContent":["import { CloudflareApiError } from \"./errors.js\";\n\ntype CloudflareResponseEnvelope<T> = {\n\tsuccess: boolean;\n\tresult: T;\n\terrors?: Array<{ code?: number; message?: string }>;\n};\n\ntype ResponseMode = \"auto\" | \"envelope\";\n\nfunction describeFailure(envelope: Partial<CloudflareResponseEnvelope<unknown>> | undefined, fallback: string): string {\n\tconst message = envelope?.errors\n\t\t?.map((entry) => entry.message)\n\t\t.filter(Boolean)\n\t\t.join(\"; \");\n\treturn message || fallback;\n}\n\nfunction isResponseEnvelope<T>(value: unknown): value is Partial<CloudflareResponseEnvelope<T>> & { success: boolean } {\n\treturn value !== null && typeof value === \"object\" && \"success\" in value;\n}\n\nfunction parseResponseBody(rawText: string): unknown {\n\tif (!rawText) {\n\t\treturn undefined;\n\t}\n\treturn JSON.parse(rawText) as unknown;\n}\n\nexport function isCloudflareNotFoundError(error: unknown): boolean {\n\treturn error instanceof CloudflareApiError && error.status === 404;\n}\n\nexport async function requestCloudflare<T>(params: {\n\turl: string;\n\tapiToken: string;\n\tmethod?: string;\n\theaders?: Record<string, string>;\n\tbody?: string;\n\tresponseMode?: ResponseMode;\n}): Promise<T> {\n\tconst headers = new Headers(params.headers);\n\theaders.set(\"Authorization\", `Bearer ${params.apiToken}`);\n\tif (!headers.has(\"Content-Type\") && params.body) {\n\t\theaders.set(\"Content-Type\", \"application/json\");\n\t}\n\n\tconst response = await fetch(params.url, {\n\t\tmethod: params.method ?? (params.body ? \"POST\" : \"GET\"),\n\t\theaders,\n\t\tbody: params.body,\n\t});\n\n\tconst rawText = await response.text();\n\tconst parsed = parseResponseBody(rawText);\n\tif (!response.ok) {\n\t\tthrow new CloudflareApiError(\n\t\t\tdescribeFailure(isResponseEnvelope(parsed) ? parsed : undefined, `Cloudflare request failed with ${response.status}.`),\n\t\t\tresponse.status,\n\t\t\tparsed,\n\t\t);\n\t}\n\n\tif (isResponseEnvelope<T>(parsed)) {\n\t\tif (!parsed.success) {\n\t\t\tthrow new CloudflareApiError(describeFailure(parsed, \"Cloudflare request failed.\"), response.status, parsed);\n\t\t}\n\t\treturn parsed.result as T;\n\t}\n\n\tif ((params.responseMode ?? \"envelope\") === \"auto\") {\n\t\treturn parsed as T;\n\t}\n\n\tthrow new CloudflareApiError(\"Cloudflare response did not include the expected success/result envelope.\", response.status, parsed);\n}\n"],"mappings":";;AAUA,SAAS,EAAgB,GAAoE,GAA0B;AAKtH,QAJgB,GAAU,QACvB,KAAK,MAAU,EAAM,QAAQ,CAC9B,OAAO,QAAQ,CACf,KAAK,KAAK,IACM;;AAGnB,SAAS,EAAsB,GAAwF;AACtH,QAAyB,OAAO,KAAU,cAAnC,KAA+C,aAAa;;AAGpE,SAAS,EAAkB,GAA0B;AAC/C,OAGL,QAAO,KAAK,MAAM,EAAQ;;AAG3B,SAAgB,EAA0B,GAAyB;AAClE,QAAO,aAAiB,KAAsB,EAAM,WAAW;;AAGhE,eAAsB,EAAqB,GAO5B;CACd,IAAM,IAAU,IAAI,QAAQ,EAAO,QAAQ;AAE3C,CADA,EAAQ,IAAI,iBAAiB,UAAU,EAAO,WAAW,EACrD,CAAC,EAAQ,IAAI,eAAe,IAAI,EAAO,QAC1C,EAAQ,IAAI,gBAAgB,mBAAmB;CAGhD,IAAM,IAAW,MAAM,MAAM,EAAO,KAAK;EACxC,QAAQ,EAAO,WAAW,EAAO,OAAO,SAAS;EACjD;EACA,MAAM,EAAO;EACb,CAAC,EAGI,IAAS,EADC,MAAM,EAAS,MAAM,CACI;AACzC,KAAI,CAAC,EAAS,GACb,OAAM,IAAI,EACT,EAAgB,EAAmB,EAAO,GAAG,IAAS,KAAA,GAAW,kCAAkC,EAAS,OAAO,GAAG,EACtH,EAAS,QACT,EACA;AAGF,KAAI,EAAsB,EAAO,EAAE;AAClC,MAAI,CAAC,EAAO,QACX,OAAM,IAAI,EAAmB,EAAgB,GAAQ,6BAA6B,EAAE,EAAS,QAAQ,EAAO;AAE7G,SAAO,EAAO;;AAGf,MAAK,EAAO,gBAAgB,gBAAgB,OAC3C,QAAO;AAGR,OAAM,IAAI,EAAmB,6EAA6E,EAAS,QAAQ,EAAO"}
package/dist/config.js CHANGED
@@ -216,34 +216,49 @@ var g = h.object({
216
216
  help: `Defaults to \${${n}} or the OpenClaw state directory.`
217
217
  }
218
218
  }
219
- };
220
- function x(...e) {
219
+ }, x = [
220
+ "cloudflare",
221
+ "vectorize",
222
+ "embeddings",
223
+ "storage"
224
+ ];
225
+ function S(e) {
226
+ if (!e || typeof e != "object" || Array.isArray(e)) return e;
227
+ let t = e;
228
+ if ("config" in t) return S(t.config);
229
+ let n = Object.fromEntries(x.filter((e) => e in t).map((e) => [e, t[e]]));
230
+ return Object.keys(n).length > 0 ? n : "enabled" in t && Object.keys(t).every((e) => e === "enabled") ? {} : e;
231
+ }
232
+ function C(...e) {
221
233
  return e.find((e) => e !== void 0);
222
234
  }
223
- function S(...e) {
235
+ function w(...e) {
224
236
  for (let t of e) if (t && t.trim().length > 0) return t.trim();
225
237
  }
226
- function C(...e) {
238
+ function T(...e) {
227
239
  return e.find((e) => typeof e == "number" && Number.isFinite(e));
228
240
  }
229
- function w(e) {
241
+ function E(e) {
230
242
  return [...new Set((e ?? []).map((e) => e.trim()).filter(Boolean))];
231
243
  }
232
- function T(e) {
244
+ function D(e) {
233
245
  return e ?? "cosine";
234
246
  }
235
- function E(e) {
247
+ function O(e) {
236
248
  return e ?? "vectorize-inline";
237
249
  }
238
- function D(e) {
250
+ function k(e) {
239
251
  return y.parse(e ?? {});
240
252
  }
241
- function O(e) {
253
+ function A(e) {
254
+ return k(S(e) ?? {});
255
+ }
256
+ function j(e) {
242
257
  let t = e.plugins?.entries?.[o];
243
- return D(t ?? {});
258
+ return A(t ?? {});
244
259
  }
245
- async function k(n) {
246
- let a = D(n.pluginConfig), h = n.env ?? process.env, g = `plugins.entries.${o}`, _ = S(a.cloudflare?.accountId, h[e]);
260
+ async function M(n) {
261
+ let a = A(n.pluginConfig), h = n.env ?? process.env, g = `plugins.entries.${o}`, _ = w(a.cloudflare?.accountId, h[e]);
247
262
  if (!_) throw new f(`Missing Cloudflare account id. Set ${e} or ${g}.cloudflare.accountId.`);
248
263
  let v = await m({
249
264
  config: n.openClawConfig,
@@ -254,29 +269,29 @@ async function k(n) {
254
269
  readFallback: () => h[t]
255
270
  });
256
271
  if (!v.value) throw new f(`Missing Cloudflare API token. Set ${t} or ${g}.cloudflare.apiToken.${v.unresolvedRefReason ? ` ${v.unresolvedRefReason}` : ""}`.trim());
257
- let y = S(a.vectorize?.indexName, h[c]);
272
+ let y = w(a.vectorize?.indexName, h[c]);
258
273
  if (!y) throw new f(`Missing Vectorize index name. Set ${c} or ${g}.vectorize.indexName.`);
259
- let b = S(a.cloudflare?.apiBaseUrl, r);
274
+ let b = w(a.cloudflare?.apiBaseUrl, r);
260
275
  if (!b) throw new f(`Invalid Cloudflare API base URL. Set ${g}.cloudflare.apiBaseUrl or ensure ${r} is a valid URL.`);
261
- let O = S(a.vectorize?.namespace, h[l]), k = C(a.vectorize?.topK, h.CLOUDFLARE_VECTORIZE_TOP_K ? Number(h[u]) : void 0), A = E(x(a.storage?.mode, h[s])), j = S(a.storage?.companionStorePath, h.OPENCLAW_CF_MEMORY_COMPANION_PATH) ?? p(".openclaw", "memory-cloudflare-vectorize", "companion-store.json"), M = n.resolvePath ?? ((e) => e), N = S(a.embeddings?.model, h[d], i);
276
+ let x = w(a.vectorize?.namespace, h[l]), S = T(a.vectorize?.topK, h.CLOUDFLARE_VECTORIZE_TOP_K ? Number(h[u]) : void 0), k = O(C(a.storage?.mode, h[s])), j = w(a.storage?.companionStorePath, h.OPENCLAW_CF_MEMORY_COMPANION_PATH) ?? p(".openclaw", "memory-cloudflare-vectorize", "companion-store.json"), M = n.resolvePath ?? ((e) => e), N = w(a.embeddings?.model, h[d], i);
262
277
  if (!N) throw new f(`Missing Workers AI embedding model. Set ${d} or ${g}.embeddings.model.`);
263
- let P = C(a.storage?.inlineTextMaxBytes) ?? 6e3, F = C(a.vectorize?.minScore) ?? 0, I = T(x(a.vectorize?.metric, a.vectorize?.createIndex?.metric));
278
+ let P = T(a.storage?.inlineTextMaxBytes) ?? 6e3, F = T(a.vectorize?.minScore) ?? 0, I = D(C(a.vectorize?.metric, a.vectorize?.createIndex?.metric));
264
279
  return {
265
280
  accountId: _,
266
281
  apiToken: v.value,
267
282
  apiBaseUrl: b,
268
- workersAiBaseUrl: S(a.cloudflare?.workersAiBaseUrl) ?? `${b}/accounts/${_}/ai/v1`,
269
- vectorizeBaseUrl: S(a.cloudflare?.vectorizeBaseUrl) ?? `${b}/accounts/${_}/vectorize/v2/indexes/${y}`,
283
+ workersAiBaseUrl: w(a.cloudflare?.workersAiBaseUrl) ?? `${b}/accounts/${_}/ai/v1`,
284
+ vectorizeBaseUrl: w(a.cloudflare?.vectorizeBaseUrl) ?? `${b}/accounts/${_}/vectorize/v2/indexes/${y}`,
270
285
  indexName: y,
271
- fixedNamespace: O,
272
- topK: k ?? 5,
286
+ fixedNamespace: x,
287
+ topK: S ?? 5,
273
288
  minScore: F,
274
289
  metric: I,
275
290
  model: N,
276
- storageMode: A,
291
+ storageMode: k,
277
292
  companionStorePath: M(j),
278
293
  inlineTextMaxBytes: P,
279
- metadataIndexedFields: w(a.vectorize?.metadataIndexedFields),
294
+ metadataIndexedFields: E(a.vectorize?.metadataIndexedFields),
280
295
  createIndex: {
281
296
  description: a.vectorize?.createIndex?.description ?? "OpenClaw memory index backed by Cloudflare Vectorize.",
282
297
  dimensions: a.vectorize?.createIndex?.dimensions,
@@ -285,6 +300,6 @@ async function k(n) {
285
300
  };
286
301
  }
287
302
  //#endregion
288
- export { O as getPluginConfigFromOpenClawConfig, b as pluginConfigSchema, k as resolvePluginConfig };
303
+ export { j as getPluginConfigFromOpenClawConfig, A as normalizePluginConfigInput, b as pluginConfigSchema, M as resolvePluginConfig };
289
304
 
290
305
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { join } from \"node:path\";\nimport type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport { resolveConfiguredSecretInputWithFallback } from \"openclaw/plugin-sdk/config-runtime\";\nimport type { OpenClawPluginConfigSchema } from \"openclaw/plugin-sdk/plugin-entry\";\nimport type { SecretInput } from \"openclaw/plugin-sdk/secret-ref-runtime\";\nimport { z } from \"zod\";\nimport {\n\tCLOUDFLARE_ACCOUNT_ID_ENV,\n\tCLOUDFLARE_API_TOKEN_ENV,\n\tCOMPANION_PATH_ENV,\n\tDEFAULT_CLOUDFLARE_API_BASE_URL,\n\tDEFAULT_EMBEDDING_MODEL,\n\tDEFAULT_INDEX_DESCRIPTION,\n\tDEFAULT_INLINE_TEXT_MAX_BYTES,\n\tDEFAULT_MIN_SCORE,\n\tDEFAULT_STORAGE_MODE,\n\tDEFAULT_TOP_K,\n\tDEFAULT_VECTORIZE_METRIC,\n\tPLUGIN_ID,\n\tSTORAGE_MODE_ENV,\n\tVECTORIZE_INDEX_ENV,\n\tVECTORIZE_NAMESPACE_ENV,\n\tVECTORIZE_TOP_K_ENV,\n\tWORKERS_AI_MODEL_ENV,\n} from \"./constants.js\";\nimport { ConfigurationError } from \"./errors.js\";\nimport type { RawPluginConfig, ResolvedPluginConfig, StorageMode, VectorizeMetric } from \"./types.js\";\n\nconst secretRefSchema = z\n\t.object({\n\t\tsource: z.enum([\"env\", \"file\", \"exec\"]),\n\t\tprovider: z.string().min(1),\n\t\tid: z.string().min(1),\n\t})\n\t.strict();\n\nconst secretInputSchema: z.ZodType<SecretInput> = z.union([z.string().min(1), secretRefSchema]);\n\nconst createIndexSchema = z\n\t.object({\n\t\tdescription: z.string().min(1).optional(),\n\t\tdimensions: z.number().int().min(1).max(1536).optional(),\n\t\tmetric: z.enum([\"cosine\", \"euclidean\", \"dot-product\"]).optional(),\n\t})\n\t.strict();\n\nconst pluginConfigZod: z.ZodType<RawPluginConfig> = z\n\t.object({\n\t\tcloudflare: z\n\t\t\t.object({\n\t\t\t\taccountId: z.string().min(1).optional(),\n\t\t\t\tapiToken: secretInputSchema.optional(),\n\t\t\t\tapiBaseUrl: z.string().url().optional(),\n\t\t\t\tworkersAiBaseUrl: z.string().url().optional(),\n\t\t\t\tvectorizeBaseUrl: z.string().url().optional(),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tvectorize: z\n\t\t\t.object({\n\t\t\t\tindexName: z.string().min(1).optional(),\n\t\t\t\tnamespace: z.string().min(1).optional(),\n\t\t\t\ttopK: z.number().int().min(1).max(50).optional(),\n\t\t\t\tminScore: z.number().min(0).max(1).optional(),\n\t\t\t\tmetric: z.enum([\"cosine\", \"euclidean\", \"dot-product\"]).optional(),\n\t\t\t\tcreateIndex: createIndexSchema.optional(),\n\t\t\t\tmetadataIndexedFields: z.array(z.string().min(1)).default([]),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tembeddings: z\n\t\t\t.object({\n\t\t\t\tmodel: z.string().min(1).optional(),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tstorage: z\n\t\t\t.object({\n\t\t\t\tmode: z.enum([\"vectorize-inline\", \"companion-store\"]).optional(),\n\t\t\t\tcompanionStorePath: z.string().min(1).optional(),\n\t\t\t\tinlineTextMaxBytes: z.number().int().min(256).max(10_000).optional(),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t})\n\t.strict();\n\nexport const pluginConfigJsonSchema = {\n\ttype: \"object\",\n\tadditionalProperties: false,\n\tproperties: {\n\t\tcloudflare: {\n\t\t\ttype: \"object\",\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\taccountId: { type: \"string\" },\n\t\t\t\tapiToken: {\n\t\t\t\t\tanyOf: [\n\t\t\t\t\t\t{ type: \"string\" },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\tadditionalProperties: false,\n\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\tsource: { type: \"string\", enum: [\"env\", \"file\", \"exec\"] },\n\t\t\t\t\t\t\t\tprovider: { type: \"string\" },\n\t\t\t\t\t\t\t\tid: { type: \"string\" },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\trequired: [\"source\", \"provider\", \"id\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tapiBaseUrl: { type: \"string\", format: \"uri\" },\n\t\t\t\tworkersAiBaseUrl: { type: \"string\", format: \"uri\" },\n\t\t\t\tvectorizeBaseUrl: { type: \"string\", format: \"uri\" },\n\t\t\t},\n\t\t},\n\t\tvectorize: {\n\t\t\ttype: \"object\",\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tindexName: { type: \"string\" },\n\t\t\t\tnamespace: { type: \"string\" },\n\t\t\t\ttopK: { type: \"integer\", minimum: 1, maximum: 50 },\n\t\t\t\tminScore: { type: \"number\", minimum: 0, maximum: 1 },\n\t\t\t\tmetric: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tenum: [\"cosine\", \"euclidean\", \"dot-product\"],\n\t\t\t\t},\n\t\t\t\tcreateIndex: {\n\t\t\t\t\ttype: \"object\",\n\t\t\t\t\tadditionalProperties: false,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tdescription: { type: \"string\" },\n\t\t\t\t\t\tdimensions: { type: \"integer\", minimum: 1, maximum: 1536 },\n\t\t\t\t\t\tmetric: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\tenum: [\"cosine\", \"euclidean\", \"dot-product\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetadataIndexedFields: {\n\t\t\t\t\ttype: \"array\",\n\t\t\t\t\titems: { type: \"string\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tembeddings: {\n\t\t\ttype: \"object\",\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tmodel: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t\tstorage: {\n\t\t\ttype: \"object\",\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tmode: { type: \"string\", enum: [\"vectorize-inline\", \"companion-store\"] },\n\t\t\t\tcompanionStorePath: { type: \"string\" },\n\t\t\t\tinlineTextMaxBytes: { type: \"integer\", minimum: 256, maximum: 10000 },\n\t\t\t},\n\t\t},\n\t},\n} as const;\n\nexport const pluginUiHints = {\n\t\"cloudflare.accountId\": {\n\t\tlabel: \"Cloudflare account ID\",\n\t\thelp: `Defaults to \\${${CLOUDFLARE_ACCOUNT_ID_ENV}}.`,\n\t},\n\t\"cloudflare.apiToken\": {\n\t\tlabel: \"Cloudflare API token\",\n\t\tsensitive: true,\n\t\thelp: `Defaults to \\${${CLOUDFLARE_API_TOKEN_ENV}}.`,\n\t},\n\t\"vectorize.indexName\": {\n\t\tlabel: \"Vectorize index name\",\n\t\thelp: `Defaults to \\${${VECTORIZE_INDEX_ENV}}.`,\n\t},\n\t\"vectorize.namespace\": {\n\t\tlabel: \"Fixed namespace override\",\n\t\thelp: `Defaults to \\${${VECTORIZE_NAMESPACE_ENV}} or derives from the agent/session context.`,\n\t},\n\t\"vectorize.topK\": {\n\t\tlabel: \"Top-K results\",\n\t\thelp: `Defaults to \\${${VECTORIZE_TOP_K_ENV}} or ${DEFAULT_TOP_K}.`,\n\t},\n\t\"embeddings.model\": {\n\t\tlabel: \"Workers AI embedding model\",\n\t\thelp: `Defaults to \\${${WORKERS_AI_MODEL_ENV}} or ${DEFAULT_EMBEDDING_MODEL}.`,\n\t},\n\t\"storage.mode\": {\n\t\tlabel: \"Storage mode\",\n\t\thelp: `Defaults to \\${${STORAGE_MODE_ENV}} or ${DEFAULT_STORAGE_MODE}.`,\n\t},\n\t\"storage.companionStorePath\": {\n\t\tlabel: \"Companion store path\",\n\t\thelp: `Defaults to \\${${COMPANION_PATH_ENV}} or the OpenClaw state directory.`,\n\t},\n} as const;\n\nexport const pluginConfigSchema: OpenClawPluginConfigSchema = {\n\tparse(value: unknown) {\n\t\treturn pluginConfigZod.parse(value ?? {});\n\t},\n\tsafeParse(value: unknown) {\n\t\tconst result = pluginConfigZod.safeParse(value ?? {});\n\t\tif (result.success) {\n\t\t\treturn { success: true, data: result.data };\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tissues: result.error.issues.map((issue) => ({\n\t\t\t\t\tpath: issue.path.filter((segment): segment is string | number => typeof segment === \"string\" || typeof segment === \"number\"),\n\t\t\t\t\tmessage: issue.message,\n\t\t\t\t})),\n\t\t\t},\n\t\t};\n\t},\n\tjsonSchema: pluginConfigJsonSchema,\n\tuiHints: pluginUiHints,\n};\n\ntype PluginEntriesAwareConfig = OpenClawConfig & {\n\tplugins?: {\n\t\tentries?: Record<string, unknown>;\n\t};\n};\n\nfunction pickFirstDefined<T>(...values: Array<T | undefined>): T | undefined {\n\treturn values.find((value) => value !== undefined);\n}\n\nfunction pickTrimmed(...values: Array<string | undefined>): string | undefined {\n\tfor (const value of values) {\n\t\tif (value && value.trim().length > 0) {\n\t\t\treturn value.trim();\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction pickNumber(...values: Array<number | undefined>): number | undefined {\n\treturn values.find((value) => typeof value === \"number\" && Number.isFinite(value));\n}\n\nfunction normalizeMetadataIndexedFields(fields: string[] | undefined): string[] {\n\treturn [...new Set((fields ?? []).map((field) => field.trim()).filter(Boolean))];\n}\n\nfunction ensureVectorizeMetric(metric: VectorizeMetric | undefined): VectorizeMetric {\n\treturn metric ?? DEFAULT_VECTORIZE_METRIC;\n}\n\nfunction ensureStorageMode(mode: StorageMode | undefined): StorageMode {\n\treturn mode ?? DEFAULT_STORAGE_MODE;\n}\n\nexport function parsePluginConfig(value: unknown): RawPluginConfig {\n\treturn pluginConfigZod.parse(value ?? {});\n}\n\nexport function getPluginConfigFromOpenClawConfig(config: OpenClawConfig): RawPluginConfig {\n\tconst candidate = (config as PluginEntriesAwareConfig).plugins?.entries?.[PLUGIN_ID];\n\treturn parsePluginConfig(candidate ?? {});\n}\n\nexport async function resolvePluginConfig(params: {\n\tpluginConfig: unknown;\n\topenClawConfig: OpenClawConfig;\n\tenv?: NodeJS.ProcessEnv;\n\tresolvePath?: (input: string) => string;\n}): Promise<ResolvedPluginConfig> {\n\tconst parsed = parsePluginConfig(params.pluginConfig);\n\tconst env = params.env ?? process.env;\n\tconst configPathBase = `plugins.entries.${PLUGIN_ID}`;\n\tconst accountId = pickTrimmed(parsed.cloudflare?.accountId, env[CLOUDFLARE_ACCOUNT_ID_ENV]);\n\tif (!accountId) {\n\t\tthrow new ConfigurationError(`Missing Cloudflare account id. Set ${CLOUDFLARE_ACCOUNT_ID_ENV} or ${configPathBase}.cloudflare.accountId.`);\n\t}\n\n\tconst tokenResult = await resolveConfiguredSecretInputWithFallback({\n\t\tconfig: params.openClawConfig,\n\t\tenv,\n\t\tvalue: parsed.cloudflare?.apiToken,\n\t\tpath: `${configPathBase}.cloudflare.apiToken`,\n\t\tunresolvedReasonStyle: \"detailed\",\n\t\treadFallback: () => env[CLOUDFLARE_API_TOKEN_ENV],\n\t});\n\tif (!tokenResult.value) {\n\t\tconst reason = tokenResult.unresolvedRefReason ? ` ${tokenResult.unresolvedRefReason}` : \"\";\n\t\tthrow new ConfigurationError(`Missing Cloudflare API token. Set ${CLOUDFLARE_API_TOKEN_ENV} or ${configPathBase}.cloudflare.apiToken.${reason}`.trim());\n\t}\n\n\tconst indexName = pickTrimmed(parsed.vectorize?.indexName, env[VECTORIZE_INDEX_ENV]);\n\tif (!indexName) {\n\t\tthrow new ConfigurationError(`Missing Vectorize index name. Set ${VECTORIZE_INDEX_ENV} or ${configPathBase}.vectorize.indexName.`);\n\t}\n\n\tconst apiBaseUrl = pickTrimmed(parsed.cloudflare?.apiBaseUrl, DEFAULT_CLOUDFLARE_API_BASE_URL);\n\tif (!apiBaseUrl) {\n\t\tthrow new ConfigurationError(\n\t\t\t`Invalid Cloudflare API base URL. Set ${configPathBase}.cloudflare.apiBaseUrl or ensure ${DEFAULT_CLOUDFLARE_API_BASE_URL} is a valid URL.`,\n\t\t);\n\t}\n\tconst fixedNamespace = pickTrimmed(parsed.vectorize?.namespace, env[VECTORIZE_NAMESPACE_ENV]);\n\tconst topK = pickNumber(parsed.vectorize?.topK, env[VECTORIZE_TOP_K_ENV] ? Number(env[VECTORIZE_TOP_K_ENV]) : undefined);\n\tconst storageMode = ensureStorageMode(pickFirstDefined(parsed.storage?.mode, env[STORAGE_MODE_ENV] as StorageMode | undefined));\n\tconst companionStorePath = pickTrimmed(parsed.storage?.companionStorePath, env[COMPANION_PATH_ENV]) ?? join(\".openclaw\", PLUGIN_ID, \"companion-store.json\");\n\n\tconst resolvePath = params.resolvePath ?? ((input: string) => input);\n\tconst model = pickTrimmed(parsed.embeddings?.model, env[WORKERS_AI_MODEL_ENV], DEFAULT_EMBEDDING_MODEL);\n\tif (!model) {\n\t\tthrow new ConfigurationError(`Missing Workers AI embedding model. Set ${WORKERS_AI_MODEL_ENV} or ${configPathBase}.embeddings.model.`);\n\t}\n\tconst inlineTextMaxBytes = pickNumber(parsed.storage?.inlineTextMaxBytes) ?? DEFAULT_INLINE_TEXT_MAX_BYTES;\n\tconst minScore = pickNumber(parsed.vectorize?.minScore) ?? DEFAULT_MIN_SCORE;\n\tconst metric = ensureVectorizeMetric(pickFirstDefined(parsed.vectorize?.metric, parsed.vectorize?.createIndex?.metric));\n\n\treturn {\n\t\taccountId,\n\t\tapiToken: tokenResult.value,\n\t\tapiBaseUrl,\n\t\tworkersAiBaseUrl: pickTrimmed(parsed.cloudflare?.workersAiBaseUrl) ?? `${apiBaseUrl}/accounts/${accountId}/ai/v1`,\n\t\tvectorizeBaseUrl: pickTrimmed(parsed.cloudflare?.vectorizeBaseUrl) ?? `${apiBaseUrl}/accounts/${accountId}/vectorize/v2/indexes/${indexName}`,\n\t\tindexName,\n\t\tfixedNamespace,\n\t\ttopK: topK ?? DEFAULT_TOP_K,\n\t\tminScore,\n\t\tmetric,\n\t\tmodel,\n\t\tstorageMode,\n\t\tcompanionStorePath: resolvePath(companionStorePath),\n\t\tinlineTextMaxBytes,\n\t\tmetadataIndexedFields: normalizeMetadataIndexedFields(parsed.vectorize?.metadataIndexedFields),\n\t\tcreateIndex: {\n\t\t\tdescription: parsed.vectorize?.createIndex?.description ?? DEFAULT_INDEX_DESCRIPTION,\n\t\t\tdimensions: parsed.vectorize?.createIndex?.dimensions,\n\t\t\tmetric,\n\t\t},\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { join } from \"node:path\";\nimport type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport { resolveConfiguredSecretInputWithFallback } from \"openclaw/plugin-sdk/config-runtime\";\nimport type { OpenClawPluginConfigSchema } from \"openclaw/plugin-sdk/plugin-entry\";\nimport type { SecretInput } from \"openclaw/plugin-sdk/secret-ref-runtime\";\nimport { z } from \"zod\";\nimport {\n\tCLOUDFLARE_ACCOUNT_ID_ENV,\n\tCLOUDFLARE_API_TOKEN_ENV,\n\tCOMPANION_PATH_ENV,\n\tDEFAULT_CLOUDFLARE_API_BASE_URL,\n\tDEFAULT_EMBEDDING_MODEL,\n\tDEFAULT_INDEX_DESCRIPTION,\n\tDEFAULT_INLINE_TEXT_MAX_BYTES,\n\tDEFAULT_MIN_SCORE,\n\tDEFAULT_STORAGE_MODE,\n\tDEFAULT_TOP_K,\n\tDEFAULT_VECTORIZE_METRIC,\n\tPLUGIN_ID,\n\tSTORAGE_MODE_ENV,\n\tVECTORIZE_INDEX_ENV,\n\tVECTORIZE_NAMESPACE_ENV,\n\tVECTORIZE_TOP_K_ENV,\n\tWORKERS_AI_MODEL_ENV,\n} from \"./constants.js\";\nimport { ConfigurationError } from \"./errors.js\";\nimport type { RawPluginConfig, ResolvedPluginConfig, StorageMode, VectorizeMetric } from \"./types.js\";\n\nconst secretRefSchema = z\n\t.object({\n\t\tsource: z.enum([\"env\", \"file\", \"exec\"]),\n\t\tprovider: z.string().min(1),\n\t\tid: z.string().min(1),\n\t})\n\t.strict();\n\nconst secretInputSchema: z.ZodType<SecretInput> = z.union([z.string().min(1), secretRefSchema]);\n\nconst createIndexSchema = z\n\t.object({\n\t\tdescription: z.string().min(1).optional(),\n\t\tdimensions: z.number().int().min(1).max(1536).optional(),\n\t\tmetric: z.enum([\"cosine\", \"euclidean\", \"dot-product\"]).optional(),\n\t})\n\t.strict();\n\nconst pluginConfigZod: z.ZodType<RawPluginConfig> = z\n\t.object({\n\t\tcloudflare: z\n\t\t\t.object({\n\t\t\t\taccountId: z.string().min(1).optional(),\n\t\t\t\tapiToken: secretInputSchema.optional(),\n\t\t\t\tapiBaseUrl: z.string().url().optional(),\n\t\t\t\tworkersAiBaseUrl: z.string().url().optional(),\n\t\t\t\tvectorizeBaseUrl: z.string().url().optional(),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tvectorize: z\n\t\t\t.object({\n\t\t\t\tindexName: z.string().min(1).optional(),\n\t\t\t\tnamespace: z.string().min(1).optional(),\n\t\t\t\ttopK: z.number().int().min(1).max(50).optional(),\n\t\t\t\tminScore: z.number().min(0).max(1).optional(),\n\t\t\t\tmetric: z.enum([\"cosine\", \"euclidean\", \"dot-product\"]).optional(),\n\t\t\t\tcreateIndex: createIndexSchema.optional(),\n\t\t\t\tmetadataIndexedFields: z.array(z.string().min(1)).default([]),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tembeddings: z\n\t\t\t.object({\n\t\t\t\tmodel: z.string().min(1).optional(),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tstorage: z\n\t\t\t.object({\n\t\t\t\tmode: z.enum([\"vectorize-inline\", \"companion-store\"]).optional(),\n\t\t\t\tcompanionStorePath: z.string().min(1).optional(),\n\t\t\t\tinlineTextMaxBytes: z.number().int().min(256).max(10_000).optional(),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t})\n\t.strict();\n\nexport const pluginConfigJsonSchema = {\n\ttype: \"object\",\n\tadditionalProperties: false,\n\tproperties: {\n\t\tcloudflare: {\n\t\t\ttype: \"object\",\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\taccountId: { type: \"string\" },\n\t\t\t\tapiToken: {\n\t\t\t\t\tanyOf: [\n\t\t\t\t\t\t{ type: \"string\" },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\tadditionalProperties: false,\n\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\tsource: { type: \"string\", enum: [\"env\", \"file\", \"exec\"] },\n\t\t\t\t\t\t\t\tprovider: { type: \"string\" },\n\t\t\t\t\t\t\t\tid: { type: \"string\" },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\trequired: [\"source\", \"provider\", \"id\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tapiBaseUrl: { type: \"string\", format: \"uri\" },\n\t\t\t\tworkersAiBaseUrl: { type: \"string\", format: \"uri\" },\n\t\t\t\tvectorizeBaseUrl: { type: \"string\", format: \"uri\" },\n\t\t\t},\n\t\t},\n\t\tvectorize: {\n\t\t\ttype: \"object\",\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tindexName: { type: \"string\" },\n\t\t\t\tnamespace: { type: \"string\" },\n\t\t\t\ttopK: { type: \"integer\", minimum: 1, maximum: 50 },\n\t\t\t\tminScore: { type: \"number\", minimum: 0, maximum: 1 },\n\t\t\t\tmetric: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tenum: [\"cosine\", \"euclidean\", \"dot-product\"],\n\t\t\t\t},\n\t\t\t\tcreateIndex: {\n\t\t\t\t\ttype: \"object\",\n\t\t\t\t\tadditionalProperties: false,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tdescription: { type: \"string\" },\n\t\t\t\t\t\tdimensions: { type: \"integer\", minimum: 1, maximum: 1536 },\n\t\t\t\t\t\tmetric: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\tenum: [\"cosine\", \"euclidean\", \"dot-product\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tmetadataIndexedFields: {\n\t\t\t\t\ttype: \"array\",\n\t\t\t\t\titems: { type: \"string\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tembeddings: {\n\t\t\ttype: \"object\",\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tmodel: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t\tstorage: {\n\t\t\ttype: \"object\",\n\t\t\tadditionalProperties: false,\n\t\t\tproperties: {\n\t\t\t\tmode: { type: \"string\", enum: [\"vectorize-inline\", \"companion-store\"] },\n\t\t\t\tcompanionStorePath: { type: \"string\" },\n\t\t\t\tinlineTextMaxBytes: { type: \"integer\", minimum: 256, maximum: 10000 },\n\t\t\t},\n\t\t},\n\t},\n} as const;\n\nexport const pluginUiHints = {\n\t\"cloudflare.accountId\": {\n\t\tlabel: \"Cloudflare account ID\",\n\t\thelp: `Defaults to \\${${CLOUDFLARE_ACCOUNT_ID_ENV}}.`,\n\t},\n\t\"cloudflare.apiToken\": {\n\t\tlabel: \"Cloudflare API token\",\n\t\tsensitive: true,\n\t\thelp: `Defaults to \\${${CLOUDFLARE_API_TOKEN_ENV}}.`,\n\t},\n\t\"vectorize.indexName\": {\n\t\tlabel: \"Vectorize index name\",\n\t\thelp: `Defaults to \\${${VECTORIZE_INDEX_ENV}}.`,\n\t},\n\t\"vectorize.namespace\": {\n\t\tlabel: \"Fixed namespace override\",\n\t\thelp: `Defaults to \\${${VECTORIZE_NAMESPACE_ENV}} or derives from the agent/session context.`,\n\t},\n\t\"vectorize.topK\": {\n\t\tlabel: \"Top-K results\",\n\t\thelp: `Defaults to \\${${VECTORIZE_TOP_K_ENV}} or ${DEFAULT_TOP_K}.`,\n\t},\n\t\"embeddings.model\": {\n\t\tlabel: \"Workers AI embedding model\",\n\t\thelp: `Defaults to \\${${WORKERS_AI_MODEL_ENV}} or ${DEFAULT_EMBEDDING_MODEL}.`,\n\t},\n\t\"storage.mode\": {\n\t\tlabel: \"Storage mode\",\n\t\thelp: `Defaults to \\${${STORAGE_MODE_ENV}} or ${DEFAULT_STORAGE_MODE}.`,\n\t},\n\t\"storage.companionStorePath\": {\n\t\tlabel: \"Companion store path\",\n\t\thelp: `Defaults to \\${${COMPANION_PATH_ENV}} or the OpenClaw state directory.`,\n\t},\n} as const;\n\nexport const pluginConfigSchema: OpenClawPluginConfigSchema = {\n\tparse(value: unknown) {\n\t\treturn pluginConfigZod.parse(value ?? {});\n\t},\n\tsafeParse(value: unknown) {\n\t\tconst result = pluginConfigZod.safeParse(value ?? {});\n\t\tif (result.success) {\n\t\t\treturn { success: true, data: result.data };\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tissues: result.error.issues.map((issue) => ({\n\t\t\t\t\tpath: issue.path.filter((segment): segment is string | number => typeof segment === \"string\" || typeof segment === \"number\"),\n\t\t\t\t\tmessage: issue.message,\n\t\t\t\t})),\n\t\t\t},\n\t\t};\n\t},\n\tjsonSchema: pluginConfigJsonSchema,\n\tuiHints: pluginUiHints,\n};\n\ntype PluginEntriesAwareConfig = OpenClawConfig & {\n\tplugins?: {\n\t\tentries?: Record<string, unknown>;\n\t};\n};\n\nconst PLUGIN_CONFIG_ROOT_KEYS = [\"cloudflare\", \"vectorize\", \"embeddings\", \"storage\"] as const satisfies ReadonlyArray<keyof RawPluginConfig>;\n\nfunction unwrapPluginConfigCandidate(value: unknown): unknown {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn value;\n\t}\n\n\tconst candidate = value as Record<string, unknown>;\n\tif (\"config\" in candidate) {\n\t\treturn unwrapPluginConfigCandidate(candidate.config);\n\t}\n\n\tconst directConfig = Object.fromEntries(PLUGIN_CONFIG_ROOT_KEYS.filter((key) => key in candidate).map((key) => [key, candidate[key]]));\n\tif (Object.keys(directConfig).length > 0) {\n\t\treturn directConfig;\n\t}\n\n\tif (\"enabled\" in candidate && Object.keys(candidate).every((key) => key === \"enabled\")) {\n\t\treturn {};\n\t}\n\n\treturn value;\n}\n\nfunction pickFirstDefined<T>(...values: Array<T | undefined>): T | undefined {\n\treturn values.find((value) => value !== undefined);\n}\n\nfunction pickTrimmed(...values: Array<string | undefined>): string | undefined {\n\tfor (const value of values) {\n\t\tif (value && value.trim().length > 0) {\n\t\t\treturn value.trim();\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction pickNumber(...values: Array<number | undefined>): number | undefined {\n\treturn values.find((value) => typeof value === \"number\" && Number.isFinite(value));\n}\n\nfunction normalizeMetadataIndexedFields(fields: string[] | undefined): string[] {\n\treturn [...new Set((fields ?? []).map((field) => field.trim()).filter(Boolean))];\n}\n\nfunction ensureVectorizeMetric(metric: VectorizeMetric | undefined): VectorizeMetric {\n\treturn metric ?? DEFAULT_VECTORIZE_METRIC;\n}\n\nfunction ensureStorageMode(mode: StorageMode | undefined): StorageMode {\n\treturn mode ?? DEFAULT_STORAGE_MODE;\n}\n\nexport function parsePluginConfig(value: unknown): RawPluginConfig {\n\treturn pluginConfigZod.parse(value ?? {});\n}\n\nexport function normalizePluginConfigInput(value: unknown): RawPluginConfig {\n\treturn parsePluginConfig(unwrapPluginConfigCandidate(value) ?? {});\n}\n\nexport function getPluginConfigFromOpenClawConfig(config: OpenClawConfig): RawPluginConfig {\n\tconst candidate = (config as PluginEntriesAwareConfig).plugins?.entries?.[PLUGIN_ID];\n\treturn normalizePluginConfigInput(candidate ?? {});\n}\n\nexport async function resolvePluginConfig(params: {\n\tpluginConfig: unknown;\n\topenClawConfig: OpenClawConfig;\n\tenv?: NodeJS.ProcessEnv;\n\tresolvePath?: (input: string) => string;\n}): Promise<ResolvedPluginConfig> {\n\tconst parsed = normalizePluginConfigInput(params.pluginConfig);\n\tconst env = params.env ?? process.env;\n\tconst configPathBase = `plugins.entries.${PLUGIN_ID}`;\n\tconst accountId = pickTrimmed(parsed.cloudflare?.accountId, env[CLOUDFLARE_ACCOUNT_ID_ENV]);\n\tif (!accountId) {\n\t\tthrow new ConfigurationError(`Missing Cloudflare account id. Set ${CLOUDFLARE_ACCOUNT_ID_ENV} or ${configPathBase}.cloudflare.accountId.`);\n\t}\n\n\tconst tokenResult = await resolveConfiguredSecretInputWithFallback({\n\t\tconfig: params.openClawConfig,\n\t\tenv,\n\t\tvalue: parsed.cloudflare?.apiToken,\n\t\tpath: `${configPathBase}.cloudflare.apiToken`,\n\t\tunresolvedReasonStyle: \"detailed\",\n\t\treadFallback: () => env[CLOUDFLARE_API_TOKEN_ENV],\n\t});\n\tif (!tokenResult.value) {\n\t\tconst reason = tokenResult.unresolvedRefReason ? ` ${tokenResult.unresolvedRefReason}` : \"\";\n\t\tthrow new ConfigurationError(`Missing Cloudflare API token. Set ${CLOUDFLARE_API_TOKEN_ENV} or ${configPathBase}.cloudflare.apiToken.${reason}`.trim());\n\t}\n\n\tconst indexName = pickTrimmed(parsed.vectorize?.indexName, env[VECTORIZE_INDEX_ENV]);\n\tif (!indexName) {\n\t\tthrow new ConfigurationError(`Missing Vectorize index name. Set ${VECTORIZE_INDEX_ENV} or ${configPathBase}.vectorize.indexName.`);\n\t}\n\n\tconst apiBaseUrl = pickTrimmed(parsed.cloudflare?.apiBaseUrl, DEFAULT_CLOUDFLARE_API_BASE_URL);\n\tif (!apiBaseUrl) {\n\t\tthrow new ConfigurationError(\n\t\t\t`Invalid Cloudflare API base URL. Set ${configPathBase}.cloudflare.apiBaseUrl or ensure ${DEFAULT_CLOUDFLARE_API_BASE_URL} is a valid URL.`,\n\t\t);\n\t}\n\tconst fixedNamespace = pickTrimmed(parsed.vectorize?.namespace, env[VECTORIZE_NAMESPACE_ENV]);\n\tconst topK = pickNumber(parsed.vectorize?.topK, env[VECTORIZE_TOP_K_ENV] ? Number(env[VECTORIZE_TOP_K_ENV]) : undefined);\n\tconst storageMode = ensureStorageMode(pickFirstDefined(parsed.storage?.mode, env[STORAGE_MODE_ENV] as StorageMode | undefined));\n\tconst companionStorePath = pickTrimmed(parsed.storage?.companionStorePath, env[COMPANION_PATH_ENV]) ?? join(\".openclaw\", PLUGIN_ID, \"companion-store.json\");\n\n\tconst resolvePath = params.resolvePath ?? ((input: string) => input);\n\tconst model = pickTrimmed(parsed.embeddings?.model, env[WORKERS_AI_MODEL_ENV], DEFAULT_EMBEDDING_MODEL);\n\tif (!model) {\n\t\tthrow new ConfigurationError(`Missing Workers AI embedding model. Set ${WORKERS_AI_MODEL_ENV} or ${configPathBase}.embeddings.model.`);\n\t}\n\tconst inlineTextMaxBytes = pickNumber(parsed.storage?.inlineTextMaxBytes) ?? DEFAULT_INLINE_TEXT_MAX_BYTES;\n\tconst minScore = pickNumber(parsed.vectorize?.minScore) ?? DEFAULT_MIN_SCORE;\n\tconst metric = ensureVectorizeMetric(pickFirstDefined(parsed.vectorize?.metric, parsed.vectorize?.createIndex?.metric));\n\n\treturn {\n\t\taccountId,\n\t\tapiToken: tokenResult.value,\n\t\tapiBaseUrl,\n\t\tworkersAiBaseUrl: pickTrimmed(parsed.cloudflare?.workersAiBaseUrl) ?? `${apiBaseUrl}/accounts/${accountId}/ai/v1`,\n\t\tvectorizeBaseUrl: pickTrimmed(parsed.cloudflare?.vectorizeBaseUrl) ?? `${apiBaseUrl}/accounts/${accountId}/vectorize/v2/indexes/${indexName}`,\n\t\tindexName,\n\t\tfixedNamespace,\n\t\ttopK: topK ?? DEFAULT_TOP_K,\n\t\tminScore,\n\t\tmetric,\n\t\tmodel,\n\t\tstorageMode,\n\t\tcompanionStorePath: resolvePath(companionStorePath),\n\t\tinlineTextMaxBytes,\n\t\tmetadataIndexedFields: normalizeMetadataIndexedFields(parsed.vectorize?.metadataIndexedFields),\n\t\tcreateIndex: {\n\t\t\tdescription: parsed.vectorize?.createIndex?.description ?? DEFAULT_INDEX_DESCRIPTION,\n\t\t\tdimensions: parsed.vectorize?.createIndex?.dimensions,\n\t\t\tmetric,\n\t\t},\n\t};\n}\n"],"mappings":"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"}
@@ -1,6 +1,9 @@
1
1
  import { requestCloudflare as e } from "./cloudflare-api.js";
2
2
  //#region src/embeddings-client.ts
3
- var t = class {
3
+ function t(e) {
4
+ return e.data.every((e) => !!e && typeof e == "object" && "embedding" in e && Array.isArray(e.embedding) && "index" in e && typeof e.index == "number");
5
+ }
6
+ var n = class {
4
7
  constructor(e) {
5
8
  this.config = e;
6
9
  }
@@ -8,21 +11,24 @@ var t = class {
8
11
  let [t] = await this.embedBatch([e]);
9
12
  return t;
10
13
  }
11
- async embedBatch(t) {
12
- return t.length === 0 ? [] : [...(await e({
14
+ async embedBatch(n) {
15
+ if (n.length === 0) return [];
16
+ let r = await e({
13
17
  url: `${this.config.workersAiBaseUrl}/embeddings`,
14
18
  apiToken: this.config.apiToken,
15
19
  body: JSON.stringify({
16
20
  model: this.config.model,
17
- input: t
18
- })
19
- })).data].sort((e, t) => e.index - t.index).map((e) => e.embedding);
21
+ input: n
22
+ }),
23
+ responseMode: "auto"
24
+ });
25
+ return t(r) ? [...r.data].sort((e, t) => e.index - t.index).map((e) => e.embedding) : r.data;
20
26
  }
21
27
  async probeDimensions() {
22
28
  return (await this.embedQuery("openclaw-memory-dimension-probe")).length;
23
29
  }
24
30
  };
25
31
  //#endregion
26
- export { t as WorkersAiEmbeddingsClient };
32
+ export { n as WorkersAiEmbeddingsClient };
27
33
 
28
34
  //# sourceMappingURL=embeddings-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"embeddings-client.js","names":[],"sources":["../src/embeddings-client.ts"],"sourcesContent":["import { requestCloudflare } from \"./cloudflare-api.js\";\nimport type { ResolvedPluginConfig } from \"./types.js\";\n\ntype OpenAiEmbeddingResponse = {\n\tdata: Array<{\n\t\tembedding: number[];\n\t\tindex: number;\n\t}>;\n};\n\nexport class WorkersAiEmbeddingsClient {\n\tconstructor(private readonly config: ResolvedPluginConfig) {}\n\n\tasync embedQuery(text: string): Promise<number[]> {\n\t\tconst [embedding] = await this.embedBatch([text]);\n\t\treturn embedding;\n\t}\n\n\tasync embedBatch(texts: string[]): Promise<number[][]> {\n\t\tif (texts.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\tconst response = await requestCloudflare<OpenAiEmbeddingResponse>({\n\t\t\turl: `${this.config.workersAiBaseUrl}/embeddings`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmodel: this.config.model,\n\t\t\t\tinput: texts,\n\t\t\t}),\n\t\t});\n\n\t\treturn [...response.data].sort((left, right) => left.index - right.index).map((entry) => entry.embedding);\n\t}\n\n\tasync probeDimensions(): Promise<number> {\n\t\tconst embedding = await this.embedQuery(\"openclaw-memory-dimension-probe\");\n\t\treturn embedding.length;\n\t}\n}\n"],"mappings":";;AAUA,IAAa,IAAb,MAAuC;CACtC,YAAY,GAA+C;AAA9B,OAAA,SAAA;;CAE7B,MAAM,WAAW,GAAiC;EACjD,IAAM,CAAC,KAAa,MAAM,KAAK,WAAW,CAAC,EAAK,CAAC;AACjD,SAAO;;CAGR,MAAM,WAAW,GAAsC;AAatD,SAZI,EAAM,WAAW,IACb,EAAE,GAWH,CAAC,IATS,MAAM,EAA2C;GACjE,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU;IACpB,OAAO,KAAK,OAAO;IACnB,OAAO;IACP,CAAC;GACF,CAAC,EAEkB,KAAK,CAAC,MAAM,GAAM,MAAU,EAAK,QAAQ,EAAM,MAAM,CAAC,KAAK,MAAU,EAAM,UAAU;;CAG1G,MAAM,kBAAmC;AAExC,UADkB,MAAM,KAAK,WAAW,kCAAkC,EACzD"}
1
+ {"version":3,"file":"embeddings-client.js","names":[],"sources":["../src/embeddings-client.ts"],"sourcesContent":["import { requestCloudflare } from \"./cloudflare-api.js\";\nimport type { ResolvedPluginConfig } from \"./types.js\";\n\ntype OpenAiEmbeddingResponse = {\n\tdata: Array<{\n\t\tembedding: number[];\n\t\tindex: number;\n\t}>;\n};\n\ntype NativeEmbeddingResponse = {\n\tdata: number[][];\n\tshape?: number[];\n};\n\ntype EmbeddingResponse = OpenAiEmbeddingResponse | NativeEmbeddingResponse;\n\nfunction isOpenAiEmbeddingResponse(response: EmbeddingResponse): response is OpenAiEmbeddingResponse {\n\treturn response.data.every(\n\t\t(entry) =>\n\t\t\tBoolean(entry) &&\n\t\t\ttypeof entry === \"object\" &&\n\t\t\t\"embedding\" in entry &&\n\t\t\tArray.isArray(entry.embedding) &&\n\t\t\t\"index\" in entry &&\n\t\t\ttypeof entry.index === \"number\",\n\t);\n}\n\nexport class WorkersAiEmbeddingsClient {\n\tconstructor(private readonly config: ResolvedPluginConfig) {}\n\n\tasync embedQuery(text: string): Promise<number[]> {\n\t\tconst [embedding] = await this.embedBatch([text]);\n\t\treturn embedding;\n\t}\n\n\tasync embedBatch(texts: string[]): Promise<number[][]> {\n\t\tif (texts.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\tconst response = await requestCloudflare<EmbeddingResponse>({\n\t\t\turl: `${this.config.workersAiBaseUrl}/embeddings`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmodel: this.config.model,\n\t\t\t\tinput: texts,\n\t\t\t}),\n\t\t\tresponseMode: \"auto\",\n\t\t});\n\n\t\tif (isOpenAiEmbeddingResponse(response)) {\n\t\t\treturn [...response.data].sort((left, right) => left.index - right.index).map((entry) => entry.embedding);\n\t\t}\n\n\t\treturn response.data;\n\t}\n\n\tasync probeDimensions(): Promise<number> {\n\t\tconst embedding = await this.embedQuery(\"openclaw-memory-dimension-probe\");\n\t\treturn embedding.length;\n\t}\n}\n"],"mappings":";;AAiBA,SAAS,EAA0B,GAAkE;AACpG,QAAO,EAAS,KAAK,OACnB,MACA,EAAQ,KACR,OAAO,KAAU,YACjB,eAAe,KACf,MAAM,QAAQ,EAAM,UAAU,IAC9B,WAAW,KACX,OAAO,EAAM,SAAU,SACxB;;AAGF,IAAa,IAAb,MAAuC;CACtC,YAAY,GAA+C;AAA9B,OAAA,SAAA;;CAE7B,MAAM,WAAW,GAAiC;EACjD,IAAM,CAAC,KAAa,MAAM,KAAK,WAAW,CAAC,EAAK,CAAC;AACjD,SAAO;;CAGR,MAAM,WAAW,GAAsC;AACtD,MAAI,EAAM,WAAW,EACpB,QAAO,EAAE;EAEV,IAAM,IAAW,MAAM,EAAqC;GAC3D,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU;IACpB,OAAO,KAAK,OAAO;IACnB,OAAO;IACP,CAAC;GACF,cAAc;GACd,CAAC;AAMF,SAJI,EAA0B,EAAS,GAC/B,CAAC,GAAG,EAAS,KAAK,CAAC,MAAM,GAAM,MAAU,EAAK,QAAQ,EAAM,MAAM,CAAC,KAAK,MAAU,EAAM,UAAU,GAGnG,EAAS;;CAGjB,MAAM,kBAAmC;AAExC,UADkB,MAAM,KAAK,WAAW,kCAAkC,EACzD"}
package/dist/index.js CHANGED
@@ -1,42 +1,46 @@
1
1
  import { CLI_ROOT_COMMAND as e, CLI_ROOT_DESCRIPTOR as t, DEFAULT_EMBEDDING_MODEL as n, PLUGIN_DESCRIPTION as r, PLUGIN_ID as i, PLUGIN_NAME as a } from "./constants.js";
2
- import { getPluginConfigFromOpenClawConfig as o, pluginConfigSchema as s, resolvePluginConfig as c } from "./config.js";
3
- import { CloudflareMemoryService as l } from "./service.js";
4
- import { registerCloudflareMemoryCli as u } from "./cli.js";
5
- import { buildPromptSection as d } from "./prompt.js";
6
- import { createPublicArtifactsProvider as f } from "./public-artifacts.js";
7
- import { createMemoryRuntime as p } from "./runtime.js";
8
- import { createDeleteTool as m, createGetTool as h, createSearchTool as g, createUpsertTool as _ } from "./tools.js";
9
- import { definePluginEntry as v } from "openclaw/plugin-sdk/plugin-entry";
2
+ import { pluginConfigSchema as o } from "./config.js";
3
+ import { createCloudflareMemoryService as s, resolveCloudflareMemoryServiceConfig as c } from "./service-factory.js";
4
+ import { registerCloudflareMemoryCli as l } from "./cli.js";
5
+ import { buildPromptSection as u } from "./prompt.js";
6
+ import { createPublicArtifactsProvider as d } from "./public-artifacts.js";
7
+ import { createMemoryRuntime as f } from "./runtime.js";
8
+ import { createDeleteTool as p, createGetTool as m, createSearchTool as h, createUpsertTool as g } from "./tools.js";
9
+ import { definePluginEntry as _ } from "openclaw/plugin-sdk/plugin-entry";
10
10
  //#region src/index.ts
11
- function y() {
11
+ function v(e) {
12
+ return e && e.trim().length > 0 ? e.trim() : void 0;
13
+ }
14
+ function y(e) {
12
15
  return {
13
16
  id: "cloudflare-workers-ai",
14
17
  defaultModel: n,
15
18
  transport: "remote",
16
19
  allowExplicitWhenConfiguredAuto: !0,
17
- async create(e) {
18
- let t = await c({
19
- pluginConfig: o(e.config),
20
- openClawConfig: e.config,
21
- env: process.env
22
- }), n = new l({
23
- ...t,
24
- model: e.model || t.model,
25
- workersAiBaseUrl: e.remote?.baseUrl && e.remote.baseUrl.trim().length > 0 ? e.remote.baseUrl : t.workersAiBaseUrl,
26
- apiToken: typeof e.remote?.apiKey == "string" && e.remote.apiKey.trim().length > 0 ? e.remote.apiKey : t.apiToken
27
- }, e.config);
20
+ async create(t) {
21
+ let n = await s({
22
+ pluginConfig: e.pluginConfig,
23
+ openClawConfig: t.config,
24
+ env: process.env,
25
+ resolvePath: e.resolvePath,
26
+ overrides: {
27
+ model: t.model || void 0,
28
+ workersAiBaseUrl: v(t.remote?.baseUrl),
29
+ apiToken: typeof t.remote?.apiKey == "string" ? v(t.remote.apiKey) : void 0
30
+ }
31
+ });
28
32
  return {
29
33
  provider: {
30
34
  id: "cloudflare-workers-ai",
31
- model: e.model || t.model,
35
+ model: n.config.model,
32
36
  embedQuery: (e) => n.embeddings.embedQuery(e),
33
37
  embedBatch: (e) => n.embeddings.embedBatch(e)
34
38
  },
35
39
  runtime: {
36
40
  id: "cloudflare-workers-ai",
37
41
  cacheKeyData: {
38
- accountId: t.accountId,
39
- model: e.model || t.model
42
+ accountId: n.config.accountId,
43
+ model: n.config.model
40
44
  }
41
45
  }
42
46
  };
@@ -45,28 +49,43 @@ function y() {
45
49
  }
46
50
  function b(n) {
47
51
  n.registerCli(({ program: e }) => {
48
- u(e, {
52
+ l(e, {
49
53
  pluginConfig: n.pluginConfig,
50
54
  openClawConfig: n.config,
51
55
  resolvePath: n.resolvePath
52
56
  });
53
57
  }, n.registrationMode === "cli-metadata" ? { descriptors: [t] } : { commands: [e] });
54
58
  }
55
- var x = v({
59
+ var x = _({
56
60
  id: i,
57
61
  name: a,
58
62
  description: r,
59
63
  kind: "memory",
60
- configSchema: s,
64
+ configSchema: o,
61
65
  register(e) {
62
- s.parse?.(e.pluginConfig ?? {}), b(e), !(e.registrationMode === "cli-metadata" || typeof e.registerMemoryEmbeddingProvider != "function" || typeof e.registerMemoryCapability != "function" || typeof e.registerTool != "function") && (e.registerMemoryEmbeddingProvider(y()), e.registerMemoryCapability({
63
- promptBuilder: d,
64
- runtime: p({
66
+ o.parse?.(e.pluginConfig ?? {}), b(e), !(e.registrationMode === "cli-metadata" || typeof e.registerMemoryEmbeddingProvider != "function" || typeof e.registerMemoryCapability != "function" || typeof e.registerTool != "function") && (e.registerMemoryEmbeddingProvider(y({
67
+ pluginConfig: e.pluginConfig,
68
+ resolvePath: e.resolvePath
69
+ })), e.registerMemoryCapability({
70
+ promptBuilder: u,
71
+ runtime: f({
65
72
  pluginConfig: e.pluginConfig,
66
73
  resolvePath: e.resolvePath
67
74
  }),
68
- publicArtifacts: f(e.pluginConfig, e.resolvePath)
69
- }), e.registerTool((t) => g(e.pluginConfig, t), { names: ["cloudflare_memory_search"] }), e.registerTool((t) => h(e.pluginConfig, t), { names: ["cloudflare_memory_get"] }), e.registerTool((t) => _(e.pluginConfig, t), { names: ["cloudflare_memory_upsert"] }), e.registerTool((t) => m(e.pluginConfig, t), { names: ["cloudflare_memory_delete"] }), c({
75
+ publicArtifacts: d(e.pluginConfig, e.resolvePath)
76
+ }), e.registerTool((t) => h({
77
+ pluginConfig: e.pluginConfig,
78
+ resolvePath: e.resolvePath
79
+ }, t), { names: ["cloudflare_memory_search"] }), e.registerTool((t) => m({
80
+ pluginConfig: e.pluginConfig,
81
+ resolvePath: e.resolvePath
82
+ }, t), { names: ["cloudflare_memory_get"] }), e.registerTool((t) => g({
83
+ pluginConfig: e.pluginConfig,
84
+ resolvePath: e.resolvePath
85
+ }, t), { names: ["cloudflare_memory_upsert"] }), e.registerTool((t) => p({
86
+ pluginConfig: e.pluginConfig,
87
+ resolvePath: e.resolvePath
88
+ }, t), { names: ["cloudflare_memory_delete"] }), c({
70
89
  pluginConfig: e.pluginConfig,
71
90
  openClawConfig: e.config,
72
91
  env: process.env,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { MemoryEmbeddingProviderAdapter } from \"openclaw/plugin-sdk/memory-core-host-engine-embeddings\";\nimport { definePluginEntry, type OpenClawPluginApi } from \"openclaw/plugin-sdk/plugin-entry\";\nimport { registerCloudflareMemoryCli } from \"./cli.js\";\nimport { getPluginConfigFromOpenClawConfig, pluginConfigSchema, resolvePluginConfig } from \"./config.js\";\nimport { CLI_ROOT_COMMAND, CLI_ROOT_DESCRIPTOR, DEFAULT_EMBEDDING_MODEL, PLUGIN_DESCRIPTION, PLUGIN_ID, PLUGIN_NAME } from \"./constants.js\";\nimport { buildPromptSection } from \"./prompt.js\";\nimport { createPublicArtifactsProvider } from \"./public-artifacts.js\";\nimport { createMemoryRuntime } from \"./runtime.js\";\nimport { CloudflareMemoryService } from \"./service.js\";\nimport { createDeleteTool, createGetTool, createSearchTool, createUpsertTool } from \"./tools.js\";\n\nfunction createMemoryEmbeddingProviderAdapter(): MemoryEmbeddingProviderAdapter {\n\treturn {\n\t\tid: \"cloudflare-workers-ai\",\n\t\tdefaultModel: DEFAULT_EMBEDDING_MODEL,\n\t\ttransport: \"remote\",\n\t\tallowExplicitWhenConfiguredAuto: true,\n\t\tasync create(options) {\n\t\t\tconst pluginConfig = getPluginConfigFromOpenClawConfig(options.config);\n\t\t\tconst resolved = await resolvePluginConfig({\n\t\t\t\tpluginConfig,\n\t\t\t\topenClawConfig: options.config,\n\t\t\t\tenv: process.env,\n\t\t\t});\n\t\t\tconst service = new CloudflareMemoryService(\n\t\t\t\t{\n\t\t\t\t\t...resolved,\n\t\t\t\t\tmodel: options.model || resolved.model,\n\t\t\t\t\tworkersAiBaseUrl: options.remote?.baseUrl && options.remote.baseUrl.trim().length > 0 ? options.remote.baseUrl : resolved.workersAiBaseUrl,\n\t\t\t\t\tapiToken: typeof options.remote?.apiKey === \"string\" && options.remote.apiKey.trim().length > 0 ? options.remote.apiKey : resolved.apiToken,\n\t\t\t\t},\n\t\t\t\toptions.config,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tprovider: {\n\t\t\t\t\tid: \"cloudflare-workers-ai\",\n\t\t\t\t\tmodel: options.model || resolved.model,\n\t\t\t\t\tembedQuery: (text) => service.embeddings.embedQuery(text),\n\t\t\t\t\tembedBatch: (texts) => service.embeddings.embedBatch(texts),\n\t\t\t\t},\n\t\t\t\truntime: {\n\t\t\t\t\tid: \"cloudflare-workers-ai\",\n\t\t\t\t\tcacheKeyData: {\n\t\t\t\t\t\taccountId: resolved.accountId,\n\t\t\t\t\t\tmodel: options.model || resolved.model,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction registerCloudflareMemoryCliEntry(api: Pick<OpenClawPluginApi, \"registerCli\" | \"pluginConfig\" | \"config\" | \"resolvePath\" | \"registrationMode\">): void {\n\tapi.registerCli(\n\t\t({ program }) => {\n\t\t\tregisterCloudflareMemoryCli(program, {\n\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\topenClawConfig: api.config,\n\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t});\n\t\t},\n\t\tapi.registrationMode === \"cli-metadata\"\n\t\t\t? {\n\t\t\t\t\tdescriptors: [CLI_ROOT_DESCRIPTOR],\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tcommands: [CLI_ROOT_COMMAND],\n\t\t\t\t},\n\t);\n}\n\nexport default definePluginEntry({\n\tid: PLUGIN_ID,\n\tname: PLUGIN_NAME,\n\tdescription: PLUGIN_DESCRIPTION,\n\tkind: \"memory\",\n\tconfigSchema: pluginConfigSchema,\n\tregister(api: OpenClawPluginApi) {\n\t\tpluginConfigSchema.parse?.(api.pluginConfig ?? {});\n\n\t\tregisterCloudflareMemoryCliEntry(api);\n\n\t\tif (\n\t\t\tapi.registrationMode === \"cli-metadata\" ||\n\t\t\ttypeof api.registerMemoryEmbeddingProvider !== \"function\" ||\n\t\t\ttypeof api.registerMemoryCapability !== \"function\" ||\n\t\t\ttypeof api.registerTool !== \"function\"\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tapi.registerMemoryEmbeddingProvider(createMemoryEmbeddingProviderAdapter());\n\t\tapi.registerMemoryCapability({\n\t\t\tpromptBuilder: buildPromptSection,\n\t\t\truntime: createMemoryRuntime({\n\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t}),\n\t\t\tpublicArtifacts: createPublicArtifactsProvider(api.pluginConfig, api.resolvePath),\n\t\t});\n\n\t\tapi.registerTool((ctx) => createSearchTool(api.pluginConfig, ctx), {\n\t\t\tnames: [\"cloudflare_memory_search\"],\n\t\t});\n\t\tapi.registerTool((ctx) => createGetTool(api.pluginConfig, ctx), {\n\t\t\tnames: [\"cloudflare_memory_get\"],\n\t\t});\n\t\tapi.registerTool((ctx) => createUpsertTool(api.pluginConfig, ctx), {\n\t\t\tnames: [\"cloudflare_memory_upsert\"],\n\t\t});\n\t\tapi.registerTool((ctx) => createDeleteTool(api.pluginConfig, ctx), {\n\t\t\tnames: [\"cloudflare_memory_delete\"],\n\t\t});\n\n\t\tvoid resolvePluginConfig({\n\t\t\tpluginConfig: api.pluginConfig,\n\t\t\topenClawConfig: api.config,\n\t\t\tenv: process.env,\n\t\t\tresolvePath: api.resolvePath,\n\t\t})\n\t\t\t.then((resolved) => {\n\t\t\t\tapi.logger.info(`${PLUGIN_ID}: registered for index ${resolved.indexName} using model ${resolved.model}.`);\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tconst message = error instanceof Error ? error.message : \"Unknown configuration error.\";\n\t\t\t\tapi.logger.warn(`${PLUGIN_ID}: deferred config validation reported: ${message}`);\n\t\t\t});\n\t},\n});\n"],"mappings":";;;;;;;;;;AAWA,SAAS,IAAuE;AAC/E,QAAO;EACN,IAAI;EACJ,cAAc;EACd,WAAW;EACX,iCAAiC;EACjC,MAAM,OAAO,GAAS;GAErB,IAAM,IAAW,MAAM,EAAoB;IAC1C,cAFoB,EAAkC,EAAQ,OAAO;IAGrE,gBAAgB,EAAQ;IACxB,KAAK,QAAQ;IACb,CAAC,EACI,IAAU,IAAI,EACnB;IACC,GAAG;IACH,OAAO,EAAQ,SAAS,EAAS;IACjC,kBAAkB,EAAQ,QAAQ,WAAW,EAAQ,OAAO,QAAQ,MAAM,CAAC,SAAS,IAAI,EAAQ,OAAO,UAAU,EAAS;IAC1H,UAAU,OAAO,EAAQ,QAAQ,UAAW,YAAY,EAAQ,OAAO,OAAO,MAAM,CAAC,SAAS,IAAI,EAAQ,OAAO,SAAS,EAAS;IACnI,EACD,EAAQ,OACR;AACD,UAAO;IACN,UAAU;KACT,IAAI;KACJ,OAAO,EAAQ,SAAS,EAAS;KACjC,aAAa,MAAS,EAAQ,WAAW,WAAW,EAAK;KACzD,aAAa,MAAU,EAAQ,WAAW,WAAW,EAAM;KAC3D;IACD,SAAS;KACR,IAAI;KACJ,cAAc;MACb,WAAW,EAAS;MACpB,OAAO,EAAQ,SAAS,EAAS;MACjC;KACD;IACD;;EAEF;;AAGF,SAAS,EAAiC,GAAoH;AAC7J,GAAI,aACF,EAAE,iBAAc;AAChB,IAA4B,GAAS;GACpC,cAAc,EAAI;GAClB,gBAAgB,EAAI;GACpB,aAAa,EAAI;GACjB,CAAC;IAEH,EAAI,qBAAqB,iBACtB,EACA,aAAa,CAAC,EAAoB,EAClC,GACA,EACA,UAAU,CAAC,EAAiB,EAC5B,CACH;;AAGF,IAAA,IAAe,EAAkB;CAChC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,MAAM;CACN,cAAc;CACd,SAAS,GAAwB;AAChC,IAAmB,QAAQ,EAAI,gBAAgB,EAAE,CAAC,EAElD,EAAiC,EAAI,EAGpC,IAAI,qBAAqB,kBACzB,OAAO,EAAI,mCAAoC,cAC/C,OAAO,EAAI,4BAA6B,cACxC,OAAO,EAAI,gBAAiB,gBAK7B,EAAI,gCAAgC,GAAsC,CAAC,EAC3E,EAAI,yBAAyB;GAC5B,eAAe;GACf,SAAS,EAAoB;IAC5B,cAAc,EAAI;IAClB,aAAa,EAAI;IACjB,CAAC;GACF,iBAAiB,EAA8B,EAAI,cAAc,EAAI,YAAY;GACjF,CAAC,EAEF,EAAI,cAAc,MAAQ,EAAiB,EAAI,cAAc,EAAI,EAAE,EAClE,OAAO,CAAC,2BAA2B,EACnC,CAAC,EACF,EAAI,cAAc,MAAQ,EAAc,EAAI,cAAc,EAAI,EAAE,EAC/D,OAAO,CAAC,wBAAwB,EAChC,CAAC,EACF,EAAI,cAAc,MAAQ,EAAiB,EAAI,cAAc,EAAI,EAAE,EAClE,OAAO,CAAC,2BAA2B,EACnC,CAAC,EACF,EAAI,cAAc,MAAQ,EAAiB,EAAI,cAAc,EAAI,EAAE,EAClE,OAAO,CAAC,2BAA2B,EACnC,CAAC,EAEG,EAAoB;GACxB,cAAc,EAAI;GAClB,gBAAgB,EAAI;GACpB,KAAK,QAAQ;GACb,aAAa,EAAI;GACjB,CAAC,CACA,MAAM,MAAa;AACnB,KAAI,OAAO,KAAK,GAAG,EAAU,yBAAyB,EAAS,UAAU,eAAe,EAAS,MAAM,GAAG;IACzG,CACD,OAAO,MAAmB;GAC1B,IAAM,IAAU,aAAiB,QAAQ,EAAM,UAAU;AACzD,KAAI,OAAO,KAAK,GAAG,EAAU,yCAAyC,IAAU;IAC/E;;CAEJ,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { MemoryEmbeddingProviderAdapter } from \"openclaw/plugin-sdk/memory-core-host-engine-embeddings\";\nimport { definePluginEntry, type OpenClawPluginApi } from \"openclaw/plugin-sdk/plugin-entry\";\nimport { registerCloudflareMemoryCli } from \"./cli.js\";\nimport { pluginConfigSchema } from \"./config.js\";\nimport { CLI_ROOT_COMMAND, CLI_ROOT_DESCRIPTOR, DEFAULT_EMBEDDING_MODEL, PLUGIN_DESCRIPTION, PLUGIN_ID, PLUGIN_NAME } from \"./constants.js\";\nimport { buildPromptSection } from \"./prompt.js\";\nimport { createPublicArtifactsProvider } from \"./public-artifacts.js\";\nimport { createMemoryRuntime } from \"./runtime.js\";\nimport { createCloudflareMemoryService, resolveCloudflareMemoryServiceConfig } from \"./service-factory.js\";\nimport { createDeleteTool, createGetTool, createSearchTool, createUpsertTool } from \"./tools.js\";\n\nfunction pickTrimmed(value: string | undefined): string | undefined {\n\treturn value && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction createMemoryEmbeddingProviderAdapter(params: { pluginConfig: unknown; resolvePath?: (input: string) => string }): MemoryEmbeddingProviderAdapter {\n\treturn {\n\t\tid: \"cloudflare-workers-ai\",\n\t\tdefaultModel: DEFAULT_EMBEDDING_MODEL,\n\t\ttransport: \"remote\",\n\t\tallowExplicitWhenConfiguredAuto: true,\n\t\tasync create(options) {\n\t\t\tconst service = await createCloudflareMemoryService({\n\t\t\t\tpluginConfig: params.pluginConfig,\n\t\t\t\topenClawConfig: options.config,\n\t\t\t\tenv: process.env,\n\t\t\t\tresolvePath: params.resolvePath,\n\t\t\t\toverrides: {\n\t\t\t\t\tmodel: options.model || undefined,\n\t\t\t\t\tworkersAiBaseUrl: pickTrimmed(options.remote?.baseUrl),\n\t\t\t\t\tapiToken: typeof options.remote?.apiKey === \"string\" ? pickTrimmed(options.remote.apiKey) : undefined,\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tprovider: {\n\t\t\t\t\tid: \"cloudflare-workers-ai\",\n\t\t\t\t\tmodel: service.config.model,\n\t\t\t\t\tembedQuery: (text) => service.embeddings.embedQuery(text),\n\t\t\t\t\tembedBatch: (texts) => service.embeddings.embedBatch(texts),\n\t\t\t\t},\n\t\t\t\truntime: {\n\t\t\t\t\tid: \"cloudflare-workers-ai\",\n\t\t\t\t\tcacheKeyData: {\n\t\t\t\t\t\taccountId: service.config.accountId,\n\t\t\t\t\t\tmodel: service.config.model,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction registerCloudflareMemoryCliEntry(api: Pick<OpenClawPluginApi, \"registerCli\" | \"pluginConfig\" | \"config\" | \"resolvePath\" | \"registrationMode\">): void {\n\tapi.registerCli(\n\t\t({ program }) => {\n\t\t\tregisterCloudflareMemoryCli(program, {\n\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\topenClawConfig: api.config,\n\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t});\n\t\t},\n\t\tapi.registrationMode === \"cli-metadata\"\n\t\t\t? {\n\t\t\t\t\tdescriptors: [CLI_ROOT_DESCRIPTOR],\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tcommands: [CLI_ROOT_COMMAND],\n\t\t\t\t},\n\t);\n}\n\nexport default definePluginEntry({\n\tid: PLUGIN_ID,\n\tname: PLUGIN_NAME,\n\tdescription: PLUGIN_DESCRIPTION,\n\tkind: \"memory\",\n\tconfigSchema: pluginConfigSchema,\n\tregister(api: OpenClawPluginApi) {\n\t\tpluginConfigSchema.parse?.(api.pluginConfig ?? {});\n\n\t\tregisterCloudflareMemoryCliEntry(api);\n\n\t\tif (\n\t\t\tapi.registrationMode === \"cli-metadata\" ||\n\t\t\ttypeof api.registerMemoryEmbeddingProvider !== \"function\" ||\n\t\t\ttypeof api.registerMemoryCapability !== \"function\" ||\n\t\t\ttypeof api.registerTool !== \"function\"\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tapi.registerMemoryEmbeddingProvider(\n\t\t\tcreateMemoryEmbeddingProviderAdapter({\n\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t}),\n\t\t);\n\t\tapi.registerMemoryCapability({\n\t\t\tpromptBuilder: buildPromptSection,\n\t\t\truntime: createMemoryRuntime({\n\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t}),\n\t\t\tpublicArtifacts: createPublicArtifactsProvider(api.pluginConfig, api.resolvePath),\n\t\t});\n\n\t\tapi.registerTool(\n\t\t\t(ctx) =>\n\t\t\t\tcreateSearchTool(\n\t\t\t\t\t{\n\t\t\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t\t\t},\n\t\t\t\t\tctx,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\tnames: [\"cloudflare_memory_search\"],\n\t\t\t},\n\t\t);\n\t\tapi.registerTool(\n\t\t\t(ctx) =>\n\t\t\t\tcreateGetTool(\n\t\t\t\t\t{\n\t\t\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t\t\t},\n\t\t\t\t\tctx,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\tnames: [\"cloudflare_memory_get\"],\n\t\t\t},\n\t\t);\n\t\tapi.registerTool(\n\t\t\t(ctx) =>\n\t\t\t\tcreateUpsertTool(\n\t\t\t\t\t{\n\t\t\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t\t\t},\n\t\t\t\t\tctx,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\tnames: [\"cloudflare_memory_upsert\"],\n\t\t\t},\n\t\t);\n\t\tapi.registerTool(\n\t\t\t(ctx) =>\n\t\t\t\tcreateDeleteTool(\n\t\t\t\t\t{\n\t\t\t\t\t\tpluginConfig: api.pluginConfig,\n\t\t\t\t\t\tresolvePath: api.resolvePath,\n\t\t\t\t\t},\n\t\t\t\t\tctx,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\tnames: [\"cloudflare_memory_delete\"],\n\t\t\t},\n\t\t);\n\n\t\tvoid resolveCloudflareMemoryServiceConfig({\n\t\t\tpluginConfig: api.pluginConfig,\n\t\t\topenClawConfig: api.config,\n\t\t\tenv: process.env,\n\t\t\tresolvePath: api.resolvePath,\n\t\t})\n\t\t\t.then((resolved) => {\n\t\t\t\tapi.logger.info(`${PLUGIN_ID}: registered for index ${resolved.indexName} using model ${resolved.model}.`);\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tconst message = error instanceof Error ? error.message : \"Unknown configuration error.\";\n\t\t\t\tapi.logger.warn(`${PLUGIN_ID}: deferred config validation reported: ${message}`);\n\t\t\t});\n\t},\n});\n"],"mappings":"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"}
@@ -1,35 +1,36 @@
1
1
  import { RESERVED_METADATA_KEYS as e } from "./constants.js";
2
2
  import { RecordSizeError as t } from "./errors.js";
3
- import { randomUUID as n } from "node:crypto";
4
- import { Buffer as r } from "node:buffer";
3
+ import { createHash as n, randomUUID as r } from "node:crypto";
4
+ import { Buffer as i } from "node:buffer";
5
5
  //#region src/record-mapper.ts
6
- function i(e) {
6
+ function a(e) {
7
7
  let t = e.trim().replace(/[.$"]/g, "_").replace(/\s+/g, "_");
8
8
  return t ? t.startsWith("oc_") ? `user_${t}` : t : "metadata";
9
9
  }
10
- function a(e) {
10
+ function o(e) {
11
11
  if (!e) return {};
12
12
  let t = Object.entries(e).filter(([, e]) => [
13
13
  "string",
14
14
  "number",
15
15
  "boolean"
16
16
  ].includes(typeof e));
17
- return Object.fromEntries(t.map(([e, t]) => [i(e), t]));
18
- }
19
- function o(e, t) {
20
- return `${e}::${t}`;
17
+ return Object.fromEntries(t.map(([e, t]) => [a(e), t]));
21
18
  }
22
19
  function s(e, t) {
20
+ let r = `${e}::${t}`;
21
+ return i.byteLength(r, "utf8") <= 64 ? r : `cfm_${n("sha256").update(r).digest("hex").slice(0, 48)}`;
22
+ }
23
+ function c(e, t) {
23
24
  return `${e}/${t}.md`;
24
25
  }
25
- function c(e) {
26
+ function l(e) {
26
27
  let t = e.replace(/\\/g, "/").replace(/^\//, "").split("/");
27
28
  return t.length !== 2 || !t[1].endsWith(".md") ? null : {
28
29
  namespace: t[0],
29
30
  logicalId: t[1].slice(0, -3)
30
31
  };
31
32
  }
32
- function l(e, t) {
33
+ function u(e, t) {
33
34
  let n = e.trim().replace(/\s+/g, " ");
34
35
  if (!n) return "";
35
36
  let r = n.toLowerCase().indexOf(t.trim().toLowerCase());
@@ -37,47 +38,47 @@ function l(e, t) {
37
38
  let i = Math.max(0, r - 80), a = Math.min(n.length, r + Math.max(t.length, 40) + 80);
38
39
  return n.slice(i, a);
39
40
  }
40
- function u(i) {
41
- let c = i.input.id?.trim() || n(), l = o(i.namespace, c), u = (/* @__PURE__ */ new Date()).toISOString(), d = a(i.input.metadata), f = {
41
+ function d(n) {
42
+ let a = n.input.id?.trim() || r(), l = s(n.namespace, a), u = (/* @__PURE__ */ new Date()).toISOString(), d = o(n.input.metadata), f = {
42
43
  ...d,
43
- [e.logicalId]: c,
44
- [e.storageMode]: i.config.storageMode,
44
+ [e.logicalId]: a,
45
+ [e.storageMode]: n.config.storageMode,
45
46
  [e.createdAt]: u,
46
47
  [e.updatedAt]: u
47
48
  };
48
- i.input.title && (f[e.title] = i.input.title), i.input.source && (f[e.source] = i.input.source);
49
+ n.input.title && (f[e.title] = n.input.title), n.input.source && (f[e.source] = n.input.source);
49
50
  let p;
50
- if (i.config.storageMode === "vectorize-inline") {
51
- let n = r.byteLength(i.input.text, "utf8");
52
- if (n > i.config.inlineTextMaxBytes) throw new t(`Memory text is ${n} bytes, which exceeds the inline metadata limit of ${i.config.inlineTextMaxBytes}. Switch storage.mode to "companion-store" or reduce the payload size.`);
53
- f[e.text] = i.input.text;
51
+ if (n.config.storageMode === "vectorize-inline") {
52
+ let r = i.byteLength(n.input.text, "utf8");
53
+ if (r > n.config.inlineTextMaxBytes) throw new t(`Memory text is ${r} bytes, which exceeds the inline metadata limit of ${n.config.inlineTextMaxBytes}. Switch storage.mode to "companion-store" or reduce the payload size.`);
54
+ f[e.text] = n.input.text;
54
55
  } else {
55
- let t = s(i.namespace, c);
56
+ let t = c(n.namespace, a);
56
57
  f[e.pointer] = t, p = {
57
- id: c,
58
- namespace: i.namespace,
59
- title: i.input.title,
60
- text: i.input.text,
58
+ id: a,
59
+ namespace: n.namespace,
60
+ title: n.input.title,
61
+ text: n.input.text,
61
62
  metadata: d,
62
- source: i.input.source,
63
+ source: n.input.source,
63
64
  createdAt: u,
64
65
  updatedAt: u
65
66
  };
66
67
  }
67
68
  return {
68
- logicalId: c,
69
+ logicalId: a,
69
70
  vectorId: l,
70
- path: s(i.namespace, c),
71
+ path: c(n.namespace, a),
71
72
  vector: {
72
73
  id: l,
73
- namespace: i.namespace,
74
- values: i.embedding,
74
+ namespace: n.namespace,
75
+ values: n.embedding,
75
76
  metadata: f
76
77
  },
77
78
  companionRecord: p
78
79
  };
79
80
  }
80
- function d(t) {
81
+ function f(t) {
81
82
  let n = t.metadata ?? {}, r = t.namespace ?? (typeof n[e.pointer] == "string" ? String(n[e.pointer]).split("/")[0] : "main"), i = typeof n[e.logicalId] == "string" ? String(n[e.logicalId]) : String(t.id ?? ""), a = Object.fromEntries(Object.entries(n).filter(([e]) => !e.startsWith("oc_")));
82
83
  return {
83
84
  logicalId: i,
@@ -89,10 +90,10 @@ function d(t) {
89
90
  source: typeof n[e.source] == "string" ? String(n[e.source]) : void 0,
90
91
  createdAt: typeof n[e.createdAt] == "string" ? String(n[e.createdAt]) : void 0,
91
92
  updatedAt: typeof n[e.updatedAt] == "string" ? String(n[e.updatedAt]) : void 0,
92
- path: s(r, i)
93
+ path: c(r, i)
93
94
  };
94
95
  }
95
96
  //#endregion
96
- export { l as buildSnippet, d as hydrateInlineRecord, u as mapRecordForUpsert, c as parseVirtualPath };
97
+ export { u as buildSnippet, s as buildVectorId, f as hydrateInlineRecord, d as mapRecordForUpsert, l as parseVirtualPath };
97
98
 
98
99
  //# sourceMappingURL=record-mapper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"record-mapper.js","names":[],"sources":["../src/record-mapper.ts"],"sourcesContent":["import { Buffer } from \"node:buffer\";\nimport { randomUUID } from \"node:crypto\";\nimport { RESERVED_METADATA_KEYS, RESERVED_METADATA_PREFIX } from \"./constants.js\";\nimport { RecordSizeError } from \"./errors.js\";\nimport type {\n\tCompanionRecord,\n\tHydratedMemoryRecord,\n\tMemoryRecordInput,\n\tMetadataValue,\n\tResolvedPluginConfig,\n\tVectorizeQueryMatch,\n\tVectorizeVector,\n} from \"./types.js\";\n\nfunction sanitizeMetadataKey(key: string): string {\n\tconst sanitized = key.trim().replace(/[.$\"]/g, \"_\").replace(/\\s+/g, \"_\");\n\tif (!sanitized) {\n\t\treturn \"metadata\";\n\t}\n\tif (sanitized.startsWith(RESERVED_METADATA_PREFIX)) {\n\t\treturn `user_${sanitized}`;\n\t}\n\treturn sanitized;\n}\n\nfunction sanitizeMetadata(metadata: Record<string, MetadataValue> | undefined): Record<string, MetadataValue> {\n\tif (!metadata) {\n\t\treturn {};\n\t}\n\tconst entries = Object.entries(metadata).filter(([, value]) => [\"string\", \"number\", \"boolean\"].includes(typeof value));\n\treturn Object.fromEntries(entries.map(([key, value]) => [sanitizeMetadataKey(key), value]));\n}\n\nexport function buildVectorId(namespace: string, logicalId: string): string {\n\treturn `${namespace}::${logicalId}`;\n}\n\nexport function buildVirtualPath(namespace: string, logicalId: string): string {\n\treturn `${namespace}/${logicalId}.md`;\n}\n\nexport function parseVirtualPath(path: string): { namespace: string; logicalId: string } | null {\n\tconst normalized = path.replace(/\\\\/g, \"/\").replace(/^\\//, \"\");\n\tconst segments = normalized.split(\"/\");\n\tif (segments.length !== 2 || !segments[1].endsWith(\".md\")) {\n\t\treturn null;\n\t}\n\treturn {\n\t\tnamespace: segments[0],\n\t\tlogicalId: segments[1].slice(0, -3),\n\t};\n}\n\nexport function buildSnippet(text: string, query: string): string {\n\tconst normalized = text.trim().replace(/\\s+/g, \" \");\n\tif (!normalized) {\n\t\treturn \"\";\n\t}\n\tconst lower = normalized.toLowerCase();\n\tconst index = lower.indexOf(query.trim().toLowerCase());\n\tif (index === -1) {\n\t\treturn normalized.slice(0, 220);\n\t}\n\tconst start = Math.max(0, index - 80);\n\tconst end = Math.min(normalized.length, index + Math.max(query.length, 40) + 80);\n\treturn normalized.slice(start, end);\n}\n\nexport function mapRecordForUpsert(params: { input: MemoryRecordInput; namespace: string; embedding: number[]; config: ResolvedPluginConfig }): {\n\tlogicalId: string;\n\tvectorId: string;\n\tpath: string;\n\tvector: VectorizeVector;\n\tcompanionRecord?: CompanionRecord;\n} {\n\tconst logicalId = params.input.id?.trim() || randomUUID();\n\tconst vectorId = buildVectorId(params.namespace, logicalId);\n\tconst now = new Date().toISOString();\n\tconst userMetadata = sanitizeMetadata(params.input.metadata);\n\tconst metadataBase: Record<string, MetadataValue> = {\n\t\t...userMetadata,\n\t\t[RESERVED_METADATA_KEYS.logicalId]: logicalId,\n\t\t[RESERVED_METADATA_KEYS.storageMode]: params.config.storageMode,\n\t\t[RESERVED_METADATA_KEYS.createdAt]: now,\n\t\t[RESERVED_METADATA_KEYS.updatedAt]: now,\n\t};\n\n\tif (params.input.title) {\n\t\tmetadataBase[RESERVED_METADATA_KEYS.title] = params.input.title;\n\t}\n\tif (params.input.source) {\n\t\tmetadataBase[RESERVED_METADATA_KEYS.source] = params.input.source;\n\t}\n\n\tlet companionRecord: CompanionRecord | undefined;\n\tif (params.config.storageMode === \"vectorize-inline\") {\n\t\tconst byteLength = Buffer.byteLength(params.input.text, \"utf8\");\n\t\tif (byteLength > params.config.inlineTextMaxBytes) {\n\t\t\tthrow new RecordSizeError(\n\t\t\t\t`Memory text is ${byteLength} bytes, which exceeds the inline metadata limit of ${params.config.inlineTextMaxBytes}. Switch storage.mode to \"companion-store\" or reduce the payload size.`,\n\t\t\t);\n\t\t}\n\t\tmetadataBase[RESERVED_METADATA_KEYS.text] = params.input.text;\n\t} else {\n\t\tconst pointer = buildVirtualPath(params.namespace, logicalId);\n\t\tmetadataBase[RESERVED_METADATA_KEYS.pointer] = pointer;\n\t\tcompanionRecord = {\n\t\t\tid: logicalId,\n\t\t\tnamespace: params.namespace,\n\t\t\ttitle: params.input.title,\n\t\t\ttext: params.input.text,\n\t\t\tmetadata: userMetadata,\n\t\t\tsource: params.input.source,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t};\n\t}\n\n\treturn {\n\t\tlogicalId,\n\t\tvectorId,\n\t\tpath: buildVirtualPath(params.namespace, logicalId),\n\t\tvector: {\n\t\t\tid: vectorId,\n\t\t\tnamespace: params.namespace,\n\t\t\tvalues: params.embedding,\n\t\t\tmetadata: metadataBase,\n\t\t},\n\t\tcompanionRecord,\n\t};\n}\n\nexport function hydrateInlineRecord(match: VectorizeQueryMatch): Omit<HydratedMemoryRecord, \"text\" | \"path\"> & {\n\ttext?: string;\n\tpath: string;\n} {\n\tconst metadata = match.metadata ?? {};\n\tconst namespace =\n\t\tmatch.namespace ?? (typeof metadata[RESERVED_METADATA_KEYS.pointer] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.pointer]).split(\"/\")[0] : \"main\");\n\tconst logicalId =\n\t\ttypeof metadata[RESERVED_METADATA_KEYS.logicalId] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.logicalId]) : String(match.id ?? \"\");\n\tconst userMetadata = Object.fromEntries(Object.entries(metadata).filter(([key]) => !key.startsWith(RESERVED_METADATA_PREFIX)));\n\treturn {\n\t\tlogicalId,\n\t\tvectorId: String(match.id ?? logicalId),\n\t\tnamespace,\n\t\ttitle: typeof metadata[RESERVED_METADATA_KEYS.title] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.title]) : undefined,\n\t\ttext: typeof metadata[RESERVED_METADATA_KEYS.text] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.text]) : undefined,\n\t\tmetadata: userMetadata,\n\t\tsource: typeof metadata[RESERVED_METADATA_KEYS.source] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.source]) : undefined,\n\t\tcreatedAt: typeof metadata[RESERVED_METADATA_KEYS.createdAt] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.createdAt]) : undefined,\n\t\tupdatedAt: typeof metadata[RESERVED_METADATA_KEYS.updatedAt] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.updatedAt]) : undefined,\n\t\tpath: buildVirtualPath(namespace, logicalId),\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"record-mapper.js","names":[],"sources":["../src/record-mapper.ts"],"sourcesContent":["import { Buffer } from \"node:buffer\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { RESERVED_METADATA_KEYS, RESERVED_METADATA_PREFIX } from \"./constants.js\";\nimport { RecordSizeError } from \"./errors.js\";\nimport type {\n\tCompanionRecord,\n\tHydratedMemoryRecord,\n\tMemoryRecordInput,\n\tMetadataValue,\n\tResolvedPluginConfig,\n\tVectorizeQueryMatch,\n\tVectorizeVector,\n} from \"./types.js\";\n\nfunction sanitizeMetadataKey(key: string): string {\n\tconst sanitized = key.trim().replace(/[.$\"]/g, \"_\").replace(/\\s+/g, \"_\");\n\tif (!sanitized) {\n\t\treturn \"metadata\";\n\t}\n\tif (sanitized.startsWith(RESERVED_METADATA_PREFIX)) {\n\t\treturn `user_${sanitized}`;\n\t}\n\treturn sanitized;\n}\n\nfunction sanitizeMetadata(metadata: Record<string, MetadataValue> | undefined): Record<string, MetadataValue> {\n\tif (!metadata) {\n\t\treturn {};\n\t}\n\tconst entries = Object.entries(metadata).filter(([, value]) => [\"string\", \"number\", \"boolean\"].includes(typeof value));\n\treturn Object.fromEntries(entries.map(([key, value]) => [sanitizeMetadataKey(key), value]));\n}\n\nexport function buildVectorId(namespace: string, logicalId: string): string {\n\tconst rawId = `${namespace}::${logicalId}`;\n\tif (Buffer.byteLength(rawId, \"utf8\") <= 64) {\n\t\treturn rawId;\n\t}\n\treturn `cfm_${createHash(\"sha256\").update(rawId).digest(\"hex\").slice(0, 48)}`;\n}\n\nexport function buildVirtualPath(namespace: string, logicalId: string): string {\n\treturn `${namespace}/${logicalId}.md`;\n}\n\nexport function parseVirtualPath(path: string): { namespace: string; logicalId: string } | null {\n\tconst normalized = path.replace(/\\\\/g, \"/\").replace(/^\\//, \"\");\n\tconst segments = normalized.split(\"/\");\n\tif (segments.length !== 2 || !segments[1].endsWith(\".md\")) {\n\t\treturn null;\n\t}\n\treturn {\n\t\tnamespace: segments[0],\n\t\tlogicalId: segments[1].slice(0, -3),\n\t};\n}\n\nexport function buildSnippet(text: string, query: string): string {\n\tconst normalized = text.trim().replace(/\\s+/g, \" \");\n\tif (!normalized) {\n\t\treturn \"\";\n\t}\n\tconst lower = normalized.toLowerCase();\n\tconst index = lower.indexOf(query.trim().toLowerCase());\n\tif (index === -1) {\n\t\treturn normalized.slice(0, 220);\n\t}\n\tconst start = Math.max(0, index - 80);\n\tconst end = Math.min(normalized.length, index + Math.max(query.length, 40) + 80);\n\treturn normalized.slice(start, end);\n}\n\nexport function mapRecordForUpsert(params: { input: MemoryRecordInput; namespace: string; embedding: number[]; config: ResolvedPluginConfig }): {\n\tlogicalId: string;\n\tvectorId: string;\n\tpath: string;\n\tvector: VectorizeVector;\n\tcompanionRecord?: CompanionRecord;\n} {\n\tconst logicalId = params.input.id?.trim() || randomUUID();\n\tconst vectorId = buildVectorId(params.namespace, logicalId);\n\tconst now = new Date().toISOString();\n\tconst userMetadata = sanitizeMetadata(params.input.metadata);\n\tconst metadataBase: Record<string, MetadataValue> = {\n\t\t...userMetadata,\n\t\t[RESERVED_METADATA_KEYS.logicalId]: logicalId,\n\t\t[RESERVED_METADATA_KEYS.storageMode]: params.config.storageMode,\n\t\t[RESERVED_METADATA_KEYS.createdAt]: now,\n\t\t[RESERVED_METADATA_KEYS.updatedAt]: now,\n\t};\n\n\tif (params.input.title) {\n\t\tmetadataBase[RESERVED_METADATA_KEYS.title] = params.input.title;\n\t}\n\tif (params.input.source) {\n\t\tmetadataBase[RESERVED_METADATA_KEYS.source] = params.input.source;\n\t}\n\n\tlet companionRecord: CompanionRecord | undefined;\n\tif (params.config.storageMode === \"vectorize-inline\") {\n\t\tconst byteLength = Buffer.byteLength(params.input.text, \"utf8\");\n\t\tif (byteLength > params.config.inlineTextMaxBytes) {\n\t\t\tthrow new RecordSizeError(\n\t\t\t\t`Memory text is ${byteLength} bytes, which exceeds the inline metadata limit of ${params.config.inlineTextMaxBytes}. Switch storage.mode to \"companion-store\" or reduce the payload size.`,\n\t\t\t);\n\t\t}\n\t\tmetadataBase[RESERVED_METADATA_KEYS.text] = params.input.text;\n\t} else {\n\t\tconst pointer = buildVirtualPath(params.namespace, logicalId);\n\t\tmetadataBase[RESERVED_METADATA_KEYS.pointer] = pointer;\n\t\tcompanionRecord = {\n\t\t\tid: logicalId,\n\t\t\tnamespace: params.namespace,\n\t\t\ttitle: params.input.title,\n\t\t\ttext: params.input.text,\n\t\t\tmetadata: userMetadata,\n\t\t\tsource: params.input.source,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t};\n\t}\n\n\treturn {\n\t\tlogicalId,\n\t\tvectorId,\n\t\tpath: buildVirtualPath(params.namespace, logicalId),\n\t\tvector: {\n\t\t\tid: vectorId,\n\t\t\tnamespace: params.namespace,\n\t\t\tvalues: params.embedding,\n\t\t\tmetadata: metadataBase,\n\t\t},\n\t\tcompanionRecord,\n\t};\n}\n\nexport function hydrateInlineRecord(match: VectorizeQueryMatch): Omit<HydratedMemoryRecord, \"text\" | \"path\"> & {\n\ttext?: string;\n\tpath: string;\n} {\n\tconst metadata = match.metadata ?? {};\n\tconst namespace =\n\t\tmatch.namespace ?? (typeof metadata[RESERVED_METADATA_KEYS.pointer] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.pointer]).split(\"/\")[0] : \"main\");\n\tconst logicalId =\n\t\ttypeof metadata[RESERVED_METADATA_KEYS.logicalId] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.logicalId]) : String(match.id ?? \"\");\n\tconst userMetadata = Object.fromEntries(Object.entries(metadata).filter(([key]) => !key.startsWith(RESERVED_METADATA_PREFIX)));\n\treturn {\n\t\tlogicalId,\n\t\tvectorId: String(match.id ?? logicalId),\n\t\tnamespace,\n\t\ttitle: typeof metadata[RESERVED_METADATA_KEYS.title] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.title]) : undefined,\n\t\ttext: typeof metadata[RESERVED_METADATA_KEYS.text] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.text]) : undefined,\n\t\tmetadata: userMetadata,\n\t\tsource: typeof metadata[RESERVED_METADATA_KEYS.source] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.source]) : undefined,\n\t\tcreatedAt: typeof metadata[RESERVED_METADATA_KEYS.createdAt] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.createdAt]) : undefined,\n\t\tupdatedAt: typeof metadata[RESERVED_METADATA_KEYS.updatedAt] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.updatedAt]) : undefined,\n\t\tpath: buildVirtualPath(namespace, logicalId),\n\t};\n}\n"],"mappings":"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"}
@@ -1,10 +1,30 @@
1
- import { resolvePluginConfig as e } from "./config.js";
2
- import { CloudflareMemoryService as t } from "./service.js";
1
+ import { getPluginConfigFromOpenClawConfig as e, normalizePluginConfigInput as t, resolvePluginConfig as n } from "./config.js";
2
+ import { CloudflareMemoryService as r } from "./service.js";
3
3
  //#region src/service-factory.ts
4
- async function n(n) {
5
- return new t(await e(n), n.openClawConfig);
4
+ function i(e) {
5
+ return e.cloudflare !== void 0 || e.vectorize !== void 0 || e.embeddings !== void 0 || e.storage !== void 0;
6
+ }
7
+ function a(n) {
8
+ let r = e(n.openClawConfig);
9
+ return i(r) ? r : t(n.pluginConfig);
10
+ }
11
+ async function o(e) {
12
+ return {
13
+ ...await n({
14
+ pluginConfig: a(e),
15
+ openClawConfig: e.openClawConfig,
16
+ env: e.env,
17
+ resolvePath: e.resolvePath
18
+ }),
19
+ ...e.overrides?.apiToken === void 0 ? {} : { apiToken: e.overrides.apiToken },
20
+ ...e.overrides?.workersAiBaseUrl === void 0 ? {} : { workersAiBaseUrl: e.overrides.workersAiBaseUrl },
21
+ ...e.overrides?.model === void 0 ? {} : { model: e.overrides.model }
22
+ };
23
+ }
24
+ async function s(e) {
25
+ return new r(await o(e), e.openClawConfig);
6
26
  }
7
27
  //#endregion
8
- export { n as createCloudflareMemoryService };
28
+ export { s as createCloudflareMemoryService, o as resolveCloudflareMemoryServiceConfig };
9
29
 
10
30
  //# sourceMappingURL=service-factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service-factory.js","names":[],"sources":["../src/service-factory.ts"],"sourcesContent":["import type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport { resolvePluginConfig } from \"./config.js\";\nimport { CloudflareMemoryService } from \"./service.js\";\n\nexport async function createCloudflareMemoryService(params: {\n\tpluginConfig: unknown;\n\topenClawConfig: OpenClawConfig;\n\tenv?: NodeJS.ProcessEnv;\n\tresolvePath?: (input: string) => string;\n}): Promise<CloudflareMemoryService> {\n\tconst resolved = await resolvePluginConfig(params);\n\treturn new CloudflareMemoryService(resolved, params.openClawConfig);\n}\n"],"mappings":";;;AAIA,eAAsB,EAA8B,GAKf;AAEpC,QAAO,IAAI,EADM,MAAM,EAAoB,EAAO,EACL,EAAO,eAAe"}
1
+ {"version":3,"file":"service-factory.js","names":[],"sources":["../src/service-factory.ts"],"sourcesContent":["import type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport { getPluginConfigFromOpenClawConfig, normalizePluginConfigInput, resolvePluginConfig } from \"./config.js\";\nimport { CloudflareMemoryService } from \"./service.js\";\nimport type { RawPluginConfig, ResolvedPluginConfig } from \"./types.js\";\n\ntype ServiceConfigOverrides = Partial<Pick<ResolvedPluginConfig, \"apiToken\" | \"workersAiBaseUrl\" | \"model\">>;\n\nfunction hasConfiguredPluginValues(config: RawPluginConfig): boolean {\n\treturn config.cloudflare !== undefined || config.vectorize !== undefined || config.embeddings !== undefined || config.storage !== undefined;\n}\n\nfunction resolveServicePluginConfig(params: { pluginConfig?: unknown; openClawConfig: OpenClawConfig }): RawPluginConfig {\n\tconst configuredFromOpenClaw = getPluginConfigFromOpenClawConfig(params.openClawConfig);\n\tif (hasConfiguredPluginValues(configuredFromOpenClaw)) {\n\t\treturn configuredFromOpenClaw;\n\t}\n\treturn normalizePluginConfigInput(params.pluginConfig);\n}\n\nexport async function resolveCloudflareMemoryServiceConfig(params: {\n\tpluginConfig?: unknown;\n\topenClawConfig: OpenClawConfig;\n\tenv?: NodeJS.ProcessEnv;\n\tresolvePath?: (input: string) => string;\n\toverrides?: ServiceConfigOverrides;\n}): Promise<ResolvedPluginConfig> {\n\tconst resolved = await resolvePluginConfig({\n\t\tpluginConfig: resolveServicePluginConfig(params),\n\t\topenClawConfig: params.openClawConfig,\n\t\tenv: params.env,\n\t\tresolvePath: params.resolvePath,\n\t});\n\n\treturn {\n\t\t...resolved,\n\t\t...(params.overrides?.apiToken !== undefined ? { apiToken: params.overrides.apiToken } : {}),\n\t\t...(params.overrides?.workersAiBaseUrl !== undefined ? { workersAiBaseUrl: params.overrides.workersAiBaseUrl } : {}),\n\t\t...(params.overrides?.model !== undefined ? { model: params.overrides.model } : {}),\n\t};\n}\n\nexport async function createCloudflareMemoryService(params: {\n\tpluginConfig?: unknown;\n\topenClawConfig: OpenClawConfig;\n\tenv?: NodeJS.ProcessEnv;\n\tresolvePath?: (input: string) => string;\n\toverrides?: ServiceConfigOverrides;\n}): Promise<CloudflareMemoryService> {\n\tconst resolved = await resolveCloudflareMemoryServiceConfig(params);\n\treturn new CloudflareMemoryService(resolved, params.openClawConfig);\n}\n"],"mappings":";;;AAOA,SAAS,EAA0B,GAAkC;AACpE,QAAO,EAAO,eAAe,KAAA,KAAa,EAAO,cAAc,KAAA,KAAa,EAAO,eAAe,KAAA,KAAa,EAAO,YAAY,KAAA;;AAGnI,SAAS,EAA2B,GAAqF;CACxH,IAAM,IAAyB,EAAkC,EAAO,eAAe;AAIvF,QAHI,EAA0B,EAAuB,GAC7C,IAED,EAA2B,EAAO,aAAa;;AAGvD,eAAsB,EAAqC,GAMzB;AAQjC,QAAO;EACN,GARgB,MAAM,EAAoB;GAC1C,cAAc,EAA2B,EAAO;GAChD,gBAAgB,EAAO;GACvB,KAAK,EAAO;GACZ,aAAa,EAAO;GACpB,CAAC;EAID,GAAI,EAAO,WAAW,aAAa,KAAA,IAAsD,EAAE,GAA5C,EAAE,UAAU,EAAO,UAAU,UAAU;EACtF,GAAI,EAAO,WAAW,qBAAqB,KAAA,IAAsE,EAAE,GAA5D,EAAE,kBAAkB,EAAO,UAAU,kBAAkB;EAC9G,GAAI,EAAO,WAAW,UAAU,KAAA,IAAgD,EAAE,GAAtC,EAAE,OAAO,EAAO,UAAU,OAAO;EAC7E;;AAGF,eAAsB,EAA8B,GAMf;AAEpC,QAAO,IAAI,EADM,MAAM,EAAqC,EAAO,EACtB,EAAO,eAAe"}
package/dist/service.js CHANGED
@@ -3,16 +3,16 @@ import { isCloudflareNotFoundError as n } from "./cloudflare-api.js";
3
3
  import { CompanionStore as r } from "./companion-store.js";
4
4
  import { runDoctor as i } from "./doctor.js";
5
5
  import { WorkersAiEmbeddingsClient as a } from "./embeddings-client.js";
6
- import { hydrateInlineRecord as o, mapRecordForUpsert as s } from "./record-mapper.js";
7
- import { VectorizeClient as c } from "./vectorize-client.js";
8
- import { randomUUID as l } from "node:crypto";
6
+ import { buildVectorId as o, hydrateInlineRecord as s, mapRecordForUpsert as c } from "./record-mapper.js";
7
+ import { VectorizeClient as l } from "./vectorize-client.js";
8
+ import { randomUUID as u } from "node:crypto";
9
9
  //#region src/service.ts
10
- var u = 12e3, d = 1e3, f = class {
10
+ var d = 3e4, f = 1e3, p = class {
11
11
  embeddings;
12
12
  vectorize;
13
13
  companionStore;
14
14
  constructor(e, t) {
15
- this.config = e, this.openClawConfig = t, this.embeddings = new a(e), this.vectorize = new c(e), this.companionStore = new r(e.companionStorePath);
15
+ this.config = e, this.openClawConfig = t, this.embeddings = new a(e), this.vectorize = new l(e), this.companionStore = new r(e.companionStorePath);
16
16
  }
17
17
  resolveNamespace(t) {
18
18
  return e({
@@ -30,7 +30,7 @@ var u = 12e3, d = 1e3, f = class {
30
30
  filter: e.filter
31
31
  });
32
32
  return (await Promise.all(r.map(async (e) => {
33
- let t = o(e), n = t.text ?? (await this.companionStore.get(t.namespace, t.logicalId))?.text ?? "";
33
+ let t = s(e), n = t.text ?? (await this.companionStore.get(t.namespace, t.logicalId))?.text ?? "";
34
34
  return {
35
35
  ...t,
36
36
  text: n,
@@ -39,9 +39,9 @@ var u = 12e3, d = 1e3, f = class {
39
39
  }))).filter((t) => t.score >= (e.minScore ?? this.config.minScore));
40
40
  }
41
41
  async get(e) {
42
- let t = `${this.resolveNamespace(e)}::${e.id}`, [n] = await this.vectorize.getByIds([t]);
42
+ let t = o(this.resolveNamespace(e), e.id), [n] = await this.vectorize.getByIds([t]);
43
43
  if (!n) return null;
44
- let r = o(n), i = await this.companionStore.get(r.namespace, r.logicalId);
44
+ let r = s(n), i = await this.companionStore.get(r.namespace, r.logicalId);
45
45
  return {
46
46
  ...r,
47
47
  text: r.text ?? i?.text ?? ""
@@ -53,25 +53,34 @@ var u = 12e3, d = 1e3, f = class {
53
53
  sessionKey: e.sessionKey,
54
54
  agentId: e.agentId,
55
55
  workspaceDir: e.workspaceDir
56
- }), n = await this.embeddings.embedQuery(e.input.text), r = s({
56
+ }), n = await this.embeddings.embedQuery(e.input.text), r = c({
57
57
  input: e.input,
58
58
  namespace: t,
59
59
  embedding: n,
60
60
  config: this.config
61
61
  });
62
62
  r.companionRecord && await this.companionStore.upsert(r.companionRecord);
63
- let i = await this.vectorize.upsert([r.vector]);
63
+ let i = await this.vectorize.upsert([r.vector]), a = await this.get({
64
+ id: r.logicalId,
65
+ namespace: t
66
+ }), o = r.companionRecord === void 0 ? this.fromInlineFallback(r.vector) : this.fromCompanionFallback(r.companionRecord, r.logicalId, t, r.path);
64
67
  return {
65
- ...await this.get({
66
- id: r.logicalId,
67
- namespace: t
68
- }) ?? this.fromCompanionFallback(r.companionRecord, r.logicalId, t, r.path),
68
+ ...a ? {
69
+ ...o,
70
+ ...a,
71
+ title: a.title ?? o.title,
72
+ text: a.text || o.text,
73
+ metadata: Object.keys(a.metadata).length > 0 ? a.metadata : o.metadata,
74
+ source: a.source ?? o.source,
75
+ createdAt: a.createdAt ?? o.createdAt,
76
+ updatedAt: a.updatedAt ?? o.updatedAt
77
+ } : o,
69
78
  mutationId: i
70
79
  };
71
80
  }
72
81
  async delete(e) {
73
82
  let t = this.resolveNamespace(e);
74
- return await this.companionStore.delete(t, e.id), this.vectorize.deleteByIds([`${t}::${e.id}`]);
83
+ return await this.companionStore.delete(t, e.id), this.vectorize.deleteByIds([o(t, e.id)]);
75
84
  }
76
85
  async doctor(e) {
77
86
  return i({
@@ -204,7 +213,7 @@ var u = 12e3, d = 1e3, f = class {
204
213
  status: "pass",
205
214
  message: "Embedding dimensions match the Vectorize index."
206
215
  });
207
- let a = t(`cf-memory-test-${l()}`), o = `cf-memory-test-${l()}`, s = `OpenClaw Cloudflare memory smoke test ${o}`, c = !1;
216
+ let a = t(`cf-memory-test-${u()}`), o = `cf-memory-test-${u()}`, s = `OpenClaw Cloudflare memory smoke test ${o}`, c = !1;
208
217
  try {
209
218
  await this.upsert({ input: {
210
219
  id: o,
@@ -224,13 +233,13 @@ var u = 12e3, d = 1e3, f = class {
224
233
  query: s,
225
234
  namespace: a,
226
235
  logicalId: o,
227
- timeoutMs: e?.timeoutMs ?? u,
228
- pollIntervalMs: e?.pollIntervalMs ?? d
236
+ timeoutMs: e?.timeoutMs ?? d,
237
+ pollIntervalMs: e?.pollIntervalMs ?? f
229
238
  });
230
239
  n.push({
231
240
  name: "probe-search",
232
241
  status: t ? "pass" : "fail",
233
- message: t ? "Semantic search returned the smoke-test record." : `Semantic search did not return the smoke-test record within ${(e?.timeoutMs ?? u) / 1e3} seconds.`
242
+ message: t ? "Semantic search returned the smoke-test record." : `Semantic search did not return the smoke-test record within ${(e?.timeoutMs ?? d) / 1e3} seconds.`
234
243
  });
235
244
  } catch (e) {
236
245
  n.push({
@@ -281,7 +290,7 @@ var u = 12e3, d = 1e3, f = class {
281
290
  fromCompanionFallback(e, t, n, r) {
282
291
  return {
283
292
  logicalId: t,
284
- vectorId: `${n}::${t}`,
293
+ vectorId: o(n, t),
285
294
  namespace: n,
286
295
  title: e?.title,
287
296
  text: e?.text ?? "",
@@ -292,6 +301,13 @@ var u = 12e3, d = 1e3, f = class {
292
301
  path: r
293
302
  };
294
303
  }
304
+ fromInlineFallback(e) {
305
+ let t = s(e);
306
+ return {
307
+ ...t,
308
+ text: t.text ?? ""
309
+ };
310
+ }
295
311
  async waitForSearchHit(e) {
296
312
  let t = Date.now() + e.timeoutMs;
297
313
  for (; Date.now() <= t;) {
@@ -311,6 +327,6 @@ var u = 12e3, d = 1e3, f = class {
311
327
  }
312
328
  };
313
329
  //#endregion
314
- export { f as CloudflareMemoryService };
330
+ export { p as CloudflareMemoryService };
315
331
 
316
332
  //# sourceMappingURL=service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","names":[],"sources":["../src/service.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport { isCloudflareNotFoundError } from \"./cloudflare-api.js\";\nimport { CompanionStore } from \"./companion-store.js\";\nimport { runDoctor } from \"./doctor.js\";\nimport { WorkersAiEmbeddingsClient } from \"./embeddings-client.js\";\nimport { sanitizeNamespace, resolveDefaultNamespace } from \"./namespace.js\";\nimport { hydrateInlineRecord, mapRecordForUpsert } from \"./record-mapper.js\";\nimport type {\n\tCompanionRecord,\n\tDoctorCheck,\n\tDoctorReport,\n\tEmbeddingDimensionsInspection,\n\tHydratedMemoryRecord,\n\tIndexInitializationReport,\n\tMemoryRecordInput,\n\tMetadataFilter,\n\tResolvedPluginConfig,\n\tSmokeTestReport,\n\tUpsertedMemoryRecord,\n\tVectorizeIndexDescription,\n} from \"./types.js\";\nimport { VectorizeClient } from \"./vectorize-client.js\";\n\nconst SMOKE_TEST_TIMEOUT_MS = 12_000;\nconst SMOKE_TEST_POLL_INTERVAL_MS = 1_000;\n\nexport class CloudflareMemoryService {\n\treadonly embeddings: WorkersAiEmbeddingsClient;\n\treadonly vectorize: VectorizeClient;\n\treadonly companionStore: CompanionStore;\n\n\tconstructor(\n\t\treadonly config: ResolvedPluginConfig,\n\t\treadonly openClawConfig: OpenClawConfig,\n\t) {\n\t\tthis.embeddings = new WorkersAiEmbeddingsClient(config);\n\t\tthis.vectorize = new VectorizeClient(config);\n\t\tthis.companionStore = new CompanionStore(config.companionStorePath);\n\t}\n\n\tresolveNamespace(params: { namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): string {\n\t\treturn resolveDefaultNamespace({\n\t\t\tfixedNamespace: params.namespace ?? this.config.fixedNamespace,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tagentId: params.agentId,\n\t\t\tworkspaceDir: params.workspaceDir,\n\t\t});\n\t}\n\n\tasync search(params: {\n\t\tquery: string;\n\t\tnamespace?: string;\n\t\tmaxResults?: number;\n\t\tminScore?: number;\n\t\tfilter?: MetadataFilter;\n\t\tsessionKey?: string;\n\t\tagentId?: string;\n\t\tworkspaceDir?: string;\n\t}): Promise<Array<HydratedMemoryRecord & { score: number }>> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tconst vector = await this.embeddings.embedQuery(params.query);\n\t\tconst matches = await this.vectorize.query({\n\t\t\tvector,\n\t\t\tnamespace,\n\t\t\ttopK: params.maxResults ?? this.config.topK,\n\t\t\tfilter: params.filter,\n\t\t});\n\n\t\tconst hydrated = await Promise.all(\n\t\t\tmatches.map(async (match) => {\n\t\t\t\tconst base = hydrateInlineRecord(match);\n\t\t\t\tconst text = base.text ?? (await this.companionStore.get(base.namespace, base.logicalId))?.text ?? \"\";\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\ttext,\n\t\t\t\t\tscore: match.score ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\treturn hydrated.filter((record) => record.score >= (params.minScore ?? this.config.minScore));\n\t}\n\n\tasync get(params: { id: string; namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<HydratedMemoryRecord | null> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tconst vectorId = `${namespace}::${params.id}`;\n\t\tconst [match] = await this.vectorize.getByIds([vectorId]);\n\t\tif (!match) {\n\t\t\treturn null;\n\t\t}\n\t\tconst base = hydrateInlineRecord(match);\n\t\tconst companion = await this.companionStore.get(base.namespace, base.logicalId);\n\t\treturn {\n\t\t\t...base,\n\t\t\ttext: base.text ?? companion?.text ?? \"\",\n\t\t};\n\t}\n\n\tasync upsert(params: { input: MemoryRecordInput; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<UpsertedMemoryRecord> {\n\t\tconst namespace = this.resolveNamespace({\n\t\t\tnamespace: params.input.namespace,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tagentId: params.agentId,\n\t\t\tworkspaceDir: params.workspaceDir,\n\t\t});\n\t\tconst embedding = await this.embeddings.embedQuery(params.input.text);\n\t\tconst mapped = mapRecordForUpsert({\n\t\t\tinput: params.input,\n\t\t\tnamespace,\n\t\t\tembedding,\n\t\t\tconfig: this.config,\n\t\t});\n\n\t\tif (mapped.companionRecord) {\n\t\t\tawait this.companionStore.upsert(mapped.companionRecord);\n\t\t}\n\n\t\tconst mutationId = await this.vectorize.upsert([mapped.vector]);\n\t\tconst hydrated = await this.get({\n\t\t\tid: mapped.logicalId,\n\t\t\tnamespace,\n\t\t});\n\n\t\treturn {\n\t\t\t...(hydrated ?? this.fromCompanionFallback(mapped.companionRecord, mapped.logicalId, namespace, mapped.path)),\n\t\t\tmutationId,\n\t\t};\n\t}\n\n\tasync delete(params: { id: string; namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<string | undefined> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tawait this.companionStore.delete(namespace, params.id);\n\t\treturn this.vectorize.deleteByIds([`${namespace}::${params.id}`]);\n\t}\n\n\tasync doctor(options: { createIndexIfMissing?: boolean }): Promise<DoctorReport> {\n\t\treturn runDoctor({\n\t\t\tservice: this,\n\t\t\tcreateIndexIfMissing: options.createIndexIfMissing ?? false,\n\t\t});\n\t}\n\n\tasync inspectEmbeddingDimensions(): Promise<EmbeddingDimensionsInspection> {\n\t\tconst embeddingDimensions = await this.embeddings.probeDimensions();\n\t\tconst configuredDimensions = this.config.createIndex.dimensions;\n\t\treturn {\n\t\t\tembeddingDimensions,\n\t\t\tconfiguredDimensions,\n\t\t\tconfiguredDimensionsMatchModel: configuredDimensions === undefined || configuredDimensions === embeddingDimensions,\n\t\t\ttargetDimensions: embeddingDimensions,\n\t\t};\n\t}\n\n\tasync describeIndexIfExists(): Promise<VectorizeIndexDescription | null> {\n\t\ttry {\n\t\t\treturn await this.vectorize.describeIndex();\n\t\t} catch (error) {\n\t\t\tif (isCloudflareNotFoundError(error)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync initializeIndex(options?: { recreateIfDimensionMismatch?: boolean }): Promise<IndexInitializationReport> {\n\t\tconst recreateIfDimensionMismatch = options?.recreateIfDimensionMismatch ?? true;\n\t\tconst checks: DoctorCheck[] = [];\n\t\tchecks.push({\n\t\t\tname: \"credentials\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Using Cloudflare account ${this.config.accountId} and Vectorize index ${this.config.indexName}.`,\n\t\t});\n\n\t\tconst embedding = await this.inspectEmbeddingDimensions();\n\t\tchecks.push({\n\t\t\tname: \"workers-ai-embeddings\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Workers AI model ${this.config.model} returned ${embedding.embeddingDimensions} dimensions.`,\n\t\t});\n\t\tif (embedding.configuredDimensions !== undefined) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"create-index-dimensions\",\n\t\t\t\tstatus: embedding.configuredDimensionsMatchModel ? \"pass\" : \"warn\",\n\t\t\t\tmessage: embedding.configuredDimensionsMatchModel\n\t\t\t\t\t? `Configured createIndex.dimensions matches the embedding model (${embedding.embeddingDimensions}).`\n\t\t\t\t\t: `Configured createIndex.dimensions (${embedding.configuredDimensions}) does not match the embedding model (${embedding.embeddingDimensions}). Using the live embedding dimensions for initialization.`,\n\t\t\t});\n\t\t}\n\n\t\tconst existingIndex = await this.describeIndexIfExists();\n\t\tlet created = false;\n\t\tlet recreated = false;\n\t\tlet indexDimensions = existingIndex?.config.dimensions;\n\n\t\tif (!existingIndex) {\n\t\t\tconst createdIndex = await this.vectorize.createIndex(embedding.targetDimensions);\n\t\t\tcreated = true;\n\t\t\tindexDimensions = createdIndex.config.dimensions;\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `Created Vectorize index \"${this.config.indexName}\" with ${indexDimensions} dimensions.`,\n\t\t\t});\n\t\t} else if (existingIndex.config.dimensions === embedding.targetDimensions) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `Vectorize index \"${this.config.indexName}\" already uses ${existingIndex.config.dimensions} dimensions.`,\n\t\t\t});\n\t\t} else if (!recreateIfDimensionMismatch) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: `Vectorize index \"${this.config.indexName}\" uses ${existingIndex.config.dimensions} dimensions, but the embedding model requires ${embedding.targetDimensions}. Recreate the index or rerun init with recreation enabled.`,\n\t\t\t});\n\t\t} else {\n\t\t\tawait this.vectorize.deleteIndex();\n\t\t\tconst recreatedIndex = await this.vectorize.createIndex(embedding.targetDimensions);\n\t\t\trecreated = true;\n\t\t\tindexDimensions = recreatedIndex.config.dimensions;\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `Recreated Vectorize index \"${this.config.indexName}\" from ${existingIndex.config.dimensions} to ${indexDimensions} dimensions.`,\n\t\t\t});\n\t\t}\n\n\t\tchecks.push({\n\t\t\tname: \"dimension-match\",\n\t\t\tstatus: indexDimensions === embedding.embeddingDimensions ? \"pass\" : \"fail\",\n\t\t\tmessage:\n\t\t\t\tindexDimensions === embedding.embeddingDimensions\n\t\t\t\t\t? \"Embedding dimensions match the Vectorize index.\"\n\t\t\t\t\t: `Embedding dimensions (${embedding.embeddingDimensions}) do not match the Vectorize index dimensions (${indexDimensions ?? \"unknown\"}).`,\n\t\t});\n\t\tchecks.push({\n\t\t\tname: \"metadata-filters\",\n\t\t\tstatus: this.config.metadataIndexedFields.length > 0 ? \"pass\" : \"warn\",\n\t\t\tmessage:\n\t\t\t\tthis.config.metadataIndexedFields.length > 0\n\t\t\t\t\t? `Configured metadata-index guidance for: ${this.config.metadataIndexedFields.join(\", \")}.`\n\t\t\t\t\t: \"No metadataIndexedFields configured. Add metadata indexes in Cloudflare before relying on filter-heavy queries.\",\n\t\t});\n\n\t\treturn {\n\t\t\tok: checks.every((check) => check.status !== \"fail\"),\n\t\t\tchecks,\n\t\t\tcreated,\n\t\t\trecreated,\n\t\t\tembeddingDimensions: embedding.embeddingDimensions,\n\t\t\tindexDimensions,\n\t\t};\n\t}\n\n\tasync runSmokeTest(options?: { timeoutMs?: number; pollIntervalMs?: number }): Promise<SmokeTestReport> {\n\t\tconst checks: DoctorCheck[] = [];\n\t\tchecks.push({\n\t\t\tname: \"credentials\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Using Cloudflare account ${this.config.accountId} and Vectorize index ${this.config.indexName}.`,\n\t\t});\n\n\t\tconst embedding = await this.inspectEmbeddingDimensions();\n\t\tchecks.push({\n\t\t\tname: \"workers-ai-embeddings\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Workers AI model ${this.config.model} returned ${embedding.embeddingDimensions} dimensions.`,\n\t\t});\n\t\tif (embedding.configuredDimensions !== undefined) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"create-index-dimensions\",\n\t\t\t\tstatus: embedding.configuredDimensionsMatchModel ? \"pass\" : \"warn\",\n\t\t\t\tmessage: embedding.configuredDimensionsMatchModel\n\t\t\t\t\t? `Configured createIndex.dimensions matches the embedding model (${embedding.embeddingDimensions}).`\n\t\t\t\t\t: `Configured createIndex.dimensions (${embedding.configuredDimensions}) does not match the embedding model (${embedding.embeddingDimensions}). Using the live embedding dimensions for validation.`,\n\t\t\t});\n\t\t}\n\n\t\tconst existingIndex = await this.describeIndexIfExists();\n\t\tif (!existingIndex) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: `Vectorize index \"${this.config.indexName}\" was not found. Run \"openclaw cf-memory init\" before rerunning this test.`,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tchecks,\n\t\t\t\tnamespace: \"n/a\",\n\t\t\t\tlogicalId: \"n/a\",\n\t\t\t};\n\t\t}\n\n\t\tchecks.push({\n\t\t\tname: \"vectorize-index\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Vectorize index \"${this.config.indexName}\" is reachable.`,\n\t\t});\n\t\tif (existingIndex.config.dimensions !== embedding.embeddingDimensions) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"dimension-match\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: `Embedding dimensions (${embedding.embeddingDimensions}) do not match the Vectorize index dimensions (${existingIndex.config.dimensions}). Run \"openclaw cf-memory init\" to repair the index.`,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tchecks,\n\t\t\t\tnamespace: \"n/a\",\n\t\t\t\tlogicalId: \"n/a\",\n\t\t\t};\n\t\t}\n\n\t\tchecks.push({\n\t\t\tname: \"dimension-match\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: \"Embedding dimensions match the Vectorize index.\",\n\t\t});\n\n\t\tconst namespace = sanitizeNamespace(`cf-memory-test-${randomUUID()}`);\n\t\tconst logicalId = `cf-memory-test-${randomUUID()}`;\n\t\tconst probeText = `OpenClaw Cloudflare memory smoke test ${logicalId}`;\n\t\tlet probeUpserted = false;\n\n\t\ttry {\n\t\t\tawait this.upsert({\n\t\t\t\tinput: {\n\t\t\t\t\tid: logicalId,\n\t\t\t\t\tnamespace,\n\t\t\t\t\ttext: probeText,\n\t\t\t\t\tsource: \"cf-memory-test\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tprobe: true,\n\t\t\t\t\t\tprobeId: logicalId,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t\tprobeUpserted = true;\n\t\t\tchecks.push({\n\t\t\t\tname: \"probe-upsert\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `Inserted smoke-test record ${logicalId} in namespace ${namespace}.`,\n\t\t\t});\n\n\t\t\tconst found = await this.waitForSearchHit({\n\t\t\t\tquery: probeText,\n\t\t\t\tnamespace,\n\t\t\t\tlogicalId,\n\t\t\t\ttimeoutMs: options?.timeoutMs ?? SMOKE_TEST_TIMEOUT_MS,\n\t\t\t\tpollIntervalMs: options?.pollIntervalMs ?? SMOKE_TEST_POLL_INTERVAL_MS,\n\t\t\t});\n\t\t\tchecks.push({\n\t\t\t\tname: \"probe-search\",\n\t\t\t\tstatus: found ? \"pass\" : \"fail\",\n\t\t\t\tmessage: found\n\t\t\t\t\t? \"Semantic search returned the smoke-test record.\"\n\t\t\t\t\t: `Semantic search did not return the smoke-test record within ${(options?.timeoutMs ?? SMOKE_TEST_TIMEOUT_MS) / 1000} seconds.`,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tchecks.push({\n\t\t\t\tname: probeUpserted ? \"probe-search\" : \"probe-upsert\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: error instanceof Error ? error.message : \"Smoke test failed with an unknown error.\",\n\t\t\t});\n\t\t} finally {\n\t\t\ttry {\n\t\t\t\tawait this.delete({ id: logicalId, namespace });\n\t\t\t\tchecks.push({\n\t\t\t\t\tname: \"probe-cleanup\",\n\t\t\t\t\tstatus: \"pass\",\n\t\t\t\t\tmessage: `Deleted smoke-test record ${logicalId}.`,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tchecks.push({\n\t\t\t\t\tname: \"probe-cleanup\",\n\t\t\t\t\tstatus: \"fail\",\n\t\t\t\t\tmessage: error instanceof Error ? error.message : `Failed to delete smoke-test record ${logicalId}.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tok: checks.every((check) => check.status !== \"fail\"),\n\t\t\tchecks,\n\t\t\tnamespace,\n\t\t\tlogicalId,\n\t\t};\n\t}\n\n\tasync ensureIndexExists(createIfMissing: boolean, targetDimensions?: number): Promise<{ created: boolean; dimensions: number }> {\n\t\ttry {\n\t\t\tconst description = await this.vectorize.describeIndex();\n\t\t\treturn {\n\t\t\t\tcreated: false,\n\t\t\t\tdimensions: description.config.dimensions,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (!createIfMissing || !isCloudflareNotFoundError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst dimensions = targetDimensions ?? (await this.inspectEmbeddingDimensions()).targetDimensions;\n\t\t\tconst createdIndex = await this.vectorize.createIndex(dimensions);\n\t\t\treturn {\n\t\t\t\tcreated: true,\n\t\t\t\tdimensions: createdIndex.config.dimensions,\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate fromCompanionFallback(companionRecord: CompanionRecord | undefined, logicalId: string, namespace: string, path: string): UpsertedMemoryRecord {\n\t\treturn {\n\t\t\tlogicalId,\n\t\t\tvectorId: `${namespace}::${logicalId}`,\n\t\t\tnamespace,\n\t\t\ttitle: companionRecord?.title,\n\t\t\ttext: companionRecord?.text ?? \"\",\n\t\t\tmetadata: companionRecord?.metadata ?? {},\n\t\t\tsource: companionRecord?.source,\n\t\t\tcreatedAt: companionRecord?.createdAt,\n\t\t\tupdatedAt: companionRecord?.updatedAt,\n\t\t\tpath,\n\t\t};\n\t}\n\n\tprivate async waitForSearchHit(params: { query: string; namespace: string; logicalId: string; timeoutMs: number; pollIntervalMs: number }): Promise<boolean> {\n\t\tconst deadline = Date.now() + params.timeoutMs;\n\t\twhile (Date.now() <= deadline) {\n\t\t\tconst results = await this.search({\n\t\t\t\tquery: params.query,\n\t\t\t\tnamespace: params.namespace,\n\t\t\t\tmaxResults: 5,\n\t\t\t\tminScore: 0,\n\t\t\t});\n\t\t\tif (results.some((record) => record.logicalId === params.logicalId)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (Date.now() + params.pollIntervalMs > deadline) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait this.pause(params.pollIntervalMs);\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate async pause(ms: number): Promise<void> {\n\t\tawait new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service.js","names":[],"sources":["../src/service.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport { isCloudflareNotFoundError } from \"./cloudflare-api.js\";\nimport { CompanionStore } from \"./companion-store.js\";\nimport { runDoctor } from \"./doctor.js\";\nimport { WorkersAiEmbeddingsClient } from \"./embeddings-client.js\";\nimport { sanitizeNamespace, resolveDefaultNamespace } from \"./namespace.js\";\nimport { buildVectorId, hydrateInlineRecord, mapRecordForUpsert } from \"./record-mapper.js\";\nimport type {\n\tCompanionRecord,\n\tDoctorCheck,\n\tDoctorReport,\n\tEmbeddingDimensionsInspection,\n\tHydratedMemoryRecord,\n\tIndexInitializationReport,\n\tMemoryRecordInput,\n\tMetadataFilter,\n\tResolvedPluginConfig,\n\tSmokeTestReport,\n\tUpsertedMemoryRecord,\n\tVectorizeIndexDescription,\n} from \"./types.js\";\nimport { VectorizeClient } from \"./vectorize-client.js\";\n\nconst SMOKE_TEST_TIMEOUT_MS = 30_000;\nconst SMOKE_TEST_POLL_INTERVAL_MS = 1_000;\n\nexport class CloudflareMemoryService {\n\treadonly embeddings: WorkersAiEmbeddingsClient;\n\treadonly vectorize: VectorizeClient;\n\treadonly companionStore: CompanionStore;\n\n\tconstructor(\n\t\treadonly config: ResolvedPluginConfig,\n\t\treadonly openClawConfig: OpenClawConfig,\n\t) {\n\t\tthis.embeddings = new WorkersAiEmbeddingsClient(config);\n\t\tthis.vectorize = new VectorizeClient(config);\n\t\tthis.companionStore = new CompanionStore(config.companionStorePath);\n\t}\n\n\tresolveNamespace(params: { namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): string {\n\t\treturn resolveDefaultNamespace({\n\t\t\tfixedNamespace: params.namespace ?? this.config.fixedNamespace,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tagentId: params.agentId,\n\t\t\tworkspaceDir: params.workspaceDir,\n\t\t});\n\t}\n\n\tasync search(params: {\n\t\tquery: string;\n\t\tnamespace?: string;\n\t\tmaxResults?: number;\n\t\tminScore?: number;\n\t\tfilter?: MetadataFilter;\n\t\tsessionKey?: string;\n\t\tagentId?: string;\n\t\tworkspaceDir?: string;\n\t}): Promise<Array<HydratedMemoryRecord & { score: number }>> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tconst vector = await this.embeddings.embedQuery(params.query);\n\t\tconst matches = await this.vectorize.query({\n\t\t\tvector,\n\t\t\tnamespace,\n\t\t\ttopK: params.maxResults ?? this.config.topK,\n\t\t\tfilter: params.filter,\n\t\t});\n\n\t\tconst hydrated = await Promise.all(\n\t\t\tmatches.map(async (match) => {\n\t\t\t\tconst base = hydrateInlineRecord(match);\n\t\t\t\tconst text = base.text ?? (await this.companionStore.get(base.namespace, base.logicalId))?.text ?? \"\";\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\ttext,\n\t\t\t\t\tscore: match.score ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\treturn hydrated.filter((record) => record.score >= (params.minScore ?? this.config.minScore));\n\t}\n\n\tasync get(params: { id: string; namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<HydratedMemoryRecord | null> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tconst vectorId = buildVectorId(namespace, params.id);\n\t\tconst [match] = await this.vectorize.getByIds([vectorId]);\n\t\tif (!match) {\n\t\t\treturn null;\n\t\t}\n\t\tconst base = hydrateInlineRecord(match);\n\t\tconst companion = await this.companionStore.get(base.namespace, base.logicalId);\n\t\treturn {\n\t\t\t...base,\n\t\t\ttext: base.text ?? companion?.text ?? \"\",\n\t\t};\n\t}\n\n\tasync upsert(params: { input: MemoryRecordInput; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<UpsertedMemoryRecord> {\n\t\tconst namespace = this.resolveNamespace({\n\t\t\tnamespace: params.input.namespace,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tagentId: params.agentId,\n\t\t\tworkspaceDir: params.workspaceDir,\n\t\t});\n\t\tconst embedding = await this.embeddings.embedQuery(params.input.text);\n\t\tconst mapped = mapRecordForUpsert({\n\t\t\tinput: params.input,\n\t\t\tnamespace,\n\t\t\tembedding,\n\t\t\tconfig: this.config,\n\t\t});\n\n\t\tif (mapped.companionRecord) {\n\t\t\tawait this.companionStore.upsert(mapped.companionRecord);\n\t\t}\n\n\t\tconst mutationId = await this.vectorize.upsert([mapped.vector]);\n\t\tconst hydrated = await this.get({\n\t\t\tid: mapped.logicalId,\n\t\t\tnamespace,\n\t\t});\n\t\tconst fallback =\n\t\t\tmapped.companionRecord === undefined\n\t\t\t\t? this.fromInlineFallback(mapped.vector)\n\t\t\t\t: this.fromCompanionFallback(mapped.companionRecord, mapped.logicalId, namespace, mapped.path);\n\t\tconst resolved = hydrated\n\t\t\t? {\n\t\t\t\t\t...fallback,\n\t\t\t\t\t...hydrated,\n\t\t\t\t\ttitle: hydrated.title ?? fallback.title,\n\t\t\t\t\ttext: hydrated.text || fallback.text,\n\t\t\t\t\tmetadata: Object.keys(hydrated.metadata).length > 0 ? hydrated.metadata : fallback.metadata,\n\t\t\t\t\tsource: hydrated.source ?? fallback.source,\n\t\t\t\t\tcreatedAt: hydrated.createdAt ?? fallback.createdAt,\n\t\t\t\t\tupdatedAt: hydrated.updatedAt ?? fallback.updatedAt,\n\t\t\t\t}\n\t\t\t: fallback;\n\n\t\treturn {\n\t\t\t...resolved,\n\t\t\tmutationId,\n\t\t};\n\t}\n\n\tasync delete(params: { id: string; namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<string | undefined> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tawait this.companionStore.delete(namespace, params.id);\n\t\treturn this.vectorize.deleteByIds([buildVectorId(namespace, params.id)]);\n\t}\n\n\tasync doctor(options: { createIndexIfMissing?: boolean }): Promise<DoctorReport> {\n\t\treturn runDoctor({\n\t\t\tservice: this,\n\t\t\tcreateIndexIfMissing: options.createIndexIfMissing ?? false,\n\t\t});\n\t}\n\n\tasync inspectEmbeddingDimensions(): Promise<EmbeddingDimensionsInspection> {\n\t\tconst embeddingDimensions = await this.embeddings.probeDimensions();\n\t\tconst configuredDimensions = this.config.createIndex.dimensions;\n\t\treturn {\n\t\t\tembeddingDimensions,\n\t\t\tconfiguredDimensions,\n\t\t\tconfiguredDimensionsMatchModel: configuredDimensions === undefined || configuredDimensions === embeddingDimensions,\n\t\t\ttargetDimensions: embeddingDimensions,\n\t\t};\n\t}\n\n\tasync describeIndexIfExists(): Promise<VectorizeIndexDescription | null> {\n\t\ttry {\n\t\t\treturn await this.vectorize.describeIndex();\n\t\t} catch (error) {\n\t\t\tif (isCloudflareNotFoundError(error)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync initializeIndex(options?: { recreateIfDimensionMismatch?: boolean }): Promise<IndexInitializationReport> {\n\t\tconst recreateIfDimensionMismatch = options?.recreateIfDimensionMismatch ?? true;\n\t\tconst checks: DoctorCheck[] = [];\n\t\tchecks.push({\n\t\t\tname: \"credentials\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Using Cloudflare account ${this.config.accountId} and Vectorize index ${this.config.indexName}.`,\n\t\t});\n\n\t\tconst embedding = await this.inspectEmbeddingDimensions();\n\t\tchecks.push({\n\t\t\tname: \"workers-ai-embeddings\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Workers AI model ${this.config.model} returned ${embedding.embeddingDimensions} dimensions.`,\n\t\t});\n\t\tif (embedding.configuredDimensions !== undefined) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"create-index-dimensions\",\n\t\t\t\tstatus: embedding.configuredDimensionsMatchModel ? \"pass\" : \"warn\",\n\t\t\t\tmessage: embedding.configuredDimensionsMatchModel\n\t\t\t\t\t? `Configured createIndex.dimensions matches the embedding model (${embedding.embeddingDimensions}).`\n\t\t\t\t\t: `Configured createIndex.dimensions (${embedding.configuredDimensions}) does not match the embedding model (${embedding.embeddingDimensions}). Using the live embedding dimensions for initialization.`,\n\t\t\t});\n\t\t}\n\n\t\tconst existingIndex = await this.describeIndexIfExists();\n\t\tlet created = false;\n\t\tlet recreated = false;\n\t\tlet indexDimensions = existingIndex?.config.dimensions;\n\n\t\tif (!existingIndex) {\n\t\t\tconst createdIndex = await this.vectorize.createIndex(embedding.targetDimensions);\n\t\t\tcreated = true;\n\t\t\tindexDimensions = createdIndex.config.dimensions;\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `Created Vectorize index \"${this.config.indexName}\" with ${indexDimensions} dimensions.`,\n\t\t\t});\n\t\t} else if (existingIndex.config.dimensions === embedding.targetDimensions) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `Vectorize index \"${this.config.indexName}\" already uses ${existingIndex.config.dimensions} dimensions.`,\n\t\t\t});\n\t\t} else if (!recreateIfDimensionMismatch) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: `Vectorize index \"${this.config.indexName}\" uses ${existingIndex.config.dimensions} dimensions, but the embedding model requires ${embedding.targetDimensions}. Recreate the index or rerun init with recreation enabled.`,\n\t\t\t});\n\t\t} else {\n\t\t\tawait this.vectorize.deleteIndex();\n\t\t\tconst recreatedIndex = await this.vectorize.createIndex(embedding.targetDimensions);\n\t\t\trecreated = true;\n\t\t\tindexDimensions = recreatedIndex.config.dimensions;\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `Recreated Vectorize index \"${this.config.indexName}\" from ${existingIndex.config.dimensions} to ${indexDimensions} dimensions.`,\n\t\t\t});\n\t\t}\n\n\t\tchecks.push({\n\t\t\tname: \"dimension-match\",\n\t\t\tstatus: indexDimensions === embedding.embeddingDimensions ? \"pass\" : \"fail\",\n\t\t\tmessage:\n\t\t\t\tindexDimensions === embedding.embeddingDimensions\n\t\t\t\t\t? \"Embedding dimensions match the Vectorize index.\"\n\t\t\t\t\t: `Embedding dimensions (${embedding.embeddingDimensions}) do not match the Vectorize index dimensions (${indexDimensions ?? \"unknown\"}).`,\n\t\t});\n\t\tchecks.push({\n\t\t\tname: \"metadata-filters\",\n\t\t\tstatus: this.config.metadataIndexedFields.length > 0 ? \"pass\" : \"warn\",\n\t\t\tmessage:\n\t\t\t\tthis.config.metadataIndexedFields.length > 0\n\t\t\t\t\t? `Configured metadata-index guidance for: ${this.config.metadataIndexedFields.join(\", \")}.`\n\t\t\t\t\t: \"No metadataIndexedFields configured. Add metadata indexes in Cloudflare before relying on filter-heavy queries.\",\n\t\t});\n\n\t\treturn {\n\t\t\tok: checks.every((check) => check.status !== \"fail\"),\n\t\t\tchecks,\n\t\t\tcreated,\n\t\t\trecreated,\n\t\t\tembeddingDimensions: embedding.embeddingDimensions,\n\t\t\tindexDimensions,\n\t\t};\n\t}\n\n\tasync runSmokeTest(options?: { timeoutMs?: number; pollIntervalMs?: number }): Promise<SmokeTestReport> {\n\t\tconst checks: DoctorCheck[] = [];\n\t\tchecks.push({\n\t\t\tname: \"credentials\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Using Cloudflare account ${this.config.accountId} and Vectorize index ${this.config.indexName}.`,\n\t\t});\n\n\t\tconst embedding = await this.inspectEmbeddingDimensions();\n\t\tchecks.push({\n\t\t\tname: \"workers-ai-embeddings\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Workers AI model ${this.config.model} returned ${embedding.embeddingDimensions} dimensions.`,\n\t\t});\n\t\tif (embedding.configuredDimensions !== undefined) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"create-index-dimensions\",\n\t\t\t\tstatus: embedding.configuredDimensionsMatchModel ? \"pass\" : \"warn\",\n\t\t\t\tmessage: embedding.configuredDimensionsMatchModel\n\t\t\t\t\t? `Configured createIndex.dimensions matches the embedding model (${embedding.embeddingDimensions}).`\n\t\t\t\t\t: `Configured createIndex.dimensions (${embedding.configuredDimensions}) does not match the embedding model (${embedding.embeddingDimensions}). Using the live embedding dimensions for validation.`,\n\t\t\t});\n\t\t}\n\n\t\tconst existingIndex = await this.describeIndexIfExists();\n\t\tif (!existingIndex) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"vectorize-index\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: `Vectorize index \"${this.config.indexName}\" was not found. Run \"openclaw cf-memory init\" before rerunning this test.`,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tchecks,\n\t\t\t\tnamespace: \"n/a\",\n\t\t\t\tlogicalId: \"n/a\",\n\t\t\t};\n\t\t}\n\n\t\tchecks.push({\n\t\t\tname: \"vectorize-index\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: `Vectorize index \"${this.config.indexName}\" is reachable.`,\n\t\t});\n\t\tif (existingIndex.config.dimensions !== embedding.embeddingDimensions) {\n\t\t\tchecks.push({\n\t\t\t\tname: \"dimension-match\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: `Embedding dimensions (${embedding.embeddingDimensions}) do not match the Vectorize index dimensions (${existingIndex.config.dimensions}). Run \"openclaw cf-memory init\" to repair the index.`,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tchecks,\n\t\t\t\tnamespace: \"n/a\",\n\t\t\t\tlogicalId: \"n/a\",\n\t\t\t};\n\t\t}\n\n\t\tchecks.push({\n\t\t\tname: \"dimension-match\",\n\t\t\tstatus: \"pass\",\n\t\t\tmessage: \"Embedding dimensions match the Vectorize index.\",\n\t\t});\n\n\t\tconst namespace = sanitizeNamespace(`cf-memory-test-${randomUUID()}`);\n\t\tconst logicalId = `cf-memory-test-${randomUUID()}`;\n\t\tconst probeText = `OpenClaw Cloudflare memory smoke test ${logicalId}`;\n\t\tlet probeUpserted = false;\n\n\t\ttry {\n\t\t\tawait this.upsert({\n\t\t\t\tinput: {\n\t\t\t\t\tid: logicalId,\n\t\t\t\t\tnamespace,\n\t\t\t\t\ttext: probeText,\n\t\t\t\t\tsource: \"cf-memory-test\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tprobe: true,\n\t\t\t\t\t\tprobeId: logicalId,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t\tprobeUpserted = true;\n\t\t\tchecks.push({\n\t\t\t\tname: \"probe-upsert\",\n\t\t\t\tstatus: \"pass\",\n\t\t\t\tmessage: `Inserted smoke-test record ${logicalId} in namespace ${namespace}.`,\n\t\t\t});\n\n\t\t\tconst found = await this.waitForSearchHit({\n\t\t\t\tquery: probeText,\n\t\t\t\tnamespace,\n\t\t\t\tlogicalId,\n\t\t\t\ttimeoutMs: options?.timeoutMs ?? SMOKE_TEST_TIMEOUT_MS,\n\t\t\t\tpollIntervalMs: options?.pollIntervalMs ?? SMOKE_TEST_POLL_INTERVAL_MS,\n\t\t\t});\n\t\t\tchecks.push({\n\t\t\t\tname: \"probe-search\",\n\t\t\t\tstatus: found ? \"pass\" : \"fail\",\n\t\t\t\tmessage: found\n\t\t\t\t\t? \"Semantic search returned the smoke-test record.\"\n\t\t\t\t\t: `Semantic search did not return the smoke-test record within ${(options?.timeoutMs ?? SMOKE_TEST_TIMEOUT_MS) / 1000} seconds.`,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tchecks.push({\n\t\t\t\tname: probeUpserted ? \"probe-search\" : \"probe-upsert\",\n\t\t\t\tstatus: \"fail\",\n\t\t\t\tmessage: error instanceof Error ? error.message : \"Smoke test failed with an unknown error.\",\n\t\t\t});\n\t\t} finally {\n\t\t\ttry {\n\t\t\t\tawait this.delete({ id: logicalId, namespace });\n\t\t\t\tchecks.push({\n\t\t\t\t\tname: \"probe-cleanup\",\n\t\t\t\t\tstatus: \"pass\",\n\t\t\t\t\tmessage: `Deleted smoke-test record ${logicalId}.`,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tchecks.push({\n\t\t\t\t\tname: \"probe-cleanup\",\n\t\t\t\t\tstatus: \"fail\",\n\t\t\t\t\tmessage: error instanceof Error ? error.message : `Failed to delete smoke-test record ${logicalId}.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tok: checks.every((check) => check.status !== \"fail\"),\n\t\t\tchecks,\n\t\t\tnamespace,\n\t\t\tlogicalId,\n\t\t};\n\t}\n\n\tasync ensureIndexExists(createIfMissing: boolean, targetDimensions?: number): Promise<{ created: boolean; dimensions: number }> {\n\t\ttry {\n\t\t\tconst description = await this.vectorize.describeIndex();\n\t\t\treturn {\n\t\t\t\tcreated: false,\n\t\t\t\tdimensions: description.config.dimensions,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (!createIfMissing || !isCloudflareNotFoundError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst dimensions = targetDimensions ?? (await this.inspectEmbeddingDimensions()).targetDimensions;\n\t\t\tconst createdIndex = await this.vectorize.createIndex(dimensions);\n\t\t\treturn {\n\t\t\t\tcreated: true,\n\t\t\t\tdimensions: createdIndex.config.dimensions,\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate fromCompanionFallback(companionRecord: CompanionRecord | undefined, logicalId: string, namespace: string, path: string): UpsertedMemoryRecord {\n\t\treturn {\n\t\t\tlogicalId,\n\t\t\tvectorId: buildVectorId(namespace, logicalId),\n\t\t\tnamespace,\n\t\t\ttitle: companionRecord?.title,\n\t\t\ttext: companionRecord?.text ?? \"\",\n\t\t\tmetadata: companionRecord?.metadata ?? {},\n\t\t\tsource: companionRecord?.source,\n\t\t\tcreatedAt: companionRecord?.createdAt,\n\t\t\tupdatedAt: companionRecord?.updatedAt,\n\t\t\tpath,\n\t\t};\n\t}\n\n\tprivate fromInlineFallback(vector: { id: string; namespace?: string; metadata?: Record<string, string | number | boolean> }): UpsertedMemoryRecord {\n\t\tconst record = hydrateInlineRecord(vector);\n\t\treturn {\n\t\t\t...record,\n\t\t\ttext: record.text ?? \"\",\n\t\t};\n\t}\n\n\tprivate async waitForSearchHit(params: { query: string; namespace: string; logicalId: string; timeoutMs: number; pollIntervalMs: number }): Promise<boolean> {\n\t\tconst deadline = Date.now() + params.timeoutMs;\n\t\twhile (Date.now() <= deadline) {\n\t\t\tconst results = await this.search({\n\t\t\t\tquery: params.query,\n\t\t\t\tnamespace: params.namespace,\n\t\t\t\tmaxResults: 5,\n\t\t\t\tminScore: 0,\n\t\t\t});\n\t\t\tif (results.some((record) => record.logicalId === params.logicalId)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (Date.now() + params.pollIntervalMs > deadline) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait this.pause(params.pollIntervalMs);\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate async pause(ms: number): Promise<void> {\n\t\tawait new Promise((resolve) => setTimeout(resolve, ms));\n\t}\n}\n"],"mappings":"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"}
package/dist/tools.js CHANGED
@@ -5,9 +5,10 @@ async function n(t, n) {
5
5
  let r = n.runtimeConfig ?? n.config;
6
6
  if (!r) throw Error("Cloudflare memory tools require an OpenClaw runtime config.");
7
7
  return e({
8
- pluginConfig: t,
8
+ pluginConfig: t.pluginConfig,
9
9
  openClawConfig: r,
10
- env: process.env
10
+ env: process.env,
11
+ resolvePath: t.resolvePath
11
12
  });
12
13
  }
13
14
  function r(e, t) {
package/dist/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","names":[],"sources":["../src/tools.ts"],"sourcesContent":["import { Type } from \"@sinclair/typebox\";\nimport type { AnyAgentTool, OpenClawPluginToolContext } from \"openclaw/plugin-sdk/plugin-entry\";\nimport type { CloudflareMemoryService } from \"./service.js\";\nimport { createCloudflareMemoryService } from \"./service-factory.js\";\nimport type { MetadataFilter, MetadataValue } from \"./types.js\";\n\nasync function buildService(pluginConfig: unknown, ctx: OpenClawPluginToolContext): Promise<CloudflareMemoryService> {\n\tconst runtimeConfig = ctx.runtimeConfig ?? ctx.config;\n\tif (!runtimeConfig) {\n\t\tthrow new Error(\"Cloudflare memory tools require an OpenClaw runtime config.\");\n\t}\n\treturn createCloudflareMemoryService({\n\t\tpluginConfig,\n\t\topenClawConfig: runtimeConfig,\n\t\tenv: process.env,\n\t});\n}\n\nfunction parseJsonObject<T>(value: string | undefined, label: string): T | undefined {\n\tif (!value) {\n\t\treturn undefined;\n\t}\n\tconst parsed = JSON.parse(value) as unknown;\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`${label} must be a JSON object.`);\n\t}\n\treturn parsed as T;\n}\n\nconst metadataValueSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean()]);\n\nfunction textResult<TDetails>(text: string, details: TDetails) {\n\treturn {\n\t\tcontent: [{ type: \"text\" as const, text }],\n\t\tdetails,\n\t};\n}\n\nexport function createSearchTool(pluginConfig: unknown, ctx: OpenClawPluginToolContext): AnyAgentTool {\n\treturn {\n\t\tname: \"cloudflare_memory_search\",\n\t\tlabel: \"Cloudflare Memory Search\",\n\t\tdescription: \"Search Cloudflare-backed memory records using semantic retrieval.\",\n\t\tparameters: Type.Object({\n\t\t\tquery: Type.String({ description: \"Semantic search query.\" }),\n\t\t\tnamespace: Type.Optional(Type.String({ description: \"Optional namespace override.\" })),\n\t\t\tmaxResults: Type.Optional(Type.Number({ description: \"Maximum results to return.\" })),\n\t\t\tminScore: Type.Optional(Type.Number({ description: \"Minimum similarity score from 0 to 1.\" })),\n\t\t\tfilterJson: Type.Optional(Type.String({ description: \"Optional JSON object for Vectorize metadata filtering.\" })),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate) {\n\t\t\tconst service = await buildService(pluginConfig, ctx);\n\t\t\tconst filter = parseJsonObject<MetadataFilter>(params.filterJson as string | undefined, \"filterJson\");\n\t\t\tconst records = await service.search({\n\t\t\t\tquery: params.query as string,\n\t\t\t\tnamespace: params.namespace as string | undefined,\n\t\t\t\tmaxResults: params.maxResults as number | undefined,\n\t\t\t\tminScore: params.minScore as number | undefined,\n\t\t\t\tfilter,\n\t\t\t\tsessionKey: ctx.sessionKey,\n\t\t\t\tagentId: ctx.agentId,\n\t\t\t\tworkspaceDir: ctx.workspaceDir,\n\t\t\t});\n\t\t\tif (records.length === 0) {\n\t\t\t\treturn textResult(\"No matching memories found.\", { count: 0, records: [] });\n\t\t\t}\n\t\t\tconst text = records\n\t\t\t\t.map((record, index) => `${index + 1}. [${record.namespace}] ${record.title ?? record.logicalId} (${record.score.toFixed(3)})\\n${record.text}`)\n\t\t\t\t.join(\"\\n\\n\");\n\t\t\treturn textResult(text, {\n\t\t\t\tcount: records.length,\n\t\t\t\trecords: records.map((record) => ({\n\t\t\t\t\tid: record.logicalId,\n\t\t\t\t\tnamespace: record.namespace,\n\t\t\t\t\ttitle: record.title,\n\t\t\t\t\tscore: record.score,\n\t\t\t\t\tpath: record.path,\n\t\t\t\t})),\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport function createGetTool(pluginConfig: unknown, ctx: OpenClawPluginToolContext): AnyAgentTool {\n\treturn {\n\t\tname: \"cloudflare_memory_get\",\n\t\tlabel: \"Cloudflare Memory Get\",\n\t\tdescription: \"Get a Cloudflare-backed memory record by id.\",\n\t\tparameters: Type.Object({\n\t\t\tid: Type.String({ description: \"Logical memory record id.\" }),\n\t\t\tnamespace: Type.Optional(Type.String({ description: \"Optional namespace override.\" })),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate) {\n\t\t\tconst service = await buildService(pluginConfig, ctx);\n\t\t\tconst record = await service.get({\n\t\t\t\tid: params.id as string,\n\t\t\t\tnamespace: params.namespace as string | undefined,\n\t\t\t\tsessionKey: ctx.sessionKey,\n\t\t\t\tagentId: ctx.agentId,\n\t\t\t\tworkspaceDir: ctx.workspaceDir,\n\t\t\t});\n\t\t\tif (!record) {\n\t\t\t\treturn textResult(\"Memory record not found.\", { found: false });\n\t\t\t}\n\t\t\treturn textResult(`${record.title ?? record.logicalId}\\nNamespace: ${record.namespace}\\nPath: ${record.path}\\n\\n${record.text}`, {\n\t\t\t\tfound: true,\n\t\t\t\tid: record.logicalId,\n\t\t\t\tnamespace: record.namespace,\n\t\t\t\tmetadata: record.metadata,\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport function createUpsertTool(pluginConfig: unknown, ctx: OpenClawPluginToolContext): AnyAgentTool {\n\treturn {\n\t\tname: \"cloudflare_memory_upsert\",\n\t\tlabel: \"Cloudflare Memory Upsert\",\n\t\tdescription: \"Insert or update a Cloudflare-backed memory record.\",\n\t\tparameters: Type.Object({\n\t\t\tid: Type.Optional(Type.String({ description: \"Optional stable logical id.\" })),\n\t\t\ttitle: Type.Optional(Type.String({ description: \"Optional title.\" })),\n\t\t\ttext: Type.String({ description: \"Memory text to store.\" }),\n\t\t\tnamespace: Type.Optional(Type.String({ description: \"Optional namespace override.\" })),\n\t\t\tsource: Type.Optional(Type.String({ description: \"Optional source label.\" })),\n\t\t\tmetadata: Type.Optional(\n\t\t\t\tType.Record(Type.String(), metadataValueSchema, {\n\t\t\t\t\tdescription: \"Flat metadata object with string, number, or boolean values.\",\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate) {\n\t\t\tconst service = await buildService(pluginConfig, ctx);\n\t\t\tconst record = await service.upsert({\n\t\t\t\tinput: {\n\t\t\t\t\tid: params.id as string | undefined,\n\t\t\t\t\ttitle: params.title as string | undefined,\n\t\t\t\t\ttext: params.text as string,\n\t\t\t\t\tnamespace: params.namespace as string | undefined,\n\t\t\t\t\tsource: params.source as string | undefined,\n\t\t\t\t\tmetadata: params.metadata as Record<string, MetadataValue> | undefined,\n\t\t\t\t},\n\t\t\t\tsessionKey: ctx.sessionKey,\n\t\t\t\tagentId: ctx.agentId,\n\t\t\t\tworkspaceDir: ctx.workspaceDir,\n\t\t\t});\n\t\t\treturn textResult(`Stored memory ${record.logicalId} in namespace ${record.namespace}.`, {\n\t\t\t\tid: record.logicalId,\n\t\t\t\tnamespace: record.namespace,\n\t\t\t\tpath: record.path,\n\t\t\t\tmutationId: record.mutationId,\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport function createDeleteTool(pluginConfig: unknown, ctx: OpenClawPluginToolContext): AnyAgentTool {\n\treturn {\n\t\tname: \"cloudflare_memory_delete\",\n\t\tlabel: \"Cloudflare Memory Delete\",\n\t\tdescription: \"Delete a Cloudflare-backed memory record by id.\",\n\t\tparameters: Type.Object({\n\t\t\tid: Type.String({ description: \"Logical memory record id.\" }),\n\t\t\tnamespace: Type.Optional(Type.String({ description: \"Optional namespace override.\" })),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate) {\n\t\t\tconst service = await buildService(pluginConfig, ctx);\n\t\t\tconst mutationId = await service.delete({\n\t\t\t\tid: params.id as string,\n\t\t\t\tnamespace: params.namespace as string | undefined,\n\t\t\t\tsessionKey: ctx.sessionKey,\n\t\t\t\tagentId: ctx.agentId,\n\t\t\t\tworkspaceDir: ctx.workspaceDir,\n\t\t\t});\n\t\t\treturn textResult(`Deleted memory ${params.id as string}.`, { mutationId });\n\t\t},\n\t};\n}\n"],"mappings":";;;AAMA,eAAe,EAAa,GAAuB,GAAkE;CACpH,IAAM,IAAgB,EAAI,iBAAiB,EAAI;AAC/C,KAAI,CAAC,EACJ,OAAU,MAAM,8DAA8D;AAE/E,QAAO,EAA8B;EACpC;EACA,gBAAgB;EAChB,KAAK,QAAQ;EACb,CAAC;;AAGH,SAAS,EAAmB,GAA2B,GAA8B;AACpF,KAAI,CAAC,EACJ;CAED,IAAM,IAAS,KAAK,MAAM,EAAM;AAChC,KAAI,CAAC,KAAU,OAAO,KAAW,YAAY,MAAM,QAAQ,EAAO,CACjE,OAAU,MAAM,GAAG,EAAM,yBAAyB;AAEnD,QAAO;;AAGR,IAAM,IAAsB,EAAK,MAAM;CAAC,EAAK,QAAQ;CAAE,EAAK,QAAQ;CAAE,EAAK,SAAS;CAAC,CAAC;AAEtF,SAAS,EAAqB,GAAc,GAAmB;AAC9D,QAAO;EACN,SAAS,CAAC;GAAE,MAAM;GAAiB;GAAM,CAAC;EAC1C;EACA;;AAGF,SAAgB,EAAiB,GAAuB,GAA8C;AACrG,QAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,EAAK,OAAO;GACvB,OAAO,EAAK,OAAO,EAAE,aAAa,0BAA0B,CAAC;GAC7D,WAAW,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,gCAAgC,CAAC,CAAC;GACtF,YAAY,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,8BAA8B,CAAC,CAAC;GACrF,UAAU,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,yCAAyC,CAAC,CAAC;GAC9F,YAAY,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,0DAA0D,CAAC,CAAC;GACjH,CAAC;EACF,MAAM,QAAQ,GAAa,GAAQ,GAAS,GAAW;GACtD,IAAM,IAAU,MAAM,EAAa,GAAc,EAAI,EAC/C,IAAS,EAAgC,EAAO,YAAkC,aAAa,EAC/F,IAAU,MAAM,EAAQ,OAAO;IACpC,OAAO,EAAO;IACd,WAAW,EAAO;IAClB,YAAY,EAAO;IACnB,UAAU,EAAO;IACjB;IACA,YAAY,EAAI;IAChB,SAAS,EAAI;IACb,cAAc,EAAI;IAClB,CAAC;AAOF,UANI,EAAQ,WAAW,IACf,EAAW,+BAA+B;IAAE,OAAO;IAAG,SAAS,EAAE;IAAE,CAAC,GAKrE,EAHM,EACX,KAAK,GAAQ,MAAU,GAAG,IAAQ,EAAE,KAAK,EAAO,UAAU,IAAI,EAAO,SAAS,EAAO,UAAU,IAAI,EAAO,MAAM,QAAQ,EAAE,CAAC,KAAK,EAAO,OAAO,CAC9I,KAAK,OAAO,EACU;IACvB,OAAO,EAAQ;IACf,SAAS,EAAQ,KAAK,OAAY;KACjC,IAAI,EAAO;KACX,WAAW,EAAO;KAClB,OAAO,EAAO;KACd,OAAO,EAAO;KACd,MAAM,EAAO;KACb,EAAE;IACH,CAAC;;EAEH;;AAGF,SAAgB,EAAc,GAAuB,GAA8C;AAClG,QAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,EAAK,OAAO;GACvB,IAAI,EAAK,OAAO,EAAE,aAAa,6BAA6B,CAAC;GAC7D,WAAW,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,gCAAgC,CAAC,CAAC;GACtF,CAAC;EACF,MAAM,QAAQ,GAAa,GAAQ,GAAS,GAAW;GAEtD,IAAM,IAAS,OADC,MAAM,EAAa,GAAc,EAAI,EACxB,IAAI;IAChC,IAAI,EAAO;IACX,WAAW,EAAO;IAClB,YAAY,EAAI;IAChB,SAAS,EAAI;IACb,cAAc,EAAI;IAClB,CAAC;AAIF,UAHK,IAGE,EAAW,GAAG,EAAO,SAAS,EAAO,UAAU,eAAe,EAAO,UAAU,UAAU,EAAO,KAAK,MAAM,EAAO,QAAQ;IAChI,OAAO;IACP,IAAI,EAAO;IACX,WAAW,EAAO;IAClB,UAAU,EAAO;IACjB,CAAC,GAPM,EAAW,4BAA4B,EAAE,OAAO,IAAO,CAAC;;EASjE;;AAGF,SAAgB,EAAiB,GAAuB,GAA8C;AACrG,QAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,EAAK,OAAO;GACvB,IAAI,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,+BAA+B,CAAC,CAAC;GAC9E,OAAO,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,mBAAmB,CAAC,CAAC;GACrE,MAAM,EAAK,OAAO,EAAE,aAAa,yBAAyB,CAAC;GAC3D,WAAW,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,gCAAgC,CAAC,CAAC;GACtF,QAAQ,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,0BAA0B,CAAC,CAAC;GAC7E,UAAU,EAAK,SACd,EAAK,OAAO,EAAK,QAAQ,EAAE,GAAqB,EAC/C,aAAa,gEACb,CAAC,CACF;GACD,CAAC;EACF,MAAM,QAAQ,GAAa,GAAQ,GAAS,GAAW;GAEtD,IAAM,IAAS,OADC,MAAM,EAAa,GAAc,EAAI,EACxB,OAAO;IACnC,OAAO;KACN,IAAI,EAAO;KACX,OAAO,EAAO;KACd,MAAM,EAAO;KACb,WAAW,EAAO;KAClB,QAAQ,EAAO;KACf,UAAU,EAAO;KACjB;IACD,YAAY,EAAI;IAChB,SAAS,EAAI;IACb,cAAc,EAAI;IAClB,CAAC;AACF,UAAO,EAAW,iBAAiB,EAAO,UAAU,gBAAgB,EAAO,UAAU,IAAI;IACxF,IAAI,EAAO;IACX,WAAW,EAAO;IAClB,MAAM,EAAO;IACb,YAAY,EAAO;IACnB,CAAC;;EAEH;;AAGF,SAAgB,EAAiB,GAAuB,GAA8C;AACrG,QAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,EAAK,OAAO;GACvB,IAAI,EAAK,OAAO,EAAE,aAAa,6BAA6B,CAAC;GAC7D,WAAW,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,gCAAgC,CAAC,CAAC;GACtF,CAAC;EACF,MAAM,QAAQ,GAAa,GAAQ,GAAS,GAAW;GAEtD,IAAM,IAAa,OADH,MAAM,EAAa,GAAc,EAAI,EACpB,OAAO;IACvC,IAAI,EAAO;IACX,WAAW,EAAO;IAClB,YAAY,EAAI;IAChB,SAAS,EAAI;IACb,cAAc,EAAI;IAClB,CAAC;AACF,UAAO,EAAW,kBAAkB,EAAO,GAAa,IAAI,EAAE,eAAY,CAAC;;EAE5E"}
1
+ {"version":3,"file":"tools.js","names":[],"sources":["../src/tools.ts"],"sourcesContent":["import { Type } from \"@sinclair/typebox\";\nimport type { AnyAgentTool, OpenClawPluginToolContext } from \"openclaw/plugin-sdk/plugin-entry\";\nimport type { CloudflareMemoryService } from \"./service.js\";\nimport { createCloudflareMemoryService } from \"./service-factory.js\";\nimport type { MetadataFilter, MetadataValue } from \"./types.js\";\n\ntype ToolRegistrationContext = {\n\tpluginConfig: unknown;\n\tresolvePath?: (input: string) => string;\n};\n\nasync function buildService(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): Promise<CloudflareMemoryService> {\n\tconst runtimeConfig = ctx.runtimeConfig ?? ctx.config;\n\tif (!runtimeConfig) {\n\t\tthrow new Error(\"Cloudflare memory tools require an OpenClaw runtime config.\");\n\t}\n\treturn createCloudflareMemoryService({\n\t\tpluginConfig: registration.pluginConfig,\n\t\topenClawConfig: runtimeConfig,\n\t\tenv: process.env,\n\t\tresolvePath: registration.resolvePath,\n\t});\n}\n\nfunction parseJsonObject<T>(value: string | undefined, label: string): T | undefined {\n\tif (!value) {\n\t\treturn undefined;\n\t}\n\tconst parsed = JSON.parse(value) as unknown;\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`${label} must be a JSON object.`);\n\t}\n\treturn parsed as T;\n}\n\nconst metadataValueSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean()]);\n\nfunction textResult<TDetails>(text: string, details: TDetails) {\n\treturn {\n\t\tcontent: [{ type: \"text\" as const, text }],\n\t\tdetails,\n\t};\n}\n\nexport function createSearchTool(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): AnyAgentTool {\n\treturn {\n\t\tname: \"cloudflare_memory_search\",\n\t\tlabel: \"Cloudflare Memory Search\",\n\t\tdescription: \"Search Cloudflare-backed memory records using semantic retrieval.\",\n\t\tparameters: Type.Object({\n\t\t\tquery: Type.String({ description: \"Semantic search query.\" }),\n\t\t\tnamespace: Type.Optional(Type.String({ description: \"Optional namespace override.\" })),\n\t\t\tmaxResults: Type.Optional(Type.Number({ description: \"Maximum results to return.\" })),\n\t\t\tminScore: Type.Optional(Type.Number({ description: \"Minimum similarity score from 0 to 1.\" })),\n\t\t\tfilterJson: Type.Optional(Type.String({ description: \"Optional JSON object for Vectorize metadata filtering.\" })),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate) {\n\t\t\tconst service = await buildService(registration, ctx);\n\t\t\tconst filter = parseJsonObject<MetadataFilter>(params.filterJson as string | undefined, \"filterJson\");\n\t\t\tconst records = await service.search({\n\t\t\t\tquery: params.query as string,\n\t\t\t\tnamespace: params.namespace as string | undefined,\n\t\t\t\tmaxResults: params.maxResults as number | undefined,\n\t\t\t\tminScore: params.minScore as number | undefined,\n\t\t\t\tfilter,\n\t\t\t\tsessionKey: ctx.sessionKey,\n\t\t\t\tagentId: ctx.agentId,\n\t\t\t\tworkspaceDir: ctx.workspaceDir,\n\t\t\t});\n\t\t\tif (records.length === 0) {\n\t\t\t\treturn textResult(\"No matching memories found.\", { count: 0, records: [] });\n\t\t\t}\n\t\t\tconst text = records\n\t\t\t\t.map((record, index) => `${index + 1}. [${record.namespace}] ${record.title ?? record.logicalId} (${record.score.toFixed(3)})\\n${record.text}`)\n\t\t\t\t.join(\"\\n\\n\");\n\t\t\treturn textResult(text, {\n\t\t\t\tcount: records.length,\n\t\t\t\trecords: records.map((record) => ({\n\t\t\t\t\tid: record.logicalId,\n\t\t\t\t\tnamespace: record.namespace,\n\t\t\t\t\ttitle: record.title,\n\t\t\t\t\tscore: record.score,\n\t\t\t\t\tpath: record.path,\n\t\t\t\t})),\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport function createGetTool(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): AnyAgentTool {\n\treturn {\n\t\tname: \"cloudflare_memory_get\",\n\t\tlabel: \"Cloudflare Memory Get\",\n\t\tdescription: \"Get a Cloudflare-backed memory record by id.\",\n\t\tparameters: Type.Object({\n\t\t\tid: Type.String({ description: \"Logical memory record id.\" }),\n\t\t\tnamespace: Type.Optional(Type.String({ description: \"Optional namespace override.\" })),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate) {\n\t\t\tconst service = await buildService(registration, ctx);\n\t\t\tconst record = await service.get({\n\t\t\t\tid: params.id as string,\n\t\t\t\tnamespace: params.namespace as string | undefined,\n\t\t\t\tsessionKey: ctx.sessionKey,\n\t\t\t\tagentId: ctx.agentId,\n\t\t\t\tworkspaceDir: ctx.workspaceDir,\n\t\t\t});\n\t\t\tif (!record) {\n\t\t\t\treturn textResult(\"Memory record not found.\", { found: false });\n\t\t\t}\n\t\t\treturn textResult(`${record.title ?? record.logicalId}\\nNamespace: ${record.namespace}\\nPath: ${record.path}\\n\\n${record.text}`, {\n\t\t\t\tfound: true,\n\t\t\t\tid: record.logicalId,\n\t\t\t\tnamespace: record.namespace,\n\t\t\t\tmetadata: record.metadata,\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport function createUpsertTool(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): AnyAgentTool {\n\treturn {\n\t\tname: \"cloudflare_memory_upsert\",\n\t\tlabel: \"Cloudflare Memory Upsert\",\n\t\tdescription: \"Insert or update a Cloudflare-backed memory record.\",\n\t\tparameters: Type.Object({\n\t\t\tid: Type.Optional(Type.String({ description: \"Optional stable logical id.\" })),\n\t\t\ttitle: Type.Optional(Type.String({ description: \"Optional title.\" })),\n\t\t\ttext: Type.String({ description: \"Memory text to store.\" }),\n\t\t\tnamespace: Type.Optional(Type.String({ description: \"Optional namespace override.\" })),\n\t\t\tsource: Type.Optional(Type.String({ description: \"Optional source label.\" })),\n\t\t\tmetadata: Type.Optional(\n\t\t\t\tType.Record(Type.String(), metadataValueSchema, {\n\t\t\t\t\tdescription: \"Flat metadata object with string, number, or boolean values.\",\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate) {\n\t\t\tconst service = await buildService(registration, ctx);\n\t\t\tconst record = await service.upsert({\n\t\t\t\tinput: {\n\t\t\t\t\tid: params.id as string | undefined,\n\t\t\t\t\ttitle: params.title as string | undefined,\n\t\t\t\t\ttext: params.text as string,\n\t\t\t\t\tnamespace: params.namespace as string | undefined,\n\t\t\t\t\tsource: params.source as string | undefined,\n\t\t\t\t\tmetadata: params.metadata as Record<string, MetadataValue> | undefined,\n\t\t\t\t},\n\t\t\t\tsessionKey: ctx.sessionKey,\n\t\t\t\tagentId: ctx.agentId,\n\t\t\t\tworkspaceDir: ctx.workspaceDir,\n\t\t\t});\n\t\t\treturn textResult(`Stored memory ${record.logicalId} in namespace ${record.namespace}.`, {\n\t\t\t\tid: record.logicalId,\n\t\t\t\tnamespace: record.namespace,\n\t\t\t\tpath: record.path,\n\t\t\t\tmutationId: record.mutationId,\n\t\t\t});\n\t\t},\n\t};\n}\n\nexport function createDeleteTool(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): AnyAgentTool {\n\treturn {\n\t\tname: \"cloudflare_memory_delete\",\n\t\tlabel: \"Cloudflare Memory Delete\",\n\t\tdescription: \"Delete a Cloudflare-backed memory record by id.\",\n\t\tparameters: Type.Object({\n\t\t\tid: Type.String({ description: \"Logical memory record id.\" }),\n\t\t\tnamespace: Type.Optional(Type.String({ description: \"Optional namespace override.\" })),\n\t\t}),\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate) {\n\t\t\tconst service = await buildService(registration, ctx);\n\t\t\tconst mutationId = await service.delete({\n\t\t\t\tid: params.id as string,\n\t\t\t\tnamespace: params.namespace as string | undefined,\n\t\t\t\tsessionKey: ctx.sessionKey,\n\t\t\t\tagentId: ctx.agentId,\n\t\t\t\tworkspaceDir: ctx.workspaceDir,\n\t\t\t});\n\t\t\treturn textResult(`Deleted memory ${params.id as string}.`, { mutationId });\n\t\t},\n\t};\n}\n"],"mappings":";;;AAWA,eAAe,EAAa,GAAuC,GAAkE;CACpI,IAAM,IAAgB,EAAI,iBAAiB,EAAI;AAC/C,KAAI,CAAC,EACJ,OAAU,MAAM,8DAA8D;AAE/E,QAAO,EAA8B;EACpC,cAAc,EAAa;EAC3B,gBAAgB;EAChB,KAAK,QAAQ;EACb,aAAa,EAAa;EAC1B,CAAC;;AAGH,SAAS,EAAmB,GAA2B,GAA8B;AACpF,KAAI,CAAC,EACJ;CAED,IAAM,IAAS,KAAK,MAAM,EAAM;AAChC,KAAI,CAAC,KAAU,OAAO,KAAW,YAAY,MAAM,QAAQ,EAAO,CACjE,OAAU,MAAM,GAAG,EAAM,yBAAyB;AAEnD,QAAO;;AAGR,IAAM,IAAsB,EAAK,MAAM;CAAC,EAAK,QAAQ;CAAE,EAAK,QAAQ;CAAE,EAAK,SAAS;CAAC,CAAC;AAEtF,SAAS,EAAqB,GAAc,GAAmB;AAC9D,QAAO;EACN,SAAS,CAAC;GAAE,MAAM;GAAiB;GAAM,CAAC;EAC1C;EACA;;AAGF,SAAgB,EAAiB,GAAuC,GAA8C;AACrH,QAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,EAAK,OAAO;GACvB,OAAO,EAAK,OAAO,EAAE,aAAa,0BAA0B,CAAC;GAC7D,WAAW,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,gCAAgC,CAAC,CAAC;GACtF,YAAY,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,8BAA8B,CAAC,CAAC;GACrF,UAAU,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,yCAAyC,CAAC,CAAC;GAC9F,YAAY,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,0DAA0D,CAAC,CAAC;GACjH,CAAC;EACF,MAAM,QAAQ,GAAa,GAAQ,GAAS,GAAW;GACtD,IAAM,IAAU,MAAM,EAAa,GAAc,EAAI,EAC/C,IAAS,EAAgC,EAAO,YAAkC,aAAa,EAC/F,IAAU,MAAM,EAAQ,OAAO;IACpC,OAAO,EAAO;IACd,WAAW,EAAO;IAClB,YAAY,EAAO;IACnB,UAAU,EAAO;IACjB;IACA,YAAY,EAAI;IAChB,SAAS,EAAI;IACb,cAAc,EAAI;IAClB,CAAC;AAOF,UANI,EAAQ,WAAW,IACf,EAAW,+BAA+B;IAAE,OAAO;IAAG,SAAS,EAAE;IAAE,CAAC,GAKrE,EAHM,EACX,KAAK,GAAQ,MAAU,GAAG,IAAQ,EAAE,KAAK,EAAO,UAAU,IAAI,EAAO,SAAS,EAAO,UAAU,IAAI,EAAO,MAAM,QAAQ,EAAE,CAAC,KAAK,EAAO,OAAO,CAC9I,KAAK,OAAO,EACU;IACvB,OAAO,EAAQ;IACf,SAAS,EAAQ,KAAK,OAAY;KACjC,IAAI,EAAO;KACX,WAAW,EAAO;KAClB,OAAO,EAAO;KACd,OAAO,EAAO;KACd,MAAM,EAAO;KACb,EAAE;IACH,CAAC;;EAEH;;AAGF,SAAgB,EAAc,GAAuC,GAA8C;AAClH,QAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,EAAK,OAAO;GACvB,IAAI,EAAK,OAAO,EAAE,aAAa,6BAA6B,CAAC;GAC7D,WAAW,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,gCAAgC,CAAC,CAAC;GACtF,CAAC;EACF,MAAM,QAAQ,GAAa,GAAQ,GAAS,GAAW;GAEtD,IAAM,IAAS,OADC,MAAM,EAAa,GAAc,EAAI,EACxB,IAAI;IAChC,IAAI,EAAO;IACX,WAAW,EAAO;IAClB,YAAY,EAAI;IAChB,SAAS,EAAI;IACb,cAAc,EAAI;IAClB,CAAC;AAIF,UAHK,IAGE,EAAW,GAAG,EAAO,SAAS,EAAO,UAAU,eAAe,EAAO,UAAU,UAAU,EAAO,KAAK,MAAM,EAAO,QAAQ;IAChI,OAAO;IACP,IAAI,EAAO;IACX,WAAW,EAAO;IAClB,UAAU,EAAO;IACjB,CAAC,GAPM,EAAW,4BAA4B,EAAE,OAAO,IAAO,CAAC;;EASjE;;AAGF,SAAgB,EAAiB,GAAuC,GAA8C;AACrH,QAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,EAAK,OAAO;GACvB,IAAI,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,+BAA+B,CAAC,CAAC;GAC9E,OAAO,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,mBAAmB,CAAC,CAAC;GACrE,MAAM,EAAK,OAAO,EAAE,aAAa,yBAAyB,CAAC;GAC3D,WAAW,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,gCAAgC,CAAC,CAAC;GACtF,QAAQ,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,0BAA0B,CAAC,CAAC;GAC7E,UAAU,EAAK,SACd,EAAK,OAAO,EAAK,QAAQ,EAAE,GAAqB,EAC/C,aAAa,gEACb,CAAC,CACF;GACD,CAAC;EACF,MAAM,QAAQ,GAAa,GAAQ,GAAS,GAAW;GAEtD,IAAM,IAAS,OADC,MAAM,EAAa,GAAc,EAAI,EACxB,OAAO;IACnC,OAAO;KACN,IAAI,EAAO;KACX,OAAO,EAAO;KACd,MAAM,EAAO;KACb,WAAW,EAAO;KAClB,QAAQ,EAAO;KACf,UAAU,EAAO;KACjB;IACD,YAAY,EAAI;IAChB,SAAS,EAAI;IACb,cAAc,EAAI;IAClB,CAAC;AACF,UAAO,EAAW,iBAAiB,EAAO,UAAU,gBAAgB,EAAO,UAAU,IAAI;IACxF,IAAI,EAAO;IACX,WAAW,EAAO;IAClB,MAAM,EAAO;IACb,YAAY,EAAO;IACnB,CAAC;;EAEH;;AAGF,SAAgB,EAAiB,GAAuC,GAA8C;AACrH,QAAO;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY,EAAK,OAAO;GACvB,IAAI,EAAK,OAAO,EAAE,aAAa,6BAA6B,CAAC;GAC7D,WAAW,EAAK,SAAS,EAAK,OAAO,EAAE,aAAa,gCAAgC,CAAC,CAAC;GACtF,CAAC;EACF,MAAM,QAAQ,GAAa,GAAQ,GAAS,GAAW;GAEtD,IAAM,IAAa,OADH,MAAM,EAAa,GAAc,EAAI,EACpB,OAAO;IACvC,IAAI,EAAO;IACX,WAAW,EAAO;IAClB,YAAY,EAAI;IAChB,SAAS,EAAI;IACb,cAAc,EAAI;IAClB,CAAC;AACF,UAAO,EAAW,kBAAkB,EAAO,GAAa,IAAI,EAAE,eAAY,CAAC;;EAE5E"}
@@ -1,3 +1,4 @@
1
+ type ResponseMode = "auto" | "envelope";
1
2
  export declare function isCloudflareNotFoundError(error: unknown): boolean;
2
3
  export declare function requestCloudflare<T>(params: {
3
4
  url: string;
@@ -5,4 +6,6 @@ export declare function requestCloudflare<T>(params: {
5
6
  method?: string;
6
7
  headers?: Record<string, string>;
7
8
  body?: string;
9
+ responseMode?: ResponseMode;
8
10
  }): Promise<T>;
11
+ export {};
@@ -163,6 +163,7 @@ export declare const pluginUiHints: {
163
163
  };
164
164
  export declare const pluginConfigSchema: OpenClawPluginConfigSchema;
165
165
  export declare function parsePluginConfig(value: unknown): RawPluginConfig;
166
+ export declare function normalizePluginConfigInput(value: unknown): RawPluginConfig;
166
167
  export declare function getPluginConfigFromOpenClawConfig(config: OpenClawConfig): RawPluginConfig;
167
168
  export declare function resolvePluginConfig(params: {
168
169
  pluginConfig: unknown;
@@ -1,8 +1,19 @@
1
1
  import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
2
2
  import { CloudflareMemoryService } from "./service.js";
3
+ import type { ResolvedPluginConfig } from "./types.js";
4
+ type ServiceConfigOverrides = Partial<Pick<ResolvedPluginConfig, "apiToken" | "workersAiBaseUrl" | "model">>;
5
+ export declare function resolveCloudflareMemoryServiceConfig(params: {
6
+ pluginConfig?: unknown;
7
+ openClawConfig: OpenClawConfig;
8
+ env?: NodeJS.ProcessEnv;
9
+ resolvePath?: (input: string) => string;
10
+ overrides?: ServiceConfigOverrides;
11
+ }): Promise<ResolvedPluginConfig>;
3
12
  export declare function createCloudflareMemoryService(params: {
4
- pluginConfig: unknown;
13
+ pluginConfig?: unknown;
5
14
  openClawConfig: OpenClawConfig;
6
15
  env?: NodeJS.ProcessEnv;
7
16
  resolvePath?: (input: string) => string;
17
+ overrides?: ServiceConfigOverrides;
8
18
  }): Promise<CloudflareMemoryService>;
19
+ export {};
@@ -65,6 +65,7 @@ export declare class CloudflareMemoryService {
65
65
  dimensions: number;
66
66
  }>;
67
67
  private fromCompanionFallback;
68
+ private fromInlineFallback;
68
69
  private waitForSearchHit;
69
70
  private pause;
70
71
  }
@@ -1,5 +1,10 @@
1
1
  import type { AnyAgentTool, OpenClawPluginToolContext } from "openclaw/plugin-sdk/plugin-entry";
2
- export declare function createSearchTool(pluginConfig: unknown, ctx: OpenClawPluginToolContext): AnyAgentTool;
3
- export declare function createGetTool(pluginConfig: unknown, ctx: OpenClawPluginToolContext): AnyAgentTool;
4
- export declare function createUpsertTool(pluginConfig: unknown, ctx: OpenClawPluginToolContext): AnyAgentTool;
5
- export declare function createDeleteTool(pluginConfig: unknown, ctx: OpenClawPluginToolContext): AnyAgentTool;
2
+ type ToolRegistrationContext = {
3
+ pluginConfig: unknown;
4
+ resolvePath?: (input: string) => string;
5
+ };
6
+ export declare function createSearchTool(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): AnyAgentTool;
7
+ export declare function createGetTool(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): AnyAgentTool;
8
+ export declare function createUpsertTool(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): AnyAgentTool;
9
+ export declare function createDeleteTool(registration: ToolRegistrationContext, ctx: OpenClawPluginToolContext): AnyAgentTool;
10
+ export {};
@@ -50,7 +50,8 @@ var t = class {
50
50
  topK: t.topK ?? this.config.topK,
51
51
  filter: t.filter,
52
52
  namespace: t.namespace,
53
- returnValues: t.returnValues ?? !1
53
+ returnValues: t.returnValues ?? !1,
54
+ returnMetadata: "all"
54
55
  })
55
56
  })).matches ?? [];
56
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vectorize-client.js","names":[],"sources":["../src/vectorize-client.ts"],"sourcesContent":["import { requestCloudflare } from \"./cloudflare-api.js\";\nimport type { MetadataFilter, ResolvedPluginConfig, VectorizeIndexDescription, VectorizeQueryMatch, VectorizeVector } from \"./types.js\";\n\ntype MutationResponse = {\n\tmutationId?: string;\n};\n\ntype QueryResponse = {\n\tcount?: number;\n\tmatches?: VectorizeQueryMatch[];\n};\n\nexport class VectorizeClient {\n\tconstructor(private readonly config: ResolvedPluginConfig) {}\n\n\tasync describeIndex(): Promise<VectorizeIndexDescription> {\n\t\treturn requestCloudflare<VectorizeIndexDescription>({\n\t\t\turl: this.config.vectorizeBaseUrl,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tmethod: \"GET\",\n\t\t});\n\t}\n\n\tasync createIndex(dimensions: number, metric = this.config.createIndex.metric): Promise<VectorizeIndexDescription> {\n\t\treturn requestCloudflare<VectorizeIndexDescription>({\n\t\t\turl: `${this.config.apiBaseUrl}/accounts/${this.config.accountId}/vectorize/v2/indexes`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tname: this.config.indexName,\n\t\t\t\tdescription: this.config.createIndex.description,\n\t\t\t\tconfig: {\n\t\t\t\t\tdimensions,\n\t\t\t\t\tmetric,\n\t\t\t\t},\n\t\t\t}),\n\t\t});\n\t}\n\n\tasync deleteIndex(): Promise<void> {\n\t\tawait requestCloudflare<unknown>({\n\t\t\turl: this.config.vectorizeBaseUrl,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tmethod: \"DELETE\",\n\t\t});\n\t}\n\n\tasync upsert(vectors: VectorizeVector[]): Promise<string | undefined> {\n\t\tconst body = vectors.map((vector) => JSON.stringify(vector)).join(\"\\n\");\n\t\tconst result = await requestCloudflare<MutationResponse>({\n\t\t\turl: `${this.config.vectorizeBaseUrl}/upsert`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-ndjson\",\n\t\t\t},\n\t\t\tbody,\n\t\t});\n\t\treturn result.mutationId;\n\t}\n\n\tasync query(params: {\n\t\tvector: number[];\n\t\tnamespace?: string;\n\t\ttopK?: number;\n\t\tfilter?: MetadataFilter;\n\t\treturnValues?: boolean;\n\t}): Promise<VectorizeQueryMatch[]> {\n\t\tconst result = await requestCloudflare<QueryResponse>({\n\t\t\turl: `${this.config.vectorizeBaseUrl}/query`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tvector: params.vector,\n\t\t\t\ttopK: params.topK ?? this.config.topK,\n\t\t\t\tfilter: params.filter,\n\t\t\t\tnamespace: params.namespace,\n\t\t\t\treturnValues: params.returnValues ?? false,\n\t\t\t}),\n\t\t});\n\t\treturn result.matches ?? [];\n\t}\n\n\tasync getByIds(ids: string[]): Promise<VectorizeQueryMatch[]> {\n\t\tif (ids.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\treturn requestCloudflare<VectorizeQueryMatch[]>({\n\t\t\turl: `${this.config.vectorizeBaseUrl}/get_by_ids`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({ ids }),\n\t\t});\n\t}\n\n\tasync deleteByIds(ids: string[]): Promise<string | undefined> {\n\t\tif (ids.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst result = await requestCloudflare<MutationResponse>({\n\t\t\turl: `${this.config.vectorizeBaseUrl}/delete_by_ids`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({ ids }),\n\t\t});\n\t\treturn result.mutationId;\n\t}\n}\n"],"mappings":";;AAYA,IAAa,IAAb,MAA6B;CAC5B,YAAY,GAA+C;AAA9B,OAAA,SAAA;;CAE7B,MAAM,gBAAoD;AACzD,SAAO,EAA6C;GACnD,KAAK,KAAK,OAAO;GACjB,UAAU,KAAK,OAAO;GACtB,QAAQ;GACR,CAAC;;CAGH,MAAM,YAAY,GAAoB,IAAS,KAAK,OAAO,YAAY,QAA4C;AAClH,SAAO,EAA6C;GACnD,KAAK,GAAG,KAAK,OAAO,WAAW,YAAY,KAAK,OAAO,UAAU;GACjE,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU;IACpB,MAAM,KAAK,OAAO;IAClB,aAAa,KAAK,OAAO,YAAY;IACrC,QAAQ;KACP;KACA;KACA;IACD,CAAC;GACF,CAAC;;CAGH,MAAM,cAA6B;AAClC,QAAM,EAA2B;GAChC,KAAK,KAAK,OAAO;GACjB,UAAU,KAAK,OAAO;GACtB,QAAQ;GACR,CAAC;;CAGH,MAAM,OAAO,GAAyD;EACrE,IAAM,IAAO,EAAQ,KAAK,MAAW,KAAK,UAAU,EAAO,CAAC,CAAC,KAAK,KAAK;AASvE,UARe,MAAM,EAAoC;GACxD,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,SAAS,EACR,gBAAgB,wBAChB;GACD;GACA,CAAC,EACY;;CAGf,MAAM,MAAM,GAMuB;AAYlC,UAXe,MAAM,EAAiC;GACrD,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU;IACpB,QAAQ,EAAO;IACf,MAAM,EAAO,QAAQ,KAAK,OAAO;IACjC,QAAQ,EAAO;IACf,WAAW,EAAO;IAClB,cAAc,EAAO,gBAAgB;IACrC,CAAC;GACF,CAAC,EACY,WAAW,EAAE;;CAG5B,MAAM,SAAS,GAA+C;AAI7D,SAHI,EAAI,WAAW,IACX,EAAE,GAEH,EAAyC;GAC/C,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU,EAAE,QAAK,CAAC;GAC7B,CAAC;;CAGH,MAAM,YAAY,GAA4C;AACzD,QAAI,WAAW,EAQnB,SALe,MAAM,EAAoC;GACxD,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU,EAAE,QAAK,CAAC;GAC7B,CAAC,EACY"}
1
+ {"version":3,"file":"vectorize-client.js","names":[],"sources":["../src/vectorize-client.ts"],"sourcesContent":["import { requestCloudflare } from \"./cloudflare-api.js\";\nimport type { MetadataFilter, ResolvedPluginConfig, VectorizeIndexDescription, VectorizeQueryMatch, VectorizeVector } from \"./types.js\";\n\ntype MutationResponse = {\n\tmutationId?: string;\n};\n\ntype QueryResponse = {\n\tcount?: number;\n\tmatches?: VectorizeQueryMatch[];\n};\n\nexport class VectorizeClient {\n\tconstructor(private readonly config: ResolvedPluginConfig) {}\n\n\tasync describeIndex(): Promise<VectorizeIndexDescription> {\n\t\treturn requestCloudflare<VectorizeIndexDescription>({\n\t\t\turl: this.config.vectorizeBaseUrl,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tmethod: \"GET\",\n\t\t});\n\t}\n\n\tasync createIndex(dimensions: number, metric = this.config.createIndex.metric): Promise<VectorizeIndexDescription> {\n\t\treturn requestCloudflare<VectorizeIndexDescription>({\n\t\t\turl: `${this.config.apiBaseUrl}/accounts/${this.config.accountId}/vectorize/v2/indexes`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tname: this.config.indexName,\n\t\t\t\tdescription: this.config.createIndex.description,\n\t\t\t\tconfig: {\n\t\t\t\t\tdimensions,\n\t\t\t\t\tmetric,\n\t\t\t\t},\n\t\t\t}),\n\t\t});\n\t}\n\n\tasync deleteIndex(): Promise<void> {\n\t\tawait requestCloudflare<unknown>({\n\t\t\turl: this.config.vectorizeBaseUrl,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tmethod: \"DELETE\",\n\t\t});\n\t}\n\n\tasync upsert(vectors: VectorizeVector[]): Promise<string | undefined> {\n\t\tconst body = vectors.map((vector) => JSON.stringify(vector)).join(\"\\n\");\n\t\tconst result = await requestCloudflare<MutationResponse>({\n\t\t\turl: `${this.config.vectorizeBaseUrl}/upsert`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-ndjson\",\n\t\t\t},\n\t\t\tbody,\n\t\t});\n\t\treturn result.mutationId;\n\t}\n\n\tasync query(params: {\n\t\tvector: number[];\n\t\tnamespace?: string;\n\t\ttopK?: number;\n\t\tfilter?: MetadataFilter;\n\t\treturnValues?: boolean;\n\t}): Promise<VectorizeQueryMatch[]> {\n\t\tconst result = await requestCloudflare<QueryResponse>({\n\t\t\turl: `${this.config.vectorizeBaseUrl}/query`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tvector: params.vector,\n\t\t\t\ttopK: params.topK ?? this.config.topK,\n\t\t\t\tfilter: params.filter,\n\t\t\t\tnamespace: params.namespace,\n\t\t\t\treturnValues: params.returnValues ?? false,\n\t\t\t\treturnMetadata: \"all\",\n\t\t\t}),\n\t\t});\n\t\treturn result.matches ?? [];\n\t}\n\n\tasync getByIds(ids: string[]): Promise<VectorizeQueryMatch[]> {\n\t\tif (ids.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\treturn requestCloudflare<VectorizeQueryMatch[]>({\n\t\t\turl: `${this.config.vectorizeBaseUrl}/get_by_ids`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({ ids }),\n\t\t});\n\t}\n\n\tasync deleteByIds(ids: string[]): Promise<string | undefined> {\n\t\tif (ids.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst result = await requestCloudflare<MutationResponse>({\n\t\t\turl: `${this.config.vectorizeBaseUrl}/delete_by_ids`,\n\t\t\tapiToken: this.config.apiToken,\n\t\t\tbody: JSON.stringify({ ids }),\n\t\t});\n\t\treturn result.mutationId;\n\t}\n}\n"],"mappings":";;AAYA,IAAa,IAAb,MAA6B;CAC5B,YAAY,GAA+C;AAA9B,OAAA,SAAA;;CAE7B,MAAM,gBAAoD;AACzD,SAAO,EAA6C;GACnD,KAAK,KAAK,OAAO;GACjB,UAAU,KAAK,OAAO;GACtB,QAAQ;GACR,CAAC;;CAGH,MAAM,YAAY,GAAoB,IAAS,KAAK,OAAO,YAAY,QAA4C;AAClH,SAAO,EAA6C;GACnD,KAAK,GAAG,KAAK,OAAO,WAAW,YAAY,KAAK,OAAO,UAAU;GACjE,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU;IACpB,MAAM,KAAK,OAAO;IAClB,aAAa,KAAK,OAAO,YAAY;IACrC,QAAQ;KACP;KACA;KACA;IACD,CAAC;GACF,CAAC;;CAGH,MAAM,cAA6B;AAClC,QAAM,EAA2B;GAChC,KAAK,KAAK,OAAO;GACjB,UAAU,KAAK,OAAO;GACtB,QAAQ;GACR,CAAC;;CAGH,MAAM,OAAO,GAAyD;EACrE,IAAM,IAAO,EAAQ,KAAK,MAAW,KAAK,UAAU,EAAO,CAAC,CAAC,KAAK,KAAK;AASvE,UARe,MAAM,EAAoC;GACxD,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,SAAS,EACR,gBAAgB,wBAChB;GACD;GACA,CAAC,EACY;;CAGf,MAAM,MAAM,GAMuB;AAalC,UAZe,MAAM,EAAiC;GACrD,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU;IACpB,QAAQ,EAAO;IACf,MAAM,EAAO,QAAQ,KAAK,OAAO;IACjC,QAAQ,EAAO;IACf,WAAW,EAAO;IAClB,cAAc,EAAO,gBAAgB;IACrC,gBAAgB;IAChB,CAAC;GACF,CAAC,EACY,WAAW,EAAE;;CAG5B,MAAM,SAAS,GAA+C;AAI7D,SAHI,EAAI,WAAW,IACX,EAAE,GAEH,EAAyC;GAC/C,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU,EAAE,QAAK,CAAC;GAC7B,CAAC;;CAGH,MAAM,YAAY,GAA4C;AACzD,QAAI,WAAW,EAQnB,SALe,MAAM,EAAoC;GACxD,KAAK,GAAG,KAAK,OAAO,iBAAiB;GACrC,UAAU,KAAK,OAAO;GACtB,MAAM,KAAK,UAAU,EAAE,QAAK,CAAC;GAC7B,CAAC,EACY"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-cloudflare-vectorize-memory",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "OpenClaw memory plugin for Cloudflare Vectorize and Workers AI embeddings.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,8 +60,9 @@
60
60
  },
61
61
  "scripts": {
62
62
  "build": "vite build && tsc -p tsconfig.build.json",
63
- "test": "vitest run",
64
- "test:watch": "vitest",
63
+ "test": "vitest run --exclude tests/live-integration.test.ts",
64
+ "test:integration": "npm run build && vitest run tests/live-integration.test.ts",
65
+ "test:watch": "vitest --exclude tests/live-integration.test.ts",
65
66
  "check": "tsc -p tsconfig.json --noEmit",
66
67
  "publish:npmjs": "npm run check && npm test && npm run build && npm publish --access public"
67
68
  }