fadenstack 0.4.2__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.
Files changed (99) hide show
  1. faden_cli/__init__.py +16 -0
  2. faden_cli/__main__.py +9 -0
  3. faden_cli/bundle/shared/.gitignore +25 -0
  4. faden_cli/bundle/shared/LICENSE +187 -0
  5. faden_cli/bundle/shared/NOTICE +15 -0
  6. faden_cli/bundle/shared/OFFICIAL.md +9 -0
  7. faden_cli/bundle/shared/README.md +16 -0
  8. faden_cli/bundle/shared/agent-binaries/.gitignore +5 -0
  9. faden_cli/bundle/shared/alloy/config.alloy +40 -0
  10. faden_cli/bundle/shared/clickhouse/config.d/system-logs.xml +26 -0
  11. faden_cli/bundle/shared/docker-compose.gpu.yaml +34 -0
  12. faden_cli/bundle/shared/docker-compose.yaml +998 -0
  13. faden_cli/bundle/shared/grafana/dashboards/templates/vllm-runtime.json +2099 -0
  14. faden_cli/bundle/shared/grafana/provisioning/dashboards/dashboard.yml +10 -0
  15. faden_cli/bundle/shared/grafana/provisioning/dashboards/json/faden-overview.json +211 -0
  16. faden_cli/bundle/shared/grafana/provisioning/datasources/ds.yaml +9 -0
  17. faden_cli/bundle/shared/grafana/provisioning/datasources/prometheus.yaml +15 -0
  18. faden_cli/bundle/shared/initdb/01-init.sql +32 -0
  19. faden_cli/bundle/shared/loki/local-config.yaml +32 -0
  20. faden_cli/bundle/shared/nginx/locations.conf +245 -0
  21. faden_cli/bundle/shared/nginx/maintenance.html +239 -0
  22. faden_cli/bundle/shared/nginx/nginx-tls.conf +79 -0
  23. faden_cli/bundle/shared/nginx/nginx.conf +44 -0
  24. faden_cli/bundle/shared/nginx/rate-limits.conf +42 -0
  25. faden_cli/bundle/shared/nginx/security-headers.conf +22 -0
  26. faden_cli/bundle/shared/nginx/select-config.sh +37 -0
  27. faden_cli/bundle/shared/prometheus/prometheus.yml +40 -0
  28. faden_cli/bundle/shared/rabbitmq/definitions.json.example +37 -0
  29. faden_cli/bundle/shared/tls/README.md +30 -0
  30. faden_cli/cli.py +158 -0
  31. faden_cli/commands/__init__.py +1 -0
  32. faden_cli/commands/admin.py +161 -0
  33. faden_cli/commands/backup.py +159 -0
  34. faden_cli/commands/config.py +146 -0
  35. faden_cli/commands/deploy.py +949 -0
  36. faden_cli/commands/dev/__init__.py +1 -0
  37. faden_cli/commands/dev/dev_doctor.py +46 -0
  38. faden_cli/commands/dev/dev_down.py +241 -0
  39. faden_cli/commands/dev/dev_group.py +24 -0
  40. faden_cli/commands/dev/dev_init.py +710 -0
  41. faden_cli/commands/dev/dev_pull.py +297 -0
  42. faden_cli/commands/dev/dev_status.py +151 -0
  43. faden_cli/commands/dev/dev_up.py +1392 -0
  44. faden_cli/commands/doctor.py +225 -0
  45. faden_cli/commands/down.py +75 -0
  46. faden_cli/commands/logs_cmd.py +41 -0
  47. faden_cli/commands/maintenance.py +74 -0
  48. faden_cli/commands/module.py +113 -0
  49. faden_cli/commands/observe.py +95 -0
  50. faden_cli/commands/ports.py +91 -0
  51. faden_cli/commands/rebuild.py +158 -0
  52. faden_cli/commands/restore.py +139 -0
  53. faden_cli/commands/runtime_images.py +174 -0
  54. faden_cli/commands/status.py +71 -0
  55. faden_cli/commands/tls.py +722 -0
  56. faden_cli/commands/tune.py +37 -0
  57. faden_cli/commands/up.py +64 -0
  58. faden_cli/commands/upgrade.py +470 -0
  59. faden_cli/commands/version.py +78 -0
  60. faden_cli/core/__init__.py +1 -0
  61. faden_cli/core/api_client.py +77 -0
  62. faden_cli/core/backup.py +717 -0
  63. faden_cli/core/bootstrap.py +291 -0
  64. faden_cli/core/bundle.py +110 -0
  65. faden_cli/core/clickhouse.py +61 -0
  66. faden_cli/core/compose.py +484 -0
  67. faden_cli/core/console.py +106 -0
  68. faden_cli/core/detect.py +580 -0
  69. faden_cli/core/dev_modules.py +149 -0
  70. faden_cli/core/docker_env.py +147 -0
  71. faden_cli/core/edge.py +94 -0
  72. faden_cli/core/env_gen.py +598 -0
  73. faden_cli/core/git.py +219 -0
  74. faden_cli/core/install.py +288 -0
  75. faden_cli/core/installation.py +186 -0
  76. faden_cli/core/local_node.py +719 -0
  77. faden_cli/core/maintenance.py +82 -0
  78. faden_cli/core/private_files.py +133 -0
  79. faden_cli/core/registry.py +574 -0
  80. faden_cli/core/release_feed.py +342 -0
  81. faden_cli/core/rmq.py +135 -0
  82. faden_cli/core/runtime_images.py +309 -0
  83. faden_cli/core/schedule.py +278 -0
  84. faden_cli/core/settings.py +159 -0
  85. faden_cli/core/sysinfo.py +303 -0
  86. faden_cli/core/tls.py +790 -0
  87. faden_cli/core/tune.py +154 -0
  88. faden_cli/core/update_check.py +254 -0
  89. faden_cli/core/workspace.py +155 -0
  90. faden_cli/templates/env.j2 +33 -0
  91. faden_cli/tui/__init__.py +1 -0
  92. faden_cli/tui/widgets/__init__.py +1 -0
  93. faden_cli/tui/wizard/__init__.py +1 -0
  94. fadenstack-0.4.2.dist-info/METADATA +304 -0
  95. fadenstack-0.4.2.dist-info/RECORD +99 -0
  96. fadenstack-0.4.2.dist-info/WHEEL +4 -0
  97. fadenstack-0.4.2.dist-info/entry_points.txt +3 -0
  98. fadenstack-0.4.2.dist-info/licenses/LICENSE +187 -0
  99. fadenstack-0.4.2.dist-info/licenses/NOTICE +15 -0
