10xgraph-api 0.7.0__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.
- 10xgraph_api-0.7.0.dist-info/METADATA +618 -0
- 10xgraph_api-0.7.0.dist-info/RECORD +203 -0
- 10xgraph_api-0.7.0.dist-info/WHEEL +5 -0
- 10xgraph_api-0.7.0.dist-info/entry_points.txt +3 -0
- 10xgraph_api-0.7.0.dist-info/licenses/LICENSE +21 -0
- 10xgraph_api-0.7.0.dist-info/top_level.txt +2 -0
- agentflow_cli/__init__.py +69 -0
- tenxgraph_api/__init__.py +23 -0
- tenxgraph_api/cli/__init__.py +6 -0
- tenxgraph_api/cli/capabilities.py +127 -0
- tenxgraph_api/cli/commands/__init__.py +49 -0
- tenxgraph_api/cli/commands/api.py +262 -0
- tenxgraph_api/cli/commands/audit.py +213 -0
- tenxgraph_api/cli/commands/build.py +305 -0
- tenxgraph_api/cli/commands/config.py +71 -0
- tenxgraph_api/cli/commands/demo.py +93 -0
- tenxgraph_api/cli/commands/eval.py +909 -0
- tenxgraph_api/cli/commands/init.py +531 -0
- tenxgraph_api/cli/commands/skills.py +532 -0
- tenxgraph_api/cli/commands/test.py +113 -0
- tenxgraph_api/cli/commands/version.py +47 -0
- tenxgraph_api/cli/config_editor/__init__.py +15 -0
- tenxgraph_api/cli/config_editor/schema.py +566 -0
- tenxgraph_api/cli/config_editor/server.py +240 -0
- tenxgraph_api/cli/config_editor/static/app.css +2 -0
- tenxgraph_api/cli/config_editor/static/app.js +3 -0
- tenxgraph_api/cli/config_editor/static/favicon.svg +11 -0
- tenxgraph_api/cli/config_editor/static/index.html +20 -0
- tenxgraph_api/cli/config_editor/store.py +120 -0
- tenxgraph_api/cli/config_editor/validation.py +377 -0
- tenxgraph_api/cli/constants.py +112 -0
- tenxgraph_api/cli/context.py +46 -0
- tenxgraph_api/cli/core/__init__.py +0 -0
- tenxgraph_api/cli/core/animations.py +550 -0
- tenxgraph_api/cli/core/config.py +279 -0
- tenxgraph_api/cli/core/output.py +625 -0
- tenxgraph_api/cli/core/prompts.py +220 -0
- tenxgraph_api/cli/core/screen.py +287 -0
- tenxgraph_api/cli/core/steps.py +621 -0
- tenxgraph_api/cli/core/theme.py +242 -0
- tenxgraph_api/cli/core/validation.py +251 -0
- tenxgraph_api/cli/exceptions.py +129 -0
- tenxgraph_api/cli/logger.py +84 -0
- tenxgraph_api/cli/main.py +936 -0
- tenxgraph_api/cli/templates/__init__.py +0 -0
- tenxgraph_api/cli/templates/defaults.py +844 -0
- tenxgraph_api/cli/templates/dev/.env.example +1 -0
- tenxgraph_api/cli/templates/dev/10xgraph.json +16 -0
- tenxgraph_api/cli/templates/dev/graph/__init__.py +0 -0
- tenxgraph_api/cli/templates/dev/graph/agent.py +63 -0
- tenxgraph_api/cli/templates/prod/.env.example +75 -0
- tenxgraph_api/cli/templates/prod/.pre-commit-config.yaml +50 -0
- tenxgraph_api/cli/templates/prod/.python-version +1 -0
- tenxgraph_api/cli/templates/prod/10xgraph.json +42 -0
- tenxgraph_api/cli/templates/prod/auth/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/auth/agent_auth.py +46 -0
- tenxgraph_api/cli/templates/prod/evals/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/evals/user_simulator_eval.py +76 -0
- tenxgraph_api/cli/templates/prod/evals/weather_agents_eval.py +53 -0
- tenxgraph_api/cli/templates/prod/graph/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/graph/agent.py +50 -0
- tenxgraph_api/cli/templates/prod/graph/state.py +5 -0
- tenxgraph_api/cli/templates/prod/graph/thread_name_generator.py +7 -0
- tenxgraph_api/cli/templates/prod/graph/tools/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/graph/tools/weather_tool.py +43 -0
- tenxgraph_api/cli/templates/prod/graph/validators/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/graph/validators/lifecyle.py +107 -0
- tenxgraph_api/cli/templates/prod/graph/validators/manager.py +9 -0
- tenxgraph_api/cli/templates/prod/graph/validators/validators.py +21 -0
- tenxgraph_api/cli/templates/prod/pyproject.toml +79 -0
- tenxgraph_api/cli/templates/prod/tests/__init__.py +0 -0
- tenxgraph_api/cli/templates/prod/tests/conftest.py +6 -0
- tenxgraph_api/cli/templates/prod/tests/test_agent_eval.py +78 -0
- tenxgraph_api/cli/templates/prod/tests/test_catalog_tools.py +47 -0
- tenxgraph_api/cli/templates/prod/tests/test_graph_nodes.py +57 -0
- tenxgraph_api/cli/templates/skills/10xgraph/SKILL.md +92 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/agents-and-tools.md +389 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/api-client.md +61 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/api-configuration.md +75 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/api-settings-and-middleware.md +89 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/architecture.md +91 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/auth-and-authorization.md +149 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/callbacks-and-command.md +283 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/checkpointing-and-threads.md +63 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/cli-commands.md +73 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/client-auth-and-errors.md +94 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/client-messages-invoke-stream.md +115 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/client-threads-memory-files.md +80 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/context-id-background.md +80 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/dependency-injection.md +58 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/evaluation.md +500 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/id-and-thread-name-generators.md +69 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/media-and-files.md +66 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/memory-and-store.md +70 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/prebuilt-agents-and-tools.md +394 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/production-runtime.md +56 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/providers-and-adapters.md +89 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/publishers-and-runtime-protocols.md +84 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/rate-limiting.md +194 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/realtime.md +172 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/remote-tools.md +55 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/rest-api-and-errors.md +97 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/security-and-validators.md +86 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/state-and-messages.md +68 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/state-graph.md +232 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/stream-emitter.md +144 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/streaming.md +53 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/testing-and-evaluation.md +64 -0
- tenxgraph_api/cli/templates/skills/10xgraph/references/unit-testing.md +202 -0
- tenxgraph_api/cli/templates/skills/copilot/10xgraph.instructions.md +108 -0
- tenxgraph_api/py.typed +0 -0
- tenxgraph_api/src/__init__.py +0 -0
- tenxgraph_api/src/app/__init__.py +13 -0
- tenxgraph_api/src/app/core/__init__.py +15 -0
- tenxgraph_api/src/app/core/auth/__init__.py +0 -0
- tenxgraph_api/src/app/core/auth/auth_backend.py +38 -0
- tenxgraph_api/src/app/core/auth/authorization.py +379 -0
- tenxgraph_api/src/app/core/auth/base_auth.py +27 -0
- tenxgraph_api/src/app/core/auth/jwt_auth.py +122 -0
- tenxgraph_api/src/app/core/auth/ownership_resolver.py +170 -0
- tenxgraph_api/src/app/core/auth/permissions.py +354 -0
- tenxgraph_api/src/app/core/auth/request_config.py +130 -0
- tenxgraph_api/src/app/core/auth/route_guard.py +105 -0
- tenxgraph_api/src/app/core/config/__init__.py +0 -0
- tenxgraph_api/src/app/core/config/graph_config.py +532 -0
- tenxgraph_api/src/app/core/config/media_settings.py +72 -0
- tenxgraph_api/src/app/core/config/sentry_config.py +60 -0
- tenxgraph_api/src/app/core/config/settings.py +202 -0
- tenxgraph_api/src/app/core/config/setup_logs.py +65 -0
- tenxgraph_api/src/app/core/config/setup_middleware.py +483 -0
- tenxgraph_api/src/app/core/config/worker_middleware.py +99 -0
- tenxgraph_api/src/app/core/exceptions/__init__.py +17 -0
- tenxgraph_api/src/app/core/exceptions/general_exception.py +58 -0
- tenxgraph_api/src/app/core/exceptions/handle_errors.py +363 -0
- tenxgraph_api/src/app/core/exceptions/resources_exceptions.py +72 -0
- tenxgraph_api/src/app/core/exceptions/user_exception.py +58 -0
- tenxgraph_api/src/app/core/middleware/__init__.py +25 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/__init__.py +15 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/base.py +27 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/factory.py +98 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/keying.py +133 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/memory.py +98 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/middleware.py +90 -0
- tenxgraph_api/src/app/core/middleware/rate_limit/redis.py +115 -0
- tenxgraph_api/src/app/core/middleware/request_limits.py +154 -0
- tenxgraph_api/src/app/core/middleware/security_headers.py +239 -0
- tenxgraph_api/src/app/core/utils/__init__.py +14 -0
- tenxgraph_api/src/app/core/utils/log_sanitizer.py +216 -0
- tenxgraph_api/src/app/loader.py +516 -0
- tenxgraph_api/src/app/main.py +180 -0
- tenxgraph_api/src/app/routers/__init__.py +4 -0
- tenxgraph_api/src/app/routers/ag_ui/__init__.py +10 -0
- tenxgraph_api/src/app/routers/ag_ui/converter.py +195 -0
- tenxgraph_api/src/app/routers/ag_ui/event_mapper.py +353 -0
- tenxgraph_api/src/app/routers/ag_ui/router.py +90 -0
- tenxgraph_api/src/app/routers/ag_ui/service.py +193 -0
- tenxgraph_api/src/app/routers/checkpointer/__init__.py +1 -0
- tenxgraph_api/src/app/routers/checkpointer/router.py +482 -0
- tenxgraph_api/src/app/routers/checkpointer/schemas/__init__.py +1 -0
- tenxgraph_api/src/app/routers/checkpointer/schemas/checkpointer_schemas.py +121 -0
- tenxgraph_api/src/app/routers/checkpointer/services/__init__.py +1 -0
- tenxgraph_api/src/app/routers/checkpointer/services/checkpointer_service.py +300 -0
- tenxgraph_api/src/app/routers/evals/__init__.py +6 -0
- tenxgraph_api/src/app/routers/evals/router.py +38 -0
- tenxgraph_api/src/app/routers/evals/services/__init__.py +1 -0
- tenxgraph_api/src/app/routers/evals/services/eval_report_service.py +354 -0
- tenxgraph_api/src/app/routers/graph/__init__.py +6 -0
- tenxgraph_api/src/app/routers/graph/realtime_guard.py +161 -0
- tenxgraph_api/src/app/routers/graph/router.py +821 -0
- tenxgraph_api/src/app/routers/graph/schemas/__init__.py +1 -0
- tenxgraph_api/src/app/routers/graph/schemas/graph_schemas.py +386 -0
- tenxgraph_api/src/app/routers/graph/services/__init__.py +1 -0
- tenxgraph_api/src/app/routers/graph/services/graph_service.py +1219 -0
- tenxgraph_api/src/app/routers/graph/services/multimodal_preprocessor.py +164 -0
- tenxgraph_api/src/app/routers/media/__init__.py +506 -0
- tenxgraph_api/src/app/routers/media/router.py +242 -0
- tenxgraph_api/src/app/routers/media/schemas.py +39 -0
- tenxgraph_api/src/app/routers/ping/__init__.py +4 -0
- tenxgraph_api/src/app/routers/ping/router.py +28 -0
- tenxgraph_api/src/app/routers/setup_router.py +60 -0
- tenxgraph_api/src/app/routers/store/__init__.py +4 -0
- tenxgraph_api/src/app/routers/store/router.py +200 -0
- tenxgraph_api/src/app/routers/store/schemas/__init__.py +28 -0
- tenxgraph_api/src/app/routers/store/schemas/store_schemas.py +200 -0
- tenxgraph_api/src/app/routers/store/services/__init__.py +4 -0
- tenxgraph_api/src/app/routers/store/services/store_service.py +203 -0
- tenxgraph_api/src/app/tasks/__init__.py +0 -0
- tenxgraph_api/src/app/tasks/user_tasks.py +38 -0
- tenxgraph_api/src/app/utils/__init__.py +12 -0
- tenxgraph_api/src/app/utils/callable_helper.py +26 -0
- tenxgraph_api/src/app/utils/media/__init__.py +15 -0
- tenxgraph_api/src/app/utils/media/extractor.py +172 -0
- tenxgraph_api/src/app/utils/media/pipeline.py +83 -0
- tenxgraph_api/src/app/utils/parse_output.py +17 -0
- tenxgraph_api/src/app/utils/response_helper.py +129 -0
- tenxgraph_api/src/app/utils/schemas/__init__.py +11 -0
- tenxgraph_api/src/app/utils/schemas/output_schemas.py +28 -0
- tenxgraph_api/src/app/utils/schemas/user_schemas.py +13 -0
- tenxgraph_api/src/app/utils/snowflake_id_generator.py +90 -0
- tenxgraph_api/src/app/utils/swagger_helper.py +160 -0
- tenxgraph_api/src/app/utils/telemetry_store.py +123 -0
- tenxgraph_api/src/app/utils/thread_name_generator.py +304 -0
- tenxgraph_api/src/app/worker.py +91 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from tenxgraph.utils.validators import PromptInjectionValidator
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
prompt_validator = PromptInjectionValidator(
|
|
5
|
+
strict_mode=True,
|
|
6
|
+
max_length=1000,
|
|
7
|
+
blocked_patterns=[],
|
|
8
|
+
suspicious_keywords=[
|
|
9
|
+
"ignore previous",
|
|
10
|
+
"forget previous",
|
|
11
|
+
"disregard previous",
|
|
12
|
+
"bypass",
|
|
13
|
+
"circumvent",
|
|
14
|
+
"override",
|
|
15
|
+
"disable",
|
|
16
|
+
"remove restrictions",
|
|
17
|
+
"token",
|
|
18
|
+
"coupon",
|
|
19
|
+
"free",
|
|
20
|
+
],
|
|
21
|
+
)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "$agent_name_slug"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "$agent_name — an AI agent built with 10xGraph."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.12"
|
|
12
|
+
authors = []
|
|
13
|
+
dependencies = [
|
|
14
|
+
"10xgraph",
|
|
15
|
+
"10xgraph-api",
|
|
16
|
+
"google-genai",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.optional-dependencies]
|
|
20
|
+
test = [
|
|
21
|
+
"pytest",
|
|
22
|
+
"pytest-asyncio",
|
|
23
|
+
"pytest-cov",
|
|
24
|
+
"pytest-env",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[tool.ruff]
|
|
28
|
+
line-length = 100
|
|
29
|
+
target-version = "py312"
|
|
30
|
+
lint.fixable = ["ALL"]
|
|
31
|
+
lint.select = [
|
|
32
|
+
"E", "W", "F", "PL", "I", "B", "A", "S", "ISC", "ICN", "PIE", "Q",
|
|
33
|
+
"RET", "SIM", "TID", "RUF", "YTT", "UP", "C4", "PTH", "G", "INP", "T20",
|
|
34
|
+
]
|
|
35
|
+
lint.ignore = [
|
|
36
|
+
"UP006", "UP007", "RUF012", "G004", "B904", "B008", "ISC001",
|
|
37
|
+
]
|
|
38
|
+
lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
39
|
+
exclude = ["venv/*"]
|
|
40
|
+
|
|
41
|
+
[tool.ruff.lint.per-file-ignores]
|
|
42
|
+
"*/tests/*.py" = ["S101", "T201"]
|
|
43
|
+
"*/__init__.py" = ["E402", "S101"]
|
|
44
|
+
|
|
45
|
+
[tool.ruff.lint.isort]
|
|
46
|
+
lines-after-imports = 2
|
|
47
|
+
|
|
48
|
+
[tool.ruff.format]
|
|
49
|
+
docstring-code-format = true
|
|
50
|
+
|
|
51
|
+
[tool.ruff.lint.pydocstyle]
|
|
52
|
+
convention = "google"
|
|
53
|
+
|
|
54
|
+
[tool.bandit]
|
|
55
|
+
skips = ["B101"]
|
|
56
|
+
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
env = ["ENVIRONMENT=pytest"]
|
|
59
|
+
testpaths = ["tests"]
|
|
60
|
+
pythonpath = ["."]
|
|
61
|
+
filterwarnings = ["ignore::DeprecationWarning"]
|
|
62
|
+
addopts = [
|
|
63
|
+
"--cov=graph", "--cov-report=html", "--cov-report=term-missing",
|
|
64
|
+
"--cov-report=xml", "--cov-fail-under=0", "--strict-markers", "-v"
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
[tool.coverage.run]
|
|
68
|
+
source = ["graph"]
|
|
69
|
+
branch = true
|
|
70
|
+
omit = [
|
|
71
|
+
"*/__init__.py", "*/tests/*", "*/venv/*", "*/.venv/*",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[tool.coverage.report]
|
|
75
|
+
exclude_lines = [
|
|
76
|
+
"if __name__ == '__main__':", "pragma: no cover", "@abstractmethod",
|
|
77
|
+
"raise NotImplementedError",
|
|
78
|
+
]
|
|
79
|
+
show_missing = true
|
|
File without changes
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
|
|
5
|
+
from tenxgraph.qa import QuickTest
|
|
6
|
+
from tenxgraph.qa.evaluation import (
|
|
7
|
+
CriterionResult,
|
|
8
|
+
EvalCaseResult,
|
|
9
|
+
EvalReport,
|
|
10
|
+
EvalSummary,
|
|
11
|
+
ReporterConfig,
|
|
12
|
+
ReporterManager,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from evals.weather_agents_eval import get_eval_set
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_eval_set_covers_core_weather_behaviors() -> None:
|
|
19
|
+
eval_set = get_eval_set()
|
|
20
|
+
|
|
21
|
+
case_ids = {case.eval_id for case in eval_set.eval_cases}
|
|
22
|
+
case_names = {case.name for case in eval_set.eval_cases}
|
|
23
|
+
|
|
24
|
+
assert eval_set.name == "weather-agent-regression"
|
|
25
|
+
assert len(eval_set.eval_cases) == 4
|
|
26
|
+
assert "greeting_response" in case_names
|
|
27
|
+
assert "weather_london" in case_ids
|
|
28
|
+
assert "weather_new_york" in case_ids
|
|
29
|
+
assert "weather_tokyo" in case_ids
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_reporter_writes_html_and_json_artifacts(tmp_path) -> None:
|
|
33
|
+
report = EvalReport(
|
|
34
|
+
eval_set_id="weather-agent-regression",
|
|
35
|
+
eval_set_name="weather-agent-regression",
|
|
36
|
+
results=[
|
|
37
|
+
EvalCaseResult(
|
|
38
|
+
eval_id="sample",
|
|
39
|
+
name="sample",
|
|
40
|
+
passed=True,
|
|
41
|
+
actual_response="The weather in London is sunny",
|
|
42
|
+
criterion_results=[
|
|
43
|
+
CriterionResult(
|
|
44
|
+
criterion="response",
|
|
45
|
+
score=1.0,
|
|
46
|
+
passed=True,
|
|
47
|
+
threshold=0.6,
|
|
48
|
+
)
|
|
49
|
+
],
|
|
50
|
+
)
|
|
51
|
+
],
|
|
52
|
+
summary=EvalSummary(
|
|
53
|
+
total_cases=1,
|
|
54
|
+
passed_cases=1,
|
|
55
|
+
failed_cases=0,
|
|
56
|
+
error_cases=0,
|
|
57
|
+
pass_rate=1.0,
|
|
58
|
+
),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
output = ReporterManager(
|
|
62
|
+
ReporterConfig(output_dir=str(tmp_path), html=True, json_report=True, console=False)
|
|
63
|
+
).run_all(report, output_dir=str(tmp_path))
|
|
64
|
+
|
|
65
|
+
assert output.json_path is not None
|
|
66
|
+
assert output.html_path is not None
|
|
67
|
+
assert "weather-agent-regression" in tmp_path.joinpath(output.json_path).read_text(
|
|
68
|
+
encoding="utf-8"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_quick_test_smoke_for_expected_weather_greeting() -> None:
|
|
73
|
+
result = QuickTest.single_turn(
|
|
74
|
+
agent_response="Hello! I can help you check the weather anywhere. What location are you interested in?",
|
|
75
|
+
user_message="Hi",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
asyncio.run(result).assert_contains("weather").assert_no_errors()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from unittest.mock import MagicMock, patch
|
|
4
|
+
|
|
5
|
+
from graph.state import WeatherState
|
|
6
|
+
from graph.tools.weather_tool import get_weather
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_get_weather_returns_sunny_message_for_location() -> None:
|
|
10
|
+
with patch(
|
|
11
|
+
"graph.tools.weather_tool.call_weather_api", return_value="The weather in London is sunny"
|
|
12
|
+
):
|
|
13
|
+
result = get_weather(location="London")
|
|
14
|
+
|
|
15
|
+
assert "London" in result
|
|
16
|
+
assert "sunny" in result
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_get_weather_retries_on_failure_and_returns_error_after_max_attempts() -> None:
|
|
20
|
+
with patch("graph.tools.weather_tool.call_weather_api", side_effect=Exception("API error")):
|
|
21
|
+
result = get_weather(location="Paris")
|
|
22
|
+
|
|
23
|
+
assert "Paris" in result
|
|
24
|
+
assert "sorry" in result.lower()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_get_weather_emits_progress_events_when_emitter_is_provided() -> None:
|
|
28
|
+
emit = MagicMock()
|
|
29
|
+
|
|
30
|
+
with patch(
|
|
31
|
+
"graph.tools.weather_tool.call_weather_api", return_value="The weather in Tokyo is sunny"
|
|
32
|
+
):
|
|
33
|
+
result = get_weather(location="Tokyo", emit=emit)
|
|
34
|
+
|
|
35
|
+
emit.progress.assert_called()
|
|
36
|
+
assert "Tokyo" in result
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_get_weather_accepts_injected_tool_call_id_and_state() -> None:
|
|
40
|
+
state = WeatherState()
|
|
41
|
+
|
|
42
|
+
with patch(
|
|
43
|
+
"graph.tools.weather_tool.call_weather_api", return_value="The weather in Berlin is sunny"
|
|
44
|
+
):
|
|
45
|
+
result = get_weather(location="Berlin", tool_call_id="call_1", state=state)
|
|
46
|
+
|
|
47
|
+
assert "Berlin" in result
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import SimpleNamespace
|
|
4
|
+
|
|
5
|
+
from tenxgraph.core.state.message import Message
|
|
6
|
+
from tenxgraph.utils.constants import END
|
|
7
|
+
|
|
8
|
+
from graph.nodes.main_node import agent
|
|
9
|
+
from graph.utils.tool_decision import should_use_tools
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_main_agent_is_configured_for_weather_assistant() -> None:
|
|
13
|
+
assert agent.model == "gemini-3-flash-preview"
|
|
14
|
+
assert agent.provider == "google"
|
|
15
|
+
assert agent.trim_context is True
|
|
16
|
+
assert agent.tool_node == "TOOL"
|
|
17
|
+
|
|
18
|
+
system_prompt_text = " ".join(
|
|
19
|
+
block["content"] for block in agent.system_prompt if "content" in block
|
|
20
|
+
)
|
|
21
|
+
assert "helpful assistant" in system_prompt_text.lower()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_should_end_when_no_context_exists() -> None:
|
|
25
|
+
assert should_use_tools(SimpleNamespace(context=[])) == END
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_should_route_assistant_tool_calls_to_tool_node() -> None:
|
|
29
|
+
state = SimpleNamespace(
|
|
30
|
+
context=[
|
|
31
|
+
Message(
|
|
32
|
+
role="assistant",
|
|
33
|
+
content=[],
|
|
34
|
+
tools_calls=[
|
|
35
|
+
{
|
|
36
|
+
"id": "call_1",
|
|
37
|
+
"name": "get_weather",
|
|
38
|
+
"args": {"location": "London"},
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
)
|
|
42
|
+
]
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
assert should_use_tools(state) == "TOOL"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_should_route_tool_result_back_to_main_agent() -> None:
|
|
49
|
+
state = SimpleNamespace(context=[Message(role="tool", content=[])])
|
|
50
|
+
|
|
51
|
+
assert should_use_tools(state) == "MAIN"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_should_end_after_regular_assistant_response() -> None:
|
|
55
|
+
state = SimpleNamespace(context=[Message(role="assistant", content=[])])
|
|
56
|
+
|
|
57
|
+
assert should_use_tools(state) == END
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 10xgraph
|
|
3
|
+
description: >-
|
|
4
|
+
Expert guidance for building, debugging, and extending applications with 10xGraph
|
|
5
|
+
(10xgraph). Use when code imports from tenxgraph or the legacy agentflow name (e.g. `from tenxgraph import`,
|
|
6
|
+
`StateGraph`, `Agent`, `ToolNode`, `AgentState`); when the user references `10xgraph.json`
|
|
7
|
+
or CLI commands (`10xgraph init`, `10xgraph api`, `10xgraph play`, `10xgraph build`,
|
|
8
|
+
`10xgraph skills`); or when the user is building graph-based multi-agent workflows, tools,
|
|
9
|
+
memory, checkpointing, or streaming with this framework. Skip generic Python or multi-agent
|
|
10
|
+
questions that do not reference 10xGraph, and other frameworks (LangGraph, CrewAI, AutoGen)
|
|
11
|
+
unless comparing.
|
|
12
|
+
license: MIT
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# 10xGraph Project Skill
|
|
16
|
+
|
|
17
|
+
Use this skill when working in a 10xGraph project. 10xGraph is a multi-agent framework that wraps official OpenAI and Google SDK capabilities behind a unified graph, agent, tool, state, storage, API, CLI, and TypeScript client interface.
|
|
18
|
+
|
|
19
|
+
Treat https://10xgraph.com/ as the first source of truth for public package names, install commands, and user-facing behavior. Use implementation source after the docs establish the intended API.
|
|
20
|
+
|
|
21
|
+
## Workflow
|
|
22
|
+
|
|
23
|
+
1. Identify the published package or docs surface involved:
|
|
24
|
+
- PyPI core Python SDK: `10xgraph` (`pip install 10xgraph`), source at https://github.com/10xGraph/10xGraph/tree/main/tenxgraph
|
|
25
|
+
- PyPI API/CLI SDK: `10xgraph-api` (`pip install 10xgraph-api`), source at https://github.com/10xGraph/10xgraph-api/tree/main/tenxgraph_api
|
|
26
|
+
- npm TypeScript SDK: `@10xscale/agentflow-client` (`npm install @10xscale/agentflow-client`), source at https://github.com/10xHub/Agentflow/tree/main/agentflow-client/src
|
|
27
|
+
- Main docs: https://10xgraph.com/
|
|
28
|
+
- Playground/UI: `10xgraph play` command after installed cli
|
|
29
|
+
|
|
30
|
+
2. Read the matching reference file before changing behavior. Paths are relative to this skill's directory:
|
|
31
|
+
|
|
32
|
+
### Core Python SDK
|
|
33
|
+
- Architecture and package flow: `references/architecture.md`
|
|
34
|
+
- Agent constructor, provider, reasoning, retry, fallback, output_schema: `references/agents-and-tools.md`
|
|
35
|
+
- Graph construction, nodes, edges, compile, interrupts, config keys: `references/state-graph.md`
|
|
36
|
+
- State, messages, and content blocks: `references/state-and-messages.md`
|
|
37
|
+
- Threads and checkpointing: `references/checkpointing-and-threads.md`
|
|
38
|
+
- Dependency injection (InjectQ): `references/dependency-injection.md`
|
|
39
|
+
- Multimodal files and media stores: `references/media-and-files.md`
|
|
40
|
+
- Long-term memory stores (MemoryConfig, QdrantStore, Mem0Store): `references/memory-and-store.md`
|
|
41
|
+
- Streaming, StreamChunk, SSE, ResponseGranularity: `references/streaming.md`
|
|
42
|
+
- Stream emitter for tool progress updates: `references/stream-emitter.md`
|
|
43
|
+
- Observability hooks, validators, and runtime jumps: `references/callbacks-and-command.md`
|
|
44
|
+
- Prebuilt agents (ReactAgent, PlanActReflectAgent, StructuredOutputAgent, SupervisorTeamAgent, SwarmAgent, RAGAgent) and tools: `references/prebuilt-agents-and-tools.md`
|
|
45
|
+
- Event publishers and A2A/ACP runtime protocols: `references/publishers-and-runtime-protocols.md`
|
|
46
|
+
- Context management, ID generation, and background tasks: `references/context-id-background.md`
|
|
47
|
+
- Provider internals and adapters: `references/providers-and-adapters.md`
|
|
48
|
+
- Prompt-injection and validation safety: `references/security-and-validators.md`
|
|
49
|
+
- Realtime audio-to-audio voice agents (AudioAgent, Gemini Live, `arealtime`, WebSocket bridge): `references/realtime.md`
|
|
50
|
+
|
|
51
|
+
### API/CLI SDK
|
|
52
|
+
- CLI commands and generated project files: `references/cli-commands.md`
|
|
53
|
+
- `10xgraph.json` and dependency loading: `references/api-configuration.md`
|
|
54
|
+
- API auth and authorization: `references/auth-and-authorization.md`
|
|
55
|
+
- API environment, settings, and middleware: `references/api-settings-and-middleware.md`
|
|
56
|
+
- Rate limiting (config, backends, headers, custom backend): `references/rate-limiting.md`
|
|
57
|
+
- REST routes and error behavior: `references/rest-api-and-errors.md`
|
|
58
|
+
- API Snowflake IDs and thread naming: `references/id-and-thread-name-generators.md`
|
|
59
|
+
- API server and deployment runtime: `references/production-runtime.md`
|
|
60
|
+
|
|
61
|
+
### TypeScript client SDK
|
|
62
|
+
- REST and TypeScript client surface: `references/api-client.md`
|
|
63
|
+
- Browser/client-side tool execution: `references/remote-tools.md`
|
|
64
|
+
- TypeScript auth helpers and structured errors: `references/client-auth-and-errors.md`
|
|
65
|
+
- TypeScript messages, invoke, and stream details: `references/client-messages-invoke-stream.md`
|
|
66
|
+
- TypeScript thread, memory, and file APIs: `references/client-threads-memory-files.md`
|
|
67
|
+
|
|
68
|
+
### Testing and QA
|
|
69
|
+
- Unit testing without LLM calls (TestAgent, QuickTest, MockToolRegistry, `10xgraph test`): `references/unit-testing.md`
|
|
70
|
+
- Evaluation framework (EvalSet, criteria, AgentEvaluator, QuickEval, UserSimulator, `10xgraph eval`): `references/evaluation.md`
|
|
71
|
+
- Testing helpers overview: `references/testing-and-evaluation.md`
|
|
72
|
+
|
|
73
|
+
3. Prefer existing 10xGraph abstractions over new custom wiring:
|
|
74
|
+
- Build workflows with `StateGraph`, `Agent`, `ToolNode`, `AgentState`, and `Message`.
|
|
75
|
+
- Use prebuilt agents (`ReactAgent`, `PlanActReflectAgent`, `StructuredOutputAgent`, `SupervisorTeamAgent`, `SwarmAgent`, `RAGAgent`) for common patterns before hand-writing graph loops.
|
|
76
|
+
- Persist conversation state with checkpointers; use stores only for cross-thread memory.
|
|
77
|
+
- Put business services in `InjectQ` instead of global variables.
|
|
78
|
+
- Keep API/CLI graph modules storage-agnostic and wire dependencies through `10xgraph.json`.
|
|
79
|
+
|
|
80
|
+
4. Verify against source when implementation details matter. Public names and expected behavior should match https://10xgraph.com/; source under https://github.com/10xGraph/10xGraph (core), https://github.com/10xGraph/10xgraph-api (API/CLI), and https://github.com/10xHub/agentflow-client (TypeScript) explains how that behavior is implemented.
|
|
81
|
+
|
|
82
|
+
## Local Conventions
|
|
83
|
+
|
|
84
|
+
- A compiled graph is normally loaded once by the API server and reused per request.
|
|
85
|
+
- Public package naming matters: use `10xgraph`, `10xgraph-api`, and `@10xscale/agentflow-client` in user-facing docs and examples, not repository folder names.
|
|
86
|
+
- Every persisted interaction should include `config.thread_id`.
|
|
87
|
+
- Tools need docstrings and type annotations so model-facing schemas are useful.
|
|
88
|
+
- Injectable tool and node parameters (`state`, `config`, `tool_call_id`) are hidden from the model schema.
|
|
89
|
+
- For production, avoid process-local storage for shared state; use durable checkpointer/store backends.
|
|
90
|
+
- Add observability or audit side effects by registering a `GraphLifecycleHook` on `CallbackManager` — do not wrap `ainvoke()` / `astream()` calls in application code to achieve the same result.
|
|
91
|
+
- `reasoning_config` is on by default at medium effort; disable explicitly with `reasoning_config=None` when not needed.
|
|
92
|
+
- Provider is auto-detected from the model name; use `base_url` for third-party OpenAI-compatible APIs (Ollama, DeepSeek, OpenRouter).
|