prompture 0.0.47.dev2__py3-none-any.whl → 0.0.47.dev3__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.
- prompture/_version.py +2 -2
- prompture/async_conversation.py +16 -0
- prompture/conversation.py +16 -0
- prompture/drivers/async_grok_driver.py +23 -9
- prompture/drivers/async_groq_driver.py +23 -9
- prompture/drivers/async_lmstudio_driver.py +10 -2
- prompture/drivers/async_moonshot_driver.py +20 -9
- prompture/drivers/async_openrouter_driver.py +43 -17
- prompture/drivers/grok_driver.py +23 -9
- prompture/drivers/groq_driver.py +23 -9
- prompture/drivers/lmstudio_driver.py +11 -2
- prompture/drivers/moonshot_driver.py +20 -9
- prompture/drivers/openrouter_driver.py +34 -10
- {prompture-0.0.47.dev2.dist-info → prompture-0.0.47.dev3.dist-info}/METADATA +1 -1
- {prompture-0.0.47.dev2.dist-info → prompture-0.0.47.dev3.dist-info}/RECORD +19 -19
- {prompture-0.0.47.dev2.dist-info → prompture-0.0.47.dev3.dist-info}/WHEEL +0 -0
- {prompture-0.0.47.dev2.dist-info → prompture-0.0.47.dev3.dist-info}/entry_points.txt +0 -0
- {prompture-0.0.47.dev2.dist-info → prompture-0.0.47.dev3.dist-info}/licenses/LICENSE +0 -0
- {prompture-0.0.47.dev2.dist-info → prompture-0.0.47.dev3.dist-info}/top_level.txt +0 -0
prompture/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.47.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0, 47, '
|
|
31
|
+
__version__ = version = '0.0.47.dev3'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 47, 'dev3')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
prompture/async_conversation.py
CHANGED
|
@@ -109,6 +109,9 @@ class AsyncConversation:
|
|
|
109
109
|
self._max_tool_rounds = max_tool_rounds
|
|
110
110
|
self._simulated_tools = simulated_tools
|
|
111
111
|
|
|
112
|
+
# Reasoning content from last response
|
|
113
|
+
self._last_reasoning: str | None = None
|
|
114
|
+
|
|
112
115
|
# Persistence
|
|
113
116
|
self._conversation_id = conversation_id or str(uuid.uuid4())
|
|
114
117
|
self._auto_save = Path(auto_save) if auto_save else None
|
|
@@ -121,6 +124,11 @@ class AsyncConversation:
|
|
|
121
124
|
# Public helpers
|
|
122
125
|
# ------------------------------------------------------------------
|
|
123
126
|
|
|
127
|
+
@property
|
|
128
|
+
def last_reasoning(self) -> str | None:
|
|
129
|
+
"""The reasoning/thinking content from the last LLM response, if any."""
|
|
130
|
+
return self._last_reasoning
|
|
131
|
+
|
|
124
132
|
@property
|
|
125
133
|
def messages(self) -> list[dict[str, Any]]:
|
|
126
134
|
"""Read-only view of the conversation history."""
|
|
@@ -326,6 +334,8 @@ class AsyncConversation:
|
|
|
326
334
|
If tools are registered and the driver supports tool use,
|
|
327
335
|
dispatches to the async tool execution loop.
|
|
328
336
|
"""
|
|
337
|
+
self._last_reasoning = None
|
|
338
|
+
|
|
329
339
|
# Route to appropriate tool handling
|
|
330
340
|
if self._tools:
|
|
331
341
|
use_native = getattr(self._driver, "supports_tool_use", False)
|
|
@@ -340,6 +350,7 @@ class AsyncConversation:
|
|
|
340
350
|
|
|
341
351
|
text = resp.get("text", "")
|
|
342
352
|
meta = resp.get("meta", {})
|
|
353
|
+
self._last_reasoning = resp.get("reasoning_content")
|
|
343
354
|
|
|
344
355
|
user_content = self._build_content_with_images(content, images)
|
|
345
356
|
self._messages.append({"role": "user", "content": user_content})
|
|
@@ -372,6 +383,7 @@ class AsyncConversation:
|
|
|
372
383
|
text = resp.get("text", "")
|
|
373
384
|
|
|
374
385
|
if not tool_calls:
|
|
386
|
+
self._last_reasoning = resp.get("reasoning_content")
|
|
375
387
|
self._messages.append({"role": "assistant", "content": text})
|
|
376
388
|
return text
|
|
377
389
|
|
|
@@ -526,6 +538,8 @@ class AsyncConversation:
|
|
|
526
538
|
images: list[ImageInput] | None = None,
|
|
527
539
|
) -> dict[str, Any]:
|
|
528
540
|
"""Send a message with schema enforcement and get structured JSON back (async)."""
|
|
541
|
+
self._last_reasoning = None
|
|
542
|
+
|
|
529
543
|
merged = {**self._options, **(options or {})}
|
|
530
544
|
|
|
531
545
|
schema_string = json.dumps(json_schema, indent=2)
|
|
@@ -563,6 +577,7 @@ class AsyncConversation:
|
|
|
563
577
|
|
|
564
578
|
text = resp.get("text", "")
|
|
565
579
|
meta = resp.get("meta", {})
|
|
580
|
+
self._last_reasoning = resp.get("reasoning_content")
|
|
566
581
|
|
|
567
582
|
user_content = self._build_content_with_images(content, images)
|
|
568
583
|
self._messages.append({"role": "user", "content": user_content})
|
|
@@ -597,6 +612,7 @@ class AsyncConversation:
|
|
|
597
612
|
"json_object": json_obj,
|
|
598
613
|
"usage": usage,
|
|
599
614
|
"output_format": output_format,
|
|
615
|
+
"reasoning": self._last_reasoning,
|
|
600
616
|
}
|
|
601
617
|
|
|
602
618
|
if output_format == "toon":
|
prompture/conversation.py
CHANGED
|
@@ -112,6 +112,9 @@ class Conversation:
|
|
|
112
112
|
self._max_tool_rounds = max_tool_rounds
|
|
113
113
|
self._simulated_tools = simulated_tools
|
|
114
114
|
|
|
115
|
+
# Reasoning content from last response
|
|
116
|
+
self._last_reasoning: str | None = None
|
|
117
|
+
|
|
115
118
|
# Persistence
|
|
116
119
|
self._conversation_id = conversation_id or str(uuid.uuid4())
|
|
117
120
|
self._auto_save = Path(auto_save) if auto_save else None
|
|
@@ -124,6 +127,11 @@ class Conversation:
|
|
|
124
127
|
# Public helpers
|
|
125
128
|
# ------------------------------------------------------------------
|
|
126
129
|
|
|
130
|
+
@property
|
|
131
|
+
def last_reasoning(self) -> str | None:
|
|
132
|
+
"""The reasoning/thinking content from the last LLM response, if any."""
|
|
133
|
+
return self._last_reasoning
|
|
134
|
+
|
|
127
135
|
@property
|
|
128
136
|
def messages(self) -> list[dict[str, Any]]:
|
|
129
137
|
"""Read-only view of the conversation history."""
|
|
@@ -340,6 +348,8 @@ class Conversation:
|
|
|
340
348
|
images: Optional list of images to include (bytes, path, URL,
|
|
341
349
|
base64 string, or :class:`ImageContent`).
|
|
342
350
|
"""
|
|
351
|
+
self._last_reasoning = None
|
|
352
|
+
|
|
343
353
|
# Route to appropriate tool handling
|
|
344
354
|
if self._tools:
|
|
345
355
|
use_native = getattr(self._driver, "supports_tool_use", False)
|
|
@@ -354,6 +364,7 @@ class Conversation:
|
|
|
354
364
|
|
|
355
365
|
text = resp.get("text", "")
|
|
356
366
|
meta = resp.get("meta", {})
|
|
367
|
+
self._last_reasoning = resp.get("reasoning_content")
|
|
357
368
|
|
|
358
369
|
# Record in history — store content with images for context
|
|
359
370
|
user_content = self._build_content_with_images(content, images)
|
|
@@ -389,6 +400,7 @@ class Conversation:
|
|
|
389
400
|
|
|
390
401
|
if not tool_calls:
|
|
391
402
|
# No tool calls -> final response
|
|
403
|
+
self._last_reasoning = resp.get("reasoning_content")
|
|
392
404
|
self._messages.append({"role": "assistant", "content": text})
|
|
393
405
|
return text
|
|
394
406
|
|
|
@@ -553,6 +565,8 @@ class Conversation:
|
|
|
553
565
|
context clean for subsequent turns.
|
|
554
566
|
"""
|
|
555
567
|
|
|
568
|
+
self._last_reasoning = None
|
|
569
|
+
|
|
556
570
|
merged = {**self._options, **(options or {})}
|
|
557
571
|
|
|
558
572
|
# Build the full prompt with schema instructions inline (handled by ask_for_json)
|
|
@@ -594,6 +608,7 @@ class Conversation:
|
|
|
594
608
|
|
|
595
609
|
text = resp.get("text", "")
|
|
596
610
|
meta = resp.get("meta", {})
|
|
611
|
+
self._last_reasoning = resp.get("reasoning_content")
|
|
597
612
|
|
|
598
613
|
# Store original content (without schema boilerplate) for cleaner context
|
|
599
614
|
# Include images in history so subsequent turns can reference them
|
|
@@ -632,6 +647,7 @@ class Conversation:
|
|
|
632
647
|
"json_object": json_obj,
|
|
633
648
|
"usage": usage,
|
|
634
649
|
"output_format": output_format,
|
|
650
|
+
"reasoning": self._last_reasoning,
|
|
635
651
|
}
|
|
636
652
|
|
|
637
653
|
if output_format == "toon":
|
|
@@ -95,8 +95,17 @@ class AsyncGrokDriver(CostMixin, AsyncDriver):
|
|
|
95
95
|
"model_name": model,
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
message = resp["choices"][0]["message"]
|
|
99
|
+
text = message.get("content") or ""
|
|
100
|
+
reasoning_content = message.get("reasoning_content")
|
|
101
|
+
|
|
102
|
+
if not text and reasoning_content:
|
|
103
|
+
text = reasoning_content
|
|
104
|
+
|
|
105
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
106
|
+
if reasoning_content is not None:
|
|
107
|
+
result["reasoning_content"] = reasoning_content
|
|
108
|
+
return result
|
|
100
109
|
|
|
101
110
|
# ------------------------------------------------------------------
|
|
102
111
|
# Tool use
|
|
@@ -173,15 +182,20 @@ class AsyncGrokDriver(CostMixin, AsyncDriver):
|
|
|
173
182
|
args = json.loads(tc["function"]["arguments"])
|
|
174
183
|
except (json.JSONDecodeError, TypeError):
|
|
175
184
|
args = {}
|
|
176
|
-
tool_calls_out.append(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
185
|
+
tool_calls_out.append(
|
|
186
|
+
{
|
|
187
|
+
"id": tc["id"],
|
|
188
|
+
"name": tc["function"]["name"],
|
|
189
|
+
"arguments": args,
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
result: dict[str, Any] = {
|
|
183
194
|
"text": text,
|
|
184
195
|
"meta": meta,
|
|
185
196
|
"tool_calls": tool_calls_out,
|
|
186
197
|
"stop_reason": stop_reason,
|
|
187
198
|
}
|
|
199
|
+
if choice["message"].get("reasoning_content") is not None:
|
|
200
|
+
result["reasoning_content"] = choice["message"]["reasoning_content"]
|
|
201
|
+
return result
|
|
@@ -88,8 +88,16 @@ class AsyncGroqDriver(CostMixin, AsyncDriver):
|
|
|
88
88
|
"model_name": model,
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
text = resp.choices[0].message.content
|
|
92
|
-
|
|
91
|
+
text = resp.choices[0].message.content or ""
|
|
92
|
+
reasoning_content = getattr(resp.choices[0].message, "reasoning_content", None)
|
|
93
|
+
|
|
94
|
+
if not text and reasoning_content:
|
|
95
|
+
text = reasoning_content
|
|
96
|
+
|
|
97
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
98
|
+
if reasoning_content is not None:
|
|
99
|
+
result["reasoning_content"] = reasoning_content
|
|
100
|
+
return result
|
|
93
101
|
|
|
94
102
|
# ------------------------------------------------------------------
|
|
95
103
|
# Tool use
|
|
@@ -152,15 +160,21 @@ class AsyncGroqDriver(CostMixin, AsyncDriver):
|
|
|
152
160
|
args = json.loads(tc.function.arguments)
|
|
153
161
|
except (json.JSONDecodeError, TypeError):
|
|
154
162
|
args = {}
|
|
155
|
-
tool_calls_out.append(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
163
|
+
tool_calls_out.append(
|
|
164
|
+
{
|
|
165
|
+
"id": tc.id,
|
|
166
|
+
"name": tc.function.name,
|
|
167
|
+
"arguments": args,
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
result: dict[str, Any] = {
|
|
162
172
|
"text": text,
|
|
163
173
|
"meta": meta,
|
|
164
174
|
"tool_calls": tool_calls_out,
|
|
165
175
|
"stop_reason": stop_reason,
|
|
166
176
|
}
|
|
177
|
+
reasoning_content = getattr(choice.message, "reasoning_content", None)
|
|
178
|
+
if reasoning_content is not None:
|
|
179
|
+
result["reasoning_content"] = reasoning_content
|
|
180
|
+
return result
|
|
@@ -98,7 +98,12 @@ class AsyncLMStudioDriver(AsyncDriver):
|
|
|
98
98
|
if "choices" not in response_data or not response_data["choices"]:
|
|
99
99
|
raise ValueError(f"Unexpected response format: {response_data}")
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
message = response_data["choices"][0]["message"]
|
|
102
|
+
text = message.get("content") or ""
|
|
103
|
+
reasoning_content = message.get("reasoning_content")
|
|
104
|
+
|
|
105
|
+
if not text and reasoning_content:
|
|
106
|
+
text = reasoning_content
|
|
102
107
|
|
|
103
108
|
usage = response_data.get("usage", {})
|
|
104
109
|
prompt_tokens = usage.get("prompt_tokens", 0)
|
|
@@ -114,7 +119,10 @@ class AsyncLMStudioDriver(AsyncDriver):
|
|
|
114
119
|
"model_name": merged_options.get("model", self.model),
|
|
115
120
|
}
|
|
116
121
|
|
|
117
|
-
|
|
122
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
123
|
+
if reasoning_content is not None:
|
|
124
|
+
result["reasoning_content"] = reasoning_content
|
|
125
|
+
return result
|
|
118
126
|
|
|
119
127
|
# -- Model management (LM Studio 0.4.0+) ----------------------------------
|
|
120
128
|
|
|
@@ -138,10 +138,11 @@ class AsyncMoonshotDriver(CostMixin, AsyncDriver):
|
|
|
138
138
|
|
|
139
139
|
message = resp["choices"][0]["message"]
|
|
140
140
|
text = message.get("content") or ""
|
|
141
|
+
reasoning_content = message.get("reasoning_content")
|
|
141
142
|
|
|
142
143
|
# Reasoning models may return content in reasoning_content when content is empty
|
|
143
|
-
if not text and
|
|
144
|
-
text =
|
|
144
|
+
if not text and reasoning_content:
|
|
145
|
+
text = reasoning_content
|
|
145
146
|
|
|
146
147
|
# Structured output fallback: if we used json_schema mode and got an
|
|
147
148
|
# empty response, retry with json_object mode and schema in the prompt.
|
|
@@ -184,8 +185,9 @@ class AsyncMoonshotDriver(CostMixin, AsyncDriver):
|
|
|
184
185
|
resp = fb_resp
|
|
185
186
|
fb_message = fb_resp["choices"][0]["message"]
|
|
186
187
|
text = fb_message.get("content") or ""
|
|
187
|
-
|
|
188
|
-
|
|
188
|
+
reasoning_content = fb_message.get("reasoning_content")
|
|
189
|
+
if not text and reasoning_content:
|
|
190
|
+
text = reasoning_content
|
|
189
191
|
|
|
190
192
|
total_cost = self._calculate_cost("moonshot", model, prompt_tokens, completion_tokens)
|
|
191
193
|
|
|
@@ -198,7 +200,10 @@ class AsyncMoonshotDriver(CostMixin, AsyncDriver):
|
|
|
198
200
|
"model_name": model,
|
|
199
201
|
}
|
|
200
202
|
|
|
201
|
-
|
|
203
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
204
|
+
if reasoning_content is not None:
|
|
205
|
+
result["reasoning_content"] = reasoning_content
|
|
206
|
+
return result
|
|
202
207
|
|
|
203
208
|
# ------------------------------------------------------------------
|
|
204
209
|
# Tool use
|
|
@@ -334,6 +339,7 @@ class AsyncMoonshotDriver(CostMixin, AsyncDriver):
|
|
|
334
339
|
data["temperature"] = opts["temperature"]
|
|
335
340
|
|
|
336
341
|
full_text = ""
|
|
342
|
+
full_reasoning = ""
|
|
337
343
|
prompt_tokens = 0
|
|
338
344
|
completion_tokens = 0
|
|
339
345
|
|
|
@@ -368,9 +374,11 @@ class AsyncMoonshotDriver(CostMixin, AsyncDriver):
|
|
|
368
374
|
if choices:
|
|
369
375
|
delta = choices[0].get("delta", {})
|
|
370
376
|
content = delta.get("content") or ""
|
|
371
|
-
|
|
372
|
-
if
|
|
373
|
-
|
|
377
|
+
reasoning_chunk = delta.get("reasoning_content") or ""
|
|
378
|
+
if reasoning_chunk:
|
|
379
|
+
full_reasoning += reasoning_chunk
|
|
380
|
+
if not content and reasoning_chunk:
|
|
381
|
+
content = reasoning_chunk
|
|
374
382
|
if content:
|
|
375
383
|
full_text += content
|
|
376
384
|
yield {"type": "delta", "text": content}
|
|
@@ -378,7 +386,7 @@ class AsyncMoonshotDriver(CostMixin, AsyncDriver):
|
|
|
378
386
|
total_tokens = prompt_tokens + completion_tokens
|
|
379
387
|
total_cost = self._calculate_cost("moonshot", model, prompt_tokens, completion_tokens)
|
|
380
388
|
|
|
381
|
-
|
|
389
|
+
done_chunk: dict[str, Any] = {
|
|
382
390
|
"type": "done",
|
|
383
391
|
"text": full_text,
|
|
384
392
|
"meta": {
|
|
@@ -390,3 +398,6 @@ class AsyncMoonshotDriver(CostMixin, AsyncDriver):
|
|
|
390
398
|
"model_name": model,
|
|
391
399
|
},
|
|
392
400
|
}
|
|
401
|
+
if full_reasoning:
|
|
402
|
+
done_chunk["reasoning_content"] = full_reasoning
|
|
403
|
+
yield done_chunk
|
|
@@ -122,8 +122,17 @@ class AsyncOpenRouterDriver(CostMixin, AsyncDriver):
|
|
|
122
122
|
"model_name": model,
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
message = resp["choices"][0]["message"]
|
|
126
|
+
text = message.get("content") or ""
|
|
127
|
+
reasoning_content = message.get("reasoning_content")
|
|
128
|
+
|
|
129
|
+
if not text and reasoning_content:
|
|
130
|
+
text = reasoning_content
|
|
131
|
+
|
|
132
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
133
|
+
if reasoning_content is not None:
|
|
134
|
+
result["reasoning_content"] = reasoning_content
|
|
135
|
+
return result
|
|
127
136
|
|
|
128
137
|
# ------------------------------------------------------------------
|
|
129
138
|
# Tool use
|
|
@@ -196,18 +205,23 @@ class AsyncOpenRouterDriver(CostMixin, AsyncDriver):
|
|
|
196
205
|
args = json.loads(tc["function"]["arguments"])
|
|
197
206
|
except (json.JSONDecodeError, TypeError):
|
|
198
207
|
args = {}
|
|
199
|
-
tool_calls_out.append(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
tool_calls_out.append(
|
|
209
|
+
{
|
|
210
|
+
"id": tc["id"],
|
|
211
|
+
"name": tc["function"]["name"],
|
|
212
|
+
"arguments": args,
|
|
213
|
+
}
|
|
214
|
+
)
|
|
204
215
|
|
|
205
|
-
|
|
216
|
+
result: dict[str, Any] = {
|
|
206
217
|
"text": text,
|
|
207
218
|
"meta": meta,
|
|
208
219
|
"tool_calls": tool_calls_out,
|
|
209
220
|
"stop_reason": stop_reason,
|
|
210
221
|
}
|
|
222
|
+
if choice["message"].get("reasoning_content") is not None:
|
|
223
|
+
result["reasoning_content"] = choice["message"]["reasoning_content"]
|
|
224
|
+
return result
|
|
211
225
|
|
|
212
226
|
# ------------------------------------------------------------------
|
|
213
227
|
# Streaming
|
|
@@ -238,21 +252,25 @@ class AsyncOpenRouterDriver(CostMixin, AsyncDriver):
|
|
|
238
252
|
data["temperature"] = opts["temperature"]
|
|
239
253
|
|
|
240
254
|
full_text = ""
|
|
255
|
+
full_reasoning = ""
|
|
241
256
|
prompt_tokens = 0
|
|
242
257
|
completion_tokens = 0
|
|
243
258
|
|
|
244
|
-
async with
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
259
|
+
async with (
|
|
260
|
+
httpx.AsyncClient() as client,
|
|
261
|
+
client.stream(
|
|
262
|
+
"POST",
|
|
263
|
+
f"{self.base_url}/chat/completions",
|
|
264
|
+
headers=self.headers,
|
|
265
|
+
json=data,
|
|
266
|
+
timeout=120,
|
|
267
|
+
) as response,
|
|
268
|
+
):
|
|
251
269
|
response.raise_for_status()
|
|
252
270
|
async for line in response.aiter_lines():
|
|
253
271
|
if not line or not line.startswith("data: "):
|
|
254
272
|
continue
|
|
255
|
-
payload = line[len("data: "):]
|
|
273
|
+
payload = line[len("data: ") :]
|
|
256
274
|
if payload.strip() == "[DONE]":
|
|
257
275
|
break
|
|
258
276
|
try:
|
|
@@ -270,6 +288,11 @@ class AsyncOpenRouterDriver(CostMixin, AsyncDriver):
|
|
|
270
288
|
if choices:
|
|
271
289
|
delta = choices[0].get("delta", {})
|
|
272
290
|
content = delta.get("content", "")
|
|
291
|
+
reasoning_chunk = delta.get("reasoning_content") or ""
|
|
292
|
+
if reasoning_chunk:
|
|
293
|
+
full_reasoning += reasoning_chunk
|
|
294
|
+
if not content and reasoning_chunk:
|
|
295
|
+
content = reasoning_chunk
|
|
273
296
|
if content:
|
|
274
297
|
full_text += content
|
|
275
298
|
yield {"type": "delta", "text": content}
|
|
@@ -277,7 +300,7 @@ class AsyncOpenRouterDriver(CostMixin, AsyncDriver):
|
|
|
277
300
|
total_tokens = prompt_tokens + completion_tokens
|
|
278
301
|
total_cost = self._calculate_cost("openrouter", model, prompt_tokens, completion_tokens)
|
|
279
302
|
|
|
280
|
-
|
|
303
|
+
done_chunk: dict[str, Any] = {
|
|
281
304
|
"type": "done",
|
|
282
305
|
"text": full_text,
|
|
283
306
|
"meta": {
|
|
@@ -289,3 +312,6 @@ class AsyncOpenRouterDriver(CostMixin, AsyncDriver):
|
|
|
289
312
|
"model_name": model,
|
|
290
313
|
},
|
|
291
314
|
}
|
|
315
|
+
if full_reasoning:
|
|
316
|
+
done_chunk["reasoning_content"] = full_reasoning
|
|
317
|
+
yield done_chunk
|
prompture/drivers/grok_driver.py
CHANGED
|
@@ -154,8 +154,17 @@ class GrokDriver(CostMixin, Driver):
|
|
|
154
154
|
"model_name": model,
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
message = resp["choices"][0]["message"]
|
|
158
|
+
text = message.get("content") or ""
|
|
159
|
+
reasoning_content = message.get("reasoning_content")
|
|
160
|
+
|
|
161
|
+
if not text and reasoning_content:
|
|
162
|
+
text = reasoning_content
|
|
163
|
+
|
|
164
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
165
|
+
if reasoning_content is not None:
|
|
166
|
+
result["reasoning_content"] = reasoning_content
|
|
167
|
+
return result
|
|
159
168
|
|
|
160
169
|
# ------------------------------------------------------------------
|
|
161
170
|
# Tool use
|
|
@@ -227,15 +236,20 @@ class GrokDriver(CostMixin, Driver):
|
|
|
227
236
|
args = json.loads(tc["function"]["arguments"])
|
|
228
237
|
except (json.JSONDecodeError, TypeError):
|
|
229
238
|
args = {}
|
|
230
|
-
tool_calls_out.append(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
239
|
+
tool_calls_out.append(
|
|
240
|
+
{
|
|
241
|
+
"id": tc["id"],
|
|
242
|
+
"name": tc["function"]["name"],
|
|
243
|
+
"arguments": args,
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
result: dict[str, Any] = {
|
|
237
248
|
"text": text,
|
|
238
249
|
"meta": meta,
|
|
239
250
|
"tool_calls": tool_calls_out,
|
|
240
251
|
"stop_reason": stop_reason,
|
|
241
252
|
}
|
|
253
|
+
if choice["message"].get("reasoning_content") is not None:
|
|
254
|
+
result["reasoning_content"] = choice["message"]["reasoning_content"]
|
|
255
|
+
return result
|
prompture/drivers/groq_driver.py
CHANGED
|
@@ -122,8 +122,16 @@ class GroqDriver(CostMixin, Driver):
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
# Extract generated text
|
|
125
|
-
text = resp.choices[0].message.content
|
|
126
|
-
|
|
125
|
+
text = resp.choices[0].message.content or ""
|
|
126
|
+
reasoning_content = getattr(resp.choices[0].message, "reasoning_content", None)
|
|
127
|
+
|
|
128
|
+
if not text and reasoning_content:
|
|
129
|
+
text = reasoning_content
|
|
130
|
+
|
|
131
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
132
|
+
if reasoning_content is not None:
|
|
133
|
+
result["reasoning_content"] = reasoning_content
|
|
134
|
+
return result
|
|
127
135
|
|
|
128
136
|
# ------------------------------------------------------------------
|
|
129
137
|
# Tool use
|
|
@@ -186,15 +194,21 @@ class GroqDriver(CostMixin, Driver):
|
|
|
186
194
|
args = json.loads(tc.function.arguments)
|
|
187
195
|
except (json.JSONDecodeError, TypeError):
|
|
188
196
|
args = {}
|
|
189
|
-
tool_calls_out.append(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
tool_calls_out.append(
|
|
198
|
+
{
|
|
199
|
+
"id": tc.id,
|
|
200
|
+
"name": tc.function.name,
|
|
201
|
+
"arguments": args,
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
result: dict[str, Any] = {
|
|
196
206
|
"text": text,
|
|
197
207
|
"meta": meta,
|
|
198
208
|
"tool_calls": tool_calls_out,
|
|
199
209
|
"stop_reason": stop_reason,
|
|
200
210
|
}
|
|
211
|
+
reasoning_content = getattr(choice.message, "reasoning_content", None)
|
|
212
|
+
if reasoning_content is not None:
|
|
213
|
+
result["reasoning_content"] = reasoning_content
|
|
214
|
+
return result
|
|
@@ -123,7 +123,13 @@ class LMStudioDriver(Driver):
|
|
|
123
123
|
raise RuntimeError(f"LM Studio request failed: {e}") from e
|
|
124
124
|
|
|
125
125
|
# Extract text
|
|
126
|
-
|
|
126
|
+
message = response_data["choices"][0]["message"]
|
|
127
|
+
text = message.get("content") or ""
|
|
128
|
+
reasoning_content = message.get("reasoning_content")
|
|
129
|
+
|
|
130
|
+
# Reasoning models (e.g. DeepSeek R1) may return content in reasoning_content
|
|
131
|
+
if not text and reasoning_content:
|
|
132
|
+
text = reasoning_content
|
|
127
133
|
|
|
128
134
|
# Meta info
|
|
129
135
|
usage = response_data.get("usage", {})
|
|
@@ -140,7 +146,10 @@ class LMStudioDriver(Driver):
|
|
|
140
146
|
"model_name": merged_options.get("model", self.model),
|
|
141
147
|
}
|
|
142
148
|
|
|
143
|
-
|
|
149
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
150
|
+
if reasoning_content is not None:
|
|
151
|
+
result["reasoning_content"] = reasoning_content
|
|
152
|
+
return result
|
|
144
153
|
|
|
145
154
|
# -- Model management (LM Studio 0.4.0+) ----------------------------------
|
|
146
155
|
|
|
@@ -228,10 +228,11 @@ class MoonshotDriver(CostMixin, Driver):
|
|
|
228
228
|
|
|
229
229
|
message = resp["choices"][0]["message"]
|
|
230
230
|
text = message.get("content") or ""
|
|
231
|
+
reasoning_content = message.get("reasoning_content")
|
|
231
232
|
|
|
232
233
|
# Reasoning models may return content in reasoning_content when content is empty
|
|
233
|
-
if not text and
|
|
234
|
-
text =
|
|
234
|
+
if not text and reasoning_content:
|
|
235
|
+
text = reasoning_content
|
|
235
236
|
|
|
236
237
|
# Structured output fallback: if we used json_schema mode and got an
|
|
237
238
|
# empty response, retry with json_object mode and schema in the prompt.
|
|
@@ -275,8 +276,9 @@ class MoonshotDriver(CostMixin, Driver):
|
|
|
275
276
|
resp = fb_resp
|
|
276
277
|
fb_message = fb_resp["choices"][0]["message"]
|
|
277
278
|
text = fb_message.get("content") or ""
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
reasoning_content = fb_message.get("reasoning_content")
|
|
280
|
+
if not text and reasoning_content:
|
|
281
|
+
text = reasoning_content
|
|
280
282
|
|
|
281
283
|
total_cost = self._calculate_cost("moonshot", model, prompt_tokens, completion_tokens)
|
|
282
284
|
|
|
@@ -289,7 +291,10 @@ class MoonshotDriver(CostMixin, Driver):
|
|
|
289
291
|
"model_name": model,
|
|
290
292
|
}
|
|
291
293
|
|
|
292
|
-
|
|
294
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
295
|
+
if reasoning_content is not None:
|
|
296
|
+
result["reasoning_content"] = reasoning_content
|
|
297
|
+
return result
|
|
293
298
|
|
|
294
299
|
# ------------------------------------------------------------------
|
|
295
300
|
# Tool use
|
|
@@ -439,6 +444,7 @@ class MoonshotDriver(CostMixin, Driver):
|
|
|
439
444
|
response.raise_for_status()
|
|
440
445
|
|
|
441
446
|
full_text = ""
|
|
447
|
+
full_reasoning = ""
|
|
442
448
|
prompt_tokens = 0
|
|
443
449
|
completion_tokens = 0
|
|
444
450
|
|
|
@@ -462,9 +468,11 @@ class MoonshotDriver(CostMixin, Driver):
|
|
|
462
468
|
if choices:
|
|
463
469
|
delta = choices[0].get("delta", {})
|
|
464
470
|
content = delta.get("content") or ""
|
|
465
|
-
|
|
466
|
-
if
|
|
467
|
-
|
|
471
|
+
reasoning_chunk = delta.get("reasoning_content") or ""
|
|
472
|
+
if reasoning_chunk:
|
|
473
|
+
full_reasoning += reasoning_chunk
|
|
474
|
+
if not content and reasoning_chunk:
|
|
475
|
+
content = reasoning_chunk
|
|
468
476
|
if content:
|
|
469
477
|
full_text += content
|
|
470
478
|
yield {"type": "delta", "text": content}
|
|
@@ -472,7 +480,7 @@ class MoonshotDriver(CostMixin, Driver):
|
|
|
472
480
|
total_tokens = prompt_tokens + completion_tokens
|
|
473
481
|
total_cost = self._calculate_cost("moonshot", model, prompt_tokens, completion_tokens)
|
|
474
482
|
|
|
475
|
-
|
|
483
|
+
done_chunk: dict[str, Any] = {
|
|
476
484
|
"type": "done",
|
|
477
485
|
"text": full_text,
|
|
478
486
|
"meta": {
|
|
@@ -484,3 +492,6 @@ class MoonshotDriver(CostMixin, Driver):
|
|
|
484
492
|
"model_name": model,
|
|
485
493
|
},
|
|
486
494
|
}
|
|
495
|
+
if full_reasoning:
|
|
496
|
+
done_chunk["reasoning_content"] = full_reasoning
|
|
497
|
+
yield done_chunk
|
|
@@ -181,8 +181,18 @@ class OpenRouterDriver(CostMixin, Driver):
|
|
|
181
181
|
"model_name": model,
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
message = resp["choices"][0]["message"]
|
|
185
|
+
text = message.get("content") or ""
|
|
186
|
+
reasoning_content = message.get("reasoning_content")
|
|
187
|
+
|
|
188
|
+
# Reasoning models may return content in reasoning_content when content is empty
|
|
189
|
+
if not text and reasoning_content:
|
|
190
|
+
text = reasoning_content
|
|
191
|
+
|
|
192
|
+
result: dict[str, Any] = {"text": text, "meta": meta}
|
|
193
|
+
if reasoning_content is not None:
|
|
194
|
+
result["reasoning_content"] = reasoning_content
|
|
195
|
+
return result
|
|
186
196
|
|
|
187
197
|
# ------------------------------------------------------------------
|
|
188
198
|
# Tool use
|
|
@@ -257,18 +267,23 @@ class OpenRouterDriver(CostMixin, Driver):
|
|
|
257
267
|
args = json.loads(tc["function"]["arguments"])
|
|
258
268
|
except (json.JSONDecodeError, TypeError):
|
|
259
269
|
args = {}
|
|
260
|
-
tool_calls_out.append(
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
270
|
+
tool_calls_out.append(
|
|
271
|
+
{
|
|
272
|
+
"id": tc["id"],
|
|
273
|
+
"name": tc["function"]["name"],
|
|
274
|
+
"arguments": args,
|
|
275
|
+
}
|
|
276
|
+
)
|
|
265
277
|
|
|
266
|
-
|
|
278
|
+
result: dict[str, Any] = {
|
|
267
279
|
"text": text,
|
|
268
280
|
"meta": meta,
|
|
269
281
|
"tool_calls": tool_calls_out,
|
|
270
282
|
"stop_reason": stop_reason,
|
|
271
283
|
}
|
|
284
|
+
if choice["message"].get("reasoning_content") is not None:
|
|
285
|
+
result["reasoning_content"] = choice["message"]["reasoning_content"]
|
|
286
|
+
return result
|
|
272
287
|
|
|
273
288
|
# ------------------------------------------------------------------
|
|
274
289
|
# Streaming
|
|
@@ -311,13 +326,14 @@ class OpenRouterDriver(CostMixin, Driver):
|
|
|
311
326
|
response.raise_for_status()
|
|
312
327
|
|
|
313
328
|
full_text = ""
|
|
329
|
+
full_reasoning = ""
|
|
314
330
|
prompt_tokens = 0
|
|
315
331
|
completion_tokens = 0
|
|
316
332
|
|
|
317
333
|
for line in response.iter_lines(decode_unicode=True):
|
|
318
334
|
if not line or not line.startswith("data: "):
|
|
319
335
|
continue
|
|
320
|
-
payload = line[len("data: "):]
|
|
336
|
+
payload = line[len("data: ") :]
|
|
321
337
|
if payload.strip() == "[DONE]":
|
|
322
338
|
break
|
|
323
339
|
try:
|
|
@@ -335,6 +351,11 @@ class OpenRouterDriver(CostMixin, Driver):
|
|
|
335
351
|
if choices:
|
|
336
352
|
delta = choices[0].get("delta", {})
|
|
337
353
|
content = delta.get("content", "")
|
|
354
|
+
reasoning_chunk = delta.get("reasoning_content") or ""
|
|
355
|
+
if reasoning_chunk:
|
|
356
|
+
full_reasoning += reasoning_chunk
|
|
357
|
+
if not content and reasoning_chunk:
|
|
358
|
+
content = reasoning_chunk
|
|
338
359
|
if content:
|
|
339
360
|
full_text += content
|
|
340
361
|
yield {"type": "delta", "text": content}
|
|
@@ -342,7 +363,7 @@ class OpenRouterDriver(CostMixin, Driver):
|
|
|
342
363
|
total_tokens = prompt_tokens + completion_tokens
|
|
343
364
|
total_cost = self._calculate_cost("openrouter", model, prompt_tokens, completion_tokens)
|
|
344
365
|
|
|
345
|
-
|
|
366
|
+
done_chunk: dict[str, Any] = {
|
|
346
367
|
"type": "done",
|
|
347
368
|
"text": full_text,
|
|
348
369
|
"meta": {
|
|
@@ -354,3 +375,6 @@ class OpenRouterDriver(CostMixin, Driver):
|
|
|
354
375
|
"model_name": model,
|
|
355
376
|
},
|
|
356
377
|
}
|
|
378
|
+
if full_reasoning:
|
|
379
|
+
done_chunk["reasoning_content"] = full_reasoning
|
|
380
|
+
yield done_chunk
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
prompture/__init__.py,sha256=cJnkefDpiyFbU77juw4tXPdKJQWoJ-c6XBFt2v-e5Q4,7455
|
|
2
|
-
prompture/_version.py,sha256=
|
|
2
|
+
prompture/_version.py,sha256=u1zVumMYiBTlJQmr6vfEgpcsD6-vEHBNzFbXS_Hdi_Q,719
|
|
3
3
|
prompture/agent.py,sha256=-8qdo_Lz20GGssCe5B_QPxb5Kct71YtKHh5vZgrSYik,34748
|
|
4
4
|
prompture/agent_types.py,sha256=Icl16PQI-ThGLMFCU43adtQA6cqETbsPn4KssKBI4xc,4664
|
|
5
5
|
prompture/async_agent.py,sha256=_6_IRb-LGzZxGxfPVy43SIWByUoQfN-5XnUWahVP6r8,33110
|
|
6
|
-
prompture/async_conversation.py,sha256=
|
|
6
|
+
prompture/async_conversation.py,sha256=tzOy2jiCOVkRHIJ9H6VeRwwcUtbjF33--igdxMC6F7s,34811
|
|
7
7
|
prompture/async_core.py,sha256=hbRXLvsBJv3JAnUwGZbazsL6x022FrsJU6swmZolgxY,29745
|
|
8
8
|
prompture/async_driver.py,sha256=4VQ9Q_tI6Ufw6W1CYJ5j8hVtgVdqFGuk6e2tLaSceWE,8581
|
|
9
9
|
prompture/async_groups.py,sha256=pceKrt0UayQjMLFs1dFGoxOHpgD948aEjIY61r608C4,22459
|
|
10
10
|
prompture/cache.py,sha256=4dfQDMsEZ9JMQDXLOkiugPmmMJQIfKVE8rTAKDH4oL8,14401
|
|
11
11
|
prompture/callbacks.py,sha256=JPDqWGzPIzv44l54ocmezlYVBnbKPDEEXRrLdluWGAo,1731
|
|
12
12
|
prompture/cli.py,sha256=tNiIddRmgC1BomjY5O1VVVAwvqHVzF8IHmQrM-cG2wQ,2902
|
|
13
|
-
prompture/conversation.py,sha256=
|
|
13
|
+
prompture/conversation.py,sha256=uxstayJjgY6a39DtU0YxQl0Dt3JBo2UVCyMPJW95MNI,36428
|
|
14
14
|
prompture/core.py,sha256=5FHwX7fNPwFHMbFCMvV-RH7LpPpTToLAmcyDnKbrN0E,57202
|
|
15
15
|
prompture/cost_mixin.py,sha256=Qx7gPgPsWgTHiaFeI7q_p9cfe95ccjgN8Mi56d_AVX0,4563
|
|
16
16
|
prompture/discovery.py,sha256=K-svbO-qJraHinCbFVS64vEo5McWX5pURv26ZMmuL6U,10295
|
|
@@ -40,31 +40,31 @@ prompture/drivers/async_airllm_driver.py,sha256=1hIWLXfyyIg9tXaOE22tLJvFyNwHnOi1
|
|
|
40
40
|
prompture/drivers/async_azure_driver.py,sha256=s__y_EGQkK7UZjxiyF08uql8F09cnbJ0q7aFuxzreIw,7328
|
|
41
41
|
prompture/drivers/async_claude_driver.py,sha256=oawbFVVMtRlikQOmu3jRjbdpoeu95JqTF1YHLKO3ybE,10576
|
|
42
42
|
prompture/drivers/async_google_driver.py,sha256=LTUgCXJjzuTDGzsCsmY2-xH2KdTLJD7htwO49ZNFOdE,13711
|
|
43
|
-
prompture/drivers/async_grok_driver.py,sha256=
|
|
44
|
-
prompture/drivers/async_groq_driver.py,sha256=
|
|
43
|
+
prompture/drivers/async_grok_driver.py,sha256=lj160GHARe0fqTms4ovWhkpgt0idsGt55xnuc6JlH1w,7413
|
|
44
|
+
prompture/drivers/async_groq_driver.py,sha256=5G0rXAEAmsLNftI9YfGAh4E8X3B4Hb6_0cXBhf9LZMk,6348
|
|
45
45
|
prompture/drivers/async_hugging_driver.py,sha256=IblxqU6TpNUiigZ0BCgNkAgzpUr2FtPHJOZnOZMnHF0,2152
|
|
46
|
-
prompture/drivers/async_lmstudio_driver.py,sha256=
|
|
46
|
+
prompture/drivers/async_lmstudio_driver.py,sha256=4bz8NFFiZiFFkzlYDcS7abnwmEbbvbKb-CQhHeTGlU8,6102
|
|
47
47
|
prompture/drivers/async_local_http_driver.py,sha256=qoigIf-w3_c2dbVdM6m1e2RMAWP4Gk4VzVs5hM3lPvQ,1609
|
|
48
48
|
prompture/drivers/async_modelscope_driver.py,sha256=wzHYGLf9qE9KXRFZYtN1hZS10Bw1m1Wy6HcmyUD67HM,10170
|
|
49
|
-
prompture/drivers/async_moonshot_driver.py,sha256=
|
|
49
|
+
prompture/drivers/async_moonshot_driver.py,sha256=a9gr3T_4NiDFd7foM1mSHJRvXYb43iqqJnQ0FVRyI2E,15669
|
|
50
50
|
prompture/drivers/async_ollama_driver.py,sha256=pFtCvh5bHe_qwGy-jIJbyG_zmnPbNbagJCGxCTJMdPU,8244
|
|
51
51
|
prompture/drivers/async_openai_driver.py,sha256=COa_JE-AgKowKJpmRnfDJp4RSQKZel_7WswxOzvLksM,9044
|
|
52
|
-
prompture/drivers/async_openrouter_driver.py,sha256=
|
|
52
|
+
prompture/drivers/async_openrouter_driver.py,sha256=N7s72HuXHLs_RWmJO9P3pCayWE98ommfqVeAfru8Bl0,11758
|
|
53
53
|
prompture/drivers/async_registry.py,sha256=JFEnXNPm-8AAUCiNLoKuYBSCYEK-4BmAen5t55QrMvg,5223
|
|
54
54
|
prompture/drivers/async_zai_driver.py,sha256=zXHxske1CtK8dDTGY-D_kiyZZ_NfceNTJlyTpKn0R4c,10727
|
|
55
55
|
prompture/drivers/azure_driver.py,sha256=gQFffA29gOr-GZ25fNXTokV8-mEmffeV9CT_UBZ3yXc,8565
|
|
56
56
|
prompture/drivers/claude_driver.py,sha256=C8Av3DXP2x3f35jEv8BRwEM_4vh0cfmLsy3t5dsR6aM,11837
|
|
57
57
|
prompture/drivers/google_driver.py,sha256=Zck5VUsW37kDgohXz3cUWRmZ88OfhmTpVD-qzAVMp-8,16318
|
|
58
|
-
prompture/drivers/grok_driver.py,sha256=
|
|
59
|
-
prompture/drivers/groq_driver.py,sha256=
|
|
58
|
+
prompture/drivers/grok_driver.py,sha256=fxl5Gx9acFq7BlOh_N9U66oJvG3y8YX4QuSAgZWHJmU,8963
|
|
59
|
+
prompture/drivers/groq_driver.py,sha256=7YEok1BQlsDZGkA-l9yrjTDapqIWX3yq_Ctgbhu8jSI,7490
|
|
60
60
|
prompture/drivers/hugging_driver.py,sha256=gZir3XnM77VfYIdnu3S1pRftlZJM6G3L8bgGn5esg-Q,2346
|
|
61
|
-
prompture/drivers/lmstudio_driver.py,sha256=
|
|
61
|
+
prompture/drivers/lmstudio_driver.py,sha256=nZ5SvBC0kTDNDzsupIW_H7YK92dcYta_xSPUNs52gyM,7154
|
|
62
62
|
prompture/drivers/local_http_driver.py,sha256=QJgEf9kAmy8YZ5fb8FHnWuhoDoZYNd8at4jegzNVJH0,1658
|
|
63
63
|
prompture/drivers/modelscope_driver.py,sha256=yTxTG7j5f7zz4CjbrV8J0VKeoBmxv69F40bfp8nq6AE,10651
|
|
64
|
-
prompture/drivers/moonshot_driver.py,sha256=
|
|
64
|
+
prompture/drivers/moonshot_driver.py,sha256=cm1XpU6EPFjcZaneXjfetRNSUxN9daP6hkJ1y99kqLI,19123
|
|
65
65
|
prompture/drivers/ollama_driver.py,sha256=SJtMRtAr8geUB4y5GIZxPr-RJ0C3q7yqigYei2b4luM,13710
|
|
66
66
|
prompture/drivers/openai_driver.py,sha256=DqdMhxF8M2HdOY5vfsFrz0h23lqBoQlbxV3xUdHvZho,10548
|
|
67
|
-
prompture/drivers/openrouter_driver.py,sha256=
|
|
67
|
+
prompture/drivers/openrouter_driver.py,sha256=m2I5E9L5YYE_bV8PruKnAwjL63SIFEXevN_ThUzxQaA,13657
|
|
68
68
|
prompture/drivers/registry.py,sha256=Dg_5w9alnIPKhOnsR9Xspuf5T7roBGu0r_L2Cf-UhXs,9926
|
|
69
69
|
prompture/drivers/vision_helpers.py,sha256=l5iYXHJLR_vLFvqDPPPK1QqK7YPKh5GwocpbSyt0R04,5403
|
|
70
70
|
prompture/drivers/zai_driver.py,sha256=Wkur0HfwKJt8ugYErpvz1Gy6e9an8vt4R7U3i6HWV_s,11038
|
|
@@ -77,9 +77,9 @@ prompture/scaffold/templates/env.example.j2,sha256=eESKr1KWgyrczO6d-nwAhQwSpf_G-
|
|
|
77
77
|
prompture/scaffold/templates/main.py.j2,sha256=TEgc5OvsZOEX0JthkSW1NI_yLwgoeVN_x97Ibg-vyWY,2632
|
|
78
78
|
prompture/scaffold/templates/models.py.j2,sha256=JrZ99GCVK6TKWapskVRSwCssGrTu5cGZ_r46fOhY2GE,858
|
|
79
79
|
prompture/scaffold/templates/requirements.txt.j2,sha256=m3S5fi1hq9KG9l_9j317rjwWww0a43WMKd8VnUWv2A4,102
|
|
80
|
-
prompture-0.0.47.
|
|
81
|
-
prompture-0.0.47.
|
|
82
|
-
prompture-0.0.47.
|
|
83
|
-
prompture-0.0.47.
|
|
84
|
-
prompture-0.0.47.
|
|
85
|
-
prompture-0.0.47.
|
|
80
|
+
prompture-0.0.47.dev3.dist-info/licenses/LICENSE,sha256=0HgDepH7aaHNFhHF-iXuW6_GqDfYPnVkjtiCAZ4yS8I,1060
|
|
81
|
+
prompture-0.0.47.dev3.dist-info/METADATA,sha256=GCknitr30odleYVAoFwVD9zZvMaHqed8z_3omEhs3Vc,12153
|
|
82
|
+
prompture-0.0.47.dev3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
83
|
+
prompture-0.0.47.dev3.dist-info/entry_points.txt,sha256=AFPG3lJR86g4IJMoWQUW5Ph7G6MLNWG3A2u2Tp9zkp8,48
|
|
84
|
+
prompture-0.0.47.dev3.dist-info/top_level.txt,sha256=to86zq_kjfdoLeAxQNr420UWqT0WzkKoZ509J7Qr2t4,10
|
|
85
|
+
prompture-0.0.47.dev3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|