Skip to content

Feat/claude sdk provider runtime#297

Merged
genedna merged 6 commits intoweb3infra-foundation:mainfrom
Anduin9527:feat/claude-sdk-provider-runtime
Mar 16, 2026
Merged

Feat/claude sdk provider runtime#297
genedna merged 6 commits intoweb3infra-foundation:mainfrom
Anduin9527:feat/claude-sdk-provider-runtime

Conversation

@Anduin9527
Copy link
Contributor

Summary

This PR moves Claude onto an SDK-managed provider-runtime path and separates that runtime from the legacy hook adapter
layer.

Main outcomes:

  • add a dedicated claude_sdk provider-runtime module
  • keep Claude hook support as a minimal compatibility layer
  • add provider-session sync/hydration flows
  • add first-pass evidence_input
  • remove Claude hook-era draft injection artifacts
  • migrate tests from hook-first coverage to Claude SDK coverage

What Changed

Claude SDK runtime separation

  • moved Claude SDK managed runtime code out of hooks/providers/claude
  • introduced:
    • src/internal/ai/providers/claude_sdk/mod.rs
    • src/internal/ai/providers/claude_sdk/managed.rs
    • src/internal/ai/providers/claude_sdk/helper.cjs
  • src/command/claude_sdk.rs now depends on providers::claude_sdk::managed

Hook layer cleanup

  • Claude hook provider now stays focused on hook parsing/install/uninstall only
  • removed Claude hook-era intent draft artifacts:
    • src/internal/ai/hooks/providers/claude/intent_draft.rs
    • src/internal/ai/hooks/providers/claude/intent_draft_rule.md

Claude SDK command surface

Added/kept the managed command flow:

  • claude-sdk import
  • claude-sdk run
  • claude-sdk sync-sessions
  • claude-sdk hydrate-session
  • claude-sdk build-evidence-input
  • claude-sdk resolve-extraction
  • claude-sdk persist-intent

Provider session and evidence layer

  • persist Claude provider session catalog/replay as provider_session
  • derive first-pass evidence_input from hydrated provider-session messages
  • keep formal intent persistence via:
    • extraction
    • resolution
    • persisted intent binding

Copilot AI review requested due to automatic review settings March 16, 2026 04:41
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an SDK-managed Claude provider runtime and a new claude-sdk CLI command group to ingest managed artifacts, sync/hydrate provider sessions, derive evidence_input, and persist intent extraction/resolution artifacts—while removing the legacy hooks CLI surface and migrating tests/fixtures accordingly.

Changes:

  • Add libra claude-sdk command surface (run/import/sync-sessions/hydrate-session/build-evidence-input/resolve-extraction/persist-intent) plus embedded Node helper.
  • Persist new AI history object types (provider_session, evidence_input) and extend cat-file pretty-print support.
  • Remove legacy hooks command and hook-focused integration tests; add Claude SDK-focused fixtures and integration tests.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/data/ai/claude_sdk_plan_prompt.txt Adds plan-prompt fixture for managed run scenario.
