stravinsky 0.4.18__py3-none-any.whl → 0.4.66__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.

Potentially problematic release.


This version of stravinsky might be problematic. Click here for more details.

Files changed (184) hide show
  1. mcp_bridge/__init__.py +1 -1
  2. mcp_bridge/auth/__init__.py +16 -6
  3. mcp_bridge/auth/cli.py +202 -11
  4. mcp_bridge/auth/oauth.py +1 -2
  5. mcp_bridge/auth/openai_oauth.py +4 -7
  6. mcp_bridge/auth/token_store.py +0 -1
  7. mcp_bridge/cli/__init__.py +1 -1
  8. mcp_bridge/cli/install_hooks.py +503 -107
  9. mcp_bridge/cli/session_report.py +0 -3
  10. mcp_bridge/config/__init__.py +2 -2
  11. mcp_bridge/config/hook_config.py +3 -5
  12. mcp_bridge/config/rate_limits.py +108 -13
  13. mcp_bridge/hooks/HOOKS_SETTINGS.json +17 -4
  14. mcp_bridge/hooks/__init__.py +14 -4
  15. mcp_bridge/hooks/agent_reminder.py +4 -4
  16. mcp_bridge/hooks/auto_slash_command.py +5 -5
  17. mcp_bridge/hooks/budget_optimizer.py +2 -2
  18. mcp_bridge/hooks/claude_limits_hook.py +114 -0
  19. mcp_bridge/hooks/comment_checker.py +3 -4
  20. mcp_bridge/hooks/compaction.py +2 -2
  21. mcp_bridge/hooks/context.py +2 -1
  22. mcp_bridge/hooks/context_monitor.py +2 -2
  23. mcp_bridge/hooks/delegation_policy.py +85 -0
  24. mcp_bridge/hooks/directory_context.py +3 -3
  25. mcp_bridge/hooks/edit_recovery.py +3 -2
  26. mcp_bridge/hooks/edit_recovery_policy.py +49 -0
  27. mcp_bridge/hooks/empty_message_sanitizer.py +2 -2
  28. mcp_bridge/hooks/events.py +160 -0
  29. mcp_bridge/hooks/git_noninteractive.py +4 -4
  30. mcp_bridge/hooks/keyword_detector.py +8 -10
  31. mcp_bridge/hooks/manager.py +35 -22
  32. mcp_bridge/hooks/notification_hook.py +13 -6
  33. mcp_bridge/hooks/parallel_enforcement_policy.py +67 -0
  34. mcp_bridge/hooks/parallel_enforcer.py +5 -5
  35. mcp_bridge/hooks/parallel_execution.py +22 -10
  36. mcp_bridge/hooks/post_tool/parallel_validation.py +103 -0
  37. mcp_bridge/hooks/pre_compact.py +8 -9
  38. mcp_bridge/hooks/pre_tool/agent_spawn_validator.py +115 -0
  39. mcp_bridge/hooks/preemptive_compaction.py +2 -3
  40. mcp_bridge/hooks/routing_notifications.py +80 -0
  41. mcp_bridge/hooks/rules_injector.py +11 -19
  42. mcp_bridge/hooks/session_idle.py +4 -4
  43. mcp_bridge/hooks/session_notifier.py +4 -4
  44. mcp_bridge/hooks/session_recovery.py +4 -5
  45. mcp_bridge/hooks/stravinsky_mode.py +1 -1
  46. mcp_bridge/hooks/subagent_stop.py +1 -3
  47. mcp_bridge/hooks/task_validator.py +2 -2
  48. mcp_bridge/hooks/tmux_manager.py +7 -8
  49. mcp_bridge/hooks/todo_delegation.py +4 -1
  50. mcp_bridge/hooks/todo_enforcer.py +180 -10
  51. mcp_bridge/hooks/truncation_policy.py +37 -0
  52. mcp_bridge/hooks/truncator.py +1 -2
  53. mcp_bridge/metrics/cost_tracker.py +115 -0
  54. mcp_bridge/native_search.py +93 -0
  55. mcp_bridge/native_watcher.py +118 -0
  56. mcp_bridge/notifications.py +3 -4
  57. mcp_bridge/orchestrator/enums.py +11 -0
  58. mcp_bridge/orchestrator/router.py +165 -0
  59. mcp_bridge/orchestrator/state.py +32 -0
  60. mcp_bridge/orchestrator/visualization.py +14 -0
  61. mcp_bridge/orchestrator/wisdom.py +34 -0
  62. mcp_bridge/prompts/__init__.py +1 -8
  63. mcp_bridge/prompts/dewey.py +1 -1
  64. mcp_bridge/prompts/planner.py +2 -4
  65. mcp_bridge/prompts/stravinsky.py +53 -31
  66. mcp_bridge/proxy/__init__.py +0 -0
  67. mcp_bridge/proxy/client.py +70 -0
  68. mcp_bridge/proxy/model_server.py +157 -0
  69. mcp_bridge/routing/__init__.py +43 -0
  70. mcp_bridge/routing/config.py +250 -0
  71. mcp_bridge/routing/model_tiers.py +135 -0
  72. mcp_bridge/routing/provider_state.py +261 -0
  73. mcp_bridge/routing/task_classifier.py +190 -0
  74. mcp_bridge/server.py +363 -34
  75. mcp_bridge/server_tools.py +298 -6
  76. mcp_bridge/tools/__init__.py +19 -8
  77. mcp_bridge/tools/agent_manager.py +549 -799
  78. mcp_bridge/tools/background_tasks.py +13 -17
  79. mcp_bridge/tools/code_search.py +54 -51
  80. mcp_bridge/tools/continuous_loop.py +0 -1
  81. mcp_bridge/tools/dashboard.py +19 -0
  82. mcp_bridge/tools/find_code.py +296 -0
  83. mcp_bridge/tools/init.py +1 -0
  84. mcp_bridge/tools/list_directory.py +42 -0
  85. mcp_bridge/tools/lsp/__init__.py +8 -8
  86. mcp_bridge/tools/lsp/manager.py +51 -28
  87. mcp_bridge/tools/lsp/tools.py +98 -65
  88. mcp_bridge/tools/model_invoke.py +1047 -152
  89. mcp_bridge/tools/mux_client.py +75 -0
  90. mcp_bridge/tools/project_context.py +1 -2
  91. mcp_bridge/tools/query_classifier.py +132 -49
  92. mcp_bridge/tools/read_file.py +84 -0
  93. mcp_bridge/tools/replace.py +45 -0
  94. mcp_bridge/tools/run_shell_command.py +38 -0
  95. mcp_bridge/tools/search_enhancements.py +347 -0
  96. mcp_bridge/tools/semantic_search.py +677 -92
  97. mcp_bridge/tools/session_manager.py +0 -2
  98. mcp_bridge/tools/skill_loader.py +0 -1
  99. mcp_bridge/tools/task_runner.py +5 -7
  100. mcp_bridge/tools/templates.py +3 -3
  101. mcp_bridge/tools/tool_search.py +331 -0
  102. mcp_bridge/tools/write_file.py +29 -0
  103. mcp_bridge/update_manager.py +33 -37
  104. mcp_bridge/update_manager_pypi.py +6 -8
  105. mcp_bridge/utils/cache.py +82 -0
  106. mcp_bridge/utils/process.py +71 -0
  107. mcp_bridge/utils/session_state.py +51 -0
  108. mcp_bridge/utils/truncation.py +76 -0
  109. {stravinsky-0.4.18.dist-info → stravinsky-0.4.66.dist-info}/METADATA +84 -35
  110. stravinsky-0.4.66.dist-info/RECORD +198 -0
  111. {stravinsky-0.4.18.dist-info → stravinsky-0.4.66.dist-info}/entry_points.txt +1 -0
  112. stravinsky_claude_assets/HOOKS_INTEGRATION.md +316 -0
  113. stravinsky_claude_assets/agents/HOOKS.md +437 -0
  114. stravinsky_claude_assets/agents/code-reviewer.md +210 -0
  115. stravinsky_claude_assets/agents/comment_checker.md +580 -0
  116. stravinsky_claude_assets/agents/debugger.md +254 -0
  117. stravinsky_claude_assets/agents/delphi.md +495 -0
  118. stravinsky_claude_assets/agents/dewey.md +248 -0
  119. stravinsky_claude_assets/agents/explore.md +1198 -0
  120. stravinsky_claude_assets/agents/frontend.md +472 -0
  121. stravinsky_claude_assets/agents/implementation-lead.md +164 -0
  122. stravinsky_claude_assets/agents/momus.md +464 -0
  123. stravinsky_claude_assets/agents/research-lead.md +141 -0
  124. stravinsky_claude_assets/agents/stravinsky.md +730 -0
  125. stravinsky_claude_assets/commands/delphi.md +9 -0
  126. stravinsky_claude_assets/commands/dewey.md +54 -0
  127. stravinsky_claude_assets/commands/git-master.md +112 -0
  128. stravinsky_claude_assets/commands/index.md +49 -0
  129. stravinsky_claude_assets/commands/publish.md +86 -0
  130. stravinsky_claude_assets/commands/review.md +73 -0
  131. stravinsky_claude_assets/commands/str/agent_cancel.md +70 -0
  132. stravinsky_claude_assets/commands/str/agent_list.md +56 -0
  133. stravinsky_claude_assets/commands/str/agent_output.md +92 -0
  134. stravinsky_claude_assets/commands/str/agent_progress.md +74 -0
  135. stravinsky_claude_assets/commands/str/agent_retry.md +94 -0
  136. stravinsky_claude_assets/commands/str/cancel.md +51 -0
  137. stravinsky_claude_assets/commands/str/clean.md +97 -0
  138. stravinsky_claude_assets/commands/str/continue.md +38 -0
  139. stravinsky_claude_assets/commands/str/index.md +199 -0
  140. stravinsky_claude_assets/commands/str/list_watchers.md +96 -0
  141. stravinsky_claude_assets/commands/str/search.md +205 -0
  142. stravinsky_claude_assets/commands/str/start_filewatch.md +136 -0
  143. stravinsky_claude_assets/commands/str/stats.md +71 -0
  144. stravinsky_claude_assets/commands/str/stop_filewatch.md +89 -0
  145. stravinsky_claude_assets/commands/str/unwatch.md +42 -0
  146. stravinsky_claude_assets/commands/str/watch.md +45 -0
  147. stravinsky_claude_assets/commands/strav.md +53 -0
  148. stravinsky_claude_assets/commands/stravinsky.md +292 -0
  149. stravinsky_claude_assets/commands/verify.md +60 -0
  150. stravinsky_claude_assets/commands/version.md +5 -0
  151. stravinsky_claude_assets/hooks/README.md +248 -0
  152. stravinsky_claude_assets/hooks/comment_checker.py +193 -0
  153. stravinsky_claude_assets/hooks/context.py +38 -0
  154. stravinsky_claude_assets/hooks/context_monitor.py +153 -0
  155. stravinsky_claude_assets/hooks/dependency_tracker.py +73 -0
  156. stravinsky_claude_assets/hooks/edit_recovery.py +46 -0
  157. stravinsky_claude_assets/hooks/execution_state_tracker.py +68 -0
  158. stravinsky_claude_assets/hooks/notification_hook.py +103 -0
  159. stravinsky_claude_assets/hooks/notification_hook_v2.py +96 -0
  160. stravinsky_claude_assets/hooks/parallel_execution.py +241 -0
  161. stravinsky_claude_assets/hooks/parallel_reinforcement.py +106 -0
  162. stravinsky_claude_assets/hooks/parallel_reinforcement_v2.py +112 -0
  163. stravinsky_claude_assets/hooks/pre_compact.py +123 -0
  164. stravinsky_claude_assets/hooks/ralph_loop.py +173 -0
  165. stravinsky_claude_assets/hooks/session_recovery.py +263 -0
  166. stravinsky_claude_assets/hooks/stop_hook.py +89 -0
  167. stravinsky_claude_assets/hooks/stravinsky_metrics.py +164 -0
  168. stravinsky_claude_assets/hooks/stravinsky_mode.py +146 -0
  169. stravinsky_claude_assets/hooks/subagent_stop.py +98 -0
  170. stravinsky_claude_assets/hooks/todo_continuation.py +111 -0
  171. stravinsky_claude_assets/hooks/todo_delegation.py +96 -0
  172. stravinsky_claude_assets/hooks/tool_messaging.py +281 -0
  173. stravinsky_claude_assets/hooks/truncator.py +23 -0
  174. stravinsky_claude_assets/rules/deployment_safety.md +51 -0
  175. stravinsky_claude_assets/rules/integration_wiring.md +89 -0
  176. stravinsky_claude_assets/rules/pypi_deployment.md +220 -0
  177. stravinsky_claude_assets/rules/stravinsky_orchestrator.md +32 -0
  178. stravinsky_claude_assets/settings.json +152 -0
  179. stravinsky_claude_assets/skills/chrome-devtools/SKILL.md +81 -0
  180. stravinsky_claude_assets/skills/sqlite/SKILL.md +77 -0
  181. stravinsky_claude_assets/skills/supabase/SKILL.md +74 -0
  182. stravinsky_claude_assets/task_dependencies.json +34 -0
  183. stravinsky-0.4.18.dist-info/RECORD +0 -88
  184. {stravinsky-0.4.18.dist-info → stravinsky-0.4.66.dist-info}/WHEEL +0 -0
