parseforge 0.2.4__tar.gz → 0.2.5__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 (46) hide show
  1. {parseforge-0.2.4/parseforge.egg-info → parseforge-0.2.5}/PKG-INFO +15 -11
  2. {parseforge-0.2.4 → parseforge-0.2.5}/README.md +11 -10
  3. parseforge-0.2.5/parseforge/__init__.py +1 -0
  4. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/cli/main.py +4 -2
  5. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/__init__.py +2 -1
  6. parseforge-0.2.5/parseforge/naming/providers/__init__.py +5 -0
  7. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/providers/models.yaml +9 -0
  8. parseforge-0.2.5/parseforge/naming/providers/openai.py +117 -0
  9. {parseforge-0.2.4 → parseforge-0.2.5/parseforge.egg-info}/PKG-INFO +15 -11
  10. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge.egg-info/SOURCES.txt +1 -0
  11. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge.egg-info/requires.txt +4 -0
  12. {parseforge-0.2.4 → parseforge-0.2.5}/pyproject.toml +2 -1
  13. parseforge-0.2.4/parseforge/__init__.py +0 -1
  14. parseforge-0.2.4/parseforge/naming/providers/__init__.py +0 -4
  15. {parseforge-0.2.4 → parseforge-0.2.5}/LICENSE +0 -0
  16. {parseforge-0.2.4 → parseforge-0.2.5}/MANIFEST.in +0 -0
  17. {parseforge-0.2.4 → parseforge-0.2.5}/SPEC.md +0 -0
  18. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/cli/__init__.py +0 -0
  19. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/cli/config.py +0 -0
  20. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/drift.py +0 -0
  21. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/generation.py +0 -0
  22. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/integration.py +0 -0
  23. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/assemble.py +0 -0
  24. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/cache.py +0 -0
  25. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/llm.py +0 -0
  26. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/prompts.py +0 -0
  27. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/prompts.yaml +0 -0
  28. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/providers/anthropic.py +0 -0
  29. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/providers/cost.py +0 -0
  30. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/providers/deepseek.py +0 -0
  31. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/providers/errors.py +0 -0
  32. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/providers/models.py +0 -0
  33. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/providers/text.py +0 -0
  34. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/naming/resolver.py +0 -0
  35. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/paths.py +0 -0
  36. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/pipeline.py +0 -0
  37. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/promotion.py +0 -0
  38. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/sampling/__init__.py +0 -0
  39. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/sampling/backends/__init__.py +0 -0
  40. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/sampling/backends/netmiko.py +0 -0
  41. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/sampling/core.py +0 -0
  42. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge/validation.py +0 -0
  43. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge.egg-info/dependency_links.txt +0 -0
  44. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge.egg-info/entry_points.txt +0 -0
  45. {parseforge-0.2.4 → parseforge-0.2.5}/parseforge.egg-info/top_level.txt +0 -0
  46. {parseforge-0.2.4 → parseforge-0.2.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: parseforge
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: LLM-driven pipeline that forges, validates, and promotes TextFSM templates from network CLI output
5
5
  Author-email: Tuyen Mathew Duong <tuyen@geekstrident.com>
6
6
  Maintainer-email: Tuyen Mathew Duong <tuyen@geekstrident.com>
@@ -33,6 +33,9 @@ Requires-Dist: textfsm-ai[anthropic]>=0.6.1; extra == "anthropic"
33
33
  Provides-Extra: deepseek
34
34
  Requires-Dist: openai>=1.0.0; extra == "deepseek"
35
35
  Requires-Dist: textfsm-ai[deepseek]>=0.6.1; extra == "deepseek"
36
+ Provides-Extra: openai
37
+ Requires-Dist: openai>=1.0.0; extra == "openai"
38
+ Requires-Dist: textfsm-ai[openai]>=0.6.1; extra == "openai"
36
39
  Provides-Extra: sampling
37
40
  Requires-Dist: netmiko>=4.0; extra == "sampling"
38
41
  Provides-Extra: dev
@@ -83,11 +86,11 @@ pip install parseforge[anthropic]
83
86
  command that's pure local processing (`canonical`/`readable`/`recognizers`,
84
87
  `integration`, `promotion`) works with nothing further. Anything that calls an
