Skip to content

feat: add jcode integration - #2248

Open
1jehuang wants to merge 10 commits into
herdrdev:masterfrom
1jehuang:feat/jcode-integration
Open

feat: add jcode integration#2248
1jehuang wants to merge 10 commits into
herdrdev:masterfrom
1jehuang:feat/jcode-integration

Conversation

@1jehuang

@1jehuang 1jehuang commented Aug 3, 2026

Copy link
Copy Markdown

Summary

  • detect Jcode state from its composer and processing status line
  • install Jcode lifecycle reporting as a native hook-array entry while preserving existing user hooks
  • restore Jcode sessions with jcode --resume <id>
  • add a reusable shell integration conformance harness across Claude, Codex, Copilot, Devin, and Jcode
  • add an executable Jcode lifecycle state-space graph covering installation, routing, failure, replacement, uninstall, and reinstall states
  • document the integration and publish its detection manifest

Approved in #1848 (reply in thread). Screen evidence and prior reports are in #2018.

Jcode dependency

Requires 1jehuang/jcode#758, which adds backward-compatible lifecycle hook arrays and propagates each initiating client's terminal environment through shared-server hook execution.

Validation

  • cargo fmt --check
  • cargo check
  • focused Jcode adapter install/uninstall tests pass
  • all 15 shell hook conformance tests pass
  • executable 18-transition Jcode lifecycle state-space graph passes
  • same-socket two-pane routing test passes with distinct Jcode session IDs
  • live headed validation with patched Herdr and Jcode binaries showed two interactive-ready Jcode panes on one shared socket, each mapped to its own native session
  • python scripts/agent_detection_manifest_check.py

The lifecycle graph also found and fixed an installation side effect: malformed Jcode config is now validated before Herdr creates its managed hook directory.

A broader cargo nextest run previously reached an existing api_ping failure that reproduces unchanged on origin/master: new_terminal_cwd_follow_ignores_nonleader_group_member_cwd times out waiting for helper-ready on this host. The other initially observed API test passes in isolation.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds Jcode as a supported agent and integration. It adds terminal detection, session-start reporting, installation and uninstall flows, native session resume, configuration support, CLI targets, schemas, tests, and documentation.

Changes

Jcode integration

