Skip to main content

AGENT_GUIDE

Constant AGENT_GUIDE 

Source
pub const AGENT_GUIDE: &str = "# BaseForge Agent Guide\n\nThis guide describes the public API and operational behavior of BaseForge\n0.1.7. BaseForge is a blocking Rust client for discovering, inspecting, and\narchiving Hugging Face datasets and Zenodo records.\n\nThe same text is available at runtime as `baseforge::AGENT_GUIDE`.\n\n## Choose A Provider And Parse A Target\n\nCreate one `BaseForge` per `DatasetProvider`. Parse input with the same provider\nthat the client uses:\n\n```rust,no_run\nuse baseforge::{BaseForge, DatasetProvider, parse_dataset_target_for_provider};\n\nlet provider = DatasetProvider::Hf;\nlet target = parse_dataset_target_for_provider(\n    \"https://huggingface.co/datasets/openai/gsm8k\",\n    provider,\n)?;\nlet forge = BaseForge::new(provider)?;\nlet datasets = forge.discover(&target)?;\n\nprintln!(\"found {} dataset(s)\", datasets.len());\n# Ok::<(), baseforge::BaseForgeError>(())\n```\n\n`parse_dataset_target(input)` is shorthand for Hugging Face parsing.\n`DatasetProvider::from_slug` accepts `hf`, `huggingface`,\n`hugging-face`, `hugging_face`, `hugging face`, `huggingfacedatasets`,\n`hfdatasets`, `zen`, and `zenodo`, ignoring separators and ASCII case.\n\nThe following aliases are recognized before provider-specific parsing:\n\n- `top`, `trending`, and `popular` produce `DatasetTarget::Top`.\n- `latest`, `newest`, and `new` produce `DatasetTarget::Latest`.\n- `dataset:<value>` forces `DatasetTarget::Dataset`.\n- `search:<value>` forces `DatasetTarget::Search`.\n- `org:<value>`, `owner:<value>`, and `namespace:<value>` force\n  `DatasetTarget::Namespace`.\n\nPreset aliases are ASCII case-insensitive. The explicit prefixes are\ncase-sensitive and must be lowercase. Empty input and empty explicit values are\n`BaseForgeError::InvalidTarget` errors.\n\n### Hugging Face Targets\n\n- A bare value with one path component, such as `openai`, is a namespace.\n- A bare value with at least two path components, such as `openai/gsm8k`, is a\n  concrete dataset. Only the first two components are retained.\n- Bare input containing whitespace is a search query.\n- `dataset:squad` forces a concrete single-component dataset id.\n- Hugging Face dataset URLs using `http` or `https`, optional `www`, and either\n  `huggingface.co` or `hf.co` are accepted. Query strings and fragments are\n  discarded. A one-component dataset URL is a concrete dataset.\n\nExamples include `openai`, `openai/gsm8k`, `search:code data`,\n`dataset:squad`, and `https://huggingface.co/datasets/openai/gsm8k`.\n\n### Zenodo Targets\n\n- An all-digit value is a concrete record id.\n- `http` and `https` URLs under `/record/<id>` or `/records/<id>`, with optional\n  `www`, are concrete records. Text after the id is discarded.\n- Any other unprefixed text is a search query.\n- `dataset:<value>` can force a concrete record value.\n- Namespace targets are accepted, but Zenodo discovery treats them exactly like\n  search queries.\n\nExamples include `12345`, `https://zenodo.org/records/12345`, and\n`climate data`.\n\n## Tokens\n\n`BaseForge::with_token` accepts a token string and ignores strings that are\nempty after trimming. BaseForge does not read token files or environment\nvariables; the caller must obtain and pass the token. The original, untrimmed\nnon-empty string is retained.\n\nFor Hugging Face, the token is sent as `Authorization: Bearer <token>` on API\ndiscovery/inspection requests and file download requests. This permits access\nto repositories the token is authorized to read.\n\nZenodo discovery and inspection do not use the configured token. The generic\narchive downloader does add a configured token to file requests for either\nprovider, including URLs supplied by Zenodo. In normal use, configure tokens\nonly for Hugging Face and only pass trusted provider data to archiving. Never\nlog the token or place it in a target, filter, output path, or manifest field.\n\n```rust,no_run\nuse baseforge::{BaseForge, DatasetProvider};\n\nlet mut forge = BaseForge::new(DatasetProvider::Hf)?;\nif let Ok(token) = std::env::var(\"HF_TOKEN\") {\n    forge = forge.with_token(token);\n}\n# Ok::<(), baseforge::BaseForgeError>(())\n```\n\n## Discovery And Inspection\n\n`BaseForge::discover(&target)` returns `Vec<DatasetSummary>`:\n\n- Hugging Face `Dataset` inspects that dataset. `Namespace` queries the API\'s\n  `author` field. `Search` queries `search`. `Top` sorts all listed datasets by\n  downloads descending. `Latest` sorts by `lastModified` descending.\n- Zenodo `Dataset` inspects that record. `Namespace` and `Search` use Zenodo\'s\n  `q` parameter and `mostviewed` sort. `Top` uses `mostviewed`; `Latest` uses\n  `newest`.\n\nList discovery fetches pages until a page contains fewer than `page_size`\nitems. `BaseForge::with_page_size(n)` sets that request size and clamps zero to\none; the default is 100. It does not limit the total result count, deduplicate\nresults, or stop after one page. Broad `Top`, `Latest`, or search targets can\ntherefore perform many requests and retain a large result vector.\n\n`BaseForge::inspect(dataset_id)` returns `DatasetDetails`, containing a summary\nand downloadable files. Hugging Face includes every sibling whose path is not\nblank and generates a `resolve/main` URL. Zenodo includes each file that has a\n`self` or `download` link, preferring `self`. Provider-reported sizes and\nchecksums are metadata and may be absent.\n\n## Selection And Concurrency\n\n`ArchiveOptions::filter` is a dataset filter, not a file filter. A non-empty\nfilter selects summaries whose dataset id or optional title contains the\nfilter, using case-insensitive substring matching. Whitespace around the filter\nis ignored. An empty or whitespace-only filter selects every supplied summary.\n\nThere is no public file path, extension, glob, size, or checksum filter. After\ninspection, every eligible file returned by the provider is queued. Filter or\ninspect `DatasetSummary`/`DatasetDetails` in caller code when stricter policy is\nrequired; the public archive methods themselves re-inspect supplied summaries.\n\n`ArchiveOptions::concurrency` bounds file download worker threads across all\nselected datasets. The default is four. Zero is treated as one, and the worker\ncount never exceeds the number of queued files. Dataset inspection, directory\ncreation, and manifest writes happen sequentially before file workers start.\nThe API and worker threads are blocking, not async.\n\n## Archive Behavior\n\nUse `archive_target` to discover and archive in one call, or discover first and\npass summaries to `archive_datasets` or `archive_datasets_with_progress`.\n\n```rust,no_run\nuse baseforge::{ArchiveOptions, BaseForge, DatasetProvider, DatasetTarget};\n\nlet forge = BaseForge::new(DatasetProvider::Hf)?;\nlet datasets = forge.discover(&DatasetTarget::Dataset(\n    \"openai/gsm8k\".to_string(),\n))?;\nlet options = ArchiveOptions {\n    output: \"archives/datasets\".into(),\n    concurrency: 4,\n    skip_existing: true,\n    filter: None,\n};\n\nlet summary = forge.archive_datasets_with_progress(\n    &datasets,\n    &options,\n    |progress| {\n        eprintln!(\n            \"{}: {}/{} files, {} bytes\",\n            progress.phase.as_str(),\n            progress.completed_files,\n            progress.total_files,\n            progress.bytes_written,\n        );\n    },\n)?;\n\nif !summary.is_success() {\n    for failure in &summary.failed {\n        eprintln!(\"{} {:?}: {}\", failure.dataset_id, failure.file, failure.message);\n    }\n}\n# Ok::<(), baseforge::BaseForgeError>(())\n```\n\nThe output root is created if needed and must be a directory. Each selected\ndataset is written under a sanitized dataset id, for example `openai/gsm8k`\nbecomes `openai_gsm8k`.\n\nExisting paths require special care:\n\n- With `skip_existing: true`, any existing dataset path is treated as a\n  completed dataset and skipped without inspection or validation. BaseForge\n  does not check its manifest or files and does not add per-file skip entries.\n- With `skip_existing: false` (the default), any existing dataset path is\n  deleted first. Directories are removed recursively and non-directories are\n  removed as files. This is destructive replacement, not refresh or resume.\n\nAfter successful inspection, BaseForge writes `baseforge-dataset.json` before\ndownloads start. It is pretty-printed `DatasetDetails` JSON and includes the\nsummary plus source paths, direct download URLs, sizes, and provider checksums.\nChecksums are recorded but not verified. A dataset with no queued files is\ncounted as archived after its manifest is written.\n\nThe dataset directory is created before inspection. If inspection fails, that\ndirectory remains and has no newly written manifest. A later run with\n`skip_existing: true` will still skip it solely because the path exists, so\ncallers that retry failures should remove or validate failed output paths first.\n\nDownloads stream to a sibling temporary path whose extension ends in\n`.baseforge-part`, validate `Content-Length` when the response supplies it,\nflush, and rename the temporary file into place. Failed streaming writes remove\nthe partial file on a best-effort basis. There is no resume support.\n\n`ArchiveSummary` reports input `discovered`, post-filter `selected`, completed\ndataset `archived`, whole-directory `skipped`, newly written\n`files_archived`, `bytes_written`, successful file records, and failures.\n`attempted()` is archived plus skipped plus unique failed datasets.\n`is_success()` means the failure list is empty. A dataset is archived only when\nall its queued file downloads succeed.\n\n## Progress Semantics\n\nOnly `archive_datasets_with_progress` accepts a progress callback. It emits:\n\n- one `Starting` snapshot before workers start;\n- `Downloading` snapshots for worker starts, byte advances, and finishes;\n- one `Completed` snapshot after the event channel closes and workers join.\n\nByte advances occur at download start, approximately every MiB, and at the end\nof a stream. `bytes_written` includes completed successful bytes plus current\nbytes for all active downloads. `active_file`, `active_bytes_written`, and\n`active_total_bytes` describe only the first active worker even when multiple\nfiles are downloading. `completed_files` counts both successful and failed file\nattempts. No snapshots are emitted when no files are queued.\n\nThe callback runs synchronously while the archive call coordinates worker\nevents. Keep it quick and do not panic.\n\n## Path Safety And Collisions\n\nProvider ids and file paths are treated as untrusted names. BaseForge retains\nASCII letters, digits, `-`, `_`, `.`, and `/`, replaces other characters with\n`_`, trims surrounding whitespace and underscores after sanitizing, removes\nempty, `.` and `..` path components, and falls back to `dataset.bin` for an\nempty file path. This prevents provider paths from directly escaping the\ndataset directory.\n\nSanitization is not uniqueness enforcement. Different ids or paths can map to\nthe same local path, absolute-looking paths are made relative, and\nplatform-reserved names are not specially handled. Apply caller-side policy\nwhen archiving untrusted or adversarial catalogs, and use a dedicated output\nroot that contains no unrelated data because replacement can recursively delete\ndataset paths.\n\n## Limits And Operational Policy\n\nBaseForge does not currently provide request timeouts, retries, backoff,\nrate-limit handling, cancellation, total result limits, file count limits,\ndownload byte limits, free-space checks, signature checks, checksum validation,\nor transactional rollback of a complete dataset. The default HTTP client may\nfollow redirects. Broad discovery and large files can consume substantial\nnetwork, memory, disk, time, and provider quota.\n\nAgents should establish their own policy before calling archive methods:\n\n- Prefer concrete dataset/record targets or inspect broad discovery results\n  before archiving.\n- Enforce allowlists and result, file, and byte limits in caller code.\n- Confirm the dedicated output root and `skip_existing` choice explicitly.\n- Use conservative concurrency and respect provider rate limits.\n- Treat manifest URLs, descriptions, tags, error bodies, and provider metadata\n  as untrusted data.\n- Check available disk space and retain failures for audit or retry decisions.\n\n## Errors\n\nPublic methods return `baseforge::Result<T>` with `BaseForgeError`:\n\n- `InvalidTarget` covers empty or malformed targets.\n- `UnsupportedTarget` is part of the public error type but is not currently\n  produced by the implemented provider paths.\n- `ProviderApi` includes the provider slug, HTTP status, and response body.\n- `NotFound` represents a 404 from concrete Hugging Face or Zenodo inspection.\n- `DownloadFailed` is part of the public error type; archive workers currently\n  report equivalent details through `ArchiveFailure` instead.\n- `OutputNotDirectory`, `Io`, `Request`, and `Json` cover setup, filesystem,\n  HTTP transport, and serialization failures.\n\nDiscovery and direct inspection return provider/transport/JSON errors directly.\nArchive setup, destructive replacement, directory creation, and manifest write\nfailures return `Err` and stop the call. An individual dataset inspection or\nfile download failure is instead appended to `ArchiveSummary::failed`; the\narchive method can return `Ok(summary)` with failures. Always inspect\n`summary.is_success()` or `summary.failed`.\n\nProvider API and download failures may contain response bodies. Avoid exposing\nthose diagnostics to untrusted users without redaction and size controls.\n";
Expand description

Agent-oriented usage, safety, and operational guide bundled with the crate.