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

180 lines
6.3 KiB
Go

package managedmodels
import (
"context"
"fmt"
"strings"
"time"
cliservice "github.com/tutti-os/tutti/services/tuttid/service/cli"
managedcredentialsservice "github.com/tutti-os/tutti/services/tuttid/service/managedcredentials"
)
const providerID = "managed-model"
const (
commandGrantExchange = providerID + ".grant.exchange"
commandModels = providerID + ".models"
commandCredential = providerID + ".credential"
commandRevoke = providerID + ".revoke"
)
type Provider struct {
service *managedcredentialsservice.Service
}
func NewProvider(service *managedcredentialsservice.Service) Provider {
return Provider{service: service}
}
func (Provider) AppID() string {
return providerID
}
func (p Provider) Commands() []cliservice.Command {
return []cliservice.Command{
p.newExchangeCommand(),
p.newModelsCommand(),
p.newCredentialCommand(),
p.newRevokeCommand(),
}
}
func (p Provider) newExchangeCommand() cliservice.Command {
return p.command(commandGrantExchange, []string{"managed-model", "grant", "exchange"}, "Exchange a managed-model grant", []string{"contextToken", "grantCode", "nonce", "state"}, p.exchange)
}
func (p Provider) newModelsCommand() cliservice.Command {
return p.command(commandModels, []string{"managed-model", "models"}, "List managed-model grant models", []string{"grantRef"}, p.models)
}
func (p Provider) newCredentialCommand() cliservice.Command {
return p.command(commandCredential, []string{"managed-model", "credential"}, "Lease a managed-model provider credential", []string{"grantRef", "provider", "model", "capability"}, p.credential)
}
func (p Provider) newRevokeCommand() cliservice.Command {
return p.command(commandRevoke, []string{"managed-model", "revoke"}, "Revoke a managed-model grant", []string{"grantRef"}, p.revoke)
}
func (p Provider) command(id string, path []string, summary string, required []string, run func(context.Context, cliservice.InvokeRequest) (map[string]any, error)) cliservice.Command {
properties := map[string]any{}
for _, name := range required {
properties[name] = map[string]any{"type": "string"}
}
return cliservice.Command{
Capability: cliservice.Capability{
ID: id,
Path: path,
Summary: summary,
Description: summary + ". This integration command is available only from a workspace app CLI context.",
Visibility: cliservice.CapabilityVisibilityIntegration,
InputSchema: map[string]any{"type": "object", "required": required, "properties": properties},
Output: cliservice.CapabilityOutput{
DefaultMode: cliservice.OutputModeJSON,
JSON: true,
},
},
Handler: func(ctx context.Context, request cliservice.InvokeRequest) (cliservice.CommandOutput, error) {
if p.service == nil {
return cliservice.CommandOutput{}, cliservice.ServiceUnavailableError("managed_model_service_unavailable", fmt.Errorf("managed model service is unavailable"))
}
if err := requireExactInput(request.Input, required); err != nil {
return cliservice.CommandOutput{}, err
}
if err := requireAppContext(request.Context); err != nil {
return cliservice.CommandOutput{}, err
}
value, err := run(ctx, request)
if err != nil {
return cliservice.CommandOutput{}, err
}
return cliservice.CommandOutput{Kind: cliservice.OutputModeJSON, Value: value}, nil
},
}
}
func (p Provider) exchange(ctx context.Context, request cliservice.InvokeRequest) (map[string]any, error) {
result, err := p.service.Exchange(ctx, managedcredentialsservice.ExchangeInput{
AppID: request.Context.AppID,
ContextToken: request.Input["contextToken"].(string),
GrantCode: request.Input["grantCode"].(string),
Nonce: request.Input["nonce"].(string),
State: request.Input["state"].(string),
WorkspaceID: request.Context.WorkspaceID,
})
if err != nil {
return nil, err
}
return map[string]any{
"expiresAt": formatTime(result.ExpiresAt),
"grantRef": result.GrantRef,
"models": result.Models,
"providers": result.Providers,
}, nil
}
func (p Provider) models(ctx context.Context, request cliservice.InvokeRequest) (map[string]any, error) {
result, err := p.service.ListGrantModels(ctx, request.Context.WorkspaceID, request.Context.AppID, request.Input["grantRef"].(string))
if err != nil {
return nil, err
}
return map[string]any{"expiresAt": formatTime(result.ExpiresAt), "models": result.Models}, nil
}
func (p Provider) credential(ctx context.Context, request cliservice.InvokeRequest) (map[string]any, error) {
result, err := p.service.Credential(ctx, managedcredentialsservice.CredentialInput{
AppID: request.Context.AppID,
Capability: request.Input["capability"].(string),
GrantRef: request.Input["grantRef"].(string),
Model: request.Input["model"].(string),
Provider: request.Input["provider"].(string),
WorkspaceID: request.Context.WorkspaceID,
})
if err != nil {
return nil, err
}
return map[string]any{
"credential": result.Credential,
"expiresAt": formatTime(result.ExpiresAt),
"models": result.GrantModels,
}, nil
}
func (p Provider) revoke(ctx context.Context, request cliservice.InvokeRequest) (map[string]any, error) {
if err := p.service.Revoke(ctx, request.Context.WorkspaceID, request.Context.AppID, request.Input["grantRef"].(string)); err != nil {
return nil, err
}
return map[string]any{"ok": true}, nil
}
func requireAppContext(context cliservice.InvokeContext) error {
if strings.TrimSpace(context.WorkspaceID) == "" || strings.TrimSpace(context.AppID) == "" {
return fmt.Errorf("%w: managed-model commands require workspace and app context", cliservice.ErrInvalidInput)
}
return nil
}
func requireExactInput(input map[string]any, required []string) error {
if input == nil {
return fmt.Errorf("%w: command input is required", cliservice.ErrInvalidInput)
}
allowed := make(map[string]struct{}, len(required))
for _, name := range required {
allowed[name] = struct{}{}
value, ok := input[name].(string)
if !ok || strings.TrimSpace(value) == "" {
return fmt.Errorf("%w: %s is required", cliservice.ErrInvalidInput, name)
}
}
for name := range input {
if _, ok := allowed[name]; !ok {
return fmt.Errorf("%w: %s is not supported", cliservice.ErrInvalidInput, name)
}
}
return nil
}
func formatTime(value time.Time) string {
return value.UTC().Format(time.RFC3339)
}