feat: add ai-skill and ai-memory hive CLI commands#287
Merged
Conversation
Mirrors the two new typed hives added in legion_config_hive: ai_skill
(Claude Code skill definitions) and ai_memory (per-agent memory store
with a server-side partial-merge hook).
ai-skill is a straight hive shortcut on top of make_hive_group: list,
get, set, delete, enable, disable.
ai-memory is custom because its hook lets Set on a single memory name
update only that one entry while every other memory on the record is
preserved by the server. The new AiMemory SDK class bakes that
mechanism in: set/delete take a required --memory-name and send
{memories: {name: content|null}} only — no GET-then-PUT round trip,
no etag race window. delete-record removes the whole agent record
through the regular DELETE verb.
Both hive names are also added to Configs.ALL_HIVES, the sync flag
map (--hive-ai-skill, --hive-ai-memory), the hive list-types output,
and the lazy-loading regression snapshot.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The /mtd endpoint serializes "data": {} into the response even though
the call is metadata-only. HiveRecord.from_raw kept the empty dict, so
a follow-up set() saw record.data != None and routed to /data with an
empty payload. Hives whose validator requires fields (ai_skill needs
content, ai_agent needs provider config, ...) then rejected the
disable/enable flow with "<field> is required".
Drop the envelope in get_metadata so set() routes back to /mtd, where
the validator-skip-on-metadata-only path applies and the round-trip
preserves the record's data on the server.
Surfaced testing the new ai-skill disable/enable shortcut against
white-sands; secret/lookup escaped the bug only because their
validators tolerate empty data.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
|
/gcbrun |
The 5 failing tests mocked Client/Organization but never set a return
value for client.request(), so the SDK call returned a MagicMock that
the CLI's _output() then crashed on with
"Type is not JSON serializable: MagicMock".
Set request.return_value = {} on each so the CLI's serialization step
gets a real dict.
Co-Authored-By: Claude Opus 4.7 (1M context) <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
Mirrors the two new typed hives that landed in
legion_config_hive:ai_skill— Claude Code skill definitions (master, refractionPOINT/legion_config_hive#282).ai_memory— per-agent memory store with a server-side partial-merge hook (branchfeat/ai-memory-hive, refractionPOINT/legion_config_hive5c15eb9).ai-skillA straight hive shortcut on top of
make_hive_group(list,get,set,delete,enable,disable). No special semantics — the validator on the server enforces the SKILL.md schema.ai-memory(partial-merge mechanism baked in)The
ai_memoryhive'sPreIngesthook merges incomingmemoriesmap keys into the stored record on a per-key basis: keys present in the request replace or drop (when the value is JSON null) their counterpart, while keys absent from the request are preserved untouched. Per the task brief, that mechanism is baked into the CLI tool: everyai-memorysub-command takes both--key(the hive record / agent identifier) and--memory-name(required) so write operations are always targeted at one entry.ai-memory set --key A --memory-name Xsends{memories: {X: content}}only — no GET round-trip, no etag race window.ai-memory delete --key A --memory-name X --confirmsends{memories: {X: null}}so the merge hook drops just that one entry.ai-memory delete-record --key A --confirmremoves the whole agent record (regular DELETE verb, not the merge path).ai-memory get --key A --memory-name Xreturns the single memory's content;listreturns the per-record memory map;list-recordsenumerates every agent.The shape lives in a dedicated
AiMemorySDK class (limacharlie/sdk/ai_memory.py) so the merge convention isn't re-derived in every CLI module.Plumbing
Configs.ALL_HIVES,_KNOWN_HIVE_TYPES, sync flag map, sync help text,hive list-typesdocs, NEW_CLI.md hive table.--hive-ai-skill/--hive-ai-memoryflags onsync pull/sync push.Test plan
pytest tests/unit/test_sdk_ai_memory.py tests/unit/test_cli_ai_skill_memory.py -v(27 new tests; partial-merge payload shape pinned for bothsetanddelete).pytest tests/unit/test_cli_command_map_lint.py tests/unit/test_cli_lazy_loading_regression.py tests/unit/test_sdk_configs.py tests/unit/test_sdk_hive.py tests/unit/test_cli_commands.py -q(1061 passed).set→get→deleteround-trip against a real org once the upstreamai_memoryhive is on master.🤖 Generated with Claude Code