 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			326 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package openai
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"net/url"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	assistantsSuffix      = "/assistants"
 | |
| 	assistantsFilesSuffix = "/files"
 | |
| )
 | |
| 
 | |
| type Assistant struct {
 | |
| 	ID             string                 `json:"id"`
 | |
| 	Object         string                 `json:"object"`
 | |
| 	CreatedAt      int64                  `json:"created_at"`
 | |
| 	Name           *string                `json:"name,omitempty"`
 | |
| 	Description    *string                `json:"description,omitempty"`
 | |
| 	Model          string                 `json:"model"`
 | |
| 	Instructions   *string                `json:"instructions,omitempty"`
 | |
| 	Tools          []AssistantTool        `json:"tools"`
 | |
| 	ToolResources  *AssistantToolResource `json:"tool_resources,omitempty"`
 | |
| 	FileIDs        []string               `json:"file_ids,omitempty"` // Deprecated in v2
 | |
| 	Metadata       map[string]any         `json:"metadata,omitempty"`
 | |
| 	Temperature    *float32               `json:"temperature,omitempty"`
 | |
| 	TopP           *float32               `json:"top_p,omitempty"`
 | |
| 	ResponseFormat any                    `json:"response_format,omitempty"`
 | |
| 
 | |
| 	httpHeader
 | |
| }
 | |
| 
 | |
| type AssistantToolType string
 | |
| 
 | |
| const (
 | |
| 	AssistantToolTypeCodeInterpreter AssistantToolType = "code_interpreter"
 | |
| 	AssistantToolTypeRetrieval       AssistantToolType = "retrieval"
 | |
| 	AssistantToolTypeFunction        AssistantToolType = "function"
 | |
| 	AssistantToolTypeFileSearch      AssistantToolType = "file_search"
 | |
| )
 | |
| 
 | |
| type AssistantTool struct {
 | |
| 	Type     AssistantToolType   `json:"type"`
 | |
| 	Function *FunctionDefinition `json:"function,omitempty"`
 | |
| }
 | |
| 
 | |
| type AssistantToolFileSearch struct {
 | |
| 	VectorStoreIDs []string `json:"vector_store_ids"`
 | |
| }
 | |
| 
 | |
| type AssistantToolCodeInterpreter struct {
 | |
| 	FileIDs []string `json:"file_ids"`
 | |
| }
 | |
| 
 | |
| type AssistantToolResource struct {
 | |
| 	FileSearch      *AssistantToolFileSearch      `json:"file_search,omitempty"`
 | |
| 	CodeInterpreter *AssistantToolCodeInterpreter `json:"code_interpreter,omitempty"`
 | |
| }
 | |
| 
 | |
| // AssistantRequest provides the assistant request parameters.
 | |
| // When modifying the tools the API functions as the following:
 | |
| // If Tools is undefined, no changes are made to the Assistant's tools.
 | |
| // If Tools is empty slice it will effectively delete all of the Assistant's tools.
 | |
| // If Tools is populated, it will replace all of the existing Assistant's tools with the provided tools.
 | |
| type AssistantRequest struct {
 | |
| 	Model          string                 `json:"model"`
 | |
| 	Name           *string                `json:"name,omitempty"`
 | |
| 	Description    *string                `json:"description,omitempty"`
 | |
| 	Instructions   *string                `json:"instructions,omitempty"`
 | |
| 	Tools          []AssistantTool        `json:"-"`
 | |
| 	FileIDs        []string               `json:"file_ids,omitempty"`
 | |
| 	Metadata       map[string]any         `json:"metadata,omitempty"`
 | |
| 	ToolResources  *AssistantToolResource `json:"tool_resources,omitempty"`
 | |
| 	ResponseFormat any                    `json:"response_format,omitempty"`
 | |
| 	Temperature    *float32               `json:"temperature,omitempty"`
 | |
| 	TopP           *float32               `json:"top_p,omitempty"`
 | |
| }
 | |
| 
 | |
| // MarshalJSON provides a custom marshaller for the assistant request to handle the API use cases
 | |
| // If Tools is nil, the field is omitted from the JSON.
 | |