85
88
  LLM (`name`, `check --provider`, `run`, `generate-template`, `trial`) needs the
86
- extra for whichever provider it uses: `anthropic` or `deepseek`. `--provider`
87
- defaults to `anthropic` wherever it isn't required, so that's the one most
88
- setups need. `pip install parseforge[sampling]` adds Netmiko for live device
89
- sampling; combine extras as needed, e.g.
90
- `pip install parseforge[anthropic,deepseek,sampling]`.
89
+ extra for whichever provider it uses: `anthropic`, `openai`, or `deepseek`.
90
+ `--provider` defaults to `anthropic` wherever it isn't required, so that's the
91
+ one most setups need. `pip install parseforge[sampling]` adds Netmiko for live
92
+ device sampling; combine extras as needed, e.g.
93
+ `pip install parseforge[anthropic,openai,deepseek,sampling]`.
91
94
 
92
95
  ## Development
93
96
 
@@ -95,9 +98,10 @@ sampling; combine extras as needed, e.g.
95
98
  pip install -e ".[dev,sampling]"
96
99
  pytest
97
100
  ```
98
- `dev` already includes both `anthropic` and `openai` (tests exercise both
99
- providers, never silently skip) add `,anthropic`/`,deepseek` explicitly only
100
- if installing outside of `dev`.
101
+ `dev` already includes both the `anthropic` and `openai` SDKs (tests exercise
102
+ all three providers`anthropic`, `openai`, `deepseek` share just those two
103
+ packages and never silently skip) — add `,anthropic`/`,openai`/`,deepseek`
104
+ explicitly only if installing outside of `dev`.
101
105
 
102
106
  Linting/formatting/type-checking/docs run through tox instead of extras — see
103
107
  `tox.ini` (`tox -e lint`/`format`/`typecheck`/`docs`), each installing its own
@@ -119,8 +123,8 @@ parseforge name --vendor cisco --family catalyst9200 --os ios-xe --version 17.9.
119
123
  ```
120
124
  Still needs an LLM provider on a cache miss — `--provider` defaults to `anthropic`,
121
125
  and `--api-key` falls back to that provider's own env var (`ANTHROPIC_API_KEY`/
122
- `DEEPSEEK_API_KEY`). A cache hit (a command already seen before) never touches the
123
- LLM, so no key is needed at all in that case.
126
+ `OPENAI_API_KEY`/`DEEPSEEK_API_KEY`). A cache hit (a command already seen before)
127
+ never touches the LLM, so no key is needed at all in that case.
124
128
 
125
129
  **`check`** — validate a connector or provider before spending time/tokens on a real
126
130
  run. With neither `--env` nor explicit connection flags, prints what a connector needs
@@ -33,11 +33,11 @@ pip install parseforge[anthropic]
33
33
  command that's pure local processing (`canonical`/`readable`/`recognizers`,
34
34
  `integration`, `promotion`) works with nothing further. Anything that calls an
35
35
  LLM (`name`, `check --provider`, `run`, `generate-template`, `trial`) needs the
36
- extra for whichever provider it uses: `anthropic` or `deepseek`. `--provider`
37
- defaults to `anthropic` wherever it isn't required, so that's the one most
38
- setups need. `pip install parseforge[sampling]` adds Netmiko for live device
39
- sampling; combine extras as needed, e.g.
40
- `pip install parseforge[anthropic,deepseek,sampling]`.
36
+ extra for whichever provider it uses: `anthropic`, `openai`, or `deepseek`.
37
+ `--provider` defaults to `anthropic` wherever it isn't required, so that's the
38
+ one most setups need. `pip install parseforge[sampling]` adds Netmiko for live
39
+ device sampling; combine extras as needed, e.g.
40
+ `pip install parseforge[anthropic,openai,deepseek,sampling]`.
41
41
 