mcp_bridge/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.4.18"
1
+ __version__ = "0.4.66"
@@ -1,18 +1,28 @@
1
1
  # Authentication module
2
- from .token_store import TokenStore, TokenData
3
2
  from .oauth import (
4
- perform_oauth_flow as gemini_oauth_flow,
5
- refresh_access_token as gemini_refresh_token,
6
3
  ANTIGRAVITY_CLIENT_ID,
7
- ANTIGRAVITY_SCOPES,
8
4
  ANTIGRAVITY_HEADERS,
5
+ ANTIGRAVITY_SCOPES,
6
+ )
7
+ from .oauth import (
8
+ perform_oauth_flow as gemini_oauth_flow,
9
+ )
10
+ from .oauth import (
11
+ refresh_access_token as gemini_refresh_token,
9
12
  )
10
13
  from .openai_oauth import (
11
- perform_oauth_flow as openai_oauth_flow,
12
- refresh_access_token as openai_refresh_token,
13
14
  CLIENT_ID as OPENAI_CLIENT_ID,
15
+ )
16
+ from .openai_oauth import (
14
17
  OPENAI_CALLBACK_PORT,
15
18
  )
19
+ from .openai_oauth import (
20
+ perform_oauth_flow as openai_oauth_flow,
21
+ )
22
+ from .openai_oauth import (
23
+ refresh_access_token as openai_refresh_token,
24
+ )
25
+ from .token_store import TokenData, TokenStore
16
26
 