Layer / File(s) Summary
Agent identity and screen detection
src/detect/*, website/agent-detection/*, src/config/*
Adds Jcode mappings, aliases, screen-state rules, sound overrides, configuration names, and detection tests.
Integration installation and lifecycle hook
Cargo.toml, src/integration/*
Adds TOML configuration editing, Jcode directories and constants, hook installation, previous-hook preservation, uninstall restoration, status validation, lifecycle reporting, and integration tests.
Native session resume
src/agent_resume.rs, docs/next/website/src/content/docs/session-state.mdx
Reserves Jcode native state and generates jcode --resume <session-id> plans.
Public target and CLI wiring
src/api/schema/integrations.rs, src/cli/integration.rs, docs/next/api/herdr-api.schema.json
Adds Jcode to integration target enums, parsing, help text, validation messages, and API schemas.
Jcode documentation and configuration reference
docs/next/website/src/content/docs/*, docs/next/website/src/data/config-reference.json
Documents Jcode installation, lifecycle behavior, session identity, restore support, resume commands, and sound configuration.
Lifecycle and hook contract tests
tests/cli/hooks.rs, tests/cli/jcode_lifecycle.rs, tests/cli/mod.rs
Adds shared hook socket utilities, Jcode lifecycle state-space tests, session-reporting contracts, and lifecycle test registration.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Jcode
  participant HerdrHook
  participant HerdrSocket
  Jcode->>HerdrHook: Invoke session_start hook
  HerdrHook->>HerdrHook: Derive session metadata
  HerdrHook->>HerdrSocket: Send pane.report_agent_session
  HerdrHook->>Jcode: Forward the previous hook
Loading

Possibly related PRs

  • herdrdev/herdr#2087: Adds another agent integration through the same registry, CLI, schema, resume, and installation paths.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.24% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: adding Jcode integration.
Description check ✅ Passed The description directly covers Jcode integration, testing, lifecycle behavior, session restoration, and documentation changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@kangal-bot

Copy link
Copy Markdown
Collaborator

Hi @1jehuang, thanks for your interest in contributing!

Herdr automatically admits focused bug fixes from contributors who are not maintainers when the title uses fix: ... or fix(scope): ... and the patch changes no more than 20 files and 1,000 total added or deleted lines.

Contributors who are not maintainers may submit only focused bug fixes. If this pull request fixes a bug, rename it to use a conventional fix: ... or fix(scope): ... title, then tag a maintainer to review and reopen it.

Feature requests, behavior changes, and other proposals belong in GitHub Discussions and require maintainer approval before a pull request.

If this gate classified the pull request incorrectly, reply and tag a maintainer listed in .github/MAINTAINERS. A verified maintainer can reopen it; reopening by anyone else will be closed again automatically.

Patch size: 26 changed files, 756 changed lines.

See https://github.com/herdrdev/herdr/blob/master/CONTRIBUTING.md for the contribution policy.

@kangal-bot kangal-bot closed this Aug 3, 2026
@1jehuang

1jehuang commented Aug 3, 2026

Copy link
Copy Markdown
Author

Hi @ogulcancelik, the intake gate closed this approved feature PR after the follow-up schema commit. Could you reopen it to grant the PR-specific scope override? This is the Jcode integration you invited in Discussion #1848: #1848 (reply in thread)

@ogulcancelik ogulcancelik reopened this Aug 3, 2026
@kangal-bot kangal-bot added ai-review Trigger automated AI reviews for pull requests admitted by the PR gate maintainer-approved PR scope explicitly approved by a maintainer labels Aug 3, 2026
@greptile-apps

greptile-apps Bot commented Aug 3, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds end-to-end Jcode support for screen-based state detection, native session reporting and restoration, and integration lifecycle management.

  • Registers Jcode across agent detection, configuration, API schemas, CLI commands, sound settings, and documentation.
  • Installs Herdr as an independent session_start hook-array entry while preserving existing user commands.
  • Adds conformance and lifecycle coverage for installation, replacement, failure, uninstall, reinstall, and session routing.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the two previously reported observer-forwarding issues are eliminated by registering Herdr and user observers as independent native Jcode hook-array entries.

Important Files Changed

Filename Overview
src/integration/assets/jcode/herdr-agent-state.sh Adds a session-only socket reporter whose optional Python dependency does not gate independently registered user hooks.
src/integration/config_edit.rs Adds TOML-preserving helpers that normalize, append, and remove only Herdr's Jcode hook-array entry.
src/integration/targets.rs Adds validated, idempotent Jcode installation and targeted uninstallation without creating managed state before config validation.
src/detect/manifests/jcode.toml Defines screen evidence for Jcode composer-ready and processing states.
tests/cli/jcode_lifecycle.rs Exercises Jcode integration lifecycle transitions and failure recovery.
tests/cli/hooks.rs Extends the reusable hook conformance harness for independent Jcode hook-array execution.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Install["herdr integration install jcode"] --> Validate["Parse and validate config.toml"]
  Validate --> Hook["Write executable Herdr hook"]
  Validate --> Config["Append independent session_start entry"]
  Jcode["Jcode session_start"] --> UserHooks["Existing user hooks"]
  Jcode --> Hook
  Hook --> Socket["pane.report_agent_session"]
  Socket --> Restore["Persist native session identity"]
  Restore --> Resume["jcode --resume <id>"]
  Screen["Jcode terminal output"] --> Manifest["Jcode screen manifest"]
  Manifest --> State["Working / idle state"]
Loading

Reviews (5): Last reviewed commit: "test: model jcode integration lifecycle ..." | Re-trigger Greptile

Comment thread src/integration/assets/jcode/herdr-agent-state.sh Outdated
Comment thread src/integration/assets/jcode/herdr-agent-state.sh Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
src/agent_resume.rs (1)

444-453: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extend Jcode coverage to the negative and adversarial cases.

Add Jcode to planner_rejects_path_refs_for_id_only_agents and ids_are_data_not_shell_text. The current test covers only the happy-path argument vector.

Source: Coding guidelines

src/integration/config_edit.rs (1)

814-825: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Consider rejecting a non-string session_start value.

jcode_session_start_command returns Ok(None) when hooks.session_start exists but is not a string. install_jcode then treats the slot as empty, skips the backup, and overwrites the value. The parse path and the table path both return descriptive errors, so an explicit error here would keep the behavior consistent and prevent silent loss of a user value.

♻️ Proposed change
 pub(crate) fn jcode_session_start_command(
     content: &str,
     config_path: &Path,
 ) -> io::Result<Option<String>> {
     let document = parse_jcode_config(content, config_path)?;
-    Ok(document
+    let Some(entry) = document
         .get("hooks")
         .and_then(Item::as_table_like)
         .and_then(|hooks| hooks.get("session_start"))
-        .and_then(Item::as_str)
-        .map(str::to_string))
+    else {
+        return Ok(None);
+    };
+    match entry.as_str() {
+        Some(command) => Ok(Some(command.to_string())),
+        None => Err(io::Error::other(format!(
+            "jcode hooks.session_start at {} must be a string",
+            config_path.display()
+        ))),
+    }
 }
src/integration/registry.rs (1)

461-466: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a short comment for the Jcode downgrade rule.

The Grok branch above explains why a valid hook file with a broken config counts as outdated. The Jcode branch repeats the pattern without that context. One comment line, or a combined condition for both targets, keeps the rule clear.

src/integration/assets/jcode/herdr-agent-state.sh (1)

9-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use an explicit empty CDPATH assignment.

CDPATH= cd is intentional, but ShellCheck reports SC1007. Use CDPATH='' cd ... to make the assignment explicit.

Source: Linters/SAST tools


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e05c73e5-123b-4ea1-9a62-7267d241f10d

📥 Commits

Reviewing files that changed from the base of the PR and between 35be08c and cd8a41b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (26)
  • Cargo.toml
  • docs/next/api/herdr-api.schema.json
  • docs/next/website/src/content/docs/agents.mdx
  • docs/next/website/src/content/docs/integrations.mdx
  • docs/next/website/src/content/docs/session-state.mdx
  • docs/next/website/src/data/config-reference.json
  • src/agent_resume.rs
  • src/api/schema/integrations.rs
  • src/cli/integration.rs
  • src/config/model.rs
  • src/config/sidebar.rs
  • src/config/sound.rs
  • src/detect/manifest.rs
  • src/detect/manifests/jcode.toml
  • src/detect/mod.rs
  • src/integration/actions.rs
  • src/integration/assets/jcode/herdr-agent-state.sh
  • src/integration/config_edit.rs
  • src/integration/env.rs
  • src/integration/mod.rs
  • src/integration/registry.rs
  • src/integration/targets.rs
  • src/integration/tests.rs
  • src/integration/types.rs
  • website/agent-detection/index.toml
  • website/agent-detection/jcode.toml

Comment thread src/integration/actions.rs
Comment thread src/integration/assets/jcode/herdr-agent-state.sh Outdated
Comment thread src/integration/targets.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 97d851c7-3803-469e-bf8e-8eb79105c4f8

📥 Commits

Reviewing files that changed from the base of the PR and between 35be08c and cd8a41b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (26)
  • Cargo.toml
  • docs/next/api/herdr-api.schema.json
  • docs/next/website/src/content/docs/agents.mdx
  • docs/next/website/src/content/docs/integrations.mdx
  • docs/next/website/src/content/docs/session-state.mdx
  • docs/next/website/src/data/config-reference.json
  • src/agent_resume.rs
  • src/api/schema/integrations.rs
  • src/cli/integration.rs
  • src/config/model.rs
  • src/config/sidebar.rs
  • src/config/sound.rs
  • src/detect/manifest.rs
  • src/detect/manifests/jcode.toml
  • src/detect/mod.rs
  • src/integration/actions.rs
  • src/integration/assets/jcode/herdr-agent-state.sh
  • src/integration/config_edit.rs
  • src/integration/env.rs
  • src/integration/mod.rs
  • src/integration/registry.rs
  • src/integration/targets.rs
  • src/integration/tests.rs
  • src/integration/types.rs
  • website/agent-detection/index.toml
  • website/agent-detection/jcode.toml
🚧 Files skipped from review as they are similar to previous changes (25)
  • src/config/model.rs
  • src/detect/manifest.rs
  • website/agent-detection/index.toml
  • src/detect/manifests/jcode.toml
  • docs/next/api/herdr-api.schema.json
  • docs/next/website/src/data/config-reference.json
  • Cargo.toml
  • docs/next/website/src/content/docs/agents.mdx
  • docs/next/website/src/content/docs/session-state.mdx
  • src/config/sound.rs
  • docs/next/website/src/content/docs/integrations.mdx
  • src/cli/integration.rs
  • src/integration/actions.rs
  • src/api/schema/integrations.rs
  • src/integration/env.rs
  • src/config/sidebar.rs
  • website/agent-detection/jcode.toml
  • src/integration/registry.rs
  • src/integration/mod.rs
  • src/integration/targets.rs
  • src/integration/types.rs
  • src/integration/tests.rs
  • src/integration/config_edit.rs
  • src/detect/mod.rs
  • src/agent_resume.rs

Comment thread src/integration/assets/jcode/herdr-agent-state.sh Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/integration/tests.rs (1)

4149-4174: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider bounding the socket accept/join and the output-polling window.

Two robustness concerns in this new end-to-end test:

  • The polling loop waits at most 1 second (100 × 10ms) for previous_output to appear before asserting its contents. Under a loaded CI runner, this window can be too short, causing an intermittent, hard-to-diagnose failure rather than a clear one.
  • The spawned server thread calls listener.accept() with no timeout, and server.join() later waits on it unconditionally. If the hook script fails to connect to the socket for any reason (a regression in the hook, environment issue, etc.), this test hangs indefinitely instead of failing with a clear timeout error.

Consider widening the polling budget and adding a bounded wait around the accept()/join() (for example, a channel-based recv_timeout guard) so a broken hook produces a clear test failure instead of a stalled CI job.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 61912794-59cf-4a93-a443-d746c899aa95

📥 Commits

Reviewing files that changed from the base of the PR and between cd8a41b and a26b201.

📒 Files selected for processing (7)
  • src/agent_resume.rs
  • src/integration/actions.rs
  • src/integration/assets/jcode/herdr-agent-state.sh
  • src/integration/config_edit.rs
  • src/integration/registry.rs
  • src/integration/targets.rs
  • src/integration/tests.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/integration/config_edit.rs
  • src/integration/registry.rs
  • src/integration/targets.rs
  • src/agent_resume.rs
  • src/integration/actions.rs

Comment thread src/integration/tests.rs Outdated
@ogulcancelik

Copy link
Copy Markdown
Collaborator

hey jeremy, thanks for the pr. the detection part looks good, but the session restore hook has a problem.

jcode runs hooks from its shared server, so they use the server’s original herdr pane id. the first pane may work, but later panes can report their session to the wrong pane. if the server started outside herdr, they report nothing. the current test does not cover this.

existing hooks are also run differently after installation: jcode normally runs them directly, but this adapter uses sh -c, which can change their behavior.

could we fix these in jcode first and test two panes using the same server? native support for multiple hooks would make the herdr integration much safer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/cli/hooks.rs (1)

173-272: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Also assert params["source"] in the shared contract table.

The header comment describes this table as the check for "Herdr's stable session-report contract". assert_report in tests/cli/jcode_lifecycle.rs (lines 690) asserts params["source"] == "herdr:jcode", but this table does not check source at all. A regression that drops or renames the source field in one adapter would pass here.

Add a source field to Case and assert it per agent.

♻️ Proposed refactor
     struct Case<'a> {
         name: &'a str,
         invocation: ShellHookInvocation<'a>,
         agent: &'a str,
+        source: &'a str,
         session_id: &'a str,
     }
         assert_eq!(request["params"]["agent"], case.agent, "{}", case.name);
+        assert_eq!(request["params"]["source"], case.source, "{}", case.name);

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c49c7833-8dcc-4951-8f30-ad5c5b9f2e81

📥 Commits

Reviewing files that changed from the base of the PR and between a26b201 and 70a219f.

📒 Files selected for processing (10)
  • docs/next/website/src/content/docs/integrations.mdx
  • src/integration/assets/jcode/herdr-agent-state.sh
  • src/integration/config_edit.rs
  • src/integration/mod.rs
  • src/integration/registry.rs
  • src/integration/targets.rs
  • src/integration/tests.rs
  • tests/cli/hooks.rs
  • tests/cli/jcode_lifecycle.rs
  • tests/cli/mod.rs
💤 Files with no reviewable changes (2)
  • src/integration/assets/jcode/herdr-agent-state.sh
  • src/integration/mod.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • docs/next/website/src/content/docs/integrations.mdx
  • src/integration/registry.rs
  • src/integration/tests.rs

Comment thread tests/cli/hooks.rs
Comment on lines +24 to +52
pub(super) fn start(expected_requests: usize) -> Self {
let base = unique_test_dir();
fs::create_dir_all(&base).unwrap();
let socket_path = base.join("herdr.sock");
let listener = UnixListener::bind(&socket_path).unwrap();

let server = thread::spawn(move || {
listener.set_nonblocking(true).unwrap();
let deadline = Instant::now() + Duration::from_millis(700);
let mut requests = Vec::with_capacity(expected_requests);
while requests.len() < expected_requests && Instant::now() < deadline {
match listener.accept() {
Ok((mut stream, _)) => {
let mut line = String::new();
let mut reader = BufReader::new(stream.try_clone().unwrap());
reader.read_line(&mut line).unwrap();
let _ = stream.write_all(br#"{"id":"test","result":{"type":"ok"}}"#);
let _ = stream.write_all(b"\n");
let _ = stream.flush();
requests.push(serde_json::from_str(&line).unwrap());
}
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
thread::sleep(Duration::from_millis(10));
}
Err(err) => panic!("accept failed: {err}"),
}
}
requests
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Raise the collector deadline to remove a timing race.

The deadline starts when start() runs, not when the hooks run. Callers then spawn bash (and, for the Jcode asset, a Python interpreter) sequentially. run_shell_hooks invokes every hook after start(), so the 700 ms budget covers all process startups. On a loaded machine two sequential hook invocations can exceed that budget. The collector then returns fewer requests, and tests/cli/jcode_lifecycle.rs assertions such as assert_eq!(requests.len(), 2, ...) fail intermittently.

The equivalent production-path test in src/integration/tests.rs (lines 4146-4229) uses a 5-second deadline for two hooks.

The loop already exits as soon as expected_requests arrive, so a longer deadline does not slow the positive cases. It does slow the expected-empty cases (run_outside_herdr, run_without_python), which always wait for the full deadline. Consider making the deadline a parameter so those cases keep a short wait.

🐛 Proposed fix
 impl FakeHookSocket {
     pub(super) fn start(expected_requests: usize) -> Self {
+        Self::start_with_timeout(expected_requests, Duration::from_secs(5))
+    }
+
+    pub(super) fn start_with_timeout(expected_requests: usize, timeout: Duration) -> Self {
         let base = unique_test_dir();
         fs::create_dir_all(&base).unwrap();
         let socket_path = base.join("herdr.sock");
         let listener = UnixListener::bind(&socket_path).unwrap();
 
         let server = thread::spawn(move || {
             listener.set_nonblocking(true).unwrap();
-            let deadline = Instant::now() + Duration::from_millis(700);
+            let deadline = Instant::now() + timeout;

Then use start_with_timeout(1, Duration::from_millis(700)) in the tests that expect no report.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub(super) fn start(expected_requests: usize) -> Self {
let base = unique_test_dir();
fs::create_dir_all(&base).unwrap();
let socket_path = base.join("herdr.sock");
let listener = UnixListener::bind(&socket_path).unwrap();
let server = thread::spawn(move || {
listener.set_nonblocking(true).unwrap();
let deadline = Instant::now() + Duration::from_millis(700);
let mut requests = Vec::with_capacity(expected_requests);
while requests.len() < expected_requests && Instant::now() < deadline {
match listener.accept() {
Ok((mut stream, _)) => {
let mut line = String::new();
let mut reader = BufReader::new(stream.try_clone().unwrap());
reader.read_line(&mut line).unwrap();
let _ = stream.write_all(br#"{"id":"test","result":{"type":"ok"}}"#);
let _ = stream.write_all(b"\n");
let _ = stream.flush();
requests.push(serde_json::from_str(&line).unwrap());
}
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
thread::sleep(Duration::from_millis(10));
}
Err(err) => panic!("accept failed: {err}"),
}
}
requests
});
pub(super) fn start(expected_requests: usize) -> Self {
Self::start_with_timeout(expected_requests, Duration::from_secs(5))
}
pub(super) fn start_with_timeout(expected_requests: usize, timeout: Duration) -> Self {
let base = unique_test_dir();
fs::create_dir_all(&base).unwrap();
let socket_path = base.join("herdr.sock");
let listener = UnixListener::bind(&socket_path).unwrap();
let server = thread::spawn(move || {
listener.set_nonblocking(true).unwrap();
let deadline = Instant::now() + timeout;
let mut requests = Vec::with_capacity(expected_requests);
while requests.len() < expected_requests && Instant::now() < deadline {
match listener.accept() {
Ok((mut stream, _)) => {
let mut line = String::new();
let mut reader = BufReader::new(stream.try_clone().unwrap());
reader.read_line(&mut line).unwrap();
let _ = stream.write_all(br#"{"id":"test","result":{"type":"ok"}}"#);
let _ = stream.write_all(b"\n");
let _ = stream.flush();
requests.push(serde_json::from_str(&line).unwrap());
}
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
thread::sleep(Duration::from_millis(10));
}
Err(err) => panic!("accept failed: {err}"),
}
}
requests
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Trigger automated AI reviews for pull requests admitted by the PR gate maintainer-approved PR scope explicitly approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants