devsquad 3.6.0__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.
Files changed (95) hide show
  1. devsquad-3.6.0.dist-info/METADATA +944 -0
  2. devsquad-3.6.0.dist-info/RECORD +95 -0
  3. devsquad-3.6.0.dist-info/WHEEL +5 -0
  4. devsquad-3.6.0.dist-info/entry_points.txt +2 -0
  5. devsquad-3.6.0.dist-info/licenses/LICENSE +21 -0
  6. devsquad-3.6.0.dist-info/top_level.txt +2 -0
  7. scripts/__init__.py +0 -0
  8. scripts/ai_semantic_matcher.py +512 -0
  9. scripts/alert_manager.py +505 -0
  10. scripts/api/__init__.py +43 -0
  11. scripts/api/models.py +386 -0
  12. scripts/api/routes/__init__.py +20 -0
  13. scripts/api/routes/dispatch.py +348 -0
  14. scripts/api/routes/lifecycle.py +330 -0
  15. scripts/api/routes/metrics_gates.py +347 -0
  16. scripts/api_server.py +318 -0
  17. scripts/auth.py +451 -0
  18. scripts/cli/__init__.py +1 -0
  19. scripts/cli/cli_visual.py +642 -0
  20. scripts/cli.py +1094 -0
  21. scripts/collaboration/__init__.py +212 -0
  22. scripts/collaboration/_version.py +1 -0
  23. scripts/collaboration/agent_briefing.py +656 -0
  24. scripts/collaboration/ai_semantic_matcher.py +260 -0
  25. scripts/collaboration/anchor_checker.py +281 -0
  26. scripts/collaboration/anti_rationalization.py +470 -0
  27. scripts/collaboration/async_integration_example.py +255 -0
  28. scripts/collaboration/batch_scheduler.py +149 -0
  29. scripts/collaboration/checkpoint_manager.py +561 -0
  30. scripts/collaboration/ci_feedback_adapter.py +351 -0
  31. scripts/collaboration/code_map_generator.py +247 -0
  32. scripts/collaboration/concern_pack_loader.py +352 -0
  33. scripts/collaboration/confidence_score.py +496 -0
  34. scripts/collaboration/config_loader.py +188 -0
  35. scripts/collaboration/consensus.py +244 -0
  36. scripts/collaboration/context_compressor.py +533 -0
  37. scripts/collaboration/coordinator.py +668 -0
  38. scripts/collaboration/dispatcher.py +1636 -0
  39. scripts/collaboration/dual_layer_context.py +128 -0
  40. scripts/collaboration/enhanced_worker.py +539 -0
  41. scripts/collaboration/feature_usage_tracker.py +206 -0
  42. scripts/collaboration/five_axis_consensus.py +334 -0
  43. scripts/collaboration/input_validator.py +401 -0
  44. scripts/collaboration/integration_example.py +287 -0
  45. scripts/collaboration/intent_workflow_mapper.py +350 -0
  46. scripts/collaboration/language_parsers.py +269 -0
  47. scripts/collaboration/lifecycle_protocol.py +1446 -0
  48. scripts/collaboration/llm_backend.py +453 -0
  49. scripts/collaboration/llm_cache.py +448 -0
  50. scripts/collaboration/llm_cache_async.py +347 -0
  51. scripts/collaboration/llm_retry.py +387 -0
  52. scripts/collaboration/llm_retry_async.py +389 -0
  53. scripts/collaboration/mce_adapter.py +597 -0
  54. scripts/collaboration/memory_bridge.py +1607 -0
  55. scripts/collaboration/models.py +537 -0
  56. scripts/collaboration/null_providers.py +297 -0
  57. scripts/collaboration/operation_classifier.py +289 -0
  58. scripts/collaboration/output_slicer.py +225 -0
  59. scripts/collaboration/performance_monitor.py +462 -0
  60. scripts/collaboration/permission_guard.py +865 -0
  61. scripts/collaboration/prompt_assembler.py +756 -0
  62. scripts/collaboration/prompt_variant_generator.py +483 -0
  63. scripts/collaboration/protocols.py +267 -0
  64. scripts/collaboration/report_formatter.py +352 -0
  65. scripts/collaboration/retrospective.py +279 -0
  66. scripts/collaboration/role_matcher.py +92 -0
  67. scripts/collaboration/role_template_market.py +352 -0
  68. scripts/collaboration/rule_collector.py +678 -0
  69. scripts/collaboration/scratchpad.py +346 -0
  70. scripts/collaboration/skill_registry.py +151 -0
  71. scripts/collaboration/skillifier.py +878 -0
  72. scripts/collaboration/standardized_role_template.py +317 -0
  73. scripts/collaboration/task_completion_checker.py +237 -0
  74. scripts/collaboration/test_quality_guard.py +695 -0
  75. scripts/collaboration/unified_gate_engine.py +598 -0
  76. scripts/collaboration/usage_tracker.py +309 -0
  77. scripts/collaboration/user_friendly_error.py +176 -0
  78. scripts/collaboration/verification_gate.py +312 -0
  79. scripts/collaboration/warmup_manager.py +635 -0
  80. scripts/collaboration/worker.py +513 -0
  81. scripts/collaboration/workflow_engine.py +684 -0
  82. scripts/dashboard.py +1088 -0
  83. scripts/generate_benchmark_report.py +786 -0
  84. scripts/history_manager.py +604 -0
  85. scripts/mcp_server.py +289 -0
  86. skills/__init__.py +32 -0
  87. skills/dispatch/handler.py +52 -0
  88. skills/intent/handler.py +59 -0
  89. skills/registry.py +67 -0
  90. skills/retrospective/__init__.py +0 -0
  91. skills/retrospective/handler.py +125 -0
  92. skills/review/handler.py +356 -0
  93. skills/security/handler.py +454 -0
  94. skills/test/__init__.py +0 -0
  95. skills/test/handler.py +78 -0
