memorix 1.4.4 → 1.4.6
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/CHANGELOG.md +69 -0
- package/CLAUDE.md +7 -3
- package/README.md +14 -4
- package/README.zh-CN.md +9 -2
- package/dist/cli/index.js +1802 -1138
- package/dist/index.js +1298 -991
- package/dist/{maintenance-jobs-B1-W0ssz.d.ts → maintenance-jobs-DVRF-46r.d.ts} +1 -1
- package/dist/maintenance-runner.d.ts +1 -1
- package/dist/maintenance-runner.js +1755 -829
- package/dist/media-audio-runner.js +1760 -835
- package/dist/media-video-runner.js +1755 -830
- package/dist/memcode-runtime/CHANGELOG.md +69 -0
- package/dist/sdk.js +1290 -990
- package/dist/types.d.ts +7 -1
- package/dist/vector-backfill-runner.d.ts +1 -1
- package/dist/vector-backfill-runner.js +1751 -826
- package/docs/1.4.5-AGENT-AUTO-MEMORY-RESEARCH.md +95 -0
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +3 -2
- package/docs/API_REFERENCE.md +23 -4
- package/docs/CONFIGURATION.md +17 -3
- package/docs/INTEGRATIONS.md +9 -2
- package/docs/KNOWN_ISSUES_AND_ROADMAP.md +1 -0
- package/docs/MEMCODE.md +1 -1
- package/docs/SETUP.md +14 -4
- package/llms-full.txt +5 -4
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/plugins/antigravity/memorix/mcp_config.json +3 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/memorix/.mcp.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.mcp.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.mcp.json +1 -1
- package/plugins/copilot/memorix/.mcp.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +4 -2
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/openclaw/memorix/.mcp.json +3 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/commands/agent-integrations.ts +7 -1
- package/src/cli/commands/dashboard.ts +14 -3
- package/src/cli/commands/hooks-install.ts +2 -0
- package/src/cli/commands/hooks-preview.ts +5 -0
- package/src/cli/commands/ingest-commit.ts +47 -3
- package/src/cli/commands/integrate.ts +2 -0
- package/src/cli/commands/memory.ts +17 -4
- package/src/cli/commands/purge.ts +120 -0
- package/src/cli/commands/serve-http.ts +39 -5
- package/src/cli/commands/setup.ts +60 -3
- package/src/cli/commands/uninstall.ts +20 -0
- package/src/cli/index.ts +3 -804
- package/src/codegraph/auto-context.ts +82 -1
- package/src/config/yaml-loader.ts +3 -8
- package/src/config.ts +0 -5
- package/src/evaluation/session-replay.ts +98 -0
- package/src/git/extractor.ts +5 -3
- package/src/hooks/installers/index.ts +58 -2
- package/src/hooks/types.ts +2 -0
- package/src/integrations/registry.ts +9 -0
- package/src/knowledge/workset.ts +58 -0
- package/src/memory/long-term.ts +97 -2
- package/src/runtime/control-plane-maintenance.ts +1 -0
- package/src/runtime/isolated-maintenance.ts +1 -0
- package/src/runtime/lifecycle.ts +19 -0
- package/src/runtime/maintenance-jobs.ts +1 -0
- package/src/runtime/project-maintenance.ts +8 -0
- package/src/search/surfaced-registry.ts +62 -0
- package/src/server.ts +74 -14
- package/src/store/orama-store.ts +17 -1
- package/src/types.ts +7 -1
- package/src/workspace/mcp-adapters/dsh.ts +147 -0
- package/src/cli/commands/audit-list.ts +0 -89
- package/src/cli/commands/purge-all-memory.ts +0 -85
- package/src/cli/commands/purge-project-memory.ts +0 -83
- package/src/cli/commands/uninstall-project-artifacts.ts +0 -86
- package/src/cli/tui/Sidebar.tsx +0 -179
- package/src/cli/tui/interactive-commands.ts +0 -261
- package/src/cli/tui/markdown-render.tsx +0 -371
- package/src/cli/tui/use-mouse.ts +0 -157
- package/src/cli/tui/useNavigation.ts +0 -56
- package/src/orchestrate/context-compact.ts +0 -188
- package/src/team/file-locks.ts +0 -173
- package/src/team/index.ts +0 -23
- package/src/team/messages.ts +0 -203
- package/src/team/persistence.ts +0 -96
- package/src/team/registry.ts +0 -158
- package/src/team/tasks.ts +0 -211
package/dist/cli/index.js
CHANGED
|
@@ -3221,7 +3221,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
|
|
|
3221
3221
|
|
|
3222
3222
|
// src/cli/version.ts
|
|
3223
3223
|
function getCliVersion() {
|
|
3224
|
-
return true ? "1.4.
|
|
3224
|
+
return true ? "1.4.6" : pkg.version;
|
|
3225
3225
|
}
|
|
3226
3226
|
var init_version = __esm({
|
|
3227
3227
|
"src/cli/version.ts"() {
|
|
@@ -21729,7 +21729,6 @@ __export(config_exports, {
|
|
|
21729
21729
|
getLLMProvider: () => getLLMProvider,
|
|
21730
21730
|
getLoadedEnvFiles: () => getLoadedEnvFiles,
|
|
21731
21731
|
getServerConfig: () => getServerConfig,
|
|
21732
|
-
getTeamConfig: () => getTeamConfig,
|
|
21733
21732
|
loadDotenv: () => loadDotenv,
|
|
21734
21733
|
loadFileConfig: () => loadFileConfig,
|
|
21735
21734
|
loadYamlConfig: () => loadYamlConfig,
|
|
@@ -21801,14 +21800,10 @@ function getServerConfig() {
|
|
|
21801
21800
|
port: server.port
|
|
21802
21801
|
};
|
|
21803
21802
|
}
|
|
21804
|
-
function getTeamConfig() {
|
|
21805
|
-
return loadYamlConfig().team ?? {};
|
|
21806
|
-
}
|
|
21807
21803
|
var init_config = __esm({
|
|
21808
21804
|
"src/config.ts"() {
|
|
21809
21805
|
"use strict";
|
|
21810
21806
|
init_esm_shims();
|
|
21811
|
-
init_yaml_loader();
|
|
21812
21807
|
init_resolved_config();
|
|
21813
21808
|
init_dotenv_loader();
|
|
21814
21809
|
init_legacy_loader();
|
|
@@ -24093,9 +24088,9 @@ async function saveRegistry(baseDir) {
|
|
|
24093
24088
|
await fs6.mkdir(path8.dirname(filePath), { recursive: true });
|
|
24094
24089
|
await fs6.writeFile(filePath, JSON.stringify(registryCache, null, 2), "utf-8");
|
|
24095
24090
|
}
|
|
24096
|
-
function findMatchingGroup(
|
|
24091
|
+
function findMatchingGroup(registry3, projectInfo) {
|
|
24097
24092
|
const normalizedRoot = normalizePath(projectInfo.rootPath);
|
|
24098
|
-
for (const group of
|
|
24093
|
+
for (const group of registry3.groups) {
|
|
24099
24094
|
if (group.aliases.includes(projectInfo.id)) return group;
|
|
24100
24095
|
if (group.rootPaths.some((rp) => rp === normalizedRoot)) return group;
|
|
24101
24096
|
if (projectInfo.gitRemote && group.gitRemote && group.gitRemote === projectInfo.gitRemote) {
|
|
@@ -24108,9 +24103,9 @@ function selectCanonical(aliases) {
|
|
|
24108
24103
|
return [...aliases].sort((a4, b4) => idPriority(b4) - idPriority(a4))[0];
|
|
24109
24104
|
}
|
|
24110
24105
|
async function registerAlias(projectInfo, baseDir) {
|
|
24111
|
-
const
|
|
24106
|
+
const registry3 = await loadRegistry(baseDir);
|
|
24112
24107
|
const normalizedRoot = normalizePath(projectInfo.rootPath);
|
|
24113
|
-
const existingGroup = findMatchingGroup(
|
|
24108
|
+
const existingGroup = findMatchingGroup(registry3, projectInfo);
|
|
24114
24109
|
if (existingGroup) {
|
|
24115
24110
|
let changed = false;
|
|
24116
24111
|
if (!existingGroup.aliases.includes(projectInfo.id)) {
|
|
@@ -24141,13 +24136,13 @@ async function registerAlias(projectInfo, baseDir) {
|
|
|
24141
24136
|
rootPaths: [normalizedRoot],
|
|
24142
24137
|
...projectInfo.gitRemote ? { gitRemote: projectInfo.gitRemote } : {}
|
|
24143
24138
|
};
|
|
24144
|
-
|
|
24139
|
+
registry3.groups.push(newGroup);
|
|
24145
24140
|
await saveRegistry(baseDir);
|
|
24146
24141
|
return newGroup.canonical;
|
|
24147
24142
|
}
|
|
24148
24143
|
async function resolveAliases(projectId, baseDir) {
|
|
24149
|
-
const
|
|
24150
|
-
for (const group of
|
|
24144
|
+
const registry3 = await loadRegistry(baseDir);
|
|
24145
|
+
for (const group of registry3.groups) {
|
|
24151
24146
|
if (group.aliases.includes(projectId) || group.canonical === projectId) {
|
|
24152
24147
|
return [...group.aliases];
|
|
24153
24148
|
}
|
|
@@ -24155,8 +24150,8 @@ async function resolveAliases(projectId, baseDir) {
|
|
|
24155
24150
|
return [projectId];
|
|
24156
24151
|
}
|
|
24157
24152
|
async function getCanonicalId(projectId, baseDir) {
|
|
24158
|
-
const
|
|
24159
|
-
for (const group of
|
|
24153
|
+
const registry3 = await loadRegistry(baseDir);
|
|
24154
|
+
for (const group of registry3.groups) {
|
|
24160
24155
|
if (group.aliases.includes(projectId) || group.canonical === projectId) {
|
|
24161
24156
|
return group.canonical;
|
|
24162
24157
|
}
|
|
@@ -24164,12 +24159,12 @@ async function getCanonicalId(projectId, baseDir) {
|
|
|
24164
24159
|
return projectId;
|
|
24165
24160
|
}
|
|
24166
24161
|
async function getAllAliasGroups(baseDir) {
|
|
24167
|
-
const
|
|
24168
|
-
return
|
|
24162
|
+
const registry3 = await loadRegistry(baseDir);
|
|
24163
|
+
return registry3.groups;
|
|
24169
24164
|
}
|
|
24170
24165
|
async function autoMergeByBaseName(observedIds, baseDir) {
|
|
24171
24166
|
if (observedIds.length <= 1) return 0;
|
|
24172
|
-
const
|
|
24167
|
+
const registry3 = await loadRegistry(baseDir);
|
|
24173
24168
|
const byBaseName = /* @__PURE__ */ new Map();
|
|
24174
24169
|
for (const id of observedIds) {
|
|
24175
24170
|
const baseName = id.split("/").pop() ?? id;
|
|
@@ -24182,7 +24177,7 @@ async function autoMergeByBaseName(observedIds, baseDir) {
|
|
|
24182
24177
|
const existingGroups = /* @__PURE__ */ new Set();
|
|
24183
24178
|
const ungroupedIds = [];
|
|
24184
24179
|
for (const id of ids) {
|
|
24185
|
-
const groupIdx =
|
|
24180
|
+
const groupIdx = registry3.groups.findIndex(
|
|
24186
24181
|
(g4) => g4.aliases.includes(id) || g4.canonical === id
|
|
24187
24182
|
);
|
|
24188
24183
|
if (groupIdx >= 0) {
|
|
@@ -24196,7 +24191,7 @@ async function autoMergeByBaseName(observedIds, baseDir) {
|
|
|
24196
24191
|
const canonical = selectCanonical(allIdsInGroup);
|
|
24197
24192
|
if (existingGroups.size > 0) {
|
|
24198
24193
|
const primaryIdx = [...existingGroups][0];
|
|
24199
|
-
const primaryGroup =
|
|
24194
|
+
const primaryGroup = registry3.groups[primaryIdx];
|
|
24200
24195
|
for (const id of allIdsInGroup) {
|
|
24201
24196
|
if (!primaryGroup.aliases.includes(id)) {
|
|
24202
24197
|
primaryGroup.aliases.push(id);
|
|
@@ -24204,7 +24199,7 @@ async function autoMergeByBaseName(observedIds, baseDir) {
|
|
|
24204
24199
|
}
|
|
24205
24200
|
const otherIdxs = [...existingGroups].slice(1).sort((a4, b4) => b4 - a4);
|
|
24206
24201
|
for (const idx of otherIdxs) {
|
|
24207
|
-
const other =
|
|
24202
|
+
const other = registry3.groups[idx];
|
|
24208
24203
|
for (const alias of other.aliases) {
|
|
24209
24204
|
if (!primaryGroup.aliases.includes(alias)) {
|
|
24210
24205
|
primaryGroup.aliases.push(alias);
|
|
@@ -24218,12 +24213,12 @@ async function autoMergeByBaseName(observedIds, baseDir) {
|
|
|
24218
24213
|
if (other.gitRemote && !primaryGroup.gitRemote) {
|
|
24219
24214
|
primaryGroup.gitRemote = other.gitRemote;
|
|
24220
24215
|
}
|
|
24221
|
-
|
|
24216
|
+
registry3.groups.splice(idx, 1);
|
|
24222
24217
|
}
|
|
24223
24218
|
primaryGroup.canonical = selectCanonical(primaryGroup.aliases);
|
|
24224
24219
|
mergeCount++;
|
|
24225
24220
|
} else {
|
|
24226
|
-
|
|
24221
|
+
registry3.groups.push({
|
|
24227
24222
|
canonical,
|
|
24228
24223
|
aliases: allIdsInGroup,
|
|
24229
24224
|
rootPaths: []
|
|
@@ -25105,7 +25100,8 @@ var init_maintenance_jobs = __esm({
|
|
|
25105
25100
|
"claim-requalification",
|
|
25106
25101
|
"knowledge-compile",
|
|
25107
25102
|
"knowledge-lint",
|
|
25108
|
-
"workflow-index"
|
|
25103
|
+
"workflow-index",
|
|
25104
|
+
"long-term-maintenance"
|
|
25109
25105
|
];
|
|
25110
25106
|
DEFAULT_MAX_ATTEMPTS = 8;
|
|
25111
25107
|
DEFAULT_LEASE_MS = 3e4;
|
|
@@ -25514,6 +25510,7 @@ __export(lifecycle_exports, {
|
|
|
25514
25510
|
enqueueClaimRequalification: () => enqueueClaimRequalification,
|
|
25515
25511
|
enqueueCodegraphRefresh: () => enqueueCodegraphRefresh,
|
|
25516
25512
|
enqueueKnowledgeFollowups: () => enqueueKnowledgeFollowups,
|
|
25513
|
+
enqueueLongTermMaintenance: () => enqueueLongTermMaintenance,
|
|
25517
25514
|
enqueueObservationQualification: () => enqueueObservationQualification
|
|
25518
25515
|
});
|
|
25519
25516
|
function queueFor(input) {
|
|
@@ -25557,6 +25554,14 @@ function enqueueObservationQualification(input) {
|
|
|
25557
25554
|
payload: { source: input.source, limit: 100 }
|
|
25558
25555
|
});
|
|
25559
25556
|
}
|
|
25557
|
+
function enqueueLongTermMaintenance(input) {
|
|
25558
|
+
queueFor(input).enqueue({
|
|
25559
|
+
projectId: input.projectId,
|
|
25560
|
+
kind: "long-term-maintenance",
|
|
25561
|
+
dedupeKey: "long-term-maintenance",
|
|
25562
|
+
payload: { source: input.source }
|
|
25563
|
+
});
|
|
25564
|
+
}
|
|
25560
25565
|
function enqueueKnowledgeFollowups(input) {
|
|
25561
25566
|
const queue2 = queueFor(input);
|
|
25562
25567
|
const payload = {
|
|
@@ -25736,7 +25741,8 @@ var init_isolated_maintenance = __esm({
|
|
|
25736
25741
|
"claim-requalification",
|
|
25737
25742
|
"knowledge-compile",
|
|
25738
25743
|
"knowledge-lint",
|
|
25739
|
-
"workflow-index"
|
|
25744
|
+
"workflow-index",
|
|
25745
|
+
"long-term-maintenance"
|
|
25740
25746
|
];
|
|
25741
25747
|
DEFAULT_TIMEOUT_MS = 5 * 6e4;
|
|
25742
25748
|
MAX_CHILD_OUTPUT_BYTES = 1e6;
|
|
@@ -177446,6 +177452,893 @@ var init_retention = __esm({
|
|
|
177446
177452
|
}
|
|
177447
177453
|
});
|
|
177448
177454
|
|
|
177455
|
+
// src/memory/owner.ts
|
|
177456
|
+
var owner_exports = {};
|
|
177457
|
+
__export(owner_exports, {
|
|
177458
|
+
resolveLocalMemoryOwner: () => resolveLocalMemoryOwner
|
|
177459
|
+
});
|
|
177460
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
177461
|
+
import { promises as fs11 } from "fs";
|
|
177462
|
+
import path18 from "path";
|
|
177463
|
+
function ownerPath(dataDir) {
|
|
177464
|
+
const resolved = path18.resolve(dataDir);
|
|
177465
|
+
const home = path18.basename(resolved).toLocaleLowerCase("en-US") === "data" ? path18.dirname(resolved) : resolved;
|
|
177466
|
+
return path18.join(home, "memorix-user.json");
|
|
177467
|
+
}
|
|
177468
|
+
function normalizedOwnerId(value) {
|
|
177469
|
+
const trimmed = value?.trim();
|
|
177470
|
+
return trimmed && ID_PATTERN.test(trimmed) ? trimmed : void 0;
|
|
177471
|
+
}
|
|
177472
|
+
async function readOwnerFile(filePath) {
|
|
177473
|
+
try {
|
|
177474
|
+
const value = JSON.parse(await fs11.readFile(filePath, "utf8"));
|
|
177475
|
+
const id = typeof value.id === "string" ? normalizedOwnerId(value.id) : void 0;
|
|
177476
|
+
return id ? { id, source: "local-file" } : void 0;
|
|
177477
|
+
} catch {
|
|
177478
|
+
return void 0;
|
|
177479
|
+
}
|
|
177480
|
+
}
|
|
177481
|
+
async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
177482
|
+
const configured = normalizedOwnerId(process.env.MEMORIX_USER_ID);
|
|
177483
|
+
if (configured) return { id: configured, source: "environment" };
|
|
177484
|
+
const filePath = ownerPath(dataDir);
|
|
177485
|
+
const existing = await readOwnerFile(filePath);
|
|
177486
|
+
if (existing || !options.create) return existing;
|
|
177487
|
+
await fs11.mkdir(path18.dirname(filePath), { recursive: true });
|
|
177488
|
+
const created = {
|
|
177489
|
+
version: 1,
|
|
177490
|
+
id: "local-" + randomUUID6(),
|
|
177491
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
177492
|
+
};
|
|
177493
|
+
try {
|
|
177494
|
+
await fs11.writeFile(filePath, JSON.stringify(created, null, 2) + "\n", { encoding: "utf8", flag: "wx" });
|
|
177495
|
+
return { id: created.id, source: "local-file" };
|
|
177496
|
+
} catch (error40) {
|
|
177497
|
+
if (error40?.code !== "EEXIST") throw error40;
|
|
177498
|
+
const concurrent = await readOwnerFile(filePath);
|
|
177499
|
+
if (concurrent) return concurrent;
|
|
177500
|
+
throw new Error("Memorix could not establish a valid local memory owner identity.");
|
|
177501
|
+
}
|
|
177502
|
+
}
|
|
177503
|
+
var ID_PATTERN;
|
|
177504
|
+
var init_owner = __esm({
|
|
177505
|
+
"src/memory/owner.ts"() {
|
|
177506
|
+
"use strict";
|
|
177507
|
+
init_esm_shims();
|
|
177508
|
+
ID_PATTERN = /^[A-Za-z0-9:_-]{3,160}$/;
|
|
177509
|
+
}
|
|
177510
|
+
});
|
|
177511
|
+
|
|
177512
|
+
// src/memory/long-term-store.ts
|
|
177513
|
+
var long_term_store_exports = {};
|
|
177514
|
+
__export(long_term_store_exports, {
|
|
177515
|
+
LongTermMemoryStore: () => LongTermMemoryStore
|
|
177516
|
+
});
|
|
177517
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
177518
|
+
function optionalText2(value) {
|
|
177519
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
177520
|
+
}
|
|
177521
|
+
function arrayValue2(value) {
|
|
177522
|
+
if (typeof value !== "string" || !value) return [];
|
|
177523
|
+
try {
|
|
177524
|
+
const parsed = JSON.parse(value);
|
|
177525
|
+
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
|
|
177526
|
+
} catch {
|
|
177527
|
+
return [];
|
|
177528
|
+
}
|
|
177529
|
+
}
|
|
177530
|
+
function rowToMemory(row) {
|
|
177531
|
+
return {
|
|
177532
|
+
id: row.id,
|
|
177533
|
+
originProjectId: row.originProjectId,
|
|
177534
|
+
ownerId: row.ownerId,
|
|
177535
|
+
scope: row.scope,
|
|
177536
|
+
kind: row.kind,
|
|
177537
|
+
state: row.state,
|
|
177538
|
+
portability: row.portability,
|
|
177539
|
+
title: row.title,
|
|
177540
|
+
content: row.content,
|
|
177541
|
+
facts: arrayValue2(row.factsJson),
|
|
177542
|
+
tags: arrayValue2(row.tagsJson),
|
|
177543
|
+
...optionalText2(row.applicability) ? { applicability: row.applicability } : {},
|
|
177544
|
+
origin: row.origin,
|
|
177545
|
+
createdAt: row.createdAt,
|
|
177546
|
+
updatedAt: row.updatedAt,
|
|
177547
|
+
...optionalText2(row.qualifiedAt) ? { qualifiedAt: row.qualifiedAt } : {},
|
|
177548
|
+
...optionalText2(row.approvedAt) ? { approvedAt: row.approvedAt } : {},
|
|
177549
|
+
...optionalText2(row.archivedAt) ? { archivedAt: row.archivedAt } : {},
|
|
177550
|
+
...optionalText2(row.supersededBy) ? { supersededBy: row.supersededBy } : {},
|
|
177551
|
+
...optionalText2(row.lastValidatedAt) ? { lastValidatedAt: row.lastValidatedAt } : {},
|
|
177552
|
+
accessCount: Number(row.accessCount ?? 0),
|
|
177553
|
+
...optionalText2(row.lastAccessedAt) ? { lastAccessedAt: row.lastAccessedAt } : {}
|
|
177554
|
+
};
|
|
177555
|
+
}
|
|
177556
|
+
function rowToEvidence(row) {
|
|
177557
|
+
return {
|
|
177558
|
+
id: row.id,
|
|
177559
|
+
memoryId: row.memoryId,
|
|
177560
|
+
kind: row.kind,
|
|
177561
|
+
referenceId: row.referenceId,
|
|
177562
|
+
relation: row.relation,
|
|
177563
|
+
...optionalText2(row.locator) ? { locator: row.locator } : {},
|
|
177564
|
+
...optionalText2(row.capturedHash) ? { capturedHash: row.capturedHash } : {},
|
|
177565
|
+
createdAt: row.createdAt
|
|
177566
|
+
};
|
|
177567
|
+
}
|
|
177568
|
+
function rowToEvent(row) {
|
|
177569
|
+
return {
|
|
177570
|
+
id: row.id,
|
|
177571
|
+
memoryId: row.memoryId,
|
|
177572
|
+
kind: row.kind,
|
|
177573
|
+
...optionalText2(row.fromState) ? { fromState: row.fromState } : {},
|
|
177574
|
+
...optionalText2(row.toState) ? { toState: row.toState } : {},
|
|
177575
|
+
...optionalText2(row.detail) ? { detail: row.detail } : {},
|
|
177576
|
+
createdAt: row.createdAt
|
|
177577
|
+
};
|
|
177578
|
+
}
|
|
177579
|
+
var LongTermMemoryStore;
|
|
177580
|
+
var init_long_term_store = __esm({
|
|
177581
|
+
"src/memory/long-term-store.ts"() {
|
|
177582
|
+
"use strict";
|
|
177583
|
+
init_esm_shims();
|
|
177584
|
+
init_sqlite_db();
|
|
177585
|
+
LongTermMemoryStore = class {
|
|
177586
|
+
db = null;
|
|
177587
|
+
async init(dataDir) {
|
|
177588
|
+
this.db = getDatabase(dataDir);
|
|
177589
|
+
}
|
|
177590
|
+
transaction(fn2) {
|
|
177591
|
+
return this.db.transaction(fn2)();
|
|
177592
|
+
}
|
|
177593
|
+
get(id) {
|
|
177594
|
+
const row = this.db.prepare("SELECT * FROM long_term_memories WHERE id = ?").get(id);
|
|
177595
|
+
return row ? rowToMemory(row) : void 0;
|
|
177596
|
+
}
|
|
177597
|
+
list(options = {}) {
|
|
177598
|
+
const limit2 = Math.max(1, Math.min(1e3, Math.floor(options.limit ?? 500)));
|
|
177599
|
+
const clauses = [];
|
|
177600
|
+
const params = [];
|
|
177601
|
+
if (options.ownerId) {
|
|
177602
|
+
clauses.push("ownerId = ?");
|
|
177603
|
+
params.push(options.ownerId);
|
|
177604
|
+
}
|
|
177605
|
+
if (options.originProjectId) {
|
|
177606
|
+
clauses.push("originProjectId = ?");
|
|
177607
|
+
params.push(options.originProjectId);
|
|
177608
|
+
}
|
|
177609
|
+
const where = clauses.length ? " WHERE " + clauses.join(" AND ") : "";
|
|
177610
|
+
const rows = this.db.prepare(
|
|
177611
|
+
"SELECT * FROM long_term_memories" + where + " ORDER BY updatedAt DESC, id LIMIT ?"
|
|
177612
|
+
).all(...params, limit2);
|
|
177613
|
+
return rows.map(rowToMemory);
|
|
177614
|
+
}
|
|
177615
|
+
insert(memory) {
|
|
177616
|
+
this.db.prepare(`
|
|
177617
|
+
INSERT INTO long_term_memories (
|
|
177618
|
+
id, originProjectId, ownerId, scope, kind, state, portability,
|
|
177619
|
+
title, content, factsJson, tagsJson, applicability, origin,
|
|
177620
|
+
createdAt, updatedAt, qualifiedAt, approvedAt, archivedAt,
|
|
177621
|
+
supersededBy, lastValidatedAt, accessCount, lastAccessedAt
|
|
177622
|
+
) VALUES (
|
|
177623
|
+
@id, @originProjectId, @ownerId, @scope, @kind, @state, @portability,
|
|
177624
|
+
@title, @content, @factsJson, @tagsJson, @applicability, @origin,
|
|
177625
|
+
@createdAt, @updatedAt, @qualifiedAt, @approvedAt, @archivedAt,
|
|
177626
|
+
@supersededBy, @lastValidatedAt, @accessCount, @lastAccessedAt
|
|
177627
|
+
)
|
|
177628
|
+
`).run({
|
|
177629
|
+
...memory,
|
|
177630
|
+
factsJson: JSON.stringify(memory.facts),
|
|
177631
|
+
tagsJson: JSON.stringify(memory.tags),
|
|
177632
|
+
applicability: memory.applicability ?? null,
|
|
177633
|
+
qualifiedAt: memory.qualifiedAt ?? null,
|
|
177634
|
+
approvedAt: memory.approvedAt ?? null,
|
|
177635
|
+
archivedAt: memory.archivedAt ?? null,
|
|
177636
|
+
supersededBy: memory.supersededBy ?? null,
|
|
177637
|
+
lastValidatedAt: memory.lastValidatedAt ?? null,
|
|
177638
|
+
lastAccessedAt: memory.lastAccessedAt ?? null
|
|
177639
|
+
});
|
|
177640
|
+
}
|
|
177641
|
+
update(memory) {
|
|
177642
|
+
this.db.prepare(`
|
|
177643
|
+
UPDATE long_term_memories SET
|
|
177644
|
+
scope = @scope,
|
|
177645
|
+
kind = @kind,
|
|
177646
|
+
state = @state,
|
|
177647
|
+
portability = @portability,
|
|
177648
|
+
title = @title,
|
|
177649
|
+
content = @content,
|
|
177650
|
+
factsJson = @factsJson,
|
|
177651
|
+
tagsJson = @tagsJson,
|
|
177652
|
+
applicability = @applicability,
|
|
177653
|
+
updatedAt = @updatedAt,
|
|
177654
|
+
qualifiedAt = @qualifiedAt,
|
|
177655
|
+
approvedAt = @approvedAt,
|
|
177656
|
+
archivedAt = @archivedAt,
|
|
177657
|
+
supersededBy = @supersededBy,
|
|
177658
|
+
lastValidatedAt = @lastValidatedAt,
|
|
177659
|
+
accessCount = @accessCount,
|
|
177660
|
+
lastAccessedAt = @lastAccessedAt
|
|
177661
|
+
WHERE id = @id
|
|
177662
|
+
`).run({
|
|
177663
|
+
...memory,
|
|
177664
|
+
factsJson: JSON.stringify(memory.facts),
|
|
177665
|
+
tagsJson: JSON.stringify(memory.tags),
|
|
177666
|
+
applicability: memory.applicability ?? null,
|
|
177667
|
+
qualifiedAt: memory.qualifiedAt ?? null,
|
|
177668
|
+
approvedAt: memory.approvedAt ?? null,
|
|
177669
|
+
archivedAt: memory.archivedAt ?? null,
|
|
177670
|
+
supersededBy: memory.supersededBy ?? null,
|
|
177671
|
+
lastValidatedAt: memory.lastValidatedAt ?? null,
|
|
177672
|
+
lastAccessedAt: memory.lastAccessedAt ?? null
|
|
177673
|
+
});
|
|
177674
|
+
}
|
|
177675
|
+
insertEvidence(input) {
|
|
177676
|
+
const evidence = {
|
|
177677
|
+
id: randomUUID7(),
|
|
177678
|
+
...input,
|
|
177679
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
177680
|
+
};
|
|
177681
|
+
this.db.prepare(`
|
|
177682
|
+
INSERT INTO long_term_memory_evidence (
|
|
177683
|
+
id, memoryId, kind, referenceId, relation, locator, capturedHash, createdAt
|
|
177684
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
177685
|
+
`).run(
|
|
177686
|
+
evidence.id,
|
|
177687
|
+
evidence.memoryId,
|
|
177688
|
+
evidence.kind,
|
|
177689
|
+
evidence.referenceId,
|
|
177690
|
+
evidence.relation,
|
|
177691
|
+
evidence.locator ?? null,
|
|
177692
|
+
evidence.capturedHash ?? null,
|
|
177693
|
+
evidence.createdAt
|
|
177694
|
+
);
|
|
177695
|
+
return evidence;
|
|
177696
|
+
}
|
|
177697
|
+
listEvidence(memoryId) {
|
|
177698
|
+
return this.db.prepare(`
|
|
177699
|
+
SELECT * FROM long_term_memory_evidence WHERE memoryId = ? ORDER BY createdAt ASC, id
|
|
177700
|
+
`).all(memoryId).map(rowToEvidence);
|
|
177701
|
+
}
|
|
177702
|
+
recordEvent(input) {
|
|
177703
|
+
const event = {
|
|
177704
|
+
id: randomUUID7(),
|
|
177705
|
+
...input,
|
|
177706
|
+
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
177707
|
+
};
|
|
177708
|
+
this.db.prepare(`
|
|
177709
|
+
INSERT INTO long_term_memory_events (id, memoryId, kind, fromState, toState, detail, createdAt)
|
|
177710
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
177711
|
+
`).run(
|
|
177712
|
+
event.id,
|
|
177713
|
+
event.memoryId,
|
|
177714
|
+
event.kind,
|
|
177715
|
+
event.fromState ?? null,
|
|
177716
|
+
event.toState ?? null,
|
|
177717
|
+
event.detail ?? null,
|
|
177718
|
+
event.createdAt
|
|
177719
|
+
);
|
|
177720
|
+
return event;
|
|
177721
|
+
}
|
|
177722
|
+
listEvents(memoryId) {
|
|
177723
|
+
return this.db.prepare(`
|
|
177724
|
+
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
177725
|
+
`).all(memoryId).map(rowToEvent);
|
|
177726
|
+
}
|
|
177727
|
+
markAccess(ids, at2 = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
177728
|
+
const unique3 = [...new Set(ids.filter(Boolean))];
|
|
177729
|
+
if (unique3.length === 0) return;
|
|
177730
|
+
const statement = this.db.prepare(`
|
|
177731
|
+
UPDATE long_term_memories
|
|
177732
|
+
SET accessCount = accessCount + 1, lastAccessedAt = ?
|
|
177733
|
+
WHERE id = ?
|
|
177734
|
+
`);
|
|
177735
|
+
this.db.transaction(() => {
|
|
177736
|
+
for (const id of unique3) statement.run(at2, id);
|
|
177737
|
+
})();
|
|
177738
|
+
}
|
|
177739
|
+
};
|
|
177740
|
+
}
|
|
177741
|
+
});
|
|
177742
|
+
|
|
177743
|
+
// src/memory/long-term-types.ts
|
|
177744
|
+
var LONG_TERM_MEMORY_KINDS, LONG_TERM_MEMORY_SCOPES, LONG_TERM_MEMORY_PORTABILITIES, LONG_TERM_MEMORY_EVIDENCE_KINDS, LONG_TERM_MEMORY_EVIDENCE_RELATIONS;
|
|
177745
|
+
var init_long_term_types = __esm({
|
|
177746
|
+
"src/memory/long-term-types.ts"() {
|
|
177747
|
+
"use strict";
|
|
177748
|
+
init_esm_shims();
|
|
177749
|
+
LONG_TERM_MEMORY_KINDS = ["episodic", "semantic", "procedural"];
|
|
177750
|
+
LONG_TERM_MEMORY_SCOPES = ["project", "user", "team"];
|
|
177751
|
+
LONG_TERM_MEMORY_PORTABILITIES = ["project-bound", "portable"];
|
|
177752
|
+
LONG_TERM_MEMORY_EVIDENCE_KINDS = [
|
|
177753
|
+
"observation",
|
|
177754
|
+
"claim",
|
|
177755
|
+
"workflow",
|
|
177756
|
+
"session",
|
|
177757
|
+
"checkpoint",
|
|
177758
|
+
"git",
|
|
177759
|
+
"code",
|
|
177760
|
+
"test",
|
|
177761
|
+
"run",
|
|
177762
|
+
"document",
|
|
177763
|
+
"manual",
|
|
177764
|
+
"user"
|
|
177765
|
+
];
|
|
177766
|
+
LONG_TERM_MEMORY_EVIDENCE_RELATIONS = [
|
|
177767
|
+
"supports",
|
|
177768
|
+
"verifies",
|
|
177769
|
+
"derives",
|
|
177770
|
+
"user-confirmed"
|
|
177771
|
+
];
|
|
177772
|
+
}
|
|
177773
|
+
});
|
|
177774
|
+
|
|
177775
|
+
// src/memory/long-term.ts
|
|
177776
|
+
var long_term_exports = {};
|
|
177777
|
+
__export(long_term_exports, {
|
|
177778
|
+
approveLongTermMemory: () => approveLongTermMemory,
|
|
177779
|
+
archiveLongTermMemory: () => archiveLongTermMemory,
|
|
177780
|
+
canReadLongTermMemory: () => canReadLongTermMemory,
|
|
177781
|
+
createLongTermMemoryCandidate: () => createLongTermMemoryCandidate,
|
|
177782
|
+
createManualLongTermMemory: () => createManualLongTermMemory,
|
|
177783
|
+
getLongTermMemoryDetail: () => getLongTermMemoryDetail,
|
|
177784
|
+
isEligibleLongTermMemory: () => isEligibleLongTermMemory,
|
|
177785
|
+
listLongTermMemories: () => listLongTermMemories,
|
|
177786
|
+
maintainLongTermMemories: () => maintainLongTermMemories,
|
|
177787
|
+
maybeAutoQualifyLongTermMemory: () => maybeAutoQualifyLongTermMemory,
|
|
177788
|
+
promoteObservationToLongTermMemory: () => promoteObservationToLongTermMemory,
|
|
177789
|
+
qualifyLongTermMemory: () => qualifyLongTermMemory,
|
|
177790
|
+
renderLongTermMemorySummary: () => renderLongTermMemorySummary,
|
|
177791
|
+
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
177792
|
+
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
177793
|
+
});
|
|
177794
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
177795
|
+
function isOneOf(value, values) {
|
|
177796
|
+
return typeof value === "string" && values.includes(value);
|
|
177797
|
+
}
|
|
177798
|
+
function compactText(value, field, max = MAX_TEXT_LENGTH) {
|
|
177799
|
+
if (typeof value !== "string") throw new Error("Long-term memory " + field + " must be text.");
|
|
177800
|
+
const safe = sanitizeCredentials(value).replace(/\s+/g, " ").trim();
|
|
177801
|
+
if (!safe) throw new Error("Long-term memory " + field + " is required.");
|
|
177802
|
+
if (safe.length > max) throw new Error("Long-term memory " + field + " is too long.");
|
|
177803
|
+
return safe;
|
|
177804
|
+
}
|
|
177805
|
+
function compactList(values, field) {
|
|
177806
|
+
if (!values) return [];
|
|
177807
|
+
if (!Array.isArray(values)) throw new Error("Long-term memory " + field + " must be an array.");
|
|
177808
|
+
return [...new Set(values.filter((value) => typeof value === "string").map((value) => compactText(value, field, 500)))].slice(0, MAX_LIST_ITEMS);
|
|
177809
|
+
}
|
|
177810
|
+
function normalizeEvidence(input) {
|
|
177811
|
+
if (!Array.isArray(input) || input.length === 0) {
|
|
177812
|
+
throw new Error("A long-term memory requires at least one source evidence reference.");
|
|
177813
|
+
}
|
|
177814
|
+
return input.map((evidence) => {
|
|
177815
|
+
if (!evidence || !isOneOf(evidence.kind, LONG_TERM_MEMORY_EVIDENCE_KINDS)) {
|
|
177816
|
+
throw new Error("Long-term memory evidence kind is invalid.");
|
|
177817
|
+
}
|
|
177818
|
+
if (!isOneOf(evidence.relation, LONG_TERM_MEMORY_EVIDENCE_RELATIONS)) {
|
|
177819
|
+
throw new Error("Long-term memory evidence relation is invalid.");
|
|
177820
|
+
}
|
|
177821
|
+
return {
|
|
177822
|
+
kind: evidence.kind,
|
|
177823
|
+
referenceId: compactText(evidence.referenceId, "evidence reference", 1e3),
|
|
177824
|
+
relation: evidence.relation,
|
|
177825
|
+
...evidence.locator ? { locator: compactText(evidence.locator, "evidence locator", 1e3) } : {},
|
|
177826
|
+
...evidence.capturedHash ? { capturedHash: compactText(evidence.capturedHash, "evidence hash", 1e3) } : {}
|
|
177827
|
+
};
|
|
177828
|
+
});
|
|
177829
|
+
}
|
|
177830
|
+
function assertScope(scope) {
|
|
177831
|
+
if (!isOneOf(scope, LONG_TERM_MEMORY_SCOPES)) throw new Error("Long-term memory scope is invalid.");
|
|
177832
|
+
}
|
|
177833
|
+
function assertKind(kind) {
|
|
177834
|
+
if (!isOneOf(kind, LONG_TERM_MEMORY_KINDS)) throw new Error("Long-term memory kind is invalid.");
|
|
177835
|
+
}
|
|
177836
|
+
function assertPortability(value) {
|
|
177837
|
+
if (!isOneOf(value, LONG_TERM_MEMORY_PORTABILITIES)) {
|
|
177838
|
+
throw new Error("Long-term memory portability is invalid.");
|
|
177839
|
+
}
|
|
177840
|
+
}
|
|
177841
|
+
function assertPortableEvidence(scope, portability, evidence) {
|
|
177842
|
+
if (portability !== "portable") return;
|
|
177843
|
+
if (scope !== "user") {
|
|
177844
|
+
throw new Error("Only user-scoped long-term memories may be portable across projects.");
|
|
177845
|
+
}
|
|
177846
|
+
if (evidence.some((item) => !PORTABLE_EVIDENCE_KINDS.has(item.kind))) {
|
|
177847
|
+
throw new Error("Portable user memory may only use manual or user-confirmed evidence; project code, Git, observation, test, session, claim, and workflow evidence must remain project-bound.");
|
|
177848
|
+
}
|
|
177849
|
+
}
|
|
177850
|
+
function requireTeamReader(scope, reader) {
|
|
177851
|
+
if (scope === "team" && reader?.isTeamMember !== true) {
|
|
177852
|
+
throw new Error("Team long-term memory requires an explicit active team identity for this project.");
|
|
177853
|
+
}
|
|
177854
|
+
}
|
|
177855
|
+
function matchesScope(memory, reader) {
|
|
177856
|
+
if (memory.scope === "project") return memory.originProjectId === reader.projectId;
|
|
177857
|
+
if (memory.scope === "team") {
|
|
177858
|
+
return memory.originProjectId === reader.projectId && reader.isTeamMember === true;
|
|
177859
|
+
}
|
|
177860
|
+
if (!reader.ownerId || memory.ownerId !== reader.ownerId) return false;
|
|
177861
|
+
return memory.portability === "portable" || memory.originProjectId === reader.projectId;
|
|
177862
|
+
}
|
|
177863
|
+
function canReadLongTermMemory(memory, reader) {
|
|
177864
|
+
return matchesScope(memory, reader);
|
|
177865
|
+
}
|
|
177866
|
+
function isEligibleLongTermMemory(memory) {
|
|
177867
|
+
return memory.state === "qualified" || memory.state === "approved";
|
|
177868
|
+
}
|
|
177869
|
+
function taskTerms(task) {
|
|
177870
|
+
const matches = task.toLocaleLowerCase("en-US").match(/[\p{L}\p{N}_./:-]+/gu) ?? [];
|
|
177871
|
+
return [...new Set(matches.filter((term) => term.length > 1 && !STOP_TERMS.has(term)))].slice(0, 16);
|
|
177872
|
+
}
|
|
177873
|
+
function kindFitScore(kind, task) {
|
|
177874
|
+
const normalized = task.toLocaleLowerCase("en-US");
|
|
177875
|
+
const hints = {
|
|
177876
|
+
episodic: ["resume", "continue", "handoff", "previous", "session", "\u63A5\u624B", "\u7EE7\u7EED", "\u4EA4\u63A5", "\u4E0A\u6B21", "\u4F1A\u8BDD"],
|
|
177877
|
+
semantic: ["why", "what", "architecture", "design", "decision", "reason", "\u4E3A\u4EC0\u4E48", "\u662F\u4EC0\u4E48", "\u67B6\u6784", "\u8BBE\u8BA1", "\u51B3\u7B56", "\u539F\u56E0"],
|
|
177878
|
+
procedural: ["how", "steps", "procedure", "run", "release", "publish", "verify", "implement", "\u6D41\u7A0B", "\u6B65\u9AA4", "\u53D1\u5E03", "\u9A8C\u8BC1", "\u4FEE\u590D", "\u5B9E\u73B0"]
|
|
177879
|
+
};
|
|
177880
|
+
return hints[kind].some((hint) => normalized.includes(hint)) ? 1 : 0;
|
|
177881
|
+
}
|
|
177882
|
+
function validationFreshnessScore(memory) {
|
|
177883
|
+
const validatedAt = memory.lastValidatedAt ?? memory.approvedAt ?? memory.qualifiedAt;
|
|
177884
|
+
if (!validatedAt) return 0;
|
|
177885
|
+
const time3 = Date.parse(validatedAt);
|
|
177886
|
+
if (!Number.isFinite(time3)) return 0;
|
|
177887
|
+
const ageDays = Math.max(0, Date.now() - time3) / (24 * 60 * 60 * 1e3);
|
|
177888
|
+
if (ageDays <= 30) return 0.35;
|
|
177889
|
+
if (ageDays <= 90) return 0.15;
|
|
177890
|
+
return 0;
|
|
177891
|
+
}
|
|
177892
|
+
function scoreForTask(memory, task) {
|
|
177893
|
+
const terms = taskTerms(task);
|
|
177894
|
+
if (terms.length === 0) return void 0;
|
|
177895
|
+
const title = memory.title.toLocaleLowerCase("en-US");
|
|
177896
|
+
const content = memory.content.toLocaleLowerCase("en-US");
|
|
177897
|
+
const facts = memory.facts.join(" ").toLocaleLowerCase("en-US");
|
|
177898
|
+
const tags = memory.tags.join(" ").toLocaleLowerCase("en-US");
|
|
177899
|
+
const applicability = (memory.applicability ?? "").toLocaleLowerCase("en-US");
|
|
177900
|
+
let score = memory.state === "approved" ? 0.5 : 0;
|
|
177901
|
+
const matched = [];
|
|
177902
|
+
for (const term of terms) {
|
|
177903
|
+
let termScore = 0;
|
|
177904
|
+
if (title.includes(term)) termScore += 5;
|
|
177905
|
+
if (tags.includes(term)) termScore += 4;
|
|
177906
|
+
if (applicability.includes(term)) termScore += 3;
|
|
177907
|
+
if (facts.includes(term)) termScore += 2;
|
|
177908
|
+
if (content.includes(term)) termScore += 1;
|
|
177909
|
+
if (termScore > 0) {
|
|
177910
|
+
score += termScore;
|
|
177911
|
+
matched.push(term);
|
|
177912
|
+
}
|
|
177913
|
+
}
|
|
177914
|
+
if (matched.length === 0) return void 0;
|
|
177915
|
+
score += kindFitScore(memory.kind, task);
|
|
177916
|
+
score += validationFreshnessScore(memory);
|
|
177917
|
+
const kindLabel = memory.kind === "procedural" ? "procedure" : memory.kind === "semantic" ? "fact" : "episode";
|
|
177918
|
+
const freshness = validationFreshnessScore(memory) > 0 ? "; recently validated" : "";
|
|
177919
|
+
return { score, reason: kindLabel + " matches " + matched.slice(0, 3).join(", ") + freshness };
|
|
177920
|
+
}
|
|
177921
|
+
function semanticText(memory) {
|
|
177922
|
+
return sanitizeCredentials([
|
|
177923
|
+
memory.title,
|
|
177924
|
+
memory.applicability,
|
|
177925
|
+
memory.tags.join(" "),
|
|
177926
|
+
memory.facts.join(" "),
|
|
177927
|
+
memory.content
|
|
177928
|
+
].filter((value) => Boolean(value)).join("\n")).replace(/\s+/g, " ").trim().slice(0, MAX_TEXT_LENGTH);
|
|
177929
|
+
}
|
|
177930
|
+
function cosineSimilarity(left, right) {
|
|
177931
|
+
if (left.length === 0 || left.length !== right.length) return 0;
|
|
177932
|
+
let dot = 0;
|
|
177933
|
+
let leftMagnitude = 0;
|
|
177934
|
+
let rightMagnitude = 0;
|
|
177935
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
177936
|
+
const a4 = left[index];
|
|
177937
|
+
const b4 = right[index];
|
|
177938
|
+
if (!Number.isFinite(a4) || !Number.isFinite(b4)) return 0;
|
|
177939
|
+
dot += a4 * b4;
|
|
177940
|
+
leftMagnitude += a4 * a4;
|
|
177941
|
+
rightMagnitude += b4 * b4;
|
|
177942
|
+
}
|
|
177943
|
+
if (leftMagnitude === 0 || rightMagnitude === 0) return 0;
|
|
177944
|
+
return dot / Math.sqrt(leftMagnitude * rightMagnitude);
|
|
177945
|
+
}
|
|
177946
|
+
function semanticSelection(memory, similarity, task) {
|
|
177947
|
+
if (similarity < MIN_SEMANTIC_SIMILARITY) return void 0;
|
|
177948
|
+
const kindLabel = memory.kind === "procedural" ? "procedure" : memory.kind === "semantic" ? "fact" : "episode";
|
|
177949
|
+
const freshness = validationFreshnessScore(memory) > 0 ? "; recently validated" : "";
|
|
177950
|
+
return {
|
|
177951
|
+
score: similarity * 10 + (memory.state === "approved" ? 0.5 : 0) + kindFitScore(memory.kind, task) + validationFreshnessScore(memory),
|
|
177952
|
+
reason: kindLabel + " semantic match " + similarity.toFixed(2) + freshness
|
|
177953
|
+
};
|
|
177954
|
+
}
|
|
177955
|
+
async function resolveSemanticProvider(explicit) {
|
|
177956
|
+
if (explicit !== void 0) return explicit;
|
|
177957
|
+
try {
|
|
177958
|
+
const { getEmbeddingProvider: getEmbeddingProvider2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
|
|
177959
|
+
return await withTimeout(
|
|
177960
|
+
getEmbeddingProvider2({ requestTimeoutMs: SEMANTIC_RETRIEVAL_TIMEOUT_MS, retry: false }),
|
|
177961
|
+
SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
177962
|
+
"Long-term semantic provider initialization"
|
|
177963
|
+
);
|
|
177964
|
+
} catch {
|
|
177965
|
+
return null;
|
|
177966
|
+
}
|
|
177967
|
+
}
|
|
177968
|
+
function createStore(dataDir) {
|
|
177969
|
+
const store2 = new LongTermMemoryStore();
|
|
177970
|
+
return store2.init(dataDir).then(() => store2);
|
|
177971
|
+
}
|
|
177972
|
+
async function createManualLongTermMemory(input) {
|
|
177973
|
+
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
177974
|
+
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
177975
|
+
assertScope(input.scope);
|
|
177976
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID8(), relation: "supports" }];
|
|
177977
|
+
return createLongTermMemoryWithDataDir({
|
|
177978
|
+
dataDir: input.dataDir,
|
|
177979
|
+
originProjectId: input.projectId,
|
|
177980
|
+
ownerId: owner.id,
|
|
177981
|
+
scope: input.scope,
|
|
177982
|
+
kind: input.kind,
|
|
177983
|
+
portability: input.portability,
|
|
177984
|
+
title: input.title,
|
|
177985
|
+
content: input.content,
|
|
177986
|
+
facts: input.facts,
|
|
177987
|
+
tags: input.tags,
|
|
177988
|
+
applicability: input.applicability,
|
|
177989
|
+
origin: "manual",
|
|
177990
|
+
evidence,
|
|
177991
|
+
reader: input.reader
|
|
177992
|
+
});
|
|
177993
|
+
}
|
|
177994
|
+
async function promoteObservationToLongTermMemory(input) {
|
|
177995
|
+
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
177996
|
+
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
177997
|
+
return createLongTermMemoryWithDataDir({
|
|
177998
|
+
dataDir: input.dataDir,
|
|
177999
|
+
originProjectId: input.observation.projectId,
|
|
178000
|
+
ownerId: owner.id,
|
|
178001
|
+
scope: input.scope,
|
|
178002
|
+
kind: input.kind,
|
|
178003
|
+
portability: "project-bound",
|
|
178004
|
+
title: input.observation.title,
|
|
178005
|
+
content: input.observation.narrative,
|
|
178006
|
+
facts: input.observation.facts,
|
|
178007
|
+
tags: input.tags ?? input.observation.concepts,
|
|
178008
|
+
applicability: input.applicability,
|
|
178009
|
+
origin: input.observation.source === "git" ? "git" : "agent",
|
|
178010
|
+
evidence: [{
|
|
178011
|
+
kind: "observation",
|
|
178012
|
+
referenceId: "obs:" + input.observation.projectId + ":" + input.observation.id,
|
|
178013
|
+
relation: "derives"
|
|
178014
|
+
}],
|
|
178015
|
+
reader: input.reader
|
|
178016
|
+
});
|
|
178017
|
+
}
|
|
178018
|
+
async function createLongTermMemoryCandidate(input) {
|
|
178019
|
+
return createLongTermMemoryWithDataDir(input);
|
|
178020
|
+
}
|
|
178021
|
+
async function createLongTermMemoryWithDataDir(input) {
|
|
178022
|
+
assertScope(input.scope);
|
|
178023
|
+
assertKind(input.kind);
|
|
178024
|
+
const portability = input.portability ?? "project-bound";
|
|
178025
|
+
assertPortability(portability);
|
|
178026
|
+
requireTeamReader(input.scope, input.reader);
|
|
178027
|
+
const evidenceInputs = normalizeEvidence(input.evidence);
|
|
178028
|
+
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
178029
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
178030
|
+
const memory = {
|
|
178031
|
+
id: randomUUID8(),
|
|
178032
|
+
originProjectId: compactText(input.originProjectId, "origin project id", 1e3),
|
|
178033
|
+
ownerId: compactText(input.ownerId, "owner id", 160),
|
|
178034
|
+
scope: input.scope,
|
|
178035
|
+
kind: input.kind,
|
|
178036
|
+
state: "candidate",
|
|
178037
|
+
portability,
|
|
178038
|
+
title: compactText(input.title, "title", 500),
|
|
178039
|
+
content: compactText(input.content, "content"),
|
|
178040
|
+
facts: compactList(input.facts, "facts"),
|
|
178041
|
+
tags: compactList(input.tags, "tags"),
|
|
178042
|
+
...input.applicability ? { applicability: compactText(input.applicability, "applicability", 1e3) } : {},
|
|
178043
|
+
origin: input.origin ?? "manual",
|
|
178044
|
+
createdAt: now3,
|
|
178045
|
+
updatedAt: now3,
|
|
178046
|
+
accessCount: 0
|
|
178047
|
+
};
|
|
178048
|
+
const store2 = await createStore(input.dataDir);
|
|
178049
|
+
const evidence = store2.transaction(() => {
|
|
178050
|
+
store2.insert(memory);
|
|
178051
|
+
const written = evidenceInputs.map((item) => store2.insertEvidence({ memoryId: memory.id, ...item, createdAt: now3 }));
|
|
178052
|
+
store2.recordEvent({
|
|
178053
|
+
memoryId: memory.id,
|
|
178054
|
+
kind: "created",
|
|
178055
|
+
toState: "candidate",
|
|
178056
|
+
detail: "Created as a source-backed long-term memory candidate.",
|
|
178057
|
+
createdAt: now3
|
|
178058
|
+
});
|
|
178059
|
+
return written;
|
|
178060
|
+
});
|
|
178061
|
+
return { memory, evidence };
|
|
178062
|
+
}
|
|
178063
|
+
function transitionDetail(value) {
|
|
178064
|
+
return compactText(value, "transition reason", 1e3);
|
|
178065
|
+
}
|
|
178066
|
+
async function transitionMemory(input) {
|
|
178067
|
+
const store2 = await createStore(input.dataDir);
|
|
178068
|
+
return store2.transaction(() => {
|
|
178069
|
+
const current = store2.get(input.id);
|
|
178070
|
+
if (!current) throw new Error("Long-term memory was not found.");
|
|
178071
|
+
if (current.state !== input.expected) {
|
|
178072
|
+
throw new Error("Long-term memory must be " + input.expected + " before it can be " + input.next + ".");
|
|
178073
|
+
}
|
|
178074
|
+
const evidence = store2.listEvidence(current.id);
|
|
178075
|
+
if (evidence.length === 0) throw new Error("Long-term memory cannot advance without source evidence.");
|
|
178076
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
178077
|
+
const next = {
|
|
178078
|
+
...current,
|
|
178079
|
+
state: input.next,
|
|
178080
|
+
updatedAt: now3,
|
|
178081
|
+
lastValidatedAt: now3,
|
|
178082
|
+
...input.next === "qualified" ? { qualifiedAt: now3 } : { approvedAt: now3 }
|
|
178083
|
+
};
|
|
178084
|
+
store2.update(next);
|
|
178085
|
+
store2.recordEvent({
|
|
178086
|
+
memoryId: next.id,
|
|
178087
|
+
kind: input.event,
|
|
178088
|
+
fromState: current.state,
|
|
178089
|
+
toState: next.state,
|
|
178090
|
+
detail: transitionDetail(input.reason),
|
|
178091
|
+
createdAt: now3
|
|
178092
|
+
});
|
|
178093
|
+
return next;
|
|
178094
|
+
});
|
|
178095
|
+
}
|
|
178096
|
+
async function qualifyLongTermMemory(input) {
|
|
178097
|
+
return transitionMemory({ ...input, expected: "candidate", next: "qualified", event: "qualified" });
|
|
178098
|
+
}
|
|
178099
|
+
async function approveLongTermMemory(input) {
|
|
178100
|
+
return transitionMemory({ ...input, expected: "qualified", next: "approved", event: "approved" });
|
|
178101
|
+
}
|
|
178102
|
+
async function archiveLongTermMemory(input) {
|
|
178103
|
+
const store2 = await createStore(input.dataDir);
|
|
178104
|
+
return store2.transaction(() => {
|
|
178105
|
+
const current = store2.get(input.id);
|
|
178106
|
+
if (!current) throw new Error("Long-term memory was not found.");
|
|
178107
|
+
if (current.state === "archived" || current.state === "superseded") {
|
|
178108
|
+
throw new Error("Long-term memory is already inactive.");
|
|
178109
|
+
}
|
|
178110
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
178111
|
+
const next = { ...current, state: "archived", archivedAt: now3, updatedAt: now3 };
|
|
178112
|
+
store2.update(next);
|
|
178113
|
+
store2.recordEvent({
|
|
178114
|
+
memoryId: next.id,
|
|
178115
|
+
kind: "archived",
|
|
178116
|
+
fromState: current.state,
|
|
178117
|
+
toState: "archived",
|
|
178118
|
+
detail: transitionDetail(input.reason),
|
|
178119
|
+
createdAt: now3
|
|
178120
|
+
});
|
|
178121
|
+
return next;
|
|
178122
|
+
});
|
|
178123
|
+
}
|
|
178124
|
+
async function supersedeLongTermMemory(input) {
|
|
178125
|
+
const store2 = await createStore(input.dataDir);
|
|
178126
|
+
return store2.transaction(() => {
|
|
178127
|
+
const current = store2.get(input.id);
|
|
178128
|
+
if (!current) throw new Error("Long-term memory was not found.");
|
|
178129
|
+
if (current.state === "archived" || current.state === "superseded") {
|
|
178130
|
+
throw new Error("Long-term memory is already inactive.");
|
|
178131
|
+
}
|
|
178132
|
+
if (current.id === input.supersededBy) {
|
|
178133
|
+
throw new Error("Long-term memory cannot supersede itself.");
|
|
178134
|
+
}
|
|
178135
|
+
const replacement = store2.get(input.supersededBy);
|
|
178136
|
+
if (!replacement || !isEligibleLongTermMemory(replacement)) {
|
|
178137
|
+
throw new Error("Replacement long-term memory must be qualified or approved.");
|
|
178138
|
+
}
|
|
178139
|
+
if (replacement.scope !== current.scope) {
|
|
178140
|
+
throw new Error("Replacement long-term memory must use the same scope.");
|
|
178141
|
+
}
|
|
178142
|
+
if (current.scope === "user" && replacement.ownerId !== current.ownerId) {
|
|
178143
|
+
throw new Error("User long-term memory may only be superseded by the same local owner.");
|
|
178144
|
+
}
|
|
178145
|
+
if (current.scope !== "user" && replacement.originProjectId !== current.originProjectId) {
|
|
178146
|
+
throw new Error("Project and team long-term memory may only be superseded within the same project.");
|
|
178147
|
+
}
|
|
178148
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
178149
|
+
const next = {
|
|
178150
|
+
...current,
|
|
178151
|
+
state: "superseded",
|
|
178152
|
+
supersededBy: replacement.id,
|
|
178153
|
+
updatedAt: now3
|
|
178154
|
+
};
|
|
178155
|
+
store2.update(next);
|
|
178156
|
+
store2.recordEvent({
|
|
178157
|
+
memoryId: next.id,
|
|
178158
|
+
kind: "superseded",
|
|
178159
|
+
fromState: current.state,
|
|
178160
|
+
toState: "superseded",
|
|
178161
|
+
detail: transitionDetail(input.reason),
|
|
178162
|
+
createdAt: now3
|
|
178163
|
+
});
|
|
178164
|
+
return next;
|
|
178165
|
+
});
|
|
178166
|
+
}
|
|
178167
|
+
async function maybeAutoQualifyLongTermMemory(input) {
|
|
178168
|
+
if (input.source !== "manual" && input.sourceDetail !== "explicit") return null;
|
|
178169
|
+
try {
|
|
178170
|
+
return await qualifyLongTermMemory({
|
|
178171
|
+
dataDir: input.dataDir,
|
|
178172
|
+
id: input.id,
|
|
178173
|
+
reason: "auto-qualified: explicit request carries its own source evidence"
|
|
178174
|
+
});
|
|
178175
|
+
} catch {
|
|
178176
|
+
return null;
|
|
178177
|
+
}
|
|
178178
|
+
}
|
|
178179
|
+
async function maintainLongTermMemories(input) {
|
|
178180
|
+
const now3 = input.now ?? /* @__PURE__ */ new Date();
|
|
178181
|
+
const decayDays = input.decayDays ?? 30;
|
|
178182
|
+
const cutoff = now3.getTime() - decayDays * 24 * 60 * 60 * 1e3;
|
|
178183
|
+
const result = { archived: 0, superseded: 0 };
|
|
178184
|
+
const store2 = await createStore(input.dataDir);
|
|
178185
|
+
const all = store2.list({ originProjectId: input.projectId });
|
|
178186
|
+
for (const memory of all) {
|
|
178187
|
+
if (memory.state !== "qualified" && memory.state !== "approved") continue;
|
|
178188
|
+
const lastActivity = Date.parse(memory.lastAccessedAt ?? memory.updatedAt);
|
|
178189
|
+
if (!Number.isFinite(lastActivity) || lastActivity >= cutoff) continue;
|
|
178190
|
+
try {
|
|
178191
|
+
await archiveLongTermMemory({
|
|
178192
|
+
dataDir: input.dataDir,
|
|
178193
|
+
id: memory.id,
|
|
178194
|
+
reason: "auto-archive: no activity since " + new Date(lastActivity).toISOString().slice(0, 10)
|
|
178195
|
+
});
|
|
178196
|
+
result.archived += 1;
|
|
178197
|
+
} catch {
|
|
178198
|
+
}
|
|
178199
|
+
}
|
|
178200
|
+
const groups = /* @__PURE__ */ new Map();
|
|
178201
|
+
for (const memory of store2.list({ originProjectId: input.projectId })) {
|
|
178202
|
+
if (memory.state !== "qualified" && memory.state !== "approved") continue;
|
|
178203
|
+
const key = memory.scope + "\0" + memory.kind + "\0" + memory.title.trim().toLowerCase();
|
|
178204
|
+
const group = groups.get(key) ?? [];
|
|
178205
|
+
group.push(memory);
|
|
178206
|
+
groups.set(key, group);
|
|
178207
|
+
}
|
|
178208
|
+
for (const group of groups.values()) {
|
|
178209
|
+
if (group.length < 2) continue;
|
|
178210
|
+
group.sort((a4, b4) => Date.parse(b4.createdAt) - Date.parse(a4.createdAt));
|
|
178211
|
+
const newest = group[0];
|
|
178212
|
+
for (const older of group.slice(1)) {
|
|
178213
|
+
try {
|
|
178214
|
+
await supersedeLongTermMemory({
|
|
178215
|
+
dataDir: input.dataDir,
|
|
178216
|
+
id: older.id,
|
|
178217
|
+
supersededBy: newest.id,
|
|
178218
|
+
reason: "auto-supersede: a newer record shares the same title"
|
|
178219
|
+
});
|
|
178220
|
+
result.superseded += 1;
|
|
178221
|
+
} catch {
|
|
178222
|
+
}
|
|
178223
|
+
}
|
|
178224
|
+
}
|
|
178225
|
+
return result;
|
|
178226
|
+
}
|
|
178227
|
+
async function listLongTermMemories(input) {
|
|
178228
|
+
const store2 = await createStore(input.dataDir);
|
|
178229
|
+
return store2.list({ limit: input.limit ?? 100 }).filter((memory) => canReadLongTermMemory(memory, input.reader)).filter((memory) => input.includeInactive || memory.state !== "archived" && memory.state !== "superseded").map((memory) => ({ memory, evidence: store2.listEvidence(memory.id) }));
|
|
178230
|
+
}
|
|
178231
|
+
async function getLongTermMemoryDetail(input) {
|
|
178232
|
+
const store2 = await createStore(input.dataDir);
|
|
178233
|
+
const memory = store2.get(input.id);
|
|
178234
|
+
if (!memory || !canReadLongTermMemory(memory, input.reader)) {
|
|
178235
|
+
throw new Error("Long-term memory was not found in the active scope.");
|
|
178236
|
+
}
|
|
178237
|
+
store2.markAccess([memory.id]);
|
|
178238
|
+
return { memory, evidence: store2.listEvidence(memory.id), events: store2.listEvents(memory.id) };
|
|
178239
|
+
}
|
|
178240
|
+
async function selectLongTermMemoriesForTask(input) {
|
|
178241
|
+
const task = input.task?.trim();
|
|
178242
|
+
if (!task) return [];
|
|
178243
|
+
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: false });
|
|
178244
|
+
const reader = {
|
|
178245
|
+
projectId: input.projectId,
|
|
178246
|
+
...owner ? { ownerId: owner.id } : {},
|
|
178247
|
+
...input.agentId ? { agentId: input.agentId } : {},
|
|
178248
|
+
...input.isTeamMember ? { isTeamMember: true } : {}
|
|
178249
|
+
};
|
|
178250
|
+
const store2 = await createStore(input.dataDir);
|
|
178251
|
+
const eligible = store2.list({ limit: 1e3 }).filter((memory) => isEligibleLongTermMemory(memory) && canReadLongTermMemory(memory, reader));
|
|
178252
|
+
let selected = eligible.map((memory) => {
|
|
178253
|
+
const ranked = scoreForTask(memory, task);
|
|
178254
|
+
return ranked ? {
|
|
178255
|
+
memory,
|
|
178256
|
+
evidence: store2.listEvidence(memory.id),
|
|
178257
|
+
score: ranked.score,
|
|
178258
|
+
reason: ranked.reason
|
|
178259
|
+
} : void 0;
|
|
178260
|
+
}).filter((item) => Boolean(item)).sort((left, right) => right.score - left.score || right.memory.updatedAt.localeCompare(left.memory.updatedAt) || left.memory.id.localeCompare(right.memory.id));
|
|
178261
|
+
if (selected.length === 0 && eligible.length > 0) {
|
|
178262
|
+
const provider2 = await resolveSemanticProvider(input.embeddingProvider);
|
|
178263
|
+
const candidates = eligible.slice(0, MAX_SEMANTIC_CANDIDATES);
|
|
178264
|
+
if (provider2 && candidates.length > 0) {
|
|
178265
|
+
try {
|
|
178266
|
+
const vectors = await withTimeout(
|
|
178267
|
+
provider2.embedBatch([task, ...candidates.map(semanticText)], {
|
|
178268
|
+
timeoutMs: SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
178269
|
+
retry: false
|
|
178270
|
+
}),
|
|
178271
|
+
SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
178272
|
+
"Long-term semantic retrieval"
|
|
178273
|
+
);
|
|
178274
|
+
const query = vectors[0];
|
|
178275
|
+
if (Array.isArray(query)) {
|
|
178276
|
+
selected = candidates.map((memory, index) => {
|
|
178277
|
+
const vector = vectors[index + 1];
|
|
178278
|
+
const ranked = Array.isArray(vector) ? semanticSelection(memory, cosineSimilarity(query, vector), task) : void 0;
|
|
178279
|
+
return ranked ? {
|
|
178280
|
+
memory,
|
|
178281
|
+
evidence: store2.listEvidence(memory.id),
|
|
178282
|
+
score: ranked.score,
|
|
178283
|
+
reason: ranked.reason
|
|
178284
|
+
} : void 0;
|
|
178285
|
+
}).filter((item) => Boolean(item)).sort((left, right) => right.score - left.score || right.memory.updatedAt.localeCompare(left.memory.updatedAt) || left.memory.id.localeCompare(right.memory.id));
|
|
178286
|
+
}
|
|
178287
|
+
} catch {
|
|
178288
|
+
}
|
|
178289
|
+
}
|
|
178290
|
+
}
|
|
178291
|
+
selected = selected.slice(0, Math.max(1, Math.min(input.limit ?? 3, 5)));
|
|
178292
|
+
store2.markAccess(selected.map((item) => item.memory.id));
|
|
178293
|
+
return selected;
|
|
178294
|
+
}
|
|
178295
|
+
function renderLongTermMemorySummary(memory, maxTokens = 22) {
|
|
178296
|
+
const source = [memory.title, memory.applicability, memory.content].filter(Boolean).join(": ");
|
|
178297
|
+
const safe = sanitizeCredentials(source).replace(/\s+/g, " ").trim();
|
|
178298
|
+
return countTextTokens(safe) <= maxTokens ? safe : truncateToTokenBudget(safe, maxTokens);
|
|
178299
|
+
}
|
|
178300
|
+
var MAX_TEXT_LENGTH, MAX_LIST_ITEMS, MAX_SEMANTIC_CANDIDATES, SEMANTIC_RETRIEVAL_TIMEOUT_MS, MIN_SEMANTIC_SIMILARITY, PORTABLE_EVIDENCE_KINDS, STOP_TERMS;
|
|
178301
|
+
var init_long_term = __esm({
|
|
178302
|
+
"src/memory/long-term.ts"() {
|
|
178303
|
+
"use strict";
|
|
178304
|
+
init_esm_shims();
|
|
178305
|
+
init_token_budget();
|
|
178306
|
+
init_timeout();
|
|
178307
|
+
init_secret_filter();
|
|
178308
|
+
init_owner();
|
|
178309
|
+
init_long_term_store();
|
|
178310
|
+
init_long_term_types();
|
|
178311
|
+
MAX_TEXT_LENGTH = 12e3;
|
|
178312
|
+
MAX_LIST_ITEMS = 40;
|
|
178313
|
+
MAX_SEMANTIC_CANDIDATES = 48;
|
|
178314
|
+
SEMANTIC_RETRIEVAL_TIMEOUT_MS = 1800;
|
|
178315
|
+
MIN_SEMANTIC_SIMILARITY = 0.58;
|
|
178316
|
+
PORTABLE_EVIDENCE_KINDS = /* @__PURE__ */ new Set(["manual", "user"]);
|
|
178317
|
+
STOP_TERMS = /* @__PURE__ */ new Set([
|
|
178318
|
+
"the",
|
|
178319
|
+
"and",
|
|
178320
|
+
"for",
|
|
178321
|
+
"with",
|
|
178322
|
+
"from",
|
|
178323
|
+
"that",
|
|
178324
|
+
"this",
|
|
178325
|
+
"into",
|
|
178326
|
+
"when",
|
|
178327
|
+
"what",
|
|
178328
|
+
"\u5982\u4F55",
|
|
178329
|
+
"\u4EC0\u4E48",
|
|
178330
|
+
"\u8FD9\u4E2A",
|
|
178331
|
+
"\u90A3\u4E2A",
|
|
178332
|
+
"\u6211\u4EEC",
|
|
178333
|
+
"\u9879\u76EE",
|
|
178334
|
+
"\u8FDB\u884C",
|
|
178335
|
+
"\u9700\u8981",
|
|
178336
|
+
"\u7EE7\u7EED",
|
|
178337
|
+
"\u5904\u7406"
|
|
178338
|
+
]);
|
|
178339
|
+
}
|
|
178340
|
+
});
|
|
178341
|
+
|
|
177449
178342
|
// src/codegraph/ids.ts
|
|
177450
178343
|
import { createHash as createHash5 } from "crypto";
|
|
177451
178344
|
function digest(input) {
|
|
@@ -177484,7 +178377,7 @@ var store_exports = {};
|
|
|
177484
178377
|
__export(store_exports, {
|
|
177485
178378
|
CodeGraphStore: () => CodeGraphStore
|
|
177486
178379
|
});
|
|
177487
|
-
import { randomUUID as
|
|
178380
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
177488
178381
|
import { posix as pathPosix } from "path";
|
|
177489
178382
|
function rowToFile(row) {
|
|
177490
178383
|
return {
|
|
@@ -178201,7 +179094,7 @@ var init_store = __esm({
|
|
|
178201
179094
|
* so an interrupted scan cannot be advertised as complete.
|
|
178202
179095
|
*/
|
|
178203
179096
|
recordCodeStateSnapshot(input) {
|
|
178204
|
-
const id =
|
|
179097
|
+
const id = randomUUID9();
|
|
178205
179098
|
let snapshot;
|
|
178206
179099
|
const tx = this.db.transaction(() => {
|
|
178207
179100
|
const previous = this.db.prepare(
|
|
@@ -178979,8 +179872,8 @@ var claim_store_exports = {};
|
|
|
178979
179872
|
__export(claim_store_exports, {
|
|
178980
179873
|
ClaimStore: () => ClaimStore
|
|
178981
179874
|
});
|
|
178982
|
-
import { createHash as createHash8, randomUUID as
|
|
178983
|
-
function
|
|
179875
|
+
import { createHash as createHash8, randomUUID as randomUUID10 } from "crypto";
|
|
179876
|
+
function optionalText3(value) {
|
|
178984
179877
|
return typeof value === "string" && value ? value : void 0;
|
|
178985
179878
|
}
|
|
178986
179879
|
function rowToClaim(row) {
|
|
@@ -178996,38 +179889,38 @@ function rowToClaim(row) {
|
|
|
178996
179889
|
status: row.status,
|
|
178997
179890
|
confidence: Number(row.confidence),
|
|
178998
179891
|
observedAt: row.observedAt,
|
|
178999
|
-
...
|
|
179000
|
-
...
|
|
179001
|
-
...
|
|
179892
|
+
...optionalText3(row.validFrom) ? { validFrom: row.validFrom } : {},
|
|
179893
|
+
...optionalText3(row.validTo) ? { validTo: row.validTo } : {},
|
|
179894
|
+
...optionalText3(row.supersededBy) ? { supersededBy: row.supersededBy } : {},
|
|
179002
179895
|
reviewState: row.reviewState,
|
|
179003
179896
|
origin: row.origin,
|
|
179004
179897
|
createdAt: row.createdAt,
|
|
179005
179898
|
updatedAt: row.updatedAt
|
|
179006
179899
|
};
|
|
179007
179900
|
}
|
|
179008
|
-
function
|
|
179901
|
+
function rowToEvidence2(row) {
|
|
179009
179902
|
return {
|
|
179010
179903
|
id: row.id,
|
|
179011
179904
|
claimId: row.claimId,
|
|
179012
179905
|
evidenceKind: row.evidenceKind,
|
|
179013
179906
|
evidenceId: row.evidenceId,
|
|
179014
179907
|
relation: row.relation,
|
|
179015
|
-
...
|
|
179016
|
-
...
|
|
179017
|
-
...
|
|
179908
|
+
...optionalText3(row.snapshotId) ? { snapshotId: row.snapshotId } : {},
|
|
179909
|
+
...optionalText3(row.locator) ? { locator: row.locator } : {},
|
|
179910
|
+
...optionalText3(row.capturedHash) ? { capturedHash: row.capturedHash } : {},
|
|
179018
179911
|
createdAt: row.createdAt
|
|
179019
179912
|
};
|
|
179020
179913
|
}
|
|
179021
|
-
function
|
|
179914
|
+
function rowToEvent2(row) {
|
|
179022
179915
|
return {
|
|
179023
179916
|
id: row.id,
|
|
179024
179917
|
projectId: row.projectId,
|
|
179025
179918
|
claimId: row.claimId,
|
|
179026
179919
|
kind: row.kind,
|
|
179027
|
-
...
|
|
179028
|
-
...
|
|
179029
|
-
...
|
|
179030
|
-
...
|
|
179920
|
+
...optionalText3(row.fromStatus) ? { fromStatus: row.fromStatus } : {},
|
|
179921
|
+
...optionalText3(row.toStatus) ? { toStatus: row.toStatus } : {},
|
|
179922
|
+
...optionalText3(row.relatedClaimId) ? { relatedClaimId: row.relatedClaimId } : {},
|
|
179923
|
+
...optionalText3(row.detail) ? { detail: row.detail } : {},
|
|
179031
179924
|
createdAt: row.createdAt
|
|
179032
179925
|
};
|
|
179033
179926
|
}
|
|
@@ -179163,7 +180056,7 @@ var init_claim_store = __esm({
|
|
|
179163
180056
|
locator, capturedHash, evidenceKey, createdAt
|
|
179164
180057
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
179165
180058
|
`).run(
|
|
179166
|
-
|
|
180059
|
+
randomUUID10(),
|
|
179167
180060
|
input.claimId,
|
|
179168
180061
|
input.evidenceKind,
|
|
179169
180062
|
input.evidenceId,
|
|
@@ -179181,11 +180074,11 @@ var init_claim_store = __esm({
|
|
|
179181
180074
|
SELECT * FROM knowledge_claim_evidence
|
|
179182
180075
|
WHERE claimId = ?
|
|
179183
180076
|
ORDER BY createdAt ASC, id
|
|
179184
|
-
`).all(claimId).map(
|
|
180077
|
+
`).all(claimId).map(rowToEvidence2);
|
|
179185
180078
|
}
|
|
179186
180079
|
recordEvent(input) {
|
|
179187
180080
|
const event = {
|
|
179188
|
-
id:
|
|
180081
|
+
id: randomUUID10(),
|
|
179189
180082
|
...input,
|
|
179190
180083
|
...input.detail ? { detail: sanitizeCredentials(input.detail) } : {},
|
|
179191
180084
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -179213,7 +180106,7 @@ var init_claim_store = __esm({
|
|
|
179213
180106
|
SELECT * FROM knowledge_claim_events
|
|
179214
180107
|
WHERE claimId = ?
|
|
179215
180108
|
ORDER BY createdAt ASC, id
|
|
179216
|
-
`).all(claimId).map(
|
|
180109
|
+
`).all(claimId).map(rowToEvent2);
|
|
179217
180110
|
}
|
|
179218
180111
|
};
|
|
179219
180112
|
}
|
|
@@ -179230,8 +180123,8 @@ __export(claims_exports, {
|
|
|
179230
180123
|
supersedeClaim: () => supersedeClaim,
|
|
179231
180124
|
writeClaim: () => writeClaim
|
|
179232
180125
|
});
|
|
179233
|
-
import { createHash as createHash9, randomUUID as
|
|
179234
|
-
function
|
|
180126
|
+
import { createHash as createHash9, randomUUID as randomUUID11 } from "crypto";
|
|
180127
|
+
function compactText2(value, field) {
|
|
179235
180128
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
179236
180129
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
179237
180130
|
if (!sanitized) throw new Error("Claim " + field + " is required");
|
|
@@ -179239,7 +180132,7 @@ function compactText(value, field) {
|
|
|
179239
180132
|
return sanitized;
|
|
179240
180133
|
}
|
|
179241
180134
|
function normalizedTerm(value) {
|
|
179242
|
-
return
|
|
180135
|
+
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
179243
180136
|
}
|
|
179244
180137
|
function hashIdentity(parts) {
|
|
179245
180138
|
return createHash9("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
@@ -179268,7 +180161,7 @@ function validateEvidence(input) {
|
|
|
179268
180161
|
if (!evidence || typeof evidence !== "object") {
|
|
179269
180162
|
throw new Error("Claim evidence must be an object");
|
|
179270
180163
|
}
|
|
179271
|
-
const evidenceId =
|
|
180164
|
+
const evidenceId = compactText2(evidence.evidenceId, "evidence id");
|
|
179272
180165
|
if (evidenceId.length > MAX_EVIDENCE_ID_LENGTH) {
|
|
179273
180166
|
throw new Error("Claim evidence id is too long");
|
|
179274
180167
|
}
|
|
@@ -179282,9 +180175,9 @@ function validateEvidence(input) {
|
|
|
179282
180175
|
evidenceKind: evidence.evidenceKind,
|
|
179283
180176
|
evidenceId,
|
|
179284
180177
|
relation: evidence.relation,
|
|
179285
|
-
...evidence.snapshotId ? { snapshotId:
|
|
179286
|
-
...evidence.locator ? { locator:
|
|
179287
|
-
...evidence.capturedHash ? { capturedHash:
|
|
180178
|
+
...evidence.snapshotId ? { snapshotId: compactText2(evidence.snapshotId, "evidence snapshot id") } : {},
|
|
180179
|
+
...evidence.locator ? { locator: compactText2(evidence.locator, "evidence locator") } : {},
|
|
180180
|
+
...evidence.capturedHash ? { capturedHash: compactText2(evidence.capturedHash, "evidence hash") } : {}
|
|
179288
180181
|
};
|
|
179289
180182
|
});
|
|
179290
180183
|
}
|
|
@@ -179292,10 +180185,10 @@ function normalizeClaimInput(input) {
|
|
|
179292
180185
|
if (!["project", "workspace", "team", "workflow", "task"].includes(input.scope)) {
|
|
179293
180186
|
throw new Error("Claim scope is invalid");
|
|
179294
180187
|
}
|
|
179295
|
-
const projectId =
|
|
179296
|
-
const subject =
|
|
179297
|
-
const predicate =
|
|
179298
|
-
const objectValue =
|
|
180188
|
+
const projectId = compactText2(input.projectId, "project id");
|
|
180189
|
+
const subject = compactText2(input.subject, "subject");
|
|
180190
|
+
const predicate = compactText2(input.predicate, "predicate");
|
|
180191
|
+
const objectValue = compactText2(input.objectValue, "object value");
|
|
179299
180192
|
const identity = buildClaimIdentity({ subject, predicate, objectValue, scope: input.scope });
|
|
179300
180193
|
const origin = input.origin ?? "explicit";
|
|
179301
180194
|
let reviewState = input.reviewState ?? "approved";
|
|
@@ -179316,7 +180209,7 @@ function normalizeClaimInput(input) {
|
|
|
179316
180209
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
179317
180210
|
return {
|
|
179318
180211
|
claim: {
|
|
179319
|
-
id:
|
|
180212
|
+
id: randomUUID11(),
|
|
179320
180213
|
projectId,
|
|
179321
180214
|
subject,
|
|
179322
180215
|
predicate,
|
|
@@ -179416,7 +180309,7 @@ function reviewClaim(store2, input) {
|
|
|
179416
180309
|
if (input.reviewState !== "approved" && input.reviewState !== "rejected") {
|
|
179417
180310
|
throw new Error("A claim review must approve or reject the claim");
|
|
179418
180311
|
}
|
|
179419
|
-
const detail =
|
|
180312
|
+
const detail = compactText2(input.detail, "review detail");
|
|
179420
180313
|
return store2.transaction(() => {
|
|
179421
180314
|
const claim = store2.getClaim(input.claimId);
|
|
179422
180315
|
if (!claim) throw new Error("Claim was not found");
|
|
@@ -179728,8 +180621,8 @@ var init_frontmatter = __esm({
|
|
|
179728
180621
|
|
|
179729
180622
|
// src/knowledge/markdown.ts
|
|
179730
180623
|
import { createHash as createHash10 } from "crypto";
|
|
179731
|
-
import { promises as
|
|
179732
|
-
import
|
|
180624
|
+
import { promises as fs12 } from "fs";
|
|
180625
|
+
import path19 from "path";
|
|
179733
180626
|
function hashContent(content) {
|
|
179734
180627
|
return createHash10("sha256").update(content).digest("hex");
|
|
179735
180628
|
}
|
|
@@ -179787,8 +180680,8 @@ function extractInternalMarkdownLinks(body) {
|
|
|
179787
180680
|
return [...links].sort();
|
|
179788
180681
|
}
|
|
179789
180682
|
function resolvePageLink(sourceRelativePath, target) {
|
|
179790
|
-
const sourceDir =
|
|
179791
|
-
const normalized =
|
|
180683
|
+
const sourceDir = path19.posix.dirname(sourceRelativePath.replace(/\\/g, "/"));
|
|
180684
|
+
const normalized = path19.posix.normalize(path19.posix.join(sourceDir, target.replace(/\\/g, "/")));
|
|
179792
180685
|
if (!normalized || normalized === "." || normalized === ".." || normalized.startsWith("../")) return void 0;
|
|
179793
180686
|
return normalized;
|
|
179794
180687
|
}
|
|
@@ -179810,13 +180703,13 @@ function renderKnowledgePage(frontmatter, body) {
|
|
|
179810
180703
|
});
|
|
179811
180704
|
}
|
|
179812
180705
|
async function readKnowledgePage(absolutePath, workspaceRoot) {
|
|
179813
|
-
const raw = await
|
|
180706
|
+
const raw = await fs12.readFile(absolutePath, "utf8");
|
|
179814
180707
|
try {
|
|
179815
180708
|
const parsed = frontmatter_default(raw);
|
|
179816
180709
|
const frontmatter = validateKnowledgePageFrontmatter(parsed.data);
|
|
179817
180710
|
return {
|
|
179818
180711
|
absolutePath,
|
|
179819
|
-
relativePath: workspaceRoot ?
|
|
180712
|
+
relativePath: workspaceRoot ? path19.relative(workspaceRoot, absolutePath).split(path19.sep).join("/") : path19.basename(absolutePath),
|
|
179820
180713
|
frontmatter,
|
|
179821
180714
|
body: parsed.content.trim(),
|
|
179822
180715
|
contentHash: hashContent(raw),
|
|
@@ -179828,7 +180721,7 @@ async function readKnowledgePage(absolutePath, workspaceRoot) {
|
|
|
179828
180721
|
}
|
|
179829
180722
|
}
|
|
179830
180723
|
async function writeKnowledgePage(absolutePath, content) {
|
|
179831
|
-
await
|
|
180724
|
+
await fs12.mkdir(path19.dirname(absolutePath), { recursive: true });
|
|
179832
180725
|
await atomicWriteFile(absolutePath, content);
|
|
179833
180726
|
return hashContent(content);
|
|
179834
180727
|
}
|
|
@@ -179858,8 +180751,8 @@ __export(wiki_exports, {
|
|
|
179858
180751
|
readKnowledgePage: () => readKnowledgePage
|
|
179859
180752
|
});
|
|
179860
180753
|
import { createHash as createHash11 } from "crypto";
|
|
179861
|
-
import { promises as
|
|
179862
|
-
import
|
|
180754
|
+
import { promises as fs13 } from "fs";
|
|
180755
|
+
import path20 from "path";
|
|
179863
180756
|
function hash2(value) {
|
|
179864
180757
|
return createHash11("sha256").update(value).digest("hex");
|
|
179865
180758
|
}
|
|
@@ -179991,7 +180884,7 @@ function candidatePage(workspace, title, claims, store2) {
|
|
|
179991
180884
|
}
|
|
179992
180885
|
async function fileHashIfPresent(filePath) {
|
|
179993
180886
|
try {
|
|
179994
|
-
return pageContentHash(await
|
|
180887
|
+
return pageContentHash(await fs13.readFile(filePath, "utf8"));
|
|
179995
180888
|
} catch (error40) {
|
|
179996
180889
|
const code = error40 && typeof error40 === "object" && "code" in error40 ? error40.code : void 0;
|
|
179997
180890
|
if (code === "ENOENT") return void 0;
|
|
@@ -180015,8 +180908,8 @@ async function writeIndex(workspace, store2) {
|
|
|
180015
180908
|
lines.push("No pending proposals.");
|
|
180016
180909
|
} else {
|
|
180017
180910
|
for (const proposal of pending) {
|
|
180018
|
-
const relative3 =
|
|
180019
|
-
lines.push("- [" +
|
|
180911
|
+
const relative3 = path20.relative(paths.root, proposal.proposalPath).split(path20.sep).join("/");
|
|
180912
|
+
lines.push("- [" + path20.basename(proposal.proposalPath, ".md") + "](" + relative3 + ")");
|
|
180020
180913
|
}
|
|
180021
180914
|
}
|
|
180022
180915
|
lines.push("");
|
|
@@ -180024,7 +180917,7 @@ async function writeIndex(workspace, store2) {
|
|
|
180024
180917
|
}
|
|
180025
180918
|
async function appendLog(workspace, line) {
|
|
180026
180919
|
const logPath = getKnowledgeWorkspacePaths(workspace).log;
|
|
180027
|
-
await
|
|
180920
|
+
await fs13.appendFile(logPath, "- " + now() + " " + line + "\n", "utf8");
|
|
180028
180921
|
}
|
|
180029
180922
|
function toPageRecord(workspace, page, status, contentHash, manualContentHash) {
|
|
180030
180923
|
return {
|
|
@@ -180109,9 +181002,9 @@ async function applyKnowledgeProposal(input) {
|
|
|
180109
181002
|
}
|
|
180110
181003
|
if (proposal.status !== "pending") throw new Error("Knowledge proposal is not pending review");
|
|
180111
181004
|
const root = getKnowledgeWorkspacePaths(input.workspace).root;
|
|
180112
|
-
const targetPath =
|
|
180113
|
-
const proposalPath =
|
|
180114
|
-
if (!targetPath.startsWith(root +
|
|
181005
|
+
const targetPath = path20.resolve(proposal.targetPath);
|
|
181006
|
+
const proposalPath = path20.resolve(proposal.proposalPath);
|
|
181007
|
+
if (!targetPath.startsWith(root + path20.sep) || !proposalPath.startsWith(root + path20.sep)) {
|
|
180115
181008
|
throw new Error("Knowledge proposal path escapes its workspace");
|
|
180116
181009
|
}
|
|
180117
181010
|
await withFileLock(root, async () => {
|
|
@@ -180149,12 +181042,12 @@ async function markdownFiles(directory) {
|
|
|
180149
181042
|
const files = [];
|
|
180150
181043
|
let entries;
|
|
180151
181044
|
try {
|
|
180152
|
-
entries = await
|
|
181045
|
+
entries = await fs13.readdir(directory, { withFileTypes: true });
|
|
180153
181046
|
} catch {
|
|
180154
181047
|
return files;
|
|
180155
181048
|
}
|
|
180156
181049
|
for (const entry of entries) {
|
|
180157
|
-
const filePath =
|
|
181050
|
+
const filePath = path20.join(directory, entry.name);
|
|
180158
181051
|
if (entry.isDirectory()) {
|
|
180159
181052
|
files.push(...await markdownFiles(filePath));
|
|
180160
181053
|
} else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
|
|
@@ -180177,13 +181070,13 @@ async function lintKnowledgeWorkspace(input) {
|
|
|
180177
181070
|
kind: "malformed-frontmatter",
|
|
180178
181071
|
severity: "error",
|
|
180179
181072
|
message: error40 instanceof Error ? error40.message : "Malformed knowledge page.",
|
|
180180
|
-
relativePath:
|
|
181073
|
+
relativePath: path20.relative(paths.root, filePath).split(path20.sep).join("/")
|
|
180181
181074
|
});
|
|
180182
181075
|
}
|
|
180183
181076
|
}
|
|
180184
181077
|
const indexed = /* @__PURE__ */ new Set();
|
|
180185
181078
|
try {
|
|
180186
|
-
const index = await
|
|
181079
|
+
const index = await fs13.readFile(paths.index, "utf8");
|
|
180187
181080
|
for (const link of extractInternalMarkdownLinks(index)) {
|
|
180188
181081
|
const resolved = resolvePageLink("index.md", link);
|
|
180189
181082
|
if (resolved) indexed.add(resolved);
|
|
@@ -180272,7 +181165,7 @@ async function lintKnowledgeWorkspace(input) {
|
|
|
180272
181165
|
kind: "manual-edit-protected",
|
|
180273
181166
|
severity: "warning",
|
|
180274
181167
|
message: "A newer proposal was held because the target page has manual edits.",
|
|
180275
|
-
relativePath:
|
|
181168
|
+
relativePath: path20.relative(paths.root, proposal.targetPath).split(path20.sep).join("/")
|
|
180276
181169
|
});
|
|
180277
181170
|
}
|
|
180278
181171
|
}
|
|
@@ -180405,7 +181298,7 @@ var workflow_store_exports = {};
|
|
|
180405
181298
|
__export(workflow_store_exports, {
|
|
180406
181299
|
WorkflowStore: () => WorkflowStore
|
|
180407
181300
|
});
|
|
180408
|
-
import { randomUUID as
|
|
181301
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
180409
181302
|
function parseJson(value, fallback) {
|
|
180410
181303
|
if (typeof value !== "string" || !value) return fallback;
|
|
180411
181304
|
try {
|
|
@@ -180414,7 +181307,7 @@ function parseJson(value, fallback) {
|
|
|
180414
181307
|
return fallback;
|
|
180415
181308
|
}
|
|
180416
181309
|
}
|
|
180417
|
-
function
|
|
181310
|
+
function optionalText4(value) {
|
|
180418
181311
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
180419
181312
|
}
|
|
180420
181313
|
function rowToWorkflow(row) {
|
|
@@ -180451,14 +181344,14 @@ function rowToRun(row) {
|
|
|
180451
181344
|
workflowId: row.workflowId,
|
|
180452
181345
|
projectId: row.projectId,
|
|
180453
181346
|
task: row.task,
|
|
180454
|
-
...
|
|
181347
|
+
...optionalText4(row.startingSnapshotId) ? { startingSnapshotId: row.startingSnapshotId } : {},
|
|
180455
181348
|
selectedEvidence: parseJson(row.selectedEvidenceJson, []),
|
|
180456
181349
|
phaseState: parseJson(row.phaseStateJson, {}),
|
|
180457
181350
|
outcome: row.outcome,
|
|
180458
181351
|
verificationVerdict: row.verificationVerdict,
|
|
180459
|
-
...
|
|
181352
|
+
...optionalText4(row.failureReason) ? { failureReason: row.failureReason } : {},
|
|
180460
181353
|
startedAt: row.startedAt,
|
|
180461
|
-
...
|
|
181354
|
+
...optionalText4(row.completedAt) ? { completedAt: row.completedAt } : {}
|
|
180462
181355
|
};
|
|
180463
181356
|
}
|
|
180464
181357
|
var WorkflowStore;
|
|
@@ -180505,7 +181398,7 @@ var init_workflow_store = __esm({
|
|
|
180505
181398
|
}
|
|
180506
181399
|
recordRun(input) {
|
|
180507
181400
|
const run = {
|
|
180508
|
-
id:
|
|
181401
|
+
id: randomUUID12(),
|
|
180509
181402
|
workflowId: input.workflowId,
|
|
180510
181403
|
projectId: input.projectId,
|
|
180511
181404
|
task: input.task.trim(),
|
|
@@ -180583,8 +181476,8 @@ var init_outcome_types = __esm({
|
|
|
180583
181476
|
});
|
|
180584
181477
|
|
|
180585
181478
|
// src/knowledge/outcome-store.ts
|
|
180586
|
-
import { randomUUID as
|
|
180587
|
-
function
|
|
181479
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
181480
|
+
function optionalText5(value) {
|
|
180588
181481
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
180589
181482
|
}
|
|
180590
181483
|
function text(value, field, max = 1e3) {
|
|
@@ -180607,8 +181500,8 @@ function rowToSignal(row) {
|
|
|
180607
181500
|
candidateId: row.candidateId,
|
|
180608
181501
|
kind: row.kind,
|
|
180609
181502
|
sourceRef: row.sourceRef,
|
|
180610
|
-
...
|
|
180611
|
-
...
|
|
181503
|
+
...optionalText5(row.snapshotId) ? { snapshotId: row.snapshotId } : {},
|
|
181504
|
+
...optionalText5(row.detail) ? { detail: row.detail } : {},
|
|
180612
181505
|
observedAt: row.observedAt
|
|
180613
181506
|
};
|
|
180614
181507
|
}
|
|
@@ -180627,7 +181520,7 @@ var init_outcome_store = __esm({
|
|
|
180627
181520
|
}
|
|
180628
181521
|
record(input) {
|
|
180629
181522
|
const signal = {
|
|
180630
|
-
id:
|
|
181523
|
+
id: randomUUID13(),
|
|
180631
181524
|
projectId: text(input.projectId, "project id"),
|
|
180632
181525
|
candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
|
|
180633
181526
|
candidateId: text(input.candidateId, "candidate id"),
|
|
@@ -181054,8 +181947,8 @@ __export(workflows_exports, {
|
|
|
181054
181947
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
181055
181948
|
});
|
|
181056
181949
|
import { createHash as createHash12 } from "crypto";
|
|
181057
|
-
import { promises as
|
|
181058
|
-
import
|
|
181950
|
+
import { promises as fs14 } from "fs";
|
|
181951
|
+
import path21 from "path";
|
|
181059
181952
|
function hash3(value) {
|
|
181060
181953
|
return createHash12("sha256").update(value).digest("hex");
|
|
181061
181954
|
}
|
|
@@ -181076,7 +181969,7 @@ function requiredText(data, key) {
|
|
|
181076
181969
|
}
|
|
181077
181970
|
return value.trim();
|
|
181078
181971
|
}
|
|
181079
|
-
function
|
|
181972
|
+
function optionalText6(data, key) {
|
|
181080
181973
|
const value = data[key];
|
|
181081
181974
|
if (value === void 0 || value === null || value === "") return void 0;
|
|
181082
181975
|
if (typeof value !== "string") throw new Error("workflow frontmatter field " + key + " must be text");
|
|
@@ -181119,11 +182012,11 @@ function phaseFromValue(value, index) {
|
|
|
181119
182012
|
}
|
|
181120
182013
|
const data = value;
|
|
181121
182014
|
const title = requiredText(data, "title");
|
|
181122
|
-
const phaseId =
|
|
182015
|
+
const phaseId = optionalText6(data, "id") ?? slug(title) + "-" + (index + 1);
|
|
181123
182016
|
return {
|
|
181124
182017
|
id: phaseId,
|
|
181125
182018
|
title,
|
|
181126
|
-
instructions:
|
|
182019
|
+
instructions: optionalText6(data, "instructions") ?? "",
|
|
181127
182020
|
branches: optionalStringArray(data, "branches"),
|
|
181128
182021
|
expectedOutputs: optionalStringArray(data, "expectedOutputs"),
|
|
181129
182022
|
verificationGates: optionalStringArray(data, "verificationGates")
|
|
@@ -181158,7 +182051,7 @@ function phasesFromBody(body) {
|
|
|
181158
182051
|
}
|
|
181159
182052
|
function normalizeSourcePath(sourcePath) {
|
|
181160
182053
|
const normalized = sourcePath.replace(/\\/g, "/");
|
|
181161
|
-
if (!normalized.startsWith("workflows/") || !normalized.toLowerCase().endsWith(".md") || normalized.includes("../") ||
|
|
182054
|
+
if (!normalized.startsWith("workflows/") || !normalized.toLowerCase().endsWith(".md") || normalized.includes("../") || path21.posix.normalize(normalized) !== normalized) {
|
|
181162
182055
|
throw new Error("workflow source path must be a safe workflows/*.md path");
|
|
181163
182056
|
}
|
|
181164
182057
|
return normalized;
|
|
@@ -181232,7 +182125,7 @@ function parsedWorkflow(data, body, input) {
|
|
|
181232
182125
|
id: requiredText(data, "id"),
|
|
181233
182126
|
workspaceId: input.workspaceId,
|
|
181234
182127
|
title: requiredText(data, "title"),
|
|
181235
|
-
description:
|
|
182128
|
+
description: optionalText6(data, "description") ?? "",
|
|
181236
182129
|
status: optionalStatus(data),
|
|
181237
182130
|
version: optionalNumber(data, "version", 1),
|
|
181238
182131
|
taskLenses: optionalStringArray(data, "taskLenses"),
|
|
@@ -181251,9 +182144,9 @@ function parsedWorkflow(data, body, input) {
|
|
|
181251
182144
|
sourcePath: normalizeSourcePath(input.sourcePath),
|
|
181252
182145
|
sourceHash: "",
|
|
181253
182146
|
contentHash: input.contentHash,
|
|
181254
|
-
createdAt:
|
|
181255
|
-
updatedAt:
|
|
181256
|
-
...
|
|
182147
|
+
createdAt: optionalText6(data, "createdAt") ?? now2(),
|
|
182148
|
+
updatedAt: optionalText6(data, "updatedAt") ?? now2(),
|
|
182149
|
+
...optionalText6(data, "importedFrom") ? { importedFrom: optionalText6(data, "importedFrom") } : {}
|
|
181257
182150
|
};
|
|
181258
182151
|
if (candidate2.phases.length === 0) {
|
|
181259
182152
|
throw new Error("workflow must contain at least one phase or a non-empty body");
|
|
@@ -181307,7 +182200,7 @@ async function writeCanonicalWorkflow(input) {
|
|
|
181307
182200
|
const filePath = resolveKnowledgeWorkspaceFile(input.workspace, workflow.sourcePath);
|
|
181308
182201
|
const content = renderWorkflowMarkdown(workflow);
|
|
181309
182202
|
await withFileLock(paths.root, async () => {
|
|
181310
|
-
await
|
|
182203
|
+
await fs14.mkdir(path21.dirname(filePath), { recursive: true });
|
|
181311
182204
|
await atomicWriteFile(filePath, content);
|
|
181312
182205
|
});
|
|
181313
182206
|
const store2 = await storeFor2(input.workspace);
|
|
@@ -181316,13 +182209,13 @@ async function writeCanonicalWorkflow(input) {
|
|
|
181316
182209
|
async function markdownFiles2(directory) {
|
|
181317
182210
|
let entries;
|
|
181318
182211
|
try {
|
|
181319
|
-
entries = await
|
|
182212
|
+
entries = await fs14.readdir(directory, { withFileTypes: true });
|
|
181320
182213
|
} catch {
|
|
181321
182214
|
return [];
|
|
181322
182215
|
}
|
|
181323
182216
|
const files = [];
|
|
181324
182217
|
for (const entry of entries) {
|
|
181325
|
-
const absolutePath =
|
|
182218
|
+
const absolutePath = path21.join(directory, entry.name);
|
|
181326
182219
|
if (entry.isDirectory()) {
|
|
181327
182220
|
files.push(...await markdownFiles2(absolutePath));
|
|
181328
182221
|
} else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
|
|
@@ -181337,9 +182230,9 @@ async function syncCanonicalWorkflows(workspace) {
|
|
|
181337
182230
|
const workflows = [];
|
|
181338
182231
|
const errors2 = [];
|
|
181339
182232
|
for (const absolutePath of await markdownFiles2(paths.workflows)) {
|
|
181340
|
-
const sourcePath =
|
|
182233
|
+
const sourcePath = path21.relative(paths.root, absolutePath).split(path21.sep).join("/");
|
|
181341
182234
|
try {
|
|
181342
|
-
const raw = await
|
|
182235
|
+
const raw = await fs14.readFile(absolutePath, "utf8");
|
|
181343
182236
|
const workflow = parseWorkflowMarkdown(raw, { workspaceId: workspace.id, sourcePath });
|
|
181344
182237
|
workflows.push(store2.upsertWorkflow(workflow));
|
|
181345
182238
|
} catch (error40) {
|
|
@@ -181451,21 +182344,21 @@ function importedWorkflowSpec(input) {
|
|
|
181451
182344
|
return materializeWorkflow(spec);
|
|
181452
182345
|
}
|
|
181453
182346
|
async function importWindsurfWorkflows(input) {
|
|
181454
|
-
const sourceDirectory =
|
|
182347
|
+
const sourceDirectory = path21.join(path21.resolve(input.projectRoot), ".windsurf", "workflows");
|
|
181455
182348
|
const paths = getKnowledgeWorkspacePaths(input.workspace);
|
|
181456
182349
|
const imported = [];
|
|
181457
182350
|
const skipped = [];
|
|
181458
182351
|
let entries;
|
|
181459
182352
|
try {
|
|
181460
|
-
entries = await
|
|
182353
|
+
entries = await fs14.readdir(sourceDirectory, { withFileTypes: true });
|
|
181461
182354
|
} catch {
|
|
181462
182355
|
return { imported, skipped };
|
|
181463
182356
|
}
|
|
181464
182357
|
for (const entry of entries.filter((item) => item.isFile() && item.name.toLowerCase().endsWith(".md"))) {
|
|
181465
|
-
const originalPath =
|
|
181466
|
-
const sourcePath =
|
|
182358
|
+
const originalPath = path21.join(sourceDirectory, entry.name);
|
|
182359
|
+
const sourcePath = path21.relative(path21.resolve(input.projectRoot), originalPath).split(path21.sep).join("/");
|
|
181467
182360
|
try {
|
|
181468
|
-
const raw = await
|
|
182361
|
+
const raw = await fs14.readFile(originalPath, "utf8");
|
|
181469
182362
|
const workflow = importedWorkflowSpec({
|
|
181470
182363
|
workspace: input.workspace,
|
|
181471
182364
|
sourceName: entry.name,
|
|
@@ -181474,7 +182367,7 @@ async function importWindsurfWorkflows(input) {
|
|
|
181474
182367
|
});
|
|
181475
182368
|
const targetPath = resolveKnowledgeWorkspaceFile(input.workspace, workflow.sourcePath);
|
|
181476
182369
|
try {
|
|
181477
|
-
await
|
|
182370
|
+
await fs14.access(targetPath);
|
|
181478
182371
|
skipped.push({ sourcePath, reason: "canonical workflow already exists and was preserved" });
|
|
181479
182372
|
continue;
|
|
181480
182373
|
} catch {
|
|
@@ -181487,12 +182380,12 @@ async function importWindsurfWorkflows(input) {
|
|
|
181487
182380
|
});
|
|
181488
182381
|
}
|
|
181489
182382
|
}
|
|
181490
|
-
await
|
|
182383
|
+
await fs14.mkdir(paths.workflows, { recursive: true });
|
|
181491
182384
|
return { imported, skipped };
|
|
181492
182385
|
}
|
|
181493
182386
|
function isWithin2(root, candidate2) {
|
|
181494
|
-
const relative3 =
|
|
181495
|
-
return relative3 !== "" && relative3 !== ".." && !relative3.startsWith(".." +
|
|
182387
|
+
const relative3 = path21.relative(root, candidate2);
|
|
182388
|
+
return relative3 !== "" && relative3 !== ".." && !relative3.startsWith(".." + path21.sep) && !path21.isAbsolute(relative3);
|
|
181496
182389
|
}
|
|
181497
182390
|
function adapterRelativePath(workflow, agent) {
|
|
181498
182391
|
const name = "memorix-workflow-" + slug(workflow.id.replace(/^workflow:/, ""));
|
|
@@ -181578,15 +182471,15 @@ async function previewWorkflowAdapter(input) {
|
|
|
181578
182471
|
reason: "The canonical workflow does not declare compatibility with this agent."
|
|
181579
182472
|
};
|
|
181580
182473
|
}
|
|
181581
|
-
const projectRoot =
|
|
181582
|
-
const targetPath =
|
|
182474
|
+
const projectRoot = path21.resolve(input.projectRoot);
|
|
182475
|
+
const targetPath = path21.resolve(projectRoot, adapterRelativePath(input.workflow, input.agent));
|
|
181583
182476
|
if (!isWithin2(projectRoot, targetPath)) {
|
|
181584
182477
|
throw new Error("Workflow adapter target escapes the project root");
|
|
181585
182478
|
}
|
|
181586
182479
|
const content = adapterContent(input.workflow, input.agent);
|
|
181587
182480
|
let existing;
|
|
181588
182481
|
try {
|
|
181589
|
-
existing = await
|
|
182482
|
+
existing = await fs14.readFile(targetPath, "utf8");
|
|
181590
182483
|
} catch (error40) {
|
|
181591
182484
|
const code = error40 && typeof error40 === "object" && "code" in error40 ? error40.code : void 0;
|
|
181592
182485
|
if (code !== "ENOENT") throw error40;
|
|
@@ -181607,11 +182500,11 @@ async function applyWorkflowAdapter(input) {
|
|
|
181607
182500
|
if (initial.status === "unsupported" || initial.status === "conflict" || initial.status === "unchanged") {
|
|
181608
182501
|
return initial;
|
|
181609
182502
|
}
|
|
181610
|
-
const projectRoot =
|
|
182503
|
+
const projectRoot = path21.resolve(input.projectRoot);
|
|
181611
182504
|
return withFileLock(projectRoot, async () => {
|
|
181612
182505
|
const current = await previewWorkflowAdapter(input);
|
|
181613
182506
|
if (current.status !== "create" && current.status !== "update") return current;
|
|
181614
|
-
await
|
|
182507
|
+
await fs14.mkdir(path21.dirname(current.targetPath), { recursive: true });
|
|
181615
182508
|
await atomicWriteFile(current.targetPath, current.content);
|
|
181616
182509
|
return current;
|
|
181617
182510
|
});
|
|
@@ -181901,6 +182794,11 @@ function createProjectMaintenanceHandler(projectId, projectDir2, projectRoot, op
|
|
|
181901
182794
|
}
|
|
181902
182795
|
return { action: "complete" };
|
|
181903
182796
|
}
|
|
182797
|
+
if (job.kind === "long-term-maintenance") {
|
|
182798
|
+
const { maintainLongTermMemories: maintainLongTermMemories2 } = await Promise.resolve().then(() => (init_long_term(), long_term_exports));
|
|
182799
|
+
await maintainLongTermMemories2({ dataDir: projectDir2, projectId });
|
|
182800
|
+
return { action: "reschedule", delayMs: 24 * 60 * 60 * 1e3, resetAttempts: true };
|
|
182801
|
+
}
|
|
181904
182802
|
if (job.kind === "consolidation") {
|
|
181905
182803
|
const limit2 = consolidationBatchSize(job.payload);
|
|
181906
182804
|
const result2 = await runAutomaticConsolidation(projectId, projectDir2, {
|
|
@@ -182242,15 +183140,15 @@ __export(vector_backfill_runner_exports, {
|
|
|
182242
183140
|
});
|
|
182243
183141
|
import { spawn as spawn4 } from "child_process";
|
|
182244
183142
|
import { existsSync as existsSync12 } from "fs";
|
|
182245
|
-
import
|
|
183143
|
+
import path22 from "path";
|
|
182246
183144
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
182247
183145
|
function isNonEmptyString(value) {
|
|
182248
183146
|
return typeof value === "string" && value.trim().length > 0;
|
|
182249
183147
|
}
|
|
182250
183148
|
function resolveVectorBackfillRunnerPath(moduleUrl = import.meta.url) {
|
|
182251
|
-
const moduleDir =
|
|
182252
|
-
const distDir =
|
|
182253
|
-
return
|
|
183149
|
+
const moduleDir = path22.dirname(fileURLToPath6(moduleUrl));
|
|
183150
|
+
const distDir = path22.basename(moduleDir) === "cli" ? path22.dirname(moduleDir) : path22.basename(moduleDir) === "runtime" && path22.basename(path22.dirname(moduleDir)) === "src" ? path22.join(path22.dirname(path22.dirname(moduleDir)), "dist") : moduleDir;
|
|
183151
|
+
return path22.join(distDir, "vector-backfill-runner.js");
|
|
182254
183152
|
}
|
|
182255
183153
|
function parseVectorBackfillRequest(raw) {
|
|
182256
183154
|
let value;
|
|
@@ -182259,7 +183157,7 @@ function parseVectorBackfillRequest(raw) {
|
|
|
182259
183157
|
} catch {
|
|
182260
183158
|
throw new Error("Vector backfill runner received invalid JSON input");
|
|
182261
183159
|
}
|
|
182262
|
-
if (!value || typeof value !== "object" || !isNonEmptyString(value.projectId) || !isNonEmptyString(value.projectRoot) || !isNonEmptyString(value.dataDir) || !
|
|
183160
|
+
if (!value || typeof value !== "object" || !isNonEmptyString(value.projectId) || !isNonEmptyString(value.projectRoot) || !isNonEmptyString(value.dataDir) || !path22.isAbsolute(value.projectRoot) || !path22.isAbsolute(value.dataDir)) {
|
|
182263
183161
|
throw new Error("Vector backfill runner received an invalid request");
|
|
182264
183162
|
}
|
|
182265
183163
|
return {
|
|
@@ -183783,7 +184681,7 @@ async function searchObservations(options) {
|
|
|
183783
184681
|
const expandedEmbeddingQuery = quality === "thorough" && tier === "heavy" ? await maybeExpandSearchQuery(options.query) : options.query;
|
|
183784
184682
|
mark("queryExpansion");
|
|
183785
184683
|
const intentResult = quality === "fast" || !hasQuery ? null : detectQueryIntent(originalQuery);
|
|
183786
|
-
const requestLimit = projectIds ? (options.limit ?? 20) * 3 : options.limit ?? 20;
|
|
184684
|
+
const requestLimit = projectIds || options.surfacedIds && options.surfacedIds.length > 0 ? (options.limit ?? 20) * 3 : options.limit ?? 20;
|
|
183787
184685
|
const defaultBoost = {
|
|
183788
184686
|
title: 3,
|
|
183789
184687
|
entityName: 2,
|
|
@@ -184015,6 +184913,14 @@ async function searchObservations(options) {
|
|
|
184015
184913
|
});
|
|
184016
184914
|
intermediate.sort((a4, b4) => b4.score - a4.score);
|
|
184017
184915
|
}
|
|
184916
|
+
if (options.surfacedIds && options.surfacedIds.length > 0) {
|
|
184917
|
+
const SURFACED_PENALTY = 0.5;
|
|
184918
|
+
const surfaced = new Set(options.surfacedIds);
|
|
184919
|
+
intermediate = intermediate.map(
|
|
184920
|
+
(entry) => surfaced.has(entry.id) ? { ...entry, score: (entry.score ?? 0) * SURFACED_PENALTY } : entry
|
|
184921
|
+
);
|
|
184922
|
+
intermediate.sort((a4, b4) => (b4.score ?? 0) - (a4.score ?? 0));
|
|
184923
|
+
}
|
|
184018
184924
|
if (options.since) {
|
|
184019
184925
|
const sinceDate = new Date(options.since).getTime();
|
|
184020
184926
|
intermediate = intermediate.filter((e5) => new Date(e5.rawTime).getTime() >= sinceDate);
|
|
@@ -185021,9 +185927,9 @@ __export(team_store_exports, {
|
|
|
185021
185927
|
isTeamStoreInitialized: () => isTeamStoreInitialized,
|
|
185022
185928
|
resetTeamStore: () => resetTeamStore
|
|
185023
185929
|
});
|
|
185024
|
-
import { randomUUID as
|
|
185025
|
-
import
|
|
185026
|
-
import
|
|
185930
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
185931
|
+
import path23 from "path";
|
|
185932
|
+
import fs15 from "fs";
|
|
185027
185933
|
function getTeamStore() {
|
|
185028
185934
|
if (!_teamStore) {
|
|
185029
185935
|
throw new Error("[memorix] TeamStore not initialized \u2014 call initTeamStore() first");
|
|
@@ -185310,7 +186216,7 @@ var init_team_store = __esm({
|
|
|
185310
186216
|
* reactivate it (preserving agent_id). Otherwise create a new one.
|
|
185311
186217
|
*/
|
|
185312
186218
|
registerAgent(input) {
|
|
185313
|
-
const instanceId = input.instanceId ||
|
|
186219
|
+
const instanceId = input.instanceId || randomUUID14();
|
|
185314
186220
|
const now3 = Date.now();
|
|
185315
186221
|
const existing = this.stmtAgentFindByInstance.get(
|
|
185316
186222
|
input.projectId,
|
|
@@ -185336,7 +186242,7 @@ var init_team_store = __esm({
|
|
|
185336
186242
|
this.eventBus?.emit("agent:joined", { agentId: row2.agent_id, projectId: input.projectId, agentType: input.agentType });
|
|
185337
186243
|
return row2;
|
|
185338
186244
|
}
|
|
185339
|
-
const agentId =
|
|
186245
|
+
const agentId = randomUUID14();
|
|
185340
186246
|
this.stmtAgentUpsert.run({
|
|
185341
186247
|
agent_id: agentId,
|
|
185342
186248
|
project_id: input.projectId,
|
|
@@ -185438,7 +186344,7 @@ var init_team_store = __esm({
|
|
|
185438
186344
|
return { error: `Recipient agent '${input.recipientAgentId}' not found \u2014 cannot send to unknown agent` };
|
|
185439
186345
|
}
|
|
185440
186346
|
}
|
|
185441
|
-
const id =
|
|
186347
|
+
const id = randomUUID14();
|
|
185442
186348
|
const now3 = Date.now();
|
|
185443
186349
|
const row = {
|
|
185444
186350
|
id,
|
|
@@ -185488,7 +186394,7 @@ var init_team_store = __esm({
|
|
|
185488
186394
|
// Task Operations (with atomic claim semantics)
|
|
185489
186395
|
// ═══════════════════════════════════════════════════════════════════
|
|
185490
186396
|
createTask(input) {
|
|
185491
|
-
const taskId =
|
|
186397
|
+
const taskId = randomUUID14();
|
|
185492
186398
|
const now3 = Date.now();
|
|
185493
186399
|
const row = {
|
|
185494
186400
|
task_id: taskId,
|
|
@@ -185713,19 +186619,19 @@ var init_team_store = __esm({
|
|
|
185713
186619
|
const agentCount = this.db.prepare(`SELECT COUNT(*) AS cnt FROM team_agents`).get();
|
|
185714
186620
|
if (agentCount.cnt > 0) return;
|
|
185715
186621
|
const candidates = [
|
|
185716
|
-
|
|
185717
|
-
|
|
186622
|
+
path23.join(this.dataDir, "team-state.json"),
|
|
186623
|
+
path23.join(this.dataDir, "..", "team-state.json")
|
|
185718
186624
|
];
|
|
185719
186625
|
let jsonPath = null;
|
|
185720
186626
|
for (const p3 of candidates) {
|
|
185721
|
-
if (
|
|
186627
|
+
if (fs15.existsSync(p3)) {
|
|
185722
186628
|
jsonPath = p3;
|
|
185723
186629
|
break;
|
|
185724
186630
|
}
|
|
185725
186631
|
}
|
|
185726
186632
|
if (!jsonPath) return;
|
|
185727
186633
|
try {
|
|
185728
|
-
const raw =
|
|
186634
|
+
const raw = fs15.readFileSync(jsonPath, "utf-8");
|
|
185729
186635
|
const snap = JSON.parse(raw);
|
|
185730
186636
|
if (snap.version !== 1) return;
|
|
185731
186637
|
console.error(`[memorix] Migrating team-state.json to SQLite...`);
|
|
@@ -185760,7 +186666,7 @@ var init_team_store = __esm({
|
|
|
185760
186666
|
for (const [agentId, msgs] of Object.entries(snap.messages.inboxes)) {
|
|
185761
186667
|
for (const msg of msgs) {
|
|
185762
186668
|
this.stmtMsgInsert.run({
|
|
185763
|
-
id: msg.id ??
|
|
186669
|
+
id: msg.id ?? randomUUID14(),
|
|
185764
186670
|
project_id: "migrated",
|
|
185765
186671
|
sender_agent_id: msg.from ?? "unknown",
|
|
185766
186672
|
recipient_agent_id: msg.to === "__broadcast__" ? null : msg.to ?? agentId,
|
|
@@ -185819,7 +186725,7 @@ var init_team_store = __esm({
|
|
|
185819
186725
|
`[memorix] Team migration complete: ${agentsMigrated} agents, ${messagesMigrated} messages, ${tasksMigrated} tasks, ${locksMigrated} locks.`
|
|
185820
186726
|
);
|
|
185821
186727
|
try {
|
|
185822
|
-
|
|
186728
|
+
fs15.renameSync(jsonPath, jsonPath + ".migrated");
|
|
185823
186729
|
} catch {
|
|
185824
186730
|
}
|
|
185825
186731
|
} catch (err) {
|
|
@@ -185854,7 +186760,7 @@ var init_team_store = __esm({
|
|
|
185854
186760
|
* Uses projectId derived from the dataDir path.
|
|
185855
186761
|
*/
|
|
185856
186762
|
seedDefaultRoles(dataDir) {
|
|
185857
|
-
const projectId =
|
|
186763
|
+
const projectId = path23.basename(path23.resolve(dataDir, ".."));
|
|
185858
186764
|
const count3 = this.stmtRoleCountByProject.get(projectId).cnt;
|
|
185859
186765
|
if (count3 > 0) return;
|
|
185860
186766
|
const now3 = Date.now();
|
|
@@ -185948,10 +186854,10 @@ var init_team_store = __esm({
|
|
|
185948
186854
|
});
|
|
185949
186855
|
|
|
185950
186856
|
// src/cli/identity.ts
|
|
185951
|
-
import { promises as
|
|
185952
|
-
import
|
|
186857
|
+
import { promises as fs16 } from "fs";
|
|
186858
|
+
import path24 from "path";
|
|
185953
186859
|
function identityPath(dataDir) {
|
|
185954
|
-
return
|
|
186860
|
+
return path24.join(dataDir, "cli-identity.json");
|
|
185955
186861
|
}
|
|
185956
186862
|
function isCliIdentity(value) {
|
|
185957
186863
|
if (!value || typeof value !== "object") return false;
|
|
@@ -185960,18 +186866,18 @@ function isCliIdentity(value) {
|
|
|
185960
186866
|
}
|
|
185961
186867
|
async function loadCliIdentity(dataDir, projectId) {
|
|
185962
186868
|
try {
|
|
185963
|
-
const parsed = JSON.parse(await
|
|
186869
|
+
const parsed = JSON.parse(await fs16.readFile(identityPath(dataDir), "utf8"));
|
|
185964
186870
|
return isCliIdentity(parsed) && parsed.projectId === projectId ? parsed : null;
|
|
185965
186871
|
} catch {
|
|
185966
186872
|
return null;
|
|
185967
186873
|
}
|
|
185968
186874
|
}
|
|
185969
186875
|
async function saveCliIdentity(dataDir, identity) {
|
|
185970
|
-
await
|
|
186876
|
+
await fs16.writeFile(identityPath(dataDir), `${JSON.stringify(identity, null, 2)}
|
|
185971
186877
|
`, "utf8");
|
|
185972
186878
|
}
|
|
185973
186879
|
async function clearCliIdentity(dataDir) {
|
|
185974
|
-
await
|
|
186880
|
+
await fs16.rm(identityPath(dataDir), { force: true });
|
|
185975
186881
|
}
|
|
185976
186882
|
async function resolveCliIdentity(options) {
|
|
185977
186883
|
const stored = await loadCliIdentity(options.dataDir, options.project.id);
|
|
@@ -187321,8 +188227,8 @@ __export(session_store_exports, {
|
|
|
187321
188227
|
initSessionStore: () => initSessionStore,
|
|
187322
188228
|
resetSessionStore: () => resetSessionStore
|
|
187323
188229
|
});
|
|
187324
|
-
import
|
|
187325
|
-
import
|
|
188230
|
+
import path25 from "path";
|
|
188231
|
+
import fs17 from "fs";
|
|
187326
188232
|
function sessionToRow(session) {
|
|
187327
188233
|
return {
|
|
187328
188234
|
id: session.id,
|
|
@@ -187408,10 +188314,10 @@ var init_session_store = __esm({
|
|
|
187408
188314
|
async migrateFromJsonIfNeeded() {
|
|
187409
188315
|
const count3 = this.db.prepare(`SELECT COUNT(*) AS cnt FROM sessions`).get();
|
|
187410
188316
|
if (count3.cnt > 0) return;
|
|
187411
|
-
const jsonPath =
|
|
187412
|
-
if (!
|
|
188317
|
+
const jsonPath = path25.join(this.dataDir, "sessions.json");
|
|
188318
|
+
if (!fs17.existsSync(jsonPath)) return;
|
|
187413
188319
|
try {
|
|
187414
|
-
const raw =
|
|
188320
|
+
const raw = fs17.readFileSync(jsonPath, "utf-8");
|
|
187415
188321
|
const sessions = JSON.parse(raw);
|
|
187416
188322
|
if (!Array.isArray(sessions) || sessions.length === 0) return;
|
|
187417
188323
|
console.error(`[memorix] Migrating ${sessions.length} sessions from JSON to SQLite...`);
|
|
@@ -187753,827 +188659,6 @@ var init_operator_shared = __esm({
|
|
|
187753
188659
|
}
|
|
187754
188660
|
});
|
|
187755
188661
|
|
|
187756
|
-
// src/memory/owner.ts
|
|
187757
|
-
var owner_exports = {};
|
|
187758
|
-
__export(owner_exports, {
|
|
187759
|
-
resolveLocalMemoryOwner: () => resolveLocalMemoryOwner
|
|
187760
|
-
});
|
|
187761
|
-
import { randomUUID as randomUUID12 } from "crypto";
|
|
187762
|
-
import { promises as fs17 } from "fs";
|
|
187763
|
-
import path25 from "path";
|
|
187764
|
-
function ownerPath(dataDir) {
|
|
187765
|
-
const resolved = path25.resolve(dataDir);
|
|
187766
|
-
const home = path25.basename(resolved).toLocaleLowerCase("en-US") === "data" ? path25.dirname(resolved) : resolved;
|
|
187767
|
-
return path25.join(home, "memorix-user.json");
|
|
187768
|
-
}
|
|
187769
|
-
function normalizedOwnerId(value) {
|
|
187770
|
-
const trimmed = value?.trim();
|
|
187771
|
-
return trimmed && ID_PATTERN.test(trimmed) ? trimmed : void 0;
|
|
187772
|
-
}
|
|
187773
|
-
async function readOwnerFile(filePath) {
|
|
187774
|
-
try {
|
|
187775
|
-
const value = JSON.parse(await fs17.readFile(filePath, "utf8"));
|
|
187776
|
-
const id = typeof value.id === "string" ? normalizedOwnerId(value.id) : void 0;
|
|
187777
|
-
return id ? { id, source: "local-file" } : void 0;
|
|
187778
|
-
} catch {
|
|
187779
|
-
return void 0;
|
|
187780
|
-
}
|
|
187781
|
-
}
|
|
187782
|
-
async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
187783
|
-
const configured = normalizedOwnerId(process.env.MEMORIX_USER_ID);
|
|
187784
|
-
if (configured) return { id: configured, source: "environment" };
|
|
187785
|
-
const filePath = ownerPath(dataDir);
|
|
187786
|
-
const existing = await readOwnerFile(filePath);
|
|
187787
|
-
if (existing || !options.create) return existing;
|
|
187788
|
-
await fs17.mkdir(path25.dirname(filePath), { recursive: true });
|
|
187789
|
-
const created = {
|
|
187790
|
-
version: 1,
|
|
187791
|
-
id: "local-" + randomUUID12(),
|
|
187792
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
187793
|
-
};
|
|
187794
|
-
try {
|
|
187795
|
-
await fs17.writeFile(filePath, JSON.stringify(created, null, 2) + "\n", { encoding: "utf8", flag: "wx" });
|
|
187796
|
-
return { id: created.id, source: "local-file" };
|
|
187797
|
-
} catch (error40) {
|
|
187798
|
-
if (error40?.code !== "EEXIST") throw error40;
|
|
187799
|
-
const concurrent = await readOwnerFile(filePath);
|
|
187800
|
-
if (concurrent) return concurrent;
|
|
187801
|
-
throw new Error("Memorix could not establish a valid local memory owner identity.");
|
|
187802
|
-
}
|
|
187803
|
-
}
|
|
187804
|
-
var ID_PATTERN;
|
|
187805
|
-
var init_owner = __esm({
|
|
187806
|
-
"src/memory/owner.ts"() {
|
|
187807
|
-
"use strict";
|
|
187808
|
-
init_esm_shims();
|
|
187809
|
-
ID_PATTERN = /^[A-Za-z0-9:_-]{3,160}$/;
|
|
187810
|
-
}
|
|
187811
|
-
});
|
|
187812
|
-
|
|
187813
|
-
// src/memory/long-term-store.ts
|
|
187814
|
-
import { randomUUID as randomUUID13 } from "crypto";
|
|
187815
|
-
function optionalText6(value) {
|
|
187816
|
-
return typeof value === "string" && value.trim() ? value : void 0;
|
|
187817
|
-
}
|
|
187818
|
-
function arrayValue2(value) {
|
|
187819
|
-
if (typeof value !== "string" || !value) return [];
|
|
187820
|
-
try {
|
|
187821
|
-
const parsed = JSON.parse(value);
|
|
187822
|
-
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
|
|
187823
|
-
} catch {
|
|
187824
|
-
return [];
|
|
187825
|
-
}
|
|
187826
|
-
}
|
|
187827
|
-
function rowToMemory(row) {
|
|
187828
|
-
return {
|
|
187829
|
-
id: row.id,
|
|
187830
|
-
originProjectId: row.originProjectId,
|
|
187831
|
-
ownerId: row.ownerId,
|
|
187832
|
-
scope: row.scope,
|
|
187833
|
-
kind: row.kind,
|
|
187834
|
-
state: row.state,
|
|
187835
|
-
portability: row.portability,
|
|
187836
|
-
title: row.title,
|
|
187837
|
-
content: row.content,
|
|
187838
|
-
facts: arrayValue2(row.factsJson),
|
|
187839
|
-
tags: arrayValue2(row.tagsJson),
|
|
187840
|
-
...optionalText6(row.applicability) ? { applicability: row.applicability } : {},
|
|
187841
|
-
origin: row.origin,
|
|
187842
|
-
createdAt: row.createdAt,
|
|
187843
|
-
updatedAt: row.updatedAt,
|
|
187844
|
-
...optionalText6(row.qualifiedAt) ? { qualifiedAt: row.qualifiedAt } : {},
|
|
187845
|
-
...optionalText6(row.approvedAt) ? { approvedAt: row.approvedAt } : {},
|
|
187846
|
-
...optionalText6(row.archivedAt) ? { archivedAt: row.archivedAt } : {},
|
|
187847
|
-
...optionalText6(row.supersededBy) ? { supersededBy: row.supersededBy } : {},
|
|
187848
|
-
...optionalText6(row.lastValidatedAt) ? { lastValidatedAt: row.lastValidatedAt } : {},
|
|
187849
|
-
accessCount: Number(row.accessCount ?? 0),
|
|
187850
|
-
...optionalText6(row.lastAccessedAt) ? { lastAccessedAt: row.lastAccessedAt } : {}
|
|
187851
|
-
};
|
|
187852
|
-
}
|
|
187853
|
-
function rowToEvidence2(row) {
|
|
187854
|
-
return {
|
|
187855
|
-
id: row.id,
|
|
187856
|
-
memoryId: row.memoryId,
|
|
187857
|
-
kind: row.kind,
|
|
187858
|
-
referenceId: row.referenceId,
|
|
187859
|
-
relation: row.relation,
|
|
187860
|
-
...optionalText6(row.locator) ? { locator: row.locator } : {},
|
|
187861
|
-
...optionalText6(row.capturedHash) ? { capturedHash: row.capturedHash } : {},
|
|
187862
|
-
createdAt: row.createdAt
|
|
187863
|
-
};
|
|
187864
|
-
}
|
|
187865
|
-
function rowToEvent2(row) {
|
|
187866
|
-
return {
|
|
187867
|
-
id: row.id,
|
|
187868
|
-
memoryId: row.memoryId,
|
|
187869
|
-
kind: row.kind,
|
|
187870
|
-
...optionalText6(row.fromState) ? { fromState: row.fromState } : {},
|
|
187871
|
-
...optionalText6(row.toState) ? { toState: row.toState } : {},
|
|
187872
|
-
...optionalText6(row.detail) ? { detail: row.detail } : {},
|
|
187873
|
-
createdAt: row.createdAt
|
|
187874
|
-
};
|
|
187875
|
-
}
|
|
187876
|
-
var LongTermMemoryStore;
|
|
187877
|
-
var init_long_term_store = __esm({
|
|
187878
|
-
"src/memory/long-term-store.ts"() {
|
|
187879
|
-
"use strict";
|
|
187880
|
-
init_esm_shims();
|
|
187881
|
-
init_sqlite_db();
|
|
187882
|
-
LongTermMemoryStore = class {
|
|
187883
|
-
db = null;
|
|
187884
|
-
async init(dataDir) {
|
|
187885
|
-
this.db = getDatabase(dataDir);
|
|
187886
|
-
}
|
|
187887
|
-
transaction(fn2) {
|
|
187888
|
-
return this.db.transaction(fn2)();
|
|
187889
|
-
}
|
|
187890
|
-
get(id) {
|
|
187891
|
-
const row = this.db.prepare("SELECT * FROM long_term_memories WHERE id = ?").get(id);
|
|
187892
|
-
return row ? rowToMemory(row) : void 0;
|
|
187893
|
-
}
|
|
187894
|
-
list(options = {}) {
|
|
187895
|
-
const limit2 = Math.max(1, Math.min(1e3, Math.floor(options.limit ?? 500)));
|
|
187896
|
-
const clauses = [];
|
|
187897
|
-
const params = [];
|
|
187898
|
-
if (options.ownerId) {
|
|
187899
|
-
clauses.push("ownerId = ?");
|
|
187900
|
-
params.push(options.ownerId);
|
|
187901
|
-
}
|
|
187902
|
-
if (options.originProjectId) {
|
|
187903
|
-
clauses.push("originProjectId = ?");
|
|
187904
|
-
params.push(options.originProjectId);
|
|
187905
|
-
}
|
|
187906
|
-
const where = clauses.length ? " WHERE " + clauses.join(" AND ") : "";
|
|
187907
|
-
const rows = this.db.prepare(
|
|
187908
|
-
"SELECT * FROM long_term_memories" + where + " ORDER BY updatedAt DESC, id LIMIT ?"
|
|
187909
|
-
).all(...params, limit2);
|
|
187910
|
-
return rows.map(rowToMemory);
|
|
187911
|
-
}
|
|
187912
|
-
insert(memory) {
|
|
187913
|
-
this.db.prepare(`
|
|
187914
|
-
INSERT INTO long_term_memories (
|
|
187915
|
-
id, originProjectId, ownerId, scope, kind, state, portability,
|
|
187916
|
-
title, content, factsJson, tagsJson, applicability, origin,
|
|
187917
|
-
createdAt, updatedAt, qualifiedAt, approvedAt, archivedAt,
|
|
187918
|
-
supersededBy, lastValidatedAt, accessCount, lastAccessedAt
|
|
187919
|
-
) VALUES (
|
|
187920
|
-
@id, @originProjectId, @ownerId, @scope, @kind, @state, @portability,
|
|
187921
|
-
@title, @content, @factsJson, @tagsJson, @applicability, @origin,
|
|
187922
|
-
@createdAt, @updatedAt, @qualifiedAt, @approvedAt, @archivedAt,
|
|
187923
|
-
@supersededBy, @lastValidatedAt, @accessCount, @lastAccessedAt
|
|
187924
|
-
)
|
|
187925
|
-
`).run({
|
|
187926
|
-
...memory,
|
|
187927
|
-
factsJson: JSON.stringify(memory.facts),
|
|
187928
|
-
tagsJson: JSON.stringify(memory.tags),
|
|
187929
|
-
applicability: memory.applicability ?? null,
|
|
187930
|
-
qualifiedAt: memory.qualifiedAt ?? null,
|
|
187931
|
-
approvedAt: memory.approvedAt ?? null,
|
|
187932
|
-
archivedAt: memory.archivedAt ?? null,
|
|
187933
|
-
supersededBy: memory.supersededBy ?? null,
|
|
187934
|
-
lastValidatedAt: memory.lastValidatedAt ?? null,
|
|
187935
|
-
lastAccessedAt: memory.lastAccessedAt ?? null
|
|
187936
|
-
});
|
|
187937
|
-
}
|
|
187938
|
-
update(memory) {
|
|
187939
|
-
this.db.prepare(`
|
|
187940
|
-
UPDATE long_term_memories SET
|
|
187941
|
-
scope = @scope,
|
|
187942
|
-
kind = @kind,
|
|
187943
|
-
state = @state,
|
|
187944
|
-
portability = @portability,
|
|
187945
|
-
title = @title,
|
|
187946
|
-
content = @content,
|
|
187947
|
-
factsJson = @factsJson,
|
|
187948
|
-
tagsJson = @tagsJson,
|
|
187949
|
-
applicability = @applicability,
|
|
187950
|
-
updatedAt = @updatedAt,
|
|
187951
|
-
qualifiedAt = @qualifiedAt,
|
|
187952
|
-
approvedAt = @approvedAt,
|
|
187953
|
-
archivedAt = @archivedAt,
|
|
187954
|
-
supersededBy = @supersededBy,
|
|
187955
|
-
lastValidatedAt = @lastValidatedAt,
|
|
187956
|
-
accessCount = @accessCount,
|
|
187957
|
-
lastAccessedAt = @lastAccessedAt
|
|
187958
|
-
WHERE id = @id
|
|
187959
|
-
`).run({
|
|
187960
|
-
...memory,
|
|
187961
|
-
factsJson: JSON.stringify(memory.facts),
|
|
187962
|
-
tagsJson: JSON.stringify(memory.tags),
|
|
187963
|
-
applicability: memory.applicability ?? null,
|
|
187964
|
-
qualifiedAt: memory.qualifiedAt ?? null,
|
|
187965
|
-
approvedAt: memory.approvedAt ?? null,
|
|
187966
|
-
archivedAt: memory.archivedAt ?? null,
|
|
187967
|
-
supersededBy: memory.supersededBy ?? null,
|
|
187968
|
-
lastValidatedAt: memory.lastValidatedAt ?? null,
|
|
187969
|
-
lastAccessedAt: memory.lastAccessedAt ?? null
|
|
187970
|
-
});
|
|
187971
|
-
}
|
|
187972
|
-
insertEvidence(input) {
|
|
187973
|
-
const evidence = {
|
|
187974
|
-
id: randomUUID13(),
|
|
187975
|
-
...input,
|
|
187976
|
-
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
187977
|
-
};
|
|
187978
|
-
this.db.prepare(`
|
|
187979
|
-
INSERT INTO long_term_memory_evidence (
|
|
187980
|
-
id, memoryId, kind, referenceId, relation, locator, capturedHash, createdAt
|
|
187981
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
187982
|
-
`).run(
|
|
187983
|
-
evidence.id,
|
|
187984
|
-
evidence.memoryId,
|
|
187985
|
-
evidence.kind,
|
|
187986
|
-
evidence.referenceId,
|
|
187987
|
-
evidence.relation,
|
|
187988
|
-
evidence.locator ?? null,
|
|
187989
|
-
evidence.capturedHash ?? null,
|
|
187990
|
-
evidence.createdAt
|
|
187991
|
-
);
|
|
187992
|
-
return evidence;
|
|
187993
|
-
}
|
|
187994
|
-
listEvidence(memoryId) {
|
|
187995
|
-
return this.db.prepare(`
|
|
187996
|
-
SELECT * FROM long_term_memory_evidence WHERE memoryId = ? ORDER BY createdAt ASC, id
|
|
187997
|
-
`).all(memoryId).map(rowToEvidence2);
|
|
187998
|
-
}
|
|
187999
|
-
recordEvent(input) {
|
|
188000
|
-
const event = {
|
|
188001
|
-
id: randomUUID13(),
|
|
188002
|
-
...input,
|
|
188003
|
-
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
188004
|
-
};
|
|
188005
|
-
this.db.prepare(`
|
|
188006
|
-
INSERT INTO long_term_memory_events (id, memoryId, kind, fromState, toState, detail, createdAt)
|
|
188007
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
188008
|
-
`).run(
|
|
188009
|
-
event.id,
|
|
188010
|
-
event.memoryId,
|
|
188011
|
-
event.kind,
|
|
188012
|
-
event.fromState ?? null,
|
|
188013
|
-
event.toState ?? null,
|
|
188014
|
-
event.detail ?? null,
|
|
188015
|
-
event.createdAt
|
|
188016
|
-
);
|
|
188017
|
-
return event;
|
|
188018
|
-
}
|
|
188019
|
-
listEvents(memoryId) {
|
|
188020
|
-
return this.db.prepare(`
|
|
188021
|
-
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
188022
|
-
`).all(memoryId).map(rowToEvent2);
|
|
188023
|
-
}
|
|
188024
|
-
markAccess(ids, at2 = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
188025
|
-
const unique3 = [...new Set(ids.filter(Boolean))];
|
|
188026
|
-
if (unique3.length === 0) return;
|
|
188027
|
-
const statement = this.db.prepare(`
|
|
188028
|
-
UPDATE long_term_memories
|
|
188029
|
-
SET accessCount = accessCount + 1, lastAccessedAt = ?
|
|
188030
|
-
WHERE id = ?
|
|
188031
|
-
`);
|
|
188032
|
-
this.db.transaction(() => {
|
|
188033
|
-
for (const id of unique3) statement.run(at2, id);
|
|
188034
|
-
})();
|
|
188035
|
-
}
|
|
188036
|
-
};
|
|
188037
|
-
}
|
|
188038
|
-
});
|
|
188039
|
-
|
|
188040
|
-
// src/memory/long-term-types.ts
|
|
188041
|
-
var LONG_TERM_MEMORY_KINDS, LONG_TERM_MEMORY_SCOPES, LONG_TERM_MEMORY_PORTABILITIES, LONG_TERM_MEMORY_EVIDENCE_KINDS, LONG_TERM_MEMORY_EVIDENCE_RELATIONS;
|
|
188042
|
-
var init_long_term_types = __esm({
|
|
188043
|
-
"src/memory/long-term-types.ts"() {
|
|
188044
|
-
"use strict";
|
|
188045
|
-
init_esm_shims();
|
|
188046
|
-
LONG_TERM_MEMORY_KINDS = ["episodic", "semantic", "procedural"];
|
|
188047
|
-
LONG_TERM_MEMORY_SCOPES = ["project", "user", "team"];
|
|
188048
|
-
LONG_TERM_MEMORY_PORTABILITIES = ["project-bound", "portable"];
|
|
188049
|
-
LONG_TERM_MEMORY_EVIDENCE_KINDS = [
|
|
188050
|
-
"observation",
|
|
188051
|
-
"claim",
|
|
188052
|
-
"workflow",
|
|
188053
|
-
"session",
|
|
188054
|
-
"checkpoint",
|
|
188055
|
-
"git",
|
|
188056
|
-
"code",
|
|
188057
|
-
"test",
|
|
188058
|
-
"run",
|
|
188059
|
-
"document",
|
|
188060
|
-
"manual",
|
|
188061
|
-
"user"
|
|
188062
|
-
];
|
|
188063
|
-
LONG_TERM_MEMORY_EVIDENCE_RELATIONS = [
|
|
188064
|
-
"supports",
|
|
188065
|
-
"verifies",
|
|
188066
|
-
"derives",
|
|
188067
|
-
"user-confirmed"
|
|
188068
|
-
];
|
|
188069
|
-
}
|
|
188070
|
-
});
|
|
188071
|
-
|
|
188072
|
-
// src/memory/long-term.ts
|
|
188073
|
-
var long_term_exports = {};
|
|
188074
|
-
__export(long_term_exports, {
|
|
188075
|
-
approveLongTermMemory: () => approveLongTermMemory,
|
|
188076
|
-
archiveLongTermMemory: () => archiveLongTermMemory,
|
|
188077
|
-
canReadLongTermMemory: () => canReadLongTermMemory,
|
|
188078
|
-
createLongTermMemoryCandidate: () => createLongTermMemoryCandidate,
|
|
188079
|
-
createManualLongTermMemory: () => createManualLongTermMemory,
|
|
188080
|
-
getLongTermMemoryDetail: () => getLongTermMemoryDetail,
|
|
188081
|
-
isEligibleLongTermMemory: () => isEligibleLongTermMemory,
|
|
188082
|
-
listLongTermMemories: () => listLongTermMemories,
|
|
188083
|
-
promoteObservationToLongTermMemory: () => promoteObservationToLongTermMemory,
|
|
188084
|
-
qualifyLongTermMemory: () => qualifyLongTermMemory,
|
|
188085
|
-
renderLongTermMemorySummary: () => renderLongTermMemorySummary,
|
|
188086
|
-
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
188087
|
-
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
188088
|
-
});
|
|
188089
|
-
import { randomUUID as randomUUID14 } from "crypto";
|
|
188090
|
-
function isOneOf(value, values) {
|
|
188091
|
-
return typeof value === "string" && values.includes(value);
|
|
188092
|
-
}
|
|
188093
|
-
function compactText2(value, field, max = MAX_TEXT_LENGTH) {
|
|
188094
|
-
if (typeof value !== "string") throw new Error("Long-term memory " + field + " must be text.");
|
|
188095
|
-
const safe = sanitizeCredentials(value).replace(/\s+/g, " ").trim();
|
|
188096
|
-
if (!safe) throw new Error("Long-term memory " + field + " is required.");
|
|
188097
|
-
if (safe.length > max) throw new Error("Long-term memory " + field + " is too long.");
|
|
188098
|
-
return safe;
|
|
188099
|
-
}
|
|
188100
|
-
function compactList(values, field) {
|
|
188101
|
-
if (!values) return [];
|
|
188102
|
-
if (!Array.isArray(values)) throw new Error("Long-term memory " + field + " must be an array.");
|
|
188103
|
-
return [...new Set(values.filter((value) => typeof value === "string").map((value) => compactText2(value, field, 500)))].slice(0, MAX_LIST_ITEMS);
|
|
188104
|
-
}
|
|
188105
|
-
function normalizeEvidence(input) {
|
|
188106
|
-
if (!Array.isArray(input) || input.length === 0) {
|
|
188107
|
-
throw new Error("A long-term memory requires at least one source evidence reference.");
|
|
188108
|
-
}
|
|
188109
|
-
return input.map((evidence) => {
|
|
188110
|
-
if (!evidence || !isOneOf(evidence.kind, LONG_TERM_MEMORY_EVIDENCE_KINDS)) {
|
|
188111
|
-
throw new Error("Long-term memory evidence kind is invalid.");
|
|
188112
|
-
}
|
|
188113
|
-
if (!isOneOf(evidence.relation, LONG_TERM_MEMORY_EVIDENCE_RELATIONS)) {
|
|
188114
|
-
throw new Error("Long-term memory evidence relation is invalid.");
|
|
188115
|
-
}
|
|
188116
|
-
return {
|
|
188117
|
-
kind: evidence.kind,
|
|
188118
|
-
referenceId: compactText2(evidence.referenceId, "evidence reference", 1e3),
|
|
188119
|
-
relation: evidence.relation,
|
|
188120
|
-
...evidence.locator ? { locator: compactText2(evidence.locator, "evidence locator", 1e3) } : {},
|
|
188121
|
-
...evidence.capturedHash ? { capturedHash: compactText2(evidence.capturedHash, "evidence hash", 1e3) } : {}
|
|
188122
|
-
};
|
|
188123
|
-
});
|
|
188124
|
-
}
|
|
188125
|
-
function assertScope(scope) {
|
|
188126
|
-
if (!isOneOf(scope, LONG_TERM_MEMORY_SCOPES)) throw new Error("Long-term memory scope is invalid.");
|
|
188127
|
-
}
|
|
188128
|
-
function assertKind(kind) {
|
|
188129
|
-
if (!isOneOf(kind, LONG_TERM_MEMORY_KINDS)) throw new Error("Long-term memory kind is invalid.");
|
|
188130
|
-
}
|
|
188131
|
-
function assertPortability(value) {
|
|
188132
|
-
if (!isOneOf(value, LONG_TERM_MEMORY_PORTABILITIES)) {
|
|
188133
|
-
throw new Error("Long-term memory portability is invalid.");
|
|
188134
|
-
}
|
|
188135
|
-
}
|
|
188136
|
-
function assertPortableEvidence(scope, portability, evidence) {
|
|
188137
|
-
if (portability !== "portable") return;
|
|
188138
|
-
if (scope !== "user") {
|
|
188139
|
-
throw new Error("Only user-scoped long-term memories may be portable across projects.");
|
|
188140
|
-
}
|
|
188141
|
-
if (evidence.some((item) => !PORTABLE_EVIDENCE_KINDS.has(item.kind))) {
|
|
188142
|
-
throw new Error("Portable user memory may only use manual or user-confirmed evidence; project code, Git, observation, test, session, claim, and workflow evidence must remain project-bound.");
|
|
188143
|
-
}
|
|
188144
|
-
}
|
|
188145
|
-
function requireTeamReader(scope, reader) {
|
|
188146
|
-
if (scope === "team" && reader?.isTeamMember !== true) {
|
|
188147
|
-
throw new Error("Team long-term memory requires an explicit active team identity for this project.");
|
|
188148
|
-
}
|
|
188149
|
-
}
|
|
188150
|
-
function matchesScope(memory, reader) {
|
|
188151
|
-
if (memory.scope === "project") return memory.originProjectId === reader.projectId;
|
|
188152
|
-
if (memory.scope === "team") {
|
|
188153
|
-
return memory.originProjectId === reader.projectId && reader.isTeamMember === true;
|
|
188154
|
-
}
|
|
188155
|
-
if (!reader.ownerId || memory.ownerId !== reader.ownerId) return false;
|
|
188156
|
-
return memory.portability === "portable" || memory.originProjectId === reader.projectId;
|
|
188157
|
-
}
|
|
188158
|
-
function canReadLongTermMemory(memory, reader) {
|
|
188159
|
-
return matchesScope(memory, reader);
|
|
188160
|
-
}
|
|
188161
|
-
function isEligibleLongTermMemory(memory) {
|
|
188162
|
-
return memory.state === "qualified" || memory.state === "approved";
|
|
188163
|
-
}
|
|
188164
|
-
function taskTerms(task) {
|
|
188165
|
-
const matches = task.toLocaleLowerCase("en-US").match(/[\p{L}\p{N}_./:-]+/gu) ?? [];
|
|
188166
|
-
return [...new Set(matches.filter((term) => term.length > 1 && !STOP_TERMS.has(term)))].slice(0, 16);
|
|
188167
|
-
}
|
|
188168
|
-
function kindFitScore(kind, task) {
|
|
188169
|
-
const normalized = task.toLocaleLowerCase("en-US");
|
|
188170
|
-
const hints = {
|
|
188171
|
-
episodic: ["resume", "continue", "handoff", "previous", "session", "\u63A5\u624B", "\u7EE7\u7EED", "\u4EA4\u63A5", "\u4E0A\u6B21", "\u4F1A\u8BDD"],
|
|
188172
|
-
semantic: ["why", "what", "architecture", "design", "decision", "reason", "\u4E3A\u4EC0\u4E48", "\u662F\u4EC0\u4E48", "\u67B6\u6784", "\u8BBE\u8BA1", "\u51B3\u7B56", "\u539F\u56E0"],
|
|
188173
|
-
procedural: ["how", "steps", "procedure", "run", "release", "publish", "verify", "implement", "\u6D41\u7A0B", "\u6B65\u9AA4", "\u53D1\u5E03", "\u9A8C\u8BC1", "\u4FEE\u590D", "\u5B9E\u73B0"]
|
|
188174
|
-
};
|
|
188175
|
-
return hints[kind].some((hint) => normalized.includes(hint)) ? 1 : 0;
|
|
188176
|
-
}
|
|
188177
|
-
function validationFreshnessScore(memory) {
|
|
188178
|
-
const validatedAt = memory.lastValidatedAt ?? memory.approvedAt ?? memory.qualifiedAt;
|
|
188179
|
-
if (!validatedAt) return 0;
|
|
188180
|
-
const time3 = Date.parse(validatedAt);
|
|
188181
|
-
if (!Number.isFinite(time3)) return 0;
|
|
188182
|
-
const ageDays = Math.max(0, Date.now() - time3) / (24 * 60 * 60 * 1e3);
|
|
188183
|
-
if (ageDays <= 30) return 0.35;
|
|
188184
|
-
if (ageDays <= 90) return 0.15;
|
|
188185
|
-
return 0;
|
|
188186
|
-
}
|
|
188187
|
-
function scoreForTask(memory, task) {
|
|
188188
|
-
const terms = taskTerms(task);
|
|
188189
|
-
if (terms.length === 0) return void 0;
|
|
188190
|
-
const title = memory.title.toLocaleLowerCase("en-US");
|
|
188191
|
-
const content = memory.content.toLocaleLowerCase("en-US");
|
|
188192
|
-
const facts = memory.facts.join(" ").toLocaleLowerCase("en-US");
|
|
188193
|
-
const tags = memory.tags.join(" ").toLocaleLowerCase("en-US");
|
|
188194
|
-
const applicability = (memory.applicability ?? "").toLocaleLowerCase("en-US");
|
|
188195
|
-
let score = memory.state === "approved" ? 0.5 : 0;
|
|
188196
|
-
const matched = [];
|
|
188197
|
-
for (const term of terms) {
|
|
188198
|
-
let termScore = 0;
|
|
188199
|
-
if (title.includes(term)) termScore += 5;
|
|
188200
|
-
if (tags.includes(term)) termScore += 4;
|
|
188201
|
-
if (applicability.includes(term)) termScore += 3;
|
|
188202
|
-
if (facts.includes(term)) termScore += 2;
|
|
188203
|
-
if (content.includes(term)) termScore += 1;
|
|
188204
|
-
if (termScore > 0) {
|
|
188205
|
-
score += termScore;
|
|
188206
|
-
matched.push(term);
|
|
188207
|
-
}
|
|
188208
|
-
}
|
|
188209
|
-
if (matched.length === 0) return void 0;
|
|
188210
|
-
score += kindFitScore(memory.kind, task);
|
|
188211
|
-
score += validationFreshnessScore(memory);
|
|
188212
|
-
const kindLabel = memory.kind === "procedural" ? "procedure" : memory.kind === "semantic" ? "fact" : "episode";
|
|
188213
|
-
const freshness = validationFreshnessScore(memory) > 0 ? "; recently validated" : "";
|
|
188214
|
-
return { score, reason: kindLabel + " matches " + matched.slice(0, 3).join(", ") + freshness };
|
|
188215
|
-
}
|
|
188216
|
-
function semanticText(memory) {
|
|
188217
|
-
return sanitizeCredentials([
|
|
188218
|
-
memory.title,
|
|
188219
|
-
memory.applicability,
|
|
188220
|
-
memory.tags.join(" "),
|
|
188221
|
-
memory.facts.join(" "),
|
|
188222
|
-
memory.content
|
|
188223
|
-
].filter((value) => Boolean(value)).join("\n")).replace(/\s+/g, " ").trim().slice(0, MAX_TEXT_LENGTH);
|
|
188224
|
-
}
|
|
188225
|
-
function cosineSimilarity(left, right) {
|
|
188226
|
-
if (left.length === 0 || left.length !== right.length) return 0;
|
|
188227
|
-
let dot = 0;
|
|
188228
|
-
let leftMagnitude = 0;
|
|
188229
|
-
let rightMagnitude = 0;
|
|
188230
|
-
for (let index = 0; index < left.length; index += 1) {
|
|
188231
|
-
const a4 = left[index];
|
|
188232
|
-
const b4 = right[index];
|
|
188233
|
-
if (!Number.isFinite(a4) || !Number.isFinite(b4)) return 0;
|
|
188234
|
-
dot += a4 * b4;
|
|
188235
|
-
leftMagnitude += a4 * a4;
|
|
188236
|
-
rightMagnitude += b4 * b4;
|
|
188237
|
-
}
|
|
188238
|
-
if (leftMagnitude === 0 || rightMagnitude === 0) return 0;
|
|
188239
|
-
return dot / Math.sqrt(leftMagnitude * rightMagnitude);
|
|
188240
|
-
}
|
|
188241
|
-
function semanticSelection(memory, similarity, task) {
|
|
188242
|
-
if (similarity < MIN_SEMANTIC_SIMILARITY) return void 0;
|
|
188243
|
-
const kindLabel = memory.kind === "procedural" ? "procedure" : memory.kind === "semantic" ? "fact" : "episode";
|
|
188244
|
-
const freshness = validationFreshnessScore(memory) > 0 ? "; recently validated" : "";
|
|
188245
|
-
return {
|
|
188246
|
-
score: similarity * 10 + (memory.state === "approved" ? 0.5 : 0) + kindFitScore(memory.kind, task) + validationFreshnessScore(memory),
|
|
188247
|
-
reason: kindLabel + " semantic match " + similarity.toFixed(2) + freshness
|
|
188248
|
-
};
|
|
188249
|
-
}
|
|
188250
|
-
async function resolveSemanticProvider(explicit) {
|
|
188251
|
-
if (explicit !== void 0) return explicit;
|
|
188252
|
-
try {
|
|
188253
|
-
const { getEmbeddingProvider: getEmbeddingProvider2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
|
|
188254
|
-
return await withTimeout(
|
|
188255
|
-
getEmbeddingProvider2({ requestTimeoutMs: SEMANTIC_RETRIEVAL_TIMEOUT_MS, retry: false }),
|
|
188256
|
-
SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
188257
|
-
"Long-term semantic provider initialization"
|
|
188258
|
-
);
|
|
188259
|
-
} catch {
|
|
188260
|
-
return null;
|
|
188261
|
-
}
|
|
188262
|
-
}
|
|
188263
|
-
function createStore(dataDir) {
|
|
188264
|
-
const store2 = new LongTermMemoryStore();
|
|
188265
|
-
return store2.init(dataDir).then(() => store2);
|
|
188266
|
-
}
|
|
188267
|
-
async function createManualLongTermMemory(input) {
|
|
188268
|
-
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
188269
|
-
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
188270
|
-
assertScope(input.scope);
|
|
188271
|
-
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID14(), relation: "supports" }];
|
|
188272
|
-
return createLongTermMemoryWithDataDir({
|
|
188273
|
-
dataDir: input.dataDir,
|
|
188274
|
-
originProjectId: input.projectId,
|
|
188275
|
-
ownerId: owner.id,
|
|
188276
|
-
scope: input.scope,
|
|
188277
|
-
kind: input.kind,
|
|
188278
|
-
portability: input.portability,
|
|
188279
|
-
title: input.title,
|
|
188280
|
-
content: input.content,
|
|
188281
|
-
facts: input.facts,
|
|
188282
|
-
tags: input.tags,
|
|
188283
|
-
applicability: input.applicability,
|
|
188284
|
-
origin: "manual",
|
|
188285
|
-
evidence,
|
|
188286
|
-
reader: input.reader
|
|
188287
|
-
});
|
|
188288
|
-
}
|
|
188289
|
-
async function promoteObservationToLongTermMemory(input) {
|
|
188290
|
-
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
188291
|
-
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
188292
|
-
return createLongTermMemoryWithDataDir({
|
|
188293
|
-
dataDir: input.dataDir,
|
|
188294
|
-
originProjectId: input.observation.projectId,
|
|
188295
|
-
ownerId: owner.id,
|
|
188296
|
-
scope: input.scope,
|
|
188297
|
-
kind: input.kind,
|
|
188298
|
-
portability: "project-bound",
|
|
188299
|
-
title: input.observation.title,
|
|
188300
|
-
content: input.observation.narrative,
|
|
188301
|
-
facts: input.observation.facts,
|
|
188302
|
-
tags: input.tags ?? input.observation.concepts,
|
|
188303
|
-
applicability: input.applicability,
|
|
188304
|
-
origin: input.observation.source === "git" ? "git" : "agent",
|
|
188305
|
-
evidence: [{
|
|
188306
|
-
kind: "observation",
|
|
188307
|
-
referenceId: "obs:" + input.observation.projectId + ":" + input.observation.id,
|
|
188308
|
-
relation: "derives"
|
|
188309
|
-
}],
|
|
188310
|
-
reader: input.reader
|
|
188311
|
-
});
|
|
188312
|
-
}
|
|
188313
|
-
async function createLongTermMemoryCandidate(input) {
|
|
188314
|
-
return createLongTermMemoryWithDataDir(input);
|
|
188315
|
-
}
|
|
188316
|
-
async function createLongTermMemoryWithDataDir(input) {
|
|
188317
|
-
assertScope(input.scope);
|
|
188318
|
-
assertKind(input.kind);
|
|
188319
|
-
const portability = input.portability ?? "project-bound";
|
|
188320
|
-
assertPortability(portability);
|
|
188321
|
-
requireTeamReader(input.scope, input.reader);
|
|
188322
|
-
const evidenceInputs = normalizeEvidence(input.evidence);
|
|
188323
|
-
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
188324
|
-
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
188325
|
-
const memory = {
|
|
188326
|
-
id: randomUUID14(),
|
|
188327
|
-
originProjectId: compactText2(input.originProjectId, "origin project id", 1e3),
|
|
188328
|
-
ownerId: compactText2(input.ownerId, "owner id", 160),
|
|
188329
|
-
scope: input.scope,
|
|
188330
|
-
kind: input.kind,
|
|
188331
|
-
state: "candidate",
|
|
188332
|
-
portability,
|
|
188333
|
-
title: compactText2(input.title, "title", 500),
|
|
188334
|
-
content: compactText2(input.content, "content"),
|
|
188335
|
-
facts: compactList(input.facts, "facts"),
|
|
188336
|
-
tags: compactList(input.tags, "tags"),
|
|
188337
|
-
...input.applicability ? { applicability: compactText2(input.applicability, "applicability", 1e3) } : {},
|
|
188338
|
-
origin: input.origin ?? "manual",
|
|
188339
|
-
createdAt: now3,
|
|
188340
|
-
updatedAt: now3,
|
|
188341
|
-
accessCount: 0
|
|
188342
|
-
};
|
|
188343
|
-
const store2 = await createStore(input.dataDir);
|
|
188344
|
-
const evidence = store2.transaction(() => {
|
|
188345
|
-
store2.insert(memory);
|
|
188346
|
-
const written = evidenceInputs.map((item) => store2.insertEvidence({ memoryId: memory.id, ...item, createdAt: now3 }));
|
|
188347
|
-
store2.recordEvent({
|
|
188348
|
-
memoryId: memory.id,
|
|
188349
|
-
kind: "created",
|
|
188350
|
-
toState: "candidate",
|
|
188351
|
-
detail: "Created as a source-backed long-term memory candidate.",
|
|
188352
|
-
createdAt: now3
|
|
188353
|
-
});
|
|
188354
|
-
return written;
|
|
188355
|
-
});
|
|
188356
|
-
return { memory, evidence };
|
|
188357
|
-
}
|
|
188358
|
-
function transitionDetail(value) {
|
|
188359
|
-
return compactText2(value, "transition reason", 1e3);
|
|
188360
|
-
}
|
|
188361
|
-
async function transitionMemory(input) {
|
|
188362
|
-
const store2 = await createStore(input.dataDir);
|
|
188363
|
-
return store2.transaction(() => {
|
|
188364
|
-
const current = store2.get(input.id);
|
|
188365
|
-
if (!current) throw new Error("Long-term memory was not found.");
|
|
188366
|
-
if (current.state !== input.expected) {
|
|
188367
|
-
throw new Error("Long-term memory must be " + input.expected + " before it can be " + input.next + ".");
|
|
188368
|
-
}
|
|
188369
|
-
const evidence = store2.listEvidence(current.id);
|
|
188370
|
-
if (evidence.length === 0) throw new Error("Long-term memory cannot advance without source evidence.");
|
|
188371
|
-
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
188372
|
-
const next = {
|
|
188373
|
-
...current,
|
|
188374
|
-
state: input.next,
|
|
188375
|
-
updatedAt: now3,
|
|
188376
|
-
lastValidatedAt: now3,
|
|
188377
|
-
...input.next === "qualified" ? { qualifiedAt: now3 } : { approvedAt: now3 }
|
|
188378
|
-
};
|
|
188379
|
-
store2.update(next);
|
|
188380
|
-
store2.recordEvent({
|
|
188381
|
-
memoryId: next.id,
|
|
188382
|
-
kind: input.event,
|
|
188383
|
-
fromState: current.state,
|
|
188384
|
-
toState: next.state,
|
|
188385
|
-
detail: transitionDetail(input.reason),
|
|
188386
|
-
createdAt: now3
|
|
188387
|
-
});
|
|
188388
|
-
return next;
|
|
188389
|
-
});
|
|
188390
|
-
}
|
|
188391
|
-
async function qualifyLongTermMemory(input) {
|
|
188392
|
-
return transitionMemory({ ...input, expected: "candidate", next: "qualified", event: "qualified" });
|
|
188393
|
-
}
|
|
188394
|
-
async function approveLongTermMemory(input) {
|
|
188395
|
-
return transitionMemory({ ...input, expected: "qualified", next: "approved", event: "approved" });
|
|
188396
|
-
}
|
|
188397
|
-
async function archiveLongTermMemory(input) {
|
|
188398
|
-
const store2 = await createStore(input.dataDir);
|
|
188399
|
-
return store2.transaction(() => {
|
|
188400
|
-
const current = store2.get(input.id);
|
|
188401
|
-
if (!current) throw new Error("Long-term memory was not found.");
|
|
188402
|
-
if (current.state === "archived" || current.state === "superseded") {
|
|
188403
|
-
throw new Error("Long-term memory is already inactive.");
|
|
188404
|
-
}
|
|
188405
|
-
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
188406
|
-
const next = { ...current, state: "archived", archivedAt: now3, updatedAt: now3 };
|
|
188407
|
-
store2.update(next);
|
|
188408
|
-
store2.recordEvent({
|
|
188409
|
-
memoryId: next.id,
|
|
188410
|
-
kind: "archived",
|
|
188411
|
-
fromState: current.state,
|
|
188412
|
-
toState: "archived",
|
|
188413
|
-
detail: transitionDetail(input.reason),
|
|
188414
|
-
createdAt: now3
|
|
188415
|
-
});
|
|
188416
|
-
return next;
|
|
188417
|
-
});
|
|
188418
|
-
}
|
|
188419
|
-
async function supersedeLongTermMemory(input) {
|
|
188420
|
-
const store2 = await createStore(input.dataDir);
|
|
188421
|
-
return store2.transaction(() => {
|
|
188422
|
-
const current = store2.get(input.id);
|
|
188423
|
-
if (!current) throw new Error("Long-term memory was not found.");
|
|
188424
|
-
if (current.state === "archived" || current.state === "superseded") {
|
|
188425
|
-
throw new Error("Long-term memory is already inactive.");
|
|
188426
|
-
}
|
|
188427
|
-
if (current.id === input.supersededBy) {
|
|
188428
|
-
throw new Error("Long-term memory cannot supersede itself.");
|
|
188429
|
-
}
|
|
188430
|
-
const replacement = store2.get(input.supersededBy);
|
|
188431
|
-
if (!replacement || !isEligibleLongTermMemory(replacement)) {
|
|
188432
|
-
throw new Error("Replacement long-term memory must be qualified or approved.");
|
|
188433
|
-
}
|
|
188434
|
-
if (replacement.scope !== current.scope) {
|
|
188435
|
-
throw new Error("Replacement long-term memory must use the same scope.");
|
|
188436
|
-
}
|
|
188437
|
-
if (current.scope === "user" && replacement.ownerId !== current.ownerId) {
|
|
188438
|
-
throw new Error("User long-term memory may only be superseded by the same local owner.");
|
|
188439
|
-
}
|
|
188440
|
-
if (current.scope !== "user" && replacement.originProjectId !== current.originProjectId) {
|
|
188441
|
-
throw new Error("Project and team long-term memory may only be superseded within the same project.");
|
|
188442
|
-
}
|
|
188443
|
-
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
188444
|
-
const next = {
|
|
188445
|
-
...current,
|
|
188446
|
-
state: "superseded",
|
|
188447
|
-
supersededBy: replacement.id,
|
|
188448
|
-
updatedAt: now3
|
|
188449
|
-
};
|
|
188450
|
-
store2.update(next);
|
|
188451
|
-
store2.recordEvent({
|
|
188452
|
-
memoryId: next.id,
|
|
188453
|
-
kind: "superseded",
|
|
188454
|
-
fromState: current.state,
|
|
188455
|
-
toState: "superseded",
|
|
188456
|
-
detail: transitionDetail(input.reason),
|
|
188457
|
-
createdAt: now3
|
|
188458
|
-
});
|
|
188459
|
-
return next;
|
|
188460
|
-
});
|
|
188461
|
-
}
|
|
188462
|
-
async function listLongTermMemories(input) {
|
|
188463
|
-
const store2 = await createStore(input.dataDir);
|
|
188464
|
-
return store2.list({ limit: input.limit ?? 100 }).filter((memory) => canReadLongTermMemory(memory, input.reader)).filter((memory) => input.includeInactive || memory.state !== "archived" && memory.state !== "superseded").map((memory) => ({ memory, evidence: store2.listEvidence(memory.id) }));
|
|
188465
|
-
}
|
|
188466
|
-
async function getLongTermMemoryDetail(input) {
|
|
188467
|
-
const store2 = await createStore(input.dataDir);
|
|
188468
|
-
const memory = store2.get(input.id);
|
|
188469
|
-
if (!memory || !canReadLongTermMemory(memory, input.reader)) {
|
|
188470
|
-
throw new Error("Long-term memory was not found in the active scope.");
|
|
188471
|
-
}
|
|
188472
|
-
store2.markAccess([memory.id]);
|
|
188473
|
-
return { memory, evidence: store2.listEvidence(memory.id), events: store2.listEvents(memory.id) };
|
|
188474
|
-
}
|
|
188475
|
-
async function selectLongTermMemoriesForTask(input) {
|
|
188476
|
-
const task = input.task?.trim();
|
|
188477
|
-
if (!task) return [];
|
|
188478
|
-
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: false });
|
|
188479
|
-
const reader = {
|
|
188480
|
-
projectId: input.projectId,
|
|
188481
|
-
...owner ? { ownerId: owner.id } : {},
|
|
188482
|
-
...input.agentId ? { agentId: input.agentId } : {},
|
|
188483
|
-
...input.isTeamMember ? { isTeamMember: true } : {}
|
|
188484
|
-
};
|
|
188485
|
-
const store2 = await createStore(input.dataDir);
|
|
188486
|
-
const eligible = store2.list({ limit: 1e3 }).filter((memory) => isEligibleLongTermMemory(memory) && canReadLongTermMemory(memory, reader));
|
|
188487
|
-
let selected = eligible.map((memory) => {
|
|
188488
|
-
const ranked = scoreForTask(memory, task);
|
|
188489
|
-
return ranked ? {
|
|
188490
|
-
memory,
|
|
188491
|
-
evidence: store2.listEvidence(memory.id),
|
|
188492
|
-
score: ranked.score,
|
|
188493
|
-
reason: ranked.reason
|
|
188494
|
-
} : void 0;
|
|
188495
|
-
}).filter((item) => Boolean(item)).sort((left, right) => right.score - left.score || right.memory.updatedAt.localeCompare(left.memory.updatedAt) || left.memory.id.localeCompare(right.memory.id));
|
|
188496
|
-
if (selected.length === 0 && eligible.length > 0) {
|
|
188497
|
-
const provider2 = await resolveSemanticProvider(input.embeddingProvider);
|
|
188498
|
-
const candidates = eligible.slice(0, MAX_SEMANTIC_CANDIDATES);
|
|
188499
|
-
if (provider2 && candidates.length > 0) {
|
|
188500
|
-
try {
|
|
188501
|
-
const vectors = await withTimeout(
|
|
188502
|
-
provider2.embedBatch([task, ...candidates.map(semanticText)], {
|
|
188503
|
-
timeoutMs: SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
188504
|
-
retry: false
|
|
188505
|
-
}),
|
|
188506
|
-
SEMANTIC_RETRIEVAL_TIMEOUT_MS,
|
|
188507
|
-
"Long-term semantic retrieval"
|
|
188508
|
-
);
|
|
188509
|
-
const query = vectors[0];
|
|
188510
|
-
if (Array.isArray(query)) {
|
|
188511
|
-
selected = candidates.map((memory, index) => {
|
|
188512
|
-
const vector = vectors[index + 1];
|
|
188513
|
-
const ranked = Array.isArray(vector) ? semanticSelection(memory, cosineSimilarity(query, vector), task) : void 0;
|
|
188514
|
-
return ranked ? {
|
|
188515
|
-
memory,
|
|
188516
|
-
evidence: store2.listEvidence(memory.id),
|
|
188517
|
-
score: ranked.score,
|
|
188518
|
-
reason: ranked.reason
|
|
188519
|
-
} : void 0;
|
|
188520
|
-
}).filter((item) => Boolean(item)).sort((left, right) => right.score - left.score || right.memory.updatedAt.localeCompare(left.memory.updatedAt) || left.memory.id.localeCompare(right.memory.id));
|
|
188521
|
-
}
|
|
188522
|
-
} catch {
|
|
188523
|
-
}
|
|
188524
|
-
}
|
|
188525
|
-
}
|
|
188526
|
-
selected = selected.slice(0, Math.max(1, Math.min(input.limit ?? 3, 5)));
|
|
188527
|
-
store2.markAccess(selected.map((item) => item.memory.id));
|
|
188528
|
-
return selected;
|
|
188529
|
-
}
|
|
188530
|
-
function renderLongTermMemorySummary(memory, maxTokens = 22) {
|
|
188531
|
-
const source = [memory.title, memory.applicability, memory.content].filter(Boolean).join(": ");
|
|
188532
|
-
const safe = sanitizeCredentials(source).replace(/\s+/g, " ").trim();
|
|
188533
|
-
return countTextTokens(safe) <= maxTokens ? safe : truncateToTokenBudget(safe, maxTokens);
|
|
188534
|
-
}
|
|
188535
|
-
var MAX_TEXT_LENGTH, MAX_LIST_ITEMS, MAX_SEMANTIC_CANDIDATES, SEMANTIC_RETRIEVAL_TIMEOUT_MS, MIN_SEMANTIC_SIMILARITY, PORTABLE_EVIDENCE_KINDS, STOP_TERMS;
|
|
188536
|
-
var init_long_term = __esm({
|
|
188537
|
-
"src/memory/long-term.ts"() {
|
|
188538
|
-
"use strict";
|
|
188539
|
-
init_esm_shims();
|
|
188540
|
-
init_token_budget();
|
|
188541
|
-
init_timeout();
|
|
188542
|
-
init_secret_filter();
|
|
188543
|
-
init_owner();
|
|
188544
|
-
init_long_term_store();
|
|
188545
|
-
init_long_term_types();
|
|
188546
|
-
MAX_TEXT_LENGTH = 12e3;
|
|
188547
|
-
MAX_LIST_ITEMS = 40;
|
|
188548
|
-
MAX_SEMANTIC_CANDIDATES = 48;
|
|
188549
|
-
SEMANTIC_RETRIEVAL_TIMEOUT_MS = 1800;
|
|
188550
|
-
MIN_SEMANTIC_SIMILARITY = 0.58;
|
|
188551
|
-
PORTABLE_EVIDENCE_KINDS = /* @__PURE__ */ new Set(["manual", "user"]);
|
|
188552
|
-
STOP_TERMS = /* @__PURE__ */ new Set([
|
|
188553
|
-
"the",
|
|
188554
|
-
"and",
|
|
188555
|
-
"for",
|
|
188556
|
-
"with",
|
|
188557
|
-
"from",
|
|
188558
|
-
"that",
|
|
188559
|
-
"this",
|
|
188560
|
-
"into",
|
|
188561
|
-
"when",
|
|
188562
|
-
"what",
|
|
188563
|
-
"\u5982\u4F55",
|
|
188564
|
-
"\u4EC0\u4E48",
|
|
188565
|
-
"\u8FD9\u4E2A",
|
|
188566
|
-
"\u90A3\u4E2A",
|
|
188567
|
-
"\u6211\u4EEC",
|
|
188568
|
-
"\u9879\u76EE",
|
|
188569
|
-
"\u8FDB\u884C",
|
|
188570
|
-
"\u9700\u8981",
|
|
188571
|
-
"\u7EE7\u7EED",
|
|
188572
|
-
"\u5904\u7406"
|
|
188573
|
-
]);
|
|
188574
|
-
}
|
|
188575
|
-
});
|
|
188576
|
-
|
|
188577
188662
|
// src/cli/commands/memory.ts
|
|
188578
188663
|
var memory_exports2 = {};
|
|
188579
188664
|
__export(memory_exports2, {
|
|
@@ -189052,6 +189137,7 @@ var init_memory3 = __esm({
|
|
|
189052
189137
|
createManualLongTermMemory: createManualLongTermMemory2,
|
|
189053
189138
|
getLongTermMemoryDetail: getLongTermMemoryDetail2,
|
|
189054
189139
|
listLongTermMemories: listLongTermMemories2,
|
|
189140
|
+
maybeAutoQualifyLongTermMemory: maybeAutoQualifyLongTermMemory2,
|
|
189055
189141
|
promoteObservationToLongTermMemory: promoteObservationToLongTermMemory2,
|
|
189056
189142
|
qualifyLongTermMemory: qualifyLongTermMemory2,
|
|
189057
189143
|
supersedeLongTermMemory: supersedeLongTermMemory2
|
|
@@ -189122,9 +189208,14 @@ var init_memory3 = __esm({
|
|
|
189122
189208
|
portability: portability(),
|
|
189123
189209
|
reader: longTermReader
|
|
189124
189210
|
});
|
|
189211
|
+
const qualified = await maybeAutoQualifyLongTermMemory2({
|
|
189212
|
+
dataDir,
|
|
189213
|
+
id: result.memory.id,
|
|
189214
|
+
source: "manual"
|
|
189215
|
+
});
|
|
189125
189216
|
emitResult(
|
|
189126
|
-
{ project, ...result },
|
|
189127
|
-
`Created long-term memory
|
|
189217
|
+
{ project, ...result, memory: qualified ?? result.memory },
|
|
189218
|
+
`Created long-term memory ${result.memory.id}.`,
|
|
189128
189219
|
asJson
|
|
189129
189220
|
);
|
|
189130
189221
|
return;
|
|
@@ -189150,9 +189241,14 @@ var init_memory3 = __esm({
|
|
|
189150
189241
|
applicability: asStringArg(args.applicability),
|
|
189151
189242
|
reader: longTermReader
|
|
189152
189243
|
});
|
|
189244
|
+
const qualified = await maybeAutoQualifyLongTermMemory2({
|
|
189245
|
+
dataDir,
|
|
189246
|
+
id: result.memory.id,
|
|
189247
|
+
sourceDetail: "explicit"
|
|
189248
|
+
});
|
|
189153
189249
|
emitResult(
|
|
189154
|
-
{ project, sourceObservationId: observation.id, ...result },
|
|
189155
|
-
`Promoted observation #${observation.id} to long-term memory
|
|
189250
|
+
{ project, sourceObservationId: observation.id, ...result, memory: qualified ?? result.memory },
|
|
189251
|
+
`Promoted observation #${observation.id} to long-term memory ${result.memory.id}.`,
|
|
189156
189252
|
asJson
|
|
189157
189253
|
);
|
|
189158
189254
|
return;
|
|
@@ -190538,9 +190634,116 @@ var init_trae = __esm({
|
|
|
190538
190634
|
}
|
|
190539
190635
|
});
|
|
190540
190636
|
|
|
190541
|
-
// src/workspace/mcp-adapters/
|
|
190637
|
+
// src/workspace/mcp-adapters/dsh.ts
|
|
190542
190638
|
import { homedir as homedir22 } from "os";
|
|
190543
190639
|
import { join as join19 } from "path";
|
|
190640
|
+
function resolveDshHome() {
|
|
190641
|
+
const configured = process.env.DSH_HOME?.trim();
|
|
190642
|
+
if (configured) return configured;
|
|
190643
|
+
return join19(homedir22(), ".dsh");
|
|
190644
|
+
}
|
|
190645
|
+
function isMemorixRow(row) {
|
|
190646
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) return false;
|
|
190647
|
+
const record2 = row;
|
|
190648
|
+
if (record2.name !== MCP_CLIENT_PLUGIN) return false;
|
|
190649
|
+
const config2 = record2.config;
|
|
190650
|
+
return Boolean(
|
|
190651
|
+
config2 && typeof config2 === "object" && !Array.isArray(config2) && config2.serverName === "memorix"
|
|
190652
|
+
);
|
|
190653
|
+
}
|
|
190654
|
+
function rowToEntry(row) {
|
|
190655
|
+
const config2 = row.config;
|
|
190656
|
+
if (!config2 || typeof config2 !== "object") return null;
|
|
190657
|
+
const entry = {
|
|
190658
|
+
name: "memorix",
|
|
190659
|
+
command: typeof config2.command === "string" ? config2.command : "",
|
|
190660
|
+
args: Array.isArray(config2.args) ? config2.args.filter((arg) => typeof arg === "string") : []
|
|
190661
|
+
};
|
|
190662
|
+
if (typeof config2.url === "string" && config2.url) entry.url = config2.url;
|
|
190663
|
+
if (config2.env && typeof config2.env === "object" && !Array.isArray(config2.env)) {
|
|
190664
|
+
const env3 = {};
|
|
190665
|
+
for (const [key, value] of Object.entries(config2.env)) {
|
|
190666
|
+
if (typeof value === "string") env3[key] = value;
|
|
190667
|
+
}
|
|
190668
|
+
if (Object.keys(env3).length > 0) entry.env = env3;
|
|
190669
|
+
}
|
|
190670
|
+
if (config2.disabled === true) entry.disabled = true;
|
|
190671
|
+
return entry;
|
|
190672
|
+
}
|
|
190673
|
+
function patchRows(document2) {
|
|
190674
|
+
const rows = [];
|
|
190675
|
+
if (!Array.isArray(document2)) return rows;
|
|
190676
|
+
for (const item of document2) {
|
|
190677
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
190678
|
+
const record2 = item;
|
|
190679
|
+
if (Array.isArray(record2.insert)) {
|
|
190680
|
+
for (const row of record2.insert) {
|
|
190681
|
+
if (row && typeof row === "object" && !Array.isArray(row)) {
|
|
190682
|
+
rows.push(row);
|
|
190683
|
+
}
|
|
190684
|
+
}
|
|
190685
|
+
continue;
|
|
190686
|
+
}
|
|
190687
|
+
rows.push(record2);
|
|
190688
|
+
}
|
|
190689
|
+
return rows;
|
|
190690
|
+
}
|
|
190691
|
+
var import_yaml4, MCP_CLIENT_PLUGIN, MEMORIX_ROW_ID, DshMCPAdapter;
|
|
190692
|
+
var init_dsh = __esm({
|
|
190693
|
+
"src/workspace/mcp-adapters/dsh.ts"() {
|
|
190694
|
+
"use strict";
|
|
190695
|
+
init_esm_shims();
|
|
190696
|
+
import_yaml4 = __toESM(require_dist(), 1);
|
|
190697
|
+
MCP_CLIENT_PLUGIN = "@deepseek-ai/dsh-mcp-client";
|
|
190698
|
+
MEMORIX_ROW_ID = "memory-memorix";
|
|
190699
|
+
DshMCPAdapter = class {
|
|
190700
|
+
source = "dsh";
|
|
190701
|
+
parse(content) {
|
|
190702
|
+
if (!content.trim()) return [];
|
|
190703
|
+
let document2;
|
|
190704
|
+
try {
|
|
190705
|
+
document2 = (0, import_yaml4.parse)(content);
|
|
190706
|
+
} catch {
|
|
190707
|
+
return [];
|
|
190708
|
+
}
|
|
190709
|
+
return patchRows(document2).filter(isMemorixRow).map(rowToEntry).filter((entry) => entry !== null);
|
|
190710
|
+
}
|
|
190711
|
+
generate(servers) {
|
|
190712
|
+
const rows = servers.filter((server) => server.name === "memorix").map((server) => {
|
|
190713
|
+
const config2 = {
|
|
190714
|
+
serverName: server.name
|
|
190715
|
+
};
|
|
190716
|
+
if (server.url) {
|
|
190717
|
+
config2.transport = "streamable-http";
|
|
190718
|
+
config2.url = server.url;
|
|
190719
|
+
if (server.headers && Object.keys(server.headers).length > 0) config2.headers = server.headers;
|
|
190720
|
+
} else {
|
|
190721
|
+
config2.transport = "stdio";
|
|
190722
|
+
config2.command = server.command;
|
|
190723
|
+
if (server.args && server.args.length > 0) config2.args = server.args;
|
|
190724
|
+
if (server.env && Object.keys(server.env).length > 0) config2.env = server.env;
|
|
190725
|
+
}
|
|
190726
|
+
const row = {
|
|
190727
|
+
id: MEMORIX_ROW_ID,
|
|
190728
|
+
name: MCP_CLIENT_PLUGIN,
|
|
190729
|
+
config: config2
|
|
190730
|
+
};
|
|
190731
|
+
if (server.disabled === true) row.disabled = true;
|
|
190732
|
+
return row;
|
|
190733
|
+
});
|
|
190734
|
+
if (rows.length === 0) return "";
|
|
190735
|
+
return (0, import_yaml4.stringify)([{ insert: rows }], { lineWidth: 0 }) + "\n";
|
|
190736
|
+
}
|
|
190737
|
+
getConfigPath(_projectRoot) {
|
|
190738
|
+
return join19(resolveDshHome(), "cordis.patch.yml");
|
|
190739
|
+
}
|
|
190740
|
+
};
|
|
190741
|
+
}
|
|
190742
|
+
});
|
|
190743
|
+
|
|
190744
|
+
// src/workspace/mcp-adapters/codebuddy.ts
|
|
190745
|
+
import { homedir as homedir23 } from "os";
|
|
190746
|
+
import { join as join20 } from "path";
|
|
190544
190747
|
var CodeBuddyMCPAdapter;
|
|
190545
190748
|
var init_codebuddy = __esm({
|
|
190546
190749
|
"src/workspace/mcp-adapters/codebuddy.ts"() {
|
|
@@ -190572,7 +190775,7 @@ var init_codebuddy = __esm({
|
|
|
190572
190775
|
return JSON.stringify({ mcpServers }, null, 2);
|
|
190573
190776
|
}
|
|
190574
190777
|
getConfigPath(projectRoot) {
|
|
190575
|
-
return projectRoot ?
|
|
190778
|
+
return projectRoot ? join20(projectRoot, ".mcp.json") : join20(homedir23(), ".codebuddy", ".mcp.json");
|
|
190576
190779
|
}
|
|
190577
190780
|
};
|
|
190578
190781
|
}
|
|
@@ -190713,6 +190916,15 @@ var init_registry2 = __esm({
|
|
|
190713
190916
|
install: "memorix setup --agent trae",
|
|
190714
190917
|
surfaces: ["MCP", "rules"]
|
|
190715
190918
|
},
|
|
190919
|
+
{
|
|
190920
|
+
agent: "dsh",
|
|
190921
|
+
name: "DeepSeek Harness",
|
|
190922
|
+
entry: "official-config",
|
|
190923
|
+
status: "ready",
|
|
190924
|
+
install: "memorix setup --agent dsh",
|
|
190925
|
+
surfaces: ["MCP", "AGENTS.md", "skills"],
|
|
190926
|
+
note: "DeepSeek Harness support writes a @deepseek-ai/dsh-mcp-client row into $DSH_HOME/cordis.patch.yml (default ~/.dsh/cordis.patch.yml), guidance into the harness AGENTS.md, and skills under $DSH_HOME/skills."
|
|
190927
|
+
},
|
|
190716
190928
|
{
|
|
190717
190929
|
agent: "memcode",
|
|
190718
190930
|
name: "memcode",
|
|
@@ -191006,9 +191218,9 @@ __export(audit_exports, {
|
|
|
191006
191218
|
});
|
|
191007
191219
|
import * as fs18 from "fs/promises";
|
|
191008
191220
|
import * as path28 from "path";
|
|
191009
|
-
import { homedir as
|
|
191221
|
+
import { homedir as homedir24 } from "os";
|
|
191010
191222
|
function getAuditFilePath() {
|
|
191011
|
-
return process.env.MEMORIX_AUDIT_FILE || path28.join(
|
|
191223
|
+
return process.env.MEMORIX_AUDIT_FILE || path28.join(homedir24(), ".memorix", "audit.json");
|
|
191012
191224
|
}
|
|
191013
191225
|
async function loadAudit() {
|
|
191014
191226
|
try {
|
|
@@ -191321,7 +191533,7 @@ async function installOfficialSkillsForAgent(agent, projectRoot, global2 = false
|
|
|
191321
191533
|
const dirs = AGENT_SKILL_DIRS[agent];
|
|
191322
191534
|
const relativeDir = global2 ? dirs?.global : dirs?.project;
|
|
191323
191535
|
if (!relativeDir) return [];
|
|
191324
|
-
const root = global2 ? os3.homedir() : projectRoot;
|
|
191536
|
+
const root = global2 ? agent === "dsh" ? process.env.DSH_HOME?.trim() || path29.join(os3.homedir(), ".dsh") : os3.homedir() : projectRoot;
|
|
191325
191537
|
const skillPaths = [];
|
|
191326
191538
|
for (const skillEntry of OFFICIAL_MEMORIX_SKILLS) {
|
|
191327
191539
|
const skillPath = path29.join(root, relativeDir, skillEntry.name, "SKILL.md");
|
|
@@ -191553,6 +191765,8 @@ function getProjectConfigPath(agent, projectRoot) {
|
|
|
191553
191765
|
return path29.join(projectRoot, "AGENTS.md");
|
|
191554
191766
|
case "trae":
|
|
191555
191767
|
return path29.join(projectRoot, ".trae", "rules", "project_rules.md");
|
|
191768
|
+
case "dsh":
|
|
191769
|
+
return path29.join(projectRoot, "AGENTS.md");
|
|
191556
191770
|
case "opencode":
|
|
191557
191771
|
return path29.join(projectRoot, ".opencode", "plugins", "memorix.js");
|
|
191558
191772
|
case "pi":
|
|
@@ -191598,6 +191812,8 @@ function getGlobalConfigPath(agent) {
|
|
|
191598
191812
|
return path29.join(home, ".omp", "agent", "packages", "memorix", "extensions", "memorix.js");
|
|
191599
191813
|
case "trae":
|
|
191600
191814
|
return path29.join(home, ".trae", "rules", "project_rules.md");
|
|
191815
|
+
case "dsh":
|
|
191816
|
+
return path29.join(process.env.DSH_HOME?.trim() || path29.join(home, ".dsh"), "AGENTS.md");
|
|
191601
191817
|
default:
|
|
191602
191818
|
return path29.join(home, ".memorix", "hooks.json");
|
|
191603
191819
|
}
|
|
@@ -191622,6 +191838,8 @@ function getAgentRulesPath(agent, root, global2 = false) {
|
|
|
191622
191838
|
return path29.join(root, ".gemini", "GEMINI.md");
|
|
191623
191839
|
case "trae":
|
|
191624
191840
|
return path29.join(root, ".trae", "rules", "project_rules.md");
|
|
191841
|
+
case "dsh":
|
|
191842
|
+
return path29.join(process.env.DSH_HOME?.trim() || path29.join(root, ".dsh"), "AGENTS.md");
|
|
191625
191843
|
default:
|
|
191626
191844
|
return path29.join(root, ".agent", "rules", "memorix.md");
|
|
191627
191845
|
}
|
|
@@ -191646,6 +191864,8 @@ function getAgentRulesPath(agent, root, global2 = false) {
|
|
|
191646
191864
|
return path29.join(root, "GEMINI.md");
|
|
191647
191865
|
case "trae":
|
|
191648
191866
|
return path29.join(root, ".trae", "rules", "project_rules.md");
|
|
191867
|
+
case "dsh":
|
|
191868
|
+
return path29.join(root, "AGENTS.md");
|
|
191649
191869
|
default:
|
|
191650
191870
|
return path29.join(root, ".agent", "rules", "memorix.md");
|
|
191651
191871
|
}
|
|
@@ -191728,6 +191948,12 @@ async function detectInstalledAgents() {
|
|
|
191728
191948
|
agents.push("trae");
|
|
191729
191949
|
} catch {
|
|
191730
191950
|
}
|
|
191951
|
+
const dshDir = process.env.DSH_HOME?.trim() || path29.join(home, ".dsh");
|
|
191952
|
+
try {
|
|
191953
|
+
await fs19.access(dshDir);
|
|
191954
|
+
agents.push("dsh");
|
|
191955
|
+
} catch {
|
|
191956
|
+
}
|
|
191731
191957
|
return agents;
|
|
191732
191958
|
}
|
|
191733
191959
|
async function installHooks(agent, projectRoot, global2 = false) {
|
|
@@ -191810,6 +192036,19 @@ async function installHooks(agent, projectRoot, global2 = false) {
|
|
|
191810
192036
|
generated: { note: "Trae has no hooks system, only rules (.trae/rules/project_rules.md) installed" }
|
|
191811
192037
|
};
|
|
191812
192038
|
}
|
|
192039
|
+
case "dsh": {
|
|
192040
|
+
const rulesPath = await installAgentRules(agent, projectRoot, global2);
|
|
192041
|
+
const skillPaths2 = await installOfficialSkillsForAgent(agent, projectRoot, global2);
|
|
192042
|
+
return {
|
|
192043
|
+
agent,
|
|
192044
|
+
configPath: rulesPath,
|
|
192045
|
+
events: [],
|
|
192046
|
+
generated: {
|
|
192047
|
+
note: "DeepSeek Harness has no hook system \u2014 installed AGENTS.md guidance and skills; the MCP row is installed by `memorix setup --agent dsh`.",
|
|
192048
|
+
...skillPaths2.length > 0 ? { skillPaths: skillPaths2, skillPath: skillPaths2[0] } : {}
|
|
192049
|
+
}
|
|
192050
|
+
};
|
|
192051
|
+
}
|
|
191813
192052
|
case "opencode": {
|
|
191814
192053
|
const pluginContent = generateOpenCodePlugin();
|
|
191815
192054
|
const pluginPath = global2 ? getGlobalConfigPath(agent) : getProjectConfigPath(agent, projectRoot);
|
|
@@ -191944,7 +192183,7 @@ async function installAgentRules(agent, projectRoot, global2 = false) {
|
|
|
191944
192183
|
const rulesPath = getAgentRulesPath(agent, rulesRoot, global2);
|
|
191945
192184
|
try {
|
|
191946
192185
|
await fs19.mkdir(path29.dirname(rulesPath), { recursive: true });
|
|
191947
|
-
if (agent === "claude" || agent === "codex" || agent === "opencode" || agent === "antigravity" || agent === "gemini-cli") {
|
|
192186
|
+
if (agent === "claude" || agent === "codex" || agent === "opencode" || agent === "antigravity" || agent === "gemini-cli" || agent === "dsh") {
|
|
191948
192187
|
try {
|
|
191949
192188
|
const existing = await fs19.readFile(rulesPath, "utf-8");
|
|
191950
192189
|
await fs19.writeFile(rulesPath, mergeMemorixRulesContent(existing, rulesContent), "utf-8");
|
|
@@ -192057,13 +192296,28 @@ alwaysApply: true
|
|
|
192057
192296
|
'- For "why" decisions, use `memorix_store_reasoning`',
|
|
192058
192297
|
'- For a stable fact, reusable procedure, or completed episode that merits deliberate long-term review, include `longTerm` in `memorix_store` with the appropriate kind and normally `scope: "project"`. It creates a candidate only: do not use it for routine updates, do not make project-derived evidence portable user memory, and do not assume it enters context until an operator qualifies and approves it through `memorix memory long-term`.',
|
|
192059
192298
|
"- A `user` + `portable` durable memory delivered in a task brief is intentionally available across projects. When it matches the task, use it as reusable background even if its origin differs; do not treat it as a current-project fact. Expand it only when needed with `memorix_detail` using its `durable:<id>` reference and a specific purpose.",
|
|
192299
|
+
'- Record the user profile: the user\u2019s role, expertise, preferences, and goals. Save these with `entityName: "user-profile"` and `visibility: "personal"` so they stay private and appear in every brief as the "who you are" context.',
|
|
192060
192300
|
"",
|
|
192061
192301
|
"**Don't store:** greetings, simple file reads, trivial commands (ls, pwd, git status).",
|
|
192062
192302
|
"",
|
|
192303
|
+
"**Only store what a future session cannot re-derive.** Code structure, file contents, and Git history are live in the checkout \u2014 do not store facts already visible there. A memory earns its place by capturing the why, the context, or a conclusion the checkout alone cannot show.",
|
|
192304
|
+
"",
|
|
192305
|
+
`**Record what worked, not only what failed.** Store validated approaches and explicit user confirmations alongside corrections. Saving only failures drifts behavior away from what the user already accepted; a clear "yes, that's right" is feedback worth keeping too.`,
|
|
192306
|
+
"",
|
|
192307
|
+
"**Recalled memory is a claim about the past.** A memory naming a specific file, function, or flag describes the past at write time \u2014 check the file exists or grep the symbol before recommending it. If the user says to ignore or not use memory, proceed as if memory were empty: do not apply, cite, compare, or mention stored content.",
|
|
192308
|
+
"",
|
|
192063
192309
|
"## When to resolve memory",
|
|
192064
192310
|
"",
|
|
192065
192311
|
"Use `memorix_resolve` when a task is done or a bug is fixed. This keeps future searches focused on active work instead of surfacing completed items.",
|
|
192066
192312
|
"",
|
|
192313
|
+
"## End sessions with a summary",
|
|
192314
|
+
"",
|
|
192315
|
+
"When a session finishes, call `memorix_session_end` with a short structured summary so the next agent can resume. Recommended sections:",
|
|
192316
|
+
"- **Goal** \u2014 what this session was working on",
|
|
192317
|
+
"- **Discoveries** \u2014 findings, gotchas, learnings",
|
|
192318
|
+
"- **Accomplished** \u2014 completed items, plus PENDING items for the next session",
|
|
192319
|
+
"- **Relevant Files** \u2014 paths and what changed",
|
|
192320
|
+
"",
|
|
192067
192321
|
"## Tools quick reference",
|
|
192068
192322
|
"",
|
|
192069
192323
|
"| Tool | Use when |",
|
|
@@ -192233,7 +192487,10 @@ var init_installers = __esm({
|
|
|
192233
192487
|
windsurf: { project: path29.join(".windsurf", "skills"), global: path29.join(".windsurf", "skills") },
|
|
192234
192488
|
kiro: { project: path29.join(".kiro", "skills"), global: path29.join(".kiro", "skills") },
|
|
192235
192489
|
opencode: { project: path29.join(".opencode", "skills"), global: path29.join(".config", "opencode", "skills") },
|
|
192236
|
-
trae: { project: path29.join(".trae", "skills"), global: path29.join(".trae", "skills") }
|
|
192490
|
+
trae: { project: path29.join(".trae", "skills"), global: path29.join(".trae", "skills") },
|
|
192491
|
+
// DSH's user skill root is <harness home>/skills; the global root below is
|
|
192492
|
+
// resolved to $DSH_HOME (or ~/.dsh) for dsh by installOfficialSkillsForAgent.
|
|
192493
|
+
dsh: { project: path29.join(".dsh", "skills"), global: "skills" }
|
|
192237
192494
|
};
|
|
192238
192495
|
PACKAGE_OWNED_HOOK_AGENTS = /* @__PURE__ */ new Set(["openclaw", "hermes", "omp"]);
|
|
192239
192496
|
}
|
|
@@ -192266,7 +192523,7 @@ __export(setup_exports, {
|
|
|
192266
192523
|
import { spawnSync } from "child_process";
|
|
192267
192524
|
import { existsSync as existsSync14 } from "fs";
|
|
192268
192525
|
import { copyFile as copyFile2, mkdir as mkdir6, readFile as readFile6, readdir as readdir3, rm as rm2, writeFile as writeFile7 } from "fs/promises";
|
|
192269
|
-
import { homedir as
|
|
192526
|
+
import { homedir as homedir26 } from "os";
|
|
192270
192527
|
import path30 from "path";
|
|
192271
192528
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
192272
192529
|
function getSetupAgentTargets() {
|
|
@@ -192390,7 +192647,7 @@ async function stripHookCaptureFromOpenClawBundle(bundlePath) {
|
|
|
192390
192647
|
function mergeHermesPluginEnabled(existingContent, pluginName) {
|
|
192391
192648
|
let config2 = {};
|
|
192392
192649
|
try {
|
|
192393
|
-
const loaded = existingContent ? (0,
|
|
192650
|
+
const loaded = existingContent ? (0, import_yaml5.parse)(existingContent) : {};
|
|
192394
192651
|
config2 = loaded && typeof loaded === "object" && !Array.isArray(loaded) ? loaded : {};
|
|
192395
192652
|
} catch {
|
|
192396
192653
|
config2 = {};
|
|
@@ -192399,7 +192656,7 @@ function mergeHermesPluginEnabled(existingContent, pluginName) {
|
|
|
192399
192656
|
const plugins = pluginsValue && typeof pluginsValue === "object" && !Array.isArray(pluginsValue) ? pluginsValue : {};
|
|
192400
192657
|
const enabled = Array.isArray(plugins.enabled) ? plugins.enabled.filter((value) => typeof value === "string") : [];
|
|
192401
192658
|
if (!enabled.includes(pluginName)) enabled.push(pluginName);
|
|
192402
|
-
return (0,
|
|
192659
|
+
return (0, import_yaml5.stringify)({
|
|
192403
192660
|
...config2,
|
|
192404
192661
|
plugins: {
|
|
192405
192662
|
...plugins,
|
|
@@ -192427,7 +192684,8 @@ function getMcpAdapter(agent) {
|
|
|
192427
192684
|
omp: new OmpMCPAdapter(),
|
|
192428
192685
|
kiro: new KiroMCPAdapter(),
|
|
192429
192686
|
opencode: new OpenCodeMCPAdapter(),
|
|
192430
|
-
trae: new TraeMCPAdapter()
|
|
192687
|
+
trae: new TraeMCPAdapter(),
|
|
192688
|
+
dsh: new DshMCPAdapter()
|
|
192431
192689
|
};
|
|
192432
192690
|
return adapters[agent];
|
|
192433
192691
|
}
|
|
@@ -192443,7 +192701,9 @@ function buildMemorixServer(mcp) {
|
|
|
192443
192701
|
return {
|
|
192444
192702
|
name: "memorix",
|
|
192445
192703
|
command: "memorix",
|
|
192446
|
-
|
|
192704
|
+
// The installed surface must expose every tool the generated guidance
|
|
192705
|
+
// teaches. lite covers the full taught set; micro would hide half of it.
|
|
192706
|
+
args: ["serve", "--mode", "lite"]
|
|
192447
192707
|
};
|
|
192448
192708
|
}
|
|
192449
192709
|
function mergeJsonMcpConfig(existingContent, generatedContent) {
|
|
@@ -192547,7 +192807,7 @@ function isOwnedLegacyCodexMcp(content) {
|
|
|
192547
192807
|
const server = new CodexMCPAdapter().parse(content).find((entry) => entry.name === "memorix");
|
|
192548
192808
|
return Boolean(server && isLegacyCodexMemorixNodeServer(server));
|
|
192549
192809
|
}
|
|
192550
|
-
async function removeLegacyCodexMemorixMcpConfig(configPath = path30.join(
|
|
192810
|
+
async function removeLegacyCodexMemorixMcpConfig(configPath = path30.join(homedir26(), ".codex", "config.toml")) {
|
|
192551
192811
|
let existingContent;
|
|
192552
192812
|
try {
|
|
192553
192813
|
existingContent = await readFile6(configPath, "utf-8");
|
|
@@ -192604,7 +192864,7 @@ async function removeOwnedLegacyCodexPluginFolder(homeDir) {
|
|
|
192604
192864
|
}
|
|
192605
192865
|
}
|
|
192606
192866
|
async function migrateLegacyCodexIntegration(options = {}) {
|
|
192607
|
-
const homeDir = options.homeDir ??
|
|
192867
|
+
const homeDir = options.homeDir ?? homedir26();
|
|
192608
192868
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
192609
192869
|
const configPath = path30.join(homeDir, ".codex", "config.toml");
|
|
192610
192870
|
let mcp = "missing";
|
|
@@ -192635,14 +192895,14 @@ async function migrateLegacyCodexIntegration(options = {}) {
|
|
|
192635
192895
|
function mergeYamlMcpConfig(existingContent, generatedContent) {
|
|
192636
192896
|
let existing = {};
|
|
192637
192897
|
try {
|
|
192638
|
-
const loaded = existingContent ? (0,
|
|
192898
|
+
const loaded = existingContent ? (0, import_yaml5.parse)(existingContent) : {};
|
|
192639
192899
|
existing = loaded && typeof loaded === "object" && !Array.isArray(loaded) ? loaded : {};
|
|
192640
192900
|
} catch {
|
|
192641
192901
|
existing = {};
|
|
192642
192902
|
}
|
|
192643
192903
|
let generated = {};
|
|
192644
192904
|
try {
|
|
192645
|
-
const loaded = (0,
|
|
192905
|
+
const loaded = (0, import_yaml5.parse)(generatedContent);
|
|
192646
192906
|
generated = loaded && typeof loaded === "object" && !Array.isArray(loaded) ? loaded : {};
|
|
192647
192907
|
} catch {
|
|
192648
192908
|
return generatedContent.endsWith("\n") ? generatedContent : `${generatedContent}
|
|
@@ -192658,7 +192918,46 @@ function mergeYamlMcpConfig(existingContent, generatedContent) {
|
|
|
192658
192918
|
...generatedServers
|
|
192659
192919
|
}
|
|
192660
192920
|
};
|
|
192661
|
-
return (0,
|
|
192921
|
+
return (0, import_yaml5.stringify)(merged, { lineWidth: 0 });
|
|
192922
|
+
}
|
|
192923
|
+
function mergeDshPatchConfig(existingContent, generatedContent) {
|
|
192924
|
+
const generatedTrimmed = generatedContent.trimEnd();
|
|
192925
|
+
if (!existingContent?.trim()) {
|
|
192926
|
+
return generatedTrimmed.endsWith("\n") ? generatedTrimmed : `${generatedTrimmed}
|
|
192927
|
+
`;
|
|
192928
|
+
}
|
|
192929
|
+
const isMemorixInsertRow = (row) => {
|
|
192930
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) return false;
|
|
192931
|
+
const record2 = row;
|
|
192932
|
+
if (record2.name !== "@deepseek-ai/dsh-mcp-client") return false;
|
|
192933
|
+
const config2 = record2.config;
|
|
192934
|
+
return Boolean(
|
|
192935
|
+
config2 && typeof config2 === "object" && !Array.isArray(config2) && config2.serverName === "memorix"
|
|
192936
|
+
);
|
|
192937
|
+
};
|
|
192938
|
+
const opContainsMemorixRow = (op) => {
|
|
192939
|
+
if (!op || typeof op !== "object" || Array.isArray(op)) return false;
|
|
192940
|
+
const insert4 = op.insert;
|
|
192941
|
+
return Array.isArray(insert4) && insert4.some(isMemorixInsertRow);
|
|
192942
|
+
};
|
|
192943
|
+
let existingDocument;
|
|
192944
|
+
try {
|
|
192945
|
+
existingDocument = (0, import_yaml5.parse)(existingContent);
|
|
192946
|
+
} catch {
|
|
192947
|
+
return `${existingContent.trimEnd()}
|
|
192948
|
+
|
|
192949
|
+
${generatedTrimmed}
|
|
192950
|
+
`;
|
|
192951
|
+
}
|
|
192952
|
+
if (!Array.isArray(existingDocument)) {
|
|
192953
|
+
return `${existingContent.trimEnd()}
|
|
192954
|
+
|
|
192955
|
+
${generatedTrimmed}
|
|
192956
|
+
`;
|
|
192957
|
+
}
|
|
192958
|
+
const kept = existingDocument.filter((op) => !opContainsMemorixRow(op));
|
|
192959
|
+
const merged = [...kept, ...(0, import_yaml5.parse)(generatedContent)];
|
|
192960
|
+
return (0, import_yaml5.stringify)(merged, { lineWidth: 0 }) + "\n";
|
|
192662
192961
|
}
|
|
192663
192962
|
async function installMcpConfig(options) {
|
|
192664
192963
|
const adapter = getMcpAdapter(options.agent);
|
|
@@ -192675,7 +192974,7 @@ async function installMcpConfig(options) {
|
|
|
192675
192974
|
existingContent = null;
|
|
192676
192975
|
}
|
|
192677
192976
|
const generated = adapter.generate([server]);
|
|
192678
|
-
const content = options.agent === "codex" ? mergeTomlMcpConfig(existingContent, generated) : options.agent === "hermes" ? mergeYamlMcpConfig(existingContent, generated) : mergeJsonMcpConfig(existingContent, generated);
|
|
192977
|
+
const content = options.agent === "codex" ? mergeTomlMcpConfig(existingContent, generated) : options.agent === "hermes" ? mergeYamlMcpConfig(existingContent, generated) : options.agent === "dsh" ? mergeDshPatchConfig(existingContent, generated) : mergeJsonMcpConfig(existingContent, generated);
|
|
192679
192978
|
await mkdir6(path30.dirname(configPath), { recursive: true });
|
|
192680
192979
|
await writeFile7(configPath, content, "utf-8");
|
|
192681
192980
|
return { agent: options.agent, configPath, transport: options.mcp };
|
|
@@ -192766,7 +193065,7 @@ async function stripCodeBuddyHookCapture(pluginPath) {
|
|
|
192766
193065
|
await writeFile7(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
192767
193066
|
}
|
|
192768
193067
|
async function installCodeBuddyPluginPackage(options = {}) {
|
|
192769
|
-
const home = options.homeDir ??
|
|
193068
|
+
const home = options.homeDir ?? homedir26();
|
|
192770
193069
|
const packageRoot = findPackageRoot();
|
|
192771
193070
|
const source = path30.join(packageRoot, "plugins", "codebuddy", "memorix");
|
|
192772
193071
|
if (!existsSync14(source)) throw new Error(`CodeBuddy plugin template not found: ${source}`);
|
|
@@ -192786,7 +193085,7 @@ async function installCodeBuddyPluginPackage(options = {}) {
|
|
|
192786
193085
|
};
|
|
192787
193086
|
}
|
|
192788
193087
|
async function installPluginPackage(options) {
|
|
192789
|
-
const home = options.homeDir ??
|
|
193088
|
+
const home = options.homeDir ?? homedir26();
|
|
192790
193089
|
const packageRoot = findPackageRoot();
|
|
192791
193090
|
const source = path30.join(packageRoot, "plugins", options.agent, "memorix");
|
|
192792
193091
|
const includeHooks = options.includeHooks ?? true;
|
|
@@ -192835,7 +193134,7 @@ async function installPluginPackage(options) {
|
|
|
192835
193134
|
};
|
|
192836
193135
|
}
|
|
192837
193136
|
async function installGeminiExtensionPackage(options = {}) {
|
|
192838
|
-
const home = options.homeDir ??
|
|
193137
|
+
const home = options.homeDir ?? homedir26();
|
|
192839
193138
|
const packageRoot = findPackageRoot();
|
|
192840
193139
|
const source = path30.join(packageRoot, "plugins", "gemini", "memorix");
|
|
192841
193140
|
if (!existsSync14(source)) {
|
|
@@ -192855,7 +193154,7 @@ async function installAntigravityPluginPackage(options = {}) {
|
|
|
192855
193154
|
if (!existsSync14(source)) {
|
|
192856
193155
|
throw new Error(`Antigravity plugin template not found: ${source}`);
|
|
192857
193156
|
}
|
|
192858
|
-
const pluginPath = options.global === false ? path30.join(options.projectRoot ?? process.cwd(), ".agents", "plugins", "memorix") : path30.join(options.homeDir ??
|
|
193157
|
+
const pluginPath = options.global === false ? path30.join(options.projectRoot ?? process.cwd(), ".agents", "plugins", "memorix") : path30.join(options.homeDir ?? homedir26(), ".gemini", "config", "plugins", "memorix");
|
|
192859
193158
|
await copyDir(source, pluginPath);
|
|
192860
193159
|
if (options.includeHooks === false) {
|
|
192861
193160
|
await rm2(path30.join(pluginPath, "hooks.json"), { force: true });
|
|
@@ -192873,7 +193172,7 @@ async function installPiPackage(options = {}) {
|
|
|
192873
193172
|
if (!existsSync14(source)) {
|
|
192874
193173
|
throw new Error(`Pi package template not found: ${source}`);
|
|
192875
193174
|
}
|
|
192876
|
-
const defaultRoot = options.global ? path30.join(options.homeDir ??
|
|
193175
|
+
const defaultRoot = options.global ? path30.join(options.homeDir ?? homedir26(), ".pi", "agent", "packages") : path30.join(process.cwd(), ".pi", "packages");
|
|
192877
193176
|
const packagePath = options.packageDir ?? path30.join(defaultRoot, "memorix");
|
|
192878
193177
|
await copyDir(source, packagePath);
|
|
192879
193178
|
await writeOfficialSkills(path30.join(packagePath, "skills"));
|
|
@@ -192885,7 +193184,7 @@ async function installPiPackage(options = {}) {
|
|
|
192885
193184
|
};
|
|
192886
193185
|
}
|
|
192887
193186
|
async function installOpenClawBundlePackage(options = {}) {
|
|
192888
|
-
const home = options.homeDir ??
|
|
193187
|
+
const home = options.homeDir ?? homedir26();
|
|
192889
193188
|
const packageRoot = findPackageRoot();
|
|
192890
193189
|
const source = path30.join(packageRoot, "plugins", "openclaw", "memorix");
|
|
192891
193190
|
if (!existsSync14(source)) {
|
|
@@ -192934,7 +193233,7 @@ async function installOmpPackage(options = {}) {
|
|
|
192934
193233
|
if (!existsSync14(source)) {
|
|
192935
193234
|
throw new Error(`Oh-my-Pi package template not found: ${source}`);
|
|
192936
193235
|
}
|
|
192937
|
-
const defaultRoot = options.global ? path30.join(options.homeDir ??
|
|
193236
|
+
const defaultRoot = options.global ? path30.join(options.homeDir ?? homedir26(), ".omp", "agent", "packages") : path30.join(process.cwd(), ".omp", "packages");
|
|
192938
193237
|
const packagePath = options.packageDir ?? path30.join(defaultRoot, "memorix");
|
|
192939
193238
|
await copyDir(source, packagePath);
|
|
192940
193239
|
await writeOfficialSkills(path30.join(packagePath, "skills"));
|
|
@@ -193208,7 +193507,7 @@ ${result.stdout || ""}`.toLowerCase();
|
|
|
193208
193507
|
}
|
|
193209
193508
|
async function installAgentSetup(agent, plan, global2) {
|
|
193210
193509
|
const { installAgentGuidance: installAgentGuidance2, installHooks: installHooks2 } = await Promise.resolve().then(() => (init_installers(), installers_exports));
|
|
193211
|
-
const targetRoot = global2 ?
|
|
193510
|
+
const targetRoot = global2 ? homedir26() : process.cwd();
|
|
193212
193511
|
const hasPluginPackage = plan.actions.includes("plugin-package") && PLUGIN_PACKAGE_AGENTS.has(agent);
|
|
193213
193512
|
const hasExtensionPackage = plan.actions.includes("extension-package") && agent === "gemini-cli";
|
|
193214
193513
|
const hasPiPackage = plan.actions.includes("pi-package") && agent === "pi";
|
|
@@ -193394,14 +193693,14 @@ function printSetupIntegrationRows() {
|
|
|
193394
193693
|
].join("\n");
|
|
193395
193694
|
ye2(table, "Memorix integrations");
|
|
193396
193695
|
}
|
|
193397
|
-
var
|
|
193696
|
+
var import_yaml5, PLUGIN_PACKAGE_AGENTS, EXTENSION_PACKAGE_AGENTS, PI_PACKAGE_AGENTS, OPENCLAW_BUNDLE_AGENTS, ANTIGRAVITY_PLUGIN_AGENTS, HERMES_PLUGIN_AGENTS, OMP_PACKAGE_AGENTS, CODEBUDDY_PLUGIN_AGENTS, PACKAGE_OWNED_INTEGRATION_AGENTS, SUPPORTED_SETUP_AGENTS, getSetupIntegrationRows2, setup_default;
|
|
193398
193697
|
var init_setup = __esm({
|
|
193399
193698
|
"src/cli/commands/setup.ts"() {
|
|
193400
193699
|
"use strict";
|
|
193401
193700
|
init_esm_shims();
|
|
193402
193701
|
init_dist2();
|
|
193403
193702
|
init_dist4();
|
|
193404
|
-
|
|
193703
|
+
import_yaml5 = __toESM(require_dist(), 1);
|
|
193405
193704
|
init_claude_code();
|
|
193406
193705
|
init_codex();
|
|
193407
193706
|
init_cursor();
|
|
@@ -193415,6 +193714,7 @@ var init_setup = __esm({
|
|
|
193415
193714
|
init_kiro();
|
|
193416
193715
|
init_opencode();
|
|
193417
193716
|
init_trae();
|
|
193717
|
+
init_dsh();
|
|
193418
193718
|
init_codebuddy();
|
|
193419
193719
|
init_registry2();
|
|
193420
193720
|
init_official_skills();
|
|
@@ -193443,6 +193743,7 @@ var init_setup = __esm({
|
|
|
193443
193743
|
"omp",
|
|
193444
193744
|
"kiro",
|
|
193445
193745
|
"trae",
|
|
193746
|
+
"dsh",
|
|
193446
193747
|
"pi"
|
|
193447
193748
|
];
|
|
193448
193749
|
getSetupIntegrationRows2 = getSetupIntegrationRows;
|
|
@@ -193454,7 +193755,7 @@ var init_setup = __esm({
|
|
|
193454
193755
|
args: {
|
|
193455
193756
|
agent: {
|
|
193456
193757
|
type: "string",
|
|
193457
|
-
description: "Target agent (claude, codex, codebuddy, opencode, cursor, windsurf, copilot, gemini-cli, antigravity, openclaw, hermes, omp, kiro, trae, pi, all)",
|
|
193758
|
+
description: "Target agent (claude, codex, codebuddy, opencode, cursor, windsurf, copilot, gemini-cli, antigravity, openclaw, hermes, omp, kiro, trae, dsh, pi, all)",
|
|
193458
193759
|
required: false
|
|
193459
193760
|
},
|
|
193460
193761
|
mcp: {
|
|
@@ -193526,6 +193827,7 @@ var init_setup = __esm({
|
|
|
193526
193827
|
{ value: "hermes", label: "Hermes Agent", hint: "plugin + hooks + commands + skills + MCP" },
|
|
193527
193828
|
{ value: "omp", label: "Oh-my-Pi", hint: "package + extension + command + MCP" },
|
|
193528
193829
|
{ value: "pi", label: "Pi coding agent", hint: "package + extension + skill" },
|
|
193830
|
+
{ value: "dsh", label: "DeepSeek Harness", hint: "MCP patch + AGENTS.md + skills" },
|
|
193529
193831
|
{ value: "opencode", label: "OpenCode", hint: "local plugin + AGENTS.md + MCP" },
|
|
193530
193832
|
{ value: "windsurf", label: "Windsurf", hint: "rules + hooks + MCP" },
|
|
193531
193833
|
{ value: "all", label: "All supported agents", hint: "install detected-compatible files" }
|
|
@@ -193585,7 +193887,7 @@ var config_path_exports = {};
|
|
|
193585
193887
|
__export(config_path_exports, {
|
|
193586
193888
|
default: () => config_path_default
|
|
193587
193889
|
});
|
|
193588
|
-
import { homedir as
|
|
193890
|
+
import { homedir as homedir27 } from "os";
|
|
193589
193891
|
var config_path_default;
|
|
193590
193892
|
var init_config_path = __esm({
|
|
193591
193893
|
"src/cli/commands/config-path.ts"() {
|
|
@@ -193603,7 +193905,7 @@ var init_config_path = __esm({
|
|
|
193603
193905
|
run: async () => {
|
|
193604
193906
|
const project = detectProject(process.cwd());
|
|
193605
193907
|
ye2([
|
|
193606
|
-
`Global: ${getGlobalConfigTomlPath(
|
|
193908
|
+
`Global: ${getGlobalConfigTomlPath(homedir27())}`,
|
|
193607
193909
|
`Project: ${project ? getProjectConfigTomlPath(project.rootPath) : "not inside a git project"}`
|
|
193608
193910
|
].join("\n"), "Memorix config");
|
|
193609
193911
|
}
|
|
@@ -193679,7 +193981,7 @@ __export(config_migrate_exports, {
|
|
|
193679
193981
|
serializeResolvedConfigToToml: () => serializeResolvedConfigToToml
|
|
193680
193982
|
});
|
|
193681
193983
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
193682
|
-
import { homedir as
|
|
193984
|
+
import { homedir as homedir28 } from "os";
|
|
193683
193985
|
import { dirname as dirname4 } from "path";
|
|
193684
193986
|
function serializeResolvedConfigToToml(config2, options = {}) {
|
|
193685
193987
|
const includeSecrets = options.includeSecrets === true;
|
|
@@ -193772,7 +194074,7 @@ var init_config_migrate = __esm({
|
|
|
193772
194074
|
v3.error("Not inside a git project. Use `memorix config migrate --global` for global config.");
|
|
193773
194075
|
return;
|
|
193774
194076
|
}
|
|
193775
|
-
const target = isGlobal ? getGlobalConfigTomlPath(
|
|
194077
|
+
const target = isGlobal ? getGlobalConfigTomlPath(homedir28()) : getProjectConfigTomlPath(project.rootPath);
|
|
193776
194078
|
const resolved = getResolvedConfig({ projectRoot: project?.rootPath ?? null });
|
|
193777
194079
|
const content = serializeResolvedConfigToToml(resolved, { includeSecrets: isGlobal });
|
|
193778
194080
|
mkdirSync2(dirname4(target), { recursive: true });
|
|
@@ -193784,8 +194086,8 @@ var init_config_migrate = __esm({
|
|
|
193784
194086
|
});
|
|
193785
194087
|
|
|
193786
194088
|
// src/cli/commands/integrate-shared.ts
|
|
193787
|
-
import { homedir as
|
|
193788
|
-
function getIntegrationTargetRoot(useGlobalDefaults, cwd, homeDir =
|
|
194089
|
+
import { homedir as homedir29 } from "os";
|
|
194090
|
+
function getIntegrationTargetRoot(useGlobalDefaults, cwd, homeDir = homedir29()) {
|
|
193789
194091
|
return useGlobalDefaults ? homeDir : cwd;
|
|
193790
194092
|
}
|
|
193791
194093
|
function getIntegrationScopeLabel(useGlobalDefaults) {
|
|
@@ -193822,7 +194124,8 @@ function getAgentLabel(agent) {
|
|
|
193822
194124
|
codex: "Codex",
|
|
193823
194125
|
antigravity: "Antigravity",
|
|
193824
194126
|
"gemini-cli": "Gemini CLI",
|
|
193825
|
-
trae: "Trae"
|
|
194127
|
+
trae: "Trae",
|
|
194128
|
+
dsh: "DeepSeek Harness"
|
|
193826
194129
|
};
|
|
193827
194130
|
return labels[agent] || agent;
|
|
193828
194131
|
}
|
|
@@ -193837,7 +194140,8 @@ function getAgentHint(agent) {
|
|
|
193837
194140
|
codex: "AGENTS.md",
|
|
193838
194141
|
antigravity: "plugin + MCP + hooks + skills",
|
|
193839
194142
|
"gemini-cli": "settings + GEMINI.md",
|
|
193840
|
-
trae: "rules"
|
|
194143
|
+
trae: "rules",
|
|
194144
|
+
dsh: "MCP patch + AGENTS.md + skills"
|
|
193841
194145
|
};
|
|
193842
194146
|
return hints[agent] || "integration files";
|
|
193843
194147
|
}
|
|
@@ -194122,6 +194426,37 @@ function renderTaskWorksetPrompt(input) {
|
|
|
194122
194426
|
trust: "source-backed"
|
|
194123
194427
|
});
|
|
194124
194428
|
appendLine(lines, "Task lens: " + input.lens, maxTokens, omitted, "lens");
|
|
194429
|
+
if (input.alwaysOn) {
|
|
194430
|
+
const hasAlwaysOn = input.alwaysOn.profile.length > 0 || Boolean(input.alwaysOn.state) || input.alwaysOn.durable.length > 0;
|
|
194431
|
+
if (hasAlwaysOn) {
|
|
194432
|
+
appendLine(lines, "", maxTokens, omitted, "always-on-heading");
|
|
194433
|
+
appendLine(lines, "You and this workspace", maxTokens, omitted, "always-on-heading");
|
|
194434
|
+
for (const profile of input.alwaysOn.profile.slice(0, 2)) {
|
|
194435
|
+
appendLine(lines, "- " + short(profile, 26), maxTokens, omitted, "always-on-profile", selected, {
|
|
194436
|
+
kind: "memory",
|
|
194437
|
+
id: "profile",
|
|
194438
|
+
reason: "user profile memory",
|
|
194439
|
+
trust: "source-backed"
|
|
194440
|
+
});
|
|
194441
|
+
}
|
|
194442
|
+
if (input.alwaysOn.state) {
|
|
194443
|
+
appendLine(lines, "- Recently: " + short(input.alwaysOn.state, 40), maxTokens, omitted, "always-on-state", selected, {
|
|
194444
|
+
kind: "continuation",
|
|
194445
|
+
id: "workspace-state",
|
|
194446
|
+
reason: "latest session summary for this workspace",
|
|
194447
|
+
trust: "historical"
|
|
194448
|
+
});
|
|
194449
|
+
}
|
|
194450
|
+
for (const durable of input.alwaysOn.durable.slice(0, 2)) {
|
|
194451
|
+
appendLine(lines, "- " + short(durable, 28), maxTokens, omitted, "always-on-durable", selected, {
|
|
194452
|
+
kind: "durable-memory",
|
|
194453
|
+
id: "durable-always",
|
|
194454
|
+
reason: "recent durable memory for this workspace",
|
|
194455
|
+
trust: "source-backed"
|
|
194456
|
+
});
|
|
194457
|
+
}
|
|
194458
|
+
}
|
|
194459
|
+
}
|
|
194125
194460
|
const hasContinuation = Boolean(
|
|
194126
194461
|
input.continuation?.previousSession || (input.continuation?.memories.length ?? 0) > 0 || input.continuation?.compactCheckpoint
|
|
194127
194462
|
);
|
|
@@ -194592,6 +194927,7 @@ async function buildTaskWorkset(input) {
|
|
|
194592
194927
|
version: "1.3",
|
|
194593
194928
|
task,
|
|
194594
194929
|
lens: input.lens,
|
|
194930
|
+
...input.alwaysOn && (input.alwaysOn.profile.length > 0 || input.alwaysOn.state || input.alwaysOn.durable.length > 0) ? { alwaysOn: input.alwaysOn } : {},
|
|
194595
194931
|
currentFacts: input.currentFacts?.map((fact) => fact.startsWith("Historical note:") ? short(fact, 48) : short(fact, 28)).slice(0, 4) ?? [],
|
|
194596
194932
|
...continuation ? { continuation } : {},
|
|
194597
194933
|
...input.codeState ? { codeState: short(input.codeState, 28) } : {},
|
|
@@ -194830,7 +195166,7 @@ __export(external_provider_exports, {
|
|
|
194830
195166
|
});
|
|
194831
195167
|
import { spawn as spawn5 } from "child_process";
|
|
194832
195168
|
import { existsSync as existsSync16, readFileSync as readFileSync9 } from "fs";
|
|
194833
|
-
import { delimiter, dirname as dirname5, extname, isAbsolute as isAbsolute2, join as
|
|
195169
|
+
import { delimiter, dirname as dirname5, extname, isAbsolute as isAbsolute2, join as join23, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
|
|
194834
195170
|
function boundedTimeout(value) {
|
|
194835
195171
|
if (!Number.isFinite(value)) return DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS;
|
|
194836
195172
|
return Math.max(100, Math.min(Math.floor(value), MAX_EXTERNAL_CODEGRAPH_TIMEOUT_MS));
|
|
@@ -194859,10 +195195,10 @@ function resolveCommandCandidates(command) {
|
|
|
194859
195195
|
}
|
|
194860
195196
|
const names = extname(requested) ? [requested] : process.platform === "win32" ? [requested + ".exe", requested + ".cmd", requested + ".js", requested] : [requested];
|
|
194861
195197
|
const directories = [
|
|
194862
|
-
...process.platform === "win32" && process.env.LOCALAPPDATA ? [
|
|
195198
|
+
...process.platform === "win32" && process.env.LOCALAPPDATA ? [join23(process.env.LOCALAPPDATA, "codegraph", "current", "bin")] : [],
|
|
194863
195199
|
...(process.env.PATH ?? "").split(delimiter).filter(Boolean)
|
|
194864
195200
|
];
|
|
194865
|
-
return [...new Set(directories.flatMap((directory) => names.map((name) =>
|
|
195201
|
+
return [...new Set(directories.flatMap((directory) => names.map((name) => join23(directory, name))))];
|
|
194866
195202
|
}
|
|
194867
195203
|
function resolveLaunch(command) {
|
|
194868
195204
|
for (const candidate2 of resolveCommandCandidates(command)) {
|
|
@@ -194870,8 +195206,8 @@ function resolveLaunch(command) {
|
|
|
194870
195206
|
const extension3 = extname(candidate2).toLowerCase();
|
|
194871
195207
|
if (extension3 === ".cmd") {
|
|
194872
195208
|
const bundleRoot = resolve3(dirname5(candidate2), "..");
|
|
194873
|
-
const node =
|
|
194874
|
-
const entry =
|
|
195209
|
+
const node = join23(bundleRoot, "node.exe");
|
|
195210
|
+
const entry = join23(bundleRoot, "lib", "dist", "bin", "codegraph.js");
|
|
194875
195211
|
if (existsSync16(node) && existsSync16(entry)) {
|
|
194876
195212
|
return { executable: node, prefixArgs: ["--liftoff-only", entry] };
|
|
194877
195213
|
}
|
|
@@ -195002,7 +195338,7 @@ async function inspectExternalCodeGraph(input) {
|
|
|
195002
195338
|
const health2 = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
|
|
195003
195339
|
return { health: health2, quality: providerQuality({ mode, health: health2 }) };
|
|
195004
195340
|
}
|
|
195005
|
-
if (!existsSync16(
|
|
195341
|
+
if (!existsSync16(join23(input.projectRoot, ".codegraph"))) {
|
|
195006
195342
|
const health2 = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
|
|
195007
195343
|
return { health: health2, quality: providerQuality({ mode, health: health2 }) };
|
|
195008
195344
|
}
|
|
@@ -196641,6 +196977,33 @@ function activeProjectObservations(observations2, projectId) {
|
|
|
196641
196977
|
function deliveryEligibleProjectObservations(observations2, projectId) {
|
|
196642
196978
|
return activeProjectObservations(observations2, projectId).filter((observation) => isEligibleForAutomaticDelivery(observation));
|
|
196643
196979
|
}
|
|
196980
|
+
async function buildAlwaysOnBlock(input) {
|
|
196981
|
+
const profile = filterReadableObservations(input.eligible, input.reader).filter((observation) => observation.visibility === "personal" && observation.entityName === "user-profile").slice(0, 2).map((observation) => compactContinuationText(observation.title, 22));
|
|
196982
|
+
let state;
|
|
196983
|
+
try {
|
|
196984
|
+
await initSessionStore(input.dataDir);
|
|
196985
|
+
const { getSessionStore: getSessionStore2 } = await Promise.resolve().then(() => (init_session_store(), session_store_exports));
|
|
196986
|
+
const sessions = await getSessionStore2().loadByProject(input.projectId);
|
|
196987
|
+
const latest = sessions.filter((session) => session.endedAt && session.summary?.trim()).sort((a4, b4) => Date.parse(b4.endedAt ?? "") - Date.parse(a4.endedAt ?? ""))[0];
|
|
196988
|
+
if (latest?.summary) state = compactContinuationText(latest.summary, 40);
|
|
196989
|
+
} catch {
|
|
196990
|
+
}
|
|
196991
|
+
const durable = [];
|
|
196992
|
+
try {
|
|
196993
|
+
const items = await listLongTermMemories({
|
|
196994
|
+
dataDir: input.dataDir,
|
|
196995
|
+
reader: {
|
|
196996
|
+
projectId: input.projectId,
|
|
196997
|
+
...input.reader.agentId ? { agentId: input.reader.agentId } : {},
|
|
196998
|
+
...input.reader.isTeamMember ? { isTeamMember: true } : {}
|
|
196999
|
+
},
|
|
197000
|
+
limit: 10
|
|
197001
|
+
});
|
|
197002
|
+
durable.push(...items.filter((item) => item.memory.state === "approved").sort((a4, b4) => (b4.memory.updatedAt ?? "").localeCompare(a4.memory.updatedAt ?? "")).slice(0, 2).map((item) => item.memory.kind + ": " + compactContinuationText(item.memory.title, 22)));
|
|
197003
|
+
} catch {
|
|
197004
|
+
}
|
|
197005
|
+
return { profile, state, durable };
|
|
197006
|
+
}
|
|
196644
197007
|
function decideRefresh(input) {
|
|
196645
197008
|
if (input.mode === "never") {
|
|
196646
197009
|
return { performed: false, reason: "disabled", message: "Automatic project scan disabled." };
|
|
@@ -196845,12 +197208,19 @@ async function buildAutoProjectContext(input) {
|
|
|
196845
197208
|
};
|
|
196846
197209
|
}
|
|
196847
197210
|
}
|
|
197211
|
+
const alwaysOn = await buildAlwaysOnBlock({
|
|
197212
|
+
dataDir: input.dataDir,
|
|
197213
|
+
projectId: input.project.id,
|
|
197214
|
+
reader: input.reader ?? { projectId: input.project.id },
|
|
197215
|
+
eligible: deliveryEligibleProjectObservations(input.observations, input.project.id)
|
|
197216
|
+
});
|
|
196848
197217
|
const workset = await buildTaskWorkset({
|
|
196849
197218
|
projectId: input.project.id,
|
|
196850
197219
|
dataDir: input.dataDir,
|
|
196851
197220
|
...task ? { task } : {},
|
|
196852
197221
|
lens: lens.id,
|
|
196853
197222
|
startHere,
|
|
197223
|
+
...alwaysOn.profile.length > 0 || alwaysOn.state || alwaysOn.durable.length > 0 ? { alwaysOn } : {},
|
|
196854
197224
|
...externalOutline ? { semanticCode: externalOutline } : {},
|
|
196855
197225
|
providerQuality: providerQuality2,
|
|
196856
197226
|
currentFacts: worksetFactLines(currentFacts),
|
|
@@ -197033,7 +197403,16 @@ function formatAutoProjectContextSummary(context) {
|
|
|
197033
197403
|
lensLine(context),
|
|
197034
197404
|
"",
|
|
197035
197405
|
...formatCurrentFactsLines(context.currentFacts),
|
|
197036
|
-
""
|
|
197406
|
+
""
|
|
197407
|
+
].filter(Boolean);
|
|
197408
|
+
if (context.workset.alwaysOn && (context.workset.alwaysOn.profile.length > 0 || context.workset.alwaysOn.state || context.workset.alwaysOn.durable.length > 0)) {
|
|
197409
|
+
lines.push("You and this workspace");
|
|
197410
|
+
for (const profile of context.workset.alwaysOn.profile.slice(0, 2)) lines.push(`- ${profile}`);
|
|
197411
|
+
if (context.workset.alwaysOn.state) lines.push(`- Recently: ${context.workset.alwaysOn.state}`);
|
|
197412
|
+
for (const durable of context.workset.alwaysOn.durable.slice(0, 2)) lines.push(`- ${durable}`);
|
|
197413
|
+
lines.push("");
|
|
197414
|
+
}
|
|
197415
|
+
lines.push(...[
|
|
197037
197416
|
`- Code memory: ${context.overview.code.files} files / ${context.overview.code.symbols} symbols / ${context.overview.code.refs} memory links`,
|
|
197038
197417
|
`- Code provider: ${context.providerQuality.selected} (${context.providerQuality.selectedQuality})`,
|
|
197039
197418
|
`- Languages: ${formatLanguages(context.overview)}`,
|
|
@@ -197042,7 +197421,7 @@ function formatAutoProjectContextSummary(context) {
|
|
|
197042
197421
|
`- Refresh: ${context.refresh.message}`,
|
|
197043
197422
|
"",
|
|
197044
197423
|
"Start here"
|
|
197045
|
-
].filter(Boolean);
|
|
197424
|
+
].filter(Boolean));
|
|
197046
197425
|
if (startHere.length > 0) {
|
|
197047
197426
|
startHere.forEach((path47, index) => lines.push(`${index + 1}. ${path47}`));
|
|
197048
197427
|
} else {
|
|
@@ -197166,6 +197545,8 @@ var init_auto_context = __esm({
|
|
|
197166
197545
|
init_store();
|
|
197167
197546
|
init_admission();
|
|
197168
197547
|
init_session();
|
|
197548
|
+
init_long_term();
|
|
197549
|
+
init_visibility();
|
|
197169
197550
|
init_session_store();
|
|
197170
197551
|
init_task_lens();
|
|
197171
197552
|
DEFAULT_MAX_AGE_MS = 10 * 60 * 1e3;
|
|
@@ -200229,8 +200610,8 @@ __export(engine_exports2, {
|
|
|
200229
200610
|
SkillsEngine: () => SkillsEngine
|
|
200230
200611
|
});
|
|
200231
200612
|
import { existsSync as existsSync18, readFileSync as readFileSync10, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync3 } from "fs";
|
|
200232
|
-
import { join as
|
|
200233
|
-
import { homedir as
|
|
200613
|
+
import { join as join24 } from "path";
|
|
200614
|
+
import { homedir as homedir30 } from "os";
|
|
200234
200615
|
var SKILLS_DIRS, SKILL_WORTHY_TYPES, MIN_OBS_FOR_SKILL, MIN_SCORE_FOR_SKILL, LOW_SIGNAL_TITLE_PATTERNS, LOW_SIGNAL_ENTITY_PATTERNS, COMMAND_TRACE_PATTERNS2, SkillsEngine;
|
|
200235
200616
|
var init_engine4 = __esm({
|
|
200236
200617
|
"src/skills/engine.ts"() {
|
|
@@ -200301,12 +200682,12 @@ var init_engine4 = __esm({
|
|
|
200301
200682
|
listSkills() {
|
|
200302
200683
|
const skills = [];
|
|
200303
200684
|
const seen = /* @__PURE__ */ new Set();
|
|
200304
|
-
const home =
|
|
200685
|
+
const home = homedir30();
|
|
200305
200686
|
for (const [agent, dirs] of Object.entries(SKILLS_DIRS)) {
|
|
200306
200687
|
for (const dir of dirs) {
|
|
200307
|
-
const paths = [
|
|
200688
|
+
const paths = [join24(this.projectRoot, dir)];
|
|
200308
200689
|
if (!this.skipGlobal) {
|
|
200309
|
-
paths.push(
|
|
200690
|
+
paths.push(join24(home, dir));
|
|
200310
200691
|
}
|
|
200311
200692
|
for (const skillsRoot of paths) {
|
|
200312
200693
|
if (!existsSync18(skillsRoot)) continue;
|
|
@@ -200316,7 +200697,7 @@ var init_engine4 = __esm({
|
|
|
200316
200697
|
if (!entry.isDirectory()) continue;
|
|
200317
200698
|
const name = entry.name;
|
|
200318
200699
|
if (seen.has(name)) continue;
|
|
200319
|
-
const skillMd =
|
|
200700
|
+
const skillMd = join24(skillsRoot, name, "SKILL.md");
|
|
200320
200701
|
if (!existsSync18(skillMd)) continue;
|
|
200321
200702
|
try {
|
|
200322
200703
|
const content = readFileSync10(skillMd, "utf-8");
|
|
@@ -200324,7 +200705,7 @@ var init_engine4 = __esm({
|
|
|
200324
200705
|
skills.push({
|
|
200325
200706
|
name,
|
|
200326
200707
|
description,
|
|
200327
|
-
sourcePath:
|
|
200708
|
+
sourcePath: join24(skillsRoot, name),
|
|
200328
200709
|
sourceAgent: agent,
|
|
200329
200710
|
content,
|
|
200330
200711
|
generated: false
|
|
@@ -200367,11 +200748,11 @@ var init_engine4 = __esm({
|
|
|
200367
200748
|
writeSkill(skill2, target) {
|
|
200368
200749
|
const dirs = SKILLS_DIRS[target];
|
|
200369
200750
|
if (!dirs || dirs.length === 0) return null;
|
|
200370
|
-
const targetDir =
|
|
200751
|
+
const targetDir = join24(this.projectRoot, dirs[0], skill2.name);
|
|
200371
200752
|
try {
|
|
200372
200753
|
mkdirSync3(targetDir, { recursive: true });
|
|
200373
|
-
writeFileSync3(
|
|
200374
|
-
return
|
|
200754
|
+
writeFileSync3(join24(targetDir, "SKILL.md"), skill2.content, "utf-8");
|
|
200755
|
+
return join24(dirs[0], skill2.name, "SKILL.md");
|
|
200375
200756
|
} catch {
|
|
200376
200757
|
return null;
|
|
200377
200758
|
}
|
|
@@ -201540,7 +201921,7 @@ var init_task_graph = __esm({
|
|
|
201540
201921
|
// src/orchestrate/context-collector.ts
|
|
201541
201922
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
201542
201923
|
import { readFileSync as readFileSync11, existsSync as existsSync19 } from "fs";
|
|
201543
|
-
import { join as
|
|
201924
|
+
import { join as join25 } from "path";
|
|
201544
201925
|
function normalizeEntryLimit(value, fallback) {
|
|
201545
201926
|
if (!Number.isSafeInteger(value) || value < 1) return fallback;
|
|
201546
201927
|
return Math.min(value, 500);
|
|
@@ -201615,7 +201996,7 @@ function collectFileTree(projectDir2, maxEntries) {
|
|
|
201615
201996
|
}
|
|
201616
201997
|
function collectDependencies(projectDir2) {
|
|
201617
201998
|
try {
|
|
201618
|
-
const pkgPath =
|
|
201999
|
+
const pkgPath = join25(projectDir2, "package.json");
|
|
201619
202000
|
if (!existsSync19(pkgPath)) return "";
|
|
201620
202001
|
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
201621
202002
|
const parts = [];
|
|
@@ -215855,8 +216236,8 @@ __export(engine_exports3, {
|
|
|
215855
216236
|
WorkspaceSyncEngine: () => WorkspaceSyncEngine
|
|
215856
216237
|
});
|
|
215857
216238
|
import { readFileSync as readFileSync13, readdirSync as readdirSync4, existsSync as existsSync22, cpSync, mkdirSync as mkdirSync5 } from "fs";
|
|
215858
|
-
import { join as
|
|
215859
|
-
import { homedir as
|
|
216239
|
+
import { join as join27 } from "path";
|
|
216240
|
+
import { homedir as homedir31 } from "os";
|
|
215860
216241
|
var WorkspaceSyncEngine;
|
|
215861
216242
|
var init_engine5 = __esm({
|
|
215862
216243
|
"src/workspace/engine.ts"() {
|
|
@@ -215928,9 +216309,9 @@ var init_engine5 = __esm({
|
|
|
215928
216309
|
const globalPath = adapter.getConfigPath();
|
|
215929
216310
|
const pathsToCheck = [configPath, globalPath];
|
|
215930
216311
|
if (target === "antigravity") {
|
|
215931
|
-
pathsToCheck.push(
|
|
215932
|
-
pathsToCheck.push(
|
|
215933
|
-
pathsToCheck.push(
|
|
216312
|
+
pathsToCheck.push(join27(this.projectRoot, ".gemini", "settings.json"));
|
|
216313
|
+
pathsToCheck.push(join27(homedir31(), ".gemini", "settings.json"));
|
|
216314
|
+
pathsToCheck.push(join27(homedir31(), ".gemini", "antigravity", "mcp_config.json"));
|
|
215934
216315
|
}
|
|
215935
216316
|
const merged = /* @__PURE__ */ new Map();
|
|
215936
216317
|
for (const path47 of pathsToCheck) {
|
|
@@ -216047,7 +216428,7 @@ var init_engine5 = __esm({
|
|
|
216047
216428
|
getTargetSkillsDir(target) {
|
|
216048
216429
|
const dirs = _WorkspaceSyncEngine.SKILLS_DIRS[target];
|
|
216049
216430
|
if (!dirs || dirs.length === 0) return null;
|
|
216050
|
-
return
|
|
216431
|
+
return join27(this.projectRoot, dirs[0]);
|
|
216051
216432
|
}
|
|
216052
216433
|
/**
|
|
216053
216434
|
* Scan all agent skills directories and collect unique skills.
|
|
@@ -216056,12 +216437,12 @@ var init_engine5 = __esm({
|
|
|
216056
216437
|
const skills = [];
|
|
216057
216438
|
const conflicts = [];
|
|
216058
216439
|
const seen = /* @__PURE__ */ new Map();
|
|
216059
|
-
const home =
|
|
216440
|
+
const home = homedir31();
|
|
216060
216441
|
for (const [agent, dirs] of Object.entries(_WorkspaceSyncEngine.SKILLS_DIRS)) {
|
|
216061
216442
|
for (const dir of dirs) {
|
|
216062
216443
|
const paths = [
|
|
216063
|
-
|
|
216064
|
-
|
|
216444
|
+
join27(this.projectRoot, dir),
|
|
216445
|
+
join27(home, dir)
|
|
216065
216446
|
];
|
|
216066
216447
|
for (const skillsRoot of paths) {
|
|
216067
216448
|
if (!existsSync22(skillsRoot)) continue;
|
|
@@ -216069,7 +216450,7 @@ var init_engine5 = __esm({
|
|
|
216069
216450
|
const entries = readdirSync4(skillsRoot, { withFileTypes: true });
|
|
216070
216451
|
for (const entry of entries) {
|
|
216071
216452
|
if (!entry.isDirectory()) continue;
|
|
216072
|
-
const skillMd =
|
|
216453
|
+
const skillMd = join27(skillsRoot, entry.name, "SKILL.md");
|
|
216073
216454
|
if (!existsSync22(skillMd)) continue;
|
|
216074
216455
|
let description = "";
|
|
216075
216456
|
try {
|
|
@@ -216081,7 +216462,7 @@ var init_engine5 = __esm({
|
|
|
216081
216462
|
const newEntry = {
|
|
216082
216463
|
name: entry.name,
|
|
216083
216464
|
description,
|
|
216084
|
-
sourcePath:
|
|
216465
|
+
sourcePath: join27(skillsRoot, entry.name),
|
|
216085
216466
|
sourceAgent: agent
|
|
216086
216467
|
};
|
|
216087
216468
|
const existing = seen.get(entry.name);
|
|
@@ -216118,7 +216499,7 @@ var init_engine5 = __esm({
|
|
|
216118
216499
|
}
|
|
216119
216500
|
for (const skill2 of skills) {
|
|
216120
216501
|
if (skill2.sourceAgent === target) continue;
|
|
216121
|
-
const dest =
|
|
216502
|
+
const dest = join27(targetDir, skill2.name);
|
|
216122
216503
|
if (existsSync22(dest)) {
|
|
216123
216504
|
skipped.push(`${skill2.name} (already exists in ${target})`);
|
|
216124
216505
|
continue;
|
|
@@ -216134,13 +216515,13 @@ var init_engine5 = __esm({
|
|
|
216134
216515
|
}
|
|
216135
216516
|
scanWorkflows() {
|
|
216136
216517
|
const workflows = [];
|
|
216137
|
-
const wfDir =
|
|
216518
|
+
const wfDir = join27(this.projectRoot, ".windsurf", "workflows");
|
|
216138
216519
|
if (!existsSync22(wfDir)) return workflows;
|
|
216139
216520
|
try {
|
|
216140
216521
|
const files = readdirSync4(wfDir).filter((f7) => f7.endsWith(".md"));
|
|
216141
216522
|
for (const file2 of files) {
|
|
216142
216523
|
try {
|
|
216143
|
-
const content = readFileSync13(
|
|
216524
|
+
const content = readFileSync13(join27(wfDir, file2), "utf-8");
|
|
216144
216525
|
workflows.push(this.workflowSyncer.parseWindsurfWorkflow(file2, content));
|
|
216145
216526
|
} catch {
|
|
216146
216527
|
}
|
|
@@ -216266,6 +216647,46 @@ var init_formation_timeout = __esm({
|
|
|
216266
216647
|
}
|
|
216267
216648
|
});
|
|
216268
216649
|
|
|
216650
|
+
// src/search/surfaced-registry.ts
|
|
216651
|
+
function touch(key) {
|
|
216652
|
+
const ids = registry2.get(key);
|
|
216653
|
+
if (!ids) return [];
|
|
216654
|
+
registry2.delete(key);
|
|
216655
|
+
registry2.set(key, ids);
|
|
216656
|
+
return ids;
|
|
216657
|
+
}
|
|
216658
|
+
function getSurfacedIds(key) {
|
|
216659
|
+
return [...touch(key)];
|
|
216660
|
+
}
|
|
216661
|
+
function recordSurfacedIds(key, ids) {
|
|
216662
|
+
if (ids.length === 0) return;
|
|
216663
|
+
let list = registry2.get(key) ?? [];
|
|
216664
|
+
const known = new Set(list);
|
|
216665
|
+
for (const id of ids) {
|
|
216666
|
+
if (known.has(id)) continue;
|
|
216667
|
+
known.add(id);
|
|
216668
|
+
list.push(id);
|
|
216669
|
+
}
|
|
216670
|
+
if (list.length > MAX_IDS) {
|
|
216671
|
+
list = list.slice(list.length - MAX_IDS);
|
|
216672
|
+
}
|
|
216673
|
+
registry2.set(key, list);
|
|
216674
|
+
if (registry2.size > MAX_KEYS) {
|
|
216675
|
+
const oldestKey = registry2.keys().next().value;
|
|
216676
|
+
if (oldestKey !== void 0 && oldestKey !== key) registry2.delete(oldestKey);
|
|
216677
|
+
}
|
|
216678
|
+
}
|
|
216679
|
+
var MAX_KEYS, MAX_IDS, registry2;
|
|
216680
|
+
var init_surfaced_registry = __esm({
|
|
216681
|
+
"src/search/surfaced-registry.ts"() {
|
|
216682
|
+
"use strict";
|
|
216683
|
+
init_esm_shims();
|
|
216684
|
+
MAX_KEYS = 64;
|
|
216685
|
+
MAX_IDS = 200;
|
|
216686
|
+
registry2 = /* @__PURE__ */ new Map();
|
|
216687
|
+
}
|
|
216688
|
+
});
|
|
216689
|
+
|
|
216269
216690
|
// src/server/request-context.ts
|
|
216270
216691
|
var request_context_exports = {};
|
|
216271
216692
|
__export(request_context_exports, {
|
|
@@ -216348,7 +216769,7 @@ __export(behavior_exports, {
|
|
|
216348
216769
|
resetBehaviorConfigCache: () => resetBehaviorConfigCache
|
|
216349
216770
|
});
|
|
216350
216771
|
import { existsSync as existsSync23, readFileSync as readFileSync14 } from "fs";
|
|
216351
|
-
import { homedir as
|
|
216772
|
+
import { homedir as homedir32 } from "os";
|
|
216352
216773
|
function isSessionInject(value) {
|
|
216353
216774
|
return value === "full" || value === "minimal" || value === "silent";
|
|
216354
216775
|
}
|
|
@@ -216366,7 +216787,7 @@ function legacyBehavior(homeDir) {
|
|
|
216366
216787
|
}
|
|
216367
216788
|
}
|
|
216368
216789
|
function getBehaviorConfig(options = {}) {
|
|
216369
|
-
const homeDir = options.homeDir ??
|
|
216790
|
+
const homeDir = options.homeDir ?? homedir32();
|
|
216370
216791
|
const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
|
|
216371
216792
|
const cacheKey2 = `${homeDir}\0${projectRoot ?? ""}`;
|
|
216372
216793
|
const cached2 = cache4.get(cacheKey2);
|
|
@@ -217335,7 +217756,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
217335
217756
|
case "/config": {
|
|
217336
217757
|
const os6 = await import("os");
|
|
217337
217758
|
const { existsSync: existsSync33 } = await import("fs");
|
|
217338
|
-
const { join:
|
|
217759
|
+
const { join: join34 } = await import("path");
|
|
217339
217760
|
let yml = {};
|
|
217340
217761
|
const configProjectRoot = effectiveProjectRoot;
|
|
217341
217762
|
try {
|
|
@@ -217360,11 +217781,11 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
217360
217781
|
try {
|
|
217361
217782
|
const home = os6.homedir();
|
|
217362
217783
|
const paths = {
|
|
217363
|
-
"project memorix.yml": configProjectRoot ?
|
|
217364
|
-
"user memorix.yml":
|
|
217365
|
-
"project .env": configProjectRoot ?
|
|
217366
|
-
"user .env":
|
|
217367
|
-
"legacy config.json":
|
|
217784
|
+
"project memorix.yml": configProjectRoot ? join34(configProjectRoot, "memorix.yml") : null,
|
|
217785
|
+
"user memorix.yml": join34(home, ".memorix", "memorix.yml"),
|
|
217786
|
+
"project .env": configProjectRoot ? join34(configProjectRoot, ".env") : null,
|
|
217787
|
+
"user .env": join34(home, ".memorix", ".env"),
|
|
217788
|
+
"legacy config.json": join34(home, ".memorix", "config.json")
|
|
217368
217789
|
};
|
|
217369
217790
|
for (const [key, fpath] of Object.entries(paths)) {
|
|
217370
217791
|
if (fpath === null) {
|
|
@@ -217469,8 +217890,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
217469
217890
|
const { promises: fsP } = await import("fs");
|
|
217470
217891
|
const registryPath = path39.join(baseDir, ".project-aliases.json");
|
|
217471
217892
|
const raw = await fsP.readFile(registryPath, "utf-8");
|
|
217472
|
-
const
|
|
217473
|
-
aliasGroups =
|
|
217893
|
+
const registry3 = JSON.parse(raw);
|
|
217894
|
+
aliasGroups = registry3.groups || [];
|
|
217474
217895
|
} catch {
|
|
217475
217896
|
}
|
|
217476
217897
|
const currentGroup = aliasGroups.find((g4) => g4.aliases?.includes(effectiveProjectId) || g4.canonical === effectiveProjectId);
|
|
@@ -258219,6 +258640,12 @@ async function createMemorixServer(cwd, existingServer, sharedTeam, options = {}
|
|
|
258219
258640
|
kind: "consolidation",
|
|
258220
258641
|
dedupeKey: "startup-consolidation"
|
|
258221
258642
|
});
|
|
258643
|
+
lifecycle.enqueueLongTermMaintenance({
|
|
258644
|
+
dataDir: projectDir2,
|
|
258645
|
+
projectId: project.id,
|
|
258646
|
+
source: "startup",
|
|
258647
|
+
queue: queue2
|
|
258648
|
+
});
|
|
258222
258649
|
}
|
|
258223
258650
|
try {
|
|
258224
258651
|
const { CodeGraphStore: CodeGraphStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
@@ -258268,7 +258695,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
258268
258695
|
};
|
|
258269
258696
|
const server = existingServer ?? new McpServer({
|
|
258270
258697
|
name: "memorix",
|
|
258271
|
-
version: true ? "1.4.
|
|
258698
|
+
version: true ? "1.4.6" : "1.0.1"
|
|
258272
258699
|
});
|
|
258273
258700
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
258274
258701
|
server.registerTool = ((name, ...args) => {
|
|
@@ -258753,7 +259180,7 @@ Mode: ${decision.usedLLM ? "LLM" : "heuristic"}`
|
|
|
258753
259180
|
let longTermNote = "";
|
|
258754
259181
|
if (longTerm) {
|
|
258755
259182
|
try {
|
|
258756
|
-
const { promoteObservationToLongTermMemory: promoteObservationToLongTermMemory2 } = await Promise.resolve().then(() => (init_long_term(), long_term_exports));
|
|
259183
|
+
const { promoteObservationToLongTermMemory: promoteObservationToLongTermMemory2, maybeAutoQualifyLongTermMemory: maybeAutoQualifyLongTermMemory2 } = await Promise.resolve().then(() => (init_long_term(), long_term_exports));
|
|
258757
259184
|
const promoted = await promoteObservationToLongTermMemory2({
|
|
258758
259185
|
dataDir: projectDir2,
|
|
258759
259186
|
observation: obs,
|
|
@@ -258767,7 +259194,24 @@ Mode: ${decision.usedLLM ? "LLM" : "heuristic"}`
|
|
|
258767
259194
|
...reader.isTeamMember ? { isTeamMember: true } : {}
|
|
258768
259195
|
}
|
|
258769
259196
|
});
|
|
258770
|
-
|
|
259197
|
+
const autoQualified = await maybeAutoQualifyLongTermMemory2({
|
|
259198
|
+
dataDir: projectDir2,
|
|
259199
|
+
id: promoted.memory.id,
|
|
259200
|
+
sourceDetail: "explicit"
|
|
259201
|
+
});
|
|
259202
|
+
if (autoQualified) {
|
|
259203
|
+
try {
|
|
259204
|
+
const { enqueueLongTermMaintenance: enqueueLongTermMaintenance2 } = await Promise.resolve().then(() => (init_lifecycle(), lifecycle_exports));
|
|
259205
|
+
enqueueLongTermMaintenance2({
|
|
259206
|
+
dataDir: projectDir2,
|
|
259207
|
+
projectId: project.id,
|
|
259208
|
+
source: "long-term:" + promoted.memory.id
|
|
259209
|
+
});
|
|
259210
|
+
} catch {
|
|
259211
|
+
}
|
|
259212
|
+
}
|
|
259213
|
+
longTermNote = autoQualified ? `
|
|
259214
|
+
Long-term memory: ${promoted.memory.id} (${promoted.memory.kind}/${promoted.memory.scope}, auto-qualified) and now enters briefs as durable context. Audit with \`memorix memory long-term list\`.` : `
|
|
258771
259215
|
Long-term candidate: ${promoted.memory.id} (${promoted.memory.kind}/${promoted.memory.scope}). Review it with the CLI before it is delivered automatically.`;
|
|
258772
259216
|
} catch (longTermError) {
|
|
258773
259217
|
longTermNote = `
|
|
@@ -258963,6 +259407,13 @@ Use this as the \`topicKey\` parameter in \`memorix_store\` to enable upsert beh
|
|
|
258963
259407
|
const boundary = requireExplicitAutopilotExpansion("memorix_search", purpose);
|
|
258964
259408
|
if (boundary) return boundary;
|
|
258965
259409
|
}
|
|
259410
|
+
let surfacedKey = `project:${project.id}`;
|
|
259411
|
+
try {
|
|
259412
|
+
const { getActiveSession: getActiveSession2 } = await Promise.resolve().then(() => (init_session(), session_exports));
|
|
259413
|
+
const active = await getActiveSession2(projectDir2, project.id);
|
|
259414
|
+
if (active) surfacedKey = `session:${active.id}`;
|
|
259415
|
+
} catch {
|
|
259416
|
+
}
|
|
258966
259417
|
return withFreshIndex(async () => {
|
|
258967
259418
|
const safeLimit2 = limit2 != null ? coerceNumber(limit2, 20) : void 0;
|
|
258968
259419
|
const safeMaxTokens = maxTokens != null ? coerceNumber(maxTokens, 0) : void 0;
|
|
@@ -258980,7 +259431,8 @@ Use this as the \`topicKey\` parameter in \`memorix_store\` to enable upsert beh
|
|
|
258980
259431
|
status: status ?? "active",
|
|
258981
259432
|
source,
|
|
258982
259433
|
quality,
|
|
258983
|
-
reader: getObservationReader(scope === "global" ? "global" : "project")
|
|
259434
|
+
reader: getObservationReader(scope === "global" ? "global" : "project"),
|
|
259435
|
+
surfacedIds: getSurfacedIds(surfacedKey)
|
|
258984
259436
|
});
|
|
258985
259437
|
let result;
|
|
258986
259438
|
try {
|
|
@@ -258999,6 +259451,7 @@ Use this as the \`topicKey\` parameter in \`memorix_store\` to enable upsert beh
|
|
|
258999
259451
|
}
|
|
259000
259452
|
throw error40;
|
|
259001
259453
|
}
|
|
259454
|
+
recordSurfacedIds(surfacedKey, result.entries.map((entry) => entry.id));
|
|
259002
259455
|
const activeBoundary = getActiveAutopilotRetrievalBoundary();
|
|
259003
259456
|
if (scope !== "global" && activeBoundary && !force && result.entries.length > 0 && result.entries.every((entry) => activeBoundary.coveredObservationIds.has(entry.id))) {
|
|
259004
259457
|
const duplicate = blockCoveredAutopilotEvidence("memorix_search", result.entries.map((entry) => entry.id), force);
|
|
@@ -260270,10 +260723,10 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
260270
260723
|
);
|
|
260271
260724
|
let enableKG = isToolInProfile("create_entities", toolProfile);
|
|
260272
260725
|
try {
|
|
260273
|
-
const { homedir:
|
|
260274
|
-
const { join:
|
|
260726
|
+
const { homedir: homedir36 } = await import("os");
|
|
260727
|
+
const { join: join34 } = await import("path");
|
|
260275
260728
|
const { readFile: readFile10 } = await import("fs/promises");
|
|
260276
|
-
const raw = await readFile10(
|
|
260729
|
+
const raw = await readFile10(join34(homedir36(), ".memorix", "settings.json"), "utf-8");
|
|
260277
260730
|
const s4 = JSON.parse(raw);
|
|
260278
260731
|
if (s4.knowledgeGraph === true) enableKG = true;
|
|
260279
260732
|
} catch {
|
|
@@ -261961,13 +262414,26 @@ ${lines.join("\n")}` }] };
|
|
|
261961
262414
|
if (bytes.length >= 12 && Buffer.from(bytes.subarray(0, 4)).toString("ascii") === "RIFF" && Buffer.from(bytes.subarray(8, 12)).toString("ascii") === "WEBP") return "image/webp";
|
|
261962
262415
|
return void 0;
|
|
261963
262416
|
}
|
|
262417
|
+
const mediaGenerationEnabled = process.env.MEMORIX_MCP_MEDIA_GENERATION === "1";
|
|
262418
|
+
const mediaTranscriptionEnabled = process.env.MEMORIX_MCP_MEDIA_TRANSCRIPTION === "1";
|
|
262419
|
+
const mediaGenerationOrTranscription = mediaGenerationEnabled || mediaTranscriptionEnabled;
|
|
261964
262420
|
server.registerTool(
|
|
261965
262421
|
"memorix_media",
|
|
261966
262422
|
{
|
|
261967
262423
|
title: "Manage Controlled Media",
|
|
261968
262424
|
description: "Use the controlled local media library for an explicit import, attachment, inspection, or MiniMax generation request. Assets stay outside the Git worktree and enter normal memory only when attach is explicitly true. Use the CLI for destructive removal, quota cleanup, and direct generation. MCP generation is disabled by default and requires MEMORIX_MCP_MEDIA_GENERATION=1 after the operator reviews provider billing.",
|
|
261969
262425
|
inputSchema: {
|
|
261970
|
-
action: external_exports2.enum([
|
|
262426
|
+
action: external_exports2.enum([
|
|
262427
|
+
"import",
|
|
262428
|
+
"attach",
|
|
262429
|
+
"list",
|
|
262430
|
+
"show",
|
|
262431
|
+
"derive-pdf",
|
|
262432
|
+
"status",
|
|
262433
|
+
"cancel",
|
|
262434
|
+
...mediaTranscriptionEnabled ? ["derive-audio"] : [],
|
|
262435
|
+
...mediaGenerationEnabled ? ["generate-image", "generate-video"] : []
|
|
262436
|
+
]),
|
|
261971
262437
|
path: external_exports2.string().optional().describe("Explicit local image/audio/video/PDF path for import."),
|
|
261972
262438
|
assetId: external_exports2.string().optional().describe("Controlled MediaAsset ID for attach/show."),
|
|
261973
262439
|
jobId: external_exports2.string().optional().describe("Durable media job ID for status."),
|
|
@@ -261975,20 +262441,26 @@ ${lines.join("\n")}` }] };
|
|
|
261975
262441
|
limit: external_exports2.number().int().min(1).max(100).optional().describe("Maximum assets to list."),
|
|
261976
262442
|
title: external_exports2.string().optional().describe("Observation title when attaching generated/imported output."),
|
|
261977
262443
|
narrative: external_exports2.string().optional().describe("Short retrieval text when attaching an asset."),
|
|
261978
|
-
prompt: external_exports2.string().optional().describe("Explicit MiniMax generation prompt."),
|
|
261979
|
-
image: external_exports2.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
|
|
261980
|
-
model: external_exports2.string().max(160).optional().describe("Provider model for the selected media action."),
|
|
261981
|
-
provider: external_exports2.enum(["openai", "groq"]).optional().describe("Explicit audio transcription provider."),
|
|
261982
|
-
language: external_exports2.string().max(32).optional().describe("Optional ISO-639-1 hint for audio transcription."),
|
|
261983
|
-
region: external_exports2.enum(["global", "cn"]).optional().describe("MiniMax deployment region."),
|
|
261984
|
-
n: external_exports2.number().int().min(1).max(4).optional().describe("Image output count."),
|
|
261985
|
-
ratio: external_exports2.enum(["adaptive", "1:1", "16:9", "4:3", "3:2", "2:3", "3:4", "9:16", "21:9"]).optional().describe("Image or video aspect ratio."),
|
|
261986
|
-
width: external_exports2.number().int().min(1).max(8192).optional().describe("Requested image width."),
|
|
261987
|
-
height: external_exports2.number().int().min(1).max(8192).optional().describe("Requested image height."),
|
|
261988
|
-
duration: external_exports2.union([external_exports2.literal(5), external_exports2.literal(10)]).optional().describe("MiniMax video duration in seconds."),
|
|
261989
262444
|
maxPages: external_exports2.number().int().min(1).max(100).optional().describe("Bounded PDF extraction page limit."),
|
|
261990
262445
|
maxChars: external_exports2.number().int().min(1).max(6e4).optional().describe("Bounded PDF extraction character limit."),
|
|
261991
|
-
attach: external_exports2.boolean().optional().describe("Attach generated/imported output to normal project memory explicitly.")
|
|
262446
|
+
attach: external_exports2.boolean().optional().describe("Attach generated/imported output to normal project memory explicitly."),
|
|
262447
|
+
...mediaGenerationOrTranscription ? {
|
|
262448
|
+
model: external_exports2.string().max(160).optional().describe("Provider model for the selected media action."),
|
|
262449
|
+
prompt: external_exports2.string().optional().describe("Explicit prompt for generation or transcription.")
|
|
262450
|
+
} : {},
|
|
262451
|
+
...mediaTranscriptionEnabled ? {
|
|
262452
|
+
provider: external_exports2.enum(["openai", "groq"]).optional().describe("Explicit audio transcription provider."),
|
|
262453
|
+
language: external_exports2.string().max(32).optional().describe("Optional ISO-639-1 hint for audio transcription.")
|
|
262454
|
+
} : {},
|
|
262455
|
+
...mediaGenerationEnabled ? {
|
|
262456
|
+
image: external_exports2.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
|
|
262457
|
+
region: external_exports2.enum(["global", "cn"]).optional().describe("MiniMax deployment region."),
|
|
262458
|
+
n: external_exports2.number().int().min(1).max(4).optional().describe("Image output count."),
|
|
262459
|
+
ratio: external_exports2.enum(["adaptive", "1:1", "16:9", "4:3", "3:2", "2:3", "3:4", "9:16", "21:9"]).optional().describe("Image or video aspect ratio."),
|
|
262460
|
+
width: external_exports2.number().int().min(1).max(8192).optional().describe("Requested image width."),
|
|
262461
|
+
height: external_exports2.number().int().min(1).max(8192).optional().describe("Requested image height."),
|
|
262462
|
+
duration: external_exports2.union([external_exports2.literal(5), external_exports2.literal(10)]).optional().describe("MiniMax video duration in seconds.")
|
|
262463
|
+
} : {}
|
|
261992
262464
|
}
|
|
261993
262465
|
},
|
|
261994
262466
|
async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt: prompt2, image, model, provider: provider2, language, region, n: n3, ratio, width, height, duration: duration3, maxPages, maxChars, attach }) => {
|
|
@@ -262474,6 +262946,7 @@ var init_server4 = __esm({
|
|
|
262474
262946
|
init_formation_timeout();
|
|
262475
262947
|
init_timeout();
|
|
262476
262948
|
init_secret_filter();
|
|
262949
|
+
init_surfaced_registry();
|
|
262477
262950
|
init_request_context();
|
|
262478
262951
|
FORMATION_TIMEOUT_MS = parseFormationTimeoutMs(process.env.MEMORIX_FORMATION_TIMEOUT_MS);
|
|
262479
262952
|
COMPACT_ON_WRITE_TIMEOUT_MS = 12e3;
|
|
@@ -262576,8 +263049,8 @@ __export(update_checker_exports, {
|
|
|
262576
263049
|
});
|
|
262577
263050
|
import { execFile as execFile3 } from "child_process";
|
|
262578
263051
|
import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir7 } from "fs/promises";
|
|
262579
|
-
import { join as
|
|
262580
|
-
import { homedir as
|
|
263052
|
+
import { join as join28 } from "path";
|
|
263053
|
+
import { homedir as homedir33 } from "os";
|
|
262581
263054
|
function getCurrentVersion() {
|
|
262582
263055
|
try {
|
|
262583
263056
|
return getCliVersion();
|
|
@@ -262756,8 +263229,8 @@ var init_update_checker = __esm({
|
|
|
262756
263229
|
MIN_AUTO_UPDATE_TIMEOUT_MS = 5e3;
|
|
262757
263230
|
MAX_AUTO_UPDATE_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
262758
263231
|
REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
262759
|
-
CACHE_DIR2 =
|
|
262760
|
-
CACHE_FILE2 =
|
|
263232
|
+
CACHE_DIR2 = join28(homedir33(), ".memorix");
|
|
263233
|
+
CACHE_FILE2 = join28(CACHE_DIR2, "update-check.json");
|
|
262761
263234
|
_testing = {
|
|
262762
263235
|
CACHE_FILE: CACHE_FILE2,
|
|
262763
263236
|
CHECK_INTERVAL_MS,
|
|
@@ -262813,7 +263286,7 @@ var init_serve = __esm({
|
|
|
262813
263286
|
const { StdioServerTransport: StdioServerTransport2 } = await Promise.resolve().then(() => (init_stdio2(), stdio_exports));
|
|
262814
263287
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
|
|
262815
263288
|
const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
262816
|
-
const { homedir:
|
|
263289
|
+
const { homedir: homedir36 } = await import("os");
|
|
262817
263290
|
const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
|
|
262818
263291
|
process.stdin.on("end", () => {
|
|
262819
263292
|
console.error("[memorix] stdin closed \u2014 exiting");
|
|
@@ -262823,7 +263296,7 @@ var init_serve = __esm({
|
|
|
262823
263296
|
try {
|
|
262824
263297
|
safeCwd = process.cwd();
|
|
262825
263298
|
} catch {
|
|
262826
|
-
safeCwd =
|
|
263299
|
+
safeCwd = homedir36();
|
|
262827
263300
|
}
|
|
262828
263301
|
const resolution = resolveServeProject2(
|
|
262829
263302
|
{
|
|
@@ -262831,7 +263304,7 @@ var init_serve = __esm({
|
|
|
262831
263304
|
envProjectRoot: process.env.MEMORIX_PROJECT_ROOT,
|
|
262832
263305
|
initCwd: process.env.INIT_CWD,
|
|
262833
263306
|
processCwd: safeCwd,
|
|
262834
|
-
homeDir:
|
|
263307
|
+
homeDir: homedir36()
|
|
262835
263308
|
},
|
|
262836
263309
|
{ detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 }
|
|
262837
263310
|
);
|
|
@@ -265052,7 +265525,8 @@ var init_control_plane_maintenance = __esm({
|
|
|
265052
265525
|
"claim-requalification",
|
|
265053
265526
|
"knowledge-compile",
|
|
265054
265527
|
"knowledge-lint",
|
|
265055
|
-
"workflow-index"
|
|
265528
|
+
"workflow-index",
|
|
265529
|
+
"long-term-maintenance"
|
|
265056
265530
|
];
|
|
265057
265531
|
TARGET_WAIT_RETRY_MS = 3e4;
|
|
265058
265532
|
}
|
|
@@ -265064,7 +265538,8 @@ __export(serve_http_exports, {
|
|
|
265064
265538
|
DEFAULT_SESSION_TIMEOUT_MS: () => DEFAULT_SESSION_TIMEOUT_MS,
|
|
265065
265539
|
_testing: () => _testing2,
|
|
265066
265540
|
default: () => serve_http_default,
|
|
265067
|
-
parseSessionTimeoutMs: () => parseSessionTimeoutMs
|
|
265541
|
+
parseSessionTimeoutMs: () => parseSessionTimeoutMs,
|
|
265542
|
+
resolveServeHttpDefaults: () => resolveServeHttpDefaults
|
|
265068
265543
|
});
|
|
265069
265544
|
function parseSessionTimeoutMs(raw) {
|
|
265070
265545
|
const value = raw?.trim();
|
|
@@ -265073,6 +265548,15 @@ function parseSessionTimeoutMs(raw) {
|
|
|
265073
265548
|
if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_SESSION_TIMEOUT_MS;
|
|
265074
265549
|
return Math.floor(parsed);
|
|
265075
265550
|
}
|
|
265551
|
+
function resolveServeHttpDefaults(argsPort, configured) {
|
|
265552
|
+
const configuredPort = typeof configured.port === "number" && Number.isFinite(configured.port) ? configured.port : void 0;
|
|
265553
|
+
const port = parseTcpPortOrReport(argsPort, configuredPort ?? 3211);
|
|
265554
|
+
if (port === void 0) {
|
|
265555
|
+
return { port: 3211 };
|
|
265556
|
+
}
|
|
265557
|
+
const transportNotice = configured.transport === "stdio" ? '[memorix] config server.transport = "stdio"; serve-http continues on HTTP (the explicit command wins).' : void 0;
|
|
265558
|
+
return { port, transportNotice };
|
|
265559
|
+
}
|
|
265076
265560
|
var DEFAULT_SESSION_TIMEOUT_MS, serve_http_default, _testing2;
|
|
265077
265561
|
var init_serve_http = __esm({
|
|
265078
265562
|
"src/cli/commands/serve-http.ts"() {
|
|
@@ -265122,19 +265606,23 @@ var init_serve_http = __esm({
|
|
|
265122
265606
|
const { createProjectBindingController: createProjectBindingController2 } = await Promise.resolve().then(() => (init_request_context(), request_context_exports));
|
|
265123
265607
|
const { findGitInSubdirs: findGitInSubdirs2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
265124
265608
|
const { writeFileSync: writeFileSync11, mkdirSync: mkdirSync11 } = await import("fs");
|
|
265125
|
-
const { homedir:
|
|
265126
|
-
|
|
265127
|
-
|
|
265128
|
-
|
|
265129
|
-
|
|
265609
|
+
const { homedir: homedir36 } = await import("os");
|
|
265610
|
+
let configuredDefaults = {};
|
|
265611
|
+
try {
|
|
265612
|
+
const { getServerConfig: getServerConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
265613
|
+
configuredDefaults = getServerConfig2();
|
|
265614
|
+
} catch {
|
|
265130
265615
|
}
|
|
265616
|
+
const resolved = resolveServeHttpDefaults(args.port, configuredDefaults);
|
|
265617
|
+
if (resolved.transportNotice) console.error(resolved.transportNotice);
|
|
265618
|
+
const port = resolved.port;
|
|
265131
265619
|
const host = args.host || "127.0.0.1";
|
|
265132
265620
|
const toolProfile = resolveToolProfile({ explicit: args.mode, envValue: process.env.MEMORIX_MODE, fallback: "team" });
|
|
265133
265621
|
let safeCwd;
|
|
265134
265622
|
try {
|
|
265135
265623
|
safeCwd = process.cwd();
|
|
265136
265624
|
} catch {
|
|
265137
|
-
safeCwd =
|
|
265625
|
+
safeCwd = homedir36();
|
|
265138
265626
|
}
|
|
265139
265627
|
let projectRoot = args.cwd || process.env.MEMORIX_PROJECT_ROOT || safeCwd;
|
|
265140
265628
|
console.error(`[memorix] HTTP transport starting on ${host}:${port}`);
|
|
@@ -265844,7 +266332,7 @@ var init_serve_http = __esm({
|
|
|
265844
266332
|
const { projectId: configProjectId } = await resolveRequestProject(url2);
|
|
265845
266333
|
const os6 = await import("os");
|
|
265846
266334
|
const { existsSync: existsSync33 } = await import("fs");
|
|
265847
|
-
const { join:
|
|
266335
|
+
const { join: join34 } = await import("path");
|
|
265848
266336
|
const { loadYamlConfig: loadYamlConfig2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
|
|
265849
266337
|
const { loadFileConfig: loadFileConfig2, loadDotenv: loadDotenv2, getLoadedEnvFiles: getLoadedEnvFiles2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
265850
266338
|
const isStartupProject = configProjectId === defaultProject.id;
|
|
@@ -265858,11 +266346,11 @@ var init_serve_http = __esm({
|
|
|
265858
266346
|
const home = os6.homedir();
|
|
265859
266347
|
if (effectiveRoot) {
|
|
265860
266348
|
const paths = {
|
|
265861
|
-
"project memorix.yml":
|
|
265862
|
-
"user memorix.yml":
|
|
265863
|
-
"project .env":
|
|
265864
|
-
"user .env":
|
|
265865
|
-
"legacy config.json":
|
|
266349
|
+
"project memorix.yml": join34(effectiveRoot, "memorix.yml"),
|
|
266350
|
+
"user memorix.yml": join34(home, ".memorix", "memorix.yml"),
|
|
266351
|
+
"project .env": join34(effectiveRoot, ".env"),
|
|
266352
|
+
"user .env": join34(home, ".memorix", ".env"),
|
|
266353
|
+
"legacy config.json": join34(home, ".memorix", "config.json")
|
|
265866
266354
|
};
|
|
265867
266355
|
for (const [key, fpath] of Object.entries(paths)) {
|
|
265868
266356
|
files[key] = { exists: existsSync33(fpath), path: fpath };
|
|
@@ -265871,9 +266359,9 @@ var init_serve_http = __esm({
|
|
|
265871
266359
|
files["project memorix.yml"] = { exists: false, path: "unavailable", unavailable: true };
|
|
265872
266360
|
files["project .env"] = { exists: false, path: "unavailable", unavailable: true };
|
|
265873
266361
|
const userPaths = {
|
|
265874
|
-
"user memorix.yml":
|
|
265875
|
-
"user .env":
|
|
265876
|
-
"legacy config.json":
|
|
266362
|
+
"user memorix.yml": join34(home, ".memorix", "memorix.yml"),
|
|
266363
|
+
"user .env": join34(home, ".memorix", ".env"),
|
|
266364
|
+
"legacy config.json": join34(home, ".memorix", "config.json")
|
|
265877
266365
|
};
|
|
265878
266366
|
for (const [key, fpath] of Object.entries(userPaths)) {
|
|
265879
266367
|
files[key] = { exists: existsSync33(fpath), path: fpath };
|
|
@@ -265999,8 +266487,8 @@ var init_serve_http = __esm({
|
|
|
265999
266487
|
canonicalId = await aliasModule.getCanonicalId(idProjectId);
|
|
266000
266488
|
const registryPath = pathModule.default.join(baseDir, ".project-aliases.json");
|
|
266001
266489
|
const raw = await fsPromises.readFile(registryPath, "utf-8");
|
|
266002
|
-
const
|
|
266003
|
-
aliasGroups =
|
|
266490
|
+
const registry3 = JSON.parse(raw);
|
|
266491
|
+
aliasGroups = registry3.groups || [];
|
|
266004
266492
|
} catch {
|
|
266005
266493
|
}
|
|
266006
266494
|
const currentGroup = aliasGroups.find((g4) => g4.aliases?.includes(idProjectId) || g4.canonical === idProjectId);
|
|
@@ -268550,6 +269038,7 @@ var init_types9 = __esm({
|
|
|
268550
269038
|
hermes: "community",
|
|
268551
269039
|
opencode: "community",
|
|
268552
269040
|
trae: "community",
|
|
269041
|
+
dsh: "community",
|
|
268553
269042
|
pi: "community",
|
|
268554
269043
|
omp: "community",
|
|
268555
269044
|
antigravity: "community"
|
|
@@ -268608,7 +269097,8 @@ function getAgentLabel2(agent) {
|
|
|
268608
269097
|
openclaw: "OpenClaw",
|
|
268609
269098
|
hermes: "Hermes Agent",
|
|
268610
269099
|
omp: "Oh-my-Pi",
|
|
268611
|
-
trae: "Trae"
|
|
269100
|
+
trae: "Trae",
|
|
269101
|
+
dsh: "DeepSeek Harness"
|
|
268612
269102
|
};
|
|
268613
269103
|
return labels[agent] || agent;
|
|
268614
269104
|
}
|
|
@@ -268626,6 +269116,7 @@ function getAgentHint2(agent) {
|
|
|
268626
269116
|
hermes: "Hermes plugin hooks; use `memorix setup --agent hermes`",
|
|
268627
269117
|
omp: "Oh-my-Pi package hooks; use `memorix setup --agent omp`",
|
|
268628
269118
|
trae: ".trae/rules/project_rules.md (rules only, no hooks system)",
|
|
269119
|
+
dsh: "~/.dsh/cordis.patch.yml MCP row via `memorix setup --agent dsh` (no hooks system)",
|
|
268629
269120
|
codex: "Codex plugin hooks; use `memorix setup --agent codex`"
|
|
268630
269121
|
};
|
|
268631
269122
|
return hints[agent] || "";
|
|
@@ -268733,7 +269224,8 @@ function estimateFileSize(agent, configPath) {
|
|
|
268733
269224
|
codex: "~1KB",
|
|
268734
269225
|
antigravity: "~2KB",
|
|
268735
269226
|
opencode: "~3KB",
|
|
268736
|
-
trae: "~1KB"
|
|
269227
|
+
trae: "~1KB",
|
|
269228
|
+
dsh: "~1KB"
|
|
268737
269229
|
};
|
|
268738
269230
|
return sizes[agent] || "~2KB";
|
|
268739
269231
|
}
|
|
@@ -268751,6 +269243,8 @@ function getRulesPath(agent, cwd, global2) {
|
|
|
268751
269243
|
return path42.join(home, ".gemini", "GEMINI.md");
|
|
268752
269244
|
case "trae":
|
|
268753
269245
|
return path42.join(home, ".trae", "rules", "project_rules.md");
|
|
269246
|
+
case "dsh":
|
|
269247
|
+
return path42.join(process.env.DSH_HOME?.trim() || path42.join(home, ".dsh"), "AGENTS.md");
|
|
268754
269248
|
default:
|
|
268755
269249
|
return "";
|
|
268756
269250
|
}
|
|
@@ -268766,6 +269260,8 @@ function getRulesPath(agent, cwd, global2) {
|
|
|
268766
269260
|
return path42.join(cwd, "GEMINI.md");
|
|
268767
269261
|
case "trae":
|
|
268768
269262
|
return path42.join(cwd, ".trae", "rules", "project_rules.md");
|
|
269263
|
+
case "dsh":
|
|
269264
|
+
return path42.join(cwd, "AGENTS.md");
|
|
268769
269265
|
default:
|
|
268770
269266
|
return "";
|
|
268771
269267
|
}
|
|
@@ -269063,7 +269559,8 @@ function normalizeCommitCount(count3) {
|
|
|
269063
269559
|
}
|
|
269064
269560
|
return count3;
|
|
269065
269561
|
}
|
|
269066
|
-
function getCommitInfo(cwd, ref = "HEAD") {
|
|
269562
|
+
function getCommitInfo(cwd, ref = "HEAD", maxDiffChars = 500) {
|
|
269563
|
+
const cap = Number.isFinite(maxDiffChars) ? Math.max(0, Math.floor(maxDiffChars)) : 500;
|
|
269067
269564
|
const FORMAT = "%H%n%h%n%aN%n%aI%n%s%n%b";
|
|
269068
269565
|
const revision = normalizeCommitRef(ref);
|
|
269069
269566
|
const raw = runGit3(cwd, ["log", "-1", `--format=${FORMAT}`, "--end-of-options", revision]).trim();
|
|
@@ -269091,7 +269588,7 @@ function getCommitInfo(cwd, ref = "HEAD") {
|
|
|
269091
269588
|
let diffSummary = "";
|
|
269092
269589
|
try {
|
|
269093
269590
|
const diff = runGit3(cwd, ["diff-tree", "-p", "--no-commit-id", hash4], 1024 * 100);
|
|
269094
|
-
diffSummary = diff.substring(0,
|
|
269591
|
+
diffSummary = diff.substring(0, cap);
|
|
269095
269592
|
} catch {
|
|
269096
269593
|
}
|
|
269097
269594
|
return {
|
|
@@ -269342,8 +269839,23 @@ var init_noise_filter = __esm({
|
|
|
269342
269839
|
// src/cli/commands/ingest-commit.ts
|
|
269343
269840
|
var ingest_commit_exports = {};
|
|
269344
269841
|
__export(ingest_commit_exports, {
|
|
269842
|
+
applyGitIngestPolicy: () => applyGitIngestPolicy,
|
|
269345
269843
|
default: () => ingest_commit_default
|
|
269346
269844
|
});
|
|
269845
|
+
function applyGitIngestPolicy(commit, policy) {
|
|
269846
|
+
if (policy.ingestOnCommit === false) {
|
|
269847
|
+
return {
|
|
269848
|
+
skip: true,
|
|
269849
|
+
reason: "ingest_on_commit is disabled",
|
|
269850
|
+
diffSummary: commit.diffSummary
|
|
269851
|
+
};
|
|
269852
|
+
}
|
|
269853
|
+
const cap = policy.maxDiffSize;
|
|
269854
|
+
return {
|
|
269855
|
+
skip: false,
|
|
269856
|
+
diffSummary: typeof cap === "number" && Number.isFinite(cap) ? commit.diffSummary.slice(0, Math.max(0, Math.floor(cap))) : commit.diffSummary
|
|
269857
|
+
};
|
|
269858
|
+
}
|
|
269347
269859
|
var ingest_commit_default;
|
|
269348
269860
|
var init_ingest_commit = __esm({
|
|
269349
269861
|
"src/cli/commands/ingest-commit.ts"() {
|
|
@@ -269386,11 +269898,21 @@ var init_ingest_commit = __esm({
|
|
|
269386
269898
|
const force = !!args.force;
|
|
269387
269899
|
if (!auto) we(`Ingest commit: ${ref}`);
|
|
269388
269900
|
try {
|
|
269389
|
-
const { getCommitInfo: getCommitInfo2, ingestCommit: ingestCommit2 } = await Promise.resolve().then(() => (init_extractor(), extractor_exports));
|
|
269390
|
-
const commit = getCommitInfo2(cwd, ref);
|
|
269391
|
-
const { shouldFilterCommit: shouldFilterCommit2 } = await Promise.resolve().then(() => (init_noise_filter(), noise_filter_exports));
|
|
269392
269901
|
const { getGitConfig: getGitConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
269393
269902
|
const gitCfg = getGitConfig2();
|
|
269903
|
+
const { getCommitInfo: getCommitInfo2, ingestCommit: ingestCommit2 } = await Promise.resolve().then(() => (init_extractor(), extractor_exports));
|
|
269904
|
+
const commit = getCommitInfo2(cwd, ref, gitCfg.maxDiffSize ?? 500);
|
|
269905
|
+
const policy = applyGitIngestPolicy(commit, {
|
|
269906
|
+
ingestOnCommit: gitCfg.ingestOnCommit,
|
|
269907
|
+
maxDiffSize: gitCfg.maxDiffSize
|
|
269908
|
+
});
|
|
269909
|
+
if (policy.skip && auto) {
|
|
269910
|
+
console.error(`[memorix] Skipped ${commit.shortHash}: ${policy.reason}`);
|
|
269911
|
+
process.exit(0);
|
|
269912
|
+
return;
|
|
269913
|
+
}
|
|
269914
|
+
commit.diffSummary = policy.diffSummary;
|
|
269915
|
+
const { shouldFilterCommit: shouldFilterCommit2 } = await Promise.resolve().then(() => (init_noise_filter(), noise_filter_exports));
|
|
269394
269916
|
const filterResult = shouldFilterCommit2(commit, {
|
|
269395
269917
|
skipMergeCommits: gitCfg.skipMergeCommits,
|
|
269396
269918
|
excludePatterns: gitCfg.excludePatterns,
|
|
@@ -271256,7 +271778,7 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
271256
271778
|
import { existsSync as existsSync28 } from "fs";
|
|
271257
271779
|
import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile9 } from "fs/promises";
|
|
271258
271780
|
import { basename as basename5, dirname as dirname8, resolve as resolve4 } from "path";
|
|
271259
|
-
import { homedir as
|
|
271781
|
+
import { homedir as homedir34 } from "os";
|
|
271260
271782
|
function requestedAgents(agent) {
|
|
271261
271783
|
const all = getSetupAgentTargets();
|
|
271262
271784
|
if (!agent || agent === "all") return all;
|
|
@@ -271334,16 +271856,16 @@ function asRecordArray(value) {
|
|
|
271334
271856
|
return Array.isArray(value) ? value.map(asRecord3).filter((entry) => entry !== null) : [];
|
|
271335
271857
|
}
|
|
271336
271858
|
function codexPluginPath() {
|
|
271337
|
-
return `${
|
|
271859
|
+
return `${homedir34()}/plugins/${CODEX_PLUGIN_NAME}`;
|
|
271338
271860
|
}
|
|
271339
271861
|
function codexPluginMcpPath() {
|
|
271340
271862
|
return `${codexPluginPath()}/.mcp.json`;
|
|
271341
271863
|
}
|
|
271342
271864
|
function codexMarketplacePath() {
|
|
271343
|
-
return `${
|
|
271865
|
+
return `${homedir34()}/.agents/plugins/marketplace.json`;
|
|
271344
271866
|
}
|
|
271345
271867
|
function codexConfigPath() {
|
|
271346
|
-
return `${
|
|
271868
|
+
return `${homedir34()}/.codex/config.toml`;
|
|
271347
271869
|
}
|
|
271348
271870
|
function normalizeMarketplacePath(value) {
|
|
271349
271871
|
return value.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
@@ -271653,7 +272175,7 @@ function defaultClaudeProjectKey(projectRoot) {
|
|
|
271653
272175
|
return resolve4(projectRoot).replace(/\\/g, "/");
|
|
271654
272176
|
}
|
|
271655
272177
|
function getClaudeLocalConfigPath() {
|
|
271656
|
-
return `${
|
|
272178
|
+
return `${homedir34()}/.claude.json`;
|
|
271657
272179
|
}
|
|
271658
272180
|
function coerceMcpServer(name, value) {
|
|
271659
272181
|
const entry = asRecord3(value);
|
|
@@ -271834,7 +272356,9 @@ async function inspectMcp(agent, projectRoot, scope) {
|
|
|
271834
272356
|
}
|
|
271835
272357
|
}
|
|
271836
272358
|
const configPath = adapter.getConfigPath(targetScope === "project" ? projectRoot : void 0);
|
|
271837
|
-
if (targetScope === "global" && configPath === adapter.getConfigPath(projectRoot))
|
|
272359
|
+
if (targetScope === "global" && configPath === adapter.getConfigPath(projectRoot) && scope === "all") {
|
|
272360
|
+
continue;
|
|
272361
|
+
}
|
|
271838
272362
|
if (!existsSync28(configPath)) {
|
|
271839
272363
|
checks.push({
|
|
271840
272364
|
scope: targetScope,
|
|
@@ -271910,7 +272434,7 @@ async function inspectGuidance(agent, projectRoot, scope) {
|
|
|
271910
272434
|
}
|
|
271911
272435
|
const checks = [];
|
|
271912
272436
|
for (const targetScope of requestedGuidanceScopes(scope)) {
|
|
271913
|
-
const root = targetScope === "project" ? projectRoot :
|
|
272437
|
+
const root = targetScope === "project" ? projectRoot : homedir34();
|
|
271914
272438
|
const rulesPath = getAgentRulesPath(agent, root, targetScope === "global");
|
|
271915
272439
|
if (!existsSync28(rulesPath)) {
|
|
271916
272440
|
checks.push({
|
|
@@ -272126,7 +272650,8 @@ var init_agent_integrations = __esm({
|
|
|
272126
272650
|
"antigravity",
|
|
272127
272651
|
"kiro",
|
|
272128
272652
|
"opencode",
|
|
272129
|
-
"trae"
|
|
272653
|
+
"trae",
|
|
272654
|
+
"dsh"
|
|
272130
272655
|
]);
|
|
272131
272656
|
CODEX_PLUGIN_NAME = "memorix";
|
|
272132
272657
|
CODEX_PLUGIN_MARKETPLACE = "personal";
|
|
@@ -272188,8 +272713,8 @@ var init_doctor = __esm({
|
|
|
272188
272713
|
return;
|
|
272189
272714
|
}
|
|
272190
272715
|
const { existsSync: existsSync33, readFileSync: readFileSync22 } = await import("fs");
|
|
272191
|
-
const { join:
|
|
272192
|
-
const { homedir:
|
|
272716
|
+
const { join: join34, basename: basename7 } = await import("path");
|
|
272717
|
+
const { homedir: homedir36 } = await import("os");
|
|
272193
272718
|
const { execSync: execSync5 } = await import("child_process");
|
|
272194
272719
|
const report = {};
|
|
272195
272720
|
const issues = [];
|
|
@@ -272251,8 +272776,8 @@ var init_doctor = __esm({
|
|
|
272251
272776
|
}
|
|
272252
272777
|
lines.push("");
|
|
272253
272778
|
lines.push("\u250C\u2500 Runtime Mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
272254
|
-
const memorixDir =
|
|
272255
|
-
const bgStatePath =
|
|
272779
|
+
const memorixDir = join34(homedir36(), ".memorix");
|
|
272780
|
+
const bgStatePath = join34(memorixDir, "background.json");
|
|
272256
272781
|
let bgRunning = false;
|
|
272257
272782
|
let bgPort = 0;
|
|
272258
272783
|
let bgPid = 0;
|
|
@@ -272349,7 +272874,7 @@ var init_doctor = __esm({
|
|
|
272349
272874
|
report.embedding = { mode, status: "temporarily_unavailable" };
|
|
272350
272875
|
}
|
|
272351
272876
|
try {
|
|
272352
|
-
const cachePath =
|
|
272877
|
+
const cachePath = join34(memorixDir, "embedding-cache.json");
|
|
272353
272878
|
if (existsSync33(cachePath)) {
|
|
272354
272879
|
const cache5 = JSON.parse(readFileSync22(cachePath, "utf-8"));
|
|
272355
272880
|
const cacheCount = Object.keys(cache5).length;
|
|
@@ -272543,7 +273068,7 @@ var init_doctor = __esm({
|
|
|
272543
273068
|
lines.push("\u250C\u2500 Conflict Check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
272544
273069
|
let conflictsFound = false;
|
|
272545
273070
|
if (dataDir) {
|
|
272546
|
-
const lockFile =
|
|
273071
|
+
const lockFile = join34(dataDir, ".memorix.lock");
|
|
272547
273072
|
if (existsSync33(lockFile)) {
|
|
272548
273073
|
try {
|
|
272549
273074
|
const lockData = JSON.parse(readFileSync22(lockFile, "utf-8"));
|
|
@@ -272746,21 +273271,28 @@ var init_dashboard = __esm({
|
|
|
272746
273271
|
args: {
|
|
272747
273272
|
port: {
|
|
272748
273273
|
type: "string",
|
|
272749
|
-
description: "Port to run the dashboard on (default: 3210)",
|
|
272750
|
-
|
|
273274
|
+
description: "Port to run the dashboard on (default: [server].dashboardPort or 3210)",
|
|
273275
|
+
required: false
|
|
272751
273276
|
}
|
|
272752
273277
|
},
|
|
272753
273278
|
run: async ({ args }) => {
|
|
272754
273279
|
const { detectProject: detectProject2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
272755
273280
|
const { getProjectDataDir: getProjectDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
|
|
272756
273281
|
const { startDashboard: startDashboard2 } = await Promise.resolve().then(() => (init_server3(), server_exports));
|
|
273282
|
+
let configuredDashboardPort;
|
|
273283
|
+
try {
|
|
273284
|
+
const { getServerConfig: getServerConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
273285
|
+
const serverConfig = getServerConfig2();
|
|
273286
|
+
configuredDashboardPort = typeof serverConfig.dashboardPort === "number" ? serverConfig.dashboardPort : void 0;
|
|
273287
|
+
} catch {
|
|
273288
|
+
}
|
|
272757
273289
|
const project = detectProject2();
|
|
272758
273290
|
if (!project) {
|
|
272759
273291
|
console.error("Memorix requires a git repo to establish project identity. Run `git init` in this workspace first.");
|
|
272760
273292
|
process.exit(1);
|
|
272761
273293
|
}
|
|
272762
273294
|
const dataDir = await getProjectDataDir2(project.id);
|
|
272763
|
-
const port = parseTcpPortOrReport(args.port, 3210);
|
|
273295
|
+
const port = parseTcpPortOrReport(args.port, configuredDashboardPort ?? 3210);
|
|
272764
273296
|
if (port === void 0) {
|
|
272765
273297
|
process.exitCode = 1;
|
|
272766
273298
|
return;
|
|
@@ -273017,6 +273549,116 @@ Project: ${projectName} (${projectId})
|
|
|
273017
273549
|
}
|
|
273018
273550
|
});
|
|
273019
273551
|
|
|
273552
|
+
// src/cli/commands/purge.ts
|
|
273553
|
+
var purge_exports = {};
|
|
273554
|
+
__export(purge_exports, {
|
|
273555
|
+
default: () => purge_default
|
|
273556
|
+
});
|
|
273557
|
+
var purge_default;
|
|
273558
|
+
var init_purge = __esm({
|
|
273559
|
+
"src/cli/commands/purge.ts"() {
|
|
273560
|
+
"use strict";
|
|
273561
|
+
init_esm_shims();
|
|
273562
|
+
init_dist2();
|
|
273563
|
+
init_detector();
|
|
273564
|
+
init_persistence();
|
|
273565
|
+
purge_default = defineCommand({
|
|
273566
|
+
meta: {
|
|
273567
|
+
name: "purge",
|
|
273568
|
+
description: "Retire memories from retrieval (current project by default, --all for every project)"
|
|
273569
|
+
},
|
|
273570
|
+
args: {
|
|
273571
|
+
all: {
|
|
273572
|
+
type: "boolean",
|
|
273573
|
+
description: "Purge every project instead of the current one",
|
|
273574
|
+
default: false
|
|
273575
|
+
},
|
|
273576
|
+
yes: {
|
|
273577
|
+
type: "boolean",
|
|
273578
|
+
description: "Skip the interactive confirmation",
|
|
273579
|
+
default: false
|
|
273580
|
+
},
|
|
273581
|
+
json: {
|
|
273582
|
+
type: "boolean",
|
|
273583
|
+
description: "Emit a machine-readable result",
|
|
273584
|
+
default: false
|
|
273585
|
+
}
|
|
273586
|
+
},
|
|
273587
|
+
async run({ args }) {
|
|
273588
|
+
const purgeAll = Boolean(args.all);
|
|
273589
|
+
const yes = Boolean(args.yes);
|
|
273590
|
+
const asJson = Boolean(args.json);
|
|
273591
|
+
if (!yes && !process.stdin.isTTY) {
|
|
273592
|
+
console.error("[ERROR] Non-interactive environment. Add --yes to confirm.");
|
|
273593
|
+
console.error("[ERROR] Refusing to purge memories without confirmation.");
|
|
273594
|
+
process.exitCode = 1;
|
|
273595
|
+
return;
|
|
273596
|
+
}
|
|
273597
|
+
if (!yes) {
|
|
273598
|
+
const readline = await import("readline");
|
|
273599
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
273600
|
+
const question = purgeAll ? "Retire ALL memories from every project? (y/N) " : "Retire all memories for this project? (y/N) ";
|
|
273601
|
+
const answer = await new Promise((resolve6) => rl.question(question, resolve6));
|
|
273602
|
+
rl.close();
|
|
273603
|
+
if (answer.trim().toLowerCase() !== "y") {
|
|
273604
|
+
console.log("Cancelled.");
|
|
273605
|
+
return;
|
|
273606
|
+
}
|
|
273607
|
+
}
|
|
273608
|
+
let projectId = null;
|
|
273609
|
+
if (!purgeAll) {
|
|
273610
|
+
const project = detectProject();
|
|
273611
|
+
if (!project) {
|
|
273612
|
+
console.error("[ERROR] No .git found \u2014 run from a project directory or pass --all.");
|
|
273613
|
+
process.exitCode = 1;
|
|
273614
|
+
return;
|
|
273615
|
+
}
|
|
273616
|
+
projectId = project.id;
|
|
273617
|
+
}
|
|
273618
|
+
const dataDir = await getProjectDataDir(projectId ?? "");
|
|
273619
|
+
const { initObservationStore: initObservationStore2 } = await Promise.resolve().then(() => (init_obs_store(), obs_store_exports));
|
|
273620
|
+
const { getAllObservations: getAllObservations2, resolveObservations: resolveObservations2 } = await Promise.resolve().then(() => (init_observations(), observations_exports));
|
|
273621
|
+
const { withFreshIndex: withFreshIndex2 } = await Promise.resolve().then(() => (init_freshness(), freshness_exports));
|
|
273622
|
+
await initObservationStore2(dataDir);
|
|
273623
|
+
const observations2 = await withFreshIndex2(() => getAllObservations2());
|
|
273624
|
+
const target = purgeAll ? observations2 : observations2.filter((o4) => o4.projectId === projectId);
|
|
273625
|
+
const ids = target.map((o4) => o4.id).filter((id) => typeof id === "number");
|
|
273626
|
+
const archived = ids.length > 0 ? (await resolveObservations2(ids, "archived")).resolved.length : 0;
|
|
273627
|
+
const { LongTermMemoryStore: LongTermMemoryStore2 } = await Promise.resolve().then(() => (init_long_term_store(), long_term_store_exports));
|
|
273628
|
+
const { archiveLongTermMemory: archiveLongTermMemory2 } = await Promise.resolve().then(() => (init_long_term(), long_term_exports));
|
|
273629
|
+
const longTermStore = new LongTermMemoryStore2();
|
|
273630
|
+
await longTermStore.init(dataDir);
|
|
273631
|
+
let longTermArchived = 0;
|
|
273632
|
+
for (const memory of longTermStore.list()) {
|
|
273633
|
+
if (memory.state === "archived" || memory.state === "superseded") continue;
|
|
273634
|
+
if (!purgeAll && memory.originProjectId !== projectId) continue;
|
|
273635
|
+
try {
|
|
273636
|
+
await archiveLongTermMemory2({
|
|
273637
|
+
dataDir,
|
|
273638
|
+
id: memory.id,
|
|
273639
|
+
reason: purgeAll ? "purge --all" : "purge (project) " + (projectId ?? "")
|
|
273640
|
+
});
|
|
273641
|
+
longTermArchived += 1;
|
|
273642
|
+
} catch {
|
|
273643
|
+
}
|
|
273644
|
+
}
|
|
273645
|
+
const result = {
|
|
273646
|
+
scope: purgeAll ? "all" : projectId,
|
|
273647
|
+
observationsArchived: archived,
|
|
273648
|
+
longTermArchived
|
|
273649
|
+
};
|
|
273650
|
+
if (asJson) {
|
|
273651
|
+
console.log(JSON.stringify(result));
|
|
273652
|
+
} else {
|
|
273653
|
+
console.log(
|
|
273654
|
+
`[OK] Purged ${purgeAll ? "all projects" : result.scope}: archived ${archived} observations and ${longTermArchived} long-term memories.`
|
|
273655
|
+
);
|
|
273656
|
+
}
|
|
273657
|
+
}
|
|
273658
|
+
});
|
|
273659
|
+
}
|
|
273660
|
+
});
|
|
273661
|
+
|
|
273020
273662
|
// src/cli/commands/uninstall.ts
|
|
273021
273663
|
var uninstall_exports = {};
|
|
273022
273664
|
__export(uninstall_exports, {
|
|
@@ -273053,6 +273695,16 @@ function checkTOML(p3) {
|
|
|
273053
273695
|
return false;
|
|
273054
273696
|
}
|
|
273055
273697
|
}
|
|
273698
|
+
function checkDshPatch(p3) {
|
|
273699
|
+
if (!exists(p3)) return false;
|
|
273700
|
+
try {
|
|
273701
|
+
const content = fs27.readFileSync(p3, "utf-8");
|
|
273702
|
+
if (!content.includes("memory-memorix")) return false;
|
|
273703
|
+
return /serverName:\s*['"]?memorix['"]?/.test(content);
|
|
273704
|
+
} catch {
|
|
273705
|
+
return false;
|
|
273706
|
+
}
|
|
273707
|
+
}
|
|
273056
273708
|
function getMCPConfigEntries(home, cwd) {
|
|
273057
273709
|
const entries = [];
|
|
273058
273710
|
entries.push({
|
|
@@ -273184,6 +273836,15 @@ function getMCPConfigEntries(home, cwd) {
|
|
|
273184
273836
|
detected: checkJSON(traeCfg),
|
|
273185
273837
|
note: 'Remove the "memorix" key from mcpServers in this file.'
|
|
273186
273838
|
});
|
|
273839
|
+
const dshPatchPath = path45.join(process.env.DSH_HOME?.trim() || path45.join(home, ".dsh"), "cordis.patch.yml");
|
|
273840
|
+
entries.push({
|
|
273841
|
+
agent: "DeepSeek Harness",
|
|
273842
|
+
path: dshPatchPath,
|
|
273843
|
+
kind: "global",
|
|
273844
|
+
format: "json",
|
|
273845
|
+
detected: checkDshPatch(dshPatchPath),
|
|
273846
|
+
note: "Remove the memory-memorix insert row from this patch file."
|
|
273847
|
+
});
|
|
273187
273848
|
return entries;
|
|
273188
273849
|
}
|
|
273189
273850
|
function checkBackground(home) {
|
|
@@ -274688,7 +275349,7 @@ var init_pipeline_trace = __esm({
|
|
|
274688
275349
|
// src/orchestrate/worktree.ts
|
|
274689
275350
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
274690
275351
|
import { existsSync as existsSync30, rmSync as rmSync2 } from "fs";
|
|
274691
|
-
import { join as
|
|
275352
|
+
import { join as join32, basename as basename6 } from "path";
|
|
274692
275353
|
function runGit4(cwd, args, timeout = 5e3) {
|
|
274693
275354
|
return String(execFileSync5("git", args, {
|
|
274694
275355
|
cwd,
|
|
@@ -274727,7 +275388,7 @@ function isManagedWorktreePath(worktreePath, worktreeBase) {
|
|
|
274727
275388
|
function createWorktree(projectDir2, taskId, pipelineId) {
|
|
274728
275389
|
const shortId2 = taskId.slice(0, 8);
|
|
274729
275390
|
const shortPipeline = pipelineId.slice(0, 8);
|
|
274730
|
-
const worktreeBase =
|
|
275391
|
+
const worktreeBase = join32(projectDir2, WORKTREE_DIR, `task-${shortId2}`);
|
|
274731
275392
|
const branchBase = `pipeline/${shortPipeline}/task-${shortId2}`;
|
|
274732
275393
|
for (let attempt = 1; attempt <= 100; attempt++) {
|
|
274733
275394
|
const suffix = attempt === 1 ? "" : `-${attempt}`;
|
|
@@ -274817,7 +275478,7 @@ function listWorktrees(projectDir2) {
|
|
|
274817
275478
|
}
|
|
274818
275479
|
}
|
|
274819
275480
|
if (current) worktrees.push(current);
|
|
274820
|
-
const worktreeBase =
|
|
275481
|
+
const worktreeBase = join32(projectDir2, WORKTREE_DIR);
|
|
274821
275482
|
return worktrees.filter((w4) => isManagedWorktreePath(w4.path, worktreeBase));
|
|
274822
275483
|
} catch {
|
|
274823
275484
|
return [];
|
|
@@ -275239,16 +275900,16 @@ var init_cost_tracker = __esm({
|
|
|
275239
275900
|
|
|
275240
275901
|
// src/orchestrate/evidence.ts
|
|
275241
275902
|
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
275242
|
-
import { join as
|
|
275903
|
+
import { join as join33 } from "path";
|
|
275243
275904
|
function writeTaskEvidence(projectDir2, pipelineId, evidence) {
|
|
275244
275905
|
try {
|
|
275245
|
-
const dir =
|
|
275906
|
+
const dir = join33(projectDir2, ".pipeline", pipelineId, "evidence", evidence.taskId.slice(0, 12));
|
|
275246
275907
|
mkdirSync9(dir, { recursive: true });
|
|
275247
275908
|
if (evidence.prompt) {
|
|
275248
|
-
safeWrite(
|
|
275909
|
+
safeWrite(join33(dir, "prompt.md"), evidence.prompt);
|
|
275249
275910
|
}
|
|
275250
275911
|
if (evidence.tailOutput) {
|
|
275251
|
-
safeWrite(
|
|
275912
|
+
safeWrite(join33(dir, "output.txt"), evidence.tailOutput);
|
|
275252
275913
|
}
|
|
275253
275914
|
if (evidence.gateResults) {
|
|
275254
275915
|
for (const g4 of evidence.gateResults) {
|
|
@@ -275257,7 +275918,7 @@ Status: ${g4.passed ? "PASS" : "FAIL"}
|
|
|
275257
275918
|
Duration: ${(g4.durationMs / 1e3).toFixed(1)}s
|
|
275258
275919
|
|
|
275259
275920
|
${g4.output}`;
|
|
275260
|
-
safeWrite(
|
|
275921
|
+
safeWrite(join33(dir, `${g4.gate}.txt`), content);
|
|
275261
275922
|
}
|
|
275262
275923
|
}
|
|
275263
275924
|
const resultJson = {
|
|
@@ -275271,7 +275932,7 @@ ${g4.output}`;
|
|
|
275271
275932
|
tokenUsage: evidence.tokenUsage,
|
|
275272
275933
|
costUSD: evidence.costUSD
|
|
275273
275934
|
};
|
|
275274
|
-
safeWrite(
|
|
275935
|
+
safeWrite(join33(dir, "result.json"), JSON.stringify(resultJson, null, 2));
|
|
275275
275936
|
return dir;
|
|
275276
275937
|
} catch {
|
|
275277
275938
|
return null;
|
|
@@ -275279,7 +275940,7 @@ ${g4.output}`;
|
|
|
275279
275940
|
}
|
|
275280
275941
|
function writePipelineSummary(projectDir2, summary) {
|
|
275281
275942
|
try {
|
|
275282
|
-
const dir =
|
|
275943
|
+
const dir = join33(projectDir2, ".pipeline", summary.pipelineId);
|
|
275283
275944
|
mkdirSync9(dir, { recursive: true });
|
|
275284
275945
|
const elapsed = (summary.elapsedMs / 1e3).toFixed(0);
|
|
275285
275946
|
const lines = [
|
|
@@ -275300,8 +275961,8 @@ function writePipelineSummary(projectDir2, summary) {
|
|
|
275300
275961
|
lines.push(`- [${status}] ${t4.taskDescription.slice(0, 80)} \u2014 ${t4.agentName}, ${dur}s${fixes}`);
|
|
275301
275962
|
}
|
|
275302
275963
|
const content = lines.join("\n") + "\n";
|
|
275303
|
-
safeWrite(
|
|
275304
|
-
return
|
|
275964
|
+
safeWrite(join33(dir, "summary.md"), content);
|
|
275965
|
+
return join33(dir, "summary.md");
|
|
275305
275966
|
} catch {
|
|
275306
275967
|
return null;
|
|
275307
275968
|
}
|
|
@@ -281898,6 +282559,7 @@ var main2 = defineCommand({
|
|
|
281898
282559
|
repair: () => Promise.resolve().then(() => (init_repair3(), repair_exports)).then((m6) => m6.default),
|
|
281899
282560
|
dashboard: () => Promise.resolve().then(() => (init_dashboard(), dashboard_exports)).then((m6) => m6.default),
|
|
281900
282561
|
cleanup: () => Promise.resolve().then(() => (init_cleanup(), cleanup_exports)).then((m6) => m6.default),
|
|
282562
|
+
purge: () => Promise.resolve().then(() => (init_purge(), purge_exports)).then((m6) => m6.default),
|
|
281901
282563
|
uninstall: () => Promise.resolve().then(() => (init_uninstall(), uninstall_exports)).then((m6) => m6.default),
|
|
281902
282564
|
orchestrate: () => Promise.resolve().then(() => (init_orchestrate(), orchestrate_exports)).then((m6) => m6.default),
|
|
281903
282565
|
workbench: () => Promise.resolve(defineCommand({
|
|
@@ -281973,6 +282635,7 @@ var main2 = defineCommand({
|
|
|
281973
282635
|
"repair",
|
|
281974
282636
|
"dashboard",
|
|
281975
282637
|
"cleanup",
|
|
282638
|
+
"purge",
|
|
281976
282639
|
"uninstall",
|
|
281977
282640
|
"orchestrate"
|
|
281978
282641
|
];
|
|
@@ -282036,6 +282699,7 @@ var main2 = defineCommand({
|
|
|
282036
282699
|
console.error(" dashboard Open standalone dashboard (read-mostly)");
|
|
282037
282700
|
console.error(" hooks Open legacy hook installer menu");
|
|
282038
282701
|
console.error(" cleanup Remove old memories");
|
|
282702
|
+
console.error(" purge Retire all memories (project by default, --all for everything)");
|
|
282039
282703
|
console.error(" sync Rules/workspace sync plus interactive wizard");
|
|
282040
282704
|
console.error(" ingest Ingest commit, log, or image knowledge");
|
|
282041
282705
|
console.error("\nRun `memorix` in an interactive terminal for memcode TUI.");
|