agstack 1.21.1__tar.gz → 1.22.0__tar.gz

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.
Files changed (77) hide show
  1. {agstack-1.21.1 → agstack-1.22.0}/PKG-INFO +3 -1
  2. {agstack-1.21.1 → agstack-1.22.0}/agstack/config/manager.py +47 -11
  3. {agstack-1.21.1 → agstack-1.22.0}/agstack.egg-info/PKG-INFO +3 -1
  4. {agstack-1.21.1 → agstack-1.22.0}/agstack.egg-info/requires.txt +3 -0
  5. {agstack-1.21.1 → agstack-1.22.0}/pyproject.toml +2 -1
  6. {agstack-1.21.1 → agstack-1.22.0}/LICENSE +0 -0
  7. {agstack-1.21.1 → agstack-1.22.0}/README.md +0 -0
  8. {agstack-1.21.1 → agstack-1.22.0}/agstack/__init__.py +0 -0
  9. {agstack-1.21.1 → agstack-1.22.0}/agstack/cache/__init__.py +0 -0
  10. {agstack-1.21.1 → agstack-1.22.0}/agstack/cache/base.py +0 -0
  11. {agstack-1.21.1 → agstack-1.22.0}/agstack/cache/memory.py +0 -0
  12. {agstack-1.21.1 → agstack-1.22.0}/agstack/cache/redis.py +0 -0
  13. {agstack-1.21.1 → agstack-1.22.0}/agstack/config/__init__.py +0 -0
  14. {agstack-1.21.1 → agstack-1.22.0}/agstack/config/logger.py +0 -0
  15. {agstack-1.21.1 → agstack-1.22.0}/agstack/config/types.py +0 -0
  16. {agstack-1.21.1 → agstack-1.22.0}/agstack/contexts.py +0 -0
  17. {agstack-1.21.1 → agstack-1.22.0}/agstack/decorators.py +0 -0
  18. {agstack-1.21.1 → agstack-1.22.0}/agstack/events.py +0 -0
  19. {agstack-1.21.1 → agstack-1.22.0}/agstack/exceptions.py +0 -0
  20. {agstack-1.21.1 → agstack-1.22.0}/agstack/fastapi/__init__.py +0 -0
  21. {agstack-1.21.1 → agstack-1.22.0}/agstack/fastapi/exception.py +0 -0
  22. {agstack-1.21.1 → agstack-1.22.0}/agstack/fastapi/middleware.py +0 -0
  23. {agstack-1.21.1 → agstack-1.22.0}/agstack/fastapi/offline.py +0 -0
  24. {agstack-1.21.1 → agstack-1.22.0}/agstack/fastapi/sse.py +0 -0
  25. {agstack-1.21.1 → agstack-1.22.0}/agstack/infra/db/__init__.py +0 -0
  26. {agstack-1.21.1 → agstack-1.22.0}/agstack/infra/es/__init__.py +0 -0
  27. {agstack-1.21.1 → agstack-1.22.0}/agstack/infra/kg/__init__.py +0 -0
  28. {agstack-1.21.1 → agstack-1.22.0}/agstack/infra/mq/__init__.py +0 -0
  29. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/__init__.py +0 -0
  30. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/client.py +0 -0
  31. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/__init__.py +0 -0
  32. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/agent.py +0 -0
  33. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/context.py +0 -0
  34. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/event.py +0 -0
  35. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/exceptions.py +0 -0
  36. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/factory.py +0 -0
  37. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/flow.py +0 -0
  38. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/loader.py +0 -0
  39. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/__init__.py +0 -0
  40. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/agent_node.py +0 -0
  41. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/base.py +0 -0
  42. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/detect_node.py +0 -0
  43. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/echo_node.py +0 -0
  44. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/llm_chat_node.py +0 -0
  45. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/llm_embed_node.py +0 -0
  46. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/llm_rerank_node.py +0 -0
  47. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/python_node.py +0 -0
  48. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/subflow_node.py +0 -0
  49. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/switch_node.py +0 -0
  50. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/nodes/tool_node.py +0 -0
  51. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/records.py +0 -0
  52. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/registry.py +0 -0
  53. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/sandbox.py +0 -0
  54. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/state.py +0 -0
  55. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/tool.py +0 -0
  56. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/flow/trace.py +0 -0
  57. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/prompts.py +0 -0
  58. {agstack-1.21.1 → agstack-1.22.0}/agstack/llm/token.py +0 -0
  59. {agstack-1.21.1 → agstack-1.22.0}/agstack/messagebus/__init__.py +0 -0
  60. {agstack-1.21.1 → agstack-1.22.0}/agstack/messagebus/base.py +0 -0
  61. {agstack-1.21.1 → agstack-1.22.0}/agstack/messagebus/memory.py +0 -0
  62. {agstack-1.21.1 → agstack-1.22.0}/agstack/messagebus/redis.py +0 -0
  63. {agstack-1.21.1 → agstack-1.22.0}/agstack/schema.py +0 -0
  64. {agstack-1.21.1 → agstack-1.22.0}/agstack/security/__init__.py +0 -0
  65. {agstack-1.21.1 → agstack-1.22.0}/agstack/security/casbin.py +0 -0
  66. {agstack-1.21.1 → agstack-1.22.0}/agstack/security/crypt.py +0 -0
  67. {agstack-1.21.1 → agstack-1.22.0}/agstack/status.py +0 -0
  68. {agstack-1.21.1 → agstack-1.22.0}/agstack.egg-info/SOURCES.txt +0 -0
  69. {agstack-1.21.1 → agstack-1.22.0}/agstack.egg-info/dependency_links.txt +0 -0
  70. {agstack-1.21.1 → agstack-1.22.0}/agstack.egg-info/top_level.txt +0 -0
  71. {agstack-1.21.1 → agstack-1.22.0}/setup.cfg +0 -0
  72. {agstack-1.21.1 → agstack-1.22.0}/tests/test_cache_memory.py +0 -0
  73. {agstack-1.21.1 → agstack-1.22.0}/tests/test_cache_redis.py +0 -0
  74. {agstack-1.21.1 → agstack-1.22.0}/tests/test_flow_io.py +0 -0
  75. {agstack-1.21.1 → agstack-1.22.0}/tests/test_flow_switch_subflow.py +0 -0
  76. {agstack-1.21.1 → agstack-1.22.0}/tests/test_messagebus_memory.py +0 -0
  77. {agstack-1.21.1 → agstack-1.22.0}/tests/test_messagebus_redis.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agstack