17
27
  __all__ = [
18
28
  # Token Store
mcp_bridge/auth/cli.py CHANGED
@@ -14,16 +14,26 @@ Usage:
14
14
  """
15
15
 
16
16
  import argparse
17
+ import json
17
18
  import sys
18
19
  import time
20
+ from pathlib import Path
19
21
 
20
- from .token_store import TokenStore
21
22
  from ..tools.init import bootstrap_repo
22
- from .oauth import perform_oauth_flow as gemini_oauth, refresh_access_token as gemini_refresh
23
+ from .oauth import perform_oauth_flow as gemini_oauth
24
+ from .oauth import refresh_access_token as gemini_refresh
23
25
  from .openai_oauth import (
24
26
  perform_oauth_flow as openai_oauth,
27
+ )
28
+ from .openai_oauth import (
25
29
  refresh_access_token as openai_refresh,
26
30
  )
31
+ from .token_store import TokenStore
32
+
33
+ try:
34
+ from ..routing import get_provider_tracker
35
+ except ImportError:
36
+ get_provider_tracker = None # type: ignore
27
37
 
28
38
 
29
39
  def cmd_login(provider: str, token_store: TokenStore) -> int:
@@ -34,7 +44,7 @@ def cmd_login(provider: str, token_store: TokenStore) -> int:
34
44
  For OpenAI: Uses OpenAI OAuth (ChatGPT Plus/Pro subscription)
35
45
  """
36
46
  if provider == "gemini":
37
- print(f"Starting Google OAuth for Gemini...")
47
+ print("Starting Google OAuth for Gemini...")
38
48
 
39
49
  try:
40
50
  result = gemini_oauth()
@@ -57,7 +67,7 @@ def cmd_login(provider: str, token_store: TokenStore) -> int:
57
67
  return 1
58
68
 
59
69
  elif provider == "openai":
60
- print(f"Starting OpenAI OAuth for ChatGPT Plus/Pro...")
70
+ print("Starting OpenAI OAuth for ChatGPT Plus/Pro...")
61
71
  print("Note: Requires ChatGPT Plus/Pro subscription and port 1455 available")
62
72
 
63
73
  try:
@@ -72,7 +82,7 @@ def cmd_login(provider: str, token_store: TokenStore) -> int:
72
82
  expires_at=expires_at,
73
83
  )