42
42
  ## Development
43
43
 
@@ -45,9 +45,10 @@ sampling; combine extras as needed, e.g.
45
45
  pip install -e ".[dev,sampling]"
46
46
  pytest
47
47
  ```
48
- `dev` already includes both `anthropic` and `openai` (tests exercise both
49
- providers, never silently skip) add `,anthropic`/`,deepseek` explicitly only
50
- if installing outside of `dev`.
48
+ `dev` already includes both the `anthropic` and `openai` SDKs (tests exercise
49
+ all three providers`anthropic`, `openai`, `deepseek` share just those two
50
+ packages and never silently skip) — add `,anthropic`/`,openai`/`,deepseek`
51
+ explicitly only if installing outside of `dev`.
51
52
 
52
53
  Linting/formatting/type-checking/docs run through tox instead of extras — see
53
54
  `tox.ini` (`tox -e lint`/`format`/`typecheck`/`docs`), each installing its own
@@ -69,8 +70,8 @@ parseforge name --vendor cisco --family catalyst9200 --os ios-xe --version 17.9.
69
70
  ```
70
71
  Still needs an LLM provider on a cache miss — `--provider` defaults to `anthropic`,
71
72
  and `--api-key` falls back to that provider's own env var (`ANTHROPIC_API_KEY`/
72
- `DEEPSEEK_API_KEY`). A cache hit (a command already seen before) never touches the
73
- LLM, so no key is needed at all in that case.
73
+ `OPENAI_API_KEY`/`DEEPSEEK_API_KEY`). A cache hit (a command already seen before)
74
+ never touches the LLM, so no key is needed at all in that case.
74
75
 
75
76
  **`check`** — validate a connector or provider before spending time/tokens on a real
76
77
  run. With neither `--env` nor explicit connection flags, prints what a connector needs
@@ -0,0 +1 @@
1
+ __version__ = "0.2.5"
@@ -24,6 +24,7 @@ from parseforge.cli import config as cli_config
24
24
  _BUILDERS: dict[str, type[naming.RegexBuilder]] = {
25
25
  "anthropic": naming.AnthropicRegexBuilder,
26
26
  "deepseek": naming.DeepSeekRegexBuilder,
27
+ "openai": naming.OpenAIRegexBuilder,
27
28
  }
28
29
 
29
30
  _CONNECTORS = ("netmiko",)
@@ -198,7 +199,8 @@ def main() -> None:
198
199
  "--api-key",
199
200
  default=None,
200
201
  help="Provider API key. Defaults to that provider's own API key environment "
201
- "variable (ANTHROPIC_API_KEY, DEEPSEEK_API_KEY); only needed on a cache miss.",
202
+ "variable (ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY); only needed "
203
+ "on a cache miss.",
202
204
  )