3
- Version: 1.21.1
3
+ Version: 1.22.0
4
4
  Summary: Production-ready toolkit for building FastAPI and LLM applications
5
5
  Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
6
6
  Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
@@ -43,6 +43,8 @@ Provides-Extra: graph
43
43
  Requires-Dist: nebula3-python>=3.8.3; extra == "graph"
44
44
  Provides-Extra: redis
45
45
  Requires-Dist: redis>=5.0; extra == "redis"
46
+ Provides-Extra: yaml
47
+ Requires-Dist: pyyaml>=6.0; extra == "yaml"
46
48
  Provides-Extra: std
47
49
  Requires-Dist: agstack[mq]; extra == "std"
48
50
  Requires-Dist: agstack[db]; extra == "std"
@@ -10,14 +10,42 @@ from .logger import setup_logger
10
10
  from .types import AppConfig
11
11
 
12
12
 
13
+ _CONFIG_CANDIDATES = ("config.toml", "config.yaml", "config.yml")
14
+
15
+
16
+ def _find_config_file(approot: Path) -> Path:
17
+ """按优先级查找配置文件"""
18
+ for name in _CONFIG_CANDIDATES:
19
+ path = approot / name
20
+ if path.exists():
21
+ return path
22
+ return approot / "config.toml"
23
+
24
+
13
25
  def _load_config_file(config_path: Path) -> dict[str, Any]:
14
- """加载配置文件(容错处理)"""
26
+ """加载配置文件(支持 TOML 和 YAML 格式)"""
15
27
  if not config_path.exists():
16
28
  return {}
17
29
 
30
+ suffix = config_path.suffix.lower()
18
31
  try:
19
- with open(config_path, "rb") as f:
20
- return tomllib.load(f)
32
+ if suffix == ".toml":
33
+ with open(config_path, "rb") as f:
34
+ return tomllib.load(f)
35
+ elif suffix in (".yaml", ".yml"):
36
+ try:
37
+ import yaml
38
+ except ImportError as err:
39
+ raise ImportError(
40
+ f"PyYAML is required to load {config_path}. Install it with: pip install agstack[yaml]"
41
+ ) from err
42
+ with open(config_path) as f:
43
+ return yaml.safe_load(f) or {}
44
+ else:
45
+ print(f"Unsupported config format: {suffix}")
46
+ return {}
47
+ except ImportError:
48
+ raise
21
49
  except Exception: # noqa
