Skip to content
144 changes: 144 additions & 0 deletions cmd/download_weights.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package cmd

import (
"context"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/CognitiveOS-Project/cpm/internal/weights"
"github.com/spf13/cobra"
)

var (
downloadProvider string
downloadKind string
downloadFormat string
downloadOutput string
downloadDryRun bool
)

var downloadWeightsCmd = &cobra.Command{
Use: "download-weights <model-name>",
Short: "Download model weights from a provider",
Long: `Download model weights (GGUF, safetensors) from a weight provider.

Provider: hf (Hugging Face Hub) — searches public GGUF models sorted by downloads.
cpm download-weights --provider hf --kind wide --type gguf google/gemma-4-2b
cpm download-weights --provider hf --kind raw --type gguf CognitiveOS/raw-model

Files are placed at:
--kind raw → /cognitiveos/models/raw/raw-model-<name>.gguf (skip if exists)
--kind wide → /cognitiveos/models/wide/active/<filename>.gguf
`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
modelName := args[0]

var kind weights.Kind
switch downloadKind {
case "raw":
kind = weights.KindRaw
case "wide":
kind = weights.KindWide
default:
return fmt.Errorf("invalid --kind: %q (must be raw or wide)", downloadKind)
}

var format weights.Format
switch downloadFormat {
case "gguf":
format = weights.FormatGGUF
case "safetensors":
format = weights.FormatSafeTensors
default:
return fmt.Errorf("invalid --type: %q (must be gguf or safetensors)", downloadFormat)
}

var prov weights.Provider
switch downloadProvider {
case "hf":
prov = weights.NewHFProvider()
default:
return fmt.Errorf("invalid --provider: %q (must be hf)", downloadProvider)
}

ctx := context.Background()

candidates, err := prov.Search(ctx, modelName, 5)
if err != nil {
return fmt.Errorf("search: %w", err)
}

formatExt := "." + format.String()

var match *weights.Candidate
for i := range candidates {
if strings.HasSuffix(strings.ToLower(candidates[i].Filename), formatExt) {
match = &candidates[i]
break
}
}
if match == nil {
for i := range candidates {
if strings.Contains(strings.ToLower(candidates[i].Filename), strings.ToLower(modelName)) {
match = &candidates[i]
break
}
}
}
if match == nil && len(candidates) > 0 {
match = &candidates[0]
}
if match == nil {
return fmt.Errorf("no %s files found for %q", formatExt, modelName)
}

dest := downloadOutput
if dest == "" {
dest = resolveDest(kind, match)
}
fmt.Printf("Found: %s\n", match.DownloadURL)
fmt.Printf("File: %s\n", match.Filename)
fmt.Printf("Dest: %s\n", dest)

if downloadDryRun {
return nil
}

if kind == weights.KindRaw {
if _, err := os.Stat(dest); err == nil {
fmt.Printf("File already exists at %s — skipping (use --kind wide to re-download)\n", dest)
return nil
}
}

fmt.Println("Downloading...")
if err := weights.Download(ctx, match.DownloadURL, dest, match.SHA256, weights.TextProgress); err != nil {
return fmt.Errorf("download: %w", err)
}
fmt.Printf("✓ Downloaded to %s\n", dest)
return nil
},
}

func resolveDest(kind weights.Kind, c *weights.Candidate) string {
dir := weights.ModelDir(kind)
if kind == weights.KindRaw {
base := strings.TrimSuffix(c.Filename, filepath.Ext(c.Filename))
name := fmt.Sprintf("raw-model-%s%s", base, filepath.Ext(c.Filename))
return filepath.Join(dir, name)
}
return filepath.Join(dir, c.Filename)
}

