baserun-cli 0.1.0__tar.gz → 0.1.1__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 (22) hide show
  1. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/PKG-INFO +1 -1
  2. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/_vendored/cli.py +28 -12
  3. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/channel.py +16 -0
  4. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/runner.py +7 -6
  5. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli.egg-info/PKG-INFO +1 -1
  6. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/pyproject.toml +1 -1
  7. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/README.md +0 -0
  8. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/__init__.py +0 -0
  9. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/_vendored/__init__.py +0 -0
  10. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/_vendored/base.py +0 -0
  11. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/_vendored/parsers/__init__.py +0 -0
  12. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/_vendored/parsers/base.py +0 -0
  13. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/_vendored/parsers/bash_agent.py +0 -0
  14. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/_vendored/parsers/claude.py +0 -0
  15. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/_vendored/parsers/codex.py +0 -0
  16. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli/main.py +0 -0
  17. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli.egg-info/SOURCES.txt +0 -0
  18. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli.egg-info/dependency_links.txt +0 -0
  19. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli.egg-info/entry_points.txt +0 -0
  20. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli.egg-info/requires.txt +0 -0
  21. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/baserun_cli.egg-info/top_level.txt +0 -0
  22. {baserun_cli-0.1.0 → baserun_cli-0.1.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: baserun-cli
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: BaseRun agent-side daemon (connects to nchan, spawns CLI agents, publishes run events)
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -101,20 +101,36 @@ class CLIAgentConnector(AgentConnector):
101
101
  ) -> AsyncIterator[ConnectorEvent]:
102
102
  import logging as _log
103
103
  _dbg = _log.getLogger("baserun_cli._vendored.cli")
104
- cli = shutil.which(self.spec.bin) or (
105
- self.spec.bin if os.path.exists(self.spec.bin) else self.spec.bin
106
- )
104
+ cli = shutil.which(self.spec.bin)
105
+ if not cli:
106
+ message = f"CLI not found: {self.spec.bin}. Please install it or configure cli_spec.bin with the correct executable path."
107
+ _dbg.error(message)
108
+ yield ConnectorEvent(ConnectorEventType.ERROR, {"message": message})
109
+ return
110
+
107
111
  args = self._build_args(prompt, session_id, fork)
108
112
  _dbg.info("spawning: %s %s (cwd=%s)", cli, " ".join(args[:6]) + ("..." if len(args) > 6 else ""), self.spec.workdir)
109
113
 
110
- proc = await asyncio.create_subprocess_exec(
111
- cli,
112
- *args,
113
- stdout=asyncio.subprocess.PIPE,
114
- stderr=asyncio.subprocess.PIPE,
115
- env=self._env(),
116
- cwd=self.spec.workdir,
117
- )
114
+ proc = None
115
+ try:
116
+ proc = await asyncio.create_subprocess_exec(
117
+ cli,
118
+ *args,
119
+ stdout=asyncio.subprocess.PIPE,
120
+ stderr=asyncio.subprocess.PIPE,
121
+ env=self._env(),
122
+ cwd=self.spec.workdir,
123
+ )
124
+ except FileNotFoundError:
125
+ message = f"CLI not found: {self.spec.bin}. Please install it or configure cli_spec.bin with the correct executable path."
126
+ _dbg.exception(message)
127
+ yield ConnectorEvent(ConnectorEventType.ERROR, {"message": message})
128
+ return
129
+ except Exception as e:
130
+ message = f"failed to start CLI {self.spec.bin}: {e}"
131
+ _dbg.exception(message)
132
+ yield ConnectorEvent(ConnectorEventType.ERROR, {"message": message})
133
+ return
118
134
  _dbg.info("pid=%s started", proc.pid)
119
135
 
120
136
  resolved_session_id: str | None = session_id
@@ -196,7 +212,7 @@ class CLIAgentConnector(AgentConnector):
196
212
  _dbg.exception("pid=%s _run exception", proc.pid)
197
213
  yield ConnectorEvent(ConnectorEventType.ERROR, {"message": str(e)})
198
214
  finally:
199
- if proc.returncode is None:
215
+ if proc is not None and proc.returncode is None:
200
216
  _dbg.warning("pid=%s still running, killing", proc.pid)
201
217
  proc.kill()
202
218
  await proc.wait()
@@ -133,6 +133,22 @@ class ChannelClient:
133
133
  run_id, payload.get("data", {}).get("seq"), max_retries)
134
134
  return False
135
135
 
136
+ async def publish_event_reliably(self, run_id: str, payload: dict[str, Any]) -> bool:
137
+ """Publish a critical run event, falling back to HTTP if WS fails."""
138
+ if await self.publish_event(run_id, payload):
139
+ return True
140
+ try:
141
+ await self._http_publish(run_id, payload)
142
+ return True
143
+ except Exception as e:
144
+ log.error(
145
+ "http publish fallback failed for run %s seq=%s: %s",
146
+ run_id,
147
+ payload.get("data", {}).get("seq"),
148
+ e,
149
+ )
150
+ return False
151
+
136
152
  async def _open_run_pub(self, run_id: str) -> Any:
137
153
  """Open a WS publisher connection for run:{run_id}."""
138
154
  base = self.nchan_url
@@ -204,7 +204,10 @@ class TaskRunner:
204
204
  log.debug("run %s event seq=%d kind=%s", run_id, seq, kind)
205
205
 
206
206
  # publish
207
- await self.channel.publish_event(run_id, payload)
207
+ if is_terminal:
208
+ await self.channel.publish_event_reliably(run_id, payload)
209
+ else:
210
+ await self.channel.publish_event(run_id, payload)
208
211
 
209
212
  if is_terminal:
210
213
  saw_terminal = True
@@ -225,9 +228,7 @@ class TaskRunner:
225
228
  }
226
229
  log_file.write(json.dumps(payload["data"], ensure_ascii=False) + "\n")
227
230
  log_file.flush()
228
- ok = await self.channel.publish_event(run_id, payload)
229
- if not ok:
230
- failed_events.append(payload)
231
+ await self.channel.publish_event_reliably(run_id, payload)
231
232
  log.info("run %s synthesized terminal (seq=%d)", run_id, seq)
232
233
 
233
234
  # verify-and-replay:对比 nchan 实际状态,精确补发缺失事件
@@ -249,7 +250,7 @@ class TaskRunner:
249
250
 
250
251
  except Exception as e:
251
252
  log.exception("run %s failed at seq=%d", run_id, seq)
252
- # publish error terminal via HTTP (reliable)
253
+ # publish error terminal reliably
253
254
  seq += 1
254
255
  error_payload = {
255
256
  "type": "result",
@@ -266,7 +267,7 @@ class TaskRunner:
266
267
  log_file.write(json.dumps(error_payload["data"], ensure_ascii=False) + "\n")
267
268
  except Exception:
268
269
  pass
269
- await self.channel.publish_event(run_id, error_payload)
270
+ await self.channel.publish_event_reliably(run_id, error_payload)
270
271
  return True, "error", seq
271
272
 
272
273
  finally:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: baserun-cli
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: BaseRun agent-side daemon (connects to nchan, spawns CLI agents, publishes run events)
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "baserun-cli"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  description = "BaseRun agent-side daemon (connects to nchan, spawns CLI agents, publishes run events)"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
File without changes
File without changes