203
205
  @click.option(
204
206
  "--model",
@@ -266,7 +268,7 @@ def name_cmd(
266
268
  "--provider",
267
269
  required=True,
268
270
  help="LLM provider for template generation (textfsm-ai's own registry, "
269
- 'e.g. "anthropic", "deepseek"). Naming uses its own separate '
271
+ 'e.g. "anthropic", "openai", "deepseek"). Naming uses its own separate '
270
272
  "--naming-provider, not this one.",
271
273
  )
272
274
  @click.option("--api-key", required=True, help="API key for the generation LLM call.")
@@ -8,7 +8,7 @@ from .llm import (
8
8
  UnimplementedRegexBuilder,
9
9
  build_prompt,
10
10
  )
11
- from .providers import AnthropicRegexBuilder, DeepSeekRegexBuilder
11
+ from .providers import AnthropicRegexBuilder, DeepSeekRegexBuilder, OpenAIRegexBuilder
12
12
  from .resolver import NamingResolution, cli_name, resolve_cli_name
13
13
 
14
14
  __all__ = [
@@ -20,6 +20,7 @@ __all__ = [
20
20
  "UnimplementedRegexBuilder",
21
21
  "AnthropicRegexBuilder",
22
22
  "DeepSeekRegexBuilder",
23
+ "OpenAIRegexBuilder",
23
24
  "LLMCLIResponse",
24
25
  "TokenUsage",
25
26
  "build_prompt",
@@ -0,0 +1,5 @@
1
+ from .anthropic import AnthropicRegexBuilder
2
+ from .deepseek import DeepSeekRegexBuilder
3
+ from .openai import OpenAIRegexBuilder
4
+
5
+ __all__ = ["AnthropicRegexBuilder", "DeepSeekRegexBuilder", "OpenAIRegexBuilder"]
@@ -22,3 +22,12 @@ deepseek:
22
22
  - deepseek-v4-flash
23
23
  - deepseek-v4-pro
24
24
  deprecated: []
25
+
26
+ openai:
27
+ default: gpt-5.4-mini
28
+ supported:
29
+ - gpt-5.4-mini
30
+ - gpt-5.4
31
+ - gpt-5.4-nano
32
+ - gpt-5.5
33
+ deprecated: []
@@ -0,0 +1,117 @@
1
+ """OpenAI-backed RegexBuilder implementation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import time
6
+ from typing import TYPE_CHECKING, Any
7
+
8
+ from ..llm import CliContext, LLMCLIResponse, TokenUsage, build_prompt
9
+ from .cost import estimate_cost
10
+ from .errors import format_llm_error_reason, is_retryable
11
+ from .models import default_model
12
+ from .text import extract_pattern
13
+
14
+ if TYPE_CHECKING:
15
+ import openai as openai_sdk
16
+
17
+ DEFAULT_MODEL = default_model("openai")
18
+
19
+ _DEFAULT_MAX_TOKENS = 1024
20
+
21
+
22
+ def _import_openai() -> Any:
23
+ """Deferred import — openai is an optional extra (parseforge[openai]);
24
+ nothing else in this module (or a cache-hit lookup, which never reaches
25
+ build_pattern at all — see resolver.cli_name) should require it to be
26
+ installed."""
27
+ try:
28
+ import openai
29
+ except ImportError as exc:
30
+ raise ImportError(
31
+ "the openai package is required to use OpenAIRegexBuilder — "
32
+ "install it via `pip install parseforge[openai]`"
33
+ ) from exc
34
+ return openai
35
+
36
+
37
+ class OpenAIRegexBuilder:
38
+ """Builds a cli-name regex pattern by prompting an OpenAI model.
39
+
40
+ The client is constructed lazily, on the first actual call — not in
41
+ ``__init__`` — so this can be used as a default RegexBuilder without
42
+ requiring ``OPENAI_API_KEY`` to be set for cache-hit lookups, which
43
+ never reach the LLM at all (see resolver.cli_name).
44
+
45
+ API key resolves from the ``api_key`` argument if given, otherwise the
46
+ ``OPENAI_API_KEY`` environment variable (the SDK's own default).
47
+ """
48
+
49
+ provider = "openai"
50
+
51
+ def __init__(self, model: str = DEFAULT_MODEL, api_key: str | None = None) -> None:
52
+ self.model = model
53
+ self._api_key = api_key
54
+ self._client: openai_sdk.OpenAI | None = None
55
+
56
+ def _get_client(self) -> openai_sdk.OpenAI:
57
+ if self._client is None:
58
+ openai = _import_openai()
59
+ self._client = (
60
+ openai.OpenAI(api_key=self._api_key)
61
+ if self._api_key
62
+ else openai.OpenAI()
63
+ )
64
+ return self._client
65
+
66
+ def build_pattern(
67
+ self, command: str, context: CliContext, **kwargs: Any
68
+ ) -> LLMCLIResponse:
69
+ openai = _import_openai()
70
+ prompt = build_prompt(command, context)
71
+ max_tokens = kwargs.pop("max_tokens", None) or _DEFAULT_MAX_TOKENS
72
+
73
+ start = time.monotonic()
74
+ try:
75
+ response = self._get_client().chat.completions.create(
76
+ model=self.model,
77
+ max_tokens=max_tokens,
78
+ messages=[{"role": "user", "content": prompt}],
79
+ **kwargs,
80
+ )
81
+ except openai.OpenAIError as exc:
82
+ if not is_retryable(exc):
83
+ # Same request would fail the same way again — stop rather
84
+ # than let a caller burn another attempt on it.
85
+ raise
86
+ return LLMCLIResponse(
87
+ content="",
88
+ raw=exc,
89
+ usage=TokenUsage(
90
+ input_tokens=0, output_tokens=0, total_tokens=0, estimated_cost=0.0
91
+ ),
92
+ duration_ms=(time.monotonic() - start) * 1000,
93
+ reason=format_llm_error_reason(exc),
94
+ ready=False,
95
+ )
96
+ duration_ms = (time.monotonic() - start) * 1000
97
+
98
+ choice = response.choices[0]
99
+ return LLMCLIResponse(
100
+ content=extract_pattern(choice.message.content or ""),
101
+ raw=response,
102
+ usage=TokenUsage(
103
+ input_tokens=response.usage.prompt_tokens,
104
+ output_tokens=response.usage.completion_tokens,
105
+ total_tokens=response.usage.total_tokens,
106
+ estimated_cost=estimate_cost(
107
+ input_tokens=response.usage.prompt_tokens,
108
+ output_tokens=response.usage.completion_tokens,
109
+ total_tokens=response.usage.total_tokens,
110
+ provider=self.provider,
111
+ model=self.model,
112
+ ),
113
+ ),
114
+ duration_ms=duration_ms,
115
+ reason=choice.finish_reason or "",
116
+ ready=choice.finish_reason == "stop",
117
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: parseforge
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: LLM-driven pipeline that forges, validates, and promotes TextFSM templates from network CLI output
5
5
  Author-email: Tuyen Mathew Duong <tuyen@geekstrident.com>
6
6
  Maintainer-email: Tuyen Mathew Duong <tuyen@geekstrident.com>
@@ -33,6 +33,9 @@ Requires-Dist: textfsm-ai[anthropic]>=0.6.1; extra == "anthropic"
33
33
  Provides-Extra: deepseek
34
34
  Requires-Dist: openai>=1.0.0; extra == "deepseek"
35
35
  Requires-Dist: textfsm-ai[deepseek]>=0.6.1; extra == "deepseek"
36
+ Provides-Extra: openai
37
+ Requires-Dist: openai>=1.0.0; extra == "openai"
38
+ Requires-Dist: textfsm-ai[openai]>=0.6.1; extra == "openai"
36
39
  Provides-Extra: sampling
37
40
  Requires-Dist: netmiko>=4.0; extra == "sampling"
38
41
  Provides-Extra: dev
@@ -83,11 +86,11 @@ pip install parseforge[anthropic]
83
86
  command that's pure local processing (`canonical`/`readable`/`recognizers`,
84
87
  `integration`, `promotion`) works with nothing further. Anything that calls an
85
88
  LLM (`name`, `check --provider`, `run`, `generate-template`, `trial`) needs the
86
- extra for whichever provider it uses: `anthropic` or `deepseek`. `--provider`
87
- defaults to `anthropic` wherever it isn't required, so that's the one most
88
- setups need. `pip install parseforge[sampling]` adds Netmiko for live device
89
- sampling; combine extras as needed, e.g.
90
- `pip install parseforge[anthropic,deepseek,sampling]`.
89
+ extra for whichever provider it uses: `anthropic`, `openai`, or `deepseek`.
90
+ `--provider` defaults to `anthropic` wherever it isn't required, so that's the
91
+ one most setups need. `pip install parseforge[sampling]` adds Netmiko for live
92
+ device sampling; combine extras as needed, e.g.
93
+ `pip install parseforge[anthropic,openai,deepseek,sampling]`.
91
94
 
92
95
  ## Development
93
96
 
@@ -95,9 +98,10 @@ sampling; combine extras as needed, e.g.
95
98
  pip install -e ".[dev,sampling]"
96
99
  pytest
97
100
  ```
98
- `dev` already includes both `anthropic` and `openai` (tests exercise both
99
- providers, never silently skip) add `,anthropic`/`,deepseek` explicitly only
100
- if installing outside of `dev`.
101
+ `dev` already includes both the `anthropic` and `openai` SDKs (tests exercise
102
+ all three providers`anthropic`, `openai`, `deepseek` share just those two
103
+ packages and never silently skip) — add `,anthropic`/`,openai`/`,deepseek`
104
+ explicitly only if installing outside of `dev`.
101
105
 
102
106
  Linting/formatting/type-checking/docs run through tox instead of extras — see
103
107
  `tox.ini` (`tox -e lint`/`format`/`typecheck`/`docs`), each installing its own
@@ -119,8 +123,8 @@ parseforge name --vendor cisco --family catalyst9200 --os ios-xe --version 17.9.
119
123
  ```
120
124
  Still needs an LLM provider on a cache miss — `--provider` defaults to `anthropic`,
121
125
  and `--api-key` falls back to that provider's own env var (`ANTHROPIC_API_KEY`/
122
- `DEEPSEEK_API_KEY`). A cache hit (a command already seen before) never touches the
123
- LLM, so no key is needed at all in that case.
126
+ `OPENAI_API_KEY`/`DEEPSEEK_API_KEY`). A cache hit (a command already seen before)
127
+ never touches the LLM, so no key is needed at all in that case.
124
128
 
125
129
  **`check`** — validate a connector or provider before spending time/tokens on a real
126
130
  run. With neither `--env` nor explicit connection flags, prints what a connector needs
@@ -34,6 +34,7 @@ parseforge/naming/providers/deepseek.py
34
34
  parseforge/naming/providers/errors.py
35
35
  parseforge/naming/providers/models.py
36
36
  parseforge/naming/providers/models.yaml
37
+ parseforge/naming/providers/openai.py
37
38
  parseforge/naming/providers/text.py
38
39
  parseforge/sampling/__init__.py
39
40
  parseforge/sampling/core.py
@@ -20,6 +20,10 @@ mypy>=1.10.0
20
20
  anthropic>=0.40.0
21
21
  openai>=1.0.0
22
22
 
23
+ [openai]
24
+ openai>=1.0.0
25
+ textfsm-ai[openai]>=0.6.1
26
+
23
27
  [release]
24
28
  bump2version
25
29
  build
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "parseforge"
7
- version = "0.2.4"
7
+ version = "0.2.5"
8
8
  description = "LLM-driven pipeline that forges, validates, and promotes TextFSM templates from network CLI output"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -64,6 +64,7 @@ keywords = [
64
64
  # provider(s) you actually use.
65
65
  anthropic = ["anthropic>=0.40.0", "textfsm-ai[anthropic]>=0.6.1"]
66
66
  deepseek = ["openai>=1.0.0", "textfsm-ai[deepseek]>=0.6.1"]
67
+ openai = ["openai>=1.0.0", "textfsm-ai[openai]>=0.6.1"]
67
68
  sampling = ["netmiko>=4.0"]
68
69
  dev = [
69
70
  "pytest>=8.0.0",
@@ -1 +0,0 @@
1
- __version__ = "0.2.4"
@@ -1,4 +0,0 @@
1
- from .anthropic import AnthropicRegexBuilder
2
- from .deepseek import DeepSeekRegexBuilder
3
-
4
- __all__ = ["AnthropicRegexBuilder", "DeepSeekRegexBuilder"]
File without changes
File without changes
File without changes
File without changes