shotgun-sh 0.2.3.dev2__py3-none-any.whl → 0.2.4.dev1__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 shotgun-sh might be problematic. Click here for more details.

@@ -256,9 +256,16 @@ class ConfigManager:
256
256
  config = self.load()
257
257
 
258
258
  # Get provider config (shotgun or LLM provider)
259
- provider_config, _ = self._get_provider_config_and_type(config, provider)
259
+ provider_config, is_shotgun = self._get_provider_config_and_type(
260
+ config, provider
261
+ )
260
262
 
261
263
  provider_config.api_key = None
264
+
265
+ # For Shotgun Account, also clear the JWT
266
+ if is_shotgun and isinstance(provider_config, ShotgunAccountConfig):
267
+ provider_config.supabase_jwt = None
268
+
262
269
  self.save(config)
263
270
 
264
271
  def update_selected_model(self, model_name: "ModelName") -> None:
@@ -10,7 +10,10 @@ from pydantic_ai.providers.google import GoogleProvider
10
10
  from pydantic_ai.providers.openai import OpenAIProvider
11
11
  from pydantic_ai.settings import ModelSettings
12
12
 
13
- from shotgun.llm_proxy import create_litellm_provider
13
+ from shotgun.llm_proxy import (
14
+ create_anthropic_proxy_provider,
15
+ create_litellm_provider,
16
+ )
14
17
  from shotgun.logging_config import get_logger
15
18
 
16
19
  from .manager import get_config_manager
