adelie-ai 0.2.3 → 0.2.5

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.
@@ -55,12 +55,22 @@ def _check_http(url: str, timeout: int = 5) -> dict:
55
55
 
56
56
 
57
57
  def _check_process(pid: int) -> bool:
58
- """Check if a process is still running."""
58
+ """Check if a process is still running (cross-platform)."""
59
59
  import os
60
+ import sys
60
61
  try:
61
- os.kill(pid, 0)
62
- return True
63
- except (ProcessLookupError, PermissionError):
62
+ if sys.platform == "win32":
63
+ import ctypes
64
+ SYNCHRONIZE = 0x00100000
65
+ handle = ctypes.windll.kernel32.OpenProcess(SYNCHRONIZE, 0, pid)
66
+ if handle:
67
+ ctypes.windll.kernel32.CloseHandle(handle)
68
+ return True
69
+ return False
70
+ else:
71
+ os.kill(pid, 0)
72
+ return True
73
+ except (ProcessLookupError, PermissionError, OSError):
64
74
  return False
65
75
 
66
76
 
@@ -337,10 +337,19 @@ def _cleanup_dead_processes() -> None:
337
337
  pid = proc.get("pid")
338
338
  if pid:
339
339
  try:
340
- os.kill(pid, 0)
341
- alive.append(proc)
340
+ if sys.platform == "win32":
341
+ import ctypes
342
+ handle = ctypes.windll.kernel32.OpenProcess(0x00100000, 0, pid)
343
+ is_alive = bool(handle)
344
+ if handle:
345
+ ctypes.windll.kernel32.CloseHandle(handle)
346
+ else:
347
+ os.kill(pid, 0)
348
+ is_alive = True
342
349
  except (ProcessLookupError, PermissionError, OSError):
343
- pass # Dead — drop it
350
+ is_alive = False
351
+ if is_alive:
352
+ alive.append(proc)
344
353
  RUNNER_ROOT.mkdir(parents=True, exist_ok=True)
345
354
  PROCESS_FILE.write_text(json.dumps(alive, indent=2), encoding="utf-8")
346
355
 
@@ -354,10 +363,19 @@ def _is_similar_running(description: str) -> int | None:
354
363
  pid = proc.get("pid")
355
364
  if pid:
356
365
  try:
357
- os.kill(pid, 0)
358
- return pid # Still alive
366
+ if sys.platform == "win32":
367
+ import ctypes
368
+ handle = ctypes.windll.kernel32.OpenProcess(0x00100000, 0, pid)
369
+ is_alive = bool(handle)
370
+ if handle:
371
+ ctypes.windll.kernel32.CloseHandle(handle)
372
+ else:
373
+ os.kill(pid, 0)
374
+ is_alive = True
359
375
  except (ProcessLookupError, PermissionError, OSError):
360
- pass
376
+ is_alive = False
377
+ if is_alive:
378
+ return pid # Still alive
361
379
  return None
362
380
 
363
381
 
@@ -194,6 +194,9 @@ class AdelieApp:
194
194
  workspace=str(cfg.PROJECT_ROOT),
195
195
  )
196
196
 
197
+ # Start dashboard server FIRST (so _setup_logger can reference it)
198
+ self._start_dashboard(cfg)
199
+
197
200
  # Setup UILogger
198
201
  self._setup_logger()
199
202
 
@@ -203,9 +206,6 @@ class AdelieApp:
203
206
  # Wire orchestrator callbacks
204
207
  self._wire_orchestrator()
205
208
 
206
- # Start dashboard server
207
- self._start_dashboard(cfg)
208
-
209
209
  self._real_console.print("[dim]Type '/help' for a list of commands.[/dim]")
210
210
  self._real_console.print()
211
211
 
@@ -251,11 +251,11 @@ class AdelieApp:
251
251
  """Create UILogger and wire callbacks."""
252
252
  # Use the saved real console so callbacks never recurse through UILogger
253
253
  real_con = self._real_console
254
- ds = self._dashboard_state # may be None if dashboard disabled
255
254
  self._ui_logger = UILogger()
256
255
 
257
256
  def _on_agent_update(name, info):
258
257
  print_agent_event(name, info)
258
+ ds = self._dashboard_state
259
259
  if ds:
260
260
  ds.update_agent(name, {
261
261
  "state": info.state.value if hasattr(info, 'state') else str(info.state) if hasattr(info, 'state') else "idle",
@@ -265,6 +265,7 @@ class AdelieApp:
265
265
 
266
266
  def _on_log(category, obj):
267
267
  real_con.print(obj)
268
+ ds = self._dashboard_state
268
269
  if ds:
269
270
  import re
270
271
  msg = re.sub(r'\[/?[^\]]*\]', '', str(obj))
@@ -272,11 +273,13 @@ class AdelieApp:
272
273
 
273
274
  def _on_cycle_start(it, ph, st):
274
275
  print_cycle_header(it, ph, st)
276
+ ds = self._dashboard_state
275
277
  if ds:
276
278
  ds.update_cycle(it, ph, st)
277
279
 
278
280
  def _on_cycle_metrics(m):
279
281
  print_cycle_metrics(m)
282
+ ds = self._dashboard_state
280
283
  if ds:
281
284
  ds.update_metrics({
282
285
  "total_tokens": getattr(m, 'total_tokens', 0),
@@ -293,6 +296,7 @@ class AdelieApp:
293
296
  self._ui_logger.on_cycle_start = _on_cycle_start
294
297
  self._ui_logger.on_cycle_metrics = _on_cycle_metrics
295
298
 
299
+
296
300
  def _wire_orchestrator(self):
297
301
  """Wire orchestrator event callbacks."""
298
302
  def _on_agent_start(agent_name: str):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adelie-ai",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Adelie — Self-Communicating Autonomous AI Loop CLI",
5
5
  "bin": {
6
6
  "adelie": "bin/adelie.js"