| // If Tools is an empty slice, it's included in the JSON as an empty array ([]).
 | |
| // If Tools is populated, it's included in the JSON with the elements.
 | |
| func (a AssistantRequest) MarshalJSON() ([]byte, error) {
 | |
| 	type Alias AssistantRequest
 | |
| 	assistantAlias := &struct {
 | |
| 		Tools *[]AssistantTool `json:"tools,omitempty"`
 | |
| 		*Alias
 | |
| 	}{
 | |
| 		Alias: (*Alias)(&a),
 | |
| 	}
 | |
| 
 | |
| 	if a.Tools != nil {
 | |
| 		assistantAlias.Tools = &a.Tools
 | |
| 	}
 | |
| 
 | |
| 	return json.Marshal(assistantAlias)
 | |
| }
 | |
| 
 | |
| // AssistantsList is a list of assistants.
 | |
| type AssistantsList struct {
 | |
| 	Assistants []Assistant `json:"data"`
 | |
| 	LastID     *string     `json:"last_id"`
 | |
| 	FirstID    *string     `json:"first_id"`
 | |
| 	HasMore    bool        `json:"has_more"`
 | |
| 	httpHeader
 | |
| }
 | |
| 
 | |
| type AssistantDeleteResponse struct {
 | |
| 	ID      string `json:"id"`
 | |
| 	Object  string `json:"object"`
 | |
| 	Deleted bool   `json:"deleted"`
 | |
| 
 | |
| 	httpHeader
 | |
| }
 | |
| 
 | |
| type AssistantFile struct {
 | |
| 	ID          string `json:"id"`
 | |
| 	Object      string `json:"object"`
 | |
| 	CreatedAt   int64  `json:"created_at"`
 | |
| 	AssistantID string `json:"assistant_id"`
 | |
| 
 | |
| 	httpHeader
 | |
| }
 | |
| 
 | |
| type AssistantFileRequest struct {
 | |
| 	FileID string `json:"file_id"`
 | |
| }
 | |
| 
 | |
| type AssistantFilesList struct {
 | |
| 	AssistantFiles []AssistantFile `json:"data"`
 | |
| 
 | |
| 	httpHeader
 | |
| }
 | |
| 
 | |
| // CreateAssistant creates a new assistant.
 | |
| func (c *Client) CreateAssistant(ctx context.Context, request AssistantRequest) (response Assistant, err error) {
 | |
| 	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(assistantsSuffix), withBody(request),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, &response)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // RetrieveAssistant retrieves an assistant.
 | |
| func (c *Client) RetrieveAssistant(
 | |
| 	ctx context.Context,
 | |
| 	assistantID string,
 | |
| ) (response Assistant, err error) {
 | |
| 	urlSuffix := fmt.Sprintf("%s/%s", assistantsSuffix, assistantID)
 | |
| 	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, &response)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // ModifyAssistant modifies an assistant.
 | |
| func (c *Client) ModifyAssistant(
 | |
| 	ctx context.Context,
 | |
| 	assistantID string,
 | |
| 	request AssistantRequest,
 | |
| ) (response Assistant, err error) {
 | |
| 	urlSuffix := fmt.Sprintf("%s/%s", assistantsSuffix, assistantID)
 | |
| 	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(urlSuffix), withBody(request),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, &response)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // DeleteAssistant deletes an assistant.
 | |
| func (c *Client) DeleteAssistant(
 | |
| 	ctx context.Context,
 | |
| 	assistantID string,
 | |
| ) (response AssistantDeleteResponse, err error) {
 | |
| 	urlSuffix := fmt.Sprintf("%s/%s", assistantsSuffix, assistantID)
 | |
| 	req, err := c.newRequest(ctx, http.MethodDelete, c.fullURL(urlSuffix),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, &response)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // ListAssistants Lists the currently available assistants.
 | |
| func (c *Client) ListAssistants(
 | |
| 	ctx context.Context,
 | |
| 	limit *int,
 | |
| 	order *string,
 | |
| 	after *string,
 | |
| 	before *string,
 | |
| ) (response AssistantsList, err error) {
 | |
| 	urlValues := url.Values{}
 | |
| 	if limit != nil {
 | |
| 		urlValues.Add("limit", fmt.Sprintf("%d", *limit))
 | |
| 	}
 | |
| 	if order != nil {
 | |
| 		urlValues.Add("order", *order)
 | |
| 	}
 | |
| 	if after != nil {
 | |
| 		urlValues.Add("after", *after)
 | |
| 	}
 | |
| 	if before != nil {
 | |
| 		urlValues.Add("before", *before)
 | |
| 	}
 | |
| 
 | |
| 	encodedValues := ""
 | |
| 	if len(urlValues) > 0 {
 | |
| 		encodedValues = "?" + urlValues.Encode()
 | |
| 	}
 | |
| 
 | |
| 	urlSuffix := fmt.Sprintf("%s%s", assistantsSuffix, encodedValues)
 | |
| 	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, &response)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // CreateAssistantFile creates a new assistant file.
 | |
| func (c *Client) CreateAssistantFile(
 | |
| 	ctx context.Context,
 | |
| 	assistantID string,
 | |
| 	request AssistantFileRequest,
 | |
| ) (response AssistantFile, err error) {
 | |
| 	urlSuffix := fmt.Sprintf("%s/%s%s", assistantsSuffix, assistantID, assistantsFilesSuffix)
 | |
| 	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL(urlSuffix),
 | |
| 		withBody(request),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, &response)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // RetrieveAssistantFile retrieves an assistant file.
 | |
| func (c *Client) RetrieveAssistantFile(
 | |
| 	ctx context.Context,
 | |
| 	assistantID string,
 | |
| 	fileID string,
 | |
| ) (response AssistantFile, err error) {
 | |
| 	urlSuffix := fmt.Sprintf("%s/%s%s/%s", assistantsSuffix, assistantID, assistantsFilesSuffix, fileID)
 | |
| 	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, &response)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // DeleteAssistantFile deletes an existing file.
 | |
| func (c *Client) DeleteAssistantFile(
 | |
| 	ctx context.Context,
 | |
| 	assistantID string,
 | |
| 	fileID string,
 | |
| ) (err error) {
 | |
| 	urlSuffix := fmt.Sprintf("%s/%s%s/%s", assistantsSuffix, assistantID, assistantsFilesSuffix, fileID)
 | |
| 	req, err := c.newRequest(ctx, http.MethodDelete, c.fullURL(urlSuffix),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, nil)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // ListAssistantFiles Lists the currently available files for an assistant.
 | |
| func (c *Client) ListAssistantFiles(
 | |
| 	ctx context.Context,
 | |
| 	assistantID string,
 | |
| 	limit *int,
 | |
| 	order *string,
 | |
| 	after *string,
 | |
| 	before *string,
 | |
| ) (response AssistantFilesList, err error) {
 | |
| 	urlValues := url.Values{}
 | |
| 	if limit != nil {
 | |
| 		urlValues.Add("limit", fmt.Sprintf("%d", *limit))
 | |
| 	}
 | |
| 	if order != nil {
 | |
| 		urlValues.Add("order", *order)
 | |
| 	}
 | |
| 	if after != nil {
 | |
| 		urlValues.Add("after", *after)
 | |
| 	}
 | |
| 	if before != nil {
 | |
| 		urlValues.Add("before", *before)
 | |
| 	}
 | |
| 
 | |
| 	encodedValues := ""
 | |
| 	if len(urlValues) > 0 {
 | |
| 		encodedValues = "?" + urlValues.Encode()
 | |
| 	}
 | |
| 
 | |
| 	urlSuffix := fmt.Sprintf("%s/%s%s%s", assistantsSuffix, assistantID, assistantsFilesSuffix, encodedValues)
 | |
| 	req, err := c.newRequest(ctx, http.MethodGet, c.fullURL(urlSuffix),
 | |
| 		withBetaAssistantVersion(c.config.AssistantVersion))
 | |
| 	if err != nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	err = c.sendRequest(req, &response)
 | |
| 	return
 | |
| }
 |