@@ -0,0 +1,255 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Async Integration Example
5
+
6
+ Demonstrates how to use async LLM cache and retry modules together
7
+ for optimal performance in asyncio applications.
8
+
9
+ This example shows:
10
+ - Async cache integration
11
+ - Async retry with fallback
12
+ - Combined usage patterns
13
+ - Performance monitoring
14
+ """
15
+
16
+ import asyncio
17
+ import logging
18
+ import time
19
+ from typing import Optional
20
+
21
+ from scripts.collaboration.llm_cache_async import get_async_llm_cache
22
+ from scripts.collaboration.llm_retry_async import async_retry_with_fallback, get_async_retry_manager
23
+
24
+ logging.basicConfig(level=logging.INFO)
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ # Simulated async LLM API calls
29
+ async def mock_openai_api(prompt: str, model: str = "gpt-4") -> str:
30
+ """Simulate OpenAI API call"""
31
+ await asyncio.sleep(0.1) # Simulate network latency
32
+ return f"OpenAI {model} response to: {prompt}"
33
+
34
+
35
+ async def mock_anthropic_api(prompt: str, model: str = "claude-3") -> str:
36
+ """Simulate Anthropic API call"""
37
+ await asyncio.sleep(0.1)
38
+ return f"Anthropic {model} response to: {prompt}"
39
+
40
+
41
+ # Example 1: Basic async cache usage
42
+ async def example_basic_cache():
43
+ """Example: Basic async cache usage"""
44
+ print("\n=== Example 1: Basic Async Cache ===")
45
+
46
+ cache = get_async_llm_cache()
47
+ prompt = "What is Python?"
48
+
49
+ # First call - cache miss
50
+ start = time.time()
51
+ cached = await cache.get(prompt, "openai", "gpt-4")
52
+ if not cached:
53
+ response = await mock_openai_api(prompt)
54
+ await cache.set(prompt, response, "openai", "gpt-4")
55
+ print(f"Cache miss - API called ({time.time() - start:.3f}s)")
56
+
57
+ # Second call - cache hit
58
+ start = time.time()
59
+ cached = await cache.get(prompt, "openai", "gpt-4")
60
+ print(f"Cache hit - Response: {cached[:50]}... ({time.time() - start:.3f}s)")
61
+
62
+ # Print stats
63
+ stats = cache.get_stats()
64
+ print(f"Cache stats: {stats['hits']} hits, {stats['misses']} misses, {stats['hit_rate']:.1%} hit rate")
65
+
66
+
67
+ # Example 2: Async retry with fallback
68
+ async def example_retry_fallback():
69
+ """Example: Async retry with fallback"""
70
+ print("\n=== Example 2: Async Retry with Fallback ===")
71
+
72
+ call_count = {"count": 0}
73
+
74
+ @async_retry_with_fallback(
75
+ max_retries=3,
76
+ initial_delay=0.1,
77
+ fallback_backends=["anthropic"]
78
+ )
79
+ async def call_llm(prompt: str, backend: str = "openai"):
80
+ call_count["count"] += 1
81
+ print(f" Attempt {call_count['count']}: Calling {backend}")
82
+
83
+ # Simulate failure on first 2 attempts with openai
84
+ if backend == "openai" and call_count["count"] < 3:
85
+ raise Exception("503 Service Unavailable")
86
+
87
+ if backend == "openai":
88
+ return await mock_openai_api(prompt)
89
+ else:
90
+ return await mock_anthropic_api(prompt)
91
+
92
+ try:
93
+ result = await call_llm("Hello, world!")
94
+ print(f"Success: {result}")
95
+ except Exception as e:
96
+ print(f"Failed: {e}")
97
+
98
+ # Print stats
99
+ manager = get_async_retry_manager()
100
+ stats = manager.get_stats()
101
+ print(f"Retry stats: {stats['retries']} retries, {stats['fallbacks']} fallbacks")
102
+
103
+
104
+ # Example 3: Combined cache + retry
105
+ async def example_combined():
106
+ """Example: Combined cache and retry"""
107
+ print("\n=== Example 3: Combined Cache + Retry ===")
108
+
109
+ cache = get_async_llm_cache()
110
+
111
+ @async_retry_with_fallback(
112
+ max_retries=2,
113
+ initial_delay=0.1,
114
+ fallback_backends=["anthropic"]
115
+ )
116
+ async def cached_llm_call(prompt: str, backend: str = "openai", model: str = "gpt-4"):
117
+ # Try cache first
118
+ cached = await cache.get(prompt, backend, model)
119
+ if cached:
120
+ print(f" Cache hit for {backend}")
121
+ return cached
122
+
123
+ # Cache miss - call API
124
+ print(f" Cache miss - calling {backend} API")
125
+ if backend == "openai":
126
+ response = await mock_openai_api(prompt, model)
127
+ else:
128
+ response = await mock_anthropic_api(prompt, model)
129
+
130
+ # Save to cache
131
+ await cache.set(prompt, response, backend, model)
132
+ return response
133
+
134
+ # First call - cache miss, API call
135
+ result1 = await cached_llm_call("What is async/await?")
136
+ print(f"Result 1: {result1[:50]}...")
137
+
138
+ # Second call - cache hit, no API call
139
+ result2 = await cached_llm_call("What is async/await?")
140
+ print(f"Result 2: {result2[:50]}...")
141
+
142
+ # Print combined stats
143
+ cache_stats = cache.get_stats()
144
+ retry_stats = get_async_retry_manager().get_stats()
145
+ print(f"\nCache: {cache_stats['hit_rate']:.1%} hit rate")
146
+ print(f"Retry: {retry_stats['successful_calls']}/{retry_stats['total_calls']} successful")
147
+
148
+
149
+ # Example 4: Concurrent requests
150
+ async def example_concurrent():
151
+ """Example: Concurrent async requests"""
152
+ print("\n=== Example 4: Concurrent Requests ===")
153
+
154
+ cache = get_async_llm_cache()
155
+
156
+ @async_retry_with_fallback(max_retries=2, initial_delay=0.1)
157
+ async def cached_call(prompt: str, backend: str = "openai"):
158
+ cached = await cache.get(prompt, backend, "gpt-4")
159
+ if cached:
160
+ return cached
161
+
162
+ response = await mock_openai_api(prompt)
163
+ await cache.set(prompt, response, backend, "gpt-4")
164
+ return response
165
+
166
+ # Make multiple concurrent requests
167
+ prompts = [
168
+ "What is Python?",
169
+ "What is JavaScript?",
170
+ "What is Rust?",
171
+ "What is Python?", # Duplicate - should hit cache
172
+ "What is Go?"
173
+ ]
174
+
175
+ start = time.time()
176
+ results = await asyncio.gather(*[cached_call(p) for p in prompts])
177
+ elapsed = time.time() - start
178
+
179
+ print(f"Processed {len(prompts)} requests in {elapsed:.3f}s")
180
+ print(f"Average: {elapsed/len(prompts):.3f}s per request")
181
+
182
+ # Print stats
183
+ stats = cache.get_stats()
184
+ print(f"Cache: {stats['hits']} hits, {stats['misses']} misses")
185
+
186
+
187
+ # Example 5: Error handling and circuit breaker
188
+ async def example_circuit_breaker():
189
+ """Example: Circuit breaker in action"""
190
+ print("\n=== Example 5: Circuit Breaker ===")
191
+
192
+ failure_count = {"count": 0}
193
+
194
+ @async_retry_with_fallback(
195
+ max_retries=1,
196
+ initial_delay=0.05,
197
+ fallback_backends=["anthropic"]
198
+ )
199
+ async def unreliable_call(prompt: str, backend: str = "openai"):
200
+ failure_count["count"] += 1
201
+
202
+ # Simulate consistent failures to trigger circuit breaker
203
+ if backend == "openai" and failure_count["count"] <= 6:
204
+ raise Exception("503 Service Unavailable")
205
+
206
+ if backend == "openai":
207
+ return await mock_openai_api(prompt)
208
+ else:
209
+ return await mock_anthropic_api(prompt)
210
+
211
+ # Make multiple calls to trigger circuit breaker
212
+ for i in range(8):
213
+ try:
214
+ result = await unreliable_call(f"Request {i+1}")
215
+ print(f" Request {i+1}: Success - {result[:40]}...")
216
+ except Exception as e:
217
+ print(f" Request {i+1}: Failed - {str(e)[:40]}...")
218
+
219
+ await asyncio.sleep(0.05)
220
+
221
+ # Print circuit breaker stats
222
+ manager = get_async_retry_manager()
223
+ stats = manager.get_stats()
224
+ print(f"\nCircuit breaker trips: {stats['circuit_breaker_trips']}")
225
+ print(f"Fallbacks: {stats['fallbacks']}")
226
+
227
+
228
+ # Main example runner
229
+ async def main():
230
+ """Run all examples"""
231
+ print("=" * 60)
232
+ print("Async LLM Optimization Examples")
233
+ print("=" * 60)
234
+
235
+ await example_basic_cache()
236
+ await asyncio.sleep(0.5)
237
+
238
+ await example_retry_fallback()
239
+ await asyncio.sleep(0.5)
240
+
241
+ await example_combined()
242
+ await asyncio.sleep(0.5)
243
+
244
+ await example_concurrent()
245
+ await asyncio.sleep(0.5)
246
+
247
+ await example_circuit_breaker()
248
+
249
+ print("\n" + "=" * 60)
250
+ print("All examples completed!")
251
+ print("=" * 60)
252
+
253
+
254
+ if __name__ == "__main__":
255
+ asyncio.run(main())
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ BatchScheduler - 批处理调度器
5
+
6
+ 支持并行/串行混合调度,带超时、重试和依赖管理。
7
+ """
8
+
9
+ import time
10
+ from typing import List, Optional
11
+
12
+ from .models import (
13
+ TaskDefinition,
14
+ TaskBatch,
15
+ BatchMode,
16
+ ScheduleResult,
17
+ WorkerResult,
18
+ )
19
+ from .worker import Worker
20
+
21
+
22
+ class BatchScheduler:
23
+ """
24
+ 批处理调度器 - 并行/串行混合任务调度
25
+
26
+ 负责 TaskBatch 列表的执行编排:
27
+ - PARALLEL 批次: 并发执行(受 max_concurrency 限制)
28
+ - SEQUENTIAL 批次: 串行逐个执行(带自动重试)
29
+ - 依赖管理: 检查批次间依赖关系,依赖未满足则跳过
30
+
31
+ 默认配置:
32
+ - 超时: 300s
33
+ - 重试次数: 2次
34
+ """
35
+
36
+ def __init__(self):
37
+ """
38
+ 初始化批处理调度器
39
+
40
+ 使用默认超时(300s)和重试次数(2次)。
41
+ 可通过修改 _default_timeout / _default_retries 调整。
42
+ """
43
+ self._default_timeout = 300
44
+ self._default_retries = 2
45
+
46
+ def schedule(self, batches: List[TaskBatch],
47
+ workers: dict) -> ScheduleResult:
48
+ """
49
+ 执行批处理调度计划
50
+
51
+ 按顺序遍历批次列表,对每个批次:
52
+ 1. 检查依赖是否满足(未满足则跳过并记录错误)
53
+ 2. 根据 mode 选择并行或串行执行
54
+ 3. 汇总所有结果和错误
55
+
56
+ Args:
57
+ batches: 任务批次列表(由 Coordinator.plan_task 生成)
58
+ workers: Worker 字典 {worker_id: Worker 实例}
59
+
60
+ Returns:
61
+ ScheduleResult: 调度结果,包含成功/失败统计、各Worker结果、耗时
62
+ """
63
+ start_time = time.time()
64
+ all_results = []
65
+ all_errors = []
66
+ total_tasks = 0
67
+
68
+ completed_batches = set()
69
+ for batch in batches:
70
+ if batch.dependencies:
71
+ missing = [d for d in batch.dependencies if d not in completed_batches]
72
+ if missing:
73
+ all_errors.append(f"Batch {batch.batch_id} 依赖未满足: {missing}")
74
+ continue
75
+
76
+ if batch.mode == BatchMode.PARALLEL:
77
+ results, errors = self._execute_parallel(batch, workers)
78
+ else:
79
+ results, errors = self._execute_serial(batch, workers)
80
+
81
+ all_results.extend(results)
82
+ all_errors.extend(errors)
83
+ total_tasks += len(batch.tasks)
84
+ completed_batches.add(batch.batch_id)
85
+
86
+ return ScheduleResult(
87
+ success=len(all_errors) == 0,
88
+ total_tasks=total_tasks,
89
+ completed_tasks=sum(1 for r in all_results if r.success),
90
+ failed_tasks=len(all_errors),
91
+ results=all_results,
92
+ duration_seconds=time.time() - start_time,
93
+ errors=all_errors,
94
+ )
95
+
96
+ def _execute_parallel(self, batch: TaskBatch,
97
+ workers: dict) -> tuple:
98
+ results = []
99
+ errors = []
100
+ for task in batch.tasks[:batch.max_concurrency]:
101
+ worker = self._find_worker(workers, task.role_id)
102
+ if not worker:
103
+ errors.append(f"No worker available for role {task.role_id}")
104
+ continue
105
+ try:
106
+ result = worker.execute(task)
107
+ results.append(result)
108
+ except Exception as e:
109
+ errors.append(f"Worker {worker.worker_id} error: {e}")
110
+ return results, errors
111
+
112
+ def _execute_serial(self, batch: TaskBatch,
113
+ workers: dict) -> tuple:
114
+ results = []
115
+ errors = []
116
+ for task in batch.tasks:
117
+ worker = self._find_worker(workers, task.role_id)
118
+ if not worker:
119
+ errors.append(f"No worker available for role {task.role_id}")
120
+ continue
121
+ for attempt in range(self._default_retries + 1):
122
+ try:
123
+ result = worker.execute(task)
124
+ results.append(result)
125
+ break
126
+ except Exception as e:
127
+ if attempt == self._default_retries:
128
+ errors.append(f"Task {task.task_id} failed after retries: {e}")
129
+ return results, errors
130
+
131
+ def is_concurrency_safe(self, task: TaskDefinition) -> bool:
132
+ """
133
+ 判断任务是否可安全并发执行
134
+
135
+ 当前实现: 只读任务(is_read_only=True) 可并发。
136
+
137
+ Args:
138
+ task: 任务定义
139
+
140
+ Returns:
141
+ bool: 是否允许并发
142
+ """
143
+ return task.is_read_only
144
+
145
+ def _find_worker(self, workers: dict, role_id: str) -> Optional[Worker]:
146
+ for w in workers.values():
147
+ if w.role_id == role_id:
148
+ return w
149
+ return None