func init() {
fs := downloadWeightsCmd.Flags()
fs.StringVar(&downloadProvider, "provider", "hf", "Weight provider (hf)")
fs.StringVar(&downloadKind, "kind", "wide", "Model kind (raw or wide)")
fs.StringVar(&downloadFormat, "type", "gguf", "File format (gguf or safetensors)")
fs.StringVar(&downloadOutput, "output", "", "Custom output path (overrides default)")
fs.BoolVar(&downloadDryRun, "dry-run", false, "Show what would be downloaded without downloading")
rootCmd.AddCommand(downloadWeightsCmd)
}
2 changes: 1 addition & 1 deletion cmd/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ var infoCmd = &cobra.Command{

func dirSize(path string) int64 {
var size int64
filepath.Walk(path, func(_ string, fi os.FileInfo, err error) error {
_ = filepath.Walk(path, func(_ string, fi os.FileInfo, err error) error {
if err == nil && !fi.IsDir() {
size += fi.Size()
}
Expand Down
155 changes: 115 additions & 40 deletions cmd/init_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"github.com/spf13/cobra"
)

var initTemplate string

var initCmd = &cobra.Command{
Use: "init [<dir>]",
Short: "Create a .cgp skeleton directory",
Expand All @@ -23,58 +25,131 @@ var initCmd = &cobra.Command{
return fmt.Errorf("directory %q already exists", dir)
}

dirs := []string{
filepath.Join(dir, "prompts", "templates"),
filepath.Join(dir, "tools"),
}
for _, d := range dirs {
if err := os.MkdirAll(d, 0755); err != nil {
return fmt.Errorf("create %s: %w", d, err)
}
switch initTemplate {
case "gguf-model":
return initGGUFModel(dir)
default:
return initDefault(dir)
}
},
}

manifest := map[string]interface{}{
"name": filepath.Base(dir),
"version": "0.1.0",
"description": "Describe what this patch does",
"author": "",
"license": "MIT",
"hardware_requirements": map[string]interface{}{
"min_ram_mb": 512,
"min_storage_mb": 50,
},
"runtime": map[string]interface{}{
"system_prompt": "prompts/system.md",
"tools_root": "tools",
},
func initDefault(dir string) error {
dirs := []string{
filepath.Join(dir, "prompts", "templates"),
filepath.Join(dir, "tools"),
}
for _, d := range dirs {
if err := os.MkdirAll(d, 0755); err != nil {
return fmt.Errorf("create %s: %w", d, err)
}
}

mf, err := os.Create(filepath.Join(dir, "cognitive.json"))
if err != nil {
return fmt.Errorf("create cognitive.json: %w", err)
}
defer mf.Close()
manifest := map[string]interface{}{
"name": filepath.Base(dir),
"version": "0.1.0",
"description": "Describe what this patch does",
"author": "",
"license": "MIT",
"hardware_requirements": map[string]interface{}{
"min_ram_mb": 512,
"min_storage_mb": 50,
},
"runtime": map[string]interface{}{
"system_prompt": "prompts/system.md",
"tools_root": "tools",
},
}

enc := json.NewEncoder(mf)
enc.SetIndent("", " ")
if err := enc.Encode(manifest); err != nil {
return fmt.Errorf("write cognitive.json: %w", err)
}
if err := writeManifest(dir, manifest); err != nil {
return err
}

systemPrompt := `# System Prompt
systemPrompt := `# System Prompt

You are a CognitiveOS skill. When loaded, your behavior is defined here.
`
if err := os.WriteFile(filepath.Join(dir, "prompts", "system.md"), []byte(systemPrompt), 0644); err != nil {
return fmt.Errorf("write system.md: %w", err)
}
if err := os.WriteFile(filepath.Join(dir, "prompts", "system.md"), []byte(systemPrompt), 0644); err != nil {
return fmt.Errorf("write system.md: %w", err)
}

fmt.Printf("✓ Created .cgp skeleton in %s/\n", dir)
fmt.Printf(" Next: edit %s and add your tools/prompts\n", filepath.Join(dir, "cognitive.json"))
return nil
},
fmt.Printf("✓ Created .cgp skeleton in %s/\n", dir)
fmt.Printf(" Next: edit %s and add your tools/prompts\n", filepath.Join(dir, "cognitive.json"))
return nil
}

func initGGUFModel(dir string) error {
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("create %s: %w", dir, err)
}

manifest := map[string]interface{}{
"name": filepath.Base(dir),
"version": "1.0.0",
"description": "GGUF model distributed via CognitiveOS",
"author": "",
"license": "MIT",
"source": map[string]interface{}{
"repository": "",
"issues": "",
},
"hardware_requirements": map[string]interface{}{
"min_ram_mb": 4096,
"min_storage_mb": 2048,
"npu_required": false,
},
"checksum": map[string]interface{}{
"sha256": "",
},
"brain": map[string]interface{}{
"wide_model": map[string]interface{}{
"base_model": filepath.Base(dir),
"weights": map[string]interface{}{
"remote": map[string]interface{}{
"source": "huggingface",
"model_id": "org/model-name",
"filename": "model-name-Q4_K_M.gguf",
"format": "gguf",
"quant": "Q4_K_M",
"size_bytes": 0,
},
},
"parameters": map[string]interface{}{
"temperature": 0.7,
"num_ctx": 8192,
},
},
},
"runtime": map[string]interface{}{
"capabilities": []string{"model.llm", "model.chat"},
},
}

if err := writeManifest(dir, manifest); err != nil {
return err
}

fmt.Printf("✓ Created gguf-model skeleton in %s/\n", dir)
fmt.Printf(" Next: edit cognitive.json — set model_id, filename, quant, size_bytes\n")
return nil
}

func writeManifest(dir string, manifest map[string]interface{}) error {
mf, err := os.Create(filepath.Join(dir, "cognitive.json"))
if err != nil {
return fmt.Errorf("create cognitive.json: %w", err)
}
defer mf.Close()

enc := json.NewEncoder(mf)
enc.SetIndent("", " ")
if err := enc.Encode(manifest); err != nil {
return fmt.Errorf("write cognitive.json: %w", err)
}
return nil
}

func init() {
initCmd.Flags().StringVar(&initTemplate, "template", "", "Skeleton template (gguf-model)")
rootCmd.AddCommand(initCmd)
}
Loading
Loading