0b28b4cb0f
herdr 0.8.0 redesigned the agent API out from under the daemon: agent.start now launches a supported kind INTO an existing pane, env/cwd move to pane creation (tab.create / pane.split — the subscription-boundary seam now), agent.send is replaced by agent.prompt (self-submitting) plus agent.send_keys for the Enter nudge, and terminal ids are no longer valid agent.* targets. - AgentControl: start(name, kind, args, paneId); prompt/send_keys delivery; cached terminal→pane target translation (invalidated on agent_not_found). - WorkspaceControl: tab.create carries cwd+env; pane.split for legacy placement. - HerdrPeerLauncher: the seed pane IS the worker pane (no drop step); retry agent.start while the seed shell boots (agent_pane_busy). - FakeHerdr and the test suite model protocol 19 (unique seed panes, required kind/pane_id, prompt-based delivery); contract tests probe the seed shell instead of arbitrary-command agents, which protocol 19 removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SUTLvxtRPr2iT5u5g45BEs
57 lines
2.4 KiB
Java
57 lines
2.4 KiB
Java
package dev.ltms.bridged.herdr;
|
|
|
|
import org.junit.jupiter.api.Tag;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import java.nio.file.Files;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
|
|
|
/**
|
|
* Contract test for the worker env seam against a REAL herdr. Under protocol 19 (CB-521) the
|
|
* env map is injected at PANE CREATION ({@code tab.create}), not {@code agent.start} — and
|
|
* {@code agent.start} now only launches supported agent kinds, so this probes the seed pane's
|
|
* SHELL directly (never {@code claude}, so no subscription/token involvement) and always tears
|
|
* the throwaway space down.
|
|
*
|
|
* <p>Tagged {@code contract}; run with {@code mvn test -Pcontract}.
|
|
*/
|
|
@Tag("contract")
|
|
class AgentControlContractTest {
|
|
|
|
private boolean noSocket() {
|
|
return !Files.exists(UnixSocketHerdrClient.defaultSocketPath());
|
|
}
|
|
|
|
@Test
|
|
void tabCreateInjectsEnvIntoTheSeedShell() throws Exception {
|
|
assumeTrue(!noSocket(), "no herdr socket — skipping");
|
|
try (UnixSocketHerdrClient herdr = UnixSocketHerdrClient.connect()) {
|
|
WorkspaceControl spaces = new WorkspaceControl(herdr);
|
|
Workspace space = spaces.ensureWorkspace("__bridged_env_contract__");
|
|
Tab.Created tab = spaces.createTab(space.workspaceId(), null,
|
|
Map.of("ANTHROPIC_BASE_URL", "http://gx00.gw:8000"));
|
|
try {
|
|
assertNotNull(tab.rootPaneId(), "tab.create must return the seed pane");
|
|
Thread.sleep(1000); // let the seed shell reach its prompt
|
|
herdr.call("pane.send_input", Map.of(
|
|
"pane_id", tab.rootPaneId(),
|
|
"text", "printf 'PROBE_BASE=[%s]\\n' \"$ANTHROPIC_BASE_URL\"",
|
|
"keys", List.of("enter")));
|
|
Thread.sleep(800);
|
|
String visible = herdr.call("pane.read",
|
|
Map.of("pane_id", tab.rootPaneId(), "source", "visible"))
|
|
.path("read").path("text").asText("");
|
|
assertTrue(visible.contains("PROBE_BASE=[http://gx00.gw:8000]"),
|
|
"env map must reach the seed shell; saw: " + visible);
|
|
} finally {
|
|
spaces.closeTab(tab.tab().tabId());
|
|
herdr.call("workspace.close", Map.of("workspace_id", space.workspaceId()));
|
|
}
|
|
}
|
|
}
|
|
}
|