package cfg
import (
"log/slog"
"strings"
)
var Version = "0.4.1"
var (
FlagLogLevel string
// MaxLineLen is the maximum line length for code generation.
// Prompt bodies are not wrapped.
MaxLineLen int
)
func LogLevel() slog.Level {
switch strings.ToUpper(FlagLogLevel) {
case "DEBUG":
return slog.LevelDebug
case "INFO":
return slog.LevelInfo
case "WARN":
return slog.LevelWarn
case "ERROR":
return slog.LevelError
default:
return slog.LevelInfo
}
}
func TestMode() {
MaxLineLen = 80
FlagLogLevel = "DEBUG"
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package gen
import (
"github.com/omniaura/agentflow/cfg"
"github.com/omniaura/agentflow/cmd/af/gen/prompts"
"github.com/spf13/cobra"
)
func CMD() *cobra.Command {
cmd := &cobra.Command{
Use: "gen",
Short: "Generate code from .af files",
}
cmd.PersistentFlags().IntVar(&cfg.MaxLineLen, "max-line-len", 80, "Maximum line length")
cmd.AddCommand(prompts.CMD())
return cmd
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package prompts
import (
"fmt"
"io"
"io/fs"
"log/slog"
"os"
"path/filepath"
"github.com/omniaura/agentflow/pkg/assert"
"github.com/omniaura/agentflow/pkg/ast"
"github.com/omniaura/agentflow/pkg/gen/gogen"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
)
var (
Dir string
Lang string
)
func flags(cmd *cobra.Command) *cobra.Command {
cmd.Flags().StringVarP(&Dir,
"dir", "d", ".", "Directory to read .af files from. Defaults to current directory.")
cmd.Flags().StringVarP(&Lang,
"lang", "l", "go", "Language to generate prompts for. Only 'go' is supported.")
return cmd
}
func CMD() *cobra.Command {
cmd := &cobra.Command{
Use: "prompts",
Short: "Generate prompts",
Long: `Generate prompts from .af files in the input directory.
The generated prompts will be written next to their corresponding .af files.`,
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
// Use filepath.Walk to recursively find all .af files
var files []string
err := filepath.WalkDir(Dir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() && filepath.Ext(path) == ".af" {
files = append(files, path)
}
return nil
})
assert.NoError(err)
group, _ := errgroup.WithContext(ctx)
for _, name := range files {
group.Go(func() error {
file, err := os.Open(name)
if err != nil {
return err
}
defer file.Close()
f, err := io.ReadAll(file)
if err != nil {
return err
}
fName := filepath.Base(file.Name())
ff, err := ast.NewFile(fName, f)
if err != nil {
return err
}
// Create a subdirectory for all languages
pkgDir := filepath.Join(filepath.Dir(name), ff.Name)
if err := os.MkdirAll(pkgDir, 0755); err != nil {
return fmt.Errorf("failed to create package directory: %w", err)
}
// Generate the output file in the subdirectory
outFileName := ff.Name + "." + Lang
outFilePath := filepath.Join(pkgDir, outFileName)
outFile, err := os.OpenFile(outFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer outFile.Close()
var genErr error
switch Lang {
case "go":
genErr = gogen.GenFile(outFile, ff)
default:
return fmt.Errorf("unsupported language: %s (only 'go' is supported)", Lang)
}
if genErr != nil {
return genErr
}
slog.Info("Generated", "file", outFilePath)
return nil
})
}
if err := group.Wait(); err != nil {
slog.Error("Error", "error", err)
os.Exit(1)
}
},
}
return flags(cmd)
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"github.com/omniaura/agentflow/cfg"
"github.com/omniaura/agentflow/cmd/af/gen"
"github.com/omniaura/agentflow/pkg/assert"
"github.com/omniaura/agentflow/pkg/logger"
"github.com/spf13/cobra"
)
var Root = &cobra.Command{
Version: cfg.Version, // This line will be updated by the sync-version script
Use: "af",
Short: "AgentFlow CLI",
Long: "AgentFlow is a CLI for bootstrapping AI agents.",
PersistentPreRun: func(cmd *cobra.Command, args []string) { logger.Setup() },
}
func main() {
Root.PersistentFlags().StringVar(&cfg.FlagLogLevel, "log", "debug", "Log level")
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
Root.AddCommand(gen.CMD())
err := Root.ExecuteContext(ctx)
assert.NoError(err)
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package apigenerator
import (
"strconv"
"strings"
)
type ApiDocumentationGenerator struct{}
func (input *ApiDocumentationGenerator) String() string {
return `You are APIDocBot, an intelligent documentation generator that creates comprehensive, up-to-date API documentation with interactive examples, versioning support, and developer-friendly formatting.`
}
type ApiOverview struct {
Api struct {
Name string
Version string
BaseUrl string
Protocol string
AuthType string
Deprecated bool
ReplacementVersion string
SunsetDate string
Beta bool
StabilityLevel string
}
Changelog struct {
HasBreakingChanges bool
BreakingChanges string
NewFeatures string
Improvements string
BugFixes string
}
Docs struct {
MigrationUrl string
}
Auth struct {
Type string
Required bool
DashboardUrl string
OauthFlow string
Scopes string
AuthUrl string
TokenUrl string
ScopeCount int
ScopeList string
HeaderName string
QueryParam string
RateLimits bool
}
RateLimits struct {
StandardRequests int
StandardWindow string
PremiumRequests int
PremiumWindow string
HasBurst bool
BurstRequests int
BurstWindow string
}
}
func (input *ApiOverview) isApiZero() bool {
return input.Api.Name == "" &&
input.Api.Version == "" &&
input.Api.BaseUrl == "" &&
input.Api.Protocol == "" &&
input.Api.AuthType == "" &&
!input.Api.Deprecated &&
input.Api.ReplacementVersion == "" &&
input.Api.SunsetDate == "" &&
!input.Api.Beta &&
input.Api.StabilityLevel == ""
}
func (input *ApiOverview) isChangelogZero() bool {
return !input.Changelog.HasBreakingChanges &&
input.Changelog.BreakingChanges == "" &&
input.Changelog.NewFeatures == "" &&
input.Changelog.Improvements == "" &&
input.Changelog.BugFixes == ""
}
func (input *ApiOverview) isDocsZero() bool {
return input.Docs.MigrationUrl == ""
}
func (input *ApiOverview) isAuthZero() bool {
return input.Auth.Type == "" &&
!input.Auth.Required &&
input.Auth.DashboardUrl == "" &&
input.Auth.OauthFlow == "" &&
input.Auth.Scopes == "" &&
input.Auth.AuthUrl == "" &&
input.Auth.TokenUrl == "" &&
input.Auth.ScopeCount == 0 &&
input.Auth.ScopeList == "" &&
input.Auth.HeaderName == "" &&
input.Auth.QueryParam == "" &&
!input.Auth.RateLimits
}
func (input *ApiOverview) isRateLimitsZero() bool {
return input.RateLimits.StandardRequests == 0 &&
input.RateLimits.StandardWindow == "" &&
input.RateLimits.PremiumRequests == 0 &&
input.RateLimits.PremiumWindow == "" &&
!input.RateLimits.HasBurst &&
input.RateLimits.BurstRequests == 0 &&
input.RateLimits.BurstWindow == ""
}
func (input *ApiOverview) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.RateLimits.StandardRequests)
var1 := strconv.Itoa(input.RateLimits.PremiumRequests)
var2 := strconv.Itoa(input.RateLimits.BurstRequests)
length := 0
length += 7
length += len(input.Api.Name)
length += 33
length += len(input.Api.Version)
length += 16
length += len(input.Api.BaseUrl)
length += 16
length += len(input.Api.Protocol)
length += 21
length += len(input.Api.AuthType)
length += 2
if input.Api.Deprecated {
length += 86
length += len(input.Api.ReplacementVersion)
length += 19
length += len(input.Api.SunsetDate)
length += 1
}
length += 2
if input.Api.Beta {
length += 92
length += len(input.Api.StabilityLevel)
length += 3
}
length += 25
length += len(input.Api.Version)
length += 2
if input.Changelog.HasBreakingChanges {
length += 27
length += len(input.Changelog.BreakingChanges)
length += 59
length += len(input.Docs.MigrationUrl)
length += 28
}
length += 2
if input.Changelog.NewFeatures != "" {
length += 22
length += len(input.Changelog.NewFeatures)
length += 1
}
length += 2
if input.Changelog.Improvements != "" {
length += 23
length += len(input.Changelog.Improvements)
length += 1
}
length += 2
if input.Changelog.BugFixes != "" {
length += 20
length += len(input.Changelog.BugFixes)
length += 1
}
length += 36
length += len(input.Auth.Type)
length += 15
length += 5
length += 2
if input.Auth.Type == "bearer" {
length += 176
length += len(input.Auth.DashboardUrl)
length += 2
}
length += 2
if input.Auth.Type == "oauth2" {
length += 40
length += len(input.Auth.OauthFlow)
length += 13
length += len(input.Auth.Scopes)
length += 26
length += len(input.Auth.AuthUrl)
length += 18
length += len(input.Auth.TokenUrl)
length += 25
if input.Auth.ScopeCount != 0 {
length += 1
length += len(input.Auth.ScopeList)
length += 1
}
length += 1
}
length += 2
if input.Auth.Type == "apikey" {
length += 41
length += len(input.Auth.HeaderName)
length += 24
length += len(input.Auth.QueryParam)
length += 25
length += len(input.Auth.HeaderName)
length += 19
}
length += 2
if input.Auth.RateLimits {
length += 41
length += len(var0)
length += 10
length += len(input.RateLimits.StandardWindow)
length += 19
length += len(var1)
length += 10
length += len(input.RateLimits.PremiumWindow)
length += 165
if input.RateLimits.HasBurst {
length += 22
length += len(var2)
length += 13
length += len(input.RateLimits.BurstWindow)
length += 9
}
length += 1
}
b.Grow(length)
b.WriteString(`# ๐ก `)
b.WriteString(input.Api.Name)
b.WriteString(` API Documentation
**Version**: `)
b.WriteString(input.Api.Version)
b.WriteString("\n**Base URL**: `")
b.WriteString(input.Api.BaseUrl)
b.WriteString("`\n**Protocol**: ")
b.WriteString(input.Api.Protocol)
b.WriteString(`
**Authentication**: `)
b.WriteString(input.Api.AuthType)
b.WriteString(`
`)
if input.Api.Deprecated {
b.WriteString(`
โ ๏ธ **DEPRECATED API**: This API version is deprecated. Please migrate to version `)
b.WriteString(input.Api.ReplacementVersion)
b.WriteString(`.
**Sunset Date**: `)
b.WriteString(input.Api.SunsetDate)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Api.Beta {
b.WriteString(`
๐งช **BETA API**: This API is in beta. Features may change without notice.
**Stability**: `)
b.WriteString(input.Api.StabilityLevel)
b.WriteString(`/5
`)
}
b.WriteString(`
## ๐ What's New in v`)
b.WriteString(input.Api.Version)
b.WriteString(`
`)
if input.Changelog.HasBreakingChanges {
b.WriteString(`
### ๐ฅ Breaking Changes
`)
b.WriteString(input.Changelog.BreakingChanges)
b.WriteString(`
โ ๏ธ **Migration Required**: See our [migration guide](`)
b.WriteString(input.Docs.MigrationUrl)
b.WriteString(`) for upgrade instructions.
`)
}
b.WriteString(`
`)
if input.Changelog.NewFeatures != "" {
b.WriteString(`
### โจ New Features
`)
b.WriteString(input.Changelog.NewFeatures)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Changelog.Improvements != "" {
b.WriteString(`
### ๐ Improvements
`)
b.WriteString(input.Changelog.Improvements)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Changelog.BugFixes != "" {
b.WriteString(`
### ๐ Bug Fixes
`)
b.WriteString(input.Changelog.BugFixes)
b.WriteRune('\n')
}
b.WriteString(`
## ๐ Authentication
**Type**: `)
b.WriteString(input.Auth.Type)
b.WriteString(`
**Required**: `)
b.WriteString(strconv.FormatBool(input.Auth.Required))
b.WriteString(`
`)
if input.Auth.Type == "bearer" {
b.WriteString("\n### Bearer Token Authentication\nInclude your API key in the Authorization header:\n\n```http\nAuthorization: Bearer YOUR_API_KEY\n```\n\n**Get your API key**: [Developer Dashboard](")
b.WriteString(input.Auth.DashboardUrl)
b.WriteString(`)
`)
}
b.WriteString(`
`)
if input.Auth.Type == "oauth2" {
b.WriteString(`
### OAuth 2.0 Authentication
**Flow**: `)
b.WriteString(input.Auth.OauthFlow)
b.WriteString(`
**Scopes**: `)
b.WriteString(input.Auth.Scopes)
b.WriteString("\n\n**Authorization URL**: `")
b.WriteString(input.Auth.AuthUrl)
b.WriteString("`\n**Token URL**: `")
b.WriteString(input.Auth.TokenUrl)
b.WriteString("`\n\n#### Required Scopes:\n")
if input.Auth.ScopeCount != 0 {
b.WriteRune('\n')
b.WriteString(input.Auth.ScopeList)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Auth.Type == "apikey" {
b.WriteString("\n### API Key Authentication\n**Header**: `")
b.WriteString(input.Auth.HeaderName)
b.WriteString("`\n**Query Parameter**: `")
b.WriteString(input.Auth.QueryParam)
b.WriteString("` (alternative)\n\n```http\n")
b.WriteString(input.Auth.HeaderName)
b.WriteString(": YOUR_API_KEY\n```\n")
}
b.WriteString(`
`)
if input.Auth.RateLimits {
b.WriteString(`
## ๐ Rate Limits
**Standard Tier**: `)
b.WriteString(var0)
b.WriteString(` requests/`)
b.WriteString(input.RateLimits.StandardWindow)
b.WriteString(`
**Premium Tier**: `)
b.WriteString(var1)
b.WriteString(` requests/`)
b.WriteString(input.RateLimits.PremiumWindow)
b.WriteString("\n\n**Rate Limit Headers**:\n- `X-RateLimit-Limit`: Total requests allowed\n- `X-RateLimit-Remaining`: Requests remaining\n- `X-RateLimit-Reset`: Time when limit resets\n\n")
if input.RateLimits.HasBurst {
b.WriteString(`
**Burst Allowance**: `)
b.WriteString(var2)
b.WriteString(` requests in `)
b.WriteString(input.RateLimits.BurstWindow)
b.WriteString(` seconds
`)
}
b.WriteRune('\n')
}
return b.String()
}
type EndpointDocumentation struct {
Endpoints struct {
Count int
HasCategories bool
UserManagement bool
UserCount int
DataOperations bool
DataCount int
Analytics bool
AnalyticsCount int
Webhooks bool
WebhookCount int
}
Endpoint struct {
Featured bool
Name string
Method string
Path string
Description string
RequiresAuth bool
HasPathParams bool
PathParams string
ParamName string
ParamType string
ParamRequired bool
ParamDescription string
HasQueryParams bool
QueryParams string
QueryName string
QueryType string
QueryRequired bool
QueryDefault string
QueryDescription string
HasBody bool
RequestBody string
RequestSchema string
SuccessCodes string
ResponseExample string
HasErrorCodes bool
ErrorCodes string
ErrorCode int
ErrorDescription string
ErrorSolution string
CurlBody string
JsBody string
PythonBody string
MethodLower string
NoBody bool
GoBody string
}
Api struct {
BaseUrl string
}
Examples struct {
Curl bool
Javascript bool
Python bool
Go bool
}
}
func (input *EndpointDocumentation) isEndpointsZero() bool {
return input.Endpoints.Count == 0 &&
!input.Endpoints.HasCategories &&
!input.Endpoints.UserManagement &&
input.Endpoints.UserCount == 0 &&
!input.Endpoints.DataOperations &&
input.Endpoints.DataCount == 0 &&
!input.Endpoints.Analytics &&
input.Endpoints.AnalyticsCount == 0 &&
!input.Endpoints.Webhooks &&
input.Endpoints.WebhookCount == 0
}
func (input *EndpointDocumentation) isEndpointZero() bool {
return !input.Endpoint.Featured &&
input.Endpoint.Name == "" &&
input.Endpoint.Method == "" &&
input.Endpoint.Path == "" &&
input.Endpoint.Description == "" &&
!input.Endpoint.RequiresAuth &&
!input.Endpoint.HasPathParams &&
input.Endpoint.PathParams == "" &&
input.Endpoint.ParamName == "" &&
input.Endpoint.ParamType == "" &&
!input.Endpoint.ParamRequired &&
input.Endpoint.ParamDescription == "" &&
!input.Endpoint.HasQueryParams &&
input.Endpoint.QueryParams == "" &&
input.Endpoint.QueryName == "" &&
input.Endpoint.QueryType == "" &&
!input.Endpoint.QueryRequired &&
input.Endpoint.QueryDefault == "" &&
input.Endpoint.QueryDescription == "" &&
!input.Endpoint.HasBody &&
input.Endpoint.RequestBody == "" &&
input.Endpoint.RequestSchema == "" &&
input.Endpoint.SuccessCodes == "" &&
input.Endpoint.ResponseExample == "" &&
!input.Endpoint.HasErrorCodes &&
input.Endpoint.ErrorCodes == "" &&
input.Endpoint.ErrorCode == 0 &&
input.Endpoint.ErrorDescription == "" &&
input.Endpoint.ErrorSolution == "" &&
input.Endpoint.CurlBody == "" &&
input.Endpoint.JsBody == "" &&
input.Endpoint.PythonBody == "" &&
input.Endpoint.MethodLower == "" &&
!input.Endpoint.NoBody &&
input.Endpoint.GoBody == ""
}
func (input *EndpointDocumentation) isApiZero() bool {
return input.Api.BaseUrl == ""
}
func (input *EndpointDocumentation) isExamplesZero() bool {
return !input.Examples.Curl &&
!input.Examples.Javascript &&
!input.Examples.Python &&
!input.Examples.Go
}
func (input *EndpointDocumentation) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Endpoints.UserCount)
var1 := strconv.Itoa(input.Endpoints.DataCount)
var2 := strconv.Itoa(input.Endpoints.AnalyticsCount)
var3 := strconv.Itoa(input.Endpoints.WebhookCount)
var4 := strconv.Itoa(input.Endpoint.ErrorCode)
length := 0
if input.Endpoints.Count != 0 {
length += 30
length += len(strconv.Itoa(input.Endpoints.Count))
length += 9
if input.Endpoints.HasCategories {
length += 26
if input.Endpoints.UserManagement {
length += 29
length += len(var0)
length += 11
}
length += 1
if input.Endpoints.DataOperations {
length += 29
length += len(var1)
length += 13
}
length += 1
if input.Endpoints.Analytics {
length += 23
length += len(var2)
length += 11
}
length += 1
if input.Endpoints.Webhooks {
length += 22
length += len(var3)
length += 11
}
length += 1
}
length += 1
}
length += 2
if input.Endpoint.Featured {
length += 28
length += len(input.Endpoint.Name)
length += 15
length += len(input.Endpoint.Method)
length += 13
length += len(input.Endpoint.Path)
length += 15
length += len(input.Endpoint.Description)
length += 23
length += len(input.Endpoint.Method)
length += 1
length += len(input.Api.BaseUrl)
length += len(input.Endpoint.Path)
length += 32
if input.Endpoint.RequiresAuth {
length += 36
}
length += 6
if input.Endpoint.HasPathParams {
length += 114
if input.Endpoint.PathParams != "" {
length += 3
length += len(input.Endpoint.ParamName)
length += 3
length += len(input.Endpoint.ParamType)
length += 3
length += 5
length += 3
length += len(input.Endpoint.ParamDescription)
length += 3
}
length += 1
}
length += 2
if input.Endpoint.HasQueryParams {
length += 135
if input.Endpoint.QueryParams != "" {
length += 3
length += len(input.Endpoint.QueryName)
length += 3
length += len(input.Endpoint.QueryType)
length += 3
length += 5
length += 3
length += len(input.Endpoint.QueryDefault)
length += 3
length += len(input.Endpoint.QueryDescription)
length += 3
}
length += 1
}
length += 2
if input.Endpoint.HasBody {
length += 28
length += len(input.Endpoint.RequestBody)
length += 18
length += len(input.Endpoint.RequestSchema)
length += 1
}
length += 16
if input.Endpoint.SuccessCodes != "" {
length += 20
length += len(input.Endpoint.SuccessCodes)
length += 1
}
length += 10
length += len(input.Endpoint.ResponseExample)
length += 6
if input.Endpoint.HasErrorCodes {
length += 91
if input.Endpoint.ErrorCodes != "" {
length += 3
length += len(var4)
length += 3
length += len(input.Endpoint.ErrorDescription)
length += 3
length += len(input.Endpoint.ErrorSolution)
length += 3
}
length += 1
}
length += 21
if input.Examples.Curl {
length += 27
length += len(input.Endpoint.Method)
length += 6
length += len(input.Api.BaseUrl)
length += len(input.Endpoint.Path)
length += 44
if input.Endpoint.RequiresAuth {
length += 45
}
length += 1
if input.Endpoint.HasBody {
length += 7
length += len(input.Endpoint.CurlBody)
length += 2
}
length += 5
}
length += 2
if input.Examples.Javascript {
length += 69
length += len(input.Api.BaseUrl)
length += len(input.Endpoint.Path)
length += 16
length += len(input.Endpoint.Method)
length += 56
if input.Endpoint.RequiresAuth {
length += 45
}
length += 6
if input.Endpoint.HasBody {
length += 24
length += len(input.Endpoint.JsBody)
length += 2
}
length += 65
}
length += 2
if input.Examples.Python {
length += 58
length += len(input.Api.BaseUrl)
length += len(input.Endpoint.Path)
length += 2
if input.Endpoint.RequiresAuth {
length += 98
}
length += 1
if input.Endpoint.HasBody {
length += 8
length += len(input.Endpoint.PythonBody)
length += 22
length += len(input.Endpoint.MethodLower)
length += 34
}
length += 1
if input.Endpoint.NoBody {
length += 21
length += len(input.Endpoint.MethodLower)
length += 23
}
length += 28
}
length += 2
if input.Examples.Go {
length += 124
length += len(input.Api.BaseUrl)
length += len(input.Endpoint.Path)
length += 7
if input.Endpoint.HasBody {
length += 13
length += len(input.Endpoint.GoBody)
length += 75
length += len(input.Endpoint.Method)
length += 35
}
length += 1
if input.Endpoint.NoBody {
length += 32
length += len(input.Endpoint.Method)
length += 13
}
length += 61
if input.Endpoint.RequiresAuth {
length += 60
}
length += 130
}
length += 1
}
b.Grow(length)
if input.Endpoints.Count != 0 {
b.WriteString(`
## ๐ Available Endpoints (`)
b.WriteString(strconv.Itoa(input.Endpoints.Count))
b.WriteString(` total)
`)
if input.Endpoints.HasCategories {
b.WriteString(`
### Endpoint Categories:
`)
if input.Endpoints.UserManagement {
b.WriteString(`
- **๐ค User Management**: `)
b.WriteString(var0)
b.WriteString(` endpoints
`)
}
b.WriteRune('\n')
if input.Endpoints.DataOperations {
b.WriteString(`
- **๐พ Data Operations**: `)
b.WriteString(var1)
b.WriteString(` endpoints
`)
}
b.WriteRune('\n')
if input.Endpoints.Analytics {
b.WriteString(`
- **๐ Analytics**: `)
b.WriteString(var2)
b.WriteString(` endpoints
`)
}
b.WriteRune('\n')
if input.Endpoints.Webhooks {
b.WriteString(`
- **๐ Webhooks**: `)
b.WriteString(var3)
b.WriteString(` endpoints
`)
}
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Endpoint.Featured {
b.WriteString(`
## ๐ Featured Endpoint: `)
b.WriteString(input.Endpoint.Name)
b.WriteString("\n\n**Method**: `")
b.WriteString(input.Endpoint.Method)
b.WriteString("`\n**Path**: `")
b.WriteString(input.Endpoint.Path)
b.WriteString("`\n**Purpose**: ")
b.WriteString(input.Endpoint.Description)
b.WriteString("\n\n### Request\n\n```http\n")
b.WriteString(input.Endpoint.Method)
b.WriteString(` `)
b.WriteString(input.Api.BaseUrl)
b.WriteString(input.Endpoint.Path)
b.WriteString(`
Content-Type: application/json
`)
if input.Endpoint.RequiresAuth {
b.WriteString(`
Authorization: Bearer YOUR_API_KEY
`)
}
b.WriteString("\n```\n\n")
if input.Endpoint.HasPathParams {
b.WriteString(`
#### Path Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
`)
if input.Endpoint.PathParams != "" {
b.WriteString(`
| `)
b.WriteString(input.Endpoint.ParamName)
b.WriteString(` | `)
b.WriteString(input.Endpoint.ParamType)
b.WriteString(` | `)
b.WriteString(strconv.FormatBool(input.Endpoint.ParamRequired))
b.WriteString(` | `)
b.WriteString(input.Endpoint.ParamDescription)
b.WriteString(` |
`)
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Endpoint.HasQueryParams {
b.WriteString(`
#### Query Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
`)
if input.Endpoint.QueryParams != "" {
b.WriteString(`
| `)
b.WriteString(input.Endpoint.QueryName)
b.WriteString(` | `)
b.WriteString(input.Endpoint.QueryType)
b.WriteString(` | `)
b.WriteString(strconv.FormatBool(input.Endpoint.QueryRequired))
b.WriteString(` | `)
b.WriteString(input.Endpoint.QueryDefault)
b.WriteString(` | `)
b.WriteString(input.Endpoint.QueryDescription)
b.WriteString(` |
`)
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Endpoint.HasBody {
b.WriteString("\n#### Request Body\n\n```json\n")
b.WriteString(input.Endpoint.RequestBody)
b.WriteString("\n```\n\n**Schema**: ")
b.WriteString(input.Endpoint.RequestSchema)
b.WriteRune('\n')
}
b.WriteString(`
### Response
`)
if input.Endpoint.SuccessCodes != "" {
b.WriteString(`
**Success Codes**: `)
b.WriteString(input.Endpoint.SuccessCodes)
b.WriteRune('\n')
}
b.WriteString("\n\n```json\n")
b.WriteString(input.Endpoint.ResponseExample)
b.WriteString("\n```\n\n")
if input.Endpoint.HasErrorCodes {
b.WriteString(`
#### Error Responses
| Code | Description | Solution |
|------|-------------|----------|
`)
if input.Endpoint.ErrorCodes != "" {
b.WriteString(`
| `)
b.WriteString(var4)
b.WriteString(` | `)
b.WriteString(input.Endpoint.ErrorDescription)
b.WriteString(` | `)
b.WriteString(input.Endpoint.ErrorSolution)
b.WriteString(` |
`)
}
b.WriteRune('\n')
}
b.WriteString(`
### Code Examples
`)
if input.Examples.Curl {
b.WriteString("\n#### cURL\n```bash\ncurl -X ")
b.WriteString(input.Endpoint.Method)
b.WriteString(` \
'`)
b.WriteString(input.Api.BaseUrl)
b.WriteString(input.Endpoint.Path)
b.WriteString(`' \
-H 'Content-Type: application/json' \
`)
if input.Endpoint.RequiresAuth {
b.WriteString(`
-H 'Authorization: Bearer YOUR_API_KEY' \
`)
}
b.WriteRune('\n')
if input.Endpoint.HasBody {
b.WriteString(`
-d '`)
b.WriteString(input.Endpoint.CurlBody)
b.WriteString(`'
`)
}
b.WriteString("\n```\n")
}
b.WriteString(`
`)
if input.Examples.Javascript {
b.WriteString("\n#### JavaScript (fetch)\n```javascript\nconst response = await fetch('")
b.WriteString(input.Api.BaseUrl)
b.WriteString(input.Endpoint.Path)
b.WriteString(`', {
method: '`)
b.WriteString(input.Endpoint.Method)
b.WriteString(`',
headers: {
'Content-Type': 'application/json',
`)
if input.Endpoint.RequiresAuth {
b.WriteString(`
'Authorization': 'Bearer YOUR_API_KEY',
`)
}
b.WriteString(`
},
`)
if input.Endpoint.HasBody {
b.WriteString(`
body: JSON.stringify(`)
b.WriteString(input.Endpoint.JsBody)
b.WriteString(`)
`)
}
b.WriteString("\n});\n\nconst data = await response.json();\nconsole.log(data);\n```\n")
}
b.WriteString(`
`)
if input.Examples.Python {
b.WriteString("\n#### Python (requests)\n```python\nimport requests\n\nurl = \"")
b.WriteString(input.Api.BaseUrl)
b.WriteString(input.Endpoint.Path)
b.WriteString(`"
`)
if input.Endpoint.RequiresAuth {
b.WriteString(`
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_KEY"
}
`)
}
b.WriteRune('\n')
if input.Endpoint.HasBody {
b.WriteString(`
data = `)
b.WriteString(input.Endpoint.PythonBody)
b.WriteString(`
response = requests.`)
b.WriteString(input.Endpoint.MethodLower)
b.WriteString(`(url, headers=headers, json=data)
`)
}
b.WriteRune('\n')
if input.Endpoint.NoBody {
b.WriteString(`
response = requests.`)
b.WriteString(input.Endpoint.MethodLower)
b.WriteString(`(url, headers=headers)
`)
}
b.WriteString("\nprint(response.json())\n```\n")
}
b.WriteString(`
`)
if input.Examples.Go {
b.WriteString("\n#### Go\n```go\npackage main\n\nimport (\n \"bytes\"\n \"encoding/json\"\n \"fmt\"\n \"net/http\"\n)\n\nfunc main() {\n url := \"")
b.WriteString(input.Api.BaseUrl)
b.WriteString(input.Endpoint.Path)
b.WriteString(`"
`)
if input.Endpoint.HasBody {
b.WriteString(`
data := `)
b.WriteString(input.Endpoint.GoBody)
b.WriteString(`
jsonData, _ := json.Marshal(data)
req, _ := http.NewRequest("`)
b.WriteString(input.Endpoint.Method)
b.WriteString(`", url, bytes.NewBuffer(jsonData))
`)
}
b.WriteRune('\n')
if input.Endpoint.NoBody {
b.WriteString(`
req, _ := http.NewRequest("`)
b.WriteString(input.Endpoint.Method)
b.WriteString(`", url, nil)
`)
}
b.WriteString(`
req.Header.Set("Content-Type", "application/json")
`)
if input.Endpoint.RequiresAuth {
b.WriteString(`
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
`)
}
b.WriteString("\n \n client := &http.Client{}\n resp, _ := client.Do(req)\n defer resp.Body.Close()\n \n // Handle response...\n}\n```\n")
}
b.WriteRune('\n')
}
return b.String()
}
type SchemaReference struct {
Schemas struct {
Available bool
Count int
Schema1 struct {
Name string
Description string
Example string
Properties string
HasValidation bool
ValidationRules string
}
FieldName string
FieldType string
FieldRequired bool
FieldDescription string
}
}
func (input *SchemaReference) isSchemasZero() bool {
return !input.Schemas.Available &&
input.Schemas.Count == 0 &&
input.isSchemasSchema1Zero() &&
input.Schemas.FieldName == "" &&
input.Schemas.FieldType == "" &&
!input.Schemas.FieldRequired &&
input.Schemas.FieldDescription == ""
}
func (input *SchemaReference) isSchemasSchema1Zero() bool {
return input.Schemas.Schema1.Name == "" &&
input.Schemas.Schema1.Description == "" &&
input.Schemas.Schema1.Example == "" &&
input.Schemas.Schema1.Properties == "" &&
!input.Schemas.Schema1.HasValidation &&
input.Schemas.Schema1.ValidationRules == ""
}
func (input *SchemaReference) String() string {
var b strings.Builder
length := 0
if input.Schemas.Available {
length += 23
if input.Schemas.Count != 0 {
length += 24
length += len(strconv.Itoa(input.Schemas.Count))
length += 9
if !input.isSchemasSchema1Zero() {
length += 6
length += len(input.Schemas.Schema1.Name)
length += 19
length += len(input.Schemas.Schema1.Description)
length += 10
length += len(input.Schemas.Schema1.Example)
length += 106
if input.Schemas.Schema1.Properties != "" {
length += 3
length += len(input.Schemas.FieldName)
length += 3
length += len(input.Schemas.FieldType)
length += 3
length += 5
length += 3
length += len(input.Schemas.FieldDescription)
length += 3
}
length += 2
if input.Schemas.Schema1.HasValidation {
length += 23
length += len(input.Schemas.Schema1.ValidationRules)
length += 1
}
length += 1
}
length += 1
}
length += 1
}
b.Grow(length)
if input.Schemas.Available {
b.WriteString(`
## ๐ Data Schemas
`)
if input.Schemas.Count != 0 {
b.WriteString(`
### Available Schemas (`)
b.WriteString(strconv.Itoa(input.Schemas.Count))
b.WriteString(` total)
`)
if !input.isSchemasSchema1Zero() {
b.WriteString(`
#### `)
b.WriteString(input.Schemas.Schema1.Name)
b.WriteString(`
**Description**: `)
b.WriteString(input.Schemas.Schema1.Description)
b.WriteString("\n\n```json\n")
b.WriteString(input.Schemas.Schema1.Example)
b.WriteString("\n```\n\n**Properties**:\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n")
if input.Schemas.Schema1.Properties != "" {
b.WriteString(`
| `)
b.WriteString(input.Schemas.FieldName)
b.WriteString(` | `)
b.WriteString(input.Schemas.FieldType)
b.WriteString(` | `)
b.WriteString(strconv.FormatBool(input.Schemas.FieldRequired))
b.WriteString(` | `)
b.WriteString(input.Schemas.FieldDescription)
b.WriteString(` |
`)
}
b.WriteString(`
`)
if input.Schemas.Schema1.HasValidation {
b.WriteString(`
**Validation Rules**:
`)
b.WriteString(input.Schemas.Schema1.ValidationRules)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteRune('\n')
}
return b.String()
}
type SdksAndTools struct {
Sdks struct {
Available bool
OfficialCount int
Javascript bool
JsPackage string
JsDocs string
JsVersion string
JsSize string
Python bool
PythonPackage string
PythonDocs string
PythonVersion string
PythonCompat string
Go bool
GoPackage string
GoDocs string
GoVersion string
GoCompat string
Ruby bool
RubyPackage string
RubyDocs string
RubyVersion string
CommunityCount int
CommunityList string
}
Tools struct {
Postman bool
PostmanUrl string
Openapi bool
OpenapiUrl string
SwaggerUrl string
Insomnia bool
InsomniaUrl string
}
}
func (input *SdksAndTools) isSdksZero() bool {
return !input.Sdks.Available &&
input.Sdks.OfficialCount == 0 &&
!input.Sdks.Javascript &&
input.Sdks.JsPackage == "" &&
input.Sdks.JsDocs == "" &&
input.Sdks.JsVersion == "" &&
input.Sdks.JsSize == "" &&
!input.Sdks.Python &&
input.Sdks.PythonPackage == "" &&
input.Sdks.PythonDocs == "" &&
input.Sdks.PythonVersion == "" &&
input.Sdks.PythonCompat == "" &&
!input.Sdks.Go &&
input.Sdks.GoPackage == "" &&
input.Sdks.GoDocs == "" &&
input.Sdks.GoVersion == "" &&
input.Sdks.GoCompat == "" &&
!input.Sdks.Ruby &&
input.Sdks.RubyPackage == "" &&
input.Sdks.RubyDocs == "" &&
input.Sdks.RubyVersion == "" &&
input.Sdks.CommunityCount == 0 &&
input.Sdks.CommunityList == ""
}
func (input *SdksAndTools) isToolsZero() bool {
return !input.Tools.Postman &&
input.Tools.PostmanUrl == "" &&
!input.Tools.Openapi &&
input.Tools.OpenapiUrl == "" &&
input.Tools.SwaggerUrl == "" &&
!input.Tools.Insomnia &&
input.Tools.InsomniaUrl == ""
}
func (input *SdksAndTools) String() string {
var b strings.Builder
length := 0
if input.Sdks.Available {
length += 30
if input.Sdks.OfficialCount != 0 {
length += 20
length += len(strconv.Itoa(input.Sdks.OfficialCount))
length += 13
if input.Sdks.Javascript {
length += 48
length += len(input.Sdks.JsPackage)
length += 48
length += len(input.Sdks.JsDocs)
length += 15
length += len(input.Sdks.JsVersion)
length += 18
length += len(input.Sdks.JsSize)
length += 1
}
length += 2
if input.Sdks.Python {
length += 33
length += len(input.Sdks.PythonPackage)
length += 44
length += len(input.Sdks.PythonDocs)
length += 15
length += len(input.Sdks.PythonVersion)
length += 27
length += len(input.Sdks.PythonCompat)
length += 1
}
length += 2
if input.Sdks.Go {
length += 24
length += len(input.Sdks.GoPackage)
length += 40
length += len(input.Sdks.GoDocs)
length += 15
length += len(input.Sdks.GoVersion)
length += 17
length += len(input.Sdks.GoCompat)
length += 1
}
length += 2
if input.Sdks.Ruby {
length += 31
length += len(input.Sdks.RubyPackage)
length += 42
length += len(input.Sdks.RubyDocs)
length += 15
length += len(input.Sdks.RubyVersion)
length += 1
}
length += 1
}
length += 2
if input.Sdks.CommunityCount != 0 {
length += 21
length += len(strconv.Itoa(input.Sdks.CommunityCount))
length += 12
length += len(input.Sdks.CommunityList)
length += 84
}
length += 1
}
length += 29
if input.Tools.Postman {
length += 90
length += len(input.Tools.PostmanUrl)
length += 107
}
length += 2
if input.Tools.Openapi {
length += 60
length += len(input.Tools.OpenapiUrl)
length += 46
length += len(input.Tools.SwaggerUrl)
length += 2
}
length += 2
if input.Tools.Insomnia {
length += 66
length += len(input.Tools.InsomniaUrl)
length += 2
}
b.Grow(length)
if input.Sdks.Available {
b.WriteString(`
## ๐ ๏ธ SDKs & Libraries
`)
if input.Sdks.OfficialCount != 0 {
b.WriteString(`
### Official SDKs (`)
b.WriteString(strconv.Itoa(input.Sdks.OfficialCount))
b.WriteString(` languages)
`)
if input.Sdks.Javascript {
b.WriteString("\n#### JavaScript/TypeScript\n```bash\nnpm install ")
b.WriteString(input.Sdks.JsPackage)
b.WriteString("\n```\n\n**Documentation**: [JavaScript SDK Guide](")
b.WriteString(input.Sdks.JsDocs)
b.WriteString(`)
**Version**: `)
b.WriteString(input.Sdks.JsVersion)
b.WriteString(`
**Bundle Size**: `)
b.WriteString(input.Sdks.JsSize)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Sdks.Python {
b.WriteString("\n#### Python\n```bash\npip install ")
b.WriteString(input.Sdks.PythonPackage)
b.WriteString("\n```\n\n**Documentation**: [Python SDK Guide](")
b.WriteString(input.Sdks.PythonDocs)
b.WriteString(`)
**Version**: `)
b.WriteString(input.Sdks.PythonVersion)
b.WriteString(`
**Python Compatibility**: `)
b.WriteString(input.Sdks.PythonCompat)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Sdks.Go {
b.WriteString("\n#### Go\n```bash\ngo get ")
b.WriteString(input.Sdks.GoPackage)
b.WriteString("\n```\n\n**Documentation**: [Go SDK Guide](")
b.WriteString(input.Sdks.GoDocs)
b.WriteString(`)
**Version**: `)
b.WriteString(input.Sdks.GoVersion)
b.WriteString(`
**Go Version**: `)
b.WriteString(input.Sdks.GoCompat)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Sdks.Ruby {
b.WriteString("\n#### Ruby\n```bash\ngem install ")
b.WriteString(input.Sdks.RubyPackage)
b.WriteString("\n```\n\n**Documentation**: [Ruby SDK Guide](")
b.WriteString(input.Sdks.RubyDocs)
b.WriteString(`)
**Version**: `)
b.WriteString(input.Sdks.RubyVersion)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Sdks.CommunityCount != 0 {
b.WriteString(`
### Community SDKs (`)
b.WriteString(strconv.Itoa(input.Sdks.CommunityCount))
b.WriteString(` languages)
`)
b.WriteString(input.Sdks.CommunityList)
b.WriteString(`
*Note: Community SDKs are maintained by third parties and may not be up-to-date.*
`)
}
b.WriteRune('\n')
}
b.WriteString(`
## ๐ง Development Tools
`)
if input.Tools.Postman {
b.WriteString(`
### Postman Collection
Import our complete API collection: [Download Postman Collection](`)
b.WriteString(input.Tools.PostmanUrl)
b.WriteString(`)
**Features**:
- Pre-configured environments
- Authentication setup
- Example requests for all endpoints
`)
}
b.WriteString(`
`)
if input.Tools.Openapi {
b.WriteString(`
### OpenAPI Specification
**OpenAPI 3.0**: [Download Spec](`)
b.WriteString(input.Tools.OpenapiUrl)
b.WriteString(`)
**Swagger UI**: [Interactive Documentation](`)
b.WriteString(input.Tools.SwaggerUrl)
b.WriteString(`)
`)
}
b.WriteString(`
`)
if input.Tools.Insomnia {
b.WriteString(`
### Insomnia Workspace
Import for Insomnia: [Download Workspace](`)
b.WriteString(input.Tools.InsomniaUrl)
b.WriteString(`)
`)
}
return b.String()
}
type SupportAndResources struct {
Support struct {
HasPremium bool
PremiumResponseTime string
PremiumEmail string
PremiumPhone string
PremiumSlack string
Discord string
StackoverflowTag string
GithubIssues string
StatusPage bool
StatusUrl string
SlaUptime string
CurrentStatus string
}
Docs struct {
TutorialsUrl string
BestPracticesUrl string
ChangelogUrl string
Version string
LastUpdated string
}
Api struct {
Version string
}
Company struct {
Name string
}
}
func (input *SupportAndResources) isSupportZero() bool {
return !input.Support.HasPremium &&
input.Support.PremiumResponseTime == "" &&
input.Support.PremiumEmail == "" &&
input.Support.PremiumPhone == "" &&
input.Support.PremiumSlack == "" &&
input.Support.Discord == "" &&
input.Support.StackoverflowTag == "" &&
input.Support.GithubIssues == "" &&
!input.Support.StatusPage &&
input.Support.StatusUrl == "" &&
input.Support.SlaUptime == "" &&
input.Support.CurrentStatus == ""
}
func (input *SupportAndResources) isDocsZero() bool {
return input.Docs.TutorialsUrl == "" &&
input.Docs.BestPracticesUrl == "" &&
input.Docs.ChangelogUrl == "" &&
input.Docs.Version == "" &&
input.Docs.LastUpdated == ""
}
func (input *SupportAndResources) isApiZero() bool {
return input.Api.Version == ""
}
func (input *SupportAndResources) isCompanyZero() bool {
return input.Company.Name == ""
}
func (input *SupportAndResources) String() string {
var b strings.Builder
length := 0
length += 43
if input.Support.HasPremium {
length += 22
length += len(input.Support.PremiumResponseTime)
length += 24
length += len(input.Support.PremiumEmail)
length += 10
length += len(input.Support.PremiumPhone)
length += 10
length += len(input.Support.PremiumSlack)
length += 1
}
length += 36
length += len(input.Support.Discord)
length += 29
length += len(input.Support.StackoverflowTag)
length += 19
length += len(input.Support.GithubIssues)
length += 92
length += len(input.Docs.TutorialsUrl)
length += 23
length += len(input.Docs.BestPracticesUrl)
length += 18
length += len(input.Docs.ChangelogUrl)
length += 2
if input.Support.StatusPage {
length += 46
length += len(input.Support.StatusUrl)
length += 11
length += len(input.Support.SlaUptime)
length += 21
length += len(input.Support.CurrentStatus)
length += 1
}
length += 33
length += len(input.Docs.Version)
length += 19
length += len(input.Docs.LastUpdated)
length += 18
length += len(input.Api.Version)
length += 28
length += len(input.Company.Name)
length += 11
b.Grow(length)
b.WriteString(`## ๐ Getting Help
### Support Channels
`)
if input.Support.HasPremium {
b.WriteString(`
**Premium Support**: `)
b.WriteString(input.Support.PremiumResponseTime)
b.WriteString(` response time
- Email: `)
b.WriteString(input.Support.PremiumEmail)
b.WriteString(`
- Phone: `)
b.WriteString(input.Support.PremiumPhone)
b.WriteString(`
- Slack: `)
b.WriteString(input.Support.PremiumSlack)
b.WriteRune('\n')
}
b.WriteString(`
**Community Support**:
- Discord: `)
b.WriteString(input.Support.Discord)
b.WriteString("\n- Stack Overflow: Tag with `")
b.WriteString(input.Support.StackoverflowTag)
b.WriteString("`\n- GitHub Issues: ")
b.WriteString(input.Support.GithubIssues)
b.WriteString(`
### Documentation Resources
- **API Reference**: You're reading it! ๐
- **Tutorials**: `)
b.WriteString(input.Docs.TutorialsUrl)
b.WriteString(`
- **Best Practices**: `)
b.WriteString(input.Docs.BestPracticesUrl)
b.WriteString(`
- **Changelog**: `)
b.WriteString(input.Docs.ChangelogUrl)
b.WriteString(`
`)
if input.Support.StatusPage {
b.WriteString(`
### Service Status
Check our service status: `)
b.WriteString(input.Support.StatusUrl)
b.WriteString(`
**SLA**: `)
b.WriteString(input.Support.SlaUptime)
b.WriteString(`% uptime
**Status**: `)
b.WriteString(input.Support.CurrentStatus)
b.WriteRune('\n')
}
b.WriteString(`
---
**Documentation Version**: `)
b.WriteString(input.Docs.Version)
b.WriteString(`
**Last Updated**: `)
b.WriteString(input.Docs.LastUpdated)
b.WriteString(`
**API Version**: `)
b.WriteString(input.Api.Version)
b.WriteString(`
*Built with โค๏ธ by the `)
b.WriteString(input.Company.Name)
b.WriteString(` API Team* `)
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package chatagent
import (
"strings"
)
type SystemPrompt struct{}
func (input *SystemPrompt) String() string {
return `You are a friendly assistant named Bob who can help users with their questions.
Do not hallucinate. Do not lie. Do not be rude. Do not be inappropriate.
If you do not know the answer to a question, please say so.`
}
type TitleChat struct {
UserName string
Messages string
}
func (input *TitleChat) String() string {
var b strings.Builder
length := 0
length += 62
length += len(input.UserName)
length += 2
length += len(input.Messages)
length += 8
b.Grow(length)
b.WriteString(`Create a title summarizing the contents of this exchange with `)
b.WriteString(input.UserName)
b.WriteString(`:
`)
b.WriteString(input.Messages)
b.WriteString(`
title: `)
return b.String()
}
type ChatWithUser struct {
PreviousMessages string
AiName string
}
func (input *ChatWithUser) String() string {
var b strings.Builder
length := 0
length += 41
length += len(input.PreviousMessages)
length += 1
length += len(input.AiName)
length += 2
b.Grow(length)
b.WriteString(`Please respond to the chat thread below:
`)
b.WriteString(input.PreviousMessages)
b.WriteRune('\n')
b.WriteString(input.AiName)
b.WriteString(`: `)
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package chatagent2
import (
"strconv"
"strings"
)
type SystemPrompt struct {
AiName string
}
func (input *SystemPrompt) String() string {
var b strings.Builder
length := 0
length += 35
length += len(input.AiName)
length += 281
b.Grow(length)
b.WriteString(`You are a friendly assistant named `)
b.WriteString(input.AiName)
b.WriteString(` who can help users with their questions.
Do not hallucinate. Do not lie. Do not be rude. Do not be inappropriate.
If you do not know the answer to a question, please say so.
2 newlines will produce a newline in the output at the end of the prompt.
This prompt uses the technique.
`)
return b.String()
}
type CreateTitle struct {
UserName string
MessageThread string
}
func (input *CreateTitle) String() string {
var b strings.Builder
length := 0
length += 62
length += len(input.UserName)
length += 2
length += len(input.MessageThread)
length += 8
b.Grow(length)
b.WriteString(`Create a title summarizing the contents of this exchange with `)
b.WriteString(input.UserName)
b.WriteString(`:
`)
b.WriteString(input.MessageThread)
b.WriteString(`
title: `)
return b.String()
}
type ChatWithUser struct {
AiName string
MessageThread string
}
func (input *ChatWithUser) String() string {
var b strings.Builder
length := 0
length += 20
length += len(input.AiName)
length += 43
length += len(input.MessageThread)
length += 1
length += len(input.AiName)
length += 2
b.Grow(length)
b.WriteString(`You are an AI named `)
b.WriteString(input.AiName)
b.WriteString(`. Please respond to the chat thread below:
`)
b.WriteString(input.MessageThread)
b.WriteRune('\n')
b.WriteString(input.AiName)
b.WriteString(`: `)
return b.String()
}
type ExampleWithManyVariables struct {
UserName string
MessageThread string
AiName string
Title string
MaxLineLen string
MoreVariables string
}
func (input *ExampleWithManyVariables) String() string {
var b strings.Builder
length := 0
length += len(input.UserName)
length += 1
length += len(input.MessageThread)
length += 1
length += len(input.AiName)
length += 1
length += len(input.Title)
length += 32
length += len(input.UserName)
length += 15
length += len(input.AiName)
length += 64
length += len(input.MaxLineLen)
length += 13
length += len(input.MoreVariables)
length += 151
b.Grow(length)
b.WriteString(input.UserName)
b.WriteRune('\n')
b.WriteString(input.MessageThread)
b.WriteRune('\n')
b.WriteString(input.AiName)
b.WriteRune('\n')
b.WriteString(input.Title)
b.WriteString(`
As the title says, the user is `)
b.WriteString(input.UserName)
b.WriteString(` and the AI is `)
b.WriteString(input.AiName)
b.WriteString(`.
The default max line length is 80 characters. It is currently `)
b.WriteString(input.MaxLineLen)
b.WriteString(`.
Sometimes, `)
b.WriteString(input.MoreVariables)
b.WriteString(` are needed.
When the max line length is surpassed, AgentFlow will wrap the line.
This only applies to function headers. Prompt bodies are not wrapped.`)
return b.String()
}
type ConditionalPrompting struct {
User struct {
Email string
}
}
func (input *ConditionalPrompting) isUserZero() bool {
return input.User.Email == ""
}
func (input *ConditionalPrompting) String() string {
var b strings.Builder
length := 0
length += 64
if input.User.Email != "" {
length += 21
length += len(input.User.Email)
length += 2
}
b.Grow(length)
b.WriteString(`This prompt demonstrates conditional prompting using optionals.
`)
if input.User.Email != "" {
b.WriteString(`
The user's email is `)
b.WriteString(input.User.Email)
b.WriteString(`.
`)
}
return b.String()
}
type ConditionalWithElse struct {
User struct {
Premium bool
Subscription struct {
Tier int
}
}
}
func (input *ConditionalWithElse) isUserZero() bool {
return !input.User.Premium &&
input.isUserSubscriptionZero()
}
func (input *ConditionalWithElse) isUserSubscriptionZero() bool {
return input.User.Subscription.Tier == 0
}
func (input *ConditionalWithElse) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.User.Subscription.Tier)
length := 0
length += 36
if input.User.Premium {
length += 88
length += len(var0)
length += 34
length += len(var0)
length += 2
} else {
length += 80
}
b.Grow(length)
b.WriteString(`Here's an example with else syntax:
`)
if input.User.Premium {
b.WriteString(`
Welcome premium user! You have access to all features.
Your subscription tier is level `)
b.WriteString(var0)
b.WriteString(`.
Once again, that tier number is `)
b.WriteString(var0)
b.WriteString(`.
`)
} else {
b.WriteString(`
Welcome! You're using the basic version. Upgrade to premium for more features.
`)
}
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package ditto
import (
"strings"
)
type SystemPrompt struct{}
func (input *SystemPrompt) String() string {
return `You are a friendly AI named Ditto here to help the user who is your best friend.`
}
type MainChatTemplate struct {
Tools string
Examples string
Memory struct {
Long string
Short string
}
Script struct {
Name string
Type string
}
User struct {
Name string
Prompt string
}
CurrentTime string
}
func (input *MainChatTemplate) isMemoryZero() bool {
return input.Memory.Long == "" &&
input.Memory.Short == ""
}
func (input *MainChatTemplate) isScriptZero() bool {
return input.Script.Name == "" &&
input.Script.Type == ""
}
func (input *MainChatTemplate) isUserZero() bool {
return input.User.Name == "" &&
input.User.Prompt == ""
}
func (input *MainChatTemplate) String() string {
var b strings.Builder
length := 0
length += 205
if input.Tools != "" {
length += 20
length += len(input.Tools)
length += 1
}
length += 2
if input.Examples != "" {
length += 67
length += len(input.Examples)
length += 20
}
length += 2
if input.Memory.Long != "" {
length += 255
length += len(input.Memory.Long)
length += 28
}
length += 2
if input.Memory.Short != "" {
length += 248
length += len(input.Memory.Short)
length += 29
}
length += 2
if input.Script.Name != "" {
length += 20
length += len(input.Script.Name)
length += 74
length += len(input.Script.Type)
length += 92
length += len(input.Script.Type)
length += 147
}
length += 15
length += len(input.User.Name)
length += 34
length += len(input.CurrentTime)
length += 16
length += len(input.User.Prompt)
length += 8
b.Grow(length)
b.WriteString(`The following is a conversation between an AI named Ditto and a human that are best friends. Ditto is helpful and answers factual questions correctly but maintains a friendly relationship with the human.
`)
if input.Tools != "" {
b.WriteString(`
## Available Tools
`)
b.WriteString(input.Tools)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Examples != "" {
b.WriteString(`
## Examples of User Prompts that need tools:
-- Begin Examples --
`)
b.WriteString(input.Examples)
b.WriteString(`
-- End Examples --
`)
}
b.WriteString(`
`)
if input.Memory.Long != "" {
b.WriteString(`
## Long Term Memory
- Relevant prompt/response pairs from the user's prompt history are indexed using cosine similarity and are shown below as Long Term Memory.
Long Term Memory Buffer (most relevant prompt/response pairs):
-- Begin Long Term Memory --
`)
b.WriteString(input.Memory.Long)
b.WriteString(`
-- End Long Term Memory --
`)
}
b.WriteString(`
`)
if input.Memory.Short != "" {
b.WriteString(`
## Short Term Memory
- The most recent prompt/response pairs are shown below as Short Term Memory. This is usually 5-10 most recent prompt/response pairs.
Short Term Memory Buffer (most recent prompt/response pairs):
-- Begin Short Term Memory --
`)
b.WriteString(input.Memory.Short)
b.WriteString(`
-- End Short Term Memory --
`)
}
b.WriteString(`
`)
if input.Script.Name != "" {
b.WriteString(`
## Current Script: `)
b.WriteString(input.Script.Name)
b.WriteString(`
- If you are reading this, that means the user is currently working on a `)
b.WriteString(input.Script.Type)
b.WriteString(` script. Please send any requests from the user to the respective agent/tool for the user's `)
b.WriteString(input.Script.Type)
b.WriteString(` script.
- Don't send a user's prompt to the tool if they are obviously asking you something off topic to the current script or chatting with you.
`)
}
b.WriteString(`
User's Name: `)
b.WriteString(input.User.Name)
b.WriteString(`
Current Time in User's Timezone: `)
b.WriteString(input.CurrentTime)
b.WriteString(`
User's Prompt: `)
b.WriteString(input.User.Prompt)
b.WriteString(`
Ditto:
`)
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package storyassistant
import (
"strconv"
"strings"
)
type SystemPrompt struct{}
func (input *SystemPrompt) String() string {
return `You are CreativeWriter Pro, a versatile AI writing assistant specializing in storytelling, creative fiction, and narrative development. You adapt your style and guidance based on genre, target audience, and the writer's experience level.`
}
type WritingSessionIntroduction struct {
Writer struct {
Name string
Experience string
FavoriteGenres string
CurrentStreak int
}
Session struct {
Goal string
TargetWords int
}
Project struct {
Title string
Genre string
Audience string
CurrentWords int
CompletionPercentage int
}
}
func (input *WritingSessionIntroduction) isWriterZero() bool {
return input.Writer.Name == "" &&
input.Writer.Experience == "" &&
input.Writer.FavoriteGenres == "" &&
input.Writer.CurrentStreak == 0
}
func (input *WritingSessionIntroduction) isSessionZero() bool {
return input.Session.Goal == "" &&
input.Session.TargetWords == 0
}
func (input *WritingSessionIntroduction) isProjectZero() bool {
return input.Project.Title == "" &&
input.Project.Genre == "" &&
input.Project.Audience == "" &&
input.Project.CurrentWords == 0 &&
input.Project.CompletionPercentage == 0
}
func (input *WritingSessionIntroduction) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Session.TargetWords)
var1 := strconv.Itoa(input.Project.CurrentWords)
length := 0
length += 49
length += len(input.Writer.Name)
length += 84
length += len(input.Writer.Experience)
length += 25
length += len(input.Writer.FavoriteGenres)
length += 21
length += len(input.Session.Goal)
length += 26
length += len(var0)
length += 8
if input.Writer.CurrentStreak != 0 {
length += 26
length += len(strconv.Itoa(input.Writer.CurrentStreak))
length += 20
if input.Writer.CurrentStreak >= 30 {
length += 67
}
length += 37
length += len(input.Project.Title)
length += 12
length += len(input.Project.Genre)
length += 22
length += len(input.Project.Audience)
length += 21
length += len(var1)
length += 8
if input.Project.CompletionPercentage != 0 {
length += 15
length += len(strconv.Itoa(input.Project.CompletionPercentage))
length += 12
if input.Project.CompletionPercentage >= 75 {
length += 53
}
length += 2
if input.Project.CompletionPercentage < 25 {
length += 65
}
length += 1
}
}
b.Grow(length)
b.WriteString(`# โ๏ธ Creative Writing Session
Welcome back, `)
b.WriteString(input.Writer.Name)
b.WriteString(`! Let's bring your stories to life.
## ๐ค Writer Profile
- **Experience Level**: `)
b.WriteString(input.Writer.Experience)
b.WriteString(`
- **Preferred Genres**: `)
b.WriteString(input.Writer.FavoriteGenres)
b.WriteString(`
- **Writing Goal**: `)
b.WriteString(input.Session.Goal)
b.WriteString(`
- **Target Word Count**: `)
b.WriteString(var0)
b.WriteString(` words
`)
if input.Writer.CurrentStreak != 0 {
b.WriteString(`
๐ฅ **Writing Streak**: `)
b.WriteString(strconv.Itoa(input.Writer.CurrentStreak))
b.WriteString(` days! Keep it up!
`)
if input.Writer.CurrentStreak >= 30 {
b.WriteString(`
๐ **Master Writer**: 30+ day streak! You're a writing machine!
`)
}
b.WriteString(`
## ๐ Current Project
**Title**: `)
b.WriteString(input.Project.Title)
b.WriteString(`
**Genre**: `)
b.WriteString(input.Project.Genre)
b.WriteString(`
**Target Audience**: `)
b.WriteString(input.Project.Audience)
b.WriteString(`
**Current Length**: `)
b.WriteString(var1)
b.WriteString(` words
`)
if input.Project.CompletionPercentage != 0 {
b.WriteString(`
**Progress**: `)
b.WriteString(strconv.Itoa(input.Project.CompletionPercentage))
b.WriteString(`% complete
`)
if input.Project.CompletionPercentage >= 75 {
b.WriteString(`
๐ **Almost there!** You're in the final stretch!
`)
}
b.WriteString(`
`)
if input.Project.CompletionPercentage < 25 {
b.WriteString(`
๐ฑ **Just getting started** - The hardest part is behind you!
`)
}
b.WriteRune('\n')
}
}
return b.String()
}
type GenreSpecificGuidance struct {
Project struct {
Genre string
}
Fantasy struct {
WorldComplexity string
MagicSystem string
TimePeriod string
Creatures string
Locations string
Conflicts string
HasMagicRules bool
MagicRules string
MagicLimitations string
MagicConsequences string
}
Scifi struct {
Subgenre string
TechnologyLevel string
Setting string
Technologies string
ScienceFocus string
Themes string
HasTimeTravel bool
TimeTravelType string
TimeTravelRules string
ParadoxApproach string
}
Mystery struct {
Type string
ProtagonistType string
CrimeType string
ClueCount int
TotalClues int
RedHerrings int
SuspectCount int
RemainingClues int
Suspect1 string
Motive1 string
Suspect2 string
Motive2 string
Suspect3 string
Motive3 string
}
Romance struct {
Subgenre string
HeatLevel string
MainTrope string
ProtagonistName string
LoveInterestName string
MeetCute string
ConflictType string
ConflictSource string
ResolutionApproach string
}
}
func (input *GenreSpecificGuidance) isProjectZero() bool {
return input.Project.Genre == ""
}
func (input *GenreSpecificGuidance) isFantasyZero() bool {
return input.Fantasy.WorldComplexity == "" &&
input.Fantasy.MagicSystem == "" &&
input.Fantasy.TimePeriod == "" &&
input.Fantasy.Creatures == "" &&
input.Fantasy.Locations == "" &&
input.Fantasy.Conflicts == "" &&
!input.Fantasy.HasMagicRules &&
input.Fantasy.MagicRules == "" &&
input.Fantasy.MagicLimitations == "" &&
input.Fantasy.MagicConsequences == ""
}
func (input *GenreSpecificGuidance) isScifiZero() bool {
return input.Scifi.Subgenre == "" &&
input.Scifi.TechnologyLevel == "" &&
input.Scifi.Setting == "" &&
input.Scifi.Technologies == "" &&
input.Scifi.ScienceFocus == "" &&
input.Scifi.Themes == "" &&
!input.Scifi.HasTimeTravel &&
input.Scifi.TimeTravelType == "" &&
input.Scifi.TimeTravelRules == "" &&
input.Scifi.ParadoxApproach == ""
}
func (input *GenreSpecificGuidance) isMysteryZero() bool {
return input.Mystery.Type == "" &&
input.Mystery.ProtagonistType == "" &&
input.Mystery.CrimeType == "" &&
input.Mystery.ClueCount == 0 &&
input.Mystery.TotalClues == 0 &&
input.Mystery.RedHerrings == 0 &&
input.Mystery.SuspectCount == 0 &&
input.Mystery.RemainingClues == 0 &&
input.Mystery.Suspect1 == "" &&
input.Mystery.Motive1 == "" &&
input.Mystery.Suspect2 == "" &&
input.Mystery.Motive2 == "" &&
input.Mystery.Suspect3 == "" &&
input.Mystery.Motive3 == ""
}
func (input *GenreSpecificGuidance) isRomanceZero() bool {
return input.Romance.Subgenre == "" &&
input.Romance.HeatLevel == "" &&
input.Romance.MainTrope == "" &&
input.Romance.ProtagonistName == "" &&
input.Romance.LoveInterestName == "" &&
input.Romance.MeetCute == "" &&
input.Romance.ConflictType == "" &&
input.Romance.ConflictSource == "" &&
input.Romance.ResolutionApproach == ""
}
func (input *GenreSpecificGuidance) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Mystery.ClueCount)
var1 := strconv.Itoa(input.Mystery.TotalClues)
var2 := strconv.Itoa(input.Mystery.RedHerrings)
var3 := strconv.Itoa(input.Mystery.SuspectCount)
var4 := strconv.Itoa(input.Mystery.RemainingClues)
length := 0
if input.Project.Genre == "fantasy" {
length += 66
length += len(input.Fantasy.WorldComplexity)
length += 19
length += len(input.Fantasy.MagicSystem)
length += 18
length += len(input.Fantasy.TimePeriod)
length += 51
length += len(input.Fantasy.Creatures)
length += 18
length += len(input.Fantasy.Locations)
length += 18
length += len(input.Fantasy.Conflicts)
length += 2
if input.Fantasy.HasMagicRules {
length += 28
length += len(input.Fantasy.MagicRules)
length += 25
length += len(input.Fantasy.MagicLimitations)
length += 19
length += len(input.Fantasy.MagicConsequences)
length += 1
}
length += 150
}
length += 2
if input.Project.Genre == "sci-fi" {
length += 54
length += len(input.Scifi.Subgenre)
length += 17
length += len(input.Scifi.TechnologyLevel)
length += 14
length += len(input.Scifi.Setting)
length += 41
length += len(input.Scifi.Technologies)
length += 28
length += len(input.Scifi.ScienceFocus)
length += 22
length += len(input.Scifi.Themes)
length += 2
if input.Scifi.HasTimeTravel {
length += 41
length += len(input.Scifi.TimeTravelType)
length += 12
length += len(input.Scifi.TimeTravelRules)
length += 23
length += len(input.Scifi.ParadoxApproach)
length += 1
}
length += 138
}
length += 2
if input.Project.Genre == "mystery" {
length += 49
length += len(input.Mystery.Type)
length += 16
length += len(input.Mystery.ProtagonistType)
length += 12
length += len(input.Mystery.CrimeType)
length += 46
length += len(var0)
length += 1
length += len(var1)
length += 21
length += len(var2)
length += 17
length += len(var3)
length += 2
if input.Mystery.ClueCount < input.Mystery.TotalClues {
length += 48
length += len(var4)
length += 13
}
length += 27
length += len(input.Mystery.Suspect1)
length += 11
length += len(input.Mystery.Motive1)
length += 4
length += len(input.Mystery.Suspect2)
length += 11
length += len(input.Mystery.Motive2)
length += 4
length += len(input.Mystery.Suspect3)
length += 11
length += len(input.Mystery.Motive3)
length += 130
}
length += 2
if input.Project.Genre == "romance" {
length += 49
length += len(input.Romance.Subgenre)
length += 17
length += len(input.Romance.HeatLevel)
length += 12
length += len(input.Romance.MainTrope)
length += 48
length += len(input.Romance.ProtagonistName)
length += 22
length += len(input.Romance.LoveInterestName)
length += 18
length += len(input.Romance.MeetCute)
length += 2
if input.Romance.ConflictType != "" {
length += 32
length += len(input.Romance.ConflictType)
length += 13
length += len(input.Romance.ConflictSource)
length += 26
length += len(input.Romance.ResolutionApproach)
length += 1
}
length += 132
}
b.Grow(length)
if input.Project.Genre == "fantasy" {
b.WriteString(`
## ๐งโโ๏ธ Fantasy Writing Mode
**World-Building Focus**: `)
b.WriteString(input.Fantasy.WorldComplexity)
b.WriteString(`
**Magic System**: `)
b.WriteString(input.Fantasy.MagicSystem)
b.WriteString(`
**Setting Era**: `)
b.WriteString(input.Fantasy.TimePeriod)
b.WriteString(`
### Fantasy Elements Checklist:
- **Creatures**: `)
b.WriteString(input.Fantasy.Creatures)
b.WriteString(`
- **Locations**: `)
b.WriteString(input.Fantasy.Locations)
b.WriteString(`
- **Conflicts**: `)
b.WriteString(input.Fantasy.Conflicts)
b.WriteString(`
`)
if input.Fantasy.HasMagicRules {
b.WriteString(`
### โก Magic System Rules
`)
b.WriteString(input.Fantasy.MagicRules)
b.WriteString(`
**Power Limitations**: `)
b.WriteString(input.Fantasy.MagicLimitations)
b.WriteString(`
**Consequences**: `)
b.WriteString(input.Fantasy.MagicConsequences)
b.WriteRune('\n')
}
b.WriteString(`
**Writing Tip**: In fantasy, consistency in world-building is key. Make sure your magic system and world rules stay coherent throughout your story.
`)
}
b.WriteString(`
`)
if input.Project.Genre == "sci-fi" {
b.WriteString(`
## ๐ Science Fiction Writing Mode
**Sub-genre**: `)
b.WriteString(input.Scifi.Subgenre)
b.WriteString(`
**Tech Level**: `)
b.WriteString(input.Scifi.TechnologyLevel)
b.WriteString(`
**Setting**: `)
b.WriteString(input.Scifi.Setting)
b.WriteString(`
### Sci-Fi Elements:
- **Technology**: `)
b.WriteString(input.Scifi.Technologies)
b.WriteString(`
- **Scientific Concepts**: `)
b.WriteString(input.Scifi.ScienceFocus)
b.WriteString(`
- **Social Issues**: `)
b.WriteString(input.Scifi.Themes)
b.WriteString(`
`)
if input.Scifi.HasTimeTravel {
b.WriteString(`
### โฐ Time Travel Mechanics
**Type**: `)
b.WriteString(input.Scifi.TimeTravelType)
b.WriteString(`
**Rules**: `)
b.WriteString(input.Scifi.TimeTravelRules)
b.WriteString(`
**Paradox Handling**: `)
b.WriteString(input.Scifi.ParadoxApproach)
b.WriteRune('\n')
}
b.WriteString(`
**Writing Tip**: Great sci-fi isn't just about the technologyโit's about how that technology affects human relationships and society.
`)
}
b.WriteString(`
`)
if input.Project.Genre == "mystery" {
b.WriteString(`
## ๐ Mystery Writing Mode
**Mystery Type**: `)
b.WriteString(input.Mystery.Type)
b.WriteString(`
**Detective**: `)
b.WriteString(input.Mystery.ProtagonistType)
b.WriteString(`
**Crime**: `)
b.WriteString(input.Mystery.CrimeType)
b.WriteString(`
### Mystery Structure:
- **Clues Planted**: `)
b.WriteString(var0)
b.WriteString(`/`)
b.WriteString(var1)
b.WriteString(`
- **Red Herrings**: `)
b.WriteString(var2)
b.WriteString(`
- **Suspects**: `)
b.WriteString(var3)
b.WriteString(`
`)
if input.Mystery.ClueCount < input.Mystery.TotalClues {
b.WriteString(`
โ ๏ธ **Clue Alert**: You still need to plant `)
b.WriteString(var4)
b.WriteString(` more clues!
`)
}
b.WriteString(`
### Current Suspects:
1. `)
b.WriteString(input.Mystery.Suspect1)
b.WriteString(` - Motive: `)
b.WriteString(input.Mystery.Motive1)
b.WriteString(`
2. `)
b.WriteString(input.Mystery.Suspect2)
b.WriteString(` - Motive: `)
b.WriteString(input.Mystery.Motive2)
b.WriteString(`
3. `)
b.WriteString(input.Mystery.Suspect3)
b.WriteString(` - Motive: `)
b.WriteString(input.Mystery.Motive3)
b.WriteString(`
**Writing Tip**: Play fair with your readersโgive them all the clues they need to solve the mystery alongside your detective.
`)
}
b.WriteString(`
`)
if input.Project.Genre == "romance" {
b.WriteString(`
## ๐ Romance Writing Mode
**Romance Type**: `)
b.WriteString(input.Romance.Subgenre)
b.WriteString(`
**Heat Level**: `)
b.WriteString(input.Romance.HeatLevel)
b.WriteString(`
**Trope**: `)
b.WriteString(input.Romance.MainTrope)
b.WriteString(`
### Character Development:
- **Protagonist**: `)
b.WriteString(input.Romance.ProtagonistName)
b.WriteString(`
- **Love Interest**: `)
b.WriteString(input.Romance.LoveInterestName)
b.WriteString(`
- **Meet-Cute**: `)
b.WriteString(input.Romance.MeetCute)
b.WriteString(`
`)
if input.Romance.ConflictType != "" {
b.WriteString(`
### Central Conflict
**Type**: `)
b.WriteString(input.Romance.ConflictType)
b.WriteString(`
**Source**: `)
b.WriteString(input.Romance.ConflictSource)
b.WriteString(`
**Resolution Strategy**: `)
b.WriteString(input.Romance.ResolutionApproach)
b.WriteRune('\n')
}
b.WriteString(`
**Writing Tip**: Great romance is built on emotional truth. Make sure both characters grow and change through their relationship.
`)
}
return b.String()
}
type CharacterDevelopmentWorkshop struct {
Characters struct {
MainCharacter struct {
Name string
Archetype string
Flaw string
Desire string
Arc string
BackstoryComplete bool
NeedsDevelopment bool
WeakAreas string
}
Antagonist struct {
Name string
Type string
Motivation string
Methods string
Sympathetic bool
ConflictStyle string
}
SupportingCast int
Support1 struct {
Name string
Role string
}
Support2 struct {
Name string
Role string
}
Support3 struct {
Name string
Role string
}
}
}
func (input *CharacterDevelopmentWorkshop) isCharactersZero() bool {
return input.isCharactersMainCharacterZero() &&
input.isCharactersAntagonistZero() &&
input.Characters.SupportingCast == 0 &&
input.isCharactersSupport1Zero() &&
input.isCharactersSupport2Zero() &&
input.isCharactersSupport3Zero()
}
func (input *CharacterDevelopmentWorkshop) isCharactersMainCharacterZero() bool {
return input.Characters.MainCharacter.Name == "" &&
input.Characters.MainCharacter.Archetype == "" &&
input.Characters.MainCharacter.Flaw == "" &&
input.Characters.MainCharacter.Desire == "" &&
input.Characters.MainCharacter.Arc == "" &&
!input.Characters.MainCharacter.BackstoryComplete &&
!input.Characters.MainCharacter.NeedsDevelopment &&
input.Characters.MainCharacter.WeakAreas == ""
}
func (input *CharacterDevelopmentWorkshop) isCharactersAntagonistZero() bool {
return input.Characters.Antagonist.Name == "" &&
input.Characters.Antagonist.Type == "" &&
input.Characters.Antagonist.Motivation == "" &&
input.Characters.Antagonist.Methods == "" &&
!input.Characters.Antagonist.Sympathetic &&
input.Characters.Antagonist.ConflictStyle == ""
}
func (input *CharacterDevelopmentWorkshop) isCharactersSupport1Zero() bool {
return input.Characters.Support1.Name == "" &&
input.Characters.Support1.Role == ""
}
func (input *CharacterDevelopmentWorkshop) isCharactersSupport2Zero() bool {
return input.Characters.Support2.Name == "" &&
input.Characters.Support2.Role == ""
}
func (input *CharacterDevelopmentWorkshop) isCharactersSupport3Zero() bool {
return input.Characters.Support3.Name == "" &&
input.Characters.Support3.Role == ""
}
func (input *CharacterDevelopmentWorkshop) String() string {
var b strings.Builder
length := 0
length += 28
if !input.isCharactersMainCharacterZero() {
length += 18
length += len(input.Characters.MainCharacter.Name)
length += 17
length += len(input.Characters.MainCharacter.Archetype)
length += 17
length += len(input.Characters.MainCharacter.Flaw)
length += 21
length += len(input.Characters.MainCharacter.Desire)
length += 17
length += len(input.Characters.MainCharacter.Arc)
length += 2
if input.Characters.MainCharacter.BackstoryComplete {
length += 55
}
length += 2
if input.Characters.MainCharacter.NeedsDevelopment {
length += 61
length += len(input.Characters.MainCharacter.WeakAreas)
length += 1
}
length += 1
}
length += 2
if !input.isCharactersAntagonistZero() {
length += 17
length += len(input.Characters.Antagonist.Name)
length += 12
length += len(input.Characters.Antagonist.Type)
length += 17
length += len(input.Characters.Antagonist.Motivation)
length += 14
length += len(input.Characters.Antagonist.Methods)
length += 2
if input.Characters.Antagonist.Sympathetic {
length += 92
}
length += 22
length += len(input.Characters.Antagonist.ConflictStyle)
length += 1
}
length += 2
if input.Characters.SupportingCast != 0 {
length += 28
length += len(strconv.Itoa(input.Characters.SupportingCast))
length += 9
if input.Characters.SupportingCast > 5 {
length += 109
}
length += 30
length += len(input.Characters.Support1.Name)
length += 2
length += len(input.Characters.Support1.Role)
length += 3
length += len(input.Characters.Support2.Name)
length += 2
length += len(input.Characters.Support2.Role)
length += 3
length += len(input.Characters.Support3.Name)
length += 2
length += len(input.Characters.Support3.Role)
length += 1
}
b.Grow(length)
b.WriteString(`## ๐ฅ Character Analysis
`)
if !input.isCharactersMainCharacterZero() {
b.WriteString(`
### Protagonist: `)
b.WriteString(input.Characters.MainCharacter.Name)
b.WriteString(`
**Archetype**: `)
b.WriteString(input.Characters.MainCharacter.Archetype)
b.WriteString(`
**Fatal Flaw**: `)
b.WriteString(input.Characters.MainCharacter.Flaw)
b.WriteString(`
**Deepest Desire**: `)
b.WriteString(input.Characters.MainCharacter.Desire)
b.WriteString(`
**Growth Arc**: `)
b.WriteString(input.Characters.MainCharacter.Arc)
b.WriteString(`
`)
if input.Characters.MainCharacter.BackstoryComplete {
b.WriteString(`
โ
**Backstory Complete**: Well-developed background
`)
}
b.WriteString(`
`)
if input.Characters.MainCharacter.NeedsDevelopment {
b.WriteString(`
๐ง **Development Needed**: Character needs more depth in: `)
b.WriteString(input.Characters.MainCharacter.WeakAreas)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if !input.isCharactersAntagonistZero() {
b.WriteString(`
### Antagonist: `)
b.WriteString(input.Characters.Antagonist.Name)
b.WriteString(`
**Type**: `)
b.WriteString(input.Characters.Antagonist.Type)
b.WriteString(`
**Motivation**: `)
b.WriteString(input.Characters.Antagonist.Motivation)
b.WriteString(`
**Methods**: `)
b.WriteString(input.Characters.Antagonist.Methods)
b.WriteString(`
`)
if input.Characters.Antagonist.Sympathetic {
b.WriteString(`
๐ก **Sympathetic Villain**: Your antagonist has relatable motivations - this adds depth!
`)
}
b.WriteString(`
**Conflict Style**: `)
b.WriteString(input.Characters.Antagonist.ConflictStyle)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Characters.SupportingCast != 0 {
b.WriteString(`
### Supporting Characters (`)
b.WriteString(strconv.Itoa(input.Characters.SupportingCast))
b.WriteString(` total)
`)
if input.Characters.SupportingCast > 5 {
b.WriteString(`
โ ๏ธ **Character Overload**: You have many supporting characters. Make sure each serves a unique purpose!
`)
}
b.WriteString(`
**Key Supporting Roles**:
- `)
b.WriteString(input.Characters.Support1.Name)
b.WriteString(`: `)
b.WriteString(input.Characters.Support1.Role)
b.WriteString(`
- `)
b.WriteString(input.Characters.Support2.Name)
b.WriteString(`: `)
b.WriteString(input.Characters.Support2.Role)
b.WriteString(`
- `)
b.WriteString(input.Characters.Support3.Name)
b.WriteString(`: `)
b.WriteString(input.Characters.Support3.Role)
b.WriteRune('\n')
}
return b.String()
}
type PlotStructureAnalysis struct {
Plot struct {
StructureType string
CurrentAct int
TotalActs int
IncitingIncident bool
FirstPlotPoint bool
Midpoint bool
Climax bool
Resolution bool
Pacing string
TensionLevel int
}
Scene struct {
Description string
Purpose string
PovCharacter string
Location string
PlotGoal string
CharacterGoal string
EmotionalGoal string
HasConflict bool
ConflictType string
}
}
func (input *PlotStructureAnalysis) isPlotZero() bool {
return input.Plot.StructureType == "" &&
input.Plot.CurrentAct == 0 &&
input.Plot.TotalActs == 0 &&
!input.Plot.IncitingIncident &&
!input.Plot.FirstPlotPoint &&
!input.Plot.Midpoint &&
!input.Plot.Climax &&
!input.Plot.Resolution &&
input.Plot.Pacing == "" &&
input.Plot.TensionLevel == 0
}
func (input *PlotStructureAnalysis) isSceneZero() bool {
return input.Scene.Description == "" &&
input.Scene.Purpose == "" &&
input.Scene.PovCharacter == "" &&
input.Scene.Location == "" &&
input.Scene.PlotGoal == "" &&
input.Scene.CharacterGoal == "" &&
input.Scene.EmotionalGoal == "" &&
!input.Scene.HasConflict &&
input.Scene.ConflictType == ""
}
func (input *PlotStructureAnalysis) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Plot.CurrentAct)
var1 := strconv.Itoa(input.Plot.TotalActs)
var2 := strconv.Itoa(input.Plot.TensionLevel)
length := 0
length += 45
length += len(input.Plot.StructureType)
length += 18
length += len(var0)
length += 1
length += len(var1)
length += 29
if input.Plot.IncitingIncident {
length += 38
}
length += 2
if input.Plot.FirstPlotPoint {
length += 39
}
length += 2
if input.Plot.Midpoint {
length += 29
}
length += 2
if input.Plot.Climax {
length += 27
}
length += 2
if input.Plot.Resolution {
length += 31
}
length += 40
length += len(input.Plot.Pacing)
length += 20
length += len(var2)
length += 5
if input.Plot.TensionLevel < 4 {
length += 84
}
length += 2
if input.Plot.TensionLevel > 8 {
length += 93
}
length += 42
length += len(input.Scene.Description)
length += 14
length += len(input.Scene.Purpose)
length += 20
length += len(input.Scene.PovCharacter)
length += 14
length += len(input.Scene.Location)
length += 49
length += len(input.Scene.PlotGoal)
length += 31
length += len(input.Scene.CharacterGoal)
length += 24
length += len(input.Scene.EmotionalGoal)
length += 2
if input.Scene.HasConflict {
length += 79
length += len(input.Scene.ConflictType)
length += 1
}
b.Grow(length)
b.WriteString(`## ๐ Story Structure
**Structure Type**: `)
b.WriteString(input.Plot.StructureType)
b.WriteString(`
**Current Act**: `)
b.WriteString(var0)
b.WriteString(`/`)
b.WriteString(var1)
b.WriteString(`
### Plot Points Checklist:
`)
if input.Plot.IncitingIncident {
b.WriteString(`
โ
**Inciting Incident**: Completed
`)
}
b.WriteString(`
`)
if input.Plot.FirstPlotPoint {
b.WriteString(`
โ
**First Plot Point**: Completed
`)
}
b.WriteString(`
`)
if input.Plot.Midpoint {
b.WriteString(`
โ
**Midpoint**: Completed
`)
}
b.WriteString(`
`)
if input.Plot.Climax {
b.WriteString(`
โ
**Climax**: Completed
`)
}
b.WriteString(`
`)
if input.Plot.Resolution {
b.WriteString(`
โ
**Resolution**: Completed
`)
}
b.WriteString(`
### Pacing Analysis
**Current Pace**: `)
b.WriteString(input.Plot.Pacing)
b.WriteString(`
**Tension Level**: `)
b.WriteString(var2)
b.WriteString(`/10
`)
if input.Plot.TensionLevel < 4 {
b.WriteString(`
๐ **Pacing Note**: Consider adding more conflict or stakes to increase tension.
`)
}
b.WriteString(`
`)
if input.Plot.TensionLevel > 8 {
b.WriteString(`
โ ๏ธ **High Intensity**: Make sure to give readers breathing room between intense scenes.
`)
}
b.WriteString(`
## ๐ฏ Scene Goals
**Today's Scene**: `)
b.WriteString(input.Scene.Description)
b.WriteString(`
**Purpose**: `)
b.WriteString(input.Scene.Purpose)
b.WriteString(`
**POV Character**: `)
b.WriteString(input.Scene.PovCharacter)
b.WriteString(`
**Setting**: `)
b.WriteString(input.Scene.Location)
b.WriteString(`
### Scene Objectives:
1. **Plot Advancement**: `)
b.WriteString(input.Scene.PlotGoal)
b.WriteString(`
2. **Character Development**: `)
b.WriteString(input.Scene.CharacterGoal)
b.WriteString(`
3. **Emotional Beat**: `)
b.WriteString(input.Scene.EmotionalGoal)
b.WriteString(`
`)
if input.Scene.HasConflict {
b.WriteString(`
โ
**Conflict Present**: Good! Every scene needs tension.
**Conflict Type**: `)
b.WriteString(input.Scene.ConflictType)
b.WriteRune('\n')
}
return b.String()
}
type WritingProductivityDashboard struct {
Session struct {
DailyGoal int
WordsWritten int
ProgressPercentage int
BonusWords int
StartTime string
EndTime string
NextGoal string
}
Motivation struct {
Tip string
}
Stats struct {
WordsPerMinute int
SessionMinutes int
BreakMinutes int
WritingSpeedTrend string
}
Prompts struct {
HasCustom bool
CustomPrompt string
CustomReason string
GeneralSuggestions string
CharacterExercise string
DialogueChallenge string
WorldbuildingPrompt string
}
Tools struct {
GrammarCheck bool
ResearchNeeded bool
ResearchTopics string
}
Writer struct {
Experience string
Name string
}
Tips struct {
BeginnerFocus string
AdvancedChallenge string
}
}
func (input *WritingProductivityDashboard) isSessionZero() bool {
return input.Session.DailyGoal == 0 &&
input.Session.WordsWritten == 0 &&
input.Session.ProgressPercentage == 0 &&
input.Session.BonusWords == 0 &&
input.Session.StartTime == "" &&
input.Session.EndTime == "" &&
input.Session.NextGoal == ""
}
func (input *WritingProductivityDashboard) isMotivationZero() bool {
return input.Motivation.Tip == ""
}
func (input *WritingProductivityDashboard) isStatsZero() bool {
return input.Stats.WordsPerMinute == 0 &&
input.Stats.SessionMinutes == 0 &&
input.Stats.BreakMinutes == 0 &&
input.Stats.WritingSpeedTrend == ""
}
func (input *WritingProductivityDashboard) isPromptsZero() bool {
return !input.Prompts.HasCustom &&
input.Prompts.CustomPrompt == "" &&
input.Prompts.CustomReason == "" &&
input.Prompts.GeneralSuggestions == "" &&
input.Prompts.CharacterExercise == "" &&
input.Prompts.DialogueChallenge == "" &&
input.Prompts.WorldbuildingPrompt == ""
}
func (input *WritingProductivityDashboard) isToolsZero() bool {
return !input.Tools.GrammarCheck &&
!input.Tools.ResearchNeeded &&
input.Tools.ResearchTopics == ""
}
func (input *WritingProductivityDashboard) isWriterZero() bool {
return input.Writer.Experience == "" &&
input.Writer.Name == ""
}
func (input *WritingProductivityDashboard) isTipsZero() bool {
return input.Tips.BeginnerFocus == "" &&
input.Tips.AdvancedChallenge == ""
}
func (input *WritingProductivityDashboard) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Session.DailyGoal)
var1 := strconv.Itoa(input.Session.WordsWritten)
var2 := strconv.Itoa(input.Session.ProgressPercentage)
var3 := strconv.Itoa(input.Stats.WordsPerMinute)
var4 := strconv.Itoa(input.Stats.SessionMinutes)
var5 := strconv.Itoa(input.Stats.BreakMinutes)
length := 0
length += 43
length += len(var0)
length += 29
length += len(var1)
length += 8
length += len(var2)
length += 4
if input.Session.ProgressPercentage >= 100 {
length += 48
if input.Session.BonusWords != 0 {
length += 19
length += len(strconv.Itoa(input.Session.BonusWords))
length += 23
}
length += 1
}
length += 2
if input.Session.ProgressPercentage < 50 {
length += 75
length += len(input.Motivation.Tip)
length += 1
}
length += 47
length += len(var3)
length += 38
length += len(var4)
length += 27
length += len(var5)
length += 10
if input.Stats.WritingSpeedTrend != "" {
length += 18
length += len(input.Stats.WritingSpeedTrend)
length += 25
}
length += 41
if input.Prompts.HasCustom {
length += 34
length += len(input.Prompts.CustomPrompt)
length += 32
length += len(input.Prompts.CustomReason)
length += 1
}
length += 2
if input.Prompts.GeneralSuggestions != "" {
length += 58
length += len(input.Prompts.CharacterExercise)
length += 27
length += len(input.Prompts.DialogueChallenge)
length += 23
length += len(input.Prompts.WorldbuildingPrompt)
length += 1
}
length += 32
if input.Tools.GrammarCheck {
length += 90
}
length += 2
if input.Tools.ResearchNeeded {
length += 55
length += len(input.Tools.ResearchTopics)
length += 1
}
length += 2
if input.Writer.Experience == "beginner" {
length += 203
length += len(input.Tips.BeginnerFocus)
length += 1
}
length += 2
if input.Writer.Experience == "advanced" {
length += 170
length += len(input.Tips.AdvancedChallenge)
length += 1
}
length += 24
length += len(input.Session.StartTime)
length += 3
length += len(input.Session.EndTime)
length += 24
length += len(input.Session.NextGoal)
length += 17
length += len(input.Writer.Name)
length += 45
b.Grow(length)
b.WriteString(`## ๐ Writing Metrics
**Today's Goal**: `)
b.WriteString(var0)
b.WriteString(` words
**Current Progress**: `)
b.WriteString(var1)
b.WriteString(` words (`)
b.WriteString(var2)
b.WriteString(`%)
`)
if input.Session.ProgressPercentage >= 100 {
b.WriteString(`
๐ **Goal Achieved!** Fantastic work today!
`)
if input.Session.BonusWords != 0 {
b.WriteString(`
**Bonus Words**: +`)
b.WriteString(strconv.Itoa(input.Session.BonusWords))
b.WriteString(` words over your goal!
`)
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Session.ProgressPercentage < 50 {
b.WriteString(`
๐ช **Keep Going**: You're halfway to your goal!
**Motivational Tip**: `)
b.WriteString(input.Motivation.Tip)
b.WriteRune('\n')
}
b.WriteString(`
### Writing Statistics:
- **Writing Speed**: `)
b.WriteString(var3)
b.WriteString(` words/minute
- **Session Duration**: `)
b.WriteString(var4)
b.WriteString(` minutes
- **Break Time**: `)
b.WriteString(var5)
b.WriteString(` minutes
`)
if input.Stats.WritingSpeedTrend != "" {
b.WriteString(`
**Speed Trend**: `)
b.WriteString(input.Stats.WritingSpeedTrend)
b.WriteString(` (compared to last week)
`)
}
b.WriteString(`
## ๐จ Writing Prompts & Inspiration
`)
if input.Prompts.HasCustom {
b.WriteString(`
### Personalized Prompt for You:
`)
b.WriteString(input.Prompts.CustomPrompt)
b.WriteString(`
**Why this fits your style**: `)
b.WriteString(input.Prompts.CustomReason)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Prompts.GeneralSuggestions != "" {
b.WriteString(`
### General Writing Exercises:
- **Character Exercise**: `)
b.WriteString(input.Prompts.CharacterExercise)
b.WriteString(`
- **Dialogue Challenge**: `)
b.WriteString(input.Prompts.DialogueChallenge)
b.WriteString(`
- **World-Building**: `)
b.WriteString(input.Prompts.WorldbuildingPrompt)
b.WriteRune('\n')
}
b.WriteString(`
## ๐ง Writing Tools & Tips
`)
if input.Tools.GrammarCheck {
b.WriteString(`
๐ **Grammar Assistant**: Available - Run a quick check before finishing your session.
`)
}
b.WriteString(`
`)
if input.Tools.ResearchNeeded {
b.WriteString(`
๐ **Research Reminder**: Don't forget to research: `)
b.WriteString(input.Tools.ResearchTopics)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Writer.Experience == "beginner" {
b.WriteString(`
### Beginner Writer Tips:
- Write first, edit later
- Don't worry about perfection in your first draft
- Read extensively in your chosen genre
- Join a writing community for support
**Today's Focus**: `)
b.WriteString(input.Tips.BeginnerFocus)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Writer.Experience == "advanced" {
b.WriteString(`
### Advanced Techniques:
- Experiment with unreliable narrators
- Layer multiple subplots effectively
- Master show vs. tell
- Develop your unique voice
**Challenge**: `)
b.WriteString(input.Tips.AdvancedChallenge)
b.WriteRune('\n')
}
b.WriteString(`
---
**Session Time**: `)
b.WriteString(input.Session.StartTime)
b.WriteString(` - `)
b.WriteString(input.Session.EndTime)
b.WriteString(`
**Next Session Goal**: `)
b.WriteString(input.Session.NextGoal)
b.WriteString(`
*Keep writing, `)
b.WriteString(input.Writer.Name)
b.WriteString(`! Your story is waiting to be told. ๐โจ* `)
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package supportagent
import (
"strconv"
"strings"
)
type SystemPrompt struct{}
func (input *SystemPrompt) String() string {
return `You are SupportBot Pro, an intelligent customer support agent with advanced escalation capabilities. You provide empathetic, efficient support while routing complex issues to appropriate specialists based on priority, customer tier, and issue complexity.`
}
type InitialCustomerGreeting struct {
Ticket struct {
Id string
}
Customer struct {
Name string
Tier string
JoinDate string
TicketHistory struct {
TotalCount int
}
SatisfactionScore int
AccountManager string
ManagerContact string
}
Issue struct {
Category string
Severity string
PriorityLevel int
Timestamp string
IsUrgent bool
}
}
func (input *InitialCustomerGreeting) isTicketZero() bool {
return input.Ticket.Id == ""
}
func (input *InitialCustomerGreeting) isCustomerZero() bool {
return input.Customer.Name == "" &&
input.Customer.Tier == "" &&
input.Customer.JoinDate == "" &&
input.isCustomerTicketHistoryZero() &&
input.Customer.SatisfactionScore == 0 &&
input.Customer.AccountManager == "" &&
input.Customer.ManagerContact == ""
}
func (input *InitialCustomerGreeting) isCustomerTicketHistoryZero() bool {
return input.Customer.TicketHistory.TotalCount == 0
}
func (input *InitialCustomerGreeting) isIssueZero() bool {
return input.Issue.Category == "" &&
input.Issue.Severity == "" &&
input.Issue.PriorityLevel == 0 &&
input.Issue.Timestamp == "" &&
!input.Issue.IsUrgent
}
func (input *InitialCustomerGreeting) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Customer.TicketHistory.TotalCount)
var1 := strconv.Itoa(input.Customer.SatisfactionScore)
var2 := strconv.Itoa(input.Issue.PriorityLevel)
length := 0
length += 34
length += len(input.Ticket.Id)
length += 8
length += len(input.Customer.Name)
length += 76
length += len(input.Customer.Tier)
length += 30
length += len(input.Customer.JoinDate)
length += 25
length += len(var0)
length += 27
length += len(var1)
length += 9
if input.Customer.Tier == "premium" {
length += 95
}
length += 2
if input.Customer.Tier == "enterprise" {
length += 64
length += len(input.Customer.AccountManager)
length += 15
length += len(input.Customer.ManagerContact)
length += 2
}
length += 40
length += len(input.Issue.Category)
length += 17
length += len(input.Issue.Severity)
length += 17
length += len(var2)
length += 19
length += len(input.Issue.Timestamp)
length += 2
if input.Issue.IsUrgent {
length += 85
}
b.Grow(length)
b.WriteString(`# ๐ง Customer Support - Ticket #`)
b.WriteString(input.Ticket.Id)
b.WriteString(`
Hello `)
b.WriteString(input.Customer.Name)
b.WriteString(`! I'm here to help you today.
## ๐ค Customer Profile
- **Account Type**: `)
b.WriteString(input.Customer.Tier)
b.WriteString(` Customer
- **Member Since**: `)
b.WriteString(input.Customer.JoinDate)
b.WriteString(`
- **Previous Tickets**: `)
b.WriteString(var0)
b.WriteString(`
- **Satisfaction Score**: `)
b.WriteString(var1)
b.WriteString(`/10 โญ
`)
if input.Customer.Tier == "premium" {
b.WriteString(`
๐ **Premium Support**: You'll receive priority assistance with our fastest response times.
`)
}
b.WriteString(`
`)
if input.Customer.Tier == "enterprise" {
b.WriteString(`
๐ข **Enterprise Support**: Your dedicated account manager is `)
b.WriteString(input.Customer.AccountManager)
b.WriteString(`, available at `)
b.WriteString(input.Customer.ManagerContact)
b.WriteString(`.
`)
}
b.WriteString(`
## ๐ Issue Details
- **Category**: `)
b.WriteString(input.Issue.Category)
b.WriteString(`
- **Severity**: `)
b.WriteString(input.Issue.Severity)
b.WriteString(`
- **Priority**: `)
b.WriteString(var2)
b.WriteString(`/5
- **Reported**: `)
b.WriteString(input.Issue.Timestamp)
b.WriteString(`
`)
if input.Issue.IsUrgent {
b.WriteString(`
๐จ **URGENT ISSUE DETECTED** - This will be fast-tracked for immediate attention.
`)
}
return b.String()
}
type IssueAnalysisAndRouting struct {
Issue struct {
Description string
Category string
}
Technical struct {
System string
ErrorCode string
Environment string
HasLogs bool
Logs string
ComplexityScore int
EstimatedHours int
AssignedSpecialist string
EstimatedMinutes int
}
Billing struct {
InvoiceId string
Amount float64
PaymentMethod string
DisputeReason string
RequiresRefund bool
RefundAmount float64
RefundDays int
PaymentFailed bool
FailureReason string
NextRetryDate string
CustomerAction string
}
Customer struct {
Tier string
}
Account struct {
IssueType string
Status string
Locked bool
LockReason string
SecurityLevel string
UnlockStep1 string
UnlockStep2 string
UnlockStep3 string
RequiresVerification bool
VerificationDocuments string
SubscriptionChange bool
CurrentPlan string
RequestedPlan string
ChangeDate string
ProrateAmount float64
}
}
func (input *IssueAnalysisAndRouting) isIssueZero() bool {
return input.Issue.Description == "" &&
input.Issue.Category == ""
}
func (input *IssueAnalysisAndRouting) isTechnicalZero() bool {
return input.Technical.System == "" &&
input.Technical.ErrorCode == "" &&
input.Technical.Environment == "" &&
!input.Technical.HasLogs &&
input.Technical.Logs == "" &&
input.Technical.ComplexityScore == 0 &&
input.Technical.EstimatedHours == 0 &&
input.Technical.AssignedSpecialist == "" &&
input.Technical.EstimatedMinutes == 0
}
func (input *IssueAnalysisAndRouting) isBillingZero() bool {
return input.Billing.InvoiceId == "" &&
input.Billing.Amount == 0 &&
input.Billing.PaymentMethod == "" &&
input.Billing.DisputeReason == "" &&
!input.Billing.RequiresRefund &&
input.Billing.RefundAmount == 0 &&
input.Billing.RefundDays == 0 &&
!input.Billing.PaymentFailed &&
input.Billing.FailureReason == "" &&
input.Billing.NextRetryDate == "" &&
input.Billing.CustomerAction == ""
}
func (input *IssueAnalysisAndRouting) isCustomerZero() bool {
return input.Customer.Tier == ""
}
func (input *IssueAnalysisAndRouting) isAccountZero() bool {
return input.Account.IssueType == "" &&
input.Account.Status == "" &&
!input.Account.Locked &&
input.Account.LockReason == "" &&
input.Account.SecurityLevel == "" &&
input.Account.UnlockStep1 == "" &&
input.Account.UnlockStep2 == "" &&
input.Account.UnlockStep3 == "" &&
!input.Account.RequiresVerification &&
input.Account.VerificationDocuments == "" &&
!input.Account.SubscriptionChange &&
input.Account.CurrentPlan == "" &&
input.Account.RequestedPlan == "" &&
input.Account.ChangeDate == "" &&
input.Account.ProrateAmount == 0
}
func (input *IssueAnalysisAndRouting) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Technical.EstimatedHours)
var1 := strconv.Itoa(input.Technical.EstimatedMinutes)
var2 := strconv.FormatFloat(input.Billing.Amount, 'g', -1, 64)
var3 := strconv.FormatFloat(input.Billing.RefundAmount, 'g', -1, 64)
var4 := strconv.Itoa(input.Billing.RefundDays)
var5 := strconv.FormatFloat(input.Account.ProrateAmount, 'g', -1, 64)
length := 0
length += 47
length += len(input.Issue.Description)
length += 2
if input.Issue.Category == "technical" {
length += 60
length += len(input.Technical.System)
length += 17
length += len(input.Technical.ErrorCode)
length += 18
length += len(input.Technical.Environment)
length += 2
if input.Technical.HasLogs {
length += 35
length += len(input.Technical.Logs)
length += 5
}
length += 2
if input.Technical.ComplexityScore != 0 {
length += 28
length += len(strconv.Itoa(input.Technical.ComplexityScore))
length += 5
if input.Technical.ComplexityScore >= 8 {
length += 90
length += len(var0)
length += 32
length += len(input.Technical.AssignedSpecialist)
length += 1
}
length += 2
if input.Technical.ComplexityScore <= 3 {
length += 93
length += len(var1)
length += 9
}
length += 1
}
length += 1
}
length += 2
if input.Issue.Category == "billing" {
length += 54
length += len(input.Billing.InvoiceId)
length += 14
length += len(var2)
length += 21
length += len(input.Billing.PaymentMethod)
length += 21
length += len(input.Billing.DisputeReason)
length += 2
if input.Billing.RequiresRefund {
length += 54
length += len(var3)
length += 22
length += len(var4)
length += 16
if input.Customer.Tier == "premium" {
length += 75
}
length += 2
if input.Customer.Tier == "enterprise" {
length += 75
}
length += 1
}
length += 2
if input.Billing.PaymentFailed {
length += 54
length += len(input.Billing.FailureReason)
length += 17
length += len(input.Billing.NextRetryDate)
length += 23
length += len(input.Billing.CustomerAction)
length += 1
}
length += 1
}
length += 2
if input.Issue.Category == "account" {
length += 50
length += len(input.Account.IssueType)
length += 21
length += len(input.Account.Status)
length += 2
if input.Account.Locked {
length += 42
length += len(input.Account.LockReason)
length += 21
length += len(input.Account.SecurityLevel)
length += 23
length += len(input.Account.UnlockStep1)
length += 4
length += len(input.Account.UnlockStep2)
length += 4
length += len(input.Account.UnlockStep3)
length += 2
if input.Account.RequiresVerification {
length += 52
length += len(input.Account.VerificationDocuments)
length += 1
}
length += 1
}
length += 2
if input.Account.SubscriptionChange {
length += 56
length += len(input.Account.CurrentPlan)
length += 21
length += len(input.Account.RequestedPlan)
length += 21
length += len(input.Account.ChangeDate)
length += 23
length += len(var5)
length += 1
}
length += 1
}
b.Grow(length)
b.WriteString(`## ๐ Issue Classification
**Description**: `)
b.WriteString(input.Issue.Description)
b.WriteString(`
`)
if input.Issue.Category == "technical" {
b.WriteString(`
### ๐ ๏ธ Technical Issue Analysis
**System Affected**: `)
b.WriteString(input.Technical.System)
b.WriteString(`
**Error Code**: `)
b.WriteString(input.Technical.ErrorCode)
b.WriteString(`
**Environment**: `)
b.WriteString(input.Technical.Environment)
b.WriteString(`
`)
if input.Technical.HasLogs {
b.WriteString("\n**Error Logs Available**: Yes\n```\n")
b.WriteString(input.Technical.Logs)
b.WriteString("\n```\n")
}
b.WriteString(`
`)
if input.Technical.ComplexityScore != 0 {
b.WriteString(`
**Complexity Assessment**: `)
b.WriteString(strconv.Itoa(input.Technical.ComplexityScore))
b.WriteString(`/10
`)
if input.Technical.ComplexityScore >= 8 {
b.WriteString(`
๐ด **High Complexity** - Escalating to Senior Technical Team
**Estimated Resolution**: `)
b.WriteString(var0)
b.WriteString(` hours
**Assigned Specialist**: `)
b.WriteString(input.Technical.AssignedSpecialist)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Technical.ComplexityScore <= 3 {
b.WriteString(`
โ
**Standard Issue** - Can be resolved with standard procedures
**Estimated Resolution**: `)
b.WriteString(var1)
b.WriteString(` minutes
`)
}
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Issue.Category == "billing" {
b.WriteString(`
### ๐ณ Billing Issue Analysis
**Invoice Number**: `)
b.WriteString(input.Billing.InvoiceId)
b.WriteString(`
**Amount**: $`)
b.WriteString(var2)
b.WriteString(`
**Payment Method**: `)
b.WriteString(input.Billing.PaymentMethod)
b.WriteString(`
**Dispute Reason**: `)
b.WriteString(input.Billing.DisputeReason)
b.WriteString(`
`)
if input.Billing.RequiresRefund {
b.WriteString(`
๐ฐ **Refund Request Detected**
**Refund Amount**: $`)
b.WriteString(var3)
b.WriteString(`
**Processing Time**: `)
b.WriteString(var4)
b.WriteString(` business days
`)
if input.Customer.Tier == "premium" {
b.WriteString(`
โก **Fast-Track Refund**: Your refund will be processed within 24 hours.
`)
}
b.WriteString(`
`)
if input.Customer.Tier == "enterprise" {
b.WriteString(`
โก **Fast-Track Refund**: Your refund will be processed within 24 hours.
`)
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Billing.PaymentFailed {
b.WriteString(`
โ **Payment Failure Detected**
**Failure Reason**: `)
b.WriteString(input.Billing.FailureReason)
b.WriteString(`
**Next Retry**: `)
b.WriteString(input.Billing.NextRetryDate)
b.WriteString(`
**Action Required**: `)
b.WriteString(input.Billing.CustomerAction)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Issue.Category == "account" {
b.WriteString(`
### ๐ค Account Issue Analysis
**Issue Type**: `)
b.WriteString(input.Account.IssueType)
b.WriteString(`
**Account Status**: `)
b.WriteString(input.Account.Status)
b.WriteString(`
`)
if input.Account.Locked {
b.WriteString(`
๐ **Account Locked**
**Lock Reason**: `)
b.WriteString(input.Account.LockReason)
b.WriteString(`
**Security Level**: `)
b.WriteString(input.Account.SecurityLevel)
b.WriteString(`
**Unlock Steps**:
1. `)
b.WriteString(input.Account.UnlockStep1)
b.WriteString(`
2. `)
b.WriteString(input.Account.UnlockStep2)
b.WriteString(`
3. `)
b.WriteString(input.Account.UnlockStep3)
b.WriteString(`
`)
if input.Account.RequiresVerification {
b.WriteString(`
**Identity Verification Required**: Please prepare `)
b.WriteString(input.Account.VerificationDocuments)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Account.SubscriptionChange {
b.WriteString(`
๐ **Subscription Change Request**
**Current Plan**: `)
b.WriteString(input.Account.CurrentPlan)
b.WriteString(`
**Requested Plan**: `)
b.WriteString(input.Account.RequestedPlan)
b.WriteString(`
**Effective Date**: `)
b.WriteString(input.Account.ChangeDate)
b.WriteString(`
**Prorated Amount**: $`)
b.WriteString(var5)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
return b.String()
}
type IntelligentEscalationLogic struct {
Escalation struct {
Required bool
Level int
Reason string
ManagerName string
ManagerContact string
SlaHours int
ExecutiveContact string
Notes string
SpecialistTeam string
ExpertName string
ExpertSpecialty string
ResponseTime int
SeniorAgent string
QueuePosition int
PickupTime string
CallbackRequested bool
CallbackTime string
}
Customer struct {
VipStatus bool
Phone string
Timezone string
}
}
func (input *IntelligentEscalationLogic) isEscalationZero() bool {
return !input.Escalation.Required &&
input.Escalation.Level == 0 &&
input.Escalation.Reason == "" &&
input.Escalation.ManagerName == "" &&
input.Escalation.ManagerContact == "" &&
input.Escalation.SlaHours == 0 &&
input.Escalation.ExecutiveContact == "" &&
input.Escalation.Notes == "" &&
input.Escalation.SpecialistTeam == "" &&
input.Escalation.ExpertName == "" &&
input.Escalation.ExpertSpecialty == "" &&
input.Escalation.ResponseTime == 0 &&
input.Escalation.SeniorAgent == "" &&
input.Escalation.QueuePosition == 0 &&
input.Escalation.PickupTime == "" &&
!input.Escalation.CallbackRequested &&
input.Escalation.CallbackTime == ""
}
func (input *IntelligentEscalationLogic) isCustomerZero() bool {
return !input.Customer.VipStatus &&
input.Customer.Phone == "" &&
input.Customer.Timezone == ""
}
func (input *IntelligentEscalationLogic) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Escalation.Level)
var1 := strconv.Itoa(input.Escalation.SlaHours)
var2 := strconv.Itoa(input.Escalation.ResponseTime)
var3 := strconv.Itoa(input.Escalation.QueuePosition)
length := 0
if input.Escalation.Required {
length += 53
length += len(var0)
length += 21
length += len(input.Escalation.Reason)
length += 2
if input.Escalation.Level >= 3 {
length += 74
length += len(input.Escalation.ManagerName)
length += 14
length += len(input.Escalation.ManagerContact)
length += 10
length += len(var1)
length += 8
if input.Customer.VipStatus {
length += 87
length += len(input.Escalation.ExecutiveContact)
length += 1
}
length += 24
length += len(input.Escalation.Notes)
length += 1
}
length += 2
if input.Escalation.Level == 2 {
length += 73
length += len(input.Escalation.SpecialistTeam)
length += 22
length += len(input.Escalation.ExpertName)
length += 16
length += len(input.Escalation.ExpertSpecialty)
length += 25
length += len(var2)
length += 9
}
length += 2
if input.Escalation.Level == 1 {
length += 65
length += len(input.Escalation.SeniorAgent)
length += 21
length += len(var3)
length += 22
length += len(input.Escalation.PickupTime)
length += 1
}
length += 2
if input.Escalation.CallbackRequested {
length += 47
length += len(input.Customer.Phone)
length += 21
length += len(input.Escalation.CallbackTime)
length += 16
length += len(input.Customer.Timezone)
length += 1
}
length += 1
}
b.Grow(length)
if input.Escalation.Required {
b.WriteString(`
## ๐ Escalation Triggered
**Escalation Level**: `)
b.WriteString(var0)
b.WriteString(`
**Trigger Reason**: `)
b.WriteString(input.Escalation.Reason)
b.WriteString(`
`)
if input.Escalation.Level >= 3 {
b.WriteString(`
### ๐ด Level 3+ Escalation - Management Involvement
**Escalated To**: `)
b.WriteString(input.Escalation.ManagerName)
b.WriteString(`
**Contact**: `)
b.WriteString(input.Escalation.ManagerContact)
b.WriteString(`
**SLA**: `)
b.WriteString(var1)
b.WriteString(` hours
`)
if input.Customer.VipStatus {
b.WriteString(`
๐ **VIP Customer Alert**: Executive team has been notified.
**Executive Contact**: `)
b.WriteString(input.Escalation.ExecutiveContact)
b.WriteRune('\n')
}
b.WriteString(`
**Escalation Notes**: `)
b.WriteString(input.Escalation.Notes)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Escalation.Level == 2 {
b.WriteString(`
### ๐ก Level 2 Escalation - Specialist Required
**Specialist Team**: `)
b.WriteString(input.Escalation.SpecialistTeam)
b.WriteString(`
**Expert Assigned**: `)
b.WriteString(input.Escalation.ExpertName)
b.WriteString(`
**Specialty**: `)
b.WriteString(input.Escalation.ExpertSpecialty)
b.WriteString(`
**Estimated Response**: `)
b.WriteString(var2)
b.WriteString(` minutes
`)
}
b.WriteString(`
`)
if input.Escalation.Level == 1 {
b.WriteString(`
### ๐ข Level 1 Escalation - Senior Support
**Senior Agent**: `)
b.WriteString(input.Escalation.SeniorAgent)
b.WriteString(`
**Queue Position**: `)
b.WriteString(var3)
b.WriteString(`
**Expected Pickup**: `)
b.WriteString(input.Escalation.PickupTime)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Escalation.CallbackRequested {
b.WriteString(`
๐ **Callback Scheduled**
**Phone Number**: `)
b.WriteString(input.Customer.Phone)
b.WriteString(`
**Preferred Time**: `)
b.WriteString(input.Escalation.CallbackTime)
b.WriteString(`
**Time Zone**: `)
b.WriteString(input.Customer.Timezone)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
return b.String()
}
type ResolutionAndNextSteps struct {
Solution struct {
HasQuickFix bool
QuickFix string
Step1 string
Step2 string
Step3 string
RequiresRestart bool
RestartComponent string
VerificationSteps string
RequiresInvestigation bool
}
Investigation struct {
Timeline string
Team string
UpdateFrequency int
Check1 string
Check2 string
Check3 string
ContactMethod string
}
Ticket struct {
Status string
PriorityLevel string
NextUpdate string
SlaAtRisk bool
SlaDeadline string
Id string
}
Followup struct {
SurveyLink string
HasCompensation bool
CompensationType string
CompensationValue float64
CompensationTarget string
CompensationDate string
}
Customer struct {
Tier string
DedicatedSupportContact string
EmergencyContact string
Name string
}
Support struct {
PremiumPhone string
PremiumWaitTime int
GeneralContact string
ChatUrl string
KbUrl string
}
Agent struct {
Name string
Id string
}
Session struct {
EndTime string
}
}
func (input *ResolutionAndNextSteps) isSolutionZero() bool {
return !input.Solution.HasQuickFix &&
input.Solution.QuickFix == "" &&
input.Solution.Step1 == "" &&
input.Solution.Step2 == "" &&
input.Solution.Step3 == "" &&
!input.Solution.RequiresRestart &&
input.Solution.RestartComponent == "" &&
input.Solution.VerificationSteps == "" &&
!input.Solution.RequiresInvestigation
}
func (input *ResolutionAndNextSteps) isInvestigationZero() bool {
return input.Investigation.Timeline == "" &&
input.Investigation.Team == "" &&
input.Investigation.UpdateFrequency == 0 &&
input.Investigation.Check1 == "" &&
input.Investigation.Check2 == "" &&
input.Investigation.Check3 == "" &&
input.Investigation.ContactMethod == ""
}
func (input *ResolutionAndNextSteps) isTicketZero() bool {
return input.Ticket.Status == "" &&
input.Ticket.PriorityLevel == "" &&
input.Ticket.NextUpdate == "" &&
!input.Ticket.SlaAtRisk &&
input.Ticket.SlaDeadline == "" &&
input.Ticket.Id == ""
}
func (input *ResolutionAndNextSteps) isFollowupZero() bool {
return input.Followup.SurveyLink == "" &&
!input.Followup.HasCompensation &&
input.Followup.CompensationType == "" &&
input.Followup.CompensationValue == 0 &&
input.Followup.CompensationTarget == "" &&
input.Followup.CompensationDate == ""
}
func (input *ResolutionAndNextSteps) isCustomerZero() bool {
return input.Customer.Tier == "" &&
input.Customer.DedicatedSupportContact == "" &&
input.Customer.EmergencyContact == "" &&
input.Customer.Name == ""
}
func (input *ResolutionAndNextSteps) isSupportZero() bool {
return input.Support.PremiumPhone == "" &&
input.Support.PremiumWaitTime == 0 &&
input.Support.GeneralContact == "" &&
input.Support.ChatUrl == "" &&
input.Support.KbUrl == ""
}
func (input *ResolutionAndNextSteps) isAgentZero() bool {
return input.Agent.Name == "" &&
input.Agent.Id == ""
}
func (input *ResolutionAndNextSteps) isSessionZero() bool {
return input.Session.EndTime == ""
}
func (input *ResolutionAndNextSteps) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Investigation.UpdateFrequency)
var1 := strconv.FormatFloat(input.Followup.CompensationValue, 'g', -1, 64)
var2 := strconv.Itoa(input.Support.PremiumWaitTime)
length := 0
length += 27
if input.Solution.HasQuickFix {
length += 51
length += len(input.Solution.QuickFix)
length += 27
length += len(input.Solution.Step1)
length += 4
length += len(input.Solution.Step2)
length += 4
length += len(input.Solution.Step3)
length += 2
if input.Solution.RequiresRestart {
length += 52
length += len(input.Solution.RestartComponent)
length += 35
}
length += 20
length += len(input.Solution.VerificationSteps)
length += 1
}
length += 2
if input.Solution.RequiresInvestigation {
length += 68
length += len(input.Investigation.Timeline)
length += 20
length += len(input.Investigation.Team)
length += 29
length += len(var0)
length += 35
length += len(input.Investigation.Check1)
length += 3
length += len(input.Investigation.Check2)
length += 3
length += len(input.Investigation.Check3)
length += 29
length += len(input.Investigation.ContactMethod)
length += 1
}
length += 52
length += len(input.Ticket.Status)
length += 15
length += len(input.Ticket.PriorityLevel)
length += 20
length += len(input.Ticket.NextUpdate)
length += 2
if input.Ticket.SlaAtRisk {
length += 64
length += len(input.Ticket.SlaDeadline)
length += 32
}
length += 93
if input.Followup.SurveyLink != "" {
length += 19
length += len(input.Followup.SurveyLink)
length += 13
}
length += 2
if input.Followup.HasCompensation {
length += 89
length += len(input.Followup.CompensationType)
length += 13
length += len(var1)
length += 17
length += len(input.Followup.CompensationTarget)
length += 16
length += len(input.Followup.CompensationDate)
length += 1
}
length += 27
if input.Customer.Tier == "enterprise" {
length += 29
length += len(input.Customer.DedicatedSupportContact)
length += 19
length += len(input.Customer.EmergencyContact)
length += 1
}
length += 2
if input.Customer.Tier == "premium" {
length += 27
length += len(input.Support.PremiumPhone)
length += 24
length += len(var2)
length += 9
}
length += 23
length += len(input.Support.GeneralContact)
length += 34
length += len(input.Support.ChatUrl)
length += 21
length += len(input.Support.KbUrl)
length += 29
length += len(input.Ticket.Id)
length += 20
length += len(input.Agent.Name)
length += 6
length += len(input.Agent.Id)
length += 19
length += len(input.Session.EndTime)
length += 39
length += len(input.Customer.Name)
length += 8
b.Grow(length)
b.WriteString(`## ๐ก Immediate Actions
`)
if input.Solution.HasQuickFix {
b.WriteString(`
### โ
Quick Resolution Available
**Solution**: `)
b.WriteString(input.Solution.QuickFix)
b.WriteString(`
**Steps to Resolve**:
1. `)
b.WriteString(input.Solution.Step1)
b.WriteString(`
2. `)
b.WriteString(input.Solution.Step2)
b.WriteString(`
3. `)
b.WriteString(input.Solution.Step3)
b.WriteString(`
`)
if input.Solution.RequiresRestart {
b.WriteString(`
โ ๏ธ **System Restart Required**: Please restart `)
b.WriteString(input.Solution.RestartComponent)
b.WriteString(` after completing the above steps.
`)
}
b.WriteString(`
**Verification**: `)
b.WriteString(input.Solution.VerificationSteps)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Solution.RequiresInvestigation {
b.WriteString(`
### ๐ Further Investigation Needed
**Investigation Timeline**: `)
b.WriteString(input.Investigation.Timeline)
b.WriteString(`
**Assigned Team**: `)
b.WriteString(input.Investigation.Team)
b.WriteString(`
**Progress Updates**: Every `)
b.WriteString(var0)
b.WriteString(` hours
**What We're Checking**:
- `)
b.WriteString(input.Investigation.Check1)
b.WriteString(`
- `)
b.WriteString(input.Investigation.Check2)
b.WriteString(`
- `)
b.WriteString(input.Investigation.Check3)
b.WriteString(`
**How We'll Contact You**: `)
b.WriteString(input.Investigation.ContactMethod)
b.WriteRune('\n')
}
b.WriteString(`
## ๐ Ticket Status Update
**Current Status**: `)
b.WriteString(input.Ticket.Status)
b.WriteString(`
**Priority**: `)
b.WriteString(input.Ticket.PriorityLevel)
b.WriteString(`/5
**Next Update**: `)
b.WriteString(input.Ticket.NextUpdate)
b.WriteString(`
`)
if input.Ticket.SlaAtRisk {
b.WriteString(`
โ ๏ธ **SLA Alert**: This ticket is approaching SLA deadline (`)
b.WriteString(input.Ticket.SlaDeadline)
b.WriteString(`)
**Escalation Triggered**: Yes
`)
}
b.WriteString(`
## ๐ฏ Customer Satisfaction
Before we close, how would you rate your experience today?
`)
if input.Followup.SurveyLink != "" {
b.WriteString(`
**Quick Survey**: `)
b.WriteString(input.Followup.SurveyLink)
b.WriteString(` (2 minutes)
`)
}
b.WriteString(`
`)
if input.Followup.HasCompensation {
b.WriteString(`
### ๐ Service Recovery
Due to the inconvenience, we're providing:
**Compensation**: `)
b.WriteString(input.Followup.CompensationType)
b.WriteString(`
**Value**: $`)
b.WriteString(var1)
b.WriteString(`
**Applied To**: `)
b.WriteString(input.Followup.CompensationTarget)
b.WriteString(`
**Effective**: `)
b.WriteString(input.Followup.CompensationDate)
b.WriteRune('\n')
}
b.WriteString(`
## ๐ Need More Help?
`)
if input.Customer.Tier == "enterprise" {
b.WriteString(`
**Your Dedicated Support**: `)
b.WriteString(input.Customer.DedicatedSupportContact)
b.WriteString(`
**24/7 Hotline**: `)
b.WriteString(input.Customer.EmergencyContact)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Customer.Tier == "premium" {
b.WriteString(`
**Premium Support Line**: `)
b.WriteString(input.Support.PremiumPhone)
b.WriteString(`
**Average Wait Time**: `)
b.WriteString(var2)
b.WriteString(` minutes
`)
}
b.WriteString(`
**General Support**: `)
b.WriteString(input.Support.GeneralContact)
b.WriteString(`
**Live Chat**: Available 24/7 at `)
b.WriteString(input.Support.ChatUrl)
b.WriteString(`
**Knowledge Base**: `)
b.WriteString(input.Support.KbUrl)
b.WriteString(`
---
**Ticket Reference**: #`)
b.WriteString(input.Ticket.Id)
b.WriteString(`
**Support Agent**: `)
b.WriteString(input.Agent.Name)
b.WriteString(` (ID: `)
b.WriteString(input.Agent.Id)
b.WriteString(`)
**Session End**: `)
b.WriteString(input.Session.EndTime)
b.WriteString(`
*Thank you for choosing our service, `)
b.WriteString(input.Customer.Name)
b.WriteString(`! ๐* `)
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package tutor
import (
"strconv"
"strings"
)
type SystemPrompt struct{}
func (input *SystemPrompt) String() string {
return `You are AdaptiveTutor, an AI learning assistant that personalizes education based on student progress, learning style, and current skill level. You provide engaging, interactive lessons with appropriate difficulty scaling.`
}
type LessonIntroduction struct {
Subject string
Student struct {
Name string
Level string
LearningStyle string
CompletionPercentage int
StreakDays int
PreferredLanguage string
}
Lesson struct {
Topic string
Difficulty string
}
}
func (input *LessonIntroduction) isStudentZero() bool {
return input.Student.Name == "" &&
input.Student.Level == "" &&
input.Student.LearningStyle == "" &&
input.Student.CompletionPercentage == 0 &&
input.Student.StreakDays == 0 &&
input.Student.PreferredLanguage == ""
}
func (input *LessonIntroduction) isLessonZero() bool {
return input.Lesson.Topic == "" &&
input.Lesson.Difficulty == ""
}
func (input *LessonIntroduction) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Student.CompletionPercentage)
var1 := strconv.Itoa(input.Student.StreakDays)
length := 0
length += 7
length += len(input.Subject)
length += 22
length += len(input.Student.Name)
length += 92
length += len(input.Student.Level)
length += 23
length += len(input.Student.LearningStyle)
length += 17
length += len(var0)
length += 25
length += len(var1)
length += 12
if input.Student.PreferredLanguage != "" {
length += 31
length += len(input.Student.PreferredLanguage)
length += 2
}
length += 39
length += len(input.Lesson.Topic)
length += 17
length += len(input.Lesson.Difficulty)
length += 8
if input.Student.Level == "beginner" {
length += 100
}
length += 2
if input.Student.Level == "intermediate" {
length += 105
}
length += 2
if input.Student.Level == "advanced" {
length += 87
}
b.Grow(length)
b.WriteString(`# ๐ `)
b.WriteString(input.Subject)
b.WriteString(` Learning Session
Hi `)
b.WriteString(input.Student.Name)
b.WriteString(`! Welcome to your personalized learning session.
## ๐ค Your Profile
- **Current Level**: `)
b.WriteString(input.Student.Level)
b.WriteString(`
- **Learning Style**: `)
b.WriteString(input.Student.LearningStyle)
b.WriteString(`
- **Progress**: `)
b.WriteString(var0)
b.WriteString(`% complete
- **Streak**: `)
b.WriteString(var1)
b.WriteString(` days ๐ฅ
`)
if input.Student.PreferredLanguage != "" {
b.WriteString(`
*Lesson will be delivered in: `)
b.WriteString(input.Student.PreferredLanguage)
b.WriteString(`*
`)
}
b.WriteString(`
## ๐ฏ Today's Objective
**Topic**: `)
b.WriteString(input.Lesson.Topic)
b.WriteString(`
**Difficulty**: `)
b.WriteString(input.Lesson.Difficulty)
b.WriteString(`/5 โญ
`)
if input.Student.Level == "beginner" {
b.WriteString(`
Don't worry if this seems challenging - we'll break everything down into simple, manageable steps!
`)
}
b.WriteString(`
`)
if input.Student.Level == "intermediate" {
b.WriteString(`
You're making great progress! Today we'll build on what you already know and explore some new concepts.
`)
}
b.WriteString(`
`)
if input.Student.Level == "advanced" {
b.WriteString(`
Ready for a challenge? Today's lesson will push your understanding to the next level.
`)
}
return b.String()
}
type AdaptiveContentDelivery struct {
Lesson struct {
HasPrerequisites bool
Prerequisites string
ReviewContent string
VisualContent string
HasDiagrams bool
Diagrams string
HasCharts bool
Charts string
AuditoryContent string
InteractiveExercises string
PracticeActivities string
ConceptCount int
}
Student struct {
PrerequisitesScore int
LearningStyle string
Level string
}
Concepts struct {
Concept1 string
Concept2 string
Concept3 string
Concept4 string
Concept5 string
}
Examples struct {
Basic string
BasicExplanation string
Intermediate string
IntermediateAnalysis string
IntermediateReasoning string
Advanced string
AdvancedAnalysis string
Optimizations string
}
}
func (input *AdaptiveContentDelivery) isLessonZero() bool {
return !input.Lesson.HasPrerequisites &&
input.Lesson.Prerequisites == "" &&
input.Lesson.ReviewContent == "" &&
input.Lesson.VisualContent == "" &&
!input.Lesson.HasDiagrams &&
input.Lesson.Diagrams == "" &&
!input.Lesson.HasCharts &&
input.Lesson.Charts == "" &&
input.Lesson.AuditoryContent == "" &&
input.Lesson.InteractiveExercises == "" &&
input.Lesson.PracticeActivities == "" &&
input.Lesson.ConceptCount == 0
}
func (input *AdaptiveContentDelivery) isStudentZero() bool {
return input.Student.PrerequisitesScore == 0 &&
input.Student.LearningStyle == "" &&
input.Student.Level == ""
}
func (input *AdaptiveContentDelivery) isConceptsZero() bool {
return input.Concepts.Concept1 == "" &&
input.Concepts.Concept2 == "" &&
input.Concepts.Concept3 == "" &&
input.Concepts.Concept4 == "" &&
input.Concepts.Concept5 == ""
}
func (input *AdaptiveContentDelivery) isExamplesZero() bool {
return input.Examples.Basic == "" &&
input.Examples.BasicExplanation == "" &&
input.Examples.Intermediate == "" &&
input.Examples.IntermediateAnalysis == "" &&
input.Examples.IntermediateReasoning == "" &&
input.Examples.Advanced == "" &&
input.Examples.AdvancedAnalysis == "" &&
input.Examples.Optimizations == ""
}
func (input *AdaptiveContentDelivery) String() string {
var b strings.Builder
length := 0
if input.Lesson.HasPrerequisites {
length += 94
length += len(input.Lesson.Prerequisites)
length += 2
if input.Student.PrerequisitesScore != 0 {
length += 30
length += len(strconv.Itoa(input.Student.PrerequisitesScore))
length += 6
if input.Student.PrerequisitesScore < 70 {
length += 97
length += len(input.Lesson.ReviewContent)
length += 1
}
length += 2
if input.Student.PrerequisitesScore >= 90 {
length += 56
}
length += 1
}
length += 1
}
length += 26
if input.Student.LearningStyle == "visual" {
length += 35
length += len(input.Lesson.VisualContent)
length += 2
if input.Lesson.HasDiagrams {
length += 27
length += len(input.Lesson.Diagrams)
length += 1
}
length += 2
if input.Lesson.HasCharts {
length += 22
length += len(input.Lesson.Charts)
length += 1
}
length += 1
}
length += 2
if input.Student.LearningStyle == "auditory" {
length += 37
length += len(input.Lesson.AuditoryContent)
length += 91
}
length += 2
if input.Student.LearningStyle == "kinesthetic" {
length += 100
length += len(input.Lesson.InteractiveExercises)
length += 27
length += len(input.Lesson.PracticeActivities)
length += 1
}
length += 25
if input.Lesson.ConceptCount != 0 {
length += 13
length += len(strconv.Itoa(input.Lesson.ConceptCount))
length += 26
length += len(input.Concepts.Concept1)
length += 4
length += len(input.Concepts.Concept2)
length += 1
if input.Lesson.ConceptCount >= 3 {
length += 4
length += len(input.Concepts.Concept3)
length += 1
}
length += 1
if input.Lesson.ConceptCount >= 4 {
length += 4
length += len(input.Concepts.Concept4)
length += 1
}
length += 1
if input.Lesson.ConceptCount >= 5 {
length += 4
length += len(input.Concepts.Concept5)
length += 1
}
length += 1
}
length += 20
if input.Student.Level == "beginner" {
length += 59
length += len(input.Examples.Basic)
length += 23
length += len(input.Examples.BasicExplanation)
length += 1
}
length += 2
if input.Student.Level == "intermediate" {
length += 58
length += len(input.Examples.Intermediate)
length += 20
length += len(input.Examples.IntermediateAnalysis)
length += 22
length += len(input.Examples.IntermediateReasoning)
length += 1
}
length += 2
if input.Student.Level == "advanced" {
length += 68
length += len(input.Examples.Advanced)
length += 21
length += len(input.Examples.AdvancedAnalysis)
length += 34
length += len(input.Examples.Optimizations)
length += 1
}
b.Grow(length)
if input.Lesson.HasPrerequisites {
b.WriteString(`
## ๐ Prerequisites Check
Before we start, let's make sure you understand these concepts:
`)
b.WriteString(input.Lesson.Prerequisites)
b.WriteString(`
`)
if input.Student.PrerequisitesScore != 0 {
b.WriteString(`
**Your prerequisite score**: `)
b.WriteString(strconv.Itoa(input.Student.PrerequisitesScore))
b.WriteString(`/100
`)
if input.Student.PrerequisitesScore < 70 {
b.WriteString(`
๐ **Recommendation**: Let's do a quick review of the basics first.
### Quick Review Session
`)
b.WriteString(input.Lesson.ReviewContent)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Student.PrerequisitesScore >= 90 {
b.WriteString(`
โ
**Excellent!** You're ready for advanced concepts.
`)
}
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
## ๐ Lesson Content
`)
if input.Student.LearningStyle == "visual" {
b.WriteString(`
### ๐ Visual Learning Approach
`)
b.WriteString(input.Lesson.VisualContent)
b.WriteString(`
`)
if input.Lesson.HasDiagrams {
b.WriteString(`
**Interactive Diagrams:**
`)
b.WriteString(input.Lesson.Diagrams)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Lesson.HasCharts {
b.WriteString(`
**Charts & Graphs:**
`)
b.WriteString(input.Lesson.Charts)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Student.LearningStyle == "auditory" {
b.WriteString(`
### ๐ต Auditory Learning Approach
`)
b.WriteString(input.Lesson.AuditoryContent)
b.WriteString(`
*๐ก Tip: Try reading this lesson out loud or use text-to-speech for better retention!*
`)
}
b.WriteString(`
`)
if input.Student.LearningStyle == "kinesthetic" {
b.WriteString(`
### ๐ ๏ธ Hands-On Learning Approach
Let's learn by doing! Here are some interactive exercises:
`)
b.WriteString(input.Lesson.InteractiveExercises)
b.WriteString(`
**Practice Activities:**
`)
b.WriteString(input.Lesson.PracticeActivities)
b.WriteRune('\n')
}
b.WriteString(`
## ๐ง Core Concepts
`)
if input.Lesson.ConceptCount != 0 {
b.WriteString(`
We'll cover `)
b.WriteString(strconv.Itoa(input.Lesson.ConceptCount))
b.WriteString(` main concepts today:
1. `)
b.WriteString(input.Concepts.Concept1)
b.WriteString(`
2. `)
b.WriteString(input.Concepts.Concept2)
b.WriteRune('\n')
if input.Lesson.ConceptCount >= 3 {
b.WriteString(`
3. `)
b.WriteString(input.Concepts.Concept3)
b.WriteRune('\n')
}
b.WriteRune('\n')
if input.Lesson.ConceptCount >= 4 {
b.WriteString(`
4. `)
b.WriteString(input.Concepts.Concept4)
b.WriteRune('\n')
}
b.WriteRune('\n')
if input.Lesson.ConceptCount >= 5 {
b.WriteString(`
5. `)
b.WriteString(input.Concepts.Concept5)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
## ๐ก Examples
`)
if input.Student.Level == "beginner" {
b.WriteString("\n### Simple Example\nLet's start with a basic example:\n\n```\n")
b.WriteString(input.Examples.Basic)
b.WriteString("\n```\n\n**Explanation**: ")
b.WriteString(input.Examples.BasicExplanation)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Student.Level == "intermediate" {
b.WriteString("\n### Practical Example\nHere's a real-world scenario:\n\n```\n")
b.WriteString(input.Examples.Intermediate)
b.WriteString("\n```\n\n**Analysis**: ")
b.WriteString(input.Examples.IntermediateAnalysis)
b.WriteString(`
**Why this works**: `)
b.WriteString(input.Examples.IntermediateReasoning)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Student.Level == "advanced" {
b.WriteString("\n### Complex Example\nLet's examine an advanced implementation:\n\n```\n")
b.WriteString(input.Examples.Advanced)
b.WriteString("\n```\n\n**Deep Dive**: ")
b.WriteString(input.Examples.AdvancedAnalysis)
b.WriteString(`
**Optimization Opportunities**: `)
b.WriteString(input.Examples.Optimizations)
b.WriteRune('\n')
}
return b.String()
}
type InteractiveAssessment struct {
Assessment struct {
HasQuiz bool
HasProject bool
}
Question struct {
Number int
Text string
Type string
OptionA string
OptionB string
OptionC string
OptionD string
CodeTemplate string
ExpectedOutput string
Prompt string
Hint string
}
Project struct {
Title string
EstimatedMinutes int
Requirements string
Language string
StarterCode string
HasBonus bool
BonusChallenge string
}
}
func (input *InteractiveAssessment) isAssessmentZero() bool {
return !input.Assessment.HasQuiz &&
!input.Assessment.HasProject
}
func (input *InteractiveAssessment) isQuestionZero() bool {
return input.Question.Number == 0 &&
input.Question.Text == "" &&
input.Question.Type == "" &&
input.Question.OptionA == "" &&
input.Question.OptionB == "" &&
input.Question.OptionC == "" &&
input.Question.OptionD == "" &&
input.Question.CodeTemplate == "" &&
input.Question.ExpectedOutput == "" &&
input.Question.Prompt == "" &&
input.Question.Hint == ""
}
func (input *InteractiveAssessment) isProjectZero() bool {
return input.Project.Title == "" &&
input.Project.EstimatedMinutes == 0 &&
input.Project.Requirements == "" &&
input.Project.Language == "" &&
input.Project.StarterCode == "" &&
!input.Project.HasBonus &&
input.Project.BonusChallenge == ""
}
func (input *InteractiveAssessment) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Question.Number)
var1 := strconv.Itoa(input.Project.EstimatedMinutes)
length := 0
length += 24
if input.Assessment.HasQuiz {
length += 39
length += len(var0)
length += 4
length += len(input.Question.Text)
length += 2
if input.Question.Type == "multiple_choice" {
length += 4
length += len(input.Question.OptionA)
length += 4
length += len(input.Question.OptionB)
length += 4
length += len(input.Question.OptionC)
length += 4
length += len(input.Question.OptionD)
length += 1
}
length += 2
if input.Question.Type == "coding" {
length += 27
length += len(input.Question.CodeTemplate)
length += 27
length += len(input.Question.ExpectedOutput)
length += 1
}
length += 2
if input.Question.Type == "explanation" {
length += 32
length += len(input.Question.Prompt)
length += 22
length += len(input.Question.Hint)
length += 1
}
length += 1
}
length += 2
if input.Assessment.HasProject {
length += 36
length += len(input.Project.Title)
length += 21
length += len(var1)
length += 28
length += len(input.Project.Requirements)
length += 23
length += len(input.Project.Language)
length += 1
length += len(input.Project.StarterCode)
length += 6
if input.Project.HasBonus {
length += 22
length += len(input.Project.BonusChallenge)
length += 1
}
length += 1
}
b.Grow(length)
b.WriteString(`## ๐ฏ Practice Time!
`)
if input.Assessment.HasQuiz {
b.WriteString(`
### Quick Knowledge Check
**Question `)
b.WriteString(var0)
b.WriteString(`**: `)
b.WriteString(input.Question.Text)
b.WriteString(`
`)
if input.Question.Type == "multiple_choice" {
b.WriteString(`
A) `)
b.WriteString(input.Question.OptionA)
b.WriteString(`
B) `)
b.WriteString(input.Question.OptionB)
b.WriteString(`
C) `)
b.WriteString(input.Question.OptionC)
b.WriteString(`
D) `)
b.WriteString(input.Question.OptionD)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Question.Type == "coding" {
b.WriteString("\n**Coding Challenge:**\n```\n")
b.WriteString(input.Question.CodeTemplate)
b.WriteString("\n```\n\n**Expected Output**: ")
b.WriteString(input.Question.ExpectedOutput)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Question.Type == "explanation" {
b.WriteString(`
**Explain in your own words**: `)
b.WriteString(input.Question.Prompt)
b.WriteString(`
*Hint*: Think about `)
b.WriteString(input.Question.Hint)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Assessment.HasProject {
b.WriteString(`
## ๐ Mini Project
**Project**: `)
b.WriteString(input.Project.Title)
b.WriteString(`
**Estimated Time**: `)
b.WriteString(var1)
b.WriteString(` minutes
**Requirements**:
`)
b.WriteString(input.Project.Requirements)
b.WriteString("\n\n**Starter Code**:\n```")
b.WriteString(input.Project.Language)
b.WriteRune('\n')
b.WriteString(input.Project.StarterCode)
b.WriteString("\n```\n\n")
if input.Project.HasBonus {
b.WriteString(`
**Bonus Challenge**: `)
b.WriteString(input.Project.BonusChallenge)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
return b.String()
}
type ProgressTracking struct {
Progress struct {
CurrentLesson int
TotalLessons int
StrugglingAreas string
StrengthAreas string
}
Student struct {
CompletionPercentage int
StreakDays int
Name string
}
NextSteps struct {
FinalAssessment string
NextTopic string
StudyMinutes int
HasHomework bool
Homework string
}
Session struct {
Timestamp string
}
}
func (input *ProgressTracking) isProgressZero() bool {
return input.Progress.CurrentLesson == 0 &&
input.Progress.TotalLessons == 0 &&
input.Progress.StrugglingAreas == "" &&
input.Progress.StrengthAreas == ""
}
func (input *ProgressTracking) isStudentZero() bool {
return input.Student.CompletionPercentage == 0 &&
input.Student.StreakDays == 0 &&
input.Student.Name == ""
}
func (input *ProgressTracking) isNextStepsZero() bool {
return input.NextSteps.FinalAssessment == "" &&
input.NextSteps.NextTopic == "" &&
input.NextSteps.StudyMinutes == 0 &&
!input.NextSteps.HasHomework &&
input.NextSteps.Homework == ""
}
func (input *ProgressTracking) isSessionZero() bool {
return input.Session.Timestamp == ""
}
func (input *ProgressTracking) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.Progress.CurrentLesson)
var1 := strconv.Itoa(input.Progress.TotalLessons)
var2 := strconv.Itoa(input.NextSteps.StudyMinutes)
length := 0
length += 46
length += len(var0)
length += 1
length += len(var1)
length += 31
length += len(strconv.Itoa(input.Student.CompletionPercentage))
length += 3
if input.Student.StreakDays >= 7 {
length += 31
length += len(strconv.Itoa(input.Student.StreakDays))
length += 23
if input.Student.StreakDays >= 30 {
length += 66
}
length += 2
if input.Progress.StrugglingAreas != "" {
length += 74
length += len(input.Progress.StrugglingAreas)
length += 1
}
length += 2
if input.Progress.StrengthAreas != "" {
length += 46
length += len(input.Progress.StrengthAreas)
length += 1
}
length += 22
if input.Student.CompletionPercentage >= 80 {
length += 74
length += len(input.NextSteps.FinalAssessment)
length += 1
}
length += 2
if input.Student.CompletionPercentage < 80 {
length += 18
length += len(input.NextSteps.NextTopic)
length += 29
length += len(var2)
length += 10
if input.NextSteps.HasHomework {
length += 26
length += len(input.NextSteps.Homework)
length += 1
}
length += 1
}
length += 31
length += len(input.Student.Name)
length += 31
length += len(input.Session.Timestamp)
length += 2
}
b.Grow(length)
b.WriteString(`## ๐ Your Progress
**Lesson Completion**: `)
b.WriteString(var0)
b.WriteString(`/`)
b.WriteString(var1)
b.WriteString(` lessons
**Overall Progress**: `)
b.WriteString(strconv.Itoa(input.Student.CompletionPercentage))
b.WriteString(`%
`)
if input.Student.StreakDays >= 7 {
b.WriteString(`
๐ **Amazing!** You're on a `)
b.WriteString(strconv.Itoa(input.Student.StreakDays))
b.WriteString(`-day learning streak!
`)
if input.Student.StreakDays >= 30 {
b.WriteString(`
๐ **Legendary Learner!** 30+ day streak - you're unstoppable!
`)
}
b.WriteString(`
`)
if input.Progress.StrugglingAreas != "" {
b.WriteString(`
### ๐ Areas for Review
Based on your performance, consider reviewing:
`)
b.WriteString(input.Progress.StrugglingAreas)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Progress.StrengthAreas != "" {
b.WriteString(`
### ๐ช Your Strengths
You're excelling in:
`)
b.WriteString(input.Progress.StrengthAreas)
b.WriteRune('\n')
}
b.WriteString(`
## ๐ฏ Next Steps
`)
if input.Student.CompletionPercentage >= 80 {
b.WriteString(`
๐ **Almost there!** You're ready for the final assessment.
**Next**: `)
b.WriteString(input.NextSteps.FinalAssessment)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Student.CompletionPercentage < 80 {
b.WriteString(`
**Next Lesson**: `)
b.WriteString(input.NextSteps.NextTopic)
b.WriteString(`
**Recommended Study Time**: `)
b.WriteString(var2)
b.WriteString(` minutes
`)
if input.NextSteps.HasHomework {
b.WriteString(`
**Homework Assignment**: `)
b.WriteString(input.NextSteps.Homework)
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
---
*Keep up the great work, `)
b.WriteString(input.Student.Name)
b.WriteString(`! ๐*
*Session completed at: `)
b.WriteString(input.Session.Timestamp)
b.WriteString(`* `)
}
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package minimaltest
import (
"strconv"
"strings"
)
type TestBasic struct {
Name string
}
func (input *TestBasic) String() string {
var b strings.Builder
length := 0
length += 29
length += len(input.Name)
length += 1
b.Grow(length)
b.WriteString("Simple test with backticks: `")
b.WriteString(input.Name)
b.WriteString("`")
return b.String()
}
type TestConditional struct {
User struct {
Premium bool
}
}
func (input *TestConditional) isUserZero() bool {
return !input.User.Premium
}
func (input *TestConditional) String() string {
var b strings.Builder
length := 0
if input.User.Premium {
length += 31
} else {
length += 31
}
b.Grow(length)
if input.User.Premium {
b.WriteString("\nPremium user with `backticks`\n")
} else {
b.WriteString("\nRegular user with `backticks`\n")
}
return b.String()
}
type TestNested struct {
Outer string
Inner string
}
func (input *TestNested) String() string {
var b strings.Builder
length := 0
if input.Outer != "" {
length += 13
if input.Inner != "" {
length += 15
}
length += 11
}
b.Grow(length)
if input.Outer != "" {
b.WriteString(`
Outer start
`)
if input.Inner != "" {
b.WriteString(`
Inner content
`)
}
b.WriteString(`
Outer end
`)
}
return b.String()
}
type TestComparison struct {
Age int
}
func (input *TestComparison) String() string {
var b strings.Builder
length := 0
if input.Age >= 18 {
length += 24
length += len(strconv.Itoa(input.Age))
length += 2
} else {
length += 23
length += len(strconv.Itoa(input.Age))
length += 2
}
length += 1
b.Grow(length)
if input.Age >= 18 {
b.WriteString(`
You are an adult (age: `)
b.WriteString(strconv.Itoa(input.Age))
b.WriteString(`)
`)
} else {
b.WriteString(`
You are a minor (age: `)
b.WriteString(strconv.Itoa(input.Age))
b.WriteString(`)
`)
}
b.WriteString(` `)
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package simpleapidocs
import (
"strconv"
"strings"
)
type ApiDocumentationGenerator struct{}
func (input *ApiDocumentationGenerator) String() string {
return `You are APIDocBot, an intelligent documentation generator that creates comprehensive, up-to-date API documentation with interactive examples, versioning support, and developer-friendly formatting.`
}
type ApiOverview struct {
Api struct {
Name string
Version string
BaseUrl string
Protocol string
AuthType string
Deprecated bool
ReplacementVersion string
SunsetDate string
Beta bool
StabilityLevel string
}
Changelog struct {
HasBreakingChanges bool
BreakingChanges string
NewFeatures string
Improvements string
BugFixes string
}
Docs struct {
MigrationUrl string
}
Auth struct {
Type string
Required bool
DashboardUrl string
OauthFlow string
Scopes string
AuthUrl string
TokenUrl string
HasScopes bool
ScopeList string
HeaderName string
QueryParam string
RateLimits bool
}
RateLimits struct {
StandardRequests int
StandardWindow string
PremiumRequests int
PremiumWindow string
HasBurst bool
BurstRequests int
BurstWindow string
}
}
func (input *ApiOverview) isApiZero() bool {
return input.Api.Name == "" &&
input.Api.Version == "" &&
input.Api.BaseUrl == "" &&
input.Api.Protocol == "" &&
input.Api.AuthType == "" &&
!input.Api.Deprecated &&
input.Api.ReplacementVersion == "" &&
input.Api.SunsetDate == "" &&
!input.Api.Beta &&
input.Api.StabilityLevel == ""
}
func (input *ApiOverview) isChangelogZero() bool {
return !input.Changelog.HasBreakingChanges &&
input.Changelog.BreakingChanges == "" &&
input.Changelog.NewFeatures == "" &&
input.Changelog.Improvements == "" &&
input.Changelog.BugFixes == ""
}
func (input *ApiOverview) isDocsZero() bool {
return input.Docs.MigrationUrl == ""
}
func (input *ApiOverview) isAuthZero() bool {
return input.Auth.Type == "" &&
!input.Auth.Required &&
input.Auth.DashboardUrl == "" &&
input.Auth.OauthFlow == "" &&
input.Auth.Scopes == "" &&
input.Auth.AuthUrl == "" &&
input.Auth.TokenUrl == "" &&
!input.Auth.HasScopes &&
input.Auth.ScopeList == "" &&
input.Auth.HeaderName == "" &&
input.Auth.QueryParam == "" &&
!input.Auth.RateLimits
}
func (input *ApiOverview) isRateLimitsZero() bool {
return input.RateLimits.StandardRequests == 0 &&
input.RateLimits.StandardWindow == "" &&
input.RateLimits.PremiumRequests == 0 &&
input.RateLimits.PremiumWindow == "" &&
!input.RateLimits.HasBurst &&
input.RateLimits.BurstRequests == 0 &&
input.RateLimits.BurstWindow == ""
}
func (input *ApiOverview) String() string {
var b strings.Builder
var0 := strconv.Itoa(input.RateLimits.StandardRequests)
var1 := strconv.Itoa(input.RateLimits.PremiumRequests)
var2 := strconv.Itoa(input.RateLimits.BurstRequests)
length := 0
length += 7
length += len(input.Api.Name)
length += 33
length += len(input.Api.Version)
length += 16
length += len(input.Api.BaseUrl)
length += 16
length += len(input.Api.Protocol)
length += 21
length += len(input.Api.AuthType)
length += 2
if input.Api.Deprecated {
length += 86
length += len(input.Api.ReplacementVersion)
length += 19
length += len(input.Api.SunsetDate)
length += 1
}
length += 2
if input.Api.Beta {
length += 92
length += len(input.Api.StabilityLevel)
length += 3
}
length += 25
length += len(input.Api.Version)
length += 2
if input.Changelog.HasBreakingChanges {
length += 27
length += len(input.Changelog.BreakingChanges)
length += 59
length += len(input.Docs.MigrationUrl)
length += 28
}
length += 2
if input.Changelog.NewFeatures != "" {
length += 22
length += len(input.Changelog.NewFeatures)
length += 1
}
length += 2
if input.Changelog.Improvements != "" {
length += 23
length += len(input.Changelog.Improvements)
length += 1
}
length += 2
if input.Changelog.BugFixes != "" {
length += 20
length += len(input.Changelog.BugFixes)
length += 1
}
length += 36
length += len(input.Auth.Type)
length += 15
length += 5
length += 2
if input.Auth.Type == "bearer" {
length += 176
length += len(input.Auth.DashboardUrl)
length += 2
}
length += 2
if input.Auth.Type == "oauth2" {
length += 40
length += len(input.Auth.OauthFlow)
length += 13
length += len(input.Auth.Scopes)
length += 26
length += len(input.Auth.AuthUrl)
length += 18
length += len(input.Auth.TokenUrl)
length += 3
if input.Auth.HasScopes {
length += 23
length += len(input.Auth.ScopeList)
length += 1
} else {
length += 13
length += 5
length += 1
}
length += 1
}
length += 2
if input.Auth.Type == "apikey" {
length += 41
length += len(input.Auth.HeaderName)
length += 24
length += len(input.Auth.QueryParam)
length += 25
length += len(input.Auth.HeaderName)
length += 19
}
length += 2
if input.Auth.RateLimits {
length += 41
length += len(var0)
length += 10
length += len(input.RateLimits.StandardWindow)
length += 19
length += len(var1)
length += 10
length += len(input.RateLimits.PremiumWindow)
length += 165
if input.RateLimits.HasBurst {
length += 22
length += len(var2)
length += 13
length += len(input.RateLimits.BurstWindow)
length += 9
}
length += 1
}
length += 1
b.Grow(length)
b.WriteString(`# ๐ก `)
b.WriteString(input.Api.Name)
b.WriteString(` API Documentation
**Version**: `)
b.WriteString(input.Api.Version)
b.WriteString("\n**Base URL**: `")
b.WriteString(input.Api.BaseUrl)
b.WriteString("`\n**Protocol**: ")
b.WriteString(input.Api.Protocol)
b.WriteString(`
**Authentication**: `)
b.WriteString(input.Api.AuthType)
b.WriteString(`
`)
if input.Api.Deprecated {
b.WriteString(`
โ ๏ธ **DEPRECATED API**: This API version is deprecated. Please migrate to version `)
b.WriteString(input.Api.ReplacementVersion)
b.WriteString(`.
**Sunset Date**: `)
b.WriteString(input.Api.SunsetDate)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Api.Beta {
b.WriteString(`
๐งช **BETA API**: This API is in beta. Features may change without notice.
**Stability**: `)
b.WriteString(input.Api.StabilityLevel)
b.WriteString(`/5
`)
}
b.WriteString(`
## ๐ What's New in v`)
b.WriteString(input.Api.Version)
b.WriteString(`
`)
if input.Changelog.HasBreakingChanges {
b.WriteString(`
### ๐ฅ Breaking Changes
`)
b.WriteString(input.Changelog.BreakingChanges)
b.WriteString(`
โ ๏ธ **Migration Required**: See our [migration guide](`)
b.WriteString(input.Docs.MigrationUrl)
b.WriteString(`) for upgrade instructions.
`)
}
b.WriteString(`
`)
if input.Changelog.NewFeatures != "" {
b.WriteString(`
### โจ New Features
`)
b.WriteString(input.Changelog.NewFeatures)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Changelog.Improvements != "" {
b.WriteString(`
### ๐ Improvements
`)
b.WriteString(input.Changelog.Improvements)
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Changelog.BugFixes != "" {
b.WriteString(`
### ๐ Bug Fixes
`)
b.WriteString(input.Changelog.BugFixes)
b.WriteRune('\n')
}
b.WriteString(`
## ๐ Authentication
**Type**: `)
b.WriteString(input.Auth.Type)
b.WriteString(`
**Required**: `)
b.WriteString(strconv.FormatBool(input.Auth.Required))
b.WriteString(`
`)
if input.Auth.Type == "bearer" {
b.WriteString("\n### Bearer Token Authentication\nInclude your API key in the Authorization header:\n\n```http\nAuthorization: Bearer YOUR_API_KEY\n```\n\n**Get your API key**: [Developer Dashboard](")
b.WriteString(input.Auth.DashboardUrl)
b.WriteString(`)
`)
}
b.WriteString(`
`)
if input.Auth.Type == "oauth2" {
b.WriteString(`
### OAuth 2.0 Authentication
**Flow**: `)
b.WriteString(input.Auth.OauthFlow)
b.WriteString(`
**Scopes**: `)
b.WriteString(input.Auth.Scopes)
b.WriteString("\n\n**Authorization URL**: `")
b.WriteString(input.Auth.AuthUrl)
b.WriteString("`\n**Token URL**: `")
b.WriteString(input.Auth.TokenUrl)
b.WriteString("`\n\n")
if input.Auth.HasScopes {
b.WriteString(`
#### Required Scopes:
`)
b.WriteString(input.Auth.ScopeList)
b.WriteRune('\n')
} else {
b.WriteString(`
Has Scopes: `)
b.WriteString(strconv.FormatBool(input.Auth.HasScopes))
b.WriteRune('\n')
}
b.WriteRune('\n')
}
b.WriteString(`
`)
if input.Auth.Type == "apikey" {
b.WriteString("\n### API Key Authentication\n**Header**: `")
b.WriteString(input.Auth.HeaderName)
b.WriteString("`\n**Query Parameter**: `")
b.WriteString(input.Auth.QueryParam)
b.WriteString("` (alternative)\n\n```http\n")
b.WriteString(input.Auth.HeaderName)
b.WriteString(": YOUR_API_KEY\n```\n")
}
b.WriteString(`
`)
if input.Auth.RateLimits {
b.WriteString(`
## ๐ Rate Limits
**Standard Tier**: `)
b.WriteString(var0)
b.WriteString(` requests/`)
b.WriteString(input.RateLimits.StandardWindow)
b.WriteString(`
**Premium Tier**: `)
b.WriteString(var1)
b.WriteString(` requests/`)
b.WriteString(input.RateLimits.PremiumWindow)
b.WriteString("\n\n**Rate Limit Headers**:\n- `X-RateLimit-Limit`: Total requests allowed\n- `X-RateLimit-Remaining`: Requests remaining\n- `X-RateLimit-Reset`: Time when limit resets\n\n")
if input.RateLimits.HasBurst {
b.WriteString(`
**Burst Allowance**: `)
b.WriteString(var2)
b.WriteString(` requests in `)
b.WriteString(input.RateLimits.BurstWindow)
b.WriteString(` seconds
`)
}
b.WriteRune('\n')
}
b.WriteRune('\n')
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package simplest
import (
"strings"
)
type ApiDocumentationGenerator struct{}
func (input *ApiDocumentationGenerator) String() string {
return `You are APIDocBot, an intelligent documentation generator that creates comprehensive, up-to-date API documentation with interactive examples, versioning support, and developer-friendly formatting.`
}
type ApiOverview struct {
Api struct {
Name string
BaseUrl string
Protocol string
AuthType string
}
}
func (input *ApiOverview) isApiZero() bool {
return input.Api.Name == "" &&
input.Api.BaseUrl == "" &&
input.Api.Protocol == "" &&
input.Api.AuthType == ""
}
func (input *ApiOverview) String() string {
var b strings.Builder
length := 0
length += 7
length += len(input.Api.Name)
length += 35
length += len(input.Api.BaseUrl)
length += 16
length += len(input.Api.Protocol)
length += 21
length += len(input.Api.AuthType)
b.Grow(length)
b.WriteString(`# ๐ก `)
b.WriteString(input.Api.Name)
b.WriteString(" API Documentation\n\n**Base URL**: `")
b.WriteString(input.Api.BaseUrl)
b.WriteString("`\n**Protocol**: ")
b.WriteString(input.Api.Protocol)
b.WriteString(`
**Authentication**: `)
b.WriteString(input.Api.AuthType)
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package hellowithoutnewlines
import (
"strings"
)
type SystemPrompt struct{}
func (input *SystemPrompt) String() string {
return `You are HelloBot, a simple assistant that loves to say hello to users.
Your only purpose is to greet users in a friendly way and say "Hello, World!" with some variation.
Keep your responses short, cheerful, and hello-focused.`
}
type CreateTitle struct {
Messages string
}
func (input *CreateTitle) String() string {
var b strings.Builder
length := 0
length += 54
length += len(input.Messages)
length += 8
b.Grow(length)
b.WriteString(`Create a simple hello-themed title for this exchange:
`)
b.WriteString(input.Messages)
b.WriteString(`
title: `)
return b.String()
}
type ChatWithUser struct {
PreviousMessages string
}
func (input *ChatWithUser) String() string {
var b strings.Builder
length := 0
length += 41
length += len(input.PreviousMessages)
length += 11
b.Grow(length)
b.WriteString(`Say hello to the user in a cheerful way:
`)
b.WriteString(input.PreviousMessages)
b.WriteString(`
HelloBot: `)
return b.String()
}
// Code generated by agentflow v0.3.0; DO NOT EDIT.
package hello
import (
"strings"
)
type SystemPrompt struct{}
func (input *SystemPrompt) String() string {
return `You are HelloBot, a simple assistant that loves to say hello to users.
Your only purpose is to greet users in a friendly way and say "Hello, World!" with some variation.
Keep your responses short, cheerful, and hello-focused.
`
}
type CreateTitle struct {
Messages string
}
func (input *CreateTitle) String() string {
var b strings.Builder
length := 0
length += 54
length += len(input.Messages)
length += 8
b.Grow(length)
b.WriteString(`Create a simple hello-themed title for this exchange:
`)
b.WriteString(input.Messages)
b.WriteString(`
title:
`)
return b.String()
}
type ChatWithUser struct {
PreviousMessages string
}
func (input *ChatWithUser) String() string {
var b strings.Builder
length := 0
length += 41
length += len(input.PreviousMessages)
length += 11
b.Grow(length)
b.WriteString(`Say hello to the user in a cheerful way:
`)
b.WriteString(input.PreviousMessages)
b.WriteString(`
HelloBot:
`)
return b.String()
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package assert
import (
"fmt"
"log/slog"
"os"
"runtime"
)
func NoError(err error) {
if err != nil {
_, file, line, _ := runtime.Caller(1)
slog.Error(fmt.Sprintf(
"%s:%d: unexpected error: %v",
file, line, err,
))
os.Exit(1)
}
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package require
import (
"errors"
"fmt"
"runtime"
"strings"
"testing"
)
type Equaler[T any] interface {
Equal(actual T) bool
}
func EqualErr(t *testing.T, want, got error) {
if !errors.Is(want, got) {
// Get caller info for clickable file:line
_, file, line, ok := runtime.Caller(1)
if ok {
t.Fatalf("%s:%d: expected %v, got %v", file, line, want, got)
} else {
t.Fatalf("expected %v, got %v", want, got)
}
}
}
func Equal[T Equaler[T]](t *testing.T, want, got T) {
if !want.Equal(got) {
var sb strings.Builder
// Get caller info for clickable file:line
_, file, line, ok := runtime.Caller(1)
if ok {
sb.WriteString(fmt.Sprintf("%s:%d: ", file, line))
}
sb.WriteString("Should equal:\n")
WantGotDiff(&sb, want, got)
t.Fatal(sb.String())
}
}
func NotEqual[T Equaler[T]](t *testing.T, want, got T) {
if want.Equal(got) {
var sb strings.Builder
// Get caller info for clickable file:line
_, file, line, ok := runtime.Caller(1)
if ok {
sb.WriteString(fmt.Sprintf("%s:%d: ", file, line))
}
sb.WriteString("Should not equal:\n")
WantGotDiff(&sb, want, got)
t.Fatal(sb.String())
}
}
func NoError(t *testing.T, err error) {
if err != nil {
// Get caller info for clickable file:line
_, file, line, ok := runtime.Caller(1)
if ok {
t.Fatalf("%s:%d: expected no error, got %v", file, line, err)
} else {
t.Fatalf("expected no error, got %v", err)
}
}
}
// makeWhitespaceVisible replaces whitespace characters with visible representations
func makeWhitespaceVisible(s string) string {
s = strings.ReplaceAll(s, " ", "ยท")
s = strings.ReplaceAll(s, "\t", "โ")
s = strings.ReplaceAll(s, "\n", "โต\n")
s = strings.ReplaceAll(s, "\r", "โคด")
return s
}
// WantGotDiff shows a diff-style comparison with visible whitespace
func WantGotDiff(sb *strings.Builder, want, got any) {
var wantStr, gotStr string
if s, ok := want.(fmt.Stringer); ok {
wantStr = s.String()
} else {
wantStr = fmt.Sprintf("%+v", want)
}
if s, ok := got.(fmt.Stringer); ok {
gotStr = s.String()
} else {
gotStr = fmt.Sprintf("%+v", got)
}
wantLines := strings.Split(wantStr, "\n")
gotLines := strings.Split(gotStr, "\n")
sb.WriteString("\n\x1b[1mDIFF:\x1b[0m\n")
maxLines := len(wantLines)
if len(gotLines) > maxLines {
maxLines = len(gotLines)
}
for i := 0; i < maxLines; i++ {
var wantLine, gotLine string
if i < len(wantLines) {
wantLine = wantLines[i]
}
if i < len(gotLines) {
gotLine = gotLines[i]
}
if wantLine == gotLine {
sb.WriteString(fmt.Sprintf(" %s\n", makeWhitespaceVisible(wantLine)))
} else {
if wantLine != "" {
sb.WriteString(fmt.Sprintf("\x1b[31m- %s\x1b[0m\n", makeWhitespaceVisible(wantLine)))
}
if gotLine != "" {
sb.WriteString(fmt.Sprintf("\x1b[32m+ %s\x1b[0m\n", makeWhitespaceVisible(gotLine)))
}
}
}
}
func WantGot(sb *strings.Builder, want, got any) {
sb.WriteString("\x1b[1mWANT:\x1b[0m\n")
if s, ok := want.(fmt.Stringer); ok {
sb.WriteString(s.String())
} else {
fmt.Fprintf(sb, "%+v", want)
}
sb.WriteString("\n\x1b[1mGOT:\x1b[0m\n")
if s, ok := got.(fmt.Stringer); ok {
sb.WriteString(s.String())
} else {
fmt.Fprintf(sb, "%+v", got)
}
}
func WantGotBoldQuotes(sb *strings.Builder, want, got any) {
sb.WriteString("\x1b[1mWANT:\x1b[0m\n")
sb.WriteString("\x1b[1m|\x1b[0m")
if s, ok := want.(fmt.Stringer); ok {
sb.WriteString(s.String())
} else {
fmt.Fprintf(sb, "%+v", want)
}
sb.WriteString("\x1b[1m|\x1b[0m")
sb.WriteString("\n\x1b[1mGOT:\x1b[0m\n")
sb.WriteString("\x1b[1m|\x1b[0m")
if s, ok := got.(fmt.Stringer); ok {
sb.WriteString(s.String())
} else {
fmt.Fprintf(sb, "%+v", got)
}
sb.WriteString("\x1b[1m|\x1b[0m")
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ast
import (
"bytes"
"fmt"
"log/slog"
"slices"
"strings"
"github.com/omniaura/agentflow/pkg/token"
"github.com/omniaura/agentflow/pkg/token/kind"
"github.com/peyton-spencer/caseconv"
"github.com/peyton-spencer/caseconv/bytcase"
)
type File struct {
Name string
Content []byte
Prompts []Prompt
}
func (f File) String() string {
var sb strings.Builder
sb.WriteString("File{\n")
sb.WriteString(fmt.Sprintf(" Name: %s,\n", f.Name))
sb.WriteString(" Prompts: [\n")
for i, prompt := range f.Prompts {
sb.WriteString(" ")
sb.WriteString(prompt.Stringify(f.Content))
if i < len(f.Prompts)-1 {
sb.WriteString(",")
}
sb.WriteString("\n")
}
sb.WriteString(" ]\n")
sb.WriteRune('}')
return sb.String()
}
func (f1 File) Equal(f2 File) bool {
e := f1.Name == f2.Name && bytes.Equal(f1.Content, f2.Content)
if !e {
return false
}
if len(f1.Prompts) != len(f2.Prompts) {
return false
}
for i, p1 := range f1.Prompts {
if !p1.Equal(f2.Prompts[i]) {
return false
}
}
return true
}
type Prompt struct {
// Title is the name of the prompt.
Title token.T
// Nodes are the nodes of the prompt.
Nodes token.Slice
}
func (p Prompt) Stringify(content []byte) string {
var buf strings.Builder
buf.WriteString("Prompt{Title: ")
buf.Write(content[p.Title.Start:p.Title.End])
buf.WriteString(", Nodes: ")
for i, node := range p.Nodes {
buf.WriteString(node.Stringify(content))
if i < len(p.Nodes)-1 {
buf.WriteString(", ")
}
}
buf.WriteRune('}')
return buf.String()
}
func (p Prompt) Vars(content []byte, c caseconv.Case) (vars [][]byte, length int) {
vars = make([][]byte, 0, len(p.Nodes))
for _, node := range p.Nodes {
if node.Kind == kind.Var {
name := node.Get(content)
if slices.ContainsFunc(vars, func(b []byte) bool { return bytes.Equal(b, name) }) {
continue
}
vars = append(vars, name)
}
}
for i := range vars {
switch c {
case caseconv.CaseCamel:
vars[i] = bytcase.ToLowerCamel(vars[i])
case caseconv.CaseSnake:
vars[i] = bytcase.ToSnake(vars[i])
}
length += len(vars[i])
}
return
}
type InputStruct struct {
TopLevel []InputNode
}
func (i InputStruct) Equal(other InputStruct) bool {
return slices.EqualFunc(i.TopLevel, other.TopLevel, InputNode.Equal)
}
func (i InputStruct) String() string {
var buf strings.Builder
buf.WriteString("type Input struct {\n")
for _, n := range i.TopLevel {
buf.WriteString(" ")
buf.Write(n.Name)
buf.WriteString(" ")
buf.WriteString(n.String())
buf.WriteString("\n")
}
buf.WriteString("}")
return buf.String()
}
type InputNode struct {
Name []byte
Type string // New: type of the variable ("string", "int", "bool", etc.)
Subnodes []InputNode
}
func (n InputNode) Equal(other InputNode) bool {
return bytes.Equal(n.Name, other.Name) && n.Type == other.Type && slices.EqualFunc(n.Subnodes, other.Subnodes, InputNode.Equal)
}
func (n InputNode) String() string {
if len(n.Subnodes) == 0 {
if n.Type == "" {
return "string"
}
return n.Type
}
var buf strings.Builder
buf.WriteString("struct {\n")
for _, sub := range n.Subnodes {
buf.WriteString(" ")
buf.Write(sub.Name)
buf.WriteString(" ")
buf.WriteString(sub.String())
buf.WriteString("\n")
}
buf.WriteString(" }")
return buf.String()
}
func (ii *InputStruct) insertVar(node token.T, content []byte, c caseconv.Case, typeCache map[string]string) {
varInfo := node.GetVar(content, typeCache)
if len(varInfo.Path) == 0 {
return
}
// Insert all path parts and set their types based on the cache
ii.insertVarWithCache(varInfo.Path, varInfo.Type, c, typeCache)
}
func (ii *InputStruct) insertVarWithCache(path [][]byte, typ string, c caseconv.Case, typeCache map[string]string) {
if len(path) == 0 {
return
}
nn := c.BytCase(path[0])
idx := slices.IndexFunc(ii.TopLevel, func(n InputNode) bool {
return bytes.Equal(n.Name, nn)
})
if idx == -1 {
newNode := InputNode{Name: nn}
ii.TopLevel = append(ii.TopLevel, newNode)
idx = len(ii.TopLevel) - 1
}
if len(path) == 1 {
// This is a leaf node, set its type from the cache
pathKey := string(bytes.Join(path, []byte(".")))
if cachedType, exists := typeCache[pathKey]; exists && cachedType != "" {
ii.TopLevel[idx].Type = cachedType
} else if ii.TopLevel[idx].Type == "" {
ii.TopLevel[idx].Type = typ
}
return
}
// Check if this intermediate node should be a struct
pathKey := string(bytes.Join(path[:1], []byte(".")))
if cachedType, exists := typeCache[pathKey]; exists && cachedType == "struct" {
ii.TopLevel[idx].Type = "struct"
}
// We're adding nested fields
ii.TopLevel[idx].insertMultiLevelVarWithCache(path[1:], typ, c, typeCache, path[:1])
}
func (n *InputNode) insertMultiLevelVarWithCache(path [][]byte, typ string, c caseconv.Case, typeCache map[string]string, parentPath [][]byte) {
if len(path) == 0 {
slog.Debug("0 len name reached")
return
}
nn := c.BytCase(path[0])
idx := slices.IndexFunc(n.Subnodes, func(n InputNode) bool {
return bytes.Equal(n.Name, nn)
})
if idx == -1 {
newNode := InputNode{Name: nn}
n.Subnodes = append(n.Subnodes, newNode)
idx = len(n.Subnodes) - 1
}
// Build full path for cache lookup
fullPath := make([][]byte, len(parentPath)+1)
copy(fullPath, parentPath)
fullPath[len(parentPath)] = path[0]
if len(path) == 1 {
// This is a leaf node, set its type from the cache or the provided type
pathKey := string(bytes.Join(fullPath, []byte(".")))
if cachedType, exists := typeCache[pathKey]; exists && cachedType != "" {
n.Subnodes[idx].Type = cachedType
} else if n.Subnodes[idx].Type == "" {
n.Subnodes[idx].Type = typ
}
return
}
// Check if this intermediate node should be a struct
pathKey := string(bytes.Join(fullPath, []byte(".")))
if cachedType, exists := typeCache[pathKey]; exists && cachedType == "struct" {
n.Subnodes[idx].Type = "struct"
}
// We're adding nested fields
n.Subnodes[idx].insertMultiLevelVarWithCache(path[1:], typ, c, typeCache, fullPath)
}
func (p Prompt) GetInputs(content []byte, c caseconv.Case) (ii InputStruct, err error) {
typeCache := make(map[string]string)
allPaths := make(map[string]bool)
// First pass: collect all variable paths to understand the complete structure
for _, node := range p.Nodes {
switch node.Kind {
case kind.Var, kind.OptionalBlock:
varInfo := node.GetVar(content, typeCache)
if len(varInfo.Path) > 0 {
pathKey := string(bytes.Join(varInfo.Path, []byte(".")))
allPaths[pathKey] = true
// Store explicit type information
if varInfo.Type != "" && varInfo.Type != "string" {
typeCache[pathKey] = varInfo.Type
}
}
}
}
// Analyze paths to determine which should be structs
inferStructTypes(allPaths, typeCache)
// Second pass: build the struct with complete type information
for _, node := range p.Nodes {
switch node.Kind {
case kind.Var, kind.OptionalBlock:
ii.insertVar(node, content, c, typeCache)
}
}
// Post-process: set type to "struct" for nodes that have subnodes
for i := range ii.TopLevel {
ii.TopLevel[i].setStructTypes()
}
return
}
// inferStructTypes analyzes all variable paths to determine which should be struct types
// A path should be a struct if there are other paths that are extensions of it
func inferStructTypes(allPaths map[string]bool, typeCache map[string]string) {
for path := range allPaths {
// Check if this path has any children (i.e., other paths that start with this path + ".")
hasChildren := false
pathPrefix := path + "."
for otherPath := range allPaths {
if otherPath != path && strings.HasPrefix(otherPath, pathPrefix) {
hasChildren = true
break
}
}
// If this path has children and doesn't already have a non-struct type, mark it as struct
if hasChildren {
if existingType, exists := typeCache[path]; !exists || existingType == "" || existingType == "string" {
typeCache[path] = "struct"
}
}
}
}
// setStructTypes recursively sets the type to "struct" for nodes that have subnodes
func (n *InputNode) setStructTypes() {
if len(n.Subnodes) > 0 {
n.Type = "struct"
}
for i := range n.Subnodes {
n.Subnodes[i].setStructTypes()
}
}
func (p1 Prompt) Equal(p2 Prompt) bool {
return p1.Title == p2.Title && p1.Nodes.Equal(p2.Nodes)
}
func NewFile(name string, content []byte) (f File, err error) {
if !strings.HasSuffix(name, ".af") {
err = fmt.Errorf("file does not have .af extension: %s", name)
return
}
tokens, err := token.Tokenize(content)
if err != nil {
return
}
f.Name = strings.TrimSuffix(name, ".af")
f.Content = content
f.Prompts, err = newPrompts(tokens)
return
}
func newPrompts(tokens token.Slice) (prompts []Prompt, err error) {
for _, t := range tokens {
if t.Kind == kind.Title {
prompts = append(prompts, Prompt{Title: t})
} else if len(prompts) == 0 {
prompts = append(prompts, Prompt{Nodes: token.Slice{t}})
} else {
prompts[len(prompts)-1].Nodes = append(prompts[len(prompts)-1].Nodes, t)
}
}
return
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package errs
import (
"unique"
)
// TODO INTEGRATE WITH SLOG.ATTR
func New[M ~string](msg M) Error {
return Error{
msg: unique.Make(message(msg)),
}
}
// TODO USE ERROR STACK
func (e Error) Error() string {
return e.Msg().Error()
}
type Error struct {
msg unique.Handle[message]
stack []fmtErr
}
func (e Error) Msg() message {
return e.msg.Value()
}
type message string
func (m message) String() string {
return string(m)
}
func (m message) Error() string {
return string(m)
}
type fmtErr struct {
err error
msg string
args []any
}
// TODO CAPTURE RUNTIME.CALLER FOR ALL BELOW
func (e Error) S(msg string) Error {
e.stack = append(e.stack, fmtErr{msg: msg})
return e
}
func (e Error) F(msg string, args ...any) Error {
e.stack = append(e.stack, fmtErr{msg: msg, args: args})
return e
}
func (e Error) E(err error) Error {
e.stack = append(e.stack, fmtErr{err: err})
return e
}
func (e Error) ES(err error, msg string) Error {
e.stack = append(e.stack, fmtErr{err: err, msg: msg})
return e
}
func (e Error) EF(err error, fmt string, args ...any) Error {
e.stack = append(e.stack, fmtErr{err: err, msg: fmt, args: args})
return e
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package gogen
import (
"bytes"
"fmt"
"go/format"
"io"
"slices"
"strconv"
"strings"
"github.com/omniaura/agentflow/cfg"
"github.com/omniaura/agentflow/pkg/ast"
"github.com/omniaura/agentflow/pkg/gen"
"github.com/omniaura/agentflow/pkg/token"
"github.com/omniaura/agentflow/pkg/token/kind"
"github.com/peyton-spencer/caseconv"
"github.com/peyton-spencer/caseconv/bytcase"
)
var replacerPackageName = strings.NewReplacer(" ", "", "-", "", "_", "")
func GenInputStructs(w io.Writer, f ast.File) error {
var buf bytes.Buffer
// Track generated struct names to avoid duplicates
generatedStructs := make(map[string]bool)
for _, p := range f.Prompts {
inputs, err := p.GetInputs(f.Content, caseconv.CaseCamel)
if err != nil {
return err
}
// Generate embedded structs first
for _, node := range inputs.TopLevel {
if len(node.Subnodes) > 0 {
structName := string(node.Name)
if !generatedStructs[structName] {
generateEmbeddedStruct(&buf, node)
buf.WriteRune('\n')
generatedStructs[structName] = true
}
}
}
}
_, err := buf.WriteTo(w)
return err
}
func generateEmbeddedStruct(buf *bytes.Buffer, node ast.InputNode) {
buf.WriteString("type ")
buf.Write(node.Name)
if len(node.Subnodes) == 0 {
buf.WriteString(" struct{}")
buf.WriteString("\n")
return
}
buf.WriteString(" struct {\n")
for _, subnode := range node.Subnodes {
buf.WriteString("\t")
buf.Write(subnode.Name)
buf.WriteString(" ")
if len(subnode.Subnodes) > 0 {
buf.Write(subnode.Name)
} else {
buf.WriteString("string")
}
buf.WriteString("\n")
}
buf.WriteString("}\n")
}
func GenFile(w io.Writer, f ast.File) error {
var buf bytes.Buffer
fmt.Fprintf(&buf, "// Code generated by agentflow v%s; DO NOT EDIT.\n\n", cfg.Version)
buf.WriteString("package ")
buf.WriteString(strings.ToLower(replacerPackageName.Replace(f.Name)))
buf.WriteString("\n\n")
// Collect required imports for all prompts
imports := map[string]bool{"strings": false, "strconv": false}
for _, p := range f.Prompts {
typeCache := make(map[string]string)
for _, t := range p.Nodes {
switch t.Kind {
case kind.Var:
vi := t.GetVar(f.Content, typeCache)
switch vi.Type {
case "int", "bool", "float32", "float64":
imports["strconv"] = true
}
fallthrough
case kind.OptionalBlock:
imports["strings"] = true
}
}
}
// Emit import block if needed
importList := []string{}
for k, v := range imports {
if v {
importList = append(importList, k)
}
}
if len(importList) > 0 {
slices.Sort(importList)
buf.WriteString("import (\n")
for _, imp := range importList {
buf.WriteString("\t\"")
buf.WriteString(imp)
buf.WriteString("\"\n")
}
buf.WriteString(")\n\n")
}
if len(f.Prompts) == 0 {
return gen.ErrNoPrompts
}
for i, p := range f.Prompts {
if p.Title.Kind == kind.Unset && len(f.Prompts) > 1 {
return gen.ErrMissingTitle.F("index: %d", i)
}
// Get the struct name
var structName []byte
if p.Title.Kind == kind.Title {
structName = bytcase.ToCamel(p.Title.Get(f.Content))
} else {
structName = bytcase.ToCamel([]byte(f.Name))
}
// Generate the struct
inputs, err := p.GetInputs(f.Content, caseconv.CaseCamel)
if err != nil {
return err
}
writeRootStruct(&buf, structName, inputs)
// Generate IsZero methods for nested structs
generateIsZeroMethods(&buf, structName, inputs)
// Generate the String method
buf.WriteString("func (input *")
buf.Write(structName)
buf.WriteString(") String() string {\n")
vars, _ := p.Vars(f.Content, caseconv.CaseCamel)
hasVariables := len(vars) > 0
// Also check for conditionals or any complex tokens that need processing
hasComplexTokens := false
for _, t := range p.Nodes {
if t.Kind == kind.OptionalBlock || t.Kind == kind.ElseBlock || t.Kind == kind.EndTag {
hasComplexTokens = true
break
}
}
if hasVariables || hasComplexTokens {
stringTemplateWithStruct(&buf, p.Nodes, f.Content, inputs)
} else {
stringTemplate(&buf, p.Nodes, f.Content)
}
if i < len(f.Prompts)-1 {
buf.WriteRune('\n')
}
}
outputBytes := buf.Bytes()
formattedBytes, err := format.Source(outputBytes)
if err != nil {
return fmt.Errorf("failed to format code: %w", err)
}
_, err = w.Write(formattedBytes)
return err
}
// generateIsZeroMethods generates IsXxxZero() methods for nested struct fields
func generateIsZeroMethods(buf *bytes.Buffer, structName []byte, inputs ast.InputStruct) {
generateIsZeroMethodsRecursive(buf, structName, inputs.TopLevel, []string{})
}
func generateIsZeroMethodsRecursive(buf *bytes.Buffer, structName []byte, nodes []ast.InputNode, fieldPath []string) {
for _, node := range nodes {
if len(node.Subnodes) > 0 && node.Type == "struct" {
// Generate isZero method for this nested struct (private)
currentPath := append(fieldPath, string(node.Name))
methodName := "is" + strings.Join(currentPath, "") + "Zero"
buf.WriteString("func (input *")
buf.Write(structName)
buf.WriteString(") ")
buf.WriteString(methodName)
buf.WriteString("() bool {\n")
// Build the field access path
fieldAccess := "input"
for _, part := range currentPath {
fieldAccess += "." + part
}
// Generate zero value checks for all fields
buf.WriteString("\treturn ")
for i, subnode := range node.Subnodes {
if i > 0 {
buf.WriteString(" &&\n\t\t")
}
fieldRef := fieldAccess + "." + string(subnode.Name)
// Check if this subnode is a struct (has subnodes)
if len(subnode.Subnodes) > 0 {
// Use the isZero method for struct types
currentPathForSubnode := append(currentPath, string(subnode.Name))
subnodeMethodName := "is" + strings.Join(currentPathForSubnode, "") + "Zero"
buf.WriteString("input." + subnodeMethodName + "()")
} else {
switch subnode.Type {
case "bool":
buf.WriteString("!" + fieldRef)
case "int", "float32", "float64":
buf.WriteString(fieldRef + " == 0")
default: // string and other types
buf.WriteString(fieldRef + " == \"\"")
}
}
}
buf.WriteString("\n}\n\n")
// Recursively generate methods for deeper nested structs
generateIsZeroMethodsRecursive(buf, structName, node.Subnodes, currentPath)
}
}
}
func writeRootStruct(buf *bytes.Buffer, structName []byte, inputs ast.InputStruct) {
buf.WriteString("type ")
buf.Write(structName)
if len(inputs.TopLevel) == 0 {
buf.WriteString(" struct{}\n\n")
return
}
buf.WriteString(" struct {\n")
for _, node := range inputs.TopLevel {
if len(node.Subnodes) > 0 && (node.Type == "struct" || node.Type == "") {
// Generate the embedded struct inline
buf.WriteString("\t")
buf.Write(node.Name)
buf.WriteString(" struct {\n")
generateStructFields(buf, node.Subnodes, 2)
buf.WriteString("\t}\n")
} else {
buf.WriteString("\t")
buf.Write(node.Name)
buf.WriteString(" ")
buf.WriteString(goTypeFor(node.Type))
buf.WriteString("\n")
}
}
buf.WriteString("}\n\n")
}
func generateStructFields(buf *bytes.Buffer, nodes []ast.InputNode, indent int) {
for _, node := range nodes {
for range indent {
buf.WriteString("\t")
}
buf.Write(node.Name)
buf.WriteString(" ")
if len(node.Subnodes) > 0 && (node.Type == "struct" || node.Type == "") {
buf.WriteString("struct {\n")
generateStructFields(buf, node.Subnodes, indent+1)
for range indent {
buf.WriteString("\t")
}
buf.WriteString("}")
} else {
buf.WriteString(goTypeFor(node.Type))
}
buf.WriteString("\n")
}
}
// goTypeFor returns the Go type for a given type string (default: string)
func goTypeFor(typ string) string {
switch typ {
case "int":
return "int"
case "bool":
return "bool"
case "float32":
return "float32"
case "float64":
return "float64"
case "struct":
return "struct{}" // fallback, should not be used for leaf
case "":
return "string"
default:
return "string"
}
}
func stringTemplate(buf *bytes.Buffer, toks token.Slice, content []byte) {
buf.WriteString("\treturn `")
for _, t := range toks {
buf.Write(t.Get(content))
}
buf.WriteString("`\n}\n")
}
func stringTemplateWithStruct(buf *bytes.Buffer, toks token.Slice, content []byte, inputs ast.InputStruct) {
buf.WriteString("\tvar b strings.Builder\n")
// Create type cache to track variable types
typeCache := make(map[string]string)
// Create mapping from variable paths to local variable names for numeric variables
numericVarMap := make(map[string]string)
var varDecls []string
varCounter := 0
// First pass: identify which numeric variables are actually used for output (kind.Var)
usedInOutput := make(map[string]bool)
for _, t := range toks {
if t.Kind == kind.Var {
vi := t.GetVar(content, typeCache)
if vi.Type == "int" || vi.Type == "float32" || vi.Type == "float64" {
pathKey := string(bytes.Join(vi.Path, []byte(".")))
usedInOutput[pathKey] = true
}
}
}
// Second pass: pre-declare string conversions only for numeric variables used in output
for _, t := range toks {
if t.Kind == kind.Var || t.Kind == kind.OptionalBlock {
vi := t.GetVar(content, typeCache)
pathKey := string(bytes.Join(vi.Path, []byte(".")))
// Only create string conversion if this variable is actually used for output
if usedInOutput[pathKey] {
if _, exists := numericVarMap[pathKey]; !exists {
switch vi.Type {
case "int":
localVar := "var" + strconv.Itoa(varCounter)
numericVarMap[pathKey] = localVar
varDecls = append(varDecls, localVar+" := strconv.Itoa("+varFieldAccess(vi.Path)+")")
varCounter++
case "float32":
localVar := "var" + strconv.Itoa(varCounter)
numericVarMap[pathKey] = localVar
varDecls = append(varDecls, localVar+" := strconv.FormatFloat(float64("+varFieldAccess(vi.Path)+"), 'g', -1, 32)")
varCounter++
case "float64":
localVar := "var" + strconv.Itoa(varCounter)
numericVarMap[pathKey] = localVar
varDecls = append(varDecls, localVar+" := strconv.FormatFloat("+varFieldAccess(vi.Path)+", 'g', -1, 64)")
varCounter++
}
}
}
}
}
// Emit variable declarations
for _, decl := range varDecls {
buf.WriteString("\t")
buf.WriteString(decl)
buf.WriteString("\n")
}
// First pass: Generate length calculation code
buf.WriteString("\tlength := 0\n")
generateLengthCalculation(buf, toks, content, typeCache, numericVarMap, inputs)
// Grow the buffer
buf.WriteString("\tb.Grow(length)\n")
// Second pass: Generate the actual string building code
generateStringBuilding(buf, toks, content, typeCache, numericVarMap, inputs)
buf.WriteString("\treturn b.String()\n}\n")
}
func generateLengthCalculation(buf *bytes.Buffer, toks token.Slice, content []byte, typeCache map[string]string, numericVarMap map[string]string, inputs ast.InputStruct) {
conditionalStack := []bool{} // Track nested conditionals
indentLevel := 1
for _, t := range toks {
switch t.Kind {
case kind.Var:
vi := t.GetVar(content, typeCache)
writeIndent(buf, indentLevel)
buf.WriteString("length += ")
pathKey := string(bytes.Join(vi.Path, []byte(".")))
switch vi.Type {
case "int", "float32", "float64":
if localVar, exists := numericVarMap[pathKey]; exists {
buf.WriteString("len(" + localVar + ")")
} else {
// Variable not pre-declared (only used in conditionals), calculate length inline
switch vi.Type {
case "int":
buf.WriteString("len(strconv.Itoa(" + varFieldAccess(vi.Path) + "))")
case "float32":
buf.WriteString("len(strconv.FormatFloat(float64(" + varFieldAccess(vi.Path) + "), 'g', -1, 32))")
case "float64":
buf.WriteString("len(strconv.FormatFloat(" + varFieldAccess(vi.Path) + ", 'g', -1, 64))")
}
}
case "bool":
buf.WriteString("5") // max length for "false"
default:
buf.WriteString("len(" + varFieldAccess(vi.Path) + ")")
}
buf.WriteString("\n")
case kind.OptionalBlock:
conditionalStack = append(conditionalStack, true)
indentLevel++
vi := t.GetVar(content, typeCache)
writeIndent(buf, indentLevel-1)
buf.WriteString("if ")
// Generate conditional expression
if vi.Operator != "" {
// Custom operator expression
buf.WriteString(varFieldAccess(vi.Path))
buf.WriteString(" ")
buf.WriteString(convertWordOperatorToGo(vi.Operator))
buf.WriteString(" ")
buf.WriteString(vi.Operand) // Use vi.Operand directly (already formatted)
} else {
// Default truthiness check
if isStructPath(vi.Path, inputs) {
// Use the private isZero method for struct types
buf.WriteString("!")
buf.WriteString(generateIsZeroMethodCall(vi.Path))
} else {
switch vi.Type {
case "bool":
// just check if true
buf.WriteString(varFieldAccess(vi.Path))
case "int":
buf.WriteString(varFieldAccess(vi.Path))
buf.WriteString(" != 0")
default:
buf.WriteString(varFieldAccess(vi.Path))
buf.WriteString(" != \"\"")
}
}
}
buf.WriteString(" {\n")
case kind.ElseBlock:
writeIndent(buf, indentLevel-1)
buf.WriteString("} else {\n")
case kind.EndTag:
if len(conditionalStack) > 0 {
conditionalStack = conditionalStack[:len(conditionalStack)-1]
indentLevel--
writeIndent(buf, indentLevel)
buf.WriteString("}\n")
}
default:
// static text
textContent := t.Get(content)
if len(textContent) > 0 {
writeIndent(buf, indentLevel)
buf.WriteString("length += ")
buf.WriteString(strconv.Itoa(len(textContent)))
buf.WriteString("\n")
}
}
}
// Close any remaining open conditionals
for len(conditionalStack) > 0 {
conditionalStack = conditionalStack[:len(conditionalStack)-1]
indentLevel--
writeIndent(buf, indentLevel)
buf.WriteString("}\n")
}
}
func generateStringBuilding(buf *bytes.Buffer, toks token.Slice, content []byte, typeCache map[string]string, numericVarMap map[string]string, inputs ast.InputStruct) {
conditionalStack := []bool{} // Track nested conditionals
for _, t := range toks {
switch t.Kind {
case kind.Var:
// Add proper indentation based on nesting level
for range len(conditionalStack) {
buf.WriteRune('\t')
}
vi := t.GetVar(content, typeCache)
buf.WriteString("\tb.WriteString(")
pathKey := string(bytes.Join(vi.Path, []byte(".")))
switch vi.Type {
case "int", "float32", "float64":
if localVar, exists := numericVarMap[pathKey]; exists {
buf.WriteString(localVar)
} else {
// Variable not pre-declared, format inline
switch vi.Type {
case "int":
buf.WriteString("strconv.Itoa(" + varFieldAccess(vi.Path) + ")")
case "float32":
buf.WriteString("strconv.FormatFloat(float64(" + varFieldAccess(vi.Path) + "), 'g', -1, 32)")
case "float64":
buf.WriteString("strconv.FormatFloat(" + varFieldAccess(vi.Path) + ", 'g', -1, 64)")
}
}
case "bool":
buf.WriteString("strconv.FormatBool(" + varFieldAccess(vi.Path) + ")")
default:
buf.WriteString(varFieldAccess(vi.Path))
}
buf.WriteString(")\n")
case kind.OptionalBlock:
conditionalStack = append(conditionalStack, true)
// Add proper indentation for the if statement
for range len(conditionalStack) - 1 {
buf.WriteRune('\t')
}
vi := t.GetVar(content, typeCache)
buf.WriteString("\tif ")
// Generate conditional expression
if vi.Operator != "" {
// Custom operator expression
buf.WriteString(varFieldAccess(vi.Path))
buf.WriteString(" ")
buf.WriteString(convertWordOperatorToGo(vi.Operator))
buf.WriteString(" ")
buf.WriteString(vi.Operand) // Use vi.Operand directly (already formatted)
} else {
// Default truthiness check
if isStructPath(vi.Path, inputs) {
// Use the private isZero method for struct types
buf.WriteString("!")
buf.WriteString(generateIsZeroMethodCall(vi.Path))
} else {
switch vi.Type {
case "bool":
// just check if true
buf.WriteString(varFieldAccess(vi.Path))
case "int":
buf.WriteString(varFieldAccess(vi.Path))
buf.WriteString(" != 0")
default:
buf.WriteString(varFieldAccess(vi.Path))
buf.WriteString(" != \"\"")
}
}
}
buf.WriteString(" {\n")
case kind.ElseBlock:
// Add proper indentation for the else statement
for range len(conditionalStack) - 1 {
buf.WriteRune('\t')
}
buf.WriteString("\t} else {\n")
case kind.EndTag:
if len(conditionalStack) > 0 {
conditionalStack = conditionalStack[:len(conditionalStack)-1]
// Add proper indentation for the closing brace
for range len(conditionalStack) {
buf.WriteRune('\t')
}
buf.WriteString("\t}\n")
}
default:
// static text
// Add proper indentation based on nesting level
for range len(conditionalStack) {
buf.WriteRune('\t')
}
textContent := t.Get(content)
if bytes.Equal(textContent, []byte("\n")) {
buf.WriteString("\tb.WriteRune('\\n')\n")
} else if len(textContent) > 0 {
// Check if content contains backticks - if so, use quoted strings
if bytes.Contains(textContent, []byte("`")) {
buf.WriteString("\tb.WriteString(")
writeQuotedString(buf, textContent)
buf.WriteString(")\n")
} else {
buf.WriteString("\tb.WriteString(`")
buf.Write(textContent)
buf.WriteString("`)\n")
}
}
}
}
// Close any remaining open conditionals
for len(conditionalStack) > 0 {
conditionalStack = conditionalStack[:len(conditionalStack)-1]
// Add proper indentation for the closing brace
for range len(conditionalStack) {
buf.WriteRune('\t')
}
buf.WriteString("\t}\n")
}
}
func writeIndent(buf *bytes.Buffer, level int) {
for i := 0; i < level; i++ {
buf.WriteRune('\t')
}
}
// writeQuotedString writes a properly escaped quoted string literal
func writeQuotedString(buf *bytes.Buffer, content []byte) {
buf.WriteRune('"')
for _, b := range content {
switch b {
case '"':
buf.WriteString(`\"`)
case '\\':
buf.WriteString(`\\`)
case '\n':
buf.WriteString(`\n`)
case '\r':
buf.WriteString(`\r`)
case '\t':
buf.WriteString(`\t`)
default:
buf.WriteByte(b)
}
}
buf.WriteRune('"')
}
// convertWordOperatorToGo converts word operators to Go operators
func convertWordOperatorToGo(wordOp string) string {
switch wordOp {
case "gte":
return ">="
case "lte":
return "<="
case "gt":
return ">"
case "lt":
return "<"
case "eq":
return "=="
case "ne":
return "!="
default:
return wordOp // fallback
}
}
// varFieldAccess returns the Go field access string for a variable path
func varFieldAccess(path [][]byte) string {
var buf strings.Builder
buf.WriteString("input.")
for i, part := range path {
buf.Write(bytcase.ToCamel(part))
if i < len(path)-1 {
buf.WriteRune('.')
}
}
return buf.String()
}
// generateIsZeroMethodCall generates a call to the private isZero method for a struct field
func generateIsZeroMethodCall(path [][]byte) string {
var buf strings.Builder
buf.WriteString("input.is")
for _, part := range path {
buf.Write(bytcase.ToCamel(part))
}
buf.WriteString("Zero()")
return buf.String()
}
// isStructPath checks if a given variable path represents a struct field in the InputStruct
func isStructPath(path [][]byte, inputs ast.InputStruct) bool {
if len(path) == 0 {
return false
}
// Find the top-level node
topLevelName := bytcase.ToCamel(path[0])
var currentNode *ast.InputNode
for i := range inputs.TopLevel {
if bytes.Equal(inputs.TopLevel[i].Name, topLevelName) {
currentNode = &inputs.TopLevel[i]
break
}
}
if currentNode == nil {
return false
}
// Traverse the path
for i := 1; i < len(path); i++ {
found := false
fieldName := bytcase.ToCamel(path[i])
for j := range currentNode.Subnodes {
if bytes.Equal(currentNode.Subnodes[j].Name, fieldName) {
currentNode = ¤tNode.Subnodes[j]
found = true
break
}
}
if !found {
return false
}
}
// Check if this final node is a struct (has subnodes)
return len(currentNode.Subnodes) > 0
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package logger
import (
"log/slog"
"github.com/omniaura/agentflow/cfg"
)
func Setup() {
SetupLevel(cfg.LogLevel())
}
func SetupLevel(lvl slog.Level) {
slog.SetLogLoggerLevel(lvl)
}
package kind
//go:generate go tool stringer -type=Kind
type Kind int
// TODO: add KindDoc, KindVarDoc
// TODO: add .var var predeclare optional; sets the types
// example:
//
// .title say hello to your new friends
// .var names string list join="\n"
// Please say hello to:
// <!names>
//
// INPUT:
// Joe,Mary,Jane
//
// OUTPUT:
// Please say hello to:
// Joe
// Mary
// Jane
const (
Unset Kind = iota
EndTag
OptionalBlock
ElseBlock
Title
Text
// TODO: add var parameters
// such as:
// <!name string>
// <!age int>
// <!is_admin bool>
// <!created_at datetime>
// <!meeting_time time>
// <!meeting_date date>
// <!any_data any>
// <!todos string list join="\n">
// <!weights float32 list join=",">
// <!flags bool list join="," start="[" end="]">
// <!names join="\n">
Var
RawBlock
)
func (k Kind) IsTag() bool {
switch k {
case
Var,
OptionalBlock,
ElseBlock,
EndTag:
return true
}
return false
}
// Code generated by "stringer -type=Kind"; DO NOT EDIT.
package kind
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Unset-0]
_ = x[EndTag-1]
_ = x[OptionalBlock-2]
_ = x[ElseBlock-3]
_ = x[Title-4]
_ = x[Text-5]
_ = x[Var-6]
_ = x[RawBlock-7]
}
const _Kind_name = "UnsetEndTagOptionalBlockElseBlockTitleTextVarRawBlock"
var _Kind_index = [...]uint8{0, 5, 11, 24, 33, 38, 42, 45, 53}
func (i Kind) String() string {
if i < 0 || i >= Kind(len(_Kind_index)-1) {
return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
}
/*
Copyright ยฉ 2024 Omni Aura peyton@omniaura.co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package token
import (
"bytes"
"log/slog"
"strconv"
"strings"
"github.com/omniaura/agentflow/pkg/token/kind"
"github.com/peyton-spencer/caseconv/bytcase"
)
type Slice []T
func (t Slice) Equal(o Slice) bool {
if len(t) != len(o) {
return false
}
for i, tok := range t {
if tok != o[i] {
return false
}
}
return true
}
type T struct {
Kind kind.Kind
Start int
End int
}
func (t T) Get(in []byte) []byte {
return in[t.Start:t.End]
}
func (t T) GetWrap(in []byte, left, right byte) []byte {
out := make([]byte, 0, len(in)+2)
out = append(out, left)
out = append(out, in[t.Start:t.End]...)
out = append(out, right)
return out
}
func (t T) GetWrapLL(in []byte, left []byte, right byte) []byte {
out := make([]byte, 0, len(in)+len(left)+1)
out = append(out, left...)
out = append(out, in[t.Start:t.End]...)
out = append(out, right)
return out
}
func (t T) GetJSFmtVar(in []byte) []byte {
out := make([]byte, 0, len(in)+3)
out = append(out, '$', '{')
out = append(out, bytcase.ToLowerCamel(in[t.Start:t.End])...)
out = append(out, '}')
return out
}
var (
cmdTitle = []byte(".title")
)
func Tokenize(input []byte) (Slice, error) {
var tokens []T
var ct T
startLine := true
cmdStart := -1
cmdEnd := cmdStart
for i, b := range input {
if startLine {
startLine = false
switch b {
case '~':
case '.':
cmdStart = i
if ct.Kind != kind.Unset {
// trim newlines before the directive
// sub := 1
// for input[i-sub] == '\n' {
// sub++
// }
// ct.End = i - sub + 1
if input[i-1] == '\n' {
if input[i-2] == '\n' {
ct.End = i - 2
} else {
ct.End = i - 1
}
} else {
ct.End = i
}
tokens = append(tokens, ct)
// log.Trace().Msgf("command start: %+v", ct)
} else {
// log.Trace().Msgf("kind was previously set: %+v", ct)
}
case '<':
case '\n':
default:
}
}
if cmdStart != -1 {
switch b {
case ' ':
cmdEnd = i
switch {
case bytes.Equal(input[cmdStart:cmdEnd], cmdTitle):
ct.Kind = kind.Title
ct.Start = i + 1
}
}
}
if b == '>' && ct.Kind.IsTag() {
ct.End = i
tokens = append(tokens, ct)
ct = T{}
continue
}
if b == '<' && len(input) > i {
if ct.Kind != kind.Unset {
ct.End = i
tokens = append(tokens, ct)
}
switch input[i+1] {
case '!':
ct.Kind = kind.Var
case '?':
ct.Kind = kind.OptionalBlock
case '/':
ct.Kind = kind.EndTag
case 'e':
ct.Kind = kind.ElseBlock
}
ct.Start = i + 2
}
if b == '\n' {
startLine = true
switch ct.Kind {
case kind.Text:
case kind.Title:
ct.End = i
tokens = append(tokens, ct)
ct = T{}
continue
case kind.Unset:
if len(input) > i+1 {
switch input[i+1] {
case '.':
slog.Debug("ignoring text node", "token", ct.Stringify(input))
continue
}
}
}
}
if ct.Kind == kind.Unset {
ct.Kind = kind.Text
ct.Start = i
}
if i == len(input)-1 && ct.Kind != kind.Unset {
ct.End = i + 1
// slog.Debug("end of input, adding token", "token", ct.Stringify(input))
tokens = append(tokens, ct)
}
}
return tokens, nil
}
func (t T) Stringify(in []byte) string {
var buf strings.Builder
buf.Grow(len(in) + 100)
buf.WriteString(t.Kind.String())
buf.WriteString(":\t[")
buf.WriteString(strconv.Itoa(t.Start))
buf.WriteString(":")
buf.WriteString(strconv.Itoa(t.End))
buf.WriteString("]\t")
if t.Start < 0 || t.End > len(in) || t.Start > t.End {
buf.WriteString("INVALID BOUNDS")
} else {
buf.WriteString("\"")
buf.Write(in[t.Start:t.End])
buf.WriteString("\"")
}
return buf.String()
}
func (s Slice) Stringify(in []byte) string {
if len(in) == 0 {
return "no content"
}
if len(s) == 0 {
return "no tokens"
}
var buf strings.Builder
buf.Grow(len(in) + 100)
for i, tok := range s {
buf.WriteString(tok.Stringify(in))
if i != len(s)-1 {
buf.WriteRune('\n')
}
}
return buf.String()
}
// VarInfo holds the parsed variable path and type from a var token
// Path is the dot-separated path as a slice of []byte (e.g. ["user", "subscription", "tier"])
// Type is the type string (e.g. "string", "int", "bool")
// Operator is the conditional operator (e.g. ">=", "==", "!=") for OptionalBlock tokens
// Operand is the value to compare against (e.g. "30", "true", "\"gold\"")
type VarInfo struct {
Path [][]byte
Type string
Operator string // For conditionals: ">=", "<=", "==", "!=", ">", "<"
Operand string // For conditionals: the value to compare against
}
// GetVar parses the variable name and type from a var token
// The typeCache map stores previously seen variable types for reuse
// For OptionalBlock tokens, it also parses conditional operators and operands
func (t T) GetVar(in []byte, typeCache map[string]string) VarInfo {
b := in[t.Start:t.End]
// Handle conditional expressions for OptionalBlock tokens
if t.Kind == kind.OptionalBlock {
return parseConditionalExpression(b, typeCache)
}
// Handle regular variable tokens
parts := bytes.Fields(b)
var path [][]byte
var typ string
if len(parts) > 0 {
path = bytes.Split(parts[0], []byte{'.'})
}
// Create cache key from the variable path
pathKey := string(bytes.Join(path, []byte(".")))
if len(parts) > 1 {
// Type is explicitly specified, cache it
typ = string(parts[1])
typeCache[pathKey] = typ
} else {
// No type specified, check cache
if cachedType, exists := typeCache[pathKey]; exists {
typ = cachedType
} else {
typ = "string" // default
}
}
return VarInfo{Path: path, Type: typ}
}
// parseConditionalExpression parses conditional expressions like "writer.current_streak gte 30"
func parseConditionalExpression(expr []byte, typeCache map[string]string) VarInfo {
exprStr := string(expr)
// List of word operators to check for
operators := []string{"gte", "lte", "gt", "lt", "eq", "ne"}
for _, op := range operators {
if idx := strings.Index(exprStr, " "+op+" "); idx != -1 {
// Found an operator
varPart := strings.TrimSpace(exprStr[:idx])
operandPart := strings.TrimSpace(exprStr[idx+len(op)+2:]) // +2 for the spaces around operator
// Parse variable path and type
varInfo := parseVariablePart(varPart, typeCache)
// Check if operand is a variable reference (contains dot notation)
if strings.Contains(operandPart, ".") && !strings.Contains(operandPart, "\"") && !strings.Contains(operandPart, "'") {
// Operand is another variable - convert to Go field access
operandPath := strings.Split(operandPart, ".")
var operandFieldAccess strings.Builder
operandFieldAccess.WriteString("input.")
for i, part := range operandPath {
// Convert to CamelCase using the proper bytcase function
if len(part) > 0 {
operandFieldAccess.Write(bytcase.ToCamel([]byte(part)))
if i < len(operandPath)-1 {
operandFieldAccess.WriteString(".")
}
}
}
varInfo.Operand = operandFieldAccess.String()
} else {
// Infer type from operand constant
inferredType := inferTypeFromOperand(operandPart)
if inferredType != "string" || varInfo.Type == "string" {
varInfo.Type = inferredType
// Cache the inferred type
pathKey := string(bytes.Join(varInfo.Path, []byte(".")))
typeCache[pathKey] = inferredType
}
varInfo.Operand = formatOperandForGeneration(operandPart, varInfo.Type)
}
varInfo.Operator = op
return varInfo
}
}
// No operator found - treat as simple truthiness check
varInfo := parseVariablePart(exprStr, typeCache)
return varInfo
}
// formatOperandForGeneration formats operands for code generation
func formatOperandForGeneration(operand, varType string) string {
operand = strings.TrimSpace(operand)
switch varType {
case "string":
// Ensure string operands are properly quoted
if !strings.HasPrefix(operand, "\"") && !strings.HasPrefix(operand, "'") {
return "\"" + operand + "\""
}
return operand
case "int", "float32", "float64":
// Numeric types - use as-is
return operand
case "bool":
// Boolean types - use as-is
return operand
default:
// Default to quoted string
if !strings.HasPrefix(operand, "\"") && !strings.HasPrefix(operand, "'") {
return "\"" + operand + "\""
}
return operand
}
}
// parseVariablePart parses the variable name and optional explicit type
func parseVariablePart(varPart string, typeCache map[string]string) VarInfo {
parts := strings.Fields(varPart)
var path [][]byte
var typ string
if len(parts) > 0 {
path = bytes.Split([]byte(parts[0]), []byte{'.'})
}
// Create cache key from the variable path
pathKey := string(bytes.Join(path, []byte(".")))
if len(parts) > 1 {
// Type is explicitly specified, cache it
typ = parts[1]
typeCache[pathKey] = typ
} else {
// No type specified, check cache
if cachedType, exists := typeCache[pathKey]; exists {
typ = cachedType
} else {
typ = "string" // default
}
}
return VarInfo{Path: path, Type: typ}
}
// inferTypeFromOperand infers the Go type from the operand value
func inferTypeFromOperand(operand string) string {
operand = strings.TrimSpace(operand)
// Check for boolean values
if operand == "true" || operand == "false" {
return "bool"
}
// Check for quoted strings
if (strings.HasPrefix(operand, "\"") && strings.HasSuffix(operand, "\"")) ||
(strings.HasPrefix(operand, "'") && strings.HasSuffix(operand, "'")) {
return "string"
}
// Check for floating point numbers
if strings.Contains(operand, ".") {
if _, err := strconv.ParseFloat(operand, 64); err == nil {
return "float64"
}
}
// Check for integers
if _, err := strconv.Atoi(operand); err == nil {
return "int"
}
// Default to string for unquoted values
return "string"
}
// hasComparisonOperator checks if the token content contains any comparison operators
func hasComparisonOperator(content string) bool {
operators := []string{">=", "<=", "==", "!=", ">", "<"}
for _, op := range operators {
if strings.Contains(content, op) {
return true
}
}
return false
}