goose-py 0.3.1__py3-none-any.whl → 0.3.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.
goose/agent.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
import base64
|
2
|
+
import json
|
2
3
|
import logging
|
3
4
|
from datetime import datetime
|
4
5
|
from enum import StrEnum
|
5
|
-
from typing import Any,
|
6
|
+
from typing import Any, ClassVar, Literal, NotRequired, Protocol, TypedDict
|
6
7
|
|
7
8
|
from litellm import acompletion
|
8
9
|
from pydantic import BaseModel, computed_field
|
@@ -97,6 +98,24 @@ class SystemMessage(BaseModel):
|
|
97
98
|
}
|
98
99
|
|
99
100
|
|
101
|
+
class AgentResponseDump(TypedDict):
|
102
|
+
run_id: str
|
103
|
+
flow_name: str
|
104
|
+
task_name: str
|
105
|
+
model: str
|
106
|
+
system_message: str
|
107
|
+
input_messages: str
|
108
|
+
output_message: str
|
109
|
+
input_cost: float
|
110
|
+
output_cost: float
|
111
|
+
total_cost: float
|
112
|
+
input_tokens: int
|
113
|
+
output_tokens: int
|
114
|
+
start_time: datetime
|
115
|
+
end_time: datetime
|
116
|
+
duration_ms: int
|
117
|
+
|
118
|
+
|
100
119
|
class AgentResponse[R: BaseModel](BaseModel):
|
101
120
|
INPUT_CENTS_PER_MILLION_TOKENS: ClassVar[dict[GeminiModel, float]] = {
|
102
121
|
GeminiModel.FLASH_8B: 30,
|
@@ -143,6 +162,44 @@ class AgentResponse[R: BaseModel](BaseModel):
|
|
143
162
|
def total_cost(self) -> float:
|
144
163
|
return self.input_cost + self.output_cost
|
145
164
|
|
165
|
+
def minimized_dump(self) -> AgentResponseDump:
|
166
|
+
if self.system is None:
|
167
|
+
minimized_system_message = ""
|
168
|
+
else:
|
169
|
+
minimized_system_message = self.system.model_dump()
|
170
|
+
for part in minimized_system_message["parts"]:
|
171
|
+
if part["type"] == "image_url":
|
172
|
+
part["content"] = b"__MEDIA__"
|
173
|
+
|
174
|
+
minimized_input_messages = [
|
175
|
+
message.model_dump() for message in self.input_messages
|
176
|
+
]
|
177
|
+
for message in minimized_input_messages:
|
178
|
+
if message["type"] == "image_url":
|
179
|
+
message["content"] = b"__MEDIA__"
|
180
|
+
|
181
|
+
return {
|
182
|
+
"run_id": self.run_id,
|
183
|
+
"flow_name": self.flow_name,
|
184
|
+
"task_name": self.task_name,
|
185
|
+
"model": self.model.value,
|
186
|
+
"system_message": json.dumps(minimized_system_message),
|
187
|
+
"input_messages": json.dumps(minimized_input_messages),
|
188
|
+
"output_message": self.response.model_dump_json(),
|
189
|
+
"input_tokens": self.input_tokens,
|
190
|
+
"output_tokens": self.output_tokens,
|
191
|
+
"input_cost": self.input_cost,
|
192
|
+
"output_cost": self.output_cost,
|
193
|
+
"total_cost": self.total_cost,
|
194
|
+
"start_time": self.start_time,
|
195
|
+
"end_time": self.end_time,
|
196
|
+
"duration_ms": self.duration_ms,
|
197
|
+
}
|
198
|
+
|
199
|
+
|
200
|
+
class IAgentLogger(Protocol):
|
201
|
+
async def __call__(self, *, response: AgentResponse[Any]) -> None: ...
|
202
|
+
|
146
203
|
|
147
204
|
class Agent:
|
148
205
|
def __init__(
|
@@ -150,7 +207,7 @@ class Agent:
|
|
150
207
|
*,
|
151
208
|
flow_name: str,
|
152
209
|
run_id: str,
|
153
|
-
logger:
|
210
|
+
logger: IAgentLogger | None = None,
|
154
211
|
) -> None:
|
155
212
|
self.flow_name = flow_name
|
156
213
|
self.run_id = run_id
|
@@ -202,7 +259,7 @@ class Agent:
|
|
202
259
|
)
|
203
260
|
|
204
261
|
if self.logger is not None:
|
205
|
-
await self.logger(agent_response)
|
262
|
+
await self.logger(response=agent_response)
|
206
263
|
else:
|
207
264
|
logging.info(agent_response.model_dump())
|
208
265
|
|
goose/flow.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
import json
|
2
|
-
from contextlib import
|
2
|
+
from contextlib import asynccontextmanager
|
3
3
|
from contextvars import ContextVar
|
4
4
|
from typing import (
|
5
5
|
Any,
|
6
|
+
AsyncIterator,
|
6
7
|
Awaitable,
|
7
8
|
Callable,
|
8
|
-
Iterator,
|
9
9
|
NewType,
|
10
10
|
Protocol,
|
11
11
|
Self,
|
@@ -14,8 +14,16 @@ from typing import (
|
|
14
14
|
|
15
15
|
from pydantic import BaseModel, ConfigDict, field_validator
|
16
16
|
|
17
|
-
from goose.agent import
|
17
|
+
from goose.agent import (
|
18
|
+
Agent,
|
19
|
+
AssistantMessage,
|
20
|
+
IAgentLogger,
|
21
|
+
LLMMessage,
|
22
|
+
SystemMessage,
|
23
|
+
UserMessage,
|
24
|
+
)
|
18
25
|
from goose.errors import Honk
|
26
|
+
from goose.store import IFlowRunStore, InMemoryFlowRunStore
|
19
27
|
|
20
28
|
SerializedFlowRun = NewType("SerializedFlowRun", str)
|
21
29
|
|
@@ -174,11 +182,19 @@ class FlowRun:
|
|
174
182
|
last_input_hash=0,
|
175
183
|
)
|
176
184
|
|
177
|
-
def start(
|
185
|
+
def start(
|
186
|
+
self,
|
187
|
+
*,
|
188
|
+
flow_name: str,
|
189
|
+
run_id: str,
|
190
|
+
agent_logger: IAgentLogger | None = None,
|
191
|
+
) -> None:
|
178
192
|
self._last_requested_indices = {}
|
179
193
|
self._flow_name = flow_name
|
180
194
|
self._id = run_id
|
181
|
-
self._agent = Agent(
|
195
|
+
self._agent = Agent(
|
196
|
+
flow_name=self.flow_name, run_id=self.id, logger=agent_logger
|
197
|
+
)
|
182
198
|
|
183
199
|
def end(self) -> None:
|
184
200
|
self._last_requested_indices = {}
|
@@ -216,10 +232,18 @@ _current_flow_run: ContextVar[FlowRun | None] = ContextVar(
|
|
216
232
|
|
217
233
|
class Flow[**P]:
|
218
234
|
def __init__(
|
219
|
-
self,
|
235
|
+
self,
|
236
|
+
fn: Callable[P, Awaitable[None]],
|
237
|
+
/,
|
238
|
+
*,
|
239
|
+
store: IFlowRunStore | None = None,
|
240
|
+
name: str | None = None,
|
241
|
+
agent_logger: IAgentLogger | None = None,
|
220
242
|
) -> None:
|
221
243
|
self._fn = fn
|
222
244
|
self._name = name
|
245
|
+
self._agent_logger = agent_logger
|
246
|
+
self._store = store or InMemoryFlowRunStore(flow_name=self.name)
|
223
247
|
|
224
248
|
@property
|
225
249
|
def name(self) -> str:
|
@@ -232,20 +256,20 @@ class Flow[**P]:
|
|
232
256
|
raise Honk("No current flow run")
|
233
257
|
return run
|
234
258
|
|
235
|
-
@
|
236
|
-
def start_run(
|
237
|
-
|
238
|
-
|
239
|
-
if preload is None:
|
259
|
+
@asynccontextmanager
|
260
|
+
async def start_run(self, *, run_id: str) -> AsyncIterator[FlowRun]:
|
261
|
+
existing_run = await self._store.get(run_id=run_id)
|
262
|
+
if existing_run is None:
|
240
263
|
run = FlowRun()
|
241
264
|
else:
|
242
|
-
run =
|
265
|
+
run = existing_run
|
243
266
|
|
244
267
|
old_run = _current_flow_run.get()
|
245
268
|
_current_flow_run.set(run)
|
246
269
|
|
247
|
-
run.start(flow_name=self.name, run_id=run_id)
|
270
|
+
run.start(flow_name=self.name, run_id=run_id, agent_logger=self._agent_logger)
|
248
271
|
yield run
|
272
|
+
await self._store.save(run=run)
|
249
273
|
run.end()
|
250
274
|
|
251
275
|
_current_flow_run.set(old_run)
|
@@ -365,16 +389,20 @@ def task[**P, R: Result](
|
|
365
389
|
def flow[**P](fn: Callable[P, Awaitable[None]], /) -> Flow[P]: ...
|
366
390
|
@overload
|
367
391
|
def flow[**P](
|
368
|
-
*, name: str | None = None
|
392
|
+
*, name: str | None = None, agent_logger: IAgentLogger | None = None
|
369
393
|
) -> Callable[[Callable[P, Awaitable[None]]], Flow[P]]: ...
|
370
394
|
def flow[**P](
|
371
|
-
fn: Callable[P, Awaitable[None]] | None = None,
|
395
|
+
fn: Callable[P, Awaitable[None]] | None = None,
|
396
|
+
/,
|
397
|
+
*,
|
398
|
+
name: str | None = None,
|
399
|
+
agent_logger: IAgentLogger | None = None,
|
372
400
|
) -> Flow[P] | Callable[[Callable[P, Awaitable[None]]], Flow[P]]:
|
373
401
|
if fn is None:
|
374
402
|
|
375
403
|
def decorator(fn: Callable[P, Awaitable[None]]) -> Flow[P]:
|
376
|
-
return Flow(fn, name=name)
|
404
|
+
return Flow(fn, name=name, agent_logger=agent_logger)
|
377
405
|
|
378
406
|
return decorator
|
379
407
|
|
380
|
-
return Flow(fn, name=name)
|
408
|
+
return Flow(fn, name=name, agent_logger=agent_logger)
|
goose/store.py
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING, Protocol
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
from goose.flow import FlowRun
|
7
|
+
|
8
|
+
|
9
|
+
class IFlowRunStore(Protocol):
|
10
|
+
def __init__(self, *, flow_name: str) -> None: ...
|
11
|
+
async def get(self, *, run_id: str) -> FlowRun | None: ...
|
12
|
+
async def save(self, *, run: FlowRun) -> None: ...
|
13
|
+
|
14
|
+
|
15
|
+
class InMemoryFlowRunStore(IFlowRunStore):
|
16
|
+
def __init__(self, *, flow_name: str) -> None:
|
17
|
+
self._flow_name = flow_name
|
18
|
+
self._runs: dict[str, FlowRun] = {}
|
19
|
+
|
20
|
+
async def get(self, *, run_id: str) -> FlowRun | None:
|
21
|
+
return self._runs.get(run_id)
|
22
|
+
|
23
|
+
async def save(self, *, run: FlowRun) -> None:
|
24
|
+
self._runs[run.id] = run
|
@@ -0,0 +1,9 @@
|
|
1
|
+
goose/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
goose/agent.py,sha256=uCqHl5BKUX5niPbuZBOqtwnmHf8IZeBcOMylVLUfQlY,7453
|
3
|
+
goose/errors.py,sha256=-0OyZQJWYTRw5YgnCB2_uorVaUsL6Z0QYQO2FqzCiyg,32
|
4
|
+
goose/flow.py,sha256=I7iWizu6MPHOJYJL-ZQyjbgvjxECBJekibkfO0bGKX0,12490
|
5
|
+
goose/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
goose/store.py,sha256=6IIGkIYt6CWiNENi2gaS9C0Z-62ia-Qdz29HhCg8njw,698
|
7
|
+
goose_py-0.3.3.dist-info/METADATA,sha256=KAvJyHSN3cfcjFUVQCRCGSpwGxKqk76JMkNWZRPCH_g,1106
|
8
|
+
goose_py-0.3.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
9
|
+
goose_py-0.3.3.dist-info/RECORD,,
|
goose_py-0.3.1.dist-info/RECORD
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
goose/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
goose/agent.py,sha256=cJO6Jlh8En_FGLzjelm0w1pM4rsVqfIOpfKUdpkord4,5650
|
3
|
-
goose/errors.py,sha256=-0OyZQJWYTRw5YgnCB2_uorVaUsL6Z0QYQO2FqzCiyg,32
|
4
|
-
goose/flow.py,sha256=_ws3Jrp96E5UG7D0dgT0_c1RDs07H-hgJ0mSAmJf_yE,11735
|
5
|
-
goose/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
goose_py-0.3.1.dist-info/METADATA,sha256=wOP3QDcyVUJg-vjBw2KBb1xWdw_NA-50wgJtwg24WQc,1106
|
7
|
-
goose_py-0.3.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
8
|
-
goose_py-0.3.1.dist-info/RECORD,,
|
File without changes
|