@hasna/models 0.0.1

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.
package/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ https://www.apache.org/licenses/
4
+
5
+ Copyright 2026 Hasna
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ https://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
package/PLAN.md ADDED
@@ -0,0 +1,359 @@
1
+ # Open Models build plan
2
+
3
+ ## Goal
4
+
5
+ Build `@hasna/models` as a CLI-first local model and dataset lifecycle tool.
6
+ The first version should make Hugging Face easy to search, inspect, install,
7
+ cache, and run locally, while keeping the provider contract broad enough for
8
+ ModelScope, Kaggle, Civitai, GitHub release assets, Ollama libraries, and future
9
+ registries.
10
+
11
+ The product should feel like the model equivalent of the existing Hasna tools:
12
+ one package, one CLI, stable JSON contracts, local-first storage, optional MCP
13
+ later, and optional `@hasna/machines/consumer` integration for remote/local
14
+ machine resolution.
15
+
16
+ ## Research summary
17
+
18
+ Hugging Face is the first provider, but the abstraction should not be named
19
+ around Hugging Face. The Hub has model, dataset, and Space repo types, plus
20
+ collections, papers, jobs, inference providers/endpoints, and storage buckets.
21
+ Its repo cards carry the important discovery metadata: license, task, language,
22
+ dataset links, tags, and size-like metadata. Hugging Face also exposes JS and
23
+ Python libraries for listing, repo access checks, file downloads, cache scans,
24
+ and full snapshot downloads.
25
+
26
+ Datasets need first-class treatment, not a side command. Hugging Face Datasets
27
+ supports Hub datasets, local files, remote files, specific revisions, split
28
+ mapping, streaming for huge datasets, and separate cache controls. The CLI
29
+ should default to inspecting and streaming samples before downloading large
30
+ datasets.
31
+
32
+ Local execution is a runtime problem, not a provider problem. Providers answer
33
+ "what exists and where are the files"; runtimes answer "can this artifact run on
34
+ this machine." The first runtime adapters should be:
35
+
36
+ - `ollama`: easiest local UX for common chat models and its own model store/API.
37
+ - `llama.cpp`: best direct path for GGUF, CPU/GPU, OpenAI-compatible local server.
38
+ - `vllm`: higher-throughput server for GPU machines and safetensors/HF models.
39
+ - `mlx`: Apple Silicon path through `mlx-lm` and MLX-compatible models.
40
+ - `python-transformers`: fallback/debug path for models that need custom Python.
41
+
42
+ Comparable providers are not all model hubs. ModelScope is a model/dataset hub
43
+ with inference/training APIs. Kaggle has datasets, models, competitions, and
44
+ kernels. Civitai is model/version/artifact heavy for image models. GitHub
45
+ releases are a generic artifact source with release asset metadata and digests.
46
+ The provider interface must therefore support different entity kinds, metadata
47
+ quality, auth, license gates, and download mechanisms.
48
+
49
+ ## Local ecosystem constraints
50
+
51
+ Follow these existing package patterns:
52
+
53
+ - Use Bun, TypeScript, Commander, and `@hasna/models` with binaries
54
+ `models` first and `models-mcp` later.
55
+ - Store local state under `~/.hasna/models/`.
56
+ - Prefer dry-run plans for installs, runtime setup, destructive cache actions,
57
+ and remote-machine operations.
58
+ - Every important command should have `--json`.
59
+ - Keep CLI/MCP parity as a contract, even if MCP ships after the CLI.
60
+ - Keep private credentials out of public manifests. Store provider tokens in a
61
+ local profile/auth file or delegate to existing connector/secret tooling later.
62
+ - Treat `@hasna/machines/consumer` as optional. Try SDK, then `machines` CLI,
63
+ then local fallback diagnostics.
64
+
65
+ ## Core architecture
66
+
67
+ Separate the system into four contracts.
68
+
69
+ ### Provider adapter
70
+
71
+ Responsible for catalog/search/info/files/download metadata, not execution.
72
+
73
+ ```ts
74
+ export interface ModelProviderAdapter {
75
+ id: string;
76
+ capabilities: ProviderCapabilities;
77
+ search(input: SearchInput): AsyncIterable<CatalogEntry>;
78
+ info(ref: ProviderRef): Promise<CatalogEntryDetail>;
79
+ files(ref: ProviderRef): AsyncIterable<RemoteFileEntry>;
80
+ resolveDownload(input: DownloadRequest): Promise<DownloadPlan>;
81
+ checkAccess?(ref: ProviderRef): Promise<AccessCheck>;
82
+ }
83
+ ```
84
+
85
+ Normalize all providers into:
86
+
87
+ - `provider`, `entity_kind`, `repo_id`, `revision`, `canonical_url`
88
+ - `license`, `gated`, `requires_auth`, `publisher`, `tags`, `task`, `modality`
89
+ - `files[]` with path, size, etag/digest when available, format, quantization
90
+ - `card` metadata and raw provider metadata for debug
91
+
92
+ First adapters:
93
+
94
+ - `huggingface`: models, datasets, spaces, collections, repo files.
95
+ - `github-release`: generic artifact fallback for projects distributing GGUF,
96
+ ONNX, safetensors, or archives outside model hubs.
97
+ - Later: `modelscope`, `kaggle`, `civitai`, `ollama-library`.
98
+
99
+ ### Artifact selector
100
+
101
+ Responsible for picking the right file set.
102
+
103
+ Inputs:
104
+
105
+ - desired task: chat, completion, embedding, rerank, image, audio, dataset
106
+ - machine facts: OS, CPU, RAM, disk, GPU, VRAM, Apple Silicon, installed runtimes
107
+ - preferences: quantization, format, max size, license policy, offline mode
108
+
109
+ Output:
110
+
111
+ - ranked install candidates
112
+ - reason for each candidate
113
+ - expected disk and memory requirements
114
+ - compatible runtimes
115
+ - exact files to download
116
+
117
+ This avoids blindly downloading every file in a large repo.
118
+
119
+ ### Local store
120
+
121
+ Use SQLite metadata plus a content/cache directory.
122
+
123
+ Recommended layout:
124
+
125
+ ```text
126
+ ~/.hasna/models/
127
+ models.db
128
+ auth.json
129
+ config.json
130
+ cache/
131
+ huggingface/
132
+ github-release/
133
+ installs/
134
+ <provider>/<namespace>/<name>/<revision>/
135
+ runtimes/
136
+ logs/
137
+ ```
138
+
139
+ Do not fight Hugging Face's cache unless needed. Use provider-native caching
140
+ where reliable, but record installed entities in `models.db` with paths,
141
+ revision, selected files, size, digests, license decision, access decision,
142
+ runtime compatibility, and provenance. Prefer symlinks or references from
143
+ `installs/` into provider cache over duplicate bytes.
144
+
145
+ ### Runtime adapter
146
+
147
+ Responsible for setup, run, serve, stop, and health.
148
+
149
+ ```ts
150
+ export interface RuntimeAdapter {
151
+ id: string;
152
+ detect(machine: MachineTarget): Promise<RuntimeStatus>;
153
+ planSetup(input: RuntimeSetupInput): Promise<RuntimeSetupPlan>;
154
+ canRun(input: InstalledArtifact): Promise<RuntimeCompatibility>;
155
+ run(input: RunInput): Promise<RunPlan | RunHandle>;
156
+ serve(input: ServeInput): Promise<ServePlan | ServeHandle>;
157
+ }
158
+ ```
159
+
160
+ Each runtime adapter should produce a plan first. Applying a setup plan should
161
+ require explicit `--apply --yes`, matching `open-machines`.
162
+
163
+ ## CLI shape
164
+
165
+ First release command surface:
166
+
167
+ ```bash
168
+ models providers list
169
+ models providers auth huggingface
170
+ models providers status --json
171
+
172
+ models search "qwen coder" --task text-generation --license apache-2.0 --json
173
+ models info hf:Qwen/Qwen3-Coder --json
174
+ models files hf:Qwen/Qwen3-Coder --format safetensors --json
175
+
176
+ models plan hf:Qwen/Qwen3-Coder --machine local --json
177
+ models install hf:Qwen/Qwen3-Coder --runtime llama.cpp --quant q4_k_m --json
178
+ models list --installed --json
179
+ models where hf:Qwen/Qwen3-Coder --json
180
+ models remove <install-id> --dry-run --json
181
+ models cache status --json
182
+ models cache prune --dry-run --json
183
+
184
+ models run <install-id-or-ref> "hello" --json
185
+ models serve <install-id-or-ref> --runtime vllm --port 11435 --json
186
+ models ps --json
187
+ models stop <serve-id> --json
188
+
189
+ models datasets search "medical images" --json
190
+ models datasets info hf:stanford-crfm/whatever --json
191
+ models datasets sample hf:... --split train --limit 5 --json
192
+ models datasets stream hf:... --split train
193
+ models datasets install hf:... --split train --max-bytes 20GB --json
194
+
195
+ models machines topology --json
196
+ models machines preflight local --json
197
+ models machines install spark01 hf:... --dry-run --json
198
+ models machines run spark01 <install-id-or-ref> "hello" --json
199
+
200
+ models doctor --json
201
+ models manual
202
+ ```
203
+
204
+ Keep `models install` friendly for humans, but make `models plan` the contract
205
+ agents and tests depend on.
206
+
207
+ ## Machine integration
208
+
209
+ Machine support should be optional and layered:
210
+
211
+ 1. Import `@hasna/machines/consumer` dynamically.
212
+ 2. If unavailable, call installed `machines topology --json` / compatibility
213
+ commands.
214
+ 3. If unavailable, use local-only probes.
215
+
216
+ Use machines for route and workspace resolution, then run app-owned probes over
217
+ `runMachineCommand` or CLI fallback:
218
+
219
+ - OS, architecture, CPU cores
220
+ - RAM and disk free
221
+ - GPU command availability: `nvidia-smi`, `rocm-smi`, `system_profiler`
222
+ - runtime command availability: `ollama`, `llama-server`, `vllm`, `mlx_lm`
223
+ - Python/Bun availability
224
+
225
+ The `models` package should own model-specific compatibility logic; machines
226
+ should only provide route/workspace/command execution boundaries.
227
+
228
+ ## Dataset handling
229
+
230
+ Datasets should share provider/search/auth/storage infrastructure with models
231
+ but have their own install semantics:
232
+
233
+ - `sample` and `stream` before `install`
234
+ - split-aware metadata
235
+ - file-pattern selection
236
+ - row/sample previews
237
+ - max byte caps by default
238
+ - local materialization records with source revision and data files
239
+ - no accidental full download of massive corpora
240
+
241
+ For Python-heavy dataset transforms, `models` can generate a deterministic
242
+ Python runner script or call `python -m datasets` helpers, but the durable CLI
243
+ contract should stay in TypeScript JSON.
244
+
245
+ ## Safety and policy
246
+
247
+ Defaults:
248
+
249
+ - Search/info/list are side-effect free.
250
+ - Install is explicit and records license/gated access decisions.
251
+ - Runtime setup is dry-run by default.
252
+ - Running provider repo code is disabled unless a command opts in clearly.
253
+ - Destructive removal and pruning are preview-first.
254
+ - Provider tokens are never printed in JSON, logs, or errors.
255
+ - Download plans must show total estimated bytes and unresolved size gaps.
256
+ - Gated/private repo errors should be structured, not swallowed.
257
+
258
+ ## Implementation phases
259
+
260
+ ### Phase 0: scaffold and contracts
261
+
262
+ - Add `package.json`, `tsconfig.json`, Bun build/test scripts.
263
+ - Add `src/cli/index.ts`, `src/index.ts`, `src/types.ts`.
264
+ - Add `src/providers/types.ts`, `src/store/schema.ts`, `src/runtimes/types.ts`.
265
+ - Add a small JSON contract test for every command added.
266
+
267
+ Exit criteria: `models --help`, `models doctor --json`, and `bun test`.
268
+
269
+ ### Phase 1: Hugging Face catalog
270
+
271
+ - Implement `huggingface` provider using `@huggingface/hub` where practical.
272
+ - Commands: `providers`, `search`, `info`, `files`.
273
+ - Normalize model/dataset/space entries.
274
+ - Persist search snapshots and info lookups in SQLite with TTL.
275
+
276
+ Exit criteria: can inspect public/gated/private error states and produce stable
277
+ JSON without downloading model bytes.
278
+
279
+ ### Phase 2: install/store manager
280
+
281
+ - Implement download planning and exact file selection.
282
+ - Support full snapshot and selected-file download.
283
+ - Record install provenance, size, digests/etag, and local paths.
284
+ - Add `list`, `where`, `remove`, `cache status`, `cache prune`.
285
+
286
+ Exit criteria: install a small public model and a small dataset, list them,
287
+ remove them through dry-run/apply, and verify no duplicate metadata drift.
288
+
289
+ ### Phase 3: runtime adapters
290
+
291
+ - Start with `ollama` and `llama.cpp`; add `vllm` and `mlx` after contracts hold.
292
+ - Implement `doctor`, `runtimes status`, `plan`, `run`, and `serve`.
293
+ - Normalize OpenAI-compatible local endpoint output where possible.
294
+
295
+ Exit criteria: run or serve a compatible local artifact, capture process/port
296
+ metadata, and expose health in JSON.
297
+
298
+ ### Phase 4: machine-aware workflows
299
+
300
+ - Add optional `@hasna/machines/consumer` integration.
301
+ - Commands: `machines topology`, `machines preflight`, `machines install`,
302
+ `machines run`.
303
+ - Add remote dry-run plans before SSH execution.
304
+
305
+ Exit criteria: local fallback works without machines installed; SDK/CLI adapter
306
+ smoke tests pass when machines is present.
307
+
308
+ ### Phase 5: more providers and MCP
309
+
310
+ - Add `github-release`, then `modelscope` or `kaggle` based on usage.
311
+ - Add `models-mcp` with parity manifest.
312
+ - Add SDK fixtures and command contract snapshots.
313
+
314
+ Exit criteria: provider adapter tests prove Hugging Face is not special-cased in
315
+ the store or runtime layers.
316
+
317
+ ## Tests to require early
318
+
319
+ - Provider contract tests with fixture JSON and no network.
320
+ - One network smoke behind an explicit env flag.
321
+ - CLI JSON snapshot tests.
322
+ - Store migration tests.
323
+ - Download planner tests for GGUF, safetensors shards, dataset shards, missing
324
+ sizes, gated repos, and revision pinning.
325
+ - Runtime planner tests for CPU-only, NVIDIA GPU, Apple Silicon, and missing
326
+ runtime cases.
327
+ - Machines adapter smoke matching `open-knowledge` style: SDK, CLI, unsupported
328
+ future contract, no-SDK fallback.
329
+
330
+ ## Sources checked
331
+
332
+ - Hugging Face Hub Python API:
333
+ https://huggingface.co/docs/huggingface_hub/en/package_reference/hf_api
334
+ - Hugging Face file download API:
335
+ https://huggingface.co/docs/huggingface_hub/en/package_reference/file_download
336
+ - Huggingface.js Hub API:
337
+ https://huggingface.co/docs/huggingface.js/en/hub/README
338
+ - Hugging Face model cards:
339
+ https://huggingface.co/docs/hub/en/model-cards
340
+ - Hugging Face dataset cards:
341
+ https://huggingface.co/docs/hub/en/datasets-cards
342
+ - Hugging Face Datasets loading, streaming, and cache docs:
343
+ https://huggingface.co/docs/datasets/en/loading
344
+ https://huggingface.co/docs/datasets/en/stream
345
+ https://huggingface.co/docs/datasets/en/cache
346
+ - Ollama API docs:
347
+ https://github.com/ollama/ollama/blob/main/docs/api.md
348
+ - llama.cpp server docs:
349
+ https://github.com/ggml-org/llama.cpp/tree/master/tools/server
350
+ - vLLM project README:
351
+ https://github.com/vllm-project/vllm
352
+ - MLX LM README:
353
+ https://github.com/ml-explore/mlx-lm
354
+ - ModelScope README:
355
+ https://github.com/modelscope/modelscope
356
+ - Kaggle CLI README:
357
+ https://github.com/Kaggle/kaggle-cli
358
+ - GitHub release assets API:
359
+ https://docs.github.com/en/rest/releases/assets
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # models
2
+
3
+ A friendlier, more capable wrapper around Hugging Face for **discovering, searching,
4
+ downloading, and running local models** — open source.
5
+
6
+ > Folder: `open-models` · npm: `@hasna/models` · GitHub: `hasna/models` · CLI: `models`
7
+
8
+ ## Why
9
+
10
+ The Hugging Face CLI gets the bytes down, but finding the right model, picking the
11
+ right format/quantization, managing disk, and actually running it is still fiddly.
12
+ `models` aims to be the single tool for the whole local-model lifecycle.
13
+
14
+ ## Planned features
15
+
16
+ - **Browse & search** the full HF catalog with rich filters (task, library, license,
17
+ size, format — GGUF/safetensors, quantization)
18
+ - **One-command install** of any model to a local store, with resumable downloads
19
+ - **Disk management** — see what's installed, sizes, dedupe, prune
20
+ - **Run / serve helpers** — quick local inference or an OpenAI-compatible endpoint
21
+ - **Search across installed + remote** in one place
22
+ - CLI + (later) MCP server, consistent with the Hasna OSS tooling
23
+
24
+ ## Status
25
+
26
+ First CLI slice implemented. The package now has a Bun/TypeScript `models` CLI,
27
+ Hugging Face provider access, local SQLite catalog storage, selected-file
28
+ downloads, dataset search/install parity, and a local implementation goal chain.
29
+
30
+ See [PLAN.md](PLAN.md) for the full architecture and [docs/GOALS.md](docs/GOALS.md)
31
+ for the chained build goals.
32
+
33
+ ## Quick start
34
+
35
+ ```bash
36
+ bun install
37
+ bun run build
38
+ bun run src/cli/index.ts providers status --json
39
+ bun run src/cli/index.ts search tiny-gpt2 --limit 3
40
+ bun run src/cli/index.ts index best --limit 500 --json
41
+ bun run src/cli/index.ts install hf:sshleifer/tiny-gpt2 \
42
+ --include config.json \
43
+ --include tokenizer_config.json \
44
+ --include vocab.json \
45
+ --include merges.txt \
46
+ --max-bytes 5mb
47
+ ```
48
+
49
+ Local data is stored under `~/.hasna/models/` by default. Set
50
+ `HASNA_MODELS_HOME` or `HASNA_MODELS_DB` to isolate test stores.
51
+
52
+ Provider tokens are read from environment variables, `~/.hasna/models/auth.json`,
53
+ or generic local `secrets` keys such as `huggingface/token`. Secret references
54
+ stay local and are redacted from normal status output. For private or
55
+ organization-specific secret names, configure a local reference without
56
+ committing it:
57
+
58
+ ```bash
59
+ models providers auth huggingface --secret-key <your/local/hf/token/key>
60
+ ```
61
+
62
+ This package targets Bun for the CLI and library surface because it uses
63
+ `bun:sqlite`.
64
+
65
+ ## License
66
+
67
+ Apache-2.0.
package/dist/auth.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { AuthStatus } from "./types.js";
2
+ export declare function redactAuthStatus(status: AuthStatus): AuthStatus;
3
+ export declare function resolveHuggingFaceToken(): {
4
+ token: string | null;
5
+ status: AuthStatus;
6
+ };
7
+ export declare function getHuggingFaceAuthStatus(): AuthStatus;
8
+ export declare function saveHuggingFaceSecretRef(secretKey: string): AuthStatus;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ export {};