Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ func (a *App) GetWSLPiDetection(distro string) (wsl.PiDetection, error) {
return wsl.DetectPi(distro)
}

func (a *App) GetWSLPiConfigDocuments(distro string) (wsl.PiConfigDocuments, error) {
return wsl.ReadPiConfigDocuments(distro)
}

func (a *App) ListProviders() ([]provider.ConfigTransport, error) {
cfg, err := a.coordinator.Load()
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions frontend/wailsjs/go/main/App.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export function GetAppState():Promise<config.AppState>;

export function GetWSLDetection():Promise<wsl.Detection>;

export function GetWSLPiConfigDocuments(arg1:string):Promise<wsl.PiConfigDocuments>;

export function GetWSLPiDetection(arg1:string):Promise<wsl.PiDetection>;

export function ImportModels(arg1:string,arg2:Array<provider.ModelTransport>):Promise<void>;
Expand Down
4 changes: 4 additions & 0 deletions frontend/wailsjs/go/main/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export function GetWSLDetection() {
return window['go']['main']['App']['GetWSLDetection']();
}

export function GetWSLPiConfigDocuments(arg1) {
return window['go']['main']['App']['GetWSLPiConfigDocuments'](arg1);
}

export function GetWSLPiDetection(arg1) {
return window['go']['main']['App']['GetWSLPiDetection'](arg1);
}
Expand Down
20 changes: 20 additions & 0 deletions frontend/wailsjs/go/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,26 @@ export namespace wsl {
this.distros = source["distros"];
}
}
export class PiConfigDocuments {
distro: string;
settingsExists: boolean;
modelsExists: boolean;
settingsJson: string;
modelsJson: string;

static createFrom(source: any = {}) {
return new PiConfigDocuments(source);
}

constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.distro = source["distro"];
this.settingsExists = source["settingsExists"];
this.modelsExists = source["modelsExists"];
this.settingsJson = source["settingsJson"];
this.modelsJson = source["modelsJson"];
}
}
export class PiDetection {
distro: string;
home: string;
Expand Down
99 changes: 99 additions & 0 deletions internal/wsl/pi_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package wsl

import (
"fmt"
"io"
"os/exec"
"path"
"unicode/utf8"
)

const piConfigDocumentLimit int64 = 1 << 23

type PiConfigDocuments struct {
Distro string `json:"distro"`
SettingsExists bool `json:"settingsExists"`
ModelsExists bool `json:"modelsExists"`
SettingsJSON string `json:"settingsJson"`
ModelsJSON string `json:"modelsJson"`
}

type piConfigDetector func(string) (PiDetection, error)
type piConfigFileReader func(distro, linuxPath string) (string, error)

func readPiConfigDocuments(distro string, detect piConfigDetector, readFile piConfigFileReader) (PiConfigDocuments, error) {
detection, err := detect(distro)
if err != nil {
return PiConfigDocuments{}, fmt.Errorf("detect WSL Pi configuration: %w", err)
}

result := PiConfigDocuments{
Distro: detection.Distro,
SettingsExists: detection.SettingsExists,
ModelsExists: detection.ModelsExists,
}

if detection.SettingsExists {
settingsPath := path.Join(detection.PiHome, "agent", "settings.json")
content, err := readFile(distro, settingsPath)
if err != nil {
return PiConfigDocuments{}, fmt.Errorf("read WSL Pi document %q: %w", settingsPath, err)
}
result.SettingsJSON = content
}

if detection.ModelsExists {
modelsPath := path.Join(detection.PiHome, "agent", "models.json")
content, err := readFile(distro, modelsPath)
if err != nil {
return PiConfigDocuments{}, fmt.Errorf("read WSL Pi document %q: %w", modelsPath, err)
}
result.ModelsJSON = content
}

return result, nil
}

func readBounded(r io.Reader, limit int64) ([]byte, error) {
data, err := io.ReadAll(io.LimitReader(r, limit+1))
if err != nil {
return nil, err
}
if int64(len(data)) > limit {
return nil, fmt.Errorf("document exceeds %d bytes", limit)
}
return data, nil
}

func decodePiConfigDocument(data []byte) (string, error) {
if !utf8.Valid(data) {
return "", fmt.Errorf("document is not valid UTF-8")
}
return string(data), nil
}

func consumePiConfigCommand(cmd *exec.Cmd, limit int64) (string, error) {
stdout, err := cmd.StdoutPipe()
if err != nil {
return "", fmt.Errorf("open document stdout: %w", err)
}
if err := cmd.Start(); err != nil {
return "", fmt.Errorf("start document read: %w", err)
}

data, readErr := readBounded(stdout, limit)
if readErr != nil {
_ = stdout.Close()
_ = cmd.Wait()
return "", readErr
}
if err := cmd.Wait(); err != nil {
return "", err
}

text, err := decodePiConfigDocument(data)
if err != nil {
return "", err
}
return text, nil
}
9 changes: 9 additions & 0 deletions internal/wsl/pi_config_stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//go:build !windows

package wsl

import "fmt"

func ReadPiConfigDocuments(string) (PiConfigDocuments, error) {
return PiConfigDocuments{}, fmt.Errorf("WSL Pi configuration reading is supported only on Windows")
}
Loading
Loading