@h-rig/runtime 0.0.6-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/dist/bin/rig-agent-dispatch.js +9615 -0
- package/dist/bin/rig-agent.js +9512 -0
- package/dist/bin/rig-browser-tool.js +269 -0
- package/dist/src/agent-mode.js +48 -0
- package/dist/src/baked-secrets.js +121 -0
- package/dist/src/binary-build-worker.js +312 -0
- package/dist/src/binary-run.js +540 -0
- package/dist/src/boundaries.js +1 -0
- package/dist/src/build-time-config.js +25 -0
- package/dist/src/control-plane/agent-roles.js +27 -0
- package/dist/src/control-plane/agent-wrapper.js +9621 -0
- package/dist/src/control-plane/authority-files.js +582 -0
- package/dist/src/control-plane/browser-contract.js +135 -0
- package/dist/src/control-plane/controlled-bash.js +1111 -0
- package/dist/src/control-plane/errors.js +13 -0
- package/dist/src/control-plane/harness-main.js +10828 -0
- package/dist/src/control-plane/hook-materializer.js +75 -0
- package/dist/src/control-plane/hooks/audit-trail.js +353 -0
- package/dist/src/control-plane/hooks/completion-verification.js +7552 -0
- package/dist/src/control-plane/hooks/import-guard.js +890 -0
- package/dist/src/control-plane/hooks/inject-context.js +4189 -0
- package/dist/src/control-plane/hooks/post-edit-lint.js +43 -0
- package/dist/src/control-plane/hooks/safety-guard.js +910 -0
- package/dist/src/control-plane/hooks/scope-guard.js +907 -0
- package/dist/src/control-plane/hooks/shared.js +44 -0
- package/dist/src/control-plane/hooks/submodule-branch.js +7797 -0
- package/dist/src/control-plane/hooks/task-runtime-start.js +7799 -0
- package/dist/src/control-plane/hooks/test-integrity-guard.js +891 -0
- package/dist/src/control-plane/materialize-task-config.js +453 -0
- package/dist/src/control-plane/memory-sync/cli.js +2019 -0
- package/dist/src/control-plane/memory-sync/db.js +753 -0
- package/dist/src/control-plane/memory-sync/embed.js +281 -0
- package/dist/src/control-plane/memory-sync/index.js +2049 -0
- package/dist/src/control-plane/memory-sync/query.js +294 -0
- package/dist/src/control-plane/memory-sync/read.js +784 -0
- package/dist/src/control-plane/memory-sync/types.js +6 -0
- package/dist/src/control-plane/memory-sync/write.js +1547 -0
- package/dist/src/control-plane/native/git-native.js +490 -0
- package/dist/src/control-plane/native/git-ops.js +2860 -0
- package/dist/src/control-plane/native/harness-cli.js +9721 -0
- package/dist/src/control-plane/native/pr-automation.js +373 -0
- package/dist/src/control-plane/native/profile-ops.js +481 -0
- package/dist/src/control-plane/native/repo-ops.js +2342 -0
- package/dist/src/control-plane/native/root-resolver.js +66 -0
- package/dist/src/control-plane/native/run-ops.js +3281 -0
- package/dist/src/control-plane/native/runtime-native-sidecar.js +299 -0
- package/dist/src/control-plane/native/runtime-native.js +392 -0
- package/dist/src/control-plane/native/scope-rules.js +17 -0
- package/dist/src/control-plane/native/task-ops.js +6320 -0
- package/dist/src/control-plane/native/task-state.js +1512 -0
- package/dist/src/control-plane/native/utils.js +535 -0
- package/dist/src/control-plane/native/validator-binaries.js +889 -0
- package/dist/src/control-plane/native/validator.js +2197 -0
- package/dist/src/control-plane/native/verifier.js +3249 -0
- package/dist/src/control-plane/native/workspace-ops.js +1635 -0
- package/dist/src/control-plane/plugin-host-context.js +334 -0
- package/dist/src/control-plane/project-main-pre-run-sync.js +630 -0
- package/dist/src/control-plane/provider/claude-stream-records.js +158 -0
- package/dist/src/control-plane/provider/codex-app-server.js +885 -0
- package/dist/src/control-plane/provider/codex-exec-records.js +203 -0
- package/dist/src/control-plane/provider/rig-task-run-skill.js +39 -0
- package/dist/src/control-plane/provider/runtime-instructions.js +96 -0
- package/dist/src/control-plane/remote.js +854 -0
- package/dist/src/control-plane/repos/index.js +473 -0
- package/dist/src/control-plane/repos/layout.js +124 -0
- package/dist/src/control-plane/repos/mirror/bootstrap.js +268 -0
- package/dist/src/control-plane/repos/mirror/refresh.js +398 -0
- package/dist/src/control-plane/repos/mirror/state.js +167 -0
- package/dist/src/control-plane/repos/registry.js +77 -0
- package/dist/src/control-plane/repos/types.js +1 -0
- package/dist/src/control-plane/runtime/agent-mode.js +48 -0
- package/dist/src/control-plane/runtime/baked-secrets.js +120 -0
- package/dist/src/control-plane/runtime/claude-tool-router-binary.js +343 -0
- package/dist/src/control-plane/runtime/claude-tool-router.js +520 -0
- package/dist/src/control-plane/runtime/context.js +216 -0
- package/dist/src/control-plane/runtime/events.js +218 -0
- package/dist/src/control-plane/runtime/guard-types.js +6 -0
- package/dist/src/control-plane/runtime/guard.js +880 -0
- package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +1194 -0
- package/dist/src/control-plane/runtime/image/index.js +2255 -0
- package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +1191 -0
- package/dist/src/control-plane/runtime/image.js +2255 -0
- package/dist/src/control-plane/runtime/index.js +8511 -0
- package/dist/src/control-plane/runtime/isolation/discovery.js +599 -0
- package/dist/src/control-plane/runtime/isolation/home.js +1217 -0
- package/dist/src/control-plane/runtime/isolation/index.js +8193 -0
- package/dist/src/control-plane/runtime/isolation/runner.js +2651 -0
- package/dist/src/control-plane/runtime/isolation/shared.js +501 -0
- package/dist/src/control-plane/runtime/isolation/toolchain.js +1892 -0
- package/dist/src/control-plane/runtime/isolation/types.js +1 -0
- package/dist/src/control-plane/runtime/isolation/worktree.js +509 -0
- package/dist/src/control-plane/runtime/isolation.js +8193 -0
- package/dist/src/control-plane/runtime/overlay.js +67 -0
- package/dist/src/control-plane/runtime/plugin-mode.js +41 -0
- package/dist/src/control-plane/runtime/plugins.js +1131 -0
- package/dist/src/control-plane/runtime/provisioning-env.js +220 -0
- package/dist/src/control-plane/runtime/queue.js +8358 -0
- package/dist/src/control-plane/runtime/rig-shell.js +205 -0
- package/dist/src/control-plane/runtime/rig-tools.js +182 -0
- package/dist/src/control-plane/runtime/runner-context.js +1 -0
- package/dist/src/control-plane/runtime/runtime-paths.js +184 -0
- package/dist/src/control-plane/runtime/sandbox/backend-bwrap.js +311 -0
- package/dist/src/control-plane/runtime/sandbox/backend-none.js +21 -0
- package/dist/src/control-plane/runtime/sandbox/backend-seatbelt.js +268 -0
- package/dist/src/control-plane/runtime/sandbox/backend.js +1718 -0
- package/dist/src/control-plane/runtime/sandbox/orchestrator.js +1745 -0
- package/dist/src/control-plane/runtime/sandbox/utils.js +137 -0
- package/dist/src/control-plane/runtime/sandbox-backend-bwrap.js +311 -0
- package/dist/src/control-plane/runtime/sandbox-backend-none.js +21 -0
- package/dist/src/control-plane/runtime/sandbox-backend-seatbelt.js +268 -0
- package/dist/src/control-plane/runtime/sandbox-backend.js +1718 -0
- package/dist/src/control-plane/runtime/sandbox-orchestrator.js +1745 -0
- package/dist/src/control-plane/runtime/sandbox-utils.js +137 -0
- package/dist/src/control-plane/runtime/snapshot/index.js +454 -0
- package/dist/src/control-plane/runtime/snapshot/sidecar.js +502 -0
- package/dist/src/control-plane/runtime/snapshot/task-run.js +1578 -0
- package/dist/src/control-plane/runtime/snapshot-sidecar.js +498 -0
- package/dist/src/control-plane/runtime/snapshot.js +454 -0
- package/dist/src/control-plane/runtime/task-run-snapshot.js +1578 -0
- package/dist/src/control-plane/runtime/tool-gateway.js +422 -0
- package/dist/src/control-plane/runtime/tooling/browser-tools.js +32 -0
- package/dist/src/control-plane/runtime/tooling/claude-router-binary.js +343 -0
- package/dist/src/control-plane/runtime/tooling/claude-router.js +524 -0
- package/dist/src/control-plane/runtime/tooling/file-tools.js +182 -0
- package/dist/src/control-plane/runtime/tooling/gateway.js +422 -0
- package/dist/src/control-plane/runtime/tooling/index.js +1290 -0
- package/dist/src/control-plane/runtime/tooling/shell.js +205 -0
- package/dist/src/control-plane/runtime/types.js +1 -0
- package/dist/src/control-plane/setup-version.js +14 -0
- package/dist/src/control-plane/state-sync/index.js +1509 -0
- package/dist/src/control-plane/state-sync/read.js +856 -0
- package/dist/src/control-plane/state-sync/reconcile.js +260 -0
- package/dist/src/control-plane/state-sync/repo.js +302 -0
- package/dist/src/control-plane/state-sync/types.js +111 -0
- package/dist/src/control-plane/state-sync/write.js +1469 -0
- package/dist/src/control-plane/task-fields.js +38 -0
- package/dist/src/control-plane/task-source-bootstrap.js +46 -0
- package/dist/src/control-plane/task-source.js +30 -0
- package/dist/src/control-plane/tasks/legacy-task-config-source.js +130 -0
- package/dist/src/control-plane/tasks/plugin-task-source.js +103 -0
- package/dist/src/control-plane/tasks/source-aware-task-config-source.js +611 -0
- package/dist/src/control-plane/tasks/source-lifecycle.js +1093 -0
- package/dist/src/control-plane/tasks/task-record-reader.js +9 -0
- package/dist/src/control-plane/validators/boundary/public-apis.js +107 -0
- package/dist/src/control-plane/validators/integration/_shared.js +51 -0
- package/dist/src/control-plane/validators/integration/adm-audit-http.js +85 -0
- package/dist/src/control-plane/validators/integration/adm-auth-http.js +78 -0
- package/dist/src/control-plane/validators/integration/adm-issuer-http.js +80 -0
- package/dist/src/control-plane/validators/integration/adm-migration.js +78 -0
- package/dist/src/control-plane/validators/integration/adm-scaffold.js +78 -0
- package/dist/src/control-plane/validators/runtime-registration.js +64 -0
- package/dist/src/control-plane/validators/shared.js +683 -0
- package/dist/src/events.js +218 -0
- package/dist/src/execution.js +35 -0
- package/dist/src/index.js +1633 -0
- package/dist/src/layout.js +145 -0
- package/dist/src/local-server.js +202 -0
- package/dist/src/plugins.js +329 -0
- package/dist/src/remote-http.js +83 -0
- package/dist/src/runtime-context.js +216 -0
- package/dist/src/types.js +1 -0
- package/native/darwin-arm64/bin/rig-git +0 -0
- package/native/darwin-arm64/bin/rig-shell +0 -0
- package/native/darwin-arm64/bin/rig-tools +0 -0
- package/native/darwin-arm64/lib/runtime-native-darwin-arm64.dylib +0 -0
- package/native/darwin-arm64/lib/runtime-native.dylib +0 -0
- package/native/darwin-arm64/manifest.json +1 -0
- package/native/linux-x64/bin/rig-git +0 -0
- package/native/linux-x64/bin/rig-shell +0 -0
- package/native/linux-x64/bin/rig-tools +0 -0
- package/native/linux-x64/lib/runtime-native-linux-x64.so +0 -0
- package/native/linux-x64/lib/runtime-native.so +0 -0
- package/native/linux-x64/manifest.json +1 -0
- package/package.json +74 -0
- package/skills/rig-task-run.md +71 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/runtime/src/control-plane/memory-sync/embed.ts
|
|
3
|
+
import { createHash } from "crypto";
|
|
4
|
+
|
|
5
|
+
// packages/runtime/src/control-plane/memory-sync/db.ts
|
|
6
|
+
function parseJsonRecord(value) {
|
|
7
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return JSON.parse(value);
|
|
11
|
+
}
|
|
12
|
+
function parseEmbedding(value) {
|
|
13
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return JSON.parse(value);
|
|
17
|
+
}
|
|
18
|
+
function rowString(row, key) {
|
|
19
|
+
const value = row[key];
|
|
20
|
+
return value == null ? null : String(value);
|
|
21
|
+
}
|
|
22
|
+
function toMemoryItemRow(row) {
|
|
23
|
+
return {
|
|
24
|
+
canonicalKey: String(row.canonical_key),
|
|
25
|
+
summary: String(row.summary),
|
|
26
|
+
kind: rowString(row, "kind"),
|
|
27
|
+
category: rowString(row, "category"),
|
|
28
|
+
status: String(row.status),
|
|
29
|
+
confidence: Number(row.confidence),
|
|
30
|
+
sourceRunId: rowString(row, "source_run_id"),
|
|
31
|
+
sourceTaskId: rowString(row, "source_task_id"),
|
|
32
|
+
branch: rowString(row, "branch"),
|
|
33
|
+
details: parseJsonRecord(row.details_json),
|
|
34
|
+
createdAt: String(row.created_at),
|
|
35
|
+
updatedAt: String(row.updated_at),
|
|
36
|
+
lastEventId: String(row.last_event_id),
|
|
37
|
+
supersededBy: rowString(row, "superseded_by"),
|
|
38
|
+
embedding: parseEmbedding(row.embedding)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function listActiveMemoryItems(db) {
|
|
42
|
+
const result = await db.client.execute(`
|
|
43
|
+
SELECT
|
|
44
|
+
canonical_key,
|
|
45
|
+
summary,
|
|
46
|
+
kind,
|
|
47
|
+
category,
|
|
48
|
+
status,
|
|
49
|
+
confidence,
|
|
50
|
+
source_run_id,
|
|
51
|
+
source_task_id,
|
|
52
|
+
branch,
|
|
53
|
+
details_json,
|
|
54
|
+
created_at,
|
|
55
|
+
updated_at,
|
|
56
|
+
last_event_id,
|
|
57
|
+
superseded_by,
|
|
58
|
+
embedding
|
|
59
|
+
FROM memory_items
|
|
60
|
+
WHERE status = 'active'
|
|
61
|
+
ORDER BY canonical_key
|
|
62
|
+
`);
|
|
63
|
+
return result.rows.map((row) => toMemoryItemRow(row));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// packages/runtime/src/control-plane/memory-sync/embed.ts
|
|
67
|
+
var DEFAULT_EMBEDDING_API_BASE_URL = "https://api.openai.com/v1";
|
|
68
|
+
var DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small";
|
|
69
|
+
var DETERMINISTIC_EMBEDDER_MODE = "deterministic";
|
|
70
|
+
var DETERMINISTIC_VECTOR_DIMS = 32;
|
|
71
|
+
function tokenizeForDeterministicEmbedding(text) {
|
|
72
|
+
const tokens = text.toLowerCase().match(/[a-z0-9_./:-]+/g) ?? [];
|
|
73
|
+
return tokens.length > 0 ? tokens : [text.toLowerCase()];
|
|
74
|
+
}
|
|
75
|
+
function deterministicTokenVector(token) {
|
|
76
|
+
const hash = createHash("sha256").update(token).digest();
|
|
77
|
+
const vector = new Array(DETERMINISTIC_VECTOR_DIMS).fill(0);
|
|
78
|
+
for (let index = 0;index < 8; index += 1) {
|
|
79
|
+
const slot = (hash[index] ?? 0) % DETERMINISTIC_VECTOR_DIMS;
|
|
80
|
+
const sign = ((hash[index + 8] ?? 0) & 1) === 0 ? 1 : -1;
|
|
81
|
+
const magnitude = ((hash[index + 16] ?? 0) + 1) / 256;
|
|
82
|
+
vector[slot] = (vector[slot] ?? 0) + sign * magnitude;
|
|
83
|
+
}
|
|
84
|
+
return vector;
|
|
85
|
+
}
|
|
86
|
+
function normalizeVector(vector) {
|
|
87
|
+
const norm = Math.sqrt(vector.reduce((sum, value) => sum + value * value, 0));
|
|
88
|
+
if (norm === 0) {
|
|
89
|
+
return vector.map(() => 0);
|
|
90
|
+
}
|
|
91
|
+
return vector.map((value) => Number((value / norm).toFixed(6)));
|
|
92
|
+
}
|
|
93
|
+
function createDeterministicMemoryEmbedder() {
|
|
94
|
+
return {
|
|
95
|
+
async embed(texts) {
|
|
96
|
+
return texts.map((text) => {
|
|
97
|
+
const vector = new Array(DETERMINISTIC_VECTOR_DIMS).fill(0);
|
|
98
|
+
for (const token of tokenizeForDeterministicEmbedding(text)) {
|
|
99
|
+
const tokenVector = deterministicTokenVector(token);
|
|
100
|
+
for (let index = 0;index < tokenVector.length; index += 1) {
|
|
101
|
+
vector[index] = (vector[index] ?? 0) + (tokenVector[index] ?? 0);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return normalizeVector(vector);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function embeddingResponseMessage(payload, status) {
|
|
110
|
+
if (typeof payload === "object" && payload !== null) {
|
|
111
|
+
const maybeMessage = payload.error?.message;
|
|
112
|
+
if (maybeMessage) {
|
|
113
|
+
return maybeMessage;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return `memory embedding request failed with status ${status}`;
|
|
117
|
+
}
|
|
118
|
+
function createOpenAiMemoryEmbedder(options) {
|
|
119
|
+
const apiKey = options.apiKey.trim();
|
|
120
|
+
const model = options.model?.trim() || DEFAULT_EMBEDDING_MODEL;
|
|
121
|
+
const apiBaseUrl = (options.apiBaseUrl?.trim() || DEFAULT_EMBEDDING_API_BASE_URL).replace(/\/+$/, "");
|
|
122
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
123
|
+
if (!apiKey) {
|
|
124
|
+
throw new Error("memory embedding api key must be non-empty");
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
async embed(texts) {
|
|
128
|
+
if (texts.length === 0) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
const response = await fetchImpl(`${apiBaseUrl}/embeddings`, {
|
|
132
|
+
method: "POST",
|
|
133
|
+
headers: {
|
|
134
|
+
authorization: `Bearer ${apiKey}`,
|
|
135
|
+
"content-type": "application/json"
|
|
136
|
+
},
|
|
137
|
+
body: JSON.stringify({
|
|
138
|
+
input: texts,
|
|
139
|
+
model
|
|
140
|
+
})
|
|
141
|
+
});
|
|
142
|
+
const payload = await response.json();
|
|
143
|
+
if (!response.ok) {
|
|
144
|
+
throw new Error(embeddingResponseMessage(payload, response.status));
|
|
145
|
+
}
|
|
146
|
+
if (!Array.isArray(payload.data) || payload.data.length !== texts.length) {
|
|
147
|
+
throw new Error(`memory embedding provider returned ${payload.data?.length ?? 0} embeddings for ${texts.length} inputs`);
|
|
148
|
+
}
|
|
149
|
+
const byIndex = new Map;
|
|
150
|
+
for (const row of payload.data) {
|
|
151
|
+
if (typeof row.index !== "number" || !Array.isArray(row.embedding)) {
|
|
152
|
+
throw new Error("memory embedding provider returned an invalid response payload");
|
|
153
|
+
}
|
|
154
|
+
byIndex.set(row.index, row.embedding);
|
|
155
|
+
}
|
|
156
|
+
return texts.map((_text, index) => {
|
|
157
|
+
const embedding = byIndex.get(index);
|
|
158
|
+
if (!embedding) {
|
|
159
|
+
throw new Error(`memory embedding provider omitted embedding ${index}`);
|
|
160
|
+
}
|
|
161
|
+
return embedding;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function createConfiguredMemoryEmbedder(options = {}) {
|
|
167
|
+
const env = options.env ?? process.env;
|
|
168
|
+
const mode = env.RIG_MEMORY_EMBEDDER?.trim();
|
|
169
|
+
if (mode === DETERMINISTIC_EMBEDDER_MODE) {
|
|
170
|
+
return createDeterministicMemoryEmbedder();
|
|
171
|
+
}
|
|
172
|
+
const apiKey = env.OPENAI_API_KEY?.trim();
|
|
173
|
+
if (!apiKey) {
|
|
174
|
+
throw new Error("memory embeddings require OPENAI_API_KEY or RIG_MEMORY_EMBEDDER=deterministic");
|
|
175
|
+
}
|
|
176
|
+
return createOpenAiMemoryEmbedder({
|
|
177
|
+
apiKey,
|
|
178
|
+
model: env.RIG_MEMORY_EMBEDDING_MODEL?.trim() || DEFAULT_EMBEDDING_MODEL,
|
|
179
|
+
apiBaseUrl: options.apiBaseUrl ?? env.RIG_MEMORY_EMBEDDING_API_BASE_URL?.trim() ?? DEFAULT_EMBEDDING_API_BASE_URL,
|
|
180
|
+
fetchImpl: options.fetchImpl
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// packages/runtime/src/control-plane/runtime/context.ts
|
|
185
|
+
var DEFAULT_RUNTIME_MEMORY_RETRIEVAL = {
|
|
186
|
+
topK: 5,
|
|
187
|
+
lexicalWeight: 0.35,
|
|
188
|
+
vectorWeight: 0.45,
|
|
189
|
+
recencyWeight: 0.1,
|
|
190
|
+
confidenceWeight: 0.1
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// packages/runtime/src/control-plane/memory-sync/query.ts
|
|
194
|
+
var DEFAULT_RESULT_LIMIT = DEFAULT_RUNTIME_MEMORY_RETRIEVAL.topK;
|
|
195
|
+
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
196
|
+
var MIN_VECTOR_MATCH_SCORE = 0.2;
|
|
197
|
+
function tokenize(text) {
|
|
198
|
+
return (text.toLowerCase().match(/[a-z0-9_./:-]+/g) ?? []).flatMap((token) => {
|
|
199
|
+
const split = token.split(/[./:_-]+/).filter(Boolean);
|
|
200
|
+
return split.length > 0 ? [token, ...split] : [token];
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function lexicalScore(query, item) {
|
|
204
|
+
const queryTokens = [...new Set(tokenize(query))];
|
|
205
|
+
if (queryTokens.length === 0) {
|
|
206
|
+
return 0;
|
|
207
|
+
}
|
|
208
|
+
const haystackTokens = new Set(tokenize(item.summary));
|
|
209
|
+
let matched = 0;
|
|
210
|
+
for (const token of queryTokens) {
|
|
211
|
+
if (haystackTokens.has(token)) {
|
|
212
|
+
matched += 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return matched / queryTokens.length;
|
|
216
|
+
}
|
|
217
|
+
function cosineSimilarity(left, right) {
|
|
218
|
+
if (left.length === 0 || left.length !== right.length) {
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
let dot = 0;
|
|
222
|
+
let leftNorm = 0;
|
|
223
|
+
let rightNorm = 0;
|
|
224
|
+
for (let index = 0;index < left.length; index += 1) {
|
|
225
|
+
const l = left[index] ?? 0;
|
|
226
|
+
const r = right[index] ?? 0;
|
|
227
|
+
dot += l * r;
|
|
228
|
+
leftNorm += l * l;
|
|
229
|
+
rightNorm += r * r;
|
|
230
|
+
}
|
|
231
|
+
if (leftNorm === 0 || rightNorm === 0) {
|
|
232
|
+
return 0;
|
|
233
|
+
}
|
|
234
|
+
return dot / Math.sqrt(leftNorm * rightNorm);
|
|
235
|
+
}
|
|
236
|
+
function recencyScore(item, now) {
|
|
237
|
+
const updatedAt = Date.parse(item.updatedAt);
|
|
238
|
+
if (Number.isNaN(updatedAt)) {
|
|
239
|
+
return 0;
|
|
240
|
+
}
|
|
241
|
+
const ageMs = Math.max(0, now.getTime() - updatedAt);
|
|
242
|
+
return 1 / (1 + ageMs / DAY_MS);
|
|
243
|
+
}
|
|
244
|
+
async function maybeEmbedQuery(items, query, embedder) {
|
|
245
|
+
if (!items.some((item) => Array.isArray(item.embedding) && item.embedding.length > 0)) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
const resolvedEmbedder = embedder ?? createConfiguredMemoryEmbedder();
|
|
250
|
+
const [queryEmbedding] = await resolvedEmbedder.embed([query]);
|
|
251
|
+
return queryEmbedding ?? null;
|
|
252
|
+
} catch {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async function queryRelevantMemory(db, input) {
|
|
257
|
+
const retrieval = input.retrieval ?? DEFAULT_RUNTIME_MEMORY_RETRIEVAL;
|
|
258
|
+
const now = input.now instanceof Date ? input.now : new Date(input.now ?? Date.now());
|
|
259
|
+
const items = await listActiveMemoryItems(db);
|
|
260
|
+
if (items.length === 0) {
|
|
261
|
+
return [];
|
|
262
|
+
}
|
|
263
|
+
const queryEmbedding = await maybeEmbedQuery(items, input.query, input.embedder);
|
|
264
|
+
const scored = items.map((item) => {
|
|
265
|
+
const lexical = lexicalScore(input.query, item);
|
|
266
|
+
const vector = queryEmbedding && item.embedding ? cosineSimilarity(queryEmbedding, item.embedding) : 0;
|
|
267
|
+
const recency = recencyScore(item, now);
|
|
268
|
+
const score = retrieval.lexicalWeight * lexical + retrieval.vectorWeight * vector + retrieval.recencyWeight * recency + retrieval.confidenceWeight * item.confidence;
|
|
269
|
+
return {
|
|
270
|
+
canonicalKey: item.canonicalKey,
|
|
271
|
+
summary: item.summary,
|
|
272
|
+
kind: item.kind,
|
|
273
|
+
category: item.category,
|
|
274
|
+
confidence: item.confidence,
|
|
275
|
+
updatedAt: item.updatedAt,
|
|
276
|
+
score,
|
|
277
|
+
lexicalScore: lexical,
|
|
278
|
+
vectorScore: vector,
|
|
279
|
+
recencyScore: recency
|
|
280
|
+
};
|
|
281
|
+
}).filter((item) => item.lexicalScore > 0 || item.vectorScore >= MIN_VECTOR_MATCH_SCORE).sort((left, right) => right.score - left.score || Date.parse(right.updatedAt) - Date.parse(left.updatedAt) || right.confidence - left.confidence || left.canonicalKey.localeCompare(right.canonicalKey));
|
|
282
|
+
return scored.slice(0, input.limit ?? retrieval.topK ?? DEFAULT_RESULT_LIMIT);
|
|
283
|
+
}
|
|
284
|
+
function formatMemoryQueryResults(results) {
|
|
285
|
+
if (results.length === 0) {
|
|
286
|
+
return "No shared memories matched.";
|
|
287
|
+
}
|
|
288
|
+
return results.map((result, index) => `${index + 1}. [${result.canonicalKey}] ${result.summary} (confidence ${result.confidence.toFixed(2)})`).join(`
|
|
289
|
+
`);
|
|
290
|
+
}
|
|
291
|
+
export {
|
|
292
|
+
queryRelevantMemory,
|
|
293
|
+
formatMemoryQueryResults
|
|
294
|
+
};
|