goose-py 0.11.0__py3-none-any.whl → 0.11.2__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/_internal/agent.py CHANGED
@@ -6,10 +6,10 @@ from aikernel import (
6
6
  LLMAssistantMessage,
7
7
  LLMModel,
8
8
  LLMSystemMessage,
9
+ LLMToolMessage,
9
10
  LLMUserMessage,
10
11
  llm_structured,
11
12
  llm_unstructured,
12
- render_message,
13
13
  )
14
14
  from pydantic import ValidationError
15
15
 
@@ -17,6 +17,8 @@ from goose._internal.result import FindReplaceResponse, Result, TextResult
17
17
  from goose._internal.types.telemetry import AgentResponse
18
18
  from goose.errors import Honk
19
19
 
20
+ ExpectedMessage = LLMUserMessage | LLMAssistantMessage | LLMSystemMessage | LLMToolMessage
21
+
20
22
 
21
23
  class IAgentLogger(Protocol):
22
24
  async def __call__(self, *, response: AgentResponse[Any]) -> None: ...
@@ -43,22 +45,23 @@ class Agent:
43
45
  response_model: type[R] = TextResult,
44
46
  ) -> R:
45
47
  start_time = datetime.now()
48
+ typed_messages: list[ExpectedMessage] = [*messages]
46
49
 
47
50
  if response_model is TextResult:
48
- response = await llm_unstructured(model=model, messages=messages)
51
+ response = await llm_unstructured(model=model, messages=typed_messages)
49
52
  parsed_response = response_model.model_validate({"text": response.text})
50
53
  else:
51
- response = await llm_structured(model=model, messages=messages, response_model=response_model)
54
+ response = await llm_structured(model=model, messages=typed_messages, response_model=response_model)
52
55
  parsed_response = response.structured_response
53
56
 
54
57
  end_time = datetime.now()
55
58
 
56
59
  if isinstance(messages[0], LLMSystemMessage):
57
- system = render_message(messages[0])
58
- input_messages = [render_message(message) for message in messages[1:]]
60
+ system = messages[0].render()
61
+ input_messages = [message.render() for message in messages[1:]]
59
62
  else:
60
63
  system = None
61
- input_messages = [render_message(message) for message in messages]
64
+ input_messages = [message.render() for message in messages]
62
65
 
63
66
  agent_response = AgentResponse(
64
67
  response=parsed_response,
@@ -89,15 +92,16 @@ class Agent:
89
92
  task_name: str,
90
93
  ) -> str:
91
94
  start_time = datetime.now()
92
- response = await llm_unstructured(model=model, messages=messages)
95
+ typed_messages: list[ExpectedMessage] = [*messages]
96
+ response = await llm_unstructured(model=model, messages=typed_messages)
93
97
  end_time = datetime.now()
94
98
 
95
99
  if isinstance(messages[0], LLMSystemMessage):
96
- system = render_message(messages[0])
97
- input_messages = [render_message(message) for message in messages[1:]]
100
+ system = messages[0].render()
101
+ input_messages = [message.render() for message in messages[1:]]
98
102
  else:
99
103
  system = None
100
- input_messages = [render_message(message) for message in messages]
104
+ input_messages = [message.render() for message in messages]
101
105
 
102
106
  agent_response = AgentResponse(
103
107
  response=response.text,
@@ -129,16 +133,19 @@ class Agent:
129
133
  response_model: type[R],
130
134
  ) -> R:
131
135
  start_time = datetime.now()
132
- find_replace_response = await llm_structured(model=model, messages=messages, response_model=FindReplaceResponse)
136
+ typed_messages: list[ExpectedMessage] = [*messages]
137
+ find_replace_response = await llm_structured(
138
+ model=model, messages=typed_messages, response_model=FindReplaceResponse
139
+ )
133
140
  parsed_find_replace_response = find_replace_response.structured_response
134
141
  end_time = datetime.now()
135
142
 
136
143
  if isinstance(messages[0], LLMSystemMessage):