74
84
 
75
- print(f"\nāœ“ Successfully authenticated with OpenAI")
85
+ print("\nāœ“ Successfully authenticated with OpenAI")
76
86
  print(f" Token expires in: {result.expires_in // 60} minutes")
77
87
  return 0
78
88
 
@@ -116,20 +126,156 @@ def cmd_status(token_store: TokenStore) -> int:
116
126
  minutes = (remaining % 3600) // 60
117
127
  print(f" Expires in: {hours}h {minutes}m")
118
128
  else:
119
- print(f" Token expired")
129
+ print(" Token expired")
120
130
 
121
131
  print()
122
132
  return 0
123
133
 
124
134
 
125
135
  def cmd_refresh(provider: str, token_store: TokenStore) -> int:
126
- """Refresh access token for a provider."""
127
- token = token_store.get_token(provider)
128
- if not token or not token.get("refresh_token"):
129
- print(f"No refresh token found for {provider}")
130
- print(f"Please run: python -m mcp_bridge.auth.cli login {provider}")
136
+ """Manually refresh an access token."""
137
+ try:
138
+ token = token_store.get_token(provider)
139
+ if not token:
140
+ print(f"Not logged in to {provider}. Run 'stravinsky-auth login {provider}' first.")
141
+ return 1
142
+
143
+ print(f"Refreshing {provider} access token...")
144
+
145
+ if provider == "gemini":
146
+ result = gemini_refresh(token["refresh_token"])
147
+ elif provider == "openai":
148
+ result = openai_refresh(token["refresh_token"])
149
+ else:
150
+ print(f"Refresh not supported for {provider}")
151
+ return 1
152
+
153
+ expires_at = int(time.time()) + result.expires_in
154
+
155
+ token_store.set_token(
156
+ provider=provider,
157
+ access_token=result.access_token,
158
+ refresh_token=result.refresh_token or token["refresh_token"],
159
+ expires_at=expires_at,
160
+ )
161
+
162
+ print(f"āœ“ Token refreshed, expires in {result.expires_in // 60} minutes")
163
+ return 0
164
+
165
+ except Exception as e:
166
+ print(f"āœ— Refresh failed: {e}", file=sys.stderr)
167
+ return 1
168
+
169
+
170
+ def cmd_routing_status() -> int:
171
+ """Show current routing provider states."""
172
+ if not get_provider_tracker or not callable(get_provider_tracker):
173
+ print("āœ— Routing module not available", file=sys.stderr)
131
174
  return 1
