Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ interface PluginConfig {
apiKey: string | string[];
model?: string;
baseURL?: string;
/** Internal schema/validation dimension (LanceDB + local checks). */
dimensions?: number;
/** Optional provider request dimension (dimensions/output_dimension). */
requestDimensions?: number;
omitDimensions?: boolean;
taskQuery?: string;
taskPassage?: string;
Expand Down Expand Up @@ -1639,7 +1642,10 @@ const memoryLanceDBProPlugin = {
apiKey: config.embedding.apiKey,
model: config.embedding.model || "text-embedding-3-small",
baseURL: config.embedding.baseURL,
// Internal dimension for local schema/validation checks.
dimensions: config.embedding.dimensions,
// Optional request hint sent to providers that support variable dimensions.
requestDimensions: config.embedding.requestDimensions,
omitDimensions: config.embedding.omitDimensions,
taskQuery: config.embedding.taskQuery,
taskPassage: config.embedding.taskPassage,
Expand Down Expand Up @@ -3776,6 +3782,8 @@ export function parsePluginConfig(value: unknown): PluginConfig {
// Accept number, numeric string, or env-var string (e.g. "${EMBED_DIM}").
// Also accept legacy top-level `dimensions` for convenience.
dimensions: parsePositiveInt(embedding.dimensions ?? cfg.dimensions),
// Request dimension is intentionally separate from internal schema sizing.
requestDimensions: parsePositiveInt(embedding.requestDimensions),
omitDimensions:
typeof embedding.omitDimensions === "boolean"
? embedding.omitDimensions
Expand Down
5 changes: 5 additions & 0 deletions openclaw.plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
"type": "integer",
"minimum": 1
},
"requestDimensions": {
"type": "integer",
"minimum": 1,
"description": "Optional output dimension sent to embedding API requests only (for providers supporting variable dimensions)"
},
"omitDimensions": {
"type": "boolean",
"description": "When true, omit the dimensions parameter from embedding requests even if dimensions is configured"
Expand Down
7 changes: 6 additions & 1 deletion src/embedder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ export interface EmbeddingConfig {
apiKey: string | string[];
model: string;
baseURL?: string;
/** Internal vector dimension for schema/validation. This does NOT imply sending API dimensions. */
dimensions?: number;
/** Optional API request output dimension for providers that support variable dimensions. */
requestDimensions?: number;

/** Optional task type for query embeddings (e.g. "retrieval.query") */
taskQuery?: string;
Expand Down Expand Up @@ -428,7 +431,8 @@ export class Embedder {
this._taskQuery = config.taskQuery;
this._taskPassage = config.taskPassage;
this._normalized = config.normalized;
this._requestDimensions = config.dimensions;
// Request-side dimension hint is isolated from internal schema dimension.
this._requestDimensions = config.requestDimensions;
this._omitDimensions = config.omitDimensions === true;
// Enable auto-chunking by default for better handling of long documents
this._autoChunk = config.chunking !== false;
Expand Down Expand Up @@ -472,6 +476,7 @@ export class Embedder {
console.log(`[memory-lancedb-pro] Initialized ${this.clients.length} API keys for round-robin rotation`);
}

// Internal dimension remains the single source of truth for local validation.
this.dimensions = getVectorDimensions(config.model, config.dimensions);
this._cache = new EmbeddingCache(256, 30); // 256 entries, 30 min TTL
}
Expand Down
44 changes: 40 additions & 4 deletions test/plugin-manifest-regression.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ assert.equal(
"boolean",
"embedding.omitDimensions should be declared in the plugin schema",
);
assert.equal(
manifest.configSchema.properties.embedding.properties.requestDimensions?.type,
"integer",
"embedding.requestDimensions should be declared in the plugin schema",
);
assert.equal(
manifest.configSchema.properties.sessionMemory.properties.enabled.default,
false,
Expand Down Expand Up @@ -325,14 +330,44 @@ try {
});
const requestCountBeforeWithDimensions = embeddingRequests.length;
await withDimensionsTool.execute("tool-3", {
text: "dimensions should be sent by default",
text: "dimensions should not be sent by default",
scope: "global",
});
const withDimensionsRequest = embeddingRequests.at(requestCountBeforeWithDimensions);
assert.equal(
withDimensionsRequest?.dimensions,
Object.prototype.hasOwnProperty.call(withDimensionsRequest ?? {}, "dimensions"),
false,
"embedding.dimensions should be used for internal schema sizing, not forwarded by default",
);

const withRequestDimensionsApi = createMockApi({
dbPath: path.join(workDir, "db-with-request-dimensions"),
autoCapture: false,
autoRecall: false,
embedding: {
provider: "openai-compatible",
apiKey: "dummy",
model: "text-embedding-3-small",
baseURL: embeddingBaseURL,
dimensions: 4,
requestDimensions: 4,
},
});
plugin.register(withRequestDimensionsApi);
const withRequestDimensionsTool = withRequestDimensionsApi.toolFactories.memory_store({
agentId: "main",
sessionKey: "agent:main:test",
});
const requestCountBeforeRequestDimensions = embeddingRequests.length;
await withRequestDimensionsTool.execute("tool-3b", {
text: "requestDimensions should be forwarded",
scope: "global",
});
const withRequestDimensionsRequest = embeddingRequests.at(requestCountBeforeRequestDimensions);
assert.equal(
withRequestDimensionsRequest?.dimensions,
4,
"embedding.dimensions should be forwarded by default",
"embedding.requestDimensions should be forwarded to embedding requests",
);

const omitDimensionsApi = createMockApi({
Expand All @@ -345,6 +380,7 @@ try {
model: "text-embedding-3-small",
baseURL: embeddingBaseURL,
dimensions: 4,
requestDimensions: 4,
omitDimensions: true,
},
});
Expand All @@ -362,7 +398,7 @@ try {
assert.equal(
Object.prototype.hasOwnProperty.call(omitDimensionsRequest, "dimensions"),
false,
"embedding.omitDimensions=true should omit dimensions from embedding requests",
"embedding.omitDimensions=true should omit dimensions from embedding requests even when requestDimensions is set",
);
} finally {
await new Promise((resolve) => embeddingServer.close(resolve));
Expand Down
Loading