flyteplugins-agents-hermes 2.5.17__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.
- flyteplugins/agents/hermes/__init__.py +19 -0
- flyteplugins/agents/hermes/_memory.py +53 -0
- flyteplugins/agents/hermes/_run.py +196 -0
- flyteplugins/agents/hermes/_tools.py +122 -0
- flyteplugins_agents_hermes-2.5.17.dist-info/METADATA +9 -0
- flyteplugins_agents_hermes-2.5.17.dist-info/RECORD +8 -0
- flyteplugins_agents_hermes-2.5.17.dist-info/WHEEL +5 -0
- flyteplugins_agents_hermes-2.5.17.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Hermes agent adapter for Flyte.
|
|
2
|
+
|
|
3
|
+
Bring your own Hermes agent (the ``hermes-agent`` package's ``AIAgent``) and
|
|
4
|
+
run it durably on Flyte. The adapter provides:
|
|
5
|
+
|
|
6
|
+
- :func:`tool` — turn a Flyte ``@env.task`` into a Hermes tool that executes as
|
|
7
|
+
a durable child action (own container/GPU, retries, caching), registered in
|
|
8
|
+
the Hermes tool registry under the :data:`FLYTE_TOOLSET` toolset.
|
|
9
|
+
- :func:`run_agent` — run the Hermes agent loop inside your task and return the
|
|
10
|
+
final answer.
|
|
11
|
+
|
|
12
|
+
Each tool call runs as a durable Flyte child action, and the run timeline is
|
|
13
|
+
rendered into the Flyte task report.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from ._run import run_agent, run_agent_sync
|
|
17
|
+
from ._tools import FLYTE_TOOLSET, tool
|
|
18
|
+
|
|
19
|
+
__all__ = ["FLYTE_TOOLSET", "run_agent", "run_agent_sync", "tool"]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Cross-run Hermes memory — a thin bridge over Flyte's keyed ``MemoryStore``.
|
|
2
|
+
|
|
3
|
+
Hermes keeps conversation state in-memory. This module persists the conversation
|
|
4
|
+
transcript to a durable, keyed :class:`~flyte.ai.agents.memory.MemoryStore` (an
|
|
5
|
+
object-store slot addressed by ``memory_key``) so a later run with the same key
|
|
6
|
+
continues the conversation — across workers and restarts.
|
|
7
|
+
|
|
8
|
+
The transcript is a plain list of ``{"role": ..., "content": ...}`` turns, stored
|
|
9
|
+
via ``read_json`` / ``write_json``.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import typing
|
|
15
|
+
|
|
16
|
+
from flyte._logging import logger
|
|
17
|
+
from flyteplugins.agents.core import resolve_memory as _resolve_memory
|
|
18
|
+
|
|
19
|
+
# Path-addressed slot holding the conversation transcript inside the MemoryStore.
|
|
20
|
+
_MEMORY_HISTORY_PATH = "hermes/history.json"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
async def resolve_memory(memory_key: str | None) -> typing.Any | None:
|
|
24
|
+
"""Resolve a keyed MemoryStore for Hermes cross-run memory, or ``None``.
|
|
25
|
+
|
|
26
|
+
Best-effort: returns ``None`` when ``memory_key`` is falsy or no durable
|
|
27
|
+
store can be resolved, so memory never breaks a run.
|
|
28
|
+
"""
|
|
29
|
+
if not memory_key:
|
|
30
|
+
return None
|
|
31
|
+
return await _resolve_memory(memory_key)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def load_transcript(store: typing.Any) -> list[dict[str, typing.Any]]:
|
|
35
|
+
"""Load the prior conversation transcript (empty list if none)."""
|
|
36
|
+
if store is None:
|
|
37
|
+
return []
|
|
38
|
+
try:
|
|
39
|
+
return list(await store.read_json.aio(_MEMORY_HISTORY_PATH, []))
|
|
40
|
+
except Exception: # pragma: no cover - memory is best-effort, never fatal
|
|
41
|
+
logger.warning("Could not load Hermes memory; continuing without prior history.")
|
|
42
|
+
return []
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async def save_transcript(store: typing.Any, transcript: typing.Sequence[dict[str, typing.Any]]) -> None:
|
|
46
|
+
"""Persist the conversation transcript back to the keyed store."""
|
|
47
|
+
if store is None:
|
|
48
|
+
return
|
|
49
|
+
try:
|
|
50
|
+
await store.write_json.aio(_MEMORY_HISTORY_PATH, list(transcript))
|
|
51
|
+
await store.save.aio()
|
|
52
|
+
except Exception: # pragma: no cover - memory is best-effort, never fatal
|
|
53
|
+
logger.warning("Could not persist Hermes memory; continuing.")
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""``run_agent`` — run a Hermes (``hermes-agent``) agent on Flyte.
|
|
2
|
+
|
|
3
|
+
Hermes owns the agent loop: its ``AIAgent`` (the ``run_agent`` top-level module
|
|
4
|
+
of the ``hermes-agent`` package) drives the model and dispatches tools from a
|
|
5
|
+
process-global registry. ``run_agent`` runs that loop inside your ``@env.task``:
|
|
6
|
+
it builds an ``AIAgent`` scoped to exactly the Flyte-task tools you pass (via a
|
|
7
|
+
custom Hermes toolset), drives ``AIAgent.run_conversation`` (a blocking call,
|
|
8
|
+
bridged off the event loop with ``asyncio.to_thread``), and returns the final
|
|
9
|
+
answer. Each tool call runs as a durable Flyte child action (its own
|
|
10
|
+
container/resources, with retries and caching).
|
|
11
|
+
|
|
12
|
+
Observability: the run timeline is rendered into the Flyte task report.
|
|
13
|
+
|
|
14
|
+
The adapter minimizes delta between native Hermes code and Flyte integration:
|
|
15
|
+
bring your own pre-configured ``AIAgent`` (with ``enabled_toolsets`` including
|
|
16
|
+
:data:`~flyteplugins.agents.hermes.FLYTE_TOOLSET`) or let ``run_agent`` build
|
|
17
|
+
one from ``tools`` + ``model``.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import asyncio
|
|
23
|
+
import inspect
|
|
24
|
+
import os
|
|
25
|
+
import re
|
|
26
|
+
import typing
|
|
27
|
+
|
|
28
|
+
from flyteplugins.agents.core import ReportTimeline, flush_report, sync_variant
|
|
29
|
+
|
|
30
|
+
from ._memory import load_transcript, resolve_memory, save_transcript
|
|
31
|
+
from ._tools import tool
|
|
32
|
+
|
|
33
|
+
if typing.TYPE_CHECKING:
|
|
34
|
+
from run_agent import AIAgent as _AIAgent # hermes-agent's top-level module
|
|
35
|
+
else:
|
|
36
|
+
_AIAgent = None
|
|
37
|
+
|
|
38
|
+
_OPENAI_BASE_URL = "https://api.openai.com/v1"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _coerce_tool(t: typing.Any) -> typing.Any:
|
|
42
|
+
"""Route anything not already Hermes-registered through :func:`tool`."""
|
|
43
|
+
if getattr(t, "__hermes_registered__", False):
|
|
44
|
+
return t
|
|
45
|
+
return tool(t)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _scoped_toolset(agent_name: str, registered: typing.Sequence[typing.Any]) -> str:
|
|
49
|
+
"""Create (or refresh) a Hermes toolset holding exactly this agent's tools.
|
|
50
|
+
|
|
51
|
+
:func:`tool` registers every tool under the shared ``FLYTE_TOOLSET``; scoping
|
|
52
|
+
each built agent to a named subset keeps two agents in one process from
|
|
53
|
+
seeing each other's tools.
|
|
54
|
+
"""
|
|
55
|
+
from toolsets import create_custom_toolset # hermes-agent
|
|
56
|
+
|
|
57
|
+
toolset = f"flyte-{re.sub(r'[^A-Za-z0-9_-]+', '-', agent_name).strip('-') or 'agent'}"
|
|
58
|
+
names = [getattr(t, "__name__", str(t)) for t in registered]
|
|
59
|
+
create_custom_toolset(toolset, f"Flyte tools for agent {agent_name!r}", tools=names)
|
|
60
|
+
return toolset
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async def run_agent(
|
|
64
|
+
input: str,
|
|
65
|
+
*,
|
|
66
|
+
tools: typing.Sequence[typing.Any] = (),
|
|
67
|
+
model: str | None = None,
|
|
68
|
+
instructions: str | None = None,
|
|
69
|
+
agent: typing.Any = None,
|
|
70
|
+
name: str = "hermes-agent",
|
|
71
|
+
durable: bool = True,
|
|
72
|
+
observability: bool = True,
|
|
73
|
+
memory_key: str | None = None,
|
|
74
|
+
**agent_kwargs: typing.Any,
|
|
75
|
+
) -> str:
|
|
76
|
+
"""Run a Hermes agent with the given tools and prompt; return the final text.
|
|
77
|
+
|
|
78
|
+
Await this from an async task as ``await run_agent(...)``; from a sync task
|
|
79
|
+
use :func:`run_agent_sync` instead.
|
|
80
|
+
|
|
81
|
+
Call this from inside an ``@env.task`` — that task is the durable parent.
|
|
82
|
+
Within it, each tool call runs as a durable Flyte child action. Give the
|
|
83
|
+
enclosing task ``retries=...`` for self-healing and ``report=True`` to see
|
|
84
|
+
the agent timeline.
|
|
85
|
+
|
|
86
|
+
Provide either a pre-built ``agent`` (an ``AIAgent`` with its own
|
|
87
|
+
``enabled_toolsets``) or ``tools`` + ``model`` to have one built for you.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
input: The user prompt.
|
|
91
|
+
tools: ``tool``-wrapped tools or bare ``@env.task`` templates.
|
|
92
|
+
agent: A pre-built Hermes ``AIAgent``. Mutually exclusive with ``tools``.
|
|
93
|
+
model: Model name for the built agent. Required when ``agent`` is not
|
|
94
|
+
given (there is no default model).
|
|
95
|
+
instructions: System prompt. On the builder path this becomes the
|
|
96
|
+
agent's ``ephemeral_system_prompt``; with a pre-built agent it is
|
|
97
|
+
passed as this run's ``system_message``.
|
|
98
|
+
name: Agent name (used for the scoped toolset and observability).
|
|
99
|
+
durable: Accepted for the shared adapter contract, but currently a
|
|
100
|
+
no-op for Hermes: ``hermes-agent`` exposes no per-model-turn hook
|
|
101
|
+
(the model client is buried inside ``AIAgent``), so completed model
|
|
102
|
+
turns cannot be recorded/replayed via ``flyte.trace`` the way the
|
|
103
|
+
openai/langchain adapters do. Tool calls are durable regardless —
|
|
104
|
+
each runs as a Flyte child action with retries and caching — so a
|
|
105
|
+
retried task still self-heals at tool granularity.
|
|
106
|
+
observability: Render the run timeline into the Flyte task report.
|
|
107
|
+
memory_key: Stable id (e.g. a user/thread id) for cross-run memory.
|
|
108
|
+
When set, conversation history is persisted to a keyed ``MemoryStore``
|
|
109
|
+
and resumed on a later run with the same key (passed to Hermes as
|
|
110
|
+
``conversation_history``).
|
|
111
|
+
**agent_kwargs: Extra keyword arguments for the built ``AIAgent``
|
|
112
|
+
(e.g. ``api_key=``, ``base_url=``, ``provider=``,
|
|
113
|
+
``max_iterations=``). Only valid on the builder path. When none of
|
|
114
|
+
``api_key``/``base_url``/``provider`` are given and
|
|
115
|
+
``OPENAI_API_KEY`` is set, the built agent is pointed at OpenAI
|
|
116
|
+
with that key (Hermes otherwise only reads credentials from its own
|
|
117
|
+
``hermes setup`` config, which a fresh container doesn't have).
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
The agent's final output as a string.
|
|
121
|
+
"""
|
|
122
|
+
timeline = ReportTimeline() if observability else None
|
|
123
|
+
if timeline is not None:
|
|
124
|
+
timeline.heading("Hermes agent")
|
|
125
|
+
|
|
126
|
+
if agent is not None and tools:
|
|
127
|
+
raise ValueError("Pass either `agent` (with its own tools) or `tools`, not both.")
|
|
128
|
+
if agent is not None and agent_kwargs:
|
|
129
|
+
raise ValueError("`**agent_kwargs` configure the built agent; don't pass them with a pre-built `agent=`.")
|
|
130
|
+
|
|
131
|
+
# Cross-run memory: load the prior transcript (if any) and resume the thread.
|
|
132
|
+
store = await resolve_memory(memory_key)
|
|
133
|
+
history = await load_transcript(store)
|
|
134
|
+
|
|
135
|
+
system_message: str | None = None
|
|
136
|
+
if agent is None:
|
|
137
|
+
if model is None:
|
|
138
|
+
raise ValueError("Provide `model=` when building the agent (or pass a pre-built `agent=`).")
|
|
139
|
+
|
|
140
|
+
if _AIAgent is None:
|
|
141
|
+
from run_agent import AIAgent as _HermesAgent # hermes-agent's top-level module
|
|
142
|
+
else:
|
|
143
|
+
_HermesAgent = _AIAgent
|
|
144
|
+
|
|
145
|
+
enabled_toolsets: list[str] = []
|
|
146
|
+
if tools:
|
|
147
|
+
registered = [_coerce_tool(t) for t in tools]
|
|
148
|
+
enabled_toolsets = [_scoped_toolset(name, registered)]
|
|
149
|
+
|
|
150
|
+
has_credentials = any(k in agent_kwargs for k in ("api_key", "base_url", "provider"))
|
|
151
|
+
if not has_credentials and os.environ.get("OPENAI_API_KEY"):
|
|
152
|
+
agent_kwargs["api_key"] = os.environ["OPENAI_API_KEY"]
|
|
153
|
+
agent_kwargs["base_url"] = _OPENAI_BASE_URL
|
|
154
|
+
|
|
155
|
+
agent = _HermesAgent(
|
|
156
|
+
model=model,
|
|
157
|
+
ephemeral_system_prompt=instructions or f"You are a helpful assistant named {name}.",
|
|
158
|
+
enabled_toolsets=enabled_toolsets,
|
|
159
|
+
quiet_mode=True,
|
|
160
|
+
**agent_kwargs,
|
|
161
|
+
)
|
|
162
|
+
else:
|
|
163
|
+
# A pre-built agent keeps its own prompt; explicit instructions ride
|
|
164
|
+
# along as this run's system message.
|
|
165
|
+
system_message = instructions
|
|
166
|
+
|
|
167
|
+
# Drive the agent. ``run_conversation`` is synchronous (Hermes bridges its
|
|
168
|
+
# async tool handlers internally), so run it off the event loop;
|
|
169
|
+
# ``to_thread`` propagates the Flyte task context into the worker thread.
|
|
170
|
+
call_kwargs: dict[str, typing.Any] = {}
|
|
171
|
+
if system_message:
|
|
172
|
+
call_kwargs["system_message"] = system_message
|
|
173
|
+
if history:
|
|
174
|
+
call_kwargs["conversation_history"] = list(history)
|
|
175
|
+
|
|
176
|
+
result = await asyncio.to_thread(lambda: agent.run_conversation(input, **call_kwargs))
|
|
177
|
+
if inspect.isawaitable(result): # tolerate async fakes/wrappers
|
|
178
|
+
result = await result
|
|
179
|
+
|
|
180
|
+
final = result.get("final_response") if isinstance(result, dict) else result
|
|
181
|
+
final = str(final) if final is not None else ""
|
|
182
|
+
|
|
183
|
+
# Persist the updated transcript for the next run with this memory_key.
|
|
184
|
+
if store is not None:
|
|
185
|
+
await save_transcript(
|
|
186
|
+
store,
|
|
187
|
+
[*history, {"role": "user", "content": input}, {"role": "assistant", "content": final}],
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
if observability:
|
|
191
|
+
await flush_report()
|
|
192
|
+
|
|
193
|
+
return final
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
run_agent_sync = sync_variant(run_agent)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Turn Flyte tasks into Hermes tools that execute as durable actions.
|
|
2
|
+
|
|
3
|
+
Hermes (the ``hermes-agent`` package) does not accept tool callables on the
|
|
4
|
+
agent object. Tools live in a process-global registry (``tools.registry``),
|
|
5
|
+
keyed by name and grouped into *toolsets*; an ``AIAgent`` exposes whatever its
|
|
6
|
+
``enabled_toolsets`` resolve to. :func:`tool` therefore does two things:
|
|
7
|
+
|
|
8
|
+
1. wraps the Flyte ``@env.task`` with the shared core wrapper
|
|
9
|
+
(:func:`flyteplugins.agents.core.tool`) so a call dispatches to
|
|
10
|
+
``task.aio()`` — a durable Flyte child action (its own container/resources,
|
|
11
|
+
with retries and caching) — and the backing task resolves to itself on the
|
|
12
|
+
worker;
|
|
13
|
+
2. registers that wrapper in the Hermes tool registry under the
|
|
14
|
+
:data:`FLYTE_TOOLSET` toolset, with an OpenAI-format schema derived from the
|
|
15
|
+
task via the Flyte type engine.
|
|
16
|
+
|
|
17
|
+
``run_agent`` then scopes each built agent to exactly the requested tools via a
|
|
18
|
+
custom toolset (see ``_run``); a bring-your-own ``AIAgent`` opts in with
|
|
19
|
+
``enabled_toolsets=[FLYTE_TOOLSET]``.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import inspect
|
|
25
|
+
import json
|
|
26
|
+
import typing
|
|
27
|
+
from functools import partial
|
|
28
|
+
|
|
29
|
+
from flyte._task import AsyncFunctionTaskTemplate
|
|
30
|
+
from flyte.models import NativeInterface
|
|
31
|
+
from flyteplugins.agents.core import task_json_schema
|
|
32
|
+
from flyteplugins.agents.core import tool as core_tool
|
|
33
|
+
|
|
34
|
+
FLYTE_TOOLSET = "flyte"
|
|
35
|
+
"""The Hermes toolset every Flyte ``tool`` registers under."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def tool(
|
|
39
|
+
func: AsyncFunctionTaskTemplate | typing.Callable | None = None,
|
|
40
|
+
*,
|
|
41
|
+
name: str | None = None,
|
|
42
|
+
description: str | None = None,
|
|
43
|
+
) -> typing.Any:
|
|
44
|
+
"""Convert a Flyte task (or plain callable) into a Hermes tool.
|
|
45
|
+
|
|
46
|
+
- For an ``@env.task``: returns the shared core tool wrapper (a plain async
|
|
47
|
+
function dispatching to the task as a durable Flyte child action, with
|
|
48
|
+
``__wrapped_task__`` and the resolver wired), *and* registers it in the
|
|
49
|
+
Hermes tool registry under :data:`FLYTE_TOOLSET` so an ``AIAgent`` can
|
|
50
|
+
call it by name. The input schema is derived from the task via the Flyte
|
|
51
|
+
type engine.
|
|
52
|
+
- For a plain (sync or async) callable: registers it as an inline Hermes
|
|
53
|
+
tool, deriving the schema from its signature.
|
|
54
|
+
|
|
55
|
+
Usable bare, parametrized, or as a direct call::
|
|
56
|
+
|
|
57
|
+
@tool
|
|
58
|
+
@env.task
|
|
59
|
+
async def get_weather(city: str) -> str: ...
|
|
60
|
+
"""
|
|
61
|
+
if func is None:
|
|
62
|
+
return partial(tool, name=name, description=description)
|
|
63
|
+
|
|
64
|
+
wrapper = core_tool(func, name=name, description=description)
|
|
65
|
+
tool_name = getattr(wrapper, "__name__", None) or type(wrapper).__name__
|
|
66
|
+
|
|
67
|
+
if isinstance(func, AsyncFunctionTaskTemplate):
|
|
68
|
+
desc = (description or func.func.__doc__ or f"Run {tool_name}").strip()
|
|
69
|
+
parameters = task_json_schema(func)
|
|
70
|
+
else:
|
|
71
|
+
desc = (description or getattr(func, "__doc__", None) or f"Run {tool_name}").strip()
|
|
72
|
+
parameters = NativeInterface.from_callable(func).json_schema
|
|
73
|
+
|
|
74
|
+
_register_hermes_tool(tool_name, desc, parameters, wrapper)
|
|
75
|
+
try:
|
|
76
|
+
wrapper.__hermes_registered__ = True
|
|
77
|
+
except (AttributeError, TypeError): # pragma: no cover - slotted/immutable callable
|
|
78
|
+
pass
|
|
79
|
+
return wrapper
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _register_hermes_tool(
|
|
83
|
+
tool_name: str,
|
|
84
|
+
description: str,
|
|
85
|
+
parameters: dict[str, typing.Any],
|
|
86
|
+
wrapper: typing.Callable,
|
|
87
|
+
) -> None:
|
|
88
|
+
"""Register ``wrapper`` in the Hermes tool registry under :data:`FLYTE_TOOLSET`.
|
|
89
|
+
|
|
90
|
+
The handler receives the model's arguments as a dict (Hermes dispatches
|
|
91
|
+
``handler(args, **context)``) and returns a string for the model. Re-registering
|
|
92
|
+
the same name replaces the previous entry, so module reloads are safe.
|
|
93
|
+
"""
|
|
94
|
+
from tools.registry import registry # hermes-agent's process-global tool registry
|
|
95
|
+
|
|
96
|
+
async def _handler(args: dict[str, typing.Any] | None = None, **_: typing.Any) -> str:
|
|
97
|
+
out = wrapper(**(args or {}))
|
|
98
|
+
if inspect.isawaitable(out):
|
|
99
|
+
out = await out
|
|
100
|
+
return _as_content(out)
|
|
101
|
+
|
|
102
|
+
registry.register(
|
|
103
|
+
name=tool_name,
|
|
104
|
+
toolset=FLYTE_TOOLSET,
|
|
105
|
+
schema={
|
|
106
|
+
"type": "function",
|
|
107
|
+
"function": {"name": tool_name, "description": description, "parameters": parameters},
|
|
108
|
+
},
|
|
109
|
+
handler=_handler,
|
|
110
|
+
is_async=True,
|
|
111
|
+
description=description,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _as_content(result: typing.Any) -> str:
|
|
116
|
+
"""Convert a tool result to a string for the model."""
|
|
117
|
+
if isinstance(result, str):
|
|
118
|
+
return result
|
|
119
|
+
try:
|
|
120
|
+
return json.dumps(result, default=str)
|
|
121
|
+
except (TypeError, ValueError):
|
|
122
|
+
return str(result)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flyteplugins-agents-hermes
|
|
3
|
+
Version: 2.5.17
|
|
4
|
+
Summary: Run Hermes agent on Flyte.
|
|
5
|
+
Author-email: Niels Bantilan <niels@union.ai>
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: flyteplugins-agents-core
|
|
9
|
+
Requires-Dist: hermes-agent
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
flyteplugins/agents/hermes/__init__.py,sha256=lDU18HA4WedhsEJ_KKZGRaVVmPXDQVfcHCx-KSbm5Ws,759
|
|
2
|
+
flyteplugins/agents/hermes/_memory.py,sha256=NHTnsdrZ44XhZO2gs6V3mYaaP--fAnhupj1cp1izwMQ,2112
|
|
3
|
+
flyteplugins/agents/hermes/_run.py,sha256=eVfs3YZnmQDYkxC_OunaYrcj_ofyd4Mql9y0uZfb24M,8394
|
|
4
|
+
flyteplugins/agents/hermes/_tools.py,sha256=MnDvPFUh0Tx_mPYjV0TPWyaeveCkREPuwoVKjGkclZE,4594
|
|
5
|
+
flyteplugins_agents_hermes-2.5.17.dist-info/METADATA,sha256=RpbKppFN0p49egiOOT0iQeVR3QBLYDGc_YaG3jORFCI,285
|
|
6
|
+
flyteplugins_agents_hermes-2.5.17.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
7
|
+
flyteplugins_agents_hermes-2.5.17.dist-info/top_level.txt,sha256=cgd779rPu9EsvdtuYgUxNHHgElaQvPn74KhB5XSeMBE,13
|
|
8
|
+
flyteplugins_agents_hermes-2.5.17.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
flyteplugins
|