132
175
 
176
+ try:
177
+ tracker = get_provider_tracker()
178
+ status = tracker.get_status()
179
+
180
+ print("\nšŸ“Š Provider Routing Status\n")
181
+ for provider_name, state in status.items():
182
+ available = "āœ“ Available" if state["available"] else "ā³ In Cooldown"
183
+ print(f"{provider_name.title():10} {available}")
184
+
185
+ if state["cooldown_remaining"]:
186
+ mins = int(state["cooldown_remaining"] / 60)
187
+ secs = int(state["cooldown_remaining"] % 60)
188
+ print(f" Cooldown: {mins}m {secs}s remaining")
189
+
190
+ print(f" Requests: {state['total_requests']}")
191
+ print(f" Failures: {state['total_failures']}")
192
+
193
+ if state["last_error"]:
194
+ print(f" Last error: {state['last_error']}")
195
+
196
+ print()
197
+
198
+ return 0
199
+
200
+ except Exception as e:
201
+ print(f"āœ— Failed to get routing status: {e}", file=sys.stderr)
202
+ return 1
203
+
204
+
205
+ def cmd_routing_reset(provider: str | None = None) -> int:
206
+ """Reset provider cooldown states."""
207
+ if not get_provider_tracker or not callable(get_provider_tracker):
208
+ print("āœ— Routing module not available", file=sys.stderr)
209
+ return 1
210
+
211
+ try:
212
+ tracker = get_provider_tracker()
213
+
214
+ if provider:
215
+ tracker.reset_provider(provider)
216
+ print(f"āœ“ Reset cooldown state for {provider}")
217
+ else:
218
+ tracker.reset_all()
219
+ print("āœ“ Reset all provider cooldown states")
220
+
221
+ return 0
222
+
223
+ except Exception as e:
224
+ print(f"āœ— Failed to reset routing state: {e}", file=sys.stderr)
225
+ return 1
226
+
227
+
228
+ def cmd_routing_init() -> int:
229
+ """Create default routing.json configuration."""
230
+ config_path = Path(".stravinsky/routing.json")
231
+
232
+ if config_path.exists():
233
+ response = input(f"{config_path} already exists. Overwrite? [y/N]: ")
234
+ if response.lower() != "y":
235
+ print("Cancelled.")
236
+ return 0
237
+
238
+ config_path.parent.mkdir(parents=True, exist_ok=True)
239
+
240
+ default_config = {
241
+ "routing": {
242
+ "task_routing": {
243
+ "code_generation": {
244
+ "provider": "openai",
245
+ "model": "gpt-5-codex",
246
+ "description": "Complex code generation tasks",
247
+ },
248
+ "debugging": {
249
+ "provider": "openai",
250
+ "model": "gpt-5-codex",
251
+ "description": "Code analysis and debugging",
252
+ },
253
+ "documentation": {
254
+ "provider": "gemini",
255
+ "model": "gemini-3-flash",
256
+ "description": "Documentation writing",
257
+ },
258
+ "code_search": {
259
+ "provider": "gemini",
260
+ "model": "gemini-3-flash",
261
+ "description": "Finding code patterns",
262
+ },
263
+ },
264
+ "fallback": {
265
+ "enabled": True,
266
+ "chain": ["claude", "openai", "gemini"],
267
+ "cooldown_seconds": 300,
268
+ },
269
+ }
270
+ }
271
+
272
+ with open(config_path, "w") as f:
273
+ json.dump(default_config, f, indent=2)
274
+
275
+ print(f"āœ“ Created {config_path}")
276
+ print("\nEdit this file to customize routing behavior for this project.")
277
+ return 0
278
+
133
279
  try:
