mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 09:28:14 +00:00
refactor: P0-P3 fixes, C1 cleanup, architecture diagrams, go.work upgrade
- P0-1: ProviderError type + ReportStatus for precise 401/403 detection - P0-2: Remove -config flag from deploy/homeagent.service - P2-1: 5s debounce on context.go Save() - P2-2→C1: Delete output_set_channel entirely - P2-3: Extract mediaDataURL/mediaChat helpers - P2-4: Dedup defaultSources var - P3: Delete dead packages (embed/tokenizer/container/snapshot) - P3: Delete dead functions (messagesToMap, RunStageAll) - CL: Update .gitignore, docs, Makefile, gojieba removal - Config: Delete config/config.yaml, update docs - Arch: Remove EmitOutputTo from emitResponse - CL-1: go.work 1.19→1.21 - Docs: Add Mermaid architecture diagrams to README - Docs: Add kernel-rebuild requires plugin-rebuild note to PLUGIN_DEV.md
This commit is contained in:
@ -12,6 +12,34 @@ import (
|
||||
sdk "gitcode.com/JianFeeeee/HomeAgent/internal/sdk"
|
||||
)
|
||||
|
||||
// shellUnquote 拆解命令字符串,处理单引号/双引号包裹的参数
|
||||
func shellUnquote(s string) []string {
|
||||
var args []string
|
||||
var cur strings.Builder
|
||||
inSingle := false
|
||||
inDouble := false
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
switch {
|
||||
case c == '\'' && !inDouble:
|
||||
inSingle = !inSingle
|
||||
case c == '"' && !inSingle:
|
||||
inDouble = !inDouble
|
||||
case (c == ' ' || c == '\t') && !inSingle && !inDouble:
|
||||
if cur.Len() > 0 {
|
||||
args = append(args, cur.String())
|
||||
cur.Reset()
|
||||
}
|
||||
default:
|
||||
cur.WriteByte(c)
|
||||
}
|
||||
}
|
||||
if cur.Len() > 0 {
|
||||
args = append(args, cur.String())
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func init() {
|
||||
plugin.RegisterFactory("cmd", func(name string, config map[string]interface{}) (sdk.Plugin, error) {
|
||||
return New(name), nil
|
||||
@ -79,7 +107,11 @@ func (p *Plugin) Start(s *sdk.PluginSDK) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
cmd := exec.CommandContext(ctx, "sh", "-c", command)
|
||||
parts := shellUnquote(command)
|
||||
if len(parts) == 0 {
|
||||
return map[string]interface{}{"error": "command is required"}, nil
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, parts[0], parts[1:]...)
|
||||
if workdir != "" {
|
||||
cmd.Dir = workdir
|
||||
}
|
||||
|
||||
@ -81,8 +81,9 @@ func TestCmdRunWithStderr(t *testing.T) {
|
||||
}
|
||||
|
||||
handler := tc.handlers["cmd_run"]
|
||||
// ls with a nonexistent path writes to stderr and returns non-zero exit code
|
||||
result, err := handler(map[string]interface{}{
|
||||
"command": "echo out && echo err >&2 && exit 1",
|
||||
"command": "ls /tmp/cmd_test_nonexistent_xxxxx",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -95,14 +96,11 @@ func TestCmdRunWithStderr(t *testing.T) {
|
||||
if resp["status"] != "ok" {
|
||||
t.Fatalf("expected status ok, got %v", resp["status"])
|
||||
}
|
||||
if resp["stdout"] != "out" {
|
||||
t.Fatalf("expected stdout 'out', got %v", resp["stdout"])
|
||||
if stderr, ok := resp["stderr"].(string); !ok || stderr == "" {
|
||||
t.Fatalf("expected stderr output, got %q", stderr)
|
||||
}
|
||||
if resp["stderr"] != "err" {
|
||||
t.Fatalf("expected stderr 'err', got %v", resp["stderr"])
|
||||
}
|
||||
if resp["exit_code"].(float64) != 1 {
|
||||
t.Fatalf("expected exit code 1, got %v", resp["exit_code"])
|
||||
if exitCode, ok := resp["exit_code"].(float64); !ok || exitCode == 0 {
|
||||
t.Fatalf("expected non-zero exit code, got %v", exitCode)
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +195,7 @@ func TestCmdRunNonZeroExit(t *testing.T) {
|
||||
|
||||
handler := tc.handlers["cmd_run"]
|
||||
result, err := handler(map[string]interface{}{
|
||||
"command": "exit 42",
|
||||
"command": "false",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -210,8 +208,8 @@ func TestCmdRunNonZeroExit(t *testing.T) {
|
||||
if resp["status"] != "ok" {
|
||||
t.Fatalf("expected status ok, got %v", resp["status"])
|
||||
}
|
||||
if resp["exit_code"].(float64) != 42 {
|
||||
t.Fatalf("expected exit code 42, got %v", resp["exit_code"])
|
||||
if resp["exit_code"].(float64) != 1 {
|
||||
t.Fatalf("expected exit code 1, got %v", resp["exit_code"])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user