memorix 1.9.8 → 1.9.10
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 +17 -0
- package/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/dist/cli/index.js +125 -31
- package/dist/index.js +117 -31
- 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 +17 -0
- package/dist/sdk.js +116 -30
- 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 +89 -21
- package/src/llm/provider.ts +2 -1
- package/src/multimodal/image-loader.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,23 @@ All notable changes to this project will be documented in this file.
|
|
|
6
6
|
|
|
7
7
|
No unreleased changes.
|
|
8
8
|
|
|
9
|
+
## [1.9.10] - 2026-10-08
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **OpenCode 1.x regression** -- generated plugins now include the v1
|
|
13
|
+
`server` field alongside the v2 `setup` contract, so OpenCode 1.x can load
|
|
14
|
+
the legacy named export. Lifecycle, file, command, message, and compaction
|
|
15
|
+
events are also forwarded through the v1 generic `event` hook, with a longer
|
|
16
|
+
Windows hook timeout to reduce stale Bun timer failures.
|
|
17
|
+
|
|
18
|
+
## [1.9.9] - 2026-10-02
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **Requesty memory preset** -- `memorix init` and the configuration TUI can
|
|
22
|
+
select Requesty for optional background memory LLM work through its
|
|
23
|
+
OpenAI-compatible endpoint, with provider-specific key isolation.
|
|
24
|
+
`REQUESTY_API_KEY` is also accepted for Requesty embedding endpoints.
|
|
25
|
+
|
|
9
26
|
## [1.9.8] - 2026-10-02
|
|
10
27
|
|
|
11
28
|
### Fixed
|
package/README.md
CHANGED
|
@@ -533,6 +533,8 @@ OpenAI-compatible `https://api.atlascloud.ai/v1` endpoint and reads
|
|
|
533
533
|
|
|
534
534
|
For OpenRouter embeddings, use `provider = "api"`, `base_url = "https://openrouter.ai/api/v1"`, and `model = "qwen/qwen3-embedding-8b"`. Memorix accepts `OPENROUTER_API_KEY` for that embedding endpoint; `MEMORIX_EMBEDDING_API_KEY` remains the explicit override.
|
|
535
535
|
|
|
536
|
+
For Requesty, choose Requesty in `memorix init` or set `provider = "requesty"` in `[memory.llm]` (endpoint `https://router.requesty.ai/v1`, key from `REQUESTY_API_KEY` or `MEMORIX_LLM_API_KEY`). Requesty embeddings use `provider = "api"`, `base_url = "https://router.requesty.ai/v1"`, and `model = "openai/text-embedding-3-small"` with `REQUESTY_API_KEY`.
|
|
537
|
+
|
|
536
538
|
For controlled MiniMax media generation, set `MINIMAX_API_KEY` (global) or
|
|
537
539
|
`MINIMAX_CN_API_KEY` (China region) in your environment or `.env`. The media
|
|
538
540
|
library never stores that key, a signed output URL, or base64 payloads. CLI
|
package/README.zh-CN.md
CHANGED
|
@@ -506,6 +506,8 @@ OpenAI-compatible 的 `https://api.atlascloud.ai/v1` endpoint,并读取
|
|
|
506
506
|
|
|
507
507
|
如果使用 OpenRouter embedding,可以设置 `provider = "api"`、`base_url = "https://openrouter.ai/api/v1"`、`model = "qwen/qwen3-embedding-8b"`。这个 endpoint 下 Memorix 会读取官方 `OPENROUTER_API_KEY`;需要单独覆盖 embedding key 时仍可用 `MEMORIX_EMBEDDING_API_KEY`。
|
|
508
508
|
|
|
509
|
+
使用 Requesty 时,可在 `memorix init` 中选择 Requesty,或在 `[memory.llm]` 中设置 `provider = "requesty"`(endpoint 为 `https://router.requesty.ai/v1`,key 读取 `REQUESTY_API_KEY` 或 `MEMORIX_LLM_API_KEY`)。Requesty embedding 使用 `provider = "api"`、`base_url = "https://router.requesty.ai/v1"`、`model = "openai/text-embedding-3-small"`,并读取 `REQUESTY_API_KEY`。
|
|
510
|
+
|
|
509
511
|
受控 MiniMax 媒体生成可在环境变量或 `.env` 中设置全局 `MINIMAX_API_KEY`,或中国区 `MINIMAX_CN_API_KEY`。媒体库不会保存该 key、临时签名 URL 或 base64 负载。CLI 生成本身就是显式操作;若要让 MCP 中的 Agent 发起生成,还必须明确设置 `MEMORIX_MCP_MEDIA_GENERATION=1`。
|
|
510
512
|
|
|
511
513
|
<h2 id="docker"><picture><source media="(prefers-color-scheme: dark)" srcset="assets/tags/light/section-docker.svg"><img src="assets/tags/section-docker.svg" alt="Docker" height="32" /></picture></h2>
|
package/dist/cli/index.js
CHANGED
|
@@ -3232,7 +3232,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
|
|
|
3232
3232
|
|
|
3233
3233
|
// src/cli/version.ts
|
|
3234
3234
|
function getCliVersion() {
|
|
3235
|
-
return true ? "1.9.
|
|
3235
|
+
return true ? "1.9.10" : pkg.version;
|
|
3236
3236
|
}
|
|
3237
3237
|
var init_version = __esm({
|
|
3238
3238
|
"src/cli/version.ts"() {
|
|
@@ -22122,6 +22122,7 @@ function getResolvedConfig(options = {}) {
|
|
|
22122
22122
|
const legacy = loadFileConfig(homeDir);
|
|
22123
22123
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
22124
22124
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
22125
|
+
const requestyEmbeddingApiKey = isRequestyUrl(embeddingBaseUrl) ? process.env.REQUESTY_API_KEY : void 0;
|
|
22125
22126
|
const memoryLlmProvider = first(
|
|
22126
22127
|
process.env.MEMORIX_LLM_PROVIDER,
|
|
22127
22128
|
toml.memory?.llm?.provider,
|
|
@@ -22142,16 +22143,18 @@ function getResolvedConfig(options = {}) {
|
|
|
22142
22143
|
);
|
|
22143
22144
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
22144
22145
|
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
22146
|
+
const isRequesty = memoryLlmProvider === "requesty";
|
|
22147
|
+
const usesPresetKeyOnly = isAtlasCloud || isRequesty;
|
|
22145
22148
|
const memoryLlmApiKey = first(
|
|
22146
22149
|
process.env.MEMORIX_LLM_API_KEY,
|
|
22147
22150
|
process.env.MEMORIX_API_KEY,
|
|
22148
22151
|
toml.memory?.llm?.api_key,
|
|
22149
22152
|
yaml.llm?.apiKey,
|
|
22150
22153
|
legacy.llm?.apiKey,
|
|
22151
|
-
// Never borrow another provider's credentials for the Atlas Cloud
|
|
22152
|
-
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
22153
|
-
|
|
22154
|
-
|
|
22154
|
+
// Never borrow another provider's credentials for the Atlas Cloud or Requesty presets.
|
|
22155
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
|
|
22156
|
+
usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
22157
|
+
usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
|
|
22155
22158
|
);
|
|
22156
22159
|
const resolved = {
|
|
22157
22160
|
agent: {
|
|
@@ -22200,7 +22203,7 @@ function getResolvedConfig(options = {}) {
|
|
|
22200
22203
|
provider: first(process.env.MEMORIX_EMBEDDING, toml.embedding?.provider, yaml.embedding?.provider, legacy.embedding, "off"),
|
|
22201
22204
|
model: first(process.env.MEMORIX_EMBEDDING_MODEL, toml.embedding?.model, yaml.embedding?.model, legacy.embeddingApi?.model),
|
|
22202
22205
|
baseUrl: embeddingBaseUrl,
|
|
22203
|
-
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
|
|
22206
|
+
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey, requestyEmbeddingApiKey),
|
|
22204
22207
|
dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
|
|
22205
22208
|
},
|
|
22206
22209
|
rerank: resolveRerankLane({
|
|
@@ -22331,6 +22334,7 @@ function getEnvSourceNames() {
|
|
|
22331
22334
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
22332
22335
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
22333
22336
|
"OPENROUTER_API_KEY",
|
|
22337
|
+
"REQUESTY_API_KEY",
|
|
22334
22338
|
"ATLASCLOUD_API_KEY"
|
|
22335
22339
|
].filter((name) => process.env[name]);
|
|
22336
22340
|
}
|
|
@@ -22343,6 +22347,15 @@ function isOpenRouterUrl(value) {
|
|
|
22343
22347
|
return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
|
|
22344
22348
|
}
|
|
22345
22349
|
}
|
|
22350
|
+
function isRequestyUrl(value) {
|
|
22351
|
+
if (!value) return false;
|
|
22352
|
+
try {
|
|
22353
|
+
const url2 = new URL(value);
|
|
22354
|
+
return url2.hostname.toLowerCase() === "requesty.ai" || url2.hostname.toLowerCase().endsWith(".requesty.ai");
|
|
22355
|
+
} catch {
|
|
22356
|
+
return /(^|\.)requesty\.ai(?::|\/|$)/i.test(value);
|
|
22357
|
+
}
|
|
22358
|
+
}
|
|
22346
22359
|
function isOpenRouterMemoryLane(provider2, baseUrl) {
|
|
22347
22360
|
return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
|
|
22348
22361
|
}
|
|
@@ -22497,6 +22510,9 @@ function defaultEmbeddingModelFor(baseUrl, explicitModel) {
|
|
|
22497
22510
|
if (url2 && (url2.hostname === "openrouter.ai" || url2.hostname.endsWith(".openrouter.ai"))) {
|
|
22498
22511
|
return "qwen/qwen3-embedding-8b";
|
|
22499
22512
|
}
|
|
22513
|
+
if (url2 && (url2.hostname === "requesty.ai" || url2.hostname.endsWith(".requesty.ai"))) {
|
|
22514
|
+
return "openai/text-embedding-3-small";
|
|
22515
|
+
}
|
|
22500
22516
|
} catch {
|
|
22501
22517
|
}
|
|
22502
22518
|
return "text-embedding-3-small";
|
|
@@ -25311,6 +25327,7 @@ var init_provider2 = __esm({
|
|
|
25311
25327
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
25312
25328
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
25313
25329
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
25330
|
+
requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
|
|
25314
25331
|
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
25315
25332
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
25316
25333
|
};
|
|
@@ -193093,6 +193110,8 @@ function buildInitTomlConfig(options) {
|
|
|
193093
193110
|
lines.push('model = "claude-3-haiku-20240307"');
|
|
193094
193111
|
} else if (options.llmProvider === "openrouter") {
|
|
193095
193112
|
lines.push('# model = "openai/gpt-4o-mini"');
|
|
193113
|
+
} else if (options.llmProvider === "requesty") {
|
|
193114
|
+
lines.push('# model = "openai/gpt-4o-mini"');
|
|
193096
193115
|
} else if (options.llmProvider === "atlascloud") {
|
|
193097
193116
|
lines.push('model = "deepseek-ai/deepseek-v3.2"');
|
|
193098
193117
|
}
|
|
@@ -193227,6 +193246,7 @@ var init_init = __esm({
|
|
|
193227
193246
|
{ value: "openai", label: "OpenAI", hint: "gpt-4o-mini" },
|
|
193228
193247
|
{ value: "anthropic", label: "Anthropic", hint: "claude-3-haiku" },
|
|
193229
193248
|
{ value: "openrouter", label: "OpenRouter", hint: "multi-provider" },
|
|
193249
|
+
{ value: "requesty", label: "Requesty", hint: "multi-provider" },
|
|
193230
193250
|
{ value: "atlascloud", label: "Atlas Cloud", hint: "DeepSeek V3.2" },
|
|
193231
193251
|
{ value: "custom", label: "Custom", hint: "OpenAI-compatible endpoint" }
|
|
193232
193252
|
]
|
|
@@ -193287,6 +193307,8 @@ var init_init = __esm({
|
|
|
193287
193307
|
envLines.push("MEMORIX_LLM_API_KEY=sk-ant-your-key-here");
|
|
193288
193308
|
} else if (llmProvider === "openrouter") {
|
|
193289
193309
|
envLines.push("MEMORIX_LLM_API_KEY=sk-or-your-key-here");
|
|
193310
|
+
} else if (llmProvider === "requesty") {
|
|
193311
|
+
envLines.push("MEMORIX_LLM_API_KEY=rqsty-your-key-here");
|
|
193290
193312
|
}
|
|
193291
193313
|
if (llmProvider === "custom") {
|
|
193292
193314
|
envLines.push("# MEMORIX_LLM_BASE_URL=http://localhost:11434/v1");
|
|
@@ -193313,6 +193335,7 @@ var init_init = __esm({
|
|
|
193313
193335
|
envLines.push("# OPENAI_API_KEY=sk-...");
|
|
193314
193336
|
envLines.push("# ANTHROPIC_API_KEY=sk-ant-...");
|
|
193315
193337
|
envLines.push("# OPENROUTER_API_KEY=sk-or-...");
|
|
193338
|
+
envLines.push("# REQUESTY_API_KEY=rqsty-...");
|
|
193316
193339
|
envLines.push("");
|
|
193317
193340
|
mkdirSync3(targetDir, { recursive: true });
|
|
193318
193341
|
writeFileSync3(targetPath, tomlContent, "utf-8");
|
|
@@ -195486,6 +195509,8 @@ function generateOpenCodePlugin() {
|
|
|
195486
195509
|
*/
|
|
195487
195510
|
import { spawnSync } from 'node:child_process';
|
|
195488
195511
|
|
|
195512
|
+
const HOOK_TIMEOUT_MS = 30_000;
|
|
195513
|
+
|
|
195489
195514
|
export const MemorixPlugin = async ({ project, client, $, directory, worktree }) => {
|
|
195490
195515
|
// Generate a stable session ID for this plugin lifetime
|
|
195491
195516
|
const sessionId = \`opencode-\${Date.now().toString(36)}-\${Math.random().toString(36).slice(2, 8)}\`;
|
|
@@ -195511,14 +195536,14 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
195511
195536
|
* - spawnSync is simpler: no stream lifecycle, no writer.close() bugs
|
|
195512
195537
|
* - stdin pipe via input option is reliable cross-platform
|
|
195513
195538
|
*/
|
|
195514
|
-
function runHook(payload) {
|
|
195515
|
-
payload.session_id =
|
|
195539
|
+
function runHook(payload, activeSessionId = sessionId) {
|
|
195540
|
+
payload.session_id = activeSessionId;
|
|
195516
195541
|
const data = JSON.stringify(payload);
|
|
195517
195542
|
const eventName = payload.hook_event_name || 'unknown';
|
|
195518
195543
|
try {
|
|
195519
195544
|
const result = spawnSync(hookCommand, ['hook'], {
|
|
195520
195545
|
input: data,
|
|
195521
|
-
timeout:
|
|
195546
|
+
timeout: HOOK_TIMEOUT_MS,
|
|
195522
195547
|
encoding: 'utf-8',
|
|
195523
195548
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
195524
195549
|
shell: process.platform === 'win32',
|
|
@@ -195563,7 +195588,87 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
195563
195588
|
.trim();
|
|
195564
195589
|
}
|
|
195565
195590
|
|
|
195591
|
+
function flushAssistantResponse(activeSessionId = sessionId) {
|
|
195592
|
+
if (!pendingAssistantResponse?.text) return;
|
|
195593
|
+
const deliveryKey = pendingAssistantResponse.id
|
|
195594
|
+
? \`\${pendingAssistantResponse.id}:\${pendingAssistantResponse.text}\`
|
|
195595
|
+
: pendingAssistantResponse.text;
|
|
195596
|
+
if (deliveryKey === lastDeliveredAssistantKey) return;
|
|
195597
|
+
runHook({
|
|
195598
|
+
agent: 'opencode',
|
|
195599
|
+
hook_event_name: 'message.updated',
|
|
195600
|
+
ai_response: pendingAssistantResponse.text,
|
|
195601
|
+
message_id: pendingAssistantResponse.id,
|
|
195602
|
+
cwd: directory,
|
|
195603
|
+
}, activeSessionId);
|
|
195604
|
+
lastDeliveredAssistantKey = deliveryKey;
|
|
195605
|
+
}
|
|
195606
|
+
|
|
195607
|
+
function eventSessionId(event) {
|
|
195608
|
+
const properties = event?.properties ?? {};
|
|
195609
|
+
const value = properties.sessionID ?? properties.sessionId ?? properties.info?.id;
|
|
195610
|
+
return typeof value === 'string' && value ? value : sessionId;
|
|
195611
|
+
}
|
|
195612
|
+
|
|
195613
|
+
async function handleEvent({ event }) {
|
|
195614
|
+
const properties = event?.properties ?? {};
|
|
195615
|
+
const activeSessionId = eventSessionId(event);
|
|
195616
|
+
switch (event?.type) {
|
|
195617
|
+
case 'session.created':
|
|
195618
|
+
runHook({
|
|
195619
|
+
agent: 'opencode',
|
|
195620
|
+
hook_event_name: 'session.created',
|
|
195621
|
+
cwd: directory,
|
|
195622
|
+
}, activeSessionId);
|
|
195623
|
+
break;
|
|
195624
|
+
case 'session.idle':
|
|
195625
|
+
flushAssistantResponse(activeSessionId);
|
|
195626
|
+
runHook({
|
|
195627
|
+
agent: 'opencode',
|
|
195628
|
+
hook_event_name: 'session.idle',
|
|
195629
|
+
cwd: directory,
|
|
195630
|
+
}, activeSessionId);
|
|
195631
|
+
break;
|
|
195632
|
+
case 'file.edited':
|
|
195633
|
+
runHook({
|
|
195634
|
+
agent: 'opencode',
|
|
195635
|
+
hook_event_name: 'file.edited',
|
|
195636
|
+
file_path: properties.file ?? properties.path ?? '',
|
|
195637
|
+
cwd: directory,
|
|
195638
|
+
}, activeSessionId);
|
|
195639
|
+
break;
|
|
195640
|
+
case 'command.executed':
|
|
195641
|
+
runHook({
|
|
195642
|
+
agent: 'opencode',
|
|
195643
|
+
hook_event_name: 'command.executed',
|
|
195644
|
+
command: properties.name ?? properties.command ?? '',
|
|
195645
|
+
cwd: directory,
|
|
195646
|
+
}, activeSessionId);
|
|
195647
|
+
break;
|
|
195648
|
+
case 'message.updated': {
|
|
195649
|
+
const message = properties.info ?? properties.message ?? properties;
|
|
195650
|
+
if (message?.role !== 'assistant') break;
|
|
195651
|
+
const text = extractMessageText(message);
|
|
195652
|
+
if (!text) break;
|
|
195653
|
+
pendingAssistantResponse = { id: message.id, text };
|
|
195654
|
+
break;
|
|
195655
|
+
}
|
|
195656
|
+
case 'session.compacted':
|
|
195657
|
+
runHook({
|
|
195658
|
+
agent: 'opencode',
|
|
195659
|
+
hook_event_name: 'session.compacted',
|
|
195660
|
+
cwd: directory,
|
|
195661
|
+
}, activeSessionId);
|
|
195662
|
+
break;
|
|
195663
|
+
default:
|
|
195664
|
+
break;
|
|
195665
|
+
}
|
|
195666
|
+
}
|
|
195667
|
+
|
|
195566
195668
|
return {
|
|
195669
|
+
// OpenCode 1.x delivers lifecycle/file/command/message events through this
|
|
195670
|
+
// generic hook. The named keys below remain for older compatible hosts.
|
|
195671
|
+
event: handleEvent,
|
|
195567
195672
|
/** Session created \u2014 record session start */
|
|
195568
195673
|
'session.created': async ({ session }) => {
|
|
195569
195674
|
runHook({
|
|
@@ -195575,21 +195680,7 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
195575
195680
|
|
|
195576
195681
|
/** Session idle \u2014 record session end */
|
|
195577
195682
|
'session.idle': async ({ session }) => {
|
|
195578
|
-
|
|
195579
|
-
const deliveryKey = pendingAssistantResponse.id
|
|
195580
|
-
? \`\${pendingAssistantResponse.id}:\${pendingAssistantResponse.text}\`
|
|
195581
|
-
: pendingAssistantResponse.text;
|
|
195582
|
-
if (deliveryKey !== lastDeliveredAssistantKey) {
|
|
195583
|
-
runHook({
|
|
195584
|
-
agent: 'opencode',
|
|
195585
|
-
hook_event_name: 'message.updated',
|
|
195586
|
-
ai_response: pendingAssistantResponse.text,
|
|
195587
|
-
message_id: pendingAssistantResponse.id,
|
|
195588
|
-
cwd: directory,
|
|
195589
|
-
});
|
|
195590
|
-
lastDeliveredAssistantKey = deliveryKey;
|
|
195591
|
-
}
|
|
195592
|
-
}
|
|
195683
|
+
flushAssistantResponse();
|
|
195593
195684
|
runHook({
|
|
195594
195685
|
agent: 'opencode',
|
|
195595
195686
|
hook_event_name: 'session.idle',
|
|
@@ -195697,7 +195788,7 @@ function v2RunHook(payload, directory, sessionId) {
|
|
|
195697
195788
|
try {
|
|
195698
195789
|
const result = spawnSync(v2HookCommand, ['hook'], {
|
|
195699
195790
|
input: JSON.stringify(nextPayload),
|
|
195700
|
-
timeout:
|
|
195791
|
+
timeout: HOOK_TIMEOUT_MS,
|
|
195701
195792
|
encoding: 'utf-8',
|
|
195702
195793
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
195703
195794
|
shell: process.platform === 'win32',
|
|
@@ -195821,7 +195912,7 @@ function setup(ctx) {
|
|
|
195821
195912
|
return () => controller.abort();
|
|
195822
195913
|
}
|
|
195823
195914
|
|
|
195824
|
-
export default { id: 'memorix', setup };
|
|
195915
|
+
export default { id: 'memorix', server: MemorixPlugin, setup };
|
|
195825
195916
|
`;
|
|
195826
195917
|
}
|
|
195827
195918
|
async function installOpenCodeSkills(projectRoot, global2 = false) {
|
|
@@ -196647,7 +196738,7 @@ var init_installers = __esm({
|
|
|
196647
196738
|
"use strict";
|
|
196648
196739
|
init_esm_shims();
|
|
196649
196740
|
init_official_skills();
|
|
196650
|
-
OPENCODE_PLUGIN_VERSION =
|
|
196741
|
+
OPENCODE_PLUGIN_VERSION = 9;
|
|
196651
196742
|
AGENT_SKILL_DIRS = {
|
|
196652
196743
|
cursor: { project: path31.join(".cursor", "skills"), global: path31.join(".cursor", "skills") },
|
|
196653
196744
|
windsurf: { project: path31.join(".windsurf", "skills"), global: path31.join(".windsurf", "skills") },
|
|
@@ -209174,7 +209265,7 @@ var init_tool_profile = __esm({
|
|
|
209174
209265
|
function getMcpServerInfo() {
|
|
209175
209266
|
return {
|
|
209176
209267
|
name: "memorix",
|
|
209177
|
-
version: true ? "1.9.
|
|
209268
|
+
version: true ? "1.9.10" : "1.0.1"
|
|
209178
209269
|
};
|
|
209179
209270
|
}
|
|
209180
209271
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -225106,7 +225197,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
225106
225197
|
"MEMORIX_API_KEY",
|
|
225107
225198
|
"OPENAI_API_KEY",
|
|
225108
225199
|
"ANTHROPIC_API_KEY",
|
|
225109
|
-
...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : []
|
|
225200
|
+
...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : [],
|
|
225201
|
+
...resolved.memory.llm.provider === "requesty" ? ["REQUESTY_API_KEY"] : []
|
|
225110
225202
|
];
|
|
225111
225203
|
if (llmKey) {
|
|
225112
225204
|
const src2 = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
|
|
@@ -265497,7 +265589,7 @@ async function analyzeImage(input) {
|
|
|
265497
265589
|
const config2 = getLLMConfig();
|
|
265498
265590
|
if (!OPENAI_COMPATIBLE_PROVIDERS.has(config2.provider)) {
|
|
265499
265591
|
throw new Error(
|
|
265500
|
-
`Image analysis requires an OpenAI-compatible provider (openai, openrouter, or custom). Current provider "${config2.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
|
|
265592
|
+
`Image analysis requires an OpenAI-compatible provider (openai, openrouter, requesty, or custom). Current provider "${config2.provider}" uses a different API shape. Set MEMORIX_LLM_PROVIDER=openai or configure an OpenAI-compatible base URL.`
|
|
265501
265593
|
);
|
|
265502
265594
|
}
|
|
265503
265595
|
const bytes = decodeBase64ImagePayload(input.base64, MAX_VISION_IMAGE_BYTES);
|
|
@@ -265536,7 +265628,7 @@ var init_image_loader = __esm({
|
|
|
265536
265628
|
init_provider2();
|
|
265537
265629
|
init_secret_filter();
|
|
265538
265630
|
init_image_payload();
|
|
265539
|
-
OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "custom"]);
|
|
265631
|
+
OPENAI_COMPATIBLE_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openrouter", "requesty", "custom"]);
|
|
265540
265632
|
MAX_VISION_PROMPT_CHARS = 12e3;
|
|
265541
265633
|
MAX_VISION_DESCRIPTION_CHARS = 12e3;
|
|
265542
265634
|
MAX_VISION_LABELS = 50;
|
|
@@ -289682,6 +289774,7 @@ function ConfigureView({ onBack }) {
|
|
|
289682
289774
|
{ key: "openai", label: "OpenAI", hint: "gpt-4o-mini" },
|
|
289683
289775
|
{ key: "anthropic", label: "Anthropic", hint: "claude-3-haiku" },
|
|
289684
289776
|
{ key: "openrouter", label: "OpenRouter", hint: "multi-provider" },
|
|
289777
|
+
{ key: "requesty", label: "Requesty", hint: "multi-provider" },
|
|
289685
289778
|
{ key: "atlascloud", label: "Atlas Cloud", hint: "DeepSeek V3.2" },
|
|
289686
289779
|
{ key: "custom", label: "Custom endpoint", hint: "OpenAI-compatible" },
|
|
289687
289780
|
{ key: "disable", label: "Disable LLM", hint: "free heuristic mode", color: COLORS.warning },
|
|
@@ -289975,6 +290068,7 @@ function ConfigureView({ onBack }) {
|
|
|
289975
290068
|
function getDefaultModel(provider2) {
|
|
289976
290069
|
if (provider2 === "anthropic") return "claude-3-haiku-20240307";
|
|
289977
290070
|
if (provider2 === "openrouter") return "openai/gpt-4o-mini";
|
|
290071
|
+
if (provider2 === "requesty") return "openai/gpt-4o-mini";
|
|
289978
290072
|
if (provider2 === "atlascloud") return "deepseek-ai/deepseek-v3.2";
|
|
289979
290073
|
return "gpt-4o-mini";
|
|
289980
290074
|
}
|
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.10" : "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;
|
|
@@ -169912,6 +169930,8 @@ function generateOpenCodePlugin() {
|
|
|
169912
169930
|
*/
|
|
169913
169931
|
import { spawnSync } from 'node:child_process';
|
|
169914
169932
|
|
|
169933
|
+
const HOOK_TIMEOUT_MS = 30_000;
|
|
169934
|
+
|
|
169915
169935
|
export const MemorixPlugin = async ({ project, client, $, directory, worktree }) => {
|
|
169916
169936
|
// Generate a stable session ID for this plugin lifetime
|
|
169917
169937
|
const sessionId = \`opencode-\${Date.now().toString(36)}-\${Math.random().toString(36).slice(2, 8)}\`;
|
|
@@ -169937,14 +169957,14 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
169937
169957
|
* - spawnSync is simpler: no stream lifecycle, no writer.close() bugs
|
|
169938
169958
|
* - stdin pipe via input option is reliable cross-platform
|
|
169939
169959
|
*/
|
|
169940
|
-
function runHook(payload) {
|
|
169941
|
-
payload.session_id =
|
|
169960
|
+
function runHook(payload, activeSessionId = sessionId) {
|
|
169961
|
+
payload.session_id = activeSessionId;
|
|
169942
169962
|
const data = JSON.stringify(payload);
|
|
169943
169963
|
const eventName = payload.hook_event_name || 'unknown';
|
|
169944
169964
|
try {
|
|
169945
169965
|
const result = spawnSync(hookCommand, ['hook'], {
|
|
169946
169966
|
input: data,
|
|
169947
|
-
timeout:
|
|
169967
|
+
timeout: HOOK_TIMEOUT_MS,
|
|
169948
169968
|
encoding: 'utf-8',
|
|
169949
169969
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
169950
169970
|
shell: process.platform === 'win32',
|
|
@@ -169989,7 +170009,87 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
169989
170009
|
.trim();
|
|
169990
170010
|
}
|
|
169991
170011
|
|
|
170012
|
+
function flushAssistantResponse(activeSessionId = sessionId) {
|
|
170013
|
+
if (!pendingAssistantResponse?.text) return;
|
|
170014
|
+
const deliveryKey = pendingAssistantResponse.id
|
|
170015
|
+
? \`\${pendingAssistantResponse.id}:\${pendingAssistantResponse.text}\`
|
|
170016
|
+
: pendingAssistantResponse.text;
|
|
170017
|
+
if (deliveryKey === lastDeliveredAssistantKey) return;
|
|
170018
|
+
runHook({
|
|
170019
|
+
agent: 'opencode',
|
|
170020
|
+
hook_event_name: 'message.updated',
|
|
170021
|
+
ai_response: pendingAssistantResponse.text,
|
|
170022
|
+
message_id: pendingAssistantResponse.id,
|
|
170023
|
+
cwd: directory,
|
|
170024
|
+
}, activeSessionId);
|
|
170025
|
+
lastDeliveredAssistantKey = deliveryKey;
|
|
170026
|
+
}
|
|
170027
|
+
|
|
170028
|
+
function eventSessionId(event) {
|
|
170029
|
+
const properties = event?.properties ?? {};
|
|
170030
|
+
const value = properties.sessionID ?? properties.sessionId ?? properties.info?.id;
|
|
170031
|
+
return typeof value === 'string' && value ? value : sessionId;
|
|
170032
|
+
}
|
|
170033
|
+
|
|
170034
|
+
async function handleEvent({ event }) {
|
|
170035
|
+
const properties = event?.properties ?? {};
|
|
170036
|
+
const activeSessionId = eventSessionId(event);
|
|
170037
|
+
switch (event?.type) {
|
|
170038
|
+
case 'session.created':
|
|
170039
|
+
runHook({
|
|
170040
|
+
agent: 'opencode',
|
|
170041
|
+
hook_event_name: 'session.created',
|
|
170042
|
+
cwd: directory,
|
|
170043
|
+
}, activeSessionId);
|
|
170044
|
+
break;
|
|
170045
|
+
case 'session.idle':
|
|
170046
|
+
flushAssistantResponse(activeSessionId);
|
|
170047
|
+
runHook({
|
|
170048
|
+
agent: 'opencode',
|
|
170049
|
+
hook_event_name: 'session.idle',
|
|
170050
|
+
cwd: directory,
|
|
170051
|
+
}, activeSessionId);
|
|
170052
|
+
break;
|
|
170053
|
+
case 'file.edited':
|
|
170054
|
+
runHook({
|
|
170055
|
+
agent: 'opencode',
|
|
170056
|
+
hook_event_name: 'file.edited',
|
|
170057
|
+
file_path: properties.file ?? properties.path ?? '',
|
|
170058
|
+
cwd: directory,
|
|
170059
|
+
}, activeSessionId);
|
|
170060
|
+
break;
|
|
170061
|
+
case 'command.executed':
|
|
170062
|
+
runHook({
|
|
170063
|
+
agent: 'opencode',
|
|
170064
|
+
hook_event_name: 'command.executed',
|
|
170065
|
+
command: properties.name ?? properties.command ?? '',
|
|
170066
|
+
cwd: directory,
|
|
170067
|
+
}, activeSessionId);
|
|
170068
|
+
break;
|
|
170069
|
+
case 'message.updated': {
|
|
170070
|
+
const message = properties.info ?? properties.message ?? properties;
|
|
170071
|
+
if (message?.role !== 'assistant') break;
|
|
170072
|
+
const text = extractMessageText(message);
|
|
170073
|
+
if (!text) break;
|
|
170074
|
+
pendingAssistantResponse = { id: message.id, text };
|
|
170075
|
+
break;
|
|
170076
|
+
}
|
|
170077
|
+
case 'session.compacted':
|
|
170078
|
+
runHook({
|
|
170079
|
+
agent: 'opencode',
|
|
170080
|
+
hook_event_name: 'session.compacted',
|
|
170081
|
+
cwd: directory,
|
|
170082
|
+
}, activeSessionId);
|
|
170083
|
+
break;
|
|
170084
|
+
default:
|
|
170085
|
+
break;
|
|
170086
|
+
}
|
|
170087
|
+
}
|
|
170088
|
+
|
|
169992
170089
|
return {
|
|
170090
|
+
// OpenCode 1.x delivers lifecycle/file/command/message events through this
|
|
170091
|
+
// generic hook. The named keys below remain for older compatible hosts.
|
|
170092
|
+
event: handleEvent,
|
|
169993
170093
|
/** Session created \u2014 record session start */
|
|
169994
170094
|
'session.created': async ({ session }) => {
|
|
169995
170095
|
runHook({
|
|
@@ -170001,21 +170101,7 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
170001
170101
|
|
|
170002
170102
|
/** Session idle \u2014 record session end */
|
|
170003
170103
|
'session.idle': async ({ session }) => {
|
|
170004
|
-
|
|
170005
|
-
const deliveryKey = pendingAssistantResponse.id
|
|
170006
|
-
? \`\${pendingAssistantResponse.id}:\${pendingAssistantResponse.text}\`
|
|
170007
|
-
: pendingAssistantResponse.text;
|
|
170008
|
-
if (deliveryKey !== lastDeliveredAssistantKey) {
|
|
170009
|
-
runHook({
|
|
170010
|
-
agent: 'opencode',
|
|
170011
|
-
hook_event_name: 'message.updated',
|
|
170012
|
-
ai_response: pendingAssistantResponse.text,
|
|
170013
|
-
message_id: pendingAssistantResponse.id,
|
|
170014
|
-
cwd: directory,
|
|
170015
|
-
});
|
|
170016
|
-
lastDeliveredAssistantKey = deliveryKey;
|
|
170017
|
-
}
|
|
170018
|
-
}
|
|
170104
|
+
flushAssistantResponse();
|
|
170019
170105
|
runHook({
|
|
170020
170106
|
agent: 'opencode',
|
|
170021
170107
|
hook_event_name: 'session.idle',
|
|
@@ -170123,7 +170209,7 @@ function v2RunHook(payload, directory, sessionId) {
|
|
|
170123
170209
|
try {
|
|
170124
170210
|
const result = spawnSync(v2HookCommand, ['hook'], {
|
|
170125
170211
|
input: JSON.stringify(nextPayload),
|
|
170126
|
-
timeout:
|
|
170212
|
+
timeout: HOOK_TIMEOUT_MS,
|
|
170127
170213
|
encoding: 'utf-8',
|
|
170128
170214
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
170129
170215
|
shell: process.platform === 'win32',
|
|
@@ -170247,7 +170333,7 @@ function setup(ctx) {
|
|
|
170247
170333
|
return () => controller.abort();
|
|
170248
170334
|
}
|
|
170249
170335
|
|
|
170250
|
-
export default { id: 'memorix', setup };
|
|
170336
|
+
export default { id: 'memorix', server: MemorixPlugin, setup };
|
|
170251
170337
|
`;
|
|
170252
170338
|
}
|
|
170253
170339
|
async function installOpenCodeSkills(projectRoot, global2 = false) {
|
|
@@ -171073,7 +171159,7 @@ var init_installers = __esm({
|
|
|
171073
171159
|
"use strict";
|
|
171074
171160
|
init_esm_shims();
|
|
171075
171161
|
init_official_skills();
|
|
171076
|
-
OPENCODE_PLUGIN_VERSION =
|
|
171162
|
+
OPENCODE_PLUGIN_VERSION = 9;
|
|
171077
171163
|
AGENT_SKILL_DIRS = {
|
|
171078
171164
|
cursor: { project: path34.join(".cursor", "skills"), global: path34.join(".cursor", "skills") },
|
|
171079
171165
|
windsurf: { project: path34.join(".windsurf", "skills"), global: path34.join(".windsurf", "skills") },
|
|
@@ -176597,7 +176683,7 @@ var init_serve_shared = __esm({
|
|
|
176597
176683
|
|
|
176598
176684
|
// src/cli/version.ts
|
|
176599
176685
|
function getCliVersion() {
|
|
176600
|
-
return true ? "1.9.
|
|
176686
|
+
return true ? "1.9.10" : pkg.version;
|
|
176601
176687
|
}
|
|
176602
176688
|
var init_version3 = __esm({
|
|
176603
176689
|
"src/cli/version.ts"() {
|