134
280
  print(f"Refreshing {provider} token...")
135
281
 
@@ -226,6 +372,41 @@ def main():
226
372
  description="Creates .stravinsky/ directory structure and copies default configuration files.",
227
373
  )
228
374
 
375
+ # routing command
376
+ routing_parser = subparsers.add_parser(
377
+ "routing",
378
+ help="Manage provider routing and fallback",
379
+ description="View and manage provider routing states, cooldowns, and configuration.",
380
+ )
381
+ routing_subparsers = routing_parser.add_subparsers(
382
+ dest="routing_command", help="Routing subcommands", metavar="SUBCOMMAND"
383
+ )
384
+
385
+ routing_subparsers.add_parser(
386
+ "status",
387
+ help="Show current provider routing states",
388
+ description="Display availability, cooldown timers, and error counts for all providers.",
389
+ )
390
+
391
+ routing_reset_parser = routing_subparsers.add_parser(
392
+ "reset",
393
+ help="Reset provider cooldown states",
394
+ description="Clear cooldown timers for one or all providers.",
395
+ )
396
+ routing_reset_parser.add_argument(
397
+ "provider",
398
+ nargs="?",
399
+ choices=["claude", "openai", "gemini"],
400
+ metavar="PROVIDER",
401
+ help="Provider to reset (omit to reset all)",
402
+ )
403
+
404
+ routing_subparsers.add_parser(
405
+ "init",
406
+ help="Create default routing.json configuration",
407
+ description="Generate .stravinsky/routing.json with default task-based routing rules.",
408
+ )
409
+
229
410
  args = parser.parse_args()
