Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

154 lines
5.0 KiB
Go

package agentcontext
import (
"context"
agentservice "github.com/tutti-os/tutti/services/tuttid/service/agent"
cliservice "github.com/tutti-os/tutti/services/tuttid/service/cli"
"github.com/tutti-os/tutti/services/tuttid/service/cli/framework"
)
type composerOptionsInput struct {
AgentID string `cli:"agent-id" advertise-required:"true" hint:"Use agent list --json to discover available agents."`
Cwd string `cli:"cwd"`
Locale string `cli:"locale"`
Model string `cli:"model"`
PermissionMode string `cli:"permission-mode"`
Provider string `cli:"provider" hidden:"true"`
ReasoningEffort string `cli:"reasoning-effort"`
}
type composerOptionsResult struct {
AgentTargetID string
Legacy bool
Options agentservice.ComposerOptions
}
func (p Provider) newComposerOptionsCommand() cliservice.Command {
return framework.Register(framework.CommandSpec[composerOptionsInput]{
ID: appID + ".agent.composer-options",
Path: []string{"agent", "composer-options"},
Summary: "Get agent composer options",
Description: "Get model, reasoning, and permission options for one agent without starting a session. Some runtimes may spin up a hidden discovery session.",
Kind: framework.KindGet,
Workspace: framework.WorkspaceOptional,
Inputs: framework.FromStruct[composerOptionsInput](),
Output: framework.OutputSpec{
DefaultMode: cliservice.OutputModeJSON,
DefaultView: framework.ViewDetail,
JSON: true,
JSONViews: map[framework.OutputView]func(any) map[string]any{
framework.ViewDetail: func(result any) map[string]any {
return composerOptionsValue(result.(composerOptionsResult))
},
},
},
Run: p.runComposerOptions,
})
}
func (p Provider) runComposerOptions(ctx context.Context, invoke framework.InvokeContext, input composerOptionsInput) (any, error) {
if err := p.requireSessions(); err != nil {
return nil, err
}
target, legacy, err := p.resolveAgentSelector(ctx, input.AgentID, input.Provider)
if err != nil {
return nil, err
}
canonicalProvider := target.Provider
locale := input.Locale
if locale == "" {
locale = p.composerDefaultLocale(ctx)
}
// The app-facing composer facade does not return CapabilityCatalog. Keep
// discovery off here so a catalog scan is never paid for and discarded.
includeCapabilityCatalog := false
options, err := p.sessions.GetComposerOptions(ctx, agentservice.ComposerOptionsInput{
AgentTargetID: target.ID,
Cwd: input.Cwd,
Locale: locale,
Provider: canonicalProvider,
WorkspaceID: invoke.WorkspaceID,
IncludeCapabilityCatalog: &includeCapabilityCatalog,
Settings: agentservice.ComposerSettings{
Model: input.Model,
PermissionModeID: input.PermissionMode,
ReasoningEffort: input.ReasoningEffort,
},
})
if err != nil {
return nil, err
}
return composerOptionsResult{AgentTargetID: target.ID, Legacy: legacy, Options: options}, nil
}
func (p Provider) composerDefaultLocale(ctx context.Context) string {
if p.preferences == nil {
return ""
}
preferences, err := p.preferences.Get(ctx)
if err != nil {
return ""
}
return preferences.Locale
}
func composerOptionsValue(result composerOptionsResult) map[string]any {
options := result.Options
value := map[string]any{
"schemaVersion": 2,
"agentTargetId": result.AgentTargetID,
"provider": options.Provider,
"effectiveSettings": agentservice.ComposerSettingsToMap(options.EffectiveSettings),
"modelConfig": composerConfigOptionValue(options.ModelConfig),
"permissionConfig": permissionConfigValue(options.PermissionConfig),
"reasoningConfig": composerConfigOptionValue(options.ReasoningConfig),
"speedConfig": composerConfigOptionValue(options.SpeedConfig),
}
if result.Legacy {
value["schemaVersion"] = 1
delete(value, "agentTargetId")
}
return value
}
func permissionConfigValue(config agentservice.PermissionConfig) map[string]any {
modes := make([]any, 0, len(config.Modes))
for _, mode := range config.Modes {
value := map[string]any{
"id": mode.ID,
"description": mode.Description,
"label": mode.Label,
"semantic": string(mode.Semantic),
}
modes = append(modes, value)
}
return map[string]any{
"configurable": config.Configurable,
"defaultValue": config.DefaultValue,
"modes": modes,
}
}
func composerConfigOptionValue(config agentservice.ComposerConfigOption) map[string]any {
options := make([]any, 0, len(config.Options))
for _, option := range config.Options {
value := map[string]any{
"id": option.ID,
"value": option.Value,
"label": option.Label,
"description": option.Description,
}
if option.SupportsImageInput != nil {
value["supportsImageInput"] = *option.SupportsImageInput
}
options = append(options, value)
}
return map[string]any{
"configurable": config.Configurable,
"currentValue": config.CurrentValue,
"defaultValue": config.DefaultValue,
"options": options,
}
}