memorix 1.9.7 → 1.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/dist/cli/index.js +192 -11
- package/dist/index.js +184 -11
- package/dist/maintenance-runner.js +22 -5
- package/dist/media-audio-runner.js +22 -5
- package/dist/media-video-runner.js +22 -5
- package/dist/memcode-runtime/CHANGELOG.md +15 -0
- package/dist/sdk.js +183 -10
- package/dist/vector-backfill-runner.js +22 -5
- package/docs/CONFIGURATION.md +22 -0
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/README.md +1 -1
- package/docs/SETUP.md +1 -1
- package/package.json +1 -1
- package/plugins/antigravity/memorix/plugin.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/hermes/memorix/plugin.yaml +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/cli/commands/init.ts +7 -1
- package/src/cli/tui/ConfigureView.tsx +2 -0
- package/src/config/dotenv-loader.ts +1 -0
- package/src/config/resolved-config.ts +19 -5
- package/src/config/yaml-loader.ts +2 -2
- package/src/config.ts +5 -1
- package/src/dashboard/server.ts +3 -0
- package/src/hooks/installers/index.ts +160 -3
- package/src/llm/provider.ts +2 -1
- package/src/multimodal/image-loader.ts +2 -2
package/dist/index.js
CHANGED
|
@@ -3818,6 +3818,7 @@ function getResolvedConfig(options = {}) {
|
|
|
3818
3818
|
const legacy = loadFileConfig(homeDir);
|
|
3819
3819
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
3820
3820
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3821
|
+
const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
|
|
3821
3822
|
const memoryLlmProvider = first(
|
|
3822
3823
|
process.env.MEMORIX_LLM_PROVIDER,
|
|
3823
3824
|
toml.memory?.llm?.provider,
|
|
@@ -3838,16 +3839,18 @@ function getResolvedConfig(options = {}) {
|
|
|
3838
3839
|
);
|
|
3839
3840
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3840
3841
|
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
3842
|
+
const isRequesty = memoryLlmProvider === "requesty";
|
|
3843
|
+
const usesPresetKeyOnly = isAtlasCloud || isRequesty;
|
|
3841
3844
|
const memoryLlmApiKey = first(
|
|
3842
3845
|
process.env.MEMORIX_LLM_API_KEY,
|
|
3843
3846
|
process.env.MEMORIX_API_KEY,
|
|
3844
3847
|
toml.memory?.llm?.api_key,
|
|
3845
3848
|
yaml.llm?.apiKey,
|
|
3846
3849
|
legacy.llm?.apiKey,
|
|
3847
|
-
// Never borrow another provider's credentials for the Atlas Cloud
|
|
3848
|
-
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
3849
|
-
|
|
3850
|
-
|
|
3850
|
+
// Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
|
|
3851
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
|
|
3852
|
+
usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
3853
|
+
usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
|
|
3851
3854
|
);
|
|
3852
3855
|
const resolved = {
|
|
3853
3856
|
agent: {
|
|
@@ -3896,7 +3899,7 @@ function getResolvedConfig(options = {}) {
|
|
|
3896
3899
|
provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
|
|
3897
3900
|
model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
|
|
3898
3901
|
baseUrl: embeddingBaseUrl,
|
|
3899
|
-
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
|
|
3902
|
+
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
|
|
3900
3903
|
dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
|
|
3901
3904
|
},
|
|
3902
3905
|
rerank: resolveRerankLane({
|
|
@@ -4027,6 +4030,7 @@ function getEnvSourceNames() {
|
|
|
4027
4030
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
4028
4031
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
4029
4032
|
"OPENROUTER_API_KEY",
|
|
4033
|
+
"REQUESTY_API_KEY",
|
|
4030
4034
|
"ATLASCLOUD_API_KEY"
|
|
4031
4035
|
].filter((name) => process.env[name]);
|
|
4032
4036
|
}
|
|
@@ -4039,6 +4043,15 @@ function isOpenRouterUrl(value) {
|
|
|
4039
4043
|
return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
|
|
4040
4044
|
}
|
|
4041
4045
|
}
|
|
4046
|
+
function isRequestyUrl(value) {
|
|
4047
|
+
if (!value) return false;
|
|
4048
|
+
try {
|
|
4049
|
+
const url = new URL(value);
|
|
4050
|
+
return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
|
|
4051
|
+
} catch {
|
|
4052
|
+
return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4042
4055
|
function isOpenRouterMemoryLane(provider2, baseUrl) {
|
|
4043
4056
|
return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
|
|
4044
4057
|
}
|
|
@@ -4193,6 +4206,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
|
|
|
4193
4206
|
if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
|
|
4194
4207
|
return "qwen/qwen3-embedding-8b";
|
|
4195
4208
|
}
|
|
4209
|
+
if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
|
|
4210
|
+
return "openai/text-embedding-3-small";
|
|
4211
|
+
}
|
|
4196
4212
|
} catch {
|
|
4197
4213
|
}
|
|
4198
4214
|
return "text-embedding-3-small";
|
|
@@ -7007,6 +7023,7 @@ var init_provider2 = __esm({
|
|
|
7007
7023
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
7008
7024
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
7009
7025
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
7026
|
+
requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
|
|
7010
7027
|
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
7011
7028
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
7012
7029
|
};
|
|
@@ -160104,7 +160121,7 @@ var init_request_context = __esm({
|
|
|
160104
160121
|
function getMcpServerInfo() {
|
|
160105
160122
|
return {
|
|
160106
160123
|
name: "memorix",
|
|
160107
|
-
version: true ? "1.9.
|
|
160124
|
+
version: true ? "1.9.9" : "1.0.1"
|
|
160108
160125
|
};
|
|
160109
160126
|
}
|
|
160110
160127
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -167573,7 +167590,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
167573
167590
|
"MEMORIX_API_KEY",
|
|
167574
167591
|
"OPENAI_API_KEY",
|
|
167575
167592
|
"ANTHROPIC_API_KEY",
|
|
167576
|
-
...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : []
|
|
167593
|
+
...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : [],
|
|
167594
|
+
...resolved.memory.llm.provider === "requesty" ? ["REQUESTY_API_KEY"] : []
|
|
167577
167595
|
];
|
|
167578
167596
|
if (llmKey) {
|
|
167579
167597
|
const src = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
|
|
@@ -169158,7 +169176,7 @@ async function analyzeImage(input) {
|
|
|
169158
169176
|
const config = getLLMConfig();
|
|
169159
169177
|
if (!OPENAI_COMPATIBLE_PROVIDERS.has(config.provider)) {
|
|
169160
169178
|
throw new Error(
|
|
169161
|
-
`Image analysis requires an OpenAI-compatible provider (openai, openrouter, or custom). Current provider "${config.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
|
|
169179
|
+
`Image analysis requires an OpenAI-compatible provider (openai, openrouter, requesty, or custom). Current provider "${config.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
|
|
169162
169180
|
);
|
|
169163
169181
|
}
|
|
169164
169182
|
const bytes = decodeBase64ImagePayload(input.base64, MAX_VISION_IMAGE_BYTES);
|
|
@@ -169197,7 +169215,7 @@ var init_image_loader = __esm({
|
|
|
169197
169215
|
init_provider2();
|
|
169198
169216
|
init_secret_filter();
|
|
169199
169217
|
init_image_payload();
|
|
169200
|
-
OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "custom"]);
|
|
169218
|
+
OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "requesty", "custom"]);
|
|
169201
169219
|
MAX_VISION_PROMPT_CHARS = 12e3;
|
|
169202
169220
|
MAX_VISION_DESCRIPTION_CHARS = 12e3;
|
|
169203
169221
|
MAX_VISION_LABELS = 50;
|
|
@@ -170093,6 +170111,161 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
170093
170111
|
},
|
|
170094
170112
|
};
|
|
170095
170113
|
};
|
|
170114
|
+
|
|
170115
|
+
/**
|
|
170116
|
+
* OpenCode v2 compatibility layer. Keep this beside the v1 export so one
|
|
170117
|
+
* generated file can be loaded by both host generations during migration.
|
|
170118
|
+
*/
|
|
170119
|
+
const v2HookCommand = ${hookCommand};
|
|
170120
|
+
|
|
170121
|
+
function v2ReportHookFailure(eventName, detail) {
|
|
170122
|
+
if (process.env.MEMORIX_HOOK_DEBUG !== '1') return;
|
|
170123
|
+
console.error('[memorix-plugin] v2 hook delivery failed:', eventName, detail);
|
|
170124
|
+
}
|
|
170125
|
+
|
|
170126
|
+
function v2EventData(event) {
|
|
170127
|
+
return event && typeof event.data === 'object' && event.data !== null ? event.data : {};
|
|
170128
|
+
}
|
|
170129
|
+
|
|
170130
|
+
function v2SessionId(event) {
|
|
170131
|
+
const data = v2EventData(event);
|
|
170132
|
+
const value = data.sessionID ?? data.sessionId ?? data.session_id
|
|
170133
|
+
?? event?.sessionID ?? event?.sessionId;
|
|
170134
|
+
return typeof value === 'string' ? value : '';
|
|
170135
|
+
}
|
|
170136
|
+
|
|
170137
|
+
function v2RunHook(payload, directory, sessionId) {
|
|
170138
|
+
const nextPayload = { agent: 'opencode', cwd: directory, ...payload };
|
|
170139
|
+
if (sessionId) nextPayload.session_id = sessionId;
|
|
170140
|
+
const eventName = nextPayload.hook_event_name || 'unknown';
|
|
170141
|
+
try {
|
|
170142
|
+
const result = spawnSync(v2HookCommand, ['hook'], {
|
|
170143
|
+
input: JSON.stringify(nextPayload),
|
|
170144
|
+
timeout: 10_000,
|
|
170145
|
+
encoding: 'utf-8',
|
|
170146
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
170147
|
+
shell: process.platform === 'win32',
|
|
170148
|
+
windowsHide: true,
|
|
170149
|
+
});
|
|
170150
|
+
if (result.status !== 0) {
|
|
170151
|
+
v2ReportHookFailure(eventName, {
|
|
170152
|
+
exit: result.status,
|
|
170153
|
+
stderr: (result.stderr || '').slice(0, 200),
|
|
170154
|
+
error: result.error?.message,
|
|
170155
|
+
});
|
|
170156
|
+
}
|
|
170157
|
+
} catch (error) {
|
|
170158
|
+
v2ReportHookFailure(eventName, error?.message ?? error);
|
|
170159
|
+
}
|
|
170160
|
+
}
|
|
170161
|
+
|
|
170162
|
+
function v2SessionState(states, sessionId) {
|
|
170163
|
+
const key = sessionId || '__unknown__';
|
|
170164
|
+
let state = states.get(key);
|
|
170165
|
+
if (!state) {
|
|
170166
|
+
state = { pendingText: '', lastDeliveredKey: '' };
|
|
170167
|
+
states.set(key, state);
|
|
170168
|
+
}
|
|
170169
|
+
return state;
|
|
170170
|
+
}
|
|
170171
|
+
|
|
170172
|
+
function v2FlushAssistant(state, directory, sessionId) {
|
|
170173
|
+
const text = state.pendingText.trim();
|
|
170174
|
+
if (!text || text === state.lastDeliveredKey) return;
|
|
170175
|
+
v2RunHook({ hook_event_name: 'message.updated', ai_response: text }, directory, sessionId);
|
|
170176
|
+
state.lastDeliveredKey = text;
|
|
170177
|
+
state.pendingText = '';
|
|
170178
|
+
}
|
|
170179
|
+
|
|
170180
|
+
function v2FilePath(file) {
|
|
170181
|
+
if (typeof file === 'string') return file;
|
|
170182
|
+
if (!file || typeof file !== 'object') return '';
|
|
170183
|
+
return file.path ?? file.file ?? file.name ?? '';
|
|
170184
|
+
}
|
|
170185
|
+
|
|
170186
|
+
function v2HandleEvent(event, directory, states) {
|
|
170187
|
+
if (!event || typeof event !== 'object') return;
|
|
170188
|
+
const type = typeof event.type === 'string' ? event.type : '';
|
|
170189
|
+
const data = v2EventData(event);
|
|
170190
|
+
const sessionId = v2SessionId(event);
|
|
170191
|
+
const state = v2SessionState(states, sessionId);
|
|
170192
|
+
const run = (payload) => v2RunHook(payload, directory, sessionId);
|
|
170193
|
+
|
|
170194
|
+
switch (type) {
|
|
170195
|
+
case 'session.created':
|
|
170196
|
+
run({ hook_event_name: 'session.created' });
|
|
170197
|
+
break;
|
|
170198
|
+
case 'session.text.delta':
|
|
170199
|
+
state.pendingText += typeof data.delta === 'string' ? data.delta : (typeof data.text === 'string' ? data.text : '');
|
|
170200
|
+
break;
|
|
170201
|
+
case 'session.message.updated':
|
|
170202
|
+
case 'message.updated':
|
|
170203
|
+
if (data.role === 'assistant' && typeof data.text === 'string') state.pendingText = data.text;
|
|
170204
|
+
break;
|
|
170205
|
+
case 'session.step.ended': {
|
|
170206
|
+
const files = Array.isArray(data.files) ? data.files : [];
|
|
170207
|
+
for (const file of files) {
|
|
170208
|
+
const filePath = v2FilePath(file);
|
|
170209
|
+
if (filePath) run({ hook_event_name: 'file.edited', file_path: filePath });
|
|
170210
|
+
}
|
|
170211
|
+
if (typeof data.text === 'string') state.pendingText += data.text;
|
|
170212
|
+
break;
|
|
170213
|
+
}
|
|
170214
|
+
case 'session.idle':
|
|
170215
|
+
v2FlushAssistant(state, directory, sessionId);
|
|
170216
|
+
run({ hook_event_name: 'session.idle' });
|
|
170217
|
+
break;
|
|
170218
|
+
case 'session.compacted':
|
|
170219
|
+
run({ hook_event_name: 'session.compacted' });
|
|
170220
|
+
break;
|
|
170221
|
+
default:
|
|
170222
|
+
break;
|
|
170223
|
+
}
|
|
170224
|
+
}
|
|
170225
|
+
|
|
170226
|
+
function setup(ctx) {
|
|
170227
|
+
const directory = ctx?.location?.directory || ctx?.location?.worktree || process.cwd();
|
|
170228
|
+
const controller = new AbortController();
|
|
170229
|
+
const states = new Map();
|
|
170230
|
+
|
|
170231
|
+
if (ctx?.tool?.hook) {
|
|
170232
|
+
try {
|
|
170233
|
+
Promise.resolve(ctx.tool.hook('execute.after', async (event) => {
|
|
170234
|
+
const sessionId = v2SessionId(event);
|
|
170235
|
+
const data = event && typeof event.input === 'object' ? event.input : {};
|
|
170236
|
+
const tool = event?.tool ?? event?.name ?? '';
|
|
170237
|
+
v2RunHook({
|
|
170238
|
+
hook_event_name: 'tool.execute.after',
|
|
170239
|
+
tool_name: tool,
|
|
170240
|
+
tool_input: data,
|
|
170241
|
+
}, directory, sessionId);
|
|
170242
|
+
if (tool === 'shell') {
|
|
170243
|
+
v2RunHook({
|
|
170244
|
+
hook_event_name: 'command.executed',
|
|
170245
|
+
command: data.command ?? data.cmd ?? '',
|
|
170246
|
+
}, directory, sessionId);
|
|
170247
|
+
}
|
|
170248
|
+
})).catch((error) => v2ReportHookFailure('execute.after', error?.message ?? error));
|
|
170249
|
+
} catch (error) {
|
|
170250
|
+
v2ReportHookFailure('execute.after', error?.message ?? error);
|
|
170251
|
+
}
|
|
170252
|
+
}
|
|
170253
|
+
|
|
170254
|
+
if (ctx?.event?.subscribe) {
|
|
170255
|
+
void (async () => {
|
|
170256
|
+
try {
|
|
170257
|
+
const stream = ctx.event.subscribe({ signal: controller.signal });
|
|
170258
|
+
for await (const event of stream) v2HandleEvent(event, directory, states);
|
|
170259
|
+
} catch (error) {
|
|
170260
|
+
if (!controller.signal.aborted) v2ReportHookFailure('event.subscribe', error?.message ?? error);
|
|
170261
|
+
}
|
|
170262
|
+
})();
|
|
170263
|
+
}
|
|
170264
|
+
|
|
170265
|
+
return () => controller.abort();
|
|
170266
|
+
}
|
|
170267
|
+
|
|
170268
|
+
export default { id: 'memorix', setup };
|
|
170096
170269
|
`;
|
|
170097
170270
|
}
|
|
170098
170271
|
async function installOpenCodeSkills(projectRoot, global2 = false) {
|
|
@@ -170918,7 +171091,7 @@ var init_installers = __esm({
|
|
|
170918
171091
|
"use strict";
|
|
170919
171092
|
init_esm_shims();
|
|
170920
171093
|
init_official_skills();
|
|
170921
|
-
OPENCODE_PLUGIN_VERSION =
|
|
171094
|
+
OPENCODE_PLUGIN_VERSION = 8;
|
|
170922
171095
|
AGENT_SKILL_DIRS = {
|
|
170923
171096
|
cursor: { project: path34.join(".cursor", "skills"), global: path34.join(".cursor", "skills") },
|
|
170924
171097
|
windsurf: { project: path34.join(".windsurf", "skills"), global: path34.join(".windsurf", "skills") },
|
|
@@ -176442,7 +176615,7 @@ var init_serve_shared = __esm({
|
|
|
176442
176615
|
|
|
176443
176616
|
// src/cli/version.ts
|
|
176444
176617
|
function getCliVersion() {
|
|
176445
|
-
return true ? "1.9.
|
|
176618
|
+
return true ? "1.9.9" : pkg.version;
|
|
176446
176619
|
}
|
|
176447
176620
|
var init_version3 = __esm({
|
|
176448
176621
|
"src/cli/version.ts"() {
|
|
@@ -2089,6 +2089,7 @@ function getResolvedConfig(options = {}) {
|
|
|
2089
2089
|
const legacy = loadFileConfig(homeDir);
|
|
2090
2090
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
2091
2091
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2092
|
+
const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
|
|
2092
2093
|
const memoryLlmProvider = first(
|
|
2093
2094
|
process.env.MEMORIX_LLM_PROVIDER,
|
|
2094
2095
|
toml.memory?.llm?.provider,
|
|
@@ -2109,16 +2110,18 @@ function getResolvedConfig(options = {}) {
|
|
|
2109
2110
|
);
|
|
2110
2111
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2111
2112
|
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
2113
|
+
const isRequesty = memoryLlmProvider === "requesty";
|
|
2114
|
+
const usesPresetKeyOnly = isAtlasCloud || isRequesty;
|
|
2112
2115
|
const memoryLlmApiKey = first(
|
|
2113
2116
|
process.env.MEMORIX_LLM_API_KEY,
|
|
2114
2117
|
process.env.MEMORIX_API_KEY,
|
|
2115
2118
|
toml.memory?.llm?.api_key,
|
|
2116
2119
|
yaml.llm?.apiKey,
|
|
2117
2120
|
legacy.llm?.apiKey,
|
|
2118
|
-
// Never borrow another provider's credentials for the Atlas Cloud
|
|
2119
|
-
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
2120
|
-
|
|
2121
|
-
|
|
2121
|
+
// Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
|
|
2122
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
|
|
2123
|
+
usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
2124
|
+
usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
|
|
2122
2125
|
);
|
|
2123
2126
|
const resolved = {
|
|
2124
2127
|
agent: {
|
|
@@ -2167,7 +2170,7 @@ function getResolvedConfig(options = {}) {
|
|
|
2167
2170
|
provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
|
|
2168
2171
|
model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
|
|
2169
2172
|
baseUrl: embeddingBaseUrl,
|
|
2170
|
-
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
|
|
2173
|
+
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
|
|
2171
2174
|
dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
|
|
2172
2175
|
},
|
|
2173
2176
|
rerank: resolveRerankLane({
|
|
@@ -2298,6 +2301,7 @@ function getEnvSourceNames() {
|
|
|
2298
2301
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
2299
2302
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
2300
2303
|
"OPENROUTER_API_KEY",
|
|
2304
|
+
"REQUESTY_API_KEY",
|
|
2301
2305
|
"ATLASCLOUD_API_KEY"
|
|
2302
2306
|
].filter((name) => process.env[name]);
|
|
2303
2307
|
}
|
|
@@ -2310,6 +2314,15 @@ function isOpenRouterUrl(value) {
|
|
|
2310
2314
|
return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
|
|
2311
2315
|
}
|
|
2312
2316
|
}
|
|
2317
|
+
function isRequestyUrl(value) {
|
|
2318
|
+
if (!value) return false;
|
|
2319
|
+
try {
|
|
2320
|
+
const url = new URL(value);
|
|
2321
|
+
return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
|
|
2322
|
+
} catch {
|
|
2323
|
+
return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2313
2326
|
function isOpenRouterMemoryLane(provider2, baseUrl) {
|
|
2314
2327
|
return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
|
|
2315
2328
|
}
|
|
@@ -2464,6 +2477,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
|
|
|
2464
2477
|
if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
|
|
2465
2478
|
return "qwen/qwen3-embedding-8b";
|
|
2466
2479
|
}
|
|
2480
|
+
if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
|
|
2481
|
+
return "openai/text-embedding-3-small";
|
|
2482
|
+
}
|
|
2467
2483
|
} catch {
|
|
2468
2484
|
}
|
|
2469
2485
|
return "text-embedding-3-small";
|
|
@@ -3129,6 +3145,7 @@ var init_provider = __esm({
|
|
|
3129
3145
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
3130
3146
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
3131
3147
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
3148
|
+
requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
|
|
3132
3149
|
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
3133
3150
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
3134
3151
|
};
|
|
@@ -3372,6 +3372,7 @@ function getResolvedConfig(options = {}) {
|
|
|
3372
3372
|
const legacy = loadFileConfig(homeDir);
|
|
3373
3373
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
3374
3374
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3375
|
+
const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
|
|
3375
3376
|
const memoryLlmProvider = first(
|
|
3376
3377
|
process.env.MEMORIX_LLM_PROVIDER,
|
|
3377
3378
|
toml.memory?.llm?.provider,
|
|
@@ -3392,16 +3393,18 @@ function getResolvedConfig(options = {}) {
|
|
|
3392
3393
|
);
|
|
3393
3394
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3394
3395
|
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
3396
|
+
const isRequesty = memoryLlmProvider === "requesty";
|
|
3397
|
+
const usesPresetKeyOnly = isAtlasCloud || isRequesty;
|
|
3395
3398
|
const memoryLlmApiKey = first(
|
|
3396
3399
|
process.env.MEMORIX_LLM_API_KEY,
|
|
3397
3400
|
process.env.MEMORIX_API_KEY,
|
|
3398
3401
|
toml.memory?.llm?.api_key,
|
|
3399
3402
|
yaml.llm?.apiKey,
|
|
3400
3403
|
legacy.llm?.apiKey,
|
|
3401
|
-
// Never borrow another provider's credentials for the Atlas Cloud
|
|
3402
|
-
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
3403
|
-
|
|
3404
|
-
|
|
3404
|
+
// Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
|
|
3405
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
|
|
3406
|
+
usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
3407
|
+
usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
|
|
3405
3408
|
);
|
|
3406
3409
|
const resolved = {
|
|
3407
3410
|
agent: {
|
|
@@ -3450,7 +3453,7 @@ function getResolvedConfig(options = {}) {
|
|
|
3450
3453
|
provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
|
|
3451
3454
|
model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
|
|
3452
3455
|
baseUrl: embeddingBaseUrl,
|
|
3453
|
-
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
|
|
3456
|
+
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
|
|
3454
3457
|
dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
|
|
3455
3458
|
},
|
|
3456
3459
|
rerank: resolveRerankLane({
|
|
@@ -3581,6 +3584,7 @@ function getEnvSourceNames() {
|
|
|
3581
3584
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
3582
3585
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
3583
3586
|
"OPENROUTER_API_KEY",
|
|
3587
|
+
"REQUESTY_API_KEY",
|
|
3584
3588
|
"ATLASCLOUD_API_KEY"
|
|
3585
3589
|
].filter((name) => process.env[name]);
|
|
3586
3590
|
}
|
|
@@ -3593,6 +3597,15 @@ function isOpenRouterUrl(value) {
|
|
|
3593
3597
|
return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
|
|
3594
3598
|
}
|
|
3595
3599
|
}
|
|
3600
|
+
function isRequestyUrl(value) {
|
|
3601
|
+
if (!value) return false;
|
|
3602
|
+
try {
|
|
3603
|
+
const url = new URL(value);
|
|
3604
|
+
return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
|
|
3605
|
+
} catch {
|
|
3606
|
+
return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3596
3609
|
function isOpenRouterMemoryLane(provider2, baseUrl) {
|
|
3597
3610
|
return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
|
|
3598
3611
|
}
|
|
@@ -3747,6 +3760,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
|
|
|
3747
3760
|
if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
|
|
3748
3761
|
return "qwen/qwen3-embedding-8b";
|
|
3749
3762
|
}
|
|
3763
|
+
if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
|
|
3764
|
+
return "openai/text-embedding-3-small";
|
|
3765
|
+
}
|
|
3750
3766
|
} catch {
|
|
3751
3767
|
}
|
|
3752
3768
|
return "text-embedding-3-small";
|
|
@@ -6561,6 +6577,7 @@ var init_provider2 = __esm({
|
|
|
6561
6577
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
6562
6578
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
6563
6579
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
6580
|
+
requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
|
|
6564
6581
|
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
6565
6582
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
6566
6583
|
};
|
|
@@ -2384,6 +2384,7 @@ function getResolvedConfig(options = {}) {
|
|
|
2384
2384
|
const legacy = loadFileConfig(homeDir);
|
|
2385
2385
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
2386
2386
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2387
|
+
const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
|
|
2387
2388
|
const memoryLlmProvider = first(
|
|
2388
2389
|
process.env.MEMORIX_LLM_PROVIDER,
|
|
2389
2390
|
toml.memory?.llm?.provider,
|
|
@@ -2404,16 +2405,18 @@ function getResolvedConfig(options = {}) {
|
|
|
2404
2405
|
);
|
|
2405
2406
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2406
2407
|
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
2408
|
+
const isRequesty = memoryLlmProvider === "requesty";
|
|
2409
|
+
const usesPresetKeyOnly = isAtlasCloud || isRequesty;
|
|
2407
2410
|
const memoryLlmApiKey = first(
|
|
2408
2411
|
process.env.MEMORIX_LLM_API_KEY,
|
|
2409
2412
|
process.env.MEMORIX_API_KEY,
|
|
2410
2413
|
toml.memory?.llm?.api_key,
|
|
2411
2414
|
yaml.llm?.apiKey,
|
|
2412
2415
|
legacy.llm?.apiKey,
|
|
2413
|
-
// Never borrow another provider's credentials for the Atlas Cloud
|
|
2414
|
-
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
2415
|
-
|
|
2416
|
-
|
|
2416
|
+
// Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
|
|
2417
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
|
|
2418
|
+
usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
2419
|
+
usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
|
|
2417
2420
|
);
|
|
2418
2421
|
const resolved = {
|
|
2419
2422
|
agent: {
|
|
@@ -2462,7 +2465,7 @@ function getResolvedConfig(options = {}) {
|
|
|
2462
2465
|
provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
|
|
2463
2466
|
model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
|
|
2464
2467
|
baseUrl: embeddingBaseUrl,
|
|
2465
|
-
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
|
|
2468
|
+
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
|
|
2466
2469
|
dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
|
|
2467
2470
|
},
|
|
2468
2471
|
rerank: resolveRerankLane({
|
|
@@ -2593,6 +2596,7 @@ function getEnvSourceNames() {
|
|
|
2593
2596
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
2594
2597
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
2595
2598
|
"OPENROUTER_API_KEY",
|
|
2599
|
+
"REQUESTY_API_KEY",
|
|
2596
2600
|
"ATLASCLOUD_API_KEY"
|
|
2597
2601
|
].filter((name) => process.env[name]);
|
|
2598
2602
|
}
|
|
@@ -2605,6 +2609,15 @@ function isOpenRouterUrl(value) {
|
|
|
2605
2609
|
return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
|
|
2606
2610
|
}
|
|
2607
2611
|
}
|
|
2612
|
+
function isRequestyUrl(value) {
|
|
2613
|
+
if (!value) return false;
|
|
2614
|
+
try {
|
|
2615
|
+
const url = new URL(value);
|
|
2616
|
+
return url.hostname.toLowerCase() === "requesty.ai" || url.hostname.toLowerCase().endsWith(".requesty.ai");
|
|
2617
|
+
} catch {
|
|
2618
|
+
return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2608
2621
|
function isOpenRouterMemoryLane(provider2, baseUrl) {
|
|
2609
2622
|
return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
|
|
2610
2623
|
}
|
|
@@ -2759,6 +2772,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
|
|
|
2759
2772
|
if (url && (url.hostname === "openrouter.ai" || url.hostname.endsWith(".openrouter.ai"))) {
|
|
2760
2773
|
return "qwen/qwen3-embedding-8b";
|
|
2761
2774
|
}
|
|
2775
|
+
if (url && (url.hostname === "requesty.ai" || url.hostname.endsWith(".requesty.ai"))) {
|
|
2776
|
+
return "openai/text-embedding-3-small";
|
|
2777
|
+
}
|
|
2762
2778
|
} catch {
|
|
2763
2779
|
}
|
|
2764
2780
|
return "text-embedding-3-small";
|
|
@@ -5573,6 +5589,7 @@ var init_provider2 = __esm({
|
|
|
5573
5589
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
5574
5590
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
5575
5591
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
5592
|
+
requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
|
|
5576
5593
|
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
5577
5594
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
5578
5595
|
};
|
|
@@ -6,6 +6,21 @@ All notable changes to this project will be documented in this file.
|
|
|
6
6
|
|
|
7
7
|
No unreleased changes.
|
|
8
8
|
|
|
9
|
+
## [1.9.9] - 2026-10-02
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **Requesty memory preset** -- `memorix init` and the configuration TUI can
|
|
13
|
+
select Requesty for optional background memory LLM work through its
|
|
14
|
+
OpenAI-compatible endpoint, with provider-specific key isolation.
|
|
15
|
+
`REQUESTY_API_KEY` is also accepted for Requesty embedding endpoints.
|
|
16
|
+
|
|
17
|
+
## [1.9.8] - 2026-10-02
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- **OpenCode v2 plugin compatibility** -- generated plugins retain the v1
|
|
21
|
+
named export while also exposing the v2 default `id`/`setup` contract,
|
|
22
|
+
including event subscriptions, tool hooks, cleanup, and host session IDs.
|
|
23
|
+
|
|
9
24
|
## [1.9.7] - 2026-09-28
|
|
10
25
|
|
|
11
26
|
### Fixed
|