230
411
 
231
412
  if not args.command:
@@ -245,6 +426,16 @@ def main():
245
426
  elif args.command == "init":
246
427
  print(bootstrap_repo())
247
428
  return 0
429
+ elif args.command == "routing":
430
+ if not args.routing_command:
431
+ routing_parser.print_help()
432
+ return 1
433
+ if args.routing_command == "status":
434
+ return cmd_routing_status()
435
+ elif args.routing_command == "reset":
436
+ return cmd_routing_reset(args.provider if hasattr(args, "provider") else None)
437
+ elif args.routing_command == "init":
438
+ return cmd_routing_init()
248
439
 
249
440
  return 0
250
441
 
mcp_bridge/auth/oauth.py CHANGED
@@ -13,13 +13,12 @@ import secrets
13
13
  import threading
14
14
  import webbrowser
15
15
  from dataclasses import dataclass
16
- from http.server import HTTPServer, BaseHTTPRequestHandler
16
+ from http.server import BaseHTTPRequestHandler, HTTPServer
17
17
  from typing import Any
18
18
  from urllib.parse import parse_qs, urlencode, urlparse
19
19
 
20
20
  import httpx
21
21
 
22
-
23
22
  # OAuth 2.0 Client Credentials (from constants.ts)
24
23
  ANTIGRAVITY_CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com"
25
24
  ANTIGRAVITY_CLIENT_SECRET = "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"
@@ -9,19 +9,16 @@ Port from: https://github.com/numman-ali/opencode-openai-codex-auth/blob/main/li
9
9
 
10
10
  import base64
11
11
  import hashlib
12
- import json
13
12
  import secrets
14
13
  import threading
15
14
  import webbrowser
16
15
  from dataclasses import dataclass
17
- from http.server import HTTPServer, BaseHTTPRequestHandler
16
+ from http.server import BaseHTTPRequestHandler, HTTPServer
18
17
  from typing import Any
19
18
  from urllib.parse import parse_qs, urlencode, urlparse
20
- import time
21
19
 
22
20
  import httpx
23
21
 
24
-
25
22
  # OAuth constants (from openai/codex via opencode-openai-codex-auth)
26
23
  CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann"
27
24
  AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize" # Note: /oauth/authorize
@@ -303,8 +300,8 @@ def perform_oauth_flow(timeout: int = 300) -> TokenResult:
303
300
  try:
304
301
  auth_url, verifier, state = build_auth_url(redirect_uri)
305
302
 
306
- print(f"\nšŸ” Opening browser for OpenAI authentication...")
307
- print(f"\nIf browser doesn't open, visit:")
303
+ print("\nšŸ” Opening browser for OpenAI authentication...")
304
+ print("\nIf browser doesn't open, visit:")
308
305
  print(f"{auth_url}\n")
309
306
 
310
307
  webbrowser.open(auth_url)
@@ -329,7 +326,7 @@ def perform_oauth_flow(timeout: int = 300) -> TokenResult:
329
326
  print("šŸ“ Exchanging code for tokens...")
330
327
  tokens = exchange_code(result["code"], verifier, redirect_uri)
331
328
 
332
- print(f"āœ“ Successfully authenticated with OpenAI")
329
+ print("āœ“ Successfully authenticated with OpenAI")
333
330
 
334
331
  return tokens
335
332
 
@@ -8,7 +8,6 @@ Stores OAuth tokens securely using the OS keyring:
8
8
  """
9
9
 
10
10
  import json
11
- import os
12
11
  import time
13
12
  from pathlib import Path
14
13
  from typing import TypedDict
@@ -1,6 +1,6 @@
1
1
  """CLI tools for Stravinsky."""
2
2
 
3
- from .session_report import main as session_report_main
4
3
  from .install_hooks import main as install_hooks_main
4
+ from .session_report import main as session_report_main
5
5
 
6
6
  __all__ = ["session_report_main", "install_hooks_main"]