tests/data/ai/claude_managed_semantic_full_template.json Adds full managed artifact template fixture.
tests/data/ai/claude_managed_probe_like.json Adds probe-like managed artifact fixture.
tests/data/ai/claude_managed_plan_task_only_template.json Adds plan/task-only managed artifact fixture.
tests/command/mod.rs Switches integration test module set to Claude SDK coverage.
tests/command/hooks_test.rs Removes legacy hooks install/uninstall integration tests.
tests/command/claude_sdk_test.rs Adds comprehensive claude-sdk command integration coverage.
tests/command/ai_hook_test.rs Removes unified hook-ingestion integration tests.
src/internal/ai/providers/mod.rs Exposes new claude_sdk provider module.
src/internal/ai/providers/claude_sdk/mod.rs New Claude SDK provider module entrypoint.
src/internal/ai/providers/claude_sdk/helper.cjs Adds embedded Node helper for SDK querying and session APIs.
src/internal/ai/hooks/runtime.rs Adds provider post-processing hook after event application.
src/internal/ai/hooks/providers/claude/settings.rs Minor formatting change within Claude hook settings module.
src/internal/ai/hooks/providers/claude/mod.rs Minor doc cleanup in Claude hook provider facade.
src/internal/ai/hooks/provider.rs Extends HookProvider trait with optional command output + post-processing hook.
src/command/mod.rs Registers claude_sdk command module and removes hooks command module.
src/command/hooks.rs Removes the unified hooks CLI entrypoint.
src/command/claude_sdk.rs Adds the new Claude SDK CLI command implementation.
src/command/cat_file.rs Adds provider_session and evidence_input AI types + pretty summaries.
src/cli.rs Wires claude-sdk into top-level CLI; removes hooks command variant.
README.md Updates documentation to reference claude-sdk instead of hook forwarding.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +75 to 83
#[command(
name = "claude-sdk",
about = "Run or import Claude Agent SDK managed sessions"
)]
ClaudeSdk(command::claude_sdk::ClaudeSdkArgs),
#[command(about = "Start Libra Code interactive TUI (with background web server)")]
Code(command::code::CodeArgs),
#[command(about = "Connect to Codex app-server via WebSocket")]
AgentCodex(command::agent_codex::AgentCodexArgs),
Comment on lines +50 to +75
fn write_shell_helper(path: &Path, artifact_path: &Path) {
let artifact_rendered = artifact_path.to_string_lossy().replace('\'', r#"'\''"#);
let script = format!("#!/bin/sh\ncat '{artifact_rendered}'\n");
fs::write(path, script)
.unwrap_or_else(|err| panic!("failed to write helper script '{}': {err}", path.display()));
}

fn write_request_capture_shell_helper(path: &Path, artifact_path: &Path, request_path: &Path) {
let artifact_rendered = artifact_path.to_string_lossy().replace('\'', r#"'\''"#);
let request_rendered = request_path.to_string_lossy().replace('\'', r#"'\''"#);
let script = format!("#!/bin/sh\ncat > '{request_rendered}'\ncat '{artifact_rendered}'\n");
fs::write(path, script)
.unwrap_or_else(|err| panic!("failed to write helper script '{}': {err}", path.display()));
}

fn write_json_response_capture_shell_helper(
path: &Path,
response_path: &Path,
request_path: &Path,
) {
let response_rendered = response_path.to_string_lossy().replace('\'', r#"'\''"#);
let request_rendered = request_path.to_string_lossy().replace('\'', r#"'\''"#);
let script = format!("#!/bin/sh\ncat > '{request_rendered}'\ncat '{response_rendered}'\n");
fs::write(path, script)
.unwrap_or_else(|err| panic!("failed to write helper script '{}': {err}", path.display()));
}
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f3ef662296

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +75 to +79
#[command(
name = "claude-sdk",
about = "Run or import Claude Agent SDK managed sessions"
)]
ClaudeSdk(command::claude_sdk::ClaudeSdkArgs),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore legacy hooks subcommand compatibility

Removing the hooks CLI entrypoint here breaks already-installed provider hooks, because existing provider configs still invoke libra hooks ... (see src/internal/ai/hooks/providers/claude/settings.rs and src/internal/ai/hooks/providers/gemini/settings.rs). After upgrading, those commands fail as unknown subcommands, which silently stops hook ingestion and leaves users without a working uninstall path. Keep a compatibility hooks command (or a migration shim) until stored hook commands are migrated.

Useful? React with 👍 / 👎.


const resolverCwd = cwd || process.cwd();
attempts.push(() =>
createRequire(path.join(resolverCwd, '__libra_claude_sdk__.cjs'))(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resolve helper require path from absolute cwd

loadClaudeAgentSdk passes cwd directly to createRequire, but Node requires that filename argument to be absolute; --cwd . or any relative path will throw before SDK resolution. In that failure path, fallback require('@anthropic-ai/claude-agent-sdk') resolves from the temp helper location rather than the target project, so project-local SDK installs are not found and claude-sdk commands fail. Normalize with path.resolve(cwd) before constructing createRequire.

Useful? React with 👍 / 👎.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 76f7d219d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +567 to +570
let raw_artifact_path = write_pretty_json_artifact(
&storage_path.join(MANAGED_ARTIFACTS_DIR),
&ai_session_id,
artifact,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Sanitize session IDs before deriving artifact paths

persist_managed_artifact writes files using ai_session_id as the artifact filename stem, but ai_session_id is built from session_id extracted in extract_system_init with only a non-empty check and no character validation. A managed artifact containing session_id path segments (for example ../...) can therefore escape .libra/managed-artifacts/.libra/audit-bundles when write_pretty_json_artifact does directory.join(format!("{artifact_id}.json")), causing unintended file writes; this path should validate or sanitize IDs (e.g., same [A-Za-z0-9._-] constraint used by hook ingestion) before using them in filesystem paths.

Useful? React with 👍 / 👎.

Copilot AI review requested due to automatic review settings March 16, 2026 06:01
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an SDK-managed Claude provider runtime and a new claude-sdk CLI command group to ingest/persist Claude Agent SDK artifacts (including provider sessions and evidence inputs), while migrating tests and docs away from the legacy hook-first flow.

Changes:

  • Added libra claude-sdk command surface (run/import/sync-sessions/hydrate-session/build-evidence-input/resolve-extraction/persist-intent) and supporting Claude SDK helper/runtime modules.
  • Persisted new AI object types (provider_session, evidence_input) and enhanced cat-file --ai pretty-printing for them.
  • Migrated integration tests/data fixtures to SDK-managed Claude flows and updated README usage.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/data/ai/claude_sdk_plan_prompt.txt Adds plan-prompt fixture for managed Claude SDK scenarios
tests/data/ai/claude_managed_semantic_full_template.json Adds full managed artifact template fixture
tests/data/ai/claude_managed_probe_like.json Adds probe-like managed artifact fixture
tests/data/ai/claude_managed_plan_task_only_template.json Adds plan+task-only artifact fixture
tests/command/mod.rs Switches integration test module set to claude_sdk_test and removes hook tests
tests/command/claude_sdk_test.rs Adds end-to-end CLI tests for Claude SDK flows and new artifacts
tests/command/hooks_test.rs Removes hook install/uninstall integration tests
tests/command/ai_hook_test.rs Removes unified hooks ingestion integration tests
src/internal/ai/providers/mod.rs Registers new claude_sdk provider module
src/internal/ai/providers/claude_sdk/mod.rs Declares Claude SDK provider runtime module
src/internal/ai/providers/claude_sdk/managed.rs Implements managed artifact parsing, bridge conversion, and persistence
src/internal/ai/providers/claude_sdk/helper.cjs Adds Node helper for Claude Agent SDK (query + sessions/messages)
src/internal/ai/hooks/runtime.rs Extends hook runtime to support provider post-processing callbacks
src/internal/ai/hooks/provider.rs Extends provider trait with optional command output/post-processing hooks
src/internal/ai/hooks/providers/claude/settings.rs Minor formatting change (hook installer logic remains)
src/internal/ai/hooks/providers/claude/mod.rs Minor formatting change
src/command/mod.rs Adds claude_sdk command module and removes hooks module export
src/command/hooks.rs Removes unified hooks CLI entrypoint
src/command/claude_sdk.rs Adds full claude-sdk CLI implementation and artifact persistence flows
src/command/cat_file.rs Adds listing/pretty-print support for provider_session and evidence_input
src/cli.rs Adds top-level claude-sdk command and removes hooks command dispatch
README.md Updates docs to describe claude-sdk flows instead of hook forwarding

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +522 to +546
pub async fn persist_managed_artifact(
storage_path: &Path,
artifact: &ClaudeManagedArtifact,
) -> Result<PersistedManagedArtifactOutcome> {
let bundle = build_managed_audit_bundle(artifact)?;
let ai_session_id = bundle.ai_session_id.clone();
let provider_session_id = bundle.provider_session_id.clone();

let objects_dir = storage_path.join("objects");
fs::create_dir_all(&objects_dir).with_context(|| {
format!(
"failed to create objects directory '{}'",
objects_dir.display()
)
})?;

let storage = Arc::new(LocalStorage::new(objects_dir));
let db_conn = Arc::new(db::get_db_conn_instance().await.clone());
let history_manager = HistoryManager::new(storage, storage_path.to_path_buf(), db_conn);

let ai_session_payload = normalize_json_value(bundle.bridge.ai_session.clone());
let blob_data = serde_json::to_vec(&ai_session_payload)
.context("failed to serialize ai_session payload")?;
let blob_hash = write_git_object(storage_path, "blob", &blob_data)
.context("failed to write ai_session git blob")?;
ClaudeSdk(command::claude_sdk::ClaudeSdkArgs),
#[command(about = "Start Libra Code interactive TUI (with background web server)")]
Code(command::code::CodeArgs),
#[command(about = "Connect to Codex app-server via WebSocket")]
pub mod fetch;
pub mod hooks;
pub mod index_pack;
pub mod init;
Comment on lines 99 to 108

mod add_cli_test;
mod add_test;
mod ai_hook_test;
mod blame_test;
mod branch_test;
mod cat_file_test;
mod checkout_test;
mod cherry_pick_test;
mod claude_sdk_test;
mod clean_test;
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 62dac08db9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 973db52283

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

let mcp_server = init_local_mcp_server(&storage_path).await?;
let intent_id = persist_intentspec(&resolved.intentspec, mcp_server.as_ref()).await?;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate resolved IntentSpec before persisting it

persist-intent writes resolved.intentspec straight to MCP history without running validate_intentspec, so a hand-edited or externally supplied --resolution file can persist structurally valid but semantically invalid intent data (empty/contradictory fields, invalid checks) into production history. This creates silent data-quality corruption because the command reports success and downstream tooling will consume the bad intent; run the same validation gate used in resolve-extraction (and fail with a clear validation report) before calling persist_intentspec.

Useful? React with 👍 / 👎.

Comment on lines +1104 to +1110
None => storage_path.join(INTENT_INPUTS_DIR).join(format!(
"{}.json",
resolved
.ai_session_id
.clone()
.unwrap_or_else(|| intent_id.clone())
)),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject unsafe aiSessionId values before building binding path

When --output is omitted, the binding filename is derived directly from resolved.ai_session_id, so a resolution artifact containing path segments like ../ can escape .libra/intent-inputs and overwrite unintended files in the repo. This is reachable through persist-intent --resolution <file> on untrusted or tampered artifacts; enforce a safe identifier policy (e.g. [A-Za-z0-9._-]) or canonicalize and reject paths that are not descendants of the intended directory before writing.

Useful? React with 👍 / 👎.

Copilot AI review requested due to automatic review settings March 16, 2026 08:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR moves Claude support onto an SDK-managed provider-runtime path by introducing a dedicated claude_sdk runtime + CLI surface, and shifting tests/fixtures away from the legacy unified hooks command.

Changes:

  • Add libra claude-sdk ... command group (run/import/sync/hydrate/evidence/resolve/persist) plus the Node helper used to talk to @anthropic-ai/claude-agent-sdk.
  • Introduce new AI object types surfaced via cat-file (provider_session, evidence_input) and persist related artifacts into .libra/.
  • Remove the legacy CLI hooks command and migrate integration coverage to new Claude SDK fixtures/tests.

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/command/claude_sdk.rs New Claude SDK command surface + persistence flows (run/import/sync/hydrate/evidence/resolve/persist).
src/internal/ai/providers/claude_sdk/helper.cjs Bundled Node helper that loads Claude Agent SDK and returns managed artifacts/session data.
src/internal/ai/providers/mod.rs / src/internal/ai/providers/claude_sdk/mod.rs Wire new claude_sdk provider runtime module.
src/command/cat_file.rs Add pretty-print + type listing support for provider_session and evidence_input.
src/cli.rs / src/command/mod.rs Expose claude-sdk command and remove hooks command wiring.
src/internal/ai/hooks/provider.rs / src/internal/ai/hooks/runtime.rs Extend hook provider contract with post-processing hook; adjust runtime to call it.
README.md Update docs to reference claude-sdk flows instead of hook forwarding.
Cargo.toml Move tempfile from dev-dependencies to runtime dependencies (used by claude_sdk command).
tests/command/claude_sdk_test.rs New integration coverage for Claude SDK flows and new AI object types.
tests/data/ai/* Add fixtures/templates for managed artifacts, probe artifacts, and plan prompt.
tests/command/mod.rs Register new claude_sdk_test (unix-only) and remove hook-focused tests.
src/command/hooks.rs, tests/command/hooks_test.rs, tests/command/ai_hook_test.rs Remove legacy unified hooks command + its integration coverage.
Comments suppressed due to low confidence (1)

README.md:146

  • This section says provider session and evidence artifacts are inspectable, but the example commands only show ai_session. Since this PR introduces provider_session and evidence_input AI object types, the README snippet should include the corresponding cat-file --ai-list provider_session / --ai-list evidence_input (and an example cat-file --ai <object_id> for each), or reword the text to match what the commands demonstrate.
Persisted provider session and evidence artifacts are inspectable with:

```bash
libra cat-file --ai-list ai_session
libra cat-file --ai <ai_session_id>
</details>



---

You can also share your feedback on Copilot code review. [Take the survey](https://www.surveymonkey.com/r/XP6L3XJ).

Comment on lines +1463 to +1470
Some("user") => {
user_message_count += 1;
collect_message_content_evidence(
message,
&mut observed_tools,
&mut observed_paths,
&mut Vec::new(),
);
@genedna genedna merged commit 7ef8d49 into web3infra-foundation:main Mar 16, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants