style: fix gofumpt/gci formatting and bodyclose lint warning
Run gofumpt and gci to fix import ordering and formatting across all files flagged by golangci-lint. Add nolint:bodyclose directive for streaming HTTP response (body is closed in goroutine). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9885bc1f36
commit
5801176dfe
27 changed files with 182 additions and 194 deletions
|
|
@ -1174,8 +1174,10 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
|
|||
}
|
||||
|
||||
// Task reminder constants and helpers.
|
||||
const taskReminderMaxChars = 500
|
||||
const blockerMaxChars = 200
|
||||
const (
|
||||
taskReminderMaxChars = 500
|
||||
blockerMaxChars = 200
|
||||
)
|
||||
|
||||
func shouldInjectReminder(iteration, interval int) bool {
|
||||
if interval <= 0 {
|
||||
|
|
|
|||
|
|
@ -1833,15 +1833,18 @@ func TestBuildRichStatus_FixedHeight(t *testing.T) {
|
|||
lines0 := countLines(buildRichStatus(task0, true, "/ws/p"))
|
||||
|
||||
// 1 entry
|
||||
task1 := &activeTask{Iteration: 1, MaxIter: 10,
|
||||
toolLog: []toolLogEntry{{Name: "exec", ArgsSnip: "ls", Result: "⏳"}}}
|
||||
task1 := &activeTask{
|
||||
Iteration: 1, MaxIter: 10,
|
||||
toolLog: []toolLogEntry{{Name: "exec", ArgsSnip: "ls", Result: "⏳"}},
|
||||
}
|
||||
lines1 := countLines(buildRichStatus(task1, true, "/ws/p"))
|
||||
|
||||
// 5 entries
|
||||
task5 := &activeTask{Iteration: 5, MaxIter: 10}
|
||||
for i := 0; i < 5; i++ {
|
||||
task5.toolLog = append(task5.toolLog, toolLogEntry{
|
||||
Name: fmt.Sprintf("[%d] exec", i), ArgsSnip: "cmd", Result: "✓ 1.0s"})
|
||||
Name: fmt.Sprintf("[%d] exec", i), ArgsSnip: "cmd", Result: "✓ 1.0s",
|
||||
})
|
||||
}
|
||||
lines5 := countLines(buildRichStatus(task5, true, "/ws/p"))
|
||||
|
||||
|
|
@ -1849,10 +1852,13 @@ func TestBuildRichStatus_FixedHeight(t *testing.T) {
|
|||
task5err := &activeTask{Iteration: 5, MaxIter: 10}
|
||||
for i := 0; i < 5; i++ {
|
||||
task5err.toolLog = append(task5err.toolLog, toolLogEntry{
|
||||
Name: fmt.Sprintf("[%d] exec", i), ArgsSnip: "cmd", Result: "✓ 1.0s"})
|
||||
Name: fmt.Sprintf("[%d] exec", i), ArgsSnip: "cmd", Result: "✓ 1.0s",
|
||||
})
|
||||
}
|
||||
errEntry := toolLogEntry{
|
||||
Name: "[3] exec", ArgsSnip: "pytest", Result: "✗ 2.0s",
|
||||
ErrDetail: "FAILED test\nExit code: 1",
|
||||
}
|
||||
errEntry := toolLogEntry{Name: "[3] exec", ArgsSnip: "pytest", Result: "✗ 2.0s",
|
||||
ErrDetail: "FAILED test\nExit code: 1"}
|
||||
task5err.lastError = &errEntry
|
||||
lines5err := countLines(buildRichStatus(task5err, true, "/ws/p"))
|
||||
|
||||
|
|
|
|||
|
|
@ -10,19 +10,16 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
|
||||
func (h *Handler) apiSkills(w http.ResponseWriter, r *http.Request) {
|
||||
skillsList := h.provider.ListSkills()
|
||||
writeJSON(w, skillsList)
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) apiPlan(w http.ResponseWriter, r *http.Request) {
|
||||
info := h.provider.GetPlanInfo()
|
||||
writeJSON(w, info)
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) apiSessions(w http.ResponseWriter, r *http.Request) {
|
||||
sessions := h.provider.GetActiveSessions()
|
||||
if sessions == nil {
|
||||
|
|
@ -31,7 +28,6 @@ func (h *Handler) apiSessions(w http.ResponseWriter, r *http.Request) {
|
|||
writeJSON(w, sessions)
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) apiSession(w http.ResponseWriter, r *http.Request) {
|
||||
s := h.provider.GetSessionStats()
|
||||
if s == nil {
|
||||
|
|
@ -41,17 +37,14 @@ func (h *Handler) apiSession(w http.ResponseWriter, r *http.Request) {
|
|||
writeJSON(w, s)
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) apiContext(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, h.provider.GetContextInfo())
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) apiPrompt(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, map[string]string{"prompt": h.provider.GetSystemPrompt()})
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) apiGit(w http.ResponseWriter, r *http.Request) {
|
||||
repo := r.URL.Query().Get("repo")
|
||||
if repo == "" {
|
||||
|
|
@ -61,7 +54,6 @@ func (h *Handler) apiGit(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) apiCommand(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed)
|
||||
|
|
@ -99,7 +91,6 @@ func (h *Handler) apiCommand(w http.ResponseWriter, r *http.Request) {
|
|||
writeJSON(w, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) apiEvents(w http.ResponseWriter, r *http.Request) {
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
|
|
@ -148,7 +139,6 @@ func (h *Handler) apiEvents(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func sendSSEIfChanged(w http.ResponseWriter, f http.Flusher, event string, v any, last *[]byte) {
|
||||
data, _ := json.Marshal(v)
|
||||
if !bytes.Equal(data, *last) {
|
||||
|
|
@ -158,11 +148,9 @@ func sendSSEIfChanged(w http.ResponseWriter, f http.Flusher, event string, v any
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func writeJSON(w http.ResponseWriter, v any) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(v)
|
||||
}
|
||||
|
||||
// apiDevConsole receives console output from dev preview iframes.
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import (
|
|||
"github.com/sipeed/picoclaw/pkg/logger"
|
||||
)
|
||||
|
||||
|
||||
// validateLocalhostURL parses and validates that a URL targets localhost.
|
||||
func validateLocalhostURL(target string) (*url.URL, error) {
|
||||
u, err := url.Parse(target)
|
||||
|
|
@ -33,7 +32,6 @@ func validateLocalhostURL(target string) (*url.URL, error) {
|
|||
|
||||
// RegisterDevTarget registers a new dev server target. Only localhost targets are allowed.
|
||||
|
||||
|
||||
// RegisterDevTarget registers a new dev server target. Only localhost targets are allowed.
|
||||
func (h *Handler) RegisterDevTarget(name, target string) (string, error) {
|
||||
if _, err := validateLocalhostURL(target); err != nil {
|
||||
|
|
@ -55,7 +53,6 @@ func (h *Handler) RegisterDevTarget(name, target string) (string, error) {
|
|||
|
||||
// UnregisterDevTarget removes a registered target. If it was active, the proxy is disabled.
|
||||
|
||||
|
||||
// UnregisterDevTarget removes a registered target. If it was active, the proxy is disabled.
|
||||
func (h *Handler) UnregisterDevTarget(id string) error {
|
||||
h.devMu.Lock()
|
||||
|
|
@ -79,7 +76,6 @@ func (h *Handler) UnregisterDevTarget(id string) error {
|
|||
|
||||
// ActivateDevTarget sets the reverse proxy to the registered target with the given ID.
|
||||
|
||||
|
||||
// ActivateDevTarget sets the reverse proxy to the registered target with the given ID.
|
||||
func (h *Handler) ActivateDevTarget(id string) error {
|
||||
h.devMu.Lock()
|
||||
|
|
@ -148,7 +144,6 @@ p{color:#8e8e93;font-size:14px;margin:0}
|
|||
|
||||
// DeactivateDevTarget disables the reverse proxy without removing registrations.
|
||||
|
||||
|
||||
// DeactivateDevTarget disables the reverse proxy without removing registrations.
|
||||
func (h *Handler) DeactivateDevTarget() error {
|
||||
h.devMu.Lock()
|
||||
|
|
@ -165,7 +160,6 @@ func (h *Handler) DeactivateDevTarget() error {
|
|||
|
||||
// GetDevTarget returns the current dev proxy target URL, or empty string if disabled.
|
||||
|
||||
|
||||
// GetDevTarget returns the current dev proxy target URL, or empty string if disabled.
|
||||
func (h *Handler) GetDevTarget() string {
|
||||
h.devMu.RLock()
|
||||
|
|
@ -178,7 +172,6 @@ func (h *Handler) GetDevTarget() string {
|
|||
|
||||
// ListDevTargets returns all registered dev targets.
|
||||
|
||||
|
||||
// ListDevTargets returns all registered dev targets.
|
||||
func (h *Handler) ListDevTargets() []DevTarget {
|
||||
h.devMu.RLock()
|
||||
|
|
@ -198,7 +191,6 @@ func (h *Handler) ListDevTargets() []DevTarget {
|
|||
// "/api/items" are prefixed with "/miniapp/dev", matching the reverse proxy mount.
|
||||
// It also captures console.log/warn/error/info and forwards them to the server.
|
||||
|
||||
|
||||
// devProxyScript is the JavaScript injected into HTML responses from the dev proxy.
|
||||
// It rewrites fetch() and XMLHttpRequest.open() so that absolute paths like
|
||||
// "/api/items" are prefixed with "/miniapp/dev", matching the reverse proxy mount.
|
||||
|
|
@ -255,7 +247,6 @@ const devProxyScript = `<script data-dev-proxy>
|
|||
// injectDevProxyScript inserts the dev proxy rewrite script into an HTML document.
|
||||
// Insertion priority: before </head>, after <body...>, or prepend to document.
|
||||
|
||||
|
||||
// injectDevProxyScript inserts the dev proxy rewrite script into an HTML document.
|
||||
// Insertion priority: before </head>, after <body...>, or prepend to document.
|
||||
func injectDevProxyScript(html []byte) []byte {
|
||||
|
|
@ -294,7 +285,6 @@ func injectDevProxyScript(html []byte) []byte {
|
|||
|
||||
// escapeHTMLString escapes HTML special characters in a string.
|
||||
|
||||
|
||||
// escapeHTMLString escapes HTML special characters in a string.
|
||||
func escapeHTMLString(s string) string {
|
||||
s = strings.ReplaceAll(s, "&", "&")
|
||||
|
|
@ -306,7 +296,6 @@ func escapeHTMLString(s string) string {
|
|||
|
||||
// RegisterRoutes registers Mini App routes on the given mux.
|
||||
|
||||
|
||||
func (h *Handler) apiDev(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
|
|
@ -359,7 +348,6 @@ func (h *Handler) apiDev(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func (h *Handler) serveDevProxy(w http.ResponseWriter, r *http.Request) {
|
||||
h.devMu.RLock()
|
||||
proxy := h.devProxy
|
||||
|
|
@ -381,7 +369,6 @@ func (h *Handler) serveDevProxy(w http.ResponseWriter, r *http.Request) {
|
|||
// extractUserFromInitData parses user.id from the initData query string.
|
||||
// initData contains a "user" param with JSON like {"id":123456,...}.
|
||||
|
||||
|
||||
func (h *Handler) devStatus() map[string]any {
|
||||
h.devMu.RLock()
|
||||
defer h.devMu.RUnlock()
|
||||
|
|
@ -406,7 +393,6 @@ func (h *Handler) devStatus() map[string]any {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// apiDevConsole receives console output from dev preview iframes.
|
||||
func (h *Handler) apiDevConsole(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
|
|
@ -474,4 +460,3 @@ func (h *Handler) apiDevConsole(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// wsLogs serves a WebSocket endpoint that streams log entries in real time.
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/sipeed/picoclaw/pkg/logger"
|
||||
)
|
||||
|
||||
|
||||
// apiLogsSnapshot creates a tar.gz snapshot of the current log buffer.
|
||||
func (h *Handler) apiLogsSnapshot(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
|
|
@ -86,7 +85,6 @@ func (h *Handler) apiLogsSnapshot(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// apiLogsSnapshotDownload serves a snapshot tar.gz file.
|
||||
|
||||
|
||||
// apiLogsSnapshotDownload serves a snapshot tar.gz file.
|
||||
func (h *Handler) apiLogsSnapshotDownload(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
|
|
@ -117,7 +115,6 @@ func (h *Handler) apiLogsSnapshotDownload(w http.ResponseWriter, r *http.Request
|
|||
|
||||
// cleanOldSnapshots removes snapshot files older than maxAge.
|
||||
|
||||
|
||||
// cleanOldSnapshots removes snapshot files older than maxAge.
|
||||
func cleanOldSnapshots(dir string, maxAge time.Duration) {
|
||||
entries, err := os.ReadDir(dir)
|
||||
|
|
@ -140,4 +137,3 @@ func cleanOldSnapshots(dir string, maxAge time.Duration) {
|
|||
}
|
||||
|
||||
// initDataMaxAge is the maximum age of initData before it is considered expired.
|
||||
|
||||
|
|
|
|||
|
|
@ -175,24 +175,31 @@ type mockDataProvider struct{}
|
|||
func (m *mockDataProvider) ListSkills() []skills.SkillInfo {
|
||||
return []skills.SkillInfo{{Name: "test-skill", Description: "A test", Source: "local"}}
|
||||
}
|
||||
|
||||
func (m *mockDataProvider) GetPlanInfo() PlanInfo {
|
||||
return PlanInfo{HasPlan: false, Status: "none"}
|
||||
}
|
||||
|
||||
func (m *mockDataProvider) GetSessionStats() *stats.Stats {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockDataProvider) GetActiveSessions() []SessionInfo {
|
||||
return []SessionInfo{}
|
||||
}
|
||||
|
||||
func (m *mockDataProvider) GetGitRepos() []GitRepoSummary {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockDataProvider) GetGitRepoDetail(name string) GitInfo {
|
||||
return GitInfo{Name: name}
|
||||
}
|
||||
|
||||
func (m *mockDataProvider) GetContextInfo() ContextInfo {
|
||||
return ContextInfo{Workspace: "/mock/workspace"}
|
||||
}
|
||||
|
||||
func (m *mockDataProvider) GetSystemPrompt() string {
|
||||
return "mock system prompt"
|
||||
}
|
||||
|
|
@ -464,6 +471,7 @@ type mutatingDataProvider struct {
|
|||
func (m *mutatingDataProvider) ListSkills() []skills.SkillInfo {
|
||||
return []skills.SkillInfo{{Name: "test-skill", Description: "A test", Source: "local"}}
|
||||
}
|
||||
|
||||
func (m *mutatingDataProvider) GetPlanInfo() PlanInfo {
|
||||
if m.mutated.Load() {
|
||||
return PlanInfo{HasPlan: true, Status: "executing", CurrentPhase: 1, TotalPhases: 2}
|
||||
|
|
@ -474,15 +482,19 @@ func (m *mutatingDataProvider) GetSessionStats() *stats.Stats { return nil }
|
|||
func (m *mutatingDataProvider) GetActiveSessions() []SessionInfo {
|
||||
return []SessionInfo{}
|
||||
}
|
||||
|
||||
func (m *mutatingDataProvider) GetGitRepos() []GitRepoSummary {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mutatingDataProvider) GetGitRepoDetail(name string) GitInfo {
|
||||
return GitInfo{Name: name}
|
||||
}
|
||||
|
||||
func (m *mutatingDataProvider) GetContextInfo() ContextInfo {
|
||||
return ContextInfo{Workspace: "/mock/workspace"}
|
||||
}
|
||||
|
||||
func (m *mutatingDataProvider) GetSystemPrompt() string {
|
||||
return "mock system prompt"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/logger"
|
||||
)
|
||||
|
||||
|
||||
const maxWSClients = 4
|
||||
|
||||
const (
|
||||
|
|
@ -22,7 +22,6 @@ type wsClient struct {
|
|||
conn *websocket.Conn
|
||||
}
|
||||
|
||||
|
||||
var wsUpgrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
origin := r.Header.Get("Origin")
|
||||
|
|
@ -43,7 +42,6 @@ var wsUpgrader = websocket.Upgrader{
|
|||
|
||||
// NewHandler creates a new Mini App handler.
|
||||
|
||||
|
||||
// wsLogs serves a WebSocket endpoint that streams log entries in real time.
|
||||
func (h *Handler) wsLogs(w http.ResponseWriter, r *http.Request) {
|
||||
// Parse filter params
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ func (p *Provider) ChatStream(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := p.httpClient.Do(req)
|
||||
resp, err := p.httpClient.Do(req) //nolint:bodyclose // closed in goroutine or error path below
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||
}
|
||||
|
|
@ -626,4 +626,3 @@ type streamToolCallAcc struct {
|
|||
Name string
|
||||
Arguments strings.Builder
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ func findToolCallBlock(text string) (blockStart, blockEnd int, content string, f
|
|||
return 0, 0, "", false
|
||||
}
|
||||
|
||||
// --- XML tool call extraction ---
|
||||
// ExtractXMLToolCalls extracts tool calls from XML-formatted text.
|
||||
//
|
||||
// Expected format:
|
||||
//
|
||||
|
|
@ -195,7 +195,6 @@ func findToolCallBlock(text string) (blockStart, blockEnd int, content string, f
|
|||
// <parameter name="param">value</parameter>
|
||||
// </invoke>
|
||||
// </ns:toolcall>
|
||||
// ExtractXMLToolCalls is the exported version for use by the agent loop.
|
||||
func ExtractXMLToolCalls(text string) []ToolCall {
|
||||
return extractXMLToolCalls(text)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ type Tracker struct {
|
|||
// NewTracker creates a tracker that persists to {workspace}/state/stats.json.
|
||||
func NewTracker(workspace string) *Tracker {
|
||||
stateDir := filepath.Join(workspace, "state")
|
||||
os.MkdirAll(stateDir, 0755)
|
||||
os.MkdirAll(stateDir, 0o755)
|
||||
|
||||
t := &Tracker{
|
||||
stateFile: filepath.Join(stateDir, "stats.json"),
|
||||
|
|
@ -135,7 +135,7 @@ func (t *Tracker) save() {
|
|||
return
|
||||
}
|
||||
tmp := t.stateFile + ".tmp"
|
||||
if err := os.WriteFile(tmp, data, 0644); err != nil {
|
||||
if err := os.WriteFile(tmp, data, 0o644); err != nil {
|
||||
return
|
||||
}
|
||||
if err := os.Rename(tmp, t.stateFile); err != nil {
|
||||
|
|
|
|||
|
|
@ -808,7 +808,7 @@ func isExecutable(path string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
return info.Mode()&0111 != 0
|
||||
return info.Mode()&0o111 != 0
|
||||
}
|
||||
|
||||
func (t *ExecTool) SetTimeout(timeout time.Duration) {
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@ func TestGuardCommand_ExecutableBinaryAllowed(t *testing.T) {
|
|||
|
||||
// Create a fake executable outside the workspace
|
||||
execPath := filepath.Join(externalDir, "mybin")
|
||||
os.WriteFile(execPath, []byte("#!/bin/sh\necho ok"), 0755)
|
||||
os.WriteFile(execPath, []byte("#!/bin/sh\necho ok"), 0o755)
|
||||
|
||||
tool, _ := NewExecTool(workspace, true)
|
||||
|
||||
|
|
@ -393,7 +393,7 @@ func TestGuardCommand_ExecutableBinaryAllowed_Windows(t *testing.T) {
|
|||
|
||||
// Create a fake .exe outside the workspace
|
||||
execPath := filepath.Join(externalDir, "tool.exe")
|
||||
os.WriteFile(execPath, []byte("MZ"), 0644)
|
||||
os.WriteFile(execPath, []byte("MZ"), 0o644)
|
||||
|
||||
tool, _ := NewExecTool(workspace, true)
|
||||
|
||||
|
|
@ -416,7 +416,7 @@ func TestGuardCommand_NonExecutableOutsideBlocked(t *testing.T) {
|
|||
|
||||
// Create a regular (non-executable) file outside workspace
|
||||
dataFile := filepath.Join(externalDir, "secret.txt")
|
||||
os.WriteFile(dataFile, []byte("secret data"), 0644)
|
||||
os.WriteFile(dataFile, []byte("secret data"), 0o644)
|
||||
|
||||
tool, _ := NewExecTool(workspace, true)
|
||||
|
||||
|
|
@ -477,7 +477,7 @@ func TestGuardCommand_AbsolutePathInsideWorkspace(t *testing.T) {
|
|||
tool, _ := NewExecTool(workspace, true)
|
||||
|
||||
innerDir := filepath.Join(workspace, "projects", "myapp")
|
||||
os.MkdirAll(innerDir, 0755)
|
||||
os.MkdirAll(innerDir, 0o755)
|
||||
|
||||
cmd := "ls " + innerDir
|
||||
result := tool.guardCommand(cmd, workspace)
|
||||
|
|
@ -514,7 +514,7 @@ func TestGuardCommand_PathTraversal(t *testing.T) {
|
|||
func TestGuardCommand_CdWithAbsoluteWorkspacePath(t *testing.T) {
|
||||
workspace := t.TempDir()
|
||||
innerDir := filepath.Join(workspace, "projects", "foo")
|
||||
os.MkdirAll(innerDir, 0755)
|
||||
os.MkdirAll(innerDir, 0o755)
|
||||
|
||||
tool, _ := NewExecTool(workspace, true)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ func (r *reporterSpy) ReportStateChange(id, state, tool string) {
|
|||
r.calls = append(r.calls, spyCall{state, tool})
|
||||
r.mu.Unlock()
|
||||
}
|
||||
|
||||
func (r *reporterSpy) snapshot() []spyCall {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
|
@ -77,6 +78,7 @@ func (t *echoTool) Description() string { return "echo" }
|
|||
func (t *echoTool) Parameters() map[string]any {
|
||||
return map[string]any{"type": "object", "properties": map[string]any{}}
|
||||
}
|
||||
|
||||
func (t *echoTool) Execute(_ context.Context, _ map[string]any) *ToolResult {
|
||||
return &ToolResult{ForLLM: "echoed"}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type workspaceOverrideKey struct{}
|
||||
type overrideFsKey struct{}
|
||||
type (
|
||||
workspaceOverrideKey struct{}
|
||||
overrideFsKey struct{}
|
||||
)
|
||||
|
||||
// WithWorkspaceOverride returns a context carrying a workspace override path
|
||||
// and a pre-built sandboxFs for that workspace. Tools will resolve file
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ var (
|
|||
|
||||
// IsAudioFile checks if a file is an audio file based on its filename extension and content type.
|
||||
func IsAudioFile(filename, contentType string) bool {
|
||||
|
||||
for _, ext := range audioExtensions {
|
||||
if strings.HasSuffix(strings.ToLower(filename), ext) {
|
||||
return true
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue