Skip to content

API Reference

Everything below is exported from parseforge.api and re-exported at the package root (from parseforge import ...). Anything not listed here — module-internal helpers, provider implementation details, CLI plumbing — isn't part of the public API and may change without notice. See the Python API guide for worked examples.

Naming — SPEC.md §2

Resolve a raw CLI command to its canonical, indexed cli-name.

cli_name(command, context, builder=UnimplementedRegexBuilder(), index_path=DEFAULT_INDEX_PATH, **kwargs) -> str : Look up (or resolve and cache) a command's cli-name. **kwargs (e.g. max_tokens) pass through to the builder's underlying API call.

resolve_cli_name(command, context, builder=..., index_path=..., **kwargs) -> NamingResolution : Same as cli_name(), but returns the full resolution — including the raw LLM response, if any — instead of just the name.

NamingResolution : name: str, response: LLMCLIResponse | None — response is None on a cache hit, since no LLM call happens at all in that case.

CliContext : vendor: str, family: str, os: str, version: str — the device context every naming/generation call needs.

RegexBuilder : Protocol every naming provider implements — build_pattern(command, context, **kwargs) -> LLMCLIResponse. See Providers for the eighteen concrete builder classes (AnthropicRegexBuilder, OCIRegexBuilder, ...), importable from parseforge.naming — not re-exported at the root.

LLMCLIResponse : content: str, raw: Any, usage: NamingTokenUsage, duration_ms: float, reason: str, ready: bool — ready=False means the response was cut off before completing (e.g. hit max_tokens).

NamingTokenUsage : input_tokens: int, output_tokens: int, total_tokens: int — one naming LLM call's usage. Aliased from naming.llm.TokenUsage to avoid colliding with GenerationTokenUsage (a separate class with the same shape).

Sampling — SPEC.md §3

Capture raw command output from a device.

sample(sampler, connection, command) -> str : Run command over connection using sampler and return the raw output.

DeviceConnection : host: str, username: str, password: str, device_type: str (e.g. "cisco_ios").

Sampler : Protocol a connector backend implements — run_command(connection, command) -> str. NetmikoSampler (parseforge.sampling.backends, needs the sampling extra) is the only backend today.

Generation — SPEC.md §5 steps 5-6

Sample → candidate TextFSM template, via textfsm-ai's delivery pipeline.

generate(sample, provider, api_key, model, **kwargs) -> GenerationResult : Run textfsm-ai's full sample → template → DSL-compiled pipeline. Never raises for a failed generation (check .ready); does raise ImportError if provider's SDK isn't installed. **kwargs forwards to textfsm-ai's run_pipeline() (endpoint, region, compartment_id, max_tries, ...).

GenerationResult : template: str (canonical, DSL-compiled), raw_template: str (pre-cleanup, as the LLM returned it), readable_dsl: str, recognizers: list[str], records: list[dict[str, str]], usage: GenerationTokenUsage, duration_ms: float, ready: bool, reason: str, raw: dict[str, Any] (full debug payload, credentials redacted).

GenerationTokenUsage : input_tokens: int, output_tokens: int, total_tokens: int — already accumulated across every LLM call in the generation pipeline (every base-prompt attempt and correction-prompt retry), courtesy of textfsm-ai's own accumulate_usage(). Aliased from generation.TokenUsage.

Validation — SPEC.md §5 step 7

Self-validate a template against its own sample.

parse(template_text, input_text) -> ParseResult : Run template_text against input_text and report what parsed.

ParseResult : records: list[dict], errors: list[str], and a passed property (True iff errors is empty).

Pipeline orchestration — SPEC.md §5

One call runs steps 1-7 (naming → sampling → generation → validation) for a single trial, writing the result under a trial directory.

run_command_pipeline(command, context, connection, naming_builder, sampler, generation_config, *, store_root=DEFAULT_STORE_ROOT, naming_index_path=DEFAULT_INDEX_PATH, metadata=TrialMetadata(), mode=Mode.LOOP) -> TrialResult : The full pipeline, one call. Writes samples/sample.txt, derive/*.textfsm/.txt, and summary.json under <store_root>/trials/<vendor>/<family>/<os>/<cli-name>/<run-id>/.

LLMProviderConfig : provider: str, api_key: str, model: str, plus provider-specific optional fields: endpoint/api_version (azure), project/location (vertexai), region (bedrock/oci), compartment_id (oci). Each is ignored by every provider it doesn't apply to.

TrialMetadata : project: str | None, username: str | None, email: str | None, description: str | None, note: str | None — optional context recorded in summary.json, never used for path resolution.

TrialResult : run_dir: Path, cli_name: str, passed: bool, duration_ms: int, total_usage: dict[str, int] (input_tokens/output_tokens/ total_tokens, naming + generation combined).

Mode : LOOP (sample → generate, per command — the only mode implemented) or BATCH (collect N samples per command before generating — designed in SPEC.md §4, not built).

Integration — SPEC.md §5 step 8

Cluster every passed trial for a cli-name by output schema.

build_integration(store_root, key) -> Reference : Rebuild integration/<...>/reference.json for one DeviceKey from every trial currently under trials/.

build_reference_summary(store_root) -> dict[str, Any] : Aggregate every reference.json into one cross-cli-name match-rate report — a read-only transform, no filesystem rescan of trials/.

write_reference_summary(store_root) -> Path : build_reference_summary(), written to integration/reference-summary.json; returns the path written.

Reference : dict[str, ReferenceGroup] — a cli-name's clustered output-schema groups.

ReferenceGroup : keys: list[str], sample_path: str, variants: dict[str, ReferenceVariant].

ReferenceVariant : template_path: str, exact_template_count: int, exact_records_count: int.

Promotion — SPEC.md §5 step 9

Auto-promote every group that clears its gate; queue everything else for human review.

promote_auto(store_root, metadata, default_gate=PromotionGate(), case_gates=None) -> PromotionRunResult : Refreshes integration first, then promotes every group across every case that clears default_gate (or its per-case override in case_gates) into authoritative/.

promote_user_reviewed(store_root, metadata, requests, default_gate=PromotionGate(), case_gates=None) -> PromotionRunResult : Same, but only for the specific (case_key, suffix) pairs in requests — a human-reviewed promotion, recorded as a named snapshot alongside whatever's currently live rather than overwriting it.

decide_promotion(match_rate, sample_count, gate) -> PromotionDecision : Pure decision: AUTO_PROMOTED if both thresholds in gate are met, else QUEUED_FOR_REVIEW.

evaluate_cases(references, summary, default_gate, case_gates=None, only_cases=None) -> list[GroupEvaluation] : Pure decision pass over every group in references — no I/O. One decide_promotion() call per group, per case.

PromotionGate : match_rate_threshold: float = 1.0, min_sample_count: int = 1.

PromotionMetadata : user: str, email: str | None, description: str | None, note: str | None — recorded into every artifact.json/ authoritative-log.json entry a promotion run writes.

UserReviewedRequest : case_key: str, suffix: str | None, gate: PromotionGate | None — one human-reviewed case, tagged with a minor revision marker (e.g. "2", "beta") combined with the group's own major version tag.

GroupEvaluation : case_key: str, group_id: str, decision: PromotionDecision, match_rate: float, sample_count: int.

PromotionRunResult : promoted: list[Path], unqualified: list[GroupEvaluation], unmatched_cases: list[str], invalid_requests: list[str] (USER_REVIEWED requests with no usable suffix).

PromotionDecision : AUTO_PROMOTED or QUEUED_FOR_REVIEW.

PromotionMode : AUTO_PROMOTED or USER_REVIEWED.

Drift monitoring — SPEC.md §5 step 11

Check an authoritative template against new production samples.

check_drift(store_root, key, sample_text, *, suffix=None, gate=DriftGate()) -> DriftCheckResult : Run the authoritative template for (key, suffix) against sample_text, append the result to that cli-name's drift-log.json, and return the rolling match rate + status.

DriftGate : match_rate_threshold: float = 1.0, window: int = 20.

DriftCheckResult : case_key: str, suffix: str | None, passed: bool, match_rate: float, status: str ("ok" or "drifting"), checked_at: str, requeued_to: str | None.

Store-root layout helpers

DEFAULT_STORE_ROOT : Path — ~/.parseforge/tests, the default root every workflow command reads/writes under.

DeviceKey : vendor: str, family: str, os: str, cli_name: str — identifies a template family within a store root.

discover_device_keys(store_root) -> list[DeviceKey] : Every DeviceKey that has at least one trial on disk under store_root.