Repository navigation
Expand file tree
/
Copy pathworkspace.go
More file actions
86 lines (81 loc) · 3.08 KB
/
Copy pathworkspace.go
File metadata and controls
86 lines (81 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package mcode
import (
"fmt"
"maps"
"os"
"path/filepath"
"runtime"
"slices"
"github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/localworkspace"
"github.com/MiniMax-AI/OpenAgentCore/internal/agentdaemon/proto"
)
// WorkspaceConfig is frozen deployment input, separate from public Agent options.
type WorkspaceConfig struct {
Binary, Node, Companion, Directory string
}
func ConfigureLocal(binary, node, companion, workspace string) (WorkspaceConfig, error) {
c := WorkspaceConfig{Binary: binary, Node: node, Companion: companion, Directory: workspace}
if runtime.GOOS == "windows" {
return c, fmt.Errorf("mcode: native execution requires Linux or macOS")
}
for _, path := range []string{binary, node, companion, workspace} {
if !filepath.IsAbs(path) || filepath.Clean(path) != path || path == "/" {
return c, fmt.Errorf("mcode: canonical absolute deployment paths are required")
}
}
for _, path := range []string{binary, node} {
info, err := os.Stat(path)
if err != nil || !info.Mode().IsRegular() {
return c, fmt.Errorf("mcode: runtime program unavailable")
}
}
bound, err := os.Stat(workspace)
if err != nil || !bound.IsDir() {
return c, fmt.Errorf("mcode: workspace directory unavailable")
}
return c, nil
}
func prepareWorkspaceOptions(runtimeRoot string, c WorkspaceConfig, req proto.PromptRequestPayload) (launchOptions, error) {
if req.LocalEnvironment == nil || req.LocalEnvironment.WorkspaceRoot != c.Directory || req.DisableExecutionEnvironment || req.WorkspaceReadOnly {
return launchOptions{}, fmt.Errorf("mcode: execution does not match the dedicated workspace")
}
values, err := localworkspace.ReadOptionalToolEnvironment()
if err != nil {
return launchOptions{}, err
}
// A disabled web_search control removes web_fetch as well; without the control the native default applies.
searchDisabled := req.ExecutionControls != nil && req.ExecutionControls.WebSearch != nil && req.ExecutionControls.WebSearch.Mode == "disabled"
profile := &workspaceProfile{WebFetch: !searchDisabled}
for _, key := range slices.Sorted(maps.Keys(values)) {
profile.ToolEnv = append(profile.ToolEnv, key+"="+values[key])
}
// Reuse public option validation and private Session state provisioning.
// The native process runs in the declared workspace.
private := req
private.LocalEnvironment, private.DisableExecutionEnvironment = nil, true
opts, err := prepareOptions(runtimeRoot, private, profile)
if err != nil {
return opts, err
}
opts.Dir = c.Directory
if len(req.LocalEnvironment.Skills) > 0 {
root := filepath.Join(opts.DataDir, "skills")
if err := os.MkdirAll(root, 0700); err != nil {
return opts, err
}
for _, skill := range req.LocalEnvironment.Skills {
link, target := filepath.Join(root, skill.Metadata.Name), localworkspace.SkillPath(skill)
actual, err := os.Readlink(link)
if err == nil {
if actual != target {
return opts, fmt.Errorf("mcode: unexpected native Skill root")
}
} else if !os.IsNotExist(err) {
return opts, err
} else if err := os.Symlink(target, link); err != nil {
return opts, err
}
}
}
return opts, nil
}