22
50
  print(f"Failed to load config file: {config_path}")
23
51
  return {}
@@ -95,37 +123,45 @@ def _determine_log_level(config_data: dict[str, Any]) -> str:
95
123
  return config_data.get("logger", {}).get("level", "INFO")
96
124
 
97
125
 
98
- def setup_config(appname: str, envprefix: str = "APP") -> AppConfig:
126
+ def setup_config(appname: str, envprefix: str = "APP", config_file: str | Path | None = None) -> AppConfig:
99
127
  """初始化配置
100
128
 
101
129
  Args:
102
130
  appname: 应用名称
103
131
  envprefix: 环境变量前缀
132
+ config_file: 配置文件路径(支持 .toml / .yaml / .yml),为 None 时自动查找
104
133
 
105
134
  Returns:
106
135
  AppConfig: 配置实例
107
136
  """
108
137
  approot = Path.cwd()
109
- config_path = approot / "config.toml"
110
138
 
111
- # 1. 加载配置文件(容错)
139
+ # 1. 确定配置文件路径
140
+ if config_file:
141
+ config_path = Path(config_file)
142
+ if not config_path.is_absolute():
143
+ config_path = approot / config_path
144
+ else:
145
+ config_path = _find_config_file(approot)
146
+
147
+ # 2. 加载配置文件(容错)
112
148
  config_data = _load_config_file(config_path)
113
149
 
114
- # 2. 加载环境变量覆盖
150
+ # 3. 加载环境变量覆盖
115
151
  env_overrides = _load_env_overrides(envprefix)
116
152
  config_data.update(env_overrides)
117
153
 
118
- # 3. 设置应用信息
154
+ # 4. 设置应用信息
119
155
  config_data.update({"appname": appname, "approot": approot})
120
156
 
121
- # 4. 确定日志级别(优先级处理)
157
+ # 5. 确定日志级别(优先级处理)
122
158
  log_level = _determine_log_level(config_data)
123
159
  config_data.setdefault("logger", {})["level"] = log_level
124
160
 
125
- # 5. 初始化日志(使用字典配置)
161
+ # 6. 初始化日志(使用字典配置)
126
162
  setup_logger(appname, **config_data["logger"])
127
163
 
128
- # 8. 创建配置实例(最后验证)
164
+ # 7. 创建配置实例(最后验证)
129
165
  config = AppConfig.model_validate(config_data)
130
166
 
131
167
  return config
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agstack
3
- Version: 1.21.1
3
+ Version: 1.22.0
4
4
  Summary: Production-ready toolkit for building FastAPI and LLM applications
5
5
  Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
6
6
  Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
@@ -43,6 +43,8 @@ Provides-Extra: graph
43
43
  Requires-Dist: nebula3-python>=3.8.3; extra == "graph"
44
44
  Provides-Extra: redis
45
45
  Requires-Dist: redis>=5.0; extra == "redis"
46
+ Provides-Extra: yaml
47
+ Requires-Dist: pyyaml>=6.0; extra == "yaml"
46
48
  Provides-Extra: std
47
49
  Requires-Dist: agstack[mq]; extra == "std"
48
50
  Requires-Dist: agstack[db]; extra == "std"
@@ -38,3 +38,6 @@ redis>=5.0
38
38
  [std]
39
39
  agstack[mq]
40
40
  agstack[db]
41
+
42
+ [yaml]
43
+ pyyaml>=6.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agstack"
3
- version = "1.21.1"
3
+ version = "1.22.0"
4
4
  description = "Production-ready toolkit for building FastAPI and LLM applications"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -60,6 +60,7 @@ db = ["asyncpg>=0.30.0"]
60
60
  es = ["elasticsearch[async]>=9.3.0"]
61
61
  graph = ["nebula3-python>=3.8.3"]
62
62
  redis = ["redis>=5.0"]
63
+ yaml = ["pyyaml>=6.0"]
63
64
  std = ["agstack[mq]", "agstack[db]"]
64
65
  pro = ["agstack[std]", "agstack[es]"]
65
66
  ent = ["agstack[pro]", "agstack[graph]"]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes