- Auth commands: login, logout, status - Document commands: create, list, get, update, delete - Project commands: list, get - Folder commands: list, create - Tag commands: list, create, add - Search command - Reasoning save command - JSON output format with --output text option - Viper-based configuration management - Cobra CLI framework
747 lines
18 KiB
Go
747 lines
18 KiB
Go
package cobra
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/claudia/docs-cli/internal/api"
|
|
"github.com/claudia/docs-cli/internal/auth"
|
|
"github.com/claudia/docs-cli/internal/config"
|
|
"github.com/claudia/docs-cli/internal/output"
|
|
"github.com/claudia/docs-cli/pkg/types"
|
|
)
|
|
|
|
var (
|
|
server string
|
|
token string
|
|
outputFormat string
|
|
quiet bool
|
|
verbose bool
|
|
)
|
|
|
|
var rootCmd = &cobra.Command{
|
|
Use: "claudia-docs",
|
|
Short: "Claudia Docs CLI - Interact with Claudia Docs from the command line",
|
|
Long: `Claudia Docs CLI allows you to manage documents, projects, folders, tags, and more.`,
|
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
|
return initConfig()
|
|
},
|
|
}
|
|
|
|
func Execute() error {
|
|
return rootCmd.Execute()
|
|
}
|
|
|
|
func initConfig() error {
|
|
cfg, err := config.Load()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
config.UpdateFromFlags(server, token, outputFormat, quiet, verbose)
|
|
_ = cfg
|
|
return nil
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.PersistentFlags().StringVar(&server, "server", "", "API server URL")
|
|
rootCmd.PersistentFlags().StringVar(&token, "token", "", "JWT token")
|
|
rootCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "json", "Output format: json, text")
|
|
rootCmd.PersistentFlags().BoolVar(&quiet, "quiet", false, "Suppress stdout, only JSON")
|
|
rootCmd.PersistentFlags().BoolVar(&verbose, "verbose", false, "Verbose output")
|
|
|
|
// Auth commands
|
|
rootCmd.AddCommand(authCmd)
|
|
|
|
// Document commands
|
|
rootCmd.AddCommand(docCmd)
|
|
|
|
// Project commands
|
|
rootCmd.AddCommand(projectCmd)
|
|
|
|
// Folder commands
|
|
rootCmd.AddCommand(folderCmd)
|
|
|
|
// Tag commands
|
|
rootCmd.AddCommand(tagCmd)
|
|
|
|
// Search command
|
|
rootCmd.AddCommand(searchCmd)
|
|
|
|
// Reasoning command
|
|
rootCmd.AddCommand(reasoningCmd)
|
|
}
|
|
|
|
// Auth command group
|
|
var authCmd = &cobra.Command{
|
|
Use: "auth",
|
|
Short: "Authentication commands",
|
|
}
|
|
|
|
var authLoginCmd = &cobra.Command{
|
|
Use: "login",
|
|
Short: "Login to Claudia Docs",
|
|
RunE: runAuthLogin,
|
|
}
|
|
|
|
var authLogoutCmd = &cobra.Command{
|
|
Use: "logout",
|
|
Short: "Logout and clear saved token",
|
|
RunE: runAuthLogout,
|
|
}
|
|
|
|
var authStatusCmd = &cobra.Command{
|
|
Use: "status",
|
|
Short: "Show authentication status",
|
|
RunE: runAuthStatus,
|
|
}
|
|
|
|
func init() {
|
|
authCmd.AddCommand(authLoginCmd, authLogoutCmd, authStatusCmd)
|
|
authLoginCmd.Flags().StringP("username", "u", "", "Username (required)")
|
|
authLoginCmd.Flags().StringP("password", "p", "", "Password (required)")
|
|
authLoginCmd.Flags().Bool("save", false, "Save token to config file")
|
|
authLoginCmd.MarkFlagRequired("username")
|
|
authLoginCmd.MarkFlagRequired("password")
|
|
}
|
|
|
|
func runAuthLogin(cmd *cobra.Command, args []string) error {
|
|
username, _ := cmd.Flags().GetString("username")
|
|
password, _ := cmd.Flags().GetString("password")
|
|
save, _ := cmd.Flags().GetBool("save")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
authClient := auth.NewAuthClient(client)
|
|
authResp, err := authClient.Login(username, password)
|
|
if err != nil {
|
|
return printError("Login failed", err)
|
|
}
|
|
|
|
if save {
|
|
if err := config.SaveToken(authResp.Token); err != nil {
|
|
return printError("Failed to save token", err)
|
|
}
|
|
}
|
|
|
|
data := map[string]interface{}{
|
|
"token": authResp.Token,
|
|
"expires_at": authResp.ExpiresAt,
|
|
}
|
|
|
|
printResponse(cmd, data, "auth login")
|
|
return nil
|
|
}
|
|
|
|
func runAuthLogout(cmd *cobra.Command, args []string) error {
|
|
if err := auth.Logout(); err != nil {
|
|
return printError("Logout failed", err)
|
|
}
|
|
printResponse(cmd, map[string]string{"message": "Logged out successfully"}, "auth logout")
|
|
return nil
|
|
}
|
|
|
|
func runAuthStatus(cmd *cobra.Command, args []string) error {
|
|
status, err := auth.Status()
|
|
if err != nil {
|
|
return printError("Status check failed", err)
|
|
}
|
|
printResponse(cmd, status, "auth status")
|
|
return nil
|
|
}
|
|
|
|
// Document command group
|
|
var docCmd = &cobra.Command{
|
|
Use: "doc",
|
|
Short: "Document commands",
|
|
}
|
|
|
|
var docCreateCmd = &cobra.Command{
|
|
Use: "create",
|
|
Short: "Create a new document",
|
|
RunE: runDocCreate,
|
|
}
|
|
|
|
var docListCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "List documents",
|
|
RunE: runDocList,
|
|
}
|
|
|
|
var docGetCmd = &cobra.Command{
|
|
Use: "get",
|
|
Short: "Get a document by ID",
|
|
RunE: runDocGet,
|
|
}
|
|
|
|
var docUpdateCmd = &cobra.Command{
|
|
Use: "update",
|
|
Short: "Update a document",
|
|
RunE: runDocUpdate,
|
|
}
|
|
|
|
var docDeleteCmd = &cobra.Command{
|
|
Use: "delete",
|
|
Short: "Delete a document",
|
|
RunE: runDocDelete,
|
|
}
|
|
|
|
func init() {
|
|
docCmd.AddCommand(docCreateCmd, docListCmd, docGetCmd, docUpdateCmd, docDeleteCmd)
|
|
|
|
docCreateCmd.Flags().StringP("title", "t", "", "Document title (required)")
|
|
docCreateCmd.Flags().StringP("content", "c", "", "Document content")
|
|
docCreateCmd.Flags().StringP("project-id", "p", "", "Project ID (required)")
|
|
docCreateCmd.Flags().StringP("folder-id", "f", "", "Folder ID")
|
|
docCreateCmd.Flags().String("metadata", "", "Extra metadata as JSON")
|
|
docCreateCmd.MarkFlagRequired("title")
|
|
docCreateCmd.MarkFlagRequired("project-id")
|
|
|
|
docListCmd.Flags().StringP("project-id", "p", "", "Filter by project")
|
|
docListCmd.Flags().StringP("folder-id", "f", "", "Filter by folder")
|
|
docListCmd.Flags().Int("limit", 20, "Limit results")
|
|
docListCmd.Flags().Int("offset", 0, "Offset for pagination")
|
|
|
|
docGetCmd.Flags().Bool("include-reasoning", false, "Include reasoning metadata")
|
|
docGetCmd.Flags().Bool("include-tags", false, "Include tags")
|
|
|
|
docUpdateCmd.Flags().StringP("title", "t", "", "New title")
|
|
docUpdateCmd.Flags().StringP("content", "c", "", "New content")
|
|
docUpdateCmd.Flags().StringP("folder-id", "f", "", "Move to folder")
|
|
|
|
docDeleteCmd.Flags().Bool("force", false, "Skip confirmation")
|
|
}
|
|
|
|
func runDocCreate(cmd *cobra.Command, args []string) error {
|
|
title, _ := cmd.Flags().GetString("title")
|
|
content, _ := cmd.Flags().GetString("content")
|
|
projectID, _ := cmd.Flags().GetString("project-id")
|
|
folderID, _ := cmd.Flags().GetString("folder-id")
|
|
metadataJSON, _ := cmd.Flags().GetString("metadata")
|
|
|
|
var metadata map[string]interface{}
|
|
if metadataJSON != "" {
|
|
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
|
|
return printError("Invalid metadata JSON", err)
|
|
}
|
|
}
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
docsClient := api.NewDocumentsClient(client)
|
|
req := types.CreateDocumentRequest{
|
|
Title: title,
|
|
Content: content,
|
|
FolderID: folderID,
|
|
Metadata: metadata,
|
|
}
|
|
|
|
doc, err := docsClient.Create(projectID, req)
|
|
if err != nil {
|
|
return printError("Failed to create document", err)
|
|
}
|
|
|
|
printResponse(cmd, doc, "doc create")
|
|
return nil
|
|
}
|
|
|
|
func runDocList(cmd *cobra.Command, args []string) error {
|
|
projectID, _ := cmd.Flags().GetString("project-id")
|
|
folderID, _ := cmd.Flags().GetString("folder-id")
|
|
limit, _ := cmd.Flags().GetInt("limit")
|
|
offset, _ := cmd.Flags().GetInt("offset")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
docsClient := api.NewDocumentsClient(client)
|
|
docs, err := docsClient.List(projectID, folderID, limit, offset)
|
|
if err != nil {
|
|
return printError("Failed to list documents", err)
|
|
}
|
|
|
|
printResponse(cmd, docs, "doc list")
|
|
return nil
|
|
}
|
|
|
|
func runDocGet(cmd *cobra.Command, args []string) error {
|
|
if len(args) < 1 {
|
|
return fmt.Errorf("document ID required")
|
|
}
|
|
docID := args[0]
|
|
|
|
includeReasoning, _ := cmd.Flags().GetBool("include-reasoning")
|
|
includeTags, _ := cmd.Flags().GetBool("include-tags")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
docsClient := api.NewDocumentsClient(client)
|
|
doc, err := docsClient.Get(docID, includeReasoning, includeTags)
|
|
if err != nil {
|
|
return printError("Failed to get document", err)
|
|
}
|
|
|
|
printResponse(cmd, doc, "doc get")
|
|
return nil
|
|
}
|
|
|
|
func runDocUpdate(cmd *cobra.Command, args []string) error {
|
|
if len(args) < 1 {
|
|
return fmt.Errorf("document ID required")
|
|
}
|
|
docID := args[0]
|
|
|
|
title, _ := cmd.Flags().GetString("title")
|
|
content, _ := cmd.Flags().GetString("content")
|
|
folderID, _ := cmd.Flags().GetString("folder-id")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
docsClient := api.NewDocumentsClient(client)
|
|
req := types.UpdateDocumentRequest{
|
|
Title: title,
|
|
Content: content,
|
|
FolderID: folderID,
|
|
}
|
|
|
|
doc, err := docsClient.Update(docID, req)
|
|
if err != nil {
|
|
return printError("Failed to update document", err)
|
|
}
|
|
|
|
printResponse(cmd, doc, "doc update")
|
|
return nil
|
|
}
|
|
|
|
func runDocDelete(cmd *cobra.Command, args []string) error {
|
|
if len(args) < 1 {
|
|
return fmt.Errorf("document ID required")
|
|
}
|
|
docID := args[0]
|
|
|
|
force, _ := cmd.Flags().GetBool("force")
|
|
if !force {
|
|
fmt.Printf("Are you sure you want to delete document %s? (y/N): ", docID)
|
|
var confirm string
|
|
fmt.Scanln(&confirm)
|
|
if confirm != "y" && confirm != "Y" {
|
|
fmt.Println("Cancelled")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
docsClient := api.NewDocumentsClient(client)
|
|
if err := docsClient.Delete(docID); err != nil {
|
|
return printError("Failed to delete document", err)
|
|
}
|
|
|
|
printResponse(cmd, map[string]string{"id": docID, "deleted": "true"}, "doc delete")
|
|
return nil
|
|
}
|
|
|
|
// Project command group
|
|
var projectCmd = &cobra.Command{
|
|
Use: "project",
|
|
Short: "Project commands",
|
|
}
|
|
|
|
var projectListCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "List projects",
|
|
RunE: runProjectList,
|
|
}
|
|
|
|
var projectGetCmd = &cobra.Command{
|
|
Use: "get",
|
|
Short: "Get a project by ID",
|
|
RunE: runProjectGet,
|
|
}
|
|
|
|
func init() {
|
|
projectCmd.AddCommand(projectListCmd, projectGetCmd)
|
|
}
|
|
|
|
func runProjectList(cmd *cobra.Command, args []string) error {
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
projectsClient := api.NewProjectsClient(client)
|
|
projects, err := projectsClient.List()
|
|
if err != nil {
|
|
return printError("Failed to list projects", err)
|
|
}
|
|
|
|
printResponse(cmd, projects, "project list")
|
|
return nil
|
|
}
|
|
|
|
func runProjectGet(cmd *cobra.Command, args []string) error {
|
|
if len(args) < 1 {
|
|
return fmt.Errorf("project ID required")
|
|
}
|
|
projectID := args[0]
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
projectsClient := api.NewProjectsClient(client)
|
|
project, err := projectsClient.Get(projectID)
|
|
if err != nil {
|
|
return printError("Failed to get project", err)
|
|
}
|
|
|
|
printResponse(cmd, project, "project get")
|
|
return nil
|
|
}
|
|
|
|
// Folder command group
|
|
var folderCmd = &cobra.Command{
|
|
Use: "folder",
|
|
Short: "Folder commands",
|
|
}
|
|
|
|
var folderListCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "List folders in a project",
|
|
RunE: runFolderList,
|
|
}
|
|
|
|
var folderCreateCmd = &cobra.Command{
|
|
Use: "create",
|
|
Short: "Create a folder",
|
|
RunE: runFolderCreate,
|
|
}
|
|
|
|
func init() {
|
|
folderCmd.AddCommand(folderListCmd, folderCreateCmd)
|
|
|
|
folderListCmd.Flags().StringP("project-id", "p", "", "Project ID (required)")
|
|
folderListCmd.Flags().String("parent-id", "", "Parent folder ID")
|
|
folderListCmd.MarkFlagRequired("project-id")
|
|
|
|
folderCreateCmd.Flags().StringP("project-id", "p", "", "Project ID (required)")
|
|
folderCreateCmd.Flags().StringP("name", "n", "", "Folder name (required)")
|
|
folderCreateCmd.Flags().String("parent-id", "", "Parent folder ID")
|
|
folderCreateCmd.MarkFlagRequired("project-id")
|
|
folderCreateCmd.MarkFlagRequired("name")
|
|
}
|
|
|
|
func runFolderList(cmd *cobra.Command, args []string) error {
|
|
projectID, _ := cmd.Flags().GetString("project-id")
|
|
parentID, _ := cmd.Flags().GetString("parent-id")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
foldersClient := api.NewFoldersClient(client)
|
|
folders, err := foldersClient.List(projectID, parentID)
|
|
if err != nil {
|
|
return printError("Failed to list folders", err)
|
|
}
|
|
|
|
printResponse(cmd, folders, "folder list")
|
|
return nil
|
|
}
|
|
|
|
func runFolderCreate(cmd *cobra.Command, args []string) error {
|
|
projectID, _ := cmd.Flags().GetString("project-id")
|
|
name, _ := cmd.Flags().GetString("name")
|
|
parentID, _ := cmd.Flags().GetString("parent-id")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
foldersClient := api.NewFoldersClient(client)
|
|
req := types.CreateFolderRequest{
|
|
Name: name,
|
|
ParentID: parentID,
|
|
}
|
|
|
|
folder, err := foldersClient.Create(projectID, req)
|
|
if err != nil {
|
|
return printError("Failed to create folder", err)
|
|
}
|
|
|
|
printResponse(cmd, folder, "folder create")
|
|
return nil
|
|
}
|
|
|
|
// Tag command group
|
|
var tagCmd = &cobra.Command{
|
|
Use: "tag",
|
|
Short: "Tag commands",
|
|
}
|
|
|
|
var tagListCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "List all tags",
|
|
RunE: runTagList,
|
|
}
|
|
|
|
var tagCreateCmd = &cobra.Command{
|
|
Use: "create",
|
|
Short: "Create a tag",
|
|
RunE: runTagCreate,
|
|
}
|
|
|
|
var tagAddCmd = &cobra.Command{
|
|
Use: "add",
|
|
Short: "Add a tag to a document",
|
|
RunE: runTagAdd,
|
|
}
|
|
|
|
func init() {
|
|
tagCmd.AddCommand(tagListCmd, tagCreateCmd, tagAddCmd)
|
|
|
|
tagCreateCmd.Flags().StringP("name", "n", "", "Tag name (required)")
|
|
tagCreateCmd.Flags().String("color", "", "Tag color (hex)")
|
|
tagCreateCmd.MarkFlagRequired("name")
|
|
|
|
tagAddCmd.Flags().String("doc-id", "", "Document ID (required)")
|
|
tagAddCmd.Flags().String("tag-id", "", "Tag ID (required)")
|
|
tagAddCmd.MarkFlagRequired("doc-id")
|
|
tagAddCmd.MarkFlagRequired("tag-id")
|
|
}
|
|
|
|
func runTagList(cmd *cobra.Command, args []string) error {
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
tagsClient := api.NewTagsClient(client)
|
|
tags, err := tagsClient.List()
|
|
if err != nil {
|
|
return printError("Failed to list tags", err)
|
|
}
|
|
|
|
printResponse(cmd, tags, "tag list")
|
|
return nil
|
|
}
|
|
|
|
func runTagCreate(cmd *cobra.Command, args []string) error {
|
|
name, _ := cmd.Flags().GetString("name")
|
|
color, _ := cmd.Flags().GetString("color")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
tagsClient := api.NewTagsClient(client)
|
|
req := types.CreateTagRequest{
|
|
Name: name,
|
|
Color: color,
|
|
}
|
|
|
|
tag, err := tagsClient.Create(req)
|
|
if err != nil {
|
|
return printError("Failed to create tag", err)
|
|
}
|
|
|
|
printResponse(cmd, tag, "tag create")
|
|
return nil
|
|
}
|
|
|
|
func runTagAdd(cmd *cobra.Command, args []string) error {
|
|
docID, _ := cmd.Flags().GetString("doc-id")
|
|
tagID, _ := cmd.Flags().GetString("tag-id")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
tagsClient := api.NewTagsClient(client)
|
|
if err := tagsClient.AddToDocument(docID, tagID); err != nil {
|
|
return printError("Failed to add tag", err)
|
|
}
|
|
|
|
printResponse(cmd, map[string]string{"doc_id": docID, "tag_id": tagID, "added": "true"}, "tag add")
|
|
return nil
|
|
}
|
|
|
|
// Search command
|
|
var searchCmd = &cobra.Command{
|
|
Use: "search",
|
|
Short: "Search documents",
|
|
RunE: runSearch,
|
|
}
|
|
|
|
func init() {
|
|
searchCmd.Flags().StringP("query", "q", "", "Search query (required)")
|
|
searchCmd.Flags().StringP("project-id", "p", "", "Filter by project")
|
|
searchCmd.Flags().String("tags", "", "Filter by tags (comma-separated)")
|
|
searchCmd.MarkFlagRequired("query")
|
|
}
|
|
|
|
func runSearch(cmd *cobra.Command, args []string) error {
|
|
query, _ := cmd.Flags().GetString("query")
|
|
projectID, _ := cmd.Flags().GetString("project-id")
|
|
tags, _ := cmd.Flags().GetString("tags")
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
searchClient := api.NewSearchClient(client)
|
|
result, err := searchClient.Search(query, projectID, tags)
|
|
if err != nil {
|
|
return printError("Search failed", err)
|
|
}
|
|
|
|
printResponse(cmd, result, "search")
|
|
return nil
|
|
}
|
|
|
|
// Reasoning command
|
|
var reasoningCmd = &cobra.Command{
|
|
Use: "reasoning",
|
|
Short: "Reasoning commands",
|
|
}
|
|
|
|
var reasoningSaveCmd = &cobra.Command{
|
|
Use: "save",
|
|
Short: "Save reasoning for a document",
|
|
RunE: runReasoningSave,
|
|
}
|
|
|
|
func init() {
|
|
reasoningCmd.AddCommand(reasoningSaveCmd)
|
|
|
|
reasoningSaveCmd.Flags().StringP("doc-id", "d", "", "Document ID (required)")
|
|
reasoningSaveCmd.Flags().StringP("type", "t", "", "Reasoning type: research, planning, analysis, synthesis (required)")
|
|
reasoningSaveCmd.Flags().String("steps", "", "JSON array of reasoning steps (required)")
|
|
reasoningSaveCmd.Flags().Float64("confidence", 0.0, "Confidence score 0.0-1.0")
|
|
reasoningSaveCmd.Flags().String("model", "", "Source model")
|
|
reasoningSaveCmd.MarkFlagRequired("doc-id")
|
|
reasoningSaveCmd.MarkFlagRequired("type")
|
|
reasoningSaveCmd.MarkFlagRequired("steps")
|
|
}
|
|
|
|
func runReasoningSave(cmd *cobra.Command, args []string) error {
|
|
docID, _ := cmd.Flags().GetString("doc-id")
|
|
reasoningType, _ := cmd.Flags().GetString("type")
|
|
stepsJSON, _ := cmd.Flags().GetString("steps")
|
|
confidence, _ := cmd.Flags().GetFloat64("confidence")
|
|
model, _ := cmd.Flags().GetString("model")
|
|
|
|
var steps []types.ReasoningStep
|
|
if err := json.Unmarshal([]byte(stepsJSON), &steps); err != nil {
|
|
return printError("Invalid steps JSON", err)
|
|
}
|
|
|
|
client, err := api.NewClient()
|
|
if err != nil {
|
|
return printError("Failed to create client", err)
|
|
}
|
|
|
|
reasoningClient := api.NewReasoningClient(client)
|
|
req := types.SaveReasoningRequest{
|
|
Type: reasoningType,
|
|
Steps: steps,
|
|
Confidence: confidence,
|
|
Model: model,
|
|
}
|
|
|
|
reasoning, err := reasoningClient.Save(docID, req)
|
|
if err != nil {
|
|
return printError("Failed to save reasoning", err)
|
|
}
|
|
|
|
printResponse(cmd, reasoning, "reasoning save")
|
|
return nil
|
|
}
|
|
|
|
// Helper functions
|
|
func printResponse(cmd *cobra.Command, data interface{}, command string) {
|
|
start := time.Now()
|
|
cfg := config.GetConfig()
|
|
server := "http://localhost:8000"
|
|
if cfg != nil {
|
|
server = cfg.Server
|
|
}
|
|
|
|
formatter := output.NewFormatter(command, server)
|
|
durationMs := int64(time.Since(start).Milliseconds())
|
|
resp := formatter.Success(data, durationMs)
|
|
|
|
if cfg != nil && cfg.Output == "text" {
|
|
printTextOutput(command, data)
|
|
} else {
|
|
output.PrintJSON(resp)
|
|
}
|
|
}
|
|
|
|
func printTextOutput(command string, data interface{}) {
|
|
switch v := data.(type) {
|
|
case map[string]interface{}:
|
|
for k, val := range v {
|
|
fmt.Printf("%s: %v\n", k, val)
|
|
}
|
|
case []interface{}:
|
|
fmt.Println("Items:")
|
|
for i, item := range v {
|
|
fmt.Printf(" [%d] %v\n", i, item)
|
|
}
|
|
default:
|
|
fmt.Println(data)
|
|
}
|
|
}
|
|
|
|
func printError(context string, err error) error {
|
|
cfg := config.GetConfig()
|
|
server := "http://localhost:8000"
|
|
if cfg != nil {
|
|
server = cfg.Server
|
|
}
|
|
|
|
formatter := output.NewFormatter("", server)
|
|
durationMs := int64(0)
|
|
|
|
code := "ERROR"
|
|
if err != nil {
|
|
code = "NETWORK_ERROR"
|
|
}
|
|
|
|
resp := formatter.Error(code, err.Error(), durationMs)
|
|
|
|
if cfg != nil && cfg.Output == "text" {
|
|
fmt.Fprintf(os.Stderr, "%s: %v\n", context, err)
|
|
} else {
|
|
output.PrintJSON(resp)
|
|
}
|
|
return err
|
|
}
|