textfsm-ai 0.1.19__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 (30) hide show
  1. textfsm_ai-0.1.19/LICENSE +21 -0
  2. textfsm_ai-0.1.19/MANIFEST.in +3 -0
  3. textfsm_ai-0.1.19/PKG-INFO +65 -0
  4. textfsm_ai-0.1.19/README.md +17 -0
  5. textfsm_ai-0.1.19/pyproject.toml +124 -0
  6. textfsm_ai-0.1.19/setup.cfg +4 -0
  7. textfsm_ai-0.1.19/textfsm_ai/__init__.py +5 -0
  8. textfsm_ai-0.1.19/textfsm_ai/ai_router.py +57 -0
  9. textfsm_ai-0.1.19/textfsm_ai/api.py +5 -0
  10. textfsm_ai-0.1.19/textfsm_ai/cli/__init__.py +1 -0
  11. textfsm_ai-0.1.19/textfsm_ai/cli/_utils.py +61 -0
  12. textfsm_ai-0.1.19/textfsm_ai/cli/generate_cmd.py +29 -0
  13. textfsm_ai-0.1.19/textfsm_ai/cli/providers_cmd.py +11 -0
  14. textfsm_ai-0.1.19/textfsm_ai/cli/quota_cmd.py +7 -0
  15. textfsm_ai-0.1.19/textfsm_ai/cli/top.py +35 -0
  16. textfsm_ai-0.1.19/textfsm_ai/cli/version_cmd.py +8 -0
  17. textfsm_ai-0.1.19/textfsm_ai/config.yaml +24 -0
  18. textfsm_ai-0.1.19/textfsm_ai/config_loader.py +9 -0
  19. textfsm_ai-0.1.19/textfsm_ai/providers/__init__.py +0 -0
  20. textfsm_ai-0.1.19/textfsm_ai/providers/claude_provider.py +32 -0
  21. textfsm_ai-0.1.19/textfsm_ai/providers/deepseek_provider.py +28 -0
  22. textfsm_ai-0.1.19/textfsm_ai/providers/gemini_provider.py +25 -0
  23. textfsm_ai-0.1.19/textfsm_ai/providers/openai_provider.py +28 -0
  24. textfsm_ai-0.1.19/textfsm_ai/quota_manager.py +84 -0
  25. textfsm_ai-0.1.19/textfsm_ai.egg-info/PKG-INFO +65 -0
  26. textfsm_ai-0.1.19/textfsm_ai.egg-info/SOURCES.txt +28 -0
  27. textfsm_ai-0.1.19/textfsm_ai.egg-info/dependency_links.txt +1 -0
  28. textfsm_ai-0.1.19/textfsm_ai.egg-info/entry_points.txt +2 -0
  29. textfsm_ai-0.1.19/textfsm_ai.egg-info/requires.txt +21 -0
  30. textfsm_ai-0.1.19/textfsm_ai.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Geeks Trident LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ include LICENSE
