stirrup 0.1.2__py3-none-any.whl → 0.1.3__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.
- stirrup/__init__.py +2 -0
- stirrup/clients/chat_completions_client.py +0 -3
- stirrup/clients/litellm_client.py +20 -11
- stirrup/clients/utils.py +6 -1
- stirrup/constants.py +6 -2
- stirrup/core/agent.py +180 -57
- stirrup/core/cache.py +479 -0
- stirrup/core/models.py +49 -7
- stirrup/prompts/base_system_prompt.txt +1 -1
- stirrup/tools/__init__.py +2 -0
- stirrup/tools/calculator.py +1 -1
- stirrup/tools/code_backends/base.py +7 -0
- stirrup/tools/code_backends/e2b.py +25 -11
- stirrup/tools/code_backends/local.py +2 -2
- stirrup/tools/finish.py +1 -1
- stirrup/tools/user_input.py +130 -0
- stirrup/tools/web.py +1 -0
- stirrup/utils/logging.py +24 -0
- {stirrup-0.1.2.dist-info → stirrup-0.1.3.dist-info}/METADATA +1 -1
- stirrup-0.1.3.dist-info/RECORD +36 -0
- {stirrup-0.1.2.dist-info → stirrup-0.1.3.dist-info}/WHEEL +1 -1
- stirrup-0.1.2.dist-info/RECORD +0 -34
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
+
from pydantic import ValidationError
|
|
6
|
+
|
|
5
7
|
try:
|
|
6
8
|
from e2b import InvalidArgumentException, TimeoutException
|
|
7
9
|
from e2b.sandbox.filesystem.filesystem import FileType
|
|
@@ -13,7 +15,7 @@ except ImportError as e:
|
|
|
13
15
|
|
|
14
16
|
import logging
|
|
15
17
|
|
|
16
|
-
from stirrup.constants import
|
|
18
|
+
from stirrup.constants import SANDBOX_REQUEST_TIMEOUT, SANDBOX_TIMEOUT
|
|
17
19
|
from stirrup.core.models import ImageContentBlock, Tool, ToolUseCountMetadata
|
|
18
20
|
|
|
19
21
|
from .base import (
|
|
@@ -51,7 +53,8 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
51
53
|
def __init__(
|
|
52
54
|
self,
|
|
53
55
|
*,
|
|
54
|
-
timeout: int =
|
|
56
|
+
timeout: int = SANDBOX_TIMEOUT,
|
|
57
|
+
request_timeout: int = SANDBOX_REQUEST_TIMEOUT,
|
|
55
58
|
template: str | None = None,
|
|
56
59
|
allowed_commands: list[str] | None = None,
|
|
57
60
|
) -> None:
|
|
@@ -67,6 +70,7 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
67
70
|
"""
|
|
68
71
|
super().__init__(allowed_commands=allowed_commands)
|
|
69
72
|
self._timeout = timeout
|
|
73
|
+
self._request_timeout = request_timeout
|
|
70
74
|
self._template = template
|
|
71
75
|
self._sbx: AsyncSandbox | None = None
|
|
72
76
|
|
|
@@ -109,7 +113,7 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
109
113
|
if not await self._sbx.files.exists(path):
|
|
110
114
|
raise FileNotFoundError(f"File not found: {path}")
|
|
111
115
|
|
|
112
|
-
file_bytes = await self._sbx.files.read(path, format="bytes")
|
|
116
|
+
file_bytes = await self._sbx.files.read(path, format="bytes", request_timeout=self._request_timeout)
|
|
113
117
|
return bytes(file_bytes)
|
|
114
118
|
|
|
115
119
|
async def write_file_bytes(self, path: str, content: bytes) -> None:
|
|
@@ -126,7 +130,7 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
126
130
|
if self._sbx is None:
|
|
127
131
|
raise RuntimeError("ExecutionEnvironment not started.")
|
|
128
132
|
|
|
129
|
-
await self._sbx.files.write(path, content)
|
|
133
|
+
await self._sbx.files.write(path, content, request_timeout=self._request_timeout)
|
|
130
134
|
|
|
131
135
|
async def run_command(self, cmd: str, *, timeout: int = SHELL_TIMEOUT) -> CommandResult:
|
|
132
136
|
"""Execute command in E2B execution environment, returning raw CommandResult."""
|
|
@@ -146,7 +150,7 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
146
150
|
)
|
|
147
151
|
|
|
148
152
|
try:
|
|
149
|
-
r = await self._sbx.commands.run(cmd, timeout=timeout)
|
|
153
|
+
r = await self._sbx.commands.run(cmd, timeout=timeout, request_timeout=self._request_timeout)
|
|
150
154
|
|
|
151
155
|
return CommandResult(
|
|
152
156
|
exit_code=getattr(r, "exit_code", 0),
|
|
@@ -231,7 +235,7 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
231
235
|
continue
|
|
232
236
|
|
|
233
237
|
# Read file content from execution environment
|
|
234
|
-
file_bytes = await self._sbx.files.read(env_path, format="bytes")
|
|
238
|
+
file_bytes = await self._sbx.files.read(env_path, format="bytes", request_timeout=self._request_timeout)
|
|
235
239
|
content = bytes(file_bytes)
|
|
236
240
|
|
|
237
241
|
# Save with original filename directly in output_dir
|
|
@@ -297,6 +301,7 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
297
301
|
result = UploadFilesResult()
|
|
298
302
|
|
|
299
303
|
for source in paths:
|
|
304
|
+
original_name = Path(source).name # Get name BEFORE resolve
|
|
300
305
|
source = Path(source).resolve()
|
|
301
306
|
|
|
302
307
|
if not source.exists():
|
|
@@ -306,9 +311,10 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
306
311
|
|
|
307
312
|
try:
|
|
308
313
|
if source.is_file():
|
|
309
|
-
|
|
314
|
+
source = Path(source).resolve()
|
|
315
|
+
dest = f"{dest_base}/{original_name}"
|
|
310
316
|
content = source.read_bytes()
|
|
311
|
-
await self._sbx.files.write(dest, content)
|
|
317
|
+
await self._sbx.files.write(dest, content, request_timeout=self._request_timeout)
|
|
312
318
|
result.uploaded.append(
|
|
313
319
|
UploadedFile(
|
|
314
320
|
source_path=source,
|
|
@@ -327,7 +333,7 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
327
333
|
relative = file_path.relative_to(source)
|
|
328
334
|
dest = f"{dest_base}/{relative}" if dest_dir else f"{dest_base}/{source.name}/{relative}"
|
|
329
335
|
content = file_path.read_bytes()
|
|
330
|
-
await self._sbx.files.write(dest, content)
|
|
336
|
+
await self._sbx.files.write(dest, content, request_timeout=self._request_timeout)
|
|
331
337
|
result.uploaded.append(
|
|
332
338
|
UploadedFile(
|
|
333
339
|
source_path=file_path,
|
|
@@ -360,5 +366,13 @@ class E2BCodeExecToolProvider(CodeExecToolProvider):
|
|
|
360
366
|
FileNotFoundError: If file does not exist.
|
|
361
367
|
|
|
362
368
|
"""
|
|
363
|
-
|
|
364
|
-
|
|
369
|
+
if not path.lower().endswith((".png", ".jpg", ".jpeg")):
|
|
370
|
+
raise ValueError(f"Unsupported image type for `{path}`. Only .png, .jpg, or .jpeg are allowed.")
|
|
371
|
+
|
|
372
|
+
try:
|
|
373
|
+
file_bytes = await self.read_file_bytes(path)
|
|
374
|
+
image = ImageContentBlock(data=file_bytes)
|
|
375
|
+
except ValidationError as e:
|
|
376
|
+
raise ValueError("You submitted a corrupt/unsupported image file.") from e
|
|
377
|
+
|
|
378
|
+
return image
|
|
@@ -122,7 +122,7 @@ class LocalCodeExecToolProvider(CodeExecToolProvider):
|
|
|
122
122
|
if self._temp_base_dir:
|
|
123
123
|
self._temp_base_dir.mkdir(parents=True, exist_ok=True)
|
|
124
124
|
self._temp_dir = Path(tempfile.mkdtemp(prefix="local_exec_env_", dir=self._temp_base_dir))
|
|
125
|
-
logger.
|
|
125
|
+
logger.debug("Created local execution environment temp directory: %s", self._temp_dir)
|
|
126
126
|
return self.get_code_exec_tool(description=self._description)
|
|
127
127
|
|
|
128
128
|
async def __aexit__(
|
|
@@ -359,7 +359,7 @@ class LocalCodeExecToolProvider(CodeExecToolProvider):
|
|
|
359
359
|
|
|
360
360
|
# Move file (overwrites if exists)
|
|
361
361
|
shutil.move(str(source_path), str(dest_path))
|
|
362
|
-
logger.
|
|
362
|
+
logger.debug("Moved file: %s -> %s", source_path, dest_path)
|
|
363
363
|
|
|
364
364
|
result.saved.append(
|
|
365
365
|
SavedFile(
|
stirrup/tools/finish.py
CHANGED
|
@@ -19,5 +19,5 @@ SIMPLE_FINISH_TOOL: Tool[FinishParams, ToolUseCountMetadata] = Tool[FinishParams
|
|
|
19
19
|
name=FINISH_TOOL_NAME,
|
|
20
20
|
description="Signal task completion with a reason. Use when the task is finished or cannot proceed further. Note that you will need a separate turn to finish.",
|
|
21
21
|
parameters=FinishParams,
|
|
22
|
-
executor=lambda params: ToolResult(content=params.reason, metadata=ToolUseCountMetadata()),
|
|
22
|
+
executor=lambda params: ToolResult(content=params.reason, metadata=ToolUseCountMetadata(), success=True),
|
|
23
23
|
)
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""User input tool for interactive clarification during agent execution.
|
|
2
|
+
|
|
3
|
+
This module provides the user_input tool that allows agents to ask questions
|
|
4
|
+
and receive text responses from users during task execution.
|
|
5
|
+
|
|
6
|
+
Example usage:
|
|
7
|
+
from stirrup.clients.chat_completions_client import ChatCompletionsClient
|
|
8
|
+
from stirrup.tools import DEFAULT_TOOLS, USER_INPUT_TOOL
|
|
9
|
+
|
|
10
|
+
client = ChatCompletionsClient(model="gpt-5")
|
|
11
|
+
agent = Agent(
|
|
12
|
+
client=client,
|
|
13
|
+
name="assistant",
|
|
14
|
+
tools=[*DEFAULT_TOOLS, USER_INPUT_TOOL],
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
async with agent.session() as session:
|
|
18
|
+
await session.run("Help me configure my project")
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from typing import Annotated, Literal
|
|
22
|
+
|
|
23
|
+
from pydantic import BaseModel, Field
|
|
24
|
+
from rich.panel import Panel
|
|
25
|
+
from rich.prompt import Confirm, Prompt
|
|
26
|
+
|
|
27
|
+
from stirrup.core.models import Tool, ToolResult, ToolUseCountMetadata
|
|
28
|
+
from stirrup.utils.logging import AgentLoggerBase, console
|
|
29
|
+
|
|
30
|
+
__all__ = ["USER_INPUT_TOOL", "UserInputParams"]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class UserInputParams(BaseModel):
|
|
34
|
+
"""Parameters for asking the user a single question.
|
|
35
|
+
|
|
36
|
+
Supports three question types:
|
|
37
|
+
- "text": Free-form text input (default)
|
|
38
|
+
- "choice": Multiple choice from a list of options
|
|
39
|
+
- "confirm": Yes/no confirmation
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
question: Annotated[str, Field(description="A single question to ask the user (*not* multiple questions)")]
|
|
43
|
+
question_type: Annotated[
|
|
44
|
+
Literal["text", "choice", "confirm"],
|
|
45
|
+
Field(
|
|
46
|
+
default="text",
|
|
47
|
+
description="Type of question: 'text' for free-form, 'choice' for multiple choice, 'confirm' for yes/no",
|
|
48
|
+
),
|
|
49
|
+
]
|
|
50
|
+
choices: Annotated[
|
|
51
|
+
list[str] | None,
|
|
52
|
+
Field(default=None, description="List of valid choices (required when question_type is 'choice')"),
|
|
53
|
+
]
|
|
54
|
+
default: Annotated[
|
|
55
|
+
str,
|
|
56
|
+
Field(default="", description="Default value if user presses Enter without input"),
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _get_logger() -> "AgentLoggerBase | None":
|
|
61
|
+
"""Get the current session's logger for pause/resume.
|
|
62
|
+
|
|
63
|
+
Returns the logger from SessionState if available, None otherwise.
|
|
64
|
+
"""
|
|
65
|
+
from stirrup.core.agent import _SESSION_STATE
|
|
66
|
+
|
|
67
|
+
state = _SESSION_STATE.get(None)
|
|
68
|
+
return state.logger if state else None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def user_input_executor(params: UserInputParams) -> ToolResult[ToolUseCountMetadata]:
|
|
72
|
+
"""Prompt the user for input and return their response."""
|
|
73
|
+
logger = _get_logger()
|
|
74
|
+
|
|
75
|
+
# Pause spinner before prompting
|
|
76
|
+
if logger:
|
|
77
|
+
logger.pause_live()
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
# Print newline to separate from spinner, then display question in a styled panel
|
|
81
|
+
console.print()
|
|
82
|
+
panel = Panel(
|
|
83
|
+
params.question,
|
|
84
|
+
title="[bold cyan]🤔 Agent Question[/]",
|
|
85
|
+
title_align="left",
|
|
86
|
+
border_style="cyan",
|
|
87
|
+
padding=(0, 1),
|
|
88
|
+
)
|
|
89
|
+
console.print(panel)
|
|
90
|
+
|
|
91
|
+
# Get user input based on question type
|
|
92
|
+
if params.question_type == "confirm":
|
|
93
|
+
# Yes/no confirmation
|
|
94
|
+
default_bool = params.default.lower() in ("yes", "y", "true", "1") if params.default else False
|
|
95
|
+
result = Confirm.ask("[bold]Your answer[/]", default=default_bool, console=console)
|
|
96
|
+
answer = "yes" if result else "no"
|
|
97
|
+
|
|
98
|
+
elif params.question_type == "choice" and params.choices:
|
|
99
|
+
# Multiple choice
|
|
100
|
+
answer = Prompt.ask(
|
|
101
|
+
"[bold]Your answer[/]",
|
|
102
|
+
choices=params.choices,
|
|
103
|
+
default=params.default,
|
|
104
|
+
console=console,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
else:
|
|
108
|
+
# Free-form text (default)
|
|
109
|
+
answer = Prompt.ask("[bold]Your answer[/]", default=params.default or "", console=console)
|
|
110
|
+
|
|
111
|
+
return ToolResult(content=answer, metadata=ToolUseCountMetadata())
|
|
112
|
+
|
|
113
|
+
finally:
|
|
114
|
+
# Always resume spinner, even if an exception occurs
|
|
115
|
+
if logger:
|
|
116
|
+
logger.resume_live()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
USER_INPUT_TOOL: Tool[UserInputParams, ToolUseCountMetadata] = Tool(
|
|
120
|
+
name="user_input",
|
|
121
|
+
description=(
|
|
122
|
+
"Ask the user a question when you need clarification or are uncertain. "
|
|
123
|
+
"Supports three types: 'text' for free-form input, 'choice' for multiple choice "
|
|
124
|
+
"(provide choices list), 'confirm' for yes/no questions. Returns the user's response."
|
|
125
|
+
"There should only EVER be one question per call to this tool."
|
|
126
|
+
"If you need to ask multiple questions, you should call this tool multiple times."
|
|
127
|
+
),
|
|
128
|
+
parameters=UserInputParams,
|
|
129
|
+
executor=user_input_executor,
|
|
130
|
+
)
|
stirrup/tools/web.py
CHANGED
|
@@ -125,6 +125,7 @@ def _get_fetch_web_page_tool(client: httpx.AsyncClient | None = None) -> Tool[Fe
|
|
|
125
125
|
return ToolResult(
|
|
126
126
|
content=f"<web_fetch><url>{params.url}</url><error>"
|
|
127
127
|
f"{truncate_msg(str(exc), MAX_LENGTH_WEB_FETCH_HTML)}</error></web_fetch>",
|
|
128
|
+
success=False,
|
|
128
129
|
metadata=WebFetchMetadata(pages_fetched=[params.url]),
|
|
129
130
|
)
|
|
130
131
|
|
stirrup/utils/logging.py
CHANGED
|
@@ -27,6 +27,7 @@ from stirrup.core.models import AssistantMessage, ToolMessage, UserMessage, _agg
|
|
|
27
27
|
__all__ = [
|
|
28
28
|
"AgentLogger",
|
|
29
29
|
"AgentLoggerBase",
|
|
30
|
+
"console",
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
# Shared console instance
|
|
@@ -247,6 +248,12 @@ class AgentLoggerBase(ABC):
|
|
|
247
248
|
"""Log an error message."""
|
|
248
249
|
...
|
|
249
250
|
|
|
251
|
+
def pause_live(self) -> None: # noqa: B027
|
|
252
|
+
"""Pause live display (e.g., spinner) before user interaction."""
|
|
253
|
+
|
|
254
|
+
def resume_live(self) -> None: # noqa: B027
|
|
255
|
+
"""Resume live display after user interaction."""
|
|
256
|
+
|
|
250
257
|
|
|
251
258
|
class AgentLogger(AgentLoggerBase):
|
|
252
259
|
"""Rich console logger for agent workflows.
|
|
@@ -655,6 +662,23 @@ class AgentLogger(AgentLoggerBase):
|
|
|
655
662
|
if self._live:
|
|
656
663
|
self._live.update(self._make_spinner())
|
|
657
664
|
|
|
665
|
+
def pause_live(self) -> None:
|
|
666
|
+
"""Pause the live spinner display.
|
|
667
|
+
|
|
668
|
+
Call this before prompting for user input to prevent the spinner
|
|
669
|
+
from interfering with the input prompt.
|
|
670
|
+
"""
|
|
671
|
+
if self._live is not None:
|
|
672
|
+
self._live.stop()
|
|
673
|
+
|
|
674
|
+
def resume_live(self) -> None:
|
|
675
|
+
"""Resume the live spinner display.
|
|
676
|
+
|
|
677
|
+
Call this after user input is complete to restart the spinner.
|
|
678
|
+
"""
|
|
679
|
+
if self._live is not None:
|
|
680
|
+
self._live.start()
|
|
681
|
+
|
|
658
682
|
def set_level(self, level: int) -> None:
|
|
659
683
|
"""Set the logging level."""
|
|
660
684
|
self._level = level
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
stirrup/__init__.py,sha256=4p5Rw7f_wdxVu1FJTgJROe0aTlnc8tOsainBEzDRGEY,1905
|
|
2
|
+
stirrup/clients/__init__.py,sha256=oO8VMHmbUhoxFyC0JLQs_kUFNSRlvTj5xz0FgzBb98E,405
|
|
3
|
+
stirrup/clients/chat_completions_client.py,sha256=P0VOGFQcfLIVf7zCGYbopQDjNVEJlpeLBeGvB87sQQg,7390
|
|
4
|
+
stirrup/clients/litellm_client.py,sha256=2ZrZKKAEV2dEFs6ze4qBl3it5VwiGH8s7wHVuHdw-uY,5507
|
|
5
|
+
stirrup/clients/utils.py,sha256=Z_8KiENDZVD9fChUm7PA-RLhvoChswHVQsjrHXlIfkg,5684
|
|
6
|
+
stirrup/constants.py,sha256=WpVPm2jRN2AqYMyoMYeJimiggoquP7M3IrcHNpduFF4,644
|
|
7
|
+
stirrup/core/__init__.py,sha256=ReBVl7B9h_FNkZ77vCx2xlfuK1JuQ0yTSXrEgc4tONU,39
|
|
8
|
+
stirrup/core/agent.py,sha256=2KxjuCy3scLRc59habPSZyYDCHL9a9--UcdFKYV-86w,56907
|
|
9
|
+
stirrup/core/cache.py,sha256=lAbbBJzgYInewoBBPMzNooroU2Q7JbF21riggfdIDa8,16697
|
|
10
|
+
stirrup/core/exceptions.py,sha256=CzLVAi7Ns-t9BWSkqQUCB7ypVHAesV2s4a09-i0NXyQ,213
|
|
11
|
+
stirrup/core/models.py,sha256=qMmpecRIl8sKdUePtoVChKA3rBHxzG8lI4ZvuLFHNzo,22553
|
|
12
|
+
stirrup/prompts/__init__.py,sha256=e4bpTktBaFPuO_bIW5DelGNWtT6_NIUqnD2lRv8n89I,796
|
|
13
|
+
stirrup/prompts/base_system_prompt.txt,sha256=D_UlDWEnG2yaPCMFrE7IqMHI8VCzi4BZ-GnuL3qs5q4,288
|
|
14
|
+
stirrup/prompts/message_summarizer.txt,sha256=uQoTxreMuC42rTGSZmoH1Dnj06WrEQb0gLkDvVMhosQ,1173
|
|
15
|
+
stirrup/prompts/message_summarizer_bridge.txt,sha256=sWbfnHtI6RWemBIyQsnqHMGpnU-E6FTbfUC6rvkEHLY,372
|
|
16
|
+
stirrup/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
stirrup/skills/__init__.py,sha256=BEcmdSskfBzx_QK4eKXECucndIKRjHXzzwwwsaez8k4,700
|
|
18
|
+
stirrup/skills/skills.py,sha256=qhA3HI55kaRqLyvn_56Cs71833Xacg-8qP7muHrwruE,4282
|
|
19
|
+
stirrup/tools/__init__.py,sha256=l8bKHZwPBZfBPgxQfLzOKyyzdfoF86NrgdmxhjYW09s,2790
|
|
20
|
+
stirrup/tools/calculator.py,sha256=Cckt-8TtltxtuyY_Hh0wOr8efUzBZzg7rG4dBpvpuRM,1293
|
|
21
|
+
stirrup/tools/code_backends/__init__.py,sha256=O3Rs76r0YcQ27voTrx_zuhIEFawK3b1TQdKi70MORG8,987
|
|
22
|
+
stirrup/tools/code_backends/base.py,sha256=5mQxbHoOvtTdiF1y1aVe4csodaCOGvHaVN5viRnUlUE,17250
|
|
23
|
+
stirrup/tools/code_backends/docker.py,sha256=Xx4aBZ1uXVznP0qV4tXL2PMMs-8QEPw1bIPvgPasEGk,30281
|
|
24
|
+
stirrup/tools/code_backends/e2b.py,sha256=4I5Aqas-4PVhYgMhIAQh3xcwl_0kGiUpo64UU9-awfE,14921
|
|
25
|
+
stirrup/tools/code_backends/local.py,sha256=snzbWHnZkVu1ibLLRyRVmi6U9-8407_A0sKbdDNyTe4,19600
|
|
26
|
+
stirrup/tools/finish.py,sha256=zdljSs77zMVkA2AGUfV05QmeLxz6JrwJF_ar02yvsVA,950
|
|
27
|
+
stirrup/tools/mcp.py,sha256=4wWYae95y8Bs7e36hHwnxRfVVj0PABrsRStw492lLaw,18749
|
|
28
|
+
stirrup/tools/user_input.py,sha256=XwK14FvRQly3vGwgNzPVGoSXfbco0WWaSVpTDyjV09E,4508
|
|
29
|
+
stirrup/tools/view_image.py,sha256=zazCpZMtLOD6lplLPYGNQ8JeYfc0oUDJoUUyVAp3AMU,3126
|
|
30
|
+
stirrup/tools/web.py,sha256=B-zp5i1WhjOOMAlYtnvU3N5hNYnJYm8qVXAtNx_ZaRw,12292
|
|
31
|
+
stirrup/utils/__init__.py,sha256=4kcuExrphSXqgxRgu1q8_Z6Rrb9aAZpIo4Xq4S9Twuk,230
|
|
32
|
+
stirrup/utils/logging.py,sha256=48rCzv7B15jiVM1JlKzwTSnGodbqGSKLlsZi9xRMmVM,35045
|
|
33
|
+
stirrup/utils/text.py,sha256=3lGlcXFzQ-Mclsbu7wJciG3CcHvQ_Sk98tqOZxYLlGw,479
|
|
34
|
+
stirrup-0.1.3.dist-info/WHEEL,sha256=KSLUh82mDPEPk0Bx0ScXlWL64bc8KmzIPNcpQZFV-6E,79
|
|
35
|
+
stirrup-0.1.3.dist-info/METADATA,sha256=EyJEJTRFzLoSXnkBPauFvskBgMwJDJ8O2Vm8HdJPdsI,12862
|
|
36
|
+
stirrup-0.1.3.dist-info/RECORD,,
|
stirrup-0.1.2.dist-info/RECORD
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
stirrup/__init__.py,sha256=Dol0Uui-gBslpplfEUrgxkqqJWr1ucZJej5finNvCeI,1869
|
|
2
|
-
stirrup/clients/__init__.py,sha256=oO8VMHmbUhoxFyC0JLQs_kUFNSRlvTj5xz0FgzBb98E,405
|
|
3
|
-
stirrup/clients/chat_completions_client.py,sha256=p_EeXqRuo6mWnzgMhy22SWdHE6_OXIRyABvCKgHdnu4,7586
|
|
4
|
-
stirrup/clients/litellm_client.py,sha256=J-HDv7ZZTkNYC-aeSNyd7xTDd_5r8DEeXOPz9eQMC7A,4985
|
|
5
|
-
stirrup/clients/utils.py,sha256=Yyeh6unQSvqgDTDhjpD5DoRu_wP_nWfsNv9DGXQwgo8,5452
|
|
6
|
-
stirrup/constants.py,sha256=h3NzsePJ4FKpImTpV5xtFeJarKb67jR_6n89tNOkQYs,523
|
|
7
|
-
stirrup/core/__init__.py,sha256=ReBVl7B9h_FNkZ77vCx2xlfuK1JuQ0yTSXrEgc4tONU,39
|
|
8
|
-
stirrup/core/agent.py,sha256=tt1V564B6n_C0ffyH24LuC6PhE4EJA8NOolQCxDG9iw,50836
|
|
9
|
-
stirrup/core/exceptions.py,sha256=CzLVAi7Ns-t9BWSkqQUCB7ypVHAesV2s4a09-i0NXyQ,213
|
|
10
|
-
stirrup/core/models.py,sha256=KAyjJIoqbhgy_MN0sPwGI8XWxSiziPnyndMD05ylj_U,21121
|
|
11
|
-
stirrup/prompts/__init__.py,sha256=e4bpTktBaFPuO_bIW5DelGNWtT6_NIUqnD2lRv8n89I,796
|
|
12
|
-
stirrup/prompts/base_system_prompt.txt,sha256=KZ2_JhJ91u4oMqRZvhuAp99nb6ZkXkJdVbIRN6drVME,348
|
|
13
|
-
stirrup/prompts/message_summarizer.txt,sha256=uQoTxreMuC42rTGSZmoH1Dnj06WrEQb0gLkDvVMhosQ,1173
|
|
14
|
-
stirrup/prompts/message_summarizer_bridge.txt,sha256=sWbfnHtI6RWemBIyQsnqHMGpnU-E6FTbfUC6rvkEHLY,372
|
|
15
|
-
stirrup/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
stirrup/skills/__init__.py,sha256=BEcmdSskfBzx_QK4eKXECucndIKRjHXzzwwwsaez8k4,700
|
|
17
|
-
stirrup/skills/skills.py,sha256=qhA3HI55kaRqLyvn_56Cs71833Xacg-8qP7muHrwruE,4282
|
|
18
|
-
stirrup/tools/__init__.py,sha256=ohyeMvXb6oURiAyoHi0VmC9ksZSRyGleT341VNzHCy4,2714
|
|
19
|
-
stirrup/tools/calculator.py,sha256=JkuGmGZJtaKbC4vHVrIph4aTjlGcFMhhv5MB1ntqgv4,1278
|
|
20
|
-
stirrup/tools/code_backends/__init__.py,sha256=O3Rs76r0YcQ27voTrx_zuhIEFawK3b1TQdKi70MORG8,987
|
|
21
|
-
stirrup/tools/code_backends/base.py,sha256=Nx0tTDX4GKoBWQK2F953vSsFgWCcOd_1WNtYCA4FG4o,17021
|
|
22
|
-
stirrup/tools/code_backends/docker.py,sha256=Xx4aBZ1uXVznP0qV4tXL2PMMs-8QEPw1bIPvgPasEGk,30281
|
|
23
|
-
stirrup/tools/code_backends/e2b.py,sha256=7wV1SOu4S5g5uCtnipC1xNg8kBzCrudyIEOIkf-JCkE,14072
|
|
24
|
-
stirrup/tools/code_backends/local.py,sha256=WV-MMcPY5ooKPhOwd3JUUz718Ht8eRyYklGAZ0gkrx4,19598
|
|
25
|
-
stirrup/tools/finish.py,sha256=K_NxwOwdvncT2QTua2A_8lZ9MwK4WQQ5FL2gdUrE29c,936
|
|
26
|
-
stirrup/tools/mcp.py,sha256=4wWYae95y8Bs7e36hHwnxRfVVj0PABrsRStw492lLaw,18749
|
|
27
|
-
stirrup/tools/view_image.py,sha256=zazCpZMtLOD6lplLPYGNQ8JeYfc0oUDJoUUyVAp3AMU,3126
|
|
28
|
-
stirrup/tools/web.py,sha256=2yfBJsu8GgFI7Oh1dFlXwNaXth6WQfGpbJFU-rV-yuI,12261
|
|
29
|
-
stirrup/utils/__init__.py,sha256=4kcuExrphSXqgxRgu1q8_Z6Rrb9aAZpIo4Xq4S9Twuk,230
|
|
30
|
-
stirrup/utils/logging.py,sha256=3Li6MhjLJWwaXHDZ06EjgW42XDL6V3ZDt9rccV_ZYZ4,34292
|
|
31
|
-
stirrup/utils/text.py,sha256=3lGlcXFzQ-Mclsbu7wJciG3CcHvQ_Sk98tqOZxYLlGw,479
|
|
32
|
-
stirrup-0.1.2.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
|
|
33
|
-
stirrup-0.1.2.dist-info/METADATA,sha256=eIK1F1yXhCgFspDO8q5J48B7P3Jt16QZez3ZBVFU5n8,12862
|
|
34
|
-
stirrup-0.1.2.dist-info/RECORD,,
|