Skip to content

Commit e7efc2f

Browse files
committed
feat(memory): enforce daemon schema compatibility
1 parent 06dacf9 commit e7efc2f

4 files changed

Lines changed: 89 additions & 43 deletions

File tree

Cargo.lock

Lines changed: 49 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fs2 = "0.4"
2323
hex = "0.4"
2424
hf-hub = { version = "=1.0.0", features = ["blocking"] }
2525
ignore = "0.4.31"
26-
llama-cpp-2 = { version = "=0.1.152", default-features = false }
26+
llama-cpp-2 = { version = "=0.1.153", default-features = false }
2727
prost = "=0.14.4"
2828
regex = "1.13.1"
2929
self_cell = "=1.3.0"
@@ -33,7 +33,7 @@ sha2 = "0.11"
3333
unicode-normalization = "0.1"
3434
rustix = { version = "1.1", features = ["fs", "process"] }
3535
tokio = { version = "1", features = ["io-util", "net", "rt-multi-thread", "sync", "time"] }
36-
xberg = { version = "=1.0.0", default-features = false, features = ["tokio-runtime", "simd-utf8", "pdf"] }
36+
xberg = { version = "=1.0.3", default-features = false, features = ["tokio-runtime", "simd-utf8", "pdf"] }
3737
zvec-rust = "=0.6.0"
3838

3939
[build-dependencies]

opencode-memory/src/daemon-client.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { describe, expect, test } from "bun:test";
22
import {
33
assertDaemonVersionCompatible,
4+
assertDaemonSchemaCompatible,
45
isRetrySafeMemoryMethod,
56
NativeMemoryClient,
67
NativeMemoryClientPool,
@@ -46,6 +47,25 @@ describe("shared daemon client", () => {
4647
expect(() => assertDaemonVersionCompatible("development", "0.6.0-beta.0")).not.toThrow();
4748
});
4849

50+
test("reports both domain schema generations for a stale daemon", () => {
51+
expect(() =>
52+
assertDaemonSchemaCompatible(
53+
"0.6.0",
54+
{ daemonVersion: "0.6.0", domainSchemaGeneration: 2, pid: 64346 },
55+
"/tmp/opencode-memory/daemon.sock",
56+
),
57+
).toThrow(
58+
"Native memory daemon domain schema mismatch at /tmp/opencode-memory/daemon.sock: client 4, daemon 2 (plugin 0.6.0, daemon 0.6.0, pid 64346)",
59+
);
60+
expect(() =>
61+
assertDaemonSchemaCompatible(
62+
"0.6.0",
63+
{ daemonVersion: "0.6.0", domainSchemaGeneration: 4, pid: 64346 },
64+
"/tmp/opencode-memory/daemon.sock",
65+
),
66+
).not.toThrow();
67+
});
68+
4969
test("preserves model retry classifications", () => {
5070
expect(isRetrySafeMemoryMethod("model_profiles")).toBe(true);
5171
expect(isRetrySafeMemoryMethod("model_switch_status")).toBe(true);

opencode-memory/src/daemon-client.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ class DaemonProjectClient implements NativeMemoryRequester {
372372
if (response.body.case !== "getDaemonInfo") {
373373
throw new Error("Native memory daemon omitted GetDaemonInfo");
374374
}
375+
assertDaemonSchemaCompatible(this.pluginVersion, response.body.value, this.endpoint);
375376
const hello = create(OpenSessionRequestSchema, {
376377
clientInstanceId: randomUUID(),
377378
minimumProtocolGeneration: DAEMON_PROTOCOL_GENERATION,
@@ -473,10 +474,11 @@ class DaemonProjectClient implements NativeMemoryRequester {
473474
throw new Error(
474475
`Native memory daemon protocol mismatch at ${this.endpoint}: ` +
475476
`client supports ${DAEMON_PROTOCOL_GENERATION}, daemon ${daemon.daemonVersion} supports ` +
476-
`${daemon.minimumProtocolGeneration}-${daemon.maximumProtocolGeneration}. ` +
477-
"Close active OpenCode processes and restart the native memory daemon.",
477+
`${daemon.minimumProtocolGeneration}-${daemon.maximumProtocolGeneration} (pid ${daemon.pid}). ` +
478+
"Close all OpenCode processes using memory and restart the native memory daemon.",
478479
);
479480
}
481+
assertDaemonSchemaCompatible(this.pluginVersion, daemon, this.endpoint);
480482
assertDaemonVersionCompatible(this.pluginVersion, daemon.daemonVersion, daemon.pid);
481483
const hello = create(OpenSessionRequestSchema, {
482484
clientInstanceId: randomUUID(),
@@ -909,6 +911,20 @@ export function assertDaemonVersionCompatible(
909911
);
910912
}
911913

914+
export function assertDaemonSchemaCompatible(
915+
pluginVersion: string,
916+
daemon: Pick<GetDaemonInfoResponse, "daemonVersion" | "domainSchemaGeneration" | "pid">,
917+
endpoint: string,
918+
): void {
919+
if (daemon.domainSchemaGeneration === DOMAIN_SCHEMA_GENERATION) return;
920+
throw new Error(
921+
`Native memory daemon domain schema mismatch at ${endpoint}: ` +
922+
`client ${DOMAIN_SCHEMA_GENERATION}, daemon ${daemon.domainSchemaGeneration} ` +
923+
`(plugin ${pluginVersion}, daemon ${daemon.daemonVersion}, pid ${daemon.pid}). ` +
924+
"Close all OpenCode processes using memory and restart the native memory daemon.",
925+
);
926+
}
927+
912928
function resolvePackagedBinary(packageName: string, binaryName: string): string | undefined {
913929
try {
914930
return require.resolve(`${packageName}/bin/${binaryName}`);

0 commit comments

Comments
 (0)