2
+ include README.md
3
+ recursive-include textfsm_ai *.yaml
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: textfsm-ai
3
+ Version: 0.1.19
4
+ Summary: AI-powered TextFSM template generator with multi-provider routing
5
+ Author-email: Tuyen Mathew Duong <tuyen@geekstrident.com>
6
+ Maintainer-email: Tuyen Mathew Duong <tuyen@geekstrident.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/Geeks-Trident-LLC/textfsm-ai
9
+ Project-URL: Repository, https://github.com/Geeks-Trident-LLC/textfsm-ai
10
+ Project-URL: Issues, https://github.com/Geeks-Trident-LLC/textfsm-ai/issues
11
+ Project-URL: Documentation, https://geeks-trident-llc.github.io/textfsm-ai/latest/
12
+ Keywords: textfsm,network automation,cli parsing,template generator,ai,llm,openai,claude,gemini,deepseek,router,quota manager
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Information Technology
16
+ Classifier: Intended Audience :: System Administrators
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Classifier: Topic :: Software Development :: Code Generators
24
+ Classifier: Topic :: Text Processing
25
+ Classifier: Topic :: Utilities
26
+ Classifier: Operating System :: OS Independent
27
+ Requires-Python: >=3.9
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: PyYAML>=6.0
31
+ Requires-Dist: requests>=2.31
32
+ Requires-Dist: click>=8.1
33
+ Provides-Extra: dev
34
+ Requires-Dist: build; extra == "dev"
35
+ Requires-Dist: twine; extra == "dev"
36
+ Provides-Extra: test
37
+ Requires-Dist: pytest; extra == "test"
38
+ Requires-Dist: pytest-cov; extra == "test"
39
+ Provides-Extra: lint
40
+ Requires-Dist: ruff; extra == "lint"
41
+ Provides-Extra: all
42
+ Requires-Dist: build; extra == "all"
43
+ Requires-Dist: twine; extra == "all"
44
+ Requires-Dist: pytest; extra == "all"
45
+ Requires-Dist: pytest-cov; extra == "all"
46
+ Requires-Dist: ruff; extra == "all"
47
+ Dynamic: license-file
48
+
49
+ # textfsm-ai
50
+
51
+ **AI‑powered TextFSM template generation, parsing assistance, and smart log extraction.**
52
+
53
+ `textfsm-ai` brings modern LLM intelligence to traditional TextFSM workflows.
54
+ It helps you automatically generate templates, validate patterns, explain parsing logic, and accelerate network automation development.
55
+
56
+ ---
57
+
58
+ ## 🚀 Features
59
+
60
+ - **AI‑Powered Template Generation** — Turn raw CLI output into production‑ready TextFSM templates in seconds.
61
+ - **Smart Validation & Refinement** — Automatically verify template correctness and refine ambiguous patterns with AI assistance.
62
+ - **Built‑In Golden Master Testing** — Lock in deterministic parsing behavior and detect regressions instantly.
63
+ - **Flexible Multi‑Provider AI Routing** — Use the best AI model for each task with automatic routing across supported cloud providers.
64
+
65
+ ---
@@ -0,0 +1,17 @@
1
+ # textfsm-ai
2
+
3
+ **AI‑powered TextFSM template generation, parsing assistance, and smart log extraction.**
4
+
5
+ `textfsm-ai` brings modern LLM intelligence to traditional TextFSM workflows.
6
+ It helps you automatically generate templates, validate patterns, explain parsing logic, and accelerate network automation development.
7
+
8
+ ---
9
+
10
+ ## 🚀 Features
11
+
12
+ - **AI‑Powered Template Generation** — Turn raw CLI output into production‑ready TextFSM templates in seconds.
13
+ - **Smart Validation & Refinement** — Automatically verify template correctness and refine ambiguous patterns with AI assistance.
14
+ - **Built‑In Golden Master Testing** — Lock in deterministic parsing behavior and detect regressions instantly.
15
+ - **Flexible Multi‑Provider AI Routing** — Use the best AI model for each task with automatic routing across supported cloud providers.
16
+
17
+ ---
@@ -0,0 +1,124 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "textfsm-ai"
7
+ version = "0.1.19"
8
+ description = "AI-powered TextFSM template generator with multi-provider routing"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+
12
+ authors = [
13
+ { name = "Tuyen Mathew Duong", email = "tuyen@geekstrident.com" }
14
+ ]
15
+
16
+ maintainers = [
17
+ { name = "Tuyen Mathew Duong", email = "tuyen@geekstrident.com" }
18
+ ]
19
+
20
+ requires-python = ">=3.9"
21
+
22
+ dependencies = [
23
+ "PyYAML>=6.0",
24
+ "requests>=2.31",
25
+ "click>=8.1",
26
+ ]
27
+
28
+ classifiers = [
29
+ "Development Status :: 4 - Beta",
30
+ "Intended Audience :: Developers",
31
+ "Intended Audience :: Information Technology",
32
+ "Intended Audience :: System Administrators",
33
+
34
+ "Programming Language :: Python :: 3",
35
+ "Programming Language :: Python :: 3.9",
36
+ "Programming Language :: Python :: 3.10",
37
+ "Programming Language :: Python :: 3.11",
38
+ "Programming Language :: Python :: 3.12",
39
+
40
+ "Topic :: Software Development :: Libraries",
41
+ "Topic :: Software Development :: Code Generators",
42
+ "Topic :: Text Processing",
43
+ "Topic :: Utilities",
44
+
45
+ "Operating System :: OS Independent",
46
+ ]
47
+
48
+ keywords = [
49
+ "textfsm",
50
+ "network automation",
51
+ "cli parsing",
52
+ "template generator",
53
+ "ai",
54
+ "llm",
55
+ "openai",
56
+ "claude",
57
+ "gemini",
58
+ "deepseek",
59
+ "router",
60
+ "quota manager",
61
+ ]
62
+
63
+ [project.optional-dependencies]
64
+ dev = [
65
+ "build",
66
+ "twine",
67
+ ]
68
+
69
+ test = [
70
+ "pytest",
71
+ "pytest-cov",
72
+ ]
73
+
74
+ lint = [
75
+ "ruff",
76
+ ]
77
+
78
+ all = [
79
+ "build",
80
+ "twine",
81
+ "pytest",
82
+ "pytest-cov",
83
+ "ruff",
84
+ ]
85
+
86
+ [project.scripts]
87
+ textfsm-ai = "textfsm_ai.cli.top:main"
88
+
89
+ [project.urls]
90
+ Homepage = "https://github.com/Geeks-Trident-LLC/textfsm-ai"
91
+ Repository = "https://github.com/Geeks-Trident-LLC/textfsm-ai"
92
+ Issues = "https://github.com/Geeks-Trident-LLC/textfsm-ai/issues"
93
+ Documentation = "https://geeks-trident-llc.github.io/textfsm-ai/latest/"
94
+
95
+ [tool.setuptools]
96
+ include-package-data = true
97
+
98
+ [tool.setuptools.packages.find]
99
+ where = ["."]
100
+ include = ["textfsm_ai*"]
101
+ exclude = ["tests*", "docs*", "examples*"]
102
+
103
+ [tool.pytest.ini_options]
104
+ addopts = "-q --disable-warnings --maxfail=1"
105
+
106
+ # ---------------------------
107
+ # Formatting + Linting Tools
108
+ # ---------------------------
109
+
110
+ [tool.black]
111
+ line-length = 88
112
+ target-version = ["py39"]
113
+
114
+ [tool.isort]
115
+ profile = "black"
116
+ line_length = 88
117
+
118
+ [tool.ruff]
119
+ line-length = 88
120
+ target-version = "py39"
121
+
122
+ [tool.ruff.lint]
123
+ select = ["E", "F", "W"]
124
+ extend-select = ["I"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ __version__ = "0.1.19"
2
+ version = __version__
3
+
4
+
5
+ __all__ = ["version", "__version__"]
@@ -0,0 +1,57 @@
1
+ from textfsm_ai.config_loader import load_config
2
+ from textfsm_ai.providers.claude_provider import ClaudeProvider
3
+ from textfsm_ai.providers.deepseek_provider import DeepSeekProvider
4
+ from textfsm_ai.providers.gemini_provider import GeminiProvider
5
+ from textfsm_ai.providers.openai_provider import OpenAIProvider
6
+
7
+
8
+ class MultiProviderRouter:
9
+ def __init__(self):
10
+ cfg = load_config()
11
+
12
+ p = cfg["providers"]
13
+
14
+ self.openai = OpenAIProvider(
15
+ p["openai"]["api_key"],
16
+ p["openai"]["model"],
17
+ p["openai"]["daily_limit"],
18
+ p["openai"]["monthly_limit"],
19
+ )
20
+
21
+ self.claude = ClaudeProvider(
22
+ p["claude"]["api_key"],
23
+ p["claude"]["model"],
24
+ p["claude"]["daily_limit"],
25
+ p["claude"]["monthly_limit"],
26
+ )
27
+
28
+ self.gemini = GeminiProvider(
29
+ p["gemini"]["api_key"],
30
+ p["gemini"]["model"],
31
+ p["gemini"]["daily_limit"],
32
+ p["gemini"]["monthly_limit"],
33
+ )
34
+
35
+ self.deepseek = DeepSeekProvider(
36
+ p["deepseek"]["api_key"],
37
+ p["deepseek"]["model"],
38
+ p["deepseek"]["daily_limit"],
39
+ p["deepseek"]["monthly_limit"],
40
+ )
41
+
42
+ self.providers = [
43
+ self.gemini,
44
+ self.deepseek,
45
+ self.openai,
46
+ self.claude,
47
+ self.local,
48
+ ]
49
+
50
+ def generate(self, prompt: str) -> str:
51
+ for provider in self.providers:
52
+ try:
53
+ return provider.generate(prompt)
54
+ except Exception:
55
+ continue
56
+
57
+ raise RuntimeError("All providers failed")
@@ -0,0 +1,5 @@
1
+ """
2
+ Public API surface for textfsm-ai.
3
+ """
4
+
5
+ __all__ = []
@@ -0,0 +1 @@
1
+ """CLI package for textfsm-ai."""
@@ -0,0 +1,61 @@
1
+ import contextlib
2
+ import functools
3
+ import io
4
+ import json
5
+ import time
6
+
7
+ import click
8
+
9
+
10
+ def run_with_capture(ctx, func, *args, **kwargs):
11
+ """Execute a subcommand, capture stdout, and wrap in JSON if requested.
12
+
13
+ Behavior:
14
+ - Default: print human-readable output.
15
+ - --time: append human-readable timing.
16
+ - --json: wrap stdout + elapsed_sec in JSON (always include elapsed_sec).
17
+ """
18
+ use_json = ctx.obj.get("json", False)
19
+ use_time = ctx.obj.get("time", False)
20
+
21
+ buffer = io.StringIO()
22
+
23
+ start = time.perf_counter()
24
+ with contextlib.redirect_stdout(buffer):
25
+ func(*args, **kwargs)
26
+ elapsed = time.perf_counter() - start
27
+
28
+ output = buffer.getvalue()
29
+
30
+ if use_json:
31
+ payload = {
32
+ "output": output,
33
+ "elapsed_sec": round(elapsed, 6),
34
+ }
35
+ click.echo(json.dumps(payload, indent=2))
36
+ return
37
+
38
+ # Human-readable mode
39
+ click.echo(output, nl=False)
40
+ if use_time:
41
+ click.echo(f"[time] {elapsed:.6f}s")
42
+
43
+
44
+ def wrap_command(cmd):
45
+ """Wrap a Click command so we can intercept execution with run_with_capture()."""
46
+
47
+ @functools.wraps(cmd.callback)
48
+ @click.pass_context
49
+ def wrapper(ctx, *args, **kwargs):
50
+ return run_with_capture(ctx, cmd.callback, *args, **kwargs)
51
+
52
+ return click.Command(
53
+ name=cmd.name,
54
+ callback=wrapper,
55
+ params=cmd.params,
56
+ help=cmd.help,
57
+ short_help=cmd.short_help,
58
+ epilog=cmd.epilog,
59
+ options_metavar=cmd.options_metavar,
60
+ add_help_option=cmd.add_help_option,
61
+ )
@@ -0,0 +1,29 @@
1
+ import pathlib
2
+ from typing import Optional
3
+
4
+ import click
5
+
6
+
7
+ @click.command(name="generate", help="Generate a TextFSM template from raw CLI output.")
8
+ @click.argument(
9
+ "input_file",
10
+ type=click.Path(exists=True, dir_okay=False, path_type=pathlib.Path),
11
+ )
12
+ @click.option(
13
+ "--provider",
14
+ "-p",
15
+ default="openai",
16
+ show_default=True,
17
+ help="Provider name to use for generation.",
18
+ )
19
+ @click.option(
20
+ "--model",
21
+ "-m",
22
+ default=None,
23
+ help="Optional model name override.",
24
+ )
25
+ def generate(input_file: pathlib.Path, provider: str, model: Optional[str]) -> None:
26
+ click.echo(f"Generating template from: {input_file}")
27
+ click.echo(f"Provider: {provider}")
28
+ click.echo(f"Model: {model}")
29
+ click.echo("Status: ok")
@@ -0,0 +1,11 @@
1
+ import click
2
+
3
+
4
+ @click.command(
5
+ name="providers", help="List configured AI providers and routing information."
6
+ )
7
+ def providers() -> None:
8
+ click.echo("openai")
9
+ click.echo("claude")
10
+ click.echo("gemini")
11
+ click.echo("deepseek")
@@ -0,0 +1,7 @@
1
+ import click
2
+
3
+
4
+ @click.command(name="quota", help="Show quota and usage information for providers.")
5
+ def quota() -> None:
6
+ click.echo("openai: ok")
7
+ click.echo("claude: ok")
@@ -0,0 +1,35 @@
1
+ import click
2
+
3
+ from ._utils import wrap_command # if you place wrappers in a helper file
4
+ from .generate_cmd import generate
5
+ from .providers_cmd import providers
6
+ from .quota_cmd import quota
7
+ from .version_cmd import version_cmd
8
+
9
+
10
+ @click.group(
11
+ name="textfsm-ai",
12
+ help="AI-powered TextFSM template generator with multi-provider routing.",
13
+ )
14
+ @click.option(
15
+ "--time", "time_flag", is_flag=True, help="Show execution time (human mode only)."
16
+ )
17
+ @click.option(
18
+ "--json", "json_flag", is_flag=True, help="Output results in JSON format."
19
+ )
20
+ @click.pass_context
21
+ def cli(ctx, time_flag, json_flag):
22
+ ctx.ensure_object(dict)
23
+ ctx.obj["time"] = time_flag
24
+ ctx.obj["json"] = json_flag
25
+
26
+
27
+ # Register wrapped subcommands
28
+ cli.add_command(wrap_command(generate))
29
+ cli.add_command(wrap_command(providers))
30
+ cli.add_command(wrap_command(quota))
31
+ cli.add_command(wrap_command(version_cmd))
32
+
33
+
34
+ def main():
35
+ cli()
@@ -0,0 +1,8 @@
1
+ import click
2
+
3
+ from textfsm_ai import __version__
4
+
5
+
6
+ @click.command(name="version", help="Show the textfsm-ai package version.")
7
+ def version_cmd():
8
+ click.echo(f"textfsm-ai v{__version__}")
@@ -0,0 +1,24 @@
1
+ providers:
2
+ openai:
3
+ api_key: "${OPENAI_API_KEY}"
4
+ model: "gpt-5-mini"
5
+ daily_limit: 20000
6
+ monthly_limit: 300000
7
+
8
+ claude:
9
+ api_key: "${CLAUDE_API_KEY}"
10
+ model: "claude-3-haiku"
11
+ daily_limit: 20000
12
+ monthly_limit: 300000
13
+
14
+ gemini:
15
+ api_key: "${GEMINI_API_KEY}"
16
+ model: "gemini-2.5-flash"
17
+ daily_limit: 50000
18
+ monthly_limit: 500000
19
+
20
+ deepseek:
21
+ api_key: "${DEEPSEEK_API_KEY}"
22
+ model: "deepseek-v3.2-exp"
23
+ daily_limit: 50000
24
+ monthly_limit: 500000
@@ -0,0 +1,9 @@
1
+ from pathlib import Path
2
+
3
+ import yaml
4
+
5
+
6
+ def load_config():
7
+ path = Path(__file__).parent / "config.yaml"
8
+ with open(path, "r", encoding="utf-8") as f:
9
+ return yaml.safe_load(f)
File without changes
@@ -0,0 +1,32 @@
1
+ import requests
2
+
3
+ from textfsm_ai.quota_manager import QuotaManager
4
+
5
+
6
+ class ClaudeProvider:
7
+ def __init__(self, api_key, model, daily_limit, monthly_limit):
8
+ self.api_key = api_key
9
+ self.model = model
10
+ self.url = "https://api.anthropic.com/v1/messages"
11
+ self.quota = QuotaManager("claude", daily_limit, monthly_limit)
12
+
13
+ def generate(self, prompt: str) -> str:
14
+ estimated_tokens = len(prompt.split()) * 2
15
+ if not self.quota.allowed(estimated_tokens):
16
+ raise RuntimeError("Claude quota exceeded")
17
+
18
+ headers = {
19
+ "x-api-key": self.api_key,
20
+ "anthropic-version": "2023-06-01",
21
+ }
22
+ payload = {
23
+ "model": self.model,
24
+ "max_tokens": 2048,
25
+ "messages": [{"role": "user", "content": prompt}],
26
+ }
27
+
28
+ resp = requests.post(self.url, json=payload, headers=headers, timeout=30)
29
+ resp.raise_for_status()
30
+
31
+ self.quota.add_tokens(estimated_tokens)
32
+ return resp.json()["content"][0]["text"]
@@ -0,0 +1,28 @@
1
+ import requests
2
+
3
+ from textfsm_ai.quota_manager import QuotaManager
4
+
5
+
6
+ class DeepSeekProvider:
7
+ def __init__(self, api_key, model, daily_limit, monthly_limit):
8
+ self.api_key = api_key
9
+ self.model = model
10
+ self.url = "https://api.deepseek.com/v1/chat/completions"
11
+ self.quota = QuotaManager("deepseek", daily_limit, monthly_limit)
12
+
13
+ def generate(self, prompt: str) -> str:
14
+ estimated_tokens = len(prompt.split()) * 2
15
+ if not self.quota.allowed(estimated_tokens):
16
+ raise RuntimeError("DeepSeek quota exceeded")
17
+
18
+ headers = {"Authorization": f"Bearer {self.api_key}"}
19
+ payload = {
20
+ "model": self.model,
21
+ "messages": [{"role": "user", "content": prompt}],
22
+ }
23
+
24
+ resp = requests.post(self.url, json=payload, headers=headers, timeout=30)
25
+ resp.raise_for_status()
26
+
27
+ self.quota.add_tokens(estimated_tokens)
28
+ return resp.json()["choices"][0]["message"]["content"]
@@ -0,0 +1,25 @@
1
+ import requests
2
+
3
+ from textfsm_ai.quota_manager import QuotaManager
4
+
5
+
6
+ class GeminiProvider:
7
+ def __init__(self, api_key, model, daily_limit, monthly_limit):
8
+ self.api_key = api_key
9
+ self.model = model
10
+ self.url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent"
11
+ self.quota = QuotaManager("gemini", daily_limit, monthly_limit)
12
+
13
+ def generate(self, prompt: str) -> str:
14
+ estimated_tokens = len(prompt.split()) * 2
15
+ if not self.quota.allowed(estimated_tokens):
16
+ raise RuntimeError("Gemini quota exceeded")
17
+
18
+ payload = {"contents": [{"parts": [{"text": prompt}]}]}
19
+ params = {"key": self.api_key}
20
+
21
+ resp = requests.post(self.url, json=payload, params=params, timeout=30)
22
+ resp.raise_for_status()
23
+
24
+ self.quota.add_tokens(estimated_tokens)
25
+ return resp.json()["candidates"][0]["content"]["parts"][0]["text"]
@@ -0,0 +1,28 @@
1
+ import requests
2
+
3
+ from textfsm_ai.quota_manager import QuotaManager
4
+
5
+
6
+ class OpenAIProvider:
7
+ def __init__(self, api_key, model, daily_limit, monthly_limit):
8
+ self.api_key = api_key
9
+ self.model = model
10
+ self.url = "https://api.openai.com/v1/chat/completions"
11
+ self.quota = QuotaManager("openai", daily_limit, monthly_limit)
12
+
13
+ def generate(self, prompt: str) -> str:
14
+ estimated_tokens = len(prompt.split()) * 2
15
+ if not self.quota.allowed(estimated_tokens):
16
+ raise RuntimeError("OpenAI quota exceeded")
17
+
18
+ headers = {"Authorization": f"Bearer {self.api_key}"}
19
+ payload = {
20
+ "model": self.model,
21
+ "messages": [{"role": "user", "content": prompt}],
22
+ }
23
+
24
+ resp = requests.post(self.url, json=payload, headers=headers, timeout=30)
25
+ resp.raise_for_status()
26
+
27
+ self.quota.add_tokens(estimated_tokens)
28
+ return resp.json()["choices"][0]["message"]["content"]
@@ -0,0 +1,84 @@
1
+ import json
2
+ import time
3
+ from pathlib import Path
4
+
5
+
6
+ class QuotaManager:
7
+ def __init__(self, provider_name: str, daily_limit: int, monthly_limit: int):
8
+ self.provider = provider_name
9
+ self.daily_limit = daily_limit
10
+ self.monthly_limit = monthly_limit
11
+
12
+ self.path = Path.home() / f".textfsm_ai_usage_{provider_name}.json"
13
+ self._load()
14
+
15
+ def _load(self):
16
+ if self.path.exists():
17
+ with open(self.path, "r") as f:
18
+ self.data = json.load(f)
19
+ else:
20
+ self.data = {
21
+ "day": self._today(),
22
+ "month": self._month(),
23
+ "daily_tokens": 0,
24
+ "monthly_tokens": 0,
25
+ "just_reset_month": False,
26
+ }
27
+ self._save()
28
+
29
+ def _save(self):
30
+ with open(self.path, "w") as f:
31
+ json.dump(self.data, f)
32
+
33
+ def _today(self):
34
+ return time.strftime("%Y-%m-%d")
35
+
36
+ def _month(self):
37
+ return time.strftime("%Y-%m")
38
+
39
+ def _maybe_reset(self):
40
+ today = self._today()
41
+ month = self._month()
42
+
43
+ # Monthly reset
44
+ if self.data["month"] != month:
45
+ self.data["month"] = month
46
+ self.data["monthly_tokens"] = 0
47
+ self.data["day"] = today
48
+ self.data["daily_tokens"] = 0
49
+ self.data["just_reset_month"] = True
50
+ self._save()
51
+ return
52
+
53
+ # Daily reset
54
+ if self.data["day"] != today:
55
+ self.data["day"] = today
56
+ self.data["daily_tokens"] = 0
57
+ self.data["just_reset_month"] = False
58
+ self._save()
59
+ return
60
+
61
+ def allowed(self, count: int) -> bool:
62
+ self._maybe_reset()
63
+
64
+ # Monthly limit always enforced
65
+ if self.data["monthly_tokens"] + count > self.monthly_limit:
66
+ return False
67
+
68
+ # Daily limit skipped ONCE after monthly reset
69
+ if not self.data.get("just_reset_month", False):
70
+ if self.data["daily_tokens"] + count > self.daily_limit:
71
+ return False
72
+
73
+ return True
74
+
75
+ def add_tokens(self, count: int):
76
+ self._maybe_reset()
77
+
78
+ # After first request of new month, daily limit applies again
79
+ if self.data.get("just_reset_month", False):
80
+ self.data["just_reset_month"] = False
81
+
82
+ self.data["daily_tokens"] += count
83
+ self.data["monthly_tokens"] += count
84
+ self._save()
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: textfsm-ai
3
+ Version: 0.1.19
4
+ Summary: AI-powered TextFSM template generator with multi-provider routing
5
+ Author-email: Tuyen Mathew Duong <tuyen@geekstrident.com>
6
+ Maintainer-email: Tuyen Mathew Duong <tuyen@geekstrident.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/Geeks-Trident-LLC/textfsm-ai
9
+ Project-URL: Repository, https://github.com/Geeks-Trident-LLC/textfsm-ai
10
+ Project-URL: Issues, https://github.com/Geeks-Trident-LLC/textfsm-ai/issues
11
+ Project-URL: Documentation, https://geeks-trident-llc.github.io/textfsm-ai/latest/
12
+ Keywords: textfsm,network automation,cli parsing,template generator,ai,llm,openai,claude,gemini,deepseek,router,quota manager
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Information Technology
16
+ Classifier: Intended Audience :: System Administrators
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Classifier: Topic :: Software Development :: Code Generators
24
+ Classifier: Topic :: Text Processing
25
+ Classifier: Topic :: Utilities
26
+ Classifier: Operating System :: OS Independent
27
+ Requires-Python: >=3.9
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: PyYAML>=6.0
31
+ Requires-Dist: requests>=2.31
32
+ Requires-Dist: click>=8.1
33
+ Provides-Extra: dev
34
+ Requires-Dist: build; extra == "dev"
35
+ Requires-Dist: twine; extra == "dev"
36
+ Provides-Extra: test
37
+ Requires-Dist: pytest; extra == "test"
38
+ Requires-Dist: pytest-cov; extra == "test"
39
+ Provides-Extra: lint
40
+ Requires-Dist: ruff; extra == "lint"
41
+ Provides-Extra: all
42
+ Requires-Dist: build; extra == "all"
43
+ Requires-Dist: twine; extra == "all"
44
+ Requires-Dist: pytest; extra == "all"
45
+ Requires-Dist: pytest-cov; extra == "all"
46
+ Requires-Dist: ruff; extra == "all"
47
+ Dynamic: license-file
48
+
49
+ # textfsm-ai
50
+
51
+ **AI‑powered TextFSM template generation, parsing assistance, and smart log extraction.**
52
+
53
+ `textfsm-ai` brings modern LLM intelligence to traditional TextFSM workflows.
54
+ It helps you automatically generate templates, validate patterns, explain parsing logic, and accelerate network automation development.
55
+
56
+ ---
57
+
58
+ ## 🚀 Features
59
+
60
+ - **AI‑Powered Template Generation** — Turn raw CLI output into production‑ready TextFSM templates in seconds.
61
+ - **Smart Validation & Refinement** — Automatically verify template correctness and refine ambiguous patterns with AI assistance.
62
+ - **Built‑In Golden Master Testing** — Lock in deterministic parsing behavior and detect regressions instantly.
63
+ - **Flexible Multi‑Provider AI Routing** — Use the best AI model for each task with automatic routing across supported cloud providers.
64
+
65
+ ---
@@ -0,0 +1,28 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ textfsm_ai/__init__.py
6
+ textfsm_ai/ai_router.py
7
+ textfsm_ai/api.py
8
+ textfsm_ai/config.yaml
9
+ textfsm_ai/config_loader.py
10
+ textfsm_ai/quota_manager.py
11
+ textfsm_ai.egg-info/PKG-INFO
12
+ textfsm_ai.egg-info/SOURCES.txt
13
+ textfsm_ai.egg-info/dependency_links.txt
14
+ textfsm_ai.egg-info/entry_points.txt
15
+ textfsm_ai.egg-info/requires.txt
16
+ textfsm_ai.egg-info/top_level.txt
17
+ textfsm_ai/cli/__init__.py
18
+ textfsm_ai/cli/_utils.py
19
+ textfsm_ai/cli/generate_cmd.py
20
+ textfsm_ai/cli/providers_cmd.py
21
+ textfsm_ai/cli/quota_cmd.py
22
+ textfsm_ai/cli/top.py
23
+ textfsm_ai/cli/version_cmd.py
24
+ textfsm_ai/providers/__init__.py
25
+ textfsm_ai/providers/claude_provider.py
26
+ textfsm_ai/providers/deepseek_provider.py
27
+ textfsm_ai/providers/gemini_provider.py
28
+ textfsm_ai/providers/openai_provider.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ textfsm-ai = textfsm_ai.cli.top:main
@@ -0,0 +1,21 @@
1
+ PyYAML>=6.0
2
+ requests>=2.31
3
+ click>=8.1
4
+
5
+ [all]
6
+ build
7
+ twine
8
+ pytest
9
+ pytest-cov
10
+ ruff
11
+
12
+ [dev]
13
+ build
14
+ twine
15
+
16
+ [lint]
17
+ ruff
18
+
19
+ [test]
20
+ pytest
21
+ pytest-cov
@@ -0,0 +1 @@
1
+ textfsm_ai