package llmfs
import (
"fmt"
"io"
"strconv"
"strings"
"github.com/NERVsystems/llm9p/internal/llm"
"github.com/NERVsystems/llm9p/internal/protocol"
)
// ThinkingFile exposes the thinking token budget (read/write)
// Values: -1 = max (31999), 0 = disabled, >0 = specific budget
// Only effective with CLI backend; API backend ignores this setting.
type ThinkingFile struct {
*protocol.BaseFile
client llm.Backend
}
// NewThinkingFile creates the thinking file
func NewThinkingFile(client llm.Backend) *ThinkingFile {
return &ThinkingFile{
BaseFile: protocol.NewBaseFile("thinking", 0666),
client: client,
}
}
func (f *ThinkingFile) Read(p []byte, offset int64) (int, error) {
tokens := f.client.ThinkingTokens()
var content string
switch {
case tokens < 0:
content = "max\n"
case tokens == 0:
content = "off\n"
default:
content = fmt.Sprintf("%d\n", tokens)
}
if offset >= int64(len(content)) {
return 0, io.EOF
}
n := copy(p, content[offset:])
return n, nil
}
func (f *ThinkingFile) Write(p []byte, offset int64) (int, error) {
input := strings.TrimSpace(string(p))
input = strings.ToLower(input)
var tokens int
switch input {
case "max", "on", "true", "enabled", "-1":
tokens = -1
case "off", "false", "disabled", "0":
tokens = 0
default:
var err error
tokens, err = strconv.Atoi(input)
if err != nil {
return 0, fmt.Errorf("invalid thinking value: use 'max', 'off', or a number")
}
if tokens < 0 {
tokens = -1 // Treat any negative as max
}
}
f.client.SetThinkingTokens(tokens)
return len(p), nil
}
func (f *ThinkingFile) Stat() protocol.Stat {
s := f.BaseFile.Stat()
tokens := f.client.ThinkingTokens()
var content string
switch {
case tokens < 0:
content = "max\n"
case tokens == 0:
content = "off\n"
default:
content = fmt.Sprintf("%d\n", tokens)
}
s.Length = uint64(len(content))
return s
}