@@ -72,19 +75,37 @@ def get_or_create_model(
72
75
 
73
76
  # Use LiteLLM proxy for Shotgun Account, native providers for BYOK
74
77
  if key_provider == KeyProvider.SHOTGUN:
75
- # Shotgun Account uses LiteLLM proxy for any model
78
+ # Shotgun Account uses LiteLLM proxy with native model types where possible
76
79
  if model_name in MODEL_SPECS:
77
80
  litellm_model_name = MODEL_SPECS[model_name].litellm_proxy_model_name
78
81
  else:
79
82
  # Fallback for unmapped models
80
83
  litellm_model_name = f"openai/{model_name.value}"
81
84
 
82
- litellm_provider = create_litellm_provider(api_key)
83
- _model_cache[cache_key] = OpenAIChatModel(
84
- litellm_model_name,
85
- provider=litellm_provider,
86
- settings=ModelSettings(max_tokens=max_tokens),
87
- )
85
+ # Use native provider types to preserve API formats and features
86
+ if provider == ProviderType.ANTHROPIC:
87
+ # Anthropic: Use native AnthropicProvider with /anthropic endpoint
88
+ # This preserves Anthropic-specific features like tool_choice
89
+ # Note: Web search for Shotgun Account uses Gemini only (not Anthropic)
90
+ # Note: Anthropic API expects model name without prefix (e.g., "claude-sonnet-4-5")
91
+ anthropic_provider = create_anthropic_proxy_provider(api_key)
92
+ _model_cache[cache_key] = AnthropicModel(
93
+ model_name.value, # Use model name without "anthropic/" prefix
94
+ provider=anthropic_provider,
95
+ settings=AnthropicModelSettings(
96
+ max_tokens=max_tokens,
97
+ timeout=600, # 10 minutes timeout for large responses
98
+ ),
99
+ )
100
+ else:
101
+ # OpenAI and Google: Use LiteLLMProvider (OpenAI-compatible format)
102
+ # Google's GoogleProvider doesn't support base_url, so use LiteLLM
103
+ litellm_provider = create_litellm_provider(api_key)
104
+ _model_cache[cache_key] = OpenAIChatModel(
105
+ litellm_model_name,
106
+ provider=litellm_provider,
107
+ settings=ModelSettings(max_tokens=max_tokens),
108
+ )
88
109
  elif key_provider == KeyProvider.BYOK:
89
110
  # Use native provider implementations with user's API keys
90
111
  if provider == ProviderType.OPENAI:
@@ -145,13 +166,19 @@ def get_provider_model(
145
166
  # Priority 1: Check if Shotgun key exists - if so, use it for ANY model
146
167
  shotgun_api_key = _get_api_key(config.shotgun.api_key)
147
168
  if shotgun_api_key:
148
- # Use selected model or default to claude-sonnet-4-5
149
- model_name = config.selected_model or ModelName.CLAUDE_SONNET_4_5
169
+ # Determine which model to use
170
+ if isinstance(provider_or_model, ModelName):
171
+ # Specific model requested - honor it (e.g., web search tools)
172
+ model_name = provider_or_model
173
+ else:
174
+ # No specific model requested - use selected or default
175
+ model_name = config.selected_model or ModelName.CLAUDE_SONNET_4_5
176
+
150
177
  if model_name not in MODEL_SPECS:
151
178
  raise ValueError(f"Model '{model_name.value}' not found")
152
179
  spec = MODEL_SPECS[model_name]
153
180
 
154
- # Use Shotgun Account with selected model (provider = actual LLM provider)
181
+ # Use Shotgun Account with determined model (provider = actual LLM provider)
155
182
  return ModelConfig(
156
183
  name=spec.name,
157
184
  provider=spec.provider, # Actual LLM provider (OPENAI/ANTHROPIC/GOOGLE)
@@ -3,7 +3,7 @@
3
3
  from pydantic_ai.messages import ModelMessage
4
4
 
5
5
  from shotgun.agents.config.models import KeyProvider
6
- from shotgun.llm_proxy import create_anthropic_proxy_client
6
+ from shotgun.llm_proxy import create_anthropic_proxy_provider
7
7
  from shotgun.logging_config import get_logger
8
8
 
9
9
  from .base import TokenCounter, extract_text_from_messages
@@ -36,19 +36,20 @@ class AnthropicTokenCounter(TokenCounter):
36
36
  try:
37
37
  if key_provider == KeyProvider.SHOTGUN:
38
38
  # Use LiteLLM proxy for Shotgun Account
39
- # Proxies to Anthropic's token counting API
40
- self.client = create_anthropic_proxy_client(api_key)
39
+ # Get async client from AnthropicProvider
40
+ provider = create_anthropic_proxy_provider(api_key)
41
+ self.client = provider.client
41
42
  logger.debug(
42
- f"Initialized Anthropic token counter for {model_name} via LiteLLM proxy"
43
+ f"Initialized async Anthropic token counter for {model_name} via LiteLLM proxy"
43
44
  )
44
45
  else:
45
- # Direct Anthropic API for BYOK
46
- self.client = anthropic.Anthropic(api_key=api_key)
46
+ # Direct Anthropic API for BYOK - use async client
47
+ self.client = anthropic.AsyncAnthropic(api_key=api_key)
47
48
  logger.debug(
48
- f"Initialized Anthropic token counter for {model_name} via direct API"
49
+ f"Initialized async Anthropic token counter for {model_name} via direct API"
49
50
  )
50
51
  except Exception as e:
51
- raise RuntimeError("Failed to initialize Anthropic client") from e
52
+ raise RuntimeError("Failed to initialize Anthropic async client") from e
52
53
 
53
54
  async def count_tokens(self, text: str) -> int:
54
55
  """Count tokens using Anthropic's official API (async).
@@ -64,7 +65,8 @@ class AnthropicTokenCounter(TokenCounter):
64
65
  """
65
66
  try:
66
67
  # Anthropic API expects messages format and model parameter
67
- result = self.client.messages.count_tokens(
68
+ # Use await with async client
69
+ result = await self.client.messages.count_tokens(
68
70
  messages=[{"role": "user", "content": text}], model=self.model_name
69
71
  )
70
72
  return result.input_tokens
@@ -3,7 +3,10 @@
3
3
  Provides web search capabilities for multiple LLM providers:
4
4
  - OpenAI: Uses Responses API with web_search tool (BYOK only)
5
5
  - Anthropic: Uses Messages API with web_search_20250305 tool (BYOK only)
6
- - Gemini: Uses grounding with Google Search via Pydantic AI (works with Shotgun Account)
6
+ - Gemini: Uses grounding with Google Search via Pydantic AI (Shotgun Account and BYOK)
7
+
8
+ Shotgun Account: Only Gemini web search is available
9
+ BYOK: All tools work with direct provider API keys
7
10
  """
8
11
 
9
12
  from collections.abc import Awaitable, Callable
@@ -26,11 +29,12 @@ WebSearchTool = Callable[[str], Awaitable[str]]
26
29
  def get_available_web_search_tools() -> list[WebSearchTool]:
27
30
  """Get list of available web search tools based on configured API keys.
28
31
 
29
- When using Shotgun Account (via LiteLLM proxy):
30
- Only Gemini web search is available (others use provider-specific APIs)
32
+ Works with both Shotgun Account (via LiteLLM proxy) and BYOK (individual provider keys).
31
33
 
32
- When using BYOK (individual provider keys):
33
- All provider tools are available based on their respective keys
34
+ Available tools:
35
+ - Gemini: Available for both Shotgun Account and BYOK
36
+ - Anthropic: BYOK only (uses Messages API with web search)
37
+ - OpenAI: BYOK only (uses Responses API not compatible with LiteLLM proxy)
34
38
 
35
39
  Returns:
36
40
  List of web search tool functions that have API keys configured
@@ -43,15 +47,23 @@ def get_available_web_search_tools() -> list[WebSearchTool]:
43
47
  has_shotgun_key = config.shotgun.api_key is not None
44
48
 
45
49
  if has_shotgun_key:
46
- # Shotgun Account mode: Only Gemini supports web search via LiteLLM
50
+ logger.debug("🔑 Shotgun Account - only Gemini web search available")
51
+
52
+ # Gemini: Only search tool available for Shotgun Account
47
53
  if is_provider_available(ProviderType.GOOGLE):
48
- logger.info("🔑 Shotgun Account detected - using Gemini web search only")
49
- logger.debug(" OpenAI and Anthropic web search require direct API keys")
54
+ logger.debug(" Gemini web search tool available")
50
55
  tools.append(gemini_web_search_tool)
51
- else:
52
- logger.warning(
53
- "⚠️ Shotgun Account configured but no Gemini key - "
54
- "web search unavailable"
56
+
57
+ # Anthropic: Not available for Shotgun Account (Gemini-only for Shotgun)
58
+ if is_provider_available(ProviderType.ANTHROPIC):
59
+ logger.debug(
60
+ "⚠️ Anthropic web search requires BYOK (Shotgun Account uses Gemini only)"
61
+ )
62
+
63
+ # OpenAI: Not available for Shotgun Account (Responses API incompatible with proxy)
64
+ if is_provider_available(ProviderType.OPENAI):
65
+ logger.debug(
66
+ "⚠️ OpenAI web search requires BYOK (Responses API not supported via proxy)"
55
67
  )
56
68
  else:
57
69
  # BYOK mode: Load all available tools based on individual provider keys
@@ -1,6 +1,9 @@
1
1
  """LiteLLM proxy client utilities and configuration."""
2
2
 
3
- from .clients import create_anthropic_proxy_client, create_litellm_provider
3
+ from .clients import (
4
+ create_anthropic_proxy_provider,
5
+ create_litellm_provider,
6
+ )
4
7
  from .constants import (
5
8
  LITELLM_PROXY_ANTHROPIC_BASE,
6
9
  LITELLM_PROXY_BASE_URL,
@@ -12,5 +15,5 @@ __all__ = [
12
15
  "LITELLM_PROXY_ANTHROPIC_BASE",
13
16
  "LITELLM_PROXY_OPENAI_BASE",
14
17
  "create_litellm_provider",
15
- "create_anthropic_proxy_client",
18
+ "create_anthropic_proxy_provider",
16
19
  ]
@@ -1,6 +1,6 @@
1
1
  """Client creation utilities for LiteLLM proxy."""
2
2
 
3
- from anthropic import Anthropic
3
+ from pydantic_ai.providers.anthropic import AnthropicProvider
4
4
  from pydantic_ai.providers.litellm import LiteLLMProvider
5
5
 
6
6
  from .constants import LITELLM_PROXY_ANTHROPIC_BASE, LITELLM_PROXY_BASE_URL
@@ -21,19 +21,24 @@ def create_litellm_provider(api_key: str) -> LiteLLMProvider:
21
21
  )
22
22
 
23
23
 
24
- def create_anthropic_proxy_client(api_key: str) -> Anthropic:
25
- """Create Anthropic client configured for LiteLLM proxy.
24
+ def create_anthropic_proxy_provider(api_key: str) -> AnthropicProvider:
25
+ """Create Anthropic provider configured for LiteLLM proxy.
26
26
 
27
- This client will proxy token counting requests through the
28
- LiteLLM proxy to Anthropic's actual token counting API.
27
+ This provider uses native Anthropic API format while routing through
28
+ the LiteLLM proxy. This preserves Anthropic-specific features like
29
+ tool_choice and web search.
30
+
31
+ The provider's .client attribute provides access to the async Anthropic
32
+ client (AsyncAnthropic), which should be used for all API operations
33
+ including token counting.
29
34
 
30
35
  Args:
31
36
  api_key: Shotgun API key
32
37
 
33
38
  Returns:
34
- Anthropic client configured to use LiteLLM proxy
39
+ AnthropicProvider configured to use LiteLLM proxy /anthropic endpoint
35
40
  """
36
- return Anthropic(
41
+ return AnthropicProvider(
37
42
  api_key=api_key,
38
43
  base_url=LITELLM_PROXY_ANTHROPIC_BASE,
39
44
  )
@@ -136,6 +136,12 @@ class WelcomeScreen(Screen[None]):
136
136
 
137
137
  def on_mount(self) -> None:
138
138
  """Focus the first button on mount."""
139
+ # Update BYOK button text based on whether user has existing providers
140
+ byok_button = self.query_one("#byok-button", Button)
141
+ app = cast("ShotgunApp", self.app)
142
+ if app.config_manager.has_any_provider_key():
143
+ byok_button.label = "I'll stick with my BYOK setup"
144
+
139
145
  self.query_one("#shotgun-button", Button).focus()
140
146
 
141
147
  @on(Button.Pressed, "#shotgun-button")
@@ -147,13 +153,18 @@ class WelcomeScreen(Screen[None]):
147
153
  def _on_byok_pressed(self) -> None:
148
154
  """Handle BYOK button press."""
149
155
  self._mark_welcome_shown()
150
- # Push provider config screen before dismissing
156
+
157
+ app = cast("ShotgunApp", self.app)
158
+
159
+ # If user already has providers, just dismiss and continue to chat
160
+ if app.config_manager.has_any_provider_key():
161
+ self.dismiss()
162
+ return
163
+
164
+ # Otherwise, push provider config screen
151
165
  from .provider_config import ProviderConfigScreen
152
166
 
153
- self.app.push_screen(
154
- ProviderConfigScreen(),
155
- callback=lambda _arg: self.dismiss(),
156
- )
167
+ self.app.push_screen(ProviderConfigScreen())
157
168
 
158
169
  async def _start_shotgun_auth(self) -> None:
159
170
  """Launch Shotgun Account authentication flow."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shotgun-sh
3
- Version: 0.2.3.dev2
3
+ Version: 0.2.4.dev1
4
4
  Summary: AI-powered research, planning, and task management CLI tool
5
5
  Project-URL: Homepage, https://shotgun.sh/
6
6
  Project-URL: Repository, https://github.com/shotgun-sh/shotgun
@@ -23,9 +23,9 @@ shotgun/agents/tasks.py,sha256=nk8zIl24o01hfzOGyWSbeVWeke6OGseO4Ppciurh13U,2999
23
23
  shotgun/agents/usage_manager.py,sha256=5d9JC4_cthXwhTSytMfMExMDAUYp8_nkPepTJZXk13w,5017
24
24
  shotgun/agents/config/__init__.py,sha256=Fl8K_81zBpm-OfOW27M_WWLSFdaHHek6lWz95iDREjQ,318
25
25
  shotgun/agents/config/constants.py,sha256=JNuLpeBUKikEsxGSjwX3RVWUQpbCKnDKstF2NczuDqk,932
26
- shotgun/agents/config/manager.py,sha256=TeGl8n-gFLtphCjoGEma4Ej4JyltWXOJj-okYLi_INk,18491
26
+ shotgun/agents/config/manager.py,sha256=AR3ENgt9zsJSyswOzc8XrnNIiMuq5hCbjU4n6S2ud4I,18699
27
27
  shotgun/agents/config/models.py,sha256=ohLXt9niCy4uFfFP1E6WSBZtxh7aZ16gTA2S3pHYkmc,5431
28
- shotgun/agents/config/provider.py,sha256=TwwZC_BtYSOpN2jdX6WZdor29EnAqfMoQK5GmNEYaPI,11012
28
+ shotgun/agents/config/provider.py,sha256=K2uW7DkdAhZfoDJcWV7NxOrSoEq1rQzArtZnxIgEe3E,12496
29
29
  shotgun/agents/history/__init__.py,sha256=XFQj2a6fxDqVg0Q3juvN9RjV_RJbgvFZtQOCOjVJyp4,147
30
30
  shotgun/agents/history/compaction.py,sha256=9RMpG0aY_7L4TecbgwHSOkGtbd9W5XZTg-MbzZmNl00,3515
31
31
  shotgun/agents/history/constants.py,sha256=yWY8rrTZarLA3flCCMB_hS2NMvUDRDTwP4D4j7MIh1w,446
@@ -35,7 +35,7 @@ shotgun/agents/history/history_processors.py,sha256=D3z-hzrXHxE7OAZaVX4_YAKN_nyx
35
35
  shotgun/agents/history/message_utils.py,sha256=aPusAl2RYKbjc7lBxPaNprRHmZEG6fe97q7DQUlhlzU,2918
36
36
  shotgun/agents/history/token_estimation.py,sha256=iRyKq-YDivEpJrULIbQgNpjhOuSC4nHVJYfsWEFV8sQ,4770
37
37
  shotgun/agents/history/token_counting/__init__.py,sha256=YZt5Lus--fkF6l1hdkIlp1e_oAIpACNwHOI0FRP4q8s,924
38
- shotgun/agents/history/token_counting/anthropic.py,sha256=b2LvwKM4dSILGhv_-W4mLMKMUCPLhe1ov9UGW_-iBsw,3011
38
+ shotgun/agents/history/token_counting/anthropic.py,sha256=fdRmm91od814mH1fSCv0WxmivEOy8xmcDIXJum1JaiE,3146
39
39
  shotgun/agents/history/token_counting/base.py,sha256=TN4mzwSyWNQyTuOuCFaU-8AgLdAyquoX3af4qrmkxCs,1904
40
40
  shotgun/agents/history/token_counting/openai.py,sha256=XJ2z2HaUG6f3Cw9tCK_yaOsaMJGHpSFF1I30-d3soSI,2350
41
41
  shotgun/agents/history/token_counting/sentencepiece_counter.py,sha256=qj1bT7J5nCd5y6Mr42O9K1KTaele0rjdd09FeyyEA70,3987
@@ -51,7 +51,7 @@ shotgun/agents/tools/codebase/file_read.py,sha256=EGK5yNqiS4cbIEQfDtdKVoJSJYk20N
51
51
  shotgun/agents/tools/codebase/models.py,sha256=8eR3_8DQiBNgB2twu0aC_evIJbugN9KW3gtxMZdGYCE,10087
52
52
  shotgun/agents/tools/codebase/query_graph.py,sha256=vOeyN4-OZj-vpTSk3Z9W5TjraZAepJ-Qjk_zzvum3fU,2115
53
53
  shotgun/agents/tools/codebase/retrieve_code.py,sha256=2VjiqVKJMd9rPV-mGrL4C-N8fqGjYLW6ZInFGbcTxOM,2878
54
- shotgun/agents/tools/web_search/__init__.py,sha256=_9rgs_gv41-wfPvwfWM_Qfq-zvboyQ_srfyneGsxgM4,3182
54
+ shotgun/agents/tools/web_search/__init__.py,sha256=166SzGDspEqRoHvAoguoy02WAT5EQfozoc5Ha5VubdY,3699
55
55
  shotgun/agents/tools/web_search/anthropic.py,sha256=GelAhAmb-b4o87-3sgxNFfw-G2LXDEjfdZ7XfF0bQD0,4983
56
56
  shotgun/agents/tools/web_search/gemini.py,sha256=-fI_deaBT4-_61A7KlKtz8tmKXW50fVx_97WAJTUg4w,3468
57
57
  shotgun/agents/tools/web_search/openai.py,sha256=pnIcTV3vwXJQuxPs4I7gQNX18XzM7D7FqeNxnn1E7yw,3437
@@ -82,8 +82,8 @@ shotgun/codebase/core/language_config.py,sha256=vsqHyuFnumRPRBV1lMOxWKNOIiClO6Fy
82
82
  shotgun/codebase/core/manager.py,sha256=kjxQ9eCs5vVCVDproCN1eYSKuGiqtcxF01reQ18JfOw,66184
83
83
  shotgun/codebase/core/nl_query.py,sha256=kPoSJXBlm5rLhzOofZhqPVMJ_Lj3rV2H6sld6BwtMdg,16115
84
84
  shotgun/codebase/core/parser_loader.py,sha256=LZRrDS8Sp518jIu3tQW-BxdwJ86lnsTteI478ER9Td8,4278
85
- shotgun/llm_proxy/__init__.py,sha256=BLD9NnVzdD0H7gFb65Ajud-Q7SiCymegLRaGx8UkC-Y,435
86
- shotgun/llm_proxy/clients.py,sha256=wP4UlgtCdrNwWsZLZ9inE3fEIDa-i1j7gsr9oXQf1o4,1037
85
+ shotgun/llm_proxy/__init__.py,sha256=3ST3ygtf2sXXSOjIFHxVZ5xqRbT3TF7jpNHwuZAtIwA,452
86
+ shotgun/llm_proxy/clients.py,sha256=Y19W8Gb2e-37w8rUKPmxJOqoTk6GlcPhZhoeAbbURU0,1341
87
87
  shotgun/llm_proxy/constants.py,sha256=_4piKdyvM7pAIRdAGrzYexwWoDlueUZiEMfwWrOa4T0,381
88
88
  shotgun/prompts/__init__.py,sha256=RswUm0HMdfm2m2YKUwUsEdRIwoczdbI7zlucoEvHYRo,132
89
89
  shotgun/prompts/loader.py,sha256=jy24-E02pCSmz2651aCT2NgHfRrHAGMYvKrD6gs0Er8,4424
@@ -135,7 +135,7 @@ shotgun/tui/screens/model_picker.py,sha256=G-EvalpxgHKk0W3FgHMcxIr817VwZyEgh_Zad
135
135
  shotgun/tui/screens/provider_config.py,sha256=UCnAzjXPoP7Y73gsXxZF2PNA4LdSgpgoGYwiOd6fERA,10902
136
136
  shotgun/tui/screens/shotgun_auth.py,sha256=Y--7LZewV6gfDkucxymfAO7BCd7eI2C3H1ClDMztVio,10663
137
137
  shotgun/tui/screens/splash.py,sha256=E2MsJihi3c9NY1L28o_MstDxGwrCnnV7zdq00MrGAsw,706
138
- shotgun/tui/screens/welcome.py,sha256=cpsBK2Gy99Nz7rwZhxVn310G68TjSdGXpIXGRp7DoLY,5329
138
+ shotgun/tui/screens/welcome.py,sha256=r-RjtzjMhAaA0XKgnYKdZOuE07bcBi223fleKEf-Faw,5772
139
139
  shotgun/tui/screens/chat_screen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
140
140
  shotgun/tui/screens/chat_screen/command_providers.py,sha256=7Xnxd4k30bpLOMZSX32bcugU4IgpqU4Y8f6eHWKXd4o,12694
141
141
  shotgun/tui/screens/chat_screen/hint_message.py,sha256=WOpbk8q7qt7eOHTyyHvh_IQIaublVDeJGaLpsxEk9FA,933
@@ -147,8 +147,8 @@ shotgun/utils/env_utils.py,sha256=ulM3BRi9ZhS7uC-zorGeDQm4SHvsyFuuU9BtVPqdrHY,14
147
147
  shotgun/utils/file_system_utils.py,sha256=l-0p1bEHF34OU19MahnRFdClHufThfGAjQ431teAIp0,1004
148
148
  shotgun/utils/source_detection.py,sha256=Co6Q03R3fT771TF3RzB-70stfjNP2S4F_ArZKibwzm8,454
149
149
  shotgun/utils/update_checker.py,sha256=IgzPHRhS1ETH7PnJR_dIx6lxgr1qHpCkMTgzUxvGjhI,7586
150
- shotgun_sh-0.2.3.dev2.dist-info/METADATA,sha256=83cmMLDU0Zfx2TiRiX6cbJ6goC6i9cP6YmxvKI5hdzE,11226
151
- shotgun_sh-0.2.3.dev2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
152
- shotgun_sh-0.2.3.dev2.dist-info/entry_points.txt,sha256=asZxLU4QILneq0MWW10saVCZc4VWhZfb0wFZvERnzfA,45
153
- shotgun_sh-0.2.3.dev2.dist-info/licenses/LICENSE,sha256=YebsZl590zCHrF_acCU5pmNt0pnAfD2DmAnevJPB1tY,1065
154
- shotgun_sh-0.2.3.dev2.dist-info/RECORD,,
150
+ shotgun_sh-0.2.4.dev1.dist-info/METADATA,sha256=R13OhYSbeSg9EqpiXR5o2s8MQr2uflp44Adqwnn8hxc,11226
151
+ shotgun_sh-0.2.4.dev1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
152
+ shotgun_sh-0.2.4.dev1.dist-info/entry_points.txt,sha256=asZxLU4QILneq0MWW10saVCZc4VWhZfb0wFZvERnzfA,45
153
+ shotgun_sh-0.2.4.dev1.dist-info/licenses/LICENSE,sha256=YebsZl590zCHrF_acCU5pmNt0pnAfD2DmAnevJPB1tY,1065
154
+ shotgun_sh-0.2.4.dev1.dist-info/RECORD,,