memorix 1.4.3 → 1.4.4
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 +19 -0
- package/README.md +11 -4
- package/README.zh-CN.md +7 -1
- package/TEAM.md +86 -86
- package/assets/star-history-dark.svg +8 -8
- package/assets/star-history-light.svg +8 -8
- package/assets/star-history.json +16 -2
- package/dist/cli/index.js +194 -109
- package/dist/cli/memcode.js +0 -0
- package/dist/index.js +39 -12
- package/dist/maintenance-runner.js +9 -7
- package/dist/media-audio-runner.js +9 -7
- package/dist/media-video-runner.js +9 -7
- package/dist/memcode/index.js +9 -7
- package/dist/memcode-runtime/CHANGELOG.md +19 -0
- package/dist/sdk.js +38 -11
- package/dist/vector-backfill-runner.js +9 -7
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +3 -3
- package/docs/API_REFERENCE.md +9 -5
- package/docs/CONFIGURATION.md +15 -5
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/docs/DEVELOPMENT.md +2 -2
- package/docs/KNOWN_ISSUES_AND_ROADMAP.md +3 -3
- package/docs/MODULES.md +1 -1
- package/docs/README.md +1 -1
- package/docs/SETUP.md +3 -3
- package/docs/hooks-architecture.md +2 -1
- package/llms-full.txt +4 -4
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/audit/index.ts +156 -156
- package/src/cli/commands/audit-list.ts +89 -89
- package/src/cli/commands/formation.ts +48 -48
- package/src/cli/commands/git-hook-install.ts +111 -111
- package/src/cli/commands/handoff.ts +54 -54
- package/src/cli/commands/hooks-status.ts +63 -63
- package/src/cli/commands/ingest.ts +44 -44
- package/src/cli/commands/integrate-shared.ts +15 -15
- package/src/cli/commands/lock.ts +82 -82
- package/src/cli/commands/media-image.ts +27 -0
- package/src/cli/commands/media.ts +8 -1
- package/src/cli/commands/memory.ts +44 -34
- package/src/cli/commands/message.ts +104 -104
- package/src/cli/commands/operator-shared.ts +62 -18
- package/src/cli/commands/poll.ts +58 -58
- package/src/cli/commands/purge-all-memory.ts +85 -85
- package/src/cli/commands/purge-project-memory.ts +83 -83
- package/src/cli/commands/reasoning.ts +118 -118
- package/src/cli/commands/skills.ts +114 -114
- package/src/cli/commands/task.ts +167 -167
- package/src/cli/commands/transfer.ts +47 -47
- package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
- package/src/cli/tui/ChatView.tsx +234 -234
- package/src/cli/tui/CommandBar.tsx +312 -312
- package/src/cli/tui/ContextRail.tsx +118 -118
- package/src/cli/tui/HeaderBar.tsx +72 -72
- package/src/cli/tui/LogoBanner.tsx +51 -51
- package/src/cli/tui/Sidebar.tsx +179 -179
- package/src/cli/tui/index.ts +41 -41
- package/src/cli/tui/markdown-render.tsx +371 -371
- package/src/cli/tui/use-mouse.ts +157 -157
- package/src/cli/tui/useNavigation.ts +56 -56
- package/src/cli/version.ts +7 -7
- package/src/cli/workbench.ts +1 -1
- package/src/dashboard/project-classification.ts +64 -64
- package/src/git/hooks-path.ts +85 -85
- package/src/hooks/pattern-detector.ts +173 -173
- package/src/hooks/significance-filter.ts +250 -250
- package/src/llm/memory-manager.ts +328 -328
- package/src/llm/provider.ts +885 -885
- package/src/llm/quality.ts +248 -248
- package/src/media/minimax.ts +9 -1
- package/src/memory/attribution-guard.ts +249 -249
- package/src/memory/disclosure-policy.ts +135 -135
- package/src/memory/entity-extractor.ts +197 -197
- package/src/memory/formation/evaluate.ts +217 -217
- package/src/memory/formation/extract.ts +361 -361
- package/src/memory/formation/index.ts +417 -417
- package/src/memory/formation/resolve.ts +344 -344
- package/src/memory/formation/types.ts +315 -315
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph.ts +197 -197
- package/src/memory/refs.ts +94 -94
- package/src/memory/secret-filter.ts +79 -79
- package/src/orchestrate/adapters/claude-stream.ts +192 -192
- package/src/orchestrate/adapters/claude.ts +111 -111
- package/src/orchestrate/adapters/codex-stream.ts +134 -134
- package/src/orchestrate/adapters/codex.ts +41 -41
- package/src/orchestrate/adapters/gemini-stream.ts +166 -166
- package/src/orchestrate/adapters/gemini.ts +42 -42
- package/src/orchestrate/adapters/index.ts +73 -73
- package/src/orchestrate/adapters/opencode-stream.ts +143 -143
- package/src/orchestrate/adapters/opencode.ts +47 -47
- package/src/orchestrate/adapters/types.ts +77 -77
- package/src/orchestrate/capability-router.ts +284 -284
- package/src/orchestrate/context-compact.ts +188 -188
- package/src/orchestrate/cost-tracker.ts +219 -219
- package/src/orchestrate/error-recovery.ts +191 -191
- package/src/orchestrate/evidence.ts +140 -140
- package/src/orchestrate/ledger.ts +110 -110
- package/src/orchestrate/memorix-bridge.ts +343 -343
- package/src/orchestrate/output-budget.ts +80 -80
- package/src/orchestrate/permission.ts +152 -152
- package/src/orchestrate/pipeline-trace.ts +131 -131
- package/src/orchestrate/prompt-builder.ts +155 -155
- package/src/orchestrate/ring-buffer.ts +37 -37
- package/src/orchestrate/task-graph.ts +389 -389
- package/src/project/aliases.ts +374 -374
- package/src/rules/adapters/trae.ts +56 -56
- package/src/rules/syncer.ts +235 -235
- package/src/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/server.ts +23 -1
- package/src/skills/mini-skills.ts +386 -386
- package/src/store/chat-store.ts +119 -119
- package/src/store/graph-store.ts +249 -249
- package/src/store/mini-skill-store.ts +349 -349
- package/src/store/persistence-json.ts +212 -212
- package/src/store/persistence.ts +291 -291
- package/src/store/project-affinity.ts +195 -195
- package/src/team/event-bus.ts +76 -76
- package/src/team/file-locks.ts +173 -173
- package/src/team/handoff.ts +161 -161
- package/src/team/messages.ts +203 -203
- package/src/team/poll.ts +132 -132
- package/src/team/tasks.ts +211 -211
- package/src/workspace/mcp-adapters/codex.ts +191 -191
- package/src/workspace/mcp-adapters/copilot.ts +105 -105
- package/src/workspace/mcp-adapters/cursor.ts +53 -53
- package/src/workspace/mcp-adapters/kiro.ts +64 -64
- package/src/workspace/mcp-adapters/opencode.ts +123 -123
- package/src/workspace/mcp-adapters/trae.ts +134 -134
- package/src/workspace/mcp-adapters/windsurf.ts +91 -91
- package/src/workspace/sanitizer.ts +60 -60
- package/dist/memcode-runtime/docs/images/exy.png +0 -0
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.4" : pkg.version;
|
|
3225
3225
|
}
|
|
3226
3226
|
var init_version = __esm({
|
|
3227
3227
|
"src/cli/version.ts"() {
|
|
@@ -10246,8 +10246,8 @@ async function acquireLock(lockPath) {
|
|
|
10246
10246
|
const code = err instanceof Error && "code" in err ? err.code : void 0;
|
|
10247
10247
|
if (code === "EEXIST" || code === "EPERM") {
|
|
10248
10248
|
try {
|
|
10249
|
-
const
|
|
10250
|
-
if (Date.now() -
|
|
10249
|
+
const stat5 = await fs2.stat(lockPath);
|
|
10250
|
+
if (Date.now() - stat5.mtimeMs > LOCK_STALE_MS) {
|
|
10251
10251
|
await fs2.unlink(lockPath).catch(() => {
|
|
10252
10252
|
});
|
|
10253
10253
|
continue;
|
|
@@ -27247,11 +27247,11 @@ async function importKnownMedia(input) {
|
|
|
27247
27247
|
async function importMediaFile(input) {
|
|
27248
27248
|
const maxBytes = input.maxBytes ?? DEFAULT_MAX_MEDIA_BYTES;
|
|
27249
27249
|
const source = path12.resolve(input.filePath);
|
|
27250
|
-
const
|
|
27251
|
-
if (
|
|
27252
|
-
if (!
|
|
27253
|
-
if (
|
|
27254
|
-
if (
|
|
27250
|
+
const stat5 = await lstat(source);
|
|
27251
|
+
if (stat5.isSymbolicLink()) throw new Error("Media import does not follow symbolic links");
|
|
27252
|
+
if (!stat5.isFile()) throw new Error("Media import accepts regular files only");
|
|
27253
|
+
if (stat5.size <= 0) throw new Error("Media import rejects empty files");
|
|
27254
|
+
if (stat5.size > maxBytes) throw new Error(`Media file is too large (${stat5.size} bytes; limit ${maxBytes})`);
|
|
27255
27255
|
const header = await readHeader(source);
|
|
27256
27256
|
const detected = detectMedia(header);
|
|
27257
27257
|
const sha2562 = await sha256File(source);
|
|
@@ -27259,7 +27259,7 @@ async function importMediaFile(input) {
|
|
|
27259
27259
|
dataDir: input.dataDir,
|
|
27260
27260
|
projectId: input.projectId,
|
|
27261
27261
|
sha256: sha2562,
|
|
27262
|
-
bytes:
|
|
27262
|
+
bytes: stat5.size,
|
|
27263
27263
|
detected,
|
|
27264
27264
|
persist: (destination) => persistFile(source, destination),
|
|
27265
27265
|
sourceKind: input.sourceKind ?? "import",
|
|
@@ -35222,7 +35222,7 @@ var init_image_models_generated = __esm({
|
|
|
35222
35222
|
api: "minimax-images",
|
|
35223
35223
|
provider: "minimax",
|
|
35224
35224
|
baseUrl: "https://api.minimax.io/v1/image_generation",
|
|
35225
|
-
input: ["text"],
|
|
35225
|
+
input: ["text", "image"],
|
|
35226
35226
|
output: ["image"],
|
|
35227
35227
|
cost: {
|
|
35228
35228
|
"input": 0,
|
|
@@ -35237,7 +35237,7 @@ var init_image_models_generated = __esm({
|
|
|
35237
35237
|
api: "minimax-images",
|
|
35238
35238
|
provider: "minimax",
|
|
35239
35239
|
baseUrl: "https://api.minimax.io/v1/image_generation",
|
|
35240
|
-
input: ["text"],
|
|
35240
|
+
input: ["text", "image"],
|
|
35241
35241
|
output: ["image"],
|
|
35242
35242
|
cost: {
|
|
35243
35243
|
"input": 0,
|
|
@@ -35254,7 +35254,7 @@ var init_image_models_generated = __esm({
|
|
|
35254
35254
|
api: "minimax-images",
|
|
35255
35255
|
provider: "minimax-cn",
|
|
35256
35256
|
baseUrl: "https://api.minimaxi.com/v1/image_generation",
|
|
35257
|
-
input: ["text"],
|
|
35257
|
+
input: ["text", "image"],
|
|
35258
35258
|
output: ["image"],
|
|
35259
35259
|
cost: {
|
|
35260
35260
|
"input": 0,
|
|
@@ -35269,7 +35269,7 @@ var init_image_models_generated = __esm({
|
|
|
35269
35269
|
api: "minimax-images",
|
|
35270
35270
|
provider: "minimax-cn",
|
|
35271
35271
|
baseUrl: "https://api.minimaxi.com/v1/image_generation",
|
|
35272
|
-
input: ["text"],
|
|
35272
|
+
input: ["text", "image"],
|
|
35273
35273
|
output: ["image"],
|
|
35274
35274
|
cost: {
|
|
35275
35275
|
"input": 0,
|
|
@@ -35368,9 +35368,10 @@ __export(minimax_exports, {
|
|
|
35368
35368
|
});
|
|
35369
35369
|
import { isIP as isIP2 } from "net";
|
|
35370
35370
|
function buildPayload(model, context, options) {
|
|
35371
|
-
|
|
35372
|
-
|
|
35373
|
-
|
|
35371
|
+
const subjectReference = context.input.filter((item) => item.type === "image").map((item) => ({
|
|
35372
|
+
type: "character",
|
|
35373
|
+
image_file: `data:${item.mimeType};base64,${item.data}`
|
|
35374
|
+
}));
|
|
35374
35375
|
const prompt2 = context.input.filter((item) => item.type === "text").map((item) => sanitizeSurrogates(item.text).trim()).filter(Boolean).join("\n");
|
|
35375
35376
|
if (!prompt2) {
|
|
35376
35377
|
throw new Error("MiniMax image generation requires a text prompt");
|
|
@@ -35381,6 +35382,7 @@ function buildPayload(model, context, options) {
|
|
|
35381
35382
|
return {
|
|
35382
35383
|
model: model.id,
|
|
35383
35384
|
prompt: prompt2,
|
|
35385
|
+
...subjectReference.length > 0 ? { subject_reference: subjectReference } : {},
|
|
35384
35386
|
...options?.aspectRatio !== void 0 ? { aspect_ratio: options.aspectRatio } : {},
|
|
35385
35387
|
...options?.width !== void 0 ? { width: options.width } : {},
|
|
35386
35388
|
...options?.height !== void 0 ? { height: options.height } : {},
|
|
@@ -78440,21 +78442,21 @@ var init_from = __esm({
|
|
|
78440
78442
|
init_fetch_blob();
|
|
78441
78443
|
({ stat: stat2 } = fs9);
|
|
78442
78444
|
blobFromSync = (path47, type) => fromBlob(statSync3(path47), path47, type);
|
|
78443
|
-
blobFrom = (path47, type) => stat2(path47).then((
|
|
78444
|
-
fileFrom = (path47, type) => stat2(path47).then((
|
|
78445
|
+
blobFrom = (path47, type) => stat2(path47).then((stat5) => fromBlob(stat5, path47, type));
|
|
78446
|
+
fileFrom = (path47, type) => stat2(path47).then((stat5) => fromFile(stat5, path47, type));
|
|
78445
78447
|
fileFromSync = (path47, type) => fromFile(statSync3(path47), path47, type);
|
|
78446
|
-
fromBlob = (
|
|
78448
|
+
fromBlob = (stat5, path47, type = "") => new fetch_blob_default([new BlobDataItem({
|
|
78447
78449
|
path: path47,
|
|
78448
|
-
size:
|
|
78449
|
-
lastModified:
|
|
78450
|
+
size: stat5.size,
|
|
78451
|
+
lastModified: stat5.mtimeMs,
|
|
78450
78452
|
start: 0
|
|
78451
78453
|
})], { type });
|
|
78452
|
-
fromFile = (
|
|
78454
|
+
fromFile = (stat5, path47, type = "") => new file_default([new BlobDataItem({
|
|
78453
78455
|
path: path47,
|
|
78454
|
-
size:
|
|
78455
|
-
lastModified:
|
|
78456
|
+
size: stat5.size,
|
|
78457
|
+
lastModified: stat5.mtimeMs,
|
|
78456
78458
|
start: 0
|
|
78457
|
-
})], basename(path47), { type, lastModified:
|
|
78459
|
+
})], basename(path47), { type, lastModified: stat5.mtimeMs });
|
|
78458
78460
|
BlobDataItem = class _BlobDataItem {
|
|
78459
78461
|
#path;
|
|
78460
78462
|
#start;
|
|
@@ -85748,7 +85750,7 @@ var require_getCredentials = __commonJS({
|
|
|
85748
85750
|
var fs31 = __require("fs");
|
|
85749
85751
|
var util_1 = __require("util");
|
|
85750
85752
|
var errorWithCode_1 = require_errorWithCode();
|
|
85751
|
-
var
|
|
85753
|
+
var readFile10 = fs31.readFile ? (0, util_1.promisify)(fs31.readFile) : async () => {
|
|
85752
85754
|
throw new errorWithCode_1.ErrorWithCode("use key rather than keyFile.", "MISSING_CREDENTIALS");
|
|
85753
85755
|
};
|
|
85754
85756
|
var ExtensionFiles;
|
|
@@ -85770,7 +85772,7 @@ var require_getCredentials = __commonJS({
|
|
|
85770
85772
|
* @returns A promise that resolves with the credentials.
|
|
85771
85773
|
*/
|
|
85772
85774
|
async getCredentials() {
|
|
85773
|
-
const key = await
|
|
85775
|
+
const key = await readFile10(this.keyFilePath, "utf8");
|
|
85774
85776
|
let body;
|
|
85775
85777
|
try {
|
|
85776
85778
|
body = JSON.parse(key);
|
|
@@ -85796,7 +85798,7 @@ var require_getCredentials = __commonJS({
|
|
|
85796
85798
|
* @returns A promise that resolves with the private key.
|
|
85797
85799
|
*/
|
|
85798
85800
|
async getCredentials() {
|
|
85799
|
-
const privateKey = await
|
|
85801
|
+
const privateKey = await readFile10(this.keyFilePath, "utf8");
|
|
85800
85802
|
return { privateKey };
|
|
85801
85803
|
}
|
|
85802
85804
|
};
|
|
@@ -87437,7 +87439,7 @@ var require_filesubjecttokensupplier = __commonJS({
|
|
|
87437
87439
|
exports.FileSubjectTokenSupplier = void 0;
|
|
87438
87440
|
var util_1 = __require("util");
|
|
87439
87441
|
var fs31 = __require("fs");
|
|
87440
|
-
var
|
|
87442
|
+
var readFile10 = (0, util_1.promisify)(fs31.readFile ?? (() => {
|
|
87441
87443
|
}));
|
|
87442
87444
|
var realpath = (0, util_1.promisify)(fs31.realpath ?? (() => {
|
|
87443
87445
|
}));
|
|
@@ -87477,7 +87479,7 @@ var require_filesubjecttokensupplier = __commonJS({
|
|
|
87477
87479
|
throw err;
|
|
87478
87480
|
}
|
|
87479
87481
|
let subjectToken;
|
|
87480
|
-
const rawText = await
|
|
87482
|
+
const rawText = await readFile10(parsedFilePath, { encoding: "utf8" });
|
|
87481
87483
|
if (this.formatType === "text") {
|
|
87482
87484
|
subjectToken = rawText;
|
|
87483
87485
|
} else if (this.formatType === "json" && this.subjectTokenFieldName) {
|
|
@@ -176394,6 +176396,7 @@ async function generateMiniMaxImages(input, dependencies = {}) {
|
|
|
176394
176396
|
...input.height !== void 0 ? { height: input.height } : {},
|
|
176395
176397
|
...input.seed !== void 0 ? { seed: input.seed } : {},
|
|
176396
176398
|
...input.promptOptimizer !== void 0 ? { promptOptimizer: input.promptOptimizer } : {},
|
|
176399
|
+
...input.subjectImages !== void 0 && input.subjectImages.length > 0 ? { subjectImages: input.subjectImages } : {},
|
|
176397
176400
|
timeoutMs
|
|
176398
176401
|
});
|
|
176399
176402
|
} catch (error40) {
|
|
@@ -176433,9 +176436,13 @@ var init_minimax2 = __esm({
|
|
|
176433
176436
|
const model = getImageModel(input.provider, input.model);
|
|
176434
176437
|
if (!model) throw new Error(`MiniMax image model is not registered: ${input.model}`);
|
|
176435
176438
|
const configuredModel = input.baseUrl ? { ...model, baseUrl: input.baseUrl } : model;
|
|
176439
|
+
const content = [
|
|
176440
|
+
...(input.subjectImages ?? []).map((image) => ({ type: "image", data: image.data, mimeType: image.mimeType })),
|
|
176441
|
+
{ type: "text", text: input.prompt }
|
|
176442
|
+
];
|
|
176436
176443
|
const response = await generateImages(
|
|
176437
176444
|
configuredModel,
|
|
176438
|
-
{ input:
|
|
176445
|
+
{ input: content },
|
|
176439
176446
|
{
|
|
176440
176447
|
apiKey: input.apiKey,
|
|
176441
176448
|
timeoutMs: input.timeoutMs,
|
|
@@ -178523,7 +178530,7 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
|
|
|
178523
178530
|
const rel = normalizeCodePath(relative(projectRoot, abs));
|
|
178524
178531
|
try {
|
|
178525
178532
|
const text2 = readFileSync7(abs, "utf-8");
|
|
178526
|
-
const
|
|
178533
|
+
const stat5 = fileStat ?? statSync4(abs);
|
|
178527
178534
|
const file2 = {
|
|
178528
178535
|
id: makeCodeFileId(projectId, rel),
|
|
178529
178536
|
projectId,
|
|
@@ -178532,8 +178539,8 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
|
|
|
178532
178539
|
contentHash: hashText(text2),
|
|
178533
178540
|
// Preserve filesystem precision. Rounding here made same-size edits in
|
|
178534
178541
|
// a short Windows timestamp window indistinguishable to refresh.
|
|
178535
|
-
mtimeMs: Number(
|
|
178536
|
-
sizeBytes: Number(
|
|
178542
|
+
mtimeMs: Number(stat5.mtimeMs),
|
|
178543
|
+
sizeBytes: Number(stat5.size),
|
|
178537
178544
|
indexedAt
|
|
178538
178545
|
};
|
|
178539
178546
|
return {
|
|
@@ -178560,18 +178567,18 @@ async function indexProjectLite(options) {
|
|
|
178560
178567
|
let skippedOversizedFiles = 0;
|
|
178561
178568
|
let unreadableFiles = 0;
|
|
178562
178569
|
for (const abs of paths) {
|
|
178563
|
-
let
|
|
178570
|
+
let stat5;
|
|
178564
178571
|
try {
|
|
178565
|
-
|
|
178572
|
+
stat5 = statSync4(abs);
|
|
178566
178573
|
} catch {
|
|
178567
178574
|
unreadableFiles++;
|
|
178568
178575
|
continue;
|
|
178569
178576
|
}
|
|
178570
|
-
if (Number(
|
|
178577
|
+
if (Number(stat5.size) > maxFileBytes) {
|
|
178571
178578
|
skippedOversizedFiles++;
|
|
178572
178579
|
continue;
|
|
178573
178580
|
}
|
|
178574
|
-
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt,
|
|
178581
|
+
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat5);
|
|
178575
178582
|
if (!attempt.delta) {
|
|
178576
178583
|
if (attempt.unreadable) unreadableFiles++;
|
|
178577
178584
|
continue;
|
|
@@ -178599,16 +178606,16 @@ async function refreshProjectLite(store2, options) {
|
|
|
178599
178606
|
for (const abs of paths) {
|
|
178600
178607
|
const rel = normalizeCodePath(relative(options.projectRoot, abs));
|
|
178601
178608
|
seenPaths.add(rel);
|
|
178602
|
-
let
|
|
178609
|
+
let stat5;
|
|
178603
178610
|
try {
|
|
178604
|
-
|
|
178611
|
+
stat5 = statSync4(abs);
|
|
178605
178612
|
} catch {
|
|
178606
178613
|
unreadableFiles++;
|
|
178607
178614
|
continue;
|
|
178608
178615
|
}
|
|
178609
178616
|
const existing = existingByPath.get(rel);
|
|
178610
|
-
const mtimeMs = Number(
|
|
178611
|
-
const sizeBytes = Number(
|
|
178617
|
+
const mtimeMs = Number(stat5.mtimeMs);
|
|
178618
|
+
const sizeBytes = Number(stat5.size);
|
|
178612
178619
|
if (sizeBytes > maxFileBytes) {
|
|
178613
178620
|
skippedOversizedFiles++;
|
|
178614
178621
|
if (existing) oversizedExistingFileIds.add(existing.id);
|
|
@@ -178618,7 +178625,7 @@ async function refreshProjectLite(store2, options) {
|
|
|
178618
178625
|
unchangedFiles++;
|
|
178619
178626
|
continue;
|
|
178620
178627
|
}
|
|
178621
|
-
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt,
|
|
178628
|
+
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat5);
|
|
178622
178629
|
if (!attempt.delta) {
|
|
178623
178630
|
if (attempt.unreadable) unreadableFiles++;
|
|
178624
178631
|
continue;
|
|
@@ -187607,9 +187614,30 @@ function emitError(message, asJson) {
|
|
|
187607
187614
|
console.error(asJson ? JSON.stringify({ error: message }, null, 2) : `Error: ${message}`);
|
|
187608
187615
|
process.exitCode = 1;
|
|
187609
187616
|
}
|
|
187617
|
+
function asStringArg(value) {
|
|
187618
|
+
if (value == null) return void 0;
|
|
187619
|
+
if (typeof value === "string") {
|
|
187620
|
+
const trimmed = value.trim();
|
|
187621
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
187622
|
+
}
|
|
187623
|
+
if (Array.isArray(value)) {
|
|
187624
|
+
const joined = value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean).join(" ");
|
|
187625
|
+
return joined.length > 0 ? joined : void 0;
|
|
187626
|
+
}
|
|
187627
|
+
return void 0;
|
|
187628
|
+
}
|
|
187629
|
+
function lastStringArg(value) {
|
|
187630
|
+
if (typeof value === "string") return value;
|
|
187631
|
+
if (Array.isArray(value)) {
|
|
187632
|
+
const strings = value.filter((item) => typeof item === "string");
|
|
187633
|
+
return strings[strings.length - 1];
|
|
187634
|
+
}
|
|
187635
|
+
return void 0;
|
|
187636
|
+
}
|
|
187610
187637
|
function parseCsvList(input) {
|
|
187611
187638
|
if (!input) return [];
|
|
187612
|
-
|
|
187639
|
+
const source = Array.isArray(input) ? input.filter((item) => typeof item === "string").join(",") : input;
|
|
187640
|
+
return source.split(",").map((item) => item.trim()).filter(Boolean);
|
|
187613
187641
|
}
|
|
187614
187642
|
function parseOptionalJsonObject(input, field = "value") {
|
|
187615
187643
|
if (!input) return void 0;
|
|
@@ -187629,43 +187657,44 @@ function shortId(id) {
|
|
|
187629
187657
|
return id ? `${id.slice(0, 8)}\u2026` : "-";
|
|
187630
187658
|
}
|
|
187631
187659
|
function parsePositiveInt(input, fallback) {
|
|
187632
|
-
|
|
187633
|
-
if (
|
|
187634
|
-
|
|
187660
|
+
const value = lastStringArg(input);
|
|
187661
|
+
if (value == null || value.trim() === "") return fallback;
|
|
187662
|
+
if (!/^\d+$/.test(value.trim())) {
|
|
187663
|
+
throw new Error(`Expected a positive integer, received "${value}".`);
|
|
187635
187664
|
}
|
|
187636
|
-
const parsed = Number(
|
|
187665
|
+
const parsed = Number(value);
|
|
187637
187666
|
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
187638
|
-
throw new Error(`Expected a positive integer, received "${
|
|
187667
|
+
throw new Error(`Expected a positive integer, received "${value}".`);
|
|
187639
187668
|
}
|
|
187640
187669
|
return parsed;
|
|
187641
187670
|
}
|
|
187642
187671
|
function coerceObservationType(input) {
|
|
187643
|
-
const normalized = input ?? "discovery";
|
|
187672
|
+
const normalized = lastStringArg(input) ?? "discovery";
|
|
187644
187673
|
if (!OBSERVATION_TYPES.includes(normalized)) {
|
|
187645
187674
|
throw new Error(
|
|
187646
|
-
`Unknown observation type "${input}". Valid types: ${OBSERVATION_TYPES.join(", ")}`
|
|
187675
|
+
`Unknown observation type "${String(input ?? "")}". Valid types: ${OBSERVATION_TYPES.join(", ")}`
|
|
187647
187676
|
);
|
|
187648
187677
|
}
|
|
187649
187678
|
return normalized;
|
|
187650
187679
|
}
|
|
187651
187680
|
function coerceObservationStatus(input) {
|
|
187652
|
-
const normalized = input ?? "resolved";
|
|
187681
|
+
const normalized = lastStringArg(input) ?? "resolved";
|
|
187653
187682
|
if (!OBSERVATION_STATUSES.includes(normalized)) {
|
|
187654
187683
|
throw new Error(
|
|
187655
|
-
`Unknown observation status "${input}". Valid statuses: ${OBSERVATION_STATUSES.join(", ")}`
|
|
187684
|
+
`Unknown observation status "${String(input ?? "")}". Valid statuses: ${OBSERVATION_STATUSES.join(", ")}`
|
|
187656
187685
|
);
|
|
187657
187686
|
}
|
|
187658
187687
|
return normalized;
|
|
187659
187688
|
}
|
|
187660
187689
|
function coerceRetrievalQuality(input) {
|
|
187661
|
-
const normalized = (input ?? "balanced").trim().toLowerCase();
|
|
187690
|
+
const normalized = (lastStringArg(input) ?? "balanced").trim().toLowerCase();
|
|
187662
187691
|
if (!RETRIEVAL_QUALITIES.includes(normalized)) {
|
|
187663
187692
|
throw new Error("quality must be fast, balanced, or thorough");
|
|
187664
187693
|
}
|
|
187665
187694
|
return normalized;
|
|
187666
187695
|
}
|
|
187667
187696
|
function coerceObservationVisibility(input) {
|
|
187668
|
-
const normalized = (input ?? "project").trim().toLowerCase();
|
|
187697
|
+
const normalized = (lastStringArg(input) ?? "project").trim().toLowerCase();
|
|
187669
187698
|
if (normalized === "personal" || normalized === "project" || normalized === "team") {
|
|
187670
187699
|
return normalized;
|
|
187671
187700
|
}
|
|
@@ -188551,23 +188580,23 @@ __export(memory_exports2, {
|
|
|
188551
188580
|
default: () => memory_default
|
|
188552
188581
|
});
|
|
188553
188582
|
function getStringArg(named, positional) {
|
|
188554
|
-
const value = named
|
|
188583
|
+
const value = asStringArg(named) || positional.join(" ").trim();
|
|
188555
188584
|
return value || void 0;
|
|
188556
188585
|
}
|
|
188557
188586
|
function getIdArg(args, positional) {
|
|
188558
|
-
return args.ids || args.id || positional.join(",");
|
|
188587
|
+
return lastStringArg(args.ids) || lastStringArg(args.id) || positional.join(",");
|
|
188559
188588
|
}
|
|
188560
188589
|
function parseObservationId(value) {
|
|
188561
|
-
const normalized = value.trim();
|
|
188590
|
+
const normalized = (asStringArg(value) ?? "").trim();
|
|
188562
188591
|
if (!/^[1-9]\d*$/.test(normalized)) {
|
|
188563
|
-
throw new Error(`Invalid observation ID: ${value}`);
|
|
188592
|
+
throw new Error(`Invalid observation ID: ${String(value ?? "")}`);
|
|
188564
188593
|
}
|
|
188565
188594
|
const id = Number(normalized);
|
|
188566
|
-
if (!Number.isSafeInteger(id)) throw new Error(`Invalid observation ID: ${value}`);
|
|
188595
|
+
if (!Number.isSafeInteger(id)) throw new Error(`Invalid observation ID: ${String(value ?? "")}`);
|
|
188567
188596
|
return id;
|
|
188568
188597
|
}
|
|
188569
188598
|
function parseObservationIds(value) {
|
|
188570
|
-
const values = parseCsvList(value);
|
|
188599
|
+
const values = parseCsvList(typeof value === "string" || Array.isArray(value) ? value : void 0);
|
|
188571
188600
|
if (values.length === 0) return [];
|
|
188572
188601
|
return values.map(parseObservationId);
|
|
188573
188602
|
}
|
|
@@ -188595,22 +188624,22 @@ function printMemoryUsage() {
|
|
|
188595
188624
|
console.log(' memorix memory long-term supersede --id <old-id> --superseded-by <qualified-id> --reason "replaced"');
|
|
188596
188625
|
}
|
|
188597
188626
|
function longTermKind(value) {
|
|
188598
|
-
const normalized = (value ?? "semantic").
|
|
188627
|
+
const normalized = (asStringArg(value) ?? "semantic").toLowerCase();
|
|
188599
188628
|
if (normalized === "episodic" || normalized === "semantic" || normalized === "procedural") return normalized;
|
|
188600
188629
|
throw new Error("long-term kind must be episodic, semantic, or procedural.");
|
|
188601
188630
|
}
|
|
188602
188631
|
function longTermScope(value) {
|
|
188603
|
-
const normalized = (value ?? "project").
|
|
188632
|
+
const normalized = (asStringArg(value) ?? "project").toLowerCase();
|
|
188604
188633
|
if (normalized === "project" || normalized === "user" || normalized === "team") return normalized;
|
|
188605
188634
|
throw new Error("long-term scope must be project, user, or team.");
|
|
188606
188635
|
}
|
|
188607
188636
|
function longTermPortability(value) {
|
|
188608
|
-
const normalized = (value ?? "project-bound").
|
|
188637
|
+
const normalized = (asStringArg(value) ?? "project-bound").toLowerCase();
|
|
188609
188638
|
if (normalized === "project-bound" || normalized === "portable") return normalized;
|
|
188610
188639
|
throw new Error("long-term portability must be project-bound or portable.");
|
|
188611
188640
|
}
|
|
188612
188641
|
function requiredLongTermReason(value) {
|
|
188613
|
-
const reason = value
|
|
188642
|
+
const reason = asStringArg(value);
|
|
188614
188643
|
if (!reason) throw new Error("reason is required for this long-term memory transition.");
|
|
188615
188644
|
return reason;
|
|
188616
188645
|
}
|
|
@@ -188674,7 +188703,7 @@ var init_memory3 = __esm({
|
|
|
188674
188703
|
run: async ({ args }) => {
|
|
188675
188704
|
const action = args._?.[0] || "";
|
|
188676
188705
|
const positional = (args._ ?? []).slice(1);
|
|
188677
|
-
const longTermAction = action === "long-term" ? (positional[0] || args.action || "list").trim().toLowerCase() : void 0;
|
|
188706
|
+
const longTermAction = action === "long-term" ? (positional[0] || asStringArg(args.action) || "list").trim().toLowerCase() : void 0;
|
|
188678
188707
|
const asJson = !!args.json;
|
|
188679
188708
|
try {
|
|
188680
188709
|
const readOnlyActions = /* @__PURE__ */ new Set(["", "search", "graph-context", "recent", "suggest-topic-key", "detail", "timeline"]);
|
|
@@ -188707,7 +188736,7 @@ var init_memory3 = __esm({
|
|
|
188707
188736
|
query,
|
|
188708
188737
|
limit: parsePositiveInt(args.graphLimit, 5)
|
|
188709
188738
|
});
|
|
188710
|
-
const format = args.format?.
|
|
188739
|
+
const format = asStringArg(args.format)?.toLowerCase();
|
|
188711
188740
|
const formatted = format === "prompt" ? formatGraphContextPrompt(packet) : [
|
|
188712
188741
|
`Graph context packet for ${project.name}`,
|
|
188713
188742
|
`- ${packet.summary}`,
|
|
@@ -188737,15 +188766,15 @@ var init_memory3 = __esm({
|
|
|
188737
188766
|
emitError('text is required for "memorix memory store"', asJson);
|
|
188738
188767
|
return;
|
|
188739
188768
|
}
|
|
188740
|
-
const title = args.title
|
|
188769
|
+
const title = asStringArg(args.title) || narrative.slice(0, 80);
|
|
188741
188770
|
const type = coerceObservationType(args.type);
|
|
188742
|
-
const topicKey = args.topicKey
|
|
188771
|
+
const topicKey = asStringArg(args.topicKey) || suggestTopicKey(type, title) || void 0;
|
|
188743
188772
|
const writeScope = resolveCliWriteScope(
|
|
188744
188773
|
{ reader, identity },
|
|
188745
188774
|
args.visibility
|
|
188746
188775
|
);
|
|
188747
188776
|
const result = await storeObservation({
|
|
188748
|
-
entityName: args.entity
|
|
188777
|
+
entityName: asStringArg(args.entity) || "general",
|
|
188749
188778
|
type,
|
|
188750
188779
|
title,
|
|
188751
188780
|
narrative,
|
|
@@ -188766,7 +188795,7 @@ var init_memory3 = __esm({
|
|
|
188766
188795
|
}
|
|
188767
188796
|
case "suggest-topic-key": {
|
|
188768
188797
|
const type = coerceObservationType(args.type);
|
|
188769
|
-
const title = args.title
|
|
188798
|
+
const title = asStringArg(args.title);
|
|
188770
188799
|
if (!title) {
|
|
188771
188800
|
emitError('title is required for "memorix memory suggest-topic-key"', asJson);
|
|
188772
188801
|
return;
|
|
@@ -188855,7 +188884,7 @@ var init_memory3 = __esm({
|
|
|
188855
188884
|
return;
|
|
188856
188885
|
}
|
|
188857
188886
|
case "deduplicate": {
|
|
188858
|
-
const query = args.query
|
|
188887
|
+
const query = asStringArg(args.query);
|
|
188859
188888
|
const dryRun = !!args.dryRun || !!args["dry-run"];
|
|
188860
188889
|
const { isLLMEnabled: isLLMEnabled2 } = await Promise.resolve().then(() => (init_provider2(), provider_exports2));
|
|
188861
188890
|
if (!isLLMEnabled2()) {
|
|
@@ -189036,7 +189065,7 @@ var init_memory3 = __esm({
|
|
|
189036
189065
|
...reader.isTeamMember ? { isTeamMember: true } : {}
|
|
189037
189066
|
};
|
|
189038
189067
|
const memoryId = () => {
|
|
189039
|
-
const id = args.id
|
|
189068
|
+
const id = asStringArg(args.id) || asStringArg(args.fromObservation) || longTermPositional[0]?.trim();
|
|
189040
189069
|
if (!id) throw new Error("long-term memory id is required.");
|
|
189041
189070
|
return id;
|
|
189042
189071
|
};
|
|
@@ -189085,11 +189114,11 @@ var init_memory3 = __esm({
|
|
|
189085
189114
|
projectId: project.id,
|
|
189086
189115
|
scope: scope(),
|
|
189087
189116
|
kind: kind(),
|
|
189088
|
-
title: args.title
|
|
189117
|
+
title: asStringArg(args.title) || content.slice(0, 100),
|
|
189089
189118
|
content,
|
|
189090
189119
|
facts: parseCsvList(args.facts),
|
|
189091
189120
|
tags: parseCsvList(args.tags),
|
|
189092
|
-
applicability: args.applicability
|
|
189121
|
+
applicability: asStringArg(args.applicability),
|
|
189093
189122
|
portability: portability(),
|
|
189094
189123
|
reader: longTermReader
|
|
189095
189124
|
});
|
|
@@ -189101,7 +189130,7 @@ var init_memory3 = __esm({
|
|
|
189101
189130
|
return;
|
|
189102
189131
|
}
|
|
189103
189132
|
case "promote": {
|
|
189104
|
-
const rawId = args.fromObservation
|
|
189133
|
+
const rawId = asStringArg(args.fromObservation) || asStringArg(args.id) || longTermPositional[0]?.trim();
|
|
189105
189134
|
const observationId2 = Number.parseInt(rawId || "", 10);
|
|
189106
189135
|
if (!Number.isFinite(observationId2)) {
|
|
189107
189136
|
emitError('fromObservation or id must be an observation ID for "memorix memory long-term promote"', asJson);
|
|
@@ -189118,7 +189147,7 @@ var init_memory3 = __esm({
|
|
|
189118
189147
|
scope: scope(),
|
|
189119
189148
|
kind: kind(),
|
|
189120
189149
|
tags: parseCsvList(args.tags),
|
|
189121
|
-
applicability: args.applicability
|
|
189150
|
+
applicability: asStringArg(args.applicability),
|
|
189122
189151
|
reader: longTermReader
|
|
189123
189152
|
});
|
|
189124
189153
|
emitResult(
|
|
@@ -189147,7 +189176,7 @@ var init_memory3 = __esm({
|
|
|
189147
189176
|
return;
|
|
189148
189177
|
}
|
|
189149
189178
|
case "supersede": {
|
|
189150
|
-
const supersededBy = args.supersededBy
|
|
189179
|
+
const supersededBy = asStringArg(args.supersededBy) || asStringArg(args["superseded-by"]);
|
|
189151
189180
|
if (!supersededBy) {
|
|
189152
189181
|
emitError('supersededBy is required for "memorix memory long-term supersede"', asJson);
|
|
189153
189182
|
return;
|
|
@@ -196908,9 +196937,9 @@ function existingLensCandidates(rootPath, lens) {
|
|
|
196908
196937
|
const absolute = path33.join(rootPath, candidate2);
|
|
196909
196938
|
try {
|
|
196910
196939
|
if (!existsSync17(absolute)) continue;
|
|
196911
|
-
const
|
|
196912
|
-
if (
|
|
196913
|
-
if (
|
|
196940
|
+
const stat5 = statSync5(absolute);
|
|
196941
|
+
if (stat5.isFile()) out.push(candidate2);
|
|
196942
|
+
if (stat5.isDirectory()) out.push(candidate2.replace(/\\/g, "/"));
|
|
196914
196943
|
} catch {
|
|
196915
196944
|
}
|
|
196916
196945
|
}
|
|
@@ -215641,8 +215670,8 @@ var init_syncer = __esm({
|
|
|
215641
215670
|
const dir = path37.dirname(pattern);
|
|
215642
215671
|
const fileGlob = path37.basename(pattern);
|
|
215643
215672
|
try {
|
|
215644
|
-
const
|
|
215645
|
-
if (!
|
|
215673
|
+
const stat5 = await fs22.stat(dir);
|
|
215674
|
+
if (!stat5.isDirectory()) {
|
|
215646
215675
|
try {
|
|
215647
215676
|
await fs22.access(pattern);
|
|
215648
215677
|
return [pattern];
|
|
@@ -257832,11 +257861,11 @@ import path40 from "path";
|
|
|
257832
257861
|
function resolveGitDir(projectRoot) {
|
|
257833
257862
|
const dotGit = path40.join(projectRoot, ".git");
|
|
257834
257863
|
if (!existsSync24(dotGit)) return null;
|
|
257835
|
-
const
|
|
257836
|
-
if (
|
|
257864
|
+
const stat5 = statSync6(dotGit);
|
|
257865
|
+
if (stat5.isDirectory()) {
|
|
257837
257866
|
return dotGit;
|
|
257838
257867
|
}
|
|
257839
|
-
if (
|
|
257868
|
+
if (stat5.isFile()) {
|
|
257840
257869
|
try {
|
|
257841
257870
|
const content = readFileSync15(dotGit, "utf-8").trim();
|
|
257842
257871
|
const match2 = content.match(/^gitdir:\s*(.+)$/);
|
|
@@ -258239,7 +258268,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
258239
258268
|
};
|
|
258240
258269
|
const server = existingServer ?? new McpServer({
|
|
258241
258270
|
name: "memorix",
|
|
258242
|
-
version: true ? "1.4.
|
|
258271
|
+
version: true ? "1.4.4" : "1.0.1"
|
|
258243
258272
|
});
|
|
258244
258273
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
258245
258274
|
server.registerTool = ((name, ...args) => {
|
|
@@ -260243,8 +260272,8 @@ ${Math.max(0, managedIds.size - result.resolved.length)} visible writable observ
|
|
|
260243
260272
|
try {
|
|
260244
260273
|
const { homedir: homedir35 } = await import("os");
|
|
260245
260274
|
const { join: join33 } = await import("path");
|
|
260246
|
-
const { readFile:
|
|
260247
|
-
const raw = await
|
|
260275
|
+
const { readFile: readFile10 } = await import("fs/promises");
|
|
260276
|
+
const raw = await readFile10(join33(homedir35(), ".memorix", "settings.json"), "utf-8");
|
|
260248
260277
|
const s4 = JSON.parse(raw);
|
|
260249
260278
|
if (s4.knowledgeGraph === true) enableKG = true;
|
|
260250
260279
|
} catch {
|
|
@@ -261922,6 +261951,16 @@ ${lines.join("\n")}` }] };
|
|
|
261922
261951
|
return { content: [{ type: "text", text: lines.filter(Boolean).join("\n") }] };
|
|
261923
261952
|
}
|
|
261924
261953
|
);
|
|
261954
|
+
function matchesImagePrefix2(bytes, prefix) {
|
|
261955
|
+
return prefix.every((byte, index) => bytes[index] === byte);
|
|
261956
|
+
}
|
|
261957
|
+
function detectReferenceImageMimeType2(bytes) {
|
|
261958
|
+
if (bytes.length >= 8 && matchesImagePrefix2(bytes, [137, 80, 78, 71, 13, 10, 26, 10])) return "image/png";
|
|
261959
|
+
if (bytes.length >= 3 && matchesImagePrefix2(bytes, [255, 216, 255])) return "image/jpeg";
|
|
261960
|
+
if (bytes.length >= 6 && (Buffer.from(bytes.subarray(0, 6)).toString("ascii") === "GIF87a" || Buffer.from(bytes.subarray(0, 6)).toString("ascii") === "GIF89a")) return "image/gif";
|
|
261961
|
+
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
|
+
return void 0;
|
|
261963
|
+
}
|
|
261925
261964
|
server.registerTool(
|
|
261926
261965
|
"memorix_media",
|
|
261927
261966
|
{
|
|
@@ -261937,6 +261976,7 @@ ${lines.join("\n")}` }] };
|
|
|
261937
261976
|
title: external_exports2.string().optional().describe("Observation title when attaching generated/imported output."),
|
|
261938
261977
|
narrative: external_exports2.string().optional().describe("Short retrieval text when attaching an asset."),
|
|
261939
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."),
|
|
261940
261980
|
model: external_exports2.string().max(160).optional().describe("Provider model for the selected media action."),
|
|
261941
261981
|
provider: external_exports2.enum(["openai", "groq"]).optional().describe("Explicit audio transcription provider."),
|
|
261942
261982
|
language: external_exports2.string().max(32).optional().describe("Optional ISO-639-1 hint for audio transcription."),
|
|
@@ -261951,7 +261991,7 @@ ${lines.join("\n")}` }] };
|
|
|
261951
261991
|
attach: external_exports2.boolean().optional().describe("Attach generated/imported output to normal project memory explicitly.")
|
|
261952
261992
|
}
|
|
261953
261993
|
},
|
|
261954
|
-
async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt: prompt2, model, provider: provider2, language, region, n: n3, ratio, width, height, duration: duration3, maxPages, maxChars, attach }) => {
|
|
261994
|
+
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 }) => {
|
|
261955
261995
|
const unresolved = requireResolvedProject("manage controlled media");
|
|
261956
261996
|
if (unresolved) return unresolved;
|
|
261957
261997
|
const safeError4 = (error40) => sanitizeCredentials(
|
|
@@ -262080,6 +262120,14 @@ ${lines.join("\n")}` }] };
|
|
|
262080
262120
|
if (model && !imageModel) throw new Error("generate-image accepts image-01 or image-01-live");
|
|
262081
262121
|
const imageRatio = ratio === "1:1" || ratio === "16:9" || ratio === "4:3" || ratio === "3:2" || ratio === "2:3" || ratio === "3:4" || ratio === "9:16" || ratio === "21:9" ? ratio : void 0;
|
|
262082
262122
|
if (ratio && !imageRatio) throw new Error("generate-image received an unsupported aspect ratio");
|
|
262123
|
+
let subjectImages;
|
|
262124
|
+
if (image?.trim()) {
|
|
262125
|
+
const { decodeBase64ImagePayload: decodeBase64ImagePayload2 } = await Promise.resolve().then(() => (init_image_payload(), image_payload_exports));
|
|
262126
|
+
const bytes = decodeBase64ImagePayload2(image);
|
|
262127
|
+
const mimeType = detectReferenceImageMimeType2(bytes);
|
|
262128
|
+
if (!mimeType) throw new Error("Reference image must be a PNG, JPEG, GIF, or WebP image");
|
|
262129
|
+
subjectImages = [{ data: bytes.toString("base64"), mimeType }];
|
|
262130
|
+
}
|
|
262083
262131
|
const { generateMiniMaxImages: generateMiniMaxImages2 } = await Promise.resolve().then(() => (init_minimax2(), minimax_exports2));
|
|
262084
262132
|
const generated = await generateMiniMaxImages2({
|
|
262085
262133
|
dataDir: projectDir2,
|
|
@@ -262090,7 +262138,8 @@ ${lines.join("\n")}` }] };
|
|
|
262090
262138
|
n: n3,
|
|
262091
262139
|
aspectRatio: imageRatio,
|
|
262092
262140
|
width,
|
|
262093
|
-
height
|
|
262141
|
+
height,
|
|
262142
|
+
subjectImages
|
|
262094
262143
|
});
|
|
262095
262144
|
const observations2 = attach === true ? await Promise.all(generated.assets.map(({ asset }) => attachAsset(
|
|
262096
262145
|
asset,
|
|
@@ -269025,11 +269074,11 @@ function getCommitInfo(cwd, ref = "HEAD") {
|
|
|
269025
269074
|
const date5 = lines[3];
|
|
269026
269075
|
const subject = lines[4];
|
|
269027
269076
|
const body = lines.slice(5).join("\n").trim();
|
|
269028
|
-
const
|
|
269077
|
+
const stat5 = runGit3(cwd, ["diff-tree", "--no-commit-id", "--numstat", hash4]).trim();
|
|
269029
269078
|
let insertions = 0;
|
|
269030
269079
|
let deletions = 0;
|
|
269031
269080
|
const filesChanged = [];
|
|
269032
|
-
for (const line of
|
|
269081
|
+
for (const line of stat5.split("\n").filter(Boolean)) {
|
|
269033
269082
|
const parts = line.split(" ");
|
|
269034
269083
|
if (parts.length >= 3) {
|
|
269035
269084
|
const ins = parseInt(parts[0], 10) || 0;
|
|
@@ -269869,6 +269918,37 @@ var init_embedding = __esm({
|
|
|
269869
269918
|
}
|
|
269870
269919
|
});
|
|
269871
269920
|
|
|
269921
|
+
// src/cli/commands/media-image.ts
|
|
269922
|
+
import { readFile as readFile8, stat as stat4 } from "fs/promises";
|
|
269923
|
+
function matchesImagePrefix(bytes, prefix) {
|
|
269924
|
+
return prefix.every((byte, index) => bytes[index] === byte);
|
|
269925
|
+
}
|
|
269926
|
+
function detectReferenceImageMimeType(bytes) {
|
|
269927
|
+
if (bytes.length >= 8 && matchesImagePrefix(bytes, [137, 80, 78, 71, 13, 10, 26, 10])) return "image/png";
|
|
269928
|
+
if (bytes.length >= 3 && matchesImagePrefix(bytes, [255, 216, 255])) return "image/jpeg";
|
|
269929
|
+
if (bytes.length >= 6 && (bytes.subarray(0, 6).toString("ascii") === "GIF87a" || bytes.subarray(0, 6).toString("ascii") === "GIF89a")) return "image/gif";
|
|
269930
|
+
if (bytes.length >= 12 && bytes.subarray(0, 4).toString("ascii") === "RIFF" && bytes.subarray(8, 12).toString("ascii") === "WEBP") return "image/webp";
|
|
269931
|
+
return void 0;
|
|
269932
|
+
}
|
|
269933
|
+
async function readSubjectImage(filePath) {
|
|
269934
|
+
const fileStats = await stat4(filePath);
|
|
269935
|
+
if (fileStats.size > MAX_VISION_IMAGE_BYTES) {
|
|
269936
|
+
throw new Error(`Reference image exceeds the ${MAX_VISION_IMAGE_BYTES}-byte visual analysis limit`);
|
|
269937
|
+
}
|
|
269938
|
+
const bytes = await readFile8(filePath);
|
|
269939
|
+
if (bytes.length === 0) throw new Error(`Reference image is empty: ${filePath}`);
|
|
269940
|
+
const mimeType = detectReferenceImageMimeType(bytes);
|
|
269941
|
+
if (!mimeType) throw new Error("Reference image must be a PNG, JPEG, GIF, or WebP file");
|
|
269942
|
+
return { data: bytes.toString("base64"), mimeType };
|
|
269943
|
+
}
|
|
269944
|
+
var init_media_image = __esm({
|
|
269945
|
+
"src/cli/commands/media-image.ts"() {
|
|
269946
|
+
"use strict";
|
|
269947
|
+
init_esm_shims();
|
|
269948
|
+
init_image_payload();
|
|
269949
|
+
}
|
|
269950
|
+
});
|
|
269951
|
+
|
|
269872
269952
|
// src/cli/commands/media.ts
|
|
269873
269953
|
var media_exports = {};
|
|
269874
269954
|
__export(media_exports, {
|
|
@@ -269954,7 +270034,7 @@ function help() {
|
|
|
269954
270034
|
' memorix media attach --asset <asset-id> [--title "Architecture"] [--text "..."]',
|
|
269955
270035
|
" memorix media embed --asset <asset-id>",
|
|
269956
270036
|
" memorix media similar --asset <asset-id> [--limit 10]",
|
|
269957
|
-
' memorix media generate image --prompt "..." [--model image-01] [--attach]',
|
|
270037
|
+
' memorix media generate image --prompt "..." [--model image-01] [--image ./reference.png] [--attach]',
|
|
269958
270038
|
' memorix media generate video --prompt "..." [--model MiniMax-H3] [--duration 5] [--ratio 16:9] [--attach]',
|
|
269959
270039
|
" memorix media status --job <media-job-id>",
|
|
269960
270040
|
" memorix media cancel --job <media-job-id>",
|
|
@@ -269979,6 +270059,7 @@ var init_media = __esm({
|
|
|
269979
270059
|
init_minimax2();
|
|
269980
270060
|
init_video_jobs();
|
|
269981
270061
|
init_audio_jobs();
|
|
270062
|
+
init_media_image();
|
|
269982
270063
|
init_operator_shared();
|
|
269983
270064
|
media_default = defineCommand({
|
|
269984
270065
|
meta: {
|
|
@@ -269996,6 +270077,7 @@ var init_media = __esm({
|
|
|
269996
270077
|
concepts: { type: "string", description: "Comma-separated concepts when attaching" },
|
|
269997
270078
|
visibility: { type: "string", description: "Observation visibility when attaching" },
|
|
269998
270079
|
prompt: { type: "string", description: "Generation prompt" },
|
|
270080
|
+
image: { type: "string", description: "Path to a reference image for image-to-image generation" },
|
|
269999
270081
|
model: { type: "string", description: "Provider model" },
|
|
270000
270082
|
provider: { type: "string", description: "Audio transcription provider: openai or groq" },
|
|
270001
270083
|
language: { type: "string", description: "Optional ISO-639-1 hint for audio transcription" },
|
|
@@ -270067,6 +270149,8 @@ var init_media = __esm({
|
|
|
270067
270149
|
);
|
|
270068
270150
|
return;
|
|
270069
270151
|
}
|
|
270152
|
+
const referenceImagePath = getValue(args.image);
|
|
270153
|
+
const subjectImages = referenceImagePath ? [await readSubjectImage(referenceImagePath)] : void 0;
|
|
270070
270154
|
const generated = await generateMiniMaxImages({
|
|
270071
270155
|
dataDir,
|
|
270072
270156
|
projectId: project.id,
|
|
@@ -270079,6 +270163,7 @@ var init_media = __esm({
|
|
|
270079
270163
|
height: parseOptionalInteger(args.height, "height", 1, 8192),
|
|
270080
270164
|
seed: parseOptionalInteger(args.seed, "seed", 0, 2147483647),
|
|
270081
270165
|
promptOptimizer: args.promptOptimizer === true || args["prompt-optimizer"] === true,
|
|
270166
|
+
subjectImages,
|
|
270082
270167
|
maxBytes: parseByteLimit(args.maxBytes ?? args["max-bytes"], 100 * 1024 * 1024)
|
|
270083
270168
|
});
|
|
270084
270169
|
const observations2 = args.attach === true ? await Promise.all(generated.assets.map(({ asset }) => attachMediaAssetToObservation({
|
|
@@ -271045,14 +271130,14 @@ function doLogs(follow, lines) {
|
|
|
271045
271130
|
let position = fs26.statSync(logFile).size;
|
|
271046
271131
|
const watcher = fs26.watch(logFile, () => {
|
|
271047
271132
|
try {
|
|
271048
|
-
const
|
|
271049
|
-
if (
|
|
271133
|
+
const stat5 = fs26.statSync(logFile);
|
|
271134
|
+
if (stat5.size > position) {
|
|
271050
271135
|
const fd = fs26.openSync(logFile, "r");
|
|
271051
|
-
const buf = Buffer.alloc(
|
|
271136
|
+
const buf = Buffer.alloc(stat5.size - position);
|
|
271052
271137
|
fs26.readSync(fd, buf, 0, buf.length, position);
|
|
271053
271138
|
fs26.closeSync(fd);
|
|
271054
271139
|
process.stdout.write(buf.toString("utf-8"));
|
|
271055
|
-
position =
|
|
271140
|
+
position = stat5.size;
|
|
271056
271141
|
}
|
|
271057
271142
|
} catch {
|
|
271058
271143
|
}
|
|
@@ -271169,7 +271254,7 @@ __export(agent_integrations_exports, {
|
|
|
271169
271254
|
});
|
|
271170
271255
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
271171
271256
|
import { existsSync as existsSync28 } from "fs";
|
|
271172
|
-
import { mkdir as mkdir8, readFile as
|
|
271257
|
+
import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile9 } from "fs/promises";
|
|
271173
271258
|
import { basename as basename5, dirname as dirname8, resolve as resolve4 } from "path";
|
|
271174
271259
|
import { homedir as homedir33 } from "os";
|
|
271175
271260
|
function requestedAgents(agent) {
|
|
@@ -271312,7 +271397,7 @@ async function inspectCodexPluginBundle() {
|
|
|
271312
271397
|
}
|
|
271313
271398
|
let manifest = null;
|
|
271314
271399
|
try {
|
|
271315
|
-
manifest = asRecord3(JSON.parse(await
|
|
271400
|
+
manifest = asRecord3(JSON.parse(await readFile9(manifestPath, "utf-8")));
|
|
271316
271401
|
} catch {
|
|
271317
271402
|
return {
|
|
271318
271403
|
scope: "global",
|
|
@@ -271341,7 +271426,7 @@ async function inspectCodexPluginBundle() {
|
|
|
271341
271426
|
issues.push("codex-plugin-mcp-manifest-missing");
|
|
271342
271427
|
} else {
|
|
271343
271428
|
try {
|
|
271344
|
-
const mcpConfig = asRecord3(JSON.parse(await
|
|
271429
|
+
const mcpConfig = asRecord3(JSON.parse(await readFile9(mcpPath, "utf-8")));
|
|
271345
271430
|
const server = coerceMcpServer("memorix", asRecord3(mcpConfig?.mcpServers)?.memorix);
|
|
271346
271431
|
if (!server || !isRecommendedStdioServer(server)) {
|
|
271347
271432
|
issues.push("codex-plugin-mcp-manifest-invalid");
|
|
@@ -271355,7 +271440,7 @@ async function inspectCodexPluginBundle() {
|
|
|
271355
271440
|
issues.push("codex-hook-manifest-missing");
|
|
271356
271441
|
} else {
|
|
271357
271442
|
try {
|
|
271358
|
-
const hooksConfig = asRecord3(JSON.parse(await
|
|
271443
|
+
const hooksConfig = asRecord3(JSON.parse(await readFile9(hooksPath, "utf-8")));
|
|
271359
271444
|
const hooks = asRecord3(hooksConfig?.hooks);
|
|
271360
271445
|
declared = hooks ? Object.keys(hooks) : [];
|
|
271361
271446
|
if (CODEX_HOOK_EVENTS.some((event) => !declared.includes(event))) {
|
|
@@ -271390,7 +271475,7 @@ async function inspectCodexMarketplace() {
|
|
|
271390
271475
|
}
|
|
271391
271476
|
let catalog = null;
|
|
271392
271477
|
try {
|
|
271393
|
-
catalog = asRecord3(JSON.parse(await
|
|
271478
|
+
catalog = asRecord3(JSON.parse(await readFile9(marketplacePath, "utf-8")));
|
|
271394
271479
|
} catch {
|
|
271395
271480
|
return {
|
|
271396
271481
|
scope: "global",
|
|
@@ -271480,7 +271565,7 @@ async function inspectCodexHookTrust() {
|
|
|
271480
271565
|
}
|
|
271481
271566
|
let config2 = "";
|
|
271482
271567
|
try {
|
|
271483
|
-
config2 = await
|
|
271568
|
+
config2 = await readFile9(configPath, "utf-8");
|
|
271484
271569
|
} catch {
|
|
271485
271570
|
return {
|
|
271486
271571
|
scope: "global",
|
|
@@ -271607,7 +271692,7 @@ async function inspectClaudeLocalMcp(projectRoot) {
|
|
|
271607
271692
|
}
|
|
271608
271693
|
let config2 = {};
|
|
271609
271694
|
try {
|
|
271610
|
-
config2 = JSON.parse(await
|
|
271695
|
+
config2 = JSON.parse(await readFile9(configPath, "utf-8"));
|
|
271611
271696
|
} catch {
|
|
271612
271697
|
return {
|
|
271613
271698
|
scope: "local",
|
|
@@ -271656,7 +271741,7 @@ async function installClaudeLocalMcpConfig(projectRoot) {
|
|
|
271656
271741
|
const configPath = getClaudeLocalConfigPath();
|
|
271657
271742
|
let config2 = {};
|
|
271658
271743
|
try {
|
|
271659
|
-
config2 = JSON.parse(await
|
|
271744
|
+
config2 = JSON.parse(await readFile9(configPath, "utf-8"));
|
|
271660
271745
|
} catch {
|
|
271661
271746
|
config2 = {};
|
|
271662
271747
|
}
|
|
@@ -271695,7 +271780,7 @@ async function inspectCodexPluginMcp() {
|
|
|
271695
271780
|
};
|
|
271696
271781
|
}
|
|
271697
271782
|
try {
|
|
271698
|
-
const config2 = asRecord3(JSON.parse(await
|
|
271783
|
+
const config2 = asRecord3(JSON.parse(await readFile9(mcpPath, "utf-8")));
|
|
271699
271784
|
const server = coerceMcpServer("memorix", asRecord3(config2?.mcpServers)?.memorix);
|
|
271700
271785
|
if (!server) {
|
|
271701
271786
|
return {
|
|
@@ -271760,7 +271845,7 @@ async function inspectMcp(agent, projectRoot, scope) {
|
|
|
271760
271845
|
});
|
|
271761
271846
|
continue;
|
|
271762
271847
|
}
|
|
271763
|
-
const content = await
|
|
271848
|
+
const content = await readFile9(configPath, "utf-8");
|
|
271764
271849
|
if (agent === "claude" && targetScope === "global") {
|
|
271765
271850
|
try {
|
|
271766
271851
|
const parsed = JSON.parse(content);
|
|
@@ -271837,7 +271922,7 @@ async function inspectGuidance(agent, projectRoot, scope) {
|
|
|
271837
271922
|
});
|
|
271838
271923
|
continue;
|
|
271839
271924
|
}
|
|
271840
|
-
const content = await
|
|
271925
|
+
const content = await readFile9(rulesPath, "utf-8");
|
|
271841
271926
|
const issues = isCurrentGuidance(content) ? [] : ["guidance-outdated"];
|
|
271842
271927
|
checks.push({
|
|
271843
271928
|
scope: targetScope,
|