aethergraph 0.1.0a1__py3-none-any.whl → 0.1.0a3__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.
- aethergraph/__init__.py +4 -10
- aethergraph/__main__.py +296 -0
- aethergraph/api/v1/__init__.py +0 -0
- aethergraph/api/v1/agents.py +46 -0
- aethergraph/api/v1/apps.py +70 -0
- aethergraph/api/v1/artifacts.py +415 -0
- aethergraph/api/v1/channels.py +89 -0
- aethergraph/api/v1/deps.py +168 -0
- aethergraph/api/v1/graphs.py +259 -0
- aethergraph/api/v1/identity.py +25 -0
- aethergraph/api/v1/memory.py +353 -0
- aethergraph/api/v1/misc.py +47 -0
- aethergraph/api/v1/pagination.py +29 -0
- aethergraph/api/v1/runs.py +568 -0
- aethergraph/api/v1/schemas.py +535 -0
- aethergraph/api/v1/session.py +323 -0
- aethergraph/api/v1/stats.py +201 -0
- aethergraph/api/v1/viz.py +152 -0
- aethergraph/config/config.py +22 -0
- aethergraph/config/loader.py +3 -2
- aethergraph/config/storage.py +209 -0
- aethergraph/contracts/__init__.py +0 -0
- aethergraph/contracts/services/__init__.py +0 -0
- aethergraph/contracts/services/artifacts.py +27 -14
- aethergraph/contracts/services/memory.py +45 -17
- aethergraph/contracts/services/metering.py +129 -0
- aethergraph/contracts/services/runs.py +50 -0
- aethergraph/contracts/services/sessions.py +87 -0
- aethergraph/contracts/services/state_stores.py +3 -0
- aethergraph/contracts/services/viz.py +44 -0
- aethergraph/contracts/storage/artifact_index.py +88 -0
- aethergraph/contracts/storage/artifact_store.py +99 -0
- aethergraph/contracts/storage/async_kv.py +34 -0
- aethergraph/contracts/storage/blob_store.py +50 -0
- aethergraph/contracts/storage/doc_store.py +35 -0
- aethergraph/contracts/storage/event_log.py +31 -0
- aethergraph/contracts/storage/vector_index.py +48 -0
- aethergraph/core/__init__.py +0 -0
- aethergraph/core/execution/forward_scheduler.py +13 -2
- aethergraph/core/execution/global_scheduler.py +21 -15
- aethergraph/core/execution/step_forward.py +10 -1
- aethergraph/core/graph/__init__.py +0 -0
- aethergraph/core/graph/graph_builder.py +8 -4
- aethergraph/core/graph/graph_fn.py +156 -15
- aethergraph/core/graph/graph_spec.py +8 -0
- aethergraph/core/graph/graphify.py +146 -27
- aethergraph/core/graph/node_spec.py +0 -2
- aethergraph/core/graph/node_state.py +3 -0
- aethergraph/core/graph/task_graph.py +39 -1
- aethergraph/core/runtime/__init__.py +0 -0
- aethergraph/core/runtime/ad_hoc_context.py +64 -4
- aethergraph/core/runtime/base_service.py +28 -4
- aethergraph/core/runtime/execution_context.py +13 -15
- aethergraph/core/runtime/graph_runner.py +222 -37
- aethergraph/core/runtime/node_context.py +510 -6
- aethergraph/core/runtime/node_services.py +12 -5
- aethergraph/core/runtime/recovery.py +15 -1
- aethergraph/core/runtime/run_manager.py +783 -0
- aethergraph/core/runtime/run_manager_local.py +204 -0
- aethergraph/core/runtime/run_registration.py +2 -2
- aethergraph/core/runtime/run_types.py +89 -0
- aethergraph/core/runtime/runtime_env.py +136 -7
- aethergraph/core/runtime/runtime_metering.py +71 -0
- aethergraph/core/runtime/runtime_registry.py +36 -13
- aethergraph/core/runtime/runtime_services.py +194 -6
- aethergraph/core/tools/builtins/toolset.py +1 -1
- aethergraph/core/tools/toolkit.py +5 -0
- aethergraph/plugins/agents/default_chat_agent copy.py +90 -0
- aethergraph/plugins/agents/default_chat_agent.py +171 -0
- aethergraph/plugins/agents/shared.py +81 -0
- aethergraph/plugins/channel/adapters/webui.py +112 -112
- aethergraph/plugins/channel/routes/webui_routes.py +367 -102
- aethergraph/plugins/channel/utils/slack_utils.py +115 -59
- aethergraph/plugins/channel/utils/telegram_utils.py +88 -47
- aethergraph/plugins/channel/websockets/weibui_ws.py +172 -0
- aethergraph/runtime/__init__.py +15 -0
- aethergraph/server/app_factory.py +196 -34
- aethergraph/server/clients/channel_client.py +202 -0
- aethergraph/server/http/channel_http_routes.py +116 -0
- aethergraph/server/http/channel_ws_routers.py +45 -0
- aethergraph/server/loading.py +117 -0
- aethergraph/server/server.py +131 -0
- aethergraph/server/server_state.py +240 -0
- aethergraph/server/start.py +227 -66
- aethergraph/server/ui_static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- aethergraph/server/ui_static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- aethergraph/server/ui_static/assets/index-BR5GtXcZ.css +1 -0
- aethergraph/server/ui_static/assets/index-CQ0HZZ83.js +400 -0
- aethergraph/server/ui_static/index.html +15 -0
- aethergraph/server/ui_static/logo.png +0 -0
- aethergraph/services/artifacts/__init__.py +0 -0
- aethergraph/services/artifacts/facade.py +1239 -132
- aethergraph/services/auth/{dev.py → authn.py} +0 -8
- aethergraph/services/auth/authz.py +100 -0
- aethergraph/services/channel/__init__.py +0 -0
- aethergraph/services/channel/channel_bus.py +19 -1
- aethergraph/services/channel/factory.py +13 -1
- aethergraph/services/channel/ingress.py +311 -0
- aethergraph/services/channel/queue_adapter.py +75 -0
- aethergraph/services/channel/session.py +502 -19
- aethergraph/services/container/default_container.py +122 -43
- aethergraph/services/continuations/continuation.py +6 -0
- aethergraph/services/continuations/stores/fs_store.py +19 -0
- aethergraph/services/eventhub/event_hub.py +76 -0
- aethergraph/services/kv/__init__.py +0 -0
- aethergraph/services/kv/ephemeral.py +244 -0
- aethergraph/services/llm/__init__.py +0 -0
- aethergraph/services/llm/generic_client copy.py +691 -0
- aethergraph/services/llm/generic_client.py +1288 -187
- aethergraph/services/llm/providers.py +3 -1
- aethergraph/services/llm/types.py +47 -0
- aethergraph/services/llm/utils.py +284 -0
- aethergraph/services/logger/std.py +3 -0
- aethergraph/services/mcp/__init__.py +9 -0
- aethergraph/services/mcp/http_client.py +38 -0
- aethergraph/services/mcp/service.py +225 -1
- aethergraph/services/mcp/stdio_client.py +41 -6
- aethergraph/services/mcp/ws_client.py +44 -2
- aethergraph/services/memory/__init__.py +0 -0
- aethergraph/services/memory/distillers/llm_long_term.py +234 -0
- aethergraph/services/memory/distillers/llm_meta_summary.py +398 -0
- aethergraph/services/memory/distillers/long_term.py +225 -0
- aethergraph/services/memory/facade/__init__.py +3 -0
- aethergraph/services/memory/facade/chat.py +440 -0
- aethergraph/services/memory/facade/core.py +447 -0
- aethergraph/services/memory/facade/distillation.py +424 -0
- aethergraph/services/memory/facade/rag.py +410 -0
- aethergraph/services/memory/facade/results.py +315 -0
- aethergraph/services/memory/facade/retrieval.py +139 -0
- aethergraph/services/memory/facade/types.py +77 -0
- aethergraph/services/memory/facade/utils.py +43 -0
- aethergraph/services/memory/facade_dep.py +1539 -0
- aethergraph/services/memory/factory.py +9 -3
- aethergraph/services/memory/utils.py +10 -0
- aethergraph/services/metering/eventlog_metering.py +470 -0
- aethergraph/services/metering/noop.py +25 -4
- aethergraph/services/rag/__init__.py +0 -0
- aethergraph/services/rag/facade.py +279 -23
- aethergraph/services/rag/index_factory.py +2 -2
- aethergraph/services/rag/node_rag.py +317 -0
- aethergraph/services/rate_limit/inmem_rate_limit.py +24 -0
- aethergraph/services/registry/__init__.py +0 -0
- aethergraph/services/registry/agent_app_meta.py +419 -0
- aethergraph/services/registry/registry_key.py +1 -1
- aethergraph/services/registry/unified_registry.py +74 -6
- aethergraph/services/scope/scope.py +159 -0
- aethergraph/services/scope/scope_factory.py +164 -0
- aethergraph/services/state_stores/serialize.py +5 -0
- aethergraph/services/state_stores/utils.py +2 -1
- aethergraph/services/viz/__init__.py +0 -0
- aethergraph/services/viz/facade.py +413 -0
- aethergraph/services/viz/viz_service.py +69 -0
- aethergraph/storage/artifacts/artifact_index_jsonl.py +180 -0
- aethergraph/storage/artifacts/artifact_index_sqlite.py +426 -0
- aethergraph/storage/artifacts/cas_store.py +422 -0
- aethergraph/storage/artifacts/fs_cas.py +18 -0
- aethergraph/storage/artifacts/s3_cas.py +14 -0
- aethergraph/storage/artifacts/utils.py +124 -0
- aethergraph/storage/blob/fs_blob.py +86 -0
- aethergraph/storage/blob/s3_blob.py +115 -0
- aethergraph/storage/continuation_store/fs_cont.py +283 -0
- aethergraph/storage/continuation_store/inmem_cont.py +146 -0
- aethergraph/storage/continuation_store/kvdoc_cont.py +261 -0
- aethergraph/storage/docstore/fs_doc.py +63 -0
- aethergraph/storage/docstore/sqlite_doc.py +31 -0
- aethergraph/storage/docstore/sqlite_doc_sync.py +90 -0
- aethergraph/storage/eventlog/fs_event.py +136 -0
- aethergraph/storage/eventlog/sqlite_event.py +47 -0
- aethergraph/storage/eventlog/sqlite_event_sync.py +178 -0
- aethergraph/storage/factory.py +432 -0
- aethergraph/storage/fs_utils.py +28 -0
- aethergraph/storage/graph_state_store/state_store.py +64 -0
- aethergraph/storage/kv/inmem_kv.py +103 -0
- aethergraph/storage/kv/layered_kv.py +52 -0
- aethergraph/storage/kv/sqlite_kv.py +39 -0
- aethergraph/storage/kv/sqlite_kv_sync.py +98 -0
- aethergraph/storage/memory/event_persist.py +68 -0
- aethergraph/storage/memory/fs_persist.py +118 -0
- aethergraph/{services/memory/hotlog_kv.py → storage/memory/hotlog.py} +8 -2
- aethergraph/{services → storage}/memory/indices.py +31 -7
- aethergraph/storage/metering/meter_event.py +55 -0
- aethergraph/storage/runs/doc_store.py +280 -0
- aethergraph/storage/runs/inmen_store.py +82 -0
- aethergraph/storage/runs/sqlite_run_store.py +403 -0
- aethergraph/storage/sessions/doc_store.py +183 -0
- aethergraph/storage/sessions/inmem_store.py +110 -0
- aethergraph/storage/sessions/sqlite_session_store.py +399 -0
- aethergraph/storage/vector_index/chroma_index.py +138 -0
- aethergraph/storage/vector_index/faiss_index.py +179 -0
- aethergraph/storage/vector_index/sqlite_index.py +187 -0
- {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a3.dist-info}/METADATA +138 -31
- aethergraph-0.1.0a3.dist-info/RECORD +356 -0
- aethergraph-0.1.0a3.dist-info/entry_points.txt +3 -0
- aethergraph/services/artifacts/factory.py +0 -35
- aethergraph/services/artifacts/fs_store.py +0 -656
- aethergraph/services/artifacts/jsonl_index.py +0 -123
- aethergraph/services/artifacts/sqlite_index.py +0 -209
- aethergraph/services/memory/distillers/episode.py +0 -116
- aethergraph/services/memory/distillers/rolling.py +0 -74
- aethergraph/services/memory/facade.py +0 -633
- aethergraph/services/memory/persist_fs.py +0 -40
- aethergraph/services/rag/index/base.py +0 -27
- aethergraph/services/rag/index/faiss_index.py +0 -121
- aethergraph/services/rag/index/sqlite_index.py +0 -134
- aethergraph-0.1.0a1.dist-info/RECORD +0 -182
- aethergraph-0.1.0a1.dist-info/entry_points.txt +0 -2
- {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a3.dist-info}/WHEEL +0 -0
- {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a3.dist-info}/licenses/LICENSE +0 -0
- {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a3.dist-info}/licenses/NOTICE +0 -0
- {aethergraph-0.1.0a1.dist-info → aethergraph-0.1.0a3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
# aethergraph/runtime/agent_app_meta.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
import inspect
|
|
6
|
+
from typing import Any, Literal, TypedDict
|
|
7
|
+
|
|
8
|
+
from aethergraph.core.runtime.run_types import RunImportance, RunVisibility
|
|
9
|
+
|
|
10
|
+
# ---------------------------------------------------------------------
|
|
11
|
+
# Config schemas used by decorators
|
|
12
|
+
# ---------------------------------------------------------------------
|
|
13
|
+
SUPPORTED_AGENT_MODES = {"chat_v1"}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AgentConfig(TypedDict, total=False):
|
|
17
|
+
"""
|
|
18
|
+
Configuration metadata for an agent. Register an agent with `as_agent`
|
|
19
|
+
parameter in `@graphify` or `@graph_fn`.
|
|
20
|
+
|
|
21
|
+
All fields are optional except `id` in practice; anything omitted gets
|
|
22
|
+
reasonable defaults in build_agent_meta.
|
|
23
|
+
|
|
24
|
+
Attributes:
|
|
25
|
+
id (str): Unique identifier for the agent. Defaults to graph name.
|
|
26
|
+
title (str): Display name of the agent. Optional, shown in the UI.
|
|
27
|
+
description (str): Brief description of the agent. Optional, shown in the UI.
|
|
28
|
+
short_description (str): Shorter summary (used in cards). Optional.
|
|
29
|
+
icon_key (str): Icon key used in the UI (e.g. "message-circle").
|
|
30
|
+
color (str): Accent color token (e.g. "emerald").
|
|
31
|
+
badge (str): Badge label, e.g. "Chat Agent".
|
|
32
|
+
category (str): Category, e.g. "Core", "R&D Lab", "Infra", "Productivity".
|
|
33
|
+
status (str): "available" | "coming-soon" | "hidden" | "error" | ...
|
|
34
|
+
mode (str): Operational mode. Defaults to "chat_v1" for chat agents.
|
|
35
|
+
session_kind (str): Session type, e.g. "chat". Defaults to "chat".
|
|
36
|
+
flow_id (str): Flow identifier for wiring. Defaults to graph name.
|
|
37
|
+
tags (list[str]): Tags used for search / grouping.
|
|
38
|
+
tool_graphs (list[str]): Related tool graph identifiers.
|
|
39
|
+
features (list[str]): Optional feature bullets for UI.
|
|
40
|
+
run_visibility (RunVisibility): "normal" | "inline" | ...
|
|
41
|
+
run_importance (RunImportance): "normal" | "high" | ...
|
|
42
|
+
memory_level (Literal["user","session","run"]): Memory scope level.
|
|
43
|
+
memory_scope (str): Logical scope, e.g. "session.global", "user.all".
|
|
44
|
+
github_url (str): Optional GitHub link.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
# Identity & basic UI
|
|
48
|
+
id: str
|
|
49
|
+
title: str
|
|
50
|
+
description: str
|
|
51
|
+
short_description: str
|
|
52
|
+
icon_key: str
|
|
53
|
+
color: str
|
|
54
|
+
badge: str
|
|
55
|
+
category: str
|
|
56
|
+
status: str # "available" | "coming-soon" | "hidden" | ...
|
|
57
|
+
|
|
58
|
+
# Behavior & wiring
|
|
59
|
+
mode: str # "chat_v1", etc.
|
|
60
|
+
session_kind: str # "chat", "batch", ...
|
|
61
|
+
|
|
62
|
+
flow_id: str
|
|
63
|
+
tags: list[str]
|
|
64
|
+
tool_graphs: list[str]
|
|
65
|
+
features: list[str]
|
|
66
|
+
|
|
67
|
+
# Runtime behavior
|
|
68
|
+
run_visibility: RunVisibility
|
|
69
|
+
run_importance: RunImportance
|
|
70
|
+
|
|
71
|
+
# Memory policy
|
|
72
|
+
memory_level: Literal["user", "session", "run"]
|
|
73
|
+
memory_scope: str
|
|
74
|
+
|
|
75
|
+
# Optional metadata
|
|
76
|
+
github_url: str
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class AppConfig(TypedDict, total=False):
|
|
80
|
+
"""
|
|
81
|
+
Configuration metadata for an application. Register an app with `as_app`
|
|
82
|
+
parameter in `@graphify` or `@graph_fn`.
|
|
83
|
+
|
|
84
|
+
Attributes:
|
|
85
|
+
id (str): Unique identifier for the app. Defaults to graph name.
|
|
86
|
+
name (str): Human-readable name of the app. Defaults to "App for <graph>".
|
|
87
|
+
badge (str): Short badge or label for the app. Optional, shown in the UI.
|
|
88
|
+
short_description (str): Brief summary of the app's purpose. Optional.
|
|
89
|
+
description (str): Detailed description of the app. Optional.
|
|
90
|
+
category (str): Category, e.g. "Core", "R&D Lab", "Infra", "Productivity".
|
|
91
|
+
status (str): "available" | "coming-soon" | "hidden" | "error" | ...
|
|
92
|
+
icon_key (str): Icon key for the app.
|
|
93
|
+
color (str): Accent color token.
|
|
94
|
+
mode (str): App mode, e.g. "no_input_v1". Defaults to "no_input_v1".
|
|
95
|
+
tags (list[str]): Tags for search / grouping.
|
|
96
|
+
features (list[str]): Notable features for the app.
|
|
97
|
+
run_visibility (RunVisibility): "normal" | "inline" | ...
|
|
98
|
+
run_importance (RunImportance): "normal" | "high" | ...
|
|
99
|
+
flow_id (str): Flow identifier. Defaults to graph name.
|
|
100
|
+
github_url (str): Optional GitHub link.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
# Identity & UI
|
|
104
|
+
id: str
|
|
105
|
+
name: str
|
|
106
|
+
badge: str
|
|
107
|
+
short_description: str
|
|
108
|
+
description: str
|
|
109
|
+
category: str
|
|
110
|
+
status: str
|
|
111
|
+
icon_key: str
|
|
112
|
+
color: str
|
|
113
|
+
mode: str
|
|
114
|
+
tags: list[str]
|
|
115
|
+
|
|
116
|
+
# UX hints
|
|
117
|
+
features: list[str]
|
|
118
|
+
|
|
119
|
+
# Runtime behavior
|
|
120
|
+
run_visibility: RunVisibility
|
|
121
|
+
run_importance: RunImportance
|
|
122
|
+
flow_id: str
|
|
123
|
+
|
|
124
|
+
# Optional metadata
|
|
125
|
+
github_url: str
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
AGENT_CORE_KEYS = {
|
|
129
|
+
"id",
|
|
130
|
+
"title",
|
|
131
|
+
"description",
|
|
132
|
+
"short_description",
|
|
133
|
+
"icon_key",
|
|
134
|
+
"color",
|
|
135
|
+
"badge",
|
|
136
|
+
"category",
|
|
137
|
+
"status",
|
|
138
|
+
"mode",
|
|
139
|
+
"session_kind",
|
|
140
|
+
"flow_id",
|
|
141
|
+
"tags",
|
|
142
|
+
"tool_graphs",
|
|
143
|
+
"features",
|
|
144
|
+
"run_visibility",
|
|
145
|
+
"run_importance",
|
|
146
|
+
"memory_level",
|
|
147
|
+
"memory_scope",
|
|
148
|
+
"github_url",
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
APP_CORE_KEYS = {
|
|
152
|
+
"id",
|
|
153
|
+
"name",
|
|
154
|
+
"badge",
|
|
155
|
+
"short_description",
|
|
156
|
+
"description",
|
|
157
|
+
"category",
|
|
158
|
+
"status",
|
|
159
|
+
"icon_key",
|
|
160
|
+
"color",
|
|
161
|
+
"mode",
|
|
162
|
+
"tags",
|
|
163
|
+
"features",
|
|
164
|
+
"run_visibility",
|
|
165
|
+
"run_importance",
|
|
166
|
+
"flow_id",
|
|
167
|
+
"github_url",
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# ---------------------------------------------------------------------
|
|
171
|
+
# Shared constants / validators
|
|
172
|
+
# ---------------------------------------------------------------------
|
|
173
|
+
|
|
174
|
+
CHAT_V1_REQUIRED_INPUTS = [
|
|
175
|
+
"message",
|
|
176
|
+
"files",
|
|
177
|
+
"context_refs",
|
|
178
|
+
"session_id",
|
|
179
|
+
"user_meta",
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def normalize_agent_mode(agent_cfg: AgentConfig) -> str:
|
|
184
|
+
# Default behavior: if user doesn't specify, it's chat_v1
|
|
185
|
+
mode = (agent_cfg.mode or "chat_v1").strip()
|
|
186
|
+
|
|
187
|
+
if mode not in SUPPORTED_AGENT_MODES:
|
|
188
|
+
# this will be caught and turned into status="error" for now
|
|
189
|
+
raise ValueError(
|
|
190
|
+
f"Unsupported agent mode '{mode}'. "
|
|
191
|
+
"Currently only 'chat_v1' is supported. "
|
|
192
|
+
"Omit 'mode' or set mode='chat_v1'."
|
|
193
|
+
)
|
|
194
|
+
return mode
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
SUPPORTED_APP_MODES = {"no_input_v1"}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def normalize_app_mode(app_cfg: AppConfig) -> str:
|
|
201
|
+
mode = (app_cfg.mode or "no_input_v1").strip()
|
|
202
|
+
if mode not in SUPPORTED_APP_MODES:
|
|
203
|
+
raise ValueError(
|
|
204
|
+
f"Unsupported app mode '{mode}'. "
|
|
205
|
+
"Currently only 'no_input_v1' is supported for gallery apps. "
|
|
206
|
+
"Omit 'mode' or set mode='no_input_v1'."
|
|
207
|
+
)
|
|
208
|
+
return mode
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def validate_agent_signature(
|
|
212
|
+
graph_name: str, fn: Callable, agent_cfg: AgentConfig
|
|
213
|
+
) -> tuple[str, list[str]]:
|
|
214
|
+
mode = normalize_agent_mode(agent_cfg)
|
|
215
|
+
|
|
216
|
+
sig = inspect.signature(fn)
|
|
217
|
+
param_names = list(sig.parameters.keys())
|
|
218
|
+
|
|
219
|
+
if mode == "chat_v1":
|
|
220
|
+
missing = [p for p in CHAT_V1_REQUIRED_INPUTS if p not in param_names]
|
|
221
|
+
if missing:
|
|
222
|
+
raise ValueError(
|
|
223
|
+
f"chat_v1 agent '{graph_name}' is missing parameters: {missing}. "
|
|
224
|
+
f"Expected parameters: {CHAT_V1_REQUIRED_INPUTS}"
|
|
225
|
+
)
|
|
226
|
+
# TODO future: could be more flexible here:
|
|
227
|
+
# - use CHAT_V1_REQUIRED_INPUTS as canonical inputs, or
|
|
228
|
+
# - accept superset but keep these first.
|
|
229
|
+
inputs = CHAT_V1_REQUIRED_INPUTS
|
|
230
|
+
else:
|
|
231
|
+
# Currently unreachable because normalize_agent_mode rejects unknowns,
|
|
232
|
+
# but future-proof if add more modes.
|
|
233
|
+
inputs = param_names
|
|
234
|
+
|
|
235
|
+
return mode, inputs
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# ---------------------------------------------------------------------
|
|
239
|
+
# Normalization helpers used by decorators & other runtime code
|
|
240
|
+
# ---------------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def build_agent_meta(
|
|
244
|
+
*,
|
|
245
|
+
graph_name: str,
|
|
246
|
+
version: str,
|
|
247
|
+
graph_meta: dict[str, Any],
|
|
248
|
+
agent_cfg: AgentConfig | None,
|
|
249
|
+
) -> dict[str, Any] | None:
|
|
250
|
+
"""
|
|
251
|
+
Normalize AgentConfig + graph metadata into a registry-ready meta dict.
|
|
252
|
+
|
|
253
|
+
Returns None if agent_cfg is None.
|
|
254
|
+
"""
|
|
255
|
+
if agent_cfg is None:
|
|
256
|
+
return None
|
|
257
|
+
|
|
258
|
+
cfg: dict[str, Any] = dict(agent_cfg)
|
|
259
|
+
base_tags = graph_meta.get("tags") or []
|
|
260
|
+
|
|
261
|
+
agent_id = cfg.get("id", graph_name)
|
|
262
|
+
agent_title = cfg.get("title", f"Agent for {graph_name}")
|
|
263
|
+
agent_flow_id = cfg.get("flow_id", graph_meta.get("flow_id", graph_name))
|
|
264
|
+
agent_tags = cfg.get("tags", base_tags)
|
|
265
|
+
|
|
266
|
+
# Anything not in core keys becomes "extra" for future use
|
|
267
|
+
extra = {k: v for k, v in cfg.items() if k not in AGENT_CORE_KEYS}
|
|
268
|
+
|
|
269
|
+
# Memory policy
|
|
270
|
+
memory_level = cfg.get("memory_level", "session")
|
|
271
|
+
memory_scope = cfg.get("memory_scope")
|
|
272
|
+
|
|
273
|
+
# Text fields
|
|
274
|
+
description = cfg.get("description")
|
|
275
|
+
short_description = cfg.get("short_description") or description
|
|
276
|
+
|
|
277
|
+
# Visuals
|
|
278
|
+
icon_key = cfg.get("icon_key")
|
|
279
|
+
accent_color = cfg.get("color")
|
|
280
|
+
|
|
281
|
+
# Behavior
|
|
282
|
+
agent_mode = cfg.get("mode") or "chat_v1"
|
|
283
|
+
session_kind = cfg.get("session_kind", "chat")
|
|
284
|
+
|
|
285
|
+
meta: dict[str, Any] = {
|
|
286
|
+
"kind": "agent",
|
|
287
|
+
"id": agent_id,
|
|
288
|
+
"title": agent_title,
|
|
289
|
+
"description": description,
|
|
290
|
+
"short_description": short_description,
|
|
291
|
+
"icon_key": icon_key,
|
|
292
|
+
"color": accent_color,
|
|
293
|
+
"badge": cfg.get("badge"),
|
|
294
|
+
"category": cfg.get("category"),
|
|
295
|
+
"status": cfg.get("status", "available"),
|
|
296
|
+
"mode": agent_mode,
|
|
297
|
+
"session_kind": session_kind,
|
|
298
|
+
"flow_id": agent_flow_id,
|
|
299
|
+
"tags": agent_tags,
|
|
300
|
+
"tool_graphs": cfg.get("tool_graphs", []),
|
|
301
|
+
"features": cfg.get("features", []),
|
|
302
|
+
"run_visibility": cfg.get("run_visibility", "inline"),
|
|
303
|
+
"run_importance": cfg.get("run_importance", "normal"),
|
|
304
|
+
"memory": {
|
|
305
|
+
"level": memory_level,
|
|
306
|
+
"scope": memory_scope,
|
|
307
|
+
},
|
|
308
|
+
"github_url": cfg.get("github_url"),
|
|
309
|
+
"backing": {
|
|
310
|
+
"type": "graphfn",
|
|
311
|
+
"name": graph_name,
|
|
312
|
+
"version": version,
|
|
313
|
+
},
|
|
314
|
+
"extra": extra,
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
# unified gallery view
|
|
318
|
+
meta["gallery"] = {
|
|
319
|
+
"kind": "agent",
|
|
320
|
+
"id": agent_id,
|
|
321
|
+
"title": agent_title,
|
|
322
|
+
"subtitle": session_kind or agent_mode,
|
|
323
|
+
"badge": cfg.get("badge"),
|
|
324
|
+
"category": cfg.get("category"),
|
|
325
|
+
"status": meta["status"],
|
|
326
|
+
"short_description": short_description,
|
|
327
|
+
"description": description,
|
|
328
|
+
"icon_key": icon_key,
|
|
329
|
+
"accent_color": accent_color,
|
|
330
|
+
"tags": agent_tags,
|
|
331
|
+
"github_url": cfg.get("github_url"),
|
|
332
|
+
"flow_id": agent_flow_id,
|
|
333
|
+
"backing": meta["backing"],
|
|
334
|
+
"extra": extra,
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return meta
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def build_app_meta(
|
|
341
|
+
*,
|
|
342
|
+
graph_name: str,
|
|
343
|
+
version: str,
|
|
344
|
+
graph_meta: dict[str, Any],
|
|
345
|
+
app_cfg: AppConfig | None,
|
|
346
|
+
) -> dict[str, Any] | None:
|
|
347
|
+
"""
|
|
348
|
+
Normalize AppConfig + graph metadata into a registry-ready meta dict.
|
|
349
|
+
|
|
350
|
+
Returns None if app_cfg is None.
|
|
351
|
+
"""
|
|
352
|
+
if app_cfg is None:
|
|
353
|
+
return None
|
|
354
|
+
|
|
355
|
+
cfg: dict[str, Any] = dict(app_cfg)
|
|
356
|
+
base_tags = graph_meta.get("tags") or []
|
|
357
|
+
|
|
358
|
+
app_id = cfg.get("id", graph_name)
|
|
359
|
+
app_flow_id = cfg.get("flow_id", graph_meta.get("flow_id", graph_name))
|
|
360
|
+
app_name = cfg.get("name", f"App for {graph_name}")
|
|
361
|
+
app_tags = cfg.get("tags", base_tags)
|
|
362
|
+
|
|
363
|
+
extra = {k: v for k, v in cfg.items() if k not in APP_CORE_KEYS}
|
|
364
|
+
|
|
365
|
+
short_description = cfg.get("short_description") or cfg.get("description")
|
|
366
|
+
description = cfg.get("description")
|
|
367
|
+
|
|
368
|
+
icon_key = cfg.get("icon_key")
|
|
369
|
+
accent_color = cfg.get("color")
|
|
370
|
+
app_mode = cfg.get("mode") or "no_input_v1"
|
|
371
|
+
|
|
372
|
+
meta: dict[str, Any] = {
|
|
373
|
+
"kind": "app",
|
|
374
|
+
"id": app_id,
|
|
375
|
+
"name": app_name,
|
|
376
|
+
"graph_id": graph_name,
|
|
377
|
+
"flow_id": app_flow_id,
|
|
378
|
+
"badge": cfg.get("badge"),
|
|
379
|
+
"category": cfg.get("category"),
|
|
380
|
+
"short_description": short_description,
|
|
381
|
+
"description": description,
|
|
382
|
+
"status": cfg.get("status", "available"),
|
|
383
|
+
"icon_key": icon_key,
|
|
384
|
+
"color": accent_color,
|
|
385
|
+
"mode": app_mode,
|
|
386
|
+
"tags": app_tags,
|
|
387
|
+
"features": cfg.get("features", []),
|
|
388
|
+
"run_visibility": cfg.get("run_visibility", "normal"),
|
|
389
|
+
"run_importance": cfg.get("run_importance", "normal"),
|
|
390
|
+
"github_url": cfg.get("github_url"),
|
|
391
|
+
"backing": {
|
|
392
|
+
"type": "graphfn",
|
|
393
|
+
"name": graph_name,
|
|
394
|
+
"version": version,
|
|
395
|
+
},
|
|
396
|
+
"extra": extra,
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
# unified gallery view
|
|
400
|
+
meta["gallery"] = {
|
|
401
|
+
"kind": "app",
|
|
402
|
+
"id": app_id,
|
|
403
|
+
"title": app_name,
|
|
404
|
+
"subtitle": cfg.get("category"),
|
|
405
|
+
"badge": cfg.get("badge"),
|
|
406
|
+
"category": cfg.get("category"),
|
|
407
|
+
"status": meta["status"],
|
|
408
|
+
"short_description": short_description,
|
|
409
|
+
"description": description,
|
|
410
|
+
"icon_key": icon_key,
|
|
411
|
+
"accent_color": accent_color,
|
|
412
|
+
"tags": app_tags,
|
|
413
|
+
"github_url": cfg.get("github_url"),
|
|
414
|
+
"flow_id": app_flow_id,
|
|
415
|
+
"backing": meta["backing"],
|
|
416
|
+
"extra": extra,
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return meta
|
|
@@ -37,9 +37,20 @@ class UnifiedRegistry:
|
|
|
37
37
|
self._lock = threading.RLock()
|
|
38
38
|
self._allow_overwrite = allow_overwrite
|
|
39
39
|
|
|
40
|
+
# per-version metadata
|
|
41
|
+
self._meta: dict[tuple[str, str, str], dict[str, Any]] = {}
|
|
42
|
+
|
|
40
43
|
# ---------- registration ----------
|
|
41
44
|
|
|
42
|
-
def register(
|
|
45
|
+
def register(
|
|
46
|
+
self,
|
|
47
|
+
*,
|
|
48
|
+
nspace: str,
|
|
49
|
+
name: str,
|
|
50
|
+
version: str,
|
|
51
|
+
obj: RegistryValue,
|
|
52
|
+
meta: dict[str, Any] | None = None,
|
|
53
|
+
) -> None:
|
|
43
54
|
if nspace not in NS:
|
|
44
55
|
raise ValueError(f"Unknown namespace: {nspace}")
|
|
45
56
|
key = (nspace, name)
|
|
@@ -52,6 +63,10 @@ class UnifiedRegistry:
|
|
|
52
63
|
versions[version] = obj
|
|
53
64
|
self._latest[key] = self._pick_latest(versions.keys())
|
|
54
65
|
|
|
66
|
+
# Store metadata
|
|
67
|
+
if meta is not None:
|
|
68
|
+
self._meta[(nspace, name, version)] = meta
|
|
69
|
+
|
|
55
70
|
def register_latest(
|
|
56
71
|
self, *, nspace: str, name: str, obj: RegistryValue, version: str = "0.0.0"
|
|
57
72
|
) -> None:
|
|
@@ -85,11 +100,13 @@ class UnifiedRegistry:
|
|
|
85
100
|
raise KeyError(f"Version not found: {key.nspace}:{key.name}@{ver}")
|
|
86
101
|
|
|
87
102
|
val = versions[ver]
|
|
88
|
-
|
|
89
|
-
if
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
103
|
+
|
|
104
|
+
## Materialize if factory -> we handle it when executing the graphs. Here it can cause
|
|
105
|
+
# the graph_fn returns a coroutine inside the GraphFunction object, not the expected function.
|
|
106
|
+
# if callable(val):
|
|
107
|
+
# obj = val()
|
|
108
|
+
# versions[ver] = obj
|
|
109
|
+
# return obj
|
|
93
110
|
return val
|
|
94
111
|
|
|
95
112
|
# ---------- listing / admin ----------
|
|
@@ -123,6 +140,10 @@ class UnifiedRegistry:
|
|
|
123
140
|
self._store.pop(k, None)
|
|
124
141
|
self._latest.pop(k, None)
|
|
125
142
|
self._aliases.pop(k, None)
|
|
143
|
+
# NEW: drop all meta for this (ns,name)
|
|
144
|
+
for key in list(self._meta.keys()):
|
|
145
|
+
if key[0] == nspace and key[1] == name:
|
|
146
|
+
self._meta.pop(key, None)
|
|
126
147
|
return
|
|
127
148
|
vers = self._store[k]
|
|
128
149
|
vers.pop(version, None)
|
|
@@ -131,6 +152,8 @@ class UnifiedRegistry:
|
|
|
131
152
|
for tag, v in list(self._aliases[k].items()):
|
|
132
153
|
if v == version:
|
|
133
154
|
self._aliases[k].pop(tag, None)
|
|
155
|
+
# drop meta for this version
|
|
156
|
+
self._meta.pop((nspace, name, version), None)
|
|
134
157
|
# recompute latest
|
|
135
158
|
if vers:
|
|
136
159
|
self._latest[k] = self._pick_latest(vers.keys())
|
|
@@ -144,6 +167,7 @@ class UnifiedRegistry:
|
|
|
144
167
|
self._store.clear()
|
|
145
168
|
self._latest.clear()
|
|
146
169
|
self._aliases.clear()
|
|
170
|
+
self._meta.clear()
|
|
147
171
|
|
|
148
172
|
# ---------- typed getters ----------
|
|
149
173
|
|
|
@@ -159,6 +183,50 @@ class UnifiedRegistry:
|
|
|
159
183
|
def get_agent(self, name: str, version: str | None = None) -> Any:
|
|
160
184
|
return self.get(Key(nspace="agent", name=name, version=version))
|
|
161
185
|
|
|
186
|
+
def get_meta(
|
|
187
|
+
self,
|
|
188
|
+
nspace: str,
|
|
189
|
+
name: str,
|
|
190
|
+
version: str | None = None,
|
|
191
|
+
) -> dict[str, Any] | None:
|
|
192
|
+
"""
|
|
193
|
+
Return metadata for a given registered object, or None if not set.
|
|
194
|
+
Follows the same version resolution as `get()`: explicit → alias → latest.
|
|
195
|
+
"""
|
|
196
|
+
if nspace not in NS:
|
|
197
|
+
raise ValueError(f"Unknown namespace: {nspace}")
|
|
198
|
+
key = (nspace, name)
|
|
199
|
+
with self._lock:
|
|
200
|
+
versions = self._store.get(key)
|
|
201
|
+
if not versions:
|
|
202
|
+
return None
|
|
203
|
+
|
|
204
|
+
ver = version
|
|
205
|
+
# resolve aliases or default to latest
|
|
206
|
+
ver = self._aliases.get(key, {}).get(ver, ver) if ver else self._latest.get(key)
|
|
207
|
+
if ver is None:
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
return self._meta.get((nspace, name, ver))
|
|
211
|
+
|
|
212
|
+
# ---------- list typed ----------
|
|
213
|
+
def list_tools(self) -> dict[str, str]:
|
|
214
|
+
return self.list(nspace="tool")
|
|
215
|
+
|
|
216
|
+
def list_graphs(self) -> dict[str, str]:
|
|
217
|
+
return self.list(nspace="graph")
|
|
218
|
+
|
|
219
|
+
def list_graphfns(self) -> dict[str, str]:
|
|
220
|
+
return self.list(nspace="graphfn")
|
|
221
|
+
|
|
222
|
+
def list_agents(self) -> dict[str, str]:
|
|
223
|
+
# Return {'agent:<id>': '<latest_version>'}
|
|
224
|
+
return self.list(nspace="agent")
|
|
225
|
+
|
|
226
|
+
def list_apps(self) -> dict[str, str]:
|
|
227
|
+
# Return {'app:<id>': '<latest_version>'}
|
|
228
|
+
return self.list(nspace="app")
|
|
229
|
+
|
|
162
230
|
# ---------- helpers ----------
|
|
163
231
|
|
|
164
232
|
@staticmethod
|