swytchcode-runtime 1.1.3__tar.gz → 1.1.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. {swytchcode_runtime-1.1.3/swytchcode_runtime.egg-info → swytchcode_runtime-1.1.5}/PKG-INFO +1 -1
  2. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/pyproject.toml +1 -1
  3. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/cli.py +4 -4
  4. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/exec.py +21 -10
  5. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/schema.py +3 -1
  6. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5/swytchcode_runtime.egg-info}/PKG-INFO +1 -1
  7. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/LICENSE.md +0 -0
  8. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/README.md +0 -0
  9. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/setup.cfg +0 -0
  10. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/__init__.py +0 -0
  11. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/client.py +0 -0
  12. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/discover.py +0 -0
  13. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/errors.py +0 -0
  14. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/manage.py +0 -0
  15. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/prompts.py +0 -0
  16. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/providers/__init__.py +0 -0
  17. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/providers/anthropic.py +0 -0
  18. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/providers/base.py +0 -0
  19. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/providers/crewai.py +0 -0
  20. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/providers/langgraph.py +0 -0
  21. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/providers/openai_agents.py +0 -0
  22. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime/providers/vercel.py +0 -0
  23. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime.egg-info/SOURCES.txt +0 -0
  24. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime.egg-info/dependency_links.txt +0 -0
  25. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/swytchcode_runtime.egg-info/top_level.txt +0 -0
  26. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/tests/test_alias.py +0 -0
  27. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/tests/test_exec_errors.py +0 -0
  28. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/tests/test_nested_body.py +0 -0
  29. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/tests/test_prompts.py +0 -0
  30. {swytchcode_runtime-1.1.3 → swytchcode_runtime-1.1.5}/tests/test_schema_routing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: swytchcode-runtime
3
- Version: 1.1.3
3
+ Version: 1.1.5
4
4
  Summary: Thin runtime wrapper around the Swytchcode CLI
5
5
  Author: Swytchcode
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "swytchcode-runtime"
7
- version = "1.1.3"
7
+ version = "1.1.5"
8
8
  description = "Thin runtime wrapper around the Swytchcode CLI"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -18,14 +18,14 @@ def run_cli(
18
18
  env: dict | None = None,
19
19
  timeout: float | None = 60,
20
20
  ) -> Any:
21
- cmd = [_resolve_bin(), *args]
22
- if "--json" not in args:
23
- cmd.append("--json")
24
-
25
21
  run_env = os.environ.copy()
26
22
  if env:
27
23
  run_env.update(env)
28
24
 
25
+ cmd = [_resolve_bin(run_env), *args]
26
+ if "--json" not in args:
27
+ cmd.append("--json")
28
+
29
29
  try:
30
30
  r = subprocess.run(
31
31
  cmd,
@@ -10,7 +10,7 @@ from typing import Any
10
10
  from .errors import SwytchcodeError
11
11
 
12
12
 
13
- def _resolve_bin() -> str:
13
+ def _resolve_bin(env: dict[str, str]) -> str:
14
14
  """
15
15
  Resolve the swytchcode binary path using the following order:
16
16
 
@@ -19,25 +19,26 @@ def _resolve_bin() -> str:
19
19
  3. Common install-path fallbacks for when PATH is not configured.
20
20
  """
21
21
  # 1. Explicit override
22
- explicit = os.environ.get("SWYTCHCODE_BIN", "").strip()
22
+ explicit = env.get("SWYTCHCODE_BIN", "").strip()
23
23
  if explicit:
24
24
  return explicit
25
25
 
26
26
  # 2. PATH lookup
27
- found = shutil.which("swytchcode")
27
+ found = shutil.which("swytchcode", path=env.get("PATH"))
28
28
  if found:
29
29
  return found
30
30
 
31
31
  # 3. Common install-path fallbacks
32
32
  if sys.platform == "win32":
33
- local_app_data = os.environ.get("LOCALAPPDATA", "")
33
+ local_app_data = env.get("LOCALAPPDATA", "")
34
34
  candidates = [
35
35
  os.path.join(
36
36
  local_app_data, "Programs", "swytchcode", "bin", "swytchcode.exe"
37
37
  ),
38
38
  ]
39
39
  else:
40
- home = os.path.expanduser("~")
40
+ # Fallback to os.environ for HOME if not explicitly in env
41
+ home = env.get("HOME") or os.path.expanduser("~")
41
42
  candidates = [
42
43
  os.path.join(home, ".local", "bin", "swytchcode"),
43
44
  "/usr/local/bin/swytchcode",
@@ -112,18 +113,18 @@ def exec_(
112
113
  if not canonical_id:
113
114
  raise SwytchcodeError("canonical_id must be a non-empty string")
114
115
 
116
+ run_env = os.environ.copy()
117
+ if env:
118
+ run_env.update(env)
119
+
115
120
  flag = "--raw" if raw else "--json"
116
- bin_path = _resolve_bin()
121
+ bin_path = _resolve_bin(run_env)
117
122
  cmd = [bin_path, "exec", canonical_id, flag]
118
123
  if dry_run:
119
124
  cmd.append("--dry-run")
120
125
  if allow_raw:
121
126
  cmd.append("--allow-raw")
122
127
 
123
- run_env = os.environ.copy()
124
- if env:
125
- run_env.update(env)
126
-
127
128
  stdin_payload: bytes | None = None
128
129
  if input is not None:
129
130
  stdin_payload = json.dumps(input).encode("utf-8")
@@ -155,6 +156,16 @@ def exec_(
155
156
  stderr = result.stderr.decode("utf-8", errors="replace").strip()
156
157
  stdout = result.stdout.decode("utf-8", errors="replace")
157
158
 
159
+ if "demo_mode" in stderr or "data is simulated" in stderr:
160
+ demo_allowed = (env and env.get("SWYTCHCODE_DEMO") == "1") or os.environ.get(
161
+ "SWYTCHCODE_DEMO"
162
+ ) == "1"
163
+ if not demo_allowed:
164
+ raise SwytchcodeError(
165
+ f"Swytchcode CLI executed in simulated demo mode: {stderr}. "
166
+ "Initialize a project with `swytchcode init` or pass --demo explicitly."
167
+ )
168
+
158
169
  if result.returncode != 0:
159
170
  classified = _parse_classified_error(stderr)
160
171
  if classified:
@@ -102,6 +102,8 @@ def _expand(spec: Any) -> dict:
102
102
  items = spec["schema"].get("items")
103
103
  if isinstance(items, dict):
104
104
  out["items"] = _expand(items)
105
+ else:
106
+ out["items"] = {"type": "string"}
105
107
 
106
108
  return out
107
109
 
@@ -191,7 +193,7 @@ def to_pydantic_model(schema: dict, name: str = "ArgsSchema") -> Any:
191
193
  elif t == "boolean":
192
194
  field_type = bool
193
195
  elif t == "array":
194
- field_type = list
196
+ field_type = list[str]
195
197
  elif t == "object":
196
198
  # Only build a nested model when the object's fields are known.
197
199
  # A property-less object (freeform body) becomes a plain dict: an
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: swytchcode-runtime
3
- Version: 1.1.3
3
+ Version: 1.1.5
4
4
  Summary: Thin runtime wrapper around the Swytchcode CLI
5
5
  Author: Swytchcode
6
6
  License: MIT