@@ -0,0 +1 @@
1
+ """Dev-mode commands for workspace and development stack management."""
@@ -0,0 +1,46 @@
1
+ """``faden dev doctor`` — check and optionally install prerequisites."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import click
6
+
7
+ from faden_cli.core.console import console, success, warning
8
+ from faden_cli.core.install import ensure_prerequisites
9
+
10
+ from .dev_group import dev_group
11
+
12
+
13
+ @dev_group.command("doctor")
14
+ @click.option(
15
+ "--install",
16
+ is_flag=True,
17
+ help="Offer to install missing tools (uv, git, node).",
18
+ )
19
+ @click.option(
20
+ "--yes", "-y",
21
+ is_flag=True,
22
+ help="Auto-confirm installation without prompting.",
23
+ )
24
+ def dev_doctor(*, install: bool, yes: bool) -> None:
25
+ """Check development prerequisites and system readiness.
26
+
27
+ Verifies that Docker, Git, uv, and Node.js are installed.
28
+ With --install, offers to install missing tools automatically.
29
+
30
+ \b
31
+ Examples:
32
+ faden dev doctor
33
+ faden dev doctor --install
34
+ faden dev doctor --install -y
35
+ """
36
+ console.print("\n[bold cyan]Checking prerequisites…[/bold cyan]")
37
+ all_ok = ensure_prerequisites(install=install, auto_confirm=yes)
38
+
39
+ if all_ok:
40
+ success("\nAll prerequisites are satisfied.")
41
+ else:
42
+ warning(
43
+ "\nSome prerequisites are missing. "
44
+ "Run [bold]faden dev doctor --install[/bold] to install them."
45
+ )
46
+ raise SystemExit(1)
@@ -0,0 +1,241 @@
1
+ """``faden dev down`` — stop the development environment (full reset).
2
+
3
+ Counterpart of ``faden dev up``:
4
+
5
+ 1. Stops the dev host processes (backend, taskiq worker, API gateway,
6
+ frontend) launched by ``dev up`` — on Windows/macOS/Linux.
7
+ 2. Runs ``docker compose down --volumes --remove-orphans`` on the shared
8
+ infrastructure compose file — removes the containers AND every named
9
+ data volume (postgres, redis, minio, clickhouse, langfuse, …).
10
+ 3. Deletes the generated secret/env files
11
+ (``shared/.env``, ``backend/.env``,
12
+ ``gateway/.env``) so the next ``dev up`` starts from a clean
13
+ slate with freshly generated credentials.
14
+
15
+ The full reset avoids the failure modes that occur when stale volumes or
16
+ env files from an older commit outlive a code update (alembic revision
17
+ not found, RMQ credential drift, …).
18
+
19
+ ``faden dev up`` regenerates any deleted env file (fresh dev
20
+ credentials + RMQ definitions) before infra starts, so the workspace is
21
+ always restorable with a plain ``dev up``.
22
+
23
+ Use ``--keep-infra`` to only stop the host processes and leave the shared
24
+ infra (and its data) running; ``dev up --skip-deps`` then restarts fast.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import platform
30
+ import shutil
31
+ import subprocess
32
+ import sys
33
+ from pathlib import Path
34
+
35
+ import click
36
+
37
+ from faden_cli.core.console import console, error, info, success, warning
38
+ from faden_cli.core.settings import load_config
39
+ from faden_cli.core.workspace import CORE_DIRNAME, dev_logs_dir, resolve_shared_compose
40
+
41
+ from .dev_group import dev_group
42
+
43
+ # (label, [pattern, …]) — a service counts as "was running" if ANY of its
44
+ # patterns matched a live process. Patterns are EREs over the full command
45
+ # line, tuned to the real `ps` output of a live dev stack:
46
+ #
47
+ # Backend uv run -m faden_backend → python3 -m faden_backend
48
+ # TaskIQ worker uv run taskiq worker faden_backend.tkq:broker … (+ forkserver)
49
+ # API gateway uv run -m faden_gateway → python3 -m faden_gateway
50
+ # Frontend npm run dev → node …/react-router dev
51
+ #
52
+ # The Backend pattern is ``m faden_backend`` (the ``-m`` module form),
53
+ # NOT bare ``faden_backend``: the worker's cmdline also contains
54
+ # ``faden_backend`` (so a bare match would kill the worker too), and
55
+ # ``postgres: … faden_backend …`` backend sessions carry the db name in
56
+ # their rewritten cmdline — both would be matched by a bare pattern. The
57
+ # ``m …`` form (leading dash dropped so pkill doesn't parse it as its own
58
+ # flag) hits only the real ``-m faden_backend`` server.
59
+ _DEV_PROCESS_PATTERNS: list[tuple[str, list[str]]] = [
60
+ # ``taskiq worker`` hits the uv launcher + taskiq main; the broker URI
61
+ # additionally hits the forkserver workers whose argv no longer carries
62
+ # the word "taskiq".
63
+ ("TaskIQ worker", ["taskiq worker", "faden_backend.tkq:broker"]),
64
+ ("API gateway", ["m faden_gateway"]),
65
+ ("Backend", ["m faden_backend"]),
66
+ ("Frontend", ["npm run dev", "react-router dev"]),
67
+ # Optional modules started by ``dev up --modules``.
68
+ ("PII", ["m faden_pii"]),
69
+ ("MCP", ["m faden_mcp"]),
70
+ ("Skills", ["m faden_skills"]),
71
+ ]
72
+
73
+
74
+ def _kill_pattern(pattern: str) -> bool:
75
+ """Kill processes whose command line matches *pattern*.
76
+
77
+ Returns ``True`` if at least one process was matched & killed.
78
+ Cross-platform: ``pkill -f`` on Unix, Win32 query on Windows.
79
+ """
80
+ system = platform.system()
81
+
82
+ if system in ("Linux", "Darwin"):
83
+ if not shutil.which("pkill"):
84
+ warning("pkill not found — cannot stop host processes.")
85
+ return False
86
+ result = subprocess.run(["pkill", "-f", pattern])
87
+ return result.returncode == 0
88
+
89
+ # Windows: match on the full command line, kill the whole set.
90
+ ps_cmd = (
91
+ "$m = Get-CimInstance Win32_Process | "
92
+ f"Where-Object {{ $_.CommandLine -like '*{pattern}*' }} | "
93
+ "Select-Object -ExpandProperty ProcessId; "
94
+ "if ($m) { Stop-Process -Id $m -Force -ErrorAction SilentlyContinue; 'KILLED' } "
95
+ "else { 'NONE' }"
96
+ )
97
+ result = subprocess.run(
98
+ ["powershell", "-NoProfile", "-Command", ps_cmd],
99
+ capture_output=True,
100
+ text=True,
101
+ )
102
+ return "KILLED" in result.stdout
103
+
104
+
105
+ def _stop_dev_processes() -> int:
106
+ """Stop every dev host process group. Returns how many groups matched."""
107
+ stopped = 0
108
+ for label, patterns in _DEV_PROCESS_PATTERNS:
109
+ matched = any(_kill_pattern(p) for p in patterns)
110
+ if matched:
111
+ stopped += 1
112
+ console.print(f" [green]✓[/green] {label}")
113
+ else:
114
+ console.print(f" [dim]○[/dim] {label} (not running)")
115
+ return stopped
116
+
117
+
118
+ def _find_workspace() -> Path:
119
+ """Resolve the dev workspace (shared with dev up / dev status)."""
120
+ from faden_cli.core.workspace import resolve_workspace
121
+
122
+ return resolve_workspace()
123
+
124
+
125
+ def _generated_env_files(workspace: Path) -> list[Path]:
126
+ """Locate the secret/env files generated by ``dev init`` / ``dev up``.
127
+
128
+ ``resolve_shared_compose`` handles the monorepo/flat layout for the
129
+ shared file; the service-local files follow the same two layouts, so
130
+ both candidate positions are collected and deduplicated.
131
+ """
132
+ env_files: list[Path] = []
133
+
134
+ compose_file = resolve_shared_compose(workspace)
135
+ if compose_file:
136
+ env_files.append(compose_file.parent / ".env")
137
+
138
+ for name in ("backend", "gateway"):
139
+ base = workspace / CORE_DIRNAME
140
+ for candidate in (base / name / ".env", workspace / name / ".env"):
141
+ if candidate not in env_files:
142
+ env_files.append(candidate)
143
+
144
+ return env_files
145
+
146
+
147
+ @dev_group.command("down")
148
+ @click.option(
149
+ "--keep-infra",
150
+ is_flag=True,
151
+ help="Only stop the dev host processes; leave shared infra containers, volumes and env files running/kept.",
152
+ )
153
+ @click.option("--yes", "-y", is_flag=True, help="Do not prompt for confirmation.")
154
+ def dev_down(*, keep_infra: bool, yes: bool) -> None:
155
+ """Stop the dev environment and reset its state (full teardown).
156
+
157
+ Kills the host processes, then removes the infra containers, the named
158
+ data volumes (postgres, redis, minio, clickhouse, langfuse, …) and the
159
+ generated .env secret files. Everything is regenerated on the next
160
+ ``faden dev up``.
161
+
162
+ \b
163
+ Examples:
164
+ faden dev down # full reset (prompts for confirmation)
165
+ faden dev down -y # full reset, no prompt (scripts)
166
+ faden dev down --keep-infra # stop only the host processes
167
+ """
168
+ console.print("\n[bold magenta]fadenstack — Dev Environment Teardown[/bold magenta]\n")
169
+
170
+ # ── 1. Stop host processes ───────────────────────────────────
171
+ console.print("[cyan]Stopping dev processes…[/cyan]")
172
+ stopped = _stop_dev_processes()
173
+ if stopped:
174
+ success(f"Stopped {stopped} dev process group(s).")
175
+ else:
176
+ info("No dev processes running.")
177
+
178
+ # ── 2. Keep-infra mode: host processes only ──────────────────
179
+ if keep_infra:
180
+ console.print(
181
+ f"\n[dim]Shared infra, volumes and .env files left running. Logs kept: {dev_logs_dir()}\n"
182
+ "[dim]Restart with: faden dev up --skip-deps[/dim]\n"
183
+ )
184
+ return
185
+
186
+ workspace = _find_workspace()
187
+ compose_file = resolve_shared_compose(workspace)
188
+ env_files = _generated_env_files(workspace)
189
+
190
+ if not yes:
191
+ if not click.confirm(
192
+ "[red]Full teardown:[/red] removes infra containers + "
193
+ "[red]all dev data volumes[/red] (postgres, redis, minio, "
194
+ "clickhouse, langfuse, …) and generated .env files. "
195
+ "Everything is regenerated on the next 'dev up'. Continue?",
196
+ default=False,
197
+ ):
198
+ error("Aborted — no changes made.")
199
+ sys.exit(1)
200
+
201
+ # ── 3. Stop shared infrastructure + volumes ──────────────────
202
+ if not compose_file:
203
+ warning(f"Shared compose file not found in {workspace}. Infra may have been started manually.")
204
+ else:
205
+ from faden_cli.core.compose import ComposeContext, down as compose_down
206
+
207
+ env_file = compose_file.parent / ".env"
208
+ if env_file.exists():
209
+ from faden_cli.commands.dev.dev_up import heal_dev_env
210
+
211
+ heal_dev_env(env_file)
212
+ ctx = ComposeContext(
213
+ compose_files=[compose_file],
214
+ env_file=env_file if env_file.exists() else None,
215
+ project_dir=compose_file.parent,
216
+ )
217
+ # NOTE: dev up only brings up INFRA_SERVICES, but `down` on the
218
+ # whole project is correct — it removes exactly the containers
219
+ # defined here that are actually running.
220
+ with console.status("[bold cyan]docker compose down --volumes --remove-orphans[/bold cyan]"):
221
+ rc = compose_down(ctx, volumes=True, remove_orphans=True)
222
+ if rc == 0:
223
+ success("Shared infrastructure and data volumes removed.")
224
+ else:
225
+ error(f"docker compose down exited with code {rc}.")
226
+ sys.exit(rc)
227
+
228
+ # ── 4. Remove generated env / secret files ───────────────────
229
+ removed = 0
230
+ for env_path in env_files:
231
+ if env_path.exists():
232
+ env_path.unlink()
233
+ removed += 1
234
+ info(f"Removed {env_path}")
235
+ if removed == 0:
236
+ info("No generated .env files to remove.")
237
+
238
+ console.print(
239
+ f"\n[dim]Dev state fully reset. Logs kept: {dev_logs_dir()}\n"
240
+ f"[dim]Start fresh with: faden dev up[/dim]\n"
241
+ )
@@ -0,0 +1,24 @@
1
+ """``faden dev`` — developer workflow commands."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import click
6
+
7
+
8
+ @click.group("dev")
9
+ def dev_group() -> None:
10
+ """Developer workflow — clone, set up, and run the dev environment."""
11
+
12
+
13
+ def _register_dev_commands() -> None:
14
+ """Import and register dev subcommands."""
15
+ # Importing these modules triggers the @dev_group.command() decorators
16
+ from faden_cli.commands.dev import dev_doctor as _doctor # noqa: F401
17
+ from faden_cli.commands.dev import dev_down as _down # noqa: F401
18
+ from faden_cli.commands.dev import dev_init as _init # noqa: F401
19
+ from faden_cli.commands.dev import dev_pull as _pull # noqa: F401
20
+ from faden_cli.commands.dev import dev_up as _up # noqa: F401
21
+ from faden_cli.commands.dev import dev_status as _status # noqa: F401
22
+
23
+
24
+ _register_dev_commands()