mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-08 17:36:45 +08:00
* feat: add live run supplements (MUL-7565) Co-authored-by: multica-agent <[email protected]> * fix: address MUL-7565 review feedback Co-authored-by: multica-agent <[email protected]> * fix: resolve MUL-7565 supplement panel and receipt review Co-authored-by: multica-agent <[email protected]> * refactor: remove MUL-7565 supplement ordinals Co-authored-by: multica-agent <[email protected]> * fix: close supplement composer after run remount * fix: exclude task supplements from completion reconciliation * fix: build a persistent binary for local daemon launches * feat: support Claude task supplements through SDK hooks * refactor: simplify task supplement delivery * test: remove redundant task supplement coverage * fix: remove redundant supplement delivery notices * refactor: extract local daemon launcher fix to its own PR * fix: preserve ordinary comment size compatibility * fix: accept empty task start acknowledgements * fix: bound task start response decoding and retries --------- Co-authored-by: Forge-Boy <[email protected]> Co-authored-by: multica-agent <[email protected]> Co-authored-by: yushen <[email protected]>
87 lines
3.6 KiB
Go
87 lines
3.6 KiB
Go
package daemon
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"reflect"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// A test-created Grok ACP process carries provider cost through the real
|
|
// backend and runTask conversion, without an installed CLI or model account.
|
|
const taskUsageGrokFixture = `#!/bin/sh
|
|
case "$*" in *--version*) echo '1.0.0'; exit 0;; esac
|
|
while IFS= read -r line; do
|
|
id=$(printf '%s' "$line" | sed -n 's/.*"id":\([0-9]*\).*/\1/p')
|
|
case "$line" in
|
|
*'"method":"initialize"'*)
|
|
printf '{"jsonrpc":"2.0","id":%s,"result":{"protocolVersion":1,"authMethods":[{"id":"cached_token","name":"Test authentication"}],"agentCapabilities":{"mcpCapabilities":{"http":true,"sse":true}}}}\n' "$id";;
|
|
*'"method":"session/new"'*)
|
|
printf '{"jsonrpc":"2.0","id":%s,"result":{"sessionId":"test-session","models":{"currentModelId":"grok-4.6","availableModels":[{"modelId":"grok-4.6","name":"Test model"}]}}}\n' "$id";;
|
|
*'"method":"session/prompt"'*)
|
|
printf '%s\n' '{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"test-session","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"done"}}}}'
|
|
printf '{"jsonrpc":"2.0","id":%s,"result":{"stopReason":"end_turn","_meta":{"modelId":"grok-4.6","usage":{"inputTokens":FIXTURE_INPUT,"costUsdTicks":FIXTURE_COST}}}}\n' "$id";;
|
|
*) if [ -n "$id" ]; then printf '{"jsonrpc":"2.0","id":%s,"result":{}}\n' "$id"; fi;;
|
|
esac
|
|
done
|
|
`
|
|
|
|
func TestRunTaskPreservesProviderCostWithoutTokens(t *testing.T) {
|
|
if runtime.GOOS == "windows" {
|
|
t.Skip("shell-script agent fixture is POSIX-only")
|
|
}
|
|
for _, tc := range []struct {
|
|
name string
|
|
input, cost int64
|
|
want []TaskUsageEntry
|
|
}{
|
|
{"cost_only", 0, 100000000, []TaskUsageEntry{{Provider: "grok", Model: "grok-4.6", CostUSDTicks: 100000000}}},
|
|
{"tokens_and_cost", 10, 100000000, []TaskUsageEntry{{Provider: "grok", Model: "grok-4.6", InputTokens: 10, CostUSDTicks: 100000000}}},
|
|
{"tokens_only", 10, 0, []TaskUsageEntry{{Provider: "grok", Model: "grok-4.6", InputTokens: 10}}},
|
|
{"empty", 0, 0, nil},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
|
fake := filepath.Join(t.TempDir(), "grok-fixture")
|
|
script := strings.NewReplacer("FIXTURE_INPUT", fmt.Sprint(tc.input), "FIXTURE_COST", fmt.Sprint(tc.cost)).Replace(taskUsageGrokFixture)
|
|
writeTestExecutable(t, fake, []byte(script))
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
_, _ = w.Write([]byte(`{}`))
|
|
}))
|
|
defer srv.Close()
|
|
d := &Daemon{
|
|
client: NewClient(srv.URL), logger: logger,
|
|
workspaces: make(map[string]*workspaceState), activeEnvRoots: make(map[string]int),
|
|
runtimeIndex: map[string]Runtime{"test-rt": {ID: "test-rt", Provider: "grok"}},
|
|
cfg: Config{
|
|
WorkspacesRoot: t.TempDir(), AgentTimeout: 5 * time.Second, ServerBaseURL: srv.URL,
|
|
Agents: map[string]AgentEntry{"grok": {Path: fake}},
|
|
},
|
|
}
|
|
task := Task{
|
|
ID: "test-task", WorkspaceID: "test-ws", RuntimeID: "test-rt", IssueID: "test-issue",
|
|
AgentID: "test-agent", AuthToken: "mat_test_usage",
|
|
Agent: &AgentData{ID: "test-agent", Name: "test", Model: "grok-4.6"},
|
|
}
|
|
result, err := d.runTask(context.Background(), task, "grok", 0, logger)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.Status != "completed" || result.Comment != "done" {
|
|
t.Fatalf("unexpected result: %+v", result)
|
|
}
|
|
if !reflect.DeepEqual(result.Usage, tc.want) {
|
|
t.Fatalf("usage = %+v, want %+v", result.Usage, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|