Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ permissions:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion src/yoke/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ def native_input(self) -> dict[str, Any]:
if self.native_name is not None:
data["name"] = self.native_name
if self.script_path is not None:
data["scriptPath"] = str(self.script_path)
data["scriptPath"] = self.script_path.as_posix()
if self.args is not None:
data["args"] = self.args
if self.resume_from_run_id is not None:
Expand Down
12 changes: 6 additions & 6 deletions src/yoke/providers/claude.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ async def read_session(
from claude_agent_sdk import get_session_info, get_session_messages
except ImportError as exc:
raise YokeError(f"Claude support requires `{CLAUDE_INSTALL}`.") from exc
directory = str(harness.cwd) if harness.cwd else None
directory = harness.cwd.as_posix() if harness.cwd else None
info = await asyncio.to_thread(
get_session_info,
session_id,
Expand Down Expand Up @@ -396,7 +396,7 @@ async def rename(self, session: Session, title: str) -> SessionSummary:
except ImportError as exc:
raise YokeError(f"Claude support requires `{CLAUDE_INSTALL}`.") from exc
session_id = session.provider_session_id or session.id
directory = str(session.cwd) if session.cwd else None
directory = session.cwd.as_posix() if session.cwd else None
await asyncio.to_thread(
rename_session,
session_id,
Expand All @@ -409,7 +409,7 @@ async def rename(self, session: Session, title: str) -> SessionSummary:
id=session_id,
provider_session_id=session_id,
title=title,
cwd=str(session.cwd) if session.cwd else None,
cwd=session.cwd.as_posix() if session.cwd else None,
)

async def tag(self, session: Session, tag: str | None) -> SessionSummary:
Expand All @@ -418,7 +418,7 @@ async def tag(self, session: Session, tag: str | None) -> SessionSummary:
except ImportError as exc:
raise YokeError(f"Claude support requires `{CLAUDE_INSTALL}`.") from exc
session_id = session.provider_session_id or session.id
directory = str(session.cwd) if session.cwd else None
directory = session.cwd.as_posix() if session.cwd else None
await asyncio.to_thread(
tag_session,
session_id,
Expand All @@ -431,7 +431,7 @@ async def tag(self, session: Session, tag: str | None) -> SessionSummary:
id=session_id,
provider_session_id=session_id,
tag=tag,
cwd=str(session.cwd) if session.cwd else None,
cwd=session.cwd.as_posix() if session.cwd else None,
)

async def start(self, harness: Harness, options: SessionOptions) -> Session:
Expand Down Expand Up @@ -716,7 +716,7 @@ def claude_options(
goal,
compile_inline=deployment is None,
),
"cwd": str(harness.cwd),
"cwd": harness.cwd.as_posix() if harness.cwd else None,
"model": options.model or agent.model,
"effort": options.effort or agent.effort,
"max_turns": options.max_turns,
Expand Down
7 changes: 6 additions & 1 deletion src/yoke/providers/codex_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def codex_agent_toml(
continue
lines.append("")
lines.append("[[skills.config]]")
lines.append(f"path = {toml_string(str(path))}")
lines.append(f"path = {toml_string(path_string(path))}")
lines.append(f"enabled = {'true' if enabled else 'false'}")

return "\n".join(lines) + "\n"
Expand Down Expand Up @@ -225,6 +225,11 @@ def slug(value: str) -> str:
return normalized or "agent"


def path_string(path: Path | str) -> str:
"""Serialize filesystem paths with forward slashes for Codex agent TOML."""
return Path(path).as_posix()


def toml_string(value: str) -> str:
return json.dumps(value)

Expand Down
6 changes: 3 additions & 3 deletions src/yoke/providers/codex_app_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ def codex_runtime_config(deployment: RuntimeDeployment) -> dict[str, Any]:
if deployment.codex_parent_skill_settings:
config["skills"] = {
"config": [
{"path": str(path), "enabled": enabled}
{"path": Path(path).as_posix(), "enabled": enabled}
for path, enabled in deployment.codex_parent_skill_settings
]
}
Expand Down Expand Up @@ -1105,7 +1105,7 @@ def thread_params(
) -> dict[str, Any]:
permission_profile = codex_app_server_option(provider_options, "permissions")
params: dict[str, Any] = {
"cwd": str(harness.cwd),
"cwd": harness.cwd.as_posix() if harness.cwd else None,
"model": model or harness.agent.model,
"approvalPolicy": approval_policy(permissions, provider_options),
"developerInstructions": developer_instructions(
Expand Down Expand Up @@ -1164,7 +1164,7 @@ def turn_params(
permission_profile = codex_app_server_option(effective_options, "permissions")
params: dict[str, Any] = {
"threadId": thread.thread_id,
"cwd": str(thread.cwd),
"cwd": thread.cwd.as_posix() if thread.cwd else None,
"input": [
{
"type": "text",
Expand Down
8 changes: 4 additions & 4 deletions src/yoke/providers/codex_sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ async def stream(self, session: Session, turn: Turn, options: RunOptions):
permissions = options.permissions or session.permissions
handle = await sdk_session.thread.turn(
prompt_with_goal(turn.prompt, options.resolve_goal(session.goal)),
cwd=str(session.cwd) if session.cwd else None,
cwd=session.cwd.as_posix() if session.cwd else None,
effort=str(options.effort or session.agent.effort)
if options.effort or session.agent.effort
else None,
Expand Down Expand Up @@ -398,7 +398,7 @@ async def fork(self, session: Session, options: ForkOptions) -> Session:
thread = await sdk_session.process.client.thread_fork(
session.id,
approval_mode=approval_mode(sdk, permissions),
cwd=str(session.cwd) if session.cwd else None,
cwd=session.cwd.as_posix() if session.cwd else None,
developer_instructions=developer_instructions(session.agent),
ephemeral=options.ephemeral,
model=sdk_session.model,
Expand Down Expand Up @@ -437,7 +437,7 @@ async def _thread(
kwargs = {
"approval_mode": approval_mode(sdk, permissions),
"config": codex_config(options),
"cwd": str(harness.cwd),
"cwd": harness.cwd.as_posix() if harness.cwd else None,
"developer_instructions": developer_instructions(harness.agent),
"model": options.model or harness.agent.model,
"sandbox": sandbox(sdk, permissions),
Expand Down Expand Up @@ -466,7 +466,7 @@ async def _send(
try:
result = await sdk_session.thread.run(
prompt_with_goal(turn.prompt, run_options.resolve_goal(session.goal)),
cwd=str(session.cwd) if session.cwd else None,
cwd=session.cwd.as_posix() if session.cwd else None,
effort=str(run_options.effort or session.agent.effort)
if run_options.effort or session.agent.effort
else None,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_claude_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def test_claude_provider_options_reach_sdk_options(
assert options.kwargs["include_partial_messages"] is True
assert options.kwargs["include_hook_events"] is True
assert options.kwargs["max_budget_usd"] == 1.5
assert options.kwargs["cwd"] == str(Path.cwd())
assert options.kwargs["cwd"] == Path.cwd().as_posix()
assert options.kwargs["append_system_prompt"] == "extra"
assert options.kwargs["model"] == "sonnet"

Expand Down