stravinsky 0.2.38__py3-none-any.whl → 0.2.40__py3-none-any.whl

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.
@@ -8,6 +8,7 @@ This replaces the simple model-only invocation with true agentic execution.
8
8
  import asyncio
9
9
  import json
10
10
  import os
11
+ import shutil
11
12
  import subprocess
12
13
  import signal
13
14
  import uuid
@@ -62,9 +63,13 @@ class AgentManager:
62
63
  - Provides notification mechanism for task completion
63
64
  """
64
65
 
65
- CLAUDE_CLI = "/opt/homebrew/bin/claude"
66
+ # Dynamic CLI path - find claude in PATH, fallback to common locations
67
+ CLAUDE_CLI = shutil.which("claude") or "/opt/homebrew/bin/claude"
66
68
 
67
69
  def __init__(self, base_dir: Optional[str] = None):
70
+ # Initialize lock FIRST - used by _save_tasks and _load_tasks
71
+ self._lock = threading.RLock()
72
+
68
73
  if base_dir:
69
74
  self.base_dir = Path(base_dir)
70
75
  else:
@@ -82,7 +87,6 @@ class AgentManager:
82
87
  # In-memory tracking for running processes
83
88
  self._processes: Dict[str, subprocess.Popen] = {}
84
89
  self._notification_queue: Dict[str, List[AgentTask]] = {}
85
- self._lock = threading.RLock()
86
90
 
87
91
  def _load_tasks(self) -> Dict[str, Any]:
88
92
  """Load tasks from persistent storage."""
@@ -218,9 +222,10 @@ class AgentManager:
218
222
  "text",
219
223
  ]
220
224
 
221
- # Add model selection if specified
222
- if model:
223
- cmd.extend(["--model", model])
225
+ # NOTE: We intentionally do NOT pass --model to Claude CLI
226
+ # The agent_configs have Stravinsky MCP model names (gemini-3-pro-low, gpt-5.2)
227
+ # which Claude CLI doesn't recognize. Agents use Claude's default model
228
+ # and can invoke Stravinsky MCP tools (invoke_gemini, invoke_openai) if needed.
224
229
 
225
230
  # Add system prompt file if we have one
226
231
  if system_prompt:
@@ -231,16 +236,17 @@ class AgentManager:
231
236
  # Execute Claude CLI as subprocess with full tool access
232
237
  logger.info(f"[AgentManager] Running: {' '.join(cmd[:3])}...")
233
238
 
234
- with open(log_file, "w") as log_f:
235
- process = subprocess.Popen(
236
- cmd,
237
- stdout=subprocess.PIPE,
238
- stderr=log_f,
239
- text=True,
240
- cwd=str(Path.cwd()),
241
- env={**os.environ, "CLAUDE_CODE_ENTRYPOINT": "stravinsky-agent"},
242
- start_new_session=True, # Allow process group management
243
- )
239
+ # Use PIPE for stderr to capture it properly
240
+ # (Previously used file handle which was closed before process finished)
241
+ process = subprocess.Popen(
242
+ cmd,
243
+ stdout=subprocess.PIPE,
244
+ stderr=subprocess.PIPE,
245
+ text=True,
246
+ cwd=str(Path.cwd()),
247
+ env={**os.environ, "CLAUDE_CODE_ENTRYPOINT": "stravinsky-agent"},
248
+ start_new_session=True, # Allow process group management
249
+ )
244
250
 
245
251
  # Track the process
246
252
  self._processes[task_id] = process
@@ -248,9 +254,13 @@ class AgentManager:
248
254
 
249
255
  # Wait for completion with timeout
250
256
  try:
251
- stdout, _ = process.communicate(timeout=timeout)
257
+ stdout, stderr = process.communicate(timeout=timeout)
252
258
  result = stdout.strip() if stdout else ""
253
259
 
260
+ # Write stderr to log file
261
+ if stderr:
262
+ log_file.write_text(stderr)
263
+
254
264
  if process.returncode == 0:
255
265
  output_file.write_text(result)
256
266
  self._update_task(
@@ -262,8 +272,8 @@ class AgentManager:
262
272
  logger.info(f"[AgentManager] Agent {task_id} completed successfully")
263
273
  else:
264
274
  error_msg = f"Claude CLI exited with code {process.returncode}"
265
- if log_file.exists():
266
- error_msg += f"\n{log_file.read_text()}"
275
+ if stderr:
276
+ error_msg += f"\n{stderr}"
267
277
  self._update_task(
268
278
  task_id,
269
279
  status="failed",
@@ -663,24 +673,16 @@ RESPONSE RULES:
663
673
 
664
674
  system_prompt = system_prompts.get(agent_type, None)
665
675
 
666
- # Override model and thinking_budget based on agent type for optimal performance
667
- # Per project requirements:
668
- # - Gemini tiers are controlled by thinking_budget, NOT model name
669
- # - high: 32000, medium: 16000, low: 8000 thinking tokens
670
- # - "gemini-3-pro-high" = gemini-3-pro-low + thinking_budget=32000
671
- # - "gemini-3-flash" equivalent = gemini-3-pro-low + thinking_budget=0
672
- agent_configs = {
673
- "stravinsky": {"model": "claude-opus-4-5", "thinking_budget": 0},
674
- "frontend": {"model": "gemini-3-pro-low", "thinking_budget": 32000}, # HIGH tier
675
- "document_writer": {"model": "gemini-3-pro-low", "thinking_budget": 0}, # Flash equiv
676
- "multimodal": {"model": "gemini-3-pro-low", "thinking_budget": 0}, # Flash equiv
677
- "explore": {"model": "gemini-3-pro-low", "thinking_budget": 0}, # Flash equiv
678
- "delphi": {"model": "gpt-5.2", "thinking_budget": 0}, # GPT-5.2 strategic
679
- "dewey": {"model": "gemini-3-pro-low", "thinking_budget": 0}, # Flash equiv
680
- }
681
- config = agent_configs.get(agent_type, {"model": model, "thinking_budget": thinking_budget})
682
- actual_model = config["model"]
683
- actual_thinking_budget = config["thinking_budget"]
676
+ # NOTE: All agents run via Claude CLI using Claude's default model.
677
+ # The agent_configs below are kept for documentation purposes only.
678
+ # Agents can invoke Stravinsky MCP tools (invoke_gemini, invoke_openai)
679
+ # within their prompts if they need to use other models.
680
+ #
681
+ # Agent model preferences (for reference - NOT passed to Claude CLI):
682
+ # - stravinsky: Claude Opus 4.5 (orchestration)
683
+ # - delphi: GPT-5.2 (strategic advice) - use invoke_openai
684
+ # - frontend: Gemini Pro High (UI/UX) - use invoke_gemini with thinking_budget
685
+ # - explore, dewey, document_writer, multimodal: Gemini Flash (fast) - use invoke_gemini
684
686
 
685
687
  # Get token store for authentication
686
688
  from ..auth.token_store import TokenStore
@@ -693,8 +695,8 @@ RESPONSE RULES:
693
695
  agent_type=agent_type,
694
696
  description=description or prompt[:50],
695
697
  system_prompt=system_prompt,
696
- model=actual_model,
697
- thinking_budget=actual_thinking_budget,
698
+ model=model, # Not used for Claude CLI, kept for API compatibility
699
+ thinking_budget=thinking_budget, # Not used for Claude CLI, kept for API compatibility
698
700
  timeout=timeout,
699
701
  )
700
702
 
@@ -702,8 +704,6 @@ RESPONSE RULES:
702
704
 
703
705
  **Task ID**: {task_id}
704
706
  **Agent Type**: {agent_type}
705
- **Model**: {actual_model}
706
- **Thinking Budget**: {actual_thinking_budget if actual_thinking_budget > 0 else "N/A"}
707
707
  **Description**: {description or prompt[:50]}
708
708
 
709
709
  The agent is now running. Use:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stravinsky
3
- Version: 0.2.38
3
+ Version: 0.2.40
4
4
  Summary: MCP Bridge for Claude Code with Multi-Model Support. Install globally: claude mcp add --scope user stravinsky -- uvx stravinsky. Add to CLAUDE.md: See https://pypi.org/project/stravinsky/
5
5
  Project-URL: Repository, https://github.com/GratefulDave/stravinsky
6
6
  Project-URL: Issues, https://github.com/GratefulDave/stravinsky/issues
@@ -37,7 +37,7 @@ mcp_bridge/prompts/frontend.py,sha256=j91I8k5vcVed13eeX-Ebiv49x9Qj4HO_SQN1xhB8TL
37
37
  mcp_bridge/prompts/multimodal.py,sha256=Svw11N392LjshalasOd80X0Qw_qtOMqu_lD-_HmQDIo,1936
38
38
  mcp_bridge/prompts/stravinsky.py,sha256=_ar9w9ZJkYKu73cW0YUrqqz7EAfsPX98SH8AiPQIcsg,24793
39
39
  mcp_bridge/tools/__init__.py,sha256=SRnMaUni0BhlvCABBEYeyveNiOAMQPNBXmjUKG6aXQA,1150
40
- mcp_bridge/tools/agent_manager.py,sha256=uuFMmOCiwtV4WcepuED8g5NdYqAMCbniScclGXrxTcQ,28216
40
+ mcp_bridge/tools/agent_manager.py,sha256=OiKEpG-wBEVySD-ulmKkrLzEVXYfal-0Dtllp5agb40,28233
41
41
  mcp_bridge/tools/background_tasks.py,sha256=G1iQ00538q939-DJbzaEsA0uZI2TfwzawFCDx8QC5Hg,5178
42
42
  mcp_bridge/tools/code_search.py,sha256=sR-alLQuxaXUFB9hby_wQsQu3Io644wdnpdOM_vm0aw,9978
43
43
  mcp_bridge/tools/continuous_loop.py,sha256=MM3FnF3ULuR32h0tqJP8uF48iJg6R9dbyHy_36KLOls,2100
@@ -51,7 +51,7 @@ mcp_bridge/tools/templates.py,sha256=A7eFk08Y2TZ2FPnsYLkVYCGOm1dd8scpNfcjCl_vC24
51
51
  mcp_bridge/tools/lsp/__init__.py,sha256=fLiII9qgeachI3MlkO6uGulfUH3T0YDeyEfO65bbxdw,549
52
52
  mcp_bridge/tools/lsp/tools.py,sha256=nfXT3LBD5Mas_98f1zwu62jkpInGXUR-1vLl1zIykUw,16315
53
53
  mcp_bridge/utils/__init__.py,sha256=pbHV4nq5SLUYcAyTmLUZYrp293Ctud57X8hwsMGA_BM,20
54
- stravinsky-0.2.38.dist-info/METADATA,sha256=Es0t_TM3xhCbTa4lRYKhsdcKCNGVK1bt7W4MLa-kz_c,7091
55
- stravinsky-0.2.38.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
56
- stravinsky-0.2.38.dist-info/entry_points.txt,sha256=BISwF7i71Oen7jFVmBXz8fxiU11Cp415wPF0xXG2Q3s,97
57
- stravinsky-0.2.38.dist-info/RECORD,,
54
+ stravinsky-0.2.40.dist-info/METADATA,sha256=dtiavtqJ4fboG8mRZIxMOrTGPI_7wKFar_Muuq-qy7Y,7091
55
+ stravinsky-0.2.40.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
56
+ stravinsky-0.2.40.dist-info/entry_points.txt,sha256=BISwF7i71Oen7jFVmBXz8fxiU11Cp415wPF0xXG2Q3s,97
57
+ stravinsky-0.2.40.dist-info/RECORD,,