create-context-graph 0.1.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.
- create_context_graph/__init__.py +3 -0
- create_context_graph/__main__.py +5 -0
- create_context_graph/cli.py +157 -0
- create_context_graph/config.py +76 -0
- create_context_graph/domains/_base.yaml +82 -0
- create_context_graph/domains/agent-memory.yaml +390 -0
- create_context_graph/domains/conservation.yaml +407 -0
- create_context_graph/domains/data-journalism.yaml +408 -0
- create_context_graph/domains/digital-twin.yaml +402 -0
- create_context_graph/domains/financial-services.yaml +357 -0
- create_context_graph/domains/gaming.yaml +429 -0
- create_context_graph/domains/genai-llm-ops.yaml +384 -0
- create_context_graph/domains/gis-cartography.yaml +421 -0
- create_context_graph/domains/golf-sports.yaml +409 -0
- create_context_graph/domains/healthcare.yaml +411 -0
- create_context_graph/domains/hospitality.yaml +433 -0
- create_context_graph/domains/manufacturing.yaml +420 -0
- create_context_graph/domains/oil-gas.yaml +445 -0
- create_context_graph/domains/personal-knowledge.yaml +387 -0
- create_context_graph/domains/product-management.yaml +434 -0
- create_context_graph/domains/real-estate.yaml +441 -0
- create_context_graph/domains/retail-ecommerce.yaml +415 -0
- create_context_graph/domains/scientific-research.yaml +421 -0
- create_context_graph/domains/software-engineering.yaml +406 -0
- create_context_graph/domains/trip-planning.yaml +419 -0
- create_context_graph/domains/vacation-industry.yaml +427 -0
- create_context_graph/domains/wildlife-management.yaml +413 -0
- create_context_graph/fixtures/agent-memory.json +1133 -0
- create_context_graph/fixtures/conservation.json +1115 -0
- create_context_graph/fixtures/data-journalism.json +1188 -0
- create_context_graph/fixtures/digital-twin.json +1143 -0
- create_context_graph/fixtures/financial-services.json +1154 -0
- create_context_graph/fixtures/gaming.json +1227 -0
- create_context_graph/fixtures/genai-llm-ops.json +1128 -0
- create_context_graph/fixtures/gis-cartography.json +1225 -0
- create_context_graph/fixtures/golf-sports.json +1222 -0
- create_context_graph/fixtures/healthcare.json +1441 -0
- create_context_graph/fixtures/hospitality.json +1250 -0
- create_context_graph/fixtures/manufacturing.json +1175 -0
- create_context_graph/fixtures/oil-gas.json +1223 -0
- create_context_graph/fixtures/personal-knowledge.json +1139 -0
- create_context_graph/fixtures/product-management.json +1209 -0
- create_context_graph/fixtures/real-estate.json +1224 -0
- create_context_graph/fixtures/retail-ecommerce.json +1172 -0
- create_context_graph/fixtures/scientific-research.json +1180 -0
- create_context_graph/fixtures/software-engineering.json +1518 -0
- create_context_graph/fixtures/trip-planning.json +1243 -0
- create_context_graph/fixtures/vacation-industry.json +1159 -0
- create_context_graph/fixtures/wildlife-management.json +1189 -0
- create_context_graph/generator.py +378 -0
- create_context_graph/ingest.py +288 -0
- create_context_graph/neo4j_validator.py +25 -0
- create_context_graph/ontology.py +365 -0
- create_context_graph/renderer.py +222 -0
- create_context_graph/templates/backend/agents/claude_agent_sdk/agent.py.j2 +143 -0
- create_context_graph/templates/backend/agents/crewai/agent.py.j2 +94 -0
- create_context_graph/templates/backend/agents/google_adk/agent.py.j2 +103 -0
- create_context_graph/templates/backend/agents/langgraph/agent.py.j2 +94 -0
- create_context_graph/templates/backend/agents/maf/agent.py.j2 +115 -0
- create_context_graph/templates/backend/agents/openai_agents/agent.py.j2 +81 -0
- create_context_graph/templates/backend/agents/pydanticai/agent.py.j2 +97 -0
- create_context_graph/templates/backend/agents/strands/agent.py.j2 +84 -0
- create_context_graph/templates/backend/shared/agent_stub.py.j2 +36 -0
- create_context_graph/templates/backend/shared/config.py.j2 +20 -0
- create_context_graph/templates/backend/shared/context_graph_client.py.j2 +88 -0
- create_context_graph/templates/backend/shared/gds_client.py.j2 +82 -0
- create_context_graph/templates/backend/shared/generate_data.py.j2 +85 -0
- create_context_graph/templates/backend/shared/main.py.j2 +41 -0
- create_context_graph/templates/backend/shared/models.py.j2 +3 -0
- create_context_graph/templates/backend/shared/pyproject.toml.j2 +23 -0
- create_context_graph/templates/backend/shared/routes.py.j2 +104 -0
- create_context_graph/templates/backend/shared/vector_client.py.j2 +84 -0
- create_context_graph/templates/base/Makefile.j2 +60 -0
- create_context_graph/templates/base/README.md.j2 +79 -0
- create_context_graph/templates/base/docker-compose.yml.j2 +17 -0
- create_context_graph/templates/base/dot_env.j2 +15 -0
- create_context_graph/templates/base/gitignore.j2 +30 -0
- create_context_graph/templates/cypher/gds_projections.cypher.j2 +29 -0
- create_context_graph/templates/cypher/schema.cypher.j2 +4 -0
- create_context_graph/templates/frontend/app/globals.css.j2 +12 -0
- create_context_graph/templates/frontend/app/layout.tsx.j2 +23 -0
- create_context_graph/templates/frontend/app/page.tsx.j2 +46 -0
- create_context_graph/templates/frontend/components/ChatInterface.tsx.j2 +147 -0
- create_context_graph/templates/frontend/components/ContextGraphView.tsx.j2 +154 -0
- create_context_graph/templates/frontend/components/DecisionTracePanel.tsx.j2 +158 -0
- create_context_graph/templates/frontend/components/Provider.tsx.j2 +9 -0
- create_context_graph/templates/frontend/lib/config.ts.j2 +26 -0
- create_context_graph/templates/frontend/next.config.ts.j2 +9 -0
- create_context_graph/templates/frontend/package.json.j2 +27 -0
- create_context_graph/templates/frontend/theme/index.ts.j2 +28 -0
- create_context_graph/templates/frontend/tsconfig.json.j2 +23 -0
- create_context_graph/wizard.py +165 -0
- create_context_graph-0.1.0.dist-info/METADATA +323 -0
- create_context_graph-0.1.0.dist-info/RECORD +97 -0
- create_context_graph-0.1.0.dist-info/WHEEL +4 -0
- create_context_graph-0.1.0.dist-info/entry_points.txt +2 -0
- create_context_graph-0.1.0.dist-info/licenses/LICENSE +190 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""CLI entry point for create-context-graph."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
10
|
+
|
|
11
|
+
from create_context_graph.config import SUPPORTED_FRAMEWORKS, ProjectConfig
|
|
12
|
+
from create_context_graph.ontology import list_available_domains, load_domain
|
|
13
|
+
from create_context_graph.renderer import ProjectRenderer
|
|
14
|
+
|
|
15
|
+
console = Console()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.command()
|
|
19
|
+
@click.argument("project_name", required=False)
|
|
20
|
+
@click.option(
|
|
21
|
+
"--domain",
|
|
22
|
+
type=str,
|
|
23
|
+
help="Domain ID (e.g., financial-services, healthcare, software-engineering)",
|
|
24
|
+
)
|
|
25
|
+
@click.option(
|
|
26
|
+
"--framework",
|
|
27
|
+
type=click.Choice(SUPPORTED_FRAMEWORKS, case_sensitive=False),
|
|
28
|
+
help="Agent framework to use",
|
|
29
|
+
)
|
|
30
|
+
@click.option("--demo-data", is_flag=True, help="Generate synthetic demo data")
|
|
31
|
+
@click.option("--ingest", is_flag=True, help="Ingest generated data into Neo4j")
|
|
32
|
+
@click.option("--neo4j-uri", envvar="NEO4J_URI", help="Neo4j connection URI")
|
|
33
|
+
@click.option("--neo4j-username", envvar="NEO4J_USERNAME", default="neo4j")
|
|
34
|
+
@click.option("--neo4j-password", envvar="NEO4J_PASSWORD", default="password")
|
|
35
|
+
@click.option("--anthropic-api-key", envvar="ANTHROPIC_API_KEY", help="Anthropic API key for LLM generation")
|
|
36
|
+
@click.option("--output-dir", type=click.Path(), help="Output directory (default: ./<project-name>)")
|
|
37
|
+
@click.option("--list-domains", is_flag=True, help="List available domains and exit")
|
|
38
|
+
@click.version_option(package_name="create-context-graph")
|
|
39
|
+
def main(
|
|
40
|
+
project_name: str | None,
|
|
41
|
+
domain: str | None,
|
|
42
|
+
framework: str | None,
|
|
43
|
+
demo_data: bool,
|
|
44
|
+
ingest: bool,
|
|
45
|
+
neo4j_uri: str | None,
|
|
46
|
+
neo4j_username: str,
|
|
47
|
+
neo4j_password: str,
|
|
48
|
+
anthropic_api_key: str | None,
|
|
49
|
+
output_dir: str | None,
|
|
50
|
+
list_domains: bool,
|
|
51
|
+
) -> None:
|
|
52
|
+
"""Create a domain-specific context graph application.
|
|
53
|
+
|
|
54
|
+
Generates a full-stack application with a FastAPI backend,
|
|
55
|
+
Next.js frontend, Neo4j knowledge graph, and AI agent—
|
|
56
|
+
all customized for your industry domain.
|
|
57
|
+
"""
|
|
58
|
+
# List domains mode
|
|
59
|
+
if list_domains:
|
|
60
|
+
domains = list_available_domains()
|
|
61
|
+
console.print("\n[bold]Available domains:[/bold]\n")
|
|
62
|
+
for d in domains:
|
|
63
|
+
console.print(f" {d['id']:30s} {d['name']}")
|
|
64
|
+
console.print()
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
# If all required args are provided, skip wizard
|
|
68
|
+
if project_name and domain and framework:
|
|
69
|
+
config = ProjectConfig(
|
|
70
|
+
project_name=project_name,
|
|
71
|
+
domain=domain,
|
|
72
|
+
framework=framework,
|
|
73
|
+
data_source="demo" if demo_data else "demo",
|
|
74
|
+
neo4j_uri=neo4j_uri or "neo4j://localhost:7687",
|
|
75
|
+
neo4j_username=neo4j_username,
|
|
76
|
+
neo4j_password=neo4j_password,
|
|
77
|
+
neo4j_type="docker",
|
|
78
|
+
anthropic_api_key=anthropic_api_key,
|
|
79
|
+
generate_data=demo_data,
|
|
80
|
+
)
|
|
81
|
+
else:
|
|
82
|
+
# Launch interactive wizard
|
|
83
|
+
from create_context_graph.wizard import run_wizard
|
|
84
|
+
|
|
85
|
+
config = run_wizard()
|
|
86
|
+
|
|
87
|
+
# Resolve output directory
|
|
88
|
+
out = Path(output_dir) if output_dir else Path.cwd() / config.project_slug
|
|
89
|
+
if out.exists() and any(out.iterdir()):
|
|
90
|
+
console.print(f"[red]Error:[/red] Directory {out} already exists and is not empty.")
|
|
91
|
+
raise SystemExit(1)
|
|
92
|
+
|
|
93
|
+
# Load domain ontology
|
|
94
|
+
try:
|
|
95
|
+
ontology = load_domain(config.domain)
|
|
96
|
+
except FileNotFoundError:
|
|
97
|
+
console.print(f"[red]Error:[/red] Domain '{config.domain}' not found.")
|
|
98
|
+
available = list_available_domains()
|
|
99
|
+
console.print("Available domains: " + ", ".join(d["id"] for d in available))
|
|
100
|
+
raise SystemExit(1)
|
|
101
|
+
|
|
102
|
+
# Generate project
|
|
103
|
+
with Progress(
|
|
104
|
+
SpinnerColumn(),
|
|
105
|
+
TextColumn("[progress.description]{task.description}"),
|
|
106
|
+
console=console,
|
|
107
|
+
) as progress:
|
|
108
|
+
task = progress.add_task("Creating project scaffold...", total=None)
|
|
109
|
+
|
|
110
|
+
renderer = ProjectRenderer(config, ontology)
|
|
111
|
+
renderer.render(out)
|
|
112
|
+
|
|
113
|
+
progress.update(task, description="Project generated!")
|
|
114
|
+
|
|
115
|
+
# Generate demo data if requested
|
|
116
|
+
fixture_path = out / "data" / "fixtures.json"
|
|
117
|
+
if config.generate_data or demo_data:
|
|
118
|
+
console.print("\n[bold]Generating demo data...[/bold]")
|
|
119
|
+
from create_context_graph.generator import generate_fixture_data
|
|
120
|
+
|
|
121
|
+
generate_fixture_data(
|
|
122
|
+
ontology,
|
|
123
|
+
fixture_path,
|
|
124
|
+
api_key=config.anthropic_api_key or anthropic_api_key,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Ingest into Neo4j if requested
|
|
128
|
+
if ingest and fixture_path.exists():
|
|
129
|
+
console.print("\n[bold]Ingesting data into Neo4j...[/bold]")
|
|
130
|
+
from create_context_graph.ingest import ingest_data
|
|
131
|
+
|
|
132
|
+
ingest_data(
|
|
133
|
+
fixture_path,
|
|
134
|
+
ontology,
|
|
135
|
+
config.neo4j_uri,
|
|
136
|
+
config.neo4j_username,
|
|
137
|
+
config.neo4j_password,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Success message
|
|
141
|
+
console.print()
|
|
142
|
+
console.print(f"[bold green]Done![/bold green] Your {ontology.domain.name} context graph app is ready.")
|
|
143
|
+
console.print()
|
|
144
|
+
try:
|
|
145
|
+
display_path = out.relative_to(Path.cwd())
|
|
146
|
+
except ValueError:
|
|
147
|
+
display_path = out
|
|
148
|
+
console.print(f" [bold]cd {display_path}[/bold]")
|
|
149
|
+
console.print(f" [bold]make install[/bold] # Install dependencies")
|
|
150
|
+
if config.neo4j_type == "docker":
|
|
151
|
+
console.print(f" [bold]make docker-up[/bold] # Start Neo4j")
|
|
152
|
+
console.print(f" [bold]make seed[/bold] # Seed sample data")
|
|
153
|
+
console.print(f" [bold]make start[/bold] # Start backend + frontend")
|
|
154
|
+
console.print()
|
|
155
|
+
console.print(f" Backend: http://localhost:8000")
|
|
156
|
+
console.print(f" Frontend: http://localhost:3000")
|
|
157
|
+
console.print()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Project configuration model."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field, computed_field
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
SUPPORTED_FRAMEWORKS = [
|
|
12
|
+
"pydanticai",
|
|
13
|
+
"claude-agent-sdk",
|
|
14
|
+
"strands",
|
|
15
|
+
"google-adk",
|
|
16
|
+
"openai-agents",
|
|
17
|
+
"langgraph",
|
|
18
|
+
"crewai",
|
|
19
|
+
"maf",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
FRAMEWORK_DISPLAY_NAMES = {
|
|
23
|
+
"pydanticai": "PydanticAI",
|
|
24
|
+
"claude-agent-sdk": "Claude Agent SDK",
|
|
25
|
+
"strands": "Strands (AWS)",
|
|
26
|
+
"google-adk": "Google ADK",
|
|
27
|
+
"openai-agents": "OpenAI Agents SDK",
|
|
28
|
+
"langgraph": "LangGraph",
|
|
29
|
+
"crewai": "CrewAI",
|
|
30
|
+
"maf": "MAF (Modular Agent Framework)",
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
FRAMEWORK_DEPENDENCIES = {
|
|
34
|
+
"pydanticai": ["pydantic-ai>=0.1"],
|
|
35
|
+
"claude-agent-sdk": ["claude-agent-sdk>=0.1"],
|
|
36
|
+
"strands": ["strands-agents>=0.1"],
|
|
37
|
+
"google-adk": ["google-adk>=0.1"],
|
|
38
|
+
"openai-agents": ["openai-agents>=0.1"],
|
|
39
|
+
"langgraph": ["langgraph>=0.1"],
|
|
40
|
+
"crewai": ["crewai>=0.1"],
|
|
41
|
+
"maf": ["maf>=0.1"],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ProjectConfig(BaseModel):
|
|
46
|
+
"""All configuration collected from the wizard or CLI flags."""
|
|
47
|
+
|
|
48
|
+
project_name: str = Field(description="Human-readable project name")
|
|
49
|
+
domain: str = Field(description="Domain ID from ontology YAML")
|
|
50
|
+
framework: str = Field(description="Agent framework key")
|
|
51
|
+
data_source: Literal["demo", "saas"] = Field(default="demo")
|
|
52
|
+
neo4j_uri: str = Field(default="neo4j://localhost:7687")
|
|
53
|
+
neo4j_username: str = Field(default="neo4j")
|
|
54
|
+
neo4j_password: str = Field(default="password")
|
|
55
|
+
neo4j_type: Literal["aurads", "aura-free", "docker", "existing"] = Field(
|
|
56
|
+
default="docker"
|
|
57
|
+
)
|
|
58
|
+
anthropic_api_key: str | None = Field(default=None)
|
|
59
|
+
openai_api_key: str | None = Field(default=None)
|
|
60
|
+
generate_data: bool = Field(default=False)
|
|
61
|
+
|
|
62
|
+
@computed_field
|
|
63
|
+
@property
|
|
64
|
+
def project_slug(self) -> str:
|
|
65
|
+
"""Kebab-case slug derived from project name."""
|
|
66
|
+
slug = self.project_name.lower().strip()
|
|
67
|
+
slug = re.sub(r"[^a-z0-9]+", "-", slug)
|
|
68
|
+
return slug.strip("-")
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def framework_display_name(self) -> str:
|
|
72
|
+
return FRAMEWORK_DISPLAY_NAMES.get(self.framework, self.framework)
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def framework_deps(self) -> list[str]:
|
|
76
|
+
return FRAMEWORK_DEPENDENCIES.get(self.framework, [])
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Base POLE+O ontology - shared foundation for all domains
|
|
2
|
+
# Person, Object, Location, Event + Organization
|
|
3
|
+
version: "1.0"
|
|
4
|
+
|
|
5
|
+
base_entity_types:
|
|
6
|
+
Person:
|
|
7
|
+
pole_type: PERSON
|
|
8
|
+
color: "#22c55e"
|
|
9
|
+
icon: user
|
|
10
|
+
base_properties:
|
|
11
|
+
- name: name
|
|
12
|
+
type: string
|
|
13
|
+
required: true
|
|
14
|
+
- name: email
|
|
15
|
+
type: string
|
|
16
|
+
- name: role
|
|
17
|
+
type: string
|
|
18
|
+
- name: description
|
|
19
|
+
type: string
|
|
20
|
+
|
|
21
|
+
Organization:
|
|
22
|
+
pole_type: ORGANIZATION
|
|
23
|
+
color: "#3b82f6"
|
|
24
|
+
icon: building
|
|
25
|
+
base_properties:
|
|
26
|
+
- name: name
|
|
27
|
+
type: string
|
|
28
|
+
required: true
|
|
29
|
+
- name: description
|
|
30
|
+
type: string
|
|
31
|
+
- name: industry
|
|
32
|
+
type: string
|
|
33
|
+
|
|
34
|
+
Location:
|
|
35
|
+
pole_type: LOCATION
|
|
36
|
+
color: "#a855f7"
|
|
37
|
+
icon: map-pin
|
|
38
|
+
base_properties:
|
|
39
|
+
- name: name
|
|
40
|
+
type: string
|
|
41
|
+
required: true
|
|
42
|
+
- name: address
|
|
43
|
+
type: string
|
|
44
|
+
- name: latitude
|
|
45
|
+
type: float
|
|
46
|
+
- name: longitude
|
|
47
|
+
type: float
|
|
48
|
+
|
|
49
|
+
Event:
|
|
50
|
+
pole_type: EVENT
|
|
51
|
+
color: "#f97316"
|
|
52
|
+
icon: calendar
|
|
53
|
+
base_properties:
|
|
54
|
+
- name: name
|
|
55
|
+
type: string
|
|
56
|
+
required: true
|
|
57
|
+
- name: date
|
|
58
|
+
type: datetime
|
|
59
|
+
- name: description
|
|
60
|
+
type: string
|
|
61
|
+
|
|
62
|
+
Object:
|
|
63
|
+
pole_type: OBJECT
|
|
64
|
+
color: "#eab308"
|
|
65
|
+
icon: box
|
|
66
|
+
base_properties:
|
|
67
|
+
- name: name
|
|
68
|
+
type: string
|
|
69
|
+
required: true
|
|
70
|
+
- name: description
|
|
71
|
+
type: string
|
|
72
|
+
|
|
73
|
+
base_relationships:
|
|
74
|
+
WORKS_FOR:
|
|
75
|
+
source: Person
|
|
76
|
+
target: Organization
|
|
77
|
+
LOCATED_AT:
|
|
78
|
+
source: Organization
|
|
79
|
+
target: Location
|
|
80
|
+
PARTICIPATED_IN:
|
|
81
|
+
source: Person
|
|
82
|
+
target: Event
|