137
- system = render_message(messages[0])
138
- input_messages = [render_message(message) for message in messages[1:]]
144
+ system = messages[0].render()
145
+ input_messages = [message.render() for message in messages[1:]]
139
146
  else:
140
147
  system = None
141
- input_messages = [render_message(message) for message in messages]
148
+ input_messages = [message.render() for message in messages]
142
149
 
143
150
  agent_response = AgentResponse(
144
151
  response=parsed_find_replace_response,
goose/_internal/state.py CHANGED
@@ -2,7 +2,7 @@ import json
2
2
  from contextvars import ContextVar
3
3
  from typing import TYPE_CHECKING, Any, NewType, Self
4
4
 
5
- from aikernel import LLMAssistantMessage, LLMSystemMessage, LLMUserMessage
5
+ from aikernel import LLMAssistantMessage, LLMMessagePart, LLMSystemMessage, LLMUserMessage
6
6
  from pydantic import BaseModel, ConfigDict
7
7
 
8
8
  from goose._internal.agent import Agent, IAgentLogger
@@ -46,15 +46,15 @@ class NodeState(BaseModel):
46
46
  overwrite: bool = False,
47
47
  ) -> Self:
48
48
  if overwrite and len(self.conversation.assistant_messages) > 0:
49
- self.conversation.assistant_messages[-1] = LLMAssistantMessage.from_text(result)
49
+ self.conversation.assistant_messages[-1] = LLMAssistantMessage(parts=[LLMMessagePart(content=result)])
50
50
  else:
51
- self.conversation.assistant_messages.append(LLMAssistantMessage.from_text(result))
51
+ self.conversation.assistant_messages.append(LLMAssistantMessage(parts=[LLMMessagePart(content=result)]))
52
52
  if new_hash is not None:
53
53
  self.last_hash = new_hash
54
54
  return self
55
55
 
56
56
  def add_answer(self, *, answer: str) -> Self:
57
- self.conversation.assistant_messages.append(LLMAssistantMessage.from_text(answer))
57
+ self.conversation.assistant_messages.append(LLMAssistantMessage(parts=[LLMMessagePart(content=answer)]))
58
58
  return self
59
59
 
60
60
  def add_user_message(self, *, message: LLMUserMessage) -> Self:
@@ -68,7 +68,9 @@ class NodeState(BaseModel):
68
68
  for message_index, message in enumerate(reversed(self.conversation.assistant_messages)):
69
69
  if self.__message_is_result(message):
70
70
  index = len(self.conversation.assistant_messages) - message_index - 1
71
- self.conversation.assistant_messages[index] = LLMAssistantMessage.from_text(result)
71
+ self.conversation.assistant_messages[index] = LLMAssistantMessage(
72
+ parts=[LLMMessagePart(content=result)]
73
+ )
72
74
  return self
73
75
 
74
76
  raise Honk("Node awaiting response, has no result")
@@ -5,6 +5,8 @@ from typing import ClassVar, TypedDict
5
5
  from aikernel import LiteLLMMessage, LLMModel
6
6
  from pydantic import BaseModel, computed_field
7
7
 
8
+ from goose.errors import Honk
9
+
8
10
 
9
11
  class AgentResponseDump(TypedDict):
10
12
  run_id: str
@@ -77,15 +79,18 @@ class AgentResponse[R: BaseModel | str](BaseModel):
77
79
  def minimized_dump(self) -> AgentResponseDump:
78
80
  if self.system is None:
79
81
  minimized_system_message = ""
82
+ elif self.system["role"] == "tool" or not isinstance(self.system["content"], list):
83
+ raise Honk("System message cannot use tools")
80
84
  else:
81
- minimized_system_message = self.system
82
- for part in minimized_system_message["content"]:
85
+ for part in self.system["content"]:
83
86
  if part["type"] == "image_url":
84
87
  part["image_url"] = "__MEDIA__"
85
- minimized_system_message = json.dumps(minimized_system_message)
88
+ minimized_system_message = json.dumps(self.system)
86
89
 
