feat: add manual known-word cache refresh path

- Add CLI command flag  with non-GUI dispatch flow and OSD error handling.

- Add runtime integration call and IPC hook so manual refresh works from command runner without app startup.

- Add public AnkiIntegration manual refresh API with force refresh semantics and guard reuse.

- Preserve default n+1 behavior by fixing config validation for malformed  values and adding tests.
This commit is contained in:
2026-02-15 00:03:38 -08:00
parent fb20e1ca25
commit a1f196ee52
17 changed files with 315 additions and 23 deletions

View File

@@ -26,6 +26,7 @@ function makeArgs(overrides: Partial<CliArgs> = {}): CliArgs {
triggerFieldGrouping: false,
triggerSubsync: false,
markAudioCard: false,
refreshKnownWords: false,
openRuntimeOptions: false,
texthooker: false,
help: false,
@@ -106,6 +107,9 @@ function createDeps(overrides: Partial<CliCommandServiceDeps> = {}) {
updateLastCardFromClipboard: async () => {
calls.push("updateLastCardFromClipboard");
},
refreshKnownWords: async () => {
calls.push("refreshKnownWords");
},
cycleSecondarySubMode: () => {
calls.push("cycleSecondarySubMode");
},
@@ -288,3 +292,27 @@ test("handleCliCommandService handles visibility and utility command dispatches"
);
}
});
test("handleCliCommandService runs refresh-known-words command", () => {
const { deps, calls } = createDeps();
handleCliCommandService(makeArgs({ refreshKnownWords: true }), "initial", deps);
assert.ok(calls.includes("refreshKnownWords"));
});
test("handleCliCommandService reports async refresh-known-words errors to OSD", async () => {
const { deps, calls, osd } = createDeps({
refreshKnownWords: async () => {
throw new Error("refresh boom");
},
});
handleCliCommandService(makeArgs({ refreshKnownWords: true }), "initial", deps);
await new Promise((resolve) => setImmediate(resolve));
assert.ok(
calls.some((value) => value.startsWith("error:refreshKnownWords failed:")),
);
assert.ok(osd.some((value) => value.includes("Refresh known words failed: refresh boom")));
});