Repository navigation
feat: readOnly option, and a text fallback for recall without structured output - #56
Open
mhuinquiry wants to merge 3 commits into
Open
mhuinquiry wants to merge 3 commits into
mhuinquiry wants to merge 3 commits into
Conversation
For hosts that may read what Claude Code remembers but must not add to it. With `readOnly: true` nothing under CLAUDE_CONFIG_DIR is written: - parseConfig forces extract / autodream off - MemoryStore skips mkdir; save / delete throw - memory_save / memory_delete are not offered (list / search / read stay) - only the recall agent is registered (V1 and V2) - V2 logs nowhere (its log file lives under the config directory) - the prompt is a read-only variant: no "write to it directly", no how-to-save, no update/delete bullets Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On 1.x the selector fork asks for json_schema output. A model or provider without structured output gets a StructuredOutputError from the server even though its text answer is right, so recall silently selected nothing. The first StructuredOutputError switches that host to the text path V2 already uses (buildGeneratePrompt, now shared in src/host/generate.ts) and parseSelectedMemories, which now also accepts a bare JSON array. Other model errors still fail the call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two additions for hosts that want Claude Code's memory but can't use all of it:
readOnly: true— read Claude Code's memory without ever writing to the Claude config directory.Why
readOnly. I'm using this plugin in an OpenCode-based host where the rule is one-way: the agent may read what Claude Code remembers, but must never add to it (nothing from that host may end up in Claude Code's context). Turning off
extractandautodreamisn't enough:memory_save/memory_deleteare still offered to the main agent, the prompt tells it to "write to it directly" and to save when asked to remember,MemoryStorecreates the memory folder, and on 2.x the log file lands underCLAUDE_CONFIG_DIR. I wrapped all of that from the outside first; an option is cleaner and keeps working across upgrades.Text fallback. On 1.x the selector fork asks for
format: json_schema. With models that can't produce structured output, the server returns aStructuredOutputErroreven though the text answer is correct (in my case the model replied["staging.md"]) —forkFailuretreats it as a failed fork, so recall never fires. The 2.x host already uses the text path (buildGeneratePrompt+parseSelectedMemories).Changes
feat(config): readOnly— withreadOnly: true:parseConfigforcesextract.enabled/autodream.enabledoff, whatever they sayMemoryStoreskipsmkdir;save/deletethrow (defence in depth — nothing should reach them)buildMemoryToolSpecsdropsmemory_save/memory_delete; list / search / read stayconfighook, V2agent.transform)buildMemorySystemPromptuses a read-only variant: says the memory is read-only, keeps the reading rules (WHEN_TO_ACCESS_READ_ONLY,TRUSTING_RECALL, searching past context), index and recalled memories; drops types/how-to-save/what-not-to-save/persistence and the update/delete bulletsfix(recall): text fallback—createV1Host().generate: the firstStructuredOutputErrorswitches that host to text mode (schema described in the prompt viabuildGeneratePrompt, moved fromhost/v2/host.tsto the sharedsrc/host/generate.ts); other model errors still fail.parseSelectedMemoriesalso accepts a bare JSON array.docs— README configuration + FAQ, AGENTS.md notes/structure.Default behaviour is unchanged (
readOnlydefaults tofalse; the fallback only runs after aStructuredOutputError).Tests
New:
test/readOnly.test.ts(config forcing, store mkdir/save/delete, read-only prompt, V1 tools + agents, a full V1 turn with recall that leaves every file underCLAUDE_CONFIG_DIRbyte-identical and never lists sessions, no folder for an unseen project, V2 tools + agents + no log file) andtest/recall/structuredFallback.test.ts(retry once then stay in text mode, other errors still throw, bare array parsing). I checked that the store and fallback tests fail with the respective change reverted.Context: in my host (on 2.0.2, the newest release its dependency policy allows) I first hit the structured-output problem with a real model and worked around it with an adapter that does the same thing as this fallback — there recall went from never surfacing the memory to surfacing it. This PR's own code is covered by the unit tests above; I haven't run it against a real model.
🤖 Generated with Claude Code