87
90
  minimized_input_messages = [message for message in self.input_messages]
88
91
  for message in minimized_input_messages:
92
+ if message["role"] == "tool" or not isinstance(message["content"], list):
93
+ raise Honk("Input messages cannot use tools")
89
94
  for part in message["content"]:
90
95
  if part["type"] == "image_url":
91
96
  part["image_url"] = "__MEDIA__"
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: goose-py
3
- Version: 0.11.0
3
+ Version: 0.11.2
4
4
  Summary: A tool for AI workflows based on human-computer collaboration and structured output.
5
5
  Author-email: Nash Taylor <nash@chelle.ai>, Joshua Cook <joshua@chelle.ai>, Michael Sankur <michael@chelle.ai>
6
6
  Requires-Python: >=3.12
7
- Requires-Dist: aikernel>=0.1.5
7
+ Requires-Dist: aikernel>=0.1.22
8
8
  Requires-Dist: jsonpath-ng>=1.7.0
9
9
  Requires-Dist: pydantic>=2.8.2
10
10
  Description-Content-Type: text/markdown
@@ -4,15 +4,15 @@ goose/flow.py,sha256=YsZLBa5I1W27_P6LYGWbtFX8ZYx9vJG3KtENYChHm5E,111
4
4
  goose/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  goose/runs.py,sha256=ub-r_gzbUbaIzWXX-jc-dncNxEh6zTfzIkmnDfCSbRI,160
6
6
  goose/task.py,sha256=95rspdxETJoY12IHBl3KjnVIdqQnf1jDKlnGWNWOTvQ,53
7
- goose/_internal/agent.py,sha256=hpg8xXo7lhFDE3ezr8C0-BC61xWoXl1KChxu2n9o8Aw,8449
7
+ goose/_internal/agent.py,sha256=qDPPsOuvTkUpaKXV5aVTIn_yWUs_XZyHDPJaIq49YAI,8704
8
8
  goose/_internal/conversation.py,sha256=vhJwe1pHk2lV60DaB9Tz9KbpzQo7_thRYInPjbIoUTE,1437
9
9
  goose/_internal/flow.py,sha256=8MJxlhHYSAzUHZefpF_sRJc37o532OF0X7l3KRopDmc,4115
10
10
  goose/_internal/result.py,sha256=vtJMfBxb9skfl8st2tn4hBmEq6qmXiJTme_B5QTgu2M,538
11
- goose/_internal/state.py,sha256=jGKKZKeDcKaCY-uqgXLOnMNwyzR5qEH5m9afOtixsLk,7923
11
+ goose/_internal/state.py,sha256=kA116MpsetsQz6nYodsXOqE3uYz37OTgjC9Vcy_3Qvg,8065
12
12
  goose/_internal/store.py,sha256=tWmKfa1-yq1jU6lT3l6kSOmVt2m3H7I1xLMTrxnUDI8,889
13
13
  goose/_internal/task.py,sha256=X_eRZxZlf6SwyvF1nIyjoneyqD_TISXqESyxluk63mE,6416
14
14
  goose/_internal/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- goose/_internal/types/telemetry.py,sha256=wDQz1C60KxlftC0aQCXIjswrSYGI1KNaM2wtnlP1Q7k,3823
16
- goose_py-0.11.0.dist-info/METADATA,sha256=LZvLxXhKOj-edk54qSemq8dxnplsUmSzPRPIrmAxO-w,442
17
- goose_py-0.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
- goose_py-0.11.0.dist-info/RECORD,,
15
+ goose/_internal/types/telemetry.py,sha256=xTJCJo-TW9Pd5QK983HMw9CqJ7vw-BLUkYkbantIP30,4075
16
+ goose_py-0.11.2.dist-info/METADATA,sha256=I9TPDZ7ERKKn26HLIWKyWXuyHnjSifMFlxiRloXkDPU,443
17
+ goose_py-0.11.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
+ goose_py-0.11.2.dist-info/RECORD,,